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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/CMakeLists.txt4
-rw-r--r--source/blender/CMakeLists.txt4
-rw-r--r--source/blender/alembic/CMakeLists.txt2
-rw-r--r--source/blender/alembic/intern/abc_camera.cc5
-rw-r--r--source/blender/alembic/intern/abc_camera.h3
-rw-r--r--source/blender/alembic/intern/abc_curves.cc5
-rw-r--r--source/blender/alembic/intern/abc_curves.h3
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc120
-rw-r--r--source/blender/alembic/intern/abc_exporter.h20
-rw-r--r--source/blender/alembic/intern/abc_hair.cc7
-rw-r--r--source/blender/alembic/intern/abc_hair.h3
-rw-r--r--source/blender/alembic/intern/abc_mball.cc6
-rw-r--r--source/blender/alembic/intern/abc_mball.h1
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc14
-rw-r--r--source/blender/alembic/intern/abc_mesh.h3
-rw-r--r--source/blender/alembic/intern/abc_nurbs.cc5
-rw-r--r--source/blender/alembic/intern/abc_nurbs.h3
-rw-r--r--source/blender/alembic/intern/abc_object.cc5
-rw-r--r--source/blender/alembic/intern/abc_object.h4
-rw-r--r--source/blender/alembic/intern/abc_points.cc6
-rw-r--r--source/blender/alembic/intern/abc_points.h3
-rw-r--r--source/blender/alembic/intern/abc_transform.cc5
-rw-r--r--source/blender/alembic/intern/abc_transform.h3
-rw-r--r--source/blender/alembic/intern/abc_util.cc36
-rw-r--r--source/blender/alembic/intern/abc_util.h4
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc60
-rw-r--r--source/blender/blenfont/BLF_api.h34
-rw-r--r--source/blender/blenfont/intern/blf.c230
-rw-r--r--source/blender/blenfont/intern/blf_font.c49
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c146
-rw-r--r--source/blender/blenfont/intern/blf_internal.h5
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h8
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h74
-rw-r--r--source/blender/blenkernel/BKE_anim.h9
-rw-r--r--source/blender/blenkernel/BKE_animsys.h8
-rw-r--r--source/blender/blenkernel/BKE_appdir.h1
-rw-r--r--source/blender/blenkernel/BKE_armature.h32
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h4
-rw-r--r--source/blender/blenkernel/BKE_blendfile.h4
-rw-r--r--source/blender/blenkernel/BKE_cachefile.h2
-rw-r--r--source/blender/blenkernel/BKE_camera.h8
-rw-r--r--source/blender/blenkernel/BKE_cloth.h3
-rw-r--r--source/blender/blenkernel/BKE_collection.h107
-rw-r--r--source/blender/blenkernel/BKE_collision.h2
-rw-r--r--source/blender/blenkernel/BKE_constraint.h10
-rw-r--r--source/blender/blenkernel/BKE_context.h21
-rw-r--r--source/blender/blenkernel/BKE_crazyspace.h9
-rw-r--r--source/blender/blenkernel/BKE_curve.h23
-rw-r--r--source/blender/blenkernel/BKE_customdata.h11
-rw-r--r--source/blender/blenkernel/BKE_data_transfer.h8
-rw-r--r--source/blender/blenkernel/BKE_depsgraph.h181
-rw-r--r--source/blender/blenkernel/BKE_displist.h29
-rw-r--r--source/blender/blenkernel/BKE_dynamicpaint.h7
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h5
-rw-r--r--source/blender/blenkernel/BKE_editmesh_tangent.h40
-rw-r--r--source/blender/blenkernel/BKE_effect.h8
-rw-r--r--source/blender/blenkernel/BKE_fluidsim.h3
-rw-r--r--source/blender/blenkernel/BKE_global.h3
-rw-r--r--source/blender/blenkernel/BKE_group.h27
-rw-r--r--source/blender/blenkernel/BKE_idprop.h1
-rw-r--r--source/blender/blenkernel/BKE_lamp.h2
-rw-r--r--source/blender/blenkernel/BKE_lattice.h22
-rw-r--r--source/blender/blenkernel/BKE_layer.h292
-rw-r--r--source/blender/blenkernel/BKE_library.h3
-rw-r--r--source/blender/blenkernel/BKE_library_override.h86
-rw-r--r--source/blender/blenkernel/BKE_library_query.h3
-rw-r--r--source/blender/blenkernel/BKE_library_remap.h2
-rw-r--r--source/blender/blenkernel/BKE_lightprobe.h46
-rw-r--r--source/blender/blenkernel/BKE_main.h2
-rw-r--r--source/blender/blenkernel/BKE_material.h14
-rw-r--r--source/blender/blenkernel/BKE_mball.h13
-rw-r--r--source/blender/blenkernel/BKE_mball_tessellate.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h34
-rw-r--r--source/blender/blenkernel/BKE_mesh_tangent.h61
-rw-r--r--source/blender/blenkernel/BKE_modifier.h55
-rw-r--r--source/blender/blenkernel/BKE_multires.h13
-rw-r--r--source/blender/blenkernel/BKE_node.h31
-rw-r--r--source/blender/blenkernel/BKE_object.h91
-rw-r--r--source/blender/blenkernel/BKE_object_facemap.h53
-rw-r--r--source/blender/blenkernel/BKE_outliner_treehash.h3
-rw-r--r--source/blender/blenkernel/BKE_paint.h13
-rw-r--r--source/blender/blenkernel/BKE_particle.h27
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h5
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h5
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h13
-rw-r--r--source/blender/blenkernel/BKE_scene.h100
-rw-r--r--source/blender/blenkernel/BKE_screen.h37
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h3
-rw-r--r--source/blender/blenkernel/BKE_smoke.h4
-rw-r--r--source/blender/blenkernel/BKE_softbody.h4
-rw-r--r--source/blender/blenkernel/BKE_sound.h8
-rw-r--r--source/blender/blenkernel/BKE_tracking.h1
-rw-r--r--source/blender/blenkernel/BKE_workspace.h155
-rw-r--r--source/blender/blenkernel/BKE_world.h6
-rw-r--r--source/blender/blenkernel/CMakeLists.txt30
-rw-r--r--source/blender/blenkernel/depsgraph_private.h169
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c2
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c4
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c680
-rw-r--r--source/blender/blenkernel/intern/action.c10
-rw-r--r--source/blender/blenkernel/intern/anim.c102
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c12
-rw-r--r--source/blender/blenkernel/intern/armature.c40
-rw-r--r--source/blender/blenkernel/intern/armature_update.c67
-rw-r--r--source/blender/blenkernel/intern/blender.c8
-rw-r--r--source/blender/blenkernel/intern/blender_copybuffer.c17
-rw-r--r--source/blender/blenkernel/intern/blender_undo.c5
-rw-r--r--source/blender/blenkernel/intern/blendfile.c113
-rw-r--r--source/blender/blenkernel/intern/boids.c1
-rw-r--r--source/blender/blenkernel/intern/cachefile.c8
-rw-r--r--source/blender/blenkernel/intern/camera.c73
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c318
-rw-r--r--source/blender/blenkernel/intern/cloth.c13
-rw-r--r--source/blender/blenkernel/intern/collection.c820
-rw-r--r--source/blender/blenkernel/intern/collision.c46
-rw-r--r--source/blender/blenkernel/intern/constraint.c75
-rw-r--r--source/blender/blenkernel/intern/context.c143
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c26
-rw-r--r--source/blender/blenkernel/intern/curve.c38
-rw-r--r--source/blender/blenkernel/intern/customdata.c112
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c25
-rw-r--r--source/blender/blenkernel/intern/deform.c3
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c3712
-rw-r--r--source/blender/blenkernel/intern/displist.c106
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c115
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c693
-rw-r--r--source/blender/blenkernel/intern/editmesh.c20
-rw-r--r--source/blender/blenkernel/intern/editmesh_tangent.c431
-rw-r--r--source/blender/blenkernel/intern/effect.c89
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c4
-rw-r--r--source/blender/blenkernel/intern/group.c165
-rw-r--r--source/blender/blenkernel/intern/icons.c2
-rw-r--r--source/blender/blenkernel/intern/idcode.c9
-rw-r--r--source/blender/blenkernel/intern/idprop.c35
-rw-r--r--source/blender/blenkernel/intern/image.c21
-rw-r--r--source/blender/blenkernel/intern/lamp.c47
-rw-r--r--source/blender/blenkernel/intern/lattice.c52
-rw-r--r--source/blender/blenkernel/intern/layer.c2189
-rw-r--r--source/blender/blenkernel/intern/library.c113
-rw-r--r--source/blender/blenkernel/intern/library_override.c680
-rw-r--r--source/blender/blenkernel/intern/library_query.c156
-rw-r--r--source/blender/blenkernel/intern/library_remap.c100
-rw-r--r--source/blender/blenkernel/intern/lightprobe.c100
-rw-r--r--source/blender/blenkernel/intern/linestyle.c13
-rw-r--r--source/blender/blenkernel/intern/mask.c5
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c3
-rw-r--r--source/blender/blenkernel/intern/material.c590
-rw-r--r--source/blender/blenkernel/intern/mball.c84
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c9
-rw-r--r--source/blender/blenkernel/intern/mesh.c189
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c204
-rw-r--r--source/blender/blenkernel/intern/mesh_tangent.c690
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c84
-rw-r--r--source/blender/blenkernel/intern/modifier.c22
-rw-r--r--source/blender/blenkernel/intern/multires.c38
-rw-r--r--source/blender/blenkernel/intern/nla.c2
-rw-r--r--source/blender/blenkernel/intern/node.c63
-rw-r--r--source/blender/blenkernel/intern/object.c253
-rw-r--r--source/blender/blenkernel/intern/object_deform.c3
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c168
-rw-r--r--source/blender/blenkernel/intern/object_facemap.c257
-rw-r--r--source/blender/blenkernel/intern/object_update.c212
-rw-r--r--source/blender/blenkernel/intern/outliner_treehash.c39
-rw-r--r--source/blender/blenkernel/intern/paint.c49
-rw-r--r--source/blender/blenkernel/intern/particle.c91
-rw-r--r--source/blender/blenkernel/intern/particle_child.c2
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c11
-rw-r--r--source/blender/blenkernel/intern/particle_system.c67
-rw-r--r--source/blender/blenkernel/intern/pbvh.c109
-rw-r--r--source/blender/blenkernel/intern/pointcache.c13
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c183
-rw-r--r--source/blender/blenkernel/intern/scene.c1385
-rw-r--r--source/blender/blenkernel/intern/screen.c113
-rw-r--r--source/blender/blenkernel/intern/sequencer.c29
-rw-r--r--source/blender/blenkernel/intern/smoke.c40
-rw-r--r--source/blender/blenkernel/intern/softbody.c129
-rw-r--r--source/blender/blenkernel/intern/sound.c168
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c264
-rw-r--r--source/blender/blenkernel/intern/text.c1
-rw-r--r--source/blender/blenkernel/intern/tracking.c3
-rw-r--r--source/blender/blenkernel/intern/workspace.c523
-rw-r--r--source/blender/blenkernel/intern/world.c11
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c4
-rw-r--r--source/blender/blenlib/BLI_callbacks.h2
-rw-r--r--source/blender/blenlib/BLI_iterator.h62
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h255
-rw-r--r--source/blender/blenlib/BLI_math_vector.h2
-rw-r--r--source/blender/blenlib/BLI_memiter.h73
-rw-r--r--source/blender/blenlib/CMakeLists.txt3
-rw-r--r--source/blender/blenlib/intern/BLI_memiter.c357
-rw-r--r--source/blender/blenlib/intern/math_color.c6
-rw-r--r--source/blender/blenlib/intern/math_matrix.c347
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c2
-rw-r--r--source/blender/blenlib/intern/scanfill_utils.c14
-rw-r--r--source/blender/blenloader/BLO_readfile.h25
-rw-r--r--source/blender/blenloader/CMakeLists.txt6
-rw-r--r--source/blender/blenloader/intern/readfile.c1007
-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.c21
-rw-r--r--source/blender/blenloader/intern/versioning_280.c830
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c51
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c112
-rw-r--r--source/blender/blenloader/intern/writefile.c482
-rw-r--r--source/blender/blentranslation/BLT_translation.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c45
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h2
-rw-r--r--source/blender/bmesh/operators/bmo_similar.c64
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c21
-rw-r--r--source/blender/collada/AnimationExporter.cpp23
-rw-r--r--source/blender/collada/AnimationExporter.h5
-rw-r--r--source/blender/collada/AnimationImporter.cpp6
-rw-r--r--source/blender/collada/ArmatureExporter.cpp19
-rw-r--r--source/blender/collada/ArmatureExporter.h4
-rw-r--r--source/blender/collada/ArmatureImporter.cpp7
-rw-r--r--source/blender/collada/CMakeLists.txt1
-rw-r--r--source/blender/collada/ControllerExporter.cpp16
-rw-r--r--source/blender/collada/ControllerExporter.h4
-rw-r--r--source/blender/collada/DocumentExporter.cpp18
-rw-r--r--source/blender/collada/DocumentExporter.h2
-rw-r--r--source/blender/collada/DocumentImporter.cpp28
-rw-r--r--source/blender/collada/EffectExporter.cpp78
-rw-r--r--source/blender/collada/EffectExporter.h1
-rw-r--r--source/blender/collada/ExportSettings.h3
-rw-r--r--source/blender/collada/GeometryExporter.cpp310
-rw-r--r--source/blender/collada/GeometryExporter.h39
-rw-r--r--source/blender/collada/ImageExporter.cpp76
-rw-r--r--source/blender/collada/ImageExporter.h1
-rw-r--r--source/blender/collada/InstanceWriter.cpp63
-rw-r--r--source/blender/collada/InstanceWriter.h3
-rw-r--r--source/blender/collada/MaterialExporter.cpp35
-rw-r--r--source/blender/collada/MeshImporter.cpp39
-rw-r--r--source/blender/collada/MeshImporter.h10
-rw-r--r--source/blender/collada/SceneExporter.cpp33
-rw-r--r--source/blender/collada/SceneExporter.h6
-rw-r--r--source/blender/collada/SkinInfo.cpp4
-rw-r--r--source/blender/collada/TransformWriter.cpp3
-rw-r--r--source/blender/collada/TransformWriter.h3
-rw-r--r--source/blender/collada/collada.cpp12
-rw-r--r--source/blender/collada/collada.h19
-rw-r--r--source/blender/collada/collada_internal.cpp8
-rw-r--r--source/blender/collada/collada_internal.h1
-rw-r--r--source/blender/collada/collada_utils.cpp192
-rw-r--r--source/blender/collada/collada_utils.h14
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.cpp6
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cpp12
-rw-r--r--source/blender/depsgraph/CMakeLists.txt14
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h148
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h38
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_debug.h9
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h92
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc136
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.h7
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc621
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h80
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc126
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc194
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc (renamed from source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc)77
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc378
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h31
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc124
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc17
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc (renamed from source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc)39
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc53
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc129
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h35
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc122
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc18
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc79
-rw-r--r--source/blender/depsgraph/intern/depsgraph_intern.h31
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc49
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_foreach.cc147
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc211
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc626
-rw-r--r--source/blender/depsgraph/intern/depsgraph_type_defines.cc14
-rw-r--r--source/blender/depsgraph/intern/depsgraph_types.h43
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc58
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.h3
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc939
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h109
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc329
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node.cc107
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node.h12
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.cc39
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.h10
-rw-r--r--source/blender/depsgraph/util/deg_util_foreach.h10
-rw-r--r--source/blender/depsgraph/util/deg_util_function.h61
-rw-r--r--source/blender/draw/CMakeLists.txt231
-rw-r--r--source/blender/draw/DRW_engine.h117
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c280
-rw-r--r--source/blender/draw/engines/basic/basic_engine.h32
-rw-r--r--source/blender/draw/engines/clay/clay_engine.c935
-rw-r--r--source/blender/draw/engines/clay/clay_engine.h36
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_frag.glsl201
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_particle_strand_frag.glsl144
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl34
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_vert.glsl17
-rw-r--r--source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl78
-rw-r--r--source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl122
-rw-r--r--source/blender/draw/engines/eevee/eevee_bloom.c349
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c155
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c290
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c490
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c431
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.h31
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c1668
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c1092
-rw-r--r--source/blender/draw/engines/eevee/eevee_lut.h16411
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c1451
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c206
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c251
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h811
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c341
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c260
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c196
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c581
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl377
-rw-r--r--source/blender/draw/engines/eevee/shaders/background_vert.glsl20
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl822
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl183
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_lut_frag.glsl46
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl107
-rw-r--r--source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl59
-rw-r--r--source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl267
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_frag.glsl19
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_world_frag.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl218
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl261
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_geom.glsl55
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl99
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_downsample_cube_frag.glsl30
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl37
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl69
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl65
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl65
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl453
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl90
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl14
-rw-r--r--source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl178
-rw-r--r--source/blender/draw/engines/eevee/shaders/lamps_lib.glsl448
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl15
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl28
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl197
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl86
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl88
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl34
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl11
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl34
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl20
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl262
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl15
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl17
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl40
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl24
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_vert.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl500
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl40
-rw-r--r--source/blender/draw/engines/eevee/shaders/ltc_lib.glsl240
-rw-r--r--source/blender/draw/engines/eevee/shaders/octahedron_lib.glsl38
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_frag.glsl85
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_vert.glsl18
-rw-r--r--source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl242
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl210
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_geom.glsl53
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl146
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_vert.glsl29
-rw-r--r--source/blender/draw/engines/eevee/shaders/ssr_lib.glsl73
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl66
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl52
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl63
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl155
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl21
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl83
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl27
-rw-r--r--source/blender/draw/engines/external/external_engine.c233
-rw-r--r--source/blender/draw/engines/external/external_engine.h31
-rw-r--r--source/blender/draw/intern/DRW_render.h458
-rw-r--r--source/blender/draw/intern/draw_armature.c1442
-rw-r--r--source/blender/draw/intern/draw_cache.c2591
-rw-r--r--source/blender/draw/intern/draw_cache.h163
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h117
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.c1036
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c174
-rw-r--r--source/blender/draw/intern/draw_cache_impl_lattice.c587
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c3904
-rw-r--r--source/blender/draw/intern/draw_cache_impl_metaball.c139
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c520
-rw-r--r--source/blender/draw/intern/draw_common.c463
-rw-r--r--source/blender/draw/intern/draw_common.h132
-rw-r--r--source/blender/draw/intern/draw_manager.c3910
-rw-r--r--source/blender/draw/intern/draw_manager_profiling.c242
-rw-r--r--source/blender/draw/intern/draw_manager_profiling.h43
-rw-r--r--source/blender/draw/intern/draw_manager_text.c199
-rw-r--r--source/blender/draw/intern/draw_manager_text.h54
-rw-r--r--source/blender/draw/intern/draw_view.c756
-rw-r--r--source/blender/draw/intern/draw_view.h35
-rw-r--r--source/blender/draw/modes/draw_mode_engines.h44
-rw-r--r--source/blender/draw/modes/edit_armature_mode.c157
-rw-r--r--source/blender/draw/modes/edit_curve_mode.c334
-rw-r--r--source/blender/draw/modes/edit_lattice_mode.c297
-rw-r--r--source/blender/draw/modes/edit_mesh_mode.c613
-rw-r--r--source/blender/draw/modes/edit_mesh_mode_intern.h38
-rw-r--r--source/blender/draw/modes/edit_mesh_mode_text.c301
-rw-r--r--source/blender/draw/modes/edit_metaball_mode.c251
-rw-r--r--source/blender/draw/modes/edit_surface_mode.c269
-rw-r--r--source/blender/draw/modes/edit_text_mode.c312
-rw-r--r--source/blender/draw/modes/object_mode.c2014
-rw-r--r--source/blender/draw/modes/paint_texture_mode.c417
-rw-r--r--source/blender/draw/modes/paint_vertex_mode.c216
-rw-r--r--source/blender/draw/modes/paint_weight_mode.c254
-rw-r--r--source/blender/draw/modes/particle_mode.c264
-rw-r--r--source/blender/draw/modes/pose_mode.c198
-rw-r--r--source/blender/draw/modes/sculpt_mode.c305
-rw-r--r--source/blender/draw/modes/shaders/common_fxaa_lib.glsl678
-rw-r--r--source/blender/draw/modes/shaders/common_globals_lib.glsl58
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_frag.glsl22
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl39
-rw-r--r--source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl22
-rw-r--r--source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl39
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl19
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_vert.glsl31
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl29
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl29
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl208
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl153
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl293
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl59
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl22
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl38
-rw-r--r--source/blender/draw/modes/shaders/edit_normals_geom.glsl15
-rw-r--r--source/blender/draw/modes/shaders/edit_normals_vert.glsl30
-rw-r--r--source/blender/draw/modes/shaders/object_empty_image_frag.glsl21
-rw-r--r--source/blender/draw/modes/shaders/object_empty_image_vert.glsl38
-rw-r--r--source/blender/draw/modes/shaders/object_grid_frag.glsl207
-rw-r--r--source/blender/draw/modes/shaders/object_grid_vert.glsl63
-rw-r--r--source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl28
-rw-r--r--source/blender/draw/modes/shaders/object_outline_detect_frag.glsl79
-rw-r--r--source/blender/draw/modes/shaders/object_outline_expand_frag.glsl37
-rw-r--r--source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl27
-rw-r--r--source/blender/draw/modes/shaders/object_particle_dot_frag.glsl52
-rw-r--r--source/blender/draw/modes/shaders/object_particle_dot_vert.glsl35
-rw-r--r--source/blender/draw/modes/shaders/object_particle_prim_frag.glsl9
-rw-r--r--source/blender/draw/modes/shaders/object_particle_prim_vert.glsl56
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_frag.glsl11
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_vert.glsl15
-rw-r--r--source/blender/draw/modes/shaders/paint_vert_frag.glsl26
-rw-r--r--source/blender/draw/modes/shaders/paint_wire_frag.glsl24
-rw-r--r--source/blender/draw/modes/shaders/paint_wire_vert.glsl14
-rw-r--r--source/blender/editors/CMakeLists.txt4
-rw-r--r--source/blender/editors/animation/CMakeLists.txt1
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c119
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c27
-rw-r--r--source/blender/editors/animation/anim_deps.c9
-rw-r--r--source/blender/editors/animation/anim_draw.c76
-rw-r--r--source/blender/editors/animation/anim_filter.c60
-rw-r--r--source/blender/editors/animation/anim_markers.c83
-rw-r--r--source/blender/editors/animation/drivers.c12
-rw-r--r--source/blender/editors/animation/keyframes_draw.c232
-rw-r--r--source/blender/editors/animation/keyframing.c10
-rw-r--r--source/blender/editors/animation/keyingsets.c5
-rw-r--r--source/blender/editors/armature/CMakeLists.txt1
-rw-r--r--source/blender/editors/armature/armature_naming.c7
-rw-r--r--source/blender/editors/armature/armature_relations.c34
-rw-r--r--source/blender/editors/armature/armature_select.c24
-rw-r--r--source/blender/editors/armature/armature_skinning.c17
-rw-r--r--source/blender/editors/armature/armature_utils.c5
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c188
-rw-r--r--source/blender/editors/armature/pose_edit.c32
-rw-r--r--source/blender/editors/armature/pose_lib.c21
-rw-r--r--source/blender/editors/armature/pose_select.c27
-rw-r--r--source/blender/editors/armature/pose_transform.c29
-rw-r--r--source/blender/editors/armature/pose_utils.c12
-rw-r--r--source/blender/editors/armature/reeb.c234
-rw-r--r--source/blender/editors/curve/CMakeLists.txt1
-rw-r--r--source/blender/editors/curve/editcurve.c77
-rw-r--r--source/blender/editors/curve/editcurve_add.c7
-rw-r--r--source/blender/editors/curve/editcurve_paint.c92
-rw-r--r--source/blender/editors/curve/editfont.c19
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt1
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c1167
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c32
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c19
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c8
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c87
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c18
-rw-r--r--source/blender/editors/include/BIF_gl.h53
-rw-r--r--source/blender/editors/include/BIF_glutil.h159
-rw-r--r--source/blender/editors/include/ED_anim_api.h1
-rw-r--r--source/blender/editors/include/ED_armature.h18
-rw-r--r--source/blender/editors/include/ED_gpencil.h11
-rw-r--r--source/blender/editors/include/ED_image.h3
-rw-r--r--source/blender/editors/include/ED_info.h4
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h6
-rw-r--r--source/blender/editors/include/ED_manipulator_library.h202
-rw-r--r--source/blender/editors/include/ED_mesh.h29
-rw-r--r--source/blender/editors/include/ED_node.h2
-rw-r--r--source/blender/editors/include/ED_object.h30
-rw-r--r--source/blender/editors/include/ED_particle.h27
-rw-r--r--source/blender/editors/include/ED_render.h11
-rw-r--r--source/blender/editors/include/ED_scene.h43
-rw-r--r--source/blender/editors/include/ED_screen.h88
-rw-r--r--source/blender/editors/include/ED_sculpt.h3
-rw-r--r--source/blender/editors/include/ED_transform.h18
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h7
-rw-r--r--source/blender/editors/include/ED_uvedit.h8
-rw-r--r--source/blender/editors/include/ED_view3d.h82
-rw-r--r--source/blender/editors/include/UI_interface.h64
-rw-r--r--source/blender/editors/include/UI_interface_icons.h1
-rw-r--r--source/blender/editors/include/UI_resources.h29
-rw-r--r--source/blender/editors/interface/CMakeLists.txt1
-rw-r--r--source/blender/editors/interface/interface.c116
-rw-r--r--source/blender/editors/interface/interface_align.c6
-rw-r--r--source/blender/editors/interface/interface_anim.c5
-rw-r--r--source/blender/editors/interface/interface_draw.c1528
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c39
-rw-r--r--source/blender/editors/interface/interface_handlers.c122
-rw-r--r--source/blender/editors/interface/interface_icons.c188
-rw-r--r--source/blender/editors/interface/interface_intern.h30
-rw-r--r--source/blender/editors/interface/interface_layout.c108
-rw-r--r--source/blender/editors/interface/interface_ops.c338
-rw-r--r--source/blender/editors/interface/interface_panel.c336
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c4
-rw-r--r--source/blender/editors/interface/interface_region_popup.c2
-rw-r--r--source/blender/editors/interface/interface_region_search.c5
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c97
-rw-r--r--source/blender/editors/interface/interface_regions.c3
-rw-r--r--source/blender/editors/interface/interface_style.c27
-rw-r--r--source/blender/editors/interface/interface_templates.c496
-rw-r--r--source/blender/editors/interface/interface_utils.c84
-rw-r--r--source/blender/editors/interface/interface_widgets.c677
-rw-r--r--source/blender/editors/interface/resources.c219
-rw-r--r--source/blender/editors/interface/view2d.c330
-rw-r--r--source/blender/editors/io/CMakeLists.txt1
-rw-r--r--source/blender/editors/io/io_collada.c46
-rw-r--r--source/blender/editors/manipulator_library/CMakeLists.txt59
-rw-r--r--source/blender/editors/manipulator_library/geometry/geom_arrow_manipulator.c141
-rw-r--r--source/blender/editors/manipulator_library/geometry/geom_cube_manipulator.c75
-rw-r--r--source/blender/editors/manipulator_library/geometry/geom_dial_manipulator.c813
-rw-r--r--source/blender/editors/manipulator_library/manipulator_draw_utils.c131
-rw-r--r--source/blender/editors/manipulator_library/manipulator_geometry.h54
-rw-r--r--source/blender/editors/manipulator_library/manipulator_library_intern.h108
-rw-r--r--source/blender/editors/manipulator_library/manipulator_library_presets.c154
-rw-r--r--source/blender/editors/manipulator_library/manipulator_library_utils.c221
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c224
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c503
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c1109
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c735
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c478
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c373
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c190
-rw-r--r--source/blender/editors/mask/CMakeLists.txt1
-rw-r--r--source/blender/editors/mask/mask_add.c5
-rw-r--r--source/blender/editors/mask/mask_draw.c470
-rw-r--r--source/blender/editors/mask/mask_ops.c25
-rw-r--r--source/blender/editors/mask/mask_relationships.c7
-rw-r--r--source/blender/editors/mask/mask_shapekey.c11
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt2
-rw-r--r--source/blender/editors/mesh/editface.c10
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c348
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c407
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c175
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c13
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c58
-rw-r--r--source/blender/editors/mesh/editmesh_path.c16
-rw-r--r--source/blender/editors/mesh/editmesh_polybuild.c541
-rw-r--r--source/blender/editors/mesh/editmesh_select.c118
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c63
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c22
-rw-r--r--source/blender/editors/mesh/mesh_data.c77
-rw-r--r--source/blender/editors/mesh/mesh_intern.h5
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c28
-rw-r--r--source/blender/editors/mesh/mesh_ops.c25
-rw-r--r--source/blender/editors/mesh/meshtools.c46
-rw-r--r--source/blender/editors/metaball/CMakeLists.txt1
-rw-r--r--source/blender/editors/metaball/mball_edit.c15
-rw-r--r--source/blender/editors/object/CMakeLists.txt2
-rw-r--r--source/blender/editors/object/object_add.c394
-rw-r--r--source/blender/editors/object/object_bake.c73
-rw-r--r--source/blender/editors/object/object_bake_api.c33
-rw-r--r--source/blender/editors/object/object_constraint.c71
-rw-r--r--source/blender/editors/object/object_data_transfer.c37
-rw-r--r--source/blender/editors/object/object_edit.c314
-rw-r--r--source/blender/editors/object/object_facemap_ops.c492
-rw-r--r--source/blender/editors/object/object_group.c46
-rw-r--r--source/blender/editors/object/object_hook.c44
-rw-r--r--source/blender/editors/object/object_intern.h17
-rw-r--r--source/blender/editors/object/object_lattice.c7
-rw-r--r--source/blender/editors/object/object_modifier.c134
-rw-r--r--source/blender/editors/object/object_ops.c36
-rw-r--r--source/blender/editors/object/object_relations.c554
-rw-r--r--source/blender/editors/object/object_select.c334
-rw-r--r--source/blender/editors/object/object_shapekey.c20
-rw-r--r--source/blender/editors/object/object_transform.c464
-rw-r--r--source/blender/editors/object/object_vgroup.c96
-rw-r--r--source/blender/editors/physics/CMakeLists.txt1
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c29
-rw-r--r--source/blender/editors/physics/particle_boids.c20
-rw-r--r--source/blender/editors/physics/particle_edit.c358
-rw-r--r--source/blender/editors/physics/particle_object.c102
-rw-r--r--source/blender/editors/physics/physics_fluid.c40
-rw-r--r--source/blender/editors/physics/physics_ops.c17
-rw-r--r--source/blender/editors/physics/physics_pointcache.c16
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c26
-rw-r--r--source/blender/editors/physics/rigidbody_object.c20
-rw-r--r--source/blender/editors/render/CMakeLists.txt2
-rw-r--r--source/blender/editors/render/render_intern.h4
-rw-r--r--source/blender/editors/render/render_internal.c138
-rw-r--r--source/blender/editors/render/render_opengl.c94
-rw-r--r--source/blender/editors/render/render_ops.c4
-rw-r--r--source/blender/editors/render/render_preview.c171
-rw-r--r--source/blender/editors/render/render_shading.c156
-rw-r--r--source/blender/editors/render/render_update.c203
-rw-r--r--source/blender/editors/render/render_view.c15
-rw-r--r--source/blender/editors/scene/CMakeLists.txt44
-rw-r--r--source/blender/editors/scene/scene_edit.c278
-rw-r--r--source/blender/editors/screen/CMakeLists.txt4
-rw-r--r--source/blender/editors/screen/area.c554
-rw-r--r--source/blender/editors/screen/glutil.c646
-rw-r--r--source/blender/editors/screen/screen_context.c163
-rw-r--r--source/blender/editors/screen/screen_draw.c496
-rw-r--r--source/blender/editors/screen/screen_edit.c774
-rw-r--r--source/blender/editors/screen/screen_intern.h19
-rw-r--r--source/blender/editors/screen/screen_ops.c251
-rw-r--r--source/blender/editors/screen/screendump.c31
-rw-r--r--source/blender/editors/screen/workspace_edit.c454
-rw-r--r--source/blender/editors/screen/workspace_layout_edit.c197
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt1
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c392
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c11
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c52
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c52
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h5
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c27
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c59
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c42
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c50
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.c9
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_utils.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_proj.c30
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c26
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c50
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c16
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c24
-rw-r--r--source/blender/editors/sound/CMakeLists.txt2
-rw-r--r--source/blender/editors/sound/sound_ops.c8
-rw-r--r--source/blender/editors/space_action/action_buttons.c1
-rw-r--r--source/blender/editors/space_action/action_draw.c108
-rw-r--r--source/blender/editors/space_action/space_action.c26
-rw-r--r--source/blender/editors/space_api/spacetypes.c25
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c141
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h1
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c20
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c30
-rw-r--r--source/blender/editors/space_clip/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c7
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c261
-rw-r--r--source/blender/editors/space_clip/clip_draw.c873
-rw-r--r--source/blender/editors/space_clip/clip_editor.c11
-rw-r--r--source/blender/editors/space_clip/clip_graph_draw.c150
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c5
-rw-r--r--source/blender/editors/space_clip/clip_intern.h4
-rw-r--r--source/blender/editors/space_clip/clip_ops.c5
-rw-r--r--source/blender/editors/space_clip/clip_utils.c76
-rw-r--r--source/blender/editors/space_clip/space_clip.c42
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c7
-rw-r--r--source/blender/editors/space_clip/tracking_ops_orient.c43
-rw-r--r--source/blender/editors/space_clip/tracking_ops_plane.c7
-rw-r--r--source/blender/editors/space_clip/tracking_ops_solve.c7
-rw-r--r--source/blender/editors/space_clip/tracking_ops_stabilize.c11
-rw-r--r--source/blender/editors/space_clip/tracking_ops_track.c3
-rw-r--r--source/blender/editors/space_console/console_draw.c22
-rw-r--r--source/blender/editors/space_console/space_console.c4
-rw-r--r--source/blender/editors/space_file/file_draw.c125
-rw-r--r--source/blender/editors/space_file/file_utils.c1
-rw-r--r--source/blender/editors/space_file/filesel.c5
-rw-r--r--source/blender/editors/space_file/space_file.c44
-rw-r--r--source/blender/editors/space_graph/CMakeLists.txt3
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c4
-rw-r--r--source/blender/editors/space_graph/graph_draw.c747
-rw-r--r--source/blender/editors/space_graph/graph_edit.c7
-rw-r--r--source/blender/editors/space_graph/space_graph.c87
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_image/image_draw.c478
-rw-r--r--source/blender/editors/space_image/image_edit.c10
-rw-r--r--source/blender/editors/space_image/image_intern.h2
-rw-r--r--source/blender/editors/space_image/image_ops.c44
-rw-r--r--source/blender/editors/space_image/space_image.c98
-rw-r--r--source/blender/editors/space_info/info_stats.c103
-rw-r--r--source/blender/editors/space_info/space_info.c11
-rw-r--r--source/blender/editors/space_info/textview.c46
-rw-r--r--source/blender/editors/space_logic/logic_window.c25
-rw-r--r--source/blender/editors/space_logic/space_logic.c4
-rw-r--r--source/blender/editors/space_nla/nla_channels.c24
-rw-r--r--source/blender/editors/space_nla/nla_draw.c455
-rw-r--r--source/blender/editors/space_nla/space_nla.c20
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_node/drawnode.c501
-rw-r--r--source/blender/editors/space_node/node_draw.c490
-rw-r--r--source/blender/editors/space_node/node_edit.c45
-rw-r--r--source/blender/editors/space_node/node_intern.h13
-rw-r--r--source/blender/editors/space_node/node_manipulators.c616
-rw-r--r--source/blender/editors/space_node/node_ops.c4
-rw-r--r--source/blender/editors/space_node/node_templates.c3
-rw-r--r--source/blender/editors/space_node/space_node.c63
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt3
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c572
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c1174
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c344
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h133
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c301
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c428
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c290
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c497
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c233
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c39
-rw-r--r--source/blender/editors/space_script/space_script.c4
-rw-r--r--source/blender/editors/space_sequencer/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c738
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c23
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h2
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c16
-rw-r--r--source/blender/editors/space_text/space_text.c3
-rw-r--r--source/blender/editors/space_text/text_draw.c268
-rw-r--r--source/blender/editors/space_text/text_ops.c2
-rw-r--r--source/blender/editors/space_time/space_time.c316
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c8
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt12
-rw-r--r--source/blender/editors/space_view3d/drawanimviz.c132
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c1471
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c1047
-rw-r--r--source/blender/editors/space_view3d/drawobject.c4898
-rw-r--r--source/blender/editors/space_view3d/drawsimdebug.c111
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c3
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c408
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c29
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c4579
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c2186
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c293
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c51
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c61
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h118
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c27
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_armature.c220
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_camera.c448
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_empty.c196
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_forcefield.c118
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_lamp.c289
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_ruler.c1079
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c38
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c29
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c239
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c366
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c21
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c442
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c43
-rw-r--r--source/blender/editors/transform/CMakeLists.txt6
-rw-r--r--source/blender/editors/transform/transform.c377
-rw-r--r--source/blender/editors/transform/transform.h19
-rw-r--r--source/blender/editors/transform/transform_constraints.c64
-rw-r--r--source/blender/editors/transform/transform_conversions.c335
-rw-r--r--source/blender/editors/transform/transform_generics.c122
-rw-r--r--source/blender/editors/transform/transform_manipulator.c2187
-rw-r--r--source/blender/editors/transform/transform_manipulator2d.c383
-rw-r--r--source/blender/editors/transform/transform_ops.c63
-rw-r--r--source/blender/editors/transform/transform_orientations.c114
-rw-r--r--source/blender/editors/transform/transform_snap.c90
-rw-r--r--source/blender/editors/transform/transform_snap_object.c32
-rw-r--r--source/blender/editors/util/CMakeLists.txt3
-rw-r--r--source/blender/editors/util/ed_transverts.c5
-rw-r--r--source/blender/editors/util/ed_util.c48
-rw-r--r--source/blender/editors/util/editmode_undo.c5
-rw-r--r--source/blender/editors/util/undo.c17
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt1
-rw-r--r--source/blender/editors/uvedit/uvedit_buttons.c10
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c640
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h2
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c335
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c146
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c40
-rw-r--r--source/blender/freestyle/CMakeLists.txt5
-rw-r--r--source/blender/freestyle/FRS_freestyle.h7
-rw-r--r--source/blender/freestyle/intern/application/Controller.cpp8
-rw-r--r--source/blender/freestyle/intern/application/Controller.h2
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp8
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h4
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp72
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h2
-rw-r--r--source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp38
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp9
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h15
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeViewLayer.cpp (renamed from source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp)8
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeViewLayer.h (renamed from source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h)24
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneHash.cpp4
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneHash.h4
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneVisitor.h4
-rw-r--r--source/blender/gpu/CMakeLists.txt108
-rw-r--r--source/blender/gpu/GPU_basic_shader.h9
-rw-r--r--source/blender/gpu/GPU_batch.h51
-rw-r--r--source/blender/gpu/GPU_buffers.h8
-rw-r--r--source/blender/gpu/GPU_debug.h18
-rw-r--r--source/blender/gpu/GPU_draw.h39
-rw-r--r--source/blender/gpu/GPU_extensions.h10
-rw-r--r--source/blender/gpu/GPU_framebuffer.h19
-rw-r--r--source/blender/gpu/GPU_glew.h4
-rw-r--r--source/blender/gpu/GPU_immediate.h58
-rw-r--r--source/blender/gpu/GPU_immediate_util.h64
-rw-r--r--source/blender/gpu/GPU_lamp.h77
-rw-r--r--source/blender/gpu/GPU_legacy_stubs.h457
-rw-r--r--source/blender/gpu/GPU_material.h71
-rw-r--r--source/blender/gpu/GPU_matrix.h190
-rw-r--r--source/blender/gpu/GPU_select.h3
-rw-r--r--source/blender/gpu/GPU_shader.h114
-rw-r--r--source/blender/gpu/GPU_texture.h131
-rw-r--r--source/blender/gpu/GPU_uniformbuffer.h59
-rw-r--r--source/blender/gpu/GPU_viewport.h135
-rw-r--r--source/blender/gpu/intern/gpu_basic_shader.c413
-rw-r--r--source/blender/gpu/intern/gpu_batch.c171
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c776
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c554
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h23
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c341
-rw-r--r--source/blender/gpu/intern/gpu_debug.c700
-rw-r--r--source/blender/gpu/intern/gpu_draw.c655
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c130
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c561
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c88
-rw-r--r--source/blender/gpu/intern/gpu_immediate_util.c424
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c11
-rw-r--r--source/blender/gpu/intern/gpu_lamp.c483
-rw-r--r--source/blender/gpu/intern/gpu_lamp_private.h84
-rw-r--r--source/blender/gpu/intern/gpu_material.c920
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c649
-rw-r--r--source/blender/gpu/intern/gpu_select.c33
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c10
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.c6
-rw-r--r--source/blender/gpu/intern/gpu_shader.c713
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.h45
-rw-r--r--source/blender/gpu/intern/gpu_texture.c920
-rw-r--r--source/blender/gpu/intern/gpu_uniformbuffer.c378
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c682
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl54
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl56
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl59
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl24
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl27
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_vert.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl26
-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_image_vert.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl26
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl22
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl24
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_vert.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_frag.glsl37
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_geom.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_vert.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_checker_frag.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl54
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl60
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl68
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl44
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl67
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl52
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fire_frag.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl5
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl111
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl68
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl39
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl34
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl45
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_lib.glsl7
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl23
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_vert.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_geometry.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl34
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl30
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl122
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_wire_vert.glsl103
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl50
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl25
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl57
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl63
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl36
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl29
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl32
-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.glsl22
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl31
-rw-r--r--source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl34
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl819
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl24
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl17
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl36
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl31
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl19
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl17
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl19
-rw-r--r--source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl7
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_frag.glsl15
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_vert.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex.glsl15
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex_world.glsl5
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl7
-rw-r--r--source/blender/ikplugin/BIK_api.h5
-rw-r--r--source/blender/ikplugin/intern/ikplugin_api.c8
-rw-r--r--source/blender/ikplugin/intern/ikplugin_api.h5
-rw-r--r--source/blender/ikplugin/intern/iksolver_plugin.c14
-rw-r--r--source/blender/ikplugin/intern/iksolver_plugin.h7
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.cpp42
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.h4
-rw-r--r--source/blender/imbuf/intern/thumbs.c4
-rw-r--r--source/blender/imbuf/intern/thumbs_blend.c1
-rw-r--r--source/blender/makesdna/DNA_ID.h113
-rw-r--r--source/blender/makesdna/DNA_action_types.h18
-rw-r--r--source/blender/makesdna/DNA_camera_types.h53
-rw-r--r--source/blender/makesdna/DNA_curve_types.h1
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h8
-rw-r--r--source/blender/makesdna/DNA_defs.h6
-rw-r--r--source/blender/makesdna/DNA_fileglobal_types.h6
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h5
-rw-r--r--source/blender/makesdna/DNA_gpu_types.h2
-rw-r--r--source/blender/makesdna/DNA_group_types.h7
-rw-r--r--source/blender/makesdna/DNA_lamp_types.h11
-rw-r--r--source/blender/makesdna/DNA_lattice_types.h1
-rw-r--r--source/blender/makesdna/DNA_layer_types.h164
-rw-r--r--source/blender/makesdna/DNA_lightprobe_types.h109
-rw-r--r--source/blender/makesdna/DNA_material_types.h52
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h2
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h76
-rw-r--r--source/blender/makesdna/DNA_meta_types.h8
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h2
-rw-r--r--source/blender/makesdna/DNA_node_types.h5
-rw-r--r--source/blender/makesdna/DNA_object_force.h6
-rw-r--r--source/blender/makesdna/DNA_object_types.h63
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h21
-rw-r--r--source/blender/makesdna/DNA_particle_types.h10
-rw-r--r--source/blender/makesdna/DNA_scene_types.h164
-rw-r--r--source/blender/makesdna/DNA_screen_types.h22
-rw-r--r--source/blender/makesdna/DNA_space_types.h52
-rw-r--r--source/blender/makesdna/DNA_text_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h22
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h84
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h17
-rw-r--r--source/blender/makesdna/DNA_workspace_types.h156
-rw-r--r--source/blender/makesdna/DNA_world_types.h4
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c78
-rw-r--r--source/blender/makesdna/intern/makesdna.c19
-rw-r--r--source/blender/makesrna/RNA_access.h71
-rw-r--r--source/blender/makesrna/RNA_define.h10
-rw-r--r--source/blender/makesrna/RNA_enum_types.h4
-rw-r--r--source/blender/makesrna/RNA_types.h10
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt12
-rw-r--r--source/blender/makesrna/intern/makesrna.c16
-rw-r--r--source/blender/makesrna/intern/rna_ID.c62
-rw-r--r--source/blender/makesrna/intern/rna_access.c711
-rw-r--r--source/blender/makesrna/intern/rna_animation.c39
-rw-r--r--source/blender/makesrna/intern/rna_armature.c9
-rw-r--r--source/blender/makesrna/intern/rna_boid.c14
-rw-r--r--source/blender/makesrna/intern/rna_brush.c36
-rw-r--r--source/blender/makesrna/intern/rna_cachefile.c5
-rw-r--r--source/blender/makesrna/intern/rna_camera.c211
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c9
-rw-r--r--source/blender/makesrna/intern/rna_color.c15
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c1
-rw-r--r--source/blender/makesrna/intern/rna_context.c101
-rw-r--r--source/blender/makesrna/intern/rna_curve.c12
-rw-r--r--source/blender/makesrna/intern/rna_curve_api.c10
-rw-r--r--source/blender/makesrna/intern/rna_define.c31
-rw-r--r--source/blender/makesrna/intern/rna_depsgraph.c242
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c7
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c10
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c5
-rw-r--r--source/blender/makesrna/intern/rna_group.c31
-rw-r--r--source/blender/makesrna/intern/rna_image.c35
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c5
-rw-r--r--source/blender/makesrna/intern/rna_internal.h78
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h71
-rw-r--r--source/blender/makesrna/intern/rna_key.c5
-rw-r--r--source/blender/makesrna/intern/rna_lamp.c92
-rw-r--r--source/blender/makesrna/intern/rna_lattice.c7
-rw-r--r--source/blender/makesrna/intern/rna_lattice_api.c10
-rw-r--r--source/blender/makesrna/intern/rna_layer.c2320
-rw-r--r--source/blender/makesrna/intern/rna_lightprobe.c204
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c21
-rw-r--r--source/blender/makesrna/intern/rna_main.c14
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c121
-rw-r--r--source/blender/makesrna/intern/rna_mask.c11
-rw-r--r--source/blender/makesrna/intern/rna_material.c101
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c529
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c19
-rw-r--r--source/blender/makesrna/intern/rna_mesh_utils.h11
-rw-r--r--source/blender/makesrna/intern/rna_meta.c11
-rw-r--r--source/blender/makesrna/intern/rna_meta_api.c9
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c39
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c4
-rw-r--r--source/blender/makesrna/intern/rna_nla.c1
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c48
-rw-r--r--source/blender/makesrna/intern/rna_object.c528
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c149
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c43
-rw-r--r--source/blender/makesrna/intern/rna_particle.c44
-rw-r--r--source/blender/makesrna/intern/rna_pose.c23
-rw-r--r--source/blender/makesrna/intern/rna_render.c94
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c1
-rw-r--r--source/blender/makesrna/intern/rna_rna.c1011
-rw-r--r--source/blender/makesrna/intern/rna_scene.c984
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c66
-rw-r--r--source/blender/makesrna/intern/rna_screen.c92
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c91
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c10
-rw-r--r--source/blender/makesrna/intern/rna_space.c464
-rw-r--r--source/blender/makesrna/intern/rna_space_api.c17
-rw-r--r--source/blender/makesrna/intern/rna_speaker.c1
-rw-r--r--source/blender/makesrna/intern/rna_texture.c32
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c7
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c36
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c130
-rw-r--r--source/blender/makesrna/intern/rna_vfont.c5
-rw-r--r--source/blender/makesrna/intern/rna_wm.c208
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c45
-rw-r--r--source/blender/makesrna/intern/rna_wm_manipulator.c1306
-rw-r--r--source/blender/makesrna/intern/rna_wm_manipulator_api.c290
-rw-r--r--source/blender/makesrna/intern/rna_workspace.c163
-rw-r--r--source/blender/makesrna/intern/rna_world.c18
-rw-r--r--source/blender/modifiers/CMakeLists.txt7
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c29
-rw-r--r--source/blender/modifiers/intern/MOD_array.c58
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c5
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c23
-rw-r--r--source/blender/modifiers/intern/MOD_build.c5
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c27
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c30
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c5
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c5
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c31
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c23
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c5
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c33
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c45
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c4
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c17
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim.c40
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c25
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c5
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c5
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c27
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c24
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache.c7
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c32
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c23
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c21
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c5
-rw-r--r--source/blender/modifiers/intern/MOD_none.c1
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c20
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c6
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c25
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c7
-rw-r--r--source/blender/modifiers/intern/MOD_remesh.c6
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c24
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c17
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c27
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c24
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c2
-rw-r--r--source/blender/modifiers/intern/MOD_smoke.c36
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c5
-rw-r--r--source/blender/modifiers/intern/MOD_softbody.c29
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c5
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c27
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c5
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c26
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c2
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c53
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c42
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c30
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c46
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c27
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c26
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c32
-rw-r--r--source/blender/modifiers/intern/MOD_wireframe.c4
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_composite.h2
-rw-r--r--source/blender/nodes/NOD_shader.h3
-rw-r--r--source/blender/nodes/NOD_socket.h2
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c17
-rw-r--r--source/blender/nodes/intern/node_socket.c2
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c140
-rw-r--r--source/blender/nodes/shader/node_shader_util.c2
-rw-r--r--source/blender/nodes/shader/node_shader_util.h2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_add_shader.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_attribute.c19
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_background.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bevel.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_brightness.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c44
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_toon.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bump.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_camera.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_curves.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_eevee_specular.c87
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_emission.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_fresnel.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_gamma.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geom.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geometry.c5
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hueSatVal.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_invert.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_lamp.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_layer_weight.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_light_falloff.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_light_path.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mapping.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mixRgb.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mix_shader.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_object_info.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_material.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_world.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_particle_info.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_rgb.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_squeeze.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c19
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tangent.c23
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_brick.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_checker.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_coord.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_gradient.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_magic.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_noise.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_sky.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_wave.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_texture.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_uvmap.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_valToRgb.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_value.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectMath.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_absorption.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_scatter.c4
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c5
-rw-r--r--source/blender/python/CMakeLists.txt1
-rw-r--r--source/blender/python/bmesh/CMakeLists.txt1
-rw-r--r--source/blender/python/bmesh/bmesh_py_api.c5
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c14
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c21
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.c91
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.h4
-rw-r--r--source/blender/python/gawain/CMakeLists.txt47
-rw-r--r--source/blender/python/gawain/gwn_py_api.c63
-rw-r--r--source/blender/python/gawain/gwn_py_api.h30
-rw-r--r--source/blender/python/gawain/gwn_py_types.c847
-rw-r--r--source/blender/python/gawain/gwn_py_types.h67
-rw-r--r--source/blender/python/generic/bgl.c1217
-rw-r--r--source/blender/python/generic/blf_py_api.c4
-rw-r--r--source/blender/python/intern/CMakeLists.txt8
-rw-r--r--source/blender/python/intern/bpy.c5
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c6
-rw-r--r--source/blender/python/intern/bpy_interface.c5
-rw-r--r--source/blender/python/intern/bpy_intern_string.c44
-rw-r--r--source/blender/python/intern/bpy_intern_string.h21
-rw-r--r--source/blender/python/intern/bpy_library_load.c11
-rw-r--r--source/blender/python/intern/bpy_manipulator_wrap.c236
-rw-r--r--source/blender/python/intern/bpy_manipulator_wrap.h36
-rw-r--r--source/blender/python/intern/bpy_msgbus.c400
-rw-r--r--source/blender/python/intern/bpy_msgbus.h30
-rw-r--r--source/blender/python/intern/bpy_props.h2
-rw-r--r--source/blender/python/intern/bpy_rna.c74
-rw-r--r--source/blender/python/intern/bpy_rna_manipulator.c565
-rw-r--r--source/blender/python/intern/bpy_rna_manipulator.h32
-rw-r--r--source/blender/python/intern/gpu.c8
-rw-r--r--source/blender/python/intern/gpu.h2
-rw-r--r--source/blender/python/intern/gpu_offscreen.c26
-rw-r--r--source/blender/python/intern/gpu_py_matrix.c552
-rw-r--r--source/blender/python/intern/gpu_py_select.c92
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c7
-rw-r--r--source/blender/render/CMakeLists.txt1
-rw-r--r--source/blender/render/extern/include/RE_engine.h29
-rw-r--r--source/blender/render/extern/include/RE_multires_bake.h6
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h20
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h5
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h2
-rw-r--r--source/blender/render/intern/include/render_types.h5
-rw-r--r--source/blender/render/intern/include/rendercore.h2
-rw-r--r--source/blender/render/intern/include/renderpipeline.h5
-rw-r--r--source/blender/render/intern/source/bake.c7
-rw-r--r--source/blender/render/intern/source/convertblender.c169
-rw-r--r--source/blender/render/intern/source/envmap.c21
-rw-r--r--source/blender/render/intern/source/external_engine.c151
-rw-r--r--source/blender/render/intern/source/initrender.c7
-rw-r--r--source/blender/render/intern/source/multires_bake.c57
-rw-r--r--source/blender/render/intern/source/pipeline.c208
-rw-r--r--source/blender/render/intern/source/pointdensity.c54
-rw-r--r--source/blender/render/intern/source/rayshade.c43
-rw-r--r--source/blender/render/intern/source/render_result.c94
-rw-r--r--source/blender/render/intern/source/rendercore.c16
-rw-r--r--source/blender/render/intern/source/shadeinput.c53
-rw-r--r--source/blender/render/intern/source/shadeoutput.c26
-rw-r--r--source/blender/render/intern/source/volumetric.c2
-rw-r--r--source/blender/render/intern/source/zbuf.c6
-rw-r--r--source/blender/windowmanager/CMakeLists.txt22
-rw-r--r--source/blender/windowmanager/WM_api.h46
-rw-r--r--source/blender/windowmanager/WM_message.h30
-rw-r--r--source/blender/windowmanager/WM_types.h22
-rw-r--r--source/blender/windowmanager/intern/wm.c39
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c18
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c269
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c398
-rw-r--r--source/blender/windowmanager/intern/wm_files.c306
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c114
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c262
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c22
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c401
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c93
-rw-r--r--source/blender/windowmanager/intern/wm_stereo.c198
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c33
-rw-r--r--source/blender/windowmanager/intern/wm_toolsystem.c107
-rw-r--r--source/blender/windowmanager/intern/wm_window.c322
-rw-r--r--source/blender/windowmanager/manipulators/WM_manipulator_api.h331
-rw-r--r--source/blender/windowmanager/manipulators/WM_manipulator_types.h408
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator.c731
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c788
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_group_type.c198
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h140
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c1139
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_target_props.c364
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c212
-rw-r--r--source/blender/windowmanager/manipulators/wm_manipulator_fn.h87
-rw-r--r--source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h98
-rw-r--r--source/blender/windowmanager/message_bus/intern/wm_message_bus.c247
-rw-r--r--source/blender/windowmanager/message_bus/intern/wm_message_bus_intern.h55
-rw-r--r--source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c316
-rw-r--r--source/blender/windowmanager/message_bus/intern/wm_message_bus_static.c136
-rw-r--r--source/blender/windowmanager/message_bus/wm_message_bus.h256
-rw-r--r--source/blender/windowmanager/wm.h4
-rw-r--r--source/blender/windowmanager/wm_draw.h4
-rw-r--r--source/blender/windowmanager/wm_event_system.h3
-rw-r--r--source/blender/windowmanager/wm_event_types.h2
-rw-r--r--source/blender/windowmanager/wm_files.h1
-rw-r--r--source/blender/windowmanager/wm_window.h14
-rw-r--r--source/blenderplayer/CMakeLists.txt9
-rw-r--r--source/blenderplayer/bad_level_call_stubs/CMakeLists.txt3
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c154
-rw-r--r--source/creator/CMakeLists.txt6
-rw-r--r--source/creator/creator.c4
-rw-r--r--source/creator/creator_args.c74
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp4
-rw-r--r--source/gameengine/BlenderRoutines/CMakeLists.txt2
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp3
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp6
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp42
-rw-r--r--source/gameengine/Converter/BL_ModifierDeformer.cpp8
-rw-r--r--source/gameengine/Converter/CMakeLists.txt2
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp2
-rw-r--r--source/gameengine/GamePlayer/ghost/CMakeLists.txt3
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp4
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp7
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.cpp2
-rw-r--r--source/gameengine/Ketsji/BL_Material.cpp1
-rw-r--r--source/gameengine/Ketsji/BL_Material.h1
-rw-r--r--source/gameengine/Ketsji/CMakeLists.txt2
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp23
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.h1
-rw-r--r--source/gameengine/Ketsji/KX_Camera.cpp51
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp11
-rw-r--r--source/gameengine/Ketsji/KX_Light.h1
-rw-r--r--source/gameengine/Ketsji/KX_NavMeshObject.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.h4
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp8
-rw-r--r--source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp4
-rw-r--r--source/gameengine/Rasterizer/RAS_IPolygonMaterial.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp1
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp41
m---------source/tools0
1339 files changed, 150655 insertions, 45504 deletions
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index c696719e650..4e4724771f3 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -23,6 +23,10 @@
#
# ***** END GPL LICENSE BLOCK *****
+if(WITH_LEGACY_OPENGL)
+ add_definitions(-DWITH_LEGACY_OPENGL)
+endif()
+
add_subdirectory(blender)
if(WITH_GAMEENGINE)
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 818d4cd3d89..c2fac8fc7d7 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -54,6 +54,8 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_key_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_lamp_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_lattice_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_layer_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_lightprobe_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_linestyle_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_listBase.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_material_types.h
@@ -88,6 +90,7 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_view2d_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_view3d_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_windowmanager_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_workspace_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_world_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_movieclip_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_tracking_types.h
@@ -100,6 +103,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/CMakeLists.txt b/source/blender/alembic/CMakeLists.txt
index fb08887c076..d3b5e189292 100644
--- a/source/blender/alembic/CMakeLists.txt
+++ b/source/blender/alembic/CMakeLists.txt
@@ -29,11 +29,11 @@ set(INC
../blenlib
../blenloader
../bmesh
+ ../depsgraph
../editors/include
../makesdna
../makesrna
../windowmanager
- ../depsgraph
../../../intern/guardedalloc
../../../intern/utfconv
)
diff --git a/source/blender/alembic/intern/abc_camera.cc b/source/blender/alembic/intern/abc_camera.cc
index 16416205983..aa5d77ce4ec 100644
--- a/source/blender/alembic/intern/abc_camera.cc
+++ b/source/blender/alembic/intern/abc_camera.cc
@@ -49,12 +49,13 @@ using Alembic::AbcGeom::kWrapExisting;
/* ************************************************************************** */
-AbcCameraWriter::AbcCameraWriter(Scene *scene,
+AbcCameraWriter::AbcCameraWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
ExportSettings &settings)
- : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
+ : AbcObjectWriter(eval_ctx, scene, ob, time_sampling, settings, parent)
{
OCamera camera(parent->alembicXform(), m_name, m_time_sampling);
m_camera_schema = camera.getSchema();
diff --git a/source/blender/alembic/intern/abc_camera.h b/source/blender/alembic/intern/abc_camera.h
index 16c5cccd5ea..772b7a6aec6 100644
--- a/source/blender/alembic/intern/abc_camera.h
+++ b/source/blender/alembic/intern/abc_camera.h
@@ -35,7 +35,8 @@ class AbcCameraWriter : public AbcObjectWriter {
Alembic::AbcGeom::OFloatProperty m_eye_separation;
public:
- AbcCameraWriter(Scene *scene,
+ AbcCameraWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc
index f73fe957fea..5328c471093 100644
--- a/source/blender/alembic/intern/abc_curves.cc
+++ b/source/blender/alembic/intern/abc_curves.cc
@@ -71,12 +71,13 @@ using Alembic::AbcGeom::OV2fGeomParam;
/* ************************************************************************** */
-AbcCurveWriter::AbcCurveWriter(Scene *scene,
+AbcCurveWriter::AbcCurveWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
ExportSettings &settings)
- : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
+ : AbcObjectWriter(eval_ctx, scene, ob, time_sampling, settings, parent)
{
OCurves curves(parent->alembicXform(), m_name, m_time_sampling);
m_schema = curves.getSchema();
diff --git a/source/blender/alembic/intern/abc_curves.h b/source/blender/alembic/intern/abc_curves.h
index a9231f947b2..73cc8b35e27 100644
--- a/source/blender/alembic/intern/abc_curves.h
+++ b/source/blender/alembic/intern/abc_curves.h
@@ -36,7 +36,8 @@ class AbcCurveWriter : public AbcObjectWriter {
Alembic::AbcGeom::OCurvesSchema::Sample m_sample;
public:
- AbcCurveWriter(Scene *scene,
+ AbcCurveWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index 946b89213e6..945f82e8827 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -136,45 +136,50 @@ static bool object_type_is_exportable(Scene *scene, Object *ob)
/**
* Returns whether this object should be exported into the Alembic file.
*
- * \param settings: export settings, used for options like 'selected only'.
- * \param ob: the object in question.
+ * \param settings export settings, used for options like 'selected only'.
+ * \param ob the object's base in question.
* \param is_duplicated: Normally false; true when the object is instanced
* into the scene by a dupli-object (e.g. part of a dupligroup).
* This ignores selection and layer visibility,
* and assumes that the dupli-object itself (e.g. the group-instantiating empty) is exported.
*/
-static bool export_object(const ExportSettings * const settings, Object *ob,
+static bool export_object(const ExportSettings * const settings, const Base * const ob_base,
bool is_duplicated)
{
if (!is_duplicated) {
/* These two tests only make sense when the object isn't being instanced
* into the scene. When it is, its exportability is determined by
* its dupli-object and the DupliObject::no_draw property. */
- 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;
}
/* ************************************************************************** */
-AbcExporter::AbcExporter(Main *bmain, Scene *scene, const char *filename, ExportSettings &settings)
+AbcExporter::AbcExporter(Main *bmain, EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ Depsgraph *depsgraph,
+ const char *filename, ExportSettings &settings)
: m_bmain(bmain)
, m_settings(settings)
, m_filename(filename)
, m_trans_sampling_index(0)
, m_shape_sampling_index(0)
+ , m_eval_ctx(eval_ctx)
, m_scene(scene)
+ , m_view_layer(view_layer)
+ , m_depsgraph(depsgraph)
, m_writer(NULL)
{}
@@ -359,40 +364,43 @@ 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.view_layer->object_bases.first); base; base = base->next) {
Object *ob = base->object;
- switch (ob->type) {
- case OB_LAMP:
- case OB_LATTICE:
- case OB_SPEAKER:
- /* We do not export transforms for objects of these classes. */
- break;
- default:
- exploreTransform(eval_ctx, ob, ob->parent);
+ if (export_object(&m_settings, base, false)) {
+ switch (ob->type) {
+ case OB_LAMP:
+ case OB_LATTICE:
+ case OB_SPEAKER:
+ /* We do not export transforms for objects of these classes. */
+ break;
+ default:
+ exploreTransform(eval_ctx, base, ob->parent, NULL);
+ }
}
-
- 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)
{
+ Object *ob = ob_base->object;
+
/* If an object isn't exported itself, its duplilist shouldn't be
* exported either. */
- if (!export_object(&m_settings, ob, dupliObParent != NULL)) {
+ if (!export_object(&m_settings, ob_base, dupliObParent != NULL)) {
return;
}
if (object_type_is_exportable(m_scene, ob)) {
- createTransformWriter(ob, parent, dupliObParent);
+ createTransformWriter(eval_ctx, ob, parent, dupliObParent);
}
ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
if (lb) {
+ Base fake_base = *ob_base; // copy flags (like selection state) from the real object.
+ fake_base.next = fake_base.prev = NULL;
+
DupliObject *link = static_cast<DupliObject *>(lb->first);
Object *dupli_ob = NULL;
Object *dupli_parent = NULL;
@@ -407,7 +415,8 @@ void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Obje
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);
}
}
}
@@ -415,7 +424,7 @@ void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Obje
free_object_duplilist(lb);
}
-AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupliObParent)
+AbcTransformWriter * AbcExporter::createTransformWriter(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent)
{
/* An object should not be its own parent, or we'll get infinite loops. */
BLI_assert(ob != parent);
@@ -450,29 +459,29 @@ AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *pare
* return the parent's AbcTransformWriter pointer. */
if (parent->parent) {
if (parent == dupliObParent) {
- parent_writer = createTransformWriter(parent, parent->parent, NULL);
+ parent_writer = createTransformWriter(eval_ctx, parent, parent->parent, NULL);
}
else {
- parent_writer = createTransformWriter(parent, parent->parent, dupliObParent);
+ parent_writer = createTransformWriter(eval_ctx, parent, parent->parent, dupliObParent);
}
}
else if (parent == dupliObParent) {
if (dupliObParent->parent == NULL) {
- parent_writer = createTransformWriter(parent, NULL, NULL);
+ parent_writer = createTransformWriter(eval_ctx, parent, NULL, NULL);
}
else {
- parent_writer = createTransformWriter(parent, dupliObParent->parent, dupliObParent->parent);
+ parent_writer = createTransformWriter(eval_ctx, parent, dupliObParent->parent, dupliObParent->parent);
}
}
else {
- parent_writer = createTransformWriter(parent, dupliObParent, dupliObParent);
+ parent_writer = createTransformWriter(eval_ctx, parent, dupliObParent, dupliObParent);
}
BLI_assert(parent_writer);
alembic_parent = parent_writer->alembicXform();
}
- my_writer = new AbcTransformWriter(ob, alembic_parent, parent_writer,
+ my_writer = new AbcTransformWriter(eval_ctx, ob, alembic_parent, parent_writer,
m_trans_sampling_index, m_settings);
/* When flattening, the matrix of the dupliobject has to be added. */
@@ -486,29 +495,28 @@ AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *pare
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.view_layer->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)
{
/* If an object isn't exported itself, its duplilist shouldn't be
* exported either. */
- if (!export_object(&m_settings, ob, dupliObParent != NULL)) {
+ if (!export_object(&m_settings, ob_base, dupliObParent != NULL)) {
return;
}
- createShapeWriter(ob, dupliObParent);
+ createShapeWriter(ob_base, dupliObParent);
+ Object *ob = ob_base->object;
ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
if (lb) {
+ Base fake_base = *ob_base; // copy flags (like selection state) from the real object.
+ fake_base.next = fake_base.prev = NULL;
+
DupliObject *link = static_cast<DupliObject *>(lb->first);
for (; link; link = link->next) {
@@ -516,9 +524,9 @@ void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Object *ob, Object
if (m_settings.renderable_only && link->no_draw) {
continue;
}
-
if (link->type == OB_DUPLIGROUP) {
- exploreObject(eval_ctx, link->ob, ob);
+ fake_base.object = link->ob;
+ exploreObject(eval_ctx, &fake_base, ob);
}
}
}
@@ -541,16 +549,18 @@ void AbcExporter::createParticleSystemsWriters(Object *ob, AbcTransformWriter *x
if (m_settings.export_hair && psys->part->type == PART_HAIR) {
m_settings.export_child_hairs = true;
- m_shapes.push_back(new AbcHairWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
+ m_shapes.push_back(new AbcHairWriter(m_eval_ctx, m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
}
else if (m_settings.export_particles && psys->part->type == PART_EMITTER) {
- m_shapes.push_back(new AbcPointsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
+ m_shapes.push_back(new AbcPointsWriter(m_eval_ctx, m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
}
}
}
-void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
+void AbcExporter::createShapeWriter(Base *ob_base, Object *dupliObParent)
{
+ Object *ob = ob_base->object;
+
if (!object_type_is_exportable(m_scene, ob)) {
return;
}
@@ -582,7 +592,7 @@ void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
return;
}
- m_shapes.push_back(new AbcMeshWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings));
+ m_shapes.push_back(new AbcMeshWriter(m_eval_ctx, m_scene, ob, xform, m_shape_sampling_index, m_settings));
break;
}
case OB_SURF:
@@ -593,7 +603,7 @@ void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
return;
}
- m_shapes.push_back(new AbcNurbsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings));
+ m_shapes.push_back(new AbcNurbsWriter(m_eval_ctx, m_scene, ob, xform, m_shape_sampling_index, m_settings));
break;
}
case OB_CURVE:
@@ -604,7 +614,7 @@ void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
return;
}
- m_shapes.push_back(new AbcCurveWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings));
+ m_shapes.push_back(new AbcCurveWriter(m_eval_ctx, m_scene, ob, xform, m_shape_sampling_index, m_settings));
break;
}
case OB_CAMERA:
@@ -612,7 +622,7 @@ void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
Camera *cam = static_cast<Camera *>(ob->data);
if (cam->type == CAM_PERSP) {
- m_shapes.push_back(new AbcCameraWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings));
+ m_shapes.push_back(new AbcCameraWriter(m_eval_ctx, m_scene, ob, xform, m_shape_sampling_index, m_settings));
}
break;
@@ -625,7 +635,7 @@ void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
}
m_shapes.push_back(new AbcMBallWriter(
- m_bmain, m_scene, ob, xform,
+ m_bmain, m_eval_ctx, m_scene, ob, xform,
m_shape_sampling_index, m_settings));
break;
}
@@ -647,5 +657,5 @@ void AbcExporter::setCurrentFrame(Main *bmain, double t)
{
m_scene->r.cfra = static_cast<int>(t);
m_scene->r.subframe = static_cast<float>(t) - m_scene->r.cfra;
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, m_scene, m_scene->lay);
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, m_depsgraph, bmain, m_scene, m_view_layer);
}
diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h
index 280682b2896..2a34ad2b25d 100644
--- a/source/blender/alembic/intern/abc_exporter.h
+++ b/source/blender/alembic/intern/abc_exporter.h
@@ -35,14 +35,19 @@ class AbcTransformWriter;
class ArchiveWriter;
struct EvaluationContext;
+struct Depsgraph;
struct Main;
struct Object;
struct Scene;
+struct ViewLayer;
+struct Base;
struct ExportSettings {
ExportSettings();
Scene *scene;
+ ViewLayer *view_layer; // Scene layer to export; all its objects will be exported, unless selected_only=true
+ Depsgraph *depsgraph;
SimpleLogger logger;
bool selected_only;
@@ -88,7 +93,10 @@ class AbcExporter {
unsigned int m_trans_sampling_index, m_shape_sampling_index;
+ EvaluationContext *m_eval_ctx;
Scene *m_scene;
+ ViewLayer *m_view_layer;
+ Depsgraph *m_depsgraph;
ArchiveWriter *m_writer;
@@ -99,7 +107,9 @@ class AbcExporter {
std::vector<AbcObjectWriter *> m_shapes;
public:
- AbcExporter(Main *bmain, Scene *scene, const char *filename, ExportSettings &settings);
+ AbcExporter(Main *bmain, EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ Depsgraph *depsgraph,
+ const char *filename, ExportSettings &settings);
~AbcExporter();
void operator()(Main *bmain, float &progress, bool &was_canceled);
@@ -114,11 +124,11 @@ private:
Alembic::Abc::TimeSamplingPtr createTimeSampling(double step);
void createTransformWritersHierarchy(EvaluationContext *eval_ctx);
- AbcTransformWriter * 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);
+ AbcTransformWriter * createTransformWriter(EvaluationContext *eval_ctx, Object *ob, Object *parent, 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);
void createParticleSystemsWriters(Object *ob, AbcTransformWriter *xform);
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 8f8ed2019d5..2579aa3cc36 100644
--- a/source/blender/alembic/intern/abc_hair.cc
+++ b/source/blender/alembic/intern/abc_hair.cc
@@ -49,13 +49,14 @@ using Alembic::AbcGeom::OV2fGeomParam;
/* ************************************************************************** */
-AbcHairWriter::AbcHairWriter(Scene *scene,
+AbcHairWriter::AbcHairWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
ExportSettings &settings,
ParticleSystem *psys)
- : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
+ : AbcObjectWriter(eval_ctx, scene, ob, time_sampling, settings, parent)
, m_uv_warning_shown(false)
{
m_psys = psys;
@@ -76,7 +77,7 @@ void AbcHairWriter::do_write()
return;
}
- DerivedMesh *dm = mesh_create_derived_render(m_scene, m_object, CD_MASK_MESH);
+ DerivedMesh *dm = mesh_create_derived_render(m_eval_ctx, m_scene, m_object, CD_MASK_MESH);
DM_ensure_tessface(dm);
std::vector<Imath::V3f> verts;
diff --git a/source/blender/alembic/intern/abc_hair.h b/source/blender/alembic/intern/abc_hair.h
index 61f5fe361f8..8190c449205 100644
--- a/source/blender/alembic/intern/abc_hair.h
+++ b/source/blender/alembic/intern/abc_hair.h
@@ -40,7 +40,8 @@ class AbcHairWriter : public AbcObjectWriter {
bool m_uv_warning_shown;
public:
- AbcHairWriter(Scene *scene,
+ AbcHairWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
diff --git a/source/blender/alembic/intern/abc_mball.cc b/source/blender/alembic/intern/abc_mball.cc
index 1ef7b757577..f1aa25c8f70 100644
--- a/source/blender/alembic/intern/abc_mball.cc
+++ b/source/blender/alembic/intern/abc_mball.cc
@@ -30,7 +30,6 @@ extern "C" {
#include "DNA_object_types.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_main.h"
#include "BKE_mball.h"
@@ -43,12 +42,13 @@ extern "C" {
AbcMBallWriter::AbcMBallWriter(
Main *bmain,
+ EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
ExportSettings &settings)
- : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
+ : AbcObjectWriter(eval_ctx, scene, ob, time_sampling, settings, parent)
, m_bmain(bmain)
{
m_is_animated = isAnimated();
@@ -58,7 +58,7 @@ AbcMBallWriter::AbcMBallWriter(
sizeof(CurveCache),
"CurveCache for AbcMBallWriter");
- m_mesh_writer = new AbcMeshWriter(scene, m_mesh_ob, parent,
+ m_mesh_writer = new AbcMeshWriter(eval_ctx, scene, m_mesh_ob, parent,
time_sampling, settings);
m_mesh_writer->setIsAnimated(m_is_animated);
}
diff --git a/source/blender/alembic/intern/abc_mball.h b/source/blender/alembic/intern/abc_mball.h
index 9b943698416..e657711059e 100644
--- a/source/blender/alembic/intern/abc_mball.h
+++ b/source/blender/alembic/intern/abc_mball.h
@@ -42,6 +42,7 @@ class AbcMBallWriter : public AbcObjectWriter {
public:
AbcMBallWriter(
Main *bmain,
+ EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
AbcTransformWriter *parent,
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index ffaa516d81a..fa2bbb8dfc3 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -38,7 +38,6 @@ extern "C" {
#include "BLI_string.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -287,12 +286,13 @@ static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob)
/* ************************************************************************** */
-AbcMeshWriter::AbcMeshWriter(Scene *scene,
+AbcMeshWriter::AbcMeshWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
ExportSettings &settings)
- : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
+ : AbcObjectWriter(eval_ctx, scene, ob, time_sampling, settings, parent)
{
m_is_animated = isAnimated();
m_subsurf_mod = NULL;
@@ -525,7 +525,7 @@ DerivedMesh *AbcMeshWriter::getFinalMesh()
m_subsurf_mod->mode |= eModifierMode_DisableTemporary;
}
- DerivedMesh *dm = mesh_create_derived_render(m_scene, m_object, CD_MASK_MESH);
+ DerivedMesh *dm = mesh_create_derived_render(m_eval_ctx, m_scene, m_object, CD_MASK_MESH);
if (m_subsurf_mod) {
m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
@@ -923,12 +923,6 @@ static void *add_customdata_cb(void *user_data, const char *name, int data_type)
numloops = dm->getNumLoops(dm);
cd_ptr = CustomData_add_layer_named(loopdata, cd_data_type, CD_DEFAULT,
NULL, numloops, name);
- if (cd_data_type == CD_MLOOPUV) {
- CustomData_add_layer_named(dm->getPolyDataLayout(dm),
- CD_MTEXPOLY, CD_DEFAULT,
- NULL, numloops, name);
- }
-
return cd_ptr;
}
diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h
index 77c352d7cd3..a08b7352d16 100644
--- a/source/blender/alembic/intern/abc_mesh.h
+++ b/source/blender/alembic/intern/abc_mesh.h
@@ -50,7 +50,8 @@ class AbcMeshWriter : public AbcObjectWriter {
bool m_is_subd;
public:
- AbcMeshWriter(Scene *scene,
+ AbcMeshWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
diff --git a/source/blender/alembic/intern/abc_nurbs.cc b/source/blender/alembic/intern/abc_nurbs.cc
index eaef06fd6d1..0532191a28d 100644
--- a/source/blender/alembic/intern/abc_nurbs.cc
+++ b/source/blender/alembic/intern/abc_nurbs.cc
@@ -60,12 +60,13 @@ using Alembic::AbcGeom::ONuPatchSchema;
/* ************************************************************************** */
-AbcNurbsWriter::AbcNurbsWriter(Scene *scene,
+AbcNurbsWriter::AbcNurbsWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
ExportSettings &settings)
- : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
+ : AbcObjectWriter(eval_ctx, scene, ob, time_sampling, settings, parent)
{
m_is_animated = isAnimated();
diff --git a/source/blender/alembic/intern/abc_nurbs.h b/source/blender/alembic/intern/abc_nurbs.h
index abe460a8988..3d20c5c60bb 100644
--- a/source/blender/alembic/intern/abc_nurbs.h
+++ b/source/blender/alembic/intern/abc_nurbs.h
@@ -32,7 +32,8 @@ class AbcNurbsWriter : public AbcObjectWriter {
bool m_is_animated;
public:
- AbcNurbsWriter(Scene *scene,
+ AbcNurbsWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index 6c4cb60d63c..98ebcf6debb 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -32,7 +32,6 @@ extern "C" {
#include "DNA_space_types.h" /* for FILE_MAX */
#include "BKE_constraint.h"
-#include "BKE_depsgraph.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
@@ -59,13 +58,15 @@ using Alembic::AbcGeom::OStringProperty;
/* ************************************************************************** */
-AbcObjectWriter::AbcObjectWriter(Scene *scene,
+AbcObjectWriter::AbcObjectWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
uint32_t time_sampling,
ExportSettings &settings,
AbcObjectWriter *parent)
: m_object(ob)
, m_settings(settings)
+ , m_eval_ctx(eval_ctx)
, m_scene(scene)
, m_time_sampling(time_sampling)
, m_first_frame(true)
diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h
index 852ef451f23..6aa6224f8d5 100644
--- a/source/blender/alembic/intern/abc_object.h
+++ b/source/blender/alembic/intern/abc_object.h
@@ -44,6 +44,7 @@ protected:
Object *m_object;
ExportSettings &m_settings;
+ EvaluationContext *m_eval_ctx;
Scene *m_scene;
uint32_t m_time_sampling;
@@ -56,7 +57,8 @@ protected:
std::string m_name;
public:
- AbcObjectWriter(Scene *scene,
+ AbcObjectWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
uint32_t time_sampling,
ExportSettings &settings,
diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc
index 80567cd6bf0..feb2eff5b9d 100644
--- a/source/blender/alembic/intern/abc_points.cc
+++ b/source/blender/alembic/intern/abc_points.cc
@@ -58,13 +58,14 @@ using Alembic::AbcGeom::OPointsSchema;
/* ************************************************************************** */
-AbcPointsWriter::AbcPointsWriter(Scene *scene,
+AbcPointsWriter::AbcPointsWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
ExportSettings &settings,
ParticleSystem *psys)
- : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
+ : AbcObjectWriter(eval_ctx, scene, ob, time_sampling, settings, parent)
{
m_psys = psys;
@@ -86,6 +87,7 @@ void AbcPointsWriter::do_write()
ParticleKey state;
ParticleSimulationData sim;
+ sim.eval_ctx = m_eval_ctx;
sim.scene = m_scene;
sim.ob = m_object;
sim.psys = m_psys;
diff --git a/source/blender/alembic/intern/abc_points.h b/source/blender/alembic/intern/abc_points.h
index 369a802d763..b60f1997aa8 100644
--- a/source/blender/alembic/intern/abc_points.h
+++ b/source/blender/alembic/intern/abc_points.h
@@ -38,7 +38,8 @@ class AbcPointsWriter : public AbcObjectWriter {
ParticleSystem *m_psys;
public:
- AbcPointsWriter(Scene *scene,
+ AbcPointsWriter(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
AbcTransformWriter *parent,
uint32_t time_sampling,
diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc
index 5392387663f..0a1480e62b0 100644
--- a/source/blender/alembic/intern/abc_transform.cc
+++ b/source/blender/alembic/intern/abc_transform.cc
@@ -57,12 +57,13 @@ static bool has_parent_camera(Object *ob)
/* ************************************************************************** */
-AbcTransformWriter::AbcTransformWriter(Object *ob,
+AbcTransformWriter::AbcTransformWriter(EvaluationContext *eval_ctx,
+ Object *ob,
const OObject &abc_parent,
AbcTransformWriter *parent,
unsigned int time_sampling,
ExportSettings &settings)
- : AbcObjectWriter(NULL, ob, time_sampling, settings, parent)
+ : AbcObjectWriter(eval_ctx, NULL, ob, time_sampling, settings, parent)
, m_proxy_from(NULL)
{
m_is_animated = hasAnimation(m_object);
diff --git a/source/blender/alembic/intern/abc_transform.h b/source/blender/alembic/intern/abc_transform.h
index 753a4247e9f..e82765cb169 100644
--- a/source/blender/alembic/intern/abc_transform.h
+++ b/source/blender/alembic/intern/abc_transform.h
@@ -44,7 +44,8 @@ public:
Object *m_proxy_from;
public:
- AbcTransformWriter(Object *ob,
+ AbcTransformWriter(EvaluationContext *eval_ctx,
+ Object *ob,
const Alembic::AbcGeom::OObject &abc_parent,
AbcTransformWriter *parent,
unsigned int time_sampling,
diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc
index 24a508e8292..8bdc7ae3455 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"
@@ -60,6 +61,15 @@ std::string get_id_name(const ID * const 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(const Object * const ob, Object *dupli_parent)
{
std::string name = get_id_name(ob);
@@ -78,31 +88,9 @@ std::string get_object_dag_path_name(const Object * const ob, Object *dupli_pare
return name;
}
-bool object_selected(Object *ob)
-{
- return ob->flag & SELECT;
-}
-
-bool parent_selected(Object *ob)
+bool object_selected(const Base * const ob_base)
{
- 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])
diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h
index 2526958111a..fcc3b19c48b 100644
--- a/source/blender/alembic/intern/abc_util.h
+++ b/source/blender/alembic/intern/abc_util.h
@@ -48,13 +48,13 @@ struct ImportSettings;
struct ID;
struct Object;
+struct Base;
std::string get_id_name(const ID * const id);
std::string get_id_name(const Object * const ob);
std::string get_object_dag_path_name(const Object * const 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]);
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index 0d2316ce7d9..5e93779b5f6 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -48,12 +48,15 @@ extern "C" {
#include "BKE_cdderivedmesh.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
/* SpaceType struct has a member called 'new' which obviously conflicts with C++
* so temporarily redefining the new keyword to make it compile. */
#define new extern_new
@@ -227,7 +230,10 @@ static void find_iobject(const IObject &object, IObject &ret,
}
struct ExportJobData {
+ EvaluationContext eval_ctx;
Scene *scene;
+ ViewLayer *view_layer;
+ Depsgraph *depsgraph;
Main *bmain;
char filename[1024];
@@ -259,7 +265,8 @@ static void export_startjob(void *customdata, short *stop, short *do_update, flo
try {
Scene *scene = data->scene;
- AbcExporter exporter(data->bmain, scene, data->filename, data->settings);
+ ViewLayer *view_layer = data->view_layer;
+ AbcExporter exporter(data->bmain, &data->eval_ctx, scene, view_layer, data->depsgraph, data->filename, data->settings);
const int orig_frame = CFRA;
@@ -269,8 +276,7 @@ static void export_startjob(void *customdata, short *stop, short *do_update, flo
if (CFRA != orig_frame) {
CFRA = orig_frame;
- BKE_scene_update_for_newframe(data->bmain->eval_ctx, data->bmain,
- scene, scene->lay);
+ BKE_scene_graph_update_for_newframe(data->bmain->eval_ctx, data->depsgraph, data->bmain, scene, data->view_layer);
}
data->export_ok = !data->was_canceled;
@@ -308,7 +314,12 @@ bool ABC_export(
bool as_background_job)
{
ExportJobData *job = static_cast<ExportJobData *>(MEM_mallocN(sizeof(ExportJobData), "ExportJobData"));
+
+ CTX_data_eval_ctx(C, &job->eval_ctx);
+
job->scene = scene;
+ job->view_layer = CTX_data_view_layer(C);
+ job->depsgraph = CTX_data_depsgraph(C);
job->bmain = CTX_data_main(C);
job->export_ok = false;
BLI_strncpy(job->filename, filepath, 1024);
@@ -330,13 +341,25 @@ bool ABC_export(
* hardcore refactoring. */
new (&job->settings) ExportSettings();
job->settings.scene = job->scene;
+ job->settings.depsgraph = job->depsgraph;
+
+ /* 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.view_layer = CTX_data_view_layer(C);
+
job->settings.frame_start = params->frame_start;
job->settings.frame_end = params->frame_end;
job->settings.frame_samples_xform = params->frame_samples_xform;
job->settings.frame_samples_shape = params->frame_samples_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;
@@ -345,8 +368,13 @@ bool ABC_export(
job->settings.export_particles = params->export_particles;
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;
@@ -606,6 +634,7 @@ enum {
struct ImportJobData {
Main *bmain;
Scene *scene;
+ ViewLayer *view_layer;
char filename[1024];
ImportSettings settings;
@@ -807,20 +836,32 @@ static void import_endjob(void *user_data)
else {
/* Add object to scene. */
Base *base;
+ LayerCollection *lc;
+ ViewLayer *view_layer = data->view_layer;
- BKE_scene_base_deselect_all(data->scene);
+ BKE_view_layer_base_deselect_all(view_layer);
+
+ lc = BKE_layer_collection_get_active(view_layer);
+ if (lc == NULL) {
+ BLI_assert(BLI_listbase_count_ex(&view_layer->layer_collections, 1) == 0);
+ /* when there is no collection linked to this ViewLayer, create one */
+ SceneCollection *sc = BKE_collection_add(&data->scene->id, NULL, COLLECTION_TYPE_NONE, NULL);
+ lc = BKE_collection_link(view_layer, sc);
+ }
for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
Object *ob = (*iter)->object();
ob->lay = data->scene->lay;
- base = BKE_scene_base_add(data->scene, ob);
- BKE_scene_base_select(data->scene, base);
+ BKE_collection_object_add(&data->scene->id, lc->scene_collection, ob);
+
+ base = BKE_view_layer_base_find(view_layer, ob);
+ BKE_view_layer_base_select(view_layer, base);
- DAG_id_tag_update_ex(data->bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update_ex(data->bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
- DAG_relations_tag_update(data->bmain);
+ DEG_relations_tag_update(data->bmain);
}
for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
@@ -863,6 +904,7 @@ bool ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence
ImportJobData *job = new ImportJobData();
job->bmain = CTX_data_main(C);
job->scene = CTX_data_scene(C);
+ job->view_layer = CTX_data_view_layer(C);
job->import_ok = false;
BLI_strncpy(job->filename, filepath, 1024);
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 8c8aef3de57..22559edad22 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -34,6 +34,9 @@
#include "BLI_compiler_attrs.h"
+/* enable this only if needed (unused circa 2016) */
+#define BLF_BLUR_ENABLE 0
+
struct rctf;
struct ColorManagedDisplay;
struct ResultBLF;
@@ -42,6 +45,7 @@ int BLF_init(void);
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);
@@ -61,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.
@@ -122,29 +137,16 @@ 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
void BLF_blur(int fontid, int size);
+#endif
void BLF_enable(int fontid, int option);
void BLF_disable(int fontid, int option);
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 5bd62980b6d..24347d57917 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -50,13 +50,14 @@
#include "BLI_math.h"
#include "BLI_threads.h"
-#include "BIF_gl.h"
#include "BLF_api.h"
#include "IMB_colormanagement.h"
#ifndef BLF_STANDALONE
-#include "GPU_basic_shader.h"
+#include "GPU_shader.h"
+#include "GPU_matrix.h"
+#include "GPU_immediate.h"
#endif
#include "blf_internal_types.h"
@@ -175,6 +176,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;
@@ -358,24 +365,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);
@@ -454,6 +443,7 @@ void BLF_size(int fontid, int size, int dpi)
}
}
+#if BLF_BLUR_ENABLE
void BLF_blur(int fontid, int size)
{
FontBLF *font = blf_get(fontid);
@@ -462,6 +452,77 @@ void BLF_blur(int fontid, int size)
font->blur = 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)
{
@@ -482,16 +543,7 @@ 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, GLint *mode)
+static void blf_draw_gl__start(FontBLF *font)
{
/*
* The pixmap alignment hack is handle
@@ -501,52 +553,46 @@ static void blf_draw_gl__start(FontBLF *font, GLint *mode)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-#ifndef BLF_STANDALONE
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
-#endif
+ gpuPushMatrix();
- /* Save the current matrix mode. */
- glGetIntegerv(GL_MATRIX_MODE, mode);
+ if (font->flags & BLF_MATRIX)
+ gpuMultMatrix(font->m);
- glMatrixMode(GL_TEXTURE);
- glPushMatrix();
- glLoadIdentity();
+ gpuTranslate3fv(font->pos);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ if (font->flags & BLF_ASPECT)
+ gpuScale3fv(font->aspect);
- if (font->flags & BLF_MATRIX)
- glMultMatrixf(font->m);
+ if (font->flags & BLF_ROTATION)
+ gpuRotate2D(RAD2DEG(font->angle));
- glTranslate3fv(font->pos);
+#ifndef BLF_STANDALONE
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
- if (font->flags & BLF_ASPECT)
- glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
+ BLI_assert(pos == BLF_POS_ID);
+ BLI_assert(texCoord == BLF_COORD_ID);
+ BLI_assert(color == BLF_COLOR_ID);
- if (font->flags & BLF_ROTATION) /* radians -> degrees */
- glRotatef(font->angle * (float)(180.0 / M_PI), 0.0f, 0.0f, 1.0f);
+ UNUSED_VARS_NDEBUG(pos, texCoord, color);
- if (font->shadow || font->blur)
- glGetFloatv(GL_CURRENT_COLOR, font->orig_col);
+ immBindBuiltinProgram(GPU_SHADER_TEXT);
+#endif
/* always bind the texture for the first glyph */
font->tex_bind_state = -1;
}
-static void blf_draw_gl__end(GLint mode)
+static void blf_draw_gl__end(void)
{
- glMatrixMode(GL_TEXTURE);
- glPopMatrix();
-
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- if (mode != GL_MODELVIEW)
- glMatrixMode(mode);
+ gpuPopMatrix();
#ifndef BLF_STANDALONE
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immUnbindProgram();
#endif
+
glDisable(GL_BLEND);
}
@@ -555,23 +601,26 @@ void BLF_draw_ex(
struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
- GLint mode;
BLF_RESULT_CHECK_INIT(r_info);
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode);
+ blf_draw_gl__start(font);
if (font->flags & BLF_WORD_WRAP) {
blf_font_draw__wrap(font, str, len, r_info);
}
else {
blf_font_draw(font, str, len, r_info);
}
- blf_draw_gl__end(mode);
+ blf_draw_gl__end();
}
}
void BLF_draw(int fontid, const char *str, size_t len)
{
+ if (len == 0 || str[0] == '\0') {
+ return;
+ }
+
BLF_draw_ex(fontid, str, len, NULL);
}
@@ -580,12 +629,11 @@ void BLF_draw_ascii_ex(
struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
- GLint mode;
BLF_RESULT_CHECK_INIT(r_info);
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode);
+ blf_draw_gl__start(font);
if (font->flags & BLF_WORD_WRAP) {
/* use non-ascii draw function for word-wrap */
blf_font_draw__wrap(font, str, len, r_info);
@@ -593,24 +641,31 @@ void BLF_draw_ascii_ex(
else {
blf_font_draw_ascii(font, str, len, r_info);
}
- blf_draw_gl__end(mode);
+ blf_draw_gl__end();
}
}
void BLF_draw_ascii(int fontid, const char *str, size_t len)
{
+ if (len == 0 || str[0] == '\0') {
+ return;
+ }
+
BLF_draw_ascii_ex(fontid, str, len, NULL);
}
int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
{
+ if (len == 0 || str[0] == '\0') {
+ return 0;
+ }
+
FontBLF *font = blf_get(fontid);
- GLint mode;
int columns = 0;
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode);
+ blf_draw_gl__start(font);
columns = blf_font_draw_mono(font, str, len, cwidth);
- blf_draw_gl__end(mode);
+ blf_draw_gl__end();
}
return columns;
@@ -690,14 +745,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)
@@ -728,14 +775,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)
@@ -799,15 +838,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);
@@ -829,18 +859,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);
@@ -856,7 +874,7 @@ void BLF_shadow(int fontid, int level, const float rgba[4])
if (font) {
font->shadow = level;
- copy_v4_v4(font->shadow_col, rgba);
+ rgba_float_to_uchar(font->shadow_color, rgba);
}
}
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 44a1d08f1fd..5846f7a29e4 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -58,6 +58,8 @@
#include "BIF_gl.h"
#include "BLF_api.h"
+#include "GPU_immediate.h"
+
#include "blf_internal_types.h"
#include "blf_internal.h"
@@ -172,6 +174,23 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
} \
} (void)0
+static unsigned int verts_needed(const FontBLF *font, const char *str, size_t len)
+{
+ unsigned int length = (unsigned int)((len == INT_MAX) ? strlen(str) : len);
+ unsigned int quad_ct = 1;
+
+ if (font->flags & BLF_SHADOW) {
+ if (font->shadow == 0)
+ quad_ct += 1;
+ if (font->shadow <= 4)
+ quad_ct += 9; /* 3x3 kernel */
+ else
+ quad_ct += 25; /* 5x5 kernel */
+ }
+
+ return length * quad_ct * 6;
+}
+
static void blf_font_draw_ex(
FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
int pen_y)
@@ -183,10 +202,18 @@ static void blf_font_draw_ex(
size_t i = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
+ if (len == 0) {
+ /* early output, don't do any IMM OpenGL. */
+ return;
+ }
+
BLF_KERNING_VARS(font, has_kerning, kern_mode);
blf_font_ensure_ascii_table(font);
+ immBeginAtMost(GWN_PRIM_TRIS, verts_needed(font, str, len));
+ /* at most because some glyphs might be clipped & not drawn */
+
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -204,6 +231,8 @@ static void blf_font_draw_ex(
g_prev = g;
}
+ immEnd();
+
if (r_info) {
r_info->lines = 1;
r_info->width = pen_x;
@@ -229,6 +258,8 @@ static void blf_font_draw_ascii_ex(
blf_font_ensure_ascii_table(font);
+ immBeginAtMost(GWN_PRIM_TRIS, verts_needed(font, str, len));
+
while ((c = *(str++)) && len--) {
BLI_assert(c < 128);
if ((g = glyph_ascii_table[c]) == NULL)
@@ -243,6 +274,8 @@ static void blf_font_draw_ascii_ex(
g_prev = g;
}
+ immEnd();
+
if (r_info) {
r_info->lines = 1;
r_info->width = pen_x;
@@ -265,6 +298,8 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
blf_font_ensure_ascii_table(font);
+ immBeginAtMost(GWN_PRIM_TRIS, verts_needed(font, str, len));
+
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -284,6 +319,8 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
pen_x += cwidth * col;
}
+ immEnd();
+
return columns;
}
@@ -901,8 +938,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;
@@ -910,9 +945,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;
@@ -922,7 +963,9 @@ static void blf_font_fill(FontBLF *font)
font->size = 0;
BLI_listbase_clear(&font->cache);
font->glyph_cache = NULL;
+#if BLF_BLUR_ENABLE
font->blur = 0;
+#endif
font->max_tex_size = -1;
font->buf_info.fbuf = NULL;
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index bbbabfb8ba2..a7d52e96800 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -56,7 +56,7 @@
#include "BLF_api.h"
#ifndef BLF_STANDALONE
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#endif
#include "blf_internal_types.h"
@@ -183,18 +183,7 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
-#ifndef BLF_STANDALONE
- /* needed since basic shader doesn't support alpha-only textures,
- * while we could add support this is only used in a few places
- * (an alternative could be to have a simple shader for BLF). */
- if (GLEW_ARB_texture_swizzle && GPU_basic_shader_use_glsl_get()) {
- GLint swizzle_mask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask);
- }
-#endif
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, gc->p2_width, gc->p2_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, gc->p2_width, gc->p2_height, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
}
GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
@@ -327,73 +316,83 @@ void blf_glyph_free(GlyphBLF *g)
MEM_freeN(g);
}
-static void blf_texture_draw(float uv[2][2], float dx, float y1, float dx1, float y2)
+static void blf_texture_draw(const unsigned char color[4], float uv[2][2], float dx, float y1, float dx1, float y2)
{
- glBegin(GL_QUADS);
- glTexCoord2f(uv[0][0], uv[0][1]);
- glVertex2f(dx, y1);
-
- glTexCoord2f(uv[0][0], uv[1][1]);
- glVertex2f(dx, y2);
-
- glTexCoord2f(uv[1][0], uv[1][1]);
- glVertex2f(dx1, y2);
-
- glTexCoord2f(uv[1][0], uv[0][1]);
- glVertex2f(dx1, y1);
- glEnd();
+ /* First triangle. */
+ immAttrib2f(BLF_COORD_ID, uv[0][0], uv[0][1]);
+ immSkipAttrib(BLF_COLOR_ID); /* skip color of most vertices */
+ immVertex2f(BLF_POS_ID, dx, y1);
+
+ immAttrib2f(BLF_COORD_ID, uv[0][0], uv[1][1]);
+ immSkipAttrib(BLF_COLOR_ID);
+ immVertex2f(BLF_POS_ID, dx, y2);
+
+ immAttrib2f(BLF_COORD_ID, uv[1][0], uv[1][1]);
+ immAttrib4ubv(BLF_COLOR_ID, color); /* set color of provoking vertex */
+ immVertex2f(BLF_POS_ID, dx1, y2);
+
+ /* Second triangle. */
+ immAttrib2f(BLF_COORD_ID, uv[0][0], uv[0][1]);
+ immSkipAttrib(BLF_COLOR_ID); /* skip color of most vertices */
+ immVertex2f(BLF_POS_ID, dx, y1);
+
+ immAttrib2f(BLF_COORD_ID, uv[1][0], uv[1][1]);
+ immSkipAttrib(BLF_COLOR_ID);
+ immVertex2f(BLF_POS_ID, dx1, y2);
+
+ immAttrib2f(BLF_COORD_ID, uv[1][0], uv[0][1]);
+ immAttrib4ubv(BLF_COLOR_ID, color); /* set color of provoking vertex */
+ immVertex2f(BLF_POS_ID, dx1, y1);
}
-static void blf_texture5_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture5_draw(const unsigned char color_in[4], float uv[2][2], float x1, float y1, float x2, float y2)
{
const float soft[25] = {1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f,
1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
2 / 60.0f, 5 / 60.0f, 8 / 60.0f, 5 / 60.0f, 2 / 60.0f,
1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f};
-
+
const float *fp = soft;
- float color[4];
+ unsigned char color[4];
float dx, dy;
- color[0] = shadow_col[0];
- color[1] = shadow_col[1];
- color[2] = shadow_col[2];
-
+ color[0] = color_in[0];
+ color[1] = color_in[1];
+ color[2] = color_in[2];
+
+ const float alpha_in = (1 / 255.0f) * color_in[3];
+
for (dx = -2; dx < 3; dx++) {
for (dy = -2; dy < 3; dy++, fp++) {
- color[3] = *(fp) * shadow_col[3];
- glColor4fv(color);
- blf_texture_draw(uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
+ color[3] = FTOCHAR(*fp * alpha_in);
+ blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
}
}
-
- glColor4fv(color);
}
-static void blf_texture3_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture3_draw(const unsigned char color_in[4], float uv[2][2], float x1, float y1, float x2, float y2)
{
const float soft[9] = {1 / 16.0f, 2 / 16.0f, 1 / 16.0f,
2 / 16.0f, 4 / 16.0f, 2 / 16.0f,
1 / 16.0f, 2 / 16.0f, 1 / 16.0f};
const float *fp = soft;
- float color[4];
+ unsigned char color[4];
float dx, dy;
- color[0] = shadow_col[0];
- color[1] = shadow_col[1];
- color[2] = shadow_col[2];
+ color[0] = color_in[0];
+ color[1] = color_in[1];
+ color[2] = color_in[2];
+
+ const float alpha_in = (1 / 255.0f) * color_in[3];
for (dx = -1; dx < 2; dx++) {
for (dy = -1; dy < 2; dy++, fp++) {
- color[3] = *(fp) * shadow_col[3];
- glColor4fv(color);
- blf_texture_draw(uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
+ color[3] = FTOCHAR(*fp * alpha_in);
+ blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
}
}
-
- glColor4fv(color);
}
static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
@@ -450,14 +449,21 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
}
- glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+ GLint lsb_first, row_length, alignment;
+ glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsb_first);
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
+
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, g->tex);
- glTexSubImage2D(GL_TEXTURE_2D, 0, g->xoff, g->yoff, g->width, g->height, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap);
- glPopClientAttrib();
+ glTexSubImage2D(GL_TEXTURE_2D, 0, g->xoff, g->yoff, g->width, g->height, GL_RED, GL_UNSIGNED_BYTE, g->bitmap);
+
+ glPixelStorei(GL_UNPACK_LSB_FIRST, lsb_first);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
g->uv[0][0] = ((float)g->xoff) / ((float)gc->p2_width);
g->uv[0][1] = ((float)g->yoff) / ((float)gc->p2_height);
@@ -487,39 +493,37 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = g->tex));
}
+ /* TODO: blur & shadow in shader, single quad per glyph */
+
if (font->flags & BLF_SHADOW) {
rctf rect_ofs;
blf_glyph_calc_rect(&rect_ofs, g,
x + (float)font->shadow_x,
y + (float)font->shadow_y);
- switch (font->shadow) {
- case 3:
- blf_texture3_draw(font->shadow_col, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
- break;
- case 5:
- blf_texture5_draw(font->shadow_col, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
- break;
- default:
- glColor4fv(font->shadow_col);
- blf_texture_draw(g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
- break;
+ if (font->shadow == 0) {
+ blf_texture_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+ }
+ else if (font->shadow <= 4) {
+ blf_texture3_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+ }
+ else {
+ blf_texture5_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
}
-
- glColor4fv(font->orig_col);
}
+#if BLF_BLUR_ENABLE
switch (font->blur) {
case 3:
- blf_texture3_draw(font->orig_col, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture3_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
break;
case 5:
- blf_texture5_draw(font->orig_col, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture5_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
break;
default:
- blf_texture_draw(g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- break;
+ blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
}
-
- return;
+#else
+ blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+#endif
}
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index d9d758ce548..ba17e050399 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -37,6 +37,11 @@ struct GlyphBLF;
struct GlyphCacheBLF;
struct rctf;
+/* vertex attribute IDs (fixed IDs so we don't have to pass them around) */
+#define BLF_POS_ID 0
+#define BLF_COORD_ID 1
+#define BLF_COLOR_ID 2
+
unsigned int blf_next_p2(unsigned int x);
unsigned int blf_hash(unsigned int val);
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 0fac576a8cc..9164a02b2cc 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -175,8 +175,10 @@ typedef struct FontBLF {
/* angle in radians. */
float angle;
+#if 0 /* BLF_BLUR_ENABLE */
/* blur: 3 or 5 large kernel */
int blur;
+#endif
/* shadow level. */
int shadow;
@@ -186,10 +188,10 @@ typedef struct FontBLF {
int shadow_y;
/* shadow color. */
- float shadow_col[4];
+ unsigned char shadow_color[4];
- /* store color here when drawing shadow or blur. */
- float orig_col[4];
+ /* main text color. */
+ unsigned char color[4];
/* Multiplied this matrix with the current one before
* draw the text! see blf_draw__start.
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 700bfe568f1..9bb44a726de 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -98,6 +98,7 @@ struct ColorBand;
struct GPUVertexAttribs;
struct GPUDrawObject;
struct PBVH;
+struct EvaluationContext;
/* number of sub-elements each mesh element has (for interpolation) */
#define SUB_ELEMS_VERT 0
@@ -142,8 +143,6 @@ typedef int (*DMSetMaterial)(int mat_nr, void *attribs);
typedef int (*DMCompareDrawOptions)(void *userData, int cur_index, int next_index);
typedef void (*DMSetDrawInterpOptions)(void *userData, int index, float t);
typedef DMDrawOption (*DMSetDrawOptions)(void *userData, int index);
-typedef DMDrawOption (*DMSetDrawOptionsMappedTex)(void *userData, int origindex, int mat_nr);
-typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTexPoly *mtexpoly, const bool has_vcol, int matnr);
typedef enum DMDrawFlag {
DM_DRAW_USE_COLORS = (1 << 0),
@@ -389,9 +388,6 @@ struct DerivedMesh {
/** Draw all vertices as bgl points (no options) */
void (*drawVerts)(DerivedMesh *dm);
- /** Draw edges in the UV mesh (if exists) */
- void (*drawUVEdges)(DerivedMesh *dm);
-
/** Draw all edges as lines (no options)
*
* Also called for *final* editmode DerivedMeshes
@@ -411,14 +407,6 @@ struct DerivedMesh {
void (*drawFacesSolid)(DerivedMesh *dm, float (*partial_redraw_planes)[4],
bool fast, DMSetMaterial setMaterial);
- /** Draw all faces using MTFace
- * - Drawing options too complicated to enumerate, look at code.
- */
- void (*drawFacesTex)(DerivedMesh *dm,
- DMSetDrawOptionsTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag);
-
/** Draw all faces with GLSL materials
* o setMaterial is called for every different material nr
* o Only if setMaterial returns true
@@ -445,14 +433,6 @@ struct DerivedMesh {
void *userData,
DMDrawFlag flag);
- /** Draw mapped faces using MTFace
- * - Drawing options too complicated to enumerate, look at code.
- */
- void (*drawMappedFacesTex)(DerivedMesh *dm,
- DMSetDrawOptionsMappedTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag);
-
/** Draw mapped faces with GLSL materials
* - setMaterial is called for every different material nr
* - setDrawOptions is called for every face
@@ -680,56 +660,56 @@ void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int
/* */
DerivedMesh *mesh_get_derived_final(
- struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, CustomDataMask dataMask);
DerivedMesh *mesh_get_derived_deform(
- struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, CustomDataMask dataMask);
DerivedMesh *mesh_create_derived_for_modifier(
- struct Scene *scene, struct Object *ob,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
struct ModifierData *md, int build_shapekey_layers);
DerivedMesh *mesh_create_derived_render(
- struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, CustomDataMask dataMask);
DerivedMesh *getEditDerivedBMesh(
struct BMEditMesh *em, struct Object *ob, CustomDataMask data_mask,
float (*vertexCos)[3]);
DerivedMesh *mesh_create_derived_index_render(
- struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask, int index);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, CustomDataMask dataMask, int index);
/* same as above but wont use render settings */
DerivedMesh *mesh_create_derived(struct Mesh *me, float (*vertCos)[3]);
DerivedMesh *mesh_create_derived_view(
- struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, CustomDataMask dataMask);
DerivedMesh *mesh_create_derived_no_deform(
- struct Scene *scene, struct Object *ob,
- float (*vertCos)[3],
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, float (*vertCos)[3],
CustomDataMask dataMask);
DerivedMesh *mesh_create_derived_no_deform_render(
- struct Scene *scene, struct Object *ob,
- float (*vertCos)[3],
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, float (*vertCos)[3],
CustomDataMask dataMask);
/* for gameengine */
DerivedMesh *mesh_create_derived_no_virtual(
- struct Scene *scene, struct Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
+ float (*vertCos)[3], CustomDataMask dataMask);
DerivedMesh *mesh_create_derived_physics(
- struct Scene *scene, struct Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
+ float (*vertCos)[3], CustomDataMask dataMask);
DerivedMesh *editbmesh_get_derived_base(
struct Object *ob, struct BMEditMesh *em, CustomDataMask data_mask);
DerivedMesh *editbmesh_get_derived_cage(
- struct Scene *scene, struct Object *,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *,
struct BMEditMesh *em, CustomDataMask dataMask);
DerivedMesh *editbmesh_get_derived_cage_and_final(
- struct Scene *scene, struct Object *,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *,
struct BMEditMesh *em, CustomDataMask dataMask,
DerivedMesh **r_final);
@@ -738,7 +718,7 @@ DerivedMesh *object_get_derived_final(struct Object *ob, const bool for_render);
float (*editbmesh_get_vertex_cos(struct BMEditMesh *em, int *r_numVerts))[3];
bool editbmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm);
void makeDerivedMesh(
- struct Scene *scene, struct Object *ob, struct BMEditMesh *em,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct BMEditMesh *em,
CustomDataMask dataMask, const bool build_shapekey_layers);
void weight_to_rgb(float r_rgb[3], const float weight);
@@ -789,19 +769,15 @@ void DM_draw_attrib_vertex_uniforms(const DMVertexAttribs *attribs);
void DM_calc_tangents_names_from_gpu(
const struct GPUVertexAttribs *gattribs,
char (*tangent_names)[MAX_NAME], int *tangent_names_count);
+
void DM_add_named_tangent_layer_for_uv(
CustomData *uv_data, CustomData *tan_data, int numLoopData,
const char *layer_name);
-#define DM_TANGENT_MASK_ORCO (1 << 9)
-void DM_calc_loop_tangents_step_0(
- const CustomData *loopData, bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME], int tangent_names_count,
- bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
- char *ract_uv_name, char *rren_uv_name, short *rtangent_mask);
void DM_calc_loop_tangents(
DerivedMesh *dm, bool calc_active_tangent, const char (*tangent_names)[MAX_NAME],
int tangent_names_count);
+
void DM_calc_auto_bump_scale(DerivedMesh *dm);
/** Set object's bounding box based on DerivedMesh min/max data */
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
index 584f0da323a..30a7bdb0a27 100644
--- a/source/blender/blenkernel/BKE_anim.h
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -41,6 +41,7 @@ struct bAnimVizSettings;
struct bMotionPath;
struct bPoseChannel;
struct ReportList;
+struct Main;
/* ---------------------------------------------------- */
/* Animation Visualization */
@@ -53,7 +54,7 @@ void animviz_free_motionpath(struct bMotionPath *mpath);
struct bMotionPath *animviz_verify_motionpaths(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan);
void animviz_get_object_motionpaths(struct Object *ob, ListBase *targets);
-void animviz_calc_motionpaths(struct Scene *scene, ListBase *targets);
+void animviz_calc_motionpaths(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *scene, ListBase *targets);
/* ---------------------------------------------------- */
/* Curve Paths */
@@ -65,8 +66,8 @@ int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], fl
/* ---------------------------------------------------- */
/* Dupli-Geometry */
-struct ListBase *object_duplilist_ex(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob, bool update);
-struct ListBase *object_duplilist(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob);
+struct ListBase *object_duplilist_ex(const struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob, bool update);
+struct ListBase *object_duplilist(const struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob);
void free_object_duplilist(struct ListBase *lb);
int count_duplilist(struct Object *ob);
@@ -80,7 +81,7 @@ typedef struct DupliApplyData {
DupliExtraData *extra;
} DupliApplyData;
-DupliApplyData *duplilist_apply(struct Object *ob, struct Scene *scene, struct ListBase *duplilist);
+DupliApplyData *duplilist_apply(const struct EvaluationContext *eval_ctx, struct Object *ob, struct Scene *scene, struct ListBase *duplilist);
void duplilist_restore(struct ListBase *duplilist, DupliApplyData *apply_data);
void duplilist_free_apply_data(DupliApplyData *apply_data);
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index a70690d4029..d95b4a838b8 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -47,6 +47,7 @@ struct ReportList;
struct bAction;
struct bActionGroup;
struct AnimMapper;
+struct FCurve;
/* ************************************* */
/* AnimData API */
@@ -148,7 +149,7 @@ char *BKE_animdata_driver_path_hack(struct bContext *C, struct PointerRNA *ptr,
char *base_path);
/* ************************************* */
-/* Batch AnimData API */
+/* Gwn_Batch AnimData API */
/* Define for callback looper used in BKE_animdata_main_cb */
typedef void (*ID_AnimData_Edit_Callback)(struct ID *id, struct AnimData *adt, void *user_data);
@@ -179,7 +180,6 @@ void BKE_animsys_evaluate_animdata(struct Scene *scene, struct ID *id, struct An
void BKE_animsys_evaluate_all_animation(struct Main *main, struct Scene *scene, float ctime);
/* TODO(sergey): This is mainly a temp public function. */
-struct FCurve;
bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct AnimMapper *remap, struct FCurve *fcu, float curval);
/* ------------ Specialized API --------------- */
@@ -202,8 +202,8 @@ void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act,
struct EvaluationContext;
-void BKE_animsys_eval_animdata(struct EvaluationContext *eval_ctx, struct ID *id);
-void BKE_animsys_eval_driver(struct EvaluationContext *eval_ctx, struct ID *id, struct FCurve *fcurve);
+void BKE_animsys_eval_animdata(const struct EvaluationContext *eval_ctx, struct ID *id);
+void BKE_animsys_eval_driver(const struct EvaluationContext *eval_ctx, struct ID *id, struct FCurve *fcurve);
/* ************************************* */
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h
index ac8f861fa56..ffbdc6972f4 100644
--- a/source/blender/blenkernel/BKE_appdir.h
+++ b/source/blender/blenkernel/BKE_appdir.h
@@ -82,6 +82,7 @@ enum {
#define BLENDER_STARTUP_FILE "startup.blend"
#define BLENDER_USERPREF_FILE "userpref.blend"
+#define BLENDER_WORKSPACES_FILE "workspaces.blend"
#define BLENDER_QUIT_FILE "quit.blend"
#define BLENDER_BOOKMARK_FILE "bookmarks.txt"
#define BLENDER_HISTORY_FILE "recent-files.txt"
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 60fb79d75d5..192690c074c 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -33,7 +33,9 @@
* \author nzc
*/
+struct bPose;
struct Bone;
+struct EvaluationContext;
struct GHash;
struct Main;
struct bArmature;
@@ -98,9 +100,8 @@ void BKE_armature_where_is(struct bArmature *arm);
void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion);
void BKE_pose_clear_pointers(struct bPose *pose);
void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm);
-void BKE_pose_rebuild_ex(struct Object *ob, struct bArmature *arm, const bool sort_bones);
-void BKE_pose_where_is(struct Scene *scene, struct Object *ob);
-void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);
+void BKE_pose_where_is(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void BKE_pose_where_is_bone(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);
void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);
/* get_objectspace_bone_matrix has to be removed still */
@@ -117,7 +118,7 @@ void BKE_armature_loc_pose_to_bone(struct bPoseChannel *pchan, const float inloc
void BKE_armature_mat_bone_to_pose(struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]);
void BKE_armature_mat_pose_to_delta(float delta_mat[4][4], float pose_mat[4][4], float arm_mat[4][4]);
-void BKE_armature_mat_pose_to_bone_ex(struct Object *ob, struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]);
+void BKE_armature_mat_pose_to_bone_ex(const struct EvaluationContext *eval_ctx, struct Object *ob, struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]);
void BKE_pchan_mat3_to_rot(struct bPoseChannel *pchan, float mat[3][3], bool use_compat);
void BKE_pchan_apply_mat4(struct bPoseChannel *pchan, float mat[4][4], bool use_comat);
@@ -155,7 +156,6 @@ void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array
struct bKinematicConstraint;
struct bPose;
struct bSplineIKConstraint;
-struct EvaluationContext;
struct bPoseChannel *BKE_armature_ik_solver_find_root(
struct bPoseChannel *pchan,
@@ -165,47 +165,49 @@ struct bPoseChannel *BKE_armature_splineik_solver_find_root(
struct bSplineIKConstraint *data);
void BKE_pose_splineik_init_tree(struct Scene *scene, struct Object *ob, float ctime);
-void BKE_splineik_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan_root, float ctime);
+void BKE_splineik_execute_tree(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, struct bPoseChannel *pchan_root, float ctime);
-void BKE_pose_eval_init(struct EvaluationContext *eval_ctx,
+void BKE_pose_eval_init(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPose *pose);
-void BKE_pose_eval_init_ik(struct EvaluationContext *eval_ctx,
+void BKE_pose_eval_init_ik(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPose *pose);
-void BKE_pose_eval_bone(struct EvaluationContext *eval_ctx,
+void BKE_pose_eval_bone(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPoseChannel *pchan);
-void BKE_pose_constraints_evaluate(struct EvaluationContext *eval_ctx,
+void BKE_pose_constraints_evaluate(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPoseChannel *pchan);
-void BKE_pose_bone_done(struct EvaluationContext *eval_ctx,
+void BKE_pose_bone_done(const struct EvaluationContext *eval_ctx,
struct bPoseChannel *pchan);
-void BKE_pose_iktree_evaluate(struct EvaluationContext *eval_ctx,
+void BKE_pose_iktree_evaluate(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPoseChannel *rootchan);
-void BKE_pose_splineik_evaluate(struct EvaluationContext *eval_ctx,
+void BKE_pose_splineik_evaluate(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPoseChannel *rootchan);
-void BKE_pose_eval_flush(struct EvaluationContext *eval_ctx,
+void BKE_pose_eval_flush(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPose *pose);
-void BKE_pose_eval_proxy_copy(struct EvaluationContext *eval_ctx,
+void BKE_pose_eval_proxy_copy(const struct EvaluationContext *eval_ctx,
struct Object *ob);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index f95b1963a91..8d326c6441c 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -27,8 +27,8 @@
/* these lines are grep'd, watch out for our not-so-awesome regex
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
-#define BLENDER_VERSION 279
-#define BLENDER_SUBVERSION 1
+#define BLENDER_VERSION 280
+#define BLENDER_SUBVERSION 2
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 6
diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h
index 9ff164f60be..a9a7e2045f0 100644
--- a/source/blender/blenkernel/BKE_blendfile.h
+++ b/source/blender/blenkernel/BKE_blendfile.h
@@ -61,6 +61,10 @@ struct UserDef *BKE_blendfile_userdef_read_from_memory(
bool BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports);
bool BKE_blendfile_userdef_write_app_template(const char *filepath, struct ReportList *reports);
+struct WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath, struct ReportList *reports);
+bool BKE_blendfile_workspace_config_write(struct Main *bmain, const char *filepath, struct ReportList *reports);
+void BKE_blendfile_workspace_config_data_free(struct WorkspaceConfigFileData *workspace_config);
+
/* partial blend file writing */
void BKE_blendfile_write_partial_tag_ID(struct ID *id, bool set);
void BKE_blendfile_write_partial_begin(struct Main *bmain_src);
diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h
index e9712681090..e0419d0e749 100644
--- a/source/blender/blenkernel/BKE_cachefile.h
+++ b/source/blender/blenkernel/BKE_cachefile.h
@@ -65,7 +65,7 @@ bool BKE_cachefile_filepath_get(
float BKE_cachefile_time_offset(struct CacheFile *cache_file, const float time, const float fps);
-void BKE_cachefile_clean(struct Scene *scene, struct CacheFile *cache_file);
+void BKE_cachefile_clean(struct Main *bmain, struct CacheFile *cache_file);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index 04dee70faa6..f69ac7e01cd 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -44,6 +44,7 @@ struct Object;
struct RegionView3D;
struct RenderData;
struct Scene;
+struct ViewLayer;
struct rctf;
struct View3D;
struct GPUFXSettings;
@@ -128,7 +129,7 @@ void BKE_camera_view_frame(
float r_vec[4][3]);
bool BKE_camera_view_frame_fit_to_scene(
- struct Scene *scene, struct View3D *v3d, struct Object *camera_ob,
+ struct Scene *scene, struct ViewLayer *view_layer, struct Object *camera_ob,
float r_co[3], float *r_scale);
bool BKE_camera_view_frame_fit_to_coords(
const struct Scene *scene,
@@ -147,6 +148,11 @@ float BKE_camera_multiview_shift_x(struct RenderData *rd, struct Object
void BKE_camera_multiview_params(struct RenderData *rd, struct CameraParams *params, struct Object *camera, const char *viewname);
bool BKE_camera_multiview_spherical_stereo(struct RenderData *rd, struct Object *camera);
+/* Camera background image API */
+struct CameraBGImage *BKE_camera_background_image_new(struct Camera *cam);
+void BKE_camera_background_image_remove(struct Camera *cam, struct CameraBGImage *bgpic);
+void BKE_camera_background_image_clear(struct Camera *cam);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 6c517bd02df..7f7cbd678e2 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -41,6 +41,7 @@ struct MFace;
struct DerivedMesh;
struct ClothModifierData;
struct CollisionModifierData;
+struct EvaluationContext;
#define DO_INLINE MALWAYS_INLINE
@@ -226,7 +227,7 @@ void cloth_free_contacts(ColliderContacts *collider_contacts, int totcolliders);
void cloth_free_modifier_extern (struct ClothModifierData *clmd );
void cloth_free_modifier (struct ClothModifierData *clmd );
void cloth_init (struct ClothModifierData *clmd );
-void clothModifier_do (struct ClothModifierData *clmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3]);
+void clothModifier_do(struct ClothModifierData *clmd, const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3]);
int cloth_uses_vgroup(struct ClothModifierData *clmd);
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
new file mode 100644
index 00000000000..48b4ff881ae
--- /dev/null
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -0,0 +1,107 @@
+/*
+ * ***** 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 Base;
+struct BLI_Iterator;
+struct Group;
+struct ID;
+struct LayerCollection;
+struct Main;
+struct Object;
+struct Scene;
+struct SceneCollection;
+
+struct SceneCollection *BKE_collection_add(
+ struct ID *owner_id, struct SceneCollection *sc_parent, const int type, const char *name);
+bool BKE_collection_remove(struct ID *owner_id, struct SceneCollection *sc);
+void BKE_collection_copy_data(struct SceneCollection *sc_dst, struct SceneCollection *sc_src, const int flag);
+struct SceneCollection *BKE_collection_master(const struct ID *owner_id);
+void BKE_collection_rename(const struct Scene *scene, struct SceneCollection *sc, const char *name);
+void BKE_collection_master_free(struct ID *owner_id, const bool do_id_user);
+bool BKE_collection_object_add(const struct ID *owner_id, struct SceneCollection *sc, struct Object *object);
+void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst);
+bool BKE_collection_object_remove(struct Main *bmain, struct ID *owner_id, struct SceneCollection *sc, struct Object *object, const bool free_us);
+bool BKE_collections_object_remove(struct Main *bmain, struct ID *owner_id, struct Object *object, const bool free_us);
+void BKE_collection_object_move(struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src, struct Object *ob);
+
+struct Group *BKE_collection_group_create(struct Main *bmain, struct Scene *scene, struct LayerCollection *lc);
+
+void BKE_collection_reinsert_after(const struct Scene *scene, struct SceneCollection *sc_reinsert, struct SceneCollection *sc_after);
+void BKE_collection_reinsert_into(struct SceneCollection *sc_reinsert, struct SceneCollection *sc_into);
+
+bool BKE_collection_move_above(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src);
+bool BKE_collection_move_below(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src);
+bool BKE_collection_move_into(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src);
+
+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 BLI_Iterator *iter, void *data_in);
+void BKE_scene_collections_iterator_next(struct BLI_Iterator *iter);
+void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter);
+
+void BKE_scene_objects_iterator_begin(struct BLI_Iterator *iter, void *data_in);
+void BKE_scene_objects_iterator_next(struct BLI_Iterator *iter);
+void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter);
+
+#define FOREACH_SCENE_COLLECTION(_id, _instance) \
+ ITER_BEGIN(BKE_scene_collections_iterator_begin, \
+ BKE_scene_collections_iterator_next, \
+ BKE_scene_collections_iterator_end, \
+ _id, SceneCollection *, _instance)
+
+#define FOREACH_SCENE_COLLECTION_END \
+ ITER_END
+
+#define FOREACH_SCENE_OBJECT(scene, _instance) \
+ ITER_BEGIN(BKE_scene_objects_iterator_begin, \
+ BKE_scene_objects_iterator_next, \
+ BKE_scene_objects_iterator_end, \
+ scene, Object *, _instance)
+
+#define FOREACH_SCENE_OBJECT_END \
+ ITER_END
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_COLLECTION_H__ */
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index 8fedcd4ab06..0bf7f657f70 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -148,7 +148,7 @@ void collision_get_collider_velocity(float vel_old[3], float vel_new[3], struct
/////////////////////////////////////////////////
/* explicit control over layer mask and dupli recursion */
-struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli);
+struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj, unsigned int modifier_type, bool dupli);
struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj, unsigned int modifier_type);
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 4e0eb5c65ac..cf7e2908360 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -40,6 +40,7 @@ struct ListBase;
struct Object;
struct Scene;
struct bPoseChannel;
+struct EvaluationContext;
/* ---------------------------------------------------------------------------- */
#ifdef __cplusplus
@@ -102,7 +103,7 @@ typedef struct bConstraintTypeInfo {
/* evaluation */
/* set the ct->matrix for the given constraint target (at the given ctime) */
- void (*get_target_matrix)(struct bConstraint *con, struct bConstraintOb *cob, struct bConstraintTarget *ct, float ctime);
+ void (*get_target_matrix)(const struct EvaluationContext *eval_ctx, struct bConstraint *con, struct bConstraintOb *cob, struct bConstraintTarget *ct, float ctime);
/* evaluate the constraint for the given time */
void (*evaluate_constraint)(struct bConstraint *con, struct bConstraintOb *cob, struct ListBase *targets);
} bConstraintTypeInfo;
@@ -147,9 +148,10 @@ void BKE_constraints_clear_evalob(struct bConstraintOb *cob);
void BKE_constraint_mat_convertspace(
struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to, const bool keep_scale);
-void BKE_constraint_target_matrix_get(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime);
-void BKE_constraint_targets_for_solving_get(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
-void BKE_constraints_solve(struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
+void BKE_constraint_target_matrix_get(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct bConstraint *con,
+ int n, short ownertype, void *ownerdata, float mat[4][4], float ctime);
+void BKE_constraint_targets_for_solving_get(const struct EvaluationContext *eval_ctx, struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
+void BKE_constraints_solve(const struct EvaluationContext *eval_ctx, struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 4da6a61cbfa..75e658613cb 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -40,15 +40,21 @@ extern "C" {
struct ARegion;
struct bScreen;
struct CacheFile;
+struct Depsgraph;
+struct LayerCollection;
struct ListBase;
struct Main;
struct Object;
+struct Base;
struct PointerRNA;
struct ReportList;
struct Scene;
+struct SceneCollection;
+struct ViewLayer;
struct ScrArea;
struct SpaceLink;
struct View3D;
+struct ViewRender;
struct RegionView3D;
struct StructRNA;
struct ToolSettings;
@@ -64,10 +70,12 @@ struct bGPDpalettecolor;
struct bGPDbrush;
struct wmWindow;
struct wmWindowManager;
+struct RenderEngineType;
struct SpaceText;
struct SpaceImage;
struct SpaceClip;
struct ID;
+struct EvaluationContext;
/* Structs */
@@ -140,12 +148,15 @@ void CTX_py_dict_set(bContext *C, void *value);
struct wmWindowManager *CTX_wm_manager(const bContext *C);
struct wmWindow *CTX_wm_window(const bContext *C);
+struct WorkSpace *CTX_wm_workspace(const bContext *C);
struct bScreen *CTX_wm_screen(const bContext *C);
struct ScrArea *CTX_wm_area(const bContext *C);
struct SpaceLink *CTX_wm_space_data(const bContext *C);
struct ARegion *CTX_wm_region(const bContext *C);
void *CTX_wm_region_data(const bContext *C);
struct ARegion *CTX_wm_menu(const bContext *C);
+struct wmManipulatorGroup *CTX_wm_manipulator_group(const bContext *C);
+struct wmMsgBus *CTX_wm_message_bus(const bContext *C);
struct ReportList *CTX_wm_reports(const bContext *C);
struct View3D *CTX_wm_view3d(const bContext *C);
@@ -173,6 +184,7 @@ void CTX_wm_screen_set(bContext *C, struct bScreen *screen); /* to be removed */
void CTX_wm_area_set(bContext *C, struct ScrArea *sa);
void CTX_wm_region_set(bContext *C, struct ARegion *region);
void CTX_wm_menu_set(bContext *C, struct ARegion *menu);
+void CTX_wm_manipulator_group_set(bContext *C, struct wmManipulatorGroup *mgroup);
const char *CTX_wm_operator_poll_msg_get(struct bContext *C);
void CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg);
@@ -239,9 +251,15 @@ 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 ViewLayer *CTX_data_view_layer(const bContext *C);
+struct ViewRender *CTX_data_view_render(const bContext *C);
+struct RenderEngineType *CTX_data_engine_type(const bContext *C);
struct ToolSettings *CTX_data_tool_settings(const bContext *C);
const char *CTX_data_mode_string(const bContext *C);
+int CTX_data_mode_enum_ex(const struct Object *obedit, const struct Object *ob);
int CTX_data_mode_enum(const bContext *C);
void CTX_data_main_set(bContext *C, struct Main *bmain);
@@ -296,6 +314,9 @@ int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
+struct Depsgraph *CTX_data_depsgraph(const bContext *C);
+
+void CTX_data_eval_ctx(const bContext *C, struct EvaluationContext *eval_ctx);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_crazyspace.h b/source/blender/blenkernel/BKE_crazyspace.h
index ee6c5c57678..31542cd6f8a 100644
--- a/source/blender/blenkernel/BKE_crazyspace.h
+++ b/source/blender/blenkernel/BKE_crazyspace.h
@@ -38,23 +38,24 @@ struct Scene;
struct Object;
struct BMEditMesh;
struct Mesh;
+struct EvaluationContext;
/* crazyspace.c */
float (*BKE_crazyspace_get_mapped_editverts(
- struct Scene *scene, struct Object *obedit))[3];
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *obedit))[3];
void BKE_crazyspace_set_quats_editmesh(
struct BMEditMesh *em, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4],
const bool use_select);
void BKE_crazyspace_set_quats_mesh(
struct Mesh *me, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4]);
int BKE_crazyspace_get_first_deform_matrices_editbmesh(
- struct Scene *, struct Object *, struct BMEditMesh *em,
+ const struct EvaluationContext *eval_ctx, struct Scene *, struct Object *, struct BMEditMesh *em,
float (**deformmats)[3][3], float (**deformcos)[3]);
int BKE_sculpt_get_first_deform_matrices(
- struct Scene *scene, struct Object *ob,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
float (**deformmats)[3][3], float (**deformcos)[3]);
void BKE_crazyspace_build_sculpt(
- struct Scene *scene, struct Object *ob,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
float (**deformmats)[3][3], float (**deformcos)[3]);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 175fa1dad79..fbd05552255 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -36,6 +36,7 @@
struct BezTriple;
struct Curve;
struct EditNurb;
+struct EvaluationContext;
struct GHash;
struct ListBase;
struct Main;
@@ -122,13 +123,14 @@ void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex);
void BKE_curve_editNurb_free(struct Curve *cu);
struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
-float *BKE_curve_make_orco(struct Scene *scene, struct Object *ob, int *r_numVerts);
+float *BKE_curve_make_orco(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, int *r_numVerts);
float *BKE_curve_surf_make_orco(struct Object *ob);
void BKE_curve_bevelList_free(struct ListBase *bev);
void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render);
-void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob, struct ListBase *disp,
- const bool for_render, const bool use_render_resolution);
+void BKE_curve_bevel_make(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *disp,
+ const bool for_render, const bool use_render_resolution);
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
@@ -215,10 +217,17 @@ void BKE_nurb_handles_test(struct Nurb *nu, const bool use_handles);
/* **** Depsgraph evaluation **** */
-struct EvaluationContext;
-
-void BKE_curve_eval_geometry(struct EvaluationContext *eval_ctx,
- struct Curve *curve);
+void BKE_curve_eval_geometry(
+ const struct EvaluationContext *eval_ctx,
+ struct Curve *curve);
+
+/* Draw Cache */
+enum {
+ BKE_CURVE_BATCH_DIRTY_ALL = 0,
+ BKE_CURVE_BATCH_DIRTY_SELECT,
+};
+void BKE_curve_batch_cache_dirty(struct Curve *cu, int mode);
+void BKE_curve_batch_cache_free(struct Curve *cu);
/* curve_decimate.c */
unsigned int BKE_curve_decimate_bezt_array(
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 2cdda34b9b5..51cd4da183a 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -376,15 +376,14 @@ void CustomData_validate_layer_name(const struct CustomData *data, int type, con
bool CustomData_verify_versions(struct CustomData *data, int index);
/*BMesh specific customdata stuff*/
-void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata,
- struct CustomData *ldata, int totloop, int totpoly);
-void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata, int total);
-void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata);
-void CustomData_bmesh_do_versions_update_active_layers(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata);
+void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *ldata, int totloop);
+void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *ldata, int total);
+void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct CustomData *ldata);
+void CustomData_bmesh_do_versions_update_active_layers(struct CustomData *fdata, struct CustomData *ldata);
void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, const char htype);
#ifndef NDEBUG
-bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, CustomData *ldata, bool fallback);
+bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *ldata, bool fallback);
#endif
/* External file storage */
diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h
index 2ee9d8d2408..d5f0313ca64 100644
--- a/source/blender/blenkernel/BKE_data_transfer.h
+++ b/source/blender/blenkernel/BKE_data_transfer.h
@@ -42,6 +42,7 @@ struct Object;
struct Scene;
struct SpaceTransform;
struct ReportList;
+struct EvaluationContext;
/* Warning, those def are stored in files (TransferData modifier), *DO NOT* modify those values. */
enum {
@@ -129,11 +130,12 @@ enum {
};
void BKE_object_data_transfer_layout(
- struct Scene *scene, struct Object *ob_src, struct Object *ob_dst, const int data_types, const bool use_delete,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob_src,
+ struct Object *ob_dst, const int data_types, const bool use_delete,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX]);
bool BKE_object_data_transfer_mesh(
- struct Scene *scene,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
struct Object *ob_src, struct Object *ob_dst, const int data_types, const bool use_create,
const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
struct SpaceTransform *space_transform, const bool auto_transform,
@@ -142,7 +144,7 @@ bool BKE_object_data_transfer_mesh(
const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
struct ReportList *reports);
bool BKE_object_data_transfer_dm(
- struct Scene *scene,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
struct Object *ob_src, struct Object *ob_dst, struct DerivedMesh *dm_dst,
const int data_types, bool use_create,
const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h
deleted file mode 100644
index 40564aeabe9..00000000000
--- a/source/blender/blenkernel/BKE_depsgraph.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2004 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __BKE_DEPSGRAPH_H__
-#define __BKE_DEPSGRAPH_H__
-
-/** \file BKE_depsgraph.h
- * \ingroup bke
- */
-
-/* Dependency Graph
- *
- * The dependency graph tracks relations between datablocks, and is used to
- * determine which datablocks need to be update based on dependencies and
- * visibility.
- *
- * It does not itself execute changes in objects, but rather sorts the objects
- * in the appropriate order and sets flags indicating they should be updated.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct ID;
-struct Main;
-struct Object;
-struct Scene;
-
-/* Dependency graph evaluation context
- *
- * This structure stores all the local dependency graph data,
- * which is needed for it's evaluation,
- */
-typedef struct EvaluationContext {
- int mode; /* evaluation mode */
- float ctime; /* evaluation time */
-} EvaluationContext;
-
-typedef enum eEvaluationMode {
- DAG_EVAL_VIEWPORT = 0, /* evaluate for OpenGL viewport */
- DAG_EVAL_PREVIEW = 1, /* evaluate for render with preview settings */
- DAG_EVAL_RENDER = 2, /* evaluate for render purposes */
-} eEvaluationMode;
-
-/* DagNode->eval_flags */
-enum {
- /* Regardless to curve->path animation flag path is to be evaluated anyway,
- * to meet dependencies with such a things as curve modifier and other guys
- * who're using curve deform, where_on_path and so.
- */
- DAG_EVAL_NEED_CURVE_PATH = 1,
- /* Scene evaluation would need to have object's data on CPU,
- * meaning no GPU shortcuts is allowed.
- */
- DAG_EVAL_NEED_CPU = 2,
-};
-
-/* Global initialization/deinitialization */
-void DAG_init(void);
-void DAG_exit(void);
-
-/* Build and Update
- *
- * DAG_scene_relations_update will rebuild the dependency graph for a given
- * scene if needed, and sort objects in the scene.
- *
- * DAG_relations_tag_update will clear all dependency graphs and mark them to
- * be rebuilt later. The graph is not rebuilt immediately to avoid slowdowns
- * when this function is call multiple times from different operators.
- *
- * DAG_scene_relations_rebuild forces an immediaterebuild of the dependency
- * graph, this is only needed in rare cases
- */
-
-void DAG_scene_relations_update(struct Main *bmain, struct Scene *sce);
-void DAG_scene_relations_validate(struct Main *bmain, struct Scene *sce);
-void DAG_relations_tag_update(struct Main *bmain);
-void DAG_scene_relations_rebuild(struct Main *bmain, struct Scene *scene);
-void DAG_scene_free(struct Scene *sce);
-
-/* Update Tagging
- *
- * DAG_scene_update_flags will mark all objects that depend on time (animation,
- * physics, ..) to be recalculated, used when changing the current frame.
- *
- * DAG_on_visible_update will mark all objects that are visible for the first
- * time to be updated, for example on file load or changing layer visibility.
- *
- * DAG_id_tag_update will mark a given datablock to be updated. The flag indicates
- * a specific subset to be update (only object transform and data for now).
- *
- * DAG_id_type_tag marks a particular datablock type as having changing. This does
- * not cause any updates but is used by external render engines to detect if for
- * example a datablock was removed. */
-
-void DAG_scene_update_flags(struct Main *bmain, struct Scene *sce, unsigned int lay, const bool do_time, const bool do_invisible_flush);
-void DAG_on_visible_update(struct Main *bmain, const bool do_time);
-
-void DAG_id_tag_update(struct ID *id, short flag);
-void DAG_id_tag_update_ex(struct Main *bmain, struct ID *id, short flag);
-void DAG_id_type_tag(struct Main *bmain, short idtype);
-int DAG_id_type_tagged(struct Main *bmain, short idtype);
-
-/* Flushing Tags
- *
- * DAG_scene_flush_update flushes object recalculation flags immediately to other
- * dependencies. Do not use outside of depsgraph.c, this will be removed.
- *
- * DAG_ids_flush_tagged will flush datablock update flags flags to dependencies,
- * use this right before updating to mark all the needed datablocks for update.
- *
- * DAG_ids_check_recalc and DAG_ids_clear_recalc are used for external render
- * engines to detect changes. */
-
-void DAG_scene_flush_update(struct Main *bmain, struct Scene *sce, unsigned int lay, const short do_time);
-void DAG_ids_flush_tagged(struct Main *bmain);
-void DAG_ids_check_recalc(struct Main *bmain, struct Scene *scene, bool time);
-void DAG_ids_clear_recalc(struct Main *bmain);
-
-/* Armature: sorts the bones according to dependencies between them */
-
-void DAG_pose_sort(struct Object *ob);
-
-/* Editors: callbacks to notify editors of datablock changes */
-
-void DAG_editors_update_cb(void (*id_func)(struct Main *bmain, struct ID *id),
- void (*scene_func)(struct Main *bmain, struct Scene *scene, int updated),
- void (*scene_pre_func)(struct Main *bmain, struct Scene *scene, bool time));
-
-void DAG_editors_update_pre(struct Main *bmain, struct Scene *scene, bool time);
-
-/* ** Threaded update ** */
-
-/* Initialize the DAG for threaded update. */
-void DAG_threaded_update_begin(struct Scene *scene,
- void (*func)(void *node, void *user_data),
- void *user_data);
-
-void DAG_threaded_update_handle_node_updated(void *node_v,
- void (*func)(void *node, void *user_data),
- void *user_data);
-
-/* Debugging: print dependency graph for scene or armature object to console */
-
-void DAG_print_dependencies(struct Main *bmain, struct Scene *scene, struct Object *ob);
-
-/* ************************ DAG querying ********************* */
-
-struct Object *DAG_get_node_object(void *node_v);
-const char *DAG_get_node_name(struct Scene *scene, void *node_v);
-short DAG_get_eval_flags_for_object(struct Scene *scene, void *object);
-bool DAG_is_acyclic(struct Scene *scene);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 9625f05192a..c2229976dd9 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -86,23 +86,30 @@ void BKE_displist_count(struct ListBase *lb, int *totvert, int *totface, int *to
void BKE_displist_free(struct ListBase *lb);
bool BKE_displist_has_faces(struct ListBase *lb);
-void BKE_displist_make_surf(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, struct DerivedMesh **r_dm_final,
- const bool for_render, const bool for_orco, const bool use_render_resolution);
-void BKE_displist_make_curveTypes(struct Scene *scene, struct Object *ob, const bool for_orco);
-void BKE_displist_make_curveTypes_forRender(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, struct DerivedMesh **r_dm_final,
- const bool for_orco, const bool use_render_resolution);
-void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
-void BKE_displist_make_mball(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
-void BKE_displist_make_mball_forRender(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
+void BKE_displist_make_surf(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase,
+ struct DerivedMesh **r_dm_final, const bool for_render, const bool for_orco, const bool use_render_resolution);
+void BKE_displist_make_curveTypes(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, const bool for_orco);
+void BKE_displist_make_curveTypes_forRender(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase,
+ struct DerivedMesh **r_dm_final, const bool for_orco, const bool use_render_resolution);
+void BKE_displist_make_curveTypes_forOrco(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
+void BKE_displist_make_mball(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void BKE_displist_make_mball_forRender(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
void BKE_displist_fill(struct ListBase *dispbase, struct ListBase *to, const float normal_proj[3], const bool flipnormal);
-float BKE_displist_calc_taper(struct Scene *scene, struct Object *taperobj, int cur, int tot);
+float BKE_displist_calc_taper(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *taperobj, int cur, int tot);
/* add Orco layer to the displist object which has got derived mesh and return orco */
-float *BKE_displist_make_orco(struct Scene *scene, struct Object *ob, struct DerivedMesh *dm_final,
- const bool for_render, const bool use_render_resolution);
+float *BKE_displist_make_orco(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm_final,
+ const bool for_render, const bool use_render_resolution);
void BKE_displist_minmax(struct ListBase *dispbase, float min[3], float max[3]);
diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h
index 5abb53d4c52..21c900a7f0d 100644
--- a/source/blender/blenkernel/BKE_dynamicpaint.h
+++ b/source/blender/blenkernel/BKE_dynamicpaint.h
@@ -28,6 +28,8 @@
*/
struct Scene;
+struct ViewLayer;
+struct EvaluationContext;
/* Actual surface point */
typedef struct PaintSurfaceData {
@@ -60,7 +62,8 @@ typedef struct PaintWavePoint {
short state;
} PaintWavePoint;
-struct DerivedMesh *dynamicPaint_Modifier_do(struct DynamicPaintModifierData *pmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm);
+struct DerivedMesh *dynamicPaint_Modifier_do(struct DynamicPaintModifierData *pmd, const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, struct DerivedMesh *dm);
void dynamicPaint_Modifier_free(struct DynamicPaintModifierData *pmd);
void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct DynamicPaintModifierData *tsmd);
@@ -83,7 +86,7 @@ struct DynamicPaintSurface *get_activeSurface(struct DynamicPaintCanvasSettings
/* image sequence baking */
int dynamicPaint_createUVSurface(struct Scene *scene, struct DynamicPaintSurface *surface, float *progress, short *do_update);
-int dynamicPaint_calculateFrame(struct DynamicPaintSurface *surface, struct Scene *scene, struct Object *cObject, int frame);
+int dynamicPaint_calculateFrame(struct DynamicPaintSurface *surface, const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *cObject, int frame);
void dynamicPaint_outputSurfaceImage(struct DynamicPaintSurface *surface, char *filename, short output_layer);
/* PaintPoint state */
diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h
index 55a9db9b1e5..af1aeff230f 100644
--- a/source/blender/blenkernel/BKE_editmesh.h
+++ b/source/blender/blenkernel/BKE_editmesh.h
@@ -40,6 +40,7 @@ struct Mesh;
struct Scene;
struct DerivedMesh;
struct MeshStatVis;
+struct EvaluationContext;
/**
* This structure is used for mesh edit-mode.
@@ -88,7 +89,6 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em);
BMEditMesh *BKE_editmesh_from_object(struct Object *ob);
void BKE_editmesh_free_derivedmesh(BMEditMesh *em);
void BKE_editmesh_free(BMEditMesh *em);
-void BKE_editmesh_update_linked_customdata(BMEditMesh *em);
void BKE_editmesh_color_free(BMEditMesh *em);
void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype);
@@ -99,6 +99,7 @@ float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3]
void BKE_editmesh_statvis_calc(BMEditMesh *em, struct DerivedMesh *dm,
const struct MeshStatVis *statvis);
-float (*BKE_editmesh_vertexCos_get(struct BMEditMesh *em, struct Scene *scene, int *r_numVerts))[3];
+float (*BKE_editmesh_vertexCos_get(
+ const struct EvaluationContext *eval_ctx, struct BMEditMesh *em, struct Scene *scene, int *r_numVerts))[3];
#endif /* __BKE_EDITMESH_H__ */
diff --git a/source/blender/blenkernel/BKE_editmesh_tangent.h b/source/blender/blenkernel/BKE_editmesh_tangent.h
new file mode 100644
index 00000000000..9553fbc1a5c
--- /dev/null
+++ b/source/blender/blenkernel/BKE_editmesh_tangent.h
@@ -0,0 +1,40 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Joseph Eagar.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_EDITMESH_TANGENT_H__
+#define __BKE_EDITMESH_TANGENT_H__
+
+/** \file BKE_editmesh_tangent.h
+ * \ingroup bke
+ */
+
+void BKE_editmesh_loop_tangent_calc(
+ BMEditMesh *em, bool calc_active_tangent,
+ const char (*tangent_names)[MAX_NAME], int tangent_names_len,
+ const float (*poly_normals)[3],
+ const float (*loop_normals)[3],
+ const float (*vert_orco)[3],
+ CustomData *dm_loopdata_out,
+ const uint dm_loopdata_out_len,
+ short *tangent_mask_curr_p);
+
+#endif /* __BKE_EDITMESH_TANGENT_H__ */
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index aa45132cbe9..6fa19d4aaf6 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -44,6 +44,7 @@ struct Group;
struct ParticleSimulationData;
struct ParticleData;
struct ParticleKey;
+struct EvaluationContext;
struct EffectorWeights *BKE_add_effector_weights(struct Group *group);
struct PartDeflect *object_add_collision_fields(int type);
@@ -93,6 +94,7 @@ typedef struct EffectorData {
typedef struct EffectorCache {
struct EffectorCache *next, *prev;
+ const struct EvaluationContext *eval_ctx;
struct Scene *scene;
struct Object *ob;
struct ParticleSystem *psys;
@@ -110,9 +112,11 @@ typedef struct EffectorCache {
} EffectorCache;
void free_partdeflect(struct PartDeflect *pd);
-struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool for_simulation);
+struct ListBase *pdInitEffectors(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src,
+ struct EffectorWeights *weights, bool for_simulation);
void pdEndEffectors(struct ListBase **effectors);
-void pdPrecalculateEffectors(struct ListBase *effectors);
+void pdPrecalculateEffectors(const struct EvaluationContext *eval_ctx, struct ListBase *effectors);
void pdDoEffectors(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *impulse);
void pd_point_from_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, struct EffectedPoint *point);
diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h
index 6501c968abc..4ec58b2a0e5 100644
--- a/source/blender/blenkernel/BKE_fluidsim.h
+++ b/source/blender/blenkernel/BKE_fluidsim.h
@@ -36,10 +36,11 @@ struct Object;
struct Scene;
struct FluidsimSettings;
struct MVert;
+struct EvaluationContext;
/* old interface */
-void initElbeemMesh(struct Scene *scene, struct Object *ob,
+void initElbeemMesh(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
int *numVertices, float **vertices,
int *numTriangles, int **triangles,
int useGlobalCoords, int modifierIndex);
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 790c8051ace..80a8f750d20 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -128,10 +128,11 @@ enum {
G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 11), /* single threaded depsgraph */
G_DEBUG_GPU = (1 << 12), /* gpu debug */
G_DEBUG_IO = (1 << 13), /* IO Debugging (for Collada, ...)*/
+ G_DEBUG_GPU_SHADERS = (1 << 14), /* GLSL shaders */
};
#define G_DEBUG_ALL (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \
- G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM | G_DEBUG_IO)
+ G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM | G_DEBUG_IO | G_DEBUG_GPU_SHADERS)
/* G.fileflags */
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index e07dd259970..ac436876dc4 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -41,17 +41,38 @@ struct Object;
struct Scene;
void BKE_group_free(struct Group *group);
+void BKE_group_init(struct Group *group);
struct Group *BKE_group_add(struct Main *bmain, const char *name);
void BKE_group_copy_data(struct Main *bmain, struct Group *group_dst, const struct Group *group_src, const int flag);
struct Group *BKE_group_copy(struct Main *bmain, const 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);
bool BKE_group_is_animated(struct Group *group, struct Object *parent);
-void BKE_group_handle_recalc_and_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *parent, struct Group *group);
+void BKE_group_handle_recalc_and_update(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *parent, struct Group *group);
+
+#define FOREACH_GROUP_BASE(_group, _base) \
+ for (Base *_base = (Base *)(_group)->view_layer->object_bases.first; \
+ _base; \
+ _base = _base->next) \
+ {
+
+#define FOREACH_GROUP_BASE_END \
+ }
+
+#define FOREACH_GROUP_OBJECT(_group, _object) \
+ for (Base *_base = (Base *)(_group)->view_layer->object_bases.first; \
+ _base; \
+ _base = _base->next) \
+ { \
+ Object *_object = _base->object; \
+ BLI_assert(_object != NULL);
+
+#define FOREACH_GROUP_OBJECT_END \
+ }
#endif /* __BKE_GROUP_H__ */
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 5d8cd02756d..055c530d255 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -91,6 +91,7 @@ void IDP_ReplaceGroupInGroup(struct IDProperty *dest, const struct IDProperty *s
void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
void IDP_ReplaceInGroup_ex(struct IDProperty *group, struct IDProperty *prop, struct IDProperty *prop_exist);
void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite) ATTR_NONNULL();
+void IDP_MergeGroup_ex(IDProperty *dest, const IDProperty *src, const bool do_overwrite, const int flag) ATTR_NONNULL();
bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
bool IDP_InsertToGroup(struct IDProperty *group, struct IDProperty *previous,
struct IDProperty *pnew) ATTR_NONNULL(1 /* group */, 3 /* pnew */);
diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h
index b68da654520..56b72282513 100644
--- a/source/blender/blenkernel/BKE_lamp.h
+++ b/source/blender/blenkernel/BKE_lamp.h
@@ -50,8 +50,6 @@ struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool lib_local);
void BKE_lamp_free(struct Lamp *la);
-void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index f7d006785d2..1cdf193f054 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -43,6 +43,7 @@ struct Scene;
struct DerivedMesh;
struct BPoint;
struct MDeformVert;
+struct EvaluationContext;
void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb);
void BKE_lattice_init(struct Lattice *lt);
@@ -61,10 +62,11 @@ void end_latt_deform(struct LatticeDeformData *lattice_deform_data);
bool object_deform_mball(struct Object *ob, struct ListBase *dispbase);
void outside_lattice(struct Lattice *lt);
-void curve_deform_verts(struct Scene *scene, struct Object *cuOb, struct Object *target,
- struct DerivedMesh *dm, float (*vertexCos)[3],
- int numVerts, const char *vgroup, short defaxis);
-void curve_deform_vector(struct Scene *scene, struct Object *cuOb, struct Object *target,
+void curve_deform_verts(
+ struct Object *cuOb, struct Object *target,
+ struct DerivedMesh *dm, float (*vertexCos)[3],
+ int numVerts, const char *vgroup, short defaxis);
+void curve_deform_vector(struct Object *cuOb, struct Object *target,
float orco[3], float vec[3], float mat[3][3], int no_rot_axis);
void lattice_deform_verts(struct Object *laOb, struct Object *target,
@@ -77,7 +79,7 @@ void armature_deform_verts(struct Object *armOb, struct Object *target,
float (*BKE_lattice_vertexcos_get(struct Object *ob, int *r_numVerts))[3];
void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3]);
-void BKE_lattice_modifiers_calc(struct Scene *scene, struct Object *ob);
+void BKE_lattice_modifiers_calc(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *lattice);
struct BPoint *BKE_lattice_active_point_get(struct Lattice *lt);
@@ -101,7 +103,15 @@ void BKE_lattice_bitmap_from_flag(struct Lattice *lt, unsigned int *bitmap, cons
struct EvaluationContext;
-void BKE_lattice_eval_geometry(struct EvaluationContext *eval_ctx,
+void BKE_lattice_eval_geometry(const struct EvaluationContext *eval_ctx,
struct Lattice *latt);
+/* Draw Cache */
+enum {
+ BKE_LATTICE_BATCH_DIRTY_ALL = 0,
+ BKE_LATTICE_BATCH_DIRTY_SELECT,
+};
+void BKE_lattice_batch_cache_dirty(struct Lattice *lt, int mode);
+void BKE_lattice_batch_cache_free(struct Lattice *lt);
+
#endif /* __BKE_LATTICE_H__ */
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
new file mode 100644
index 00000000000..e4f8b8790f6
--- /dev/null
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -0,0 +1,292 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation, 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_FILTER /* syncing of filter_objects across all trees */
+#define TODO_LAYER_OVERRIDE /* CollectionOverride */
+#define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */
+#define TODO_LAYER /* generic todo */
+
+#define ROOT_PROP "root"
+
+struct Base;
+struct EvaluationContext;
+struct Group;
+struct ID;
+struct IDProperty;
+struct LayerCollection;
+struct ListBase;
+struct Main;
+struct Object;
+struct RenderEngine;
+struct Scene;
+struct SceneCollection;
+struct ViewLayer;
+struct WorkSpace;
+
+void BKE_layer_exit(void);
+
+struct ViewLayer *BKE_view_layer_from_scene_get(const struct Scene *scene);
+struct ViewLayer *BKE_view_layer_from_workspace_get(const struct Scene *scene, const struct WorkSpace *workspace);
+struct ViewLayer *BKE_view_layer_add(struct Scene *scene, const char *name);
+struct ViewLayer *BKE_view_layer_group_add(struct Group *group);
+
+/* DEPRECATED */
+struct ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const struct Scene *scene);
+
+void BKE_view_layer_free(struct ViewLayer *view_layer);
+
+void BKE_view_layer_selected_objects_tag(struct ViewLayer *view_layer, const int tag);
+
+struct Object *BKE_view_layer_camera_find(struct ViewLayer *view_layer);
+struct ViewLayer *BKE_view_layer_first_from_id(const struct ID *owner_id);
+struct ViewLayer *BKE_view_layer_find_from_collection(const struct ID *owner_id, struct LayerCollection *lc);
+struct Base *BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob);
+void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer);
+void BKE_view_layer_base_select(struct ViewLayer *view_layer, struct Base *selbase);
+
+void BKE_view_layer_copy_data(
+ struct ViewLayer *view_layer_dst, struct ViewLayer *view_layer_src,
+ struct SceneCollection *mc_dst, struct SceneCollection *mc_src,
+ const int flag);
+
+void BKE_layer_collection_free(struct ViewLayer *view_layer, struct LayerCollection *lc);
+
+struct LayerCollection *BKE_layer_collection_get_active(struct ViewLayer *view_layer);
+struct LayerCollection *BKE_layer_collection_get_active_ensure(struct Scene *scene, struct ViewLayer *view_layer);
+
+int BKE_layer_collection_count(struct ViewLayer *view_layer);
+
+struct LayerCollection *BKE_layer_collection_from_index(struct ViewLayer *view_layer, const int index);
+int BKE_layer_collection_findindex(struct ViewLayer *view_layer, const struct LayerCollection *lc);
+
+bool BKE_layer_collection_move_above(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src);
+bool BKE_layer_collection_move_below(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src);
+bool BKE_layer_collection_move_into(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src);
+
+void BKE_layer_collection_resync(const struct ID *owner_id, const struct SceneCollection *sc);
+
+struct LayerCollection *BKE_collection_link(struct ViewLayer *view_layer, struct SceneCollection *sc);
+
+void BKE_collection_unlink(struct ViewLayer *view_layer, struct LayerCollection *lc);
+
+void BKE_collection_enable(struct ViewLayer *view_layer, struct LayerCollection *lc);
+void BKE_collection_disable(struct ViewLayer *view_layer, struct LayerCollection *lc);
+
+bool BKE_view_layer_has_collection(struct ViewLayer *view_layer, const struct SceneCollection *sc);
+bool BKE_scene_has_object(struct Scene *scene, struct Object *ob);
+
+/* syncing */
+
+void BKE_layer_sync_new_scene_collection(struct ID *owner_id, const struct SceneCollection *sc_parent, struct SceneCollection *sc);
+void BKE_layer_sync_object_link(const struct ID *owner_id, struct SceneCollection *sc, struct Object *ob);
+void BKE_layer_sync_object_unlink(const struct ID *owner_id, struct SceneCollection *sc, struct Object *ob);
+
+/* override */
+
+void BKE_override_view_layer_datablock_add(struct ViewLayer *view_layer, int id_type, const char *data_path, const struct ID *owner_id);
+void BKE_override_view_layer_int_add(struct ViewLayer *view_layer, int id_type, const char *data_path, const int value);
+
+void BKE_override_layer_collection_boolean_add(struct LayerCollection *layer_collection, int id_type, const char *data_path, const bool value);
+
+/* engine settings */
+typedef void (*EngineSettingsCB)(struct RenderEngine *engine, struct IDProperty *props);
+
+struct IDProperty *BKE_layer_collection_engine_evaluated_get(struct Object *ob, const int type, const char *engine_name);
+struct IDProperty *BKE_layer_collection_engine_collection_get(struct LayerCollection *lc, const int type, const char *engine_name);
+struct IDProperty *BKE_layer_collection_engine_scene_get(struct Scene *scene, const int type, const char *engine_name);
+void BKE_layer_collection_engine_settings_callback_register(struct Main *bmain, const char *engine_name, EngineSettingsCB func);
+void BKE_layer_collection_engine_settings_callback_free(void);
+void BKE_layer_collection_engine_settings_create(struct IDProperty *root);
+void BKE_layer_collection_engine_settings_validate_scene(struct Scene *scene);
+void BKE_layer_collection_engine_settings_validate_collection(struct LayerCollection *lc);
+
+struct IDProperty *BKE_view_layer_engine_evaluated_get(struct ViewLayer *view_layer, const int type, const char *engine_name);
+struct IDProperty *BKE_view_layer_engine_layer_get(struct ViewLayer *view_layer, const int type, const char *engine_name);
+struct IDProperty *BKE_view_layer_engine_scene_get(struct Scene *scene, const int type, const char *engine_name);
+void BKE_view_layer_engine_settings_callback_register(struct Main *bmain, const char *engine_name, EngineSettingsCB func);
+void BKE_view_layer_engine_settings_callback_free(void);
+void BKE_view_layer_engine_settings_validate_scene(struct Scene *scene);
+void BKE_view_layer_engine_settings_validate_layer(struct ViewLayer *view_layer);
+void BKE_view_layer_engine_settings_create(struct IDProperty *root);
+
+void BKE_collection_engine_property_add_float(struct IDProperty *props, const char *name, float value);
+void BKE_collection_engine_property_add_float_array(
+ struct IDProperty *props, const char *name, const float *values, const int array_length);
+void BKE_collection_engine_property_add_int(struct IDProperty *props, const char *name, int value);
+void BKE_collection_engine_property_add_bool(struct IDProperty *props, const char *name, bool value);
+
+int BKE_collection_engine_property_value_get_int(struct IDProperty *props, const char *name);
+float BKE_collection_engine_property_value_get_float(struct IDProperty *props, const char *name);
+const float *BKE_collection_engine_property_value_get_float_array(struct IDProperty *props, const char *name);
+bool BKE_collection_engine_property_value_get_bool(struct IDProperty *props, const char *name);
+void BKE_collection_engine_property_value_set_int(struct IDProperty *props, const char *name, int value);
+void BKE_collection_engine_property_value_set_float(struct IDProperty *props, const char *name, float value);
+void BKE_collection_engine_property_value_set_float_array(struct IDProperty *props, const char *name, const float *values);
+void BKE_collection_engine_property_value_set_bool(struct IDProperty *props, const char *name, bool value);
+
+/* evaluation */
+
+void BKE_layer_eval_layer_collection_pre(const struct EvaluationContext *eval_ctx,
+ struct ID *owner_id,
+ struct ViewLayer *view_layer);
+void BKE_layer_eval_layer_collection(const struct EvaluationContext *eval_ctx,
+ struct LayerCollection *layer_collection,
+ struct LayerCollection *parent_layer_collection);
+void BKE_layer_eval_layer_collection_post(const struct EvaluationContext *eval_ctx,
+ struct ViewLayer *view_layer);
+
+/* iterators */
+
+void BKE_selected_objects_iterator_begin(BLI_Iterator *iter, void *data_in);
+void BKE_selected_objects_iterator_next(BLI_Iterator *iter);
+void BKE_selected_objects_iterator_end(BLI_Iterator *iter);
+
+void BKE_visible_objects_iterator_begin(BLI_Iterator *iter, void *data_in);
+void BKE_visible_objects_iterator_next(BLI_Iterator *iter);
+void BKE_visible_objects_iterator_end(BLI_Iterator *iter);
+
+void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in);
+void BKE_renderable_objects_iterator_next(BLI_Iterator *iter);
+void BKE_renderable_objects_iterator_end(BLI_Iterator *iter);
+
+void BKE_selected_bases_iterator_begin(BLI_Iterator *iter, void *data_in);
+void BKE_selected_bases_iterator_next(BLI_Iterator *iter);
+void BKE_selected_bases_iterator_end(BLI_Iterator *iter);
+
+void BKE_visible_bases_iterator_begin(BLI_Iterator *iter, void *data_in);
+void BKE_visible_bases_iterator_next(BLI_Iterator *iter);
+void BKE_visible_bases_iterator_end(BLI_Iterator *iter);
+
+#define FOREACH_SELECTED_OBJECT(view_layer, _instance) \
+ ITER_BEGIN(BKE_selected_objects_iterator_begin, \
+ BKE_selected_objects_iterator_next, \
+ BKE_selected_objects_iterator_end, \
+ view_layer, Object *, _instance)
+
+#define FOREACH_SELECTED_OBJECT_END \
+ ITER_END
+
+#define FOREACH_VISIBLE_OBJECT(view_layer, _instance) \
+ ITER_BEGIN(BKE_visible_objects_iterator_begin, \
+ BKE_visible_objects_iterator_next, \
+ BKE_visible_objects_iterator_end, \
+ view_layer, Object *, _instance)
+
+#define FOREACH_VISIBLE_OBJECT_END \
+ ITER_END
+
+#define FOREACH_SELECTED_BASE(view_layer, _instance) \
+ ITER_BEGIN(BKE_selected_bases_iterator_begin, \
+ BKE_selected_bases_iterator_next, \
+ BKE_selected_bases_iterator_end, \
+ view_layer, Base *, _instance)
+
+#define FOREACH_SELECTED_BASE_END \
+ ITER_END
+
+#define FOREACH_VISIBLE_BASE(view_layer, _instance) \
+ ITER_BEGIN(BKE_visible_bases_iterator_begin, \
+ BKE_visible_bases_iterator_next, \
+ BKE_visible_bases_iterator_end, \
+ view_layer, Base *, _instance)
+
+#define FOREACH_VISIBLE_BASE_END \
+ ITER_END
+
+
+#define FOREACH_OBJECT(view_layer, _instance) \
+{ \
+ Object *_instance; \
+ Base *base; \
+ for (base = (view_layer)->object_bases.first; base; base = base->next) { \
+ _instance = base->object;
+
+#define FOREACH_OBJECT_END \
+ } \
+}
+
+#define FOREACH_OBJECT_FLAG(scene, view_layer, flag, _instance) \
+{ \
+ 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 = (view_layer); \
+ } \
+ 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 *, _instance)
+
+
+#define FOREACH_OBJECT_FLAG_END \
+ ITER_END \
+}
+
+typedef struct ObjectsRenderableIteratorData {
+ struct Scene *scene;
+
+ struct {
+ struct ViewLayer *view_layer;
+ struct Base *base;
+ struct Scene *set;
+ } iter;
+} ObjectsRenderableIteratorData;
+
+#define FOREACH_OBJECT_RENDERABLE(scene_, _instance) \
+ ObjectsRenderableIteratorData data_ = { \
+ .scene = (scene_), \
+ }; \
+ ITER_BEGIN(BKE_renderable_objects_iterator_begin, \
+ BKE_renderable_objects_iterator_next, \
+ BKE_renderable_objects_iterator_end, \
+ &data_, Object *, _instance)
+
+
+#define FOREACH_OBJECT_RENDERABLE_END \
+ 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 eb66d4edf0f..0abf99415c7 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -148,6 +148,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, const struct ID *id, struct ID **newid, bool test);
bool BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag, const bool test);
+void BKE_id_swap(struct Main *bmain, struct ID *id_a, struct ID *id_b);
void id_sort_by_name(struct ListBase *lb, struct ID *id);
void BKE_id_expand_local(struct Main *bmain, struct ID *id);
void BKE_id_copy_ensure_local(struct Main *bmain, const struct ID *old_id, struct ID *new_id);
@@ -158,7 +159,7 @@ void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_ma
struct ListBase *which_libbase(struct Main *mainlib, short type);
-#define MAX_LIBARRAY 35
+#define MAX_LIBARRAY 37
int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
/* Main API */
diff --git a/source/blender/blenkernel/BKE_library_override.h b/source/blender/blenkernel/BKE_library_override.h
new file mode 100644
index 00000000000..1ba009660f2
--- /dev/null
+++ b/source/blender/blenkernel/BKE_library_override.h
@@ -0,0 +1,86 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_LIBRARY_OVERRIDE_H__
+#define __BKE_LIBRARY_OVERRIDE_H__
+
+/** \file BKE_library_override.h
+ * \ingroup bke
+ * \since December 2016
+ * \author mont29
+ */
+
+struct ID;
+struct IDOverrideStatic;
+struct IDOverrideStaticProperty;
+struct IDOverrideStaticPropertyOperation;
+struct Main;
+
+struct IDOverrideStatic *BKE_override_static_init(struct ID *local_id, struct ID *reference_id);
+void BKE_override_static_copy(struct ID *dst_id, const struct ID *src_id);
+void BKE_override_static_clear(struct IDOverrideStatic *override);
+void BKE_override_static_free(struct IDOverrideStatic **override);
+
+struct ID *BKE_override_static_create_from(struct Main *bmain, struct ID *reference_id);
+
+struct IDOverrideStaticProperty *BKE_override_static_property_find(struct IDOverrideStatic *override, const char *rna_path);
+struct IDOverrideStaticProperty *BKE_override_static_property_get(struct IDOverrideStatic *override, const char *rna_path, bool *r_created);
+void BKE_override_static_property_delete(struct IDOverrideStatic *override, struct IDOverrideStaticProperty *override_property);
+
+struct IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_find(
+ struct IDOverrideStaticProperty *override_property,
+ const char *subitem_refname, const char *subitem_locname,
+ const int subitem_refindex, const int subitem_locindex, const bool strict, bool *r_strict);
+struct IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_get(
+ struct IDOverrideStaticProperty *override_property, const short operation,
+ const char *subitem_refname, const char *subitem_locname,
+ const int subitem_refindex, const int subitem_locindex,
+ const bool strict, bool *r_strict, bool *r_created);
+void BKE_override_static_property_operation_delete(
+ struct IDOverrideStaticProperty *override_property, struct IDOverrideStaticPropertyOperation *override_property_operation);
+
+bool BKE_override_static_status_check_local(struct ID *local);
+bool BKE_override_static_status_check_reference(struct ID *local);
+
+bool BKE_override_static_operations_create(struct ID *local);
+void BKE_main_override_static_operations_create(struct Main *bmain);
+
+void BKE_override_static_update(struct Main *bmain, struct ID *local);
+void BKE_main_override_static_update(struct Main *bmain);
+
+
+/* Storage (.blend file writing) part. */
+
+/* For now, we just use a temp main list. */
+typedef struct Main OverrideStaticStorage;
+
+OverrideStaticStorage *BKE_override_static_operations_store_initialize(void);
+struct ID *BKE_override_static_operations_store_start(OverrideStaticStorage *override_storage, struct ID *local);
+void BKE_override_static_operations_store_end(OverrideStaticStorage *override_storage, struct ID *local);
+void BKE_override_static_operations_store_finalize(OverrideStaticStorage *override_storage);
+
+
+
+#endif /* __BKE_LIBRARY_OVERRIDE_H__ */
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index d6e7d98f371..b66fc0aab16 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -56,6 +56,9 @@ enum {
* How to handle that kind of cases totally depends on what caller code is doing... */
IDWALK_CB_LOOPBACK = (1 << 4),
+ /** That ID is used as static override's reference by its owner. */
+ IDWALK_CB_STATIC_OVERRIDE_REFERENCE = (1 << 5),
+
/**
* Adjusts #ID.us reference-count.
* \note keep in sync with 'newlibadr_us' use in readfile.c
diff --git a/source/blender/blenkernel/BKE_library_remap.h b/source/blender/blenkernel/BKE_library_remap.h
index fd37fd762f4..3425ca011b7 100644
--- a/source/blender/blenkernel/BKE_library_remap.h
+++ b/source/blender/blenkernel/BKE_library_remap.h
@@ -51,6 +51,8 @@ enum {
* This is needed e.g. in reload scenario, since we have to ensure remapping of Armature data of local proxy
* is also performed. Usual nightmare... */
ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE = 1 << 4,
+ /* Do not remap static override pointers. */
+ ID_REMAP_SKIP_STATIC_OVERRIDE = 1 << 5,
};
/* Note: Requiring new_id to be non-null, this *may* not be the case ultimately, but makes things simpler for now. */
diff --git a/source/blender/blenkernel/BKE_lightprobe.h b/source/blender/blenkernel/BKE_lightprobe.h
new file mode 100644
index 00000000000..a769b6653d7
--- /dev/null
+++ b/source/blender/blenkernel/BKE_lightprobe.h
@@ -0,0 +1,46 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_LIGHTPROBE_H__
+#define __BKE_LIGHTPROBE_H__
+
+/** \file BKE_lightprobe.h
+ * \ingroup bke
+ * \brief General operations for probes.
+ */
+
+struct Main;
+struct LightProbe;
+
+void BKE_lightprobe_init(struct LightProbe *probe);
+void *BKE_lightprobe_add(struct Main *bmain, const char *name);
+void BKE_lightprobe_copy_data(struct Main *bmain, struct LightProbe *probe_dst, const struct LightProbe *probe_src, const int flag);
+struct LightProbe *BKE_lightprobe_copy(struct Main *bmain, const struct LightProbe *probe);
+void BKE_lightprobe_make_local(struct Main *bmain, struct LightProbe *probe, const bool lib_local);
+void BKE_lightprobe_free(struct LightProbe *probe);
+
+#endif /* __BKE_LIGHTPROBE_H__ */
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 387045878f3..faa91fd4f79 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -108,6 +108,7 @@ typedef struct Main {
ListBase vfont;
ListBase text;
ListBase speaker;
+ ListBase lightprobe;
ListBase sound;
ListBase group;
ListBase armature;
@@ -123,6 +124,7 @@ typedef struct Main {
ListBase mask;
ListBase linestyle;
ListBase cachefiles;
+ ListBase workspaces;
char id_tag_update[MAX_LIBARRAY];
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index c6ebda2c399..cb4ee9c2543 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -87,6 +87,10 @@ short BKE_object_material_slot_find_index(struct Object *ob, struct Material *ma
bool BKE_object_material_slot_add(struct Object *ob);
bool BKE_object_material_slot_remove(struct Object *ob);
+struct Image *BKE_object_material_edit_image_get(struct Object *ob, short mat_nr);
+struct Image **BKE_object_material_edit_image_get_array(struct Object *ob);
+bool BKE_object_material_edit_image_set(struct Object *ob, short mat_nr, struct Image *image);
+
void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);
@@ -106,17 +110,17 @@ bool material_in_material(struct Material *parmat, struct Material *mat);
void ramp_blend(int type, float r_col[3], const float fac, const float col[3]);
-/* driver update hacks */
-void material_drivers_update(struct Scene *scene, struct Material *mat, float ctime);
-
/* copy/paste */
void clear_matcopybuf(void);
void free_matcopybuf(void);
void copy_matcopybuf(struct Material *ma);
void paste_matcopybuf(struct Material *ma);
-/* handle backward compatibility for tface/materials called from doversion */
-int do_version_tface(struct Main *main);
+/* Evaluation. */
+
+struct EvaluationContext;
+
+void BKE_material_eval(const struct EvaluationContext *eval_ctx, struct Material *material);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index f02704ba903..9db277f95fb 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -73,7 +73,18 @@ void BKE_mball_select_swap(struct MetaBall *mb);
struct EvaluationContext;
-void BKE_mball_eval_geometry(struct EvaluationContext *eval_ctx,
+void BKE_mball_eval_geometry(const struct EvaluationContext *eval_ctx,
struct MetaBall *mball);
+/* Draw Cache */
+
+void BKE_mball_element_calc_display_m3x4(float r_scale_xform[3][4],
+ const float obmat[4][4],
+ const float local_pos[3]);
+
+enum {
+ BKE_MBALL_BATCH_DIRTY_ALL = 0,
+};
+void BKE_mball_batch_cache_dirty(struct MetaBall *mb, int mode);
+void BKE_mball_batch_cache_free(struct MetaBall *mb);
#endif
diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h
index 361f31b704c..40cdc80e280 100644
--- a/source/blender/blenkernel/BKE_mball_tessellate.h
+++ b/source/blender/blenkernel/BKE_mball_tessellate.h
@@ -28,7 +28,7 @@ struct Object;
struct Scene;
void BKE_mball_polygonize(
- struct EvaluationContext *eval_ctx, struct Scene *scene,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
struct Object *ob, struct ListBase *dispbase);
void BKE_mball_cubeTable_free(void);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index f3b2b653e3d..5ee3b9be5f9 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -35,6 +35,7 @@ struct ID;
struct BMeshCreateParams;
struct BoundBox;
struct EdgeHash;
+struct EvaluationContext;
struct ListBase;
struct LinkNode;
struct BLI_Stack;
@@ -92,6 +93,9 @@ struct Mesh *BKE_mesh_copy(struct Main *bmain, const struct Mesh *me);
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd);
void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
+bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me);
+bool BKE_mesh_clear_facemap_customdata(struct Mesh *me);
+
void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me, const bool lib_local);
void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]);
void BKE_mesh_texspace_calc(struct Mesh *me);
@@ -115,7 +119,7 @@ void BKE_mesh_from_nurbs_displist(
struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv, const char *obdata_name);
void BKE_mesh_from_nurbs(struct Object *ob);
void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblist, const int edge_users_test);
-void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob);
+void BKE_mesh_to_curve(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
void BKE_mesh_material_index_remove(struct Mesh *me, short index);
void BKE_mesh_material_index_clear(struct Mesh *me);
void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len);
@@ -125,6 +129,7 @@ const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
struct BoundBox *BKE_mesh_boundbox_get(struct Object *ob);
void BKE_mesh_texspace_get(struct Mesh *me, float r_loc[3], float r_rot[3], float r_size[3]);
+void BKE_mesh_texspace_get_reference(struct Mesh *me, short **r_texflag, float **r_loc, float **r_rot, float **r_size);
void BKE_mesh_texspace_copy_from_object(struct Mesh *me, struct Object *ob);
bool BKE_mesh_uv_cdlayer_rename_index(struct Mesh *me, const int poly_index, const int loop_index, const int face_index,
@@ -135,7 +140,7 @@ float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3];
void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
-struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Scene *sce, struct Object *ob,
+struct Mesh *BKE_mesh_new_from_object(const struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, struct Object *ob,
int apply_modifiers, int settings, int calc_tessface, int calc_undeformed);
/* vertex level transformations & checks (no derived mesh) */
@@ -188,13 +193,6 @@ void BKE_mesh_calc_normals_looptri(
const struct MLoop *mloop,
const struct MLoopTri *looptri, int looptri_num,
float (*r_tri_nors)[3]);
-void BKE_mesh_loop_tangents_ex(
- const struct MVert *mverts, const int numVerts, const struct MLoop *mloops,
- float (*r_looptangent)[4], float (*loopnors)[3], const struct MLoopUV *loopuv,
- const int numLoops, const struct MPoly *mpolys, const int numPolys,
- struct ReportList *reports);
-void BKE_mesh_loop_tangents(
- struct Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], struct ReportList *reports);
/**
* References a contiguous loop-fan with normal offset vars.
@@ -297,7 +295,7 @@ void BKE_mesh_loops_to_mface_corners(
const int numTex, const int numCol,
const bool hasPCol, const bool hasOrigSpace, const bool hasLNor);
void BKE_mesh_loops_to_tessdata(
- struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, struct MFace *mface,
+ struct CustomData *fdata, struct CustomData *ldata, struct MFace *mface,
int *polyindices, unsigned int (*loopindices)[4], const int num_faces);
void BKE_mesh_tangent_loops_to_tessdata(
struct CustomData *fdata, struct CustomData *ldata, struct MFace *mface,
@@ -375,7 +373,6 @@ void BKE_mesh_calc_relative_deform(
/* *** mesh_validate.c *** */
int BKE_mesh_validate(struct Mesh *me, const int do_verbose, const int cddata_check_mask);
-void BKE_mesh_cd_validate(struct Mesh *me);
int BKE_mesh_validate_material_indices(struct Mesh *me);
bool BKE_mesh_validate_arrays(
@@ -405,11 +402,20 @@ void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select);
/* **** Depsgraph evaluation **** */
-struct EvaluationContext;
-
-void BKE_mesh_eval_geometry(struct EvaluationContext *eval_ctx,
+void BKE_mesh_eval_geometry(const struct EvaluationContext *eval_ctx,
struct Mesh *mesh);
+/* Draw Cache */
+enum {
+ BKE_MESH_BATCH_DIRTY_ALL = 0,
+ BKE_MESH_BATCH_DIRTY_MAYBE_ALL,
+ BKE_MESH_BATCH_DIRTY_SELECT,
+ BKE_MESH_BATCH_DIRTY_SHADING,
+ BKE_MESH_BATCH_DIRTY_SCULPT_COORDS,
+};
+void BKE_mesh_batch_cache_dirty(struct Mesh *me, int mode);
+void BKE_mesh_batch_cache_free(struct Mesh *me);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_mesh_tangent.h b/source/blender/blenkernel/BKE_mesh_tangent.h
new file mode 100644
index 00000000000..cb3100c1c2f
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mesh_tangent.h
@@ -0,0 +1,61 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_MESH_TANGENT_H__
+#define __BKE_MESH_TANGENT_H__
+
+void BKE_mesh_calc_loop_tangent_single_ex(
+ const struct MVert *mverts, const int numVerts, const struct MLoop *mloops,
+ float (*r_looptangent)[4], float (*loopnors)[3], const struct MLoopUV *loopuv,
+ const int numLoops, const struct MPoly *mpolys, const int numPolys,
+ struct ReportList *reports);
+void BKE_mesh_calc_loop_tangent_single(
+ struct Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], struct ReportList *reports);
+
+void BKE_mesh_calc_loop_tangent_ex(
+ const struct MVert *mvert,
+ const struct MPoly *mpoly, const uint mpoly_len,
+ const struct MLoop *mloop,
+ const struct MLoopTri *looptri, const uint looptri_len,
+
+ struct CustomData *loopdata,
+ bool calc_active_tangent,
+ const char (*tangent_names)[64], int tangent_names_len,
+ const float (*poly_normals)[3],
+ const float (*loop_normals)[3],
+ const float (*vert_orco)[3],
+ /* result */
+ struct CustomData *loopdata_out,
+ const uint loopdata_out_len,
+ short *tangent_mask_curr_p);
+
+/* Helpers */
+void BKE_mesh_add_loop_tangent_named_layer_for_uv(
+ struct CustomData *uv_data, struct CustomData *tan_data, int numLoopData,
+ const char *layer_name);
+
+#define DM_TANGENT_MASK_ORCO (1 << 9)
+void BKE_mesh_calc_loop_tangent_step_0(
+ const struct CustomData *loopData, bool calc_active_tangent,
+ const char (*tangent_names)[64], int tangent_names_count,
+ bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
+ char *ract_uv_name, char *rren_uv_name, short *rtangent_mask);
+
+#endif /* __BKE_MESH_TANGENT_H__ */
+
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 30c47a4b192..451823aedf5 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -36,8 +36,10 @@ struct ID;
struct DerivedMesh;
struct DagForest;
struct DagNode;
+struct EvaluationContext;
struct Object;
struct Scene;
+struct ViewLayer;
struct ListBase;
struct bArmature;
struct Main;
@@ -157,25 +159,27 @@ typedef struct ModifierTypeInfo {
* the object it can obtain it from the derivedData argument if non-NULL,
* and otherwise the ob argument.
*/
- void (*deformVerts)(struct ModifierData *md, struct Object *ob,
- struct DerivedMesh *derivedData,
+ void (*deformVerts)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts,
ModifierApplyFlag flag);
/* Like deformMatricesEM but called from object mode (for supporting modifiers in sculpt mode) */
- void (*deformMatrices)(struct ModifierData *md, struct Object *ob,
- struct DerivedMesh *derivedData,
+ void (*deformMatrices)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct DerivedMesh *derivedData,
float (*vertexCos)[3], float (*defMats)[3][3], int numVerts);
/* Like deformVerts but called during editmode (for supporting modifiers)
*/
- void (*deformVertsEM)(struct ModifierData *md, struct Object *ob,
- struct BMEditMesh *editData, struct DerivedMesh *derivedData,
+ void (*deformVertsEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct BMEditMesh *editData,
+ struct DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts);
/* Set deform matrix per vertex for crazyspace correction */
- void (*deformMatricesEM)(struct ModifierData *md, struct Object *ob,
- struct BMEditMesh *editData, struct DerivedMesh *derivedData,
+ void (*deformMatricesEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct BMEditMesh *editData,
+ struct DerivedMesh *derivedData,
float (*vertexCos)[3], float (*defMats)[3][3], int numVerts);
/********************* Non-deform modifier functions *********************/
@@ -199,8 +203,8 @@ typedef struct ModifierTypeInfo {
* The modifier may reuse the derivedData argument (i.e. return it in
* modified form), but must not release it.
*/
- struct DerivedMesh *(*applyModifier)(struct ModifierData *md, struct Object *ob,
- struct DerivedMesh *derivedData,
+ struct DerivedMesh *(*applyModifier)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct DerivedMesh *derivedData,
ModifierApplyFlag flag);
/* Like applyModifier but called during editmode (for supporting
@@ -210,10 +214,9 @@ typedef struct ModifierTypeInfo {
* are expected from editmode objects. The same qualifications regarding
* derivedData apply as for applyModifier.
*/
- struct DerivedMesh *(*applyModifierEM)(struct ModifierData *md, struct Object *ob,
- struct BMEditMesh *editData,
- struct DerivedMesh *derivedData,
- ModifierApplyFlag flag);
+ struct DerivedMesh *(*applyModifierEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct BMEditMesh *editData,
+ struct DerivedMesh *derivedData, ModifierApplyFlag flag);
/********************* Optional functions *********************/
@@ -260,20 +263,10 @@ typedef struct ModifierTypeInfo {
*/
bool (*isDisabled)(struct ModifierData *md, int userRenderParams);
- /* Add the appropriate relations to the DEP graph depending on the
- * modifier data.
- *
- * This function is optional.
- */
- void (*updateDepgraph)(struct ModifierData *md, struct DagForest *forest,
- struct Main *bmain, struct Scene *scene,
- struct Object *ob, struct DagNode *obNode);
-
/* Add the appropriate relations to the dependency graph.
*
* This function is optional.
*/
- /* TODO(sergey): Remove once we finally switched to the new depsgraph. */
void (*updateDepsgraph)(struct ModifierData *md,
struct Main *bmain,
struct Scene *scene,
@@ -427,24 +420,24 @@ const char *modifier_path_relbase(struct Object *ob);
/* wrappers for modifier callbacks */
struct DerivedMesh *modwrap_applyModifier(
- ModifierData *md, struct Object *ob,
- struct DerivedMesh *dm,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct DerivedMesh *dm,
ModifierApplyFlag flag);
struct DerivedMesh *modwrap_applyModifierEM(
- ModifierData *md, struct Object *ob,
- struct BMEditMesh *em,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct BMEditMesh *em,
struct DerivedMesh *dm,
ModifierApplyFlag flag);
void modwrap_deformVerts(
- ModifierData *md, struct Object *ob,
- struct DerivedMesh *dm,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct DerivedMesh *dm,
float (*vertexCos)[3], int numVerts,
ModifierApplyFlag flag);
void modwrap_deformVertsEM(
- ModifierData *md, struct Object *ob,
+ ModifierData *md, const struct EvaluationContext *eval_ctx, struct Object *ob,
struct BMEditMesh *em, struct DerivedMesh *dm,
float (*vertexCos)[3], int numVerts);
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 178751d1640..761bb7e8acb 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -34,6 +34,7 @@
enum MultiresModifiedFlags;
struct DerivedMesh;
+struct EvaluationContext;
struct MDisps;
struct Mesh;
struct ModifierData;
@@ -80,18 +81,18 @@ struct DerivedMesh *multires_make_derived_from_derived(struct DerivedMesh *dm,
struct MultiresModifierData *find_multires_modifier_before(struct Scene *scene,
struct ModifierData *lastmd);
struct MultiresModifierData *get_multires_modifier(struct Scene *scene, struct Object *ob, bool use_first);
-struct DerivedMesh *get_multires_dm(struct Scene *scene, struct MultiresModifierData *mmd,
+struct DerivedMesh *get_multires_dm(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd,
struct Object *ob);
void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction);
void multiresModifier_base_apply(struct MultiresModifierData *mmd, struct Object *ob);
void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int updateblock, int simple);
void multiresModifier_sync_levels_ex(
struct Object *ob_dst, struct MultiresModifierData *mmd_src, struct MultiresModifierData *mmd_dst);
-int multiresModifier_reshape(struct Scene *scene, struct MultiresModifierData *mmd,
+int multiresModifier_reshape(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd,
struct Object *dst, struct Object *src);
-int multiresModifier_reshapeFromDM(struct Scene *scene, struct MultiresModifierData *mmd,
+int multiresModifier_reshapeFromDM(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd,
struct Object *ob, struct DerivedMesh *srcdm);
-int multiresModifier_reshapeFromDeformMod(struct Scene *scene, struct MultiresModifierData *mmd,
+int multiresModifier_reshapeFromDeformMod(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd,
struct Object *ob, struct ModifierData *md);
void multires_stitch_grids(struct Object *);
@@ -109,8 +110,8 @@ void multires_free(struct Multires *mr);
void multires_load_old(struct Object *ob, struct Mesh *me);
void multires_load_old_250(struct Mesh *);
-void multiresModifier_scale_disp(struct Scene *scene, struct Object *ob);
-void multiresModifier_prepare_join(struct Scene *scene, struct Object *ob, struct Object *to_ob);
+void multiresModifier_scale_disp(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void multiresModifier_prepare_join(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct Object *to_ob);
int multires_mdisp_corners(struct MDisps *s);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index c364d0ebb1b..39535ffd403 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -74,6 +74,7 @@ struct PointerRNA;
struct RenderData;
struct Scene;
struct Tex;
+struct ViewRender;
struct SpaceNode;
struct ARegion;
struct ColorManagedViewSettings;
@@ -251,8 +252,9 @@ typedef struct bNodeType {
#define NODE_CLASS_LAYOUT 100
/* nodetype->compatibility */
-#define NODE_OLD_SHADING 1
-#define NODE_NEW_SHADING 2
+#define NODE_OLD_SHADING (1 << 0)
+#define NODE_NEW_SHADING (1 << 1)
+#define NODE_NEWER_SHADING (1 << 2)
/* node resize directions */
#define NODE_RESIZE_TOP 1
@@ -281,7 +283,7 @@ typedef struct bNodeTreeType {
/* callbacks */
void (*free_cache)(struct bNodeTree *ntree);
void (*free_node_cache)(struct bNodeTree *ntree, struct bNode *node);
- void (*foreach_nodeclass)(struct Scene *scene, void *calldata, bNodeClassCallback func); /* iteration over all node classes */
+ void (*foreach_nodeclass)(struct ViewRender *view_render, void *calldata, bNodeClassCallback func); /* iteration over all node classes */
/* Check visibility in the node editor */
int (*poll)(const struct bContext *C, struct bNodeTreeType *ntreetype);
/* Select a node tree from the context */
@@ -689,6 +691,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
*/
@@ -788,6 +797,7 @@ struct ShadeResult;
#define SH_NODE_UVALONGSTROKE 191
#define SH_NODE_TEX_POINTDENSITY 192
#define SH_NODE_BSDF_PRINCIPLED 193
+#define SH_NODE_EEVEE_SPECULAR 195
#define SH_NODE_BEVEL 197
/* custom defines options for Material node */
@@ -807,6 +817,7 @@ extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *));
void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat, short compatibility);
+void ntreeGPUMaterialDomain(struct bNodeTree *ntree, bool *has_surface_output, bool *has_volume_output);
/** \} */
@@ -977,7 +988,7 @@ void ntreeCompositTagRender(struct Scene *sce);
int ntreeCompositTagAnimated(struct bNodeTree *ntree);
void ntreeCompositTagGenerators(struct bNodeTree *ntree);
void ntreeCompositUpdateRLayers(struct bNodeTree *ntree);
-void ntreeCompositRegisterPass(struct bNodeTree *ntree, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type);
+void ntreeCompositRegisterPass(struct bNodeTree *ntree, struct Scene *scene, struct ViewLayer *view_layer, const char *name, int type);
void ntreeCompositClearTags(struct bNodeTree *ntree);
struct bNodeSocket *ntreeCompositOutputFileAddSocket(struct bNodeTree *ntree, struct bNode *node,
@@ -1042,4 +1053,16 @@ int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target,
void init_nodesystem(void);
void free_nodesystem(void);
+/* -------------------------------------------------------------------- */
+/* evaluation support, */
+
+struct EvaluationContext;
+
+void BKE_nodetree_copy_default_values(struct bNodeTree *ntree_dst,
+ const struct bNodeTree *ntree_src);
+
+void BKE_nodetree_shading_params_eval(const struct EvaluationContext *eval_ctx,
+ struct bNodeTree *ntree_dst,
+ const struct bNodeTree *ntree_src);
+
#endif /* __BKE_NODE_H__ */
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 4d232e9ed6c..2b183906f57 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -38,6 +38,7 @@ extern "C" {
struct Base;
struct EvaluationContext;
struct Scene;
+struct ViewLayer;
struct Object;
struct BoundBox;
struct View3D;
@@ -50,7 +51,7 @@ struct HookModifierData;
struct ModifierData;
void BKE_object_workob_clear(struct Object *workob);
-void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struct Object *workob);
+void BKE_object_workob_calc_parent(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct Object *workob);
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src);
struct SoftBody *copy_softbody(const struct SoftBody *sb, const int flag);
@@ -62,7 +63,6 @@ void BKE_object_free_particlesystems(struct Object *ob);
void BKE_object_free_softbody(struct Object *ob);
void BKE_object_free_bulletsoftbody(struct Object *ob);
void BKE_object_free_curve_cache(struct Object *ob);
-void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob);
void BKE_object_free(struct Object *ob);
void BKE_object_free_derived_caches(struct Object *ob);
@@ -82,6 +82,7 @@ bool BKE_object_exists_check(struct Object *obtest);
bool BKE_object_is_in_editmode(struct Object *ob);
bool BKE_object_is_in_editmode_vgroup(struct Object *ob);
bool BKE_object_is_in_wpaint_select_vert(struct Object *ob);
+bool BKE_object_is_visible(struct Object *ob);
void BKE_object_init(struct Object *ob);
struct Object *BKE_object_add_only_object(
@@ -89,9 +90,13 @@ 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 ViewLayer *view_layer,
int type, const char *name)
- ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL;
+ ATTR_NONNULL(1, 2, 3) ATTR_RETURNS_NONNULL;
+struct Object *BKE_object_add_from(
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer,
+ int type, const char *name, struct Object *ob_src)
+ ATTR_NONNULL(1, 2, 3, 6) ATTR_RETURNS_NONNULL;
void *BKE_object_obdata_add_from_type(
struct Main *bmain,
int type, const char *name)
@@ -101,9 +106,9 @@ void BKE_object_lod_add(struct Object *ob);
void BKE_object_lod_sort(struct Object *ob);
bool BKE_object_lod_remove(struct Object *ob, int level);
void BKE_object_lod_update(struct Object *ob, const float camera_position[3]);
-bool BKE_object_lod_is_usable(struct Object *ob, struct Scene *scene);
-struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct Scene *scene);
-struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene);
+bool BKE_object_lod_is_usable(struct Object *ob, struct ViewLayer *view_layer);
+struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct ViewLayer *view_layer);
+struct Object *BKE_object_lod_matob_get(struct Object *ob, struct ViewLayer *view_layer);
void BKE_object_copy_data(struct Main *bmain, struct Object *ob_dst, const struct Object *ob_src, const int flag);
struct Object *BKE_object_copy(struct Main *bmain, const struct Object *ob);
@@ -125,11 +130,12 @@ void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4]);
bool BKE_object_pose_context_check(struct Object *ob);
struct Object *BKE_object_pose_armature_get(struct Object *ob);
-void BKE_object_get_parent_matrix(struct Scene *scene, struct Object *ob, struct Object *par, float parentmat[4][4]);
-void BKE_object_where_is_calc(struct Scene *scene, struct Object *ob);
-void BKE_object_where_is_calc_ex(struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3]);
-void BKE_object_where_is_calc_time(struct Scene *scene, struct Object *ob, float ctime);
-void BKE_object_where_is_calc_time_ex(struct Scene *scene, struct Object *ob, float ctime,
+void BKE_object_get_parent_matrix(struct Scene *scene, struct Object *ob,
+ struct Object *par, float parentmat[4][4]);
+void BKE_object_where_is_calc(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void BKE_object_where_is_calc_ex(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3]);
+void BKE_object_where_is_calc_time(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime);
+void BKE_object_where_is_calc_time_ex(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime,
struct RigidBodyWorld *rbw, float r_originmat[3][3]);
void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float obmat[4][4]);
@@ -152,8 +158,7 @@ bool BKE_object_minmax_dupli(struct Scene *scene, struct Object *ob, float r_min
void BKE_object_foreach_display_point(struct Object *ob, float obmat[4][4],
void (*func_cb)(const float[3], void *), void *user_data);
void BKE_scene_foreach_display_point(struct Scene *scene,
- struct View3D *v3d,
- const short flag,
+ struct ViewLayer *view_layer,
void (*func_cb)(const float[3], void *), void *user_data);
bool BKE_object_parent_loop_check(const struct Object *parent, const struct Object *ob);
@@ -178,41 +183,54 @@ void BKE_object_tfm_protected_restore(struct Object *ob,
const short protectflag);
/* Dependency graph evaluation callbacks. */
-void BKE_object_eval_local_transform(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_local_transform(const struct EvaluationContext *eval_ctx,
struct Object *ob);
-void BKE_object_eval_parent(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_parent(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
-void BKE_object_eval_constraints(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_constraints(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
-void BKE_object_eval_done(struct EvaluationContext *eval_ctx, struct Object *ob);
+void BKE_object_eval_done(const struct EvaluationContext *eval_ctx, struct Object *ob);
-bool BKE_object_eval_proxy_copy(struct EvaluationContext *eval_ctx,
+bool BKE_object_eval_proxy_copy(const struct EvaluationContext *eval_ct,
struct Object *object);
-void BKE_object_eval_uber_transform(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_uber_transform(const struct EvaluationContext *eval_ctx,
struct Object *ob);
-void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_uber_data(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
-void BKE_object_eval_cloth(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_cloth(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *object);
-
-void BKE_object_eval_transform_all(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_transform_all(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *object);
-void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob);
-void BKE_object_handle_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
-void BKE_object_handle_update_ex(struct EvaluationContext *eval_ctx,
- struct Scene *scene, struct Object *ob,
- struct RigidBodyWorld *rbw,
- const bool do_proxy_update);
+void BKE_object_eval_update_shading(const struct EvaluationContext *eval_ctx,
+ struct Object *object);
+void BKE_object_data_select_update(const struct EvaluationContext *eval_ctx,
+ struct ID *object_data);
+
+void BKE_object_eval_flush_base_flags(const struct EvaluationContext *eval_ctx,
+ struct Object *object, struct Base *base,
+ const bool is_from_set);
+
+void BKE_object_handle_data_update(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
+void BKE_object_handle_update(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob);
+void BKE_object_handle_update_ex(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob,
+ struct RigidBodyWorld *rbw,
+ const bool do_proxy_update);
+
void BKE_object_sculpt_modifiers_changed(struct Object *ob);
int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float **r_loc, float **r_size, float **r_rot);
@@ -255,17 +273,16 @@ typedef enum eObjectSet {
OB_SET_ALL /* All Objects */
} eObjectSet;
-struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter);
+struct LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer, 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);
bool BKE_object_modifier_use_time(struct Object *ob, struct ModifierData *md);
-bool BKE_object_modifier_update_subframe(struct Scene *scene, struct Object *ob, bool update_mesh,
- int parent_recursion, float frame,
- int type);
+bool BKE_object_modifier_update_subframe(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
+ bool update_mesh, int parent_recursion, float frame, int type);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_object_facemap.h b/source/blender/blenkernel/BKE_object_facemap.h
new file mode 100644
index 00000000000..2607e5aa2dd
--- /dev/null
+++ b/source/blender/blenkernel/BKE_object_facemap.h
@@ -0,0 +1,53 @@
+/*
+ * ***** 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): Antony Riakiotakis
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_OBJECT_FACEMAP_H__
+#define __BKE_OBJECT_FACEMAP_H__
+
+/** \file BKE_object_facemap.h
+ * \ingroup bke
+ * \brief Functions for dealing with object face-maps.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bFaceMap;
+struct ListBase;
+struct Object;
+
+struct bFaceMap *BKE_object_facemap_add(struct Object *ob);
+struct bFaceMap *BKE_object_facemap_add_name(struct Object *ob, const char *name);
+void BKE_object_facemap_remove(struct Object *ob, struct bFaceMap *fmap);
+void BKE_object_facemap_clear(struct Object *ob);
+
+int BKE_object_facemap_name_index(struct Object *ob, const char *name);
+void BKE_object_facemap_unique_name(struct Object *ob, struct bFaceMap *fmap);
+struct bFaceMap *BKE_object_facemap_find_name(struct Object *ob, const char *name);
+void BKE_object_facemap_copy_list(struct ListBase *outbase, const struct ListBase *inbase);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_OBJECT_FACEMAP_H__ */
diff --git a/source/blender/blenkernel/BKE_outliner_treehash.h b/source/blender/blenkernel/BKE_outliner_treehash.h
index 454edb40c4e..b82bc692402 100644
--- a/source/blender/blenkernel/BKE_outliner_treehash.h
+++ b/source/blender/blenkernel/BKE_outliner_treehash.h
@@ -36,8 +36,9 @@ void *BKE_outliner_treehash_create_from_treestore(struct BLI_mempool *treestore)
/* full rebuild for already allocated hashtable */
void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore);
-/* full rebuild for already allocated hashtable */
+/* Add/remove hashtable elements */
void BKE_outliner_treehash_add_element(void *treehash, struct TreeStoreElem *elem);
+void BKE_outliner_treehash_remove_element(void *treehash, struct TreeStoreElem *elem);
/* find first unused element with specific type, nr and id */
struct TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index dff7f65b39a..31f4695201c 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -52,11 +52,13 @@ struct PaletteColor;
struct PBVH;
struct ReportList;
struct Scene;
+struct ViewLayer;
struct Sculpt;
struct StrokeCache;
struct Tex;
struct ImagePool;
struct UnifiedPaintSettings;
+struct EvaluationContext;
enum eOverlayFlags;
@@ -89,8 +91,8 @@ typedef enum eOverlayControlFlags {
PAINT_OVERLAY_OVERRIDE_PRIMARY | \
PAINT_OVERLAY_OVERRIDE_CURSOR)
-void BKE_paint_invalidate_overlay_tex(struct Scene *scene, const struct Tex *tex);
-void BKE_paint_invalidate_cursor_overlay(struct Scene *scene, struct CurveMapping *curve);
+void BKE_paint_invalidate_overlay_tex(struct Scene *scene, struct ViewLayer *view_layer, const struct Tex *tex);
+void BKE_paint_invalidate_cursor_overlay(struct Scene *scene, struct ViewLayer *view_layer, struct CurveMapping *curve);
void BKE_paint_invalidate_overlay_all(void);
eOverlayControlFlags BKE_paint_get_overlay_flags(void);
void BKE_paint_reset_overlay_invalid(eOverlayControlFlags flag);
@@ -124,7 +126,7 @@ void BKE_paint_cavity_curve_preset(struct Paint *p, int preset);
short BKE_paint_object_mode_from_paint_mode(ePaintMode mode);
struct Paint *BKE_paint_get_active_from_paintmode(struct Scene *sce, ePaintMode mode);
-struct Paint *BKE_paint_get_active(struct Scene *sce);
+struct Paint *BKE_paint_get_active(struct Scene *sce, struct ViewLayer *view_layer);
struct Paint *BKE_paint_get_active_from_context(const struct bContext *C);
ePaintMode BKE_paintmode_get_active_from_context(const struct bContext *C);
struct Brush *BKE_paint_brush(struct Paint *paint);
@@ -247,8 +249,9 @@ void BKE_sculptsession_free_deformMats(struct SculptSession *ss);
void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss);
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
-void BKE_sculpt_update_mesh_elements(struct Scene *scene, struct Sculpt *sd, struct Object *ob,
- bool need_pmap, bool need_mask);
+void BKE_sculpt_update_mesh_elements(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Sculpt *sd, struct Object *ob,
+ bool need_pmap, bool need_mask);
struct MultiresModifierData *BKE_sculpt_multires_active(struct Scene *scene, struct Object *ob);
int BKE_sculpt_mask_layers_ensure(struct Object *ob,
struct MultiresModifierData *mmd);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index ddb4f9c37bd..1776872f455 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -62,6 +62,8 @@ struct RNG;
struct BVHTreeRay;
struct BVHTreeRayHit;
struct EdgeHash;
+struct EvaluationContext;
+struct ViewLayer;
#define PARTICLE_COLLISION_MAX_COLLISIONS 10
@@ -77,6 +79,7 @@ struct EdgeHash;
/* common stuff that many particle functions need */
typedef struct ParticleSimulationData {
+ const struct EvaluationContext *eval_ctx;
struct Scene *scene;
struct Object *ob;
struct ParticleSystem *psys;
@@ -294,7 +297,7 @@ void psys_set_current_num(Object *ob, int index);
struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim);
-bool psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys);
+bool psys_in_edit_mode(struct ViewLayer *view_layer, struct ParticleSystem *psys);
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, const bool use_render_params);
bool psys_check_edited(struct ParticleSystem *psys);
@@ -335,9 +338,9 @@ void psys_reset(struct ParticleSystem *psys, int mode);
void psys_find_parents(struct ParticleSimulationData *sim, const bool use_render_params);
void psys_cache_paths(struct ParticleSimulationData *sim, float cfra, const bool use_render_params);
-void psys_cache_edit_paths(struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra, const bool use_render_params);
+void psys_cache_edit_paths(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra, const bool use_render_params);
void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, const bool editupdate, const bool use_render_params);
-int do_guides(struct ParticleSettings *part, struct ListBase *effectors, ParticleKey *state, int pa_num, float time);
+int do_guides(const struct EvaluationContext *eval_ctx, struct ParticleSettings *part, struct ListBase *effectors, ParticleKey *state, int pa_num, float time);
void precalc_guides(struct ParticleSimulationData *sim, struct ListBase *effectors);
float psys_get_timestep(struct ParticleSimulationData *sim);
float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime);
@@ -369,7 +372,7 @@ void psys_tasks_create(struct ParticleThreadContext *ctx, int startpart, int end
void psys_tasks_free(struct ParticleTask *tasks, int numtasks);
void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
-void psys_apply_hair_lattice(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
+void psys_apply_hair_lattice(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
/* particle_system.c */
struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt);
@@ -384,7 +387,7 @@ void psys_check_boid_data(struct ParticleSystem *psys);
void psys_get_birth_coords(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, float dtime, float cfra);
-void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, const bool use_render_params);
+void particle_system_update(const struct EvaluationContext *eval_ctx, 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 cb_flag);
@@ -476,8 +479,20 @@ typedef struct ParticleRenderData {
struct EvaluationContext;
-void BKE_particle_system_eval_init(struct EvaluationContext *eval_ctx,
+void BKE_particle_system_settings_eval(const struct EvaluationContext *eval_ctx,
+ struct ParticleSystem *psys);
+void BKE_particle_system_settings_recalc_clear(struct EvaluationContext *UNUSED(eval_ctx),
+ struct ParticleSettings *particle_settings);
+
+void BKE_particle_system_eval_init(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
#endif
+
+/* Draw Cache */
+enum {
+ BKE_PARTICLE_BATCH_DIRTY_ALL = 0,
+};
+void BKE_particle_batch_cache_dirty(struct ParticleSystem *psys, int mode);
+void BKE_particle_batch_cache_free(struct ParticleSystem *psys);
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 2daa2ef7182..9aea5dc95a0 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -30,6 +30,7 @@
#include "BLI_ghash.h"
#include "BLI_utildefines.h"
+struct Gwn_Batch;
struct CCGElem;
struct CCGKey;
struct CCGDerivedMesh;
@@ -132,6 +133,9 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data);
void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
int (*setMaterial)(int matnr, void *attribs), bool wireframe, bool fast);
void BKE_pbvh_draw_BB(PBVH *bvh);
+void BKE_pbvh_draw_cb(
+ PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast,
+ void (*draw_fn)(void *user_data, struct Gwn_Batch *batch), void *user_data);
/* PBVH Access */
typedef enum {
@@ -369,6 +373,7 @@ bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node);
//void BKE_pbvh_node_BB_reset(PBVHNode *node);
//void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
+bool pbvh_has_mask(PBVH *bvh);
void pbvh_show_diffuse_color_set(PBVH *bvh, bool show_diffuse_color);
#endif /* __BKE_PBVH_H__ */
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index f0819c8d79d..9a5a9e9e56a 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -90,6 +90,7 @@ struct ParticleKey;
struct ParticleSystem;
struct PointCache;
struct Scene;
+struct ViewLayer;
struct SmokeModifierData;
struct SoftBody;
struct RigidBodyWorld;
@@ -186,6 +187,8 @@ typedef struct PTCacheID {
typedef struct PTCacheBaker {
struct Main *main;
struct Scene *scene;
+ struct ViewLayer *view_layer;
+ struct Depsgraph *depsgraph;
int bake;
int render;
int anim_init;
@@ -319,7 +322,7 @@ struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const st
/********************** Baking *********************/
/* Bakes cache with cache_step sized jumps in time, not accurate but very fast. */
-void BKE_ptcache_quick_cache_all(struct Main *bmain, struct Scene *scene);
+void BKE_ptcache_quick_cache_all(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer);
/* Bake cache or simulate to current frame with settings defined in the baker. */
void BKE_ptcache_bake(struct PTCacheBaker *baker);
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index 3c7274ca3c5..6aa43665427 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -37,6 +37,7 @@
struct RigidBodyWorld;
struct RigidBodyOb;
+struct EvaluationContext;
struct Scene;
struct Object;
@@ -99,21 +100,19 @@ void BKE_rigidbody_aftertrans_update(struct Object *ob, float loc[3], float rot[
void BKE_rigidbody_sync_transforms(struct RigidBodyWorld *rbw, struct Object *ob, float ctime);
bool BKE_rigidbody_check_sim_running(struct RigidBodyWorld *rbw, float ctime);
void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw);
-void BKE_rigidbody_rebuild_world(struct Scene *scene, float ctime);
-void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime);
+void BKE_rigidbody_rebuild_world(const struct EvaluationContext *eval_ctx, struct Scene *scene, float ctime);
+void BKE_rigidbody_do_simulation(const struct EvaluationContext *eval_ctx, struct Scene *scene, float ctime);
/* -------------------- */
/* Depsgraph evaluation */
-struct EvaluationContext;
-
-void BKE_rigidbody_rebuild_sim(struct EvaluationContext *eval_ctx,
+void BKE_rigidbody_rebuild_sim(const struct EvaluationContext *eval_ctx,
struct Scene *scene);
-void BKE_rigidbody_eval_simulation(struct EvaluationContext *eval_ctx,
+void BKE_rigidbody_eval_simulation(const struct EvaluationContext *eval_ctx,
struct Scene *scene);
-void BKE_rigidbody_object_sync_transforms(struct EvaluationContext *eval_ctx,
+void BKE_rigidbody_object_sync_transforms(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 481aff3cfa6..bb435df136d 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -38,43 +38,55 @@ extern "C" {
#endif
struct AviCodecData;
-struct Base;
+struct Depsgraph;
struct EvaluationContext;
struct Main;
struct Object;
struct RenderData;
-struct SceneRenderLayer;
struct Scene;
+struct SceneCollection;
+struct ViewLayer;
struct UnitSettings;
-struct Main;
+struct ViewRender;
+struct WorkSpace;
-#define SCE_COPY_NEW 0
-#define SCE_COPY_EMPTY 1
-#define SCE_COPY_LINK_OB 2
-#define SCE_COPY_LINK_DATA 3
-#define SCE_COPY_FULL 4
+typedef enum eSceneCopyMethod {
+ SCE_COPY_NEW = 0,
+ SCE_COPY_EMPTY = 1,
+ SCE_COPY_LINK_OB = 2,
+ SCE_COPY_LINK_DATA = 3,
+ SCE_COPY_FULL = 4,
+} eSceneCopyMethod;
/* Use as the contents of a 'for' loop: for (SETLOOPER(...)) { ... */
#define SETLOOPER(_sce_basis, _sce_iter, _base) \
- _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, NULL); \
+ _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, BKE_view_layer_from_scene_get(_sce_basis), NULL); \
+ _base; \
+ _base = _setlooper_base_step(&_sce_iter, NULL, _base)
+
+#define SETLOOPER_VIEW_LAYER(_sce_basis, _view_layer, _sce_iter, _base) \
+ _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, _view_layer, NULL); \
_base; \
- _base = _setlooper_base_step(&_sce_iter, _base)
+ _base = _setlooper_base_step(&_sce_iter, NULL, _base)
-struct Base *_setlooper_base_step(struct Scene **sce_iter, struct Base *base);
+#define SETLOOPER_SET_ONLY(_sce_basis, _sce_iter, _base) \
+ _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, NULL, NULL); \
+ _base; \
+ _base = _setlooper_base_step(&_sce_iter, NULL, _base)
+
+struct Base *_setlooper_base_step(struct Scene **sce_iter, struct ViewLayer *view_layer, struct Base *base);
void free_avicodecdata(struct AviCodecData *acd);
+void BKE_scene_free_ex(struct Scene *sce, const bool do_id_user);
void BKE_scene_free(struct Scene *sce);
void BKE_scene_init(struct Scene *sce);
struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
-/* base functions */
-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);
-void BKE_scene_base_deselect_all(struct Scene *sce);
-void BKE_scene_base_select(struct Scene *sce, struct Base *selbase);
+void BKE_scene_remove_rigidbody_object(struct Scene *scene, struct Object *ob);
+
+bool BKE_scene_object_find(struct Scene *scene, struct Object *ob);
+struct Object *BKE_scene_object_find_by_name(struct Scene *scene, const char *name);
/* Scene base iteration function.
* Define struct here, so no need to bother with alloc/free it.
@@ -87,11 +99,14 @@ typedef struct SceneBaseIter {
int phase;
} 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);
+int BKE_scene_base_iter_next(
+ const struct EvaluationContext *eval_ctx, struct SceneBaseIter *iter,
+ struct Scene **scene, int val, struct Base **base, struct Object **ob);
-void BKE_scene_base_flag_to_objects(struct Scene *scene);
+void BKE_scene_base_flag_to_objects(struct ViewLayer *view_layer);
void BKE_scene_base_flag_from_objects(struct Scene *scene);
+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);
@@ -102,7 +117,8 @@ void BKE_scene_groups_relink(struct Scene *sce);
void BKE_scene_make_local(struct Main *bmain, struct Scene *sce, const bool lib_local);
-struct Object *BKE_scene_camera_find(struct Scene *sc);
+struct Scene *BKE_scene_find_from_collection(const struct Main *bmain, const struct SceneCollection *scene_collection);
+
#ifdef DURIAN_CAMERA_SWITCH
struct Object *BKE_scene_camera_switch_find(struct Scene *scene); // DURIAN_CAMERA_SWITCH
#endif
@@ -119,12 +135,18 @@ float BKE_scene_frame_get_from_ctime(const struct Scene *scene, const float fram
void BKE_scene_frame_set(struct Scene *scene, double cfra);
/* ** Scene evaluation ** */
-void BKE_scene_update_tagged(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce);
-void BKE_scene_update_for_newframe(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, unsigned int lay);
-void BKE_scene_update_for_newframe_ex(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, unsigned int lay, bool do_invisible_flush);
-struct SceneRenderLayer *BKE_scene_add_render_layer(struct Scene *sce, const char *name);
-bool BKE_scene_remove_render_layer(struct Main *main, struct Scene *scene, struct SceneRenderLayer *srl);
+void BKE_scene_graph_update_tagged(struct EvaluationContext *eval_ctx,
+ struct Depsgraph *depsgraph,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
+
+void BKE_scene_graph_update_for_newframe(struct EvaluationContext *eval_ctx,
+ struct Depsgraph *depsgraph,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char *name);
bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv);
@@ -142,6 +164,7 @@ bool BKE_scene_use_spherical_stereo(struct Scene *scene);
bool BKE_scene_uses_blender_internal(const struct Scene *scene);
bool BKE_scene_uses_blender_game(const struct Scene *scene);
+bool BKE_scene_uses_blender_eevee(const struct Scene *scene);
void BKE_scene_disable_color_management(struct Scene *scene);
bool BKE_scene_check_color_management_enabled(const struct Scene *scene);
@@ -152,6 +175,22 @@ int BKE_render_num_threads(const struct RenderData *r);
int BKE_render_preview_pixel_size(const struct RenderData *r);
+/**********************************/
+
+struct ViewRender *BKE_viewrender_get(struct Scene *scene, struct WorkSpace *workspace);
+void BKE_viewrender_init(struct ViewRender *view_render);
+void BKE_viewrender_free(struct ViewRender *view_render);
+void BKE_viewrender_copy(struct ViewRender *view_render_dst, const struct ViewRender *view_render_src);
+bool BKE_viewrender_use_new_shading_nodes(const struct ViewRender *view_render);
+bool BKE_viewrender_use_shading_nodes_custom(const struct ViewRender *view_render);
+bool BKE_viewrender_use_world_space_shading(const struct ViewRender *view_render);
+bool BKE_viewrender_use_spherical_stereo(const struct ViewRender *view_render);
+bool BKE_viewrender_uses_blender_internal(const struct ViewRender *view_render);
+bool BKE_viewrender_uses_blender_game(const struct ViewRender *view_render);
+bool BKE_viewrender_uses_blender_eevee(const struct ViewRender *view_render);
+
+/**********************************/
+
double BKE_scene_unit_scale(const struct UnitSettings *unit, const int unit_type, double value);
/* multiview */
@@ -171,6 +210,13 @@ void BKE_scene_multiview_view_prefix_get(struct Scene *scene, const char
void BKE_scene_multiview_videos_dimensions_get(const struct RenderData *rd, const size_t width, const size_t height, size_t *r_width, size_t *r_height);
int BKE_scene_multiview_num_videos_get(const struct RenderData *rd);
+/* depsgraph */
+void BKE_scene_allocate_depsgraph_hash(struct Scene *scene);
+void BKE_scene_ensure_depsgraph_hash(struct Scene *scene);
+void BKE_scene_free_depsgraph_hash(struct Scene *scene);
+
+struct Depsgraph *BKE_scene_get_depsgraph(struct Scene *scene, struct ViewLayer *view_layer, bool allocate);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 14e978b23f2..6669f3103da 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -42,6 +42,7 @@ struct Panel;
struct Scene;
struct ScrArea;
struct SpaceType;
+struct TransformOrientation;
struct View3D;
struct bContext;
struct bContextDataResult;
@@ -49,10 +50,13 @@ struct bScreen;
struct uiLayout;
struct uiList;
struct wmKeyConfig;
+struct wmManipulatorMap;
struct wmNotifier;
struct wmWindow;
struct wmWindowManager;
+struct WorkSpace;
struct GPUFXSettings;
+struct wmMsgBus;
#include "BLI_compiler_attrs.h"
@@ -81,7 +85,9 @@ typedef struct SpaceType {
/* exit is called when the area is hidden or removed */
void (*exit)(struct wmWindowManager *, struct ScrArea *);
/* Listeners can react to bContext changes */
- void (*listener)(struct bScreen *sc, struct ScrArea *, struct wmNotifier *);
+ void (*listener)(struct bScreen *sc, struct ScrArea *,
+ struct wmNotifier *, struct Scene *scene,
+ struct WorkSpace *workspace);
/* refresh context, called after filereads, ED_area_tag_refresh() */
void (*refresh)(const struct bContext *, struct ScrArea *);
@@ -96,6 +102,9 @@ typedef struct SpaceType {
/* on startup, define dropboxes for spacetype+regions */
void (*dropboxes)(void);
+ /* initialize manipulator-map-types and manipulator-group-types with the region */
+ void (*manipulators)(void);
+
/* return context data */
int (*context)(const struct bContext *, const char *, struct bContextDataResult *);
@@ -129,8 +138,15 @@ typedef struct ARegionType {
/* draw entirely, view changes should be handled here */
void (*draw)(const struct bContext *, struct ARegion *);
/* contextual changes should be handled here */
- void (*listener)(struct bScreen *sc, struct ScrArea *, struct ARegion *, struct wmNotifier *);
-
+ void (*listener)(struct bScreen *, struct ScrArea *, struct ARegion *,
+ struct wmNotifier *, const struct Scene *scene);
+ /* Optional callback to generate subscriptions. */
+ void (*message_subscribe)(
+ const struct bContext *C,
+ struct WorkSpace *workspace, struct Scene *scene,
+ struct bScreen *sc, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus);
+
void (*free)(struct ARegion *);
/* split region, copy data optionally */
@@ -284,6 +300,9 @@ void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID
struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar);
void BKE_screen_area_free(struct ScrArea *sa);
+/* Manipulator-maps of a region need to be freed with the region. Uses callback to avoid low-level call. */
+void BKE_region_callback_free_manipulatormap_set(void (*callback)(struct wmManipulatorMap *));
+void BKE_region_callback_refresh_tag_manipulatormap_set(void (*callback)(struct wmManipulatorMap *));
struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
@@ -299,12 +318,16 @@ unsigned int BKE_screen_view3d_layer_active(
unsigned int BKE_screen_view3d_layer_all(const struct bScreen *sc) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void BKE_screen_manipulator_tag_refresh(struct bScreen *sc);
+
void BKE_screen_view3d_sync(struct View3D *v3d, struct Scene *scene);
-void BKE_screen_view3d_scene_sync(struct bScreen *sc);
-void BKE_screen_view3d_main_sync(ListBase *screen_lb, struct Scene *scene);
-void BKE_screen_view3d_twmode_remove(struct View3D *v3d, const int i);
-void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, struct Scene *scene, const int i);
+void BKE_screen_view3d_scene_sync(struct bScreen *sc, struct Scene *scene);
+void BKE_screen_transform_orientation_remove(
+ const struct bScreen *screen, const struct WorkSpace *workspace,
+ const struct TransformOrientation *orientation) ATTR_NONNULL();
void BKE_screen_gpu_fx_validate(struct GPUFXSettings *fx_settings);
+bool BKE_screen_is_fullscreen_area(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BKE_screen_is_used(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* zoom factor conversion */
float BKE_screen_view3d_zoom_to_fac(float camzoom);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 6c9dc12b44f..2264167eca1 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -432,7 +432,8 @@ enum {
};
typedef struct ImBuf *(*SequencerDrawView)(
- struct Scene *scene, struct Object *camera, int width, int height,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct ViewLayer *view_layer, struct Object *camera, int width, int height,
unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode,
int samples, const char *viewname,
struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h
index 20366f00df6..64d70e8e209 100644
--- a/source/blender/blenkernel/BKE_smoke.h
+++ b/source/blender/blenkernel/BKE_smoke.h
@@ -35,7 +35,9 @@
typedef float (*bresenham_callback)(float *result, float *input, int res[3], int *pixel, float *tRay, float correct);
-struct DerivedMesh *smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm);
+struct DerivedMesh *smokeModifier_do(struct SmokeModifierData *smd, const struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob, struct DerivedMesh *dm);
void smoke_reallocate_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old);
void smoke_reallocate_highres_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old);
diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h
index 486fe8ed5a8..e2255bdb779 100644
--- a/source/blender/blenkernel/BKE_softbody.h
+++ b/source/blender/blenkernel/BKE_softbody.h
@@ -34,6 +34,7 @@
struct Object;
struct Scene;
struct SoftBody;
+struct EvaluationContext;
typedef struct BodyPoint {
float origS[3], origE[3], origT[3], pos[3], vec[3], force[3];
@@ -59,7 +60,8 @@ extern void sbFree(struct SoftBody *sb);
extern void sbFreeSimulation(struct SoftBody *sb);
/* do one simul step, reading and writing vertex locs from given array */
-extern void sbObjectStep(struct Scene *scene, struct Object *ob, float framnr, float (*vertexCos)[3], int numVerts);
+extern void sbObjectStep(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
+ float framnr, float (*vertexCos)[3], int numVerts);
/* makes totally fresh start situation, resets time */
extern void sbObjectToSoftbody(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index 6f8274fabc8..98fb4f47339 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -35,8 +35,8 @@
#define SOUND_WAVE_SAMPLES_PER_SECOND 250
-#ifdef WITH_SYSTEM_AUDASPACE
-# include AUD_DEVICE_H
+#if defined(WITH_AUDASPACE)
+# include <AUD_Device.h>
#endif
struct bSound;
@@ -84,7 +84,7 @@ void BKE_sound_copy_data(struct Main *bmain, struct bSound *sound_dst, const str
void BKE_sound_make_local(struct Main *bmain, struct bSound *sound, const bool lib_local);
-#if defined(__AUD_C_API_H__) || defined(WITH_SYSTEM_AUDASPACE)
+#if defined(WITH_AUDASPACE)
AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume);
#endif
@@ -149,6 +149,4 @@ float BKE_sound_get_length(struct bSound *sound);
char **BKE_sound_get_device_names(void);
-bool BKE_sound_is_jack_supported(void);
-
#endif /* __BKE_SOUND_H__ */
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index d05ed1800fb..b4ca1b79238 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -47,6 +47,7 @@ struct MovieDistortion;
struct Camera;
struct Object;
struct Scene;
+struct EvaluationContext;
struct rcti;
/* **** Common functions **** */
diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h
new file mode 100644
index 00000000000..9f989f7ae8f
--- /dev/null
+++ b/source/blender/blenkernel/BKE_workspace.h
@@ -0,0 +1,155 @@
+/*
+ * ***** 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 BKE_workspace.h
+ * \ingroup bke
+ */
+
+#ifndef __BKE_WORKSPACE_H__
+#define __BKE_WORKSPACE_H__
+
+#include "BLI_compiler_attrs.h"
+
+struct bScreen;
+struct EvaluationContext;
+struct Main;
+struct Scene;
+struct TransformOrientation;
+struct ViewLayer;
+
+/**
+ * Plan is to store the object-mode per workspace, not per object anymore.
+ * However, there's quite some work to be done for that, so for now, there is just a basic
+ * implementation of an object <-> workspace object-mode syncing for testing, with some known
+ * problems. Main problem being that the modes can get out of sync when changing object selection.
+ * Would require a pile of temporary changes to always sync modes when changing selection. So just
+ * leaving this here for some testing until object-mode is really a workspace level setting.
+ */
+#define USE_WORKSPACE_MODE
+
+
+/* -------------------------------------------------------------------- */
+/* Create, delete, init */
+
+struct WorkSpace *BKE_workspace_add(struct Main *bmain, const char *name);
+void BKE_workspace_free(struct WorkSpace *workspace);
+void BKE_workspace_remove(struct Main *bmain, struct WorkSpace *workspace);
+
+struct WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const struct Main *bmain);
+void BKE_workspace_instance_hook_free(const struct Main *bmain, struct WorkSpaceInstanceHook *hook);
+
+struct WorkSpaceLayout *BKE_workspace_layout_add(
+ struct WorkSpace *workspace,
+ struct bScreen *screen,
+ const char *name) ATTR_NONNULL();
+void BKE_workspace_layout_remove(
+ struct Main *bmain,
+ struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL();
+
+void BKE_workspace_relations_free(
+ ListBase *relation_list);
+
+
+/* -------------------------------------------------------------------- */
+/* General Utils */
+
+void BKE_workspace_view_layer_remove_references(
+ const struct Main *bmain,
+ const struct ViewLayer *view_layer) ATTR_NONNULL();
+
+void BKE_workspace_transform_orientation_remove(
+ struct WorkSpace *workspace, struct TransformOrientation *orientation) ATTR_NONNULL();
+struct TransformOrientation *BKE_workspace_transform_orientation_find(
+ const struct WorkSpace *workspace, const int index) ATTR_NONNULL();
+int BKE_workspace_transform_orientation_get_index(
+ const struct WorkSpace *workspace, const struct TransformOrientation *orientation) ATTR_NONNULL();
+
+struct WorkSpaceLayout *BKE_workspace_layout_find(
+ const struct WorkSpace *workspace, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+struct WorkSpaceLayout *BKE_workspace_layout_find_global(
+ const struct Main *bmain, const struct bScreen *screen,
+ struct WorkSpace **r_workspace) ATTR_NONNULL(1, 2);
+
+struct WorkSpaceLayout *BKE_workspace_layout_iter_circular(
+ const struct WorkSpace *workspace, struct WorkSpaceLayout *start,
+ bool (*callback)(const struct WorkSpaceLayout *layout, void *arg),
+ void *arg, const bool iter_backward);
+
+
+/* -------------------------------------------------------------------- */
+/* Getters/Setters */
+
+#define GETTER_ATTRS ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
+#define SETTER_ATTRS ATTR_NONNULL(1)
+
+struct WorkSpace *BKE_workspace_active_get(struct WorkSpaceInstanceHook *hook) GETTER_ATTRS;
+void BKE_workspace_active_set(struct WorkSpaceInstanceHook *hook, struct WorkSpace *workspace) SETTER_ATTRS;
+struct WorkSpaceLayout *BKE_workspace_active_layout_get(const struct WorkSpaceInstanceHook *hook) GETTER_ATTRS;
+void BKE_workspace_active_layout_set(struct WorkSpaceInstanceHook *hook, struct WorkSpaceLayout *layout) SETTER_ATTRS;
+struct bScreen *BKE_workspace_active_screen_get(const struct WorkSpaceInstanceHook *hook) GETTER_ATTRS;
+void BKE_workspace_active_screen_set(
+ struct WorkSpaceInstanceHook *hook, struct WorkSpace *workspace, struct bScreen *screen) SETTER_ATTRS;
+#ifdef USE_WORKSPACE_MODE
+enum eObjectMode BKE_workspace_object_mode_get(
+ const struct WorkSpace *workspace,
+ const struct Scene *scene) GETTER_ATTRS;
+void BKE_workspace_object_mode_set(
+ struct WorkSpace *workspace,
+ struct Scene *scene,
+ const enum eObjectMode mode) SETTER_ATTRS;
+#endif
+struct Base *BKE_workspace_active_base_get(const struct WorkSpace *workspace, const struct Scene *scene);
+struct ListBase *BKE_workspace_transform_orientations_get(struct WorkSpace *workspace) GETTER_ATTRS;
+struct ViewLayer *BKE_workspace_view_layer_get(
+ const struct WorkSpace *workspace,
+ const struct Scene *scene) GETTER_ATTRS;
+void BKE_workspace_view_layer_set(
+ struct WorkSpace *workspace,
+ struct ViewLayer *layer,
+ struct Scene *scene) SETTER_ATTRS;
+struct ListBase *BKE_workspace_layouts_get(struct WorkSpace *workspace) GETTER_ATTRS;
+
+const char *BKE_workspace_layout_name_get(const struct WorkSpaceLayout *layout) GETTER_ATTRS;
+void BKE_workspace_layout_name_set(
+ struct WorkSpace *workspace, struct WorkSpaceLayout *layout, const char *new_name) ATTR_NONNULL();
+struct bScreen *BKE_workspace_layout_screen_get(const struct WorkSpaceLayout *layout) GETTER_ATTRS;
+void BKE_workspace_layout_screen_set(struct WorkSpaceLayout *layout, struct bScreen *screen) SETTER_ATTRS;
+
+struct WorkSpaceLayout *BKE_workspace_hook_layout_for_workspace_get(
+ const struct WorkSpaceInstanceHook *hook, const struct WorkSpace *workspace) GETTER_ATTRS;
+void BKE_workspace_hook_layout_for_workspace_set(
+ struct WorkSpaceInstanceHook *hook, struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL();
+
+struct ViewRender *BKE_workspace_view_render_get(struct WorkSpace *workspace) GETTER_ATTRS;
+
+/* flags */
+bool BKE_workspace_use_scene_settings_get(const struct WorkSpace *workspace) GETTER_ATTRS;
+void BKE_workspace_use_scene_settings_set(struct WorkSpace *workspace, bool value) SETTER_ATTRS;
+
+/* Update / evaluate */
+void BKE_workspace_update_tagged(struct EvaluationContext *eval_ctx,
+ struct Main *bmain,
+ struct WorkSpace *workspace,
+ struct Scene *scene);
+
+#undef GETTER_ATTRS
+#undef SETTER_ATTRS
+
+#endif /* __BKE_WORKSPACE_H__ */
diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h
index 2a811496bb9..ea0cd125b06 100644
--- a/source/blender/blenkernel/BKE_world.h
+++ b/source/blender/blenkernel/BKE_world.h
@@ -44,5 +44,11 @@ struct World *BKE_world_copy(struct Main *bmain, const struct World *wrld);
struct World *localize_world(struct World *wrld);
void BKE_world_make_local(struct Main *bmain, struct World *wrld, const bool lib_local);
+/* Evaluation. */
+
+struct EvaluationContext;
+
+void BKE_world_eval(const struct EvaluationContext *eval_ctx, struct World *world);
+
#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 3fc2c3f8eb0..279068c440e 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../blenloader
../blentranslation
../depsgraph
+ ../draw
../gpu
../ikplugin
../imbuf
@@ -86,6 +87,7 @@ set(SRC
intern/camera.c
intern/cdderivedmesh.c
intern/cloth.c
+ intern/collection.c
intern/collision.c
intern/colorband.c
intern/colortools.c
@@ -98,12 +100,12 @@ set(SRC
intern/customdata_file.c
intern/data_transfer.c
intern/deform.c
- intern/depsgraph.c
intern/displist.c
intern/dynamicpaint.c
intern/editderivedmesh.c
intern/editmesh.c
intern/editmesh_bvh.c
+ intern/editmesh_tangent.c
intern/effect.c
intern/fcurve.c
intern/fluidsim.c
@@ -123,6 +125,7 @@ set(SRC
intern/lattice.c
intern/library.c
intern/library_idmap.c
+ intern/library_override.c
intern/library_query.c
intern/library_remap.c
intern/linestyle.c
@@ -136,6 +139,7 @@ set(SRC
intern/mesh_evaluate.c
intern/mesh_mapping.c
intern/mesh_remap.c
+ intern/mesh_tangent.c
intern/mesh_validate.c
intern/modifier.c
intern/modifiers_bmesh.c
@@ -144,6 +148,7 @@ set(SRC
intern/nla.c
intern/node.c
intern/object.c
+ intern/object_facemap.c
intern/object_deform.c
intern/object_dupli.c
intern/object_update.c
@@ -159,6 +164,8 @@ set(SRC
intern/pbvh_bmesh.c
intern/pointcache.c
intern/property.c
+ intern/layer.c
+ intern/lightprobe.c
intern/report.c
intern/rigidbody.c
intern/sca.c
@@ -187,6 +194,7 @@ set(SRC
intern/tracking_stabilize.c
intern/tracking_util.c
intern/unit.c
+ intern/workspace.c
intern/world.c
intern/writeavi.c
intern/writeframeserver.c
@@ -216,6 +224,7 @@ set(SRC
BKE_ccg.h
BKE_cdderivedmesh.h
BKE_cloth.h
+ BKE_collection.h
BKE_collision.h
BKE_colorband.h
BKE_colortools.h
@@ -227,11 +236,11 @@ set(SRC
BKE_customdata_file.h
BKE_data_transfer.h
BKE_deform.h
- BKE_depsgraph.h
BKE_displist.h
BKE_dynamicpaint.h
BKE_editmesh.h
BKE_editmesh_bvh.h
+ BKE_editmesh_tangent.h
BKE_effect.h
BKE_fcurve.h
BKE_fluidsim.h
@@ -250,6 +259,7 @@ set(SRC
BKE_lattice.h
BKE_library.h
BKE_library_idmap.h
+ BKE_library_override.h
BKE_library_query.h
BKE_library_remap.h
BKE_linestyle.h
@@ -261,12 +271,14 @@ set(SRC
BKE_mesh.h
BKE_mesh_mapping.h
BKE_mesh_remap.h
+ BKE_mesh_tangent.h
BKE_modifier.h
BKE_movieclip.h
BKE_multires.h
BKE_nla.h
BKE_node.h
BKE_object.h
+ BKE_object_facemap.h
BKE_object_deform.h
BKE_ocean.h
BKE_outliner_treehash.h
@@ -276,6 +288,8 @@ set(SRC
BKE_pbvh.h
BKE_pointcache.h
BKE_property.h
+ BKE_layer.h
+ BKE_lightprobe.h
BKE_report.h
BKE_rigidbody.h
BKE_sca.h
@@ -294,11 +308,11 @@ set(SRC
BKE_texture.h
BKE_tracking.h
BKE_unit.h
+ BKE_workspace.h
BKE_world.h
BKE_writeavi.h
BKE_writeframeserver.h
- depsgraph_private.h
nla_private.h
tracking_private.h
intern/CCGSubSurf.h
@@ -324,7 +338,7 @@ if(WIN32)
endif()
if(WITH_AUDASPACE)
- add_definitions(${AUDASPACE_DEFINITIONS})
+ add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
@@ -412,6 +426,10 @@ if(WITH_PYTHON)
)
add_definitions(-DWITH_PYTHON)
+ if(WITH_PYTHON_SAFETY)
+ add_definitions(-DWITH_PYTHON_SAFETY)
+ endif()
+
if(WITH_PYTHON_SECURITY)
add_definitions(-DWITH_PYTHON_SECURITY)
endif()
@@ -528,8 +546,4 @@ endif()
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
#endif()
-if(WITH_LEGACY_DEPSGRAPH)
- add_definitions(-DWITH_LEGACY_DEPSGRAPH)
-endif()
-
blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h
deleted file mode 100644
index 69ca75836d9..00000000000
--- a/source/blender/blenkernel/depsgraph_private.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2004 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/depsgraph_private.h
- * \ingroup bke
- */
-
-#ifndef __DEPSGRAPH_PRIVATE_H__
-#define __DEPSGRAPH_PRIVATE_H__
-
-#include "BKE_depsgraph.h"
-#include "DNA_constraint_types.h"
-#include "BKE_constraint.h"
-
-struct Scene;
-struct Group;
-struct EffectorWeights;
-struct ModifierData;
-
-/* **** DAG relation types *** */
-
-/* scene link to object */
-#define DAG_RL_SCENE (1 << 0)
-/* object link to data */
-#define DAG_RL_DATA (1 << 1)
-
-/* object changes object (parent, track, constraints) */
-#define DAG_RL_OB_OB (1 << 2)
-/* object changes obdata (hooks, constraints) */
-#define DAG_RL_OB_DATA (1 << 3)
-/* data changes object (vertex parent) */
-#define DAG_RL_DATA_OB (1 << 4)
-/* data changes data (deformers) */
-#define DAG_RL_DATA_DATA (1 << 5)
-
-#define DAG_NO_RELATION (1 << 6)
-
-#define DAG_RL_ALL_BUT_DATA (DAG_RL_SCENE | DAG_RL_OB_OB | DAG_RL_OB_DATA | DAG_RL_DATA_OB | DAG_RL_DATA_DATA)
-#define DAG_RL_ALL (DAG_RL_ALL_BUT_DATA | DAG_RL_DATA)
-
-
-#define DAGQUEUEALLOC 50
-
-enum {
- DAG_WHITE = 0,
- DAG_GRAY = 1,
- DAG_BLACK = 2
-};
-
-typedef struct DagAdjList {
- struct DagNode *node;
- short type;
- int count; /* number of identical arcs */
- unsigned int lay; // for flushing redraw/rebuild events
- const char *name;
- struct DagAdjList *next;
-} DagAdjList;
-
-
-typedef struct DagNode {
- int color;
- short type;
- float x, y, k;
- void *ob;
- void *first_ancestor;
- int ancestor_count;
- unsigned int lay; /* accumulated layers of its relations + itself */
- unsigned int scelay; /* layers due to being in scene */
- uint64_t customdata_mask; /* customdata mask */
- int lasttime; /* if lasttime != DagForest->time, this node was not evaluated yet for flushing */
- int BFS_dist; /* BFS distance */
- int DFS_dist; /* DFS distance */
- int DFS_dvtm; /* DFS discovery time */
- int DFS_fntm; /* DFS Finishing time */
- struct DagAdjList *child;
- struct DagAdjList *parent;
- struct DagNode *next;
-
- /* Threaded evaluation routines */
- uint32_t num_pending_parents; /* number of parents which are not updated yet
- * this node has got.
- * Used by threaded update for faster detect whether node could be
- * updated aready.
- */
- bool scheduled;
-
- /* Runtime flags mainly used to determine which extra data is to be evaluated
- * during object_handle_update(). Such an extra data is what depends on the
- * DAG topology, meaning this flags indicates the data evaluation of which
- * depends on the node dependencies.
- */
- short eval_flags;
-} DagNode;
-
-typedef struct DagNodeQueueElem {
- struct DagNode *node;
- struct DagNodeQueueElem *next;
-} DagNodeQueueElem;
-
-typedef struct DagNodeQueue {
- DagNodeQueueElem *first;
- DagNodeQueueElem *last;
- int count;
- int maxlevel;
- struct DagNodeQueue *freenodes;
-} DagNodeQueue;
-
-/* forest as we may have more than one DAG unconnected */
-typedef struct DagForest {
- ListBase DagNode;
- struct GHash *nodeHash;
- int numNodes;
- bool is_acyclic;
- int time; /* for flushing/tagging, compare with node->lasttime */
- bool ugly_hack_sorry; /* prevent type check */
- bool need_update;
-} DagForest;
-
-// queue operations
-DagNodeQueue *queue_create(int slots);
-void queue_raz(DagNodeQueue *queue);
-void push_queue(DagNodeQueue *queue, DagNode *node);
-void push_stack(DagNodeQueue *queue, DagNode *node);
-DagNode *pop_queue(DagNodeQueue *queue);
-DagNode *get_top_node_queue(DagNodeQueue *queue);
-void queue_delete(DagNodeQueue *queue);
-
-// Dag management
-DagForest *dag_init(void);
-DagForest *build_dag(struct Main *bmain, struct Scene *sce, short mask);
-void free_forest(struct DagForest *Dag);
-DagNode *dag_find_node(DagForest *forest, void *fob);
-DagNode *dag_add_node(DagForest *forest, void *fob);
-DagNode *dag_get_node(DagForest *forest, void *fob);
-DagNode *dag_get_sub_node(DagForest *forest, void *fob);
-void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name);
-
-typedef bool (*DagCollobjFilterFunction)(struct Object *obj, struct ModifierData *md);
-
-void dag_add_collision_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name);
-void dag_add_forcefield_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct EffectorWeights *eff, bool add_absorption, int skip_forcefield, const char *name);
-
-void graph_print_queue(DagNodeQueue *nqueue);
-void graph_print_queue_dist(DagNodeQueue *nqueue);
-void graph_print_adj_list(DagForest *dag);
-
-#endif /* __DEPSGRAPH_PRIVATE_H__ */
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 792e9195f12..68bcfa878ac 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -42,7 +42,7 @@
# include "opensubdiv_converter_capi.h"
#endif
-#include "GL/glew.h"
+#include "GPU_glew.h"
/***/
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
index f568bb94ac5..c26112d3724 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
@@ -43,7 +43,7 @@
#include "opensubdiv_capi.h"
#include "opensubdiv_converter_capi.h"
-#include "GL/glew.h"
+#include "GPU_glew.h"
#include "GPU_extensions.h"
#define OSD_LOG if (false) printf
@@ -995,7 +995,7 @@ void ccgSubSurf__sync_subdivUvs(CCGSubSurf *ss, bool subdiv_uvs)
void BKE_subsurf_osd_init(void)
{
- openSubdiv_init(GPU_legacy_support());
+ openSubdiv_init();
BLI_spin_init(&delete_spin);
}
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 7ccd00b3f62..01340b97807 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -55,11 +55,13 @@
#include "BKE_colorband.h"
#include "BKE_editmesh.h"
#include "BKE_key.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
+#include "BKE_mesh_tangent.h"
#include "BKE_object.h"
#include "BKE_object_deform.h"
#include "BKE_paint.h"
@@ -76,11 +78,12 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
#include "BLI_sys_types.h" /* for intptr_t support */
#include "GPU_buffers.h"
-#include "GPU_glew.h"
#include "GPU_shader.h"
+#include "GPU_immediate.h"
#ifdef WITH_OPENSUBDIV
-# include "BKE_depsgraph.h"
+# include "DEG_depsgraph.h"
+# include "DEG_depsgraph_query.h"
# include "DNA_userdef_types.h"
#endif
@@ -347,7 +350,7 @@ void DM_init(
dm->numPolyData = numPolys;
DM_init_funcs(dm);
-
+
dm->needsFree = 1;
dm->auto_bump_scale = -1.0f;
dm->dirty = 0;
@@ -407,6 +410,7 @@ int DM_release(DerivedMesh *dm)
if (dm->needsFree) {
bvhcache_free(&dm->bvhCache);
GPU_drawobject_free(dm);
+
CustomData_free(&dm->vertData, dm->numVertData);
CustomData_free(&dm->edgeData, dm->numEdgeData);
CustomData_free(&dm->faceData, dm->numTessFaceData);
@@ -552,7 +556,6 @@ void DM_update_tessface_data(DerivedMesh *dm)
MLoop *ml = dm->getLoopArray(dm);
CustomData *fdata = dm->getTessFaceDataLayout(dm);
- CustomData *pdata = dm->getPolyDataLayout(dm);
CustomData *ldata = dm->getLoopDataLayout(dm);
const int totface = dm->getNumTessFaces(dm);
@@ -565,7 +568,7 @@ void DM_update_tessface_data(DerivedMesh *dm)
if (!polyindex)
return;
- CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
+ CustomData_from_bmeshpoly(fdata, ldata, totface);
if (CustomData_has_layer(fdata, CD_MTFACE) ||
CustomData_has_layer(fdata, CD_MCOL) ||
@@ -597,7 +600,7 @@ void DM_update_tessface_data(DerivedMesh *dm)
* 0 for quads (because our quads may have been rotated compared to their org poly, see tessellation code).
* So we pass the MFace's, and BKE_mesh_loops_to_tessdata will use MFace->v4 index as quad test.
*/
- BKE_mesh_loops_to_tessdata(fdata, ldata, pdata, mface, polyindex, loopindex, totface);
+ BKE_mesh_loops_to_tessdata(fdata, ldata, mface, polyindex, loopindex, totface);
MEM_freeN(loopindex);
}
@@ -615,7 +618,6 @@ void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate)
MLoop *ml = dm->getLoopArray(dm);
CustomData *fdata = dm->getTessFaceDataLayout(dm);
- CustomData *pdata = dm->getPolyDataLayout(dm);
CustomData *ldata = dm->getLoopDataLayout(dm);
const int totface = dm->getNumTessFaces(dm);
@@ -632,7 +634,7 @@ void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate)
for (int j = 0; j < ldata->totlayer; j++) {
if (ldata->layers[j].type == CD_TANGENT) {
CustomData_add_layer_named(fdata, CD_TANGENT, CD_CALLOC, NULL, totface, ldata->layers[j].name);
- CustomData_bmesh_update_active_layers(fdata, pdata, ldata);
+ CustomData_bmesh_update_active_layers(fdata, ldata);
if (!loopindex) {
loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__);
@@ -662,7 +664,7 @@ void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate)
}
if (loopindex)
MEM_freeN(loopindex);
- BLI_assert(CustomData_from_bmeshpoly_test(fdata, pdata, ldata, true));
+ BLI_assert(CustomData_from_bmeshpoly_test(fdata, ldata, true));
}
if (G.debug & G_DEBUG)
@@ -1147,7 +1149,7 @@ DerivedMesh *mesh_create_derived(Mesh *me, float (*vertCos)[3])
}
DerivedMesh *mesh_create_derived_for_modifier(
- Scene *scene, Object *ob,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
ModifierData *md, int build_shapekey_layers)
{
Mesh *me = ob->data;
@@ -1173,7 +1175,7 @@ DerivedMesh *mesh_create_derived_for_modifier(
int numVerts;
float (*deformedVerts)[3] = BKE_mesh_vertexCos_get(me, &numVerts);
- modwrap_deformVerts(md, ob, NULL, deformedVerts, numVerts, 0);
+ modwrap_deformVerts(md, eval_ctx, ob, NULL, deformedVerts, numVerts, 0);
dm = mesh_create_derived(me, deformedVerts);
if (build_shapekey_layers)
@@ -1187,7 +1189,7 @@ DerivedMesh *mesh_create_derived_for_modifier(
if (build_shapekey_layers)
add_shapekey_layers(tdm, me, ob);
- dm = modwrap_applyModifier(md, ob, tdm, 0);
+ dm = modwrap_applyModifier(md, eval_ctx, ob, tdm, 0);
ASSERT_IS_VALID_DM(dm);
if (tdm != dm) tdm->release(tdm);
@@ -1753,7 +1755,7 @@ static void dm_ensure_display_normals(DerivedMesh *dm)
* - apply deform modifiers and input vertexco
*/
static void mesh_calc_modifiers(
- Scene *scene, Object *ob, float (*inputVertexCos)[3],
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float (*inputVertexCos)[3],
const bool useRenderParams, int useDeform,
const bool need_mapping, CustomDataMask dataMask,
const int index, const bool useCache, const bool build_shapekey_layers,
@@ -1864,7 +1866,7 @@ static void mesh_calc_modifiers(
if (!deformedVerts)
deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts);
- modwrap_deformVerts(md, ob, NULL, deformedVerts, numVerts, deform_app_flags);
+ modwrap_deformVerts(md, eval_ctx, ob, NULL, deformedVerts, numVerts, deform_app_flags);
}
else {
break;
@@ -2005,7 +2007,7 @@ static void mesh_calc_modifiers(
}
}
- modwrap_deformVerts(md, ob, dm, deformedVerts, numVerts, deform_app_flags);
+ modwrap_deformVerts(md, eval_ctx, ob, dm, deformedVerts, numVerts, deform_app_flags);
}
else {
DerivedMesh *ndm;
@@ -2080,7 +2082,7 @@ static void mesh_calc_modifiers(
}
}
- ndm = modwrap_applyModifier(md, ob, dm, app_flags);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, dm, app_flags);
ASSERT_IS_VALID_DM(ndm);
if (ndm) {
@@ -2107,7 +2109,7 @@ static void mesh_calc_modifiers(
(mti->requiredDataMask ?
mti->requiredDataMask(ob, md) : 0));
- ndm = modwrap_applyModifier(md, ob, orcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, orcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
ASSERT_IS_VALID_DM(ndm);
if (ndm) {
@@ -2125,7 +2127,7 @@ static void mesh_calc_modifiers(
nextmask &= ~CD_MASK_CLOTH_ORCO;
DM_set_only_copy(clothorcodm, nextmask | CD_MASK_ORIGINDEX);
- ndm = modwrap_applyModifier(md, ob, clothorcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, clothorcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
ASSERT_IS_VALID_DM(ndm);
if (ndm) {
@@ -2308,8 +2310,8 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *
}
static void editbmesh_calc_modifiers(
- Scene *scene, Object *ob, BMEditMesh *em,
- CustomDataMask dataMask,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
+ BMEditMesh *em, CustomDataMask dataMask,
/* return args */
DerivedMesh **r_cage, DerivedMesh **r_final)
{
@@ -2396,9 +2398,9 @@ static void editbmesh_calc_modifiers(
}
if (mti->deformVertsEM)
- modwrap_deformVertsEM(md, ob, em, dm, deformedVerts, numVerts);
+ modwrap_deformVertsEM(md, eval_ctx, ob, em, dm, deformedVerts, numVerts);
else
- modwrap_deformVerts(md, ob, dm, deformedVerts, numVerts, 0);
+ modwrap_deformVerts(md, eval_ctx, ob, dm, deformedVerts, numVerts, 0);
}
else {
DerivedMesh *ndm;
@@ -2443,10 +2445,10 @@ static void editbmesh_calc_modifiers(
DM_set_only_copy(orcodm, mask | CD_MASK_ORIGINDEX);
if (mti->applyModifierEM) {
- ndm = modwrap_applyModifierEM(md, ob, em, orcodm, MOD_APPLY_ORCO);
+ ndm = modwrap_applyModifierEM(md, eval_ctx, ob, em, orcodm, MOD_APPLY_ORCO);
}
else {
- ndm = modwrap_applyModifier(md, ob, orcodm, MOD_APPLY_ORCO);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, orcodm, MOD_APPLY_ORCO);
}
ASSERT_IS_VALID_DM(ndm);
@@ -2471,9 +2473,9 @@ static void editbmesh_calc_modifiers(
}
if (mti->applyModifierEM)
- ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
+ ndm = modwrap_applyModifierEM(md, eval_ctx, ob, em, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
else
- ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
ASSERT_IS_VALID_DM(ndm);
if (ndm) {
@@ -2609,7 +2611,8 @@ static void editbmesh_calc_modifiers(
* we'll be using GPU backend of OpenSubdiv. This is so
* playback performance is kept as high as possible.
*/
-static bool calc_modifiers_skip_orco(Scene *scene,
+static bool calc_modifiers_skip_orco(const EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
bool use_render_params)
{
@@ -2625,7 +2628,7 @@ static bool calc_modifiers_skip_orco(Scene *scene,
else if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) != 0) {
return false;
}
- else if ((DAG_get_eval_flags_for_object(scene, ob) & DAG_EVAL_NEED_CPU) != 0) {
+ else if ((DEG_get_eval_flags_for_id(eval_ctx->depsgraph, &ob->id) & DAG_EVAL_NEED_CPU) != 0) {
return false;
}
SubsurfModifierData *smd = (SubsurfModifierData *)last_md;
@@ -2637,7 +2640,7 @@ static bool calc_modifiers_skip_orco(Scene *scene,
#endif
static void mesh_build_data(
- Scene *scene, Object *ob, CustomDataMask dataMask,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask,
const bool build_shapekey_layers, const bool need_mapping)
{
BLI_assert(ob->type == OB_MESH);
@@ -2646,13 +2649,13 @@ static void mesh_build_data(
BKE_object_sculpt_modifiers_changed(ob);
#ifdef WITH_OPENSUBDIV
- if (calc_modifiers_skip_orco(scene, ob, false)) {
+ if (calc_modifiers_skip_orco(eval_ctx, scene, ob, false)) {
dataMask &= ~(CD_MASK_ORCO | CD_MASK_PREVIEW_MCOL);
}
#endif
mesh_calc_modifiers(
- scene, ob, NULL, false, 1, need_mapping, dataMask, -1, true, build_shapekey_layers,
+ eval_ctx, scene, ob, NULL, false, 1, need_mapping, dataMask, -1, true, build_shapekey_layers,
true,
&ob->derivedDeform, &ob->derivedFinal);
@@ -2667,13 +2670,15 @@ static void mesh_build_data(
/* create PBVH immediately (would be created on the fly too,
* but this avoids waiting on first stroke) */
- BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, false, false);
+ BKE_sculpt_update_mesh_elements(eval_ctx, scene, scene->toolsettings->sculpt, ob, false, false);
}
BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS));
}
-static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask)
+static void editbmesh_build_data(
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *obedit, BMEditMesh *em, CustomDataMask dataMask)
{
BKE_object_free_derived_caches(obedit);
BKE_object_sculpt_modifiers_changed(obedit);
@@ -2681,13 +2686,13 @@ static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, C
BKE_editmesh_free_derivedmesh(em);
#ifdef WITH_OPENSUBDIV
- if (calc_modifiers_skip_orco(scene, obedit, false)) {
+ if (calc_modifiers_skip_orco(eval_ctx, scene, obedit, false)) {
dataMask &= ~(CD_MASK_ORCO | CD_MASK_PREVIEW_MCOL);
}
#endif
editbmesh_calc_modifiers(
- scene, obedit, em, dataMask,
+ eval_ctx, scene, obedit, em, dataMask,
&em->derivedCage, &em->derivedFinal);
DM_set_object_boundbox(obedit, em->derivedFinal);
@@ -2701,7 +2706,9 @@ static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, C
static CustomDataMask object_get_datamask(const Scene *scene, Object *ob, bool *r_need_mapping)
{
- Object *actob = scene->basact ? scene->basact->object : NULL;
+ /* TODO(sergey): Avoid this linear list lookup. */
+ ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
+ Object *actob = view_layer->basact ? view_layer->basact->object : NULL;
CustomDataMask mask = ob->customdata_mask;
if (r_need_mapping) {
@@ -2738,23 +2745,24 @@ static CustomDataMask object_get_datamask(const Scene *scene, Object *ob, bool *
}
void makeDerivedMesh(
- Scene *scene, Object *ob, BMEditMesh *em,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, BMEditMesh *em,
CustomDataMask dataMask, const bool build_shapekey_layers)
{
bool need_mapping;
dataMask |= object_get_datamask(scene, ob, &need_mapping);
if (em) {
- editbmesh_build_data(scene, ob, em, dataMask);
+ editbmesh_build_data(eval_ctx, scene, ob, em, dataMask);
}
else {
- mesh_build_data(scene, ob, dataMask, build_shapekey_layers, need_mapping);
+ mesh_build_data(eval_ctx, scene, ob, dataMask, build_shapekey_layers, need_mapping);
}
}
/***/
-DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dataMask)
+DerivedMesh *mesh_get_derived_final(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask)
{
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
@@ -2766,14 +2774,14 @@ DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dat
((dataMask & ob->lastDataMask) != dataMask) ||
(need_mapping != ob->lastNeedMapping))
{
- mesh_build_data(scene, ob, dataMask, false, need_mapping);
+ mesh_build_data(eval_ctx, scene, ob, dataMask, false, need_mapping);
}
if (ob->derivedFinal) { BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS)); }
return ob->derivedFinal;
}
-DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask dataMask)
+DerivedMesh *mesh_get_derived_deform(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask)
{
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
@@ -2786,37 +2794,37 @@ DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask da
((dataMask & ob->lastDataMask) != dataMask) ||
(need_mapping != ob->lastNeedMapping))
{
- mesh_build_data(scene, ob, dataMask, false, need_mapping);
+ mesh_build_data(eval_ctx, scene, ob, dataMask, false, need_mapping);
}
return ob->derivedDeform;
}
-DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask dataMask)
+DerivedMesh *mesh_create_derived_render(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, NULL, true, 1, false, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, NULL, true, 1, false, dataMask, -1, false, false, false,
NULL, &final);
return final;
}
-DerivedMesh *mesh_create_derived_index_render(Scene *scene, Object *ob, CustomDataMask dataMask, int index)
+DerivedMesh *mesh_create_derived_index_render(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask, int index)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, NULL, true, 1, false, dataMask, index, false, false, false,
+ eval_ctx, scene, ob, NULL, true, 1, false, dataMask, index, false, false, false,
NULL, &final);
return final;
}
DerivedMesh *mesh_create_derived_view(
- Scene *scene, Object *ob,
- CustomDataMask dataMask)
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, CustomDataMask dataMask)
{
DerivedMesh *final;
@@ -2827,7 +2835,7 @@ DerivedMesh *mesh_create_derived_view(
ob->transflag |= OB_NO_PSYS_UPDATE;
mesh_calc_modifiers(
- scene, ob, NULL, false, 1, false, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, NULL, false, 1, false, dataMask, -1, false, false, false,
NULL, &final);
ob->transflag &= ~OB_NO_PSYS_UPDATE;
@@ -2836,53 +2844,53 @@ DerivedMesh *mesh_create_derived_view(
}
DerivedMesh *mesh_create_derived_no_deform(
- Scene *scene, Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask)
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
+ float (*vertCos)[3], CustomDataMask dataMask)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, vertCos, false, 0, false, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, vertCos, false, 0, false, dataMask, -1, false, false, false,
NULL, &final);
return final;
}
DerivedMesh *mesh_create_derived_no_virtual(
- Scene *scene, Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask)
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
+ float (*vertCos)[3], CustomDataMask dataMask)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, vertCos, false, -1, false, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, vertCos, false, -1, false, dataMask, -1, false, false, false,
NULL, &final);
return final;
}
DerivedMesh *mesh_create_derived_physics(
- Scene *scene, Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask)
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
+ float (*vertCos)[3], CustomDataMask dataMask)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, vertCos, false, -1, true, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, vertCos, false, -1, true, dataMask, -1, false, false, false,
NULL, &final);
return final;
}
DerivedMesh *mesh_create_derived_no_deform_render(
- Scene *scene, Object *ob,
- float (*vertCos)[3],
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, float (*vertCos)[3],
CustomDataMask dataMask)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, vertCos, true, 0, false, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, vertCos, true, 0, false, dataMask, -1, false, false, false,
NULL, &final);
return final;
@@ -2891,7 +2899,7 @@ DerivedMesh *mesh_create_derived_no_deform_render(
/***/
DerivedMesh *editbmesh_get_derived_cage_and_final(
- Scene *scene, Object *obedit, BMEditMesh *em,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *obedit, BMEditMesh *em,
CustomDataMask dataMask,
/* return args */
DerivedMesh **r_final)
@@ -2904,7 +2912,7 @@ DerivedMesh *editbmesh_get_derived_cage_and_final(
if (!em->derivedCage ||
(em->lastDataMask & dataMask) != dataMask)
{
- editbmesh_build_data(scene, obedit, em, dataMask);
+ editbmesh_build_data(eval_ctx, scene, obedit, em, dataMask);
}
*r_final = em->derivedFinal;
@@ -2912,7 +2920,9 @@ DerivedMesh *editbmesh_get_derived_cage_and_final(
return em->derivedCage;
}
-DerivedMesh *editbmesh_get_derived_cage(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask)
+DerivedMesh *editbmesh_get_derived_cage(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *obedit, BMEditMesh *em,
+ CustomDataMask dataMask)
{
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
@@ -2922,7 +2932,7 @@ DerivedMesh *editbmesh_get_derived_cage(Scene *scene, Object *obedit, BMEditMesh
if (!em->derivedCage ||
(em->lastDataMask & dataMask) != dataMask)
{
- editbmesh_build_data(scene, obedit, em, dataMask);
+ editbmesh_build_data(eval_ctx, scene, obedit, em, dataMask);
}
return em->derivedCage;
@@ -3059,234 +3069,6 @@ void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int
/* ******************* GLSL ******************** */
-/** \name Tangent Space Calculation
- * \{ */
-
-/* Necessary complexity to handle looptri's as quads for correct tangents */
-#define USE_LOOPTRI_DETECT_QUADS
-
-typedef struct {
- float (*precomputedFaceNormals)[3];
- float (*precomputedLoopNormals)[3];
- const MLoopTri *looptri;
- MLoopUV *mloopuv; /* texture coordinates */
- MPoly *mpoly; /* indices */
- MLoop *mloop; /* indices */
- MVert *mvert; /* vertices & normals */
- float (*orco)[3];
- float (*tangent)[4]; /* destination */
- int numTessFaces;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- /* map from 'fake' face index to looptri,
- * quads will point to the first looptri of the quad */
- const int *face_as_quad_map;
- int num_face_as_quad_map;
-#endif
-
-} SGLSLMeshToTangent;
-
-/* interface */
-#include "mikktspace.h"
-
-static int dm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
-{
- SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- return pMesh->num_face_as_quad_map;
-#else
- return pMesh->numTessFaces;
-#endif
-}
-
-static int dm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
-{
-#ifdef USE_LOOPTRI_DETECT_QUADS
- SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
- if (pMesh->face_as_quad_map) {
- const MLoopTri *lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- return 4;
- }
- }
- return 3;
-#else
- UNUSED_VARS(pContext, face_num);
- return 3;
-#endif
-}
-
-static void dm_ts_GetPosition(
- const SMikkTSpaceContext *pContext, float r_co[3],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
- const MLoopTri *lt;
- int loop_index;
- const float *co;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- loop_index = mp->loopstart + vert_index;
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = &pMesh->looptri[face_num];
- }
-#else
- lt = &pMesh->looptri[face_num];
-#endif
- loop_index = lt->tri[vert_index];
-
-finally:
- co = pMesh->mvert[pMesh->mloop[loop_index].v].co;
- copy_v3_v3(r_co, co);
-}
-
-static void dm_ts_GetTextureCoordinate(
- const SMikkTSpaceContext *pContext, float r_uv[2],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
- const MLoopTri *lt;
- int loop_index;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- loop_index = mp->loopstart + vert_index;
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = &pMesh->looptri[face_num];
- }
-#else
- lt = &pMesh->looptri[face_num];
-#endif
- loop_index = lt->tri[vert_index];
-
-finally:
- if (pMesh->mloopuv != NULL) {
- const float *uv = pMesh->mloopuv[loop_index].uv;
- copy_v2_v2(r_uv, uv);
- }
- else {
- const float *orco = pMesh->orco[pMesh->mloop[loop_index].v];
- map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
- }
-}
-
-static void dm_ts_GetNormal(
- const SMikkTSpaceContext *pContext, float r_no[3],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
- const MLoopTri *lt;
- int loop_index;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- loop_index = mp->loopstart + vert_index;
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = &pMesh->looptri[face_num];
- }
-#else
- lt = &pMesh->looptri[face_num];
-#endif
- loop_index = lt->tri[vert_index];
-
-finally:
- if (pMesh->precomputedLoopNormals) {
- copy_v3_v3(r_no, pMesh->precomputedLoopNormals[loop_index]);
- }
- else if ((pMesh->mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */
- if (pMesh->precomputedFaceNormals) {
- copy_v3_v3(r_no, pMesh->precomputedFaceNormals[lt->poly]);
- }
- else {
-#ifdef USE_LOOPTRI_DETECT_QUADS
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- normal_quad_v3(
- r_no,
- pMesh->mvert[pMesh->mloop[mp->loopstart + 0].v].co,
- pMesh->mvert[pMesh->mloop[mp->loopstart + 1].v].co,
- pMesh->mvert[pMesh->mloop[mp->loopstart + 2].v].co,
- pMesh->mvert[pMesh->mloop[mp->loopstart + 3].v].co);
- }
- else
-#endif
- {
- normal_tri_v3(
- r_no,
- pMesh->mvert[pMesh->mloop[lt->tri[0]].v].co,
- pMesh->mvert[pMesh->mloop[lt->tri[1]].v].co,
- pMesh->mvert[pMesh->mloop[lt->tri[2]].v].co);
- }
- }
- }
- else {
- const short *no = pMesh->mvert[pMesh->mloop[loop_index].v].no;
- normal_short_to_float_v3(r_no, no);
- }
-}
-
-static void dm_ts_SetTSpace(
- const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
- const MLoopTri *lt;
- int loop_index;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- loop_index = mp->loopstart + vert_index;
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = &pMesh->looptri[face_num];
- }
-#else
- lt = &pMesh->looptri[face_num];
-#endif
- loop_index = lt->tri[vert_index];
-
- float *pRes;
-
-finally:
- pRes = pMesh->tangent[loop_index];
- copy_v3_v3(pRes, fvTangent);
- pRes[3] = fSign;
-}
-
void DM_calc_tangents_names_from_gpu(
const GPUVertexAttribs *gattribs,
char (*tangent_names)[MAX_NAME], int *r_tangent_names_count)
@@ -3300,28 +3082,6 @@ void DM_calc_tangents_names_from_gpu(
*r_tangent_names_count = count;
}
-static void DM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- struct SGLSLMeshToTangent *mesh2tangent = taskdata;
- /* new computation method */
- {
- SMikkTSpaceContext sContext = {NULL};
- SMikkTSpaceInterface sInterface = {NULL};
-
- sContext.m_pUserData = mesh2tangent;
- sContext.m_pInterface = &sInterface;
- sInterface.m_getNumFaces = dm_ts_GetNumFaces;
- sInterface.m_getNumVerticesOfFace = dm_ts_GetNumVertsOfFace;
- sInterface.m_getPosition = dm_ts_GetPosition;
- sInterface.m_getTexCoord = dm_ts_GetTextureCoordinate;
- sInterface.m_getNormal = dm_ts_GetNormal;
- sInterface.m_setTSpaceBasic = dm_ts_SetTSpace;
-
- /* 0 if failed */
- genTangSpaceDefault(&sContext);
- }
-}
-
void DM_add_named_tangent_layer_for_uv(
CustomData *uv_data, CustomData *tan_data, int numLoopData,
const char *layer_name)
@@ -3335,213 +3095,26 @@ void DM_add_named_tangent_layer_for_uv(
}
}
-/**
- * Here we get some useful information such as active uv layer name and search if it is already in tangent_names.
- * Also, we calculate tangent_mask that works as a descriptor of tangents state.
- * If tangent_mask has changed, then recalculate tangents.
- */
-void DM_calc_loop_tangents_step_0(
- const CustomData *loopData, bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME], int tangent_names_count,
- bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
- char *ract_uv_name, char *rren_uv_name, short *rtangent_mask)
-{
- /* Active uv in viewport */
- int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV);
- *ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV);
- ract_uv_name[0] = 0;
- if (*ract_uv_n != -1) {
- strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name);
- }
-
- /* Active tangent in render */
- *rren_uv_n = CustomData_get_render_layer(loopData, CD_MLOOPUV);
- rren_uv_name[0] = 0;
- if (*rren_uv_n != -1) {
- strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name);
- }
-
- /* If active tangent not in tangent_names we take it into account */
- *rcalc_act = false;
- *rcalc_ren = false;
- for (int i = 0; i < tangent_names_count; i++) {
- if (tangent_names[i][0] == 0) {
- calc_active_tangent = true;
- }
- }
- if (calc_active_tangent) {
- *rcalc_act = true;
- *rcalc_ren = true;
- for (int i = 0; i < tangent_names_count; i++) {
- if (STREQ(ract_uv_name, tangent_names[i]))
- *rcalc_act = false;
- if (STREQ(rren_uv_name, tangent_names[i]))
- *rcalc_ren = false;
- }
- }
- *rtangent_mask = 0;
-
- const int uv_layer_num = CustomData_number_of_layers(loopData, CD_MLOOPUV);
- for (int n = 0; n < uv_layer_num; n++) {
- const char *name = CustomData_get_layer_name(loopData, CD_MLOOPUV, n);
- bool add = false;
- for (int i = 0; i < tangent_names_count; i++) {
- if (tangent_names[i][0] && STREQ(tangent_names[i], name)) {
- add = true;
- break;
- }
- }
- if ((*rcalc_act && ract_uv_name[0] && STREQ(ract_uv_name, name)) ||
- (*rcalc_ren && rren_uv_name[0] && STREQ(rren_uv_name, name)))
- {
- add = true;
- }
- if (add)
- *rtangent_mask |= 1 << n;
- }
-
- if (uv_layer_num == 0)
- *rtangent_mask |= DM_TANGENT_MASK_ORCO;
-}
-
void DM_calc_loop_tangents(
DerivedMesh *dm, bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME], int tangent_names_count)
-{
- int act_uv_n = -1;
- int ren_uv_n = -1;
- bool calc_act = false;
- bool calc_ren = false;
- char act_uv_name[MAX_NAME];
- char ren_uv_name[MAX_NAME];
- short tangent_mask = 0;
- DM_calc_loop_tangents_step_0(
- &dm->loopData, calc_active_tangent, tangent_names, tangent_names_count,
- &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
- if ((dm->tangent_mask | tangent_mask) != dm->tangent_mask) {
- /* Check we have all the needed layers */
- MPoly *mpoly = dm->getPolyArray(dm);
- const MLoopTri *looptri = dm->getLoopTriArray(dm);
- int totface = dm->getNumLoopTri(dm);
- /* Allocate needed tangent layers */
- for (int i = 0; i < tangent_names_count; i++)
- if (tangent_names[i][0])
- DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, tangent_names[i]);
- if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1)
- CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, "");
- if (calc_act && act_uv_name[0])
- DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, act_uv_name);
- if (calc_ren && ren_uv_name[0])
- DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, ren_uv_name);
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- int num_face_as_quad_map;
- int *face_as_quad_map = NULL;
-
- /* map faces to quads */
- if (totface != dm->getNumPolys(dm)) {
- /* over alloc, since we dont know how many ngon or quads we have */
-
- /* map fake face index to looptri */
- face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
- int k, j;
- for (k = 0, j = 0; j < totface; k++, j++) {
- face_as_quad_map[k] = j;
- /* step over all quads */
- if (mpoly[looptri[j].poly].totloop == 4) {
- j++; /* skips the nest looptri */
- }
- }
- num_face_as_quad_map = k;
- }
- else {
- num_face_as_quad_map = totface;
- }
-#endif
-
- /* Calculation */
- {
- TaskScheduler *scheduler = BLI_task_scheduler_get();
- TaskPool *task_pool;
- task_pool = BLI_task_pool_create(scheduler, NULL);
-
- dm->tangent_mask = 0;
- /* Calculate tangent layers */
- SGLSLMeshToTangent data_array[MAX_MTFACE];
- const int tangent_layer_num = CustomData_number_of_layers(&dm->loopData, CD_TANGENT);
- for (int n = 0; n < tangent_layer_num; n++) {
- int index = CustomData_get_layer_index_n(&dm->loopData, CD_TANGENT, n);
- BLI_assert(n < MAX_MTFACE);
- SGLSLMeshToTangent *mesh2tangent = &data_array[n];
- mesh2tangent->numTessFaces = totface;
-#ifdef USE_LOOPTRI_DETECT_QUADS
- mesh2tangent->face_as_quad_map = face_as_quad_map;
- mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
-#endif
- mesh2tangent->mvert = dm->getVertArray(dm);
- mesh2tangent->mpoly = dm->getPolyArray(dm);
- mesh2tangent->mloop = dm->getLoopArray(dm);
- mesh2tangent->looptri = dm->getLoopTriArray(dm);
- /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
- * have to check this is valid...
- */
- mesh2tangent->precomputedLoopNormals = dm->getLoopDataArray(dm, CD_NORMAL);
- mesh2tangent->precomputedFaceNormals = CustomData_get_layer(&dm->polyData, CD_NORMAL);
-
- mesh2tangent->orco = NULL;
- mesh2tangent->mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name);
-
- /* Fill the resulting tangent_mask */
- if (!mesh2tangent->mloopuv) {
- mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO);
- if (!mesh2tangent->orco)
- continue;
-
- dm->tangent_mask |= DM_TANGENT_MASK_ORCO;
- }
- else {
- int uv_ind = CustomData_get_named_layer_index(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name);
- int uv_start = CustomData_get_layer_index(&dm->loopData, CD_MLOOPUV);
- BLI_assert(uv_ind != -1 && uv_start != -1);
- BLI_assert(uv_ind - uv_start < MAX_MTFACE);
- dm->tangent_mask |= 1 << (uv_ind - uv_start);
- }
-
- mesh2tangent->tangent = dm->loopData.layers[index].data;
- BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
- }
-
- BLI_assert(dm->tangent_mask == tangent_mask);
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
- }
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (face_as_quad_map) {
- MEM_freeN(face_as_quad_map);
- }
-#undef USE_LOOPTRI_DETECT_QUADS
-
-#endif
-
- /* Update active layer index */
- int act_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, act_uv_n);
- if (act_uv_index != -1) {
- int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[act_uv_index].name);
- CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index);
- } /* else tangent has been built from orco */
-
- /* Update render layer index */
- int ren_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, ren_uv_n);
- if (ren_uv_index != -1) {
- int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[ren_uv_index].name);
- CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index);
- } /* else tangent has been built from orco */
- }
+ const char (*tangent_names)[MAX_NAME], int tangent_names_len)
+{
+ BKE_mesh_calc_loop_tangent_ex(
+ dm->getVertArray(dm),
+ dm->getPolyArray(dm), dm->getNumPolys(dm),
+ dm->getLoopArray(dm),
+ dm->getLoopTriArray(dm), dm->getNumLoopTri(dm),
+ &dm->loopData,
+ calc_active_tangent,
+ tangent_names, tangent_names_len,
+ CustomData_get_layer(&dm->polyData, CD_NORMAL),
+ dm->getLoopDataArray(dm, CD_NORMAL),
+ dm->getVertDataArray(dm, CD_ORCO), /* may be NULL */
+ /* result */
+ &dm->loopData, dm->getNumLoops(dm),
+ &dm->tangent_mask);
}
-/** \} */
-
-
void DM_calc_auto_bump_scale(DerivedMesh *dm)
{
/* int totvert = dm->getNumVerts(dm); */ /* UNUSED */
@@ -3970,7 +3543,6 @@ BLI_INLINE void navmesh_intToCol(int i, float col[3])
static void navmesh_drawColored(DerivedMesh *dm)
{
- int a, glmode;
MVert *mvert = (MVert *)CustomData_get_layer(&dm->vertData, CD_MVERT);
MFace *mface = (MFace *)CustomData_get_layer(&dm->faceData, CD_MFACE);
int *polygonIdx = (int *)CustomData_get_layer(&dm->polyData, CD_RECAST);
@@ -3985,43 +3557,42 @@ static void navmesh_drawColored(DerivedMesh *dm)
dm->drawEdges(dm, 0, 1);
#endif
- /* if (GPU_buffer_legacy(dm) ) */ /* TODO - VBO draw code, not high priority - campbell */
- {
- DEBUG_VBO("Using legacy code. drawNavMeshColored\n");
- glBegin(glmode = GL_QUADS);
- for (a = 0; a < dm->numTessFaceData; a++, mface++) {
- int new_glmode = mface->v4 ? GL_QUADS : GL_TRIANGLES;
- int pi = polygonIdx[a];
- if (pi <= 0) {
- zero_v3(col);
- }
- else {
- navmesh_intToCol(pi, col);
- }
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- if (new_glmode != glmode) {
- glEnd();
- glBegin(glmode = new_glmode);
- }
- glColor3fv(col);
- glVertex3fv(mvert[mface->v1].co);
- glVertex3fv(mvert[mface->v2].co);
- glVertex3fv(mvert[mface->v3].co);
- if (mface->v4) {
- glVertex3fv(mvert[mface->v4].co);
- }
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ /* Note: batch drawing API would let us share vertices */
+ immBeginAtMost(GWN_PRIM_TRIS, dm->numTessFaceData * 6);
+ for (int a = 0; a < dm->numTessFaceData; a++, mface++) {
+ int pi = polygonIdx[a];
+ if (pi <= 0) {
+ zero_v3(col);
+ }
+ else {
+ navmesh_intToCol(pi, col);
}
- glEnd();
- }
-}
-static void navmesh_DM_drawFacesTex(
- DerivedMesh *dm,
- DMSetDrawOptionsTex UNUSED(setDrawOptions),
- DMCompareDrawOptions UNUSED(compareDrawOptions),
- void *UNUSED(userData), DMDrawFlag UNUSED(flag))
-{
- navmesh_drawColored(dm);
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v1].co);
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v2].co);
+ immAttrib3fv(color, col);
+ immVertex3fv(pos, mvert[mface->v3].co);
+
+ if (mface->v4) {
+ /* this tess face is a quad, so draw the other triangle */
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v1].co);
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v3].co);
+ immAttrib3fv(color, col);
+ immVertex3fv(pos, mvert[mface->v4].co);
+ }
+ }
+ immEnd();
+ immUnbindProgram();
}
static void navmesh_DM_drawFacesSolid(
@@ -4057,7 +3628,6 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm)
recastData = (int *)CustomData_get_layer(&result->polyData, CD_RECAST);
/* note: This is not good design! - really should not be doing this */
- result->drawFacesTex = navmesh_DM_drawFacesTex;
result->drawFacesSolid = navmesh_DM_drawFacesSolid;
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 5c2fe0bb040..88c0aa6f35a 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -55,7 +55,6 @@
#include "BKE_animsys.h"
#include "BKE_constraint.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
@@ -65,6 +64,8 @@
#include "BKE_main.h"
#include "BKE_object.h"
+#include "DEG_depsgraph_build.h"
+
#include "BIK_api.h"
#include "RNA_access.h"
@@ -587,6 +588,8 @@ void BKE_pose_copy_data_ex(bPose **dst, const bPose *src, const int flag, const
if (pchan->prop) {
pchan->prop = IDP_CopyProperty_ex(pchan->prop, flag);
}
+
+ pchan->draw_data = NULL; /* Drawing cache, no need to copy. */
}
/* for now, duplicate Bone Groups too when doing this */
@@ -780,6 +783,9 @@ void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
IDP_FreeProperty(pchan->prop);
MEM_freeN(pchan->prop);
}
+
+ /* Cached data, for new draw manager rendering code. */
+ MEM_SAFE_FREE(pchan->draw_data);
}
void BKE_pose_channel_free(bPoseChannel *pchan)
@@ -1428,7 +1434,7 @@ void BKE_pose_tag_recalc(Main *bmain, bPose *pose)
/* Depsgraph components depends on actual pose state,
* if pose was changed depsgraph is to be updated as well.
*/
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
/* For the calculation of the effects of an Action at the given frame on an object
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 2f65e71c6d2..62df97c6afa 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -43,8 +43,8 @@
#include "DNA_key_types.h"
#include "DNA_scene_types.h"
+#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_main.h"
@@ -54,6 +54,9 @@
#include "BKE_anim.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
// XXX bad level call...
/* --------------------- */
@@ -273,88 +276,23 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
/* ........ */
-/* Note on evaluation optimizations:
- * Optimization's currently used here play tricks with the depsgraph in order to try and
- * evaluate as few objects as strictly necessary to get nicer performance under standard
- * production conditions. For those people who really need the accurate version,
- * disable the ifdef (i.e. 1 -> 0) and comment out the call to motionpaths_calc_optimise_depsgraph()
- */
-
-/* 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;
- MPathTarget *mpt;
-
- /* make sure our temp-tag isn't already in use */
- for (base = scene->base.first; base; base = base->next)
- base->object->flag &= ~BA_TEMP_TAG;
-
- /* for each target, dump its object to the start of the list if it wasn't moved already */
- for (mpt = targets->first; mpt; mpt = mpt->next) {
- for (base = scene->base.first; base; base = baseNext) {
- baseNext = base->next;
-
- if ((base->object == mpt->ob) && !(mpt->ob->flag & BA_TEMP_TAG)) {
- BLI_remlink(&scene->base, base);
- BLI_addhead(&scene->base, base);
-
- mpt->ob->flag |= BA_TEMP_TAG;
-
- /* we really don't need to continue anymore once this happens, but this line might really 'break' */
- break;
- }
- }
- }
-
- /* "brew me a list that's sorted a bit faster now depsy" */
- DAG_scene_relations_rebuild(G.main, scene);
-}
-
/* update scene for current frame */
-static void motionpaths_calc_update_scene(Scene *scene)
+static void motionpaths_calc_update_scene(Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer,
+ struct Depsgraph *depsgraph)
{
-#if 1 // 'production' optimizations always on
- /* rigid body simulation needs complete update to work correctly for now */
- /* RB_TODO investigate if we could avoid updating everything */
- if (BKE_scene_check_rigidbody_active(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;
-
- /* only stuff that moves or needs display still */
- DAG_scene_update_flags(G.main, scene, scene->lay, true, false);
-
- /* find the last object with the tag
- * - all those afterwards are assumed to not be relevant for our calculations
- */
- /* optimize further by moving out... */
- for (base = scene->base.first; base; base = base->next) {
- if (base->object->flag & BA_TEMP_TAG)
- last = base;
- }
-
- /* perform updates for tagged objects */
- /* XXX: this will break if rigs depend on scene or other data that
- * is animated but not attached to/updatable from objects */
- for (base = scene->base.first; base; base = base->next) {
- /* update this object */
- BKE_object_handle_update(G.main->eval_ctx, scene, base->object);
-
- /* if this is the last one we need to update, let's stop to save some time */
- if (base == last)
- break;
- }
- }
-#else // original, 'always correct' version
- /* do all updates
+ /* Do all updates
* - if this is too slow, resort to using a more efficient way
* that doesn't force complete update, but for now, this is the
* most accurate way!
+ *
+ * TODO(segey): Bring back partial updates, which became impossible
+ * with the new depsgraph due to unsorted nature of bases.
+ *
+ * TODO(sergey): Use evaluation context dedicated to motion paths.
*/
- BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay); /* XXX this is the best way we can get anything moving */
-#endif
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
}
/* ........ */
@@ -404,7 +342,7 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
* - recalc: whether we need to
*/
/* TODO: include reports pointer? */
-void animviz_calc_motionpaths(Scene *scene, ListBase *targets)
+ void animviz_calc_motionpaths(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, ListBase *targets)
{
MPathTarget *mpt;
int sfra, efra;
@@ -428,14 +366,10 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets)
}
if (efra <= sfra) return;
- /* optimize the depsgraph for faster updates */
- /* TODO: whether this is used should depend on some setting for the level of optimizations used */
- motionpaths_calc_optimise_depsgraph(scene, targets);
-
/* calculate path over requested range */
for (CFRA = sfra; CFRA <= efra; CFRA++) {
/* update relevant data for new frame */
- motionpaths_calc_update_scene(scene);
+ motionpaths_calc_update_scene(bmain, scene, eval_ctx->view_layer, eval_ctx->depsgraph);
/* perform baking for targets */
motionpaths_calc_bake_targets(scene, targets);
@@ -443,7 +377,7 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets)
/* reset original environment */
CFRA = cfra;
- motionpaths_calc_update_scene(scene);
+ motionpaths_calc_update_scene(bmain, scene, eval_ctx->view_layer, eval_ctx->depsgraph);
/* clear recalc flags from targets */
for (mpt = targets->first; mpt; mpt = mpt->next) {
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 6107bb1e32e..07de2ad6342 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -60,7 +60,6 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_nla.h"
#include "BKE_global.h"
@@ -70,6 +69,8 @@
#include "BKE_report.h"
#include "BKE_texture.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "nla_private.h"
@@ -93,6 +94,7 @@ bool id_type_can_have_animdata(const short id_type)
case ID_MA: case ID_TE: case ID_NT:
case ID_LA: case ID_CA: case ID_WO:
case ID_LS:
+ case ID_LP:
case ID_SPK:
case ID_SCE:
case ID_MC:
@@ -1665,7 +1667,7 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val
* notify anyone of updates */
if (!(id->tag & LIB_TAG_ANIM_NO_RECALC)) {
BKE_id_tag_set_atomic(id, LIB_TAG_ID_RECALC);
- DAG_id_type_tag(G.main, GS(id->name));
+ DEG_id_type_tag(G.main, GS(id->name));
}
}
@@ -2620,7 +2622,7 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData
ID *id = ptr->id.data;
if (!(id->tag & LIB_TAG_ANIM_NO_RECALC)) {
id->tag |= LIB_TAG_ID_RECALC;
- DAG_id_type_tag(G.main, GS(id->name));
+ DEG_id_type_tag(G.main, GS(id->name));
}
}
}
@@ -2915,7 +2917,7 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime)
#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-void BKE_animsys_eval_animdata(EvaluationContext *eval_ctx, ID *id)
+void BKE_animsys_eval_animdata(const EvaluationContext *eval_ctx, ID *id)
{
AnimData *adt = BKE_animdata_from_id(id);
Scene *scene = NULL; /* XXX: this is only needed for flushing RNA updates,
@@ -2925,7 +2927,7 @@ void BKE_animsys_eval_animdata(EvaluationContext *eval_ctx, ID *id)
BKE_animsys_evaluate_animdata(scene, id, adt, eval_ctx->ctime, ADT_RECALC_ANIM);
}
-void BKE_animsys_eval_driver(EvaluationContext *eval_ctx,
+void BKE_animsys_eval_driver(const EvaluationContext *eval_ctx,
ID *id,
FCurve *fcu)
{
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 2edbd088334..953fef067b4 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -60,7 +60,6 @@
#include "BKE_anim.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_deform.h"
#include "BKE_displist.h"
@@ -1464,13 +1463,13 @@ void BKE_armature_loc_pose_to_bone(bPoseChannel *pchan, const float inloc[3], fl
copy_v3_v3(outloc, nLocMat[3]);
}
-void BKE_armature_mat_pose_to_bone_ex(Object *ob, bPoseChannel *pchan, float inmat[4][4], float outmat[4][4])
+void BKE_armature_mat_pose_to_bone_ex(const struct EvaluationContext *eval_ctx, Object *ob, bPoseChannel *pchan, float inmat[4][4], float outmat[4][4])
{
bPoseChannel work_pchan = *pchan;
/* recalculate pose matrix with only parent transformations,
* bone loc/sca/rot is ignored, scene and frame are not used. */
- BKE_pose_where_is_bone(NULL, ob, &work_pchan, 0.0f, false);
+ BKE_pose_where_is_bone(eval_ctx, NULL, ob, &work_pchan, 0.0f, false);
/* find the matrix, need to remove the bone transforms first so this is
* calculated as a matrix to set rather then a difference ontop of whats
@@ -1953,7 +1952,7 @@ void BKE_pose_clear_pointers(bPose *pose)
/* only after leave editmode, duplicating, validating older files, library syncing */
/* NOTE: pose->flag is set for it */
-void BKE_pose_rebuild_ex(Object *ob, bArmature *arm, const bool sort_bones)
+void BKE_pose_rebuild(Object *ob, bArmature *arm)
{
Bone *bone;
bPose *pose;
@@ -1997,27 +1996,12 @@ void BKE_pose_rebuild_ex(Object *ob, bArmature *arm, const bool sort_bones)
BKE_pose_update_constraint_flags(ob->pose); /* for IK detection for example */
-#ifdef WITH_LEGACY_DEPSGRAPH
- /* the sorting */
- /* Sorting for new dependnecy graph is done on the scene graph level. */
- if (counter > 1 && sort_bones) {
- DAG_pose_sort(ob);
- }
-#else
- UNUSED_VARS(sort_bones);
-#endif
-
ob->pose->flag &= ~POSE_RECALC;
ob->pose->flag |= POSE_WAS_REBUILT;
BKE_pose_channels_hash_make(ob->pose);
}
-void BKE_pose_rebuild(Object *ob, bArmature *arm)
-{
- BKE_pose_rebuild_ex(ob, arm, true);
-}
-
/* ********************** THE POSE SOLVER ******************* */
/* loc/rot/size to given mat4 */
@@ -2128,7 +2112,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha
if (STREQ(pchan->name, amod->channel)) {
float mat4[4][4], mat3[3][3];
- curve_deform_vector(scene, amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis);
+ curve_deform_vector(amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis);
copy_m4_m4(mat4, pchan->pose_mat);
mul_m4_m3m4(pchan->pose_mat, mat3, mat4);
@@ -2212,7 +2196,9 @@ void BKE_pose_where_is_bone_tail(bPoseChannel *pchan)
/* pchan is validated, as having bone and parent pointer
* 'do_extra': when zero skips loc/size/rot, constraints and strip modifiers.
*/
-void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime, bool do_extra)
+void BKE_pose_where_is_bone(
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, bPoseChannel *pchan, float ctime, bool do_extra)
{
/* This gives a chan_mat with actions (ipos) results. */
if (do_extra)
@@ -2251,7 +2237,7 @@ void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float
cob = BKE_constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE);
/* Solve PoseChannel's Constraints */
- BKE_constraints_solve(&pchan->constraints, cob, ctime); /* ctime doesnt alter objects */
+ BKE_constraints_solve(eval_ctx, &pchan->constraints, cob, ctime); /* ctime doesnt alter objects */
/* cleanup after Constraint Solving
* - applies matrix back to pchan, and frees temporary struct used
@@ -2273,7 +2259,7 @@ void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float
/* This only reads anim data from channels, and writes to channels */
/* This is the only function adding poses */
-void BKE_pose_where_is(Scene *scene, Object *ob)
+void BKE_pose_where_is(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
bArmature *arm;
Bone *bone;
@@ -2312,7 +2298,7 @@ void BKE_pose_where_is(Scene *scene, Object *ob)
}
/* 2a. construct the IK tree (standard IK) */
- BIK_initialize_tree(scene, ob, ctime);
+ BIK_initialize_tree(eval_ctx, scene, ob, ctime);
/* 2b. construct the Spline IK trees
* - this is not integrated as an IK plugin, since it should be able
@@ -2324,15 +2310,15 @@ void BKE_pose_where_is(Scene *scene, Object *ob)
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
/* 4a. if we find an IK root, we handle it separated */
if (pchan->flag & POSE_IKTREE) {
- BIK_execute_tree(scene, ob, pchan, ctime);
+ BIK_execute_tree(eval_ctx, scene, ob, pchan, ctime);
}
/* 4b. if we find a Spline IK root, we handle it separated too */
else if (pchan->flag & POSE_IKSPLINE) {
- BKE_splineik_execute_tree(scene, ob, pchan, ctime);
+ BKE_splineik_execute_tree(eval_ctx, scene, ob, pchan, ctime);
}
/* 5. otherwise just call the normal solver */
else if (!(pchan->flag & POSE_DONE)) {
- BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1);
}
}
/* 6. release the IK tree */
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index aac9cfdf792..1b8bf3feb10 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -41,7 +41,6 @@
#include "BKE_anim.h"
#include "BKE_armature.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_fcurve.h"
#include "BKE_scene.h"
@@ -51,13 +50,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
-#include "DEG_depsgraph.h"
-
-#ifdef WITH_LEGACY_DEPSGRAPH
-# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf
-#else
-# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-#endif
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
/* ********************** SPLINE IK SOLVER ******************* */
@@ -120,9 +113,11 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
* currently for paths to work it needs to go through the bevlist/displist system (ton)
*/
+ /* TODO: Make sure this doesn't crash. */
+#if 0
/* only happens on reload file, but violates depsgraph still... fix! */
if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
- BKE_displist_make_curveTypes(scene, ikData->tar, 0);
+ BKE_displist_make_curveTypes(eval_ctx, scene, ikData->tar, 0);
/* path building may fail in EditMode after removing verts [#33268]*/
if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
@@ -130,6 +125,9 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
return;
}
}
+#else
+ (void) scene;
+#endif
}
/* find the root bone and the chain of bones from the root to the tip
@@ -268,15 +266,16 @@ static void splineik_init_tree(Scene *scene, Object *ob, float UNUSED(ctime))
/* ----------- */
/* Evaluate spline IK for a given bone */
-static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan,
- int index, float ctime)
+static void splineik_evaluate_bone(
+ const struct EvaluationContext *eval_ctx, tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan,
+ int index, float ctime)
{
bSplineIKConstraint *ikData = tree->ikData;
float poseHead[3], poseTail[3], poseMat[4][4];
float splineVec[3], scaleFac, radius = 1.0f;
/* firstly, calculate the bone matrix the standard way, since this is needed for roll control */
- BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1);
copy_v3_v3(poseHead, pchan->pose_head);
copy_v3_v3(poseTail, pchan->pose_tail);
@@ -518,7 +517,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
}
/* Evaluate the chain starting from the nominated bone */
-static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
+static void splineik_execute_tree(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
{
tSplineIK_Tree *tree;
@@ -532,7 +531,7 @@ static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_
*/
for (i = tree->chainlen - 1; i >= 0; i--) {
bPoseChannel *pchan = tree->chain[i];
- splineik_evaluate_bone(tree, scene, ob, pchan, i, ctime);
+ splineik_evaluate_bone(eval_ctx, tree, scene, ob, pchan, i, ctime);
}
/* free the tree info specific to SplineIK trees now */
@@ -551,14 +550,16 @@ void BKE_pose_splineik_init_tree(Scene *scene, Object *ob, float ctime)
splineik_init_tree(scene, ob, ctime);
}
-void BKE_splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
+void BKE_splineik_execute_tree(
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, bPoseChannel *pchan_root, float ctime)
{
- splineik_execute_tree(scene, ob, pchan_root, ctime);
+ splineik_execute_tree(eval_ctx, scene, ob, pchan_root, ctime);
}
/* *************** Depsgraph evaluation callbacks ************ */
-void BKE_pose_eval_init(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_eval_init(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *UNUSED(scene),
Object *ob,
bPose *pose)
@@ -582,7 +583,7 @@ void BKE_pose_eval_init(EvaluationContext *UNUSED(eval_ctx),
}
}
-void BKE_pose_eval_init_ik(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_eval_init_ik(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
bPose *UNUSED(pose))
@@ -592,7 +593,7 @@ void BKE_pose_eval_init_ik(EvaluationContext *UNUSED(eval_ctx),
DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
/* 2a. construct the IK tree (standard IK) */
- BIK_initialize_tree(scene, ob, ctime);
+ BIK_initialize_tree(eval_ctx, scene, ob, ctime);
/* 2b. construct the Spline IK trees
* - this is not integrated as an IK plugin, since it should be able
@@ -601,7 +602,7 @@ void BKE_pose_eval_init_ik(EvaluationContext *UNUSED(eval_ctx),
BKE_pose_splineik_init_tree(scene, ob, ctime);
}
-void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_eval_bone(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
bPoseChannel *pchan)
@@ -629,14 +630,14 @@ void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx),
if ((pchan->flag & POSE_DONE) == 0) {
/* TODO(sergey): Use time source node for time. */
float ctime = BKE_scene_frame_get(scene); /* not accurate... */
- BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1);
}
}
}
}
}
-void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_constraints_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
bPoseChannel *pchan)
@@ -652,12 +653,12 @@ void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx),
else {
if ((pchan->flag & POSE_DONE) == 0) {
float ctime = BKE_scene_frame_get(scene); /* not accurate... */
- BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1);
}
}
}
-void BKE_pose_bone_done(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_bone_done(const struct EvaluationContext *UNUSED(eval_ctx),
bPoseChannel *pchan)
{
float imat[4][4];
@@ -668,27 +669,27 @@ void BKE_pose_bone_done(EvaluationContext *UNUSED(eval_ctx),
}
}
-void BKE_pose_iktree_evaluate(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_iktree_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
bPoseChannel *rootchan)
{
float ctime = BKE_scene_frame_get(scene); /* not accurate... */
DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name);
- BIK_execute_tree(scene, ob, rootchan, ctime);
+ BIK_execute_tree(eval_ctx, scene, ob, rootchan, ctime);
}
-void BKE_pose_splineik_evaluate(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_splineik_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
bPoseChannel *rootchan)
{
float ctime = BKE_scene_frame_get(scene); /* not accurate... */
DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name);
- BKE_splineik_execute_tree(scene, ob, rootchan, ctime);
+ BKE_splineik_execute_tree(eval_ctx, scene, ob, rootchan, ctime);
}
-void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_eval_flush(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *ob,
bPose *UNUSED(pose))
@@ -699,11 +700,9 @@ void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx),
/* 6. release the IK tree */
BIK_release_tree(scene, ob, ctime);
-
- ob->recalc &= ~OB_RECALC_ALL;
}
-void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob)
+void BKE_pose_eval_proxy_copy(const struct EvaluationContext *UNUSED(eval_ctx), Object *ob)
{
BLI_assert(ID_IS_LINKED(ob) && ob->proxy_from != NULL);
DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
@@ -711,8 +710,4 @@ void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob)
printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
ob->id.name + 2, ob->proxy_from->id.name + 2);
}
- /* Rest of operations are NO-OP in depsgraph, so can clear
- * flag now.
- */
- ob->recalc &= ~OB_RECALC_ALL;
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index af46b6ec852..50764e10ceb 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -51,10 +51,10 @@
#include "BKE_brush.h"
#include "BKE_cachefile.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_node.h"
#include "BKE_report.h"
@@ -62,6 +62,8 @@
#include "BKE_screen.h"
#include "BKE_sequencer.h"
+#include "DEG_depsgraph.h"
+
#include "RE_pipeline.h"
#include "RE_render_ext.h"
@@ -87,7 +89,7 @@ void BKE_blender_free(void)
IMB_exit();
BKE_cachefiles_exit();
BKE_images_exit();
- DAG_exit();
+ DEG_free_node_types();
BKE_brush_system_exit();
RE_texture_rng_exit();
@@ -96,6 +98,8 @@ void BKE_blender_free(void)
BKE_sequencer_cache_destruct();
IMB_moviecache_destruct();
+
+ BKE_layer_exit();
free_nodesystem();
}
diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c
index e57524af546..b0c571bf159 100644
--- a/source/blender/blenkernel/intern/blender_copybuffer.c
+++ b/source/blender/blenkernel/intern/blender_copybuffer.c
@@ -44,12 +44,15 @@
#include "BKE_blender_copybuffer.h" /* own include */
#include "BKE_blendfile.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "BLO_readfile.h"
#include "BLO_writefile.h"
@@ -117,7 +120,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Main *mainl = NULL;
Library *lib;
BlendHandle *bh;
@@ -129,7 +132,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
return false;
}
- BKE_scene_base_deselect_all(scene);
+ BKE_view_layer_base_deselect_all(view_layer);
/* tag everything, all untagged data can be made local
* its also generally useful to know what is new
@@ -142,7 +145,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
BLO_library_link_copypaste(mainl, bh);
- BLO_library_link_end(mainl, &bh, flag, scene, v3d);
+ BLO_library_link_end(mainl, &bh, flag, scene, view_layer);
/* mark all library linked objects to be updated */
BKE_main_lib_objects_recalc_all(bmain);
@@ -157,7 +160,11 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
/* recreate dependency graph to include new objects */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
+
+ /* Tag update the scene to flush base collection settings, since the new object is added to a
+ * new (active) collection, not its original collection, thus need recalculation. */
+ DEG_id_tag_update(&scene->id, 0);
BLO_blendhandle_close(bh);
/* remove library... */
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index e3a5edb2049..b8f46756445 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -56,7 +56,6 @@
#include "BKE_appdir.h"
#include "BKE_brush.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
@@ -66,6 +65,8 @@
#include "BLO_readfile.h"
#include "BLO_writefile.h"
+#include "DEG_depsgraph.h"
+
/* -------------------------------------------------------------------- */
/** \name Global Undo
@@ -118,7 +119,7 @@ static int read_undosave(bContext *C, UndoElem *uel)
if (success) {
/* important not to update time here, else non keyed tranforms are lost */
- DAG_on_visible_update(G.main, false);
+ DEG_on_visible_update(G.main, false);
}
return success;
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index cc992a4a520..8d61b6723c6 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -32,6 +32,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@@ -48,11 +49,13 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_ipo.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
#include "BLO_readfile.h"
#include "BLO_writefile.h"
@@ -93,7 +96,7 @@ static bool wm_scene_is_visible(wmWindowManager *wm, Scene *scene)
{
wmWindow *win;
for (win = wm->windows.first; win; win = win->next) {
- if (win->screen->scene == scene) {
+ if (win->scene == scene) {
return true;
}
}
@@ -163,17 +166,22 @@ static void setup_app_data(
* (otherwise we'd be undoing on an off-screen scene which isn't acceptable).
* see: T43424
*/
+ wmWindow *win;
bScreen *curscreen = NULL;
+ ViewLayer *cur_view_layer;
bool track_undo_scene;
/* comes from readfile.c */
SWAP(ListBase, G.main->wm, bfd->main->wm);
+ SWAP(ListBase, G.main->workspaces, bfd->main->workspaces);
SWAP(ListBase, G.main->screen, bfd->main->screen);
- /* we re-use current screen */
+ /* we re-use current window and screen */
+ win = CTX_wm_window(C);
curscreen = CTX_wm_screen(C);
- /* but use new Scene pointer */
+ /* but use Scene pointer from new file */
curscene = bfd->curscene;
+ cur_view_layer = bfd->cur_view_layer;
track_undo_scene = (mode == LOAD_UNDO && curscreen && curscene && bfd->main->wm.first);
@@ -184,34 +192,41 @@ static void setup_app_data(
if (curscene == NULL) {
curscene = BKE_scene_add(bfd->main, "Empty");
}
+ if (cur_view_layer == NULL) {
+ /* fallback to scene layer */
+ cur_view_layer = BKE_view_layer_from_scene_get(curscene);
+ }
if (track_undo_scene) {
/* keep the old (free'd) scene, let 'blo_lib_link_screen_restore'
* replace it with 'curscene' if its needed */
}
- else {
- /* and we enforce curscene to be in current screen */
- if (curscreen) {
- /* can run in bgmode */
- curscreen->scene = curscene;
- }
+ /* and we enforce curscene to be in current screen */
+ else if (win) { /* can run in bgmode */
+ win->scene = curscene;
}
/* BKE_blender_globals_clear will free G.main, here we can still restore pointers */
- blo_lib_link_screen_restore(bfd->main, curscreen, curscene);
- /* curscreen might not be set when loading without ui (see T44217) so only re-assign if available */
- if (curscreen) {
- curscene = curscreen->scene;
+ blo_lib_link_restore(bfd->main, CTX_wm_manager(C), curscene, cur_view_layer);
+ if (win) {
+ curscene = win->scene;
}
if (track_undo_scene) {
wmWindowManager *wm = bfd->main->wm.first;
if (wm_scene_is_visible(wm, bfd->curscene) == false) {
curscene = bfd->curscene;
- curscreen->scene = curscene;
- BKE_screen_view3d_scene_sync(curscreen);
+ win->scene = curscene;
+ BKE_screen_view3d_scene_sync(curscreen, curscene);
}
}
+
+ /* We need to tag this here because events may be handled immediately after.
+ * only the current screen is important because we wont have to handle
+ * events from multiple screens at once.*/
+ {
+ BKE_screen_manipulator_tag_refresh(curscreen);
+ }
}
/* free G.main Main database */
@@ -226,6 +241,7 @@ static void setup_app_data(
CTX_data_main_set(C, G.main);
if (bfd->user) {
+
/* only here free userdef themes... */
BKE_blender_userdef_data_set_and_free(bfd->user);
bfd->user = NULL;
@@ -261,12 +277,14 @@ static void setup_app_data(
/* this can happen when active scene was lib-linked, and doesn't exist anymore */
if (CTX_data_scene(C) == NULL) {
+ wmWindow *win = CTX_wm_window(C);
+
/* in case we don't even have a local scene, add one */
if (!G.main->scene.first)
BKE_scene_add(G.main, "Empty");
CTX_data_scene_set(C, G.main->scene.first);
- CTX_wm_screen(C)->scene = CTX_data_scene(C);
+ win->scene = CTX_data_scene(C);
curscene = CTX_data_scene(C);
}
@@ -315,20 +333,27 @@ static void setup_app_data(
wmWindowManager *wm = G.main->wm.first;
if (wm) {
- wmWindow *win;
-
- for (win = wm->windows.first; win; win = win->next) {
- if (win->screen && win->screen->scene) /* zealous check... */
- if (win->screen->scene != curscene)
- BKE_scene_set_background(G.main, win->screen->scene);
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (win->scene && win->scene != curscene) {
+ BKE_scene_set_background(G.main, win->scene);
+ }
}
}
}
+
+ /* Setting scene might require having a dependency graph, with copy on write
+ * we need to make sure we ensure scene has correct color management before
+ * constructing dependency graph.
+ */
+ if (mode != LOAD_UNDO) {
+ IMB_colormanagement_check_file_config(G.main);
+ }
+
BKE_scene_set_background(G.main, curscene);
if (mode != LOAD_UNDO) {
+ /* TODO(sergey): Can this be also move above? */
RE_FreeAllPersistentData();
- IMB_colormanagement_check_file_config(G.main);
}
MEM_freeN(bfd);
@@ -534,6 +559,48 @@ bool BKE_blendfile_userdef_write_app_template(const char *filepath, ReportList *
return ok;
}
+WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath, ReportList *reports)
+{
+ BlendFileData *bfd;
+ WorkspaceConfigFileData *workspace_config = NULL;
+
+ bfd = BLO_read_from_file(filepath, reports, BLO_READ_SKIP_USERDEF);
+ if (bfd) {
+ workspace_config = MEM_mallocN(sizeof(*workspace_config), __func__);
+ workspace_config->main = bfd->main;
+ workspace_config->workspaces = bfd->main->workspaces;
+
+ MEM_freeN(bfd);
+ }
+
+ return workspace_config;
+}
+
+bool BKE_blendfile_workspace_config_write(Main *bmain, const char *filepath, ReportList *reports)
+{
+ int fileflags = G.fileflags & ~(G_FILE_NO_UI | G_FILE_AUTOPLAY | G_FILE_HISTORY);
+ bool retval = false;
+
+ BKE_blendfile_write_partial_begin(bmain);
+
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ BKE_blendfile_write_partial_tag_ID(&workspace->id, true);
+ }
+
+ if (BKE_blendfile_write_partial(bmain, filepath, fileflags, reports)) {
+ retval = true;
+ }
+
+ BKE_blendfile_write_partial_end(bmain);
+
+ return retval;
+}
+
+void BKE_blendfile_workspace_config_data_free(WorkspaceConfigFileData *workspace_config)
+{
+ BKE_main_free(workspace_config->main);
+ MEM_freeN(workspace_config);
+}
/** \} */
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 7ca4e07076d..8c78787c259 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -132,6 +132,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
if (eff == NULL && gabr->ob) {
memset(&temp_eff, 0, sizeof(EffectorCache));
temp_eff.ob = gabr->ob;
+ temp_eff.eval_ctx = bbd->sim->eval_ctx;
temp_eff.scene = bbd->sim->scene;
eff = &temp_eff;
get_effector_data(eff, &efd, &epoint, 0);
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index e821a14da2e..f8215668034 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -176,7 +176,7 @@ void BKE_cachefile_update_frame(Main *bmain, Scene *scene, const float ctime, co
const float time = BKE_cachefile_time_offset(cache_file, ctime, fps);
if (BKE_cachefile_filepath_get(bmain, cache_file, time, filename)) {
- BKE_cachefile_clean(scene, cache_file);
+ BKE_cachefile_clean(bmain, cache_file);
#ifdef WITH_ALEMBIC
ABC_free_handle(cache_file->handle);
cache_file->handle = ABC_create_handle(filename, NULL);
@@ -217,11 +217,9 @@ 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)
+void BKE_cachefile_clean(struct Main *bmain, CacheFile *cache_file)
{
- for (Base *base = scene->base.first; base; base = base->next) {
- Object *ob = base->object;
-
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
if (md) {
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 719125b3317..4993caf14f1 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -40,6 +40,7 @@
#include "DNA_ID.h"
#include "BLI_math.h"
+#include "BLI_listbase.h"
#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -48,6 +49,7 @@
#include "BKE_camera.h"
#include "BKE_object.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
@@ -55,6 +57,8 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "MEM_guardedalloc.h"
+
#include "GPU_compositing.h"
/****************************** Camera Datablock *****************************/
@@ -101,9 +105,19 @@ void *BKE_camera_add(Main *bmain, const char *name)
*
* \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
*/
-void BKE_camera_copy_data(Main *UNUSED(bmain), Camera *UNUSED(cam_dst), const Camera *UNUSED(cam_src), const int UNUSED(flag))
+void BKE_camera_copy_data(Main *UNUSED(bmain), Camera *cam_dst, const Camera *cam_src, const int flag)
{
- /* Nothing to do! */
+ BLI_duplicatelist(&cam_dst->bg_images, &cam_src->bg_images);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ for (CameraBGImage *bgpic = cam_dst->bg_images.first; bgpic; bgpic = bgpic->next) {
+ if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
+ id_us_plus((ID *)bgpic->ima);
+ }
+ else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
+ id_us_plus((ID *)bgpic->clip);
+ }
+ }
+ }
}
Camera *BKE_camera_copy(Main *bmain, const Camera *cam)
@@ -121,6 +135,16 @@ void BKE_camera_make_local(Main *bmain, Camera *cam, const bool lib_local)
/** Free (or release) any data used by this camera (does not free the camera itself). */
void BKE_camera_free(Camera *ca)
{
+ for (CameraBGImage *bgpic = ca->bg_images.first; bgpic; bgpic = bgpic->next) {
+ if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
+ id_us_min((ID *)bgpic->ima);
+ }
+ else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
+ id_us_min((ID *)bgpic->clip);
+ }
+ }
+ BLI_freelistN(&ca->bg_images);
+
BKE_animdata_free((ID *)ca, false);
}
@@ -642,7 +666,7 @@ static bool camera_frame_fit_calc_from_data(
/* don't move the camera, just yield the fit location */
/* r_scale only valid/useful for ortho cameras */
bool BKE_camera_view_frame_fit_to_scene(
- Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3], float *r_scale)
+ Scene *scene, ViewLayer *view_layer, Object *camera_ob, float r_co[3], float *r_scale)
{
CameraParams params;
CameraViewFrameData data_cb;
@@ -653,7 +677,7 @@ bool BKE_camera_view_frame_fit_to_scene(
camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
/* run callback on all visible points */
- BKE_scene_foreach_display_point(scene, v3d, BA_SELECT, camera_to_frame_view_cb, &data_cb);
+ BKE_scene_foreach_display_point(scene, view_layer, camera_to_frame_view_cb, &data_cb);
return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
}
@@ -862,9 +886,9 @@ 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);
- if (base) {
- return base->object;
+ Object *ob = BKE_scene_object_find_by_name(scene, name);
+ if (ob != NULL) {
+ return ob;
}
}
@@ -961,3 +985,38 @@ void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_set
r_fx_settings->dof->focus_distance = BKE_camera_object_dof_distance(camera);
}
}
+
+CameraBGImage *BKE_camera_background_image_new(Camera *cam)
+{
+ CameraBGImage *bgpic = MEM_callocN(sizeof(CameraBGImage), "Background Image");
+
+ bgpic->scale = 1.0f;
+ bgpic->alpha = 0.5f;
+ bgpic->iuser.fie_ima = 2;
+ bgpic->iuser.ok = 1;
+ bgpic->flag |= CAM_BGIMG_FLAG_EXPANDED;
+
+ BLI_addtail(&cam->bg_images, bgpic);
+
+ return bgpic;
+}
+
+void BKE_camera_background_image_remove(Camera *cam, CameraBGImage *bgpic)
+{
+ BLI_remlink(&cam->bg_images, bgpic);
+
+ MEM_freeN(bgpic);
+}
+
+void BKE_camera_background_image_clear(Camera *cam)
+{
+ CameraBGImage *bgpic = cam->bg_images.first;
+
+ while (bgpic) {
+ CameraBGImage *next_bgpic = bgpic->next;
+
+ BKE_camera_background_image_remove(cam, bgpic);
+
+ bgpic = next_bgpic;
+ }
+}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 13949e6777d..d1282c1a0fe 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -60,6 +60,7 @@
#include "GPU_buffers.h"
#include "GPU_draw.h"
#include "GPU_glew.h"
+#include "GPU_immediate.h"
#include "GPU_shader.h"
#include "GPU_basic_shader.h"
@@ -374,40 +375,10 @@ static void cdDM_drawVerts(DerivedMesh *dm)
GPU_buffers_unbind();
}
-static void cdDM_drawUVEdges(DerivedMesh *dm)
+static void cdDM_drawEdges(DerivedMesh *dm, bool UNUSED(drawLooseEdges), bool UNUSED(drawAllEdges))
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- const MPoly *mpoly = cddm->mpoly;
- int totpoly = dm->getNumPolys(dm);
- int prevstart = 0;
- bool prevdraw = true;
- int curpos = 0;
- int i;
-
- GPU_uvedge_setup(dm);
- for (i = 0; i < totpoly; i++, mpoly++) {
- const bool draw = (mpoly->flag & ME_HIDE) == 0;
-
- if (prevdraw != draw) {
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- prevstart = curpos;
- }
- curpos += 2 * mpoly->totloop;
- prevdraw = draw;
- }
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- GPU_buffers_unbind();
-}
-
-static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- GPUDrawObject *gdo;
if (cddm->pbvh && cddm->pbvh_draw &&
BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH)
{
@@ -415,22 +386,37 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdg
return;
}
-
- GPU_edge_setup(dm);
- gdo = dm->drawObject;
- if (gdo->edges && gdo->points) {
- if (drawAllEdges && drawLooseEdges) {
- GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->totedge * 2);
- }
- else if (drawAllEdges) {
- GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->loose_edge_offset * 2);
- }
- else {
- GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->tot_edge_drawn * 2);
- GPU_buffer_draw_elements(gdo->edges, GL_LINES, gdo->loose_edge_offset * 2, dm->drawObject->tot_loose_edge_drawn * 2);
+
+ MVert *vert = cddm->mvert;
+ MEdge *edge = cddm->medge;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ /* NOTE: This is active object color, which is not really perfect.
+ * But we can't query color set by glColor() :(
+ */
+ float color[4] = {1.0f, 0.667f, 0.251f, 1.0f};
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+
+ const int chunk_size = 1024;
+ const int num_chunks = (dm->numEdgeData + chunk_size - 1) / chunk_size;
+
+ for (int chunk = 0; chunk < num_chunks; ++chunk) {
+ const int num_current_edges = (chunk < num_chunks - 1)
+ ? chunk_size
+ : dm->numEdgeData - chunk_size * (num_chunks - 1);
+ immBeginAtMost(GWN_PRIM_LINES, num_current_edges * 2);
+ for (int i = 0; i < num_current_edges; i++, edge++) {
+ immVertex3fv(pos, vert[edge->v1].co);
+ immVertex3fv(pos, vert[edge->v2].co);
}
+ immEnd();
}
- GPU_buffers_unbind();
+
+ immUnbindProgram();
}
static void cdDM_drawLooseEdges(DerivedMesh *dm)
@@ -453,8 +439,9 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm)
static void cdDM_drawFacesSolid(
DerivedMesh *dm,
float (*partial_redraw_planes)[4],
- bool UNUSED(fast), DMSetMaterial setMaterial)
+ bool fast, DMSetMaterial setMaterial)
{
+ UNUSED_VARS(partial_redraw_planes, fast, setMaterial);
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
int a;
@@ -467,177 +454,79 @@ static void cdDM_drawFacesSolid(
return;
}
}
-
- GPU_vertex_setup(dm);
- GPU_normal_setup(dm);
- GPU_triangle_setup(dm);
- for (a = 0; a < dm->drawObject->totmaterial; a++) {
- if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
- GPU_buffer_draw_elements(
- dm->drawObject->triangles, GL_TRIANGLES,
- dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements);
- }
- }
- GPU_buffers_unbind();
-}
-static void cdDM_drawFacesTex_common(
- DerivedMesh *dm,
- DMSetDrawOptionsTex drawParams,
- DMSetDrawOptionsMappedTex drawParamsMapped,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
+ const MVert *mvert = cddm->mvert;
+ const MLoop *mloop = cddm->mloop;
const MPoly *mpoly = cddm->mpoly;
- MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
- const MLoopCol *mloopcol = NULL;
- int i;
- int colType, start_element, tot_drawn;
- const bool use_hide = (flag & DM_DRAW_SKIP_HIDDEN) != 0;
- const bool use_tface = (flag & DM_DRAW_USE_ACTIVE_UV) != 0;
- const bool use_colors = (flag & DM_DRAW_USE_COLORS) != 0;
- int totpoly;
- int next_actualFace;
- int mat_index;
- int tot_element;
-
- /* double lookup */
- const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
-
- /* TODO: not entirely correct, but currently dynamic topology will
- * destroy UVs anyway, so textured display wouldn't work anyway
- *
- * this will do more like solid view with lights set up for
- * textured view, but object itself will be displayed gray
- * (the same as it'll display without UV maps in textured view)
- */
- if (cddm->pbvh) {
- if (cddm->pbvh_draw &&
- BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH &&
- BKE_pbvh_has_faces(cddm->pbvh))
- {
- GPU_set_tpage(NULL, false, false);
- BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false);
- return;
- }
- else {
- cdDM_update_normals_from_pbvh(dm);
- }
- }
+ const int num_looptris = dm->getNumLoopTri(dm);
+ const MLoopTri *looptri = dm->getLoopTriArray(dm);
+ const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
- if (use_colors) {
- colType = CD_TEXTURE_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- if (!mloopcol) {
- colType = CD_PREVIEW_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- }
- if (!mloopcol) {
- colType = CD_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- }
- }
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- GPU_vertex_setup(dm);
- GPU_normal_setup(dm);
- GPU_triangle_setup(dm);
- if (flag & DM_DRAW_USE_TEXPAINT_UV)
- GPU_texpaint_uv_setup(dm);
- else
- GPU_uv_setup(dm);
- if (mloopcol) {
- GPU_color_setup(dm, colType);
- }
+ float color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
+ const float light_vec[3] = {0.0f, 0.0f, 1.0f};
- /* lastFlag = 0; */ /* UNUSED */
- for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
- GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
- next_actualFace = bufmat->polys[0];
- totpoly = bufmat->totpolys;
+ immBindBuiltinProgram(GPU_SHADER_SIMPLE_LIGHTING);
+ immUniformColor4fv(color);
+ immUniform3fv("light", light_vec);
- tot_element = 0;
- tot_drawn = 0;
- start_element = 0;
+ const int chunk_size = 1024;
+ const int num_chunks = (num_looptris + chunk_size - 1) / chunk_size;
- for (i = 0; i < totpoly; i++) {
- int actualFace = bufmat->polys[i];
- DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
- int flush = 0;
- int tot_tri_verts;
+ for (int chunk = 0; chunk < num_chunks; ++chunk) {
+ const int num_current_looptris = (chunk < num_chunks - 1)
+ ? chunk_size
+ : num_looptris - chunk_size * (num_chunks - 1);
- if (i != totpoly - 1)
- next_actualFace = bufmat->polys[i + 1];
+ immBeginAtMost(GWN_PRIM_TRIS, num_current_looptris * 3);
- if (use_hide && (mpoly[actualFace].flag & ME_HIDE)) {
- draw_option = DM_DRAW_OPTION_SKIP;
- }
- else if (drawParams) {
- MTexPoly *tp = use_tface && mtexpoly ? &mtexpoly[actualFace] : NULL;
- draw_option = drawParams(tp, (mloopcol != NULL), mpoly[actualFace].mat_nr);
- }
- else {
- if (index_mp_to_orig) {
- const int orig = index_mp_to_orig[actualFace];
- if (orig == ORIGINDEX_NONE) {
- /* XXX, this is not really correct
- * it will draw the previous faces context for this one when we don't know its settings.
- * but better then skipping it altogether. - campbell */
- draw_option = DM_DRAW_OPTION_NORMAL;
- }
- else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, orig, mpoly[actualFace].mat_nr);
- }
+ for (a = 0; a < num_current_looptris; a++, looptri++) {
+ const MPoly *mp = &mpoly[looptri->poly];
+ const bool smoothnormal = (lnors != NULL) || (mp->flag & ME_SMOOTH);
+ const unsigned int vtri[3] = {mloop[looptri->tri[0]].v,
+ mloop[looptri->tri[1]].v,
+ mloop[looptri->tri[2]].v};
+ const unsigned int *ltri = looptri->tri;
+ float normals[3][3];
+ if (!smoothnormal) {
+ if (nors != NULL) {
+ copy_v3_v3(normals[0], nors[looptri->poly]);
}
- else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, actualFace, mpoly[actualFace].mat_nr);
+ else {
+ normal_tri_v3(normals[0],
+ mvert[vtri[0]].co,
+ mvert[vtri[1]].co,
+ mvert[vtri[2]].co);
}
+ copy_v3_v3(normals[1], normals[0]);
+ copy_v3_v3(normals[2], normals[0]);
}
-
- /* flush buffer if current triangle isn't drawable or it's last triangle */
- flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 1);
-
- if (!flush && compareDrawOptions) {
- /* also compare draw options and flush buffer if they're different
- * need for face selection highlight in edit mode */
- flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
- }
-
- tot_tri_verts = ME_POLY_TRI_TOT(&mpoly[actualFace]) * 3;
- tot_element += tot_tri_verts;
-
- if (flush) {
- if (draw_option != DM_DRAW_OPTION_SKIP)
- tot_drawn += tot_tri_verts;
-
- if (tot_drawn) {
- if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
- GPU_color_switch(1);
- else
- GPU_color_switch(0);
-
- GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn);
- tot_drawn = 0;
- }
- start_element = tot_element;
+ else if (lnors != NULL) {
+ copy_v3_v3(normals[0], lnors[ltri[0]]);
+ copy_v3_v3(normals[1], lnors[ltri[1]]);
+ copy_v3_v3(normals[2], lnors[ltri[2]]);
}
else {
- tot_drawn += tot_tri_verts;
+ normal_short_to_float_v3(normals[0], mvert[vtri[0]].no);
+ normal_short_to_float_v3(normals[1], mvert[vtri[1]].no);
+ normal_short_to_float_v3(normals[2], mvert[vtri[2]].no);
}
+
+ immAttrib3fv(nor, normals[0]);
+ immVertex3fv(pos, mvert[vtri[0]].co);
+ immAttrib3fv(nor, normals[1]);
+ immVertex3fv(pos, mvert[vtri[1]].co);
+ immAttrib3fv(nor, normals[2]);
+ immVertex3fv(pos, mvert[vtri[2]].co);
}
+ immEnd();
}
- GPU_buffers_unbind();
-
-}
-
-static void cdDM_drawFacesTex(
- DerivedMesh *dm,
- DMSetDrawOptionsTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag);
+ immUnbindProgram();
}
static void cdDM_drawMappedFaces(
@@ -849,15 +738,6 @@ static void cdDM_drawMappedFaces(
}
-static void cdDM_drawMappedFacesTex(
- DerivedMesh *dm,
- DMSetDrawOptionsMappedTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
-}
-
static void cddm_draw_attrib_vertex(
DMVertexAttribs *attribs, const MVert *mvert, int a, int index, int loop, int vert,
const float *lnor, const bool smoothnormal)
@@ -1911,7 +1791,7 @@ void CDDM_recalc_tessellation_ex(DerivedMesh *dm, const bool do_face_nor_cpy)
/* Tessellation recreated faceData, and the active layer indices need to get re-propagated
* from loops and polys to faces */
- CustomData_bmesh_update_active_layers(&dm->faceData, &dm->polyData, &dm->loopData);
+ CustomData_bmesh_update_active_layers(&dm->faceData, &dm->loopData);
}
void CDDM_recalc_tessellation(DerivedMesh *dm)
@@ -2005,16 +1885,13 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->drawVerts = cdDM_drawVerts;
- dm->drawUVEdges = cdDM_drawUVEdges;
dm->drawEdges = cdDM_drawEdges;
dm->drawLooseEdges = cdDM_drawLooseEdges;
dm->drawMappedEdges = cdDM_drawMappedEdges;
dm->drawFacesSolid = cdDM_drawFacesSolid;
- dm->drawFacesTex = cdDM_drawFacesTex;
dm->drawFacesGLSL = cdDM_drawFacesGLSL;
dm->drawMappedFaces = cdDM_drawMappedFaces;
- dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
dm->drawMappedFacesMat = cdDM_drawMappedFacesMat;
@@ -2151,7 +2028,6 @@ DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
if (alluv) {
const char *uvname = "Orco";
- CustomData_add_layer_named(&cddm->dm.polyData, CD_MTEXPOLY, CD_DEFAULT, NULL, totpoly, uvname);
CustomData_add_layer_named(&cddm->dm.loopData, CD_MLOOPUV, CD_ASSIGN, alluv, totloop, uvname);
}
@@ -2166,22 +2042,18 @@ DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
static void loops_to_customdata_corners(
BMesh *bm, CustomData *facedata,
int cdindex, const BMLoop *l3[3],
- int numCol, int numTex)
+ int numCol, int numUV)
{
const BMLoop *l;
- BMFace *f = l3[0]->f;
+// BMFace *f = l3[0]->f;
MTFace *texface;
- MTexPoly *texpoly;
MCol *mcol;
MLoopCol *mloopcol;
MLoopUV *mloopuv;
int i, j, hasPCol = CustomData_has_layer(&bm->ldata, CD_PREVIEW_MLOOPCOL);
- for (i = 0; i < numTex; i++) {
+ for (i = 0; i < numUV; i++) {
texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i);
- texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
-
- ME_MTEXFACE_CPY(texface, texpoly);
for (j = 0; j < 3; j++) {
l = l3[j];
@@ -2235,7 +2107,7 @@ static DerivedMesh *cddm_from_bmesh_ex(
MLoop *mloop = cddm->mloop;
MPoly *mpoly = cddm->mpoly;
int numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
- int numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+ int numUV = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
int *index, add_orig;
CustomDataMask mask;
unsigned int i, j;
@@ -2265,7 +2137,7 @@ static DerivedMesh *cddm_from_bmesh_ex(
/* add tessellation mface layers */
if (use_tessface) {
- CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em_tottri);
+ CustomData_from_bmeshpoly(&dm->faceData, &dm->loopData, em_tottri);
}
index = dm->getVertDataArray(dm, CD_ORIGINDEX);
@@ -2337,7 +2209,7 @@ static DerivedMesh *cddm_from_bmesh_ex(
/* map mfaces to polygons in the same cddm intentionally */
*index++ = BM_elem_index_get(efa);
- loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex);
+ loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numUV);
test_index_face(mf, &dm->faceData, i, 3);
}
}
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index dd93606a67c..09b793629f7 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -345,7 +345,7 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
return 1;
}
-static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
+static int do_step_cloth(const struct EvaluationContext *eval_ctx, Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
{
ClothVertex *verts = NULL;
Cloth *cloth;
@@ -370,7 +370,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
mul_m4_v3(ob->obmat, verts->xconst);
}
- effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights, true);
+ effectors = pdInitEffectors(eval_ctx, clmd->scene, ob, NULL, clmd->sim_parms->effector_weights, true);
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH )
cloth_update_verts ( ob, clmd, result );
@@ -400,7 +400,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
/************************************************
* clothModifier_do - main simulation function
************************************************/
-void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3])
+void clothModifier_do(ClothModifierData *clmd, const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3])
{
PointCache *cache;
PTCacheID pid;
@@ -478,7 +478,6 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
return;
}
- if (!can_simulate)
return;
/* if on second frame, write cache for first frame */
@@ -490,7 +489,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
/* do simulation */
BKE_ptcache_validate(cache, framenr);
- if (!do_step_cloth(ob, clmd, dm, framenr)) {
+ if (!do_step_cloth(eval_ctx, ob, clmd, dm, framenr)) {
BKE_ptcache_invalidate(cache);
}
else
@@ -922,7 +921,7 @@ static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm )
}
/***************************************************************************************
- * SPRING NETWORK BUILDING IMPLEMENTATION BEGIN
+ * SPRING NETWORK GWN_BATCH_BUILDING IMPLEMENTATION BEGIN
***************************************************************************************/
BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1)
@@ -1504,6 +1503,6 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
} /* cloth_build_springs */
/***************************************************************************************
- * SPRING NETWORK BUILDING IMPLEMENTATION END
+ * SPRING NETWORK GWN_BATCH_BUILDING IMPLEMENTATION END
***************************************************************************************/
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
new file mode 100644
index 00000000000..8d69563f5ff
--- /dev/null
+++ b/source/blender/blenkernel/intern/collection.c
@@ -0,0 +1,820 @@
+/*
+ * ***** 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 <string.h>
+
+#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_group.h"
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "DNA_group_types.h"
+#include "DNA_ID.h"
+#include "DNA_layer_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+/* Prototypes. */
+static bool is_collection_in_tree(const struct SceneCollection *sc_reference, struct SceneCollection *sc_parent);
+
+static SceneCollection *collection_master_from_id(const ID *owner_id)
+{
+ switch (GS(owner_id->name)) {
+ case ID_SCE:
+ return ((Scene *)owner_id)->collection;
+ case ID_GR:
+ return ((Group *)owner_id)->collection;
+ default:
+ BLI_assert(!"ID doesn't support collections");
+ return NULL;
+ }
+}
+
+/**
+ * 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(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name)
+{
+ SceneCollection *sc_master = collection_master_from_id(owner_id);
+ SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection");
+ sc->type = type;
+
+ if (!name) {
+ name = DATA_("New Collection");
+ }
+
+ if (!sc_parent) {
+ sc_parent = sc_master;
+ }
+
+ BKE_collection_rename((Scene *)owner_id, sc, name);
+ BLI_addtail(&sc_parent->scene_collections, sc);
+
+ BKE_layer_sync_new_scene_collection(owner_id, sc_parent, sc);
+ return sc;
+}
+
+/**
+ * Free the collection items recursively
+ */
+static void collection_free(SceneCollection *sc, const bool do_id_user)
+{
+ if (do_id_user) {
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ id_us_min(link->data);
+ }
+ for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+ id_us_min(link->data);
+ }
+ }
+
+ BLI_freelistN(&sc->objects);
+ BLI_freelistN(&sc->filter_objects);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ collection_free(nsc, do_id_user);
+ }
+ 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(ViewLayer *view_layer, ListBase *lb, const SceneCollection *sc)
+{
+ LayerCollection *lc = lb->first;
+ while (lc) {
+ if (lc->scene_collection == sc) {
+ BKE_layer_collection_free(view_layer, 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 != &view_layer->layer_collections) {
+ return;
+ }
+ }
+
+ else {
+ layer_collection_remove(view_layer, &lc->layer_collections, sc);
+ lc = lc->next;
+ }
+ }
+}
+
+/**
+ * Remove a collection from the scene, and syncronize all render layers
+ */
+bool BKE_collection_remove(ID *owner_id, SceneCollection *sc)
+{
+ SceneCollection *sc_master = collection_master_from_id(owner_id);
+
+ /* 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, true);
+
+ /* check all layers that use this collection and clear them */
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ layer_collection_remove(view_layer, &view_layer->layer_collections, sc);
+ view_layer->active_collection = 0;
+ }
+
+ MEM_freeN(sc);
+ return true;
+}
+
+/**
+ * Copy SceneCollection tree but keep pointing to the same objects
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_collection_copy_data(SceneCollection *sc_dst, SceneCollection *sc_src, const int flag)
+{
+ BLI_duplicatelist(&sc_dst->objects, &sc_src->objects);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ for (LinkData *link = sc_dst->objects.first; link; link = link->next) {
+ id_us_plus(link->data);
+ }
+ }
+
+ BLI_duplicatelist(&sc_dst->filter_objects, &sc_src->filter_objects);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ for (LinkData *link = sc_dst->filter_objects.first; link; link = link->next) {
+ id_us_plus(link->data);
+ }
+ }
+
+ BLI_duplicatelist(&sc_dst->scene_collections, &sc_src->scene_collections);
+ for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first;
+ nsc_src;
+ nsc_src = nsc_src->next, nsc_dst = nsc_dst->next)
+ {
+ BKE_collection_copy_data(nsc_dst, nsc_src, flag);
+ }
+}
+
+static SceneCollection *master_collection_from_id(const ID *owner_id)
+{
+ switch (GS(owner_id->name)) {
+ case ID_SCE:
+ return ((const Scene *)owner_id)->collection;
+ case ID_GR:
+ return ((const Group *)owner_id)->collection;
+ default:
+ BLI_assert(!"ID doesn't support scene collection");
+ return NULL;
+ }
+}
+
+/**
+ * Returns the master collection of the scene or group
+ */
+SceneCollection *BKE_collection_master(const ID *owner_id)
+{
+ return master_collection_from_id(owner_id);
+}
+
+struct UniqueNameCheckData {
+ ListBase *lb;
+ SceneCollection *lookup_sc;
+};
+
+static bool collection_unique_name_check(void *arg, const char *name)
+{
+ struct UniqueNameCheckData *data = arg;
+
+ for (SceneCollection *sc = data->lb->first; sc; sc = sc->next) {
+ struct UniqueNameCheckData child_data = {.lb = &sc->scene_collections, .lookup_sc = data->lookup_sc};
+
+ if (sc != data->lookup_sc) {
+ if (STREQ(sc->name, name)) {
+ return true;
+ }
+ }
+ if (collection_unique_name_check(&child_data, name)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void collection_rename(const ID *owner_id, SceneCollection *sc, const char *name)
+{
+ SceneCollection *sc_master = collection_master_from_id(owner_id);
+ struct UniqueNameCheckData data = {.lb = &sc_master->scene_collections, .lookup_sc = sc};
+
+ BLI_strncpy(sc->name, name, sizeof(sc->name));
+ BLI_uniquename_cb(collection_unique_name_check, &data, DATA_("Collection"), '.', sc->name, sizeof(sc->name));
+}
+
+void BKE_collection_rename(const Scene *scene, SceneCollection *sc, const char *name)
+{
+ collection_rename(&scene->id, sc, name);
+}
+
+/**
+ * Free (or release) any data used by the master collection (does not free the master collection itself).
+ * Used only to clear the entire scene or group data since it's not doing re-syncing of the LayerCollection tree
+ */
+void BKE_collection_master_free(ID *owner_id, const bool do_id_user)
+{
+ collection_free(BKE_collection_master(owner_id), do_id_user);
+}
+
+static void collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob)
+{
+ BLI_addtail(&sc->objects, BLI_genericNodeN(ob));
+
+ if (GS(owner_id->name) == ID_SCE) {
+ id_us_plus((ID *)ob);
+ }
+ else {
+ BLI_assert(GS(owner_id->name) == ID_GR);
+ if ((ob->flag & OB_FROMGROUP) == 0) {
+ ob->flag |= OB_FROMGROUP;
+ }
+ }
+
+ BKE_layer_sync_object_link(owner_id, sc, ob);
+}
+
+/**
+ * Add object to collection
+ */
+bool BKE_collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob)
+{
+ if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
+ /* don't add the same object twice */
+ return false;
+ }
+
+ collection_object_add(owner_id, sc, ob);
+ return true;
+}
+
+/**
+ * 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)
+{
+ FOREACH_SCENE_COLLECTION(scene, sc)
+ {
+ if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) {
+ collection_object_add(&scene->id, sc, ob_dst);
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END
+
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ Base *base_src = BKE_view_layer_base_find(view_layer, ob_src);
+ if (base_src != NULL) {
+ if (base_src->collection_properties == NULL) {
+ continue;
+ }
+ Base *base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
+ IDP_MergeGroup(base_dst->collection_properties, base_src->collection_properties, true);
+ }
+ }
+}
+
+/**
+ * Remove object from collection.
+ * \param bmain: Can be NULL if free_us is false.
+ */
+bool BKE_collection_object_remove(Main *bmain, ID *owner_id, SceneCollection *sc, Object *ob, const bool free_us)
+{
+ LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data));
+
+ if (link == NULL) {
+ return false;
+ }
+
+ 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(owner_id, sc, ob);
+
+ if (GS(owner_id->name) == ID_SCE) {
+ if (free_us) {
+ BKE_libblock_free_us(bmain, ob);
+ }
+ else {
+ id_us_min(&ob->id);
+ }
+ }
+ else {
+ BLI_assert(GS(owner_id->name) == ID_GR);
+ }
+
+ return true;
+}
+
+/**
+ * Move object from a collection into another
+ */
+void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob)
+{
+ BKE_collection_object_add(owner_id, sc_dst, ob);
+ BKE_collection_object_remove(NULL, owner_id, sc_src, ob, false);
+}
+
+/**
+ * Remove object from all collections of scene
+ */
+bool BKE_collections_object_remove(Main *bmain, ID *owner_id, Object *ob, const bool free_us)
+{
+ bool removed = false;
+ if (GS(owner_id->name) == ID_SCE) {
+ BKE_scene_remove_rigidbody_object((Scene *)owner_id, ob);
+ }
+ else {
+ BLI_assert(GS(owner_id->name) == ID_GR);
+ }
+
+ FOREACH_SCENE_COLLECTION(owner_id, sc)
+ {
+ removed |= BKE_collection_object_remove(bmain, owner_id, sc, ob, free_us);
+ }
+ FOREACH_SCENE_COLLECTION_END
+ return removed;
+}
+
+static void layer_collection_sync(LayerCollection *lc_dst, LayerCollection *lc_src)
+{
+ lc_dst->flag = lc_src->flag;
+
+ /* Pending: sync overrides. */
+ IDP_MergeGroup(lc_dst->properties, lc_src->properties, true);
+
+ /* Continue recursively. */
+ LayerCollection *lc_dst_nested, *lc_src_nested;
+ lc_src_nested = lc_src->layer_collections.first;
+ for (lc_dst_nested = lc_dst->layer_collections.first;
+ lc_dst_nested && lc_src_nested;
+ lc_dst_nested = lc_dst_nested->next, lc_src_nested = lc_src_nested->next)
+ {
+ layer_collection_sync(lc_dst_nested, lc_src_nested);
+ }
+}
+
+/**
+ * Leave only the master collection in, remove everything else.
+ * @param group
+ */
+static void collection_group_cleanup(Group *group)
+{
+ /* Unlink all the LayerCollections. */
+ while (group->view_layer->layer_collections.last != NULL) {
+ BKE_collection_unlink(group->view_layer, group->view_layer->layer_collections.last);
+ }
+
+ /* Remove all the SceneCollections but the master. */
+ collection_free(group->collection, false);
+}
+
+/**
+ * Create a group from a collection
+ *
+ * Any ViewLayer that may have this the related SceneCollection linked is converted
+ * to a Group Collection.
+ */
+Group *BKE_collection_group_create(Main *bmain, Scene *scene, LayerCollection *lc_src)
+{
+ SceneCollection *sc_dst, *sc_src = lc_src->scene_collection;
+ LayerCollection *lc_dst;
+
+ /* The master collection can't be converted. */
+ if (sc_src == BKE_collection_master(&scene->id)) {
+ return NULL;
+ }
+
+ /* If a sub-collection of sc_dst is directly linked into a ViewLayer we can't convert. */
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *lc_child = view_layer->layer_collections.first; lc_child; lc_child = lc_child->next) {
+ if (is_collection_in_tree(lc_child->scene_collection, sc_src)) {
+ return NULL;
+ }
+ }
+ }
+
+ /* Create new group with the same data as the original collection. */
+ Group *group = BKE_group_add(bmain, sc_src->name);
+ collection_group_cleanup(group);
+
+ sc_dst = BKE_collection_add(&group->id, NULL, COLLECTION_TYPE_GROUP_INTERNAL, sc_src->name);
+ BKE_collection_copy_data(sc_dst, sc_src, 0);
+ FOREACH_SCENE_COLLECTION(&group->id, sc_group)
+ {
+ sc_group->type = COLLECTION_TYPE_GROUP_INTERNAL;
+ }
+ FOREACH_SCENE_COLLECTION_END
+
+ lc_dst = BKE_collection_link(group->view_layer, sc_dst);
+ layer_collection_sync(lc_dst, lc_src);
+
+ return group;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Outliner drag and drop */
+
+/**
+ * Find and return the SceneCollection that has \a sc_child as one of its directly
+ * nested SceneCollection.
+ *
+ * \param sc_parent Initial SceneCollection to look into recursively, usually the master collection
+ */
+static SceneCollection *find_collection_parent(const SceneCollection *sc_child, SceneCollection *sc_parent)
+{
+ for (SceneCollection *sc_nested = sc_parent->scene_collections.first; sc_nested; sc_nested = sc_nested->next) {
+ if (sc_nested == sc_child) {
+ return sc_parent;
+ }
+
+ SceneCollection *found = find_collection_parent(sc_child, sc_nested);
+ if (found) {
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Check if \a sc_reference is nested to \a sc_parent SceneCollection
+ */
+static bool is_collection_in_tree(const SceneCollection *sc_reference, SceneCollection *sc_parent)
+{
+ return find_collection_parent(sc_reference, sc_parent) != NULL;
+}
+
+bool BKE_collection_move_above(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src)
+{
+ /* Find the SceneCollection the sc_src belongs to */
+ SceneCollection *sc_master = master_collection_from_id(owner_id);
+
+ /* Master Layer can't be moved around*/
+ if (ELEM(sc_master, sc_src, sc_dst)) {
+ return false;
+ }
+
+ /* collection is already where we wanted it to be */
+ if (sc_dst->prev == sc_src) {
+ return false;
+ }
+
+ /* We can't move a collection fs the destiny collection
+ * is nested to the source collection */
+ if (is_collection_in_tree(sc_dst, sc_src)) {
+ return false;
+ }
+
+ SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
+ SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master);
+ BLI_assert(sc_src_parent);
+ BLI_assert(sc_dst_parent);
+
+ /* Remove sc_src from its parent */
+ BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+
+ /* Re-insert it where it belongs */
+ BLI_insertlinkbefore(&sc_dst_parent->scene_collections, sc_dst, sc_src);
+
+ /* Update the tree */
+ BKE_layer_collection_resync(owner_id, sc_src_parent);
+ BKE_layer_collection_resync(owner_id, sc_dst_parent);
+
+ return true;
+}
+
+bool BKE_collection_move_below(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src)
+{
+ /* Find the SceneCollection the sc_src belongs to */
+ SceneCollection *sc_master = master_collection_from_id(owner_id);
+
+ /* Master Layer can't be moved around*/
+ if (ELEM(sc_master, sc_src, sc_dst)) {
+ return false;
+ }
+
+ /* Collection is already where we wanted it to be */
+ if (sc_dst->next == sc_src) {
+ return false;
+ }
+
+ /* We can't move a collection if the destiny collection
+ * is nested to the source collection */
+ if (is_collection_in_tree(sc_dst, sc_src)) {
+ return false;
+ }
+
+ SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
+ SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master);
+ BLI_assert(sc_src_parent);
+ BLI_assert(sc_dst_parent);
+
+ /* Remove sc_src from its parent */
+ BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+
+ /* Re-insert it where it belongs */
+ BLI_insertlinkafter(&sc_dst_parent->scene_collections, sc_dst, sc_src);
+
+ /* Update the tree */
+ BKE_layer_collection_resync(owner_id, sc_src_parent);
+ BKE_layer_collection_resync(owner_id, sc_dst_parent);
+
+ return true;
+}
+
+bool BKE_collection_move_into(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src)
+{
+ /* Find the SceneCollection the sc_src belongs to */
+ SceneCollection *sc_master = master_collection_from_id(owner_id);
+ if (sc_src == sc_master) {
+ return false;
+ }
+
+ /* We can't move a collection if the destiny collection
+ * is nested to the source collection */
+ if (is_collection_in_tree(sc_dst, sc_src)) {
+ return false;
+ }
+
+ SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
+ BLI_assert(sc_src_parent);
+
+ /* collection is already where we wanted it to be */
+ if (sc_dst->scene_collections.last == sc_src) {
+ return false;
+ }
+
+ /* Remove sc_src from it */
+ BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+
+ /* Insert sc_src into sc_dst */
+ BLI_addtail(&sc_dst->scene_collections, sc_src);
+
+ /* Update the tree */
+ BKE_layer_collection_resync(owner_id, sc_src_parent);
+ BKE_layer_collection_resync(owner_id, sc_dst);
+
+ return true;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Iteractors */
+/* scene collection iteractor */
+
+typedef struct SceneCollectionsIteratorData {
+ ID *owner_id;
+ 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(ID *owner_id, SceneCollection ***collections_array, int *tot)
+{
+ SceneCollection *sc;
+ SceneCollection **array;
+
+ *collections_array = NULL;
+ *tot = 0;
+
+ if (owner_id == NULL) {
+ return;
+ }
+
+ sc = master_collection_from_id(owner_id);
+ BLI_assert(sc != NULL);
+ 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(BLI_Iterator *iter, void *data_in)
+{
+ ID *owner_id = data_in;
+ SceneCollectionsIteratorData *data = MEM_callocN(sizeof(SceneCollectionsIteratorData), __func__);
+
+ data->owner_id = owner_id;
+ iter->data = data;
+
+ scene_collections_array(owner_id, (SceneCollection ***)&data->array, &data->tot);
+ BLI_assert(data->tot != 0);
+
+ data->cur = 0;
+ iter->current = data->array[data->cur];
+}
+
+void BKE_scene_collections_iterator_next(struct BLI_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 BLI_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_next;
+ BLI_Iterator scene_collection_iter;
+} SceneObjectsIteratorData;
+
+void BKE_scene_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
+{
+ Scene *scene = data_in;
+ SceneObjectsIteratorData *data = MEM_callocN(sizeof(SceneObjectsIteratorData), __func__);
+ 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;
+ if (sc->objects.first != NULL) {
+ iter->current = ((LinkData *)sc->objects.first)->data;
+ }
+ else {
+ BKE_scene_objects_iterator_next(iter);
+ }
+}
+
+/**
+ * Gets the first unique object in the sequence
+ */
+static LinkData *object_base_unique(GSet *gs, LinkData *link)
+{
+ for (; link != NULL; link = link->next) {
+ Object *ob = link->data;
+ void **ob_key_p;
+ if (!BLI_gset_ensure_p_ex(gs, ob, &ob_key_p)) {
+ *ob_key_p = ob;
+ return link;
+ }
+ }
+ return NULL;
+}
+
+void BKE_scene_objects_iterator_next(BLI_Iterator *iter)
+{
+ SceneObjectsIteratorData *data = iter->data;
+ LinkData *link = data->link_next ? object_base_unique(data->visited, data->link_next) : NULL;
+
+ if (link) {
+ data->link_next = link->next;
+ 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_next = new_link->next;
+ iter->current = new_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(BLI_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 21e28f5180c..2f80fbbec46 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -47,6 +47,8 @@
#include "BKE_cloth.h"
#include "BKE_effect.h"
+#include "BKE_group.h"
+#include "BKE_layer.h"
#include "BKE_modifier.h"
#include "BKE_scene.h"
@@ -501,22 +503,22 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
/* objects in dupli groups, one level only for now */
if (ob->dup_group && level == 0) {
- GroupObject *go;
Group *group= ob->dup_group;
/* add objects */
- for (go= group->gobject.first; go; go= go->next)
- add_collision_object(objs, numobj, maxobj, go->ob, self, level+1, modifier_type);
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ add_collision_object(objs, numobj, maxobj, object, self, level+1, modifier_type);
+ }
+ FOREACH_GROUP_OBJECT_END
}
}
// return all collision objects in scene
// 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)
+Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
{
- Base *base;
Object **objs;
- GroupObject *go;
unsigned int numobj= 0, maxobj= 100;
int level = dupli ? 0 : 1;
@@ -525,16 +527,20 @@ Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int
/* gather all collision objects */
if (group) {
/* use specified group */
- for (go= group->gobject.first; go; go= go->next)
- add_collision_object(&objs, &numobj, &maxobj, go->ob, self, level, modifier_type);
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ add_collision_object(&objs, &numobj, &maxobj, object, self, level, modifier_type);
+ }
+ FOREACH_GROUP_OBJECT_END
}
else {
Scene *sce_iter;
+ Base *base;
/* add objects in same layer in scene */
for (SETLOOPER(scene, sce_iter, base)) {
- if ( base->lay & layer )
+ if ((base->flag & BASE_VISIBLED) != 0) {
add_collision_object(&objs, &numobj, &maxobj, base->object, self, level, modifier_type);
-
+ }
}
}
@@ -547,7 +553,7 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned
{
/* Need to check for active layers, too.
Otherwise this check fails if the objects are not on the same layer - DG */
- return get_collisionobjects_ext(scene, self, group, self->lay | scene->lay, numcollobj, modifier_type, true);
+ return get_collisionobjects_ext(scene, self, group, numcollobj, modifier_type, true);
}
static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, int level)
@@ -575,24 +581,28 @@ static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self,
/* objects in dupli groups, one level only for now */
if (ob->dup_group && level == 0) {
- GroupObject *go;
Group *group= ob->dup_group;
/* add objects */
- for (go= group->gobject.first; go; go= go->next)
- add_collider_cache_object(objs, go->ob, self, level+1);
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ add_collider_cache_object(objs, object, self, level+1);
+ }
+ FOREACH_GROUP_OBJECT_END
}
}
ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
{
- GroupObject *go;
ListBase *objs= NULL;
/* add object in same layer in scene */
if (group) {
- for (go= group->gobject.first; go; go= go->next)
- add_collider_cache_object(&objs, go->ob, self, 0);
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ add_collider_cache_object(&objs, object, self, 0);
+ }
+ FOREACH_GROUP_OBJECT_END
}
else {
Scene *sce_iter;
@@ -600,7 +610,7 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
/* add objects in same layer in scene */
for (SETLOOPER(scene, sce_iter, base)) {
- if (!self || (base->lay & self->lay))
+ if (!self || ((base->flag & BASE_VISIBLED) != 0))
add_collider_cache_object(&objs, base->object, self, 0);
}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index a5d0df88198..d429149f0c4 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -98,11 +98,6 @@
/* Constraint Target Macros */
#define VALID_CONS_TARGET(ct) ((ct) && (ct->tar))
-/* Workaround for cyclic depenndnecy with curves.
- * In such case curve_cache might not be ready yet,
- */
-#define CYCLIC_DEPENDENCY_WORKAROUND
-
/* ************************ Constraints - General Utilities *************************** */
/* These functions here don't act on any specific constraints, and are therefore should/will
* not require any of the special function-pointers afforded by the relevant constraint
@@ -689,7 +684,7 @@ static bConstraintTypeInfo CTI_CONSTRNAME = {
/* This function should be used for the get_target_matrix member of all
* constraints that are not picky about what happens to their target matrix.
*/
-static void default_get_tarmat(bConstraint *con, bConstraintOb *UNUSED(cob), bConstraintTarget *ct, float UNUSED(ctime))
+static void default_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *UNUSED(cob), bConstraintTarget *ct, float UNUSED(ctime))
{
if (VALID_CONS_TARGET(ct))
constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->flag, con->headtail);
@@ -1155,7 +1150,7 @@ static void kinematic_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
}
}
-static void kinematic_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void kinematic_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
bKinematicConstraint *data = con->data;
@@ -1242,7 +1237,9 @@ static void followpath_flush_tars(bConstraint *con, ListBase *list, bool no_copy
}
}
-static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void followpath_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx),
+ bConstraint *con, bConstraintOb *UNUSED(cob),
+ bConstraintTarget *ct, float UNUSED(ctime))
{
bFollowPathConstraint *data = con->data;
@@ -1257,13 +1254,7 @@ static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
* currently for paths to work it needs to go through the bevlist/displist system (ton)
*/
-#ifdef CYCLIC_DEPENDENCY_WORKAROUND
- if (ct->tar->curve_cache == NULL) {
- BKE_displist_make_curveTypes(cob->scene, ct->tar, false);
- }
-#endif
-
- if (ct->tar->curve_cache->path && ct->tar->curve_cache->path->data) {
+ if (ct->tar->curve_cache && ct->tar->curve_cache->path && ct->tar->curve_cache->path->data) {
float quat[4];
if ((data->followflag & FOLLOWPATH_STATIC) == 0) {
/* animated position along curve depending on time */
@@ -2024,21 +2015,19 @@ static void pycon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userd
}
/* Whether this approach is maintained remains to be seen (aligorith) */
-static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void pycon_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx),
+ bConstraint *con, bConstraintOb *UNUSED(cob),
+ bConstraintTarget *ct, float UNUSED(ctime))
{
#ifdef WITH_PYTHON
bPythonConstraint *data = con->data;
#endif
if (VALID_CONS_TARGET(ct)) {
-#ifdef CYCLIC_DEPENDENCY_WORKAROUND
- /* special exception for curves - depsgraph issues */
- if (ct->tar->type == OB_CURVE) {
- if (ct->tar->curve_cache == NULL) {
- BKE_displist_make_curveTypes(cob->scene, ct->tar, false);
- }
+ if (ct->tar->type == OB_CURVE && ct->tar->curve_cache == NULL) {
+ unit_m4(ct->matrix);
+ return;
}
-#endif
/* firstly calculate the matrix the normal way, then let the py-function override
* this matrix if it needs to do so
@@ -2142,7 +2131,7 @@ static void actcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
}
}
-static void actcon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void actcon_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
bActionConstraint *data = con->data;
@@ -3131,16 +3120,10 @@ static void clampto_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
}
}
-static void clampto_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void clampto_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx),
+ bConstraint *UNUSED(con), bConstraintOb *UNUSED(cob),
+ bConstraintTarget *ct, float UNUSED(ctime))
{
-#ifdef CYCLIC_DEPENDENCY_WORKAROUND
- if (VALID_CONS_TARGET(ct)) {
- if (ct->tar->curve_cache == NULL) {
- BKE_displist_make_curveTypes(cob->scene, ct->tar, false);
- }
- }
-#endif
-
/* technically, this isn't really needed for evaluation, but we don't know what else
* might end up calling this...
*/
@@ -3474,7 +3457,7 @@ static void shrinkwrap_flush_tars(bConstraint *con, ListBase *list, bool no_copy
}
-static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void shrinkwrap_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data;
@@ -3806,16 +3789,10 @@ static void splineik_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
}
}
-static void splineik_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void splineik_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx),
+ bConstraint *UNUSED(con), bConstraintOb *UNUSED(cob),
+ bConstraintTarget *ct, float UNUSED(ctime))
{
-#ifdef CYCLIC_DEPENDENCY_WORKAROUND
- if (VALID_CONS_TARGET(ct)) {
- if (ct->tar->curve_cache == NULL) {
- BKE_displist_make_curveTypes(cob->scene, ct->tar, false);
- }
- }
-#endif
-
/* technically, this isn't really needed for evaluation, but we don't know what else
* might end up calling this...
*/
@@ -4864,7 +4841,7 @@ bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan)
* None of the actual calculations of the matrices should be done here! Also, this function is
* not to be used by any new constraints, particularly any that have multiple targets.
*/
-void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime)
+void BKE_constraint_target_matrix_get(const struct EvaluationContext *eval_ctx, Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime)
{
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
@@ -4915,7 +4892,7 @@ void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index,
if (ct) {
if (cti->get_target_matrix)
- cti->get_target_matrix(con, cob, ct, ctime);
+ cti->get_target_matrix(eval_ctx, con, cob, ct, ctime);
copy_m4_m4(mat, ct->matrix);
}
@@ -4931,7 +4908,7 @@ void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index,
}
/* Get the list of targets required for solving a constraint */
-void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
+void BKE_constraint_targets_for_solving_get(const struct EvaluationContext *eval_ctx, bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
{
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
@@ -4949,7 +4926,7 @@ void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob
*/
if (cti->get_target_matrix) {
for (ct = targets->first; ct; ct = ct->next)
- cti->get_target_matrix(con, cob, ct, ctime);
+ cti->get_target_matrix(eval_ctx, con, cob, ct, ctime);
}
else {
for (ct = targets->first; ct; ct = ct->next)
@@ -4966,7 +4943,7 @@ void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob
* BKE_constraints_make_evalob and BKE_constraints_clear_evalob should be called before and
* after running this function, to sort out cob
*/
-void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime)
+void BKE_constraints_solve(const struct EvaluationContext *eval_ctx, ListBase *conlist, bConstraintOb *cob, float ctime)
{
bConstraint *con;
float oldmat[4][4];
@@ -5001,7 +4978,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime)
BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace, false);
/* prepare targets for constraint solving */
- BKE_constraint_targets_for_solving_get(con, cob, &targets, ctime);
+ BKE_constraint_targets_for_solving_get(eval_ctx, con, cob, &targets, ctime);
/* Solve the constraint and put result in cob->matrix */
cti->evaluate_constraint(con, cob, &targets);
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 4c01bfd35f2..7b7a7c8b7af 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -38,6 +38,9 @@
#include "DNA_object_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_workspace_types.h"
+
+#include "DEG_depsgraph.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@@ -47,9 +50,14 @@
#include "BLT_translation.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_sound.h"
+#include "BKE_workspace.h"
+
+#include "RE_engine.h"
#include "RNA_access.h"
@@ -66,10 +74,12 @@ struct bContext {
struct {
struct wmWindowManager *manager;
struct wmWindow *window;
+ struct WorkSpace *workspace;
struct bScreen *screen;
struct ScrArea *area;
struct ARegion *region;
struct ARegion *menu;
+ struct wmManipulatorGroup *manipulator_group;
struct bContextStore *store;
const char *operator_poll_msg; /* reason for poll failing */
} wm;
@@ -627,6 +637,11 @@ wmWindow *CTX_wm_window(const bContext *C)
return ctx_wm_python_context_get(C, "window", &RNA_Window, C->wm.window);
}
+WorkSpace *CTX_wm_workspace(const bContext *C)
+{
+ return ctx_wm_python_context_get(C, "workspace", &RNA_WorkSpace, C->wm.workspace);
+}
+
bScreen *CTX_wm_screen(const bContext *C)
{
return ctx_wm_python_context_get(C, "screen", &RNA_Screen, C->wm.screen);
@@ -659,6 +674,16 @@ struct ARegion *CTX_wm_menu(const bContext *C)
return C->wm.menu;
}
+struct wmManipulatorGroup *CTX_wm_manipulator_group(const bContext *C)
+{
+ return C->wm.manipulator_group;
+}
+
+struct wmMsgBus *CTX_wm_message_bus(const bContext *C)
+{
+ return C->wm.manager ? C->wm.manager->message_bus : NULL;
+}
+
struct ReportList *CTX_wm_reports(const bContext *C)
{
if (C->wm.manager)
@@ -826,9 +851,11 @@ void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
void CTX_wm_window_set(bContext *C, wmWindow *win)
{
C->wm.window = win;
- C->wm.screen = (win) ? win->screen : NULL;
- if (C->wm.screen)
- C->data.scene = C->wm.screen->scene;
+ if (win) {
+ C->data.scene = win->scene;
+ }
+ C->wm.workspace = (win) ? BKE_workspace_active_get(win->workspace_hook) : NULL;
+ C->wm.screen = (win) ? BKE_workspace_active_screen_get(win->workspace_hook) : NULL;
C->wm.area = NULL;
C->wm.region = NULL;
}
@@ -836,8 +863,6 @@ 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;
C->wm.area = NULL;
C->wm.region = NULL;
}
@@ -858,6 +883,11 @@ void CTX_wm_menu_set(bContext *C, ARegion *menu)
C->wm.menu = menu;
}
+void CTX_wm_manipulator_group_set(bContext *C, struct wmManipulatorGroup *mgroup)
+{
+ C->wm.manipulator_group = mgroup;
+}
+
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
{
C->wm.operator_poll_msg = msg;
@@ -896,10 +926,82 @@ Scene *CTX_data_scene(const bContext *C)
return C->data.scene;
}
-int CTX_data_mode_enum(const bContext *C)
+ViewLayer *CTX_data_view_layer(const bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
+ ViewLayer *view_layer;
+ if (ctx_data_pointer_verify(C, "view_layer", (void *)&view_layer)) {
+ return view_layer;
+ }
+ else {
+ return BKE_view_layer_from_workspace_get(CTX_data_scene(C), CTX_wm_workspace(C));
+ }
+}
+
+ViewRender *CTX_data_view_render(const bContext *C)
+{
+ ViewRender *view_render;
+
+ if (ctx_data_pointer_verify(C, "view_render", (void *)&view_render)) {
+ return view_render;
+ }
+ else {
+ Scene *scene = CTX_data_scene(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ return BKE_viewrender_get(scene, workspace);
+ }
+}
+
+RenderEngineType *CTX_data_engine_type(const bContext *C)
+{
+ ViewRender *view_render = CTX_data_view_render(C);
+ return RE_engines_find(view_render->engine_id);
+}
+
+/**
+ * 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 ViewLayer we use it.
+ * Otherwise we fallback to the active one of the ViewLayer.
+ */
+LayerCollection *CTX_data_layer_collection(const bContext *C)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *lc;
+
+ if (ctx_data_pointer_verify(C, "layer_collection", (void *)&lc)) {
+ if (BKE_view_layer_has_collection(view_layer, lc->scene_collection)) {
+ return lc;
+ }
+ }
+
+ /* fallback */
+ return BKE_layer_collection_get_active(view_layer);
+}
+
+SceneCollection *CTX_data_scene_collection(const bContext *C)
+{
+ SceneCollection *sc;
+ if (ctx_data_pointer_verify(C, "scene_collection", (void *)&sc)) {
+ if (BKE_view_layer_has_collection(CTX_data_view_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->id);
+}
+
+int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob)
+{
+ // Object *obedit = CTX_data_edit_object(C);
if (obedit) {
switch (obedit->type) {
case OB_MESH:
@@ -919,8 +1021,7 @@ int CTX_data_mode_enum(const bContext *C)
}
}
else {
- Object *ob = CTX_data_active_object(C);
-
+ // Object *ob = CTX_data_active_object(C);
if (ob) {
if (ob->mode & OB_MODE_POSE) return CTX_MODE_POSE;
else if (ob->mode & OB_MODE_SCULPT) return CTX_MODE_SCULPT;
@@ -934,6 +1035,12 @@ int CTX_data_mode_enum(const bContext *C)
return CTX_MODE_OBJECT;
}
+int CTX_data_mode_enum(const bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Object *obact = obedit ? NULL : CTX_data_active_object(C);
+ return CTX_data_mode_enum_ex(obedit, obact);
+}
/* would prefer if we can use the enum version below over this one - Campbell */
/* must be aligned with above enum */
@@ -1154,3 +1261,21 @@ int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list)
return ctx_data_collection_get(C, "editable_gpencil_strokes", list);
}
+Depsgraph *CTX_data_depsgraph(const bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ return BKE_scene_get_depsgraph(scene, view_layer, true);
+}
+
+void CTX_data_eval_ctx(const bContext *C, EvaluationContext *eval_ctx)
+{
+ BLI_assert(C != NULL);
+
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ RenderEngineType *engine_type = CTX_data_engine_type(C);
+ DEG_evaluation_context_init_from_scene(eval_ctx,
+ scene, view_layer, engine_type,
+ DAG_EVAL_VIEWPORT);
+}
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 56df8e51eba..d2ffbbcf27b 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -99,7 +99,8 @@ static int modifiers_disable_subsurf_temporary(Object *ob)
}
/* disable subsurf temporal, get mapped cos, and enable it */
-float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3]
+float (*BKE_crazyspace_get_mapped_editverts(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *obedit))[3]
{
Mesh *me = obedit->data;
DerivedMesh *dm;
@@ -109,13 +110,13 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3]
/* disable subsurf temporal, get mapped cos, and enable it */
if (modifiers_disable_subsurf_temporary(obedit)) {
/* need to make new derivemesh */
- makeDerivedMesh(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH, false);
+ makeDerivedMesh(eval_ctx, scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH, false);
}
/* now get the cage */
vertexcos = MEM_mallocN(sizeof(*vertexcos) * nverts, "vertexcos map");
- dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH);
+ dm = editbmesh_get_derived_cage(eval_ctx, scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH);
mesh_get_mapped_verts_coords(dm, vertexcos, nverts);
@@ -250,8 +251,9 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me, float (*origcos)[3], float (*mapped
/** returns an array of deform matrices for crazyspace correction, and the
* number of modifiers left */
-int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob, BMEditMesh *em,
- float (**deformmats)[3][3], float (**deformcos)[3])
+int BKE_crazyspace_get_first_deform_matrices_editbmesh(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, BMEditMesh *em,
+ float (**deformmats)[3][3], float (**deformcos)[3])
{
ModifierData *md;
DerivedMesh *dm;
@@ -290,7 +292,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob,
unit_m3(defmats[a]);
}
- mti->deformMatricesEM(md, ob, em, dm, deformedVerts, defmats,
+ mti->deformMatricesEM(md, eval_ctx, ob, em, dm, deformedVerts, defmats,
numVerts);
}
else
@@ -310,7 +312,9 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob,
return numleft;
}
-int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3])
+int BKE_sculpt_get_first_deform_matrices(
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, float (**deformmats)[3][3], float (**deformcos)[3])
{
ModifierData *md;
DerivedMesh *dm;
@@ -346,7 +350,7 @@ int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**defo
unit_m3(defmats[a]);
}
- if (mti->deformMatrices) mti->deformMatrices(md, ob, dm, deformedVerts, defmats, numVerts);
+ if (mti->deformMatrices) mti->deformMatrices(md, eval_ctx, ob, dm, deformedVerts, defmats, numVerts);
else break;
}
}
@@ -369,9 +373,9 @@ int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**defo
return numleft;
}
-void BKE_crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3])
+void BKE_crazyspace_build_sculpt(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3])
{
- int totleft = BKE_sculpt_get_first_deform_matrices(scene, ob, deformmats, deformcos);
+ int totleft = BKE_sculpt_get_first_deform_matrices(eval_ctx, scene, ob, deformmats, deformcos);
if (totleft) {
/* there are deformation modifier which doesn't support deformation matrices
@@ -396,7 +400,7 @@ void BKE_crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[
if (mti->deformMatrices && !deformed)
continue;
- mti->deformVerts(md, ob, NULL, deformedVerts, me->totvert, 0);
+ mti->deformVerts(md, eval_ctx, ob, NULL, deformedVerts, me->totvert, 0);
deformed = 1;
}
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 5f72abbadf3..ba9ccf94303 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -53,7 +53,6 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_font.h"
#include "BKE_global.h"
@@ -65,6 +64,8 @@
#include "BKE_object.h"
#include "BKE_material.h"
+#include "DEG_depsgraph.h"
+
/* globals */
/* local */
@@ -127,6 +128,8 @@ void BKE_curve_free(Curve *cu)
{
BKE_animdata_free((ID *)cu, false);
+ BKE_curve_batch_cache_free(cu);
+
BKE_nurbList_free(&cu->nurb);
BKE_curve_editfont_free(cu);
@@ -207,6 +210,7 @@ void BKE_curve_copy_data(Main *bmain, Curve *cu_dst, const Curve *cu_src, const
cu_dst->strinfo = MEM_dupallocN(cu_src->strinfo);
cu_dst->tb = MEM_dupallocN(cu_src->tb);
cu_dst->bb = MEM_dupallocN(cu_src->bb);
+ cu_dst->batch_cache = NULL;
if (cu_src->key) {
BKE_id_copy_ex(bmain, &cu_src->key->id, (ID **)&cu_dst->key, flag, false);
@@ -1620,7 +1624,7 @@ float *BKE_curve_surf_make_orco(Object *ob)
/* NOTE: This routine is tied to the order of vertex
* built by displist and as passed to the renderer.
*/
-float *BKE_curve_make_orco(Scene *scene, Object *ob, int *r_numVerts)
+float *BKE_curve_make_orco(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, int *r_numVerts)
{
Curve *cu = ob->data;
DispList *dl;
@@ -1628,7 +1632,7 @@ float *BKE_curve_make_orco(Scene *scene, Object *ob, int *r_numVerts)
float *fp, *coord_array;
ListBase disp = {NULL, NULL};
- BKE_displist_make_curveTypes_forOrco(scene, ob, &disp);
+ BKE_displist_make_curveTypes_forOrco(eval_ctx, scene, ob, &disp);
numVerts = 0;
for (dl = disp.first; dl; dl = dl->next) {
@@ -1719,8 +1723,9 @@ float *BKE_curve_make_orco(Scene *scene, Object *ob, int *r_numVerts)
/* ***************** BEVEL ****************** */
-void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp,
- const bool for_render, const bool use_render_resolution)
+void BKE_curve_bevel_make(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *disp,
+ const bool for_render, const bool use_render_resolution)
{
DispList *dl, *dlnew;
Curve *bevcu, *cu;
@@ -1744,7 +1749,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp,
facy = cu->bevobj->size[1];
if (for_render) {
- BKE_displist_make_curveTypes_forRender(scene, cu->bevobj, &bevdisp, NULL, false, use_render_resolution);
+ BKE_displist_make_curveTypes_forRender(eval_ctx, scene, cu->bevobj, &bevdisp, NULL, false, use_render_resolution);
dl = bevdisp.first;
}
else if (cu->bevobj->curve_cache) {
@@ -5153,7 +5158,7 @@ int BKE_curve_material_index_validate(Curve *cu)
}
if (!is_valid) {
- DAG_id_tag_update(&cu->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&cu->id, OB_RECALC_DATA);
return true;
}
else {
@@ -5220,7 +5225,7 @@ void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *t
/* **** Depsgraph evaluation **** */
-void BKE_curve_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+void BKE_curve_eval_geometry(const EvaluationContext *UNUSED(eval_ctx),
Curve *curve)
{
if (G.debug & G_DEBUG_DEPSGRAPH) {
@@ -5230,3 +5235,20 @@ void BKE_curve_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
BKE_curve_texspace_calc(curve);
}
}
+
+/* Draw Engine */
+void (*BKE_curve_batch_cache_dirty_cb)(Curve *cu, int mode) = NULL;
+void (*BKE_curve_batch_cache_free_cb)(Curve *cu) = NULL;
+
+void BKE_curve_batch_cache_dirty(Curve *cu, int mode)
+{
+ if (cu->batch_cache) {
+ BKE_curve_batch_cache_dirty_cb(cu, mode);
+ }
+}
+void BKE_curve_batch_cache_free(Curve *cu)
+{
+ if (cu->batch_cache) {
+ BKE_curve_batch_cache_free_cb(cu);
+ }
+}
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 68acb60f21a..3bf5784e674 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -390,37 +390,19 @@ static void layerSwap_tface(void *data, const int *corner_indices)
{
MTFace *tf = data;
float uv[4][2];
- static const short pin_flags[4] = { TF_PIN1, TF_PIN2, TF_PIN3, TF_PIN4 };
- static const char sel_flags[4] = { TF_SEL1, TF_SEL2, TF_SEL3, TF_SEL4 };
- short unwrap = tf->unwrap & ~(TF_PIN1 | TF_PIN2 | TF_PIN3 | TF_PIN4);
- char flag = tf->flag & ~(TF_SEL1 | TF_SEL2 | TF_SEL3 | TF_SEL4);
int j;
for (j = 0; j < 4; ++j) {
const int source_index = corner_indices[j];
-
copy_v2_v2(uv[j], tf->uv[source_index]);
-
- /* swap pinning flags around */
- if (tf->unwrap & pin_flags[source_index]) {
- unwrap |= pin_flags[j];
- }
-
- /* swap selection flags around */
- if (tf->flag & sel_flags[source_index]) {
- flag |= sel_flags[j];
- }
}
memcpy(tf->uv, uv, sizeof(tf->uv));
- tf->unwrap = unwrap;
- tf->flag = flag;
}
static void layerDefault_tface(void *data, int count)
{
- static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, NULL,
- 0, 0, TF_DYNAMIC | TF_CONVERTED, 0, 0};
+ static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
MTFace *tf = (MTFace *)data;
int i;
@@ -1190,6 +1172,15 @@ static void layerSwap_flnor(void *data, const int *corner_indices)
memcpy(flnors, nors, sizeof(nors));
}
+static void layerDefault_fmap(void *data, int count)
+{
+ int *fmap_num = (int *)data;
+ int i;
+ for (i = 0; i < count; i++) {
+ *fmap_num = -1;
+ }
+}
+
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */
{sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
@@ -1215,8 +1206,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 3 floats per normal vector */
{sizeof(float) * 3, "vec3f", 1, NULL, NULL, NULL, layerInterp_normal, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, layerCopyValue_normal},
- /* 9: CD_POLYINDEX */ /* DEPRECATED */
- {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* 9: CD_FACEMAP */
+ {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, layerDefault_fmap, NULL},
/* 10: CD_PROP_FLT */
{sizeof(MFloatProperty), "MFloatProperty", 1, N_("Float"), layerCopy_propFloat, NULL, NULL, NULL},
/* 11: CD_PROP_INT */
@@ -1228,10 +1219,9 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face},
/* 14: CD_ORCO */
{sizeof(float) * 3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
- /* 15: CD_MTEXPOLY */
+ /* 15: CD_MTEXPOLY */ /* DEPRECATED */
/* note, when we expose the UV Map / TexFace split to the user, change this back to face Texture */
- {sizeof(MTexPoly), "MTexPoly", 1, N_("UVMap") /* "Face Texture" */, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_tface},
+ {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 16: CD_MLOOPUV */
{sizeof(MLoopUV), "MLoopUV", 1, N_("UVMap"), NULL, NULL, layerInterp_mloopuv, NULL, NULL,
layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv,
@@ -1310,7 +1300,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace",
- /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags",
+ /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFaceMap",
/* 10-14 */ "CDMFloatProperty", "CDMIntProperty", "CDMStringProperty", "CDOrigSpace", "CDOrco",
/* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps",
/* 20-24 */ "CDPreviewMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDMRecast",
@@ -1325,41 +1315,41 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
const CustomDataMask CD_MASK_BAREMESH =
- CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MLOOP | CD_MASK_MPOLY | CD_MASK_BWEIGHT;
+ CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MLOOP | CD_MASK_MPOLY | CD_MASK_BWEIGHT | CD_MASK_FACEMAP;
const CustomDataMask CD_MASK_MESH =
CD_MASK_MVERT | CD_MASK_MEDGE |
CD_MASK_MDEFORMVERT |
CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS |
CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MPOLY | CD_MASK_MLOOP |
- CD_MASK_MTEXPOLY | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
+ CD_MASK_RECAST | CD_MASK_PAINT_MASK |
CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
- CD_MASK_CUSTOMLOOPNORMAL;
+ CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
const CustomDataMask CD_MASK_EDITMESH =
CD_MASK_MDEFORMVERT | CD_MASK_MLOOPUV |
- CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_SHAPE_KEYINDEX |
+ CD_MASK_MLOOPCOL | CD_MASK_SHAPE_KEYINDEX |
CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR |
CD_MASK_MDISPS | CD_MASK_SHAPEKEY | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
- CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_CUSTOMLOOPNORMAL;
+ CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
const CustomDataMask CD_MASK_DERIVEDMESH =
CD_MASK_MDEFORMVERT |
CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO |
- CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_PREVIEW_MLOOPCOL |
+ CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORCO | CD_MASK_TANGENT |
CD_MASK_PREVIEW_MCOL | CD_MASK_SHAPEKEY | CD_MASK_RECAST |
CD_MASK_ORIGINDEX | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
- CD_MASK_CUSTOMLOOPNORMAL;
+ CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
const CustomDataMask CD_MASK_BMESH =
- CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
+ CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL |
CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS |
CD_MASK_CREASE | CD_MASK_BWEIGHT | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
- CD_MASK_CUSTOMLOOPNORMAL;
+ CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
/**
* cover values copied by #BKE_mesh_loops_to_tessdata
*/
const CustomDataMask CD_MASK_FACECORNERS =
- CD_MASK_MTFACE | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
+ CD_MASK_MTFACE | CD_MASK_MLOOPUV |
CD_MASK_MCOL | CD_MASK_MLOOPCOL |
CD_MASK_PREVIEW_MCOL | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP |
@@ -1368,7 +1358,7 @@ const CustomDataMask CD_MASK_FACECORNERS =
const CustomDataMask CD_MASK_EVERYTHING =
CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_NORMAL /* | CD_MASK_POLYINDEX */ | CD_MASK_PROP_FLT |
- CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
+ CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_MLOOPUV |
CD_MASK_MLOOPCOL | CD_MASK_TANGENT | CD_MASK_MDISPS | CD_MASK_PREVIEW_MCOL | CD_MASK_CLOTH_ORCO | CD_MASK_RECAST |
/* BMESH ONLY START */
CD_MASK_MPOLY | CD_MASK_MLOOP | CD_MASK_SHAPE_KEYINDEX | CD_MASK_SHAPEKEY | CD_MASK_BWEIGHT | CD_MASK_CREASE |
@@ -1376,7 +1366,7 @@ const CustomDataMask CD_MASK_EVERYTHING =
/* BMESH ONLY END */
CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN |
CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
- CD_MASK_MLOOPTANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_CUSTOMLOOPNORMAL;
+ CD_MASK_MLOOPTANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
static const LayerTypeInfo *layerType_getInfo(int type)
{
@@ -2502,13 +2492,10 @@ void CustomData_set(const CustomData *data, int index, int type, const void *sou
/* BMesh functions */
/* needed to convert to/from different face reps */
-void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata,
- int totloop, int totpoly)
+void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int totloop)
{
- int i;
- for (i = 0; i < fdata->totlayer; i++) {
+ for (int i = 0; i < fdata->totlayer; i++) {
if (fdata->layers[i].type == CD_MTFACE) {
- CustomData_add_layer_named(pdata, CD_MTEXPOLY, CD_CALLOC, NULL, totpoly, fdata->layers[i].name);
CustomData_add_layer_named(ldata, CD_MLOOPUV, CD_CALLOC, NULL, totloop, fdata->layers[i].name);
}
else if (fdata->layers[i].type == CD_MCOL) {
@@ -2523,19 +2510,18 @@ void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *l
}
}
-void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total)
+void CustomData_from_bmeshpoly(
+ CustomData *fdata, CustomData *ldata, int total)
{
int i;
/* avoid accumulating extra layers */
- BLI_assert(!CustomData_from_bmeshpoly_test(fdata, pdata, ldata, false));
+ BLI_assert(!CustomData_from_bmeshpoly_test(fdata, ldata, false));
- for (i = 0; i < pdata->totlayer; i++) {
- if (pdata->layers[i].type == CD_MTEXPOLY) {
- CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC, NULL, total, pdata->layers[i].name);
- }
- }
for (i = 0; i < ldata->totlayer; i++) {
+ if (ldata->layers[i].type == CD_MLOOPUV) {
+ CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC, NULL, total, ldata->layers[i].name);
+ }
if (ldata->layers[i].type == CD_MLOOPCOL) {
CustomData_add_layer_named(fdata, CD_MCOL, CD_CALLOC, NULL, total, ldata->layers[i].name);
}
@@ -2553,7 +2539,7 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
}
}
- CustomData_bmesh_update_active_layers(fdata, pdata, ldata);
+ CustomData_bmesh_update_active_layers(fdata, ldata);
}
#ifndef NDEBUG
@@ -2563,13 +2549,13 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
* \param fallback: Use when there are no layers to handle,
* since callers may expect success or failure.
*/
-bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, CustomData *ldata, bool fallback)
+bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *ldata, bool fallback)
{
int a_num = 0, b_num = 0;
#define LAYER_CMP(l_a, t_a, l_b, t_b) \
((a_num += CustomData_number_of_layers(l_a, t_a)) == (b_num += CustomData_number_of_layers(l_b, t_b)))
- if (!LAYER_CMP(pdata, CD_MTEXPOLY, fdata, CD_MTFACE))
+ if (!LAYER_CMP(ldata, CD_MLOOPUV, fdata, CD_MTFACE))
return false;
if (!LAYER_CMP(ldata, CD_MLOOPCOL, fdata, CD_MCOL))
return false;
@@ -2591,25 +2577,21 @@ bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, Custom
#endif
-void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *pdata, CustomData *ldata)
+void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *ldata)
{
int act;
- if (CustomData_has_layer(pdata, CD_MTEXPOLY)) {
- act = CustomData_get_active_layer(pdata, CD_MTEXPOLY);
- CustomData_set_layer_active(ldata, CD_MLOOPUV, act);
+ if (CustomData_has_layer(ldata, CD_MLOOPUV)) {
+ act = CustomData_get_active_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_active(fdata, CD_MTFACE, act);
- act = CustomData_get_render_layer(pdata, CD_MTEXPOLY);
- CustomData_set_layer_render(ldata, CD_MLOOPUV, act);
+ act = CustomData_get_render_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_render(fdata, CD_MTFACE, act);
- act = CustomData_get_clone_layer(pdata, CD_MTEXPOLY);
- CustomData_set_layer_clone(ldata, CD_MLOOPUV, act);
+ act = CustomData_get_clone_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_clone(fdata, CD_MTFACE, act);
- act = CustomData_get_stencil_layer(pdata, CD_MTEXPOLY);
- CustomData_set_layer_stencil(ldata, CD_MLOOPUV, act);
+ act = CustomData_get_stencil_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_stencil(fdata, CD_MTFACE, act);
}
@@ -2633,25 +2615,21 @@ void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *pdata,
* used by do_versions in readfile.c when creating pdata and ldata for pre-bmesh
* meshes and needed to preserve active/render/clone/stencil flags set in pre-bmesh files
*/
-void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, CustomData *pdata, CustomData *ldata)
+void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, CustomData *ldata)
{
int act;
if (CustomData_has_layer(fdata, CD_MTFACE)) {
act = CustomData_get_active_layer(fdata, CD_MTFACE);
- CustomData_set_layer_active(pdata, CD_MTEXPOLY, act);
CustomData_set_layer_active(ldata, CD_MLOOPUV, act);
act = CustomData_get_render_layer(fdata, CD_MTFACE);
- CustomData_set_layer_render(pdata, CD_MTEXPOLY, act);
CustomData_set_layer_render(ldata, CD_MLOOPUV, act);
act = CustomData_get_clone_layer(fdata, CD_MTFACE);
- CustomData_set_layer_clone(pdata, CD_MTEXPOLY, act);
CustomData_set_layer_clone(ldata, CD_MLOOPUV, act);
act = CustomData_get_stencil_layer(fdata, CD_MTFACE);
- CustomData_set_layer_stencil(pdata, CD_MTEXPOLY, act);
CustomData_set_layer_stencil(ldata, CD_MLOOPUV, act);
}
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 3bc09c0173b..00b8063110d 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -79,7 +79,7 @@ CustomDataMask BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types
cddata_mask |= CD_MASK_MDEFORMVERT; /* Exception for vgroups :/ */
}
else if (cddata_type == CD_FAKE_UV) {
- cddata_mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV;
+ cddata_mask |= CD_MASK_MLOOPUV;
}
else if (cddata_type == CD_FAKE_LNOR) {
cddata_mask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL;
@@ -962,7 +962,7 @@ static bool data_transfer_layersmapping_generate(
}
else if (elem_type == ME_POLY) {
if (cddata_type == CD_FAKE_UV) {
- cddata_type = CD_MTEXPOLY;
+ cddata_type = CD_MLOOPUV;
}
if (!(cddata_type & CD_FAKE)) {
@@ -1010,7 +1010,8 @@ static bool data_transfer_layersmapping_generate(
* to get (as much as possible) exact copy of source data layout.
*/
void BKE_object_data_transfer_layout(
- Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, const bool use_delete,
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob_src, Object *ob_dst, const int data_types, const bool use_delete,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX])
{
DerivedMesh *dm_src;
@@ -1027,7 +1028,7 @@ void BKE_object_data_transfer_layout(
/* Get source DM.*/
dm_src_mask |= BKE_object_data_transfer_dttypes_to_cdmask(data_types);
- dm_src = mesh_get_derived_final(scene, ob_src, dm_src_mask);
+ dm_src = mesh_get_derived_final(eval_ctx, scene, ob_src, dm_src_mask);
if (!dm_src) {
return;
}
@@ -1085,9 +1086,9 @@ void BKE_object_data_transfer_layout(
}
bool BKE_object_data_transfer_dm(
- Scene *scene, Object *ob_src, Object *ob_dst, DerivedMesh *dm_dst, const int data_types, bool use_create,
- const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
- SpaceTransform *space_transform, const bool auto_transform,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob_src, Object *ob_dst, DerivedMesh *dm_dst,
+ const int data_types, bool use_create, const int map_vert_mode, const int map_edge_mode,
+ const int map_loop_mode, const int map_poly_mode, SpaceTransform *space_transform, const bool auto_transform,
const float max_distance, const float ray_radius, const float islands_handling_precision,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
@@ -1149,7 +1150,7 @@ bool BKE_object_data_transfer_dm(
* Also, we need to make a local copy of dm_src, otherwise we may end with concurrent creation
* of data in it (multi-threaded evaluation of the modifier stack, see T46672).
*/
- dm_src = dm_dst ? ob_src->derivedFinal : mesh_get_derived_final(scene, ob_src, dm_src_mask);
+ dm_src = dm_dst ? ob_src->derivedFinal : mesh_get_derived_final(eval_ctx, scene, ob_src, dm_src_mask);
if (!dm_src) {
return changed;
}
@@ -1457,16 +1458,16 @@ bool BKE_object_data_transfer_dm(
}
bool BKE_object_data_transfer_mesh(
- Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, const bool use_create,
- const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
- SpaceTransform *space_transform, const bool auto_transform,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob_src, Object *ob_dst, const int data_types,
+ const bool use_create, const int map_vert_mode, const int map_edge_mode, const int map_loop_mode,
+ const int map_poly_mode, SpaceTransform *space_transform, const bool auto_transform,
const float max_distance, const float ray_radius, const float islands_handling_precision,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
ReportList *reports)
{
return BKE_object_data_transfer_dm(
- scene, ob_src, ob_dst, NULL, data_types, use_create,
+ eval_ctx, scene, ob_src, ob_dst, NULL, data_types, use_create,
map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode,
space_transform, auto_transform,
max_distance, ray_radius, islands_handling_precision,
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index eec8d2478da..1fc83b69bfe 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -54,6 +54,7 @@
#include "BKE_customdata.h"
#include "BKE_data_transfer.h"
#include "BKE_deform.h" /* own include */
+#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_object_deform.h"
@@ -73,6 +74,8 @@ bDeformGroup *BKE_defgroup_new(Object *ob, const char *name)
BLI_addtail(&ob->defbase, defgroup);
defgroup_unique_name(defgroup, ob);
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+
return defgroup;
}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
deleted file mode 100644
index 30b7f15da7c..00000000000
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ /dev/null
@@ -1,3712 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2004 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/depsgraph.c
- * \ingroup bke
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#ifdef WIN32
-# include "BLI_winstuff.h"
-#endif
-
-#include "BLI_utildefines.h"
-#include "BLI_listbase.h"
-#include "BLI_ghash.h"
-#include "BLI_threads.h"
-
-#include "DNA_anim_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_cachefile_types.h"
-#include "DNA_group_types.h"
-#include "DNA_lamp_types.h"
-#include "DNA_lattice_types.h"
-#include "DNA_key_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_node_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_windowmanager_types.h"
-#include "DNA_movieclip_types.h"
-#include "DNA_mask_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_rigidbody_types.h"
-
-#include "BKE_anim.h"
-#include "BKE_animsys.h"
-#include "BKE_action.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_collision.h"
-#include "BKE_curve.h"
-#include "BKE_effect.h"
-#include "BKE_fcurve.h"
-#include "BKE_global.h"
-#include "BKE_idcode.h"
-#include "BKE_image.h"
-#include "BKE_key.h"
-#include "BKE_library.h"
-#include "BKE_main.h"
-#include "BKE_node.h"
-#include "BKE_material.h"
-#include "BKE_mball.h"
-#include "BKE_modifier.h"
-#include "BKE_object.h"
-#include "BKE_paint.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
-#include "BKE_scene.h"
-#include "BKE_screen.h"
-#include "BKE_tracking.h"
-
-#include "GPU_buffers.h"
-
-#include "atomic_ops.h"
-
-#include "depsgraph_private.h"
-
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_build.h"
-#include "DEG_depsgraph_debug.h"
-#include "DEG_depsgraph_query.h"
-
-#ifdef WITH_LEGACY_DEPSGRAPH
-
-static SpinLock threaded_update_lock;
-
-void DAG_init(void)
-{
- BLI_spin_init(&threaded_update_lock);
- DEG_register_node_types();
-}
-
-void DAG_exit(void)
-{
- BLI_spin_end(&threaded_update_lock);
- DEG_free_node_types();
-}
-
-/* Queue and stack operations for dag traversal
- *
- * the queue store a list of freenodes to avoid successive alloc/dealloc
- */
-
-DagNodeQueue *queue_create(int slots)
-{
- DagNodeQueue *queue;
- DagNodeQueueElem *elem;
- int i;
-
- queue = MEM_mallocN(sizeof(DagNodeQueue), "DAG queue");
- queue->freenodes = MEM_mallocN(sizeof(DagNodeQueue), "DAG queue");
- queue->count = 0;
- queue->maxlevel = 0;
- queue->first = queue->last = NULL;
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem3");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->first = queue->freenodes->last = elem;
-
- for (i = 1; i < slots; i++) {
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem4");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- }
- queue->freenodes->count = slots;
- return queue;
-}
-
-void queue_raz(DagNodeQueue *queue)
-{
- DagNodeQueueElem *elem;
-
- elem = queue->first;
- if (queue->freenodes->last)
- queue->freenodes->last->next = elem;
- else
- queue->freenodes->first = queue->freenodes->last = elem;
-
- elem->node = NULL;
- queue->freenodes->count++;
- while (elem->next) {
- elem = elem->next;
- elem->node = NULL;
- queue->freenodes->count++;
- }
- queue->freenodes->last = elem;
- queue->count = 0;
-}
-
-void queue_delete(DagNodeQueue *queue)
-{
- DagNodeQueueElem *elem;
- DagNodeQueueElem *temp;
-
- elem = queue->first;
- while (elem) {
- temp = elem;
- elem = elem->next;
- MEM_freeN(temp);
- }
-
- elem = queue->freenodes->first;
- while (elem) {
- temp = elem;
- elem = elem->next;
- MEM_freeN(temp);
- }
-
- MEM_freeN(queue->freenodes);
- MEM_freeN(queue);
-}
-
-/* insert in queue, remove in front */
-void push_queue(DagNodeQueue *queue, DagNode *node)
-{
- DagNodeQueueElem *elem;
- int i;
-
- if (node == NULL) {
- fprintf(stderr, "pushing null node\n");
- return;
- }
- /*fprintf(stderr, "BFS push : %s %d\n", ((ID *) node->ob)->name, queue->count);*/
-
- elem = queue->freenodes->first;
- if (elem != NULL) {
- queue->freenodes->first = elem->next;
- if (queue->freenodes->last == elem) {
- queue->freenodes->last = NULL;
- queue->freenodes->first = NULL;
- }
- queue->freenodes->count--;
- }
- else { /* alllocating more */
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem1");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->first = queue->freenodes->last = elem;
-
- for (i = 1; i < DAGQUEUEALLOC; i++) {
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem2");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- }
- queue->freenodes->count = DAGQUEUEALLOC;
-
- elem = queue->freenodes->first;
- queue->freenodes->first = elem->next;
- }
- elem->next = NULL;
- elem->node = node;
- if (queue->last != NULL)
- queue->last->next = elem;
- queue->last = elem;
- if (queue->first == NULL) {
- queue->first = elem;
- }
- queue->count++;
-}
-
-
-/* insert in front, remove in front */
-void push_stack(DagNodeQueue *queue, DagNode *node)
-{
- DagNodeQueueElem *elem;
- int i;
-
- elem = queue->freenodes->first;
- if (elem != NULL) {
- queue->freenodes->first = elem->next;
- if (queue->freenodes->last == elem) {
- queue->freenodes->last = NULL;
- queue->freenodes->first = NULL;
- }
- queue->freenodes->count--;
- }
- else { /* alllocating more */
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem1");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->first = queue->freenodes->last = elem;
-
- for (i = 1; i < DAGQUEUEALLOC; i++) {
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem2");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- }
- queue->freenodes->count = DAGQUEUEALLOC;
-
- elem = queue->freenodes->first;
- queue->freenodes->first = elem->next;
- }
- elem->next = queue->first;
- elem->node = node;
- queue->first = elem;
- if (queue->last == NULL)
- queue->last = elem;
- queue->count++;
-}
-
-
-DagNode *pop_queue(DagNodeQueue *queue)
-{
- DagNodeQueueElem *elem;
- DagNode *node;
-
- elem = queue->first;
- if (elem) {
- queue->first = elem->next;
- if (queue->last == elem) {
- queue->last = NULL;
- queue->first = NULL;
- }
- queue->count--;
- if (queue->freenodes->last)
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- if (queue->freenodes->first == NULL)
- queue->freenodes->first = elem;
- node = elem->node;
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->count++;
- return node;
- }
- else {
- fprintf(stderr, "return null\n");
- return NULL;
- }
-}
-
-DagNode *get_top_node_queue(DagNodeQueue *queue)
-{
- return queue->first->node;
-}
-
-DagForest *dag_init(void)
-{
- DagForest *forest;
- /* use callocN to init all zero */
- forest = MEM_callocN(sizeof(DagForest), "DAG root");
- forest->ugly_hack_sorry = true;
- return forest;
-}
-
-/* isdata = object data... */
-/* XXX this needs to be extended to be more flexible (so that not only objects are evaluated via depsgraph)... */
-static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node, int isdata)
-{
- FCurve *fcu;
- DagNode *node1;
-
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
- ChannelDriver *driver = fcu->driver;
- DriverVar *dvar;
- int isdata_fcu = (isdata) || (fcu->rna_path && strstr(fcu->rna_path, "modifiers["));
-
- /* loop over variables to get the target relationships */
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- /* only used targets */
- DRIVER_TARGETS_USED_LOOPER(dvar)
- {
- if (dtar->id) {
- /* FIXME: other data types need to be added here so that they can work! */
- if (GS(dtar->id->name) == ID_OB) {
- Object *ob = (Object *)dtar->id;
-
- /* normal channel-drives-channel */
- node1 = dag_get_node(dag, dtar->id);
-
- /* check if bone... */
- if ((ob->type == OB_ARMATURE) &&
- ( ((dtar->rna_path) && strstr(dtar->rna_path, "pose.bones[")) ||
- ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) ))
- {
- dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_DATA_DATA : DAG_RL_DATA_OB, "Driver");
- }
- /* check if ob data */
- else if (dtar->rna_path && strstr(dtar->rna_path, "data."))
- dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_DATA_DATA : DAG_RL_DATA_OB, "Driver");
- /* normal */
- else
- dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_OB_DATA : DAG_RL_OB_OB, "Driver");
- }
- }
- }
- DRIVER_TARGETS_LOOPER_END
- }
- }
-}
-
-/* XXX: forward def for material driver handling... */
-static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma);
-
-/* recursive handling for shader nodetree drivers */
-static void dag_add_shader_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree)
-{
- bNode *n;
-
- /* nodetree itself */
- if (ntree->adt) {
- dag_add_driver_relation(ntree->adt, dag, node, 1);
- }
-
- /* nodetree's nodes... */
- for (n = ntree->nodes.first; n; n = n->next) {
- if (n->id) {
- if (GS(n->id->name) == ID_MA) {
- dag_add_material_driver_relations(dag, node, (Material *)n->id);
- }
- else if (n->type == NODE_GROUP) {
- dag_add_shader_nodetree_driver_relations(dag, node, (bNodeTree *)n->id);
- }
- }
- }
-}
-
-/* recursive handling for material drivers */
-static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma)
-{
- /* Prevent infinite recursion by checking (and tagging the material) as having been visited
- * already (see build_dag()). This assumes ma->id.tag & LIB_TAG_DOIT isn't set by anything else
- * in the meantime... [#32017]
- */
- if (ma->id.tag & LIB_TAG_DOIT)
- return;
-
- ma->id.tag |= LIB_TAG_DOIT;
-
- /* material itself */
- if (ma->adt)
- dag_add_driver_relation(ma->adt, dag, node, 1);
-
- /* textures */
- // TODO...
- //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id);
-
- /* material's nodetree */
- if (ma->nodetree)
- dag_add_shader_nodetree_driver_relations(dag, node, ma->nodetree);
-
- ma->id.tag &= ~LIB_TAG_DOIT;
-}
-
-/* recursive handling for lamp drivers */
-static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *la)
-{
- /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited
- * already (see build_dag()). This assumes la->id.tag & LIB_TAG_DOIT isn't set by anything else
- * in the meantime... [#32017]
- */
- if (la->id.tag & LIB_TAG_DOIT)
- return;
-
- la->id.tag |= LIB_TAG_DOIT;
-
- /* lamp itself */
- if (la->adt)
- dag_add_driver_relation(la->adt, dag, node, 1);
-
- /* textures */
- // TODO...
- //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id);
-
- /* lamp's nodetree */
- if (la->nodetree)
- dag_add_shader_nodetree_driver_relations(dag, node, la->nodetree);
-
- la->id.tag &= ~LIB_TAG_DOIT;
-}
-
-static void create_collision_relation(DagForest *dag, DagNode *node, Object *ob1, const char *name)
-{
- DagNode *node2 = dag_get_node(dag, ob1);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, name);
-}
-
-void dag_add_collision_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name)
-{
- unsigned int numcollobj;
- Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli);
-
- for (unsigned int i = 0; i < numcollobj; i++) {
- Object *ob1 = collobjs[i];
-
- if (!fn || fn(ob1, modifiers_findByType(ob1, modifier_type))) {
- create_collision_relation(dag, node, ob1, name);
- }
- }
-
- if (collobjs)
- MEM_freeN(collobjs);
-}
-
-void dag_add_forcefield_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name)
-{
- ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false);
-
- if (effectors) {
- for (EffectorCache *eff = effectors->first; eff; eff = eff->next) {
- if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) {
- create_collision_relation(dag, node, eff->ob, name);
-
- if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
- create_collision_relation(dag, node, eff->pd->f_source, "Smoke Force Domain");
- }
-
- if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
- /* Actual code uses get_collider_cache */
- dag_add_collision_relations(dag, scene, ob, node, NULL, eff->ob->lay, eModifierType_Collision, NULL, true, "Force Absorption");
- }
- }
- }
- }
-
- pdEndEffectors(&effectors);
-}
-
-static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Object *ob, int mask)
-{
- bConstraint *con;
- DagNode *node;
- DagNode *node2;
- DagNode *node3;
- Key *key;
- ParticleSystem *psys;
- int addtoroot = 1;
-
- node = dag_get_node(dag, ob);
-
- if ((ob->data) && (mask & DAG_RL_DATA)) {
- node2 = dag_get_node(dag, ob->data);
- dag_add_relation(dag, node, node2, DAG_RL_DATA, "Object-Data Relation");
- node2->first_ancestor = ob;
- node2->ancestor_count += 1;
- }
-
- /* also build a custom data mask for dependencies that need certain layers */
-
- if (ob->type == OB_ARMATURE) {
- if (ob->pose) {
- bPoseChannel *pchan;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (con = pchan->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar && ct->tar != ob) {
- // fprintf(stderr, "armature %s target :%s\n", ob->id.name, target->id.name);
- node3 = dag_get_node(dag, ct->tar);
-
- if (ct->subtarget[0]) {
- dag_add_relation(dag, node3, node, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, cti->name);
- if (ct->tar->type == OB_MESH)
- node3->customdata_mask |= CD_MASK_MDEFORMVERT;
- }
- else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH,
- CONSTRAINT_TYPE_CLAMPTO,
- CONSTRAINT_TYPE_SPLINEIK,
- CONSTRAINT_TYPE_SHRINKWRAP))
- {
- dag_add_relation(dag, node3, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name);
- }
- else {
- dag_add_relation(dag, node3, node, DAG_RL_OB_DATA, cti->name);
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
-
- }
- }
- }
- }
-
- /* driver dependencies, nla modifiers */
-#if 0 // XXX old animation system
- if (ob->nlastrips.first) {
- bActionStrip *strip;
- bActionChannel *chan;
- for (strip = ob->nlastrips.first; strip; strip = strip->next) {
- if (strip->modifiers.first) {
- bActionModifier *amod;
- for (amod = strip->modifiers.first; amod; amod = amod->next) {
- if (amod->ob) {
- node2 = dag_get_node(dag, amod->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "NLA Strip Modifier");
- }
- }
- }
- }
- }
-#endif // XXX old animation system
- if (ob->adt)
- dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation
-
- key = BKE_key_from_object(ob);
- if (key && key->adt)
- dag_add_driver_relation(key->adt, dag, node, 1);
-
- if (ob->modifiers.first) {
- ModifierData *md;
-
- for (md = ob->modifiers.first; md; md = md->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- if (mti->updateDepgraph) mti->updateDepgraph(md, dag, bmain, scene, ob, node);
- }
- }
- if (ob->parent) {
- node2 = dag_get_node(dag, ob->parent);
-
- switch (ob->partype) {
- case PARSKEL:
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Parent");
- break;
- case PARVERT1: case PARVERT3:
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Vertex Parent");
- node2->customdata_mask |= CD_MASK_ORIGINDEX;
- break;
- case PARBONE:
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Bone Parent");
- break;
- default:
- if (ob->parent->type == OB_LATTICE)
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Lattice Parent");
- else if (ob->parent->type == OB_CURVE) {
- Curve *cu = ob->parent->data;
- if (cu->flag & CU_PATH)
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Curve Parent");
- else
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Curve Parent");
- }
- else
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Parent");
- break;
- }
- /* exception case: parent is duplivert */
- if (ob->type == OB_MBALL && (ob->parent->transflag & OB_DUPLIVERTS)) {
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Duplivert");
- }
-
- addtoroot = 0;
- }
- if (ob->proxy) {
- node2 = dag_get_node(dag, ob->proxy);
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Proxy");
- /* inverted relation, so addtoroot shouldn't be set to zero */
- }
-
- if (ob->transflag & OB_DUPLI) {
- if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
- GroupObject *go;
- for (go = ob->dup_group->gobject.first; go; go = go->next) {
- if (go->ob) {
- node2 = dag_get_node(dag, go->ob);
- /* node2 changes node1, this keeps animations updated in groups?? not logical? */
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Dupligroup");
- }
- }
- }
- }
-
- /* rigidbody force fields */
- if ((ob->type == OB_MESH) || (ob->type == OB_CURVE) || (ob->type == OB_LATTICE)) {
- if (ob->rigidbody_object && scene->rigidbody_world) {
- dag_add_forcefield_relations(dag, scene, ob, node, scene->rigidbody_world->effector_weights, true, 0, "Force Field");
- }
- }
-
- /* object data drivers */
- if (ob->data) {
- AnimData *adt = BKE_animdata_from_id((ID *)ob->data);
- if (adt)
- dag_add_driver_relation(adt, dag, node, 1);
- }
-
- /* object type/data relationships */
- switch (ob->type) {
- case OB_CAMERA:
- {
- Camera *cam = (Camera *)ob->data;
-
- if (cam->dof_ob) {
- node2 = dag_get_node(dag, cam->dof_ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Camera DoF");
- }
- break;
- }
- case OB_MBALL:
- {
- Object *mom = BKE_mball_basis_find(scene, ob);
-
- if (mom != ob) {
- node2 = dag_get_node(dag, mom);
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Metaball"); /* mom depends on children! */
- }
- break;
- }
- case OB_CURVE:
- case OB_FONT:
- {
- Curve *cu = ob->data;
-
- if (cu->bevobj) {
- node2 = dag_get_node(dag, cu->bevobj);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Bevel");
- }
- if (cu->taperobj) {
- node2 = dag_get_node(dag, cu->taperobj);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Taper");
- }
- if (ob->type == OB_FONT) {
- /* Really rather dirty hack. needs to support font family to work
- * reliably on render export.
- *
- * This totally mimics behavior of regular verts duplication with
- * parenting. The only tricky thing here is to get list of objects
- * used for the custom "font".
- *
- * This shouldn't harm so much because this code only runs on DAG
- * rebuild and this feature is not that commonly used.
- *
- * - sergey -
- */
- if (cu->family[0] != '\n') {
- ListBase *duplilist;
- DupliObject *dob;
- duplilist = object_duplilist(G.main->eval_ctx, scene, ob);
- for (dob = duplilist->first; dob; dob = dob->next) {
- node2 = dag_get_node(dag, dob->ob);
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Object Font");
- }
- free_object_duplilist(duplilist);
- }
-
- if (cu->textoncurve) {
- node2 = dag_get_node(dag, cu->textoncurve);
- /* Text on curve requires path to be evaluated for the target curve. */
- node2->eval_flags |= DAG_EVAL_NEED_CURVE_PATH;
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Texture On Curve");
- }
- }
- break;
- }
- }
-
- /* material drivers */
- if (ob->totcol) {
- int a;
-
- for (a = 1; a <= ob->totcol; a++) {
- Material *ma = give_current_material(ob, a);
-
- if (ma) {
- /* recursively figure out if there are drivers, and hook these up to this object */
- dag_add_material_driver_relations(dag, node, ma);
- }
- }
- }
- else if (ob->type == OB_LAMP) {
- dag_add_lamp_driver_relations(dag, node, ob->data);
- }
-
- /* particles */
- psys = ob->particlesystem.first;
- if (psys) {
- GroupObject *go;
-
- for (; psys; psys = psys->next) {
- BoidRule *rule = NULL;
- BoidState *state = NULL;
- ParticleSettings *part = psys->part;
-
- if (part->adt) {
- dag_add_driver_relation(part->adt, dag, node, 1);
- }
-
- dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation");
-
- if (!psys_check_enabled(ob, psys, G.is_rendering))
- continue;
-
- if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
- ParticleTarget *pt = psys->targets.first;
-
- for (; pt; pt = pt->next) {
- if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) {
- node2 = dag_get_node(dag, pt->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets");
- }
- }
- }
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- node2 = dag_get_node(dag, part->dup_ob);
- /* note that this relation actually runs in the wrong direction, the problem
- * is that dupli system all have this (due to parenting), and the render
- * engine instancing assumes particular ordering of objects in list */
- dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization");
- if (part->dup_ob->type == OB_MBALL)
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization");
- }
-
- if (part->ren_as == PART_DRAW_GR && part->dup_group) {
- for (go = part->dup_group->gobject.first; go; go = go->next) {
- node2 = dag_get_node(dag, go->ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization");
- }
- }
-
- if (part->type != PART_HAIR) {
- /* Actual code uses get_collider_cache */
- dag_add_collision_relations(dag, scene, ob, node, part->collision_group, ob->lay, eModifierType_Collision, NULL, true, "Particle Collision");
- }
- else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd && psys->clmd->coll_parms) {
- /* Hair uses cloth simulation, i.e. get_collision_objects */
- dag_add_collision_relations(dag, scene, ob, node, psys->clmd->coll_parms->group, ob->lay | scene->lay, eModifierType_Collision, NULL, true, "Hair Collision");
- }
-
- dag_add_forcefield_relations(dag, scene, ob, node, part->effector_weights, part->type == PART_HAIR, 0, "Particle Force Field");
-
- if (part->boids) {
- for (state = part->boids->states.first; state; state = state->next) {
- for (rule = state->rules.first; rule; rule = rule->next) {
- Object *ruleob = NULL;
- if (rule->type == eBoidRuleType_Avoid)
- ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
- else if (rule->type == eBoidRuleType_FollowLeader)
- ruleob = ((BoidRuleFollowLeader *)rule)->ob;
-
- if (ruleob) {
- node2 = dag_get_node(dag, ruleob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Boid Rule");
- }
- }
- }
- }
- }
- }
-
- /* object constraints */
- for (con = ob->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (!cti)
- continue;
-
- /* special case for camera tracking -- it doesn't use targets to define relations */
- if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
- int depends_on_camera = 0;
-
- if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
- bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
-
- if ((data->clip || data->flag & FOLLOWTRACK_ACTIVECLIP) && data->track[0])
- depends_on_camera = 1;
-
- if (data->depth_ob) {
- node2 = dag_get_node(dag, data->depth_ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
- }
- }
- else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER)
- depends_on_camera = 1;
-
- if (depends_on_camera && scene->camera) {
- node2 = dag_get_node(dag, scene->camera);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
- }
-
- dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
- addtoroot = 0;
- }
- else if (cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- Object *obt;
-
- if (ct->tar)
- obt = ct->tar;
- else
- continue;
-
- node2 = dag_get_node(dag, obt);
- if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
- else {
- if (ELEM(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
- if (obt->type == OB_MESH)
- node2->customdata_mask |= CD_MASK_MDEFORMVERT;
- }
- else if (cti->type == CONSTRAINT_TYPE_SHRINKWRAP) {
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name);
- }
- else {
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, cti->name);
- }
- }
- addtoroot = 0;
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
-
- if (addtoroot == 1)
- dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
-}
-
-static void build_dag_group(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Group *group, short mask)
-{
- GroupObject *go;
-
- if (group->id.tag & LIB_TAG_DOIT)
- return;
-
- group->id.tag |= LIB_TAG_DOIT;
-
- for (go = group->gobject.first; go; go = go->next) {
- build_dag_object(dag, scenenode, bmain, scene, go->ob, mask);
- if (go->ob->dup_group)
- build_dag_group(dag, scenenode, bmain, scene, go->ob->dup_group, mask);
- }
-}
-
-DagForest *build_dag(Main *bmain, Scene *sce, short mask)
-{
- Base *base;
- Object *ob;
- DagNode *node;
- DagNode *scenenode;
- DagForest *dag;
- DagAdjList *itA;
-
- dag = sce->theDag;
- if (dag)
- free_forest(dag);
- else {
- dag = dag_init();
- sce->theDag = dag;
- }
- dag->need_update = false;
-
- BKE_main_id_tag_idcode(bmain, ID_OB, LIB_TAG_DOIT, false);
-
- /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later [#32017] */
- BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false);
- BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false);
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* add base node for scene. scene is always the first node in DAG */
- scenenode = dag_add_node(dag, sce);
-
- /* add current scene objects */
- for (base = sce->base.first; base; base = base->next) {
- ob = base->object;
- ob->id.tag |= LIB_TAG_DOIT;
- build_dag_object(dag, scenenode, bmain, sce, ob, mask);
- if (ob->proxy)
- build_dag_object(dag, scenenode, bmain, sce, ob->proxy, mask);
- if (ob->dup_group)
- build_dag_group(dag, scenenode, bmain, sce, ob->dup_group, mask);
- }
-
- /* There might be situations when object from current scene depends on
- * objects form other scene AND objects from other scene has own
- * dependencies on objects from other scene.
- *
- * This is really important to include such indirect dependencies in order
- * to keep threaded update safe but since we don't really know if object is
- * coming from current scene or another scene we do rather stupid tag-based
- * check here: all the objects for which build_dag_object() was called are
- * getting tagged with LIB_TAG_DOIT. This way if some node has untagged
- * object we know it's an object from other scene.
- *
- * It should be enough to to it once, because if there's longer chain of
- * indirect dependencies, all the new nodes will be added to the end of the
- * list, meaning we'll keep covering them in this for loop.
- */
- for (node = sce->theDag->DagNode.first; node != NULL; node = node->next) {
- if (node->type == ID_OB) {
- ob = node->ob;
- if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
- ob->id.tag |= LIB_TAG_DOIT;
- build_dag_object(dag, scenenode, bmain, sce, ob, mask);
- if (ob->proxy)
- build_dag_object(dag, scenenode, bmain, sce, ob->proxy, mask);
- if (ob->dup_group)
- build_dag_group(dag, scenenode, bmain, sce, ob->dup_group, mask);
- }
- }
- }
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* Now all relations were built, but we need to solve 1 exceptional case;
- * When objects have multiple "parents" (for example parent + constraint working on same object)
- * the relation type has to be synced. One of the parents can change, and should give same event to child */
-
- /* nodes were callocced, so we can use node->color for temporal storage */
- for (node = sce->theDag->DagNode.first; node; node = node->next) {
- if (node->type == ID_OB) {
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- itA->node->color |= itA->type;
- }
- }
-
- /* also flush custom data mask */
- ((Object *)node->ob)->customdata_mask = node->customdata_mask;
-
- if (node->parent == NULL) {
- dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
- }
- }
- }
- /* now set relations equal, so that when only one parent changes, the correct recalcs are found */
- for (node = sce->theDag->DagNode.first; node; node = node->next) {
- if (node->type == ID_OB) {
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- itA->type |= itA->node->color;
- }
- }
- }
- }
-
- /* cycle detection and solving */
- // solve_cycles(dag);
-
- return dag;
-}
-
-
-void free_forest(DagForest *Dag)
-{ /* remove all nodes and deps */
- DagNode *tempN;
- DagAdjList *tempA;
- DagAdjList *itA;
- DagNode *itN = Dag->DagNode.first;
-
- while (itN) {
- itA = itN->child;
- while (itA) {
- tempA = itA;
- itA = itA->next;
- MEM_freeN(tempA);
- }
-
- itA = itN->parent;
- while (itA) {
- tempA = itA;
- itA = itA->next;
- MEM_freeN(tempA);
- }
-
- tempN = itN;
- itN = itN->next;
- MEM_freeN(tempN);
- }
-
- BLI_ghash_free(Dag->nodeHash, NULL, NULL);
- Dag->nodeHash = NULL;
- Dag->DagNode.first = NULL;
- Dag->DagNode.last = NULL;
- Dag->numNodes = 0;
-
-}
-
-DagNode *dag_find_node(DagForest *forest, void *fob)
-{
- if (forest->nodeHash)
- return BLI_ghash_lookup(forest->nodeHash, fob);
-
- return NULL;
-}
-
-static int dag_print_dependencies = 0; /* debugging */
-
-/* no checking of existence, use dag_find_node first or dag_get_node */
-DagNode *dag_add_node(DagForest *forest, void *fob)
-{
- DagNode *node;
-
- node = MEM_callocN(sizeof(DagNode), "DAG node");
- if (node) {
- node->ob = fob;
- node->color = DAG_WHITE;
-
- if (forest->ugly_hack_sorry) node->type = GS(((ID *) fob)->name); /* sorry, done for pose sorting */
- if (forest->numNodes) {
- ((DagNode *) forest->DagNode.last)->next = node;
- forest->DagNode.last = node;
- forest->numNodes++;
- }
- else {
- forest->DagNode.last = node;
- forest->DagNode.first = node;
- forest->numNodes = 1;
- }
-
- if (!forest->nodeHash)
- forest->nodeHash = BLI_ghash_ptr_new("dag_add_node gh");
- BLI_ghash_insert(forest->nodeHash, fob, node);
- }
-
- return node;
-}
-
-DagNode *dag_get_node(DagForest *forest, void *fob)
-{
- DagNode *node;
-
- node = dag_find_node(forest, fob);
- if (!node)
- node = dag_add_node(forest, fob);
- return node;
-}
-
-
-
-DagNode *dag_get_sub_node(DagForest *forest, void *fob)
-{
- DagNode *node;
- DagAdjList *mainchild, *prev = NULL;
-
- mainchild = ((DagNode *) forest->DagNode.first)->child;
- /* remove from first node (scene) adj list if present */
- while (mainchild) {
- if (mainchild->node == fob) {
- if (prev) {
- prev->next = mainchild->next;
- MEM_freeN(mainchild);
- break;
- }
- else {
- ((DagNode *) forest->DagNode.first)->child = mainchild->next;
- MEM_freeN(mainchild);
- break;
- }
- }
- prev = mainchild;
- mainchild = mainchild->next;
- }
- node = dag_find_node(forest, fob);
- if (!node)
- node = dag_add_node(forest, fob);
- return node;
-}
-
-static void dag_add_parent_relation(DagForest *UNUSED(forest), DagNode *fob1, DagNode *fob2, short rel, const char *name)
-{
- DagAdjList *itA = fob2->parent;
-
- while (itA) { /* search if relation exist already */
- if (itA->node == fob1) {
- itA->type |= rel;
- itA->count += 1;
- return;
- }
- itA = itA->next;
- }
- /* create new relation and insert at head. MALLOC alert! */
- itA = MEM_mallocN(sizeof(DagAdjList), "DAG adj list");
- itA->node = fob1;
- itA->type = rel;
- itA->count = 1;
- itA->next = fob2->parent;
- itA->name = name;
- fob2->parent = itA;
-}
-
-void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name)
-{
- DagAdjList *itA = fob1->child;
-
- /* parent relation is for cycle checking */
- dag_add_parent_relation(forest, fob1, fob2, rel, name);
-
- /* TODO(sergey): Find a better place for this. */
-#ifdef WITH_OPENSUBDIV
- if ((rel & (DAG_RL_DATA_DATA | DAG_RL_DATA_OB)) != 0) {
- if (fob1->type == ID_OB) {
- if ((fob1->eval_flags & DAG_EVAL_NEED_CPU) == 0) {
- Object *ob2 = fob2->ob;
- if (ob2->recalc & OB_RECALC_ALL) {
- /* Make sure object has all the data on CPU. */
- Object *ob1 = fob1->ob;
- ob1->recalc |= OB_RECALC_DATA;
- }
- fob1->eval_flags |= DAG_EVAL_NEED_CPU;
- }
- }
- }
-#endif
-
- while (itA) { /* search if relation exist already */
- if (itA->node == fob2) {
- itA->type |= rel;
- itA->count += 1;
- return;
- }
- itA = itA->next;
- }
- /* create new relation and insert at head. MALLOC alert! */
- itA = MEM_mallocN(sizeof(DagAdjList), "DAG adj list");
- itA->node = fob2;
- itA->type = rel;
- itA->count = 1;
- itA->next = fob1->child;
- itA->name = name;
- fob1->child = itA;
-}
-
-static const char *dag_node_name(DagForest *dag, DagNode *node)
-{
- if (node->ob == NULL)
- return "null";
- else if (dag->ugly_hack_sorry)
- return ((ID *)(node->ob))->name + 2;
- else
- return ((bPoseChannel *)(node->ob))->name;
-}
-
-static void dag_node_print_dependencies(DagForest *dag, DagNode *node)
-{
- DagAdjList *itA;
-
- printf("%s depends on:\n", dag_node_name(dag, node));
-
- for (itA = node->parent; itA; itA = itA->next)
- printf(" %s through %s\n", dag_node_name(dag, itA->node), itA->name);
- printf("\n");
-}
-
-static int dag_node_print_dependency_recurs(DagForest *dag, DagNode *node, DagNode *endnode)
-{
- DagAdjList *itA;
-
- if (node->color == DAG_BLACK)
- return 0;
-
- node->color = DAG_BLACK;
-
- if (node == endnode)
- return 1;
-
- for (itA = node->parent; itA; itA = itA->next) {
- if (dag_node_print_dependency_recurs(dag, itA->node, endnode)) {
- printf(" %s depends on %s through %s.\n", dag_node_name(dag, node), dag_node_name(dag, itA->node), itA->name);
- return 1;
- }
- }
-
- return 0;
-}
-
-static void dag_node_print_dependency_cycle(DagForest *dag, DagNode *startnode, DagNode *endnode, const char *name)
-{
- DagNode *node;
-
- for (node = dag->DagNode.first; node; node = node->next)
- node->color = DAG_WHITE;
-
- printf(" %s depends on %s through %s.\n", dag_node_name(dag, endnode), dag_node_name(dag, startnode), name);
- dag_node_print_dependency_recurs(dag, startnode, endnode);
- printf("\n");
-}
-
-static int dag_node_recurs_level(DagNode *node, int level)
-{
- DagAdjList *itA;
- int newlevel;
-
- node->color = DAG_BLACK; /* done */
- newlevel = ++level;
-
- for (itA = node->parent; itA; itA = itA->next) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->ancestor_count = dag_node_recurs_level(itA->node, level);
- newlevel = MAX2(newlevel, level + itA->node->ancestor_count);
- }
- else
- newlevel = MAX2(newlevel, level + itA->node->ancestor_count);
- }
-
- return newlevel;
-}
-
-static void dag_check_cycle(DagForest *dag)
-{
- DagNode *node;
- DagAdjList *itA;
-
- dag->is_acyclic = true;
-
- /* debugging print */
- if (dag_print_dependencies)
- for (node = dag->DagNode.first; node; node = node->next)
- dag_node_print_dependencies(dag, node);
-
- /* tag nodes unchecked */
- for (node = dag->DagNode.first; node; node = node->next)
- node->color = DAG_WHITE;
-
- for (node = dag->DagNode.first; node; node = node->next) {
- if (node->color == DAG_WHITE) {
- node->ancestor_count = dag_node_recurs_level(node, 0);
- }
- }
-
- /* check relations, and print errors */
- for (node = dag->DagNode.first; node; node = node->next) {
- for (itA = node->parent; itA; itA = itA->next) {
- if (itA->node->ancestor_count > node->ancestor_count) {
- if (node->ob && itA->node->ob) {
- dag->is_acyclic = false;
- printf("Dependency cycle detected:\n");
- dag_node_print_dependency_cycle(dag, itA->node, node, itA->name);
- }
- }
- }
- }
-
- /* parent relations are only needed for cycle checking, so free now */
- for (node = dag->DagNode.first; node; node = node->next) {
- while (node->parent) {
- itA = node->parent->next;
- MEM_freeN(node->parent);
- node->parent = itA;
- }
- }
-}
-
-/* debug test functions */
-
-void graph_print_queue(DagNodeQueue *nqueue)
-{
- DagNodeQueueElem *queueElem;
-
- queueElem = nqueue->first;
- while (queueElem) {
- fprintf(stderr, "** %s %i %i-%i ", ((ID *) queueElem->node->ob)->name, queueElem->node->color, queueElem->node->DFS_dvtm, queueElem->node->DFS_fntm);
- queueElem = queueElem->next;
- }
- fprintf(stderr, "\n");
-}
-
-void graph_print_queue_dist(DagNodeQueue *nqueue)
-{
- DagNodeQueueElem *queueElem;
- int count;
-
- queueElem = nqueue->first;
- count = 0;
- while (queueElem) {
- fprintf(stderr, "** %25s %2.2i-%2.2i ", ((ID *) queueElem->node->ob)->name, queueElem->node->DFS_dvtm, queueElem->node->DFS_fntm);
- while (count < queueElem->node->DFS_dvtm - 1) { fputc(' ', stderr); count++; }
- fputc('|', stderr);
- while (count < queueElem->node->DFS_fntm - 2) { fputc('-', stderr); count++; }
- fputc('|', stderr);
- fputc('\n', stderr);
- count = 0;
- queueElem = queueElem->next;
- }
- fprintf(stderr, "\n");
-}
-
-void graph_print_adj_list(DagForest *dag)
-{
- DagNode *node;
- DagAdjList *itA;
-
- node = dag->DagNode.first;
- while (node) {
- fprintf(stderr, "node : %s col: %i", ((ID *) node->ob)->name, node->color);
- itA = node->child;
- while (itA) {
- fprintf(stderr, "-- %s ", ((ID *) itA->node->ob)->name);
-
- itA = itA->next;
- }
- fprintf(stderr, "\n");
- node = node->next;
- }
-}
-
-/* ************************ API *********************** */
-
-/* mechanism to allow editors to be informed of depsgraph updates,
- * to do their own updates based on changes... */
-static void (*EditorsUpdateIDCb)(Main *bmain, ID *id) = NULL;
-static void (*EditorsUpdateSceneCb)(Main *bmain, Scene *scene, int updated) = NULL;
-static void (*EditorsUpdateScenePreCb)(Main *bmain, Scene *scene, bool time) = NULL;
-
-void DAG_editors_update_cb(void (*id_func)(Main *bmain, ID *id),
- void (*scene_func)(Main *bmain, Scene *scene, int updated),
- void (*scene_pre_func)(Main *bmain, Scene *scene, bool time))
-{
- if (DEG_depsgraph_use_legacy()) {
- EditorsUpdateIDCb = id_func;
- EditorsUpdateSceneCb = scene_func;
- EditorsUpdateScenePreCb = scene_pre_func;
- }
- else {
- /* New dependency graph. */
- DEG_editors_set_update_cb(id_func, scene_func, scene_pre_func);
- }
-}
-
-void DAG_editors_update_pre(Main *bmain, Scene *scene, bool time)
-{
- if (DEG_depsgraph_use_legacy()) {
- if (EditorsUpdateScenePreCb != NULL) {
- EditorsUpdateScenePreCb(bmain, scene, time);
- }
- }
- else {
- DEG_editors_update_pre(bmain, scene, time);
- }
-}
-
-static void dag_editors_id_update(Main *bmain, ID *id)
-{
- if (EditorsUpdateIDCb)
- EditorsUpdateIDCb(bmain, id);
-}
-
-static void dag_editors_scene_update(Main *bmain, Scene *scene, int updated)
-{
- if (EditorsUpdateSceneCb)
- EditorsUpdateSceneCb(bmain, scene, updated);
-}
-
-/* groups with objects in this scene need to be put in the right order as well */
-static void scene_sort_groups(Main *bmain, Scene *sce)
-{
- Base *base;
- Group *group;
- GroupObject *go;
- Object *ob;
-
- /* test; are group objects all in this scene? */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- ob->id.tag &= ~LIB_TAG_DOIT;
- }
- for (base = sce->base.first; base; base = base->next)
- base->object->id.tag |= LIB_TAG_DOIT;
-
- for (group = bmain->group.first; group; group = group->id.next) {
- for (go = group->gobject.first; go; go = go->next) {
- if ((go->ob->id.tag & LIB_TAG_DOIT) == 0)
- break;
- }
- /* this group is entirely in this scene */
- if (go == NULL) {
- ListBase listb = {NULL, NULL};
-
- for (go = group->gobject.first; go; go = go->next)
- go->ob->id.newid = (ID *)go;
-
- /* in order of sorted bases we reinsert group objects */
- for (base = sce->base.first; base; base = base->next) {
-
- if (base->object->id.newid) {
- go = (GroupObject *)base->object->id.newid;
- base->object->id.newid = NULL;
- BLI_remlink(&group->gobject, go);
- BLI_addtail(&listb, go);
- }
- }
- /* copy the newly sorted listbase */
- group->gobject = listb;
- }
- }
-
- /* newid abused for GroupObject, cleanup. */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- ob->id.newid = NULL;
- }
-}
-
-static void dag_scene_tag_rebuild(Scene *sce)
-{
- if (sce->theDag) {
- sce->theDag->need_update = true;
- }
-}
-
-/* free the depency graph */
-static void dag_scene_free(Scene *sce)
-{
- if (sce->theDag) {
- free_forest(sce->theDag);
- MEM_freeN(sce->theDag);
- sce->theDag = NULL;
- }
-}
-
-/* Check whether object data needs to be evaluated before it
- * might be used by others.
- *
- * Means that mesh object needs to have proper derivedFinal,
- * curves-typed objects are to have proper curve cache.
- *
- * Other objects or objects which are tagged for data update are
- * not considered to be in need of evaluation.
- */
-static bool check_object_needs_evaluation(Object *object)
-{
- if (object->recalc & OB_RECALC_ALL) {
- /* Object is tagged for update anyway, no need to re-tag it. */
- return false;
- }
-
- if (object->type == OB_MESH) {
- return object->derivedFinal == NULL;
- }
- else if (ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
- return object->curve_cache == NULL;
- }
-
- return false;
-}
-
-/* Check whether object data is tagged for update. */
-static bool check_object_tagged_for_update(Object *object)
-{
- if (object->recalc & OB_RECALC_ALL) {
- return true;
- }
-
- if (ELEM(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
- ID *data_id = object->data;
- return (data_id->tag & (LIB_TAG_ID_RECALC_DATA | LIB_TAG_ID_RECALC)) != 0;
- }
-
- return false;
-}
-
-/* Flush changes from tagged objects in the scene to their
- * dependencies which are not evaluated yet.
- *
- * This is needed to ensure all the dependencies are met
- * before objects gets handled by object_handle_update(),
- *
- * This is needed when visible layers are changed or changing
- * scene graph layout which involved usage of objects which
- * aren't in the scene or weren't visible yet.
- */
-static void dag_invisible_dependencies_flush(Scene *scene)
-{
- DagNode *root_node = scene->theDag->DagNode.first, *node;
- DagNodeQueue *queue;
-
- for (node = root_node; node != NULL; node = node->next) {
- node->color = DAG_WHITE;
- }
-
- queue = queue_create(DAGQUEUEALLOC);
-
- for (node = root_node; node != NULL; node = node->next) {
- if (node->color == DAG_WHITE) {
- push_stack(queue, node);
- node->color = DAG_GRAY;
-
- while (queue->count) {
- DagNode *current_node = get_top_node_queue(queue);
- DagAdjList *itA;
- bool skip = false;
-
- for (itA = current_node->child; itA; itA = itA->next) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->color = DAG_GRAY;
- push_stack(queue, itA->node);
- skip = true;
- break;
- }
- }
-
- if (!skip) {
- current_node = pop_queue(queue);
-
- if (current_node->type == ID_OB) {
- Object *current_object = current_node->ob;
- if (check_object_needs_evaluation(current_object)) {
- for (itA = current_node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- Object *object = itA->node->ob;
- if (check_object_tagged_for_update(object)) {
- current_object->recalc |= OB_RECALC_OB | OB_RECALC_DATA;
- }
- }
- }
- }
- }
- node->color = DAG_BLACK;
- }
- }
- }
- }
-
- queue_delete(queue);
-}
-
-static void dag_invisible_dependencies_check_flush(Main *bmain, Scene *scene)
-{
- if (DAG_id_type_tagged(bmain, ID_OB) ||
- DAG_id_type_tagged(bmain, ID_ME) || /* Mesh */
- DAG_id_type_tagged(bmain, ID_CU) || /* Curve */
- DAG_id_type_tagged(bmain, ID_MB) || /* MetaBall */
- DAG_id_type_tagged(bmain, ID_LT)) /* Lattice */
- {
- dag_invisible_dependencies_flush(scene);
- }
-}
-
-/* sort the base list on dependency order */
-static void dag_scene_build(Main *bmain, Scene *sce)
-{
- DagNode *node, *rootnode;
- DagNodeQueue *nqueue;
- DagAdjList *itA;
- int time;
- int skip = 0;
- ListBase tempbase;
- Base *base;
-
- BLI_listbase_clear(&tempbase);
-
- build_dag(bmain, sce, DAG_RL_ALL_BUT_DATA);
-
- dag_check_cycle(sce->theDag);
-
- nqueue = queue_create(DAGQUEUEALLOC);
-
- for (node = sce->theDag->DagNode.first; node; node = node->next) {
- node->color = DAG_WHITE;
- }
-
- time = 1;
-
- rootnode = sce->theDag->DagNode.first;
- rootnode->color = DAG_GRAY;
- time++;
- push_stack(nqueue, rootnode);
-
- while (nqueue->count) {
-
- skip = 0;
- node = get_top_node_queue(nqueue);
-
- itA = node->child;
- while (itA != NULL) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->DFS_dvtm = time;
- itA->node->color = DAG_GRAY;
-
- time++;
- push_stack(nqueue, itA->node);
- skip = 1;
- break;
- }
- itA = itA->next;
- }
-
- if (!skip) {
- if (node) {
- node = pop_queue(nqueue);
- if (node->ob == sce) /* we are done */
- break;
- node->color = DAG_BLACK;
-
- time++;
- base = sce->base.first;
- while (base && base->object != node->ob)
- base = base->next;
- if (base) {
- BLI_remlink(&sce->base, base);
- BLI_addhead(&tempbase, base);
- }
- }
- }
- }
-
- /* temporal correction for circular dependencies */
- base = sce->base.first;
- while (base) {
- BLI_remlink(&sce->base, base);
- BLI_addhead(&tempbase, base);
- //if (G.debug & G_DEBUG)
- printf("cyclic %s\n", base->object->id.name);
- base = sce->base.first;
- }
-
- sce->base = tempbase;
- queue_delete(nqueue);
-
- /* all groups with objects in this scene gets resorted too */
- scene_sort_groups(bmain, sce);
-
- if (G.debug & G_DEBUG) {
- printf("\nordered\n");
- for (base = sce->base.first; base; base = base->next) {
- printf(" %s\n", base->object->id.name);
- }
- }
-
- /* Make sure that new dependencies which came from invisible layers
- * are tagged for update (if they're needed for objects which were
- * tagged for update).
- */
- dag_invisible_dependencies_check_flush(bmain, sce);
-}
-
-/* clear all dependency graphs */
-void DAG_relations_tag_update(Main *bmain)
-{
- if (DEG_depsgraph_use_legacy()) {
- Scene *sce;
- for (sce = bmain->scene.first; sce; sce = sce->id.next) {
- dag_scene_tag_rebuild(sce);
- }
- }
- else {
- /* New dependency graph. */
- DEG_relations_tag_update(bmain);
- }
-}
-
-/* rebuild dependency graph only for a given scene */
-void DAG_scene_relations_rebuild(Main *bmain, Scene *sce)
-{
- if (DEG_depsgraph_use_legacy()) {
- dag_scene_free(sce);
- DAG_scene_relations_update(bmain, sce);
- }
- else {
- /* New dependency graph. */
- DEG_scene_relations_rebuild(bmain, sce);
- }
-}
-
-/* create dependency graph if it was cleared or didn't exist yet */
-void DAG_scene_relations_update(Main *bmain, Scene *sce)
-{
- if (DEG_depsgraph_use_legacy()) {
- if (!sce->theDag || sce->theDag->need_update)
- dag_scene_build(bmain, sce);
- }
- else {
- /* New dependency graph. */
- DEG_scene_relations_update(bmain, sce);
- }
-}
-
-void DAG_scene_relations_validate(Main *bmain, Scene *sce)
-{
- if (!DEG_depsgraph_use_legacy()) {
- DEG_debug_scene_relations_validate(bmain, sce);
- }
-}
-
-void DAG_scene_free(Scene *sce)
-{
- if (DEG_depsgraph_use_legacy()) {
- if (sce->theDag) {
- free_forest(sce->theDag);
- MEM_freeN(sce->theDag);
- sce->theDag = NULL;
- }
- }
- else {
- if (sce->depsgraph) {
- DEG_graph_free(sce->depsgraph);
- sce->depsgraph = NULL;
- }
- }
-}
-
-static void lib_id_recalc_tag(Main *bmain, ID *id)
-{
- id->tag |= LIB_TAG_ID_RECALC;
- DAG_id_type_tag(bmain, GS(id->name));
-}
-
-static void lib_id_recalc_data_tag(Main *bmain, ID *id)
-{
- id->tag |= LIB_TAG_ID_RECALC_DATA;
- DAG_id_type_tag(bmain, GS(id->name));
-}
-
-/* node was checked to have lasttime != curtime and is if type ID_OB */
-static void flush_update_node(Main *bmain, DagNode *node, unsigned int layer, int curtime)
-{
- DagAdjList *itA;
- Object *ob, *obc;
- int oldflag;
- bool changed = false;
- unsigned int all_layer;
-
- node->lasttime = curtime;
-
- ob = node->ob;
- if (ob && (ob->recalc & OB_RECALC_ALL)) {
- all_layer = node->scelay;
-
- /* got an object node that changes, now check relations */
- for (itA = node->child; itA; itA = itA->next) {
- all_layer |= itA->lay;
- /* the relationship is visible */
- if ((itA->lay & layer)) { // XXX || (itA->node->ob == obedit)
- if (itA->node->type == ID_OB) {
- obc = itA->node->ob;
- oldflag = obc->recalc;
-
- /* got a ob->obc relation, now check if flag needs flush */
- if (ob->recalc & OB_RECALC_OB) {
- if (itA->type & DAG_RL_OB_OB) {
- //printf("ob %s changes ob %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &obc->id);
- }
- if (itA->type & DAG_RL_OB_DATA) {
- //printf("ob %s changes obdata %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obc->id);
- }
- }
- if (ob->recalc & OB_RECALC_DATA) {
- if (itA->type & DAG_RL_DATA_OB) {
- //printf("obdata %s changes ob %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &obc->id);
- }
- if (itA->type & DAG_RL_DATA_DATA) {
- //printf("obdata %s changes obdata %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obc->id);
- }
- }
- if (oldflag != obc->recalc) changed = 1;
- }
- }
- }
- /* even nicer, we can clear recalc flags... */
- if ((all_layer & layer) == 0) { // XXX && (ob != obedit)) {
- /* but existing displaylists or derivedmesh should be freed */
- if (ob->recalc & OB_RECALC_DATA)
- BKE_object_free_derived_caches(ob);
-
- ob->recalc &= ~OB_RECALC_ALL;
- }
- }
-
- /* check case where child changes and parent forcing obdata to change */
- /* should be done regardless if this ob has recalc set */
- /* could merge this in with loop above...? (ton) */
- for (itA = node->child; itA; itA = itA->next) {
- /* the relationship is visible */
- if ((itA->lay & layer)) { // XXX || (itA->node->ob == obedit)
- if (itA->node->type == ID_OB) {
- obc = itA->node->ob;
- /* child moves */
- if ((obc->recalc & OB_RECALC_ALL) == OB_RECALC_OB) {
- /* parent has deforming info */
- if (itA->type & (DAG_RL_OB_DATA | DAG_RL_DATA_DATA)) {
- // printf("parent %s changes ob %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obc->id);
- }
- }
- }
- }
- }
-
- /* we only go deeper if node not checked or something changed */
- for (itA = node->child; itA; itA = itA->next) {
- if (changed || itA->node->lasttime != curtime)
- flush_update_node(bmain, itA->node, layer, curtime);
- }
-
-}
-
-/* node was checked to have lasttime != curtime, and is of type ID_OB */
-static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
-{
- DagAdjList *itA;
-
- node->lasttime = curtime;
- node->lay = node->scelay;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- if (itA->node->lasttime != curtime) {
- itA->lay = flush_layer_node(sce, itA->node, curtime); /* lay is only set once for each relation */
- }
- else {
- itA->lay = itA->node->lay;
- }
-
- node->lay |= itA->lay;
- }
- }
-
- return node->lay;
-}
-
-/* node was checked to have lasttime != curtime, and is of type ID_OB */
-static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node,
- int curtime, unsigned int lay, bool reset)
-{
- DagAdjList *itA;
- Object *ob;
-
- node->lasttime = curtime;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- if (itA->node->lasttime != curtime) {
- ob = (Object *)(itA->node->ob);
-
- if (reset || (ob->recalc & OB_RECALC_ALL)) {
- if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) {
- /* Don't tag nodes which are on invisible layer. */
- if (itA->node->lay & lay) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
- }
-
- flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, true);
- }
- else
- flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, false);
- }
- }
- }
-}
-
-/* flush layer flags to dependencies */
-static void dag_scene_flush_layers(Scene *sce, int lay)
-{
- DagNode *node, *firstnode;
- DagAdjList *itA;
- Base *base;
- int lasttime;
-
- firstnode = sce->theDag->DagNode.first; /* always scene node */
-
- for (itA = firstnode->child; itA; itA = itA->next)
- itA->lay = 0;
-
- sce->theDag->time++; /* so we know which nodes were accessed */
- lasttime = sce->theDag->time;
-
- /* update layer flags in nodes */
- for (base = sce->base.first; base; base = base->next) {
- node = dag_get_node(sce->theDag, base->object);
- node->scelay = base->object->lay;
- }
-
- /* ensure cameras are set as if they are on a visible layer, because
- * they ared still used for rendering or setting the camera view
- *
- * XXX, this wont work for local view / unlocked camera's */
- if (sce->camera) {
- node = dag_get_node(sce->theDag, sce->camera);
- node->scelay |= lay;
- }
-
-#ifdef DURIAN_CAMERA_SWITCH
- {
- TimeMarker *m;
-
- for (m = sce->markers.first; m; m = m->next) {
- if (m->camera) {
- node = dag_get_node(sce->theDag, m->camera);
- node->scelay |= lay;
- }
- }
- }
-#endif
-
- /* flush layer nodes to dependencies */
- for (itA = firstnode->child; itA; itA = itA->next)
- if (itA->node->lasttime != lasttime && itA->node->type == ID_OB)
- flush_layer_node(sce, itA->node, lasttime);
-}
-
-static void dag_tag_renderlayers(Scene *sce, unsigned int lay)
-{
- if (sce->nodetree) {
- bNode *node;
- Base *base;
- unsigned int lay_changed = 0;
-
- for (base = sce->base.first; base; base = base->next)
- if (base->lay & lay)
- if (base->object->recalc)
- lay_changed |= base->lay;
-
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->id == (ID *)sce) {
- SceneRenderLayer *srl = BLI_findlink(&sce->r.layers, node->custom1);
- if (srl && (srl->lay & lay_changed))
- nodeUpdate(sce->nodetree, node);
- }
- }
- }
-}
-
-/* flushes all recalc flags in objects down the dependency tree */
-void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const short time)
-{
- DagNode *firstnode;
- DagAdjList *itA;
- Object *ob;
- int lasttime;
-
- if (!DEG_depsgraph_use_legacy()) {
- DEG_scene_flush_update(bmain, sce);
- return;
- }
-
- if (sce->theDag == NULL || sce->theDag->need_update) {
- printf("DAG zero... not allowed to happen!\n");
- DAG_scene_relations_update(bmain, sce);
- }
-
- firstnode = sce->theDag->DagNode.first; /* always scene node */
-
- /* first we flush the layer flags */
- dag_scene_flush_layers(sce, lay);
-
- /* then we use the relationships + layer info to flush update events */
- sce->theDag->time++; /* so we know which nodes were accessed */
- lasttime = sce->theDag->time;
- for (itA = firstnode->child; itA; itA = itA->next)
- if (itA->node->lasttime != lasttime && itA->node->type == ID_OB)
- flush_update_node(bmain, itA->node, lay, lasttime);
-
- /* if update is not due to time change, do pointcache clears */
- if (!time) {
- sce->theDag->time++; /* so we know which nodes were accessed */
- lasttime = sce->theDag->time;
- for (itA = firstnode->child; itA; itA = itA->next) {
- if (itA->node->lasttime != lasttime && itA->node->type == ID_OB) {
- ob = (Object *)(itA->node->ob);
-
- if (ob->recalc & OB_RECALC_ALL) {
- if (BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH)) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
-
- flush_pointcache_reset(bmain, sce, itA->node, lasttime,
- lay, true);
- }
- else
- flush_pointcache_reset(bmain, sce, itA->node, lasttime,
- lay, false);
- }
- }
- }
-
- dag_tag_renderlayers(sce, lay);
-}
-
-static bool modifier_nlastrips_use_time(ListBase *strips)
-{
- NlaStrip *strip;
-
- if (strips) {
- for (strip = strips->first; strip; strip = strip->next) {
- if (modifier_nlastrips_use_time(&strip->strips)) {
- return true;
- }
- else if (strip->act) {
- FCurve *fcu;
-
- for (fcu = strip->act->curves.first; fcu; fcu = fcu->next) {
- if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-static bool object_modifiers_use_time(Object *ob)
-{
- ModifierData *md;
-
- /* check if a modifier in modifier stack needs time input */
- for (md = ob->modifiers.first; md; md = md->next) {
- if (modifier_dependsOnTime(md))
- return true;
- }
-
- /* check whether any modifiers are animated */
- if (ob->adt) {
- AnimData *adt = ob->adt;
- NlaTrack *nlt;
- FCurve *fcu;
-
- /* action - check for F-Curves with paths containing 'modifiers[' */
- if (adt->action) {
- for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
- if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return true;
- }
- }
-
- /* This here allows modifier properties to get driven and still update properly
- *
- * Workaround to get [#26764] (e.g. subsurf levels not updating when animated/driven)
- * working, without the updating problems ([#28525] [#28690] [#28774] [#28777]) caused
- * by the RNA updates cache introduced in r.38649
- */
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
- if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return true;
- }
-
- /* Also check NLA Strips... [#T45938] */
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- if (modifier_nlastrips_use_time(&nlt->strips))
- return true;
- }
- }
-
- return false;
-}
-
-static short animdata_use_time(AnimData *adt)
-{
- NlaTrack *nlt;
-
- if (adt == NULL) return 0;
-
- /* check action - only if assigned, and it has anim curves */
- if (adt->action && adt->action->curves.first)
- return 1;
-
- /* check NLA tracks + strips */
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- if (nlt->strips.first)
- return 1;
- }
-
- /* If we have drivers, more likely than not, on a frame change
- * they'll need updating because their owner changed
- *
- * This is kindof a hack to get around a whole host of problems
- * involving drivers using non-object datablock data (which the
- * depsgraph currently has no way of representing let alone correctly
- * dependency sort+tagging). By doing this, at least we ensure that
- * some commonly attempted drivers (such as scene -> current frame;
- * see "Driver updates fail" thread on Bf-committers dated July 2)
- * will work correctly, and that other non-object datablocks will have
- * their drivers update at least on frame change.
- *
- * -- Aligorith, July 4 2011
- */
- if (adt->drivers.first)
- return 1;
-
- return 0;
-}
-
-static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
-{
- if (ob->constraints.first) {
- bConstraint *con;
- for (con = ob->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti) {
- /* special case for camera tracking -- it doesn't use targets to define relations */
- if (ELEM(cti->type,
- CONSTRAINT_TYPE_FOLLOWTRACK,
- CONSTRAINT_TYPE_CAMERASOLVER,
- CONSTRAINT_TYPE_OBJECTSOLVER,
- CONSTRAINT_TYPE_TRANSFORM_CACHE))
- {
- ob->recalc |= OB_RECALC_OB;
- }
- else if (cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar) {
- ob->recalc |= OB_RECALC_OB;
- break;
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
-
- }
- }
- }
-
- if (ob->parent) {
- /* motion path or bone child */
- if (ob->parent->type == OB_CURVE || ob->parent->type == OB_ARMATURE) ob->recalc |= OB_RECALC_OB;
- }
-
-#if 0 // XXX old animation system
- if (ob->nlastrips.first) {
- if (ob->dup_group) {
- bActionStrip *strip;
- /* this case is for groups with nla, whilst nla target has no action or nla */
- for (strip = ob->nlastrips.first; strip; strip = strip->next) {
- if (strip->object)
- strip->object->recalc |= OB_RECALC_ALL;
- }
- }
- }
-#endif // XXX old animation system
-
- if (animdata_use_time(ob->adt)) {
- ob->recalc |= OB_RECALC_OB;
- ob->adt->recalc |= ADT_RECALC_ANIM;
- }
-
- if ((ob->adt) && (ob->type == OB_ARMATURE)) ob->recalc |= OB_RECALC_DATA;
-
- if (object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA;
- if ((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA;
-
- // XXX: scene here may not be the scene that contains the rigidbody world affecting this!
- if (ob->rigidbody_object && BKE_scene_check_rigidbody_active(scene))
- ob->recalc |= OB_RECALC_OB;
-
- {
- AnimData *adt = BKE_animdata_from_id((ID *)ob->data);
- Mesh *me;
- Curve *cu;
- Lattice *lt;
-
- switch (ob->type) {
- case OB_MESH:
- me = ob->data;
- if (me->key) {
- if (!(ob->shapeflag & OB_SHAPE_LOCK)) {
- ob->recalc |= OB_RECALC_DATA;
- }
- }
- if (ob->particlesystem.first)
- ob->recalc |= OB_RECALC_DATA;
- break;
- case OB_CURVE:
- case OB_SURF:
- cu = ob->data;
- if (cu->key) {
- if (!(ob->shapeflag & OB_SHAPE_LOCK)) {
- ob->recalc |= OB_RECALC_DATA;
- }
- }
- break;
- case OB_FONT:
- cu = ob->data;
- if (cu->str && cu->vfont) {
- /* Can be in the curve-cache or the curve. */
- if (ob->curve_cache && !BLI_listbase_is_empty(&ob->curve_cache->disp)) {
- /* pass */
- }
- else if (!BLI_listbase_is_empty(&cu->nurb)) {
- /* pass */
- }
- else {
- ob->recalc |= OB_RECALC_DATA;
- }
- }
- break;
- case OB_LATTICE:
- lt = ob->data;
- if (lt->key) {
- if (!(ob->shapeflag & OB_SHAPE_LOCK)) {
- ob->recalc |= OB_RECALC_DATA;
- }
- }
- break;
- case OB_MBALL:
- if (ob->transflag & OB_DUPLI) ob->recalc |= OB_RECALC_DATA;
- break;
- case OB_EMPTY:
- /* update animated images */
- if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data)
- if (BKE_image_is_animated(ob->data))
- ob->recalc |= OB_RECALC_DATA;
- break;
- }
-
- if (animdata_use_time(adt)) {
- ob->recalc |= OB_RECALC_DATA;
- adt->recalc |= ADT_RECALC_ANIM;
- }
-
- if (ob->particlesystem.first) {
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next) {
- if (psys_check_enabled(ob, psys, G.is_rendering)) {
- ob->recalc |= OB_RECALC_DATA;
- break;
- }
- }
- }
- }
-
- if (ob->recalc & OB_RECALC_OB)
- lib_id_recalc_tag(bmain, &ob->id);
- if (ob->recalc & OB_RECALC_DATA)
- lib_id_recalc_data_tag(bmain, &ob->id);
-
-}
-
-/* recursively update objects in groups, each group is done at most once */
-static void dag_group_update_flags(Main *bmain, Scene *scene, Group *group, const bool do_time)
-{
- GroupObject *go;
-
- if (group->id.tag & LIB_TAG_DOIT)
- return;
-
- group->id.tag |= LIB_TAG_DOIT;
-
- for (go = group->gobject.first; go; go = go->next) {
- if (do_time)
- dag_object_time_update_flags(bmain, scene, go->ob);
- if (go->ob->dup_group)
- dag_group_update_flags(bmain, scene, go->ob->dup_group, do_time);
- }
-}
-
-/* flag all objects that need recalc, for changes in time for example */
-/* do_time: make this optional because undo resets objects to their animated locations without this */
-void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const bool do_time, const bool do_invisible_flush)
-{
- Base *base;
- Object *ob;
- Group *group;
- GroupObject *go;
- Scene *sce_iter;
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* set ob flags where animated systems are */
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
-
- if (do_time) {
- /* now if DagNode were part of base, the node->lay could be checked... */
- /* we do all now, since the scene_flush checks layers and clears recalc flags even */
-
- /* NOTE: "sce_iter" not "scene" so that rigidbodies in background scenes work
- * (i.e. muting + rbw availability can be checked and tagged properly) [#33970]
- */
- dag_object_time_update_flags(bmain, sce_iter, ob);
- }
-
- /* recursively tag groups with LIB_TAG_DOIT, and update flags for objects */
- if (ob->dup_group)
- dag_group_update_flags(bmain, scene, ob->dup_group, do_time);
- }
-
- for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
- DAG_scene_flush_update(bmain, sce_iter, lay, 1);
-
- if (do_time) {
- /* test: set time flag, to disable baked systems to update */
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
- if (ob->recalc & OB_RECALC_ALL)
- ob->recalc |= OB_RECALC_TIME;
- }
-
- /* hrmf... an exception to look at once, for invisible camera object we do it over */
- if (scene->camera)
- dag_object_time_update_flags(bmain, scene, scene->camera);
- }
-
- /* and store the info in groupobject */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (group->id.tag & LIB_TAG_DOIT) {
- for (go = group->gobject.first; go; go = go->next) {
- go->recalc = go->ob->recalc;
- // printf("ob %s recalc %d\n", go->ob->id.name, go->recalc);
- }
- group->id.tag &= ~LIB_TAG_DOIT;
- }
- }
-
- if (do_invisible_flush) {
- dag_invisible_dependencies_check_flush(bmain, scene);
- }
-}
-
-/* struct returned by DagSceneLayer */
-typedef struct DagSceneLayer {
- struct DagSceneLayer *next, *prev;
- Scene *scene;
- unsigned int layer;
-} DagSceneLayer;
-
-/* returns visible scenes with valid DAG */
-static void dag_current_scene_layers(Main *bmain, ListBase *lb)
-{
- wmWindowManager *wm;
- wmWindow *win;
-
- BLI_listbase_clear(lb);
-
- /* if we have a windowmanager, look into windows */
- if ((wm = bmain->wm.first)) {
-
- BKE_main_id_flag_listbase(&bmain->scene, LIB_TAG_DOIT, 1);
-
- for (win = wm->windows.first; win; win = win->next) {
- if (win->screen && win->screen->scene->theDag) {
- Scene *scene = win->screen->scene;
- DagSceneLayer *dsl;
-
- if (scene->id.tag & LIB_TAG_DOIT) {
- dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer");
-
- BLI_addtail(lb, dsl);
-
- dsl->scene = scene;
- dsl->layer = BKE_screen_visible_layers(win->screen, scene);
-
- scene->id.tag &= ~LIB_TAG_DOIT;
- }
- else {
- /* It is possible that multiple windows shares the same scene
- * and have different layers visible.
- *
- * Here we deal with such cases by squashing layers bits from
- * multiple windoew to the DagSceneLayer.
- *
- * TODO(sergey): Such a lookup could be optimized perhaps,
- * however should be fine for now since we usually have only
- * few open windows.
- */
- for (dsl = lb->first; dsl; dsl = dsl->next) {
- if (dsl->scene == scene) {
- dsl->layer |= BKE_screen_visible_layers(win->screen, scene);
- break;
- }
- }
- }
- }
- }
- }
- else {
- /* if not, use the first sce */
- DagSceneLayer *dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer");
-
- BLI_addtail(lb, dsl);
-
- dsl->scene = bmain->scene.first;
- dsl->layer = dsl->scene->lay;
-
- /* XXX for background mode, we should get the scene
- * from somewhere, for the -S option, but it's in
- * the context, how to get it here? */
- }
-}
-
-static void dag_group_on_visible_update(Scene *scene, Group *group)
-{
- GroupObject *go;
-
- if (group->id.tag & LIB_TAG_DOIT)
- return;
-
- group->id.tag |= LIB_TAG_DOIT;
-
- for (go = group->gobject.first; go; go = go->next) {
- if (ELEM(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
- go->ob->recalc |= OB_RECALC_DATA;
- go->ob->id.tag |= LIB_TAG_DOIT;
- lib_id_recalc_tag(G.main, &go->ob->id);
- }
- if (go->ob->proxy_from) {
- go->ob->recalc |= OB_RECALC_OB;
- go->ob->id.tag |= LIB_TAG_DOIT;
- lib_id_recalc_tag(G.main, &go->ob->id);
- }
-
- if (go->ob->dup_group)
- dag_group_on_visible_update(scene, go->ob->dup_group);
- }
-}
-
-void DAG_on_visible_update(Main *bmain, const bool do_time)
-{
- ListBase listbase;
- DagSceneLayer *dsl;
-
- if (!DEG_depsgraph_use_legacy()) {
- /* Inform new dependnecy graphs about visibility changes. */
- DEG_on_visible_update(bmain, do_time);
- return;
- }
-
- /* get list of visible scenes and layers */
- dag_current_scene_layers(bmain, &listbase);
-
- for (dsl = listbase.first; dsl; dsl = dsl->next) {
- Scene *scene = dsl->scene;
- Scene *sce_iter;
- Base *base;
- Object *ob;
- DagNode *node;
- unsigned int lay = dsl->layer, oblay;
-
- /* derivedmeshes and displists are not saved to file so need to be
- * remade, tag them so they get remade in the scene update loop,
- * note armature poses or object matrices are preserved and do not
- * require updates, so we skip those */
- for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
- dag_scene_flush_layers(sce_iter, lay);
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
- node = (sce_iter->theDag) ? dag_get_node(sce_iter->theDag, ob) : NULL;
- oblay = (node) ? node->lay : ob->lay;
-
- if ((oblay & lay) & ~scene->lay_updated) {
- /* TODO(sergey): Why do we need armature here now but didn't need before? */
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE, OB_ARMATURE)) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_tag(bmain, &ob->id);
- }
- /* This should not be needed here, but in some cases, like after a redo, we can end up with
- * a wrong final matrix (see T42472).
- * Quoting Sergey, this comes from BKE_object_handle_update_ex, which is calling
- * BKE_object_where_is_calc_ex when it shouldn't, but that issue is not easily fixable.
- */
- else {
- ob->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &ob->id);
- }
- if (ob->proxy && (ob->proxy_group == NULL)) {
- ob->proxy->recalc |= OB_RECALC_DATA;
- lib_id_recalc_tag(bmain, &ob->id);
- }
- if (ob->dup_group)
- dag_group_on_visible_update(scene, ob->dup_group);
- }
- }
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* now tag update flags, to ensure deformers get calculated on redraw */
- DAG_scene_update_flags(bmain, scene, lay, do_time, true);
- scene->lay_updated |= lay;
- }
-
- BLI_freelistN(&listbase);
-
- /* hack to get objects updating on layer changes */
- DAG_id_type_tag(bmain, ID_OB);
-
- /* so masks update on load */
- if (bmain->mask.first) {
- Mask *mask;
-
- for (mask = bmain->mask.first; mask; mask = mask->id.next) {
- DAG_id_tag_update(&mask->id, 0);
- }
- }
-}
-
-static void dag_id_flush_update__isDependentTexture(
- void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cb_flag))
-{
- struct { ID *id; bool is_dependent; } *data = userData;
-
- if (*idpoin && GS((*idpoin)->name) == ID_TE) {
- if (data->id == (*idpoin))
- data->is_dependent = 1;
- }
-}
-
-static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
-{
- Object *obt, *ob = NULL;
- short idtype;
-
- /* here we flush a few things before actual scene wide flush, mostly
- * due to only objects and not other datablocks being in the depsgraph */
-
- /* set flags & pointcache for object */
- if (GS(id->name) == ID_OB) {
- ob = (Object *)id;
- BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH);
-
- /* So if someone tagged object recalc directly,
- * id_tag_update bit-field stays relevant
- */
- if (ob->recalc & OB_RECALC_ALL) {
- DAG_id_type_tag(bmain, GS(id->name));
- }
-
- if (ob->recalc & OB_RECALC_DATA) {
- /* all users of this ob->data should be checked */
- id = ob->data;
-
- /* no point in trying in this cases */
- if (id && id->us <= 1) {
- dag_editors_id_update(bmain, id);
- id = NULL;
- }
- }
- }
-
- /* set flags & pointcache for object data */
- if (id) {
- idtype = GS(id->name);
-
-
- if (OB_DATA_SUPPORT_ID(idtype)) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- if (!(ob && obt == ob) && obt->data == id) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- }
- else if (idtype == ID_VF) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- if (obt->type == OB_FONT) {
- Curve *cu = obt->data;
- if (ELEM((struct VFont *)id, CURVE_VFONT_ANY(cu))) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
- }
- }
- }
- }
-
- /* set flags based on textures - can influence depgraph via modifiers */
- if (idtype == ID_TE) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- struct { ID *id; bool is_dependent; } data;
- data.id = id;
- data.is_dependent = 0;
-
- modifiers_foreachIDLink(obt, dag_id_flush_update__isDependentTexture, &data);
- if (data.is_dependent) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
- }
-
- /* particle settings can use the texture as well */
- if (obt->particlesystem.first) {
- ParticleSystem *psys = obt->particlesystem.first;
- MTex **mtexp, *mtex;
- int a;
- for (; psys; psys = psys->next) {
- mtexp = psys->part->mtex;
- for (a = 0; a < MAX_MTEX; a++, mtexp++) {
- mtex = *mtexp;
- if (mtex && mtex->tex == (Tex *)id) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
-
- if (mtex->mapto & PAMAP_INIT)
- psys->recalc |= PSYS_RECALC_RESET;
- if (mtex->mapto & PAMAP_CHILD)
- psys->recalc |= PSYS_RECALC_CHILD;
-
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- }
- }
- }
- }
-
- /* set flags based on ShapeKey */
- if (idtype == ID_KE) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- Key *key = BKE_key_from_object(obt);
- if (!(ob && obt == ob) && ((ID *)key == id)) {
- obt->flag |= (OB_RECALC_OB | OB_RECALC_DATA);
- lib_id_recalc_tag(bmain, &obt->id);
- lib_id_recalc_data_tag(bmain, &obt->id);
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- }
-
- /* set flags based on particle settings */
- if (idtype == ID_PA) {
- ParticleSystem *psys;
- for (obt = bmain->object.first; obt; obt = obt->id.next)
- for (psys = obt->particlesystem.first; psys; psys = psys->next)
- if (&psys->part->id == id)
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
-
- if (ELEM(idtype, ID_MA, ID_TE)) {
- obt = sce->basact ? sce->basact->object : NULL;
- if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) {
- BKE_texpaint_slots_refresh_object(sce, obt);
- BKE_paint_proj_mesh_data_check(sce, obt, NULL, NULL, NULL, NULL);
- GPU_drawobject_free(obt->derivedFinal);
- }
- }
-
- if (idtype == ID_MC) {
- MovieClip *clip = (MovieClip *) id;
-
- BKE_tracking_dopesheet_tag_update(&clip->tracking);
-
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- bConstraint *con;
- for (con = obt->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
- CONSTRAINT_TYPE_OBJECTSOLVER))
- {
- obt->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &obt->id);
- break;
- }
- }
- }
-
- if (sce->nodetree) {
- bNode *node;
-
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- nodeUpdate(sce->nodetree, node);
- }
- }
- }
- }
-
- /* Not pretty to iterate all the nodes here, but it's as good as it
- * could be with the current depsgraph design/
- */
- if (idtype == ID_IM) {
- FOREACH_NODETREE(bmain, ntree, parent_id) {
- if (ntree->type == NTREE_SHADER) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- lib_id_recalc_tag(bmain, &ntree->id);
- break;
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- if (idtype == ID_MSK) {
- if (sce->nodetree) {
- bNode *node;
-
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- nodeUpdate(sce->nodetree, node);
- }
- }
- }
- }
-
- /* camera's matrix is used to orient reconstructed stuff,
- * so it should happen tracking-related constraints recalculation
- * when camera is changing (sergey) */
- if (sce->camera && &sce->camera->id == id) {
- MovieClip *clip = BKE_object_movieclip_get(sce, sce->camera, true);
-
- if (clip)
- dag_id_flush_update(bmain, sce, &clip->id);
- }
-
- /* update editors */
- dag_editors_id_update(bmain, id);
- }
-}
-
-void DAG_ids_flush_tagged(Main *bmain)
-{
- ListBase listbase;
- DagSceneLayer *dsl;
- ListBase *lbarray[MAX_LIBARRAY];
- int a;
- bool do_flush = false;
-
- if (!DEG_depsgraph_use_legacy()) {
- DEG_ids_flush_tagged(bmain);
- return;
- }
-
- /* get list of visible scenes and layers */
- dag_current_scene_layers(bmain, &listbase);
-
- if (BLI_listbase_is_empty(&listbase))
- return;
-
- /* loop over all ID types */
- a = set_listbasepointers(bmain, lbarray);
-
- while (a--) {
- ListBase *lb = lbarray[a];
- ID *id = lb->first;
-
- if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) {
- for (; id; id = id->next) {
- if (id->tag & (LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA)) {
-
- for (dsl = listbase.first; dsl; dsl = dsl->next)
- dag_id_flush_update(bmain, dsl->scene, id);
-
- do_flush = true;
- }
- }
- }
- }
-
- /* flush changes to other objects */
- if (do_flush) {
- for (dsl = listbase.first; dsl; dsl = dsl->next)
- DAG_scene_flush_update(bmain, dsl->scene, dsl->layer, 0);
- }
-
- BLI_freelistN(&listbase);
-}
-
-void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
-{
- ListBase *lbarray[MAX_LIBARRAY];
- int a;
- bool updated = false;
-
- if (!DEG_depsgraph_use_legacy()) {
- DEG_ids_check_recalc(bmain, scene, time);
- return;
- }
-
- /* loop over all ID types */
- a = set_listbasepointers(bmain, lbarray);
-
- while (a--) {
- ListBase *lb = lbarray[a];
- ID *id = lb->first;
-
- if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) {
- updated = true;
- break;
- }
- }
-
- dag_editors_scene_update(bmain, scene, (updated || time));
-}
-
-/* It is possible that scene_update_post and frame_update_post handlers
- * will modify objects. The issue is that DAG_ids_clear_recalc is called
- * just after callbacks, which leaves objects with recalc flags but no
- * corresponding bit in ID recalc bitfield. This leads to some kind of
- * regression when using ID type tag fields to check whether there objects
- * to be updated internally comparing threaded DAG with legacy one.
- *
- * For now let's have a workaround which will preserve tag for ID_OB
- * if there're objects with OB_RECALC_ALL bits. This keeps behavior
- * unchanged comparing with 2.69 release.
- *
- * TODO(sergey): Need to get rid of such a workaround.
- *
- * - sergey -
- */
-
-#define POST_UPDATE_HANDLER_WORKAROUND
-
-void DAG_ids_clear_recalc(Main *bmain)
-{
- ListBase *lbarray[MAX_LIBARRAY];
- bNodeTree *ntree;
- int a;
-
-#ifdef POST_UPDATE_HANDLER_WORKAROUND
- bool have_updated_objects = false;
-
- if (DAG_id_type_tagged(bmain, ID_OB)) {
- ListBase listbase;
- DagSceneLayer *dsl;
-
- /* We need to check all visible scenes, otherwise resetting
- * OB_ID changed flag will only work fine for first scene of
- * multiple visible and all the rest will skip update.
- *
- * This could also lead to wrong behavior scene update handlers
- * because of missing ID datablock changed flags.
- *
- * This is a bit of a bummer to allocate list here, but likely
- * it wouldn't become too much bad because it only happens when
- * objects were actually changed.
- */
- dag_current_scene_layers(bmain, &listbase);
-
- for (dsl = listbase.first; dsl; dsl = dsl->next) {
- Scene *scene = dsl->scene;
- DagNode *node;
- for (node = scene->theDag->DagNode.first;
- node != NULL && have_updated_objects == false;
- node = node->next)
- {
- if (node->type == ID_OB) {
- Object *object = (Object *) node->ob;
- if (object->recalc & OB_RECALC_ALL) {
- have_updated_objects = true;
- break;
- }
- }
- }
- }
-
- BLI_freelistN(&listbase);
- }
-#endif
-
- /* loop over all ID types */
- a = set_listbasepointers(bmain, lbarray);
-
- while (a--) {
- ListBase *lb = lbarray[a];
- ID *id = lb->first;
-
- if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) {
- for (; id; id = id->next) {
- if (id->tag & (LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA))
- id->tag &= ~(LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA);
-
- /* some ID's contain semi-datablock nodetree */
- ntree = ntreeFromID(id);
- if (ntree && (ntree->id.tag & (LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA)))
- ntree->id.tag &= ~(LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA);
- }
- }
- }
-
- memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update));
-
-#ifdef POST_UPDATE_HANDLER_WORKAROUND
- if (have_updated_objects) {
- DAG_id_type_tag(bmain, ID_OB);
- }
-#endif
-}
-
-void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
-{
- if (!DEG_depsgraph_use_legacy()) {
- DEG_id_tag_update_ex(bmain, id, flag);
- return;
- }
-
- if (id == NULL) return;
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s: id=%s flag=%d\n", __func__, id->name, flag);
- }
-
- /* tag ID for update */
- if (flag) {
- if (flag & OB_RECALC_OB)
- lib_id_recalc_tag(bmain, id);
- if (flag & (OB_RECALC_DATA | PSYS_RECALC))
- lib_id_recalc_data_tag(bmain, id);
- }
- else
- lib_id_recalc_tag(bmain, id);
-
- /* flag is for objects and particle systems */
- if (flag) {
- Object *ob;
- short idtype = GS(id->name);
-
- if (idtype == ID_OB) {
- /* only quick tag */
- ob = (Object *)id;
- ob->recalc |= (flag & OB_RECALC_ALL);
- }
- else if (idtype == ID_PA) {
- ParticleSystem *psys;
- /* this is weak still, should be done delayed as well */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (&psys->part->id == id) {
- ob->recalc |= (flag & OB_RECALC_ALL);
- psys->recalc |= (flag & PSYS_RECALC);
- lib_id_recalc_tag(bmain, &ob->id);
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
- }
- }
- }
- else {
- /* disable because this is called on various ID types automatically.
- * where printing warning is not useful. for now just ignore */
- /* BLI_assert(!"invalid flag for this 'idtype'"); */
- }
- }
- else if (GS(id->name) == ID_CF) {
- for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
- ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
-
- if (md) {
- MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md;
-
- if (mcmd->cache_file && (&mcmd->cache_file->id == id)) {
- ob->recalc |= OB_RECALC_ALL;
- continue;
- }
- }
-
- for (bConstraint *con = ob->constraints.first; con; con = con->next) {
- if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) {
- continue;
- }
-
- bTransformCacheConstraint *data = con->data;
-
- if (data->cache_file && (&data->cache_file->id == id)) {
- ob->recalc |= OB_RECALC_ALL;
- break;
- }
- }
- }
- }
-}
-
-void DAG_id_tag_update(ID *id, short flag)
-{
- DAG_id_tag_update_ex(G.main, id, flag);
-}
-
-void DAG_id_type_tag(Main *bmain, short idtype)
-{
- if (idtype == ID_NT) {
- /* stupid workaround so parent datablocks of nested nodetree get looped
- * over when we loop over tagged datablock types */
- DAG_id_type_tag(bmain, ID_MA);
- DAG_id_type_tag(bmain, ID_TE);
- DAG_id_type_tag(bmain, ID_LA);
- DAG_id_type_tag(bmain, ID_WO);
- DAG_id_type_tag(bmain, ID_SCE);
- }
-
- atomic_fetch_and_or_uint8((uint8_t *)&bmain->id_tag_update[BKE_idcode_to_index(idtype)], 1);
-}
-
-int DAG_id_type_tagged(Main *bmain, short idtype)
-{
- return bmain->id_tag_update[BKE_idcode_to_index(idtype)];
-}
-
-#if 0 // UNUSED
-/* recursively descends tree, each node only checked once */
-/* node is checked to be of type object */
-static int parent_check_node(DagNode *node, int curtime)
-{
- DagAdjList *itA;
-
- node->lasttime = curtime;
-
- if (node->color == DAG_GRAY)
- return DAG_GRAY;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
-
- if (itA->node->color == DAG_GRAY)
- return DAG_GRAY;
-
- /* descend if not done */
- if (itA->node->lasttime != curtime) {
- itA->node->color = parent_check_node(itA->node, curtime);
-
- if (itA->node->color == DAG_GRAY)
- return DAG_GRAY;
- }
- }
- }
-
- return DAG_WHITE;
-}
-#endif
-
-/* ******************* DAG FOR ARMATURE POSE ***************** */
-
-/* we assume its an armature with pose */
-void DAG_pose_sort(Object *ob)
-{
- bPose *pose = ob->pose;
- bPoseChannel *pchan;
- bConstraint *con;
- DagNode *node;
- DagNode *node2, *node3;
- DagNode *rootnode;
- DagForest *dag;
- DagNodeQueue *nqueue;
- DagAdjList *itA;
- ListBase tempbase;
- int skip = 0;
-
- dag = dag_init();
- dag->ugly_hack_sorry = false; /* no ID structs */
-
- rootnode = dag_add_node(dag, NULL); /* node->ob becomes NULL */
-
- /* we add the hierarchy and the constraints */
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- int addtoroot = 1;
-
- node = dag_get_node(dag, pchan);
-
- if (pchan->parent) {
- node2 = dag_get_node(dag, pchan->parent);
- dag_add_relation(dag, node2, node, 0, "Parent Relation");
- addtoroot = 0;
- }
- for (con = pchan->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == ob && ct->subtarget[0]) {
- bPoseChannel *target = BKE_pose_channel_find_name(ob->pose, ct->subtarget);
- if (target) {
- node2 = dag_get_node(dag, target);
- dag_add_relation(dag, node2, node, 0, "Pose Constraint");
-
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- bKinematicConstraint *data = (bKinematicConstraint *)con->data;
- bPoseChannel *parchan;
- int segcount = 0;
-
- /* exclude tip from chain? */
- if (!(data->flag & CONSTRAINT_IK_TIP))
- parchan = pchan->parent;
- else
- parchan = pchan;
-
- /* Walk to the chain's root */
- while (parchan) {
- node3 = dag_get_node(dag, parchan);
- dag_add_relation(dag, node2, node3, 0, "IK Constraint");
-
- segcount++;
- if (segcount == data->rootbone || segcount > 255) break; /* 255 is weak */
- parchan = parchan->parent;
- }
- }
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
- if (addtoroot == 1) {
- dag_add_relation(dag, rootnode, node, 0, "Root Bone Relation");
- }
- }
-
- dag_check_cycle(dag);
-
- /* now we try to sort... */
- BLI_listbase_clear(&tempbase);
-
- nqueue = queue_create(DAGQUEUEALLOC);
-
- /* tag nodes unchecked */
- for (node = dag->DagNode.first; node; node = node->next)
- node->color = DAG_WHITE;
-
- rootnode->color = DAG_GRAY;
- push_stack(nqueue, rootnode);
-
- while (nqueue->count) {
-
- skip = 0;
- node = get_top_node_queue(nqueue);
-
- itA = node->child;
- while (itA != NULL) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->color = DAG_GRAY;
- push_stack(nqueue, itA->node);
- skip = 1;
- break;
- }
- itA = itA->next;
- }
-
- if (!skip) {
- if (node) {
- node = pop_queue(nqueue);
- if (node->ob == NULL) /* we are done */
- break;
- node->color = DAG_BLACK;
-
- /* put node in new list */
- BLI_remlink(&pose->chanbase, node->ob);
- BLI_addhead(&tempbase, node->ob);
- }
- }
- }
-
- /* temporal correction for circular dependencies */
- while (pose->chanbase.first) {
- pchan = pose->chanbase.first;
- BLI_remlink(&pose->chanbase, pchan);
- BLI_addhead(&tempbase, pchan);
-
- printf("cyclic %s\n", pchan->name);
- }
-
- pose->chanbase = tempbase;
- queue_delete(nqueue);
-
-// printf("\nordered\n");
-// for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
-// printf(" %s\n", pchan->name);
-// }
-
- free_forest(dag);
- MEM_freeN(dag);
-}
-
-/* ************************ DAG FOR THREADED UPDATE ********************* */
-
-/* Initialize run-time data in the graph needed for traversing it
- * from multiple threads and start threaded tree traversal by adding
- * the root node to the queue.
- *
- * This will mark DAG nodes as object/non-object and will calculate
- * num_pending_parents of nodes (which is how many non-updated parents node
- * have, which helps a lot checking whether node could be scheduled
- * already or not).
- */
-void DAG_threaded_update_begin(Scene *scene,
- void (*func)(void *node, void *user_data),
- void *user_data)
-{
- DagNode *node;
-
- /* We reset num_pending_parents to zero first and tag node as not scheduled yet... */
- for (node = scene->theDag->DagNode.first; node; node = node->next) {
- node->num_pending_parents = 0;
- node->scheduled = false;
- }
-
- /* ... and then iterate over all the nodes and
- * increase num_pending_parents for node childs.
- */
- for (node = scene->theDag->DagNode.first; node; node = node->next) {
- DagAdjList *itA;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node != node) {
- itA->node->num_pending_parents++;
- }
- }
- }
-
- /* Add root nodes to the queue. */
- BLI_spin_lock(&threaded_update_lock);
- for (node = scene->theDag->DagNode.first; node; node = node->next) {
- if (node->num_pending_parents == 0) {
- node->scheduled = true;
- func(node, user_data);
- }
- }
- BLI_spin_unlock(&threaded_update_lock);
-}
-
-/* This function is called when handling node is done.
- *
- * This function updates num_pending_parents for all childs and
- * schedules them if they're ready.
- */
-void DAG_threaded_update_handle_node_updated(void *node_v,
- void (*func)(void *node, void *user_data),
- void *user_data)
-{
- DagNode *node = node_v;
- DagAdjList *itA;
-
- for (itA = node->child; itA; itA = itA->next) {
- DagNode *child_node = itA->node;
- if (child_node != node) {
- atomic_sub_and_fetch_uint32(&child_node->num_pending_parents, 1);
-
- if (child_node->num_pending_parents == 0) {
- bool need_schedule;
-
- BLI_spin_lock(&threaded_update_lock);
- need_schedule = child_node->scheduled == false;
- child_node->scheduled = true;
- BLI_spin_unlock(&threaded_update_lock);
-
- if (need_schedule) {
- func(child_node, user_data);
- }
- }
- }
- }
-}
-
-/* ************************ DAG DEBUGGING ********************* */
-
-void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob)
-{
- /* utility for debugging dependencies */
- dag_print_dependencies = 1;
-
- if (ob && (ob->mode & OB_MODE_POSE)) {
- printf("\nDEPENDENCY RELATIONS for %s\n\n", ob->id.name + 2);
- DAG_pose_sort(ob);
- }
- else {
- printf("\nDEPENDENCY RELATIONS for %s\n\n", scene->id.name + 2);
- DAG_scene_relations_rebuild(bmain, scene);
- }
-
- dag_print_dependencies = 0;
-}
-
-/* ************************ DAG querying ********************* */
-
-/* Will return Object ID if node represents Object,
- * and will return NULL otherwise.
- */
-Object *DAG_get_node_object(void *node_v)
-{
- DagNode *node = node_v;
-
- if (node->type == ID_OB) {
- return node->ob;
- }
-
- return NULL;
-}
-
-/* Returns node name, used for debug output only, atm. */
-const char *DAG_get_node_name(Scene *scene, void *node_v)
-{
- DagNode *node = node_v;
-
- return dag_node_name(scene->theDag, node);
-}
-
-short DAG_get_eval_flags_for_object(Scene *scene, void *object)
-{
- DagNode *node;
-
- if (!DEG_depsgraph_use_legacy()) {
- return DEG_get_eval_flags_for_id(scene->depsgraph, (ID *)object);
- }
-
- if (scene->theDag == NULL) {
- /* Happens when converting objects to mesh from a python script
- * after modifying scene graph.
- *
- * Currently harmless because it's only called for temporary
- * objects which are out of the DAG anyway.
- */
- return 0;
- }
-
- node = dag_find_node(scene->theDag, object);
-
- if (node) {
- return node->eval_flags;
- }
- else {
- /* Happens when external render engine exports temporary objects
- * which are not in the DAG.
- */
-
- /* TODO(sergey): Doublecheck objects with Curve Deform exports all fine. */
-
- /* TODO(sergey): Weak but currently we can't really access proper DAG from
- * the modifiers stack. This is because in most cases modifier is to use
- * the foreground scene, but to access evaluation flags we need to know
- * active background scene, which we don't know.
- */
- if (scene->set) {
- return DAG_get_eval_flags_for_object(scene->set, object);
- }
- return 0;
- }
-}
-
-bool DAG_is_acyclic(Scene *scene)
-{
- return scene->theDag->is_acyclic;
-}
-
-#else
-
-/* *********************************************************************
- * Stubs to avoid linking issues and make sure legacy crap is not used *
- * *********************************************************************
- */
-
-DagNodeQueue *queue_create(int UNUSED(slots))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-void queue_raz(DagNodeQueue *UNUSED(queue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void queue_delete(DagNodeQueue *UNUSED(queue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void push_queue(DagNodeQueue *UNUSED(queue), DagNode *UNUSED(node))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void push_stack(DagNodeQueue *UNUSED(queue), DagNode *UNUSED(node))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-DagNode *pop_queue(DagNodeQueue *UNUSED(queue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagNode *get_top_node_queue(DagNodeQueue *UNUSED(queue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagForest *dag_init(void)
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagForest *build_dag(Main *UNUSED(bmain),
- Scene *UNUSED(sce),
- short UNUSED(mask))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-void free_forest(DagForest *UNUSED(Dag))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-DagNode *dag_find_node(DagForest *UNUSED(forest), void *UNUSED(fob))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagNode *dag_add_node(DagForest *UNUSED(forest), void *UNUSED(fob))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagNode *dag_get_node(DagForest *UNUSED(forest), void *UNUSED(fob))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagNode *dag_get_sub_node(DagForest *UNUSED(forest), void *UNUSED(fob))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-void dag_add_relation(DagForest *UNUSED(forest),
- DagNode *UNUSED(fob1),
- DagNode *UNUSED(fob2),
- short UNUSED(rel),
- const char *UNUSED(name))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-/* debug test functions */
-
-void graph_print_queue(DagNodeQueue *UNUSED(nqueue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void graph_print_queue_dist(DagNodeQueue *UNUSED(nqueue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void graph_print_adj_list(DagForest *UNUSED(dag))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void DAG_scene_flush_update(Main *UNUSED(bmain),
- Scene *UNUSED(sce),
- unsigned int UNUSED(lay),
- const short UNUSED(time))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void DAG_scene_update_flags(Main *UNUSED(bmain),
- Scene *UNUSED(scene),
- unsigned int UNUSED(lay),
- const bool UNUSED(do_time),
- const bool UNUSED(do_invisible_flush))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-/* ******************* DAG FOR ARMATURE POSE ***************** */
-
-void DAG_pose_sort(Object *UNUSED(ob))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-/* ************************ DAG FOR THREADED UPDATE ********************* */
-
-void DAG_threaded_update_begin(Scene *UNUSED(scene),
- void (*func)(void *node, void *user_data),
- void *UNUSED(user_data))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- (void)func;
-}
-
-void DAG_threaded_update_handle_node_updated(void *UNUSED(node_v),
- void (*func)(void *node, void *user_data),
- void *UNUSED(user_data))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- (void)func;
-}
-
-/* ************************ DAG querying ********************* */
-
-Object *DAG_get_node_object(void *UNUSED(node_v))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-const char *DAG_get_node_name(Scene *UNUSED(scene), void *UNUSED(node_v))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return "INVALID";
-}
-
-bool DAG_is_acyclic(Scene *UNUSED(scene))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return false;
-}
-
-/* ************************************
- * This functions are to be supported *
- * ************************************
- */
-
-void DAG_init(void)
-{
- DEG_register_node_types();
-}
-
-void DAG_exit(void)
-{
- DEG_free_node_types();
-}
-
-/* ************************ API *********************** */
-
-void DAG_editors_update_cb(DEG_EditorUpdateIDCb id_func,
- DEG_EditorUpdateSceneCb scene_func,
- DEG_EditorUpdateScenePreCb scene_func_pre)
-{
- DEG_editors_set_update_cb(id_func, scene_func, scene_func_pre);
-}
-
-void DAG_editors_update_pre(Main *bmain, Scene *scene, bool time)
-{
- DEG_editors_update_pre(bmain, scene, time);
-}
-
-/* Tag all relations for update. */
-void DAG_relations_tag_update(Main *bmain)
-{
- DEG_relations_tag_update(bmain);
-}
-
-/* Rebuild dependency graph only for a given scene. */
-void DAG_scene_relations_rebuild(Main *bmain, Scene *scene)
-{
- DEG_scene_relations_rebuild(bmain, scene);
-}
-
-/* Create dependency graph if it was cleared or didn't exist yet. */
-void DAG_scene_relations_update(Main *bmain, Scene *scene)
-{
- DEG_scene_relations_update(bmain, scene);
-}
-
-void DAG_scene_relations_validate(Main *bmain, Scene *scene)
-{
- DEG_debug_scene_relations_validate(bmain, scene);
-}
-
-void DAG_scene_free(Scene *scene)
-{
- DEG_scene_graph_free(scene);
-}
-
-void DAG_on_visible_update(Main *bmain, const bool do_time)
-{
- DEG_on_visible_update(bmain, do_time);
-}
-
-void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
-{
- DEG_ids_check_recalc(bmain, scene, time);
-}
-
-void DAG_id_tag_update(ID *id, short flag)
-{
- DEG_id_tag_update_ex(G.main, id, flag);
-}
-
-void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
-{
- DEG_id_tag_update_ex(bmain, id, flag);
-}
-
-void DAG_id_type_tag(Main *bmain, short idtype)
-{
- DEG_id_type_tag(bmain, idtype);
-}
-
-int DAG_id_type_tagged(Main *bmain, short idtype)
-{
- return DEG_id_type_tagged(bmain, idtype);
-}
-
-void DAG_ids_clear_recalc(Main *bmain)
-{
- DEG_ids_clear_recalc(bmain);
-}
-
-short DAG_get_eval_flags_for_object(Scene *scene, void *object)
-{
- return DEG_get_eval_flags_for_id(scene->depsgraph, (ID *)object);
-}
-
-void DAG_ids_flush_tagged(Main *bmain)
-{
- DEG_ids_flush_tagged(bmain);
-}
-
-/* ************************ DAG DEBUGGING ********************* */
-
-void DAG_print_dependencies(Main *UNUSED(bmain),
- Scene *scene,
- Object *UNUSED(ob))
-{
- DEG_debug_graphviz(scene->depsgraph, stdout, "Depsgraph", false);
-}
-
-#endif
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 2a300cbe47b..15a520fe8ce 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -48,7 +48,6 @@
#include "BLI_utildefines.h"
#include "BKE_global.h"
-#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_object.h"
@@ -63,6 +62,9 @@
#include "BLI_sys_types.h" // for intptr_t support
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
static void boundbox_displist_object(Object *ob);
void BKE_displist_elem_free(DispList *dl)
@@ -676,7 +678,7 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis
* - first point left, last point right
* - based on subdivided points in original curve, not on points in taper curve (still)
*/
-static float displist_calc_taper(Scene *scene, Object *taperobj, float fac)
+static float displist_calc_taper(const EvaluationContext *eval_ctx, Scene *scene, Object *taperobj, float fac)
{
DispList *dl;
@@ -685,7 +687,7 @@ static float displist_calc_taper(Scene *scene, Object *taperobj, float fac)
dl = taperobj->curve_cache ? taperobj->curve_cache->disp.first : NULL;
if (dl == NULL) {
- BKE_displist_make_curveTypes(scene, taperobj, 0);
+ BKE_displist_make_curveTypes(eval_ctx, scene, taperobj, 0);
dl = taperobj->curve_cache->disp.first;
}
if (dl) {
@@ -716,14 +718,14 @@ static float displist_calc_taper(Scene *scene, Object *taperobj, float fac)
return 1.0;
}
-float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
+float BKE_displist_calc_taper(const EvaluationContext *eval_ctx, Scene *scene, Object *taperobj, int cur, int tot)
{
float fac = ((float)cur) / (float)(tot - 1);
- return displist_calc_taper(scene, taperobj, fac);
+ return displist_calc_taper(eval_ctx, scene, taperobj, fac);
}
-void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object *ob)
+void BKE_displist_make_mball(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
if (!ob || ob->type != OB_MBALL)
return;
@@ -746,7 +748,7 @@ void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object *
}
}
-void BKE_displist_make_mball_forRender(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
+void BKE_displist_make_mball_forRender(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
{
BKE_mball_polygonize(eval_ctx, scene, ob, dispbase);
BKE_mball_texspace_calc(ob);
@@ -796,8 +798,9 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob,
return pretessellatePoint;
}
-static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
- const bool for_render, const bool use_render_resolution)
+static void curve_calc_modifiers_pre(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *nurb,
+ const bool for_render, const bool use_render_resolution)
{
VirtualModifierData virtualModifierData;
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
@@ -854,7 +857,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
deformedVerts = BKE_curve_nurbs_vertexCos_get(nurb, &numVerts);
}
- mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, app_flag);
+ mti->deformVerts(md, eval_ctx, ob, NULL, deformedVerts, numVerts, app_flag);
if (md == pretessellatePoint)
break;
@@ -906,9 +909,10 @@ static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3])
}
}
-static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb,
- ListBase *dispbase, DerivedMesh **r_dm_final,
- const bool for_render, const bool use_render_resolution)
+static void curve_calc_modifiers_post(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *nurb,
+ ListBase *dispbase, DerivedMesh **r_dm_final,
+ const bool for_render, const bool use_render_resolution)
{
VirtualModifierData virtualModifierData;
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
@@ -962,14 +966,14 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb,
dm->getVertCos(dm, vertCos);
}
- mti->deformVerts(md, ob, dm, vertCos, totvert, appf);
+ mti->deformVerts(md, eval_ctx, ob, dm, vertCos, totvert, appf);
}
else {
if (!vertCos) {
vertCos = displist_get_allverts(dispbase, &totvert);
}
- mti->deformVerts(md, ob, NULL, vertCos, totvert, appf);
+ mti->deformVerts(md, eval_ctx, ob, NULL, vertCos, totvert, appf);
}
}
else {
@@ -1011,7 +1015,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb,
if (useCache)
appf |= MOD_APPLY_USECACHE;
- ndm = modwrap_applyModifier(md, ob, dm, appf);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, dm, appf);
if (ndm) {
/* Modifier returned a new derived mesh */
@@ -1088,13 +1092,13 @@ static void displist_surf_indices(DispList *dl)
}
}
-static DerivedMesh *create_orco_dm(Scene *scene, Object *ob)
+static DerivedMesh *create_orco_dm(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
DerivedMesh *dm;
ListBase disp = {NULL, NULL};
/* OrcoDM should be created from underformed disp lists */
- BKE_displist_make_curveTypes_forOrco(scene, ob, &disp);
+ BKE_displist_make_curveTypes_forOrco(eval_ctx, scene, ob, &disp);
dm = CDDM_from_curve_displist(ob, &disp);
BKE_displist_free(&disp);
@@ -1132,8 +1136,9 @@ static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
}
-static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final,
- const bool for_render, const bool use_render_resolution)
+static void curve_calc_orcodm(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm_final,
+ const bool for_render, const bool use_render_resolution)
{
/* this function represents logic of mesh's orcodm calculation
* for displist-based objects
@@ -1170,7 +1175,7 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final,
* This means we can create ORCO DM in advance and assume it's
* never NULL.
*/
- orcodm = create_orco_dm(scene, ob);
+ orcodm = create_orco_dm(eval_ctx, scene, ob);
for (; md; md = md->next) {
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -1182,7 +1187,7 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final,
if (mti->type != eModifierTypeType_Constructive)
continue;
- ndm = modwrap_applyModifier(md, ob, orcodm, app_flag);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, orcodm, app_flag);
if (ndm) {
/* if the modifier returned a new dm, release the old one */
@@ -1199,9 +1204,10 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final,
orcodm->release(orcodm);
}
-void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
- DerivedMesh **r_dm_final,
- const bool for_render, const bool for_orco, const bool use_render_resolution)
+void BKE_displist_make_surf(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase,
+ DerivedMesh **r_dm_final,
+ const bool for_render, const bool for_orco, const bool use_render_resolution)
{
ListBase nubase = {NULL, NULL};
Nurb *nu;
@@ -1218,7 +1224,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
}
if (!for_orco)
- curve_calc_modifiers_pre(scene, ob, &nubase, for_render, use_render_resolution);
+ curve_calc_modifiers_pre(eval_ctx, scene, ob, &nubase, for_render, use_render_resolution);
for (nu = nubase.first; nu; nu = nu->next) {
if ((for_render || nu->hide == 0) && BKE_nurb_check_valid_uv(nu)) {
@@ -1285,7 +1291,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
if (!for_orco) {
BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase);
- curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final,
+ curve_calc_modifiers_post(eval_ctx, scene, ob, &nubase, dispbase, r_dm_final,
for_render, use_render_resolution);
}
@@ -1511,9 +1517,10 @@ static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu,
}
}
-static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase,
- DerivedMesh **r_dm_final,
- const bool for_render, const bool for_orco, const bool use_render_resolution)
+static void do_makeDispListCurveTypes(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase,
+ DerivedMesh **r_dm_final,
+ const bool for_render, const bool for_orco, const bool use_render_resolution)
{
Curve *cu = ob->data;
@@ -1521,7 +1528,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
if (ob->type == OB_SURF) {
- BKE_displist_make_surf(scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution);
+ BKE_displist_make_surf(eval_ctx, scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution);
}
else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
ListBase dlbev;
@@ -1546,12 +1553,12 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
}
if (!for_orco)
- curve_calc_modifiers_pre(scene, ob, &nubase, for_render, use_render_resolution);
+ curve_calc_modifiers_pre(eval_ctx, scene, ob, &nubase, for_render, use_render_resolution);
BKE_curve_bevelList_make(ob, &nubase, for_render != false);
/* If curve has no bevel will return nothing */
- BKE_curve_bevel_make(scene, ob, &dlbev, for_render, use_render_resolution);
+ BKE_curve_bevel_make(eval_ctx, scene, ob, &dlbev, for_render, use_render_resolution);
/* no bevel or extrude, and no width correction? */
if (!dlbev.first && cu->width == 1.0f) {
@@ -1686,7 +1693,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
taper_fac -= (1.0f - lastblend) / len;
}
- fac = displist_calc_taper(scene, cu->taperobj, taper_fac);
+ fac = displist_calc_taper(eval_ctx, scene, cu->taperobj, taper_fac);
}
if (bevp->split_tag) {
@@ -1739,7 +1746,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
if (!for_orco) {
if ((cu->flag & CU_PATH) ||
- DAG_get_eval_flags_for_object(scene, ob) & DAG_EVAL_NEED_CURVE_PATH)
+ DEG_get_eval_flags_for_id(eval_ctx->depsgraph, &ob->id) & DAG_EVAL_NEED_CURVE_PATH)
{
calc_curvepath(ob, &nubase);
}
@@ -1747,7 +1754,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
if (!for_orco) {
BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase);
- curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution);
+ curve_calc_modifiers_post(eval_ctx, scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution);
}
if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) {
@@ -1758,7 +1765,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
}
}
-void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco)
+void BKE_displist_make_curveTypes(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, const bool for_orco)
{
ListBase *dispbase;
@@ -1776,35 +1783,38 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco)
dispbase = &(ob->curve_cache->disp);
- do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, for_orco, 0);
+ do_makeDispListCurveTypes(eval_ctx, scene, ob, dispbase, &ob->derivedFinal, 0, for_orco, 0);
boundbox_displist_object(ob);
}
-void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase,
- DerivedMesh **r_dm_final, const bool for_orco,
- const bool use_render_resolution)
+void BKE_displist_make_curveTypes_forRender(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase,
+ DerivedMesh **r_dm_final, const bool for_orco,
+ const bool use_render_resolution)
{
if (ob->curve_cache == NULL) {
ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
}
- do_makeDispListCurveTypes(scene, ob, dispbase, r_dm_final, true, for_orco, use_render_resolution);
+ do_makeDispListCurveTypes(eval_ctx, scene, ob, dispbase, r_dm_final, true, for_orco, use_render_resolution);
}
-void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase)
+void BKE_displist_make_curveTypes_forOrco(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
{
if (ob->curve_cache == NULL) {
ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
}
- do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1, 1);
+ do_makeDispListCurveTypes(eval_ctx, scene, ob, dispbase, NULL, 1, 1, 1);
}
/* add Orco layer to the displist object which has got derived mesh and return orco */
-float *BKE_displist_make_orco(Scene *scene, Object *ob, DerivedMesh *dm_final,
- const bool for_render,
- const bool use_render_resolution)
+float *BKE_displist_make_orco(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm_final,
+ const bool for_render,
+ const bool use_render_resolution)
{
float *orco;
@@ -1812,7 +1822,7 @@ float *BKE_displist_make_orco(Scene *scene, Object *ob, DerivedMesh *dm_final,
dm_final = ob->derivedFinal;
if (!dm_final->getVertDataArray(dm_final, CD_ORCO)) {
- curve_calc_orcodm(scene, ob, dm_final, for_render, use_render_resolution);
+ curve_calc_orcodm(eval_ctx, scene, ob, dm_final, for_render, use_render_resolution);
}
orco = dm_final->getVertDataArray(dm_final, CD_ORCO);
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index b44ee21432c..8d27fcd2835 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -74,6 +74,8 @@
#include "BKE_pointcache.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
/* for image output */
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -486,36 +488,27 @@ static void scene_setSubframe(Scene *scene, float subframe)
scene->r.subframe = subframe;
}
-static int surface_getBrushFlags(DynamicPaintSurface *surface, const Scene *scene)
+static int surface_getBrushFlags(DynamicPaintSurface *surface, const ViewLayer *view_layer)
{
Base *base = NULL;
- GroupObject *go = NULL;
Object *brushObj = NULL;
ModifierData *md = NULL;
int flags = 0;
if (surface->brush_group)
- go = surface->brush_group->gobject.first;
+ base = FIRSTBASE(surface->brush_group->view_layer);
else
- base = scene->base.first;
+ base = FIRSTBASE(view_layer);
- while (base || go) {
+ while (base) {
brushObj = NULL;
/* select object */
- if (surface->brush_group) {
- if (go->ob)
- brushObj = go->ob;
- }
- else {
- brushObj = base->object;
- }
+ brushObj = base->object;
- if (surface->brush_group)
- go = go->next;
- else
- base = base->next;
+ /* next item */
+ base = base->next;
if (!brushObj) {
continue;
@@ -1973,7 +1966,9 @@ static void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMe
/*
* Updates derived mesh copy and processes dynamic paint step / caches.
*/
-static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm)
+static void dynamicPaint_frameUpdate(
+ DynamicPaintModifierData *pmd, const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, DerivedMesh *dm)
{
if (pmd->canvas) {
DynamicPaintCanvasSettings *canvas = pmd->canvas;
@@ -2036,7 +2031,7 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene
else if (can_simulate) {
/* calculate surface frame */
canvas->flags |= MOD_DPAINT_BAKING;
- dynamicPaint_calculateFrame(surface, scene, ob, current_frame);
+ dynamicPaint_calculateFrame(surface, eval_ctx, scene, ob, current_frame);
canvas->flags &= ~MOD_DPAINT_BAKING;
/* restore canvas derivedmesh if required */
@@ -2055,13 +2050,15 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene
}
/* Modifier call. Processes dynamic paint modifier step. */
-DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm)
+DerivedMesh *dynamicPaint_Modifier_do(
+ DynamicPaintModifierData *pmd, const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, DerivedMesh *dm)
{
if (pmd->canvas) {
DerivedMesh *ret;
/* Update canvas data for a new frame */
- dynamicPaint_frameUpdate(pmd, scene, ob, dm);
+ dynamicPaint_frameUpdate(pmd, eval_ctx, scene, ob, dm);
/* Return output mesh */
ret = dynamicPaint_Modifier_apply(pmd, ob, dm);
@@ -2070,7 +2067,7 @@ DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scen
}
else {
/* Update canvas data for a new frame */
- dynamicPaint_frameUpdate(pmd, scene, ob, dm);
+ dynamicPaint_frameUpdate(pmd, eval_ctx, scene, ob, dm);
/* Return output mesh */
return dynamicPaint_Modifier_apply(pmd, ob, dm);
@@ -3576,7 +3573,8 @@ static void dynamic_paint_brush_velocity_compute_cb(void *userdata, const int i)
}
static void dynamicPaint_brushMeshCalculateVelocity(
- Scene *scene, Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale)
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale)
{
float prev_obmat[4][4];
DerivedMesh *dm_p, *dm_c;
@@ -3598,7 +3596,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(
scene->r.subframe = prev_sfra;
BKE_object_modifier_update_subframe(
- scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
+ eval_ctx, scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
dm_p = CDDM_copy(brush->dm);
numOfVerts_p = dm_p->getNumVerts(dm_p);
mvert_p = dm_p->getVertArray(dm_p);
@@ -3609,7 +3607,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(
scene->r.subframe = cur_sfra;
BKE_object_modifier_update_subframe(
- scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
+ eval_ctx, scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
dm_c = brush->dm;
numOfVerts_c = dm_c->getNumVerts(dm_c);
mvert_c = dm_p->getVertArray(dm_c);
@@ -3634,7 +3632,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(
}
/* calculate velocity for object center point */
-static void dynamicPaint_brushObjectCalculateVelocity(Scene *scene, Object *ob, Vec3f *brushVel, float timescale)
+static void dynamicPaint_brushObjectCalculateVelocity(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, Vec3f *brushVel, float timescale)
{
float prev_obmat[4][4];
float cur_loc[3] = {0.0f}, prev_loc[3] = {0.0f};
@@ -3653,14 +3651,14 @@ static void dynamicPaint_brushObjectCalculateVelocity(Scene *scene, Object *ob,
scene->r.cfra = prev_fra;
scene->r.subframe = prev_sfra;
BKE_object_modifier_update_subframe(
- scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
+ eval_ctx, scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
copy_m4_m4(prev_obmat, ob->obmat);
/* current frame dm */
scene->r.cfra = cur_fra;
scene->r.subframe = cur_sfra;
BKE_object_modifier_update_subframe(
- scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
+ eval_ctx, scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
/* calculate speed */
mul_m4_v3(prev_obmat, prev_loc);
@@ -4030,7 +4028,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(
}
}
-static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
+static int dynamicPaint_paintMesh(const struct EvaluationContext *eval_ctx, DynamicPaintSurface *surface,
DynamicPaintBrushSettings *brush,
Object *brushOb,
BrushMaterials *bMats,
@@ -4046,7 +4044,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
const MLoop *mloop = NULL;
if (brush->flags & MOD_DPAINT_USES_VELOCITY)
- dynamicPaint_brushMeshCalculateVelocity(scene, brushOb, brush, &brushVelocity, timescale);
+ dynamicPaint_brushMeshCalculateVelocity(eval_ctx, scene, brushOb, brush, &brushVelocity, timescale);
if (!brush->dm)
return 0;
@@ -4524,7 +4522,7 @@ static void dynamic_paint_paint_single_point_cb_ex(
}
static int dynamicPaint_paintSinglePoint(
- DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush,
+ const struct EvaluationContext *eval_ctx, DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush,
Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale)
{
PaintSurfaceData *sData = surface->data;
@@ -4532,7 +4530,7 @@ static int dynamicPaint_paintSinglePoint(
Vec3f brushVel;
if (brush->flags & MOD_DPAINT_USES_VELOCITY)
- dynamicPaint_brushObjectCalculateVelocity(scene, brushOb, &brushVel, timescale);
+ dynamicPaint_brushObjectCalculateVelocity(eval_ctx, scene, brushOb, &brushVel, timescale);
const MVert *mvert = brush->dm->getVertArray(brush->dm);
@@ -4839,7 +4837,7 @@ static void dynamic_paint_prepare_effect_cb(void *userdata, const int index)
}
static int dynamicPaint_prepareEffectStep(
- DynamicPaintSurface *surface, Scene *scene, Object *ob, float **force, float timescale)
+ const struct EvaluationContext *eval_ctx, DynamicPaintSurface *surface, Scene *scene, Object *ob, float **force, float timescale)
{
double average_force = 0.0f;
float shrink_speed = 0.0f, spread_speed = 0.0f;
@@ -4850,7 +4848,7 @@ static int dynamicPaint_prepareEffectStep(
/* Init force data if required */
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
- ListBase *effectors = pdInitEffectors(scene, ob, NULL, surface->effector_weights, true);
+ ListBase *effectors = pdInitEffectors(eval_ctx, scene, ob, NULL, surface->effector_weights, true);
/* allocate memory for force data (dir vector + strength) */
*force = MEM_mallocN(sData->total_points * 4 * sizeof(float), "PaintEffectForces");
@@ -5632,7 +5630,7 @@ static void dynamic_paint_generate_bake_data_cb(void *userdata, const int index)
}
}
-static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Scene *scene, Object *ob)
+static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const ViewLayer *view_layer, Object *ob)
{
PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData;
@@ -5640,7 +5638,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Sce
int index;
bool new_bdata = false;
const bool do_velocity_data = ((surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) ||
- (surface_getBrushFlags(surface, scene) & BRUSH_USES_VELOCITY));
+ (surface_getBrushFlags(surface, view_layer) & BRUSH_USES_VELOCITY));
const bool do_accel_data = (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) != 0;
int canvasNumOfVerts = dm->getNumVerts(dm);
@@ -5752,7 +5750,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Sce
/*
* Do Dynamic Paint step. Paints scene brush objects of current state/frame to the surface.
*/
-static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *surface, float timescale, float subframe)
+static int dynamicPaint_doStep(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DynamicPaintSurface *surface, float timescale, float subframe)
{
PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData;
@@ -5773,9 +5771,9 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
*/
{
Base *base = NULL;
- GroupObject *go = NULL;
Object *brushObj = NULL;
ModifierData *md = NULL;
+ ViewLayer *view_layer = eval_ctx->view_layer;
/* backup current scene frame */
int scene_frame = scene->r.cfra;
@@ -5783,25 +5781,17 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
/* either from group or from all objects */
if (surface->brush_group)
- go = surface->brush_group->gobject.first;
+ base = FIRSTBASE(surface->brush_group->view_layer);
else
- base = scene->base.first;
+ base = FIRSTBASE(view_layer);
- while (base || go) {
+ while (base) {
brushObj = NULL;
/* select object */
- if (surface->brush_group) {
- if (go->ob)
- brushObj = go->ob;
- }
- else
- brushObj = base->object;
+ brushObj = base->object;
/* next item */
- if (surface->brush_group)
- go = go->next;
- else
- base = base->next;
+ base = base->next;
if (!brushObj) {
/* skip item */
@@ -5830,7 +5820,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
/* update object data on this subframe */
if (subframe) {
scene_setSubframe(scene, subframe);
- BKE_object_modifier_update_subframe(scene, brushObj, true, SUBFRAME_RECURSION,
+ BKE_object_modifier_update_subframe(eval_ctx, scene, brushObj, true, SUBFRAME_RECURSION,
BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
}
/* Prepare materials if required */
@@ -5838,8 +5828,6 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
dynamicPaint_updateBrushMaterials(brushObj, brush->mat, scene, &bMats);
/* Apply brush on the surface depending on it's collision type */
- /* Particle brush: */
- if (brush->collision == MOD_DPAINT_COL_PSYS) {
if (brush->psys && brush->psys->part &&
ELEM(brush->psys->part->type, PART_EMITTER, PART_FLUID) &&
psys_check_enabled(brushObj, brush->psys, G.is_rendering))
@@ -5849,14 +5837,13 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
BKE_scene_frame_get(scene), ADT_RECALC_ANIM);
dynamicPaint_paintParticles(surface, brush->psys, brush, timescale);
}
- }
/* Object center distance: */
- else if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
- dynamicPaint_paintSinglePoint(surface, brushObj->loc, brush, brushObj, &bMats, scene, timescale);
+ if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
+ dynamicPaint_paintSinglePoint(eval_ctx, surface, brushObj->loc, brush, brushObj, &bMats, scene, timescale);
}
/* Mesh volume/proximity: */
else if (brushObj != ob) {
- dynamicPaint_paintMesh(surface, brush, brushObj, &bMats, scene, timescale);
+ dynamicPaint_paintMesh(eval_ctx, surface, brush, brushObj, &bMats, scene, timescale);
}
/* free temp material data */
@@ -5866,7 +5853,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
if (subframe) {
scene->r.cfra = scene_frame;
scene->r.subframe = scene_subframe;
- BKE_object_modifier_update_subframe(scene, brushObj, true, SUBFRAME_RECURSION,
+ BKE_object_modifier_update_subframe(eval_ctx, scene, brushObj, true, SUBFRAME_RECURSION,
BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
}
@@ -5901,7 +5888,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
return setError(canvas, N_("Not enough free memory"));
/* Prepare effects and get number of required steps */
- steps = dynamicPaint_prepareEffectStep(surface, scene, ob, &force, timescale);
+ steps = dynamicPaint_prepareEffectStep(eval_ctx, surface, scene, ob, &force, timescale);
for (s = 0; s < steps; s++) {
dynamicPaint_doEffectStep(surface, force, prevPoint, timescale, (float)steps);
}
@@ -5925,7 +5912,9 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
/*
* Calculate a single frame and included subframes for surface
*/
-int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Object *cObject, int frame)
+int dynamicPaint_calculateFrame(
+ DynamicPaintSurface *surface, const struct EvaluationContext *eval_ctx,
+ Scene *scene, Object *cObject, int frame)
{
float timescale = 1.0f;
@@ -5934,7 +5923,7 @@ int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Obje
dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm);
/* update bake data */
- dynamicPaint_generateBakeData(surface, scene, cObject);
+ dynamicPaint_generateBakeData(surface, eval_ctx->view_layer, cObject);
/* don't do substeps for first frame */
if (surface->substeps && (frame != surface->start_frame)) {
@@ -5943,10 +5932,10 @@ int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Obje
for (st = 1; st <= surface->substeps; st++) {
float subframe = ((float) st) / (surface->substeps + 1);
- if (!dynamicPaint_doStep(scene, cObject, surface, timescale, subframe))
+ if (!dynamicPaint_doStep(eval_ctx, scene, cObject, surface, timescale, subframe))
return 0;
}
}
- return dynamicPaint_doStep(scene, cObject, surface, timescale, 0.0f);
+ return dynamicPaint_doStep(eval_ctx, scene, cObject, surface, timescale, 0.0f);
}
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index be8fcaa6863..0491cbd21f0 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -52,6 +52,7 @@
#include "BKE_mesh.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_bvh.h"
+#include "BKE_editmesh_tangent.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -242,392 +243,29 @@ static void emDM_calcLoopNormalsSpaceArray(
#endif
}
-
-/** \name Tangent Space Calculation
- * \{ */
-
-/* Necessary complexity to handle looptri's as quads for correct tangents */
-#define USE_LOOPTRI_DETECT_QUADS
-
-typedef struct {
- const float (*precomputedFaceNormals)[3];
- const float (*precomputedLoopNormals)[3];
- const BMLoop *(*looptris)[3];
- int cd_loop_uv_offset; /* texture coordinates */
- const float (*orco)[3];
- float (*tangent)[4]; /* destination */
- int numTessFaces;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- /* map from 'fake' face index to looptri,
- * quads will point to the first looptri of the quad */
- const int *face_as_quad_map;
- int num_face_as_quad_map;
-#endif
-
-} SGLSLEditMeshToTangent;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
-/* seems weak but only used on quads */
-static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index)
-{
- const BMLoop *l = BM_FACE_FIRST_LOOP(f);
- while (vert_index--) {
- l = l->next;
- }
- return l;
-}
-#endif
-
-/* interface */
-#include "mikktspace.h"
-
-static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
-{
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- return pMesh->num_face_as_quad_map;
-#else
- return pMesh->numTessFaces;
-#endif
-}
-
-static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
-{
-#ifdef USE_LOOPTRI_DETECT_QUADS
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- if (pMesh->face_as_quad_map) {
- const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
- if (lt[0]->f->len == 4) {
- return 4;
- }
- }
- return 3;
-#else
- UNUSED_VARS(pContext, face_num);
- return 3;
-#endif
-}
-
-static void emdm_ts_GetPosition(
- const SMikkTSpaceContext *pContext, float r_co[3],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt;
- const BMLoop *l;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
- if (lt[0]->f->len == 4) {
- l = bm_loop_at_face_index(lt[0]->f, vert_index);
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = pMesh->looptris[face_num];
- }
-#else
- lt = pMesh->looptris[face_num];
-#endif
- l = lt[vert_index];
-
- const float *co;
-
-finally:
- co = l->v->co;
- copy_v3_v3(r_co, co);
-}
-
-static void emdm_ts_GetTextureCoordinate(
- const SMikkTSpaceContext *pContext, float r_uv[2],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt;
- const BMLoop *l;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
- if (lt[0]->f->len == 4) {
- l = bm_loop_at_face_index(lt[0]->f, vert_index);
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = pMesh->looptris[face_num];
- }
-#else
- lt = pMesh->looptris[face_num];
-#endif
- l = lt[vert_index];
-
-finally:
- if (pMesh->cd_loop_uv_offset != -1) {
- const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset);
- copy_v2_v2(r_uv, uv);
- }
- else {
- const float *orco = pMesh->orco[BM_elem_index_get(l->v)];
- map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
- }
-}
-
-static void emdm_ts_GetNormal(
- const SMikkTSpaceContext *pContext, float r_no[3],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt;
- const BMLoop *l;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
- if (lt[0]->f->len == 4) {
- l = bm_loop_at_face_index(lt[0]->f, vert_index);
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = pMesh->looptris[face_num];
- }
-#else
- lt = pMesh->looptris[face_num];
-#endif
- l = lt[vert_index];
-
-finally:
- if (pMesh->precomputedLoopNormals) {
- copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]);
- }
- else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */
- if (pMesh->precomputedFaceNormals) {
- copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]);
- }
- else {
- copy_v3_v3(r_no, l->f->no);
- }
- }
- else {
- copy_v3_v3(r_no, l->v->no);
- }
-}
-
-static void emdm_ts_SetTSpace(
- const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt;
- const BMLoop *l;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
- if (lt[0]->f->len == 4) {
- l = bm_loop_at_face_index(lt[0]->f, vert_index);
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = pMesh->looptris[face_num];
- }
-#else
- lt = pMesh->looptris[face_num];
-#endif
- l = lt[vert_index];
-
- float *pRes;
-
-finally:
- pRes = pMesh->tangent[BM_elem_index_get(l)];
- copy_v3_v3(pRes, fvTangent);
- pRes[3] = fSign;
-}
-
-static void emDM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- struct SGLSLEditMeshToTangent *mesh2tangent = taskdata;
- /* new computation method */
- {
- SMikkTSpaceContext sContext = {NULL};
- SMikkTSpaceInterface sInterface = {NULL};
- sContext.m_pUserData = mesh2tangent;
- sContext.m_pInterface = &sInterface;
- sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
- sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace;
- sInterface.m_getPosition = emdm_ts_GetPosition;
- sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate;
- sInterface.m_getNormal = emdm_ts_GetNormal;
- sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace;
- /* 0 if failed */
- genTangSpaceDefault(&sContext);
- }
-}
-
-/**
- * \see #DM_calc_loop_tangents, same logic but used arrays instead of #BMesh data.
- *
- * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`.
- * This is done because #CD_TANGENT is cache data used only for drawing.
- */
-
static void emDM_calc_loop_tangents(
DerivedMesh *dm, bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME], int tangent_names_count)
+ const char (*tangent_names)[MAX_NAME], int tangent_names_len)
{
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMEditMesh *em = bmdm->em;
- BMesh *bm = bmdm->em->bm;
-
- int act_uv_n = -1;
- int ren_uv_n = -1;
- bool calc_act = false;
- bool calc_ren = false;
- char act_uv_name[MAX_NAME];
- char ren_uv_name[MAX_NAME];
- short tangent_mask = 0;
-
- DM_calc_loop_tangents_step_0(
- &bm->ldata, calc_active_tangent, tangent_names, tangent_names_count,
- &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
-
- if ((dm->tangent_mask | tangent_mask) != dm->tangent_mask) {
- for (int i = 0; i < tangent_names_count; i++)
- if (tangent_names[i][0])
- DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, tangent_names[i]);
- if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1)
- CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, "");
- if (calc_act && act_uv_name[0])
- DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, act_uv_name);
- if (calc_ren && ren_uv_name[0])
- DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, ren_uv_name);
- int totface = em->tottri;
-#ifdef USE_LOOPTRI_DETECT_QUADS
- int num_face_as_quad_map;
- int *face_as_quad_map = NULL;
-
- /* map faces to quads */
- if (bmdm->em->tottri != bm->totface) {
- /* over alloc, since we dont know how many ngon or quads we have */
-
- /* map fake face index to looptri */
- face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
- int i, j;
- for (i = 0, j = 0; j < totface; i++, j++) {
- face_as_quad_map[i] = j;
- /* step over all quads */
- if (em->looptris[j][0]->f->len == 4) {
- j++; /* skips the nest looptri */
- }
- }
- num_face_as_quad_map = i;
- }
- else {
- num_face_as_quad_map = totface;
- }
-#endif
- /* Calculation */
- {
- TaskScheduler *scheduler = BLI_task_scheduler_get();
- TaskPool *task_pool;
- task_pool = BLI_task_pool_create(scheduler, NULL);
-
- dm->tangent_mask = 0;
- /* Calculate tangent layers */
- SGLSLEditMeshToTangent data_array[MAX_MTFACE];
- int index = 0;
- int n = 0;
- CustomData_update_typemap(&dm->loopData);
- const int tangent_layer_num = CustomData_number_of_layers(&dm->loopData, CD_TANGENT);
- for (n = 0; n < tangent_layer_num; n++) {
- index = CustomData_get_layer_index_n(&dm->loopData, CD_TANGENT, n);
- BLI_assert(n < MAX_MTFACE);
- SGLSLEditMeshToTangent *mesh2tangent = &data_array[n];
- mesh2tangent->numTessFaces = em->tottri;
-#ifdef USE_LOOPTRI_DETECT_QUADS
- mesh2tangent->face_as_quad_map = face_as_quad_map;
- mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
-#endif
- mesh2tangent->precomputedFaceNormals = bmdm->polyNos; /* dm->getPolyDataArray(dm, CD_NORMAL) */
- /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
- * have to check this is valid...
- */
- mesh2tangent->precomputedLoopNormals = CustomData_get_layer(&dm->loopData, CD_NORMAL);
- mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n);
-
- /* needed for indexing loop-tangents */
- int htype_index = BM_LOOP;
- if (mesh2tangent->cd_loop_uv_offset == -1) {
- mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO);
- if (!mesh2tangent->orco)
- continue;
- /* needed for orco lookups */
- htype_index |= BM_VERT;
- dm->tangent_mask |= DM_TANGENT_MASK_ORCO;
- }
- else {
- /* Fill the resulting tangent_mask */
- int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, dm->loopData.layers[index].name);
- int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
- BLI_assert(uv_ind != -1 && uv_start != -1);
- BLI_assert(uv_ind - uv_start < MAX_MTFACE);
- dm->tangent_mask |= 1 << (uv_ind - uv_start);
- }
-
- if (mesh2tangent->precomputedFaceNormals) {
- /* needed for face normal lookups */
- htype_index |= BM_FACE;
- }
- BM_mesh_elem_index_ensure(bm, htype_index);
- mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris;
- mesh2tangent->tangent = dm->loopData.layers[index].data;
-
- BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
- }
-
- BLI_assert(dm->tangent_mask == tangent_mask);
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
- }
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (face_as_quad_map) {
- MEM_freeN(face_as_quad_map);
- }
-#undef USE_LOOPTRI_DETECT_QUADS
-#endif
+ if (CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV) == 0) {
+ return;
}
- /* Update active layer index */
- int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
- if (act_uv_index >= 0) {
- int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[act_uv_index].name);
- CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index);
- } /* else tangent has been built from orco */
-
- /* Update render layer index */
- int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
- if (ren_uv_index >= 0) {
- int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[ren_uv_index].name);
- CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index);
- } /* else tangent has been built from orco */
+ const float (*poly_normals)[3] = bmdm->polyNos;
+ const float (*loop_normals)[3] = CustomData_get_layer(&dm->loopData, CD_NORMAL);
+ const float (*vert_orco)[3] = dm->getVertDataArray(dm, CD_ORCO); /* can be NULL */
+ BKE_editmesh_loop_tangent_calc(
+ em, calc_active_tangent,
+ tangent_names, tangent_names_len,
+ poly_normals, loop_normals,
+ vert_orco,
+ &dm->loopData, dm->numLoopData,
+ &dm->tangent_mask);
}
-/** \} */
-
static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
{
@@ -816,39 +454,6 @@ static void emDM_drawMappedEdgesInterp(
}
}
-static void emDM_drawUVEdges(DerivedMesh *dm)
-{
- EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
- BMesh *bm = bmdm->em->bm;
- BMFace *efa;
- BMIter iter;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- if (UNLIKELY(cd_loop_uv_offset == -1)) {
- return;
- }
-
- glBegin(GL_LINES);
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter, *l_first;
- const float *uv, *uv_prev;
-
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
- continue;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter->prev, cd_loop_uv_offset))->uv;
- do {
- uv = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
- glVertex2fv(uv);
- glVertex2fv(uv_prev);
- uv_prev = uv;
- } while ((l_iter = l_iter->next) != l_first);
- }
- glEnd();
-}
-
static void emDM_foreachMappedLoop(
DerivedMesh *dm,
void (*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]),
@@ -1036,11 +641,11 @@ static void emDM_drawMappedFaces(
if (poly_prev != GL_ZERO) glEnd();
glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
}
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
}
else {
@@ -1057,23 +662,23 @@ static void emDM_drawMappedFaces(
if (!drawSmooth) {
glNormal3fv(polyNos[BM_elem_index_get(efa)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
}
else {
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
@@ -1138,11 +743,11 @@ static void emDM_drawMappedFaces(
if (poly_prev != GL_ZERO) glEnd();
glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
}
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
glVertex3fv(ltri[0]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
glVertex3fv(ltri[1]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
glVertex3fv(ltri[2]->v->co);
}
else {
@@ -1159,23 +764,23 @@ static void emDM_drawMappedFaces(
if (!drawSmooth) {
glNormal3fv(efa->no);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
glVertex3fv(ltri[0]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
glVertex3fv(ltri[1]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
glVertex3fv(ltri[2]->v->co);
}
else {
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
else glNormal3fv(ltri[0]->v->no);
glVertex3fv(ltri[0]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
else glNormal3fv(ltri[1]->v->no);
glVertex3fv(ltri[1]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
else glNormal3fv(ltri[2]->v->no);
glVertex3fv(ltri[2]->v->co);
@@ -1197,20 +802,6 @@ static void emDM_drawMappedFaces(
}
}
-static void bmdm_get_tri_uv(BMLoop *ltri[3], MLoopUV *luv[3], const int cd_loop_uv_offset)
-{
- luv[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_uv_offset);
- luv[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_uv_offset);
- luv[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_uv_offset);
-}
-
-static void bmdm_get_tri_col(BMLoop *ltri[3], MLoopCol *lcol[3], const int cd_loop_color_offset)
-{
- lcol[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_color_offset);
- lcol[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_color_offset);
- lcol[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_color_offset);
-}
-
static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4])
{
lcol[0] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[0]->v)];
@@ -1218,204 +809,6 @@ static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned c
lcol[2] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[2]->v)];
}
-static void emDM_drawFacesTex_common(
- DerivedMesh *dm,
- DMSetDrawOptionsTex drawParams,
- DMSetDrawOptionsMappedTex drawParamsMapped,
- DMCompareDrawOptions compareDrawOptions,
- void *userData)
-{
- EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
- BMEditMesh *em = bmdm->em;
- BMesh *bm = em->bm;
- struct BMLoop *(*looptris)[3] = em->looptris;
- BMFace *efa;
- const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
- MLoopUV *luv[3], dummyluv = {{0}};
- MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
- const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
- unsigned char(*color_vert_array)[4] = em->derivedVertColor;
- bool has_uv = (cd_loop_uv_offset != -1);
- bool has_vcol_preview = (color_vert_array != NULL);
- bool has_vcol = (cd_loop_color_offset != -1) && (has_vcol_preview == false);
- bool has_vcol_any = (has_vcol_preview || has_vcol);
- int i;
-
- (void) compareDrawOptions;
-
- luv[0] = luv[1] = luv[2] = &dummyluv;
-
- // dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255; /* UNUSED */
-
- /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
- BM_mesh_elem_index_ensure(bm, BM_FACE);
-
- /* call again below is ok */
- if (has_vcol_preview) {
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- }
-
- if (bmdm->vertexCos) {
- /* add direct access */
- const float (*vertexCos)[3] = bmdm->vertexCos;
- const float (*vertexNos)[3];
- const float (*polyNos)[3];
-
- emDM_ensureVertNormals(bmdm);
- emDM_ensurePolyNormals(bmdm);
- vertexNos = bmdm->vertexNos;
- polyNos = bmdm->polyNos;
-
- BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT);
-
- for (i = 0; i < em->tottri; i++) {
- BMLoop **ltri = looptris[i];
- MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
- /*unsigned char *cp = NULL;*/ /*UNUSED*/
- int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
- DMDrawOption draw_option;
-
- efa = ltri[0]->f;
-
- if (drawParams) {
- draw_option = drawParams(tp, has_vcol, efa->mat_nr);
- }
- else if (drawParamsMapped)
- draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
- else
- draw_option = DM_DRAW_OPTION_NORMAL;
-
- if (draw_option != DM_DRAW_OPTION_SKIP) {
-
- if (has_uv) bmdm_get_tri_uv(ltri, luv, cd_loop_uv_offset);
- if (has_vcol) bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
- else if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
-
- glBegin(GL_TRIANGLES);
- if (!drawSmooth) {
- glNormal3fv(polyNos[BM_elem_index_get(efa)]);
-
- glTexCoord2fv(luv[0]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
-
- glTexCoord2fv(luv[1]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
-
- glTexCoord2fv(luv[2]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
- }
- else {
- glTexCoord2fv(luv[0]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
- else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
-
- glTexCoord2fv(luv[1]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
- else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
-
- glTexCoord2fv(luv[2]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
- else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
- }
- glEnd();
- }
- }
- }
- else {
- BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT);
-
- for (i = 0; i < em->tottri; i++) {
- BMLoop **ltri = looptris[i];
- MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
- /*unsigned char *cp = NULL;*/ /*UNUSED*/
- int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
- DMDrawOption draw_option;
-
- efa = ltri[0]->f;
-
- if (drawParams)
- draw_option = drawParams(tp, has_vcol, efa->mat_nr);
- else if (drawParamsMapped)
- draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
- else
- draw_option = DM_DRAW_OPTION_NORMAL;
-
- if (draw_option != DM_DRAW_OPTION_SKIP) {
-
- if (has_uv) bmdm_get_tri_uv(ltri, luv, cd_loop_uv_offset);
- if (has_vcol) bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
- else if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
-
- glBegin(GL_TRIANGLES);
- if (!drawSmooth) {
- glNormal3fv(efa->no);
-
- glTexCoord2fv(luv[0]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
- glVertex3fv(ltri[0]->v->co);
-
- glTexCoord2fv(luv[1]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
- glVertex3fv(ltri[1]->v->co);
-
- glTexCoord2fv(luv[2]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
- glVertex3fv(ltri[2]->v->co);
- }
- else {
- glTexCoord2fv(luv[0]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
- else glNormal3fv(ltri[0]->v->no);
- glVertex3fv(ltri[0]->v->co);
-
- glTexCoord2fv(luv[1]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
- else glNormal3fv(ltri[1]->v->no);
- glVertex3fv(ltri[1]->v->co);
-
- glTexCoord2fv(luv[2]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
- else glNormal3fv(ltri[2]->v->no);
- glVertex3fv(ltri[2]->v->co);
- }
- glEnd();
- }
- }
- }
-}
-
-static void emDM_drawFacesTex(
- DerivedMesh *dm,
- DMSetDrawOptionsTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag UNUSED(flag))
-{
- emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
-}
-
-static void emDM_drawMappedFacesTex(
- DerivedMesh *dm,
- DMSetDrawOptionsMappedTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag UNUSED(flag))
-{
- emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
-}
-
/**
* \note
*
@@ -2061,14 +1454,8 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
if (type == CD_MTFACE || type == CD_MCOL) {
const char *bmdata;
char *data;
- bool has_type_source = false;
- if (type == CD_MTFACE) {
- has_type_source = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
- }
- else {
- has_type_source = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
- }
+ bool has_type_source = CustomData_has_layer(&bm->ldata, (type == CD_MTFACE) ? CD_MLOOPUV : CD_MLOOPCOL);
if (has_type_source) {
/* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
@@ -2084,15 +1471,8 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
if (type == CD_MTFACE) {
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);
for (i = 0; i < bmdm->em->tottri; i++, data += size) {
- BMFace *efa = looptris[i][0]->f;
-
- // bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
- bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- ME_MTEXFACE_CPY(((MTFace *)data), ((const MTexPoly *)bmdata));
for (j = 0; j < 3; j++) {
// bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV);
bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset);
@@ -2284,12 +1664,9 @@ DerivedMesh *getEditDerivedBMesh(
bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
- bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
- bmdm->dm.drawFacesTex = emDM_drawFacesTex;
bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
- bmdm->dm.drawUVEdges = emDM_drawUVEdges;
bmdm->dm.release = emDM_release;
@@ -2799,14 +2176,14 @@ static void cage_mapped_verts_callback(
}
}
-float (*BKE_editmesh_vertexCos_get(BMEditMesh *em, Scene *scene, int *r_numVerts))[3]
+float (*BKE_editmesh_vertexCos_get(const struct EvaluationContext *eval_ctx, BMEditMesh *em, Scene *scene, int *r_numVerts))[3]
{
DerivedMesh *cage, *final;
BLI_bitmap *visit_bitmap;
struct CageUserData data;
float (*cos_cage)[3];
- cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, CD_MASK_BAREMESH, &final);
+ cage = editbmesh_get_derived_cage_and_final(eval_ctx, scene, em->ob, em, CD_MASK_BAREMESH, &final);
cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
/* when initializing cage verts, we only want the first cage coordinate for each vertex,
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index fea3c24d322..c95da3b2569 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -165,26 +165,6 @@ void BKE_editmesh_tessface_calc(BMEditMesh *em)
#endif
}
-void BKE_editmesh_update_linked_customdata(BMEditMesh *em)
-{
- BMesh *bm = em->bm;
- int act;
-
- if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
- act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
- CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
-
- act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
- CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
-
- act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
- CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
-
- act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY);
- CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act);
- }
-}
-
void BKE_editmesh_free_derivedmesh(BMEditMesh *em)
{
if (em->derivedCage) {
diff --git a/source/blender/blenkernel/intern/editmesh_tangent.c b/source/blender/blenkernel/intern/editmesh_tangent.c
new file mode 100644
index 00000000000..f725a1793b4
--- /dev/null
+++ b/source/blender/blenkernel/intern/editmesh_tangent.c
@@ -0,0 +1,431 @@
+/*
+ * ***** 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/blenkernel/intern/editmesh_tangent.c
+ * \ingroup bke
+ */
+
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "BKE_DerivedMesh.h"
+
+#include "BKE_mesh.h"
+#include "BKE_mesh_tangent.h" /* for utility functions */
+#include "BKE_editmesh.h"
+#include "BKE_editmesh_tangent.h"
+
+#include "MEM_guardedalloc.h"
+
+/* interface */
+#include "mikktspace.h"
+
+/** \name Tangent Space Calculation
+ * \{ */
+
+/* Necessary complexity to handle looptri's as quads for correct tangents */
+#define USE_LOOPTRI_DETECT_QUADS
+
+typedef struct {
+ const float (*precomputedFaceNormals)[3];
+ const float (*precomputedLoopNormals)[3];
+ const BMLoop *(*looptris)[3];
+ int cd_loop_uv_offset; /* texture coordinates */
+ const float (*orco)[3];
+ float (*tangent)[4]; /* destination */
+ int numTessFaces;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ /* map from 'fake' face index to looptri,
+ * quads will point to the first looptri of the quad */
+ const int *face_as_quad_map;
+ int num_face_as_quad_map;
+#endif
+
+} SGLSLEditMeshToTangent;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+/* seems weak but only used on quads */
+static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index)
+{
+ const BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ while (vert_index--) {
+ l = l->next;
+ }
+ return l;
+}
+#endif
+
+static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
+{
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ return pMesh->num_face_as_quad_map;
+#else
+ return pMesh->numTessFaces;
+#endif
+}
+
+static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
+{
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ if (pMesh->face_as_quad_map) {
+ const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
+ if (lt[0]->f->len == 4) {
+ return 4;
+ }
+ }
+ return 3;
+#else
+ UNUSED_VARS(pContext, face_num);
+ return 3;
+#endif
+}
+
+static void emdm_ts_GetPosition(
+ const SMikkTSpaceContext *pContext, float r_co[3],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ const BMLoop **lt;
+ const BMLoop *l;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
+ if (lt[0]->f->len == 4) {
+ l = bm_loop_at_face_index(lt[0]->f, vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = pMesh->looptris[face_num];
+ }
+#else
+ lt = pMesh->looptris[face_num];
+#endif
+ l = lt[vert_index];
+
+ const float *co;
+
+finally:
+ co = l->v->co;
+ copy_v3_v3(r_co, co);
+}
+
+static void emdm_ts_GetTextureCoordinate(
+ const SMikkTSpaceContext *pContext, float r_uv[2],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ const BMLoop **lt;
+ const BMLoop *l;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
+ if (lt[0]->f->len == 4) {
+ l = bm_loop_at_face_index(lt[0]->f, vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = pMesh->looptris[face_num];
+ }
+#else
+ lt = pMesh->looptris[face_num];
+#endif
+ l = lt[vert_index];
+
+finally:
+ if (pMesh->cd_loop_uv_offset != -1) {
+ const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset);
+ copy_v2_v2(r_uv, uv);
+ }
+ else {
+ const float *orco = pMesh->orco[BM_elem_index_get(l->v)];
+ map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
+ }
+}
+
+static void emdm_ts_GetNormal(
+ const SMikkTSpaceContext *pContext, float r_no[3],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ const BMLoop **lt;
+ const BMLoop *l;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
+ if (lt[0]->f->len == 4) {
+ l = bm_loop_at_face_index(lt[0]->f, vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = pMesh->looptris[face_num];
+ }
+#else
+ lt = pMesh->looptris[face_num];
+#endif
+ l = lt[vert_index];
+
+finally:
+ if (pMesh->precomputedLoopNormals) {
+ copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]);
+ }
+ else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */
+ if (pMesh->precomputedFaceNormals) {
+ copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]);
+ }
+ else {
+ copy_v3_v3(r_no, l->f->no);
+ }
+ }
+ else {
+ copy_v3_v3(r_no, l->v->no);
+ }
+}
+
+static void emdm_ts_SetTSpace(
+ const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ const BMLoop **lt;
+ const BMLoop *l;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
+ if (lt[0]->f->len == 4) {
+ l = bm_loop_at_face_index(lt[0]->f, vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = pMesh->looptris[face_num];
+ }
+#else
+ lt = pMesh->looptris[face_num];
+#endif
+ l = lt[vert_index];
+
+ float *pRes;
+
+finally:
+ pRes = pMesh->tangent[BM_elem_index_get(l)];
+ copy_v3_v3(pRes, fvTangent);
+ pRes[3] = fSign;
+}
+
+static void emDM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
+{
+ struct SGLSLEditMeshToTangent *mesh2tangent = taskdata;
+ /* new computation method */
+ {
+ SMikkTSpaceContext sContext = {NULL};
+ SMikkTSpaceInterface sInterface = {NULL};
+ sContext.m_pUserData = mesh2tangent;
+ sContext.m_pInterface = &sInterface;
+ sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
+ sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace;
+ sInterface.m_getPosition = emdm_ts_GetPosition;
+ sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate;
+ sInterface.m_getNormal = emdm_ts_GetNormal;
+ sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace;
+ /* 0 if failed */
+ genTangSpaceDefault(&sContext);
+ }
+}
+
+/**
+ * \see #BKE_mesh_calc_loop_tangent, same logic but used arrays instead of #BMesh data.
+ *
+ * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`.
+ * This is done because #CD_TANGENT is cache data used only for drawing.
+ */
+void BKE_editmesh_loop_tangent_calc(
+ BMEditMesh *em, bool calc_active_tangent,
+ const char (*tangent_names)[MAX_NAME], int tangent_names_len,
+ const float (*poly_normals)[3],
+ const float (*loop_normals)[3],
+ const float (*vert_orco)[3],
+ /* result */
+ CustomData *loopdata_out,
+ const uint loopdata_out_len,
+ short *tangent_mask_curr_p)
+{
+ BMesh *bm = em->bm;
+
+ int act_uv_n = -1;
+ int ren_uv_n = -1;
+ bool calc_act = false;
+ bool calc_ren = false;
+ char act_uv_name[MAX_NAME];
+ char ren_uv_name[MAX_NAME];
+ short tangent_mask = 0;
+ short tangent_mask_curr = *tangent_mask_curr_p;
+
+ BKE_mesh_calc_loop_tangent_step_0(
+ &bm->ldata, calc_active_tangent, tangent_names, tangent_names_len,
+ &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
+
+ if ((tangent_mask_curr | tangent_mask) != tangent_mask_curr) {
+ for (int i = 0; i < tangent_names_len; i++) {
+ if (tangent_names[i][0]) {
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(
+ &bm->ldata, loopdata_out, (int)loopdata_out_len, tangent_names[i]);
+ }
+ }
+ if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, "") == -1)
+ CustomData_add_layer_named(loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, "");
+ if (calc_act && act_uv_name[0])
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(&bm->ldata, loopdata_out, (int)loopdata_out_len, act_uv_name);
+ if (calc_ren && ren_uv_name[0])
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(&bm->ldata, loopdata_out, (int)loopdata_out_len, ren_uv_name);
+ int totface = em->tottri;
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ int num_face_as_quad_map;
+ int *face_as_quad_map = NULL;
+
+ /* map faces to quads */
+ if (em->tottri != bm->totface) {
+ /* over alloc, since we dont know how many ngon or quads we have */
+
+ /* map fake face index to looptri */
+ face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
+ int i, j;
+ for (i = 0, j = 0; j < totface; i++, j++) {
+ face_as_quad_map[i] = j;
+ /* step over all quads */
+ if (em->looptris[j][0]->f->len == 4) {
+ j++; /* skips the nest looptri */
+ }
+ }
+ num_face_as_quad_map = i;
+ }
+ else {
+ num_face_as_quad_map = totface;
+ }
+#endif
+ /* Calculation */
+ if (em->tottri != 0) {
+ TaskScheduler *scheduler = BLI_task_scheduler_get();
+ TaskPool *task_pool;
+ task_pool = BLI_task_pool_create(scheduler, NULL);
+
+ tangent_mask_curr = 0;
+ /* Calculate tangent layers */
+ SGLSLEditMeshToTangent data_array[MAX_MTFACE];
+ int index = 0;
+ int n = 0;
+ CustomData_update_typemap(loopdata_out);
+ const int tangent_layer_num = CustomData_number_of_layers(loopdata_out, CD_TANGENT);
+ for (n = 0; n < tangent_layer_num; n++) {
+ index = CustomData_get_layer_index_n(loopdata_out, CD_TANGENT, n);
+ BLI_assert(n < MAX_MTFACE);
+ SGLSLEditMeshToTangent *mesh2tangent = &data_array[n];
+ mesh2tangent->numTessFaces = em->tottri;
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ mesh2tangent->face_as_quad_map = face_as_quad_map;
+ mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
+#endif
+ mesh2tangent->precomputedFaceNormals = poly_normals; /* dm->getPolyDataArray(dm, CD_NORMAL) */
+ /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
+ * have to check this is valid...
+ */
+ mesh2tangent->precomputedLoopNormals = loop_normals;
+ mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n);
+
+ /* needed for indexing loop-tangents */
+ int htype_index = BM_LOOP;
+ if (mesh2tangent->cd_loop_uv_offset == -1) {
+ mesh2tangent->orco = vert_orco;
+ if (!mesh2tangent->orco)
+ continue;
+ /* needed for orco lookups */
+ htype_index |= BM_VERT;
+ tangent_mask_curr |= DM_TANGENT_MASK_ORCO;
+ }
+ else {
+ /* Fill the resulting tangent_mask */
+ int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, loopdata_out->layers[index].name);
+ int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
+ BLI_assert(uv_ind != -1 && uv_start != -1);
+ BLI_assert(uv_ind - uv_start < MAX_MTFACE);
+ tangent_mask_curr |= 1 << (uv_ind - uv_start);
+ }
+ if (mesh2tangent->precomputedFaceNormals) {
+ /* needed for face normal lookups */
+ htype_index |= BM_FACE;
+ }
+ BM_mesh_elem_index_ensure(bm, htype_index);
+
+ mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris;
+ mesh2tangent->tangent = loopdata_out->layers[index].data;
+
+ BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
+ }
+
+ BLI_assert(tangent_mask_curr == tangent_mask);
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
+ }
+ else {
+ tangent_mask_curr = tangent_mask;
+ }
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (face_as_quad_map) {
+ MEM_freeN(face_as_quad_map);
+ }
+#undef USE_LOOPTRI_DETECT_QUADS
+#endif
+ }
+
+ *tangent_mask_curr_p = tangent_mask_curr;
+
+ int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
+ if (act_uv_index >= 0) {
+ int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, bm->ldata.layers[act_uv_index].name);
+ CustomData_set_layer_active_index(loopdata_out, CD_TANGENT, tan_index);
+ } /* else tangent has been built from orco */
+
+ /* Update render layer index */
+ int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
+ if (ren_uv_index >= 0) {
+ int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, bm->ldata.layers[ren_uv_index].name);
+ CustomData_set_layer_render_index(loopdata_out, CD_TANGENT, tan_index);
+ } /* else tangent has been built from orco */
+}
+
+/** \} */ \ No newline at end of file
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 38f5c00941c..16124fb4777 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -64,6 +64,8 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_effect.h"
#include "BKE_global.h"
+#include "BKE_group.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -71,6 +73,7 @@
#include "BKE_scene.h"
#include "BKE_smoke.h"
+#include "DEG_depsgraph.h"
#include "RE_render_ext.h"
#include "RE_shader_ext.h"
@@ -145,9 +148,10 @@ void free_partdeflect(PartDeflect *pd)
MEM_freeN(pd);
}
-static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd)
+static EffectorCache *new_effector_cache(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd)
{
EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache");
+ eff->eval_ctx = eval_ctx;
eff->scene = scene;
eff->ob = ob;
eff->psys = psys;
@@ -155,7 +159,7 @@ static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSyste
eff->frame = -1;
return eff;
}
-static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src, bool for_simulation)
+static void add_object_to_effectors(ListBase **effectors, const struct EvaluationContext *eval_ctx, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src, bool for_simulation)
{
EffectorCache *eff = NULL;
@@ -173,14 +177,14 @@ static void add_object_to_effectors(ListBase **effectors, Scene *scene, Effector
if (*effectors == NULL)
*effectors = MEM_callocN(sizeof(ListBase), "effectors list");
- eff = new_effector_cache(scene, ob, NULL, ob->pd);
+ eff = new_effector_cache(eval_ctx, scene, ob, NULL, ob->pd);
/* make sure imat is up to date */
invert_m4_m4(ob->imat, ob->obmat);
BLI_addtail(*effectors, eff);
}
-static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src, bool for_simulation)
+static void add_particles_to_effectors(ListBase **effectors, const struct EvaluationContext *eval_ctx, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src, bool for_simulation)
{
ParticleSettings *part= psys->part;
@@ -194,61 +198,59 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec
if (*effectors == NULL)
*effectors = MEM_callocN(sizeof(ListBase), "effectors list");
- BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd));
+ BLI_addtail(*effectors, new_effector_cache(eval_ctx, scene, ob, psys, part->pd));
}
if (part->pd2 && part->pd2->forcefield && (!for_simulation || weights->weight[part->pd2->forcefield] != 0.0f)) {
if (*effectors == NULL)
*effectors = MEM_callocN(sizeof(ListBase), "effectors list");
- BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd2));
+ BLI_addtail(*effectors, new_effector_cache(eval_ctx, scene, ob, psys, part->pd2));
}
}
/* returns ListBase handle with objects taking part in the effecting */
-ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src,
- EffectorWeights *weights, bool for_simulation)
+ListBase *pdInitEffectors(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob_src, ParticleSystem *psys_src,
+ EffectorWeights *weights, bool for_simulation)
{
+ ViewLayer *view_layer;
Base *base;
- unsigned int layer= ob_src->lay;
ListBase *effectors = NULL;
-
+
if (weights->group) {
- GroupObject *go;
-
- for (go= weights->group->gobject.first; go; go= go->next) {
- if ( (go->ob->lay & layer) ) {
- if ( go->ob->pd && go->ob->pd->forcefield )
- add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src, for_simulation);
+ view_layer = weights->group->view_layer;
+ }
+ else if (eval_ctx) {
+ view_layer = eval_ctx->view_layer;
+ }
+ else {
+ /* eval_ctx is NULL during deg build */
+ view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
+ }
- if ( go->ob->particlesystem.first ) {
- ParticleSystem *psys= go->ob->particlesystem.first;
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) == 0) {
+ continue;
+ }
- for ( ; psys; psys=psys->next )
- add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src, for_simulation);
- }
- }
+ if (base->object->pd && base->object->pd->forcefield) {
+ add_object_to_effectors(&effectors, eval_ctx, scene, weights, base->object, ob_src, for_simulation);
}
- }
- else {
- for (base = scene->base.first; base; base= base->next) {
- if ( (base->lay & layer) ) {
- if ( base->object->pd && base->object->pd->forcefield )
- add_object_to_effectors(&effectors, scene, weights, base->object, ob_src, for_simulation);
- if ( base->object->particlesystem.first ) {
- ParticleSystem *psys= base->object->particlesystem.first;
+ if (base->object->particlesystem.first) {
+ ParticleSystem *psys= base->object->particlesystem.first;
- for ( ; psys; psys=psys->next )
- add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src, for_simulation);
- }
+ for (; psys; psys=psys->next) {
+ add_particles_to_effectors(&effectors, eval_ctx, scene, weights, base->object, psys, psys_src, for_simulation);
}
}
}
-
- if (for_simulation)
- pdPrecalculateEffectors(effectors);
-
+
+ if (for_simulation) {
+ pdPrecalculateEffectors(eval_ctx, effectors);
+ }
+
return effectors;
}
@@ -268,7 +270,7 @@ void pdEndEffectors(ListBase **effectors)
}
}
-static void precalculate_effector(EffectorCache *eff)
+static void precalculate_effector(const struct EvaluationContext *eval_ctx, EffectorCache *eff)
{
unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra);
if (!eff->pd->rng)
@@ -280,7 +282,7 @@ static void precalculate_effector(EffectorCache *eff)
Curve *cu= eff->ob->data;
if (cu->flag & CU_PATH) {
if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL)
- BKE_displist_make_curveTypes(eff->scene, eff->ob, 0);
+ BKE_displist_make_curveTypes(eval_ctx, eff->scene, eff->ob, 0);
if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) {
where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL);
@@ -301,19 +303,19 @@ static void precalculate_effector(EffectorCache *eff)
if (eff->ob) {
float old_vel[3];
- BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra - 1.0f);
+ BKE_object_where_is_calc_time(eval_ctx, eff->scene, eff->ob, cfra - 1.0f);
copy_v3_v3(old_vel, eff->ob->obmat[3]);
- BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra);
+ BKE_object_where_is_calc_time(eval_ctx, eff->scene, eff->ob, cfra);
sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel);
}
}
-void pdPrecalculateEffectors(ListBase *effectors)
+void pdPrecalculateEffectors(const struct EvaluationContext *eval_ctx, ListBase *effectors)
{
if (effectors) {
EffectorCache *eff = effectors->first;
for (; eff; eff=eff->next)
- precalculate_effector(eff);
+ precalculate_effector(eval_ctx, eff);
}
}
@@ -612,6 +614,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
}
else {
ParticleSimulationData sim= {NULL};
+ sim.eval_ctx = eff->eval_ctx;
sim.scene= eff->scene;
sim.ob= eff->ob;
sim.psys= eff->psys;
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index 8e98a9f672d..12b9abc6d03 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -65,7 +65,7 @@
// file handling
//-------------------------------------------------------------------------------
-void initElbeemMesh(struct Scene *scene, struct Object *ob,
+void initElbeemMesh(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
int *numVertices, float **vertices,
int *numTriangles, int **triangles,
int useGlobalCoords, int modifierIndex)
@@ -78,7 +78,7 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
float *verts;
int *tris;
- dm = mesh_create_derived_index_render(scene, ob, CD_MASK_BAREMESH, modifierIndex);
+ dm = mesh_create_derived_index_render(eval_ctx, scene, ob, CD_MASK_BAREMESH, modifierIndex);
mvert = dm->getVertArray(dm);
mloop = dm->getLoopArray(dm);
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 6dc8cc5aff1..7c2eefe657c 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -45,34 +45,53 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-
-#include "BKE_depsgraph.h"
+#include "BKE_collection.h"
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_icons.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_object.h"
-#include "BKE_scene.h" /* BKE_scene_base_find */
-
-static void free_group_object(GroupObject *go)
-{
- MEM_freeN(go);
-}
+#include "BKE_scene.h"
/** Free (or release) any data used by this group (does not free the group itself). */
void BKE_group_free(Group *group)
{
- /* don't free group itself */
- GroupObject *go;
-
/* No animdata here. */
+ BKE_previewimg_free(&group->preview);
- while ((go = BLI_pophead(&group->gobject))) {
- free_group_object(go);
+ if (group->view_layer != NULL) {
+ BKE_view_layer_free(group->view_layer);
+ group->view_layer = NULL;
}
- BKE_previewimg_free(&group->preview);
+ if (group->collection != NULL) {
+ BKE_collection_master_free(&group->id, false);
+ MEM_freeN(group->collection);
+ group->collection = NULL;
+ }
+}
+
+/**
+ * Run when adding new groups or during doversion.
+ */
+void BKE_group_init(Group *group)
+{
+ group->collection = MEM_callocN(sizeof(SceneCollection), __func__);
+ BLI_strncpy(group->collection->name, "Master Collection", sizeof(group->collection->name));
+ group->view_layer = NULL; /* groups are not calloced. */
+ group->view_layer = BKE_view_layer_group_add(group);
+
+ /* Unlink the master collection. */
+ BKE_collection_unlink(group->view_layer, group->view_layer->layer_collections.first);
+
+ /* Create and link a new default collection. */
+ SceneCollection *defaut_collection = BKE_collection_add(&group->id,
+ NULL,
+ COLLECTION_TYPE_GROUP_INTERNAL,
+ "Default Collection");
+ BKE_collection_link(group->view_layer, defaut_collection);
}
Group *BKE_group_add(Main *bmain, const char *name)
@@ -85,7 +104,7 @@ Group *BKE_group_add(Main *bmain, const char *name)
group->layer = (1 << 20) - 1;
group->preview = NULL;
-
+ BKE_group_init(group);
return group;
}
@@ -99,7 +118,8 @@ Group *BKE_group_add(Main *bmain, const char *name)
*/
void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *group_src, const int flag)
{
- BLI_duplicatelist(&group_dst->gobject, &group_src->gobject);
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
/* Do not copy group's preview (same behavior as for objects). */
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
@@ -108,6 +128,18 @@ void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *gro
else {
group_dst->preview = NULL;
}
+
+ group_dst->collection = MEM_dupallocN(group_src->collection);
+ SceneCollection *master_collection_src = BKE_collection_master(&group_src->id);
+ SceneCollection *master_collection_dst = BKE_collection_master(&group_dst->id);
+
+ /* Recursively creates a new SceneCollection tree. */
+ BKE_collection_copy_data(master_collection_dst, master_collection_src,
+ flag_subdata);
+
+ BKE_view_layer_copy_data(group_dst->view_layer, group_src->view_layer,
+ master_collection_dst, master_collection_src,
+ flag_subdata);
}
Group *BKE_group_copy(Main *bmain, const Group *group)
@@ -125,38 +157,27 @@ void BKE_group_make_local(Main *bmain, Group *group, const bool lib_local)
/* external */
static bool group_object_add_internal(Group *group, Object *ob)
{
- GroupObject *go;
-
if (group == NULL || ob == NULL) {
return false;
}
-
- /* check if the object has been added already */
- if (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob))) {
+
+ /* For now always add to master collection of the group. */
+ SceneCollection *scene_collection = GROUP_MASTER_COLLECTION(group);
+
+ /* If the object has been added already it returns false. */
+ if (BKE_collection_object_add(&group->id, scene_collection, ob) == false) {
return false;
}
-
- go = MEM_callocN(sizeof(GroupObject), "groupobject");
- BLI_addtail(&group->gobject, go);
-
- go->ob = ob;
- id_us_ensure_real(&go->ob->id);
-
+
+ id_us_ensure_real(&ob->id);
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;
}
@@ -166,24 +187,17 @@ bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base
}
/* also used for (ob == NULL) */
-static int group_object_unlink_internal(Group *group, Object *ob)
+static bool group_object_unlink_internal(Group *group, Object *ob)
{
- GroupObject *go, *gon;
- int removed = 0;
- if (group == NULL) return 0;
-
- go = group->gobject.first;
- while (go) {
- gon = go->next;
- if (go->ob == ob) {
- BLI_remlink(&group->gobject, go);
- free_group_object(go);
- removed = 1;
- /* should break here since an object being in a group twice cant happen? */
- }
- go = gon;
+ if (group == NULL) {
+ return false;
+ }
+
+ if (BKE_collections_object_remove(NULL, &group->id, ob, false)) {
+ return true;
}
- return removed;
+
+ return false;
}
static bool group_object_cyclic_check_internal(Object *object, Group *group)
@@ -200,12 +214,13 @@ static bool group_object_cyclic_check_internal(Object *object, Group *group)
if (dup_group == group)
return true;
else {
- GroupObject *gob;
- for (gob = dup_group->gobject.first; gob; gob = gob->next) {
- if (group_object_cyclic_check_internal(gob->ob, group)) {
+ FOREACH_GROUP_OBJECT(dup_group, group_object)
+ {
+ if (group_object_cyclic_check_internal(group_object, dup_group)) {
return true;
}
}
+ FOREACH_GROUP_OBJECT_END
}
/* un-flag the object, it's allowed to have the same group multiple times in parallel */
@@ -223,18 +238,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;
}
@@ -249,7 +258,7 @@ bool BKE_group_object_exists(Group *group, Object *ob)
return false;
}
else {
- return (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob)) != NULL);
+ return (BLI_findptr(&group->view_layer->object_bases, ob, offsetof(Base, object)));
}
}
@@ -270,17 +279,13 @@ Group *BKE_group_object_find(Group *group, Object *ob)
bool BKE_group_is_animated(Group *group, Object *UNUSED(parent))
{
- GroupObject *go;
-
-#if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */
- if (parent->nlastrips.first)
- return 1;
-#endif
-
- for (go = group->gobject.first; go; go = go->next)
- if (go->ob && go->ob->proxy)
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ if (object->proxy) {
return true;
-
+ }
+ }
+ FOREACH_GROUP_OBJECT_END
return false;
}
@@ -330,10 +335,8 @@ static void group_replaces_nla(Object *parent, Object *target, char mode)
* you can draw everything, leaves tags in objects to signal it needs further updating */
/* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */
-void BKE_group_handle_recalc_and_update(EvaluationContext *eval_ctx, Scene *scene, Object *UNUSED(parent), Group *group)
+void BKE_group_handle_recalc_and_update(const struct EvaluationContext *eval_ctx, Scene *scene, Object *UNUSED(parent), Group *group)
{
- GroupObject *go;
-
#if 0 /* warning, isn't clearing the recalc flag on the object which causes it to run all the time,
* not just on frame change.
* This isn't working because the animation data is only re-evaluated on frame change so commenting for now
@@ -367,12 +370,12 @@ void BKE_group_handle_recalc_and_update(EvaluationContext *eval_ctx, Scene *scen
#endif
{
/* only do existing tags, as set by regular depsgraph */
- for (go = group->gobject.first; go; go = go->next) {
- if (go->ob) {
- if (go->ob->recalc) {
- BKE_object_handle_update(eval_ctx, scene, go->ob);
- }
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ if (object->id.tag & LIB_TAG_ID_RECALC_ALL) {
+ BKE_object_handle_update(eval_ctx, scene, object);
}
}
+ FOREACH_GROUP_OBJECT_END
}
}
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index a98a1b13402..a407fd0bae8 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -42,6 +42,7 @@
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "DNA_brush_types.h"
@@ -252,6 +253,7 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id)
ID_PRV_CASE(ID_OB, Object);
ID_PRV_CASE(ID_GR, Group);
ID_PRV_CASE(ID_SCE, Scene);
+ ID_PRV_CASE(ID_SCR, bScreen);
#undef ID_PRV_CASE
default:
break;
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index 70d037d85f3..487635f06ad 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -81,8 +81,9 @@ static IDType idtypes[] = {
{ ID_PA, "ParticleSettings", "particles", BLT_I18NCONTEXT_ID_PARTICLESETTINGS, IDTYPE_FLAGS_ISLINKABLE },
{ ID_PAL, "Palettes", "palettes", BLT_I18NCONTEXT_ID_PALETTE, IDTYPE_FLAGS_ISLINKABLE },
{ ID_PC, "PaintCurve", "paint_curves", BLT_I18NCONTEXT_ID_PAINTCURVE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_LP, "LightProbe", "light_probes", BLT_I18NCONTEXT_ID_LIGHTPROBE, IDTYPE_FLAGS_ISLINKABLE },
{ ID_SCE, "Scene", "scenes", BLT_I18NCONTEXT_ID_SCENE, IDTYPE_FLAGS_ISLINKABLE },
- { ID_SCR, "Screen", "screens", BLT_I18NCONTEXT_ID_SCREEN, 0 },
+ { ID_SCR, "Screen", "screens", BLT_I18NCONTEXT_ID_SCREEN, IDTYPE_FLAGS_ISLINKABLE },
{ ID_SEQ, "Sequence", "sequences", BLT_I18NCONTEXT_ID_SEQUENCE, 0 }, /* not actually ID data */
{ ID_SPK, "Speaker", "speakers", BLT_I18NCONTEXT_ID_SPEAKER, IDTYPE_FLAGS_ISLINKABLE },
{ ID_SO, "Sound", "sounds", BLT_I18NCONTEXT_ID_SOUND, IDTYPE_FLAGS_ISLINKABLE },
@@ -91,6 +92,7 @@ static IDType idtypes[] = {
{ ID_VF, "VFont", "fonts", BLT_I18NCONTEXT_ID_VFONT, IDTYPE_FLAGS_ISLINKABLE },
{ ID_WO, "World", "worlds", BLT_I18NCONTEXT_ID_WORLD, IDTYPE_FLAGS_ISLINKABLE },
{ ID_WM, "WindowManager", "window_managers", BLT_I18NCONTEXT_ID_WINDOWMANAGER, 0 },
+ { ID_WS, "WorkSpace", "workspaces", BLT_I18NCONTEXT_ID_WORKSPACE, IDTYPE_FLAGS_ISLINKABLE },
/** Keep last, not an ID exactly, only include for completeness */
{ ID_ID, "ID", "ids", BLT_I18NCONTEXT_ID_ID, 0 }, /* plural is fake */
@@ -203,6 +205,7 @@ int BKE_idcode_to_idfilter(const short idcode)
CASE_IDFILTER(PA);
CASE_IDFILTER(PAL);
CASE_IDFILTER(PC);
+ CASE_IDFILTER(LP);
CASE_IDFILTER(SCE);
CASE_IDFILTER(SPK);
CASE_IDFILTER(SO);
@@ -210,6 +213,7 @@ int BKE_idcode_to_idfilter(const short idcode)
CASE_IDFILTER(TXT);
CASE_IDFILTER(VF);
CASE_IDFILTER(WO);
+ CASE_IDFILTER(WS);
default:
return 0;
}
@@ -247,6 +251,7 @@ short BKE_idcode_from_idfilter(const int idfilter)
CASE_IDFILTER(PA);
CASE_IDFILTER(PAL);
CASE_IDFILTER(PC);
+ CASE_IDFILTER(LP);
CASE_IDFILTER(SCE);
CASE_IDFILTER(SPK);
CASE_IDFILTER(SO);
@@ -294,6 +299,7 @@ int BKE_idcode_to_index(const short idcode)
CASE_IDINDEX(PA);
CASE_IDINDEX(PAL);
CASE_IDINDEX(PC);
+ CASE_IDINDEX(LP);
CASE_IDINDEX(SCE);
CASE_IDINDEX(SCR);
CASE_IDINDEX(SPK);
@@ -303,6 +309,7 @@ int BKE_idcode_to_index(const short idcode)
CASE_IDINDEX(VF);
CASE_IDINDEX(WM);
CASE_IDINDEX(WO);
+ CASE_IDINDEX(WS);
}
BLI_assert(0);
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 45b41fa01ed..b00a62a1a87 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -476,6 +476,7 @@ static IDProperty *IDP_CopyGroup(const IDProperty *prop, const int flag)
BLI_assert(prop->type == IDP_GROUP);
newp = idp_generic_copy(prop, flag);
newp->len = prop->len;
+ newp->subtype = prop->subtype;
for (link = prop->data.group.first; link; link = link->next) {
BLI_addtail(&newp->data.group, IDP_CopyProperty_ex(link, flag));
@@ -602,8 +603,9 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop)
/**
* If a property is missing in \a dest, add it.
+ * Do it recursively.
*/
-void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite)
+void IDP_MergeGroup_ex(IDProperty *dest, const IDProperty *src, const bool do_overwrite, const int flag)
{
IDProperty *prop;
@@ -612,14 +614,30 @@ void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overw
if (do_overwrite) {
for (prop = src->data.group.first; prop; prop = prop->next) {
- IDProperty *copy = IDP_CopyProperty(prop);
+ if (prop->type == IDP_GROUP) {
+ IDProperty *prop_exist = IDP_GetPropertyFromGroup(dest, prop->name);
+
+ if (prop_exist != NULL) {
+ IDP_MergeGroup_ex(prop_exist, prop, do_overwrite, flag);
+ continue;
+ }
+ }
+
+ IDProperty *copy = IDP_CopyProperty_ex(prop, flag);
IDP_ReplaceInGroup(dest, copy);
}
}
else {
for (prop = src->data.group.first; prop; prop = prop->next) {
- if (IDP_GetPropertyFromGroup(dest, prop->name) == NULL) {
- IDProperty *copy = IDP_CopyProperty(prop);
+ IDProperty *prop_exist = IDP_GetPropertyFromGroup(dest, prop->name);
+ if (prop_exist != NULL) {
+ if (prop->type == IDP_GROUP) {
+ IDP_MergeGroup_ex(prop_exist, prop, do_overwrite, flag);
+ continue;
+ }
+ }
+ else {
+ IDProperty *copy = IDP_CopyProperty_ex(prop, flag);
dest->len++;
BLI_addtail(&dest->data.group, copy);
}
@@ -628,6 +646,15 @@ void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overw
}
/**
+ * If a property is missing in \a dest, add it.
+ * Do it recursively.
+ */
+void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite)
+{
+ IDP_MergeGroup_ex(dest, src, do_overwrite, 0);
+}
+
+/**
* This function has a sanity check to make sure ID properties with the same name don't
* get added to the group.
*
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 9ba7cc1c679..59fadffe22a 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -81,6 +81,7 @@
#include "BKE_scene.h"
#include "BKE_node.h"
#include "BKE_sequencer.h" /* seq_foreground_frame_get() */
+#include "BKE_workspace.h"
#include "BLF_api.h"
@@ -2609,19 +2610,19 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata,
}
}
+ for (Camera *cam = mainp->camera.first; cam; cam = cam->id.next) {
+ for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
+ callback(bgpic->ima, &bgpic->iuser, customdata);
+ }
+ }
+
/* image window, compo node users */
for (wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
for (win = wm->windows.first; win; win = win->next) {
- ScrArea *sa;
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
- BGpic *bgpic;
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- callback(bgpic->ima, &bgpic->iuser, customdata);
- }
- }
- else if (sa->spacetype == SPACE_IMAGE) {
+ const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
+
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype == SPACE_IMAGE) {
SpaceImage *sima = sa->spacedata.first;
callback(sima->image, &sima->iuser, customdata);
}
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index fe481905fb2..d8b9b14d755 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -69,6 +69,7 @@ void BKE_lamp_init(Lamp *la)
la->bufsize = 512;
la->clipsta = 0.5f;
la->clipend = 40.0f;
+ la->bleedexp = 2.5f;
la->samp = 3;
la->bias = 1.0f;
la->soft = 3.0f;
@@ -101,6 +102,14 @@ void BKE_lamp_init(Lamp *la)
la->sky_colorspace = BLI_XYZ_CIE;
la->sky_exposure = 1.0f;
la->shadow_frustum_size = 10.0f;
+ la->cascade_max_dist = 1000.0f;
+ la->cascade_count = 4;
+ la->cascade_exponent = 0.8f;
+ la->cascade_fade = 0.1f;
+ la->contact_dist = 1.0f;
+ la->contact_bias = 0.03f;
+ la->contact_spread = 0.2f;
+ la->contact_thickness = 0.5f;
curvemapping_initialize(la->curfalloff);
}
@@ -215,41 +224,3 @@ void BKE_lamp_free(Lamp *la)
BKE_icon_id_delete(&la->id);
la->id.icon_id = 0;
}
-
-/* Calculate all drivers for lamps, see material_drivers_update for why this is a bad hack */
-
-static void lamp_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime)
-{
- bNode *node;
-
- /* nodetree itself */
- if (ntree->adt && ntree->adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS);
-
- /* nodes */
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->id && node->type == NODE_GROUP)
- lamp_node_drivers_update(scene, (bNodeTree *)node->id, ctime);
-}
-
-void lamp_drivers_update(Scene *scene, Lamp *la, float ctime)
-{
- /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited already
- * (see BKE_scene_update_tagged()). This assumes la->id.tag & LIB_TAG_DOIT isn't set by anything else
- * in the meantime... [#32017] */
- if (la->id.tag & LIB_TAG_DOIT)
- return;
-
- la->id.tag |= LIB_TAG_DOIT;
-
- /* lamp itself */
- if (la->adt && la->adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, &la->id, la->adt, ctime, ADT_RECALC_DRIVERS);
-
- /* nodes */
- if (la->nodetree)
- lamp_node_drivers_update(scene, la->nodetree, ctime);
-
- la->id.tag &= ~LIB_TAG_DOIT;
-}
-
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index ea4c3f380ff..d92d0d9edbf 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -53,7 +53,6 @@
#include "BKE_anim.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_global.h"
#include "BKE_key.h"
@@ -67,11 +66,6 @@
#include "BKE_deform.h"
-/* Workaround for cyclic dependency with curves.
- * In such case curve_cache might not be ready yet,
- */
-#define CYCLIC_DEPENDENCY_WORKAROUND
-
int BKE_lattice_index_from_uvw(Lattice *lt,
const int u, const int v, const int w)
{
@@ -314,6 +308,8 @@ void BKE_lattice_free(Lattice *lt)
{
BKE_animdata_free(&lt->id, false);
+ BKE_lattice_batch_cache_free(lt);
+
MEM_SAFE_FREE(lt->def);
if (lt->dvert) {
BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
@@ -602,7 +598,7 @@ static bool where_on_path_deform(Object *ob, float ctime, float vec[4], float di
/* co: local coord, result local too */
/* returns quaternion for rotation, using cd->no_rot_axis */
/* axis is using another define!!! */
-static bool calc_curve_deform(Scene *scene, Object *par, float co[3],
+static bool calc_curve_deform(Object *par, float co[3],
const short axis, CurveDeform *cd, float r_quat[4])
{
Curve *cu = par->data;
@@ -610,12 +606,10 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3],
short index;
const bool is_neg_axis = (axis > 2);
- /* to be sure, mostly after file load, also cyclic dependencies */
-#ifdef CYCLIC_DEPENDENCY_WORKAROUND
if (par->curve_cache == NULL) {
- BKE_displist_make_curveTypes(scene, par, false);
+ /* Happens with a cyclic dependencies. */
+ return false;
}
-#endif
if (par->curve_cache->path == NULL) {
return false; /* happens on append, cyclic dependencies and empty curves */
@@ -706,7 +700,7 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3],
}
void curve_deform_verts(
- Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3],
+ Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3],
int numVerts, const char *vgroup, short defaxis)
{
Curve *cu;
@@ -765,7 +759,7 @@ void curve_deform_verts(
if (weight > 0.0f) {
mul_m4_v3(cd.curvespace, vertexCos[a]);
copy_v3_v3(vec, vertexCos[a]);
- calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
+ calc_curve_deform(cuOb, vec, defaxis, &cd, NULL);
interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
mul_m4_v3(cd.objectspace, vertexCos[a]);
}
@@ -788,7 +782,7 @@ void curve_deform_verts(
if (weight > 0.0f) {
/* already in 'cd.curvespace', prev for loop */
copy_v3_v3(vec, vertexCos[a]);
- calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
+ calc_curve_deform(cuOb, vec, defaxis, &cd, NULL);
interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
mul_m4_v3(cd.objectspace, vertexCos[a]);
}
@@ -799,7 +793,7 @@ void curve_deform_verts(
if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
for (a = 0; a < numVerts; a++) {
mul_m4_v3(cd.curvespace, vertexCos[a]);
- calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
+ calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL);
mul_m4_v3(cd.objectspace, vertexCos[a]);
}
}
@@ -814,7 +808,7 @@ void curve_deform_verts(
for (a = 0; a < numVerts; a++) {
/* already in 'cd.curvespace', prev for loop */
- calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
+ calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL);
mul_m4_v3(cd.objectspace, vertexCos[a]);
}
}
@@ -824,7 +818,7 @@ void curve_deform_verts(
/* input vec and orco = local coord in armature space */
/* orco is original not-animated or deformed reference point */
/* result written in vec and mat */
-void curve_deform_vector(Scene *scene, Object *cuOb, Object *target,
+void curve_deform_vector(Object *cuOb, Object *target,
float orco[3], float vec[3], float mat[3][3], int no_rot_axis)
{
CurveDeform cd;
@@ -843,7 +837,7 @@ void curve_deform_vector(Scene *scene, Object *cuOb, Object *target,
mul_m4_v3(cd.curvespace, vec);
- if (calc_curve_deform(scene, cuOb, vec, target->trackflag, &cd, quat)) {
+ if (calc_curve_deform(cuOb, vec, target->trackflag, &cd, quat)) {
float qmat[3][3];
quat_to_mat3(qmat, quat);
@@ -1033,7 +1027,7 @@ void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3])
}
}
-void BKE_lattice_modifiers_calc(Scene *scene, Object *ob)
+void BKE_lattice_modifiers_calc(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
Lattice *lt = ob->data;
VirtualModifierData virtualModifierData;
@@ -1060,7 +1054,7 @@ void BKE_lattice_modifiers_calc(Scene *scene, Object *ob)
if (mti->type != eModifierTypeType_OnlyDeform) continue;
if (!vertexCos) vertexCos = BKE_lattice_vertexcos_get(ob, &numVerts);
- mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0);
+ mti->deformVerts(md, eval_ctx, ob, NULL, vertexCos, numVerts, 0);
}
/* always displist to make this work like derivedmesh */
@@ -1234,8 +1228,24 @@ void BKE_lattice_translate(Lattice *lt, float offset[3], bool do_keys)
/* **** Depsgraph evaluation **** */
-void BKE_lattice_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+void BKE_lattice_eval_geometry(const struct EvaluationContext *UNUSED(eval_ctx),
Lattice *UNUSED(latt))
{
}
+/* Draw Engine */
+void (*BKE_lattice_batch_cache_dirty_cb)(Lattice *lt, int mode) = NULL;
+void (*BKE_lattice_batch_cache_free_cb)(Lattice *lt) = NULL;
+
+void BKE_lattice_batch_cache_dirty(Lattice *lt, int mode)
+{
+ if (lt->batch_cache) {
+ BKE_lattice_batch_cache_dirty_cb(lt, mode);
+ }
+}
+void BKE_lattice_batch_cache_free(Lattice *lt)
+{
+ if (lt->batch_cache) {
+ BKE_lattice_batch_cache_free_cb(lt);
+ }
+}
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
new file mode 100644
index 00000000000..84eb4ee2e33
--- /dev/null
+++ b/source/blender/blenkernel/intern/layer.c
@@ -0,0 +1,2189 @@
+/*
+ * ***** 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 <string.h>
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_string_utils.h"
+#include "BLT_translation.h"
+
+#include "BKE_collection.h"
+#include "BKE_freestyle.h"
+#include "BKE_global.h"
+#include "BKE_group.h"
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+#include "BKE_workspace.h"
+
+#include "DNA_group_types.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 "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
+
+#include "DRW_engine.h"
+
+#include "MEM_guardedalloc.h"
+
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+
+/* prototype */
+struct EngineSettingsCB_Type;
+static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc);
+static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects);
+static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc);
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc);
+static IDProperty *collection_engine_settings_create(struct EngineSettingsCB_Type *ces_type, const bool populate);
+static IDProperty *collection_engine_get(IDProperty *root, const int type, const char *engine_name);
+static void collection_engine_settings_init(IDProperty *root, const bool populate);
+static void layer_engine_settings_init(IDProperty *root, const bool populate);
+static void object_bases_iterator_next(BLI_Iterator *iter, const int flag);
+
+/* RenderLayer */
+
+/**
+ * Returns the ViewLayer to be used for rendering
+ * Most of the time BKE_view_layer_from_workspace_get should be used instead
+ */
+ViewLayer *BKE_view_layer_from_scene_get(const Scene *scene)
+{
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ BLI_assert(view_layer);
+ return view_layer;
+}
+
+/**
+ * Returns the ViewLayer to be used for drawing, outliner, and other context related areas.
+ */
+ViewLayer *BKE_view_layer_from_workspace_get(const struct Scene *scene, const struct WorkSpace *workspace)
+{
+ if (BKE_workspace_use_scene_settings_get(workspace)) {
+ return BKE_view_layer_from_scene_get(scene);
+ }
+ else {
+ return BKE_workspace_view_layer_get(workspace, scene);
+ }
+}
+
+/**
+ * This is a placeholder to know which areas of the code need to be addressed for the Workspace changes.
+ * Never use this, you should either use BKE_view_layer_workspace_active or get ViewLayer explicitly.
+ */
+ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const Scene *scene)
+{
+ return BKE_view_layer_from_scene_get(scene);
+}
+
+static ViewLayer *view_layer_add(const char *name, SceneCollection *master_scene_collection)
+{
+ if (!name) {
+ name = DATA_("View Layer");
+ }
+
+ IDPropertyTemplate val = {0};
+ ViewLayer *view_layer = MEM_callocN(sizeof(ViewLayer), "View Layer");
+ view_layer->flag = VIEW_LAYER_RENDER | VIEW_LAYER_FREESTYLE;
+
+ view_layer->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ layer_engine_settings_init(view_layer->properties, false);
+ BLI_strncpy_utf8(view_layer->name, name, sizeof(view_layer->name));
+
+ /* Link the master collection by default. */
+ layer_collection_add(view_layer, NULL, master_scene_collection);
+
+ /* Pure rendering pipeline settings. */
+ view_layer->layflag = 0x7FFF; /* solid ztra halo edge strand */
+ view_layer->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
+ view_layer->pass_alpha_threshold = 0.5f;
+ BKE_freestyle_config_init(&view_layer->freestyle_config);
+
+ return view_layer;
+}
+
+/**
+ * Add a new view layer
+ * by default, a view layer has the master collection
+ */
+ViewLayer *BKE_view_layer_add(Scene *scene, const char *name)
+{
+ SceneCollection *sc = BKE_collection_master(&scene->id);
+ ViewLayer *view_layer = view_layer_add(name, sc);
+
+ BLI_addtail(&scene->view_layers, view_layer);
+
+ /* unique name */
+ BLI_uniquename(
+ &scene->view_layers, view_layer, DATA_("ViewLayer"), '.',
+ offsetof(ViewLayer, name), sizeof(view_layer->name));
+
+ return view_layer;
+}
+
+/**
+ * Add a ViewLayer for a Group
+ * It should be added only once
+ */
+ViewLayer *BKE_view_layer_group_add(Group *group)
+{
+ BLI_assert(group->view_layer == NULL);
+ SceneCollection *sc = BKE_collection_master(&group->id);
+ ViewLayer *view_layer = view_layer_add(group->id.name + 2, sc);
+ return view_layer;
+}
+
+/**
+ * Free (or release) any data used by this ViewLayer.
+ */
+void BKE_view_layer_free(ViewLayer *view_layer)
+{
+ view_layer->basact = NULL;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->collection_properties) {
+ IDP_FreeProperty(base->collection_properties);
+ MEM_freeN(base->collection_properties);
+ }
+ }
+ BLI_freelistN(&view_layer->object_bases);
+
+ for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ layer_collection_free(NULL, lc);
+ }
+ BLI_freelistN(&view_layer->layer_collections);
+
+ if (view_layer->properties) {
+ IDP_FreeProperty(view_layer->properties);
+ MEM_freeN(view_layer->properties);
+ }
+
+ if (view_layer->properties_evaluated) {
+ IDP_FreeProperty(view_layer->properties_evaluated);
+ MEM_freeN(view_layer->properties_evaluated);
+ }
+
+ for (ViewLayerEngineData *sled = view_layer->drawdata.first; sled; sled = sled->next) {
+ if (sled->storage) {
+ if (sled->free) {
+ sled->free(sled->storage);
+ }
+ MEM_freeN(sled->storage);
+ }
+ }
+ BLI_freelistN(&view_layer->drawdata);
+
+ MEM_SAFE_FREE(view_layer->stats);
+
+ BKE_freestyle_config_free(&view_layer->freestyle_config);
+
+ if (view_layer->id_properties) {
+ IDP_FreeProperty(view_layer->id_properties);
+ MEM_freeN(view_layer->id_properties);
+ }
+
+ MEM_freeN(view_layer);
+}
+
+/**
+ * Tag all the selected objects of a renderlayer
+ */
+void BKE_view_layer_selected_objects_tag(ViewLayer *view_layer, const int tag)
+{
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTED) != 0) {
+ base->object->flag |= tag;
+ }
+ else {
+ base->object->flag &= ~tag;
+ }
+ }
+}
+
+/**
+ * Return the first ViewLayer for a given id
+ */
+ViewLayer *BKE_view_layer_first_from_id(const ID *owner_id)
+{
+ switch (GS(owner_id->name)) {
+ case ID_SCE:
+ return ((Scene *)owner_id)->view_layers.first;
+ case ID_GR:
+ return ((Group *)owner_id)->view_layer;
+ default:
+ BLI_assert(!"ID doesn't support view layers");
+ return NULL;
+ }
+}
+
+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;
+}
+
+/**
+ * Fallback for when a Scene has no camera to use
+ *
+ * \param view_layer: in general you want to use the same ViewLayer that is used
+ * for depsgraph. If rendering you pass the scene active layer, when viewing in the viewport
+ * you want to get ViewLayer from context.
+ */
+Object *BKE_view_layer_camera_find(ViewLayer *view_layer)
+{
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object->type == OB_CAMERA) {
+ return base->object;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Find the ViewLayer a LayerCollection belongs to
+ */
+ViewLayer *BKE_view_layer_find_from_collection(const ID *owner_id, LayerCollection *lc)
+{
+ switch (GS(owner_id->name)) {
+ case ID_GR:
+ return ((Group *)owner_id)->view_layer;
+ case ID_SCE:
+ {
+ Scene *scene = (Scene *)owner_id;
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ if (find_scene_collection_in_scene_collections(&view_layer->layer_collections, lc)) {
+ return view_layer;
+ }
+ }
+ return NULL;
+ }
+ default:
+ BLI_assert(!"ID doesn't support scene layers");
+ return NULL;
+ }
+}
+
+/* Base */
+
+Base *BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
+{
+ return BLI_findptr(&view_layer->object_bases, ob, offsetof(Base, object));
+}
+
+void BKE_view_layer_base_deselect_all(ViewLayer *view_layer)
+{
+ Base *base;
+
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ base->flag &= ~BASE_SELECTED;
+ }
+}
+
+void BKE_view_layer_base_select(struct ViewLayer *view_layer, Base *selbase)
+{
+ view_layer->basact = selbase;
+ if ((selbase->flag & BASE_SELECTABLED) != 0) {
+ selbase->flag |= BASE_SELECTED;
+ }
+}
+
+/****************************************************************************/
+/* Copying functions for datablocks that use ViewLayer/SceneCollection */
+
+/* Find the equivalent SceneCollection in the new tree */
+static SceneCollection *scene_collection_from_new_tree(
+ SceneCollection *sc_reference, SceneCollection *sc_dst, SceneCollection *sc_src)
+{
+ if (sc_src == sc_reference) {
+ return sc_dst;
+ }
+
+ for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first;
+ nsc_src;
+ nsc_src = nsc_src->next, nsc_dst = nsc_dst->next)
+ {
+ SceneCollection *found = scene_collection_from_new_tree(sc_reference, nsc_dst, nsc_src);
+ if (found != NULL) {
+ return found;
+ }
+ }
+ return NULL;
+}
+
+static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src)
+{
+ LayerCollection *layer_collection_dst = (LayerCollection *)layer_collections_dst->first;
+ const LayerCollection *layer_collection_src = (const LayerCollection *)layer_collections_src->first;
+ while (layer_collection_dst != NULL) {
+ layer_collection_dst->flag = layer_collection_src->flag;
+
+ if (layer_collection_dst->properties != NULL) {
+ IDP_FreeProperty(layer_collection_dst->properties);
+ MEM_SAFE_FREE(layer_collection_dst->properties);
+ }
+
+ if (layer_collection_src->properties != NULL) {
+ layer_collection_dst->properties = IDP_CopyProperty(layer_collection_src->properties);
+ }
+
+ layer_collections_sync_flags(&layer_collection_dst->layer_collections,
+ &layer_collection_src->layer_collections);
+
+ layer_collection_dst = layer_collection_dst->next;
+ layer_collection_src = layer_collection_src->next;
+ }
+}
+
+/* recreate the LayerCollection tree */
+static void layer_collections_recreate(
+ ViewLayer *view_layer_dst, ListBase *lb_src, SceneCollection *mc_dst, SceneCollection *mc_src)
+{
+ for (LayerCollection *lc_src = lb_src->first; lc_src; lc_src = lc_src->next) {
+ SceneCollection *sc_dst = scene_collection_from_new_tree(lc_src->scene_collection, mc_dst, mc_src);
+ BLI_assert(sc_dst);
+
+ /* instead of synchronizing both trees we simply re-create it */
+ BKE_collection_link(view_layer_dst, sc_dst);
+ }
+}
+
+/**
+ * Only copy internal data of ViewLayer from source to already allocated/initialized destination.
+ *
+ * \param mc_src Master Collection the source ViewLayer links in.
+ * \param mc_dst Master Collection the destination ViewLayer links in.
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_view_layer_copy_data(
+ ViewLayer *view_layer_dst, ViewLayer *view_layer_src, SceneCollection *mc_dst, SceneCollection *mc_src,
+ const int flag)
+{
+ IDPropertyTemplate val = {0};
+
+ if (view_layer_dst->id_properties != NULL) {
+ view_layer_dst->id_properties = IDP_CopyProperty_ex(view_layer_dst->id_properties, flag);
+ }
+ BKE_freestyle_config_copy(&view_layer_dst->freestyle_config, &view_layer_src->freestyle_config, flag);
+
+ view_layer_dst->stats = NULL;
+ view_layer_dst->properties_evaluated = NULL;
+ view_layer_dst->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ IDP_MergeGroup_ex(view_layer_dst->properties, view_layer_src->properties, true, flag);
+
+ /* 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(&view_layer_dst->layer_collections);
+ BLI_listbase_clear(&view_layer_dst->object_bases);
+ BLI_listbase_clear(&view_layer_dst->drawdata);
+
+ layer_collections_recreate(view_layer_dst, &view_layer_src->layer_collections, mc_dst, mc_src);
+
+ /* Now we handle the syncing for visibility, selectability, ... */
+ layer_collections_sync_flags(&view_layer_dst->layer_collections, &view_layer_src->layer_collections);
+
+ Object *active_ob = OBACT(view_layer_src);
+ for (Base *base_src = view_layer_src->object_bases.first, *base_dst = view_layer_dst->object_bases.first;
+ base_src;
+ base_src = base_src->next, base_dst = base_dst->next)
+ {
+ base_dst->flag = base_src->flag;
+ base_dst->flag_legacy = base_src->flag_legacy;
+
+ if (base_dst->object == active_ob) {
+ view_layer_dst->basact = base_dst;
+ }
+ }
+}
+
+static void view_layer_object_base_unref(ViewLayer *view_layer, Base *base)
+{
+ base->refcount--;
+
+ /* It only exists in the RenderLayer */
+ if (base->refcount == 0) {
+ if (view_layer->basact == base) {
+ view_layer->basact = NULL;
+ }
+
+ if (base->collection_properties) {
+ IDP_FreeProperty(base->collection_properties);
+ MEM_freeN(base->collection_properties);
+ }
+
+ BLI_remlink(&view_layer->object_bases, base);
+ MEM_freeN(base);
+ }
+}
+
+/**
+ * Return the base if existent, or create it if necessary
+ * Always bump the refcount
+ */
+static Base *object_base_add(ViewLayer *view_layer, Object *ob)
+{
+ Base *base;
+ base = BKE_view_layer_base_find(view_layer, 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(&view_layer->object_bases, base);
+
+ IDPropertyTemplate val = {0};
+ base->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ }
+
+ base->refcount++;
+ return base;
+}
+
+/* LayerCollection */
+
+static void layer_collection_objects_unpopulate(ViewLayer *view_layer, LayerCollection *lc)
+{
+ if (view_layer) {
+ for (LinkData *link = lc->object_bases.first; link; link = link->next) {
+ view_layer_object_base_unref(view_layer, link->data);
+ }
+ }
+
+ BLI_freelistN(&lc->object_bases);
+}
+
+/**
+ * When freeing the entire ViewLayer at once we don't bother with unref
+ * otherwise ViewLayer is passed to keep the syncing of the LayerCollection tree
+ */
+static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc)
+{
+ layer_collection_objects_unpopulate(view_layer, lc);
+ BLI_freelistN(&lc->overrides);
+
+ if (lc->properties) {
+ IDP_FreeProperty(lc->properties);
+ MEM_freeN(lc->properties);
+ }
+
+ if (lc->properties_evaluated) {
+ IDP_FreeProperty(lc->properties_evaluated);
+ MEM_freeN(lc->properties_evaluated);
+ }
+
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ layer_collection_free(view_layer, nlc);
+ }
+
+ BLI_freelistN(&lc->layer_collections);
+}
+
+/**
+ * Free (or release) LayerCollection from ViewLayer
+ * (does not free the LayerCollection itself).
+ */
+void BKE_layer_collection_free(ViewLayer *view_layer, LayerCollection *lc)
+{
+ layer_collection_free(view_layer, 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 collection for a given index
+ */
+LayerCollection *BKE_layer_collection_from_index(ViewLayer *view_layer, const int index)
+{
+ int i = 0;
+ return collection_from_index(&view_layer->layer_collections, index, &i);
+}
+
+/**
+ * Get the active collection
+ */
+LayerCollection *BKE_layer_collection_get_active(ViewLayer *view_layer)
+{
+ int i = 0;
+ return collection_from_index(&view_layer->layer_collections, view_layer->active_collection, &i);
+}
+
+
+/**
+ * Return layer collection to add new object(s).
+ * Create one if none exists.
+ */
+LayerCollection *BKE_layer_collection_get_active_ensure(Scene *scene, ViewLayer *view_layer)
+{
+ LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
+
+ if (lc == NULL) {
+ BLI_assert(BLI_listbase_is_empty(&view_layer->layer_collections));
+ /* When there is no collection linked to this ViewLayer, create one. */
+ SceneCollection *sc = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL);
+ lc = BKE_collection_link(view_layer, sc);
+ /* New collection has to be the active one. */
+ BLI_assert(lc == BKE_layer_collection_get_active(view_layer));
+ }
+
+ return lc;
+}
+
+/**
+ * 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(ViewLayer *view_layer)
+{
+ return collection_count(&view_layer->layer_collections);
+}
+
+/**
+ * Recursively get the index for a given collection
+ */
+static int index_from_collection(ListBase *lb, const 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(ViewLayer *view_layer, const LayerCollection *lc)
+{
+ int i = 0;
+ return index_from_collection(&view_layer->layer_collections, lc, &i);
+}
+
+/**
+ * Lookup the listbase that contains \a lc.
+ */
+static ListBase *layer_collection_listbase_find(ListBase *lb, LayerCollection *lc)
+{
+ for (LayerCollection *lc_iter = lb->first; lc_iter; lc_iter = lc_iter->next) {
+ if (lc_iter == lc) {
+ return lb;
+ }
+
+ ListBase *lb_child_result;
+ if ((lb_child_result = layer_collection_listbase_find(&lc_iter->layer_collections, lc))) {
+ return lb_child_result;
+ }
+ }
+
+ return NULL;
+}
+
+#if 0
+/**
+ * Lookup the listbase that contains \a sc.
+ */
+static ListBase *scene_collection_listbase_find(ListBase *lb, SceneCollection *sc)
+{
+ for (SceneCollection *sc_iter = lb->first; sc_iter; sc_iter = sc_iter->next) {
+ if (sc_iter == sc) {
+ return lb;
+ }
+
+ ListBase *lb_child_result;
+ if ((lb_child_result = scene_collection_listbase_find(&sc_iter->scene_collections, sc))) {
+ return lb_child_result;
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+/* ---------------------------------------------------------------------- */
+/* Outliner drag and drop */
+
+/**
+ * Nest a LayerCollection into another one
+ * Both collections must be from the same ViewLayer, return true if succeded.
+ *
+ * The LayerCollection will effectively be moved into the
+ * new (nested) position. So all the settings, overrides, ... go with it, and
+ * if the collection was directly linked to the ViewLayer it's then unlinked.
+ *
+ * For the other ViewLayers we simply resync the tree, without changing directly
+ * linked collections (even if they link to the same SceneCollection)
+ *
+ * \param lc_src LayerCollection to nest into \a lc_dst
+ * \param lc_dst LayerCollection to have \a lc_src inserted into
+ */
+
+static void layer_collection_swap(
+ ViewLayer *view_layer, ListBase *lb_a, ListBase *lb_b,
+ LayerCollection *lc_a, LayerCollection *lc_b)
+{
+ if (lb_a == NULL) {
+ lb_a = layer_collection_listbase_find(&view_layer->layer_collections, lc_a);
+ }
+
+ if (lb_b == NULL) {
+ lb_b = layer_collection_listbase_find(&view_layer->layer_collections, lc_b);
+ }
+
+ BLI_assert(lb_a);
+ BLI_assert(lb_b);
+
+ BLI_listbases_swaplinks(lb_a, lb_b, lc_a, lc_b);
+}
+
+/**
+ * Move \a lc_src into \a lc_dst. Both have to be stored in \a view_layer.
+ * If \a lc_src is directly linked to the ViewLayer it's unlinked
+ */
+bool BKE_layer_collection_move_into(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src)
+{
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src);
+ bool is_directly_linked = false;
+
+ if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) {
+ return false;
+ }
+
+ /* We can't nest the collection into itself */
+ if (lc_src->scene_collection == lc_dst->scene_collection) {
+ return false;
+ }
+
+ /* Collection is already where we wanted it to be */
+ if (lc_dst->layer_collections.last == lc_src) {
+ return false;
+ }
+
+ /* Collection is already where we want it to be in the scene tree
+ * but we want to swap it in the layer tree still */
+ if (lc_dst->scene_collection->scene_collections.last == lc_src->scene_collection) {
+ LayerCollection *lc_swap = lc_dst->layer_collections.last;
+ layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_dst->layer_collections.last, lc_src);
+
+ if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) {
+ BKE_collection_unlink(view_layer, lc_swap);
+ }
+ return true;
+ }
+ else {
+ LayerCollection *lc_temp;
+ is_directly_linked = BLI_findindex(&view_layer->layer_collections, lc_src) != -1;
+
+ if (!is_directly_linked) {
+ /* lc_src will be invalid after BKE_collection_move_into!
+ * so we swap it with lc_temp to preserve its settings */
+ lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection);
+ layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src);
+ }
+
+ if (!BKE_collection_move_into(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) {
+ if (!is_directly_linked) {
+ /* Swap back and remove */
+ layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src);
+ BKE_collection_unlink(view_layer, lc_temp);
+ }
+ return false;
+ }
+ }
+
+ LayerCollection *lc_new = BLI_findptr(
+ &lc_dst->layer_collections, lc_src->scene_collection, offsetof(LayerCollection, scene_collection));
+ BLI_assert(lc_new);
+ layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_new, lc_src);
+
+ /* If it's directly linked, unlink it after the swap */
+ if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) {
+ BKE_collection_unlink(view_layer, lc_new);
+ }
+
+ return true;
+}
+
+/**
+ * Move \a lc_src above \a lc_dst. Both have to be stored in \a view_layer.
+ * If \a lc_src is directly linked to the ViewLayer it's unlinked
+ */
+bool BKE_layer_collection_move_above(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src)
+{
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src);
+ const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1;
+ const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1;
+
+ if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) {
+ return false;
+ }
+
+ /* Collection is already where we wanted it to be */
+ if (lc_dst->prev == lc_src) {
+ return false;
+ }
+
+ /* Collection is already where we want it to be in the scene tree
+ * but we want to swap it in the layer tree still */
+ if (lc_dst->prev && lc_dst->prev->scene_collection == lc_src->scene_collection) {
+ LayerCollection *lc_swap = lc_dst->prev;
+ layer_collection_swap(view_layer, NULL, NULL, lc_dst->prev, lc_src);
+
+ if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) {
+ BKE_collection_unlink(view_layer, lc_swap);
+ }
+ return true;
+ }
+ /* We don't allow to move above/below a directly linked collection
+ * unless the source collection is also directly linked */
+ else if (is_directly_linked_dst) {
+ /* Both directly linked to the ViewLayer, just need to swap */
+ if (is_directly_linked_src) {
+ BLI_remlink(&view_layer->layer_collections, lc_src);
+ BLI_insertlinkbefore(&view_layer->layer_collections, lc_dst, lc_src);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ LayerCollection *lc_temp;
+
+ if (!is_directly_linked_src) {
+ /* lc_src will be invalid after BKE_collection_move_into!
+ * so we swap it with lc_temp to preserve its settings */
+ lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection);
+ layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src);
+ }
+
+ if (!BKE_collection_move_above(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) {
+ if (!is_directly_linked_src) {
+ /* Swap back and remove */
+ layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src);
+ BKE_collection_unlink(view_layer, lc_temp);
+ }
+ return false;
+ }
+ }
+
+ LayerCollection *lc_new = lc_dst->prev;
+ BLI_assert(lc_new);
+ layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src);
+
+ /* If it's directly linked, unlink it after the swap */
+ if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) {
+ BKE_collection_unlink(view_layer, lc_new);
+ }
+
+ return true;
+}
+
+/**
+ * Move \a lc_src below \a lc_dst. Both have to be stored in \a view_layer.
+ * If \a lc_src is directly linked to the ViewLayer it's unlinked
+ */
+bool BKE_layer_collection_move_below(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src)
+{
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src);
+ const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1;
+ const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1;
+
+ if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) {
+ return false;
+ }
+
+ /* Collection is already where we wanted it to be */
+ if (lc_dst->next == lc_src) {
+ return false;
+ }
+
+ /* Collection is already where we want it to be in the scene tree
+ * but we want to swap it in the layer tree still */
+ if (lc_dst->next && lc_dst->next->scene_collection == lc_src->scene_collection) {
+ LayerCollection *lc_swap = lc_dst->next;
+ layer_collection_swap(view_layer, NULL, NULL, lc_dst->next, lc_src);
+
+ if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) {
+ BKE_collection_unlink(view_layer, lc_swap);
+ }
+ return true;
+ }
+ /* We don't allow to move above/below a directly linked collection
+ * unless the source collection is also directly linked */
+ else if (is_directly_linked_dst) {
+ /* Both directly linked to the ViewLayer, just need to swap */
+ if (is_directly_linked_src) {
+ BLI_remlink(&view_layer->layer_collections, lc_src);
+ BLI_insertlinkafter(&view_layer->layer_collections, lc_dst, lc_src);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ LayerCollection *lc_temp;
+
+ if (!is_directly_linked_src) {
+ /* lc_src will be invalid after BKE_collection_move_into!
+ * so we swap it with lc_temp to preserve its settings */
+ lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection);
+ layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src);
+ }
+
+ if (!BKE_collection_move_below(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) {
+ if (!is_directly_linked_src) {
+ /* Swap back and remove */
+ layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src);
+ BKE_collection_unlink(view_layer, lc_temp);
+ }
+ return false;
+ }
+ }
+
+ LayerCollection *lc_new = lc_dst->next;
+ BLI_assert(lc_new);
+ layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src);
+
+ /* If it's directly linked, unlink it after the swap */
+ if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) {
+ BKE_collection_unlink(view_layer, lc_new);
+ }
+
+ return true;
+}
+
+static bool layer_collection_resync(ViewLayer *view_layer, LayerCollection *lc, const SceneCollection *sc)
+{
+ if (lc->scene_collection == sc) {
+ ListBase collections = {NULL};
+ BLI_movelisttolist(&collections, &lc->layer_collections);
+
+ for (SceneCollection *sc_nested = sc->scene_collections.first; sc_nested; sc_nested = sc_nested->next) {
+ LayerCollection *lc_nested = BLI_findptr(&collections, sc_nested, offsetof(LayerCollection, scene_collection));
+ if (lc_nested) {
+ BLI_remlink(&collections, lc_nested);
+ BLI_addtail(&lc->layer_collections, lc_nested);
+ }
+ else {
+ layer_collection_add(view_layer, lc, sc_nested);
+ }
+ }
+
+ for (LayerCollection *lc_nested = collections.first; lc_nested; lc_nested = lc_nested->next) {
+ layer_collection_free(view_layer, lc_nested);
+ }
+ BLI_freelistN(&collections);
+
+ BLI_assert(BLI_listbase_count(&lc->layer_collections) ==
+ BLI_listbase_count(&sc->scene_collections));
+
+ return true;
+ }
+
+ for (LayerCollection *lc_nested = lc->layer_collections.first; lc_nested; lc_nested = lc_nested->next) {
+ if (layer_collection_resync(view_layer, lc_nested, sc)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Update the scene layers so that any LayerCollection that points
+ * to \a sc is re-synced again
+ */
+void BKE_layer_collection_resync(const ID *owner_id, const SceneCollection *sc)
+{
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ layer_collection_resync(view_layer, lc, sc);
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+/**
+ * Link a collection to a renderlayer
+ * The collection needs to be created separately
+ */
+LayerCollection *BKE_collection_link(ViewLayer *view_layer, SceneCollection *sc)
+{
+ LayerCollection *lc = layer_collection_add(view_layer, NULL, sc);
+ view_layer->active_collection = BKE_layer_collection_findindex(view_layer, lc);
+ return lc;
+}
+
+/**
+ * Unlink a collection base from a renderlayer
+ * The corresponding collection is not removed from the master collection
+ */
+void BKE_collection_unlink(ViewLayer *view_layer, LayerCollection *lc)
+{
+ BKE_layer_collection_free(view_layer, lc);
+ BLI_remlink(&view_layer->layer_collections, lc);
+ MEM_freeN(lc);
+ view_layer->active_collection = 0;
+}
+
+/**
+ * Recursively enable nested collections
+ */
+static void layer_collection_enable(ViewLayer *view_layer, LayerCollection *lc)
+{
+ layer_collection_objects_populate(view_layer, lc, &lc->scene_collection->objects);
+
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ layer_collection_enable(view_layer, nlc);
+ }
+}
+
+/**
+ * Enable collection
+ * Add its objects bases to ViewLayer
+ * Depsgraph needs to be rebuilt afterwards
+ */
+void BKE_collection_enable(ViewLayer *view_layer, LayerCollection *lc)
+{
+ if ((lc->flag & COLLECTION_DISABLED) == 0) {
+ return;
+ }
+
+ lc->flag &= ~COLLECTION_DISABLED;
+ layer_collection_enable(view_layer, lc);
+}
+
+/**
+ * Recursively disable nested collections
+ */
+static void layer_collection_disable(ViewLayer *view_layer, LayerCollection *lc)
+{
+ layer_collection_objects_unpopulate(view_layer, lc);
+
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ layer_collection_disable(view_layer, nlc);
+ }
+}
+
+/**
+ * Disable collection
+ * Remove all its object bases from ViewLayer
+ * Depsgraph needs to be rebuilt afterwards
+ */
+void BKE_collection_disable(ViewLayer *view_layer, LayerCollection *lc)
+{
+ if ((lc->flag & COLLECTION_DISABLED) != 0) {
+ return;
+ }
+
+ lc->flag |= COLLECTION_DISABLED;
+ layer_collection_disable(view_layer, lc);
+}
+
+static void layer_collection_object_add(ViewLayer *view_layer, LayerCollection *lc, Object *ob)
+{
+ Base *base = object_base_add(view_layer, 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;
+ }
+
+ bool is_visible = (lc->flag & COLLECTION_VISIBLE) != 0;
+ bool is_selectable = is_visible && ((lc->flag & COLLECTION_SELECTABLE) != 0);
+
+ if (is_visible) {
+ base->flag |= BASE_VISIBLED;
+ }
+
+ if (is_selectable) {
+ base->flag |= BASE_SELECTABLED;
+ }
+
+ BLI_addtail(&lc->object_bases, BLI_genericNodeN(base));
+}
+
+static void layer_collection_object_remove(ViewLayer *view_layer, LayerCollection *lc, Object *ob)
+{
+ Base *base;
+ base = BKE_view_layer_base_find(view_layer, ob);
+
+ LinkData *link = BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data));
+ BLI_remlink(&lc->object_bases, link);
+ MEM_freeN(link);
+
+ view_layer_object_base_unref(view_layer, base);
+}
+
+static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects)
+{
+ for (LinkData *link = objects->first; link; link = link->next) {
+ layer_collection_object_add(view_layer, lc, link->data);
+ }
+}
+
+static void layer_collection_populate(ViewLayer *view_layer, LayerCollection *lc, SceneCollection *sc)
+{
+ layer_collection_objects_populate(view_layer, lc, &sc->objects);
+ layer_collection_objects_populate(view_layer, lc, &sc->filter_objects);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ layer_collection_add(view_layer, lc, nsc);
+ }
+}
+
+static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc)
+{
+ IDPropertyTemplate val = {0};
+ LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
+
+ lc->scene_collection = sc;
+ lc->flag = COLLECTION_VISIBLE | COLLECTION_SELECTABLE;
+
+ lc->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ collection_engine_settings_init(lc->properties, false);
+
+ if (parent != NULL) {
+ BLI_addtail(&parent->layer_collections, lc);
+ }
+ else {
+ BLI_addtail(&view_layer->layer_collections, lc);
+ }
+
+ layer_collection_populate(view_layer, lc, sc);
+
+ return lc;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/**
+ * See if render layer has the scene collection linked directly, or indirectly (nested)
+ */
+bool BKE_view_layer_has_collection(ViewLayer *view_layer, const SceneCollection *sc)
+{
+ for (LayerCollection *lc = view_layer->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 (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ Base *base = BKE_view_layer_base_find(view_layer, 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 ViewLayers that have sc_parent
+ */
+void BKE_layer_sync_new_scene_collection(ID *owner_id, const SceneCollection *sc_parent, SceneCollection *sc)
+{
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *lc = view_layer->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(view_layer, lc_parent, sc);
+ }
+ }
+ }
+}
+
+/**
+ * Add a corresponding ObjectBase to all the equivalent LayerCollection
+ */
+void BKE_layer_sync_object_link(const ID *owner_id, SceneCollection *sc, Object *ob)
+{
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
+ if (found) {
+ layer_collection_object_add(view_layer, 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(const ID *owner_id, SceneCollection *sc, Object *ob)
+{
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
+ if (found) {
+ layer_collection_object_remove(view_layer, found, ob);
+ }
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Override */
+
+/**
+ * Add a new datablock override
+ */
+void BKE_override_view_layer_datablock_add(ViewLayer *view_layer, int id_type, const char *data_path, const ID *owner_id)
+{
+ UNUSED_VARS(view_layer, id_type, data_path, owner_id);
+ TODO_LAYER_OVERRIDE;
+}
+
+/**
+ * Add a new int override
+ */
+void BKE_override_view_layer_int_add(ViewLayer *view_layer, int id_type, const char *data_path, const int value)
+{
+ UNUSED_VARS(view_layer, id_type, data_path, value);
+ TODO_LAYER_OVERRIDE;
+}
+
+/**
+ * Add a new boolean override
+ */
+void BKE_override_layer_collection_boolean_add(struct LayerCollection *layer_collection, int id_type, const char *data_path, const bool value)
+{
+ UNUSED_VARS(layer_collection, id_type, data_path, value);
+ TODO_LAYER_OVERRIDE;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Engine Settings */
+
+ListBase R_layer_collection_engines_settings_callbacks = {NULL, NULL};
+ListBase R_view_layer_engines_settings_callbacks = {NULL, NULL};
+
+typedef struct EngineSettingsCB_Type {
+ struct EngineSettingsCB_Type *next, *prev;
+
+ char name[MAX_NAME]; /* engine name */
+
+ EngineSettingsCB callback;
+
+} EngineSettingsCB_Type;
+
+static void create_engine_settings_scene(IDProperty *root, EngineSettingsCB_Type *es_type)
+{
+ if (collection_engine_get(root, COLLECTION_MODE_NONE, es_type->name)) {
+ return;
+ }
+
+ IDProperty *props = collection_engine_settings_create(es_type, true);
+ IDP_AddToGroup(root, props);
+}
+
+static void create_layer_collection_engine_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type)
+{
+ create_engine_settings_scene(scene->collection_properties, es_type);
+}
+
+static void create_view_layer_engine_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type)
+{
+ create_engine_settings_scene(scene->layer_properties, es_type);
+}
+
+static void create_layer_collection_engine_settings_collection(LayerCollection *lc, EngineSettingsCB_Type *es_type)
+{
+ if (BKE_layer_collection_engine_collection_get(lc, COLLECTION_MODE_NONE, es_type->name)) {
+ return;
+ }
+
+ IDProperty *props = collection_engine_settings_create(es_type, false);
+ IDP_AddToGroup(lc->properties, props);
+
+ for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
+ create_layer_collection_engine_settings_collection(lcn, es_type);
+ }
+}
+
+static void create_layer_collection_engines_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type)
+{
+ /* Populate the scene with the new settings. */
+ create_layer_collection_engine_settings_scene(scene, es_type);
+
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ create_layer_collection_engine_settings_collection(lc, es_type);
+ }
+ }
+}
+
+static void create_view_layer_engines_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type)
+{
+ /* Populate the scene with the new settings. */
+ create_view_layer_engine_settings_scene(scene, es_type);
+}
+
+static void create_view_layer_engines_settings_layer(ViewLayer *view_layer, EngineSettingsCB_Type *es_type)
+{
+ if (BKE_view_layer_engine_layer_get(view_layer, COLLECTION_MODE_NONE, es_type->name)) {
+ return;
+ }
+
+ IDProperty *props = collection_engine_settings_create(es_type, false);
+ IDP_AddToGroup(view_layer->properties, props);
+}
+
+static EngineSettingsCB_Type *engine_settings_callback_register(const char *engine_name, EngineSettingsCB func, ListBase *lb)
+{
+ EngineSettingsCB_Type *es_type;
+
+ /* Cleanup in case it existed. */
+ es_type = BLI_findstring(lb, engine_name, offsetof(EngineSettingsCB_Type, name));
+
+ if (es_type) {
+ BLI_remlink(lb, es_type);
+ MEM_freeN(es_type);
+ }
+
+ es_type = MEM_callocN(sizeof(EngineSettingsCB_Type), __func__);
+ BLI_strncpy_utf8(es_type->name, engine_name, sizeof(es_type->name));
+ es_type->callback = func;
+ BLI_addtail(lb, es_type);
+
+ return es_type;
+}
+
+void BKE_layer_collection_engine_settings_callback_register(
+ Main *bmain, const char *engine_name, EngineSettingsCB func)
+{
+ EngineSettingsCB_Type *es_type =
+ engine_settings_callback_register(engine_name, func, &R_layer_collection_engines_settings_callbacks);
+
+ 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_layer_collection_engines_settings_scene(scene, es_type);
+ }
+ }
+}
+
+void BKE_view_layer_engine_settings_callback_register(
+ Main *bmain, const char *engine_name, EngineSettingsCB func)
+{
+ EngineSettingsCB_Type *es_type =
+ engine_settings_callback_register(engine_name, func, &R_view_layer_engines_settings_callbacks);
+
+ 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_view_layer_engines_settings_scene(scene, es_type);
+
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ create_view_layer_engines_settings_layer(view_layer, es_type);
+ }
+ }
+ }
+}
+
+void BKE_layer_collection_engine_settings_callback_free(void)
+{
+ BLI_freelistN(&R_layer_collection_engines_settings_callbacks);
+}
+
+void BKE_view_layer_engine_settings_callback_free(void)
+{
+ BLI_freelistN(&R_view_layer_engines_settings_callbacks);
+}
+
+/**
+ * Create a root IDProperty for this engine
+ *
+ * \param populate whether we want to pre-fill the collection with the default properties
+ */
+static IDProperty *collection_engine_settings_create(EngineSettingsCB_Type *es_type, const bool populate)
+{
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, es_type->name);
+ props->subtype = IDP_GROUP_SUB_ENGINE_RENDER;
+
+ /* properties */
+ if (populate) {
+ es_type->callback(NULL, props);
+ }
+
+ return props;
+}
+
+static void layer_collection_create_mode_settings_object(IDProperty *root, const bool populate)
+{
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, "ObjectMode");
+ props->subtype = IDP_GROUP_SUB_MODE_OBJECT;
+
+ /* properties */
+ if (populate) {
+ OBJECT_collection_settings_create(props);
+ }
+
+ IDP_AddToGroup(root, props);
+}
+
+static void layer_collection_create_mode_settings_edit(IDProperty *root, const bool populate)
+{
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, "EditMode");
+ props->subtype = IDP_GROUP_SUB_MODE_EDIT;
+
+ /* properties */
+ if (populate) {
+ EDIT_MESH_collection_settings_create(props);
+ }
+
+ IDP_AddToGroup(root, props);
+}
+
+static void layer_collection_create_mode_settings_paint_weight(IDProperty *root, const bool populate)
+{
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, "WeightPaintMode");
+ props->subtype = IDP_GROUP_SUB_MODE_PAINT_WEIGHT;
+
+ /* properties */
+ if (populate) {
+ PAINT_WEIGHT_collection_settings_create(props);
+ }
+
+ IDP_AddToGroup(root, props);
+}
+
+static void layer_collection_create_mode_settings_paint_vertex(IDProperty *root, const bool populate)
+{
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, "VertexPaintMode");
+ props->subtype = IDP_GROUP_SUB_MODE_PAINT_VERTEX;
+
+ /* properties */
+ if (populate) {
+ PAINT_VERTEX_collection_settings_create(props);
+ }
+
+ IDP_AddToGroup(root, props);
+}
+
+static void layer_collection_create_render_settings(IDProperty *root, const bool populate)
+{
+ EngineSettingsCB_Type *es_type;
+ for (es_type = R_layer_collection_engines_settings_callbacks.first; es_type; es_type = es_type->next) {
+ IDProperty *props = collection_engine_settings_create(es_type, populate);
+ IDP_AddToGroup(root, props);
+ }
+}
+
+static void view_layer_create_render_settings(IDProperty *root, const bool populate)
+{
+ EngineSettingsCB_Type *es_type;
+ for (es_type = R_view_layer_engines_settings_callbacks.first; es_type; es_type = es_type->next) {
+ IDProperty *props = collection_engine_settings_create(es_type, populate);
+ IDP_AddToGroup(root, props);
+ }
+}
+
+static void collection_create_mode_settings(IDProperty *root, const bool populate)
+{
+ /* XXX TODO: put all those engines in the R_engines_settings_callbacks
+ * and have IDP_AddToGroup outside the callbacks */
+ layer_collection_create_mode_settings_object(root, populate);
+ layer_collection_create_mode_settings_edit(root, populate);
+ layer_collection_create_mode_settings_paint_weight(root, populate);
+ layer_collection_create_mode_settings_paint_vertex(root, populate);
+}
+
+static void layer_create_mode_settings(IDProperty *root, const bool populate)
+{
+ TODO_LAYER; /* XXX like collection_create_mode_settings */
+ UNUSED_VARS(root, populate);
+}
+
+static int idproperty_group_subtype(const int mode_type)
+{
+ int idgroup_type;
+
+ switch (mode_type) {
+ case COLLECTION_MODE_OBJECT:
+ idgroup_type = IDP_GROUP_SUB_MODE_OBJECT;
+ break;
+ case COLLECTION_MODE_EDIT:
+ idgroup_type = IDP_GROUP_SUB_MODE_EDIT;
+ break;
+ case COLLECTION_MODE_PAINT_WEIGHT:
+ idgroup_type = IDP_GROUP_SUB_MODE_PAINT_WEIGHT;
+ break;
+ case COLLECTION_MODE_PAINT_VERTEX:
+ idgroup_type = IDP_GROUP_SUB_MODE_PAINT_VERTEX;
+ break;
+ default:
+ case COLLECTION_MODE_NONE:
+ return IDP_GROUP_SUB_ENGINE_RENDER;
+ break;
+ }
+
+ return idgroup_type;
+}
+
+/**
+ * Return collection enginne settings for either Object s of LayerCollection s
+ */
+static IDProperty *collection_engine_get(
+ IDProperty *root, const int type, const char *engine_name)
+{
+ const int subtype = idproperty_group_subtype(type);
+
+ if (subtype == IDP_GROUP_SUB_ENGINE_RENDER) {
+ return IDP_GetPropertyFromGroup(root, engine_name);
+ }
+ else {
+ IDProperty *prop;
+ for (prop = root->data.group.first; prop; prop = prop->next) {
+ if (prop->subtype == subtype) {
+ return prop;
+ }
+ }
+ }
+
+ BLI_assert(false);
+ return NULL;
+}
+
+/**
+ * Return collection engine settings from Object for specified engine of mode
+ */
+IDProperty *BKE_layer_collection_engine_evaluated_get(Object *ob, const int type, const char *engine_name)
+{
+ return collection_engine_get(ob->base_collection_properties, type, engine_name);
+}
+/**
+ * Return layer collection engine settings for specified engine
+ */
+IDProperty *BKE_layer_collection_engine_collection_get(LayerCollection *lc, const int type, const char *engine_name)
+{
+ return collection_engine_get(lc->properties, type, engine_name);
+}
+
+/**
+ * Return layer collection engine settings for specified engine in the scene
+ */
+IDProperty *BKE_layer_collection_engine_scene_get(Scene *scene, const int type, const char *engine_name)
+{
+ return collection_engine_get(scene->collection_properties, type, engine_name);
+}
+
+/**
+ * Return scene layer engine settings for specified engine in the scene
+ */
+IDProperty *BKE_view_layer_engine_scene_get(Scene *scene, const int type, const char *engine_name)
+{
+ return collection_engine_get(scene->layer_properties, type, engine_name);
+}
+
+/**
+ * Return scene layer engine settings for specified engine
+ */
+IDProperty *BKE_view_layer_engine_layer_get(ViewLayer *view_layer, const int type, const char *engine_name)
+{
+ return collection_engine_get(view_layer->properties, type, engine_name);
+}
+
+/**
+ * Return scene layer evaluated engine settings for specified engine
+ */
+IDProperty *BKE_view_layer_engine_evaluated_get(ViewLayer *view_layer, const int type, const char *engine_name)
+{
+ return collection_engine_get(view_layer->properties_evaluated, type, engine_name);
+}
+
+/* ---------------------------------------------------------------------- */
+/* Engine Settings Properties */
+
+void BKE_collection_engine_property_add_float(IDProperty *props, const char *name, float value)
+{
+ IDPropertyTemplate val = {0};
+ val.f = value;
+ IDP_AddToGroup(props, IDP_New(IDP_FLOAT, &val, name));
+}
+
+void BKE_collection_engine_property_add_float_array(
+ IDProperty *props, const char *name, const float *values, const int array_length)
+{
+ IDPropertyTemplate val = {0};
+ val.array.len = array_length;
+ val.array.type = IDP_FLOAT;
+
+ IDProperty *idprop = IDP_New(IDP_ARRAY, &val, name);
+ memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
+ IDP_AddToGroup(props, idprop);
+}
+
+void BKE_collection_engine_property_add_int(IDProperty *props, const char *name, int value)
+{
+ IDPropertyTemplate val = {0};
+ val.i = value;
+ IDP_AddToGroup(props, IDP_New(IDP_INT, &val, name));
+}
+
+void BKE_collection_engine_property_add_bool(IDProperty *props, const char *name, bool value)
+{
+ IDPropertyTemplate val = {0};
+ val.i = value;
+ IDP_AddToGroup(props, IDP_New(IDP_INT, &val, name));
+}
+
+int BKE_collection_engine_property_value_get_int(IDProperty *props, const char *name)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ return idprop ? IDP_Int(idprop) : 0;
+}
+
+float BKE_collection_engine_property_value_get_float(IDProperty *props, const char *name)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ return idprop ? IDP_Float(idprop) : 0.0f;
+}
+
+const float *BKE_collection_engine_property_value_get_float_array(IDProperty *props, const char *name)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ return idprop ? IDP_Array(idprop) : NULL;
+}
+
+bool BKE_collection_engine_property_value_get_bool(IDProperty *props, const char *name)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ return idprop ? IDP_Int(idprop) : 0;
+}
+
+void BKE_collection_engine_property_value_set_int(IDProperty *props, const char *name, int value)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ IDP_Int(idprop) = value;
+}
+
+void BKE_collection_engine_property_value_set_float(IDProperty *props, const char *name, float value)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ IDP_Float(idprop) = value;
+}
+
+void BKE_collection_engine_property_value_set_float_array(IDProperty *props, const char *name, const float *values)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
+}
+
+void BKE_collection_engine_property_value_set_bool(IDProperty *props, const char *name, bool value)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ IDP_Int(idprop) = value;
+}
+
+/* Engine Settings recalculate */
+
+/* get all the default settings defined in scene and merge them here */
+static void collection_engine_settings_init(IDProperty *root, const bool populate)
+{
+ /* render engines */
+ layer_collection_create_render_settings(root, populate);
+
+ /* mode engines */
+ collection_create_mode_settings(root, populate);
+}
+
+/* get all the default settings defined in scene and merge them here */
+static void layer_engine_settings_init(IDProperty *root, const bool populate)
+{
+ /* render engines */
+ view_layer_create_render_settings(root, populate);
+
+ /* mode engines */
+ layer_create_mode_settings(root, populate);
+}
+
+/**
+ * Initialize the layer collection render setings
+ * It's used mainly for scenes
+ */
+void BKE_layer_collection_engine_settings_create(IDProperty *root)
+{
+ collection_engine_settings_init(root, true);
+}
+
+/**
+ * Initialize the render setings
+ * It's used mainly for scenes
+ */
+void BKE_view_layer_engine_settings_create(IDProperty *root)
+{
+ layer_engine_settings_init(root, true);
+}
+
+/**
+ * Reference of IDProperty group scene collection settings
+ * Used when reading blendfiles, to see if there is any missing settings.
+ */
+static struct {
+ struct {
+ IDProperty *collection_properties;
+ IDProperty *render_settings;
+ } scene;
+ IDProperty *view_layer;
+ IDProperty *layer_collection;
+} root_reference = {
+ .scene = {NULL, NULL},
+ .view_layer = NULL,
+ .layer_collection = NULL,
+};
+
+/**
+ * Free the reference scene collection settings IDProperty group.
+ */
+static void engine_settings_validate_init(void)
+{
+ IDPropertyTemplate val = {0};
+
+ /* LayerCollection engine settings. */
+ if (root_reference.scene.collection_properties == NULL) {
+ root_reference.scene.collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ collection_engine_settings_init(root_reference.scene.collection_properties, true);
+ }
+
+ if (root_reference.layer_collection == NULL) {
+ root_reference.layer_collection = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ collection_engine_settings_init(root_reference.layer_collection, false);
+ }
+
+ /* Render engine setting. */
+ if (root_reference.scene.render_settings == NULL) {
+ root_reference.scene.render_settings = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ layer_engine_settings_init(root_reference.scene.render_settings, true);
+ }
+
+ if (root_reference.view_layer == NULL) {
+ root_reference.view_layer = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ layer_engine_settings_init(root_reference.view_layer, false);
+ }
+}
+
+/**
+ * Free the reference scene collection settings IDProperty group.
+ */
+static void layer_collection_engine_settings_validate_free(void)
+{
+ IDProperty *idprops[] = {
+ root_reference.scene.render_settings,
+ root_reference.scene.collection_properties,
+ root_reference.view_layer,
+ root_reference.layer_collection,
+ NULL,
+ };
+
+ IDProperty **idprop = &idprops[0];
+ while (*idprop) {
+ if (*idprop) {
+ IDP_FreeProperty(*idprop);
+ MEM_freeN(*idprop);
+ *idprop = NULL;
+ idprop++;
+ }
+ }
+}
+
+/**
+ * Make sure Scene has all required collection settings.
+ */
+void BKE_layer_collection_engine_settings_validate_scene(Scene *scene)
+{
+ if (root_reference.scene.collection_properties == NULL) {
+ engine_settings_validate_init();
+ }
+
+ if (scene->collection_properties == NULL) {
+ IDPropertyTemplate val = {0};
+ scene->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_layer_collection_engine_settings_create(scene->collection_properties);
+ }
+ else {
+ IDP_MergeGroup(scene->collection_properties, root_reference.scene.collection_properties, false);
+ }
+}
+
+/**
+ * Maker sure LayerCollection has all required collection settings.
+ */
+void BKE_layer_collection_engine_settings_validate_collection(LayerCollection *lc)
+{
+ if (root_reference.layer_collection == NULL) {
+ engine_settings_validate_init();
+ }
+
+ BLI_assert(lc->properties != NULL);
+ IDP_MergeGroup(lc->properties, root_reference.layer_collection, false);
+}
+
+/**
+ * Make sure Scene has all required collection settings.
+ */
+void BKE_view_layer_engine_settings_validate_scene(Scene *scene)
+{
+ if (root_reference.scene.render_settings == NULL) {
+ engine_settings_validate_init();
+ }
+
+ if (scene->layer_properties == NULL) {
+ IDPropertyTemplate val = {0};
+ scene->layer_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_view_layer_engine_settings_create(scene->layer_properties);
+ }
+ else {
+ IDP_MergeGroup(scene->layer_properties, root_reference.scene.render_settings, false);
+ }
+}
+
+/**
+ * Make sure Scene has all required collection settings.
+ */
+void BKE_view_layer_engine_settings_validate_layer(ViewLayer *view_layer)
+{
+ if (root_reference.view_layer == NULL) {
+ engine_settings_validate_init();
+ }
+
+ IDP_MergeGroup(view_layer->properties, root_reference.view_layer, false);
+}
+
+/* ---------------------------------------------------------------------- */
+/* Iterators */
+
+static void object_bases_iterator_begin(BLI_Iterator *iter, void *data_in, const int flag)
+{
+ ViewLayer *view_layer = data_in;
+ Base *base = view_layer->object_bases.first;
+
+ /* when there are no objects */
+ if (base == NULL) {
+ iter->valid = false;
+ return;
+ }
+
+ iter->data = base;
+
+ if ((base->flag & flag) == 0) {
+ object_bases_iterator_next(iter, flag);
+ }
+ else {
+ iter->current = base;
+ }
+}
+
+static void object_bases_iterator_next(BLI_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->valid = false;
+}
+
+static void objects_iterator_begin(BLI_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(BLI_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(BLI_Iterator *iter, void *data_in)
+{
+ objects_iterator_begin(iter, data_in, BASE_SELECTED);
+}
+
+void BKE_selected_objects_iterator_next(BLI_Iterator *iter)
+{
+ objects_iterator_next(iter, BASE_SELECTED);
+}
+
+void BKE_selected_objects_iterator_end(BLI_Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_visible_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
+{
+ objects_iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_iterator_next(BLI_Iterator *iter)
+{
+ objects_iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_iterator_end(BLI_Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_selected_bases_iterator_begin(BLI_Iterator *iter, void *data_in)
+{
+ object_bases_iterator_begin(iter, data_in, BASE_SELECTED);
+}
+
+void BKE_selected_bases_iterator_next(BLI_Iterator *iter)
+{
+ object_bases_iterator_next(iter, BASE_SELECTED);
+}
+
+void BKE_selected_bases_iterator_end(BLI_Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_visible_bases_iterator_begin(BLI_Iterator *iter, void *data_in)
+{
+ object_bases_iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_iterator_next(BLI_Iterator *iter)
+{
+ object_bases_iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_iterator_end(BLI_Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
+{
+ ObjectsRenderableIteratorData *data = data_in;
+
+ for (Scene *scene = data->scene; scene; scene = scene->set) {
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ base->object->id.flag |= LIB_TAG_DOIT;
+ }
+ }
+ }
+
+ ViewLayer *view_layer = data->scene->view_layers.first;
+ data->iter.view_layer = view_layer;
+
+ Base base = {(Base *)view_layer->object_bases.first, NULL};
+ data->iter.base = &base;
+
+ data->iter.set = NULL;
+
+ iter->data = data_in;
+ BKE_renderable_objects_iterator_next(iter);
+}
+
+void BKE_renderable_objects_iterator_next(BLI_Iterator *iter)
+{
+ ObjectsRenderableIteratorData *data = iter->data;
+ Base *base = data->iter.base->next;
+
+ /* There is still a base in the current scene layer. */
+ if (base != NULL) {
+ Object *ob = base->object;
+
+ iter->current = ob;
+ data->iter.base = base;
+
+ if ((base->flag & BASE_VISIBLED) == 0) {
+ BKE_renderable_objects_iterator_next(iter);
+ }
+ return;
+ }
+
+ /* Time to go to the next scene layer. */
+ if (data->iter.set == NULL) {
+ while ((data->iter.view_layer = data->iter.view_layer->next)) {
+ ViewLayer *view_layer = data->iter.view_layer;
+ if (view_layer->flag & VIEW_LAYER_RENDER) {
+
+ Base base_iter = {(Base *)view_layer->object_bases.first, NULL};
+ data->iter.base = &base_iter;
+
+ BKE_renderable_objects_iterator_next(iter);
+ return;
+ }
+ }
+
+ /* Setup the "set" for the next iteration. */
+ Scene scene = {.set = data->scene};
+ data->iter.set = &scene;
+ BKE_renderable_objects_iterator_next(iter);
+ return;
+ }
+
+ /* Look for an object in the next set. */
+ while ((data->iter.set = data->iter.set->set)) {
+ ViewLayer *view_layer = BKE_view_layer_from_scene_get(data->iter.set);
+
+ Base base_iter = {(Base *)view_layer->object_bases.first, NULL};
+ data->iter.base = &base_iter;
+
+ BKE_renderable_objects_iterator_next(iter);
+ return;
+ }
+
+ iter->valid = false;
+}
+
+void BKE_renderable_objects_iterator_end(BLI_Iterator *UNUSED(iter))
+{
+ /* Do nothing - iter->data was static allocated, we can't free it. */
+}
+
+/* Evaluation */
+
+/**
+ * Reset props
+ *
+ * If props_ref is pasted, copy props from it
+ */
+static void idproperty_reset(IDProperty **props, IDProperty *props_ref)
+{
+ IDPropertyTemplate val = {0};
+
+ if (*props) {
+ IDP_FreeProperty(*props);
+ MEM_freeN(*props);
+ }
+ *props = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+
+ if (props_ref) {
+ IDP_MergeGroup(*props, props_ref, true);
+ }
+}
+
+void BKE_layer_eval_layer_collection_pre(const struct EvaluationContext *UNUSED(eval_ctx),
+ ID *owner_id, ViewLayer *view_layer)
+{
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, view_layer->name, view_layer);
+ Scene *scene = (GS(owner_id->name) == ID_SCE) ? (Scene *)owner_id : NULL;
+
+ for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
+ base->flag &= ~(BASE_VISIBLED | BASE_SELECTABLED);
+ idproperty_reset(&base->collection_properties, scene ? scene->collection_properties : NULL);
+ }
+
+ /* Sync properties from scene to scene layer. */
+ idproperty_reset(&view_layer->properties_evaluated, scene ? scene->layer_properties : NULL);
+ IDP_MergeGroup(view_layer->properties_evaluated, view_layer->properties, true);
+
+ /* TODO(sergey): Is it always required? */
+ view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY;
+}
+
+static const char *collection_type_lookup[] =
+{
+ "None", /* COLLECTION_TYPE_NONE */
+ "Group Internal", /* COLLECTION_TYPE_GROUP_INTERNAL */
+};
+
+void BKE_layer_eval_layer_collection(const struct EvaluationContext *UNUSED(eval_ctx),
+ LayerCollection *layer_collection,
+ LayerCollection *parent_layer_collection)
+{
+ DEBUG_PRINT("%s on %s (%p) [%s], parent %s (%p) [%s]\n",
+ __func__,
+ layer_collection->scene_collection->name,
+ layer_collection->scene_collection,
+ collection_type_lookup[layer_collection->scene_collection->type],
+ (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection->name : "NONE",
+ (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection : NULL,
+ (parent_layer_collection != NULL) ? collection_type_lookup[parent_layer_collection->scene_collection->type] : "");
+ BLI_assert(layer_collection != parent_layer_collection);
+
+ /* visibility */
+ layer_collection->flag_evaluated = layer_collection->flag;
+ bool is_visible = (layer_collection->flag & COLLECTION_VISIBLE) != 0;
+ bool is_selectable = is_visible && ((layer_collection->flag & COLLECTION_SELECTABLE) != 0);
+
+ if (parent_layer_collection != NULL) {
+ is_visible &= (parent_layer_collection->flag_evaluated & COLLECTION_VISIBLE) != 0;
+ is_selectable &= (parent_layer_collection->flag_evaluated & COLLECTION_SELECTABLE) != 0;
+ layer_collection->flag_evaluated &= parent_layer_collection->flag_evaluated;
+ }
+
+ /* overrides */
+ if (is_visible) {
+ if (parent_layer_collection == NULL) {
+ idproperty_reset(&layer_collection->properties_evaluated, layer_collection->properties);
+ }
+ else {
+ idproperty_reset(&layer_collection->properties_evaluated, parent_layer_collection->properties_evaluated);
+ IDP_MergeGroup(layer_collection->properties_evaluated, layer_collection->properties, true);
+ }
+ }
+
+ for (LinkData *link = layer_collection->object_bases.first; link != NULL; link = link->next) {
+ Base *base = link->data;
+
+ if (is_visible) {
+ IDP_MergeGroup(base->collection_properties, layer_collection->properties_evaluated, true);
+ base->flag |= BASE_VISIBLED;
+ }
+
+ if (is_selectable) {
+ base->flag |= BASE_SELECTABLED;
+ }
+ }
+}
+
+void BKE_layer_eval_layer_collection_post(const struct EvaluationContext *UNUSED(eval_ctx),
+ ViewLayer *view_layer)
+{
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, view_layer->name, view_layer);
+ /* if base is not selectabled, clear select */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) == 0) {
+ base->flag &= ~BASE_SELECTED;
+ }
+ }
+}
+
+/**
+ * Free any static allocated memory.
+ */
+void BKE_layer_exit(void)
+{
+ layer_collection_engine_settings_validate_free();
+}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 9d05f13d7df..0ef1fe52994 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -62,6 +62,7 @@
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_speaker_types.h"
@@ -70,6 +71,7 @@
#include "DNA_vfont_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_world_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -91,7 +93,6 @@
#include "BKE_cachefile.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_group.h"
@@ -103,6 +104,7 @@
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
+#include "BKE_library_override.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
#include "BKE_linestyle.h"
@@ -117,6 +119,7 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_packedFile.h"
+#include "BKE_lightprobe.h"
#include "BKE_sound.h"
#include "BKE_speaker.h"
#include "BKE_scene.h"
@@ -418,6 +421,9 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
case ID_SPK:
if (!test) BKE_speaker_make_local(bmain, (Speaker *)id, lib_local);
return true;
+ case ID_LP:
+ if (!test) BKE_lightprobe_make_local(bmain, (LightProbe *)id, lib_local);
+ return true;
case ID_WO:
if (!test) BKE_world_make_local(bmain, (World *)id, lib_local);
return true;
@@ -469,7 +475,11 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
case ID_CF:
if (!test) BKE_cachefile_make_local(bmain, (CacheFile *)id, lib_local);
return true;
+ case ID_WS:
case ID_SCR:
+ /* A bit special: can be appended but not linked. Return false
+ * since supporting make-local doesn't make much sense. */
+ return false;
case ID_LI:
case ID_KE:
case ID_WM:
@@ -589,6 +599,9 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, con
case ID_SPK:
BKE_speaker_copy_data(bmain, (Speaker *)*r_newid, (Speaker *)id, flag);
break;
+ case ID_LP:
+ BKE_lightprobe_copy_data(bmain, (LightProbe *)*r_newid, (LightProbe *)id, flag);
+ break;
case ID_CA:
BKE_camera_copy_data(bmain, (Camera *)*r_newid, (Camera *)id, flag);
break;
@@ -649,6 +662,7 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, con
case ID_LI:
case ID_SCR:
case ID_WM:
+ case ID_WS:
case ID_IP:
BLI_assert(0); /* Should have been rejected at start of function! */
break;
@@ -680,6 +694,75 @@ bool id_copy(Main *bmain, const ID *id, ID **newid, bool test)
return BKE_id_copy_ex(bmain, id, newid, 0, test);
}
+/** Does a mere memory swap over the whole IDs data (including type-specific memory).
+ * \note Most internal ID data itself is not swapped (only IDProperties are). */
+void BKE_id_swap(Main *bmain, ID *id_a, ID *id_b)
+{
+ BLI_assert(GS(id_a->name) == GS(id_b->name));
+
+ const ID id_a_back = *id_a;
+ const ID id_b_back = *id_b;
+
+#define CASE_SWAP(_gs, _type) \
+ case _gs: \
+ SWAP(_type, *(_type *)id_a, *(_type *)id_b); \
+ break
+
+ switch ((ID_Type)GS(id_a->name)) {
+ CASE_SWAP(ID_SCE, Scene);
+ CASE_SWAP(ID_LI, Library);
+ CASE_SWAP(ID_OB, Object);
+ CASE_SWAP(ID_ME, Mesh);
+ CASE_SWAP(ID_CU, Curve);
+ CASE_SWAP(ID_MB, MetaBall);
+ CASE_SWAP(ID_MA, Material);
+ CASE_SWAP(ID_TE, Tex);
+ CASE_SWAP(ID_IM, Image);
+ CASE_SWAP(ID_LT, Lattice);
+ CASE_SWAP(ID_LA, Lamp);
+ CASE_SWAP(ID_LP, LightProbe);
+ CASE_SWAP(ID_CA, Camera);
+ CASE_SWAP(ID_KE, Key);
+ CASE_SWAP(ID_WO, World);
+ CASE_SWAP(ID_SCR, bScreen);
+ CASE_SWAP(ID_VF, VFont);
+ CASE_SWAP(ID_TXT, Text);
+ CASE_SWAP(ID_SPK, Speaker);
+ CASE_SWAP(ID_SO, bSound);
+ CASE_SWAP(ID_GR, Group);
+ CASE_SWAP(ID_AR, bArmature);
+ CASE_SWAP(ID_AC, bAction);
+ CASE_SWAP(ID_NT, bNodeTree);
+ CASE_SWAP(ID_BR, Brush);
+ CASE_SWAP(ID_PA, ParticleSettings);
+ CASE_SWAP(ID_WM, wmWindowManager);
+ CASE_SWAP(ID_WS, WorkSpace);
+ CASE_SWAP(ID_GD, bGPdata);
+ CASE_SWAP(ID_MC, MovieClip);
+ CASE_SWAP(ID_MSK, Mask);
+ CASE_SWAP(ID_LS, FreestyleLineStyle);
+ CASE_SWAP(ID_PAL, Palette);
+ CASE_SWAP(ID_PC, PaintCurve);
+ CASE_SWAP(ID_CF, CacheFile);
+ case ID_IP:
+ break; /* Deprecated. */
+ }
+
+#undef CASE_SWAP
+
+ /* Restore original ID's internal data. */
+ *id_a = id_a_back;
+ *id_b = id_b_back;
+
+ /* Exception: IDProperties. */
+ id_a->properties = id_b_back.properties;
+ id_b->properties = id_a_back.properties;
+
+ /* Swap will have broken internal references to itself, restore them. */
+ BKE_libblock_relink_ex(bmain, id_a, id_b, id_a, false);
+ BKE_libblock_relink_ex(bmain, id_b, id_a, id_b, false);
+}
+
/** Does *not* set ID->newid pointer. */
bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
{
@@ -845,6 +928,8 @@ ListBase *which_libbase(Main *mainlib, short type)
return &(mainlib->text);
case ID_SPK:
return &(mainlib->speaker);
+ case ID_LP:
+ return &(mainlib->lightprobe);
case ID_SO:
return &(mainlib->sound);
case ID_GR:
@@ -875,6 +960,8 @@ ListBase *which_libbase(Main *mainlib, short type)
return &(mainlib->paintcurves);
case ID_CF:
return &(mainlib->cachefiles);
+ case ID_WS:
+ return &(mainlib->workspaces);
}
return NULL;
}
@@ -960,11 +1047,11 @@ void BKE_main_lib_objects_recalc_all(Main *bmain)
/* flag for full recalc */
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (ID_IS_LINKED(ob)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
}
- DAG_id_type_tag(bmain, ID_OB);
+ DEG_id_type_tag(bmain, ID_OB);
}
/**
@@ -1013,6 +1100,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[INDEX_ID_BR] = &(main->brush);
lb[INDEX_ID_PA] = &(main->particle);
lb[INDEX_ID_SPK] = &(main->speaker);
+ lb[INDEX_ID_LP] = &(main->lightprobe);
lb[INDEX_ID_WO] = &(main->world);
lb[INDEX_ID_MC] = &(main->movieclip);
@@ -1020,6 +1108,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[INDEX_ID_OB] = &(main->object);
lb[INDEX_ID_LS] = &(main->linestyle); /* referenced by scenes */
lb[INDEX_ID_SCE] = &(main->scene);
+ lb[INDEX_ID_WS] = &(main->workspaces); /* before wm, so it's freed after it! */
lb[INDEX_ID_WM] = &(main->wm);
lb[INDEX_ID_MSK] = &(main->mask);
@@ -1072,6 +1161,7 @@ size_t BKE_libblock_get_alloc_info(short type, const char **name)
CASE_RETURN(ID_VF, VFont);
CASE_RETURN(ID_TXT, Text);
CASE_RETURN(ID_SPK, Speaker);
+ CASE_RETURN(ID_LP, LightProbe);
CASE_RETURN(ID_SO, bSound);
CASE_RETURN(ID_GR, Group);
CASE_RETURN(ID_AR, bArmature);
@@ -1087,6 +1177,7 @@ size_t BKE_libblock_get_alloc_info(short type, const char **name)
CASE_RETURN(ID_PAL, Palette);
CASE_RETURN(ID_PC, PaintCurve);
CASE_RETURN(ID_CF, CacheFile);
+ CASE_RETURN(ID_WS, WorkSpace);
}
return 0;
#undef CASE_RETURN
@@ -1143,7 +1234,7 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
/* TODO to be removed from here! */
if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) {
- DAG_id_type_tag(bmain, type);
+ DEG_id_type_tag(bmain, type);
}
}
else {
@@ -1202,6 +1293,9 @@ void BKE_libblock_init_empty(ID *id)
case ID_SPK:
BKE_speaker_init((Speaker *)id);
break;
+ case ID_LP:
+ BKE_lightprobe_init((LightProbe *)id);
+ break;
case ID_CA:
BKE_camera_init((Camera *)id);
break;
@@ -1322,11 +1416,20 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int fla
new_id->properties = IDP_CopyProperty_ex(id->properties, flag);
}
+ /* XXX Again... We need a way to control what we copy in a much more refined way.
+ * We cannot always copy this, some internal copying will die on it! */
+ /* For now, upper level code will have to do that itself when required. */
+#if 0
+ if (id->override != NULL) {
+ BKE_override_copy(new_id, id);
+ }
+#endif
+
/* the duplicate should get a copy of the animdata */
id_copy_animdata(bmain, new_id, (flag & LIB_ID_COPY_ACTIONS) != 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0);
if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0) {
- DAG_id_type_tag(bmain, GS(new_id->name));
+ DEG_id_type_tag(bmain, GS(new_id->name));
}
*r_newid = new_id;
diff --git a/source/blender/blenkernel/intern/library_override.c b/source/blender/blenkernel/intern/library_override.c
new file mode 100644
index 00000000000..22896cff64a
--- /dev/null
+++ b/source/blender/blenkernel/intern/library_override.c
@@ -0,0 +1,680 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/library_override.c
+ * \ingroup bke
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_object_types.h"
+
+#include "DEG_depsgraph.h"
+#include "BKE_library.h"
+#include "BKE_library_override.h"
+#include "BKE_library_remap.h"
+#include "BKE_main.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+#include "PIL_time.h"
+#include "PIL_time_utildefines.h"
+
+#define OVERRIDE_AUTO_CHECK_DELAY 0.2 /* 200ms between auto-override checks. */
+
+static void bke_override_property_copy(IDOverrideStaticProperty *op_dst, IDOverrideStaticProperty *op_src);
+static void bke_override_property_operation_copy(IDOverrideStaticPropertyOperation *opop_dst, IDOverrideStaticPropertyOperation *opop_src);
+
+static void bke_override_property_clear(IDOverrideStaticProperty *op);
+static void bke_override_property_operation_clear(IDOverrideStaticPropertyOperation *opop);
+
+/** Initialize empty overriding of \a reference_id by \a local_id. */
+IDOverrideStatic *BKE_override_static_init(ID *local_id, ID *reference_id)
+{
+ /* If reference_id is NULL, we are creating an override template for purely local data.
+ * Else, reference *must* be linked data. */
+ BLI_assert(reference_id == NULL || reference_id->lib != NULL);
+ BLI_assert(local_id->override_static == NULL);
+
+ if (reference_id != NULL && reference_id->override_static != NULL && reference_id->override_static->reference == NULL) {
+ /* reference ID has an override template, use it! */
+ BKE_override_static_copy(local_id, reference_id);
+ return local_id->override_static;
+ }
+
+ /* Else, generate new empty override. */
+ local_id->override_static = MEM_callocN(sizeof(*local_id->override_static), __func__);
+ local_id->override_static->reference = reference_id;
+ id_us_plus(reference_id);
+ local_id->tag &= ~LIB_TAG_OVERRIDESTATIC_OK;
+ /* TODO do we want to add tag or flag to referee to mark it as such? */
+ return local_id->override_static;
+}
+
+/** Deep copy of a whole override from \a src_id to \a dst_id. */
+void BKE_override_static_copy(ID *dst_id, const ID *src_id)
+{
+ BLI_assert(src_id->override_static != NULL);
+
+ if (dst_id->override_static != NULL) {
+ if (src_id->override_static == NULL) {
+ BKE_override_static_free(&dst_id->override_static);
+ return;
+ }
+ else {
+ BKE_override_static_clear(dst_id->override_static);
+ }
+ }
+ else if (src_id->override_static == NULL) {
+ return;
+ }
+ else {
+ BKE_override_static_init(dst_id, NULL);
+ }
+
+ /* Source is already overriding data, we copy it but reuse its reference for dest ID.
+ * otherwise, source is only an override template, it then becomes reference of dest ID. */
+ dst_id->override_static->reference = src_id->override_static->reference ? src_id->override_static->reference : (ID *)src_id;
+ id_us_plus(dst_id->override_static->reference);
+
+ BLI_duplicatelist(&dst_id->override_static->properties, &src_id->override_static->properties);
+ for (IDOverrideStaticProperty *op_dst = dst_id->override_static->properties.first, *op_src = src_id->override_static->properties.first;
+ op_dst;
+ op_dst = op_dst->next, op_src = op_src->next)
+ {
+ bke_override_property_copy(op_dst, op_src);
+ }
+
+ dst_id->tag &= ~LIB_TAG_OVERRIDESTATIC_OK;
+}
+
+/** Clear any overriding data from given \a override. */
+void BKE_override_static_clear(IDOverrideStatic *override)
+{
+ BLI_assert(override != NULL);
+
+ for (IDOverrideStaticProperty *op = override->properties.first; op; op = op->next) {
+ bke_override_property_clear(op);
+ }
+ BLI_freelistN(&override->properties);
+
+ id_us_min(override->reference);
+ /* override->storage should never be refcounted... */
+}
+
+/** Free given \a override. */
+void BKE_override_static_free(struct IDOverrideStatic **override)
+{
+ BLI_assert(*override != NULL);
+
+ BKE_override_static_clear(*override);
+ MEM_freeN(*override);
+ *override = NULL;
+}
+
+/** Create an overriden local copy of linked reference. */
+ID *BKE_override_static_create_from(Main *bmain, ID *reference_id)
+{
+ BLI_assert(reference_id != NULL);
+ BLI_assert(reference_id->lib != NULL);
+
+ ID *local_id;
+
+ if (!id_copy(bmain, reference_id, (ID **)&local_id, false)) {
+ return NULL;
+ }
+ id_us_min(local_id);
+
+ BKE_override_static_init(local_id, reference_id);
+ local_id->flag |= LIB_OVERRIDE_STATIC_AUTO;
+
+ /* Remapping, we obviously only want to affect local data (and not our own reference pointer to overriden ID). */
+ BKE_libblock_remap(bmain, reference_id, local_id, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_STATIC_OVERRIDE);
+
+ return local_id;
+}
+
+/**
+ * Find override property from given RNA path, if it exists.
+ */
+IDOverrideStaticProperty *BKE_override_static_property_find(IDOverrideStatic *override, const char *rna_path)
+{
+ /* XXX TODO we'll most likely want a runtime ghash to store that mapping at some point. */
+ return BLI_findstring_ptr(&override->properties, rna_path, offsetof(IDOverrideStaticProperty, rna_path));
+}
+
+/**
+ * Find override property from given RNA path, or create it if it does not exist.
+ */
+IDOverrideStaticProperty *BKE_override_static_property_get(IDOverrideStatic *override, const char *rna_path, bool *r_created)
+{
+ /* XXX TODO we'll most likely want a runtime ghash to store taht mapping at some point. */
+ IDOverrideStaticProperty *op = BKE_override_static_property_find(override, rna_path);
+
+ if (op == NULL) {
+ op = MEM_callocN(sizeof(IDOverrideStaticProperty), __func__);
+ op->rna_path = BLI_strdup(rna_path);
+ BLI_addtail(&override->properties, op);
+
+ if (r_created) {
+ *r_created = true;
+ }
+ }
+ else if (r_created) {
+ *r_created = false;
+ }
+
+ return op;
+}
+
+void bke_override_property_copy(IDOverrideStaticProperty *op_dst, IDOverrideStaticProperty *op_src)
+{
+ op_dst->rna_path = BLI_strdup(op_src->rna_path);
+ BLI_duplicatelist(&op_dst->operations, &op_src->operations);
+
+ for (IDOverrideStaticPropertyOperation *opop_dst = op_dst->operations.first, *opop_src = op_src->operations.first;
+ opop_dst;
+ opop_dst = opop_dst->next, opop_src = opop_src->next)
+ {
+ bke_override_property_operation_copy(opop_dst, opop_src);
+ }
+}
+
+void bke_override_property_clear(IDOverrideStaticProperty *op)
+{
+ BLI_assert(op->rna_path != NULL);
+
+ MEM_freeN(op->rna_path);
+
+ for (IDOverrideStaticPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
+ bke_override_property_operation_clear(opop);
+ }
+ BLI_freelistN(&op->operations);
+}
+
+/**
+ * Remove and free given \a override_property from given ID \a override.
+ */
+void BKE_override_static_property_delete(IDOverrideStatic *override, IDOverrideStaticProperty *override_property)
+{
+ bke_override_property_clear(override_property);
+ BLI_freelinkN(&override->properties, override_property);
+}
+
+/**
+ * Find override property operation from given sub-item(s), if it exists.
+ */
+IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_find(
+ IDOverrideStaticProperty *override_property,
+ const char *subitem_refname, const char *subitem_locname,
+ const int subitem_refindex, const int subitem_locindex, const bool strict, bool *r_strict)
+{
+ IDOverrideStaticPropertyOperation *opop;
+ const int subitem_defindex = -1;
+
+ if (r_strict) {
+ *r_strict = true;
+ }
+
+ if (subitem_locname &&
+ (opop = BLI_findstring_ptr(&override_property->operations, subitem_locname,
+ offsetof(IDOverrideStaticPropertyOperation, subitem_local_name))))
+ {
+ return opop;
+ }
+
+ if (subitem_refname &&
+ (opop = BLI_findstring_ptr(&override_property->operations, subitem_refname,
+ offsetof(IDOverrideStaticPropertyOperation, subitem_reference_name))))
+ {
+ return opop;
+ }
+
+ if ((opop = BLI_listbase_bytes_find(&override_property->operations, &subitem_locindex, sizeof(subitem_locindex),
+ offsetof(IDOverrideStaticPropertyOperation, subitem_local_index))))
+ {
+ return opop;
+ }
+
+ if ((opop = BLI_listbase_bytes_find(&override_property->operations, &subitem_refindex, sizeof(subitem_refindex),
+ offsetof(IDOverrideStaticPropertyOperation, subitem_reference_index))))
+ {
+ return opop;
+ }
+
+ /* index == -1 means all indices, that is valid fallback in case we requested specific index. */
+ if (!strict && (subitem_locindex != subitem_defindex) &&
+ (opop = BLI_listbase_bytes_find(&override_property->operations, &subitem_defindex, sizeof(subitem_defindex),
+ offsetof(IDOverrideStaticPropertyOperation, subitem_local_index))))
+ {
+ if (r_strict) {
+ *r_strict = false;
+ }
+ return opop;
+ }
+
+ return NULL;
+}
+
+/**
+ * Find override property operation from given sub-item(s), or create it if it does not exist.
+ */
+IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_get(
+ IDOverrideStaticProperty *override_property, const short operation,
+ const char *subitem_refname, const char *subitem_locname,
+ const int subitem_refindex, const int subitem_locindex,
+ const bool strict, bool *r_strict, bool *r_created)
+{
+ IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find(override_property,
+ subitem_refname, subitem_locname,
+ subitem_refindex, subitem_locindex,
+ strict, r_strict);
+
+ if (opop == NULL) {
+ opop = MEM_callocN(sizeof(IDOverrideStaticPropertyOperation), __func__);
+ opop->operation = operation;
+ if (subitem_locname) {
+ opop->subitem_local_name = BLI_strdup(subitem_locname);
+ }
+ if (subitem_refname) {
+ opop->subitem_reference_name = BLI_strdup(subitem_refname);
+ }
+ opop->subitem_local_index = subitem_locindex;
+ opop->subitem_reference_index = subitem_refindex;
+
+ BLI_addtail(&override_property->operations, opop);
+
+ if (r_created) {
+ *r_created = true;
+ }
+ }
+ else if (r_created) {
+ *r_created = false;
+ }
+
+ return opop;
+}
+
+void bke_override_property_operation_copy(IDOverrideStaticPropertyOperation *opop_dst, IDOverrideStaticPropertyOperation *opop_src)
+{
+ if (opop_src->subitem_reference_name) {
+ opop_dst->subitem_reference_name = BLI_strdup(opop_src->subitem_reference_name);
+ }
+ if (opop_src->subitem_local_name) {
+ opop_dst->subitem_local_name = BLI_strdup(opop_src->subitem_local_name);
+ }
+}
+
+void bke_override_property_operation_clear(IDOverrideStaticPropertyOperation *opop)
+{
+ if (opop->subitem_reference_name) {
+ MEM_freeN(opop->subitem_reference_name);
+ }
+ if (opop->subitem_local_name) {
+ MEM_freeN(opop->subitem_local_name);
+ }
+}
+
+/**
+ * Remove and free given \a override_property_operation from given ID \a override_property.
+ */
+void BKE_override_static_property_operation_delete(
+ IDOverrideStaticProperty *override_property, IDOverrideStaticPropertyOperation *override_property_operation)
+{
+ bke_override_property_operation_clear(override_property_operation);
+ BLI_freelinkN(&override_property->operations, override_property_operation);
+}
+
+/**
+ * Check that status of local data-block is still valid against current reference one.
+ *
+ * It means that all overridable, but not overridden, properties' local values must be equal to reference ones.
+ * Clears LIB_TAG_OVERRIDE_OK if they do not.
+ *
+ * This is typically used to detect whether some property has been changed in local and a new IDOverrideProperty
+ * (of IDOverridePropertyOperation) has to be added.
+ *
+ * \return true if status is OK, false otherwise. */
+bool BKE_override_static_status_check_local(ID *local)
+{
+ BLI_assert(local->override_static != NULL);
+
+ ID *reference = local->override_static->reference;
+
+ if (reference == NULL) {
+ /* This is an override template, local status is always OK! */
+ return true;
+ }
+
+ BLI_assert(GS(local->name) == GS(reference->name));
+
+ /* Note that reference is assumed always valid, caller has to ensure that itself. */
+
+ PointerRNA rnaptr_local, rnaptr_reference;
+ RNA_id_pointer_create(local, &rnaptr_local);
+ RNA_id_pointer_create(reference, &rnaptr_reference);
+
+ if (!RNA_struct_override_matches(&rnaptr_local, &rnaptr_reference, local->override_static, true, true)) {
+ local->tag &= ~LIB_TAG_OVERRIDESTATIC_OK;
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Check that status of reference data-block is still valid against current local one.
+ *
+ * It means that all non-overridden properties' local values must be equal to reference ones.
+ * Clears LIB_TAG_OVERRIDE_OK if they do not.
+ *
+ * This is typically used to detect whether some reference has changed and local needs to be updated against it.
+ *
+ * \return true if status is OK, false otherwise. */
+bool BKE_override_static_status_check_reference(ID *local)
+{
+ BLI_assert(local->override_static != NULL);
+
+ ID *reference = local->override_static->reference;
+
+ if (reference == NULL) {
+ /* This is an override template, reference is virtual, so its status is always OK! */
+ return true;
+ }
+
+ BLI_assert(GS(local->name) == GS(reference->name));
+
+ if (reference->override_static && (reference->tag & LIB_TAG_OVERRIDESTATIC_OK) == 0) {
+ if (!BKE_override_static_status_check_reference(reference)) {
+ /* If reference is also override of another data-block, and its status is not OK,
+ * then this override is not OK either.
+ * Note that this should only happen when reloading libraries... */
+ local->tag &= ~LIB_TAG_OVERRIDESTATIC_OK;
+ return false;
+ }
+ }
+
+ PointerRNA rnaptr_local, rnaptr_reference;
+ RNA_id_pointer_create(local, &rnaptr_local);
+ RNA_id_pointer_create(reference, &rnaptr_reference);
+
+ if (!RNA_struct_override_matches(&rnaptr_local, &rnaptr_reference, local->override_static, false, true)) {
+ local->tag &= ~LIB_TAG_OVERRIDESTATIC_OK;
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Compares local and reference data-blocks and create new override operations as needed,
+ * or reset to reference values if overriding is not allowed.
+ *
+ * \note Defining override operations is only mandatory before saving a .blend file on disk (not for undo!).
+ * Knowing that info at runtime is only useful for UI/UX feedback.
+ *
+ * \note This is by far the biggest operation (the more time-consuming) of the three so far, since it has to go over
+ * all properties in depth (all overridable ones at least). Generating diff values and applying overrides
+ * are much cheaper.
+ *
+ * \return true is new overriding op was created, or some local data was reset. */
+bool BKE_override_static_operations_create(ID *local)
+{
+ BLI_assert(local->override_static != NULL);
+ const bool is_template = (local->override_static->reference == NULL);
+ bool ret = false;
+
+ if (!is_template && local->flag & LIB_OVERRIDE_STATIC_AUTO) {
+ PointerRNA rnaptr_local, rnaptr_reference;
+ RNA_id_pointer_create(local, &rnaptr_local);
+ RNA_id_pointer_create(local->override_static->reference, &rnaptr_reference);
+
+ ret = RNA_struct_auto_override(&rnaptr_local, &rnaptr_reference, local->override_static, NULL);
+#ifndef NDEBUG
+ if (ret) {
+ printf("We did generate static override rules for %s\n", local->name);
+ }
+ else {
+ printf("No new static override rules for %s\n", local->name);
+ }
+#endif
+ }
+ return ret;
+}
+
+/** Check all overrides from given \a bmain and create/update overriding operations as needed. */
+void BKE_main_override_static_operations_create(Main *bmain)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ int base_count, i;
+
+ base_count = set_listbasepointers(bmain, lbarray);
+
+ for (i = 0; i < base_count; i++) {
+ ListBase *lb = lbarray[i];
+ ID *id;
+
+ for (id = lb->first; id; id = id->next) {
+ /* TODO Maybe we could also add an 'override update' tag e.g. when tagging for DEG update? */
+ if (id->lib == NULL && id->override_static != NULL && id->override_static->reference != NULL && (id->flag & LIB_OVERRIDE_STATIC_AUTO)) {
+ BKE_override_static_operations_create(id);
+ }
+ }
+ }
+}
+
+/** Update given override from its reference (re-applying overriden properties). */
+void BKE_override_static_update(Main *bmain, ID *local)
+{
+ if (local->override_static == NULL || local->override_static->reference == NULL) {
+ return;
+ }
+
+ /* Recursively do 'ancestors' overrides first, if any. */
+ if (local->override_static->reference->override_static && (local->override_static->reference->tag & LIB_TAG_OVERRIDESTATIC_OK) == 0) {
+ BKE_override_static_update(bmain, local->override_static->reference);
+ }
+
+ /* We want to avoid having to remap here, however creating up-to-date override is much simpler if based
+ * on reference than on current override.
+ * So we work on temp copy of reference, and 'swap' its content with local. */
+
+ /* XXX We need a way to get off-Main copies of IDs (similar to localized mats/texts/ etc.)!
+ * However, this is whole bunch of code work in itself, so for now plain stupid ID copy will do,
+ * as innefficient as it is. :/
+ * Actually, maybe not! Since we are swapping with original ID's local content, we want to keep
+ * usercount in correct state when freeing tmp_id (and that usercounts of IDs used by 'new' local data
+ * also remain correct). */
+ /* This would imply change in handling of usercout all over RNA (and possibly all over Blender code).
+ * Not impossible to do, but would rather see first if extra useless usual user handling is actually
+ * a (performances) issue here. */
+
+ ID *tmp_id;
+ id_copy(bmain, local->override_static->reference, &tmp_id, false);
+
+ if (tmp_id == NULL) {
+ return;
+ }
+
+ PointerRNA rnaptr_src, rnaptr_dst, rnaptr_storage_stack, *rnaptr_storage = NULL;
+ RNA_id_pointer_create(local, &rnaptr_src);
+ RNA_id_pointer_create(tmp_id, &rnaptr_dst);
+ if (local->override_static->storage) {
+ rnaptr_storage = &rnaptr_storage_stack;
+ RNA_id_pointer_create(local->override_static->storage, rnaptr_storage);
+ }
+
+ RNA_struct_override_apply(&rnaptr_dst, &rnaptr_src, rnaptr_storage, local->override_static);
+
+ /* This also transfers all pointers (memory) owned by local to tmp_id, and vice-versa. So when we'll free tmp_id,
+ * we'll actually free old, outdated data from local. */
+ BKE_id_swap(bmain, local, tmp_id);
+
+ /* Again, horribly innefficient in our case, we need something off-Main (aka moar generic nolib copy/free stuff)! */
+ /* XXX And crashing in complex cases (e.g. because depsgraph uses same data...). */
+ BKE_libblock_free_ex(bmain, tmp_id, true, false);
+
+ if (local->override_static->storage) {
+ /* We know this datablock is not used anywhere besides local->override->storage. */
+ /* XXX For until we get fully shadow copies, we still need to ensure storage releases
+ * its usage of any ID pointers it may have. */
+ BKE_libblock_free_ex(bmain, local->override_static->storage, true, false);
+ local->override_static->storage = NULL;
+ }
+
+ local->tag |= LIB_TAG_OVERRIDESTATIC_OK;
+
+ /* Full rebuild of Depsgraph! */
+ DEG_on_visible_update(bmain, true); /* XXX Is this actual valid replacement for old DAG_relations_tag_update(bmain) ? */
+}
+
+/** Update all overrides from given \a bmain. */
+void BKE_main_override_static_update(Main *bmain)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ int base_count, i;
+
+ base_count = set_listbasepointers(bmain, lbarray);
+
+ for (i = 0; i < base_count; i++) {
+ ListBase *lb = lbarray[i];
+ ID *id;
+
+ for (id = lb->first; id; id = id->next) {
+ if (id->override_static != NULL && id->lib == NULL) {
+ BKE_override_static_update(bmain, id);
+ }
+ }
+ }
+}
+
+/***********************************************************************************************************************
+ * Storage (how to wtore overriding data into .blend files).
+ *
+ * Basically:
+ * I) Only 'differential' storage needs special handling here. All others (replacing values or
+ * inserting/removing items from a collection) can be handled with simply storing current content of local data-block.
+ * II) We store the differential value into a second 'ghost' data-block, which is an empty ID of same type as local one,
+ * where we only define values that need differential data.
+ *
+ * This avoids us having to modify 'real' data-block at write time (and retoring it afterwards), which is inneficient,
+ * and potentially dangerous (in case of concurrent access...), while not using much extra memory in typical cases.
+ * It also ensures stored data-block always contains exact same data as "desired" ones (kind of "baked" data-blocks).
+ */
+
+/** Initialize an override storage. */
+OverrideStaticStorage *BKE_override_static_operations_store_initialize(void)
+{
+ return BKE_main_new();
+}
+
+/**
+ * Generate suitable 'write' data (this only affects differential override operations).
+ *
+ * Note that \a local ID is no more modified by this call, all extra data are stored in its temp \a storage_id copy. */
+ID *BKE_override_static_operations_store_start(OverrideStaticStorage *override_storage, ID *local)
+{
+ BLI_assert(local->override_static != NULL);
+ BLI_assert(override_storage != NULL);
+ const bool is_template = (local->override_static->reference == NULL);
+
+ if (is_template) {
+ /* This is actually purely local data with an override template, nothing to do here! */
+ return NULL;
+ }
+
+ /* Forcefully ensure we know about all needed override operations. */
+ BKE_override_static_operations_create(local);
+
+ ID *storage_id;
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_START_AVERAGED(BKE_override_operations_store_start);
+#endif
+
+ /* XXX TODO We may also want a specialized handling of things here too, to avoid copying heavy never-overridable
+ * data (like Mesh geometry etc.)? And also maybe avoid lib refcounting completely (shallow copy...). */
+ /* This would imply change in handling of usercout all over RNA (and possibly all over Blender code).
+ * Not impossible to do, but would rather see first is extra useless usual user handling is actually
+ * a (performances) issue here, before doing it. */
+ id_copy((Main *)override_storage, local, &storage_id, false);
+
+ if (storage_id != NULL) {
+ PointerRNA rnaptr_reference, rnaptr_final, rnaptr_storage;
+ RNA_id_pointer_create(local->override_static->reference, &rnaptr_reference);
+ RNA_id_pointer_create(local, &rnaptr_final);
+ RNA_id_pointer_create(storage_id, &rnaptr_storage);
+
+ if (!RNA_struct_override_store(&rnaptr_final, &rnaptr_reference, &rnaptr_storage, local->override_static)) {
+ BKE_libblock_free_ex(override_storage, storage_id, true, false);
+ storage_id = NULL;
+ }
+ }
+
+ local->override_static->storage = storage_id;
+
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_END_AVERAGED(BKE_override_operations_store_start);
+#endif
+ return storage_id;
+}
+
+/** Restore given ID modified by \a BKE_override_operations_store_start, to its original state. */
+void BKE_override_static_operations_store_end(OverrideStaticStorage *UNUSED(override_storage), ID *local)
+{
+ BLI_assert(local->override_static != NULL);
+
+ /* Nothing else to do here really, we need to keep all temp override storage data-blocks in memory until
+ * whole file is written anyway (otherwise we'd get mem pointers overlap...). */
+ local->override_static->storage = NULL;
+}
+
+void BKE_override_static_operations_store_finalize(OverrideStaticStorage *override_storage)
+{
+ /* We cannot just call BKE_main_free(override_storage), not until we have option to make 'ghost' copies of IDs
+ * without increasing usercount of used data-blocks... */
+ ListBase *lbarray[MAX_LIBARRAY];
+ int base_count, i;
+
+ base_count = set_listbasepointers(override_storage, lbarray);
+
+ for (i = 0; i < base_count; i++) {
+ ListBase *lb = lbarray[i];
+ ID *id;
+
+ while ((id = lb->first)) {
+ BKE_libblock_free_ex(override_storage, id, true, false);
+ }
+ }
+
+ BKE_main_free(override_storage);
+}
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index f6101498aca..e25a354c8af 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -52,6 +52,7 @@
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_object_force.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_sensor_types.h"
@@ -61,6 +62,8 @@
#include "DNA_sound_types.h"
#include "DNA_text_types.h"
#include "DNA_vfont_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_world_types.h"
#include "BLI_utildefines.h"
@@ -69,8 +72,10 @@
#include "BLI_linklist_stack.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
+#include "BKE_group.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -82,6 +87,7 @@
#include "BKE_sca.h"
#include "BKE_sequencer.h"
#include "BKE_tracking.h"
+#include "BKE_workspace.h"
#define FOREACH_FINALIZE _finalize
@@ -368,6 +374,10 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
#define CALLBACK_INVOKE(check_id_super, cb_flag) \
FOREACH_CALLBACK_INVOKE(&data, check_id_super, cb_flag)
+ if (id->override_static != NULL) {
+ CALLBACK_INVOKE_ID(id->override_static->reference, IDWALK_CB_USER | IDWALK_CB_STATIC_OVERRIDE_REFERENCE);
+ }
+
for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) {
data.self_id = id;
data.cb_flag = ID_IS_LINKED(id) ? IDWALK_CB_INDIRECT_USAGE : 0;
@@ -402,8 +412,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
{
Scene *scene = (Scene *) id;
ToolSettings *toolsett = scene->toolsettings;
- SceneRenderLayer *srl;
- Base *base;
CALLBACK_INVOKE(scene->camera, IDWALK_CB_NOP);
CALLBACK_INVOKE(scene->world, IDWALK_CB_USER);
@@ -417,31 +425,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
* since basact is just a pointer to one of those items. */
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_CB_USER);
- }
- if (srl->light_override) {
- 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_CB_NOP);
- }
- }
- for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
- if (fls->group) {
- CALLBACK_INVOKE(fls->group, IDWALK_CB_USER);
- }
- if (fls->linestyle) {
- CALLBACK_INVOKE(fls->linestyle, IDWALK_CB_USER);
- }
- }
- }
-
if (scene->ed) {
Sequence *seq;
SEQP_BEGIN(scene->ed, seq)
@@ -461,8 +444,39 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
- for (base = scene->base.first; base; base = base->next) {
- CALLBACK_INVOKE(base->object, IDWALK_CB_USER);
+ 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
+
+ ViewLayer *view_layer;
+ for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ CALLBACK_INVOKE(base->object, IDWALK_NOP);
+ }
+
+ for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) {
+ if (fmc->script) {
+ CALLBACK_INVOKE(fmc->script, IDWALK_CB_NOP);
+ }
+ }
+
+ for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) {
+ if (fls->group) {
+ CALLBACK_INVOKE(fls->group, IDWALK_CB_USER);
+ }
+
+ if (fls->linestyle) {
+ CALLBACK_INVOKE(fls->linestyle, IDWALK_CB_USER);
+ }
+ }
}
for (TimeMarker *marker = scene->markers.first; marker; marker = marker->next) {
@@ -624,31 +638,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
for (i = 0; i < mesh->totcol; i++) {
CALLBACK_INVOKE(mesh->mat[i], IDWALK_CB_USER);
}
-
- /* XXX Really not happy with this - probably texface should rather use some kind of
- * 'texture slots' and just set indices in each poly/face item - would also save some memory.
- * Maybe a nice TODO for blender2.8? */
- if (mesh->mtface || mesh->mtpoly) {
- for (i = 0; i < mesh->pdata.totlayer; i++) {
- if (mesh->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)mesh->pdata.layers[i].data;
-
- for (int j = 0; j < mesh->totpoly; j++, txface++) {
- CALLBACK_INVOKE(txface->tpage, IDWALK_CB_USER_ONE);
- }
- }
- }
-
- for (i = 0; i < mesh->fdata.totlayer; i++) {
- if (mesh->fdata.layers[i].type == CD_MTFACE) {
- MTFace *tface = (MTFace *)mesh->fdata.layers[i].data;
-
- for (int j = 0; j < mesh->totface; j++, tface++) {
- CALLBACK_INVOKE(tface->tpage, IDWALK_CB_USER_ONE);
- }
- }
- }
- }
break;
}
@@ -691,6 +680,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
library_foreach_ID_as_subdata_link((ID **)&material->nodetree, callback, user_data, flag, &data);
}
CALLBACK_INVOKE(material->group, IDWALK_CB_USER);
+ CALLBACK_INVOKE(material->edit_image, IDWALK_CB_USER);
break;
}
@@ -751,13 +741,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
break;
}
- case ID_SCR:
- {
- bScreen *screen = (bScreen *) id;
- CALLBACK_INVOKE(screen->scene, IDWALK_CB_USER_ONE);
- break;
- }
-
case ID_WO:
{
World *world = (World *) id;
@@ -780,13 +763,21 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
break;
}
+ case ID_LP:
+ {
+ LightProbe *probe = (LightProbe *) id;
+ CALLBACK_INVOKE(probe->image, IDWALK_CB_USER);
+ break;
+ }
+
case ID_GR:
{
Group *group = (Group *) id;
- GroupObject *gob;
- for (gob = group->gobject.first; gob; gob = gob->next) {
- CALLBACK_INVOKE(gob->ob, IDWALK_CB_USER_ONE);
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ CALLBACK_INVOKE(object, IDWALK_CB_USER_ONE);
}
+ FOREACH_GROUP_OBJECT_END
break;
}
@@ -968,6 +959,38 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
}
break;
}
+
+ case ID_WM:
+ {
+ wmWindowManager *wm = (wmWindowManager *)id;
+
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ ID *workspace = (ID *)BKE_workspace_active_get(win->workspace_hook);
+
+ CALLBACK_INVOKE(win->scene, IDWALK_CB_USER_ONE);
+
+ CALLBACK_INVOKE_ID(workspace, IDWALK_CB_NOP);
+ /* allow callback to set a different workspace */
+ BKE_workspace_active_set(win->workspace_hook, (WorkSpace *)workspace);
+ }
+ break;
+ }
+
+ case ID_WS:
+ {
+ WorkSpace *workspace = (WorkSpace *)id;
+ ListBase *layouts = BKE_workspace_layouts_get(workspace);
+
+ for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) {
+ bScreen *screen = BKE_workspace_layout_screen_get(layout);
+
+ CALLBACK_INVOKE(screen, IDWALK_CB_NOP);
+ /* allow callback to set a different screen */
+ BKE_workspace_layout_screen_set(layout, screen);
+ }
+
+ break;
+ }
case ID_GD:
{
bGPdata *gpencil = (bGPdata *) id;
@@ -979,11 +1002,11 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
}
/* Nothing needed for those... */
+ case ID_SCR:
case ID_IM:
case ID_VF:
case ID_TXT:
case ID_SO:
- case ID_WM:
case ID_PAL:
case ID_PC:
case ID_CF:
@@ -1111,6 +1134,9 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
return ELEM(id_type_used, ID_MC); /* WARNING! mask->parent.id, not typed. */
case ID_LS:
return (ELEM(id_type_used, ID_TE, ID_OB));
+ case ID_LP:
+ return ELEM(id_type_used, ID_IM);
+ case ID_WS:
case ID_IM:
case ID_VF:
case ID_TXT:
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 62cc5108b4e..fb672cb8b9f 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -53,6 +53,7 @@
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_speaker_types.h"
@@ -60,6 +61,7 @@
#include "DNA_text_types.h"
#include "DNA_vfont_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_world_types.h"
#include "BLI_blenlib.h"
@@ -71,8 +73,8 @@
#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"
#include "BKE_font.h"
#include "BKE_group.h"
@@ -83,7 +85,9 @@
#include "BKE_key.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
+#include "BKE_library_override.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
#include "BKE_linestyle.h"
@@ -99,6 +103,7 @@
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
+#include "BKE_lightprobe.h"
#include "BKE_sca.h"
#include "BKE_speaker.h"
#include "BKE_sound.h"
@@ -106,8 +111,12 @@
#include "BKE_scene.h"
#include "BKE_text.h"
#include "BKE_texture.h"
+#include "BKE_workspace.h"
#include "BKE_world.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -173,6 +182,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
}
if (*id_p && (*id_p == old_id)) {
+ const bool is_reference = (cb_flag & IDWALK_CB_STATIC_OVERRIDE_REFERENCE) != 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,
@@ -183,6 +193,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id));
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_reference = (id_remap_data->flag & ID_REMAP_SKIP_STATIC_OVERRIDE) != 0;
const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0;
#ifdef DEBUG_PRINT
@@ -197,7 +208,8 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
/* Special hack in case it's Object->data and we are in edit mode (skipped_direct too). */
if ((is_never_null && skip_never_null) ||
(is_obj_editmode && (((Object *)id)->data == *id_p)) ||
- (skip_indirect && is_indirect))
+ (skip_indirect && is_indirect) ||
+ (is_reference && skip_reference))
{
if (is_indirect) {
id_remap_data->skipped_indirect++;
@@ -210,7 +222,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
}
}
}
- else if (is_never_null || is_obj_editmode) {
+ else if (is_never_null || is_obj_editmode || is_reference) {
id_remap_data->skipped_direct++;
}
else {
@@ -227,7 +239,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
else {
if (!is_never_null) {
*id_p = new_id;
- DAG_id_tag_update_ex(id_remap_data->bmain, id_self, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update_ex(id_remap_data->bmain, id_self, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
if (cb_flag & IDWALK_CB_USER) {
id_us_min(old_id);
@@ -250,17 +262,15 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
}
/* Some remapping 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)
+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 {
- id_us_min((ID *)base->object);
- BKE_scene_base_unlink(sce, base);
- MEM_freeN(base);
+ BKE_collections_object_remove(r_id_remap_data->bmain, &sce->id, ob, false);
if (!is_indirect) {
r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
@@ -281,22 +291,18 @@ 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;
- for (base = sce->base.first; base; base = base_next) {
- base_next = base->next;
- libblock_remap_data_preprocess_scene_base_unlink(
- r_id_remap_data, sce, base, skip_indirect, is_indirect);
+ 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
}
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);
-
- if (base) {
- libblock_remap_data_preprocess_scene_base_unlink(
- r_id_remap_data, sce, base, skip_indirect, is_indirect);
- }
+ libblock_remap_data_preprocess_scene_object_unlink(
+ r_id_remap_data, sce, old_ob, skip_indirect, is_indirect);
}
}
break;
@@ -338,7 +344,7 @@ static void libblock_remap_data_postprocess_object_update(Main *bmain, Object *o
}
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 {
@@ -348,7 +354,7 @@ static void libblock_remap_data_postprocess_object_update(Main *bmain, Object *o
if (old_ob->type == OB_MBALL) {
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->type == OB_MBALL && BKE_mball_is_basis_for(ob, old_ob)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
}
@@ -358,26 +364,21 @@ 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;
- }
+ FOREACH_SCENE_OBJECT(sce, ob)
+ {
+ 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;
}
}
}
+ FOREACH_SCENE_OBJECT_END
}
static void libblock_remap_data_postprocess_obdata_relink(Main *UNUSED(bmain), Object *ob, ID *new_id)
@@ -592,8 +593,8 @@ void BKE_libblock_remap_locked(
libblock_remap_data_postprocess_nodetree_update(bmain, new_id);
BKE_main_lock(bmain);
- /* Full rebuild of DAG! */
- DAG_relations_tag_update(bmain);
+ /* Full rebuild of DEG! */
+ DEG_relations_tag_update(bmain);
}
void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
@@ -745,6 +746,10 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user)
MEM_freeN(id->properties);
}
+ if (id->override_static) {
+ BKE_override_static_free(&id->override_static);
+ }
+
/* XXX TODO remove animdata handling from each type's freeing func, and do it here, like for copy! */
}
@@ -809,6 +814,9 @@ void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
case ID_SPK:
BKE_speaker_free((Speaker *)id);
break;
+ case ID_LP:
+ BKE_lightprobe_free((LightProbe *)id);
+ break;
case ID_SO:
BKE_sound_free((bSound *)id);
break;
@@ -855,6 +863,9 @@ void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
case ID_CF:
BKE_cachefile_free((CacheFile *)id);
break;
+ case ID_WS:
+ BKE_workspace_free((WorkSpace *)id);
+ break;
}
}
@@ -893,7 +904,7 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i
const short type = GS(id->name);
if (bmain && (flag & LIB_ID_FREE_NO_DEG_TAG) == 0) {
- DAG_id_type_tag(bmain, type);
+ DEG_id_type_tag(bmain, type);
}
#ifdef WITH_PYTHON
@@ -956,11 +967,16 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b
short type = GS(id->name);
ListBase *lb = which_libbase(bmain, type);
- DAG_id_type_tag(bmain, type);
+ DEG_id_type_tag(bmain, type);
#ifdef WITH_PYTHON
+#ifdef WITH_PYTHON_SAFETY
BPY_id_release(id);
#endif
+ if (id->py_instance) {
+ BPY_DECREF_RNA_INVALIDATE(id->py_instance);
+ }
+#endif
if (do_id_user) {
BKE_libblock_relink_ex(bmain, id, NULL, NULL, true);
diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c
new file mode 100644
index 00000000000..d5dbbe873a2
--- /dev/null
+++ b/source/blender/blenkernel/intern/lightprobe.c
@@ -0,0 +1,100 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/lightprobe.c
+ * \ingroup bke
+ */
+
+#include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_animsys.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_lightprobe.h"
+
+void BKE_lightprobe_init(LightProbe *probe)
+{
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(probe, id));
+
+ probe->grid_resolution_x = probe->grid_resolution_y = probe->grid_resolution_z = 4;
+ probe->distinf = 2.5f;
+ probe->distpar = 2.5f;
+ probe->falloff = 0.2f;
+ probe->clipsta = 0.8f;
+ probe->clipend = 40.0f;
+ probe->vis_bias = 1.0f;
+ probe->vis_blur = 0.2f;
+ probe->data_draw_size = 1.0f;
+
+ probe->flag = LIGHTPROBE_FLAG_SHOW_INFLUENCE | LIGHTPROBE_FLAG_SHOW_DATA;
+}
+
+void *BKE_lightprobe_add(Main *bmain, const char *name)
+{
+ LightProbe *probe;
+
+ probe = BKE_libblock_alloc(bmain, ID_LP, name, 0);
+
+ BKE_lightprobe_init(probe);
+
+ return probe;
+}
+
+/**
+ * Only copy internal data of LightProbe ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_lightprobe_copy_data(
+ Main *UNUSED(bmain), LightProbe *UNUSED(probe_dst), const LightProbe *UNUSED(probe_src), const int UNUSED(flag))
+{
+ /* Nothing to do here. */
+}
+
+LightProbe *BKE_lightprobe_copy(Main *bmain, const LightProbe *probe)
+{
+ LightProbe *probe_copy;
+ BKE_id_copy_ex(bmain, &probe->id, (ID **)&probe_copy, 0, false);
+ return probe_copy;
+}
+
+void BKE_lightprobe_make_local(Main *bmain, LightProbe *probe, const bool lib_local)
+{
+ BKE_id_make_local_generic(bmain, &probe->id, true, lib_local);
+}
+
+void BKE_lightprobe_free(LightProbe *probe)
+{
+ BKE_animdata_free((ID *)probe, false);
+}
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 0465c5d54f7..2fc4c81cb0b 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -215,12 +215,13 @@ void BKE_linestyle_make_local(struct Main *bmain, FreestyleLineStyle *linestyle,
FreestyleLineStyle *BKE_linestyle_active_from_scene(Scene *scene)
{
- SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleConfig *config = &actsrl->freestyleConfig;
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
-
- if (lineset) {
- return lineset->linestyle;
+ ViewLayer *active_render_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ if (active_render_layer) {
+ FreestyleConfig *config = &active_render_layer->freestyle_config;
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
+ if (lineset) {
+ return lineset->linestyle;
+ }
}
return NULL;
}
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index b8a241ed956..eaa2f89ab82 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -51,7 +51,6 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -62,6 +61,8 @@
#include "BKE_movieclip.h"
#include "BKE_image.h"
+#include "DEG_depsgraph_build.h"
+
static struct {
ListBase splines;
struct GHash *id_hash;
@@ -818,7 +819,7 @@ Mask *BKE_mask_new(Main *bmain, const char *name)
mask->sfra = 1;
mask->efra = 100;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
return mask;
}
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index 0d71cc548c7..f60d87f2464 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -42,10 +42,11 @@
#include "DNA_mask_types.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_mask.h"
+#include "DEG_depsgraph.h"
+
unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
{
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 147b169910e..585567b6665 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -58,7 +58,6 @@
#include "BKE_animsys.h"
#include "BKE_displist.h"
#include "BKE_global.h"
-#include "BKE_depsgraph.h"
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_library.h"
@@ -73,6 +72,8 @@
#include "BKE_editmesh.h"
#include "BKE_font.h"
+#include "DEG_depsgraph_build.h"
+
#include "GPU_material.h"
/* used in UI and render */
@@ -206,6 +207,8 @@ void BKE_material_init(Material *ma)
ma->mode2 = MA_CASTSHADOW;
ma->shade_flag = MA_APPROX_OCCLUSION;
ma->preview = NULL;
+
+ ma->alpha_threshold = 0.5f;
}
Material *BKE_material_add(Main *bmain, const char *name)
@@ -257,6 +260,8 @@ void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_sr
}
BLI_listbase_clear(&ma_dst->gpumaterial);
+
+ /* TODO Duplicate Engine Settings and set runtime to NULL */
}
Material *BKE_material_copy(Main *bmain, const Material *ma)
@@ -299,6 +304,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;
}
@@ -454,7 +461,7 @@ void BKE_material_resize_id(Main *bmain, ID *id, short totcol, bool do_id_user)
}
*totcolp = totcol;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
void BKE_material_append_id(Main *bmain, ID *id, Material *ma)
@@ -471,7 +478,7 @@ void BKE_material_append_id(Main *bmain, ID *id, Material *ma)
id_us_plus((ID *)ma);
test_all_objects_materials(bmain, id);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
}
@@ -505,7 +512,7 @@ Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i, bool update_data
material_data_index_remove_id(id, index);
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
}
@@ -532,7 +539,7 @@ void BKE_material_clear_id(Main *bmain, ID *id, bool update_data)
material_data_index_clear_id(id);
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
}
@@ -627,7 +634,7 @@ void BKE_material_resize_object(Main *bmain, Object *ob, const short totcol, boo
if (ob->totcol && ob->actcol == 0) ob->actcol = 1;
if (ob->actcol > ob->totcol) ob->actcol = ob->totcol;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
void test_object_materials(Object *ob, ID *id)
@@ -967,7 +974,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
if (needtang) ma->mode |= MA_NORMAP_TANG;
else ma->mode &= ~MA_NORMAP_TANG;
- if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) {
+ if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) {
needuv = 1;
if (r_mode & R_OSA) ma->texco |= TEXCO_OSA; /* for texfaces */
}
@@ -1149,61 +1156,6 @@ bool material_in_material(Material *parmat, Material *mat)
/* ****************** */
-/* Update drivers for materials in a nodetree */
-static void material_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime)
-{
- bNode *node;
-
- /* nodetree itself */
- if (ntree->adt && ntree->adt->drivers.first) {
- BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* nodes */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id) {
- if (GS(node->id->name) == ID_MA) {
- material_drivers_update(scene, (Material *)node->id, ctime);
- }
- else if (node->type == NODE_GROUP) {
- material_node_drivers_update(scene, (bNodeTree *)node->id, ctime);
- }
- }
- }
-}
-
-/* Calculate all drivers for materials
- * FIXME: this is really a terrible method which may result in some things being calculated
- * multiple times. However, without proper despgraph support for these things, we are forced
- * into this sort of thing...
- */
-void material_drivers_update(Scene *scene, Material *ma, float ctime)
-{
- //if (G.f & G_DEBUG)
- // printf("material_drivers_update(%s, %s)\n", scene->id.name, ma->id.name);
-
- /* Prevent infinite recursion by checking (and tagging the material) as having been visited already
- * (see BKE_scene_update_tagged()). This assumes ma->id.tag & LIB_TAG_DOIT isn't set by anything else
- * in the meantime... [#32017]
- */
- if (ma->id.tag & LIB_TAG_DOIT)
- return;
-
- ma->id.tag |= LIB_TAG_DOIT;
-
- /* material itself */
- if (ma->adt && ma->adt->drivers.first) {
- BKE_animsys_evaluate_animdata(scene, &ma->id, ma->adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* nodes */
- if (ma->nodetree) {
- material_node_drivers_update(scene, ma->nodetree, ctime);
- }
-
- ma->id.tag &= ~LIB_TAG_DOIT;
-}
-
bool BKE_object_material_slot_remove(Object *ob)
{
Material *mao, ***matarar;
@@ -1328,6 +1280,14 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
bool use_nodes = BKE_scene_use_new_shading_nodes(scene);
bool is_bi = BKE_scene_uses_blender_internal(scene) || BKE_scene_uses_blender_game(scene);
+
+ /* XXX, for 2.8 testing & development its useful to have non Cycles/BI engines use material nodes
+ * In the future we may have some way to check this which each engine can define.
+ * For now use material slots for Clay/Eevee.
+ * - Campbell */
+ if (!(use_nodes || is_bi)) {
+ is_bi = true;
+ }
if (!ma)
return;
@@ -1726,6 +1686,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;
}
@@ -1781,501 +1742,40 @@ void paste_matcopybuf(Material *ma)
ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, G.main, false);
}
-
-/*********************** texface to material convert functions **********************/
-/* encode all the TF information into a single int */
-static int encode_tfaceflag(MTFace *tf, int convertall)
-{
- /* calculate the flag */
- int flag = tf->mode;
-
- /* options that change the material offline render */
- if (!convertall) {
- flag &= ~TF_OBCOL;
- }
-
- /* clean flags that are not being converted */
- flag &= ~TF_TEX;
- flag &= ~TF_SHAREDVERT;
- flag &= ~TF_SHAREDCOL;
- flag &= ~TF_CONVERTED;
-
- /* light tface flag is ignored in GLSL mode */
- flag &= ~TF_LIGHT;
-
- /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */
- flag |= tf->transp << 15;
-
- /* increase 1 so flag 0 is different than no flag yet */
- return flag + 1;
-}
-
-/* set the material options based in the tface flag */
-static void decode_tfaceflag(Material *ma, int flag, int convertall)
-{
- int alphablend;
- GameSettings *game = &ma->game;
-
- /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
- flag -= 1;
-
- alphablend = flag >> 15; /* encoded in the encode_tfaceflag function */
- (*game).flag = 0;
-
- /* General Material Options */
- if ((flag & TF_DYNAMIC) == 0) (*game).flag |= GEMAT_NOPHYSICS;
-
- /* Material Offline Rendering Properties */
- if (convertall) {
- if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR;
- }
-
- /* Special Face Properties */
- if ((flag & TF_TWOSIDE) == 0) (*game).flag |= GEMAT_BACKCULL;
- if (flag & TF_INVISIBLE) (*game).flag |= GEMAT_INVISIBLE;
- if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT;
-
- /* Face Orientation */
- if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO;
- else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD;
- else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW;
-
- /* Alpha Blend */
- if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT;
- else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA;
- else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD;
- else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP;
-}
-
-/* boolean check to see if the mesh needs a material */
-static int check_tfaceneedmaterial(int flag)
-{
- /* check if the flags we have are not deprecated != than default material options
- * also if only flags are visible and collision see if all objects using this mesh have this option in physics */
-
- /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
- flag -= 1;
-
- /* deprecated flags */
- flag &= ~TF_OBCOL;
- flag &= ~TF_SHAREDVERT;
- flag &= ~TF_SHAREDCOL;
-
- /* light tface flag is ignored in GLSL mode */
- flag &= ~TF_LIGHT;
-
- /* automatic detected if tex image has alpha */
- flag &= ~(TF_ALPHA << 15);
- /* automatic detected if using texture */
- flag &= ~TF_TEX;
-
- /* settings for the default NoMaterial */
- if (flag == TF_DYNAMIC)
- return 0;
-
- else
- return 1;
-}
-
-/* return number of digits of an integer */
-/* XXX to be optmized or replaced by an equivalent blender internal function */
-static int integer_getdigits(int number)
-{
- int i = 0;
- if (number == 0) return 1;
-
- while (number != 0) {
- number = (int)(number / 10);
- i++;
- }
- return i;
-}
-
-static void calculate_tface_materialname(char *matname, char *newname, int flag)
-{
- /* if flag has only light and collision and material matches those values
- * you can do strcpy(name, mat_name);
- * otherwise do: */
- int digits = integer_getdigits(flag);
- /* clamp the old name, remove the MA prefix and add the .TF.flag suffix
- * e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */
- BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME - (digits + 5), matname, digits, flag);
-}
-
-/* returns -1 if no match */
-static short mesh_getmaterialnumber(Mesh *me, Material *ma)
+struct Image *BKE_object_material_edit_image_get(Object *ob, short mat_nr)
{
- short a;
-
- for (a = 0; a < me->totcol; a++) {
- if (me->mat[a] == ma) {
- return a;
- }
- }
-
- return -1;
+ Material *ma = give_current_material(ob, mat_nr + 1);
+ return ma ? ma->edit_image : NULL;
}
-/* append material */
-static short mesh_addmaterial(Mesh *me, Material *ma)
+struct Image **BKE_object_material_edit_image_get_array(Object *ob)
{
- BKE_material_append_id(G.main, &me->id, NULL);
- me->mat[me->totcol - 1] = ma;
-
- id_us_plus(&ma->id);
-
- return me->totcol - 1;
-}
-
-static void set_facetexture_flags(Material *ma, Image *image)
-{
- if (image) {
- ma->mode |= MA_FACETEXTURE;
- /* we could check if the texture has alpha, but then more meshes sharing the same
- * material may need it. Let's make it simple. */
- if (BKE_image_has_alpha(image))
- ma->mode |= MA_FACETEXTURE_ALPHA;
- }
-}
-
-/* returns material number */
-static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag)
-{
- Material *ma;
- char idname[MAX_ID_NAME];
- short mat_nr = -1;
-
- /* new material, the name uses the flag*/
- BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag);
-
- if ((ma = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
- mat_nr = mesh_getmaterialnumber(me, ma);
- /* assign the material to the mesh */
- if (mat_nr == -1) mat_nr = mesh_addmaterial(me, ma);
-
- /* if needed set "Face Textures [Alpha]" Material options */
- set_facetexture_flags(ma, tf->tpage);
- }
- /* create a new material */
- else {
- ma = BKE_material_add(main, idname + 2);
-
- if (ma) {
- printf("TexFace Convert: Material \"%s\" created.\n", idname + 2);
- mat_nr = mesh_addmaterial(me, ma);
-
- /* if needed set "Face Textures [Alpha]" Material options */
- set_facetexture_flags(ma, tf->tpage);
-
- decode_tfaceflag(ma, flag, 1);
- /* the final decoding will happen after, outside the main loop
- * for now store the flag into the material and change light/tex/collision
- * store the flag as a negative number */
- ma->game.flag = -flag;
- id_us_min((ID *)ma);
- }
- else {
- printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2);
- }
+ Image **image_array = MEM_mallocN(sizeof(Material *) * ob->totcol, __func__);
+ for (int i = 0; i < ob->totcol; i++) {
+ image_array[i] = BKE_object_material_edit_image_get(ob, i);
}
-
- /* set as converted, no need to go bad to this face */
- tf->mode |= TF_CONVERTED;
- return mat_nr;
+ return image_array;
}
-/* Function to fully convert materials */
-static void convert_tfacematerial(Main *main, Material *ma)
+bool BKE_object_material_edit_image_set(Object *ob, short mat_nr, Image *image)
{
- Mesh *me;
- Material *mat_new;
- MFace *mf;
- MTFace *tf;
- int flag, index;
- int a;
- short mat_nr;
- CustomDataLayer *cdl;
- char idname[MAX_ID_NAME];
-
- for (me = main->mesh.first; me; me = me->id.next) {
- /* check if this mesh uses this material */
- for (a = 0; a < me->totcol; a++)
- if (me->mat[a] == ma) break;
-
- /* no material found */
- if (a == me->totcol) continue;
-
- /* get the active tface layer */
- index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
- cdl = (index == -1) ? NULL : &me->fdata.layers[index];
- if (!cdl) continue;
-
- /* loop over all the faces and stop at the ones that use the material*/
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- if (me->mat[mf->mat_nr] != ma) continue;
-
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
- flag = encode_tfaceflag(tf, 1);
-
- /* the name of the new material */
- calculate_tface_materialname(ma->id.name, (char *)&idname, flag);
-
- if ((mat_new = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
- /* material already existent, see if the mesh has it */
- mat_nr = mesh_getmaterialnumber(me, mat_new);
- /* material is not in the mesh, add it */
- if (mat_nr == -1) mat_nr = mesh_addmaterial(me, mat_new);
- }
- /* create a new material */
- else {
- mat_new = BKE_material_copy(main, ma);
- if (mat_new) {
- /* rename the material*/
- BLI_strncpy(mat_new->id.name, idname, sizeof(mat_new->id.name));
- id_us_min((ID *)mat_new);
-
- mat_nr = mesh_addmaterial(me, mat_new);
- decode_tfaceflag(mat_new, flag, 1);
- }
- else {
- printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", idname + 2, me->id.name + 2);
- mat_nr = mf->mat_nr;
- continue;
- }
- }
-
- /* if the material has a texture but no texture channel
- * set "Face Textures [Alpha]" Material options
- * actually we need to run it always, because of old behavior
- * of using face texture if any texture channel was present (multitex) */
- //if ((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex))
- set_facetexture_flags(mat_new, tf->tpage);
-
- /* set the material number to the face*/
- mf->mat_nr = mat_nr;
- }
- /* remove material from mesh */
- for (a = 0; a < me->totcol; ) {
- if (me->mat[a] == ma) {
- BKE_material_pop_id(main, &me->id, a, true);
- }
- else {
- a++;
- }
- }
+ Material *ma = give_current_material(ob, mat_nr + 1);
+ if (ma) {
+ /* both may be NULL */
+ id_us_min((ID *)ma->edit_image);
+ ma->edit_image = image;
+ id_us_plus((ID *)ma->edit_image);
+ return true;
}
+ return false;
}
-
-#define MAT_BGE_DISPUTED -99999
-
-int do_version_tface(Main *main)
+void BKE_material_eval(const struct EvaluationContext *UNUSED(eval_ctx), Material *material)
{
- Mesh *me;
- Material *ma;
- MFace *mf;
- MTFace *tf;
- CustomDataLayer *cdl;
- int a;
- int flag;
- int index;
-
- /* Operator in help menu has been removed for 2.7x */
- int fileload = 1;
-
- /* sometimes mesh has no materials but will need a new one. In those
- * cases we need to ignore the mf->mat_nr and only look at the face
- * mode because it can be zero as uninitialized or the 1st created material
- */
- int nomaterialslots;
-
- /* alert to user to check the console */
- int nowarning = 1;
-
- /* mark all the materials to conversion with a flag
- * if there is tface create a complete flag for that storing in flag
- * if there is tface and flag > 0: creates a new flag based on this face
- * if flags are different set flag to -1
- */
-
- /* 1st part: marking mesh materials to update */
- for (me = main->mesh.first; me; me = me->id.next) {
- if (ID_IS_LINKED(me)) continue;
-
- /* get the active tface layer */
- index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
- cdl = (index == -1) ? NULL : &me->fdata.layers[index];
- if (!cdl) continue;
-
- nomaterialslots = (me->totcol == 0 ? 1 : 0);
-
- /* loop over all the faces*/
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
-
- /* conversion should happen only once */
- if (fileload)
- tf->mode &= ~TF_CONVERTED;
- else {
- if ((tf->mode & TF_CONVERTED)) continue;
- else tf->mode |= TF_CONVERTED;
- }
-
- /* no material slots */
- if (nomaterialslots) {
- flag = encode_tfaceflag(tf, 1);
-
- /* create/find a new material and assign to the face */
- if (check_tfaceneedmaterial(flag)) {
- mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
- }
- /* else mark them as no-material to be reverted to 0 later */
- else {
- mf->mat_nr = -1;
- }
- }
- else if (mf->mat_nr < me->totcol) {
- ma = me->mat[mf->mat_nr];
-
- /* no material create one if necessary */
- if (!ma) {
- /* find a new material and assign to the face */
- flag = encode_tfaceflag(tf, 1);
-
- /* create/find a new material and assign to the face */
- if (check_tfaceneedmaterial(flag))
- mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
-
- continue;
- }
-
- /* we can't read from this if it comes from a library,
- * at doversion time: direct_link might not have happened on it,
- * so ma->mtex is not pointing to valid memory yet.
- * later we could, but it's better not */
- else if (ID_IS_LINKED(ma))
- continue;
-
- /* material already marked as disputed */
- else if (ma->game.flag == MAT_BGE_DISPUTED)
- continue;
-
- /* found a material */
- else {
- flag = encode_tfaceflag(tf, ((fileload) ? 0 : 1));
-
- /* first time changing this material */
- if (ma->game.flag == 0)
- ma->game.flag = -flag;
-
- /* mark material as disputed */
- else if (ma->game.flag != -flag) {
- ma->game.flag = MAT_BGE_DISPUTED;
- continue;
- }
-
- /* material ok so far */
- else {
- ma->game.flag = -flag;
-
- /* some people uses multitexture with TexFace by creating a texture
- * channel which not necessarily the tf->tpage image. But the game engine
- * was enabling it. Now it's required to set "Face Texture [Alpha] in the
- * material settings. */
- if (!fileload)
- set_facetexture_flags(ma, tf->tpage);
- }
- }
- }
- else {
- continue;
- }
- }
-
- /* if we didn't have material slot and now we do, we need to
- * make sure the materials are correct */
- if (nomaterialslots) {
- if (me->totcol > 0) {
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- if (mf->mat_nr == -1) {
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
- mf->mat_nr = convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1));
- }
- }
- }
- else {
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- mf->mat_nr = 0;
- }
- }
- }
-
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s (%p)\n", __func__, material->id.name, material);
}
-
- /* 2nd part - conversion */
- /* skip library files */
-
- /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */
- for (ma = main->mat.first, a = 0; ma; ma = ma->id.next, a++) {
- if (ID_IS_LINKED(ma)) continue;
-
- /* disputed material */
- if (ma->game.flag == MAT_BGE_DISPUTED) {
- ma->game.flag = 0;
- if (fileload) {
- printf("Warning: material \"%s\" skipped.\n", ma->id.name + 2);
- nowarning = 0;
- }
- else {
- convert_tfacematerial(main, ma);
- }
- continue;
- }
-
- /* no conflicts in this material - 90% of cases
- * convert from tface system to material */
- else if (ma->game.flag < 0) {
- decode_tfaceflag(ma, -(ma->game.flag), 1);
-
- /* material is good make sure all faces using
- * this material are set to converted */
- if (fileload) {
- for (me = main->mesh.first; me; me = me->id.next) {
- /* check if this mesh uses this material */
- for (a = 0; a < me->totcol; a++)
- if (me->mat[a] == ma) break;
-
- /* no material found */
- if (a == me->totcol) continue;
-
- /* get the active tface layer */
- index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
- cdl = (index == -1) ? NULL : &me->fdata.layers[index];
- if (!cdl) continue;
-
- /* loop over all the faces and stop at the ones that use the material*/
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- if (me->mat[mf->mat_nr] == ma) {
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
- tf->mode |= TF_CONVERTED;
- }
- }
- }
- }
- }
- /* material is not used by faces with texface
- * set the default flag - do it only once */
- else {
- if (fileload) {
- ma->game.flag = GEMAT_BACKCULL;
- }
- }
+ if ((BLI_listbase_is_empty(&material->gpumaterial) == false)) {
+ GPU_material_uniform_buffer_tag_dirty(&material->gpumaterial);
}
-
- return nowarning;
}
-
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index dfc49c996b1..5a0ac86823f 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -57,7 +57,6 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_scene.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -67,6 +66,8 @@
#include "BKE_object.h"
#include "BKE_material.h"
+//#include "DEG_depsgraph.h"
+
/* Functions */
/** Free (or release) any data used by this mball (does not free the mball itself). */
@@ -74,6 +75,8 @@ void BKE_mball_free(MetaBall *mb)
{
BKE_animdata_free((ID *)mb, false);
+ BKE_mball_batch_cache_free(mb);
+
MEM_SAFE_FREE(mb->mat);
BLI_freelistN(&mb->elems);
@@ -119,6 +122,7 @@ void BKE_mball_copy_data(Main *UNUSED(bmain), MetaBall *mb_dst, const MetaBall *
mb_dst->editelems = NULL;
mb_dst->lastelem = NULL;
+ mb_dst->batch_cache = NULL;
}
MetaBall *BKE_mball_copy(Main *bmain, const MetaBall *mb)
@@ -325,7 +329,7 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
int basisnr, obnr;
char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
SceneBaseIter iter;
- EvaluationContext *eval_ctx = G.main->eval_ctx;
+ struct EvaluationContext *eval_ctx = G.main->eval_ctx;
BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.');
@@ -362,27 +366,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 (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (Base *base = view_layer->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;
+ }
}
}
}
@@ -539,7 +541,51 @@ void BKE_mball_select_swap(struct MetaBall *mb)
/* **** Depsgraph evaluation **** */
-void BKE_mball_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+void BKE_mball_eval_geometry(const struct EvaluationContext *UNUSED(eval_ctx),
MetaBall *UNUSED(mball))
{
}
+
+/* Draw Engine */
+
+/* use for draw-manager only. */
+void BKE_mball_element_calc_display_m3x4(float r_scale_xform[3][4],
+ const float obmat[4][4],
+ const float local_pos[3])
+{
+ float world_pos[3], scamat[3][3];
+ mul_v3_m4v3(world_pos, obmat, local_pos);
+ copy_m3_m4(scamat, obmat);
+ {
+ /* Get the normalized inverse matrix to extract only
+ * the scale of Scamat */
+ float iscamat[3][3];
+ invert_m3_m3(iscamat, scamat);
+ normalize_m3(iscamat);
+ mul_m3_m3_post(scamat, iscamat);
+ }
+
+ copy_v3_v3(r_scale_xform[0], scamat[0]);
+ copy_v3_v3(r_scale_xform[1], scamat[1]);
+ copy_v3_v3(r_scale_xform[2], scamat[2]);
+
+ r_scale_xform[0][3] = world_pos[0];
+ r_scale_xform[1][3] = world_pos[1];
+ r_scale_xform[2][3] = world_pos[2];
+}
+
+void (*BKE_mball_batch_cache_dirty_cb)(MetaBall *mb, int mode) = NULL;
+void (*BKE_mball_batch_cache_free_cb)(MetaBall *mb) = NULL;
+
+void BKE_mball_batch_cache_dirty(MetaBall *mb, int mode)
+{
+ if (mb->batch_cache) {
+ BKE_mball_batch_cache_dirty_cb(mb, mode);
+ }
+}
+void BKE_mball_batch_cache_free(MetaBall *mb)
+{
+ if (mb->batch_cache) {
+ BKE_mball_batch_cache_free_cb(mb);
+ }
+}
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index a1ae3a7f572..5e63b5c1607 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -48,11 +48,12 @@
#include "BKE_global.h"
-#include "BKE_depsgraph.h"
#include "BKE_scene.h"
#include "BKE_displist.h"
#include "BKE_mball_tessellate.h" /* own include */
+#include "DEG_depsgraph.h"
+
#include "BLI_strict_flags.h"
/* experimental (faster) normal calculation */
@@ -1055,7 +1056,7 @@ static void polygonize(PROCESS *process)
* Iterates over ALL objects in the scene and all of its sets, including
* making all duplis(not only metas). Copies metas to mainb array.
* Computes bounding boxes for building BVH. */
-static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob)
+static void init_meta(const EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob)
{
Scene *sce_iter = scene;
Base *base;
@@ -1080,7 +1081,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;
@@ -1232,7 +1233,7 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen
}
}
-void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
+void BKE_mball_polygonize(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
{
MetaBall *mb;
DispList *dl;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 0d01fe77453..8f41f0611d4 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -59,7 +59,6 @@
#include "BKE_multires.h"
#include "BKE_key.h"
#include "BKE_mball.h"
-#include "BKE_depsgraph.h"
/* these 2 are only used by conversion functions */
#include "BKE_curve.h"
/* -- */
@@ -127,7 +126,7 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
for (i = 0; i < c1->totlayer; i++) {
if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
{
i1++;
}
@@ -135,7 +134,7 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
for (i = 0; i < c2->totlayer; i++) {
if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
{
i2++;
}
@@ -149,14 +148,14 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
i1 = 0; i2 = 0;
for (i = 0; i < tot; i++) {
while (i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
{
i1++;
l1++;
}
while (i2 < c2->totlayer && !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
{
i2++;
l2++;
@@ -324,7 +323,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
* Callers could also check but safer to do here - campbell */
}
else {
- const int tottex_original = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
+ const int tottex_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
const int totcol_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
const int tottex_tessface = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
@@ -335,7 +334,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
{
BKE_mesh_tessface_clear(me);
- CustomData_from_bmeshpoly(&me->fdata, &me->pdata, &me->ldata, me->totface);
+ CustomData_from_bmeshpoly(&me->fdata, &me->ldata, me->totface);
/* TODO - add some --debug-mesh option */
if (G.debug & G_DEBUG) {
@@ -344,7 +343,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
* and check if there was any data to begin with, for now just print the warning with
* some info to help troubleshoot whats going on - campbell */
printf("%s: warning! Tessellation uvs or vcol data got out of sync, "
- "had to reset!\n CD_MTFACE: %d != CD_MTEXPOLY: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n",
+ "had to reset!\n CD_MTFACE: %d != CD_MLOOPUV: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n",
__func__, tottex_tessface, tottex_original, totcol_tessface, totcol_original);
}
}
@@ -388,6 +387,48 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
}
}
+bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me)
+{
+ BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL;
+ bool changed = false;
+ if (bm) {
+ if (!CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
+ BM_data_layer_add(bm, &bm->pdata, CD_FACEMAP);
+ changed = true;
+ }
+ }
+ else {
+ if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
+ CustomData_add_layer(&me->pdata,
+ CD_FACEMAP,
+ CD_DEFAULT,
+ NULL,
+ me->totpoly);
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+bool BKE_mesh_clear_facemap_customdata(struct Mesh *me)
+{
+ BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL;
+ bool changed = false;
+ if (bm) {
+ if (CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
+ BM_data_layer_free(bm, &bm->pdata, CD_FACEMAP);
+ changed = true;
+ }
+ }
+ else {
+ if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
+ CustomData_free_layers(&me->pdata, CD_FACEMAP, me->totpoly);
+ changed = true;
+ }
+ }
+ return changed;
+}
+
/* this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or
* mloopcol and mcol) have the same relative active/render/clone/mask indices.
*
@@ -396,14 +437,11 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
* versions of the mesh. - campbell*/
static void mesh_update_linked_customdata(Mesh *me, const bool do_ensure_tess_cd)
{
- if (me->edit_btmesh)
- BKE_editmesh_update_linked_customdata(me->edit_btmesh);
-
if (do_ensure_tess_cd) {
mesh_ensure_tessellation_customdata(me);
}
- CustomData_bmesh_update_active_layers(&me->fdata, &me->pdata, &me->ldata);
+ CustomData_bmesh_update_active_layers(&me->fdata, &me->ldata);
}
void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd)
@@ -422,7 +460,6 @@ void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd)
me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
- me->mtpoly = CustomData_get_layer(&me->pdata, CD_MTEXPOLY);
me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
}
@@ -442,6 +479,8 @@ void BKE_mesh_free(Mesh *me)
{
BKE_animdata_free(&me->id, false);
+ BKE_mesh_batch_cache_free(me);
+
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
@@ -529,6 +568,7 @@ void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int
BKE_mesh_update_customdata_pointers(me_dst, do_tessface);
me_dst->edit_btmesh = NULL;
+ me_dst->batch_cache = NULL;
me_dst->mselect = MEM_dupallocN(me_dst->mselect);
me_dst->bb = MEM_dupallocN(me_dst->bb);
@@ -586,33 +626,44 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int
ldata = &me->ldata;
fdata = &me->fdata;
}
- cdlp = &pdata->layers[poly_index];
+
cdlu = &ldata->layers[loop_index];
- cdlf = fdata && do_tessface ? &fdata->layers[face_index] : NULL;
+ cdlp = (poly_index != -1) ? &pdata->layers[poly_index] : NULL;
+ cdlf = (face_index != -1) && fdata && do_tessface ? &fdata->layers[face_index] : NULL;
- if (cdlp->name != new_name) {
+ if (cdlu->name != new_name) {
/* Mesh validate passes a name from the CD layer as the new name,
* Avoid memcpy from self to self in this case.
*/
- BLI_strncpy(cdlp->name, new_name, sizeof(cdlp->name));
- CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers);
+ BLI_strncpy(cdlu->name, new_name, sizeof(cdlu->name));
+ CustomData_set_layer_unique_name(ldata, loop_index);
+ }
+
+ if (cdlp == NULL && cdlf == NULL) {
+ return false;
}
/* Loop until we do have exactly the same name for all layers! */
- for (i = 1; !STREQ(cdlp->name, cdlu->name) || (cdlf && !STREQ(cdlp->name, cdlf->name)); i++) {
+ for (i = 1;
+ (cdlp && !STREQ(cdlu->name, cdlp->name)) ||
+ (cdlf && !STREQ(cdlu->name, cdlf->name));
+ i++)
+ {
switch (i % step) {
case 0:
- BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name));
- CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers);
+ if (cdlp) {
+ BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name));
+ CustomData_set_layer_unique_name(pdata, poly_index);
+ }
break;
case 1:
BLI_strncpy(cdlu->name, cdlp->name, sizeof(cdlu->name));
- CustomData_set_layer_unique_name(ldata, cdlu - ldata->layers);
+ CustomData_set_layer_unique_name(ldata, loop_index);
break;
case 2:
if (cdlf) {
- BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name));
- CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers);
+ BLI_strncpy(cdlf->name, cdlu->name, sizeof(cdlf->name));
+ CustomData_set_layer_unique_name(fdata, face_index);
}
break;
}
@@ -623,66 +674,44 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int
bool BKE_mesh_uv_cdlayer_rename(Mesh *me, const char *old_name, const char *new_name, bool do_tessface)
{
- CustomData *pdata, *ldata, *fdata;
+ CustomData *ldata, *fdata;
if (me->edit_btmesh) {
- pdata = &me->edit_btmesh->bm->pdata;
ldata = &me->edit_btmesh->bm->ldata;
/* No tessellated data in BMesh! */
fdata = NULL;
do_tessface = false;
}
else {
- pdata = &me->pdata;
ldata = &me->ldata;
fdata = &me->fdata;
do_tessface = (do_tessface && fdata->totlayer);
}
{
- const int pidx_start = CustomData_get_layer_index(pdata, CD_MTEXPOLY);
const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV);
const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1;
- int pidx = CustomData_get_named_layer(pdata, CD_MTEXPOLY, old_name);
int lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name);
int fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1;
/* None of those cases should happen, in theory!
* Note this assume we have the same number of mtexpoly, mloopuv and mtface layers!
*/
- if (pidx == -1) {
- if (lidx == -1) {
- if (fidx == -1) {
- /* No layer found with this name! */
- return false;
- }
- else {
- lidx = fidx;
- }
- }
- pidx = lidx;
- }
- else {
- if (lidx == -1) {
- lidx = pidx;
+ if (lidx == -1) {
+ if (fidx == -1) {
+ /* No layer found with this name! */
+ return false;
}
- if (fidx == -1 && do_tessface) {
- fidx = pidx;
+ else {
+ lidx = fidx;
}
}
-#if 0
- /* For now, we do not consider mismatch in indices (i.e. same name leading to (relative) different indices). */
- else if (pidx != lidx) {
- lidx = pidx;
- }
-#endif
/* Go back to absolute indices! */
- pidx += pidx_start;
lidx += lidx_start;
if (fidx != -1)
fidx += fidx_start;
- return BKE_mesh_uv_cdlayer_rename_index(me, pidx, lidx, fidx, new_name, do_tessface);
+ return BKE_mesh_uv_cdlayer_rename_index(me, -1, lidx, fidx, new_name, do_tessface);
}
}
@@ -760,6 +789,18 @@ void BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_rot[3], float r_siz
if (r_size) copy_v3_v3(r_size, me->size);
}
+void BKE_mesh_texspace_get_reference(Mesh *me, short **r_texflag, float **r_loc, float **r_rot, float **r_size)
+{
+ if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) {
+ BKE_mesh_texspace_calc(me);
+ }
+
+ if (r_texflag != NULL) *r_texflag = &me->texflag;
+ if (r_loc != NULL) *r_loc = me->loc;
+ if (r_rot != NULL) *r_rot = me->rot;
+ if (r_size != NULL) *r_size = me->size;
+}
+
void BKE_mesh_texspace_copy_from_object(Mesh *me, Object *ob)
{
float *texloc, *texrot, *texsize;
@@ -1382,7 +1423,6 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
if (alluv) {
const char *uvname = "Orco";
- me->mtpoly = CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname);
me->mloopuv = CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, me->totloop, uvname);
}
@@ -1591,10 +1631,10 @@ void BKE_mesh_to_curve_nurblist(DerivedMesh *dm, ListBase *nurblist, const int e
}
}
-void BKE_mesh_to_curve(Scene *scene, Object *ob)
+void BKE_mesh_to_curve(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
/* make new mesh data from the original copy */
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_MESH);
+ DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_MESH);
ListBase nurblist = {NULL, NULL};
bool needsFree = false;
@@ -2373,7 +2413,7 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
/* settings: 1 - preview, 2 - render */
Mesh *BKE_mesh_new_from_object(
- Main *bmain, Scene *sce, Object *ob,
+ const EvaluationContext *eval_ctx, Main *bmain, Scene *sce, Object *ob,
int apply_modifiers, int settings, int calc_tessface, int calc_undeformed)
{
Mesh *tmpmesh;
@@ -2427,7 +2467,7 @@ Mesh *BKE_mesh_new_from_object(
copycu->editnurb = tmpcu->editnurb;
/* get updated display list, and convert to a mesh */
- BKE_displist_make_curveTypes_forRender(sce, tmpobj, &dispbase, &derivedFinal, false, render);
+ BKE_displist_make_curveTypes_forRender(eval_ctx, sce, tmpobj, &dispbase, &derivedFinal, false, render);
copycu->editfont = NULL;
copycu->editnurb = NULL;
@@ -2478,13 +2518,7 @@ Mesh *BKE_mesh_new_from_object(
if (render) {
ListBase disp = {NULL, NULL};
- /* TODO(sergey): This is gonna to work for until EvaluationContext
- * only contains for_render flag. As soon as CoW is
- * implemented, this is to be rethinked.
- */
- EvaluationContext eval_ctx;
- DEG_evaluation_context_init(&eval_ctx, DAG_EVAL_RENDER);
- BKE_displist_make_mball_forRender(&eval_ctx, sce, ob, &disp);
+ BKE_displist_make_mball_forRender(eval_ctx, sce, ob, &disp);
BKE_mesh_from_metaball(&disp, tmpmesh);
BKE_displist_free(&disp);
}
@@ -2523,9 +2557,9 @@ Mesh *BKE_mesh_new_from_object(
/* Write the display mesh into the dummy mesh */
if (render)
- dm = mesh_create_derived_render(sce, ob, mask);
+ dm = mesh_create_derived_render(eval_ctx, sce, ob, mask);
else
- dm = mesh_create_derived_view(sce, ob, mask);
+ dm = mesh_create_derived_view(eval_ctx, sce, ob, mask);
tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2);
DM_to_mesh(dm, tmpmesh, ob, mask, true);
@@ -2616,7 +2650,7 @@ Mesh *BKE_mesh_new_from_object(
/* **** Depsgraph evaluation **** */
-void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+void BKE_mesh_eval_geometry(const EvaluationContext *UNUSED(eval_ctx),
Mesh *mesh)
{
if (G.debug & G_DEBUG_DEPSGRAPH) {
@@ -2626,3 +2660,20 @@ void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
BKE_mesh_texspace_calc(mesh);
}
}
+
+/* Draw Engine */
+void (*BKE_mesh_batch_cache_dirty_cb)(Mesh *me, int mode) = NULL;
+void (*BKE_mesh_batch_cache_free_cb)(Mesh *me) = NULL;
+
+void BKE_mesh_batch_cache_dirty(Mesh *me, int mode)
+{
+ if (me->batch_cache) {
+ BKE_mesh_batch_cache_dirty_cb(me, mode);
+ }
+}
+void BKE_mesh_batch_cache_free(Mesh *me)
+{
+ if (me->batch_cache) {
+ BKE_mesh_batch_cache_free_cb(me);
+ }
+}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index a0df43ca102..c21c16adc85 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -1666,152 +1666,6 @@ void BKE_mesh_normals_loop_to_vertex(
/* -------------------------------------------------------------------- */
-/** \name Mesh Tangent Calculations
- * \{ */
-
-/* Tangent space utils. */
-
-/* User data. */
-typedef struct {
- const MPoly *mpolys; /* faces */
- const MLoop *mloops; /* faces's vertices */
- const MVert *mverts; /* vertices */
- const MLoopUV *luvs; /* texture coordinates */
- float (*lnors)[3]; /* loops' normals */
- float (*tangents)[4]; /* output tangents */
- int num_polys; /* number of polygons */
-} BKEMeshToTangent;
-
-/* Mikktspace's API */
-static int get_num_faces(const SMikkTSpaceContext *pContext)
-{
- BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
- return p_mesh->num_polys;
-}
-
-static int get_num_verts_of_face(const SMikkTSpaceContext *pContext, const int face_idx)
-{
- BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
- return p_mesh->mpolys[face_idx].totloop;
-}
-
-static void get_position(const SMikkTSpaceContext *pContext, float r_co[3], const int face_idx, const int vert_idx)
-{
- BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
- const int loop_idx = p_mesh->mpolys[face_idx].loopstart + vert_idx;
- copy_v3_v3(r_co, p_mesh->mverts[p_mesh->mloops[loop_idx].v].co);
-}
-
-static void get_texture_coordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_idx,
- const int vert_idx)
-{
- BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
- copy_v2_v2(r_uv, p_mesh->luvs[p_mesh->mpolys[face_idx].loopstart + vert_idx].uv);
-}
-
-static void get_normal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_idx, const int vert_idx)
-{
- BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
- copy_v3_v3(r_no, p_mesh->lnors[p_mesh->mpolys[face_idx].loopstart + vert_idx]);
-}
-
-static void set_tspace(const SMikkTSpaceContext *pContext, const float fv_tangent[3], const float face_sign,
- const int face_idx, const int vert_idx)
-{
- BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
- float *p_res = p_mesh->tangents[p_mesh->mpolys[face_idx].loopstart + vert_idx];
- copy_v3_v3(p_res, fv_tangent);
- p_res[3] = face_sign;
-}
-
-/**
- * Compute simplified tangent space normals, i.e. tangent vector + sign of bi-tangent one, which combined with
- * split normals can be used to recreate the full tangent space.
- * Note: * The mesh should be made of only tris and quads!
- */
-void BKE_mesh_loop_tangents_ex(
- const MVert *mverts, const int UNUSED(numVerts), const MLoop *mloops,
- float (*r_looptangent)[4], float (*loopnors)[3], const MLoopUV *loopuvs,
- const int UNUSED(numLoops), const MPoly *mpolys, const int numPolys,
- ReportList *reports)
-{
- BKEMeshToTangent mesh_to_tangent = {NULL};
- SMikkTSpaceContext s_context = {NULL};
- SMikkTSpaceInterface s_interface = {NULL};
-
- const MPoly *mp;
- int mp_index;
-
- /* First check we do have a tris/quads only mesh. */
- for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
- if (mp->totloop > 4) {
- BKE_report(reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting");
- return;
- }
- }
-
- /* Compute Mikktspace's tangent normals. */
- mesh_to_tangent.mpolys = mpolys;
- mesh_to_tangent.mloops = mloops;
- mesh_to_tangent.mverts = mverts;
- mesh_to_tangent.luvs = loopuvs;
- mesh_to_tangent.lnors = loopnors;
- mesh_to_tangent.tangents = r_looptangent;
- mesh_to_tangent.num_polys = numPolys;
-
- s_context.m_pUserData = &mesh_to_tangent;
- s_context.m_pInterface = &s_interface;
- s_interface.m_getNumFaces = get_num_faces;
- s_interface.m_getNumVerticesOfFace = get_num_verts_of_face;
- s_interface.m_getPosition = get_position;
- s_interface.m_getTexCoord = get_texture_coordinate;
- s_interface.m_getNormal = get_normal;
- s_interface.m_setTSpaceBasic = set_tspace;
-
- /* 0 if failed */
- if (genTangSpaceDefault(&s_context) == false) {
- BKE_report(reports, RPT_ERROR, "Mikktspace failed to generate tangents for this mesh!");
- }
-}
-
-/**
- * Wrapper around BKE_mesh_loop_tangents_ex, which takes care of most boiling code.
- * \note
- * - There must be a valid loop's CD_NORMALS available.
- * - The mesh should be made of only tris and quads!
- */
-void BKE_mesh_loop_tangents(Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], ReportList *reports)
-{
- MLoopUV *loopuvs;
- float (*loopnors)[3];
-
- /* Check we have valid texture coordinates first! */
- if (uvmap) {
- loopuvs = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvmap);
- }
- else {
- loopuvs = CustomData_get_layer(&mesh->ldata, CD_MLOOPUV);
- }
- if (!loopuvs) {
- BKE_reportf(reports, RPT_ERROR, "Tangent space computation needs an UVMap, \"%s\" not found, aborting", uvmap);
- return;
- }
-
- loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
- if (!loopnors) {
- BKE_report(reports, RPT_ERROR, "Tangent space computation needs loop normals, none found, aborting");
- return;
- }
-
- BKE_mesh_loop_tangents_ex(mesh->mvert, mesh->totvert, mesh->mloop, r_looptangents,
- loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports);
-}
-
-/** \} */
-
-
-/* -------------------------------------------------------------------- */
-
/** \name Polygon Calculations
* \{ */
@@ -2382,12 +2236,12 @@ void BKE_mesh_calc_volume(
*/
void BKE_mesh_loops_to_mface_corners(
CustomData *fdata, CustomData *ldata,
- CustomData *pdata, unsigned int lindex[4], int findex,
- const int polyindex,
+ CustomData *UNUSED(pdata), unsigned int lindex[4], int findex,
+ const int UNUSED(polyindex),
const int mf_len, /* 3 or 4 */
/* cache values to avoid lookups every time */
- const int numTex, /* CustomData_number_of_layers(pdata, CD_MTEXPOLY) */
+ const int numUV, /* CustomData_number_of_layers(ldata, CD_MLOOPUV) */
const int numCol, /* CustomData_number_of_layers(ldata, CD_MLOOPCOL) */
const bool hasPCol, /* CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL) */
const bool hasOrigSpace, /* CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP) */
@@ -2395,17 +2249,13 @@ void BKE_mesh_loops_to_mface_corners(
)
{
MTFace *texface;
- MTexPoly *texpoly;
MCol *mcol;
MLoopCol *mloopcol;
MLoopUV *mloopuv;
int i, j;
- for (i = 0; i < numTex; i++) {
+ for (i = 0; i < numUV; i++) {
texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
- texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i);
-
- ME_MTEXFACE_CPY(texface, texpoly);
for (j = 0; j < mf_len; j++) {
mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, (int)lindex[j], i);
@@ -2457,14 +2307,14 @@ void BKE_mesh_loops_to_mface_corners(
*
* \note when mface is not NULL, mface[face_index].v4 is used to test quads, else, loopindices[face_index][3] is used.
*/
-void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData *pdata, MFace *mface,
+void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, MFace *mface,
int *polyindices, unsigned int (*loopindices)[4], const int num_faces)
{
/* Note: performances are sub-optimal when we get a NULL mface, we could be ~25% quicker with dedicated code...
* Issue is, unless having two different functions with nearly the same code, there's not much ways to solve
* this. Better imho to live with it for now. :/ --mont29
*/
- const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+ const int numUV = CustomData_number_of_layers(ldata, CD_MLOOPUV);
const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
@@ -2474,17 +2324,14 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
const int *pidx;
unsigned int (*lidx)[4];
- for (i = 0; i < numTex; i++) {
+ for (i = 0; i < numUV; i++) {
MTFace *texface = CustomData_get_layer_n(fdata, CD_MTFACE, i);
- MTexPoly *texpoly = CustomData_get_layer_n(pdata, CD_MTEXPOLY, i);
MLoopUV *mloopuv = CustomData_get_layer_n(ldata, CD_MLOOPUV, i);
for (findex = 0, pidx = polyindices, lidx = loopindices;
findex < num_faces;
pidx++, lidx++, findex++, texface++)
{
- ME_MTEXFACE_CPY(texface, &texpoly[*pidx]);
-
for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
copy_v2_v2(texface->uv[j], mloopuv[(*lidx)[j]].uv);
}
@@ -2807,7 +2654,7 @@ int BKE_mesh_recalc_tessellation(
/* CD_ORIGINDEX will contain an array of indices from tessfaces to the polygons
* they are directly tessellated from */
CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface);
- CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
+ CustomData_from_bmeshpoly(fdata, ldata, totface);
if (do_face_nor_copy) {
/* If polys have a normals layer, copying that to faces can help
@@ -2828,7 +2675,7 @@ int BKE_mesh_recalc_tessellation(
* So we pass NULL as MFace pointer, and BKE_mesh_loops_to_tessdata will use the fourth loop index as quad test.
* ...
*/
- BKE_mesh_loops_to_tessdata(fdata, ldata, pdata, NULL, mface_to_poly_map, lindices, totface);
+ BKE_mesh_loops_to_tessdata(fdata, ldata, NULL, mface_to_poly_map, lindices, totface);
/* NOTE: quad detection issue - fourth vertidx vs fourth loopidx:
* ...However, most TFace code uses 'MFace->v4 == 0' test to check whether it is a tri or quad.
@@ -3007,7 +2854,7 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
MPoly *mp, *mpoly;
MFace *mface, *mf;
- const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+ const int numUV = CustomData_number_of_layers(ldata, CD_MLOOPUV);
const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
@@ -3047,7 +2894,7 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface);
- CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
+ CustomData_from_bmeshpoly(fdata, ldata, totface);
mp = mpoly;
k = 0;
@@ -3069,9 +2916,10 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
mf->v2 = mloop[mf->v2].v;
mf->v3 = mloop[mf->v3].v;
- BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
- lindex, k, i, 3,
- numTex, numCol, hasPCol, hasOrigSpace, hasLNor);
+ BKE_mesh_loops_to_mface_corners(
+ fdata, ldata, pdata,
+ lindex, k, i, 3,
+ numUV, numCol, hasPCol, hasOrigSpace, hasLNor);
test_index_face(mf, fdata, k, 3);
}
else {
@@ -3089,9 +2937,10 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
mf->v3 = mloop[mf->v3].v;
mf->v4 = mloop[mf->v4].v;
- BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
- lindex, k, i, 4,
- numTex, numCol, hasPCol, hasOrigSpace, hasLNor);
+ BKE_mesh_loops_to_mface_corners(
+ fdata, ldata, pdata,
+ lindex, k, i, 4,
+ numUV, numCol, hasPCol, hasOrigSpace, hasLNor);
test_index_face(mf, fdata, k, 4);
}
@@ -3106,11 +2955,11 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata,
#endif /* USE_BMESH_SAVE_AS_COMPAT */
-static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata,
- MFace *mface, int totloop, int findex, int loopstart, int numTex, int numCol)
+static void bm_corners_to_loops_ex(
+ ID *id, CustomData *fdata, CustomData *ldata,
+ MFace *mface, int totloop, int findex, int loopstart, int numTex, int numCol)
{
MTFace *texface;
- MTexPoly *texpoly;
MCol *mcol;
MLoopCol *mloopcol;
MLoopUV *mloopuv;
@@ -3121,9 +2970,6 @@ static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata,
for (i = 0; i < numTex; i++) {
texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
- texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, findex, i);
-
- ME_MTEXFACE_CPY(texpoly, texface);
mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
copy_v2_v2(mloopuv->uv, texface->uv[0]); mloopuv++;
@@ -3231,7 +3077,7 @@ void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh)
mesh->medge, mesh->mface,
&mesh->totloop, &mesh->totpoly, &mesh->mloop, &mesh->mpoly);
- CustomData_bmesh_do_versions_update_active_layers(&mesh->fdata, &mesh->pdata, &mesh->ldata);
+ CustomData_bmesh_do_versions_update_active_layers(&mesh->fdata, &mesh->ldata);
BKE_mesh_update_customdata_pointers(mesh, true);
}
@@ -3274,7 +3120,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData
CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop);
- CustomData_to_bmeshpoly(fdata, pdata, ldata, totloop, totpoly);
+ CustomData_to_bmeshpoly(fdata, ldata, totloop);
if (id) {
/* ensure external data is transferred */
@@ -3324,7 +3170,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData
# undef ML
- bm_corners_to_loops_ex(id, fdata, ldata, pdata, mface, totloop, i, mp->loopstart, numTex, numCol);
+ bm_corners_to_loops_ex(id, fdata, ldata, mface, totloop, i, mp->loopstart, numTex, numCol);
if (polyindex) {
*polyindex = i;
diff --git a/source/blender/blenkernel/intern/mesh_tangent.c b/source/blender/blenkernel/intern/mesh_tangent.c
new file mode 100644
index 00000000000..77288bd672e
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_tangent.c
@@ -0,0 +1,690 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/mesh_tangent.c
+ * \ingroup bke
+ *
+ * Functions to evaluate mesh tangents.
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_stack.h"
+#include "BLI_task.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_tangent.h"
+#include "BKE_report.h"
+
+#include "BLI_strict_flags.h"
+
+#include "atomic_ops.h"
+#include "mikktspace.h"
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Tangent Calculations (Single Layer)
+ * \{ */
+
+/* Tangent space utils. */
+
+/* User data. */
+typedef struct {
+ const MPoly *mpolys; /* faces */
+ const MLoop *mloops; /* faces's vertices */
+ const MVert *mverts; /* vertices */
+ const MLoopUV *luvs; /* texture coordinates */
+ float (*lnors)[3]; /* loops' normals */
+ float (*tangents)[4]; /* output tangents */
+ int num_polys; /* number of polygons */
+} BKEMeshToTangent;
+
+/* Mikktspace's API */
+static int get_num_faces(const SMikkTSpaceContext *pContext)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ return p_mesh->num_polys;
+}
+
+static int get_num_verts_of_face(const SMikkTSpaceContext *pContext, const int face_idx)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ return p_mesh->mpolys[face_idx].totloop;
+}
+
+static void get_position(const SMikkTSpaceContext *pContext, float r_co[3], const int face_idx, const int vert_idx)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ const int loop_idx = p_mesh->mpolys[face_idx].loopstart + vert_idx;
+ copy_v3_v3(r_co, p_mesh->mverts[p_mesh->mloops[loop_idx].v].co);
+}
+
+static void get_texture_coordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_idx,
+ const int vert_idx)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ copy_v2_v2(r_uv, p_mesh->luvs[p_mesh->mpolys[face_idx].loopstart + vert_idx].uv);
+}
+
+static void get_normal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_idx, const int vert_idx)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ copy_v3_v3(r_no, p_mesh->lnors[p_mesh->mpolys[face_idx].loopstart + vert_idx]);
+}
+
+static void set_tspace(const SMikkTSpaceContext *pContext, const float fv_tangent[3], const float face_sign,
+ const int face_idx, const int vert_idx)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ float *p_res = p_mesh->tangents[p_mesh->mpolys[face_idx].loopstart + vert_idx];
+ copy_v3_v3(p_res, fv_tangent);
+ p_res[3] = face_sign;
+}
+
+/**
+ * Compute simplified tangent space normals, i.e. tangent vector + sign of bi-tangent one, which combined with
+ * split normals can be used to recreate the full tangent space.
+ * Note: * The mesh should be made of only tris and quads!
+ */
+void BKE_mesh_calc_loop_tangent_single_ex(
+ const MVert *mverts, const int UNUSED(numVerts), const MLoop *mloops,
+ float (*r_looptangent)[4], float (*loopnors)[3], const MLoopUV *loopuvs,
+ const int UNUSED(numLoops), const MPoly *mpolys, const int numPolys,
+ ReportList *reports)
+{
+ BKEMeshToTangent mesh_to_tangent = {NULL};
+ SMikkTSpaceContext s_context = {NULL};
+ SMikkTSpaceInterface s_interface = {NULL};
+
+ const MPoly *mp;
+ int mp_index;
+
+ /* First check we do have a tris/quads only mesh. */
+ for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
+ if (mp->totloop > 4) {
+ BKE_report(reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting");
+ return;
+ }
+ }
+
+ /* Compute Mikktspace's tangent normals. */
+ mesh_to_tangent.mpolys = mpolys;
+ mesh_to_tangent.mloops = mloops;
+ mesh_to_tangent.mverts = mverts;
+ mesh_to_tangent.luvs = loopuvs;
+ mesh_to_tangent.lnors = loopnors;
+ mesh_to_tangent.tangents = r_looptangent;
+ mesh_to_tangent.num_polys = numPolys;
+
+ s_context.m_pUserData = &mesh_to_tangent;
+ s_context.m_pInterface = &s_interface;
+ s_interface.m_getNumFaces = get_num_faces;
+ s_interface.m_getNumVerticesOfFace = get_num_verts_of_face;
+ s_interface.m_getPosition = get_position;
+ s_interface.m_getTexCoord = get_texture_coordinate;
+ s_interface.m_getNormal = get_normal;
+ s_interface.m_setTSpaceBasic = set_tspace;
+
+ /* 0 if failed */
+ if (genTangSpaceDefault(&s_context) == false) {
+ BKE_report(reports, RPT_ERROR, "Mikktspace failed to generate tangents for this mesh!");
+ }
+}
+
+/**
+ * Wrapper around BKE_mesh_calc_loop_tangent_single_ex, which takes care of most boiling code.
+ * \note
+ * - There must be a valid loop's CD_NORMALS available.
+ * - The mesh should be made of only tris and quads!
+ */
+void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], ReportList *reports)
+{
+ MLoopUV *loopuvs;
+ float (*loopnors)[3];
+
+ /* Check we have valid texture coordinates first! */
+ if (uvmap) {
+ loopuvs = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvmap);
+ }
+ else {
+ loopuvs = CustomData_get_layer(&mesh->ldata, CD_MLOOPUV);
+ }
+ if (!loopuvs) {
+ BKE_reportf(reports, RPT_ERROR, "Tangent space computation needs an UVMap, \"%s\" not found, aborting", uvmap);
+ return;
+ }
+
+ loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+ if (!loopnors) {
+ BKE_report(reports, RPT_ERROR, "Tangent space computation needs loop normals, none found, aborting");
+ return;
+ }
+
+ BKE_mesh_calc_loop_tangent_single_ex(mesh->mvert, mesh->totvert, mesh->mloop, r_looptangents,
+ loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Tangent Calculations (All Layers)
+ * \{ */
+
+
+/* Necessary complexity to handle looptri's as quads for correct tangents */
+#define USE_LOOPTRI_DETECT_QUADS
+
+typedef struct {
+ const float (*precomputedFaceNormals)[3];
+ const float (*precomputedLoopNormals)[3];
+ const MLoopTri *looptri;
+ MLoopUV *mloopuv; /* texture coordinates */
+ const MPoly *mpoly; /* indices */
+ const MLoop *mloop; /* indices */
+ const MVert *mvert; /* vertices & normals */
+ const float (*orco)[3];
+ float (*tangent)[4]; /* destination */
+ int numTessFaces;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ /* map from 'fake' face index to looptri,
+ * quads will point to the first looptri of the quad */
+ const int *face_as_quad_map;
+ int num_face_as_quad_map;
+#endif
+
+} SGLSLMeshToTangent;
+
+/* interface */
+static int dm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
+{
+ SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ return pMesh->num_face_as_quad_map;
+#else
+ return pMesh->numTessFaces;
+#endif
+}
+
+static int dm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
+{
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
+ if (pMesh->face_as_quad_map) {
+ const MLoopTri *lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ return 4;
+ }
+ }
+ return 3;
+#else
+ UNUSED_VARS(pContext, face_num);
+ return 3;
+#endif
+}
+
+static void dm_ts_GetPosition(
+ const SMikkTSpaceContext *pContext, float r_co[3],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
+ const MLoopTri *lt;
+ uint loop_index;
+ const float *co;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ loop_index = (uint)(mp->loopstart + vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = &pMesh->looptri[face_num];
+ }
+#else
+ lt = &pMesh->looptri[face_num];
+#endif
+ loop_index = lt->tri[vert_index];
+
+finally:
+ co = pMesh->mvert[pMesh->mloop[loop_index].v].co;
+ copy_v3_v3(r_co, co);
+}
+
+static void dm_ts_GetTextureCoordinate(
+ const SMikkTSpaceContext *pContext, float r_uv[2],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
+ const MLoopTri *lt;
+ uint loop_index;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ loop_index = (uint)(mp->loopstart + vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = &pMesh->looptri[face_num];
+ }
+#else
+ lt = &pMesh->looptri[face_num];
+#endif
+ loop_index = lt->tri[vert_index];
+
+finally:
+ if (pMesh->mloopuv != NULL) {
+ const float *uv = pMesh->mloopuv[loop_index].uv;
+ copy_v2_v2(r_uv, uv);
+ }
+ else {
+ const float *orco = pMesh->orco[pMesh->mloop[loop_index].v];
+ map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
+ }
+}
+
+static void dm_ts_GetNormal(
+ const SMikkTSpaceContext *pContext, float r_no[3],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ const MLoopTri *lt;
+ uint loop_index;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ loop_index = (uint)(mp->loopstart + vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = &pMesh->looptri[face_num];
+ }
+#else
+ lt = &pMesh->looptri[face_num];
+#endif
+ loop_index = lt->tri[vert_index];
+
+finally:
+ if (pMesh->precomputedLoopNormals) {
+ copy_v3_v3(r_no, pMesh->precomputedLoopNormals[loop_index]);
+ }
+ else if ((pMesh->mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */
+ if (pMesh->precomputedFaceNormals) {
+ copy_v3_v3(r_no, pMesh->precomputedFaceNormals[lt->poly]);
+ }
+ else {
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ normal_quad_v3(
+ r_no,
+ pMesh->mvert[pMesh->mloop[mp->loopstart + 0].v].co,
+ pMesh->mvert[pMesh->mloop[mp->loopstart + 1].v].co,
+ pMesh->mvert[pMesh->mloop[mp->loopstart + 2].v].co,
+ pMesh->mvert[pMesh->mloop[mp->loopstart + 3].v].co);
+ }
+ else
+#endif
+ {
+ normal_tri_v3(
+ r_no,
+ pMesh->mvert[pMesh->mloop[lt->tri[0]].v].co,
+ pMesh->mvert[pMesh->mloop[lt->tri[1]].v].co,
+ pMesh->mvert[pMesh->mloop[lt->tri[2]].v].co);
+ }
+ }
+ }
+ else {
+ const short *no = pMesh->mvert[pMesh->mloop[loop_index].v].no;
+ normal_short_to_float_v3(r_no, no);
+ }
+}
+
+static void dm_ts_SetTSpace(
+ const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ const MLoopTri *lt;
+ uint loop_index;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ loop_index = (uint)(mp->loopstart + vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = &pMesh->looptri[face_num];
+ }
+#else
+ lt = &pMesh->looptri[face_num];
+#endif
+ loop_index = lt->tri[vert_index];
+
+ float *pRes;
+
+finally:
+ pRes = pMesh->tangent[loop_index];
+ copy_v3_v3(pRes, fvTangent);
+ pRes[3] = fSign;
+}
+
+static void DM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
+{
+ struct SGLSLMeshToTangent *mesh2tangent = taskdata;
+ /* new computation method */
+ {
+ SMikkTSpaceContext sContext = {NULL};
+ SMikkTSpaceInterface sInterface = {NULL};
+
+ sContext.m_pUserData = mesh2tangent;
+ sContext.m_pInterface = &sInterface;
+ sInterface.m_getNumFaces = dm_ts_GetNumFaces;
+ sInterface.m_getNumVerticesOfFace = dm_ts_GetNumVertsOfFace;
+ sInterface.m_getPosition = dm_ts_GetPosition;
+ sInterface.m_getTexCoord = dm_ts_GetTextureCoordinate;
+ sInterface.m_getNormal = dm_ts_GetNormal;
+ sInterface.m_setTSpaceBasic = dm_ts_SetTSpace;
+
+ /* 0 if failed */
+ genTangSpaceDefault(&sContext);
+ }
+}
+
+void BKE_mesh_add_loop_tangent_named_layer_for_uv(
+ CustomData *uv_data, CustomData *tan_data, int numLoopData,
+ const char *layer_name)
+{
+ if (CustomData_get_named_layer_index(tan_data, CD_TANGENT, layer_name) == -1 &&
+ CustomData_get_named_layer_index(uv_data, CD_MLOOPUV, layer_name) != -1)
+ {
+ CustomData_add_layer_named(
+ tan_data, CD_TANGENT, CD_CALLOC, NULL,
+ numLoopData, layer_name);
+ }
+}
+
+/**
+ * Here we get some useful information such as active uv layer name and search if it is already in tangent_names.
+ * Also, we calculate tangent_mask that works as a descriptor of tangents state.
+ * If tangent_mask has changed, then recalculate tangents.
+ */
+void BKE_mesh_calc_loop_tangent_step_0(
+ const CustomData *loopData, bool calc_active_tangent,
+ const char (*tangent_names)[MAX_NAME], int tangent_names_count,
+ bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
+ char *ract_uv_name, char *rren_uv_name, short *rtangent_mask) {
+ /* Active uv in viewport */
+ int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV);
+ *ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV);
+ ract_uv_name[0] = 0;
+ if (*ract_uv_n != -1) {
+ strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name);
+ }
+
+ /* Active tangent in render */
+ *rren_uv_n = CustomData_get_render_layer(loopData, CD_MLOOPUV);
+ rren_uv_name[0] = 0;
+ if (*rren_uv_n != -1) {
+ strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name);
+ }
+
+ /* If active tangent not in tangent_names we take it into account */
+ *rcalc_act = false;
+ *rcalc_ren = false;
+ for (int i = 0; i < tangent_names_count; i++) {
+ if (tangent_names[i][0] == 0) {
+ calc_active_tangent = true;
+ }
+ }
+ if (calc_active_tangent) {
+ *rcalc_act = true;
+ *rcalc_ren = true;
+ for (int i = 0; i < tangent_names_count; i++) {
+ if (STREQ(ract_uv_name, tangent_names[i]))
+ *rcalc_act = false;
+ if (STREQ(rren_uv_name, tangent_names[i]))
+ *rcalc_ren = false;
+ }
+ }
+ *rtangent_mask = 0;
+
+ const int uv_layer_num = CustomData_number_of_layers(loopData, CD_MLOOPUV);
+ for (int n = 0; n < uv_layer_num; n++) {
+ const char *name = CustomData_get_layer_name(loopData, CD_MLOOPUV, n);
+ bool add = false;
+ for (int i = 0; i < tangent_names_count; i++) {
+ if (tangent_names[i][0] && STREQ(tangent_names[i], name)) {
+ add = true;
+ break;
+ }
+ }
+ if (!add && ((*rcalc_act && ract_uv_name[0] && STREQ(ract_uv_name, name)) ||
+ (*rcalc_ren && rren_uv_name[0] && STREQ(rren_uv_name, name))))
+ {
+ add = true;
+ }
+ if (add)
+ *rtangent_mask |= (short)(1 << n);
+ }
+
+ if (uv_layer_num == 0)
+ *rtangent_mask |= DM_TANGENT_MASK_ORCO;
+}
+
+/**
+ * See: #BKE_editmesh_loop_tangent_calc (matching logic).
+ */
+void BKE_mesh_calc_loop_tangent_ex(
+ const MVert *mvert,
+ const MPoly *mpoly, const uint mpoly_len,
+ const MLoop *mloop,
+ const MLoopTri *looptri,
+ const uint looptri_len,
+
+ CustomData *loopdata,
+ bool calc_active_tangent,
+ const char (*tangent_names)[MAX_NAME], int tangent_names_len,
+ const float (*poly_normals)[3],
+ const float (*loop_normals)[3],
+ const float (*vert_orco)[3],
+ /* result */
+ CustomData *loopdata_out,
+ const uint loopdata_out_len,
+ short *tangent_mask_curr_p)
+{
+ int act_uv_n = -1;
+ int ren_uv_n = -1;
+ bool calc_act = false;
+ bool calc_ren = false;
+ char act_uv_name[MAX_NAME];
+ char ren_uv_name[MAX_NAME];
+ short tangent_mask = 0;
+ short tangent_mask_curr = *tangent_mask_curr_p;
+
+ BKE_mesh_calc_loop_tangent_step_0(
+ loopdata, calc_active_tangent, tangent_names, tangent_names_len,
+ &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
+ if ((tangent_mask_curr | tangent_mask) != tangent_mask_curr) {
+ /* Check we have all the needed layers */
+ /* Allocate needed tangent layers */
+ for (int i = 0; i < tangent_names_len; i++)
+ if (tangent_names[i][0])
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(loopdata, loopdata_out, (int)loopdata_out_len, tangent_names[i]);
+ if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(loopdata, CD_TANGENT, "") == -1)
+ CustomData_add_layer_named(loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, "");
+ if (calc_act && act_uv_name[0])
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(loopdata, loopdata_out, (int)loopdata_out_len, act_uv_name);
+ if (calc_ren && ren_uv_name[0])
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(loopdata, loopdata_out, (int)loopdata_out_len, ren_uv_name);
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ int num_face_as_quad_map;
+ int *face_as_quad_map = NULL;
+
+ /* map faces to quads */
+ if (looptri_len != mpoly_len) {
+ /* over alloc, since we dont know how many ngon or quads we have */
+
+ /* map fake face index to looptri */
+ face_as_quad_map = MEM_mallocN(sizeof(int) * looptri_len, __func__);
+ int k, j;
+ for (k = 0, j = 0; j < (int)looptri_len; k++, j++) {
+ face_as_quad_map[k] = j;
+ /* step over all quads */
+ if (mpoly[looptri[j].poly].totloop == 4) {
+ j++; /* skips the nest looptri */
+ }
+ }
+ num_face_as_quad_map = k;
+ }
+ else {
+ num_face_as_quad_map = (int)looptri_len;
+ }
+#endif
+
+ /* Calculation */
+ if (looptri_len != 0) {
+ TaskScheduler *scheduler = BLI_task_scheduler_get();
+ TaskPool *task_pool;
+ task_pool = BLI_task_pool_create(scheduler, NULL);
+
+ tangent_mask_curr = 0;
+ /* Calculate tangent layers */
+ SGLSLMeshToTangent data_array[MAX_MTFACE];
+ const int tangent_layer_num = CustomData_number_of_layers(loopdata_out, CD_TANGENT);
+ for (int n = 0; n < tangent_layer_num; n++) {
+ int index = CustomData_get_layer_index_n(loopdata_out, CD_TANGENT, n);
+ BLI_assert(n < MAX_MTFACE);
+ SGLSLMeshToTangent *mesh2tangent = &data_array[n];
+ mesh2tangent->numTessFaces = (int)looptri_len;
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ mesh2tangent->face_as_quad_map = face_as_quad_map;
+ mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
+#endif
+ mesh2tangent->mvert = mvert;
+ mesh2tangent->mpoly = mpoly;
+ mesh2tangent->mloop = mloop;
+ mesh2tangent->looptri = looptri;
+ /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
+ * have to check this is valid...
+ */
+ mesh2tangent->precomputedLoopNormals = loop_normals;
+ mesh2tangent->precomputedFaceNormals = poly_normals;
+
+ mesh2tangent->orco = NULL;
+ mesh2tangent->mloopuv = CustomData_get_layer_named(loopdata, CD_MLOOPUV, loopdata_out->layers[index].name);
+
+ /* Fill the resulting tangent_mask */
+ if (!mesh2tangent->mloopuv) {
+ mesh2tangent->orco = vert_orco;
+ if (!mesh2tangent->orco)
+ continue;
+
+ tangent_mask_curr |= DM_TANGENT_MASK_ORCO;
+ }
+ else {
+ int uv_ind = CustomData_get_named_layer_index(loopdata, CD_MLOOPUV, loopdata_out->layers[index].name);
+ int uv_start = CustomData_get_layer_index(loopdata, CD_MLOOPUV);
+ BLI_assert(uv_ind != -1 && uv_start != -1);
+ BLI_assert(uv_ind - uv_start < MAX_MTFACE);
+ tangent_mask_curr |= (short)(1 << (uv_ind - uv_start));
+ }
+
+ mesh2tangent->tangent = loopdata_out->layers[index].data;
+ BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
+ }
+
+ BLI_assert(tangent_mask_curr == tangent_mask);
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
+ }
+ else {
+ tangent_mask_curr = tangent_mask;
+ }
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (face_as_quad_map) {
+ MEM_freeN(face_as_quad_map);
+ }
+#undef USE_LOOPTRI_DETECT_QUADS
+
+#endif
+
+ *tangent_mask_curr_p = tangent_mask_curr;
+
+ /* Update active layer index */
+ int act_uv_index = CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, act_uv_n);
+ if (act_uv_index != -1) {
+ int tan_index = CustomData_get_named_layer_index(loopdata, CD_TANGENT, loopdata->layers[act_uv_index].name);
+ CustomData_set_layer_active_index(loopdata, CD_TANGENT, tan_index);
+ }/* else tangent has been built from orco */
+
+ /* Update render layer index */
+ int ren_uv_index = CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, ren_uv_n);
+ if (ren_uv_index != -1) {
+ int tan_index = CustomData_get_named_layer_index(loopdata, CD_TANGENT, loopdata->layers[ren_uv_index].name);
+ CustomData_set_layer_render_index(loopdata, CD_TANGENT, tan_index);
+ }/* else tangent has been built from orco */
+ }
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 4aeddbb4c45..54de843bc64 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -43,10 +43,11 @@
#include "BLI_math_vector.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_mesh.h"
+#include "DEG_depsgraph.h"
+
#include "MEM_guardedalloc.h"
/* loop v/e are unsigned, so using max uint_32 value as invalid marker... */
@@ -936,7 +937,7 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
{
bool is_valid = true;
bool is_change_v, is_change_e, is_change_l, is_change_p;
- int tot_texpoly, tot_uvloop, tot_vcolloop;
+ int tot_uvloop, tot_vcolloop;
CustomDataMask mask = check_meshmask ? CD_MASK_MESH : 0;
is_valid &= mesh_validate_customdata(vdata, mask, do_verbose, do_fixes, &is_change_v);
@@ -944,17 +945,8 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
is_valid &= mesh_validate_customdata(ldata, mask, do_verbose, do_fixes, &is_change_l);
is_valid &= mesh_validate_customdata(pdata, mask, do_verbose, do_fixes, &is_change_p);
- tot_texpoly = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
tot_uvloop = CustomData_number_of_layers(ldata, CD_MLOOPUV);
tot_vcolloop = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
- if (tot_texpoly != tot_uvloop) {
- PRINT_ERR("\tCustomDataLayer mismatch, tot_texpoly(%d), tot_uvloop(%d)\n",
- tot_texpoly, tot_uvloop);
- }
- if (tot_texpoly > MAX_MTFACE) {
- PRINT_ERR("\tMore UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n",
- MAX_MTFACE, tot_texpoly - MAX_MTFACE);
- }
if (tot_uvloop > MAX_MTFACE) {
PRINT_ERR("\tMore UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n",
MAX_MTFACE, tot_uvloop - MAX_MTFACE);
@@ -965,18 +957,10 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
}
/* check indices of clone/stencil */
- if (do_fixes && CustomData_get_clone_layer(pdata, CD_MTEXPOLY) >= tot_texpoly) {
- CustomData_set_layer_clone(pdata, CD_MTEXPOLY, 0);
- is_change_p = true;
- }
if (do_fixes && CustomData_get_clone_layer(ldata, CD_MLOOPUV) >= tot_uvloop) {
CustomData_set_layer_clone(ldata, CD_MLOOPUV, 0);
is_change_l = true;
}
- if (do_fixes && CustomData_get_stencil_layer(pdata, CD_MTEXPOLY) >= tot_texpoly) {
- CustomData_set_layer_stencil(pdata, CD_MTEXPOLY, 0);
- is_change_p = true;
- }
if (do_fixes && CustomData_get_stencil_layer(ldata, CD_MLOOPUV) >= tot_uvloop) {
CustomData_set_layer_stencil(ldata, CD_MLOOPUV, 0);
is_change_l = true;
@@ -1019,7 +1003,7 @@ int BKE_mesh_validate(Mesh *me, const int do_verbose, const int cddata_check_mas
&changed);
if (changed) {
- DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&me->id, OB_RECALC_DATA);
return true;
}
else {
@@ -1028,64 +1012,6 @@ int BKE_mesh_validate(Mesh *me, const int do_verbose, const int cddata_check_mas
}
/**
- * Duplicate of BM_mesh_cd_validate() for Mesh data.
- */
-void BKE_mesh_cd_validate(Mesh *me)
-{
- int totlayer_mtex = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
- int totlayer_uv = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
- int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
- int mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY);
- int uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV);
- int i;
-
- /* XXX For now, do not delete those, just warn they are not really usable. */
- if (UNLIKELY(totlayer_mtex > MAX_MTFACE)) {
- printf("WARNING! More UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n",
- MAX_MTFACE, totlayer_mtex - MAX_MTFACE);
- }
- if (UNLIKELY(totlayer_uv > MAX_MTFACE)) {
- printf("WARNING! More UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n",
- MAX_MTFACE, totlayer_uv - MAX_MTFACE);
- }
- if (UNLIKELY(totlayer_mcol > MAX_MCOL)) {
- printf("WARNING! More VCol layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n",
- MAX_MCOL, totlayer_mcol - MAX_MCOL);
- }
-
- if (LIKELY(totlayer_mtex == totlayer_uv)) {
- /* pass */
- }
- else if (totlayer_mtex < totlayer_uv) {
- do {
- const char *from_name = me->ldata.layers[uv_index + totlayer_mtex].name;
- CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, from_name);
- CustomData_set_layer_unique_name(&me->pdata, totlayer_mtex);
- } while (totlayer_uv != ++totlayer_mtex);
- mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY);
- }
- else if (totlayer_uv < totlayer_mtex) {
- do {
- const char *from_name = me->pdata.layers[mtex_index + totlayer_uv].name;
- CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, from_name);
- CustomData_set_layer_unique_name(&me->ldata, totlayer_uv);
- } while (totlayer_mtex != ++totlayer_uv);
- uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV);
- }
-
- BLI_assert(totlayer_mtex == totlayer_uv);
-
- /* Check uv/tex names match as well!!! */
- for (i = 0; i < totlayer_mtex; i++, mtex_index++, uv_index++) {
- const char *name_src = me->pdata.layers[mtex_index].name;
- const char *name_dst = me->ldata.layers[uv_index].name;
- if (!STREQ(name_src, name_dst)) {
- BKE_mesh_uv_cdlayer_rename_index(me, mtex_index, uv_index, -1, name_src, false);
- }
- }
-}
-
-/**
* Check all material indices of polygons are valid, invalid ones are set to 0.
* \returns is_valid.
*/
@@ -1105,7 +1031,7 @@ int BKE_mesh_validate_material_indices(Mesh *me)
}
if (!is_valid) {
- DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&me->id, OB_RECALC_DATA);
return true;
}
else {
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 1e7c3104d17..8eb1a7733c1 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -757,8 +757,8 @@ void modifier_path_init(char *path, int path_maxlen, const char *name)
/* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */
struct DerivedMesh *modwrap_applyModifier(
- ModifierData *md, Object *ob,
- struct DerivedMesh *dm,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, struct DerivedMesh *dm,
ModifierApplyFlag flag)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -767,12 +767,12 @@ struct DerivedMesh *modwrap_applyModifier(
if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
DM_ensure_normals(dm);
}
- return mti->applyModifier(md, ob, dm, flag);
+ return mti->applyModifier(md, eval_ctx, ob, dm, flag);
}
struct DerivedMesh *modwrap_applyModifierEM(
- ModifierData *md, Object *ob,
- struct BMEditMesh *em,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, struct BMEditMesh *em,
DerivedMesh *dm,
ModifierApplyFlag flag)
{
@@ -782,12 +782,12 @@ struct DerivedMesh *modwrap_applyModifierEM(
if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
DM_ensure_normals(dm);
}
- return mti->applyModifierEM(md, ob, em, dm, flag);
+ return mti->applyModifierEM(md, eval_ctx, ob, em, dm, flag);
}
void modwrap_deformVerts(
- ModifierData *md, Object *ob,
- DerivedMesh *dm,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts,
ModifierApplyFlag flag)
{
@@ -797,11 +797,11 @@ void modwrap_deformVerts(
if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
DM_ensure_normals(dm);
}
- mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag);
+ mti->deformVerts(md, eval_ctx, ob, dm, vertexCos, numVerts, flag);
}
void modwrap_deformVertsEM(
- ModifierData *md, Object *ob,
+ ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob,
struct BMEditMesh *em, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
@@ -811,6 +811,6 @@ void modwrap_deformVertsEM(
if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
DM_ensure_normals(dm);
}
- mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts);
+ mti->deformVertsEM(md, eval_ctx, ob, em, dm, vertexCos, numVerts);
}
/* end modifier callback wrappers */
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 9679b585e6f..7ef4b588dcd 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -276,14 +276,14 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level)
return mdisps;
}
-DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob)
+DerivedMesh *get_multires_dm(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd, Object *ob)
{
ModifierData *md = (ModifierData *)mmd;
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- DerivedMesh *tdm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+ DerivedMesh *tdm = mesh_get_derived_deform(eval_ctx, scene, ob, CD_MASK_BAREMESH);
DerivedMesh *dm;
- dm = mti->applyModifier(md, ob, tdm, MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY);
+ dm = mti->applyModifier(md, eval_ctx, ob, tdm, MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY);
if (dm == tdm) {
dm = CDDM_copy(tdm);
}
@@ -397,10 +397,10 @@ void multires_force_render_update(Object *ob)
multires_force_update(ob);
}
-int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd,
+int multiresModifier_reshapeFromDM(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd,
Object *ob, DerivedMesh *srcdm)
{
- DerivedMesh *mrdm = get_multires_dm(scene, mmd, ob);
+ DerivedMesh *mrdm = get_multires_dm(eval_ctx, scene, mmd, ob);
if (mrdm && srcdm && mrdm->getNumVerts(mrdm) == srcdm->getNumVerts(srcdm)) {
multires_mvert_to_ss(mrdm, srcdm->getVertArray(srcdm));
@@ -419,13 +419,13 @@ int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd,
}
/* Returns 1 on success, 0 if the src's totvert doesn't match */
-int multiresModifier_reshape(Scene *scene, MultiresModifierData *mmd, Object *dst, Object *src)
+int multiresModifier_reshape(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd, Object *dst, Object *src)
{
- DerivedMesh *srcdm = mesh_get_derived_final(scene, src, CD_MASK_BAREMESH);
- return multiresModifier_reshapeFromDM(scene, mmd, dst, srcdm);
+ DerivedMesh *srcdm = mesh_get_derived_final(eval_ctx, scene, src, CD_MASK_BAREMESH);
+ return multiresModifier_reshapeFromDM(eval_ctx, scene, mmd, dst, srcdm);
}
-int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mmd,
+int multiresModifier_reshapeFromDeformMod(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd,
Object *ob, ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -437,12 +437,12 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm
return 0;
/* Create DerivedMesh for deformation modifier */
- dm = get_multires_dm(scene, mmd, ob);
+ dm = get_multires_dm(eval_ctx, scene, mmd, ob);
numVerts = dm->getNumVerts(dm);
deformedVerts = MEM_mallocN(sizeof(float[3]) * numVerts, "multiresReshape_deformVerts");
dm->getVertCos(dm, deformedVerts);
- mti->deformVerts(md, ob, dm, deformedVerts, numVerts, 0);
+ mti->deformVerts(md, eval_ctx, ob, dm, deformedVerts, numVerts, 0);
ndm = CDDM_copy(dm);
CDDM_apply_vert_coords(ndm, deformedVerts);
@@ -451,7 +451,7 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm
dm->release(dm);
/* Reshaping */
- result = multiresModifier_reshapeFromDM(scene, mmd, ob, ndm);
+ result = multiresModifier_reshapeFromDM(eval_ctx, scene, mmd, ob, ndm);
/* Cleanup */
ndm->release(ndm);
@@ -2174,7 +2174,7 @@ static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst)
}
}
-static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3])
+static void multires_apply_smat(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float smat[3][3])
{
DerivedMesh *dm = NULL, *cddm = NULL, *subdm = NULL;
CCGElem **gridData, **subGridData;
@@ -2199,10 +2199,10 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3])
high_mmd.lvl = high_mmd.totlvl;
/* unscaled multires with applied displacement */
- subdm = get_multires_dm(scene, &high_mmd, ob);
+ subdm = get_multires_dm(eval_ctx, scene, &high_mmd, ob);
/* prepare scaled CDDM to create ccgDN */
- cddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+ cddm = mesh_get_derived_deform(eval_ctx, scene, ob, CD_MASK_BAREMESH);
totvert = cddm->getNumVerts(cddm);
vertCos = MEM_mallocN(sizeof(*vertCos) * totvert, "multiresScale vertCos");
@@ -2276,17 +2276,17 @@ int multires_mdisp_corners(MDisps *s)
return 0;
}
-void multiresModifier_scale_disp(Scene *scene, Object *ob)
+void multiresModifier_scale_disp(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
float smat[3][3];
/* object's scale matrix */
BKE_object_scale_to_mat3(ob, smat);
- multires_apply_smat(scene, ob, smat);
+ multires_apply_smat(eval_ctx, scene, ob, smat);
}
-void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob)
+void multiresModifier_prepare_join(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, Object *to_ob)
{
float smat[3][3], tmat[3][3], mat[3][3];
multires_sync_levels(scene, to_ob, ob);
@@ -2297,7 +2297,7 @@ void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob)
BKE_object_scale_to_mat3(ob, smat);
mul_m3_m3m3(mat, smat, tmat);
- multires_apply_smat(scene, ob, mat);
+ multires_apply_smat(eval_ctx, scene, ob, mat);
}
/* update multires data after topology changing */
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 2363eb525d5..cbb7a766dfe 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -59,7 +59,7 @@
#include "BKE_library.h"
#ifdef WITH_AUDASPACE
-# include AUD_SPECIAL_H
+# include <AUD_Special.h>
#endif
#include "RNA_access.h"
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 2ca414c5e6e..b76fd49fc9c 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -2023,7 +2023,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = node->next) {
/* store new_node pointer to original */
- node->new_node->new_node = node;
+ node->new_node->original = node;
}
if (ntree->typeinfo->localize)
@@ -3595,6 +3595,7 @@ static void registerShaderNodes(void)
register_node_type_sh_add_shader();
register_node_type_sh_uvmap();
register_node_type_sh_uvalongstroke();
+ register_node_type_sh_eevee_specular();
register_node_type_sh_output_lamp();
register_node_type_sh_output_material();
@@ -3787,3 +3788,63 @@ 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--;
+ }
+ }
+ }
+}
+
+static void node_copy_default_values_list(ListBase *sockets_dst,
+ const ListBase *sockets_src)
+{
+ bNodeSocket *sock_dst = sockets_dst->first;
+ const bNodeSocket *sock_src = sockets_src->first;
+ while (sock_dst != NULL) {
+ node_socket_copy_default_value(sock_dst, sock_src);
+ sock_dst = sock_dst->next;
+ sock_src = sock_src->next;
+ }
+}
+
+static void node_copy_default_values(bNode *node_dst, const bNode *node_src)
+{
+ node_copy_default_values_list(&node_dst->inputs, &node_src->inputs);
+ node_copy_default_values_list(&node_dst->outputs, &node_src->outputs);
+}
+
+void BKE_nodetree_copy_default_values(bNodeTree *ntree_dst,
+ const bNodeTree *ntree_src)
+{
+ if (ntree_dst == ntree_src) {
+ return;
+ }
+ bNode *node_dst = ntree_dst->nodes.first;
+ const bNode *node_src = ntree_src->nodes.first;
+ while (node_dst != NULL) {
+ node_copy_default_values(node_dst, node_src);
+ node_dst = node_dst->next;
+ node_src = node_src->next;
+ }
+}
+
+void BKE_nodetree_shading_params_eval(const struct EvaluationContext *UNUSED(eval_ctx),
+ bNodeTree *ntree_dst,
+ const bNodeTree *ntree_src)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s (%p)\n", __func__, ntree_src->id.name, ntree_dst);
+ }
+ BKE_nodetree_copy_default_values(ntree_dst, ntree_src);
+}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index c6b4e3fb0c7..bea9e3bdcac 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -58,6 +58,7 @@
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
#include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_property_types.h"
#include "DNA_rigidbody_types.h"
@@ -78,7 +79,6 @@
#include "BKE_action.h"
#include "BKE_bullet.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_animsys.h"
#include "BKE_anim.h"
@@ -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"
@@ -103,9 +104,11 @@
#include "BKE_multires.h"
#include "BKE_node.h"
#include "BKE_object.h"
+#include "BKE_object_facemap.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
+#include "BKE_lightprobe.h"
#include "BKE_property.h"
#include "BKE_rigidbody.h"
#include "BKE_sca.h"
@@ -118,6 +121,10 @@
#include "BKE_camera.h"
#include "BKE_image.h"
+#include "DEG_depsgraph.h"
+
+#include "DRW_engine.h"
+
#ifdef WITH_MOD_FLUID
#include "LBM_fluidsim.h"
#endif
@@ -129,7 +136,7 @@
#include "CCGSubSurf.h"
#include "atomic_ops.h"
-#include "GPU_material.h"
+#include "GPU_lamp.h"
/* Vertex parent modifies original BMesh which is not safe for threading.
* Ideally such a modification should be handled as a separate DAG update
@@ -152,16 +159,6 @@ void BKE_object_workob_clear(Object *workob)
workob->rotmode = ROT_MODE_EUL;
}
-void BKE_object_update_base_layer(struct Scene *scene, Object *ob)
-{
- Base *base = scene->base.first;
-
- while (base) {
- if (base->object == ob) base->lay = ob->lay;
- base = base->next;
- }
-}
-
void BKE_object_free_particlesystems(Object *ob)
{
ParticleSystem *psys;
@@ -356,7 +353,18 @@ void BKE_object_free_derived_caches(Object *ob)
ob->derivedDeform->release(ob->derivedDeform);
ob->derivedDeform = NULL;
}
-
+
+ if (ob->mesh_evaluated != NULL) {
+ /* Restore initial pointer. */
+ ob->data = ob->mesh_evaluated->id.newid;
+ /* Evaluated mesh points to edit mesh, but does not own it. */
+ ob->mesh_evaluated->edit_btmesh = NULL;
+ BKE_mesh_free(ob->mesh_evaluated);
+ BKE_libblock_free_data(&ob->mesh_evaluated->id, false);
+ MEM_freeN(ob->mesh_evaluated);
+ ob->mesh_evaluated = NULL;
+ }
+
BKE_object_free_curve_cache(ob);
}
@@ -401,7 +409,7 @@ void BKE_object_free_caches(Object *object)
* guaranteed to be in a known state.
*/
if (update_flag != 0) {
- DAG_id_tag_update(&object->id, update_flag);
+ DEG_id_tag_update(&object->id, update_flag);
}
}
@@ -418,6 +426,7 @@ void BKE_object_free(Object *ob)
MEM_SAFE_FREE(ob->bb);
BLI_freelistN(&ob->defbase);
+ BLI_freelistN(&ob->fmaps);
if (ob->pose) {
BKE_pose_free_ex(ob->pose, false);
ob->pose = NULL;
@@ -448,6 +457,16 @@ void BKE_object_free(Object *ob)
}
GPU_lamp_free(ob);
+ for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) {
+ if (oed->storage) {
+ if (oed->free) {
+ oed->free(oed->storage);
+ }
+ MEM_freeN(oed->storage);
+ }
+ }
+ BLI_freelistN(&ob->drawdata);
+
BKE_sculptsession_free(ob);
BLI_freelistN(&ob->pc_ids);
@@ -464,6 +483,9 @@ void BKE_object_free(Object *ob)
}
BKE_previewimg_free(&ob->preview);
+
+ /* don't free, let the base free it */
+ ob->base_collection_properties = NULL;
}
/* actual check for internal data, not context or flags */
@@ -528,6 +550,15 @@ bool BKE_object_is_in_wpaint_select_vert(Object *ob)
return false;
}
+/**
+ * Return if the object is visible, as evaluated by depsgraph
+ * Keep in sync with rna_object.c (object.is_visible).
+ */
+bool BKE_object_is_visible(Object *ob)
+{
+ return (ob->base_flag & BASE_VISIBLED) != 0;
+}
+
bool BKE_object_exists_check(Object *obtest)
{
Object *ob;
@@ -581,6 +612,7 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
case OB_LATTICE: return BKE_lattice_add(bmain, name);
case OB_ARMATURE: return BKE_armature_add(bmain, name);
case OB_SPEAKER: return BKE_speaker_add(bmain, name);
+ case OB_LIGHTPROBE:return BKE_lightprobe_add(bmain, name);
case OB_EMPTY: return NULL;
default:
printf("%s: Internal error, bad type: %d\n", __func__, type);
@@ -672,6 +704,9 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
ob = BKE_libblock_alloc(bmain, ID_OB, name, 0);
+ /* We increase object user count when linking to SceneCollections. */
+ id_us_min(&ob->id);
+
/* default object vars */
ob->type = type;
@@ -680,29 +715,65 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
return ob;
}
-/* general add: to scene, with layer from area and default name */
+
+static Object *object_add_common(Main *bmain, ViewLayer *view_layer, int type, const char *name)
+{
+ Object *ob;
+
+ ob = BKE_object_add_only_object(bmain, type, name);
+ ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
+ BKE_view_layer_base_deselect_all(view_layer);
+
+ DEG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ return ob;
+}
+
+/**
+ * General add: to scene, with layer from area and default name
+ *
+ * Object is added to the active SceneCollection.
+ * If there is no linked collection to the active ViewLayer we create a new one.
+ */
/* creates minimum required data, but without vertices etc. */
Object *BKE_object_add(
- Main *bmain, Scene *scene,
+ Main *bmain, Scene *scene, ViewLayer *view_layer,
int type, const char *name)
{
Object *ob;
Base *base;
+ LayerCollection *layer_collection;
- ob = BKE_object_add_only_object(bmain, type, name);
+ ob = object_add_common(bmain, view_layer, type, name);
- ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
+ layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer);
+ BKE_collection_object_add(&scene->id, layer_collection->scene_collection, ob);
- 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);
+ base = BKE_view_layer_base_find(view_layer, ob);
+ BKE_view_layer_base_select(view_layer, base);
return ob;
}
+/**
+ * Add a new object, using another one as a reference
+ *
+ * /param ob_src object to use to determine the collections of the new object.
+ */
+Object *BKE_object_add_from(
+ Main *bmain, Scene *scene, ViewLayer *view_layer,
+ int type, const char *name, Object *ob_src)
+{
+ Object *ob;
+ Base *base;
+
+ ob = object_add_common(bmain, view_layer, type, name);
+ BKE_collection_object_add_from(scene, ob_src, ob);
+
+ base = BKE_view_layer_base_find(view_layer, ob);
+ BKE_view_layer_base_select(view_layer, base);
+
+ return ob;
+}
#ifdef WITH_GAMEENGINE
@@ -794,9 +865,9 @@ static LodLevel *lod_level_select(Object *ob, const float camera_position[3])
return current;
}
-bool BKE_object_lod_is_usable(Object *ob, Scene *scene)
+bool BKE_object_lod_is_usable(Object *ob, ViewLayer *view_layer)
{
- bool active = (scene) ? ob == OBACT : false;
+ bool active = (view_layer) ? ob == OBACT(view_layer) : false;
return (ob->mode == OB_MODE_OBJECT || !active);
}
@@ -810,11 +881,11 @@ void BKE_object_lod_update(Object *ob, const float camera_position[3])
}
}
-static Object *lod_ob_get(Object *ob, Scene *scene, int flag)
+static Object *lod_ob_get(Object *ob, ViewLayer *view_layer, int flag)
{
LodLevel *current = ob->currentlod;
- if (!current || !BKE_object_lod_is_usable(ob, scene))
+ if (!current || !BKE_object_lod_is_usable(ob, view_layer))
return ob;
while (current->prev && (!(current->flags & flag) || !current->source || current->source->type != OB_MESH)) {
@@ -824,14 +895,14 @@ static Object *lod_ob_get(Object *ob, Scene *scene, int flag)
return current->source;
}
-struct Object *BKE_object_lod_meshob_get(Object *ob, Scene *scene)
+struct Object *BKE_object_lod_meshob_get(Object *ob, ViewLayer *view_layer)
{
- return lod_ob_get(ob, scene, OB_LOD_USE_MESH);
+ return lod_ob_get(ob, view_layer, OB_LOD_USE_MESH);
}
-struct Object *BKE_object_lod_matob_get(Object *ob, Scene *scene)
+struct Object *BKE_object_lod_matob_get(Object *ob, ViewLayer *view_layer)
{
- return lod_ob_get(ob, scene, OB_LOD_USE_MAT);
+ return lod_ob_get(ob, view_layer, OB_LOD_USE_MAT);
}
#endif /* WITH_GAMEENGINE */
@@ -943,6 +1014,7 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f
psysn->effectors = NULL;
psysn->tree = NULL;
psysn->bvhtree = NULL;
+ psysn->batch_cache = NULL;
BLI_listbase_clear(&psysn->pathcachebufs);
BLI_listbase_clear(&psysn->childcachebufs);
@@ -1147,6 +1219,7 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_
BKE_pose_rebuild(ob_dst, ob_dst->data);
}
defgroup_copy_list(&ob_dst->defbase, &ob_src->defbase);
+ BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps);
BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true);
ob_dst->mode = OB_MODE_OBJECT;
@@ -1169,6 +1242,7 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_
ob_dst->derivedFinal = NULL;
BLI_listbase_clear(&ob_dst->gpulamp);
+ BLI_listbase_clear(&ob_dst->drawdata);
BLI_listbase_clear(&ob_dst->pc_ids);
ob_dst->mpath = NULL;
@@ -1329,8 +1403,8 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
ob->proxy_group = gob;
id_lib_extern(&target->id);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- DAG_id_tag_update(&target->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&target->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* copy transform
* - gob means this proxy comes from a group, just apply the matrix
@@ -1673,13 +1747,16 @@ static bool ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
Curve *cu = par->data;
float vec[4], dir[3], quat[4], radius, ctime;
+ /* TODO: Make sure this doesn't crash. */
+#if 0
/* only happens on reload file, but violates depsgraph still... fix! */
if (par->curve_cache == NULL) {
if (scene == NULL) {
return false;
}
- BKE_displist_make_curveTypes(scene, par, 0);
+ BKE_displist_make_curveTypes(eval_ctx, scene, par, 0);
}
+#endif
if (par->curve_cache->path == NULL) {
return false;
@@ -2060,8 +2137,9 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat
}
/* note, scene is the active scene while actual_scene is the scene the object resides in */
-void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime,
- RigidBodyWorld *rbw, float r_originmat[3][3])
+void BKE_object_where_is_calc_time_ex(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, float ctime,
+ RigidBodyWorld *rbw, float r_originmat[3][3])
{
if (ob == NULL) return;
@@ -2096,7 +2174,7 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime,
if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) {
bConstraintOb *cob;
cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
- BKE_constraints_solve(&ob->constraints, cob, ctime);
+ BKE_constraints_solve(eval_ctx, &ob->constraints, cob, ctime);
BKE_constraints_clear_evalob(cob);
}
@@ -2105,9 +2183,9 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime,
else ob->transflag &= ~OB_NEG_SCALE;
}
-void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
+void BKE_object_where_is_calc_time(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, float ctime)
{
- BKE_object_where_is_calc_time_ex(scene, ob, ctime, NULL, NULL);
+ BKE_object_where_is_calc_time_ex(eval_ctx, scene, ob, ctime, NULL, NULL);
}
/* get object transformation matrix without recalculating dependencies and
@@ -2132,17 +2210,17 @@ void BKE_object_where_is_calc_mat4(Scene *scene, Object *ob, float obmat[4][4])
}
}
-void BKE_object_where_is_calc_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob, float r_originmat[3][3])
+void BKE_object_where_is_calc_ex(const EvaluationContext *eval_ctx, Scene *scene, RigidBodyWorld *rbw, Object *ob, float r_originmat[3][3])
{
- BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), rbw, r_originmat);
+ BKE_object_where_is_calc_time_ex(eval_ctx, scene, ob, BKE_scene_frame_get(scene), rbw, r_originmat);
}
-void BKE_object_where_is_calc(Scene *scene, Object *ob)
+void BKE_object_where_is_calc(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
- BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), NULL, NULL);
+ BKE_object_where_is_calc_time_ex(eval_ctx, scene, ob, BKE_scene_frame_get(scene), NULL, NULL);
}
/* for calculation of the inverse parent transform, only used for editor */
-void BKE_object_workob_calc_parent(Scene *scene, Object *ob, Object *workob)
+void BKE_object_workob_calc_parent(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, Object *workob)
{
BKE_object_workob_clear(workob);
@@ -2164,7 +2242,7 @@ void BKE_object_workob_calc_parent(Scene *scene, Object *ob, Object *workob)
BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr));
- BKE_object_where_is_calc(scene, workob);
+ BKE_object_where_is_calc(eval_ctx, scene, workob);
}
/* see BKE_pchan_apply_mat4() for the equivalent 'pchan' function */
@@ -2489,14 +2567,14 @@ void BKE_object_foreach_display_point(
}
void BKE_scene_foreach_display_point(
- Scene *scene, View3D *v3d, const short flag,
+ Scene *scene, ViewLayer *view_layer,
void (*func_cb)(const float[3], void *), void *user_data)
{
Base *base;
Object *ob;
- for (base = FIRSTBASE; base; base = base->next) {
- if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag & flag) == flag) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTED) != 0)) {
ob = base->object;
if ((ob->transflag & OB_DUPLI) == 0) {
@@ -2586,7 +2664,7 @@ bool BKE_object_parent_loop_check(const Object *par, const Object *ob)
return BKE_object_parent_loop_check(par->parent, ob);
}
-static void object_handle_update_proxy(EvaluationContext *eval_ctx,
+static void object_handle_update_proxy(const EvaluationContext *eval_ctx,
Scene *scene,
Object *object,
const bool do_proxy_update)
@@ -2616,12 +2694,14 @@ static void object_handle_update_proxy(EvaluationContext *eval_ctx,
/* the main object update call, for object matrix, constraints, keys and displist (modifiers) */
/* requires flags to be set! */
/* Ideally we shouldn't have to pass the rigid body world, but need bigger restructuring to avoid id */
-void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
+void BKE_object_handle_update_ex(const EvaluationContext *eval_ctx,
Scene *scene, Object *ob,
RigidBodyWorld *rbw,
const bool do_proxy_update)
{
- if ((ob->recalc & OB_RECALC_ALL) == 0) {
+ const bool recalc_object = (ob->id.tag & LIB_TAG_ID_RECALC) != 0;
+ const bool recalc_data = (ob->id.tag & LIB_TAG_ID_RECALC_DATA) != 0;
+ if (!recalc_object && ! recalc_data) {
object_handle_update_proxy(eval_ctx, scene, ob, do_proxy_update);
return;
}
@@ -2632,7 +2712,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
BKE_pose_update_constraint_flags(ob->pose);
}
}
- if (ob->recalc & OB_RECALC_DATA) {
+ if (recalc_data) {
if (ob->type == OB_ARMATURE) {
/* this happens for reading old files and to match library armatures
* with poses we do it ahead of BKE_object_where_is_calc to ensure animation
@@ -2645,21 +2725,21 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
/* XXX new animsys warning: depsgraph tag OB_RECALC_DATA should not skip drivers,
* which is only in BKE_object_where_is_calc now */
/* XXX: should this case be OB_RECALC_OB instead? */
- if (ob->recalc & OB_RECALC_ALL) {
+ if (recalc_object || recalc_data) {
if (G.debug & G_DEBUG_DEPSGRAPH) {
printf("recalcob %s\n", ob->id.name + 2);
}
/* Handle proxy copy for target. */
if (!BKE_object_eval_proxy_copy(eval_ctx, ob)) {
- BKE_object_where_is_calc_ex(scene, rbw, ob, NULL);
+ BKE_object_where_is_calc_ex(eval_ctx, scene, rbw, ob, NULL);
}
}
- if (ob->recalc & OB_RECALC_DATA) {
+ if (recalc_data) {
BKE_object_handle_data_update(eval_ctx, scene, ob);
}
- ob->recalc &= ~OB_RECALC_ALL;
+ ob->id.tag &= ~LIB_TAG_ID_RECALC_ALL;
object_handle_update_proxy(eval_ctx, scene, ob, do_proxy_update);
}
@@ -2669,7 +2749,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
* e.g. "scene" <-- set 1 <-- set 2 ("ob" lives here) <-- set 3 <-- ... <-- set n
* rigid bodies depend on their world so use BKE_object_handle_update_ex() to also pass along the corrent rigid body world
*/
-void BKE_object_handle_update(EvaluationContext *eval_ctx, Scene *scene, Object *ob)
+void BKE_object_handle_update(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
BKE_object_handle_update_ex(eval_ctx, scene, ob, NULL, true);
}
@@ -2716,14 +2796,7 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc,
switch (GS(((ID *)ob->data)->name)) {
case ID_ME:
{
- Mesh *me = ob->data;
- if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) {
- BKE_mesh_texspace_calc(me);
- }
- if (r_texflag) *r_texflag = &me->texflag;
- if (r_loc) *r_loc = me->loc;
- if (r_size) *r_size = me->size;
- if (r_rot) *r_rot = me->rot;
+ BKE_mesh_texspace_get_reference((Mesh *)ob->data, r_texflag, r_loc, r_rot, r_size);
break;
}
case ID_CU:
@@ -3290,33 +3363,33 @@ static void obrel_list_add(LinkNode **links, Object *ob)
}
/*
- * Iterates over all objects of the given scene.
+ * Iterates over all objects of the given scene layer.
* Depending on the eObjectSet flag:
* collect either OB_SET_ALL, OB_SET_VISIBLE or OB_SET_SELECTED objects.
* If OB_SET_VISIBLE or OB_SET_SELECTED are collected,
* then also add related objects according to the given includeFilters.
*/
-LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter)
+LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer, eObjectSet objectSet, eObRelationTypes includeFilter)
{
LinkNode *links = NULL;
Base *base;
/* Remove markers from all objects */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = view_layer->object_bases.first; base; base = base->next) {
base->object->id.tag &= ~LIB_TAG_DOIT;
}
/* iterate over all selected and visible objects */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = view_layer->object_bases.first; base; base = base->next) {
if (objectSet == OB_SET_ALL) {
/* as we get all anyways just add it */
Object *ob = base->object;
obrel_list_add(&links, ob);
}
else {
- if ((objectSet == OB_SET_SELECTED && TESTBASELIB_BGMODE(((View3D *)NULL), scene, base)) ||
- (objectSet == OB_SET_VISIBLE && BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, base)))
+ if ((objectSet == OB_SET_SELECTED && TESTBASELIB_BGMODE(base)) ||
+ (objectSet == OB_SET_VISIBLE && BASE_EDITABLE_BGMODE(base)))
{
Object *ob = base->object;
@@ -3345,8 +3418,8 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS
/* child relationship */
if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) {
Base *local_base;
- for (local_base = scene->base.first; local_base; local_base = local_base->next) {
- if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) {
+ for (local_base = view_layer->object_bases.first; local_base; local_base = local_base->next) {
+ if (BASE_EDITABLE_BGMODE(local_base)) {
Object *child = local_base->object;
if (obrel_list_test(child)) {
@@ -3390,18 +3463,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);
}
}
@@ -3602,9 +3668,9 @@ static void object_cacheIgnoreClear(Object *ob, int state)
/* Note: this function should eventually be replaced by depsgraph functionality.
* Avoid calling this in new code unless there is a very good reason for it!
*/
-bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_mesh,
- int parent_recursion, float frame,
- int type)
+bool BKE_object_modifier_update_subframe(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update_mesh,
+ int parent_recursion, float frame, int type)
{
ModifierData *md = modifiers_findByType(ob, (ModifierType)type);
bConstraint *con;
@@ -3627,8 +3693,8 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m
if (parent_recursion) {
int recursion = parent_recursion - 1;
bool no_update = false;
- if (ob->parent) no_update |= BKE_object_modifier_update_subframe(scene, ob->parent, 0, recursion, frame, type);
- if (ob->track) no_update |= BKE_object_modifier_update_subframe(scene, ob->track, 0, recursion, frame, type);
+ if (ob->parent) no_update |= BKE_object_modifier_update_subframe(eval_ctx, scene, ob->parent, 0, recursion, frame, type);
+ if (ob->track) no_update |= BKE_object_modifier_update_subframe(eval_ctx, scene, ob->track, 0, recursion, frame, type);
/* skip subframe if object is parented
* to vertex of a dynamic paint canvas */
@@ -3645,7 +3711,7 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m
cti->get_constraint_targets(con, &targets);
for (ct = targets.first; ct; ct = ct->next) {
if (ct->tar)
- BKE_object_modifier_update_subframe(scene, ct->tar, 0, recursion, frame, type);
+ BKE_object_modifier_update_subframe(eval_ctx, scene, ct->tar, 0, recursion, frame, type);
}
/* free temp targets */
if (cti->flush_constraint_targets)
@@ -3655,7 +3721,8 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m
}
/* was originally OB_RECALC_ALL - TODO - which flags are really needed??? */
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ /* TODO(sergey): What about animation? */
+ ob->id.tag |= LIB_TAG_ID_RECALC_ALL;
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM);
if (update_mesh) {
/* ignore cache clear during subframe updates
@@ -3665,7 +3732,7 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m
object_cacheIgnoreClear(ob, 0);
}
else
- BKE_object_where_is_calc_time(scene, ob, frame);
+ BKE_object_where_is_calc_time(eval_ctx, scene, ob, frame);
/* for curve following objects, parented curve has to be updated too */
if (ob->type == OB_CURVE) {
@@ -3676,7 +3743,7 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m
if (ob->type == OB_ARMATURE) {
bArmature *arm = ob->data;
BKE_animsys_evaluate_animdata(scene, &arm->id, arm->adt, frame, ADT_RECALC_ANIM);
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(eval_ctx, scene, ob);
}
return false;
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index d387e30050c..754434eaef6 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -51,6 +51,7 @@
#include "BKE_editmesh.h"
#include "BKE_object_deform.h" /* own include */
#include "BKE_object.h"
+#include "BKE_mesh.h"
#include "BKE_modifier.h"
/** \name Misc helpers
@@ -405,6 +406,8 @@ void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
object_defgroup_remove_edit_mode(ob, defgroup);
else
object_defgroup_remove_object_mode(ob, defgroup);
+
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
}
/**
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index b49e481b068..a16acd9d564 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -49,10 +49,10 @@
#include "BKE_animsys.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_depsgraph.h"
#include "BKE_font.h"
-#include "BKE_group.h"
#include "BKE_global.h"
+#include "BKE_group.h"
+#include "BKE_idprop.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
@@ -62,6 +62,7 @@
#include "BKE_editmesh.h"
#include "BKE_anim.h"
+#include "DEG_depsgraph.h"
#include "BLI_strict_flags.h"
#include "BLI_hash.h"
@@ -69,15 +70,15 @@
/* Dupli-Geometry */
typedef struct DupliContext {
- EvaluationContext *eval_ctx;
+ const EvaluationContext *eval_ctx;
bool do_update;
bool animated;
Group *group; /* XXX child objects are selected from this group if set, could be nicer */
Scene *scene;
+ ViewLayer *view_layer;
Object *object;
float space_mat[4][4];
- unsigned int lay;
int persistent_id[MAX_DUPLI_RECUR];
int level;
@@ -96,10 +97,11 @@ typedef struct DupliGenerator {
static const DupliGenerator *get_dupli_generator(const DupliContext *ctx);
/* create initial context for root object */
-static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update)
+static void init_context(DupliContext *r_ctx, const EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update)
{
r_ctx->eval_ctx = eval_ctx;
r_ctx->scene = scene;
+ r_ctx->view_layer = eval_ctx->view_layer;
/* don't allow BKE_object_handle_update for viewport during render, can crash */
r_ctx->do_update = update && !(G.is_rendering && eval_ctx->mode != DAG_EVAL_RENDER);
r_ctx->animated = false;
@@ -110,7 +112,6 @@ static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene
copy_m4_m4(r_ctx->space_mat, space_mat);
else
unit_m4(r_ctx->space_mat);
- r_ctx->lay = ob->lay;
r_ctx->level = 0;
r_ctx->gen = get_dupli_generator(r_ctx);
@@ -143,7 +144,8 @@ static void copy_dupli_context(DupliContext *r_ctx, const DupliContext *ctx, Obj
*/
static DupliObject *make_dupli(const DupliContext *ctx,
Object *ob, float mat[4][4], int index,
- bool animated, bool hide)
+ bool animated, bool hide,
+ IDProperty *collection_properties)
{
DupliObject *dob;
int i;
@@ -198,6 +200,10 @@ static DupliObject *make_dupli(const DupliContext *ctx,
dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->object->id.name + 2));
}
+ if (collection_properties) {
+ dob->collection_properties = IDP_CopyProperty(collection_properties);
+ }
+
return dob;
}
@@ -238,32 +244,30 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
Object *obedit = ctx->scene->obedit;
if (ctx->group) {
- unsigned int lay = ctx->group->layer;
int groupid = 0;
- GroupObject *go;
- for (go = ctx->group->gobject.first; go; go = go->next, groupid++) {
- Object *ob = go->ob;
-
- if ((ob->lay & lay) && ob != obedit && is_child(ob, parent)) {
+ FOREACH_GROUP_BASE(ctx->group, base)
+ {
+ Object *ob = base->object;
+ if ((base->flag & BASE_VISIBLED) && ob != obedit && is_child(ob, parent)) {
DupliContext pctx;
copy_dupli_context(&pctx, ctx, ctx->object, NULL, groupid, false);
/* mballs have a different dupli handling */
- if (ob->type != OB_MBALL)
+ if (ob->type != OB_MBALL) {
ob->flag |= OB_DONE; /* doesnt render */
-
+ }
make_child_duplis_cb(&pctx, userdata, ob);
}
+ groupid++;
}
+ FOREACH_GROUP_BASE_END
}
else {
- unsigned int lay = ctx->scene->lay;
int baseid = 0;
- Base *base;
- for (base = ctx->scene->base.first; base; base = base->next, baseid++) {
+ ViewLayer *view_layer = ctx->view_layer;
+ for (Base *base = view_layer->object_bases.first; base; base = base->next, baseid++) {
Object *ob = base->object;
-
- if ((base->lay & lay) && ob != obedit && is_child(ob, parent)) {
+ if ((base->flag & BASE_VISIBLED) && ob != obedit && is_child(ob, parent)) {
DupliContext pctx;
copy_dupli_context(&pctx, ctx, ctx->object, NULL, baseid, false);
@@ -283,13 +287,12 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
/* OB_DUPLIGROUP */
static void make_duplis_group(const DupliContext *ctx)
{
- bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER);
Object *ob = ctx->object;
Group *group;
- GroupObject *go;
+ Base *base;
float group_mat[4][4];
int id;
- bool animated, hide;
+ bool animated;
if (ob->dup_group == NULL) return;
group = ob->dup_group;
@@ -311,34 +314,18 @@ static void make_duplis_group(const DupliContext *ctx)
animated = BKE_group_is_animated(group, ob);
- for (go = group->gobject.first, id = 0; go; go = go->next, id++) {
- /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
- if (go->ob != ob) {
+ for (base = group->view_layer->object_bases.first, id = 0; base; base = base->next, id++) {
+ if (base->object != ob && (base->flag & BASE_VISIBLED)) {
float mat[4][4];
- /* Special case for instancing dupli-groups, see: T40051
- * this object may be instanced via dupli-verts/faces, in this case we don't want to render
- * (blender convention), but _do_ show in the viewport.
- *
- * Regular objects work fine but not if we're instancing dupli-groups,
- * because the rules for rendering aren't applied to objects they instance.
- * We could recursively pass down the 'hide' flag instead, but that seems unnecessary.
- */
- if (for_render && go->ob->parent && go->ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES)) {
- continue;
- }
-
/* group dupli offset, should apply after everything else */
- mul_m4_m4m4(mat, group_mat, go->ob->obmat);
+ mul_m4_m4m4(mat, group_mat, base->object->obmat);
- /* check the group instance and object layers match, also that the object visible flags are ok. */
- hide = (go->ob->lay & group->layer) == 0 ||
- (for_render ? go->ob->restrictflag & OB_RESTRICT_RENDER : go->ob->restrictflag & OB_RESTRICT_VIEW);
-
- make_dupli(ctx, go->ob, mat, id, animated, hide);
+ BLI_assert(base->collection_properties != NULL);
+ make_dupli(ctx, base->object, mat, id, animated, false, base->collection_properties);
/* recursion */
- make_recursive_duplis(ctx, go->ob, group_mat, id, animated);
+ make_recursive_duplis(ctx, base->object, group_mat, id, animated);
}
}
}
@@ -399,9 +386,9 @@ static void make_duplis_frames(const DupliContext *ctx)
* However, this has always been the way that this worked (i.e. pre 2.5), so I guess that it'll be fine!
*/
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
- BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra);
+ BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, (float)scene->r.cfra);
- make_dupli(ctx, ob, ob->obmat, scene->r.cfra, false, false);
+ make_dupli(ctx, ob, ob->obmat, scene->r.cfra, false, false, NULL);
}
}
@@ -413,7 +400,7 @@ static void make_duplis_frames(const DupliContext *ctx)
scene->r.cfra = cfrao;
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
- BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra);
+ BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, (float)scene->r.cfra);
/* but, to make sure unkeyed object transforms are still sane,
* let's copy object's original data back over
@@ -486,7 +473,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
*/
mul_m4_m4m4(space_mat, obmat, inst_ob->imat);
- dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false);
+ dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false, NULL);
if (vdd->orco)
copy_v3_v3(dob->orco, vdd->orco[index]);
@@ -548,13 +535,13 @@ static void make_duplis_verts(const DupliContext *ctx)
CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH);
if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) {
- vdd.dm = mesh_create_derived_render(scene, parent, dm_mask);
+ vdd.dm = mesh_create_derived_render(ctx->eval_ctx, scene, parent, dm_mask);
}
else if (em) {
- vdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask);
+ vdd.dm = editbmesh_get_derived_cage(ctx->eval_ctx, scene, parent, em, dm_mask);
}
else {
- vdd.dm = mesh_get_derived_final(scene, parent, dm_mask);
+ vdd.dm = mesh_get_derived_final(ctx->eval_ctx, scene, parent, dm_mask);
}
vdd.edit_btmesh = me->edit_btmesh;
@@ -671,7 +658,7 @@ static void make_duplis_font(const DupliContext *ctx)
copy_v3_v3(obmat[3], vec);
- make_dupli(ctx, ob, obmat, a, false, false);
+ make_dupli(ctx, ob, obmat, a, false, false, NULL);
}
}
@@ -777,7 +764,7 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj
*/
mul_m4_m4m4(space_mat, obmat, inst_ob->imat);
- dob = make_dupli(ctx, inst_ob, obmat, a, false, false);
+ dob = make_dupli(ctx, inst_ob, obmat, a, false, false, NULL);
if (use_texcoords) {
float w = 1.0f / (float)mp->totloop;
@@ -816,13 +803,13 @@ static void make_duplis_faces(const DupliContext *ctx)
CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH);
if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) {
- fdd.dm = mesh_create_derived_render(scene, parent, dm_mask);
+ fdd.dm = mesh_create_derived_render(ctx->eval_ctx, scene, parent, dm_mask);
}
else if (em) {
- fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask);
+ fdd.dm = editbmesh_get_derived_cage(ctx->eval_ctx, scene, parent, em, dm_mask);
}
else {
- fdd.dm = mesh_get_derived_final(scene, parent, dm_mask);
+ fdd.dm = mesh_get_derived_final(ctx->eval_ctx, scene, parent, dm_mask);
}
if (use_texcoords) {
@@ -860,7 +847,6 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER;
bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
- GroupObject *go;
Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL;
DupliObject *dob;
ParticleDupliWeight *dw;
@@ -900,6 +886,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
ParticleSimulationData sim = {NULL};
+ sim.eval_ctx = ctx->eval_ctx;
sim.scene = scene;
sim.ob = par;
sim.psys = psys;
@@ -913,10 +900,10 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
return;
}
else { /*PART_DRAW_GR */
- if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->gobject))
+ if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->view_layer->object_bases))
return;
- if (BLI_findptr(&part->dup_group->gobject, par, offsetof(GroupObject, ob))) {
+ if (BLI_findptr(&part->dup_group->view_layer->object_bases, par, offsetof(Base, object))) {
return;
}
}
@@ -948,8 +935,12 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
totgroup += dw->count;
}
else {
- for (go = part->dup_group->gobject.first; go; go = go->next)
+ FOREACH_GROUP_OBJECT(part->dup_group, object)
+ {
+ (void) object;
totgroup++;
+ }
+ FOREACH_GROUP_OBJECT_END
}
/* we also copy the actual objects to restore afterwards, since
@@ -968,11 +959,18 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
}
else {
- go = part->dup_group->gobject.first;
- for (a = 0; a < totgroup; a++, go = go->next) {
- oblist[a] = go->ob;
- obcopylist[a] = *go->ob;
+ a = 0;
+ FOREACH_GROUP_OBJECT(part->dup_group, object)
+ {
+ oblist[a] = object;
+ obcopylist[a] = *object;
+ a++;
+
+ if (a >= totgroup) {
+ continue;
+ }
}
+ FOREACH_GROUP_OBJECT_END
}
}
else {
@@ -1061,27 +1059,37 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
- for (go = part->dup_group->gobject.first, b = 0; go; go = go->next, b++) {
-
+ b = 0;
+ FOREACH_GROUP_OBJECT(part->dup_group, object)
+ {
copy_m4_m4(tmat, oblist[b]->obmat);
+
/* apply particle scale */
mul_mat3_m4_fl(tmat, size * scale);
mul_v3_fl(tmat[3], size * scale);
+
/* group dupli offset, should apply after everything else */
- if (!is_zero_v3(part->dup_group->dupli_ofs))
+ if (!is_zero_v3(part->dup_group->dupli_ofs)) {
sub_v3_v3(tmat[3], part->dup_group->dupli_ofs);
+ }
+
/* individual particle transform */
mul_m4_m4m4(mat, pamat, tmat);
- dob = make_dupli(ctx, go->ob, mat, a, false, false);
+ dob = make_dupli(ctx, object, mat, a, false, false, NULL);
dob->particle_system = psys;
- if (use_texcoords)
+
+ if (use_texcoords) {
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
+ }
+
+ b++;
}
+ FOREACH_GROUP_OBJECT_END
}
else {
/* to give ipos in object correct offset */
- BKE_object_where_is_calc_time(scene, ob, ctime - pa_time);
+ BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, ctime - pa_time);
copy_v3_v3(vec, obmat[3]);
obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f;
@@ -1122,7 +1130,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
if (part->draw & PART_DRAW_GLOBAL_OB)
add_v3_v3v3(mat[3], mat[3], vec);
- dob = make_dupli(ctx, ob, mat, a, false, false);
+ dob = make_dupli(ctx, ob, mat, a, false, false, NULL);
dob->particle_system = psys;
if (use_texcoords)
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
@@ -1217,7 +1225,7 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
/* ---- ListBase dupli container implementation ---- */
/* Returns a list of DupliObject */
-ListBase *object_duplilist_ex(EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update)
+ListBase *object_duplilist_ex(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update)
{
ListBase *duplilist = MEM_callocN(sizeof(ListBase), "duplilist");
DupliContext ctx;
@@ -1232,13 +1240,21 @@ ListBase *object_duplilist_ex(EvaluationContext *eval_ctx, Scene *scene, Object
/* note: previously updating was always done, this is why it defaults to be on
* but there are likely places it can be called without updating */
-ListBase *object_duplilist(EvaluationContext *eval_ctx, Scene *sce, Object *ob)
+ListBase *object_duplilist(const EvaluationContext *eval_ctx, Scene *sce, Object *ob)
{
return object_duplilist_ex(eval_ctx, sce, ob, true);
}
void free_object_duplilist(ListBase *lb)
{
+
+ for (DupliObject *dob = lb->first; dob; dob = dob->next) {
+ if (dob->collection_properties) {
+ IDP_FreeProperty(dob->collection_properties);
+ MEM_freeN(dob->collection_properties);
+ }
+ }
+
BLI_freelistN(lb);
MEM_freeN(lb);
}
@@ -1273,7 +1289,7 @@ int count_duplilist(Object *ob)
return 1;
}
-DupliApplyData *duplilist_apply(Object *ob, Scene *scene, ListBase *duplilist)
+DupliApplyData *duplilist_apply(const EvaluationContext *eval_ctx, Object *ob, Scene *scene, ListBase *duplilist)
{
DupliApplyData *apply_data = NULL;
int num_objects = BLI_listbase_count(duplilist);
@@ -1289,7 +1305,7 @@ DupliApplyData *duplilist_apply(Object *ob, Scene *scene, ListBase *duplilist)
for (dob = duplilist->first, i = 0; dob; dob = dob->next, ++i) {
/* make sure derivedmesh is calculated once, before drawing */
if (scene && !(dob->ob->transflag & OB_DUPLICALCDERIVED) && dob->ob->type == OB_MESH) {
- mesh_get_derived_final(scene, dob->ob, scene->customdata_mask);
+ mesh_get_derived_final(eval_ctx, scene, dob->ob, scene->customdata_mask);
dob->ob->transflag |= OB_DUPLICALCDERIVED;
}
}
diff --git a/source/blender/blenkernel/intern/object_facemap.c b/source/blender/blenkernel/intern/object_facemap.c
new file mode 100644
index 00000000000..1218dd376cb
--- /dev/null
+++ b/source/blender/blenkernel/intern/object_facemap.c
@@ -0,0 +1,257 @@
+
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/object_facemap.c
+ * \ingroup bke
+ */
+
+#include <string.h>
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
+#include "BLI_listbase.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_editmesh.h"
+#include "BKE_object.h"
+#include "BKE_object_facemap.h" /* own include */
+#include "BKE_object_deform.h"
+
+#include "BLT_translation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+static bool fmap_unique_check(void *arg, const char *name)
+{
+ struct {Object *ob; void *fm; } *data = arg;
+
+ bFaceMap *fmap;
+
+ for (fmap = data->ob->fmaps.first; fmap; fmap = fmap->next) {
+ if (data->fm != fmap) {
+ if (!strcmp(fmap->name, name)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static bFaceMap *fmap_duplicate(bFaceMap *infmap)
+{
+ bFaceMap *outfmap;
+
+ if (!infmap)
+ return NULL;
+
+ outfmap = MEM_callocN(sizeof(bFaceMap), "copy facemap");
+
+ /* For now, just copy everything over. */
+ memcpy(outfmap, infmap, sizeof(bFaceMap));
+
+ outfmap->next = outfmap->prev = NULL;
+
+ return outfmap;
+}
+
+void BKE_object_facemap_copy_list(ListBase *outbase, const ListBase *inbase)
+{
+ bFaceMap *fmap, *fmapn;
+
+ BLI_listbase_clear(outbase);
+
+ for (fmap = inbase->first; fmap; fmap = fmap->next) {
+ fmapn = fmap_duplicate(fmap);
+ BLI_addtail(outbase, fmapn);
+ }
+}
+
+void BKE_object_facemap_unique_name(Object *ob, bFaceMap *fmap)
+{
+ struct {Object *ob; void *fmap; } data;
+ data.ob = ob;
+ data.fmap = fmap;
+
+ BLI_uniquename_cb(fmap_unique_check, &data, DATA_("Group"), '.', fmap->name, sizeof(fmap->name));
+}
+
+bFaceMap *BKE_object_facemap_add_name(Object *ob, const char *name)
+{
+ bFaceMap *fmap;
+
+ if (!ob || ob->type != OB_MESH)
+ return NULL;
+
+ fmap = MEM_callocN(sizeof(bFaceMap), __func__);
+
+ BLI_strncpy(fmap->name, name, sizeof(fmap->name));
+
+ BLI_addtail(&ob->fmaps, fmap);
+
+ ob->actfmap = BLI_listbase_count(&ob->fmaps);
+
+ BKE_object_facemap_unique_name(ob, fmap);
+
+ return fmap;
+}
+
+bFaceMap *BKE_object_facemap_add(Object *ob)
+{
+ return BKE_object_facemap_add_name(ob, DATA_("FaceMap"));
+}
+
+
+static void object_fmap_remove_edit_mode(Object *ob, bFaceMap *fmap, bool do_selected, bool purge)
+{
+ const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_btmesh) {
+ BMEditMesh *em = me->edit_btmesh;
+ const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ if (cd_fmap_offset != -1) {
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+
+ if (purge) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (map) {
+ if (*map == fmap_nr)
+ *map = -1;
+ else if (*map > fmap_nr)
+ *map -= 1;
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (map && *map == fmap_nr && (!do_selected || BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
+ *map = -1;
+ }
+ }
+ }
+ }
+
+ if (ob->actfmap == BLI_listbase_count(&ob->fmaps))
+ ob->actfmap--;
+
+ BLI_remlink(&ob->fmaps, fmap);
+ MEM_freeN(fmap);
+ }
+ }
+}
+
+static void object_fmap_remove_object_mode(Object *ob, bFaceMap *fmap, bool purge)
+{
+ const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
+ int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+ int i;
+
+ if (map) {
+ for (i = 0; i < me->totpoly; i++) {
+ if (map[i] == fmap_nr)
+ map[i] = -1;
+ else if (purge && map[i] > fmap_nr)
+ map[i]--;
+ }
+ }
+ }
+
+ if (ob->actfmap == BLI_listbase_count(&ob->fmaps))
+ ob->actfmap--;
+
+ BLI_remlink(&ob->fmaps, fmap);
+ MEM_freeN(fmap);
+ }
+}
+
+static void fmap_remove_exec(Object *ob, bFaceMap *fmap, const bool is_edit_mode, const bool purge)
+{
+ if (is_edit_mode)
+ object_fmap_remove_edit_mode(ob, fmap, false, purge);
+ else
+ object_fmap_remove_object_mode(ob, fmap, purge);
+}
+
+void BKE_object_facemap_remove(Object *ob, bFaceMap *fmap)
+{
+ fmap_remove_exec(ob, fmap, BKE_object_is_in_editmode(ob), true);
+}
+
+void BKE_object_facemap_clear(Object *ob)
+{
+ bFaceMap *fmap = (bFaceMap *)ob->fmaps.first;
+
+ if (fmap) {
+ const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
+
+ while (fmap) {
+ bFaceMap *next_fmap = fmap->next;
+ fmap_remove_exec(ob, fmap, edit_mode, false);
+ fmap = next_fmap;
+ }
+ }
+ /* remove all face-maps */
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ CustomData_free_layer(&me->pdata, CD_FACEMAP, me->totpoly, 0);
+ }
+ ob->actfmap = 0;
+}
+
+int BKE_object_facemap_name_index(Object *ob, const char *name)
+{
+ return (name) ? BLI_findstringindex(&ob->fmaps, name, offsetof(bFaceMap, name)) : -1;
+}
+
+bFaceMap *BKE_object_facemap_find_name(Object *ob, const char *name)
+{
+ return BLI_findstring(&ob->fmaps, name, offsetof(bFaceMap, name));
+}
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 84d2f624577..71d8c1981af 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -32,18 +32,18 @@
#include "DNA_group_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLI_threads.h"
#include "BKE_global.h"
#include "BKE_armature.h"
#include "BKE_action.h"
#include "BKE_constraint.h"
-#include "BKE_depsgraph.h"
+#include "BKE_curve.h"
#include "BKE_DerivedMesh.h"
#include "BKE_animsys.h"
#include "BKE_displist.h"
@@ -51,28 +51,26 @@
#include "BKE_key.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
+#include "BKE_library.h"
#include "BKE_editmesh.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_material.h"
+#include "BKE_mball.h"
+#include "BKE_mesh.h"
#include "BKE_image.h"
+#include "MEM_guardedalloc.h"
#include "DEG_depsgraph.h"
-#ifdef WITH_LEGACY_DEPSGRAPH
-# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf
-#else
-# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-#endif
-
-static ThreadMutex material_lock = BLI_MUTEX_INITIALIZER;
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-void BKE_object_eval_local_transform(EvaluationContext *UNUSED(eval_ctx),
+void BKE_object_eval_local_transform(const EvaluationContext *UNUSED(eval_ctx),
Object *ob)
{
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
/* calculate local matrix */
BKE_object_to_mat4(ob, ob->obmat);
@@ -80,7 +78,7 @@ void BKE_object_eval_local_transform(EvaluationContext *UNUSED(eval_ctx),
/* Evaluate parent */
/* NOTE: based on solve_parenting(), but with the cruft stripped out */
-void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx),
+void BKE_object_eval_parent(const EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *ob)
{
@@ -90,7 +88,7 @@ void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx),
float tmat[4][4];
float locmat[4][4];
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
/* get local matrix (but don't calculate it, as that was done already!) */
// XXX: redundant?
@@ -112,14 +110,14 @@ void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx),
}
}
-void BKE_object_eval_constraints(EvaluationContext *UNUSED(eval_ctx),
+void BKE_object_eval_constraints(const EvaluationContext *eval_ctx,
Scene *scene,
Object *ob)
{
bConstraintOb *cob;
float ctime = BKE_scene_frame_get(scene);
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
/* evaluate constraints stack */
/* TODO: split this into:
@@ -131,22 +129,23 @@ void BKE_object_eval_constraints(EvaluationContext *UNUSED(eval_ctx),
*
*/
cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
- BKE_constraints_solve(&ob->constraints, cob, ctime);
+ BKE_constraints_solve(eval_ctx, &ob->constraints, cob, ctime);
BKE_constraints_clear_evalob(cob);
}
-void BKE_object_eval_done(EvaluationContext *UNUSED(eval_ctx), Object *ob)
+void BKE_object_eval_done(const EvaluationContext *UNUSED(eval_ctx), Object *ob)
{
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
/* Set negative scale flag in object. */
if (is_negative_m4(ob->obmat)) ob->transflag |= OB_NEG_SCALE;
else ob->transflag &= ~OB_NEG_SCALE;
}
-void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
- Scene *scene,
- Object *ob)
+void BKE_object_handle_data_update(
+ const EvaluationContext *eval_ctx,
+ Scene *scene,
+ Object *ob)
{
ID *data_id = (ID *)ob->data;
AnimData *adt = BKE_animdata_from_id(data_id);
@@ -183,10 +182,10 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
}
#endif
if (em) {
- makeDerivedMesh(scene, ob, em, data_mask, false); /* was CD_MASK_BAREMESH */
+ makeDerivedMesh(eval_ctx, scene, ob, em, data_mask, false); /* was CD_MASK_BAREMESH */
}
else {
- makeDerivedMesh(scene, ob, NULL, data_mask, false);
+ makeDerivedMesh(eval_ctx, scene, ob, NULL, data_mask, false);
}
break;
}
@@ -198,7 +197,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
}
}
else {
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(eval_ctx, scene, ob);
}
break;
@@ -209,11 +208,11 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
case OB_CURVE:
case OB_SURF:
case OB_FONT:
- BKE_displist_make_curveTypes(scene, ob, 0);
+ BKE_displist_make_curveTypes(eval_ctx, scene, ob, 0);
break;
case OB_LATTICE:
- BKE_lattice_modifiers_calc(scene, ob);
+ BKE_lattice_modifiers_calc(eval_ctx, scene, ob);
break;
case OB_EMPTY:
@@ -223,28 +222,6 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
break;
}
- /* related materials */
- /* XXX: without depsgraph tagging, this will always need to be run, which will be slow!
- * However, not doing anything (or trying to hack around this lack) is not an option
- * anymore, especially due to Cycles [#31834]
- */
- if (ob->totcol) {
- int a;
- if (ob->totcol != 0) {
- BLI_mutex_lock(&material_lock);
- for (a = 1; a <= ob->totcol; a++) {
- Material *ma = give_current_material(ob, a);
- if (ma) {
- /* recursively update drivers for this material */
- material_drivers_update(scene, ma, ctime);
- }
- }
- BLI_mutex_unlock(&material_lock);
- }
- }
- else if (ob->type == OB_LAMP)
- lamp_drivers_update(scene, ob->data, ctime);
-
/* particles */
if (ob != scene->obedit && ob->particlesystem.first) {
ParticleSystem *tpsys, *psys;
@@ -266,7 +243,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
ob->transflag |= OB_DUPLIPARTS;
}
- particle_system_update(scene, ob, psys, (eval_ctx->mode == DAG_EVAL_RENDER));
+ particle_system_update(eval_ctx, scene, ob, psys, (eval_ctx->mode == DAG_EVAL_RENDER));
psys = psys->next;
}
else if (psys->flag & PSYS_DELETE) {
@@ -284,7 +261,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
* the derivedmesh must be created before init_render_mesh,
* since object_duplilist does dupliparticles before that */
CustomDataMask data_mask = CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL;
- dm = mesh_create_derived_render(scene, ob, data_mask);
+ dm = mesh_create_derived_render(eval_ctx, scene, ob, data_mask);
dm->release(dm);
for (psys = ob->particlesystem.first; psys; psys = psys->next)
@@ -295,7 +272,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
/* quick cache removed */
}
-bool BKE_object_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx),
+bool BKE_object_eval_proxy_copy(const EvaluationContext *UNUSED(eval_ctx),
Object *object)
{
/* Handle proxy copy for target, */
@@ -319,35 +296,98 @@ bool BKE_object_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx),
return false;
}
-void BKE_object_eval_uber_transform(EvaluationContext *eval_ctx, Object *object)
+void BKE_object_eval_uber_transform(const EvaluationContext *eval_ctx, Object *object)
{
BKE_object_eval_proxy_copy(eval_ctx, object);
- object->recalc &= ~(OB_RECALC_OB | OB_RECALC_TIME);
- if (object->data == NULL) {
- object->recalc &= ~OB_RECALC_DATA;
- }
}
-void BKE_object_eval_uber_data(EvaluationContext *eval_ctx,
+void BKE_object_eval_uber_data(const EvaluationContext *eval_ctx,
Scene *scene,
Object *ob)
{
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
BLI_assert(ob->type != OB_ARMATURE);
BKE_object_handle_data_update(eval_ctx, scene, ob);
- ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME);
+ switch (ob->type) {
+ case OB_MESH:
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ break;
+ case OB_LATTICE:
+ BKE_lattice_batch_cache_dirty(ob->data, BKE_LATTICE_BATCH_DIRTY_ALL);
+ break;
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ BKE_curve_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_ALL);
+ break;
+ case OB_MBALL:
+ BKE_mball_batch_cache_dirty(ob->data, BKE_MBALL_BATCH_DIRTY_ALL);
+ break;
+ }
+
+ if (DEG_depsgraph_use_copy_on_write()) {
+ if (ob->type == OB_MESH) {
+ /* Quick hack to convert evaluated derivedMesh to Mesh. */
+ DerivedMesh *dm = ob->derivedFinal;
+ if (dm != NULL) {
+ Mesh *mesh = (Mesh *)ob->data;
+ Mesh *new_mesh = BKE_libblock_alloc_notest(ID_ME);
+ BKE_mesh_init(new_mesh);
+ /* Copy ID name so GS(new_mesh->id) works correct later on. */
+ BLI_strncpy(new_mesh->id.name, mesh->id.name, sizeof(new_mesh->id.name));
+ /* Copy materials so render engines can access them. */
+ new_mesh->mat = MEM_dupallocN(mesh->mat);
+ new_mesh->totcol = mesh->totcol;
+ DM_to_mesh(dm, new_mesh, ob, CD_MASK_MESH, true);
+ new_mesh->edit_btmesh = mesh->edit_btmesh;
+ /* Store result mesh as derived_mesh of object. This way we have
+ * explicit way to query final object evaluated data and know for sure
+ * who owns the newly created mesh datablock.
+ */
+ ob->mesh_evaluated = new_mesh;
+ /* TODO(sergey): This is kind of compatibility thing, so all render
+ * engines can use object->data for mesh data for display. This is
+ * something what we might want to change in the future.
+ */
+ ob->data = new_mesh;
+ /* Special flags to help debugging. */
+ new_mesh->id.tag |= LIB_TAG_COPY_ON_WRITE_EVAL;
+ /* Save some memory by throwing DerivedMesh away. */
+ /* NOTE: Watch out, some tools might need it!
+ * So keep around for now..
+ */
+ /* Store original ID as a pointer in evaluated ID.
+ * This way we can restore original object data when we are freeing
+ * evaluated mesh.
+ */
+ new_mesh->id.newid = &mesh->id;
+ }
+#if 0
+ if (ob->derivedFinal != NULL) {
+ ob->derivedFinal->needsFree = 1;
+ ob->derivedFinal->release(ob->derivedFinal);
+ ob->derivedFinal = NULL;
+ }
+ if (ob->derivedDeform != NULL) {
+ ob->derivedDeform->needsFree = 1;
+ ob->derivedDeform->release(ob->derivedDeform);
+ ob->derivedDeform = NULL;
+ }
+#endif
+ }
+ }
}
-void BKE_object_eval_cloth(EvaluationContext *UNUSED(eval_ctx),
+void BKE_object_eval_cloth(const EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *object)
{
- DEBUG_PRINT("%s on %s\n", __func__, object->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH);
}
-void BKE_object_eval_transform_all(EvaluationContext *eval_ctx,
+void BKE_object_eval_transform_all(const EvaluationContext *eval_ctx,
Scene *scene,
Object *object)
{
@@ -362,3 +402,51 @@ void BKE_object_eval_transform_all(EvaluationContext *eval_ctx,
BKE_object_eval_uber_transform(eval_ctx, object);
BKE_object_eval_done(eval_ctx, object);
}
+
+void BKE_object_eval_update_shading(const EvaluationContext *UNUSED(eval_ctx),
+ Object *object)
+{
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
+ if (object->type == OB_MESH) {
+ BKE_mesh_batch_cache_dirty(object->data, BKE_MESH_BATCH_DIRTY_SHADING);
+ }
+}
+
+void BKE_object_data_select_update(const EvaluationContext *UNUSED(eval_ctx),
+ struct ID *object_data)
+{
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, object_data->name, object_data);
+ switch (GS(object_data->name)) {
+ case ID_ME:
+ BKE_mesh_batch_cache_dirty((Mesh *)object_data,
+ BKE_CURVE_BATCH_DIRTY_SELECT);
+ break;
+ case ID_CU:
+ BKE_curve_batch_cache_dirty((Curve *)object_data,
+ BKE_CURVE_BATCH_DIRTY_SELECT);
+ break;
+ case ID_LT:
+ BKE_lattice_batch_cache_dirty((struct Lattice *)object_data,
+ BKE_CURVE_BATCH_DIRTY_SELECT);
+ break;
+ default:
+ break;
+ }
+}
+
+void BKE_object_eval_flush_base_flags(const EvaluationContext *UNUSED(eval_ctx),
+ Object *object, Base *base, bool is_from_set)
+{
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
+ /* Make sure we have the base collection settings is already populated.
+ * This will fail when BKE_layer_eval_layer_collection_pre hasn't run yet
+ * Which usually means a missing call to DEG_id_tag_update(). */
+ BLI_assert(!BLI_listbase_is_empty(&base->collection_properties->data.group));
+ /* Copy flags and settings from base. */
+ object->base_flag = base->flag;
+ if (is_from_set) {
+ object->base_flag |= BASE_FROM_SET;
+ object->base_flag &= ~(BASE_SELECTED | BASE_SELECTABLED);
+ }
+ object->base_collection_properties = base->collection_properties;
+}
diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c
index 4d97121e2a3..d9a602aa41e 100644
--- a/source/blender/blenkernel/intern/outliner_treehash.c
+++ b/source/blender/blenkernel/intern/outliner_treehash.c
@@ -27,6 +27,7 @@
*/
#include <stdlib.h>
+#include <string.h>
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -56,7 +57,7 @@ static TseGroup *tse_group_create(void)
return tse_group;
}
-static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem)
+static void tse_group_add_element(TseGroup *tse_group, TreeStoreElem *elem)
{
if (UNLIKELY(tse_group->size == tse_group->allocated)) {
tse_group->allocated *= 2;
@@ -66,6 +67,26 @@ static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem)
tse_group->size++;
}
+static void tse_group_remove_element(TseGroup *tse_group, TreeStoreElem *elem)
+{
+ int min_allocated = MAX2(1, tse_group->allocated / 2);
+ BLI_assert(tse_group->allocated == 1 || (tse_group->allocated % 2) == 0);
+
+ tse_group->size--;
+ BLI_assert(tse_group->size >= 0);
+ for (int i = 0; i < tse_group->size; i++) {
+ if (tse_group->elems[i] == elem) {
+ memcpy(tse_group->elems[i], tse_group->elems[i + 1], (tse_group->size - (i + 1)) * sizeof(TreeStoreElem *));
+ break;
+ }
+ }
+
+ if (UNLIKELY(tse_group->size > 0 && tse_group->size <= min_allocated)) {
+ tse_group->allocated = min_allocated;
+ tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated);
+ }
+}
+
static void tse_group_free(TseGroup *tse_group)
{
MEM_freeN(tse_group->elems);
@@ -140,7 +161,21 @@ void BKE_outliner_treehash_add_element(void *treehash, TreeStoreElem *elem)
*val_p = tse_group_create();
}
group = *val_p;
- tse_group_add(group, elem);
+ tse_group_add_element(group, elem);
+}
+
+void BKE_outliner_treehash_remove_element(void *treehash, TreeStoreElem *elem)
+{
+ TseGroup *group = BLI_ghash_lookup(treehash, elem);
+
+ BLI_assert(group != NULL);
+ if (group->size <= 1) {
+ /* one element -> remove group completely */
+ BLI_ghash_remove(treehash, elem, NULL, free_treehash_group);
+ }
+ else {
+ tse_group_remove_element(group, elem);
+ }
}
static TseGroup *BKE_outliner_treehash_lookup_group(GHash *th, short type, short nr, struct ID *id)
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index c1ad31a1cab..c88642a8164 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -53,7 +53,6 @@
#include "BKE_main.h"
#include "BKE_context.h"
#include "BKE_crazyspace.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_key.h"
@@ -65,6 +64,8 @@
#include "BKE_pbvh.h"
#include "BKE_subsurf.h"
+#include "DEG_depsgraph.h"
+
#include "bmesh.h"
const char PAINT_CURSOR_SCULPT[3] = {255, 100, 100};
@@ -74,9 +75,9 @@ const char PAINT_CURSOR_TEXTURE_PAINT[3] = {255, 255, 255};
static eOverlayControlFlags overlay_flags = 0;
-void BKE_paint_invalidate_overlay_tex(Scene *scene, const Tex *tex)
+void BKE_paint_invalidate_overlay_tex(Scene *scene, ViewLayer *view_layer, const Tex *tex)
{
- Paint *p = BKE_paint_get_active(scene);
+ Paint *p = BKE_paint_get_active(scene, view_layer);
Brush *br = p->brush;
if (!br)
@@ -88,9 +89,9 @@ void BKE_paint_invalidate_overlay_tex(Scene *scene, const Tex *tex)
overlay_flags |= PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY;
}
-void BKE_paint_invalidate_cursor_overlay(Scene *scene, CurveMapping *curve)
+void BKE_paint_invalidate_cursor_overlay(Scene *scene, ViewLayer *view_layer, CurveMapping *curve)
{
- Paint *p = BKE_paint_get_active(scene);
+ Paint *p = BKE_paint_get_active(scene, view_layer);
Brush *br = p->brush;
if (br && br->curve == curve)
@@ -156,13 +157,13 @@ Paint *BKE_paint_get_active_from_paintmode(Scene *sce, ePaintMode mode)
return NULL;
}
-Paint *BKE_paint_get_active(Scene *sce)
+Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
{
- if (sce) {
+ if (sce && view_layer) {
ToolSettings *ts = sce->toolsettings;
- if (sce->basact && sce->basact->object) {
- switch (sce->basact->object->mode) {
+ if (view_layer->basact && view_layer->basact->object) {
+ switch (view_layer->basact->object->mode) {
case OB_MODE_SCULPT:
return &ts->sculpt->paint;
case OB_MODE_VERTEX_PAINT:
@@ -188,14 +189,15 @@ Paint *BKE_paint_get_active(Scene *sce)
Paint *BKE_paint_get_active_from_context(const bContext *C)
{
Scene *sce = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceImage *sima;
- if (sce) {
+ if (sce && view_layer) {
ToolSettings *ts = sce->toolsettings;
Object *obact = NULL;
- if (sce->basact && sce->basact->object)
- obact = sce->basact->object;
+ if (view_layer->basact && view_layer->basact->object)
+ obact = view_layer->basact->object;
if ((sima = CTX_wm_space_image(C)) != NULL) {
if (obact && obact->mode == OB_MODE_EDIT) {
@@ -238,14 +240,15 @@ Paint *BKE_paint_get_active_from_context(const bContext *C)
ePaintMode BKE_paintmode_get_active_from_context(const bContext *C)
{
Scene *sce = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceImage *sima;
- if (sce) {
+ if (sce && view_layer) {
ToolSettings *ts = sce->toolsettings;
Object *obact = NULL;
- if (sce->basact && sce->basact->object)
- obact = sce->basact->object;
+ if (view_layer->basact && view_layer->basact->object)
+ obact = view_layer->basact->object;
if ((sima = CTX_wm_space_image(C)) != NULL) {
if (obact && obact->mode == OB_MODE_EDIT) {
@@ -726,7 +729,7 @@ void BKE_sculptsession_bm_to_me(Object *ob, bool reorder)
sculptsession_bm_to_me_update_data_only(ob, reorder);
/* ensure the objects DerivedMesh mesh doesn't hold onto arrays now realloc'd in the mesh [#34473] */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
@@ -736,7 +739,7 @@ void BKE_sculptsession_bm_to_me_for_render(Object *object)
if (object->sculpt->bm) {
/* Ensure no points to old arrays are stored in DM
*
- * Apparently, we could not use DAG_id_tag_update
+ * Apparently, we could not use DEG_id_tag_update
* here because this will lead to the while object
* surface to disappear, so we'll release DM in place.
*/
@@ -867,8 +870,9 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
/**
* \param need_mask So the DerivedMesh thats returned has mask data
*/
-void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
- bool need_pmap, bool need_mask)
+void BKE_sculpt_update_mesh_elements(
+ const EvaluationContext *eval_ctx, Scene *scene, Sculpt *sd, Object *ob,
+ bool need_pmap, bool need_mask)
{
DerivedMesh *dm;
SculptSession *ss = ob->sculpt;
@@ -906,7 +910,7 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
ss->kb = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL;
- dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH);
/* VWPaint require mesh info for loop lookup, so require sculpt mode here */
if (mmd && ob->mode & OB_MODE_SCULPT) {
@@ -940,7 +944,7 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
ss->orig_cos = (ss->kb) ? BKE_keyblock_convert_to_vertcos(ob, ss->kb) : BKE_mesh_vertexCos_get(me, NULL);
- BKE_crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos);
+ BKE_crazyspace_build_sculpt(eval_ctx, scene, ob, &ss->deform_imats, &ss->deform_cos);
BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
for (a = 0; a < me->totvert; ++a) {
@@ -976,6 +980,9 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
}
}
}
+
+ /* 2.8x - avoid full mesh update! */
+ BKE_mesh_batch_cache_dirty(me, BKE_MESH_BATCH_DIRTY_SCULPT_COORDS);
}
int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 8c94cdfe784..7d1c80dca41 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -78,7 +78,6 @@
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
-#include "BKE_depsgraph.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
#include "BKE_cdderivedmesh.h"
@@ -86,6 +85,9 @@
#include "BKE_scene.h"
#include "BKE_deform.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RE_render_ext.h"
unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
@@ -250,7 +252,7 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData
{
struct LatticeDeformData *lattice_deform_data = NULL;
- if (psys_in_edit_mode(sim->scene, sim->psys) == 0) {
+ if (psys_in_edit_mode(sim->eval_ctx->view_layer, sim->psys) == 0) {
Object *lattice = NULL;
ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys);
int mode = G.is_rendering ? eModifierMode_Render : eModifierMode_Realtime;
@@ -286,10 +288,16 @@ void psys_enable_all(Object *ob)
for (; psys; psys = psys->next)
psys->flag &= ~PSYS_DISABLED;
}
-bool psys_in_edit_mode(Scene *scene, ParticleSystem *psys)
+
+bool psys_in_edit_mode(ViewLayer *view_layer, ParticleSystem *psys)
{
- return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys == psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit) && !psys->renderdata);
+ return (view_layer->basact &&
+ (view_layer->basact->object->mode & OB_MODE_PARTICLE_EDIT) &&
+ psys == psys_get_current((view_layer->basact)->object) &&
+ (psys->edit || psys->pointcache->edit) &&
+ !psys->renderdata);
}
+
bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_params)
{
ParticleSystemModifierData *psmd;
@@ -319,18 +327,17 @@ bool psys_check_edited(ParticleSystem *psys)
void psys_check_group_weights(ParticleSettings *part)
{
ParticleDupliWeight *dw, *tdw;
- GroupObject *go;
int current = 0;
- if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first) {
+ if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->view_layer->object_bases.first) {
/* First try to find NULL objects from their index,
* and remove all weights that don't have an object in the group. */
dw = part->dupliweights.first;
while (dw) {
if (dw->ob == NULL || !BKE_group_object_exists(part->dup_group, dw->ob)) {
- go = (GroupObject *)BLI_findlink(&part->dup_group->gobject, dw->index);
- if (go) {
- dw->ob = go->ob;
+ Base *base = BLI_findlink(&part->dup_group->view_layer->object_bases, dw->index);
+ if (base != NULL) {
+ dw->ob = base->object;
}
else {
tdw = dw->next;
@@ -344,21 +351,21 @@ void psys_check_group_weights(ParticleSettings *part)
}
/* then add objects in the group to new list */
- go = part->dup_group->gobject.first;
- while (go) {
+ FOREACH_GROUP_OBJECT(part->dup_group, object)
+ {
dw = part->dupliweights.first;
- while (dw && dw->ob != go->ob)
+ while (dw && dw->ob != object) {
dw = dw->next;
-
+ }
+
if (!dw) {
dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight");
- dw->ob = go->ob;
+ dw->ob = object;
dw->count = 1;
BLI_addtail(&part->dupliweights, dw);
}
-
- go = go->next;
}
+ FOREACH_GROUP_OBJECT_END
dw = part->dupliweights.first;
for (; dw; dw = dw->next) {
@@ -606,6 +613,8 @@ void psys_free(Object *ob, ParticleSystem *psys)
MEM_freeN(psys->pdd);
}
+ BKE_particle_batch_cache_free(psys);
+
MEM_freeN(psys);
}
}
@@ -1841,7 +1850,7 @@ void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
}
}
-int do_guides(ParticleSettings *part, ListBase *effectors, ParticleKey *state, int index, float time)
+int do_guides(const EvaluationContext *eval_ctx, ParticleSettings *part, ListBase *effectors, ParticleKey *state, int index, float time)
{
CurveMapping *clumpcurve = (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) ? part->clumpcurve : NULL;
CurveMapping *roughcurve = (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) ? part->roughcurve : NULL;
@@ -1904,7 +1913,7 @@ int do_guides(ParticleSettings *part, ListBase *effectors, ParticleKey *state, i
/* curve taper */
if (cu->taperobj)
- mul_v3_fl(vec_to_point, BKE_displist_calc_taper(eff->scene, cu->taperobj, (int)(data->strength * guidetime * 100.0f), 100));
+ mul_v3_fl(vec_to_point, BKE_displist_calc_taper(eval_ctx, eff->scene, cu->taperobj, (int)(data->strength * guidetime * 100.0f), 100));
else { /* curve size*/
if (cu->flag & CU_PATH_RADIUS) {
@@ -2087,7 +2096,7 @@ static bool psys_thread_context_init_path(
psys_thread_context_init(ctx, sim);
/*---start figuring out what is actually wanted---*/
- if (psys_in_edit_mode(scene, psys)) {
+ if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys)) {
ParticleEditSettings *pset = &scene->toolsettings->particle;
if ((psys->renderdata == 0 && use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
@@ -2176,7 +2185,7 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp
ParticleSystem *psys = ctx->sim.psys;
ParticleSettings *part = psys->part;
ParticleCacheKey **cache = psys->childcache;
- ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.scene, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache;
+ ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.eval_ctx->view_layer, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache;
ParticleCacheKey *child, *key[4];
ParticleTexture ptex;
float *cpa_fuv = 0, *par_rot = 0, rot[4];
@@ -2585,7 +2594,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
if ((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache) == 0)
return;
- if (psys_in_edit_mode(sim->scene, psys))
+ if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys))
if (psys->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
return;
@@ -2705,7 +2714,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
if (sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT) == 0) {
for (k = 0, ca = cache[p]; k <= segments; k++, ca++)
/* ca is safe to cast, since only co and vel are used */
- do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)ca, p, (float)k / (float)segments);
+ do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, (ParticleKey *)ca, p, (float)k / (float)segments);
}
/* lattices have to be calculated separately to avoid mixups between effector calculations */
@@ -2753,7 +2762,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
if (vg_length)
MEM_freeN(vg_length);
}
-void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cfra, const bool use_render_params)
+void psys_cache_edit_paths(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, PTCacheEdit *edit, float cfra, const bool use_render_params)
{
ParticleCacheKey *ca, **cache = edit->pathcache;
ParticleEditSettings *pset = &scene->toolsettings->particle;
@@ -2944,6 +2953,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
if (psys) {
ParticleSimulationData sim = {0};
+ sim.eval_ctx = eval_ctx;
sim.scene = scene;
sim.ob = ob;
sim.psys = psys;
@@ -3158,8 +3168,8 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n
psys->flag = PSYS_CURRENT;
psys->cfra = BKE_scene_frame_get_from_ctime(scene, CFRA + 1);
- DAG_relations_tag_update(G.main);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(G.main);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
return md;
}
@@ -3204,8 +3214,8 @@ void object_remove_particle_system(Scene *UNUSED(scene), Object *ob)
else
ob->mode &= ~OB_MODE_PARTICLE_EDIT;
- DAG_relations_tag_update(G.main);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(G.main);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
static void default_particle_settings(ParticleSettings *part)
@@ -3290,6 +3300,7 @@ static void default_particle_settings(ParticleSettings *part)
part->omat = 1;
part->use_modifier_stack = false;
+ part->draw_size = 0.1f;
}
@@ -3766,7 +3777,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
/* pind.dm disabled in editmode means we don't get effectors taken into
* account when subdividing for instance */
- pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : psys->hair_out_dm;
+ pind.dm = psys_in_edit_mode(sim->eval_ctx->view_layer, psys) ? NULL : psys->hair_out_dm;
init_particle_interpolation(sim->ob, psys, pa, &pind);
do_particle_interpolation(psys, p, pa, t, &pind, state);
@@ -3781,7 +3792,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
mul_mat3_m4_v3(hairmat, state->vel);
if (sim->psys->effectors && (part->flag & PART_CHILD_GUIDE) == 0) {
- do_guides(sim->psys->part, sim->psys->effectors, state, p, state->time);
+ do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, state, p, state->time);
/* TODO: proper velocity handling */
}
@@ -4308,9 +4319,10 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3]
madd_v3_v3fl(center, yvec, bb->offset[1]);
}
-void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
+void psys_apply_hair_lattice(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ParticleSystem *psys)
{
ParticleSimulationData sim = {0};
+ sim.eval_ctx = eval_ctx;
sim.scene = scene;
sim.ob = ob;
sim.psys = psys;
@@ -4343,3 +4355,22 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
psys->flag |= PSYS_EDITED;
}
}
+
+
+
+/* Draw Engine */
+void (*BKE_particle_batch_cache_dirty_cb)(ParticleSystem *psys, int mode) = NULL;
+void (*BKE_particle_batch_cache_free_cb)(ParticleSystem *psys) = NULL;
+
+void BKE_particle_batch_cache_dirty(ParticleSystem *psys, int mode)
+{
+ if (psys->batch_cache) {
+ BKE_particle_batch_cache_dirty_cb(psys, mode);
+ }
+}
+void BKE_particle_batch_cache_free(ParticleSystem *psys)
+{
+ if (psys->batch_cache) {
+ BKE_particle_batch_cache_free_cb(psys);
+ }
+}
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
index bfcda89a635..d2ad05c20b7 100644
--- a/source/blender/blenkernel/intern/particle_child.c
+++ b/source/blender/blenkernel/intern/particle_child.c
@@ -702,7 +702,7 @@ void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
if (part->flag & PART_CHILD_EFFECT)
/* state is safe to cast, since only co and vel are used */
- guided = do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t);
+ guided = do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t);
if (guided == 0) {
float orco_offset[3];
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 9a7980827ad..ff8a638089f 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -312,19 +312,16 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
static void hammersley_create(float *out, int n, int seed, float amount)
{
RNG *rng;
- double p, t, offs[2];
- int k, kk;
+
+ double offs[2], t;
rng = BLI_rng_new(31415926 + n + seed);
offs[0] = BLI_rng_get_double(rng) + (double)amount;
offs[1] = BLI_rng_get_double(rng) + (double)amount;
BLI_rng_free(rng);
- for (k = 0; k < n; k++) {
- t = 0;
- for (p = 0.5, kk = k; kk; p *= 0.5, kk >>= 1)
- if (kk & 1) /* kk mod 2 = 1 */
- t += p;
+ for (int k = 0; k < n; k++) {
+ BLI_hammersley_1D(k, &t);
out[2*k + 0] = fmod((double)k/(double)n + offs[0], 1.0);
out[2*k + 1] = fmod(t + offs[1], 1.0);
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 38eb861599a..da227514512 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -78,6 +78,7 @@
#include "BKE_particle.h"
#include "BKE_global.h"
+#include "BKE_collection.h"
#include "BKE_DerivedMesh.h"
#include "BKE_object.h"
#include "BKE_material.h"
@@ -88,7 +89,8 @@
#include "BKE_modifier.h"
#include "BKE_scene.h"
#include "BKE_bvhutils.h"
-#include "BKE_depsgraph.h"
+
+#include "DEG_depsgraph.h"
#include "PIL_time.h"
@@ -980,14 +982,14 @@ void psys_get_birth_coords(ParticleSimulationData *sim, ParticleData *pa, Partic
}
/* recursively evaluate emitter parent anim at cfra */
-static void evaluate_emitter_anim(Scene *scene, Object *ob, float cfra)
+static void evaluate_emitter_anim(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float cfra)
{
if (ob->parent)
- evaluate_emitter_anim(scene, ob->parent, cfra);
+ evaluate_emitter_anim(eval_ctx, scene, ob->parent, cfra);
/* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, cfra, ADT_RECALC_ANIM);
- BKE_object_where_is_calc_time(scene, ob, cfra);
+ BKE_object_where_is_calc_time(eval_ctx, scene, ob, cfra);
}
/* sets particle to the emitter surface with initial velocity & rotation */
@@ -1001,7 +1003,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
/* get precise emitter matrix if particle is born */
if (part->type != PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) {
- evaluate_emitter_anim(sim->scene, sim->ob, pa->time);
+ evaluate_emitter_anim(sim->eval_ctx, sim->scene, sim->ob, pa->time);
psys->flag |= PSYS_OB_ANIM_RESTORE;
}
@@ -1133,7 +1135,8 @@ static void set_keyed_keys(ParticleSimulationData *sim)
int totpart = psys->totpart, k, totkeys = psys->totkeyed;
int keyed_flag = 0;
- ksim.scene= sim->scene;
+ ksim.eval_ctx = sim->eval_ctx;
+ ksim.scene = sim->scene;
/* no proper targets so let's clear and bail out */
if (psys->totkeyed==0) {
@@ -1294,7 +1297,7 @@ void psys_update_particle_tree(ParticleSystem *psys, float cfra)
static void psys_update_effectors(ParticleSimulationData *sim)
{
pdEndEffectors(&sim->psys->effectors);
- sim->psys->effectors = pdInitEffectors(sim->scene, sim->ob, sim->psys,
+ sim->psys->effectors = pdInitEffectors(sim->eval_ctx, sim->scene, sim->ob, sim->psys,
sim->psys->part->effector_weights, true);
precalc_guides(sim, sim->psys->effectors);
}
@@ -2115,7 +2118,7 @@ static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, floa
tkey.time=pa->state.time;
if (part->type != PART_HAIR) {
- if (do_guides(sim->psys->part, sim->psys->effectors, &tkey, p, time)) {
+ if (do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, &tkey, p, time)) {
copy_v3_v3(pa->state.co,tkey.co);
/* guides don't produce valid velocity */
sub_v3_v3v3(pa->state.vel, tkey.co, pa->prev_state.co);
@@ -2896,7 +2899,6 @@ 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;
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)
@@ -2931,7 +2933,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
skip = 1; /* draw visualization */
else if (psys->pointcache->flag & PTCACHE_BAKING)
skip = 1; /* no need to cache paths while baking dynamics */
- else if (psys_in_edit_mode(sim->scene, psys)) {
+ else if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys)) {
if ((pset->flag & PE_DRAW_PART)==0)
skip = 1;
else if (part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0)
@@ -2941,8 +2943,9 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
/* particle instance modifier with "path" option need cached paths even if particle system doesn't */
- for (base = sim->scene->base.first; base; base= base->next) {
- ModifierData *md = modifiers_findByType(base->object, eModifierType_ParticleInstance);
+ FOREACH_SCENE_OBJECT(sim->scene, ob)
+ {
+ ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleInstance);
if (md) {
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
if (pimd->flag & eParticleInstanceFlag_Path && pimd->ob == sim->ob && pimd->psys == (psys - (ParticleSystem*)sim->ob->particlesystem.first)) {
@@ -2951,6 +2954,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
}
}
}
+ FOREACH_SCENE_OBJECT_END
if (!skip) {
psys_cache_paths(sim, cfra, use_render_params);
@@ -3196,7 +3200,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
psys->hair_out_dm = CDDM_copy(psys->hair_in_dm);
psys->hair_out_dm->getVertCos(psys->hair_out_dm, deformedVerts);
- clothModifier_do(psys->clmd, sim->scene, sim->ob, psys->hair_in_dm, deformedVerts);
+ clothModifier_do(psys->clmd, sim->eval_ctx, sim->scene, sim->ob, psys->hair_in_dm, deformedVerts);
CDDM_apply_vert_coords(psys->hair_out_dm, deformedVerts);
@@ -4156,7 +4160,7 @@ static int hair_needs_recalc(ParticleSystem *psys)
/* main particle update call, checks that things are ok on the large scale and
* then advances in to actual particle calculations depending on particle type */
-void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params)
+void particle_system_update(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params)
{
ParticleSimulationData sim= {0};
ParticleSettings *part = psys->part;
@@ -4170,10 +4174,11 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons
cfra= BKE_scene_frame_get(scene);
- sim.scene= scene;
- sim.ob= ob;
- sim.psys= psys;
- sim.psmd= psys_get_modifier(ob, psys);
+ sim.eval_ctx = eval_ctx;
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(ob, psys);
/* system was already updated from modifier stack */
if (sim.psmd->flag & eParticleSystemFlag_psys_updated) {
@@ -4316,7 +4321,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons
/* make sure emitter is left at correct time (particle emission can change this) */
if (psys->flag & PSYS_OB_ANIM_RESTORE) {
- evaluate_emitter_anim(scene, ob, cfra);
+ evaluate_emitter_anim(eval_ctx, scene, ob, cfra);
psys->flag &= ~PSYS_OB_ANIM_RESTORE;
}
@@ -4326,6 +4331,8 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons
/* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */
if (psys->renderdata==0)
invert_m4_m4(psys->imat, ob->obmat);
+
+ BKE_particle_batch_cache_dirty(psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
}
/* ID looper */
@@ -4356,12 +4363,30 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func,
/* **** Depsgraph evaluation **** */
-void BKE_particle_system_eval_init(EvaluationContext *UNUSED(eval_ctx),
+void BKE_particle_system_settings_eval(const struct EvaluationContext *UNUSED(eval_ctx),
+ ParticleSystem *psys)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s (%p)\n", __func__, psys->name, psys);
+ }
+ psys->recalc |= psys->part->recalc;
+}
+
+void BKE_particle_system_settings_recalc_clear(struct EvaluationContext *UNUSED(eval_ctx),
+ ParticleSettings *particle_settings)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s (%p)\n", __func__, particle_settings->id.name, particle_settings);
+ }
+ particle_settings->recalc = 0;
+}
+
+void BKE_particle_system_eval_init(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *ob)
{
if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s\n", __func__, ob->id.name);
+ printf("%s on %s (%p)\n", __func__, ob->id.name, ob);
}
BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 39d1d8e8510..585a18cdad5 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -41,6 +41,7 @@
#include "BKE_paint.h"
#include "GPU_buffers.h"
+#include "GPU_immediate.h"
#include "bmesh.h"
@@ -1162,15 +1163,16 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
void BKE_pbvh_draw_BB(PBVH *bvh)
{
- GPU_pbvh_BB_draw_init();
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
for (int a = 0; a < bvh->totnode; a++) {
PBVHNode *node = &bvh->nodes[a];
- GPU_pbvh_BB_draw(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0));
+ GPU_pbvh_BB_draw(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0), pos);
}
- GPU_pbvh_BB_draw_end();
+ immUnbindProgram();
}
static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
@@ -1991,24 +1993,6 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data_v)
{
PBVHNodeDrawData *data = data_v;
-#if 0
- /* XXX: Just some quick code to show leaf nodes in different colors */
- float col[3];
- float spec[3] = {0.0f, 0.0f, 0.0f};
-
- if (0) { //is_partial) {
- col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6;
- }
- else {
- srand((long long)node);
- for (int i = 0; i < 3; ++i)
- col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7;
- }
-
- GPU_basic_shader_colors(col, spec, 0, 1.0f);
- glColor3f(1, 0, 0);
-#endif
-
if (!(node->flag & PBVH_FullyHidden)) {
GPU_pbvh_buffers_draw(node->draw_buffers,
data->setMaterial,
@@ -2115,6 +2099,67 @@ void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*fnors)[3],
BKE_pbvh_draw_BB(bvh);
}
+struct PBVHNodeDrawCallbackData {
+
+ void (*draw_fn)(void *user_data, Gwn_Batch *batch);
+ void *user_data;
+ bool fast;
+};
+
+static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
+{
+ struct PBVHNodeDrawCallbackData *data = data_v;
+
+ if (!(node->flag & PBVH_FullyHidden)) {
+ Gwn_Batch *triangles = GPU_pbvh_buffers_batch_get(node->draw_buffers, data->fast);
+ if (triangles != NULL) {
+ data->draw_fn(data->user_data, triangles);
+ }
+ }
+}
+
+/**
+ * Version of #BKE_pbvh_draw that runs a callback.
+ */
+void BKE_pbvh_draw_cb(
+ PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast,
+ void (*draw_fn)(void *user_data, Gwn_Batch *batch), void *user_data)
+{
+ struct PBVHNodeDrawCallbackData draw_data = {
+ .fast = fast,
+ .draw_fn = draw_fn,
+ .user_data = user_data,
+ };
+ PBVHNode **nodes;
+ int totnode;
+
+ for (int a = 0; a < bvh->totnode; a++)
+ pbvh_node_check_diffuse_changed(bvh, &bvh->nodes[a]);
+
+ BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers),
+ &nodes, &totnode);
+
+ pbvh_update_normals(bvh, nodes, totnode, fnors);
+ pbvh_update_draw_buffers(bvh, nodes, totnode);
+
+ if (nodes) MEM_freeN(nodes);
+
+ if (planes) {
+ BKE_pbvh_search_callback(
+ bvh, BKE_pbvh_node_planes_contain_AABB,
+ planes, pbvh_node_draw_cb, &draw_data);
+ }
+ else {
+ BKE_pbvh_search_callback(
+ bvh, NULL,
+ NULL, pbvh_node_draw_cb, &draw_data);
+ }
+#if 0
+ if (G.debug_value == 14)
+ pbvh_draw_BB(bvh);
+#endif
+}
+
void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, void **gridfaces,
DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
{
@@ -2324,22 +2369,22 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK);
}
-void pbvh_show_diffuse_color_set(PBVH *bvh, bool show_diffuse_color)
+bool pbvh_has_mask(PBVH *bvh)
{
- bool has_mask = false;
-
switch (bvh->type) {
case PBVH_GRIDS:
- has_mask = (bvh->gridkey.has_mask != 0);
- break;
+ return (bvh->gridkey.has_mask != 0);
case PBVH_FACES:
- has_mask = (bvh->vdata && CustomData_get_layer(bvh->vdata,
- CD_PAINT_MASK));
- break;
+ return (bvh->vdata && CustomData_get_layer(bvh->vdata,
+ CD_PAINT_MASK));
case PBVH_BMESH:
- has_mask = (bvh->bm && (CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK) != -1));
- break;
+ return (bvh->bm && (CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK) != -1));
}
- bvh->show_diffuse_color = !has_mask || show_diffuse_color;
+ return false;
+}
+
+void pbvh_show_diffuse_color_set(PBVH *bvh, bool show_diffuse_color)
+{
+ bvh->show_diffuse_color = !pbvh_has_mask(bvh) || show_diffuse_color;
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 7a1b378b3c4..b794fcfd929 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -3509,13 +3509,14 @@ PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, const ListBase *ptcach
* every user action changing stuff, and then it runs a complete bake??? (ton) */
/* Baking */
-void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene)
+void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene, ViewLayer *view_layer)
{
PTCacheBaker baker;
memset(&baker, 0, sizeof(baker));
baker.main = bmain;
baker.scene = scene;
+ baker.view_layer = view_layer;
baker.bake = 0;
baker.render = 0;
baker.anim_init = 0;
@@ -3541,6 +3542,8 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
{
Main *bmain = baker->main;
Scene *scene = baker->scene;
+ ViewLayer *view_layer = baker->view_layer;
+ struct Depsgraph *depsgraph = baker->depsgraph;
Scene *sce_iter; /* SETLOOPER macro only */
Base *base;
ListBase pidlist;
@@ -3603,7 +3606,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
}
}
else {
- for (SETLOOPER(scene, sce_iter, base)) {
+ for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) {
/* cache/bake everything in the scene */
BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
@@ -3659,7 +3662,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
stime = ptime = PIL_check_seconds_timer();
for (int fr = CFRA; fr <= endframe; fr += baker->quick_step, CFRA = fr) {
- BKE_scene_update_for_newframe(G.main->eval_ctx, bmain, scene, scene->lay);
+ BKE_scene_graph_update_for_newframe(G.main->eval_ctx, depsgraph, bmain, scene, view_layer);
if (baker->update_progress) {
float progress = ((float)(CFRA - startframe)/(float)(endframe - startframe));
@@ -3714,7 +3717,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
}
}
else {
- for (SETLOOPER(scene, sce_iter, base)) {
+ for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) {
BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
for (pid=pidlist.first; pid; pid=pid->next) {
@@ -3745,7 +3748,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
CFRA = cfrao;
if (bake) { /* already on cfra unless baking */
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
}
/* TODO: call redraw all windows somehow */
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 03eb83376e7..bd4b817c8cd 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -55,9 +55,9 @@
#include "DNA_scene_types.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_depsgraph.h"
#include "BKE_effect.h"
#include "BKE_global.h"
+#include "BKE_group.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_mesh.h"
@@ -91,26 +91,30 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
if (rbw->physics_world) {
/* free physics references, we assume that all physics objects in will have been added to the world */
- GroupObject *go;
if (rbw->constraints) {
- for (go = rbw->constraints->gobject.first; go; go = go->next) {
- if (go->ob && go->ob->rigidbody_constraint) {
- RigidBodyCon *rbc = go->ob->rigidbody_constraint;
-
- if (rbc->physics_constraint)
+ FOREACH_GROUP_OBJECT(rbw->constraints, object)
+ {
+ if (object->rigidbody_constraint) {
+ RigidBodyCon *rbc = object->rigidbody_constraint;
+ if (rbc->physics_constraint) {
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
+ }
}
}
+ FOREACH_GROUP_OBJECT_END
}
- if (rbw->group) {
- for (go = rbw->group->gobject.first; go; go = go->next) {
- if (go->ob && go->ob->rigidbody_object) {
- RigidBodyOb *rbo = go->ob->rigidbody_object;
- if (rbo->physics_object)
+ if (rbw->group) {
+ FOREACH_GROUP_OBJECT(rbw->group, object)
+ {
+ if (object->rigidbody_object) {
+ RigidBodyOb *rbo = object->rigidbody_object;
+ if (rbo->physics_object) {
RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
+ }
}
}
+ FOREACH_GROUP_OBJECT_END
}
/* free dynamics world */
RB_dworld_delete(rbw->physics_world);
@@ -1125,7 +1129,6 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
RigidBodyWorld *rbw = scene->rigidbody_world;
RigidBodyOb *rbo = ob->rigidbody_object;
RigidBodyCon *rbc;
- GroupObject *go;
int i;
if (rbw) {
@@ -1145,8 +1148,8 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
/* remove object from rigid body constraints */
if (rbw->constraints) {
- for (go = rbw->constraints->gobject.first; go; go = go->next) {
- Object *obt = go->ob;
+ FOREACH_GROUP_OBJECT(rbw->constraints, obt)
+ {
if (obt && obt->rigidbody_constraint) {
rbc = obt->rigidbody_constraint;
if (ELEM(ob, rbc->ob1, rbc->ob2)) {
@@ -1154,6 +1157,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
}
}
}
+ FOREACH_GROUP_OBJECT_END
}
}
@@ -1187,20 +1191,22 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
/* Update object array and rigid body count so they're in sync with the rigid body group */
static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
{
- GroupObject *go;
int i, n;
- n = BLI_listbase_count(&rbw->group->gobject);
+ n = BLI_listbase_count(&rbw->group->view_layer->object_bases);
if (rbw->numbodies != n) {
rbw->numbodies = n;
rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies);
}
- for (go = rbw->group->gobject.first, i = 0; go; go = go->next, i++) {
- Object *ob = go->ob;
- rbw->objects[i] = ob;
+ i = 0;
+ FOREACH_GROUP_OBJECT(rbw->group, object)
+ {
+ rbw->objects[i] = object;
+ i++;
}
+ FOREACH_GROUP_OBJECT_END
}
static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
@@ -1223,7 +1229,7 @@ static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
rigidbody_update_ob_array(rbw);
}
-static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo)
+static void rigidbody_update_sim_ob(const struct EvaluationContext *eval_ctx, Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo)
{
float loc[3];
float rot[4];
@@ -1271,7 +1277,7 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o
ListBase *effectors;
/* get effectors present in the group specified by effector_weights */
- effectors = pdInitEffectors(scene, ob, NULL, effector_weights, true);
+ effectors = pdInitEffectors(eval_ctx, scene, ob, NULL, effector_weights, true);
if (effectors) {
float eff_force[3] = {0.0f, 0.0f, 0.0f};
float eff_loc[3], eff_vel[3];
@@ -1312,10 +1318,8 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o
*
* \param rebuild Rebuild entire simulation
*/
-static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool rebuild)
+static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx, Scene *scene, RigidBodyWorld *rbw, bool rebuild)
{
- GroupObject *go;
-
/* update world */
if (rebuild)
BKE_rigidbody_validate_sim_world(scene, rbw, true);
@@ -1328,28 +1332,26 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool
* Memory management needs redesign here, this is just a dirty workaround.
*/
if (rebuild && rbw->constraints) {
- for (go = rbw->constraints->gobject.first; go; go = go->next) {
- Object *ob = go->ob;
- if (ob) {
- RigidBodyCon *rbc = ob->rigidbody_constraint;
- if (rbc && rbc->physics_constraint) {
- RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
- RB_constraint_delete(rbc->physics_constraint);
- rbc->physics_constraint = NULL;
- }
+ FOREACH_GROUP_OBJECT(rbw->constraints, ob)
+ {
+ RigidBodyCon *rbc = ob->rigidbody_constraint;
+ if (rbc && rbc->physics_constraint) {
+ RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
+ RB_constraint_delete(rbc->physics_constraint);
+ rbc->physics_constraint = NULL;
}
}
+ FOREACH_GROUP_OBJECT_END
}
/* update objects */
- for (go = rbw->group->gobject.first; go; go = go->next) {
- Object *ob = go->ob;
-
- if (ob && ob->type == OB_MESH) {
+ FOREACH_GROUP_OBJECT(rbw->group, ob)
+ {
+ if (ob->type == OB_MESH) {
/* validate that we've got valid object set up here... */
RigidBodyOb *rbo = ob->rigidbody_object;
/* update transformation matrix of the object so we don't get a frame of lag for simple animations */
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc(eval_ctx, scene, ob);
if (rbo == NULL) {
/* Since this object is included in the sim group but doesn't have
@@ -1383,65 +1385,62 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool
}
/* update simulation object... */
- rigidbody_update_sim_ob(scene, rbw, ob, rbo);
+ rigidbody_update_sim_ob(eval_ctx, scene, rbw, ob, rbo);
}
}
+ FOREACH_GROUP_OBJECT_END
/* update constraints */
if (rbw->constraints == NULL) /* no constraints, move on */
return;
- for (go = rbw->constraints->gobject.first; go; go = go->next) {
- Object *ob = go->ob;
- if (ob) {
- /* validate that we've got valid object set up here... */
- RigidBodyCon *rbc = ob->rigidbody_constraint;
- /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
- BKE_object_where_is_calc(scene, ob);
+ FOREACH_GROUP_OBJECT(rbw->constraints, ob)
+ {
+ /* validate that we've got valid object set up here... */
+ RigidBodyCon *rbc = ob->rigidbody_constraint;
+ /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
+ BKE_object_where_is_calc(eval_ctx, scene, ob);
- if (rbc == NULL) {
- /* Since this object is included in the group but doesn't have
- * constraint settings (perhaps it was added manually), add!
- */
- ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED);
- rigidbody_validate_sim_constraint(rbw, ob, true);
+ if (rbc == NULL) {
+ /* Since this object is included in the group but doesn't have
+ * constraint settings (perhaps it was added manually), add!
+ */
+ ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED);
+ rigidbody_validate_sim_constraint(rbw, ob, true);
- rbc = ob->rigidbody_constraint;
+ rbc = ob->rigidbody_constraint;
+ }
+ else {
+ /* perform simulation data updates as tagged */
+ if (rebuild) {
+ /* World has been rebuilt so rebuild constraint */
+ rigidbody_validate_sim_constraint(rbw, ob, true);
}
- else {
- /* perform simulation data updates as tagged */
- if (rebuild) {
- /* World has been rebuilt so rebuild constraint */
- rigidbody_validate_sim_constraint(rbw, ob, true);
- }
- else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) {
- rigidbody_validate_sim_constraint(rbw, ob, false);
- }
- rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
+ else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) {
+ rigidbody_validate_sim_constraint(rbw, ob, false);
}
+ rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
}
}
+ FOREACH_GROUP_OBJECT_END
}
static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
{
- GroupObject *go;
-
- for (go = rbw->group->gobject.first; go; go = go->next) {
- Object *ob = go->ob;
-
- if (ob) {
- RigidBodyOb *rbo = ob->rigidbody_object;
- /* reset kinematic state for transformed objects */
- if (rbo && (ob->flag & SELECT) && (G.moving & G_TRANSFORM_OBJ)) {
- RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
- RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
- /* deactivate passive objects so they don't interfere with deactivation of active objects */
- if (rbo->type == RBO_TYPE_PASSIVE)
- RB_body_deactivate(rbo->physics_object);
- }
+ FOREACH_GROUP_BASE(rbw->group, base)
+ {
+ Object *ob = base->object;
+ RigidBodyOb *rbo = ob->rigidbody_object;
+ /* Reset kinematic state for transformed objects. */
+ if (rbo && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ)) {
+ RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
+ RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
+ /* Deactivate passive objects so they don't interfere with deactivation of active objects. */
+ if (rbo->type == RBO_TYPE_PASSIVE)
+ RB_body_deactivate(rbo->physics_object);
}
}
+ FOREACH_GROUP_BASE_END
}
bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime)
@@ -1556,7 +1555,7 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
/* Rebuild rigid body world */
/* NOTE: this needs to be called before frame update to work correctly */
-void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
+void BKE_rigidbody_rebuild_world(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
PointCache *cache;
@@ -1568,14 +1567,14 @@ void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
cache = rbw->pointcache;
/* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */
- if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->gobject)) {
+ if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->view_layer->object_bases)) {
cache->flag |= PTCACHE_OUTDATED;
}
if (ctime == startframe + 1 && rbw->ltime == startframe) {
if (cache->flag & PTCACHE_OUTDATED) {
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
- rigidbody_update_simulation(scene, rbw, true);
+ rigidbody_update_simulation(eval_ctx, scene, rbw, true);
BKE_ptcache_validate(cache, (int)ctime);
cache->last_exact = 0;
cache->flag &= ~PTCACHE_REDO_NEEDED;
@@ -1584,7 +1583,7 @@ void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
}
/* Run RigidBody simulation for the specified physics world */
-void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
+void BKE_rigidbody_do_simulation(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime)
{
float timestep;
RigidBodyWorld *rbw = scene->rigidbody_world;
@@ -1622,14 +1621,14 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
}
/* advance simulation, we can only step one frame forward */
- if (can_simulate) {
+ if (ctime == rbw->ltime + 1) {
/* write cache for first frame when on second frame */
if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
BKE_ptcache_write(&pid, startframe);
}
/* update and validate simulation */
- rigidbody_update_simulation(scene, rbw, false);
+ rigidbody_update_simulation(eval_ctx, scene, rbw, false);
/* calculate how much time elapsed since last step in seconds */
timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale;
@@ -1673,8 +1672,8 @@ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {}
bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) { return false; }
void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {}
-void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) {}
-void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {}
+void BKE_rigidbody_rebuild_world(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime) {}
+void BKE_rigidbody_do_simulation(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime) {}
#ifdef __GNUC__
# pragma GCC diagnostic pop
@@ -1685,7 +1684,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {}
/* -------------------- */
/* Depsgraph evaluation */
-void BKE_rigidbody_rebuild_sim(EvaluationContext *UNUSED(eval_ctx),
+void BKE_rigidbody_rebuild_sim(const struct EvaluationContext *eval_ctx,
Scene *scene)
{
float ctime = BKE_scene_frame_get(scene);
@@ -1696,11 +1695,11 @@ void BKE_rigidbody_rebuild_sim(EvaluationContext *UNUSED(eval_ctx),
/* rebuild sim data (i.e. after resetting to start of timeline) */
if (BKE_scene_check_rigidbody_active(scene)) {
- BKE_rigidbody_rebuild_world(scene, ctime);
+ BKE_rigidbody_rebuild_world(eval_ctx, scene, ctime);
}
}
-void BKE_rigidbody_eval_simulation(EvaluationContext *UNUSED(eval_ctx),
+void BKE_rigidbody_eval_simulation(const struct EvaluationContext *eval_ctx,
Scene *scene)
{
float ctime = BKE_scene_frame_get(scene);
@@ -1711,11 +1710,11 @@ void BKE_rigidbody_eval_simulation(EvaluationContext *UNUSED(eval_ctx),
/* evaluate rigidbody sim */
if (BKE_scene_check_rigidbody_active(scene)) {
- BKE_rigidbody_do_simulation(scene, ctime);
+ BKE_rigidbody_do_simulation(eval_ctx, scene, ctime);
}
}
-void BKE_rigidbody_object_sync_transforms(EvaluationContext *UNUSED(eval_ctx),
+void BKE_rigidbody_object_sync_transforms(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *ob)
{
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 9ce578a9105..c095236733f 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -49,6 +49,7 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_gpencil_types.h"
#include "BLI_math.h"
@@ -67,8 +68,8 @@
#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"
#include "BKE_fcurve.h"
#include "BKE_freestyle.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"
@@ -92,9 +94,13 @@
#include "BKE_sequencer.h"
#include "BKE_sound.h"
#include "BKE_unit.h"
+#include "BKE_workspace.h"
#include "BKE_world.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_debug.h"
+#include "DEG_depsgraph_query.h"
#include "RE_engine.h"
@@ -107,6 +113,8 @@
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_BLENDER_EEVEE = "BLENDER_EEVEE";
const char *RE_engine_id_CYCLES = "CYCLES";
void free_avicodecdata(AviCodecData *acd)
@@ -157,25 +165,37 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
sce_dst->ed = NULL;
- sce_dst->theDag = NULL;
- sce_dst->depsgraph = NULL;
+ sce_dst->depsgraph_hash = NULL;
sce_dst->obedit = NULL;
- sce_dst->stats = NULL;
sce_dst->fps_info = NULL;
- BLI_duplicatelist(&(sce_dst->base), &(sce_src->base));
- for (Base *base_dst = sce_dst->base.first, *base_src = sce_src->base.first;
- base_dst;
- base_dst = base_dst->next, base_src = base_src->next)
+ /* layers and collections */
+ sce_dst->collection = MEM_dupallocN(sce_src->collection);
+ SceneCollection *mc_src = BKE_collection_master(&sce_src->id);
+ SceneCollection *mc_dst = BKE_collection_master(&sce_dst->id);
+
+ /* Recursively creates a new SceneCollection tree. */
+ BKE_collection_copy_data(mc_dst, mc_src, flag_subdata);
+
+ IDPropertyTemplate val = {0};
+ BLI_duplicatelist(&sce_dst->view_layers, &sce_src->view_layers);
+ for (ViewLayer *view_layer_src = sce_src->view_layers.first, *view_layer_dst = sce_dst->view_layers.first;
+ view_layer_src;
+ view_layer_src = view_layer_src->next, view_layer_dst = view_layer_dst->next)
{
- if (base_src == sce_src->basact) {
- sce_dst->basact = base_dst;
- }
+ BKE_view_layer_copy_data(view_layer_dst, view_layer_src, mc_dst, mc_src, flag_subdata);
+ }
+
+ sce_dst->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ if (sce_src->collection_properties) {
+ IDP_MergeGroup_ex(sce_dst->collection_properties, sce_src->collection_properties, true, flag_subdata);
+ }
+ sce_dst->layer_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ if (sce_src->layer_properties) {
+ IDP_MergeGroup_ex(sce_dst->layer_properties, sce_src->layer_properties, true, flag_subdata);
}
BLI_duplicatelist(&(sce_dst->markers), &(sce_src->markers));
- BLI_duplicatelist(&(sce_dst->transform_spaces), &(sce_src->transform_spaces));
- BLI_duplicatelist(&(sce_dst->r.layers), &(sce_src->r.layers));
BLI_duplicatelist(&(sce_dst->r.views), &(sce_src->r.views));
BKE_keyingsets_copy(&(sce_dst->keyingsets), &(sce_src->keyingsets));
@@ -190,17 +210,6 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
sce_dst->rigidbody_world = BKE_rigidbody_world_copy(sce_src->rigidbody_world, flag_subdata);
}
- /* copy Freestyle settings */
- for (SceneRenderLayer *srl_dst = sce_dst->r.layers.first, *srl_src = sce_src->r.layers.first;
- srl_src;
- srl_dst = srl_dst->next, srl_src = srl_src->next)
- {
- if (srl_dst->prop != NULL) {
- srl_dst->prop = IDP_CopyProperty_ex(srl_dst->prop, flag_subdata);
- }
- BKE_freestyle_config_copy(&srl_dst->freestyleConfig, &srl_src->freestyleConfig, flag_subdata);
- }
-
/* copy color management settings */
BKE_color_managed_display_settings_copy(&sce_dst->display_settings, &sce_src->display_settings);
BKE_color_managed_view_settings_copy(&sce_dst->view_settings, &sce_src->view_settings);
@@ -289,16 +298,14 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
* But for now, let's keep it well isolated here. */
if (type == SCE_COPY_EMPTY) {
ToolSettings *ts;
- ListBase rl, rv;
+ ListBase rv;
sce_copy = BKE_scene_add(bmain, sce->id.name + 2);
- rl = sce_copy->r.layers;
rv = sce_copy->r.views;
curvemapping_free_data(&sce_copy->r.mblur_shutter_curve);
sce_copy->r = sce->r;
- sce_copy->r.layers = rl;
- sce_copy->r.actlay = 0;
+ sce_copy->active_view_layer = 0;
sce_copy->r.views = rv;
sce_copy->unit = sce->unit;
sce_copy->physics_settings = sce->physics_settings;
@@ -396,8 +403,8 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
if (type == SCE_COPY_FULL) {
/* Copy Freestyle LineStyle datablocks. */
- for (SceneRenderLayer *srl_dst = sce_copy->r.layers.first; srl_dst; srl_dst = srl_dst->next) {
- for (FreestyleLineSet *lineset = srl_dst->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ for (ViewLayer *view_layer_dst = sce_copy->view_layers.first; view_layer_dst; view_layer_dst = view_layer_dst->next) {
+ for (FreestyleLineSet *lineset = view_layer_dst->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
if (lineset->linestyle) {
/* XXX Not copying anim/actions here? */
BKE_id_copy_ex(bmain, (ID *)lineset->linestyle, (ID **)&lineset->linestyle, 0, false);
@@ -449,17 +456,13 @@ void BKE_scene_make_local(Main *bmain, Scene *sce, const bool lib_local)
}
/** Free (or release) any data used by this scene (does not free the scene itself). */
-void BKE_scene_free(Scene *sce)
+void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
{
- SceneRenderLayer *srl;
-
BKE_animdata_free((ID *)sce, false);
/* check all sequences */
BKE_sequencer_clear_scene_in_allseqs(G.main, sce);
- sce->basact = NULL;
- BLI_freelistN(&sce->base);
BKE_sequencer_editing_free(sce);
BKE_keyingsets_free(&sce->keyingsets);
@@ -487,17 +490,7 @@ void BKE_scene_free(Scene *sce)
sce->r.ffcodecdata.properties = NULL;
}
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- if (srl->prop != NULL) {
- IDP_FreeProperty(srl->prop);
- MEM_freeN(srl->prop);
- }
- BKE_freestyle_config_free(&srl->freestyleConfig);
- }
-
BLI_freelistN(&sce->markers);
- BLI_freelistN(&sce->transform_spaces);
- BLI_freelistN(&sce->r.layers);
BLI_freelistN(&sce->r.views);
if (sce->toolsettings) {
@@ -532,11 +525,8 @@ void BKE_scene_free(Scene *sce)
sce->toolsettings = NULL;
}
- DAG_scene_free(sce);
- if (sce->depsgraph)
- DEG_graph_free(sce->depsgraph);
-
- MEM_SAFE_FREE(sce->stats);
+ BKE_scene_free_depsgraph_hash(sce);
+
MEM_SAFE_FREE(sce->fps_info);
BKE_sound_destroy_scene(sce);
@@ -545,6 +535,37 @@ void BKE_scene_free(Scene *sce)
BKE_previewimg_free(&sce->preview);
curvemapping_free_data(&sce->r.mblur_shutter_curve);
+
+ for (ViewLayer *view_layer = sce->view_layers.first, *view_layer_next; view_layer; view_layer = view_layer_next) {
+ view_layer_next = view_layer->next;
+
+ BLI_remlink(&sce->view_layers, view_layer);
+ BKE_view_layer_free(view_layer);
+ }
+
+ /* Master Collection */
+ BKE_collection_master_free(&sce->id, do_id_user);
+ MEM_freeN(sce->collection);
+ sce->collection = NULL;
+
+ /* LayerCollection engine settings. */
+ if (sce->collection_properties) {
+ IDP_FreeProperty(sce->collection_properties);
+ MEM_freeN(sce->collection_properties);
+ sce->collection_properties = NULL;
+ }
+
+ /* Render engine setting. */
+ if (sce->layer_properties) {
+ IDP_FreeProperty(sce->layer_properties);
+ MEM_freeN(sce->layer_properties);
+ sce->layer_properties = NULL;
+ }
+}
+
+void BKE_scene_free(Scene *sce)
+{
+ BKE_scene_free_ex(sce, true);
}
void BKE_scene_init(Scene *sce)
@@ -748,7 +769,7 @@ void BKE_scene_init(Scene *sce)
sce->r.ffcodecdata.audio_bitrate = 192;
sce->r.ffcodecdata.audio_channels = 2;
- BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_RENDER, sizeof(sce->r.engine));
+ BKE_viewrender_init(&sce->view_render);
sce->audio.distance_model = 2.0f;
sce->audio.doppler_factor = 1.0f;
@@ -761,7 +782,6 @@ void BKE_scene_init(Scene *sce)
sce->r.osa = 8;
/* note; in header_info.c the scene copy happens..., if you add more to renderdata it has to be checked there */
- BKE_scene_add_render_layer(sce, NULL);
/* multiview - stereo */
BKE_scene_add_render_view(sce, STEREO_LEFT_NAME);
@@ -800,7 +820,7 @@ void BKE_scene_init(Scene *sce)
sce->gm.angulardeactthreshold = 1.0f;
sce->gm.deactivationtime = 0.0f;
- sce->gm.flag = GAME_DISPLAY_LISTS;
+ sce->gm.flag = 0;
sce->gm.matmode = GAME_MAT_MULTITEX;
sce->gm.obstacleSimulation = OBSTSIMULATION_NONE;
@@ -894,6 +914,20 @@ 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));
+
+ /* Engine settings */
+ IDPropertyTemplate val = {0};
+ sce->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_layer_collection_engine_settings_create(sce->collection_properties);
+
+ sce->layer_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_view_layer_engine_settings_create(sce->layer_properties);
+
+ BKE_view_layer_add(sce, "View Layer");
}
Scene *BKE_scene_add(Main *bmain, const char *name)
@@ -909,37 +943,40 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
return sce;
}
-Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
+/**
+ * Check if there is any intance of the object in the scene
+ */
+bool BKE_scene_object_find(Scene *scene, Object *ob)
{
- Base *base;
-
- for (base = scene->base.first; base; base = base->next) {
- if (STREQ(base->object->id.name + 2, name)) {
- break;
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ if (BLI_findptr(&view_layer->object_bases, ob, offsetof(Base, object))) {
+ return true;
}
}
-
- return base;
+ return false;
}
-Base *BKE_scene_base_find(Scene *scene, Object *ob)
+Object *BKE_scene_object_find_by_name(Scene *scene, const char *name)
{
- return BLI_findptr(&scene->base, ob, offsetof(Base, object));
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (STREQ(base->object->id.name + 2, name)) {
+ return base->object;
+ }
+ }
+ }
+ return NULL;
}
/**
* Sets the active scene, mainly used when running in background mode (``--scene`` command line argument).
* This is also called to set the scene directly, bypassing windowing code.
- * Otherwise #ED_screen_set_scene is used when changing scenes by the user.
+ * Otherwise #WM_window_change_active_scene is used when changing scenes by the user.
*/
void BKE_scene_set_background(Main *bmain, Scene *scene)
{
- Scene *sce;
- Base *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);
@@ -954,30 +991,20 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
/* group flags again */
for (group = bmain->group.first; group; group = group->id.next) {
- for (go = group->gobject.first; go; go = go->next) {
- if (go->ob) {
- go->ob->flag |= OB_FROMGROUP;
- }
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ object->flag |= OB_FROMGROUP;
}
+ FOREACH_GROUP_OBJECT_END
}
- /* sort baselist for scene and sets */
- for (sce = scene; sce; sce = sce->set)
- DAG_scene_relations_rebuild(bmain, sce);
-
/* copy layers and flags from bases to objects */
- for (base = scene->base.first; base; base = base->next) {
- ob = base->object;
- 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;
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ ob = base->object;
+ /* group patch... */
+ BKE_scene_object_base_flag_sync_from_base(base);
+ }
}
/* no full animation update, this to enable render code to work (render code calls own animation updates) */
}
@@ -997,8 +1024,9 @@ 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)
+int BKE_scene_base_iter_next(
+ const EvaluationContext *eval_ctx, SceneBaseIter *iter,
+ Scene **scene, int val, Base **base, Object **ob)
{
bool run_again = true;
@@ -1016,17 +1044,19 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
/* the first base */
if (iter->phase == F_START) {
- *base = (*scene)->base.first;
+ ViewLayer *view_layer = eval_ctx->view_layer;
+ *base = view_layer->object_bases.first;
if (*base) {
*ob = (*base)->object;
iter->phase = F_SCENE;
}
else {
- /* exception: empty scene */
+ /* exception: empty scene layer */
while ((*scene)->set) {
(*scene) = (*scene)->set;
- if ((*scene)->base.first) {
- *base = (*scene)->base.first;
+ ViewLayer *view_layer_set = BKE_view_layer_from_scene_get((*scene));
+ if (view_layer_set->object_bases.first) {
+ *base = view_layer_set->object_bases.first;
*ob = (*base)->object;
iter->phase = F_SCENE;
break;
@@ -1045,8 +1075,9 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
/* (*scene) is finished, now do the set */
while ((*scene)->set) {
(*scene) = (*scene)->set;
- if ((*scene)->base.first) {
- *base = (*scene)->base.first;
+ ViewLayer *view_layer_set = BKE_view_layer_from_scene_get((*scene));
+ if (view_layer_set->object_bases.first) {
+ *base = view_layer_set->object_bases.first;
*ob = (*base)->object;
break;
}
@@ -1080,7 +1111,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;
@@ -1099,7 +1130,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. */
@@ -1124,13 +1155,15 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
return iter->phase;
}
-Object *BKE_scene_camera_find(Scene *sc)
+Scene *BKE_scene_find_from_collection(const Main *bmain, const SceneCollection *scene_collection)
{
- Base *base;
-
- for (base = sc->base.first; base; base = base->next)
- if (base->object->type == OB_CAMERA)
- return base->object;
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ for (ViewLayer *layer = scene->view_layers.first; layer; layer = layer->next) {
+ if (BKE_view_layer_has_collection(layer, scene_collection)) {
+ return scene;
+ }
+ }
+ }
return NULL;
}
@@ -1228,49 +1261,14 @@ char *BKE_scene_find_last_marker_name(Scene *scene, int frame)
return best_marker ? best_marker->name : NULL;
}
-
-Base *BKE_scene_base_add(Scene *sce, Object *ob)
-{
- Base *b = MEM_callocN(sizeof(*b), __func__);
- BLI_addhead(&sce->base, b);
-
- b->object = ob;
- b->flag = ob->flag;
- b->lay = ob->lay;
-
- return b;
-}
-
-void BKE_scene_base_unlink(Scene *sce, Base *base)
+void BKE_scene_remove_rigidbody_object(Scene *scene, Object *ob)
{
/* remove rigid body constraint from world before removing object */
- if (base->object->rigidbody_constraint)
- BKE_rigidbody_remove_constraint(sce, base->object);
+ if (ob->rigidbody_constraint)
+ BKE_rigidbody_remove_constraint(scene, ob);
/* remove rigid body object from world before removing object */
- if (base->object->rigidbody_object)
- BKE_rigidbody_remove_object(sce, base->object);
-
- BLI_remlink(&sce->base, base);
- if (sce->basact == base)
- sce->basact = NULL;
-}
-
-void BKE_scene_base_deselect_all(Scene *sce)
-{
- Base *b;
-
- for (b = sce->base.first; b; b = b->next) {
- b->flag &= ~SELECT;
- b->object->flag = b->flag;
- }
-}
-
-void BKE_scene_base_select(Scene *sce, Base *selbase)
-{
- selbase->flag |= SELECT;
- selbase->object->flag = selbase->flag;
-
- sce->basact = selbase;
+ if (ob->rigidbody_object)
+ BKE_rigidbody_remove_object(scene, ob);
}
/* checks for cycle, returns 1 if it's all OK */
@@ -1322,109 +1320,6 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra)
scene->r.cfra = (int)intpart;
}
-#ifdef WITH_LEGACY_DEPSGRAPH
-/* drivers support/hacks
- * - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render
- * - these are always run since the depsgraph can't handle non-object data
- * - these happen after objects are all done so that we can read in their final transform values,
- * though this means that objects can't refer to scene info for guidance...
- */
-static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
-{
- SceneRenderLayer *srl;
- float ctime = BKE_scene_frame_get(scene);
-
- /* scene itself */
- if (scene->adt && scene->adt->drivers.first) {
- BKE_animsys_evaluate_animdata(scene, &scene->id, scene->adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* world */
- /* TODO: what about world textures? but then those have nodes too... */
- if (scene->world) {
- ID *wid = (ID *)scene->world;
- AnimData *adt = BKE_animdata_from_id(wid);
-
- if (adt && adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, wid, adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* nodes */
- if (scene->nodetree) {
- ID *nid = (ID *)scene->nodetree;
- AnimData *adt = BKE_animdata_from_id(nid);
-
- if (adt && adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* world nodes */
- if (scene->world && scene->world->nodetree) {
- ID *nid = (ID *)scene->world->nodetree;
- AnimData *adt = BKE_animdata_from_id(nid);
-
- if (adt && adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* freestyle */
- for (srl = scene->r.layers.first; srl; srl = srl->next) {
- FreestyleConfig *config = &srl->freestyleConfig;
- FreestyleLineSet *lineset;
-
- for (lineset = config->linesets.first; lineset; lineset = lineset->next) {
- if (lineset->linestyle) {
- ID *lid = &lineset->linestyle->id;
- AnimData *adt = BKE_animdata_from_id(lid);
-
- if (adt && adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, lid, adt, ctime, ADT_RECALC_DRIVERS);
- }
- }
- }
-}
-
-/* deps hack - do extra recalcs at end */
-static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent)
-{
- Base *base;
-
- scene->customdata_mask = scene_parent->customdata_mask;
-
- /* sets first, we allow per definition current scene to have
- * dependencies on sets, but not the other way around. */
- if (scene->set)
- scene_depsgraph_hack(eval_ctx, scene->set, scene_parent);
-
- for (base = scene->base.first; base; base = base->next) {
- Object *ob = base->object;
-
- if (ob->depsflag) {
- int recalc = 0;
- // printf("depshack %s\n", ob->id.name + 2);
-
- if (ob->depsflag & OB_DEPS_EXTRA_OB_RECALC)
- recalc |= OB_RECALC_OB;
- if (ob->depsflag & OB_DEPS_EXTRA_DATA_RECALC)
- recalc |= OB_RECALC_DATA;
-
- ob->recalc |= recalc;
- BKE_object_handle_update(eval_ctx, scene_parent, ob);
-
- if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) {
- GroupObject *go;
-
- for (go = ob->dup_group->gobject.first; go; go = go->next) {
- if (go->ob)
- go->ob->recalc |= recalc;
- }
- BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, ob, ob->dup_group);
- }
- }
- }
-}
-#endif /* WITH_LEGACY_DEPSGRAPH */
-
/* That's like really a bummer, because currently animation data for armatures
* might want to use pose, and pose might be missing on the object.
* This happens when changing visible layers, which leads to situations when
@@ -1440,7 +1335,7 @@ static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scen
static void scene_armature_depsgraph_workaround(Main *bmain)
{
Object *ob;
- if (BLI_listbase_is_empty(&bmain->armature) || !DAG_id_type_tagged(bmain, ID_OB)) {
+ if (BLI_listbase_is_empty(&bmain->armature) || !DEG_id_type_tagged(bmain, ID_OB)) {
return;
}
for (ob = bmain->object.first; ob; ob = ob->id.next) {
@@ -1453,372 +1348,27 @@ static void scene_armature_depsgraph_workaround(Main *bmain)
}
#endif
-#ifdef WITH_LEGACY_DEPSGRAPH
-static void scene_rebuild_rbw_recursive(Scene *scene, float ctime)
-{
- if (scene->set)
- scene_rebuild_rbw_recursive(scene->set, ctime);
-
- if (BKE_scene_check_rigidbody_active(scene))
- BKE_rigidbody_rebuild_world(scene, ctime);
-}
-
-static void scene_do_rb_simulation_recursive(Scene *scene, float ctime)
-{
- if (scene->set)
- scene_do_rb_simulation_recursive(scene->set, ctime);
-
- if (BKE_scene_check_rigidbody_active(scene))
- BKE_rigidbody_do_simulation(scene, ctime);
-}
-#endif
-
-/* Used to visualize CPU threads activity during threaded object update,
- * would pollute STDERR with whole bunch of timing information which then
- * could be parsed and nicely visualized.
- */
-#ifdef WITH_LEGACY_DEPSGRAPH
-# undef DETAILED_ANALYSIS_OUTPUT
-#else
-/* ALWAYS KEEY DISABLED! */
-# undef DETAILED_ANALYSIS_OUTPUT
-#endif
-
-/* Mballs evaluation uses BKE_scene_base_iter_next which calls
- * duplilist for all objects in the scene. This leads to conflict
- * accessing and writing same data from multiple threads.
- *
- * Ideally Mballs shouldn't do such an iteration and use DAG
- * queries instead. For the time being we've got new DAG
- * let's keep it simple and update mballs in a single thread.
- */
-#define MBALL_SINGLETHREAD_HACK
-
-#ifdef WITH_LEGACY_DEPSGRAPH
-typedef struct StatisicsEntry {
- struct StatisicsEntry *next, *prev;
- Object *object;
- double start_time;
- double duration;
-} StatisicsEntry;
-
-typedef struct ThreadedObjectUpdateState {
- /* TODO(sergey): We might want this to be per-thread object. */
- EvaluationContext *eval_ctx;
- Scene *scene;
- Scene *scene_parent;
- double base_time;
-
-#ifdef MBALL_SINGLETHREAD_HACK
- bool has_mballs;
-#endif
-
- /* Execution statistics */
- bool has_updated_objects;
- ListBase *statistics;
-} ThreadedObjectUpdateState;
-
-static void scene_update_object_add_task(void *node, void *user_data);
-
-static void scene_update_all_bases(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent)
-{
- Base *base;
-
- for (base = scene->base.first; base; base = base->next) {
- Object *object = base->object;
-
- BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, true);
-
- if (object->dup_group && (object->transflag & OB_DUPLIGROUP))
- BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, object, object->dup_group);
-
- /* always update layer, so that animating layers works (joshua july 2010) */
- /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes
- * (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */
- // base->lay = ob->lay;
- }
-}
-
-static void scene_update_object_func(TaskPool * __restrict pool, void *taskdata, int threadid)
-{
-/* Disable print for now in favor of summary statistics at the end of update. */
-#define PRINT if (false) printf
-
- ThreadedObjectUpdateState *state = (ThreadedObjectUpdateState *) BLI_task_pool_userdata(pool);
- void *node = taskdata;
- Object *object = DAG_get_node_object(node);
- EvaluationContext *eval_ctx = state->eval_ctx;
- Scene *scene = state->scene;
- Scene *scene_parent = state->scene_parent;
-
-#ifdef MBALL_SINGLETHREAD_HACK
- if (object && object->type == OB_MBALL) {
- state->has_mballs = true;
- }
- else
-#endif
- if (object) {
- double start_time = 0.0;
- bool add_to_stats = false;
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- if (object->recalc & OB_RECALC_ALL) {
- printf("Thread %d: update object %s\n", threadid, object->id.name);
- }
-
- start_time = PIL_check_seconds_timer();
-
- if (object->recalc & OB_RECALC_ALL) {
- state->has_updated_objects = true;
- add_to_stats = true;
- }
- }
-
- /* We only update object itself here, dupli-group will be updated
- * separately from main thread because of we've got no idea about
- * dependencies inside the group.
- */
- BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, false);
-
- /* Calculate statistics. */
- if (add_to_stats) {
- StatisicsEntry *entry;
-
- entry = MEM_mallocN(sizeof(StatisicsEntry), "update thread statistics");
- entry->object = object;
- entry->start_time = start_time;
- entry->duration = PIL_check_seconds_timer() - start_time;
-
- BLI_addtail(&state->statistics[threadid], entry);
- }
- }
- else {
- PRINT("Threda %d: update node %s\n", threadid,
- DAG_get_node_name(scene, node));
- }
-
- /* Update will decrease child's valency and schedule child with zero valency. */
- DAG_threaded_update_handle_node_updated(node, scene_update_object_add_task, pool);
-
-#undef PRINT
-}
-
-static void scene_update_object_add_task(void *node, void *user_data)
-{
- TaskPool *task_pool = user_data;
-
- BLI_task_pool_push(task_pool, scene_update_object_func, node, false, TASK_PRIORITY_LOW);
-}
-
-static void print_threads_statistics(ThreadedObjectUpdateState *state)
-{
- int i, tot_thread;
- double finish_time;
-
- if ((G.debug & G_DEBUG_DEPSGRAPH) == 0) {
- return;
- }
-
-#ifdef DETAILED_ANALYSIS_OUTPUT
- if (state->has_updated_objects) {
- tot_thread = BLI_system_thread_count();
-
- fprintf(stderr, "objects update base time %f\n", state->base_time);
-
- for (i = 0; i < tot_thread; i++) {
- StatisicsEntry *entry;
- for (entry = state->statistics[i].first;
- entry;
- entry = entry->next)
- {
- fprintf(stderr, "thread %d object %s start_time %f duration %f\n",
- i, entry->object->id.name + 2,
- entry->start_time, entry->duration);
- }
- BLI_freelistN(&state->statistics[i]);
- }
- }
-#else
- finish_time = PIL_check_seconds_timer();
- tot_thread = BLI_system_thread_count();
- int total_objects = 0;
-
- for (i = 0; i < tot_thread; i++) {
- int thread_total_objects = 0;
- double thread_total_time = 0.0;
- StatisicsEntry *entry;
-
- if (state->has_updated_objects) {
- /* Don't pollute output if no objects were updated. */
- for (entry = state->statistics[i].first;
- entry;
- entry = entry->next)
- {
- thread_total_objects++;
- thread_total_time += entry->duration;
- }
-
- printf("Thread %d: total %d objects in %f sec.\n",
- i,
- thread_total_objects,
- thread_total_time);
-
- for (entry = state->statistics[i].first;
- entry;
- entry = entry->next)
- {
- printf(" %s in %f sec\n", entry->object->id.name + 2, entry->duration);
- }
-
- total_objects += thread_total_objects;
- }
-
- BLI_freelistN(&state->statistics[i]);
- }
- if (state->has_updated_objects) {
- printf("Scene updated %d objects in %f sec\n",
- total_objects,
- finish_time - state->base_time);
- }
-#endif
-}
-
-static bool scene_need_update_objects(Main *bmain)
-{
- return
- /* Object datablocks themselves (for OB_RECALC_OB) */
- DAG_id_type_tagged(bmain, ID_OB) ||
-
- /* Objects data datablocks (for OB_RECALC_DATA) */
- DAG_id_type_tagged(bmain, ID_ME) || /* Mesh */
- DAG_id_type_tagged(bmain, ID_CU) || /* Curve */
- DAG_id_type_tagged(bmain, ID_MB) || /* MetaBall */
- DAG_id_type_tagged(bmain, ID_LA) || /* Lamp */
- DAG_id_type_tagged(bmain, ID_LT) || /* Lattice */
- DAG_id_type_tagged(bmain, ID_CA) || /* Camera */
- DAG_id_type_tagged(bmain, ID_KE) || /* KE */
- DAG_id_type_tagged(bmain, ID_SPK) || /* Speaker */
- DAG_id_type_tagged(bmain, ID_AR); /* Armature */
-}
-
-static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent)
-{
- TaskScheduler *task_scheduler;
- TaskPool *task_pool;
- ThreadedObjectUpdateState state;
- bool need_singlethread_pass;
- bool need_free_scheduler;
-
- /* Early check for whether we need to invoke all the task-based
- * things (spawn new ppol, traverse dependency graph and so on).
- *
- * Basically if there's no ID datablocks tagged for update which
- * corresponds to object->recalc flags (which are checked in
- * BKE_object_handle_update() then we do nothing here.
- */
- if (!scene_need_update_objects(bmain)) {
- return;
- }
-
- state.eval_ctx = eval_ctx;
- state.scene = scene;
- state.scene_parent = scene_parent;
-
- if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
- task_scheduler = BLI_task_scheduler_create(1);
- need_free_scheduler = true;
- }
- else {
- task_scheduler = BLI_task_scheduler_get();
- need_free_scheduler = false;
- }
-
- /* Those are only needed when blender is run with --debug argument. */
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- const int tot_thread = BLI_task_scheduler_num_threads(task_scheduler);
- state.statistics = MEM_callocN(tot_thread * sizeof(*state.statistics),
- "scene update objects stats");
- state.has_updated_objects = false;
- state.base_time = PIL_check_seconds_timer();
- }
-
-#ifdef MBALL_SINGLETHREAD_HACK
- state.has_mballs = false;
-#endif
-
- task_pool = BLI_task_pool_create(task_scheduler, &state);
-
- DAG_threaded_update_begin(scene, scene_update_object_add_task, task_pool);
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- print_threads_statistics(&state);
- MEM_freeN(state.statistics);
- }
-
- /* We do single thread pass to update all the objects which are in cyclic dependency.
- * Such objects can not be handled by a generic DAG traverse and it's really tricky
- * to detect whether cycle could be solved or not.
- *
- * In this situation we simply update all remaining objects in a single thread and
- * it'll happen in the same exact order as it was in single-threaded DAG.
- *
- * We couldn't use threaded update for objects which are in cycle because they might
- * access data of each other which is being re-evaluated.
- *
- * Also, as was explained above, for now we also update all the mballs in single thread.
- *
- * - sergey -
- */
- need_singlethread_pass = DAG_is_acyclic(scene) == false;
-#ifdef MBALL_SINGLETHREAD_HACK
- need_singlethread_pass |= state.has_mballs;
-#endif
-
- if (need_singlethread_pass) {
- scene_update_all_bases(eval_ctx, scene, scene_parent);
- }
-
- if (need_free_scheduler) {
- BLI_task_scheduler_free(task_scheduler);
- }
-}
-
-static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent)
-{
- scene->customdata_mask = scene_parent->customdata_mask;
-
- /* sets first, we allow per definition current scene to have
- * dependencies on sets, but not the other way around. */
- if (scene->set)
- scene_update_tagged_recursive(eval_ctx, bmain, scene->set, scene_parent);
-
- /* scene objects */
- scene_update_objects(eval_ctx, bmain, scene, scene_parent);
-
- /* scene drivers... */
- scene_update_drivers(bmain, scene);
-
- /* update masking curves */
- BKE_mask_update_scene(bmain, scene);
-
-}
-#endif /* WITH_LEGACY_DEPSGRAPH */
-
static bool check_rendered_viewport_visible(Main *bmain)
{
wmWindowManager *wm = bmain->wm.first;
wmWindow *window;
for (window = wm->windows.first; window != NULL; window = window->next) {
- bScreen *screen = window->screen;
+ const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
+ WorkSpace *workspace = BKE_workspace_active_get(window->workspace_hook);
+ Scene *scene = window->scene;
+ ViewRender *view_render = BKE_viewrender_get(scene, workspace);
ScrArea *area;
+ RenderEngineType *type = RE_engines_find(view_render->engine_id);
+ if ((type->draw_engine != NULL) || (type->render_to_view == NULL)) {
+ continue;
+ }
+ const bool use_legacy = (type->flag & RE_USE_LEGACY_PIPELINE) != 0;
for (area = screen->areabase.first; area != NULL; area = area->next) {
View3D *v3d = area->spacedata.first;
if (area->spacetype != SPACE_VIEW3D) {
continue;
}
- if (v3d->drawtype == OB_RENDER) {
+ if (v3d->drawtype == OB_RENDER || !use_legacy) {
return true;
}
}
@@ -1847,318 +1397,94 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
if (check_rendered_viewport_visible(bmain)) {
BMesh *bm = mesh->edit_btmesh->bm;
BM_mesh_bm_to_me(bm, mesh, (&(struct BMeshToMeshParams){0}));
- DAG_id_tag_update(&mesh->id, 0);
+ DEG_id_tag_update(&mesh->id, 0);
}
}
}
}
-void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene)
-{
- Scene *sce_iter;
-#ifdef WITH_LEGACY_DEPSGRAPH
- bool use_new_eval = !DEG_depsgraph_use_legacy();
-#endif
-
- /* keep this first */
- BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_PRE);
-
- /* (re-)build dependency graph if needed */
- for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) {
- DAG_scene_relations_update(bmain, sce_iter);
- /* Uncomment this to check if graph was properly tagged for update. */
-#if 0
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (use_new_eval)
-#endif
- {
- DAG_scene_relations_validate(bmain, sce_iter);
- }
-#endif
- }
-
- /* flush editing data if needed */
+/* TODO(sergey): This actually should become view_layer_graph or so.
+ * Same applies to update_for_newframe.
+ */
+void BKE_scene_graph_update_tagged(EvaluationContext *eval_ctx,
+ Depsgraph *depsgraph,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer)
+{
+ /* TODO(sergey): Temporary solution for until pipeline.c is ported. */
+ if (view_layer == NULL) {
+ view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ BLI_assert(view_layer != NULL);
+ }
+ /* TODO(sergey): Some functions here are changing global state,
+ * for example, clearing update tags from bmain.
+ */
+ /* (Re-)build dependency graph if needed. */
+ DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
+ /* Uncomment this to check if graph was properly tagged for update. */
+ // DEG_debug_graph_relations_validate(depsgraph, bmain, scene);
+ /* Flush editing data if needed. */
prepare_mesh_for_viewport_render(bmain, scene);
-
- /* flush recalc flags to dependencies */
- DAG_ids_flush_tagged(bmain);
-
- /* removed calls to quick_cache, see pointcache.c */
-
- /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later
- * when trying to find materials with drivers that need evaluating [#32017]
+ /* Flush recalc flags to dependencies. */
+ DEG_graph_flush_update(bmain, depsgraph);
+ /* Update all objects: drivers, matrices, displists, etc. flags set
+ * by depgraph or manual, no layer check here, gets correct flushed.
*/
- BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false);
- BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false);
-
- /* update all objects: drivers, matrices, displists, etc. flags set
- * by depgraph or manual, no layer check here, gets correct flushed
- *
- * in the future this should handle updates for all datablocks, not
- * only objects and scenes. - brecht */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- scene_update_tagged_recursive(eval_ctx, bmain, scene, scene);
- }
- else
-#endif
- {
- DEG_evaluate_on_refresh(eval_ctx, scene->depsgraph, scene);
- }
-
- /* update sound system animation (TODO, move to depsgraph) */
+ DEG_evaluate_on_refresh(eval_ctx, depsgraph);
+ /* Update sound system animation (TODO, move to depsgraph). */
BKE_sound_update_scene(bmain, scene);
-
- /* extra call here to recalc scene animation (for sequencer) */
- {
- AnimData *adt = BKE_animdata_from_id(&scene->id);
- float ctime = BKE_scene_frame_get(scene);
-
- if (adt && (adt->recalc & ADT_RECALC_ANIM))
- BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, 0);
- }
-
- /* Extra call here to recalc material animation.
- *
- * Need to do this so changing material settings from the graph/dopesheet
- * will update stuff in the viewport.
- */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval && DAG_id_type_tagged(bmain, ID_MA)) {
- Material *material;
- float ctime = BKE_scene_frame_get(scene);
-
- for (material = bmain->mat.first;
- material;
- material = material->id.next)
- {
- AnimData *adt = BKE_animdata_from_id(&material->id);
- if (adt && (adt->recalc & ADT_RECALC_ANIM))
- BKE_animsys_evaluate_animdata(scene, &material->id, adt, ctime, 0);
- }
- }
-
- /* Also do the same for node trees. */
- if (!use_new_eval && DAG_id_type_tagged(bmain, ID_NT)) {
- float ctime = BKE_scene_frame_get(scene);
-
- FOREACH_NODETREE(bmain, ntree, id)
- {
- AnimData *adt = BKE_animdata_from_id(&ntree->id);
- if (adt && (adt->recalc & ADT_RECALC_ANIM))
- BKE_animsys_evaluate_animdata(scene, &ntree->id, adt, ctime, 0);
- }
- FOREACH_NODETREE_END
- }
-#endif
-
- /* notify editors and python about recalc */
- BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST);
-
/* Inform editors about possible changes. */
- DAG_ids_check_recalc(bmain, scene, false);
-
- /* clear recalc flags */
- DAG_ids_clear_recalc(bmain);
+ DEG_ids_check_recalc(bmain, scene, view_layer, false);
+ /* Clear recalc flags. */
+ DEG_ids_clear_recalc(bmain);
}
/* applies changes right away, does all sets too */
-void BKE_scene_update_for_newframe(EvaluationContext *eval_ctx, Main *bmain, Scene *sce, unsigned int lay)
-{
- BKE_scene_update_for_newframe_ex(eval_ctx, bmain, sce, lay, false);
-}
-
-void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, Scene *sce, unsigned int lay, bool do_invisible_flush)
-{
- float ctime = BKE_scene_frame_get(sce);
- Scene *sce_iter;
-#ifdef DETAILED_ANALYSIS_OUTPUT
- double start_time = PIL_check_seconds_timer();
-#endif
-#ifdef WITH_LEGACY_DEPSGRAPH
- bool use_new_eval = !DEG_depsgraph_use_legacy();
-#else
- /* TODO(sergey): Pass to evaluation routines instead of storing layer in the graph? */
- (void) do_invisible_flush;
-#endif
-
- DAG_editors_update_pre(bmain, sce, true);
-
- /* keep this first */
- BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_PRE);
- BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_PRE);
-
- /* update animated image textures for particles, modifiers, gpu, etc,
- * call this at the start so modifiers with textures don't lag 1 frame */
- BKE_image_update_frame(bmain, sce->r.cfra);
-
-#ifdef WITH_LEGACY_DEPSGRAPH
- /* rebuild rigid body worlds before doing the actual frame update
- * this needs to be done on start frame but animation playback usually starts one frame later
- * we need to do it here to avoid rebuilding the world on every simulation change, which can be very expensive
+void BKE_scene_graph_update_for_newframe(EvaluationContext *eval_ctx,
+ Depsgraph *depsgraph,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer)
+{
+ /* TODO(sergey): Temporary solution for until pipeline.c is ported. */
+ if (view_layer == NULL) {
+ view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ BLI_assert(view_layer != NULL);
+ }
+ /* TODO(sergey): Some functions here are changing global state,
+ * for example, clearing update tags from bmain.
*/
- if (!use_new_eval) {
- scene_rebuild_rbw_recursive(sce, ctime);
- }
-#endif
-
- BKE_sound_set_cfra(sce->r.cfra);
-
- /* clear animation overrides */
- /* XXX TODO... */
-
- for (sce_iter = sce; sce_iter; sce_iter = sce_iter->set)
- DAG_scene_relations_update(bmain, sce_iter);
-
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- /* flush recalc flags to dependencies, if we were only changing a frame
- * this would not be necessary, but if a user or a script has modified
- * some datablock before BKE_scene_update_tagged was called, we need the flush */
- DAG_ids_flush_tagged(bmain);
-
- /* Following 2 functions are recursive
- * so don't call within 'scene_update_tagged_recursive' */
- DAG_scene_update_flags(bmain, sce, lay, true, do_invisible_flush); // only stuff that moves or needs display still
- BKE_mask_evaluate_all_masks(bmain, ctime, true);
- }
-#endif
-
- /* Update animated cache files for modifiers. */
- BKE_cachefile_update_frame(bmain, sce, ctime, (((double)sce->r.frs_sec) / (double)sce->r.frs_sec_base));
-
+ const float ctime = BKE_scene_frame_get(scene);
+ /* Keep this first. */
+ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_FRAME_CHANGE_PRE);
+ /* Update animated image textures for particles, modifiers, gpu, etc,
+ * call this at the start so modifiers with textures don't lag 1 frame.
+ */
+ BKE_image_update_frame(bmain, scene->r.cfra);
+ BKE_sound_set_cfra(scene->r.cfra);
+ DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
+ /* Update animated cache files for modifiers.
+ *
+ * TODO(sergey): Make this a depsgraph node?
+ */
+ BKE_cachefile_update_frame(bmain, scene, ctime,
+ (((double)scene->r.frs_sec) / (double)scene->r.frs_sec_base));
#ifdef POSE_ANIMATION_WORKAROUND
scene_armature_depsgraph_workaround(bmain);
#endif
-
- /* All 'standard' (i.e. without any dependencies) animation is handled here,
- * with an 'local' to 'macro' order of evaluation. This should ensure that
- * settings stored nestled within a hierarchy (i.e. settings in a Texture block
- * can be overridden by settings from Scene, which owns the Texture through a hierarchy
- * such as Scene->World->MTex/Texture) can still get correctly overridden.
+ /* Update all objects: drivers, matrices, displists, etc. flags set
+ * by depgraph or manual, no layer check here, gets correct flushed.
*/
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- BKE_animsys_evaluate_all_animation(bmain, sce, ctime);
- /*...done with recursive funcs */
- }
-#endif
-
- /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later
- * when trying to find materials with drivers that need evaluating [#32017]
- */
- BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false);
- BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false);
-
- /* run rigidbody sim */
- /* NOTE: current position is so that rigidbody sim affects other objects, might change in the future */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- scene_do_rb_simulation_recursive(sce, ctime);
- }
-#endif
-
- /* BKE_object_handle_update() on all objects, groups and sets */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (use_new_eval) {
- DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay);
- }
- else {
- scene_update_tagged_recursive(eval_ctx, bmain, sce, sce);
- }
-#else
- DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay);
-#endif
-
- /* update sound system animation (TODO, move to depsgraph) */
- BKE_sound_update_scene(bmain, sce);
-
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- scene_depsgraph_hack(eval_ctx, sce, sce);
- }
-#endif
-
- /* notify editors and python about recalc */
- BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_POST);
- BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_POST);
-
+ DEG_evaluate_on_framechange(eval_ctx, bmain, depsgraph, ctime);
+ /* Update sound system animation (TODO, move to depsgraph). */
+ BKE_sound_update_scene(bmain, scene);
+ /* Notify editors and python about recalc. */
+ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_FRAME_CHANGE_POST);
/* Inform editors about possible changes. */
- DAG_ids_check_recalc(bmain, sce, true);
-
+ DEG_ids_check_recalc(bmain, scene, view_layer, true);
/* clear recalc flags */
- DAG_ids_clear_recalc(bmain);
-
-#ifdef DETAILED_ANALYSIS_OUTPUT
- fprintf(stderr, "frame update start_time %f duration %f\n", start_time, PIL_check_seconds_timer() - start_time);
-#endif
-}
-
-/* return default layer, also used to patch old files */
-SceneRenderLayer *BKE_scene_add_render_layer(Scene *sce, const char *name)
-{
- SceneRenderLayer *srl;
-
- if (!name)
- name = DATA_("RenderLayer");
-
- srl = MEM_callocN(sizeof(SceneRenderLayer), "new render layer");
- BLI_strncpy(srl->name, name, sizeof(srl->name));
- BLI_uniquename(&sce->r.layers, srl, DATA_("RenderLayer"), '.', offsetof(SceneRenderLayer, name), sizeof(srl->name));
- BLI_addtail(&sce->r.layers, srl);
-
- /* note, this is also in render, pipeline.c, to make layer when scenedata doesnt have it */
- srl->lay = (1 << 20) - 1;
- srl->layflag = 0x7FFF; /* solid ztra halo edge strand */
- srl->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
- srl->pass_alpha_threshold = 0.5f;
- BKE_freestyle_config_init(&srl->freestyleConfig);
-
- return srl;
-}
-
-bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *srl)
-{
- const int act = BLI_findindex(&scene->r.layers, srl);
- Scene *sce;
-
- if (act == -1) {
- return false;
- }
- else if ( (scene->r.layers.first == scene->r.layers.last) &&
- (scene->r.layers.first == srl))
- {
- /* ensure 1 layer is kept */
- return false;
- }
-
- BKE_freestyle_config_free(&srl->freestyleConfig);
-
- if (srl->prop) {
- IDP_FreeProperty(srl->prop);
- MEM_freeN(srl->prop);
- }
-
- BLI_remlink(&scene->r.layers, srl);
- MEM_freeN(srl);
-
- scene->r.actlay = 0;
-
- 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--;
- }
- }
- }
- }
-
- return true;
+ DEG_ids_clear_recalc(bmain);
}
/* return default view */
@@ -2241,21 +1567,34 @@ float get_render_aosss_error(const RenderData *r, float error)
return error;
}
-/* helper function for the SETLOOPER macro */
-Base *_setlooper_base_step(Scene **sce_iter, Base *base)
+/**
+ * Helper function for the SETLOOPER and SETLOOPER_VIEW_LAYER macros
+ *
+ * It iterates over the bases of the active layer and then the bases
+ * of the active layer of the background (set) scenes recursively.
+ */
+Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base)
{
if (base && base->next) {
- /* common case, step to the next */
+ /* Common case, step to the next. */
return base->next;
}
- else if (base == NULL && (*sce_iter)->base.first) {
- /* first time looping, return the scenes first base */
- return (Base *)(*sce_iter)->base.first;
+ else if ((base == NULL) && (view_layer != NULL)) {
+ /* First time looping, return the scenes first base. */
+ /* For the first loop we should get the layer from workspace when available. */
+ if (view_layer->object_bases.first) {
+ return (Base *)view_layer->object_bases.first;
+ }
+ /* No base on this scene layer. */
+ goto next_set;
}
else {
- /* reached the end, get the next base in the set */
+next_set:
+ /* Reached the end, get the next base in the set. */
while ((*sce_iter = (*sce_iter)->set)) {
- base = (Base *)(*sce_iter)->base.first;
+ ViewLayer *view_layer_set = BKE_view_layer_from_scene_get((*sce_iter));
+ base = (Base *)view_layer_set->object_bases.first;
+
if (base) {
return base;
}
@@ -2267,56 +1606,80 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base)
bool BKE_scene_use_new_shading_nodes(const Scene *scene)
{
- const RenderEngineType *type = RE_engines_find(scene->r.engine);
- return (type && type->flag & RE_USE_SHADING_NODES);
+ return BKE_viewrender_use_new_shading_nodes(&scene->view_render);
}
bool BKE_scene_use_shading_nodes_custom(Scene *scene)
{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
- return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM);
+ return BKE_viewrender_use_shading_nodes_custom(&scene->view_render);
}
bool BKE_scene_use_world_space_shading(Scene *scene)
{
- const RenderEngineType *type = RE_engines_find(scene->r.engine);
+ RenderEngineType *type = RE_engines_find(scene->view_render.engine_id);
return ((scene->r.mode & R_USE_WS_SHADING) ||
(type && (type->flag & RE_USE_SHADING_NODES)));
}
bool BKE_scene_use_spherical_stereo(Scene *scene)
{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
- return (type && type->flag & RE_USE_SPHERICAL_STEREO);
+ return BKE_viewrender_use_spherical_stereo(&scene->view_render);
}
-bool BKE_scene_uses_blender_internal(const Scene *scene)
+bool BKE_scene_uses_blender_internal(const Scene *scene)
{
- return STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER);
+ return BKE_viewrender_uses_blender_internal(&scene->view_render);
}
bool BKE_scene_uses_blender_game(const Scene *scene)
{
- return STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME);
+ return BKE_viewrender_uses_blender_game(&scene->view_render);
+}
+
+bool BKE_scene_uses_blender_eevee(const Scene *scene)
+{
+ return BKE_viewrender_uses_blender_eevee(&scene->view_render);
}
-void BKE_scene_base_flag_to_objects(struct Scene *scene)
+void BKE_scene_base_flag_to_objects(ViewLayer *view_layer)
{
- Base *base = scene->base.first;
+ Base *base = view_layer->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_object_base_flag_sync_from_base(Base *base)
{
- Base *base = scene->base.first;
+ Object *ob = base->object;
- while (base) {
- base->flag = base->object->flag;
- base = base->next;
+ /* 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;
}
}
@@ -2380,6 +1743,81 @@ int BKE_render_preview_pixel_size(const RenderData *r)
return r->preview_pixel_size;
}
+/* ***************************************************** */
+/* render engine settings */
+
+ViewRender *BKE_viewrender_get(Scene *scene, WorkSpace *workspace)
+{
+ if (workspace == NULL || BKE_workspace_use_scene_settings_get(workspace)) {
+ return &scene->view_render;
+ }
+ return BKE_workspace_view_render_get(workspace);
+}
+
+/**
+ * Initialize a static created struct for WorkSpace and Scene to store the viewport
+ * related drawing data.
+ */
+void BKE_viewrender_init(ViewRender *view_render)
+{
+ BLI_strncpy(view_render->engine_id, RE_engine_id_BLENDER_EEVEE, sizeof(view_render->engine_id));
+}
+
+/**
+ * Do not free ViewRender itself since it's not even allocated.
+ */
+void BKE_viewrender_free(ViewRender *UNUSED(view_render))
+{
+ /* Do nothing. */
+}
+
+/**
+ * Copy used by libblock copying.
+ */
+void BKE_viewrender_copy(ViewRender *to, const ViewRender *from)
+{
+ *to = *from;
+}
+
+bool BKE_viewrender_use_new_shading_nodes(const ViewRender *view_render)
+{
+ RenderEngineType *type = RE_engines_find(view_render->engine_id);
+ return (type && type->flag & RE_USE_SHADING_NODES);
+}
+
+bool BKE_viewrender_use_shading_nodes_custom(const ViewRender *view_render)
+{
+ RenderEngineType *type = RE_engines_find(view_render->engine_id);
+ return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM);
+}
+
+bool BKE_viewrender_use_spherical_stereo(const ViewRender *view_render)
+{
+ const char *engine_id = view_render->engine_id;
+ RenderEngineType *type = RE_engines_find(engine_id);
+ return (type && type->flag & RE_USE_SPHERICAL_STEREO);
+}
+
+bool BKE_viewrender_uses_blender_internal(const ViewRender *view_render)
+{
+ const char *engine_id = view_render->engine_id;
+ return STREQ(engine_id, RE_engine_id_BLENDER_RENDER);
+}
+
+bool BKE_viewrender_uses_blender_game(const ViewRender *view_render)
+{
+ const char *engine_id = view_render->engine_id;
+ return STREQ(engine_id, RE_engine_id_BLENDER_GAME);
+}
+
+bool BKE_viewrender_uses_blender_eevee(const ViewRender *view_render)
+{
+ const char *engine_id = view_render->engine_id;
+ return STREQ(engine_id, RE_engine_id_BLENDER_EEVEE);
+}
+
+/* ***************************************************** */
+
/* Apply the needed correction factor to value, based on unit_type (only length-related are affected currently)
* and unit->scale_length.
*/
@@ -2685,3 +2123,106 @@ int BKE_scene_multiview_num_videos_get(const RenderData *rd)
return BKE_scene_multiview_num_views_get(rd);
}
}
+
+/* Manipulation of depsgraph storage. */
+
+/* This is a key which identifies depsgraph. */
+typedef struct DepsgraphKey {
+ ViewLayer *view_layer;
+ /* TODO(sergey): Need to include window somehow (same layer might be in a
+ * different states in different windows).
+ */
+} DepsgraphKey;
+
+static unsigned int depsgraph_key_hash(const void *key_v)
+{
+ const DepsgraphKey *key = key_v;
+ unsigned int hash = BLI_ghashutil_ptrhash(key->view_layer);
+ /* TODO(sergey): Include hash from other fields in the key. */
+ return hash;
+}
+
+static bool depsgraph_key_compare(const void *key_a_v, const void *key_b_v)
+{
+ const DepsgraphKey *key_a = key_a_v;
+ const DepsgraphKey *key_b = key_b_v;
+ /* TODO(sergey): Compare rest of */
+ return !(key_a->view_layer == key_b->view_layer);
+}
+
+static void depsgraph_key_free(void *key_v)
+{
+ DepsgraphKey *key = key_v;
+ MEM_freeN(key);
+}
+
+static void depsgraph_key_value_free(void *value)
+{
+ Depsgraph *depsgraph = value;
+ DEG_graph_free(depsgraph);
+}
+
+void BKE_scene_allocate_depsgraph_hash(Scene *scene)
+{
+ scene->depsgraph_hash = BLI_ghash_new(depsgraph_key_hash,
+ depsgraph_key_compare,
+ "Scene Depsgraph Hash");
+}
+
+void BKE_scene_ensure_depsgraph_hash(Scene *scene)
+{
+ if (scene->depsgraph_hash == NULL) {
+ BKE_scene_allocate_depsgraph_hash(scene);
+ }
+}
+
+void BKE_scene_free_depsgraph_hash(Scene *scene)
+{
+ if (scene->depsgraph_hash == NULL) {
+ return;
+ }
+ BLI_ghash_free(scene->depsgraph_hash,
+ depsgraph_key_free,
+ depsgraph_key_value_free);
+}
+
+/* Query depsgraph for a specific contexts. */
+
+Depsgraph *BKE_scene_get_depsgraph(Scene *scene,
+ ViewLayer *view_layer,
+ bool allocate)
+{
+ BLI_assert(scene != NULL);
+ BLI_assert(view_layer != NULL);
+ /* Make sure hash itself exists. */
+ if (allocate) {
+ BKE_scene_ensure_depsgraph_hash(scene);
+ }
+ if (scene->depsgraph_hash == NULL) {
+ return NULL;
+ }
+ /* Either ensure item is in the hash or simply return NULL if it's not,
+ * depending on whether caller wants us to create depsgraph or not.
+ */
+ DepsgraphKey key;
+ key.view_layer = view_layer;
+ Depsgraph *depsgraph;
+ if (allocate) {
+ DepsgraphKey **key_ptr;
+ Depsgraph **depsgraph_ptr;
+ if (!BLI_ghash_ensure_p_ex(scene->depsgraph_hash,
+ &key,
+ (void ***)&key_ptr,
+ (void ***)&depsgraph_ptr))
+ {
+ *key_ptr = MEM_mallocN(sizeof(DepsgraphKey), __func__);
+ **key_ptr = key;
+ *depsgraph_ptr = DEG_graph_new();
+ }
+ depsgraph = *depsgraph_ptr;
+ }
+ else {
+ depsgraph = BLI_ghash_lookup(scene->depsgraph_hash, &key);
+ }
+ return depsgraph;
+}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index df47b89fadc..6bd88099792 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -45,13 +45,16 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_rect.h"
+#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
/* ************ Spacetype/regiontype handling ************** */
@@ -180,6 +183,7 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar)
BLI_listbase_clear(&newar->panels_category_active);
BLI_listbase_clear(&newar->ui_lists);
newar->swinid = 0;
+ newar->manipulator_map = NULL;
newar->regiontimer = NULL;
newar->headerstr = NULL;
@@ -289,6 +293,43 @@ void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID
}
}
+/**
+ * Avoid bad-level calls to #WM_manipulatormap_tag_refresh.
+ */
+static void (*region_refresh_tag_manipulatormap_callback)(struct wmManipulatorMap *) = NULL;
+
+void BKE_region_callback_refresh_tag_manipulatormap_set(void (*callback)(struct wmManipulatorMap *))
+{
+ region_refresh_tag_manipulatormap_callback = callback;
+}
+
+void BKE_screen_manipulator_tag_refresh(struct bScreen *sc)
+{
+ if (region_refresh_tag_manipulatormap_callback == NULL) {
+ return;
+ }
+
+ ScrArea *sa;
+ ARegion *ar;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->manipulator_map != NULL) {
+ region_refresh_tag_manipulatormap_callback(ar->manipulator_map);
+ }
+ }
+ }
+}
+
+/**
+ * Avoid bad-level calls to #WM_manipulatormap_delete.
+ */
+static void (*region_free_manipulatormap_callback)(struct wmManipulatorMap *) = NULL;
+
+void BKE_region_callback_free_manipulatormap_set(void (*callback)(struct wmManipulatorMap *))
+{
+ region_free_manipulatormap_callback = callback;
+}
+
/* not region itself */
void BKE_area_region_free(SpaceType *st, ARegion *ar)
{
@@ -338,6 +379,11 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
MEM_freeN(uilst->properties);
}
}
+
+ if (ar->manipulator_map != NULL) {
+ region_free_manipulatormap_callback(ar->manipulator_map);
+ }
+
BLI_freelistN(&ar->ui_lists);
BLI_freelistN(&ar->ui_previews);
BLI_freelistN(&ar->panels_category);
@@ -381,6 +427,8 @@ void BKE_screen_free(bScreen *sc)
BLI_freelistN(&sc->vertbase);
BLI_freelistN(&sc->edgebase);
BLI_freelistN(&sc->areabase);
+
+ BKE_previewimg_free(&sc->preview);
}
/* for depsgraph */
@@ -580,7 +628,7 @@ void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene)
}
}
-void BKE_screen_view3d_scene_sync(bScreen *sc)
+void BKE_screen_view3d_scene_sync(bScreen *sc, Scene *scene)
{
/* are there cameras in the views that are not in the scene? */
ScrArea *sa;
@@ -589,55 +637,26 @@ void BKE_screen_view3d_scene_sync(bScreen *sc)
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *) sl;
- BKE_screen_view3d_sync(v3d, sc->scene);
+ BKE_screen_view3d_sync(v3d, scene);
}
}
}
}
-void BKE_screen_view3d_main_sync(ListBase *screen_lb, Scene *scene)
+void BKE_screen_transform_orientation_remove(
+ const bScreen *screen, const WorkSpace *workspace, const TransformOrientation *orientation)
{
- bScreen *sc;
- ScrArea *sa;
- SpaceLink *sl;
+ const int orientation_index = BKE_workspace_transform_orientation_get_index(workspace, orientation);
- /* from scene copy to the other views */
- for (sc = screen_lb->first; sc; sc = sc->id.next) {
- if (sc->scene != scene)
- continue;
-
- for (sa = sc->areabase.first; sa; sa = sa->next)
- for (sl = sa->spacedata.first; sl; sl = sl->next)
- if (sl->spacetype == SPACE_VIEW3D)
- BKE_screen_view3d_sync((View3D *)sl, scene);
- }
-}
-
-void BKE_screen_view3d_twmode_remove(View3D *v3d, const int i)
-{
- const int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
- if (selected_index == i) {
- v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
- }
- else if (selected_index > i) {
- v3d->twmode--;
- }
-}
-
-void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, Scene *scene, const int i)
-{
- bScreen *sc;
+ for (ScrArea *area = screen->areabase.first; area; area = area->next) {
+ for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
- for (sc = screen_lb->first; sc; sc = sc->id.next) {
- if (sc->scene == scene) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- BKE_screen_view3d_twmode_remove(v3d, i);
- }
+ if (v3d->custom_orientation_index == orientation_index) {
+ /* could also use orientation_index-- */
+ v3d->twmode = V3D_MANIP_GLOBAL;
+ v3d->custom_orientation_index = -1;
}
}
}
@@ -684,3 +703,13 @@ void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings)
GPU_fx_compositor_init_ssao_settings(fx_ssao);
}
}
+
+bool BKE_screen_is_fullscreen_area(const bScreen *screen)
+{
+ return ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL);
+}
+
+bool BKE_screen_is_used(const bScreen *screen)
+{
+ return (screen->winid != 0);
+}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 5f631621dcd..2319d36ab16 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -63,9 +63,9 @@
#include "BLT_translation.h"
#include "BKE_animsys.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_sequencer.h"
#include "BKE_movieclip.h"
@@ -75,6 +75,8 @@
#include "BKE_library.h"
#include "BKE_idprop.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RE_pipeline.h"
@@ -88,8 +90,10 @@
#include "BKE_context.h"
#include "BKE_sound.h"
+#include "RE_engine.h"
+
#ifdef WITH_AUDASPACE
-# include AUD_SPECIAL_H
+# include <AUD_Special.h>
#endif
/* mutable state for sequencer */
@@ -3259,6 +3263,10 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
// have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first); /* UNUSED */
have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree;
+ /* Get depsgraph and scene layer for the strip. */
+ ViewLayer *view_layer = BKE_view_layer_from_scene_get(scene);
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+
orig_data.scemode = scene->r.scemode;
orig_data.cfra = scene->r.cfra;
orig_data.subframe = scene->r.subframe;
@@ -3314,10 +3322,12 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
context->scene->r.seq_prev_type = 3 /* == OB_SOLID */;
/* opengl offscreen render */
- BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
+ context->eval_ctx->engine_type = RE_engines_find(scene->view_render.engine_id);
+ BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer);
ibuf = sequencer_view3d_cb(
/* set for OpenGL render (NULL when scrubbing) */
- scene, camera, width, height, IB_rect, draw_flags, context->scene->r.seq_prev_type,
+ context->eval_ctx, scene, view_layer, camera, width, height, IB_rect,
+ draw_flags, context->scene->r.seq_prev_type,
scene->r.alphamode, context->gpu_samples, viewname,
context->gpu_fx, context->gpu_offscreen, err_out);
if (ibuf == NULL) {
@@ -3344,7 +3354,14 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
if (re == NULL)
re = RE_NewSceneRender(scene);
- BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
+ /* NOTE: Without this tag rendering from command line fails.
+ * TODO(sergey): Need some proper solution with ported
+ * BKE_scene_set_background() or DEG_on_visible_change() ?
+ */
+ RE_SetDepsgraph(re, depsgraph);
+ DEG_graph_id_tag_update(context->bmain, depsgraph, &scene->id, 0);
+
+ BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer);
RE_BlenderFrame(re, context->bmain, scene, NULL, camera, scene->lay, frame, false);
/* restore previous state after it was toggled on & off by RE_BlenderFrame */
@@ -3404,7 +3421,7 @@ finally:
scene->r.subframe = orig_data.subframe;
if (is_frame_update) {
- BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
+ BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer);
}
#ifdef DURIAN_CAMERA_SWITCH
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index fcf4724bd1c..b5eed6c78de 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -83,6 +83,8 @@
#include "BKE_smoke.h"
#include "BKE_texture.h"
+#include "DEG_depsgraph.h"
+
#include "RE_shader_ext.h"
#include "GPU_glew.h"
@@ -126,7 +128,7 @@ void smoke_initWaveletBlenderRNA(struct WTURBULENCE *UNUSED(wt), float *UNUSED(s
void smoke_initBlenderRNA(struct FLUID_3D *UNUSED(fluid), float *UNUSED(alpha), float *UNUSED(beta), float *UNUSED(dt_factor), float *UNUSED(vorticity),
int *UNUSED(border_colli), float *UNUSED(burning_rate), float *UNUSED(flame_smoke), float *UNUSED(flame_smoke_color),
float *UNUSED(flame_vorticity), float *UNUSED(flame_ignition_temp), float *UNUSED(flame_max_temp)) {}
-struct DerivedMesh *smokeModifier_do(SmokeModifierData *UNUSED(smd), Scene *UNUSED(scene), Object *UNUSED(ob), DerivedMesh *UNUSED(dm)) { return NULL; }
+struct DerivedMesh *smokeModifier_do(SmokeModifierData *UNUSED(smd), const struct EvaluationContext *UNUSED(eval_ctx), Scene *UNUSED(scene), Object *UNUSED(ob), DerivedMesh *UNUSED(dm)) { return NULL; }
float smoke_get_velocity_at(struct Object *UNUSED(ob), float UNUSED(position[3]), float UNUSED(velocity[3])) { return 0.0f; }
#endif /* WITH_SMOKE */
@@ -693,16 +695,16 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData
#ifdef WITH_SMOKE
// forward decleration
-static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene);
+static void smoke_calc_transparency(SmokeDomainSettings *sds, ViewLayer *view_layer);
static float calc_voxel_transp(float *result, float *input, int res[3], int *pixel, float *tRay, float correct);
-static int get_lamp(Scene *scene, float *light)
+static int get_lamp(ViewLayer *view_layer, float *light)
{
Base *base_tmp = NULL;
int found_lamp = 0;
// try to find a lamp, preferably local
- for (base_tmp = scene->base.first; base_tmp; base_tmp = base_tmp->next) {
+ for (base_tmp = FIRSTBASE(view_layer); base_tmp; base_tmp = base_tmp->next) {
if (base_tmp->object->type == OB_LAMP) {
Lamp *la = base_tmp->object->data;
@@ -2071,7 +2073,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value
}
}
-static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt)
+static void update_flowsfluids(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt)
{
Object **flowobjs = NULL;
EmissionMap *emaps = NULL;
@@ -2178,7 +2180,7 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
else { /* MOD_SMOKE_FLOW_SOURCE_MESH */
/* update flow object frame */
BLI_mutex_lock(&object_update_lock);
- BKE_object_modifier_update_subframe(scene, collob, true, 5, BKE_scene_frame_get(scene), eModifierType_Smoke);
+ BKE_object_modifier_update_subframe(eval_ctx, scene, collob, true, 5, BKE_scene_frame_get(scene), eModifierType_Smoke);
BLI_mutex_unlock(&object_update_lock);
/* apply flow */
@@ -2487,12 +2489,12 @@ static void update_effectors_task_cb(void *userdata, const int x)
}
}
-static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, float UNUSED(dt))
+static void update_effectors(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SmokeDomainSettings *sds, float UNUSED(dt))
{
ListBase *effectors;
/* make sure smoke flow influence is 0.0f */
sds->effector_weights->weight[PFIELD_SMOKEFLOW] = 0.0f;
- effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights, true);
+ effectors = pdInitEffectors(eval_ctx, scene, ob, NULL, sds->effector_weights, true);
if (effectors) {
// precalculate wind forces
@@ -2516,7 +2518,7 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds,
pdEndEffectors(&effectors);
}
-static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps)
+static void step(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps)
{
SmokeDomainSettings *sds = smd->domain;
/* stability values copied from wturbulence.cpp */
@@ -2586,11 +2588,11 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *
for (substep = 0; substep < totalSubsteps; substep++)
{
// calc animated obstacle velocities
- update_flowsfluids(scene, ob, sds, dtSubdiv);
+ update_flowsfluids(eval_ctx, scene, ob, sds, dtSubdiv);
update_obstacles(scene, ob, sds, dtSubdiv, substep, totalSubsteps);
if (sds->total_cells > 1) {
- update_effectors(scene, ob, sds, dtSubdiv); // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt
+ update_effectors(eval_ctx, scene, ob, sds, dtSubdiv); // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt
smoke_step(sds->fluid, gravity, dtSubdiv);
}
}
@@ -2683,7 +2685,8 @@ static DerivedMesh *createDomainGeometry(SmokeDomainSettings *sds, Object *ob)
return result;
}
-static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
+static void smokeModifier_process(
+ SmokeModifierData *smd, const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm)
{
if ((smd->type & MOD_SMOKE_TYPE_FLOW))
{
@@ -2804,11 +2807,11 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
}
- step(scene, ob, smd, dm, scene->r.frs_sec / scene->r.frs_sec_base);
+ step(eval_ctx, scene, ob, smd, dm, scene->r.frs_sec / scene->r.frs_sec_base);
}
// create shadows before writing cache so they get stored
- smoke_calc_transparency(sds, scene);
+ smoke_calc_transparency(sds, eval_ctx->view_layer);
if (sds->wt && sds->total_cells > 1) {
smoke_turbulence_step(sds->wt, sds->fluid);
@@ -2825,13 +2828,14 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
}
}
-struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
+struct DerivedMesh *smokeModifier_do(
+ SmokeModifierData *smd, const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm)
{
/* lock so preview render does not read smoke data while it gets modified */
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
BLI_rw_mutex_lock(smd->domain->fluid_mutex, THREAD_LOCK_WRITE);
- smokeModifier_process(smd, scene, ob, dm);
+ smokeModifier_process(smd, eval_ctx, scene, ob, dm);
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
BLI_rw_mutex_unlock(smd->domain->fluid_mutex);
@@ -2946,7 +2950,7 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f
cb(result, input, res, pixel, tRay, correct);
}
-static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene)
+static void smoke_calc_transparency(SmokeDomainSettings *sds, ViewLayer *view_layer)
{
float bv[6] = {0};
float light[3];
@@ -2954,7 +2958,7 @@ static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene)
float *density = smoke_get_density(sds->fluid);
float correct = -7.0f * sds->dx;
- if (!get_lamp(scene, light)) return;
+ if (!get_lamp(view_layer, light)) return;
/* convert light pos to sim cell space */
mul_m4_v3(sds->imat, light);
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 3052a708137..e3af77166a9 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -74,6 +74,7 @@ variables on the UI for now
#include "BKE_curve.h"
#include "BKE_effect.h"
#include "BKE_global.h"
+#include "BKE_group.h"
#include "BKE_modifier.h"
#include "BKE_softbody.h"
#include "BKE_pointcache.h"
@@ -81,6 +82,8 @@ variables on the UI for now
#include "BKE_mesh.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
#include "PIL_time.h"
/* callbacks for errors and interrupts and some goo */
@@ -512,35 +515,26 @@ static void ccd_build_deflector_hash_single(GHash *hash, Object *ob)
/**
* \note group overrides scene when not NULL.
*/
-static void ccd_build_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash)
+static void ccd_build_deflector_hash(ViewLayer *view_layer, Group *group, Object *vertexowner, GHash *hash)
{
Object *ob;
if (!hash) return;
+ /* Explicit collision group. */
if (group) {
- /* Explicit collision group */
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- ob = go->ob;
-
- if (ob == vertexowner || ob->type != OB_MESH)
- continue;
-
- ccd_build_deflector_hash_single(hash, ob);
- }
+ view_layer = group->view_layer;
}
- else {
- for (Base *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;
- if ((vertexowner) && (ob == vertexowner)) {
- /* if vertexowner is given we don't want to check collision with owner object */
- continue;
- }
- ccd_build_deflector_hash_single(hash, ob);
+ for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ /* Only proceed for mesh object in same layer. */
+ if (base->object->type == OB_MESH) {
+ ob = base->object;
+ if (ob == vertexowner) {
+ /* If vertexowner is given we don't want to check collision with owner object. */
+ continue;
}
+ ccd_build_deflector_hash_single(hash, ob);
}
}
}
@@ -558,37 +552,29 @@ static void ccd_update_deflector_hash_single(GHash *hash, Object *ob)
/**
* \note group overrides scene when not NULL.
*/
-static void ccd_update_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash)
+static void ccd_update_deflector_hash(ViewLayer *view_layer, Group *group, Object *vertexowner, GHash *hash)
{
Object *ob;
if ((!hash) || (!vertexowner)) return;
+ /* Explicit collision group. */
if (group) {
- /* Explicit collision group */
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- ob = go->ob;
+ view_layer = group->view_layer;
+ }
- if (ob == vertexowner || ob->type != OB_MESH)
+ for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ /* Only proceed for mesh object in same layer. */
+ if (base->object->type == OB_MESH) {
+ ob = base->object;
+ if (ob == vertexowner) {
+ /* If vertexowner is given we don't want to check collision with owner object. */
continue;
+ }
ccd_update_deflector_hash_single(hash, ob);
}
}
- else {
- for (Base *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;
- if (ob == vertexowner) {
- /* if vertexowner is given we don't want to check collision with owner object */
- continue;
- }
-
- ccd_update_deflector_hash_single(hash, ob);
- }
- }
- }
}
@@ -977,29 +963,21 @@ static void free_softbody_intern(SoftBody *sb)
/**
* \note group overrides scene when not NULL.
*/
-static bool are_there_deflectors(Scene *scene, Group *group, unsigned int layer)
+static bool are_there_deflectors(ViewLayer *view_layer)
{
- if (group) {
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- if (go->ob->pd && go->ob->pd->deflect)
+ for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (base->object->pd) {
+ if (base->object->pd->deflect)
return 1;
}
}
- else {
- for (Base *base = scene->base.first; base; base= base->next) {
- if ( (base->lay & layer) && base->object->pd) {
- if (base->object->pd->deflect)
- return 1;
- }
- }
- }
return 0;
}
-static int query_external_colliders(Scene *scene, Group *group, Object *me)
+static int query_external_colliders(ViewLayer *view_layer, Group *group)
{
- return(are_there_deflectors(scene, group, me->lay));
+ return(are_there_deflectors(group != NULL ? group->view_layer : view_layer));
}
/* --- dependency information functions*/
@@ -1544,12 +1522,12 @@ static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow,
}
-static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow)
+static void scan_for_ext_spring_forces(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float timenow)
{
SoftBody *sb = ob->soft;
ListBase *do_effector = NULL;
- do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
+ do_effector = pdInitEffectors(eval_ctx, scene, ob, NULL, sb->effector_weights, true);
_scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector);
pdEndEffectors(&do_effector);
}
@@ -1561,7 +1539,7 @@ static void *exec_scan_for_ext_spring_forces(void *data)
return NULL;
}
-static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow, int totsprings, int *UNUSED(ptr_to_break_func(void)))
+static void sb_sfesf_threads_run(const struct EvaluationContext *eval_ctx, Scene *scene, struct Object *ob, float timenow, int totsprings, int *UNUSED(ptr_to_break_func(void)))
{
ListBase *do_effector = NULL;
ListBase threads;
@@ -1569,7 +1547,7 @@ static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,
int i, totthread, left, dec;
int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
- do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true);
+ do_effector= pdInitEffectors(eval_ctx, scene, ob, NULL, ob->soft->effector_weights, true);
/* figure the number of threads while preventing pretty pointless threading overhead */
totthread= BKE_scene_num_threads(scene);
@@ -2233,7 +2211,7 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t
MEM_freeN(sb_threads);
}
-static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow)
+static void softbody_calc_forcesEx(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float forcetime, float timenow)
{
/* rule we never alter free variables :bp->vec bp->pos in here !
* this will ruin adaptive stepsize AKA heun! (BM)
@@ -2249,7 +2227,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
/* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */
/* check conditions for various options */
- do_deflector= query_external_colliders(scene, sb->collision_group, ob);
+ do_deflector= query_external_colliders(eval_ctx->view_layer, sb->collision_group);
/* do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); */ /* UNUSED */
do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
@@ -2258,10 +2236,10 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
/* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */
if (do_springcollision || do_aero)
- sb_sfesf_threads_run(scene, ob, timenow, sb->totspring, NULL);
+ sb_sfesf_threads_run(eval_ctx, scene, ob, timenow, sb->totspring, NULL);
/* after spring scan because it uses Effoctors too */
- do_effector= pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
+ do_effector= pdInitEffectors(eval_ctx, scene, ob, NULL, sb->effector_weights, true);
if (do_deflector) {
float defforce[3];
@@ -2278,11 +2256,11 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
}
-static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, float timenow)
+static void softbody_calc_forces(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float forcetime, float timenow)
{
/* redirection to the new threaded Version */
if (!(G.debug_value & 0x10)) { // 16
- softbody_calc_forcesEx(scene, ob, forcetime, timenow);
+ softbody_calc_forcesEx(eval_ctx, scene, ob, forcetime, timenow);
return;
}
else {
@@ -2313,7 +2291,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
}
/* check conditions for various options */
- do_deflector= query_external_colliders(scene, sb->collision_group, ob);
+ do_deflector= query_external_colliders(eval_ctx->view_layer, sb->collision_group);
do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
@@ -2321,9 +2299,9 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
/* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */
- if (do_springcollision || do_aero) scan_for_ext_spring_forces(scene, ob, timenow);
+ if (do_springcollision || do_aero) scan_for_ext_spring_forces(eval_ctx, scene, ob, timenow);
/* after spring scan because it uses Effoctors too */
- do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true);
+ do_effector= pdInitEffectors(eval_ctx, scene, ob, NULL, ob->soft->effector_weights, true);
if (do_deflector) {
float defforce[3];
@@ -3510,7 +3488,7 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int
}
}
-static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
+static void softbody_step(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SoftBody *sb, float dtime)
{
/* the simulator */
float forcetime;
@@ -3524,11 +3502,11 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
*/
if (dtime < 0 || dtime > 10.5f) return;
- ccd_update_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash);
+ ccd_update_deflector_hash(eval_ctx->view_layer, sb->collision_group, ob, sb->scratch->colliderhash);
if (sb->scratch->needstobuildcollider) {
- if (query_external_colliders(scene, sb->collision_group, ob)) {
- ccd_build_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash);
+ if (query_external_colliders(eval_ctx->view_layer, sb->collision_group)) {
+ ccd_build_deflector_hash(eval_ctx->view_layer, sb->collision_group, ob, sb->scratch->colliderhash);
}
sb->scratch->needstobuildcollider=0;
}
@@ -3558,12 +3536,12 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
sb->scratch->flag &= ~SBF_DOFUZZY;
/* do predictive euler step */
- softbody_calc_forces(scene, ob, forcetime, timedone/dtime);
+ softbody_calc_forces(eval_ctx, scene, ob, forcetime, timedone/dtime);
softbody_apply_forces(ob, forcetime, 1, NULL, mid_flags);
/* crop new slope values to do averaged slope step */
- softbody_calc_forces(scene, ob, forcetime, timedone/dtime);
+ softbody_calc_forces(eval_ctx, scene, ob, forcetime, timedone/dtime);
softbody_apply_forces(ob, forcetime, 2, &err, mid_flags);
softbody_apply_goalsnap(ob);
@@ -3644,7 +3622,7 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
}
/* simulates one step. framenr is in frames */
-void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts)
+void sbObjectStep(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts)
{
SoftBody *sb= ob->soft;
PointCache *cache;
@@ -3652,7 +3630,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
float dtime, timescale;
int framedelta, framenr, startframe, endframe;
int cache_result;
-
cache= sb->pointcache;
framenr= (int)cfra;
@@ -3721,7 +3698,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
}
/* try to read from cache */
- bool can_simulate = (framenr == sb->last_frame+1) && !(cache->flag & PTCACHE_BAKED);
+ bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED);
cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate);
@@ -3760,7 +3737,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
dtime = framedelta*timescale;
/* do simulation */
- softbody_step(scene, ob, sb, dtime);
+ softbody_step(eval_ctx, scene, ob, sb, dtime);
softbody_to_object(ob, vertexCos, numVerts, 0);
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 45d1f969d64..747ffdafe8b 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -48,13 +48,11 @@
#include "DNA_speaker_types.h"
#ifdef WITH_AUDASPACE
-# include AUD_SOUND_H
-# include AUD_SEQUENCE_H
-# include AUD_HANDLE_H
-# include AUD_SPECIAL_H
-# ifdef WITH_SYSTEM_AUDASPACE
-# include "../../../intern/audaspace/intern/AUD_Set.h"
-# endif
+# include <AUD_Sound.h>
+# include <AUD_Sequence.h>
+# include <AUD_Handle.h>
+# include <AUD_Special.h>
+# include "../../../intern/audaspace/intern/AUD_Set.h"
#endif
#include "BKE_global.h"
@@ -228,7 +226,7 @@ void BKE_sound_init_once(void)
atexit(BKE_sound_exit_once);
}
-static AUD_Device *sound_device;
+static AUD_Device *sound_device = NULL;
void *BKE_sound_get_device(void)
{
@@ -237,6 +235,9 @@ void *BKE_sound_get_device(void)
void BKE_sound_init(struct Main *bmain)
{
+ /* Make sure no instance of the sound system is running, otherwise we get leaks. */
+ BKE_sound_exit();
+
AUD_DeviceSpecs specs;
int device, buffersize;
const char *device_name;
@@ -302,7 +303,6 @@ void BKE_sound_exit_once(void)
sound_device = NULL;
AUD_exitOnce();
-#ifdef WITH_SYSTEM_AUDASPACE
if (audio_device_names != NULL) {
int i;
for (i = 0; audio_device_names[i]; i++) {
@@ -311,7 +311,6 @@ void BKE_sound_exit_once(void)
free(audio_device_names);
audio_device_names = NULL;
}
-#endif
}
/* XXX unused currently */
@@ -807,13 +806,76 @@ void BKE_sound_read_waveform(bSound *sound, short *stop)
BLI_spin_unlock(sound->spinlock);
}
-void BKE_sound_update_scene(Main *bmain, struct Scene *scene)
+static void sound_update_base(Scene *scene, Base *base, void *new_set)
{
- Object *ob;
- Base *base;
+ Object *ob = base->object;
NlaTrack *track;
NlaStrip *strip;
Speaker *speaker;
+ float quat[4];
+
+ if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
+ return;
+ }
+
+ ob->id.tag &= ~LIB_TAG_DOIT;
+
+ if ((ob->type != OB_SPEAKER) || !ob->adt) {
+ return;
+ }
+
+ for (track = ob->adt->nla_tracks.first; track; track = track->next) {
+ for (strip = track->strips.first; strip; strip = strip->next) {
+ if (strip->type != NLASTRIP_TYPE_SOUND) {
+ continue;
+ }
+ speaker = (Speaker *)ob->data;
+
+ if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) {
+ if (speaker->sound) {
+ AUD_SequenceEntry_move(strip->speaker_handle, (double)strip->start / FPS, FLT_MAX, 0);
+ }
+ else {
+ AUD_Sequence_remove(scene->sound_scene, strip->speaker_handle);
+ strip->speaker_handle = NULL;
+ }
+ }
+ else {
+ if (speaker->sound) {
+ strip->speaker_handle = AUD_Sequence_add(scene->sound_scene,
+ speaker->sound->playback_handle,
+ (double)strip->start / FPS, FLT_MAX, 0);
+ AUD_SequenceEntry_setRelative(strip->speaker_handle, 0);
+ }
+ }
+
+ if (strip->speaker_handle) {
+ const bool mute = ((strip->flag & NLASTRIP_FLAG_MUTED) || (speaker->flag & SPK_MUTED));
+ AUD_addSet(new_set, strip->speaker_handle);
+ AUD_SequenceEntry_setVolumeMaximum(strip->speaker_handle, speaker->volume_max);
+ AUD_SequenceEntry_setVolumeMinimum(strip->speaker_handle, speaker->volume_min);
+ AUD_SequenceEntry_setDistanceMaximum(strip->speaker_handle, speaker->distance_max);
+ AUD_SequenceEntry_setDistanceReference(strip->speaker_handle, speaker->distance_reference);
+ AUD_SequenceEntry_setAttenuation(strip->speaker_handle, speaker->attenuation);
+ AUD_SequenceEntry_setConeAngleOuter(strip->speaker_handle, speaker->cone_angle_outer);
+ AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner);
+ AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer);
+
+ mat4_to_quat(quat, ob->obmat);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_LOCATION, CFRA, ob->obmat[3], 1);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_ORIENTATION, CFRA, quat, 1);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_VOLUME, CFRA, &speaker->volume, 1);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_PITCH, CFRA, &speaker->pitch, 1);
+ AUD_SequenceEntry_setSound(strip->speaker_handle, speaker->sound->playback_handle);
+ AUD_SequenceEntry_setMuted(strip->speaker_handle, mute);
+ }
+ }
+ }
+}
+
+void BKE_sound_update_scene(Main *bmain, Scene *scene)
+{
+ Base *base;
Scene *sce_it;
void *new_set = AUD_createSet();
@@ -822,59 +884,18 @@ void BKE_sound_update_scene(Main *bmain, struct Scene *scene)
/* cheap test to skip looping over all objects (no speakers is a common case) */
if (!BLI_listbase_is_empty(&bmain->speaker)) {
- for (SETLOOPER(scene, sce_it, base)) {
- ob = base->object;
- if ((ob->type != OB_SPEAKER) || !ob->adt) {
- continue;
- }
- for (track = ob->adt->nla_tracks.first; track; track = track->next) {
- for (strip = track->strips.first; strip; strip = strip->next) {
- if (strip->type != NLASTRIP_TYPE_SOUND) {
- continue;
- }
- speaker = (Speaker *)ob->data;
-
- if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) {
- if (speaker->sound) {
- AUD_SequenceEntry_move(strip->speaker_handle, (double)strip->start / FPS, FLT_MAX, 0);
- }
- else {
- AUD_Sequence_remove(scene->sound_scene, strip->speaker_handle);
- strip->speaker_handle = NULL;
- }
- }
- else {
- if (speaker->sound) {
- strip->speaker_handle = AUD_Sequence_add(scene->sound_scene,
- speaker->sound->playback_handle,
- (double)strip->start / FPS, FLT_MAX, 0);
- AUD_SequenceEntry_setRelative(strip->speaker_handle, 0);
- }
- }
-
- if (strip->speaker_handle) {
- const bool mute = ((strip->flag & NLASTRIP_FLAG_MUTED) || (speaker->flag & SPK_MUTED));
- AUD_addSet(new_set, strip->speaker_handle);
- AUD_SequenceEntry_setVolumeMaximum(strip->speaker_handle, speaker->volume_max);
- AUD_SequenceEntry_setVolumeMinimum(strip->speaker_handle, speaker->volume_min);
- AUD_SequenceEntry_setDistanceMaximum(strip->speaker_handle, speaker->distance_max);
- AUD_SequenceEntry_setDistanceReference(strip->speaker_handle, speaker->distance_reference);
- AUD_SequenceEntry_setAttenuation(strip->speaker_handle, speaker->attenuation);
- AUD_SequenceEntry_setConeAngleOuter(strip->speaker_handle, speaker->cone_angle_outer);
- AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner);
- AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer);
-
- mat4_to_quat(quat, ob->obmat);
- AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_LOCATION, CFRA, ob->obmat[3], 1);
- AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_ORIENTATION, CFRA, quat, 1);
- AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_VOLUME, CFRA, &speaker->volume, 1);
- AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_PITCH, CFRA, &speaker->pitch, 1);
- AUD_SequenceEntry_setSound(strip->speaker_handle, speaker->sound->playback_handle);
- AUD_SequenceEntry_setMuted(strip->speaker_handle, mute);
- }
- }
+ BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true);
+
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ sound_update_base(scene, base, new_set);
}
}
+
+ for (SETLOOPER_SET_ONLY(scene, sce_it, base)) {
+ sound_update_base(scene, base, new_set);
+ }
+
}
while ((handle = AUD_getSet(scene->speaker_handles))) {
@@ -907,28 +928,12 @@ float BKE_sound_get_length(bSound *sound)
char **BKE_sound_get_device_names(void)
{
if (audio_device_names == NULL) {
-#ifdef WITH_SYSTEM_AUDASPACE
audio_device_names = AUD_getDeviceNames();
-#else
- static const char *names[] = {
- "Null", "SDL", "OpenAL", "JACK", NULL
- };
- audio_device_names = (char **)names;
-#endif
}
return audio_device_names;
}
-bool BKE_sound_is_jack_supported(void)
-{
-#ifdef WITH_SYSTEM_AUDASPACE
- return 1;
-#else
- return (bool)AUD_isJackSupported();
-#endif
-}
-
#else /* WITH_AUDASPACE */
#include "BLI_utildefines.h"
@@ -975,5 +980,6 @@ void BKE_sound_set_scene_sound_pan(void *UNUSED(handle), float UNUSED(pan), char
void BKE_sound_set_scene_volume(struct Scene *UNUSED(scene), float UNUSED(volume)) {}
void BKE_sound_set_scene_sound_pitch(void *UNUSED(handle), float UNUSED(pitch), char UNUSED(animated)) {}
float BKE_sound_get_length(struct bSound *UNUSED(sound)) { return 0; }
-bool BKE_sound_is_jack_supported(void) { return false; }
+char **BKE_sound_get_device_names(void) { static char *names[1] = {NULL}; return names; }
+
#endif /* WITH_AUDASPACE */
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index f8025f8df84..2f9a7090caf 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -1903,7 +1903,8 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
no[1] = b_dZ * a_cX - b_dX * a_cZ;
no[2] = b_dX * a_cY - b_dY * a_cX;
- /* don't normalize, GL_NORMALIZE is enabled */
+ normalize_v3(no); /* we no longer rely on GL_NORMALIZE */
+
glNormal3fv(no);
}
@@ -3411,261 +3412,6 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
#undef PASSATTRIB
}
-static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
- DMSetDrawOptionsTex drawParams,
- DMSetDrawOptionsMappedTex drawParamsMapped,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGKey key;
- int colType;
- const MLoopCol *mloopcol = NULL;
- MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
- DMFlagMat *faceFlags = ccgdm->faceFlags;
- DMDrawOption draw_option;
- int i, totpoly;
- bool flush;
- const bool use_tface = (flag & DM_DRAW_USE_ACTIVE_UV) != 0;
- const bool use_colors = (flag & DM_DRAW_USE_COLORS) != 0;
- unsigned int next_actualFace;
- unsigned int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
- int mat_index;
- int tot_element, start_element, tot_drawn;
-
- if (use_colors) {
- colType = CD_TEXTURE_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- if (!mloopcol) {
- colType = CD_PREVIEW_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- }
- if (!mloopcol) {
- colType = CD_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- }
- }
-
-#ifdef WITH_OPENSUBDIV
- if (ccgdm->useGpuBackend) {
- const int active_uv_layer = CustomData_get_active_layer_index(&dm->loopData, CD_MLOOPUV);
- if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, active_uv_layer) == false)) {
- return;
- }
- if (drawParams == NULL) {
- ccgSubSurf_drawGLMesh(ss, true, -1, -1);
- return;
- }
- const int level = ccgSubSurf_getSubdivisionLevels(ss);
- const int face_side = 1 << level;
- const int grid_side = 1 << (level - 1);
- const int face_patches = face_side * face_side;
- const int grid_patches = grid_side * grid_side;
- const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
- int current_patch = 0;
- int mat_nr = -1;
- int start_draw_patch = 0, num_draw_patches = 0;
- bool draw_smooth = false;
- for (i = 0; i < num_base_faces; ++i) {
- const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
- const int num_patches = (num_face_verts == 4) ? face_patches
- : num_face_verts * grid_patches;
- if (faceFlags) {
- mat_nr = faceFlags[i].mat_nr;
- draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
- }
- else {
- mat_nr = 0;
- draw_smooth = false;
- }
-
- if (drawParams != NULL) {
- MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[i] : NULL;
- draw_option = drawParams(tp, (mloopcol != NULL), mat_nr);
- }
- else {
- draw_option = (drawParamsMapped)
- ? drawParamsMapped(userData, i, mat_nr)
- : DM_DRAW_OPTION_NORMAL;
- }
-
- flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == num_base_faces - 1);
-
- const int next_face = min_ii(i + 1, num_base_faces - 1);
- if (!flush && compareDrawOptions) {
- flush |= compareDrawOptions(userData, i, next_face) == 0;
- }
- if (!flush && faceFlags) {
- bool new_draw_smooth = (faceFlags[next_face].flag & ME_SMOOTH);
- flush |= (new_draw_smooth != draw_smooth);
- }
-
- current_patch += num_patches;
-
- if (flush) {
- if (draw_option != DM_DRAW_OPTION_SKIP) {
- num_draw_patches += num_patches;
- }
- if (num_draw_patches != 0) {
- glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
- ccgSubSurf_drawGLMesh(ss,
- true,
- start_draw_patch,
- num_draw_patches);
- }
- start_draw_patch = current_patch;
- num_draw_patches = 0;
- }
- else {
- num_draw_patches += num_patches;
- }
- }
- glShadeModel(GL_SMOOTH);
- return;
- }
-#endif
-
- CCG_key_top_level(&key, ss);
- ccgdm_pbvh_update(ccgdm);
-
- GPU_vertex_setup(dm);
- GPU_normal_setup(dm);
- GPU_triangle_setup(dm);
- if (flag & DM_DRAW_USE_TEXPAINT_UV)
- GPU_texpaint_uv_setup(dm);
- else
- GPU_uv_setup(dm);
- if (mloopcol) {
- GPU_color_setup(dm, colType);
- }
-
- next_actualFace = 0;
-
- /* lastFlag = 0; */ /* UNUSED */
- for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
- GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
- next_actualFace = bufmat->polys[0];
- totpoly = bufmat->totpolys;
-
- tot_element = 0;
- tot_drawn = 0;
- start_element = 0;
-
- for (i = 0; i < totpoly; i++) {
- int polyindex = bufmat->polys[i];
- CCGFace *f = ccgdm->faceMap[polyindex].face;
- int numVerts = ccgSubSurf_getFaceNumVerts(f);
- int index = ccgDM_getFaceMapIndex(ss, f);
- int orig_index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
- int mat_nr;
- int facequads = numVerts * gridFaces * gridFaces;
- int actualFace = ccgdm->faceMap[polyindex].startFace;
-
- if (i != totpoly - 1) {
- polyindex = bufmat->polys[i + 1];
- next_actualFace = ccgdm->faceMap[polyindex].startFace;
- }
-
- if (faceFlags) {
- mat_nr = faceFlags[orig_index].mat_nr;
- }
- else {
- mat_nr = 0;
- }
-
- if (drawParams) {
- MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[actualFace] : NULL;
- draw_option = drawParams(tp, (mloopcol != NULL), mat_nr);
- }
- else if (index != ORIGINDEX_NONE)
- draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index, mat_nr) : DM_DRAW_OPTION_NORMAL;
- else
- draw_option = DM_DRAW_OPTION_NORMAL;
-
- /* flush buffer if current triangle isn't drawable or it's last triangle */
- flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 1);
-
- if (!flush && compareDrawOptions) {
- /* also compare draw options and flush buffer if they're different
- * need for face selection highlight in edit mode */
- flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
- }
-
- tot_element += facequads * 6;
-
- if (flush) {
- if (draw_option != DM_DRAW_OPTION_SKIP)
- tot_drawn += facequads * 6;
-
- if (tot_drawn) {
- if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
- GPU_color_switch(1);
- else
- GPU_color_switch(0);
-
- GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn);
- tot_drawn = 0;
- }
-
- start_element = tot_element;
- }
- else {
- tot_drawn += facequads * 6;
- }
- }
- }
-
-
- GPU_buffers_unbind();
-}
-
-static void ccgDM_drawFacesTex(DerivedMesh *dm,
- DMSetDrawOptionsTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag);
-}
-
-static void ccgDM_drawMappedFacesTex(DerivedMesh *dm,
- DMSetDrawOptionsMappedTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
-}
-
-/* same as cdDM_drawUVEdges */
-static void ccgDM_drawUVEdges(DerivedMesh *dm)
-{
- MPoly *mpoly = dm->getPolyArray(dm);
- int totpoly = dm->getNumPolys(dm);
- int prevstart = 0;
- bool prevdraw = true;
- int curpos = 0;
- int i;
-
- GPU_uvedge_setup(dm);
- for (i = 0; i < totpoly; i++, mpoly++) {
- const bool draw = (mpoly->flag & ME_HIDE) == 0;
-
- if (prevdraw != draw) {
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- prevstart = curpos;
- }
-
- curpos += 2 * mpoly->totloop;
- prevdraw = draw;
- }
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- GPU_buffers_unbind();
-}
-
static void ccgDM_drawMappedFaces(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMSetMaterial setMaterial,
@@ -4594,13 +4340,10 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
ccgdm->dm.drawEdges = ccgDM_drawEdges;
ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
- ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
- ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
ccgdm->dm.drawMappedFacesMat = ccgDM_drawMappedFacesMat;
- ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
@@ -5055,8 +4798,7 @@ static bool subsurf_use_gpu_backend(SubsurfFlags flags)
*/
return
(flags & SUBSURF_USE_GPU_BACKEND) != 0 &&
- (U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE) &&
- (openSubdiv_supportGPUDisplay());
+ (U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE);
#else
(void)flags;
return false;
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 7c4aa81ee46..4ae9818f891 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -58,7 +58,6 @@
#include "DNA_node_types.h"
#include "DNA_material_types.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index b4ef381534f..07e071df04a 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -61,6 +61,7 @@
#include "BKE_movieclip.h"
#include "BKE_object.h"
#include "BKE_scene.h"
+#include "BKE_layer.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -400,7 +401,7 @@ void BKE_tracking_get_camera_object_matrix(Scene *scene, Object *ob, float mat[4
if (scene->camera)
ob = scene->camera;
else
- ob = BKE_scene_camera_find(scene);
+ ob = BKE_view_layer_camera_find(BKE_view_layer_from_scene_get(scene));
}
if (ob)
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
new file mode 100644
index 00000000000..8554cf0fb28
--- /dev/null
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -0,0 +1,523 @@
+/*
+ * ***** 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/blenkernel/intern/workspace.c
+ * \ingroup bke
+ */
+
+/* allow accessing private members of DNA_workspace_types.h */
+#define DNA_PRIVATE_WORKSPACE_ALLOW
+
+#include <stdlib.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_string_utils.h"
+#include "BLI_listbase.h"
+
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_workspace.h"
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_workspace_types.h"
+
+#include "MEM_guardedalloc.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Internal utils */
+
+static void workspace_layout_name_set(
+ WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name)
+{
+ BLI_strncpy(layout->name, new_name, sizeof(layout->name));
+ BLI_uniquename(&workspace->layouts, layout, "Layout", '.', offsetof(WorkSpaceLayout, name), sizeof(layout->name));
+}
+
+/**
+ * This should only be used directly when it is to be expected that there isn't
+ * a layout within \a workspace that wraps \a screen. Usually - especially outside
+ * of BKE_workspace - #BKE_workspace_layout_find should be used!
+ */
+static WorkSpaceLayout *workspace_layout_find_exec(
+ const WorkSpace *workspace, const bScreen *screen)
+{
+ return BLI_findptr(&workspace->layouts, screen, offsetof(WorkSpaceLayout, screen));
+}
+
+static void workspace_relation_add(
+ ListBase *relation_list, void *parent, void *data)
+{
+ WorkSpaceDataRelation *relation = MEM_callocN(sizeof(*relation), __func__);
+ relation->parent = parent;
+ relation->value = data;
+ /* add to head, if we switch back to it soon we find it faster. */
+ BLI_addhead(relation_list, relation);
+}
+static void workspace_relation_remove(
+ ListBase *relation_list, WorkSpaceDataRelation *relation)
+{
+ BLI_remlink(relation_list, relation);
+ MEM_freeN(relation);
+}
+
+static void workspace_relation_ensure_updated(
+ ListBase *relation_list, void *parent, void *data)
+{
+ WorkSpaceDataRelation *relation = BLI_findptr(relation_list, parent, offsetof(WorkSpaceDataRelation, parent));
+ if (relation != NULL) {
+ relation->value = data;
+ /* reinsert at the head of the list, so that more commonly used relations are found faster. */
+ BLI_remlink(relation_list, relation);
+ BLI_addhead(relation_list, relation);
+ }
+ else {
+ /* no matching relation found, add new one */
+ workspace_relation_add(relation_list, parent, data);
+ }
+}
+
+static void *workspace_relation_get_data_matching_parent(
+ const ListBase *relation_list, const void *parent)
+{
+ WorkSpaceDataRelation *relation = BLI_findptr(relation_list, parent, offsetof(WorkSpaceDataRelation, parent));
+ if (relation != NULL) {
+ return relation->value;
+ }
+ else {
+ return NULL;
+ }
+}
+
+static void workspace_relation_remove_from_value(
+ ListBase *relation_list, const void *value)
+{
+ for (WorkSpaceDataRelation *relation = relation_list->first, *relation_next; relation; relation = relation_next) {
+ relation_next = relation->next;
+
+ if (relation->value == value) {
+ workspace_relation_remove(relation_list, relation);
+ }
+ }
+}
+
+/**
+ * Checks if \a screen is already used within any workspace. A screen should never be assigned to multiple
+ * WorkSpaceLayouts, but that should be ensured outside of the BKE_workspace module and without such checks.
+ * Hence, this should only be used as assert check before assigining a screen to a workspace.
+ */
+#ifndef NDEBUG
+static bool workspaces_is_screen_used
+#else
+static bool UNUSED_FUNCTION(workspaces_is_screen_used)
+#endif
+ (const Main *bmain, bScreen *screen)
+{
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ if (workspace_layout_find_exec(workspace, screen)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* -------------------------------------------------------------------- */
+/* Create, delete, init */
+
+WorkSpace *BKE_workspace_add(Main *bmain, const char *name)
+{
+ WorkSpace *new_workspace = BKE_libblock_alloc(bmain, ID_WS, name, 0);
+ return new_workspace;
+}
+
+/**
+ * The function that actually frees the workspace data (not workspace itself). It shouldn't be called
+ * directly, instead #BKE_workspace_remove should be, which calls this through #BKE_libblock_free then.
+ *
+ * Should something like a bke_internal.h be added, this should go there!
+ */
+void BKE_workspace_free(WorkSpace *workspace)
+{
+ BKE_workspace_relations_free(&workspace->hook_layout_relations);
+ BKE_workspace_relations_free(&workspace->scene_viewlayer_relations);
+
+ BLI_freelistN(&workspace->layouts);
+ BLI_freelistN(&workspace->transform_orientations);
+
+ BKE_viewrender_free(&workspace->view_render);
+}
+
+/**
+ * Remove \a workspace by freeing itself and its data. This is a higher-level wrapper that
+ * calls #BKE_workspace_free (through #BKE_libblock_free) to free the workspace data, and frees
+ * other data-blocks owned by \a workspace and its layouts (currently that is screens only).
+ *
+ * Always use this to remove (and free) workspaces. Don't free non-ID workspace members here.
+ */
+void BKE_workspace_remove(Main *bmain, WorkSpace *workspace)
+{
+ for (WorkSpaceLayout *layout = workspace->layouts.first, *layout_next; layout; layout = layout_next) {
+ layout_next = layout->next;
+ BKE_workspace_layout_remove(bmain, workspace, layout);
+ }
+ BKE_libblock_free(bmain, workspace);
+}
+
+WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const Main *bmain)
+{
+ WorkSpaceInstanceHook *hook = MEM_callocN(sizeof(WorkSpaceInstanceHook), __func__);
+
+ /* set an active screen-layout for each possible window/workspace combination */
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ BKE_workspace_hook_layout_for_workspace_set(hook, workspace, workspace->layouts.first);
+ }
+
+ return hook;
+}
+void BKE_workspace_instance_hook_free(const Main *bmain, WorkSpaceInstanceHook *hook)
+{
+ /* workspaces should never be freed before wm (during which we call this function) */
+ BLI_assert(!BLI_listbase_is_empty(&bmain->workspaces));
+
+ /* Free relations for this hook */
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first, *relation_next;
+ relation;
+ relation = relation_next)
+ {
+ relation_next = relation->next;
+ if (relation->parent == hook) {
+ workspace_relation_remove(&workspace->hook_layout_relations, relation);
+ }
+ }
+ }
+
+ MEM_freeN(hook);
+}
+
+/**
+ * Add a new layout to \a workspace for \a screen.
+ */
+WorkSpaceLayout *BKE_workspace_layout_add(
+ WorkSpace *workspace,
+ bScreen *screen,
+ const char *name)
+{
+ WorkSpaceLayout *layout = MEM_callocN(sizeof(*layout), __func__);
+
+ BLI_assert(!workspaces_is_screen_used(G.main, screen));
+ layout->screen = screen;
+ workspace_layout_name_set(workspace, layout, name);
+ BLI_addtail(&workspace->layouts, layout);
+
+ return layout;
+}
+
+void BKE_workspace_layout_remove(
+ Main *bmain,
+ WorkSpace *workspace, WorkSpaceLayout *layout)
+{
+ BKE_libblock_free(bmain, BKE_workspace_layout_screen_get(layout));
+ BLI_freelinkN(&workspace->layouts, layout);
+}
+
+void BKE_workspace_relations_free(
+ ListBase *relation_list)
+{
+ for (WorkSpaceDataRelation *relation = relation_list->first, *relation_next; relation; relation = relation_next) {
+ relation_next = relation->next;
+ workspace_relation_remove(relation_list, relation);
+ }
+}
+
+
+/* -------------------------------------------------------------------- */
+/* General Utils */
+
+void BKE_workspace_view_layer_remove_references(
+ const Main *bmain,
+ const ViewLayer *view_layer)
+{
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ workspace_relation_remove_from_value(&workspace->scene_viewlayer_relations, view_layer);
+ }
+}
+
+void BKE_workspace_transform_orientation_remove(
+ WorkSpace *workspace, TransformOrientation *orientation)
+{
+ for (WorkSpaceLayout *layout = workspace->layouts.first; layout; layout = layout->next) {
+ BKE_screen_transform_orientation_remove(BKE_workspace_layout_screen_get(layout), workspace, orientation);
+ }
+
+ BLI_freelinkN(&workspace->transform_orientations, orientation);
+}
+
+TransformOrientation *BKE_workspace_transform_orientation_find(
+ const WorkSpace *workspace, const int index)
+{
+ return BLI_findlink(&workspace->transform_orientations, index);
+}
+
+/**
+ * \return the index that \a orientation has within \a workspace's transform-orientation list or -1 if not found.
+ */
+int BKE_workspace_transform_orientation_get_index(
+ const WorkSpace *workspace, const TransformOrientation *orientation)
+{
+ return BLI_findindex(&workspace->transform_orientations, orientation);
+}
+
+WorkSpaceLayout *BKE_workspace_layout_find(
+ const WorkSpace *workspace, const bScreen *screen)
+{
+ WorkSpaceLayout *layout = workspace_layout_find_exec(workspace, screen);
+ if (layout) {
+ return layout;
+ }
+
+ printf("%s: Couldn't find layout in this workspace: '%s' screen: '%s'. "
+ "This should not happen!\n",
+ __func__, workspace->id.name + 2, screen->id.name + 2);
+
+ return NULL;
+}
+
+/**
+ * Find the layout for \a screen without knowing which workspace to look in.
+ * Can also be used to find the workspace that contains \a screen.
+ *
+ * \param r_workspace: Optionally return the workspace that contains the looked up layout (if found).
+ */
+WorkSpaceLayout *BKE_workspace_layout_find_global(
+ const Main *bmain, const bScreen *screen,
+ WorkSpace **r_workspace)
+{
+ WorkSpaceLayout *layout;
+
+ if (r_workspace) {
+ *r_workspace = NULL;
+ }
+
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ if ((layout = workspace_layout_find_exec(workspace, screen))) {
+ if (r_workspace) {
+ *r_workspace = workspace;
+ }
+
+ return layout;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Circular workspace layout iterator.
+ *
+ * \param callback: Custom function which gets executed for each layout. Can return false to stop iterating.
+ * \param arg: Custom data passed to each \a callback call.
+ *
+ * \return the layout at which \a callback returned false.
+ */
+WorkSpaceLayout *BKE_workspace_layout_iter_circular(
+ const WorkSpace *workspace, WorkSpaceLayout *start,
+ bool (*callback)(const WorkSpaceLayout *layout, void *arg),
+ void *arg, const bool iter_backward)
+{
+ WorkSpaceLayout *iter_layout;
+
+ if (iter_backward) {
+ BLI_LISTBASE_CIRCULAR_BACKWARD_BEGIN(&workspace->layouts, iter_layout, start)
+ {
+ if (!callback(iter_layout, arg)) {
+ return iter_layout;
+ }
+ }
+ BLI_LISTBASE_CIRCULAR_BACKWARD_END(&workspace->layouts, iter_layout, start);
+ }
+ else {
+ BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN(&workspace->layouts, iter_layout, start)
+ {
+ if (!callback(iter_layout, arg)) {
+ return iter_layout;
+ }
+ }
+ BLI_LISTBASE_CIRCULAR_FORWARD_END(&workspace->layouts, iter_layout, start)
+ }
+
+ return NULL;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Getters/Setters */
+
+WorkSpace *BKE_workspace_active_get(WorkSpaceInstanceHook *hook)
+{
+ return hook->active;
+}
+void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace)
+{
+ hook->active = workspace;
+ if (workspace) {
+ WorkSpaceLayout *layout = workspace_relation_get_data_matching_parent(&workspace->hook_layout_relations, hook);
+ if (layout) {
+ hook->act_layout = layout;
+ }
+ }
+}
+
+WorkSpaceLayout *BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook)
+{
+ return hook->act_layout;
+}
+void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook, WorkSpaceLayout *layout)
+{
+ hook->act_layout = layout;
+}
+
+bScreen *BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook)
+{
+ return hook->act_layout->screen;
+}
+void BKE_workspace_active_screen_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace, bScreen *screen)
+{
+ /* we need to find the WorkspaceLayout that wraps this screen */
+ WorkSpaceLayout *layout = BKE_workspace_layout_find(hook->active, screen);
+ BKE_workspace_hook_layout_for_workspace_set(hook, workspace, layout);
+}
+
+#ifdef USE_WORKSPACE_MODE
+eObjectMode BKE_workspace_object_mode_get(const WorkSpace *workspace, const Scene *scene)
+{
+ Base *active_base = BKE_workspace_active_base_get(workspace, scene);
+ return active_base ? active_base->object->mode : OB_MODE_OBJECT;
+}
+void BKE_workspace_object_mode_set(WorkSpace *workspace, Scene *scene, const eObjectMode mode)
+{
+ Base *active_base = BKE_workspace_active_base_get(workspace, scene);
+ if (active_base) {
+ active_base->object->mode = mode;
+ }
+}
+#endif
+
+Base *BKE_workspace_active_base_get(const WorkSpace *workspace, const Scene *scene)
+{
+ ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene);
+ return view_layer->basact;
+}
+
+ListBase *BKE_workspace_transform_orientations_get(WorkSpace *workspace)
+{
+ return &workspace->transform_orientations;
+}
+
+ViewLayer *BKE_workspace_view_layer_get(const WorkSpace *workspace, const Scene *scene)
+{
+ return workspace_relation_get_data_matching_parent(&workspace->scene_viewlayer_relations, scene);
+}
+void BKE_workspace_view_layer_set(WorkSpace *workspace, ViewLayer *layer, Scene *scene)
+{
+ workspace_relation_ensure_updated(&workspace->scene_viewlayer_relations, scene, layer);
+}
+
+ListBase *BKE_workspace_layouts_get(WorkSpace *workspace)
+{
+ return &workspace->layouts;
+}
+
+
+const char *BKE_workspace_layout_name_get(const WorkSpaceLayout *layout)
+{
+ return layout->name;
+}
+void BKE_workspace_layout_name_set(WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name)
+{
+ workspace_layout_name_set(workspace, layout, new_name);
+}
+
+bScreen *BKE_workspace_layout_screen_get(const WorkSpaceLayout *layout)
+{
+ return layout->screen;
+}
+void BKE_workspace_layout_screen_set(WorkSpaceLayout *layout, bScreen *screen)
+{
+ layout->screen = screen;
+}
+
+WorkSpaceLayout *BKE_workspace_hook_layout_for_workspace_get(
+ const WorkSpaceInstanceHook *hook, const WorkSpace *workspace)
+{
+ return workspace_relation_get_data_matching_parent(&workspace->hook_layout_relations, hook);
+}
+void BKE_workspace_hook_layout_for_workspace_set(
+ WorkSpaceInstanceHook *hook, WorkSpace *workspace, WorkSpaceLayout *layout)
+{
+ hook->act_layout = layout;
+ workspace_relation_ensure_updated(&workspace->hook_layout_relations, hook, layout);
+}
+
+/**
+ * Get the render engine of a workspace, to be used in the viewport.
+ */
+ViewRender *BKE_workspace_view_render_get(WorkSpace *workspace)
+{
+ return &workspace->view_render;
+}
+
+/* Flags */
+bool BKE_workspace_use_scene_settings_get(const WorkSpace *workspace)
+{
+ return (workspace->flags & WORKSPACE_USE_SCENE_SETTINGS) != 0;
+}
+
+void BKE_workspace_use_scene_settings_set(WorkSpace *workspace, bool value)
+{
+ if (value) {
+ workspace->flags |= WORKSPACE_USE_SCENE_SETTINGS;
+ }
+ else {
+ workspace->flags &= ~WORKSPACE_USE_SCENE_SETTINGS;
+ }
+}
+
+/* Update / evaluate */
+
+void BKE_workspace_update_tagged(struct EvaluationContext *eval_ctx,
+ Main *bmain,
+ WorkSpace *workspace,
+ Scene *scene)
+{
+ ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene);
+ struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene,
+ view_layer,
+ true);
+ BKE_scene_graph_update_tagged(eval_ctx, depsgraph, bmain, scene, view_layer);
+}
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index acab94be9c5..4abd2a01d40 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -193,3 +193,14 @@ void BKE_world_make_local(Main *bmain, World *wrld, const bool lib_local)
{
BKE_id_make_local_generic(bmain, &wrld->id, true, lib_local);
}
+
+void BKE_world_eval(const struct EvaluationContext *UNUSED(eval_ctx), World *world)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s (%p)\n", __func__, world->id.name, world);
+ }
+ if (!BLI_listbase_is_empty(&world->gpumaterial)) {
+ world->update_flag = 1;
+ GPU_material_uniform_buffer_tag_dirty(&world->gpumaterial);
+ }
+}
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index b5484291e37..60a1bdb0458 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -45,8 +45,8 @@
#include "BLI_blenlib.h"
#ifdef WITH_AUDASPACE
-# include AUD_DEVICE_H
-# include AUD_SPECIAL_H
+# include <AUD_Device.h>
+# include <AUD_Special.h>
#endif
#include "BLI_utildefines.h"
diff --git a/source/blender/blenlib/BLI_callbacks.h b/source/blender/blenlib/BLI_callbacks.h
index fdffbeb4c8d..be53d1f603b 100644
--- a/source/blender/blenlib/BLI_callbacks.h
+++ b/source/blender/blenlib/BLI_callbacks.h
@@ -49,8 +49,6 @@ typedef enum {
BLI_CB_EVT_LOAD_POST,
BLI_CB_EVT_SAVE_PRE,
BLI_CB_EVT_SAVE_POST,
- BLI_CB_EVT_SCENE_UPDATE_PRE,
- BLI_CB_EVT_SCENE_UPDATE_POST,
BLI_CB_EVT_GAME_PRE,
BLI_CB_EVT_GAME_POST,
BLI_CB_EVT_VERSION_UPDATE,
diff --git a/source/blender/blenlib/BLI_iterator.h b/source/blender/blenlib/BLI_iterator.h
new file mode 100644
index 00000000000..49a3cea58bc
--- /dev/null
+++ b/source/blender/blenlib/BLI_iterator.h
@@ -0,0 +1,62 @@
+/*
+ * ***** 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 BLI_Iterator {
+ void *current; /* current pointer we iterate over */
+ void *data; /* stored data required for this iterator */
+ bool skip;
+ bool valid;
+} BLI_Iterator;
+
+typedef void (*IteratorCb)(BLI_Iterator *iter);
+typedef void (*IteratorBeginCb)(BLI_Iterator *iter, void *data_in);
+
+#define ITER_BEGIN(callback_begin, callback_next, callback_end, _data_in, _type, _instance) \
+{ \
+ _type _instance; \
+ IteratorCb callback_end_func = callback_end; \
+ BLI_Iterator iter_macro; \
+ iter_macro.skip = false; \
+ iter_macro.valid = true; \
+ for (callback_begin(&iter_macro, (_data_in)); \
+ iter_macro.valid; \
+ callback_next(&iter_macro)) \
+ { \
+ if (iter_macro.skip) { \
+ iter_macro.skip = false; \
+ continue; \
+ } \
+ _instance = (_type ) iter_macro.current;
+
+#define ITER_END \
+ } \
+ callback_end_func(&iter_macro); \
+}
+
+#endif /* __BLI_ITERATOR_H__ */
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 173ef6861e6..a6f8f9a54e9 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -46,81 +46,112 @@ void unit_m2(float R[2][2]);
void unit_m3(float R[3][3]);
void unit_m4(float R[4][4]);
-void copy_m2_m2(float R[2][2], float A[2][2]);
-void copy_m3_m3(float R[3][3], float A[3][3]);
-void copy_m4_m4(float R[4][4], float A[4][4]);
-void copy_m3_m4(float R[3][3], float A[4][4]);
-void copy_m4_m3(float R[4][4], float A[3][3]);
+void copy_m2_m2(float R[2][2], const float A[2][2]);
+void copy_m3_m3(float R[3][3], const float A[3][3]);
+void copy_m4_m4(float R[4][4], const float A[4][4]);
+void copy_m3_m4(float R[3][3], const float A[4][4]);
+void copy_m4_m3(float R[4][4], const float A[3][3]);
/* double->float */
-void copy_m3_m3d(float R[3][3], double A[3][3]);
+void copy_m3_m3d(float R[3][3], const double A[3][3]);
void swap_m3m3(float A[3][3], float B[3][3]);
void swap_m4m4(float A[4][4], float B[4][4]);
/******************************** Arithmetic *********************************/
-void add_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
-void add_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
+void add_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
+void add_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
-void sub_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
-void sub_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
+void sub_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
+void sub_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
-void mul_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
-void mul_m4_m3m4(float R[4][4], float A[3][3], float B[4][4]);
-void mul_m4_m4m3(float R[4][4], float A[4][4], float B[3][3]);
-void mul_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
-void mul_m3_m3m4(float R[3][3], float A[4][4], float B[3][3]);
+void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
+void mul_m4_m3m4(float R[4][4], const float A[3][3], const float B[4][4]);
+void mul_m4_m4m3(float R[4][4], const float A[4][4], const float B[3][3]);
+void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
+void mul_m3_m3m4(float R[3][3], const float A[4][4], const float B[3][3]);
+
+/* special matrix multiplies
+ * uniq: R <-- AB, R is neither A nor B
+ * pre: R <-- AR
+ * post: R <-- RB
+ */
+void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3]);
+void mul_m3_m3_pre(float R[3][3], const float A[3][3]);
+void mul_m3_m3_post(float R[3][3], const float B[3][3]);
+void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4]);
+void mul_m4_m4_pre(float R[4][4], const float A[4][4]);
+void mul_m4_m4_post(float R[4][4], const float B[4][4]);
/* mul_m3_series */
-void _va_mul_m3_series_3(float R[3][3], float M1[3][3], float M2[3][3]) ATTR_NONNULL();
-void _va_mul_m3_series_4(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3]) ATTR_NONNULL();
-void _va_mul_m3_series_5(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3]) ATTR_NONNULL();
-void _va_mul_m3_series_6(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
- float M5[3][3]) ATTR_NONNULL();
-void _va_mul_m3_series_7(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
- float M5[3][3], float M6[3][3]) ATTR_NONNULL();
-void _va_mul_m3_series_8(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
- float M5[3][3], float M6[3][3], float M7[3][3]) ATTR_NONNULL();
-void _va_mul_m3_series_9(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
- float M5[3][3], float M6[3][3], float M7[3][3], float M8[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_3(
+ float R[3][3], const float M1[3][3], const float M2[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_4(
+ float R[3][3], const float M1[3][3], const float M2[3][3], const float M3[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_5(
+ float R[3][3], const float M1[3][3], const float M2[3][3], const float M3[3][3],
+ const float M4[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_6(
+ float R[3][3], const float M1[3][3], const float M2[3][3], const float M3[3][3],
+ const float M4[3][3], const float M5[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_7(
+ float R[3][3], const float M1[3][3], const float M2[3][3], const float M3[3][3],
+ const float M4[3][3], const float M5[3][3], const float M6[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_8(
+ float R[3][3], const float M1[3][3], const float M2[3][3], const float M3[3][3],
+ const float M4[3][3], const float M5[3][3], const float M6[3][3], const float M7[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_9(
+ float R[3][3], const float M1[3][3], const float M2[3][3], const float M3[3][3],
+ const float M4[3][3], const float M5[3][3], const float M6[3][3], const float M7[3][3],
+ const float M8[3][3]) ATTR_NONNULL();
/* mul_m4_series */
-void _va_mul_m4_series_3(float R[4][4], float M1[4][4], float M2[4][4]) ATTR_NONNULL();
-void _va_mul_m4_series_4(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4]) ATTR_NONNULL();
-void _va_mul_m4_series_5(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4]) ATTR_NONNULL();
-void _va_mul_m4_series_6(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
- float M5[4][4]) ATTR_NONNULL();
-void _va_mul_m4_series_7(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
- float M5[4][4], float M6[4][4]) ATTR_NONNULL();
-void _va_mul_m4_series_8(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
- float M5[4][4], float M6[4][4], float M7[4][4]) ATTR_NONNULL();
-void _va_mul_m4_series_9(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
- float M5[4][4], float M6[4][4], float M7[4][4], float M8[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_3(
+ float R[4][4], const float M1[4][4], const float M2[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_4(
+ float R[4][4], const float M1[4][4], const float M2[4][4], const float M3[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_5(
+ float R[4][4], const float M1[4][4], const float M2[4][4], const float M3[4][4],
+ const float M4[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_6(
+ float R[4][4], const float M1[4][4], const float M2[4][4], const float M3[4][4],
+ const float M4[4][4], const float M5[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_7(
+ float R[4][4], const float M1[4][4], const float M2[4][4], const float M3[4][4],
+ const float M4[4][4], const float M5[4][4], const float M6[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_8(
+ float R[4][4], const float M1[4][4], const float M2[4][4], const float M3[4][4],
+ const float M4[4][4], const float M5[4][4], const float M6[4][4], const float M7[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_9(
+ float R[4][4], const float M1[4][4], const float M2[4][4], const float M3[4][4],
+ const float M4[4][4], const float M5[4][4], const float M6[4][4], const float M7[4][4],
+ const float M8[4][4]) ATTR_NONNULL();
#define mul_m3_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m3_series_, __VA_ARGS__)
#define mul_m4_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m4_series_, __VA_ARGS__)
-void mul_m4_v3(float M[4][4], float r[3]);
-void mul_v3_m4v3(float r[3], float M[4][4], const float v[3]);
-void mul_v2_m4v3(float r[2], float M[4][4], const float v[3]);
-void mul_v2_m2v2(float r[2], float M[2][2], const float v[2]);
-void mul_m2v2(float M[2][2], float v[2]);
-void mul_mat3_m4_v3(float M[4][4], float r[3]);
-void mul_v3_mat3_m4v3(float r[3], float M[4][4], const float v[3]);
-void mul_m4_v4(float M[4][4], float r[4]);
-void mul_v4_m4v4(float r[4], float M[4][4], const float v[4]);
-void mul_project_m4_v3(float M[4][4], float vec[3]);
-void mul_v3_project_m4_v3(float r[3], float mat[4][4], const float vec[3]);
-void mul_v2_project_m4_v3(float r[2], float M[4][4], const float vec[3]);
-
-void mul_m3_v2(float m[3][3], float r[2]);
-void mul_v2_m3v2(float r[2], float m[3][3], float v[2]);
-void mul_m3_v3(float M[3][3], float r[3]);
-void mul_v3_m3v3(float r[3], float M[3][3], const float a[3]);
-void mul_v2_m3v3(float r[2], float M[3][3], const float a[3]);
-void mul_transposed_m3_v3(float M[3][3], float r[3]);
-void mul_transposed_mat3_m4_v3(float M[4][4], float r[3]);
-void mul_m3_v3_double(float M[3][3], double r[3]);
+void mul_m4_v3(const float M[4][4], float r[3]);
+void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3]);
+void mul_v2_m4v3(float r[2], const float M[4][4], const float v[3]);
+void mul_v2_m2v2(float r[2], const float M[2][2], const float v[2]);
+void mul_m2v2(const float M[2][2], float v[2]);
+void mul_mat3_m4_v3(const float M[4][4], float r[3]);
+void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3]);
+void mul_m4_v4(const float M[4][4], float r[4]);
+void mul_v4_m4v4(float r[4], const float M[4][4], const float v[4]);
+void mul_v4_m4v3(float r[4], const float M[4][4], const float v[3]); /* v has implicit w = 1.0f */
+void mul_project_m4_v3(const float M[4][4], float vec[3]);
+void mul_v3_project_m4_v3(float r[3], const float mat[4][4], const float vec[3]);
+void mul_v2_project_m4_v3(float r[2], const float M[4][4], const float vec[3]);
+
+void mul_m3_v2(const float m[3][3], float r[2]);
+void mul_v2_m3v2(float r[2], const float m[3][3], const float v[2]);
+void mul_m3_v3(const float M[3][3], float r[3]);
+void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3]);
+void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3]);
+void mul_transposed_m3_v3(const float M[3][3], float r[3]);
+void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3]);
+void mul_m3_v3_double(const float M[3][3], double r[3]);
void mul_m3_fl(float R[3][3], float f);
void mul_m4_fl(float R[4][4], float f);
@@ -131,103 +162,103 @@ void negate_mat3_m4(float R[4][4]);
void negate_m4(float R[4][4]);
bool invert_m3_ex(float m[3][3], const float epsilon);
-bool invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon);
+bool invert_m3_m3_ex(float m1[3][3], const float m2[3][3], const float epsilon);
bool invert_m3(float R[3][3]);
-bool invert_m3_m3(float R[3][3], float A[3][3]);
+bool invert_m3_m3(float R[3][3], const float A[3][3]);
bool invert_m4(float R[4][4]);
-bool invert_m4_m4(float R[4][4], float A[4][4]);
+bool invert_m4_m4(float R[4][4], const float A[4][4]);
/* double arithmetic (mixed float/double) */
-void mul_m4_v4d(float M[4][4], double r[4]);
-void mul_v4d_m4v4d(double r[4], float M[4][4], double v[4]);
+void mul_m4_v4d(const float M[4][4], double r[4]);
+void mul_v4d_m4v4d(double r[4], const float M[4][4], const double v[4]);
/* double matrix functions (no mixing types) */
-void mul_v3_m3v3_db(double r[3], double M[3][3], const double a[3]);
-void mul_m3_v3_db(double M[3][3], double r[3]);
+void mul_v3_m3v3_db(double r[3], const double M[3][3], const double a[3]);
+void mul_m3_v3_db(const double M[3][3], double r[3]);
/****************************** Linear Algebra *******************************/
void transpose_m3(float R[3][3]);
-void transpose_m3_m3(float R[3][3], float A[3][3]);
-void transpose_m3_m4(float R[3][3], float A[4][4]);
+void transpose_m3_m3(float R[3][3], const float A[3][3]);
+void transpose_m3_m4(float R[3][3], const float A[4][4]);
void transpose_m4(float R[4][4]);
-void transpose_m4_m4(float R[4][4], float A[4][4]);
+void transpose_m4_m4(float R[4][4], const float A[4][4]);
-int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit);
+int compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit);
void normalize_m3_ex(float R[3][3], float r_scale[3]) ATTR_NONNULL();
void normalize_m3(float R[3][3]) ATTR_NONNULL();
-void normalize_m3_m3_ex(float R[3][3], float A[3][3], float r_scale[3]) ATTR_NONNULL();
-void normalize_m3_m3(float R[3][3], float A[3][3]) ATTR_NONNULL();
+void normalize_m3_m3_ex(float R[3][3], const float A[3][3], float r_scale[3]) ATTR_NONNULL();
+void normalize_m3_m3(float R[3][3], const float A[3][3]) ATTR_NONNULL();
void normalize_m4_ex(float R[4][4], float r_scale[3]) ATTR_NONNULL();
void normalize_m4(float R[4][4]) ATTR_NONNULL();
-void normalize_m4_m4_ex(float R[4][4], float A[4][4], float r_scale[3]) ATTR_NONNULL();
-void normalize_m4_m4(float R[4][4], float A[4][4]) ATTR_NONNULL();
+void normalize_m4_m4_ex(float R[4][4], const float A[4][4], float r_scale[3]) ATTR_NONNULL();
+void normalize_m4_m4(float R[4][4], const float A[4][4]) ATTR_NONNULL();
void orthogonalize_m3(float R[3][3], int axis);
void orthogonalize_m4(float R[4][4], int axis);
-bool is_orthogonal_m3(float mat[3][3]);
-bool is_orthogonal_m4(float mat[4][4]);
-bool is_orthonormal_m3(float mat[3][3]);
-bool is_orthonormal_m4(float mat[4][4]);
+bool is_orthogonal_m3(const float mat[3][3]);
+bool is_orthogonal_m4(const float mat[4][4]);
+bool is_orthonormal_m3(const float mat[3][3]);
+bool is_orthonormal_m4(const float mat[4][4]);
-bool is_uniform_scaled_m3(float mat[3][3]);
-bool is_uniform_scaled_m4(float m[4][4]);
+bool is_uniform_scaled_m3(const float mat[3][3]);
+bool is_uniform_scaled_m4(const float m[4][4]);
/* Note: 'adjoint' here means the adjugate (adjunct, "classical adjoint") matrix!
* Nowadays 'adjoint' usually refers to the conjugate transpose,
* which for real-valued matrices is simply the transpose.
*/
-void adjoint_m2_m2(float R[2][2], float A[2][2]);
-void adjoint_m3_m3(float R[3][3], float A[3][3]);
-void adjoint_m4_m4(float R[4][4], float A[4][4]);
+void adjoint_m2_m2(float R[2][2], const float A[2][2]);
+void adjoint_m3_m3(float R[3][3], const float A[3][3]);
+void adjoint_m4_m4(float R[4][4], const float A[4][4]);
float determinant_m2(float a, float b,
float c, float d);
float determinant_m3(float a, float b, float c,
float d, float e, float f,
float g, float h, float i);
-float determinant_m3_array(float m[3][3]);
-float determinant_m4(float A[4][4]);
+float determinant_m3_array(const float m[3][3]);
+float determinant_m4(const float A[4][4]);
#define PSEUDOINVERSE_EPSILON 1e-8f
void svd_m4(float U[4][4], float s[4], float V[4][4], float A[4][4]);
-void pseudoinverse_m4_m4(float Ainv[4][4], float A[4][4], float epsilon);
-void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon);
+void pseudoinverse_m4_m4(float Ainv[4][4], const float A[4][4], float epsilon);
+void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon);
-bool has_zero_axis_m4(float matrix[4][4]);
+bool has_zero_axis_m4(const float matrix[4][4]);
-void invert_m4_m4_safe(float Ainv[4][4], float A[4][4]);
+void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4]);
/****************************** Transformations ******************************/
void scale_m3_fl(float R[3][3], float scale);
void scale_m4_fl(float R[4][4], float scale);
-float mat3_to_scale(float M[3][3]);
-float mat4_to_scale(float M[4][4]);
-float mat4_to_xy_scale(float M[4][4]);
+float mat3_to_scale(const float M[3][3]);
+float mat4_to_scale(const float M[4][4]);
+float mat4_to_xy_scale(const float M[4][4]);
void size_to_mat3(float R[3][3], const float size[3]);
void size_to_mat4(float R[4][4], const float size[3]);
-void mat3_to_size(float r[3], float M[3][3]);
-void mat4_to_size(float r[3], float M[4][4]);
+void mat3_to_size(float r[3], const float M[3][3]);
+void mat4_to_size(float r[3], const float M[4][4]);
void translate_m4(float mat[4][4], float tx, float ty, float tz);
void rotate_m4(float mat[4][4], const char axis, const float angle);
void transform_pivot_set_m4(float mat[4][4], const float pivot[3]);
-void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3]);
-void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4]);
-void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4]);
-void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]);
+void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3]);
+void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4]);
+void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4]);
+void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat[4][4]);
-void mat3_polar_decompose(float mat3[3][3], float r_U[3][3], float r_P[3][3]);
+void mat3_polar_decompose(const float mat3[3][3], float r_U[3][3], float r_P[3][3]);
void loc_eul_size_to_mat4(float R[4][4],
const float loc[3], const float eul[3], const float size[3]);
@@ -238,20 +269,20 @@ void loc_quat_size_to_mat4(float R[4][4],
void loc_axisangle_size_to_mat4(float R[4][4],
const float loc[3], const float axis[4], const float angle, const float size[3]);
-void blend_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t);
-void blend_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t);
+void blend_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], const float t);
+void blend_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], const float t);
-void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t);
-void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t);
+void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], const float t);
+void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], const float t);
-bool is_negative_m3(float mat[3][3]);
-bool is_negative_m4(float mat[4][4]);
+bool is_negative_m3(const float mat[3][3]);
+bool is_negative_m4(const float mat[4][4]);
-bool is_zero_m3(float mat[3][3]);
-bool is_zero_m4(float mat[4][4]);
+bool is_zero_m3(const float mat[3][3]);
+bool is_zero_m4(const float mat[4][4]);
-bool equals_m3m3(float mat1[3][3], float mat2[3][3]);
-bool equals_m4m4(float mat1[4][4], float mat2[4][4]);
+bool equals_m3m3(const float mat1[3][3], const float mat2[3][3]);
+bool equals_m4m4(const float mat1[4][4], const float mat2[4][4]);
/* SpaceTransform helper */
typedef struct SpaceTransform {
@@ -260,8 +291,8 @@ typedef struct SpaceTransform {
} SpaceTransform;
-void BLI_space_transform_from_matrices(struct SpaceTransform *data, float local[4][4], float target[4][4]);
-void BLI_space_transform_global_from_matrices(struct SpaceTransform *data, float local[4][4], float target[4][4]);
+void BLI_space_transform_from_matrices(struct SpaceTransform *data, const float local[4][4], const float target[4][4]);
+void BLI_space_transform_global_from_matrices(struct SpaceTransform *data, const float local[4][4], const float target[4][4]);
void BLI_space_transform_apply(const struct SpaceTransform *data, float co[3]);
void BLI_space_transform_invert(const struct SpaceTransform *data, float co[3]);
void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float no[3]);
@@ -272,8 +303,8 @@ void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float
/*********************************** Other ***********************************/
-void print_m3(const char *str, float M[3][3]);
-void print_m4(const char *str, float M[4][4]);
+void print_m3(const char *str, const float M[3][3]);
+void print_m4(const char *str, const float M[4][4]);
#define print_m3_id(M) print_m3(STRINGIFY(M), M)
#define print_m4_id(M) print_m4(STRINGIFY(M), M)
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 3f603311530..e4e0bf22de0 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -123,7 +123,7 @@ MINLINE void mul_v4_fl(float r[4], float f);
MINLINE void mul_v4_v4fl(float r[3], const float a[3], float f);
MINLINE void mul_v2_v2_cw(float r[2], const float mat[2], const float vec[2]);
MINLINE void mul_v2_v2_ccw(float r[2], const float mat[2], const float vec[2]);
-MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenlib/BLI_memiter.h b/source/blender/blenlib/BLI_memiter.h
new file mode 100644
index 00000000000..b16f1ae8c43
--- /dev/null
+++ b/source/blender/blenlib/BLI_memiter.h
@@ -0,0 +1,73 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_MEMITER_H__
+#define __BLI_MEMITER_H__
+
+/** \file BLI_memiter.h
+ * \ingroup bli
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "BLI_sys_types.h"
+#include "BLI_compiler_attrs.h"
+#include "BLI_compiler_compat.h"
+
+/* 512kb, good default for small elems. */
+#define BLI_MEMITER_DEFAULT_SIZE (1 << 19)
+
+struct BLI_memiter;
+struct BLI_memiter_chunk;
+
+typedef struct BLI_memiter BLI_memiter;
+
+/* warning, ATTR_MALLOC flag on BLI_memiter_alloc causes crash, see: D2756 */
+BLI_memiter *BLI_memiter_create(unsigned int chunk_size) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+void *BLI_memiter_alloc(BLI_memiter *mi, unsigned int size) ATTR_RETURNS_NONNULL ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void BLI_memiter_alloc_from(BLI_memiter *mi, uint elem_size, const void *data_from) ATTR_NONNULL(1, 3);
+void *BLI_memiter_calloc(BLI_memiter *mi, unsigned int size) ATTR_RETURNS_NONNULL ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void BLI_memiter_destroy(BLI_memiter *mi) ATTR_NONNULL(1);
+void BLI_memiter_clear(BLI_memiter *mi) ATTR_NONNULL(1);
+unsigned int BLI_memiter_count(const BLI_memiter *mi) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+
+/* utils */
+void *BLI_memiter_elem_first(BLI_memiter *mi);
+void *BLI_memiter_elem_first_size(BLI_memiter *mi, unsigned int *r_size);
+
+/* private structure */
+typedef struct BLI_memiter_handle {
+ struct BLI_memiter_elem *elem;
+ uint elem_left;
+} BLI_memiter_handle;
+
+void BLI_memiter_iter_init(BLI_memiter *mi, BLI_memiter_handle *iter) ATTR_NONNULL();
+bool BLI_memiter_iter_done(const BLI_memiter_handle *iter) ATTR_NONNULL();
+void *BLI_memiter_iter_step(BLI_memiter_handle *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void *BLI_memiter_iter_step_size(BLI_memiter_handle *iter, uint *r_size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BLI_MEMITER_H__ */
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 61a1241cd8f..9e7b4ed8b6f 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -50,6 +50,7 @@ set(SRC
intern/BLI_kdtree.c
intern/BLI_linklist.c
intern/BLI_memarena.c
+ intern/BLI_memiter.c
intern/BLI_mempool.c
intern/DLRB_tree.c
intern/array_store.c
@@ -156,6 +157,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
@@ -178,6 +180,7 @@ set(SRC
BLI_math_statistics.h
BLI_math_vector.h
BLI_memarena.h
+ BLI_memiter.h
BLI_memory_utils.h
BLI_mempool.h
BLI_noise.h
diff --git a/source/blender/blenlib/intern/BLI_memiter.c b/source/blender/blenlib/intern/BLI_memiter.c
new file mode 100644
index 00000000000..9c5f026f836
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_memiter.c
@@ -0,0 +1,357 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/BLI_memiter.c
+ * \ingroup bli
+ *
+ * Simple, fast memory allocator for allocating many small elements of different sizes
+ * in fixed size memory chunks,
+ * although allocations bigger than the chunk size are supported.
+ * They will reduce the efficiency of this data-structure.
+ * Elements are pointer aligned.
+ *
+ * Supports:
+ *
+ * - Allocation of mixed sizes.
+ * - Iterating over allocations in-order.
+ * - Clearing for re-use.
+ *
+ * Unsupported:
+ *
+ * - Freeing individual elements.
+ *
+ * \note We could inline iteration stepping,
+ * but tests show this doesn't give noticeable speedup.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "BLI_utildefines.h"
+
+#include "BLI_memiter.h" /* own include */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_strict_flags.h" /* keep last */
+
+typedef uintptr_t data_t;
+typedef intptr_t offset_t;
+
+/* Write the chunk terminator on adding each element.
+ * typically we rely on the 'count' to avoid iterating past the end. */
+// #define USE_TERMINATE_PARANOID
+
+/* Currently totalloc isnt used. */
+ // #define USE_TOTALLOC
+
+/* pad must be power of two */
+#define PADUP(num, pad) (((num) + ((pad) - 1)) & ~((pad) - 1))
+
+typedef struct BLI_memiter_elem {
+ offset_t size;
+ data_t data[0];
+} BLI_memiter_elem;
+
+typedef struct BLI_memiter_chunk {
+ struct BLI_memiter_chunk *next;
+ /**
+ * internal format is:
+ * ``[next_pointer, size:data, size:data, ..., negative_offset]``
+ *
+ * Where negative offset rewinds to the start.
+ */
+ data_t data[0];
+} BLI_memiter_chunk;
+
+typedef struct BLI_memiter {
+ /* A pointer to 'head' is needed so we can iterate in the order allocated. */
+ struct BLI_memiter_chunk *head, *tail;
+ data_t *data_curr;
+ data_t *data_last;
+ /* Used unless a large element is requested.
+ * (which should be very rare!). */
+ uint chunk_size_in_bytes_min;
+ uint count;
+#ifdef USE_TOTALLOC
+ uint totalloc;
+#endif
+} BLI_memiter;
+
+
+BLI_INLINE uint data_offset_from_size(uint size)
+{
+ return (PADUP(size, (uint)sizeof(data_t))) / (uint)sizeof(data_t);
+}
+
+static void memiter_set_rewind_offset(BLI_memiter *mi)
+{
+ BLI_memiter_elem *elem = (BLI_memiter_elem *)mi->data_curr;
+ elem->size = (offset_t)(((data_t *)mi->tail) - mi->data_curr);
+ BLI_assert(elem->size < 0);
+}
+
+static void memiter_init(BLI_memiter *mi)
+{
+ mi->head = NULL;
+ mi->tail = NULL;
+ mi->data_curr = NULL;
+ mi->data_last = NULL;
+ mi->count = 0;
+#ifdef USE_TOTALLOC
+ mi->totalloc = 0;
+#endif
+}
+
+/* -------------------------------------------------------------------- */
+
+/** \name Public API's
+ * \{ */
+
+/**
+ * \param chunk_size_min: Should be a power of two and
+ * significantly larger than the average element size used.
+ *
+ * While allocations of any size are supported, they won't be efficient
+ * (effectively becoming a single-linked list).
+ *
+ * Its intended that many elements can be stored per chunk.
+ */
+BLI_memiter *BLI_memiter_create(uint chunk_size_min)
+{
+ BLI_memiter *mi = MEM_mallocN(sizeof(BLI_memiter), "BLI_memiter");
+ memiter_init(mi);
+
+ /* Small values are used for tests to check for correctness,
+ * but otherwise not that useful. */
+ const uint slop_space = (sizeof(BLI_memiter_chunk) + MEM_SIZE_OVERHEAD);
+ if (chunk_size_min >= 1024) {
+ /* As long as the input is a power of 2, this will give efficient sizes. */
+ chunk_size_min -= slop_space;
+ }
+
+ mi->chunk_size_in_bytes_min = chunk_size_min;
+ return mi;
+}
+
+void *BLI_memiter_alloc(BLI_memiter *mi, uint elem_size)
+{
+ const uint data_offset = data_offset_from_size(elem_size);
+ data_t *data_curr_next = mi->data_curr + (1 + data_offset);
+
+ if (UNLIKELY(mi->data_curr == NULL) || (data_curr_next > mi->data_last)) {
+
+#ifndef USE_TERMINATE_PARANOID
+ if (mi->data_curr != NULL) {
+ memiter_set_rewind_offset(mi);
+ }
+#endif
+
+ uint chunk_size_in_bytes = mi->chunk_size_in_bytes_min;
+ if (UNLIKELY(chunk_size_in_bytes < elem_size + (uint)sizeof(data_t[2]))) {
+ chunk_size_in_bytes = elem_size + (uint)sizeof(data_t[2]);
+ }
+ uint chunk_size = data_offset_from_size(chunk_size_in_bytes);
+ BLI_memiter_chunk *chunk = MEM_mallocN(
+ sizeof(BLI_memiter_chunk) +
+ (chunk_size * sizeof(data_t)),
+ "BLI_memiter_chunk");
+
+ if (mi->head == NULL) {
+ BLI_assert(mi->tail == NULL);
+ mi->head = chunk;
+ }
+ else {
+ mi->tail->next = chunk;
+ }
+ mi->tail = chunk;
+ chunk->next = NULL;
+
+ mi->data_curr = chunk->data;
+ mi->data_last = chunk->data + (chunk_size - 1);
+ data_curr_next = mi->data_curr + (1 + data_offset);
+ }
+
+ BLI_assert(data_curr_next <= mi->data_last);
+
+ BLI_memiter_elem *elem = (BLI_memiter_elem *)mi->data_curr;
+ elem->size = (offset_t)elem_size;
+ mi->data_curr = data_curr_next;
+
+#ifdef USE_TERMINATE_PARANOID
+ memiter_set_rewind_offset(mi);
+#endif
+
+ mi->count += 1;
+
+#ifdef USE_TOTALLOC
+ mi->totalloc += elem_size;
+#endif
+
+ return elem->data;
+}
+
+void *BLI_memiter_calloc(BLI_memiter *mi, uint elem_size)
+{
+ void *data = BLI_memiter_alloc(mi, elem_size);
+ memset(data, 0, elem_size);
+ return data;
+}
+
+void BLI_memiter_alloc_from(BLI_memiter *mi, uint elem_size, const void *data_from)
+{
+ void *data = BLI_memiter_alloc(mi, elem_size);
+ memcpy(data, data_from, elem_size);
+}
+
+static void memiter_free_data(BLI_memiter *mi)
+{
+ BLI_memiter_chunk *chunk = mi->head;
+ while (chunk) {
+ BLI_memiter_chunk *chunk_next = chunk->next;
+ MEM_freeN(chunk);
+ chunk = chunk_next;
+ }
+}
+
+void BLI_memiter_destroy(BLI_memiter *mi)
+{
+ memiter_free_data(mi);
+ MEM_freeN(mi);
+}
+
+void BLI_memiter_clear(BLI_memiter *mi)
+{
+ memiter_free_data(mi);
+ memiter_init(mi);
+}
+
+uint BLI_memiter_count(const BLI_memiter *mi)
+{
+ return mi->count;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Helper API's
+ * \{ */
+
+/* Support direct lookup for first. */
+void *BLI_memiter_elem_first(BLI_memiter *mi)
+{
+ if (mi->head != NULL) {
+ BLI_memiter_chunk *chunk = mi->head;
+ BLI_memiter_elem *elem = (BLI_memiter_elem *)chunk->data;
+ return elem->data;
+ }
+ else {
+ return NULL;
+ }
+}
+
+void *BLI_memiter_elem_first_size(BLI_memiter *mi, uint *r_size)
+{
+ if (mi->head != NULL) {
+ BLI_memiter_chunk *chunk = mi->head;
+ BLI_memiter_elem *elem = (BLI_memiter_elem *)chunk->data;
+ *r_size = (uint)elem->size;
+ return elem->data;
+ }
+ else {
+ return NULL;
+ }
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Iterator API's
+ *
+ * \note We could loop over elements until a NULL chunk is found,
+ * however this means every allocation needs to preemptively run
+ * #memiter_set_rewind_offset (see #USE_TERMINATE_PARANOID).
+ * Unless we have a call to finalize allocation (which complicates usage).
+ * So use a counter instead.
+ *
+ * \{ */
+
+void BLI_memiter_iter_init(BLI_memiter *mi, BLI_memiter_handle *iter)
+{
+ iter->elem = mi->head ? (BLI_memiter_elem *)mi->head->data : NULL;
+ iter->elem_left = mi->count;
+}
+
+bool BLI_memiter_iter_done(const BLI_memiter_handle *iter)
+{
+ return iter->elem_left != 0;
+}
+
+BLI_INLINE void memiter_chunk_step(BLI_memiter_handle *iter)
+{
+ BLI_assert(iter->elem->size < 0);
+ BLI_memiter_chunk *chunk = (BLI_memiter_chunk *)(((data_t *)iter->elem) + iter->elem->size);
+ chunk = chunk->next;
+ iter->elem = chunk ? (BLI_memiter_elem *)chunk->data : NULL;
+ BLI_assert(iter->elem == NULL || iter->elem->size >= 0);
+}
+
+void *BLI_memiter_iter_step_size(BLI_memiter_handle *iter, uint *r_size)
+{
+ if (iter->elem_left != 0) {
+ iter->elem_left -= 1;
+ if (UNLIKELY(iter->elem->size < 0)) {
+ memiter_chunk_step(iter);
+ }
+ BLI_assert(iter->elem->size >= 0);
+ uint size = (uint)iter->elem->size;
+ *r_size = size; /* <-- only difference */
+ data_t *data = iter->elem->data;
+ iter->elem = (BLI_memiter_elem *)&data[data_offset_from_size(size)];
+ return (void *)data;
+ }
+ else {
+ return NULL;
+ }
+}
+
+void *BLI_memiter_iter_step(BLI_memiter_handle *iter)
+{
+ if (iter->elem_left != 0) {
+ iter->elem_left -= 1;
+ if (UNLIKELY(iter->elem->size < 0)) {
+ memiter_chunk_step(iter);
+ }
+ BLI_assert(iter->elem->size >= 0);
+ uint size = (uint)iter->elem->size;
+ data_t *data = iter->elem->data;
+ iter->elem = (BLI_memiter_elem *)&data[data_offset_from_size(size)];
+ return (void *)data;
+ }
+ else {
+ return NULL;
+ }
+}
+
+/** \} */
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index 6d7d24c79c3..cb39134af45 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -359,8 +359,10 @@ void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b, int
}
}
-/* we define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so.
- * for that reason it is sensitive for endianness... with this function it works correctly
+/**
+ * We define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so.
+ * for that reason it is sensitive for endianness... with this function it works correctly.
+ * \see #imm_cpack
*/
unsigned int hsv_to_cpack(float h, float s, float v)
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 311d963f64d..3559500bf63 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -74,23 +74,23 @@ void unit_m4(float m[4][4])
m[3][0] = m[3][1] = m[3][2] = 0.0f;
}
-void copy_m2_m2(float m1[2][2], float m2[2][2])
+void copy_m2_m2(float m1[2][2], const float m2[2][2])
{
memcpy(m1, m2, sizeof(float[2][2]));
}
-void copy_m3_m3(float m1[3][3], float m2[3][3])
+void copy_m3_m3(float m1[3][3], const float m2[3][3])
{
/* destination comes first: */
memcpy(m1, m2, sizeof(float[3][3]));
}
-void copy_m4_m4(float m1[4][4], float m2[4][4])
+void copy_m4_m4(float m1[4][4], const float m2[4][4])
{
memcpy(m1, m2, sizeof(float[4][4]));
}
-void copy_m3_m4(float m1[3][3], float m2[4][4])
+void copy_m3_m4(float m1[3][3], const float m2[4][4])
{
m1[0][0] = m2[0][0];
m1[0][1] = m2[0][1];
@@ -105,7 +105,7 @@ void copy_m3_m4(float m1[3][3], float m2[4][4])
m1[2][2] = m2[2][2];
}
-void copy_m4_m3(float m1[4][4], float m2[3][3]) /* no clear */
+void copy_m4_m3(float m1[4][4], const float m2[3][3]) /* no clear */
{
m1[0][0] = m2[0][0];
m1[0][1] = m2[0][1];
@@ -131,7 +131,7 @@ void copy_m4_m3(float m1[4][4], float m2[3][3]) /* no clear */
}
-void copy_m3_m3d(float R[3][3], double A[3][3])
+void copy_m3_m3d(float R[3][3], const double A[3][3])
{
/* Keep it stupid simple for better data flow in CPU. */
R[0][0] = (float)A[0][0];
@@ -177,64 +177,107 @@ void swap_m4m4(float m1[4][4], float m2[4][4])
/******************************** Arithmetic *********************************/
-void mul_m4_m4m4(float m1[4][4], float m3_[4][4], float m2_[4][4])
+void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
{
- float m2[4][4], m3[4][4];
+ if (A == R)
+ mul_m4_m4_post(R, B);
+ else if (B == R)
+ mul_m4_m4_pre(R, A);
+ else
+ mul_m4_m4m4_uniq(R, A, B);
+}
- /* copy so it works when m1 is the same pointer as m2 or m3 */
- copy_m4_m4(m2, m2_);
- copy_m4_m4(m3, m3_);
+void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4])
+{
+ BLI_assert(R != A && R != B);
- /* matrix product: m1[j][k] = m2[j][i].m3[i][k] */
- m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0] + m2[0][3] * m3[3][0];
- m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1] + m2[0][3] * m3[3][1];
- m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2] + m2[0][3] * m3[3][2];
- m1[0][3] = m2[0][0] * m3[0][3] + m2[0][1] * m3[1][3] + m2[0][2] * m3[2][3] + m2[0][3] * m3[3][3];
+ /* matrix product: R[j][k] = A[j][i] . B[i][k] */
+ R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0] + B[0][3] * A[3][0];
+ R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1] + B[0][3] * A[3][1];
+ R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2] + B[0][3] * A[3][2];
+ R[0][3] = B[0][0] * A[0][3] + B[0][1] * A[1][3] + B[0][2] * A[2][3] + B[0][3] * A[3][3];
- m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0] + m2[1][3] * m3[3][0];
- m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1] + m2[1][3] * m3[3][1];
- m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2] + m2[1][3] * m3[3][2];
- m1[1][3] = m2[1][0] * m3[0][3] + m2[1][1] * m3[1][3] + m2[1][2] * m3[2][3] + m2[1][3] * m3[3][3];
+ R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0] + B[1][3] * A[3][0];
+ R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1] + B[1][3] * A[3][1];
+ R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2] + B[1][3] * A[3][2];
+ R[1][3] = B[1][0] * A[0][3] + B[1][1] * A[1][3] + B[1][2] * A[2][3] + B[1][3] * A[3][3];
- m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0] + m2[2][3] * m3[3][0];
- m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1] + m2[2][3] * m3[3][1];
- m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2] + m2[2][3] * m3[3][2];
- m1[2][3] = m2[2][0] * m3[0][3] + m2[2][1] * m3[1][3] + m2[2][2] * m3[2][3] + m2[2][3] * m3[3][3];
+ R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0] + B[2][3] * A[3][0];
+ R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1] + B[2][3] * A[3][1];
+ R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2] + B[2][3] * A[3][2];
+ R[2][3] = B[2][0] * A[0][3] + B[2][1] * A[1][3] + B[2][2] * A[2][3] + B[2][3] * A[3][3];
- m1[3][0] = m2[3][0] * m3[0][0] + m2[3][1] * m3[1][0] + m2[3][2] * m3[2][0] + m2[3][3] * m3[3][0];
- m1[3][1] = m2[3][0] * m3[0][1] + m2[3][1] * m3[1][1] + m2[3][2] * m3[2][1] + m2[3][3] * m3[3][1];
- m1[3][2] = m2[3][0] * m3[0][2] + m2[3][1] * m3[1][2] + m2[3][2] * m3[2][2] + m2[3][3] * m3[3][2];
- m1[3][3] = m2[3][0] * m3[0][3] + m2[3][1] * m3[1][3] + m2[3][2] * m3[2][3] + m2[3][3] * m3[3][3];
+ R[3][0] = B[3][0] * A[0][0] + B[3][1] * A[1][0] + B[3][2] * A[2][0] + B[3][3] * A[3][0];
+ R[3][1] = B[3][0] * A[0][1] + B[3][1] * A[1][1] + B[3][2] * A[2][1] + B[3][3] * A[3][1];
+ R[3][2] = B[3][0] * A[0][2] + B[3][1] * A[1][2] + B[3][2] * A[2][2] + B[3][3] * A[3][2];
+ R[3][3] = B[3][0] * A[0][3] + B[3][1] * A[1][3] + B[3][2] * A[2][3] + B[3][3] * A[3][3];
+}
+void mul_m4_m4_pre(float R[4][4], const float A[4][4])
+{
+ BLI_assert(A != R);
+ float B[4][4];
+ copy_m4_m4(B, R);
+ mul_m4_m4m4_uniq(R, A, B);
}
-void mul_m3_m3m3(float m1[3][3], float m3_[3][3], float m2_[3][3])
+void mul_m4_m4_post(float R[4][4], const float B[4][4])
{
- float m2[3][3], m3[3][3];
+ BLI_assert(B != R);
+ float A[4][4];
+ copy_m4_m4(A, R);
+ mul_m4_m4m4_uniq(R, A, B);
+}
- /* copy so it works when m1 is the same pointer as m2 or m3 */
- copy_m3_m3(m2, m2_);
- copy_m3_m3(m3, m3_);
+void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
+{
+ if (A == R)
+ mul_m3_m3_post(R, B);
+ else if (B == R)
+ mul_m3_m3_pre(R, A);
+ else
+ mul_m3_m3m3_uniq(R, A, B);
+}
- /* m1[i][j] = m2[i][k] * m3[k][j], args are flipped! */
- m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0];
- m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1];
- m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2];
+void mul_m3_m3_pre(float R[3][3], const float A[3][3])
+{
+ BLI_assert(A != R);
+ float B[3][3];
+ copy_m3_m3(B, R);
+ mul_m3_m3m3_uniq(R, A, B);
+}
- m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0];
- m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1];
- m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2];
+void mul_m3_m3_post(float R[3][3], const float B[3][3])
+{
+ BLI_assert(B != R);
+ float A[3][3];
+ copy_m3_m3(A, R);
+ mul_m3_m3m3_uniq(R, A, B);
+}
- m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0];
- m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1];
- m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
+void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3])
+{
+ BLI_assert(R != A && R != B);
+
+ R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0];
+ R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1];
+ R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2];
+
+ R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0];
+ R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1];
+ R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2];
+
+ R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0];
+ R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1];
+ R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2];
}
-void mul_m4_m4m3(float m1[4][4], float m3_[4][4], float m2_[3][3])
+void mul_m4_m4m3(float m1[4][4], const float m3_[4][4], const float m2_[3][3])
{
float m2[3][3], m3[4][4];
/* copy so it works when m1 is the same pointer as m2 or m3 */
+ /* TODO: avoid copying when matrices are different */
copy_m3_m3(m2, m2_);
copy_m4_m4(m3, m3_);
@@ -250,11 +293,12 @@ void mul_m4_m4m3(float m1[4][4], float m3_[4][4], float m2_[3][3])
}
/* m1 = m2 * m3, ignore the elements on the 4th row/column of m3 */
-void mul_m3_m3m4(float m1[3][3], float m3_[4][4], float m2_[3][3])
+void mul_m3_m3m4(float m1[3][3], const float m3_[4][4], const float m2_[3][3])
{
float m2[3][3], m3[4][4];
/* copy so it works when m1 is the same pointer as m2 or m3 */
+ /* TODO: avoid copying when matrices are different */
copy_m3_m3(m2, m2_);
copy_m4_m4(m3, m3_);
@@ -272,11 +316,12 @@ void mul_m3_m3m4(float m1[3][3], float m3_[4][4], float m2_[3][3])
m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
}
-void mul_m4_m3m4(float m1[4][4], float m3_[3][3], float m2_[4][4])
+void mul_m4_m3m4(float m1[4][4], const float m3_[3][3], const float m2_[4][4])
{
float m2[4][4], m3[3][3];
/* copy so it works when m1 is the same pointer as m2 or m3 */
+ /* TODO: avoid copying when matrices are different */
copy_m4_m4(m2, m2_);
copy_m3_m3(m3, m3_);
@@ -296,20 +341,20 @@ void mul_m4_m3m4(float m1[4][4], float m3_[3][3], float m2_[4][4])
* \{ */
void _va_mul_m3_series_3(
float r[3][3],
- float m1[3][3], float m2[3][3])
+ const float m1[3][3], const float m2[3][3])
{
mul_m3_m3m3(r, m1, m2);
}
void _va_mul_m3_series_4(
float r[3][3],
- float m1[3][3], float m2[3][3], float m3[3][3])
+ const float m1[3][3], const float m2[3][3], const float m3[3][3])
{
mul_m3_m3m3(r, m1, m2);
mul_m3_m3m3(r, r, m3);
}
void _va_mul_m3_series_5(
float r[3][3],
- float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3])
+ const float m1[3][3], const float m2[3][3], const float m3[3][3], const float m4[3][3])
{
mul_m3_m3m3(r, m1, m2);
mul_m3_m3m3(r, r, m3);
@@ -317,8 +362,8 @@ void _va_mul_m3_series_5(
}
void _va_mul_m3_series_6(
float r[3][3],
- float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
- float m5[3][3])
+ const float m1[3][3], const float m2[3][3], const float m3[3][3], const float m4[3][3],
+ const float m5[3][3])
{
mul_m3_m3m3(r, m1, m2);
mul_m3_m3m3(r, r, m3);
@@ -327,8 +372,8 @@ void _va_mul_m3_series_6(
}
void _va_mul_m3_series_7(
float r[3][3],
- float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
- float m5[3][3], float m6[3][3])
+ const float m1[3][3], const float m2[3][3], const float m3[3][3], const float m4[3][3],
+ const float m5[3][3], const float m6[3][3])
{
mul_m3_m3m3(r, m1, m2);
mul_m3_m3m3(r, r, m3);
@@ -338,8 +383,8 @@ void _va_mul_m3_series_7(
}
void _va_mul_m3_series_8(
float r[3][3],
- float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
- float m5[3][3], float m6[3][3], float m7[3][3])
+ const float m1[3][3], const float m2[3][3], const float m3[3][3], const float m4[3][3],
+ const float m5[3][3], const float m6[3][3], const float m7[3][3])
{
mul_m3_m3m3(r, m1, m2);
mul_m3_m3m3(r, r, m3);
@@ -350,8 +395,8 @@ void _va_mul_m3_series_8(
}
void _va_mul_m3_series_9(
float r[3][3],
- float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
- float m5[3][3], float m6[3][3], float m7[3][3], float m8[3][3])
+ const float m1[3][3], const float m2[3][3], const float m3[3][3], const float m4[3][3],
+ const float m5[3][3], const float m6[3][3], const float m7[3][3], const float m8[3][3])
{
mul_m3_m3m3(r, m1, m2);
mul_m3_m3m3(r, r, m3);
@@ -367,20 +412,20 @@ void _va_mul_m3_series_9(
* \{ */
void _va_mul_m4_series_3(
float r[4][4],
- float m1[4][4], float m2[4][4])
+ const float m1[4][4], const float m2[4][4])
{
mul_m4_m4m4(r, m1, m2);
}
void _va_mul_m4_series_4(
float r[4][4],
- float m1[4][4], float m2[4][4], float m3[4][4])
+ const float m1[4][4], const float m2[4][4], const float m3[4][4])
{
mul_m4_m4m4(r, m1, m2);
mul_m4_m4m4(r, r, m3);
}
void _va_mul_m4_series_5(
float r[4][4],
- float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4])
+ const float m1[4][4], const float m2[4][4], const float m3[4][4], const float m4[4][4])
{
mul_m4_m4m4(r, m1, m2);
mul_m4_m4m4(r, r, m3);
@@ -388,8 +433,8 @@ void _va_mul_m4_series_5(
}
void _va_mul_m4_series_6(
float r[4][4],
- float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
- float m5[4][4])
+ const float m1[4][4], const float m2[4][4], const float m3[4][4], const float m4[4][4],
+ const float m5[4][4])
{
mul_m4_m4m4(r, m1, m2);
mul_m4_m4m4(r, r, m3);
@@ -398,8 +443,8 @@ void _va_mul_m4_series_6(
}
void _va_mul_m4_series_7(
float r[4][4],
- float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
- float m5[4][4], float m6[4][4])
+ const float m1[4][4], const float m2[4][4], const float m3[4][4], const float m4[4][4],
+ const float m5[4][4], const float m6[4][4])
{
mul_m4_m4m4(r, m1, m2);
mul_m4_m4m4(r, r, m3);
@@ -409,8 +454,8 @@ void _va_mul_m4_series_7(
}
void _va_mul_m4_series_8(
float r[4][4],
- float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
- float m5[4][4], float m6[4][4], float m7[4][4])
+ const float m1[4][4], const float m2[4][4], const float m3[4][4], const float m4[4][4],
+ const float m5[4][4], const float m6[4][4], const float m7[4][4])
{
mul_m4_m4m4(r, m1, m2);
mul_m4_m4m4(r, r, m3);
@@ -421,8 +466,8 @@ void _va_mul_m4_series_8(
}
void _va_mul_m4_series_9(
float r[4][4],
- float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
- float m5[4][4], float m6[4][4], float m7[4][4], float m8[4][4])
+ const float m1[4][4], const float m2[4][4], const float m3[4][4], const float m4[4][4],
+ const float m5[4][4], const float m6[4][4], const float m7[4][4], const float m8[4][4])
{
mul_m4_m4m4(r, m1, m2);
mul_m4_m4m4(r, r, m3);
@@ -434,7 +479,7 @@ void _va_mul_m4_series_9(
}
/** \} */
-void mul_v2_m3v2(float r[2], float m[3][3], float v[2])
+void mul_v2_m3v2(float r[2], const float m[3][3], const float v[2])
{
float temp[3], warped[3];
@@ -447,12 +492,12 @@ void mul_v2_m3v2(float r[2], float m[3][3], float v[2])
r[1] = warped[1] / warped[2];
}
-void mul_m3_v2(float m[3][3], float r[2])
+void mul_m3_v2(const float m[3][3], float r[2])
{
mul_v2_m3v2(r, m, r);
}
-void mul_m4_v3(float mat[4][4], float vec[3])
+void mul_m4_v3(const float mat[4][4], float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -462,7 +507,7 @@ void mul_m4_v3(float mat[4][4], float vec[3])
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
}
-void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
+void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -472,7 +517,7 @@ void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
}
-void mul_v2_m4v3(float r[2], float mat[4][4], const float vec[3])
+void mul_v2_m4v3(float r[2], const float mat[4][4], const float vec[3])
{
const float x = vec[0];
@@ -480,7 +525,7 @@ void mul_v2_m4v3(float r[2], float mat[4][4], const float vec[3])
r[1] = x * mat[0][1] + vec[1] * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
}
-void mul_v2_m2v2(float r[2], float mat[2][2], const float vec[2])
+void mul_v2_m2v2(float r[2], const float mat[2][2], const float vec[2])
{
const float x = vec[0];
@@ -488,13 +533,13 @@ void mul_v2_m2v2(float r[2], float mat[2][2], const float vec[2])
r[1] = mat[0][1] * x + mat[1][1] * vec[1];
}
-void mul_m2v2(float mat[2][2], float vec[2])
+void mul_m2v2(const float mat[2][2], float vec[2])
{
mul_v2_m2v2(vec, mat, vec);
}
/* same as mul_m4_v3() but doesnt apply translation component */
-void mul_mat3_m4_v3(float mat[4][4], float vec[3])
+void mul_mat3_m4_v3(const float mat[4][4], float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -504,7 +549,7 @@ void mul_mat3_m4_v3(float mat[4][4], float vec[3])
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
}
-void mul_v3_mat3_m4v3(float r[3], float mat[4][4], const float vec[3])
+void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -514,7 +559,7 @@ void mul_v3_mat3_m4v3(float r[3], float mat[4][4], const float vec[3])
r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
}
-void mul_project_m4_v3(float mat[4][4], float vec[3])
+void mul_project_m4_v3(const float mat[4][4], float vec[3])
{
/* absolute value to not flip the frustum upside down behind the camera */
const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
@@ -525,7 +570,7 @@ void mul_project_m4_v3(float mat[4][4], float vec[3])
vec[2] /= w;
}
-void mul_v3_project_m4_v3(float r[3], float mat[4][4], const float vec[3])
+void mul_v3_project_m4_v3(float r[3], const float mat[4][4], const float vec[3])
{
const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
mul_v3_m4v3(r, mat, vec);
@@ -535,7 +580,7 @@ void mul_v3_project_m4_v3(float r[3], float mat[4][4], const float vec[3])
r[2] /= w;
}
-void mul_v2_project_m4_v3(float r[2], float mat[4][4], const float vec[3])
+void mul_v2_project_m4_v3(float r[2], const float mat[4][4], const float vec[3])
{
const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
mul_v2_m4v3(r, mat, vec);
@@ -544,7 +589,7 @@ void mul_v2_project_m4_v3(float r[2], float mat[4][4], const float vec[3])
r[1] /= w;
}
-void mul_v4_m4v4(float r[4], float mat[4][4], const float v[4])
+void mul_v4_m4v4(float r[4], const float mat[4][4], const float v[4])
{
const float x = v[0];
const float y = v[1];
@@ -556,12 +601,12 @@ void mul_v4_m4v4(float r[4], float mat[4][4], const float v[4])
r[3] = x * mat[0][3] + y * mat[1][3] + z * mat[2][3] + mat[3][3] * v[3];
}
-void mul_m4_v4(float mat[4][4], float r[4])
+void mul_m4_v4(const float mat[4][4], float r[4])
{
mul_v4_m4v4(r, mat, r);
}
-void mul_v4d_m4v4d(double r[4], float mat[4][4], double v[4])
+void mul_v4d_m4v4d(double r[4], const float mat[4][4], const double v[4])
{
const double x = v[0];
const double y = v[1];
@@ -573,12 +618,21 @@ void mul_v4d_m4v4d(double r[4], float mat[4][4], double v[4])
r[3] = x * (double)mat[0][3] + y * (double)mat[1][3] + z * (double)mat[2][3] + (double)mat[3][3] * v[3];
}
-void mul_m4_v4d(float mat[4][4], double r[4])
+void mul_m4_v4d(const float mat[4][4], double r[4])
{
mul_v4d_m4v4d(r, mat, r);
}
-void mul_v3_m3v3(float r[3], float M[3][3], const float a[3])
+void mul_v4_m4v3(float r[4], const float M[4][4], const float v[3])
+{
+ /* v has implicit w = 1.0f */
+ r[0] = v[0] * M[0][0] + v[1] * M[1][0] + M[2][0] * v[2] + M[3][0];
+ r[1] = v[0] * M[0][1] + v[1] * M[1][1] + M[2][1] * v[2] + M[3][1];
+ r[2] = v[0] * M[0][2] + v[1] * M[1][2] + M[2][2] * v[2] + M[3][2];
+ r[3] = v[0] * M[0][3] + v[1] * M[1][3] + M[2][3] * v[2] + M[3][3];
+}
+
+void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
{
BLI_assert(r != a);
@@ -587,7 +641,7 @@ void mul_v3_m3v3(float r[3], float M[3][3], const float a[3])
r[2] = M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
}
-void mul_v3_m3v3_db(double r[3], double M[3][3], const double a[3])
+void mul_v3_m3v3_db(double r[3], const double M[3][3], const double a[3])
{
BLI_assert(r != a);
@@ -596,7 +650,7 @@ void mul_v3_m3v3_db(double r[3], double M[3][3], const double a[3])
r[2] = M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
}
-void mul_v2_m3v3(float r[2], float M[3][3], const float a[3])
+void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
{
BLI_assert(r != a);
@@ -604,17 +658,17 @@ void mul_v2_m3v3(float r[2], float M[3][3], const float a[3])
r[1] = M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
}
-void mul_m3_v3(float M[3][3], float r[3])
+void mul_m3_v3(const float M[3][3], float r[3])
{
mul_v3_m3v3(r, M, (const float[3]){UNPACK3(r)});
}
-void mul_m3_v3_db(double M[3][3], double r[3])
+void mul_m3_v3_db(const double M[3][3], double r[3])
{
mul_v3_m3v3_db(r, M, (const double[3]){UNPACK3(r)});
}
-void mul_transposed_m3_v3(float mat[3][3], float vec[3])
+void mul_transposed_m3_v3(const float mat[3][3], float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -624,7 +678,7 @@ void mul_transposed_m3_v3(float mat[3][3], float vec[3])
vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2];
}
-void mul_transposed_mat3_m4_v3(float mat[4][4], float vec[3])
+void mul_transposed_mat3_m4_v3(const float mat[4][4], float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -688,7 +742,7 @@ void negate_m4(float m[4][4])
m[i][j] *= -1.0f;
}
-void mul_m3_v3_double(float mat[3][3], double vec[3])
+void mul_m3_v3_double(const float mat[3][3], double vec[3])
{
const double x = vec[0];
const double y = vec[1];
@@ -698,7 +752,7 @@ void mul_m3_v3_double(float mat[3][3], double vec[3])
vec[2] = x * (double)mat[0][2] + y * (double)mat[1][2] + (double)mat[2][2] * vec[2];
}
-void add_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
+void add_m3_m3m3(float m1[3][3], const float m2[3][3], const float m3[3][3])
{
int i, j;
@@ -707,7 +761,7 @@ void add_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
m1[i][j] = m2[i][j] + m3[i][j];
}
-void add_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
+void add_m4_m4m4(float m1[4][4], const float m2[4][4], const float m3[4][4])
{
int i, j;
@@ -716,7 +770,7 @@ void add_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
m1[i][j] = m2[i][j] + m3[i][j];
}
-void sub_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
+void sub_m3_m3m3(float m1[3][3], const float m2[3][3], const float m3[3][3])
{
int i, j;
@@ -725,7 +779,7 @@ void sub_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
m1[i][j] = m2[i][j] - m3[i][j];
}
-void sub_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
+void sub_m4_m4m4(float m1[4][4], const float m2[4][4], const float m3[4][4])
{
int i, j;
@@ -734,7 +788,7 @@ void sub_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
m1[i][j] = m2[i][j] - m3[i][j];
}
-float determinant_m3_array(float m[3][3])
+float determinant_m3_array(const float m[3][3])
{
return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
@@ -750,7 +804,7 @@ bool invert_m3_ex(float m[3][3], const float epsilon)
return success;
}
-bool invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon)
+bool invert_m3_m3_ex(float m1[3][3], const float m2[3][3], const float epsilon)
{
float det;
int a, b;
@@ -786,7 +840,7 @@ bool invert_m3(float m[3][3])
return success;
}
-bool invert_m3_m3(float m1[3][3], float m2[3][3])
+bool invert_m3_m3(float m1[3][3], const float m2[3][3])
{
float det;
int a, b;
@@ -830,7 +884,7 @@ bool invert_m4(float m[4][4])
* Mark Segal - 1992
*/
-bool invert_m4_m4(float inverse[4][4], float mat[4][4])
+bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
{
int i, j, k;
double temp;
@@ -908,7 +962,7 @@ void transpose_m3(float mat[3][3])
mat[2][1] = t;
}
-void transpose_m3_m3(float rmat[3][3], float mat[3][3])
+void transpose_m3_m3(float rmat[3][3], const float mat[3][3])
{
BLI_assert(rmat != mat);
@@ -924,7 +978,7 @@ void transpose_m3_m3(float rmat[3][3], float mat[3][3])
}
/* seems obscure but in-fact a common operation */
-void transpose_m3_m4(float rmat[3][3], float mat[4][4])
+void transpose_m3_m4(float rmat[3][3], const float mat[4][4])
{
BLI_assert(&rmat[0][0] != &mat[0][0]);
@@ -965,7 +1019,7 @@ void transpose_m4(float mat[4][4])
mat[3][2] = t;
}
-void transpose_m4_m4(float rmat[4][4], float mat[4][4])
+void transpose_m4_m4(float rmat[4][4], const float mat[4][4])
{
BLI_assert(rmat != mat);
@@ -987,7 +1041,8 @@ void transpose_m4_m4(float rmat[4][4], float mat[4][4])
rmat[3][3] = mat[3][3];
}
-int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit)
+/* TODO: return bool */
+int compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit)
{
if (compare_v4v4(mat1[0], mat2[0], limit))
if (compare_v4v4(mat1[1], mat2[1], limit))
@@ -1165,7 +1220,7 @@ void orthogonalize_m4(float mat[4][4], int axis)
mul_v3_fl(mat[2], size[2]);
}
-bool is_orthogonal_m3(float m[3][3])
+bool is_orthogonal_m3(const float m[3][3])
{
int i, j;
@@ -1179,7 +1234,7 @@ bool is_orthogonal_m3(float m[3][3])
return true;
}
-bool is_orthogonal_m4(float m[4][4])
+bool is_orthogonal_m4(const float m[4][4])
{
int i, j;
@@ -1194,7 +1249,7 @@ bool is_orthogonal_m4(float m[4][4])
return true;
}
-bool is_orthonormal_m3(float m[3][3])
+bool is_orthonormal_m3(const float m[3][3])
{
if (is_orthogonal_m3(m)) {
int i;
@@ -1209,7 +1264,7 @@ bool is_orthonormal_m3(float m[3][3])
return false;
}
-bool is_orthonormal_m4(float m[4][4])
+bool is_orthonormal_m4(const float m[4][4])
{
if (is_orthogonal_m4(m)) {
int i;
@@ -1224,7 +1279,7 @@ bool is_orthonormal_m4(float m[4][4])
return false;
}
-bool is_uniform_scaled_m3(float m[3][3])
+bool is_uniform_scaled_m3(const float m[3][3])
{
const float eps = 1e-7f;
float t[3][3];
@@ -1252,7 +1307,7 @@ bool is_uniform_scaled_m3(float m[3][3])
return false;
}
-bool is_uniform_scaled_m4(float m[4][4])
+bool is_uniform_scaled_m4(const float m[4][4])
{
float t[3][3];
copy_m3_m4(t, m);
@@ -1274,14 +1329,14 @@ void normalize_m3(float mat[3][3])
}
}
-void normalize_m3_m3_ex(float rmat[3][3], float mat[3][3], float r_scale[3])
+void normalize_m3_m3_ex(float rmat[3][3], const float mat[3][3], float r_scale[3])
{
int i;
for (i = 0; i < 3; i++) {
r_scale[i] = normalize_v3_v3(rmat[i], mat[i]);
}
}
-void normalize_m3_m3(float rmat[3][3], float mat[3][3])
+void normalize_m3_m3(float rmat[3][3], const float mat[3][3])
{
int i;
for (i = 0; i < 3; i++) {
@@ -1310,7 +1365,7 @@ void normalize_m4(float mat[4][4])
}
}
-void normalize_m4_m4_ex(float rmat[4][4], float mat[4][4], float r_scale[3])
+void normalize_m4_m4_ex(float rmat[4][4], const float mat[4][4], float r_scale[3])
{
int i;
for (i = 0; i < 3; i++) {
@@ -1319,7 +1374,7 @@ void normalize_m4_m4_ex(float rmat[4][4], float mat[4][4], float r_scale[3])
}
copy_v4_v4(rmat[3], mat[3]);
}
-void normalize_m4_m4(float rmat[4][4], float mat[4][4])
+void normalize_m4_m4(float rmat[4][4], const float mat[4][4])
{
int i;
for (i = 0; i < 3; i++) {
@@ -1329,7 +1384,7 @@ void normalize_m4_m4(float rmat[4][4], float mat[4][4])
copy_v4_v4(rmat[3], mat[3]);
}
-void adjoint_m2_m2(float m1[2][2], float m[2][2])
+void adjoint_m2_m2(float m1[2][2], const float m[2][2])
{
BLI_assert(m1 != m);
m1[0][0] = m[1][1];
@@ -1338,7 +1393,7 @@ void adjoint_m2_m2(float m1[2][2], float m[2][2])
m1[1][1] = m[0][0];
}
-void adjoint_m3_m3(float m1[3][3], float m[3][3])
+void adjoint_m3_m3(float m1[3][3], const float m[3][3])
{
BLI_assert(m1 != m);
m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
@@ -1354,7 +1409,7 @@ void adjoint_m3_m3(float m1[3][3], float m[3][3])
m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
}
-void adjoint_m4_m4(float out[4][4], float in[4][4]) /* out = ADJ(in) */
+void adjoint_m4_m4(float out[4][4], const float in[4][4]) /* out = ADJ(in) */
{
float a1, a2, a3, a4, b1, b2, b3, b4;
float c1, c2, c3, c4, d1, d2, d3, d4;
@@ -1420,7 +1475,7 @@ float determinant_m3(float a1, float a2, float a3,
return ans;
}
-float determinant_m4(float m[4][4])
+float determinant_m4(const float m[4][4])
{
float ans;
float a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
@@ -1488,14 +1543,14 @@ void size_to_mat4(float mat[4][4], const float size[3])
mat[3][3] = 1.0f;
}
-void mat3_to_size(float size[3], float mat[3][3])
+void mat3_to_size(float size[3], const float mat[3][3])
{
size[0] = len_v3(mat[0]);
size[1] = len_v3(mat[1]);
size[2] = len_v3(mat[2]);
}
-void mat4_to_size(float size[3], float mat[4][4])
+void mat4_to_size(float size[3], const float mat[4][4])
{
size[0] = len_v3(mat[0]);
size[1] = len_v3(mat[1]);
@@ -1505,7 +1560,7 @@ void mat4_to_size(float size[3], float mat[4][4])
/* this gets the average scale of a matrix, only use when your scaling
* data that has no idea of scale axis, examples are bone-envelope-radius
* and curve radius */
-float mat3_to_scale(float mat[3][3])
+float mat3_to_scale(const float mat[3][3])
{
/* unit length vector */
float unit_vec[3];
@@ -1514,7 +1569,7 @@ float mat3_to_scale(float mat[3][3])
return len_v3(unit_vec);
}
-float mat4_to_scale(float mat[4][4])
+float mat4_to_scale(const float mat[4][4])
{
/* unit length vector */
float unit_vec[3];
@@ -1524,7 +1579,7 @@ float mat4_to_scale(float mat[4][4])
}
/** Return 2D scale (in XY plane) of given mat4. */
-float mat4_to_xy_scale(float M[4][4])
+float mat4_to_xy_scale(const float M[4][4])
{
/* unit length vector in xy plane */
float unit_vec[3] = {(float)M_SQRT1_2, (float)M_SQRT1_2, 0.0f};
@@ -1532,7 +1587,7 @@ float mat4_to_xy_scale(float M[4][4])
return len_v3(unit_vec);
}
-void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3])
+void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3])
{
/* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */
size[0] = normalize_v3_v3(rot[0], mat3[0]);
@@ -1544,7 +1599,7 @@ void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3])
}
}
-void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4])
+void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4])
{
float mat3[3][3]; /* wmat -> 3x3 */
@@ -1555,7 +1610,7 @@ void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wm
copy_v3_v3(loc, wmat[3]);
}
-void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4])
+void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4])
{
float mat3[3][3];
float mat3_n[3][3]; /* normalized mat3 */
@@ -1573,7 +1628,7 @@ void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4])
copy_v3_v3(loc, wmat[3]);
}
-void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4])
+void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat[4][4])
{
float rot[3][3];
mat4_to_loc_rot_size(loc, rot, size, wmat);
@@ -1590,7 +1645,7 @@ void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]
* See https://en.wikipedia.org/wiki/Polar_decomposition for more.
*/
#ifndef MATH_STANDALONE
-void mat3_polar_decompose(float mat3[3][3], float r_U[3][3], float r_P[3][3])
+void mat3_polar_decompose(const float mat3[3][3], float r_U[3][3], float r_P[3][3])
{
/* From svd decomposition (M = WSV*), we have:
* U = WV*
@@ -1701,7 +1756,7 @@ void transform_pivot_set_m4(float mat[4][4], const float pivot[3])
mul_m4_m4m4(mat, mat, tmat);
}
-void blend_m3_m3m3(float out[3][3], float dst[3][3], float src[3][3], const float srcweight)
+void blend_m3_m3m3(float out[3][3], const float dst[3][3], const float src[3][3], const float srcweight)
{
float srot[3][3], drot[3][3];
float squat[4], dquat[4], fquat[4];
@@ -1724,7 +1779,7 @@ void blend_m3_m3m3(float out[3][3], float dst[3][3], float src[3][3], const floa
mul_m3_m3m3(out, rmat, smat);
}
-void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const float srcweight)
+void blend_m4_m4m4(float out[4][4], const float dst[4][4], const float src[4][4], const float srcweight)
{
float sloc[3], dloc[3], floc[3];
float srot[3][3], drot[3][3];
@@ -1762,7 +1817,7 @@ void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const floa
* \param B: Input matrix which is totally effective with `t = 1.0`.
* \param t: Interpolation factor.
*/
-void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t)
+void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], const float t)
{
/* 'Rotation' component ('U' part of polar decomposition, the closest orthogonal matrix to M3 rot/scale
* transformation matrix), spherically interpolated. */
@@ -1797,7 +1852,7 @@ void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t)
* \param B: Input matrix which is totally effective with `t = 1.0`.
* \param t: Interpolation factor.
*/
-void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t)
+void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], const float t)
{
float A3[3][3], B3[3][3], R3[3][3];
@@ -1818,27 +1873,27 @@ void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t)
}
#endif /* MATH_STANDALONE */
-bool is_negative_m3(float mat[3][3])
+bool is_negative_m3(const float mat[3][3])
{
float vec[3];
cross_v3_v3v3(vec, mat[0], mat[1]);
return (dot_v3v3(vec, mat[2]) < 0.0f);
}
-bool is_negative_m4(float mat[4][4])
+bool is_negative_m4(const float mat[4][4])
{
float vec[3];
cross_v3_v3v3(vec, mat[0], mat[1]);
return (dot_v3v3(vec, mat[2]) < 0.0f);
}
-bool is_zero_m3(float mat[3][3])
+bool is_zero_m3(const float mat[3][3])
{
return (is_zero_v3(mat[0]) &&
is_zero_v3(mat[1]) &&
is_zero_v3(mat[2]));
}
-bool is_zero_m4(float mat[4][4])
+bool is_zero_m4(const float mat[4][4])
{
return (is_zero_v4(mat[0]) &&
is_zero_v4(mat[1]) &&
@@ -1846,14 +1901,14 @@ bool is_zero_m4(float mat[4][4])
is_zero_v4(mat[3]));
}
-bool equals_m3m3(float mat1[3][3], float mat2[3][3])
+bool equals_m3m3(const float mat1[3][3], const float mat2[3][3])
{
return (equals_v3v3(mat1[0], mat2[0]) &&
equals_v3v3(mat1[1], mat2[1]) &&
equals_v3v3(mat1[2], mat2[2]));
}
-bool equals_m4m4(float mat1[4][4], float mat2[4][4])
+bool equals_m4m4(const float mat1[4][4], const float mat2[4][4])
{
return (equals_v4v4(mat1[0], mat2[0]) &&
equals_v4v4(mat1[1], mat2[1]) &&
@@ -1944,7 +1999,7 @@ void loc_axisangle_size_to_mat4(float mat[4][4], const float loc[3], const float
/*********************************** Other ***********************************/
-void print_m3(const char *str, float m[3][3])
+void print_m3(const char *str, const float m[3][3])
{
printf("%s\n", str);
printf("%f %f %f\n", m[0][0], m[1][0], m[2][0]);
@@ -1953,7 +2008,7 @@ void print_m3(const char *str, float m[3][3])
printf("\n");
}
-void print_m4(const char *str, float m[4][4])
+void print_m4(const char *str, const float m[4][4])
{
printf("%s\n", str);
printf("%f %f %f %f\n", m[0][0], m[1][0], m[2][0], m[3][0]);
@@ -2407,7 +2462,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4])
}
}
-void pseudoinverse_m4_m4(float Ainv[4][4], float A_[4][4], float epsilon)
+void pseudoinverse_m4_m4(float Ainv[4][4], const float A_[4][4], float epsilon)
{
/* compute Moore-Penrose pseudo inverse of matrix, singular values
* below epsilon are ignored for stability (truncated SVD) */
@@ -2428,7 +2483,7 @@ void pseudoinverse_m4_m4(float Ainv[4][4], float A_[4][4], float epsilon)
mul_m4_series(Ainv, U, Wm, V);
}
-void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon)
+void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon)
{
/* try regular inverse when possible, otherwise fall back to slow svd */
if (!invert_m3_m3(Ainv, A)) {
@@ -2440,14 +2495,14 @@ void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon)
}
}
-bool has_zero_axis_m4(float matrix[4][4])
+bool has_zero_axis_m4(const float matrix[4][4])
{
return len_squared_v3(matrix[0]) < FLT_EPSILON ||
len_squared_v3(matrix[1]) < FLT_EPSILON ||
len_squared_v3(matrix[2]) < FLT_EPSILON;
}
-void invert_m4_m4_safe(float Ainv[4][4], float A[4][4])
+void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4])
{
if (!invert_m4_m4(Ainv, A)) {
float Atemp[4][4];
@@ -2495,7 +2550,7 @@ void invert_m4_m4_safe(float Ainv[4][4], float A[4][4])
* this defines a transform matrix TM such that (x', y', z') = TM * (x, y, z)
* where (x', y', z') are the coordinates of P' in target space such that it keeps (X, Y, Z) coordinates in global space.
*/
-void BLI_space_transform_from_matrices(SpaceTransform *data, float local[4][4], float target[4][4])
+void BLI_space_transform_from_matrices(SpaceTransform *data, const float local[4][4], const float target[4][4])
{
float itarget[4][4];
invert_m4_m4(itarget, target);
@@ -2513,7 +2568,7 @@ void BLI_space_transform_from_matrices(SpaceTransform *data, float local[4][4],
* this defines a transform matrix TM such that (X', Y', Z') = TM * (X, Y, Z)
* where (X', Y', Z') are the coordinates of p' in global space such that it keeps (x, y, z) coordinates in target space.
*/
-void BLI_space_transform_global_from_matrices(SpaceTransform *data, float local[4][4], float target[4][4])
+void BLI_space_transform_global_from_matrices(SpaceTransform *data, const float local[4][4], const float target[4][4])
{
float ilocal[4][4];
invert_m4_m4(ilocal, local);
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 08687a1ab47..4f658ef015f 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -491,7 +491,7 @@ MINLINE void mul_v2_v2_ccw(float r[2], const float mat[2], const float vec[2])
* return co_4d[3];
* \endcode
*/
-MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3])
+MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3])
{
return (mat[0][3] * co[0]) +
(mat[1][3] * co[1]) +
diff --git a/source/blender/blenlib/intern/scanfill_utils.c b/source/blender/blenlib/intern/scanfill_utils.c
index 3b6ab99ae86..ef1df479f13 100644
--- a/source/blender/blenlib/intern/scanfill_utils.c
+++ b/source/blender/blenlib/intern/scanfill_utils.c
@@ -95,20 +95,6 @@ void BLI_scanfill_obj_dump(ScanFillContext *sf_ctx)
}
#endif
-#if 0
-void BLI_scanfill_view3d_dump(ScanFillContext *sf_ctx)
-{
- ScanFillEdge *eed;
-
- bl_debug_draw_quad_clear();
- bl_debug_color_set(0x0000ff);
-
- for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
- bl_debug_draw_edge_add(eed->v1->co, eed->v2->co);
- }
-}
-#endif
-
static ListBase *edge_isect_ls_ensure(GHash *isect_hash, ScanFillEdge *eed)
{
ListBase *e_ls;
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 4fd2e227bc5..0da15fe5bbc 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -39,15 +39,18 @@ extern "C" {
struct BlendThumbnail;
struct bScreen;
struct LinkNode;
+struct ListBase;
struct Main;
struct MemFile;
struct ReportList;
struct Scene;
+struct ViewLayer;
struct UserDef;
struct View3D;
struct bContext;
struct BHead;
struct FileData;
+struct wmWindowManager;
typedef struct BlendHandle BlendHandle;
@@ -64,13 +67,20 @@ typedef struct BlendFileData {
int fileflags;
int globalf;
char filename[1024]; /* 1024 = FILE_MAX */
-
- struct bScreen *curscreen;
+
+ struct bScreen *curscreen; /* TODO think this isn't needed anymore? */
struct Scene *curscene;
-
+ struct ViewLayer *cur_view_layer; /* layer to activate in workspaces when reading without UI */
+
eBlenFileType type;
} BlendFileData;
+typedef struct WorkspaceConfigFileData {
+ struct Main *main; /* has to be freed when done reading file data */
+
+ struct ListBase workspaces;
+} WorkspaceConfigFileData;
+
/* skip reading some data-block types (may want to skip screen data too). */
typedef enum eBLOReadSkip {
@@ -124,8 +134,9 @@ struct ID *BLO_library_link_named_part(struct Main *mainl, BlendHandle **bh, con
struct ID *BLO_library_link_named_part_ex(
struct Main *mainl, BlendHandle **bh,
const short idcode, const char *name, const int flag,
- struct Scene *scene, struct View3D *v3d);
-void BLO_library_link_end(struct Main *mainl, BlendHandle **bh, short flag, struct Scene *scene, struct View3D *v3d);
+ struct Scene *scene, struct ViewLayer *view_layer);
+void BLO_library_link_end(
+ struct Main *mainl, BlendHandle **bh, int flag, struct Scene *scene, struct ViewLayer *view_layer);
void BLO_library_link_copypaste(struct Main *mainl, BlendHandle *bh);
@@ -134,7 +145,9 @@ void *BLO_library_read_struct(struct FileData *fd, struct BHead *bh, const char
BlendFileData *blo_read_blendafterruntime(int file, const char *name, int actualsize, struct ReportList *reports);
/* internal function but we need to expose it */
-void blo_lib_link_screen_restore(struct Main *newmain, struct bScreen *curscreen, struct Scene *curscene);
+void blo_lib_link_restore(
+ struct Main *newmain, struct wmWindowManager *curwm,
+ struct Scene *curscene, struct ViewLayer *cur_render_layer);
typedef void (*BLOExpandDoitCallback) (void *fdhandle, struct Main *mainvar, void *idv);
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 3d2e8a306de..61d1aa18b3c 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -29,6 +29,7 @@ set(INC
../blenkernel
../blenlib
../blentranslation
+ ../depsgraph
../imbuf
../makesdna
../makesrna
@@ -53,6 +54,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
@@ -79,6 +81,10 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_CLAY_ENGINE)
+ add_definitions(-DWITH_CLAY_ENGINE)
+endif()
+
if(WITH_CODEC_FFMPEG)
add_definitions(-DWITH_FFMPEG)
endif()
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index caf58ba3f86..6df5a505788 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -53,6 +53,10 @@
/* allow readfile to use deprecated functionality */
#define DNA_DEPRECATED_ALLOW
+/* Allow using DNA struct members that are marked as private for read/write.
+ * Note: Each header that uses this needs to define its own way of handling
+ * it. There's no generic implementation, direct use does nothing. */
+#define DNA_PRIVATE_READ_WRITE_ALLOW
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -72,6 +76,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"
@@ -84,6 +89,7 @@
#include "DNA_object_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_property_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_text_types.h"
@@ -98,10 +104,13 @@
#include "DNA_sound_types.h"
#include "DNA_space_types.h"
#include "DNA_vfont_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_world_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
+#include "RNA_access.h"
+
#include "MEM_guardedalloc.h"
#include "BLI_endian_switch.h"
@@ -120,13 +129,14 @@
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_global.h" // for G
#include "BKE_group.h"
+#include "BKE_layer.h"
#include "BKE_library.h" // for which_libbase
#include "BKE_library_idmap.h"
+#include "BKE_library_override.h"
#include "BKE_library_query.h"
#include "BKE_idcode.h"
#include "BKE_idprop.h"
@@ -148,6 +158,9 @@
#include "BKE_outliner_treehash.h"
#include "BKE_sound.h"
#include "BKE_colortools.h"
+#include "BKE_workspace.h"
+
+#include "DEG_depsgraph.h"
#include "NOD_common.h"
#include "NOD_socket.h"
@@ -238,9 +251,11 @@ typedef struct OldNewMap {
/* local prototypes */
static void *read_struct(FileData *fd, BHead *bh, const char *blockname);
static void direct_link_modifiers(FileData *fd, ListBase *lb);
-static void convert_tface_mt(FileData *fd, Main *main);
static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name);
static BHead *find_bhead_from_idname(FileData *fd, const char *idname);
+static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc);
+static SceneCollection *get_scene_collection_active_or_create(
+ struct Scene *scene, struct ViewLayer *view_layer, const int flag);
/* this function ensures that reports are printed,
* in the case of libraray linking errors this is important!
@@ -2202,6 +2217,42 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p
/* ************ READ ID *************** */
+static void lib_link_id(FileData *fd, Main *main)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ int base_count, i;
+
+ base_count = set_listbasepointers(main, lbarray);
+
+ for (i = 0; i < base_count; i++) {
+ ListBase *lb = lbarray[i];
+ ID *id;
+
+ for (id = lb->first; id; id = id->next) {
+ if (id->override_static) {
+ id->override_static->reference = newlibadr_us(fd, id->lib, id->override_static->reference);
+ id->override_static->storage = newlibadr_us(fd, id->lib, id->override_static->storage);
+ }
+ }
+ }
+}
+
+static void direct_link_id_override_property_operation_cb(FileData *fd, void *data)
+{
+ IDOverrideStaticPropertyOperation *opop = data;
+
+ opop->subitem_reference_name = newdataadr(fd, opop->subitem_reference_name);
+ opop->subitem_local_name = newdataadr(fd, opop->subitem_local_name);
+}
+
+static void direct_link_id_override_property_cb(FileData *fd, void *data)
+{
+ IDOverrideStaticProperty *op = data;
+
+ op->rna_path = newdataadr(fd, op->rna_path);
+ link_list_ex(fd, &op->operations, direct_link_id_override_property_operation_cb);
+}
+
static void direct_link_id(FileData *fd, ID *id)
{
/*link direct data of ID properties*/
@@ -2210,6 +2261,13 @@ static void direct_link_id(FileData *fd, ID *id)
/* this case means the data was written incorrectly, it should not happen */
IDP_DirectLinkGroup_OrFree(&id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
+ id->py_instance = NULL;
+
+ /* Link direct data of overrides. */
+ if (id->override_static) {
+ id->override_static = newdataadr(fd, id->override_static);
+ link_list_ex(fd, &id->override_static->properties, direct_link_id_override_property_cb);
+ }
}
/* ************ READ CurveMapping *************** */
@@ -2773,6 +2831,89 @@ static void direct_link_cachefile(FileData *fd, CacheFile *cache_file)
direct_link_animdata(fd, cache_file->adt);
}
+/* ************ READ WORKSPACES *************** */
+
+static void lib_link_workspaces(FileData *fd, Main *bmain)
+{
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ ListBase *layouts = BKE_workspace_layouts_get(workspace);
+ ID *id = (ID *)workspace;
+
+ if ((id->tag & LIB_TAG_NEED_LINK) == 0) {
+ continue;
+ }
+ IDP_LibLinkProperty(id->properties, fd);
+ id_us_ensure_real(id);
+
+ for (WorkSpaceDataRelation *relation = workspace->scene_viewlayer_relations.first;
+ relation != NULL;
+ relation = relation->next)
+ {
+ relation->parent = newlibadr(fd, id->lib, relation->parent);
+ /* relation->value is set in direct_link_workspace_link_scene_data */
+ }
+
+ for (WorkSpaceLayout *layout = layouts->first, *layout_next; layout; layout = layout_next) {
+ bScreen *screen = newlibadr(fd, id->lib, BKE_workspace_layout_screen_get(layout));
+
+ layout_next = layout->next;
+ if (screen) {
+ BKE_workspace_layout_screen_set(layout, screen);
+
+ if (ID_IS_LINKED(id)) {
+ screen->winid = 0;
+ if (screen->temp) {
+ /* delete temp layouts when appending */
+ BKE_workspace_layout_remove(bmain, workspace, layout);
+ }
+ }
+ }
+ }
+
+ id->tag &= ~LIB_TAG_NEED_LINK;
+ }
+}
+
+static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main *main)
+{
+ link_list(fd, BKE_workspace_layouts_get(workspace));
+ link_list(fd, &workspace->hook_layout_relations);
+ link_list(fd, &workspace->scene_viewlayer_relations);
+ link_list(fd, BKE_workspace_transform_orientations_get(workspace));
+
+ for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first;
+ relation;
+ relation = relation->next)
+ {
+ relation->parent = newglobadr(fd, relation->parent); /* data from window - need to access through global oldnew-map */
+ relation->value = newdataadr(fd, relation->value);
+ }
+
+ if (ID_IS_LINKED(&workspace->id)) {
+ /* Appending workspace so render layer is likely from a different scene. Unset
+ * now, when activating workspace later we set a valid one from current scene. */
+ BKE_workspace_relations_free(&workspace->scene_viewlayer_relations);
+ }
+
+ /* Same issue/fix as in direct_link_workspace_link_scene_data: Can't read workspace data
+ * when reading windows, so have to update windows after/when reading workspaces. */
+ for (wmWindowManager *wm = main->wm.first; wm; wm = wm->id.next) {
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ WorkSpaceLayout *act_layout = newdataadr(fd, BKE_workspace_active_layout_get(win->workspace_hook));
+ if (act_layout) {
+ BKE_workspace_active_layout_set(win->workspace_hook, act_layout);
+ }
+ }
+ }
+}
+
+static void lib_link_workspace_instance_hook(FileData *fd, WorkSpaceInstanceHook *hook, ID *id)
+{
+ WorkSpace *workspace = BKE_workspace_active_get(hook);
+ BKE_workspace_active_set(hook, newlibadr(fd, id->lib, workspace));
+}
+
+
/* ************ READ MOTION PATHS *************** */
/* direct data for cache */
@@ -3340,7 +3481,7 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose)
if (rebuild) {
- DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
BKE_pose_tag_recalc(bmain, pose);
}
}
@@ -3418,6 +3559,11 @@ static void lib_link_camera(FileData *fd, Main *main)
ca->dof_ob = newlibadr(fd, ca->id.lib, ca->dof_ob);
+ for (CameraBGImage *bgpic = ca->bg_images.first; bgpic; bgpic = bgpic->next) {
+ bgpic->ima = newlibadr_us(fd, ca->id.lib, bgpic->ima);
+ bgpic->clip = newlibadr_us(fd, ca->id.lib, bgpic->clip);
+ }
+
ca->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -3427,6 +3573,12 @@ static void direct_link_camera(FileData *fd, Camera *ca)
{
ca->adt = newdataadr(fd, ca->adt);
direct_link_animdata(fd, ca->adt);
+
+ link_list(fd, &ca->bg_images);
+
+ for (CameraBGImage *bgpic = ca->bg_images.first; bgpic; bgpic = bgpic->next) {
+ bgpic->iuser.ok = 1;
+ }
}
@@ -3594,6 +3746,7 @@ static void direct_link_mball(FileData *fd, MetaBall *mb)
mb->editelems = NULL;
/* mb->edit_elems.first= mb->edit_elems.last= NULL;*/
mb->lastelem = NULL;
+ mb->batch_cache = NULL;
}
/* ************ READ WORLD ***************** */
@@ -3863,6 +4016,7 @@ static void direct_link_curve(FileData *fd, Curve *cu)
cu->editnurb = NULL;
cu->editfont = NULL;
+ cu->batch_cache = NULL;
for (nu = cu->nurb.first; nu; nu = nu->next) {
nu->bezt = newdataadr(fd, nu->bezt);
@@ -4369,55 +4523,14 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
psys->tree = NULL;
psys->bvhtree = NULL;
+
+ psys->batch_cache = NULL;
}
return;
}
/* ************ READ MESH ***************** */
-static void lib_link_mtface(FileData *fd, Mesh *me, MTFace *mtface, int totface)
-{
- MTFace *tf= mtface;
- int i;
-
- /* Add pseudo-references (not fake users!) to images used by texface. A
- * little bogus; it would be better if each mesh consistently added one ref
- * to each image it used. - z0r */
- for (i = 0; i < totface; i++, tf++) {
- tf->tpage = newlibadr_real_us(fd, me->id.lib, tf->tpage);
- }
-}
-
-static void lib_link_customdata_mtface(FileData *fd, Mesh *me, CustomData *fdata, int totface)
-{
- int i;
- for (i = 0; i < fdata->totlayer; i++) {
- CustomDataLayer *layer = &fdata->layers[i];
-
- if (layer->type == CD_MTFACE)
- lib_link_mtface(fd, me, layer->data, totface);
- }
-
-}
-
-static void lib_link_customdata_mtpoly(FileData *fd, Mesh *me, CustomData *pdata, int totface)
-{
- int i;
-
- for (i=0; i < pdata->totlayer; i++) {
- CustomDataLayer *layer = &pdata->layers[i];
-
- if (layer->type == CD_MTEXPOLY) {
- MTexPoly *tf= layer->data;
- int j;
-
- for (j = 0; j < totface; j++, tf++) {
- tf->tpage = newlibadr_real_us(fd, me->id.lib, tf->tpage);
- }
- }
- }
-}
-
static void lib_link_mesh(FileData *fd, Main *main)
{
Mesh *me;
@@ -4444,19 +4557,9 @@ static void lib_link_mesh(FileData *fd, Main *main)
me->ipo = newlibadr_us(fd, me->id.lib, me->ipo); // XXX: deprecated: old anim sys
me->key = newlibadr_us(fd, me->id.lib, me->key);
me->texcomesh = newlibadr_us(fd, me->id.lib, me->texcomesh);
-
- lib_link_customdata_mtface(fd, me, &me->fdata, me->totface);
- lib_link_customdata_mtpoly(fd, me, &me->pdata, me->totpoly);
- if (me->mr && me->mr->levels.first) {
- lib_link_customdata_mtface(fd, me, &me->mr->fdata,
- ((MultiresLevel*)me->mr->levels.first)->totface);
- }
}
}
- /* convert texface options to material */
- convert_tface_mt(fd, main);
-
for (me = main->mesh.first; me; me = me->id.next) {
if (me->id.tag & LIB_TAG_NEED_LINK) {
/*check if we need to convert mfaces to mpolys*/
@@ -4612,7 +4715,6 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
mesh->dvert = newdataadr(fd, mesh->dvert);
mesh->mloopcol = newdataadr(fd, mesh->mloopcol);
mesh->mloopuv = newdataadr(fd, mesh->mloopuv);
- mesh->mtpoly = newdataadr(fd, mesh->mtpoly);
mesh->mselect = newdataadr(fd, mesh->mselect);
/* animdata */
@@ -4631,18 +4733,13 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
mesh->bb = NULL;
mesh->edit_btmesh = NULL;
+ mesh->batch_cache = NULL;
/* happens with old files */
if (mesh->mselect == NULL) {
mesh->totselect = 0;
}
- if (mesh->mloopuv || mesh->mtpoly) {
- /* for now we have to ensure texpoly and mloopuv layers are aligned
- * in the future we may allow non-aligned layers */
- BKE_mesh_cd_validate(mesh);
- }
-
/* Multires data */
mesh->mr= newdataadr(fd, mesh->mr);
if (mesh->mr) {
@@ -4722,6 +4819,7 @@ static void direct_link_latt(FileData *fd, Lattice *lt)
direct_link_dverts(fd, lt->pntsu*lt->pntsv*lt->pntsw, lt->dvert);
lt->editlatt = NULL;
+ lt->batch_cache = NULL;
lt->adt = newdataadr(fd, lt->adt);
direct_link_animdata(fd, lt->adt);
@@ -4764,7 +4862,15 @@ static void lib_link_object(FileData *fd, Main *main)
ob->parent = newlibadr(fd, ob->id.lib, ob->parent);
ob->track = newlibadr(fd, ob->id.lib, ob->track);
ob->poselib = newlibadr_us(fd, ob->id.lib, ob->poselib);
- ob->dup_group = newlibadr_us(fd, ob->id.lib, ob->dup_group);
+
+ /* 2.8x drops support for non-empty dupli instances. */
+ if (ob->type == OB_EMPTY) {
+ ob->dup_group = newlibadr_us(fd, ob->id.lib, ob->dup_group);
+ }
+ else {
+ ob->dup_group = NULL;
+ ob->transflag &= ~OB_DUPLIGROUP;
+ }
ob->proxy = newlibadr_us(fd, ob->id.lib, ob->proxy);
if (ob->proxy) {
@@ -5070,6 +5176,8 @@ static void direct_link_pose(FileData *fd, bPose *pose)
/* in case this value changes in future, clamp else we get undefined behavior */
CLAMP(pchan->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
+
+ pchan->draw_data = NULL;
}
pose->ikdata = NULL;
if (pose->ikparam != NULL) {
@@ -5412,11 +5520,6 @@ static void direct_link_object(FileData *fd, Object *ob)
/* weak weak... this was only meant as draw flag, now is used in give_base_to_objects too */
ob->flag &= ~OB_FROMGROUP;
- /* This is a transient flag; clear in order to avoid unneeded object update pending from
- * time when file was saved.
- */
- ob->recalc = 0;
-
/* XXX This should not be needed - but seems like it can happen in some cases, so for now play safe... */
ob->proxy_from = NULL;
@@ -5444,6 +5547,7 @@ static void direct_link_object(FileData *fd, Object *ob)
direct_link_motionpath(fd, ob->mpath);
link_list(fd, &ob->defbase);
+ link_list(fd, &ob->fmaps);
// XXX deprecated - old animation system <<<
direct_link_nlastrips(fd, &ob->nlastrips);
link_list(fd, &ob->constraintChannels);
@@ -5630,6 +5734,7 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->derivedDeform = NULL;
ob->derivedFinal = NULL;
BLI_listbase_clear(&ob->gpulamp);
+ BLI_listbase_clear(&ob->drawdata);
link_list(fd, &ob->pc_ids);
/* Runtime curve data */
@@ -5646,6 +5751,8 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->currentlod = ob->lodlevels.first;
ob->preview = direct_link_preview_image(fd, ob->preview);
+
+ ob->base_collection_properties = NULL;
}
/* ************ READ SCENE ***************** */
@@ -5710,6 +5817,45 @@ 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_view_layer(FileData *fd, Library *lib, ViewLayer *view_layer)
+{
+ /* tag scene layer to update for collection tree evaluation */
+ view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY;
+
+ for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) {
+ fmc->script = newlibadr(fd, lib, fmc->script);
+ }
+
+ for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) {
+ fls->linestyle = newlibadr_us(fd, lib, fls->linestyle);
+ fls->group = newlibadr_us(fd, lib, fls->group);
+ }
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ /* we only bump the use count for the collection objects */
+ base->object = newlibadr(fd, lib, base->object);
+ base->flag |= BASE_DIRTY_ENGINE_SETTINGS;
+ base->collection_properties = NULL;
+ }
+}
+
static void lib_link_scene(FileData *fd, Main *main)
{
#ifdef USE_SETSCENE_CHECK
@@ -5757,17 +5903,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 *next, *base = sce->base.first; base; base = next) {
- next = base->next;
+ for (Base *base_legacy_next, *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);
}
}
@@ -5841,7 +5987,6 @@ static void lib_link_scene(FileData *fd, Main *main)
for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
srl->mat_override = newlibadr_us(fd, sce->id.lib, srl->mat_override);
- srl->light_override = newlibadr_us(fd, sce->id.lib, srl->light_override);
for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
fmc->script = newlibadr(fd, sce->id.lib, fmc->script);
}
@@ -5856,6 +6001,12 @@ 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 (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ lib_link_view_layer(fd, sce->id.lib, view_layer);
+ }
+
#ifdef USE_SETSCENE_CHECK
if (sce->set != NULL) {
/* link flag for scenes with set would be reset later,
@@ -5959,18 +6110,107 @@ static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *vi
direct_link_curvemapping(fd, view_settings->curve_mapping);
}
-static void direct_link_scene(FileData *fd, Scene *sce)
+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_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);
+
+ if (lc->properties) {
+ lc->properties = newdataadr(fd, lc->properties);
+ IDP_DirectLinkGroup_OrFree(&lc->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ BKE_layer_collection_engine_settings_validate_collection(lc);
+ }
+ lc->properties_evaluated = NULL;
+
+ direct_link_layer_collections(fd, &lc->layer_collections);
+ }
+}
+
+static void direct_link_view_layer(FileData *fd, ViewLayer *view_layer)
+{
+ view_layer->stats = NULL;
+ link_list(fd, &view_layer->object_bases);
+ view_layer->basact = newdataadr(fd, view_layer->basact);
+ direct_link_layer_collections(fd, &view_layer->layer_collections);
+
+ if (view_layer->properties != NULL) {
+ view_layer->properties = newdataadr(fd, view_layer->properties);
+ BLI_assert(view_layer->properties != NULL);
+ IDP_DirectLinkGroup_OrFree(&view_layer->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ BKE_view_layer_engine_settings_validate_layer(view_layer);
+ }
+
+ view_layer->id_properties = newdataadr(fd, view_layer->id_properties);
+ IDP_DirectLinkGroup_OrFree(&view_layer->id_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
+ link_list(fd, &(view_layer->freestyle_config.modules));
+ link_list(fd, &(view_layer->freestyle_config.linesets));
+
+ view_layer->properties_evaluated = NULL;
+
+ BLI_listbase_clear(&view_layer->drawdata);
+}
+
+/**
+ * Workspaces store a render layer pointer which can only be read after scene is read.
+ */
+static void direct_link_workspace_link_scene_data(
+ FileData *fd, Scene *scene, const ListBase *workspaces)
+{
+ for (WorkSpace *workspace = workspaces->first; workspace; workspace = workspace->id.next) {
+ for (WorkSpaceDataRelation *relation = workspace->scene_viewlayer_relations.first;
+ relation != NULL;
+ relation = relation->next)
+ {
+ ViewLayer *layer = newdataadr(fd, relation->value);
+ if (layer) {
+ BLI_assert(BLI_findindex(&scene->view_layers, layer) != -1);
+ /* relation->parent is set in lib_link_workspaces */
+ relation->value = layer;
+ }
+ }
+
+ if (workspace->view_layer) { /* this was temporariliy used during 2.8 project. Keep files compatible */
+ ViewLayer *layer = newdataadr(fd, workspace->view_layer);
+ /* only set when layer is from the scene we read */
+ if (layer && (BLI_findindex(&scene->view_layers, layer) != -1)) {
+ workspace->view_layer = layer;
+ }
+ }
+ }
+}
+
+static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain)
{
Editing *ed;
Sequence *seq;
MetaStack *ms;
RigidBodyWorld *rbw;
+ ViewLayer *view_layer;
SceneRenderLayer *srl;
- sce->theDag = NULL;
- sce->depsgraph = NULL;
+ sce->depsgraph_hash = NULL;
sce->obedit = NULL;
- sce->stats = NULL;
sce->fps_info = NULL;
sce->customdata_mask_modal = 0;
sce->lay_updated = 0;
@@ -6002,6 +6242,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sce->toolsettings->imapaint.paintcursor = NULL;
sce->toolsettings->particle.paintcursor = NULL;
sce->toolsettings->particle.scene = NULL;
+ sce->toolsettings->particle.view_layer = NULL;
sce->toolsettings->particle.object = NULL;
sce->toolsettings->gp_sculpt.paintcursor = NULL;
@@ -6159,7 +6400,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
}
link_list(fd, &(sce->markers));
- link_list(fd, &(sce->transform_spaces));
+ link_list(fd, &(sce->transform_spaces)); /* only for old files */
link_list(fd, &(sce->r.layers));
link_list(fd, &(sce->r.views));
@@ -6167,11 +6408,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
for (srl = sce->r.layers.first; srl; srl = srl->next) {
srl->prop = newdataadr(fd, srl->prop);
IDP_DirectLinkGroup_OrFree(&srl->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- }
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
link_list(fd, &(srl->freestyleConfig.modules));
- }
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
link_list(fd, &(srl->freestyleConfig.linesets));
}
@@ -6209,6 +6446,29 @@ 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);
+ }
+
+ /* insert into global old-new map for reading without UI (link_global accesses it again) */
+ link_glob_list(fd, &sce->view_layers);
+ for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ direct_link_view_layer(fd, view_layer);
+ }
+
+ sce->collection_properties = newdataadr(fd, sce->collection_properties);
+ IDP_DirectLinkGroup_OrFree(&sce->collection_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
+ sce->layer_properties = newdataadr(fd, sce->layer_properties);
+ IDP_DirectLinkGroup_OrFree(&sce->layer_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
+ BKE_layer_collection_engine_settings_validate_scene(sce);
+ BKE_view_layer_engine_settings_validate_scene(sce);
+
+ direct_link_workspace_link_scene_data(fd, sce, &bmain->workspaces);
}
/* ************ READ WM ***************** */
@@ -6221,6 +6481,12 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
link_list(fd, &wm->windows);
for (win = wm->windows.first; win; win = win->next) {
+ WorkSpaceInstanceHook *hook = win->workspace_hook;
+
+ win->workspace_hook = newdataadr(fd, hook);
+ /* we need to restore a pointer to this later when reading workspaces, so store in global oldnew-map */
+ oldnewmap_insert(fd->globmap, hook, win->workspace_hook, 0);
+
win->ghostwin = NULL;
win->eventstate = NULL;
win->curswin = NULL;
@@ -6266,6 +6532,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
wm->addonconf = NULL;
wm->userconf = NULL;
+ wm->message_bus = NULL;
+
BLI_listbase_clear(&wm->jobs);
BLI_listbase_clear(&wm->drags);
@@ -6285,6 +6553,11 @@ static void lib_link_windowmanager(FileData *fd, Main *main)
if (wm->id.tag & LIB_TAG_NEED_LINK) {
/* Note: WM IDProperties are never written to file, hence no need to read/link them here. */
for (win = wm->windows.first; win; win = win->next) {
+ if (win->workspace_hook) { /* NULL for old files */
+ lib_link_workspace_instance_hook(fd, win->workspace_hook, &wm->id);
+ }
+ win->scene = newlibadr(fd, wm->id.lib, win->scene);
+ /* deprecated, but needed for versioning (will be NULL'ed then) */
win->screen = newlibadr(fd, NULL, win->screen);
}
@@ -6370,13 +6643,9 @@ static void lib_link_screen(FileData *fd, Main *main)
IDP_LibLinkProperty(sc->id.properties, fd);
id_us_ensure_real(&sc->id);
+ /* deprecated, but needed for versioning (will be NULL'ed then) */
sc->scene = newlibadr(fd, sc->id.lib, sc->scene);
- /* this should not happen, but apparently it does somehow. Until we figure out the cause,
- * just assign first available scene */
- if (!sc->scene)
- sc->scene = main->scene.first;
-
sc->animtimer = NULL; /* saved in rare cases */
sc->scrubbing = false;
@@ -6388,22 +6657,10 @@ static void lib_link_screen(FileData *fd, Main *main)
case SPACE_VIEW3D:
{
View3D *v3d = (View3D*) sl;
- BGpic *bgpic = NULL;
v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre);
- /* should be do_versions but not easy adding into the listbase */
- if (v3d->bgpic) {
- v3d->bgpic = newlibadr(fd, sc->id.lib, v3d->bgpic);
- BLI_addtail(&v3d->bgpicbase, bgpic);
- v3d->bgpic = NULL;
- }
-
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- bgpic->ima = newlibadr_us(fd, sc->id.lib, bgpic->ima);
- bgpic->clip = newlibadr_us(fd, sc->id.lib, bgpic->clip);
- }
if (v3d->localvd) {
v3d->localvd->camera = newlibadr(fd, sc->id.lib, v3d->localvd->camera);
}
@@ -6684,88 +6941,60 @@ static void lib_link_clipboard_restore(struct IDNameLib_Map *id_map)
BKE_sequencer_base_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map);
}
-/* called from kernel/blender.c */
-/* used to link a file (without UI) to the current UI */
-/* note that it assumes the old pointers in UI are still valid, so old Main is not freed */
-void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene)
+static void lib_link_workspace_scene_data_restore(wmWindow *win, Scene *scene)
{
- wmWindow *win;
- wmWindowManager *wm;
- bScreen *sc;
- ScrArea *sa;
+ bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
- struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain);
+ for (ScrArea *area = screen->areabase.first; area; area = area->next) {
+ for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
- /* first windowmanager */
- for (wm = newmain->wm.first; wm; wm = wm->id.next) {
- for (win= wm->windows.first; win; win= win->next) {
- win->screen = restore_pointer_by_name(id_map, (ID *)win->screen, USER_REAL);
-
- if (win->screen == NULL)
- win->screen = curscreen;
-
- win->screen->winid = win->winid;
+ if (v3d->camera == NULL || v3d->scenelock) {
+ v3d->camera = scene->camera;
+ }
+
+ if (v3d->localvd) {
+ /*Base *base;*/
+
+ v3d->localvd->camera = scene->camera;
+
+ /* localview can become invalid during undo/redo steps, so we exit it when no could be found */
+#if 0 /* XXX regionlocalview ? */
+ for (base= sc->scene->base.first; base; base= base->next) {
+ if (base->lay & v3d->lay) break;
+ }
+ if (base==NULL) {
+ v3d->lay= v3d->localvd->lay;
+ v3d->layact= v3d->localvd->layact;
+ MEM_freeN(v3d->localvd);
+ v3d->localvd= NULL;
+ }
+#endif
+ }
+ else if (v3d->scenelock) {
+ v3d->lay = scene->lay;
+ }
+ }
}
}
-
-
- for (sc = newmain->screen.first; sc; sc = sc->id.next) {
- Scene *oldscene = sc->scene;
-
- sc->scene= restore_pointer_by_name(id_map, (ID *)sc->scene, USER_REAL);
- if (sc->scene == NULL)
- sc->scene = curscene;
-
- /* keep cursor location through undo */
- copy_v3_v3(sc->scene->cursor, oldscene->cursor);
-
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
-
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
+}
+
+static void lib_link_workspace_layout_restore(struct IDNameLib_Map *id_map, Main *newmain, WorkSpaceLayout *layout)
+{
+ bScreen *screen = BKE_workspace_layout_screen_get(layout);
+
+ /* avoid conflicts with 2.8x branch */
+ {
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
- BGpic *bgpic;
ARegion *ar;
- if (v3d->scenelock)
- v3d->camera = NULL; /* always get from scene */
- else
- v3d->camera = restore_pointer_by_name(id_map, (ID *)v3d->camera, USER_REAL);
- if (v3d->camera == NULL)
- v3d->camera = sc->scene->camera;
+ v3d->camera = restore_pointer_by_name(id_map, (ID *)v3d->camera, USER_REAL);
v3d->ob_centre = restore_pointer_by_name(id_map, (ID *)v3d->ob_centre, USER_REAL);
-
- for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) {
- if ((bgpic->ima = restore_pointer_by_name(id_map, (ID *)bgpic->ima, USER_IGNORE))) {
- id_us_plus((ID *)bgpic->ima);
- }
- if ((bgpic->clip = restore_pointer_by_name(id_map, (ID *)bgpic->clip, USER_IGNORE))) {
- id_us_plus((ID *)bgpic->clip);
- }
- }
- if (v3d->localvd) {
- /*Base *base;*/
-
- v3d->localvd->camera = sc->scene->camera;
-
- /* localview can become invalid during undo/redo steps, so we exit it when no could be found */
-#if 0 /* XXX regionlocalview ? */
- for (base= sc->scene->base.first; base; base= base->next) {
- if (base->lay & v3d->lay) break;
- }
- if (base==NULL) {
- v3d->lay= v3d->localvd->lay;
- v3d->layact= v3d->localvd->layact;
- MEM_freeN(v3d->localvd);
- v3d->localvd= NULL;
- }
-#endif
- }
- else if (v3d->scenelock) {
- v3d->lay = sc->scene->lay;
- }
-
+
/* not very nice, but could help */
if ((v3d->layact & v3d->lay) == 0) v3d->layact = v3d->lay;
@@ -6967,6 +7196,44 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
}
}
}
+}
+
+/**
+ * Used to link a file (without UI) to the current UI.
+ * Note that it assumes the old pointers in UI are still valid, so old Main is not freed.
+ */
+void blo_lib_link_restore(Main *newmain, wmWindowManager *curwm, Scene *curscene, ViewLayer *cur_view_layer)
+{
+ struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain);
+
+ for (WorkSpace *workspace = newmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ ListBase *layouts = BKE_workspace_layouts_get(workspace);
+
+ for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) {
+ lib_link_workspace_layout_restore(id_map, newmain, layout);
+ }
+ BKE_workspace_view_layer_set(workspace, cur_view_layer, curscene);
+ }
+
+ for (wmWindow *win = curwm->windows.first; win; win = win->next) {
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ ID *workspace_id = (ID *)workspace;
+ Scene *oldscene = win->scene;
+
+ workspace = restore_pointer_by_name(id_map, workspace_id, USER_REAL);
+ BKE_workspace_active_set(win->workspace_hook, workspace);
+ win->scene = restore_pointer_by_name(id_map, (ID *)win->scene, USER_REAL);
+ if (win->scene == NULL) {
+ win->scene = curscene;
+ }
+ BKE_workspace_active_set(win->workspace_hook, workspace);
+
+ /* keep cursor location through undo */
+ copy_v3_v3(win->scene->cursor, oldscene->cursor);
+ lib_link_workspace_scene_data_restore(win, win->scene);
+
+ BLI_assert(win->screen == NULL);
+ }
/* update IDs stored in all possible clipboards */
lib_link_clipboard_restore(id_map);
@@ -7020,6 +7287,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
rv3d->sms = NULL;
rv3d->smooth_timer = NULL;
rv3d->compositor = NULL;
+ rv3d->viewport = NULL;
}
}
}
@@ -7036,6 +7304,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
ar->type = NULL;
ar->swap = 0;
ar->do_draw = 0;
+ ar->manipulator_map = NULL;
ar->regiontimer = NULL;
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
}
@@ -7082,6 +7351,8 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
sc->mainwin = sc->subwinactive= 0; /* indices */
sc->swap = 0;
+ sc->preview = direct_link_preview_image(fd, sc->preview);
+
/* edges */
for (se = sc->edgebase.first; se; se = se->next) {
se->v1 = newdataadr(fd, se->v1);
@@ -7146,22 +7417,8 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d= (View3D*) sl;
- BGpic *bgpic;
-
v3d->flag |= V3D_INVALID_BACKBUF;
- link_list(fd, &v3d->bgpicbase);
-
- /* should be do_versions except this doesnt fit well there */
- if (v3d->bgpic) {
- bgpic = newdataadr(fd, v3d->bgpic);
- BLI_addtail(&v3d->bgpicbase, bgpic);
- v3d->bgpic = NULL;
- }
-
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next)
- bgpic->iuser.ok = 1;
-
if (v3d->gpd) {
v3d->gpd = newdataadr(fd, v3d->gpd);
direct_link_gpencil(fd, v3d->gpd);
@@ -7447,6 +7704,26 @@ static void fix_relpaths_library(const char *basepath, Main *main)
}
}
+/* ************ READ PROBE ***************** */
+
+static void lib_link_lightprobe(FileData *fd, Main *main)
+{
+ for (LightProbe *prb = main->speaker.first; prb; prb = prb->id.next) {
+ if (prb->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(prb->id.properties, fd);
+ lib_link_animdata(fd, &prb->id, prb->adt);
+
+ prb->id.tag &= ~LIB_TAG_NEED_LINK;
+ }
+ }
+}
+
+static void direct_link_lightprobe(FileData *fd, LightProbe *prb)
+{
+ prb->adt = newdataadr(fd, prb->adt);
+ direct_link_animdata(fd, prb->adt);
+}
+
/* ************ READ SPEAKER ***************** */
static void lib_link_speaker(FileData *fd, Main *main)
@@ -7526,30 +7803,61 @@ static void direct_link_group(FileData *fd, Group *group)
link_list(fd, &group->gobject);
group->preview = direct_link_preview_image(fd, group->preview);
+
+ /* This runs before the very first doversion. */
+ if (group->collection != NULL) {
+ group->collection = newdataadr(fd, group->collection);
+ direct_link_scene_collection(fd, group->collection);
+ }
+
+ if (group->view_layer != NULL) {
+ group->view_layer = newdataadr(fd, group->view_layer);
+ direct_link_view_layer(fd, group->view_layer);
+ }
}
static void lib_link_group(FileData *fd, Main *main)
{
for (Group *group = main->group.first; group; group = group->id.next) {
if (group->id.tag & LIB_TAG_NEED_LINK) {
+ group->id.tag &= ~LIB_TAG_NEED_LINK;
IDP_LibLinkProperty(group->id.properties, fd);
-
- bool add_us = false;
-
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- go->ob = newlibadr_real_us(fd, group->id.lib, go->ob);
- if (go->ob) {
- go->ob->flag |= OB_FROMGROUP;
- /* if group has an object, it increments user... */
- add_us = true;
+
+ if (group->view_layer == NULL) {
+ /* Old file, this is required for doversion. */
+ bool add_us = false;
+
+ GroupObject *go, *gon;
+ go = group->gobject.first;
+ while (go) {
+ gon = go->next;
+ go->ob = newlibadr_real_us(fd, group->id.lib, go->ob);
+ if (go->ob != NULL) {
+ go->ob->flag |= OB_FROMGROUP;
+ /* If group has an object, it increments user... */
+ add_us = true;
+ }
+ else {
+ /* Remove NULL objects. */
+ BLI_remlink(&group->gobject, go);
+ MEM_freeN(go);
+ }
+ go = gon;
+ }
+
+ if (add_us) {
+ id_us_ensure_real(&group->id);
}
+ /* The rest of the read code is only for new files, skip it. */
+ continue;
}
- if (add_us) {
+
+ lib_link_scene_collection(fd, group->id.lib, group->collection);
+ lib_link_view_layer(fd, group->id.lib, group->view_layer);
+
+ if (!BLI_listbase_is_empty(&group->view_layer->object_bases)) {
id_us_ensure_real(&group->id);
}
- BKE_group_object_unlink(group, NULL, NULL, NULL); /* removes NULL entries */
-
- group->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -8062,6 +8370,7 @@ static const char *dataname(short id_code)
case ID_VF: return "Data from VF";
case ID_TXT : return "Data from TXT";
case ID_SPK: return "Data from SPK";
+ case ID_LP: return "Data from LP";
case ID_SO: return "Data from SO";
case ID_NT: return "Data from NT";
case ID_BR: return "Data from BR";
@@ -8074,6 +8383,7 @@ static const char *dataname(short id_code)
case ID_MSK: return "Data from MSK";
case ID_LS: return "Data from LS";
case ID_CF: return "Data from CF";
+ case ID_WS: return "Data from WS";
}
return "Data from Lib Block";
@@ -8237,7 +8547,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
wrong_id = direct_link_screen(fd, (bScreen *)id);
break;
case ID_SCE:
- direct_link_scene(fd, (Scene *)id);
+ direct_link_scene(fd, (Scene *)id, main);
break;
case ID_OB:
direct_link_object(fd, (Object *)id);
@@ -8293,6 +8603,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
case ID_SO:
direct_link_sound(fd, (bSound *)id);
break;
+ case ID_LP:
+ direct_link_lightprobe(fd, (LightProbe *)id);
+ break;
case ID_GR:
direct_link_group(fd, (Group *)id);
break;
@@ -8332,6 +8645,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
case ID_CF:
direct_link_cachefile(fd, (CacheFile *)id);
break;
+ case ID_WS:
+ direct_link_workspace(fd, (WorkSpace *)id, main);
+ break;
}
oldnewmap_free_unused(fd->datamap);
@@ -8377,7 +8693,8 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
bfd->curscreen = fg->curscreen;
bfd->curscene = fg->curscene;
-
+ bfd->cur_view_layer = fg->cur_view_layer;
+
MEM_freeN(fg);
fd->globalf = bfd->globalf;
@@ -8389,6 +8706,7 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
/* note, this has to be kept for reading older files... */
static void link_global(FileData *fd, BlendFileData *bfd)
{
+ bfd->cur_view_layer = newglobadr(fd, bfd->cur_view_layer);
bfd->curscreen = newlibadr(fd, NULL, bfd->curscreen);
bfd->curscene = newlibadr(fd, NULL, bfd->curscene);
// this happens in files older than 2.35
@@ -8397,26 +8715,6 @@ static void link_global(FileData *fd, BlendFileData *bfd)
}
}
-static void convert_tface_mt(FileData *fd, Main *main)
-{
- Main *gmain;
-
- /* this is a delayed do_version (so it can create new materials) */
- if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 3)) {
- //XXX hack, material.c uses G.main all over the place, instead of main
- // temporarily set G.main to the current main
- gmain = G.main;
- G.main = main;
-
- if (!(do_version_tface(main))) {
- BKE_report(fd->reports, RPT_WARNING, "Texface conversion problem (see error in console)");
- }
-
- //XXX hack, material.c uses G.main allover the place, instead of main
- G.main = gmain;
- }
-}
-
/* initialize userdef with non-UI dependency stuff */
/* other initializers (such as theme color defaults) go to resources.c */
static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
@@ -8470,6 +8768,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! */
@@ -8483,12 +8782,15 @@ static void do_versions_after_linking(Main *main)
// 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)
{
oldnewmap_sort(fd);
+ lib_link_id(fd, main);
+
/* No load UI for undo memfiles */
if (fd->memfile == NULL) {
lib_link_windowmanager(fd, main);
@@ -8511,6 +8813,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_text(fd, main);
lib_link_camera(fd, main);
lib_link_speaker(fd, main);
+ lib_link_lightprobe(fd, main);
lib_link_sound(fd, main);
lib_link_group(fd, main);
lib_link_armature(fd, main);
@@ -8526,6 +8829,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_linestyle(fd, main);
lib_link_gpencil(fd, main);
lib_link_cachefiles(fd, main);
+ lib_link_workspaces(fd, main);
lib_link_library(fd, main); /* only init users */
}
@@ -8712,6 +9016,12 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false);
+ /* Now that all our data-blocks are loaded, we can re-generate overrides from their references. */
+ if (fd->memfile == NULL) {
+ /* Do not apply in undo case! */
+ BKE_main_override_static_update(bfd->main);
+ }
+
lib_verify_nodetree(bfd->main, true);
fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */
@@ -8912,6 +9222,11 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
}
}
else {
+ /* in 2.50+ file identifier for screens is patched, forward compatibility */
+ if (bhead->code == ID_SCRN) {
+ bhead->code = ID_SCR;
+ }
+
id = is_yet_read(fd, mainvar, bhead);
if (id == NULL) {
read_libblock(fd, mainvar, bhead, LIB_TAG_TESTIND, NULL);
@@ -9145,6 +9460,11 @@ static void expand_group(FileData *fd, Main *mainvar, Group *group)
for (go = group->gobject.first; go; go = go->next) {
expand_doit(fd, mainvar, go->ob);
}
+
+ if (group->collection != NULL) {
+ expand_scene_collection(fd, mainvar, group->collection);
+ }
+
}
static void expand_key(FileData *fd, Main *mainvar, Key *key)
@@ -9226,6 +9546,10 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma)
if (ma->group)
expand_doit(fd, mainvar, ma->group);
+
+ if (ma->edit_image) {
+ expand_doit(fd, mainvar, ma->edit_image);
+ }
}
static void expand_lamp(FileData *fd, Main *mainvar, Lamp *la)
@@ -9315,9 +9639,7 @@ static void expand_curve(FileData *fd, Main *mainvar, Curve *cu)
static void expand_mesh(FileData *fd, Main *mainvar, Mesh *me)
{
- CustomDataLayer *layer;
- TFace *tf;
- int a, i;
+ int a;
if (me->adt)
expand_animdata(fd, mainvar, me->adt);
@@ -9328,46 +9650,6 @@ static void expand_mesh(FileData *fd, Main *mainvar, Mesh *me)
expand_doit(fd, mainvar, me->key);
expand_doit(fd, mainvar, me->texcomesh);
-
- if (me->tface) {
- tf = me->tface;
- for (i=0; i<me->totface; i++, tf++) {
- if (tf->tpage)
- expand_doit(fd, mainvar, tf->tpage);
- }
- }
-
- if (me->mface && !me->mpoly) {
- MTFace *mtf;
-
- for (a = 0; a < me->fdata.totlayer; a++) {
- layer = &me->fdata.layers[a];
-
- if (layer->type == CD_MTFACE) {
- mtf = (MTFace *) layer->data;
- for (i = 0; i < me->totface; i++, mtf++) {
- if (mtf->tpage)
- expand_doit(fd, mainvar, mtf->tpage);
- }
- }
- }
- }
- else {
- MTexPoly *mtp;
-
- for (a = 0; a < me->pdata.totlayer; a++) {
- layer = &me->pdata.layers[a];
-
- if (layer->type == CD_MTEXPOLY) {
- mtp = (MTexPoly *) layer->data;
-
- for (i = 0; i < me->totpoly; i++, mtp++) {
- if (mtp->tpage)
- expand_doit(fd, mainvar, mtp->tpage);
- }
- }
- }
- }
}
/* temp struct used to transport needed info to expand_constraint_cb() */
@@ -9610,15 +9892,29 @@ 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;
SceneRenderLayer *srl;
FreestyleModuleConfig *module;
FreestyleLineSet *lineset;
- for (base = sce->base.first; base; base = base->next) {
- expand_doit(fd, mainvar, base->object);
+ for (Base *base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy->next) {
+ expand_doit(fd, mainvar, base_legacy->object);
}
expand_doit(fd, mainvar, sce->camera);
expand_doit(fd, mainvar, sce->world);
@@ -9635,7 +9931,6 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
for (srl = sce->r.layers.first; srl; srl = srl->next) {
expand_doit(fd, mainvar, srl->mat_override);
- expand_doit(fd, mainvar, srl->light_override);
for (module = srl->freestyleConfig.modules.first; module; module = module->next) {
if (module->script)
expand_doit(fd, mainvar, module->script);
@@ -9646,7 +9941,22 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
expand_doit(fd, mainvar, lineset->linestyle);
}
}
-
+
+ for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (module = view_layer->freestyle_config.modules.first; module; module = module->next) {
+ if (module->script) {
+ expand_doit(fd, mainvar, module->script);
+ }
+ }
+
+ for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->group) {
+ expand_doit(fd, mainvar, lineset->group);
+ }
+ expand_doit(fd, mainvar, lineset->linestyle);
+ }
+ }
+
if (sce->r.dometext)
expand_doit(fd, mainvar, sce->gm.dome.warptext);
@@ -9681,6 +9991,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)
@@ -9711,6 +10023,12 @@ static void expand_sound(FileData *fd, Main *mainvar, bSound *snd)
expand_doit(fd, mainvar, snd->ipo); // XXX deprecated - old animation system
}
+static void expand_lightprobe(FileData *fd, Main *mainvar, LightProbe *prb)
+{
+ if (prb->adt)
+ expand_animdata(fd, mainvar, prb->adt);
+}
+
static void expand_movieclip(FileData *fd, Main *mainvar, MovieClip *clip)
{
if (clip->adt)
@@ -9784,6 +10102,15 @@ static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd)
expand_animdata(fd, mainvar, gpd->adt);
}
+static void expand_workspace(FileData *fd, Main *mainvar, WorkSpace *workspace)
+{
+ ListBase *layouts = BKE_workspace_layouts_get(workspace);
+
+ for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) {
+ expand_doit(fd, mainvar, BKE_workspace_layout_screen_get(layout));
+ }
+}
+
/**
* Set the callback func used over all ID data found by \a BLO_expand_main func.
*
@@ -9862,6 +10189,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
case ID_SO:
expand_sound(fd, mainvar, (bSound *)id);
break;
+ case ID_LP:
+ expand_lightprobe(fd, mainvar, (LightProbe *)id);
+ break;
case ID_AR:
expand_armature(fd, mainvar, (bArmature *)id);
break;
@@ -9898,6 +10228,8 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
case ID_CF:
expand_cachefile(fd, mainvar, (CacheFile *)id);
break;
+ case ID_WS:
+ expand_workspace(fd, mainvar, (WorkSpace *)id);
default:
break;
}
@@ -9920,7 +10252,7 @@ static bool object_in_any_scene(Main *mainvar, Object *ob)
Scene *sce;
for (sce = mainvar->scene.first; sce; sce = sce->id.next) {
- if (BKE_scene_base_find(sce, ob)) {
+ if (BKE_scene_object_find(sce, ob)) {
return true;
}
}
@@ -9928,16 +10260,17 @@ static bool object_in_any_scene(Main *mainvar, Object *ob)
return false;
}
-static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Library *lib, const short flag)
+static void give_base_to_objects(
+ Main *mainvar, Scene *scene, ViewLayer *view_layer, Library *lib, const short flag)
{
Object *ob;
Base *base;
- const unsigned int active_lay = (flag & FILE_ACTIVELAY) ? BKE_screen_view3d_layer_active(v3d, scene) : 0;
+ SceneCollection *scene_collection = NULL;
const bool is_link = (flag & FILE_LINK) != 0;
BLI_assert(scene);
- /* give all objects which are LIB_TAG_INDIRECT a base, or for a group when *lib has been set */
+ /* Give all objects which are LIB_TAG_INDIRECT a base, or for a group when *lib has been set. */
for (ob = mainvar->object.first; ob; ob = ob->id.next) {
if ((ob->id.tag & LIB_TAG_INDIRECT) && (ob->id.tag & LIB_TAG_PRE_EXISTING) == 0) {
bool do_it = false;
@@ -9952,26 +10285,26 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra
}
if (do_it) {
- base = MEM_callocN(sizeof(Base), __func__);
- BLI_addtail(&scene->base, base);
+ CLAMP_MIN(ob->id.us, 0);
- if (active_lay) {
- ob->lay = active_lay;
+ if (scene_collection == NULL) {
+ scene_collection = get_scene_collection_active_or_create(scene, view_layer, FILE_ACTIVE_COLLECTION);
}
+
+ BKE_collection_object_add(&scene->id, scene_collection, ob);
+ base = BKE_view_layer_base_find(view_layer, ob);
+ BKE_scene_object_base_flag_sync_from_base(base);
+
if (flag & FILE_AUTOSELECT) {
/* Note that link_object_postprocess() already checks for FILE_AUTOSELECT flag,
* but it will miss objects from non-instanciated groups... */
- ob->flag |= SELECT;
- /* do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level */
+ if (base->flag & BASE_SELECTABLED) {
+ base->flag |= BASE_SELECTED;
+ BKE_scene_object_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. */
}
- base->object = ob;
- base->lay = ob->lay;
- base->flag = ob->flag;
-
- CLAMP_MIN(ob->id.us, 0);
- id_us_plus_no_lib((ID *)ob);
-
ob->id.tag &= ~LIB_TAG_INDIRECT;
ob->id.tag |= LIB_TAG_EXTERN;
}
@@ -9980,32 +10313,38 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra
}
static void give_base_to_groups(
- Main *mainvar, Scene *scene, View3D *v3d, Library *UNUSED(lib), const short UNUSED(flag))
+ Main *mainvar, Scene *scene, ViewLayer *view_layer, Library *UNUSED(lib), const short UNUSED(flag))
{
Group *group;
Base *base;
Object *ob;
- const unsigned int active_lay = BKE_screen_view3d_layer_active(v3d, scene);
+ SceneCollection *scene_collection;
+
+ /* If the group is empty this function is not even called, so it's safe to ensure a collection at this point. */
+ scene_collection = get_scene_collection_active_or_create(scene, view_layer, FILE_ACTIVE_COLLECTION);
- /* give all objects which are tagged a base */
+ /* Give all objects which are tagged a base. */
for (group = mainvar->group.first; group; group = group->id.next) {
if (group->id.tag & LIB_TAG_DOIT) {
- /* any indirect group should not have been tagged */
+ /* Any indirect group should not have been tagged. */
BLI_assert((group->id.tag & LIB_TAG_INDIRECT) == 0);
- /* BKE_object_add(...) messes with the selection */
+ /* BKE_object_add(...) messes with the selection. */
ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2);
ob->type = OB_EMPTY;
- ob->lay = active_lay;
- /* assign the base */
- base = BKE_scene_base_add(scene, ob);
- base->flag |= SELECT;
- base->object->flag = base->flag;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- scene->basact = base;
+ BKE_collection_object_add(&scene->id, scene_collection, ob);
+ base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (base->flag & BASE_SELECTABLED) {
+ base->flag |= BASE_SELECTED;
+ }
+
+ BKE_scene_object_base_flag_sync_from_base(base);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ view_layer->basact = base;
- /* assign the group */
+ /* Assign the group. */
ob->dup_group = group;
ob->transflag |= OB_DUPLIGROUP;
copy_v3_v3(ob->loc, scene->cursor);
@@ -10082,31 +10421,43 @@ static ID *link_named_part(
return id;
}
-static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const int flag)
+static SceneCollection *get_scene_collection_active_or_create(
+ struct Scene *scene, struct ViewLayer *view_layer, const int flag)
+{
+ LayerCollection *lc = NULL;
+
+ if (flag & FILE_ACTIVE_COLLECTION) {
+ lc = BKE_layer_collection_get_active_ensure(scene, view_layer);
+ }
+ else {
+ SceneCollection *sc = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL);
+ lc = BKE_collection_link(view_layer, sc);
+ }
+
+ return lc->scene_collection;
+}
+
+static void link_object_postprocess(ID *id, Scene *scene, ViewLayer *view_layer, const int flag)
{
if (scene) {
+ /* link to scene */
Base *base;
Object *ob;
-
- base = MEM_callocN(sizeof(Base), "app_nam_part");
- BLI_addtail(&scene->base, base);
+ SceneCollection *sc;
ob = (Object *)id;
-
- /* link at active layer (view3d if available in context, else scene one */
- if (flag & FILE_ACTIVELAY) {
- ob->lay = BKE_screen_view3d_layer_active(v3d, scene);
- }
-
ob->mode = OB_MODE_OBJECT;
- base->lay = ob->lay;
- base->object = ob;
- base->flag = ob->flag;
- id_us_plus_no_lib((ID *)ob);
+
+ sc = get_scene_collection_active_or_create(scene, view_layer, flag);
+ BKE_collection_object_add(&scene->id, sc, ob);
+ base = BKE_view_layer_base_find(view_layer, ob);
+ BKE_scene_object_base_flag_sync_from_base(base);
if (flag & FILE_AUTOSELECT) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
+ if (base->flag & BASE_SELECTABLED) {
+ base->flag |= BASE_SELECTED;
+ BKE_scene_object_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 */
}
}
@@ -10149,12 +10500,12 @@ void BLO_library_link_copypaste(Main *mainl, BlendHandle *bh)
static ID *link_named_part_ex(
Main *mainl, FileData *fd, const short idcode, const char *name, const int flag,
- Scene *scene, View3D *v3d)
+ Scene *scene, ViewLayer *view_layer)
{
ID *id = link_named_part(mainl, fd, idcode, name, flag);
if (id && (GS(id->name) == ID_OB)) { /* loose object: give a base */
- link_object_postprocess(id, scene, v3d, flag);
+ link_object_postprocess(id, scene, view_layer, flag);
}
else if (id && (GS(id->name) == ID_GR)) {
/* tag as needing to be instantiated */
@@ -10196,10 +10547,10 @@ ID *BLO_library_link_named_part(Main *mainl, BlendHandle **bh, const short idcod
ID *BLO_library_link_named_part_ex(
Main *mainl, BlendHandle **bh,
const short idcode, const char *name, const int flag,
- Scene *scene, View3D *v3d)
+ Scene *scene, ViewLayer *view_layer)
{
FileData *fd = (FileData*)(*bh);
- return link_named_part_ex(mainl, fd, idcode, name, flag, scene, v3d);
+ return link_named_part_ex(mainl, fd, idcode, name, flag, scene, view_layer);
}
static void link_id_part(ReportList *reports, FileData *fd, Main *mainvar, ID *id, ID **r_id)
@@ -10312,7 +10663,7 @@ static void split_main_newid(Main *mainptr, Main *main_newid)
}
/* scene and v3d may be NULL. */
-static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene *scene, View3D *v3d)
+static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene *scene, ViewLayer *view_layer)
{
Main *mainvar;
Library *curlib;
@@ -10368,10 +10719,10 @@ static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene
* Only directly linked objects & groups are instantiated by `BLO_library_link_named_part_ex()` & co,
* here we handle indirect ones and other possible edge-cases. */
if (scene) {
- give_base_to_objects(mainvar, scene, v3d, curlib, flag);
+ give_base_to_objects(mainvar, scene, view_layer, curlib, flag);
if (flag & FILE_GROUP_INSTANCE) {
- give_base_to_groups(mainvar, scene, v3d, curlib, flag);
+ give_base_to_groups(mainvar, scene, view_layer, curlib, flag);
}
}
else {
@@ -10397,12 +10748,12 @@ static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene
* \param bh The blender file handle (WARNING! may be freed by this function!).
* \param flag Options for linking, used for instantiating.
* \param scene The scene in which to instantiate objects/groups (if NULL, no instantiation is done).
- * \param v3d The active View3D (only to define active layers for instantiated objects & groups, can be NULL).
+ * \param view_layer The scene layer in which to instantiate objects/groups (if NULL, no instantiation is done).
*/
-void BLO_library_link_end(Main *mainl, BlendHandle **bh, short flag, Scene *scene, View3D *v3d)
+void BLO_library_link_end(Main *mainl, BlendHandle **bh, int flag, Scene *scene, ViewLayer *view_layer)
{
FileData *fd = (FileData*)(*bh);
- library_link_end(mainl, &fd, flag, scene, v3d);
+ library_link_end(mainl, &fd, flag, scene, view_layer);
*bh = (BlendHandle*)fd;
}
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index 62ce15a640e..299c66f2bbb 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;
@@ -171,8 +173,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..3ee6891f17f 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -1119,8 +1119,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
sce->gm.matmode = GAME_MAT_MULTITEX;
else
sce->gm.matmode = GAME_MAT_TEXFACE;
-
- sce->gm.flag |= GAME_DISPLAY_LISTS;
}
for (ob = main->object.first; ob; ob = ob->id.next) {
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index fa7bf0c7dee..bf2d5c8e326 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1733,6 +1733,27 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
for (Mesh *me = main->mesh.first; me; me = me->id.next) {
CustomData_set_layer_name(&me->vdata, CD_MDEFORMVERT, 0, "");
}
+
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DDebug", "char", "background")) {
+ bScreen *screen;
+
+ for (screen = main->screen.first; screen; screen = screen->id.next) {
+ ScrArea *sa;
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ switch (sl->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d = (View3D *)sl;
+ v3d->debug.background = V3D_DEBUG_BACKGROUND_NONE;
+ }
+ }
+ }
+ }
+ }
+ }
}
{
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
new file mode 100644
index 00000000000..163df9987bb
--- /dev/null
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -0,0 +1,830 @@
+/*
+ * ***** 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 <string.h>
+
+#include "BLI_listbase.h"
+#include "BLI_mempool.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_gpu_types.h"
+#include "DNA_group_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_layer_types.h"
+#include "DNA_lightprobe_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_genfile.h"
+#include "DNA_workspace_types.h"
+
+#include "BKE_collection.h"
+#include "BKE_customdata.h"
+#include "BKE_freestyle.h"
+#include "BKE_group.h"
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_node.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_workspace.h"
+
+#include "BLO_readfile.h"
+#include "readfile.h"
+
+#include "MEM_guardedalloc.h"
+
+
+static bScreen *screen_parent_find(const bScreen *screen)
+{
+ /* can avoid lookup if screen state isn't maximized/full (parent and child store the same state) */
+ if (ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL)) {
+ for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa->full && sa->full != screen) {
+ BLI_assert(sa->full->state == screen->state);
+ return sa->full;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void do_version_workspaces_create_from_screens(Main *bmain)
+{
+ for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
+ const bScreen *screen_parent = screen_parent_find(screen);
+ Scene *scene = screen->scene;
+ WorkSpace *workspace;
+ ViewLayer *layer = BKE_view_layer_from_scene_get(scene);
+ ListBase *transform_orientations;
+
+ if (screen_parent) {
+ /* fullscreen with "Back to Previous" option, don't create
+ * a new workspace, add layout workspace containing parent */
+ workspace = BLI_findstring(
+ &bmain->workspaces, screen_parent->id.name + 2, offsetof(ID, name) + 2);
+ }
+ else {
+ workspace = BKE_workspace_add(bmain, screen->id.name + 2);
+ }
+ BKE_workspace_layout_add(workspace, screen, screen->id.name + 2);
+ BKE_workspace_view_layer_set(workspace, layer, scene);
+
+#ifdef WITH_CLAY_ENGINE
+ BLI_strncpy(workspace->view_render.engine_id, RE_engine_id_BLENDER_CLAY,
+ sizeof(workspace->view_render.engine_id));
+#else
+ BLI_strncpy(workspace->view_render.engine_id, RE_engine_id_BLENDER_EEVEE,
+ sizeof(workspace->view_render.engine_id));
+#endif
+
+ transform_orientations = BKE_workspace_transform_orientations_get(workspace);
+ BLI_duplicatelist(transform_orientations, &scene->transform_spaces);
+ }
+}
+
+/**
+ * \brief After lib-link versioning for new workspace design.
+ *
+ * * Adds a workspace for (almost) each screen of the old file
+ * and adds the needed workspace-layout to wrap the screen.
+ * * Active screen isn't stored directly in window anymore, but in the active workspace.
+ * * Active scene isn't stored in screen anymore, but in window.
+ * * Create workspace instance hook for each window.
+ *
+ * \note Some of the created workspaces might be deleted again in case of reading the default startup.blend.
+ */
+static void do_version_workspaces_after_lib_link(Main *bmain)
+{
+ BLI_assert(BLI_listbase_is_empty(&bmain->workspaces));
+
+ do_version_workspaces_create_from_screens(bmain);
+
+ for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ bScreen *screen_parent = screen_parent_find(win->screen);
+ bScreen *screen = screen_parent ? screen_parent : win->screen;
+ WorkSpace *workspace = BLI_findstring(&bmain->workspaces, screen->id.name + 2, offsetof(ID, name) + 2);
+ ListBase *layouts = BKE_workspace_layouts_get(workspace);
+
+ win->workspace_hook = BKE_workspace_instance_hook_create(bmain);
+
+ BKE_workspace_active_set(win->workspace_hook, workspace);
+ BKE_workspace_active_layout_set(win->workspace_hook, layouts->first);
+
+ win->scene = screen->scene;
+ /* Deprecated from now on! */
+ win->screen = NULL;
+ }
+ }
+
+ for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
+ /* Deprecated from now on! */
+ BLI_freelistN(&screen->scene->transform_spaces);
+ screen->scene = NULL;
+ }
+}
+
+enum {
+ DO_VERSION_COLLECTION_VISIBLE = 0,
+ DO_VERSION_COLLECTION_HIDE = 1,
+ DO_VERSION_COLLECTION_HIDE_RENDER = 2,
+ DO_VERSION_COLLECTION_HIDE_ALL = 3,
+};
+
+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->view_layers.first == NULL) {
+ SceneCollection *sc_master = BKE_collection_master(&scene->id);
+ BLI_strncpy(sc_master->name, "Master Collection", sizeof(sc_master->name));
+
+ struct DoVersionSceneCollections {
+ SceneCollection *collections[20];
+ int created;
+ const char *suffix;
+ int flag_viewport;
+ int flag_render;
+ } collections[] =
+ {
+ {
+ .collections = {NULL},
+ .created = 0,
+ .suffix = "",
+ .flag_viewport = COLLECTION_VISIBLE | COLLECTION_SELECTABLE,
+ .flag_render = COLLECTION_VISIBLE | COLLECTION_SELECTABLE
+ },
+ {
+ .collections = {NULL},
+ .created = 0,
+ .suffix = " - Hide Viewport",
+ .flag_viewport = COLLECTION_SELECTABLE,
+ .flag_render = COLLECTION_VISIBLE | COLLECTION_SELECTABLE
+ },
+ {
+ .collections = {NULL},
+ .created = 0,
+ .suffix = " - Hide Render",
+ .flag_viewport = COLLECTION_VISIBLE | COLLECTION_SELECTABLE,
+ .flag_render = COLLECTION_SELECTABLE | COLLECTION_DISABLED
+ },
+ {
+ .collections = {NULL},
+ .created = 0,
+ .suffix = " - Hide Render All",
+ .flag_viewport = COLLECTION_SELECTABLE | COLLECTION_DISABLED,
+ .flag_render = COLLECTION_SELECTABLE | COLLECTION_DISABLED
+ }
+ };
+
+ for (int layer = 0; layer < 20; layer++) {
+ for (Base *base = scene->base.first; base; base = base->next) {
+ if (base->lay & (1 << layer)) {
+ int collection_index = -1;
+ if ((base->object->restrictflag & OB_RESTRICT_VIEW) &&
+ (base->object->restrictflag & OB_RESTRICT_RENDER))
+ {
+ collection_index = DO_VERSION_COLLECTION_HIDE_ALL;
+ }
+ else if (base->object->restrictflag & OB_RESTRICT_VIEW) {
+ collection_index = DO_VERSION_COLLECTION_HIDE;
+ }
+ else if (base->object->restrictflag & OB_RESTRICT_RENDER) {
+ collection_index = DO_VERSION_COLLECTION_HIDE_RENDER;
+ }
+ else {
+ collection_index = DO_VERSION_COLLECTION_VISIBLE;
+ }
+
+ /* Create collections when needed only. */
+ if ((collections[collection_index].created & (1 << layer)) == 0) {
+ char name[MAX_NAME];
+
+ if ((collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) == 0) {
+ BLI_snprintf(name,
+ sizeof(sc_master->name),
+ "Collection %d%s",
+ layer + 1,
+ collections[DO_VERSION_COLLECTION_VISIBLE].suffix);
+ collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer] =
+ BKE_collection_add(&scene->id, sc_master, COLLECTION_TYPE_NONE, name);
+ collections[DO_VERSION_COLLECTION_VISIBLE].created |= (1 << layer);
+ }
+
+ if (collection_index != DO_VERSION_COLLECTION_VISIBLE) {
+ SceneCollection *sc_parent;
+ sc_parent = collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer];
+ BLI_snprintf(name,
+ sizeof(sc_master->name),
+ "Collection %d%s",
+ layer + 1,
+ collections[collection_index].suffix);
+ collections[collection_index].collections[layer] = BKE_collection_add(
+ &scene->id,
+ sc_parent,
+ COLLECTION_TYPE_NONE,
+ name);
+ collections[collection_index].created |= (1 << layer);
+ }
+ }
+
+ BKE_collection_object_add(
+ &scene->id, collections[collection_index].collections[layer], base->object);
+ }
+
+ if (base->flag & SELECT) {
+ base->object->flag |= SELECT;
+ }
+ else {
+ base->object->flag &= ~SELECT;
+ }
+ }
+ }
+
+ /* Re-order the nested hidden collections. */
+ SceneCollection *scene_collection_parent = sc_master->scene_collections.first;
+
+ for (int layer = 0; layer < 20; layer++) {
+ if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) {
+
+ if ((collections[DO_VERSION_COLLECTION_HIDE].created & (1 << layer)) &&
+ (collections[DO_VERSION_COLLECTION_HIDE].collections[layer] !=
+ scene_collection_parent->scene_collections.first))
+ {
+ BLI_listbase_swaplinks(
+ &scene_collection_parent->scene_collections,
+ collections[DO_VERSION_COLLECTION_HIDE].collections[layer],
+ scene_collection_parent->scene_collections.first);
+ }
+
+ if ((collections[DO_VERSION_COLLECTION_HIDE_ALL].created & (1 << layer)) &&
+ (collections[DO_VERSION_COLLECTION_HIDE_ALL].collections[layer] !=
+ scene_collection_parent->scene_collections.last))
+ {
+ BLI_listbase_swaplinks(
+ &scene_collection_parent->scene_collections,
+ collections[DO_VERSION_COLLECTION_HIDE_ALL].collections[layer],
+ scene_collection_parent->scene_collections.last);
+ }
+
+ scene_collection_parent = scene_collection_parent->next;
+ }
+ }
+ BLI_assert(scene_collection_parent == NULL);
+
+ scene->active_view_layer = 0;
+
+ /* Handle legacy render layers. */
+ if (!BKE_scene_uses_blender_game(scene)) {
+ for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
+
+ ViewLayer *view_layer = BKE_view_layer_add(scene, srl->name);
+
+ if (srl->samples != 0) {
+ /* It is up to the external engine to handle
+ * its own doversion in this case. */
+ BKE_override_view_layer_int_add(
+ view_layer,
+ ID_SCE,
+ "samples",
+ srl->samples);
+ }
+
+ if (srl->mat_override) {
+ BKE_override_view_layer_datablock_add(
+ view_layer,
+ ID_MA,
+ "self",
+ (ID *)srl->mat_override);
+ }
+
+ if (srl->layflag & SCE_LAY_DISABLE) {
+ view_layer->flag &= ~VIEW_LAYER_RENDER;
+ }
+
+ if ((srl->layflag & SCE_LAY_FRS) == 0) {
+ view_layer->flag &= ~VIEW_LAYER_FREESTYLE;
+ }
+
+ /* XXX If we are to keep layflag it should be merged with flag (dfelinto). */
+ view_layer->layflag = srl->layflag;
+ /* XXX Not sure if we should keep the passes (dfelinto). */
+ view_layer->passflag = srl->passflag;
+ view_layer->pass_xor = srl->pass_xor;
+ view_layer->pass_alpha_threshold = srl->pass_alpha_threshold;
+
+ BKE_freestyle_config_free(&view_layer->freestyle_config);
+ view_layer->freestyle_config = srl->freestyleConfig;
+ view_layer->id_properties = srl->prop;
+
+ /* unlink master collection */
+ BKE_collection_unlink(view_layer, view_layer->layer_collections.first);
+
+ /* Add new collection bases. */
+ for (int layer = 0; layer < 20; layer++) {
+ if ((scene->lay & srl->lay & ~(srl->lay_exclude) & (1 << layer)) ||
+ (srl->lay_zmask & (scene->lay | srl->lay_exclude) & (1 << layer)))
+ {
+ if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) {
+
+ LayerCollection *layer_collection_parent;
+ layer_collection_parent = BKE_collection_link(
+ view_layer,
+ collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer]);
+
+ if (srl->lay_zmask & (1 << layer)) {
+ BKE_override_layer_collection_boolean_add(
+ layer_collection_parent,
+ ID_OB,
+ "cycles.is_holdout",
+ true);
+ }
+
+ if ((srl->lay & (1 << layer)) == 0) {
+ BKE_override_layer_collection_boolean_add(
+ layer_collection_parent,
+ ID_OB,
+ "cycles_visibility.camera",
+ false);
+ }
+
+ LayerCollection *layer_collection_child;
+ layer_collection_child = layer_collection_parent->layer_collections.first;
+
+ for (int j = 1; j < 4; j++) {
+ if (collections[j].created & (1 << layer)) {
+ layer_collection_child->flag =
+ collections[j].flag_render & (~COLLECTION_DISABLED);
+
+ if (collections[j].flag_render & COLLECTION_DISABLED) {
+ BKE_collection_disable(view_layer, layer_collection_child);
+ }
+
+ layer_collection_child = layer_collection_child->next;
+ }
+ }
+ BLI_assert(layer_collection_child == NULL);
+ }
+ }
+ }
+
+ /* for convenience set the same active object in all the layers */
+ if (scene->basact) {
+ view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object);
+ }
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) && (base->object->flag & SELECT)) {
+ base->flag |= BASE_SELECTED;
+ }
+ }
+ }
+
+ if (BLI_findlink(&scene->view_layers, scene->r.actlay)) {
+ scene->active_view_layer = scene->r.actlay;
+ }
+ }
+ else {
+ for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
+ if (srl->prop) {
+ IDP_FreeProperty(srl->prop);
+ MEM_freeN(srl->prop);
+ }
+ BKE_freestyle_config_free(&srl->freestyleConfig);
+ }
+ }
+ BLI_freelistN(&scene->r.layers);
+
+ ViewLayer *view_layer = BKE_view_layer_add(scene, "Viewport");
+ /* If we ported all the original render layers, we don't need to make the viewport layer renderable. */
+ if (!BLI_listbase_is_single(&scene->view_layers)) {
+ view_layer->flag &= ~VIEW_LAYER_RENDER;
+ }
+
+ /* If layer was not set, disable it. */
+ LayerCollection *layer_collection_parent;
+ layer_collection_parent =
+ ((LayerCollection *)view_layer->layer_collections.first)->layer_collections.first;
+
+ for (int layer = 0; layer < 20; layer++) {
+ if (collections[DO_VERSION_COLLECTION_VISIBLE].created & (1 << layer)) {
+ const bool is_disabled = (scene->lay & (1 << layer)) == 0;
+
+ /* We only need to disable the parent collection. */
+ if (is_disabled) {
+ BKE_collection_disable(view_layer, layer_collection_parent);
+ }
+
+ LayerCollection *layer_collection_child;
+ layer_collection_child = layer_collection_parent->layer_collections.first;
+
+ for (int j = 1; j < 4; j++) {
+ if (collections[j].created & (1 << layer)) {
+ layer_collection_child->flag = collections[j].flag_viewport & (~COLLECTION_DISABLED);
+
+ if (collections[j].flag_viewport & COLLECTION_DISABLED) {
+ BKE_collection_disable(view_layer, layer_collection_child);
+ }
+ layer_collection_child = layer_collection_child->next;
+ }
+ }
+ BLI_assert(layer_collection_child == NULL);
+ layer_collection_parent = layer_collection_parent->next;
+ }
+ }
+ BLI_assert(layer_collection_parent == NULL);
+
+ /* convert active base */
+ if (scene->basact) {
+ view_layer->basact = BKE_view_layer_base_find(view_layer, scene->basact->object);
+ }
+
+ /* convert selected bases */
+ for (Base *base = scene->base.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) && (base->object->flag & SELECT)) {
+ base->flag |= BASE_SELECTED;
+ }
+
+ /* keep lay around for forward compatibility (open those files in 2.79) */
+ base->lay = base->object->lay;
+ }
+
+ /* Fallback name if only one layer was found in the original file */
+ if (BLI_listbase_is_single(&sc_master->scene_collections)) {
+ BKE_collection_rename(scene, sc_master->scene_collections.first, "Default Collection");
+ }
+
+ /* 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;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
+ for (bScreen *screen = main->screen.first; screen; screen = screen->id.next) {
+ /* same render-layer as do_version_workspaces_after_lib_link will activate,
+ * so same layer as BKE_view_layer_from_workspace_get would return */
+ ViewLayer *layer = screen->scene->view_layers.first;
+
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *view_layer = sa->spacedata.first; view_layer; view_layer = view_layer->next) {
+ if (view_layer->spacetype == SPACE_OUTLINER) {
+ SpaceOops *soutliner = (SpaceOops *)view_layer;
+
+ soutliner->outlinevis = SO_ACT_LAYER;
+
+ if (BLI_listbase_count_ex(&layer->layer_collections, 2) == 1) {
+ if (soutliner->treestore == NULL) {
+ soutliner->treestore = BLI_mempool_create(
+ sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER);
+ }
+
+ /* Create a tree store element for the collection. This is normally
+ * done in check_persistent (outliner_tree.c), but we need to access
+ * it here :/ (expand element if it's the only one) */
+ TreeStoreElem *tselem = BLI_mempool_calloc(soutliner->treestore);
+ tselem->type = TSE_LAYER_COLLECTION;
+ tselem->id = layer->layer_collections.first;
+ tselem->nr = tselem->used = 0;
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* New workspace design */
+ if (!MAIN_VERSION_ATLEAST(main, 280, 1)) {
+ do_version_workspaces_after_lib_link(main);
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 280, 2)) {
+ /* Cleanup any remaining SceneRenderLayer data for files that were created
+ * with Blender 2.8 before the SceneRenderLayer > RenderLayer refactor. */
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
+ if (srl->prop) {
+ IDP_FreeProperty(srl->prop);
+ MEM_freeN(srl->prop);
+ }
+ BKE_freestyle_config_free(&srl->freestyleConfig);
+ }
+ BLI_freelistN(&scene->r.layers);
+ }
+ }
+
+ {
+ for (WorkSpace *workspace = main->workspaces.first; workspace; workspace = workspace->id.next) {
+ if (workspace->view_layer) {
+ /* During 2.8 work we temporarly stored view-layer in the
+ * workspace directly, but should be stored there per-scene. */
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ if (BLI_findindex(&scene->view_layers, workspace->view_layer) != -1) {
+ BKE_workspace_view_layer_set(workspace, workspace->view_layer, scene);
+ workspace->view_layer = NULL;
+ }
+ }
+ }
+ BLI_assert(workspace->view_layer == NULL);
+ }
+ }
+
+ {
+ /* Since we don't have access to FileData we check the (always valid) master collection of the group. */
+ for (Group *group = main->group.first; group; group = group->id.next) {
+ if (group->collection == NULL) {
+ BKE_group_init(group);
+ SceneCollection *sc = GROUP_MASTER_COLLECTION(group);
+ SceneCollection *sc_hidden = NULL;
+
+ for (GroupObject *go = group->gobject.first; go; go = go->next) {
+ if (go->ob->lay & group->layer) {
+ BKE_collection_object_add(&group->id, sc, go->ob);
+ }
+ else {
+ if (sc_hidden == NULL) {
+ sc_hidden = BKE_collection_add(&group->id, sc, COLLECTION_TYPE_GROUP_INTERNAL, "Hidden");
+ }
+ BKE_collection_object_add(&group->id, sc_hidden, go->ob);
+ }
+ }
+
+ if (sc_hidden != NULL) {
+ LayerCollection *layer_collection_master, *layer_collection_hidden;
+
+ layer_collection_master = group->view_layer->layer_collections.first;
+ layer_collection_hidden = layer_collection_master->layer_collections.first;
+
+ layer_collection_hidden->flag &= ~COLLECTION_VISIBLE;
+ }
+ }
+
+ GroupObject *go;
+ while ((go = BLI_pophead(&group->gobject))) {
+ MEM_freeN(go);
+ }
+ }
+ }
+}
+
+static void do_version_layer_collections_idproperties(ListBase *lb)
+{
+ IDPropertyTemplate val = {0};
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ lc->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_layer_collection_engine_settings_create(lc->properties);
+
+ /* No overrides at first */
+ for (IDProperty *prop = lc->properties->data.group.first; prop; prop = prop->next) {
+ while (prop->data.group.first) {
+ IDP_FreeFromGroup(prop, prop->data.group.first);
+ }
+ }
+
+ /* Do it recursively */
+ do_version_layer_collections_idproperties(&lc->layer_collections);
+ }
+}
+
+void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
+{
+
+ if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ if (STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER)) {
+#ifdef WITH_CLAY_ENGINE
+ BLI_strncpy(scene->r.engine, RE_engine_id_BLENDER_CLAY, sizeof(scene->r.engine));
+#else
+ BLI_strncpy(scene->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(scene->r.engine));
+#endif
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "view_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));
+ }
+ }
+
+ if (DNA_struct_elem_find(fd->filesdna, "LayerCollection", "ListBase", "engine_settings") &&
+ !DNA_struct_elem_find(fd->filesdna, "LayerCollection", "IDProperty", "properties"))
+ {
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ do_version_layer_collections_idproperties(&view_layer->layer_collections);
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 280, 1)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "bleedexp")) {
+ for (Lamp *la = main->lamp.first; la; la = la->id.next) {
+ la->bleedexp = 2.5f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "GPUDOFSettings", "float", "ratio")) {
+ for (Camera *ca = main->camera.first; ca; ca = ca->id.next) {
+ ca->gpu_dof.ratio = 1.0f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "ViewLayer", "IDProperty", "*properties")) {
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ IDPropertyTemplate val = {0};
+ view_layer->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_view_layer_engine_settings_create(view_layer->properties);
+ }
+ }
+ }
+
+ /* MTexPoly now removed. */
+ if (DNA_struct_find(fd->filesdna, "MTexPoly")) {
+ const int cd_mtexpoly = 15; /* CD_MTEXPOLY, deprecated */
+ for (Mesh *me = main->mesh.first; me; me = me->id.next) {
+ /* If we have UV's, so this file will have MTexPoly layers too! */
+ if (me->mloopuv != NULL) {
+ CustomData_update_typemap(&me->pdata);
+ CustomData_free_layers(&me->pdata, cd_mtexpoly, me->totpoly);
+ BKE_mesh_update_customdata_pointers(me, false);
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 280, 2)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "View3D", "short", "custom_orientation_index")) {
+ for (bScreen *screen = main->screen.first; screen; screen = screen->id.next) {
+ for (ScrArea *area = screen->areabase.first; area; area = area->next) {
+ for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ if (v3d->twmode >= V3D_MANIP_CUSTOM) {
+ v3d->custom_orientation_index = v3d->twmode - V3D_MANIP_CUSTOM;
+ v3d->twmode = V3D_MANIP_CUSTOM;
+ }
+ else {
+ v3d->custom_orientation_index = -1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "cascade_max_dist")) {
+ for (Lamp *la = main->lamp.first; la; la = la->id.next) {
+ la->cascade_max_dist = 1000.0f;
+ la->cascade_count = 4;
+ la->cascade_exponent = 0.8f;
+ la->cascade_fade = 0.1f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "contact_dist")) {
+ for (Lamp *la = main->lamp.first; la; la = la->id.next) {
+ la->contact_dist = 1.0f;
+ la->contact_bias = 0.03f;
+ la->contact_spread = 0.2f;
+ la->contact_thickness = 0.5f;
+ }
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "LightProbe", "float", "vis_bias")) {
+ for (LightProbe *probe = main->lightprobe.first; probe; probe = probe->id.next) {
+ probe->vis_bias = 1.0f;
+ probe->vis_blur = 0.2f;
+ }
+ }
+
+ typedef enum eNTreeDoVersionErrors {
+ NTREE_DOVERSION_NO_ERROR = 0,
+ NTREE_DOVERSION_NEED_OUTPUT = (1 << 0),
+ NTREE_DOVERSION_TRANSPARENCY_EMISSION = (1 << 1),
+ } eNTreeDoVersionErrors;
+
+ /* Eevee shader nodes renamed because of the output node system.
+ * Note that a new output node is not being added here, because it would be overkill
+ * to handle this case in lib_verify_nodetree.
+ *
+ * Also, metallic node is now unified into the principled node. */
+ eNTreeDoVersionErrors error = NTREE_DOVERSION_NO_ERROR;
+
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == 194 /* SH_NODE_EEVEE_METALLIC */ &&
+ STREQ(node->idname, "ShaderNodeOutputMetallic"))
+ {
+ BLI_strncpy(node->idname, "ShaderNodeEeveeMetallic", sizeof(node->idname));
+ error |= NTREE_DOVERSION_NEED_OUTPUT;
+ }
+
+ else if (node->type == SH_NODE_EEVEE_SPECULAR && STREQ(node->idname, "ShaderNodeOutputSpecular")) {
+ BLI_strncpy(node->idname, "ShaderNodeEeveeSpecular", sizeof(node->idname));
+ error |= NTREE_DOVERSION_NEED_OUTPUT;
+ }
+
+ else if (node->type == 196 /* SH_NODE_OUTPUT_EEVEE_MATERIAL */ &&
+ STREQ(node->idname, "ShaderNodeOutputEeveeMaterial"))
+ {
+ node->type = SH_NODE_OUTPUT_MATERIAL;
+ BLI_strncpy(node->idname, "ShaderNodeOutputMaterial", sizeof(node->idname));
+ }
+
+ else if (node->type == 194 /* SH_NODE_EEVEE_METALLIC */ &&
+ STREQ(node->idname, "ShaderNodeEeveeMetallic"))
+ {
+ node->type = SH_NODE_BSDF_PRINCIPLED;
+ BLI_strncpy(node->idname, "ShaderNodeBsdfPrincipled", sizeof(node->idname));
+ node->custom1 = SHD_GLOSSY_MULTI_GGX;
+ error |= NTREE_DOVERSION_TRANSPARENCY_EMISSION;
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+
+ if (error & NTREE_DOVERSION_NEED_OUTPUT) {
+ BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console");
+ printf("You need to connect Principled and Eevee Specular shader nodes to new material output nodes.\n");
+ }
+
+ if (error & NTREE_DOVERSION_TRANSPARENCY_EMISSION) {
+ BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console");
+ printf("You need to combine transparency and emission shaders to the converted Principled shader nodes.\n");
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "Scene", "ViewRender", "view_render")) {
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ BLI_strncpy_utf8(scene->view_render.engine_id, scene->r.engine,
+ sizeof(scene->view_render.engine_id));
+ }
+
+ for (WorkSpace *workspace = main->workspaces.first; workspace; workspace = workspace->id.next) {
+ BKE_viewrender_init(&workspace->view_render);
+ }
+ }
+
+ if ((DNA_struct_elem_find(fd->filesdna, "ViewLayer", "FreestyleConfig", "freestyle_config") == false) &&
+ DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "view_layers"))
+ {
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ ViewLayer *view_layer;
+ for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ view_layer->flag |= VIEW_LAYER_FREESTYLE;
+ view_layer->layflag = 0x7FFF; /* solid ztra halo edge strand */
+ view_layer->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
+ view_layer->pass_alpha_threshold = 0.5f;
+ BKE_freestyle_config_init(&view_layer->freestyle_config);
+ }
+ }
+ }
+ }
+}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 3d3e73eb470..e2d4b140311 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -28,6 +28,7 @@
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_string.h"
#include "DNA_brush_types.h"
#include "DNA_freestyle_types.h"
@@ -39,10 +40,13 @@
#include "DNA_mesh_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
+#include "DNA_workspace_types.h"
#include "BKE_brush.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_scene.h"
+#include "BKE_workspace.h"
#include "BLO_readfile.h"
@@ -86,17 +90,46 @@ void BLO_update_defaults_userpref_blend(void)
}
/**
+ * New workspace design: Remove all screens/workspaces except of "Default" one and rename the workspace to "General".
+ * For compatibility, a new workspace has been created for each screen of old files,
+ * we only want one workspace and one screen in the default startup file however.
+ */
+static void update_defaults_startup_workspaces(Main *bmain)
+{
+ WorkSpace *workspace_default = NULL;
+
+ for (WorkSpace *workspace = bmain->workspaces.first, *workspace_next; workspace; workspace = workspace_next) {
+ workspace_next = workspace->id.next;
+
+ if (STREQ(workspace->id.name + 2, "Default")) {
+ /* don't rename within iterator, renaming causes listbase to be re-sorted */
+ workspace_default = workspace;
+ BKE_viewrender_init(&workspace->view_render);
+ }
+ else {
+ BKE_workspace_remove(bmain, workspace);
+ }
+ }
+
+ /* rename "Default" workspace to "General" */
+ BKE_libblock_rename(bmain, (ID *)workspace_default, "General");
+ BLI_assert(BLI_listbase_count(BKE_workspace_layouts_get(workspace_default)) == 1);
+}
+
+/**
* Update defaults in startup.blend, without having to save and embed the file.
* This function can be emptied each time the startup.blend is updated. */
void BLO_update_defaults_startup_blend(Main *bmain)
{
for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ BLI_strncpy(scene->view_render.engine_id, RE_engine_id_BLENDER_EEVEE, sizeof(scene->view_render.engine_id));
+
scene->r.im_format.planes = R_IMF_PLANES_RGBA;
scene->r.im_format.compress = 15;
- for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
- srl->freestyleConfig.sphere_radius = 0.1f;
- srl->pass_alpha_threshold = 0.5f;
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ view_layer->freestyle_config.sphere_radius = 0.1f;
+ view_layer->pass_alpha_threshold = 0.5f;
}
if (scene->toolsettings) {
@@ -191,20 +224,18 @@ void BLO_update_defaults_startup_blend(Main *bmain)
linestyle->chain_count = 10;
}
- for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
- ScrArea *area;
- for (area = screen->areabase.first; area; area = area->next) {
- SpaceLink *space_link;
- ARegion *ar;
+ update_defaults_startup_workspaces(bmain);
- for (space_link = area->spacedata.first; space_link; space_link = space_link->next) {
+ for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
+ for (ScrArea *area = screen->areabase.first; area; area = area->next) {
+ for (SpaceLink *space_link = area->spacedata.first; space_link; space_link = space_link->next) {
if (space_link->spacetype == SPACE_CLIP) {
SpaceClip *space_clip = (SpaceClip *) space_link;
space_clip->flag &= ~SC_MANUAL_CALIBRATION;
}
}
- for (ar = area->regionbase.first; ar; ar = ar->next) {
+ for (ARegion *ar = area->regionbase.first; ar; ar = ar->next) {
/* Remove all stored panels, we want to use defaults (order, open/closed) as defined by UI code here! */
BLI_freelistN(&ar->panels);
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index ad37679800b..156a6e3d1c0 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -319,55 +319,6 @@ static void idproperties_fix_group_lengths(ListBase idlist)
}
}
-static void alphasort_version_246(FileData *fd, Library *lib, Mesh *me)
-{
- Material *ma;
- MFace *mf;
- MTFace *tf;
- int a, b, texalpha;
-
- /* verify we have a tface layer */
- for (b = 0; b < me->fdata.totlayer; b++)
- if (me->fdata.layers[b].type == CD_MTFACE)
- break;
-
- if (b == me->fdata.totlayer)
- return;
-
- /* if we do, set alpha sort if the game engine did it before */
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- if (mf->mat_nr < me->totcol) {
- ma = blo_do_versions_newlibadr(fd, lib, me->mat[mf->mat_nr]);
- texalpha = 0;
-
- /* we can't read from this if it comes from a library,
- * because direct_link might not have happened on it,
- * so ma->mtex is not pointing to valid memory yet */
- if (ma && ma->id.lib)
- ma = NULL;
-
- for (b = 0; ma && b < MAX_MTEX; b++)
- if (ma->mtex[b] && ma->mtex[b]->mapto & MAP_ALPHA)
- texalpha = 1;
- }
- else {
- ma = NULL;
- texalpha = 0;
- }
-
- for (b = 0; b < me->fdata.totlayer; b++) {
- if (me->fdata.layers[b].type == CD_MTFACE) {
- tf = ((MTFace*)me->fdata.layers[b].data) + a;
-
- tf->mode &= ~TF_ALPHASORT;
- if (ma && (ma->mode & MA_ZTRANSP))
- if (ELEM(tf->transp, TF_ALPHA, TF_ADD) || (texalpha && (tf->transp != TF_CLIP)))
- tf->mode |= TF_ALPHASORT;
- }
- }
- }
-}
-
static void customdata_version_242(Mesh *me)
{
CustomDataLayer *layer;
@@ -403,13 +354,6 @@ static void customdata_version_242(Mesh *me)
for (a = 0; a < me->totface; a++, mtf++, tf++, mcol += 4) {
memcpy(mcol, tf->col, sizeof(tf->col));
memcpy(mtf->uv, tf->uv, sizeof(tf->uv));
-
- mtf->flag = tf->flag;
- mtf->unwrap = tf->unwrap;
- mtf->mode = tf->mode;
- mtf->tile = tf->tile;
- mtf->tpage = tf->tpage;
- mtf->transp = tf->transp;
}
MEM_freeN(me->tface);
@@ -916,23 +860,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
}
- if (main->versionfile <= 196) {
- Mesh *me = main->mesh.first;
- int a, b;
- while (me) {
- if (me->tface) {
- TFace *tface = me->tface;
- for (a = 0; a < me->totface; a++, tface++) {
- for (b = 0; b < 4; b++) {
- tface->mode |= TF_DYNAMIC;
- tface->mode &= ~TF_INVISIBLE;
- }
- }
- }
- me = me->id.next;
- }
- }
-
if (main->versionfile <= 200) {
Object *ob = main->object.first;
while (ob) {
@@ -1944,7 +1871,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
BKE_pose_tag_recalc(main, ob->pose);
/* cannot call stuff now (pointers!), done in setup_app_data */
- ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
+ ob->id.tag |= LIB_TAG_ID_RECALC_ALL;
/* new generic xray option */
arm = blo_do_versions_newlibadr(fd, lib, ob->data);
@@ -2218,18 +2145,16 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
if (sce->r.yparts < 2)
sce->r.yparts = 4;
- /* adds default layer */
- if (BLI_listbase_is_empty(&sce->r.layers)) {
- BKE_scene_add_render_layer(sce, NULL);
- }
- else {
- SceneRenderLayer *srl;
- /* new layer flag for sky, was default for solid */
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- if (srl->layflag & SCE_LAY_SOLID)
- srl->layflag |= SCE_LAY_SKY;
- srl->passflag &= (SCE_PASS_COMBINED|SCE_PASS_Z|SCE_PASS_NORMAL|SCE_PASS_VECTOR);
- }
+ /* We don't add default layer since blender2.8 because the layers
+ * are now in Scene->view_layers and a default layer is created in
+ * the doversion later on.
+ */
+ SceneRenderLayer *srl;
+ /* new layer flag for sky, was default for solid */
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ if (srl->layflag & SCE_LAY_SOLID)
+ srl->layflag |= SCE_LAY_SKY;
+ srl->passflag &= (SCE_PASS_COMBINED|SCE_PASS_Z|SCE_PASS_NORMAL|SCE_PASS_VECTOR);
}
/* node version changes */
@@ -2529,13 +2454,8 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
for (sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_IMAGE)
+ if (sl->spacetype == SPACE_IMAGE) {
((SpaceImage *)sl)->iuser.fie_ima = 2;
- else if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- BGpic *bgpic;
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next)
- bgpic->iuser.fie_ima = 2;
}
}
}
@@ -3290,14 +3210,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
}
-
- if (main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)) {
- Mesh *me;
-
- for (me = main->mesh.first; me; me = me->id.next)
- alphasort_version_246(fd, lib, me);
- }
-
if (main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)) {
Object *ob;
for (ob = main->object.first; ob; ob = ob->id.next) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index d7d2dd529f9..dffbb88f708 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -102,6 +102,10 @@
/* allow writefile to use deprecated functionality (for forward compatibility code) */
#define DNA_DEPRECATED_ALLOW
+/* Allow using DNA struct members that are marked as private for read/write.
+ * Note: Each header that uses this needs to define its own way of handling
+ * it. There's no generic implementation, direct use does nothing. */
+#define DNA_PRIVATE_READ_WRITE_ALLOW
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -120,6 +124,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"
@@ -130,6 +135,7 @@
#include "DNA_object_force.h"
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_property_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -146,6 +152,7 @@
#include "DNA_vfont_types.h"
#include "DNA_world_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
@@ -161,8 +168,10 @@
#include "BKE_curve.h"
#include "BKE_constraint.h"
#include "BKE_global.h" // for G
+#include "BKE_group.h"
#include "BKE_idcode.h"
#include "BKE_library.h" // for set_listbasepointers
+#include "BKE_library_override.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_report.h"
@@ -172,6 +181,7 @@
#include "BKE_fcurve.h"
#include "BKE_pointcache.h"
#include "BKE_mesh.h"
+#include "BKE_workspace.h"
#ifdef USE_NODE_COMPAT_CUSTOMNODES
#include "NOD_socket.h" /* for sock->default_value data */
@@ -675,6 +685,25 @@ static void write_iddata(void *wd, const ID *id)
if (id->properties && !ELEM(GS(id->name), ID_WM)) {
IDP_WriteProperty(id->properties, wd);
}
+
+ if (id->override_static) {
+ writestruct(wd, DATA, IDOverrideStatic, 1, id->override_static);
+
+ writelist(wd, DATA, IDOverrideStaticProperty, &id->override_static->properties);
+ for (IDOverrideStaticProperty *op = id->override_static->properties.first; op; op = op->next) {
+ writedata(wd, DATA, strlen(op->rna_path) + 1, op->rna_path);
+
+ writelist(wd, DATA, IDOverrideStaticPropertyOperation, &op->operations);
+ for (IDOverrideStaticPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
+ if (opop->subitem_reference_name) {
+ writedata(wd, DATA, strlen(opop->subitem_reference_name) + 1, opop->subitem_reference_name);
+ }
+ if (opop->subitem_local_name) {
+ writedata(wd, DATA, strlen(opop->subitem_local_name) + 1, opop->subitem_local_name);
+ }
+ }
+ }
+ }
}
static void write_previews(WriteData *wd, const PreviewImage *prv_orig)
@@ -1076,10 +1105,13 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
* Take care using 'use_active_win', since we wont want the currently active window
* to change which scene renders (currently only used for undo).
*/
-static void current_screen_compat(Main *mainvar, bScreen **r_screen, bool use_active_win)
+static void current_screen_compat(
+ Main *mainvar, bool use_active_win,
+ bScreen **r_screen, Scene **r_scene, ViewLayer **r_render_layer)
{
wmWindowManager *wm;
wmWindow *window = NULL;
+ WorkSpace *workspace;
/* find a global current screen in the first open window, to have
* a reasonable default for reading in older versions */
@@ -1103,8 +1135,11 @@ static void current_screen_compat(Main *mainvar, bScreen **r_screen, bool use_ac
window = wm->windows.first;
}
}
+ workspace = (window) ? BKE_workspace_active_get(window->workspace_hook) : NULL;
- *r_screen = (window) ? window->screen : NULL;
+ *r_screen = (window) ? BKE_workspace_active_screen_get(window->workspace_hook) : NULL;
+ *r_scene = (window) ? window->scene : NULL;
+ *r_render_layer = (window) ? BKE_workspace_view_layer_get(workspace, *r_scene) : NULL;
}
typedef struct RenderInfo {
@@ -1120,13 +1155,11 @@ static void write_renderinfo(WriteData *wd, Main *mainvar)
{
bScreen *curscreen;
Scene *sce, *curscene = NULL;
+ ViewLayer *render_layer;
RenderInfo data;
/* XXX in future, handle multiple windows with multiple screens? */
- current_screen_compat(mainvar, &curscreen, false);
- if (curscreen) {
- curscene = curscreen->scene;
- }
+ current_screen_compat(mainvar, false, &curscreen, &curscene, &render_layer);
for (sce = mainvar->scene.first; sce; sce = sce->id.next) {
if (sce->id.lib == NULL && (sce == curscene || (sce->r.scemode & R_BG_RENDER))) {
@@ -1316,9 +1349,13 @@ static void write_particlesettings(WriteData *wd, ParticleSettings *part)
if (dw->ob != NULL) {
dw->index = 0;
if (part->dup_group) { /* can be NULL if lining fails or set to None */
- for (GroupObject *go = part->dup_group->gobject.first;
- go && go->ob != dw->ob;
- go = go->next, dw->index++);
+ FOREACH_GROUP_OBJECT(part->dup_group, object)
+ {
+ if (object != dw->ob) {
+ dw->index++;
+ }
+ }
+ FOREACH_GROUP_OBJECT_END
}
}
writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
@@ -1687,6 +1724,13 @@ static void write_defgroups(WriteData *wd, ListBase *defbase)
}
}
+static void write_fmaps(WriteData *wd, ListBase *fbase)
+{
+ for (bFaceMap *fmap = fbase->first; fmap; fmap = fmap->next) {
+ writestruct(wd, DATA, bFaceMap, 1, fmap);
+ }
+}
+
static void write_modifiers(WriteData *wd, ListBase *modbase)
{
ModifierData *md;
@@ -1724,6 +1768,8 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
SmokeModifierData *smd = (SmokeModifierData *)md;
if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
+ writestruct(wd, DATA, SmokeDomainSettings, 1, smd->domain);
+
if (smd->domain) {
write_pointcaches(wd, &(smd->domain->ptcaches[0]));
@@ -1737,11 +1783,8 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
if (smd->domain->coba) {
writestruct(wd, DATA, ColorBand, 1, smd->domain->coba);
}
- }
- writestruct(wd, DATA, SmokeDomainSettings, 1, smd->domain);
- if (smd->domain) {
/* cleanup the fake pointcache */
BKE_ptcache_free_list(&smd->domain->ptcaches[1]);
smd->domain->point_cache[1] = NULL;
@@ -1891,6 +1934,7 @@ static void write_object(WriteData *wd, Object *ob)
write_pose(wd, ob->pose);
write_defgroups(wd, &ob->defbase);
+ write_fmaps(wd, &ob->fmaps);
write_constraints(wd, &ob->constraints);
write_motionpath(wd, ob->mpath);
@@ -1973,6 +2017,10 @@ static void write_camera(WriteData *wd, Camera *cam)
if (cam->adt) {
write_animdata(wd, cam->adt);
}
+
+ for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
+ writestruct(wd, DATA, CameraBGImage, 1, bgpic);
+ }
}
}
@@ -2123,6 +2171,10 @@ static void write_customdata(
else if (layer->type == CD_GRID_PAINT_MASK) {
write_grid_paint_mask(wd, count, layer->data);
}
+ else if (layer->type == CD_FACEMAP) {
+ const int *layer_data = layer->data;
+ writedata(wd, DATA, sizeof(*layer_data) * count, layer_data);
+ }
else {
CustomData_file_write_info(layer->type, &structname, &structnum);
if (structnum) {
@@ -2537,6 +2589,56 @@ 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_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);
+
+ if (lc->properties) {
+ IDP_WriteProperty(lc->properties, wd);
+ }
+
+ write_layer_collections(wd, &lc->layer_collections);
+ }
+}
+
+static void write_view_layer(WriteData *wd, ViewLayer *view_layer)
+{
+ writestruct(wd, DATA, ViewLayer, 1, view_layer);
+ writelist(wd, DATA, Base, &view_layer->object_bases);
+ if (view_layer->properties) {
+ IDP_WriteProperty(view_layer->properties, wd);
+ }
+
+ if (view_layer->id_properties) {
+ IDP_WriteProperty(view_layer->id_properties, wd);
+ }
+
+ for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) {
+ writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
+ }
+
+ for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) {
+ writestruct(wd, DATA, FreestyleLineSet, 1, fls);
+ }
+ write_layer_collections(wd, &view_layer->layer_collections);
+}
+
static void write_scene(WriteData *wd, Scene *sce)
{
/* write LibData */
@@ -2549,10 +2651,6 @@ static void write_scene(WriteData *wd, Scene *sce)
write_keyingsets(wd, &sce->keyingsets);
/* direct data */
- for (Base *base = sce->base.first; base; base = base->next) {
- writestruct(wd, DATA, Base, 1, base);
- }
-
ToolSettings *tos = sce->toolsettings;
writestruct(wd, DATA, ToolSettings, 1, tos);
if (tos->vpaint) {
@@ -2700,24 +2798,6 @@ static void write_scene(WriteData *wd, Scene *sce)
writestruct(wd, DATA, TimeMarker, 1, marker);
}
- /* writing dynamic list of TransformOrientations to the blend file */
- for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) {
- writestruct(wd, DATA, TransformOrientation, 1, ts);
- }
-
- for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
- writestruct(wd, DATA, SceneRenderLayer, 1, srl);
- if (srl->prop) {
- IDP_WriteProperty(srl->prop, wd);
- }
- for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
- writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
- }
- for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
- writestruct(wd, DATA, FreestyleLineSet, 1, fls);
- }
- }
-
/* writing MultiView to the blend file */
for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) {
writestruct(wd, DATA, SceneRenderView, 1, srv);
@@ -2739,6 +2819,19 @@ static void write_scene(WriteData *wd, Scene *sce)
write_previews(wd, sce->preview);
write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
+ write_scene_collection(wd, sce->collection);
+
+ for (ViewLayer *view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ write_view_layer(wd, view_layer);
+ }
+
+ if (sce->layer_properties) {
+ IDP_WriteProperty(sce->layer_properties, wd);
+ }
+
+ if (sce->collection_properties) {
+ IDP_WriteProperty(sce->collection_properties, wd);
+ }
}
static void write_gpencil(WriteData *wd, bGPdata *gpd)
@@ -2780,8 +2873,16 @@ static void write_windowmanager(WriteData *wd, wmWindowManager *wm)
write_iddata(wd, &wm->id);
for (wmWindow *win = wm->windows.first; win; win = win->next) {
+
+ /* update deprecated screen member (for so loading in 2.7x uses the correct screen) */
+ win->screen = BKE_workspace_active_screen_get(win->workspace_hook);
+
writestruct(wd, DATA, wmWindow, 1, win);
+ writestruct(wd, DATA, WorkSpaceInstanceHook, 1, win->workspace_hook);
writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
+
+ /* data is written, clear deprecated data again */
+ win->screen = NULL;
}
}
@@ -2872,6 +2973,8 @@ static void write_screen(WriteData *wd, bScreen *sc)
writestruct(wd, ID_SCRN, bScreen, 1, sc);
write_iddata(wd, &sc->id);
+ write_previews(wd, sc->preview);
+
/* direct data */
for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) {
writestruct(wd, DATA, ScrVert, 1, sv);
@@ -2918,11 +3021,8 @@ static void write_screen(WriteData *wd, bScreen *sc)
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
- BGpic *bgpic;
writestruct(wd, DATA, View3D, 1, v3d);
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- writestruct(wd, DATA, BGpic, 1, bgpic);
- }
+
if (v3d->localvd) {
writestruct(wd, DATA, View3D, 1, v3d->localvd);
}
@@ -3120,6 +3220,19 @@ static void write_sound(WriteData *wd, bSound *sound)
}
}
+static void write_probe(WriteData *wd, LightProbe *prb)
+{
+ if (prb->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_LP, LightProbe, 1, prb);
+ write_iddata(wd, &prb->id);
+
+ if (prb->adt) {
+ write_animdata(wd, prb->adt);
+ }
+ }
+}
+
static void write_group(WriteData *wd, Group *group)
{
if (group->id.us > 0 || wd->current) {
@@ -3128,10 +3241,8 @@ static void write_group(WriteData *wd, Group *group)
write_iddata(wd, &group->id);
write_previews(wd, group->preview);
-
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- writestruct(wd, DATA, GroupObject, 1, go);
- }
+ write_scene_collection(wd, group->collection);
+ write_view_layer(wd, group->view_layer);
}
}
@@ -3665,6 +3776,18 @@ static void write_cachefile(WriteData *wd, CacheFile *cache_file)
}
}
+static void write_workspace(WriteData *wd, WorkSpace *workspace)
+{
+ ListBase *layouts = BKE_workspace_layouts_get(workspace);
+ ListBase *transform_orientations = BKE_workspace_transform_orientations_get(workspace);
+
+ writestruct(wd, ID_WS, WorkSpace, 1, workspace);
+ writelist(wd, DATA, WorkSpaceLayout, layouts);
+ writelist(wd, DATA, WorkSpaceDataRelation, &workspace->hook_layout_relations);
+ writelist(wd, DATA, WorkSpaceDataRelation, &workspace->scene_viewlayer_relations);
+ writelist(wd, DATA, TransformOrientation, transform_orientations);
+}
+
/* Keep it last of write_foodata functions. */
static void write_libraries(WriteData *wd, Main *main)
{
@@ -3696,6 +3819,8 @@ static void write_libraries(WriteData *wd, Main *main)
/* XXX needs rethink, just like save UI in undo files now - would be nice to append things only for the]
* quit.blend and temp saves */
if (found_one) {
+ /* Not overridable. */
+
writestruct(wd, ID_LI, Library, 1, main->curlib);
write_iddata(wd, &main->curlib->id);
@@ -3734,6 +3859,8 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
const bool is_undo = (wd->current != NULL);
FileGlobal fg;
bScreen *screen;
+ Scene *scene;
+ ViewLayer *render_layer;
char subvstr[8];
/* prevent mem checkers from complaining */
@@ -3741,11 +3868,12 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
memset(fg.filename, 0, sizeof(fg.filename));
memset(fg.build_hash, 0, sizeof(fg.build_hash));
- current_screen_compat(mainvar, &screen, is_undo);
+ current_screen_compat(mainvar, is_undo, &screen, &scene, &render_layer);
/* XXX still remap G */
fg.curscreen = screen;
- fg.curscene = screen ? screen->scene : NULL;
+ fg.curscene = scene;
+ fg.cur_view_layer = render_layer;
/* prevent to save this, is not good convention, and feature with concerns... */
fg.fileflags = (fileflags & ~G_FILE_FLAGS_RUNTIME);
@@ -3827,131 +3955,159 @@ static bool write_file_handle(
* avoid thumbnail detecting changes because of this. */
mywrite_flush(wd);
- ListBase *lbarray[MAX_LIBARRAY];
- int a = set_listbasepointers(mainvar, lbarray);
- while (a--) {
- ID *id = lbarray[a]->first;
+ OverrideStaticStorage *override_storage = !wd->current ? BKE_override_static_operations_store_initialize() : NULL;
- if (id && GS(id->name) == ID_LI) {
- continue; /* Libraries are handled separately below. */
- }
+ /* This outer loop allows to save first datablocks from real mainvar, then the temp ones from override process,
+ * if needed, without duplicating whole code. */
+ Main *bmain = mainvar;
+ do {
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a = set_listbasepointers(bmain, lbarray);
+ while (a--) {
+ ID *id = lbarray[a]->first;
- for (; id; id = id->next) {
- /* We should never attempt to write non-regular IDs (i.e. all kind of temp/runtime ones). */
- BLI_assert((id->tag & (LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT | LIB_TAG_NOT_ALLOCATED)) == 0);
+ if (id && GS(id->name) == ID_LI) {
+ continue; /* Libraries are handled separately below. */
+ }
- switch ((ID_Type)GS(id->name)) {
- case ID_WM:
- write_windowmanager(wd, (wmWindowManager *)id);
- break;
- case ID_SCR:
- write_screen(wd, (bScreen *)id);
- break;
- case ID_MC:
- write_movieclip(wd, (MovieClip *)id);
- break;
- case ID_MSK:
- write_mask(wd, (Mask *)id);
- break;
- case ID_SCE:
- write_scene(wd, (Scene *)id);
- break;
- case ID_CU:
- write_curve(wd, (Curve *)id);
- break;
- case ID_MB:
- write_mball(wd, (MetaBall *)id);
- break;
- case ID_IM:
- write_image(wd, (Image *)id);
- break;
- case ID_CA:
- write_camera(wd, (Camera *)id);
- break;
- case ID_LA:
- write_lamp(wd, (Lamp *)id);
- break;
- case ID_LT:
- write_lattice(wd, (Lattice *)id);
- break;
- case ID_VF:
- write_vfont(wd, (VFont *)id);
- break;
- case ID_KE:
- write_key(wd, (Key *)id);
- break;
- case ID_WO:
- write_world(wd, (World *)id);
- break;
- case ID_TXT:
- write_text(wd, (Text *)id);
- break;
- case ID_SPK:
- write_speaker(wd, (Speaker *)id);
- break;
- case ID_SO:
- write_sound(wd, (bSound *)id);
- break;
- case ID_GR:
- write_group(wd, (Group *)id);
- break;
- case ID_AR:
- write_armature(wd, (bArmature *)id);
- break;
- case ID_AC:
- write_action(wd, (bAction *)id);
- break;
- case ID_OB:
- write_object(wd, (Object *)id);
- break;
- case ID_MA:
- write_material(wd, (Material *)id);
- break;
- case ID_TE:
- write_texture(wd, (Tex *)id);
- break;
- case ID_ME:
- write_mesh(wd, (Mesh *)id);
- break;
- case ID_PA:
- write_particlesettings(wd, (ParticleSettings *)id);
- break;
- case ID_NT:
- write_nodetree(wd, (bNodeTree *)id);
- break;
- case ID_BR:
- write_brush(wd, (Brush *)id);
- break;
- case ID_PAL:
- write_palette(wd, (Palette *)id);
- break;
- case ID_PC:
- write_paintcurve(wd, (PaintCurve *)id);
- break;
- case ID_GD:
- write_gpencil(wd, (bGPdata *)id);
- break;
- case ID_LS:
- write_linestyle(wd, (FreestyleLineStyle *)id);
- break;
- case ID_CF:
- write_cachefile(wd, (CacheFile *)id);
- break;
- case ID_LI:
- /* Do nothing, handled below - and should never be reached. */
- BLI_assert(0);
- break;
- case ID_IP:
- /* Do nothing, deprecated. */
- break;
- default:
- /* Should never be reached. */
- BLI_assert(0);
- break;
+ for (; id; id = id->next) {
+ /* We should never attempt to write non-regular IDs (i.e. all kind of temp/runtime ones). */
+ BLI_assert((id->tag & (LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT | LIB_TAG_NOT_ALLOCATED)) == 0);
+
+ const bool do_override = !ELEM(override_storage, NULL, bmain) && id->override_static;
+
+ if (do_override) {
+ BKE_override_static_operations_store_start(override_storage, id);
+ }
+
+ switch ((ID_Type)GS(id->name)) {
+ case ID_WM:
+ write_windowmanager(wd, (wmWindowManager *)id);
+ break;
+ case ID_WS:
+ write_workspace(wd, (WorkSpace *)id);
+ break;
+ case ID_SCR:
+ write_screen(wd, (bScreen *)id);
+ break;
+ case ID_MC:
+ write_movieclip(wd, (MovieClip *)id);
+ break;
+ case ID_MSK:
+ write_mask(wd, (Mask *)id);
+ break;
+ case ID_SCE:
+ write_scene(wd, (Scene *)id);
+ break;
+ case ID_CU:
+ write_curve(wd, (Curve *)id);
+ break;
+ case ID_MB:
+ write_mball(wd, (MetaBall *)id);
+ break;
+ case ID_IM:
+ write_image(wd, (Image *)id);
+ break;
+ case ID_CA:
+ write_camera(wd, (Camera *)id);
+ break;
+ case ID_LA:
+ write_lamp(wd, (Lamp *)id);
+ break;
+ case ID_LT:
+ write_lattice(wd, (Lattice *)id);
+ break;
+ case ID_VF:
+ write_vfont(wd, (VFont *)id);
+ break;
+ case ID_KE:
+ write_key(wd, (Key *)id);
+ break;
+ case ID_WO:
+ write_world(wd, (World *)id);
+ break;
+ case ID_TXT:
+ write_text(wd, (Text *)id);
+ break;
+ case ID_SPK:
+ write_speaker(wd, (Speaker *)id);
+ break;
+ case ID_LP:
+ write_probe(wd, (LightProbe *)id);
+ break;
+ case ID_SO:
+ write_sound(wd, (bSound *)id);
+ break;
+ case ID_GR:
+ write_group(wd, (Group *)id);
+ break;
+ case ID_AR:
+ write_armature(wd, (bArmature *)id);
+ break;
+ case ID_AC:
+ write_action(wd, (bAction *)id);
+ break;
+ case ID_OB:
+ write_object(wd, (Object *)id);
+ break;
+ case ID_MA:
+ write_material(wd, (Material *)id);
+ break;
+ case ID_TE:
+ write_texture(wd, (Tex *)id);
+ break;
+ case ID_ME:
+ write_mesh(wd, (Mesh *)id);
+ break;
+ case ID_PA:
+ write_particlesettings(wd, (ParticleSettings *)id);
+ break;
+ case ID_NT:
+ write_nodetree(wd, (bNodeTree *)id);
+ break;
+ case ID_BR:
+ write_brush(wd, (Brush *)id);
+ break;
+ case ID_PAL:
+ write_palette(wd, (Palette *)id);
+ break;
+ case ID_PC:
+ write_paintcurve(wd, (PaintCurve *)id);
+ break;
+ case ID_GD:
+ write_gpencil(wd, (bGPdata *)id);
+ break;
+ case ID_LS:
+ write_linestyle(wd, (FreestyleLineStyle *)id);
+ break;
+ case ID_CF:
+ write_cachefile(wd, (CacheFile *)id);
+ break;
+ case ID_LI:
+ /* Do nothing, handled below - and should never be reached. */
+ BLI_assert(0);
+ break;
+ case ID_IP:
+ /* Do nothing, deprecated. */
+ break;
+ default:
+ /* Should never be reached. */
+ BLI_assert(0);
+ break;
+ }
+
+ if (do_override) {
+ BKE_override_static_operations_store_end(override_storage, id);
+ }
}
+
+ mywrite_flush(wd);
}
+ } while ((bmain != override_storage) && (bmain = override_storage));
- mywrite_flush(wd);
+ if (override_storage) {
+ BKE_override_static_operations_store_finalize(override_storage);
+ override_storage = NULL;
}
/* Special handling, operating over split Mains... */
diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h
index 1d76077c9f1..ed1993015f6 100644
--- a/source/blender/blentranslation/BLT_translation.h
+++ b/source/blender/blentranslation/BLT_translation.h
@@ -140,6 +140,7 @@ bool BLT_lang_is_ime_supported(void);
#define BLT_I18NCONTEXT_ID_PAINTCURVE "PaintCurve"
#define BLT_I18NCONTEXT_ID_PALETTE "Palette"
#define BLT_I18NCONTEXT_ID_PARTICLESETTINGS "ParticleSettings"
+#define BLT_I18NCONTEXT_ID_LIGHTPROBE "LightProbe"
#define BLT_I18NCONTEXT_ID_SCENE "Scene"
#define BLT_I18NCONTEXT_ID_SCREEN "Screen"
#define BLT_I18NCONTEXT_ID_SEQUENCE "Sequence"
@@ -149,6 +150,7 @@ bool BLT_lang_is_ime_supported(void);
#define BLT_I18NCONTEXT_ID_TEXT "Text"
#define BLT_I18NCONTEXT_ID_VFONT "VFont"
#define BLT_I18NCONTEXT_ID_WORLD "World"
+#define BLT_I18NCONTEXT_ID_WORKSPACE "WorkSpace"
#define BLT_I18NCONTEXT_ID_WINDOWMANAGER "WindowManager"
#define BLT_I18NCONTEXT_ID_MOVIECLIP "MovieClip"
#define BLT_I18NCONTEXT_ID_MASK "Mask"
@@ -194,6 +196,7 @@ typedef struct {
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PAINTCURVE, "id_paintcurve"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PALETTE, "id_palette"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PARTICLESETTINGS, "id_particlesettings"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_LIGHTPROBE, "id_lightprobe"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCENE, "id_scene"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCREEN, "id_screen"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SEQUENCE, "id_sequence"), \
@@ -203,6 +206,7 @@ typedef struct {
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_TEXT, "id_text"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_VFONT, "id_vfont"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WORLD, "id_world"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WORKSPACE, "id_workspace"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "id_windowmanager"), \
{NULL, NULL, NULL} \
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 7787d704b59..6cc1f37db43 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -98,42 +98,6 @@
#include "bmesh.h"
#include "intern/bmesh_private.h" /* for element checking */
-/**
- * Currently this is only used for Python scripts
- * which may fail to keep matching UV/TexFace layers.
- *
- * \note This should only perform any changes in exceptional cases,
- * if we need this to be faster we could inline #BM_data_layer_add and only
- * call #update_data_blocks once at the end.
- */
-void BM_mesh_cd_validate(BMesh *bm)
-{
- int totlayer_mtex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
- int totlayer_uv = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
-
- if (LIKELY(totlayer_mtex == totlayer_uv)) {
- /* pass */
- }
- else if (totlayer_mtex < totlayer_uv) {
- const int uv_index_first = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
- do {
- const char *from_name = bm->ldata.layers[uv_index_first + totlayer_mtex].name;
- BM_data_layer_add_named(bm, &bm->pdata, CD_MTEXPOLY, from_name);
- CustomData_set_layer_unique_name(&bm->pdata, totlayer_mtex);
- } while (totlayer_uv != ++totlayer_mtex);
- }
- else if (totlayer_uv < totlayer_mtex) {
- const int mtex_index_first = CustomData_get_layer_index(&bm->pdata, CD_MTEXPOLY);
- do {
- const char *from_name = bm->pdata.layers[mtex_index_first + totlayer_uv].name;
- BM_data_layer_add_named(bm, &bm->ldata, CD_MLOOPUV, from_name);
- CustomData_set_layer_unique_name(&bm->ldata, totlayer_uv);
- } while (totlayer_mtex != ++totlayer_uv);
- }
-
- BLI_assert(totlayer_mtex == totlayer_uv);
-}
-
void BM_mesh_cd_flag_ensure(BMesh *bm, Mesh *mesh, const char cd_flag)
{
const char cd_flag_all = BM_mesh_cd_flag_from_bmesh(bm) | cd_flag;
@@ -243,7 +207,7 @@ void BM_mesh_bm_from_me(
BMEdge *e, **etable = NULL;
BMFace *f, **ftable = NULL;
float (*keyco)[3] = NULL;
- int totuv, totloops, i;
+ int totloops, i;
if (!me || !me->totvert) {
if (me && is_new) { /*no verts? still copy customdata layout*/
@@ -265,13 +229,6 @@ void BM_mesh_bm_from_me(
CustomData_copy(&me->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
-
- /* make sure uv layer names are consisten */
- totuv = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
- for (i = 0; i < totuv; i++) {
- int li = CustomData_get_layer_index_n(&bm->pdata, CD_MTEXPOLY, i);
- CustomData_set_layer_name(&bm->ldata, CD_MLOOPUV, i, bm->pdata.layers[li].name);
- }
}
/* -------------------------------------------------------------------- */
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index b670f31ad9f..80b57eb3565 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -77,13 +77,13 @@ enum {
/* similar face selection slot values */
enum {
SIMFACE_MATERIAL = 201,
- SIMFACE_IMAGE,
SIMFACE_AREA,
SIMFACE_SIDES,
SIMFACE_PERIMETER,
SIMFACE_NORMAL,
SIMFACE_COPLANAR,
SIMFACE_SMOOTH,
+ SIMFACE_FACEMAP,
#ifdef WITH_FREESTYLE
SIMFACE_FREESTYLE
#endif
diff --git a/source/blender/bmesh/operators/bmo_similar.c b/source/blender/bmesh/operators/bmo_similar.c
index 454d6d8c6c8..0cd17258834 100644
--- a/source/blender/bmesh/operators/bmo_similar.c
+++ b/source/blender/bmesh/operators/bmo_similar.c
@@ -106,11 +106,28 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
const float thresh = BMO_slot_float_get(op->slots_in, "thresh");
const float thresh_radians = thresh * (float)M_PI;
const int compare = BMO_slot_int_get(op->slots_in, "compare");
+ /* for comparison types that use custom-data */
+ int cd_offset = -1;
/* initial_elem - other_elem */
float delta_fl;
int delta_i;
+ if (type == SIMFACE_FACEMAP) {
+ cd_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
+ if (cd_offset == -1) {
+ return;
+ }
+ }
+#ifdef WITH_FREESTYLE
+ else if (type == SIMFACE_FREESTYLE) {
+ cd_offset = CustomData_get_offset(&bm->pdata, CD_FREESTYLE_FACE);
+ if (cd_offset == -1) {
+ return;
+ }
+ }
+#endif
+
num_total = BM_mesh_elem_count(bm, BM_FACE);
/*
@@ -145,7 +162,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
* Save us some computation burden: In case of perimeter/area/coplanar selection we compute
* only once.
*/
- if (type == SIMFACE_PERIMETER || type == SIMFACE_AREA || type == SIMFACE_COPLANAR || type == SIMFACE_IMAGE) {
+ if (type == SIMFACE_PERIMETER || type == SIMFACE_AREA || type == SIMFACE_COPLANAR) {
for (i = 0; i < num_total; i++) {
switch (type) {
case SIMFACE_PERIMETER:
@@ -164,14 +181,6 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
case SIMFACE_AREA:
f_ext[i].area = BM_face_calc_area(f_ext[i].f);
break;
-
- case SIMFACE_IMAGE:
- f_ext[i].t = NULL;
- if (CustomData_has_layer(&(bm->pdata), CD_MTEXPOLY)) {
- MTexPoly *mtpoly = CustomData_bmesh_get(&bm->pdata, f_ext[i].f->head.data, CD_MTEXPOLY);
- f_ext[i].t = mtpoly->tpage;
- }
- break;
}
}
}
@@ -190,14 +199,6 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
cont = false;
}
break;
-
- case SIMFACE_IMAGE:
- if (f_ext[i].t == f_ext[indices[idx]].t) {
- BMO_face_flag_enable(bm, fm, FACE_MARK);
- cont = false;
- }
- break;
-
case SIMFACE_NORMAL:
angle = angle_normalized_v3v3(fs->no, fm->no); /* if the angle between the normals -> 0 */
if (angle <= thresh_radians) {
@@ -254,20 +255,29 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
cont = false;
}
break;
+ case SIMFACE_FACEMAP:
+ {
+ BLI_assert(cd_offset != -1);
+ const int *fmap1 = BM_ELEM_CD_GET_VOID_P(fs, cd_offset);
+ const int *fmap2 = BM_ELEM_CD_GET_VOID_P(fm, cd_offset);
+ if (*fmap1 == *fmap2) {
+ BMO_face_flag_enable(bm, fm, FACE_MARK);
+ cont = false;
+ }
+ break;
+ }
#ifdef WITH_FREESTYLE
case SIMFACE_FREESTYLE:
- if (CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE)) {
- FreestyleEdge *ffa1, *ffa2;
-
- ffa1 = CustomData_bmesh_get(&bm->pdata, fs->head.data, CD_FREESTYLE_FACE);
- ffa2 = CustomData_bmesh_get(&bm->pdata, fm->head.data, CD_FREESTYLE_FACE);
-
- if (ffa1 && ffa2 && (ffa1->flag & FREESTYLE_FACE_MARK) == (ffa2->flag & FREESTYLE_FACE_MARK)) {
- BMO_face_flag_enable(bm, fm, FACE_MARK);
- cont = false;
- }
+ {
+ BLI_assert(cd_offset != -1);
+ const FreestyleEdge *ffa1 = BM_ELEM_CD_GET_VOID_P(fs, cd_offset);
+ const FreestyleEdge *ffa2 = BM_ELEM_CD_GET_VOID_P(fm, cd_offset);
+ if ((ffa1->flag & FREESTYLE_FACE_MARK) == (ffa2->flag & FREESTYLE_FACE_MARK)) {
+ BMO_face_flag_enable(bm, fm, FACE_MARK);
+ cont = false;
}
break;
+ }
#endif
default:
BLI_assert(0);
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 9d1b20cb4d2..82545a5e011 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -81,12 +81,6 @@
/* use accelerated overlap check */
#define USE_BVH
-// #define USE_BOOLEAN_RAYCAST_DRAW
-
-#ifdef USE_BOOLEAN_RAYCAST_DRAW
-/* insert bl_debug_draw_quad_clear... here */
-#endif
-
// #define USE_DUMP
static void tri_v3_scale(
@@ -1006,10 +1000,6 @@ bool BM_mesh_intersect(
int i_a, i_b;
#endif
-#ifdef USE_BOOLEAN_RAYCAST_DRAW
- bl_debug_draw_quad_clear();
-#endif
-
s.bm = bm;
s.edgetri_cache = BLI_ghash_new(BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__);
@@ -1607,17 +1597,6 @@ bool BM_mesh_intersect(
do_flip = (side == 0);
break;
}
-
-#ifdef USE_BOOLEAN_RAYCAST_DRAW
- {
- uint colors[4] = {0x00000000, 0xffffffff, 0xff000000, 0x0000ff};
- float co_other[3] = {UNPACK3(co)};
- co_other[0] += 1000.0f;
- bl_debug_color_set(colors[(hits & 1) == 1]);
- bl_debug_draw_edge_add(co, co_other);
- }
-#endif
-
}
if (do_remove) {
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index d4f434d56fd..6e59a404e47 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -34,10 +34,11 @@ void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
}
}
-bool AnimationExporter::exportAnimations(Scene *sce)
+bool AnimationExporter::exportAnimations(const struct EvaluationContext *eval_ctx, Scene *sce)
{
bool has_animations = hasAnimations(sce);
if (has_animations) {
+ this->eval_ctx = eval_ctx;
this->scene = sce;
openLibrary();
@@ -480,7 +481,7 @@ void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, B
if (flag & ARM_RESTPOS) {
arm->flag &= ~ARM_RESTPOS;
- BKE_pose_where_is(scene, ob_arm);
+ BKE_pose_where_is(eval_ctx, scene, ob_arm);
}
if (fra.size()) {
@@ -489,7 +490,7 @@ void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, B
if (flag & ARM_RESTPOS)
arm->flag = flag;
- BKE_pose_where_is(scene, ob_arm);
+ BKE_pose_where_is(eval_ctx, scene, ob_arm);
}
void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone)
@@ -938,17 +939,17 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
CFRA = BKE_scene_frame_get_from_ctime(scene, *it);
- //BKE_scene_update_for_newframe(G.main->eval_ctx, G.main,scene,scene->lay);
+ //BKE_scene_graph_update_for_newframe(G.main->eval_ctx, depsgraph, G.main,scene);
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
if (bone) {
if (pchan->flag & POSE_CHAIN) {
enable_fcurves(ob->adt->action, NULL);
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(eval_ctx, scene, ob);
}
else {
- BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1);
}
// compute bone local mat
@@ -1438,7 +1439,7 @@ void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bo
// exit rest position
if (flag & ARM_RESTPOS) {
arm->flag &= ~ARM_RESTPOS;
- BKE_pose_where_is(scene, ob_arm);
+ BKE_pose_where_is(eval_ctx, scene, ob_arm);
}
//v array will hold all values which will be exported.
if (fra.size()) {
@@ -1468,7 +1469,7 @@ void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bo
// restore restpos
if (flag & ARM_RESTPOS)
arm->flag = flag;
- BKE_pose_where_is(scene, ob_arm);
+ BKE_pose_where_is(eval_ctx, scene, ob_arm);
}
void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
@@ -1493,7 +1494,7 @@ void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, i
BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
- BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, scene, ob_arm, pchan, ctime, 1);
// compute bone local mat
if (bone->parent) {
@@ -1554,7 +1555,7 @@ void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[
if (obtar) {
BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
- BKE_object_where_is_calc_time(scene, obtar, ctime);
+ BKE_object_where_is_calc_time(eval_ctx, scene, obtar, ctime);
}
}
@@ -1562,7 +1563,7 @@ void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[
cti->flush_constraint_targets(con, &targets, 1);
}
}
- BKE_object_where_is_calc_time(scene, ob, ctime);
+ BKE_object_where_is_calc_time(eval_ctx, scene, ob, ctime);
copy_m4_m4(mat, ob->obmat);
}
diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h
index 4736361ad13..5af5d884455 100644
--- a/source/blender/collada/AnimationExporter.h
+++ b/source/blender/collada/AnimationExporter.h
@@ -79,12 +79,13 @@ extern "C"
#include <vector>
#include <algorithm> // std::find
-
+struct EvaluationContext;
class AnimationExporter: COLLADASW::LibraryAnimations
{
private:
Scene *scene;
+ const struct EvaluationContext *eval_ctx;
COLLADASW::StreamWriter *sw;
public:
@@ -94,7 +95,7 @@ public:
{ this->sw = sw; }
- bool exportAnimations(Scene *sce);
+ bool exportAnimations(const struct EvaluationContext *eval_ctx, Scene *sce);
// called for each exported object
void operator() (Object *ob);
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index bd47ee0214d..5e6fe84d3a9 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -1918,7 +1918,7 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No
job->lay = BKE_scene_base_find(scene, job)->lay = 2;
mul_v3_fl(job->size, 0.5f);
- DAG_id_tag_update(&job->id, OB_RECALC_OB);
+ DEG_id_tag_update(&job->id, OB_RECALC_OB);
verify_adt_action((ID *)&job->id, 1);
@@ -1939,14 +1939,14 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No
if (par_job) {
job->parent = par_job;
- DAG_id_tag_update(&par_job->id, OB_RECALC_OB);
+ DEG_id_tag_update(&par_job->id, OB_RECALC_OB);
job->parsubstr[0] = 0;
}
BKE_object_where_is_calc(scene, job);
// after parenting and layer change
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
joint_objects[node->getUniqueId()] = job;
}
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index d2495a8cb9f..844be2dd60b 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -62,8 +62,8 @@ ArmatureExporter::ArmatureExporter(COLLADASW::StreamWriter *sw, const ExportSett
}
// write bone nodes
-void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce,
- SceneExporter *se,
+void ArmatureExporter::add_armature_bones(const EvaluationContext *eval_ctx, Object *ob_arm,
+ Scene *sce, SceneExporter *se,
std::list<Object *>& child_objects)
{
// write bone nodes
@@ -77,7 +77,7 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce,
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);
+ add_bone_node(eval_ctx, bone, ob_arm, sce, se, child_objects);
}
if (!is_edited) {
@@ -116,10 +116,7 @@ bool ArmatureExporter::add_instance_controller(Object *ob)
write_bone_URLs(ins, ob_arm, bone);
}
- InstanceWriter::add_material_bindings(ins.getBindMaterial(),
- ob,
- this->export_settings->active_uv_only,
- this->export_settings->export_texture_type);
+ InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
ins.add();
return true;
@@ -160,7 +157,7 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O
#endif
// parent_mat is armature-space
-void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
+void ArmatureExporter::add_bone_node(const EvaluationContext *eval_ctx, Bone *bone, Object *ob_arm, Scene *sce,
SceneExporter *se,
std::list<Object *>& child_objects)
{
@@ -234,7 +231,7 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
mul_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv);
}
- se->writeNodes(*i, sce);
+ se->writeNodes(eval_ctx, *i, sce);
copy_m4_m4((*i)->parentinv, backup_parinv);
child_objects.erase(i++);
@@ -243,13 +240,13 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
}
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
- add_bone_node(child, ob_arm, sce, se, child_objects);
+ add_bone_node(eval_ctx, child, ob_arm, sce, se, child_objects);
}
node.end();
}
else {
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
- add_bone_node(child, ob_arm, sce, se, child_objects);
+ add_bone_node(eval_ctx, child, ob_arm, sce, se, child_objects);
}
}
}
diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h
index d271b505aa9..a3ed97c3a43 100644
--- a/source/blender/collada/ArmatureExporter.h
+++ b/source/blender/collada/ArmatureExporter.h
@@ -60,7 +60,7 @@ public:
ArmatureExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
// write bone nodes
- void add_armature_bones(Object *ob_arm, Scene *sce, SceneExporter *se,
+ void add_armature_bones(const struct EvaluationContext *eval_ctx, Object *ob_arm, Scene *sce, SceneExporter *se,
std::list<Object *>& child_objects);
bool add_instance_controller(Object *ob);
@@ -85,7 +85,7 @@ private:
// Scene, SceneExporter and the list of child_objects
// are required for writing bone parented objects
- void add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, SceneExporter *se,
+ void add_bone_node(const struct EvaluationContext *eval_ctx, Bone *bone, Object *ob_arm, Scene *sce, SceneExporter *se,
std::list<Object *>& child_objects);
void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node);
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index 0ea8324ed7c..9c8b8fc25d6 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -34,7 +34,6 @@
extern "C" {
#include "BKE_action.h"
-#include "BKE_depsgraph.h"
#include "BKE_object.h"
#include "BKE_armature.h"
#include "BLI_string.h"
@@ -42,6 +41,8 @@ extern "C" {
#include "ED_armature.h"
}
+#include "DEG_depsgraph.h"
+
#include "collada_utils.h"
#include "ArmatureImporter.h"
@@ -496,7 +497,7 @@ void ArmatureImporter::create_armature_bones(std::vector<Object *> &ob_arms)
ob_arms.push_back(ob_arm);
}
- DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
}
}
@@ -629,7 +630,7 @@ Object *ArmatureImporter::create_armature_bones(SkinInfo& skin)
ED_armature_from_edit(armature);
ED_armature_edit_free(armature);
- DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
return ob_arm;
}
diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt
index 293049a1a05..8642bbee698 100644
--- a/source/blender/collada/CMakeLists.txt
+++ b/source/blender/collada/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../blenkernel
../blenlib
../blentranslation
+ ../depsgraph
../editors/include
../makesdna
../makesrna
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index 5cd5e6d271a..f413651167c 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -98,17 +98,15 @@ bool ControllerExporter::add_instance_controller(Object *ob)
write_bone_URLs(ins, ob_arm, bone);
}
- InstanceWriter::add_material_bindings(ins.getBindMaterial(),
- ob,
- this->export_settings->active_uv_only,
- this->export_settings->export_texture_type);
+ InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
ins.add();
return true;
}
-void ControllerExporter::export_controllers(Scene *sce)
+void ControllerExporter::export_controllers(const struct EvaluationContext *eval_ctx, Scene *sce)
{
+ this->eval_ctx = eval_ctx;
scene = sce;
openLibrary();
@@ -200,7 +198,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
bool use_instantiation = this->export_settings->use_object_instantiation;
Mesh *me;
- me = bc_get_mesh_copy(scene,
+ me = bc_get_mesh_copy(eval_ctx, scene,
ob,
this->export_settings->export_mesh_type,
this->export_settings->apply_modifiers,
@@ -302,7 +300,7 @@ void ControllerExporter::export_morph_controller(Object *ob, Key *key)
bool use_instantiation = this->export_settings->use_object_instantiation;
Mesh *me;
- me = bc_get_mesh_copy(scene,
+ me = bc_get_mesh_copy(eval_ctx, scene,
ob,
this->export_settings->export_mesh_type,
this->export_settings->apply_modifiers,
@@ -497,7 +495,7 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas
// put armature in rest position
if (!(arm->flag & ARM_RESTPOS)) {
arm->flag |= ARM_RESTPOS;
- BKE_pose_where_is(scene, ob_arm);
+ BKE_pose_where_is(eval_ctx, scene, ob_arm);
}
for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
@@ -545,7 +543,7 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas
// back from rest positon
if (!(flag & ARM_RESTPOS)) {
arm->flag = flag;
- BKE_pose_where_is(scene, ob_arm);
+ BKE_pose_where_is(eval_ctx, scene, ob_arm);
}
source.finish();
diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h
index 80b858ca6dd..a1d46c5aafb 100644
--- a/source/blender/collada/ControllerExporter.h
+++ b/source/blender/collada/ControllerExporter.h
@@ -54,6 +54,7 @@
#include "BKE_key.h"
+struct EvaluationContext;
class SceneExporter;
class ControllerExporter : public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter
@@ -65,11 +66,12 @@ public:
bool add_instance_controller(Object *ob);
- void export_controllers(Scene *sce);
+ void export_controllers(const struct EvaluationContext *eval_ctx, Scene *sce);
void operator()(Object *ob);
private:
+ const struct EvaluationContext *eval_ctx;
Scene *scene;
UnitConverter converter;
const ExportSettings *export_settings;
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index 284a6da1a40..ce0c52cdcd1 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -138,8 +138,7 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype);
char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n)
{
int layer_index = CustomData_get_layer_index(data, type);
- if (layer_index < 0)
- return NULL;
+ if (layer_index < 0) return NULL;
return data->layers[layer_index + n].name;
}
@@ -148,10 +147,9 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
{
/* get the layer index of the active layer of type */
int layer_index = CustomData_get_active_layer_index(data, type);
- if (layer_index < 1)
- return NULL;
+ if (layer_index < 0) return NULL;
- return bc_CustomData_get_layer_name(data, type, layer_index-1);
+ return data->layers[layer_index].name;
}
DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) {
@@ -181,7 +179,7 @@ static COLLADABU::NativeString make_temp_filepath(const char *name, const char *
// COLLADA allows this through multiple <channel>s in <animation>.
// For this to work, we need to know objects that use a certain action.
-int DocumentExporter::exportCurrentScene(Scene *sce)
+int DocumentExporter::exportCurrentScene(const EvaluationContext *eval_ctx, Scene *sce)
{
PointerRNA sceneptr, unit_settings;
PropertyRNA *system; /* unused , *scale; */
@@ -287,7 +285,7 @@ int DocumentExporter::exportCurrentScene(Scene *sce)
// <library_geometries>
if (bc_has_object_type(export_set, OB_MESH)) {
GeometryExporter ge(writer, this->export_settings);
- ge.exportGeom(sce);
+ ge.exportGeom(eval_ctx, sce);
}
// <library_controllers>
@@ -295,7 +293,7 @@ int DocumentExporter::exportCurrentScene(Scene *sce)
ControllerExporter controller_exporter(writer, this->export_settings);
if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys)
{
- controller_exporter.export_controllers(sce);
+ controller_exporter.export_controllers(eval_ctx, sce);
}
// <library_visual_scenes>
@@ -308,7 +306,7 @@ int DocumentExporter::exportCurrentScene(Scene *sce)
// <library_animations>
AnimationExporter ae(writer, this->export_settings);
- bool has_animations = ae.exportAnimations(sce);
+ bool has_animations = ae.exportAnimations(eval_ctx, sce);
if (has_animations && this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
// channels adressing <matrix> objects is not (yet) supported
@@ -324,7 +322,7 @@ int DocumentExporter::exportCurrentScene(Scene *sce)
#else
se.setExportTransformationType(this->export_settings->export_transformation_type);
#endif
- se.exportScene(sce);
+ se.exportScene(eval_ctx, sce);
// <scene>
std::string scene_name(translate_id(id_name(sce)));
diff --git a/source/blender/collada/DocumentExporter.h b/source/blender/collada/DocumentExporter.h
index 6e3c1ecd7cd..895787c7bbc 100644
--- a/source/blender/collada/DocumentExporter.h
+++ b/source/blender/collada/DocumentExporter.h
@@ -39,7 +39,7 @@ class DocumentExporter
{
public:
DocumentExporter(const ExportSettings *export_settings);
- int exportCurrentScene(Scene *sce);
+ int exportCurrentScene(const struct EvaluationContext *eval_ctx, Scene *sce);
void exportScenes(const char *filename);
private:
const ExportSettings *export_settings;
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index eada4b2bf98..ec9a4169b26 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -57,11 +57,12 @@ extern "C" {
#include "BLI_fileops.h"
#include "BKE_camera.h"
+#include "BKE_collection.h"
#include "BKE_main.h"
+#include "BKE_layer.h"
#include "BKE_lamp.h"
#include "BKE_library.h"
#include "BKE_fcurve.h"
-#include "BKE_depsgraph.h"
#include "BKE_scene.h"
#include "BKE_global.h"
#include "BKE_material.h"
@@ -81,6 +82,9 @@ extern "C" {
}
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ExtraHandler.h"
#include "ErrorHandler.h"
#include "DocumentImporter.h"
@@ -129,7 +133,7 @@ bool DocumentImporter::import()
loader.registerExtraDataCallbackHandler(ehandler);
// deselect all to select new objects
- BKE_scene_base_deselect_all(CTX_data_scene(mContext));
+ BKE_view_layer_base_deselect_all(CTX_data_view_layer(mContext));
std::string mFilename = std::string(this->import_settings->filepath);
const std::string encodedFilename = bc_url_encode(mFilename);
@@ -229,7 +233,7 @@ void DocumentImporter::finish()
}
// update scene
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL);
}
@@ -240,7 +244,7 @@ void DocumentImporter::finish()
armature_importer.set_tags_map(this->uid_tags_map);
armature_importer.make_armatures(mContext, *objects_to_scale);
armature_importer.make_shape_keys();
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
#if 0
armature_importer.fix_animation();
@@ -262,19 +266,11 @@ void DocumentImporter::finish()
std::vector<Object *>::iterator it;
for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
Object *ob = *it;
-
- Base *base = BKE_scene_base_find(sce, ob);
- if (base) {
- BLI_remlink(&sce->base, base);
- BKE_libblock_free_us(G.main, base->object);
- if (sce->basact == base)
- sce->basact = NULL;
- MEM_freeN(base);
- }
+ BKE_collections_object_remove(G.main, &sce->id, ob, true);
}
libnode_ob.clear();
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
bc_match_scale(objects_to_scale, unit_converter, !this->import_settings->import_units);
@@ -412,8 +408,8 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL);
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);
+ DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ 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 2bf0859b0f0..87392352a48 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -27,6 +27,7 @@
#include <map>
+#include <set>
#include "COLLADASWEffectProfile.h"
#include "COLLADAFWColorOrTexture.h"
@@ -43,21 +44,31 @@ extern "C" {
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
+ #include "BKE_collection.h"
#include "BKE_customdata.h"
#include "BKE_mesh.h"
#include "BKE_material.h"
}
-EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) {
+// OB_MESH is assumed
+static std::string getActiveUVLayerName(Object *ob)
+{
+ Mesh *me = (Mesh *)ob->data;
+
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ if (num_layers)
+ return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
+
+ return "";
}
+EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) {
+}
bool EffectsExporter::hasEffects(Scene *sce)
{
- Base *base = (Base *)sce->base.first;
-
- while (base) {
- Object *ob = base->object;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
int a;
for (a = 0; a < ob->totcol; a++) {
Material *ma = give_current_material(ob, a + 1);
@@ -67,56 +78,20 @@ bool EffectsExporter::hasEffects(Scene *sce)
return true;
}
- base = base->next;
}
+ FOREACH_SCENE_OBJECT_END
return false;
}
void EffectsExporter::exportEffects(Scene *sce)
{
- this->scene = sce;
-
- if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
- if (hasEffects(sce)) {
- MaterialFunctor mf;
- openLibrary();
- mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
- closeLibrary();
- }
- }
- else {
- std::set<Object *> uv_textured_obs = bc_getUVTexturedObjects(sce, !this->export_settings->active_uv_only);
- std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
- if (uv_images.size() > 0) {
- openLibrary();
- std::set<Image *>::iterator uv_images_iter;
- for (uv_images_iter = uv_images.begin();
- uv_images_iter != uv_images.end();
- uv_images_iter++) {
-
- Image *ima = *uv_images_iter;
- std::string key(id_name(ima));
- key = translate_id(key);
- COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
- key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
- key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
- sampler.setImageId(key);
-
- openEffect(key + "-effect");
- COLLADASW::EffectProfile ep(mSW);
- ep.setProfileType(COLLADASW::EffectProfile::COMMON);
- ep.setShaderType(COLLADASW::EffectProfile::PHONG);
- ep.setDiffuse(createTexture(ima, key, &sampler), false, "diffuse");
- COLLADASW::ColorOrTexture cot = getcol(0, 0, 0, 1.0f);
- ep.setSpecular(cot, false, "specular");
- ep.openProfile();
- ep.addProfileElements();
- ep.addExtraTechniques(mSW);
- ep.closeProfile();
- closeEffect();
- }
- closeLibrary();
- }
+ if (hasEffects(sce)) {
+ this->scene = sce;
+ openLibrary();
+ MaterialFunctor mf;
+ mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
+
+ closeLibrary();
}
}
@@ -200,7 +175,8 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
{
// create a list of indices to textures of type TEX_IMAGE
std::vector<int> tex_indices;
- createTextureIndices(ma, tex_indices);
+ if (this->export_settings->include_material_textures)
+ createTextureIndices(ma, tex_indices);
openEffect(translate_id(id_name(ma)) + "-effect");
@@ -336,7 +312,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
// used as fallback when MTex->uvname is "" (this is pretty common)
// it is indeed the correct value to use in that case
- std::string active_uv(bc_get_active_uvlayer_name(ob));
+ std::string active_uv(getActiveUVLayerName(ob));
// write textures
// XXX very slow
diff --git a/source/blender/collada/EffectExporter.h b/source/blender/collada/EffectExporter.h
index 7d45a085777..d20cbfdfe0b 100644
--- a/source/blender/collada/EffectExporter.h
+++ b/source/blender/collada/EffectExporter.h
@@ -48,6 +48,7 @@ class EffectsExporter: COLLADASW::LibraryEffects
public:
EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
void exportEffects(Scene *sce);
+
void operator()(Material *ma, Object *ob);
COLLADASW::ColorOrTexture createTexture(Image *ima,
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index 6d90edd2f67..33a7527f383 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -28,6 +28,7 @@
#define __EXPORTSETTINGS_H__
#include "collada.h"
+#include "collada.h"
struct ExportSettings {
public:
@@ -41,7 +42,7 @@ public:
bool deform_bones_only;
bool active_uv_only;
- BC_export_texture_type export_texture_type;
+ bool include_material_textures;
bool use_texture_copies;
bool triangulate;
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index 8a9ccbbed51..587f30b6eb8 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -52,16 +52,16 @@ extern "C" {
#include "collada_internal.h"
#include "collada_utils.h"
-
// TODO: optimize UV sets by making indexed list with duplicates removed
GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings)
{
}
-void GeometryExporter::exportGeom(Scene *sce)
+void GeometryExporter::exportGeom(const struct EvaluationContext *eval_ctx, Scene *sce)
{
openLibrary();
+ mEvalCtx = eval_ctx;
mScene = sce;
GeometryFunctor gf;
gf.forEachMeshObjectInExportSet<GeometryExporter>(sce, *this, this->export_settings->export_set);
@@ -77,7 +77,7 @@ void GeometryExporter::operator()(Object *ob)
#endif
bool use_instantiation = this->export_settings->use_object_instantiation;
- Mesh *me = bc_get_mesh_copy( mScene,
+ Mesh *me = bc_get_mesh_copy(mEvalCtx, mScene,
ob,
this->export_settings->export_mesh_type,
this->export_settings->apply_modifiers,
@@ -135,22 +135,13 @@ void GeometryExporter::operator()(Object *ob)
// Only create Polylists if number of faces > 0
if (me->totface > 0) {
// XXX slow
- std::set<Image *> uv_images = bc_getUVImages(ob, !this->export_settings->active_uv_only);
- if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT || uv_images.size() == 0) {
- if (ob->totcol) {
- for (int a = 0; a < ob->totcol; a++) {
- createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
- }
- }
- else {
- int i = 0;
- createPolylist(i, has_uvs, has_color, ob, me, geom_id, norind);
+ if (ob->totcol) {
+ for (int a = 0; a < ob->totcol; a++) {
+ createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
- bool all_uv_layers = !this->export_settings->active_uv_only;
- std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
- createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
+ createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
}
}
@@ -230,15 +221,13 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
//createLooseEdgeList(ob, me, geom_id, norind);
// XXX slow
- if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
+ if (ob->totcol) {
for (int a = 0; a < ob->totcol; a++) {
createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
- bool all_uv_layers = !this->export_settings->active_uv_only;
- std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
- createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
+ createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
}
closeMesh();
@@ -307,44 +296,7 @@ std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char
return result;
}
-static void prepareToAppendValues(bool is_triangulated, COLLADASW::PrimitivesBase *facelist, std::vector<unsigned long> &vcount_list)
-{
- // performs the actual writing
- if (is_triangulated) {
- ((COLLADASW::Triangles *)facelist)->prepareToAppendValues();
- }
- else {
- // sets <vcount>
- facelist->setVCountList(vcount_list);
- ((COLLADASW::Polylist *)facelist)-> prepareToAppendValues();
- }
-}
-
-static void finishList(bool is_triangulated, COLLADASW::PrimitivesBase *facelist)
-{
- if (is_triangulated) {
- ((COLLADASW::Triangles *)facelist)->finish();
- }
- else {
- ((COLLADASW::Polylist *)facelist)->finish();
- }
-}
-
-COLLADASW::PrimitivesBase *getFacelist(bool is_triangulated, COLLADASW::StreamWriter *mSW)
-{
- COLLADASW::PrimitivesBase *facelist;
-
- if (is_triangulated)
- {
- facelist = new COLLADASW::Triangles(mSW);
- }
- else {
- facelist = new COLLADASW::Polylist(mSW);
- }
- return facelist;
-}
-
-// Export meshes with Materials
+// powerful because it handles both cases when there is material and when there's not
void GeometryExporter::createPolylist(short material_index,
bool has_uvs,
bool has_color,
@@ -362,7 +314,7 @@ void GeometryExporter::createPolylist(short material_index,
int i;
int faces_in_polylist = 0;
std::vector<unsigned long> vcount_list;
- bool is_triangulated = true;
+
// count faces with this material
for (i = 0; i < totpolys; i++) {
MPoly *p = &mpolys[i];
@@ -370,9 +322,6 @@ void GeometryExporter::createPolylist(short material_index,
if (p->mat_nr == material_index) {
faces_in_polylist++;
vcount_list.push_back(p->totloop);
- if (p->totloop != 3) {
- is_triangulated = false;
- }
}
}
@@ -383,21 +332,20 @@ void GeometryExporter::createPolylist(short material_index,
}
Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL;
- COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW);
-
+ COLLADASW::Polylist polylist(mSW);
// sets count attribute in <polylist>
- facelist->setCount(faces_in_polylist);
+ polylist.setCount(faces_in_polylist);
// sets material name
if (ma) {
std::string material_id = get_material_id(ma);
std::ostringstream ostr;
ostr << translate_id(material_id);
- facelist->setMaterial(ostr.str());
+ polylist.setMaterial(ostr.str());
}
-
- COLLADASW::InputList &til = facelist->getInputList();
+
+ COLLADASW::InputList &til = polylist.getInputList();
// creates <input> in <polylist> for vertices
COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
@@ -413,21 +361,13 @@ void GeometryExporter::createPolylist(short material_index,
int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1;
for (i = 0; i < num_layers; i++) {
if (!this->export_settings->active_uv_only || i == active_uv_index) {
-
- std::string uv_name(bc_get_uvlayer_name(me, i));
- std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
- std::string layer_id = makeTexcoordSourceId(
- effective_id,
- i, this->export_settings->active_uv_only);
-
- /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
- For now this is always 2 (This may change sometime/maybe)
- */
+
+ // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
- makeUrl(layer_id),
- 2, // this is only until we have optimized UV sets
- (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
- );
+ makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)),
+ 2, // this is only until we have optimized UV sets
+ (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
+ );
til.push_back(input3);
}
}
@@ -448,10 +388,12 @@ void GeometryExporter::createPolylist(short material_index,
}
}
+ // sets <vcount>
+ polylist.setVCountList(vcount_list);
// performs the actual writing
- prepareToAppendValues(is_triangulated, facelist, vcount_list);
-
+ polylist.prepareToAppendValues();
+
// <p>
int texindex = 0;
for (i = 0; i < totpolys; i++) {
@@ -463,202 +405,22 @@ void GeometryExporter::createPolylist(short material_index,
BCPolygonNormalsIndices normal_indices = norind[i];
for (int j = 0; j < loop_count; j++) {
- facelist->appendValues(l[j].v);
- facelist->appendValues(normal_indices[j]);
+ polylist.appendValues(l[j].v);
+ polylist.appendValues(normal_indices[j]);
if (has_uvs)
- facelist->appendValues(texindex + j);
+ polylist.appendValues(texindex + j);
if (has_color)
- facelist->appendValues(texindex + j);
+ polylist.appendValues(texindex + j);
}
}
texindex += loop_count;
}
-
- finishList(is_triangulated, facelist);
- delete facelist;
-}
-
-void GeometryExporter::createPolylists(std::set<Image *> uv_images,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind)
-{
- std::set<Image *>::iterator uv_images_iter;
- for (uv_images_iter = uv_images.begin();
- uv_images_iter != uv_images.end();
- uv_images_iter++) {
-
- Image *ima = *uv_images_iter;
- std::string imageid(id_name(ima));
- createPolylist(imageid, has_uvs,
- has_color,
- ob,
- me,
- geom_id,
- norind);
- }
-
- /* We msut add an additional collector for the case when
- * some parts of the object are not textured at all.
- * The next call creates a polylist for all untextured polygons
- */
-
- createPolylist("", has_uvs,
- has_color,
- ob,
- me,
- geom_id,
- norind);
-
+
+ polylist.finish();
}
-/* ===========================================================================
- * Export Meshes with UV Textures (export as materials, see also in
- * effectExporter and MaterialExporter)
- *
- * If imageid is the empty string, then collect only untextured polygons
- * =========================================================================== */
-void GeometryExporter::createPolylist(std::string imageid,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind)
-{
-
- MPoly *mpolys = me->mpoly;
- MLoop *mloops = me->mloop;
- MTexPoly *mtpolys = me->mtpoly;
-
- int totpolys = me->totpoly;
-
- // <vcount>
- int i;
- int faces_in_polylist = 0;
- std::vector<unsigned long> vcount_list;
- bool is_triangulated = true;
- // count faces with this material
- for (i = 0; i < totpolys; i++) {
- MTexPoly *tp = &mtpolys[i];
- MPoly *p = &mpolys[i];
-
- std::string tpageid = (tp->tpage) ? id_name(tp->tpage):"";
- if (tpageid == imageid) {
- faces_in_polylist++;
- vcount_list.push_back(p->totloop);
- if (p->totloop != 3) {
- is_triangulated = false;
- }
- }
- }
-
- // no faces using this imageid
- if (faces_in_polylist == 0) {
- if (imageid != "")
- fprintf(stderr, "%s: Image %s is not used.\n", id_name(ob).c_str(), imageid.c_str());
- return;
- }
-
- COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW);
-
- // sets count attribute in <polylist>
- facelist->setCount(faces_in_polylist);
-
- if (imageid != "") {
- // sets material name
- std::string material_id = get_material_id_from_id(imageid);
- std::ostringstream ostr;
- ostr << translate_id(material_id);
- facelist->setMaterial(ostr.str());
- }
- COLLADASW::InputList &til = facelist->getInputList();
-
- // creates <input> in <polylist> for vertices
- COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
-
- // creates <input> in <polylist> for normals
- COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1);
-
- til.push_back(input1);
- til.push_back(input2);
-
- // if mesh has uv coords writes <input> for TEXCOORD
- int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
- int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
- for (i = 0; i < num_layers; i++) {
- if (!this->export_settings->active_uv_only || i == active_uv_index) {
-
- std::string uv_name(bc_get_uvlayer_name(me, i));
- std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
- std::string layer_id = makeTexcoordSourceId(
- effective_id,
- i, this->export_settings->active_uv_only);
-
- /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
- For now this is always 2 (This may change sometime/maybe)
- */
- COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
- makeUrl(layer_id),
- 2, // this is only until we have optimized UV sets
- (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
- );
- til.push_back(input3);
- }
- }
-
- int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
- if (totlayer_mcol > 0) {
- int map_index = 0;
-
- for (int a = 0; a < totlayer_mcol; a++) {
- char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
- COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR,
- makeUrl(makeVertexColorSourceId(geom_id, layer_name)),
- (has_uvs) ? 3 : 2, // all color layers have same index order
- map_index // set number equals color map index
- );
- til.push_back(input4);
- map_index++;
- }
- }
-
- // performs the actual writing
- prepareToAppendValues(is_triangulated, facelist, vcount_list);
-
- // <p>
- int texindex = 0;
- for (i = 0; i < totpolys; i++) {
- MTexPoly *tp = &mtpolys[i];
- MPoly *p = &mpolys[i];
- int loop_count = p->totloop;
- std::string tpageid = (tp->tpage) ? id_name(tp->tpage) : "";
- if (tpageid == imageid) {
- MLoop *l = &mloops[p->loopstart];
- BCPolygonNormalsIndices normal_indices = norind[i];
-
- for (int j = 0; j < loop_count; j++) {
- facelist->appendValues(l[j].v);
- facelist->appendValues(normal_indices[j]);
- if (has_uvs)
- facelist->appendValues(texindex + j);
-
- if (has_color)
- facelist->appendValues(texindex + j);
- }
- }
-
- texindex += loop_count;
- }
-
- finishList(is_triangulated, facelist);
- delete facelist;
-}
// creates <source> for positions
void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
@@ -778,13 +540,7 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
COLLADASW::FloatSourceF source(mSW);
- std::string active_uv_name(bc_get_active_uvlayer_name(me));
- std::string effective_id = geom_id; // (active_uv_name == "") ? geom_id : active_uv_name;
- std::string layer_id = makeTexcoordSourceId(
- effective_id,
- a,
- this->export_settings->active_uv_only );
-
+ std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only);
source.setId(layer_id);
source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h
index 890304f4568..7527195fdd8 100644
--- a/source/blender/collada/GeometryExporter.h
+++ b/source/blender/collada/GeometryExporter.h
@@ -46,6 +46,8 @@
#include "BKE_key.h"
+struct EvaluationContext;
+
extern Object *bc_get_highest_selected_ancestor_or_self(Object *ob);
class Normal
@@ -72,12 +74,13 @@ class GeometryExporter : COLLADASW::LibraryGeometries
Normal n;
+ const struct EvaluationContext *mEvalCtx;
Scene *mScene;
public:
GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
- void exportGeom(Scene *sce);
+ void exportGeom(const struct EvaluationContext *eval_ctx, Scene *sce);
void operator()(Object *ob);
@@ -85,33 +88,15 @@ public:
Mesh *me,
std::string& geom_id);
- // Create polylists for meshes with Materials
+ // powerful because it handles both cases when there is material and when there's not
void createPolylist(short material_index,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind);
-
- // Create polylists for meshes with UV Textures
- void createPolylists(std::set<Image *> uv_images,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind);
-
- // Create polylists for meshes with UV Textures
- void createPolylist(std::string imageid,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind);
-
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind);
+
// creates <source> for positions
void createVertsSource(std::string geom_id, Mesh *me);
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index 93be7de6236..a2ab3ce520b 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -55,9 +55,9 @@ ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings
void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
{
- std::string id(id_name(image));
- std::string translated_id(translate_id(id));
- bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_id) == mImages.end();
+ std::string name(id_name(image));
+ std::string translated_name(translate_id(name));
+ bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end();
if (not_yet_exported) {
@@ -88,7 +88,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
// make absolute destination path
- BLI_strncpy(export_file, id.c_str(), sizeof(export_file));
+ BLI_strncpy(export_file, name.c_str(), sizeof(export_file));
BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat);
BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file);
@@ -143,60 +143,15 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
}
}
- /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
- COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_id, translated_id);
+ COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
img.add(mSW);
fprintf(stdout, "Collada export: Added image: %s\n", export_file);
- mImages.push_back(translated_id);
+ mImages.push_back(translated_name);
BKE_image_release_ibuf(image, imbuf, NULL);
}
}
-void ImagesExporter::export_UV_Images()
-{
- std::set<Image *> uv_textures;
- LinkNode *node;
- bool use_texture_copies = this->export_settings->use_texture_copies;
- bool active_uv_only = this->export_settings->active_uv_only;
-
- for (node = this->export_settings->export_set; node; node = node->next) {
- Object *ob = (Object *)node->link;
- if (ob->type == OB_MESH) {
- Mesh *me = (Mesh *) ob->data;
- BKE_mesh_tessface_ensure(me);
- int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
- for (int i = 0; i < me->pdata.totlayer; i++) {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- if (!active_uv_only || active_uv_layer == i)
- {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- for (int j = 0; j < me->totpoly; j++, txface++) {
-
- Image *ima = txface->tpage;
- if (ima == NULL)
- continue;
-
- bool not_in_list = uv_textures.find(ima) == uv_textures.end();
- if (not_in_list) {
- uv_textures.insert(ima);
- export_UV_Image(ima, use_texture_copies);
- }
- }
- }
- }
- }
- }
- }
-}
-
-/* ============================================================
- * Check if there are any images to be exported
- * Returns true as soon as an object is detected that
- * either has an UV Texture assigned, or has a material
- * assigned that uses an Image Texture.
- * ============================================================
- */
bool ImagesExporter::hasImages(Scene *sce)
{
LinkNode *node;
@@ -216,20 +171,6 @@ bool ImagesExporter::hasImages(Scene *sce)
}
}
- if (ob->type == OB_MESH) {
- Mesh *me = (Mesh *) ob->data;
- BKE_mesh_tessface_ensure(me);
- bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE);
- if (has_uvs) {
- int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
- for (int a = 0; a < num_layers; a++) {
- MTFace *tface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, a);
- Image *img = tface->tpage;
- if (img) return true;
- }
- }
- }
-
}
return false;
}
@@ -239,12 +180,9 @@ void ImagesExporter::exportImages(Scene *sce)
openLibrary();
MaterialFunctor mf;
- if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
+ if (this->export_settings->include_material_textures) {
mf.forEachMaterialInExportSet<ImagesExporter>(sce, *this, this->export_settings->export_set);
}
- else {
- export_UV_Images();
- }
closeLibrary();
}
diff --git a/source/blender/collada/ImageExporter.h b/source/blender/collada/ImageExporter.h
index 0eaebdd5cdd..f3dd2b336e4 100644
--- a/source/blender/collada/ImageExporter.h
+++ b/source/blender/collada/ImageExporter.h
@@ -51,7 +51,6 @@ public:
private:
std::vector<std::string> mImages; // contains list of written images, to avoid duplicates
- void export_UV_Images();
void export_UV_Image(Image *image, bool use_texture_copies);
bool hasImages(Scene *sce);
const ExportSettings *export_settings;
diff --git a/source/blender/collada/InstanceWriter.cpp b/source/blender/collada/InstanceWriter.cpp
index de1a4075462..71371d280df 100644
--- a/source/blender/collada/InstanceWriter.cpp
+++ b/source/blender/collada/InstanceWriter.cpp
@@ -32,76 +32,43 @@
#include "COLLADASWInstanceMaterial.h"
extern "C" {
-#include "BKE_customdata.h"
-#include "BKE_material.h"
-#include "DNA_mesh_types.h"
+ #include "BKE_customdata.h"
+ #include "BKE_material.h"
+ #include "DNA_mesh_types.h"
}
#include "InstanceWriter.h"
#include "collada_internal.h"
#include "collada_utils.h"
-void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type)
+void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only)
{
- bool all_uv_layers = !active_uv_only;
- COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
+ for (int a = 0; a < ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a + 1);
+
+ COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
- if (export_texture_type == BC_TEXTURE_TYPE_UV)
- {
- std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
- std::set<Image *>::iterator uv_images_iter;
- for (uv_images_iter = uv_images.begin();
- uv_images_iter != uv_images.end();
- uv_images_iter++) {
- Image *ima = *uv_images_iter;
- std::string matid(id_name(ima));
- matid = get_material_id_from_id(matid);
+ if (ma) {
+ std::string matid(get_material_id(ma));
+ matid = translate_id(matid);
std::ostringstream ostr;
ostr << matid;
COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
-
+
// create <bind_vertex_input> for each uv map
Mesh *me = (Mesh *)ob->data;
int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-
+
int map_index = 0;
- int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
+ int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) -1;
for (int b = 0; b < totlayer; b++) {
if (!active_uv_only || b == active_uv_index) {
char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
}
}
-
+
iml.push_back(im);
}
}
-
- else {
- for (int a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
- if (ma) {
- std::string matid(get_material_id(ma));
- matid = translate_id(matid);
- std::ostringstream ostr;
- ostr << matid;
- COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
-
- // create <bind_vertex_input> for each uv map
- Mesh *me = (Mesh *)ob->data;
- int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-
- int map_index = 0;
- int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
- for (int b = 0; b < totlayer; b++) {
- if (!active_uv_only || b == active_uv_index) {
- char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
- im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
- }
- }
-
- iml.push_back(im);
- }
- }
- }
}
diff --git a/source/blender/collada/InstanceWriter.h b/source/blender/collada/InstanceWriter.h
index a46027325a2..49ddf091b1c 100644
--- a/source/blender/collada/InstanceWriter.h
+++ b/source/blender/collada/InstanceWriter.h
@@ -31,12 +31,11 @@
#include "COLLADASWBindMaterial.h"
#include "DNA_object_types.h"
-#include "collada.h"
class InstanceWriter
{
protected:
- void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type);
+ void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only);
};
#endif
diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp
index 6e6cc24be20..4aece997f72 100644
--- a/source/blender/collada/MaterialExporter.cpp
+++ b/source/blender/collada/MaterialExporter.cpp
@@ -38,39 +38,14 @@ MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSe
void MaterialsExporter::exportMaterials(Scene *sce)
{
- if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT)
- {
- if (hasMaterials(sce)) {
- openLibrary();
+ if (hasMaterials(sce)) {
+ openLibrary();
- MaterialFunctor mf;
- mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set);
+ MaterialFunctor mf;
+ mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set);
- closeLibrary();
- }
+ closeLibrary();
}
-
- else {
- std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
- if (uv_images.size() > 0) {
- openLibrary();
- std::set<Image *>::iterator uv_images_iter;
- for (uv_images_iter = uv_images.begin();
- uv_images_iter != uv_images.end();
- uv_images_iter++) {
-
- Image *ima = *uv_images_iter;
- std::string matid(id_name(ima));
-
- openMaterial(get_material_id_from_id(matid), translate_id(matid));
- std::string efid = translate_id(matid) + "-effect";
- addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, efid));
- closeMaterial();
- }
- closeLibrary();
- }
- }
-
}
bool MaterialsExporter::hasMaterials(Scene *sce)
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index 6ca53c64299..9c95d4de695 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -472,11 +472,9 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getUVCoords().getInputInfosArray()[i];
COLLADAFW::String &uvname = info->mName;
// Allocate space for UV_data
- CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname.c_str());
CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, uvname.c_str());
}
// activate the first uv map
- me->mtpoly = (MTexPoly *)CustomData_get_layer_n(&me->pdata, CD_MTEXPOLY, 0);
me->mloopuv = (MLoopUV *) CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0);
}
@@ -1051,11 +1049,11 @@ void MeshImporter::optimize_material_assignements()
* which materials shall be moved to the created geometries. Also see
* optimize_material_assignements() above.
*/
-MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
- std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
- Object *ob, const COLLADAFW::UniqueId *geom_uid,
- char *layername, MTFace *texture_face,
- std::map<Material *, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index)
+void MeshImporter::assign_material_to_geom(
+ COLLADAFW::MaterialBinding cmaterial,
+ std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
+ Object *ob, const COLLADAFW::UniqueId *geom_uid,
+ std::map<Material *, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index)
{
MTex *color_texture = NULL;
Mesh *me = (Mesh *)ob->data;
@@ -1065,7 +1063,7 @@ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmateri
if (uid_material_map.find(ma_uid) == uid_material_map.end()) {
fprintf(stderr, "Cannot find material by UID.\n");
- return NULL;
+ return;
}
// first time we get geom_uid, ma_uid pair. Save for later check.
@@ -1089,15 +1087,6 @@ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmateri
color_texture);
}
- // set texture face
- if (color_texture &&
- strlen((color_texture)->uvname) &&
- !STREQ(layername, color_texture->uvname)) {
- texture_face = (MTFace *)CustomData_get_layer_named(&me->fdata, CD_MTFACE,
- color_texture->uvname);
- strcpy(layername, color_texture->uvname);
- }
-
MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid];
COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId();
@@ -1114,15 +1103,9 @@ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmateri
for (i = 0; i < prim.totpoly; i++, mpoly++) {
mpoly->mat_nr = mat_index;
- // bind texture images to faces
- if (texture_face && color_texture) {
- texture_face->tpage = (Image *)color_texture->tex->ima;
- texture_face++;
- }
}
}
}
- return texture_face;
}
Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
@@ -1176,10 +1159,6 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
id_us_plus(&old_mesh->id); /* Because BKE_mesh_assign_object would have already decreased it... */
BKE_libblock_free_us(G.main, old_mesh);
- char layername[100];
- layername[0] = '\0';
- MTFace *texture_face = NULL;
-
COLLADAFW::MaterialBindingArray& mat_array =
geom->getMaterialBindings();
@@ -1187,9 +1166,9 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
for (unsigned int i = 0; i < mat_array.getCount(); i++) {
if (mat_array[i].getReferencedMaterial().isValid()) {
- texture_face = assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid,
- layername, texture_face,
- material_texture_mapping_map, i);
+ assign_material_to_geom(
+ mat_array[i], uid_material_map, ob, geom_uid,
+ material_texture_mapping_map, i);
}
else {
fprintf(stderr, "invalid referenced material for %s\n", mat_array[i].getName().c_str());
diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h
index d6426fbaf56..e8ae934a393 100644
--- a/source/blender/collada/MeshImporter.h
+++ b/source/blender/collada/MeshImporter.h
@@ -171,11 +171,11 @@ public:
void optimize_material_assignements();
- MTFace *assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
- std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
- Object *ob, const COLLADAFW::UniqueId *geom_uid,
- char *layername, MTFace *texture_face,
- std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index);
+ void assign_material_to_geom(
+ COLLADAFW::MaterialBinding cmaterial,
+ std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
+ Object *ob, const COLLADAFW::UniqueId *geom_uid,
+ std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index);
Object *create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index 73945539931..c375c09d869 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -26,6 +26,7 @@
extern "C" {
#include "BLI_utildefines.h"
+ #include "BKE_group.h"
#include "BKE_object.h"
#include "BLI_listbase.h"
}
@@ -43,17 +44,17 @@ void SceneExporter::setExportTransformationType(BC_export_transformation_type tr
this->transformation_type = transformation_type;
}
-void SceneExporter::exportScene(Scene *sce)
+void SceneExporter::exportScene(const EvaluationContext *eval_ctx, Scene *sce)
{
// <library_visual_scenes> <visual_scene>
std::string id_naming = id_name(sce);
openVisualScene(translate_id(id_naming), id_naming);
- exportHierarchy(sce);
+ exportHierarchy(eval_ctx, sce);
closeVisualScene();
closeLibrary();
}
-void SceneExporter::exportHierarchy(Scene *sce)
+void SceneExporter::exportHierarchy(const EvaluationContext *eval_ctx, Scene *sce)
{
LinkNode *node;
std::vector<Object *> base_objects;
@@ -85,13 +86,13 @@ void SceneExporter::exportHierarchy(Scene *sce)
Object *ob = base_objects[index];
if (bc_is_marked(ob)) {
bc_remove_mark(ob);
- writeNodes(ob, sce);
+ writeNodes(eval_ctx, ob, sce);
}
}
}
-void SceneExporter::writeNodes(Object *ob, Scene *sce)
+void SceneExporter::writeNodes(const EvaluationContext *eval_ctx, Object *ob, Scene *sce)
{
// Add associated armature first if available
bool armature_exported = false;
@@ -100,7 +101,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
armature_exported = bc_is_in_Export_set(this->export_settings->export_set, ob_arm);
if (armature_exported && bc_is_marked(ob_arm)) {
bc_remove_mark(ob_arm);
- writeNodes(ob_arm, sce);
+ writeNodes(eval_ctx, ob_arm, sce);
armature_exported = true;
}
}
@@ -151,10 +152,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
COLLADASW::InstanceGeometry instGeom(mSW);
instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation)));
instGeom.setName(translate_id(id_name(ob)));
- InstanceWriter::add_material_bindings(instGeom.getBindMaterial(),
- ob,
- this->export_settings->active_uv_only,
- this->export_settings->export_texture_type);
+ InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only);
instGeom.add();
}
@@ -162,7 +160,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
// <instance_controller>
else if (ob->type == OB_ARMATURE) {
- arm_exporter->add_armature_bones(ob, sce, this, child_objects);
+ arm_exporter->add_armature_bones(eval_ctx, ob, sce, this, child_objects);
}
// <instance_camera>
@@ -180,12 +178,13 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
// empty object
else if (ob->type == OB_EMPTY) { // TODO: handle groups (OB_DUPLIGROUP
if ((ob->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && ob->dup_group) {
- GroupObject *go = NULL;
- Group *gr = ob->dup_group;
- /* printf("group detected '%s'\n", gr->id.name + 2); */
- for (go = (GroupObject *)(gr->gobject.first); go; go = go->next) {
- printf("\t%s\n", go->ob->id.name);
+ Group *group = ob->dup_group;
+ /* printf("group detected '%s'\n", group->id.name + 2); */
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ printf("\t%s\n", object->id.name);
}
+ FOREACH_GROUP_OBJECT_END
}
}
@@ -240,7 +239,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
for (std::list<Object *>::iterator i = child_objects.begin(); i != child_objects.end(); ++i) {
if (bc_is_marked(*i)) {
bc_remove_mark(*i);
- writeNodes(*i, sce);
+ writeNodes(eval_ctx, *i, sce);
}
}
diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h
index c7c15dba2cb..ded48983bd9 100644
--- a/source/blender/collada/SceneExporter.h
+++ b/source/blender/collada/SceneExporter.h
@@ -96,15 +96,15 @@ class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter,
{
public:
SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings);
- void exportScene(Scene *sce);
+ void exportScene(const struct EvaluationContext *eval_ctx, Scene *sce);
void setExportTransformationType(BC_export_transformation_type transformation_type);
private:
BC_export_transformation_type transformation_type;
// required for writeNodes() for bone-parented objects
friend class ArmatureExporter;
- void exportHierarchy(Scene *sce);
- void writeNodes(Object *ob, Scene *sce);
+ void exportHierarchy(const struct EvaluationContext *eval_ctx, Scene *sce);
+ void writeNodes(const struct EvaluationContext *eval_ctx, Object *ob, Scene *sce);
ArmatureExporter *arm_exporter;
const ExportSettings *export_settings;
diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp
index c48c060dc95..c29f1748efc 100644
--- a/source/blender/collada/SkinInfo.cpp
+++ b/source/blender/collada/SkinInfo.cpp
@@ -241,9 +241,9 @@ void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::Unique
BKE_object_workob_calc_parent(scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
- DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
#endif
copy_m4_m4(ob->obmat, bind_shape_matrix);
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
index b7eeff3b074..84817d76073 100644
--- a/source/blender/collada/TransformWriter.cpp
+++ b/source/blender/collada/TransformWriter.cpp
@@ -61,7 +61,8 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4],
}
}
-void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, BC_export_transformation_type transformation_type)
+void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob,
+ BC_export_transformation_type transformation_type)
{
#if 0
float rot[3], loc[3], scale[3];
diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h
index 5bb13d4aac9..580430911f7 100644
--- a/source/blender/collada/TransformWriter.h
+++ b/source/blender/collada/TransformWriter.h
@@ -41,7 +41,8 @@ class TransformWriter
protected:
void add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]);
- void add_node_transform_ob(COLLADASW::Node& node, Object *ob, BC_export_transformation_type transformation_type);
+ void add_node_transform_ob(COLLADASW::Node& node, Object *ob,
+ BC_export_transformation_type transformation_type);
void add_node_transform_identity(COLLADASW::Node& node);
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index 024bc4a4a5c..6c5fb0b33f3 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -67,7 +67,9 @@ int collada_import(bContext *C,
return 0;
}
-int collada_export(Scene *sce,
+int collada_export(const EvaluationContext *eval_ctx,
+ Scene *sce,
+ ViewLayer *view_layer,
const char *filepath,
int apply_modifiers,
@@ -80,7 +82,7 @@ int collada_export(Scene *sce,
int deform_bones_only,
int active_uv_only,
- BC_export_texture_type export_texture_type,
+ int include_material_textures,
int use_texture_copies,
int triangulate,
@@ -105,7 +107,7 @@ int collada_export(Scene *sce,
export_settings.deform_bones_only = deform_bones_only != 0;
export_settings.active_uv_only = active_uv_only != 0;
- export_settings.export_texture_type = export_texture_type;
+ export_settings.include_material_textures= include_material_textures != 0;
export_settings.use_texture_copies = use_texture_copies != 0;
export_settings.triangulate = triangulate != 0;
@@ -122,7 +124,7 @@ int collada_export(Scene *sce,
if (export_settings.include_children) includeFilter |= OB_REL_CHILDREN_RECURSIVE;
eObjectSet objectSet = (export_settings.selected) ? OB_SET_SELECTED : OB_SET_ALL;
- export_settings.export_set = BKE_object_relational_superset(sce, objectSet, (eObRelationTypes)includeFilter);
+ export_settings.export_set = BKE_object_relational_superset(view_layer, objectSet, (eObRelationTypes)includeFilter);
int export_count = BLI_linklist_count(export_settings.export_set);
if (export_count == 0) {
@@ -139,7 +141,7 @@ int collada_export(Scene *sce,
}
DocumentExporter exporter(&export_settings);
- int status = exporter.exportCurrentScene(sce);
+ int status = exporter.exportCurrentScene(eval_ctx, sce);
BLI_linklist_free(export_settings.export_set, NULL);
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index d31f5a8ba62..eb3964f9cb7 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -46,13 +46,10 @@ typedef enum BC_export_transformation_type {
BC_TRANSFORMATION_TYPE_TRANSROTLOC
} BC_export_transformation_type;
-typedef enum BC_export_texture_type {
- BC_TEXTURE_TYPE_MAT,
- BC_TEXTURE_TYPE_UV
-} BC_export_texture_type;
-
struct bContext;
struct Scene;
+struct ViewLayer;
+struct EvaluationContext;
/*
* both return 1 on success, 0 on error
@@ -67,7 +64,9 @@ int collada_import(struct bContext *C,
int keep_bind_info);
-int collada_export(struct Scene *sce,
+int collada_export(const struct EvaluationContext *eval_ctx,
+ struct Scene *sce,
+ struct ViewLayer *view_layer,
const char *filepath,
int apply_modifiers,
BC_export_mesh_type export_mesh_type,
@@ -79,7 +78,7 @@ int collada_export(struct Scene *sce,
int deform_bones_only,
int active_uv_only,
- BC_export_texture_type export_texture_type,
+ int include_material_textures,
int use_texture_copies,
int triangulate,
@@ -88,9 +87,9 @@ int collada_export(struct Scene *sce,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int open_sim,
- int limit_precision,
- int keep_bind_info);
+ int open_sim,
+ int limit_precision,
+ int keep_bind_info);
#ifdef __cplusplus
}
diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp
index 8974acb3460..6ebde6bd773 100644
--- a/source/blender/collada/collada_internal.cpp
+++ b/source/blender/collada/collada_internal.cpp
@@ -344,13 +344,7 @@ std::string get_camera_id(Object *ob)
std::string get_material_id(Material *mat)
{
- std::string id = id_name(mat);
- return get_material_id_from_id(id);
-}
-
-std::string get_material_id_from_id(std::string id)
-{
- return translate_id(id) + "-material";
+ return translate_id(id_name(mat)) + "-material";
}
std::string get_morph_id(Object *ob)
diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h
index 5f3fa34edc1..1c7aa160f57 100644
--- a/source/blender/collada/collada_internal.h
+++ b/source/blender/collada/collada_internal.h
@@ -103,7 +103,6 @@ extern std::string get_joint_sid(Bone *bone, Object *ob_arm);
extern std::string get_camera_id(Object *ob);
extern std::string get_material_id(Material *mat);
-extern std::string get_material_id_from_id(std::string id);
extern std::string get_morph_id(Object *ob);
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index b09732f9102..6a52027fb47 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -32,8 +32,6 @@
#include "COLLADAFWMeshPrimitive.h"
#include "COLLADAFWMeshVertexData.h"
-#include <set>
-
extern "C" {
#include "DNA_modifier_types.h"
#include "DNA_customdata_types.h"
@@ -47,9 +45,9 @@ extern "C" {
#include "BKE_context.h"
#include "BKE_customdata.h"
-#include "BKE_depsgraph.h"
#include "BKE_object.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_mesh.h"
#include "BKE_scene.h"
#include "BKE_DerivedMesh.h"
@@ -63,6 +61,8 @@ extern "C" {
#include "bmesh_tools.h"
}
+#include "DEG_depsgraph.h"
+
#include "collada_utils.h"
#include "ExportSettings.h"
@@ -94,6 +94,9 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
{
Object workob;
Scene *sce = CTX_data_scene(C);
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
if (!par || bc_test_parent_loop(par, ob))
return false;
@@ -106,7 +109,7 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
if (is_parent_space) {
float mat[4][4];
// calc par->obmat
- BKE_object_where_is_calc(sce, par);
+ BKE_object_where_is_calc(&eval_ctx, sce, par);
// move child obmat into world space
mul_m4_m4m4(mat, par->obmat, ob->obmat);
@@ -117,15 +120,15 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
// compute parentinv
- BKE_object_workob_calc_parent(sce, ob, &workob);
+ BKE_object_workob_calc_parent(&eval_ctx, sce, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
- DAG_id_tag_update(&par->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&par->id, OB_RECALC_OB);
/** done once after import */
#if 0
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
#endif
@@ -138,14 +141,21 @@ Object *bc_add_object(Scene *scene, int type, const char *name)
ob->data = BKE_object_obdata_add_from_type(G.main, type, name);
ob->lay = scene->lay;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+
+ /* XXX Collada should use the context scene layer, not the scene one. (dfelinto/gaia). */
+ ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
- BKE_scene_base_select(scene, BKE_scene_base_add(scene, ob));
+ LayerCollection *layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer);
+ BKE_collection_object_add(&scene->id, layer_collection->scene_collection, ob);
+
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ BKE_view_layer_base_select(view_layer, base);
return ob;
}
-Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate)
+Mesh *bc_get_mesh_copy(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate)
{
Mesh *tmpmesh;
CustomDataMask mask = CD_MASK_MESH;
@@ -155,12 +165,12 @@ Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh
switch (export_mesh_type) {
case BC_MESH_TYPE_VIEW:
{
- dm = mesh_create_derived_view(scene, ob, mask);
+ dm = mesh_create_derived_view(eval_ctx, scene, ob, mask);
break;
}
case BC_MESH_TYPE_RENDER:
{
- dm = mesh_create_derived_render(scene, ob, mask);
+ dm = mesh_create_derived_render(eval_ctx, scene, ob, mask);
break;
}
}
@@ -834,159 +844,3 @@ void bc_sanitize_mat(float mat[4][4], int precision)
for (int j = 0; j < 4; j++)
mat[i][j] = double_round(mat[i][j], precision);
}
-
-/*
-* Returns name of Active UV Layer or empty String if no active UV Layer defined.
-* Assuming the Object is of type MESH
-*/
-std::string bc_get_active_uvlayer_name(Object *ob)
-{
- Mesh *me = (Mesh *)ob->data;
- return bc_get_active_uvlayer_name(me);
-}
-
-/*
- * Returns name of Active UV Layer or empty String if no active UV Layer defined
- */
-std::string bc_get_active_uvlayer_name(Mesh *me)
-{
- int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
- if (num_layers) {
- return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
- }
- return "";
-}
-
-/*
- * Returns UV Layer name or empty string if layer index is out of range
- */
-std::string bc_get_uvlayer_name(Mesh *me, int layer)
-{
- int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
- if (num_layers && layer < num_layers) {
- return std::string(bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, layer));
- }
- return "";
-}
-
-/**********************************************************************
-*
-* Return the list of Mesh objects with assigned UVtextures and Images
-* Note: We need to create artificaial materials for each of them
-*
-***********************************************************************/
-std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers)
-{
- std::set <Object *> UVObjects;
- Base *base = (Base *)sce->base.first;
-
- while (base) {
- Object *ob = base->object;
- bool has_uvimage = false;
- if (ob->type == OB_MESH) {
- Mesh *me = (Mesh *)ob->data;
- int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
-
- for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
- if (all_uv_layers || active_uv_layer == i)
- {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- MPoly *mpoly = me->mpoly;
- for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
-
- Image *ima = txface->tpage;
- if (ima != NULL) {
- has_uvimage = true;
- break;
- }
- }
- }
- }
- }
-
- if (has_uvimage) {
- UVObjects.insert(ob);
- }
- }
- base = base->next;
- }
- return UVObjects;
-}
-
-/**********************************************************************
-*
-* Return the list of UV Texture images from all exported Mesh Items
-* Note: We need to create one artificial material for each Image.
-*
-***********************************************************************/
-std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers)
-{
- std::set <Image *> UVImages;
- Base *base = (Base *)sce->base.first;
-
- while (base) {
- Object *ob = base->object;
- bool has_uvimage = false;
- if (ob->type == OB_MESH) {
- Mesh *me = (Mesh *)ob->data;
- int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
-
- for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
- if (all_uv_layers || active_uv_layer == i)
- {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- MPoly *mpoly = me->mpoly;
- for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
-
- Image *ima = txface->tpage;
- if (ima != NULL) {
- if (UVImages.find(ima) == UVImages.end())
- UVImages.insert(ima);
- }
- }
- }
- }
- }
- }
- base = base->next;
- }
- return UVImages;
-}
-
-/**********************************************************************
-*
-* Return the list of UV Texture images for the given Object
-* Note: We need to create one artificial material for each Image.
-*
-***********************************************************************/
-std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers)
-{
- std::set <Image *> UVImages;
-
- bool has_uvimage = false;
- if (ob->type == OB_MESH) {
- Mesh *me = (Mesh *)ob->data;
- int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
-
- for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
- if (all_uv_layers || active_uv_layer == i)
- {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- MPoly *mpoly = me->mpoly;
- for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
-
- Image *ima = txface->tpage;
- if (ima != NULL) {
- if (UVImages.find(ima) == UVImages.end())
- UVImages.insert(ima);
- }
- }
- }
- }
- }
- }
- return UVImages;
-} \ No newline at end of file
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index 5447c39e902..75e9fb5dcea 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -34,7 +34,6 @@
#include <vector>
#include <map>
-#include <set>
#include <algorithm>
extern "C" {
@@ -61,13 +60,15 @@ extern "C" {
#include "ExportSettings.h"
#include "collada_internal.h"
+struct EvaluationContext;
+
typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *> > TexIndexTextureArrayMap;
extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index);
extern int bc_test_parent_loop(Object *par, Object *ob);
extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true);
extern Object *bc_add_object(Scene *scene, int type, const char *name);
-extern Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate);
+extern Mesh *bc_get_mesh_copy(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate);
extern Object *bc_get_assigned_armature(Object *ob);
extern Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob);
@@ -81,7 +82,6 @@ extern void bc_set_mark(Object *ob);
extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n);
extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type);
-extern char *bc_CustomData_get_layer_name(const CustomData *data, int layer_index, int type);
extern void bc_bubble_sort_by_Object_name(LinkNode *export_set);
extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only);
@@ -111,14 +111,6 @@ extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space);
-extern std::string bc_get_active_uvlayer_name(Object *ob);
-extern std::string bc_get_active_uvlayer_name(Mesh *me);
-extern std::string bc_get_uvlayer_name(Mesh *me, int layer);
-
-extern std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers);
-extern std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers);
-extern std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers);
-
class BCPolygonNormalsIndices
{
std::vector<unsigned int> normal_indices;
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
index 2286db81860..e16aca3fdee 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
@@ -65,12 +65,12 @@ void RenderLayersNode::testRenderLink(NodeConverter &converter,
missingRenderLink(converter);
return;
}
- SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, layerId);
- if (srl == NULL) {
+ ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, layerId);
+ if (view_layer == NULL) {
missingRenderLink(converter);
return;
}
- RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
+ RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name);
if (rl == NULL) {
missingRenderLink(converter);
return;
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
index d1c654ddb6c..a5e2d275e4f 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
@@ -55,10 +55,10 @@ void RenderLayersProg::initExecution()
rr = RE_AcquireResultRead(re);
if (rr) {
- SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, getLayerId());
- if (srl) {
+ ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, getLayerId());
+ if (view_layer) {
- RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
+ RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name);
if (rl) {
this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_passName.c_str(), this->m_viewName);
}
@@ -189,9 +189,9 @@ void RenderLayersProg::determineResolution(unsigned int resolution[2], unsigned
rr = RE_AcquireResultRead(re);
if (rr) {
- SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&sce->r.layers, getLayerId());
- if (srl) {
- RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
+ ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&sce->view_layers, getLayerId());
+ if (view_layer) {
+ RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name);
if (rl) {
resolution[0] = rl->rectx;
resolution[1] = rl->recty;
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index 9478ca306e9..9495321a0ff 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -43,16 +43,19 @@ set(SRC
intern/builder/deg_builder.cc
intern/builder/deg_builder_cycle.cc
intern/builder/deg_builder_nodes.cc
+ intern/builder/deg_builder_nodes_layer_collection.cc
intern/builder/deg_builder_nodes_rig.cc
- intern/builder/deg_builder_nodes_scene.cc
+ intern/builder/deg_builder_nodes_view_layer.cc
intern/builder/deg_builder_pchanmap.cc
intern/builder/deg_builder_relations.cc
intern/builder/deg_builder_relations_keys.cc
+ intern/builder/deg_builder_relations_layer_collection.cc
intern/builder/deg_builder_relations_rig.cc
- intern/builder/deg_builder_relations_scene.cc
+ intern/builder/deg_builder_relations_view_layer.cc
intern/builder/deg_builder_transitive.cc
intern/debug/deg_debug_graphviz.cc
intern/eval/deg_eval.cc
+ intern/eval/deg_eval_copy_on_write.cc
intern/eval/deg_eval_flush.cc
intern/nodes/deg_node.cc
intern/nodes/deg_node_component.cc
@@ -62,6 +65,8 @@ set(SRC
intern/depsgraph_debug.cc
intern/depsgraph_eval.cc
intern/depsgraph_query.cc
+ intern/depsgraph_query_foreach.cc
+ intern/depsgraph_query_iter.cc
intern/depsgraph_tag.cc
intern/depsgraph_type_defines.cc
@@ -78,6 +83,7 @@ set(SRC
intern/builder/deg_builder_relations_impl.h
intern/builder/deg_builder_transitive.h
intern/eval/deg_eval.h
+ intern/eval/deg_eval_copy_on_write.h
intern/eval/deg_eval_flush.h
intern/nodes/deg_node.h
intern/nodes/deg_node_component.h
@@ -112,10 +118,6 @@ else()
endif()
endif()
-if(WITH_LEGACY_DEPSGRAPH)
- add_definitions(-DWITH_LEGACY_DEPSGRAPH)
-endif()
-
if(WITH_BOOST)
list(APPEND INC_SYS
${BOOST_INCLUDE_DIR}
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index 0837f147275..6bcbff4950b 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -65,14 +65,49 @@ struct Main;
struct PointerRNA;
struct PropertyRNA;
+struct RenderEngineType;
+struct Scene;
+struct ViewLayer;
+
+typedef enum eEvaluationMode {
+ DAG_EVAL_VIEWPORT = 0, /* evaluate for OpenGL viewport */
+ DAG_EVAL_PREVIEW = 1, /* evaluate for render with preview settings */
+ DAG_EVAL_RENDER = 2, /* evaluate for render purposes */
+} eEvaluationMode;
+
+/* Dependency graph evaluation context
+ *
+ * This structure stores all the local dependency graph data,
+ * which is needed for it's evaluation,
+ */
+typedef struct EvaluationContext {
+ eEvaluationMode mode;
+ float ctime;
+
+ struct Depsgraph *depsgraph;
+ struct ViewLayer *view_layer;
+ struct RenderEngineType *engine_type;
+} EvaluationContext;
+
+/* DagNode->eval_flags */
+enum {
+ /* Regardless to curve->path animation flag path is to be evaluated anyway,
+ * to meet dependencies with such a things as curve modifier and other guys
+ * who're using curve deform, where_on_path and so.
+ */
+ DAG_EVAL_NEED_CURVE_PATH = 1,
+ /* Scene evaluation would need to have object's data on CPU,
+ * meaning no GPU shortcuts is allowed.
+ */
+ DAG_EVAL_NEED_CPU = 2,
+};
#ifdef __cplusplus
extern "C" {
#endif
-bool DEG_depsgraph_use_legacy(void);
-void DEG_depsgraph_switch_to_legacy(void);
-void DEG_depsgraph_switch_to_new(void);
+bool DEG_depsgraph_use_copy_on_write(void);
+void DEG_depsgraph_enable_copy_on_write(void);
/* ************************************************ */
/* Depsgraph API */
@@ -98,47 +133,71 @@ void DEG_free_node_types(void);
/* Update Tagging -------------------------------- */
-/* Tag node(s) associated with states such as time and visibility */
-void DEG_scene_update_flags(Depsgraph *graph, const bool do_time);
-
/* Update dependency graph when visible scenes/layers changes. */
-void DEG_graph_on_visible_update(struct Main *bmain, struct Scene *scene);
+void DEG_graph_on_visible_update(struct Main *bmain, Depsgraph *depsgraph);
/* Update all dependency graphs when visible scenes/layers changes. */
void DEG_on_visible_update(struct Main *bmain, const bool do_time);
-/* Tag node(s) associated with changed data for later updates */
-void DEG_graph_id_tag_update(struct Main *bmain,
- Depsgraph *graph,
- struct ID *id);
-
/* Tag given ID for an update in all the dependency graphs. */
-void DEG_id_tag_update(struct ID *id, short flag);
-void DEG_id_tag_update_ex(struct Main *bmain,
- struct ID *id,
- short flag);
+enum {
+ /* Object transformation changed, corresponds to OB_RECALC_OB. */
+ DEG_TAG_TRANSFORM = (1 << 0),
+
+ /* Object geoemtry changed, corresponds to OB_RECALC_DATA. */
+ DEG_TAG_GEOMETRY = (1 << 1),
+
+ /* Time changed and animation is to be re-evaluated, OB_RECALC_TIME. */
+ DEG_TAG_TIME = (1 << 2),
+
+ /* Particle system changed. */
+ DEG_TAG_PSYSC_REDO = (1 << 3),
+ DEG_TAG_PSYS_RESET = (1 << 4),
+ DEG_TAG_PSYS_TYPE = (1 << 5),
+ DEG_TAG_PSYS_CHILD = (1 << 6),
+ DEG_TAG_PSYS_PHYS = (1 << 7),
+ DEG_TAG_PSYS = ((1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)),
+
+ /* Update copy on write component without flushing down the road. */
+ DEG_TAG_COPY_ON_WRITE = (1 << 8),
+
+ /* Tag shading components for update.
+ * Only parameters of material changed).
+ */
+ DEG_TAG_SHADING_UPDATE = (1 << 9),
+ DEG_TAG_SELECT_UPDATE = (1 << 10),
+ DEG_TAG_BASE_FLAGS_UPDATE = (1 << 11),
+
+ /* Only inform editors about the change. Don't modify datablock itself. */
+ DEG_TAG_EDITORS_UPDATE = (1 << 12),
+};
+void DEG_id_tag_update(struct ID *id, int flag);
+void DEG_id_tag_update_ex(struct Main *bmain, struct ID *id, int flag);
+
+void DEG_graph_id_tag_update(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct ID *id,
+ int flag);
/* Mark a particular datablock type as having changing. This does
* not cause any updates but is used by external render engines to detect if for
* example a datablock was removed.
*/
-void DEG_id_type_tag(struct Main *bmain, short idtype);
+void DEG_id_type_tag(struct Main *bmain, short id_type);
void DEG_ids_clear_recalc(struct Main *bmain);
/* Update Flushing ------------------------------- */
-/* Flush updates for all IDs */
-void DEG_ids_flush_tagged(struct Main *bmain);
-
/* Flush updates for IDs in a single scene. */
-void DEG_scene_flush_update(struct Main *bmain, struct Scene *scene);
+void DEG_graph_flush_update(struct Main *bmain, Depsgraph *depsgraph);
/* Check if something was changed in the database and inform
* editors about this.
*/
void DEG_ids_check_recalc(struct Main *bmain,
struct Scene *scene,
+ struct ViewLayer *view_layer,
bool time);
/* ************************************************ */
@@ -147,13 +206,19 @@ void DEG_ids_check_recalc(struct Main *bmain,
/* Evaluation Context ---------------------------- */
/* Create new evaluation context. */
-struct EvaluationContext *DEG_evaluation_context_new(int mode);
+struct EvaluationContext *DEG_evaluation_context_new(eEvaluationMode mode);
/* Initialize evaluation context.
* Used by the areas which currently overrides the context or doesn't have
* access to a proper one.
*/
-void DEG_evaluation_context_init(struct EvaluationContext *eval_ctx, int mode);
+void DEG_evaluation_context_init(struct EvaluationContext *eval_ctx,
+ eEvaluationMode mode);
+void DEG_evaluation_context_init_from_scene(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ struct RenderEngineType *engine_type,
+ eEvaluationMode mode);
/* Free evaluation context. */
void DEG_evaluation_context_free(struct EvaluationContext *eval_ctx);
@@ -167,23 +232,13 @@ void DEG_evaluation_context_free(struct EvaluationContext *eval_ctx);
void DEG_evaluate_on_framechange(struct EvaluationContext *eval_ctx,
struct Main *bmain,
Depsgraph *graph,
- float ctime,
- const unsigned int layer);
-
-/* Data changed recalculation entry point.
- * < context_type: context to perform evaluation for
- * < layers: visible layers bitmask to update the graph for
- */
-void DEG_evaluate_on_refresh_ex(struct EvaluationContext *eval_ctx,
- Depsgraph *graph,
- const unsigned int layers);
+ float ctime);
/* Data changed recalculation entry point.
* < context_type: context to perform evaluation for
*/
void DEG_evaluate_on_refresh(struct EvaluationContext *eval_ctx,
- Depsgraph *graph,
- struct Scene *scene);
+ Depsgraph *graph);
bool DEG_needs_eval(Depsgraph *graph);
@@ -193,20 +248,21 @@ bool DEG_needs_eval(Depsgraph *graph);
* to do their own updates based on changes.
*/
-typedef void (*DEG_EditorUpdateIDCb)(struct Main *bmain, struct ID *id);
-typedef void (*DEG_EditorUpdateSceneCb)(struct Main *bmain,
- struct Scene *scene,
- int updated);
-typedef void (*DEG_EditorUpdateScenePreCb)(struct Main *bmain,
- struct Scene *scene,
- bool time);
+typedef struct DEGEditorUpdateContext {
+ struct Main *bmain;
+ struct Scene *scene;
+ struct ViewLayer *view_layer;
+} DEGEditorUpdateContext;
+
+typedef void (*DEG_EditorUpdateIDCb)(
+ const DEGEditorUpdateContext *update_ctx,
+ struct ID *id);
+typedef void (*DEG_EditorUpdateSceneCb)(
+ const DEGEditorUpdateContext *update_ctx, int updated);
/* Set callbacks which are being called when depsgraph changes. */
void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func,
- DEG_EditorUpdateSceneCb scene_func,
- DEG_EditorUpdateScenePreCb scene_pre_func);
-
-void DEG_editors_update_pre(struct Main *bmain, struct Scene *scene, bool time);
+ DEG_EditorUpdateSceneCb scene_func);
#ifdef __cplusplus
} /* extern "C" */
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
index b268822f659..334b15cc638 100644
--- a/source/blender/depsgraph/DEG_depsgraph_build.h
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -40,12 +40,15 @@ struct Depsgraph;
/* ------------------------------------------------ */
-struct Main;
-struct Scene;
-struct Group;
+struct CacheFile;
struct EffectorWeights;
+struct EvaluationContext;
+struct Group;
+struct Main;
struct ModifierData;
struct Object;
+struct Scene;
+struct ViewLayer;
#ifdef __cplusplus
extern "C" {
@@ -56,28 +59,23 @@ extern "C" {
/* Build depsgraph for the given scene, and dump results in given
* graph container.
*/
-void DEG_graph_build_from_scene(struct Depsgraph *graph,
- struct Main *bmain,
- struct Scene *scene);
+void DEG_graph_build_from_view_layer(struct Depsgraph *graph,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
/* Tag relations from the given graph for update. */
void DEG_graph_tag_relations_update(struct Depsgraph *graph);
+/* Create or update relations in the specified graph. */
+void DEG_graph_relations_update(struct Depsgraph *graph,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
+
/* Tag all relations in the database for update.*/
void DEG_relations_tag_update(struct Main *bmain);
-/* Create new graph if didn't exist yet,
- * or update relations if graph was tagged for update.
- */
-void DEG_scene_relations_update(struct Main *bmain, struct Scene *scene);
-
-/* Rebuild dependency graph only for a given scene. */
-void DEG_scene_relations_rebuild(struct Main *bmain,
- struct Scene *scene);
-
-/* Delete scene graph. */
-void DEG_scene_graph_free(struct Scene *scene);
-
/* Add Dependencies ----------------------------- */
/* Handle for components to define their dependencies from callbacks.
@@ -87,9 +85,6 @@ void DEG_scene_graph_free(struct Scene *scene);
*/
struct DepsNodeHandle;
-struct CacheFile;
-struct Object;
-
typedef enum eDepsSceneComponentType {
/* Parameters Component - Default when nothing else fits
* (i.e. just SDNA property setting).
@@ -166,7 +161,6 @@ void DEG_add_collision_relations(struct DepsNodeHandle *handle,
struct Scene *scene,
struct Object *object,
struct Group *group,
- int layer,
unsigned int modifier_type,
DEG_CollobjFilterFunction fn,
bool dupli,
diff --git a/source/blender/depsgraph/DEG_depsgraph_debug.h b/source/blender/depsgraph/DEG_depsgraph_debug.h
index 63ebe21d073..bd03874436b 100644
--- a/source/blender/depsgraph/DEG_depsgraph_debug.h
+++ b/source/blender/depsgraph/DEG_depsgraph_debug.h
@@ -40,6 +40,8 @@ extern "C" {
#endif
struct Depsgraph;
+struct Scene;
+struct ViewLayer;
/* ------------------------------------------------ */
@@ -60,9 +62,10 @@ bool DEG_debug_compare(const struct Depsgraph *graph1,
const struct Depsgraph *graph2);
/* Check that dependnecies in the graph are really up to date. */
-bool DEG_debug_scene_relations_validate(struct Main *bmain,
- struct Scene *scene);
-
+bool DEG_debug_graph_relations_validate(struct Depsgraph *graph,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
/* Perform consistency check on the graph. */
bool DEG_debug_consistency_check(struct Depsgraph *graph);
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h
index ccd204a2083..7771d35d581 100644
--- a/source/blender/depsgraph/DEG_depsgraph_query.h
+++ b/source/blender/depsgraph/DEG_depsgraph_query.h
@@ -33,20 +33,110 @@
#ifndef __DEG_DEPSGRAPH_QUERY_H__
#define __DEG_DEPSGRAPH_QUERY_H__
+#include "DEG_depsgraph.h"
+
struct ID;
+struct Base;
+struct BLI_Iterator;
struct Depsgraph;
+struct DupliObject;
+struct ListBase;
+struct Scene;
+struct ViewLayer;
#ifdef __cplusplus
extern "C" {
#endif
/* Check if given ID type was tagged for update. */
-bool DEG_id_type_tagged(struct Main *bmain, short idtype);
+bool DEG_id_type_tagged(struct Main *bmain, short id_type);
/* Get additional evaluation flags for the given ID. */
short DEG_get_eval_flags_for_id(struct Depsgraph *graph, struct ID *id);
+/* Get scene the despgraph is created for. */
+struct Scene *DEG_get_evaluated_scene(struct Depsgraph *graph);
+
+/* Get scene layer the despgraph is created for. */
+struct ViewLayer *DEG_get_evaluated_view_layer(struct Depsgraph *graph);
+
+/* Get evaluated version of object for given original one. */
+struct Object *DEG_get_evaluated_object(struct Depsgraph *depsgraph, struct Object *object);
+
+/* Get evaluated version of given ID datablock. */
+struct ID *DEG_get_evaluated_id(struct Depsgraph *depsgraph, struct ID *id);
+
+/* ************************ DEG iterators ********************* */
+
+enum {
+ DEG_ITER_OBJECT_FLAG_SET = (1 << 0),
+ DEG_ITER_OBJECT_FLAG_DUPLI = (1 << 1),
+
+ DEG_ITER_OBJECT_FLAG_ALL = (DEG_ITER_OBJECT_FLAG_SET | DEG_ITER_OBJECT_FLAG_DUPLI),
+};
+
+typedef struct DEGOIterObjectData {
+ struct Depsgraph *graph;
+ struct Scene *scene;
+ struct EvaluationContext eval_ctx;
+
+ int flag;
+
+ /* **** Iteration over dupli-list. *** */
+
+ /* Object which created the dupli-list. */
+ struct Object *dupli_parent;
+ /* List of duplicated objects. */
+ struct ListBase *dupli_list;
+ /* Next duplicated object to step into. */
+ struct DupliObject *dupli_object_next;
+ /* Corresponds to current object: current iterator object is evaluated from
+ * this duplicated object.
+ */
+ struct DupliObject *dupli_object_current;
+ /* Temporary storage to report fully populated DNA to the render engine or
+ * other users of the iterator.
+ */
+ struct Object temp_dupli_object;
+
+ /* **** Iteration ober ID nodes **** */
+ size_t id_node_index;
+ size_t num_id_nodes;
+} DEGOIterObjectData;
+
+void DEG_iterator_objects_begin(struct BLI_Iterator *iter, DEGOIterObjectData *data);
+void DEG_iterator_objects_next(struct BLI_Iterator *iter);
+void DEG_iterator_objects_end(struct BLI_Iterator *iter);
+
+#define DEG_OBJECT_ITER(graph_, instance_, flag_) \
+ { \
+ DEGOIterObjectData data_ = { \
+ .graph = (graph_), \
+ .flag = (flag_), \
+ }; \
+ \
+ ITER_BEGIN(DEG_iterator_objects_begin, \
+ DEG_iterator_objects_next, \
+ DEG_iterator_objects_end, \
+ &data_, Object *, instance_)
+
+#define DEG_OBJECT_ITER_END \
+ ITER_END \
+ }
+
+/* ************************ DEG traversal ********************* */
+
+typedef void (*DEGForeachIDCallback)(ID *id, void *user_data);
+
+/* NOTE: Modifies runtime flags in depsgraph nodes, so can not be used in
+ * parallel. Keep an eye on that!
+ */
+void DEG_foreach_dependent_ID(const Depsgraph *depsgraph,
+ const ID *id,
+ DEGForeachIDCallback callback, void *user_data);
+
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index e3494e4756e..20a93673350 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -30,146 +30,38 @@
#include "intern/builder/deg_builder.h"
-#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_ID.h"
-#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-#include "BLI_stack.h"
-
#include "intern/depsgraph.h"
#include "intern/depsgraph_types.h"
#include "intern/nodes/deg_node.h"
-#include "intern/nodes/deg_node_component.h"
-#include "intern/nodes/deg_node_operation.h"
#include "util/deg_util_foreach.h"
-#include <cstdio>
+#include "DEG_depsgraph.h"
namespace DEG {
-static bool check_object_needs_evaluation(Object *object)
-{
- if (object->recalc & OB_RECALC_ALL) {
- /* Object is tagged for update anyway, no need to re-tag it. */
- return false;
- }
- if (object->type == OB_MESH) {
- return object->derivedFinal == NULL;
- }
- else if (ELEM(object->type,
- OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE))
- {
- return object->curve_cache == NULL;
- }
- return false;
-}
-
-void deg_graph_build_flush_layers(Depsgraph *graph)
-{
- BLI_Stack *stack = BLI_stack_new(sizeof(OperationDepsNode *),
- "DEG flush layers stack");
- foreach (OperationDepsNode *node, graph->operations) {
- IDDepsNode *id_node = node->owner->owner;
- node->done = 0;
- node->num_links_pending = 0;
- foreach (DepsRelation *rel, node->outlinks) {
- if ((rel->from->type == DEG_NODE_TYPE_OPERATION) &&
- (rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
- {
- ++node->num_links_pending;
- }
- }
- if (node->num_links_pending == 0) {
- BLI_stack_push(stack, &node);
- node->done = 1;
- }
- node->owner->layers = id_node->layers;
- id_node->id->tag |= LIB_TAG_DOIT;
- }
- while (!BLI_stack_is_empty(stack)) {
- OperationDepsNode *node;
- BLI_stack_pop(stack, &node);
- /* Flush layers to parents. */
- foreach (DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
- OperationDepsNode *from = (OperationDepsNode *)rel->from;
- from->owner->layers |= node->owner->layers;
- }
- }
- /* Schedule parent nodes. */
- foreach (DepsRelation *rel, node->inlinks) {
- if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
- OperationDepsNode *from = (OperationDepsNode *)rel->from;
- if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
- BLI_assert(from->num_links_pending > 0);
- --from->num_links_pending;
- }
- if (from->num_links_pending == 0 && from->done == 0) {
- BLI_stack_push(stack, &from);
- from->done = 1;
- }
- }
- }
- }
- BLI_stack_free(stack);
-}
-
-void deg_graph_build_finalize(Depsgraph *graph)
+void deg_graph_build_finalize(Main *bmain, Depsgraph *graph)
{
- /* STEP 1: Make sure new invisible dependencies are ready for use.
- *
- * TODO(sergey): This might do a bit of extra tagging, but it's kinda nice
- * to do it ahead of a time and don't spend time on flushing updates on
- * every frame change.
- */
- GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
- {
- if (id_node->layers == 0) {
- ID *id = id_node->id;
- if (GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- if (check_object_needs_evaluation(object)) {
- id_node->tag_update(graph);
- }
- }
- }
- }
- GHASH_FOREACH_END();
- /* STEP 2: Flush visibility layers from children to parent. */
- deg_graph_build_flush_layers(graph);
- /* STEP 3: Re-tag IDs for update if it was tagged before the relations
+ const bool use_copy_on_write = DEG_depsgraph_use_copy_on_write();
+ /* Re-tag IDs for update if it was tagged before the relations
* update tag.
*/
- GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
- {
- GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp, id_node->components)
- {
- id_node->layers |= comp->layers;
+ foreach (IDDepsNode *id_node, graph->id_nodes) {
+ ID *id = id_node->id_orig;
+ id_node->finalize_build(graph);
+ if ((id->tag & LIB_TAG_ID_RECALC_ALL)) {
+ id_node->tag_update(graph);
}
- GHASH_FOREACH_END();
-
- if ((id_node->layers & graph->layers) != 0 || graph->layers == 0) {
- ID *id = id_node->id;
- if ((id->tag & LIB_TAG_ID_RECALC_ALL) &&
- (id->tag & LIB_TAG_DOIT))
- {
- id_node->tag_update(graph);
- id->tag &= ~LIB_TAG_DOIT;
- }
- else if (GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- if (object->recalc & OB_RECALC_ALL) {
- id_node->tag_update(graph);
- id->tag &= ~LIB_TAG_DOIT;
- }
- }
+ /* TODO(sergey): This is not ideal at all, since this forces
+ * re-evaluaiton of the whole tree.
+ */
+ if (use_copy_on_write) {
+ DEG_id_tag_update_ex(bmain, id_node->id_orig, DEG_TAG_COPY_ON_WRITE);
}
- id_node->finalize_build();
}
- GHASH_FOREACH_END();
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h
index b8ea8c8e599..c7ff668504c 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder.h
@@ -30,15 +30,12 @@
#pragma once
-#include "intern/depsgraph_types.h"
-
-struct FCurve;
+struct Main;
namespace DEG {
struct Depsgraph;
-void deg_graph_build_finalize(struct Depsgraph *graph);
-void deg_graph_build_flush_layers(struct Depsgraph *graph);
+void deg_graph_build_finalize(struct Main *bmain, struct Depsgraph *graph);
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 6de6feb32f2..342ce8e862b 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -62,6 +62,7 @@ extern "C" {
#include "DNA_node_types.h"
#include "DNA_particle_types.h"
#include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
@@ -72,7 +73,6 @@ extern "C" {
#include "BKE_animsys.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_idcode.h"
@@ -103,6 +103,7 @@ extern "C" {
#include "DEG_depsgraph_build.h"
#include "intern/builder/deg_builder.h"
+#include "intern/eval/deg_eval_copy_on_write.h"
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
@@ -125,7 +126,9 @@ static void modifier_walk(void *user_data,
{
BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
if (*obpoin) {
- data->builder->build_object(NULL, *obpoin);
+ data->builder->build_object(NULL,
+ *obpoin,
+ DEG_ID_LINKED_INDIRECTLY);
}
}
@@ -138,11 +141,19 @@ void constraint_walk(bConstraint * /*con*/,
if (*idpoin) {
ID *id = *idpoin;
if (GS(id->name) == ID_OB) {
- data->builder->build_object(NULL, (Object *)id);
+ data->builder->build_object(NULL,
+ (Object *)id,
+ DEG_ID_LINKED_INDIRECTLY);
}
}
}
+void free_copy_on_write_datablock(void *id_v)
+{
+ ID *id = (ID *)id_v;
+ deg_free_copy_on_write_datablock(id);
+}
+
} /* namespace */
/* ************ */
@@ -153,17 +164,51 @@ void constraint_walk(bConstraint * /*con*/,
DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph)
: bmain_(bmain),
graph_(graph),
- scene_(NULL)
+ scene_(NULL),
+ cow_id_hash_(NULL)
{
}
DepsgraphNodeBuilder::~DepsgraphNodeBuilder()
{
+ if (cow_id_hash_ != NULL) {
+ BLI_ghash_free(cow_id_hash_, NULL, free_copy_on_write_datablock);
+ }
}
-IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id)
+IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id, bool do_tag)
{
- return graph_->add_id_node(id, id->name);
+ if (!DEG_depsgraph_use_copy_on_write()) {
+ return graph_->add_id_node(id, do_tag);
+ }
+ IDDepsNode *id_node = NULL;
+ ID *id_cow = (ID *)BLI_ghash_lookup(cow_id_hash_, id);
+ if (id_cow != NULL) {
+ /* TODO(sergey): Is it possible to lookup and pop element from GHash
+ * at the same time?
+ */
+ BLI_ghash_remove(cow_id_hash_, id, NULL, NULL);
+ }
+ id_node = graph_->add_id_node(id, do_tag, id_cow);
+ /* Currently all ID nodes are supposed to have copy-on-write logic.
+ *
+ * NOTE: Zero number of components indicates that ID node was just created.
+ */
+ if (BLI_ghash_size(id_node->components) == 0) {
+ ComponentDepsNode *comp_cow =
+ id_node->add_component(DEG_NODE_TYPE_COPY_ON_WRITE);
+ OperationDepsNode *op_cow = comp_cow->add_operation(
+ function_bind(deg_evaluate_copy_on_write, _1, graph_, id_node),
+ DEG_OPCODE_COPY_ON_WRITE,
+ "", -1);
+ graph_->operations.push_back(op_cow);
+ }
+ return id_node;
+}
+
+IDDepsNode *DepsgraphNodeBuilder::find_id_node(ID *id)
+{
+ return graph_->find_id_node(id);
}
TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source()
@@ -274,6 +319,32 @@ OperationDepsNode *DepsgraphNodeBuilder::find_operation_node(
return find_operation_node(id, comp_type, "", opcode, name, name_tag);
}
+ID *DepsgraphNodeBuilder::get_cow_id(const ID *id_orig) const
+{
+ return graph_->get_cow_id(id_orig);
+}
+
+ID *DepsgraphNodeBuilder::ensure_cow_id(ID *id_orig)
+{
+ if (id_orig->tag & LIB_TAG_COPY_ON_WRITE) {
+ /* ID is already remapped to copy-on-write. */
+ return id_orig;
+ }
+ IDDepsNode *id_node = add_id_node(id_orig, false);
+ return id_node->id_cow;
+}
+
+ID *DepsgraphNodeBuilder::expand_cow_id(IDDepsNode *id_node)
+{
+ return deg_expand_copy_on_write_datablock(graph_, id_node, this, true);
+}
+
+ID *DepsgraphNodeBuilder::expand_cow_id(ID *id_orig)
+{
+ IDDepsNode *id_node = add_id_node(id_orig);
+ return expand_cow_id(id_node);
+}
+
/* **** Build functions for entity nodes **** */
void DepsgraphNodeBuilder::begin_build() {
@@ -293,9 +364,62 @@ void DepsgraphNodeBuilder::begin_build() {
}
}
FOREACH_NODETREE_END;
+
+ if (DEG_depsgraph_use_copy_on_write()) {
+ /* Store existing copy-on-write versions of datablock, so we can re-use
+ * them for new ID nodes.
+ */
+ cow_id_hash_ = BLI_ghash_ptr_new("Depsgraph id hash");
+ foreach (IDDepsNode *id_node, graph_->id_nodes) {
+ if (deg_copy_on_write_is_expanded(id_node->id_cow)) {
+ BLI_ghash_insert(cow_id_hash_,
+ id_node->id_orig,
+ id_node->id_cow);
+ id_node->id_cow = NULL;
+ }
+ }
+ }
+
+ GSET_FOREACH_BEGIN(OperationDepsNode *, op_node, graph_->entry_tags)
+ {
+ ComponentDepsNode *comp_node = op_node->owner;
+ IDDepsNode *id_node = comp_node->owner;
+
+ SavedEntryTag entry_tag;
+ entry_tag.id = id_node->id_orig;
+ entry_tag.component_type = comp_node->type;
+ entry_tag.opcode = op_node->opcode;
+ saved_entry_tags_.push_back(entry_tag);
+ };
+ GSET_FOREACH_END();
+
+ /* Make sure graph has no nodes left from previous state. */
+ graph_->clear_all_nodes();
+ graph_->operations.clear();
+ BLI_gset_clear(graph_->entry_tags, NULL);
+}
+
+void DepsgraphNodeBuilder::end_build()
+{
+ foreach (const SavedEntryTag& entry_tag, saved_entry_tags_) {
+ IDDepsNode *id_node = find_id_node(entry_tag.id);
+ if (id_node == NULL) {
+ continue;
+ }
+ ComponentDepsNode *comp_node =
+ id_node->find_component(entry_tag.component_type);
+ if (comp_node == NULL) {
+ continue;
+ }
+ OperationDepsNode *op_node = comp_node->find_operation(entry_tag.opcode);
+ if (op_node == NULL) {
+ continue;
+ }
+ op_node->tag_update(graph_);
+ }
}
-void DepsgraphNodeBuilder::build_group(Base *base, Group *group)
+void DepsgraphNodeBuilder::build_group(Group *group)
{
ID *group_id = &group->id;
if (group_id->tag & LIB_TAG_DOIT) {
@@ -303,42 +427,41 @@ void DepsgraphNodeBuilder::build_group(Base *base, Group *group)
}
group_id->tag |= LIB_TAG_DOIT;
- LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
- build_object(base, go->ob);
+ LINKLIST_FOREACH(Base *, base, &group->view_layer->object_bases) {
+ build_object(NULL, base->object, DEG_ID_LINKED_INDIRECTLY);
}
+
+ build_view_layer_collections(&group->id, group->view_layer);
}
-void DepsgraphNodeBuilder::build_object(Base *base, Object *object)
+void DepsgraphNodeBuilder::build_object(Base *base,
+ Object *object,
+ eDepsNode_LinkedState_Type linked_state)
{
- const bool has_object = (object->id.tag & LIB_TAG_DOIT);
- IDDepsNode *id_node = (has_object)
- ? graph_->find_id_node(&object->id)
- : add_id_node(&object->id);
- /* Update node layers.
- * 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;
- }
- if (object->type == OB_CAMERA) {
- /* Camera should always be updated, it used directly by viewport.
- *
- * TODO(sergey): Make it only for active scene camera.
- */
- id_node->layers |= (unsigned int)(-1);
- }
/* Skip rest of components if the ID node was already there. */
- if (has_object) {
+ if (object->id.tag & LIB_TAG_DOIT) {
+ IDDepsNode *id_node = find_id_node(&object->id);
+ /* We need to build some extra stuff if object becomes linked
+ * directly.
+ */
+ if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) {
+ build_object_flags(base, object, linked_state);
+ }
+ id_node->linked_state = max(id_node->linked_state, linked_state);
return;
}
object->id.tag |= LIB_TAG_DOIT;
+ /* Create ID node for object and begin init. */
+ IDDepsNode *id_node = add_id_node(&object->id);
+ id_node->linked_state = linked_state;
object->customdata_mask = 0;
+ /* Various flags, flushing from bases/collections. */
+ build_object_flags(base, object, linked_state);
/* Transform. */
build_object_transform(object);
/* Parent. */
if (object->parent != NULL) {
- build_object(NULL, object->parent);
+ build_object(NULL, object->parent, DEG_ID_LINKED_INDIRECTLY);
}
/* Modifiers. */
if (object->modifiers.first != NULL) {
@@ -372,23 +495,41 @@ void DepsgraphNodeBuilder::build_object(Base *base, Object *object)
/* Object that this is a proxy for. */
if (object->proxy) {
object->proxy->proxy_from = object;
- build_object(base, object->proxy);
+ build_object(NULL, object->proxy, DEG_ID_LINKED_INDIRECTLY);
}
/* Object dupligroup. */
if (object->dup_group != NULL) {
- build_group(base, object->dup_group);
+ build_group(object->dup_group);
}
}
+void DepsgraphNodeBuilder::build_object_flags(
+ Base *base,
+ Object *object,
+ eDepsNode_LinkedState_Type linked_state)
+{
+ if (base == NULL) {
+ return;
+ }
+ /* TODO(sergey): Is this really best component to be used? */
+ Object *object_cow = get_cow_datablock(object);
+ const bool is_from_set = (linked_state == DEG_ID_LINKED_VIA_SET);
+ add_operation_node(&object->id,
+ DEG_NODE_TYPE_LAYER_COLLECTIONS,
+ function_bind(BKE_object_eval_flush_base_flags,
+ _1, object_cow, base, is_from_set),
+ DEG_OPCODE_OBJECT_BASE_FLAGS);
+}
+
void DepsgraphNodeBuilder::build_object_data(Object *object)
{
if (object->data == NULL) {
return;
}
IDDepsNode *id_node = graph_->find_id_node(&object->id);
- /* type-specific data... */
+ /* type-specific data. */
switch (object->type) {
- case OB_MESH: /* Geometry */
+ case OB_MESH:
case OB_CURVE:
case OB_FONT:
case OB_SURF:
@@ -419,6 +560,9 @@ void DepsgraphNodeBuilder::build_object_data(Object *object)
case OB_CAMERA:
build_camera(object);
break;
+ case OB_LIGHTPROBE:
+ build_lightprobe(object);
+ break;
default:
{
ID *obdata = (ID *)object->data;
@@ -433,39 +577,44 @@ void DepsgraphNodeBuilder::build_object_data(Object *object)
void DepsgraphNodeBuilder::build_object_transform(Object *object)
{
OperationDepsNode *op_node;
+ Scene *scene_cow = get_cow_datablock(scene_);
+ Object *ob_cow = get_cow_datablock(object);
/* local transforms (from transform channels - loc/rot/scale + deltas) */
op_node = add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_object_eval_local_transform, _1, object),
+ function_bind(BKE_object_eval_local_transform,
+ _1,
+ ob_cow),
DEG_OPCODE_TRANSFORM_LOCAL);
op_node->set_as_entry();
/* object parent */
- if (object->parent) {
+ if (object->parent != NULL) {
add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_object_eval_parent, _1, scene_, object),
+ function_bind(BKE_object_eval_parent,
+ _1,
+ scene_cow,
+ ob_cow),
DEG_OPCODE_TRANSFORM_PARENT);
}
/* object constraints */
- if (object->constraints.first) {
+ if (object->constraints.first != NULL) {
build_object_constraints(object);
}
- /* Temporary uber-update node, which does everything.
- * It is for the being we're porting old dependencies into the new system.
- * We'll get rid of this node as soon as all the granular update functions
- * are filled in.
- *
- * TODO(sergey): Get rid of this node.
- */
+ /* Rest of transformation update. */
add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_object_eval_uber_transform, _1, object),
+ function_bind(BKE_object_eval_uber_transform,
+ _1,
+ ob_cow),
DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL);
/* object transform is done */
op_node = add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_object_eval_done, _1, object),
+ function_bind(BKE_object_eval_done,
+ _1,
+ ob_cow),
DEG_OPCODE_TRANSFORM_FINAL);
op_node->set_as_exit();
}
@@ -491,7 +640,10 @@ void DepsgraphNodeBuilder::build_object_constraints(Object *object)
{
/* create node for constraint stack */
add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_object_eval_constraints, _1, scene_, object),
+ function_bind(BKE_object_eval_constraints,
+ _1,
+ get_cow_datablock(scene_),
+ get_cow_datablock(object)),
DEG_OPCODE_TRANSFORM_CONSTRAINTS);
}
@@ -502,23 +654,34 @@ void DepsgraphNodeBuilder::build_object_constraints(Object *object)
void DepsgraphNodeBuilder::build_animdata(ID *id)
{
AnimData *adt = BKE_animdata_from_id(id);
-
- if (adt == NULL)
+ if (adt == NULL) {
return;
+ }
/* animation */
if (adt->action || adt->nla_tracks.first || adt->drivers.first) {
- // XXX: Hook up specific update callbacks for special properties which may need it...
+ (void) add_id_node(id);
+ ID *id_cow = get_cow_id(id);
+
+ // XXX: Hook up specific update callbacks for special properties which
+ // may need it...
- /* actions and NLA - as a single unit for now, as it gets complicated to schedule otherwise */
+ /* actions and NLA - as a single unit for now, as it gets complicated to
+ * schedule otherwise.
+ */
if ((adt->action) || (adt->nla_tracks.first)) {
/* create the node */
add_operation_node(id, DEG_NODE_TYPE_ANIMATION,
- function_bind(BKE_animsys_eval_animdata, _1, id),
- DEG_OPCODE_ANIMATION, id->name);
-
- // TODO: for each channel affected, we might also want to add some support for running RNA update callbacks on them
- // (which will be needed for proper handling of drivers later)
+ function_bind(BKE_animsys_eval_animdata,
+ _1,
+ id_cow),
+ DEG_OPCODE_ANIMATION,
+ id->name);
+
+ /* TODO: for each channel affected, we might also want to add some
+ * support for running RNA update callbacks on them
+ * (which will be needed for proper handling of drivers later)
+ */
}
/* drivers */
@@ -536,21 +699,28 @@ void DepsgraphNodeBuilder::build_animdata(ID *id)
*/
OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu)
{
+ ID *id_cow = get_cow_id(id);
+
/* Create data node for this driver */
/* TODO(sergey): Avoid creating same operation multiple times,
* in the future we need to avoid lookup of the operation as well
* and use some tagging magic instead.
*/
- OperationDepsNode *driver_op = find_operation_node(id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
+ OperationDepsNode *driver_op = find_operation_node(
+ id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_DRIVER,
+ fcu->rna_path ? fcu->rna_path : "",
+ fcu->array_index);
if (driver_op == NULL) {
+ /* TODO(sergey): Shall we use COW of fcu itself here? */
driver_op = add_operation_node(id,
DEG_NODE_TYPE_PARAMETERS,
- function_bind(BKE_animsys_eval_driver, _1, id, fcu),
+ function_bind(BKE_animsys_eval_driver,
+ _1,
+ id_cow,
+ fcu),
DEG_OPCODE_DRIVER,
fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
@@ -567,20 +737,19 @@ void DepsgraphNodeBuilder::build_world(World *world)
if (world_id->tag & LIB_TAG_DOIT) {
return;
}
-
+ /* Animation. */
build_animdata(world_id);
-
/* world itself */
add_operation_node(world_id,
- DEG_NODE_TYPE_PARAMETERS,
- NULL,
- DEG_OPCODE_PARAMETERS_EVAL);
-
+ DEG_NODE_TYPE_SHADING,
+ function_bind(BKE_world_eval,
+ _1,
+ get_cow_datablock(world)),
+ DEG_OPCODE_WORLD_UPDATE);
/* textures */
build_texture_stack(world->mtex);
-
/* world's nodetree */
- if (world->nodetree) {
+ if (world->nodetree != NULL) {
build_nodetree(world->nodetree);
}
}
@@ -589,55 +758,66 @@ void DepsgraphNodeBuilder::build_world(World *world)
void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
+ Scene *scene_cow = get_cow_datablock(scene);
/**
* Rigidbody Simulation Nodes
* ==========================
*
* There are 3 nodes related to Rigidbody Simulation:
- * 1) "Initialize/Rebuild World" - this is called sparingly, only when the simulation
- * needs to be rebuilt (mainly after file reload, or moving back to start frame)
- * 2) "Do Simulation" - perform a simulation step - interleaved between the evaluation
- * steps for clusters of objects (i.e. between those affected and/or not affected by
- * the sim for instance)
+ * 1) "Initialize/Rebuild World" - this is called sparingly, only when the
+ * simulation needs to be rebuilt (mainly after file reload, or moving
+ * back to start frame)
+ * 2) "Do Simulation" - perform a simulation step - interleaved between the
+ * evaluation steps for clusters of objects (i.e. between those affected
+ * and/or not affected by the sim for instance).
*
- * 3) "Pull Results" - grab the specific transforms applied for a specific object -
- * performed as part of object's transform-stack building
+ * 3) "Pull Results" - grab the specific transforms applied for a specific
+ * object - performed as part of object's transform-stack building.
*/
- /* create nodes ------------------------------------------------------------------------ */
- /* XXX: is this the right component, or do we want to use another one instead? */
+ /* Create nodes --------------------------------------------------------- */
+
+ /* XXX: is this the right component, or do we want to use another one
+ * instead?
+ */
/* init/rebuild operation */
- /*OperationDepsNode *init_node =*/ add_operation_node(&scene->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_rigidbody_rebuild_sim, _1, scene),
- DEG_OPCODE_RIGIDBODY_REBUILD);
+ /*OperationDepsNode *init_node =*/ add_operation_node(
+ &scene->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_rigidbody_rebuild_sim, _1, scene_cow),
+ DEG_OPCODE_RIGIDBODY_REBUILD);
/* do-sim operation */
// XXX: what happens if we need to split into several groups?
- OperationDepsNode *sim_node = add_operation_node(&scene->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_rigidbody_eval_simulation, _1, scene),
- DEG_OPCODE_RIGIDBODY_SIM);
+ OperationDepsNode *sim_node = add_operation_node(
+ &scene->id, DEG_NODE_TYPE_TRANSFORM,
+ function_bind(BKE_rigidbody_eval_simulation, _1, scene_cow),
+ DEG_OPCODE_RIGIDBODY_SIM);
- /* XXX: For now, the sim node is the only one that really matters here. If any other
- * sims get added later, we may have to remove these hacks...
+ /* XXX: For now, the sim node is the only one that really matters here.
+ * If any other sims get added later, we may have to remove these hacks...
*/
sim_node->owner->entry_operation = sim_node;
sim_node->owner->exit_operation = sim_node;
-
/* objects - simulation participants */
if (rbw->group) {
- LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) {
- Object *object = go->ob;
+ LINKLIST_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) {
+ Object *object = base->object;
if (!object || (object->type != OB_MESH))
continue;
/* 2) create operation for flushing results */
- /* object's transform component - where the rigidbody operation lives */
+ /* object's transform component - where the rigidbody operation
+ * lives. */
add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM,
- function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, object),
+ function_bind(
+ BKE_rigidbody_object_sync_transforms,
+ _1,
+ scene_cow,
+ get_cow_datablock(object)),
DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY);
}
}
@@ -664,41 +844,76 @@ void DepsgraphNodeBuilder::build_particles(Object *object)
ComponentDepsNode *psys_comp =
add_component_node(&object->id, DEG_NODE_TYPE_EVAL_PARTICLES);
+ /* TODO(sergey): Need to get COW of PSYS. */
+ Scene *scene_cow = get_cow_datablock(scene_);
+ Object *ob_cow = get_cow_datablock(object);
+
add_operation_node(psys_comp,
function_bind(BKE_particle_system_eval_init,
_1,
- scene_,
- object),
+ scene_cow,
+ ob_cow),
DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT);
/* particle systems */
LINKLIST_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
ParticleSettings *part = psys->part;
- /* particle settings */
- // XXX: what if this is used more than once!
- build_animdata(&part->id);
+ /* Build particle settings operations.
+ *
+ * NOTE: The call itself ensures settings are only build once.
+ */
+ build_particle_settings(part);
- /* this particle system */
- // TODO: for now, this will just be a placeholder "ubereval" node
+ /* Update on particle settings change. */
+ add_operation_node(psys_comp,
+ function_bind(BKE_particle_system_settings_eval,
+ _1,
+ psys),
+ DEG_OPCODE_PARTICLE_SETTINGS_EVAL,
+ psys->name);
+
+ /* Particle system evaluation. */
add_operation_node(psys_comp,
NULL,
DEG_OPCODE_PARTICLE_SYSTEM_EVAL,
psys->name);
}
- /* pointcache */
- // TODO...
+ /* TODO(sergey): Do we need a point cache operations here? */
+}
+
+void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *part) {
+ ID *part_id = &part->id;
+ if (part_id->tag & LIB_TAG_DOIT) {
+ return;
+ }
+ part_id->tag |= LIB_TAG_DOIT;
+ /* Animation data. */
+ build_animdata(part_id);
+ /* Parameters change. */
+ add_operation_node(part_id,
+ DEG_NODE_TYPE_PARAMETERS,
+ NULL,
+ DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
+ add_operation_node(part_id,
+ DEG_NODE_TYPE_PARAMETERS,
+ function_bind(BKE_particle_system_settings_recalc_clear,
+ _1,
+ part),
+ DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
}
void DepsgraphNodeBuilder::build_cloth(Object *object)
{
+ Scene *scene_cow = get_cow_datablock(scene_);
+ Object *object_cow = get_cow_datablock(object);
add_operation_node(&object->id,
DEG_NODE_TYPE_CACHE,
function_bind(BKE_object_eval_cloth,
_1,
- scene_,
- object),
+ scene_cow,
+ object_cow),
DEG_OPCODE_GEOMETRY_CLOTH_MODIFIER);
}
@@ -716,8 +931,9 @@ void DepsgraphNodeBuilder::build_shapekeys(Key *key)
// XXX: what happens if the datablock is shared!
void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
{
- ID *obdata = (ID *)object->data;
OperationDepsNode *op_node;
+ Scene *scene_cow = get_cow_datablock(scene_);
+ Object *object_cow = get_cow_datablock(object);
/* TODO(sergey): This way using this object's properties as driver target
* works fine.
@@ -741,8 +957,8 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
DEG_NODE_TYPE_GEOMETRY,
function_bind(BKE_object_eval_uber_data,
_1,
- scene_,
- object),
+ scene_cow,
+ object_cow),
DEG_OPCODE_GEOMETRY_UBEREVAL);
op_node->set_as_exit();
@@ -763,10 +979,21 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
}
/* materials */
- for (int a = 1; a <= object->totcol; a++) {
- Material *ma = give_current_material(object, a);
- if (ma != NULL) {
- build_material(ma);
+ if (object->totcol != 0) {
+ if (object->type == OB_MESH) {
+ add_operation_node(&object->id,
+ DEG_NODE_TYPE_SHADING,
+ function_bind(BKE_object_eval_update_shading,
+ _1,
+ object_cow),
+ DEG_OPCODE_SHADING);
+ }
+
+ for (int a = 1; a <= object->totcol; a++) {
+ Material *ma = give_current_material(object, a);
+ if (ma != NULL) {
+ build_material(ma);
+ }
}
}
@@ -775,9 +1002,14 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
// add geometry collider relations
}
+ ID *obdata = (ID *)object->data;
if (obdata->tag & LIB_TAG_DOIT) {
return;
}
+ obdata->tag |= LIB_TAG_DOIT;
+ /* Make sure we've got an ID node before requesting CoW pointer. */
+ (void) add_id_node((ID *)obdata);
+ ID *obdata_cow = get_cow_id(obdata);
/* ShapeKeys */
Key *key = BKE_key_from_object(object);
@@ -800,7 +1032,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
DEG_NODE_TYPE_GEOMETRY,
function_bind(BKE_mesh_eval_geometry,
_1,
- (Mesh *)obdata),
+ (Mesh *)obdata_cow),
DEG_OPCODE_PLACEHOLDER,
"Geometry Eval");
op_node->set_as_entry();
@@ -817,9 +1049,10 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
/* metaball evaluation operations */
op_node = add_operation_node(obdata,
DEG_NODE_TYPE_GEOMETRY,
- function_bind(BKE_mball_eval_geometry,
- _1,
- (MetaBall *)obdata),
+ function_bind(
+ BKE_mball_eval_geometry,
+ _1,
+ (MetaBall *)obdata_cow),
DEG_OPCODE_PLACEHOLDER,
"Geometry Eval");
}
@@ -844,23 +1077,22 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
DEG_NODE_TYPE_GEOMETRY,
function_bind(BKE_curve_eval_geometry,
_1,
- (Curve *)obdata),
+ (Curve *)obdata_cow),
DEG_OPCODE_PLACEHOLDER,
"Geometry Eval");
op_node->set_as_entry();
-
/* Make sure objects used for bevel.taper are in the graph.
* NOTE: This objects might be not linked to the scene.
*/
Curve *cu = (Curve *)obdata;
if (cu->bevobj != NULL) {
- build_object(NULL, cu->bevobj);
+ build_object(NULL, cu->bevobj, DEG_ID_LINKED_INDIRECTLY);
}
if (cu->taperobj != NULL) {
- build_object(NULL, cu->taperobj);
+ build_object(NULL, cu->taperobj, DEG_ID_LINKED_INDIRECTLY);
}
if (object->type == OB_FONT && cu->textoncurve != NULL) {
- build_object(NULL, cu->textoncurve);
+ build_object(NULL, cu->textoncurve, DEG_ID_LINKED_INDIRECTLY);
}
break;
}
@@ -872,7 +1104,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
DEG_NODE_TYPE_GEOMETRY,
function_bind(BKE_lattice_eval_geometry,
_1,
- (Lattice *)obdata),
+ (Lattice *)obdata_cow),
DEG_OPCODE_PLACEHOLDER,
"Geometry Eval");
op_node->set_as_entry();
@@ -889,12 +1121,28 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PARAMETERS_EVAL);
+
+ /* Batch cache. */
+ add_operation_node(obdata,
+ DEG_NODE_TYPE_BATCH_CACHE,
+ function_bind(BKE_object_data_select_update,
+ _1,
+ obdata_cow),
+ DEG_OPCODE_GEOMETRY_SELECT_UPDATE);
}
/* Cameras */
void DepsgraphNodeBuilder::build_camera(Object *object)
{
- /* TODO: Link scene-camera links in somehow... */
+ /* Object itself. */
+ add_operation_node(&object->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ NULL,
+ DEG_OPCODE_PARAMETERS_EVAL,
+ "Camera Parameters");
+
+ /* Object data. */
+ /* TODO: Link scene-camera links in somehow. */
Camera *cam = (Camera *)object->data;
ID *camera_id = &cam->id;
if (camera_id->tag & LIB_TAG_DOIT) {
@@ -907,17 +1155,19 @@ void DepsgraphNodeBuilder::build_camera(Object *object)
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PARAMETERS_EVAL);
-
- if (cam->dof_ob != NULL) {
- /* TODO(sergey): For now parametrs are on object level. */
- add_operation_node(&object->id, DEG_NODE_TYPE_PARAMETERS, NULL,
- DEG_OPCODE_PLACEHOLDER, "Camera DOF");
- }
}
/* Lamps */
void DepsgraphNodeBuilder::build_lamp(Object *object)
{
+ /* Object itself. */
+ add_operation_node(&object->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ NULL,
+ DEG_OPCODE_PARAMETERS_EVAL,
+ "Lamp Parameters");
+
+ /* Object data. */
Lamp *la = (Lamp *)object->data;
ID *lamp_id = &la->id;
if (lamp_id->tag & LIB_TAG_DOIT) {
@@ -926,7 +1176,6 @@ void DepsgraphNodeBuilder::build_lamp(Object *object)
build_animdata(&la->id);
- /* TODO(sergey): Is it really how we're supposed to work with drivers? */
add_operation_node(lamp_id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
@@ -943,22 +1192,30 @@ void DepsgraphNodeBuilder::build_lamp(Object *object)
void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
{
- if (!ntree)
+ if (ntree == NULL) {
return;
-
+ }
/* nodetree itself */
ID *ntree_id = &ntree->id;
- OperationDepsNode *op_node;
-
+ add_id_node(ntree_id);
+ bNodeTree *ntree_cow = get_cow_datablock(ntree);
+ /* Animation, */
build_animdata(ntree_id);
-
- /* Parameters for drivers. */
- op_node = add_operation_node(ntree_id,
- DEG_NODE_TYPE_PARAMETERS,
- NULL,
- DEG_OPCODE_PARAMETERS_EVAL);
- op_node->set_as_exit();
-
+ /* Shading update. */
+ add_operation_node(ntree_id,
+ DEG_NODE_TYPE_SHADING,
+ NULL,
+ DEG_OPCODE_MATERIAL_UPDATE);
+ /* NOTE: We really pass original and CoW node trees here, this is how the
+ * callback works. Ideally we need to find a better way for that.
+ */
+ add_operation_node(ntree_id,
+ DEG_NODE_TYPE_SHADING_PARAMETERS,
+ function_bind(BKE_nodetree_shading_params_eval,
+ _1,
+ ntree_cow,
+ ntree),
+ DEG_OPCODE_MATERIAL_UPDATE);
/* nodetree's nodes... */
LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) {
ID *id = bnode->id;
@@ -976,7 +1233,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
build_image((Image *)id);
}
else if (id_type == ID_OB) {
- build_object(NULL, (Object *)id);
+ build_object(NULL, (Object *)id, DEG_ID_LINKED_INDIRECTLY);
}
else if (id_type == ID_SCE) {
/* Scenes are used by compositor trees, and handled by render
@@ -1001,36 +1258,40 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
}
/* Recursively build graph for material */
-void DepsgraphNodeBuilder::build_material(Material *ma)
+void DepsgraphNodeBuilder::build_material(Material *material)
{
- ID *ma_id = &ma->id;
- if (ma_id->tag & LIB_TAG_DOIT) {
+ ID *material_id = &material->id;
+ if (material_id->tag & LIB_TAG_DOIT) {
return;
}
-
- add_operation_node(ma_id, DEG_NODE_TYPE_SHADING, NULL,
- DEG_OPCODE_PLACEHOLDER, "Material Update");
-
- /* material animation */
- build_animdata(ma_id);
-
- /* textures */
- build_texture_stack(ma->mtex);
-
- /* material's nodetree */
- build_nodetree(ma->nodetree);
+ material_id->tag |= LIB_TAG_DOIT;
+ /* Material itself. */
+ add_id_node(material_id);
+ Material *material_cow = get_cow_datablock(material);
+ /* Shading update. */
+ add_operation_node(material_id,
+ DEG_NODE_TYPE_SHADING,
+ function_bind(BKE_material_eval,
+ _1,
+ material_cow),
+ DEG_OPCODE_MATERIAL_UPDATE);
+ /* Material animation. */
+ build_animdata(material_id);
+ /* Textures. */
+ build_texture_stack(material->mtex);
+ /* Material's nodetree. */
+ build_nodetree(material->nodetree);
}
/* Texture-stack attached to some shading datablock */
void DepsgraphNodeBuilder::build_texture_stack(MTex **texture_stack)
{
- int i;
-
/* for now assume that all texture-stacks have same number of max items */
- for (i = 0; i < MAX_MTEX; i++) {
+ for (int i = 0; i < MAX_MTEX; i++) {
MTex *mtex = texture_stack[i];
- if (mtex && mtex->tex)
+ if (mtex && mtex->tex) {
build_texture(mtex->tex);
+ }
}
}
@@ -1075,7 +1336,9 @@ void DepsgraphNodeBuilder::build_compositor(Scene *scene)
// XXX: component type undefined!
//graph->get_node(&scene->id, NULL, DEG_NODE_TYPE_COMPOSITING, NULL);
- /* for now, nodetrees are just parameters; compositing occurs in internals of renderer... */
+ /* for now, nodetrees are just parameters; compositing occurs in internals
+ * of renderer...
+ */
add_component_node(&scene->id, DEG_NODE_TYPE_PARAMETERS);
build_nodetree(scene->nodetree);
}
@@ -1107,29 +1370,55 @@ void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file)
void DepsgraphNodeBuilder::build_mask(Mask *mask)
{
ID *mask_id = &mask->id;
+ Mask *mask_cow = get_cow_datablock(mask);
/* F-Curve based animation. */
build_animdata(mask_id);
/* Animation based on mask's shapes. */
add_operation_node(mask_id,
DEG_NODE_TYPE_ANIMATION,
- function_bind(BKE_mask_eval_animation, _1, mask),
+ function_bind(BKE_mask_eval_animation, _1, mask_cow),
DEG_OPCODE_MASK_ANIMATION);
/* Final mask evaluation. */
add_operation_node(mask_id,
DEG_NODE_TYPE_PARAMETERS,
- function_bind(BKE_mask_eval_update, _1, mask),
+ function_bind(BKE_mask_eval_update, _1, mask_cow),
DEG_OPCODE_MASK_EVAL);
}
-void DepsgraphNodeBuilder::build_movieclip(MovieClip *clip) {
+void DepsgraphNodeBuilder::build_movieclip(MovieClip *clip)
+{
ID *clip_id = &clip->id;
+ MovieClip *clip_cow = get_cow_datablock(clip);
/* Animation. */
build_animdata(clip_id);
/* Movie clip evaluation. */
add_operation_node(clip_id,
DEG_NODE_TYPE_PARAMETERS,
- function_bind(BKE_movieclip_eval_update, _1, clip),
+ function_bind(BKE_movieclip_eval_update, _1, clip_cow),
DEG_OPCODE_MOVIECLIP_EVAL);
}
+void DepsgraphNodeBuilder::build_lightprobe(Object *object)
+{
+ LightProbe *probe = (LightProbe *)object->data;
+ ID *probe_id = &probe->id;
+ if (probe_id->tag & LIB_TAG_DOIT) {
+ return;
+ }
+ probe_id->tag |= LIB_TAG_DOIT;
+ /* Placeholder so we can add relations and tag ID node for update. */
+ add_operation_node(probe_id,
+ DEG_NODE_TYPE_PARAMETERS,
+ NULL,
+ DEG_OPCODE_PLACEHOLDER,
+ "LightProbe Eval");
+ add_operation_node(&object->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ NULL,
+ DEG_OPCODE_PLACEHOLDER,
+ "LightProbe Eval");
+
+ build_animdata(probe_id);
+}
+
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 2fa9ba01cc7..c9bdd194227 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -32,6 +32,8 @@
#include "intern/depsgraph_types.h"
+#include "DEG_depsgraph.h" /* used for DEG_depsgraph_use_copy_on_write() */
+
struct Base;
struct CacheFile;
struct bGPdata;
@@ -42,6 +44,7 @@ struct Image;
struct FCurve;
struct Group;
struct Key;
+struct LayerCollection;
struct Main;
struct Material;
struct Mask;
@@ -49,6 +52,8 @@ struct MTex;
struct MovieClip;
struct bNodeTree;
struct Object;
+struct ParticleSettings;
+struct Probe;
struct bPoseChannel;
struct bConstraint;
struct Scene;
@@ -70,9 +75,45 @@ struct DepsgraphNodeBuilder {
DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph);
~DepsgraphNodeBuilder();
+ /* For given original ID get ID which is created by CoW system. */
+ ID *get_cow_id(const ID *id_orig) const;
+ /* Similar to above, but for the cases when there is no ID node we create
+ * one.
+ */
+ ID *ensure_cow_id(ID *id_orig);
+
+ /* Helper wrapper function which wraps get_cow_id with a needed type cast. */
+ template<typename T>
+ T *get_cow_datablock(const T *orig) const {
+ return (T *)get_cow_id(&orig->id);
+ }
+
+ /* Get fully expanded (ready for use) copy-on-write datablock for the given
+ * original datablock.
+ */
+ ID *expand_cow_id(IDDepsNode *id_node);
+ ID *expand_cow_id(ID *id_orig);
+ template<typename T>
+ T *expand_cow_datablock(T *orig) {
+ return (T *)expand_cow_id(&orig->id);
+ }
+
+ /* For a given COW datablock get corresponding original one. */
+ template<typename T>
+ T *get_orig_datablock(const T *cow) const {
+ if (DEG_depsgraph_use_copy_on_write()) {
+ return (T *)cow->id.newid;
+ }
+ else {
+ return (T *)cow;
+ }
+ }
+
void begin_build();
+ void end_build();
- IDDepsNode *add_id_node(ID *id);
+ IDDepsNode *add_id_node(ID *id, bool do_tag = true);
+ IDDepsNode *find_id_node(ID *id);
TimeSourceDepsNode *add_time_source();
ComponentDepsNode *add_component_node(ID *id,
@@ -118,15 +159,23 @@ struct DepsgraphNodeBuilder {
const char *name = "",
int name_tag = -1);
- void build_scene(Scene *scene);
- void build_group(Base *base, Group *group);
- void build_object(Base *base, Object *object);
+ void build_view_layer(Scene *scene,
+ ViewLayer *view_layer,
+ eDepsNode_LinkedState_Type linked_state);
+ void build_group(Group *group);
+ void build_object(Base *base,
+ Object *object,
+ eDepsNode_LinkedState_Type linked_state);
+ void build_object_flags(Base *base,
+ Object *object,
+ eDepsNode_LinkedState_Type linked_state);
void build_object_data(Object *object);
void build_object_transform(Object *object);
void build_object_constraints(Object *object);
void build_pose_constraints(Object *object, bPoseChannel *pchan);
void build_rigidbody(Scene *scene);
void build_particles(Object *object);
+ void build_particle_settings(ParticleSettings *part);
void build_cloth(Object *object);
void build_animdata(ID *id);
OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
@@ -153,14 +202,35 @@ struct DepsgraphNodeBuilder {
void build_cachefile(CacheFile *cache_file);
void build_mask(Mask *mask);
void build_movieclip(MovieClip *clip);
-
+ void build_lightprobe(Object *object);
+
+ struct LayerCollectionState {
+ int index;
+ LayerCollection *parent;
+ };
+ void build_layer_collection(ID *owner_id,
+ LayerCollection *layer_collection,
+ LayerCollectionState *state);
+ void build_layer_collections(ID *owner_id,
+ ListBase *layer_collections,
+ LayerCollectionState *state);
+ void build_view_layer_collections(ID *owner_id, ViewLayer *view_layer);
protected:
+ struct SavedEntryTag {
+ ID *id;
+ eDepsNode_Type component_type;
+ eDepsOperation_Code opcode;
+ };
+ vector<SavedEntryTag> saved_entry_tags_;
+
/* State which never changes, same for the whole builder time. */
Main *bmain_;
Depsgraph *graph_;
/* State which demotes currently built entities. */
Scene *scene_;
+
+ GHash *cow_id_hash_;
};
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc
new file mode 100644
index 00000000000..79316e47022
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc
@@ -0,0 +1,126 @@
+/*
+ * ***** 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc
+ * \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph's nodes
+ */
+
+#include "intern/builder/deg_builder_nodes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "BKE_layer.h"
+
+#include "DNA_scene_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+} /* extern "C" */
+
+#include "intern/builder/deg_builder.h"
+#include "intern/eval/deg_eval_copy_on_write.h"
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+#include "intern/depsgraph_types.h"
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+void DepsgraphNodeBuilder::build_layer_collection(
+ ID *owner_id,
+ LayerCollection *layer_collection,
+ LayerCollectionState *state)
+{
+ /* TODO(sergey): This will attempt to create component for each collection.
+ * Harmless but could be optimized.
+ */
+ ComponentDepsNode *comp = add_component_node(
+ owner_id,
+ DEG_NODE_TYPE_LAYER_COLLECTIONS);
+
+ add_operation_node(comp,
+ function_bind(BKE_layer_eval_layer_collection,
+ _1,
+ layer_collection,
+ state->parent),
+ DEG_OPCODE_VIEW_LAYER_EVAL,
+ layer_collection->scene_collection->name,
+ state->index);
+ ++state->index;
+
+ /* Recurs into nested layer collections. */
+ LayerCollection *parent = state->parent;
+ state->parent = layer_collection;
+ build_layer_collections(owner_id, &layer_collection->layer_collections, state);
+ state->parent = parent;
+}
+
+void DepsgraphNodeBuilder::build_layer_collections(ID *owner_id,
+ ListBase *layer_collections,
+ LayerCollectionState *state)
+{
+ LINKLIST_FOREACH (LayerCollection *, layer_collection, layer_collections) {
+ build_layer_collection(owner_id, layer_collection, state);
+ }
+}
+
+void DepsgraphNodeBuilder::build_view_layer_collections(
+ ID *owner_id,
+ ViewLayer *view_layer)
+{
+ LayerCollectionState state;
+ state.index = 0;
+ ComponentDepsNode *comp = add_component_node(
+ owner_id,
+ DEG_NODE_TYPE_LAYER_COLLECTIONS);
+ add_operation_node(comp,
+ function_bind(BKE_layer_eval_layer_collection_pre,
+ _1,
+ owner_id,
+ view_layer),
+ DEG_OPCODE_VIEW_LAYER_INIT);
+ add_operation_node(comp,
+ function_bind(BKE_layer_eval_layer_collection_post,
+ _1,
+ view_layer),
+ DEG_OPCODE_VIEW_LAYER_DONE);
+ state.parent = NULL;
+ build_layer_collections(owner_id, &view_layer->layer_collections, &state);
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
index 9868a8d2208..531ea55cf5c 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
@@ -46,6 +46,7 @@ extern "C" {
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BKE_action.h"
#include "BKE_armature.h"
@@ -55,6 +56,7 @@ extern "C" {
#include "DEG_depsgraph_build.h"
#include "intern/builder/deg_builder.h"
+#include "intern/eval/deg_eval_copy_on_write.h"
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
@@ -64,16 +66,23 @@ extern "C" {
namespace DEG {
-void DepsgraphNodeBuilder::build_pose_constraints(Object *object, bPoseChannel *pchan)
+void DepsgraphNodeBuilder::build_pose_constraints(Object *object,
+ bPoseChannel *pchan)
{
/* create node for constraint stack */
add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
- function_bind(BKE_pose_constraints_evaluate, _1, scene_, object, pchan),
+ function_bind(BKE_pose_constraints_evaluate,
+ _1,
+ get_cow_datablock(scene_),
+ get_cow_datablock(object),
+ pchan),
DEG_OPCODE_BONE_CONSTRAINTS);
}
/* IK Solver Eval Steps */
-void DepsgraphNodeBuilder::build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con)
+void DepsgraphNodeBuilder::build_ik_pose(Object *object,
+ bPoseChannel *pchan,
+ bConstraint *con)
{
bKinematicConstraint *data = (bKinematicConstraint *)con->data;
@@ -91,12 +100,18 @@ void DepsgraphNodeBuilder::build_ik_pose(Object *object, bPoseChannel *pchan, bC
/* Operation node for evaluating/running IK Solver. */
add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
- function_bind(BKE_pose_iktree_evaluate, _1, scene_, object, rootchan),
+ function_bind(BKE_pose_iktree_evaluate,
+ _1,
+ get_cow_datablock(scene_),
+ get_cow_datablock(object),
+ rootchan),
DEG_OPCODE_POSE_IK_SOLVER);
}
/* Spline IK Eval Steps */
-void DepsgraphNodeBuilder::build_splineik_pose(Object *object, bPoseChannel *pchan, bConstraint *con)
+void DepsgraphNodeBuilder::build_splineik_pose(Object *object,
+ bPoseChannel *pchan,
+ bConstraint *con)
{
bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
@@ -104,30 +119,55 @@ void DepsgraphNodeBuilder::build_splineik_pose(Object *object, bPoseChannel *pch
bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
/* Operation node for evaluating/running Spline IK Solver.
- * Store the "root bone" of this chain in the solver, so it knows where to start.
+ * Store the "root bone" of this chain in the solver, so it knows where to
+ * start.
*/
add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
- function_bind(BKE_pose_splineik_evaluate, _1, scene_, object, rootchan),
+ function_bind(BKE_pose_splineik_evaluate,
+ _1,
+ get_cow_datablock(scene_),
+ get_cow_datablock(object),
+ rootchan),
DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
}
/* Pose/Armature Bones Graph */
void DepsgraphNodeBuilder::build_rig(Object *object)
{
- bArmature *arm = (bArmature *)object->data;
+ bArmature *armature = (bArmature *)object->data;
+ const short armature_tag = armature->id.tag;
+ Scene *scene_cow;
+ Object *object_cow;
+ bArmature *armature_cow;
+ if (DEG_depsgraph_use_copy_on_write()) {
+ /* NOTE: We need to expand both object and armature, so this way we can
+ * safely create object level pose.
+ */
+ scene_cow = get_cow_datablock(scene_);
+ object_cow = expand_cow_datablock(object);
+ armature_cow = expand_cow_datablock(armature);
+ }
+ else {
+ scene_cow = scene_;
+ object_cow = object;
+ armature_cow = armature;
+ }
OperationDepsNode *op_node;
- /* animation and/or drivers linking posebones to base-armature used to define them
+ /* Animation and/or drivers linking posebones to base-armature used to
+ * define them.
+ *
* NOTE: AnimData here is really used to control animated deform properties,
- * which ideally should be able to be unique across different instances.
- * Eventually, we need some type of proxy/isolation mechanism in-between here
- * to ensure that we can use same rig multiple times in same scene...
+ * which ideally should be able to be unique across different
+ * instances. Eventually, we need some type of proxy/isolation
+ * mechanism in-between here to ensure that we can use same rig
+ * multiple times in same scene.
*/
- if ((arm->id.tag & LIB_TAG_DOIT) == 0) {
- build_animdata(&arm->id);
+ if ((armature_tag & LIB_TAG_DOIT) == 0) {
+ build_animdata(&armature->id);
/* Make sure pose is up-to-date with armature updates. */
- add_operation_node(&arm->id,
+ add_operation_node(&armature->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PLACEHOLDER,
@@ -135,22 +175,22 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
}
/* Rebuild pose if not up to date. */
- if (object->pose == NULL || (object->pose->flag & POSE_RECALC)) {
- BKE_pose_rebuild_ex(object, arm, false);
+ if (object_cow->pose == NULL || (object->pose->flag & POSE_RECALC)) {
+ BKE_pose_rebuild(object_cow, armature_cow);
/* XXX: Without this animation gets lost in certain circumstances
* after loading file. Need to investigate further since it does
* not happen with simple scenes..
*/
- if (object->adt) {
- object->adt->recalc |= ADT_RECALC_ANIM;
+ if (object_cow->adt) {
+ object_cow->adt->recalc |= ADT_RECALC_ANIM;
}
}
/* speed optimization for animation lookups */
- if (object->pose) {
- BKE_pose_channels_hash_make(object->pose);
- if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
- BKE_pose_update_constraint_flags(object->pose);
+ if (object_cow->pose != NULL) {
+ BKE_pose_channels_hash_make(object_cow->pose);
+ if (object_cow->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
+ BKE_pose_update_constraint_flags(object_cow->pose);
}
}
@@ -171,42 +211,58 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
* - Used for representing each bone within the rig
* - Acts to encapsulate the evaluation operations (base matrix + parenting,
* and constraint stack) so that they can be easily found.
- * - Everything else which depends on bone-results hook up to the component only
- * so that we can redirect those to point at either the the post-IK/
+ * - Everything else which depends on bone-results hook up to the component
+ * only so that we can redirect those to point at either the the post-IK/
* post-constraint/post-matrix steps, as needed.
*/
/* pose eval context */
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
- function_bind(BKE_pose_eval_init, _1, scene_, object, object->pose),
+ function_bind(BKE_pose_eval_init,
+ _1,
+ scene_cow,
+ object_cow,
+ object_cow->pose),
DEG_OPCODE_POSE_INIT);
op_node->set_as_entry();
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
- function_bind(BKE_pose_eval_init_ik, _1, scene_, object, object->pose),
+ function_bind(BKE_pose_eval_init_ik,
+ _1,
+ scene_cow,
+ object_cow,
+ object_cow->pose),
DEG_OPCODE_POSE_INIT_IK);
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
- function_bind(BKE_pose_eval_flush, _1, scene_, object, object->pose),
+ function_bind(BKE_pose_eval_flush,
+ _1,
+ scene_cow,
+ object_cow,
+ object_cow->pose),
DEG_OPCODE_POSE_DONE);
op_node->set_as_exit();
/* bones */
- LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ LINKLIST_FOREACH (bPoseChannel *, pchan, &object_cow->pose->chanbase) {
/* Node for bone evaluation. */
op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, NULL,
DEG_OPCODE_BONE_LOCAL);
op_node->set_as_entry();
add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
- function_bind(BKE_pose_eval_bone, _1, scene_, object, pchan),
+ function_bind(BKE_pose_eval_bone, _1,
+ scene_cow,
+ object_cow,
+ pchan),
DEG_OPCODE_BONE_POSE_PARENT);
+ /* NOTE: Dedicated noop for easier relationship construction. */
add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
- NULL, /* NOTE: dedicated noop for easier relationship construction */
+ NULL,
DEG_OPCODE_BONE_READY);
op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
@@ -221,7 +277,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
DEG_OPCODE_PARAMETERS_EVAL,
pchan->name);
}
- /* Constraints. */
+ /* Build constraints. */
if (pchan->constraints.first != NULL) {
build_pose_constraints(object, pchan);
}
@@ -233,8 +289,9 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
* base transforms of a bunch of bones is done)
*
* Unsolved Issues:
- * - Care is needed to ensure that multi-headed trees work out the same as in ik-tree building
- * - Animated chain-lengths are a problem...
+ * - Care is needed to ensure that multi-headed trees work out the same
+ * as in ik-tree building
+ * - Animated chain-lengths are a problem.
*/
LINKLIST_FOREACH (bConstraint *, con, &pchan->constraints) {
switch (con->type) {
@@ -250,6 +307,13 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
break;
}
}
+ /* Custom shape. */
+ /* NOTE: Custom shape datablock is already remapped to CoW version. */
+ if (pchan->custom != NULL) {
+ build_object(NULL,
+ get_orig_datablock(pchan->custom),
+ DEG_ID_LINKED_INDIRECTLY);
+ }
}
}
@@ -257,33 +321,52 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
{
bArmature *arm = (bArmature *)object->data;
OperationDepsNode *op_node;
-
- build_animdata(&arm->id);
-
+ Object *object_cow;
+ if (DEG_depsgraph_use_copy_on_write()) {
+ /* NOTE: We need to expand both object and armature, so this way we can
+ * safely create object level pose.
+ */
+ object_cow = expand_cow_datablock(object);
+ }
+ else {
+ object_cow = object;
+ }
+ /* Sanity check. */
BLI_assert(object->pose != NULL);
-
+ /* Animation. */
+ build_animdata(&arm->id);
/* speed optimization for animation lookups */
BKE_pose_channels_hash_make(object->pose);
- if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
- BKE_pose_update_constraint_flags(object->pose);
+ if (object_cow->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
+ BKE_pose_update_constraint_flags(object_cow->pose);
}
-
op_node = add_operation_node(&object->id,
DEG_NODE_TYPE_EVAL_POSE,
- function_bind(BKE_pose_eval_proxy_copy, _1, object),
+ function_bind(BKE_pose_eval_proxy_copy,
+ _1,
+ object_cow),
DEG_OPCODE_POSE_INIT);
op_node->set_as_entry();
-
- LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
- NULL, DEG_OPCODE_BONE_LOCAL);
+ LINKLIST_FOREACH (bPoseChannel *, pchan, &object_cow->pose->chanbase) {
+ /* Local bone transform. */
+ op_node = add_operation_node(&object->id,
+ DEG_NODE_TYPE_BONE,
+ pchan->name,
+ NULL,
+ DEG_OPCODE_BONE_LOCAL);
op_node->set_as_entry();
-
- add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
- NULL, DEG_OPCODE_BONE_READY);
-
- op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name,
- NULL, DEG_OPCODE_BONE_DONE);
+ /* Bone is ready for solvers. */
+ add_operation_node(&object->id,
+ DEG_NODE_TYPE_BONE,
+ pchan->name,
+ NULL,
+ DEG_OPCODE_BONE_READY);
+ /* Bone is fully evaluated. */
+ op_node = add_operation_node(&object->id,
+ DEG_NODE_TYPE_BONE,
+ pchan->name,
+ NULL,
+ DEG_OPCODE_BONE_DONE);
op_node->set_as_exit();
/* Custom properties. */
@@ -295,9 +378,10 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
pchan->name);
}
}
-
- op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE,
- NULL, DEG_OPCODE_POSE_DONE);
+ op_node = add_operation_node(&object->id,
+ DEG_NODE_TYPE_EVAL_POSE,
+ NULL,
+ DEG_OPCODE_POSE_DONE);
op_node->set_as_exit();
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
index 3c523b1a23c..49772c4f852 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
@@ -24,7 +24,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
+/** \file blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
* \ingroup depsgraph
*
* Methods for constructing depsgraph's nodes
@@ -43,9 +43,11 @@
extern "C" {
#include "DNA_node_types.h"
+#include "DNA_layer_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_node.h"
} /* extern "C" */
@@ -63,24 +65,64 @@ extern "C" {
namespace DEG {
-void DepsgraphNodeBuilder::build_scene(Scene *scene)
+void DepsgraphNodeBuilder::build_view_layer(
+ Scene *scene,
+ ViewLayer *view_layer,
+ eDepsNode_LinkedState_Type linked_state)
{
/* Scene ID block. */
add_id_node(&scene->id);
- /* timesource */
+ /* Time source. */
add_time_source();
- /* build subgraph for set, and link this in... */
- // XXX: depending on how this goes, that scene itself could probably store its
- // own little partial depsgraph?
- if (scene->set != NULL) {
- build_scene(scene->set);
- }
/* Setup currently building context. */
scene_ = scene;
- /* scene objects */
- LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *object = base->object;
- build_object(base, object);
+ /* Expand Scene Cow datablock to get proper pointers to bases. */
+ Scene *scene_cow;
+ ViewLayer *view_layer_cow;
+ if (DEG_depsgraph_use_copy_on_write()) {
+ /* NOTE: We need to create ID nodes for all objects coming from bases,
+ * otherwise remapping will not replace objects with their CoW versions
+ * for CoW bases.
+ */
+ LINKLIST_FOREACH(Base *, base, &view_layer->object_bases) {
+ Object *object = base->object;
+ add_id_node(&object->id, false);
+ }
+ /* Create ID node for nested ID of nodetree as well, otherwise remapping
+ * will not work correct either.
+ */
+ if (scene->nodetree != NULL) {
+ add_id_node(&scene->nodetree->id, false);
+ }
+ /* Make sure we've got ID node, so we can get pointer to CoW datablock.
+ */
+ scene_cow = expand_cow_datablock(scene);
+ view_layer_cow = (ViewLayer *)BLI_findstring(
+ &scene_cow->view_layers,
+ view_layer->name,
+ offsetof(ViewLayer, name));
+ }
+ else {
+ scene_cow = scene;
+ view_layer_cow = view_layer;
+ }
+ /* Scene objects. */
+ int select_color = 1;
+ /* NOTE: Base is used for function bindings as-is, so need to pass CoW base,
+ * but object is expected to be an original one. Hence we go into some
+ * tricks here iterating over the view layer.
+ */
+ for (Base *base_orig = (Base *)view_layer->object_bases.first,
+ *base_cow = (Base *)view_layer_cow->object_bases.first;
+ base_orig != NULL;
+ base_orig = base_orig->next, base_cow = base_cow->next)
+ {
+ /* object itself */
+ build_object(base_cow, base_orig->object, linked_state);
+ base_orig->object->select_color = select_color++;
+ }
+ if (scene->camera != NULL) {
+ build_object(NULL, scene->camera, DEG_ID_LINKED_INDIRECTLY);
}
/* Rigidbody. */
if (scene->rigidbody_world != NULL) {
@@ -94,7 +136,7 @@ void DepsgraphNodeBuilder::build_scene(Scene *scene)
if (scene->world != NULL) {
build_world(scene->world);
}
- /* Compositor nodes. */
+ /* Compositor nodes */
if (scene->nodetree != NULL) {
build_compositor(scene);
}
@@ -114,12 +156,19 @@ void DepsgraphNodeBuilder::build_scene(Scene *scene)
LINKLIST_FOREACH (MovieClip *, clip, &bmain_->movieclip) {
build_movieclip(clip);
}
+ /* Collections. */
+ build_view_layer_collections(&scene->id, view_layer_cow);
/* Parameters evaluation for scene relations mainly. */
add_operation_node(&scene->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PLACEHOLDER,
"Scene Eval");
+ /* Build all set scenes. */
+ if (scene->set != NULL) {
+ ViewLayer *set_view_layer = BKE_view_layer_from_scene_get(scene->set);
+ build_view_layer(scene->set, set_view_layer, DEG_ID_LINKED_VIA_SET);
+ }
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index f44d8f2c029..890e6c050d0 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -61,6 +61,7 @@ extern "C" {
#include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
#include "DNA_particle_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -125,7 +126,7 @@ void modifier_walk(void *user_data,
{
BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
if (*obpoin) {
- data->builder->build_object(*obpoin);
+ data->builder->build_object(NULL, *obpoin);
}
}
@@ -138,7 +139,7 @@ void constraint_walk(bConstraint * /*con*/,
if (*idpoin) {
ID *id = *idpoin;
if (GS(id->name) == ID_OB) {
- data->builder->build_object((Object *)id);
+ data->builder->build_object(NULL, (Object *)id);
}
}
}
@@ -309,19 +310,16 @@ void DepsgraphRelationBuilder::add_collision_relations(
Scene *scene,
Object *object,
Group *group,
- int layer,
bool dupli,
const char *name)
{
unsigned int numcollobj;
- Object **collobjs = get_collisionobjects_ext(
- scene,
- object,
- group,
- layer,
- &numcollobj,
- eModifierType_Collision,
- dupli);
+ Object **collobjs = get_collisionobjects_ext(scene,
+ object,
+ group,
+ &numcollobj,
+ eModifierType_Collision,
+ dupli);
for (unsigned int i = 0; i < numcollobj; i++) {
Object *ob1 = collobjs[i];
@@ -345,7 +343,7 @@ void DepsgraphRelationBuilder::add_forcefield_relations(
bool add_absorption,
const char *name)
{
- ListBase *effectors = pdInitEffectors(scene, object, psys, eff, false);
+ ListBase *effectors = pdInitEffectors(NULL, scene, object, psys, eff, false);
if (effectors != NULL) {
LINKLIST_FOREACH(EffectorCache *, eff, effectors) {
if (eff->ob != object) {
@@ -385,7 +383,6 @@ void DepsgraphRelationBuilder::add_forcefield_relations(
scene,
object,
NULL,
- eff->ob->lay,
true,
"Force Absorption");
}
@@ -417,7 +414,7 @@ void DepsgraphRelationBuilder::begin_build()
nodetree->id.tag &= ~LIB_TAG_DOIT;
}
}
- FOREACH_NODETREE_END;
+ FOREACH_NODETREE_END
}
void DepsgraphRelationBuilder::build_group(Object *object, Group *group)
@@ -427,19 +424,28 @@ void DepsgraphRelationBuilder::build_group(Object *object, Group *group)
OperationKey object_local_transform_key(&object->id,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_LOCAL);
- LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
- if (!group_done) {
- build_object(go->ob);
+
+ if (!group_done) {
+ LINKLIST_FOREACH(Base *, base, &group->view_layer->object_bases) {
+ build_object(NULL, base->object);
}
- ComponentKey dupli_transform_key(&go->ob->id, DEG_NODE_TYPE_TRANSFORM);
+
+ build_view_layer_collections(&group->id, group->view_layer);
+ group_id->tag |= LIB_TAG_DOIT;
+ }
+
+ LINKLIST_FOREACH (Base *, base, &group->view_layer->object_bases) {
+ ComponentKey dupli_transform_key(&base->object->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup");
}
- group_id->tag |= LIB_TAG_DOIT;
}
-void DepsgraphRelationBuilder::build_object(Object *object)
+void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
{
if (object->id.tag & LIB_TAG_DOIT) {
+ if (base != NULL) {
+ build_object_flags(base, object);
+ }
return;
}
object->id.tag |= LIB_TAG_DOIT;
@@ -459,6 +465,8 @@ void DepsgraphRelationBuilder::build_object(Object *object)
OperationKey ob_ubereval_key(&object->id,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL);
+ /* Various flags, flushing from bases/collections. */
+ build_object_flags(base, object);
/* Parenting. */
if (object->parent != NULL) {
/* Parent relationship. */
@@ -526,7 +534,7 @@ void DepsgraphRelationBuilder::build_object(Object *object)
/* Object that this is a proxy for. */
if (object->proxy != NULL) {
object->proxy->proxy_from = object;
- build_object(object->proxy);
+ build_object(NULL, object->proxy);
/* TODO(sergey): This is an inverted relation, matches old depsgraph
* behavior and need to be investigated if it still need to be inverted.
*/
@@ -540,6 +548,20 @@ void DepsgraphRelationBuilder::build_object(Object *object)
}
}
+void DepsgraphRelationBuilder::build_object_flags(Base *base, Object *object)
+{
+ if (base == NULL) {
+ return;
+ }
+ OperationKey view_layer_done_key(&scene_->id,
+ DEG_NODE_TYPE_LAYER_COLLECTIONS,
+ DEG_OPCODE_VIEW_LAYER_DONE);
+ OperationKey object_flags_key(&object->id,
+ DEG_NODE_TYPE_LAYER_COLLECTIONS,
+ DEG_OPCODE_OBJECT_BASE_FLAGS);
+ add_relation(view_layer_done_key, object_flags_key, "Base flags flush");
+}
+
void DepsgraphRelationBuilder::build_object_data(Object *object)
{
if (object->data == NULL) {
@@ -574,6 +596,9 @@ void DepsgraphRelationBuilder::build_object_data(Object *object)
case OB_CAMERA:
build_camera(object);
break;
+ case OB_LIGHTPROBE:
+ build_lightprobe(object);
+ break;
}
Key *key = BKE_key_from_object(object);
if (key != NULL) {
@@ -1078,18 +1103,18 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
*/
IDDepsNode *arm_node = graph_->find_id_node(id);
char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
- if (arm_node && bone_name) {
+ if (arm_node != NULL && bone_name != NULL) {
/* Find objects which use this, and make their eval callbacks
* depend on this.
*/
foreach (DepsRelation *rel, arm_node->outlinks) {
IDDepsNode *to_node = (IDDepsNode *)rel->to;
/* We only care about objects with pose data which use this. */
- if (GS(to_node->id->name) == ID_OB) {
- Object *object = (Object *)to_node->id;
- /* NOTE: object->pose may be NULL. */
- bPoseChannel *pchan = BKE_pose_channel_find_name(
- object->pose, bone_name);
+ if (GS(to_node->id_orig->name) == ID_OB) {
+ Object *object = (Object *)to_node->id_orig;
+ // NOTE: object->pose may be NULL
+ bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose,
+ bone_name);
if (pchan != NULL) {
OperationKey bone_key(&object->id,
DEG_NODE_TYPE_BONE,
@@ -1216,9 +1241,9 @@ void DepsgraphRelationBuilder::build_world(World *world)
/* world's nodetree */
if (world->nodetree != NULL) {
build_nodetree(world->nodetree);
- ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
- ComponentKey world_key(world_id, DEG_NODE_TYPE_PARAMETERS);
- add_relation(ntree_key, world_key, "NTree->World Parameters");
+ ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_SHADING);
+ ComponentKey world_key(world_id, DEG_NODE_TYPE_SHADING);
+ add_relation(ntree_key, world_key, "NTree->World Shading Update");
}
}
@@ -1240,8 +1265,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
/* objects - simulation participants */
if (rbw->group) {
- LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) {
- Object *object = go->ob;
+ LINKLIST_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) {
+ Object *object = base->object;
if (object == NULL || object->type != OB_MESH) {
continue;
}
@@ -1294,8 +1319,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
/* constraints */
if (rbw->constraints) {
- LINKLIST_FOREACH (GroupObject *, go, &rbw->constraints->gobject) {
- Object *object = go->ob;
+ LINKLIST_FOREACH (Base *, base, &rbw->constraints->view_layer->object_bases) {
+ Object *object = base->object;
if (object == NULL || !object->rigidbody_constraint) {
continue;
}
@@ -1336,11 +1361,35 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
LINKLIST_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
ParticleSettings *part = psys->part;
- /* particle settings */
- build_animdata(&part->id);
-
- /* this particle system */
- OperationKey psys_key(&object->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PARTICLE_SYSTEM_EVAL, psys->name);
+ /* Build particle settings relations.
+ *
+ * NOTE: The call itself ensures settings are only build once.
+ */
+ build_particle_settings(part);
+
+ /* This particle system. */
+ OperationKey psys_key(&object->id,
+ DEG_NODE_TYPE_EVAL_PARTICLES,
+ DEG_OPCODE_PARTICLE_SYSTEM_EVAL,
+ psys->name);
+
+ /* Update particle system when settings changes. */
+ OperationKey particle_settings_key(&part->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
+ OperationKey particle_settings_recalc_clear_key(
+ &part->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
+ OperationKey psys_settings_key(&object->id,
+ DEG_NODE_TYPE_EVAL_PARTICLES,
+ DEG_OPCODE_PARTICLE_SETTINGS_EVAL,
+ psys->name);
+ add_relation(particle_settings_key, psys_settings_key, "Particle Settings Change");
+ add_relation(psys_settings_key, psys_key, "Particle Settings Update");
+ add_relation(psys_key,
+ particle_settings_recalc_clear_key,
+ "Particle Settings Recalc Clear");
/* XXX: if particle system is later re-enabled, we must do full rebuild? */
if (!psys_check_enabled(object, psys, G.is_rendering))
@@ -1356,14 +1405,33 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
/* collisions */
if (part->type != PART_HAIR) {
- add_collision_relations(psys_key, scene_, object, part->collision_group, object->lay, true, "Particle Collision");
+ add_collision_relations(psys_key,
+ scene_,
+ object,
+ part->collision_group,
+ true,
+ "Particle Collision");
}
- else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd && psys->clmd->coll_parms) {
- add_collision_relations(psys_key, scene_, object, psys->clmd->coll_parms->group, object->lay | scene_->lay, true, "Hair Collision");
+ else if ((psys->flag & PSYS_HAIR_DYNAMICS) &&
+ psys->clmd != NULL &&
+ psys->clmd->coll_parms != NULL)
+ {
+ add_collision_relations(psys_key,
+ scene_,
+ object,
+ psys->clmd->coll_parms->group,
+ true,
+ "Hair Collision");
}
/* effectors */
- add_forcefield_relations(psys_key, scene_, object, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
+ add_forcefield_relations(psys_key,
+ scene_,
+ object,
+ psys,
+ part->effector_weights,
+ part->type == PART_HAIR,
+ "Particle Field");
/* boids */
if (part->boids) {
@@ -1398,8 +1466,27 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
ComponentKey transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(transform_key, obdata_ubereval_key, "Partcile Eval");
- /* pointcache */
- // TODO...
+ /* TODO(sergey): Do we need a point cache operations here? */
+}
+
+void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part)
+{
+ ID *part_id = &part->id;
+ if (part_id->tag & LIB_TAG_DOIT) {
+ return;
+ }
+ part_id->tag |= LIB_TAG_DOIT;
+
+ /* Animation data relations. */
+ build_animdata(&part->id);
+
+ OperationKey eval_key(part_id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
+ OperationKey recalc_clear_key(part_id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
+ add_relation(eval_key, recalc_clear_key, "Particle Settings Clear Recalc");
}
void DepsgraphRelationBuilder::build_cloth(Object *object,
@@ -1473,12 +1560,22 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
/* link components to each other */
add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
+ OperationKey obdata_ubereval_key(&object->id,
+ DEG_NODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_UBEREVAL);
+
+ /* Special case: modifiers and DerivedMesh creation queries scene for various
+ * things like data mask to be used. We add relation here to ensure object is
+ * never evaluated prior to Scene's CoW is ready.
+ */
+ OperationKey scene_key(&scene_->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PLACEHOLDER,
+ "Scene Eval");
+ add_relation(scene_key, obdata_ubereval_key, "CoW Relation");
+
/* Modifiers */
if (object->modifiers.first != NULL) {
- OperationKey obdata_ubereval_key(&object->id,
- DEG_NODE_TYPE_GEOMETRY,
- DEG_OPCODE_GEOMETRY_UBEREVAL);
-
LINKLIST_FOREACH (ModifierData *, md, &object->modifiers) {
const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
if (mti->updateDepsgraph) {
@@ -1506,6 +1603,14 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
Material *ma = give_current_material(object, a);
if (ma != NULL) {
build_material(ma);
+
+ if (object->type == OB_MESH) {
+ OperationKey material_key(&ma->id,
+ DEG_NODE_TYPE_SHADING,
+ DEG_OPCODE_MATERIAL_UPDATE);
+ OperationKey shading_key(&object->id, DEG_NODE_TYPE_SHADING, DEG_OPCODE_SHADING);
+ add_relation(material_key, shading_key, "Material Update");
+ }
}
}
}
@@ -1584,18 +1689,18 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
// XXX: these needs geom data, but where is geom stored?
if (cu->bevobj) {
ComponentKey bevob_key(&cu->bevobj->id, DEG_NODE_TYPE_GEOMETRY);
- build_object(cu->bevobj);
+ build_object(NULL, cu->bevobj);
add_relation(bevob_key, geom_key, "Curve Bevel");
}
if (cu->taperobj) {
ComponentKey taperob_key(&cu->taperobj->id, DEG_NODE_TYPE_GEOMETRY);
- build_object(cu->taperobj);
+ build_object(NULL, cu->taperobj);
add_relation(taperob_key, geom_key, "Curve Taper");
}
if (object->type == OB_FONT) {
if (cu->textoncurve) {
ComponentKey textoncurve_key(&cu->textoncurve->id, DEG_NODE_TYPE_GEOMETRY);
- build_object(cu->textoncurve);
+ build_object(NULL, cu->textoncurve);
add_relation(textoncurve_key, geom_key, "Text on Curve");
}
}
@@ -1630,11 +1735,17 @@ void DepsgraphRelationBuilder::build_camera(Object *object)
return;
}
camera_id->tag |= LIB_TAG_DOIT;
+
+ ComponentKey object_parameters_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey camera_parameters_key(camera_id, DEG_NODE_TYPE_PARAMETERS);
+
+ add_relation(camera_parameters_key, object_parameters_key,
+ "Camera -> Object");
+
/* DOF */
- if (cam->dof_ob) {
- ComponentKey ob_param_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
+ if (cam->dof_ob != NULL) {
ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM);
- add_relation(dof_ob_key, ob_param_key, "Camera DOF");
+ add_relation(dof_ob_key, object_parameters_key, "Camera DOF");
}
}
@@ -1647,30 +1758,44 @@ void DepsgraphRelationBuilder::build_lamp(Object *object)
return;
}
lamp_id->tag |= LIB_TAG_DOIT;
+
+ ComponentKey object_parameters_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
+ ComponentKey lamp_parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS);
+
+ add_relation(lamp_parameters_key, object_parameters_key,
+ "Lamp -> Object");
+
/* lamp's nodetree */
if (la->nodetree != NULL) {
build_nodetree(la->nodetree);
- ComponentKey parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS);
- ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
- add_relation(nodetree_key, parameters_key, "NTree->Lamp Parameters");
+ ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_SHADING);
+ add_relation(nodetree_key, lamp_parameters_key, "NTree->Lamp Parameters");
}
/* textures */
build_texture_stack(la->mtex);
+
+ if (DEG_depsgraph_use_copy_on_write()) {
+ /* Make sure copy on write of lamp data is always properly updated for
+ * visible lamps.
+ */
+ OperationKey ob_copy_on_write_key(&object->id,
+ DEG_NODE_TYPE_COPY_ON_WRITE,
+ DEG_OPCODE_COPY_ON_WRITE);
+ OperationKey lamp_copy_on_write_key(lamp_id,
+ DEG_NODE_TYPE_COPY_ON_WRITE,
+ DEG_OPCODE_COPY_ON_WRITE);
+ add_relation(lamp_copy_on_write_key, ob_copy_on_write_key, "Eval Order");
+ }
}
void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
{
- if (!ntree)
+ if (ntree == NULL) {
return;
-
+ }
ID *ntree_id = &ntree->id;
-
build_animdata(ntree_id);
-
- OperationKey parameters_key(ntree_id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_PARAMETERS_EVAL);
-
+ ComponentKey shading_key(ntree_id, DEG_NODE_TYPE_SHADING);
/* nodetree's nodes... */
LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) {
ID *id = bnode->id;
@@ -1688,7 +1813,7 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
/* nothing for now. */
}
else if (id_type == ID_OB) {
- build_object((Object *)id);
+ build_object(NULL, (Object *)id);
}
else if (id_type == ID_SCE) {
/* Scenes are used by compositor trees, and handled by render
@@ -1704,15 +1829,22 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
build_nodetree(group_ntree);
group_ntree->id.tag |= LIB_TAG_DOIT;
}
- OperationKey group_parameters_key(&group_ntree->id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_PARAMETERS_EVAL);
- add_relation(group_parameters_key, parameters_key, "Group Node");
+ ComponentKey group_shading_key(&group_ntree->id,
+ DEG_NODE_TYPE_SHADING);
+ add_relation(group_shading_key, shading_key, "Group Node");
}
else {
BLI_assert(!"Unknown ID type used for node");
}
}
+
+ OperationKey shading_update_key(ntree_id,
+ DEG_NODE_TYPE_SHADING,
+ DEG_OPCODE_MATERIAL_UPDATE);
+ OperationKey shading_parameters_key(ntree_id,
+ DEG_NODE_TYPE_SHADING_PARAMETERS,
+ DEG_OPCODE_MATERIAL_UPDATE);
+ add_relation(shading_parameters_key, shading_update_key, "NTree Shading Parameters");
}
/* Recursively build graph for material */
@@ -1734,12 +1866,11 @@ void DepsgraphRelationBuilder::build_material(Material *ma)
if (ma->nodetree != NULL) {
build_nodetree(ma->nodetree);
OperationKey ntree_key(&ma->nodetree->id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_PARAMETERS_EVAL);
+ DEG_NODE_TYPE_SHADING,
+ DEG_OPCODE_MATERIAL_UPDATE);
OperationKey material_key(&ma->id,
DEG_NODE_TYPE_SHADING,
- DEG_OPCODE_PLACEHOLDER,
- "Material Update");
+ DEG_OPCODE_MATERIAL_UPDATE);
add_relation(ntree_key, material_key, "Material's NTree");
}
}
@@ -1814,4 +1945,101 @@ void DepsgraphRelationBuilder::build_movieclip(MovieClip *clip)
build_animdata(&clip->id);
}
+void DepsgraphRelationBuilder::build_lightprobe(Object *object)
+{
+ LightProbe *probe = (LightProbe *)object->data;
+ ID *probe_id = &probe->id;
+ if (probe_id->tag & LIB_TAG_DOIT) {
+ return;
+ }
+ probe_id->tag |= LIB_TAG_DOIT;
+ build_animdata(&probe->id);
+
+ OperationKey probe_key(probe_id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PLACEHOLDER,
+ "LightProbe Eval");
+ OperationKey object_key(&object->id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PLACEHOLDER,
+ "LightProbe Eval");
+ add_relation(probe_key, object_key, "LightProbe Update");
+}
+
+void DepsgraphRelationBuilder::build_copy_on_write_relations()
+{
+ foreach (IDDepsNode *id_node, graph_->id_nodes) {
+ build_copy_on_write_relations(id_node);
+ }
+}
+
+void DepsgraphRelationBuilder::build_copy_on_write_relations(IDDepsNode *id_node)
+{
+ ID *id_orig = id_node->id_orig;
+
+ TimeSourceKey time_source_key;
+ OperationKey copy_on_write_key(id_orig,
+ DEG_NODE_TYPE_COPY_ON_WRITE,
+ DEG_OPCODE_COPY_ON_WRITE);
+ /* XXX: This is a quick hack to make Alt-A to work. */
+ // add_relation(time_source_key, copy_on_write_key, "Fluxgate capacitor hack");
+ /* Resat of code is using rather low level trickery, so need to get some
+ * explicit pointers.
+ */
+ DepsNode *node_cow = find_node(copy_on_write_key);
+ OperationDepsNode *op_cow = node_cow->get_exit_operation();
+ /* Plug any other components to this one. */
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
+ {
+ if (comp_node->type == DEG_NODE_TYPE_COPY_ON_WRITE) {
+ /* Copy-on-write component never depends on itself. */
+ continue;
+ }
+ if (!comp_node->depends_on_cow()) {
+ /* Component explicitly requests to not add relation. */
+ continue;
+ }
+ /* All entry operations of each component should wait for a proper
+ * copy of ID.
+ */
+ OperationDepsNode *op_entry = comp_node->get_entry_operation();
+ if (op_entry != NULL) {
+ graph_->add_new_relation(op_cow, op_entry, "CoW Dependency");
+ }
+ /* All dangling operations should also be executed after copy-on-write. */
+ GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, comp_node->operations_map)
+ {
+ if (op_node->inlinks.size() == 0) {
+ graph_->add_new_relation(op_cow, op_node, "CoW Dependency");
+ }
+ }
+ GHASH_FOREACH_END();
+ /* NOTE: We currently ignore implicit relations to an external
+ * datablocks for copy-on-write operations. This means, for example,
+ * copy-on-write component of Object will not wait for copy-on-write
+ * component of it's Mesh. This is because pointers are all known
+ * already so remapping will happen all correct. And then If some object
+ * evaluation step needs geometry, it will have transitive dependency
+ * to Mesh copy-on-write already.
+ */
+ }
+ GHASH_FOREACH_END();
+ /* TODO(sergey): This solves crash for now, but causes too many
+ * updates potentially.
+ */
+ if (GS(id_orig->name) == ID_OB) {
+ Object *object = (Object *)id_orig;
+ ID *object_data_id = (ID *)object->data;
+ if (object_data_id != NULL) {
+ OperationKey data_copy_on_write_key(object_data_id,
+ DEG_NODE_TYPE_COPY_ON_WRITE,
+ DEG_OPCODE_COPY_ON_WRITE);
+ add_relation(data_copy_on_write_key, copy_on_write_key, "Eval Order");
+ }
+ else {
+ BLI_assert(object->type == OB_EMPTY);
+ }
+ }
+}
+
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 9dd14b631af..9f661b8e825 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -56,6 +56,7 @@ struct ID;
struct FCurve;
struct Group;
struct Key;
+struct LayerCollection;
struct Main;
struct Mask;
struct Material;
@@ -67,10 +68,12 @@ struct Object;
struct bPoseChannel;
struct bConstraint;
struct Scene;
+struct ViewLayer;
struct Tex;
struct World;
struct EffectorWeights;
struct ParticleSystem;
+struct ParticleSettings;
struct PropertyRNA;
@@ -189,9 +192,10 @@ struct DepsgraphRelationBuilder
const char *description,
bool check_unique = false);
- void build_scene(Scene *scene);
+ void build_view_layer(Scene *scene, ViewLayer *view_layer);
void build_group(Object *object, Group *group);
- void build_object(Object *object);
+ void build_object(Base *base, Object *object);
+ void build_object_flags(Base *base, Object *object);
void build_object_data(Object *object);
void build_object_parent(Object *object);
void build_constraints(ID *id,
@@ -209,6 +213,7 @@ struct DepsgraphRelationBuilder
void build_world(World *world);
void build_rigidbody(Scene *scene);
void build_particles(Object *object);
+ void build_particle_settings(ParticleSettings *part);
void build_cloth(Object *object, ModifierData *md);
void build_ik_pose(Object *object,
bPoseChannel *pchan,
@@ -233,12 +238,12 @@ struct DepsgraphRelationBuilder
void build_cachefile(CacheFile *cache_file);
void build_mask(Mask *mask);
void build_movieclip(MovieClip *clip);
+ void build_lightprobe(Object *object);
void add_collision_relations(const OperationKey &key,
Scene *scene,
Object *object,
Group *group,
- int layer,
bool dupli,
const char *name);
void add_forcefield_relations(const OperationKey &key,
@@ -246,8 +251,24 @@ struct DepsgraphRelationBuilder
Object *object,
ParticleSystem *psys,
EffectorWeights *eff,
- bool add_absorption,
- const char *name);
+ bool add_absorption, const char *name);
+
+ struct LayerCollectionState {
+ int index;
+ OperationKey init_key;
+ OperationKey done_key;
+ OperationKey prev_key;
+ };
+ void build_layer_collection(ID *owner_id,
+ LayerCollection *layer_collection,
+ LayerCollectionState *state);
+ void build_layer_collections(ID *owner_id,
+ ListBase *layer_collections,
+ LayerCollectionState *state);
+ void build_view_layer_collections(struct ID *owner_id, ViewLayer *view_layer);
+
+ void build_copy_on_write_relations();
+ void build_copy_on_write_relations(IDDepsNode *id_node);
template <typename KeyType>
OperationDepsNode *find_operation_node(const KeyType &key);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc
new file mode 100644
index 00000000000..452bd7b19e7
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc
@@ -0,0 +1,124 @@
+/*
+ * ***** 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc
+ * \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph
+ */
+
+#include "intern/builder/deg_builder_relations.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cstring> /* required for STREQ later on. */
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+} /* extern "C" */
+
+#include "intern/builder/deg_builder.h"
+#include "intern/builder/deg_builder_pchanmap.h"
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "intern/depsgraph_intern.h"
+#include "intern/depsgraph_types.h"
+
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+void DepsgraphRelationBuilder::build_layer_collection(
+ ID *owner_id,
+ LayerCollection *layer_collection,
+ LayerCollectionState *state)
+{
+ OperationKey layer_key(owner_id,
+ DEG_NODE_TYPE_LAYER_COLLECTIONS,
+ DEG_OPCODE_VIEW_LAYER_EVAL,
+ layer_collection->scene_collection->name,
+ state->index);
+ add_relation(state->prev_key, layer_key, "Layer collection order");
+
+ ++state->index;
+ state->prev_key = layer_key;
+
+ /* Recurs into nested layer collections. */
+ build_layer_collections(owner_id, &layer_collection->layer_collections, state);
+}
+
+void DepsgraphRelationBuilder::build_layer_collections(
+ ID *owner_id,
+ ListBase *layer_collections,
+ LayerCollectionState *state)
+{
+ LINKLIST_FOREACH (LayerCollection *, layer_collection, layer_collections) {
+ /* Recurs into the layer. */
+ build_layer_collection(owner_id, layer_collection, state);
+ }
+}
+
+void DepsgraphRelationBuilder::build_view_layer_collections(
+ ID *owner_id,
+ ViewLayer *view_layer)
+{
+ LayerCollectionState state;
+ state.index = 0;
+
+ OperationKey init_key(owner_id,
+ DEG_NODE_TYPE_LAYER_COLLECTIONS,
+ DEG_OPCODE_VIEW_LAYER_INIT);
+ OperationKey done_key(owner_id,
+ DEG_NODE_TYPE_LAYER_COLLECTIONS,
+ DEG_OPCODE_VIEW_LAYER_DONE);
+
+ state.init_key = init_key;
+ state.done_key = done_key;
+ state.prev_key = init_key;
+
+ build_layer_collections(owner_id, &view_layer->layer_collections, &state);
+
+ add_relation(state.prev_key, done_key, "Layer collection order");
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
index dc88d80fed9..2aff1ca33c7 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
@@ -387,16 +387,12 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
OperationKey bone_pose_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
OperationKey bone_ready_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
OperationKey bone_done_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
-
pchan->flag &= ~POSE_DONE;
-
- /* pose init to bone local */
+ /* Pose init to bone local. */
add_relation(init_key, bone_local_key, "PoseEval Source-Bone Link");
-
- /* local to pose parenting operation */
+ /* Local to pose parenting operation. */
add_relation(bone_local_key, bone_pose_key, "Bone Local - PoseSpace Link");
-
- /* parent relation */
+ /* Parent relation. */
if (pchan->parent != NULL) {
eDepsOperation_Code parent_key_opcode;
@@ -411,8 +407,7 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
OperationKey parent_key(&object->id, DEG_NODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
add_relation(parent_key, bone_pose_key, "Parent Bone -> Child Bone");
}
-
- /* constraints */
+ /* Buil constraints. */
if (pchan->constraints.first != NULL) {
/* constraints stack and constraint dependencies */
build_constraints(&object->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
@@ -439,6 +434,10 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
/* assume that all bones must be done for the pose to be ready (for deformers) */
add_relation(bone_done_key, flush_key, "PoseEval Result-Bone Link");
+ /* Custom shape. */
+ if (pchan->custom != NULL) {
+ build_object(NULL, pchan->custom);
+ }
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
index feb32442cb7..29cff0cb28d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
@@ -24,7 +24,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
+/** \file blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
* \ingroup depsgraph
*
* Methods for constructing depsgraph
@@ -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"
} /* extern "C" */
@@ -67,17 +68,20 @@ extern "C" {
namespace DEG {
-void DepsgraphRelationBuilder::build_scene(Scene *scene)
+void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_layer)
{
- if (scene->set != NULL) {
- build_scene(scene->set);
- }
/* Setup currently building context. */
scene_ = scene;
/* Scene objects. */
- LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *object = base->object;
- build_object(object);
+ /* NOTE: Nodes builder requires us to pass CoW base because it's being
+ * passed to the evaluation functions. During relations builder we only
+ * do NULL-pointer check of the base, so it's fine to pass original one.
+ */
+ LINKLIST_FOREACH(Base *, base, &view_layer->object_bases) {
+ build_object(base, base->object);
+ }
+ if (scene->camera != NULL) {
+ build_object(NULL, scene->camera);
}
/* Rigidbody. */
if (scene->rigidbody_world != NULL) {
@@ -107,18 +111,25 @@ void DepsgraphRelationBuilder::build_scene(Scene *scene)
LINKLIST_FOREACH (MovieClip *, clip, &bmain_->movieclip) {
build_movieclip(clip);
}
- for (Depsgraph::OperationNodes::const_iterator it_op = graph_->operations.begin();
- it_op != graph_->operations.end();
- ++it_op)
- {
- OperationDepsNode *node = *it_op;
+ /* Collections. */
+ build_view_layer_collections(&scene_->id, view_layer);
+ /* TODO(sergey): Do this flush on CoW object? */
+ foreach (OperationDepsNode *node, graph_->operations) {
IDDepsNode *id_node = node->owner->owner;
- ID *id = id_node->id;
+ ID *id = id_node->id_orig;
if (GS(id->name) == ID_OB) {
Object *object = (Object *)id;
object->customdata_mask |= node->customdata_mask;
}
}
+ /* Build all set scenes. */
+ if (scene->set != NULL) {
+ ViewLayer *set_view_layer = BKE_view_layer_from_scene_get(scene->set);
+ build_view_layer(scene->set, set_view_layer);
+ }
+
+ graph_->scene = scene;
+ graph_->view_layer = view_layer;
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
index 51d4ed91419..5111db08e03 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
@@ -78,18 +78,21 @@ static const char *deg_debug_colors_light[] = {
#ifdef COLOR_SCHEME_NODE_TYPE
static const int deg_debug_node_type_color_map[][2] = {
{DEG_NODE_TYPE_TIMESOURCE, 0},
- {DEG_NODE_TYPE_ID_REF, 2},
+ {DEG_NODE_TYPE_ID_REF, 1},
/* Outer Types */
- {DEG_NODE_TYPE_PARAMETERS, 2},
- {DEG_NODE_TYPE_PROXY, 3},
- {DEG_NODE_TYPE_ANIMATION, 4},
- {DEG_NODE_TYPE_TRANSFORM, 5},
- {DEG_NODE_TYPE_GEOMETRY, 6},
- {DEG_NODE_TYPE_SEQUENCER, 7},
- {DEG_NODE_TYPE_SHADING, 8},
- {DEG_NODE_TYPE_CACHE, 9},
- {-1, 0}
+ {DEG_NODE_TYPE_PARAMETERS, 2},
+ {DEG_NODE_TYPE_PROXY, 3},
+ {DEG_NODE_TYPE_ANIMATION, 4},
+ {DEG_NODE_TYPE_TRANSFORM, 5},
+ {DEG_NODE_TYPE_GEOMETRY, 6},
+ {DEG_NODE_TYPE_SEQUENCER, 7},
+ {DEG_NODE_TYPE_SHADING, 8},
+ {DEG_NODE_TYPE_SHADING_PARAMETERS, 9},
+ {DEG_NODE_TYPE_CACHE, 10},
+ {DEG_NODE_TYPE_LAYER_COLLECTIONS, 11},
+ {DEG_NODE_TYPE_COPY_ON_WRITE, 12},
+ {-1, 0}
};
#endif
@@ -177,7 +180,7 @@ static void deg_debug_graphviz_legend(const DebugContext &ctx)
#ifdef COLOR_SCHEME_NODE_TYPE
const int (*pair)[2];
for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) {
- DepsNodeFactory *nti = DEG_get_node_factory((eDepsNode_Type)(*pair)[0]);
+ DepsNodeFactory *nti = DEG_get_node_factory((eDEG_NODE_TYPE)(*pair)[0]);
deg_debug_graphviz_legend_color(ctx,
nti->tname().c_str(),
deg_debug_colors_light[(*pair)[1] % deg_debug_max_colors]);
@@ -284,12 +287,6 @@ static void deg_debug_graphviz_node_single(const DebugContext &ctx,
const char *shape = "box";
string name = node->identifier();
float priority = -1.0f;
- if (node->type == DEG_NODE_TYPE_ID_REF) {
- IDDepsNode *id_node = (IDDepsNode *)node;
- char buf[256];
- BLI_snprintf(buf, sizeof(buf), " (Layers: %u)", id_node->layers);
- name += buf;
- }
if (ctx.show_eval_priority && node->tclass == DEG_NODE_CLASS_OPERATION) {
priority = ((OperationDepsNode *)node)->eval_priority;
}
@@ -320,12 +317,6 @@ static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx,
const DepsNode *node)
{
string name = node->identifier();
- if (node->type == DEG_NODE_TYPE_ID_REF) {
- IDDepsNode *id_node = (IDDepsNode *)node;
- char buf[256];
- BLI_snprintf(buf, sizeof(buf), " (Layers: %u)", id_node->layers);
- name += buf;
- }
deg_debug_fprintf(ctx, "// %s\n", name.c_str());
deg_debug_fprintf(ctx, "subgraph \"cluster_%p\" {" NL, node);
// deg_debug_fprintf(ctx, "label=<<B>%s</B>>;" NL, name);
@@ -387,8 +378,12 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
case DEG_NODE_TYPE_EVAL_POSE:
case DEG_NODE_TYPE_BONE:
case DEG_NODE_TYPE_SHADING:
+ case DEG_NODE_TYPE_SHADING_PARAMETERS:
case DEG_NODE_TYPE_CACHE:
+ case DEG_NODE_TYPE_LAYER_COLLECTIONS:
case DEG_NODE_TYPE_EVAL_PARTICLES:
+ case DEG_NODE_TYPE_COPY_ON_WRITE:
+ case DEG_NODE_TYPE_BATCH_CACHE:
{
ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
if (!comp_node->operations.empty()) {
@@ -403,7 +398,9 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
}
break;
}
- default:
+ case DEG_NODE_TYPE_UNDEFINED:
+ case DEG_NODE_TYPE_TIMESOURCE:
+ case DEG_NODE_TYPE_OPERATION:
deg_debug_graphviz_node_single(ctx, node);
break;
}
@@ -497,11 +494,9 @@ static void deg_debug_graphviz_node_relations(const DebugContext &ctx,
static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
const Depsgraph *graph)
{
- GHASH_FOREACH_BEGIN (DepsNode *, node, graph->id_hash)
- {
+ foreach (DepsNode *node, graph->id_nodes) {
deg_debug_graphviz_node(ctx, node);
}
- GHASH_FOREACH_END();
TimeSourceDepsNode *time_source = graph->find_time_source();
if (time_source != NULL) {
deg_debug_graphviz_node(ctx, time_source);
@@ -511,8 +506,7 @@ static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
const Depsgraph *graph)
{
- GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
- {
+ foreach (IDDepsNode *id_node, graph->id_nodes) {
GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
{
foreach (OperationDepsNode *op_node, comp_node->operations) {
@@ -521,7 +515,6 @@ static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
}
GHASH_FOREACH_END();
}
- GHASH_FOREACH_END();
TimeSourceDepsNode *time_source = graph->find_time_source();
if (time_source != NULL) {
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 7e9b2f5c58c..4fea8b49706 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -46,8 +46,6 @@ extern "C" {
#include "DNA_object_types.h"
#include "DNA_sequence_types.h"
-#include "BKE_depsgraph.h"
-
#include "RNA_access.h"
}
@@ -55,6 +53,8 @@ extern "C" {
#include "DEG_depsgraph.h"
+#include "intern/eval/deg_eval_copy_on_write.h"
+
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
@@ -62,16 +62,28 @@ extern "C" {
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
+static bool use_copy_on_write = false;
+
+bool DEG_depsgraph_use_copy_on_write(void)
+{
+ return use_copy_on_write;
+}
+
+void DEG_depsgraph_enable_copy_on_write(void)
+{
+ use_copy_on_write = true;
+}
+
namespace DEG {
static DEG_EditorUpdateIDCb deg_editor_update_id_cb = NULL;
static DEG_EditorUpdateSceneCb deg_editor_update_scene_cb = NULL;
-static DEG_EditorUpdateScenePreCb deg_editor_update_scene_pre_cb = NULL;
Depsgraph::Depsgraph()
: time_source(NULL),
- need_update(false),
- layers(0)
+ need_update(true),
+ scene(NULL),
+ view_layer(NULL)
{
BLI_spin_init(&lock);
id_hash = BLI_ghash_ptr_new("Depsgraph id hash");
@@ -248,12 +260,6 @@ DepsNode *Depsgraph::find_node_from_pointer(const PointerRNA *ptr,
/* Node Management ---------------------------- */
-static void id_node_deleter(void *value)
-{
- IDDepsNode *id_node = reinterpret_cast<IDDepsNode *>(value);
- OBJECT_GUARDED_DELETE(id_node, IDDepsNode);
-}
-
TimeSourceDepsNode *Depsgraph::add_time_source()
{
if (time_source == NULL) {
@@ -273,22 +279,58 @@ IDDepsNode *Depsgraph::find_id_node(const ID *id) const
return reinterpret_cast<IDDepsNode *>(BLI_ghash_lookup(id_hash, id));
}
-IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name)
+IDDepsNode *Depsgraph::add_id_node(ID *id, bool do_tag, ID *id_cow_hint)
{
+ BLI_assert((id->tag & LIB_TAG_COPY_ON_WRITE) == 0);
IDDepsNode *id_node = find_id_node(id);
if (!id_node) {
DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_ID_REF);
- id_node = (IDDepsNode *)factory->create_node(id, "", name);
- id->tag |= LIB_TAG_DOIT;
- /* register */
+ id_node = (IDDepsNode *)factory->create_node(id, "", id->name);
+ id_node->init_copy_on_write(id_cow_hint);
+ if (do_tag) {
+ id->tag |= LIB_TAG_DOIT;
+ }
+ /* Register node in ID hash.
+ *
+ * NOTE: We address ID nodes by the original ID pointer they are
+ * referencing to.
+ */
BLI_ghash_insert(id_hash, id, id_node);
+ id_nodes.push_back(id_node);
+ }
+ else if (do_tag) {
+ id->tag |= LIB_TAG_DOIT;
}
return id_node;
}
void Depsgraph::clear_id_nodes()
{
- BLI_ghash_clear(id_hash, NULL, id_node_deleter);
+ /* Free memory used by ID nodes. */
+ if (use_copy_on_write) {
+ /* Stupid workaround to ensure we free IDs in a proper order. */
+ foreach (IDDepsNode *id_node, id_nodes) {
+ if (id_node->id_cow == NULL) {
+ /* This means builder "stole" ownership of the copy-on-written
+ * datablock for her own dirty needs.
+ */
+ continue;
+ }
+ if (!deg_copy_on_write_is_expanded(id_node->id_cow)) {
+ continue;
+ }
+ const ID_Type id_type = GS(id_node->id_cow->name);
+ if (id_type != ID_PA) {
+ id_node->destroy();
+ }
+ }
+ }
+ foreach (IDDepsNode *id_node, id_nodes) {
+ OBJECT_GUARDED_DELETE(id_node, IDDepsNode);
+ }
+ /* Clear containers. */
+ BLI_ghash_clear(id_hash, NULL, NULL);
+ id_nodes.clear();
}
/* Add new relationship between two nodes. */
@@ -312,7 +354,7 @@ DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from,
if (comp_node->type == DEG_NODE_TYPE_GEOMETRY) {
IDDepsNode *id_to = to->owner->owner;
IDDepsNode *id_from = from->owner->owner;
- if (id_to != id_from && (id_to->id->tag & LIB_TAG_ID_RECALC_ALL)) {
+ if (id_to != id_from && (id_to->id_orig->tag & LIB_TAG_ID_RECALC_ALL)) {
if ((id_from->eval_flags & DAG_EVAL_NEED_CPU) == 0) {
id_from->tag_update(this);
id_from->eval_flags |= DAG_EVAL_NEED_CPU;
@@ -398,9 +440,9 @@ DepsRelation::~DepsRelation()
void Depsgraph::add_entry_tag(OperationDepsNode *node)
{
/* Sanity check. */
- if (!node)
+ if (node == NULL) {
return;
-
+ }
/* Add to graph-level set of directly modified nodes to start searching from.
* NOTE: this is necessary since we have several thousand nodes to play with...
*/
@@ -410,24 +452,52 @@ void Depsgraph::add_entry_tag(OperationDepsNode *node)
void Depsgraph::clear_all_nodes()
{
clear_id_nodes();
- BLI_ghash_clear(id_hash, NULL, NULL);
if (time_source != NULL) {
OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode);
time_source = NULL;
}
}
-void deg_editors_id_update(Main *bmain, ID *id)
+ID *Depsgraph::get_cow_id(const ID *id_orig) const
+{
+ IDDepsNode *id_node = find_id_node(id_orig);
+ if (id_node == NULL) {
+ /* This function is used from places where we expect ID to be either
+ * already a copy-on-write version or have a corresponding copy-on-write
+ * version.
+ *
+ * We try to enforce that in debug builds, for for release we play a bit
+ * safer game here.
+ */
+ if ((id_orig->tag & LIB_TAG_COPY_ON_WRITE) == 0) {
+ /* TODO(sergey): This is nice sanity check to have, but it fails
+ * in following situations:
+ *
+ * - Material has link to texture, which is not needed by new
+ * shading system and hence can be ignored at construction.
+ * - Object or mesh has material at a slot which is not used (for
+ * example, object has material slot by materials are set to
+ * object data).
+ */
+ // BLI_assert(!"Request for non-existing copy-on-write ID");
+ }
+ return (ID *)id_orig;
+ }
+ return id_node->id_cow;
+}
+
+void deg_editors_id_update(const DEGEditorUpdateContext *update_ctx, ID *id)
{
if (deg_editor_update_id_cb != NULL) {
- deg_editor_update_id_cb(bmain, id);
+ deg_editor_update_id_cb(update_ctx, id);
}
}
-void deg_editors_scene_update(Main *bmain, Scene *scene, bool updated)
+void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx,
+ bool updated)
{
if (deg_editor_update_scene_cb != NULL) {
- deg_editor_update_scene_cb(bmain, scene, updated);
+ deg_editor_update_scene_cb(update_ctx, updated);
}
}
@@ -453,17 +523,8 @@ void DEG_graph_free(Depsgraph *graph)
/* Set callbacks which are being called when depsgraph changes. */
void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func,
- DEG_EditorUpdateSceneCb scene_func,
- DEG_EditorUpdateScenePreCb scene_pre_func)
+ DEG_EditorUpdateSceneCb scene_func)
{
DEG::deg_editor_update_id_cb = id_func;
DEG::deg_editor_update_scene_cb = scene_func;
- DEG::deg_editor_update_scene_pre_cb = scene_pre_func;
-}
-
-void DEG_editors_update_pre(Main *bmain, Scene *scene, bool time)
-{
- if (DEG::deg_editor_update_scene_pre_cb != NULL) {
- DEG::deg_editor_update_scene_pre_cb(bmain, scene, time);
- }
}
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index 46da40b9938..8a34be0c7a2 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -42,9 +42,12 @@
struct ID;
struct GHash;
+struct Main;
struct GSet;
struct PointerRNA;
struct PropertyRNA;
+struct Scene;
+struct ViewLayer;
namespace DEG {
@@ -91,7 +94,9 @@ struct DepsRelation {
/* Dependency Graph object */
struct Depsgraph {
+ // TODO(sergey): Go away from C++ container and use some native BLI.
typedef vector<OperationDepsNode *> OperationNodes;
+ typedef vector<IDDepsNode *> IDDepsNodes;
Depsgraph();
~Depsgraph();
@@ -100,7 +105,8 @@ struct Depsgraph {
* Convenience wrapper to find node given just pointer + property.
*
* \param ptr: pointer to the data that node will represent
- * \param prop: optional property affected - providing this effectively results in inner nodes being returned
+ * \param prop: optional property affected - providing this effectively
+ * results in inner nodes being returned
*
* \return A node matching the required characteristics if it exists
* or NULL if no such node exists in the graph
@@ -111,7 +117,7 @@ struct Depsgraph {
TimeSourceDepsNode *find_time_source() const;
IDDepsNode *find_id_node(const ID *id) const;
- IDDepsNode *add_id_node(ID *id, const char *name = "");
+ IDDepsNode *add_id_node(ID *id, bool do_tag = true, ID *id_cow_hint = NULL);
void clear_id_nodes();
/* Add new relationship between two nodes. */
@@ -139,12 +145,24 @@ struct Depsgraph {
/* Clear storage used by all nodes. */
void clear_all_nodes();
+ /* Copy-on-Write Functionality ........ */
+
+ /* For given original ID get ID which is created by CoW system. */
+ ID *get_cow_id(const ID *id_orig) const;
+
/* Core Graph Functionality ........... */
- /* <ID : IDDepsNode> mapping from ID blocks to nodes representing these blocks
- * (for quick lookups). */
+ /* <ID : IDDepsNode> mapping from ID blocks to nodes representing these
+ * blocks, used for quick lookups.
+ */
GHash *id_hash;
+ /* Ordered list of ID nodes, order matches ID allocation order.
+ * Used for faster iteration, especially for areas which are critical to
+ * keep exact order of iteration.
+ */
+ IDDepsNodes id_nodes;
+
/* Top-level time source node. */
TimeSourceDepsNode *time_source;
@@ -167,12 +185,9 @@ struct Depsgraph {
*/
SpinLock lock;
- /* Layers Visibility .................. */
-
- /* Visible layers bitfield, used for skipping invisible objects updates. */
- unsigned int layers;
-
- // XXX: additional stuff like eval contexts, mempools for allocating nodes from, etc.
+ /* Scene and layer this dependency graph is built for. */
+ Scene *scene;
+ ViewLayer *view_layer;
};
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 4b3d4190dcd..57153279acb 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -36,6 +36,7 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "BLI_listbase.h"
#ifdef DEBUG_TIME
# include "PIL_time.h"
@@ -52,6 +53,7 @@ extern "C" {
#include "BKE_collision.h"
#include "BKE_effect.h"
#include "BKE_modifier.h"
+#include "BKE_scene.h"
} /* extern "C" */
#include "DEG_depsgraph.h"
@@ -191,31 +193,46 @@ void DEG_add_special_eval_flag(Depsgraph *graph, ID *id, short flag)
/* ******************** */
/* Graph Building API's */
-/* Build depsgraph for the given scene, and dump results in given
+/* Build depsgraph for the given scene layer, and dump results in given
* graph container.
*/
-/* XXX: assume that this is called from outside, given the current scene as
- * the "main" scene.
- */
-void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
+void DEG_graph_build_from_view_layer(Depsgraph *graph,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer)
{
#ifdef DEBUG_TIME
- TIMEIT_START(DEG_graph_build_from_scene);
+ TIMEIT_START(DEG_graph_build_from_view_layer);
#endif
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ BLI_assert(BLI_findindex(&scene->view_layers, view_layer) != -1);
+
+ /* TODO(sergey): This is a bit tricky, but ensures that all the data
+ * is evaluated properly when depsgraph is becoming "visible".
+ *
+ * This now could happen for both visible scene is changed and extra
+ * dependency graph was created for render engine.
+ */
+ const bool need_on_visible_update = (deg_graph->scene == NULL);
/* 1) Generate all the nodes in the graph first */
DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph);
node_builder.begin_build();
- node_builder.build_scene(scene);
+ node_builder.build_view_layer(scene,
+ view_layer,
+ DEG::DEG_ID_LINKED_DIRECTLY);
+ node_builder.end_build();
/* 2) Hook up relationships between operations - to determine evaluation
* order.
*/
DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph);
relation_builder.begin_build();
- relation_builder.build_scene(scene);
+ relation_builder.build_view_layer(scene, view_layer);
+ if (DEG_depsgraph_use_copy_on_write()) {
+ relation_builder.build_copy_on_write_relations();
+ }
/* Detect and solve cycles. */
DEG::deg_graph_detect_cycles(deg_graph);
@@ -230,7 +247,7 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
}
/* 4) Flush visibility layer and re-schedule nodes for update. */
- DEG::deg_graph_build_finalize(deg_graph);
+ DEG::deg_graph_build_finalize(bmain, deg_graph);
#if 0
if (!DEG_debug_consistency_check(deg_graph)) {
@@ -240,8 +257,15 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
#endif
#ifdef DEBUG_TIME
- TIMEIT_END(DEG_graph_build_from_scene);
+ TIMEIT_END(DEG_graph_build_from_view_layer);
#endif
+
+ /* Relations are up to date. */
+ deg_graph->need_update = false;
+
+ if (need_on_visible_update) {
+ DEG_graph_on_visible_update(bmain, graph);
+ }
}
/* Tag graph relations for update. */
@@ -251,64 +275,34 @@ void DEG_graph_tag_relations_update(Depsgraph *graph)
deg_graph->need_update = true;
}
-/* Tag all relations for update. */
-void DEG_relations_tag_update(Main *bmain)
-{
- for (Scene *scene = (Scene *)bmain->scene.first;
- scene != NULL;
- scene = (Scene *)scene->id.next)
- {
- if (scene->depsgraph != NULL) {
- DEG_graph_tag_relations_update(scene->depsgraph);
- }
- }
-}
-
-/* Create new graph if didn't exist yet,
- * or update relations if graph was tagged for update.
- */
-void DEG_scene_relations_update(Main *bmain, Scene *scene)
+/* Create or update relations in the specified graph. */
+void DEG_graph_relations_update(Depsgraph *graph,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer)
{
- if (scene->depsgraph == NULL) {
- /* Rebuild graph from scratch and exit. */
- scene->depsgraph = DEG_graph_new();
- DEG_graph_build_from_scene(scene->depsgraph, bmain, scene);
- return;
- }
-
- DEG::Depsgraph *graph = reinterpret_cast<DEG::Depsgraph *>(scene->depsgraph);
- if (!graph->need_update) {
+ DEG::Depsgraph *deg_graph = (DEG::Depsgraph *)graph;
+ if (!deg_graph->need_update) {
/* Graph is up to date, nothing to do. */
return;
}
-
- /* Clear all previous nodes and operations. */
- graph->clear_all_nodes();
- graph->operations.clear();
- BLI_gset_clear(graph->entry_tags, NULL);
-
- /* Build new nodes and relations. */
- DEG_graph_build_from_scene(reinterpret_cast< ::Depsgraph * >(graph),
- bmain,
- scene);
-
- graph->need_update = false;
-}
-
-/* Rebuild dependency graph only for a given scene. */
-void DEG_scene_relations_rebuild(Main *bmain, Scene *scene)
-{
- if (scene->depsgraph != NULL) {
- DEG_graph_tag_relations_update(scene->depsgraph);
- }
- DEG_scene_relations_update(bmain, scene);
+ DEG_graph_build_from_view_layer(graph, bmain, scene, view_layer);
}
-void DEG_scene_graph_free(Scene *scene)
+/* Tag all relations for update. */
+void DEG_relations_tag_update(Main *bmain)
{
- if (scene->depsgraph) {
- DEG_graph_free(scene->depsgraph);
- scene->depsgraph = NULL;
+ DEG_DEBUG_PRINTF("%s: Tagging relations for update.\n", __func__);
+ LINKLIST_FOREACH(Scene *, scene, &bmain->scene) {
+ LINKLIST_FOREACH(ViewLayer *, view_layer, &scene->view_layers) {
+ Depsgraph *depsgraph =
+ (Depsgraph *)BKE_scene_get_depsgraph(scene,
+ view_layer,
+ false);
+ if (depsgraph != NULL) {
+ DEG_graph_tag_relations_update(depsgraph);
+ }
+ }
}
}
@@ -316,14 +310,13 @@ void DEG_add_collision_relations(DepsNodeHandle *handle,
Scene *scene,
Object *object,
Group *group,
- int layer,
unsigned int modifier_type,
DEG_CollobjFilterFunction fn,
bool dupli,
const char *name)
{
unsigned int numcollobj;
- Object **collobjs = get_collisionobjects_ext(scene, object, group, layer, &numcollobj, modifier_type, dupli);
+ Object **collobjs = get_collisionobjects_ext(scene, object, group, &numcollobj, modifier_type, dupli);
for (unsigned int i = 0; i < numcollobj; i++) {
Object *ob1 = collobjs[i];
@@ -346,7 +339,7 @@ void DEG_add_forcefield_relations(DepsNodeHandle *handle,
int skip_forcefield,
const char *name)
{
- ListBase *effectors = pdInitEffectors(scene, object, NULL, effector_weights, false);
+ ListBase *effectors = pdInitEffectors(NULL, scene, object, NULL, effector_weights, false);
if (effectors) {
for (EffectorCache *eff = (EffectorCache*)effectors->first; eff; eff = eff->next) {
@@ -378,7 +371,6 @@ void DEG_add_forcefield_relations(DepsNodeHandle *handle,
scene,
object,
NULL,
- eff->ob->lay,
eModifierType_Collision,
NULL,
true,
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index 0b1156a78ba..42c1cf861eb 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -64,18 +64,20 @@ bool DEG_debug_compare(const struct Depsgraph *graph1,
return true;
}
-bool DEG_debug_scene_relations_validate(Main *bmain,
- Scene *scene)
+bool DEG_debug_graph_relations_validate(Depsgraph *graph,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer)
{
- Depsgraph *depsgraph = DEG_graph_new();
+ Depsgraph *temp_depsgraph = DEG_graph_new();
bool valid = true;
- DEG_graph_build_from_scene(depsgraph, bmain, scene);
- if (!DEG_debug_compare(depsgraph, scene->depsgraph)) {
+ DEG_graph_build_from_view_layer(temp_depsgraph, bmain, scene, view_layer);
+ if (!DEG_debug_compare(temp_depsgraph, graph)) {
fprintf(stderr, "ERROR! Depsgraph wasn't tagged for update when it should have!\n");
BLI_assert(!"This should not happen!");
valid = false;
}
- DEG_graph_free(depsgraph);
+ DEG_graph_free(temp_depsgraph);
return valid;
}
@@ -197,8 +199,7 @@ void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer,
size_t tot_outer = 0;
size_t tot_rels = 0;
- GHASH_FOREACH_BEGIN(DEG::IDDepsNode *, id_node, deg_graph->id_hash)
- {
+ foreach (DEG::IDDepsNode *id_node, deg_graph->id_nodes) {
tot_outer++;
GHASH_FOREACH_BEGIN(DEG::ComponentDepsNode *, comp_node, id_node->components)
{
@@ -209,7 +210,6 @@ void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer,
}
GHASH_FOREACH_END();
}
- GHASH_FOREACH_END();
DEG::TimeSourceDepsNode *time_source = deg_graph->find_time_source();
if (time_source != NULL) {
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index 85a0d336d28..1d389b902b8 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -36,10 +36,9 @@
#include "BLI_ghash.h"
extern "C" {
-#include "DNA_scene_types.h"
-
-#include "BKE_depsgraph.h"
#include "BKE_scene.h"
+
+#include "DNA_scene_types.h"
} /* extern "C" */
#include "DEG_depsgraph.h"
@@ -52,53 +51,19 @@ extern "C" {
#include "intern/depsgraph.h"
-#ifdef WITH_LEGACY_DEPSGRAPH
-static bool use_legacy_depsgraph = true;
-#endif
-
/* Unfinished and unused, and takes quite some pre-processing time. */
#undef USE_EVAL_PRIORITY
-bool DEG_depsgraph_use_legacy(void)
-{
-#ifdef DISABLE_NEW_DEPSGRAPH
- return true;
-#elif defined(WITH_LEGACY_DEPSGRAPH)
- return use_legacy_depsgraph;
-#else
- BLI_assert(!"Should not be used with new depsgraph");
- return false;
-#endif
-}
-
-void DEG_depsgraph_switch_to_legacy(void)
-{
-#ifdef WITH_LEGACY_DEPSGRAPH
- use_legacy_depsgraph = true;
-#else
- BLI_assert(!"Should not be used with new depsgraph");
-#endif
-}
-
-void DEG_depsgraph_switch_to_new(void)
-{
-#ifdef WITH_LEGACY_DEPSGRAPH
- use_legacy_depsgraph = false;
-#else
- BLI_assert(!"Should not be used with new depsgraph");
-#endif
-}
-
/* ****************** */
/* Evaluation Context */
/* Create new evaluation context. */
-EvaluationContext *DEG_evaluation_context_new(int mode)
+EvaluationContext *DEG_evaluation_context_new(eEvaluationMode mode)
{
EvaluationContext *eval_ctx =
(EvaluationContext *)MEM_callocN(sizeof(EvaluationContext),
"EvaluationContext");
- eval_ctx->mode = mode;
+ DEG_evaluation_context_init(eval_ctx, mode);
return eval_ctx;
}
@@ -107,11 +72,26 @@ EvaluationContext *DEG_evaluation_context_new(int mode)
* Used by the areas which currently overrides the context or doesn't have
* access to a proper one.
*/
-void DEG_evaluation_context_init(EvaluationContext *eval_ctx, int mode)
+void DEG_evaluation_context_init(EvaluationContext *eval_ctx,
+ eEvaluationMode mode)
{
eval_ctx->mode = mode;
}
+void DEG_evaluation_context_init_from_scene(EvaluationContext *eval_ctx,
+ Scene *scene,
+ ViewLayer *view_layer,
+ RenderEngineType *engine_type,
+ eEvaluationMode mode)
+{
+ DEG_evaluation_context_init(eval_ctx, mode);
+ eval_ctx->depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
+ eval_ctx->view_layer = view_layer;
+ eval_ctx->engine_type = engine_type;
+ eval_ctx->ctime = BKE_scene_frame_get(scene);
+ BLI_assert(eval_ctx->depsgraph != NULL);
+}
+
/* Free evaluation context. */
void DEG_evaluation_context_free(EvaluationContext *eval_ctx)
{
@@ -120,29 +100,20 @@ void DEG_evaluation_context_free(EvaluationContext *eval_ctx)
/* Evaluate all nodes tagged for updating. */
void DEG_evaluate_on_refresh(EvaluationContext *eval_ctx,
- Depsgraph *graph,
- Scene *scene)
+ Depsgraph *graph)
{
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
/* Update time on primary timesource. */
DEG::TimeSourceDepsNode *tsrc = deg_graph->find_time_source();
- tsrc->cfra = BKE_scene_frame_get(scene);
- unsigned int layers = deg_graph->layers;
- /* XXX(sergey): This works around missing updates in temp scenes used
- * by various scripts, but is weak and needs closer investigation.
- */
- if (layers == 0) {
- layers = scene->lay;
- }
- DEG::deg_evaluate_on_refresh(eval_ctx, deg_graph, layers);
+ tsrc->cfra = BKE_scene_frame_get(deg_graph->scene);
+ DEG::deg_evaluate_on_refresh(eval_ctx, deg_graph);
}
/* Frame-change happened for root scene that graph belongs to. */
void DEG_evaluate_on_framechange(EvaluationContext *eval_ctx,
Main *bmain,
Depsgraph *graph,
- float ctime,
- const unsigned int layers)
+ float ctime)
{
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
/* Update time on primary timesource. */
@@ -151,7 +122,7 @@ void DEG_evaluate_on_framechange(EvaluationContext *eval_ctx,
tsrc->tag_update(deg_graph);
DEG::deg_graph_flush_updates(bmain, deg_graph);
/* Perform recalculation updates. */
- DEG::deg_evaluate_on_refresh(eval_ctx, deg_graph, layers);
+ DEG::deg_evaluate_on_refresh(eval_ctx, deg_graph);
}
bool DEG_needs_eval(Depsgraph *graph)
diff --git a/source/blender/depsgraph/intern/depsgraph_intern.h b/source/blender/depsgraph/intern/depsgraph_intern.h
index 2d8e7dc841c..e7e472ea5d6 100644
--- a/source/blender/depsgraph/intern/depsgraph_intern.h
+++ b/source/blender/depsgraph/intern/depsgraph_intern.h
@@ -46,8 +46,9 @@ extern "C" {
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph.h"
-struct Main;
+struct DEGEditorUpdateContext;
struct Group;
+struct Main;
struct Scene;
namespace DEG {
@@ -109,15 +110,29 @@ DepsNodeFactory *deg_node_get_factory(const DepsNode *node);
/* Editors Integration -------------------------------------------------- */
-void deg_editors_id_update(struct Main *bmain, struct ID *id);
+void deg_editors_id_update(const DEGEditorUpdateContext *update_ctx,
+ struct ID *id);
+
+void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx,
+ bool updated);
-void deg_editors_scene_update(struct Main *bmain, struct Scene *scene, bool updated);
+/* Tagging helpers ------------------------------------------------------ */
+
+void lib_id_recalc_tag(struct Main *bmain, struct ID *id);
+void lib_id_recalc_data_tag(struct Main *bmain, struct ID *id);
+
+#define DEG_DEBUG_PRINTF(...) \
+ do { \
+ if (G.debug & G_DEBUG_DEPSGRAPH) { \
+ fprintf(stderr, __VA_ARGS__); \
+ fflush(stderr); \
+ } \
+ } while (0)
-#define DEG_DEBUG_PRINTF(...) \
- do { \
- if (G.debug & G_DEBUG_DEPSGRAPH) { \
- fprintf(stderr, __VA_ARGS__); \
- } \
+#define DEG_ERROR_PRINTF(...) \
+ do { \
+ fprintf(stderr, __VA_ARGS__); \
+ fflush(stderr); \
} while (0)
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index e58a7a32407..6892bdaa178 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -33,17 +33,23 @@
#include "MEM_guardedalloc.h"
extern "C" {
+#include "BLI_utildefines.h"
#include "BKE_idcode.h"
#include "BKE_main.h"
+#include "BLI_listbase.h"
} /* extern "C" */
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
#include "intern/depsgraph_intern.h"
-bool DEG_id_type_tagged(Main *bmain, short idtype)
+bool DEG_id_type_tagged(Main *bmain, short id_type)
{
- return bmain->id_tag_update[BKE_idcode_to_index(idtype)] != 0;
+ return bmain->id_tag_update[BKE_idcode_to_index(id_type)] != 0;
}
short DEG_get_eval_flags_for_id(Depsgraph *graph, ID *id)
@@ -68,3 +74,42 @@ short DEG_get_eval_flags_for_id(Depsgraph *graph, ID *id)
return id_node->eval_flags;
}
+
+Scene *DEG_get_evaluated_scene(Depsgraph *graph)
+{
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ Scene *scene_orig = deg_graph->scene;
+ return reinterpret_cast<Scene *>(deg_graph->get_cow_id(&scene_orig->id));
+}
+
+ViewLayer *DEG_get_evaluated_view_layer(Depsgraph *graph)
+{
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ Scene *scene_cow = DEG_get_evaluated_scene(graph);
+ ViewLayer *view_layer_orig = deg_graph->view_layer;
+ ViewLayer *view_layer_cow =
+ (ViewLayer *)BLI_findstring(&scene_cow->view_layers,
+ view_layer_orig->name,
+ offsetof(ViewLayer, name));
+ return view_layer_cow;
+}
+
+Object *DEG_get_evaluated_object(Depsgraph *depsgraph, Object *object)
+{
+ return (Object *)DEG_get_evaluated_id(depsgraph, &object->id);
+}
+
+ID *DEG_get_evaluated_id(struct Depsgraph *depsgraph, ID *id)
+{
+ /* TODO(sergey): This is a duplicate of Depsgraph::get_cow_id(),
+ * but here we never do assert, since we don't know nature of the
+ * incoming ID datablock.
+ */
+ DEG::Depsgraph *deg_graph = (DEG::Depsgraph *)depsgraph;
+ DEG::IDDepsNode *id_node = deg_graph->find_id_node(id);
+ if (id_node == NULL) {
+ return id;
+ }
+ return id_node->id_cow;
+}
+
diff --git a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
new file mode 100644
index 00000000000..b1353f528bc
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
@@ -0,0 +1,147 @@
+/*
+ * ***** 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) 2017 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_query_foreach.cc
+ * \ingroup depsgraph
+ *
+ * Implementation of Querying and Filtering API's
+ */
+
+// TODO(sergey): Use some sort of wrapper.
+#include <deque>
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+} /* extern "C" */
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "intern/depsgraph_intern.h"
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "util/deg_util_foreach.h"
+
+/* ************************ DEG TRAVERSAL ********************* */
+
+namespace DEG {
+
+typedef std::deque<OperationDepsNode *> TraversalQueue;
+
+static void deg_foreach_clear_flags(const Depsgraph *graph)
+{
+ foreach (OperationDepsNode *op_node, graph->operations) {
+ op_node->scheduled = false;
+ }
+ foreach (IDDepsNode *id_node, graph->id_nodes) {
+ id_node->done = false;
+ }
+}
+
+static void deg_foreach_dependent_ID(const Depsgraph *graph,
+ const ID *id,
+ DEGForeachIDCallback callback,
+ void *user_data)
+{
+ /* Start with getting ID node from the graph. */
+ IDDepsNode *id_node = graph->find_id_node(id);
+ if (id_node == NULL) {
+ /* TODO(sergey): Shall we inform or assert here about attempt to start
+ * iterating over non-existing ID?
+ */
+ return;
+ }
+ /* Make sure all runtime flags are ready and clear. */
+ deg_foreach_clear_flags(graph);
+ /* Start with scheduling all operations from ID node. */
+ TraversalQueue queue;
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
+ {
+ foreach (OperationDepsNode *op_node, comp_node->operations) {
+ queue.push_back(op_node);
+ op_node->scheduled = true;
+ }
+ }
+ GHASH_FOREACH_END();
+ id_node->done = true;
+ /* Process the queue. */
+ while (!queue.empty()) {
+ /* get next operation node to process. */
+ OperationDepsNode *op_node = queue.front();
+ queue.pop_front();
+ for (;;) {
+ /* Check whether we need to inform callee about corresponding ID node. */
+ ComponentDepsNode *comp_node = op_node->owner;
+ IDDepsNode *id_node = comp_node->owner;
+ if (!id_node->done) {
+ /* TODO(sergey): Is it orig or CoW? */
+ callback(id_node->id_orig, user_data);
+ id_node->done = true;
+ }
+ /* Schedule outgoing operation nodes. */
+ if (op_node->outlinks.size() == 1) {
+ OperationDepsNode *to_node = (OperationDepsNode *)op_node->outlinks[0]->to;
+ if (to_node->scheduled == false) {
+ to_node->scheduled = true;
+ op_node = to_node;
+ }
+ else {
+ break;
+ }
+ }
+ else {
+ foreach (DepsRelation *rel, op_node->outlinks) {
+ OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
+ if (to_node->scheduled == false) {
+ queue.push_front(to_node);
+ to_node->scheduled = true;
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+} // namespace DEG
+
+void DEG_foreach_dependent_ID(const Depsgraph *depsgraph,
+ const ID *id,
+ DEGForeachIDCallback callback, void *user_data)
+{
+ DEG::deg_foreach_dependent_ID((const DEG::Depsgraph *)depsgraph,
+ id,
+ callback, user_data);
+}
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
new file mode 100644
index 00000000000..d8a54642a85
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -0,0 +1,211 @@
+/*
+ * ***** 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) 2017 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Dalai Felinto
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_query_iter.cc
+ * \ingroup depsgraph
+ *
+ * Implementation of Querying and Filtering API's
+ */
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BKE_anim.h"
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
+} /* extern "C" */
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+
+#ifndef NDEBUG
+# include "intern/eval/deg_eval_copy_on_write.h"
+#endif
+
+/* ************************ DEG ITERATORS ********************* */
+
+static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
+{
+ DEGOIterObjectData *data = (DEGOIterObjectData *)iter->data;
+ while (data->dupli_object_next != NULL) {
+ DupliObject *dob = data->dupli_object_next;
+ Object *obd = dob->ob;
+
+ data->dupli_object_next = data->dupli_object_next->next;
+
+ /* Group duplis need to set ob matrices correct, for deform. so no_draw
+ * is part handled.
+ */
+ if ((obd->transflag & OB_RENDER_DUPLI) == 0 && dob->no_draw) {
+ continue;
+ }
+
+ if (obd->type == OB_MBALL) {
+ continue;
+ }
+
+ data->dupli_object_current = dob;
+
+ /* Temporary object to evaluate. */
+ Object *dupli_parent = data->dupli_parent;
+ Object *temp_dupli_object = &data->temp_dupli_object;
+ *temp_dupli_object = *dob->ob;
+ temp_dupli_object->select_color = dupli_parent->select_color;
+ temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROMDUPLI;
+ BLI_assert(dob->collection_properties != NULL);
+ temp_dupli_object->base_collection_properties = dob->collection_properties;
+ IDP_MergeGroup(temp_dupli_object->base_collection_properties, dupli_parent->base_collection_properties, false);
+ copy_m4_m4(data->temp_dupli_object.obmat, dob->mat);
+ iter->current = &data->temp_dupli_object;
+ BLI_assert(
+ DEG::deg_validate_copy_on_write_datablock(
+ &data->temp_dupli_object.id));
+ return true;
+ }
+
+ return false;
+}
+
+static void DEG_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_node)
+{
+ /* Reset the skip in case we are running from within a loop. */
+ iter->skip = false;
+
+ DEGOIterObjectData *data = (DEGOIterObjectData *)iter->data;
+ const ID_Type id_type = GS(id_node->id_orig->name);
+
+ if (id_type != ID_OB) {
+ iter->skip = true;
+ return;
+ }
+
+ switch (id_node->linked_state) {
+ case DEG::DEG_ID_LINKED_DIRECTLY:
+ break;
+ case DEG::DEG_ID_LINKED_VIA_SET:
+ if (data->flag & DEG_ITER_OBJECT_FLAG_SET) {
+ break;
+ }
+ else {
+ ATTR_FALLTHROUGH;
+ }
+ case DEG::DEG_ID_LINKED_INDIRECTLY:
+ iter->skip = true;
+ return;
+ }
+
+ Object *object = (Object *)id_node->id_cow;
+ BLI_assert(DEG::deg_validate_copy_on_write_datablock(&object->id));
+
+ if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) && (object->transflag & OB_DUPLI)) {
+ data->dupli_parent = object;
+ data->dupli_list = object_duplilist(&data->eval_ctx, data->scene, object);
+ data->dupli_object_next = (DupliObject *)data->dupli_list->first;
+ }
+
+ iter->current = object;
+}
+
+void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGOIterObjectData *data)
+{
+ Depsgraph *depsgraph = data->graph;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ const size_t num_id_nodes = deg_graph->id_nodes.size();
+
+ if (num_id_nodes == 0) {
+ iter->valid = false;
+ return;
+ }
+
+ /* TODO(sergey): What evaluation type we want here? */
+ DEG_evaluation_context_init(&data->eval_ctx, DAG_EVAL_RENDER);
+ data->eval_ctx.view_layer = DEG_get_evaluated_view_layer(depsgraph);
+
+ iter->data = data;
+ data->dupli_parent = NULL;
+ data->dupli_list = NULL;
+ data->dupli_object_next = NULL;
+ data->dupli_object_current = NULL;
+ data->scene = DEG_get_evaluated_scene(depsgraph);
+ data->id_node_index = 0;
+ data->num_id_nodes = num_id_nodes;
+
+ DEG::IDDepsNode *id_node = deg_graph->id_nodes[data->id_node_index];
+ DEG_iterator_objects_step(iter, id_node);
+
+ if (iter->skip) {
+ DEG_iterator_objects_next(iter);
+ }
+}
+
+void DEG_iterator_objects_next(BLI_Iterator *iter)
+{
+ DEGOIterObjectData *data = (DEGOIterObjectData *)iter->data;
+ Depsgraph *depsgraph = data->graph;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ do {
+ if (data->dupli_list) {
+ if (deg_objects_dupli_iterator_next(iter)) {
+ return;
+ }
+ else {
+ free_object_duplilist(data->dupli_list);
+ data->dupli_parent = NULL;
+ data->dupli_list = NULL;
+ data->dupli_object_next = NULL;
+ data->dupli_object_current = NULL;
+ }
+ }
+
+ ++data->id_node_index;
+ if (data->id_node_index == data->num_id_nodes) {
+ iter->valid = false;
+ return;
+ }
+
+ DEG::IDDepsNode *id_node = deg_graph->id_nodes[data->id_node_index];
+ DEG_iterator_objects_step(iter, id_node);
+ } while (iter->skip);
+}
+
+void DEG_iterator_objects_end(BLI_Iterator *iter)
+{
+#ifndef NDEBUG
+ DEGOIterObjectData *data = (DEGOIterObjectData *)iter->data;
+ /* Force crash in case the iterator data is referenced and accessed down the line. (T51718) */
+ memset(&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object));
+#else
+ (void) iter;
+#endif
+}
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index eafb091e53a..e928da58e87 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -49,6 +49,8 @@ extern "C" {
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_scene.h"
+#include "BKE_workspace.h"
#define new new_
#include "BKE_screen.h"
@@ -66,18 +68,17 @@ extern "C" {
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
+/* Define this in order to have more strict sanitization of what tagging flags
+ * are used for ID databnlocks. Ideally, we would always want this, but there
+ * are cases in generic modules (like IR remapping) where we don't want to spent
+ * lots of time trying to guess which components are to be updated.
+ */
+// #define STRICT_COMPONENT_TAGGING
+
/* *********************** */
/* Update Tagging/Flushing */
-/* Legacy depsgraph did some special trickery for things like particle systems
- * when tagging ID for an update. Ideally that tagging needs to become obsolete
- * in favor of havng dedicated node for that which gets tagged, but for until
- * design of those areas is more clear we'll do the same legacy code here.
- * - sergey -
- */
-#define DEPSGRAPH_USE_LEGACY_TAGGING
-
-namespace {
+namespace DEG {
/* Data-Based Tagging ------------------------------- */
@@ -93,138 +94,421 @@ void lib_id_recalc_data_tag(Main *bmain, ID *id)
DEG_id_type_tag(bmain, GS(id->name));
}
+namespace {
+
+void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag);
+
void lib_id_recalc_tag_flag(Main *bmain, ID *id, int flag)
{
+ /* This bit of code ensures legacy object->recalc flags are still filled in
+ * the same way as it was expected with the old dependency graph.
+ *
+ * This is because some areas like motion paths and likely some other
+ * physics baking process are doing manual scene update on all the frames,
+ * trying to minimize number of updates.
+ *
+ * But this flag will also let us to re-construct entry nodes for update
+ * after relations update and after layer visibility changes.
+ */
if (flag) {
- /* This bit of code ensures legacy object->recalc flags
- * are still filled in the same way as it was expected
- * with the old dependency graph.
- *
- * This is because some areas like motion paths and likely
- * some other physics baking process are doing manual scene
- * update on all the frames, trying to minimize number of
- * updates.
- *
- * But this flag will also let us to re-construct entry
- * nodes for update after relations update and after layer
- * visibility changes.
- */
- ID_Type idtype = GS(id->name);
- if (idtype == ID_OB) {
- Object *object = (Object *)id;
- object->recalc |= (flag & OB_RECALC_ALL);
- }
-
- if (flag & OB_RECALC_OB)
+ if (flag & OB_RECALC_OB) {
lib_id_recalc_tag(bmain, id);
- if (flag & (OB_RECALC_DATA | PSYS_RECALC))
+ }
+ if (flag & (OB_RECALC_DATA | PSYS_RECALC)) {
lib_id_recalc_data_tag(bmain, id);
+ }
}
else {
lib_id_recalc_tag(bmain, id);
}
}
-#ifdef DEPSGRAPH_USE_LEGACY_TAGGING
-void depsgraph_legacy_handle_update_tag(Main *bmain, ID *id, short flag)
+/* Special tagging */
+void id_tag_update_special_zero_flag(Depsgraph *graph, IDDepsNode *id_node)
{
- if (flag) {
- Object *object;
- short idtype = GS(id->name);
- if (idtype == ID_PA) {
- ParticleSystem *psys;
- for (object = (Object *)bmain->object.first;
- object != NULL;
- object = (Object *)object->id.next)
- {
- for (psys = (ParticleSystem *)object->particlesystem.first;
- psys != NULL;
- psys = (ParticleSystem *)psys->next)
- {
- if (&psys->part->id == id) {
- DEG_id_tag_update_ex(bmain, &object->id, flag & OB_RECALC_ALL);
- psys->recalc |= (flag & PSYS_RECALC);
- }
- }
+ /* NOTE: Full ID node update for now, need to minimize that i9n the future. */
+ id_node->tag_update(graph);
+}
+
+/* Tag corresponding to OB_RECALC_OB. */
+void id_tag_update_object_transform(Depsgraph *graph, IDDepsNode *id_node)
+{
+ ComponentDepsNode *transform_comp =
+ id_node->find_component(DEG_NODE_TYPE_TRANSFORM);
+ if (transform_comp == NULL) {
+#ifdef STRICT_COMPONENT_TAGGING
+ DEG_ERROR_PRINTF("ERROR: Unable to find transform component for %s\n",
+ id_node->id_orig->name);
+ BLI_assert(!"This is not supposed to happen!");
+#endif
+ return;
+ }
+ transform_comp->tag_update(graph);
+}
+
+/* Tag corresponding to OB_RECALC_DATA. */
+void id_tag_update_object_data(Depsgraph *graph, IDDepsNode *id_node)
+{
+ const ID_Type id_type = GS(id_node->id_orig->name);
+ ComponentDepsNode *data_comp = NULL;
+ switch (id_type) {
+ case ID_OB:
+ {
+ const Object *object = (Object *)id_node->id_orig;
+ switch (object->type) {
+ case OB_MESH:
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ case OB_MBALL:
+ data_comp = id_node->find_component(DEG_NODE_TYPE_GEOMETRY);
+ break;
+ case OB_ARMATURE:
+ data_comp = id_node->find_component(DEG_NODE_TYPE_EVAL_POSE);
+ break;
+ /* TODO(sergey): More cases here? */
+ }
+ break;
+ }
+ case ID_ME:
+ data_comp = id_node->find_component(DEG_NODE_TYPE_GEOMETRY);
+ break;
+ case ID_PA:
+ return;
+ case ID_LP:
+ data_comp = id_node->find_component(DEG_NODE_TYPE_PARAMETERS);
+ break;
+ default:
+ break;
+ }
+ if (data_comp == NULL) {
+#ifdef STRICT_COMPONENT_TAGGING
+ DEG_ERROR_PRINTF("ERROR: Unable to find data component for %s\n",
+ id_node->id_orig->name);
+ BLI_assert(!"This is not supposed to happen!");
+#endif
+ return;
+ }
+ data_comp->tag_update(graph);
+ /* Special legacy compatibility code, tag data ID for update when object
+ * is tagged for data update.
+ */
+ if (id_type == ID_OB) {
+ Object *object = (Object *)id_node->id_orig;
+ ID *data_id = (ID *)object->data;
+ if (data_id != NULL) {
+ IDDepsNode *data_id_node = graph->find_id_node(data_id);
+ // BLI_assert(data_id_node != NULL);
+ /* TODO(sergey): Do we want more granular tags here? */
+ /* TODO(sergey): Hrm, during some operations it's possible to have
+ * object node existing but not it's data. For example, when making
+ * objects local. This is valid situation, but how can we distinguish
+ * that from someone trying to do stupid things with dependency
+ * graph?
+ */
+ if (data_id_node != NULL) {
+ data_id_node->tag_update(graph);
}
}
}
}
+
+/* Tag corresponding to OB_RECALC_TIME. */
+void id_tag_update_object_time(Depsgraph *graph, IDDepsNode *id_node)
+{
+ ComponentDepsNode *animation_comp =
+ id_node->find_component(DEG_NODE_TYPE_ANIMATION);
+ if (animation_comp == NULL) {
+ /* It's not necessarily we've got animation component in cases when
+ * we are tagging for time updates.
+ */
+ return;
+ }
+ animation_comp->tag_update(graph);
+ /* TODO(sergey): More components to tag here? */
+}
+
+void id_tag_update_particle(Depsgraph *graph, IDDepsNode *id_node, int tag)
+{
+ ComponentDepsNode *particle_comp =
+ id_node->find_component(DEG_NODE_TYPE_PARAMETERS);
+ ParticleSettings *particle_settings = (ParticleSettings *)id_node->id_orig;
+ particle_settings->recalc |= (tag & PSYS_RECALC);
+ if (particle_comp == NULL) {
+#ifdef STRICT_COMPONENT_TAGGING
+ DEG_ERROR_PRINTF("ERROR: Unable to find particle component for %s\n",
+ id_node->id_orig->name);
+ BLI_assert(!"This is not supposed to happen!");
#endif
+ return;
+ }
+ particle_comp->tag_update(graph);
+}
-} /* namespace */
+void id_tag_update_shading(Depsgraph *graph, IDDepsNode *id_node)
+{
+ ComponentDepsNode *shading_comp;
+ if (GS(id_node->id_orig->name) == ID_NT) {
+ shading_comp = id_node->find_component(DEG_NODE_TYPE_SHADING_PARAMETERS);
+ }
+ else {
+ shading_comp = id_node->find_component(DEG_NODE_TYPE_SHADING);
+ }
+ if (shading_comp == NULL) {
+#ifdef STRICT_COMPONENT_TAGGING
+ DEG_ERROR_PRINTF("ERROR: Unable to find shading component for %s\n",
+ id_node->id_orig->name);
+ BLI_assert(!"This is not supposed to happen!");
+#endif
+ return;
+ }
+ shading_comp->tag_update(graph);
+}
-/* Tag all nodes in ID-block for update.
- * This is a crude measure, but is most convenient for old code.
- */
-void DEG_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id)
+/* Tag corresponding to DEG_TAG_COPY_ON_WRITE. */
+void id_tag_update_copy_on_write(Depsgraph *graph, IDDepsNode *id_node)
+{
+ if (!DEG_depsgraph_use_copy_on_write()) {
+ return;
+ }
+ ComponentDepsNode *cow_comp =
+ id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE);
+ OperationDepsNode *cow_node = cow_comp->get_entry_operation();
+ cow_node->tag_update(graph);
+}
+
+void id_tag_update_select_update(Depsgraph *graph, IDDepsNode *id_node)
{
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
- DEG::IDDepsNode *node = deg_graph->find_id_node(id);
- lib_id_recalc_tag(bmain, id);
+ ComponentDepsNode *component;
+ OperationDepsNode *node = NULL;
+ const ID_Type id_type = GS(id_node->id_orig->name);
+ if (id_type == ID_SCE) {
+ /* We need to flush base flags to all objects in a scene since we
+ * don't know which ones changed. However, we don't want to update
+ * the whole scene, so pick up some operation which will do as less
+ * as possible.
+ *
+ * TODO(sergey): We can introduce explicit exit operation which
+ * does nothing and which is only used to cascade flush down the
+ * road.
+ */
+ component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
+ BLI_assert(component != NULL);
+ if (component != NULL) {
+ node = component->find_operation(DEG_OPCODE_VIEW_LAYER_DONE);
+ }
+ }
+ else if (id_type == ID_OB) {
+ component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
+ /* NOTE: This component might be missing for indirectly linked
+ * objects.
+ */
+ if (component != NULL) {
+ node = component->find_operation(DEG_OPCODE_OBJECT_BASE_FLAGS);
+ }
+ }
+ else {
+ component = id_node->find_component(DEG_NODE_TYPE_BATCH_CACHE);
+ BLI_assert(component != NULL);
+ if (component != NULL) {
+ node = component->find_operation(DEG_OPCODE_GEOMETRY_SELECT_UPDATE,
+ "", -1);
+ }
+ }
if (node != NULL) {
- node->tag_update(deg_graph);
+ node->tag_update(graph);
}
}
-/* Tag given ID for an update in all the dependency graphs. */
-void DEG_id_tag_update(ID *id, short flag)
+void id_tag_update_base_flags(Depsgraph *graph, IDDepsNode *id_node)
{
- DEG_id_tag_update_ex(G.main, id, flag);
+ ComponentDepsNode *component;
+ OperationDepsNode *node = NULL;
+ const ID_Type id_type = GS(id_node->id_orig->name);
+ if (id_type == ID_SCE) {
+ component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
+ if (component == NULL) {
+ return;
+ }
+ node = component->find_operation(DEG_OPCODE_VIEW_LAYER_INIT);
+ }
+ else if (id_type == ID_OB) {
+ component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
+ if (component == NULL) {
+ return;
+ }
+ node = component->find_operation(DEG_OPCODE_OBJECT_BASE_FLAGS);
+ if (node == NULL) {
+ return;
+ }
+ }
+ if (node != NULL) {
+ node->tag_update(graph);
+ }
}
-void DEG_id_tag_update_ex(Main *bmain, ID *id, short flag)
+void id_tag_update_editors_update(Main *bmain, Depsgraph *graph, ID *id)
{
- if (id == NULL) {
- /* Ideally should not happen, but old depsgraph allowed this. */
+ /* NOTE: We handle this immediately, without delaying anything, to be
+ * sure we don't cause threading issues with OpenGL.
+ */
+ /* TODO(sergey): Make sure this works for CoW-ed datablocks as well. */
+ DEGEditorUpdateContext update_ctx = {NULL};
+ update_ctx.bmain = bmain;
+ update_ctx.scene = graph->scene;
+ update_ctx.view_layer = graph->view_layer;
+ deg_editors_id_update(&update_ctx, id);
+}
+
+void id_tag_update_ntree_special(Main *bmain, Depsgraph *graph, ID *id, int flag)
+{
+ bNodeTree *ntree = NULL;
+ switch (GS(id->name)) {
+ case ID_MA:
+ ntree = ((Material *)id)->nodetree;
+ break;
+ default:
+ break;
+ }
+ if (ntree == NULL) {
return;
}
- DEG_DEBUG_PRINTF("%s: id=%s flag=%d\n", __func__, id->name, flag);
+ IDDepsNode *id_node = graph->find_id_node(&ntree->id);
+ if (id_node != NULL) {
+ deg_graph_id_tag_update(bmain, graph, id_node->id_orig, flag);
+ }
+}
+
+void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag)
+{
+ Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ IDDepsNode *id_node = deg_graph->find_id_node(id);
+ /* Make sure legacy flags are all nicely update. */
lib_id_recalc_tag_flag(bmain, id, flag);
- for (Scene *scene = (Scene *)bmain->scene.first;
- scene != NULL;
- scene = (Scene *)scene->id.next)
- {
- if (scene->depsgraph) {
- Depsgraph *graph = scene->depsgraph;
- if (flag == 0) {
- /* TODO(sergey): Currently blender is still tagging IDs
- * for recalc just using flag=0. This isn't totally correct
- * but we'd better deal with such cases and don't fail.
- */
- DEG_graph_id_tag_update(bmain, graph, id);
- continue;
- }
- if (flag & OB_RECALC_DATA && GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- if (object->data != NULL) {
- DEG_graph_id_tag_update(bmain,
- graph,
- (ID *)object->data);
+ if (id_node == NULL) {
+ /* Shouldn't happen, but better be sure here. */
+ return;
+ }
+ /* Tag components based on flags. */
+ if (flag == 0) {
+ id_tag_update_special_zero_flag(graph, id_node);
+ id_tag_update_ntree_special(bmain, graph, id, flag);
+ return;
+ }
+ if (flag & OB_RECALC_OB) {
+ id_tag_update_object_transform(graph, id_node);
+ }
+ if (flag & OB_RECALC_DATA) {
+ id_tag_update_object_data(graph, id_node);
+ if (DEG_depsgraph_use_copy_on_write()) {
+ if (flag & DEG_TAG_COPY_ON_WRITE) {
+ const ID_Type id_type = GS(id_node->id_orig->name);
+ if (id_type == ID_OB) {
+ Object *object = (Object *)id_node->id_orig;
+ ID *ob_data = (ID *)object->data;
+ DEG_id_tag_update_ex(bmain, ob_data, flag);
}
}
- if (flag & (OB_RECALC_OB | OB_RECALC_DATA)) {
- DEG_graph_id_tag_update(bmain, graph, id);
- }
- else if (flag & OB_RECALC_TIME) {
- DEG_graph_id_tag_update(bmain, graph, id);
+ }
+ }
+ if (flag & OB_RECALC_TIME) {
+ id_tag_update_object_time(graph, id_node);
+ }
+ if (flag & PSYS_RECALC) {
+ id_tag_update_particle(graph, id_node, flag);
+ }
+ if (flag & DEG_TAG_SHADING_UPDATE) {
+ id_tag_update_shading(graph, id_node);
+ }
+ if (flag & DEG_TAG_COPY_ON_WRITE) {
+ id_tag_update_copy_on_write(graph, id_node);
+ }
+ if (flag & DEG_TAG_SELECT_UPDATE) {
+ id_tag_update_select_update(graph, id_node);
+ }
+ if (flag & DEG_TAG_BASE_FLAGS_UPDATE) {
+ id_tag_update_base_flags(graph, id_node);
+ }
+ if (flag & DEG_TAG_EDITORS_UPDATE) {
+ id_tag_update_editors_update(bmain, graph, id);
+ }
+ id_tag_update_ntree_special(bmain, graph, id, flag);
+}
+
+void deg_id_tag_update(Main *bmain, ID *id, int flag)
+{
+ lib_id_recalc_tag_flag(bmain, id, flag);
+ LINKLIST_FOREACH(Scene *, scene, &bmain->scene) {
+ LINKLIST_FOREACH(ViewLayer *, view_layer, &scene->view_layers) {
+ Depsgraph *depsgraph =
+ (Depsgraph *)BKE_scene_get_depsgraph(scene,
+ view_layer,
+ false);
+ if (depsgraph != NULL) {
+ deg_graph_id_tag_update(bmain, depsgraph, id, flag);
}
}
}
+}
-#ifdef DEPSGRAPH_USE_LEGACY_TAGGING
- /* Special handling from the legacy depsgraph.
- * TODO(sergey): Need to get rid of those once all the areas
- * are re-formulated in terms of franular nodes.
- */
- depsgraph_legacy_handle_update_tag(bmain, id, flag);
-#endif
+void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph)
+{
+ /* Make sure objects are up to date. */
+ foreach (DEG::IDDepsNode *id_node, graph->id_nodes) {
+ const ID_Type id_type = GS(id_node->id_orig->name);
+ int flag = 0;
+ /* We only tag components which needs an update. Tagging everything is
+ * not a good idea because that might reset particles cache (or any
+ * other type of cache).
+ *
+ * TODO(sergey): Need to generalize this somehow.
+ */
+ if (id_type == ID_OB) {
+ flag |= OB_RECALC_OB | OB_RECALC_DATA | DEG_TAG_COPY_ON_WRITE;
+ }
+ deg_graph_id_tag_update(bmain, graph, id_node->id_orig, flag);
+ }
+ /* Make sure collection properties are up to date. */
+ for (Scene *scene_iter = graph->scene; scene_iter != NULL; scene_iter = scene_iter->set) {
+ IDDepsNode *scene_id_node = graph->find_id_node(&scene_iter->id);
+ BLI_assert(scene_id_node != NULL);
+ scene_id_node->tag_update(graph);
+ }
+}
+
+} /* namespace */
+
+} // namespace DEG
+
+/* Tag given ID for an update in all the dependency graphs. */
+void DEG_id_tag_update(ID *id, int flag)
+{
+ DEG_id_tag_update_ex(G.main, id, flag);
+}
+
+void DEG_id_tag_update_ex(Main *bmain, ID *id, int flag)
+{
+ if (id == NULL) {
+ /* Ideally should not happen, but old depsgraph allowed this. */
+ return;
+ }
+ DEG_DEBUG_PRINTF("%s: id=%s flag=%d\n", __func__, id->name, flag);
+ DEG::deg_id_tag_update(bmain, id, flag);
+}
+
+void DEG_graph_id_tag_update(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct ID *id,
+ int flag)
+{
+ DEG::Depsgraph *graph = (DEG::Depsgraph *)depsgraph;
+ DEG::deg_graph_id_tag_update(bmain, graph, id, flag);
}
/* Mark a particular datablock type as having changing. */
-void DEG_id_type_tag(Main *bmain, short idtype)
+void DEG_id_type_tag(Main *bmain, short id_type)
{
- if (idtype == ID_NT) {
+ if (id_type == ID_NT) {
/* Stupid workaround so parent datablocks of nested nodetree get looped
* over when we loop over tagged datablock types.
*/
@@ -235,134 +519,35 @@ void DEG_id_type_tag(Main *bmain, short idtype)
DEG_id_type_tag(bmain, ID_SCE);
}
- bmain->id_tag_update[BKE_idcode_to_index(idtype)] = 1;
+ bmain->id_tag_update[BKE_idcode_to_index(id_type)] = 1;
}
-/* Recursively push updates out to all nodes dependent on this,
- * until all affected are tagged and/or scheduled up for eval
- */
-void DEG_ids_flush_tagged(Main *bmain)
+void DEG_graph_flush_update(Main *bmain, Depsgraph *depsgraph)
{
- for (Scene *scene = (Scene *)bmain->scene.first;
- scene != NULL;
- scene = (Scene *)scene->id.next)
- {
- DEG_scene_flush_update(bmain, scene);
- }
-}
-
-void DEG_scene_flush_update(Main *bmain, Scene *scene)
-{
- if (scene->depsgraph == NULL) {
+ if (depsgraph == NULL) {
return;
}
- DEG::deg_graph_flush_updates(
- bmain,
- reinterpret_cast<DEG::Depsgraph *>(scene->depsgraph));
+ DEG::deg_graph_flush_updates(bmain, (DEG::Depsgraph *)depsgraph);
}
/* Update dependency graph when visible scenes/layers changes. */
-void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
+void DEG_graph_on_visible_update(Main *bmain, Depsgraph *depsgraph)
{
- DEG::Depsgraph *graph = reinterpret_cast<DEG::Depsgraph *>(scene->depsgraph);
- wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
- int old_layers = graph->layers;
- if (wm != NULL) {
- BKE_main_id_tag_listbase(&bmain->scene, LIB_TAG_DOIT, true);
- graph->layers = 0;
- for (wmWindow *win = (wmWindow *)wm->windows.first;
- win != NULL;
- win = (wmWindow *)win->next)
- {
- Scene *scene = win->screen->scene;
- if (scene->id.tag & LIB_TAG_DOIT) {
- graph->layers |= BKE_screen_visible_layers(win->screen, scene);
- scene->id.tag &= ~LIB_TAG_DOIT;
- }
- }
- }
- else {
- /* All the layers for background render for now. */
- graph->layers = (1 << 20) - 1;
- }
- if (old_layers != graph->layers) {
- /* Tag all objects which becomes visible (or which becomes needed for dependencies)
- * for recalc.
- *
- * This is mainly needed on file load only, after that updates of invisible objects
- * will be stored in the pending list.
- */
- GHASH_FOREACH_BEGIN(DEG::IDDepsNode *, id_node, graph->id_hash)
- {
- ID *id = id_node->id;
- if ((id->tag & LIB_TAG_ID_RECALC_ALL) != 0 ||
- (id_node->layers & scene->lay_updated) == 0)
- {
- id_node->tag_update(graph);
- }
- /* A bit of magic: if object->recalc is set it means somebody tagged
- * it for update. If corresponding ID recalc flags are zero it means
- * graph has been evaluated after that and the recalc was skipped
- * because of visibility check.
- */
- if (GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- if ((id->tag & LIB_TAG_ID_RECALC_ALL) == 0 &&
- (object->recalc & OB_RECALC_ALL) != 0)
- {
- id_node->tag_update(graph);
- DEG::ComponentDepsNode *anim_comp =
- id_node->find_component(DEG::DEG_NODE_TYPE_ANIMATION);
- if (anim_comp != NULL && object->recalc & OB_RECALC_TIME) {
- anim_comp->tag_update(graph);
- }
- }
- }
- }
- GHASH_FOREACH_END();
- }
- scene->lay_updated |= graph->layers;
- /* If graph is tagged for update, we don't need to bother with updates here,
- * nodes will be re-created.
- */
- if (graph->need_update) {
- return;
- }
- /* Special trick to get local view to work. */
- LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *object = base->object;
- DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
- id_node->layers = 0;
- }
- LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *object = base->object;
- DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
- id_node->layers |= base->lay;
- if (object == scene->camera) {
- /* Camera should always be updated, it used directly by viewport. */
- id_node->layers |= (unsigned int)(-1);
- }
- }
- DEG::deg_graph_build_flush_layers(graph);
- LINKLIST_FOREACH (Base *, base, &scene->base) {
- Object *object = base->object;
- DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
- GHASH_FOREACH_BEGIN(DEG::ComponentDepsNode *, comp, id_node->components)
- {
- id_node->layers |= comp->layers;
- }
- GHASH_FOREACH_END();
- }
+ DEG::Depsgraph *graph = (DEG::Depsgraph *)depsgraph;
+ DEG::deg_graph_on_visible_update(bmain, graph);
}
void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
{
- for (Scene *scene = (Scene *)bmain->scene.first;
- scene != NULL;
- scene = (Scene *)scene->id.next)
- {
- if (scene->depsgraph != NULL) {
- DEG_graph_on_visible_update(bmain, scene);
+ LINKLIST_FOREACH(Scene *, scene, &bmain->scene) {
+ LINKLIST_FOREACH(ViewLayer *, view_layer, &scene->view_layers) {
+ Depsgraph *depsgraph =
+ (Depsgraph *)BKE_scene_get_depsgraph(scene,
+ view_layer,
+ false);
+ if (depsgraph != NULL) {
+ DEG_graph_on_visible_update(bmain, depsgraph);
+ }
}
}
}
@@ -370,7 +555,10 @@ void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
/* Check if something was changed in the database and inform
* editors about this.
*/
-void DEG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
+void DEG_ids_check_recalc(Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer,
+ bool time)
{
ListBase *lbarray[MAX_LIBARRAY];
int a;
@@ -388,7 +576,11 @@ void DEG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
}
}
- DEG::deg_editors_scene_update(bmain, scene, (updated || time));
+ DEGEditorUpdateContext update_ctx = {NULL};
+ update_ctx.bmain = bmain;
+ update_ctx.scene = scene;
+ update_ctx.view_layer = view_layer;
+ DEG::deg_editors_scene_update(&update_ctx, (updated || time));
}
void DEG_ids_clear_recalc(Main *bmain)
diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
index e5bdaf79366..24fbb8d6e6e 100644
--- a/source/blender/depsgraph/intern/depsgraph_type_defines.cc
+++ b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
@@ -105,6 +105,8 @@ static const char *stringify_opcode(eDepsOperation_Code opcode)
/* Animation, Drivers, etc. */
STRINGIFY_OPCODE(ANIMATION);
STRINGIFY_OPCODE(DRIVER);
+ /* Object related. */
+ STRINGIFY_OPCODE(OBJECT_BASE_FLAGS);
/* Transform. */
STRINGIFY_OPCODE(TRANSFORM_LOCAL);
STRINGIFY_OPCODE(TRANSFORM_PARENT);
@@ -134,11 +136,23 @@ static const char *stringify_opcode(eDepsOperation_Code opcode)
/* Particles. */
STRINGIFY_OPCODE(PARTICLE_SYSTEM_EVAL_INIT);
STRINGIFY_OPCODE(PARTICLE_SYSTEM_EVAL);
+ STRINGIFY_OPCODE(PARTICLE_SETTINGS_EVAL);
+ STRINGIFY_OPCODE(PARTICLE_SETTINGS_RECALC_CLEAR);
+ /* Batch cache. */
+ STRINGIFY_OPCODE(GEOMETRY_SELECT_UPDATE);
/* Masks. */
STRINGIFY_OPCODE(MASK_ANIMATION);
STRINGIFY_OPCODE(MASK_EVAL);
+ /* Collections. */
+ STRINGIFY_OPCODE(VIEW_LAYER_INIT);
+ STRINGIFY_OPCODE(VIEW_LAYER_EVAL);
+ STRINGIFY_OPCODE(VIEW_LAYER_DONE);
+ /* Copy on write. */
+ STRINGIFY_OPCODE(COPY_ON_WRITE);
/* Shading. */
STRINGIFY_OPCODE(SHADING);
+ STRINGIFY_OPCODE(MATERIAL_UPDATE);
+ STRINGIFY_OPCODE(WORLD_UPDATE);
/* Movie clip. */
STRINGIFY_OPCODE(MOVIECLIP_EVAL);
diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h
index 03d98c85148..b12becc5589 100644
--- a/source/blender/depsgraph/intern/depsgraph_types.h
+++ b/source/blender/depsgraph/intern/depsgraph_types.h
@@ -53,8 +53,10 @@ struct FCurve;
namespace DEG {
+/* TODO(sergey): Find a better place for this. */
using std::string;
using std::vector;
+using std::max;
/* Evaluation Operation for atomic operation */
// XXX: move this to another header that can be exposed?
@@ -79,6 +81,18 @@ typedef enum eDepsNode_Class {
DEG_NODE_CLASS_OPERATION = 2,
} eDepsNode_Class;
+/* Note: We use max comparison to mark an id node that is linked more than once
+ * So keep this enum ordered accordingly.
+ */
+typedef enum eDepsNode_LinkedState_Type {
+ /* Generic indirectly linked id node. */
+ DEG_ID_LINKED_INDIRECTLY = 0,
+ /* Id node present in the set (background) only. */
+ DEG_ID_LINKED_VIA_SET = 1,
+ /* Id node directly linked via the ScenLayer. */
+ DEG_ID_LINKED_DIRECTLY = 2,
+} eDepsNode_LinkedState_Type;
+
/* Types of Nodes */
typedef enum eDepsNode_Type {
/* Fallback type for invalid return value */
@@ -111,6 +125,14 @@ typedef enum eDepsNode_Type {
DEG_NODE_TYPE_GEOMETRY,
/* Sequencer Component (Scene Only) */
DEG_NODE_TYPE_SEQUENCER,
+ /* Component which contains all operations needed for layer collections
+ * evaluation.
+ */
+ DEG_NODE_TYPE_LAYER_COLLECTIONS,
+ /* Entry component of majority of ID nodes: prepares CoW pointers for
+ * execution.
+ */
+ DEG_NODE_TYPE_COPY_ON_WRITE,
/* **** Evaluation-Related Outer Types (with Subdata) **** */
@@ -122,8 +144,11 @@ typedef enum eDepsNode_Type {
DEG_NODE_TYPE_EVAL_PARTICLES,
/* Material Shading Component */
DEG_NODE_TYPE_SHADING,
+ DEG_NODE_TYPE_SHADING_PARAMETERS,
/* Cache Component */
DEG_NODE_TYPE_CACHE,
+ /* Batch Cache Component */
+ DEG_NODE_TYPE_BATCH_CACHE,
} eDepsNode_Type;
/* Identifiers for common operations (as an enum). */
@@ -145,6 +170,9 @@ typedef enum eDepsOperation_Code {
/* Driver */
DEG_OPCODE_DRIVER,
+ /* Object related. --------------------------------- */
+ DEG_OPCODE_OBJECT_BASE_FLAGS,
+
/* Transform. -------------------------------------- */
/* Transform entry point - local transforms only */
DEG_OPCODE_TRANSFORM_LOCAL,
@@ -206,9 +234,24 @@ typedef enum eDepsOperation_Code {
/* Particle System evaluation. */
DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT,
DEG_OPCODE_PARTICLE_SYSTEM_EVAL,
+ DEG_OPCODE_PARTICLE_SETTINGS_EVAL,
+ DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR,
+
+ /* Collections. ------------------------------------- */
+ DEG_OPCODE_VIEW_LAYER_INIT,
+ DEG_OPCODE_VIEW_LAYER_EVAL,
+ DEG_OPCODE_VIEW_LAYER_DONE,
+
+ /* Copy on Write. ------------------------------------ */
+ DEG_OPCODE_COPY_ON_WRITE,
/* Shading. ------------------------------------------- */
DEG_OPCODE_SHADING,
+ DEG_OPCODE_MATERIAL_UPDATE,
+ DEG_OPCODE_WORLD_UPDATE,
+
+ /* Batch caches. -------------------------------------- */
+ DEG_OPCODE_GEOMETRY_SELECT_UPDATE,
/* Masks. ------------------------------------------ */
DEG_OPCODE_MASK_ANIMATION,
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index 49ec68405f7..5aebd6814a0 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -38,12 +38,10 @@
#include "BLI_task.h"
#include "BLI_ghash.h"
-extern "C" {
-#include "BKE_depsgraph.h"
-#include "BKE_global.h"
-} /* extern "C" */
+#include "DNA_object_types.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "atomic_ops.h"
@@ -72,13 +70,11 @@ namespace DEG {
static void schedule_children(TaskPool *pool,
Depsgraph *graph,
OperationDepsNode *node,
- const unsigned int layers,
const int thread_id);
struct DepsgraphEvalState {
EvaluationContext *eval_ctx;
Depsgraph *graph;
- unsigned int layers;
};
static void deg_task_run_func(TaskPool *pool,
@@ -126,39 +122,31 @@ static void deg_task_run_func(TaskPool *pool,
}
BLI_task_pool_delayed_push_begin(pool, thread_id);
- schedule_children(pool, state->graph, node, state->layers, thread_id);
+ schedule_children(pool, state->graph, node, thread_id);
BLI_task_pool_delayed_push_end(pool, thread_id);
}
typedef struct CalculatePengindData {
Depsgraph *graph;
- unsigned int layers;
} CalculatePengindData;
static void calculate_pending_func(void *data_v, int i)
{
CalculatePengindData *data = (CalculatePengindData *)data_v;
Depsgraph *graph = data->graph;
- unsigned int layers = data->layers;
OperationDepsNode *node = graph->operations[i];
- IDDepsNode *id_node = node->owner->owner;
node->num_links_pending = 0;
node->scheduled = false;
/* count number of inputs that need updates */
- if ((id_node->layers & layers) != 0 &&
- (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
- {
+ if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) {
foreach (DepsRelation *rel, node->inlinks) {
if (rel->from->type == DEG_NODE_TYPE_OPERATION &&
(rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
{
OperationDepsNode *from = (OperationDepsNode *)rel->from;
- IDDepsNode *id_from_node = from->owner->owner;
- if ((id_from_node->layers & layers) != 0 &&
- (from->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
- {
+ if ((from->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) {
++node->num_links_pending;
}
}
@@ -166,13 +154,12 @@ static void calculate_pending_func(void *data_v, int i)
}
}
-static void calculate_pending_parents(Depsgraph *graph, unsigned int layers)
+static void calculate_pending_parents(Depsgraph *graph)
{
const int num_operations = graph->operations.size();
const bool do_threads = num_operations > 256;
CalculatePengindData data;
data.graph = graph;
- data.layers = layers;
BLI_task_parallel_range(0,
num_operations,
&data,
@@ -211,15 +198,11 @@ static void calculate_eval_priority(OperationDepsNode *node)
* dec_parents: Decrement pending parents count, true when child nodes are
* scheduled after a task has been completed.
*/
-static void schedule_node(TaskPool *pool, Depsgraph *graph, unsigned int layers,
+static void schedule_node(TaskPool *pool, Depsgraph *graph,
OperationDepsNode *node, bool dec_parents,
const int thread_id)
{
- unsigned int id_layers = node->owner->owner->layers;
-
- if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0 &&
- (id_layers & layers) != 0)
- {
+ if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) {
if (dec_parents) {
BLI_assert(node->num_links_pending > 0);
atomic_sub_and_fetch_uint32(&node->num_links_pending, 1);
@@ -231,7 +214,7 @@ static void schedule_node(TaskPool *pool, Depsgraph *graph, unsigned int layers,
if (!is_scheduled) {
if (node->is_noop()) {
/* skip NOOP node, schedule children right away */
- schedule_children(pool, graph, node, layers, thread_id);
+ schedule_children(pool, graph, node, thread_id);
}
else {
/* children are scheduled once this task is completed */
@@ -247,19 +230,16 @@ static void schedule_node(TaskPool *pool, Depsgraph *graph, unsigned int layers,
}
}
-static void schedule_graph(TaskPool *pool,
- Depsgraph *graph,
- const unsigned int layers)
+static void schedule_graph(TaskPool *pool, Depsgraph *graph)
{
foreach (OperationDepsNode *node, graph->operations) {
- schedule_node(pool, graph, layers, node, false, 0);
+ schedule_node(pool, graph, node, false, 0);
}
}
static void schedule_children(TaskPool *pool,
Depsgraph *graph,
OperationDepsNode *node,
- const unsigned int layers,
const int thread_id)
{
foreach (DepsRelation *rel, node->outlinks) {
@@ -271,7 +251,6 @@ static void schedule_children(TaskPool *pool,
}
schedule_node(pool,
graph,
- layers,
child,
(rel->flag & DEPSREL_FLAG_CYCLIC) == 0,
thread_id);
@@ -286,8 +265,7 @@ static void schedule_children(TaskPool *pool,
* \note Time sources should be all valid!
*/
void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
- Depsgraph *graph,
- const unsigned int layers)
+ Depsgraph *graph)
{
/* Generate base evaluation context, upon which all the others are derived. */
// TODO: this needs both main and scene access...
@@ -297,20 +275,16 @@ 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->depsgraph = (::Depsgraph *)graph;
+ eval_ctx->view_layer = DEG_get_evaluated_view_layer((::Depsgraph *)graph);
eval_ctx->ctime = time_src->cfra;
/* XXX could use a separate pool for each eval context */
DepsgraphEvalState state;
state.eval_ctx = eval_ctx;
state.graph = graph;
- state.layers = layers;
TaskScheduler *task_scheduler;
bool need_free_scheduler;
@@ -326,7 +300,7 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, &state);
- calculate_pending_parents(graph, layers);
+ calculate_pending_parents(graph);
/* Clear tags. */
foreach (OperationDepsNode *node, graph->operations) {
@@ -340,7 +314,7 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
}
#endif
- schedule_graph(task_pool, graph, layers);
+ schedule_graph(task_pool, graph);
BLI_task_pool_work_and_wait(task_pool);
BLI_task_pool_free(task_pool);
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.h b/source/blender/depsgraph/intern/eval/deg_eval.h
index 49c0379939e..576ab89dec1 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.h
+++ b/source/blender/depsgraph/intern/eval/deg_eval.h
@@ -46,7 +46,6 @@ struct Depsgraph;
* \note Time sources should be all valid!
*/
void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
- Depsgraph *graph,
- const unsigned int layers);
+ Depsgraph *graph);
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
new file mode 100644
index 00000000000..97e38af4367
--- /dev/null
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -0,0 +1,939 @@
+/*
+ * ***** 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) 20137Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+/** \file blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+ * \ingroup depsgraph
+ */
+
+/* Enable special; trickery to treat nested owned IDs (such as nodetree of
+ * material) to be handled in same way as "real" datablocks, even tho some
+ * internal BKE routines doesn't treat them like that.
+ *
+ * TODO(sergey): Re-evaluate that after new ID handling is in place.
+ */
+#define NESTED_ID_NASTY_WORKAROUND
+
+#include "intern/eval/deg_eval_copy_on_write.h"
+
+#include <cstring>
+
+#include "BLI_utildefines.h"
+#include "BLI_threads.h"
+#include "BLI_string.h"
+
+#include "BKE_global.h"
+#include "BKE_layer.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "DNA_ID.h"
+#include "DNA_mesh_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+
+#ifdef NESTED_ID_NASTY_WORKAROUND
+# include "DNA_key_types.h"
+# include "DNA_lamp_types.h"
+# include "DNA_linestyle_types.h"
+# include "DNA_material_types.h"
+# include "DNA_node_types.h"
+# include "DNA_texture_types.h"
+# include "DNA_world_types.h"
+#endif
+
+#include "BKE_action.h"
+#include "BKE_editmesh.h"
+#include "BKE_library_query.h"
+#include "BKE_object.h"
+}
+
+#include "intern/depsgraph.h"
+#include "intern/builder/deg_builder_nodes.h"
+#include "intern/nodes/deg_node.h"
+
+namespace DEG {
+
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+
+namespace {
+
+#ifdef NESTED_ID_NASTY_WORKAROUND
+union NestedIDHackTempStorage {
+ FreestyleLineStyle linestyle;
+ Lamp lamp;
+ Material material;
+ Mesh mesh;
+ Scene scene;
+ Tex tex;
+ World world;
+};
+
+/* Set nested owned ID pointers to NULL. */
+void nested_id_hack_discard_pointers(ID *id_cow)
+{
+ switch (GS(id_cow->name)) {
+# define SPECIAL_CASE(id_type, dna_type, field) \
+ case id_type: \
+ { \
+ ((dna_type *)id_cow)->field = NULL; \
+ break; \
+ }
+
+ SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree)
+ SPECIAL_CASE(ID_LA, Lamp, nodetree)
+ SPECIAL_CASE(ID_MA, Material, nodetree)
+ SPECIAL_CASE(ID_SCE, Scene, nodetree)
+ SPECIAL_CASE(ID_TE, Tex, nodetree)
+ SPECIAL_CASE(ID_WO, World, nodetree)
+
+ SPECIAL_CASE(ID_ME, Mesh, key)
+
+# undef SPECIAL_CASE
+
+ default:
+ break;
+ }
+}
+
+/* Set ID pointer of nested owned IDs (nodetree, key) to NULL.
+ *
+ * Return pointer to a new ID to be used.
+ */
+const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage,
+ const ID *id)
+{
+ switch (GS(id->name)) {
+# define SPECIAL_CASE(id_type, dna_type, field, variable) \
+ case id_type: \
+ { \
+ storage->variable = *(dna_type *)id; \
+ storage->variable.field = NULL; \
+ return &storage->variable.id; \
+ }
+
+ SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree, linestyle)
+ SPECIAL_CASE(ID_LA, Lamp, nodetree, lamp)
+ SPECIAL_CASE(ID_MA, Material, nodetree, material)
+ SPECIAL_CASE(ID_SCE, Scene, nodetree, scene)
+ SPECIAL_CASE(ID_TE, Tex, nodetree, tex)
+ SPECIAL_CASE(ID_WO, World, nodetree, world)
+
+ SPECIAL_CASE(ID_ME, Mesh, key, mesh)
+
+# undef SPECIAL_CASE
+
+ default:
+ break;
+ }
+ return id;
+}
+
+/* Set ID pointer of nested owned IDs (nodetree, key) to the original value. */
+void nested_id_hack_restore_pointers(const ID *old_id, ID *new_id)
+{
+ if (new_id == NULL) {
+ return;
+ }
+ switch (GS(old_id->name)) {
+# define SPECIAL_CASE(id_type, dna_type, field) \
+ case id_type: \
+ { \
+ ((dna_type *)(new_id))->field = \
+ ((dna_type *)(old_id))->field; \
+ break; \
+ }
+
+ SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree)
+ SPECIAL_CASE(ID_LA, Lamp, nodetree)
+ SPECIAL_CASE(ID_MA, Material, nodetree)
+ SPECIAL_CASE(ID_SCE, Scene, nodetree)
+ SPECIAL_CASE(ID_TE, Tex, nodetree)
+ SPECIAL_CASE(ID_WO, World, nodetree)
+
+ SPECIAL_CASE(ID_ME, Mesh, key)
+
+#undef SPECIAL_CASE
+ default:
+ break;
+ }
+}
+
+/* Remap pointer of nested owned IDs (nodetree. key) to the new ID values. */
+void ntree_hack_remap_pointers(const Depsgraph *depsgraph, ID *id_cow)
+{
+ switch (GS(id_cow->name)) {
+# define SPECIAL_CASE(id_type, dna_type, field, field_type) \
+ case id_type: \
+ { \
+ dna_type *data = (dna_type *)id_cow; \
+ if (data->field != NULL) { \
+ ID *ntree_id_cow = depsgraph->get_cow_id(&data->field->id); \
+ if (ntree_id_cow != NULL) { \
+ DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n", \
+ data->field->id.name, \
+ data->field, \
+ ntree_id_cow); \
+ data->field = (field_type *)ntree_id_cow; \
+ } \
+ } \
+ break; \
+ }
+
+ SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree, bNodeTree)
+ SPECIAL_CASE(ID_LA, Lamp, nodetree, bNodeTree)
+ SPECIAL_CASE(ID_MA, Material, nodetree, bNodeTree)
+ SPECIAL_CASE(ID_SCE, Scene, nodetree, bNodeTree)
+ SPECIAL_CASE(ID_TE, Tex, nodetree, bNodeTree)
+ SPECIAL_CASE(ID_WO, World, nodetree, bNodeTree)
+
+ SPECIAL_CASE(ID_ME, Mesh, key, Key)
+
+#undef SPECIAL_CASE
+ default:
+ break;
+ }
+}
+#endif /* NODETREE_NASTY_WORKAROUND */
+
+struct ValidateData {
+ bool is_valid;
+};
+
+/* Similar to generic id_copy() but does not require main and assumes pointer
+ * is already allocated,
+ */
+bool id_copy_inplace_no_main(const ID *id, ID *newid)
+{
+ const ID *id_for_copy = id;
+
+#ifdef NESTED_ID_NASTY_WORKAROUND
+ NestedIDHackTempStorage id_hack_storage;
+ id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, id);
+#endif
+
+ bool result = BKE_id_copy_ex(NULL,
+ (ID *)id_for_copy,
+ &newid,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_ALLOCATE |
+ LIB_ID_CREATE_NO_DEG_TAG,
+ false);
+
+#ifdef NESTED_ID_NASTY_WORKAROUND
+ if (result) {
+ nested_id_hack_restore_pointers(id, newid);
+ }
+#endif
+
+ return result;
+}
+
+/* Similar to BKE_scene_copy() but does not require main and assumes pointer
+ * is already allocated.
+ */
+bool scene_copy_inplace_no_main(const Scene *scene, Scene *new_scene)
+{
+ const ID *id_for_copy = &scene->id;
+
+#ifdef NESTED_ID_NASTY_WORKAROUND
+ NestedIDHackTempStorage id_hack_storage;
+ id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage,
+ &scene->id);
+#endif
+
+ bool result = BKE_id_copy_ex(NULL,
+ id_for_copy,
+ (ID **)&new_scene,
+ LIB_ID_COPY_ACTIONS |
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_ALLOCATE |
+ LIB_ID_CREATE_NO_DEG_TAG,
+ false);
+
+#ifdef NESTED_ID_NASTY_WORKAROUND
+ if (result) {
+ nested_id_hack_restore_pointers(&scene->id, &new_scene->id);
+ }
+#endif
+
+ return result;
+}
+
+/* Check whether given ID is expanded or still a shallow copy. */
+BLI_INLINE bool check_datablock_expanded(const ID *id_cow)
+{
+ return (id_cow->name[0] != '\0');
+}
+
+/* Check whether datablock was already expanded during depsgraph
+ * construction.
+ */
+static bool check_datablock_expanded_at_construction(const ID *id_orig)
+{
+ const ID_Type id_type = GS(id_orig->name);
+ return (id_type == ID_SCE) ||
+ (id_type == ID_OB && ((Object *)id_orig)->type == OB_ARMATURE) ||
+ (id_type == ID_AR);
+}
+
+/* Those are datablocks which are not covered by dependency graph and hence
+ * does not need any remapping or anything.
+ *
+ * TODO(sergey): How to make it more robust for the future, so we don't have
+ * to maintain exception lists all over the code?
+ */
+static bool check_datablocks_copy_on_writable(const ID *id_orig)
+{
+ const ID_Type id_type = GS(id_orig->name);
+ /* We shouldn't bother if copied ID is same as original one. */
+ if (!deg_copy_on_write_is_needed(id_orig)) {
+ return false;
+ }
+ return !ELEM(id_type, ID_BR,
+ ID_LS,
+ ID_AC,
+ ID_GR,
+ ID_PAL);
+}
+
+/* Callback for BKE_library_foreach_ID_link which remaps original ID pointer
+ * with the one created by CoW system.
+ */
+
+struct RemapCallbackUserData {
+ /* Dependency graph for which remapping is happening. */
+ const Depsgraph *depsgraph;
+ /* Temporarily allocated memory for copying purposes. This ID will
+ * be discarded after expanding is done, so need to make sure temp_id
+ * is replaced with proper real_id.
+ *
+ * NOTE: This is due to our logic of "inplace" duplication, where we
+ * use generic duplication routines (which gives us new ID) which then
+ * is followed with copying data to a placeholder we prepared before and
+ * discarding pointer returned by duplication routines.
+ */
+ const ID *temp_id;
+ ID *real_id;
+ /* Create placeholder for ID nodes for cases when we need to remap original
+ * ID to it[s CoW version but we don't have required ID node yet.
+ *
+ * This happens when expansion happens a ta construction time.
+ */
+ DepsgraphNodeBuilder *node_builder;
+ bool create_placeholders;
+};
+
+int foreach_libblock_remap_callback(void *user_data_v,
+ ID *id_self,
+ ID **id_p,
+ int /*cb_flag*/)
+{
+ RemapCallbackUserData *user_data = (RemapCallbackUserData *)user_data_v;
+ const Depsgraph *depsgraph = user_data->depsgraph;
+ if (*id_p != NULL) {
+ ID *id_orig = *id_p;
+ if (id_orig == user_data->temp_id) {
+ DEG_COW_PRINT(" Remapping datablock for %s: id_temp=%p id_cow=%p\n",
+ id_orig->name, id_orig, user_data->real_id);
+ *id_p = user_data->real_id;
+ }
+ else if (check_datablocks_copy_on_writable(id_orig)) {
+ ID *id_cow;
+ if (user_data->create_placeholders) {
+ /* Special workaround to stop creating temp datablocks for
+ * objects which are coming from scene's collection and which
+ * are never linked to any of layers.
+ *
+ * TODO(sergey): Ideally we need to tell ID looper to ignore
+ * those or at least make it more reliable check where the
+ * pointer is coming from.
+ */
+ const ID_Type id_type = GS(id_orig->name);
+ const ID_Type id_type_self = GS(id_self->name);
+ if (id_type == ID_OB && id_type_self == ID_SCE) {
+ IDDepsNode *id_node = depsgraph->find_id_node(id_orig);
+ if (id_node == NULL) {
+ id_cow = id_orig;
+ }
+ else {
+ id_cow = id_node->id_cow;
+ }
+ }
+ else {
+ id_cow = user_data->node_builder->ensure_cow_id(id_orig);
+ }
+ }
+ else {
+ id_cow = depsgraph->get_cow_id(id_orig);
+ }
+ BLI_assert(id_cow != NULL);
+ DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n",
+ id_orig->name, id_orig, id_cow);
+ *id_p = id_cow;
+ }
+ }
+ return IDWALK_RET_NOP;
+}
+
+/* Do some special treatment of data transfer from original ID to it's
+ * CoW complementary part.
+ *
+ * Only use for the newly created CoW datablocks.
+ */
+void update_special_pointers(const Depsgraph *depsgraph,
+ const ID *id_orig, ID *id_cow)
+{
+ const ID_Type type = GS(id_orig->name);
+ switch (type) {
+ case ID_OB:
+ {
+ /* Ensure we don't drag someone's else derived mesh to the
+ * new copy of the object.
+ */
+ Object *object_cow = (Object *)id_cow;
+ const Object *object_orig = (const Object *)id_orig;
+ (void) object_cow; /* Ignored for release builds. */
+ BLI_assert(object_cow->derivedFinal == NULL);
+ BLI_assert(object_cow->derivedDeform == NULL);
+ object_cow->mode = object_orig->mode;
+ break;
+ }
+ case ID_ME:
+ {
+ /* For meshes we need to update edit_btmesh to make it to point
+ * to the CoW version of object.
+ *
+ * This is kind of confusing, because actual bmesh is not owned by
+ * the CoW object, so need to be accurate about using link from
+ * edit_btmesh to object.
+ */
+ const Mesh *mesh_orig = (const Mesh *)id_orig;
+ Mesh *mesh_cow = (Mesh *)id_cow;
+ if (mesh_orig->edit_btmesh != NULL) {
+ mesh_cow->edit_btmesh = (BMEditMesh *)MEM_dupallocN(mesh_orig->edit_btmesh);
+ mesh_cow->edit_btmesh->ob =
+ (Object *)depsgraph->get_cow_id(&mesh_orig->edit_btmesh->ob->id);
+ mesh_cow->edit_btmesh->derivedFinal = NULL;
+ mesh_cow->edit_btmesh->derivedCage = NULL;
+ }
+ break;
+ }
+ case ID_SCE:
+ {
+ const Scene *scene_orig = (const Scene *)id_orig;
+ Scene *scene_cow = (Scene *)id_cow;
+ if (scene_orig->obedit != NULL) {
+ scene_cow->obedit = (Object *)depsgraph->get_cow_id(&scene_orig->obedit->id);
+ }
+ else {
+ scene_cow->obedit = NULL;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/* Update copy-on-write version of scene from original scene. */
+void update_copy_on_write_scene(const Depsgraph *depsgraph,
+ Scene *scene_cow,
+ const Scene *scene_orig)
+{
+ // Some non-pointer data sync, current frame for now.
+ // TODO(sergey): Are we missing something here?
+ scene_cow->r.cfra = scene_orig->r.cfra;
+ scene_cow->r.subframe = scene_orig->r.subframe;
+ // Update bases.
+ const ViewLayer *view_layer_orig = (ViewLayer *)scene_orig->view_layers.first;
+ ViewLayer *view_layer_cow = (ViewLayer *)scene_cow->view_layers.first;
+ while (view_layer_orig != NULL) {
+ // Update pointers to active base.
+ if (view_layer_orig->basact == NULL) {
+ view_layer_cow->basact = NULL;
+ }
+ else {
+ const Object *obact_orig = view_layer_orig->basact->object;
+ Object *obact_cow = (Object *)depsgraph->get_cow_id(&obact_orig->id);
+ view_layer_cow->basact = BKE_view_layer_base_find(view_layer_cow, obact_cow);
+ }
+ // Update base flags.
+ //
+ // TODO(sergey): We should probably check visibled/selectabled
+ // flag here?
+ const Base *base_orig = (Base *)view_layer_orig->object_bases.first;
+ Base *base_cow = (Base *)view_layer_cow->object_bases.first;;
+ while (base_orig != NULL) {
+ base_cow->flag = base_orig->flag;
+ base_orig = base_orig->next;
+ base_cow = base_cow->next;
+ }
+ view_layer_orig = view_layer_orig->next;
+ view_layer_cow = view_layer_cow->next;
+ }
+ // Update edit object pointer.
+ if (scene_orig->obedit != NULL) {
+ scene_cow->obedit = (Object *)depsgraph->get_cow_id(&scene_orig->obedit->id);
+ }
+ else {
+ scene_cow->obedit = NULL;
+ }
+ /* Synchronize active render engine. */
+ BLI_strncpy(scene_cow->view_render.engine_id,
+ scene_orig->view_render.engine_id,
+ sizeof(scene_cow->view_render.engine_id));
+ /* TODO(sergey): What else do we need here? */
+}
+
+/* Update copy-on-write version of armature object from original scene. */
+void update_copy_on_write_object(const Depsgraph * /*depsgraph*/,
+ Object *object_cow,
+ const Object *object_orig)
+{
+ /* TODO(sergey): This function might be split into a smaller ones,
+ * reused for different updates. And maybe even moved to BKE.
+ */
+ /* Update armature/pose related flags. */
+ bPose *pose_cow = object_cow->pose;
+ const bPose *pose_orig = object_orig->pose;
+ extract_pose_from_pose(pose_cow, pose_orig);
+ /* Update object itself. */
+ BKE_object_transform_copy(object_cow, object_orig);
+ object_cow->mode = object_orig->mode;
+}
+
+/* Update copy-on-write version of datablock from it's original ID without re-building
+ * the whole datablock from scratch.
+ *
+ * Used for such special cases as scene collections and armatures, which can not use full
+ * re-alloc due to pointers used as function bindings.
+ */
+void update_copy_on_write_datablock(const Depsgraph *depsgraph,
+ const ID *id_orig, ID *id_cow)
+{
+ bool ok = false;
+ const ID_Type id_type = GS(id_orig->name);
+ switch (id_type) {
+ case ID_SCE: {
+ const Scene *scene_orig = (const Scene *)id_orig;
+ Scene *scene_cow = (Scene *)id_cow;
+ update_copy_on_write_scene(depsgraph, scene_cow, scene_orig);
+ ok = true;
+ break;
+ }
+ case ID_OB: {
+ const Object *object_orig = (const Object *)id_orig;
+ Object *object_cow = (Object *)id_cow;
+ if (object_orig->type == OB_ARMATURE) {
+ update_copy_on_write_object(depsgraph,
+ object_cow,
+ object_orig);
+ ok = true;
+ }
+ break;
+ }
+ case ID_AR:
+ /* Nothing to do currently. */
+ ok = true;
+ break;
+ default:
+ break;
+ }
+ // TODO(sergey): Other ID types here.
+ if (!ok) {
+ BLI_assert(!"Missing update logic of expanded datablock");
+ }
+}
+
+/* This callback is used to validate that all nested ID datablocks are
+ * properly expanded.
+ */
+int foreach_libblock_validate_callback(void *user_data,
+ ID * /*id_self*/,
+ ID **id_p,
+ int /*cb_flag*/)
+{
+ ValidateData *data = (ValidateData *)user_data;
+ if (*id_p != NULL) {
+ if (!check_datablock_expanded(*id_p)) {
+ data->is_valid = false;
+ /* TODO(sergey): Store which is is not valid? */
+ }
+ }
+ return IDWALK_RET_NOP;
+}
+
+} // namespace
+
+/* Actual implementation of logic which "expands" all the data which was not
+ * yet copied-on-write.
+ *
+ * NOTE: Expects that CoW datablock is empty.
+ */
+ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
+ const IDDepsNode *id_node,
+ DepsgraphNodeBuilder *node_builder,
+ bool create_placeholders)
+{
+ BLI_assert(!create_placeholders ||
+ check_datablock_expanded_at_construction(id_node->id_orig));
+ const ID *id_orig = id_node->id_orig;
+ ID *id_cow = id_node->id_cow;
+ /* No need to expand such datablocks, their copied ID is same as original
+ * one already.
+ */
+ if (!deg_copy_on_write_is_needed(id_orig)) {
+ return id_cow;
+ }
+ DEG_COW_PRINT("Expanding datablock for %s: id_orig=%p id_cow=%p\n",
+ id_orig->name, id_orig, id_cow);
+ /* Sanity checks. */
+ /* NOTE: Disabled for now, conflicts when re-using evaluated datablock when
+ * rebuilding dependencies.
+ */
+ if (check_datablock_expanded(id_cow) && create_placeholders) {
+ deg_free_copy_on_write_datablock(id_cow);
+ }
+ // BLI_assert(check_datablock_expanded(id_cow) == false);
+ /* Copy data from original ID to a copied version. */
+ /* TODO(sergey): Avoid doing full ID copy somehow, make Mesh to reference
+ * original geometry arrays for until those are modified.
+ */
+ /* TODO(sergey): We do some trickery with temp bmain and extra ID pointer
+ * just to be able to use existing API. Ideally we need to replace this with
+ * in-place copy from existing datablock to a prepared memory.
+ *
+ * NOTE: We don't use BKE_main_{new,free} because:
+ * - We don't want heap-allocations here.
+ * - We don't want bmain's content to be freed when main is freed.
+ */
+ bool done = false;
+ /* Need to make sure the possibly temporary allocated memory is correct for
+ * until we are fully done with remapping original pointers with copied on
+ * write ones.
+ */
+ ID *newid = NULL;
+ /* First we handle special cases which are not covered by id_copy() yet.
+ * or cases where we want to do something smarter than simple datablock
+ * copy.
+ */
+ const ID_Type id_type = GS(id_orig->name);
+ switch (id_type) {
+ case ID_SCE:
+ {
+ done = scene_copy_inplace_no_main((Scene *)id_orig, (Scene *)id_cow);
+ break;
+ }
+ case ID_ME:
+ {
+ /* TODO(sergey): Ideally we want to handle meshes in a special
+ * manner here to avoid initial copy of all the geometry arrays.
+ */
+ break;
+ }
+ default:
+ break;
+ }
+ if (!done) {
+ done = id_copy_inplace_no_main(id_orig, id_cow);
+ }
+ if (!done) {
+ BLI_assert(!"No idea how to perform CoW on datablock");
+ }
+ /* Update pointers to nested ID datablocks. */
+ DEG_COW_PRINT(" Remapping ID links for %s: id_orig=%p id_cow=%p\n",
+ id_orig->name, id_orig, id_cow);
+
+#ifdef NESTED_ID_NASTY_WORKAROUND
+ ntree_hack_remap_pointers(depsgraph, id_cow);
+#endif
+ /* Do it now, so remapping will understand that possibly remapped self ID
+ * is not to be remapped again.
+ */
+ deg_tag_copy_on_write_id(id_cow, id_orig);
+ /* Perform remapping of the nodes. */
+ RemapCallbackUserData user_data;
+ user_data.depsgraph = depsgraph;
+ user_data.temp_id = newid;
+ user_data.real_id = id_cow;
+ user_data.node_builder = node_builder;
+ user_data.create_placeholders = create_placeholders;
+ BKE_library_foreach_ID_link(NULL,
+ id_cow,
+ foreach_libblock_remap_callback,
+ (void *)&user_data,
+ IDWALK_NOP);
+ /* Correct or tweak some pointers which are not taken care by foreach
+ * from above.
+ */
+ update_special_pointers(depsgraph, id_orig, id_cow);
+ /* Now we can safely discard temporary memory used for copying. */
+ if (newid != NULL) {
+ MEM_freeN(newid);
+ }
+ return id_cow;
+}
+
+/* NOTE: Depsgraph is supposed to have ID node already. */
+ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
+ ID *id_orig,
+ DepsgraphNodeBuilder *node_builder,
+ bool create_placeholders)
+{
+ DEG::IDDepsNode *id_node = depsgraph->find_id_node(id_orig);
+ BLI_assert(id_node != NULL);
+ return deg_expand_copy_on_write_datablock(depsgraph,
+ id_node,
+ node_builder,
+ create_placeholders);
+}
+
+ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph,
+ const IDDepsNode *id_node)
+{
+ const ID *id_orig = id_node->id_orig;
+ const ID_Type id_type = GS(id_orig->name);
+ ID *id_cow = id_node->id_cow;
+ /* Similar to expansion, no need to do anything here. */
+ if (!deg_copy_on_write_is_needed(id_orig)) {
+ return id_cow;
+ }
+ /* Special case for datablocks which are expanded at the dependency graph
+ * construction time. This datablocks must never change pointers of their
+ * nested data since it is used for function bindings.
+ */
+ if (check_datablock_expanded_at_construction(id_orig)) {
+ BLI_assert(check_datablock_expanded(id_cow) == true);
+ update_copy_on_write_datablock(depsgraph, id_orig, id_cow);
+ return id_cow;
+ }
+ /* For the rest if datablock types we use simple logic:
+ * - Free previously expanded data, if any.
+ * - Perform full datablock copy.
+ *
+ * Note that we never free GPU materials from here since that's not
+ * safe for threading and GPU materials are likely to be re-used.
+ */
+ /* TODO(sergey): Either move this to an utility function or redesign
+ * Copy-on-Write components in a way that only needed parts are being
+ * copied over.
+ */
+ ListBase gpumaterial_backup;
+ ListBase *gpumaterial_ptr = NULL;
+ Mesh *mesh_evaluated = NULL;
+ IDProperty *base_collection_properties = NULL;
+ short base_flag = 0;
+ if (check_datablock_expanded(id_cow)) {
+ switch (id_type) {
+ case ID_MA:
+ {
+ Material *material = (Material *)id_cow;
+ gpumaterial_ptr = &material->gpumaterial;
+ break;
+ }
+ case ID_WO:
+ {
+ World *world = (World *)id_cow;
+ gpumaterial_ptr = &world->gpumaterial;
+ break;
+ }
+ case ID_OB:
+ {
+ Object *object = (Object *)id_cow;
+ /* Store evaluated mesh, make sure we don't free it. */
+ mesh_evaluated = object->mesh_evaluated;
+ object->mesh_evaluated = NULL;
+ /* Currently object update will override actual object->data
+ * to an evaluated version. Need to make sure we don't have
+ * data set to evaluated one before free anything.
+ */
+ if (mesh_evaluated != NULL) {
+ if (object->data == mesh_evaluated) {
+ object->data = mesh_evaluated->id.newid;
+ }
+ }
+ /* Make a backup of base flags. */
+ base_collection_properties = object->base_collection_properties;
+ base_flag = object->base_flag;
+ break;
+ }
+ default:
+ break;
+ }
+ if (gpumaterial_ptr != NULL) {
+ gpumaterial_backup = *gpumaterial_ptr;
+ gpumaterial_ptr->first = gpumaterial_ptr->last = NULL;
+ }
+ }
+ deg_free_copy_on_write_datablock(id_cow);
+ deg_expand_copy_on_write_datablock(depsgraph, id_node);
+ /* Restore GPU materials. */
+ if (gpumaterial_ptr != NULL) {
+ *gpumaterial_ptr = gpumaterial_backup;
+ }
+ if (id_type == ID_OB) {
+ Object *object = (Object *)id_cow;
+ if (mesh_evaluated != NULL) {
+ object->mesh_evaluated = mesh_evaluated;
+ /* Do same thing as object update: override actual object data
+ * pointer with evaluated datablock.
+ */
+ if (object->type == OB_MESH) {
+ object->data = mesh_evaluated;
+ /* Evaluated mesh simply copied edit_btmesh pointer from
+ * original mesh during update, need to make sure no dead
+ * pointers are left behind.
+ */
+ mesh_evaluated->edit_btmesh =
+ ((Mesh *)mesh_evaluated->id.newid)->edit_btmesh;
+ }
+ }
+ if (base_collection_properties != NULL) {
+ object->base_collection_properties = base_collection_properties;
+ object->base_flag = base_flag;
+ }
+ }
+ return id_cow;
+}
+
+/* NOTE: Depsgraph is supposed to have ID node already. */
+ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph,
+ ID *id_orig)
+{
+ DEG::IDDepsNode *id_node = depsgraph->find_id_node(id_orig);
+ BLI_assert(id_node != NULL);
+ return deg_update_copy_on_write_datablock(depsgraph, id_node);
+}
+
+/* Free content of the CoW datablock
+ * Notes:
+ * - Does not recurs into nested ID datablocks.
+ * - Does not free datablock itself.
+ */
+void deg_free_copy_on_write_datablock(ID *id_cow)
+{
+ if (!check_datablock_expanded(id_cow)) {
+ /* Actual content was never copied on top of CoW block, we have
+ * nothing to free.
+ */
+ return;
+ }
+ const ID_Type type = GS(id_cow->name);
+#ifdef NESTED_ID_NASTY_WORKAROUND
+ nested_id_hack_discard_pointers(id_cow);
+#endif
+ switch (type) {
+ case ID_OB:
+ {
+ /* TODO(sergey): This workaround is only to prevent free derived
+ * caches from modifying object->data. This is currently happening
+ * due to mesh/curve datablock boundbox tagging dirty.
+ */
+ Object *ob_cow = (Object *)id_cow;
+ ob_cow->data = NULL;
+ break;
+ }
+ case ID_ME:
+ {
+ Mesh *mesh_cow = (Mesh *)id_cow;
+ if (mesh_cow->edit_btmesh != NULL) {
+ BKE_editmesh_free_derivedmesh(mesh_cow->edit_btmesh);
+ MEM_freeN(mesh_cow->edit_btmesh);
+ mesh_cow->edit_btmesh = NULL;
+ }
+ break;
+ }
+ case ID_SCE:
+ {
+ /* Special case for scene: we use explicit function call which
+ * ensures no access to other datablocks is done.
+ */
+ Scene *scene = (Scene *)id_cow;
+ BKE_scene_free_ex(scene, false);
+ BKE_libblock_free_data(id_cow, false);
+ id_cow->name[0] = '\0';
+ return;
+ }
+ default:
+ break;
+ }
+ BKE_libblock_free_datablock(id_cow, 0);
+ BKE_libblock_free_data(id_cow, false);
+ /* Signal datablock as not being expanded. */
+ id_cow->name[0] = '\0';
+}
+
+void deg_evaluate_copy_on_write(const EvaluationContext * /*eval_ctx*/,
+ const Depsgraph *depsgraph,
+ const IDDepsNode *id_node)
+{
+ DEBUG_PRINT("%s on %s\n", __func__, id_node->id_orig->name);
+ deg_update_copy_on_write_datablock(depsgraph, id_node);
+}
+
+bool deg_validate_copy_on_write_datablock(ID *id_cow)
+{
+ if (id_cow == NULL) {
+ return false;
+ }
+ ValidateData data;
+ data.is_valid = true;
+ BKE_library_foreach_ID_link(NULL,
+ id_cow,
+ foreach_libblock_validate_callback,
+ &data,
+ IDWALK_NOP);
+ return data.is_valid;
+}
+
+void deg_tag_copy_on_write_id(ID *id_cow, const ID *id_orig)
+{
+ id_cow->tag |= LIB_TAG_COPY_ON_WRITE;
+ /* TODO(sergey): Is it safe to re-use newid for original ID link? */
+ id_cow->newid = (ID *)id_orig;
+}
+
+bool deg_copy_on_write_is_expanded(const ID *id_cow)
+{
+ return check_datablock_expanded(id_cow);
+}
+
+bool deg_copy_on_write_is_needed(const ID *id_orig)
+{
+ const ID_Type id_type = GS(id_orig->name);
+ return !ELEM(id_type, ID_IM);
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
new file mode 100644
index 00000000000..a2b57cb7198
--- /dev/null
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
@@ -0,0 +1,109 @@
+/*
+ * ***** 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) 20137Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include <stddef.h>
+
+struct EvaluationContext;
+struct ID;
+
+/* Unkomment this to have verbose log about original and CoW pointers
+ * logged, with detailed information when they are allocated, expanded
+ * and remapped.
+ */
+// #define DEG_DEBUG_COW_POINTERS
+
+#ifdef DEG_DEBUG_COW_POINTERS
+# define DEG_COW_PRINT(format, ...) printf(format, __VA_ARGS__);
+#else
+# define DEG_COW_PRINT(format, ...)
+#endif
+
+namespace DEG {
+
+struct Depsgraph;
+struct DepsgraphNodeBuilder;
+struct IDDepsNode;
+
+/* Get fully expanded (ready for use) copy-on-write datablock for the given
+ * original datablock.
+ */
+ID *deg_expand_copy_on_write_datablock(const struct Depsgraph *depsgraph,
+ const IDDepsNode *id_node,
+ DepsgraphNodeBuilder *node_builder = NULL,
+ bool create_placeholders = false);
+ID *deg_expand_copy_on_write_datablock(const struct Depsgraph *depsgraph,
+ struct ID *id_orig,
+ DepsgraphNodeBuilder *node_builder = NULL,
+ bool create_placeholders = false);
+
+/* Makes sure given CoW datablock is brought back to state of the original
+ * datablock.
+ */
+ID *deg_update_copy_on_write_datablock(const struct Depsgraph *depsgraph,
+ const IDDepsNode *id_node);
+ID *deg_update_copy_on_write_datablock(const struct Depsgraph *depsgraph,
+ struct ID *id_orig);
+
+/* Helper function which frees memory used by copy-on-written databnlock. */
+void deg_free_copy_on_write_datablock(struct ID *id_cow);
+
+/* Callback function for depsgraph operation node which ensures copy-on-write
+ * datablock is ready for use by further evaluation routines.
+ */
+void deg_evaluate_copy_on_write(const struct EvaluationContext *eval_ctx,
+ const struct Depsgraph *depsgraph,
+ const struct IDDepsNode *id_node);
+
+/* Check that given ID is propely expanded and does not have any shallow
+ * copies inside.
+ */
+bool deg_validate_copy_on_write_datablock(ID *id_cow);
+
+/* Tag given ID block as being copy-on-wtritten. */
+void deg_tag_copy_on_write_id(struct ID *id_cow, const struct ID *id_orig);
+
+/* Check whether ID datablock is expanded.
+ *
+ * TODO(sergey): Make it an inline function or a macro.
+ */
+bool deg_copy_on_write_is_expanded(const struct ID *id_cow);
+
+/* Check whether copy-on-write datablock is needed for given ID.
+ *
+ * There are some exceptions on datablocks which are covered by dependency graph
+ * but which we don't want to start duplicating.
+ *
+ * This includes images.
+ */
+bool deg_copy_on_write_is_needed(const ID *id_orig);
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index dcd9a17761d..a30812c692f 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -50,200 +50,219 @@ extern "C" {
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_intern.h"
+#include "intern/eval/deg_eval_copy_on_write.h"
#include "util/deg_util_foreach.h"
namespace DEG {
enum {
+ ID_STATE_NONE = 0,
+ ID_STATE_MODIFIED = 1,
+};
+
+enum {
COMPONENT_STATE_NONE = 0,
COMPONENT_STATE_SCHEDULED = 1,
COMPONENT_STATE_DONE = 2,
};
+typedef std::deque<OperationDepsNode *> FlushQueue;
+
namespace {
-// TODO(sergey): De-duplicate with depsgraph_tag,cc
-void lib_id_recalc_tag(Main *bmain, ID *id)
+void flush_init_operation_node_func(void *data_v, int i)
{
- id->tag |= LIB_TAG_ID_RECALC;
- DEG_id_type_tag(bmain, GS(id->name));
+ Depsgraph *graph = (Depsgraph *)data_v;
+ OperationDepsNode *node = graph->operations[i];
+ node->scheduled = false;
}
-void lib_id_recalc_data_tag(Main *bmain, ID *id)
+void flush_init_id_node_func(void *data_v, int i)
{
- id->tag |= LIB_TAG_ID_RECALC_DATA;
- DEG_id_type_tag(bmain, GS(id->name));
+ Depsgraph *graph = (Depsgraph *)data_v;
+ IDDepsNode *id_node = graph->id_nodes[i];
+ id_node->done = ID_STATE_NONE;
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
+ comp_node->done = COMPONENT_STATE_NONE;
+ GHASH_FOREACH_END();
}
-} /* namespace */
+BLI_INLINE void flush_prepare(Depsgraph *graph)
+{
+ const int num_operations = graph->operations.size();
+ BLI_task_parallel_range(0, num_operations,
+ graph,
+ flush_init_operation_node_func,
+ (num_operations > 256));
+ const int num_id_nodes = graph->id_nodes.size();
+ BLI_task_parallel_range(0, num_id_nodes,
+ graph,
+ flush_init_id_node_func,
+ (num_id_nodes > 256));
+}
-typedef std::deque<OperationDepsNode *> FlushQueue;
+BLI_INLINE void flush_schedule_entrypoints(Depsgraph *graph, FlushQueue *queue)
+{
+ GSET_FOREACH_BEGIN(OperationDepsNode *, op_node, graph->entry_tags)
+ {
+ queue->push_back(op_node);
+ op_node->scheduled = true;
+ }
+ GSET_FOREACH_END();
+}
-static void flush_init_func(void *data_v, int i)
+BLI_INLINE void flush_handle_id_node(IDDepsNode *id_node)
{
- /* ID node's done flag is used to avoid multiple editors update
- * for the same ID.
+ id_node->done = ID_STATE_MODIFIED;
+}
+
+/* TODO(sergey): We can reduce number of arguments here. */
+BLI_INLINE void flush_handle_component_node(Depsgraph *graph,
+ IDDepsNode *id_node,
+ ComponentDepsNode *comp_node,
+ bool use_copy_on_write,
+ FlushQueue *queue)
+{
+ /* We only handle component once. */
+ if (comp_node->done == COMPONENT_STATE_DONE) {
+ return;
+ }
+ comp_node->done = COMPONENT_STATE_DONE;
+ /* Currently this is needed to get object->mesh to be replaced with
+ * original mesh (rather than being evaluated_mesh).
+ *
+ * TODO(sergey): This is something we need to avoid.
*/
- Depsgraph *graph = (Depsgraph *)data_v;
- OperationDepsNode *node = graph->operations[i];
- ComponentDepsNode *comp_node = node->owner;
- IDDepsNode *id_node = comp_node->owner;
- id_node->done = 0;
- comp_node->done = COMPONENT_STATE_NONE;
- node->scheduled = false;
+ if (use_copy_on_write && comp_node->depends_on_cow()) {
+ ComponentDepsNode *cow_comp =
+ id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE);
+ cow_comp->tag_update(graph);
+ }
+ /* Tag all required operations in component for update. */
+ foreach (OperationDepsNode *op, comp_node->operations) {
+ /* We don't want to flush tags in "upstream" direction for
+ * certain types of operations.
+ *
+ * TODO(sergey): Need a more generic solution for this.
+ */
+ if (op->opcode == DEG_OPCODE_PARTICLE_SETTINGS_EVAL) {
+ continue;
+ }
+ op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+ }
+ /* When some target changes bone, we might need to re-run the
+ * whole IK solver, otherwise result might be unpredictable.
+ */
+ if (comp_node->type == DEG_NODE_TYPE_BONE) {
+ ComponentDepsNode *pose_comp =
+ id_node->find_component(DEG_NODE_TYPE_EVAL_POSE);
+ BLI_assert(pose_comp != NULL);
+ if (pose_comp->done == COMPONENT_STATE_NONE) {
+ queue->push_front(pose_comp->get_entry_operation());
+ pose_comp->done = COMPONENT_STATE_SCHEDULED;
+ }
+ }
+}
+
+/* Schedule children of the given operation node for traversal.
+ *
+ * One of the children will by-pass the queue and will be returned as a function
+ * return value, so it can start being handled right away, without building too
+ * much of a queue.
+ */
+BLI_INLINE OperationDepsNode *flush_schedule_children(
+ OperationDepsNode *op_node,
+ FlushQueue *queue)
+{
+ OperationDepsNode *result = NULL;
+ foreach (DepsRelation *rel, op_node->outlinks) {
+ OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
+ if (to_node->scheduled == false) {
+ if (result != NULL) {
+ queue->push_front(to_node);
+ }
+ else {
+ result = to_node;
+ }
+ to_node->scheduled = true;
+ }
+ }
+ return result;
}
+BLI_INLINE void flush_editors_id_update(Main *bmain,
+ Depsgraph *graph,
+ const DEGEditorUpdateContext *update_ctx)
+{
+ foreach (IDDepsNode *id_node, graph->id_nodes) {
+ if (id_node->done != ID_STATE_MODIFIED) {
+ continue;
+ }
+ /* TODO(sergey): Do we need to pass original or evaluated ID here? */
+ ID *id_orig = id_node->id_orig;
+ ID *id_cow = id_node->id_cow;
+ /* Copy tag from original data to CoW storage.
+ * This is because DEG_id_tag_update() sets tags on original
+ * data.
+ */
+ id_cow->tag |= (id_orig->tag & LIB_TAG_ID_RECALC_ALL);
+ if (deg_copy_on_write_is_expanded(id_cow)) {
+ deg_editors_id_update(update_ctx, id_cow);
+ }
+ lib_id_recalc_tag(bmain, id_orig);
+ /* TODO(sergey): For until we've got proper data nodes in the graph. */
+ lib_id_recalc_data_tag(bmain, id_orig);
+ }
+}
+
+} // namespace
+
/* Flush updates from tagged nodes outwards until all affected nodes
* are tagged.
*/
void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
{
- /* Sanity check. */
- if (graph == NULL) {
- return;
- }
-
+ const bool use_copy_on_write = DEG_depsgraph_use_copy_on_write();
+ /* Sanity checks. */
+ BLI_assert(bmain != NULL);
+ BLI_assert(graph != NULL);
/* Nothing to update, early out. */
if (BLI_gset_size(graph->entry_tags) == 0) {
return;
}
-
- /* TODO(sergey): With a bit of flag magic we can get rid of this
- * extra loop.
- */
- const int num_operations = graph->operations.size();
- const bool do_threads = num_operations > 256;
- BLI_task_parallel_range(0,
- num_operations,
- graph,
- flush_init_func,
- do_threads);
-
+ /* Reset all flags, get ready for the flush. */
+ flush_prepare(graph);
+ /* Starting from the tagged "entry" nodes, flush outwards. */
FlushQueue queue;
- /* Starting from the tagged "entry" nodes, flush outwards... */
- /* NOTE: Also need to ensure that for each of these, there is a path back to
- * root, or else they won't be done.
- * NOTE: Count how many nodes we need to handle - entry nodes may be
- * component nodes which don't count for this purpose!
- */
- GSET_FOREACH_BEGIN(OperationDepsNode *, node, graph->entry_tags)
- {
- queue.push_back(node);
- node->scheduled = true;
- }
- GSET_FOREACH_END();
-
- int num_flushed_objects = 0;
+ flush_schedule_entrypoints(graph, &queue);
+ /* Prepare update context for editors. */
+ DEGEditorUpdateContext update_ctx = {
+ bmain,
+ graph->scene,
+ graph->view_layer,
+ };
+ /* Do actual flush. */
while (!queue.empty()) {
- OperationDepsNode *node = queue.front();
+ OperationDepsNode *op_node = queue.front();
queue.pop_front();
-
- for (;;) {
- node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
-
- ComponentDepsNode *comp_node = node->owner;
+ while (op_node != NULL) {
+ /* Tag operation as required for update. */
+ op_node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+ /* Inform corresponding ID and component nodes about the change. */
+ ComponentDepsNode *comp_node = op_node->owner;
IDDepsNode *id_node = comp_node->owner;
-
- ID *id = id_node->id;
- if (id_node->done == 0) {
- deg_editors_id_update(bmain, id);
- lib_id_recalc_tag(bmain, id);
- /* TODO(sergey): For until we've got proper data nodes in the graph. */
- lib_id_recalc_data_tag(bmain, id);
- }
-
- if (comp_node->done != COMPONENT_STATE_DONE) {
- Object *object = NULL;
- if (GS(id->name) == ID_OB) {
- object = (Object *)id;
- if (id_node->done == 0) {
- ++num_flushed_objects;
- }
- }
- foreach (OperationDepsNode *op, comp_node->operations) {
- op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
- }
- if (object != NULL) {
- /* This code is used to preserve those areas which does
- * direct object update,
- *
- * Plus it ensures visibility changes and relations and
- * layers visibility update has proper flags to work with.
- */
- switch (comp_node->type) {
- case DEG_NODE_TYPE_UNDEFINED:
- case DEG_NODE_TYPE_OPERATION:
- case DEG_NODE_TYPE_TIMESOURCE:
- case DEG_NODE_TYPE_ID_REF:
- case DEG_NODE_TYPE_SEQUENCER:
- /* Ignore, does not translate to object component. */
- BLI_assert(!"This should never happen!");
- break;
- case DEG_NODE_TYPE_ANIMATION:
- object->recalc |= OB_RECALC_TIME;
- break;
- case DEG_NODE_TYPE_TRANSFORM:
- object->recalc |= OB_RECALC_OB;
- break;
- case DEG_NODE_TYPE_GEOMETRY:
- case DEG_NODE_TYPE_EVAL_POSE:
- case DEG_NODE_TYPE_BONE:
- case DEG_NODE_TYPE_EVAL_PARTICLES:
- case DEG_NODE_TYPE_SHADING:
- case DEG_NODE_TYPE_CACHE:
- case DEG_NODE_TYPE_PROXY:
- object->recalc |= OB_RECALC_DATA;
- break;
- case DEG_NODE_TYPE_PARAMETERS:
- break;
- }
- }
- /* When some target changes bone, we might need to re-run the
- * whole IK solver, otherwise result might be unpredictable.
- */
- if (comp_node->type == DEG_NODE_TYPE_BONE) {
- ComponentDepsNode *pose_comp =
- id_node->find_component(DEG_NODE_TYPE_EVAL_POSE);
- BLI_assert(pose_comp != NULL);
- if (pose_comp->done == COMPONENT_STATE_NONE) {
- queue.push_front(pose_comp->get_entry_operation());
- pose_comp->done = COMPONENT_STATE_SCHEDULED;
- }
- }
- }
-
- id_node->done = 1;
- comp_node->done = COMPONENT_STATE_DONE;
-
- /* Flush to nodes along links... */
- /* TODO(sergey): This is mainly giving speedup due ot less queue pushes, which
- * reduces number of memory allocations.
- *
- * We should try solve the allocation issue instead of doing crazy things here.
- */
- if (node->outlinks.size() == 1) {
- OperationDepsNode *to_node = (OperationDepsNode *)node->outlinks[0]->to;
- if (to_node->scheduled == false) {
- to_node->scheduled = true;
- node = to_node;
- }
- else {
- break;
- }
- }
- else {
- foreach (DepsRelation *rel, node->outlinks) {
- OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
- if (to_node->scheduled == false) {
- queue.push_front(to_node);
- to_node->scheduled = true;
- }
- }
- break;
- }
+ flush_handle_id_node(id_node);
+ flush_handle_component_node(graph,
+ id_node,
+ comp_node,
+ use_copy_on_write,
+ &queue);
+ /* Flush to nodes along links. */
+ op_node = flush_schedule_children(op_node, &queue);
}
}
- DEG_DEBUG_PRINTF("Update flushed to %d objects\n", num_flushed_objects);
+ /* Inform editors about all changes. */
+ flush_editors_id_update(bmain, graph, &update_ctx);
}
static void graph_clear_func(void *data_v, int i)
diff --git a/source/blender/depsgraph/intern/nodes/deg_node.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc
index a15317586c1..5f83d02082b 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node.cc
@@ -39,16 +39,20 @@
extern "C" {
#include "DNA_ID.h"
#include "DNA_anim_types.h"
+#include "DNA_object_types.h"
#include "BKE_animsys.h"
+#include "BKE_library.h"
}
#include "DEG_depsgraph.h"
+#include "intern/eval/deg_eval_copy_on_write.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
+#include "util/deg_util_function.h"
namespace DEG {
@@ -124,8 +128,8 @@ IDDepsNode::ComponentIDKey::ComponentIDKey(eDepsNode_Type type,
bool IDDepsNode::ComponentIDKey::operator== (const ComponentIDKey &other) const
{
- return type == other.type &&
- STREQ(name, other.name);
+ return type == other.type &&
+ STREQ(name, other.name);
}
static unsigned int id_deps_node_hash_key(const void *key_v)
@@ -161,33 +165,77 @@ static void id_deps_node_hash_value_free(void *value_v)
/* Initialize 'id' node - from pointer data given. */
void IDDepsNode::init(const ID *id, const char *UNUSED(subdata))
{
- /* Store ID-pointer. */
BLI_assert(id != NULL);
- this->id = (ID *)id;
- this->layers = (1 << 20) - 1;
- this->eval_flags = 0;
-
- /* For object we initialize layers to layer from base. */
- if (GS(id->name) == ID_OB) {
- this->layers = 0;
- }
+ /* Store ID-pointer. */
+ id_orig = (ID *)id;
+ eval_flags = 0;
+ linked_state = DEG_ID_LINKED_INDIRECTLY;
components = BLI_ghash_new(id_deps_node_hash_key,
id_deps_node_hash_key_cmp,
"Depsgraph id components hash");
+}
- /* NOTE: components themselves are created if/when needed.
- * This prevents problems with components getting added
- * twice if an ID-Ref needs to be created to house it...
+void IDDepsNode::init_copy_on_write(ID *id_cow_hint)
+{
+ /* Early output for non-copy-on-write case: we keep CoW pointer same as
+ * an original one.
*/
+ if (!DEG_depsgraph_use_copy_on_write()) {
+ UNUSED_VARS(id_cow_hint);
+ id_cow = id_orig;
+ return;
+ }
+ /* Create pointer as early as possible, so we can use it for function
+ * bindings. Rest of data we'll be copying to the new datablock when
+ * it is actually needed.
+ */
+ if (id_cow_hint != NULL) {
+ // BLI_assert(deg_copy_on_write_is_needed(id_orig));
+ if (deg_copy_on_write_is_needed(id_orig)) {
+ id_cow = id_cow_hint;
+ }
+ else {
+ id_cow = id_orig;
+ }
+ }
+ else if (deg_copy_on_write_is_needed(id_orig)) {
+ id_cow = (ID *)BKE_libblock_alloc_notest(GS(id_orig->name));
+ DEG_COW_PRINT("Create shallow copy for %s: id_orig=%p id_cow=%p\n",
+ id_orig->name, id_orig, id_cow);
+ deg_tag_copy_on_write_id(id_cow, id_orig);
+ }
+ else {
+ id_cow = id_orig;
+ }
}
/* Free 'id' node. */
IDDepsNode::~IDDepsNode()
{
+ destroy();
+}
+
+void IDDepsNode::destroy()
+{
+ if (id_orig == NULL) {
+ return;
+ }
+
BLI_ghash_free(components,
id_deps_node_hash_key_free,
id_deps_node_hash_value_free);
+
+ /* Free memory used by this CoW ID. */
+ if (id_cow != id_orig && id_cow != NULL) {
+ deg_free_copy_on_write_datablock(id_cow);
+ MEM_freeN(id_cow);
+ DEG_COW_PRINT("Destroy CoW for %s: id_orig=%p id_cow=%p\n",
+ id_orig->name, id_orig, id_cow);
+ }
+
+ /* Tag that the node is freed. */
+ id_orig = NULL;
}
ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type,
@@ -203,7 +251,7 @@ ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
ComponentDepsNode *comp_node = find_component(type, name);
if (!comp_node) {
DepsNodeFactory *factory = deg_get_node_factory(type);
- comp_node = (ComponentDepsNode *)factory->create_node(this->id, "", name);
+ comp_node = (ComponentDepsNode *)factory->create_node(this->id_orig, "", name);
/* Register. */
ComponentIDKey *key = OBJECT_GUARDED_NEW(ComponentIDKey, type, name);
@@ -217,15 +265,35 @@ void IDDepsNode::tag_update(Depsgraph *graph)
{
GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
{
- /* TODO(sergey): What about drievrs? */
+ /* TODO(sergey): What about drivers? */
bool do_component_tag = comp_node->type != DEG_NODE_TYPE_ANIMATION;
if (comp_node->type == DEG_NODE_TYPE_ANIMATION) {
- AnimData *adt = BKE_animdata_from_id(id);
+ AnimData *adt = BKE_animdata_from_id(id_orig);
/* Animation data might be null if relations are tagged for update. */
if (adt != NULL && (adt->recalc & ADT_RECALC_ANIM)) {
do_component_tag = true;
}
}
+ else if (comp_node->type == DEG_NODE_TYPE_SHADING) {
+ /* TODO(sergey): For until we properly handle granular flags for DEG_id_tag_update()
+ * we skip flushing here to keep Luca happy.
+ */
+ if (GS(id_orig->name) != ID_MA &&
+ GS(id_orig->name) != ID_WO)
+ {
+ do_component_tag = false;
+ }
+ }
+ else if (comp_node->type == DEG_NODE_TYPE_SHADING_PARAMETERS) {
+ do_component_tag = false;
+ }
+ else if (comp_node->type == DEG_NODE_TYPE_EVAL_PARTICLES) {
+ /* Only do explicit particle settings tagging. */
+ do_component_tag = false;
+ }
+ else if (comp_node->type == DEG_NODE_TYPE_BATCH_CACHE) {
+ do_component_tag = false;
+ }
if (do_component_tag) {
comp_node->tag_update(graph);
}
@@ -233,11 +301,12 @@ void IDDepsNode::tag_update(Depsgraph *graph)
GHASH_FOREACH_END();
}
-void IDDepsNode::finalize_build()
+void IDDepsNode::finalize_build(Depsgraph *graph)
{
+ /* Finalize build of all components. */
GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
{
- comp_node->finalize_build();
+ comp_node->finalize_build(graph);
}
GHASH_FOREACH_END();
}
diff --git a/source/blender/depsgraph/intern/nodes/deg_node.h b/source/blender/depsgraph/intern/nodes/deg_node.h
index 9f1b61faf24..fd3ed694c9c 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node.h
@@ -138,7 +138,9 @@ struct IDDepsNode : public DepsNode {
};
void init(const ID *id, const char *subdata);
+ void init_copy_on_write(ID *id_cow_hint = NULL);
~IDDepsNode();
+ void destroy();
ComponentDepsNode *find_component(eDepsNode_Type type,
const char *name = "") const;
@@ -147,23 +149,23 @@ struct IDDepsNode : public DepsNode {
void tag_update(Depsgraph *graph);
- void finalize_build();
+ void finalize_build(Depsgraph *graph);
/* ID Block referenced. */
- ID *id;
+ ID *id_orig;
+ ID *id_cow;
/* Hash to make it faster to look up components. */
GHash *components;
- /* Layers of this node with accumulated layers of it's output relations. */
- unsigned int layers;
-
/* Additional flags needed for scene evaluation.
* TODO(sergey): Only needed for until really granular updates
* of all the entities.
*/
int eval_flags;
+ eDepsNode_LinkedState_Type linked_state;
+
DEG_DEPSNODE_DECLARE;
};
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
index 010f12409b4..01181453982 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
@@ -123,8 +123,7 @@ static void comp_node_hash_value_free(void *value_v)
ComponentDepsNode::ComponentDepsNode() :
entry_operation(NULL),
- exit_operation(NULL),
- layers(0)
+ exit_operation(NULL)
{
operations_map = BLI_ghash_new(comp_node_hash_key,
comp_node_hash_key_cmp,
@@ -157,15 +156,12 @@ string ComponentDepsNode::identifier() const
char typebuf[16];
sprintf(typebuf, "(%d)", type);
- char layers[16];
- sprintf(layers, "%u", this->layers);
-
- return string(typebuf) + name + " : " + idname + " (Layers: " + layers + ")";
+ return string(typebuf) + name + " : " + idname;
}
OperationDepsNode *ComponentDepsNode::find_operation(OperationIDKey key) const
{
- OperationDepsNode *node;
+ OperationDepsNode *node = NULL;
if (operations_map != NULL) {
node = (OperationDepsNode *)BLI_ghash_lookup(operations_map, &key);
}
@@ -232,7 +228,7 @@ OperationDepsNode *ComponentDepsNode::add_operation(const DepsEvalOperationCb& o
OperationDepsNode *op_node = find_operation(opcode, name, name_tag);
if (!op_node) {
DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_OPERATION);
- op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name);
+ op_node = (OperationDepsNode *)factory->create_node(this->owner->id_orig, "", name);
/* register opnode in this component's operation set */
OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag);
@@ -345,7 +341,7 @@ OperationDepsNode *ComponentDepsNode::get_exit_operation()
return NULL;
}
-void ComponentDepsNode::finalize_build()
+void ComponentDepsNode::finalize_build(Depsgraph * /*graph*/)
{
operations.reserve(BLI_ghash_size(operations_map));
GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, operations_map)
@@ -369,14 +365,18 @@ static DepsNodeFactoryImpl<name ## ComponentDepsNode> DNTI_ ## NAME
DEG_COMPONENT_DEFINE(Animation, ANIMATION);
+DEG_COMPONENT_DEFINE(BatchCache, BATCH_CACHE);
DEG_COMPONENT_DEFINE(Cache, CACHE);
+DEG_COMPONENT_DEFINE(CopyOnWrite, COPY_ON_WRITE);
DEG_COMPONENT_DEFINE(Geometry, GEOMETRY);
+DEG_COMPONENT_DEFINE(LayerCollections, LAYER_COLLECTIONS);
DEG_COMPONENT_DEFINE(Parameters, PARAMETERS);
DEG_COMPONENT_DEFINE(Particles, EVAL_PARTICLES);
DEG_COMPONENT_DEFINE(Proxy, PROXY);
DEG_COMPONENT_DEFINE(Pose, EVAL_POSE);
DEG_COMPONENT_DEFINE(Sequencer, SEQUENCER);
DEG_COMPONENT_DEFINE(Shading, SHADING);
+DEG_COMPONENT_DEFINE(ShadingParameters, SHADING_PARAMETERS);
DEG_COMPONENT_DEFINE(Transform, TRANSFORM);
/* Bone Component ========================================= */
@@ -404,20 +404,21 @@ DEG_COMPONENT_DEFINE(Bone, BONE);
void deg_register_component_depsnodes()
{
- deg_register_node_typeinfo(&DNTI_PARAMETERS);
- deg_register_node_typeinfo(&DNTI_PROXY);
deg_register_node_typeinfo(&DNTI_ANIMATION);
- deg_register_node_typeinfo(&DNTI_TRANSFORM);
- deg_register_node_typeinfo(&DNTI_GEOMETRY);
- deg_register_node_typeinfo(&DNTI_SEQUENCER);
-
- deg_register_node_typeinfo(&DNTI_EVAL_POSE);
deg_register_node_typeinfo(&DNTI_BONE);
-
+ deg_register_node_typeinfo(&DNTI_CACHE);
+ deg_register_node_typeinfo(&DNTI_BATCH_CACHE);
+ deg_register_node_typeinfo(&DNTI_COPY_ON_WRITE);
+ deg_register_node_typeinfo(&DNTI_GEOMETRY);
+ deg_register_node_typeinfo(&DNTI_LAYER_COLLECTIONS);
+ deg_register_node_typeinfo(&DNTI_PARAMETERS);
deg_register_node_typeinfo(&DNTI_EVAL_PARTICLES);
+ deg_register_node_typeinfo(&DNTI_PROXY);
+ deg_register_node_typeinfo(&DNTI_EVAL_POSE);
+ deg_register_node_typeinfo(&DNTI_SEQUENCER);
deg_register_node_typeinfo(&DNTI_SHADING);
-
- deg_register_node_typeinfo(&DNTI_CACHE);
+ deg_register_node_typeinfo(&DNTI_SHADING_PARAMETERS);
+ deg_register_node_typeinfo(&DNTI_TRANSFORM);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h
index 1c21a71737f..ba4f8551fea 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h
@@ -139,7 +139,7 @@ struct ComponentDepsNode : public DepsNode {
OperationDepsNode *get_entry_operation();
OperationDepsNode *get_exit_operation();
- void finalize_build();
+ void finalize_build(Depsgraph *graph);
IDDepsNode *owner;
@@ -159,9 +159,7 @@ struct ComponentDepsNode : public DepsNode {
OperationDepsNode *exit_operation;
// XXX: a poll() callback to check if component's first node can be started?
-
- /* Temporary bitmask, used during graph construction. */
- unsigned int layers;
+ virtual bool depends_on_cow() { return true; }
};
/* ---------------------------------------- */
@@ -172,14 +170,18 @@ struct ComponentDepsNode : public DepsNode {
}
DEG_COMPONENT_DECLARE_GENERIC(Animation);
+DEG_COMPONENT_DECLARE_GENERIC(BatchCache);
DEG_COMPONENT_DECLARE_GENERIC(Cache);
+DEG_COMPONENT_DECLARE_GENERIC(CopyOnWrite);
DEG_COMPONENT_DECLARE_GENERIC(Geometry);
+DEG_COMPONENT_DECLARE_GENERIC(LayerCollections);
DEG_COMPONENT_DECLARE_GENERIC(Parameters);
DEG_COMPONENT_DECLARE_GENERIC(Particles);
DEG_COMPONENT_DECLARE_GENERIC(Proxy);
DEG_COMPONENT_DECLARE_GENERIC(Pose);
DEG_COMPONENT_DECLARE_GENERIC(Sequencer);
DEG_COMPONENT_DECLARE_GENERIC(Shading);
+DEG_COMPONENT_DECLARE_GENERIC(ShadingParameters);
DEG_COMPONENT_DECLARE_GENERIC(Transform);
/* Bone Component */
diff --git a/source/blender/depsgraph/util/deg_util_foreach.h b/source/blender/depsgraph/util/deg_util_foreach.h
index cb7361fc708..e00aa5dbb5e 100644
--- a/source/blender/depsgraph/util/deg_util_foreach.h
+++ b/source/blender/depsgraph/util/deg_util_foreach.h
@@ -36,13 +36,5 @@
# include <boost/foreach.hpp>
# define foreach BOOST_FOREACH
#else
-#pragma message("No available foreach() implementation. Using stub instead, disabling new depsgraph")
-
-#ifndef WITH_LEGACY_DEPSGRAPH
-# error "Unable to build new depsgraph and legacy one is disabled."
-#endif
-
-#define DISABLE_NEW_DEPSGRAPH
-
-# define foreach(x, y) for (x; false; (void)y)
+# error "Depsgraph requires either Boost or C++11 for range-based loops."
#endif
diff --git a/source/blender/depsgraph/util/deg_util_function.h b/source/blender/depsgraph/util/deg_util_function.h
index 1e34ae04d9a..da31bb037f9 100644
--- a/source/blender/depsgraph/util/deg_util_function.h
+++ b/source/blender/depsgraph/util/deg_util_function.h
@@ -47,64 +47,5 @@ using boost::function;
#define function_bind boost::bind
#else
-
-#pragma message("No available function binding implementation. Using stub instead, disabling new depsgraph")
-
-#ifndef WITH_LEGACY_DEPSGRAPH
-# error "Unable to build new depsgraph and legacy one is disabled."
-#endif
-
-#define DISABLE_NEW_DEPSGRAPH
-
-#include "BLI_utildefines.h"
-#include <cstdlib>
-
-template<typename T>
-class function {
-public:
- function() {};
- function(void *) {}
- operator bool() const { return false; }
- bool operator== (void *) { return false; }
-
- template<typename T1>
- void operator() (T1) {
- BLI_assert(!"Should not be used");
- }
-};
-
-class Wrap {
-public:
- Wrap() {}
- template <typename T>
- Wrap(T /*arg*/) {}
-};
-
-template <typename T>
-void *function_bind(T func,
- Wrap arg1 = Wrap(),
- Wrap arg2 = Wrap(),
- Wrap arg3 = Wrap(),
- Wrap arg4 = Wrap(),
- Wrap arg5 = Wrap(),
- Wrap arg6 = Wrap(),
- Wrap arg7 = Wrap())
-{
- BLI_assert(!"Should not be used");
- (void)func;
- (void)arg1;
- (void)arg2;
- (void)arg3;
- (void)arg4;
- (void)arg5;
- (void)arg6;
- (void)arg7;
- return NULL;
-}
-
-#define _1 Wrap()
-#define _2 Wrap()
-#define _3 Wrap()
-#define _4 Wrap()
-
+# error "Depsgraph requires either Boost or C++11 for function bindings."
#endif
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
new file mode 100644
index 00000000000..8339b6b8720
--- /dev/null
+++ b/source/blender/draw/CMakeLists.txt
@@ -0,0 +1,231 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2016, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Blender Institute
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ intern
+ modes
+
+ ../blenfont
+ ../blenkernel
+ ../blenlib
+ ../blentranslation
+ ../bmesh
+ ../depsgraph
+ ../editors/include
+ ../editors/space_view3d
+ ../gpu
+ ../imbuf
+ ../makesdna
+ ../makesrna
+ ../render/extern/include
+ ../render/intern/include
+ ../windowmanager
+
+ ../../../intern/glew-mx
+ ../../../intern/guardedalloc
+)
+
+set(INC_SYS
+ ${GLEW_INCLUDE_PATH}
+)
+
+set(SRC
+ intern/draw_armature.c
+ intern/draw_cache.c
+ intern/draw_cache_impl_curve.c
+ intern/draw_cache_impl_displist.c
+ intern/draw_cache_impl_lattice.c
+ intern/draw_cache_impl_mesh.c
+ intern/draw_cache_impl_metaball.c
+ intern/draw_cache_impl_particles.c
+ intern/draw_common.c
+ intern/draw_manager.c
+ intern/draw_manager_text.c
+ intern/draw_manager_profiling.c
+ intern/draw_view.c
+ modes/edit_armature_mode.c
+ modes/edit_curve_mode.c
+ modes/edit_lattice_mode.c
+ modes/edit_mesh_mode.c
+ modes/edit_mesh_mode_text.c
+ modes/edit_metaball_mode.c
+ modes/edit_surface_mode.c
+ modes/edit_text_mode.c
+ modes/object_mode.c
+ modes/paint_texture_mode.c
+ modes/paint_vertex_mode.c
+ modes/paint_weight_mode.c
+ modes/particle_mode.c
+ modes/pose_mode.c
+ modes/sculpt_mode.c
+ engines/basic/basic_engine.c
+ engines/clay/clay_engine.c
+ engines/eevee/eevee_bloom.c
+ engines/eevee/eevee_data.c
+ engines/eevee/eevee_depth_of_field.c
+ engines/eevee/eevee_effects.c
+ engines/eevee/eevee_engine.c
+ engines/eevee/eevee_lightprobes.c
+ engines/eevee/eevee_lights.c
+ engines/eevee/eevee_materials.c
+ engines/eevee/eevee_motion_blur.c
+ engines/eevee/eevee_occlusion.c
+ engines/eevee/eevee_screen_raytrace.c
+ engines/eevee/eevee_subsurface.c
+ engines/eevee/eevee_temporal_sampling.c
+ engines/eevee/eevee_volumes.c
+ engines/external/external_engine.c
+
+ DRW_engine.h
+ intern/DRW_render.h
+ intern/draw_cache.h
+ intern/draw_cache_impl.h
+ intern/draw_common.h
+ intern/draw_manager_text.h
+ intern/draw_manager_profiling.h
+ intern/draw_view.h
+ modes/draw_mode_engines.h
+ modes/edit_mesh_mode_intern.h
+ engines/basic/basic_engine.h
+ engines/clay/clay_engine.h
+ engines/eevee/eevee_engine.h
+ engines/eevee/eevee_lut.h
+ engines/eevee/eevee_private.h
+ engines/external/external_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/clay_particle_vert.glsl SRC)
+data_to_c_simple(engines/clay/shaders/clay_particle_strand_frag.glsl SRC)
+data_to_c_simple(engines/clay/shaders/ssao_alchemy.glsl SRC)
+data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC)
+
+data_to_c_simple(engines/eevee/shaders/ambient_occlusion_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/default_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/default_world_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/background_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/concentric_samples_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lamps_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_geom.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_cube_display_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_cube_display_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_grid_display_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_grid_display_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_grid_fill_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_planar_display_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_planar_display_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lit_surface_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lit_surface_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_bloom_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_dof_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_dof_geom.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_dof_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_downsample_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_downsample_cube_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_gtao_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_minmaxz_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_motion_blur_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_ssr_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_subsurface_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/effect_temporal_aa.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/prepass_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/prepass_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/shadow_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/shadow_geom.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/shadow_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/shadow_store_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/shadow_copy_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/bsdf_lut_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/btdf_lut_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/bsdf_direct_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/bsdf_common_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/irradiance_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/octahedron_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/bsdf_sampling_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/raytrace_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/ssr_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/volumetric_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/volumetric_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/volumetric_geom.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/volumetric_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/volumetric_resolve_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/volumetric_scatter_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/volumetric_integration_frag.glsl SRC)
+
+data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
+data_to_c_simple(modes/shaders/common_fxaa_lib.glsl SRC)
+data_to_c_simple(modes/shaders/edit_mesh_overlay_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_mesh_overlay_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_mesh_overlay_geom_tri.glsl SRC)
+data_to_c_simple(modes/shaders/edit_mesh_overlay_geom_edge.glsl SRC)
+data_to_c_simple(modes/shaders/edit_mesh_overlay_loosevert_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_mesh_overlay_facedot_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_mesh_overlay_facedot_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_mesh_overlay_mix_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_curve_overlay_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_curve_overlay_loosevert_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_lattice_overlay_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_lattice_overlay_loosevert_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_normals_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_normals_geom.glsl SRC)
+data_to_c_simple(modes/shaders/object_empty_image_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_empty_image_vert.glsl SRC)
+data_to_c_simple(modes/shaders/object_outline_resolve_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_outline_expand_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_outline_detect_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_grid_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_grid_vert.glsl SRC)
+data_to_c_simple(modes/shaders/object_lightprobe_grid_vert.glsl SRC)
+data_to_c_simple(modes/shaders/object_particle_prim_vert.glsl SRC)
+data_to_c_simple(modes/shaders/object_particle_prim_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_particle_dot_vert.glsl SRC)
+data_to_c_simple(modes/shaders/object_particle_dot_frag.glsl SRC)
+data_to_c_simple(modes/shaders/paint_texture_frag.glsl SRC)
+data_to_c_simple(modes/shaders/paint_texture_vert.glsl SRC)
+data_to_c_simple(modes/shaders/paint_wire_frag.glsl SRC)
+data_to_c_simple(modes/shaders/paint_wire_vert.glsl SRC)
+data_to_c_simple(modes/shaders/paint_vert_frag.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..ba0f8681f10
--- /dev/null
+++ b/source/blender/draw/DRW_engine.h
@@ -0,0 +1,117 @@
+/*
+ * 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__
+
+struct ARegion;
+struct CollectionEngineSettings;
+struct Depsgraph;
+struct DRWPass;
+struct Main;
+struct Material;
+struct Scene;
+struct DrawEngineType;
+struct ID;
+struct IDProperty;
+struct bContext;
+struct Object;
+struct ViewLayer;
+struct ViewContext;
+struct ViewportEngineData;
+struct View3D;
+struct rcti;
+struct GPUOffScreen;
+struct RenderEngineType;
+struct WorkSpace;
+
+#include "BLI_sys_types.h" /* for bool */
+
+/* Buffer and textures used by the viewport by default */
+typedef struct DefaultFramebufferList {
+ struct GPUFrameBuffer *default_fb;
+ struct GPUFrameBuffer *multisample_fb;
+} DefaultFramebufferList;
+
+typedef struct DefaultTextureList {
+ struct GPUTexture *color;
+ struct GPUTexture *depth;
+ struct GPUTexture *multisample_color;
+ struct GPUTexture *multisample_depth;
+} DefaultTextureList;
+
+void DRW_engines_register(void);
+void DRW_engines_free(void);
+
+void DRW_engine_register(struct DrawEngineType *draw_engine_type);
+void DRW_engine_viewport_data_size_get(
+ const void *engine_type,
+ int *r_fbl_len, int *r_txl_len, int *r_psl_len, int *r_stl_len);
+
+typedef struct DRWUpdateContext {
+ struct Main *bmain;
+ struct Scene *scene;
+ struct ViewLayer *view_layer;
+ struct ARegion *ar;
+ struct View3D *v3d;
+ struct RenderEngineType *engine_type;
+} DRWUpdateContext;
+void DRW_notify_view_update(const DRWUpdateContext *update_ctx);
+void DRW_notify_id_update(const DRWUpdateContext *update_ctx, struct ID *id);
+
+void DRW_draw_view(const struct bContext *C);
+
+void DRW_draw_render_loop_ex(
+ struct Depsgraph *graph,
+ struct RenderEngineType *engine_type,
+ struct ARegion *ar, struct View3D *v3d,
+ const struct bContext *evil_C);
+void DRW_draw_render_loop(
+ struct Depsgraph *graph,
+ struct ARegion *ar, struct View3D *v3d);
+void DRW_draw_render_loop_offscreen(
+ struct Depsgraph *graph,
+ struct RenderEngineType *engine_type,
+ struct ARegion *ar, struct View3D *v3d,
+ struct GPUOffScreen *ofs);
+void DRW_draw_select_loop(
+ struct Depsgraph *graph,
+ struct ARegion *ar, struct View3D *v3d,
+ bool use_obedit_skip, bool use_nearest, const struct rcti *rect);
+void DRW_draw_depth_loop(
+ struct Depsgraph *graph,
+ struct ARegion *ar, struct View3D *v3d);
+
+/* This is here because GPUViewport needs it */
+void DRW_pass_free(struct DRWPass *pass);
+
+/* Mode engines initialization */
+void OBJECT_collection_settings_create(struct IDProperty *properties);
+void EDIT_MESH_collection_settings_create(struct IDProperty *properties);
+void EDIT_ARMATURE_collection_settings_create(struct IDProperty *properties);
+void PAINT_WEIGHT_collection_settings_create(struct IDProperty *properties);
+void PAINT_VERTEX_collection_settings_create(struct IDProperty *properties);
+
+#endif /* __DRW_ENGINE_H__ */
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
new file mode 100644
index 00000000000..10dfe7b5996
--- /dev/null
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -0,0 +1,280 @@
+/*
+ * 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 basic_engine.c
+ * \ingroup draw_engine
+ *
+ * Simple engine for drawing color and/or depth.
+ * When we only need simple flat shaders.
+ */
+
+#include "DRW_render.h"
+
+#include "BKE_icons.h"
+#include "BKE_idprop.h"
+#include "BKE_main.h"
+
+#include "GPU_shader.h"
+
+#include "basic_engine.h"
+/* Shaders */
+
+#define BASIC_ENGINE "BLENDER_BASIC"
+
+/* we may want this later? */
+#define USE_DEPTH
+
+/* *********** LISTS *********** */
+
+/* GPUViewport.storage
+ * Is freed everytime the viewport engine changes */
+typedef struct BASIC_Storage {
+ int dummy;
+} BASIC_Storage;
+
+typedef struct BASIC_StorageList {
+ struct BASIC_Storage *storage;
+ struct BASIC_PrivateData *g_data;
+} BASIC_StorageList;
+
+typedef struct BASIC_FramebufferList {
+ /* default */
+ struct GPUFrameBuffer *default_fb;
+ /* engine specific */
+#ifdef USE_DEPTH
+ struct GPUFrameBuffer *dupli_depth;
+#endif
+} BASIC_FramebufferList;
+
+typedef struct BASIC_TextureList {
+ /* default */
+ struct GPUTexture *color;
+#ifdef USE_DEPTH
+ struct GPUTexture *depth;
+ /* engine specific */
+ struct GPUTexture *depth_dup;
+#endif
+} BASIC_TextureList;
+
+typedef struct BASIC_PassList {
+#ifdef USE_DEPTH
+ struct DRWPass *depth_pass;
+ struct DRWPass *depth_pass_cull;
+#endif
+ struct DRWPass *color_pass;
+} BASIC_PassList;
+
+typedef struct BASIC_Data {
+ void *engine_type;
+ BASIC_FramebufferList *fbl;
+ BASIC_TextureList *txl;
+ BASIC_PassList *psl;
+ BASIC_StorageList *stl;
+} BASIC_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+#ifdef USE_DEPTH
+ /* Depth Pre Pass */
+ struct GPUShader *depth_sh;
+#endif
+ /* Shading Pass */
+ struct GPUShader *color_sh;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct BASIC_PrivateData {
+#ifdef USE_DEPTH
+ DRWShadingGroup *depth_shgrp;
+ DRWShadingGroup *depth_shgrp_cull;
+#endif
+ DRWShadingGroup *color_shgrp;
+} BASIC_PrivateData; /* Transient data */
+
+/* Functions */
+
+static void basic_engine_init(void *vedata)
+{
+ BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
+ BASIC_TextureList *txl = ((BASIC_Data *)vedata)->txl;
+ BASIC_FramebufferList *fbl = ((BASIC_Data *)vedata)->fbl;
+
+#ifdef USE_DEPTH
+ /* Depth prepass */
+ if (!e_data.depth_sh) {
+ e_data.depth_sh = DRW_shader_create_3D_depth_only();
+ }
+#endif
+
+ /* Shading pass */
+ if (!e_data.color_sh) {
+ e_data.color_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+
+ if (!stl->storage) {
+ stl->storage = MEM_callocN(sizeof(BASIC_Storage), "BASIC_Storage");
+ }
+
+#ifdef USE_DEPTH
+ if (DRW_state_is_fbo()) {
+ const float *viewport_size = DRW_viewport_size_get();
+ DRWFboTexture tex = {&txl->depth_dup, DRW_TEX_DEPTH_24_STENCIL_8, 0};
+ DRW_framebuffer_init(&fbl->dupli_depth, &draw_engine_basic_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex, 1);
+ }
+#endif
+}
+
+static void basic_cache_init(void *vedata)
+{
+ BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
+ BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+#ifdef USE_DEPTH
+ /* Depth Pass */
+ {
+ psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
+
+ psl->depth_pass_cull = DRW_pass_create(
+ "Depth Pass Cull",
+ DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
+ stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
+ }
+#endif
+
+ /* Color Pass */
+ {
+ psl->color_pass = DRW_pass_create("Color Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+ stl->g_data->color_shgrp = DRW_shgroup_create(e_data.color_sh, psl->color_pass);
+ }
+}
+
+static void basic_cache_populate(void *vedata, Object *ob)
+{
+ BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
+
+ if (!DRW_object_is_renderable(ob))
+ return;
+
+ struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
+ if (geom) {
+ bool do_cull = false; /* TODO (we probably wan't to take this from the viewport?) */
+#ifdef USE_DEPTH
+ /* Depth Prepass */
+ DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat);
+#endif
+ /* Shading */
+ DRW_shgroup_call_add(stl->g_data->color_shgrp, geom, ob->obmat);
+ }
+}
+
+static void basic_cache_finish(void *vedata)
+{
+ BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
+
+ UNUSED_VARS(stl);
+}
+
+static void basic_draw_scene(void *vedata)
+{
+
+ BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
+ BASIC_FramebufferList *fbl = ((BASIC_Data *)vedata)->fbl;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ const bool is_select = DRW_state_is_select();
+
+ bool use_color = true;
+ bool use_depth = true;
+ bool use_depth_cull = true;
+
+ if (is_select) {
+ /* Needed for depth-picking,
+ * for other selection types there are no need for extra passes either. */
+ use_color = false;
+ use_depth_cull = false;
+ }
+
+#ifdef USE_DEPTH
+ /* Pass 1 : Depth pre-pass */
+ if (use_depth) {
+ DRW_draw_pass(psl->depth_pass);
+ }
+
+ if (use_depth_cull) {
+ DRW_draw_pass(psl->depth_pass_cull);
+ }
+
+ /* Pass 2 : Duplicate depth */
+ if (use_depth || use_depth_cull) {
+ /* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */
+ if (DRW_state_is_fbo()) {
+ DRW_framebuffer_blit(dfbl->default_fb, fbl->dupli_depth, true, false);
+ }
+ }
+#endif
+
+ /* Pass 3 : Shading */
+ if (use_color) {
+ DRW_draw_pass(psl->color_pass);
+ }
+}
+
+static void basic_engine_free(void)
+{
+ /* all shaders are builtin */
+}
+
+static const DrawEngineDataSize basic_data_size = DRW_VIEWPORT_DATA_SIZE(BASIC_Data);
+
+DrawEngineType draw_engine_basic_type = {
+ NULL, NULL,
+ N_("Basic"),
+ &basic_data_size,
+ &basic_engine_init,
+ &basic_engine_free,
+ &basic_cache_init,
+ &basic_cache_populate,
+ &basic_cache_finish,
+ NULL,
+ &basic_draw_scene,
+ NULL,
+ NULL,
+};
+
+/* Note: currently unused, we may want to register so we can see this when debugging the view. */
+
+RenderEngineType DRW_engine_viewport_basic_type = {
+ NULL, NULL,
+ BASIC_ENGINE, N_("Basic"), RE_INTERNAL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ &draw_engine_basic_type,
+ {NULL, NULL, NULL}
+};
+
+
+#undef BASIC_ENGINE
diff --git a/source/blender/draw/engines/basic/basic_engine.h b/source/blender/draw/engines/basic/basic_engine.h
new file mode 100644
index 00000000000..0adf99835a2
--- /dev/null
+++ b/source/blender/draw/engines/basic/basic_engine.h
@@ -0,0 +1,32 @@
+/*
+ * 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 basic_engine.h
+ * \ingroup draw_engine
+ */
+
+#ifndef __BASIC_ENGINE_H__
+#define __BASIC_ENGINE_H__
+
+extern DrawEngineType draw_engine_basic_type;
+extern RenderEngineType DRW_engine_viewport_basic_type;
+
+#endif /* __BASIC_ENGINE_H__ */
diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c
new file mode 100644
index 00000000000..01f89ae6b1c
--- /dev/null
+++ b/source/blender/draw/engines/clay/clay_engine.c
@@ -0,0 +1,935 @@
+/*
+ * 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 "BLI_utildefines.h"
+#include "BLI_dynstr.h"
+#include "BLI_rand.h"
+
+#include "DNA_particle_types.h"
+
+#include "BKE_icons.h"
+#include "BKE_idprop.h"
+#include "BKE_main.h"
+#include "BKE_particle.h"
+
+#include "GPU_shader.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "UI_resources.h"
+#include "UI_interface_icons.h"
+
+#include "DRW_render.h"
+
+#include "clay_engine.h"
+
+#ifdef WITH_CLAY_ENGINE
+#include "../eevee/eevee_lut.h" /* TODO find somewhere to share blue noise Table */
+
+/* Shaders */
+
+#define CLAY_ENGINE "BLENDER_CLAY"
+
+#define MAX_CLAY_MAT 512 /* 512 = 9 bit material id */
+
+#define SHADER_DEFINES \
+ "#define MAX_MATERIAL " STRINGIFY(MAX_CLAY_MAT) "\n" \
+ "#define USE_ROTATION\n" \
+ "#define USE_AO\n" \
+ "#define USE_HSV\n"
+
+extern char datatoc_clay_frag_glsl[];
+extern char datatoc_clay_vert_glsl[];
+extern char datatoc_clay_particle_vert_glsl[];
+extern char datatoc_clay_particle_strand_frag_glsl[];
+extern char datatoc_ssao_alchemy_glsl[];
+
+/* *********** LISTS *********** */
+
+/**
+ * UBOs data needs to be 16 byte aligned (size of vec4)
+ *
+ * Reminder: float, int, bool are 4 bytes
+ *
+ * \note struct is expected to be initialized with all pad-bits zero'd
+ * so we can use 'memcmp' to check for duplicates. Possibly hash data later.
+ */
+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 */
+BLI_STATIC_ASSERT_ALIGN(CLAY_UBO_Material, 16)
+
+typedef struct CLAY_HAIR_UBO_Material {
+ float hair_randomness;
+ float matcap_id;
+ float matcap_rot[2];
+ float matcap_hsv[3];
+ float pad;
+} CLAY_HAIR_UBO_Material; /* 32 bytes */
+BLI_STATIC_ASSERT_ALIGN(CLAY_HAIR_UBO_Material, 16)
+
+typedef struct CLAY_UBO_Storage {
+ CLAY_UBO_Material materials[MAX_CLAY_MAT];
+} CLAY_UBO_Storage;
+
+typedef struct CLAY_HAIR_UBO_Storage {
+ CLAY_HAIR_UBO_Material materials[MAX_CLAY_MAT];
+} CLAY_HAIR_UBO_Storage;
+
+/* GPUViewport.storage
+ * Is freed everytime the viewport engine changes */
+typedef struct CLAY_Storage {
+ /* Materials Parameter UBO */
+ CLAY_UBO_Storage mat_storage;
+ CLAY_HAIR_UBO_Storage hair_mat_storage;
+ int ubo_current_id;
+ int hair_ubo_current_id;
+ DRWShadingGroup *shgrps[MAX_CLAY_MAT];
+ DRWShadingGroup *shgrps_flat[MAX_CLAY_MAT];
+ DRWShadingGroup *hair_shgrps[MAX_CLAY_MAT];
+} CLAY_Storage;
+
+typedef struct CLAY_StorageList {
+ struct CLAY_Storage *storage;
+ struct GPUUniformBuffer *mat_ubo;
+ struct GPUUniformBuffer *hair_mat_ubo;
+ struct CLAY_PrivateData *g_data;
+} CLAY_StorageList;
+
+typedef struct CLAY_FramebufferList {
+ /* default */
+ struct GPUFrameBuffer *default_fb;
+ /* engine specific */
+ struct GPUFrameBuffer *dupli_depth;
+} CLAY_FramebufferList;
+
+typedef struct CLAY_PassList {
+ struct DRWPass *depth_pass;
+ struct DRWPass *depth_pass_cull;
+ struct DRWPass *clay_pass;
+ struct DRWPass *clay_pass_flat;
+ struct DRWPass *hair_pass;
+} CLAY_PassList;
+
+typedef struct CLAY_Data {
+ void *engine_type;
+ CLAY_FramebufferList *fbl;
+ DRWViewportEmptyList *txl;
+ CLAY_PassList *psl;
+ CLAY_StorageList *stl;
+} CLAY_Data;
+
+typedef struct CLAY_ViewLayerData {
+ struct GPUTexture *jitter_tx;
+ struct GPUUniformBuffer *sampling_ubo;
+ int cached_sample_num;
+} CLAY_ViewLayerData;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Depth Pre Pass */
+ struct GPUShader *depth_sh;
+ /* Shading Pass */
+ struct GPUShader *clay_sh;
+ struct GPUShader *clay_flat_sh;
+ struct GPUShader *hair_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];
+
+ /* Just a serie of int from 0 to MAX_CLAY_MAT-1 */
+ int ubo_mat_idxs[MAX_CLAY_MAT];
+
+ /* engine specific */
+ struct GPUTexture *depth_dup;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct CLAY_PrivateData {
+ DRWShadingGroup *depth_shgrp;
+ DRWShadingGroup *depth_shgrp_select;
+ DRWShadingGroup *depth_shgrp_active;
+ DRWShadingGroup *depth_shgrp_cull;
+ DRWShadingGroup *depth_shgrp_cull_select;
+ DRWShadingGroup *depth_shgrp_cull_active;
+} CLAY_PrivateData; /* Transient data */
+
+/* Functions */
+
+static void clay_view_layer_data_free(void *storage)
+{
+ CLAY_ViewLayerData *sldata = (CLAY_ViewLayerData *)storage;
+
+ DRW_UBO_FREE_SAFE(sldata->sampling_ubo);
+ DRW_TEXTURE_FREE_SAFE(sldata->jitter_tx);
+}
+
+static CLAY_ViewLayerData *CLAY_view_layer_data_get(void)
+{
+ CLAY_ViewLayerData **sldata = (CLAY_ViewLayerData **)DRW_view_layer_engine_data_ensure(&draw_engine_clay_type, &clay_view_layer_data_free);
+
+ if (*sldata == NULL) {
+ *sldata = MEM_callocN(sizeof(**sldata), "CLAY_ViewLayerData");
+ }
+
+ return *sldata;
+}
+
+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) {
+ e_data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0];
+ e_data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1];
+ e_data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2];
+ }
+ }
+
+ e_data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */
+ e_data.matcap_colors[layer][1] /= 16.0f * 2.0f;
+ e_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)
+{
+ switch (matcap) {
+ case ICON_MATCAP_01: return 0;
+ case ICON_MATCAP_02: return 1;
+ case ICON_MATCAP_03: return 2;
+ case ICON_MATCAP_04: return 3;
+ case ICON_MATCAP_05: return 4;
+ case ICON_MATCAP_06: return 5;
+ case ICON_MATCAP_07: return 6;
+ case ICON_MATCAP_08: return 7;
+ case ICON_MATCAP_09: return 8;
+ case ICON_MATCAP_10: return 9;
+ case ICON_MATCAP_11: return 10;
+ case ICON_MATCAP_12: return 11;
+ case ICON_MATCAP_13: return 12;
+ case ICON_MATCAP_14: return 13;
+ case ICON_MATCAP_15: return 14;
+ case ICON_MATCAP_16: return 15;
+ case ICON_MATCAP_17: return 16;
+ case ICON_MATCAP_18: return 17;
+ case ICON_MATCAP_19: return 18;
+ case ICON_MATCAP_20: return 19;
+ case ICON_MATCAP_21: return 20;
+ case ICON_MATCAP_22: return 21;
+ case ICON_MATCAP_23: return 22;
+ case ICON_MATCAP_24: return 23;
+ }
+ BLI_assert(!"Should not happen");
+ return 0;
+}
+
+/* Using Hammersley distribution */
+static float *create_disk_samples(int num_samples)
+{
+ /* vec4 to ensure memory alignment. */
+ float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * num_samples, "concentric_tex");
+ const float num_samples_inv = 1.0f / num_samples;
+
+ for (int i = 0; i < num_samples; i++) {
+ float r = (i + 0.5f) * num_samples_inv;
+ double dphi;
+ BLI_hammersley_1D(i, &dphi);
+
+ float phi = (float)dphi * 2.0f * M_PI;
+ texels[i][0] = cosf(phi);
+ texels[i][1] = sinf(phi);
+ /* This deliberatly distribute more samples
+ * at the center of the disk (and thus the shadow). */
+ texels[i][2] = r;
+ }
+
+ return (float *)texels;
+}
+
+static struct GPUTexture *create_jitter_texture(int num_samples)
+{
+ float jitter[64 * 64][3];
+ const float num_samples_inv = 1.0f / num_samples;
+
+ for (int i = 0; i < 64 * 64; i++) {
+ float phi = blue_noise[i][0] * 2.0f * M_PI;
+ /* This rotate the sample per pixels */
+ jitter[i][0] = cosf(phi);
+ jitter[i][1] = sinf(phi);
+ /* This offset the sample along it's direction axis (reduce banding) */
+ float bn = blue_noise[i][1] - 0.5f;
+ CLAMP(bn, -0.499f, 0.499f); /* fix fireflies */
+ jitter[i][2] = bn * num_samples_inv;
+ }
+
+ UNUSED_VARS(bsdf_split_sum_ggx, btdf_split_sum_ggx, ltc_mag_ggx, ltc_mat_ggx);
+
+ return DRW_texture_create_2D(64, 64, DRW_TEX_RGB_16, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]);
+}
+
+static void clay_engine_init(void *vedata)
+{
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
+ CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
+ CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
+
+ /* Create Texture Array */
+ if (!e_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);
+
+ e_data.matcap_array = load_matcaps(prv, 24);
+ }
+
+ /* Depth prepass */
+ if (!e_data.depth_sh) {
+ e_data.depth_sh = DRW_shader_create_3D_depth_only();
+ }
+
+ /* Shading pass */
+ if (!e_data.clay_sh) {
+ DynStr *ds = BLI_dynstr_new();
+ char *matcap_with_ao;
+
+ BLI_dynstr_append(ds, datatoc_clay_frag_glsl);
+ BLI_dynstr_append(ds, datatoc_ssao_alchemy_glsl);
+
+ matcap_with_ao = BLI_dynstr_get_cstring(ds);
+
+ e_data.clay_sh = DRW_shader_create(
+ datatoc_clay_vert_glsl, NULL, matcap_with_ao,
+ SHADER_DEFINES);
+ e_data.clay_flat_sh = DRW_shader_create(
+ datatoc_clay_vert_glsl, NULL, matcap_with_ao,
+ SHADER_DEFINES
+ "#define USE_FLAT_NORMAL\n");
+
+ BLI_dynstr_free(ds);
+ MEM_freeN(matcap_with_ao);
+ }
+
+ if (!e_data.hair_sh) {
+ e_data.hair_sh = DRW_shader_create(
+ datatoc_clay_particle_vert_glsl, NULL, datatoc_clay_particle_strand_frag_glsl,
+ "#define MAX_MATERIAL 512\n");
+ }
+
+ 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 (!stl->hair_mat_ubo) {
+ stl->hair_mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_HAIR_UBO_Storage), NULL);
+ }
+
+ if (e_data.ubo_mat_idxs[1] == 0) {
+ /* Just int to have pointers to them */
+ for (int i = 0; i < MAX_CLAY_MAT; ++i) {
+ e_data.ubo_mat_idxs[i] = i;
+ }
+ }
+
+ if (DRW_state_is_fbo()) {
+ const float *viewport_size = DRW_viewport_size_get();
+ DRWFboTexture tex = {&e_data.depth_dup, DRW_TEX_DEPTH_24_STENCIL_8, DRW_TEX_TEMP};
+ DRW_framebuffer_init(&fbl->dupli_depth, &draw_engine_clay_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex, 1);
+ }
+
+ /* SSAO setup */
+ {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(
+ view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
+ int ssao_samples = BKE_collection_engine_property_value_get_int(props, "ssao_samples");
+
+ float invproj[4][4];
+ float dfdyfacs[2];
+ const 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;
+ const float *size = DRW_viewport_size_get();
+
+ DRW_state_dfdy_factors_get(dfdyfacs);
+
+ e_data.ssao_params[0] = ssao_samples;
+ e_data.ssao_params[1] = size[0] / 64.0;
+ e_data.ssao_params[2] = size[1] / 64.0;
+ e_data.ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
+
+ /* invert the view matrix */
+ DRW_viewport_matrix_get(e_data.winmat, DRW_MAT_WIN);
+ invert_m4_m4(invproj, e_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(e_data.viewvecs[i], viewvecs[i]);
+ }
+
+ /* we need to store the differences */
+ e_data.viewvecs[1][0] -= e_data.viewvecs[0][0];
+ e_data.viewvecs[1][1] = e_data.viewvecs[2][1] - e_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]);
+ e_data.viewvecs[1][2] = vec_far[2] - e_data.viewvecs[0][2];
+ }
+
+ /* AO Samples Tex */
+ if (sldata->sampling_ubo && (sldata->cached_sample_num != ssao_samples)) {
+ DRW_UBO_FREE_SAFE(sldata->sampling_ubo);
+ DRW_TEXTURE_FREE_SAFE(sldata->jitter_tx);
+ }
+
+ if (sldata->sampling_ubo == NULL) {
+ float *samples = create_disk_samples(ssao_samples);
+ sldata->jitter_tx = create_jitter_texture(ssao_samples);
+ sldata->sampling_ubo = DRW_uniformbuffer_create(sizeof(float[4]) * ssao_samples, samples);
+ sldata->cached_sample_num = ssao_samples;
+ MEM_freeN(samples);
+ }
+ }
+}
+
+static DRWShadingGroup *CLAY_shgroup_create(CLAY_Data *vedata, DRWPass *pass, int *material_id, bool use_flat)
+{
+ CLAY_StorageList *stl = vedata->stl;
+ CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get();
+ DRWShadingGroup *grp = DRW_shgroup_create(use_flat ? e_data.clay_flat_sh : e_data.clay_sh, pass);
+
+ DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1);
+ DRW_shgroup_uniform_buffer(grp, "depthtex", &e_data.depth_dup);
+ DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array);
+ DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)e_data.winmat);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)e_data.viewvecs, 3);
+ DRW_shgroup_uniform_vec4(grp, "ssao_params", e_data.ssao_params, 1);
+ DRW_shgroup_uniform_vec3(grp, "matcaps_color[0]", (float *)e_data.matcap_colors, 24);
+
+ DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1);
+
+ DRW_shgroup_uniform_texture(grp, "ssao_jitter", sldata->jitter_tx);
+ DRW_shgroup_uniform_block(grp, "samples_block", sldata->sampling_ubo);
+ DRW_shgroup_uniform_block(grp, "material_block", stl->mat_ubo);
+
+ return grp;
+}
+
+static DRWShadingGroup *CLAY_hair_shgroup_create(CLAY_Data *vedata, DRWPass *pass, int *material_id)
+{
+ CLAY_StorageList *stl = vedata->stl;
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.hair_sh, pass);
+
+ DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array);
+ DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1);
+ DRW_shgroup_uniform_block(grp, "material_block", stl->mat_ubo);
+
+ return grp;
+}
+
+static int search_mat_to_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test)
+{
+ /* 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 (memcmp(ubo, mat_ubo_test, sizeof(*mat_ubo_test)) == 0) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static int search_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test)
+{
+ /* For now just use a linear search and test all parameters */
+ /* TODO make a hash table */
+ for (int i = 0; i < storage->hair_ubo_current_id; ++i) {
+ CLAY_HAIR_UBO_Material *ubo = &storage->hair_mat_storage.materials[i];
+ if (memcmp(ubo, hair_mat_ubo_test, sizeof(*hair_mat_ubo_test)) == 0) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static int push_mat_to_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test)
+{
+ int id = storage->ubo_current_id;
+ CLAY_UBO_Material *ubo = &storage->mat_storage.materials[id];
+
+ *ubo = *mat_ubo_test;
+
+ storage->ubo_current_id++;
+
+ return id;
+}
+
+static int push_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test)
+{
+ int id = storage->hair_ubo_current_id;
+ CLAY_HAIR_UBO_Material *ubo = &storage->hair_mat_storage.materials[id];
+
+ *ubo = *hair_mat_ubo_test;
+
+ storage->hair_ubo_current_id++;
+
+ return id;
+}
+
+static int mat_in_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test)
+{
+ /* Search material in UBO */
+ int id = search_mat_to_ubo(storage, mat_ubo_test);
+
+ /* if not found create it */
+ if (id == -1) {
+ id = push_mat_to_ubo(storage, mat_ubo_test);
+ }
+
+ return id;
+}
+
+static int hair_mat_in_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test)
+{
+ /* Search material in UBO */
+ int id = search_hair_mat_to_ubo(storage, hair_mat_ubo_test);
+
+ /* if not found create it */
+ if (id == -1) {
+ id = push_hair_mat_to_ubo(storage, hair_mat_ubo_test);
+ }
+
+ return id;
+}
+
+static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo)
+{
+ IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
+
+ /* Default Settings */
+ float matcap_rot = BKE_collection_engine_property_value_get_float(props, "matcap_rotation");
+ float matcap_hue = BKE_collection_engine_property_value_get_float(props, "matcap_hue");
+ float matcap_sat = BKE_collection_engine_property_value_get_float(props, "matcap_saturation");
+ float matcap_val = BKE_collection_engine_property_value_get_float(props, "matcap_value");
+ float ssao_distance = BKE_collection_engine_property_value_get_float(props, "ssao_distance");
+ float ssao_factor_cavity = BKE_collection_engine_property_value_get_float(props, "ssao_factor_cavity");
+ float ssao_factor_edge = BKE_collection_engine_property_value_get_float(props, "ssao_factor_edge");
+ float ssao_attenuation = BKE_collection_engine_property_value_get_float(props, "ssao_attenuation");
+ int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
+
+ memset(r_ubo, 0x0, sizeof(*r_ubo));
+
+ r_ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
+ r_ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
+
+ r_ubo->matcap_hsv[0] = matcap_hue + 0.5f;
+ r_ubo->matcap_hsv[1] = matcap_sat * 2.0f;
+ r_ubo->matcap_hsv[2] = matcap_val * 2.0f;
+
+ r_ubo->ssao_params_var[0] = ssao_distance;
+ r_ubo->ssao_params_var[1] = ssao_factor_cavity;
+ r_ubo->ssao_params_var[2] = ssao_factor_edge;
+ r_ubo->ssao_params_var[3] = ssao_attenuation;
+ r_ubo->matcap_id = matcap_to_index(matcap_icon);
+}
+
+static void hair_ubo_mat_from_object(Object *ob, CLAY_HAIR_UBO_Material *r_ubo)
+{
+ IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
+
+ /* Default Settings */
+ float matcap_rot = BKE_collection_engine_property_value_get_float(props, "matcap_rotation");
+ float matcap_hue = BKE_collection_engine_property_value_get_float(props, "matcap_hue");
+ float matcap_sat = BKE_collection_engine_property_value_get_float(props, "matcap_saturation");
+ float matcap_val = BKE_collection_engine_property_value_get_float(props, "matcap_value");
+ float hair_randomness = BKE_collection_engine_property_value_get_float(props, "hair_brightness_randomness");
+ int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
+
+ memset(r_ubo, 0x0, sizeof(*r_ubo));
+
+ r_ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
+ r_ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
+ r_ubo->matcap_hsv[0] = matcap_hue + 0.5f;
+ r_ubo->matcap_hsv[1] = matcap_sat * 2.0f;
+ r_ubo->matcap_hsv[2] = matcap_val * 2.0f;
+ r_ubo->hair_randomness = hair_randomness;
+ r_ubo->matcap_id = matcap_to_index(matcap_icon);
+}
+
+static DRWShadingGroup *CLAY_object_shgrp_get(
+ CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl, bool use_flat)
+{
+ DRWShadingGroup **shgrps = use_flat ? stl->storage->shgrps_flat : stl->storage->shgrps;
+ CLAY_UBO_Material mat_ubo_test;
+
+ ubo_mat_from_object(ob, &mat_ubo_test);
+
+ int id = mat_in_ubo(stl->storage, &mat_ubo_test);
+
+ if (shgrps[id] == NULL) {
+ shgrps[id] = CLAY_shgroup_create(
+ vedata, use_flat ? psl->clay_pass_flat : psl->clay_pass, &e_data.ubo_mat_idxs[id], use_flat);
+ }
+
+ return shgrps[id];
+}
+
+static DRWShadingGroup *CLAY_hair_shgrp_get(CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
+{
+ DRWShadingGroup **hair_shgrps = stl->storage->hair_shgrps;
+
+ CLAY_HAIR_UBO_Material hair_mat_ubo_test;
+ hair_ubo_mat_from_object(ob, &hair_mat_ubo_test);
+
+ int hair_id = hair_mat_in_ubo(stl->storage, &hair_mat_ubo_test);
+
+ if (hair_shgrps[hair_id] == NULL) {
+ hair_shgrps[hair_id] = CLAY_hair_shgroup_create(vedata, psl->hair_pass, &e_data.ubo_mat_idxs[hair_id]);
+ }
+
+ return hair_shgrps[hair_id];
+}
+
+static DRWShadingGroup *CLAY_object_shgrp_default_mode_get(
+ CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
+{
+ bool use_flat = DRW_object_is_flat_normal(ob);
+ return CLAY_object_shgrp_get(vedata, ob, stl, psl, use_flat);
+}
+
+static void clay_cache_init(void *vedata)
+{
+ CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ /* Depth Pass */
+ {
+ psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
+
+ psl->depth_pass_cull = DRW_pass_create(
+ "Depth Pass Cull",
+ DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
+ stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
+ }
+
+ /* Clay Pass */
+ {
+ psl->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+ stl->storage->ubo_current_id = 0;
+ memset(stl->storage->shgrps, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
+ }
+
+ /* Clay Pass (Flat) */
+ {
+ psl->clay_pass_flat = DRW_pass_create("Clay Pass Flat", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+ memset(stl->storage->shgrps_flat, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
+ }
+
+ /* Hair Pass */
+ {
+ psl->hair_pass = DRW_pass_create(
+ "Hair Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE);
+ stl->storage->hair_ubo_current_id = 0;
+ memset(stl->storage->hair_shgrps, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
+ }
+}
+
+static void clay_cache_populate(void *vedata, Object *ob)
+{
+ CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
+
+ DRWShadingGroup *clay_shgrp, *hair_shgrp;
+
+ if (!DRW_object_is_renderable(ob))
+ return;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const bool is_active = (ob == draw_ctx->obact);
+ if (is_active) {
+ if (DRW_object_is_mode_shade(ob) == true) {
+ return;
+ }
+ }
+
+ struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
+ if (geom) {
+ IDProperty *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, "");
+ const bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
+ const bool is_sculpt_mode = is_active && (ob->mode & OB_MODE_SCULPT) != 0;
+ const bool is_default_mode_shader = is_sculpt_mode;
+
+ /* Depth Prepass */
+ {
+ DRWShadingGroup *depth_shgrp = do_cull ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp;
+ if (is_sculpt_mode) {
+ DRW_shgroup_call_sculpt_add(depth_shgrp, ob, ob->obmat);
+ }
+ else {
+ DRW_shgroup_call_object_add(depth_shgrp, geom, ob);
+ }
+ }
+
+ /* Shading */
+ if (is_default_mode_shader) {
+ clay_shgrp = CLAY_object_shgrp_default_mode_get(vedata, ob, stl, psl);
+ }
+ else {
+ clay_shgrp = CLAY_object_shgrp_get(vedata, ob, stl, psl, false);
+ }
+
+ if (is_sculpt_mode) {
+ DRW_shgroup_call_sculpt_add(clay_shgrp, ob, ob->obmat);
+ }
+ else {
+ DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat);
+ }
+ }
+
+ if (ob->type == OB_MESH) {
+ Scene *scene = draw_ctx->scene;
+ Object *obedit = scene->obedit;
+
+ if (ob != obedit) {
+ for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) {
+ if (psys_check_enabled(ob, psys, false)) {
+ ParticleSettings *part = psys->part;
+ int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
+
+ if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) {
+ draw_as = PART_DRAW_DOT;
+ }
+
+ static float mat[4][4];
+ unit_m4(mat);
+
+ if (draw_as == PART_DRAW_PATH) {
+ geom = DRW_cache_particles_get_hair(psys, NULL);
+ hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl);
+ DRW_shgroup_call_add(hair_shgrp, geom, mat);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void clay_cache_finish(void *vedata)
+{
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
+
+ DRW_uniformbuffer_update(stl->mat_ubo, &stl->storage->mat_storage);
+ DRW_uniformbuffer_update(stl->hair_mat_ubo, &stl->storage->hair_mat_storage);
+}
+
+static void clay_draw_scene(void *vedata)
+{
+
+ CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
+ CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+
+ /* Pass 1 : Depth pre-pass */
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
+
+ /* Pass 2 : Duplicate depth */
+ /* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */
+ if (DRW_state_is_fbo()) {
+ /* attach temp textures */
+ DRW_framebuffer_texture_attach(fbl->dupli_depth, e_data.depth_dup, 0, 0);
+
+ DRW_framebuffer_blit(dfbl->default_fb, fbl->dupli_depth, true, false);
+
+ /* detach temp textures */
+ DRW_framebuffer_texture_detach(e_data.depth_dup);
+
+ /* restore default fb */
+ DRW_framebuffer_bind(dfbl->default_fb);
+ }
+
+ /* Pass 3 : Shading */
+ DRW_draw_pass(psl->clay_pass);
+ DRW_draw_pass(psl->clay_pass_flat);
+ DRW_draw_pass(psl->hair_pass);
+}
+
+static void clay_layer_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
+{
+ BLI_assert(props &&
+ props->type == IDP_GROUP &&
+ props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
+
+ BKE_collection_engine_property_add_int(props, "matcap_icon", ICON_MATCAP_01);
+ BKE_collection_engine_property_add_int(props, "type", CLAY_MATCAP_NONE);
+ BKE_collection_engine_property_add_float(props, "matcap_rotation", 0.0f);
+ BKE_collection_engine_property_add_float(props, "matcap_hue", 0.5f);
+ BKE_collection_engine_property_add_float(props, "matcap_saturation", 0.5f);
+ BKE_collection_engine_property_add_float(props, "matcap_value", 0.5f);
+ BKE_collection_engine_property_add_float(props, "ssao_distance", 0.2f);
+ BKE_collection_engine_property_add_float(props, "ssao_attenuation", 1.0f);
+ BKE_collection_engine_property_add_float(props, "ssao_factor_cavity", 1.0f);
+ BKE_collection_engine_property_add_float(props, "ssao_factor_edge", 1.0f);
+ BKE_collection_engine_property_add_float(props, "hair_brightness_randomness", 0.0f);
+}
+
+static void clay_view_layer_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
+{
+ BLI_assert(props &&
+ props->type == IDP_GROUP &&
+ props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
+
+ BKE_collection_engine_property_add_int(props, "ssao_samples", 16);
+}
+
+static void clay_engine_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.clay_sh);
+ DRW_SHADER_FREE_SAFE(e_data.clay_flat_sh);
+ DRW_SHADER_FREE_SAFE(e_data.hair_sh);
+ DRW_TEXTURE_FREE_SAFE(e_data.matcap_array);
+}
+
+static const DrawEngineDataSize clay_data_size = DRW_VIEWPORT_DATA_SIZE(CLAY_Data);
+
+DrawEngineType draw_engine_clay_type = {
+ NULL, NULL,
+ N_("Clay"),
+ &clay_data_size,
+ &clay_engine_init,
+ &clay_engine_free,
+ &clay_cache_init,
+ &clay_cache_populate,
+ &clay_cache_finish,
+ NULL,
+ &clay_draw_scene,
+ NULL,
+ NULL,
+};
+
+RenderEngineType DRW_engine_viewport_clay_type = {
+ NULL, NULL,
+ CLAY_ENGINE, N_("Clay"), RE_INTERNAL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ &clay_layer_collection_settings_create,
+ &clay_view_layer_settings_create,
+ &draw_engine_clay_type,
+ {NULL, NULL, NULL}
+};
+
+
+#undef CLAY_ENGINE
+
+#endif /* WITH_CLAY_ENGINE */
diff --git a/source/blender/draw/engines/clay/clay_engine.h b/source/blender/draw/engines/clay/clay_engine.h
new file mode 100644
index 00000000000..b7c9d00c9ae
--- /dev/null
+++ b/source/blender/draw/engines/clay/clay_engine.h
@@ -0,0 +1,36 @@
+/*
+ * 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 clay_engine.h
+ * \ingroup draw_engine
+ */
+
+#ifndef __CLAY_ENGINE_H__
+#define __CLAY_ENGINE_H__
+
+extern DrawEngineType draw_engine_clay_type;
+extern RenderEngineType DRW_engine_viewport_clay_type;
+
+struct IDProperty;
+
+struct IDProperty *CLAY_render_settings_create(void);
+
+#endif /* __CLAY_ENGINE_H__ */
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..9c8c90bd5b6
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/clay_frag.glsl
@@ -0,0 +1,201 @@
+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;
+
+/* 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 samples_block {
+ vec4 ssao_samples[500];
+};
+
+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
+
+#ifdef USE_FLAT_NORMAL
+flat in vec3 normal;
+#else
+in vec3 normal;
+#endif
+
+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;
+ }
+}
+
+#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);
+
+#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_particle_strand_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_particle_strand_frag.glsl
new file mode 100644
index 00000000000..980a1e4690d
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/clay_particle_strand_frag.glsl
@@ -0,0 +1,144 @@
+
+/* Material Parameters packed in an UBO */
+struct Material {
+ vec4 one;
+ vec4 two;
+};
+
+layout(std140) uniform material_block {
+ Material shader_param[MAX_MATERIAL];
+};
+
+uniform mat4 ProjectionMatrix;
+uniform sampler2DArray matcaps;
+uniform int mat_id;
+
+#define randomness shader_param[mat_id].one.x
+#define matcap_index shader_param[mat_id].one.y
+#define matcap_rotation shader_param[mat_id].one.zw
+#define matcap_hsv shader_param[mat_id].two.xyz
+
+in vec3 tangent;
+in vec3 viewPosition;
+flat in float colRand;
+out vec4 fragColor;
+
+vec3 rotate(vec3 norm, vec3 ortho, float ang)
+{
+ return norm * cos(ang) + ortho * sin(ang);
+}
+
+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);
+}
+
+void main()
+{
+ vec3 viewvec = (ProjectionMatrix[3][3] == 0.0) ? normalize(viewPosition) : vec3(0.0, 0.0, -1.0);
+ vec3 ortho = normalize(cross(viewvec, tangent));
+ vec3 norm = normalize(cross(ortho, tangent));
+
+ vec3 col = vec3(0);
+
+ vec2 rotY = vec2(-matcap_rotation.y, matcap_rotation.x);
+
+ for (int i = 0; i < 9; i++) {
+ vec3 rotNorm = rotate(norm, ortho, -0.5 + (i * 0.125));
+ vec3 ray = reflect(viewvec, rotNorm);
+ vec2 texco = abs(vec2(dot(ray.xy, matcap_rotation), dot(ray.xy, rotY)) * .49 + 0.5);
+
+ col += texture(matcaps, vec3(texco, matcap_index)).rgb / 9.0;
+ }
+
+ hue_sat(matcap_hsv.x, matcap_hsv.y, matcap_hsv.z, col);
+
+ float maxChan = max(max(col.r, col.g), col.b);
+
+ col += (colRand * maxChan * randomness * 1.5) - (maxChan * randomness * 0.75);
+
+ fragColor.rgb = col;
+ fragColor.a = 1.0;
+}
diff --git a/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl b/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl
new file mode 100644
index 00000000000..d4c35d14182
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl
@@ -0,0 +1,34 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+uniform mat4 ModelViewMatrix;
+
+in vec3 pos;
+in vec3 nor;
+in int ind;
+out vec3 tangent;
+out vec3 viewPosition;
+flat out float colRand;
+
+float rand(int s)
+{
+ int seed = s * 1023423;
+
+ seed = (seed ^ 61) ^ (seed >> 16);
+ seed *= 9;
+ seed = seed ^ (seed >> 4);
+ seed *= 0x27d4eb2d;
+ seed = seed ^ (seed >> 15);
+
+ float value = float(seed);
+ value *= 1.0 / 42596.0;
+ return fract(value);
+}
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ tangent = normalize(NormalMatrix * nor);
+ viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz;
+ colRand = rand(ind);
+}
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..8f8866b3839
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/clay_vert.glsl
@@ -0,0 +1,17 @@
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+
+in vec3 pos;
+in vec3 nor;
+
+#ifdef USE_FLAT_NORMAL
+flat out vec3 normal;
+#else
+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..48c117c3d8d
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl
@@ -0,0 +1,78 @@
+#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 */
+ vec3 noise = texture(ssao_jitter, screenco.xy * jitter_tilling).rgb;
+
+ /* 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 num_samples = int(ssao_samples_num);
+
+ /* Note. Putting noise usage here to put some ALU after texture fetch. */
+ vec2 rotX = noise.rg;
+ vec2 rotY = vec2(-rotX.y, rotX.x);
+
+ for (int x = 0; x < num_samples && x < 500; x++) {
+ /* ssao_samples[x].xy is sample direction (normalized).
+ * ssao_samples[x].z is sample distance from disk center. */
+
+ /* Rotate with random direction to get jittered result. */
+ vec2 dir_jittered = vec2(dot(ssao_samples[x].xy, rotX), dot(ssao_samples[x].xy, rotY));
+ dir_jittered.xy *= ssao_samples[x].z + noise.b;
+
+ 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 = texture(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..9c203a4246c
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl
@@ -0,0 +1,122 @@
+#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 = texture(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;
+}
diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c
new file mode 100644
index 00000000000..63c030a574f
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_bloom.c
@@ -0,0 +1,349 @@
+/*
+ * 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 eevee_bloom.c
+ * \ingroup draw_engine
+ *
+ * Eevee's bloom shader.
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_dynstr.h"
+
+#include "BKE_global.h" /* for G.debug_value */
+
+#include "eevee_private.h"
+#include "GPU_extensions.h"
+#include "GPU_texture.h"
+
+static struct {
+ /* Bloom */
+ struct GPUShader *bloom_blit_sh[2];
+ struct GPUShader *bloom_downsample_sh[2];
+ struct GPUShader *bloom_upsample_sh[2];
+ struct GPUShader *bloom_resolve_sh[2];
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_effect_bloom_frag_glsl[];
+
+static void eevee_create_shader_bloom(void)
+{
+ e_data.bloom_blit_sh[0] = DRW_shader_create_fullscreen(
+ datatoc_effect_bloom_frag_glsl,
+ "#define STEP_BLIT\n");
+ e_data.bloom_blit_sh[1] = DRW_shader_create_fullscreen(
+ datatoc_effect_bloom_frag_glsl,
+ "#define STEP_BLIT\n"
+ "#define HIGH_QUALITY\n");
+
+ e_data.bloom_downsample_sh[0] = DRW_shader_create_fullscreen(
+ datatoc_effect_bloom_frag_glsl,
+ "#define STEP_DOWNSAMPLE\n");
+ e_data.bloom_downsample_sh[1] = DRW_shader_create_fullscreen(
+ datatoc_effect_bloom_frag_glsl,
+ "#define STEP_DOWNSAMPLE\n"
+ "#define HIGH_QUALITY\n");
+
+ e_data.bloom_upsample_sh[0] = DRW_shader_create_fullscreen(
+ datatoc_effect_bloom_frag_glsl,
+ "#define STEP_UPSAMPLE\n");
+ e_data.bloom_upsample_sh[1] = DRW_shader_create_fullscreen(
+ datatoc_effect_bloom_frag_glsl,
+ "#define STEP_UPSAMPLE\n"
+ "#define HIGH_QUALITY\n");
+
+ e_data.bloom_resolve_sh[0] = DRW_shader_create_fullscreen(
+ datatoc_effect_bloom_frag_glsl,
+ "#define STEP_RESOLVE\n");
+ e_data.bloom_resolve_sh[1] = DRW_shader_create_fullscreen(
+ datatoc_effect_bloom_frag_glsl,
+ "#define STEP_RESOLVE\n"
+ "#define HIGH_QUALITY\n");
+}
+
+int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ if (BKE_collection_engine_property_value_get_bool(props, "bloom_enable")) {
+ const float *viewport_size = DRW_viewport_size_get();
+
+ /* Shaders */
+ if (!e_data.bloom_blit_sh[0]) {
+ eevee_create_shader_bloom();
+ }
+
+ /* Bloom */
+ int blitsize[2], texsize[2];
+
+ /* Blit Buffer */
+ effects->source_texel_size[0] = 1.0f / viewport_size[0];
+ effects->source_texel_size[1] = 1.0f / viewport_size[1];
+
+ blitsize[0] = (int)viewport_size[0];
+ blitsize[1] = (int)viewport_size[1];
+
+ effects->blit_texel_size[0] = 1.0f / (float)blitsize[0];
+ effects->blit_texel_size[1] = 1.0f / (float)blitsize[1];
+
+ DRWFboTexture tex_blit = {&txl->bloom_blit, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER};
+ DRW_framebuffer_init(&fbl->bloom_blit_fb, &draw_engine_eevee_type,
+ (int)blitsize[0], (int)blitsize[1],
+ &tex_blit, 1);
+
+ /* Parameters */
+ float threshold = BKE_collection_engine_property_value_get_float(props, "bloom_threshold");
+ float knee = BKE_collection_engine_property_value_get_float(props, "bloom_knee");
+ float intensity = BKE_collection_engine_property_value_get_float(props, "bloom_intensity");
+ const float *color = BKE_collection_engine_property_value_get_float_array(props, "bloom_color");
+ float radius = BKE_collection_engine_property_value_get_float(props, "bloom_radius");
+ effects->bloom_clamp = BKE_collection_engine_property_value_get_float(props, "bloom_clamp");
+
+ /* determine the iteration count */
+ const float minDim = (float)MIN2(blitsize[0], blitsize[1]);
+ const float maxIter = (radius - 8.0f) + log(minDim) / log(2);
+ const int maxIterInt = effects->bloom_iteration_ct = (int)maxIter;
+
+ CLAMP(effects->bloom_iteration_ct, 1, MAX_BLOOM_STEP);
+
+ effects->bloom_sample_scale = 0.5f + maxIter - (float)maxIterInt;
+ effects->bloom_curve_threshold[0] = threshold - knee;
+ effects->bloom_curve_threshold[1] = knee * 2.0f;
+ effects->bloom_curve_threshold[2] = 0.25f / max_ff(1e-5f, knee);
+ effects->bloom_curve_threshold[3] = threshold;
+
+ mul_v3_v3fl(effects->bloom_color, color, intensity);
+
+ /* Downsample buffers */
+ copy_v2_v2_int(texsize, blitsize);
+ for (int i = 0; i < effects->bloom_iteration_ct; ++i) {
+ texsize[0] /= 2; texsize[1] /= 2;
+
+ if (GPU_type_matches(GPU_DEVICE_AMD_VEGA, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) {
+ texsize[0] = MAX2(texsize[0], 17);
+ texsize[1] = MAX2(texsize[1], 17);
+ }
+ else {
+ texsize[0] = MAX2(texsize[0], 2);
+ texsize[1] = MAX2(texsize[1], 2);
+ }
+
+ effects->downsamp_texel_size[i][0] = 1.0f / (float)texsize[0];
+ effects->downsamp_texel_size[i][1] = 1.0f / (float)texsize[1];
+
+ DRWFboTexture tex_bloom = {&txl->bloom_downsample[i], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER};
+ DRW_framebuffer_init(&fbl->bloom_down_fb[i], &draw_engine_eevee_type,
+ (int)texsize[0], (int)texsize[1],
+ &tex_bloom, 1);
+ }
+
+ /* Upsample buffers */
+ copy_v2_v2_int(texsize, blitsize);
+ for (int i = 0; i < effects->bloom_iteration_ct - 1; ++i) {
+ texsize[0] /= 2; texsize[1] /= 2;
+
+ if (GPU_type_matches(GPU_DEVICE_AMD_VEGA, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) {
+ texsize[0] = MAX2(texsize[0], 17);
+ texsize[1] = MAX2(texsize[1], 17);
+ }
+ else {
+ texsize[0] = MAX2(texsize[0], 2);
+ texsize[1] = MAX2(texsize[1], 2);
+ }
+
+ DRWFboTexture tex_bloom = {&txl->bloom_upsample[i], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER};
+ DRW_framebuffer_init(&fbl->bloom_accum_fb[i], &draw_engine_eevee_type,
+ (int)texsize[0], (int)texsize[1],
+ &tex_bloom, 1);
+ }
+
+ return EFFECT_BLOOM | EFFECT_POST_BUFFER;
+ }
+
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->bloom_blit);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->bloom_blit_fb);
+
+ /* Bloom and dof share this buffer. This
+ * tells dof to reconfigure it's framebuffer. */
+ if (txl->bloom_downsample[0] != NULL) {
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_down_fb);
+ }
+
+ for (int i = 0; i < MAX_BLOOM_STEP - 1; ++i) {
+ DRW_TEXTURE_FREE_SAFE(txl->bloom_downsample[i]);
+ DRW_TEXTURE_FREE_SAFE(txl->bloom_upsample[i]);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->bloom_down_fb[i]);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->bloom_accum_fb[i]);
+ }
+
+ return 0;
+}
+
+static DRWShadingGroup *eevee_create_bloom_pass(
+ const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, bool upsample)
+{
+ struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+
+ *pass = DRW_pass_create(name, DRW_STATE_WRITE_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, *pass);
+ DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_uniform_buffer(grp, "sourceBuffer", &effects->unf_source_buffer);
+ DRW_shgroup_uniform_vec2(grp, "sourceBufferTexelSize", effects->unf_source_texel_size, 1);
+ if (upsample) {
+ DRW_shgroup_uniform_buffer(grp, "baseBuffer", &effects->unf_base_buffer);
+ DRW_shgroup_uniform_float(grp, "sampleScale", &effects->bloom_sample_scale, 1);
+ }
+
+ return grp;
+}
+
+void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
+ /** Bloom algorithm
+ *
+ * Overview :
+ * - Downsample the color buffer doing a small blur during each step.
+ * - Accumulate bloom color using previously downsampled color buffers
+ * and do an upsample blur for each new accumulated layer.
+ * - Finally add accumulation buffer onto the source color buffer.
+ *
+ * [1/1] is original copy resolution (can be half or quater res for performance)
+ *
+ * [DOWNSAMPLE CHAIN] [UPSAMPLE CHAIN]
+ *
+ * Source Color ── [Blit] ──> Bright Color Extract [1/1] Final Color
+ * | Λ
+ * [Downsample First] Source Color ─> + [Resolve]
+ * v |
+ * Color Downsampled [1/2] ────────────> + Accumulation Buffer [1/2]
+ * | Λ
+ * ─── ───
+ * Repeat Repeat
+ * ─── ───
+ * v |
+ * Color Downsampled [1/N-1] ──────────> + Accumulation Buffer [1/N-1]
+ * | Λ
+ * [Downsample] [Upsample]
+ * v |
+ * Color Downsampled [1/N] ─────────────────────────┘
+ **/
+ DRWShadingGroup *grp;
+ const bool use_highres = true;
+ const bool use_antiflicker = true;
+ eevee_create_bloom_pass("Bloom Downsample First", effects, e_data.bloom_downsample_sh[use_antiflicker], &psl->bloom_downsample_first, false);
+ eevee_create_bloom_pass("Bloom Downsample", effects, e_data.bloom_downsample_sh[0], &psl->bloom_downsample, false);
+ eevee_create_bloom_pass("Bloom Upsample", effects, e_data.bloom_upsample_sh[use_highres], &psl->bloom_upsample, true);
+
+ grp = eevee_create_bloom_pass("Bloom Blit", effects, e_data.bloom_blit_sh[use_antiflicker], &psl->bloom_blit, false);
+ DRW_shgroup_uniform_vec4(grp, "curveThreshold", effects->bloom_curve_threshold, 1);
+ DRW_shgroup_uniform_float(grp, "clampIntensity", &effects->bloom_clamp, 1);
+
+ grp = eevee_create_bloom_pass("Bloom Resolve", effects, e_data.bloom_resolve_sh[use_highres], &psl->bloom_resolve, true);
+ DRW_shgroup_uniform_vec3(grp, "bloomColor", effects->bloom_color, 1);
+ }
+}
+
+void EEVEE_bloom_draw(EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ /* Bloom */
+ if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
+ struct GPUTexture *last;
+
+ /* Extract bright pixels */
+ copy_v2_v2(effects->unf_source_texel_size, effects->source_texel_size);
+ effects->unf_source_buffer = effects->source_buffer;
+
+ DRW_framebuffer_bind(fbl->bloom_blit_fb);
+ DRW_draw_pass(psl->bloom_blit);
+
+ /* Downsample */
+ copy_v2_v2(effects->unf_source_texel_size, effects->blit_texel_size);
+ effects->unf_source_buffer = txl->bloom_blit;
+
+ DRW_framebuffer_bind(fbl->bloom_down_fb[0]);
+ DRW_draw_pass(psl->bloom_downsample_first);
+
+ last = txl->bloom_downsample[0];
+
+ for (int i = 1; i < effects->bloom_iteration_ct; ++i) {
+ copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i - 1]);
+ effects->unf_source_buffer = last;
+
+ DRW_framebuffer_bind(fbl->bloom_down_fb[i]);
+ DRW_draw_pass(psl->bloom_downsample);
+
+ /* Used in next loop */
+ last = txl->bloom_downsample[i];
+ }
+
+ /* Upsample and accumulate */
+ for (int i = effects->bloom_iteration_ct - 2; i >= 0; --i) {
+ copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i]);
+ effects->unf_source_buffer = txl->bloom_downsample[i];
+ effects->unf_base_buffer = last;
+
+ DRW_framebuffer_bind(fbl->bloom_accum_fb[i]);
+ DRW_draw_pass(psl->bloom_upsample);
+
+ last = txl->bloom_upsample[i];
+ }
+
+ /* Resolve */
+ copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[0]);
+ effects->unf_source_buffer = last;
+ effects->unf_base_buffer = effects->source_buffer;
+
+ DRW_framebuffer_bind(effects->target_buffer);
+ DRW_draw_pass(psl->bloom_resolve);
+ SWAP_BUFFERS();
+ }
+}
+
+void EEVEE_bloom_free(void)
+{
+ for (int i = 0; i < 2; ++i) {
+ DRW_SHADER_FREE_SAFE(e_data.bloom_blit_sh[i]);
+ DRW_SHADER_FREE_SAFE(e_data.bloom_downsample_sh[i]);
+ DRW_SHADER_FREE_SAFE(e_data.bloom_upsample_sh[i]);
+ DRW_SHADER_FREE_SAFE(e_data.bloom_resolve_sh[i]);
+ }
+}
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
new file mode 100644
index 00000000000..d5582a498a4
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -0,0 +1,155 @@
+/*
+ * 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 eevee_data.c
+ * \ingroup draw_engine
+ *
+ * All specific data handler for Objects, Lights, ViewLayers, ...
+ */
+
+#include "DRW_render.h"
+
+#include "eevee_private.h"
+
+static void eevee_view_layer_data_free(void *storage)
+{
+ EEVEE_ViewLayerData *sldata = (EEVEE_ViewLayerData *)storage;
+
+ /* Lights */
+ MEM_SAFE_FREE(sldata->lamps);
+ DRW_UBO_FREE_SAFE(sldata->light_ubo);
+ DRW_UBO_FREE_SAFE(sldata->shadow_ubo);
+ DRW_UBO_FREE_SAFE(sldata->shadow_render_ubo);
+ DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_target_fb);
+ DRW_FRAMEBUFFER_FREE_SAFE(sldata->shadow_store_fb);
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target);
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_blur);
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target);
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_blur);
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool);
+ BLI_freelistN(&sldata->shadow_casters);
+
+ /* Probes */
+ MEM_SAFE_FREE(sldata->probes);
+ DRW_UBO_FREE_SAFE(sldata->probe_ubo);
+ DRW_UBO_FREE_SAFE(sldata->grid_ubo);
+ DRW_UBO_FREE_SAFE(sldata->planar_ubo);
+ DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_fb);
+ DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_filter_fb);
+ DRW_TEXTURE_FREE_SAFE(sldata->probe_rt);
+ DRW_TEXTURE_FREE_SAFE(sldata->probe_depth_rt);
+ DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
+ DRW_TEXTURE_FREE_SAFE(sldata->irradiance_pool);
+ DRW_TEXTURE_FREE_SAFE(sldata->irradiance_rt);
+
+ /* Volumetrics */
+ MEM_SAFE_FREE(sldata->volumetrics);
+}
+
+static void eevee_lamp_data_free(void *storage)
+{
+ EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)storage;
+
+ MEM_SAFE_FREE(led->storage);
+ BLI_freelistN(&led->shadow_caster_list);
+}
+
+static void eevee_lightprobe_data_free(void *storage)
+{
+ EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)storage;
+
+ BLI_freelistN(&ped->captured_object_list);
+}
+
+EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void)
+{
+ return (EEVEE_ViewLayerData *)DRW_view_layer_engine_data_get(
+ &draw_engine_eevee_type);
+}
+
+EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void)
+{
+ EEVEE_ViewLayerData **sldata = (EEVEE_ViewLayerData **)DRW_view_layer_engine_data_ensure(
+ &draw_engine_eevee_type, &eevee_view_layer_data_free);
+
+ if (*sldata == NULL) {
+ *sldata = MEM_callocN(sizeof(**sldata), "EEVEE_ViewLayerData");
+ }
+
+ return *sldata;
+}
+
+EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob)
+{
+ return (EEVEE_ObjectEngineData *)DRW_object_engine_data_get(
+ ob, &draw_engine_eevee_type);
+}
+
+EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob)
+{
+ EEVEE_ObjectEngineData **oedata = (EEVEE_ObjectEngineData **)DRW_object_engine_data_ensure(
+ ob, &draw_engine_eevee_type, NULL);
+
+ if (*oedata == NULL) {
+ *oedata = MEM_callocN(sizeof(**oedata), "EEVEE_ObjectEngineData");
+ }
+
+ return *oedata;
+}
+
+EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob)
+{
+ return (EEVEE_LightProbeEngineData *)DRW_object_engine_data_get(
+ ob, &draw_engine_eevee_type);
+}
+
+EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob)
+{
+ EEVEE_LightProbeEngineData **pedata = (EEVEE_LightProbeEngineData **)DRW_object_engine_data_ensure(
+ ob, &draw_engine_eevee_type, &eevee_lightprobe_data_free);
+
+ if (*pedata == NULL) {
+ *pedata = MEM_callocN(sizeof(**pedata), "EEVEE_LightProbeEngineData");
+ (*pedata)->need_full_update = true;
+ (*pedata)->need_update = true;
+ }
+
+ return *pedata;
+}
+
+EEVEE_LampEngineData *EEVEE_lamp_data_get(Object *ob)
+{
+ return (EEVEE_LampEngineData *)DRW_object_engine_data_get(
+ ob, &draw_engine_eevee_type);
+}
+
+EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob)
+{
+ EEVEE_LampEngineData **ledata = (EEVEE_LampEngineData **)DRW_object_engine_data_ensure(
+ ob, &draw_engine_eevee_type, &eevee_lamp_data_free);
+
+ if (*ledata == NULL) {
+ *ledata = MEM_callocN(sizeof(**ledata), "EEVEE_LampEngineData");
+ (*ledata)->need_update = true;
+ }
+
+ return *ledata;
+}
diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
new file mode 100644
index 00000000000..ef7e6412fc4
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -0,0 +1,290 @@
+/*
+ * 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 eevee_depth_of_field.c
+ * \ingroup draw_engine
+ *
+ * Depth of field post process effect.
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_dynstr.h"
+#include "BLI_rand.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_object_force.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_global.h" /* for G.debug_value */
+#include "BKE_camera.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_animsys.h"
+#include "BKE_screen.h"
+
+#include "DEG_depsgraph.h"
+
+#include "eevee_private.h"
+#include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
+#include "GPU_texture.h"
+
+#include "ED_screen.h"
+
+static struct {
+ /* Depth Of Field */
+ struct GPUShader *dof_downsample_sh;
+ struct GPUShader *dof_scatter_sh;
+ struct GPUShader *dof_resolve_sh;
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_effect_dof_vert_glsl[];
+extern char datatoc_effect_dof_geom_glsl[];
+extern char datatoc_effect_dof_frag_glsl[];
+
+static void eevee_create_shader_depth_of_field(void)
+{
+ e_data.dof_downsample_sh = DRW_shader_create(datatoc_effect_dof_vert_glsl, NULL,
+ datatoc_effect_dof_frag_glsl, "#define STEP_DOWNSAMPLE\n");
+ e_data.dof_scatter_sh = DRW_shader_create(datatoc_effect_dof_vert_glsl, NULL,
+ datatoc_effect_dof_frag_glsl, "#define STEP_SCATTER\n");
+ e_data.dof_resolve_sh = DRW_shader_create(datatoc_effect_dof_vert_glsl, NULL,
+ datatoc_effect_dof_frag_glsl, "#define STEP_RESOLVE\n");
+}
+
+int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ if (BKE_collection_engine_property_value_get_bool(props, "dof_enable")) {
+ Scene *scene = draw_ctx->scene;
+ View3D *v3d = draw_ctx->v3d;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+
+ if (!e_data.dof_downsample_sh) {
+ eevee_create_shader_depth_of_field();
+ }
+
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ const float *viewport_size = DRW_viewport_size_get();
+ Camera *cam = (Camera *)v3d->camera->data;
+
+ /* Retreive Near and Far distance */
+ effects->dof_near_far[0] = -cam->clipsta;
+ effects->dof_near_far[1] = -cam->clipend;
+
+ int buffer_size[2] = {(int)viewport_size[0] / 2, (int)viewport_size[1] / 2};
+
+ /* Reuse buffer from Bloom if available */
+ /* WATCH IT : must have the same size */
+ struct GPUTexture **dof_down_near;
+
+ if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
+ dof_down_near = &txl->bloom_downsample[0];
+ }
+ else {
+ dof_down_near = &txl->dof_down_near;
+ }
+
+ /* Setup buffers */
+ DRWFboTexture tex_down[3] = {
+ {dof_down_near, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}, /* filter to not interfeer with bloom */
+ {&txl->dof_down_far, DRW_TEX_RGB_11_11_10, 0},
+ {&txl->dof_coc, DRW_TEX_RG_16, 0},
+ };
+ DRW_framebuffer_init(
+ &fbl->dof_down_fb, &draw_engine_eevee_type,
+ buffer_size[0], buffer_size[1], tex_down, 3);
+
+ DRWFboTexture tex_scatter_far = {&txl->dof_far_blur, DRW_TEX_RGBA_16, DRW_TEX_FILTER};
+ DRW_framebuffer_init(
+ &fbl->dof_scatter_far_fb, &draw_engine_eevee_type,
+ buffer_size[0], buffer_size[1], &tex_scatter_far, 1);
+
+ DRWFboTexture tex_scatter_near = {&txl->dof_near_blur, DRW_TEX_RGBA_16, DRW_TEX_FILTER};
+ DRW_framebuffer_init(
+ &fbl->dof_scatter_near_fb, &draw_engine_eevee_type,
+ buffer_size[0], buffer_size[1], &tex_scatter_near, 1);
+
+ /* Parameters */
+ /* TODO UI Options */
+ float fstop = cam->gpu_dof.fstop;
+ float blades = cam->gpu_dof.num_blades;
+ float rotation = cam->gpu_dof.rotation;
+ float ratio = 1.0f / cam->gpu_dof.ratio;
+ float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
+ float focus_dist = BKE_camera_object_dof_distance(v3d->camera);
+ float focal_len = cam->lens;
+
+ UNUSED_VARS(rotation, ratio);
+
+ /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
+ * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though
+ * because the shader reads coordinates in world space, which is in blender units.
+ * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */
+ float scale = (scene->unit.system) ? scene->unit.scale_length : 1.0f;
+ float scale_camera = 0.001f / scale;
+ /* we want radius here for the aperture number */
+ float aperture = 0.5f * scale_camera * focal_len / fstop;
+ float focal_len_scaled = scale_camera * focal_len;
+ float sensor_scaled = scale_camera * sensor;
+
+ effects->dof_params[0] = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled));
+ effects->dof_params[1] = -focus_dist;
+ effects->dof_params[2] = viewport_size[0] / (rv3d->viewcamtexcofac[0] * sensor_scaled);
+ effects->dof_bokeh[0] = blades;
+ effects->dof_bokeh[1] = rotation;
+ effects->dof_bokeh[2] = ratio;
+ effects->dof_bokeh[3] = BKE_collection_engine_property_value_get_float(props, "bokeh_max_size");
+
+ return EFFECT_DOF | EFFECT_POST_BUFFER;
+ }
+ }
+
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->dof_down_near);
+ DRW_TEXTURE_FREE_SAFE(txl->dof_down_far);
+ DRW_TEXTURE_FREE_SAFE(txl->dof_coc);
+ DRW_TEXTURE_FREE_SAFE(txl->dof_far_blur);
+ DRW_TEXTURE_FREE_SAFE(txl->dof_near_blur);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_down_fb);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_scatter_far_fb);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->dof_scatter_near_fb);
+
+ return 0;
+}
+
+void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ if ((effects->enabled_effects & EFFECT_DOF) != 0) {
+ /** Depth of Field algorithm
+ *
+ * Overview :
+ * - Downsample the color buffer into 2 buffers weighted with
+ * CoC values. Also output CoC into a texture.
+ * - Shoot quads for every pixel and expand it depending on the CoC.
+ * Do one pass for near Dof and one pass for far Dof.
+ * - Finally composite the 2 blurred buffers with the original render.
+ **/
+ DRWShadingGroup *grp;
+ struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+
+ psl->dof_down = DRW_pass_create("DoF Downsample", DRW_STATE_WRITE_COLOR);
+
+ grp = DRW_shgroup_create(e_data.dof_downsample_sh, psl->dof_down);
+ DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1);
+ DRW_shgroup_uniform_vec3(grp, "dofParams", effects->dof_params, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ psl->dof_scatter = DRW_pass_create("DoF Scatter", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+
+ /* This create an empty batch of N triangles to be positioned
+ * by the vertex shader 0.4ms against 6ms with instancing */
+ const float *viewport_size = DRW_viewport_size_get();
+ const int sprite_ct = ((int)viewport_size[0] / 2) * ((int)viewport_size[1] / 2); /* brackets matters */
+ grp = DRW_shgroup_empty_tri_batch_create(e_data.dof_scatter_sh, psl->dof_scatter, sprite_ct);
+
+ DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->unf_source_buffer);
+ DRW_shgroup_uniform_buffer(grp, "cocBuffer", &txl->dof_coc);
+ DRW_shgroup_uniform_vec2(grp, "layerSelection", effects->dof_layer_select, 1);
+ DRW_shgroup_uniform_vec4(grp, "bokehParams", effects->dof_bokeh, 1);
+
+ psl->dof_resolve = DRW_pass_create("DoF Resolve", DRW_STATE_WRITE_COLOR);
+
+ grp = DRW_shgroup_create(e_data.dof_resolve_sh, psl->dof_resolve);
+ DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer);
+ DRW_shgroup_uniform_buffer(grp, "nearBuffer", &txl->dof_near_blur);
+ DRW_shgroup_uniform_buffer(grp, "farBuffer", &txl->dof_far_blur);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1);
+ DRW_shgroup_uniform_vec3(grp, "dofParams", effects->dof_params, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+ }
+}
+
+void EEVEE_depth_of_field_draw(EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ /* Depth Of Field */
+ if ((effects->enabled_effects & EFFECT_DOF) != 0) {
+ float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ /* Downsample */
+ DRW_framebuffer_bind(fbl->dof_down_fb);
+ DRW_draw_pass(psl->dof_down);
+
+ /* Scatter Far */
+ effects->unf_source_buffer = txl->dof_down_far;
+ copy_v2_fl2(effects->dof_layer_select, 0.0f, 1.0f);
+ DRW_framebuffer_bind(fbl->dof_scatter_far_fb);
+ DRW_framebuffer_clear(true, false, false, clear_col, 0.0f);
+ DRW_draw_pass(psl->dof_scatter);
+
+ /* Scatter Near */
+ if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
+ /* Reuse bloom half res buffer */
+ effects->unf_source_buffer = txl->bloom_downsample[0];
+ }
+ else {
+ effects->unf_source_buffer = txl->dof_down_near;
+ }
+ copy_v2_fl2(effects->dof_layer_select, 1.0f, 0.0f);
+ DRW_framebuffer_bind(fbl->dof_scatter_near_fb);
+ DRW_framebuffer_clear(true, false, false, clear_col, 0.0f);
+ DRW_draw_pass(psl->dof_scatter);
+
+ /* Resolve */
+ DRW_framebuffer_bind(effects->target_buffer);
+ DRW_draw_pass(psl->dof_resolve);
+ SWAP_BUFFERS();
+ }
+}
+
+void EEVEE_depth_of_field_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.dof_downsample_sh);
+ DRW_SHADER_FREE_SAFE(e_data.dof_scatter_sh);
+ DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh);
+}
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
new file mode 100644
index 00000000000..703369a86ee
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -0,0 +1,490 @@
+/*
+ * 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 eevee_effects.c
+ * \ingroup draw_engine
+ *
+ * Gather all screen space effects technique such as Bloom, Motion Blur, DoF, SSAO, SSR, ...
+ */
+
+#include "DRW_render.h"
+
+#include "BKE_global.h" /* for G.debug_value */
+
+#include "eevee_private.h"
+#include "GPU_texture.h"
+
+static struct {
+ /* Downsample Depth */
+ struct GPUShader *minz_downlevel_sh;
+ struct GPUShader *maxz_downlevel_sh;
+ struct GPUShader *minz_downdepth_sh;
+ struct GPUShader *maxz_downdepth_sh;
+ struct GPUShader *minz_downdepth_layer_sh;
+ struct GPUShader *maxz_downdepth_layer_sh;
+ struct GPUShader *minz_copydepth_sh;
+ struct GPUShader *maxz_copydepth_sh;
+
+ /* Simple Downsample */
+ struct GPUShader *downsample_sh;
+ struct GPUShader *downsample_cube_sh;
+
+ /* Theses are just references, not actually allocated */
+ struct GPUTexture *depth_src;
+ struct GPUTexture *color_src;
+
+ int depth_src_layer;
+ float cube_texel_size;
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_effect_minmaxz_frag_glsl[];
+extern char datatoc_effect_downsample_frag_glsl[];
+extern char datatoc_effect_downsample_cube_frag_glsl[];
+extern char datatoc_lightprobe_vert_glsl[];
+extern char datatoc_lightprobe_geom_glsl[];
+
+static void eevee_create_shader_downsample(void)
+{
+ e_data.downsample_sh = DRW_shader_create_fullscreen(datatoc_effect_downsample_frag_glsl, NULL);
+ e_data.downsample_cube_sh = DRW_shader_create(
+ datatoc_lightprobe_vert_glsl,
+ datatoc_lightprobe_geom_glsl,
+ datatoc_effect_downsample_cube_frag_glsl, NULL);
+
+ e_data.minz_downlevel_sh = DRW_shader_create_fullscreen(
+ datatoc_effect_minmaxz_frag_glsl,
+ "#define MIN_PASS\n");
+ e_data.maxz_downlevel_sh = DRW_shader_create_fullscreen(
+ datatoc_effect_minmaxz_frag_glsl,
+ "#define MAX_PASS\n");
+ e_data.minz_downdepth_sh = DRW_shader_create_fullscreen(
+ datatoc_effect_minmaxz_frag_glsl,
+ "#define MIN_PASS\n"
+ "#define INPUT_DEPTH\n");
+ e_data.maxz_downdepth_sh = DRW_shader_create_fullscreen(
+ datatoc_effect_minmaxz_frag_glsl,
+ "#define MAX_PASS\n"
+ "#define INPUT_DEPTH\n");
+ e_data.minz_downdepth_layer_sh = DRW_shader_create_fullscreen(
+ datatoc_effect_minmaxz_frag_glsl,
+ "#define MIN_PASS\n"
+ "#define LAYERED\n"
+ "#define INPUT_DEPTH\n");
+ e_data.maxz_downdepth_layer_sh = DRW_shader_create_fullscreen(
+ datatoc_effect_minmaxz_frag_glsl,
+ "#define MAX_PASS\n"
+ "#define LAYERED\n"
+ "#define INPUT_DEPTH\n");
+ e_data.minz_copydepth_sh = DRW_shader_create_fullscreen(
+ datatoc_effect_minmaxz_frag_glsl,
+ "#define MIN_PASS\n"
+ "#define INPUT_DEPTH\n"
+ "#define COPY_DEPTH\n");
+ e_data.maxz_copydepth_sh = DRW_shader_create_fullscreen(
+ datatoc_effect_minmaxz_frag_glsl,
+ "#define MAX_PASS\n"
+ "#define INPUT_DEPTH\n"
+ "#define COPY_DEPTH\n");
+}
+
+void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects;
+
+ const float *viewport_size = DRW_viewport_size_get();
+
+ /* Shaders */
+ if (!e_data.downsample_sh) {
+ eevee_create_shader_downsample();
+ }
+
+ if (!stl->effects) {
+ stl->effects = MEM_callocN(sizeof(EEVEE_EffectsInfo), "EEVEE_EffectsInfo");
+ }
+
+ effects = stl->effects;
+
+ effects->enabled_effects = 0;
+ effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata);
+ effects->enabled_effects |= EEVEE_bloom_init(sldata, vedata);
+ effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata);
+ effects->enabled_effects |= EEVEE_temporal_sampling_init(sldata, vedata);
+ effects->enabled_effects |= EEVEE_occlusion_init(sldata, vedata);
+ effects->enabled_effects |= EEVEE_subsurface_init(sldata, vedata);
+ effects->enabled_effects |= EEVEE_screen_raytrace_init(sldata, vedata);
+ effects->enabled_effects |= EEVEE_volumes_init(sldata, vedata);
+
+ /**
+ * Ping Pong buffer
+ */
+ if ((effects->enabled_effects & EFFECT_POST_BUFFER) != 0) {
+ DRWFboTexture tex = {&txl->color_post, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
+ DRW_framebuffer_init(&fbl->effect_fb, &draw_engine_eevee_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex, 1);
+ }
+ else {
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->color_post);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->effect_fb);
+ }
+
+ /**
+ * MinMax Pyramid
+ */
+ DRWFboTexture texmax = {&txl->maxzbuffer, DRW_TEX_DEPTH_24, DRW_TEX_MIPMAP};
+ DRW_framebuffer_init(&fbl->downsample_fb, &draw_engine_eevee_type,
+ (int)viewport_size[0] / 2, (int)viewport_size[1] / 2,
+ &texmax, 1);
+
+ /**
+ * Compute Mipmap texel alignement.
+ */
+ for (int i = 0; i < 10; ++i) {
+ float mip_size[2] = {viewport_size[0], viewport_size[1]};
+ for (int j = 0; j < i; ++j) {
+ mip_size[0] = floorf(fmaxf(1.0f, mip_size[0] / 2.0f));
+ mip_size[1] = floorf(fmaxf(1.0f, mip_size[1] / 2.0f));
+ }
+ stl->g_data->mip_ratio[i][0] = viewport_size[0] / (mip_size[0] * powf(2.0f, floorf(log2f(floorf(viewport_size[0] / mip_size[0])))));
+ stl->g_data->mip_ratio[i][1] = viewport_size[1] / (mip_size[1] * powf(2.0f, floorf(log2f(floorf(viewport_size[1] / mip_size[1])))));
+ }
+
+
+ /**
+ * Normal buffer for deferred passes.
+ */
+ if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
+ if (txl->ssr_normal_input == NULL) {
+ DRWTextureFormat nor_format = DRW_TEX_RG_16;
+ txl->ssr_normal_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], nor_format, 0, NULL);
+ }
+
+ /* Reattach textures to the right buffer (because we are alternating between buffers) */
+ /* TODO multiple FBO per texture!!!! */
+ DRW_framebuffer_texture_detach(txl->ssr_normal_input);
+ DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
+ }
+ else {
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->ssr_normal_input);
+ }
+
+ /**
+ * Setup double buffer so we can access last frame as it was before post processes.
+ */
+ if ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) {
+ DRWFboTexture tex_double_buffer = {&txl->color_double_buffer, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
+ DRW_framebuffer_init(&fbl->double_buffer, &draw_engine_eevee_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex_double_buffer, 1);
+ }
+ else {
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->color_double_buffer);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer);
+ }
+}
+
+void EEVEE_effects_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+
+ {
+ psl->color_downsample_ps = DRW_pass_create("Downsample", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_sh, psl->color_downsample_ps);
+ DRW_shgroup_uniform_buffer(grp, "source", &e_data.color_src);
+ DRW_shgroup_uniform_float(grp, "fireflyFactor", &effects->ssr_firefly_fac, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+ }
+
+ {
+ static int zero = 0;
+ psl->color_downsample_cube_ps = DRW_pass_create("Downsample Cube", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.downsample_cube_sh, psl->color_downsample_cube_ps, quad);
+ DRW_shgroup_uniform_buffer(grp, "source", &e_data.color_src);
+ DRW_shgroup_uniform_float(grp, "texelSize", &e_data.cube_texel_size, 1);
+ DRW_shgroup_uniform_int(grp, "Layer", &zero, 1);
+ DRW_shgroup_set_instance_count(grp, 6);
+ }
+
+ {
+ /* Perform min/max downsample */
+ DRWShadingGroup *grp;
+
+#if 0 /* Not used for now */
+ psl->minz_downlevel_ps = DRW_pass_create("HiZ Min Down Level", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ grp = DRW_shgroup_create(e_data.minz_downlevel_sh, psl->minz_downlevel_ps);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &stl->g_data->minzbuffer);
+ DRW_shgroup_call_add(grp, quad, NULL);
+#endif
+
+ psl->maxz_downlevel_ps = DRW_pass_create("HiZ Max Down Level", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ grp = DRW_shgroup_create(e_data.maxz_downlevel_sh, psl->maxz_downlevel_ps);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &txl->maxzbuffer);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ /* Copy depth buffer to halfres top level of HiZ */
+#if 0 /* Not used for now */
+ psl->minz_downdepth_ps = DRW_pass_create("HiZ Min Copy Depth Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ grp = DRW_shgroup_create(e_data.minz_downdepth_sh, psl->minz_downdepth_ps);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_call_add(grp, quad, NULL);
+#endif
+
+ psl->maxz_downdepth_ps = DRW_pass_create("HiZ Max Copy Depth Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ grp = DRW_shgroup_create(e_data.maxz_downdepth_sh, psl->maxz_downdepth_ps);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+#if 0 /* Not used for now */
+ psl->minz_downdepth_layer_ps = DRW_pass_create("HiZ Min Copy DepthLayer Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ grp = DRW_shgroup_create(e_data.minz_downdepth_layer_sh, psl->minz_downdepth_layer_ps);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+#endif
+
+ psl->maxz_downdepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ grp = DRW_shgroup_create(e_data.maxz_downdepth_layer_sh, psl->maxz_downdepth_layer_ps);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ /* Copy depth buffer to halfres top level of HiZ */
+#if 0 /* Not used for now */
+ psl->minz_copydepth_ps = DRW_pass_create("HiZ Min Copy Depth Fullres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ grp = DRW_shgroup_create(e_data.minz_copydepth_sh, psl->minz_copydepth_ps);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_call_add(grp, quad, NULL);
+#endif
+
+ psl->maxz_copydepth_ps = DRW_pass_create("HiZ Max Copy Depth Fullres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ grp = DRW_shgroup_create(e_data.maxz_copydepth_sh, psl->maxz_copydepth_ps);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_call_add(grp, quad, NULL);
+ }
+}
+
+#if 0 /* Not required for now */
+static void min_downsample_cb(void *vedata, int UNUSED(level))
+{
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ DRW_draw_pass(psl->minz_downlevel_ps);
+}
+#endif
+
+static void max_downsample_cb(void *vedata, int UNUSED(level))
+{
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ DRW_draw_pass(psl->maxz_downlevel_ps);
+}
+
+static void simple_downsample_cb(void *vedata, int UNUSED(level))
+{
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ DRW_draw_pass(psl->color_downsample_ps);
+}
+
+static void simple_downsample_cube_cb(void *vedata, int level)
+{
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ e_data.cube_texel_size = (float)(1 << level) / (float)GPU_texture_width(e_data.color_src);
+ DRW_draw_pass(psl->color_downsample_cube_ps);
+}
+
+void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src, int layer)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+
+ e_data.depth_src = depth_src;
+ e_data.depth_src_layer = layer;
+
+#if 0 /* Not required for now */
+ DRW_stats_group_start("Min buffer");
+ /* Copy depth buffer to min texture top level */
+ DRW_framebuffer_texture_attach(fbl->downsample_fb, stl->g_data->minzbuffer, 0, 0);
+ DRW_framebuffer_bind(fbl->downsample_fb);
+ if (layer >= 0) {
+ DRW_draw_pass(psl->minz_downdepth_layer_ps);
+ }
+ else {
+ DRW_draw_pass(psl->minz_downdepth_ps);
+ }
+ DRW_framebuffer_texture_detach(stl->g_data->minzbuffer);
+
+ /* Create lower levels */
+ DRW_framebuffer_recursive_downsample(fbl->downsample_fb, stl->g_data->minzbuffer, 8, &min_downsample_cb, vedata);
+ DRW_stats_group_end();
+#endif
+
+ DRW_stats_group_start("Max buffer");
+ /* Copy depth buffer to max texture top level */
+ DRW_framebuffer_texture_attach(fbl->downsample_fb, txl->maxzbuffer, 0, 0);
+ DRW_framebuffer_bind(fbl->downsample_fb);
+ if (layer >= 0) {
+ DRW_draw_pass(psl->maxz_downdepth_layer_ps);
+ }
+ else {
+ DRW_draw_pass(psl->maxz_downdepth_ps);
+ }
+ DRW_framebuffer_texture_detach(txl->maxzbuffer);
+
+ /* Create lower levels */
+ DRW_framebuffer_recursive_downsample(fbl->downsample_fb, txl->maxzbuffer, 8, &max_downsample_cb, vedata);
+ DRW_stats_group_end();
+
+ /* Restore */
+ DRW_framebuffer_bind(fbl->main);
+}
+
+/**
+ * Simple downsampling algorithm. Reconstruct mip chain up to mip level.
+ **/
+void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, GPUTexture *texture_src, int level)
+{
+ e_data.color_src = texture_src;
+
+ DRW_stats_group_start("Downsample buffer");
+ /* Create lower levels */
+ DRW_framebuffer_recursive_downsample(fb_src, texture_src, level, &simple_downsample_cb, vedata);
+ DRW_stats_group_end();
+}
+
+/**
+ * Simple downsampling algorithm for cubemap. Reconstruct mip chain up to mip level.
+ **/
+void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, GPUTexture *texture_src, int level)
+{
+ e_data.color_src = texture_src;
+
+ DRW_stats_group_start("Downsample Cube buffer");
+ /* Create lower levels */
+ DRW_framebuffer_recursive_downsample(fb_src, texture_src, level, &simple_downsample_cube_cb, vedata);
+ DRW_stats_group_end();
+}
+
+void EEVEE_draw_effects(EEVEE_Data *vedata)
+{
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ /* only once per frame after the first post process */
+ effects->swap_double_buffer = ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0);
+
+ /* Init pointers */
+ effects->source_buffer = txl->color; /* latest updated texture */
+ effects->target_buffer = fbl->effect_fb; /* next target to render to */
+
+ /* Temporal Anti-Aliasing MUST come first */
+ EEVEE_temporal_sampling_draw(vedata);
+
+ /* Detach depth for effects to use it */
+ DRW_framebuffer_texture_detach(dtxl->depth);
+
+ /* Post process stack (order matters) */
+ EEVEE_motion_blur_draw(vedata);
+ EEVEE_depth_of_field_draw(vedata);
+ EEVEE_bloom_draw(vedata);
+
+ /* Restore default framebuffer */
+ DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ DRW_framebuffer_bind(dfbl->default_fb);
+
+ /* Tonemapping */
+ DRW_transform_to_display(effects->source_buffer);
+
+ /* Debug : Ouput buffer to view. */
+ switch (G.debug_value) {
+ case 1:
+ if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer);
+ break;
+ case 2:
+ if (stl->g_data->ssr_hit_output[0]) DRW_transform_to_display(stl->g_data->ssr_hit_output[0]);
+ break;
+ case 3:
+ if (txl->ssr_normal_input) DRW_transform_to_display(txl->ssr_normal_input);
+ break;
+ case 4:
+ if (txl->ssr_specrough_input) DRW_transform_to_display(txl->ssr_specrough_input);
+ break;
+ case 5:
+ if (txl->color_double_buffer) DRW_transform_to_display(txl->color_double_buffer);
+ break;
+ case 6:
+ if (stl->g_data->gtao_horizons_debug) DRW_transform_to_display(stl->g_data->gtao_horizons_debug);
+ break;
+ case 7:
+ if (txl->sss_data) DRW_transform_to_display(txl->sss_data);
+ break;
+ default:
+ break;
+ }
+
+ /* If no post processes is enabled, buffers are still not swapped, do it now. */
+ SWAP_DOUBLE_BUFFERS();
+
+ if (!stl->g_data->valid_double_buffer &&
+ ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) &&
+ (DRW_state_is_image_render() == false))
+ {
+ /* If history buffer is not valid request another frame.
+ * This fix black reflections on area resize. */
+ DRW_viewport_request_redraw();
+ }
+
+ /* Record pers matrix for the next frame. */
+ DRW_viewport_matrix_get(stl->g_data->prev_persmat, DRW_MAT_PERS);
+
+ /* Update double buffer status if render mode. */
+ if (DRW_state_is_image_render()) {
+ stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL);
+ }
+}
+
+void EEVEE_effects_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.downsample_sh);
+ DRW_SHADER_FREE_SAFE(e_data.downsample_cube_sh);
+
+ DRW_SHADER_FREE_SAFE(e_data.minz_downlevel_sh);
+ DRW_SHADER_FREE_SAFE(e_data.maxz_downlevel_sh);
+ DRW_SHADER_FREE_SAFE(e_data.minz_downdepth_sh);
+ DRW_SHADER_FREE_SAFE(e_data.maxz_downdepth_sh);
+ DRW_SHADER_FREE_SAFE(e_data.minz_downdepth_layer_sh);
+ DRW_SHADER_FREE_SAFE(e_data.maxz_downdepth_layer_sh);
+ DRW_SHADER_FREE_SAFE(e_data.minz_copydepth_sh);
+ DRW_SHADER_FREE_SAFE(e_data.maxz_copydepth_sh);
+}
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
new file mode 100644
index 00000000000..a20b1afe3d4
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -0,0 +1,431 @@
+/*
+ * 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 eevee_engine.c
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_dynstr.h"
+#include "BLI_rand.h"
+
+#include "BKE_object.h"
+
+#include "DNA_world_types.h"
+
+#include "GPU_material.h"
+#include "GPU_glew.h"
+
+#include "eevee_engine.h"
+#include "eevee_private.h"
+
+#define EEVEE_ENGINE "BLENDER_EEVEE"
+
+extern GlobalsUboStorage ts;
+
+/* *********** FUNCTIONS *********** */
+
+static void eevee_engine_init(void *ved)
+{
+ EEVEE_Data *vedata = (EEVEE_Data *)ved;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
+ }
+ stl->g_data->background_alpha = 1.0f;
+ stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL);
+
+ DRWFboTexture tex = {&txl->color, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
+
+ const float *viewport_size = DRW_viewport_size_get();
+ DRW_framebuffer_init(&fbl->main, &draw_engine_eevee_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex, 1);
+
+ /* EEVEE_effects_init needs to go first for TAA */
+ EEVEE_effects_init(sldata, vedata);
+
+ EEVEE_materials_init(stl);
+ EEVEE_lights_init(sldata);
+ EEVEE_lightprobes_init(sldata, vedata);
+
+ if (stl->effects->taa_current_sample > 1) {
+ /* XXX otherwise it would break the other engines. */
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_unset(DRW_MAT_WIN);
+ DRW_viewport_matrix_override_unset(DRW_MAT_WININV);
+ }
+}
+
+static void eevee_cache_init(void *vedata)
+{
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+
+ EEVEE_bloom_cache_init(sldata, vedata);
+ EEVEE_depth_of_field_cache_init(sldata, vedata);
+ EEVEE_effects_cache_init(sldata, vedata);
+ EEVEE_lightprobes_cache_init(sldata, vedata);
+ EEVEE_lights_cache_init(sldata, psl);
+ EEVEE_materials_cache_init(vedata);
+ EEVEE_motion_blur_cache_init(sldata, vedata);
+ EEVEE_occlusion_cache_init(sldata, vedata);
+ EEVEE_screen_raytrace_cache_init(sldata, vedata);
+ EEVEE_subsurface_cache_init(sldata, vedata);
+ EEVEE_temporal_sampling_cache_init(sldata, vedata);
+ EEVEE_volumes_cache_init(sldata, vedata);
+}
+
+static void eevee_cache_populate(void *vedata, Object *ob)
+{
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const bool is_active = (ob == draw_ctx->obact);
+ if (is_active) {
+ if (DRW_object_is_mode_shade(ob) == true) {
+ return;
+ }
+ }
+
+ if (ELEM(ob->type, OB_MESH)) {
+ if (!BKE_object_is_visible(ob)) {
+ return;
+ }
+
+ EEVEE_materials_cache_populate(vedata, sldata, ob);
+
+ const bool cast_shadow = true;
+
+ if (cast_shadow) {
+ if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
+ /* TODO: Special case for dupli objects because we cannot save the object pointer. */
+ }
+ else {
+ BLI_addtail(&sldata->shadow_casters, BLI_genericNodeN(ob));
+ }
+ }
+ }
+ else if (ob->type == OB_LIGHTPROBE) {
+ if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
+ /* TODO: Special case for dupli objects because we cannot save the object pointer. */
+ }
+ else {
+ EEVEE_lightprobes_cache_add(sldata, ob);
+ }
+ }
+ else if (ob->type == OB_LAMP) {
+ if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
+ /* TODO: Special case for dupli objects because we cannot save the object pointer. */
+ }
+ else {
+ EEVEE_lights_cache_add(sldata, ob);
+ }
+ }
+}
+
+static void eevee_cache_finish(void *vedata)
+{
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+
+ EEVEE_materials_cache_finish(vedata);
+ EEVEE_lights_cache_finish(sldata);
+ EEVEE_lightprobes_cache_finish(sldata, vedata);
+}
+
+static void eevee_draw_scene(void *vedata)
+{
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+
+ /* Default framebuffer and texture */
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ /* Number of iteration: needed for all temporal effect (SSR, TAA)
+ * when using opengl render. */
+ int loop_ct = DRW_state_is_image_render() ? 4 : 1;
+
+ static float rand = 0.0f;
+
+ /* XXX temp for denoising render. TODO plug number of samples here */
+ if (DRW_state_is_image_render()) {
+ rand += 1.0f / 16.0f;
+ rand = rand - floorf(rand);
+
+ /* Set jitter offset */
+ EEVEE_update_util_texture(rand);
+ }
+ else if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) && (stl->effects->taa_current_sample > 1)) {
+ double r;
+ BLI_halton_1D(2, 0.0, stl->effects->taa_current_sample - 1, &r);
+
+ /* Set jitter offset */
+ /* PERF This is killing perf ! */
+ EEVEE_update_util_texture((float)r);
+ }
+
+ while (loop_ct--) {
+
+ /* Refresh Probes */
+ DRW_stats_group_start("Probes Refresh");
+ EEVEE_lightprobes_refresh(sldata, vedata);
+ DRW_stats_group_end();
+
+ /* Refresh shadows */
+ DRW_stats_group_start("Shadows");
+ EEVEE_draw_shadows(sldata, psl);
+ DRW_stats_group_end();
+
+ /* Attach depth to the hdr buffer and bind it */
+ DRW_framebuffer_texture_detach(dtxl->depth);
+ DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
+ DRW_framebuffer_bind(fbl->main);
+ DRW_framebuffer_clear(false, true, true, NULL, 1.0f);
+
+ if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) && stl->effects->taa_current_sample > 1) {
+ DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV);
+ }
+
+ /* Depth prepass */
+ DRW_stats_group_start("Prepass");
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
+ DRW_stats_group_end();
+
+ /* Create minmax texture */
+ DRW_stats_group_start("Main MinMax buffer");
+ EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1);
+ DRW_stats_group_end();
+
+ EEVEE_occlusion_compute(sldata, vedata);
+ EEVEE_volumes_compute(sldata, vedata);
+
+ /* Shading pass */
+ DRW_stats_group_start("Shading");
+ DRW_draw_pass(psl->background_pass);
+ EEVEE_draw_default_passes(psl);
+ DRW_draw_pass(psl->material_pass);
+ EEVEE_subsurface_data_render(sldata, vedata);
+ DRW_stats_group_end();
+
+ /* Effects pre-transparency */
+ EEVEE_subsurface_compute(sldata, vedata);
+ EEVEE_reflection_compute(sldata, vedata);
+ EEVEE_occlusion_draw_debug(sldata, vedata);
+ DRW_draw_pass(psl->probe_display);
+ EEVEE_refraction_compute(sldata, vedata);
+
+ /* Opaque refraction */
+ DRW_stats_group_start("Opaque Refraction");
+ DRW_draw_pass(psl->refract_depth_pass);
+ DRW_draw_pass(psl->refract_depth_pass_cull);
+ DRW_draw_pass(psl->refract_pass);
+ DRW_stats_group_end();
+
+ /* Volumetrics Resolve Opaque */
+ EEVEE_volumes_resolve(sldata, vedata);
+
+ /* Transparent */
+ DRW_pass_sort_shgroup_z(psl->transparent_pass);
+ DRW_draw_pass(psl->transparent_pass);
+
+ /* Post Process */
+ DRW_stats_group_start("Post FX");
+ EEVEE_draw_effects(vedata);
+ DRW_stats_group_end();
+
+ if (stl->effects->taa_current_sample > 1) {
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_unset(DRW_MAT_WIN);
+ DRW_viewport_matrix_override_unset(DRW_MAT_WININV);
+ }
+ }
+
+ EEVEE_volumes_free_smoke_textures();
+
+ stl->g_data->view_updated = false;
+}
+
+static void eevee_view_update(void *vedata)
+{
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ if (stl->g_data) {
+ stl->g_data->view_updated = true;
+ }
+}
+
+static void eevee_id_update(void *UNUSED(vedata), ID *id)
+{
+ const ID_Type id_type = GS(id->name);
+ if (id_type == ID_OB) {
+ Object *object = (Object *)id;
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object);
+ if (ped != NULL) {
+ ped->need_full_update = true;
+ }
+ EEVEE_LampEngineData *led = EEVEE_lamp_data_get(object);
+ if (led != NULL) {
+ led->need_update = true;
+ }
+ EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object);
+ if (oedata != NULL) {
+ oedata->need_update = true;
+ }
+ }
+}
+
+static void eevee_engine_free(void)
+{
+ EEVEE_bloom_free();
+ EEVEE_depth_of_field_free();
+ EEVEE_effects_free();
+ EEVEE_lightprobes_free();
+ EEVEE_lights_free();
+ EEVEE_materials_free();
+ EEVEE_motion_blur_free();
+ EEVEE_occlusion_free();
+ EEVEE_screen_raytrace_free();
+ EEVEE_subsurface_free();
+ EEVEE_temporal_sampling_free();
+ EEVEE_volumes_free();
+}
+
+static void eevee_layer_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
+{
+ BLI_assert(props &&
+ props->type == IDP_GROUP &&
+ props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
+ // BKE_collection_engine_property_add_int(props, "high_quality_sphere_lamps", false);
+ UNUSED_VARS_NDEBUG(props);
+}
+
+static void eevee_view_layer_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
+{
+ BLI_assert(props &&
+ props->type == IDP_GROUP &&
+ props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
+
+ BKE_collection_engine_property_add_int(props, "gi_diffuse_bounces", 3);
+ BKE_collection_engine_property_add_int(props, "gi_cubemap_resolution", 512);
+ BKE_collection_engine_property_add_int(props, "gi_visibility_resolution", 32);
+
+ BKE_collection_engine_property_add_int(props, "taa_samples", 8);
+
+ BKE_collection_engine_property_add_bool(props, "sss_enable", false);
+ BKE_collection_engine_property_add_int(props, "sss_samples", 7);
+ BKE_collection_engine_property_add_float(props, "sss_jitter_threshold", 0.3f);
+ BKE_collection_engine_property_add_bool(props, "sss_separate_albedo", false);
+
+ BKE_collection_engine_property_add_bool(props, "ssr_enable", false);
+ BKE_collection_engine_property_add_bool(props, "ssr_refraction", false);
+ BKE_collection_engine_property_add_bool(props, "ssr_halfres", true);
+ BKE_collection_engine_property_add_int(props, "ssr_ray_count", 1);
+ BKE_collection_engine_property_add_float(props, "ssr_quality", 0.25f);
+ BKE_collection_engine_property_add_float(props, "ssr_max_roughness", 0.5f);
+ BKE_collection_engine_property_add_float(props, "ssr_thickness", 0.2f);
+ BKE_collection_engine_property_add_float(props, "ssr_border_fade", 0.075f);
+ BKE_collection_engine_property_add_float(props, "ssr_firefly_fac", 10.0f);
+
+ BKE_collection_engine_property_add_bool(props, "volumetric_enable", false);
+ BKE_collection_engine_property_add_float(props, "volumetric_start", 0.1f);
+ BKE_collection_engine_property_add_float(props, "volumetric_end", 100.0f);
+ BKE_collection_engine_property_add_int(props, "volumetric_tile_size", 8);
+ BKE_collection_engine_property_add_int(props, "volumetric_samples", 64);
+ BKE_collection_engine_property_add_float(props, "volumetric_sample_distribution", 0.8f);
+ BKE_collection_engine_property_add_bool(props, "volumetric_lights", true);
+ BKE_collection_engine_property_add_float(props, "volumetric_light_clamp", 0.0f);
+ BKE_collection_engine_property_add_bool(props, "volumetric_shadows", false);
+ BKE_collection_engine_property_add_int(props, "volumetric_shadow_samples", 16);
+ BKE_collection_engine_property_add_bool(props, "volumetric_colored_transmittance", true);
+
+ BKE_collection_engine_property_add_bool(props, "gtao_enable", false);
+ BKE_collection_engine_property_add_bool(props, "gtao_use_bent_normals", true);
+ BKE_collection_engine_property_add_bool(props, "gtao_denoise", true);
+ BKE_collection_engine_property_add_bool(props, "gtao_bounce", true);
+ BKE_collection_engine_property_add_float(props, "gtao_distance", 0.2f);
+ BKE_collection_engine_property_add_float(props, "gtao_factor", 1.0f);
+ BKE_collection_engine_property_add_float(props, "gtao_quality", 0.25f);
+ BKE_collection_engine_property_add_int(props, "gtao_samples", 2);
+
+ BKE_collection_engine_property_add_bool(props, "dof_enable", false);
+ BKE_collection_engine_property_add_float(props, "bokeh_max_size", 100.0f);
+ BKE_collection_engine_property_add_float(props, "bokeh_threshold", 1.0f);
+
+ float default_bloom_color[3] = {1.0f, 1.0f, 1.0f};
+ BKE_collection_engine_property_add_bool(props, "bloom_enable", false);
+ BKE_collection_engine_property_add_float_array(props, "bloom_color", default_bloom_color, 3);
+ BKE_collection_engine_property_add_float(props, "bloom_threshold", 0.8f);
+ BKE_collection_engine_property_add_float(props, "bloom_knee", 0.5f);
+ BKE_collection_engine_property_add_float(props, "bloom_intensity", 0.8f);
+ BKE_collection_engine_property_add_float(props, "bloom_radius", 6.5f);
+ BKE_collection_engine_property_add_float(props, "bloom_clamp", 1.0f);
+
+ BKE_collection_engine_property_add_bool(props, "motion_blur_enable", false);
+ BKE_collection_engine_property_add_int(props, "motion_blur_samples", 8);
+ BKE_collection_engine_property_add_float(props, "motion_blur_shutter", 1.0f);
+
+ BKE_collection_engine_property_add_int(props, "shadow_method", SHADOW_ESM);
+ BKE_collection_engine_property_add_int(props, "shadow_size", 512);
+ BKE_collection_engine_property_add_bool(props, "shadow_high_bitdepth", false);
+}
+
+static const DrawEngineDataSize eevee_data_size = DRW_VIEWPORT_DATA_SIZE(EEVEE_Data);
+
+DrawEngineType draw_engine_eevee_type = {
+ NULL, NULL,
+ N_("Eevee"),
+ &eevee_data_size,
+ &eevee_engine_init,
+ &eevee_engine_free,
+ &eevee_cache_init,
+ &eevee_cache_populate,
+ &eevee_cache_finish,
+ &eevee_draw_scene,
+ NULL, //&EEVEE_draw_scene
+ &eevee_view_update,
+ &eevee_id_update,
+};
+
+RenderEngineType DRW_engine_viewport_eevee_type = {
+ NULL, NULL,
+ EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_SHADING_NODES,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ &eevee_layer_collection_settings_create,
+ &eevee_view_layer_settings_create,
+ &draw_engine_eevee_type,
+ {NULL, NULL, NULL}
+};
+
+
+#undef EEVEE_ENGINE
diff --git a/source/blender/draw/engines/eevee/eevee_engine.h b/source/blender/draw/engines/eevee/eevee_engine.h
new file mode 100644
index 00000000000..0cbd89a79fa
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_engine.h
@@ -0,0 +1,31 @@
+/*
+ * 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 eevee_engine.h
+ * \ingroup DNA
+ */
+
+#ifndef __EEVEE_ENGINE_H__
+#define __EEVEE_ENGINE_H__
+
+extern RenderEngineType DRW_engine_viewport_eevee_type;
+
+#endif /* __EEVEE_ENGINE_H__ */ \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
new file mode 100644
index 00000000000..d7ccc1a5336
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -0,0 +1,1668 @@
+/*
+ * 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 eevee_lightprobes.c
+ * \ingroup DNA
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_dynstr.h"
+#include "BLI_rand.h"
+
+#include "DNA_world_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_image_types.h"
+#include "DNA_lightprobe_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_object.h"
+
+#include "GPU_material.h"
+#include "GPU_texture.h"
+#include "GPU_glew.h"
+
+#include "eevee_engine.h"
+#include "eevee_private.h"
+
+#include "ED_screen.h"
+
+/* Rounded to nearest PowerOfTwo */
+#if defined(IRRADIANCE_SH_L2)
+#define IRRADIANCE_SAMPLE_SIZE_X 4 /* 3 in reality */
+#define IRRADIANCE_SAMPLE_SIZE_Y 4 /* 3 in reality */
+#elif defined(IRRADIANCE_CUBEMAP)
+#define IRRADIANCE_SAMPLE_SIZE_X 8
+#define IRRADIANCE_SAMPLE_SIZE_Y 8
+#elif defined(IRRADIANCE_HL2)
+#define IRRADIANCE_SAMPLE_SIZE_X 4 /* 3 in reality */
+#define IRRADIANCE_SAMPLE_SIZE_Y 2
+#endif
+
+#define IRRADIANCE_MAX_POOL_LAYER 256 /* OpenGL 3.3 core requirement, can be extended but it's already very big */
+#define IRRADIANCE_MAX_POOL_SIZE 1024
+#define MAX_IRRADIANCE_SAMPLES \
+ (IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_X) * \
+ (IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_Y)
+#define HAMMERSLEY_SIZE 1024
+
+static struct {
+ struct GPUShader *probe_default_sh;
+ struct GPUShader *probe_filter_glossy_sh;
+ struct GPUShader *probe_filter_diffuse_sh;
+ struct GPUShader *probe_filter_visibility_sh;
+ struct GPUShader *probe_grid_fill_sh;
+ struct GPUShader *probe_grid_display_sh;
+ struct GPUShader *probe_planar_display_sh;
+ struct GPUShader *probe_planar_downsample_sh;
+ struct GPUShader *probe_cube_display_sh;
+
+ struct GPUTexture *hammersley;
+ struct GPUTexture *planar_pool_placeholder;
+ struct GPUTexture *depth_placeholder;
+ struct GPUTexture *depth_array_placeholder;
+ struct GPUTexture *cube_face_minmaxz;
+
+ int update_world;
+ bool world_ready_to_shade;
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_background_vert_glsl[];
+extern char datatoc_default_world_frag_glsl[];
+extern char datatoc_lightprobe_filter_glossy_frag_glsl[];
+extern char datatoc_lightprobe_filter_diffuse_frag_glsl[];
+extern char datatoc_lightprobe_filter_visibility_frag_glsl[];
+extern char datatoc_lightprobe_geom_glsl[];
+extern char datatoc_lightprobe_vert_glsl[];
+extern char datatoc_lightprobe_planar_display_frag_glsl[];
+extern char datatoc_lightprobe_planar_display_vert_glsl[];
+extern char datatoc_lightprobe_planar_downsample_frag_glsl[];
+extern char datatoc_lightprobe_planar_downsample_geom_glsl[];
+extern char datatoc_lightprobe_planar_downsample_vert_glsl[];
+extern char datatoc_lightprobe_cube_display_frag_glsl[];
+extern char datatoc_lightprobe_cube_display_vert_glsl[];
+extern char datatoc_lightprobe_grid_display_frag_glsl[];
+extern char datatoc_lightprobe_grid_display_vert_glsl[];
+extern char datatoc_lightprobe_grid_fill_frag_glsl[];
+extern char datatoc_irradiance_lib_glsl[];
+extern char datatoc_lightprobe_lib_glsl[];
+extern char datatoc_octahedron_lib_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_bsdf_sampling_lib_glsl[];
+
+extern GlobalsUboStorage ts;
+
+/* *********** FUNCTIONS *********** */
+
+static void irradiance_pool_size_get(int visibility_size, int total_samples, int r_size[3])
+{
+ /* Compute how many irradiance samples we can store per visibility sample. */
+ int irr_per_vis = (visibility_size / IRRADIANCE_SAMPLE_SIZE_X) *
+ (visibility_size / IRRADIANCE_SAMPLE_SIZE_Y);
+
+ /* The irradiance itself take one layer, hence the +1 */
+ int layer_ct = MIN2(irr_per_vis + 1, IRRADIANCE_MAX_POOL_LAYER);
+
+ int texel_ct = (int)ceilf((float)total_samples / (float)(layer_ct - 1));
+ r_size[0] = visibility_size * max_ii(1, min_ii(texel_ct, (IRRADIANCE_MAX_POOL_SIZE / visibility_size)));
+ r_size[1] = visibility_size * max_ii(1, (texel_ct / (IRRADIANCE_MAX_POOL_SIZE / visibility_size)));
+ r_size[2] = layer_ct;
+}
+
+static struct GPUTexture *create_hammersley_sample_texture(int samples)
+{
+ struct GPUTexture *tex;
+ float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * samples, "hammersley_tex");
+ int i;
+
+ for (i = 0; i < samples; i++) {
+ double dphi;
+ BLI_hammersley_1D(i, &dphi);
+ float phi = (float)dphi * 2.0f * M_PI;
+ texels[i][0] = cosf(phi);
+ texels[i][1] = sinf(phi);
+ }
+
+ tex = DRW_texture_create_1D(samples, DRW_TEX_RG_16, DRW_TEX_WRAP, (float *)texels);
+ MEM_freeN(texels);
+ return tex;
+}
+
+static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
+{
+ /* XXX TODO OPTIMISATION : This is a complete waist of texture memory.
+ * Instead of allocating each planar probe for each viewport,
+ * only alloc them once using the biggest viewport resolution. */
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+
+ const float *viewport_size = DRW_viewport_size_get();
+
+ /* TODO get screen percentage from layer setting */
+ // const DRWContextState *draw_ctx = DRW_context_state_get();
+ // ViewLayer *view_layer = draw_ctx->view_layer;
+ float screen_percentage = 1.0f;
+
+ int width = (int)(viewport_size[0] * screen_percentage);
+ int height = (int)(viewport_size[1] * screen_percentage);
+
+ /* We need an Array texture so allocate it ourself */
+ if (!txl->planar_pool) {
+ if (num_planar_ref > 0) {
+ txl->planar_pool = DRW_texture_create_2D_array(width, height, max_ff(1, num_planar_ref),
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
+ txl->planar_depth = DRW_texture_create_2D_array(width, height, max_ff(1, num_planar_ref),
+ DRW_TEX_DEPTH_24, 0, NULL);
+ }
+ else if (num_planar_ref == 0) {
+ /* Makes Opengl Happy : Create a placeholder texture that will never be sampled but still bound to shader. */
+ txl->planar_pool = DRW_texture_create_2D_array(1, 1, 1, DRW_TEX_RGBA_8, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
+ txl->planar_depth = DRW_texture_create_2D_array(1, 1, 1, DRW_TEX_DEPTH_24, 0, NULL);
+ }
+ }
+
+ if (num_planar_ref > 0) {
+ /* NOTE : Depth buffer is 2D but the planar_pool tex is 2D array.
+ * DRW_framebuffer_init binds the whole texture making the framebuffer invalid.
+ * To overcome this, we bind the planar pool ourselves later */
+
+ /* XXX Do this one first so it gets it's mipmap done. */
+ DRW_framebuffer_init(&fbl->planarref_fb, &draw_engine_eevee_type, 1, 1, NULL, 0);
+ }
+}
+
+static void lightprobe_shaders_init(void)
+{
+ const char *filter_defines = "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n"
+#if defined(IRRADIANCE_SH_L2)
+ "#define IRRADIANCE_SH_L2\n"
+#elif defined(IRRADIANCE_CUBEMAP)
+ "#define IRRADIANCE_CUBEMAP\n"
+#elif defined(IRRADIANCE_HL2)
+ "#define IRRADIANCE_HL2\n"
+#endif
+ "#define NOISE_SIZE 64\n";
+
+ char *shader_str = NULL;
+
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lightprobe_filter_glossy_frag_glsl);
+ shader_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.probe_filter_glossy_sh = DRW_shader_create(
+ datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, shader_str, filter_defines);
+
+ e_data.probe_default_sh = DRW_shader_create(
+ datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, NULL);
+
+ MEM_freeN(shader_str);
+
+ ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lightprobe_filter_diffuse_frag_glsl);
+ shader_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.probe_filter_diffuse_sh = DRW_shader_create_fullscreen(shader_str, filter_defines);
+
+ MEM_freeN(shader_str);
+
+ ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lightprobe_filter_visibility_frag_glsl);
+ shader_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.probe_filter_visibility_sh = DRW_shader_create_fullscreen(shader_str, filter_defines);
+
+ MEM_freeN(shader_str);
+
+ ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lightprobe_grid_display_frag_glsl);
+ shader_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.probe_grid_display_sh = DRW_shader_create(
+ datatoc_lightprobe_grid_display_vert_glsl, NULL, shader_str, filter_defines);
+
+ MEM_freeN(shader_str);
+
+ e_data.probe_grid_fill_sh = DRW_shader_create_fullscreen(
+ datatoc_lightprobe_grid_fill_frag_glsl, filter_defines);
+
+ ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lightprobe_cube_display_frag_glsl);
+ shader_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.probe_cube_display_sh = DRW_shader_create(
+ datatoc_lightprobe_cube_display_vert_glsl, NULL, shader_str, NULL);
+
+ MEM_freeN(shader_str);
+
+ e_data.probe_planar_display_sh = DRW_shader_create(
+ datatoc_lightprobe_planar_display_vert_glsl, NULL,
+ datatoc_lightprobe_planar_display_frag_glsl, NULL);
+
+ e_data.probe_planar_downsample_sh = DRW_shader_create(
+ datatoc_lightprobe_planar_downsample_vert_glsl,
+ datatoc_lightprobe_planar_downsample_geom_glsl,
+ datatoc_lightprobe_planar_downsample_frag_glsl,
+ NULL);
+
+ e_data.hammersley = create_hammersley_sample_texture(HAMMERSLEY_SIZE);
+}
+
+void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(vedata))
+{
+ bool update_all = false;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ /* Shaders */
+ if (!e_data.probe_filter_glossy_sh) {
+ lightprobe_shaders_init();
+ }
+
+ if (!sldata->probes) {
+ sldata->probes = MEM_callocN(sizeof(EEVEE_LightProbesInfo), "EEVEE_LightProbesInfo");
+ sldata->probes->specular_toggle = true;
+ sldata->probes->ssr_toggle = true;
+ sldata->probes->sss_toggle = true;
+ sldata->probes->grid_initialized = false;
+ sldata->probe_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightProbe) * MAX_PROBE, NULL);
+ sldata->grid_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightGrid) * MAX_GRID, NULL);
+ sldata->planar_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_PlanarReflection) * MAX_PLANAR, NULL);
+ }
+
+ int prop_bounce_num = BKE_collection_engine_property_value_get_int(props, "gi_diffuse_bounces");
+ if (sldata->probes->num_bounce != prop_bounce_num) {
+ sldata->probes->num_bounce = prop_bounce_num;
+ update_all = true;
+ }
+
+ int prop_cubemap_res = BKE_collection_engine_property_value_get_int(props, "gi_cubemap_resolution");
+ if (sldata->probes->cubemap_res != prop_cubemap_res) {
+ sldata->probes->cubemap_res = prop_cubemap_res;
+ update_all = true;
+
+ sldata->probes->target_size = prop_cubemap_res >> 1;
+
+ DRW_TEXTURE_FREE_SAFE(sldata->probe_rt);
+ DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
+ }
+
+ int visibility_res = BKE_collection_engine_property_value_get_int(props, "gi_visibility_resolution");
+ if (sldata->probes->irradiance_vis_size != visibility_res) {
+ sldata->probes->irradiance_vis_size = visibility_res;
+ update_all = true;
+ }
+
+ if (update_all) {
+ e_data.update_world |= PROBE_UPDATE_ALL;
+ sldata->probes->updated_bounce = 0;
+ sldata->probes->grid_initialized = false;
+ }
+
+ /* Setup Render Target Cubemap */
+ if (!sldata->probe_rt) {
+ sldata->probe_depth_rt = DRW_texture_create_cube(sldata->probes->target_size, DRW_TEX_DEPTH_24, 0, NULL);
+ sldata->probe_rt = DRW_texture_create_cube(sldata->probes->target_size, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
+ }
+
+ DRWFboTexture tex_probe[2] = {{&sldata->probe_depth_rt, DRW_TEX_DEPTH_24, 0},
+ {&sldata->probe_rt, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP}};
+ DRW_framebuffer_init(&sldata->probe_fb, &draw_engine_eevee_type, sldata->probes->target_size, sldata->probes->target_size, tex_probe, 2);
+
+ /* Minmaxz Pyramid */
+ // DRWFboTexture tex_minmaxz = {&e_data.cube_face_minmaxz, DRW_TEX_RG_32, DRW_TEX_MIPMAP | DRW_TEX_TEMP};
+ // DRW_framebuffer_init(&vedata->fbl->downsample_fb, &draw_engine_eevee_type, PROBE_RT_SIZE / 2, PROBE_RT_SIZE / 2, &tex_minmaxz, 1);
+
+ /* Placeholder planar pool: used when rendering planar reflections (avoid dependency loop). */
+ if (!e_data.planar_pool_placeholder) {
+ e_data.planar_pool_placeholder = DRW_texture_create_2D_array(1, 1, 1, DRW_TEX_RGBA_8, DRW_TEX_FILTER, NULL);
+ }
+
+ if (!e_data.depth_placeholder) {
+ e_data.depth_placeholder = DRW_texture_create_2D(1, 1, DRW_TEX_DEPTH_24, 0, NULL);
+ }
+ if (!e_data.depth_array_placeholder) {
+ e_data.depth_array_placeholder = DRW_texture_create_2D_array(1, 1, 1, DRW_TEX_DEPTH_24, 0, NULL);
+ }
+}
+
+void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+
+ pinfo->num_cube = 1; /* at least one for the world */
+ pinfo->num_grid = 1;
+ pinfo->num_planar = 0;
+ pinfo->total_irradiance_samples = 1;
+ memset(pinfo->probes_cube_ref, 0, sizeof(pinfo->probes_cube_ref));
+ memset(pinfo->probes_grid_ref, 0, sizeof(pinfo->probes_grid_ref));
+ memset(pinfo->probes_planar_ref, 0, sizeof(pinfo->probes_planar_ref));
+
+ {
+ psl->probe_background = DRW_pass_create("World Probe Background Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+
+ struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ DRWShadingGroup *grp = NULL;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ World *wo = scene->world;
+
+ float *col = ts.colorBackground;
+ if (wo) {
+ col = &wo->horr;
+ if (wo->update_flag != 0) {
+ e_data.update_world |= PROBE_UPDATE_ALL;
+ pinfo->updated_bounce = 0;
+ pinfo->grid_initialized = false;
+ }
+ wo->update_flag = 0;
+
+ if (wo->use_nodes && wo->nodetree) {
+ struct GPUMaterial *gpumat = EEVEE_material_world_lightprobe_get(scene, wo);
+
+ grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
+
+ if (grp) {
+ DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ DRW_shgroup_call_add(grp, geom, NULL);
+ }
+ else {
+ /* Shader failed : pink background */
+ static float pink[3] = {1.0f, 0.0f, 1.0f};
+ col = pink;
+ }
+ }
+ }
+
+ /* Fallback if shader fails or if not using nodetree. */
+ if (grp == NULL) {
+ grp = DRW_shgroup_create(e_data.probe_default_sh, psl->probe_background);
+ DRW_shgroup_uniform_vec3(grp, "color", col, 1);
+ DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ DRW_shgroup_call_add(grp, geom, NULL);
+ }
+ }
+
+ {
+ psl->probe_glossy_compute = DRW_pass_create("LightProbe Glossy Compute", DRW_STATE_WRITE_COLOR);
+
+ struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_filter_glossy_sh, psl->probe_glossy_compute, geom);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "roughnessSquared", &sldata->probes->roughness, 1);
+ DRW_shgroup_uniform_float(grp, "lodFactor", &sldata->probes->lodfactor, 1);
+ DRW_shgroup_uniform_float(grp, "lodMax", &sldata->probes->lod_rt_max, 1);
+ DRW_shgroup_uniform_float(grp, "texelSize", &sldata->probes->texel_size, 1);
+ DRW_shgroup_uniform_float(grp, "paddingSize", &sldata->probes->padding_size, 1);
+ DRW_shgroup_uniform_int(grp, "Layer", &sldata->probes->layer, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
+ // DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
+ DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt);
+
+ DRW_shgroup_set_instance_count(grp, 1);
+ }
+
+ {
+ psl->probe_diffuse_compute = DRW_pass_create("LightProbe Diffuse Compute", DRW_STATE_WRITE_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_diffuse_sh, psl->probe_diffuse_compute);
+#ifdef IRRADIANCE_SH_L2
+ DRW_shgroup_uniform_int(grp, "probeSize", &sldata->probes->shres, 1);
+#else
+ DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "lodFactor", &sldata->probes->lodfactor, 1);
+ DRW_shgroup_uniform_float(grp, "lodMax", &sldata->probes->lod_rt_max, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
+#endif
+ DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt);
+
+ struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call_add(grp, geom, NULL);
+ }
+
+ {
+ psl->probe_visibility_compute = DRW_pass_create("LightProbe Visibility Compute", DRW_STATE_WRITE_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_visibility_sh, psl->probe_visibility_compute);
+ DRW_shgroup_uniform_int(grp, "outputSize", &sldata->probes->shres, 1);
+ DRW_shgroup_uniform_float(grp, "visibilityRange", &sldata->probes->visibility_range, 1);
+ DRW_shgroup_uniform_float(grp, "visibilityBlur", &sldata->probes->visibility_blur, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "storedTexelSize", &sldata->probes->texel_size, 1);
+ DRW_shgroup_uniform_float(grp, "nearClip", &sldata->probes->near_clip, 1);
+ DRW_shgroup_uniform_float(grp, "farClip", &sldata->probes->far_clip, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
+ DRW_shgroup_uniform_texture(grp, "probeDepth", sldata->probe_depth_rt);
+
+ struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call_add(grp, geom, NULL);
+ }
+
+ {
+ psl->probe_grid_fill = DRW_pass_create("LightProbe Grid Floodfill", DRW_STATE_WRITE_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_grid_fill_sh, psl->probe_grid_fill);
+ DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool);
+
+ struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call_add(grp, geom, NULL);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK;
+ psl->probe_display = DRW_pass_create("LightProbe Display", state);
+
+ struct Gwn_Batch *geom = DRW_cache_sphere_get();
+ DRWShadingGroup *grp = stl->g_data->cube_display_shgrp = DRW_shgroup_instance_create(e_data.probe_cube_display_sh, psl->probe_display, geom);
+ DRW_shgroup_attrib_float(grp, "probe_id", 1); /* XXX this works because we are still uploading 4bytes and using the right stride */
+ DRW_shgroup_attrib_float(grp, "probe_location", 3);
+ DRW_shgroup_attrib_float(grp, "sphere_size", 1);
+ DRW_shgroup_uniform_float(grp, "lodCubeMax", &sldata->probes->lod_cube_max, 1);
+ DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool);
+
+ geom = DRW_cache_quad_get();
+ grp = stl->g_data->planar_display_shgrp = DRW_shgroup_instance_create(e_data.probe_planar_display_sh, psl->probe_display, geom);
+ DRW_shgroup_attrib_float(grp, "probe_id", 1); /* XXX this works because we are still uploading 4bytes and using the right stride */
+ DRW_shgroup_attrib_float(grp, "probe_mat", 16);
+ DRW_shgroup_uniform_buffer(grp, "probePlanars", &txl->planar_pool);
+ }
+
+ {
+ psl->probe_planar_downsample_ps = DRW_pass_create("LightProbe Planar Downsample", DRW_STATE_WRITE_COLOR);
+
+ struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ DRWShadingGroup *grp = stl->g_data->planar_downsample = DRW_shgroup_instance_create(e_data.probe_planar_downsample_sh, psl->probe_planar_downsample_ps, geom);
+ DRW_shgroup_uniform_buffer(grp, "source", &txl->planar_pool);
+ DRW_shgroup_uniform_float(grp, "fireflyFactor", &stl->effects->ssr_firefly_fac, 1);
+ }
+}
+
+void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
+{
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ LightProbe *probe = (LightProbe *)ob->data;
+
+ /* Step 1 find all lamps in the scene and setup them */
+ if ((probe->type == LIGHTPROBE_TYPE_CUBE && pinfo->num_cube >= MAX_PROBE) ||
+ (probe->type == LIGHTPROBE_TYPE_GRID && pinfo->num_grid >= MAX_PROBE))
+ {
+ printf("Too much probes in the scene !!!\n");
+ return;
+ }
+
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+
+ ped->num_cell = probe->grid_resolution_x * probe->grid_resolution_y * probe->grid_resolution_z;
+
+ if ((probe->type == LIGHTPROBE_TYPE_GRID) &&
+ ((pinfo->total_irradiance_samples + ped->num_cell) >= MAX_IRRADIANCE_SAMPLES))
+ {
+ printf("Too much grid samples !!!\n");
+ return;
+ }
+
+ if (ped->need_full_update) {
+ ped->need_full_update = false;
+
+ ped->need_update = true;
+ ped->probe_id = 0;
+
+ if (probe->type == LIGHTPROBE_TYPE_GRID) {
+ ped->updated_cells = 0;
+ ped->updated_lvl = 0;
+ pinfo->updated_bounce = 0;
+ pinfo->grid_initialized = false;
+ }
+ }
+
+ if (e_data.update_world) {
+ ped->need_update = true;
+ ped->updated_cells = 0;
+ ped->updated_lvl = 0;
+ ped->probe_id = 0;
+ }
+
+ if (probe->type == LIGHTPROBE_TYPE_CUBE) {
+ pinfo->probes_cube_ref[pinfo->num_cube] = ob;
+ pinfo->num_cube++;
+ }
+ else if (probe->type == LIGHTPROBE_TYPE_PLANAR) {
+ pinfo->probes_planar_ref[pinfo->num_planar] = ob;
+ pinfo->num_planar++;
+ }
+ else { /* GRID */
+ pinfo->probes_grid_ref[pinfo->num_grid] = ob;
+ pinfo->num_grid++;
+ pinfo->total_irradiance_samples += ped->num_cell;
+ }
+}
+
+/* TODO find a nice name to push it to math_matrix.c */
+static void scale_m4_v3(float R[4][4], float v[3])
+{
+ for (int i = 0; i < 4; ++i)
+ mul_v3_v3(R[i], v);
+}
+
+static void EEVEE_planar_reflections_updates(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl)
+{
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ Object *ob;
+ float mtx[4][4], normat[4][4], imat[4][4], rangemat[4][4];
+
+ float viewmat[4][4], winmat[4][4];
+ DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
+
+ zero_m4(rangemat);
+ rangemat[0][0] = rangemat[1][1] = rangemat[2][2] = 0.5f;
+ rangemat[3][0] = rangemat[3][1] = rangemat[3][2] = 0.5f;
+ rangemat[3][3] = 1.0f;
+
+ /* PLANAR REFLECTION */
+ for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); i++) {
+ LightProbe *probe = (LightProbe *)ob->data;
+ EEVEE_PlanarReflection *eplanar = &pinfo->planar_data[i];
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+
+ /* Computing mtx : matrix that mirror position around object's XY plane. */
+ normalize_m4_m4(normat, ob->obmat); /* object > world */
+ invert_m4_m4(imat, normat); /* world > object */
+
+ float reflect[3] = {1.0f, 1.0f, -1.0f}; /* XY reflection plane */
+ scale_m4_v3(imat, reflect); /* world > object > mirrored obj */
+ mul_m4_m4m4(mtx, normat, imat); /* world > object > mirrored obj > world */
+
+ /* Reflect Camera Matrix. */
+ mul_m4_m4m4(ped->viewmat, viewmat, mtx);
+
+ /* TODO FOV margin */
+ float winmat_fov[4][4];
+ copy_m4_m4(winmat_fov, winmat);
+
+ /* Apply Perspective Matrix. */
+ mul_m4_m4m4(ped->persmat, winmat_fov, ped->viewmat);
+
+ /* This is the matrix used to reconstruct texture coordinates.
+ * We use the original view matrix because it does not create
+ * visual artifacts if receiver is not perfectly aligned with
+ * the planar reflection probe. */
+ mul_m4_m4m4(eplanar->reflectionmat, winmat_fov, viewmat); /* TODO FOV margin */
+ /* Convert from [-1, 1] to [0, 1] (NDC to Texture coord). */
+ mul_m4_m4m4(eplanar->reflectionmat, rangemat, eplanar->reflectionmat);
+
+ /* TODO frustum check. */
+ ped->need_update = true;
+
+ /* Compute clip plane equation / normal. */
+ float refpoint[3];
+ copy_v3_v3(eplanar->plane_equation, ob->obmat[2]);
+ normalize_v3(eplanar->plane_equation); /* plane normal */
+ eplanar->plane_equation[3] = -dot_v3v3(eplanar->plane_equation, ob->obmat[3]);
+
+ /* Compute offset plane equation (fix missing texels near reflection plane). */
+ copy_v3_v3(ped->planer_eq_offset, eplanar->plane_equation);
+ mul_v3_v3fl(refpoint, eplanar->plane_equation, -probe->clipsta);
+ add_v3_v3(refpoint, ob->obmat[3]);
+ ped->planer_eq_offset[3] = -dot_v3v3(eplanar->plane_equation, refpoint);
+
+ /* Compute XY clip planes. */
+ normalize_v3_v3(eplanar->clip_vec_x, ob->obmat[0]);
+ normalize_v3_v3(eplanar->clip_vec_y, ob->obmat[1]);
+
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+ vec[0] = 1.0f; vec[1] = 0.0f; vec[2] = 0.0f;
+ mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+ eplanar->clip_edge_x_pos = dot_v3v3(eplanar->clip_vec_x, vec);
+
+ vec[0] = 0.0f; vec[1] = 1.0f; vec[2] = 0.0f;
+ mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+ eplanar->clip_edge_y_pos = dot_v3v3(eplanar->clip_vec_y, vec);
+
+ vec[0] = -1.0f; vec[1] = 0.0f; vec[2] = 0.0f;
+ mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+ eplanar->clip_edge_x_neg = dot_v3v3(eplanar->clip_vec_x, vec);
+
+ vec[0] = 0.0f; vec[1] = -1.0f; vec[2] = 0.0f;
+ mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+ eplanar->clip_edge_y_neg = dot_v3v3(eplanar->clip_vec_y, vec);
+
+ /* Facing factors */
+ float max_angle = max_ff(1e-2f, probe->falloff) * M_PI * 0.5f;
+ float min_angle = 0.0f;
+ eplanar->facing_scale = 1.0f / max_ff(1e-8f, cosf(min_angle) - cosf(max_angle));
+ eplanar->facing_bias = -min_ff(1.0f - 1e-8f, cosf(max_angle)) * eplanar->facing_scale;
+
+ /* Distance factors */
+ float max_dist = probe->distinf;
+ float min_dist = min_ff(1.0f - 1e-8f, 1.0f - probe->falloff) * probe->distinf;
+ eplanar->attenuation_scale = -1.0f / max_ff(1e-8f, max_dist - min_dist);
+ eplanar->attenuation_bias = max_dist * -eplanar->attenuation_scale;
+
+ /* Debug Display */
+ if (BKE_object_is_visible(ob) &&
+ DRW_state_draw_support() &&
+ (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA))
+ {
+ DRW_shgroup_call_dynamic_add(stl->g_data->planar_display_shgrp, &ped->probe_id, ob->obmat);
+ }
+ }
+}
+
+static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, EEVEE_StorageList *stl)
+{
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ Object *ob;
+
+ /* CUBE REFLECTION */
+ for (int i = 1; (ob = pinfo->probes_cube_ref[i]) && (i < MAX_PROBE); i++) {
+ LightProbe *probe = (LightProbe *)ob->data;
+ EEVEE_LightProbe *eprobe = &pinfo->probe_data[i];
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+
+ /* Update transforms */
+ copy_v3_v3(eprobe->position, ob->obmat[3]);
+
+ /* Attenuation */
+ eprobe->attenuation_type = probe->attenuation_type;
+ eprobe->attenuation_fac = 1.0f / max_ff(1e-8f, probe->falloff);
+
+ unit_m4(eprobe->attenuationmat);
+ scale_m4_fl(eprobe->attenuationmat, probe->distinf);
+ mul_m4_m4m4(eprobe->attenuationmat, ob->obmat, eprobe->attenuationmat);
+ invert_m4(eprobe->attenuationmat);
+
+ /* Parallax */
+ float dist;
+ if ((probe->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) {
+ eprobe->parallax_type = probe->parallax_type;
+ dist = probe->distpar;
+ }
+ else {
+ eprobe->parallax_type = probe->attenuation_type;
+ dist = probe->distinf;
+ }
+
+ unit_m4(eprobe->parallaxmat);
+ scale_m4_fl(eprobe->parallaxmat, dist);
+ mul_m4_m4m4(eprobe->parallaxmat, ob->obmat, eprobe->parallaxmat);
+ invert_m4(eprobe->parallaxmat);
+
+ /* Debug Display */
+ if (BKE_object_is_visible(ob) &&
+ DRW_state_draw_support() &&
+ (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA))
+ {
+ ped->probe_size = probe->data_draw_size * 0.1f;
+ DRW_shgroup_call_dynamic_add(
+ stl->g_data->cube_display_shgrp, &ped->probe_id, ob->obmat[3], &ped->probe_size);
+ }
+ }
+
+ /* IRRADIANCE GRID */
+ int offset = 1; /* to account for the world probe */
+ for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_GRID); i++) {
+ LightProbe *probe = (LightProbe *)ob->data;
+ EEVEE_LightGrid *egrid = &pinfo->grid_data[i];
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+
+ /* If one grid has move we need to recompute all the lighting. */
+ if (!pinfo->grid_initialized) {
+ ped->updated_cells = 0;
+ ped->updated_lvl = 0;
+ ped->need_update = true;
+ }
+
+ /* Add one for level 0 */
+ ped->max_lvl = 1.0f + floorf(log2f((float)MAX3(probe->grid_resolution_x,
+ probe->grid_resolution_y,
+ probe->grid_resolution_z)));
+
+ egrid->offset = offset;
+ float fac = 1.0f / max_ff(1e-8f, probe->falloff);
+ egrid->attenuation_scale = fac / max_ff(1e-8f, probe->distinf);
+ egrid->attenuation_bias = fac;
+
+ /* Set offset for the next grid */
+ offset += ped->num_cell;
+
+ /* Update transforms */
+ float cell_dim[3], half_cell_dim[3];
+ cell_dim[0] = 2.0f / (float)(probe->grid_resolution_x);
+ cell_dim[1] = 2.0f / (float)(probe->grid_resolution_y);
+ cell_dim[2] = 2.0f / (float)(probe->grid_resolution_z);
+
+ mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f);
+
+ /* Matrix converting world space to cell ranges. */
+ invert_m4_m4(egrid->mat, ob->obmat);
+
+ /* First cell. */
+ copy_v3_fl(egrid->corner, -1.0f);
+ add_v3_v3(egrid->corner, half_cell_dim);
+ mul_m4_v3(ob->obmat, egrid->corner);
+
+ /* Opposite neighbor cell. */
+ copy_v3_fl3(egrid->increment_x, cell_dim[0], 0.0f, 0.0f);
+ add_v3_v3(egrid->increment_x, half_cell_dim);
+ add_v3_fl(egrid->increment_x, -1.0f);
+ mul_m4_v3(ob->obmat, egrid->increment_x);
+ sub_v3_v3(egrid->increment_x, egrid->corner);
+
+ copy_v3_fl3(egrid->increment_y, 0.0f, cell_dim[1], 0.0f);
+ add_v3_v3(egrid->increment_y, half_cell_dim);
+ add_v3_fl(egrid->increment_y, -1.0f);
+ mul_m4_v3(ob->obmat, egrid->increment_y);
+ sub_v3_v3(egrid->increment_y, egrid->corner);
+
+ copy_v3_fl3(egrid->increment_z, 0.0f, 0.0f, cell_dim[2]);
+ add_v3_v3(egrid->increment_z, half_cell_dim);
+ add_v3_fl(egrid->increment_z, -1.0f);
+ mul_m4_v3(ob->obmat, egrid->increment_z);
+ sub_v3_v3(egrid->increment_z, egrid->corner);
+
+ copy_v3_v3_int(egrid->resolution, &probe->grid_resolution_x);
+
+ /* Visibility bias */
+ egrid->visibility_bias = 0.05f * probe->vis_bias;
+ egrid->visibility_bleed = probe->vis_bleedbias;
+ egrid->visibility_range = max_ff(max_ff(len_v3(egrid->increment_x),
+ len_v3(egrid->increment_y)),
+ len_v3(egrid->increment_z)) + 1.0f;
+
+ /* Debug Display */
+ if (BKE_object_is_visible(ob) &&
+ DRW_state_draw_support() &&
+ (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA))
+ {
+ struct Gwn_Batch *geom = DRW_cache_sphere_get();
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_grid_display_sh, psl->probe_display, geom);
+ DRW_shgroup_set_instance_count(grp, ped->num_cell);
+ DRW_shgroup_uniform_int(grp, "offset", &egrid->offset, 1);
+ DRW_shgroup_uniform_ivec3(grp, "grid_resolution", egrid->resolution, 1);
+ DRW_shgroup_uniform_vec3(grp, "corner", egrid->corner, 1);
+ DRW_shgroup_uniform_vec3(grp, "increment_x", egrid->increment_x, 1);
+ DRW_shgroup_uniform_vec3(grp, "increment_y", egrid->increment_y, 1);
+ DRW_shgroup_uniform_vec3(grp, "increment_z", egrid->increment_z, 1);
+ DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool);
+ DRW_shgroup_uniform_float(grp, "sphere_size", &probe->data_draw_size, 1);
+ }
+ }
+}
+
+void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ Object *ob;
+
+ /* Setup enough layers. */
+ /* Free textures if number mismatch. */
+ if (pinfo->num_cube != pinfo->cache_num_cube) {
+ DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
+ }
+
+ if (pinfo->num_planar != pinfo->cache_num_planar) {
+ DRW_TEXTURE_FREE_SAFE(vedata->txl->planar_pool);
+ DRW_TEXTURE_FREE_SAFE(vedata->txl->planar_depth);
+ pinfo->cache_num_planar = pinfo->num_planar;
+ }
+
+ int irr_size[3];
+ irradiance_pool_size_get(pinfo->irradiance_vis_size, pinfo->total_irradiance_samples, irr_size);
+
+ if ((irr_size[0] != pinfo->cache_irradiance_size[0]) ||
+ (irr_size[1] != pinfo->cache_irradiance_size[1]) ||
+ (irr_size[2] != pinfo->cache_irradiance_size[2]))
+ {
+ DRW_TEXTURE_FREE_SAFE(sldata->irradiance_pool);
+ DRW_TEXTURE_FREE_SAFE(sldata->irradiance_rt);
+ copy_v3_v3_int(pinfo->cache_irradiance_size, irr_size);
+ }
+
+ /* XXX this should be run each frame as it ensure planar_depth is set */
+ planar_pool_ensure_alloc(vedata, pinfo->num_planar);
+
+ /* Setup planar filtering pass */
+ DRW_shgroup_set_instance_count(stl->g_data->planar_downsample, pinfo->num_planar);
+
+ if (!sldata->probe_pool) {
+ sldata->probe_pool = DRW_texture_create_2D_array(pinfo->cubemap_res, pinfo->cubemap_res, max_ff(1, pinfo->num_cube),
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
+ if (sldata->probe_filter_fb) {
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+ }
+
+ /* Tag probes to refresh */
+ e_data.update_world |= PROBE_UPDATE_CUBE;
+ e_data.world_ready_to_shade = false;
+ pinfo->num_render_cube = 0;
+ pinfo->cache_num_cube = pinfo->num_cube;
+
+ for (int i = 1; (ob = pinfo->probes_cube_ref[i]) && (i < MAX_PROBE); i++) {
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+ ped->need_update = true;
+ ped->ready_to_shade = false;
+ ped->probe_id = 0;
+ }
+ }
+
+ DRWFboTexture tex_filter = {&sldata->probe_pool, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
+
+ DRW_framebuffer_init(&sldata->probe_filter_fb, &draw_engine_eevee_type, pinfo->cubemap_res, pinfo->cubemap_res, &tex_filter, 1);
+
+
+#ifdef IRRADIANCE_SH_L2
+ /* we need a signed format for Spherical Harmonics */
+ int irradiance_format = DRW_TEX_RGBA_16;
+#else
+ int irradiance_format = DRW_TEX_RGBA_8;
+#endif
+
+ if (!sldata->irradiance_pool || !sldata->irradiance_rt) {
+ if (!sldata->irradiance_pool) {
+ sldata->irradiance_pool = DRW_texture_create_2D_array(irr_size[0], irr_size[1], irr_size[2],
+ irradiance_format, DRW_TEX_FILTER, NULL);
+ }
+ if (!sldata->irradiance_rt) {
+ sldata->irradiance_rt = DRW_texture_create_2D_array(irr_size[0], irr_size[1], irr_size[2],
+ irradiance_format, DRW_TEX_FILTER, NULL);
+ }
+ pinfo->num_render_grid = 0;
+ pinfo->updated_bounce = 0;
+ pinfo->grid_initialized = false;
+ e_data.update_world |= PROBE_UPDATE_GRID;
+
+ for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_PROBE); i++) {
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+ ped->need_update = true;
+ ped->updated_cells = 0;
+ }
+ }
+
+ if (pinfo->num_render_grid > pinfo->num_grid) {
+ /* This can happen when deleting a probe. */
+ pinfo->num_render_grid = pinfo->num_grid;
+ }
+
+ EEVEE_lightprobes_updates(sldata, vedata->psl, vedata->stl);
+ EEVEE_planar_reflections_updates(sldata, vedata->stl);
+
+ DRW_uniformbuffer_update(sldata->probe_ubo, &sldata->probes->probe_data);
+ DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data);
+ DRW_uniformbuffer_update(sldata->planar_ubo, &sldata->probes->planar_data);
+}
+
+static void downsample_planar(void *vedata, int level)
+{
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+
+ const float *size = DRW_viewport_size_get();
+ copy_v2_v2(stl->g_data->texel_size, size);
+ for (int i = 0; i < level - 1; ++i) {
+ stl->g_data->texel_size[0] /= 2.0f;
+ stl->g_data->texel_size[1] /= 2.0f;
+ min_ff(floorf(stl->g_data->texel_size[0]), 1.0f);
+ min_ff(floorf(stl->g_data->texel_size[1]), 1.0f);
+ }
+ invert_v2(stl->g_data->texel_size);
+
+ DRW_draw_pass(psl->probe_planar_downsample_ps);
+}
+
+/* Glossy filter probe_rt to probe_pool at index probe_idx */
+static void glossy_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int probe_idx)
+{
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+
+ /* Max lod used from the render target probe */
+ pinfo->lod_rt_max = floorf(log2f(pinfo->target_size)) - 2.0f;
+
+ /* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */
+ /* Bind next framebuffer to be able to gen. mips for probe_rt. */
+ DRW_framebuffer_bind(sldata->probe_filter_fb);
+ EEVEE_downsample_cube_buffer(vedata, sldata->probe_filter_fb, sldata->probe_rt, (int)(pinfo->lod_rt_max));
+
+ /* 3 - Render to probe array to the specified layer, do prefiltering. */
+ /* Detach to rebind the right mipmap. */
+ DRW_framebuffer_texture_detach(sldata->probe_pool);
+ float mipsize = pinfo->cubemap_res;
+ const int maxlevel = (int)floorf(log2f(pinfo->cubemap_res));
+ const int min_lod_level = 3;
+ for (int i = 0; i < maxlevel - min_lod_level; i++) {
+ float bias = (i == 0) ? -1.0f : 1.0f;
+ pinfo->texel_size = 1.0f / mipsize;
+ pinfo->padding_size = powf(2.0f, (float)(maxlevel - min_lod_level - 1 - i));
+ /* XXX : WHY THE HECK DO WE NEED THIS ??? */
+ /* padding is incorrect without this! float precision issue? */
+ if (pinfo->padding_size > 32) {
+ pinfo->padding_size += 5;
+ }
+ if (pinfo->padding_size > 16) {
+ pinfo->padding_size += 4;
+ }
+ else if (pinfo->padding_size > 8) {
+ pinfo->padding_size += 2;
+ }
+ else if (pinfo->padding_size > 4) {
+ pinfo->padding_size += 1;
+ }
+ pinfo->layer = probe_idx;
+ pinfo->roughness = (float)i / ((float)maxlevel - 4.0f);
+ pinfo->roughness *= pinfo->roughness; /* Disney Roughness */
+ pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */
+ CLAMP(pinfo->roughness, 1e-8f, 0.99999f); /* Avoid artifacts */
+
+#if 1 /* Variable Sample count (fast) */
+ switch (i) {
+ case 0: pinfo->samples_ct = 1.0f; break;
+ case 1: pinfo->samples_ct = 16.0f; break;
+ case 2: pinfo->samples_ct = 32.0f; break;
+ case 3: pinfo->samples_ct = 64.0f; break;
+ default: pinfo->samples_ct = 128.0f; break;
+ }
+#else /* Constant Sample count (slow) */
+ pinfo->samples_ct = 1024.0f;
+#endif
+
+ pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
+ pinfo->lodfactor = bias + 0.5f * log((float)(pinfo->target_size * pinfo->target_size) * pinfo->invsamples_ct) / log(2);
+
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, i);
+ DRW_framebuffer_viewport_size(sldata->probe_filter_fb, 0, 0, mipsize, mipsize);
+ DRW_draw_pass(psl->probe_glossy_compute);
+ DRW_framebuffer_texture_detach(sldata->probe_pool);
+
+ mipsize /= 2;
+ CLAMP_MIN(mipsize, 1);
+ }
+ /* For shading, save max level of the octahedron map */
+ pinfo->lod_cube_max = (float)(maxlevel - min_lod_level) - 1.0f;
+
+ /* reattach to have a valid framebuffer. */
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+}
+
+/* Diffuse filter probe_rt to irradiance_pool at index probe_idx */
+static void diffuse_filter_probe(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int offset,
+ float clipsta, float clipend, float vis_range, float vis_blur)
+{
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+
+ int pool_size[3];
+ irradiance_pool_size_get(pinfo->irradiance_vis_size, pinfo->total_irradiance_samples, pool_size);
+
+ /* find cell position on the virtual 3D texture */
+ /* NOTE : Keep in sync with load_irradiance_cell() */
+#if defined(IRRADIANCE_SH_L2)
+ int size[2] = {3, 3};
+#elif defined(IRRADIANCE_CUBEMAP)
+ int size[2] = {8, 8};
+ pinfo->samples_ct = 1024.0f;
+#elif defined(IRRADIANCE_HL2)
+ int size[2] = {3, 2};
+ pinfo->samples_ct = 1024.0f;
+#endif
+
+ int cell_per_row = pool_size[0] / size[0];
+ int x = size[0] * (offset % cell_per_row);
+ int y = size[1] * (offset / cell_per_row);
+
+#ifndef IRRADIANCE_SH_L2
+ /* Tweaking parameters to balance perf. vs precision */
+ const float bias = 0.0f;
+ pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
+ pinfo->lodfactor = bias + 0.5f * log((float)(pinfo->target_size * pinfo->target_size) * pinfo->invsamples_ct) / log(2);
+ pinfo->lod_rt_max = floorf(log2f(pinfo->target_size)) - 2.0f;
+#else
+ pinfo->shres = 32; /* Less texture fetches & reduce branches */
+ pinfo->lod_rt_max = 2.0f; /* Improve cache reuse */
+#endif
+
+ /* 4 - Compute spherical harmonics */
+ DRW_framebuffer_bind(sldata->probe_filter_fb);
+ EEVEE_downsample_cube_buffer(vedata, sldata->probe_filter_fb, sldata->probe_rt, (int)(pinfo->lod_rt_max));
+
+ DRW_framebuffer_texture_detach(sldata->probe_pool);
+ DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0, 0);
+
+ DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, size[0], size[1]);
+ DRW_draw_pass(psl->probe_diffuse_compute);
+
+ /* World irradiance have no visibility */
+ if (offset > 0) {
+ /* Compute visibility */
+ pinfo->samples_ct = 512.0f; /* TODO refine */
+ pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
+ pinfo->shres = pinfo->irradiance_vis_size;
+ pinfo->visibility_range = vis_range;
+ pinfo->visibility_blur = vis_blur;
+ pinfo->near_clip = -clipsta;
+ pinfo->far_clip = -clipend;
+ pinfo->texel_size = 1.0f / (float)pinfo->irradiance_vis_size;
+
+ int cell_per_col = pool_size[1] / pinfo->irradiance_vis_size;
+ cell_per_row = pool_size[0] / pinfo->irradiance_vis_size;
+ x = pinfo->irradiance_vis_size * (offset % cell_per_row);
+ y = pinfo->irradiance_vis_size * ((offset / cell_per_row) % cell_per_col);
+ int layer = 1 + ((offset / cell_per_row) / cell_per_col);
+
+ DRW_framebuffer_texture_detach(sldata->irradiance_rt);
+ DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, layer, 0);
+
+ DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, pinfo->irradiance_vis_size, sldata->probes->irradiance_vis_size);
+ DRW_draw_pass(psl->probe_visibility_compute);
+ }
+
+ /* reattach to have a valid framebuffer. */
+ DRW_framebuffer_texture_detach(sldata->irradiance_rt);
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+}
+
+/* Render the scene to the probe_rt texture. */
+static void render_scene_to_probe(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
+ const float pos[3], float clipsta, float clipend)
+{
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+
+ float winmat[4][4], wininv[4][4], posmat[4][4], tmp_ao_dist, tmp_ao_samples, tmp_ao_settings;
+
+ unit_m4(posmat);
+
+ /* Move to capture position */
+ negate_v3_v3(posmat[3], pos);
+
+ /* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */
+ sldata->probes->specular_toggle = false;
+ sldata->probes->ssr_toggle = false;
+ sldata->probes->sss_toggle = false;
+
+ /* Disable AO until we find a way to hide really bad discontinuities between cubefaces. */
+ tmp_ao_dist = stl->effects->ao_dist;
+ tmp_ao_samples = stl->effects->ao_samples;
+ tmp_ao_settings = stl->effects->ao_settings;
+ stl->effects->ao_settings = 0.0f; /* Disable AO */
+
+ /* 1 - Render to each cubeface individually.
+ * We do this instead of using geometry shader because a) it's faster,
+ * b) it's easier than fixing the nodetree shaders (for view dependant effects). */
+ pinfo->layer = 0;
+ perspective_m4(winmat, -clipsta, clipsta, -clipsta, clipsta, clipsta, clipend);
+
+ /* Avoid using the texture attached to framebuffer when rendering. */
+ /* XXX */
+ GPUTexture *tmp_planar_pool = txl->planar_pool;
+ GPUTexture *tmp_minz = stl->g_data->minzbuffer;
+ GPUTexture *tmp_maxz = txl->maxzbuffer;
+ txl->planar_pool = e_data.planar_pool_placeholder;
+ stl->g_data->minzbuffer = e_data.depth_placeholder;
+ txl->maxzbuffer = e_data.depth_placeholder;
+
+ /* Detach to rebind the right cubeface. */
+ DRW_framebuffer_bind(sldata->probe_fb);
+ DRW_framebuffer_texture_detach(sldata->probe_rt);
+ DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
+ for (int i = 0; i < 6; ++i) {
+ float viewmat[4][4], persmat[4][4];
+ float viewinv[4][4], persinv[4][4];
+
+ /* Setup custom matrices */
+ mul_m4_m4m4(viewmat, cubefacemat[i], posmat);
+ mul_m4_m4m4(persmat, winmat, viewmat);
+ invert_m4_m4(persinv, persmat);
+ invert_m4_m4(viewinv, viewmat);
+ invert_m4_m4(wininv, winmat);
+
+ DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
+ DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV);
+
+ /* Be sure that cascaded shadow maps are updated. */
+ EEVEE_draw_shadows(sldata, psl);
+
+ DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_rt, 0, i, 0);
+ DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, i, 0);
+ DRW_framebuffer_viewport_size(sldata->probe_fb, 0, 0, pinfo->target_size, pinfo->target_size);
+
+ DRW_framebuffer_clear(false, true, false, NULL, 1.0);
+
+ /* Depth prepass */
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
+
+ DRW_draw_pass(psl->probe_background);
+
+ // EEVEE_create_minmax_buffer(vedata, sldata->probe_depth_rt);
+
+ /* Rebind Planar FB */
+ DRW_framebuffer_bind(sldata->probe_fb);
+
+ /* Shading pass */
+ EEVEE_draw_default_passes(psl);
+ DRW_draw_pass(psl->material_pass);
+ DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
+
+ DRW_framebuffer_texture_detach(sldata->probe_rt);
+ DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
+ }
+ DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_rt, 0, 0);
+ DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, 0);
+
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_unset(DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_unset(DRW_MAT_VIEWINV);
+ DRW_viewport_matrix_override_unset(DRW_MAT_WIN);
+ DRW_viewport_matrix_override_unset(DRW_MAT_WININV);
+
+ /* Restore */
+ pinfo->specular_toggle = true;
+ pinfo->ssr_toggle = true;
+ pinfo->sss_toggle = true;
+ txl->planar_pool = tmp_planar_pool;
+ stl->g_data->minzbuffer = tmp_minz;
+ txl->maxzbuffer = tmp_maxz;
+ stl->effects->ao_dist = tmp_ao_dist;
+ stl->effects->ao_samples = tmp_ao_samples;
+ stl->effects->ao_settings = tmp_ao_settings;
+}
+
+static void render_scene_to_planar(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, int layer,
+ float (*viewmat)[4], float (*persmat)[4],
+ float clip_plane[4])
+{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_PassList *psl = vedata->psl;
+
+ float viewinv[4][4];
+ float persinv[4][4];
+
+ invert_m4_m4(viewinv, viewmat);
+ invert_m4_m4(persinv, persmat);
+
+ DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
+
+ /* Since we are rendering with an inverted view matrix, we need
+ * to invert the facing for backface culling to be the same. */
+ DRW_state_invert_facing();
+
+ /* Be sure that cascaded shadow maps are updated. */
+ EEVEE_draw_shadows(sldata, psl);
+
+ DRW_state_clip_planes_add(clip_plane);
+
+ /* Attach depth here since it's a DRW_TEX_TEMP */
+ DRW_framebuffer_texture_layer_attach(fbl->planarref_fb, txl->planar_depth, 0, layer, 0);
+ DRW_framebuffer_texture_layer_attach(fbl->planarref_fb, txl->planar_pool, 0, layer, 0);
+ DRW_framebuffer_bind(fbl->planarref_fb);
+
+ DRW_framebuffer_clear(false, true, false, NULL, 1.0);
+
+ /* Turn off ssr to avoid black specular */
+ /* TODO : Enable SSR in planar reflections? (Would be very heavy) */
+ sldata->probes->ssr_toggle = false;
+ sldata->probes->sss_toggle = false;
+
+ /* Avoid using the texture attached to framebuffer when rendering. */
+ /* XXX */
+ GPUTexture *tmp_planar_pool = txl->planar_pool;
+ GPUTexture *tmp_planar_depth = txl->planar_depth;
+ txl->planar_pool = e_data.planar_pool_placeholder;
+ txl->planar_depth = e_data.depth_array_placeholder;
+
+ /* Depth prepass */
+ DRW_draw_pass(psl->depth_pass_clip);
+ DRW_draw_pass(psl->depth_pass_clip_cull);
+
+ /* Background */
+ DRW_draw_pass(psl->probe_background);
+
+ EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer);
+
+ /* Compute GTAO Horizons */
+ EEVEE_occlusion_compute(sldata, vedata);
+
+ /* Rebind Planar FB */
+ DRW_framebuffer_bind(fbl->planarref_fb);
+
+ /* Shading pass */
+ EEVEE_draw_default_passes(psl);
+ DRW_draw_pass(psl->material_pass);
+ DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
+
+ DRW_state_invert_facing();
+ DRW_state_clip_planes_reset();
+
+ /* Restore */
+ sldata->probes->ssr_toggle = true;
+ sldata->probes->sss_toggle = true;
+ txl->planar_pool = tmp_planar_pool;
+ txl->planar_depth = tmp_planar_depth;
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_unset(DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_unset(DRW_MAT_VIEWINV);
+
+ DRW_framebuffer_texture_detach(txl->planar_pool);
+ DRW_framebuffer_texture_detach(txl->planar_depth);
+}
+
+static void render_world_to_probe(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
+{
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ float winmat[4][4], wininv[4][4];
+
+ /* 1 - Render to cubemap target using geometry shader. */
+ /* For world probe, we don't need to clear since we render the background directly. */
+ pinfo->layer = 0;
+
+ perspective_m4(winmat, -0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 1.0f);
+ invert_m4_m4(wininv, winmat);
+
+ /* Detach to rebind the right cubeface. */
+ DRW_framebuffer_bind(sldata->probe_fb);
+ DRW_framebuffer_texture_detach(sldata->probe_rt);
+ DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
+ for (int i = 0; i < 6; ++i) {
+ float viewmat[4][4], persmat[4][4];
+ float viewinv[4][4], persinv[4][4];
+
+ DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_rt, 0, i, 0);
+ DRW_framebuffer_viewport_size(sldata->probe_fb, 0, 0, pinfo->target_size, pinfo->target_size);
+
+ /* Setup custom matrices */
+ copy_m4_m4(viewmat, cubefacemat[i]);
+ mul_m4_m4m4(persmat, winmat, viewmat);
+ invert_m4_m4(persinv, persmat);
+ invert_m4_m4(viewinv, viewmat);
+
+ DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
+ DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV);
+
+ DRW_draw_pass(psl->probe_background);
+
+ DRW_framebuffer_texture_detach(sldata->probe_rt);
+ }
+ DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_rt, 0, 0);
+ DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, 0);
+
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_unset(DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_unset(DRW_MAT_VIEWINV);
+ DRW_viewport_matrix_override_unset(DRW_MAT_WIN);
+ DRW_viewport_matrix_override_unset(DRW_MAT_WININV);
+}
+
+static void lightprobe_cell_grid_location_get(EEVEE_LightGrid *egrid, int cell_idx, float r_local_cell[3])
+{
+ /* Keep in sync with lightprobe_grid_display_vert */
+ r_local_cell[2] = (float)(cell_idx % egrid->resolution[2]);
+ r_local_cell[1] = (float)((cell_idx / egrid->resolution[2]) % egrid->resolution[1]);
+ r_local_cell[0] = (float)(cell_idx / (egrid->resolution[2] * egrid->resolution[1]));
+}
+
+static void lightprobe_cell_world_location_get(EEVEE_LightGrid *egrid, float local_cell[3], float r_pos[3])
+{
+ float tmp[3];
+
+ copy_v3_v3(r_pos, egrid->corner);
+ mul_v3_v3fl(tmp, egrid->increment_x, local_cell[0]);
+ add_v3_v3(r_pos, tmp);
+ mul_v3_v3fl(tmp, egrid->increment_y, local_cell[1]);
+ add_v3_v3(r_pos, tmp);
+ mul_v3_v3fl(tmp, egrid->increment_z, local_cell[2]);
+ add_v3_v3(r_pos, tmp);
+}
+
+static void lightprobes_refresh_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ render_world_to_probe(sldata, psl);
+ if (e_data.update_world & PROBE_UPDATE_CUBE) {
+ glossy_filter_probe(sldata, vedata, psl, 0);
+ }
+ if (e_data.update_world & PROBE_UPDATE_GRID) {
+ diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0);
+ SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
+ DRW_framebuffer_texture_detach(sldata->probe_pool);
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ DRW_draw_pass(psl->probe_grid_fill);
+ DRW_framebuffer_texture_detach(sldata->irradiance_rt);
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+ }
+ e_data.update_world = 0;
+ if (!e_data.world_ready_to_shade) {
+ e_data.world_ready_to_shade = true;
+ pinfo->num_render_cube = 1;
+ pinfo->num_render_grid = 1;
+ }
+ DRW_viewport_request_redraw();
+}
+
+static void lightprobes_refresh_initialize_grid(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ EEVEE_PassList *psl = vedata->psl;
+ if (pinfo->grid_initialized) {
+ /* Grid is already initialized, nothing to do. */
+ return;
+ }
+ DRW_framebuffer_texture_detach(sldata->probe_pool);
+ /* Flood fill with world irradiance. */
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ DRW_framebuffer_bind(sldata->probe_filter_fb);
+ DRW_draw_pass(psl->probe_grid_fill);
+ DRW_framebuffer_texture_detach(sldata->irradiance_rt);
+
+ SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ DRW_draw_pass(psl->probe_grid_fill);
+
+ DRW_framebuffer_texture_detach(sldata->irradiance_rt);
+ SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
+ /* Reattach to have a valid framebuffer. */
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+ pinfo->grid_initialized = true;
+}
+
+static void lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_TextureList *txl = vedata->txl;
+ Object *ob;
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); i++) {
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+ if (!ped->need_update) {
+ continue;
+ }
+ /* Temporary Remove all planar reflections (avoid lag effect). */
+ int tmp_num_planar = pinfo->num_planar;
+ pinfo->num_planar = 0;
+ render_scene_to_planar(sldata, vedata, i, ped->viewmat, ped->persmat, ped->planer_eq_offset);
+ /* Restore */
+ pinfo->num_planar = tmp_num_planar;
+ ped->need_update = false;
+ ped->probe_id = i;
+ }
+ /* If there is at least one planar probe */
+ if (pinfo->num_planar > 0 && (vedata->stl->effects->enabled_effects & EFFECT_SSR) != 0) {
+ const int max_lod = 9;
+ DRW_stats_group_start("Planar Probe Downsample");
+ DRW_framebuffer_recursive_downsample(vedata->fbl->downsample_fb, txl->planar_pool, max_lod, &downsample_planar, vedata);
+ /* For shading, save max level of the planar map */
+ pinfo->lod_planar_max = (float)(max_lod);
+ DRW_stats_group_end();
+ }
+}
+
+static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ Object *ob;
+ for (int i = 1; (ob = pinfo->probes_cube_ref[i]) && (i < MAX_PROBE); i++) {
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+ if (!ped->need_update) {
+ continue;
+ }
+ LightProbe *prb = (LightProbe *)ob->data;
+ render_scene_to_probe(sldata, vedata, ob->obmat[3], prb->clipsta, prb->clipend);
+ glossy_filter_probe(sldata, vedata, psl, i);
+ ped->need_update = false;
+ ped->probe_id = i;
+ if (!ped->ready_to_shade) {
+ pinfo->num_render_cube++;
+ ped->ready_to_shade = true;
+ }
+#if 0
+ printf("Update Cubemap %d\n", i);
+#endif
+ DRW_viewport_request_redraw();
+ /* Do not let this frame accumulate. */
+ stl->effects->taa_current_sample = 1;
+
+ /* Only do one probe per frame */
+ lightprobes_refresh_planar(sldata, vedata);
+ return;
+ }
+}
+
+static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ Object *ob;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ RegionView3D *rv3d = draw_ctx->rv3d;
+
+ if (draw_ctx->evil_C != NULL) {
+ /* Only compute probes if not navigating or in playback */
+ struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
+ if (((rv3d->rflag & RV3D_NAVIGATING) != 0) || ED_screen_animation_no_scrub(wm) != NULL) {
+ lightprobes_refresh_planar(sldata, vedata);
+ return;
+ }
+ }
+ /* Make sure grid is initialized. */
+ lightprobes_refresh_initialize_grid(sldata, vedata);
+ /* Reflection probes depend on diffuse lighting thus on irradiance grid,
+ * so update them first. */
+ while (pinfo->updated_bounce < pinfo->num_bounce) {
+ pinfo->num_render_grid = pinfo->num_grid;
+ /* TODO(sergey): This logic can be split into smaller functions. */
+ for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_GRID); i++) {
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+ if (!ped->need_update) {
+ continue;
+ }
+ EEVEE_LightGrid *egrid = &pinfo->grid_data[i];
+ LightProbe *prb = (LightProbe *)ob->data;
+ /* Find the next cell corresponding to the current level. */
+ bool valid_cell = false;
+ int cell_id = ped->updated_cells;
+ float pos[3], grid_loc[3];
+ /* Other levels */
+ int current_stride = 1 << max_ii(0, ped->max_lvl - ped->updated_lvl);
+ int prev_stride = current_stride << 1;
+ bool do_rendering = true;
+ while (!valid_cell) {
+ cell_id = ped->updated_cells;
+ lightprobe_cell_grid_location_get(egrid, cell_id, grid_loc);
+ if (ped->updated_lvl == 0 && cell_id == 0) {
+ valid_cell = true;
+ ped->updated_cells = ped->num_cell;
+ continue;
+ }
+ else if (((((int)grid_loc[0] % current_stride) == 0) &&
+ (((int)grid_loc[1] % current_stride) == 0) &&
+ (((int)grid_loc[2] % current_stride) == 0)) &&
+ !((((int)grid_loc[0] % prev_stride) == 0) &&
+ (((int)grid_loc[1] % prev_stride) == 0) &&
+ (((int)grid_loc[2] % prev_stride) == 0)))
+ {
+ valid_cell = true;
+ }
+ ped->updated_cells++;
+ if (ped->updated_cells > ped->num_cell) {
+ do_rendering = false;
+ break;
+ }
+ }
+ if (do_rendering) {
+ lightprobe_cell_world_location_get(egrid, grid_loc, pos);
+ SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
+ /* Temporary Remove all probes. */
+ int tmp_num_render_grid = pinfo->num_render_grid;
+ int tmp_num_render_cube = pinfo->num_render_cube;
+ int tmp_num_planar = pinfo->num_planar;
+ float tmp_level_bias = egrid->level_bias;
+ pinfo->num_render_cube = 0;
+ pinfo->num_planar = 0;
+ /* Use light from previous bounce when capturing radiance. */
+ if (pinfo->updated_bounce == 0) {
+ /* But not on first bounce. */
+ pinfo->num_render_grid = 0;
+ }
+ else {
+ /* Remove bias */
+ egrid->level_bias = (float)(1 << 0);
+ DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data);
+ }
+ render_scene_to_probe(sldata, vedata, pos, prb->clipsta, prb->clipend);
+ diffuse_filter_probe(sldata, vedata, psl, egrid->offset + cell_id,
+ prb->clipsta, prb->clipend, egrid->visibility_range, prb->vis_blur);
+ /* To see what is going on. */
+ SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
+ /* Restore */
+ pinfo->num_render_cube = tmp_num_render_cube;
+ pinfo->num_planar = tmp_num_planar;
+ if (pinfo->updated_bounce == 0) {
+ pinfo->num_render_grid = tmp_num_render_grid;
+ }
+ else {
+ egrid->level_bias = tmp_level_bias;
+ DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data);
+ }
+#if 0
+ printf("Updated Grid %d : cell %d / %d, bounce %d / %d\n",
+ i, cell_id + 1, ped->num_cell, pinfo->updated_bounce + 1, pinfo->num_bounce);
+#endif
+ }
+ if (ped->updated_cells >= ped->num_cell) {
+ ped->updated_lvl++;
+ ped->updated_cells = 0;
+ if (ped->updated_lvl > ped->max_lvl) {
+ ped->need_update = false;
+ }
+ egrid->level_bias = (float)(1 << max_ii(0, ped->max_lvl - ped->updated_lvl + 1));
+ DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data);
+ }
+ /* Only do one probe per frame */
+ DRW_viewport_request_redraw();
+ /* Do not let this frame accumulate. */
+ stl->effects->taa_current_sample = 1;
+ lightprobes_refresh_planar(sldata, vedata);
+ return;
+ }
+
+ pinfo->updated_bounce++;
+ pinfo->num_render_grid = pinfo->num_grid;
+
+ if (pinfo->updated_bounce < pinfo->num_bounce) {
+ /* Retag all grids to update for next bounce */
+ for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_GRID); i++) {
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
+ ped->need_update = true;
+ ped->updated_cells = 0;
+ ped->updated_lvl = 0;
+ }
+ /* Reset the next buffer so we can see the progress. */
+ /* irradiance_rt is already the next rt because of the previous SWAP */
+ DRW_framebuffer_texture_detach(sldata->probe_pool);
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
+ DRW_framebuffer_bind(sldata->probe_filter_fb);
+ DRW_draw_pass(psl->probe_grid_fill);
+ DRW_framebuffer_texture_detach(sldata->irradiance_rt);
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+ /* Swap AFTER */
+ SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
+ }
+ }
+ /* Refresh cube probe when needed. */
+ lightprobes_refresh_cube(sldata, vedata);
+}
+
+void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ /* Render world in priority */
+ if (e_data.update_world) {
+ lightprobes_refresh_world(sldata, vedata);
+ }
+ else if (true) { /* TODO if at least one probe needs refresh */
+ lightprobes_refresh_all_no_world(sldata, vedata);
+ }
+}
+
+void EEVEE_lightprobes_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.probe_default_sh);
+ DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh);
+ DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh);
+ DRW_SHADER_FREE_SAFE(e_data.probe_filter_visibility_sh);
+ DRW_SHADER_FREE_SAFE(e_data.probe_grid_fill_sh);
+ DRW_SHADER_FREE_SAFE(e_data.probe_grid_display_sh);
+ DRW_SHADER_FREE_SAFE(e_data.probe_planar_display_sh);
+ DRW_SHADER_FREE_SAFE(e_data.probe_planar_downsample_sh);
+ DRW_SHADER_FREE_SAFE(e_data.probe_cube_display_sh);
+ DRW_TEXTURE_FREE_SAFE(e_data.hammersley);
+ DRW_TEXTURE_FREE_SAFE(e_data.planar_pool_placeholder);
+ DRW_TEXTURE_FREE_SAFE(e_data.depth_placeholder);
+ DRW_TEXTURE_FREE_SAFE(e_data.depth_array_placeholder);
+}
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
new file mode 100644
index 00000000000..22465c04cfa
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -0,0 +1,1092 @@
+/*
+ * 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 eevee_lights.c
+ * \ingroup DNA
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_dynstr.h"
+
+#include "BKE_object.h"
+
+#include "eevee_engine.h"
+#include "eevee_private.h"
+
+/* Theses are the structs stored inside Objects.
+ * It works with even if the object is in multiple layers
+ * because we don't get the same "Object *" for each layer. */
+typedef struct EEVEE_LightData {
+ short light_id, shadow_id;
+} EEVEE_LightData;
+
+typedef struct EEVEE_ShadowCubeData {
+ short light_id, shadow_id, cube_id, layer_id;
+} EEVEE_ShadowCubeData;
+
+typedef struct EEVEE_ShadowCascadeData {
+ short light_id, shadow_id, cascade_id, layer_id;
+ float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
+ float radius[MAX_CASCADE_NUM];
+} EEVEE_ShadowCascadeData;
+
+typedef struct ShadowCaster {
+ struct ShadowCaster *next, *prev;
+ void *ob;
+ bool prune;
+} ShadowCaster;
+
+static struct {
+ struct GPUShader *shadow_sh;
+ struct GPUShader *shadow_store_cube_sh[SHADOW_METHOD_MAX];
+ struct GPUShader *shadow_store_cascade_sh[SHADOW_METHOD_MAX];
+ struct GPUShader *shadow_copy_cube_sh[SHADOW_METHOD_MAX];
+ struct GPUShader *shadow_copy_cascade_sh[SHADOW_METHOD_MAX];
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_shadow_vert_glsl[];
+extern char datatoc_shadow_geom_glsl[];
+extern char datatoc_shadow_frag_glsl[];
+extern char datatoc_shadow_store_frag_glsl[];
+extern char datatoc_shadow_copy_frag_glsl[];
+extern char datatoc_concentric_samples_lib_glsl[];
+
+/* *********** FUNCTIONS *********** */
+
+void EEVEE_lights_init(EEVEE_ViewLayerData *sldata)
+{
+ const unsigned int shadow_ubo_size = sizeof(EEVEE_Shadow) * MAX_SHADOW +
+ sizeof(EEVEE_ShadowCube) * MAX_SHADOW_CUBE +
+ sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ if (!e_data.shadow_sh) {
+ e_data.shadow_sh = DRW_shader_create(
+ datatoc_shadow_vert_glsl, datatoc_shadow_geom_glsl, datatoc_shadow_frag_glsl, NULL);
+
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_concentric_samples_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_shadow_store_frag_glsl);
+ char *store_shadow_shader_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.shadow_store_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
+ store_shadow_shader_str,
+ "#define ESM\n");
+ e_data.shadow_store_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
+ store_shadow_shader_str, "#define ESM\n"
+ "#define CSM\n");
+
+ e_data.shadow_store_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
+ store_shadow_shader_str,
+ "#define VSM\n");
+ e_data.shadow_store_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
+ store_shadow_shader_str,
+ "#define VSM\n"
+ "#define CSM\n");
+
+ MEM_freeN(store_shadow_shader_str);
+
+ e_data.shadow_copy_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
+ datatoc_shadow_copy_frag_glsl,
+ "#define ESM\n"
+ "#define COPY\n");
+ e_data.shadow_copy_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
+ datatoc_shadow_copy_frag_glsl, "#define ESM\n"
+ "#define COPY\n"
+ "#define CSM\n");
+
+ e_data.shadow_copy_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
+ datatoc_shadow_copy_frag_glsl,
+ "#define VSM\n"
+ "#define COPY\n");
+ e_data.shadow_copy_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
+ datatoc_shadow_copy_frag_glsl,
+ "#define VSM\n"
+ "#define COPY\n"
+ "#define CSM\n");
+ }
+
+ if (!sldata->lamps) {
+ sldata->lamps = MEM_callocN(sizeof(EEVEE_LampsInfo), "EEVEE_LampsInfo");
+ sldata->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL);
+ sldata->shadow_ubo = DRW_uniformbuffer_create(shadow_ubo_size, NULL);
+ sldata->shadow_render_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_ShadowRender), NULL);
+ }
+
+ int sh_method = BKE_collection_engine_property_value_get_int(props, "shadow_method");
+ int sh_size = BKE_collection_engine_property_value_get_int(props, "shadow_size");
+ int sh_high_bitdepth = BKE_collection_engine_property_value_get_int(props, "shadow_high_bitdepth");
+
+ EEVEE_LampsInfo *linfo = sldata->lamps;
+ if ((linfo->shadow_size != sh_size) ||
+ (linfo->shadow_method != sh_method) ||
+ (linfo->shadow_high_bitdepth != sh_high_bitdepth))
+ {
+ BLI_assert((sh_size > 0) && (sh_size <= 8192));
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool);
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target);
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target);
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_blur);
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_blur);
+
+ linfo->shadow_high_bitdepth = sh_high_bitdepth;
+ linfo->shadow_method = sh_method;
+ linfo->shadow_size = sh_size;
+ linfo->shadow_render_data.stored_texel_size = 1.0 / (float)linfo->shadow_size;
+
+ /* Compute adequate size for the cubemap render target.
+ * The 3.0f factor is here to make sure there is no under sampling between
+ * the octahedron mapping and the cubemap. */
+ int new_cube_target_size = (int)ceil(sqrt((float)(sh_size * sh_size) / 6.0f) * 3.0f);
+
+ CLAMP(new_cube_target_size, 1, 4096);
+
+ linfo->shadow_cube_target_size = new_cube_target_size;
+ linfo->shadow_render_data.cube_texel_size = 1.0 / (float)linfo->shadow_cube_target_size;
+ }
+}
+
+void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
+{
+ EEVEE_LampsInfo *linfo = sldata->lamps;
+
+ linfo->num_light = 0;
+ linfo->num_layer = 0;
+ linfo->gpu_cube_ct = linfo->gpu_cascade_ct = linfo->gpu_shadow_ct = 0;
+ linfo->cpu_cube_ct = linfo->cpu_cascade_ct = 0;
+ memset(linfo->light_ref, 0, sizeof(linfo->light_ref));
+ memset(linfo->shadow_cube_ref, 0, sizeof(linfo->shadow_cube_ref));
+ memset(linfo->shadow_cascade_ref, 0, sizeof(linfo->shadow_cascade_ref));
+
+ {
+ psl->shadow_cube_store_pass = DRW_pass_create("Shadow Storage Pass", DRW_STATE_WRITE_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(
+ e_data.shadow_store_cube_sh[linfo->shadow_method], psl->shadow_cube_store_pass);
+ DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cube_blur);
+ DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
+ DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ }
+
+ {
+ psl->shadow_cascade_store_pass = DRW_pass_create("Shadow Cascade Storage Pass", DRW_STATE_WRITE_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(
+ e_data.shadow_store_cascade_sh[linfo->shadow_method], psl->shadow_cascade_store_pass);
+ DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cascade_blur);
+ DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
+ DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1);
+ DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ }
+
+ {
+ psl->shadow_cube_copy_pass = DRW_pass_create("Shadow Copy Pass", DRW_STATE_WRITE_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(
+ e_data.shadow_copy_cube_sh[linfo->shadow_method], psl->shadow_cube_copy_pass);
+ DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cube_target);
+ DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
+ DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
+ DRW_shgroup_uniform_int(grp, "faceId", &linfo->current_shadow_face, 1);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ }
+
+ {
+ psl->shadow_cascade_copy_pass = DRW_pass_create("Shadow Cascade Copy Pass", DRW_STATE_WRITE_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(
+ e_data.shadow_copy_cascade_sh[linfo->shadow_method], psl->shadow_cascade_copy_pass);
+ DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cascade_target);
+ DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
+ DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
+ DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ }
+
+ {
+ psl->shadow_cube_pass = DRW_pass_create(
+ "Shadow Cube Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ }
+
+ {
+ psl->shadow_cascade_pass = DRW_pass_create(
+ "Shadow Cascade Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ }
+
+ /* Reset shadow casters list */
+ BLI_freelistN(&sldata->shadow_casters);
+}
+
+void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
+{
+ EEVEE_LampsInfo *linfo = sldata->lamps;
+
+ /* Step 1 find all lamps in the scene and setup them */
+ if (linfo->num_light >= MAX_LIGHT) {
+ printf("Too much lamps in the scene !!!\n");
+ linfo->num_light = MAX_LIGHT - 1;
+ }
+ else {
+ Lamp *la = (Lamp *)ob->data;
+ EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
+
+ MEM_SAFE_FREE(led->storage);
+
+ if (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) {
+ if (la->type == LA_SUN) {
+ int sh_nbr = 1; /* TODO : MSM */
+ int cascade_nbr = MAX_CASCADE_NUM; /* TODO : Custom cascade number */
+
+ if ((linfo->gpu_cascade_ct + sh_nbr) <= MAX_SHADOW_CASCADE) {
+ /* Save Light object. */
+ linfo->shadow_cascade_ref[linfo->cpu_cascade_ct] = ob;
+
+ /* Create storage and store indices. */
+ EEVEE_ShadowCascadeData *data = MEM_mallocN(
+ sizeof(EEVEE_ShadowCascadeData), "EEVEE_ShadowCascadeData");
+ data->shadow_id = linfo->gpu_shadow_ct;
+ data->cascade_id = linfo->gpu_cascade_ct;
+ data->layer_id = linfo->num_layer;
+ led->storage = data;
+
+ /* Increment indices. */
+ linfo->gpu_shadow_ct += 1;
+ linfo->gpu_cascade_ct += sh_nbr;
+ linfo->num_layer += sh_nbr * cascade_nbr;
+
+ linfo->cpu_cascade_ct += 1;
+ }
+ }
+ else if (la->type == LA_SPOT || la->type == LA_LOCAL || la->type == LA_AREA) {
+ int sh_nbr = 1; /* TODO : MSM */
+
+ if ((linfo->gpu_cube_ct + sh_nbr) <= MAX_SHADOW_CUBE) {
+ /* Save Light object. */
+ linfo->shadow_cube_ref[linfo->cpu_cube_ct] = ob;
+
+ /* Create storage and store indices. */
+ EEVEE_ShadowCubeData *data = MEM_mallocN(
+ sizeof(EEVEE_ShadowCubeData), "EEVEE_ShadowCubeData");
+ data->shadow_id = linfo->gpu_shadow_ct;
+ data->cube_id = linfo->gpu_cube_ct;
+ data->layer_id = linfo->num_layer;
+ led->storage = data;
+
+ /* Increment indices. */
+ linfo->gpu_shadow_ct += 1;
+ linfo->gpu_cube_ct += sh_nbr;
+ linfo->num_layer += sh_nbr;
+
+ linfo->cpu_cube_ct += 1;
+ }
+ }
+ }
+
+ /* Default light without shadows */
+ if (!led->storage) {
+ led->storage = MEM_mallocN(sizeof(EEVEE_LightData), "EEVEE_LightData");
+ ((EEVEE_LightData *)led->storage)->shadow_id = -1;
+ }
+
+ ((EEVEE_LightData *)led->storage)->light_id = linfo->num_light;
+ linfo->light_ref[linfo->num_light] = ob;
+ linfo->num_light++;
+ }
+}
+
+/* Add a shadow caster to the shadowpasses */
+void EEVEE_lights_cache_shcaster_add(
+ EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, struct Gwn_Batch *geom, float (*obmat)[4])
+{
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cube_pass, geom);
+ DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
+ DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
+ DRW_shgroup_set_instance_count(grp, 6);
+
+ grp = DRW_shgroup_instance_create(e_data.shadow_sh, psl->shadow_cascade_pass, geom);
+ DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
+ DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
+ DRW_shgroup_set_instance_count(grp, MAX_CASCADE_NUM);
+}
+
+void EEVEE_lights_cache_shcaster_material_add(
+ EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, struct GPUMaterial *gpumat,
+ struct Gwn_Batch *geom, struct Object *ob, float (*obmat)[4], float *alpha_threshold)
+{
+ DRWShadingGroup *grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cube_pass, geom, ob);
+
+ if (grp == NULL) return;
+
+ DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
+ DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
+
+ if (alpha_threshold != NULL)
+ DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
+
+ DRW_shgroup_set_instance_count(grp, 6);
+
+ grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cascade_pass, geom, ob);
+ DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
+ DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
+
+ if (alpha_threshold != NULL)
+ DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
+
+ DRW_shgroup_set_instance_count(grp, MAX_CASCADE_NUM);
+}
+
+void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata)
+{
+ EEVEE_LampsInfo *linfo = sldata->lamps;
+ DRWTextureFormat shadow_pool_format = DRW_TEX_R_32;
+
+ /* Setup enough layers. */
+ /* Free textures if number mismatch. */
+ if (linfo->num_layer != linfo->cache_num_layer) {
+ DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool);
+ linfo->cache_num_layer = linfo->num_layer;
+ linfo->update_flag |= LIGHT_UPDATE_SHADOW_CUBE;
+ }
+
+ switch (linfo->shadow_method) {
+ case SHADOW_ESM: shadow_pool_format = ((linfo->shadow_high_bitdepth) ? DRW_TEX_R_32 : DRW_TEX_R_16); break;
+ case SHADOW_VSM: shadow_pool_format = ((linfo->shadow_high_bitdepth) ? DRW_TEX_RG_32 : DRW_TEX_RG_16); break;
+ default:
+ BLI_assert(!"Incorrect Shadow Method");
+ break;
+ }
+
+ if (!sldata->shadow_cube_target) {
+ /* TODO render everything on the same 2d render target using clip planes and no Geom Shader. */
+ /* Cubemaps */
+ sldata->shadow_cube_target = DRW_texture_create_cube(
+ linfo->shadow_cube_target_size, DRW_TEX_DEPTH_24, 0, NULL);
+ sldata->shadow_cube_blur = DRW_texture_create_cube(
+ linfo->shadow_cube_target_size, shadow_pool_format, DRW_TEX_FILTER, NULL);
+ }
+
+ if (!sldata->shadow_cascade_target) {
+ /* CSM */
+ sldata->shadow_cascade_target = DRW_texture_create_2D_array(
+ linfo->shadow_size, linfo->shadow_size, MAX_CASCADE_NUM, DRW_TEX_DEPTH_24, 0, NULL);
+ sldata->shadow_cascade_blur = DRW_texture_create_2D_array(
+ linfo->shadow_size, linfo->shadow_size, MAX_CASCADE_NUM, shadow_pool_format, DRW_TEX_FILTER, NULL);
+ }
+
+ /* Initialize Textures Array first so DRW_framebuffer_init just bind them. */
+ if (!sldata->shadow_pool) {
+ /* All shadows fit in this array */
+ sldata->shadow_pool = DRW_texture_create_2D_array(
+ linfo->shadow_size, linfo->shadow_size, max_ff(1, linfo->num_layer),
+ shadow_pool_format, DRW_TEX_FILTER, NULL);
+ }
+
+ /* Render FB */
+ DRWFboTexture tex_cascade = {&sldata->shadow_cube_target, DRW_TEX_DEPTH_24, 0};
+ DRW_framebuffer_init(&sldata->shadow_target_fb, &draw_engine_eevee_type,
+ linfo->shadow_size, linfo->shadow_size,
+ &tex_cascade, 1);
+
+ /* Storage FB */
+ DRWFboTexture tex_pool = {&sldata->shadow_pool, shadow_pool_format, DRW_TEX_FILTER};
+ DRW_framebuffer_init(&sldata->shadow_store_fb, &draw_engine_eevee_type,
+ linfo->shadow_size, linfo->shadow_size,
+ &tex_pool, 1);
+
+ /* Restore */
+ DRW_framebuffer_texture_detach(sldata->shadow_cube_target);
+
+ /* Update Lamps UBOs. */
+ EEVEE_lights_update(sldata);
+}
+
+/* Update buffer with lamp data */
+static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
+{
+ /* TODO only update if data changes */
+ EEVEE_LightData *evld = led->storage;
+ EEVEE_Light *evli = linfo->light_data + evld->light_id;
+ Lamp *la = (Lamp *)ob->data;
+ float mat[4][4], scale[3], power;
+
+ /* Position */
+ copy_v3_v3(evli->position, ob->obmat[3]);
+
+ /* Color */
+ copy_v3_v3(evli->color, &la->r);
+
+ /* Influence Radius */
+ evli->dist = la->dist;
+
+ /* Vectors */
+ normalize_m4_m4_ex(mat, ob->obmat, scale);
+ copy_v3_v3(evli->forwardvec, mat[2]);
+ normalize_v3(evli->forwardvec);
+ negate_v3(evli->forwardvec);
+
+ copy_v3_v3(evli->rightvec, mat[0]);
+ normalize_v3(evli->rightvec);
+
+ copy_v3_v3(evli->upvec, mat[1]);
+ normalize_v3(evli->upvec);
+
+ /* Spot size & blend */
+ if (la->type == LA_SPOT) {
+ evli->sizex = scale[0] / scale[2];
+ evli->sizey = scale[1] / scale[2];
+ evli->spotsize = cosf(la->spotsize * 0.5f);
+ evli->spotblend = (1.0f - evli->spotsize) * la->spotblend;
+ evli->radius = max_ff(0.001f, la->area_size);
+ }
+ else if (la->type == LA_AREA) {
+ evli->sizex = max_ff(0.0001f, la->area_size * scale[0] * 0.5f);
+ if (la->area_shape == LA_AREA_RECT) {
+ evli->sizey = max_ff(0.0001f, la->area_sizey * scale[1] * 0.5f);
+ }
+ else {
+ evli->sizey = max_ff(0.0001f, la->area_size * scale[1] * 0.5f);
+ }
+ }
+ else {
+ evli->radius = max_ff(0.001f, la->area_size);
+ }
+
+ /* Make illumination power constant */
+ if (la->type == LA_AREA) {
+ power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) * /* 1/(w*h*Pi) */
+ 80.0f; /* XXX : Empirical, Fit cycles power */
+ }
+ else if (la->type == LA_SPOT || la->type == LA_LOCAL) {
+ power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(4*r²*Pi²) */
+ M_PI * M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */
+
+ /* for point lights (a.k.a radius == 0.0) */
+ // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
+ }
+ else {
+ power = 1.0f;
+ }
+ mul_v3_fl(evli->color, power * la->energy);
+
+ /* Lamp Type */
+ evli->lamptype = (float)la->type;
+
+ /* No shadow by default */
+ evli->shadowid = -1.0f;
+}
+
+static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
+{
+ EEVEE_ShadowCubeData *sh_data = (EEVEE_ShadowCubeData *)led->storage;
+ EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
+ EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
+ EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + sh_data->cube_id;
+ Lamp *la = (Lamp *)ob->data;
+
+ int sh_nbr = 1; /* TODO: MSM */
+
+ for (int i = 0; i < sh_nbr; ++i) {
+ /* TODO : choose MSM sample point here. */
+ copy_v3_v3(cube_data->position, ob->obmat[3]);
+ }
+
+ ubo_data->bias = 0.05f * la->bias;
+ ubo_data->near = la->clipsta;
+ ubo_data->far = la->clipend;
+ ubo_data->exp = (linfo->shadow_method == SHADOW_VSM) ? la->bleedbias : la->bleedexp;
+
+ evli->shadowid = (float)(sh_data->shadow_id);
+ ubo_data->shadow_start = (float)(sh_data->layer_id);
+ ubo_data->data_start = (float)(sh_data->cube_id);
+ ubo_data->multi_shadow_count = (float)(sh_nbr);
+ ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */
+
+ ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
+ ubo_data->contact_bias = 0.05f * la->contact_bias;
+ ubo_data->contact_spread = la->contact_spread;
+ ubo_data->contact_thickness = la->contact_thickness;
+}
+
+#define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
+
+static void frustum_min_bounding_sphere(const float corners[8][4], float r_center[3], float *r_radius)
+{
+#if 0 /* Simple solution but waist too much space. */
+ float minvec[3], maxvec[3];
+
+ /* compute the bounding box */
+ INIT_MINMAX(minvec, maxvec);
+ for (int i = 0; i < 8; ++i) {
+ minmax_v3v3_v3(minvec, maxvec, corners[i]);
+ }
+
+ /* compute the bounding sphere of this box */
+ r_radius = len_v3v3(minvec, maxvec) * 0.5f;
+ add_v3_v3v3(r_center, minvec, maxvec);
+ mul_v3_fl(r_center, 0.5f);
+#else
+ /* Make the bouding sphere always centered on the front diagonal */
+ add_v3_v3v3(r_center, corners[4], corners[7]);
+ mul_v3_fl(r_center, 0.5f);
+ *r_radius = len_v3v3(corners[0], r_center);
+
+ /* Search the largest distance between the sphere center
+ * and the front plane corners. */
+ for (int i = 0; i < 4; ++i) {
+ float rad = len_v3v3(corners[4 + i], r_center);
+ if (rad > *r_radius) {
+ *r_radius = rad;
+ }
+ }
+#endif
+}
+
+static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
+{
+ Lamp *la = (Lamp *)ob->data;
+
+ /* Camera Matrices */
+ float persmat[4][4], persinv[4][4];
+ float viewprojmat[4][4], projinv[4][4];
+ float view_near, view_far;
+ float near_v[4] = {0.0f, 0.0f, -1.0f, 1.0f};
+ float far_v[4] = {0.0f, 0.0f, 1.0f, 1.0f};
+ bool is_persp = DRW_viewport_is_persp_get();
+ DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
+ invert_m4_m4(persinv, persmat);
+ /* FIXME : Get near / far from Draw manager? */
+ DRW_viewport_matrix_get(viewprojmat, DRW_MAT_WIN);
+ invert_m4_m4(projinv, viewprojmat);
+ mul_m4_v4(projinv, near_v);
+ mul_m4_v4(projinv, far_v);
+ view_near = near_v[2];
+ view_far = far_v[2]; /* TODO: Should be a shadow parameter */
+ if (is_persp) {
+ view_near /= near_v[3];
+ view_far /= far_v[3];
+ }
+
+ /* Lamps Matrices */
+ float viewmat[4][4], projmat[4][4];
+ int sh_nbr = 1; /* TODO : MSM */
+ int cascade_nbr = la->cascade_count;
+
+ EEVEE_ShadowCascadeData *sh_data = (EEVEE_ShadowCascadeData *)led->storage;
+ EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
+ EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
+ EEVEE_ShadowCascade *cascade_data = linfo->shadow_cascade_data + sh_data->cascade_id;
+
+ /* The technique consists into splitting
+ * the view frustum into several sub-frustum
+ * that are individually receiving one shadow map */
+
+ float csm_start, csm_end;
+
+ if (is_persp) {
+ csm_start = view_near;
+ csm_end = max_ff(view_far, -la->cascade_max_dist);
+ /* Avoid artifacts */
+ csm_end = min_ff(view_near, csm_end);
+ }
+ else {
+ csm_start = -view_far;
+ csm_end = view_far;
+ }
+
+ /* init near/far */
+ for (int c = 0; c < MAX_CASCADE_NUM; ++c) {
+ cascade_data->split_start[c] = csm_end;
+ cascade_data->split_end[c] = csm_end;
+ }
+
+ /* Compute split planes */
+ float splits_start_ndc[MAX_CASCADE_NUM];
+ float splits_end_ndc[MAX_CASCADE_NUM];
+
+ {
+ /* Nearest plane */
+ float p[4] = {1.0f, 1.0f, csm_start, 1.0f};
+ /* TODO: we don't need full m4 multiply here */
+ mul_m4_v4(viewprojmat, p);
+ splits_start_ndc[0] = p[2];
+ if (is_persp) {
+ splits_start_ndc[0] /= p[3];
+ }
+ }
+
+ {
+ /* Farthest plane */
+ float p[4] = {1.0f, 1.0f, csm_end, 1.0f};
+ /* TODO: we don't need full m4 multiply here */
+ mul_m4_v4(viewprojmat, p);
+ splits_end_ndc[cascade_nbr - 1] = p[2];
+ if (is_persp) {
+ splits_end_ndc[cascade_nbr - 1] /= p[3];
+ }
+ }
+
+ cascade_data->split_start[0] = csm_start;
+ cascade_data->split_end[cascade_nbr - 1] = csm_end;
+
+ for (int c = 1; c < cascade_nbr; ++c) {
+ /* View Space */
+ float linear_split = LERP(((float)(c) / (float)cascade_nbr), csm_start, csm_end);
+ float exp_split = csm_start * powf(csm_end / csm_start, (float)(c) / (float)cascade_nbr);
+
+ if (is_persp) {
+ cascade_data->split_start[c] = LERP(la->cascade_exponent, linear_split, exp_split);
+ }
+ else {
+ cascade_data->split_start[c] = linear_split;
+ }
+ cascade_data->split_end[c - 1] = cascade_data->split_start[c];
+
+ /* Add some overlap for smooth transition */
+ cascade_data->split_start[c] = LERP(la->cascade_fade, cascade_data->split_end[c - 1],
+ (c > 1) ? cascade_data->split_end[c - 2] : cascade_data->split_start[0]);
+
+ /* NDC Space */
+ {
+ float p[4] = {1.0f, 1.0f, cascade_data->split_start[c], 1.0f};
+ /* TODO: we don't need full m4 multiply here */
+ mul_m4_v4(viewprojmat, p);
+ splits_start_ndc[c] = p[2];
+
+ if (is_persp) {
+ splits_start_ndc[c] /= p[3];
+ }
+ }
+
+ {
+ float p[4] = {1.0f, 1.0f, cascade_data->split_end[c - 1], 1.0f};
+ /* TODO: we don't need full m4 multiply here */
+ mul_m4_v4(viewprojmat, p);
+ splits_end_ndc[c - 1] = p[2];
+
+ if (is_persp) {
+ splits_end_ndc[c - 1] /= p[3];
+ }
+ }
+ }
+
+ /* Set last cascade split fade distance into the first split_start. */
+ float prev_split = (cascade_nbr > 1) ? cascade_data->split_end[cascade_nbr - 2] : cascade_data->split_start[0];
+ cascade_data->split_start[0] = LERP(la->cascade_fade, cascade_data->split_end[cascade_nbr - 1], prev_split);
+
+ /* For each cascade */
+ for (int c = 0; c < cascade_nbr; ++c) {
+ /* Given 8 frustum corners */
+ float corners[8][4] = {
+ /* Near Cap */
+ {-1.0f, -1.0f, splits_start_ndc[c], 1.0f},
+ { 1.0f, -1.0f, splits_start_ndc[c], 1.0f},
+ {-1.0f, 1.0f, splits_start_ndc[c], 1.0f},
+ { 1.0f, 1.0f, splits_start_ndc[c], 1.0f},
+ /* Far Cap */
+ {-1.0f, -1.0f, splits_end_ndc[c], 1.0f},
+ { 1.0f, -1.0f, splits_end_ndc[c], 1.0f},
+ {-1.0f, 1.0f, splits_end_ndc[c], 1.0f},
+ { 1.0f, 1.0f, splits_end_ndc[c], 1.0f}
+ };
+
+ /* Transform them into world space */
+ for (int i = 0; i < 8; ++i) {
+ mul_m4_v4(persinv, corners[i]);
+ mul_v3_fl(corners[i], 1.0f / corners[i][3]);
+ corners[i][3] = 1.0f;
+ }
+
+
+ /* Project them into light space */
+ invert_m4_m4(viewmat, ob->obmat);
+ normalize_v3(viewmat[0]);
+ normalize_v3(viewmat[1]);
+ normalize_v3(viewmat[2]);
+
+ for (int i = 0; i < 8; ++i) {
+ mul_m4_v4(viewmat, corners[i]);
+ }
+
+ float center[3];
+ frustum_min_bounding_sphere(corners, center, &(sh_data->radius[c]));
+
+ /* Snap projection center to nearest texel to cancel shimmering. */
+ float shadow_origin[2], shadow_texco[2];
+ /* Light to texture space. */
+ mul_v2_v2fl(shadow_origin, center, linfo->shadow_size / (2.0f * sh_data->radius[c]));
+
+ /* Find the nearest texel. */
+ shadow_texco[0] = round(shadow_origin[0]);
+ shadow_texco[1] = round(shadow_origin[1]);
+
+ /* Compute offset. */
+ sub_v2_v2(shadow_texco, shadow_origin);
+ mul_v2_fl(shadow_texco, (2.0f * sh_data->radius[c]) / linfo->shadow_size); /* Texture to light space. */
+
+ /* Apply offset. */
+ add_v2_v2(center, shadow_texco);
+
+ /* Expand the projection to cover frustum range */
+ orthographic_m4(projmat,
+ center[0] - sh_data->radius[c],
+ center[0] + sh_data->radius[c],
+ center[1] - sh_data->radius[c],
+ center[1] + sh_data->radius[c],
+ la->clipsta, la->clipend);
+
+ mul_m4_m4m4(sh_data->viewprojmat[c], projmat, viewmat);
+ mul_m4_m4m4(cascade_data->shadowmat[c], texcomat, sh_data->viewprojmat[c]);
+ }
+
+ ubo_data->bias = 0.05f * la->bias;
+ ubo_data->near = la->clipsta;
+ ubo_data->far = la->clipend;
+ ubo_data->exp = (linfo->shadow_method == SHADOW_VSM) ? la->bleedbias : la->bleedexp;
+
+ evli->shadowid = (float)(sh_data->shadow_id);
+ ubo_data->shadow_start = (float)(sh_data->layer_id);
+ ubo_data->data_start = (float)(sh_data->cascade_id);
+ ubo_data->multi_shadow_count = (float)(sh_nbr);
+ ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */
+
+ ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
+ ubo_data->contact_bias = 0.05f * la->contact_bias;
+ ubo_data->contact_spread = la->contact_spread;
+ ubo_data->contact_thickness = la->contact_thickness;
+}
+
+/* Used for checking if object is inside the shadow volume. */
+static bool cube_bbox_intersect(const float cube_center[3], float cube_half_dim, const BoundBox *bb, float (*obmat)[4])
+{
+ float min[3], max[4], tmp[4][4];
+ unit_m4(tmp);
+ translate_m4(tmp, -cube_center[0], -cube_center[1], -cube_center[2]);
+ mul_m4_m4m4(tmp, tmp, obmat);
+
+ /* Just simple AABB intersection test in world space. */
+ INIT_MINMAX(min, max);
+ for (int i = 0; i < 8; ++i) {
+ float vec[3];
+ copy_v3_v3(vec, bb->vec[i]);
+ mul_m4_v3(tmp, vec);
+ minmax_v3v3_v3(min, max, vec);
+ }
+
+ if (MAX3(max[0], max[1], max[2]) < -cube_half_dim) return false;
+ if (MIN3(min[0], min[1], min[2]) > cube_half_dim) return false;
+
+ return true;
+}
+
+static ShadowCaster *search_object_in_list(ListBase *list, Object *ob)
+{
+ for (ShadowCaster *ldata = list->first; ldata; ldata = ldata->next) {
+ if (ldata->ob == ob)
+ return ldata;
+ }
+
+ return NULL;
+}
+
+static void delete_pruned_shadowcaster(EEVEE_LampEngineData *led)
+{
+ ShadowCaster *next;
+ for (ShadowCaster *ldata = led->shadow_caster_list.first; ldata; ldata = next) {
+ next = ldata->next;
+ if (ldata->prune == true) {
+ led->need_update = true;
+ BLI_freelinkN(&led->shadow_caster_list, ldata);
+ }
+ }
+}
+
+static void light_tag_shadow_update(Object *lamp, Object *ob)
+{
+ Lamp *la = lamp->data;
+ EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(lamp);
+
+ bool is_inside_range = cube_bbox_intersect(lamp->obmat[3], la->clipend, BKE_object_boundbox_get(ob), ob->obmat);
+ ShadowCaster *ldata = search_object_in_list(&led->shadow_caster_list, ob);
+
+ if (is_inside_range) {
+ if (ldata == NULL) {
+ /* Object was not a shadow caster previously but is now. Add it. */
+ ldata = MEM_callocN(sizeof(ShadowCaster), "ShadowCaster");
+ ldata->ob = ob;
+ BLI_addtail(&led->shadow_caster_list, ldata);
+ led->need_update = true;
+ }
+ else {
+ EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob);
+ if (oedata->need_update) {
+ led->need_update = true;
+ }
+ }
+ ldata->prune = false;
+ }
+ else if (ldata != NULL) {
+ /* Object was a shadow caster previously and is not anymore. Remove it. */
+ led->need_update = true;
+ BLI_freelinkN(&led->shadow_caster_list, ldata);
+ }
+}
+
+static void eevee_lights_shcaster_updated(EEVEE_ViewLayerData *sldata, Object *ob)
+{
+ Object *lamp;
+ EEVEE_LampsInfo *linfo = sldata->lamps;
+
+ /* Iterate over all shadow casting lamps to see if
+ * each of them needs update because of this object */
+ for (int i = 0; (lamp = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
+ light_tag_shadow_update(lamp, ob);
+ }
+ EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob);
+ oedata->need_update = false;
+}
+
+void EEVEE_lights_update(EEVEE_ViewLayerData *sldata)
+{
+ EEVEE_LampsInfo *linfo = sldata->lamps;
+ Object *ob;
+ int i;
+
+ /* Prune shadow casters to remove if object does not exists anymore (unprune them if object exists) */
+ Object *lamp;
+ for (i = 0; (lamp = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
+ EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(lamp);
+
+ if ((linfo->update_flag & LIGHT_UPDATE_SHADOW_CUBE) != 0) {
+ led->need_update = true;
+ }
+
+ for (ShadowCaster *ldata = led->shadow_caster_list.first; ldata; ldata = ldata->next) {
+ ldata->prune = true;
+ }
+ }
+
+ for (LinkData *ldata = sldata->shadow_casters.first; ldata; ldata = ldata->next) {
+ eevee_lights_shcaster_updated(sldata, ldata->data);
+ }
+
+ for (i = 0; (ob = linfo->light_ref[i]) && (i < MAX_LIGHT); i++) {
+ EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
+ eevee_light_setup(ob, linfo, led);
+ }
+
+ for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
+ EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
+ eevee_shadow_cube_setup(ob, linfo, led);
+ delete_pruned_shadowcaster(led);
+ }
+}
+
+/* this refresh lamps shadow buffers */
+void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
+{
+ EEVEE_LampsInfo *linfo = sldata->lamps;
+ Object *ob;
+ int i;
+ float clear_col[4] = {FLT_MAX};
+
+ /* Cube Shadow Maps */
+ DRW_stats_group_start("Cube Shadow Maps");
+ DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cube_target, 0, 0);
+ /* Render each shadow to one layer of the array */
+ for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
+ EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
+ Lamp *la = (Lamp *)ob->data;
+
+ float cube_projmat[4][4];
+ perspective_m4(cube_projmat, -la->clipsta, la->clipsta, -la->clipsta, la->clipsta, la->clipsta, la->clipend);
+
+ if (!led->need_update) {
+ continue;
+ }
+
+ EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
+ EEVEE_ShadowCubeData *evscd = (EEVEE_ShadowCubeData *)led->storage;
+
+ srd->clip_near = la->clipsta;
+ srd->clip_far = la->clipend;
+ copy_v3_v3(srd->position, ob->obmat[3]);
+ for (int j = 0; j < 6; j++) {
+ float tmp[4][4];
+
+ unit_m4(tmp);
+ negate_v3_v3(tmp[3], ob->obmat[3]);
+ mul_m4_m4m4(srd->viewmat[j], cubefacemat[j], tmp);
+
+ mul_m4_m4m4(srd->shadowmat[j], cube_projmat, srd->viewmat[j]);
+ }
+ DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
+
+ DRW_framebuffer_bind(sldata->shadow_target_fb);
+ DRW_framebuffer_clear(true, true, false, clear_col, 1.0f);
+
+ /* Render shadow cube */
+ DRW_draw_pass(psl->shadow_cube_pass);
+
+ /* 0.001f is arbitrary, but it should be relatively small so that filter size is not too big. */
+ float filter_texture_size = la->soft * 0.001f;
+ float filter_pixel_size = ceil(filter_texture_size / linfo->shadow_render_data.cube_texel_size);
+ linfo->filter_size = linfo->shadow_render_data.cube_texel_size * ((filter_pixel_size > 1.0f) ? 1.5f : 0.0f);
+
+ /* TODO: OPTI: Filter all faces in one/two draw call */
+ for (linfo->current_shadow_face = 0;
+ linfo->current_shadow_face < 6;
+ linfo->current_shadow_face++)
+ {
+ /* Copy using a small 3x3 box filter */
+ DRW_framebuffer_cubeface_attach(sldata->shadow_store_fb, sldata->shadow_cube_blur, 0, linfo->current_shadow_face, 0);
+ DRW_framebuffer_bind(sldata->shadow_store_fb);
+ DRW_draw_pass(psl->shadow_cube_copy_pass);
+ DRW_framebuffer_texture_detach(sldata->shadow_cube_blur);
+ }
+
+ /* Push it to shadowmap array */
+
+ /* Adjust constants if concentric samples change. */
+ const float max_filter_size = 7.5f;
+ const float previous_box_filter_size = 9.0f; /* Dunno why but that works. */
+ const int max_sample = 256;
+
+ if (filter_pixel_size > 2.0f) {
+ linfo->filter_size = linfo->shadow_render_data.cube_texel_size * max_filter_size * previous_box_filter_size;
+ filter_pixel_size = max_ff(0.0f, filter_pixel_size - 3.0f);
+ /* Compute number of concentric samples. Depends directly on filter size. */
+ float pix_size_sqr = filter_pixel_size * filter_pixel_size;
+ srd->shadow_samples_ct = min_ii(max_sample, 4 + 8 * (int)filter_pixel_size + 4 * (int)(pix_size_sqr));
+ }
+ else {
+ linfo->filter_size = 0.0f;
+ srd->shadow_samples_ct = 4;
+ }
+ srd->shadow_inv_samples_ct = 1.0f / (float)srd->shadow_samples_ct;
+ DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
+
+ DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, evscd->layer_id, 0);
+ DRW_framebuffer_bind(sldata->shadow_store_fb);
+ DRW_draw_pass(psl->shadow_cube_store_pass);
+
+ led->need_update = false;
+ }
+ linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE;
+
+ DRW_framebuffer_texture_detach(sldata->shadow_cube_target);
+ DRW_stats_group_end();
+
+ /* Cascaded Shadow Maps */
+ DRW_stats_group_start("Cascaded Shadow Maps");
+ DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cascade_target, 0, 0);
+ for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
+ EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
+ Lamp *la = (Lamp *)ob->data;
+
+ EEVEE_ShadowCascadeData *evscd = (EEVEE_ShadowCascadeData *)led->storage;
+ EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
+
+ eevee_shadow_cascade_setup(ob, linfo, led);
+
+ srd->clip_near = la->clipsta;
+ srd->clip_far = la->clipend;
+ for (int j = 0; j < la->cascade_count; ++j) {
+ copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
+ }
+ DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
+
+ DRW_framebuffer_bind(sldata->shadow_target_fb);
+ DRW_framebuffer_clear(false, true, false, NULL, 1.0);
+
+ /* Render shadow cascades */
+ DRW_draw_pass(psl->shadow_cascade_pass);
+
+ /* TODO: OPTI: Filter all cascade in one/two draw call */
+ for (linfo->current_shadow_cascade = 0;
+ linfo->current_shadow_cascade < la->cascade_count;
+ ++linfo->current_shadow_cascade)
+ {
+ /* 0.01f factor to convert to percentage */
+ float filter_texture_size = la->soft * 0.01f / evscd->radius[linfo->current_shadow_cascade];
+ float filter_pixel_size = ceil(linfo->shadow_size * filter_texture_size);
+
+ /* Copy using a small 3x3 box filter */
+ linfo->filter_size = linfo->shadow_render_data.stored_texel_size * ((filter_pixel_size > 1.0f) ? 1.0f : 0.0f);
+ DRW_framebuffer_texture_layer_attach(
+ sldata->shadow_store_fb, sldata->shadow_cascade_blur, 0, linfo->current_shadow_cascade, 0);
+ DRW_framebuffer_bind(sldata->shadow_store_fb);
+ DRW_draw_pass(psl->shadow_cascade_copy_pass);
+ DRW_framebuffer_texture_detach(sldata->shadow_cascade_blur);
+
+ /* Push it to shadowmap array and blur more */
+
+ /* Adjust constants if concentric samples change. */
+ const float max_filter_size = 7.5f;
+ const float previous_box_filter_size = 3.2f; /* Arbitrary: less banding */
+ const int max_sample = 256;
+
+ if (filter_pixel_size > 2.0f) {
+ linfo->filter_size = linfo->shadow_render_data.stored_texel_size * max_filter_size * previous_box_filter_size;
+ filter_pixel_size = max_ff(0.0f, filter_pixel_size - 3.0f);
+ /* Compute number of concentric samples. Depends directly on filter size. */
+ float pix_size_sqr = filter_pixel_size * filter_pixel_size;
+ srd->shadow_samples_ct = min_ii(max_sample, 4 + 8 * (int)filter_pixel_size + 4 * (int)(pix_size_sqr));
+ }
+ else {
+ linfo->filter_size = 0.0f;
+ srd->shadow_samples_ct = 4;
+ }
+ srd->shadow_inv_samples_ct = 1.0f / (float)srd->shadow_samples_ct;
+ DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
+
+ int layer = evscd->layer_id + linfo->current_shadow_cascade;
+ DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, layer, 0);
+ DRW_framebuffer_bind(sldata->shadow_store_fb);
+ DRW_draw_pass(psl->shadow_cascade_store_pass);
+ }
+ }
+
+ DRW_framebuffer_texture_detach(sldata->shadow_cascade_target);
+ DRW_stats_group_end();
+
+ DRW_uniformbuffer_update(sldata->light_ubo, &linfo->light_data);
+ DRW_uniformbuffer_update(sldata->shadow_ubo, &linfo->shadow_data); /* Update all data at once */
+}
+
+void EEVEE_lights_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.shadow_sh);
+ for (int i = 0; i < SHADOW_METHOD_MAX; ++i) {
+ DRW_SHADER_FREE_SAFE(e_data.shadow_store_cube_sh[i]);
+ DRW_SHADER_FREE_SAFE(e_data.shadow_store_cascade_sh[i]);
+ DRW_SHADER_FREE_SAFE(e_data.shadow_copy_cube_sh[i]);
+ DRW_SHADER_FREE_SAFE(e_data.shadow_copy_cascade_sh[i]);
+ }
+}
diff --git a/source/blender/draw/engines/eevee/eevee_lut.h b/source/blender/draw/engines/eevee/eevee_lut.h
new file mode 100644
index 00000000000..d706110351e
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_lut.h
@@ -0,0 +1,16411 @@
+/*
+ * ***** 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 eevee_lut.h
+ * \ingroup gpu
+ */
+
+#ifndef __EEVEE_LUT_H__
+#define __EEVEE_LUT_H__
+
+static float ltc_mat_ggx[64 * 64 * 4] = {
+ 0.000200, -0.000000, 1.000000, -0.000000, 0.000504, -0.000000, 1.000000, -0.000000, 0.002016,
+ -0.000000, 1.000000, -0.000000, 0.004535, -0.000000, 1.000000, -0.000000, 0.008063, -0.000000,
+ 1.000000, -0.000000, 0.012598, -0.000000, 1.000000, -0.000000, 0.018141, -0.000000, 1.000000,
+ -0.000000, 0.024692, -0.000000, 1.000000, -0.000000, 0.032252, -0.000000, 1.000000, -0.000000,
+ 0.040821, -0.000000, 1.000000, -0.000000, 0.050400, -0.000000, 1.000000, -0.000000, 0.060989,
+ -0.000000, 1.000000, -0.000000, 0.072591, -0.000000, 1.000000, -0.000000, 0.085206, -0.000000,
+ 1.000000, -0.000000, 0.098836, -0.000000, 1.000000, -0.000000, 0.113483, -0.000000, 1.000000,
+ -0.000000, 0.129147, -0.000000, 1.000000, -0.000000, 0.145828, -0.000000, 1.000000, -0.000000,
+ 0.163499, -0.000000, 1.000000, -0.000000, 0.181972, -0.000000, 1.000000, -0.000000, 0.199498,
+ -0.000000, 1.000000, -0.000000, 0.220031, -0.000000, 1.000000, -0.000000, 0.241588, -0.000000,
+ 1.000000, -0.000000, 0.264120, -0.000000, 1.000000, -0.000000, 0.287521, -0.000000, 1.000000,
+ -0.000000, 0.311478, -0.000000, 1.000000, -0.000000, 0.335127, -0.000000, 1.000000, -0.000000,
+ 0.359811, -0.000000, 1.000000, -0.000000, 0.386446, -0.000000, 1.000000, -0.000000, 0.413161,
+ -0.000000, 1.000000, -0.000000, 0.439142, -0.000000, 1.000000, -0.000000, 0.467039, -0.000000,
+ 1.000000, -0.000000, 0.495170, -0.000000, 1.000000, -0.000000, 0.522324, -0.000000, 1.000000,
+ -0.000000, 0.551482, -0.000000, 1.000000, -0.000000, 0.579621, -0.000000, 1.000000, -0.000000,
+ 0.608255, -0.000000, 1.000000, -0.000000, 0.636515, -0.000000, 1.000000, -0.000000, 0.664835,
+ -0.000000, 1.000000, -0.000000, 0.692549, -0.000000, 1.000000, -0.000000, 0.720375, -0.000000,
+ 1.000000, -0.000000, 0.747238, -0.000000, 1.000000, -0.000000, 0.773956, -0.000000, 1.000000,
+ -0.000000, 0.799879, -0.000000, 1.000000, -0.000000, 0.824889, -0.000000, 1.000000, -0.000000,
+ 0.849357, -0.000000, 1.000000, -0.000000, 0.873016, -0.000000, 1.000000, -0.000000, 0.895670,
+ -0.000000, 1.000000, -0.000000, 0.917194, -0.000000, 1.000000, -0.000000, 0.937978, -0.000000,
+ 1.000000, -0.000000, 0.957872, -0.000000, 1.000000, -0.000000, 0.976736, -0.000000, 1.000000,
+ -0.000000, 0.994433, -0.000000, 1.000000, -0.000000, 1.011206, -0.000000, 1.000000, -0.000000,
+ 1.026820, -0.000000, 1.000000, -0.000000, 1.041720, -0.000000, 1.000000, -0.000000, 1.055657,
+ -0.000000, 1.000000, -0.000000, 1.068642, -0.000000, 1.000000, -0.000000, 1.080646, -0.000000,
+ 1.000000, -0.000000, 1.091637, -0.000000, 1.000000, -0.000000, 1.101837, -0.000000, 1.000000,
+ -0.000000, 1.111292, -0.000000, 1.000000, -0.000000, 1.120025, -0.000000, 1.000000, -0.000000,
+ 1.127918, -0.000000, 1.000000, -0.000000, 0.000200, -0.000005, 1.000623, 0.024938, 0.000504,
+ -0.000013, 1.000643, 0.024938, 0.002016, -0.000050, 1.000618, 0.024938, 0.004535, -0.000113,
+ 1.000621, 0.024938, 0.008063, -0.000201, 1.000746, 0.024938, 0.012596, -0.000314, 1.000463,
+ 0.024937, 0.018140, -0.000452, 1.000511, 0.024939, 0.024693, -0.000616, 1.000541, 0.024938,
+ 0.032253, -0.000804, 1.000684, 0.024938, 0.040815, -0.001018, 1.000524, 0.024940, 0.050399,
+ -0.001257, 1.000582, 0.024937, 0.060989, -0.001521, 1.000655, 0.024937, 0.072591, -0.001810,
+ 1.000608, 0.024938, 0.085204, -0.002125, 1.000622, 0.024939, 0.098835, -0.002465, 1.000632,
+ 0.024937, 0.113483, -0.002830, 1.000640, 0.024939, 0.129143, -0.003220, 1.000568, 0.024938,
+ 0.145830, -0.003633, 1.000635, 0.024938, 0.163497, -0.004062, 1.000626, 0.024938, 0.181956,
+ -0.004424, 1.000612, 0.024924, 0.199791, -0.004593, 1.000627, 0.024890, 0.220029, -0.005480,
+ 1.000594, 0.024935, 0.241586, -0.006010, 1.000616, 0.024933, 0.264115, -0.006550, 1.000607,
+ 0.024927, 0.287514, -0.007072, 1.000595, 0.024909, 0.311455, -0.007472, 1.000616, 0.024872,
+ 0.335083, -0.007491, 1.000589, 0.024755, 0.359805, -0.008810, 1.000601, 0.024877, 0.386438,
+ -0.009282, 1.000640, 0.024824, 0.413131, -0.009534, 1.000599, 0.024708, 0.439249, -0.009701,
+ 1.000497, 0.024573, 0.466997, -0.010878, 1.000467, 0.024652, 0.495138, -0.010959, 1.000539,
+ 0.024455, 0.522654, -0.011386, 1.000518, 0.024318, 0.551415, -0.012022, 1.000533, 0.024216,
+ 0.579610, -0.011805, 1.000495, 0.023867, 0.608185, -0.012773, 1.000474, 0.023834, 0.636492,
+ -0.012377, 1.000488, 0.023327, 0.664826, -0.013172, 1.000576, 0.023205, 0.692674, -0.012847,
+ 1.000505, 0.022708, 0.720341, -0.013141, 1.000424, 0.022349, 0.747373, -0.013227, 1.000449,
+ 0.021871, 0.773980, -0.012739, 1.000478, 0.021171, 0.799839, -0.012999, 1.000396, 0.020606,
+ 0.825113, -0.012727, 1.000425, 0.020006, 0.849579, -0.012170, 1.000469, 0.019089, 0.873046,
+ -0.011855, 1.000411, 0.018291, 0.895777, -0.011711, 1.000426, 0.017534, 0.917518, -0.011107,
+ 1.000373, 0.016542, 0.938264, -0.010439, 1.000322, 0.015512, 0.958032, -0.009807, 1.000324,
+ 0.014491, 0.976838, -0.009268, 1.000341, 0.013468, 0.994631, -0.008662, 1.000318, 0.012376,
+ 1.011434, -0.007923, 1.000289, 0.011187, 1.027169, -0.007132, 1.000216, 0.010078, 1.041929,
+ -0.006332, 1.000096, 0.008924, 1.055767, -0.005554, 1.000156, 0.007770, 1.068595, -0.004811,
+ 1.000084, 0.006611, 1.080612, -0.003950, 1.000047, 0.005485, 1.091785, -0.003174, 1.000109,
+ 0.004352, 1.101998, -0.002363, 1.000029, 0.003180, 1.111423, -0.001552, 0.999985, 0.002091,
+ 1.120007, -0.000786, 0.999947, 0.000991, 1.127918, 0.000004, 1.000000, -0.000004, 0.000200,
+ -0.000010, 1.002495, 0.049907, 0.000504, -0.000025, 1.002476, 0.049908, 0.002016, -0.000101,
+ 1.002500, 0.049908, 0.004535, -0.000226, 1.002487, 0.049908, 0.008062, -0.000402, 1.002364,
+ 0.049908, 0.012598, -0.000629, 1.002412, 0.049908, 0.018140, -0.000905, 1.002379, 0.049908,
+ 0.024691, -0.001232, 1.002490, 0.049907, 0.032251, -0.001610, 1.002398, 0.049908, 0.040821,
+ -0.002037, 1.002392, 0.049908, 0.050398, -0.002515, 1.002431, 0.049907, 0.060989, -0.003044,
+ 1.002475, 0.049908, 0.072592, -0.003623, 1.002546, 0.049907, 0.085204, -0.004252, 1.002467,
+ 0.049907, 0.098832, -0.004932, 1.002450, 0.049908, 0.113481, -0.005663, 1.002482, 0.049907,
+ 0.129145, -0.006443, 1.002443, 0.049907, 0.145825, -0.007271, 1.002495, 0.049906, 0.163491,
+ -0.008128, 1.002475, 0.049903, 0.181911, -0.008826, 1.002459, 0.049879, 0.200065, -0.009285,
+ 1.002443, 0.049824, 0.220025, -0.010966, 1.002450, 0.049897, 0.241581, -0.012025, 1.002463,
+ 0.049893, 0.264099, -0.013105, 1.002395, 0.049881, 0.287493, -0.014145, 1.002390, 0.049855,
+ 0.311399, -0.014925, 1.002414, 0.049769, 0.335096, -0.015239, 1.002363, 0.049591, 0.359815,
+ -0.017559, 1.002415, 0.049777, 0.386365, -0.018554, 1.002354, 0.049675, 0.413017, -0.019043,
+ 1.002297, 0.049444, 0.439519, -0.019815, 1.002284, 0.049253, 0.466938, -0.021741, 1.002307,
+ 0.049327, 0.494999, -0.021887, 1.002181, 0.048922, 0.522922, -0.022844, 1.002107, 0.048677,
+ 0.551270, -0.024014, 1.002101, 0.048478, 0.579771, -0.024156, 1.002060, 0.047904, 0.608156,
+ -0.025317, 1.002077, 0.047594, 0.636662, -0.025321, 1.001975, 0.046876, 0.664846, -0.026018,
+ 1.001992, 0.046354, 0.692877, -0.026041, 1.001846, 0.045504, 0.720316, -0.026252, 1.001846,
+ 0.044655, 0.747658, -0.026159, 1.001931, 0.043670, 0.774252, -0.026086, 1.001845, 0.042515,
+ 0.800179, -0.025653, 1.001794, 0.041211, 0.825525, -0.025170, 1.001787, 0.039823, 0.850013,
+ -0.024788, 1.001806, 0.038409, 0.873593, -0.023992, 1.001688, 0.036767, 0.896343, -0.022985,
+ 1.001666, 0.034900, 0.918062, -0.022005, 1.001548, 0.033010, 0.938928, -0.021110, 1.001503,
+ 0.031143, 0.958667, -0.019893, 1.001341, 0.029059, 0.977457, -0.018546, 1.001194, 0.026888,
+ 0.995243, -0.017152, 1.001095, 0.024713, 1.012023, -0.015750, 1.001100, 0.022496, 1.027614,
+ -0.014289, 1.000851, 0.020153, 1.042389, -0.012688, 1.000724, 0.017839, 1.056161, -0.011118,
+ 1.000572, 0.015529, 1.068968, -0.009540, 1.000407, 0.013240, 1.080866, -0.007963, 1.000258,
+ 0.010940, 1.091944, -0.006416, 1.000254, 0.008716, 1.102104, -0.004771, 1.000175, 0.006434,
+ 1.111571, -0.003056, 1.000148, 0.004169, 1.120084, -0.001458, 1.000050, 0.002033, 1.127981,
+ 0.000021, 0.999987, -0.000027, 0.000200, -0.000015, 1.005620, 0.074940, 0.000504, -0.000038,
+ 1.005650, 0.074939, 0.002016, -0.000151, 1.005613, 0.074939, 0.004535, -0.000340, 1.005618,
+ 0.074939, 0.008062, -0.000604, 1.005614, 0.074939, 0.012597, -0.000944, 1.005616, 0.074940,
+ 0.018141, -0.001359, 1.005558, 0.074939, 0.024695, -0.001851, 1.005495, 0.074940, 0.032253,
+ -0.002417, 1.005616, 0.074939, 0.040822, -0.003059, 1.005591, 0.074940, 0.050399, -0.003777,
+ 1.005596, 0.074940, 0.060989, -0.004570, 1.005599, 0.074939, 0.072591, -0.005440, 1.005616,
+ 0.074940, 0.085203, -0.006385, 1.005616, 0.074939, 0.098833, -0.007406, 1.005595, 0.074938,
+ 0.113481, -0.008502, 1.005605, 0.074938, 0.129147, -0.009674, 1.005605, 0.074937, 0.145817,
+ -0.010916, 1.005513, 0.074937, 0.163485, -0.012199, 1.005579, 0.074928, 0.181824, -0.013172,
+ 1.005552, 0.074885, 0.200274, -0.014100, 1.005524, 0.074825, 0.220017, -0.016464, 1.005529,
+ 0.074928, 0.241568, -0.018052, 1.005490, 0.074914, 0.264084, -0.019671, 1.005457, 0.074898,
+ 0.287450, -0.021217, 1.005431, 0.074860, 0.311281, -0.022341, 1.005395, 0.074717, 0.335228,
+ -0.023296, 1.005320, 0.074526, 0.360047, -0.025965, 1.005302, 0.074649, 0.386273, -0.027808,
+ 1.005285, 0.074575, 0.412855, -0.028504, 1.005167, 0.074237, 0.439705, -0.030007, 1.005129,
+ 0.074013, 0.466975, -0.032263, 1.005082, 0.073967, 0.494874, -0.032931, 1.004960, 0.073475,
+ 0.523066, -0.034348, 1.004834, 0.073084, 0.551198, -0.035739, 1.004806, 0.072657, 0.579889,
+ -0.036575, 1.004687, 0.072029, 0.608282, -0.037434, 1.004605, 0.071309, 0.636812, -0.038323,
+ 1.004589, 0.070507, 0.665010, -0.038676, 1.004403, 0.069424, 0.693063, -0.039237, 1.004340,
+ 0.068370, 0.720750, -0.039332, 1.004224, 0.066988, 0.747911, -0.039179, 1.004117, 0.065447,
+ 0.774576, -0.039110, 1.004035, 0.063838, 0.800737, -0.038542, 1.004027, 0.061923, 0.825966,
+ -0.037966, 1.003825, 0.059859, 0.850534, -0.036943, 1.003786, 0.057529, 0.874289, -0.035853,
+ 1.003560, 0.055081, 0.897152, -0.034730, 1.003549, 0.052476, 0.919029, -0.033242, 1.003454,
+ 0.049647, 0.939851, -0.031508, 1.003215, 0.046670, 0.959599, -0.029695, 1.002916, 0.043588,
+ 0.978293, -0.027845, 1.002720, 0.040401, 0.996085, -0.025775, 1.002445, 0.037060, 1.012768,
+ -0.023607, 1.002133, 0.033726, 1.028404, -0.021374, 1.001822, 0.030217, 1.043150, -0.019108,
+ 1.001602, 0.026820, 1.056760, -0.016823, 1.001274, 0.023372, 1.069471, -0.014378, 1.000964,
+ 0.019891, 1.081283, -0.011884, 1.000684, 0.016405, 1.092238, -0.009398, 1.000514, 0.012950,
+ 1.102384, -0.007030, 1.000319, 0.009579, 1.111737, -0.004751, 1.000225, 0.006384, 1.120274,
+ -0.002404, 1.000046, 0.003192, 1.128182, 0.000031, 1.000020, 0.000033, 0.000200, -0.000020,
+ 1.010006, 0.100065, 0.000504, -0.000050, 1.009927, 0.100065, 0.002016, -0.000202, 1.010026,
+ 0.100064, 0.004535, -0.000454, 1.010018, 0.100065, 0.008062, -0.000807, 1.009891, 0.100064,
+ 0.012599, -0.001261, 1.010175, 0.100064, 0.018141, -0.001815, 1.010067, 0.100065, 0.024692,
+ -0.002471, 1.010014, 0.100066, 0.032251, -0.003227, 1.009950, 0.100065, 0.040818, -0.004084,
+ 1.009963, 0.100067, 0.050401, -0.005043, 1.010032, 0.100064, 0.060988, -0.006102, 1.009979,
+ 0.100064, 0.072588, -0.007263, 1.009984, 0.100063, 0.085205, -0.008525, 1.010023, 0.100063,
+ 0.098832, -0.009888, 1.009960, 0.100062, 0.113479, -0.011352, 1.009974, 0.100063, 0.129142,
+ -0.012916, 1.009945, 0.100062, 0.145817, -0.014573, 1.009924, 0.100058, 0.163468, -0.016276,
+ 1.009912, 0.100050, 0.181674, -0.017411, 1.009859, 0.099975, 0.200435, -0.019002, 1.009842,
+ 0.099932, 0.220005, -0.021978, 1.009820, 0.100043, 0.241550, -0.024096, 1.009778, 0.100031,
+ 0.264058, -0.026250, 1.009765, 0.100002, 0.287399, -0.028286, 1.009724, 0.099939, 0.311134,
+ -0.029698, 1.009596, 0.099748, 0.335350, -0.031442, 1.009508, 0.099582, 0.360295, -0.034401,
+ 1.009475, 0.099613, 0.386112, -0.037030, 1.009329, 0.099558, 0.412733, -0.038163, 1.009250,
+ 0.099137, 0.439833, -0.040250, 1.009125, 0.098866, 0.467099, -0.042583, 1.009011, 0.098626,
+ 0.494828, -0.044299, 1.008803, 0.098149, 0.523217, -0.045876, 1.008712, 0.097600, 0.551338,
+ -0.047440, 1.008509, 0.096929, 0.579917, -0.048995, 1.008371, 0.096178, 0.608454, -0.049901,
+ 1.008212, 0.095145, 0.636785, -0.051224, 1.007963, 0.094151, 0.665220, -0.051675, 1.007741,
+ 0.092728, 0.693194, -0.052278, 1.007616, 0.091195, 0.721008, -0.052406, 1.007327, 0.089384,
+ 0.748196, -0.052529, 1.007219, 0.087461, 0.774975, -0.051950, 1.006851, 0.085133, 0.801129,
+ -0.051456, 1.006732, 0.082628, 0.826668, -0.050569, 1.006612, 0.079817, 0.851291, -0.049328,
+ 1.006374, 0.076710, 0.875056, -0.047988, 1.006183, 0.073481, 0.897872, -0.046149, 1.005742,
+ 0.069943, 0.919803, -0.044144, 1.005514, 0.066151, 0.940701, -0.042095, 1.005153, 0.062247,
+ 0.960580, -0.039730, 1.004843, 0.058158, 0.979427, -0.037104, 1.004535, 0.053850, 0.997157,
+ -0.034369, 1.004023, 0.049403, 1.013777, -0.031555, 1.003622, 0.044944, 1.029452, -0.028571,
+ 1.003212, 0.040414, 1.044029, -0.025416, 1.002698, 0.035723, 1.057586, -0.022217, 1.002202,
+ 0.031072, 1.070148, -0.019037, 1.001703, 0.026429, 1.081875, -0.015936, 1.001322, 0.021896,
+ 1.092789, -0.012734, 1.001053, 0.017288, 1.102704, -0.009454, 1.000604, 0.012841, 1.112011,
+ -0.006199, 1.000387, 0.008446, 1.120590, -0.003010, 1.000166, 0.004122, 1.128283, 0.000027,
+ 0.999956, -0.000038, 0.000200, -0.000025, 1.015664, 0.125315, 0.000504, -0.000063, 1.015664,
+ 0.125316, 0.002016, -0.000253, 1.015727, 0.125315, 0.004535, -0.000568, 1.015695, 0.125314,
+ 0.008063, -0.001010, 1.015823, 0.125316, 0.012599, -0.001579, 1.015867, 0.125315, 0.018141,
+ -0.002273, 1.015758, 0.125316, 0.024691, -0.003094, 1.015662, 0.125316, 0.032252, -0.004042,
+ 1.015674, 0.125316, 0.040820, -0.005115, 1.015678, 0.125316, 0.050400, -0.006316, 1.015684,
+ 0.125315, 0.060989, -0.007642, 1.015685, 0.125315, 0.072590, -0.009096, 1.015703, 0.125314,
+ 0.085203, -0.010676, 1.015654, 0.125314, 0.098833, -0.012383, 1.015670, 0.125315, 0.113477,
+ -0.014215, 1.015635, 0.125312, 0.129138, -0.016173, 1.015599, 0.125311, 0.145815, -0.018246,
+ 1.015610, 0.125306, 0.163450, -0.020360, 1.015564, 0.125294, 0.181595, -0.021807, 1.015460,
+ 0.125204, 0.200563, -0.023971, 1.015440, 0.125165, 0.220186, -0.027280, 1.015412, 0.125250,
+ 0.241528, -0.030164, 1.015342, 0.125267, 0.264020, -0.032847, 1.015269, 0.125233, 0.287311,
+ -0.035345, 1.015232, 0.125138, 0.310993, -0.037108, 1.015063, 0.124903, 0.335467, -0.039653,
+ 1.014970, 0.124749, 0.360497, -0.042914, 1.014819, 0.124702, 0.385986, -0.046142, 1.014685,
+ 0.124623, 0.412703, -0.048050, 1.014543, 0.124193, 0.439929, -0.050527, 1.014315, 0.123833,
+ 0.467163, -0.052880, 1.014087, 0.123375, 0.494824, -0.055672, 1.013898, 0.122982, 0.523222,
+ -0.057388, 1.013647, 0.122166, 0.551557, -0.059328, 1.013403, 0.121343, 0.579884, -0.061315,
+ 1.013059, 0.120430, 0.608619, -0.062531, 1.012745, 0.119140, 0.637014, -0.063778, 1.012425,
+ 0.117721, 0.665425, -0.064734, 1.012067, 0.116069, 0.693580, -0.065315, 1.011712, 0.114146,
+ 0.721194, -0.065535, 1.011200, 0.111846, 0.748586, -0.065501, 1.010896, 0.109309, 0.775437,
+ -0.065091, 1.010576, 0.106504, 0.801554, -0.064332, 1.010136, 0.103308, 0.827079, -0.063078,
+ 1.009629, 0.099695, 0.851693, -0.061728, 1.009233, 0.095946, 0.875586, -0.059853, 1.008726,
+ 0.091802, 0.898589, -0.057727, 1.008412, 0.087339, 0.920421, -0.055377, 1.007767, 0.082687,
+ 0.941533, -0.052571, 1.007529, 0.077716, 0.961426, -0.049544, 1.006929, 0.072574, 0.980287,
+ -0.046400, 1.006393, 0.067217, 0.998080, -0.042966, 1.005872, 0.061757, 1.014940, -0.039321,
+ 1.005346, 0.056072, 1.030455, -0.035585, 1.004609, 0.050410, 1.045078, -0.031823, 1.004151,
+ 0.044622, 1.058555, -0.027947, 1.003421, 0.038893, 1.071009, -0.023891, 1.002704, 0.032977,
+ 1.082594, -0.019822, 1.002023, 0.027290, 1.093265, -0.015765, 1.001403, 0.021543, 1.103132,
+ -0.011790, 1.000944, 0.016072, 1.112348, -0.007784, 1.000550, 0.010511, 1.120845, -0.003849,
+ 1.000224, 0.005174, 1.128573, 0.000057, 0.999975, -0.000039, 0.000200, -0.000030, 1.022609,
+ 0.150725, 0.000504, -0.000076, 1.022728, 0.150725, 0.002016, -0.000304, 1.022728, 0.150725,
+ 0.004535, -0.000684, 1.022733, 0.150725, 0.008062, -0.001215, 1.022715, 0.150725, 0.012598,
+ -0.001899, 1.022720, 0.150725, 0.018141, -0.002734, 1.022659, 0.150725, 0.024694, -0.003722,
+ 1.022801, 0.150724, 0.032254, -0.004861, 1.022779, 0.150726, 0.040815, -0.006152, 1.022693,
+ 0.150724, 0.050400, -0.007596, 1.022716, 0.150725, 0.060990, -0.009192, 1.022733, 0.150725,
+ 0.072587, -0.010939, 1.022630, 0.150723, 0.085203, -0.012839, 1.022676, 0.150725, 0.098828,
+ -0.014891, 1.022659, 0.150725, 0.113473, -0.017095, 1.022589, 0.150720, 0.129137, -0.019449,
+ 1.022572, 0.150716, 0.145803, -0.021938, 1.022508, 0.150712, 0.163417, -0.024443, 1.022471,
+ 0.150691, 0.181580, -0.026329, 1.022406, 0.150600, 0.200667, -0.028997, 1.022336, 0.150553,
+ 0.220429, -0.032584, 1.022296, 0.150610, 0.241497, -0.036260, 1.022202, 0.150658, 0.263975,
+ -0.039465, 1.022119, 0.150619, 0.287210, -0.042385, 1.021988, 0.150490, 0.310935, -0.044758,
+ 1.021771, 0.150241, 0.335556, -0.047922, 1.021658, 0.150076, 0.360667, -0.051493, 1.021437,
+ 0.149931, 0.386028, -0.054931, 1.021228, 0.149754, 0.412665, -0.058007, 1.021023, 0.149400,
+ 0.439951, -0.060813, 1.020723, 0.148913, 0.467262, -0.063461, 1.020332, 0.148319, 0.494972,
+ -0.066738, 1.020097, 0.147798, 0.523153, -0.068976, 1.019630, 0.146903, 0.551700, -0.071268,
+ 1.019245, 0.145863, 0.580046, -0.073439, 1.018797, 0.144695, 0.608649, -0.075193, 1.018201,
+ 0.143237, 0.637239, -0.076536, 1.017746, 0.141463, 0.665388, -0.077771, 1.017111, 0.139462,
+ 0.693755, -0.078344, 1.016609, 0.137082, 0.721345, -0.078817, 1.015863, 0.134403, 0.748879,
+ -0.078512, 1.015390, 0.131252, 0.775560, -0.078128, 1.014652, 0.127866, 0.801897, -0.077094,
+ 1.013877, 0.123928, 0.827193, -0.075863, 1.013021, 0.119733, 0.851990, -0.073973, 1.012395,
+ 0.115055, 0.875823, -0.071765, 1.011595, 0.110098, 0.898655, -0.069241, 1.010862, 0.104722,
+ 0.920915, -0.066232, 1.010185, 0.098991, 0.941969, -0.062980, 1.009588, 0.093044, 0.961882,
+ -0.059507, 1.008777, 0.086925, 0.980952, -0.055606, 1.008252, 0.080520, 0.998955, -0.051503,
+ 1.007633, 0.073890, 1.015756, -0.047292, 1.006908, 0.067302, 1.031571, -0.042804, 1.006338,
+ 0.060412, 1.046095, -0.038132, 1.005512, 0.053497, 1.059542, -0.033380, 1.004592, 0.046569,
+ 1.072006, -0.028613, 1.003731, 0.039679, 1.083348, -0.023811, 1.002871, 0.032772, 1.093969,
+ -0.018930, 1.002068, 0.025894, 1.103697, -0.014098, 1.001284, 0.019178, 1.112813, -0.009339,
+ 1.000820, 0.012652, 1.121193, -0.004661, 1.000324, 0.006226, 1.128930, 0.000052, 0.999988,
+ -0.000008, 0.000200, -0.000035, 1.030857, 0.176327, 0.000504, -0.000089, 1.031137, 0.176326,
+ 0.002016, -0.000355, 1.031049, 0.176325, 0.004535, -0.000800, 1.031105, 0.176326, 0.008062,
+ -0.001422, 1.030973, 0.176326, 0.012598, -0.002221, 1.031168, 0.176326, 0.018141, -0.003199,
+ 1.031093, 0.176326, 0.024695, -0.004354, 1.031297, 0.176326, 0.032253, -0.005687, 1.031091,
+ 0.176327, 0.040821, -0.007197, 1.031012, 0.176326, 0.050399, -0.008886, 1.031068, 0.176325,
+ 0.060987, -0.010752, 1.030967, 0.176323, 0.072588, -0.012797, 1.031028, 0.176324, 0.085200,
+ -0.015019, 1.030985, 0.176322, 0.098829, -0.017419, 1.030983, 0.176320, 0.113474, -0.019997,
+ 1.030953, 0.176317, 0.129133, -0.022748, 1.030891, 0.176312, 0.145800, -0.025655, 1.030825,
+ 0.176306, 0.163372, -0.028510, 1.030781, 0.176279, 0.181578, -0.030914, 1.030683, 0.176187,
+ 0.200761, -0.034076, 1.030574, 0.176139, 0.220645, -0.037985, 1.030476, 0.176160, 0.241473,
+ -0.042391, 1.030384, 0.176238, 0.263922, -0.046105, 1.030241, 0.176175, 0.287074, -0.049390,
+ 1.030049, 0.176013, 0.310915, -0.052511, 1.029839, 0.175776, 0.335604, -0.056236, 1.029608,
+ 0.175578, 0.360775, -0.060118, 1.029355, 0.175359, 0.386196, -0.063907, 1.029052, 0.175083,
+ 0.412599, -0.067997, 1.028766, 0.174791, 0.439916, -0.071088, 1.028326, 0.174174, 0.467444,
+ -0.074247, 1.027890, 0.173487, 0.495132, -0.077728, 1.027374, 0.172774, 0.523117, -0.080822,
+ 1.026763, 0.171824, 0.551783, -0.083228, 1.026205, 0.170554, 0.580234, -0.085682, 1.025614,
+ 0.169090, 0.608568, -0.087860, 1.024668, 0.167468, 0.637357, -0.089346, 1.023939, 0.165283,
+ 0.665507, -0.090704, 1.022946, 0.162966, 0.693704, -0.091388, 1.022010, 0.160131, 0.721396,
+ -0.091783, 1.021085, 0.156957, 0.748676, -0.091688, 1.019894, 0.153292, 0.775370, -0.090992,
+ 1.018608, 0.149158, 0.801547, -0.089881, 1.017646, 0.144551, 0.827013, -0.088267, 1.016355,
+ 0.139614, 0.851708, -0.086132, 1.015446, 0.134026, 0.875652, -0.083707, 1.014321, 0.128101,
+ 0.898703, -0.080619, 1.013454, 0.121841, 0.920904, -0.077280, 1.012634, 0.115379, 0.942077,
+ -0.073484, 1.011770, 0.108355, 0.962245, -0.069252, 1.010894, 0.101153, 0.981385, -0.064807,
+ 1.010114, 0.093666, 0.999379, -0.060080, 1.009294, 0.086007, 1.016494, -0.055007, 1.008591,
+ 0.078194, 1.032357, -0.049760, 1.007821, 0.070328, 1.047061, -0.044468, 1.006871, 0.062358,
+ 1.060675, -0.038960, 1.006062, 0.054279, 1.073032, -0.033343, 1.004911, 0.046158, 1.084293,
+ -0.027699, 1.003791, 0.038111, 1.094724, -0.022130, 1.002744, 0.030239, 1.104302, -0.016508,
+ 1.001815, 0.022397, 1.113290, -0.010846, 1.001083, 0.014747, 1.121649, -0.005294, 1.000490,
+ 0.007234, 1.129230, 0.000071, 0.999975, -0.000053, 0.000200, -0.000040, 1.040431, 0.202155,
+ 0.000504, -0.000102, 1.040912, 0.202154, 0.002016, -0.000407, 1.041328, 0.202152, 0.004535,
+ -0.000917, 1.040877, 0.202154, 0.008063, -0.001630, 1.040867, 0.202153, 0.012598, -0.002547,
+ 1.040870, 0.202153, 0.018140, -0.003667, 1.040808, 0.202153, 0.024692, -0.004991, 1.040861,
+ 0.202153, 0.032252, -0.006519, 1.040861, 0.202153, 0.040822, -0.008252, 1.040864, 0.202153,
+ 0.050397, -0.010187, 1.040717, 0.202151, 0.060988, -0.012327, 1.040791, 0.202152, 0.072582,
+ -0.014669, 1.040640, 0.202149, 0.085198, -0.017217, 1.040716, 0.202147, 0.098827, -0.019968,
+ 1.040748, 0.202141, 0.113467, -0.022921, 1.040632, 0.202142, 0.129129, -0.026074, 1.040606,
+ 0.202137, 0.145793, -0.029399, 1.040566, 0.202127, 0.163294, -0.032524, 1.040459, 0.202078,
+ 0.181589, -0.035552, 1.040315, 0.201996, 0.200844, -0.039208, 1.040221, 0.201948, 0.220835,
+ -0.043489, 1.040047, 0.201945, 0.241471, -0.048523, 1.039921, 0.202031, 0.263854, -0.052764,
+ 1.039756, 0.201957, 0.286935, -0.056387, 1.039497, 0.201743, 0.310902, -0.060338, 1.039252,
+ 0.201531, 0.335642, -0.064594, 1.038954, 0.201286, 0.360859, -0.068772, 1.038582, 0.200983,
+ 0.386419, -0.073086, 1.038160, 0.200651, 0.412588, -0.077887, 1.037724, 0.200343, 0.439836,
+ -0.081391, 1.037182, 0.199618, 0.467538, -0.085121, 1.036602, 0.198839, 0.495286, -0.088718,
+ 1.035893, 0.197895, 0.523231, -0.092514, 1.035121, 0.196887, 0.551730, -0.095238, 1.034127,
+ 0.195390, 0.580302, -0.097949, 1.033131, 0.193668, 0.608559, -0.100418, 1.031962, 0.191773,
+ 0.637224, -0.102129, 1.030838, 0.189319, 0.665597, -0.103578, 1.029511, 0.186529, 0.693535,
+ -0.104652, 1.028263, 0.183303, 0.721325, -0.104766, 1.026611, 0.179497, 0.748384, -0.104717,
+ 1.025128, 0.175283, 0.775058, -0.103846, 1.023385, 0.170493, 0.801387, -0.102728, 1.022236,
+ 0.165187, 0.826412, -0.100679, 1.019908, 0.159362, 0.851314, -0.098451, 1.018839, 0.153059,
+ 0.875100, -0.095363, 1.017306, 0.146284, 0.898280, -0.092008, 1.016151, 0.138975, 0.920450,
+ -0.088095, 1.014880, 0.131361, 0.941727, -0.083690, 1.013556, 0.123417, 0.962308, -0.079077,
+ 1.012998, 0.115201, 0.981364, -0.073894, 1.011841, 0.106711, 0.999798, -0.068435, 1.011021,
+ 0.098063, 1.016983, -0.062830, 1.010194, 0.089183, 1.033039, -0.056914, 1.009292, 0.080190,
+ 1.047994, -0.050721, 1.008474, 0.071010, 1.061580, -0.044454, 1.007386, 0.061867, 1.074023,
+ -0.038145, 1.006135, 0.052711, 1.085470, -0.031679, 1.004890, 0.043595, 1.095673, -0.025157,
+ 1.003627, 0.034506, 1.105000, -0.018702, 1.002331, 0.025468, 1.113795, -0.012458, 1.001278,
+ 0.016834, 1.122012, -0.006169, 1.000548, 0.008265, 1.129683, 0.000078, 0.999988, -0.000072,
+ 0.000200, -0.000046, 1.052496, 0.228243, 0.000504, -0.000115, 1.052079, 0.228243, 0.002016,
+ -0.000460, 1.052079, 0.228241, 0.004535, -0.001035, 1.052091, 0.228242, 0.008062, -0.001840,
+ 1.051962, 0.228242, 0.012598, -0.002875, 1.052087, 0.228242, 0.018141, -0.004140, 1.052088,
+ 0.228242, 0.024692, -0.005636, 1.052096, 0.228239, 0.032251, -0.007361, 1.052029, 0.228243,
+ 0.040820, -0.009316, 1.052038, 0.228241, 0.050399, -0.011501, 1.052042, 0.228239, 0.060990,
+ -0.013917, 1.052046, 0.228238, 0.072586, -0.016562, 1.051990, 0.228236, 0.085198, -0.019437,
+ 1.051946, 0.228234, 0.098824, -0.022542, 1.051879, 0.228229, 0.113467, -0.025875, 1.051841,
+ 0.228227, 0.129121, -0.029430, 1.051724, 0.228219, 0.145780, -0.033170, 1.051672, 0.228205,
+ 0.163222, -0.036567, 1.051556, 0.228143, 0.181604, -0.040245, 1.051382, 0.228069, 0.200913,
+ -0.044395, 1.051230, 0.228010, 0.221005, -0.049088, 1.051062, 0.227988, 0.241667, -0.054506,
+ 1.050881, 0.228044, 0.263777, -0.059437, 1.050643, 0.227986, 0.286841, -0.063590, 1.050312,
+ 0.227755, 0.310879, -0.068224, 1.050009, 0.227525, 0.335650, -0.072986, 1.049597, 0.227253,
+ 0.360869, -0.077435, 1.049121, 0.226845, 0.386609, -0.082385, 1.048587, 0.226466, 0.412742,
+ -0.087570, 1.047987, 0.226059, 0.439789, -0.091929, 1.047308, 0.225331, 0.467558, -0.096038,
+ 1.046423, 0.224409, 0.495406, -0.099938, 1.045481, 0.223288, 0.523417, -0.104050, 1.044512,
+ 0.222066, 0.551755, -0.107503, 1.043408, 0.220487, 0.580468, -0.110234, 1.042016, 0.218451,
+ 0.608904, -0.112993, 1.040535, 0.216200, 0.637230, -0.115173, 1.038934, 0.213458, 0.665566,
+ -0.116433, 1.036961, 0.210158, 0.693413, -0.117589, 1.035130, 0.206457, 0.721025, -0.117885,
+ 1.033080, 0.202197, 0.748054, -0.117606, 1.030752, 0.197296, 0.774631, -0.116771, 1.028608,
+ 0.191813, 0.800677, -0.115194, 1.026350, 0.185691, 0.826062, -0.113138, 1.024472, 0.179053,
+ 0.850590, -0.110359, 1.022174, 0.171839, 0.874550, -0.107072, 1.020381, 0.164067, 0.897567,
+ -0.103268, 1.018777, 0.155959, 0.919609, -0.098794, 1.016886, 0.147320, 0.941177, -0.094067,
+ 1.015880, 0.138365, 0.961752, -0.088670, 1.014616, 0.129051, 0.981518, -0.082965, 1.013807,
+ 0.119515, 0.999880, -0.076971, 1.012793, 0.109897, 1.017370, -0.070518, 1.011894, 0.099872,
+ 1.033661, -0.063830, 1.010943, 0.089883, 1.048672, -0.057040, 1.009802, 0.079691, 1.062479,
+ -0.049917, 1.008670, 0.069458, 1.075052, -0.042735, 1.007429, 0.059191, 1.086371, -0.035513,
+ 1.005991, 0.048894, 1.096623, -0.028359, 1.004468, 0.038770, 1.105871, -0.021111, 1.002927,
+ 0.028745, 1.114481, -0.013908, 1.001728, 0.018884, 1.122610, -0.006843, 1.000740, 0.009264,
+ 1.130165, 0.000062, 0.999983, -0.000006, 0.000200, -0.000051, 1.064931, 0.254630, 0.000504,
+ -0.000128, 1.064668, 0.254630, 0.002016, -0.000513, 1.064794, 0.254630, 0.004535, -0.001155,
+ 1.064851, 0.254630, 0.008063, -0.002053, 1.064966, 0.254630, 0.012598, -0.003208, 1.064840,
+ 0.254630, 0.018140, -0.004619, 1.064602, 0.254631, 0.024695, -0.006288, 1.064965, 0.254632,
+ 0.032251, -0.008211, 1.064795, 0.254630, 0.040821, -0.010393, 1.064802, 0.254628, 0.050398,
+ -0.012830, 1.064758, 0.254627, 0.060987, -0.015525, 1.064731, 0.254625, 0.072584, -0.018474,
+ 1.064615, 0.254621, 0.085199, -0.021682, 1.064672, 0.254619, 0.098826, -0.025144, 1.064630,
+ 0.254613, 0.113465, -0.028860, 1.064515, 0.254606, 0.129119, -0.032823, 1.064416, 0.254598,
+ 0.145767, -0.036969, 1.064347, 0.254579, 0.163190, -0.040754, 1.064132, 0.254506, 0.181622,
+ -0.044989, 1.063951, 0.254437, 0.200981, -0.049642, 1.063745, 0.254370, 0.221145, -0.054776,
+ 1.063547, 0.254324, 0.241896, -0.060538, 1.063289, 0.254346, 0.263684, -0.066113, 1.063013,
+ 0.254296, 0.286796, -0.070925, 1.062625, 0.254059, 0.310867, -0.076187, 1.062216, 0.253817,
+ 0.335644, -0.081406, 1.061703, 0.253481, 0.360917, -0.086336, 1.061066, 0.253005, 0.386786,
+ -0.091790, 1.060454, 0.252558, 0.412921, -0.097230, 1.059568, 0.252008, 0.439722, -0.102574,
+ 1.058706, 0.251323, 0.467559, -0.106972, 1.057682, 0.250239, 0.495605, -0.111329, 1.056612,
+ 0.248944, 0.523589, -0.115561, 1.055101, 0.247471, 0.551787, -0.119732, 1.053745, 0.245777,
+ 0.580426, -0.122711, 1.051829, 0.243448, 0.608778, -0.125436, 1.049642, 0.240769, 0.637069,
+ -0.127993, 1.047749, 0.237739, 0.665251, -0.129448, 1.045244, 0.233928, 0.692977, -0.130408,
+ 1.042279, 0.229640, 0.720346, -0.130931, 1.039693, 0.224829, 0.747365, -0.130392, 1.036675,
+ 0.219144, 0.773734, -0.129540, 1.033719, 0.212965, 0.799578, -0.127689, 1.030774, 0.206047,
+ 0.825002, -0.125456, 1.028551, 0.198576, 0.849564, -0.122291, 1.025800, 0.190471, 0.873412,
+ -0.118720, 1.023657, 0.181739, 0.896628, -0.114323, 1.021381, 0.172586, 0.918952, -0.109587,
+ 1.019674, 0.162914, 0.940602, -0.104093, 1.018126, 0.153039, 0.960917, -0.098187, 1.016339,
+ 0.142774, 0.980911, -0.091963, 1.015440, 0.132316, 0.999686, -0.085159, 1.014377, 0.121453,
+ 1.017538, -0.078139, 1.013498, 0.110527, 1.033918, -0.070797, 1.012332, 0.099437, 1.049390,
+ -0.063129, 1.011368, 0.088157, 1.063402, -0.055354, 1.010111, 0.076951, 1.076096, -0.047522,
+ 1.008774, 0.065616, 1.087562, -0.039447, 1.007202, 0.054310, 1.097591, -0.031359, 1.005346,
+ 0.042948, 1.106782, -0.023393, 1.003710, 0.031799, 1.115234, -0.015461, 1.002116, 0.020943,
+ 1.123166, -0.007589, 1.000858, 0.010288, 1.130796, 0.000104, 1.000032, -0.000024, 0.000200,
+ -0.000056, 1.078780, 0.281356, 0.000504, -0.000142, 1.079271, 0.281355, 0.002015, -0.000567,
+ 1.078635, 0.281355, 0.004535, -0.001276, 1.079164, 0.281356, 0.008064, -0.002269, 1.079300,
+ 0.281355, 0.012598, -0.003544, 1.079149, 0.281355, 0.018143, -0.005104, 1.079329, 0.281355,
+ 0.024691, -0.006947, 1.079073, 0.281353, 0.032254, -0.009074, 1.079253, 0.281354, 0.040822,
+ -0.011484, 1.079176, 0.281353, 0.050399, -0.014177, 1.079057, 0.281349, 0.060987, -0.017153,
+ 1.079007, 0.281347, 0.072586, -0.020412, 1.078998, 0.281343, 0.085203, -0.023956, 1.078962,
+ 0.281336, 0.098823, -0.027778, 1.078839, 0.281332, 0.113464, -0.031882, 1.078783, 0.281325,
+ 0.129114, -0.036255, 1.078633, 0.281315, 0.145748, -0.040790, 1.078545, 0.281287, 0.163179,
+ -0.045024, 1.078311, 0.281208, 0.181649, -0.049791, 1.078135, 0.281137, 0.201042, -0.054953,
+ 1.077845, 0.281063, 0.221267, -0.060551, 1.077576, 0.281006, 0.242114, -0.066663, 1.077257,
+ 0.280978, 0.263568, -0.072771, 1.076897, 0.280925, 0.286744, -0.078349, 1.076405, 0.280689,
+ 0.310840, -0.084201, 1.075898, 0.280418, 0.335612, -0.089846, 1.075287, 0.280020, 0.360975,
+ -0.095394, 1.074482, 0.279513, 0.386932, -0.101290, 1.073617, 0.278961, 0.413171, -0.107042,
+ 1.072719, 0.278283, 0.439886, -0.113083, 1.071698, 0.277547, 0.467535, -0.118010, 1.070213,
+ 0.276311, 0.495701, -0.122793, 1.068857, 0.274867, 0.523772, -0.127278, 1.067037, 0.273153,
+ 0.551849, -0.131671, 1.064923, 0.271176, 0.580338, -0.135293, 1.062749, 0.268626, 0.608771,
+ -0.138065, 1.059944, 0.265569, 0.636756, -0.140565, 1.056851, 0.262054, 0.664574, -0.142434,
+ 1.053461, 0.257807, 0.692151, -0.143237, 1.049910, 0.252930, 0.719376, -0.143717, 1.046426,
+ 0.247414, 0.745852, -0.143117, 1.042377, 0.241001, 0.772300, -0.141975, 1.038789, 0.233797,
+ 0.798050, -0.140114, 1.035290, 0.226218, 0.823370, -0.137379, 1.032374, 0.217785, 0.847735,
+ -0.134119, 1.028853, 0.208748, 0.871897, -0.129985, 1.026395, 0.198877, 0.894950, -0.125324,
+ 1.023787, 0.188803, 0.917909, -0.120007, 1.022073, 0.178493, 0.939567, -0.114099, 1.020098,
+ 0.167466, 0.960534, -0.107748, 1.018851, 0.156223, 0.980423, -0.100748, 1.017362, 0.144716,
+ 0.999334, -0.093494, 1.015961, 0.133028, 1.017561, -0.085728, 1.015059, 0.120953, 1.034225,
+ -0.077627, 1.013888, 0.108943, 1.049937, -0.069375, 1.012898, 0.096678, 1.064265, -0.060807,
+ 1.011635, 0.084350, 1.077188, -0.052052, 1.010095, 0.071964, 1.088637, -0.043304, 1.008399,
+ 0.059531, 1.098766, -0.034458, 1.006397, 0.047134, 1.107697, -0.025637, 1.004354, 0.034887,
+ 1.116055, -0.016932, 1.002611, 0.022948, 1.123819, -0.008437, 1.001023, 0.011386, 1.131333,
+ 0.000087, 0.999952, -0.000097, 0.000200, -0.000062, 1.095622, 0.308458, 0.000504, -0.000155,
+ 1.094863, 0.308458, 0.002016, -0.000622, 1.095169, 0.308458, 0.004535, -0.001399, 1.095156,
+ 0.308458, 0.008063, -0.002487, 1.095413, 0.308455, 0.012598, -0.003886, 1.095147, 0.308458,
+ 0.018141, -0.005596, 1.095150, 0.308457, 0.024692, -0.007616, 1.095140, 0.308457, 0.032252,
+ -0.009947, 1.095098, 0.308456, 0.040822, -0.012589, 1.095096, 0.308453, 0.050399, -0.015541,
+ 1.095070, 0.308451, 0.060985, -0.018803, 1.094922, 0.308448, 0.072583, -0.022375, 1.094902,
+ 0.308444, 0.085197, -0.026258, 1.094882, 0.308438, 0.098822, -0.030448, 1.094775, 0.308429,
+ 0.113460, -0.034944, 1.094641, 0.308419, 0.129112, -0.039731, 1.094530, 0.308403, 0.145711,
+ -0.044610, 1.094332, 0.308365, 0.163178, -0.049362, 1.094149, 0.308285, 0.181679, -0.054666,
+ 1.093876, 0.308210, 0.201109, -0.060336, 1.093603, 0.308132, 0.221388, -0.066414, 1.093250,
+ 0.308047, 0.242315, -0.072881, 1.092835, 0.307985, 0.263651, -0.079453, 1.092391, 0.307902,
+ 0.286720, -0.085882, 1.091866, 0.307688, 0.310817, -0.092274, 1.091225, 0.307379, 0.335562,
+ -0.098306, 1.090346, 0.306906, 0.361043, -0.104572, 1.089423, 0.306374, 0.387051, -0.110843,
+ 1.088437, 0.305710, 0.413405, -0.117062, 1.087228, 0.304906, 0.440122, -0.123501, 1.085879,
+ 0.304017, 0.467522, -0.129245, 1.084197, 0.302783, 0.495721, -0.134285, 1.082284, 0.301104,
+ 0.523925, -0.139143, 1.080109, 0.299142, 0.551814, -0.143638, 1.077043, 0.296825, 0.579878,
+ -0.147774, 1.074071, 0.294071, 0.608316, -0.150724, 1.070621, 0.290519, 0.636059, -0.153168,
+ 1.066390, 0.286424, 0.663481, -0.155139, 1.062069, 0.281559, 0.690753, -0.155944, 1.057211,
+ 0.276024, 0.717767, -0.156176, 1.052682, 0.269622, 0.743937, -0.155783, 1.047747, 0.262532,
+ 0.770214, -0.154245, 1.043510, 0.254609, 0.795542, -0.152192, 1.039121, 0.246007, 0.821099,
+ -0.149256, 1.035962, 0.236663, 0.845452, -0.145605, 1.032320, 0.226751, 0.869780, -0.141186,
+ 1.029390, 0.216165, 0.893141, -0.136137, 1.026485, 0.204937, 0.916034, -0.130332, 1.024389,
+ 0.193624, 0.938089, -0.124040, 1.022270, 0.181756, 0.959488, -0.117011, 1.020457, 0.169339,
+ 0.979594, -0.109617, 1.018871, 0.156875, 0.998912, -0.101562, 1.017533, 0.144288, 1.017100,
+ -0.093164, 1.016445, 0.131370, 1.034413, -0.084488, 1.015453, 0.118322, 1.050347, -0.075377,
+ 1.014259, 0.104963, 1.064958, -0.066108, 1.013057, 0.091722, 1.078045, -0.056702, 1.011491,
+ 0.078231, 1.089749, -0.047106, 1.009662, 0.064797, 1.099831, -0.037467, 1.007417, 0.051315,
+ 1.108789, -0.027990, 1.005144, 0.038064, 1.116865, -0.018464, 1.002925, 0.025008, 1.124609,
+ -0.009068, 1.001221, 0.012250, 1.132040, 0.000093, 0.999984, -0.000071, 0.000200, -0.000067,
+ 1.112554, 0.335981, 0.000504, -0.000169, 1.112660, 0.335981, 0.002016, -0.000677, 1.112827,
+ 0.335981, 0.004533, -0.001523, 1.112147, 0.335982, 0.008063, -0.002709, 1.112882, 0.335979,
+ 0.012598, -0.004233, 1.112891, 0.335980, 0.018141, -0.006095, 1.112882, 0.335980, 0.024693,
+ -0.008296, 1.112877, 0.335978, 0.032252, -0.010834, 1.112860, 0.335976, 0.040824, -0.013713,
+ 1.112965, 0.335974, 0.050398, -0.016927, 1.112753, 0.335971, 0.060991, -0.020482, 1.112826,
+ 0.335970, 0.072587, -0.024371, 1.112676, 0.335962, 0.085199, -0.028597, 1.112593, 0.335955,
+ 0.098822, -0.033159, 1.112453, 0.335943, 0.113461, -0.038052, 1.112329, 0.335930, 0.129108,
+ -0.043255, 1.112144, 0.335910, 0.145665, -0.048412, 1.111905, 0.335857, 0.163185, -0.053786,
+ 1.111668, 0.335781, 0.181710, -0.059608, 1.111345, 0.335696, 0.201166, -0.065794, 1.110979,
+ 0.335606, 0.221489, -0.072361, 1.110553, 0.335505, 0.242471, -0.079184, 1.110112, 0.335396,
+ 0.263900, -0.086213, 1.109584, 0.335271, 0.286688, -0.093491, 1.108927, 0.335089, 0.310773,
+ -0.100406, 1.108091, 0.334737, 0.335573, -0.106987, 1.107169, 0.334208, 0.361117, -0.113844,
+ 1.106097, 0.333600, 0.387175, -0.120463, 1.104826, 0.332828, 0.413665, -0.127245, 1.103415,
+ 0.331929, 0.440386, -0.133927, 1.101632, 0.330851, 0.467527, -0.140496, 1.099563, 0.329538,
+ 0.495630, -0.145874, 1.096956, 0.327618, 0.523864, -0.150997, 1.094201, 0.325390, 0.551705,
+ -0.155713, 1.090342, 0.322688, 0.579383, -0.159993, 1.086010, 0.319483, 0.607301, -0.163238,
+ 1.081226, 0.315522, 0.634873, -0.165667, 1.076065, 0.310840, 0.662028, -0.167606, 1.070466,
+ 0.305377, 0.688755, -0.168626, 1.064601, 0.299056, 0.715612, -0.168578, 1.059269, 0.291963,
+ 0.741604, -0.167961, 1.053648, 0.284018, 0.767757, -0.166439, 1.048928, 0.275474, 0.793264,
+ -0.164023, 1.044343, 0.266056, 0.818165, -0.160965, 1.039909, 0.255750, 0.843255, -0.156896,
+ 1.036180, 0.244843, 0.867249, -0.152262, 1.032303, 0.233464, 0.890994, -0.146655, 1.029365,
+ 0.221128, 0.913829, -0.140574, 1.026607, 0.208554, 0.936508, -0.133640, 1.024512, 0.195772,
+ 0.957720, -0.126220, 1.022421, 0.182420, 0.978940, -0.118164, 1.021293, 0.168852, 0.998285,
+ -0.109558, 1.019444, 0.155261, 1.016764, -0.100562, 1.017825, 0.141395, 1.034387, -0.091064,
+ 1.016996, 0.127311, 1.050916, -0.081468, 1.015945, 0.113089, 1.065652, -0.071463, 1.014547,
+ 0.098879, 1.079155, -0.061240, 1.013066, 0.084468, 1.090822, -0.050980, 1.010788, 0.069940,
+ 1.101100, -0.040549, 1.008563, 0.055475, 1.109824, -0.030101, 1.005950, 0.041033, 1.117828,
+ -0.019884, 1.003453, 0.027022, 1.125443, -0.009900, 1.001484, 0.013306, 1.132869, 0.000094,
+ 1.000004, -0.000046, 0.000200, -0.000073, 1.132849, 0.363970, 0.000504, -0.000183, 1.132155,
+ 0.363969, 0.002016, -0.000734, 1.132516, 0.363969, 0.004535, -0.001651, 1.132256, 0.363969,
+ 0.008062, -0.002934, 1.132318, 0.363966, 0.012597, -0.004585, 1.132386, 0.363968, 0.018141,
+ -0.006602, 1.132457, 0.363967, 0.024693, -0.008987, 1.132511, 0.363967, 0.032252, -0.011737,
+ 1.132488, 0.363965, 0.040819, -0.014853, 1.132241, 0.363959, 0.050398, -0.018336, 1.132372,
+ 0.363958, 0.060988, -0.022185, 1.132373, 0.363954, 0.072582, -0.026396, 1.132137, 0.363943,
+ 0.085195, -0.030973, 1.132071, 0.363935, 0.098822, -0.035913, 1.131978, 0.363922, 0.113461,
+ -0.041209, 1.131801, 0.363905, 0.129116, -0.046833, 1.131535, 0.363867, 0.145640, -0.052346,
+ 1.131290, 0.363814, 0.163199, -0.058275, 1.131046, 0.363734, 0.181742, -0.064623, 1.130671,
+ 0.363642, 0.201227, -0.071336, 1.130224, 0.363539, 0.221587, -0.078396, 1.129758, 0.363419,
+ 0.242625, -0.085545, 1.129213, 0.363256, 0.264183, -0.093110, 1.128549, 0.363097, 0.286668,
+ -0.101206, 1.127767, 0.362939, 0.310745, -0.108586, 1.126796, 0.362516, 0.335602, -0.115827,
+ 1.125686, 0.361953, 0.361202, -0.123212, 1.124451, 0.361275, 0.387298, -0.130294, 1.122861,
+ 0.360376, 0.413918, -0.137553, 1.121154, 0.359362, 0.440680, -0.144577, 1.118825, 0.358069,
+ 0.467667, -0.151558, 1.116002, 0.356581, 0.495449, -0.157621, 1.112778, 0.354531, 0.523514,
+ -0.162844, 1.108842, 0.351915, 0.551250, -0.167744, 1.104075, 0.348797, 0.578629, -0.172132,
+ 1.098733, 0.345222, 0.605757, -0.175733, 1.092224, 0.340665, 0.633392, -0.178109, 1.086201,
+ 0.335286, 0.660783, -0.180009, 1.080110, 0.329286, 0.687219, -0.181105, 1.073419, 0.322319,
+ 0.713873, -0.181046, 1.067410, 0.314616, 0.740094, -0.180219, 1.061414, 0.306014, 0.765233,
+ -0.178559, 1.055287, 0.296704, 0.790885, -0.175806, 1.049727, 0.286394, 0.815464, -0.172354,
+ 1.044519, 0.275189, 0.840259, -0.168048, 1.040375, 0.263441, 0.864285, -0.162904, 1.036010,
+ 0.250918, 0.888806, -0.157194, 1.033525, 0.237611, 0.911682, -0.150486, 1.029490, 0.223809,
+ 0.934481, -0.143212, 1.026778, 0.209705, 0.956337, -0.135233, 1.024632, 0.195281, 0.977380,
+ -0.126650, 1.022737, 0.180878, 0.997427, -0.117552, 1.021110, 0.166112, 1.016666, -0.107814,
+ 1.019869, 0.151231, 1.034337, -0.097814, 1.018543, 0.136375, 1.051082, -0.087330, 1.017476,
+ 0.121187, 1.066326, -0.076614, 1.016083, 0.106043, 1.079897, -0.065793, 1.014227, 0.090566,
+ 1.092136, -0.054654, 1.012334, 0.074988, 1.102315, -0.043516, 1.009627, 0.059577, 1.111105,
+ -0.032509, 1.006808, 0.044202, 1.118861, -0.021381, 1.003917, 0.028995, 1.126363, -0.010489,
+ 1.001670, 0.014269, 1.133598, 0.000083, 0.999989, -0.000035, 0.000200, -0.000079, 1.155026,
+ 0.392470, 0.000504, -0.000198, 1.154184, 0.392469, 0.002016, -0.000791, 1.153990, 0.392469,
+ 0.004535, -0.001780, 1.154045, 0.392469, 0.008063, -0.003164, 1.154007, 0.392466, 0.012598,
+ -0.004944, 1.154022, 0.392469, 0.018141, -0.007119, 1.154015, 0.392468, 0.024692, -0.009690,
+ 1.154017, 0.392466, 0.032254, -0.012656, 1.154069, 0.392465, 0.040826, -0.016018, 1.153980,
+ 0.392459, 0.050399, -0.019771, 1.153911, 0.392456, 0.060987, -0.023919, 1.153860, 0.392447,
+ 0.072588, -0.028461, 1.153777, 0.392442, 0.085197, -0.033393, 1.153582, 0.392428, 0.098822,
+ -0.038716, 1.153434, 0.392412, 0.113462, -0.044422, 1.153271, 0.392390, 0.129101, -0.050455,
+ 1.153019, 0.392359, 0.145642, -0.056392, 1.152721, 0.392283, 0.163223, -0.062859, 1.152404,
+ 0.392201, 0.181779, -0.069721, 1.151941, 0.392099, 0.201289, -0.076968, 1.151422, 0.391978,
+ 0.221678, -0.084518, 1.150861, 0.391833, 0.242752, -0.092017, 1.150156, 0.391618, 0.264474,
+ -0.100184, 1.149402, 0.391421, 0.286768, -0.108921, 1.148545, 0.391249, 0.310719, -0.116815,
+ 1.147388, 0.390773, 0.335638, -0.124785, 1.146042, 0.390168, 0.361240, -0.132630, 1.144529,
+ 0.389394, 0.387443, -0.140298, 1.142602, 0.388391, 0.414067, -0.147913, 1.140361, 0.387199,
+ 0.440904, -0.155362, 1.137612, 0.385742, 0.467771, -0.162574, 1.133659, 0.383926, 0.494907,
+ -0.169312, 1.129246, 0.381715, 0.522801, -0.174778, 1.124228, 0.378678, 0.550751, -0.179824,
+ 1.118697, 0.375158, 0.578018, -0.184284, 1.112019, 0.370851, 0.605291, -0.188215, 1.105151,
+ 0.365928, 0.632269, -0.190760, 1.097677, 0.360114, 0.659432, -0.192457, 1.090816, 0.353498,
+ 0.685839, -0.193458, 1.083286, 0.346094, 0.711876, -0.193502, 1.076245, 0.337754, 0.738184,
+ -0.192371, 1.069684, 0.328412, 0.763723, -0.190531, 1.063249, 0.318164, 0.789192, -0.187726,
+ 1.057265, 0.306900, 0.813744, -0.183783, 1.051177, 0.295021, 0.838408, -0.179328, 1.045902,
+ 0.282144, 0.862116, -0.173573, 1.040853, 0.268438, 0.885636, -0.167350, 1.036515, 0.254108,
+ 0.909342, -0.160229, 1.033269, 0.239082, 0.931962, -0.152529, 1.029627, 0.224024, 0.954671,
+ -0.144080, 1.027507, 0.208393, 0.975707, -0.135023, 1.024657, 0.192630, 0.996644, -0.125258,
+ 1.022998, 0.176741, 1.015817, -0.115089, 1.021234, 0.160926, 1.034301, -0.104317, 1.020025,
+ 0.145042, 1.051131, -0.093218, 1.018739, 0.129052, 1.066836, -0.081828, 1.017419, 0.112905,
+ 1.081027, -0.070132, 1.015714, 0.096578, 1.093225, -0.058382, 1.013465, 0.080077, 1.103691,
+ -0.046527, 1.010853, 0.063580, 1.112431, -0.034624, 1.007702, 0.047118, 1.120035, -0.022913,
+ 1.004551, 0.031018, 1.127336, -0.011284, 1.001924, 0.015283, 1.134510, 0.000170, 0.999937,
+ -0.000058, 0.000200, -0.000084, 1.177044, 0.421534, 0.000504, -0.000212, 1.177312, 0.421533,
+ 0.002016, -0.000850, 1.177730, 0.421533, 0.004535, -0.001912, 1.177722, 0.421533, 0.008063,
+ -0.003399, 1.177844, 0.421529, 0.012598, -0.005310, 1.177768, 0.421533, 0.018141, -0.007646,
+ 1.177730, 0.421531, 0.024692, -0.010407, 1.177663, 0.421530, 0.032252, -0.013592, 1.177681,
+ 0.421527, 0.040821, -0.017201, 1.177562, 0.421524, 0.050401, -0.021234, 1.177445, 0.421516,
+ 0.060988, -0.025688, 1.177461, 0.421509, 0.072590, -0.030565, 1.177364, 0.421498, 0.085200,
+ -0.035860, 1.177205, 0.421482, 0.098823, -0.041572, 1.177011, 0.421462, 0.113465, -0.047694,
+ 1.176794, 0.421436, 0.129094, -0.054122, 1.176504, 0.421396, 0.145652, -0.060530, 1.176203,
+ 0.421311, 0.163245, -0.067517, 1.175805, 0.421218, 0.181825, -0.074919, 1.175271, 0.421108,
+ 0.201360, -0.082700, 1.174717, 0.420974, 0.221773, -0.090727, 1.174021, 0.420795, 0.242908,
+ -0.098719, 1.173173, 0.420536, 0.264742, -0.107417, 1.172285, 0.420296, 0.287091, -0.116601,
+ 1.171326, 0.420065, 0.310723, -0.125265, 1.169907, 0.419582, 0.335685, -0.133876, 1.168352,
+ 0.418912, 0.361285, -0.142140, 1.166322, 0.418006, 0.387562, -0.150436, 1.164136, 0.416899,
+ 0.414175, -0.158388, 1.161162, 0.415513, 0.441021, -0.166258, 1.157608, 0.413836, 0.467698,
+ -0.173720, 1.152519, 0.411702, 0.494730, -0.180843, 1.147020, 0.409102, 0.522524, -0.186906,
+ 1.141256, 0.405789, 0.550055, -0.192004, 1.134114, 0.401759, 0.577512, -0.196588, 1.127086,
+ 0.397153, 0.604348, -0.200420, 1.119029, 0.391767, 0.630970, -0.203320, 1.110308, 0.385573,
+ 0.658023, -0.204883, 1.102643, 0.378245, 0.684422, -0.205716, 1.094573, 0.370191, 0.710405,
+ -0.205767, 1.086405, 0.361231, 0.736417, -0.204513, 1.078712, 0.351106, 0.761836, -0.202281,
+ 1.071619, 0.340096, 0.787140, -0.199395, 1.064873, 0.328139, 0.812197, -0.195185, 1.058313,
+ 0.315044, 0.836342, -0.190191, 1.052085, 0.300933, 0.860311, -0.184343, 1.046705, 0.286411,
+ 0.883597, -0.177415, 1.041072, 0.270897, 0.906852, -0.170003, 1.036797, 0.254825, 0.929991,
+ -0.161592, 1.033264, 0.238176, 0.952478, -0.152792, 1.030250, 0.221581, 0.974216, -0.143032,
+ 1.027331, 0.204378, 0.995372, -0.132922, 1.025135, 0.187470, 1.015330, -0.122009, 1.023250,
+ 0.170538, 1.034070, -0.110740, 1.022021, 0.153777, 1.051295, -0.099016, 1.020271, 0.136916,
+ 1.067460, -0.086920, 1.018948, 0.119880, 1.082022, -0.074729, 1.017336, 0.102565, 1.094378,
+ -0.062036, 1.014820, 0.084994, 1.104998, -0.049413, 1.011999, 0.067650, 1.113773, -0.036812,
+ 1.008711, 0.050148, 1.121263, -0.024274, 1.005141, 0.032976, 1.128420, -0.012038, 1.002196,
+ 0.016239, 1.135496, 0.000106, 1.000042, -0.000062, 0.000200, -0.000090, 1.203048, 0.451217,
+ 0.000504, -0.000227, 1.203226, 0.451215, 0.002016, -0.000909, 1.203450, 0.451215, 0.004535,
+ -0.002046, 1.203569, 0.451215, 0.008062, -0.003638, 1.203609, 0.451209, 0.012598, -0.005684,
+ 1.203580, 0.451214, 0.018141, -0.008185, 1.203515, 0.451212, 0.024694, -0.011141, 1.203618,
+ 0.451211, 0.032253, -0.014549, 1.203609, 0.451207, 0.040815, -0.018409, 1.203302, 0.451203,
+ 0.050401, -0.022727, 1.203454, 0.451195, 0.060990, -0.027495, 1.203480, 0.451188, 0.072591,
+ -0.032713, 1.203220, 0.451172, 0.085203, -0.038378, 1.203058, 0.451154, 0.098829, -0.044489,
+ 1.202838, 0.451130, 0.113466, -0.051031, 1.202530, 0.451098, 0.129084, -0.057808, 1.202270,
+ 0.451041, 0.145669, -0.064769, 1.201904, 0.450956, 0.163278, -0.072278, 1.201411, 0.450853,
+ 0.181880, -0.080224, 1.200825, 0.450721, 0.201436, -0.088537, 1.200164, 0.450566, 0.221865,
+ -0.097009, 1.199335, 0.450351, 0.243083, -0.105591, 1.198383, 0.450062, 0.265033, -0.114818,
+ 1.197380, 0.449769, 0.287456, -0.124372, 1.196137, 0.449438, 0.310758, -0.133892, 1.194554,
+ 0.448974, 0.335721, -0.143052, 1.192649, 0.448216, 0.361348, -0.151868, 1.190233, 0.447202,
+ 0.387573, -0.160644, 1.187211, 0.445926, 0.414159, -0.169028, 1.183452, 0.444313, 0.440950,
+ -0.177169, 1.178562, 0.442315, 0.467998, -0.185090, 1.173540, 0.439960, 0.494566, -0.192396,
+ 1.166344, 0.436989, 0.521730, -0.198915, 1.159283, 0.433439, 0.549405, -0.204240, 1.151503,
+ 0.428984, 0.576755, -0.208861, 1.143004, 0.423839, 0.603635, -0.212734, 1.134099, 0.418012,
+ 0.629979, -0.215712, 1.124555, 0.411445, 0.656597, -0.217385, 1.115293, 0.403628, 0.683317,
+ -0.218093, 1.106460, 0.394639, 0.708990, -0.217835, 1.097389, 0.385012, 0.734898, -0.216774,
+ 1.088940, 0.373999, 0.760342, -0.214120, 1.080385, 0.362128, 0.785517, -0.210821, 1.072959,
+ 0.349184, 0.809933, -0.206443, 1.065450, 0.335080, 0.834339, -0.200942, 1.058701, 0.320257,
+ 0.858793, -0.194938, 1.052711, 0.304133, 0.882300, -0.187615, 1.047044, 0.287771, 0.905560,
+ -0.179626, 1.042083, 0.270571, 0.927916, -0.170753, 1.037077, 0.252741, 0.950415, -0.161270,
+ 1.033200, 0.234656, 0.972920, -0.151239, 1.030418, 0.216652, 0.993893, -0.140358, 1.027479,
+ 0.198252, 1.014204, -0.128963, 1.024897, 0.180113, 1.033878, -0.117128, 1.023648, 0.162282,
+ 1.051754, -0.104678, 1.022230, 0.144366, 1.067924, -0.092000, 1.020453, 0.126455, 1.082643,
+ -0.078837, 1.018518, 0.108194, 1.095503, -0.065669, 1.016199, 0.089966, 1.106290, -0.052345,
+ 1.013113, 0.071530, 1.115219, -0.039024, 1.009636, 0.053158, 1.122587, -0.025789, 1.005801,
+ 0.034959, 1.129461, -0.012622, 1.002442, 0.017222, 1.136468, 0.000152, 0.999964, -0.000065,
+ 0.000200, -0.000096, 1.231156, 0.481574, 0.000504, -0.000243, 1.232187, 0.481572, 0.002016,
+ -0.000971, 1.231948, 0.481572, 0.004535, -0.002184, 1.231919, 0.481572, 0.008061, -0.003882,
+ 1.231453, 0.481566, 0.012597, -0.006066, 1.231800, 0.481572, 0.018142, -0.008736, 1.231756,
+ 0.481569, 0.024693, -0.011889, 1.232062, 0.481570, 0.032254, -0.015528, 1.231915, 0.481563,
+ 0.040822, -0.019650, 1.231863, 0.481559, 0.050402, -0.024255, 1.231737, 0.481550, 0.060992,
+ -0.029342, 1.231678, 0.481537, 0.072592, -0.034908, 1.231537, 0.481521, 0.085207, -0.040953,
+ 1.231336, 0.481499, 0.098834, -0.047469, 1.231071, 0.481469, 0.113474, -0.054441, 1.230757,
+ 0.481431, 0.129077, -0.061556, 1.230424, 0.481359, 0.145691, -0.069091, 1.230022, 0.481269,
+ 0.163321, -0.077151, 1.229461, 0.481156, 0.181936, -0.085636, 1.228718, 0.481011, 0.201516,
+ -0.094484, 1.228023, 0.480830, 0.221963, -0.103362, 1.227057, 0.480562, 0.243264, -0.112628,
+ 1.225997, 0.480247, 0.265291, -0.122366, 1.224744, 0.479891, 0.287824, -0.132256, 1.223255,
+ 0.479461, 0.310927, -0.142614, 1.221348, 0.478978, 0.335749, -0.152326, 1.218953, 0.478132,
+ 0.361361, -0.161747, 1.215806, 0.476971, 0.387480, -0.170879, 1.211853, 0.475477, 0.414231,
+ -0.179865, 1.207783, 0.473686, 0.441065, -0.188331, 1.202051, 0.471415, 0.467923, -0.196454,
+ 1.195463, 0.468647, 0.494526, -0.204048, 1.187542, 0.465459, 0.521318, -0.211020, 1.179235,
+ 0.461650, 0.548654, -0.216520, 1.170110, 0.456868, 0.575778, -0.221098, 1.160163, 0.451227,
+ 0.602610, -0.224923, 1.149751, 0.444866, 0.628891, -0.227895, 1.139169, 0.437577, 0.655635,
+ -0.230020, 1.129736, 0.429369, 0.682115, -0.230419, 1.119516, 0.419673, 0.707514, -0.229789,
+ 1.108277, 0.409143, 0.733169, -0.228520, 1.099159, 0.397296, 0.758342, -0.225793, 1.089839,
+ 0.384578, 0.783477, -0.222049, 1.081428, 0.370323, 0.808497, -0.217562, 1.073742, 0.355253,
+ 0.832790, -0.211697, 1.065850, 0.339282, 0.856677, -0.204989, 1.058834, 0.322181, 0.880662,
+ -0.197653, 1.053291, 0.304610, 0.903474, -0.188858, 1.046822, 0.286042, 0.926313, -0.179746,
+ 1.041663, 0.267224, 0.948458, -0.169542, 1.036532, 0.247978, 0.970873, -0.159005, 1.033008,
+ 0.228535, 0.992958, -0.147658, 1.029844, 0.208819, 1.013413, -0.135771, 1.026930, 0.189486,
+ 1.033483, -0.123256, 1.025545, 0.170422, 1.051872, -0.110401, 1.023935, 0.152075, 1.068396,
+ -0.096860, 1.022092, 0.133169, 1.083731, -0.083259, 1.020221, 0.114022, 1.096849, -0.069266,
+ 1.017663, 0.094772, 1.107864, -0.055203, 1.014524, 0.075432, 1.116600, -0.041097, 1.010514,
+ 0.055980, 1.123871, -0.027083, 1.006313, 0.036839, 1.130718, -0.013510, 1.002778, 0.018156,
+ 1.137649, 0.000154, 1.000033, -0.000028, 0.000200, -0.000103, 1.264025, 0.512670, 0.000504,
+ -0.000258, 1.262437, 0.512667, 0.002016, -0.001033, 1.262691, 0.512668, 0.004535, -0.002325,
+ 1.262834, 0.512667, 0.008063, -0.004133, 1.262783, 0.512659, 0.012598, -0.006458, 1.262803,
+ 0.512666, 0.018141, -0.009299, 1.262720, 0.512665, 0.024683, -0.012652, 1.262061, 0.512655,
+ 0.032257, -0.016532, 1.262858, 0.512656, 0.040826, -0.020919, 1.262709, 0.512649, 0.050403,
+ -0.025820, 1.262685, 0.512639, 0.060993, -0.031233, 1.262544, 0.512625, 0.072597, -0.037157,
+ 1.262435, 0.512607, 0.085211, -0.043587, 1.262209, 0.512581, 0.098842, -0.050520, 1.261907,
+ 0.512544, 0.113484, -0.057926, 1.261575, 0.512500, 0.129097, -0.065460, 1.261293, 0.512420,
+ 0.145727, -0.073543, 1.260736, 0.512316, 0.163375, -0.082134, 1.260117, 0.512190, 0.182011,
+ -0.091173, 1.259299, 0.512024, 0.201598, -0.100540, 1.258381, 0.511810, 0.222084, -0.109931,
+ 1.257293, 0.511505, 0.243446, -0.119838, 1.256050, 0.511151, 0.265574, -0.130090, 1.254607,
+ 0.510724, 0.288230, -0.140421, 1.252808, 0.510191, 0.311336, -0.151343, 1.250489, 0.509627,
+ 0.335719, -0.161689, 1.247279, 0.508688, 0.361314, -0.171748, 1.243467, 0.507393, 0.387541,
+ -0.181399, 1.239145, 0.505758, 0.414204, -0.190768, 1.233760, 0.503676, 0.441092, -0.199659,
+ 1.227433, 0.501129, 0.467789, -0.207934, 1.219247, 0.498078, 0.494454, -0.215747, 1.210441,
+ 0.494630, 0.520950, -0.222869, 1.200559, 0.490467, 0.547802, -0.228881, 1.189872, 0.485444,
+ 0.575563, -0.233760, 1.180081, 0.479268, 0.602426, -0.237566, 1.168544, 0.472272, 0.628772,
+ -0.240447, 1.156546, 0.464390, 0.654963, -0.242427, 1.145123, 0.455345, 0.681384, -0.242980,
+ 1.134322, 0.444885, 0.707173, -0.242150, 1.122665, 0.433338, 0.732477, -0.240435, 1.111733,
+ 0.420647, 0.757567, -0.237806, 1.101271, 0.406799, 0.782341, -0.233503, 1.091341, 0.391761,
+ 0.806690, -0.228346, 1.082042, 0.375576, 0.830804, -0.222386, 1.073504, 0.358545, 0.854940,
+ -0.215141, 1.065880, 0.340431, 0.878709, -0.207207, 1.058850, 0.321690, 0.901928, -0.198273,
+ 1.052588, 0.301930, 0.924845, -0.188476, 1.046521, 0.281513, 0.946932, -0.177996, 1.040966,
+ 0.261234, 0.969256, -0.166644, 1.036670, 0.240356, 0.991323, -0.154968, 1.032694, 0.219748,
+ 1.013013, -0.142425, 1.030061, 0.199103, 1.032845, -0.129456, 1.027254, 0.178936, 1.051887,
+ -0.115763, 1.025497, 0.159243, 1.069179, -0.101851, 1.023807, 0.139560, 1.084499, -0.087357,
+ 1.021441, 0.119607, 1.097921, -0.072796, 1.018780, 0.099501, 1.109281, -0.058037, 1.015566,
+ 0.079211, 1.118194, -0.043226, 1.011494, 0.058873, 1.125351, -0.028633, 1.007089, 0.038736,
+ 1.132002, -0.013996, 1.003014, 0.019063, 1.138951, 0.000132, 1.000036, -0.000007, 0.000200,
+ -0.000109, 1.296791, 0.544571, 0.000504, -0.000274, 1.296055, 0.544568, 0.002016, -0.001098,
+ 1.297239, 0.544568, 0.004535, -0.002470, 1.296600, 0.544568, 0.008062, -0.004390, 1.296368,
+ 0.544559, 0.012597, -0.006860, 1.296454, 0.544566, 0.018141, -0.009878, 1.296522, 0.544565,
+ 0.024693, -0.013444, 1.296536, 0.544560, 0.032256, -0.017559, 1.296638, 0.544557, 0.040824,
+ -0.022218, 1.296491, 0.544547, 0.050408, -0.027426, 1.296552, 0.544532, 0.060997, -0.033173,
+ 1.296283, 0.544518, 0.072600, -0.039463, 1.296113, 0.544496, 0.085220, -0.046292, 1.295894,
+ 0.544466, 0.098851, -0.053648, 1.295545, 0.544422, 0.113496, -0.061487, 1.295201, 0.544371,
+ 0.129112, -0.069467, 1.294754, 0.544273, 0.145765, -0.078092, 1.294209, 0.544160, 0.163431,
+ -0.087231, 1.293534, 0.544017, 0.182088, -0.096837, 1.292580, 0.543828, 0.201698, -0.106713,
+ 1.291586, 0.543585, 0.222231, -0.116699, 1.290325, 0.543238, 0.243653, -0.127208, 1.288888,
+ 0.542836, 0.265855, -0.137949, 1.287131, 0.542329, 0.288623, -0.148847, 1.284936, 0.541700,
+ 0.311830, -0.160204, 1.282109, 0.540997, 0.335728, -0.171324, 1.278036, 0.540045, 0.361403,
+ -0.181915, 1.273912, 0.538603, 0.387647, -0.192124, 1.268881, 0.536741, 0.414217, -0.201807,
+ 1.262363, 0.534432, 0.441090, -0.211093, 1.254755, 0.531623, 0.467823, -0.219678, 1.245456,
+ 0.528314, 0.494361, -0.227581, 1.234953, 0.524391, 0.521264, -0.235087, 1.224839, 0.519902,
+ 0.547881, -0.241508, 1.213175, 0.514574, 0.574965, -0.246315, 1.200505, 0.507837, 0.601847,
+ -0.250061, 1.187901, 0.500286, 0.628207, -0.252822, 1.174601, 0.491502, 0.654445, -0.254691,
+ 1.161944, 0.481726, 0.680175, -0.255318, 1.149305, 0.470727, 0.706168, -0.254257, 1.136708,
+ 0.458045, 0.731458, -0.252100, 1.124047, 0.444438, 0.756378, -0.249115, 1.112942, 0.429611,
+ 0.781311, -0.244899, 1.101800, 0.413501, 0.805755, -0.239225, 1.091662, 0.395889, 0.829867,
+ -0.232830, 1.082291, 0.377860, 0.853067, -0.225193, 1.072820, 0.358704, 0.877084, -0.216648,
+ 1.065415, 0.338413, 0.900123, -0.207390, 1.058403, 0.317596, 0.923370, -0.197095, 1.051412,
+ 0.296301, 0.946021, -0.186084, 1.045877, 0.274498, 0.967669, -0.174262, 1.040316, 0.252565,
+ 0.989761, -0.161814, 1.035489, 0.230312, 1.012163, -0.149076, 1.032540, 0.208746, 1.032547,
+ -0.135299, 1.029598, 0.187180, 1.052032, -0.121277, 1.027355, 0.166482, 1.069907, -0.106582,
+ 1.025622, 0.145939, 1.085563, -0.091589, 1.023244, 0.125362, 1.099447, -0.076263, 1.020661,
+ 0.104087, 1.110848, -0.060825, 1.017035, 0.083036, 1.119923, -0.045319, 1.012675, 0.061719,
+ 1.126805, -0.029852, 1.007668, 0.040583, 1.133282, -0.014846, 1.003335, 0.019969, 1.140128,
+ 0.000149, 1.000024, -0.000037, 0.000200, -0.000116, 1.334863, 0.577350, 0.000504, -0.000291,
+ 1.333350, 0.577348, 0.002015, -0.001164, 1.332853, 0.577347, 0.004535, -0.002618, 1.333295,
+ 0.577347, 0.008062, -0.004655, 1.333189, 0.577336, 0.012598, -0.007273, 1.333309, 0.577345,
+ 0.018141, -0.010472, 1.333274, 0.577342, 0.024694, -0.014253, 1.333231, 0.577339, 0.032254,
+ -0.018614, 1.333265, 0.577332, 0.040827, -0.023556, 1.333261, 0.577321, 0.050400, -0.029069,
+ 1.332893, 0.577309, 0.061000, -0.035166, 1.332998, 0.577288, 0.072608, -0.041833, 1.332901,
+ 0.577263, 0.085227, -0.049067, 1.332603, 0.577226, 0.098864, -0.056860, 1.332264, 0.577177,
+ 0.113507, -0.065114, 1.331825, 0.577109, 0.129146, -0.073610, 1.331311, 0.577005, 0.145808,
+ -0.082766, 1.330639, 0.576872, 0.163494, -0.092458, 1.329878, 0.576709, 0.182176, -0.102639,
+ 1.328889, 0.576501, 0.201804, -0.112983, 1.327710, 0.576207, 0.222394, -0.123650, 1.326256,
+ 0.575823, 0.243881, -0.134780, 1.324593, 0.575363, 0.266122, -0.145931, 1.322426, 0.574751,
+ 0.289043, -0.157500, 1.319837, 0.574033, 0.312330, -0.169208, 1.316301, 0.573181, 0.336120,
+ -0.181125, 1.312251, 0.572188, 0.361506, -0.192232, 1.307003, 0.570631, 0.387757, -0.202981,
+ 1.301068, 0.568558, 0.414365, -0.213160, 1.293695, 0.566027, 0.440986, -0.222617, 1.283958,
+ 0.562942, 0.467943, -0.231583, 1.274057, 0.559219, 0.494821, -0.239881, 1.262864, 0.554913,
+ 0.521486, -0.247336, 1.250633, 0.549953, 0.547884, -0.253921, 1.237448, 0.544251, 0.574582,
+ -0.259099, 1.223164, 0.537120, 0.601342, -0.262695, 1.208784, 0.528650, 0.627861, -0.265337,
+ 1.194424, 0.518978, 0.653745, -0.266872, 1.179361, 0.508525, 0.679348, -0.267403, 1.165010,
+ 0.496705, 0.705068, -0.266429, 1.151693, 0.482926, 0.730312, -0.263829, 1.137584, 0.468519,
+ 0.755576, -0.260491, 1.125328, 0.452213, 0.780371, -0.256166, 1.113759, 0.435127, 0.804632,
+ -0.250079, 1.101656, 0.416833, 0.828983, -0.243181, 1.091235, 0.397009, 0.852585, -0.235383,
+ 1.081475, 0.376647, 0.875237, -0.226031, 1.071806, 0.355506, 0.899152, -0.216343, 1.064453,
+ 0.333133, 0.922121, -0.205772, 1.057161, 0.311073, 0.944523, -0.193980, 1.050447, 0.287781,
+ 0.967313, -0.181920, 1.044531, 0.264350, 0.989042, -0.168822, 1.039312, 0.241128, 1.010881,
+ -0.155350, 1.035298, 0.218138, 1.032368, -0.141231, 1.032073, 0.195579, 1.052254, -0.126521,
+ 1.029395, 0.173399, 1.070207, -0.111243, 1.026938, 0.151866, 1.086528, -0.095617, 1.024957,
+ 0.130711, 1.100670, -0.079687, 1.021924, 0.108865, 1.112461, -0.063593, 1.018281, 0.086760,
+ 1.121588, -0.047313, 1.013747, 0.064575, 1.128522, -0.031385, 1.008433, 0.042499, 1.134759,
+ -0.015356, 1.003569, 0.020840, 1.141448, 0.000114, 0.999978, -0.000056, 0.000200, -0.000122,
+ 1.372763, 0.611086, 0.000503, -0.000308, 1.371456, 0.611084, 0.002016, -0.001232, 1.373440,
+ 0.611084, 0.004535, -0.002771, 1.373387, 0.611083, 0.008061, -0.004926, 1.372916, 0.611083,
+ 0.012601, -0.007700, 1.373956, 0.611084, 0.018142, -0.011084, 1.373419, 0.611078, 0.024695,
+ -0.015087, 1.373492, 0.611074, 0.032255, -0.019701, 1.373360, 0.611066, 0.040827, -0.024930,
+ 1.373327, 0.611055, 0.050408, -0.030769, 1.373222, 0.611037, 0.061004, -0.037217, 1.373079,
+ 0.611014, 0.072613, -0.044270, 1.372895, 0.610982, 0.085238, -0.051923, 1.372624, 0.610941,
+ 0.098878, -0.060161, 1.372252, 0.610883, 0.113522, -0.068785, 1.371785, 0.610798, 0.129176,
+ -0.077863, 1.371103, 0.610683, 0.145876, -0.087593, 1.370541, 0.610537, 0.163570, -0.097847,
+ 1.369496, 0.610349, 0.182283, -0.108592, 1.368477, 0.610109, 0.201930, -0.119420, 1.366980,
+ 0.609763, 0.222570, -0.130789, 1.365375, 0.609343, 0.244123, -0.142514, 1.363456, 0.608815,
+ 0.266437, -0.154232, 1.360916, 0.608114, 0.289467, -0.166370, 1.357909, 0.607291, 0.312861,
+ -0.178505, 1.353588, 0.606272, 0.336736, -0.190980, 1.349211, 0.605153, 0.361740, -0.202859,
+ 1.343319, 0.603548, 0.387878, -0.213997, 1.335908, 0.601268, 0.414357, -0.224584, 1.326676,
+ 0.598499, 0.441442, -0.234664, 1.317331, 0.595066, 0.468409, -0.243875, 1.305818, 0.590996,
+ 0.494999, -0.252121, 1.291863, 0.586293, 0.521730, -0.259714, 1.278212, 0.580840, 0.547894,
+ -0.266242, 1.262656, 0.574494, 0.573865, -0.271578, 1.246364, 0.567007, 0.601124, -0.275503,
+ 1.231274, 0.557771, 0.627606, -0.277954, 1.215252, 0.547255, 0.654004, -0.279404, 1.199977,
+ 0.535766, 0.679554, -0.279632, 1.183995, 0.522792, 0.704280, -0.278457, 1.167428, 0.508488,
+ 0.729830, -0.275706, 1.152760, 0.492425, 0.754376, -0.271640, 1.137942, 0.475285, 0.779209,
+ -0.266911, 1.125222, 0.456679, 0.803562, -0.260838, 1.112179, 0.437267, 0.827985, -0.253353,
+ 1.101439, 0.416227, 0.851737, -0.245027, 1.089890, 0.394728, 0.874850, -0.235719, 1.080018,
+ 0.372244, 0.897680, -0.225051, 1.070807, 0.348846, 0.921351, -0.214051, 1.063180, 0.324961,
+ 0.943818, -0.202039, 1.056148, 0.300836, 0.966368, -0.189134, 1.049277, 0.276333, 0.987426,
+ -0.175613, 1.042176, 0.251862, 1.010162, -0.161473, 1.038567, 0.227217, 1.031224, -0.146866,
+ 1.034102, 0.203582, 1.052317, -0.131644, 1.031600, 0.180629, 1.070879, -0.115909, 1.028913,
+ 0.158165, 1.087407, -0.099638, 1.026193, 0.135905, 1.102159, -0.083091, 1.023567, 0.113394,
+ 1.114006, -0.066178, 1.019567, 0.090325, 1.123374, -0.049430, 1.014856, 0.067302, 1.130310,
+ -0.032557, 1.009141, 0.044264, 1.136334, -0.016157, 1.003984, 0.021807, 1.142961, 0.000172,
+ 0.999951, -0.000077, 0.000200, -0.000129, 1.416584, 0.645866, 0.000504, -0.000326, 1.417762,
+ 0.645865, 0.002016, -0.001302, 1.417825, 0.645866, 0.004535, -0.002929, 1.417142, 0.645865,
+ 0.008062, -0.005207, 1.416968, 0.645864, 0.012598, -0.008136, 1.417109, 0.645862, 0.018141,
+ -0.011715, 1.417001, 0.645859, 0.024690, -0.015941, 1.416878, 0.645853, 0.032257, -0.020823,
+ 1.417134, 0.645843, 0.040827, -0.026347, 1.416983, 0.645829, 0.050411, -0.032518, 1.416949,
+ 0.645808, 0.061007, -0.039330, 1.416694, 0.645781, 0.072621, -0.046783, 1.416599, 0.645746,
+ 0.085249, -0.054865, 1.416241, 0.645695, 0.098897, -0.063563, 1.415832, 0.645630, 0.113546,
+ -0.072607, 1.415264, 0.645529, 0.129220, -0.082257, 1.414482, 0.645396, 0.145888, -0.092515,
+ 1.413626, 0.645268, 0.163659, -0.103393, 1.412710, 0.645018, 0.182385, -0.114684, 1.411418,
+ 0.644739, 0.202078, -0.126098, 1.409822, 0.644348, 0.222772, -0.138145, 1.407948, 0.643872,
+ 0.244370, -0.150405, 1.405678, 0.643255, 0.266787, -0.162798, 1.402763, 0.642463, 0.289844,
+ -0.175434, 1.398863, 0.641504, 0.313540, -0.188158, 1.394695, 0.640346, 0.337489, -0.201014,
+ 1.389376, 0.639042, 0.362008, -0.213719, 1.382439, 0.637412, 0.387990, -0.225248, 1.373281,
+ 0.634930, 0.414728, -0.236348, 1.363729, 0.631861, 0.441635, -0.246701, 1.352304, 0.628155,
+ 0.468588, -0.256167, 1.339162, 0.623625, 0.495337, -0.264662, 1.323811, 0.618458, 0.521886,
+ -0.272207, 1.307630, 0.612373, 0.548355, -0.278890, 1.291265, 0.605263, 0.574535, -0.284442,
+ 1.273752, 0.597048, 0.600870, -0.288389, 1.256171, 0.587401, 0.627715, -0.290816, 1.238447,
+ 0.576001, 0.653830, -0.291886, 1.221036, 0.563198, 0.679175, -0.291629, 1.202283, 0.549249,
+ 0.704539, -0.290489, 1.185866, 0.533881, 0.729126, -0.287529, 1.168822, 0.516966, 0.754297,
+ -0.283184, 1.152934, 0.498501, 0.778678, -0.277732, 1.137821, 0.478728, 0.802473, -0.271203,
+ 1.123387, 0.457814, 0.826596, -0.263494, 1.110573, 0.435865, 0.850835, -0.254572, 1.099099,
+ 0.412597, 0.874203, -0.244815, 1.088403, 0.388995, 0.897271, -0.233993, 1.078085, 0.364487,
+ 0.919667, -0.221934, 1.068543, 0.339344, 0.943001, -0.209714, 1.061081, 0.313770, 0.965688,
+ -0.196367, 1.054023, 0.287928, 0.987598, -0.182263, 1.047247, 0.262157, 1.009280, -0.167775,
+ 1.041376, 0.236855, 1.031762, -0.152530, 1.037647, 0.211847, 1.051965, -0.136809, 1.033396,
+ 0.187546, 1.071699, -0.120418, 1.031021, 0.164186, 1.088881, -0.103618, 1.028403, 0.141184,
+ 1.103482, -0.086271, 1.024987, 0.117665, 1.115646, -0.068973, 1.020884, 0.093896, 1.125258,
+ -0.051285, 1.015966, 0.069978, 1.132045, -0.033998, 1.009990, 0.046126, 1.138004, -0.016696,
+ 1.004270, 0.022635, 1.144463, 0.000089, 0.999987, -0.000016, 0.000200, -0.000136, 1.463614,
+ 0.681786, 0.000504, -0.000344, 1.465345, 0.681785, 0.002015, -0.001374, 1.464172, 0.681783,
+ 0.004535, -0.003092, 1.464846, 0.681784, 0.008062, -0.005496, 1.464783, 0.681784, 0.012598,
+ -0.008588, 1.464883, 0.681781, 0.018141, -0.012366, 1.464740, 0.681777, 0.024692, -0.016829,
+ 1.464665, 0.681770, 0.032258, -0.021980, 1.464720, 0.681760, 0.040829, -0.027811, 1.464625,
+ 0.681742, 0.050415, -0.034324, 1.464571, 0.681720, 0.061013, -0.041513, 1.464346, 0.681688,
+ 0.072628, -0.049375, 1.464131, 0.681644, 0.085264, -0.057903, 1.463847, 0.681588, 0.098918,
+ -0.067067, 1.463369, 0.681509, 0.113568, -0.076570, 1.462549, 0.681389, 0.129265, -0.086782,
+ 1.461703, 0.681239, 0.145997, -0.097637, 1.460840, 0.681047, 0.163751, -0.109101, 1.459737,
+ 0.680806, 0.182505, -0.120922, 1.458231, 0.680480, 0.202241, -0.133007, 1.456393, 0.680042,
+ 0.222987, -0.145693, 1.454258, 0.679503, 0.244638, -0.158488, 1.451543, 0.678792, 0.267132,
+ -0.171585, 1.448115, 0.677907, 0.290365, -0.184746, 1.443992, 0.676796, 0.314178, -0.198101,
+ 1.439271, 0.675498, 0.338289, -0.211370, 1.432830, 0.673922, 0.362543, -0.224489, 1.424163,
+ 0.672151, 0.388470, -0.236914, 1.415160, 0.669601, 0.415105, -0.248342, 1.403811, 0.666255,
+ 0.441925, -0.258957, 1.390149, 0.662166, 0.468668, -0.268556, 1.374104, 0.657229, 0.495720,
+ -0.277359, 1.358102, 0.651347, 0.522574, -0.285078, 1.340754, 0.644598, 0.548981, -0.291718,
+ 1.322033, 0.636820, 0.574946, -0.297087, 1.302148, 0.627812, 0.600744, -0.301079, 1.282130,
+ 0.617485, 0.627565, -0.303566, 1.263339, 0.605047, 0.653598, -0.304330, 1.242712, 0.591167,
+ 0.679239, -0.303820, 1.223212, 0.576025, 0.704043, -0.302064, 1.203763, 0.559649, 0.728796,
+ -0.299095, 1.185434, 0.541271, 0.753581, -0.294392, 1.167630, 0.521800, 0.778577, -0.288603,
+ 1.151930, 0.500628, 0.802550, -0.281604, 1.136072, 0.478434, 0.825803, -0.273472, 1.121673,
+ 0.455384, 0.849768, -0.264011, 1.108491, 0.430811, 0.873250, -0.253653, 1.096550, 0.405524,
+ 0.896725, -0.242642, 1.085905, 0.380038, 0.919158, -0.230191, 1.075091, 0.353482, 0.942236,
+ -0.217145, 1.066848, 0.326605, 0.965031, -0.203555, 1.059310, 0.299842, 0.987048, -0.188777,
+ 1.051749, 0.272859, 1.008718, -0.173613, 1.044999, 0.246040, 1.031097, -0.157972, 1.040066,
+ 0.219826, 1.052493, -0.141589, 1.035951, 0.194278, 1.071773, -0.124814, 1.032520, 0.169830,
+ 1.089646, -0.107321, 1.029803, 0.146135, 1.104932, -0.089726, 1.026612, 0.122127, 1.117687,
+ -0.071433, 1.022391, 0.097461, 1.127188, -0.053395, 1.017113, 0.072556, 1.134010, -0.035151,
+ 1.010934, 0.047749, 1.139746, -0.017427, 1.004633, 0.023530, 1.146205, 0.000151, 1.000020,
+ -0.000106, 0.000200, -0.000144, 1.517643, 0.718949, 0.000504, -0.000362, 1.516387, 0.718947,
+ 0.002016, -0.001449, 1.516742, 0.718946, 0.004536, -0.003261, 1.517196, 0.718946, 0.008063,
+ -0.005796, 1.516806, 0.718945, 0.012598, -0.009057, 1.516986, 0.718943, 0.018140, -0.013039,
+ 1.516603, 0.718937, 0.024694, -0.017747, 1.516739, 0.718929, 0.032260, -0.023178, 1.516994,
+ 0.718917, 0.040831, -0.029325, 1.516649, 0.718896, 0.050419, -0.036192, 1.516594, 0.718870,
+ 0.061019, -0.043770, 1.516327, 0.718833, 0.072638, -0.052056, 1.516054, 0.718782, 0.085274,
+ -0.061039, 1.515628, 0.718714, 0.098938, -0.070676, 1.515199, 0.718623, 0.113607, -0.080679,
+ 1.514222, 0.718483, 0.129329, -0.091485, 1.513354, 0.718316, 0.146077, -0.102931, 1.512301,
+ 0.718096, 0.163856, -0.114986, 1.510977, 0.717818, 0.182640, -0.127305, 1.509225, 0.717432,
+ 0.202432, -0.140147, 1.507152, 0.716939, 0.223229, -0.153468, 1.504780, 0.716331, 0.244943,
+ -0.166875, 1.501612, 0.715527, 0.267559, -0.180658, 1.497898, 0.714523, 0.290926, -0.194405,
+ 1.493208, 0.713266, 0.314863, -0.208302, 1.487388, 0.711758, 0.339053, -0.222020, 1.479677,
+ 0.709982, 0.363627, -0.235683, 1.470950, 0.707958, 0.388887, -0.248723, 1.459907, 0.705346,
+ 0.415474, -0.260563, 1.446579, 0.701644, 0.442065, -0.271352, 1.429962, 0.697134, 0.469418,
+ -0.281541, 1.414343, 0.691665, 0.496419, -0.290429, 1.395681, 0.685227, 0.523071, -0.298032,
+ 1.375347, 0.677815, 0.549641, -0.304679, 1.354816, 0.669063, 0.575489, -0.309902, 1.332505,
+ 0.659071, 0.601108, -0.313771, 1.309752, 0.647799, 0.627199, -0.316225, 1.288381, 0.634856,
+ 0.653243, -0.316679, 1.265785, 0.619627, 0.678960, -0.315816, 1.244333, 0.603244, 0.704055,
+ -0.313776, 1.223315, 0.585191, 0.728713, -0.310417, 1.203142, 0.565969, 0.753301, -0.305786,
+ 1.184323, 0.545347, 0.777890, -0.299262, 1.166070, 0.522753, 0.802354, -0.291830, 1.149599,
+ 0.499017, 0.826005, -0.283281, 1.133655, 0.474335, 0.848920, -0.273512, 1.118132, 0.449019,
+ 0.872765, -0.262525, 1.105606, 0.422329, 0.895950, -0.250769, 1.093539, 0.395057, 0.918816,
+ -0.238257, 1.082388, 0.367709, 0.941089, -0.224381, 1.072484, 0.339350, 0.964514, -0.210289,
+ 1.064054, 0.311239, 0.987128, -0.195488, 1.056645, 0.283272, 1.009064, -0.179491, 1.049549,
+ 0.255163, 1.030163, -0.163172, 1.042741, 0.227757, 1.052502, -0.146457, 1.038270, 0.200970,
+ 1.072971, -0.129054, 1.035014, 0.175767, 1.091223, -0.111285, 1.032231, 0.151118, 1.106518,
+ -0.092617, 1.028211, 0.126196, 1.119235, -0.074168, 1.023686, 0.100828, 1.129311, -0.055212,
+ 1.018311, 0.075240, 1.135983, -0.036571, 1.011485, 0.049558, 1.141648, -0.017954, 1.004952,
+ 0.024273, 1.147938, 0.000125, 1.000009, -0.000048, 0.000199, -0.000151, 1.566887, 0.757466,
+ 0.000504, -0.000382, 1.574111, 0.757466, 0.002016, -0.001527, 1.573735, 0.757466, 0.004535,
+ -0.003435, 1.573737, 0.757466, 0.008062, -0.006107, 1.573782, 0.757464, 0.012599, -0.009542,
+ 1.573796, 0.757460, 0.018142, -0.013739, 1.573710, 0.757455, 0.024694, -0.018697, 1.573562,
+ 0.757446, 0.032259, -0.024418, 1.573667, 0.757429, 0.040834, -0.030895, 1.573555, 0.757407,
+ 0.050422, -0.038127, 1.573383, 0.757376, 0.061025, -0.046108, 1.573086, 0.757332, 0.072650,
+ -0.054835, 1.572833, 0.757274, 0.085296, -0.064294, 1.572395, 0.757195, 0.098962, -0.074376,
+ 1.571729, 0.757087, 0.113649, -0.084955, 1.570571, 0.756925, 0.129389, -0.096334, 1.569582,
+ 0.756729, 0.146167, -0.108406, 1.568444, 0.756481, 0.163973, -0.121056, 1.566905, 0.756158,
+ 0.182798, -0.133970, 1.564939, 0.755715, 0.202650, -0.147522, 1.562666, 0.755167, 0.223502,
+ -0.161466, 1.559877, 0.754465, 0.245269, -0.175539, 1.556008, 0.753552, 0.268010, -0.189957,
+ 1.552013, 0.752420, 0.291474, -0.204361, 1.546509, 0.751008, 0.315527, -0.218714, 1.539575,
+ 0.749266, 0.339954, -0.233029, 1.530968, 0.747232, 0.364649, -0.247149, 1.520994, 0.744906,
+ 0.389520, -0.260672, 1.507748, 0.742123, 0.415717, -0.272873, 1.491777, 0.738187, 0.442862,
+ -0.284317, 1.475658, 0.733189, 0.469939, -0.294552, 1.456572, 0.727165, 0.496916, -0.303517,
+ 1.435237, 0.720043, 0.523480, -0.311061, 1.412192, 0.711640, 0.550092, -0.317596, 1.389033,
+ 0.702174, 0.576384, -0.322921, 1.365086, 0.691225, 0.602280, -0.326806, 1.341317, 0.678841,
+ 0.627676, -0.329057, 1.316518, 0.664815, 0.653458, -0.329372, 1.291877, 0.648548, 0.679227,
+ -0.328067, 1.268126, 0.630676, 0.704476, -0.325585, 1.244424, 0.611585, 0.729232, -0.321775,
+ 1.223010, 0.590803, 0.753405, -0.316713, 1.201297, 0.568653, 0.777274, -0.309858, 1.181071,
+ 0.544763, 0.801882, -0.301866, 1.162826, 0.519747, 0.826030, -0.292861, 1.145704, 0.493531,
+ 0.849359, -0.282794, 1.129629, 0.466900, 0.871837, -0.271197, 1.114155, 0.439230, 0.895896,
+ -0.258954, 1.102334, 0.410570, 0.918951, -0.245878, 1.090163, 0.381314, 0.941148, -0.231897,
+ 1.078738, 0.352268, 0.963464, -0.216743, 1.068862, 0.322688, 0.986628, -0.201486, 1.061077,
+ 0.293523, 1.009289, -0.185521, 1.053561, 0.264125, 1.030659, -0.168429, 1.046627, 0.235706,
+ 1.052382, -0.151210, 1.040953, 0.208022, 1.073476, -0.133289, 1.036534, 0.181245, 1.092237,
+ -0.114768, 1.033580, 0.155661, 1.108200, -0.095917, 1.029997, 0.130223, 1.121435, -0.076492,
+ 1.025374, 0.104098, 1.131382, -0.057204, 1.019485, 0.077776, 1.137994, -0.037747, 1.012188,
+ 0.051250, 1.143441, -0.018673, 1.005309, 0.025245, 1.149714, 0.000216, 1.000004, -0.000120,
+ 0.000200, -0.000159, 1.633988, 0.797469, 0.000504, -0.000402, 1.636076, 0.797469, 0.002016,
+ -0.001607, 1.635679, 0.797467, 0.004535, -0.003617, 1.636040, 0.797468, 0.008063, -0.006430,
+ 1.636159, 0.797467, 0.012599, -0.010046, 1.636128, 0.797462, 0.018141, -0.014464, 1.635730,
+ 0.797457, 0.024696, -0.019685, 1.635836, 0.797445, 0.032259, -0.025705, 1.635719, 0.797426,
+ 0.040835, -0.032523, 1.635610, 0.797401, 0.050425, -0.040135, 1.635460, 0.797363, 0.061033,
+ -0.048536, 1.635182, 0.797313, 0.072661, -0.057718, 1.634817, 0.797243, 0.085315, -0.067666,
+ 1.634314, 0.797150, 0.098985, -0.078179, 1.633350, 0.797016, 0.113699, -0.089383, 1.632253,
+ 0.796839, 0.129456, -0.101364, 1.631025, 0.796623, 0.146275, -0.114081, 1.629867, 0.796331,
+ 0.164108, -0.127318, 1.628043, 0.795956, 0.182983, -0.140901, 1.625813, 0.795458, 0.202891,
+ -0.155174, 1.623149, 0.794834, 0.223787, -0.169654, 1.619686, 0.794015, 0.245678, -0.184540,
+ 1.615694, 0.793013, 0.268495, -0.199543, 1.610812, 0.791727, 0.292093, -0.214639, 1.604629,
+ 0.790107, 0.316184, -0.229499, 1.596061, 0.788154, 0.340986, -0.244407, 1.587195, 0.785797,
+ 0.365808, -0.258907, 1.575031, 0.783093, 0.390528, -0.272746, 1.559448, 0.779970, 0.416510,
+ -0.285845, 1.543294, 0.775852, 0.443443, -0.297404, 1.523476, 0.770323, 0.470442, -0.307757,
+ 1.501515, 0.763721, 0.497499, -0.316846, 1.477841, 0.755889, 0.524316, -0.324561, 1.452427,
+ 0.746662, 0.551212, -0.331060, 1.427421, 0.736004, 0.577323, -0.335956, 1.400369, 0.723810,
+ 0.602976, -0.339501, 1.373093, 0.710184, 0.628357, -0.341577, 1.345853, 0.695017, 0.653642,
+ -0.342031, 1.319040, 0.677972, 0.679440, -0.340342, 1.292490, 0.658877, 0.704744, -0.337356,
+ 1.267182, 0.638085, 0.729692, -0.333042, 1.243280, 0.615615, 0.753920, -0.327504, 1.219751,
+ 0.592054, 0.777695, -0.320537, 1.197796, 0.566967, 0.801426, -0.311880, 1.176872, 0.540643,
+ 0.825649, -0.302211, 1.158160, 0.512906, 0.849282, -0.291665, 1.141257, 0.484587, 0.872341,
+ -0.280050, 1.125469, 0.455556, 0.895110, -0.266978, 1.110222, 0.425652, 0.918841, -0.253326,
+ 1.097419, 0.395015, 0.941209, -0.238899, 1.086101, 0.364948, 0.963142, -0.223523, 1.075023,
+ 0.334151, 0.985996, -0.207346, 1.065628, 0.303708, 1.008718, -0.190889, 1.057256, 0.273008,
+ 1.030554, -0.173517, 1.049720, 0.243221, 1.053085, -0.155645, 1.043837, 0.214426, 1.074267,
+ -0.137472, 1.039312, 0.187036, 1.093591, -0.118385, 1.035457, 0.160512, 1.109850, -0.098883,
+ 1.031630, 0.134384, 1.123516, -0.079050, 1.026762, 0.107424, 1.133578, -0.058977, 1.020640,
+ 0.080317, 1.140289, -0.039013, 1.013096, 0.052944, 1.145610, -0.019228, 1.005694, 0.025989,
+ 1.151704, 0.000105, 0.999981, -0.000019, 0.000200, -0.000168, 1.704841, 0.839096, 0.000504,
+ -0.000423, 1.704242, 0.839097, 0.002016, -0.001691, 1.703821, 0.839091, 0.004534, -0.003805,
+ 1.703804, 0.839094, 0.008063, -0.006765, 1.704224, 0.839092, 0.012598, -0.010570, 1.704013,
+ 0.839087, 0.018142, -0.015219, 1.703889, 0.839079, 0.024697, -0.020712, 1.704023, 0.839066,
+ 0.032261, -0.027046, 1.703836, 0.839045, 0.040837, -0.034218, 1.703608, 0.839014, 0.050429,
+ -0.042224, 1.703414, 0.838972, 0.061041, -0.051061, 1.703148, 0.838912, 0.072676, -0.060717,
+ 1.702744, 0.838831, 0.085340, -0.071175, 1.702223, 0.838724, 0.099023, -0.082182, 1.700984,
+ 0.838567, 0.113759, -0.094007, 1.699764, 0.838367, 0.129546, -0.106621, 1.698462, 0.838112,
+ 0.146382, -0.119956, 1.696938, 0.837782, 0.164260, -0.133760, 1.694868, 0.837346, 0.183188,
+ -0.148108, 1.692262, 0.836780, 0.203158, -0.163075, 1.689251, 0.836073, 0.224147, -0.178255,
+ 1.685408, 0.835148, 0.246147, -0.193900, 1.680946, 0.833992, 0.269072, -0.209553, 1.675277,
+ 0.832546, 0.292718, -0.225226, 1.667626, 0.830727, 0.317159, -0.240836, 1.658952, 0.828510,
+ 0.341979, -0.256103, 1.647624, 0.825843, 0.366844, -0.270887, 1.633014, 0.822760, 0.392043,
+ -0.285324, 1.617191, 0.819159, 0.417356, -0.298817, 1.597501, 0.814788, 0.444093, -0.310711,
+ 1.575184, 0.808751, 0.471379, -0.321410, 1.551590, 0.801294, 0.498267, -0.330421, 1.524134,
+ 0.792711, 0.525401, -0.338331, 1.496672, 0.782480, 0.551846, -0.344430, 1.467062, 0.770659,
+ 0.578009, -0.349047, 1.436943, 0.757348, 0.604054, -0.352490, 1.407611, 0.742541, 0.629387,
+ -0.354158, 1.377441, 0.726071, 0.654435, -0.354422, 1.347651, 0.707524, 0.679845, -0.352663,
+ 1.318769, 0.687067, 0.704892, -0.348994, 1.290600, 0.664637, 0.729763, -0.344105, 1.263997,
+ 0.640663, 0.754345, -0.338129, 1.239273, 0.615484, 0.778629, -0.330905, 1.215858, 0.589210,
+ 0.801939, -0.322113, 1.192318, 0.561550, 0.825723, -0.311673, 1.171380, 0.532175, 0.849387,
+ -0.300410, 1.152991, 0.502055, 0.872792, -0.288328, 1.136139, 0.471308, 0.895083, -0.275087,
+ 1.119534, 0.440427, 0.918335, -0.260700, 1.105542, 0.409260, 0.941577, -0.245717, 1.093070,
+ 0.377142, 0.963992, -0.230079, 1.081207, 0.345289, 0.986510, -0.213523, 1.071488, 0.313508,
+ 1.008806, -0.196157, 1.062011, 0.281962, 1.030724, -0.178467, 1.053240, 0.251177, 1.053782,
+ -0.160291, 1.047057, 0.220986, 1.075451, -0.141308, 1.041842, 0.192256, 1.094947, -0.121975,
+ 1.037704, 0.165023, 1.111783, -0.101744, 1.033300, 0.138228, 1.125525, -0.081476, 1.028234,
+ 0.110679, 1.135873, -0.060770, 1.021695, 0.082672, 1.142478, -0.040207, 1.013838, 0.054506,
+ 1.147889, -0.019908, 1.006166, 0.026938, 1.153852, 0.000204, 0.999983, -0.000123, 0.000199,
+ -0.000176, 1.771601, 0.882501, 0.000504, -0.000445, 1.779195, 0.882504, 0.002016, -0.001779,
+ 1.779635, 0.882498, 0.004536, -0.004003, 1.779586, 0.882499, 0.008062, -0.007115, 1.778613,
+ 0.882496, 0.012598, -0.011116, 1.778678, 0.882492, 0.018142, -0.016005, 1.778531, 0.882481,
+ 0.024696, -0.021782, 1.778556, 0.882466, 0.032262, -0.028444, 1.778507, 0.882442, 0.040842,
+ -0.035987, 1.778385, 0.882408, 0.050436, -0.044404, 1.778034, 0.882364, 0.061053, -0.053695,
+ 1.777761, 0.882287, 0.072692, -0.063842, 1.777256, 0.882190, 0.085364, -0.074821, 1.776518,
+ 0.882067, 0.099064, -0.086368, 1.775080, 0.881884, 0.113828, -0.098805, 1.773836, 0.881657,
+ 0.129649, -0.112090, 1.772370, 0.881361, 0.146518, -0.126067, 1.770594, 0.880982, 0.164440,
+ -0.140493, 1.768089, 0.880484, 0.183437, -0.155646, 1.765301, 0.879843, 0.203468, -0.171266,
+ 1.761698, 0.879035, 0.224562, -0.187231, 1.757518, 0.877982, 0.246665, -0.203540, 1.752318,
+ 0.876667, 0.269652, -0.219916, 1.745356, 0.875028, 0.293531, -0.236255, 1.737186, 0.872977,
+ 0.318048, -0.252410, 1.726709, 0.870448, 0.342963, -0.268192, 1.713109, 0.867400, 0.368336,
+ -0.283587, 1.698087, 0.863882, 0.393512, -0.298186, 1.678638, 0.859724, 0.418602, -0.311882,
+ 1.655604, 0.854835, 0.445080, -0.324500, 1.632250, 0.848353, 0.472289, -0.335295, 1.605069,
+ 0.840218, 0.499128, -0.344256, 1.573846, 0.830556, 0.525834, -0.351716, 1.541120, 0.819269,
+ 0.553177, -0.358241, 1.511385, 0.806222, 0.579480, -0.362640, 1.477866, 0.791647, 0.605205,
+ -0.365513, 1.444218, 0.775398, 0.630617, -0.366822, 1.410954, 0.757144, 0.655730, -0.366785,
+ 1.379010, 0.737323, 0.680529, -0.364904, 1.347280, 0.715601, 0.705800, -0.360990, 1.316416,
+ 0.691547, 0.730550, -0.355397, 1.286344, 0.666141, 0.754970, -0.348664, 1.258954, 0.638929,
+ 0.779042, -0.340774, 1.232965, 0.611015, 0.802839, -0.331767, 1.209775, 0.581877, 0.825793,
+ -0.321054, 1.185813, 0.551509, 0.849512, -0.309016, 1.165080, 0.519698, 0.873120, -0.296369,
+ 1.147091, 0.487506, 0.895942, -0.282704, 1.129658, 0.455320, 0.917996, -0.268007, 1.113463,
+ 0.422605, 0.941281, -0.252329, 1.100040, 0.389347, 0.964584, -0.236203, 1.087973, 0.356430,
+ 0.986371, -0.219209, 1.075983, 0.323089, 1.009522, -0.201588, 1.066940, 0.290806, 1.031976,
+ -0.183296, 1.057999, 0.258682, 1.053461, -0.164509, 1.049542, 0.227722, 1.076121, -0.145165,
+ 1.043718, 0.197439, 1.096597, -0.125199, 1.039607, 0.169578, 1.113908, -0.104921, 1.035528,
+ 0.142222, 1.127939, -0.083623, 1.029807, 0.113802, 1.138391, -0.062589, 1.023312, 0.085164,
+ 1.145110, -0.041376, 1.014806, 0.056186, 1.150141, -0.020433, 1.006501, 0.027654, 1.156069,
+ 0.000097, 0.999949, -0.000046, 0.000200, -0.000185, 1.858268, 0.927857, 0.000504, -0.000468,
+ 1.861583, 0.927859, 0.002016, -0.001870, 1.860659, 0.927855, 0.004535, -0.004208, 1.860963,
+ 0.927867, 0.008063, -0.007480, 1.860766, 0.927855, 0.012594, -0.011683, 1.859996, 0.927851,
+ 0.018142, -0.016828, 1.860739, 0.927839, 0.024698, -0.022901, 1.860763, 0.927818, 0.032263,
+ -0.029903, 1.860501, 0.927791, 0.040846, -0.037834, 1.860431, 0.927751, 0.050440, -0.046680,
+ 1.859827, 0.927690, 0.061066, -0.056446, 1.859624, 0.927610, 0.072713, -0.067109, 1.859039,
+ 0.927505, 0.085393, -0.078613, 1.858144, 0.927357, 0.099120, -0.090747, 1.856618, 0.927145,
+ 0.113910, -0.103850, 1.855221, 0.926884, 0.129755, -0.117777, 1.853470, 0.926546, 0.146669,
+ -0.132441, 1.851413, 0.926104, 0.164648, -0.147565, 1.848498, 0.925530, 0.183708, -0.163470,
+ 1.845281, 0.924802, 0.203832, -0.179763, 1.841273, 0.923871, 0.225029, -0.196564, 1.836481,
+ 0.922691, 0.247221, -0.213537, 1.830273, 0.921198, 0.270343, -0.230662, 1.822374, 0.919320,
+ 0.294399, -0.247740, 1.812975, 0.917008, 0.319040, -0.264448, 1.800693, 0.914141, 0.344269,
+ -0.280831, 1.785923, 0.910707, 0.369625, -0.296478, 1.767203, 0.906585, 0.394925, -0.311287,
+ 1.744434, 0.901918, 0.420583, -0.325578, 1.720938, 0.896240, 0.446200, -0.338384, 1.693005,
+ 0.889335, 0.472969, -0.349187, 1.660901, 0.880394, 0.500490, -0.358687, 1.628806, 0.869705,
+ 0.527312, -0.366042, 1.593001, 0.857145, 0.554207, -0.372045, 1.557046, 0.842943, 0.580620,
+ -0.376134, 1.520192, 0.826837, 0.606480, -0.378636, 1.482947, 0.808891, 0.631815, -0.379414,
+ 1.445954, 0.789119, 0.657021, -0.378972, 1.410833, 0.767564, 0.681686, -0.376728, 1.376575,
+ 0.744338, 0.706498, -0.372844, 1.342935, 0.718799, 0.731258, -0.366649, 1.311052, 0.691756,
+ 0.755937, -0.359354, 1.280478, 0.662683, 0.779259, -0.350487, 1.250585, 0.632892, 0.803295,
+ -0.340941, 1.225722, 0.602160, 0.826570, -0.330174, 1.201003, 0.570520, 0.849954, -0.317854,
+ 1.178488, 0.537651, 0.873696, -0.304426, 1.158302, 0.503799, 0.896695, -0.290120, 1.139886,
+ 0.469645, 0.919149, -0.275106, 1.122884, 0.435625, 0.942121, -0.259282, 1.107691, 0.401228,
+ 0.964627, -0.242123, 1.093661, 0.367086, 0.986614, -0.224575, 1.081580, 0.332885, 1.009623,
+ -0.206837, 1.071375, 0.299209, 1.033126, -0.188092, 1.062241, 0.266187, 1.054954, -0.168637,
+ 1.052912, 0.233733, 1.077660, -0.149166, 1.047047, 0.203192, 1.097983, -0.128587, 1.041607,
+ 0.173918, 1.115586, -0.107339, 1.036850, 0.145531, 1.130170, -0.086203, 1.031427, 0.116890,
+ 1.141018, -0.064171, 1.024395, 0.087388, 1.147681, -0.042530, 1.015719, 0.057733, 1.152560,
+ -0.021011, 1.006883, 0.028413, 1.158406, 0.000158, 0.999897, -0.000106, 0.000200, -0.000195,
+ 1.950982, 0.975366, 0.000504, -0.000491, 1.950207, 0.975365, 0.002015, -0.001966, 1.950675,
+ 0.975362, 0.004535, -0.004423, 1.951281, 0.975370, 0.008062, -0.007863, 1.951045, 0.975362,
+ 0.012597, -0.012285, 1.951199, 0.975356, 0.018145, -0.017692, 1.951528, 0.975340, 0.024699,
+ -0.024074, 1.951194, 0.975321, 0.032266, -0.031434, 1.950865, 0.975288, 0.040853, -0.039771,
+ 1.951038, 0.975244, 0.050452, -0.049067, 1.950336, 0.975173, 0.061077, -0.059324, 1.949805,
+ 0.975078, 0.072736, -0.070526, 1.949133, 0.974951, 0.085431, -0.082528, 1.947947, 0.974777,
+ 0.099182, -0.095345, 1.946337, 0.974540, 0.113999, -0.109118, 1.944725, 0.974241, 0.129888,
+ -0.123741, 1.942857, 0.973852, 0.146842, -0.139071, 1.940251, 0.973342, 0.164890, -0.154986,
+ 1.937086, 0.972684, 0.184025, -0.171661, 1.933404, 0.971856, 0.204245, -0.188672, 1.928770,
+ 0.970785, 0.225528, -0.206252, 1.923041, 0.969448, 0.247841, -0.223972, 1.915788, 0.967742,
+ 0.271157, -0.241827, 1.907008, 0.965607, 0.295297, -0.259562, 1.895854, 0.963007, 0.320121,
+ -0.276909, 1.881289, 0.959722, 0.345566, -0.293883, 1.864528, 0.955831, 0.371012, -0.309816,
+ 1.842062, 0.951127, 0.396834, -0.325157, 1.818068, 0.945725, 0.422277, -0.339357, 1.788874,
+ 0.939318, 0.447928, -0.352387, 1.758283, 0.931470, 0.474315, -0.363680, 1.723668, 0.921900,
+ 0.501560, -0.372963, 1.686081, 0.909996, 0.528391, -0.380159, 1.645816, 0.896244, 0.554754,
+ -0.385545, 1.603709, 0.880326, 0.581888, -0.389778, 1.565475, 0.862716, 0.607791, -0.391839,
+ 1.524196, 0.843146, 0.633511, -0.392331, 1.483921, 0.821554, 0.658621, -0.391193, 1.445013,
+ 0.798336, 0.683160, -0.388424, 1.406963, 0.773299, 0.707429, -0.384104, 1.370996, 0.746668,
+ 0.732212, -0.377945, 1.335879, 0.717502, 0.756871, -0.369856, 1.302489, 0.686954, 0.781065,
+ -0.360707, 1.271815, 0.655372, 0.804167, -0.350091, 1.242416, 0.622683, 0.827948, -0.338941,
+ 1.217208, 0.589185, 0.850901, -0.326427, 1.192354, 0.555005, 0.873589, -0.312199, 1.169639,
+ 0.519594, 0.897085, -0.297374, 1.150181, 0.484105, 0.920459, -0.281932, 1.132858, 0.448661,
+ 0.942637, -0.265625, 1.115401, 0.413051, 0.965341, -0.248332, 1.101078, 0.377329, 0.987530,
+ -0.229983, 1.087377, 0.342349, 1.010739, -0.211647, 1.076582, 0.307824, 1.033449, -0.192725,
+ 1.065900, 0.273368, 1.055618, -0.172726, 1.056958, 0.240238, 1.079345, -0.152640, 1.049620,
+ 0.208322, 1.100058, -0.131931, 1.044084, 0.178242, 1.118547, -0.110351, 1.039387, 0.149493,
+ 1.132748, -0.088128, 1.033049, 0.119673, 1.143419, -0.066069, 1.025521, 0.089728, 1.150316,
+ -0.043513, 1.016378, 0.059253, 1.155208, -0.021593, 1.007506, 0.029140, 1.160871, 0.000111,
+ 0.999916, -0.000035, 0.000201, -0.000206, 2.061000, 1.025243, 0.000504, -0.000516, 2.049647,
+ 1.025237, 0.002015, -0.002066, 2.050169, 1.025237, 0.004535, -0.004650, 2.051254, 1.025255,
+ 0.008063, -0.008266, 2.051302, 1.025236, 0.012600, -0.012915, 2.051508, 1.025226, 0.018144,
+ -0.018594, 2.050981, 1.025215, 0.024700, -0.025304, 2.050841, 1.025190, 0.032267, -0.033038,
+ 2.050537, 1.025152, 0.040852, -0.041795, 2.050660, 1.025090, 0.050460, -0.051570, 2.049921,
+ 1.025017, 0.061094, -0.062347, 2.049350, 1.024908, 0.072762, -0.074111, 2.048517, 1.024760,
+ 0.085475, -0.086661, 2.047009, 1.024555, 0.099249, -0.100160, 2.045261, 1.024278, 0.114106,
+ -0.114628, 2.043508, 1.023941, 0.130032, -0.130002, 2.041321, 1.023488, 0.147050, -0.145985,
+ 2.038299, 1.022905, 0.165164, -0.162762, 2.034658, 1.022151, 0.184380, -0.180172, 2.030312,
+ 1.021200, 0.204704, -0.198022, 2.024944, 1.019966, 0.226129, -0.216359, 2.018546, 1.018424,
+ 0.248582, -0.234923, 2.010153, 1.016519, 0.272011, -0.253474, 1.999659, 1.014072, 0.296259,
+ -0.271820, 1.986076, 1.011071, 0.321423, -0.289959, 1.970618, 1.007389, 0.346897, -0.307283,
+ 1.949667, 1.002955, 0.372750, -0.323817, 1.925287, 0.997633, 0.398603, -0.339241, 1.896006,
+ 0.991354, 0.424351, -0.353633, 1.863658, 0.983937, 0.449887, -0.366660, 1.827430, 0.975254,
+ 0.475715, -0.378213, 1.789521, 0.964753, 0.502204, -0.387133, 1.745632, 0.951594, 0.530179,
+ -0.394976, 1.705347, 0.936344, 0.556732, -0.400134, 1.658928, 0.918907, 0.583123, -0.403439,
+ 1.613077, 0.899504, 0.609477, -0.405285, 1.567884, 0.878172, 0.634927, -0.405055, 1.523507,
+ 0.854396, 0.660357, -0.403494, 1.481712, 0.829259, 0.684851, -0.400104, 1.439000, 0.802359,
+ 0.709654, -0.395536, 1.400956, 0.773534, 0.733472, -0.388996, 1.362156, 0.743230, 0.757502,
+ -0.380263, 1.325113, 0.711090, 0.782249, -0.370594, 1.292913, 0.677166, 0.806017, -0.359509,
+ 1.262088, 0.642527, 0.828687, -0.347126, 1.232059, 0.607589, 0.852372, -0.334474, 1.207160,
+ 0.571938, 0.874266, -0.320074, 1.181978, 0.535518, 0.898168, -0.304719, 1.161156, 0.498375,
+ 0.920456, -0.288246, 1.140667, 0.461179, 0.942832, -0.271311, 1.122780, 0.424533, 0.966458,
+ -0.254154, 1.108743, 0.387784, 0.988907, -0.235659, 1.093872, 0.351689, 1.011557, -0.216322,
+ 1.081959, 0.315743, 1.035099, -0.197007, 1.070885, 0.280402, 1.056354, -0.176878, 1.059968,
+ 0.246472, 1.079854, -0.156058, 1.051815, 0.212818, 1.101494, -0.134772, 1.045757, 0.182143,
+ 1.120587, -0.113071, 1.041169, 0.152867, 1.135399, -0.090411, 1.034844, 0.122796, 1.146612,
+ -0.067477, 1.026974, 0.091888, 1.153168, -0.044849, 1.017303, 0.060779, 1.157912, -0.021998,
+ 1.007735, 0.029919, 1.163607, 0.000121, 0.999959, 0.000003, 0.000200, -0.000216, 2.163956,
+ 1.077737, 0.000504, -0.000543, 2.161128, 1.077732, 0.002016, -0.002173, 2.162732, 1.077729,
+ 0.004535, -0.004887, 2.161402, 1.077749, 0.008066, -0.008692, 2.163252, 1.077732, 0.012599,
+ -0.013576, 2.161300, 1.077727, 0.018145, -0.019546, 2.161151, 1.077702, 0.024702, -0.026599,
+ 2.161223, 1.077675, 0.032272, -0.034729, 2.160949, 1.077632, 0.040862, -0.043936, 2.160967,
+ 1.077575, 0.050470, -0.054203, 2.160035, 1.077473, 0.061113, -0.065528, 2.159490, 1.077348,
+ 0.072794, -0.077882, 2.158517, 1.077178, 0.085528, -0.091030, 2.156605, 1.076937, 0.099337,
+ -0.105251, 2.154828, 1.076631, 0.114228, -0.120456, 2.152812, 1.076229, 0.130202, -0.136573,
+ 2.150298, 1.075713, 0.147284, -0.153306, 2.146752, 1.075031, 0.165480, -0.170931, 2.142744,
+ 1.074173, 0.184793, -0.189083, 2.137475, 1.073063, 0.205224, -0.207840, 2.131320, 1.071683,
+ 0.226743, -0.226939, 2.123154, 1.069914, 0.249401, -0.246344, 2.114086, 1.067718, 0.272955,
+ -0.265640, 2.101599, 1.064924, 0.297494, -0.284846, 2.086612, 1.061512, 0.322731, -0.303452,
+ 2.067356, 1.057359, 0.348451, -0.321330, 2.043711, 1.052294, 0.374451, -0.338201, 2.015033,
+ 1.046153, 0.400454, -0.353816, 1.981139, 1.039003, 0.426434, -0.368216, 1.944128, 1.030498,
+ 0.452088, -0.381251, 1.903094, 1.020454, 0.477901, -0.392833, 1.860402, 1.008793, 0.504173,
+ -0.402408, 1.814402, 0.994791, 0.531520, -0.409545, 1.766273, 0.977733, 0.558049, -0.414351,
+ 1.714119, 0.958625, 0.584778, -0.417437, 1.664612, 0.937189, 0.610808, -0.418519, 1.613793,
+ 0.913543, 0.636915, -0.418094, 1.565942, 0.888137, 0.662204, -0.415742, 1.518783, 0.860728,
+ 0.686848, -0.411746, 1.473306, 0.831793, 0.710992, -0.406153, 1.430153, 0.800862, 0.735382,
+ -0.399519, 1.389824, 0.768768, 0.759079, -0.390927, 1.350744, 0.734825, 0.782912, -0.380111,
+ 1.313559, 0.699450, 0.806746, -0.368383, 1.280028, 0.663191, 0.830269, -0.355606, 1.249814,
+ 0.625927, 0.853305, -0.341988, 1.221138, 0.588644, 0.876326, -0.327545, 1.195837, 0.550849,
+ 0.898322, -0.311779, 1.171844, 0.512694, 0.921811, -0.294944, 1.150671, 0.474225, 0.944563,
+ -0.277333, 1.132224, 0.435772, 0.967089, -0.259340, 1.115422, 0.398001, 0.989754, -0.240836,
+ 1.100405, 0.360802, 1.012470, -0.221293, 1.086533, 0.323566, 1.036426, -0.201191, 1.075496,
+ 0.287387, 1.058709, -0.180590, 1.064233, 0.252184, 1.081593, -0.159810, 1.055296, 0.218441,
+ 1.103146, -0.137772, 1.047978, 0.186223, 1.122814, -0.115347, 1.042693, 0.156019, 1.137790,
+ -0.092582, 1.036049, 0.125579, 1.149184, -0.069152, 1.027944, 0.093986, 1.156062, -0.045661,
+ 1.018039, 0.062122, 1.160733, -0.022719, 1.008072, 0.030650, 1.166487, 0.000231, 1.000063,
+ -0.000120, 0.000201, -0.000228, 2.308308, 1.133128, 0.000504, -0.000571, 2.283756, 1.133123,
+ 0.002016, -0.002284, 2.283756, 1.133123, 0.004535, -0.005138, 2.283310, 1.133144, 0.008048,
+ -0.009119, 2.266192, 1.133138, 0.012600, -0.014274, 2.284377, 1.133110, 0.018147, -0.020553,
+ 2.284204, 1.133093, 0.024702, -0.027964, 2.283517, 1.133060, 0.032272, -0.036510, 2.282997,
+ 1.133007, 0.040866, -0.046188, 2.282986, 1.132930, 0.050481, -0.056979, 2.282260, 1.132824,
+ 0.061133, -0.068881, 2.281533, 1.132678, 0.072830, -0.081850, 2.280504, 1.132481, 0.085592,
+ -0.095657, 2.278304, 1.132202, 0.099431, -0.110594, 2.276269, 1.131845, 0.114360, -0.126590,
+ 2.273890, 1.131383, 0.130388, -0.143454, 2.270761, 1.130784, 0.147547, -0.161029, 2.266794,
+ 1.130003, 0.165836, -0.179523, 2.262332, 1.129016, 0.185269, -0.198527, 2.256326, 1.127738,
+ 0.205822, -0.218138, 2.249031, 1.126156, 0.227527, -0.238141, 2.239993, 1.124132, 0.250325,
+ -0.258302, 2.228878, 1.121594, 0.274070, -0.278329, 2.214204, 1.118449, 0.298793, -0.298310,
+ 2.196654, 1.114528, 0.324131, -0.317462, 2.173394, 1.109783, 0.350101, -0.335853, 2.146395,
+ 1.103901, 0.376293, -0.353064, 2.112341, 1.096954, 0.402547, -0.368950, 2.073700, 1.088642,
+ 0.428791, -0.383462, 2.031152, 1.078946, 0.454976, -0.396635, 1.986661, 1.067536, 0.480566,
+ -0.407873, 1.937038, 1.054403, 0.506154, -0.417303, 1.885155, 1.038894, 0.532862, -0.424194,
+ 1.830369, 1.020535, 0.560354, -0.429344, 1.776976, 0.999295, 0.587114, -0.431949, 1.721214,
+ 0.975990, 0.613345, -0.432547, 1.665739, 0.950239, 0.639335, -0.431338, 1.612200, 0.922467,
+ 0.664996, -0.428473, 1.561035, 0.892593, 0.688947, -0.423355, 1.508240, 0.861325, 0.713403,
+ -0.417235, 1.461776, 0.828289, 0.737649, -0.409848, 1.418888, 0.793863, 0.761275, -0.400901,
+ 1.376807, 0.758074, 0.784778, -0.390174, 1.337204, 0.721974, 0.808762, -0.377683, 1.301527,
+ 0.682718, 0.831993, -0.364037, 1.267144, 0.644001, 0.854696, -0.349494, 1.236023, 0.605478,
+ 0.877933, -0.334499, 1.209284, 0.565588, 0.900180, -0.318435, 1.183967, 0.526138, 0.923039,
+ -0.301669, 1.161513, 0.486524, 0.945895, -0.283298, 1.140838, 0.446747, 0.968069, -0.264438,
+ 1.122475, 0.408041, 0.991179, -0.245463, 1.106968, 0.369477, 1.012926, -0.225680, 1.091435,
+ 0.331626, 1.036995, -0.205401, 1.079561, 0.294288, 1.060909, -0.184310, 1.068215, 0.257696,
+ 1.083531, -0.162846, 1.058133, 0.223343, 1.105644, -0.141040, 1.050851, 0.190541, 1.125691,
+ -0.117965, 1.045001, 0.159310, 1.141297, -0.094377, 1.038028, 0.128238, 1.152672, -0.070831,
+ 1.029694, 0.096282, 1.159333, -0.046853, 1.019136, 0.063720, 1.163819, -0.022991, 1.008518,
+ 0.031234, 1.169564, 0.000125, 1.000069, -0.000024, 0.000202, -0.000241, 2.458341, 1.191742,
+ 0.000504, -0.000600, 2.418738, 1.191740, 0.002015, -0.002401, 2.418821, 1.191730, 0.004535,
+ -0.005405, 2.421986, 1.191756, 0.008071, -0.009618, 2.424988, 1.191753, 0.012600, -0.015012,
+ 2.420242, 1.191727, 0.018145, -0.021612, 2.419937, 1.191703, 0.024704, -0.029410, 2.419746,
+ 1.191662, 0.032278, -0.038398, 2.419409, 1.191604, 0.040874, -0.048574, 2.418995, 1.191515,
+ 0.050496, -0.059920, 2.418190, 1.191389, 0.061160, -0.072432, 2.417487, 1.191221, 0.072871,
+ -0.086009, 2.415853, 1.190984, 0.085664, -0.100559, 2.413669, 1.190664, 0.099543, -0.116283,
+ 2.411423, 1.190256, 0.114520, -0.133071, 2.408711, 1.189719, 0.130616, -0.150670, 2.404900,
+ 1.189019, 0.147856, -0.169197, 2.400512, 1.188125, 0.166235, -0.188545, 2.394939, 1.186972,
+ 0.185804, -0.208480, 2.388232, 1.185515, 0.206488, -0.228883, 2.379190, 1.183673, 0.228383,
+ -0.249897, 2.369208, 1.181382, 0.251305, -0.270851, 2.355459, 1.178478, 0.275349, -0.291780,
+ 2.339142, 1.174857, 0.300106, -0.312257, 2.316655, 1.170411, 0.325849, -0.332225, 2.291540,
+ 1.164883, 0.351782, -0.350862, 2.257242, 1.158196, 0.378248, -0.368431, 2.218671, 1.150173,
+ 0.404674, -0.384428, 2.173680, 1.140703, 0.431385, -0.399230, 2.127083, 1.129555, 0.457407,
+ -0.411875, 2.073236, 1.116436, 0.483275, -0.423013, 2.018223, 1.101373, 0.509278, -0.432624,
+ 1.962674, 1.084257, 0.534751, -0.439261, 1.900814, 1.064592, 0.561895, -0.443801, 1.839558,
+ 1.040881, 0.588677, -0.445872, 1.777763, 1.015208, 0.614900, -0.445896, 1.716550, 0.987252,
+ 0.641051, -0.444148, 1.657984, 0.957271, 0.666409, -0.440299, 1.600832, 0.924841, 0.691872,
+ -0.435318, 1.548237, 0.891185, 0.716638, -0.428631, 1.497572, 0.855929, 0.739864, -0.419872,
+ 1.447043, 0.819676, 0.763707, -0.410456, 1.403648, 0.781455, 0.786744, -0.399390, 1.360844,
+ 0.742965, 0.809585, -0.386381, 1.320529, 0.703260, 0.834164, -0.372622, 1.286467, 0.662385,
+ 0.856713, -0.357177, 1.252306, 0.621379, 0.879820, -0.341458, 1.223070, 0.580238, 0.902721,
+ -0.325024, 1.197115, 0.539028, 0.924650, -0.307543, 1.172314, 0.498592, 0.947613, -0.289557,
+ 1.151171, 0.457980, 0.969590, -0.269799, 1.129986, 0.417696, 0.992961, -0.250111, 1.113321,
+ 0.377529, 1.014582, -0.229761, 1.097149, 0.339096, 1.038069, -0.209375, 1.083913, 0.301119,
+ 1.061661, -0.188038, 1.071241, 0.263506, 1.085069, -0.165874, 1.060508, 0.227921, 1.107744,
+ -0.143437, 1.052930, 0.194062, 1.127982, -0.120574, 1.046396, 0.162506, 1.144541, -0.096569,
+ 1.039880, 0.130788, 1.155876, -0.072039, 1.030946, 0.098057, 1.162719, -0.047888, 1.020124,
+ 0.064956, 1.167089, -0.023740, 1.008953, 0.031966, 1.172775, 0.000277, 1.000067, -0.000111,
+ 0.000200, -0.000251, 2.573709, 1.253951, 0.000504, -0.000632, 2.572401, 1.253940, 0.002015,
+ -0.002527, 2.571267, 1.253927, 0.004535, -0.005687, 2.572481, 1.253948, 0.008062, -0.010108,
+ 2.571851, 1.253941, 0.012588, -0.015780, 2.568431, 1.253934, 0.018139, -0.022731, 2.569765,
+ 1.253893, 0.024709, -0.030948, 2.572115, 1.253853, 0.032283, -0.040401, 2.571456, 1.253785,
+ 0.040883, -0.051105, 2.571041, 1.253683, 0.050514, -0.063041, 2.570153, 1.253538, 0.061188,
+ -0.076195, 2.569085, 1.253336, 0.072926, -0.090402, 2.567184, 1.253065, 0.085746, -0.105745,
+ 2.564731, 1.252697, 0.099661, -0.122296, 2.561995, 1.252218, 0.114699, -0.139912, 2.559019,
+ 1.251590, 0.130882, -0.158362, 2.555017, 1.250766, 0.148202, -0.177856, 2.549419, 1.249744,
+ 0.166706, -0.198049, 2.542908, 1.248423, 0.186404, -0.219014, 2.535205, 1.246741, 0.207272,
+ -0.240376, 2.524893, 1.244596, 0.229345, -0.262230, 2.512804, 1.241917, 0.252494, -0.284134,
+ 2.496923, 1.238610, 0.276690, -0.305828, 2.476583, 1.234474, 0.301798, -0.327107, 2.451548,
+ 1.229292, 0.327423, -0.347300, 2.418630, 1.222997, 0.353848, -0.366699, 2.381002, 1.215366,
+ 0.380342, -0.384421, 2.334413, 1.206199, 0.407390, -0.400855, 2.285660, 1.195374, 0.433913,
+ -0.415241, 2.228604, 1.182290, 0.460837, -0.428275, 2.171532, 1.167385, 0.486381, -0.438573,
+ 2.105639, 1.150401, 0.511959, -0.447348, 2.040835, 1.130990, 0.537586, -0.454152, 1.974797,
+ 1.109302, 0.564035, -0.458684, 1.907895, 1.084131, 0.590690, -0.460058, 1.839482, 1.055803,
+ 0.617250, -0.459662, 1.772332, 1.025103, 0.643406, -0.457260, 1.707313, 0.992502, 0.668794,
+ -0.452666, 1.644722, 0.957657, 0.693930, -0.446641, 1.586832, 0.921340, 0.718708, -0.439121,
+ 1.531197, 0.883841, 0.743469, -0.430429, 1.480765, 0.844931, 0.766080, -0.419622, 1.430338,
+ 0.804786, 0.789801, -0.408368, 1.386295, 0.764206, 0.812718, -0.395392, 1.343758, 0.722565,
+ 0.835453, -0.380699, 1.304655, 0.680585, 0.858801, -0.364834, 1.269287, 0.637235, 0.881537,
+ -0.348092, 1.237493, 0.594579, 0.904656, -0.331087, 1.208862, 0.552313, 0.926357, -0.312966,
+ 1.182365, 0.510080, 0.949001, -0.294684, 1.159452, 0.468677, 0.971598, -0.275361, 1.138706,
+ 0.426723, 0.994905, -0.254947, 1.120552, 0.385875, 1.017981, -0.234109, 1.104215, 0.345751,
+ 1.040840, -0.213040, 1.089276, 0.306762, 1.063893, -0.191616, 1.075845, 0.269066, 1.086907,
+ -0.169272, 1.063788, 0.232171, 1.109937, -0.146076, 1.054977, 0.197826, 1.130808, -0.122544,
+ 1.048572, 0.165272, 1.146831, -0.098492, 1.040742, 0.133280, 1.158955, -0.073710, 1.031818,
+ 0.100262, 1.166161, -0.048610, 1.020747, 0.066165, 1.170491, -0.024209, 1.009380, 0.032741,
+ 1.176111, 0.000010, 1.000042, 0.000056, 0.000202, -0.000267, 2.786357, 1.320169, 0.000504,
+ -0.000665, 2.741889, 1.320168, 0.002015, -0.002660, 2.740000, 1.320143, 0.004536, -0.005987,
+ 2.744276, 1.320161, 0.008063, -0.010644, 2.743432, 1.320162, 0.012600, -0.016628, 2.741741,
+ 1.320148, 0.018144, -0.023937, 2.741314, 1.320127, 0.024708, -0.032577, 2.741916, 1.320061,
+ 0.032290, -0.042536, 2.742132, 1.319976, 0.040894, -0.053799, 2.741199, 1.319861, 0.050533,
+ -0.066361, 2.740258, 1.319691, 0.061223, -0.080202, 2.739045, 1.319458, 0.072985, -0.095109,
+ 2.736519, 1.319138, 0.085841, -0.111296, 2.733903, 1.318715, 0.099808, -0.128685, 2.730944,
+ 1.318156, 0.114903, -0.147202, 2.727293, 1.317424, 0.131164, -0.166575, 2.722169, 1.316485,
+ 0.148599, -0.187019, 2.716148, 1.315274, 0.167245, -0.208240, 2.708701, 1.313733, 0.187078,
+ -0.230151, 2.698998, 1.311792, 0.208153, -0.252538, 2.687341, 1.309343, 0.230418, -0.275295,
+ 2.672621, 1.306247, 0.253802, -0.298066, 2.653619, 1.302374, 0.278261, -0.320673, 2.629943,
+ 1.297573, 0.303527, -0.342528, 2.599228, 1.291625, 0.329571, -0.363531, 2.562226, 1.284374,
+ 0.355939, -0.382963, 2.515491, 1.275478, 0.382987, -0.401306, 2.464858, 1.264866, 0.409917,
+ -0.417455, 2.404877, 1.252184, 0.437015, -0.432067, 2.341408, 1.237415, 0.463474, -0.444204,
+ 2.271837, 1.220687, 0.489835, -0.454631, 2.200593, 1.200973, 0.516054, -0.463338, 2.129733,
+ 1.179346, 0.541397, -0.469425, 2.055635, 1.155039, 0.566798, -0.473526, 1.980812, 1.127866,
+ 0.593114, -0.474632, 1.904723, 1.097304, 0.619945, -0.473597, 1.832456, 1.063603, 0.646325,
+ -0.470656, 1.761501, 1.027971, 0.672320, -0.465675, 1.694248, 0.990692, 0.697163, -0.458527,
+ 1.629227, 0.951582, 0.721472, -0.449904, 1.568132, 0.911197, 0.745855, -0.440140, 1.512084,
+ 0.869745, 0.770089, -0.429338, 1.460694, 0.827648, 0.792546, -0.416701, 1.410739, 0.784728,
+ 0.815161, -0.403151, 1.365438, 0.741884, 0.837994, -0.388714, 1.324811, 0.697800, 0.861220,
+ -0.372573, 1.287723, 0.653341, 0.883737, -0.355024, 1.252491, 0.609455, 0.906784, -0.337092,
+ 1.221844, 0.565275, 0.928493, -0.318370, 1.192881, 0.521558, 0.951495, -0.299605, 1.169131,
+ 0.478149, 0.973586, -0.280067, 1.146316, 0.436325, 0.996400, -0.259823, 1.127860, 0.394409,
+ 1.019780, -0.238313, 1.110521, 0.353045, 1.042775, -0.216506, 1.093915, 0.312803, 1.066822,
+ -0.194695, 1.080326, 0.274100, 1.089869, -0.172290, 1.067722, 0.236657, 1.113606, -0.149264,
+ 1.058471, 0.201603, 1.134229, -0.124814, 1.050701, 0.168398, 1.150922, -0.100070, 1.043051,
+ 0.135616, 1.163224, -0.075155, 1.033742, 0.102144, 1.169965, -0.049933, 1.021818, 0.067532,
+ 1.174200, -0.024461, 1.009916, 0.033215, 1.179766, 0.000188, 1.000045, -0.000014, 0.000202,
+ -0.000281, 2.964186, 1.390880, 0.000505, -0.000702, 2.945157, 1.390903, 0.002015, -0.002802,
+ 2.931184, 1.390863, 0.004535, -0.006307, 2.935673, 1.390900, 0.008063, -0.011213, 2.934274,
+ 1.390890, 0.012598, -0.017516, 2.932216, 1.390876, 0.018147, -0.025221, 2.933324, 1.390832,
+ 0.024711, -0.034322, 2.933945, 1.390769, 0.032295, -0.044810, 2.933496, 1.390674, 0.040904,
+ -0.056673, 2.932487, 1.390538, 0.050555, -0.069906, 2.931571, 1.390342, 0.061259, -0.084468,
+ 2.929914, 1.390064, 0.073053, -0.100152, 2.927039, 1.389695, 0.085948, -0.117202, 2.924241,
+ 1.389201, 0.099968, -0.135531, 2.920760, 1.388548, 0.115135, -0.154906, 2.915998, 1.387692,
+ 0.131496, -0.175352, 2.910285, 1.386611, 0.149049, -0.196783, 2.903174, 1.385190, 0.167848,
+ -0.219066, 2.894584, 1.383407, 0.187879, -0.241983, 2.883171, 1.381148, 0.209143, -0.265398,
+ 2.869102, 1.378261, 0.231689, -0.289254, 2.852238, 1.374690, 0.255223, -0.312776, 2.828264,
+ 1.370166, 0.279952, -0.336260, 2.800175, 1.364591, 0.305572, -0.358865, 2.764282, 1.357758,
+ 0.331650, -0.380223, 2.717845, 1.349413, 0.358491, -0.400252, 2.665326, 1.339084, 0.385445,
+ -0.418422, 2.602293, 1.326773, 0.412947, -0.434993, 2.536973, 1.312141, 0.439681, -0.448757,
+ 2.459463, 1.295205, 0.467272, -0.461427, 2.386250, 1.275573, 0.493568, -0.471102, 2.303225,
+ 1.253400, 0.519743, -0.478930, 2.221945, 1.228890, 0.544882, -0.484098, 2.136425, 1.201730,
+ 0.570690, -0.488125, 2.057093, 1.172022, 0.595905, -0.489185, 1.975334, 1.139312, 0.622747,
+ -0.487535, 1.895055, 1.103038, 0.648695, -0.483482, 1.815995, 1.064364, 0.675159, -0.478096,
+ 1.744272, 1.024098, 0.700714, -0.470492, 1.675257, 0.982186, 0.725641, -0.461398, 1.609135,
+ 0.939137, 0.748552, -0.449825, 1.545091, 0.894791, 0.772808, -0.438185, 1.489394, 0.850373,
+ 0.795928, -0.425073, 1.437026, 0.805287, 0.818900, -0.411028, 1.389654, 0.760003, 0.841633,
+ -0.396047, 1.345873, 0.714914, 0.863213, -0.379637, 1.305185, 0.669271, 0.886662, -0.362227,
+ 1.269147, 0.622935, 0.908504, -0.343068, 1.234714, 0.577757, 0.931425, -0.323982, 1.204997,
+ 0.532922, 0.953835, -0.304347, 1.178871, 0.488154, 0.975813, -0.284219, 1.155019, 0.444885,
+ 0.997662, -0.263544, 1.133941, 0.402224, 1.021167, -0.242611, 1.116100, 0.360530, 1.044038,
+ -0.220065, 1.098348, 0.318968, 1.068837, -0.197580, 1.084605, 0.279107, 1.092548, -0.174779,
+ 1.071217, 0.241111, 1.116157, -0.151596, 1.060486, 0.204913, 1.137486, -0.127478, 1.052751,
+ 0.171410, 1.154694, -0.101915, 1.044807, 0.137999, 1.166867, -0.076246, 1.034824, 0.103807,
+ 1.173715, -0.050661, 1.022501, 0.068802, 1.178236, -0.025355, 1.010324, 0.034155, 1.183545,
+ 0.000205, 1.000059, -0.000110, 0.000201, -0.000294, 3.161080, 1.466721, 0.000505, -0.000740,
+ 3.155526, 1.466737, 0.002016, -0.002957, 3.152852, 1.466688, 0.004537, -0.006655, 3.150654,
+ 1.466667, 0.008066, -0.011828, 3.153109, 1.466694, 0.012604, -0.018479, 3.152143, 1.466721,
+ 0.018150, -0.026598, 3.151025, 1.466636, 0.024714, -0.036191, 3.150300, 1.466562, 0.032301,
+ -0.047249, 3.149861, 1.466450, 0.040924, -0.059766, 3.149548, 1.466289, 0.050579, -0.073703,
+ 3.147516, 1.466055, 0.061306, -0.089022, 3.145680, 1.465738, 0.073135, -0.105563, 3.142428,
+ 1.465301, 0.086075, -0.123544, 3.139113, 1.464715, 0.100153, -0.142853, 3.135064, 1.463956,
+ 0.115411, -0.163183, 3.129509, 1.462962, 0.131876, -0.184760, 3.122959, 1.461670, 0.149570,
+ -0.207172, 3.114153, 1.460045, 0.168523, -0.230578, 3.103626, 1.457945, 0.188784, -0.254658,
+ 3.090818, 1.455279, 0.210264, -0.279114, 3.073352, 1.451998, 0.233030, -0.303930, 3.052592,
+ 1.447780, 0.256959, -0.328517, 3.025187, 1.442568, 0.281901, -0.352755, 2.990341, 1.436026,
+ 0.307728, -0.375894, 2.946820, 1.427979, 0.334197, -0.397924, 2.892845, 1.418249, 0.360966,
+ -0.417914, 2.827937, 1.406370, 0.388478, -0.436526, 2.758006, 1.392134, 0.415567, -0.452366,
+ 2.674696, 1.375244, 0.443518, -0.466917, 2.595136, 1.355660, 0.470631, -0.478417, 2.504173,
+ 1.333123, 0.497419, -0.487825, 2.413227, 1.308181, 0.523961, -0.495064, 2.321239, 1.280227,
+ 0.549708, -0.499844, 2.228911, 1.249894, 0.575296, -0.502844, 2.138834, 1.217130, 0.600168,
+ -0.503368, 2.049030, 1.181412, 0.625874, -0.501622, 1.962267, 1.142648, 0.652164, -0.496936,
+ 1.876900, 1.101268, 0.678029, -0.490319, 1.796344, 1.057782, 0.703248, -0.481575, 1.718925,
+ 1.012884, 0.728520, -0.471822, 1.648358, 0.966487, 0.752577, -0.460134, 1.581989, 0.919880,
+ 0.776163, -0.447164, 1.520109, 0.873087, 0.800016, -0.433601, 1.465081, 0.825803, 0.822176,
+ -0.418388, 1.412564, 0.778249, 0.844873, -0.402704, 1.366184, 0.730849, 0.865955, -0.385633,
+ 1.321865, 0.684037, 0.888173, -0.368255, 1.283464, 0.637192, 0.910994, -0.349332, 1.249215,
+ 0.590131, 0.934270, -0.329612, 1.218366, 0.543213, 0.956653, -0.309228, 1.189808, 0.497752,
+ 0.978476, -0.288310, 1.163674, 0.452837, 1.000755, -0.267243, 1.141389, 0.409481, 1.023827,
+ -0.246015, 1.122012, 0.367354, 1.045572, -0.223777, 1.103303, 0.325171, 1.070445, -0.200837,
+ 1.088010, 0.284442, 1.094268, -0.177211, 1.073650, 0.245138, 1.118639, -0.153531, 1.063051,
+ 0.208289, 1.139786, -0.129074, 1.053921, 0.173607, 1.157848, -0.104051, 1.045968, 0.140467,
+ 1.170697, -0.077694, 1.035782, 0.105594, 1.177874, -0.051393, 1.023483, 0.069898, 1.182242,
+ -0.025392, 1.010620, 0.034532, 1.187612, -0.000032, 1.000062, -0.000035, 0.000202, -0.000313,
+ 3.450327, 1.548291, 0.000504, -0.000780, 3.396162, 1.548289, 0.002015, -0.003120, 3.395621,
+ 1.548260, 0.004533, -0.007019, 3.394299, 1.548217, 0.008066, -0.012486, 3.398803, 1.548274,
+ 0.012600, -0.019500, 3.396363, 1.548245, 0.018151, -0.028076, 3.396805, 1.548192, 0.024722,
+ -0.038209, 3.396384, 1.548109, 0.032306, -0.049868, 3.395158, 1.547979, 0.040936, -0.063077,
+ 3.394303, 1.547785, 0.050610, -0.077791, 3.392979, 1.547513, 0.061360, -0.093869, 3.389910,
+ 1.547134, 0.073227, -0.111380, 3.386669, 1.546619, 0.086217, -0.130371, 3.382974, 1.545938,
+ 0.100364, -0.150684, 3.378046, 1.545039, 0.115733, -0.172116, 3.371719, 1.543880, 0.132309,
+ -0.194809, 3.363764, 1.542380, 0.150174, -0.218431, 3.353699, 1.540462, 0.169340, -0.242954,
+ 3.341397, 1.538002, 0.189788, -0.268175, 3.324957, 1.534894, 0.211581, -0.293776, 3.304776,
+ 1.530954, 0.234561, -0.319619, 3.278192, 1.526033, 0.258776, -0.345089, 3.244910, 1.519926,
+ 0.284059, -0.370176, 3.203338, 1.512296, 0.310312, -0.394171, 3.152477, 1.502956, 0.336748,
+ -0.416137, 3.083616, 1.491463, 0.364029, -0.436752, 3.010481, 1.477493, 0.391575, -0.455102,
+ 2.925454, 1.460933, 0.419409, -0.471378, 2.834380, 1.441554, 0.446811, -0.484714, 2.733329,
+ 1.418861, 0.474489, -0.496021, 2.633630, 1.393405, 0.501751, -0.504991, 2.530935, 1.364633,
+ 0.528488, -0.511392, 2.426653, 1.333234, 0.554428, -0.515395, 2.323633, 1.299138, 0.580434,
+ -0.517761, 2.224964, 1.262462, 0.605474, -0.517598, 2.127228, 1.223784, 0.629888, -0.514946,
+ 2.030545, 1.182321, 0.655579, -0.510177, 1.939070, 1.138515, 0.681940, -0.503097, 1.852355,
+ 1.091502, 0.707228, -0.493537, 1.768084, 1.043464, 0.731894, -0.482372, 1.690840, 0.994242,
+ 0.756741, -0.470312, 1.619277, 0.944749, 0.780160, -0.456412, 1.553430, 0.894816, 0.803384,
+ -0.441492, 1.493357, 0.845202, 0.826347, -0.425944, 1.437830, 0.795954, 0.849145, -0.409532,
+ 1.388578, 0.746915, 0.870617, -0.391988, 1.341527, 0.698025, 0.892943, -0.374229, 1.302188,
+ 0.649579, 0.913828, -0.355148, 1.262877, 0.601833, 0.936830, -0.335238, 1.230136, 0.554521,
+ 0.958687, -0.313939, 1.199596, 0.507208, 0.982008, -0.292741, 1.173619, 0.461357, 1.003691,
+ -0.270940, 1.149015, 0.416031, 1.027223, -0.249102, 1.128689, 0.372457, 1.050048, -0.226899,
+ 1.109444, 0.330281, 1.074105, -0.204329, 1.092943, 0.288987, 1.098971, -0.180560, 1.078591,
+ 0.249075, 1.123324, -0.155987, 1.066885, 0.211519, 1.145445, -0.130929, 1.057617, 0.176506,
+ 1.162856, -0.105269, 1.048453, 0.142345, 1.175360, -0.079267, 1.037439, 0.107452, 1.182514,
+ -0.052547, 1.024393, 0.071252, 1.186575, -0.025744, 1.011093, 0.035019, 1.192050, 0.000318,
+ 1.000013, -0.000152, 0.000204, -0.000334, 3.909175, 1.636412, 0.000504, -0.000825, 3.678647,
+ 1.636410, 0.002015, -0.003298, 3.678315, 1.636387, 0.004533, -0.007417, 3.674126, 1.636310,
+ 0.008062, -0.013190, 3.676771, 1.636376, 0.012603, -0.020613, 3.678135, 1.636369, 0.018153,
+ -0.029675, 3.677315, 1.636299, 0.024723, -0.040378, 3.676872, 1.636196, 0.032318, -0.052708,
+ 3.675750, 1.636038, 0.040955, -0.066660, 3.674803, 1.635810, 0.050645, -0.082203, 3.672735,
+ 1.635494, 0.061429, -0.099150, 3.669047, 1.635048, 0.073333, -0.117679, 3.665401, 1.634437,
+ 0.086388, -0.137725, 3.661315, 1.633634, 0.100620, -0.159081, 3.654992, 1.632571, 0.116087,
+ -0.181721, 3.647341, 1.631202, 0.132820, -0.205611, 3.637877, 1.629432, 0.150867, -0.230542,
+ 3.626333, 1.627161, 0.170234, -0.256239, 3.610671, 1.624266, 0.190981, -0.282751, 3.591685,
+ 1.620589, 0.213013, -0.309430, 3.565864, 1.615999, 0.236387, -0.336427, 3.534826, 1.610216,
+ 0.260943, -0.362931, 3.493984, 1.603047, 0.286497, -0.388644, 3.442075, 1.593920, 0.312769,
+ -0.412912, 3.375973, 1.582961, 0.339832, -0.435635, 3.299355, 1.569343, 0.367214, -0.456181,
+ 3.208994, 1.553137, 0.394935, -0.474325, 3.108910, 1.533791, 0.422935, -0.490318, 3.001767,
+ 1.511093, 0.451166, -0.503827, 2.891735, 1.485145, 0.478695, -0.514185, 2.773430, 1.455617,
+ 0.506313, -0.522502, 2.657639, 1.422946, 0.533427, -0.528119, 2.541132, 1.387843, 0.559942,
+ -0.531430, 2.426950, 1.349542, 0.585150, -0.531978, 2.312437, 1.309303, 0.610500, -0.531054,
+ 2.205966, 1.266280, 0.635380, -0.528058, 2.101993, 1.221709, 0.659852, -0.522751, 2.002950,
+ 1.175062, 0.685151, -0.515026, 1.908647, 1.125078, 0.710920, -0.505020, 1.819389, 1.074296,
+ 0.736066, -0.493268, 1.735806, 1.022420, 0.760503, -0.480032, 1.658607, 0.970230, 0.785091,
+ -0.465986, 1.589424, 0.917077, 0.807523, -0.449721, 1.522533, 0.864888, 0.830974, -0.433461,
+ 1.465416, 0.813006, 0.852659, -0.415808, 1.409076, 0.761689, 0.874841, -0.397855, 1.360758,
+ 0.711258, 0.896322, -0.379041, 1.316829, 0.661721, 0.918134, -0.360048, 1.278574, 0.612263,
+ 0.939356, -0.340108, 1.242200, 0.564369, 0.961025, -0.318877, 1.210305, 0.516506, 0.984371,
+ -0.297130, 1.183689, 0.469342, 1.006905, -0.274661, 1.157466, 0.423080, 1.029941, -0.252234,
+ 1.135066, 0.378315, 1.052751, -0.229268, 1.114518, 0.335169, 1.077981, -0.206662, 1.097760,
+ 0.293336, 1.102542, -0.183331, 1.082051, 0.252984, 1.126539, -0.158797, 1.068935, 0.214990,
+ 1.149023, -0.133014, 1.058996, 0.178903, 1.167550, -0.106641, 1.050245, 0.144559, 1.179994,
+ -0.079952, 1.038648, 0.108667, 1.187104, -0.053316, 1.025284, 0.072209, 1.191406, -0.026826,
+ 1.011453, 0.035833, 1.196748, 0.000226, 1.000034, -0.000061, 0.000200, -0.000346, 3.996419,
+ 1.732034, 0.000504, -0.000873, 4.000138, 1.732038, 0.002016, -0.003492, 4.002078, 1.732012,
+ 0.004538, -0.007859, 4.005626, 1.731962, 0.008064, -0.013963, 3.998500, 1.731999, 0.012590,
+ -0.021794, 3.995024, 1.732004, 0.018154, -0.031406, 3.999233, 1.731901, 0.024727, -0.042733,
+ 3.998497, 1.731774, 0.032327, -0.055781, 3.997064, 1.731599, 0.040974, -0.070543, 3.995856,
+ 1.731325, 0.050685, -0.086984, 3.993839, 1.730945, 0.061506, -0.104897, 3.989519, 1.730417,
+ 0.073458, -0.124506, 3.985313, 1.729697, 0.086573, -0.145706, 3.979984, 1.728747, 0.100909,
+ -0.168211, 3.972562, 1.727491, 0.116509, -0.192198, 3.963836, 1.725854, 0.133404, -0.217280,
+ 3.951919, 1.723749, 0.151659, -0.243556, 3.937734, 1.721093, 0.171288, -0.270611, 3.919021,
+ 1.717640, 0.192301, -0.298389, 3.895171, 1.713272, 0.214683, -0.326338, 3.864171, 1.707825,
+ 0.238392, -0.354394, 3.824682, 1.700956, 0.263151, -0.381636, 3.771168, 1.692392, 0.289155,
+ -0.408266, 3.709961, 1.681769, 0.315832, -0.433070, 3.630302, 1.668539, 0.342942, -0.455741,
+ 3.534719, 1.652513, 0.370892, -0.476655, 3.431531, 1.633428, 0.398985, -0.494692, 3.314933,
+ 1.610694, 0.427206, -0.510313, 3.189741, 1.584240, 0.455266, -0.522760, 3.058325, 1.554195,
+ 0.483472, -0.532872, 2.927213, 1.520805, 0.511192, -0.540229, 2.794112, 1.484026, 0.538706,
+ -0.545105, 2.663786, 1.443796, 0.565422, -0.547251, 2.534841, 1.401429, 0.591270, -0.547115,
+ 2.408437, 1.356231, 0.616787, -0.545113, 2.291284, 1.308887, 0.641380, -0.540853, 2.177478,
+ 1.260447, 0.665344, -0.534561, 2.069265, 1.210634, 0.690147, -0.527115, 1.969776, 1.158569,
+ 0.714578, -0.516171, 1.870847, 1.104593, 0.740349, -0.504048, 1.782674, 1.049578, 0.764563,
+ -0.489683, 1.698614, 0.994458, 0.788710, -0.474541, 1.624447, 0.938612, 0.812154, -0.458099,
+ 1.554453, 0.883694, 0.834566, -0.440345, 1.490045, 0.830220, 0.857486, -0.422491, 1.432889,
+ 0.776499, 0.879224, -0.403588, 1.380669, 0.724257, 0.899971, -0.383819, 1.333124, 0.673311,
+ 0.922111, -0.364250, 1.292648, 0.622999, 0.942842, -0.343873, 1.253933, 0.573304, 0.964398,
+ -0.323206, 1.221027, 0.525090, 0.986860, -0.301711, 1.191806, 0.477580, 1.009760, -0.278695,
+ 1.165162, 0.430624, 1.033347, -0.255591, 1.141715, 0.384482, 1.055937, -0.232039, 1.119739,
+ 0.340532, 1.081178, -0.208664, 1.102117, 0.297311, 1.105696, -0.184935, 1.085062, 0.256227,
+ 1.129575, -0.160673, 1.070918, 0.217709, 1.152135, -0.135414, 1.060642, 0.181471, 1.171221,
+ -0.108462, 1.051041, 0.146380, 1.184412, -0.081008, 1.039694, 0.110120, 1.191820, -0.053710,
+ 1.025903, 0.073052, 1.196195, -0.026625, 1.011816, 0.036129, 1.201677, -0.000175, 0.999945,
+ 0.000098, 0.000196, -0.000360, 4.100786, 1.836290, 0.000504, -0.000925, 4.370184, 1.836295,
+ 0.002018, -0.003706, 4.385247, 1.836243, 0.004534, -0.008324, 4.370146, 1.836210, 0.008064,
+ -0.014805, 4.372335, 1.836256, 0.012597, -0.023116, 4.359918, 1.836259, 0.018158, -0.033299,
+ 4.371503, 1.836123, 0.024732, -0.045301, 4.370533, 1.835988, 0.032344, -0.059143, 4.369649,
+ 1.835768, 0.040999, -0.074779, 4.367861, 1.835454, 0.050739, -0.092178, 4.364322, 1.834974,
+ 0.061594, -0.111161, 4.359221, 1.834355, 0.073604, -0.131958, 4.354620, 1.833499, 0.086796,
+ -0.154393, 4.347915, 1.832355, 0.101246, -0.178201, 4.339152, 1.830880, 0.116990, -0.203531,
+ 4.328327, 1.828936, 0.134086, -0.230043, 4.314240, 1.826442, 0.152589, -0.257718, 4.296795,
+ 1.823230, 0.172514, -0.286176, 4.273985, 1.819124, 0.193853, -0.315295, 4.244136, 1.813909,
+ 0.216582, -0.344507, 4.205152, 1.807410, 0.240668, -0.373646, 4.154781, 1.799084, 0.265904,
+ -0.401897, 4.091563, 1.788905, 0.292226, -0.429136, 4.013199, 1.776206, 0.319045, -0.454057,
+ 3.912886, 1.760500, 0.346721, -0.477219, 3.800927, 1.741586, 0.374849, -0.497883, 3.675652,
+ 1.718818, 0.403078, -0.515504, 3.536892, 1.692138, 0.431597, -0.530621, 3.391351, 1.661434,
+ 0.460246, -0.542852, 3.242817, 1.626989, 0.488899, -0.552238, 3.093685, 1.588582, 0.517215,
+ -0.559045, 2.944163, 1.546300, 0.544480, -0.562351, 2.794189, 1.501299, 0.571542, -0.563394,
+ 2.650239, 1.453758, 0.598167, -0.562590, 2.513757, 1.403321, 0.624104, -0.559636, 2.384203,
+ 1.352431, 0.648789, -0.554148, 2.259149, 1.298758, 0.672715, -0.546779, 2.140250, 1.244943,
+ 0.696258, -0.537896, 2.030401, 1.189971, 0.720048, -0.527401, 1.928311, 1.134526, 0.744078,
+ -0.514142, 1.830175, 1.076504, 0.768895, -0.499352, 1.740731, 1.018032, 0.792551, -0.482982,
+ 1.658911, 0.960250, 0.817007, -0.466406, 1.586579, 0.903029, 0.839035, -0.447616, 1.516969,
+ 0.846484, 0.862742, -0.429261, 1.458675, 0.791420, 0.884307, -0.409479, 1.402989, 0.737125,
+ 0.905641, -0.389303, 1.352817, 0.683912, 0.926185, -0.368344, 1.306684, 0.632690, 0.947229,
+ -0.347366, 1.267395, 0.581739, 0.969502, -0.326720, 1.233192, 0.532305, 0.990758, -0.304973,
+ 1.201017, 0.484166, 1.012749, -0.282816, 1.173018, 0.437385, 1.035533, -0.259084, 1.147184,
+ 0.390755, 1.059915, -0.235239, 1.125388, 0.345399, 1.084348, -0.211044, 1.105859, 0.301356,
+ 1.109544, -0.186698, 1.088888, 0.259708, 1.133770, -0.161900, 1.073848, 0.220324, 1.157553,
+ -0.136604, 1.063190, 0.183857, 1.176461, -0.110428, 1.053110, 0.148521, 1.190137, -0.082898,
+ 1.041484, 0.112124, 1.197215, -0.054554, 1.026844, 0.074160, 1.201654, -0.026744, 1.012264,
+ 0.036527, 1.207085, 0.000399, 1.000034, -0.000201, 0.000191, -0.000373, 4.194318, 1.950551,
+ 0.000504, -0.000983, 4.804350, 1.950552, 0.002015, -0.003931, 4.802820, 1.950518, 0.004536,
+ -0.008847, 4.805254, 1.950472, 0.008064, -0.015725, 4.804152, 1.950517, 0.012693, -0.024740,
+ 4.826828, 1.949914, 0.018159, -0.035365, 4.803103, 1.950349, 0.024740, -0.048122, 4.803220,
+ 1.950183, 0.032361, -0.062822, 4.801522, 1.949917, 0.041034, -0.079430, 4.799593, 1.949538,
+ 0.050815, -0.097841, 4.797179, 1.948972, 0.061702, -0.118026, 4.789557, 1.948246, 0.073766,
+ -0.140112, 4.783293, 1.947204, 0.087066, -0.163819, 4.775698, 1.945855, 0.101637, -0.189122,
+ 4.764612, 1.944052, 0.117558, -0.215884, 4.751486, 1.941710, 0.134884, -0.243968, 4.734791,
+ 1.938727, 0.153637, -0.273170, 4.712078, 1.934891, 0.173890, -0.303146, 4.683575, 1.929976,
+ 0.195643, -0.333704, 4.646766, 1.923740, 0.218767, -0.364170, 4.596814, 1.915888, 0.243337,
+ -0.394530, 4.535509, 1.905970, 0.268860, -0.423512, 4.452006, 1.893623, 0.295173, -0.450609,
+ 4.345682, 1.878286, 0.322784, -0.476488, 4.231632, 1.859391, 0.350616, -0.499420, 4.093553,
+ 1.836912, 0.379127, -0.519862, 3.944127, 1.809625, 0.407860, -0.537373, 3.782223, 1.778529,
+ 0.436717, -0.551802, 3.615563, 1.742684, 0.465345, -0.562951, 3.440672, 1.702289, 0.494158,
+ -0.571334, 3.268070, 1.658666, 0.522896, -0.577227, 3.100668, 1.611027, 0.551379, -0.580514,
+ 2.937615, 1.559742, 0.578992, -0.580610, 2.778703, 1.507257, 0.605095, -0.577729, 2.621626,
+ 1.451941, 0.630653, -0.573000, 2.476506, 1.395218, 0.656175, -0.566944, 2.341592, 1.337862,
+ 0.681036, -0.558988, 2.216478, 1.279275, 0.704713, -0.549211, 2.096972, 1.220526, 0.726894,
+ -0.537190, 1.983311, 1.161709, 0.749865, -0.524167, 1.881100, 1.102095, 0.773553, -0.508991,
+ 1.785637, 1.042039, 0.797102, -0.491658, 1.697234, 0.981588, 0.821187, -0.474093, 1.620250,
+ 0.921265, 0.843848, -0.454980, 1.547071, 0.862757, 0.866662, -0.435421, 1.482008, 0.804700,
+ 0.888696, -0.414990, 1.424116, 0.749432, 0.910945, -0.394472, 1.372658, 0.694767, 0.932300,
+ -0.373239, 1.325157, 0.641106, 0.952850, -0.351347, 1.282217, 0.589689, 0.974718, -0.329809,
+ 1.244897, 0.539322, 0.996445, -0.307902, 1.212306, 0.490083, 1.017580, -0.285392, 1.181402,
+ 0.442702, 1.040342, -0.262782, 1.155996, 0.395911, 1.064399, -0.238995, 1.131708, 0.350206,
+ 1.089464, -0.214297, 1.111215, 0.305175, 1.115565, -0.189293, 1.093094, 0.262686, 1.140640,
+ -0.163843, 1.077994, 0.223078, 1.163824, -0.137789, 1.066014, 0.185651, 1.182577, -0.111087,
+ 1.055615, 0.150045, 1.195775, -0.083945, 1.042940, 0.113457, 1.203175, -0.056145, 1.028015,
+ 0.075453, 1.207282, -0.027685, 1.012552, 0.037217, 1.213019, 0.000362, 0.999938, -0.000293,
+ 0.000187, -0.000388, 4.316009, 2.076500, 0.000504, -0.001048, 5.317799, 2.076499, 0.002014,
+ -0.004182, 5.306557, 2.076523, 0.004539, -0.009425, 5.317505, 2.076453, 0.008063, -0.016737,
+ 5.312143, 2.076410, 0.012614, -0.026171, 5.316434, 2.076389, 0.018158, -0.037641, 5.307836,
+ 2.076265, 0.024767, -0.051266, 5.315297, 2.076044, 0.032372, -0.066859, 5.307433, 2.075743,
+ 0.041066, -0.084538, 5.304809, 2.075270, 0.050871, -0.104062, 5.299277, 2.074622, 0.061821,
+ -0.125613, 5.293419, 2.073708, 0.073970, -0.149085, 5.286629, 2.072457, 0.087375, -0.174214,
+ 5.275937, 2.070804, 0.102105, -0.201136, 5.263267, 2.068647, 0.118223, -0.229505, 5.246309,
+ 2.065846, 0.135814, -0.259217, 5.225496, 2.062189, 0.154887, -0.289990, 5.196580, 2.057566,
+ 0.175510, -0.321618, 5.160716, 2.051593, 0.197636, -0.353632, 5.112202, 2.043949, 0.221168,
+ -0.385303, 5.046981, 2.034445, 0.246099, -0.416511, 4.965386, 2.022368, 0.272070, -0.446377,
+ 4.860735, 2.007160, 0.299090, -0.474279, 4.735140, 1.988598, 0.326702, -0.499809, 4.584962,
+ 1.965865, 0.355017, -0.522790, 4.420447, 1.938705, 0.383856, -0.542755, 4.241942, 1.906370,
+ 0.413059, -0.559903, 4.053302, 1.869455, 0.441882, -0.573174, 3.852753, 1.827946, 0.471516,
+ -0.584151, 3.660377, 1.781652, 0.500872, -0.591843, 3.466027, 1.730885, 0.529677, -0.596253,
+ 3.272812, 1.676821, 0.557683, -0.597604, 3.084286, 1.620064, 0.585652, -0.596591, 2.906111,
+ 1.560909, 0.612819, -0.593138, 2.738258, 1.500318, 0.639848, -0.588245, 2.584172, 1.438127,
+ 0.664758, -0.580140, 2.430697, 1.375746, 0.688754, -0.570189, 2.290701, 1.312727, 0.712848,
+ -0.559420, 2.162679, 1.250063, 0.735111, -0.546570, 2.042186, 1.187840, 0.757521, -0.532944,
+ 1.933435, 1.125513, 0.780056, -0.517981, 1.833524, 1.063827, 0.802513, -0.500724, 1.739053,
+ 1.002154, 0.825462, -0.481625, 1.652381, 0.939811, 0.848973, -0.462327, 1.577560, 0.878279,
+ 0.871521, -0.441928, 1.509291, 0.819200, 0.892325, -0.420297, 1.443799, 0.761607, 0.914935,
+ -0.399072, 1.389647, 0.705351, 0.936429, -0.377232, 1.339903, 0.650213, 0.957614, -0.355091,
+ 1.295467, 0.597773, 0.979578, -0.332767, 1.256692, 0.545914, 1.000860, -0.310147, 1.221666,
+ 0.495661, 1.022550, -0.287395, 1.190775, 0.448026, 1.045005, -0.264582, 1.162641, 0.400490,
+ 1.068703, -0.241464, 1.138358, 0.354088, 1.093098, -0.217504, 1.115973, 0.309812, 1.119230,
+ -0.192140, 1.096284, 0.266297, 1.144608, -0.165975, 1.080042, 0.225831, 1.168599, -0.139174,
+ 1.067749, 0.187761, 1.187970, -0.111910, 1.056635, 0.151322, 1.201240, -0.083978, 1.043566,
+ 0.114337, 1.208895, -0.056089, 1.028366, 0.076083, 1.213344, -0.028369, 1.013074, 0.037735,
+ 1.219220, -0.000534, 0.999968, 0.000076, 0.000182, -0.000404, 4.433519, 2.216201, 0.000504,
+ -0.001117, 5.911693, 2.216198, 0.002017, -0.004469, 5.919142, 2.216190, 0.004536, -0.010051,
+ 5.913172, 2.216130, 0.008065, -0.017867, 5.911791, 2.216145, 0.012467, -0.027603, 5.785357,
+ 2.216447, 0.018156, -0.040159, 5.901121, 2.215958, 0.024758, -0.054670, 5.908781, 2.215654,
+ 0.032395, -0.071352, 5.906098, 2.215283, 0.041108, -0.090201, 5.902558, 2.214715, 0.050955,
+ -0.111004, 5.895707, 2.213905, 0.061968, -0.134002, 5.888736, 2.212807, 0.074206, -0.159038,
+ 5.880633, 2.211303, 0.087742, -0.185801, 5.867001, 2.209297, 0.102652, -0.214368, 5.851446,
+ 2.206657, 0.119006, -0.244573, 5.830722, 2.203232, 0.136883, -0.276067, 5.802688, 2.198778,
+ 0.156335, -0.308660, 5.767185, 2.193091, 0.177396, -0.341940, 5.719726, 2.185858, 0.200070,
+ -0.375591, 5.658792, 2.176584, 0.224067, -0.408564, 5.573508, 2.164759, 0.249420, -0.440668,
+ 5.465696, 2.149777, 0.275879, -0.471138, 5.332207, 2.131225, 0.303307, -0.499204, 5.173339,
+ 2.108794, 0.331189, -0.524547, 4.985102, 2.080585, 0.359932, -0.547256, 4.785788, 2.047792,
+ 0.389063, -0.566479, 4.569344, 2.009518, 0.418725, -0.583031, 4.349557, 1.965601, 0.448181,
+ -0.595809, 4.121278, 1.916911, 0.477703, -0.605102, 3.892291, 1.863530, 0.507999, -0.612462,
+ 3.676557, 1.806286, 0.536889, -0.615451, 3.456241, 1.745841, 0.565778, -0.616029, 3.249464,
+ 1.681137, 0.593863, -0.613644, 3.050273, 1.615238, 0.620770, -0.608268, 2.859599, 1.548003,
+ 0.647171, -0.601116, 2.683287, 1.480447, 0.673458, -0.592840, 2.524036, 1.412084, 0.698064,
+ -0.581973, 2.371046, 1.345130, 0.721011, -0.568963, 2.229104, 1.278440, 0.744293, -0.555642,
+ 2.103213, 1.212448, 0.766314, -0.540934, 1.985370, 1.146287, 0.788164, -0.525271, 1.878842,
+ 1.082600, 0.809019, -0.507986, 1.779821, 1.019978, 0.830947, -0.489717, 1.691630, 0.956931,
+ 0.853732, -0.469345, 1.607513, 0.894207, 0.874904, -0.447618, 1.531176, 0.833436, 0.897289,
+ -0.426124, 1.467302, 0.773611, 0.919226, -0.404025, 1.408321, 0.716016, 0.940860, -0.381454,
+ 1.356209, 0.659515, 0.962764, -0.358901, 1.310082, 0.604629, 0.984322, -0.335983, 1.268485,
+ 0.552335, 1.005343, -0.312533, 1.230662, 0.501591, 1.028153, -0.289452, 1.199168, 0.452032,
+ 1.049283, -0.265754, 1.168575, 0.404347, 1.073687, -0.242571, 1.143533, 0.357445, 1.097546,
+ -0.218681, 1.119859, 0.312534, 1.123340, -0.194465, 1.099634, 0.269437, 1.148166, -0.168797,
+ 1.081968, 0.228586, 1.172518, -0.141552, 1.068789, 0.189866, 1.192930, -0.113325, 1.057548,
+ 0.152772, 1.206816, -0.084800, 1.044145, 0.115390, 1.215045, -0.056019, 1.028938, 0.076493,
+ 1.220048, -0.027733, 1.013338, 0.037767, 1.225852, 0.000050, 0.999927, -0.000160, 0.000178,
+ -0.000422, 4.587902, 2.372253, 0.000504, -0.001195, 6.624675, 2.372248, 0.002016, -0.004782,
+ 6.626884, 2.372187, 0.004531, -0.010746, 6.607379, 2.372318, 0.008081, -0.019161, 6.640102,
+ 2.372084, 0.012637, -0.029945, 6.653708, 2.372128, 0.018167, -0.042999, 6.623837, 2.371902,
+ 0.024769, -0.058516, 6.624484, 2.371595, 0.032421, -0.076370, 6.620877, 2.371120, 0.041164,
+ -0.096474, 6.615235, 2.370428, 0.051057, -0.118786, 6.607844, 2.369440, 0.062136, -0.143390,
+ 6.599216, 2.368075, 0.074490, -0.170034, 6.588018, 2.366218, 0.088179, -0.198717, 6.572526,
+ 2.363747, 0.103307, -0.229147, 6.551868, 2.360517, 0.119964, -0.261253, 6.526089, 2.356304,
+ 0.138173, -0.294703, 6.489593, 2.350797, 0.158072, -0.329261, 6.443573, 2.343783, 0.179592,
+ -0.364298, 6.379764, 2.334673, 0.202709, -0.399375, 6.295845, 2.323125, 0.227335, -0.433616,
+ 6.184929, 2.308547, 0.253230, -0.466794, 6.045905, 2.289980, 0.280100, -0.497509, 5.871803,
+ 2.266964, 0.308146, -0.525956, 5.672422, 2.239074, 0.336544, -0.551101, 5.443256, 2.204809,
+ 0.365223, -0.572471, 5.188034, 2.164827, 0.395484, -0.592088, 4.943783, 2.119489, 0.424416,
+ -0.606026, 4.666400, 2.067262, 0.455641, -0.619671, 4.418961, 2.009937, 0.485298, -0.627583,
+ 4.152737, 1.948900, 0.514774, -0.632072, 3.893344, 1.882692, 0.544172, -0.634033, 3.645332,
+ 1.814073, 0.573283, -0.633239, 3.414651, 1.742717, 0.602155, -0.630008, 3.195712, 1.669703,
+ 0.630520, -0.624550, 2.994536, 1.596021, 0.657121, -0.615749, 2.799373, 1.522572, 0.682071,
+ -0.604738, 2.616102, 1.448978, 0.707605, -0.593301, 2.456112, 1.376250, 0.731492, -0.579628,
+ 2.303517, 1.305297, 0.754139, -0.564473, 2.165340, 1.235548, 0.776505, -0.548787, 2.041646,
+ 1.167051, 0.796833, -0.531415, 1.923334, 1.100534, 0.817565, -0.513778, 1.818176, 1.035144,
+ 0.837981, -0.495167, 1.723830, 0.971583, 0.858513, -0.475690, 1.638448, 0.908841, 0.879892,
+ -0.454099, 1.559420, 0.846701, 0.902258, -0.432038, 1.491471, 0.785332, 0.924114, -0.409316,
+ 1.428878, 0.726409, 0.944230, -0.385618, 1.370785, 0.668588, 0.967001, -0.362604, 1.323529,
+ 0.612943, 0.988579, -0.339117, 1.279679, 0.559038, 1.010210, -0.315355, 1.240104, 0.506867,
+ 1.032084, -0.291408, 1.205261, 0.456934, 1.054671, -0.267387, 1.175197, 0.407792, 1.078314,
+ -0.243346, 1.148153, 0.360992, 1.102443, -0.219205, 1.123799, 0.315577, 1.128524, -0.194996,
+ 1.102624, 0.271742, 1.153989, -0.169897, 1.085134, 0.230702, 1.179420, -0.143960, 1.071699,
+ 0.192146, 1.200098, -0.116173, 1.060179, 0.155164, 1.214837, -0.086655, 1.046290, 0.117071,
+ 1.222749, -0.056956, 1.030040, 0.077450, 1.227273, -0.027883, 1.013650, 0.038092, 1.233293,
+ 0.000831, 1.000043, -0.000462, 0.000173, -0.000442, 4.741539, 2.547922, 0.000504, -0.001284,
+ 7.491127, 2.547919, 0.002014, -0.005132, 7.484889, 2.547844, 0.004523, -0.011521, 7.439875,
+ 2.547587, 0.008059, -0.020524, 7.483694, 2.547725, 0.012586, -0.032029, 7.470912, 2.547685,
+ 0.018081, -0.045948, 7.422534, 2.547686, 0.024783, -0.062844, 7.487581, 2.547107, 0.032451,
+ -0.082011, 7.483603, 2.546522, 0.041233, -0.103540, 7.475124, 2.545684, 0.051181, -0.127537,
+ 7.467521, 2.544438, 0.062347, -0.153921, 7.456266, 2.542744, 0.074829, -0.182427, 7.440422,
+ 2.540459, 0.088703, -0.213134, 7.420694, 2.537380, 0.104080, -0.245750, 7.394875, 2.533347,
+ 0.121050, -0.279941, 7.358515, 2.528069, 0.139697, -0.315591, 7.313001, 2.521237, 0.160036,
+ -0.351980, 7.246342, 2.512378, 0.182147, -0.388993, 7.163688, 2.500993, 0.205799, -0.425570,
+ 7.048339, 2.486450, 0.231091, -0.461093, 6.902586, 2.468174, 0.257405, -0.494668, 6.712721,
+ 2.444774, 0.284956, -0.525889, 6.491261, 2.415538, 0.313180, -0.553693, 6.232833, 2.380610,
+ 0.342327, -0.578724, 5.953834, 2.338525, 0.371689, -0.599706, 5.649698, 2.290256, 0.401919,
+ -0.617615, 5.347900, 2.235157, 0.432204, -0.631632, 5.036417, 2.173932, 0.463151, -0.643082,
+ 4.735976, 2.107298, 0.493388, -0.649970, 4.432044, 2.036121, 0.524128, -0.654188, 4.145472,
+ 1.961595, 0.553930, -0.654671, 3.866877, 1.883602, 0.583856, -0.653051, 3.607848, 1.804521,
+ 0.611762, -0.646994, 3.356237, 1.724047, 0.639117, -0.638860, 3.122531, 1.643016, 0.666279,
+ -0.629093, 2.913178, 1.563932, 0.692936, -0.617862, 2.722675, 1.484614, 0.716498, -0.603279,
+ 2.536926, 1.406734, 0.742273, -0.589878, 2.381054, 1.331469, 0.764031, -0.572744, 2.228312,
+ 1.256796, 0.786601, -0.555933, 2.095451, 1.185290, 0.807776, -0.537992, 1.972866, 1.115940,
+ 0.828400, -0.519596, 1.863394, 1.048371, 0.847412, -0.499847, 1.760630, 0.982934, 0.866850,
+ -0.479920, 1.670998, 0.919972, 0.886340, -0.459434, 1.587962, 0.858100, 0.906933, -0.437767,
+ 1.515505, 0.796714, 0.927490, -0.414068, 1.448243, 0.736162, 0.950217, -0.390910, 1.390505,
+ 0.677613, 0.971545, -0.366964, 1.337865, 0.620477, 0.992901, -0.342603, 1.291104, 0.565807,
+ 1.015460, -0.318596, 1.251138, 0.513086, 1.037859, -0.294242, 1.214291, 0.461573, 1.060535,
+ -0.269601, 1.182517, 0.411838, 1.086885, -0.245608, 1.155300, 0.363221, 1.111237, -0.220589,
+ 1.129715, 0.317174, 1.138718, -0.196008, 1.108103, 0.273213, 1.164223, -0.170408, 1.089640,
+ 0.231968, 1.187256, -0.144205, 1.074145, 0.192987, 1.207851, -0.116945, 1.061615, 0.156118,
+ 1.222217, -0.088852, 1.047599, 0.118674, 1.230315, -0.059381, 1.030869, 0.078993, 1.235052,
+ -0.029145, 1.014126, 0.038924, 1.241359, 0.000479, 1.000114, -0.000211, 0.000169, -0.000465,
+ 4.953966, 2.747437, 0.000504, -0.001384, 8.544530, 2.747430, 0.002015, -0.005537, 8.545147,
+ 2.747339, 0.004542, -0.012477, 8.557734, 2.747125, 0.008064, -0.022143, 8.530193, 2.747341,
+ 0.012543, -0.034411, 8.465151, 2.747411, 0.018178, -0.049792, 8.543328, 2.746874, 0.024810,
+ -0.067784, 8.547247, 2.746396, 0.032489, -0.088416, 8.537436, 2.745730, 0.041313, -0.111580,
+ 8.526655, 2.744596, 0.051332, -0.137462, 8.517438, 2.743082, 0.062603, -0.165860, 8.502803,
+ 2.740950, 0.075240, -0.196548, 8.481507, 2.738057, 0.089341, -0.229440, 8.454287, 2.734174,
+ 0.105021, -0.264395, 8.420289, 2.729086, 0.122399, -0.301020, 8.373503, 2.722420, 0.141526,
+ -0.338997, 8.309059, 2.713686, 0.162451, -0.377589, 8.221539, 2.702492, 0.185098, -0.416349,
+ 8.100116, 2.687893, 0.209406, -0.454284, 7.941704, 2.669386, 0.235098, -0.490450, 7.733318,
+ 2.645590, 0.262100, -0.524592, 7.486120, 2.615709, 0.290103, -0.555558, 7.193498, 2.579231,
+ 0.319135, -0.583516, 6.874796, 2.534957, 0.348286, -0.606714, 6.516118, 2.483017, 0.378840,
+ -0.627850, 6.163912, 2.424214, 0.409608, -0.644715, 5.801404, 2.357563, 0.440553, -0.657657,
+ 5.435955, 2.285835, 0.470599, -0.665621, 5.063481, 2.207940, 0.503172, -0.673767, 4.743532,
+ 2.126440, 0.533884, -0.676009, 4.413409, 2.040694, 0.563808, -0.674536, 4.092169, 1.953979,
+ 0.591849, -0.668913, 3.787057, 1.865897, 0.621474, -0.663159, 3.520578, 1.777762, 0.650500,
+ -0.655018, 3.275065, 1.689902, 0.678011, -0.643949, 3.043141, 1.603528, 0.703490, -0.630030,
+ 2.827104, 1.519484, 0.728250, -0.614910, 2.632620, 1.436677, 0.752165, -0.598649, 2.455570,
+ 1.355753, 0.775894, -0.581771, 2.295932, 1.278884, 0.797650, -0.563193, 2.152291, 1.202767,
+ 0.818505, -0.543750, 2.022099, 1.130338, 0.838596, -0.524017, 1.903562, 1.060263, 0.858396,
+ -0.504064, 1.797204, 0.993077, 0.877088, -0.483418, 1.701208, 0.928606, 0.896606, -0.462786,
+ 1.617736, 0.866039, 0.914342, -0.440943, 1.539227, 0.804293, 0.933550, -0.419129, 1.470383,
+ 0.745206, 0.955237, -0.396100, 1.409100, 0.685832, 0.976700, -0.371743, 1.354930, 0.627953,
+ 0.997681, -0.346882, 1.305249, 0.572127, 1.020784, -0.322391, 1.262603, 0.517941, 1.043840,
+ -0.297564, 1.225115, 0.466188, 1.067224, -0.272639, 1.190817, 0.415499, 1.092358, -0.247664,
+ 1.161265, 0.366782, 1.117573, -0.222260, 1.133935, 0.319377, 1.145730, -0.196933, 1.111750,
+ 0.275293, 1.170822, -0.170577, 1.091981, 0.233306, 1.194559, -0.143878, 1.075810, 0.193950,
+ 1.214819, -0.116347, 1.062438, 0.156724, 1.229830, -0.088233, 1.048092, 0.118984, 1.238185,
+ -0.059408, 1.031325, 0.079385, 1.243527, -0.030703, 1.014698, 0.039893, 1.249724, -0.001520,
+ 0.999819, 0.000760, 0.000164, -0.000489, 5.157359, 2.976300, 0.000505, -0.001502, 9.891415,
+ 2.976286, 0.002016, -0.006000, 9.857730, 2.976197, 0.004543, -0.013519, 9.870651, 2.975832,
+ 0.008064, -0.023985, 9.855780, 2.976170, 0.012611, -0.037471, 9.850209, 2.975941, 0.018162,
+ -0.053866, 9.827134, 2.974968, 0.024820, -0.073390, 9.849955, 2.975010, 0.032545, -0.095758,
+ 9.842021, 2.974073, 0.041418, -0.120834, 9.829989, 2.972700, 0.051511, -0.148861, 9.817421,
+ 2.970736, 0.062920, -0.179456, 9.797347, 2.968033, 0.075744, -0.212674, 9.771533, 2.964371,
+ 0.090131, -0.248193, 9.735924, 2.959437, 0.106187, -0.285748, 9.687707, 2.952881, 0.124035,
+ -0.325017, 9.622684, 2.944273, 0.143733, -0.365463, 9.531452, 2.933093, 0.165262, -0.406157,
+ 9.401732, 2.918484, 0.188622, -0.446833, 9.232451, 2.899529, 0.213693, -0.486209, 9.013432,
+ 2.875137, 0.239987, -0.522925, 8.725671, 2.844166, 0.267796, -0.557452, 8.400028, 2.805649,
+ 0.296547, -0.588266, 8.023041, 2.758720, 0.325838, -0.614837, 7.606773, 2.702676, 0.355479,
+ -0.636760, 7.160680, 2.638483, 0.386984, -0.657230, 6.736765, 2.566849, 0.418853, -0.673592,
+ 6.313742, 2.488091, 0.450302, -0.684966, 5.884479, 2.402458, 0.481149, -0.691591, 5.455771,
+ 2.311816, 0.512177, -0.695337, 5.055698, 2.217330, 0.543437, -0.696370, 4.681506, 2.121285,
+ 0.574309, -0.694186, 4.334716, 2.024160, 0.604787, -0.689158, 4.008524, 1.927738, 0.633483,
+ -0.680580, 3.703505, 1.830456, 0.660766, -0.669088, 3.418386, 1.734934, 0.688471, -0.656673,
+ 3.168101, 1.642316, 0.715729, -0.642820, 2.941735, 1.550744, 0.740435, -0.626155, 2.730570,
+ 1.463345, 0.764114, -0.608299, 2.537561, 1.378151, 0.787028, -0.589519, 2.364323, 1.297630,
+ 0.807985, -0.569257, 2.207970, 1.217830, 0.830663, -0.550055, 2.076646, 1.142746, 0.850416,
+ -0.528812, 1.948085, 1.070757, 0.869609, -0.507478, 1.834684, 1.001282, 0.888324, -0.486131,
+ 1.734879, 0.934987, 0.907482, -0.464910, 1.645974, 0.871203, 0.924829, -0.442742, 1.563550,
+ 0.809260, 0.942958, -0.420777, 1.491264, 0.750037, 0.961999, -0.398842, 1.428069, 0.691715,
+ 0.981043, -0.375967, 1.369668, 0.635669, 1.002371, -0.351469, 1.318588, 0.578689, 1.025343,
+ -0.326601, 1.273628, 0.524424, 1.048511, -0.301395, 1.234572, 0.471403, 1.072242, -0.275835,
+ 1.198354, 0.419950, 1.096758, -0.250200, 1.166392, 0.370733, 1.122781, -0.224474, 1.138991,
+ 0.322864, 1.150871, -0.198592, 1.114313, 0.277723, 1.177319, -0.171805, 1.093534, 0.234950,
+ 1.201765, -0.144291, 1.077462, 0.195376, 1.222629, -0.115949, 1.063288, 0.157315, 1.237334,
+ -0.087140, 1.048366, 0.118843, 1.246153, -0.058094, 1.031224, 0.079207, 1.252570, -0.029194,
+ 1.014695, 0.039376, 1.259060, -0.000418, 0.999881, 0.000307, 0.000159, -0.000515, 5.393984,
+ 3.241865, 0.000505, -0.001636, 11.548038, 3.241848, 0.002016, -0.006534, 11.506640, 3.241718,
+ 0.004537, -0.014706, 11.513460, 3.241196, 0.008068, -0.026134, 11.510533, 3.241693, 0.012573,
+ -0.040676, 11.428978, 3.241030, 0.018212, -0.058794, 11.510745, 3.240924, 0.024847, -0.079926,
+ 11.497339, 3.240201, 0.032603, -0.104160, 11.484607, 3.238994, 0.041543, -0.131552, 11.470801,
+ 3.237182, 0.051738, -0.162012, 11.453219, 3.234635, 0.063313, -0.195260, 11.427244, 3.231153,
+ 0.076381, -0.231205, 11.388534, 3.226361, 0.091096, -0.269678, 11.340406, 3.219943, 0.107600,
+ -0.310170, 11.270127, 3.211448, 0.126017, -0.352435, 11.178583, 3.200168, 0.146411, -0.395551,
+ 11.046559, 3.185328, 0.168663, -0.438627, 10.858624, 3.165972, 0.192730, -0.480660, 10.606379,
+ 3.140735, 0.218497, -0.520987, 10.288093, 3.108388, 0.245752, -0.558483, 9.907480, 3.067586,
+ 0.273993, -0.592090, 9.453246, 3.016931, 0.303495, -0.622416, 8.966138, 2.956444, 0.333717,
+ -0.648303, 8.443776, 2.885116, 0.363928, -0.668640, 7.894122, 2.805963, 0.396240, -0.687748,
+ 7.385728, 2.718338, 0.427161, -0.699903, 6.838511, 2.622346, 0.460175, -0.711210, 6.356371,
+ 2.522476, 0.492593, -0.717734, 5.878312, 2.417984, 0.524449, -0.719956, 5.423285, 2.310941,
+ 0.556010, -0.719127, 4.997909, 2.201885, 0.587032, -0.715077, 4.600426, 2.093330, 0.617030,
+ -0.707574, 4.235885, 1.986585, 0.644684, -0.695781, 3.881712, 1.881279, 0.674483, -0.685313,
+ 3.590960, 1.777918, 0.700290, -0.669619, 3.303138, 1.678004, 0.727892, -0.654728, 3.057771,
+ 1.581162, 0.751694, -0.635727, 2.826642, 1.487769, 0.776271, -0.617343, 2.622178, 1.399628,
+ 0.799502, -0.597683, 2.441265, 1.313195, 0.821768, -0.577090, 2.276954, 1.232316, 0.841960,
+ -0.555165, 2.125744, 1.153914, 0.861582, -0.532983, 1.991236, 1.079598, 0.881460, -0.510933,
+ 1.874027, 1.008883, 0.899952, -0.488321, 1.766812, 0.940802, 0.918954, -0.466405, 1.673436,
+ 0.875653, 0.936130, -0.443623, 1.586986, 0.813130, 0.954799, -0.421532, 1.513558, 0.752241,
+ 0.972435, -0.398897, 1.445787, 0.694711, 0.990147, -0.376302, 1.384382, 0.638770, 1.009189,
+ -0.353623, 1.331934, 0.583826, 1.029687, -0.330635, 1.284478, 0.530476, 1.052604, -0.305698,
+ 1.243632, 0.477187, 1.076524, -0.279917, 1.204997, 0.425349, 1.101701, -0.253951, 1.171750,
+ 0.375165, 1.127264, -0.227541, 1.142519, 0.326869, 1.156397, -0.201265, 1.116817, 0.280912,
+ 1.183020, -0.173943, 1.095289, 0.237447, 1.208448, -0.145860, 1.078296, 0.196694, 1.230417,
+ -0.116901, 1.064416, 0.158409, 1.248617, -0.087507, 1.050504, 0.119483, 1.257310, -0.057353,
+ 1.032796, 0.079092, 1.263076, -0.027785, 1.015128, 0.038883, 1.269870, 0.001331, 0.999935,
+ -0.000557, 0.000154, -0.000549, 5.705205, 3.554136, 0.000506, -0.001797, 13.703335, 3.554133,
+ 0.002014, -0.007156, 13.614074, 3.553937, 0.004544, -0.016145, 13.657344, 3.553096, 0.008070,
+ -0.028652, 13.627997, 3.553894, 0.012584, -0.044617, 13.606235, 3.554000, 0.018180, -0.064288,
+ 13.581339, 3.549637, 0.024887, -0.087627, 13.608851, 3.552006, 0.032690, -0.114134, 13.599099,
+ 3.550341, 0.041705, -0.144154, 13.579829, 3.547982, 0.052035, -0.177400, 13.552845, 3.544641,
+ 0.063810, -0.213813, 13.515619, 3.539941, 0.077171, -0.252978, 13.460460, 3.533696, 0.092329,
+ -0.294852, 13.393559, 3.524977, 0.109390, -0.338688, 13.292376, 3.513655, 0.128455, -0.384018,
+ 13.147332, 3.498484, 0.149661, -0.429960, 12.945774, 3.478323, 0.172694, -0.475024, 12.658979,
+ 3.451862, 0.197650, -0.518614, 12.289564, 3.417602, 0.224156, -0.559298, 11.828307, 3.372913,
+ 0.252008, -0.596110, 11.285162, 3.317454, 0.281165, -0.629292, 10.684922, 3.251171, 0.311434,
+ -0.658379, 10.052939, 3.172222, 0.342741, -0.683455, 9.405296, 3.082825, 0.373543, -0.701674,
+ 8.716078, 2.983976, 0.407008, -0.719664, 8.108425, 2.876244, 0.438623, -0.729882, 7.461252,
+ 2.763279, 0.471872, -0.738696, 6.880182, 2.645590, 0.504700, -0.743136, 6.324308, 2.524680,
+ 0.537118, -0.743676, 5.808302, 2.402723, 0.569412, -0.741181, 5.332306, 2.281437, 0.598202,
+ -0.732348, 4.857402, 2.161401, 0.629640, -0.724832, 4.465554, 2.043872, 0.659239, -0.713435,
+ 4.093661, 1.930129, 0.686547, -0.698539, 3.752593, 1.817654, 0.715529, -0.684471, 3.457593,
+ 1.712567, 0.739456, -0.664983, 3.171220, 1.610687, 0.764892, -0.646322, 2.929674, 1.512031,
+ 0.789301, -0.626393, 2.710719, 1.419033, 0.809881, -0.603498, 2.506139, 1.330115, 0.833385,
+ -0.582934, 2.336089, 1.245859, 0.854254, -0.560419, 2.178470, 1.165042, 0.873964, -0.537294,
+ 2.040087, 1.086633, 0.893433, -0.514264, 1.911969, 1.015028, 0.911756, -0.490657, 1.799840,
+ 0.944938, 0.930894, -0.467601, 1.703188, 0.878743, 0.948078, -0.444043, 1.612092, 0.815356,
+ 0.966162, -0.421155, 1.534444, 0.753883, 0.984166, -0.398238, 1.462397, 0.695534, 1.002184,
+ -0.375278, 1.400793, 0.638806, 1.019669, -0.352159, 1.344172, 0.584549, 1.039571, -0.329651,
+ 1.295227, 0.531660, 1.059989, -0.306804, 1.251281, 0.480529, 1.081116, -0.283345, 1.211504,
+ 0.430071, 1.105742, -0.258568, 1.176400, 0.380277, 1.133080, -0.232146, 1.144519, 0.331076,
+ 1.161888, -0.205244, 1.118059, 0.284040, 1.192408, -0.177932, 1.097561, 0.239958, 1.221043,
+ -0.149532, 1.082021, 0.198751, 1.244141, -0.120046, 1.067634, 0.160114, 1.259465, -0.089542,
+ 1.051626, 0.121101, 1.268124, -0.058593, 1.033296, 0.079898, 1.274330, -0.028011, 1.015382,
+ 0.039038, 1.281590, 0.002330, 1.000087, -0.001259, 0.000149, -0.000587, 6.059834, 3.927143,
+ 0.000507, -0.001992, 16.560400, 3.927149, 0.002014, -0.007910, 16.406326, 3.926821, 0.004549,
+ -0.017856, 16.545532, 3.927027, 0.008064, -0.031632, 16.375853, 3.925487, 0.012450, -0.048749,
+ 15.928564, 3.928272, 0.018030, -0.070371, 16.072989, 3.917862, 0.024964, -0.096897, 16.458925,
+ 3.924489, 0.032807, -0.126073, 16.377851, 3.921896, 0.041917, -0.159205, 16.351561, 3.918860,
+ 0.052416, -0.195762, 16.307037, 3.914339, 0.064464, -0.235784, 16.255514, 3.907954, 0.078225,
+ -0.278812, 16.176226, 3.899254, 0.093900, -0.324457, 16.066530, 3.887455, 0.111657, -0.372174,
+ 15.913818, 3.871777, 0.131478, -0.420530, 15.669197, 3.850776, 0.153574, -0.469330, 15.355453,
+ 3.822348, 0.177505, -0.516029, 14.908978, 3.785168, 0.203383, -0.560585, 14.352687, 3.736602,
+ 0.230569, -0.600607, 13.666022, 3.675046, 0.259188, -0.636296, 12.900244, 3.599811, 0.289272,
+ -0.668312, 12.111226, 3.510550, 0.320490, -0.695986, 11.292102, 3.408535, 0.353031, -0.719848,
+ 10.493485, 3.295667, 0.385228, -0.737073, 9.661955, 3.171998, 0.419219, -0.752419, 8.909942,
+ 3.042428, 0.452096, -0.761179, 8.155107, 2.907108, 0.484909, -0.766166, 7.450609, 2.769858,
+ 0.518306, -0.768596, 6.811866, 2.631935, 0.550067, -0.765683, 6.205275, 2.492870, 0.582562,
+ -0.761197, 5.663215, 2.358645, 0.614450, -0.753834, 5.165358, 2.227377, 0.644563, -0.742860,
+ 4.712554, 2.097547, 0.673658, -0.729294, 4.306101, 1.974920, 0.702857, -0.714839, 3.943352,
+ 1.857613, 0.729350, -0.696774, 3.609432, 1.743601, 0.754958, -0.677394, 3.308389, 1.636607,
+ 0.779575, -0.657018, 3.043803, 1.533841, 0.800491, -0.633342, 2.793592, 1.437092, 0.825030,
+ -0.612471, 2.590307, 1.344272, 0.847535, -0.589882, 2.406477, 1.256436, 0.865979, -0.564850,
+ 2.231999, 1.173938, 0.886254, -0.541357, 2.083556, 1.094722, 0.905566, -0.517353, 1.950928,
+ 1.021107, 0.924607, -0.493320, 1.835979, 0.948941, 0.943365, -0.469366, 1.731417, 0.881060,
+ 0.960405, -0.444745, 1.635838, 0.816479, 0.977893, -0.420493, 1.552981, 0.754604, 0.996573,
+ -0.397150, 1.481595, 0.694917, 1.014000, -0.373483, 1.414070, 0.638445, 1.031807, -0.349985,
+ 1.356031, 0.584035, 1.051877, -0.327062, 1.305041, 0.530010, 1.071701, -0.304134, 1.258836,
+ 0.479439, 1.093109, -0.280962, 1.217297, 0.429763, 1.116681, -0.258121, 1.182063, 0.381050,
+ 1.143886, -0.235365, 1.150039, 0.333395, 1.175163, -0.211621, 1.125074, 0.287477, 1.203675,
+ -0.184061, 1.102339, 0.243301, 1.230477, -0.154815, 1.083927, 0.201826, 1.253134, -0.124513,
+ 1.067989, 0.162271, 1.270092, -0.093383, 1.052032, 0.122855, 1.279576, -0.061770, 1.033685,
+ 0.081639, 1.286472, -0.030317, 1.015583, 0.040411, 1.294476, 0.000964, 1.000206, -0.000454,
+ 0.000144, -0.000630, 6.467978, 4.381146, 0.000504, -0.002208, 20.193617, 4.381151, 0.002017,
+ -0.008834, 20.206446, 4.380687, 0.004536, -0.019864, 20.183254, 4.380550, 0.008174, -0.035759,
+ 20.564249, 4.381247, 0.012608, -0.055034, 20.111612, 4.382390, 0.018198, -0.079119, 20.106096,
+ 4.379815, 0.025057, -0.108067, 20.215635, 4.376874, 0.032962, -0.140630, 20.153549, 4.374143,
+ 0.042199, -0.177350, 20.084061, 4.369558, 0.052928, -0.218094, 20.026609, 4.363287, 0.065327,
+ -0.262407, 19.940054, 4.354386, 0.079568, -0.309833, 19.806814, 4.342127, 0.095961, -0.360074,
+ 19.641878, 4.325533, 0.114516, -0.411747, 19.370914, 4.302950, 0.135349, -0.463726, 18.983900,
+ 4.271991, 0.158293, -0.514211, 18.433926, 4.230856, 0.183348, -0.562511, 17.733471, 4.176250,
+ 0.209959, -0.606310, 16.864214, 4.105895, 0.238736, -0.646958, 15.935207, 4.020104, 0.268543,
+ -0.681574, 14.890014, 3.916094, 0.299996, -0.712458, 13.846786, 3.798239, 0.331930, -0.737130,
+ 12.758296, 3.664191, 0.365222, -0.758156, 11.732940, 3.521867, 0.399061, -0.774364, 10.741743,
+ 3.369831, 0.433480, -0.786412, 9.812527, 3.212079, 0.467002, -0.792373, 8.915130, 3.053715,
+ 0.500754, -0.795410, 8.094276, 2.894526, 0.534023, -0.794617, 7.342067, 2.735959, 0.566988,
+ -0.790689, 6.664186, 2.581160, 0.599960, -0.784433, 6.052983, 2.432318, 0.630599, -0.773378,
+ 5.486277, 2.287630, 0.660807, -0.760334, 4.982516, 2.150183, 0.690103, -0.745430, 4.531104,
+ 2.017266, 0.717315, -0.727511, 4.120734, 1.891699, 0.743819, -0.708376, 3.759599, 1.772680,
+ 0.770147, -0.688632, 3.441912, 1.660620, 0.793510, -0.665931, 3.152600, 1.553166, 0.816535,
+ -0.643045, 2.898883, 1.452080, 0.839163, -0.619917, 2.674488, 1.355544, 0.859066, -0.594923,
+ 2.469262, 1.267232, 0.879489, -0.570343, 2.292209, 1.181702, 0.898525, -0.544975, 2.131086,
+ 1.102089, 0.918359, -0.520585, 1.994526, 1.024744, 0.937502, -0.496044, 1.873079, 0.951712,
+ 0.955573, -0.471010, 1.761232, 0.883374, 0.972957, -0.445712, 1.661604, 0.818008, 0.991248,
+ -0.421201, 1.577169, 0.754446, 1.008997, -0.396444, 1.499653, 0.694518, 1.028127, -0.372362,
+ 1.432030, 0.637259, 1.045710, -0.347895, 1.369870, 0.581515, 1.065977, -0.324409, 1.317341,
+ 0.527713, 1.087469, -0.301181, 1.270447, 0.476281, 1.109943, -0.277866, 1.228398, 0.426403,
+ 1.134440, -0.254849, 1.190986, 0.377822, 1.160986, -0.231754, 1.157681, 0.330740, 1.188458,
+ -0.207973, 1.128665, 0.286014, 1.214405, -0.183424, 1.103711, 0.243600, 1.239504, -0.157972,
+ 1.084253, 0.203686, 1.262961, -0.130607, 1.068258, 0.165214, 1.280340, -0.099652, 1.051919,
+ 0.126067, 1.292129, -0.067363, 1.034016, 0.084791, 1.299876, -0.035026, 1.015775, 0.042786,
+ 1.308328, -0.002944, 0.999963, 0.001385, 0.000138, -0.000681, 6.943771, 4.946556, 0.000503,
+ -0.002486, 25.346689, 4.946532, 0.002016, -0.009973, 25.494320, 4.946311, 0.004539, -0.022440,
+ 25.484949, 4.945823, 0.008069, -0.039836, 25.420902, 4.945311, 0.012628, -0.062172, 25.394403,
+ 4.945041, 0.018294, -0.089609, 25.440279, 4.943295, 0.025079, -0.121584, 25.399988, 4.939368,
+ 0.033142, -0.158595, 25.356537, 4.936200, 0.042596, -0.199971, 25.295067, 4.929842, 0.053628,
+ -0.245624, 25.196465, 4.920586, 0.066496, -0.295240, 25.055311, 4.907700, 0.081434, -0.348006,
+ 24.846170, 4.889647, 0.098640, -0.403167, 24.527803, 4.864680, 0.118231, -0.459106, 24.051735,
+ 4.830574, 0.140139, -0.513907, 23.352467, 4.783530, 0.164198, -0.565953, 22.418245, 4.720530,
+ 0.190502, -0.614858, 21.324049, 4.638075, 0.218530, -0.658304, 20.038671, 4.535464, 0.248094,
+ -0.696133, 18.639786, 4.411646, 0.279435, -0.729388, 17.234526, 4.268872, 0.312002, -0.757534,
+ 15.830426, 4.109603, 0.346173, -0.781866, 14.495901, 3.938782, 0.379435, -0.797579, 13.136444,
+ 3.756138, 0.414945, -0.812334, 11.946491, 3.571258, 0.449991, -0.821119, 10.811908, 3.384217,
+ 0.484636, -0.825066, 9.763482, 3.198076, 0.518675, -0.824728, 8.796811, 3.015808, 0.552559,
+ -0.821710, 7.932528, 2.836886, 0.587272, -0.817478, 7.185156, 2.664995, 0.616960, -0.804441,
+ 6.445302, 2.502223, 0.648054, -0.792063, 5.818812, 2.345851, 0.678575, -0.777793, 5.264731,
+ 2.197150, 0.707287, -0.760476, 4.766033, 2.056042, 0.735851, -0.742541, 4.335871, 1.922805,
+ 0.760594, -0.720503, 3.928021, 1.798585, 0.784534, -0.697719, 3.579153, 1.680605, 0.811029,
+ -0.677036, 3.285307, 1.568942, 0.831809, -0.651479, 3.001423, 1.465496, 0.854364, -0.627376,
+ 2.760672, 1.367849, 0.872639, -0.600496, 2.540697, 1.275644, 0.894296, -0.576297, 2.355273,
+ 1.188638, 0.913123, -0.550377, 2.188563, 1.105652, 0.932025, -0.524640, 2.040739, 1.028614,
+ 0.949876, -0.498402, 1.910315, 0.954421, 0.968933, -0.473220, 1.795750, 0.884061, 0.985366,
+ -0.447086, 1.690336, 0.817765, 1.004940, -0.422394, 1.599626, 0.753295, 1.022217, -0.396726,
+ 1.519055, 0.693380, 1.041490, -0.371854, 1.448745, 0.635747, 1.059920, -0.346769, 1.384292,
+ 0.579508, 1.080408, -0.322343, 1.328798, 0.525045, 1.101632, -0.297979, 1.279898, 0.473773,
+ 1.124812, -0.274059, 1.234005, 0.422949, 1.148503, -0.249954, 1.195373, 0.374609, 1.174554,
+ -0.225988, 1.160362, 0.327350, 1.202931, -0.201932, 1.131307, 0.283494, 1.229335, -0.176886,
+ 1.105885, 0.241092, 1.254254, -0.151225, 1.085802, 0.201514, 1.275743, -0.124282, 1.068524,
+ 0.162866, 1.292929, -0.097122, 1.051493, 0.124991, 1.305805, -0.068939, 1.033890, 0.085521,
+ 1.314991, -0.040082, 1.015927, 0.045247, 1.324033, -0.009923, 0.999893, 0.004738, 0.000131,
+ -0.000745, 7.562414, 5.671075, 0.000473, -0.002681, 27.216688, 5.670949, 0.002021, -0.011462,
+ 32.962402, 5.670177, 0.004540, -0.025728, 33.183949, 5.670197, 0.008087, -0.045746, 33.185688,
+ 5.667313, 0.012673, -0.071427, 33.170441, 5.668396, 0.018358, -0.102673, 33.145138, 5.665252,
+ 0.025299, -0.139780, 33.303326, 5.653404, 0.033469, -0.181718, 33.107243, 5.652829, 0.043139,
+ -0.228698, 32.859524, 5.645676, 0.054622, -0.280648, 32.694893, 5.631547, 0.068115, -0.336524,
+ 32.422569, 5.611561, 0.083957, -0.395671, 32.035511, 5.583449, 0.102259, -0.456164, 31.415047,
+ 5.543651, 0.123021, -0.515765, 30.470440, 5.488278, 0.146127, -0.572309, 29.186451, 5.413118,
+ 0.171749, -0.625710, 27.653852, 5.312369, 0.199549, -0.673853, 25.902435, 5.185774, 0.229188,
+ -0.715905, 23.978609, 5.030582, 0.260421, -0.751533, 21.999035, 4.853484, 0.293421, -0.782309,
+ 20.087366, 4.656137, 0.327077, -0.806332, 18.186535, 4.443975, 0.361892, -0.825818, 16.418409,
+ 4.223844, 0.397146, -0.840019, 14.774344, 3.998959, 0.434169, -0.852434, 13.321097, 3.775443,
+ 0.469288, -0.856632, 11.929448, 3.552818, 0.504319, -0.857130, 10.675201, 3.338825, 0.540067,
+ -0.855903, 9.591900, 3.130547, 0.575404, -0.851565, 8.607655, 2.932930, 0.606782, -0.839818,
+ 7.690560, 2.743876, 0.638660, -0.827508, 6.900781, 2.565115, 0.670577, -0.814154, 6.216821,
+ 2.395215, 0.696718, -0.793162, 5.551886, 2.238233, 0.725990, -0.775291, 5.015406, 2.090264,
+ 0.754140, -0.755758, 4.546843, 1.950834, 0.775992, -0.729824, 4.094254, 1.820582, 0.802990,
+ -0.708909, 3.732984, 1.699191, 0.828291, -0.686483, 3.413194, 1.583805, 0.847406, -0.659162,
+ 3.103861, 1.478093, 0.864951, -0.631051, 2.832976, 1.378496, 0.887154, -0.606590, 2.616645,
+ 1.282127, 0.906337, -0.580124, 2.413988, 1.194643, 0.927184, -0.554835, 2.244380, 1.110354,
+ 0.943810, -0.527583, 2.081964, 1.031996, 0.963630, -0.502243, 1.948979, 0.956718, 0.979691,
+ -0.475006, 1.822701, 0.886957, 0.997690, -0.448815, 1.715714, 0.819006, 1.016460, -0.423044,
+ 1.621868, 0.754892, 1.035485, -0.397637, 1.539537, 0.693707, 1.053165, -0.371775, 1.462285,
+ 0.634867, 1.072394, -0.346372, 1.396193, 0.578574, 1.093397, -0.321291, 1.338344, 0.524341,
+ 1.115194, -0.296102, 1.287594, 0.472059, 1.137943, -0.271023, 1.240495, 0.421674, 1.164163,
+ -0.246367, 1.201224, 0.371963, 1.191457, -0.221414, 1.164472, 0.325040, 1.220253, -0.196228,
+ 1.134325, 0.280343, 1.245456, -0.169991, 1.108214, 0.238098, 1.270647, -0.143314, 1.087277,
+ 0.197886, 1.292124, -0.115881, 1.069397, 0.159560, 1.309091, -0.087816, 1.051426, 0.120547,
+ 1.321130, -0.059301, 1.032904, 0.080834, 1.332484, -0.030912, 1.015767, 0.040933, 1.342834,
+ -0.002172, 0.999591, 0.001185, 0.000125, -0.000830, 8.392562, 6.634228, 0.000443, -0.002936,
+ 29.687805, 6.634032, 0.002016, -0.013374, 45.025234, 6.633008, 0.004540, -0.030089, 45.020294,
+ 6.633056, 0.008092, -0.053499, 45.066029, 6.626466, 0.012710, -0.083610, 44.810101, 6.630330,
+ 0.018485, -0.120260, 45.216747, 6.614516, 0.025134, -0.161031, 44.674168, 6.600349, 0.033897,
+ -0.212161, 44.819195, 6.610186, 0.043978, -0.266661, 44.450245, 6.593605, 0.056094, -0.326582,
+ 44.134544, 6.570142, 0.070528, -0.390342, 43.591648, 6.536712, 0.087498, -0.456162, 42.708160,
+ 6.488329, 0.107138, -0.521609, 41.365093, 6.420198, 0.129461, -0.584225, 39.525822, 6.323702,
+ 0.154245, -0.641931, 37.186111, 6.193606, 0.181228, -0.692829, 34.478470, 6.026897, 0.210711,
+ -0.738440, 31.680904, 5.825769, 0.242181, -0.777397, 28.828054, 5.595428, 0.275337, -0.809980,
+ 26.042755, 5.342321, 0.309698, -0.835990, 23.376804, 5.073076, 0.345702, -0.858077, 20.965754,
+ 4.794572, 0.382135, -0.874122, 18.710079, 4.516676, 0.419871, -0.887133, 16.713011, 4.241767,
+ 0.455609, -0.891199, 14.819674, 3.972124, 0.492617, -0.894082, 13.187921, 3.717271, 0.528186,
+ -0.891270, 11.708584, 3.471719, 0.563462, -0.885719, 10.422834, 3.237760, 0.596013, -0.874241,
+ 9.237741, 3.019060, 0.629455, -0.862814, 8.248549, 2.813572, 0.661110, -0.848126, 7.358398,
+ 2.621046, 0.690314, -0.829798, 6.569392, 2.441627, 0.720589, -0.812314, 5.905934, 2.274629,
+ 0.745631, -0.788704, 5.276800, 2.119423, 0.771488, -0.766133, 4.752773, 1.974380, 0.798704,
+ -0.744726, 4.306095, 1.839482, 0.820172, -0.718062, 3.889792, 1.713244, 0.844368, -0.693972,
+ 3.545456, 1.594809, 0.863128, -0.665748, 3.212762, 1.487512, 0.880094, -0.637003, 2.926572,
+ 1.386724, 0.904252, -0.613728, 2.704260, 1.288131, 0.920506, -0.585217, 2.483164, 1.199845,
+ 0.940919, -0.559603, 2.300348, 1.114958, 0.957044, -0.531597, 2.130516, 1.034754, 0.972648,
+ -0.503583, 1.979313, 0.960912, 0.994318, -0.478813, 1.859664, 0.889786, 1.008754, -0.450943,
+ 1.742705, 0.820833, 1.028667, -0.425516, 1.645220, 0.756332, 1.046145, -0.398977, 1.557184,
+ 0.693921, 1.067212, -0.373657, 1.480814, 0.635955, 1.084111, -0.346657, 1.408762, 0.578832,
+ 1.106749, -0.321392, 1.350468, 0.523561, 1.128440, -0.295773, 1.294865, 0.471146, 1.151073,
+ -0.270028, 1.246118, 0.420298, 1.178601, -0.244816, 1.204226, 0.370575, 1.206845, -0.219027,
+ 1.166896, 0.323716, 1.235963, -0.192622, 1.135756, 0.278058, 1.263030, -0.165331, 1.109240,
+ 0.235743, 1.288937, -0.137489, 1.088379, 0.195390, 1.310681, -0.108685, 1.068987, 0.156439,
+ 1.334352, -0.079710, 1.054273, 0.117096, 1.344847, -0.049947, 1.034598, 0.076554, 1.354943,
+ -0.020272, 1.016079, 0.035585, 1.365515, 0.009170, 0.999969, -0.004771, 0.000117, -0.000935,
+ 9.424866, 7.979243, 0.000410, -0.003275, 33.013195, 7.979422, 0.002009, -0.016024, 64.370331,
+ 7.977156, 0.004541, -0.036176, 64.655952, 7.976128, 0.008109, -0.064384, 64.864494, 7.964988,
+ 0.012694, -0.099984, 64.487198, 7.971348, 0.018554, -0.143991, 64.637970, 7.923116, 0.025303,
+ -0.192040, 61.930538, 7.953975, 0.035297, -0.259442, 66.274422, 7.921861, 0.045226, -0.318370,
+ 63.334690, 7.909609, 0.058370, -0.388821, 62.686401, 7.864696, 0.074083, -0.461667, 61.332054,
+ 7.801843, 0.092537, -0.533744, 59.125607, 7.708949, 0.113781, -0.601905, 55.997845, 7.575799,
+ 0.137786, -0.664409, 52.177567, 7.393524, 0.164770, -0.721193, 48.019485, 7.161756, 0.193894,
+ -0.768842, 43.460278, 6.882018, 0.225586, -0.810332, 39.086590, 6.564607, 0.259311, -0.845096,
+ 34.896049, 6.221983, 0.294517, -0.872849, 30.952213, 5.865831, 0.331163, -0.895159, 27.375792,
+ 5.507064, 0.368964, -0.912860, 24.213310, 5.149763, 0.407255, -0.925338, 21.364958, 4.806172,
+ 0.444704, -0.930956, 18.791691, 4.472272, 0.482041, -0.932576, 16.521160, 4.160864, 0.519572,
+ -0.931547, 14.589918, 3.865206, 0.556236, -0.926554, 12.887797, 3.590445, 0.590431, -0.915839,
+ 11.352402, 3.332747, 0.622723, -0.901266, 10.002660, 3.093264, 0.657029, -0.888747, 8.905210,
+ 2.873842, 0.686164, -0.868666, 7.876704, 2.666740, 0.719168, -0.853152, 7.051816, 2.479017,
+ 0.742294, -0.826169, 6.226034, 2.306498, 0.770320, -0.804936, 5.590831, 2.141328, 0.792337,
+ -0.777772, 4.984083, 1.994663, 0.819050, -0.755478, 4.507655, 1.853950, 0.837684, -0.726072,
+ 4.049884, 1.725590, 0.861324, -0.701424, 3.678201, 1.606303, 0.880741, -0.673615, 3.337163,
+ 1.495452, 0.903335, -0.648506, 3.055720, 1.391162, 0.920311, -0.619640, 2.792068, 1.294734,
+ 0.935769, -0.590245, 2.554566, 1.204518, 0.956592, -0.564944, 2.366468, 1.118630, 0.972424,
+ -0.536842, 2.187863, 1.038323, 0.986269, -0.508020, 2.023480, 0.963803, 1.006122, -0.482411,
+ 1.895137, 0.890986, 1.022504, -0.455110, 1.775886, 0.820936, 1.037905, -0.427450, 1.665951,
+ 0.758556, 1.059281, -0.402198, 1.577363, 0.696126, 1.076613, -0.375156, 1.493391, 0.636676,
+ 1.097828, -0.349577, 1.421129, 0.579947, 1.116671, -0.322955, 1.355205, 0.525140, 1.140514,
+ -0.297406, 1.299979, 0.471460, 1.166473, -0.271786, 1.249847, 0.420473, 1.192591, -0.245461,
+ 1.204625, 0.371118, 1.223349, -0.219412, 1.166686, 0.322600, 1.254833, -0.192660, 1.134121,
+ 0.277572, 1.285808, -0.165167, 1.108617, 0.234417, 1.322015, -0.137236, 1.093841, 0.194640,
+ 1.342172, -0.106871, 1.074616, 0.155001, 1.357238, -0.075759, 1.053550, 0.114648, 1.367725,
+ -0.044279, 1.033851, 0.073254, 1.379461, -0.013001, 1.015713, 0.031895, 1.391625, 0.018075,
+ 1.000203, -0.009397, 0.000109, -0.001093, 10.986820, 9.992467, 0.000378, -0.003779, 37.989063,
+ 9.992861, 0.002028, -0.020252, 101.850441, 9.988345, 0.004557, -0.045429, 101.106750, 9.983879,
+ 0.008115, -0.080453, 100.646606, 9.953411, 0.012864, -0.125836, 101.366592, 9.943727, 0.018734,
+ -0.179350, 100.786118, 9.908408, 0.026314, -0.243680, 99.779343, 9.821631, 0.035500, -0.313552,
+ 98.608231, 9.782450, 0.047562, -0.394644, 97.689568, 9.845875, 0.062065, -0.476697, 95.177795,
+ 9.755218, 0.079552, -0.557933, 91.095581, 9.615121, 0.099905, -0.632818, 85.110382, 9.408299,
+ 0.123231, -0.699926, 77.948921, 9.120996, 0.149980, -0.760671, 70.491119, 8.764173, 0.179550,
+ -0.812251, 62.821407, 8.341752, 0.211839, -0.855909, 55.512890, 7.876337, 0.246434, -0.892023,
+ 48.744549, 7.386268, 0.282317, -0.919200, 42.462059, 6.886009, 0.319580, -0.940333, 36.901031,
+ 6.400318, 0.360135, -0.962176, 32.353752, 5.937503, 0.397805, -0.969755, 27.996445, 5.489783,
+ 0.437077, -0.976494, 24.359192, 5.072855, 0.474388, -0.975265, 21.124300, 4.684682, 0.513695,
+ -0.975335, 18.476677, 4.326597, 0.551542, -0.970264, 16.167391, 3.999049, 0.587525, -0.960365,
+ 14.143442, 3.696317, 0.621251, -0.945944, 12.374341, 3.414176, 0.654738, -0.930709, 10.877112,
+ 3.160455, 0.685794, -0.911702, 9.580887, 2.921461, 0.717135, -0.892948, 8.481939, 2.707478,
+ 0.740798, -0.865086, 7.435941, 2.510382, 0.770920, -0.845137, 6.650625, 2.329648, 0.792303,
+ -0.815956, 5.879976, 2.163206, 0.818363, -0.792225, 5.274404, 2.008042, 0.837362, -0.762396,
+ 4.700960, 1.867576, 0.862266, -0.738465, 4.254798, 1.735819, 0.880069, -0.708890, 3.828697,
+ 1.614690, 0.896021, -0.678588, 3.451655, 1.503477, 0.920156, -0.654832, 3.168722, 1.395800,
+ 0.934948, -0.624740, 2.879533, 1.299955, 0.949686, -0.595203, 2.628258, 1.208597, 0.970989,
+ -0.570041, 2.433689, 1.122310, 0.985606, -0.541116, 2.241461, 1.042168, 1.000819, -0.512835,
+ 2.075567, 0.966543, 1.012209, -0.483024, 1.919932, 0.895758, 1.035320, -0.459125, 1.807884,
+ 0.825668, 1.052077, -0.432333, 1.695689, 0.760812, 1.070459, -0.406131, 1.595491, 0.699897,
+ 1.088704, -0.379721, 1.508512, 0.640575, 1.103817, -0.352104, 1.428159, 0.583765, 1.131711,
+ -0.328122, 1.366565, 0.528240, 1.156448, -0.302568, 1.306843, 0.473988, 1.181821, -0.276487,
+ 1.252861, 0.422189, 1.211347, -0.250540, 1.205265, 0.372005, 1.243636, -0.224264, 1.165943,
+ 0.324184, 1.283038, -0.198289, 1.137772, 0.278419, 1.316722, -0.170179, 1.115057, 0.235425,
+ 1.342715, -0.140095, 1.092994, 0.195084, 1.363288, -0.108794, 1.071875, 0.155439, 1.380656,
+ -0.076774, 1.052475, 0.114636, 1.394826, -0.044509, 1.032525, 0.072890, 1.408830, -0.011968,
+ 1.015459, 0.031101, 1.422370, 0.020555, 0.999808, -0.011002, 0.000100, -0.001334, 13.377127,
+ 13.342275, 0.000342, -0.004563, 45.758434, 13.342710, 0.002026, -0.027004, 179.672058,
+ 13.331846, 0.004559, -0.060563, 179.294235, 13.314877, 0.008232, -0.108154, 181.242035,
+ 13.222856, 0.013031, -0.167590, 179.684509, 13.153860, 0.019526, -0.242041, 181.004608,
+ 12.986094, 0.026364, -0.309289, 159.606293, 13.247752, 0.037670, -0.409755, 179.468521,
+ 12.368877, 0.051804, -0.512051, 167.955582, 12.981333, 0.068214, -0.601994, 156.278793,
+ 12.704532, 0.088295, -0.686849, 143.096878, 12.316531, 0.111478, -0.758670, 127.423111,
+ 11.793048, 0.138336, -0.821348, 111.763031, 11.157992, 0.168447, -0.873616, 96.887924,
+ 10.447472, 0.201411, -0.916322, 83.225327, 9.696606, 0.237443, -0.953090, 71.403137, 8.949244,
+ 0.274234, -0.977751, 60.739277, 8.225874, 0.314566, -1.003135, 52.115578, 7.547433, 0.353932,
+ -1.016312, 44.341869, 6.910326, 0.393858, -1.024848, 37.827263, 6.324401, 0.433805, -1.028950,
+ 32.380932, 5.790555, 0.475812, -1.034084, 27.955982, 5.312826, 0.513254, -1.026743, 23.977417,
+ 4.866118, 0.549965, -1.016740, 20.628025, 4.468437, 0.590300, -1.012030, 18.036856, 4.105483,
+ 0.626420, -0.998919, 15.669224, 3.780593, 0.658897, -0.979874, 13.603898, 3.482054, 0.687252,
+ -0.955238, 11.788331, 3.211213, 0.718941, -0.935663, 10.355552, 2.962083, 0.749877, -0.915206,
+ 9.131123, 2.741382, 0.772094, -0.884837, 7.973935, 2.536501, 0.799495, -0.861214, 7.086230,
+ 2.347282, 0.820136, -0.830976, 6.240769, 2.179332, 0.846715, -0.807408, 5.604792, 2.018005,
+ 0.865176, -0.776657, 4.975034, 1.877021, 0.881100, -0.744657, 4.442767, 1.743528, 0.907637,
+ -0.722088, 4.035177, 1.621563, 0.922239, -0.690432, 3.633160, 1.506158, 0.936558, -0.659650,
+ 3.281798, 1.403606, 0.950047, -0.629105, 2.974179, 1.304276, 0.961959, -0.598277, 2.704483,
+ 1.213888, 0.987410, -0.576085, 2.510453, 1.125569, 0.999996, -0.546494, 2.304016, 1.045567,
+ 1.014127, -0.518186, 2.127867, 0.970718, 1.036275, -0.494009, 1.985804, 0.897557, 1.049695,
+ -0.465659, 1.845074, 0.830584, 1.064617, -0.438159, 1.725130, 0.766083, 1.077131, -0.409813,
+ 1.613818, 0.705101, 1.101054, -0.385632, 1.528694, 0.644828, 1.122361, -0.360045, 1.447086,
+ 0.587878, 1.147359, -0.335186, 1.377588, 0.532130, 1.169881, -0.309040, 1.313673, 0.478843,
+ 1.200554, -0.284590, 1.257256, 0.426855, 1.232047, -0.259332, 1.208431, 0.376125, 1.275402,
+ -0.235215, 1.174692, 0.326614, 1.306595, -0.207508, 1.141042, 0.281524, 1.334304, -0.178290,
+ 1.111778, 0.238694, 1.364678, -0.148530, 1.090976, 0.198549, 1.387168, -0.117114, 1.069308,
+ 0.158529, 1.408657, -0.084977, 1.050625, 0.118042, 1.426214, -0.052052, 1.031444, 0.076541,
+ 1.444257, -0.018653, 1.014298, 0.034061, 1.460618, 0.015206, 0.999413, -0.008132, 0.000100,
+ -0.002003, 20.052612, 20.032721, 0.000297, -0.005947, 59.540512, 20.033842, 0.002022,
+ -0.040439, 404.848511, 20.032743, 0.004588, -0.090999, 403.741241, 19.910591, 0.008769,
+ -0.169802, 441.471558, 19.572552, 0.013708, -0.253629, 411.667816, 19.145721, 0.020331,
+ -0.349396, 371.322571, 18.591049, 0.030259, -0.468121, 385.816498, 18.331083, 0.045190,
+ -0.611444, 391.924133, 15.807686, 0.058476, -0.676875, 319.638641, 16.947781, 0.079894,
+ -0.781421, 278.804260, 17.512903, 0.103871, -0.855116, 235.999786, 16.290295, 0.131756,
+ -0.915747, 197.168076, 14.956566, 0.163487, -0.966333, 163.452347, 13.608010, 0.198693,
+ -1.008386, 135.632706, 12.299661, 0.236157, -1.039862, 111.919281, 11.088790, 0.274579,
+ -1.059988, 92.136581, 9.983883, 0.317164, -1.084069, 77.063034, 9.008505, 0.357624, -1.092124,
+ 63.963051, 8.127298, 0.399009, -1.097560, 53.483341, 7.347628, 0.441182, -1.100981, 45.052429,
+ 6.658191, 0.481606, -1.097318, 37.932640, 6.047333, 0.524253, -1.096570, 32.395638, 5.505878,
+ 0.564351, -1.088739, 27.679380, 5.018494, 0.600843, -1.073396, 23.611519, 4.580770, 0.635527,
+ -1.055024, 20.207081, 4.194785, 0.672045, -1.039775, 17.469036, 3.847436, 0.698372, -1.009545,
+ 14.928226, 3.532546, 0.729336, -0.987168, 12.953170, 3.248834, 0.761147, -0.966299, 11.346271,
+ 2.994166, 0.782270, -0.932841, 9.813129, 2.762244, 0.811832, -0.910431, 8.672224, 2.549933,
+ 0.832053, -0.878369, 7.578633, 2.363132, 0.849383, -0.844673, 6.648379, 2.189266, 0.866020,
+ -0.811703, 5.850784, 2.031716, 0.893083, -0.789181, 5.273372, 1.884480, 0.909212, -0.757541,
+ 4.700618, 1.750298, 0.923169, -0.725157, 4.196640, 1.627590, 0.937112, -0.693769, 3.764841,
+ 1.514906, 0.961901, -0.670828, 3.444598, 1.406839, 0.975245, -0.640240, 3.120745, 1.307873,
+ 0.989696, -0.611032, 2.840732, 1.216417, 1.002057, -0.581144, 2.591596, 1.132553, 1.014022,
+ -0.551620, 2.373820, 1.051695, 1.025307, -0.522268, 2.177992, 0.977500, 1.052190, -0.500826,
+ 2.042511, 0.904301, 1.064408, -0.472355, 1.891934, 0.837557, 1.077876, -0.444815, 1.761054,
+ 0.773004, 1.088939, -0.416531, 1.638939, 0.713958, 1.118551, -0.395057, 1.555724, 0.652485,
+ 1.134469, -0.368289, 1.465490, 0.596330, 1.162778, -0.345095, 1.390977, 0.539703, 1.185298,
+ -0.319527, 1.321225, 0.486250, 1.208419, -0.293590, 1.259318, 0.434178, 1.261013, -0.273471,
+ 1.219767, 0.382032, 1.297811, -0.248226, 1.176422, 0.334190, 1.326591, -0.220354, 1.139881,
+ 0.289075, 1.357918, -0.191937, 1.111418, 0.246259, 1.387590, -0.162282, 1.086511, 0.205129,
+ 1.415797, -0.131515, 1.067072, 0.165601, 1.440194, -0.099555, 1.047799, 0.125462, 1.465600,
+ -0.066957, 1.030406, 0.084082, 1.487714, -0.033496, 1.013889, 0.041981, 1.509947, 0.000663,
+ 0.998773, -0.000485, 0.000100, -0.004009, 40.102047, 40.087105, 0.000228, -0.009141, 91.431366,
+ 40.074432, 0.001522, -0.060544, 605.651733, 39.918827, 0.004919, -0.188871, 1712.982300,
+ 38.873421, 0.009053, -0.320325, 1583.453125, 39.715633, 0.015375, -0.471415, 1486.033691,
+ 39.162876, 0.029306, -0.735111, 1751.701050, 28.083200, 0.043450, -0.859759, 1392.475220,
+ 24.599945, 0.079075, -1.220033, 1629.972656, 18.507019, 0.090130, -1.091255, 940.347351,
+ 17.961655, 0.098008, -0.945965, 425.901093, 24.478010, 0.138246, -1.084105, 416.823944,
+ 20.003433, 0.174489, -1.133148, 302.730042, 18.550846, 0.207969, -1.138483, 242.853577,
+ 15.923334, 0.249132, -1.168197, 191.649445, 13.940813, 0.291391, -1.187038, 152.910309,
+ 12.263267, 0.332856, -1.192793, 121.905075, 10.822873, 0.377473, -1.202846, 99.145561,
+ 9.618412, 0.422601, -1.208871, 81.343315, 8.591735, 0.465276, -1.204545, 66.742569, 7.692911,
+ 0.504710, -1.190839, 54.787876, 6.915612, 0.544909, -1.178827, 45.507313, 6.242786, 0.582125,
+ -1.160590, 37.819912, 5.651690, 0.620694, -1.145481, 31.926588, 5.123660, 0.659127, -1.130178,
+ 27.147310, 4.669475, 0.684358, -1.093728, 22.650702, 4.258717, 0.719453, -1.074591, 19.454103,
+ 3.901225, 0.751695, -1.051678, 16.735672, 3.576870, 0.775082, -1.017716, 14.281039, 3.287471,
+ 0.796233, -0.982759, 12.261332, 3.023708, 0.827404, -0.961227, 10.767912, 2.787740, 0.848149,
+ -0.928433, 9.371350, 2.570737, 0.864891, -0.892838, 8.142364, 2.379204, 0.880979, -0.858193,
+ 7.118954, 2.204470, 0.910434, -0.837281, 6.389041, 2.041554, 0.925396, -0.803638, 5.643217,
+ 1.893353, 0.942463, -0.772925, 5.031223, 1.757331, 0.955217, -0.739720, 4.486978, 1.633572,
+ 0.968570, -0.708048, 4.014621, 1.520414, 0.981672, -0.677109, 3.617768, 1.412506, 0.992829,
+ -0.645712, 3.258773, 1.317079, 1.021270, -0.625746, 3.006640, 1.222611, 1.031247, -0.594628,
+ 2.733073, 1.137911, 1.043581, -0.565540, 2.498495, 1.058439, 1.055930, -0.536962, 2.289843,
+ 0.984428, 1.066727, -0.508076, 2.108603, 0.912794, 1.081225, -0.481297, 1.951454, 0.845536,
+ 1.088198, -0.451563, 1.801891, 0.782718, 1.123316, -0.433247, 1.704316, 0.721664, 1.133206,
+ -0.404812, 1.586153, 0.662761, 1.152889, -0.379901, 1.490958, 0.606866, 1.188158, -0.359421,
+ 1.415730, 0.550666, 1.217064, -0.336049, 1.344172, 0.496748, 1.257727, -0.314816, 1.283196,
+ 0.443538, 1.286647, -0.289530, 1.225903, 0.394018, 1.308729, -0.262053, 1.173928, 0.346255,
+ 1.351453, -0.237704, 1.139992, 0.300393, 1.380284, -0.209733, 1.105997, 0.256661, 1.414621,
+ -0.181613, 1.082109, 0.215429, 1.453045, -0.152797, 1.063853, 0.177098, 1.481066, -0.121803,
+ 1.043185, 0.137203, 1.514113, -0.090250, 1.027072, 0.096998, 1.547317, -0.057603, 1.012551,
+ 0.055328, 1.577983, -0.023799, 0.999267, 0.013094, 0.000108, -0.124970, 1249.704346,
+ 1249.703491, 0.000140, -0.119585, 1195.855469, 1195.854370, 0.003995, -0.927433, 9274.246094,
+ 232.443573, 0.012013, -1.131580, 11315.999023, 98.211105, 0.023892, -1.216018, 12162.739258,
+ 67.214500, 0.047506, -1.517865, 15186.294922, 42.410069, 0.082523, -1.812564, 18145.718750,
+ 24.421545, 0.112452, -1.805072, 11112.966797, 18.450365, 0.164460, -2.016784, 8086.032715,
+ 14.043465, 0.195870, -1.898199, 4245.658203, 13.178202, 0.197797, -1.556158, 1315.561768,
+ 30.760096, 0.219540, -1.433455, 802.380371, 25.037956, 0.268696, -1.483235, 579.715515,
+ 20.975695, 0.265968, -1.261051, 386.583649, 12.017023, 0.325369, -1.343349, 316.795959,
+ 12.612406, 0.387968, -1.411606, 232.491623, 13.296940, 0.435543, -1.411236, 181.515228,
+ 11.646996, 0.482729, -1.405722, 143.425354, 10.265131, 0.531742, -1.402782, 114.920082,
+ 9.114828, 0.559383, -1.346165, 88.589005, 8.089214, 0.607851, -1.342407, 73.056610, 7.249064,
+ 0.656928, -1.338238, 60.826897, 6.531094, 0.681212, -1.285692, 48.727219, 5.868711, 0.729238,
+ -1.279951, 41.256016, 5.324553, 0.751172, -1.230045, 33.728260, 4.816513, 0.773107, -1.184288,
+ 27.913816, 4.377203, 0.815726, -1.171653, 24.065962, 3.999965, 0.837886, -1.130636, 20.254860,
+ 3.658493, 0.857674, -1.089071, 17.138168, 3.347930, 0.876120, -1.048303, 14.572968, 3.072666,
+ 0.893935, -1.009040, 12.496377, 2.825165, 0.927998, -0.989064, 11.040731, 2.605520, 0.928445,
+ -0.935017, 9.365102, 2.401481, 0.945279, -0.899993, 8.177711, 2.222282, 0.959378, -0.863854,
+ 7.155303, 2.059342, 0.971761, -0.827684, 6.284632, 1.909314, 0.987812, -0.795878, 5.583837,
+ 1.771094, 1.001958, -0.763540, 4.962345, 1.645968, 1.014357, -0.730897, 4.435898, 1.527438,
+ 1.025946, -0.698675, 3.973241, 1.421337, 1.036435, -0.666662, 3.568025, 1.323677, 1.046807,
+ -0.635466, 3.218647, 1.232678, 1.052974, -0.602660, 2.902273, 1.147675, 1.086089, -0.585364,
+ 2.694939, 1.068352, 1.094660, -0.554784, 2.454491, 0.993445, 1.117131, -0.531500, 2.270746,
+ 0.923758, 1.114009, -0.496581, 2.063934, 0.858381, 1.137328, -0.473914, 1.917990, 0.794980,
+ 1.158671, -0.450127, 1.786523, 0.735697, 1.177878, -0.425306, 1.662454, 0.677498, 1.207510,
+ -0.403797, 1.559058, 0.621762, 1.244496, -0.383812, 1.466801, 0.566190, 1.240412, -0.351080,
+ 1.366853, 0.514288, 1.321257, -0.341200, 1.309808, 0.464621, 1.336512, -0.312710, 1.241822,
+ 0.413228, 1.365047, -0.286935, 1.186612, 0.366092, 1.418984, -0.265184, 1.152120, 0.321528,
+ 1.388864, -0.227750, 1.089937, 0.271827, 1.464383, -0.207168, 1.077271, 0.232838, 1.473125,
+ -0.175770, 1.041835, 0.193289, 1.542908, -0.150424, 1.036794, 0.156153, 1.563005, -0.118748,
+ 1.013029, 0.114866, 1.637048, -0.089604, 1.013493, 0.076804, 1.670777, -0.056398, 0.999208,
+ 0.032691,
+};
+static float ltc_mag_ggx[64 * 64] = {
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 0.999995, 0.999990, 0.999971, 0.999937, 0.999853, 0.999670,
+ 0.999138, 0.996746, 0.979578, 0.979309, 0.978836, 0.977972, 0.976223, 0.972205, 0.962466,
+ 0.953919, 0.949829, 0.942492, 0.929870, 0.921319, 0.911112, 0.896015, 0.885105, 0.869971,
+ 0.855017, 0.838328, 0.821241, 0.802352, 0.783873, 0.763309, 0.743058, 0.721929, 0.699755,
+ 0.677721, 0.655456, 0.632681, 0.609629, 0.586831, 0.564287, 0.541772, 0.519428, 0.497353,
+ 0.475624, 0.454606, 0.434099, 0.414085, 0.394605, 0.375698, 0.357386, 0.339871, 0.323085,
+ 0.306905, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 0.999999, 0.999999, 0.999998, 0.999995, 0.999990, 0.999980, 0.999959, 0.999923, 0.999842,
+ 0.999660, 0.999119, 0.996613, 0.981824, 0.979298, 0.978826, 0.977957, 0.976184, 0.972091,
+ 0.962188, 0.953875, 0.949746, 0.942335, 0.930166, 0.921211, 0.910927, 0.896979, 0.884940,
+ 0.869864, 0.854835, 0.838200, 0.821049, 0.802552, 0.783659, 0.763512, 0.742927, 0.721715,
+ 0.699938, 0.677775, 0.655246, 0.632555, 0.609805, 0.586996, 0.564225, 0.541606, 0.519346,
+ 0.497419, 0.475863, 0.454738, 0.434099, 0.414003, 0.394547, 0.375747, 0.357564, 0.340012,
+ 0.323099, 0.306861, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 0.999999, 0.999998, 0.999995, 0.999991, 0.999979, 0.999959, 0.999917,
+ 0.999839, 0.999648, 0.999074, 0.996168, 0.983770, 0.979279, 0.978800, 0.977905, 0.976058,
+ 0.971727, 0.962120, 0.953901, 0.949485, 0.941859, 0.930911, 0.920853, 0.910394, 0.897600,
+ 0.884427, 0.870101, 0.854522, 0.838325, 0.820754, 0.802707, 0.783223, 0.763605, 0.742872,
+ 0.721565, 0.699935, 0.677726, 0.655242, 0.632580, 0.609766, 0.586946, 0.564275, 0.541759,
+ 0.519467, 0.497478, 0.475886, 0.454794, 0.434233, 0.414207, 0.394751, 0.375892, 0.357683,
+ 0.340146, 0.323287, 0.307095, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 0.999999, 0.999999, 0.999998, 0.999996, 0.999992, 0.999987, 0.999975, 0.999953,
+ 0.999913, 0.999830, 0.999630, 0.998993, 0.995279, 0.985142, 0.979252, 0.978754, 0.977821,
+ 0.975838, 0.971088, 0.962563, 0.954785, 0.949048, 0.941052, 0.931420, 0.920812, 0.909750,
+ 0.897867, 0.883856, 0.870091, 0.854353, 0.838166, 0.820661, 0.802465, 0.783308, 0.763346,
+ 0.742734, 0.721608, 0.699747, 0.677626, 0.655245, 0.632547, 0.609793, 0.587044, 0.564340,
+ 0.541779, 0.519529, 0.497633, 0.476114, 0.455030, 0.434430, 0.414406, 0.394974, 0.376154,
+ 0.357979, 0.340443, 0.323572, 0.307379, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 0.999998, 0.999998, 0.999996, 0.999991, 0.999984, 0.999970,
+ 0.999946, 0.999905, 0.999815, 0.999599, 0.998856, 0.993704, 0.986135, 0.979212, 0.978690,
+ 0.977691, 0.975504, 0.970133, 0.962951, 0.955649, 0.948405, 0.940418, 0.931660, 0.920881,
+ 0.909376, 0.897785, 0.883844, 0.869756, 0.854326, 0.837732, 0.820617, 0.802053, 0.783195,
+ 0.763119, 0.742610, 0.721344, 0.699709, 0.677624, 0.655114, 0.632523, 0.609812, 0.587052,
+ 0.564417, 0.541966, 0.519751, 0.497824, 0.476309, 0.455271, 0.434735, 0.414736, 0.395317,
+ 0.376524, 0.358364, 0.340852, 0.323988, 0.307786, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 0.999999, 0.999999, 0.999997, 0.999996, 0.999994, 0.999989, 0.999980,
+ 0.999965, 0.999940, 0.999895, 0.999796, 0.999559, 0.998638, 0.992774, 0.986878, 0.980297,
+ 0.978602, 0.977514, 0.975026, 0.969169, 0.963214, 0.956267, 0.947689, 0.940054, 0.931637,
+ 0.920678, 0.908990, 0.897349, 0.883905, 0.869139, 0.854177, 0.837476, 0.820295, 0.801977,
+ 0.782798, 0.762978, 0.742418, 0.721193, 0.699560, 0.677402, 0.655108, 0.632543, 0.609804,
+ 0.587158, 0.564557, 0.542096, 0.519908, 0.498088, 0.476632, 0.455623, 0.435104, 0.415161,
+ 0.395783, 0.377005, 0.358843, 0.341345, 0.324529, 0.308355, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 0.999999, 0.999999, 0.999998, 0.999997, 0.999992, 0.999991, 0.999985,
+ 0.999977, 0.999959, 0.999935, 0.999878, 0.999773, 0.999505, 0.998284, 0.992353, 0.987457,
+ 0.981665, 0.978492, 0.977277, 0.974360, 0.968716, 0.963373, 0.956629, 0.947397, 0.939657,
+ 0.931339, 0.920588, 0.908975, 0.896712, 0.883763, 0.868890, 0.853731, 0.837333, 0.819702,
+ 0.801738, 0.782454, 0.762712, 0.742024, 0.721037, 0.699325, 0.677359, 0.655030, 0.632439,
+ 0.609869, 0.587221, 0.564663, 0.542328, 0.520220, 0.498400, 0.476997, 0.456053, 0.435593,
+ 0.415658, 0.396300, 0.377577, 0.359473, 0.342004, 0.325170, 0.308997, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999998, 0.999996, 0.999993, 0.999988,
+ 0.999981, 0.999971, 0.999951, 0.999921, 0.999863, 0.999748, 0.999433, 0.997681, 0.992120,
+ 0.987920, 0.982864, 0.978353, 0.976961, 0.973451, 0.968396, 0.963400, 0.956680, 0.947529,
+ 0.939151, 0.930747, 0.920511, 0.908867, 0.896142, 0.883335, 0.868764, 0.853025, 0.837015,
+ 0.819452, 0.801249, 0.782176, 0.762345, 0.741843, 0.720721, 0.699135, 0.677194, 0.654889,
+ 0.632487, 0.609902, 0.587328, 0.564891, 0.542567, 0.520501, 0.498793, 0.477442, 0.456528,
+ 0.436131, 0.416273, 0.396980, 0.378276, 0.360176, 0.342738, 0.325950, 0.309803, 1.000000,
+ 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999999, 0.999997, 0.999995, 0.999991,
+ 0.999985, 0.999978, 0.999963, 0.999942, 0.999907, 0.999844, 0.999715, 0.999332, 0.996612,
+ 0.991974, 0.988297, 0.983843, 0.978349, 0.976540, 0.972351, 0.968109, 0.963280, 0.956464,
+ 0.947779, 0.938754, 0.929952, 0.920253, 0.908530, 0.895785, 0.882679, 0.868456, 0.852669,
+ 0.836406, 0.819138, 0.800708, 0.781803, 0.761855, 0.741534, 0.720405, 0.698959, 0.676964,
+ 0.654827, 0.632411, 0.609922, 0.587477, 0.565051, 0.542829, 0.520889, 0.499225, 0.477951,
+ 0.457148, 0.436792, 0.416963, 0.397723, 0.379068, 0.361025, 0.343608, 0.326842, 0.310718,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999995, 0.999994,
+ 0.999990, 0.999983, 0.999971, 0.999954, 0.999932, 0.999892, 0.999820, 0.999675, 0.999190,
+ 0.995492, 0.991911, 0.988610, 0.984662, 0.979221, 0.975975, 0.971671, 0.967788, 0.963002,
+ 0.955938, 0.947965, 0.938692, 0.929309, 0.919781, 0.908268, 0.895518, 0.882022, 0.867884,
+ 0.852346, 0.835746, 0.818607, 0.800261, 0.781335, 0.761539, 0.741063, 0.720116, 0.698617,
+ 0.676815, 0.654700, 0.632389, 0.610037, 0.587591, 0.565328, 0.543205, 0.521293, 0.499745,
+ 0.478562, 0.457776, 0.437515, 0.417776, 0.398586, 0.379963, 0.361984, 0.344616, 0.327857,
+ 0.311751, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999997, 0.999996,
+ 0.999992, 0.999986, 0.999977, 0.999965, 0.999947, 0.999916, 0.999873, 0.999794, 0.999628,
+ 0.998966, 0.994914, 0.991849, 0.988873, 0.985288, 0.980170, 0.975207, 0.971156, 0.967476,
+ 0.962538, 0.955601, 0.947978, 0.938542, 0.928618, 0.919056, 0.907890, 0.895098, 0.881352,
+ 0.867263, 0.851806, 0.835168, 0.818003, 0.799785, 0.780633, 0.761080, 0.740618, 0.719795,
+ 0.698332, 0.676629, 0.654544, 0.632411, 0.610042, 0.587805, 0.565593, 0.543549, 0.521793,
+ 0.500309, 0.479195, 0.458546, 0.438353, 0.418669, 0.399557, 0.381012, 0.363049, 0.345710,
+ 0.329006, 0.312948, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999997,
+ 0.999993, 0.999990, 0.999984, 0.999972, 0.999960, 0.999939, 0.999906, 0.999853, 0.999765,
+ 0.999567, 0.998603, 0.994519, 0.991794, 0.989089, 0.985781, 0.980956, 0.974161, 0.970688,
+ 0.967064, 0.961890, 0.955292, 0.947848, 0.938359, 0.928226, 0.918214, 0.907361, 0.894702,
+ 0.880834, 0.866500, 0.851209, 0.834627, 0.817211, 0.799250, 0.780131, 0.760512, 0.740218,
+ 0.719264, 0.698063, 0.676325, 0.654450, 0.632316, 0.610170, 0.587988, 0.565891, 0.544013,
+ 0.522305, 0.500958, 0.479971, 0.459376, 0.439271, 0.419699, 0.400620, 0.382126, 0.364246,
+ 0.346967, 0.330273, 0.314236, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998,
+ 0.999996, 0.999994, 0.999988, 0.999979, 0.999967, 0.999952, 0.999924, 0.999888, 0.999833,
+ 0.999733, 0.999490, 0.997946, 0.994192, 0.991812, 0.989274, 0.986224, 0.981547, 0.974000,
+ 0.970269, 0.966545, 0.961031, 0.954921, 0.947416, 0.938226, 0.928003, 0.917390, 0.906553,
+ 0.894191, 0.880329, 0.865540, 0.850476, 0.834058, 0.816467, 0.798509, 0.779561, 0.759828,
+ 0.739738, 0.718878, 0.697718, 0.676138, 0.654342, 0.632317, 0.610292, 0.588207, 0.566289,
+ 0.544443, 0.522927, 0.501674, 0.480765, 0.460314, 0.440304, 0.420782, 0.401824, 0.383410,
+ 0.365538, 0.348312, 0.331692, 0.315688, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999,
+ 0.999998, 0.999996, 0.999993, 0.999985, 0.999976, 0.999961, 0.999943, 0.999913, 0.999872,
+ 0.999807, 0.999691, 0.999390, 0.996859, 0.994003, 0.991808, 0.989423, 0.986523, 0.981783,
+ 0.974511, 0.969791, 0.965933, 0.960377, 0.954434, 0.946803, 0.938026, 0.927620, 0.916545,
+ 0.905639, 0.893489, 0.879820, 0.864852, 0.849513, 0.833311, 0.815878, 0.797621, 0.778938,
+ 0.759253, 0.739142, 0.718479, 0.697274, 0.675902, 0.654135, 0.632357, 0.610364, 0.588497,
+ 0.566631, 0.545012, 0.523579, 0.502429, 0.481680, 0.461304, 0.441425, 0.422039, 0.403135,
+ 0.384779, 0.366976, 0.349796, 0.333231, 0.317277, 1.000000, 1.000000, 1.000000, 1.000000,
+ 0.999999, 0.999998, 0.999996, 0.999991, 0.999983, 0.999974, 0.999956, 0.999932, 0.999901,
+ 0.999852, 0.999780, 0.999646, 0.999248, 0.996193, 0.993784, 0.991782, 0.989539, 0.986694,
+ 0.981765, 0.975135, 0.969309, 0.965128, 0.959788, 0.953831, 0.946255, 0.937664, 0.927351,
+ 0.916044, 0.904715, 0.892528, 0.879111, 0.864256, 0.848452, 0.832434, 0.815129, 0.796806,
+ 0.778118, 0.758668, 0.738466, 0.718024, 0.696958, 0.675642, 0.654067, 0.632325, 0.610546,
+ 0.588786, 0.567123, 0.545617, 0.524312, 0.503348, 0.482637, 0.462418, 0.442657, 0.423338,
+ 0.404564, 0.386277, 0.368545, 0.351448, 0.334906, 0.318961, 1.000000, 1.000000, 1.000000,
+ 0.999999, 0.999999, 0.999998, 0.999994, 0.999989, 0.999979, 0.999968, 0.999949, 0.999921,
+ 0.999886, 0.999833, 0.999747, 0.999596, 0.999029, 0.995749, 0.993677, 0.991724, 0.989620,
+ 0.986723, 0.981515, 0.975767, 0.969056, 0.964124, 0.959142, 0.953036, 0.945650, 0.937022,
+ 0.926971, 0.915515, 0.903584, 0.891603, 0.878212, 0.863472, 0.847652, 0.831398, 0.814299,
+ 0.796105, 0.777231, 0.757977, 0.737895, 0.717415, 0.696595, 0.675317, 0.653980, 0.632343,
+ 0.610735, 0.589076, 0.567620, 0.546251, 0.525165, 0.504255, 0.483759, 0.463666, 0.443987,
+ 0.424783, 0.406042, 0.387891, 0.370293, 0.353221, 0.336715, 0.320806, 1.000000, 1.000000,
+ 1.000000, 0.999999, 0.999998, 0.999998, 0.999993, 0.999987, 0.999977, 0.999964, 0.999943,
+ 0.999911, 0.999867, 0.999807, 0.999714, 0.999531, 0.998645, 0.995399, 0.993512, 0.991717,
+ 0.989661, 0.986652, 0.981559, 0.976183, 0.969411, 0.963317, 0.958457, 0.952091, 0.944951,
+ 0.936307, 0.926454, 0.915043, 0.902668, 0.890462, 0.877245, 0.862672, 0.846823, 0.830201,
+ 0.813293, 0.795306, 0.776393, 0.757199, 0.737324, 0.716808, 0.696187, 0.675094, 0.653814,
+ 0.632453, 0.610885, 0.589483, 0.568099, 0.546975, 0.525953, 0.505268, 0.484936, 0.464988,
+ 0.445458, 0.426314, 0.407750, 0.389670, 0.372098, 0.355105, 0.338682, 0.322825, 1.000000,
+ 1.000000, 1.000000, 1.000000, 0.999999, 0.999996, 0.999992, 0.999983, 0.999976, 0.999959,
+ 0.999933, 0.999898, 0.999849, 0.999780, 0.999676, 0.999454, 0.997884, 0.995166, 0.993394,
+ 0.991723, 0.989654, 0.986389, 0.981632, 0.976607, 0.969701, 0.962555, 0.957605, 0.951232,
+ 0.944099, 0.935556, 0.925699, 0.914492, 0.902027, 0.889116, 0.876093, 0.861649, 0.845956,
+ 0.829238, 0.812220, 0.794420, 0.775657, 0.756265, 0.736673, 0.716372, 0.695669, 0.674886,
+ 0.653728, 0.632568, 0.611217, 0.589929, 0.568783, 0.547752, 0.526931, 0.506425, 0.486238,
+ 0.466425, 0.446945, 0.428026, 0.409536, 0.391551, 0.374087, 0.357155, 0.340787, 0.324974,
+ 1.000000, 1.000000, 1.000000, 1.000000, 0.999998, 0.999996, 0.999990, 0.999984, 0.999970,
+ 0.999952, 0.999925, 0.999886, 0.999831, 0.999757, 0.999633, 0.999356, 0.997017, 0.994868,
+ 0.993337, 0.991710, 0.989580, 0.985848, 0.981640, 0.976711, 0.969755, 0.962166, 0.956609,
+ 0.950365, 0.943026, 0.934693, 0.924880, 0.913729, 0.901350, 0.887966, 0.874726, 0.860474,
+ 0.844905, 0.828269, 0.810905, 0.793364, 0.774812, 0.755478, 0.735886, 0.715847, 0.695231,
+ 0.674537, 0.653667, 0.632527, 0.611475, 0.590363, 0.569462, 0.548571, 0.527976, 0.507634,
+ 0.487632, 0.467901, 0.448680, 0.429833, 0.411467, 0.393568, 0.376197, 0.359374, 0.343034,
+ 0.327273, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999993, 0.999989, 0.999980,
+ 0.999965, 0.999945, 0.999913, 0.999869, 0.999810, 0.999723, 0.999583, 0.999213, 0.996540,
+ 0.994740, 0.993244, 0.991671, 0.989411, 0.985533, 0.981616, 0.976847, 0.969968, 0.962315,
+ 0.955468, 0.949420, 0.942016, 0.933617, 0.923949, 0.912899, 0.900495, 0.887022, 0.873283,
+ 0.859153, 0.843830, 0.827325, 0.809888, 0.792172, 0.773832, 0.754686, 0.735035, 0.715297,
+ 0.694955, 0.674242, 0.653660, 0.632752, 0.611804, 0.590993, 0.570154, 0.549539, 0.529087,
+ 0.508974, 0.489030, 0.469599, 0.450466, 0.431761, 0.413508, 0.395761, 0.378480, 0.361679,
+ 0.345465, 0.329752, 1.000000, 1.000000, 1.000000, 1.000000, 0.999997, 0.999994, 0.999987,
+ 0.999978, 0.999961, 0.999936, 0.999903, 0.999855, 0.999786, 0.999689, 0.999527, 0.998988,
+ 0.996137, 0.994527, 0.993108, 0.991599, 0.989084, 0.985308, 0.981527, 0.976677, 0.970079,
+ 0.962535, 0.954490, 0.948271, 0.940942, 0.932422, 0.922836, 0.911896, 0.899632, 0.886118,
+ 0.871864, 0.857719, 0.842536, 0.826163, 0.808849, 0.790860, 0.772802, 0.753860, 0.734335,
+ 0.714582, 0.694543, 0.674071, 0.653544, 0.632922, 0.612153, 0.591573, 0.570951, 0.550520,
+ 0.530352, 0.510311, 0.490707, 0.471359, 0.452396, 0.433837, 0.415736, 0.398052, 0.380874,
+ 0.364232, 0.348023, 0.332368, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999994,
+ 0.999988, 0.999976, 0.999957, 0.999928, 0.999891, 0.999837, 0.999759, 0.999650, 0.999463,
+ 0.998551, 0.995879, 0.994366, 0.992964, 0.991479, 0.988521, 0.985101, 0.981482, 0.976168,
+ 0.970242, 0.962585, 0.953950, 0.946973, 0.939686, 0.931248, 0.921614, 0.910765, 0.898617,
+ 0.885183, 0.870772, 0.856138, 0.841120, 0.824962, 0.807732, 0.789813, 0.771638, 0.753008,
+ 0.733686, 0.713927, 0.694082, 0.673967, 0.653549, 0.633135, 0.612702, 0.592200, 0.571904,
+ 0.551679, 0.531678, 0.511898, 0.492437, 0.473239, 0.454451, 0.436067, 0.418054, 0.400542,
+ 0.383486, 0.366848, 0.350781, 0.335182, 1.000000, 1.000000, 1.000000, 0.999999, 0.999997,
+ 0.999993, 0.999985, 0.999972, 0.999951, 0.999919, 0.999877, 0.999817, 0.999733, 0.999608,
+ 0.999380, 0.997685, 0.995603, 0.994264, 0.992911, 0.991287, 0.987923, 0.984871, 0.981239,
+ 0.975933, 0.970149, 0.962511, 0.953824, 0.945699, 0.938285, 0.929907, 0.920343, 0.909537,
+ 0.897435, 0.884056, 0.869626, 0.854490, 0.839459, 0.823511, 0.806511, 0.788752, 0.770440,
+ 0.751995, 0.732962, 0.713424, 0.693525, 0.673798, 0.653622, 0.633301, 0.613224, 0.592938,
+ 0.572833, 0.552904, 0.533030, 0.513556, 0.494215, 0.475279, 0.456673, 0.438411, 0.420583,
+ 0.403178, 0.386178, 0.369728, 0.353688, 0.338147, 1.000000, 1.000000, 1.000000, 0.999999,
+ 0.999997, 0.999991, 0.999984, 0.999967, 0.999944, 0.999912, 0.999863, 0.999796, 0.999703,
+ 0.999563, 0.999279, 0.997104, 0.995394, 0.994111, 0.992825, 0.990979, 0.987529, 0.984661,
+ 0.980774, 0.975758, 0.969866, 0.962465, 0.953678, 0.944489, 0.936886, 0.928356, 0.918820,
+ 0.908073, 0.896092, 0.882833, 0.868463, 0.853212, 0.837744, 0.822048, 0.805333, 0.787643,
+ 0.769414, 0.750830, 0.732178, 0.712972, 0.693227, 0.673569, 0.653744, 0.633739, 0.613735,
+ 0.593822, 0.573916, 0.554158, 0.534652, 0.515248, 0.496233, 0.477436, 0.459009, 0.440929,
+ 0.423259, 0.405951, 0.389136, 0.372690, 0.356789, 0.341329, 1.000000, 1.000000, 1.000000,
+ 0.999999, 0.999996, 0.999991, 0.999981, 0.999966, 0.999939, 0.999903, 0.999847, 0.999771,
+ 0.999666, 0.999510, 0.999131, 0.996690, 0.995147, 0.993882, 0.992696, 0.990474, 0.987227,
+ 0.984334, 0.980153, 0.975438, 0.969406, 0.962238, 0.953598, 0.943868, 0.935356, 0.926721,
+ 0.917122, 0.906430, 0.894550, 0.881354, 0.867131, 0.851954, 0.835972, 0.820331, 0.803911,
+ 0.786452, 0.768420, 0.749821, 0.731298, 0.712393, 0.692979, 0.673418, 0.653859, 0.634232,
+ 0.614327, 0.594732, 0.575131, 0.555584, 0.536346, 0.517175, 0.498323, 0.479744, 0.461485,
+ 0.443645, 0.426061, 0.408969, 0.392155, 0.375921, 0.360060, 0.344677, 1.000000, 1.000000,
+ 1.000000, 0.999999, 0.999997, 0.999991, 0.999979, 0.999960, 0.999931, 0.999891, 0.999832,
+ 0.999748, 0.999629, 0.999449, 0.998880, 0.996305, 0.995024, 0.993812, 0.992508, 0.989721,
+ 0.986936, 0.983936, 0.979629, 0.974979, 0.968928, 0.961970, 0.953291, 0.943458, 0.933644,
+ 0.925007, 0.915388, 0.904755, 0.892932, 0.879831, 0.865794, 0.850672, 0.834591, 0.818398,
+ 0.802304, 0.785151, 0.767450, 0.748987, 0.730325, 0.711758, 0.692761, 0.673417, 0.653908,
+ 0.634686, 0.615168, 0.595707, 0.576393, 0.557198, 0.538018, 0.519253, 0.500555, 0.482220,
+ 0.464197, 0.446414, 0.429106, 0.412035, 0.395508, 0.379284, 0.363538, 0.348220, 1.000000,
+ 1.000000, 1.000000, 0.999999, 0.999995, 0.999989, 0.999977, 0.999955, 0.999924, 0.999879,
+ 0.999813, 0.999722, 0.999590, 0.999381, 0.998335, 0.996088, 0.994814, 0.993709, 0.992220,
+ 0.989209, 0.986575, 0.983383, 0.979084, 0.974272, 0.968359, 0.961275, 0.953025, 0.943098,
+ 0.932434, 0.923101, 0.913477, 0.902861, 0.891059, 0.878072, 0.864118, 0.849188, 0.833281,
+ 0.816808, 0.800596, 0.783745, 0.766331, 0.748123, 0.729686, 0.711078, 0.692527, 0.673491,
+ 0.654296, 0.635113, 0.616048, 0.596847, 0.577720, 0.558879, 0.540028, 0.521371, 0.502996,
+ 0.484858, 0.466997, 0.449477, 0.432217, 0.415426, 0.398924, 0.382890, 0.367206, 0.351955,
+ 1.000000, 1.000000, 1.000000, 0.999998, 0.999996, 0.999988, 0.999974, 0.999953, 0.999918,
+ 0.999865, 0.999791, 0.999690, 0.999542, 0.999293, 0.997535, 0.995790, 0.994609, 0.993557,
+ 0.991766, 0.988767, 0.986255, 0.982544, 0.978541, 0.973528, 0.967700, 0.960596, 0.952299,
+ 0.942684, 0.931653, 0.921211, 0.911489, 0.900818, 0.889018, 0.876245, 0.862406, 0.847517,
+ 0.831852, 0.815367, 0.798719, 0.782224, 0.765167, 0.747304, 0.729133, 0.710485, 0.692196,
+ 0.673589, 0.654770, 0.635717, 0.616986, 0.598119, 0.579298, 0.560560, 0.542163, 0.523669,
+ 0.505564, 0.487642, 0.469991, 0.452658, 0.435620, 0.418937, 0.402612, 0.386633, 0.371091,
+ 0.355949, 1.000000, 1.000000, 0.999999, 0.999998, 0.999995, 0.999986, 0.999973, 0.999948,
+ 0.999909, 0.999852, 0.999769, 0.999656, 0.999490, 0.999186, 0.997059, 0.995624, 0.994510,
+ 0.993327, 0.991020, 0.988379, 0.985771, 0.981971, 0.978051, 0.972892, 0.967020, 0.959965,
+ 0.951625, 0.941902, 0.930951, 0.919370, 0.909285, 0.898562, 0.886809, 0.874251, 0.860597,
+ 0.845808, 0.830365, 0.813972, 0.797260, 0.780597, 0.763854, 0.746401, 0.728519, 0.710203,
+ 0.691882, 0.673687, 0.655275, 0.636621, 0.617909, 0.599473, 0.581032, 0.562560, 0.544295,
+ 0.526228, 0.508293, 0.490652, 0.473242, 0.456004, 0.439212, 0.422663, 0.406476, 0.390647,
+ 0.375204, 0.360129, 1.000000, 1.000000, 1.000000, 0.999999, 0.999994, 0.999984, 0.999969,
+ 0.999940, 0.999898, 0.999837, 0.999746, 0.999617, 0.999438, 0.999016, 0.996703, 0.995302,
+ 0.994356, 0.992993, 0.990390, 0.988072, 0.985152, 0.981447, 0.977273, 0.972234, 0.966113,
+ 0.959033, 0.950869, 0.941217, 0.930175, 0.918279, 0.906941, 0.896201, 0.884509, 0.871920,
+ 0.858420, 0.843906, 0.828730, 0.812524, 0.795978, 0.778979, 0.762450, 0.745459, 0.727966,
+ 0.710046, 0.691808, 0.673739, 0.655756, 0.637574, 0.619153, 0.600887, 0.582796, 0.564748,
+ 0.546636, 0.528904, 0.511252, 0.493791, 0.476563, 0.459695, 0.442942, 0.426632, 0.410558,
+ 0.394895, 0.379517, 0.364560, 1.000000, 1.000000, 1.000000, 0.999998, 0.999994, 0.999984,
+ 0.999966, 0.999934, 0.999887, 0.999819, 0.999720, 0.999578, 0.999367, 0.998696, 0.996353,
+ 0.995201, 0.994115, 0.992665, 0.989948, 0.987633, 0.984331, 0.980827, 0.976390, 0.971327,
+ 0.965201, 0.957977, 0.949712, 0.940128, 0.929187, 0.917237, 0.904645, 0.893711, 0.882112,
+ 0.869516, 0.856236, 0.841929, 0.826924, 0.810991, 0.794686, 0.777761, 0.760980, 0.744384,
+ 0.727314, 0.709877, 0.691988, 0.674098, 0.656243, 0.638603, 0.620606, 0.602574, 0.584694,
+ 0.567018, 0.549311, 0.531673, 0.514403, 0.497148, 0.480177, 0.463439, 0.446998, 0.430743,
+ 0.414943, 0.399304, 0.384121, 0.369251, 1.000000, 1.000000, 1.000000, 0.999997, 0.999992,
+ 0.999981, 0.999962, 0.999927, 0.999874, 0.999798, 0.999691, 0.999533, 0.999291, 0.997909,
+ 0.996117, 0.995029, 0.993880, 0.992142, 0.989576, 0.987185, 0.983587, 0.980055, 0.975487,
+ 0.970172, 0.963998, 0.956738, 0.948637, 0.939083, 0.928169, 0.916144, 0.903147, 0.890916,
+ 0.879389, 0.866895, 0.853826, 0.839729, 0.824957, 0.809472, 0.793341, 0.776743, 0.759808,
+ 0.743277, 0.726643, 0.709685, 0.692249, 0.674639, 0.657008, 0.639576, 0.622114, 0.604471,
+ 0.586851, 0.569340, 0.552135, 0.534806, 0.517599, 0.500765, 0.484035, 0.467440, 0.451212,
+ 0.435240, 0.419399, 0.404083, 0.388944, 0.374182, 1.000000, 1.000000, 1.000000, 0.999998,
+ 0.999993, 0.999979, 0.999958, 0.999919, 0.999861, 0.999774, 0.999656, 0.999482, 0.999195,
+ 0.997307, 0.995837, 0.994722, 0.993707, 0.991391, 0.989169, 0.986461, 0.982904, 0.979062,
+ 0.974536, 0.969035, 0.962653, 0.955486, 0.947243, 0.937747, 0.926861, 0.914936, 0.901835,
+ 0.888472, 0.876571, 0.864223, 0.851252, 0.837374, 0.822985, 0.807788, 0.791927, 0.775702,
+ 0.758928, 0.742347, 0.725914, 0.709495, 0.692569, 0.675363, 0.658085, 0.640639, 0.623698,
+ 0.606505, 0.589267, 0.572008, 0.554939, 0.538132, 0.521211, 0.504487, 0.488048, 0.471807,
+ 0.455651, 0.439858, 0.424332, 0.408983, 0.394071, 0.379402, 1.000000, 1.000000, 1.000000,
+ 0.999997, 0.999992, 0.999978, 0.999954, 0.999913, 0.999844, 0.999753, 0.999618, 0.999424,
+ 0.999067, 0.996875, 0.995659, 0.994603, 0.993420, 0.990874, 0.988713, 0.985585, 0.982193,
+ 0.978145, 0.973416, 0.967801, 0.961483, 0.954069, 0.945704, 0.936138, 0.925374, 0.913395,
+ 0.900339, 0.886675, 0.873512, 0.861326, 0.848513, 0.834956, 0.820820, 0.805943, 0.790574,
+ 0.774677, 0.758279, 0.741807, 0.725271, 0.709231, 0.692874, 0.676189, 0.659352, 0.642296,
+ 0.625250, 0.608700, 0.591823, 0.575012, 0.558143, 0.541491, 0.525075, 0.508558, 0.492277,
+ 0.476270, 0.460459, 0.444740, 0.429400, 0.414309, 0.399421, 0.384907, 1.000000, 1.000000,
+ 1.000000, 0.999997, 0.999990, 0.999977, 0.999947, 0.999902, 0.999832, 0.999730, 0.999577,
+ 0.999359, 0.998845, 0.996554, 0.995328, 0.994442, 0.992919, 0.990393, 0.988170, 0.984855,
+ 0.981312, 0.977149, 0.972137, 0.966207, 0.959967, 0.952454, 0.943873, 0.934434, 0.923813,
+ 0.911942, 0.898928, 0.885120, 0.871043, 0.858248, 0.845666, 0.832346, 0.818482, 0.804029,
+ 0.788982, 0.773571, 0.757700, 0.741484, 0.725186, 0.708915, 0.693244, 0.677028, 0.660656,
+ 0.644079, 0.627377, 0.610804, 0.594542, 0.578112, 0.561650, 0.545163, 0.528962, 0.512926,
+ 0.496893, 0.481007, 0.465397, 0.450042, 0.434740, 0.419831, 0.405156, 0.390692, 1.000000,
+ 1.000000, 0.999999, 0.999997, 0.999989, 0.999973, 0.999942, 0.999891, 0.999813, 0.999698,
+ 0.999532, 0.999285, 0.998286, 0.996295, 0.995215, 0.994182, 0.992032, 0.989855, 0.987415,
+ 0.984047, 0.980050, 0.976017, 0.970845, 0.964767, 0.958269, 0.950600, 0.942033, 0.932501,
+ 0.921807, 0.910017, 0.897149, 0.883414, 0.869182, 0.855055, 0.842687, 0.829548, 0.816162,
+ 0.802072, 0.787436, 0.772533, 0.757043, 0.741263, 0.725330, 0.709262, 0.693497, 0.678038,
+ 0.662128, 0.646068, 0.629824, 0.613437, 0.597334, 0.581401, 0.565372, 0.549288, 0.533182,
+ 0.517405, 0.501765, 0.486143, 0.470675, 0.455465, 0.440532, 0.425630, 0.411113, 0.396887,
+ 1.000000, 1.000000, 0.999999, 0.999996, 0.999989, 0.999970, 0.999934, 0.999879, 0.999793,
+ 0.999665, 0.999481, 0.999192, 0.997506, 0.995926, 0.995009, 0.993736, 0.991298, 0.989326,
+ 0.986371, 0.983199, 0.979032, 0.974596, 0.969364, 0.963198, 0.956385, 0.948509, 0.939993,
+ 0.930421, 0.919590, 0.908140, 0.895349, 0.881699, 0.867456, 0.852784, 0.839500, 0.826629,
+ 0.813602, 0.799983, 0.785873, 0.771340, 0.756480, 0.741190, 0.725687, 0.709997, 0.694192,
+ 0.678975, 0.663673, 0.648135, 0.632442, 0.616477, 0.600565, 0.584772, 0.569202, 0.553595,
+ 0.537881, 0.522193, 0.506784, 0.491554, 0.476349, 0.461278, 0.446419, 0.431913, 0.417443,
+ 0.403271, 1.000000, 1.000000, 0.999999, 0.999995, 0.999986, 0.999966, 0.999927, 0.999867,
+ 0.999772, 0.999629, 0.999423, 0.999075, 0.997024, 0.995773, 0.994651, 0.993353, 0.990822,
+ 0.988569, 0.985596, 0.982182, 0.977871, 0.973140, 0.967584, 0.961408, 0.954294, 0.946398,
+ 0.937603, 0.927937, 0.917305, 0.905833, 0.893138, 0.879770, 0.865720, 0.851023, 0.836801,
+ 0.823784, 0.810909, 0.797886, 0.784177, 0.770243, 0.755925, 0.741144, 0.726214, 0.710971,
+ 0.695563, 0.680212, 0.665304, 0.650297, 0.635168, 0.619796, 0.604217, 0.588692, 0.573254,
+ 0.557998, 0.542839, 0.527470, 0.512162, 0.497115, 0.482296, 0.467477, 0.452812, 0.438310,
+ 0.424184, 0.410163, 1.000000, 1.000000, 0.999999, 0.999996, 0.999984, 0.999962, 0.999920,
+ 0.999852, 0.999745, 0.999586, 0.999354, 0.998894, 0.996686, 0.995485, 0.994493, 0.992573,
+ 0.990323, 0.987772, 0.984692, 0.980887, 0.976446, 0.971625, 0.965717, 0.959421, 0.951975,
+ 0.944086, 0.935066, 0.925403, 0.914814, 0.903208, 0.890958, 0.877817, 0.863828, 0.849289,
+ 0.834872, 0.820889, 0.808183, 0.795660, 0.782556, 0.769066, 0.755386, 0.741229, 0.726726,
+ 0.712170, 0.697209, 0.682170, 0.667203, 0.652689, 0.637938, 0.623262, 0.608190, 0.593002,
+ 0.577817, 0.562737, 0.547836, 0.533036, 0.518052, 0.503135, 0.488422, 0.473986, 0.459552,
+ 0.445282, 0.431149, 0.417407, 1.000000, 1.000000, 0.999999, 0.999994, 0.999983, 0.999957,
+ 0.999914, 0.999835, 0.999718, 0.999538, 0.999275, 0.998454, 0.996341, 0.995246, 0.994222,
+ 0.991844, 0.989829, 0.986688, 0.983562, 0.979638, 0.974932, 0.969827, 0.963621, 0.957146,
+ 0.949365, 0.941398, 0.932245, 0.922556, 0.911949, 0.900627, 0.888440, 0.875544, 0.862005,
+ 0.847810, 0.833372, 0.819134, 0.805508, 0.793339, 0.780916, 0.767837, 0.754858, 0.741307,
+ 0.727496, 0.713386, 0.699131, 0.684542, 0.669878, 0.655261, 0.641035, 0.626685, 0.612377,
+ 0.597625, 0.582805, 0.568030, 0.553204, 0.538684, 0.524269, 0.509662, 0.495119, 0.480735,
+ 0.466634, 0.452593, 0.438748, 0.424915, 1.000000, 1.000000, 0.999998, 0.999994, 0.999982,
+ 0.999956, 0.999901, 0.999818, 0.999683, 0.999487, 0.999185, 0.997584, 0.996004, 0.995050,
+ 0.993715, 0.991212, 0.989057, 0.985879, 0.982243, 0.978206, 0.973119, 0.967919, 0.961343,
+ 0.954603, 0.946712, 0.938378, 0.929266, 0.919443, 0.908911, 0.897725, 0.885589, 0.873254,
+ 0.859889, 0.846123, 0.832094, 0.817898, 0.803866, 0.791061, 0.779235, 0.766885, 0.754292,
+ 0.741565, 0.728331, 0.714861, 0.701179, 0.687166, 0.673012, 0.658716, 0.644442, 0.630472,
+ 0.616519, 0.602514, 0.588172, 0.573689, 0.559281, 0.544768, 0.530543, 0.516485, 0.502303,
+ 0.488100, 0.474095, 0.460245, 0.446598, 0.433169, 1.000000, 1.000000, 0.999997, 0.999993,
+ 0.999980, 0.999947, 0.999891, 0.999794, 0.999647, 0.999425, 0.999062, 0.997049, 0.995778,
+ 0.994652, 0.992778, 0.990482, 0.988004, 0.984893, 0.980881, 0.976605, 0.971199, 0.965610,
+ 0.958925, 0.951746, 0.943791, 0.935200, 0.926018, 0.916028, 0.905724, 0.894528, 0.882914,
+ 0.870740, 0.857802, 0.844552, 0.830857, 0.816921, 0.803102, 0.789625, 0.777480, 0.765891,
+ 0.753908, 0.741795, 0.729390, 0.716440, 0.703411, 0.690068, 0.676438, 0.662586, 0.648697,
+ 0.634732, 0.620997, 0.607451, 0.593765, 0.579748, 0.565661, 0.551594, 0.537396, 0.523433,
+ 0.509708, 0.495972, 0.482082, 0.468427, 0.454890, 0.441623, 1.000000, 1.000000, 0.999999,
+ 0.999991, 0.999977, 0.999940, 0.999875, 0.999769, 0.999605, 0.999352, 0.998882, 0.996665,
+ 0.995459, 0.994380, 0.992014, 0.989912, 0.986796, 0.983537, 0.979326, 0.974792, 0.969140,
+ 0.963160, 0.956222, 0.948807, 0.940518, 0.931755, 0.922452, 0.912319, 0.902227, 0.891142,
+ 0.879838, 0.868047, 0.855745, 0.842718, 0.829827, 0.816398, 0.802786, 0.789396, 0.776581,
+ 0.764901, 0.753710, 0.742102, 0.730448, 0.718337, 0.705768, 0.693172, 0.680153, 0.666882,
+ 0.653401, 0.639837, 0.626152, 0.612676, 0.599435, 0.586109, 0.572473, 0.558715, 0.544964,
+ 0.531112, 0.517416, 0.503992, 0.490653, 0.477162, 0.463832, 0.450645, 1.000000, 1.000000,
+ 0.999999, 0.999992, 0.999973, 0.999933, 0.999861, 0.999741, 0.999554, 0.999267, 0.998411,
+ 0.996303, 0.995191, 0.993945, 0.991406, 0.989019, 0.985720, 0.982057, 0.977501, 0.972605,
+ 0.966697, 0.960340, 0.953031, 0.945347, 0.936866, 0.927917, 0.918562, 0.908598, 0.898486,
+ 0.887794, 0.876545, 0.865379, 0.853428, 0.841167, 0.828649, 0.815967, 0.802957, 0.789865,
+ 0.777077, 0.764695, 0.753544, 0.742694, 0.731571, 0.720304, 0.708490, 0.696351, 0.684134,
+ 0.671470, 0.658541, 0.645376, 0.632209, 0.618776, 0.605511, 0.592527, 0.579546, 0.566310,
+ 0.552860, 0.539492, 0.526005, 0.512564, 0.499340, 0.486360, 0.473357, 0.460306, 1.000000,
+ 1.000000, 0.999998, 0.999991, 0.999970, 0.999926, 0.999842, 0.999710, 0.999498, 0.999164,
+ 0.997464, 0.995870, 0.994917, 0.992911, 0.990682, 0.987816, 0.984410, 0.980551, 0.975693,
+ 0.970263, 0.963946, 0.957248, 0.949765, 0.941571, 0.932941, 0.923873, 0.914332, 0.904560,
+ 0.894394, 0.884127, 0.873294, 0.862503, 0.851335, 0.839566, 0.827776, 0.815708, 0.803370,
+ 0.790821, 0.778386, 0.766121, 0.754193, 0.743420, 0.732975, 0.722326, 0.711376, 0.699992,
+ 0.688180, 0.676354, 0.664004, 0.651449, 0.638600, 0.625776, 0.612660, 0.599603, 0.586719,
+ 0.574078, 0.561273, 0.548129, 0.535155, 0.522015, 0.508851, 0.495837, 0.483190, 0.470624,
+ 1.000000, 1.000000, 0.999998, 0.999988, 0.999965, 0.999916, 0.999823, 0.999669, 0.999425,
+ 0.999025, 0.996874, 0.995670, 0.994415, 0.991991, 0.989766, 0.986646, 0.982812, 0.978356,
+ 0.973317, 0.967612, 0.960820, 0.953603, 0.945969, 0.937323, 0.928661, 0.919507, 0.909833,
+ 0.900245, 0.890390, 0.880252, 0.870000, 0.859518, 0.849163, 0.838101, 0.826960, 0.815688,
+ 0.804126, 0.792234, 0.780356, 0.768474, 0.756678, 0.745159, 0.734601, 0.724624, 0.714339,
+ 0.703751, 0.692766, 0.681267, 0.669799, 0.657871, 0.645577, 0.633102, 0.620560, 0.607737,
+ 0.594890, 0.582143, 0.569779, 0.557360, 0.544651, 0.531942, 0.519228, 0.506467, 0.493710,
+ 0.481143, 1.000000, 1.000000, 0.999998, 0.999988, 0.999961, 0.999902, 0.999798, 0.999622,
+ 0.999341, 0.998801, 0.996397, 0.995225, 0.993927, 0.991338, 0.988500, 0.985327, 0.981195,
+ 0.976383, 0.970726, 0.964471, 0.957386, 0.949813, 0.941694, 0.932681, 0.923974, 0.914755,
+ 0.905026, 0.895649, 0.886178, 0.876277, 0.866629, 0.856890, 0.846934, 0.836887, 0.826373,
+ 0.815885, 0.805169, 0.794133, 0.782812, 0.771547, 0.760175, 0.748896, 0.737687, 0.727152,
+ 0.717601, 0.707670, 0.697425, 0.686788, 0.675664, 0.664513, 0.652962, 0.640965, 0.628851,
+ 0.616551, 0.604168, 0.591559, 0.579009, 0.566648, 0.554597, 0.542382, 0.529999, 0.517655,
+ 0.505254, 0.492894, 1.000000, 1.000000, 0.999997, 0.999986, 0.999956, 0.999889, 0.999766,
+ 0.999562, 0.999240, 0.997952, 0.996094, 0.994979, 0.992773, 0.990536, 0.987214, 0.983322,
+ 0.978938, 0.973714, 0.967681, 0.960981, 0.953144, 0.945475, 0.936909, 0.927734, 0.918826,
+ 0.909590, 0.900085, 0.890867, 0.881801, 0.872565, 0.863236, 0.854239, 0.845060, 0.835686,
+ 0.826251, 0.816284, 0.806586, 0.796419, 0.785914, 0.775210, 0.764461, 0.753599, 0.742805,
+ 0.731872, 0.721370, 0.711898, 0.702337, 0.692383, 0.682137, 0.671365, 0.660479, 0.649314,
+ 0.637685, 0.625899, 0.613898, 0.601865, 0.589582, 0.577285, 0.565013, 0.553106, 0.541280,
+ 0.529367, 0.517320, 0.505411, 1.000000, 1.000000, 0.999997, 0.999983, 0.999948, 0.999869,
+ 0.999732, 0.999499, 0.999111, 0.997167, 0.995720, 0.994349, 0.991727, 0.989197, 0.985883,
+ 0.981483, 0.976618, 0.970597, 0.964122, 0.956994, 0.948639, 0.940500, 0.931606, 0.922385,
+ 0.913291, 0.904205, 0.894938, 0.885890, 0.877334, 0.868754, 0.860053, 0.851683, 0.843447,
+ 0.834889, 0.826304, 0.817441, 0.808285, 0.799141, 0.789570, 0.779600, 0.769510, 0.759155,
+ 0.748882, 0.738346, 0.727629, 0.717273, 0.707467, 0.698283, 0.688609, 0.678748, 0.668371,
+ 0.657739, 0.646951, 0.635765, 0.624254, 0.612647, 0.600900, 0.589061, 0.576998, 0.564991,
+ 0.553102, 0.541517, 0.530027, 0.518495, 1.000000, 1.000000, 0.999997, 0.999983, 0.999939,
+ 0.999851, 0.999684, 0.999412, 0.998925, 0.996597, 0.995207, 0.993603, 0.990903, 0.987594,
+ 0.983814, 0.979016, 0.973647, 0.967048, 0.960109, 0.952123, 0.943560, 0.934900, 0.925747,
+ 0.916566, 0.907305, 0.898441, 0.889629, 0.881042, 0.872874, 0.865064, 0.857225, 0.849446,
+ 0.842063, 0.834561, 0.826814, 0.818875, 0.810748, 0.802316, 0.793699, 0.784704, 0.775198,
+ 0.765643, 0.755735, 0.745873, 0.735526, 0.725229, 0.714892, 0.704807, 0.695502, 0.686241,
+ 0.676633, 0.666688, 0.656384, 0.645871, 0.635174, 0.624113, 0.612788, 0.601426, 0.589925,
+ 0.578399, 0.566612, 0.554931, 0.543383, 0.532065, 1.000000, 1.000000, 0.999996, 0.999977,
+ 0.999928, 0.999824, 0.999633, 0.999306, 0.998429, 0.996133, 0.994890, 0.992316, 0.989752,
+ 0.986095, 0.981564, 0.976234, 0.970081, 0.962779, 0.955232, 0.946702, 0.937716, 0.928604,
+ 0.919281, 0.910167, 0.901046, 0.892446, 0.884183, 0.876253, 0.868619, 0.861545, 0.854673,
+ 0.847885, 0.841074, 0.834610, 0.827984, 0.820945, 0.813648, 0.806232, 0.798444, 0.790232,
+ 0.781853, 0.772897, 0.763648, 0.754227, 0.744542, 0.734689, 0.724526, 0.714204, 0.704152,
+ 0.694222, 0.685143, 0.675860, 0.666319, 0.656415, 0.646273, 0.635902, 0.625399, 0.614563,
+ 0.603490, 0.592413, 0.581217, 0.570000, 0.558608, 0.547242, 1.000000, 0.999999, 0.999995,
+ 0.999972, 0.999915, 0.999790, 0.999562, 0.999168, 0.997237, 0.995672, 0.994074, 0.991220,
+ 0.987792, 0.983822, 0.978599, 0.972804, 0.965718, 0.958053, 0.949460, 0.940503, 0.931011,
+ 0.921608, 0.912409, 0.903378, 0.894606, 0.886369, 0.878756, 0.871573, 0.864862, 0.858421,
+ 0.852541, 0.846802, 0.841027, 0.835206, 0.829628, 0.823730, 0.817415, 0.810655, 0.803873,
+ 0.796659, 0.788887, 0.780940, 0.772537, 0.763507, 0.754487, 0.745163, 0.735572, 0.725687,
+ 0.715611, 0.705398, 0.695418, 0.685592, 0.676518, 0.667304, 0.657875, 0.648182, 0.638235,
+ 0.628062, 0.617813, 0.607283, 0.596552, 0.585770, 0.575033, 0.564153, 1.000000, 1.000000,
+ 0.999995, 0.999970, 0.999898, 0.999748, 0.999472, 0.998969, 0.996528, 0.995102, 0.992701,
+ 0.989963, 0.985981, 0.981194, 0.975183, 0.968501, 0.960502, 0.952012, 0.942861, 0.933376,
+ 0.923506, 0.914042, 0.904921, 0.896282, 0.887987, 0.880341, 0.873536, 0.867293, 0.861556,
+ 0.856148, 0.850987, 0.846352, 0.841684, 0.836880, 0.832036, 0.827091, 0.821900, 0.816206,
+ 0.810042, 0.803629, 0.796918, 0.789653, 0.781915, 0.774014, 0.765530, 0.756526, 0.747669,
+ 0.738342, 0.728770, 0.718942, 0.708942, 0.698855, 0.688933, 0.679131, 0.669855, 0.660811,
+ 0.651549, 0.642127, 0.632454, 0.622651, 0.612709, 0.602606, 0.592344, 0.581877, 1.000000,
+ 0.999999, 0.999993, 0.999963, 0.999874, 0.999691, 0.999350, 0.998431, 0.995873, 0.994456,
+ 0.991327, 0.987798, 0.983232, 0.977500, 0.970828, 0.962815, 0.954228, 0.944752, 0.935126,
+ 0.925179, 0.915102, 0.905763, 0.897087, 0.888933, 0.881452, 0.874687, 0.868716, 0.863585,
+ 0.858931, 0.854662, 0.850569, 0.846719, 0.843151, 0.839426, 0.835588, 0.831443, 0.827004,
+ 0.822395, 0.817254, 0.811630, 0.805464, 0.799124, 0.792382, 0.785091, 0.777315, 0.769360,
+ 0.760908, 0.751957, 0.743128, 0.733917, 0.724340, 0.714713, 0.704721, 0.694835, 0.684862,
+ 0.675099, 0.665570, 0.656644, 0.647651, 0.638581, 0.629337, 0.619926, 0.610358, 0.600707,
+ 1.000000, 1.000000, 0.999990, 0.999953, 0.999843, 0.999613, 0.999186, 0.997025, 0.995317,
+ 0.992850, 0.989760, 0.985270, 0.979807, 0.973049, 0.965228, 0.956248, 0.946394, 0.936324,
+ 0.926124, 0.915808, 0.905942, 0.897060, 0.889001, 0.881755, 0.875351, 0.869688, 0.864736,
+ 0.860745, 0.857305, 0.854190, 0.851261, 0.848484, 0.845642, 0.842948, 0.840060, 0.836901,
+ 0.833379, 0.829393, 0.825103, 0.820431, 0.815288, 0.809575, 0.803326, 0.796949, 0.790174,
+ 0.782873, 0.775048, 0.767139, 0.758772, 0.750019, 0.741120, 0.732127, 0.722743, 0.713225,
+ 0.703637, 0.693768, 0.684016, 0.674277, 0.664703, 0.655328, 0.646550, 0.637812, 0.629036,
+ 0.620129, 1.000000, 1.000000, 0.999988, 0.999933, 0.999800, 0.999508, 0.998917, 0.996236,
+ 0.994617, 0.991176, 0.987089, 0.981880, 0.974966, 0.967156, 0.957914, 0.947585, 0.936937,
+ 0.926318, 0.915662, 0.905567, 0.896223, 0.888166, 0.881117, 0.875079, 0.869981, 0.865675,
+ 0.862091, 0.859183, 0.856981, 0.855065, 0.853273, 0.851572, 0.849782, 0.847768, 0.845668,
+ 0.843345, 0.840703, 0.837646, 0.834094, 0.830030, 0.825631, 0.820873, 0.815619, 0.809856,
+ 0.803578, 0.797096, 0.790359, 0.783152, 0.775507, 0.767504, 0.759411, 0.750982, 0.742208,
+ 0.733383, 0.724445, 0.715190, 0.705827, 0.696440, 0.686773, 0.677242, 0.667735, 0.658471,
+ 0.649236, 0.640305, 1.000000, 0.999999, 0.999984, 0.999918, 0.999737, 0.999350, 0.997576,
+ 0.995476, 0.992614, 0.988817, 0.983601, 0.976880, 0.968694, 0.959092, 0.948297, 0.936831,
+ 0.925592, 0.914494, 0.904159, 0.894643, 0.886417, 0.879620, 0.874023, 0.869533, 0.865967,
+ 0.863238, 0.861113, 0.859527, 0.858367, 0.857594, 0.856882, 0.856172, 0.855316, 0.854197,
+ 0.852818, 0.851062, 0.849046, 0.846747, 0.844043, 0.840842, 0.837164, 0.832985, 0.828344,
+ 0.823544, 0.818276, 0.812543, 0.806374, 0.799838, 0.793170, 0.786246, 0.778956, 0.771297,
+ 0.763278, 0.755252, 0.746984, 0.738445, 0.729688, 0.721045, 0.712189, 0.703099, 0.694045,
+ 0.684930, 0.675601, 0.666480, 1.000000, 0.999999, 0.999978, 0.999888, 0.999639, 0.999093,
+ 0.996310, 0.994405, 0.990527, 0.985186, 0.978518, 0.969748, 0.959597, 0.948104, 0.935724,
+ 0.923704, 0.912023, 0.901356, 0.891850, 0.883847, 0.877280, 0.872289, 0.868583, 0.865913,
+ 0.864098, 0.862993, 0.862356, 0.862125, 0.862107, 0.862168, 0.862359, 0.862490, 0.862430,
+ 0.862063, 0.861431, 0.860386, 0.858950, 0.857090, 0.854848, 0.852381, 0.849503, 0.846167,
+ 0.842399, 0.838194, 0.833566, 0.828579, 0.823464, 0.817951, 0.812079, 0.805873, 0.799320,
+ 0.792533, 0.785715, 0.778636, 0.771260, 0.763618, 0.755719, 0.747815, 0.739825, 0.731602,
+ 0.723212, 0.714845, 0.706465, 0.697933, 1.000000, 0.999998, 0.999969, 0.999836, 0.999475,
+ 0.997943, 0.995219, 0.991760, 0.986663, 0.979592, 0.970218, 0.959155, 0.946575, 0.933047,
+ 0.920022, 0.907749, 0.896801, 0.887506, 0.880077, 0.874322, 0.870126, 0.867481, 0.865949,
+ 0.865293, 0.865287, 0.865746, 0.866502, 0.867439, 0.868442, 0.869382, 0.870161, 0.870782,
+ 0.871303, 0.871511, 0.871427, 0.870978, 0.870136, 0.868892, 0.867248, 0.865209, 0.862775,
+ 0.859944, 0.857004, 0.853671, 0.849984, 0.845927, 0.841518, 0.836774, 0.831750, 0.826407,
+ 0.821001, 0.815333, 0.809412, 0.803238, 0.796802, 0.790204, 0.783457, 0.776713, 0.769749,
+ 0.762596, 0.755239, 0.747690, 0.740127, 0.732595, 1.000000, 0.999997, 0.999950, 0.999744,
+ 0.999162, 0.996124, 0.992844, 0.987757, 0.980062, 0.969642, 0.957087, 0.942735, 0.927747,
+ 0.913622, 0.900889, 0.890115, 0.881584, 0.875288, 0.870926, 0.868307, 0.867033, 0.866972,
+ 0.867692, 0.868950, 0.870549, 0.872320, 0.874144, 0.875947, 0.877674, 0.879192, 0.880478,
+ 0.881539, 0.882307, 0.882739, 0.882902, 0.882847, 0.882461, 0.881725, 0.880636, 0.879197,
+ 0.877422, 0.875296, 0.872849, 0.870076, 0.866988, 0.863637, 0.860159, 0.856475, 0.852525,
+ 0.848328, 0.843883, 0.839198, 0.834322, 0.829221, 0.823907, 0.818461, 0.812972, 0.807316,
+ 0.801474, 0.795459, 0.789276, 0.783025, 0.776615, 0.770223, 0.999999, 0.999994, 0.999909,
+ 0.999536, 0.997195, 0.994123, 0.988168, 0.979344, 0.967003, 0.951763, 0.934724, 0.917948,
+ 0.902918, 0.890432, 0.880902, 0.874401, 0.870394, 0.868503, 0.868209, 0.869062, 0.870725,
+ 0.873006, 0.875558, 0.878230, 0.880893, 0.883445, 0.885832, 0.888059, 0.890058, 0.891782,
+ 0.893247, 0.894460, 0.895397, 0.896023, 0.896380, 0.896433, 0.896198, 0.895673, 0.894865,
+ 0.893908, 0.892700, 0.891224, 0.889501, 0.887539, 0.885336, 0.882903, 0.880244, 0.877373,
+ 0.874296, 0.871019, 0.867549, 0.863933, 0.860153, 0.856355, 0.852395, 0.848277, 0.844006,
+ 0.839587, 0.835045, 0.830378, 0.825579, 0.820649, 0.815592, 0.810432, 0.999998, 0.999988,
+ 0.999795, 0.998892, 0.994635, 0.987290, 0.975397, 0.958508, 0.938352, 0.917733, 0.899800,
+ 0.885878, 0.876516, 0.871200, 0.869099, 0.869317, 0.871112, 0.873870, 0.877160, 0.880682,
+ 0.884228, 0.887737, 0.891076, 0.894161, 0.896981, 0.899543, 0.901847, 0.903882, 0.905672,
+ 0.907188, 0.908451, 0.909480, 0.910289, 0.910878, 0.911259, 0.911430, 0.911396, 0.911154,
+ 0.910712, 0.910081, 0.909266, 0.908264, 0.907094, 0.905752, 0.904244, 0.902577, 0.900799,
+ 0.898931, 0.896923, 0.894782, 0.892513, 0.890117, 0.887600, 0.884968, 0.882222, 0.879369,
+ 0.876408, 0.873345, 0.870183, 0.866926, 0.863575, 0.860160, 0.856672, 0.853098, 0.999991,
+ 0.999947, 0.999158, 0.992842, 0.980107, 0.957230, 0.928231, 0.901539, 0.882688, 0.872588,
+ 0.869394, 0.870671, 0.874458, 0.879378, 0.884639, 0.889770, 0.894601, 0.898972, 0.902930,
+ 0.906456, 0.909568, 0.912329, 0.914750, 0.916893, 0.918774, 0.920429, 0.921868, 0.923110,
+ 0.924185, 0.925089, 0.925842, 0.926457, 0.926934, 0.927285, 0.927522, 0.927639, 0.927650,
+ 0.927553, 0.927356, 0.927061, 0.926671, 0.926187, 0.925617, 0.924962, 0.924224, 0.923409,
+ 0.922519, 0.921555, 0.920521, 0.919419, 0.918252, 0.917021, 0.915729, 0.914377, 0.912967,
+ 0.911503, 0.909984, 0.908414, 0.906791, 0.905122, 0.903401, 0.901637, 0.899826, 0.897972,
+ 0.987461, 0.940121, 0.871507, 0.898572, 0.916705, 0.926425, 0.931922, 0.935265, 0.937431,
+ 0.938899, 0.939950, 0.940717, 0.941301, 0.941754, 0.942111, 0.942397, 0.942631, 0.942823,
+ 0.942983, 0.943117, 0.943231, 0.943329, 0.943412, 0.943484, 0.943545, 0.943599, 0.943644,
+ 0.943682, 0.943716, 0.943744, 0.943766, 0.943785, 0.943799, 0.943808, 0.943815, 0.943818,
+ 0.943818, 0.943814, 0.943807, 0.943797, 0.943784, 0.943769, 0.943751, 0.943730, 0.943707,
+ 0.943681, 0.943652, 0.943623, 0.943589, 0.943554, 0.943518, 0.943479, 0.943438, 0.943396,
+ 0.943351, 0.943305, 0.943257, 0.943207, 0.943156, 0.943104, 0.943049, 0.942993, 0.942936,
+ 0.942877,
+};
+
+static float bsdf_split_sum_ggx[64 * 64 * 2] = {
+ 1.000000f, 0.000000f, 1.000000f, 0.000000f, 1.000000f, 0.000000f, 1.000000f, 0.000000f,
+ 1.000000f, 0.000000f, 1.000000f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000000f,
+ 0.999512f, 0.000000f, 0.999023f, 0.000001f, 0.999023f, 0.000001f, 0.998535f, 0.000001f,
+ 0.998047f, 0.000001f, 0.997559f, 0.000002f, 0.997070f, 0.000003f, 0.996094f, 0.000004f,
+ 0.994629f, 0.000004f, 0.993652f, 0.000006f, 0.991699f, 0.000007f, 0.989746f, 0.000008f,
+ 0.987305f, 0.000010f, 0.984375f, 0.000012f, 0.980957f, 0.000013f, 0.977539f, 0.000016f,
+ 0.973145f, 0.000018f, 0.967773f, 0.000020f, 0.961914f, 0.000023f, 0.955566f, 0.000025f,
+ 0.947754f, 0.000028f, 0.939941f, 0.000031f, 0.930664f, 0.000033f, 0.920410f, 0.000036f,
+ 0.909180f, 0.000039f, 0.896973f, 0.000042f, 0.884277f, 0.000044f, 0.870117f, 0.000047f,
+ 0.854980f, 0.000049f, 0.838867f, 0.000051f, 0.821777f, 0.000053f, 0.803711f, 0.000055f,
+ 0.785156f, 0.000057f, 0.765625f, 0.000058f, 0.745605f, 0.000059f, 0.724609f, 0.000060f,
+ 0.703613f, 0.000061f, 0.681641f, 0.000061f, 0.659668f, 0.000061f, 0.637695f, 0.000061f,
+ 0.615234f, 0.000061f, 0.592773f, 0.000060f, 0.570801f, 0.000060f, 0.548340f, 0.000059f,
+ 0.526855f, 0.000058f, 0.504883f, 0.000057f, 0.483887f, 0.000055f, 0.462891f, 0.000054f,
+ 0.442627f, 0.000053f, 0.422607f, 0.000051f, 0.403320f, 0.000050f, 0.384766f, 0.000048f,
+ 0.366455f, 0.000046f, 0.348877f, 0.000045f, 0.332031f, 0.000043f, 0.315918f, 0.000041f,
+ 0.999512f, 0.000000f, 0.999512f, 0.000000f, 1.000000f, 0.000000f, 1.000000f, 0.000000f,
+ 0.999512f, 0.000000f, 1.000000f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000000f,
+ 0.999512f, 0.000000f, 0.999023f, 0.000001f, 0.999023f, 0.000001f, 0.998535f, 0.000002f,
+ 0.998047f, 0.000003f, 0.997559f, 0.000004f, 0.997070f, 0.000005f, 0.996094f, 0.000006f,
+ 0.994629f, 0.000008f, 0.993164f, 0.000010f, 0.991699f, 0.000012f, 0.989746f, 0.000015f,
+ 0.987305f, 0.000018f, 0.984375f, 0.000020f, 0.980957f, 0.000024f, 0.977051f, 0.000027f,
+ 0.972168f, 0.000031f, 0.967285f, 0.000035f, 0.961426f, 0.000039f, 0.954590f, 0.000043f,
+ 0.947266f, 0.000048f, 0.938965f, 0.000052f, 0.929199f, 0.000057f, 0.919434f, 0.000061f,
+ 0.908203f, 0.000065f, 0.895996f, 0.000069f, 0.882812f, 0.000073f, 0.868652f, 0.000077f,
+ 0.853027f, 0.000080f, 0.837402f, 0.000083f, 0.820312f, 0.000086f, 0.802246f, 0.000088f,
+ 0.783691f, 0.000090f, 0.764160f, 0.000092f, 0.744141f, 0.000093f, 0.723633f, 0.000093f,
+ 0.702637f, 0.000094f, 0.681152f, 0.000094f, 0.659180f, 0.000093f, 0.637207f, 0.000093f,
+ 0.615234f, 0.000091f, 0.593262f, 0.000090f, 0.571289f, 0.000088f, 0.549316f, 0.000087f,
+ 0.527344f, 0.000085f, 0.505859f, 0.000082f, 0.485107f, 0.000080f, 0.464355f, 0.000078f,
+ 0.444336f, 0.000075f, 0.424561f, 0.000072f, 0.405273f, 0.000070f, 0.386719f, 0.000067f,
+ 0.368652f, 0.000065f, 0.351318f, 0.000062f, 0.334473f, 0.000059f, 0.318115f, 0.000057f,
+ 0.999512f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000000f, 1.000000f, 0.000000f,
+ 0.999512f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000001f, 0.999512f, 0.000001f,
+ 0.999512f, 0.000001f, 0.999512f, 0.000003f, 0.999023f, 0.000002f, 0.998535f, 0.000004f,
+ 0.998047f, 0.000005f, 0.997559f, 0.000007f, 0.997070f, 0.000009f, 0.996094f, 0.000011f,
+ 0.994629f, 0.000013f, 0.993164f, 0.000017f, 0.991211f, 0.000020f, 0.989258f, 0.000024f,
+ 0.986816f, 0.000028f, 0.983887f, 0.000033f, 0.980469f, 0.000038f, 0.976562f, 0.000043f,
+ 0.971680f, 0.000049f, 0.966797f, 0.000055f, 0.960449f, 0.000062f, 0.953613f, 0.000068f,
+ 0.946289f, 0.000075f, 0.937500f, 0.000081f, 0.928223f, 0.000088f, 0.917969f, 0.000094f,
+ 0.906738f, 0.000100f, 0.894531f, 0.000106f, 0.880859f, 0.000111f, 0.866699f, 0.000116f,
+ 0.851562f, 0.000120f, 0.835449f, 0.000124f, 0.818359f, 0.000127f, 0.800781f, 0.000130f,
+ 0.782227f, 0.000132f, 0.762695f, 0.000134f, 0.742676f, 0.000134f, 0.722656f, 0.000135f,
+ 0.701660f, 0.000134f, 0.680176f, 0.000133f, 0.658691f, 0.000132f, 0.636719f, 0.000130f,
+ 0.615234f, 0.000128f, 0.593262f, 0.000125f, 0.571289f, 0.000123f, 0.549805f, 0.000119f,
+ 0.528320f, 0.000116f, 0.507324f, 0.000112f, 0.486328f, 0.000109f, 0.466064f, 0.000105f,
+ 0.446045f, 0.000101f, 0.426514f, 0.000097f, 0.407471f, 0.000093f, 0.388916f, 0.000089f,
+ 0.370850f, 0.000085f, 0.353516f, 0.000082f, 0.336914f, 0.000078f, 0.320557f, 0.000074f,
+ 1.000000f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000000f,
+ 1.000000f, 0.000000f, 1.000000f, 0.000001f, 0.999512f, 0.000001f, 0.999512f, 0.000002f,
+ 0.999512f, 0.000002f, 0.999023f, 0.000003f, 0.999023f, 0.000005f, 0.998535f, 0.000006f,
+ 0.998535f, 0.000008f, 0.997559f, 0.000011f, 0.997070f, 0.000014f, 0.996094f, 0.000017f,
+ 0.994629f, 0.000020f, 0.993164f, 0.000026f, 0.991211f, 0.000030f, 0.989258f, 0.000036f,
+ 0.986816f, 0.000043f, 0.983398f, 0.000050f, 0.979980f, 0.000058f, 0.976074f, 0.000066f,
+ 0.971191f, 0.000074f, 0.965820f, 0.000082f, 0.959961f, 0.000093f, 0.952637f, 0.000101f,
+ 0.945312f, 0.000111f, 0.936523f, 0.000120f, 0.927246f, 0.000129f, 0.916504f, 0.000137f,
+ 0.905273f, 0.000145f, 0.892578f, 0.000153f, 0.879395f, 0.000160f, 0.865234f, 0.000166f,
+ 0.850098f, 0.000171f, 0.833984f, 0.000176f, 0.816895f, 0.000179f, 0.799316f, 0.000182f,
+ 0.780762f, 0.000184f, 0.761230f, 0.000185f, 0.741699f, 0.000185f, 0.721191f, 0.000184f,
+ 0.700684f, 0.000183f, 0.679688f, 0.000181f, 0.658203f, 0.000178f, 0.636719f, 0.000175f,
+ 0.615234f, 0.000171f, 0.593262f, 0.000167f, 0.571777f, 0.000162f, 0.550293f, 0.000158f,
+ 0.529297f, 0.000152f, 0.508301f, 0.000147f, 0.487793f, 0.000142f, 0.467529f, 0.000136f,
+ 0.447754f, 0.000131f, 0.428223f, 0.000125f, 0.409424f, 0.000120f, 0.391113f, 0.000115f,
+ 0.373291f, 0.000109f, 0.355957f, 0.000104f, 0.339355f, 0.000099f, 0.323242f, 0.000094f,
+ 0.999512f, 0.000002f, 0.999512f, 0.000002f, 1.000000f, 0.000002f, 0.999512f, 0.000002f,
+ 1.000000f, 0.000002f, 0.999512f, 0.000002f, 0.999512f, 0.000002f, 0.999512f, 0.000003f,
+ 0.999512f, 0.000004f, 0.999512f, 0.000005f, 0.999023f, 0.000007f, 0.998535f, 0.000010f,
+ 0.998047f, 0.000012f, 0.997559f, 0.000017f, 0.996582f, 0.000020f, 0.995605f, 0.000025f,
+ 0.994629f, 0.000032f, 0.993164f, 0.000038f, 0.991211f, 0.000047f, 0.988770f, 0.000055f,
+ 0.986328f, 0.000063f, 0.983398f, 0.000074f, 0.979492f, 0.000085f, 0.975586f, 0.000095f,
+ 0.970703f, 0.000108f, 0.965332f, 0.000121f, 0.958984f, 0.000132f, 0.952148f, 0.000145f,
+ 0.944336f, 0.000157f, 0.935547f, 0.000170f, 0.925781f, 0.000181f, 0.915039f, 0.000192f,
+ 0.903809f, 0.000203f, 0.891113f, 0.000212f, 0.877930f, 0.000220f, 0.863281f, 0.000227f,
+ 0.848145f, 0.000234f, 0.832031f, 0.000239f, 0.814941f, 0.000242f, 0.797363f, 0.000245f,
+ 0.778809f, 0.000247f, 0.759766f, 0.000247f, 0.740234f, 0.000246f, 0.720215f, 0.000244f,
+ 0.699707f, 0.000241f, 0.678711f, 0.000237f, 0.657715f, 0.000233f, 0.636230f, 0.000228f,
+ 0.614746f, 0.000222f, 0.593750f, 0.000216f, 0.572266f, 0.000209f, 0.551270f, 0.000202f,
+ 0.530273f, 0.000195f, 0.509277f, 0.000187f, 0.489014f, 0.000180f, 0.468994f, 0.000172f,
+ 0.449463f, 0.000165f, 0.430176f, 0.000157f, 0.411377f, 0.000150f, 0.393311f, 0.000143f,
+ 0.375488f, 0.000136f, 0.358398f, 0.000129f, 0.341797f, 0.000123f, 0.325684f, 0.000116f,
+ 0.999512f, 0.000005f, 0.999512f, 0.000005f, 0.999512f, 0.000005f, 0.999512f, 0.000005f,
+ 0.999512f, 0.000005f, 0.999512f, 0.000005f, 0.999512f, 0.000006f, 0.999512f, 0.000007f,
+ 0.999512f, 0.000008f, 0.999512f, 0.000011f, 0.999023f, 0.000013f, 0.998535f, 0.000015f,
+ 0.998047f, 0.000019f, 0.997559f, 0.000026f, 0.996582f, 0.000033f, 0.995605f, 0.000040f,
+ 0.994141f, 0.000047f, 0.993164f, 0.000058f, 0.991211f, 0.000069f, 0.988770f, 0.000080f,
+ 0.985840f, 0.000093f, 0.982910f, 0.000106f, 0.979004f, 0.000121f, 0.975098f, 0.000137f,
+ 0.970215f, 0.000153f, 0.964355f, 0.000169f, 0.958008f, 0.000186f, 0.951172f, 0.000201f,
+ 0.943359f, 0.000218f, 0.934082f, 0.000233f, 0.924316f, 0.000248f, 0.914062f, 0.000262f,
+ 0.902344f, 0.000275f, 0.889648f, 0.000286f, 0.875977f, 0.000295f, 0.861816f, 0.000304f,
+ 0.846680f, 0.000311f, 0.830566f, 0.000316f, 0.813477f, 0.000319f, 0.795898f, 0.000321f,
+ 0.777344f, 0.000322f, 0.758301f, 0.000320f, 0.739258f, 0.000318f, 0.719238f, 0.000314f,
+ 0.698730f, 0.000309f, 0.678223f, 0.000303f, 0.657227f, 0.000296f, 0.636230f, 0.000288f,
+ 0.614746f, 0.000280f, 0.593750f, 0.000271f, 0.572754f, 0.000262f, 0.551758f, 0.000252f,
+ 0.531250f, 0.000243f, 0.510742f, 0.000233f, 0.490479f, 0.000223f, 0.470703f, 0.000213f,
+ 0.451172f, 0.000203f, 0.432129f, 0.000194f, 0.413574f, 0.000184f, 0.395508f, 0.000175f,
+ 0.377930f, 0.000166f, 0.360840f, 0.000157f, 0.344238f, 0.000149f, 0.328125f, 0.000141f,
+ 0.999512f, 0.000011f, 0.999512f, 0.000011f, 0.999512f, 0.000011f, 0.999512f, 0.000011f,
+ 0.999512f, 0.000011f, 0.999512f, 0.000012f, 0.999512f, 0.000014f, 0.999512f, 0.000015f,
+ 0.999512f, 0.000017f, 0.999023f, 0.000020f, 0.998535f, 0.000022f, 0.998535f, 0.000028f,
+ 0.998047f, 0.000034f, 0.997559f, 0.000042f, 0.996582f, 0.000050f, 0.995605f, 0.000060f,
+ 0.994141f, 0.000072f, 0.992676f, 0.000084f, 0.990723f, 0.000099f, 0.988281f, 0.000115f,
+ 0.985840f, 0.000133f, 0.982422f, 0.000150f, 0.978516f, 0.000171f, 0.974609f, 0.000191f,
+ 0.969238f, 0.000211f, 0.963867f, 0.000232f, 0.957520f, 0.000253f, 0.950195f, 0.000274f,
+ 0.941895f, 0.000294f, 0.933105f, 0.000314f, 0.922852f, 0.000332f, 0.912109f, 0.000348f,
+ 0.900879f, 0.000363f, 0.888184f, 0.000377f, 0.874512f, 0.000387f, 0.859863f, 0.000397f,
+ 0.844727f, 0.000404f, 0.828613f, 0.000408f, 0.811523f, 0.000411f, 0.793945f, 0.000412f,
+ 0.775879f, 0.000411f, 0.756836f, 0.000407f, 0.737793f, 0.000403f, 0.717773f, 0.000396f,
+ 0.697754f, 0.000389f, 0.677246f, 0.000380f, 0.656738f, 0.000370f, 0.635742f, 0.000359f,
+ 0.614746f, 0.000347f, 0.594238f, 0.000335f, 0.573242f, 0.000323f, 0.552734f, 0.000310f,
+ 0.532227f, 0.000297f, 0.511719f, 0.000284f, 0.491943f, 0.000272f, 0.472412f, 0.000259f,
+ 0.453125f, 0.000246f, 0.434082f, 0.000234f, 0.415771f, 0.000222f, 0.397705f, 0.000211f,
+ 0.380127f, 0.000199f, 0.363281f, 0.000189f, 0.346680f, 0.000178f, 0.330811f, 0.000168f,
+ 0.999512f, 0.000022f, 0.999512f, 0.000022f, 0.999512f, 0.000022f, 0.999512f, 0.000022f,
+ 0.999512f, 0.000023f, 0.999512f, 0.000025f, 0.999512f, 0.000024f, 0.999512f, 0.000028f,
+ 0.999023f, 0.000030f, 0.999023f, 0.000035f, 0.999023f, 0.000040f, 0.998535f, 0.000046f,
+ 0.998047f, 0.000056f, 0.997559f, 0.000063f, 0.996094f, 0.000077f, 0.995605f, 0.000089f,
+ 0.994141f, 0.000106f, 0.992188f, 0.000123f, 0.990234f, 0.000143f, 0.987793f, 0.000163f,
+ 0.985352f, 0.000185f, 0.981934f, 0.000211f, 0.978027f, 0.000236f, 0.973633f, 0.000261f,
+ 0.968750f, 0.000288f, 0.962891f, 0.000314f, 0.956055f, 0.000341f, 0.949219f, 0.000366f,
+ 0.940918f, 0.000391f, 0.931641f, 0.000414f, 0.921875f, 0.000436f, 0.910645f, 0.000455f,
+ 0.898926f, 0.000471f, 0.886230f, 0.000487f, 0.872559f, 0.000499f, 0.858398f, 0.000509f,
+ 0.842773f, 0.000515f, 0.826660f, 0.000518f, 0.810059f, 0.000520f, 0.792480f, 0.000519f,
+ 0.774414f, 0.000515f, 0.755371f, 0.000509f, 0.736328f, 0.000501f, 0.716797f, 0.000492f,
+ 0.696777f, 0.000480f, 0.676758f, 0.000468f, 0.656250f, 0.000454f, 0.635742f, 0.000439f,
+ 0.615234f, 0.000424f, 0.594238f, 0.000408f, 0.573730f, 0.000392f, 0.553223f, 0.000375f,
+ 0.533203f, 0.000359f, 0.513184f, 0.000342f, 0.493408f, 0.000326f, 0.474121f, 0.000310f,
+ 0.455078f, 0.000294f, 0.436279f, 0.000279f, 0.417969f, 0.000264f, 0.400146f, 0.000250f,
+ 0.382812f, 0.000237f, 0.365723f, 0.000223f, 0.349365f, 0.000211f, 0.333496f, 0.000199f,
+ 0.999512f, 0.000041f, 0.999512f, 0.000041f, 0.999512f, 0.000041f, 0.999512f, 0.000042f,
+ 0.999512f, 0.000042f, 0.999512f, 0.000044f, 0.999512f, 0.000046f, 0.999512f, 0.000049f,
+ 0.999512f, 0.000054f, 0.999512f, 0.000059f, 0.999023f, 0.000065f, 0.998535f, 0.000076f,
+ 0.998047f, 0.000087f, 0.997070f, 0.000098f, 0.996582f, 0.000117f, 0.995117f, 0.000135f,
+ 0.993652f, 0.000152f, 0.992188f, 0.000176f, 0.989746f, 0.000201f, 0.987793f, 0.000228f,
+ 0.984863f, 0.000256f, 0.981445f, 0.000286f, 0.977539f, 0.000318f, 0.973145f, 0.000352f,
+ 0.967773f, 0.000384f, 0.961914f, 0.000417f, 0.955566f, 0.000451f, 0.947754f, 0.000481f,
+ 0.939453f, 0.000510f, 0.930176f, 0.000537f, 0.919922f, 0.000563f, 0.909180f, 0.000585f,
+ 0.897461f, 0.000604f, 0.884766f, 0.000620f, 0.871094f, 0.000632f, 0.856445f, 0.000641f,
+ 0.841309f, 0.000647f, 0.825195f, 0.000648f, 0.808105f, 0.000648f, 0.790527f, 0.000643f,
+ 0.772949f, 0.000637f, 0.754395f, 0.000627f, 0.735352f, 0.000615f, 0.715820f, 0.000601f,
+ 0.695801f, 0.000585f, 0.675781f, 0.000568f, 0.655762f, 0.000550f, 0.635742f, 0.000530f,
+ 0.615234f, 0.000510f, 0.594727f, 0.000490f, 0.574707f, 0.000469f, 0.554199f, 0.000448f,
+ 0.534180f, 0.000428f, 0.514648f, 0.000407f, 0.495117f, 0.000387f, 0.475830f, 0.000367f,
+ 0.456787f, 0.000348f, 0.438232f, 0.000329f, 0.420166f, 0.000311f, 0.402344f, 0.000294f,
+ 0.385254f, 0.000277f, 0.368408f, 0.000262f, 0.352051f, 0.000246f, 0.336182f, 0.000232f,
+ 0.999512f, 0.000072f, 0.999512f, 0.000072f, 0.999512f, 0.000072f, 0.999512f, 0.000072f,
+ 0.999512f, 0.000073f, 0.999512f, 0.000076f, 0.999512f, 0.000078f, 0.999512f, 0.000082f,
+ 0.999023f, 0.000086f, 0.999023f, 0.000095f, 0.998535f, 0.000102f, 0.998047f, 0.000116f,
+ 0.998047f, 0.000131f, 0.997070f, 0.000147f, 0.996094f, 0.000167f, 0.995117f, 0.000195f,
+ 0.993652f, 0.000219f, 0.991699f, 0.000246f, 0.989746f, 0.000278f, 0.987305f, 0.000315f,
+ 0.984375f, 0.000350f, 0.980957f, 0.000385f, 0.976562f, 0.000427f, 0.972168f, 0.000467f,
+ 0.967285f, 0.000509f, 0.960938f, 0.000548f, 0.954102f, 0.000587f, 0.946777f, 0.000623f,
+ 0.937988f, 0.000657f, 0.928711f, 0.000690f, 0.918457f, 0.000718f, 0.907715f, 0.000741f,
+ 0.895508f, 0.000762f, 0.882812f, 0.000778f, 0.869141f, 0.000791f, 0.854492f, 0.000798f,
+ 0.839355f, 0.000802f, 0.823242f, 0.000801f, 0.806152f, 0.000796f, 0.789062f, 0.000788f,
+ 0.770996f, 0.000777f, 0.752930f, 0.000762f, 0.733887f, 0.000745f, 0.714844f, 0.000726f,
+ 0.695312f, 0.000704f, 0.675293f, 0.000682f, 0.655273f, 0.000658f, 0.635254f, 0.000633f,
+ 0.615234f, 0.000607f, 0.595215f, 0.000582f, 0.575195f, 0.000556f, 0.555176f, 0.000530f,
+ 0.535645f, 0.000504f, 0.515625f, 0.000479f, 0.496582f, 0.000455f, 0.477539f, 0.000431f,
+ 0.458984f, 0.000407f, 0.440430f, 0.000385f, 0.422363f, 0.000363f, 0.404785f, 0.000343f,
+ 0.387695f, 0.000323f, 0.370850f, 0.000304f, 0.354736f, 0.000286f, 0.338867f, 0.000268f,
+ 0.999512f, 0.000119f, 0.999512f, 0.000119f, 0.999512f, 0.000119f, 0.999512f, 0.000119f,
+ 0.999512f, 0.000121f, 0.999512f, 0.000122f, 0.999512f, 0.000128f, 0.999512f, 0.000131f,
+ 0.999512f, 0.000139f, 0.999023f, 0.000149f, 0.998535f, 0.000161f, 0.998047f, 0.000179f,
+ 0.998047f, 0.000194f, 0.997070f, 0.000220f, 0.996094f, 0.000247f, 0.994629f, 0.000275f,
+ 0.993652f, 0.000309f, 0.991699f, 0.000344f, 0.989746f, 0.000385f, 0.986816f, 0.000429f,
+ 0.983887f, 0.000471f, 0.980469f, 0.000519f, 0.976074f, 0.000565f, 0.971680f, 0.000614f,
+ 0.966309f, 0.000664f, 0.959961f, 0.000710f, 0.953125f, 0.000754f, 0.945312f, 0.000797f,
+ 0.936523f, 0.000837f, 0.927246f, 0.000873f, 0.916992f, 0.000902f, 0.905762f, 0.000929f,
+ 0.893555f, 0.000950f, 0.880859f, 0.000966f, 0.866699f, 0.000977f, 0.852539f, 0.000981f,
+ 0.836914f, 0.000981f, 0.821289f, 0.000977f, 0.804688f, 0.000968f, 0.787109f, 0.000955f,
+ 0.769531f, 0.000937f, 0.751465f, 0.000917f, 0.732422f, 0.000894f, 0.713379f, 0.000868f,
+ 0.694336f, 0.000840f, 0.674805f, 0.000811f, 0.655273f, 0.000780f, 0.635254f, 0.000749f,
+ 0.615723f, 0.000716f, 0.595703f, 0.000685f, 0.575684f, 0.000653f, 0.556152f, 0.000621f,
+ 0.536621f, 0.000590f, 0.517090f, 0.000559f, 0.498291f, 0.000530f, 0.479492f, 0.000501f,
+ 0.460938f, 0.000473f, 0.442627f, 0.000446f, 0.424805f, 0.000420f, 0.407227f, 0.000396f,
+ 0.390137f, 0.000373f, 0.373535f, 0.000350f, 0.357422f, 0.000329f, 0.341553f, 0.000309f,
+ 0.999512f, 0.000187f, 0.999512f, 0.000187f, 0.999512f, 0.000188f, 0.999512f, 0.000188f,
+ 0.999512f, 0.000190f, 0.999512f, 0.000194f, 0.999512f, 0.000201f, 0.999023f, 0.000204f,
+ 0.999023f, 0.000213f, 0.999023f, 0.000228f, 0.998535f, 0.000242f, 0.998535f, 0.000264f,
+ 0.997559f, 0.000285f, 0.997070f, 0.000311f, 0.996094f, 0.000351f, 0.995117f, 0.000386f,
+ 0.993164f, 0.000429f, 0.991211f, 0.000470f, 0.989258f, 0.000520f, 0.986328f, 0.000575f,
+ 0.983398f, 0.000628f, 0.979492f, 0.000683f, 0.975586f, 0.000741f, 0.970703f, 0.000801f,
+ 0.965332f, 0.000855f, 0.958984f, 0.000910f, 0.951660f, 0.000961f, 0.943848f, 0.001009f,
+ 0.935059f, 0.001053f, 0.925781f, 0.001090f, 0.915039f, 0.001123f, 0.903809f, 0.001152f,
+ 0.891602f, 0.001172f, 0.878906f, 0.001186f, 0.864746f, 0.001194f, 0.850586f, 0.001195f,
+ 0.835449f, 0.001191f, 0.819336f, 0.001181f, 0.802734f, 0.001164f, 0.785645f, 0.001144f,
+ 0.768066f, 0.001121f, 0.750000f, 0.001092f, 0.731445f, 0.001061f, 0.712402f, 0.001027f,
+ 0.693359f, 0.000992f, 0.674316f, 0.000955f, 0.654785f, 0.000916f, 0.635254f, 0.000877f,
+ 0.615723f, 0.000838f, 0.596191f, 0.000799f, 0.576660f, 0.000760f, 0.557129f, 0.000721f,
+ 0.538086f, 0.000684f, 0.518555f, 0.000648f, 0.500000f, 0.000612f, 0.481445f, 0.000578f,
+ 0.462891f, 0.000545f, 0.444824f, 0.000513f, 0.427246f, 0.000483f, 0.409912f, 0.000454f,
+ 0.392822f, 0.000427f, 0.376221f, 0.000401f, 0.360107f, 0.000376f, 0.344482f, 0.000353f,
+ 0.999512f, 0.000284f, 0.999512f, 0.000284f, 0.999512f, 0.000284f, 0.999512f, 0.000285f,
+ 0.999512f, 0.000287f, 0.999512f, 0.000292f, 0.999512f, 0.000296f, 0.999023f, 0.000307f,
+ 0.999023f, 0.000320f, 0.999023f, 0.000338f, 0.998535f, 0.000349f, 0.998047f, 0.000381f,
+ 0.997559f, 0.000407f, 0.996582f, 0.000447f, 0.995605f, 0.000480f, 0.994629f, 0.000531f,
+ 0.992676f, 0.000579f, 0.990723f, 0.000637f, 0.988770f, 0.000693f, 0.985840f, 0.000755f,
+ 0.982422f, 0.000824f, 0.979004f, 0.000889f, 0.975098f, 0.000958f, 0.969727f, 0.001024f,
+ 0.963867f, 0.001090f, 0.957520f, 0.001152f, 0.950684f, 0.001211f, 0.942383f, 0.001263f,
+ 0.933594f, 0.001309f, 0.923828f, 0.001353f, 0.913086f, 0.001387f, 0.901855f, 0.001413f,
+ 0.889648f, 0.001432f, 0.876465f, 0.001443f, 0.862793f, 0.001446f, 0.848145f, 0.001442f,
+ 0.833008f, 0.001431f, 0.817383f, 0.001413f, 0.800781f, 0.001390f, 0.783691f, 0.001362f,
+ 0.766113f, 0.001328f, 0.748535f, 0.001291f, 0.729980f, 0.001250f, 0.711426f, 0.001207f,
+ 0.692871f, 0.001163f, 0.673828f, 0.001116f, 0.654785f, 0.001068f, 0.635254f, 0.001020f,
+ 0.616211f, 0.000973f, 0.596680f, 0.000926f, 0.577637f, 0.000878f, 0.558105f, 0.000833f,
+ 0.539062f, 0.000788f, 0.520508f, 0.000745f, 0.501465f, 0.000702f, 0.483154f, 0.000663f,
+ 0.465088f, 0.000624f, 0.447266f, 0.000587f, 0.429443f, 0.000552f, 0.412354f, 0.000518f,
+ 0.395508f, 0.000486f, 0.378906f, 0.000456f, 0.363037f, 0.000427f, 0.347168f, 0.000400f,
+ 0.999512f, 0.000417f, 0.999512f, 0.000417f, 0.999512f, 0.000418f, 0.999512f, 0.000419f,
+ 0.999512f, 0.000422f, 0.999512f, 0.000425f, 0.999023f, 0.000434f, 0.999023f, 0.000447f,
+ 0.999023f, 0.000462f, 0.999023f, 0.000480f, 0.998047f, 0.000508f, 0.998047f, 0.000538f,
+ 0.997070f, 0.000576f, 0.996582f, 0.000621f, 0.995605f, 0.000669f, 0.993652f, 0.000721f,
+ 0.992188f, 0.000784f, 0.990723f, 0.000849f, 0.987793f, 0.000918f, 0.985840f, 0.000996f,
+ 0.982422f, 0.001071f, 0.978516f, 0.001148f, 0.973633f, 0.001225f, 0.968750f, 0.001304f,
+ 0.962891f, 0.001378f, 0.956543f, 0.001447f, 0.948730f, 0.001511f, 0.940918f, 0.001568f,
+ 0.931641f, 0.001617f, 0.921875f, 0.001660f, 0.911621f, 0.001697f, 0.899902f, 0.001719f,
+ 0.887695f, 0.001735f, 0.874512f, 0.001740f, 0.860840f, 0.001738f, 0.846191f, 0.001725f,
+ 0.831055f, 0.001706f, 0.815430f, 0.001679f, 0.798828f, 0.001646f, 0.782227f, 0.001607f,
+ 0.764648f, 0.001562f, 0.747070f, 0.001514f, 0.729004f, 0.001462f, 0.710449f, 0.001409f,
+ 0.691895f, 0.001352f, 0.673340f, 0.001295f, 0.654297f, 0.001237f, 0.635254f, 0.001179f,
+ 0.616211f, 0.001122f, 0.597168f, 0.001065f, 0.578125f, 0.001010f, 0.559570f, 0.000955f,
+ 0.540527f, 0.000902f, 0.521973f, 0.000852f, 0.503418f, 0.000803f, 0.485352f, 0.000755f,
+ 0.467285f, 0.000710f, 0.449463f, 0.000668f, 0.431885f, 0.000626f, 0.414795f, 0.000587f,
+ 0.398193f, 0.000551f, 0.381836f, 0.000516f, 0.365723f, 0.000483f, 0.350098f, 0.000452f,
+ 0.999023f, 0.000597f, 0.999023f, 0.000597f, 0.999023f, 0.000597f, 0.999023f, 0.000598f,
+ 0.999023f, 0.000602f, 0.999023f, 0.000610f, 0.999023f, 0.000618f, 0.999023f, 0.000632f,
+ 0.998535f, 0.000651f, 0.998535f, 0.000675f, 0.998047f, 0.000704f, 0.997559f, 0.000742f,
+ 0.997070f, 0.000787f, 0.996094f, 0.000843f, 0.995117f, 0.000902f, 0.993652f, 0.000966f,
+ 0.992188f, 0.001039f, 0.990234f, 0.001117f, 0.987793f, 0.001197f, 0.984863f, 0.001286f,
+ 0.981445f, 0.001372f, 0.977539f, 0.001464f, 0.972656f, 0.001553f, 0.967773f, 0.001639f,
+ 0.961914f, 0.001722f, 0.955078f, 0.001798f, 0.947754f, 0.001868f, 0.938965f, 0.001928f,
+ 0.930176f, 0.001982f, 0.920410f, 0.002026f, 0.909668f, 0.002056f, 0.897949f, 0.002075f,
+ 0.885254f, 0.002085f, 0.872559f, 0.002083f, 0.858398f, 0.002071f, 0.844238f, 0.002048f,
+ 0.828613f, 0.002018f, 0.812988f, 0.001980f, 0.796875f, 0.001934f, 0.780273f, 0.001883f,
+ 0.763184f, 0.001824f, 0.745605f, 0.001763f, 0.728027f, 0.001698f, 0.709473f, 0.001632f,
+ 0.691406f, 0.001563f, 0.672852f, 0.001494f, 0.654297f, 0.001422f, 0.635254f, 0.001355f,
+ 0.616699f, 0.001286f, 0.598145f, 0.001218f, 0.579102f, 0.001152f, 0.560547f, 0.001089f,
+ 0.541992f, 0.001027f, 0.523438f, 0.000968f, 0.505371f, 0.000911f, 0.487305f, 0.000857f,
+ 0.469482f, 0.000804f, 0.451904f, 0.000755f, 0.434570f, 0.000708f, 0.417480f, 0.000663f,
+ 0.400879f, 0.000621f, 0.384521f, 0.000581f, 0.368652f, 0.000544f, 0.353027f, 0.000508f,
+ 0.999023f, 0.000833f, 0.999023f, 0.000833f, 0.999023f, 0.000834f, 0.999023f, 0.000835f,
+ 0.999023f, 0.000840f, 0.999023f, 0.000845f, 0.998535f, 0.000861f, 0.998535f, 0.000875f,
+ 0.998535f, 0.000897f, 0.998047f, 0.000928f, 0.997559f, 0.000965f, 0.997070f, 0.001007f,
+ 0.996582f, 0.001061f, 0.995605f, 0.001128f, 0.994629f, 0.001195f, 0.993164f, 0.001276f,
+ 0.991699f, 0.001362f, 0.989258f, 0.001453f, 0.986816f, 0.001539f, 0.983887f, 0.001645f,
+ 0.980469f, 0.001747f, 0.976562f, 0.001849f, 0.971680f, 0.001945f, 0.966309f, 0.002045f,
+ 0.959961f, 0.002136f, 0.953613f, 0.002218f, 0.945801f, 0.002291f, 0.937500f, 0.002357f,
+ 0.928223f, 0.002407f, 0.917969f, 0.002447f, 0.907227f, 0.002472f, 0.895508f, 0.002487f,
+ 0.883301f, 0.002485f, 0.870117f, 0.002474f, 0.856445f, 0.002451f, 0.841797f, 0.002417f,
+ 0.826660f, 0.002373f, 0.811035f, 0.002317f, 0.794922f, 0.002258f, 0.778320f, 0.002190f,
+ 0.761230f, 0.002117f, 0.744141f, 0.002041f, 0.726562f, 0.001961f, 0.708496f, 0.001880f,
+ 0.690430f, 0.001796f, 0.672363f, 0.001713f, 0.654297f, 0.001630f, 0.635742f, 0.001547f,
+ 0.617188f, 0.001466f, 0.598633f, 0.001387f, 0.580078f, 0.001310f, 0.561523f, 0.001235f,
+ 0.543457f, 0.001164f, 0.524902f, 0.001095f, 0.507324f, 0.001029f, 0.489258f, 0.000967f,
+ 0.471680f, 0.000906f, 0.454346f, 0.000850f, 0.437012f, 0.000796f, 0.420166f, 0.000745f,
+ 0.403564f, 0.000698f, 0.387451f, 0.000652f, 0.371582f, 0.000609f, 0.356201f, 0.000569f,
+ 0.998535f, 0.001139f, 0.998535f, 0.001139f, 0.998535f, 0.001140f, 0.998535f, 0.001142f,
+ 0.998535f, 0.001147f, 0.998535f, 0.001159f, 0.998535f, 0.001168f, 0.998047f, 0.001190f,
+ 0.998047f, 0.001217f, 0.997559f, 0.001254f, 0.997559f, 0.001301f, 0.997070f, 0.001356f,
+ 0.996094f, 0.001416f, 0.995605f, 0.001493f, 0.994141f, 0.001574f, 0.992676f, 0.001663f,
+ 0.990723f, 0.001759f, 0.988770f, 0.001867f, 0.986328f, 0.001980f, 0.982910f, 0.002087f,
+ 0.979492f, 0.002199f, 0.975586f, 0.002319f, 0.970703f, 0.002422f, 0.965332f, 0.002531f,
+ 0.958496f, 0.002628f, 0.952148f, 0.002714f, 0.944336f, 0.002792f, 0.935547f, 0.002851f,
+ 0.926270f, 0.002903f, 0.916016f, 0.002935f, 0.904785f, 0.002954f, 0.893066f, 0.002956f,
+ 0.880859f, 0.002947f, 0.867676f, 0.002920f, 0.853516f, 0.002882f, 0.839355f, 0.002831f,
+ 0.824219f, 0.002769f, 0.809082f, 0.002699f, 0.792969f, 0.002619f, 0.776367f, 0.002533f,
+ 0.759766f, 0.002443f, 0.742676f, 0.002350f, 0.725586f, 0.002251f, 0.708008f, 0.002151f,
+ 0.689941f, 0.002052f, 0.671875f, 0.001953f, 0.653809f, 0.001854f, 0.635742f, 0.001758f,
+ 0.617676f, 0.001663f, 0.599121f, 0.001572f, 0.581055f, 0.001482f, 0.562988f, 0.001395f,
+ 0.544922f, 0.001313f, 0.526855f, 0.001234f, 0.508789f, 0.001158f, 0.491455f, 0.001086f,
+ 0.473877f, 0.001018f, 0.456787f, 0.000954f, 0.439697f, 0.000892f, 0.422852f, 0.000834f,
+ 0.406494f, 0.000780f, 0.390381f, 0.000729f, 0.374512f, 0.000680f, 0.359131f, 0.000635f,
+ 0.998047f, 0.001528f, 0.998047f, 0.001528f, 0.998047f, 0.001529f, 0.998047f, 0.001532f,
+ 0.998047f, 0.001539f, 0.998047f, 0.001546f, 0.998047f, 0.001562f, 0.998047f, 0.001589f,
+ 0.997559f, 0.001621f, 0.997559f, 0.001668f, 0.996582f, 0.001715f, 0.996582f, 0.001777f,
+ 0.995605f, 0.001859f, 0.994629f, 0.001939f, 0.993652f, 0.002035f, 0.992188f, 0.002140f,
+ 0.990234f, 0.002243f, 0.987793f, 0.002369f, 0.985352f, 0.002489f, 0.981934f, 0.002621f,
+ 0.978516f, 0.002750f, 0.974121f, 0.002876f, 0.969238f, 0.002991f, 0.963867f, 0.003105f,
+ 0.957031f, 0.003206f, 0.950195f, 0.003300f, 0.942383f, 0.003374f, 0.933594f, 0.003431f,
+ 0.923828f, 0.003473f, 0.913574f, 0.003498f, 0.902344f, 0.003506f, 0.890625f, 0.003494f,
+ 0.878418f, 0.003468f, 0.865234f, 0.003426f, 0.851074f, 0.003366f, 0.836914f, 0.003296f,
+ 0.822266f, 0.003216f, 0.806641f, 0.003122f, 0.791016f, 0.003023f, 0.774902f, 0.002916f,
+ 0.758301f, 0.002804f, 0.741211f, 0.002689f, 0.724121f, 0.002573f, 0.707031f, 0.002453f,
+ 0.689453f, 0.002335f, 0.671875f, 0.002216f, 0.653809f, 0.002102f, 0.636230f, 0.001987f,
+ 0.618164f, 0.001878f, 0.600098f, 0.001771f, 0.582031f, 0.001668f, 0.564453f, 0.001569f,
+ 0.546387f, 0.001475f, 0.528809f, 0.001384f, 0.511230f, 0.001297f, 0.493652f, 0.001217f,
+ 0.476318f, 0.001139f, 0.459229f, 0.001065f, 0.442383f, 0.000996f, 0.425781f, 0.000930f,
+ 0.409424f, 0.000869f, 0.393311f, 0.000811f, 0.377686f, 0.000757f, 0.362305f, 0.000707f,
+ 0.997559f, 0.002018f, 0.997559f, 0.002018f, 0.997559f, 0.002018f, 0.997559f, 0.002022f,
+ 0.997559f, 0.002028f, 0.997559f, 0.002045f, 0.997559f, 0.002066f, 0.997559f, 0.002092f,
+ 0.997559f, 0.002129f, 0.996582f, 0.002176f, 0.996094f, 0.002235f, 0.995605f, 0.002312f,
+ 0.995605f, 0.002407f, 0.993652f, 0.002491f, 0.992676f, 0.002605f, 0.991211f, 0.002729f,
+ 0.989258f, 0.002846f, 0.987305f, 0.002987f, 0.984375f, 0.003120f, 0.980957f, 0.003263f,
+ 0.977051f, 0.003403f, 0.972656f, 0.003542f, 0.967285f, 0.003666f, 0.961914f, 0.003782f,
+ 0.955566f, 0.003889f, 0.947754f, 0.003967f, 0.939941f, 0.004044f, 0.931152f, 0.004097f,
+ 0.921387f, 0.004131f, 0.911133f, 0.004139f, 0.899902f, 0.004131f, 0.888184f, 0.004108f,
+ 0.875488f, 0.004055f, 0.862305f, 0.003990f, 0.848633f, 0.003914f, 0.834473f, 0.003819f,
+ 0.819824f, 0.003712f, 0.804199f, 0.003593f, 0.788574f, 0.003469f, 0.772949f, 0.003338f,
+ 0.756348f, 0.003201f, 0.739746f, 0.003063f, 0.723145f, 0.002924f, 0.706055f, 0.002781f,
+ 0.688965f, 0.002644f, 0.671387f, 0.002506f, 0.653809f, 0.002371f, 0.636230f, 0.002239f,
+ 0.618652f, 0.002111f, 0.601074f, 0.001989f, 0.583496f, 0.001871f, 0.565430f, 0.001759f,
+ 0.547852f, 0.001650f, 0.530273f, 0.001547f, 0.513184f, 0.001449f, 0.495850f, 0.001356f,
+ 0.478760f, 0.001269f, 0.461670f, 0.001185f, 0.445068f, 0.001107f, 0.428467f, 0.001035f,
+ 0.412354f, 0.000965f, 0.396240f, 0.000901f, 0.380615f, 0.000840f, 0.365479f, 0.000783f,
+ 0.997070f, 0.002625f, 0.997070f, 0.002625f, 0.997070f, 0.002626f, 0.997070f, 0.002630f,
+ 0.997070f, 0.002640f, 0.997070f, 0.002659f, 0.997070f, 0.002676f, 0.996582f, 0.002708f,
+ 0.996582f, 0.002752f, 0.996094f, 0.002813f, 0.995605f, 0.002886f, 0.995117f, 0.002956f,
+ 0.994141f, 0.003071f, 0.992676f, 0.003172f, 0.991699f, 0.003292f, 0.990234f, 0.003433f,
+ 0.988281f, 0.003580f, 0.985840f, 0.003727f, 0.982910f, 0.003870f, 0.979492f, 0.004028f,
+ 0.975586f, 0.004177f, 0.971191f, 0.004322f, 0.966309f, 0.004456f, 0.959961f, 0.004570f,
+ 0.953125f, 0.004669f, 0.945801f, 0.004757f, 0.937500f, 0.004826f, 0.928711f, 0.004864f,
+ 0.918945f, 0.004883f, 0.908691f, 0.004875f, 0.897461f, 0.004845f, 0.885254f, 0.004795f,
+ 0.872559f, 0.004723f, 0.859863f, 0.004631f, 0.846191f, 0.004520f, 0.832031f, 0.004398f,
+ 0.817383f, 0.004261f, 0.802246f, 0.004116f, 0.786621f, 0.003963f, 0.770996f, 0.003805f,
+ 0.754883f, 0.003639f, 0.738770f, 0.003475f, 0.722168f, 0.003307f, 0.705078f, 0.003143f,
+ 0.688477f, 0.002981f, 0.671387f, 0.002821f, 0.653809f, 0.002665f, 0.636719f, 0.002512f,
+ 0.619141f, 0.002367f, 0.602051f, 0.002226f, 0.584473f, 0.002090f, 0.566895f, 0.001963f,
+ 0.549805f, 0.001840f, 0.532227f, 0.001722f, 0.515137f, 0.001613f, 0.498047f, 0.001508f,
+ 0.481201f, 0.001409f, 0.464355f, 0.001316f, 0.447754f, 0.001228f, 0.431396f, 0.001145f,
+ 0.415283f, 0.001069f, 0.399414f, 0.000997f, 0.383789f, 0.000929f, 0.368652f, 0.000865f,
+ 0.996582f, 0.003370f, 0.996582f, 0.003370f, 0.996582f, 0.003372f, 0.996582f, 0.003378f,
+ 0.996582f, 0.003389f, 0.996094f, 0.003410f, 0.996094f, 0.003435f, 0.996094f, 0.003471f,
+ 0.996094f, 0.003523f, 0.995117f, 0.003588f, 0.995117f, 0.003664f, 0.994141f, 0.003754f,
+ 0.993164f, 0.003864f, 0.992676f, 0.003990f, 0.990723f, 0.004128f, 0.989746f, 0.004288f,
+ 0.987793f, 0.004429f, 0.984375f, 0.004601f, 0.981445f, 0.004757f, 0.978027f, 0.004925f,
+ 0.974121f, 0.005089f, 0.969727f, 0.005241f, 0.964355f, 0.005375f, 0.958008f, 0.005486f,
+ 0.951172f, 0.005596f, 0.943848f, 0.005665f, 0.935547f, 0.005718f, 0.925781f, 0.005737f,
+ 0.916016f, 0.005733f, 0.905762f, 0.005707f, 0.894531f, 0.005650f, 0.882324f, 0.005569f,
+ 0.870117f, 0.005466f, 0.856934f, 0.005341f, 0.843262f, 0.005199f, 0.829102f, 0.005043f,
+ 0.814941f, 0.004871f, 0.799805f, 0.004692f, 0.784668f, 0.004505f, 0.769043f, 0.004314f,
+ 0.753418f, 0.004116f, 0.737305f, 0.003922f, 0.721191f, 0.003729f, 0.704590f, 0.003536f,
+ 0.687988f, 0.003347f, 0.670898f, 0.003162f, 0.654297f, 0.002983f, 0.637207f, 0.002810f,
+ 0.620117f, 0.002642f, 0.603027f, 0.002481f, 0.585938f, 0.002329f, 0.568359f, 0.002182f,
+ 0.551270f, 0.002045f, 0.534180f, 0.001913f, 0.517090f, 0.001788f, 0.500488f, 0.001671f,
+ 0.483643f, 0.001560f, 0.467041f, 0.001456f, 0.450684f, 0.001358f, 0.434326f, 0.001266f,
+ 0.418213f, 0.001181f, 0.402588f, 0.001101f, 0.386963f, 0.001025f, 0.371826f, 0.000954f,
+ 0.995605f, 0.004276f, 0.995605f, 0.004276f, 0.995605f, 0.004280f, 0.995605f, 0.004284f,
+ 0.995605f, 0.004299f, 0.995117f, 0.004318f, 0.995117f, 0.004349f, 0.995117f, 0.004383f,
+ 0.994629f, 0.004456f, 0.994629f, 0.004524f, 0.994141f, 0.004612f, 0.993164f, 0.004704f,
+ 0.992676f, 0.004848f, 0.991699f, 0.004974f, 0.990234f, 0.005142f, 0.987793f, 0.005291f,
+ 0.986328f, 0.005474f, 0.982910f, 0.005638f, 0.980469f, 0.005825f, 0.976562f, 0.005989f,
+ 0.972656f, 0.006157f, 0.967773f, 0.006313f, 0.961914f, 0.006443f, 0.955566f, 0.006554f,
+ 0.948730f, 0.006645f, 0.940918f, 0.006702f, 0.932617f, 0.006733f, 0.923340f, 0.006733f,
+ 0.913574f, 0.006699f, 0.902832f, 0.006645f, 0.891602f, 0.006550f, 0.879395f, 0.006435f,
+ 0.867188f, 0.006294f, 0.854004f, 0.006130f, 0.840332f, 0.005951f, 0.826660f, 0.005756f,
+ 0.812500f, 0.005543f, 0.797363f, 0.005325f, 0.782715f, 0.005100f, 0.767090f, 0.004871f,
+ 0.751465f, 0.004642f, 0.735840f, 0.004414f, 0.719727f, 0.004185f, 0.703613f, 0.003960f,
+ 0.687500f, 0.003744f, 0.670898f, 0.003531f, 0.654297f, 0.003326f, 0.637695f, 0.003128f,
+ 0.620605f, 0.002939f, 0.604004f, 0.002756f, 0.586914f, 0.002584f, 0.569824f, 0.002420f,
+ 0.553223f, 0.002264f, 0.536133f, 0.002117f, 0.519531f, 0.001978f, 0.502930f, 0.001847f,
+ 0.486328f, 0.001723f, 0.469727f, 0.001607f, 0.453369f, 0.001498f, 0.437256f, 0.001395f,
+ 0.421387f, 0.001300f, 0.405762f, 0.001211f, 0.390381f, 0.001127f, 0.375244f, 0.001050f,
+ 0.994141f, 0.005367f, 0.994141f, 0.005367f, 0.994141f, 0.005371f, 0.994141f, 0.005375f,
+ 0.994141f, 0.005394f, 0.994141f, 0.005413f, 0.994141f, 0.005447f, 0.994141f, 0.005508f,
+ 0.993652f, 0.005558f, 0.993652f, 0.005650f, 0.992676f, 0.005741f, 0.991699f, 0.005848f,
+ 0.991211f, 0.006004f, 0.990234f, 0.006149f, 0.988281f, 0.006317f, 0.986328f, 0.006504f,
+ 0.984863f, 0.006687f, 0.981934f, 0.006866f, 0.978516f, 0.007050f, 0.974609f, 0.007233f,
+ 0.970215f, 0.007393f, 0.965820f, 0.007553f, 0.959961f, 0.007675f, 0.953125f, 0.007774f,
+ 0.946289f, 0.007843f, 0.938477f, 0.007889f, 0.929688f, 0.007889f, 0.920410f, 0.007858f,
+ 0.910156f, 0.007793f, 0.899414f, 0.007694f, 0.888672f, 0.007565f, 0.876465f, 0.007401f,
+ 0.864258f, 0.007214f, 0.851074f, 0.007008f, 0.837402f, 0.006779f, 0.823730f, 0.006535f,
+ 0.809570f, 0.006279f, 0.794922f, 0.006023f, 0.780273f, 0.005753f, 0.765137f, 0.005482f,
+ 0.750000f, 0.005215f, 0.734375f, 0.004944f, 0.718750f, 0.004681f, 0.703125f, 0.004425f,
+ 0.687012f, 0.004173f, 0.670898f, 0.003929f, 0.654297f, 0.003700f, 0.638184f, 0.003473f,
+ 0.621582f, 0.003260f, 0.604980f, 0.003056f, 0.588379f, 0.002861f, 0.571777f, 0.002676f,
+ 0.555176f, 0.002502f, 0.538574f, 0.002337f, 0.521973f, 0.002180f, 0.505371f, 0.002035f,
+ 0.488770f, 0.001898f, 0.472656f, 0.001769f, 0.456299f, 0.001649f, 0.440430f, 0.001534f,
+ 0.424561f, 0.001430f, 0.408936f, 0.001329f, 0.393555f, 0.001238f, 0.378418f, 0.001151f,
+ 0.993164f, 0.006672f, 0.993164f, 0.006672f, 0.993164f, 0.006676f, 0.993164f, 0.006687f,
+ 0.993164f, 0.006699f, 0.993164f, 0.006721f, 0.992676f, 0.006760f, 0.992676f, 0.006821f,
+ 0.992188f, 0.006897f, 0.991699f, 0.006973f, 0.991211f, 0.007099f, 0.990234f, 0.007206f,
+ 0.990234f, 0.007366f, 0.988281f, 0.007519f, 0.986328f, 0.007706f, 0.984863f, 0.007912f,
+ 0.982422f, 0.008087f, 0.979980f, 0.008286f, 0.977051f, 0.008476f, 0.972656f, 0.008667f,
+ 0.968262f, 0.008827f, 0.962891f, 0.008980f, 0.957520f, 0.009079f, 0.951172f, 0.009171f,
+ 0.943848f, 0.009216f, 0.935547f, 0.009224f, 0.926758f, 0.009193f, 0.917480f, 0.009125f,
+ 0.906738f, 0.009010f, 0.895996f, 0.008865f, 0.885254f, 0.008682f, 0.873047f, 0.008469f,
+ 0.860840f, 0.008232f, 0.847656f, 0.007973f, 0.834473f, 0.007690f, 0.820801f, 0.007397f,
+ 0.807129f, 0.007092f, 0.792969f, 0.006783f, 0.778320f, 0.006462f, 0.763184f, 0.006145f,
+ 0.748535f, 0.005833f, 0.733398f, 0.005524f, 0.717773f, 0.005219f, 0.702148f, 0.004925f,
+ 0.686523f, 0.004639f, 0.670898f, 0.004364f, 0.654785f, 0.004097f, 0.638672f, 0.003847f,
+ 0.622559f, 0.003605f, 0.605957f, 0.003376f, 0.589844f, 0.003157f, 0.573242f, 0.002951f,
+ 0.556641f, 0.002756f, 0.540527f, 0.002573f, 0.523926f, 0.002399f, 0.507812f, 0.002237f,
+ 0.491455f, 0.002085f, 0.475342f, 0.001943f, 0.459229f, 0.001809f, 0.443359f, 0.001684f,
+ 0.427734f, 0.001567f, 0.412109f, 0.001457f, 0.396973f, 0.001356f, 0.382080f, 0.001261f,
+ 0.991699f, 0.008217f, 0.991699f, 0.008217f, 0.991699f, 0.008217f, 0.991699f, 0.008232f,
+ 0.991211f, 0.008240f, 0.991211f, 0.008270f, 0.991211f, 0.008324f, 0.991211f, 0.008377f,
+ 0.990723f, 0.008461f, 0.990234f, 0.008553f, 0.989746f, 0.008682f, 0.988770f, 0.008820f,
+ 0.987793f, 0.008972f, 0.986816f, 0.009163f, 0.985352f, 0.009338f, 0.982910f, 0.009567f,
+ 0.980957f, 0.009758f, 0.977539f, 0.009956f, 0.974609f, 0.010155f, 0.970215f, 0.010330f,
+ 0.965820f, 0.010483f, 0.960449f, 0.010597f, 0.954590f, 0.010696f, 0.947754f, 0.010750f,
+ 0.940430f, 0.010757f, 0.932129f, 0.010735f, 0.923340f, 0.010651f, 0.913574f, 0.010536f,
+ 0.903809f, 0.010376f, 0.892578f, 0.010162f, 0.881348f, 0.009926f, 0.869629f, 0.009651f,
+ 0.857422f, 0.009354f, 0.844727f, 0.009026f, 0.831543f, 0.008690f, 0.817871f, 0.008331f,
+ 0.804199f, 0.007973f, 0.790527f, 0.007603f, 0.775879f, 0.007233f, 0.761719f, 0.006866f,
+ 0.747070f, 0.006500f, 0.731934f, 0.006145f, 0.716797f, 0.005798f, 0.701660f, 0.005466f,
+ 0.686523f, 0.005138f, 0.670898f, 0.004829f, 0.655273f, 0.004532f, 0.639160f, 0.004246f,
+ 0.623535f, 0.003975f, 0.607422f, 0.003719f, 0.591309f, 0.003477f, 0.575195f, 0.003246f,
+ 0.558594f, 0.003029f, 0.542480f, 0.002827f, 0.526367f, 0.002634f, 0.510254f, 0.002455f,
+ 0.494141f, 0.002285f, 0.478271f, 0.002129f, 0.462402f, 0.001980f, 0.446533f, 0.001843f,
+ 0.430908f, 0.001715f, 0.415527f, 0.001594f, 0.400391f, 0.001483f, 0.385498f, 0.001378f,
+ 0.989746f, 0.010040f, 0.989746f, 0.010040f, 0.989746f, 0.010040f, 0.989746f, 0.010048f,
+ 0.989746f, 0.010071f, 0.989746f, 0.010094f, 0.989258f, 0.010147f, 0.989258f, 0.010223f,
+ 0.988770f, 0.010300f, 0.988770f, 0.010406f, 0.987793f, 0.010529f, 0.986816f, 0.010696f,
+ 0.986328f, 0.010857f, 0.984863f, 0.011055f, 0.982422f, 0.011238f, 0.981445f, 0.011467f,
+ 0.978516f, 0.011673f, 0.975098f, 0.011871f, 0.972168f, 0.012062f, 0.967285f, 0.012215f,
+ 0.962402f, 0.012352f, 0.957031f, 0.012459f, 0.951172f, 0.012535f, 0.944336f, 0.012535f,
+ 0.937012f, 0.012520f, 0.928711f, 0.012428f, 0.919922f, 0.012299f, 0.910156f, 0.012115f,
+ 0.899414f, 0.011879f, 0.889160f, 0.011612f, 0.877441f, 0.011299f, 0.865723f, 0.010956f,
+ 0.853516f, 0.010582f, 0.841309f, 0.010193f, 0.828125f, 0.009773f, 0.814941f, 0.009361f,
+ 0.801270f, 0.008926f, 0.787598f, 0.008499f, 0.773926f, 0.008064f, 0.759766f, 0.007641f,
+ 0.745117f, 0.007225f, 0.730469f, 0.006817f, 0.716309f, 0.006424f, 0.701172f, 0.006042f,
+ 0.686035f, 0.005676f, 0.670898f, 0.005329f, 0.655273f, 0.004993f, 0.640137f, 0.004673f,
+ 0.624512f, 0.004372f, 0.608398f, 0.004086f, 0.592773f, 0.003817f, 0.576660f, 0.003561f,
+ 0.561035f, 0.003323f, 0.544922f, 0.003098f, 0.528809f, 0.002884f, 0.512695f, 0.002686f,
+ 0.497070f, 0.002501f, 0.481201f, 0.002327f, 0.465332f, 0.002165f, 0.449707f, 0.002014f,
+ 0.434326f, 0.001873f, 0.418945f, 0.001740f, 0.403809f, 0.001617f, 0.388916f, 0.001504f,
+ 0.987793f, 0.012169f, 0.987793f, 0.012169f, 0.987793f, 0.012169f, 0.987793f, 0.012184f,
+ 0.987305f, 0.012207f, 0.987305f, 0.012245f, 0.987305f, 0.012291f, 0.986816f, 0.012360f,
+ 0.986816f, 0.012459f, 0.986328f, 0.012573f, 0.985840f, 0.012695f, 0.984863f, 0.012878f,
+ 0.983887f, 0.013046f, 0.982422f, 0.013237f, 0.980469f, 0.013466f, 0.979004f, 0.013680f,
+ 0.976074f, 0.013878f, 0.972656f, 0.014069f, 0.969238f, 0.014259f, 0.964355f, 0.014397f,
+ 0.959961f, 0.014488f, 0.954102f, 0.014580f, 0.947754f, 0.014595f, 0.940430f, 0.014557f,
+ 0.933105f, 0.014481f, 0.925293f, 0.014328f, 0.915527f, 0.014122f, 0.906250f, 0.013870f,
+ 0.895996f, 0.013565f, 0.885254f, 0.013206f, 0.873535f, 0.012817f, 0.862305f, 0.012383f,
+ 0.850098f, 0.011932f, 0.837891f, 0.011452f, 0.824707f, 0.010963f, 0.812012f, 0.010460f,
+ 0.798828f, 0.009964f, 0.785156f, 0.009460f, 0.771484f, 0.008965f, 0.757812f, 0.008484f,
+ 0.743652f, 0.008003f, 0.729492f, 0.007542f, 0.715332f, 0.007095f, 0.700684f, 0.006668f,
+ 0.686035f, 0.006256f, 0.670898f, 0.005863f, 0.655762f, 0.005489f, 0.640625f, 0.005135f,
+ 0.625488f, 0.004799f, 0.609863f, 0.004478f, 0.594238f, 0.004181f, 0.578613f, 0.003901f,
+ 0.562988f, 0.003635f, 0.547363f, 0.003386f, 0.531250f, 0.003153f, 0.515625f, 0.002935f,
+ 0.500000f, 0.002729f, 0.484131f, 0.002539f, 0.468506f, 0.002361f, 0.453125f, 0.002195f,
+ 0.437744f, 0.002041f, 0.422363f, 0.001897f, 0.407471f, 0.001763f, 0.392578f, 0.001637f,
+ 0.985352f, 0.014641f, 0.985352f, 0.014641f, 0.984863f, 0.014648f, 0.984863f, 0.014656f,
+ 0.984863f, 0.014679f, 0.984863f, 0.014717f, 0.984863f, 0.014771f, 0.984375f, 0.014839f,
+ 0.984375f, 0.014938f, 0.983398f, 0.015060f, 0.983398f, 0.015244f, 0.981934f, 0.015388f,
+ 0.980957f, 0.015587f, 0.979492f, 0.015778f, 0.977539f, 0.015976f, 0.975586f, 0.016190f,
+ 0.972656f, 0.016388f, 0.969727f, 0.016571f, 0.965820f, 0.016739f, 0.961426f, 0.016861f,
+ 0.956055f, 0.016922f, 0.950684f, 0.016953f, 0.943848f, 0.016922f, 0.937012f, 0.016815f,
+ 0.929199f, 0.016663f, 0.920410f, 0.016434f, 0.911621f, 0.016144f, 0.901855f, 0.015793f,
+ 0.891602f, 0.015411f, 0.880859f, 0.014954f, 0.869629f, 0.014473f, 0.857910f, 0.013947f,
+ 0.846191f, 0.013390f, 0.833984f, 0.012825f, 0.821289f, 0.012253f, 0.809082f, 0.011665f,
+ 0.795898f, 0.011086f, 0.782715f, 0.010506f, 0.769531f, 0.009933f, 0.755859f, 0.009377f,
+ 0.742188f, 0.008842f, 0.728516f, 0.008316f, 0.714355f, 0.007812f, 0.700195f, 0.007336f,
+ 0.685547f, 0.006874f, 0.670898f, 0.006435f, 0.656250f, 0.006020f, 0.641602f, 0.005623f,
+ 0.626465f, 0.005253f, 0.611328f, 0.004902f, 0.596191f, 0.004570f, 0.580566f, 0.004261f,
+ 0.564941f, 0.003967f, 0.549316f, 0.003695f, 0.533691f, 0.003437f, 0.518066f, 0.003199f,
+ 0.502930f, 0.002975f, 0.487305f, 0.002766f, 0.471680f, 0.002571f, 0.456299f, 0.002388f,
+ 0.441162f, 0.002220f, 0.426025f, 0.002062f, 0.411133f, 0.001916f, 0.396240f, 0.001781f,
+ 0.982422f, 0.017502f, 0.982422f, 0.017502f, 0.982422f, 0.017502f, 0.982422f, 0.017517f,
+ 0.981934f, 0.017532f, 0.981934f, 0.017593f, 0.981934f, 0.017639f, 0.981934f, 0.017731f,
+ 0.981445f, 0.017838f, 0.980957f, 0.017960f, 0.979980f, 0.018112f, 0.979004f, 0.018295f,
+ 0.978027f, 0.018478f, 0.975586f, 0.018677f, 0.974609f, 0.018860f, 0.972168f, 0.019073f,
+ 0.969238f, 0.019287f, 0.965820f, 0.019455f, 0.962402f, 0.019562f, 0.958008f, 0.019653f,
+ 0.952637f, 0.019653f, 0.946289f, 0.019623f, 0.939453f, 0.019516f, 0.932617f, 0.019348f,
+ 0.924316f, 0.019089f, 0.916016f, 0.018784f, 0.907227f, 0.018387f, 0.897461f, 0.017944f,
+ 0.887207f, 0.017426f, 0.876465f, 0.016861f, 0.865234f, 0.016266f, 0.854004f, 0.015640f,
+ 0.842285f, 0.014999f, 0.830078f, 0.014320f, 0.818359f, 0.013641f, 0.805664f, 0.012962f,
+ 0.792969f, 0.012291f, 0.780273f, 0.011627f, 0.767090f, 0.010979f, 0.753906f, 0.010345f,
+ 0.740723f, 0.009735f, 0.727539f, 0.009155f, 0.713867f, 0.008591f, 0.699707f, 0.008049f,
+ 0.685547f, 0.007534f, 0.671387f, 0.007050f, 0.656738f, 0.006588f, 0.642578f, 0.006149f,
+ 0.627441f, 0.005737f, 0.612793f, 0.005352f, 0.597656f, 0.004986f, 0.582520f, 0.004642f,
+ 0.567383f, 0.004322f, 0.551758f, 0.004021f, 0.536621f, 0.003744f, 0.520996f, 0.003481f,
+ 0.505859f, 0.003235f, 0.490479f, 0.003006f, 0.475098f, 0.002794f, 0.459717f, 0.002596f,
+ 0.444580f, 0.002411f, 0.429688f, 0.002241f, 0.414795f, 0.002081f, 0.400146f, 0.001933f,
+ 0.979004f, 0.020798f, 0.979004f, 0.020798f, 0.979004f, 0.020798f, 0.979004f, 0.020813f,
+ 0.979004f, 0.020844f, 0.978516f, 0.020874f, 0.978516f, 0.020935f, 0.978027f, 0.021027f,
+ 0.978027f, 0.021149f, 0.977539f, 0.021286f, 0.977051f, 0.021454f, 0.975586f, 0.021622f,
+ 0.974121f, 0.021820f, 0.972656f, 0.021988f, 0.970215f, 0.022186f, 0.968750f, 0.022385f,
+ 0.965820f, 0.022552f, 0.961914f, 0.022675f, 0.958008f, 0.022736f, 0.953613f, 0.022751f,
+ 0.948242f, 0.022736f, 0.942383f, 0.022614f, 0.935547f, 0.022415f, 0.927734f, 0.022156f,
+ 0.919922f, 0.021790f, 0.911621f, 0.021362f, 0.901855f, 0.020859f, 0.892090f, 0.020279f,
+ 0.882324f, 0.019638f, 0.872070f, 0.018951f, 0.860840f, 0.018234f, 0.849609f, 0.017487f,
+ 0.838379f, 0.016708f, 0.826172f, 0.015930f, 0.814453f, 0.015144f, 0.802246f, 0.014359f,
+ 0.790527f, 0.013588f, 0.777832f, 0.012833f, 0.765137f, 0.012100f, 0.752441f, 0.011383f,
+ 0.739258f, 0.010696f, 0.726074f, 0.010040f, 0.712891f, 0.009415f, 0.699219f, 0.008812f,
+ 0.685547f, 0.008240f, 0.671875f, 0.007698f, 0.657715f, 0.007191f, 0.643555f, 0.006710f,
+ 0.628906f, 0.006252f, 0.614258f, 0.005829f, 0.599609f, 0.005428f, 0.584473f, 0.005051f,
+ 0.569336f, 0.004704f, 0.554199f, 0.004372f, 0.539062f, 0.004063f, 0.523926f, 0.003780f,
+ 0.508789f, 0.003513f, 0.493652f, 0.003263f, 0.478271f, 0.003033f, 0.463135f, 0.002817f,
+ 0.448242f, 0.002615f, 0.433350f, 0.002430f, 0.418457f, 0.002256f, 0.403809f, 0.002094f,
+ 0.975098f, 0.024582f, 0.975098f, 0.024567f, 0.975098f, 0.024582f, 0.975098f, 0.024597f,
+ 0.975098f, 0.024628f, 0.975098f, 0.024658f, 0.975098f, 0.024734f, 0.974609f, 0.024826f,
+ 0.973633f, 0.024933f, 0.973633f, 0.025055f, 0.972656f, 0.025223f, 0.972168f, 0.025421f,
+ 0.970215f, 0.025589f, 0.968262f, 0.025742f, 0.966309f, 0.025925f, 0.964355f, 0.026108f,
+ 0.960938f, 0.026230f, 0.957520f, 0.026321f, 0.953613f, 0.026352f, 0.948242f, 0.026260f,
+ 0.943848f, 0.026154f, 0.937500f, 0.025970f, 0.930664f, 0.025650f, 0.922852f, 0.025253f,
+ 0.915039f, 0.024765f, 0.906738f, 0.024200f, 0.897461f, 0.023560f, 0.887207f, 0.022827f,
+ 0.877441f, 0.022064f, 0.866699f, 0.021225f, 0.855957f, 0.020370f, 0.845215f, 0.019470f,
+ 0.833984f, 0.018570f, 0.822266f, 0.017654f, 0.811035f, 0.016754f, 0.799316f, 0.015854f,
+ 0.787109f, 0.014984f, 0.775391f, 0.014122f, 0.763184f, 0.013298f, 0.750488f, 0.012489f,
+ 0.737793f, 0.011726f, 0.725098f, 0.010986f, 0.712402f, 0.010284f, 0.699219f, 0.009621f,
+ 0.685547f, 0.008987f, 0.671875f, 0.008392f, 0.658203f, 0.007828f, 0.644531f, 0.007305f,
+ 0.630371f, 0.006802f, 0.615723f, 0.006336f, 0.601562f, 0.005898f, 0.586914f, 0.005489f,
+ 0.571777f, 0.005104f, 0.557129f, 0.004745f, 0.541992f, 0.004414f, 0.526855f, 0.004101f,
+ 0.511719f, 0.003809f, 0.496826f, 0.003538f, 0.481689f, 0.003286f, 0.466797f, 0.003052f,
+ 0.451904f, 0.002832f, 0.437012f, 0.002630f, 0.422363f, 0.002441f, 0.407715f, 0.002268f,
+ 0.970703f, 0.028870f, 0.970703f, 0.028870f, 0.970703f, 0.028885f, 0.970703f, 0.028900f,
+ 0.970703f, 0.028915f, 0.970703f, 0.028961f, 0.970215f, 0.029022f, 0.970215f, 0.029114f,
+ 0.969727f, 0.029251f, 0.968750f, 0.029373f, 0.968262f, 0.029526f, 0.966797f, 0.029678f,
+ 0.966309f, 0.029877f, 0.964844f, 0.030045f, 0.962402f, 0.030167f, 0.959473f, 0.030304f,
+ 0.956543f, 0.030411f, 0.953125f, 0.030411f, 0.948242f, 0.030319f, 0.943359f, 0.030197f,
+ 0.938477f, 0.029968f, 0.931641f, 0.029648f, 0.924805f, 0.029221f, 0.917969f, 0.028687f,
+ 0.909180f, 0.028030f, 0.900879f, 0.027313f, 0.891602f, 0.026505f, 0.881836f, 0.025620f,
+ 0.871582f, 0.024673f, 0.861816f, 0.023697f, 0.851074f, 0.022659f, 0.840820f, 0.021622f,
+ 0.829590f, 0.020569f, 0.818359f, 0.019516f, 0.807129f, 0.018478f, 0.795898f, 0.017456f,
+ 0.784180f, 0.016464f, 0.772461f, 0.015503f, 0.760742f, 0.014572f, 0.748535f, 0.013672f,
+ 0.736816f, 0.012817f, 0.724121f, 0.012001f, 0.711914f, 0.011215f, 0.698730f, 0.010483f,
+ 0.686035f, 0.009789f, 0.672852f, 0.009132f, 0.659180f, 0.008514f, 0.645508f, 0.007935f,
+ 0.631836f, 0.007389f, 0.617676f, 0.006878f, 0.603516f, 0.006397f, 0.588867f, 0.005951f,
+ 0.574219f, 0.005531f, 0.559570f, 0.005142f, 0.544922f, 0.004776f, 0.529785f, 0.004436f,
+ 0.515137f, 0.004120f, 0.500000f, 0.003828f, 0.485352f, 0.003555f, 0.470215f, 0.003302f,
+ 0.455566f, 0.003065f, 0.440918f, 0.002844f, 0.426270f, 0.002642f, 0.411621f, 0.002451f,
+ 0.965820f, 0.033752f, 0.965820f, 0.033752f, 0.965820f, 0.033752f, 0.965820f, 0.033783f,
+ 0.965820f, 0.033783f, 0.965820f, 0.033875f, 0.965332f, 0.033905f, 0.965332f, 0.033997f,
+ 0.964844f, 0.034088f, 0.963867f, 0.034241f, 0.963379f, 0.034393f, 0.962402f, 0.034546f,
+ 0.960938f, 0.034698f, 0.958496f, 0.034851f, 0.957520f, 0.034973f, 0.954102f, 0.035034f,
+ 0.951172f, 0.035034f, 0.947754f, 0.034943f, 0.942871f, 0.034821f, 0.937988f, 0.034576f,
+ 0.932129f, 0.034180f, 0.926270f, 0.033722f, 0.918945f, 0.033142f, 0.911133f, 0.032410f,
+ 0.902832f, 0.031616f, 0.894531f, 0.030685f, 0.885254f, 0.029694f, 0.876465f, 0.028641f,
+ 0.866699f, 0.027512f, 0.856445f, 0.026337f, 0.846191f, 0.025146f, 0.835449f, 0.023926f,
+ 0.825195f, 0.022720f, 0.814453f, 0.021515f, 0.803711f, 0.020340f, 0.792480f, 0.019165f,
+ 0.781250f, 0.018051f, 0.770020f, 0.016968f, 0.758789f, 0.015915f, 0.747070f, 0.014931f,
+ 0.735352f, 0.013977f, 0.723145f, 0.013069f, 0.710938f, 0.012215f, 0.698730f, 0.011398f,
+ 0.686035f, 0.010635f, 0.673340f, 0.009918f, 0.660156f, 0.009239f, 0.646484f, 0.008598f,
+ 0.633301f, 0.008003f, 0.619141f, 0.007446f, 0.605469f, 0.006927f, 0.591309f, 0.006439f,
+ 0.576660f, 0.005985f, 0.562500f, 0.005562f, 0.547852f, 0.005165f, 0.533203f, 0.004795f,
+ 0.518066f, 0.004456f, 0.503418f, 0.004135f, 0.488770f, 0.003841f, 0.474121f, 0.003565f,
+ 0.459229f, 0.003311f, 0.444580f, 0.003073f, 0.430176f, 0.002853f, 0.415771f, 0.002647f,
+ 0.960449f, 0.039276f, 0.960449f, 0.039276f, 0.960449f, 0.039276f, 0.960449f, 0.039307f,
+ 0.960449f, 0.039337f, 0.959961f, 0.039368f, 0.959961f, 0.039429f, 0.959961f, 0.039520f,
+ 0.959473f, 0.039612f, 0.958984f, 0.039764f, 0.958008f, 0.039886f, 0.956543f, 0.040009f,
+ 0.955566f, 0.040131f, 0.953125f, 0.040253f, 0.951172f, 0.040314f, 0.948242f, 0.040283f,
+ 0.945801f, 0.040222f, 0.940918f, 0.040039f, 0.936523f, 0.039764f, 0.931152f, 0.039368f,
+ 0.926270f, 0.038879f, 0.919434f, 0.038208f, 0.913086f, 0.037445f, 0.905273f, 0.036530f,
+ 0.897461f, 0.035522f, 0.888184f, 0.034393f, 0.879395f, 0.033173f, 0.870117f, 0.031891f,
+ 0.860352f, 0.030563f, 0.850586f, 0.029190f, 0.840820f, 0.027802f, 0.830566f, 0.026398f,
+ 0.820312f, 0.025009f, 0.810059f, 0.023636f, 0.799805f, 0.022308f, 0.789062f, 0.020996f,
+ 0.778809f, 0.019730f, 0.767578f, 0.018524f, 0.756348f, 0.017365f, 0.745605f, 0.016251f,
+ 0.733887f, 0.015213f, 0.722656f, 0.014206f, 0.710938f, 0.013260f, 0.698730f, 0.012367f,
+ 0.686523f, 0.011536f, 0.673828f, 0.010742f, 0.661133f, 0.010002f, 0.647949f, 0.009308f,
+ 0.634766f, 0.008659f, 0.621094f, 0.008057f, 0.607422f, 0.007488f, 0.593262f, 0.006958f,
+ 0.579102f, 0.006466f, 0.564941f, 0.006004f, 0.550781f, 0.005577f, 0.536133f, 0.005177f,
+ 0.521484f, 0.004807f, 0.506836f, 0.004463f, 0.492432f, 0.004143f, 0.477783f, 0.003847f,
+ 0.463135f, 0.003571f, 0.448730f, 0.003315f, 0.434082f, 0.003077f, 0.419922f, 0.002857f,
+ 0.954102f, 0.045502f, 0.954102f, 0.045502f, 0.954102f, 0.045502f, 0.954102f, 0.045532f,
+ 0.954102f, 0.045563f, 0.954102f, 0.045593f, 0.953613f, 0.045654f, 0.953613f, 0.045715f,
+ 0.953125f, 0.045868f, 0.952148f, 0.045990f, 0.951660f, 0.046082f, 0.950195f, 0.046143f,
+ 0.948242f, 0.046265f, 0.946777f, 0.046265f, 0.943848f, 0.046265f, 0.941895f, 0.046204f,
+ 0.938477f, 0.046021f, 0.935059f, 0.045685f, 0.929199f, 0.045258f, 0.925293f, 0.044708f,
+ 0.919434f, 0.044006f, 0.912109f, 0.043121f, 0.905273f, 0.042145f, 0.897949f, 0.041016f,
+ 0.890137f, 0.039734f, 0.881348f, 0.038391f, 0.872559f, 0.036926f, 0.863770f, 0.035431f,
+ 0.854004f, 0.033813f, 0.844727f, 0.032227f, 0.835449f, 0.030640f, 0.825195f, 0.029037f,
+ 0.815430f, 0.027451f, 0.806152f, 0.025909f, 0.795898f, 0.024399f, 0.785645f, 0.022934f,
+ 0.775391f, 0.021530f, 0.765137f, 0.020187f, 0.754883f, 0.018890f, 0.743652f, 0.017670f,
+ 0.732910f, 0.016510f, 0.721680f, 0.015411f, 0.710449f, 0.014374f, 0.698730f, 0.013405f,
+ 0.686523f, 0.012482f, 0.674316f, 0.011620f, 0.662109f, 0.010811f, 0.649414f, 0.010063f,
+ 0.636230f, 0.009354f, 0.623047f, 0.008698f, 0.609375f, 0.008080f, 0.595703f, 0.007507f,
+ 0.582031f, 0.006973f, 0.567871f, 0.006477f, 0.553711f, 0.006016f, 0.539551f, 0.005585f,
+ 0.524902f, 0.005180f, 0.510254f, 0.004810f, 0.496094f, 0.004463f, 0.481689f, 0.004147f,
+ 0.467041f, 0.003847f, 0.452637f, 0.003571f, 0.438232f, 0.003315f, 0.424072f, 0.003077f,
+ 0.947266f, 0.052490f, 0.947266f, 0.052490f, 0.947266f, 0.052490f, 0.947266f, 0.052521f,
+ 0.947266f, 0.052551f, 0.946777f, 0.052582f, 0.946777f, 0.052612f, 0.946289f, 0.052734f,
+ 0.945801f, 0.052795f, 0.945312f, 0.052887f, 0.944336f, 0.052948f, 0.942871f, 0.053040f,
+ 0.941406f, 0.053009f, 0.939941f, 0.053009f, 0.937012f, 0.052917f, 0.934570f, 0.052704f,
+ 0.931641f, 0.052399f, 0.926758f, 0.051971f, 0.922852f, 0.051331f, 0.917480f, 0.050568f,
+ 0.911133f, 0.049622f, 0.904297f, 0.048523f, 0.898438f, 0.047272f, 0.890137f, 0.045868f,
+ 0.882812f, 0.044312f, 0.874512f, 0.042694f, 0.865723f, 0.040955f, 0.856934f, 0.039154f,
+ 0.847656f, 0.037354f, 0.838867f, 0.035522f, 0.829590f, 0.033661f, 0.820312f, 0.031830f,
+ 0.811035f, 0.030060f, 0.801270f, 0.028305f, 0.791992f, 0.026611f, 0.782227f, 0.024994f,
+ 0.772461f, 0.023422f, 0.762695f, 0.021927f, 0.752441f, 0.020508f, 0.742188f, 0.019165f,
+ 0.731445f, 0.017883f, 0.721191f, 0.016678f, 0.709961f, 0.015556f, 0.698730f, 0.014488f,
+ 0.687012f, 0.013489f, 0.675293f, 0.012550f, 0.663086f, 0.011673f, 0.650879f, 0.010849f,
+ 0.638184f, 0.010086f, 0.625000f, 0.009369f, 0.611816f, 0.008705f, 0.598145f, 0.008087f,
+ 0.584961f, 0.007511f, 0.570801f, 0.006977f, 0.556641f, 0.006474f, 0.542480f, 0.006012f,
+ 0.528320f, 0.005581f, 0.514160f, 0.005180f, 0.499756f, 0.004807f, 0.485596f, 0.004459f,
+ 0.471191f, 0.004139f, 0.456787f, 0.003843f, 0.442383f, 0.003569f, 0.428467f, 0.003313f,
+ 0.939453f, 0.060333f, 0.939453f, 0.060333f, 0.939453f, 0.060333f, 0.939453f, 0.060333f,
+ 0.939453f, 0.060394f, 0.938965f, 0.060394f, 0.938965f, 0.060455f, 0.938477f, 0.060516f,
+ 0.937988f, 0.060577f, 0.937500f, 0.060638f, 0.936035f, 0.060669f, 0.935547f, 0.060669f,
+ 0.933594f, 0.060608f, 0.931641f, 0.060516f, 0.929688f, 0.060272f, 0.927246f, 0.059967f,
+ 0.922363f, 0.059448f, 0.918945f, 0.058868f, 0.914062f, 0.057953f, 0.908691f, 0.056946f,
+ 0.902832f, 0.055786f, 0.897461f, 0.054382f, 0.890137f, 0.052826f, 0.882324f, 0.051117f,
+ 0.874023f, 0.049255f, 0.866211f, 0.047302f, 0.858398f, 0.045288f, 0.849609f, 0.043213f,
+ 0.840820f, 0.041107f, 0.832031f, 0.038971f, 0.823730f, 0.036896f, 0.814453f, 0.034821f,
+ 0.806152f, 0.032806f, 0.796875f, 0.030853f, 0.788086f, 0.028961f, 0.778809f, 0.027161f,
+ 0.769531f, 0.025421f, 0.760254f, 0.023788f, 0.750488f, 0.022217f, 0.740723f, 0.020737f,
+ 0.730957f, 0.019333f, 0.720703f, 0.018021f, 0.709961f, 0.016785f, 0.698730f, 0.015625f,
+ 0.687500f, 0.014549f, 0.676270f, 0.013535f, 0.664551f, 0.012573f, 0.652344f, 0.011688f,
+ 0.640137f, 0.010864f, 0.627441f, 0.010086f, 0.614258f, 0.009369f, 0.601074f, 0.008698f,
+ 0.587402f, 0.008080f, 0.573730f, 0.007500f, 0.560059f, 0.006962f, 0.545898f, 0.006462f,
+ 0.531738f, 0.006001f, 0.517578f, 0.005569f, 0.503418f, 0.005165f, 0.489502f, 0.004795f,
+ 0.475098f, 0.004452f, 0.460938f, 0.004131f, 0.446777f, 0.003838f, 0.432861f, 0.003563f,
+ 0.930664f, 0.069031f, 0.930664f, 0.069031f, 0.930664f, 0.069031f, 0.930664f, 0.069031f,
+ 0.930664f, 0.069092f, 0.930664f, 0.069092f, 0.930176f, 0.069214f, 0.929688f, 0.069153f,
+ 0.929199f, 0.069214f, 0.929199f, 0.069275f, 0.927246f, 0.069214f, 0.926758f, 0.069153f,
+ 0.925293f, 0.069031f, 0.923340f, 0.068787f, 0.920410f, 0.068420f, 0.917480f, 0.067932f,
+ 0.914551f, 0.067261f, 0.911133f, 0.066345f, 0.905273f, 0.065247f, 0.900391f, 0.063965f,
+ 0.894043f, 0.062469f, 0.888184f, 0.060699f, 0.880859f, 0.058807f, 0.873535f, 0.056763f,
+ 0.866211f, 0.054565f, 0.858887f, 0.052277f, 0.850586f, 0.049896f, 0.841797f, 0.047485f,
+ 0.833496f, 0.045105f, 0.825684f, 0.042664f, 0.817383f, 0.040283f, 0.809082f, 0.037964f,
+ 0.800781f, 0.035706f, 0.792480f, 0.033539f, 0.784180f, 0.031433f, 0.775391f, 0.029449f,
+ 0.766602f, 0.027542f, 0.757812f, 0.025726f, 0.748535f, 0.024017f, 0.739258f, 0.022400f,
+ 0.729980f, 0.020874f, 0.719727f, 0.019440f, 0.709961f, 0.018097f, 0.699219f, 0.016830f,
+ 0.688477f, 0.015656f, 0.677246f, 0.014557f, 0.665527f, 0.013527f, 0.653809f, 0.012573f,
+ 0.641602f, 0.011681f, 0.629395f, 0.010841f, 0.616699f, 0.010071f, 0.603516f, 0.009346f,
+ 0.590332f, 0.008682f, 0.577148f, 0.008057f, 0.563477f, 0.007481f, 0.549316f, 0.006943f,
+ 0.535645f, 0.006443f, 0.521484f, 0.005978f, 0.507324f, 0.005550f, 0.493408f, 0.005150f,
+ 0.479248f, 0.004780f, 0.465332f, 0.004436f, 0.451172f, 0.004124f, 0.437256f, 0.003828f,
+ 0.920898f, 0.078735f, 0.920898f, 0.078735f, 0.920898f, 0.078735f, 0.920898f, 0.078735f,
+ 0.920898f, 0.078796f, 0.920898f, 0.078796f, 0.920410f, 0.078796f, 0.919922f, 0.078857f,
+ 0.919922f, 0.078857f, 0.918945f, 0.078796f, 0.917480f, 0.078735f, 0.916992f, 0.078613f,
+ 0.915039f, 0.078308f, 0.913086f, 0.077942f, 0.910645f, 0.077454f, 0.908691f, 0.076660f,
+ 0.905273f, 0.075745f, 0.899902f, 0.074585f, 0.895996f, 0.073181f, 0.889648f, 0.071533f,
+ 0.883789f, 0.069641f, 0.877930f, 0.067566f, 0.872070f, 0.065247f, 0.864258f, 0.062805f,
+ 0.856934f, 0.060242f, 0.849121f, 0.057556f, 0.841797f, 0.054810f, 0.833984f, 0.052063f,
+ 0.827148f, 0.049316f, 0.818848f, 0.046570f, 0.811035f, 0.043915f, 0.803223f, 0.041290f,
+ 0.795898f, 0.038788f, 0.788086f, 0.036377f, 0.779785f, 0.034058f, 0.771973f, 0.031830f,
+ 0.763672f, 0.029755f, 0.755371f, 0.027771f, 0.747070f, 0.025894f, 0.738281f, 0.024139f,
+ 0.729004f, 0.022476f, 0.719238f, 0.020935f, 0.709473f, 0.019470f, 0.699707f, 0.018097f,
+ 0.688965f, 0.016830f, 0.678223f, 0.015640f, 0.666992f, 0.014534f, 0.655762f, 0.013496f,
+ 0.643555f, 0.012535f, 0.631348f, 0.011642f, 0.619141f, 0.010803f, 0.606445f, 0.010033f,
+ 0.593262f, 0.009308f, 0.580078f, 0.008644f, 0.566406f, 0.008018f, 0.553223f, 0.007446f,
+ 0.539062f, 0.006908f, 0.525391f, 0.006413f, 0.511230f, 0.005951f, 0.497559f, 0.005527f,
+ 0.483643f, 0.005131f, 0.469482f, 0.004765f, 0.455566f, 0.004421f, 0.441650f, 0.004108f,
+ 0.910156f, 0.089539f, 0.910156f, 0.089539f, 0.910156f, 0.089539f, 0.910156f, 0.089539f,
+ 0.910156f, 0.089539f, 0.909668f, 0.089539f, 0.909668f, 0.089539f, 0.909180f, 0.089539f,
+ 0.908691f, 0.089478f, 0.907715f, 0.089417f, 0.907227f, 0.089233f, 0.905762f, 0.088989f,
+ 0.904297f, 0.088562f, 0.902832f, 0.088013f, 0.900391f, 0.087280f, 0.896973f, 0.086243f,
+ 0.895020f, 0.085083f, 0.889160f, 0.083557f, 0.884766f, 0.081787f, 0.878906f, 0.079712f,
+ 0.874512f, 0.077393f, 0.867676f, 0.074951f, 0.860840f, 0.072205f, 0.854492f, 0.069275f,
+ 0.848145f, 0.066223f, 0.840820f, 0.063171f, 0.833008f, 0.060059f, 0.826172f, 0.056885f,
+ 0.819336f, 0.053741f, 0.812012f, 0.050690f, 0.804688f, 0.047699f, 0.797852f, 0.044800f,
+ 0.790527f, 0.042023f, 0.783691f, 0.039337f, 0.776367f, 0.036804f, 0.768555f, 0.034393f,
+ 0.761230f, 0.032074f, 0.753418f, 0.029922f, 0.745117f, 0.027893f, 0.736816f, 0.025970f,
+ 0.728516f, 0.024170f, 0.719238f, 0.022491f, 0.709961f, 0.020905f, 0.700195f, 0.019440f,
+ 0.689941f, 0.018066f, 0.679688f, 0.016785f, 0.668457f, 0.015587f, 0.657227f, 0.014473f,
+ 0.645996f, 0.013443f, 0.633789f, 0.012474f, 0.621582f, 0.011581f, 0.609375f, 0.010750f,
+ 0.596191f, 0.009972f, 0.583496f, 0.009262f, 0.569824f, 0.008591f, 0.556641f, 0.007973f,
+ 0.542969f, 0.007404f, 0.529297f, 0.006874f, 0.515625f, 0.006378f, 0.501465f, 0.005920f,
+ 0.487793f, 0.005501f, 0.474121f, 0.005108f, 0.460205f, 0.004742f, 0.446289f, 0.004406f,
+ 0.898438f, 0.101440f, 0.898438f, 0.101440f, 0.898438f, 0.101440f, 0.898438f, 0.101440f,
+ 0.897949f, 0.101440f, 0.897949f, 0.101440f, 0.897461f, 0.101440f, 0.896973f, 0.101379f,
+ 0.896973f, 0.101318f, 0.895996f, 0.101135f, 0.895508f, 0.100830f, 0.894043f, 0.100464f,
+ 0.893066f, 0.099854f, 0.890625f, 0.099121f, 0.888184f, 0.098083f, 0.885254f, 0.096802f,
+ 0.882324f, 0.095215f, 0.878418f, 0.093323f, 0.872559f, 0.091125f, 0.869629f, 0.088623f,
+ 0.862793f, 0.085815f, 0.855957f, 0.082764f, 0.850098f, 0.079590f, 0.844727f, 0.076172f,
+ 0.837402f, 0.072693f, 0.831055f, 0.069092f, 0.824219f, 0.065491f, 0.817871f, 0.061981f,
+ 0.811035f, 0.058472f, 0.804688f, 0.055023f, 0.797852f, 0.051697f, 0.791992f, 0.048492f,
+ 0.785645f, 0.045410f, 0.778809f, 0.042480f, 0.771973f, 0.039673f, 0.765625f, 0.037018f,
+ 0.758789f, 0.034515f, 0.750977f, 0.032166f, 0.743652f, 0.029968f, 0.735840f, 0.027878f,
+ 0.727539f, 0.025940f, 0.718750f, 0.024124f, 0.709961f, 0.022430f, 0.700684f, 0.020844f,
+ 0.690918f, 0.019363f, 0.680664f, 0.017975f, 0.670410f, 0.016693f, 0.659180f, 0.015495f,
+ 0.647949f, 0.014389f, 0.636230f, 0.013359f, 0.624512f, 0.012398f, 0.611816f, 0.011505f,
+ 0.599609f, 0.010681f, 0.586426f, 0.009911f, 0.573730f, 0.009201f, 0.560547f, 0.008537f,
+ 0.546875f, 0.007927f, 0.533203f, 0.007355f, 0.519531f, 0.006828f, 0.505859f, 0.006340f,
+ 0.492432f, 0.005890f, 0.478516f, 0.005470f, 0.464844f, 0.005077f, 0.450928f, 0.004719f,
+ 0.885254f, 0.114624f, 0.885254f, 0.114624f, 0.885254f, 0.114624f, 0.885254f, 0.114624f,
+ 0.884766f, 0.114624f, 0.884766f, 0.114563f, 0.884766f, 0.114502f, 0.884277f, 0.114380f,
+ 0.883789f, 0.114258f, 0.883301f, 0.114014f, 0.882324f, 0.113525f, 0.881348f, 0.112976f,
+ 0.879395f, 0.112183f, 0.877441f, 0.111145f, 0.875977f, 0.109802f, 0.872559f, 0.108215f,
+ 0.869141f, 0.106201f, 0.865723f, 0.103821f, 0.860352f, 0.101196f, 0.854492f, 0.098145f,
+ 0.850586f, 0.094849f, 0.845215f, 0.091187f, 0.838379f, 0.087463f, 0.833496f, 0.083496f,
+ 0.826660f, 0.079468f, 0.820801f, 0.075378f, 0.814453f, 0.071289f, 0.809082f, 0.067322f,
+ 0.803711f, 0.063354f, 0.797363f, 0.059540f, 0.791992f, 0.055878f, 0.786133f, 0.052338f,
+ 0.780762f, 0.048950f, 0.774414f, 0.045746f, 0.768555f, 0.042664f, 0.762207f, 0.039795f,
+ 0.755859f, 0.037079f, 0.749023f, 0.034546f, 0.741699f, 0.032135f, 0.734863f, 0.029892f,
+ 0.727051f, 0.027802f, 0.718750f, 0.025833f, 0.710449f, 0.024002f, 0.701172f, 0.022293f,
+ 0.691895f, 0.020706f, 0.682129f, 0.019226f, 0.671875f, 0.017853f, 0.661133f, 0.016571f,
+ 0.650391f, 0.015381f, 0.639160f, 0.014282f, 0.626953f, 0.013252f, 0.615234f, 0.012299f,
+ 0.602539f, 0.011414f, 0.590332f, 0.010597f, 0.577148f, 0.009834f, 0.563965f, 0.009132f,
+ 0.550781f, 0.008476f, 0.537598f, 0.007866f, 0.523926f, 0.007309f, 0.510254f, 0.006786f,
+ 0.496826f, 0.006306f, 0.483154f, 0.005856f, 0.469482f, 0.005440f, 0.455811f, 0.005054f,
+ 0.870605f, 0.129028f, 0.870605f, 0.129028f, 0.870605f, 0.129028f, 0.870605f, 0.129028f,
+ 0.870605f, 0.129028f, 0.870605f, 0.129028f, 0.870117f, 0.128906f, 0.870117f, 0.128784f,
+ 0.869629f, 0.128540f, 0.869141f, 0.128052f, 0.868164f, 0.127563f, 0.867188f, 0.126709f,
+ 0.865723f, 0.125732f, 0.863281f, 0.124329f, 0.862305f, 0.122742f, 0.858887f, 0.120544f,
+ 0.854980f, 0.118103f, 0.850098f, 0.115173f, 0.847168f, 0.111938f, 0.843750f, 0.108276f,
+ 0.836426f, 0.104309f, 0.832031f, 0.100159f, 0.827148f, 0.095764f, 0.821289f, 0.091187f,
+ 0.815918f, 0.086609f, 0.810547f, 0.081970f, 0.806152f, 0.077393f, 0.800781f, 0.072937f,
+ 0.795410f, 0.068542f, 0.790039f, 0.064270f, 0.785645f, 0.060242f, 0.780762f, 0.056335f,
+ 0.775391f, 0.052643f, 0.770020f, 0.049133f, 0.765137f, 0.045807f, 0.759766f, 0.042694f,
+ 0.753906f, 0.039734f, 0.747559f, 0.036987f, 0.740723f, 0.034393f, 0.733887f, 0.031982f,
+ 0.726562f, 0.029739f, 0.719238f, 0.027618f, 0.710449f, 0.025650f, 0.702148f, 0.023834f,
+ 0.692871f, 0.022125f, 0.683594f, 0.020538f, 0.673828f, 0.019058f, 0.663574f, 0.017685f,
+ 0.652832f, 0.016418f, 0.641602f, 0.015244f, 0.629883f, 0.014153f, 0.618164f, 0.013138f,
+ 0.605957f, 0.012192f, 0.593750f, 0.011314f, 0.581055f, 0.010506f, 0.567871f, 0.009750f,
+ 0.555176f, 0.009056f, 0.541504f, 0.008408f, 0.528320f, 0.007809f, 0.514648f, 0.007252f,
+ 0.501465f, 0.006741f, 0.487793f, 0.006260f, 0.474365f, 0.005817f, 0.460938f, 0.005409f,
+ 0.854492f, 0.145020f, 0.854492f, 0.145020f, 0.854492f, 0.145020f, 0.854492f, 0.145020f,
+ 0.854492f, 0.144897f, 0.854492f, 0.144897f, 0.854004f, 0.144653f, 0.854492f, 0.144531f,
+ 0.854004f, 0.144165f, 0.853027f, 0.143555f, 0.852051f, 0.142822f, 0.851074f, 0.141724f,
+ 0.850586f, 0.140503f, 0.848145f, 0.138672f, 0.846191f, 0.136475f, 0.843262f, 0.133911f,
+ 0.839844f, 0.130859f, 0.835449f, 0.127319f, 0.832031f, 0.123474f, 0.828613f, 0.119141f,
+ 0.823242f, 0.114502f, 0.819824f, 0.109558f, 0.813477f, 0.104431f, 0.809570f, 0.099304f,
+ 0.804199f, 0.094055f, 0.799316f, 0.088867f, 0.794922f, 0.083740f, 0.791992f, 0.078735f,
+ 0.786621f, 0.073914f, 0.783203f, 0.069214f, 0.779297f, 0.064758f, 0.774902f, 0.060516f,
+ 0.770508f, 0.056488f, 0.765625f, 0.052673f, 0.761230f, 0.049072f, 0.756348f, 0.045715f,
+ 0.750977f, 0.042511f, 0.745605f, 0.039551f, 0.739746f, 0.036774f, 0.733398f, 0.034180f,
+ 0.726562f, 0.031738f, 0.719238f, 0.029495f, 0.711426f, 0.027390f, 0.703125f, 0.025421f,
+ 0.694336f, 0.023605f, 0.685059f, 0.021912f, 0.675781f, 0.020340f, 0.665527f, 0.018875f,
+ 0.655273f, 0.017517f, 0.644043f, 0.016251f, 0.632812f, 0.015091f, 0.621582f, 0.014008f,
+ 0.609375f, 0.013000f, 0.597168f, 0.012070f, 0.584473f, 0.011200f, 0.571777f, 0.010406f,
+ 0.559082f, 0.009659f, 0.545898f, 0.008972f, 0.532715f, 0.008339f, 0.519531f, 0.007748f,
+ 0.505859f, 0.007198f, 0.492676f, 0.006691f, 0.479248f, 0.006218f, 0.465820f, 0.005783f,
+ 0.837402f, 0.162476f, 0.837402f, 0.162476f, 0.837402f, 0.162476f, 0.837402f, 0.162354f,
+ 0.837402f, 0.162354f, 0.836914f, 0.162231f, 0.836914f, 0.161987f, 0.836426f, 0.161743f,
+ 0.836426f, 0.161133f, 0.835449f, 0.160522f, 0.835449f, 0.159546f, 0.834473f, 0.158203f,
+ 0.833496f, 0.156372f, 0.831055f, 0.154175f, 0.830078f, 0.151489f, 0.826660f, 0.148315f,
+ 0.823242f, 0.144531f, 0.821289f, 0.140381f, 0.817383f, 0.135620f, 0.812012f, 0.130615f,
+ 0.810547f, 0.125122f, 0.805176f, 0.119507f, 0.800293f, 0.113647f, 0.797852f, 0.107788f,
+ 0.792480f, 0.101868f, 0.788574f, 0.096008f, 0.785156f, 0.090332f, 0.782715f, 0.084839f,
+ 0.779297f, 0.079468f, 0.774902f, 0.074341f, 0.772461f, 0.069458f, 0.769531f, 0.064819f,
+ 0.765137f, 0.060486f, 0.761719f, 0.056366f, 0.758301f, 0.052490f, 0.753418f, 0.048828f,
+ 0.749023f, 0.045410f, 0.743652f, 0.042206f, 0.738770f, 0.039215f, 0.732422f, 0.036438f,
+ 0.726074f, 0.033844f, 0.719238f, 0.031433f, 0.711914f, 0.029190f, 0.704102f, 0.027100f,
+ 0.695801f, 0.025146f, 0.687012f, 0.023346f, 0.677734f, 0.021667f, 0.667969f, 0.020111f,
+ 0.657715f, 0.018646f, 0.646973f, 0.017319f, 0.636230f, 0.016068f, 0.624512f, 0.014923f,
+ 0.612793f, 0.013855f, 0.601074f, 0.012863f, 0.588379f, 0.011948f, 0.576172f, 0.011093f,
+ 0.563477f, 0.010300f, 0.550293f, 0.009567f, 0.537109f, 0.008896f, 0.523926f, 0.008263f,
+ 0.510742f, 0.007687f, 0.497559f, 0.007145f, 0.484375f, 0.006645f, 0.470947f, 0.006180f,
+ 0.818359f, 0.181519f, 0.818359f, 0.181519f, 0.818359f, 0.181519f, 0.817871f, 0.181519f,
+ 0.817871f, 0.181396f, 0.817871f, 0.181274f, 0.817871f, 0.181030f, 0.817871f, 0.180542f,
+ 0.817871f, 0.179932f, 0.817383f, 0.178955f, 0.816406f, 0.177612f, 0.815918f, 0.175903f,
+ 0.814941f, 0.173584f, 0.812500f, 0.170898f, 0.811035f, 0.167603f, 0.808594f, 0.163696f,
+ 0.805664f, 0.159180f, 0.802246f, 0.154175f, 0.799805f, 0.148560f, 0.796875f, 0.142700f,
+ 0.792480f, 0.136353f, 0.789551f, 0.129883f, 0.787598f, 0.123230f, 0.782227f, 0.116577f,
+ 0.780273f, 0.109985f, 0.777344f, 0.103516f, 0.774414f, 0.097168f, 0.771973f, 0.091125f,
+ 0.770508f, 0.085205f, 0.767578f, 0.079651f, 0.765625f, 0.074341f, 0.763184f, 0.069336f,
+ 0.760254f, 0.064636f, 0.757812f, 0.060181f, 0.754395f, 0.056000f, 0.750977f, 0.052063f,
+ 0.747559f, 0.048431f, 0.742188f, 0.044983f, 0.737793f, 0.041779f, 0.732422f, 0.038818f,
+ 0.726074f, 0.036041f, 0.719727f, 0.033447f, 0.712891f, 0.031052f, 0.705566f, 0.028824f,
+ 0.697266f, 0.026749f, 0.688965f, 0.024826f, 0.679688f, 0.023041f, 0.670410f, 0.021393f,
+ 0.660645f, 0.019852f, 0.649902f, 0.018433f, 0.639160f, 0.017105f, 0.627930f, 0.015869f,
+ 0.616211f, 0.014748f, 0.604492f, 0.013687f, 0.592773f, 0.012718f, 0.580078f, 0.011818f,
+ 0.567871f, 0.010979f, 0.554688f, 0.010201f, 0.541992f, 0.009483f, 0.528809f, 0.008812f,
+ 0.515625f, 0.008194f, 0.502441f, 0.007626f, 0.489502f, 0.007088f, 0.476318f, 0.006599f,
+ 0.797363f, 0.202393f, 0.797363f, 0.202393f, 0.797363f, 0.202393f, 0.797363f, 0.202393f,
+ 0.797363f, 0.202148f, 0.797363f, 0.202026f, 0.797363f, 0.201660f, 0.797363f, 0.201050f,
+ 0.796875f, 0.200195f, 0.796875f, 0.198975f, 0.796387f, 0.197266f, 0.795898f, 0.195068f,
+ 0.794922f, 0.192261f, 0.792969f, 0.188843f, 0.792480f, 0.184937f, 0.789551f, 0.180298f,
+ 0.787598f, 0.174927f, 0.785645f, 0.168823f, 0.782715f, 0.162231f, 0.779297f, 0.155273f,
+ 0.775879f, 0.148071f, 0.775391f, 0.140747f, 0.772461f, 0.133179f, 0.770508f, 0.125732f,
+ 0.767578f, 0.118347f, 0.766113f, 0.111206f, 0.764648f, 0.104248f, 0.763184f, 0.097595f,
+ 0.762695f, 0.091187f, 0.761719f, 0.085144f, 0.759277f, 0.079407f, 0.758301f, 0.073975f,
+ 0.755859f, 0.068909f, 0.754395f, 0.064087f, 0.751465f, 0.059631f, 0.748535f, 0.055450f,
+ 0.745117f, 0.051514f, 0.741211f, 0.047852f, 0.737305f, 0.044434f, 0.731934f, 0.041260f,
+ 0.726562f, 0.038300f, 0.720215f, 0.035553f, 0.713867f, 0.032990f, 0.706543f, 0.030624f,
+ 0.699219f, 0.028427f, 0.690918f, 0.026382f, 0.682129f, 0.024475f, 0.672852f, 0.022720f,
+ 0.663086f, 0.021088f, 0.652832f, 0.019577f, 0.642578f, 0.018173f, 0.631348f, 0.016876f,
+ 0.620117f, 0.015671f, 0.608398f, 0.014565f, 0.596680f, 0.013535f, 0.584473f, 0.012573f,
+ 0.572266f, 0.011681f, 0.559570f, 0.010857f, 0.546875f, 0.010101f, 0.533691f, 0.009392f,
+ 0.520996f, 0.008736f, 0.507812f, 0.008125f, 0.494629f, 0.007565f, 0.481689f, 0.007042f,
+ 0.774414f, 0.225098f, 0.774414f, 0.225098f, 0.774414f, 0.225098f, 0.774414f, 0.225098f,
+ 0.774414f, 0.224854f, 0.774902f, 0.224609f, 0.774414f, 0.224121f, 0.774414f, 0.223389f,
+ 0.774414f, 0.222290f, 0.773926f, 0.220581f, 0.773926f, 0.218628f, 0.773926f, 0.215942f,
+ 0.773438f, 0.212524f, 0.772461f, 0.208374f, 0.771484f, 0.203491f, 0.770508f, 0.197754f,
+ 0.769043f, 0.191284f, 0.766113f, 0.184204f, 0.763672f, 0.176514f, 0.760742f, 0.168457f,
+ 0.760742f, 0.160278f, 0.757812f, 0.151855f, 0.757812f, 0.143433f, 0.756836f, 0.135132f,
+ 0.754395f, 0.126953f, 0.755371f, 0.119141f, 0.755371f, 0.111511f, 0.754395f, 0.104309f,
+ 0.753418f, 0.097351f, 0.754395f, 0.090820f, 0.753906f, 0.084595f, 0.752441f, 0.078796f,
+ 0.751465f, 0.073303f, 0.750000f, 0.068176f, 0.748535f, 0.063354f, 0.746094f, 0.058899f,
+ 0.743164f, 0.054718f, 0.740234f, 0.050812f, 0.736816f, 0.047150f, 0.731934f, 0.043793f,
+ 0.727051f, 0.040649f, 0.721191f, 0.037720f, 0.714844f, 0.035004f, 0.708008f, 0.032501f,
+ 0.700684f, 0.030167f, 0.692871f, 0.027985f, 0.684570f, 0.025986f, 0.675781f, 0.024124f,
+ 0.666016f, 0.022385f, 0.656250f, 0.020782f, 0.645996f, 0.019302f, 0.635254f, 0.017929f,
+ 0.624023f, 0.016647f, 0.612793f, 0.015480f, 0.601074f, 0.014381f, 0.588867f, 0.013367f,
+ 0.576660f, 0.012428f, 0.563965f, 0.011559f, 0.551270f, 0.010750f, 0.539062f, 0.010002f,
+ 0.525879f, 0.009308f, 0.513184f, 0.008659f, 0.500000f, 0.008064f, 0.487061f, 0.007511f,
+ 0.750000f, 0.249878f, 0.749512f, 0.249878f, 0.750000f, 0.249878f, 0.750000f, 0.249756f,
+ 0.750000f, 0.249512f, 0.750000f, 0.249146f, 0.750000f, 0.248413f, 0.750488f, 0.247559f,
+ 0.750488f, 0.246094f, 0.750488f, 0.244141f, 0.750488f, 0.241577f, 0.750488f, 0.238281f,
+ 0.748535f, 0.234009f, 0.749512f, 0.229004f, 0.749023f, 0.223022f, 0.747070f, 0.216309f,
+ 0.745117f, 0.208496f, 0.743164f, 0.200195f, 0.744629f, 0.191406f, 0.741211f, 0.182251f,
+ 0.741699f, 0.172852f, 0.740234f, 0.163330f, 0.742676f, 0.154053f, 0.741211f, 0.144775f,
+ 0.743652f, 0.135864f, 0.744629f, 0.127197f, 0.743164f, 0.118958f, 0.744629f, 0.111145f,
+ 0.745605f, 0.103638f, 0.746582f, 0.096558f, 0.748047f, 0.089966f, 0.747559f, 0.083679f,
+ 0.747559f, 0.077820f, 0.746582f, 0.072327f, 0.745605f, 0.067261f, 0.744629f, 0.062469f,
+ 0.742676f, 0.058014f, 0.739746f, 0.053864f, 0.735840f, 0.049988f, 0.731934f, 0.046417f,
+ 0.727539f, 0.043091f, 0.722168f, 0.039978f, 0.716309f, 0.037079f, 0.709473f, 0.034424f,
+ 0.702637f, 0.031952f, 0.695312f, 0.029663f, 0.687012f, 0.027542f, 0.678223f, 0.025558f,
+ 0.668945f, 0.023743f, 0.659180f, 0.022049f, 0.649414f, 0.020477f, 0.638672f, 0.019028f,
+ 0.627930f, 0.017670f, 0.616699f, 0.016434f, 0.604980f, 0.015274f, 0.593262f, 0.014198f,
+ 0.581055f, 0.013206f, 0.568848f, 0.012283f, 0.556641f, 0.011429f, 0.543945f, 0.010643f,
+ 0.531250f, 0.009903f, 0.518066f, 0.009224f, 0.505371f, 0.008591f, 0.492676f, 0.008003f,
+ 0.723145f, 0.276611f, 0.723145f, 0.276611f, 0.723145f, 0.276611f, 0.723145f, 0.276611f,
+ 0.723145f, 0.276123f, 0.723145f, 0.275635f, 0.723145f, 0.274902f, 0.723633f, 0.273682f,
+ 0.723633f, 0.271973f, 0.724121f, 0.269531f, 0.724609f, 0.266113f, 0.725098f, 0.262207f,
+ 0.725098f, 0.257080f, 0.724609f, 0.250732f, 0.722656f, 0.243652f, 0.725586f, 0.235474f,
+ 0.724121f, 0.226685f, 0.723145f, 0.216919f, 0.722656f, 0.206787f, 0.720703f, 0.196289f,
+ 0.723145f, 0.185791f, 0.723633f, 0.175171f, 0.724121f, 0.164795f, 0.728027f, 0.154663f,
+ 0.730469f, 0.144897f, 0.731934f, 0.135498f, 0.734863f, 0.126587f, 0.737305f, 0.118103f,
+ 0.739258f, 0.110107f, 0.739746f, 0.102478f, 0.741699f, 0.095398f, 0.743164f, 0.088745f,
+ 0.743652f, 0.082520f, 0.743652f, 0.076660f, 0.743652f, 0.071228f, 0.742676f, 0.066101f,
+ 0.741211f, 0.061401f, 0.739258f, 0.057007f, 0.735840f, 0.052887f, 0.732422f, 0.049103f,
+ 0.728516f, 0.045563f, 0.723145f, 0.042297f, 0.717773f, 0.039246f, 0.711914f, 0.036438f,
+ 0.704590f, 0.033813f, 0.697754f, 0.031403f, 0.689453f, 0.029160f, 0.681152f, 0.027069f,
+ 0.671875f, 0.025146f, 0.662598f, 0.023346f, 0.652832f, 0.021698f, 0.642578f, 0.020157f,
+ 0.631836f, 0.018738f, 0.621094f, 0.017426f, 0.609375f, 0.016205f, 0.597656f, 0.015076f,
+ 0.585938f, 0.014023f, 0.573730f, 0.013054f, 0.561523f, 0.012146f, 0.548828f, 0.011314f,
+ 0.536621f, 0.010536f, 0.523926f, 0.009811f, 0.511230f, 0.009148f, 0.498291f, 0.008530f,
+ 0.693848f, 0.305664f, 0.693848f, 0.305664f, 0.693848f, 0.305664f, 0.693848f, 0.305664f,
+ 0.693848f, 0.305176f, 0.694336f, 0.304443f, 0.694824f, 0.303467f, 0.695312f, 0.302002f,
+ 0.695312f, 0.299561f, 0.696289f, 0.296631f, 0.696777f, 0.292725f, 0.696777f, 0.287598f,
+ 0.697754f, 0.281250f, 0.698242f, 0.273926f, 0.698730f, 0.265137f, 0.697266f, 0.255615f,
+ 0.699707f, 0.245239f, 0.699707f, 0.234131f, 0.700195f, 0.222412f, 0.702637f, 0.210693f,
+ 0.705078f, 0.198853f, 0.708496f, 0.187134f, 0.708984f, 0.175781f, 0.715332f, 0.164673f,
+ 0.718750f, 0.154053f, 0.722168f, 0.143921f, 0.724121f, 0.134277f, 0.727539f, 0.125244f,
+ 0.731934f, 0.116638f, 0.733398f, 0.108582f, 0.736816f, 0.101013f, 0.738281f, 0.093872f,
+ 0.740234f, 0.087219f, 0.741699f, 0.081055f, 0.741211f, 0.075256f, 0.741211f, 0.069885f,
+ 0.740723f, 0.064880f, 0.738281f, 0.060211f, 0.736328f, 0.055908f, 0.732910f, 0.051849f,
+ 0.729004f, 0.048157f, 0.724609f, 0.044678f, 0.719727f, 0.041473f, 0.713379f, 0.038483f,
+ 0.707031f, 0.035736f, 0.699707f, 0.033173f, 0.692383f, 0.030823f, 0.684082f, 0.028625f,
+ 0.675293f, 0.026596f, 0.666016f, 0.024704f, 0.656738f, 0.022964f, 0.646484f, 0.021347f,
+ 0.636230f, 0.019852f, 0.625488f, 0.018463f, 0.614258f, 0.017181f, 0.602539f, 0.015976f,
+ 0.590820f, 0.014877f, 0.578613f, 0.013855f, 0.566895f, 0.012901f, 0.554688f, 0.012024f,
+ 0.541992f, 0.011200f, 0.529297f, 0.010437f, 0.516602f, 0.009735f, 0.503906f, 0.009079f,
+ 0.662598f, 0.337158f, 0.662598f, 0.337158f, 0.662598f, 0.337158f, 0.662598f, 0.336914f,
+ 0.662598f, 0.336670f, 0.663086f, 0.335938f, 0.663086f, 0.334473f, 0.664062f, 0.332520f,
+ 0.665039f, 0.329834f, 0.666016f, 0.325928f, 0.665527f, 0.320801f, 0.667969f, 0.314697f,
+ 0.667480f, 0.306885f, 0.669922f, 0.298096f, 0.669434f, 0.287842f, 0.671387f, 0.276367f,
+ 0.675781f, 0.264404f, 0.675781f, 0.251465f, 0.677734f, 0.238403f, 0.681152f, 0.225342f,
+ 0.686035f, 0.212036f, 0.690430f, 0.199219f, 0.694824f, 0.186768f, 0.700684f, 0.174805f,
+ 0.702637f, 0.163330f, 0.708008f, 0.152466f, 0.714844f, 0.142212f, 0.718750f, 0.132446f,
+ 0.724609f, 0.123291f, 0.728516f, 0.114685f, 0.731445f, 0.106628f, 0.734375f, 0.099121f,
+ 0.736816f, 0.092102f, 0.738770f, 0.085510f, 0.740723f, 0.079407f, 0.740234f, 0.073730f,
+ 0.739258f, 0.068420f, 0.738770f, 0.063538f, 0.736328f, 0.058960f, 0.734375f, 0.054718f,
+ 0.730469f, 0.050781f, 0.726562f, 0.047150f, 0.721191f, 0.043762f, 0.715332f, 0.040619f,
+ 0.709473f, 0.037720f, 0.702637f, 0.035034f, 0.695312f, 0.032532f, 0.687500f, 0.030243f,
+ 0.678711f, 0.028107f, 0.669922f, 0.026123f, 0.660645f, 0.024277f, 0.650391f, 0.022583f,
+ 0.640137f, 0.021011f, 0.629395f, 0.019547f, 0.618652f, 0.018188f, 0.607422f, 0.016937f,
+ 0.595703f, 0.015778f, 0.583984f, 0.014694f, 0.572266f, 0.013695f, 0.560059f, 0.012764f,
+ 0.547852f, 0.011902f, 0.535156f, 0.011101f, 0.522461f, 0.010353f, 0.510254f, 0.009666f,
+ 0.628418f, 0.371338f, 0.628418f, 0.371338f, 0.628418f, 0.371094f, 0.628418f, 0.371094f,
+ 0.628418f, 0.370361f, 0.629395f, 0.369385f, 0.629883f, 0.367920f, 0.630859f, 0.365234f,
+ 0.631836f, 0.361816f, 0.633301f, 0.357178f, 0.634766f, 0.350830f, 0.635742f, 0.343262f,
+ 0.638184f, 0.333984f, 0.640137f, 0.322998f, 0.641113f, 0.311035f, 0.645508f, 0.297852f,
+ 0.647949f, 0.283691f, 0.652344f, 0.269043f, 0.657227f, 0.254395f, 0.662598f, 0.239868f,
+ 0.669922f, 0.225464f, 0.673340f, 0.211426f, 0.680664f, 0.197876f, 0.685547f, 0.184937f,
+ 0.693359f, 0.172729f, 0.700684f, 0.161011f, 0.705566f, 0.150146f, 0.711426f, 0.139771f,
+ 0.718750f, 0.130005f, 0.722168f, 0.120911f, 0.727051f, 0.112427f, 0.732422f, 0.104431f,
+ 0.733887f, 0.097046f, 0.737305f, 0.090088f, 0.738770f, 0.083618f, 0.740234f, 0.077637f,
+ 0.739258f, 0.072083f, 0.738281f, 0.066895f, 0.736816f, 0.062073f, 0.734375f, 0.057648f,
+ 0.731934f, 0.053497f, 0.728027f, 0.049683f, 0.723145f, 0.046112f, 0.717773f, 0.042816f,
+ 0.712402f, 0.039764f, 0.705566f, 0.036957f, 0.698242f, 0.034332f, 0.690430f, 0.031891f,
+ 0.682617f, 0.029663f, 0.673340f, 0.027573f, 0.664551f, 0.025650f, 0.654785f, 0.023865f,
+ 0.644531f, 0.022202f, 0.634277f, 0.020676f, 0.623535f, 0.019257f, 0.612305f, 0.017929f,
+ 0.601074f, 0.016708f, 0.589355f, 0.015579f, 0.577637f, 0.014526f, 0.565430f, 0.013550f,
+ 0.553223f, 0.012642f, 0.541016f, 0.011787f, 0.528809f, 0.011009f, 0.516113f, 0.010277f,
+ 0.591309f, 0.407959f, 0.591797f, 0.407959f, 0.591797f, 0.407959f, 0.591797f, 0.407471f,
+ 0.592285f, 0.406982f, 0.592773f, 0.405762f, 0.593750f, 0.403564f, 0.594727f, 0.400391f,
+ 0.596680f, 0.396240f, 0.598145f, 0.390137f, 0.600098f, 0.382568f, 0.602539f, 0.373047f,
+ 0.604980f, 0.361816f, 0.606934f, 0.348877f, 0.611816f, 0.334473f, 0.616699f, 0.319336f,
+ 0.620605f, 0.302979f, 0.627930f, 0.286865f, 0.634277f, 0.270508f, 0.638672f, 0.254150f,
+ 0.647949f, 0.238525f, 0.654297f, 0.223389f, 0.663086f, 0.208862f, 0.673828f, 0.195068f,
+ 0.680176f, 0.182007f, 0.689941f, 0.169678f, 0.696289f, 0.157959f, 0.705078f, 0.147095f,
+ 0.713867f, 0.136841f, 0.719727f, 0.127197f, 0.724121f, 0.118225f, 0.729980f, 0.109863f,
+ 0.731934f, 0.101990f, 0.735840f, 0.094727f, 0.737305f, 0.087952f, 0.738770f, 0.081604f,
+ 0.740234f, 0.075745f, 0.739258f, 0.070312f, 0.738281f, 0.065247f, 0.735840f, 0.060608f,
+ 0.733398f, 0.056274f, 0.729492f, 0.052246f, 0.725098f, 0.048523f, 0.720703f, 0.045074f,
+ 0.714355f, 0.041870f, 0.708496f, 0.038910f, 0.701660f, 0.036163f, 0.693848f, 0.033630f,
+ 0.686035f, 0.031281f, 0.677734f, 0.029099f, 0.668457f, 0.027069f, 0.659180f, 0.025192f,
+ 0.648926f, 0.023453f, 0.639160f, 0.021851f, 0.628418f, 0.020355f, 0.617676f, 0.018967f,
+ 0.605957f, 0.017685f, 0.594727f, 0.016495f, 0.583008f, 0.015388f, 0.571289f, 0.014366f,
+ 0.559570f, 0.013412f, 0.546875f, 0.012520f, 0.534668f, 0.011696f, 0.522461f, 0.010925f,
+ 0.551758f, 0.447754f, 0.551758f, 0.447754f, 0.552246f, 0.447510f, 0.552246f, 0.447266f,
+ 0.552734f, 0.446289f, 0.553223f, 0.444580f, 0.555176f, 0.441895f, 0.556152f, 0.438232f,
+ 0.558594f, 0.432617f, 0.561035f, 0.425049f, 0.563477f, 0.415527f, 0.566406f, 0.404053f,
+ 0.570312f, 0.390381f, 0.575195f, 0.375000f, 0.578613f, 0.358154f, 0.584473f, 0.340332f,
+ 0.593750f, 0.322266f, 0.600098f, 0.303955f, 0.611328f, 0.286133f, 0.617676f, 0.268555f,
+ 0.629395f, 0.251709f, 0.640625f, 0.235352f, 0.649902f, 0.219849f, 0.661621f, 0.205078f,
+ 0.671387f, 0.191284f, 0.678711f, 0.178223f, 0.688965f, 0.166016f, 0.699707f, 0.154419f,
+ 0.707031f, 0.143555f, 0.714844f, 0.133545f, 0.719727f, 0.124084f, 0.726074f, 0.115295f,
+ 0.731445f, 0.107056f, 0.734863f, 0.099365f, 0.737305f, 0.092285f, 0.739258f, 0.085632f,
+ 0.740234f, 0.079529f, 0.739746f, 0.073792f, 0.739258f, 0.068542f, 0.737793f, 0.063599f,
+ 0.734863f, 0.059082f, 0.731934f, 0.054871f, 0.727539f, 0.050964f, 0.723633f, 0.047394f,
+ 0.717773f, 0.044006f, 0.711426f, 0.040924f, 0.705078f, 0.038055f, 0.697754f, 0.035400f,
+ 0.689941f, 0.032928f, 0.681641f, 0.030655f, 0.672852f, 0.028534f, 0.663574f, 0.026581f,
+ 0.653809f, 0.024750f, 0.644043f, 0.023071f, 0.633301f, 0.021515f, 0.622559f, 0.020050f,
+ 0.611328f, 0.018707f, 0.600098f, 0.017456f, 0.588867f, 0.016296f, 0.577148f, 0.015221f,
+ 0.565430f, 0.014221f, 0.553223f, 0.013290f, 0.541504f, 0.012421f, 0.528809f, 0.011620f,
+ 0.509277f, 0.490234f, 0.509277f, 0.490234f, 0.509277f, 0.489990f, 0.509766f, 0.489502f,
+ 0.510254f, 0.488525f, 0.511230f, 0.486328f, 0.512695f, 0.482910f, 0.514160f, 0.478027f,
+ 0.517578f, 0.470947f, 0.520996f, 0.461670f, 0.523926f, 0.449707f, 0.528809f, 0.435303f,
+ 0.534180f, 0.418945f, 0.540527f, 0.400635f, 0.548340f, 0.381348f, 0.554688f, 0.361328f,
+ 0.566895f, 0.340820f, 0.577637f, 0.320801f, 0.588867f, 0.301270f, 0.601074f, 0.282471f,
+ 0.610352f, 0.264404f, 0.624023f, 0.247070f, 0.637207f, 0.230591f, 0.649414f, 0.215210f,
+ 0.662109f, 0.200562f, 0.672852f, 0.186768f, 0.685547f, 0.173828f, 0.693359f, 0.161743f,
+ 0.702148f, 0.150391f, 0.711426f, 0.139771f, 0.720703f, 0.129883f, 0.726074f, 0.120667f,
+ 0.730469f, 0.112061f, 0.733887f, 0.104065f, 0.738281f, 0.096619f, 0.739258f, 0.089722f,
+ 0.740234f, 0.083252f, 0.741699f, 0.077332f, 0.740723f, 0.071777f, 0.739258f, 0.066711f,
+ 0.736816f, 0.061951f, 0.734375f, 0.057556f, 0.730469f, 0.053497f, 0.726074f, 0.049713f,
+ 0.720703f, 0.046234f, 0.714844f, 0.042999f, 0.708496f, 0.039978f, 0.701172f, 0.037231f,
+ 0.693848f, 0.034637f, 0.685547f, 0.032257f, 0.677246f, 0.030060f, 0.667969f, 0.028000f,
+ 0.658691f, 0.026108f, 0.648926f, 0.024338f, 0.638672f, 0.022705f, 0.627930f, 0.021194f,
+ 0.617188f, 0.019775f, 0.605957f, 0.018463f, 0.594727f, 0.017258f, 0.583008f, 0.016129f,
+ 0.571289f, 0.015076f, 0.559570f, 0.014099f, 0.547852f, 0.013191f, 0.535645f, 0.012337f,
+ 0.463623f, 0.536133f, 0.463623f, 0.536133f, 0.463867f, 0.535645f, 0.464111f, 0.535156f,
+ 0.465088f, 0.533691f, 0.466064f, 0.530762f, 0.468506f, 0.526367f, 0.471191f, 0.520020f,
+ 0.474609f, 0.511230f, 0.478516f, 0.499268f, 0.483643f, 0.484375f, 0.489990f, 0.466797f,
+ 0.495361f, 0.447266f, 0.502441f, 0.425537f, 0.515137f, 0.403564f, 0.526855f, 0.380859f,
+ 0.540039f, 0.358887f, 0.553711f, 0.336914f, 0.564453f, 0.315918f, 0.587891f, 0.295898f,
+ 0.600098f, 0.276611f, 0.610840f, 0.258545f, 0.624512f, 0.241211f, 0.641113f, 0.225098f,
+ 0.657715f, 0.209717f, 0.668457f, 0.195312f, 0.678223f, 0.181763f, 0.687988f, 0.169067f,
+ 0.701172f, 0.157104f, 0.707031f, 0.146118f, 0.715332f, 0.135620f, 0.723145f, 0.125977f,
+ 0.728516f, 0.117126f, 0.734375f, 0.108704f, 0.736328f, 0.100952f, 0.739746f, 0.093750f,
+ 0.741699f, 0.087036f, 0.742188f, 0.080872f, 0.741699f, 0.075134f, 0.741211f, 0.069763f,
+ 0.739258f, 0.064819f, 0.736816f, 0.060272f, 0.733398f, 0.056030f, 0.729004f, 0.052124f,
+ 0.724121f, 0.048492f, 0.718750f, 0.045105f, 0.712402f, 0.041992f, 0.705078f, 0.039093f,
+ 0.698242f, 0.036407f, 0.689941f, 0.033905f, 0.681641f, 0.031616f, 0.672852f, 0.029480f,
+ 0.663574f, 0.027512f, 0.653809f, 0.025665f, 0.644043f, 0.023956f, 0.633301f, 0.022369f,
+ 0.622559f, 0.020889f, 0.611816f, 0.019516f, 0.601074f, 0.018250f, 0.589355f, 0.017059f,
+ 0.578125f, 0.015961f, 0.565918f, 0.014946f, 0.554199f, 0.013992f, 0.542480f, 0.013107f,
+ 0.414551f, 0.584961f, 0.414551f, 0.584961f, 0.414795f, 0.584961f, 0.415039f, 0.583984f,
+ 0.416260f, 0.582031f, 0.418457f, 0.578613f, 0.420166f, 0.572754f, 0.424072f, 0.563965f,
+ 0.428467f, 0.552246f, 0.433838f, 0.537109f, 0.441162f, 0.518066f, 0.448730f, 0.497070f,
+ 0.458984f, 0.473633f, 0.467773f, 0.449219f, 0.480713f, 0.424072f, 0.497559f, 0.399414f,
+ 0.511719f, 0.375244f, 0.529297f, 0.352051f, 0.543945f, 0.329834f, 0.566895f, 0.308838f,
+ 0.581543f, 0.288574f, 0.598633f, 0.269531f, 0.619629f, 0.251465f, 0.635742f, 0.234497f,
+ 0.646973f, 0.218506f, 0.659668f, 0.203369f, 0.674805f, 0.189331f, 0.684570f, 0.176025f,
+ 0.695801f, 0.163696f, 0.707031f, 0.152222f, 0.718750f, 0.141357f, 0.723145f, 0.131348f,
+ 0.729004f, 0.122009f, 0.734375f, 0.113342f, 0.738281f, 0.105286f, 0.741211f, 0.097778f,
+ 0.743164f, 0.090820f, 0.744629f, 0.084412f, 0.744629f, 0.078430f, 0.743652f, 0.072876f,
+ 0.742676f, 0.067749f, 0.739746f, 0.062988f, 0.735840f, 0.058624f, 0.731934f, 0.054535f,
+ 0.727539f, 0.050751f, 0.721680f, 0.047241f, 0.715820f, 0.044006f, 0.709473f, 0.040985f,
+ 0.702148f, 0.038208f, 0.694824f, 0.035614f, 0.686523f, 0.033234f, 0.677734f, 0.031006f,
+ 0.668457f, 0.028946f, 0.659180f, 0.027023f, 0.649414f, 0.025238f, 0.639160f, 0.023590f,
+ 0.628906f, 0.022049f, 0.618164f, 0.020630f, 0.606934f, 0.019287f, 0.595703f, 0.018051f,
+ 0.584473f, 0.016907f, 0.572754f, 0.015839f, 0.561035f, 0.014839f, 0.549316f, 0.013908f,
+ 0.361816f, 0.637695f, 0.361816f, 0.637695f, 0.362061f, 0.637207f, 0.362793f, 0.636230f,
+ 0.364258f, 0.633301f, 0.366455f, 0.628906f, 0.369873f, 0.621094f, 0.374512f, 0.609375f,
+ 0.378906f, 0.593750f, 0.387451f, 0.573730f, 0.396484f, 0.550293f, 0.407471f, 0.524414f,
+ 0.419189f, 0.497314f, 0.433594f, 0.469971f, 0.453613f, 0.442627f, 0.473633f, 0.416016f,
+ 0.488037f, 0.390381f, 0.509277f, 0.365967f, 0.528809f, 0.343262f, 0.549805f, 0.320801f,
+ 0.574707f, 0.299805f, 0.590332f, 0.280029f, 0.609375f, 0.261475f, 0.631836f, 0.243774f,
+ 0.641602f, 0.227173f, 0.659668f, 0.211426f, 0.671387f, 0.196777f, 0.685059f, 0.183105f,
+ 0.698730f, 0.170166f, 0.705078f, 0.158203f, 0.715820f, 0.146973f, 0.723145f, 0.136597f,
+ 0.730469f, 0.126831f, 0.737793f, 0.117920f, 0.740723f, 0.109558f, 0.741699f, 0.101807f,
+ 0.745117f, 0.094604f, 0.747559f, 0.087891f, 0.747070f, 0.081726f, 0.747070f, 0.075989f,
+ 0.744141f, 0.070679f, 0.742676f, 0.065796f, 0.739258f, 0.061218f, 0.735840f, 0.056976f,
+ 0.730957f, 0.053070f, 0.725586f, 0.049438f, 0.719727f, 0.046082f, 0.713867f, 0.042938f,
+ 0.706543f, 0.040070f, 0.699219f, 0.037384f, 0.690918f, 0.034882f, 0.682617f, 0.032562f,
+ 0.673828f, 0.030426f, 0.664551f, 0.028442f, 0.654785f, 0.026581f, 0.645020f, 0.024857f,
+ 0.634766f, 0.023254f, 0.624023f, 0.021774f, 0.613281f, 0.020386f, 0.602051f, 0.019089f,
+ 0.590820f, 0.017899f, 0.579590f, 0.016769f, 0.567871f, 0.015732f, 0.556641f, 0.014755f,
+ 0.305420f, 0.694336f, 0.305420f, 0.694336f, 0.305664f, 0.693848f, 0.306641f, 0.691895f,
+ 0.308105f, 0.687988f, 0.311279f, 0.681152f, 0.316162f, 0.669922f, 0.321777f, 0.654297f,
+ 0.330078f, 0.632812f, 0.344238f, 0.606934f, 0.353027f, 0.578125f, 0.367432f, 0.547852f,
+ 0.385498f, 0.517578f, 0.405273f, 0.487793f, 0.422852f, 0.458496f, 0.448730f, 0.431152f,
+ 0.473633f, 0.404541f, 0.493896f, 0.379639f, 0.519531f, 0.355469f, 0.539551f, 0.332520f,
+ 0.563477f, 0.310791f, 0.583008f, 0.290283f, 0.604004f, 0.270752f, 0.626953f, 0.252686f,
+ 0.642090f, 0.235352f, 0.657715f, 0.218994f, 0.672852f, 0.203857f, 0.686523f, 0.189575f,
+ 0.699219f, 0.176270f, 0.707031f, 0.163818f, 0.717285f, 0.152344f, 0.723633f, 0.141602f,
+ 0.730469f, 0.131592f, 0.739258f, 0.122375f, 0.741699f, 0.113708f, 0.745605f, 0.105713f,
+ 0.747559f, 0.098267f, 0.748047f, 0.091370f, 0.749023f, 0.085022f, 0.748535f, 0.079102f,
+ 0.747070f, 0.073608f, 0.746582f, 0.068542f, 0.742188f, 0.063843f, 0.739258f, 0.059448f,
+ 0.734375f, 0.055420f, 0.730469f, 0.051666f, 0.724609f, 0.048187f, 0.717773f, 0.044952f,
+ 0.710938f, 0.041962f, 0.704102f, 0.039154f, 0.695801f, 0.036591f, 0.687988f, 0.034180f,
+ 0.679199f, 0.031952f, 0.670410f, 0.029892f, 0.660645f, 0.027969f, 0.650879f, 0.026184f,
+ 0.640625f, 0.024521f, 0.630371f, 0.022964f, 0.619629f, 0.021515f, 0.608887f, 0.020172f,
+ 0.598145f, 0.018921f, 0.586914f, 0.017761f, 0.575195f, 0.016663f, 0.563965f, 0.015656f,
+ 0.244995f, 0.754395f, 0.245117f, 0.754395f, 0.245483f, 0.753418f, 0.246704f, 0.750977f,
+ 0.249634f, 0.745117f, 0.253662f, 0.734863f, 0.260010f, 0.717773f, 0.268555f, 0.694336f,
+ 0.277344f, 0.665527f, 0.292480f, 0.632812f, 0.309814f, 0.599121f, 0.331787f, 0.565918f,
+ 0.352539f, 0.533203f, 0.376465f, 0.501953f, 0.405518f, 0.472412f, 0.433838f, 0.444336f,
+ 0.456787f, 0.417236f, 0.488281f, 0.391357f, 0.510254f, 0.366211f, 0.540039f, 0.343018f,
+ 0.564941f, 0.320557f, 0.579590f, 0.299561f, 0.606445f, 0.279541f, 0.627441f, 0.260498f,
+ 0.638184f, 0.242676f, 0.666504f, 0.226074f, 0.670898f, 0.210327f, 0.687988f, 0.195801f,
+ 0.700684f, 0.182129f, 0.706055f, 0.169312f, 0.718262f, 0.157471f, 0.727539f, 0.146362f,
+ 0.735840f, 0.136108f, 0.738770f, 0.126587f, 0.743164f, 0.117737f, 0.746582f, 0.109497f,
+ 0.751953f, 0.101868f, 0.751953f, 0.094788f, 0.753906f, 0.088257f, 0.752930f, 0.082153f,
+ 0.750977f, 0.076538f, 0.749512f, 0.071289f, 0.745605f, 0.066406f, 0.742188f, 0.061951f,
+ 0.738281f, 0.057770f, 0.734375f, 0.053894f, 0.729004f, 0.050293f, 0.722656f, 0.046967f,
+ 0.715332f, 0.043854f, 0.708496f, 0.040985f, 0.701172f, 0.038330f, 0.693359f, 0.035828f,
+ 0.684570f, 0.033539f, 0.676270f, 0.031403f, 0.666992f, 0.029404f, 0.657227f, 0.027542f,
+ 0.646973f, 0.025818f, 0.636719f, 0.024200f, 0.626465f, 0.022705f, 0.615723f, 0.021301f,
+ 0.604980f, 0.020004f, 0.593750f, 0.018784f, 0.582520f, 0.017654f, 0.571289f, 0.016586f,
+ 0.180542f, 0.818848f, 0.180664f, 0.818848f, 0.181274f, 0.817383f, 0.183350f, 0.812988f,
+ 0.187134f, 0.802734f, 0.193237f, 0.784180f, 0.201416f, 0.757324f, 0.214355f, 0.723145f,
+ 0.231445f, 0.685547f, 0.248901f, 0.648438f, 0.272217f, 0.611816f, 0.302979f, 0.577148f,
+ 0.329834f, 0.544922f, 0.364258f, 0.514160f, 0.394043f, 0.484619f, 0.425781f, 0.456055f,
+ 0.456543f, 0.428467f, 0.481934f, 0.402344f, 0.512207f, 0.376709f, 0.540039f, 0.352783f,
+ 0.566406f, 0.329346f, 0.579102f, 0.307617f, 0.607910f, 0.286865f, 0.627930f, 0.267822f,
+ 0.645996f, 0.249512f, 0.661621f, 0.232178f, 0.677734f, 0.216309f, 0.691406f, 0.201172f,
+ 0.702637f, 0.187256f, 0.711426f, 0.174194f, 0.721680f, 0.161987f, 0.730957f, 0.150879f,
+ 0.736328f, 0.140259f, 0.742188f, 0.130493f, 0.746582f, 0.121582f, 0.750488f, 0.113159f,
+ 0.751953f, 0.105347f, 0.752930f, 0.098083f, 0.756836f, 0.091370f, 0.755859f, 0.085144f,
+ 0.755371f, 0.079346f, 0.752441f, 0.073975f, 0.750488f, 0.069031f, 0.746582f, 0.064392f,
+ 0.743652f, 0.060120f, 0.737793f, 0.056152f, 0.733398f, 0.052460f, 0.727051f, 0.049011f,
+ 0.720215f, 0.045837f, 0.713867f, 0.042847f, 0.706543f, 0.040100f, 0.699219f, 0.037537f,
+ 0.690430f, 0.035156f, 0.682129f, 0.032928f, 0.672852f, 0.030884f, 0.663086f, 0.028961f,
+ 0.653809f, 0.027161f, 0.644043f, 0.025497f, 0.633301f, 0.023941f, 0.622559f, 0.022491f,
+ 0.612305f, 0.021133f, 0.601074f, 0.019867f, 0.590332f, 0.018692f, 0.579102f, 0.017578f,
+ 0.111816f, 0.888184f, 0.112000f, 0.887207f, 0.112976f, 0.883789f, 0.115845f, 0.873047f,
+ 0.122864f, 0.849609f, 0.133301f, 0.813477f, 0.147217f, 0.770996f, 0.167236f, 0.728027f,
+ 0.196411f, 0.688965f, 0.222290f, 0.653320f, 0.258057f, 0.619629f, 0.293457f, 0.587402f,
+ 0.328613f, 0.556152f, 0.361328f, 0.524902f, 0.392578f, 0.495850f, 0.430420f, 0.466064f,
+ 0.459961f, 0.437744f, 0.482422f, 0.410889f, 0.511230f, 0.385010f, 0.536621f, 0.359863f,
+ 0.568848f, 0.336182f, 0.592773f, 0.313721f, 0.614258f, 0.293213f, 0.626953f, 0.273193f,
+ 0.646484f, 0.254639f, 0.657227f, 0.237427f, 0.683105f, 0.221191f, 0.693359f, 0.205933f,
+ 0.698242f, 0.191772f, 0.709473f, 0.178589f, 0.724609f, 0.166260f, 0.733398f, 0.154907f,
+ 0.739746f, 0.144165f, 0.745605f, 0.134399f, 0.750977f, 0.125122f, 0.753906f, 0.116577f,
+ 0.754883f, 0.108704f, 0.758301f, 0.101257f, 0.759766f, 0.094482f, 0.757812f, 0.088074f,
+ 0.759766f, 0.082092f, 0.758301f, 0.076660f, 0.756348f, 0.071594f, 0.752441f, 0.066833f,
+ 0.748047f, 0.062469f, 0.741699f, 0.058380f, 0.736816f, 0.054596f, 0.732910f, 0.051086f,
+ 0.726074f, 0.047791f, 0.719727f, 0.044769f, 0.711914f, 0.041901f, 0.704590f, 0.039276f,
+ 0.696289f, 0.036804f, 0.688477f, 0.034546f, 0.678711f, 0.032410f, 0.669922f, 0.030411f,
+ 0.660156f, 0.028564f, 0.650391f, 0.026840f, 0.640625f, 0.025223f, 0.630371f, 0.023727f,
+ 0.619629f, 0.022324f, 0.608887f, 0.020996f, 0.597656f, 0.019775f, 0.586914f, 0.018631f,
+ 0.038452f, 0.960938f, 0.039124f, 0.957520f, 0.042480f, 0.933594f, 0.051575f, 0.879395f,
+ 0.069275f, 0.824219f, 0.091064f, 0.785156f, 0.126343f, 0.753906f, 0.154419f, 0.725586f,
+ 0.192139f, 0.695312f, 0.234375f, 0.663086f, 0.273438f, 0.630371f, 0.305908f, 0.597656f,
+ 0.338379f, 0.565430f, 0.379150f, 0.532227f, 0.413818f, 0.501465f, 0.444336f, 0.471191f,
+ 0.471436f, 0.442383f, 0.504395f, 0.414795f, 0.531250f, 0.388672f, 0.547363f, 0.364014f,
+ 0.579590f, 0.340088f, 0.603516f, 0.317627f, 0.622559f, 0.297119f, 0.635742f, 0.276855f,
+ 0.669434f, 0.258301f, 0.670410f, 0.241089f, 0.685547f, 0.224854f, 0.699219f, 0.209717f,
+ 0.712402f, 0.195190f, 0.720703f, 0.182373f, 0.729980f, 0.169678f, 0.746582f, 0.158325f,
+ 0.744629f, 0.147705f, 0.748535f, 0.137695f, 0.760254f, 0.128296f, 0.757812f, 0.119629f,
+ 0.761230f, 0.111755f, 0.762207f, 0.104248f, 0.764160f, 0.097290f, 0.763184f, 0.090881f,
+ 0.762207f, 0.084900f, 0.760742f, 0.079285f, 0.759766f, 0.074097f, 0.755859f, 0.069275f,
+ 0.752930f, 0.064758f, 0.747559f, 0.060669f, 0.742676f, 0.056793f, 0.737305f, 0.053131f,
+ 0.731445f, 0.049774f, 0.725586f, 0.046661f, 0.718262f, 0.043732f, 0.710449f, 0.041077f,
+ 0.702637f, 0.038544f, 0.694336f, 0.036163f, 0.685547f, 0.033966f, 0.676758f, 0.031921f,
+ 0.667480f, 0.030014f, 0.657715f, 0.028229f, 0.647461f, 0.026566f, 0.637207f, 0.025009f,
+ 0.626953f, 0.023544f, 0.616699f, 0.022186f, 0.605957f, 0.020920f, 0.594727f, 0.019730f
+};
+
+static float btdf_split_sum_ggx[32][64 * 64] = {
+ {
+ 0.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f,
+ 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.999512f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.039917f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f,
+ 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.999512f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ },
+ {
+ 0.000122f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000122f, 0.004147f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.897949f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000732f, 0.996094f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.002439f,
+ 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000366f, 0.078308f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.001098f, 0.992188f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.999512f,
+ 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.005001f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f,
+ 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000732f, 0.902344f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.002928f, 0.997070f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 1.000000f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000732f, 0.301758f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 1.000000f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.002562f, 0.996094f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000732f, 0.433594f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000244f, 0.004021f, 0.996582f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.001098f, 0.949219f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000610f,
+ 0.012039f, 0.998047f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.002073f, 0.993652f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000854f, 0.725586f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000610f, 0.011856f, 0.998047f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.002905f, 0.995117f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.001098f, 0.978027f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000732f, 0.314941f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000731f, 0.017670f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000366f, 0.005852f, 0.997559f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.003050f,
+ 0.996094f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.001957f, 0.993652f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.001586f, 0.990234f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.001220f, 0.986816f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.001220f, 0.984375f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f,
+ 0.001098f, 0.985352f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.001220f, 0.989258f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.001341f, 0.993652f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.001586f, 0.996094f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.002802f, 0.997559f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000117f, 0.000122f, 0.000122f,
+ 0.000243f, 0.006088f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000366f, 0.026321f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000732f, 0.892578f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000975f, 0.993652f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.002317f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.017944f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000731f, 0.983887f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000122f, 0.000122f, 0.001653f, 0.998535f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.026108f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000732f, 0.995605f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.003777f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000365f, 0.991211f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.002195f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000364f, 0.993164f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.002672f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000360f, 0.998047f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000122f, 0.000122f, 0.017075f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000731f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.997070f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.006874f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000480f, 0.999512f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.996582f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000067f, 0.005440f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000365f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.995605f, 0.995117f,
+ 0.995117f, 0.995605f, 0.995117f, 0.995117f,
+ },
+ {
+ 0.003168f, 0.995605f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 1.000000f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000976f, 0.053314f, 0.994629f, 0.998535f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000122f, 0.000122f, 0.000732f, 0.003660f,
+ 0.653809f, 0.995117f, 0.998047f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000488f, 0.001463f, 0.010452f, 0.947266f, 0.995605f, 0.998535f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000365f, 0.000853f, 0.002928f, 0.037750f,
+ 0.980957f, 0.996582f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000243f, 0.000610f, 0.001342f, 0.006100f, 0.314453f, 0.989746f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000487f, 0.001091f, 0.002317f, 0.015839f, 0.910645f,
+ 0.993652f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000366f, 0.000732f, 0.001463f, 0.005302f, 0.068909f, 0.977539f, 0.995605f, 0.998047f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000732f, 0.001098f, 0.002560f, 0.011551f, 0.658691f, 0.989746f,
+ 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000366f,
+ 0.000732f, 0.001585f, 0.004868f, 0.041077f, 0.958984f, 0.994141f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000732f, 0.001215f, 0.002802f, 0.010834f, 0.441895f, 0.987305f, 0.996094f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000242f, 0.000488f, 0.000850f,
+ 0.001586f, 0.004753f, 0.039154f, 0.948242f, 0.993652f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000366f, 0.000732f, 0.001220f, 0.003159f, 0.012032f, 0.480713f, 0.985840f, 0.996094f, 0.998047f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000240f, 0.000731f, 0.001097f, 0.001950f,
+ 0.005966f, 0.054413f, 0.957520f, 0.994141f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000486f, 0.000732f, 0.001534f, 0.003536f, 0.016937f, 0.726562f, 0.988281f, 0.996582f, 0.998047f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000365f, 0.000732f, 0.001098f, 0.002192f, 0.008278f,
+ 0.125244f, 0.974121f, 0.994629f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000365f, 0.000731f, 0.000947f, 0.001828f, 0.005314f, 0.031677f, 0.916016f, 0.991699f, 0.997070f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000488f, 0.000732f, 0.001339f, 0.003294f, 0.014389f, 0.562012f,
+ 0.985840f, 0.996094f, 0.998047f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000487f,
+ 0.000732f, 0.001098f, 0.002310f, 0.008163f, 0.123779f, 0.973633f, 0.994629f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000365f, 0.000732f, 0.001097f, 0.002071f, 0.005669f, 0.041199f, 0.937988f, 0.992676f,
+ 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000118f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000366f, 0.000728f, 0.000732f,
+ 0.001585f, 0.004143f, 0.020813f, 0.813965f, 0.989746f, 0.996582f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000116f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000488f, 0.000732f, 0.001220f, 0.003292f, 0.012581f, 0.446533f, 0.984863f, 0.996094f, 0.998047f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000471f, 0.000732f, 0.001220f, 0.002796f,
+ 0.009338f, 0.161865f, 0.977051f, 0.995117f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000365f, 0.000732f, 0.001098f, 0.002285f, 0.006870f, 0.074097f, 0.965820f, 0.994141f, 0.997559f, 0.998535f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000366f, 0.000731f, 0.001086f, 0.001945f, 0.005238f, 0.043732f,
+ 0.947754f, 0.993652f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000366f,
+ 0.000730f, 0.000893f, 0.001826f, 0.004871f, 0.030411f, 0.922852f, 0.992188f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000609f, 0.000732f, 0.001407f, 0.004375f, 0.023758f, 0.892090f, 0.992188f,
+ 0.997070f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000605f, 0.000732f,
+ 0.001579f, 0.003941f, 0.020767f, 0.862793f, 0.991699f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000238f, 0.000483f, 0.000732f, 0.001449f, 0.003654f, 0.018951f, 0.847656f, 0.991699f, 0.997559f, 0.998535f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000233f, 0.000485f, 0.000732f, 0.001308f, 0.003353f,
+ 0.018997f, 0.855469f, 0.991699f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000118f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000487f, 0.000732f, 0.001292f, 0.003649f, 0.019791f, 0.881836f, 0.992188f, 0.997559f, 0.998535f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000432f, 0.000732f, 0.001220f, 0.003635f, 0.021912f, 0.916992f,
+ 0.993652f, 0.997559f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000116f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000487f,
+ 0.000732f, 0.001245f, 0.004002f, 0.028107f, 0.946289f, 0.994141f, 0.998047f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000085f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000475f, 0.000732f, 0.001611f, 0.004581f, 0.040466f, 0.966309f, 0.995605f, 0.998535f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000487f, 0.000732f, 0.001703f,
+ 0.005589f, 0.073486f, 0.979980f, 0.996094f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000475f, 0.000732f, 0.001706f, 0.006809f, 0.198730f, 0.987305f, 0.997559f, 0.998535f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000488f, 0.000732f, 0.002071f, 0.009590f, 0.647949f,
+ 0.992188f, 0.997559f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000710f, 0.001093f, 0.002541f, 0.015533f, 0.922852f, 0.995117f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000116f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000242f, 0.000728f, 0.001218f, 0.003387f, 0.034454f, 0.975586f, 0.996582f, 0.998535f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000365f, 0.000731f, 0.001219f,
+ 0.004959f, 0.161865f, 0.989746f, 0.998047f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000366f, 0.000731f, 0.001767f, 0.009331f, 0.849121f, 0.994629f, 0.998535f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000487f, 0.000732f, 0.002644f, 0.024231f, 0.977051f,
+ 0.997559f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000685f, 0.001217f, 0.004139f, 0.195435f, 0.992676f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000362f, 0.000731f, 0.001570f, 0.010086f, 0.944824f, 0.997070f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000365f, 0.000745f, 0.002781f,
+ 0.051758f, 0.990723f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000599f, 0.001176f, 0.006641f, 0.899414f, 0.997070f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000731f, 0.002066f, 0.032654f, 0.991211f, 0.998535f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000448f,
+ 0.001088f, 0.005440f, 0.918457f, 0.997070f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000725f, 0.001822f, 0.038452f, 0.994141f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000329f, 0.000848f, 0.005672f, 0.972168f,
+ 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000581f, 0.001982f, 0.155273f, 0.997070f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000330f, 0.000848f, 0.009247f, 0.992676f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000589f, 0.002625f,
+ 0.958496f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.001199f, 0.083374f, 0.998047f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000716f, 0.007244f, 0.996582f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f,
+ 0.002277f, 0.991211f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000070f, 0.000121f, 0.000122f, 0.000122f, 0.000854f, 0.950684f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000111f, 0.000121f, 0.000122f, 0.000475f, 0.067139f, 0.999512f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000118f, 0.000122f,
+ 0.000002f, 0.005859f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000014f, 0.001376f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000572f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000077f, 0.000002f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000103f, 0.992188f, 0.991699f, 0.991699f, 0.992188f, 0.992188f, 0.991699f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.940430f, 0.940430f,
+ 0.940918f, 0.940918f, 0.940430f, 0.940430f,
+ },
+ {
+ 0.014023f, 0.979492f, 0.994629f, 0.997070f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000488f, 0.004757f, 0.163330f, 0.975098f, 0.993164f, 0.996582f, 0.997559f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000610f, 0.002928f, 0.017166f,
+ 0.563965f, 0.978027f, 0.992676f, 0.996094f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000364f, 0.000732f, 0.002192f, 0.006573f, 0.044952f, 0.830566f, 0.980957f, 0.992676f, 0.996094f, 0.997070f, 0.998047f,
+ 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000366f, 0.000854f, 0.001586f, 0.004253f, 0.014313f, 0.130371f,
+ 0.919922f, 0.984375f, 0.993652f, 0.996094f, 0.997070f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000488f,
+ 0.000854f, 0.001342f, 0.003025f, 0.007305f, 0.028870f, 0.407715f, 0.954590f, 0.987305f, 0.993652f, 0.996094f, 0.997070f, 0.998047f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000609f, 0.000842f, 0.000976f, 0.002193f, 0.005112f, 0.012505f, 0.066589f, 0.768066f,
+ 0.970703f, 0.989746f, 0.994629f, 0.996582f, 0.997070f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000244f, 0.000599f, 0.000609f, 0.000976f,
+ 0.001829f, 0.003046f, 0.007256f, 0.023499f, 0.194946f, 0.908691f, 0.979980f, 0.991699f, 0.995117f, 0.996582f, 0.997559f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000244f, 0.000488f, 0.000609f, 0.000976f, 0.001583f, 0.002647f, 0.004726f, 0.012169f, 0.050537f, 0.568359f, 0.954102f,
+ 0.985840f, 0.993164f, 0.995605f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000488f, 0.000610f, 0.000975f, 0.001211f, 0.001946f,
+ 0.003532f, 0.007793f, 0.022446f, 0.139648f, 0.856445f, 0.974121f, 0.989746f, 0.994141f, 0.996094f, 0.997559f, 0.998047f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000241f,
+ 0.000310f, 0.000609f, 0.000807f, 0.001098f, 0.001822f, 0.002794f, 0.005699f, 0.012878f, 0.047821f, 0.469238f, 0.941406f, 0.982910f,
+ 0.991699f, 0.995117f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000244f, 0.000609f, 0.000732f, 0.001098f, 0.001461f, 0.002274f, 0.004025f,
+ 0.008247f, 0.023254f, 0.135254f, 0.833984f, 0.969727f, 0.987793f, 0.993652f, 0.995605f, 0.997070f, 0.998047f, 0.998535f, 0.998535f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000207f, 0.000244f, 0.000609f,
+ 0.000610f, 0.001096f, 0.001098f, 0.002071f, 0.003370f, 0.006172f, 0.014442f, 0.052795f, 0.486572f, 0.940430f, 0.981934f, 0.991699f,
+ 0.994629f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000485f, 0.000610f, 0.001080f, 0.001098f, 0.001742f, 0.002668f, 0.004692f, 0.010147f,
+ 0.028076f, 0.168701f, 0.854004f, 0.970703f, 0.988770f, 0.993652f, 0.996094f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000487f, 0.000610f, 0.000731f,
+ 0.001098f, 0.001413f, 0.002411f, 0.003895f, 0.007072f, 0.017242f, 0.069580f, 0.605957f, 0.948730f, 0.983398f, 0.992188f, 0.995117f,
+ 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000244f, 0.000244f, 0.000609f, 0.000610f, 0.001094f, 0.001337f, 0.001828f, 0.003275f, 0.005814f, 0.012054f, 0.036987f,
+ 0.270752f, 0.899414f, 0.975586f, 0.989746f, 0.993652f, 0.996094f, 0.997070f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000241f, 0.000365f, 0.000597f, 0.000610f, 0.000970f, 0.001098f,
+ 0.001815f, 0.002771f, 0.005009f, 0.008888f, 0.023804f, 0.115845f, 0.775879f, 0.962891f, 0.986328f, 0.993164f, 0.995605f, 0.997070f,
+ 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000244f, 0.000536f, 0.000731f, 0.000937f, 0.001203f, 0.001581f, 0.002186f, 0.004005f, 0.007061f, 0.016830f, 0.061218f, 0.522949f,
+ 0.940430f, 0.981934f, 0.991211f, 0.994629f, 0.996582f, 0.997559f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000363f, 0.000487f, 0.000731f, 0.000732f, 0.001097f, 0.001339f, 0.002071f,
+ 0.003498f, 0.005947f, 0.012390f, 0.037964f, 0.268799f, 0.896973f, 0.975586f, 0.989258f, 0.994141f, 0.996094f, 0.997070f, 0.998047f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000366f,
+ 0.000609f, 0.000610f, 0.001094f, 0.001215f, 0.002056f, 0.003183f, 0.004742f, 0.009880f, 0.026337f, 0.139526f, 0.813477f, 0.966309f,
+ 0.986816f, 0.993164f, 0.996094f, 0.997070f, 0.997559f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000163f, 0.000363f, 0.000600f, 0.000731f, 0.001088f, 0.001216f, 0.001616f, 0.002640f, 0.004402f,
+ 0.008156f, 0.019669f, 0.083191f, 0.664062f, 0.953125f, 0.984375f, 0.992188f, 0.995117f, 0.997070f, 0.998047f, 0.998535f, 0.998535f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000244f, 0.000523f, 0.000731f,
+ 0.000732f, 0.001097f, 0.001690f, 0.002169f, 0.003998f, 0.006939f, 0.015808f, 0.055634f, 0.471191f, 0.935059f, 0.980957f, 0.991211f,
+ 0.995117f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000336f, 0.000486f, 0.000731f, 0.000732f, 0.001097f, 0.001558f, 0.002069f, 0.003525f, 0.006058f, 0.013062f,
+ 0.040894f, 0.306396f, 0.910156f, 0.978027f, 0.990234f, 0.994141f, 0.996582f, 0.997559f, 0.998535f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000113f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000360f, 0.000515f, 0.000731f, 0.000731f, 0.001094f,
+ 0.001219f, 0.002148f, 0.003159f, 0.005577f, 0.011360f, 0.031952f, 0.203979f, 0.874512f, 0.973633f, 0.989258f, 0.994141f, 0.996582f,
+ 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000325f, 0.000366f, 0.000731f, 0.000731f, 0.001093f, 0.001219f, 0.001820f, 0.002916f, 0.005291f, 0.009758f, 0.026352f, 0.145020f,
+ 0.832520f, 0.969238f, 0.988281f, 0.993652f, 0.996094f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000440f, 0.000605f, 0.000731f, 0.001086f, 0.001097f, 0.001646f,
+ 0.002670f, 0.004230f, 0.008835f, 0.022415f, 0.112183f, 0.786133f, 0.966309f, 0.987793f, 0.993652f, 0.996094f, 0.997559f, 0.998047f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000272f, 0.000358f,
+ 0.000565f, 0.000731f, 0.000790f, 0.001210f, 0.001573f, 0.002434f, 0.004360f, 0.008102f, 0.020660f, 0.092896f, 0.741699f, 0.962891f,
+ 0.987305f, 0.993164f, 0.996094f, 0.997070f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000364f, 0.000723f, 0.000731f, 0.000731f, 0.001216f, 0.001698f, 0.002510f, 0.003998f,
+ 0.007484f, 0.018463f, 0.082336f, 0.709961f, 0.961426f, 0.986816f, 0.993652f, 0.996094f, 0.997559f, 0.998535f, 0.998535f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000242f, 0.000362f, 0.000704f, 0.000730f,
+ 0.000845f, 0.001096f, 0.001513f, 0.002302f, 0.003941f, 0.007168f, 0.017746f, 0.076782f, 0.693848f, 0.961426f, 0.987305f, 0.993652f,
+ 0.996094f, 0.997559f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000364f, 0.000579f, 0.000728f, 0.000731f, 0.001096f, 0.001491f, 0.002069f, 0.003899f, 0.007195f, 0.017059f,
+ 0.075439f, 0.701172f, 0.962402f, 0.987793f, 0.993652f, 0.996094f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000357f, 0.000482f, 0.000730f, 0.000731f, 0.001094f,
+ 0.001334f, 0.002230f, 0.003708f, 0.007217f, 0.017410f, 0.079163f, 0.730469f, 0.965820f, 0.988281f, 0.994141f, 0.996582f, 0.998047f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000112f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000238f,
+ 0.000243f, 0.000365f, 0.000729f, 0.000731f, 0.001095f, 0.001330f, 0.002066f, 0.003637f, 0.007118f, 0.018112f, 0.087708f, 0.775391f,
+ 0.969238f, 0.989258f, 0.994629f, 0.997070f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000073f, 0.000121f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000323f, 0.000390f, 0.000729f, 0.000731f, 0.001094f, 0.001332f, 0.002275f,
+ 0.003782f, 0.007252f, 0.019379f, 0.105042f, 0.827637f, 0.973145f, 0.990723f, 0.994629f, 0.997070f, 0.998047f, 0.998535f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000114f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000240f, 0.000369f,
+ 0.000729f, 0.000731f, 0.001093f, 0.001330f, 0.002209f, 0.003937f, 0.007896f, 0.021805f, 0.137207f, 0.876953f, 0.979004f, 0.991699f,
+ 0.995605f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000272f, 0.000479f, 0.000727f, 0.000731f, 0.001085f, 0.001331f, 0.002291f, 0.004105f, 0.008446f,
+ 0.025024f, 0.202271f, 0.916504f, 0.982910f, 0.993164f, 0.996094f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000120f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000360f, 0.000469f, 0.000681f, 0.000731f,
+ 0.001092f, 0.001331f, 0.002184f, 0.004227f, 0.009521f, 0.030899f, 0.335205f, 0.945312f, 0.986816f, 0.993652f, 0.996582f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000116f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000241f, 0.000429f, 0.000726f, 0.000731f, 0.001091f, 0.001649f, 0.002464f, 0.004810f, 0.010895f, 0.041931f, 0.563477f,
+ 0.963867f, 0.989746f, 0.995117f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000101f, 0.000120f,
+ 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000288f, 0.000481f, 0.000720f, 0.000731f, 0.001093f, 0.001571f,
+ 0.002735f, 0.005405f, 0.013199f, 0.064880f, 0.786133f, 0.976562f, 0.992188f, 0.995605f, 0.997559f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000112f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000240f,
+ 0.000481f, 0.000727f, 0.000731f, 0.001093f, 0.001655f, 0.003132f, 0.005909f, 0.017181f, 0.123169f, 0.904297f, 0.984375f, 0.993652f,
+ 0.996582f, 0.998047f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000110f, 0.000120f, 0.000121f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000264f, 0.000392f, 0.000727f, 0.000835f, 0.001196f, 0.001765f, 0.003252f, 0.007343f,
+ 0.024521f, 0.304199f, 0.954102f, 0.989258f, 0.995605f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000034f, 0.000119f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000235f, 0.000375f, 0.000728f,
+ 0.000822f, 0.001095f, 0.002024f, 0.003952f, 0.009193f, 0.040894f, 0.694824f, 0.975586f, 0.992676f, 0.996582f, 0.998047f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000112f, 0.000121f, 0.000121f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000307f, 0.000475f, 0.000728f, 0.000943f, 0.001216f, 0.002283f, 0.004829f, 0.013008f, 0.092224f, 0.908203f,
+ 0.986328f, 0.995117f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000073f, 0.000118f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000240f, 0.000576f, 0.000728f, 0.001073f, 0.001569f,
+ 0.002668f, 0.005947f, 0.020889f, 0.331543f, 0.965820f, 0.992188f, 0.996582f, 0.998047f, 0.998535f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000100f, 0.000120f, 0.000121f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000362f, 0.000630f, 0.000729f, 0.001087f, 0.001567f, 0.003241f, 0.008240f, 0.043793f, 0.824219f, 0.984375f, 0.994629f, 0.997559f,
+ 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000075f, 0.000119f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000363f, 0.000689f, 0.000730f, 0.001185f, 0.002022f, 0.004108f, 0.013702f,
+ 0.161011f, 0.957031f, 0.991699f, 0.996582f, 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000105f, 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000156f, 0.000372f, 0.000689f,
+ 0.000730f, 0.001198f, 0.002651f, 0.006214f, 0.028854f, 0.750000f, 0.984375f, 0.995605f, 0.998047f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000102f,
+ 0.000118f, 0.000120f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000472f, 0.000724f, 0.000966f, 0.001658f, 0.003397f, 0.010582f, 0.116028f, 0.959473f, 0.993164f,
+ 0.997559f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000111f, 0.000119f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000130f, 0.000479f, 0.000726f, 0.001163f, 0.002157f,
+ 0.004829f, 0.024338f, 0.776855f, 0.987793f, 0.996582f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000097f, 0.000117f,
+ 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000219f, 0.000580f, 0.000728f, 0.001203f, 0.002872f, 0.009109f, 0.130371f, 0.972168f, 0.995117f, 0.998047f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000112f, 0.000118f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000333f, 0.000681f, 0.000940f, 0.001629f, 0.004120f, 0.025467f, 0.890625f,
+ 0.991699f, 0.997559f, 0.999512f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000083f, 0.000116f, 0.000120f,
+ 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000353f, 0.000722f,
+ 0.000961f, 0.002403f, 0.009354f, 0.295166f, 0.985840f, 0.997070f, 0.999512f, 0.999023f, 0.999512f, 0.999023f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000105f, 0.000118f, 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000130f, 0.000427f, 0.000605f, 0.001345f, 0.004620f, 0.041229f, 0.966797f, 0.996094f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000074f, 0.000114f, 0.000119f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000089f, 0.000562f, 0.000942f, 0.002352f, 0.012459f,
+ 0.854004f, 0.994141f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000103f, 0.000117f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000007f, 0.000002f,
+ 0.000231f, 0.000596f, 0.001180f, 0.005474f, 0.211426f, 0.991211f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000111f, 0.000118f, 0.000120f, 0.000121f,
+ 0.000121f, 0.000122f, 0.000029f, 0.000004f, 0.000001f, 0.000348f, 0.000896f, 0.002764f, 0.032562f, 0.984375f, 0.998535f, 0.998535f,
+ 0.999023f, 0.998535f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000089f, 0.000116f, 0.000119f, 0.000121f, 0.000121f, 0.000121f, 0.000013f, 0.000003f, 0.000075f, 0.000586f, 0.001508f,
+ 0.010292f, 0.963379f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000107f, 0.000118f, 0.000120f, 0.000121f, 0.000116f,
+ 0.000008f, 0.000002f, 0.000233f, 0.000857f, 0.004566f, 0.834961f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000083f, 0.000114f, 0.000119f, 0.000120f, 0.000060f, 0.000005f, 0.000001f, 0.000557f, 0.002064f, 0.182373f, 0.997559f, 0.997559f,
+ 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000103f, 0.000117f, 0.000120f, 0.000024f, 0.000003f, 0.000168f,
+ 0.000968f, 0.026428f, 0.996582f, 0.997070f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000047f,
+ 0.000110f, 0.000118f, 0.000017f, 0.000002f, 0.000513f, 0.006870f, 0.995605f, 0.995605f, 0.995117f, 0.995117f, 0.995117f, 0.995117f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000096f, 0.000115f, 0.000011f, 0.000042f, 0.001919f, 0.992676f, 0.992676f,
+ 0.992676f, 0.992676f, 0.992676f, 0.992676f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000044f, 0.000109f,
+ 0.000008f, 0.000314f, 0.985840f, 0.985840f, 0.985840f, 0.985840f, 0.986328f, 0.985840f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000089f, 0.000060f, 0.964355f, 0.964355f, 0.963867f, 0.963867f, 0.963379f, 0.964355f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000022f, 0.818848f, 0.819824f,
+ 0.819336f, 0.819824f, 0.819824f, 0.819824f,
+ },
+ {
+ 0.038849f, 0.941406f, 0.984375f, 0.992188f, 0.994141f, 0.996094f, 0.996582f, 0.997070f, 0.998047f, 0.998047f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 1.000000f, 1.000000f, 1.000000f, 0.999512f, 0.001582f, 0.014984f, 0.262451f, 0.930664f, 0.979980f, 0.989258f, 0.993164f, 0.995117f,
+ 0.996094f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 0.000244f, 0.002317f, 0.009003f, 0.047180f,
+ 0.524902f, 0.936523f, 0.978027f, 0.988281f, 0.992188f, 0.994629f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f,
+ 0.000122f, 0.001098f, 0.002560f, 0.006824f, 0.020493f, 0.108826f, 0.715820f, 0.946289f, 0.978516f, 0.988281f, 0.992188f, 0.994141f,
+ 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000607f, 0.001098f, 0.002310f, 0.005646f, 0.012825f, 0.040131f, 0.231201f,
+ 0.825195f, 0.954590f, 0.979980f, 0.988281f, 0.992188f, 0.994141f, 0.995117f, 0.996582f, 0.996582f, 0.997559f, 0.998047f, 0.998047f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000244f, 0.000609f, 0.001341f,
+ 0.002310f, 0.004208f, 0.008865f, 0.021591f, 0.074585f, 0.439209f, 0.885742f, 0.962402f, 0.981934f, 0.989258f, 0.992676f, 0.994141f,
+ 0.995605f, 0.996582f, 0.997070f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f,
+ 0.000000f, 0.000122f, 0.000483f, 0.000610f, 0.001460f, 0.002192f, 0.003994f, 0.007030f, 0.013847f, 0.036316f, 0.146362f, 0.661621f,
+ 0.921875f, 0.969238f, 0.983398f, 0.989746f, 0.993164f, 0.994141f, 0.995605f, 0.996582f, 0.996582f, 0.997559f, 0.998047f, 0.998047f,
+ 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000243f, 0.000604f, 0.000730f, 0.001307f, 0.001944f, 0.003017f,
+ 0.004997f, 0.009834f, 0.021606f, 0.063416f, 0.295410f, 0.808594f, 0.944336f, 0.974609f, 0.985352f, 0.990234f, 0.993652f, 0.995117f,
+ 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000366f,
+ 0.000495f, 0.000731f, 0.001217f, 0.001823f, 0.002796f, 0.004398f, 0.007656f, 0.015366f, 0.035828f, 0.119263f, 0.531738f, 0.886230f,
+ 0.958496f, 0.979004f, 0.986816f, 0.991699f, 0.993652f, 0.995117f, 0.996094f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000244f, 0.000366f, 0.000607f, 0.000731f, 0.001211f, 0.001650f, 0.002441f, 0.003975f, 0.006207f,
+ 0.011536f, 0.023315f, 0.060822f, 0.242798f, 0.744141f, 0.927734f, 0.969238f, 0.982422f, 0.989258f, 0.992188f, 0.994141f, 0.995605f,
+ 0.996094f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.998535f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000211f, 0.000455f, 0.000486f, 0.000853f,
+ 0.001081f, 0.001810f, 0.002426f, 0.003759f, 0.005501f, 0.009094f, 0.016876f, 0.037109f, 0.114075f, 0.475586f, 0.862305f, 0.951172f,
+ 0.975586f, 0.985840f, 0.990234f, 0.992676f, 0.995117f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000364f, 0.000366f, 0.000464f, 0.000731f, 0.001093f, 0.001577f, 0.002235f, 0.002798f, 0.004841f, 0.007637f, 0.013008f,
+ 0.025635f, 0.063965f, 0.238403f, 0.720215f, 0.919434f, 0.965820f, 0.981445f, 0.987793f, 0.991211f, 0.993652f, 0.995117f, 0.996094f,
+ 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000238f, 0.000609f, 0.000712f, 0.000974f, 0.000976f, 0.001507f,
+ 0.002031f, 0.002680f, 0.004066f, 0.006294f, 0.010284f, 0.018326f, 0.040924f, 0.124146f, 0.485596f, 0.859375f, 0.949707f, 0.975586f,
+ 0.984375f, 0.989746f, 0.992676f, 0.994629f, 0.995605f, 0.996582f, 0.997070f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000113f, 0.000487f,
+ 0.000488f, 0.000610f, 0.000961f, 0.000976f, 0.001337f, 0.001705f, 0.002663f, 0.003521f, 0.005417f, 0.008408f, 0.014809f, 0.028793f,
+ 0.073120f, 0.270996f, 0.741699f, 0.922363f, 0.965332f, 0.980957f, 0.987793f, 0.991699f, 0.993652f, 0.995117f, 0.996094f, 0.997070f,
+ 0.997070f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000122f, 0.000244f, 0.000224f, 0.000486f, 0.000609f, 0.000610f, 0.000973f, 0.000975f, 0.001306f, 0.001703f, 0.002350f,
+ 0.003239f, 0.004848f, 0.007122f, 0.011955f, 0.021820f, 0.048859f, 0.152710f, 0.554199f, 0.875977f, 0.953125f, 0.976562f, 0.985352f,
+ 0.990234f, 0.993164f, 0.994629f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000234f, 0.000244f, 0.000485f, 0.000488f, 0.000610f,
+ 0.000969f, 0.000975f, 0.001335f, 0.001693f, 0.001991f, 0.002811f, 0.004097f, 0.006397f, 0.009903f, 0.017303f, 0.035034f, 0.094421f,
+ 0.354736f, 0.795898f, 0.933594f, 0.969238f, 0.981934f, 0.988281f, 0.991699f, 0.993652f, 0.995117f, 0.996094f, 0.997070f, 0.997559f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000244f, 0.000244f, 0.000480f, 0.000608f, 0.000488f, 0.000922f, 0.000975f, 0.000976f, 0.001339f, 0.001827f, 0.002674f, 0.003891f,
+ 0.005688f, 0.008324f, 0.014320f, 0.026917f, 0.064392f, 0.216431f, 0.668945f, 0.904785f, 0.959961f, 0.978516f, 0.986816f, 0.990723f,
+ 0.993652f, 0.994141f, 0.996094f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000188f, 0.000220f, 0.000480f, 0.000608f, 0.000609f, 0.000876f, 0.000975f,
+ 0.000976f, 0.001454f, 0.002068f, 0.002649f, 0.003481f, 0.004757f, 0.007801f, 0.012230f, 0.021698f, 0.046814f, 0.138306f, 0.506348f,
+ 0.859375f, 0.947754f, 0.974121f, 0.984375f, 0.989746f, 0.992188f, 0.994141f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f,
+ 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f,
+ 0.000446f, 0.000487f, 0.000609f, 0.000731f, 0.000973f, 0.000975f, 0.001310f, 0.001823f, 0.002304f, 0.002869f, 0.004890f, 0.006813f,
+ 0.010475f, 0.017731f, 0.036163f, 0.095337f, 0.353516f, 0.792480f, 0.932129f, 0.968262f, 0.982422f, 0.988770f, 0.992188f, 0.993652f,
+ 0.995605f, 0.996094f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000241f, 0.000362f, 0.000487f, 0.000609f, 0.000609f, 0.000973f, 0.001213f, 0.001419f,
+ 0.001807f, 0.002068f, 0.002794f, 0.004070f, 0.005917f, 0.009140f, 0.015129f, 0.029053f, 0.070068f, 0.242554f, 0.700684f, 0.911621f,
+ 0.961914f, 0.979492f, 0.987305f, 0.991211f, 0.993164f, 0.995117f, 0.995605f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000243f, 0.000483f, 0.000603f,
+ 0.000609f, 0.000730f, 0.001076f, 0.000975f, 0.001327f, 0.001598f, 0.002056f, 0.002848f, 0.003519f, 0.005589f, 0.008041f, 0.013321f,
+ 0.024155f, 0.054718f, 0.171875f, 0.590332f, 0.885742f, 0.955566f, 0.977051f, 0.985840f, 0.990723f, 0.993164f, 0.994629f, 0.995605f,
+ 0.997070f, 0.997070f, 0.997559f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000192f, 0.000122f, 0.000244f, 0.000483f, 0.000606f, 0.000608f, 0.000731f, 0.000953f, 0.001095f, 0.001258f, 0.001575f, 0.002066f,
+ 0.002594f, 0.003857f, 0.004734f, 0.007683f, 0.011642f, 0.021179f, 0.044464f, 0.127930f, 0.476807f, 0.850586f, 0.947266f, 0.974121f,
+ 0.984375f, 0.989746f, 0.992676f, 0.994141f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998535f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000229f, 0.000239f, 0.000244f, 0.000343f, 0.000483f, 0.000608f, 0.000609f,
+ 0.000857f, 0.000973f, 0.001097f, 0.001571f, 0.002041f, 0.002399f, 0.002922f, 0.004471f, 0.006836f, 0.010643f, 0.018661f, 0.037354f,
+ 0.100037f, 0.378418f, 0.810547f, 0.937988f, 0.971191f, 0.983887f, 0.989258f, 0.992188f, 0.994141f, 0.995605f, 0.996582f, 0.997070f,
+ 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000161f,
+ 0.000230f, 0.000244f, 0.000486f, 0.000607f, 0.000609f, 0.000819f, 0.000972f, 0.000975f, 0.001431f, 0.001945f, 0.002283f, 0.003031f,
+ 0.004238f, 0.006424f, 0.009995f, 0.016068f, 0.032104f, 0.081360f, 0.302246f, 0.765625f, 0.928223f, 0.968750f, 0.982422f, 0.988770f,
+ 0.992676f, 0.994629f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000240f, 0.000240f, 0.000244f, 0.000450f, 0.000607f, 0.000609f, 0.000731f, 0.001084f,
+ 0.000974f, 0.001341f, 0.001910f, 0.002254f, 0.003216f, 0.004017f, 0.005692f, 0.008980f, 0.014832f, 0.028854f, 0.069641f, 0.248657f,
+ 0.719238f, 0.918945f, 0.965820f, 0.981445f, 0.988770f, 0.992188f, 0.994629f, 0.995605f, 0.996094f, 0.997070f, 0.997559f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000360f,
+ 0.000461f, 0.000607f, 0.000608f, 0.000731f, 0.001086f, 0.001202f, 0.001307f, 0.001592f, 0.002066f, 0.003134f, 0.003990f, 0.005611f,
+ 0.008133f, 0.013680f, 0.025986f, 0.061462f, 0.211670f, 0.676758f, 0.910156f, 0.963867f, 0.980957f, 0.988281f, 0.991699f, 0.994629f,
+ 0.995605f, 0.996582f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000240f, 0.000243f, 0.000482f, 0.000604f, 0.000608f, 0.000730f, 0.001040f, 0.001188f, 0.001287f,
+ 0.001574f, 0.002064f, 0.002613f, 0.003721f, 0.005428f, 0.008018f, 0.013161f, 0.024200f, 0.055573f, 0.186401f, 0.642578f, 0.904785f,
+ 0.962402f, 0.980469f, 0.987793f, 0.991699f, 0.994141f, 0.995605f, 0.996582f, 0.997070f, 0.998047f, 0.998535f, 0.998535f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000480f, 0.000602f,
+ 0.000721f, 0.000705f, 0.000907f, 0.001094f, 0.001096f, 0.001493f, 0.002058f, 0.002607f, 0.003639f, 0.004826f, 0.007595f, 0.012413f,
+ 0.022171f, 0.051697f, 0.171143f, 0.619629f, 0.899414f, 0.961426f, 0.980957f, 0.987793f, 0.992188f, 0.994629f, 0.995605f, 0.996582f,
+ 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000172f, 0.000232f, 0.000243f, 0.000244f, 0.000576f, 0.000711f, 0.000608f, 0.000767f, 0.001089f, 0.001213f, 0.001509f, 0.002029f,
+ 0.002684f, 0.003550f, 0.005161f, 0.007107f, 0.011871f, 0.021545f, 0.049347f, 0.163086f, 0.609863f, 0.900391f, 0.962891f, 0.980957f,
+ 0.988281f, 0.992676f, 0.994629f, 0.996094f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000210f, 0.000122f, 0.000337f, 0.000290f, 0.000594f, 0.000726f, 0.000730f,
+ 0.000731f, 0.001090f, 0.001212f, 0.001506f, 0.002029f, 0.002335f, 0.003489f, 0.005077f, 0.007000f, 0.011398f, 0.021027f, 0.048218f,
+ 0.161133f, 0.614258f, 0.903809f, 0.963379f, 0.981934f, 0.988770f, 0.992188f, 0.994629f, 0.996094f, 0.997070f, 0.997559f, 0.998047f,
+ 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000281f, 0.000440f, 0.000683f, 0.000726f, 0.000730f, 0.000731f, 0.001087f, 0.001095f, 0.001485f, 0.001793f, 0.002214f, 0.002991f,
+ 0.004951f, 0.006912f, 0.011162f, 0.020905f, 0.048187f, 0.165527f, 0.633789f, 0.910156f, 0.965820f, 0.982422f, 0.989746f, 0.993164f,
+ 0.995117f, 0.996094f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000241f, 0.000243f, 0.000480f, 0.000725f, 0.000697f, 0.000731f, 0.001007f,
+ 0.001094f, 0.001360f, 0.001795f, 0.002161f, 0.003244f, 0.004871f, 0.006966f, 0.011330f, 0.020706f, 0.049591f, 0.178345f, 0.667969f,
+ 0.918457f, 0.968262f, 0.983887f, 0.990234f, 0.993652f, 0.995605f, 0.996582f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000086f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000243f,
+ 0.000465f, 0.000592f, 0.000729f, 0.000730f, 0.001079f, 0.001093f, 0.001332f, 0.001885f, 0.002129f, 0.003254f, 0.004818f, 0.006889f,
+ 0.011429f, 0.021957f, 0.052521f, 0.201294f, 0.714355f, 0.929199f, 0.972168f, 0.985352f, 0.991211f, 0.994141f, 0.995605f, 0.997070f,
+ 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000115f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000184f, 0.000241f, 0.000347f, 0.000453f, 0.000579f, 0.000728f, 0.000729f, 0.001034f, 0.001093f, 0.001292f,
+ 0.001857f, 0.002131f, 0.003296f, 0.004826f, 0.006958f, 0.011726f, 0.023071f, 0.057983f, 0.239258f, 0.767578f, 0.939453f, 0.976074f,
+ 0.987305f, 0.992676f, 0.994629f, 0.996094f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000088f, 0.000119f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000191f, 0.000242f, 0.000425f, 0.000558f,
+ 0.000723f, 0.000730f, 0.001058f, 0.001092f, 0.001297f, 0.001653f, 0.002352f, 0.003124f, 0.004860f, 0.007072f, 0.012131f, 0.024551f,
+ 0.066406f, 0.300537f, 0.820312f, 0.951172f, 0.979492f, 0.988281f, 0.993164f, 0.995117f, 0.996582f, 0.997070f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000119f,
+ 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000227f, 0.000239f, 0.000341f, 0.000359f, 0.000587f, 0.000605f, 0.000729f, 0.001040f, 0.001185f, 0.001275f, 0.001849f, 0.002390f,
+ 0.003399f, 0.005001f, 0.007404f, 0.012871f, 0.027237f, 0.079529f, 0.395264f, 0.868164f, 0.960938f, 0.982910f, 0.990234f, 0.993164f,
+ 0.995605f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000211f, 0.000239f, 0.000307f, 0.000394f, 0.000704f, 0.000711f, 0.000728f,
+ 0.001001f, 0.001088f, 0.001204f, 0.001713f, 0.002367f, 0.003151f, 0.004639f, 0.007820f, 0.014084f, 0.030609f, 0.102722f, 0.527344f,
+ 0.906250f, 0.969727f, 0.985840f, 0.991699f, 0.994629f, 0.996094f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000117f, 0.000115f, 0.000121f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000196f,
+ 0.000332f, 0.000363f, 0.000686f, 0.000719f, 0.000723f, 0.000963f, 0.001089f, 0.001290f, 0.001849f, 0.002394f, 0.003458f, 0.004833f,
+ 0.008301f, 0.015579f, 0.036926f, 0.143188f, 0.676270f, 0.934570f, 0.976562f, 0.988281f, 0.992676f, 0.995605f, 0.996582f, 0.998047f,
+ 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000102f, 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000311f, 0.000345f, 0.000479f, 0.000723f, 0.000728f, 0.000934f, 0.001085f,
+ 0.001282f, 0.001821f, 0.002399f, 0.003355f, 0.005524f, 0.008881f, 0.017807f, 0.047058f, 0.222046f, 0.803223f, 0.954102f, 0.981445f,
+ 0.990723f, 0.994141f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000090f, 0.000116f, 0.000121f, 0.000121f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000201f, 0.000239f, 0.000358f,
+ 0.000618f, 0.000719f, 0.000727f, 0.000863f, 0.001087f, 0.001350f, 0.001945f, 0.002689f, 0.003731f, 0.005817f, 0.010033f, 0.021332f,
+ 0.064514f, 0.374512f, 0.885254f, 0.969238f, 0.986328f, 0.992676f, 0.995605f, 0.996582f, 0.998047f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000086f, 0.000117f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000164f, 0.000238f, 0.000353f, 0.000596f, 0.000591f, 0.000727f, 0.000901f, 0.001085f, 0.001266f, 0.001767f,
+ 0.002663f, 0.003914f, 0.006153f, 0.011612f, 0.026871f, 0.100525f, 0.605957f, 0.934082f, 0.978027f, 0.989746f, 0.994141f, 0.996094f,
+ 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999023f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000107f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000195f, 0.000323f, 0.000339f, 0.000461f, 0.000706f,
+ 0.000726f, 0.000845f, 0.001086f, 0.001298f, 0.001843f, 0.003027f, 0.004387f, 0.007011f, 0.013832f, 0.036530f, 0.183228f, 0.805664f,
+ 0.959961f, 0.984863f, 0.991699f, 0.995605f, 0.997070f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000117f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000224f, 0.000336f, 0.000464f, 0.000708f, 0.000726f, 0.000965f, 0.001083f, 0.001458f, 0.002180f, 0.003096f, 0.004425f,
+ 0.008377f, 0.017639f, 0.056610f, 0.390869f, 0.909180f, 0.975586f, 0.989746f, 0.994141f, 0.996582f, 0.998047f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000110f, 0.000113f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000135f, 0.000336f, 0.000467f, 0.000713f, 0.000725f, 0.000959f,
+ 0.001191f, 0.001287f, 0.001939f, 0.003231f, 0.005306f, 0.009888f, 0.024414f, 0.105835f, 0.709961f, 0.955078f, 0.984863f, 0.993164f,
+ 0.996094f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000061f, 0.000089f,
+ 0.000118f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000309f,
+ 0.000299f, 0.000460f, 0.000710f, 0.000724f, 0.000997f, 0.001073f, 0.001410f, 0.002117f, 0.003506f, 0.006031f, 0.012863f, 0.038391f,
+ 0.260742f, 0.892090f, 0.975098f, 0.990723f, 0.995117f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000085f, 0.000110f, 0.000118f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000317f, 0.000499f, 0.000706f, 0.000599f, 0.000851f, 0.001069f, 0.001633f,
+ 0.002367f, 0.003918f, 0.007580f, 0.017929f, 0.074646f, 0.645508f, 0.956055f, 0.986328f, 0.994141f, 0.996582f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000099f, 0.000113f,
+ 0.000119f, 0.000119f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000160f, 0.000326f, 0.000308f,
+ 0.000578f, 0.000602f, 0.000921f, 0.001071f, 0.001807f, 0.002783f, 0.004620f, 0.010017f, 0.029465f, 0.211792f, 0.896484f, 0.979004f,
+ 0.992188f, 0.996094f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000027f, 0.000103f, 0.000114f, 0.000118f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000090f, 0.000212f, 0.000309f, 0.000586f, 0.000602f, 0.000937f, 0.001147f, 0.002031f, 0.003237f, 0.006134f,
+ 0.014969f, 0.063171f, 0.665527f, 0.964355f, 0.989258f, 0.995117f, 0.999023f, 0.998535f, 0.999023f, 0.999023f, 0.998535f, 0.999023f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000018f, 0.000103f, 0.000113f,
+ 0.000117f, 0.000119f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000004f, 0.000002f, 0.000199f, 0.000390f, 0.000586f, 0.000665f,
+ 0.000946f, 0.001365f, 0.002207f, 0.003767f, 0.008308f, 0.025955f, 0.227661f, 0.924316f, 0.984863f, 0.994141f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000098f, 0.000109f, 0.000117f, 0.000119f, 0.000120f, 0.000120f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000011f, 0.000005f, 0.000003f,
+ 0.000002f, 0.000193f, 0.000388f, 0.000586f, 0.000659f, 0.000952f, 0.001580f, 0.002762f, 0.005363f, 0.013153f, 0.066589f, 0.781738f,
+ 0.977051f, 0.993164f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000075f, 0.000112f,
+ 0.000116f, 0.000118f, 0.000119f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f,
+ 0.000088f, 0.000026f, 0.000010f, 0.000005f, 0.000003f, 0.000002f, 0.000186f, 0.000407f, 0.000586f, 0.000760f, 0.000986f, 0.001796f,
+ 0.003275f, 0.007565f, 0.026794f, 0.363281f, 0.959473f, 0.990723f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000010f, 0.000090f, 0.000110f, 0.000115f, 0.000117f, 0.000119f, 0.000120f, 0.000120f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000077f, 0.000023f, 0.000011f, 0.000005f, 0.000003f, 0.000002f, 0.000158f,
+ 0.000407f, 0.000587f, 0.000826f, 0.001264f, 0.002174f, 0.004894f, 0.013359f, 0.098511f, 0.911133f, 0.987793f, 0.998047f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000084f, 0.000107f,
+ 0.000114f, 0.000117f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000093f, 0.000024f,
+ 0.000011f, 0.000005f, 0.000003f, 0.000002f, 0.000220f, 0.000476f, 0.000585f, 0.000913f, 0.001374f, 0.002951f, 0.007511f, 0.034973f,
+ 0.736328f, 0.982910f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000056f, 0.000102f, 0.000112f, 0.000116f, 0.000117f, 0.000119f, 0.000120f, 0.000120f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000075f, 0.000025f, 0.000010f, 0.000005f, 0.000003f, 0.000034f, 0.000222f, 0.000491f, 0.000589f,
+ 0.001020f, 0.001881f, 0.004669f, 0.015717f, 0.298340f, 0.974609f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000048f, 0.000095f,
+ 0.000106f, 0.000114f, 0.000117f, 0.000118f, 0.000119f, 0.000120f, 0.000120f, 0.000121f, 0.000089f, 0.000029f, 0.000012f, 0.000006f,
+ 0.000003f, 0.000002f, 0.000223f, 0.000525f, 0.000687f, 0.001122f, 0.002672f, 0.008255f, 0.079590f, 0.954590f, 0.996582f, 0.996582f,
+ 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000077f, 0.000104f, 0.000112f, 0.000115f, 0.000117f, 0.000119f, 0.000119f,
+ 0.000120f, 0.000109f, 0.000031f, 0.000013f, 0.000006f, 0.000003f, 0.000002f, 0.000254f, 0.000550f, 0.000846f, 0.001545f, 0.004223f,
+ 0.027771f, 0.901855f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000037f,
+ 0.000090f, 0.000107f, 0.000113f, 0.000116f, 0.000118f, 0.000119f, 0.000120f, 0.000041f, 0.000015f, 0.000007f, 0.000004f, 0.000002f,
+ 0.000271f, 0.000563f, 0.000786f, 0.002211f, 0.012207f, 0.711426f, 0.994629f, 0.994629f, 0.995117f, 0.994629f, 0.994629f, 0.994629f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000028f, 0.000083f, 0.000102f, 0.000110f, 0.000114f, 0.000117f, 0.000118f,
+ 0.000052f, 0.000019f, 0.000008f, 0.000004f, 0.000002f, 0.000314f, 0.000444f, 0.001049f, 0.005669f, 0.266846f, 0.993164f, 0.993652f,
+ 0.993164f, 0.993652f, 0.993164f, 0.993164f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000048f, 0.000089f, 0.000106f, 0.000112f, 0.000115f, 0.000077f, 0.000026f, 0.000010f, 0.000005f, 0.000079f, 0.000425f, 0.000405f,
+ 0.002468f, 0.064209f, 0.990234f, 0.990723f, 0.990234f, 0.990234f, 0.990234f, 0.991211f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000020f, 0.000075f, 0.000098f, 0.000108f, 0.000113f, 0.000044f,
+ 0.000016f, 0.000006f, 0.000027f, 0.000270f, 0.000825f, 0.018448f, 0.986328f, 0.986328f, 0.986328f, 0.986328f, 0.986328f, 0.986328f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000049f, 0.000085f, 0.000102f, 0.000070f, 0.000022f, 0.000008f, 0.000133f, 0.000295f, 0.005318f, 0.978516f, 0.979004f,
+ 0.977539f, 0.977539f, 0.978027f, 0.978516f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000066f, 0.000092f, 0.000036f, 0.000011f,
+ 0.000135f, 0.000925f, 0.959473f, 0.959961f, 0.959961f, 0.959473f, 0.959961f, 0.959473f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000027f, 0.000065f, 0.000016f, 0.000109f, 0.907715f, 0.907227f, 0.907715f, 0.907227f, 0.907715f, 0.907715f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000017f, 0.711914f, 0.712402f,
+ 0.711426f, 0.711426f, 0.711914f, 0.712402f,
+ },
+ {
+ 0.076172f, 0.877441f, 0.964355f, 0.980957f, 0.987305f, 0.990723f, 0.992676f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f,
+ 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.003897f, 0.033173f, 0.320557f, 0.863770f, 0.953613f, 0.975586f, 0.984863f, 0.988770f,
+ 0.991211f, 0.992676f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.997559f, 0.997559f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000975f, 0.005951f, 0.020935f, 0.093140f,
+ 0.501465f, 0.873047f, 0.950684f, 0.973145f, 0.981934f, 0.986816f, 0.990234f, 0.992188f, 0.993164f, 0.994629f, 0.995605f, 0.996094f,
+ 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998047f, 0.998535f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000610f, 0.002430f, 0.006081f, 0.015915f, 0.045593f, 0.179810f, 0.635254f, 0.889648f, 0.951172f, 0.972168f, 0.981445f, 0.986328f,
+ 0.989746f, 0.991699f, 0.993652f, 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.001219f, 0.002796f, 0.006172f, 0.012848f, 0.028458f, 0.081177f, 0.301758f,
+ 0.733398f, 0.905273f, 0.953613f, 0.972168f, 0.981445f, 0.986328f, 0.989258f, 0.991699f, 0.993652f, 0.994141f, 0.995117f, 0.996094f,
+ 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000731f, 0.001706f, 0.003166f,
+ 0.005470f, 0.010406f, 0.020813f, 0.047089f, 0.136719f, 0.449951f, 0.803223f, 0.919434f, 0.957520f, 0.973633f, 0.981934f, 0.986328f,
+ 0.989746f, 0.991699f, 0.993164f, 0.994629f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000244f, 0.000366f, 0.001214f, 0.001894f, 0.003159f, 0.005108f, 0.008720f, 0.015839f, 0.031586f, 0.074951f, 0.224121f, 0.596680f,
+ 0.851074f, 0.932617f, 0.962402f, 0.975586f, 0.982910f, 0.987305f, 0.989746f, 0.991699f, 0.993164f, 0.994141f, 0.995117f, 0.995605f,
+ 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000366f, 0.000731f, 0.000976f, 0.001827f, 0.002987f, 0.004757f, 0.007988f,
+ 0.013023f, 0.023544f, 0.048431f, 0.120239f, 0.352783f, 0.717285f, 0.887207f, 0.943848f, 0.966309f, 0.978027f, 0.983887f, 0.987305f,
+ 0.990234f, 0.992188f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.998047f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000434f, 0.000488f, 0.000704f,
+ 0.001218f, 0.002190f, 0.002783f, 0.004723f, 0.006878f, 0.011040f, 0.018372f, 0.034241f, 0.073242f, 0.194336f, 0.510742f, 0.803711f,
+ 0.912598f, 0.952637f, 0.970703f, 0.979004f, 0.984863f, 0.988281f, 0.991211f, 0.992676f, 0.994141f, 0.994629f, 0.995605f, 0.996094f,
+ 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000243f, 0.000488f, 0.000488f, 0.000916f, 0.001219f, 0.002308f, 0.002914f, 0.004124f, 0.006523f, 0.009537f, 0.014793f,
+ 0.025833f, 0.050446f, 0.116089f, 0.312744f, 0.661133f, 0.860840f, 0.931641f, 0.960449f, 0.974121f, 0.981445f, 0.986328f, 0.989258f,
+ 0.991211f, 0.992676f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000121f, 0.000356f, 0.000488f, 0.000609f, 0.000944f, 0.001339f, 0.002296f,
+ 0.002964f, 0.003880f, 0.005676f, 0.008476f, 0.012909f, 0.020874f, 0.036926f, 0.075500f, 0.187988f, 0.474854f, 0.774414f, 0.900391f,
+ 0.946289f, 0.966309f, 0.978027f, 0.983887f, 0.987793f, 0.990234f, 0.991699f, 0.993164f, 0.994141f, 0.995117f, 0.995605f, 0.996094f,
+ 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000244f, 0.000483f,
+ 0.000488f, 0.000731f, 0.001070f, 0.001551f, 0.002024f, 0.002520f, 0.003990f, 0.004738f, 0.007584f, 0.010834f, 0.016800f, 0.028763f,
+ 0.054535f, 0.120728f, 0.309082f, 0.642090f, 0.848145f, 0.926270f, 0.957031f, 0.971191f, 0.980469f, 0.985352f, 0.988770f, 0.990723f,
+ 0.992188f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000242f, 0.000485f, 0.000608f, 0.000731f, 0.001091f, 0.001339f, 0.001943f, 0.002602f, 0.003466f,
+ 0.004845f, 0.006649f, 0.009529f, 0.014824f, 0.023407f, 0.041351f, 0.083496f, 0.199951f, 0.482422f, 0.770996f, 0.896484f, 0.944336f,
+ 0.965332f, 0.976562f, 0.982910f, 0.986816f, 0.990234f, 0.991699f, 0.993164f, 0.994141f, 0.995117f, 0.995117f, 0.996094f, 0.996582f,
+ 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000121f, 0.000243f, 0.000243f, 0.000602f, 0.000609f, 0.000799f,
+ 0.001088f, 0.001459f, 0.001822f, 0.002432f, 0.003033f, 0.004375f, 0.006042f, 0.008560f, 0.012810f, 0.019791f, 0.032715f, 0.061584f,
+ 0.135254f, 0.335693f, 0.660156f, 0.853027f, 0.926758f, 0.956543f, 0.972168f, 0.980469f, 0.984863f, 0.988281f, 0.991211f, 0.992676f,
+ 0.993652f, 0.994141f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000119f,
+ 0.000243f, 0.000366f, 0.000605f, 0.000730f, 0.000731f, 0.001201f, 0.001458f, 0.001804f, 0.002428f, 0.003593f, 0.004234f, 0.005745f,
+ 0.007755f, 0.011139f, 0.016754f, 0.027054f, 0.047424f, 0.097107f, 0.231323f, 0.525879f, 0.791016f, 0.902832f, 0.945801f, 0.966797f,
+ 0.977051f, 0.982910f, 0.987793f, 0.990234f, 0.991699f, 0.993164f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f,
+ 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000116f, 0.000122f, 0.000365f, 0.000244f, 0.000602f, 0.000721f, 0.000730f, 0.000852f, 0.001451f,
+ 0.001842f, 0.002518f, 0.002993f, 0.004097f, 0.005253f, 0.007099f, 0.009865f, 0.014908f, 0.022827f, 0.038879f, 0.072815f, 0.163940f,
+ 0.396484f, 0.707031f, 0.869141f, 0.932129f, 0.960449f, 0.973145f, 0.980957f, 0.986328f, 0.988770f, 0.991211f, 0.992676f, 0.993652f,
+ 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000110f, 0.000361f, 0.000242f, 0.000244f,
+ 0.000602f, 0.000728f, 0.000853f, 0.001260f, 0.001569f, 0.001704f, 0.002287f, 0.003103f, 0.003857f, 0.004848f, 0.006680f, 0.009003f,
+ 0.012978f, 0.019897f, 0.032135f, 0.057983f, 0.121033f, 0.291504f, 0.604980f, 0.827148f, 0.915039f, 0.953125f, 0.969238f, 0.978516f,
+ 0.984375f, 0.988281f, 0.991211f, 0.992188f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000241f, 0.000241f, 0.000365f, 0.000365f, 0.000589f, 0.000852f, 0.000852f, 0.001246f, 0.001562f, 0.001812f, 0.002241f,
+ 0.002794f, 0.003633f, 0.004669f, 0.006069f, 0.008202f, 0.011772f, 0.016891f, 0.027618f, 0.047089f, 0.093506f, 0.216309f, 0.495605f,
+ 0.771484f, 0.894531f, 0.942383f, 0.965332f, 0.976074f, 0.982910f, 0.987305f, 0.989746f, 0.991699f, 0.993164f, 0.994629f, 0.995117f,
+ 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000364f, 0.000242f, 0.000487f, 0.000737f, 0.000730f,
+ 0.000974f, 0.001083f, 0.001520f, 0.001701f, 0.001938f, 0.002768f, 0.003658f, 0.004227f, 0.005741f, 0.007671f, 0.010796f, 0.015511f,
+ 0.023529f, 0.040009f, 0.074158f, 0.165405f, 0.395264f, 0.703613f, 0.868164f, 0.932129f, 0.959473f, 0.973633f, 0.980957f, 0.985840f,
+ 0.988770f, 0.991699f, 0.992676f, 0.994141f, 0.995117f, 0.995117f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f,
+ 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000100f, 0.000000f, 0.000241f,
+ 0.000224f, 0.000487f, 0.000488f, 0.000710f, 0.000972f, 0.000848f, 0.001181f, 0.001333f, 0.001910f, 0.001830f, 0.002661f, 0.003298f,
+ 0.004154f, 0.005386f, 0.007271f, 0.009735f, 0.013908f, 0.021149f, 0.034149f, 0.062042f, 0.130371f, 0.313477f, 0.627930f, 0.837402f,
+ 0.919922f, 0.954590f, 0.970215f, 0.979492f, 0.985352f, 0.988770f, 0.991211f, 0.992676f, 0.993652f, 0.995117f, 0.995605f, 0.996094f,
+ 0.996582f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000049f, 0.000242f, 0.000483f, 0.000606f, 0.000487f, 0.000695f, 0.000970f, 0.000974f, 0.001136f,
+ 0.001328f, 0.001694f, 0.002028f, 0.002617f, 0.002953f, 0.003847f, 0.004951f, 0.006653f, 0.009193f, 0.012672f, 0.018661f, 0.029968f,
+ 0.052673f, 0.106689f, 0.250977f, 0.549805f, 0.801758f, 0.907227f, 0.948242f, 0.967773f, 0.978027f, 0.984375f, 0.987793f, 0.990723f,
+ 0.992188f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000166f, 0.000243f, 0.000485f, 0.000487f,
+ 0.000487f, 0.000945f, 0.000834f, 0.000974f, 0.000974f, 0.001300f, 0.001810f, 0.002058f, 0.002573f, 0.002703f, 0.003761f, 0.004887f,
+ 0.006393f, 0.008514f, 0.011818f, 0.016937f, 0.026672f, 0.046051f, 0.089478f, 0.204712f, 0.476807f, 0.762207f, 0.891602f, 0.942383f,
+ 0.965820f, 0.976562f, 0.983398f, 0.987793f, 0.990234f, 0.992188f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.997070f,
+ 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000224f, 0.000358f, 0.000477f, 0.000486f, 0.000487f, 0.000580f, 0.000841f, 0.000973f, 0.001079f, 0.001255f, 0.001649f,
+ 0.002045f, 0.002241f, 0.002995f, 0.003841f, 0.004826f, 0.005920f, 0.007866f, 0.010925f, 0.015930f, 0.024109f, 0.040619f, 0.077454f,
+ 0.171509f, 0.412354f, 0.720215f, 0.876953f, 0.936035f, 0.962402f, 0.975098f, 0.982422f, 0.987305f, 0.990234f, 0.992188f, 0.993164f,
+ 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000165f, 0.000205f, 0.000411f, 0.000480f, 0.000486f, 0.000608f, 0.000688f,
+ 0.000966f, 0.000968f, 0.000974f, 0.001421f, 0.001489f, 0.001695f, 0.002090f, 0.002886f, 0.003326f, 0.004608f, 0.005604f, 0.007317f,
+ 0.010414f, 0.014862f, 0.022232f, 0.036469f, 0.067810f, 0.146973f, 0.359375f, 0.680664f, 0.861816f, 0.931152f, 0.959961f, 0.974609f,
+ 0.981934f, 0.986816f, 0.989746f, 0.991699f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000242f,
+ 0.000453f, 0.000539f, 0.000486f, 0.000487f, 0.000487f, 0.000957f, 0.000969f, 0.001202f, 0.001139f, 0.001393f, 0.001986f, 0.002045f,
+ 0.002863f, 0.003216f, 0.004128f, 0.005417f, 0.007378f, 0.009689f, 0.013466f, 0.020432f, 0.033722f, 0.060883f, 0.129395f, 0.318115f,
+ 0.642090f, 0.847656f, 0.926270f, 0.958008f, 0.973145f, 0.981934f, 0.986328f, 0.989746f, 0.992188f, 0.993164f, 0.994629f, 0.995605f,
+ 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000380f, 0.000482f, 0.000606f, 0.000607f, 0.000608f, 0.000829f, 0.000970f,
+ 0.000972f, 0.001070f, 0.001402f, 0.001812f, 0.002138f, 0.002619f, 0.003246f, 0.004082f, 0.005318f, 0.006699f, 0.009262f, 0.012764f,
+ 0.019318f, 0.031052f, 0.055878f, 0.116821f, 0.286621f, 0.610352f, 0.835938f, 0.922852f, 0.956543f, 0.973145f, 0.981445f, 0.986328f,
+ 0.989746f, 0.991699f, 0.993652f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000350f, 0.000480f,
+ 0.000605f, 0.000596f, 0.000608f, 0.000890f, 0.000963f, 0.000972f, 0.000974f, 0.001316f, 0.001798f, 0.002058f, 0.002560f, 0.002811f,
+ 0.003983f, 0.005108f, 0.006489f, 0.008888f, 0.012314f, 0.018021f, 0.029495f, 0.051941f, 0.107422f, 0.263428f, 0.585449f, 0.827148f,
+ 0.919434f, 0.956055f, 0.971680f, 0.981445f, 0.986816f, 0.989746f, 0.992188f, 0.994141f, 0.995117f, 0.995605f, 0.996582f, 0.996582f,
+ 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000130f, 0.000176f, 0.000462f, 0.000483f, 0.000604f, 0.000607f, 0.000638f, 0.000922f, 0.000965f, 0.000971f, 0.001235f,
+ 0.001376f, 0.001769f, 0.002041f, 0.002575f, 0.003130f, 0.003487f, 0.004936f, 0.006264f, 0.008415f, 0.012047f, 0.017517f, 0.027786f,
+ 0.049164f, 0.101257f, 0.249512f, 0.568848f, 0.821777f, 0.918945f, 0.956055f, 0.972168f, 0.981445f, 0.986816f, 0.990234f, 0.992188f,
+ 0.993652f, 0.995117f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000130f, 0.000122f, 0.000242f, 0.000352f, 0.000560f, 0.000602f, 0.000604f,
+ 0.000606f, 0.000767f, 0.001046f, 0.001089f, 0.000973f, 0.001327f, 0.001583f, 0.002033f, 0.002272f, 0.002657f, 0.003563f, 0.004589f,
+ 0.006138f, 0.008194f, 0.011299f, 0.016861f, 0.026718f, 0.047119f, 0.097656f, 0.240967f, 0.562500f, 0.821289f, 0.919922f, 0.957031f,
+ 0.973145f, 0.981934f, 0.987305f, 0.990234f, 0.992676f, 0.994141f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.998047f, 0.998047f,
+ 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000241f, 0.000314f, 0.000459f, 0.000600f, 0.000605f, 0.000598f, 0.000804f, 0.000958f, 0.001084f, 0.001104f, 0.001389f, 0.001709f,
+ 0.002041f, 0.002211f, 0.002645f, 0.003635f, 0.004467f, 0.005718f, 0.008072f, 0.011185f, 0.016846f, 0.026184f, 0.046112f, 0.094971f,
+ 0.239014f, 0.565430f, 0.825684f, 0.922363f, 0.958496f, 0.973633f, 0.983398f, 0.987793f, 0.990723f, 0.992676f, 0.994141f, 0.995605f,
+ 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000238f, 0.000122f, 0.000173f, 0.000246f, 0.000387f, 0.000480f, 0.000604f, 0.000604f, 0.000701f,
+ 0.000951f, 0.000968f, 0.001184f, 0.001315f, 0.001597f, 0.001899f, 0.002268f, 0.002813f, 0.003716f, 0.004372f, 0.005886f, 0.007759f,
+ 0.010918f, 0.015915f, 0.025726f, 0.045685f, 0.095459f, 0.243774f, 0.579102f, 0.833984f, 0.926270f, 0.960449f, 0.976074f, 0.983887f,
+ 0.988770f, 0.991211f, 0.993164f, 0.994629f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999023f, 0.999512f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000238f, 0.000237f, 0.000242f,
+ 0.000463f, 0.000585f, 0.000587f, 0.000718f, 0.000607f, 0.000885f, 0.001081f, 0.001087f, 0.001299f, 0.001553f, 0.001982f, 0.002104f,
+ 0.002777f, 0.003494f, 0.004406f, 0.005798f, 0.007645f, 0.010750f, 0.016159f, 0.025467f, 0.045959f, 0.097778f, 0.256104f, 0.603516f,
+ 0.847168f, 0.931152f, 0.963379f, 0.977539f, 0.985352f, 0.989258f, 0.991699f, 0.993652f, 0.995117f, 0.996094f, 0.996582f, 0.997559f,
+ 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000231f, 0.000122f, 0.000242f, 0.000242f, 0.000400f, 0.000525f, 0.000495f, 0.000605f, 0.000607f, 0.000898f, 0.001075f,
+ 0.001191f, 0.001133f, 0.001420f, 0.001794f, 0.002041f, 0.002733f, 0.003548f, 0.004448f, 0.005585f, 0.007656f, 0.010735f, 0.015671f,
+ 0.025589f, 0.047363f, 0.102783f, 0.276855f, 0.637695f, 0.862793f, 0.938477f, 0.966797f, 0.979004f, 0.985840f, 0.990234f, 0.992676f,
+ 0.994141f, 0.995117f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000226f, 0.000242f, 0.000470f, 0.000469f,
+ 0.000547f, 0.000711f, 0.000723f, 0.000829f, 0.001024f, 0.001188f, 0.001081f, 0.001415f, 0.001765f, 0.002048f, 0.002708f, 0.003252f,
+ 0.004448f, 0.005711f, 0.007557f, 0.010780f, 0.016220f, 0.026398f, 0.048950f, 0.111267f, 0.309082f, 0.680664f, 0.880371f, 0.945801f,
+ 0.970703f, 0.980957f, 0.986816f, 0.990723f, 0.993164f, 0.994629f, 0.995605f, 0.996582f, 0.997559f, 0.998047f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000204f, 0.000239f, 0.000242f, 0.000283f, 0.000479f, 0.000594f, 0.000603f, 0.000606f, 0.000779f, 0.001068f, 0.001084f, 0.001118f,
+ 0.001515f, 0.001926f, 0.002098f, 0.002674f, 0.002975f, 0.004040f, 0.005478f, 0.007488f, 0.010651f, 0.016327f, 0.027222f, 0.052460f,
+ 0.123718f, 0.355713f, 0.729980f, 0.899902f, 0.952637f, 0.973145f, 0.983887f, 0.988770f, 0.991699f, 0.994141f, 0.995117f, 0.996094f,
+ 0.997070f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000122f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000236f, 0.000207f, 0.000240f, 0.000435f, 0.000534f, 0.000594f, 0.000602f,
+ 0.000722f, 0.000727f, 0.000947f, 0.001081f, 0.001090f, 0.001471f, 0.001829f, 0.002010f, 0.002478f, 0.002956f, 0.004051f, 0.005753f,
+ 0.007717f, 0.011040f, 0.017105f, 0.028748f, 0.057159f, 0.142944f, 0.421387f, 0.780762f, 0.916992f, 0.960449f, 0.976562f, 0.985352f,
+ 0.989746f, 0.992676f, 0.994629f, 0.996094f, 0.997070f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000224f, 0.000232f,
+ 0.000230f, 0.000382f, 0.000472f, 0.000576f, 0.000715f, 0.000721f, 0.000727f, 0.001046f, 0.001078f, 0.001186f, 0.001434f, 0.001674f,
+ 0.002066f, 0.002546f, 0.003407f, 0.004181f, 0.005634f, 0.007542f, 0.011330f, 0.017609f, 0.031189f, 0.064392f, 0.172729f, 0.506836f,
+ 0.828125f, 0.933105f, 0.966309f, 0.980469f, 0.987305f, 0.991211f, 0.993652f, 0.995117f, 0.996582f, 0.997070f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000232f, 0.000234f, 0.000352f, 0.000461f, 0.000535f, 0.000594f, 0.000722f, 0.000725f,
+ 0.000921f, 0.001116f, 0.001192f, 0.001416f, 0.001637f, 0.001911f, 0.002380f, 0.002949f, 0.003948f, 0.005589f, 0.007942f, 0.011650f,
+ 0.018631f, 0.034302f, 0.075867f, 0.219238f, 0.607422f, 0.870605f, 0.946777f, 0.972656f, 0.983887f, 0.989258f, 0.992676f, 0.995117f,
+ 0.996094f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000239f, 0.000302f,
+ 0.000396f, 0.000564f, 0.000674f, 0.000617f, 0.000722f, 0.001003f, 0.001068f, 0.001084f, 0.001302f, 0.001598f, 0.001929f, 0.002375f,
+ 0.002935f, 0.004349f, 0.005714f, 0.007957f, 0.012306f, 0.020493f, 0.039001f, 0.092590f, 0.293213f, 0.711426f, 0.905762f, 0.958984f,
+ 0.978027f, 0.986328f, 0.990723f, 0.994141f, 0.995605f, 0.996582f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000232f, 0.000227f, 0.000240f, 0.000282f, 0.000542f, 0.000703f, 0.000718f, 0.000724f, 0.000833f, 0.001069f,
+ 0.001184f, 0.001346f, 0.001464f, 0.001898f, 0.002649f, 0.003164f, 0.004467f, 0.005863f, 0.008400f, 0.013199f, 0.022614f, 0.046051f,
+ 0.120605f, 0.406738f, 0.801270f, 0.931641f, 0.968262f, 0.982422f, 0.988770f, 0.992676f, 0.994629f, 0.996094f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000219f, 0.000237f, 0.000235f, 0.000241f, 0.000480f,
+ 0.000584f, 0.000715f, 0.000723f, 0.000775f, 0.001061f, 0.000959f, 0.001139f, 0.001526f, 0.001770f, 0.002546f, 0.003151f, 0.004250f,
+ 0.006195f, 0.009071f, 0.014595f, 0.026413f, 0.056763f, 0.169067f, 0.557617f, 0.869141f, 0.951172f, 0.976074f, 0.986328f, 0.990723f,
+ 0.994141f, 0.995605f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000120f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000216f, 0.000228f, 0.000285f, 0.000339f, 0.000454f, 0.000572f, 0.000595f, 0.000721f, 0.000604f, 0.000930f, 0.000958f, 0.001171f,
+ 0.001431f, 0.001888f, 0.002663f, 0.003256f, 0.004402f, 0.006527f, 0.009964f, 0.016281f, 0.031189f, 0.074524f, 0.258301f, 0.714355f,
+ 0.916016f, 0.965332f, 0.982422f, 0.989746f, 0.992676f, 0.995117f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.000000f, 0.000063f, 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000194f, 0.000184f, 0.000228f, 0.000340f, 0.000396f, 0.000668f, 0.000571f,
+ 0.000478f, 0.000602f, 0.000919f, 0.000956f, 0.001061f, 0.001497f, 0.001888f, 0.002565f, 0.003523f, 0.004578f, 0.006935f, 0.010765f,
+ 0.018417f, 0.038635f, 0.107727f, 0.416260f, 0.832520f, 0.946289f, 0.975586f, 0.986328f, 0.991699f, 0.994629f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000045f, 0.000118f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000234f, 0.000294f, 0.000220f, 0.000486f, 0.000579f, 0.000588f, 0.000669f, 0.000878f, 0.001038f, 0.001135f, 0.001451f, 0.001820f,
+ 0.002529f, 0.003551f, 0.005199f, 0.007542f, 0.012230f, 0.022369f, 0.051910f, 0.174927f, 0.630859f, 0.905273f, 0.965332f, 0.982910f,
+ 0.990234f, 0.993652f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000091f,
+ 0.000117f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000171f, 0.000151f, 0.000166f, 0.000195f, 0.000342f, 0.000452f, 0.000594f, 0.000599f,
+ 0.000862f, 0.001019f, 0.001135f, 0.001465f, 0.002031f, 0.002676f, 0.003714f, 0.005497f, 0.008286f, 0.014320f, 0.028854f, 0.077332f,
+ 0.322754f, 0.809082f, 0.946289f, 0.977051f, 0.987793f, 0.993164f, 0.998047f, 0.998535f, 0.998047f, 0.998047f, 0.998535f, 0.998047f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000079f, 0.000105f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000008f, 0.000006f, 0.000098f, 0.000137f,
+ 0.000233f, 0.000324f, 0.000566f, 0.000589f, 0.000618f, 0.000874f, 0.000941f, 0.001108f, 0.001621f, 0.001880f, 0.002726f, 0.003788f,
+ 0.005840f, 0.009583f, 0.017563f, 0.039368f, 0.133545f, 0.582520f, 0.906738f, 0.968262f, 0.984863f, 0.992188f, 0.998047f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000069f, 0.000114f,
+ 0.000117f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000021f,
+ 0.000013f, 0.000009f, 0.000006f, 0.000004f, 0.000090f, 0.000206f, 0.000305f, 0.000538f, 0.000585f, 0.000596f, 0.000869f, 0.000941f,
+ 0.001149f, 0.001516f, 0.002150f, 0.002729f, 0.004475f, 0.006660f, 0.011360f, 0.022690f, 0.061401f, 0.281494f, 0.813965f, 0.952148f,
+ 0.980957f, 0.990723f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000085f, 0.000114f, 0.000117f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000122f, 0.000122f, 0.000077f, 0.000041f, 0.000022f, 0.000013f, 0.000009f, 0.000006f, 0.000066f, 0.000107f, 0.000223f, 0.000250f,
+ 0.000532f, 0.000576f, 0.000593f, 0.000784f, 0.000937f, 0.001126f, 0.001523f, 0.002306f, 0.003193f, 0.004574f, 0.007717f, 0.014191f,
+ 0.032410f, 0.116577f, 0.595215f, 0.921875f, 0.974609f, 0.988770f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000056f, 0.000112f,
+ 0.000114f, 0.000118f, 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000074f, 0.000038f, 0.000021f, 0.000013f, 0.000009f,
+ 0.000006f, 0.000004f, 0.000003f, 0.000179f, 0.000258f, 0.000367f, 0.000469f, 0.000583f, 0.000770f, 0.000932f, 0.001131f, 0.001758f,
+ 0.002483f, 0.003517f, 0.005432f, 0.009232f, 0.019302f, 0.054504f, 0.293457f, 0.853516f, 0.964844f, 0.986816f, 0.997070f, 0.997070f,
+ 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000015f, 0.000084f, 0.000107f, 0.000113f, 0.000117f, 0.000118f, 0.000119f, 0.000120f, 0.000120f,
+ 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000076f, 0.000042f, 0.000023f, 0.000015f, 0.000009f, 0.000007f, 0.000005f, 0.000004f, 0.000147f, 0.000238f, 0.000457f, 0.000545f,
+ 0.000586f, 0.000821f, 0.000936f, 0.001139f, 0.001849f, 0.002665f, 0.003687f, 0.006367f, 0.011810f, 0.028931f, 0.120605f, 0.687988f,
+ 0.947754f, 0.982910f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000082f, 0.000095f,
+ 0.000111f, 0.000115f, 0.000117f, 0.000118f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000083f, 0.000042f, 0.000026f, 0.000015f, 0.000010f, 0.000007f, 0.000005f,
+ 0.000013f, 0.000086f, 0.000185f, 0.000309f, 0.000552f, 0.000577f, 0.000796f, 0.000925f, 0.001251f, 0.001838f, 0.002878f, 0.004509f,
+ 0.007572f, 0.016617f, 0.054932f, 0.391602f, 0.912109f, 0.978516f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996094f, 0.996094f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000095f, 0.000106f, 0.000112f, 0.000113f, 0.000115f, 0.000118f, 0.000118f,
+ 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000099f, 0.000048f,
+ 0.000027f, 0.000017f, 0.000011f, 0.000008f, 0.000006f, 0.000004f, 0.000089f, 0.000182f, 0.000347f, 0.000495f, 0.000570f, 0.000777f,
+ 0.000922f, 0.001316f, 0.001831f, 0.003004f, 0.005028f, 0.010078f, 0.028183f, 0.161865f, 0.833496f, 0.972168f, 0.995117f, 0.995605f,
+ 0.995605f, 0.995117f, 0.995117f, 0.995605f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000074f,
+ 0.000093f, 0.000107f, 0.000111f, 0.000115f, 0.000116f, 0.000117f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f,
+ 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000057f, 0.000032f, 0.000021f, 0.000013f, 0.000008f, 0.000006f, 0.000005f, 0.000034f,
+ 0.000159f, 0.000267f, 0.000514f, 0.000566f, 0.000714f, 0.000888f, 0.001348f, 0.001995f, 0.003302f, 0.006447f, 0.015945f, 0.069153f,
+ 0.646484f, 0.960449f, 0.994629f, 0.995117f, 0.994629f, 0.995117f, 0.994629f, 0.995117f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000080f, 0.000095f, 0.000102f, 0.000109f, 0.000114f, 0.000115f,
+ 0.000116f, 0.000118f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000077f, 0.000044f, 0.000025f,
+ 0.000015f, 0.000011f, 0.000007f, 0.000005f, 0.000004f, 0.000106f, 0.000244f, 0.000476f, 0.000561f, 0.000622f, 0.000893f, 0.001266f,
+ 0.001968f, 0.003990f, 0.009476f, 0.033234f, 0.342529f, 0.940918f, 0.993652f, 0.993652f, 0.993652f, 0.993652f, 0.993652f, 0.993652f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000046f, 0.000079f, 0.000093f, 0.000104f, 0.000110f, 0.000111f, 0.000113f, 0.000116f, 0.000117f, 0.000118f, 0.000118f, 0.000119f,
+ 0.000119f, 0.000119f, 0.000092f, 0.000050f, 0.000029f, 0.000019f, 0.000012f, 0.000009f, 0.000006f, 0.000004f, 0.000061f, 0.000188f,
+ 0.000324f, 0.000456f, 0.000525f, 0.000657f, 0.001371f, 0.002445f, 0.005634f, 0.017563f, 0.135986f, 0.902832f, 0.992188f, 0.992188f,
+ 0.992676f, 0.992188f, 0.992676f, 0.992188f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000038f, 0.000075f, 0.000092f, 0.000100f, 0.000105f,
+ 0.000111f, 0.000112f, 0.000114f, 0.000116f, 0.000117f, 0.000117f, 0.000118f, 0.000118f, 0.000074f, 0.000041f, 0.000024f, 0.000016f,
+ 0.000010f, 0.000007f, 0.000005f, 0.000033f, 0.000167f, 0.000423f, 0.000410f, 0.000413f, 0.000575f, 0.001446f, 0.003387f, 0.009644f,
+ 0.056183f, 0.817383f, 0.990234f, 0.990234f, 0.990234f, 0.990723f, 0.990234f, 0.990723f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000011f, 0.000067f, 0.000084f, 0.000096f, 0.000103f, 0.000108f, 0.000110f, 0.000113f, 0.000115f, 0.000115f,
+ 0.000116f, 0.000104f, 0.000057f, 0.000035f, 0.000021f, 0.000013f, 0.000009f, 0.000006f, 0.000054f, 0.000161f, 0.000317f, 0.000332f,
+ 0.000393f, 0.000723f, 0.001760f, 0.005203f, 0.025345f, 0.617676f, 0.987793f, 0.987793f, 0.987793f, 0.988281f, 0.988281f, 0.988281f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000017f, 0.000052f, 0.000075f,
+ 0.000091f, 0.000097f, 0.000105f, 0.000108f, 0.000111f, 0.000113f, 0.000114f, 0.000085f, 0.000050f, 0.000031f, 0.000018f, 0.000012f,
+ 0.000008f, 0.000005f, 0.000095f, 0.000314f, 0.000306f, 0.000363f, 0.000813f, 0.002583f, 0.011734f, 0.308105f, 0.983887f, 0.984375f,
+ 0.984375f, 0.984375f, 0.983887f, 0.983887f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000037f, 0.000065f, 0.000083f, 0.000093f, 0.000099f, 0.000105f, 0.000108f,
+ 0.000110f, 0.000082f, 0.000045f, 0.000027f, 0.000017f, 0.000011f, 0.000007f, 0.000114f, 0.000245f, 0.000209f, 0.000379f, 0.001151f,
+ 0.005260f, 0.107971f, 0.977539f, 0.979004f, 0.978027f, 0.978027f, 0.978027f, 0.978027f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000007f, 0.000045f, 0.000069f, 0.000084f, 0.000093f, 0.000099f, 0.000104f, 0.000076f, 0.000044f, 0.000026f, 0.000016f, 0.000010f,
+ 0.000012f, 0.000152f, 0.000179f, 0.000373f, 0.001760f, 0.035522f, 0.969238f, 0.968750f, 0.968750f, 0.968750f, 0.968750f, 0.968750f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000014f, 0.000050f, 0.000070f, 0.000082f,
+ 0.000092f, 0.000075f, 0.000044f, 0.000026f, 0.000015f, 0.000009f, 0.000121f, 0.000117f, 0.000611f, 0.010231f, 0.951172f, 0.951172f,
+ 0.951172f, 0.951172f, 0.950684f, 0.951660f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000020f, 0.000047f, 0.000069f, 0.000077f, 0.000042f, 0.000024f, 0.000013f, 0.000078f,
+ 0.000130f, 0.001914f, 0.915039f, 0.915527f, 0.915039f, 0.915527f, 0.916016f, 0.915039f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000017f, 0.000047f, 0.000040f, 0.000019f, 0.000035f, 0.000188f, 0.833984f, 0.833496f, 0.833496f, 0.834473f, 0.834473f, 0.833984f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000014f, 0.000007f, 0.642578f, 0.643555f,
+ 0.643066f, 0.643555f, 0.642578f, 0.642578f,
+ },
+ {
+ 0.113464f, 0.797852f, 0.930176f, 0.961914f, 0.974609f, 0.980469f, 0.984863f, 0.987793f, 0.989258f, 0.991211f, 0.992188f, 0.993164f,
+ 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997559f,
+ 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.007183f, 0.058716f, 0.349609f, 0.784668f, 0.912598f, 0.952148f, 0.968262f, 0.977539f,
+ 0.981934f, 0.985352f, 0.988281f, 0.990234f, 0.991211f, 0.992188f, 0.993652f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.995605f,
+ 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.002432f, 0.011818f, 0.039581f, 0.143677f,
+ 0.482910f, 0.800293f, 0.908691f, 0.947266f, 0.964844f, 0.974609f, 0.980469f, 0.984375f, 0.987305f, 0.989258f, 0.990723f, 0.991699f,
+ 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f,
+ 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.001096f, 0.005062f, 0.012482f, 0.030151f, 0.079956f, 0.239014f, 0.581055f, 0.819824f, 0.909180f, 0.946289f, 0.963379f, 0.973145f,
+ 0.979492f, 0.983398f, 0.986328f, 0.988281f, 0.990234f, 0.991699f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995605f, 0.996094f,
+ 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000610f, 0.002434f, 0.005779f, 0.012207f, 0.023972f, 0.052765f, 0.129883f, 0.342773f,
+ 0.660156f, 0.841309f, 0.914062f, 0.947266f, 0.963379f, 0.973145f, 0.979004f, 0.982910f, 0.985840f, 0.987793f, 0.989746f, 0.991211f,
+ 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f,
+ 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000397f, 0.001559f, 0.003397f, 0.006058f,
+ 0.011177f, 0.020355f, 0.039307f, 0.083130f, 0.196777f, 0.452148f, 0.724121f, 0.862305f, 0.920410f, 0.949219f, 0.964355f, 0.973145f,
+ 0.979004f, 0.982910f, 0.985840f, 0.988770f, 0.989258f, 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995605f, 0.995605f,
+ 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000366f, 0.001097f, 0.002163f, 0.003523f, 0.006268f, 0.010941f, 0.017487f, 0.030930f, 0.058411f, 0.122925f, 0.281738f, 0.556152f,
+ 0.776367f, 0.881348f, 0.928223f, 0.951660f, 0.966309f, 0.973633f, 0.979492f, 0.983398f, 0.986328f, 0.988281f, 0.989746f, 0.991211f,
+ 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000728f, 0.001340f, 0.002533f, 0.003813f, 0.006081f, 0.009750f, 0.015419f,
+ 0.025177f, 0.044067f, 0.084473f, 0.179077f, 0.384033f, 0.649902f, 0.818848f, 0.897949f, 0.935547f, 0.956055f, 0.967285f, 0.975098f,
+ 0.980957f, 0.983887f, 0.986328f, 0.988281f, 0.990234f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000609f, 0.000854f, 0.001898f,
+ 0.002781f, 0.004246f, 0.006218f, 0.008835f, 0.013504f, 0.021362f, 0.035400f, 0.062347f, 0.121460f, 0.255127f, 0.495361f, 0.726562f,
+ 0.852539f, 0.912598f, 0.943359f, 0.959473f, 0.969238f, 0.976562f, 0.981445f, 0.984375f, 0.987305f, 0.988770f, 0.990234f, 0.991699f,
+ 0.992676f, 0.993652f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000244f, 0.000244f, 0.000731f, 0.001295f, 0.002159f, 0.003092f, 0.004051f, 0.005836f, 0.008560f, 0.011925f, 0.018585f, 0.029373f,
+ 0.048950f, 0.088013f, 0.174194f, 0.354980f, 0.604492f, 0.788086f, 0.880371f, 0.925293f, 0.950195f, 0.963867f, 0.972168f, 0.978027f,
+ 0.982422f, 0.985840f, 0.987793f, 0.990234f, 0.991699f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000114f, 0.000244f, 0.000709f, 0.001089f, 0.001580f, 0.002100f, 0.002848f, 0.004028f,
+ 0.005646f, 0.008232f, 0.011276f, 0.016647f, 0.024948f, 0.039215f, 0.067566f, 0.125244f, 0.249878f, 0.471436f, 0.698242f, 0.834961f,
+ 0.902344f, 0.937012f, 0.955078f, 0.967773f, 0.974609f, 0.979492f, 0.983887f, 0.987305f, 0.988770f, 0.990723f, 0.991699f, 0.992676f,
+ 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f,
+ 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000244f, 0.000480f, 0.001081f,
+ 0.001216f, 0.001684f, 0.002287f, 0.003113f, 0.004246f, 0.005711f, 0.007412f, 0.010658f, 0.014900f, 0.021408f, 0.033173f, 0.053711f,
+ 0.094299f, 0.179688f, 0.351807f, 0.591309f, 0.774902f, 0.871582f, 0.919922f, 0.946289f, 0.961426f, 0.971191f, 0.977051f, 0.981934f,
+ 0.984863f, 0.987305f, 0.989258f, 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000364f, 0.000366f, 0.000729f, 0.001195f, 0.001218f, 0.001693f, 0.002209f, 0.003038f, 0.004192f, 0.005249f, 0.006981f,
+ 0.009926f, 0.013405f, 0.019165f, 0.028473f, 0.044250f, 0.073975f, 0.134521f, 0.260010f, 0.476562f, 0.696289f, 0.830566f, 0.898438f,
+ 0.933594f, 0.954102f, 0.966309f, 0.974609f, 0.979492f, 0.982910f, 0.986328f, 0.988281f, 0.989746f, 0.991699f, 0.992676f, 0.993652f,
+ 0.994141f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000226f, 0.000365f, 0.000488f, 0.000731f, 0.001090f, 0.001245f, 0.002028f,
+ 0.002169f, 0.003023f, 0.003952f, 0.005043f, 0.006790f, 0.009026f, 0.012276f, 0.016754f, 0.024628f, 0.037384f, 0.060120f, 0.104431f,
+ 0.196045f, 0.372803f, 0.604980f, 0.779785f, 0.872070f, 0.919922f, 0.945312f, 0.960938f, 0.970703f, 0.977539f, 0.980957f, 0.984863f,
+ 0.987305f, 0.989258f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f,
+ 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000364f, 0.000487f,
+ 0.000488f, 0.000608f, 0.001092f, 0.001323f, 0.001909f, 0.002028f, 0.002829f, 0.003754f, 0.004940f, 0.006329f, 0.008850f, 0.011353f,
+ 0.015572f, 0.022110f, 0.032196f, 0.050293f, 0.083984f, 0.151978f, 0.288574f, 0.507812f, 0.715332f, 0.839844f, 0.902832f, 0.936035f,
+ 0.955566f, 0.966797f, 0.974609f, 0.979492f, 0.983887f, 0.986816f, 0.988281f, 0.989746f, 0.991699f, 0.992676f, 0.993652f, 0.994141f,
+ 0.994629f, 0.995605f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000341f, 0.000486f, 0.000487f, 0.000591f, 0.000846f, 0.001213f, 0.001407f, 0.002018f, 0.002306f, 0.003119f,
+ 0.003736f, 0.004700f, 0.005936f, 0.007858f, 0.010498f, 0.013939f, 0.019913f, 0.028564f, 0.043060f, 0.069275f, 0.120972f, 0.225830f,
+ 0.416748f, 0.642090f, 0.798828f, 0.881836f, 0.924805f, 0.948730f, 0.962891f, 0.971191f, 0.978516f, 0.982422f, 0.985352f, 0.987793f,
+ 0.989746f, 0.991211f, 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.996582f, 0.997070f,
+ 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000121f, 0.000122f, 0.000475f, 0.000486f, 0.000487f, 0.000714f, 0.000913f,
+ 0.001296f, 0.001350f, 0.001884f, 0.002163f, 0.002871f, 0.003702f, 0.004578f, 0.005573f, 0.007278f, 0.009819f, 0.013039f, 0.017883f,
+ 0.025589f, 0.037445f, 0.058655f, 0.099243f, 0.180542f, 0.338867f, 0.563965f, 0.751465f, 0.857422f, 0.912109f, 0.941406f, 0.958496f,
+ 0.968262f, 0.976074f, 0.980957f, 0.984375f, 0.986816f, 0.989258f, 0.990723f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f,
+ 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000122f, 0.000242f,
+ 0.000417f, 0.000607f, 0.000602f, 0.000644f, 0.001016f, 0.001223f, 0.001337f, 0.002010f, 0.002087f, 0.002752f, 0.003380f, 0.004486f,
+ 0.005760f, 0.007523f, 0.009048f, 0.012169f, 0.016312f, 0.022949f, 0.033295f, 0.050812f, 0.082886f, 0.146851f, 0.275635f, 0.486572f,
+ 0.696777f, 0.828613f, 0.896484f, 0.933594f, 0.953613f, 0.965820f, 0.973633f, 0.979980f, 0.983887f, 0.986328f, 0.988770f, 0.990723f,
+ 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.997559f, 0.997559f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000262f, 0.000463f, 0.000603f, 0.000665f, 0.000716f, 0.001069f, 0.001322f, 0.001538f,
+ 0.001895f, 0.002293f, 0.003120f, 0.003323f, 0.004166f, 0.005638f, 0.006828f, 0.008942f, 0.011368f, 0.015465f, 0.021057f, 0.029663f,
+ 0.044861f, 0.070923f, 0.123169f, 0.228149f, 0.416504f, 0.640137f, 0.797363f, 0.880859f, 0.924805f, 0.948730f, 0.963379f, 0.971680f,
+ 0.978516f, 0.982422f, 0.985840f, 0.988281f, 0.990723f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.996094f,
+ 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000120f, 0.000172f, 0.000243f, 0.000365f, 0.000475f, 0.000607f,
+ 0.000608f, 0.000609f, 0.001013f, 0.001424f, 0.001456f, 0.001904f, 0.002411f, 0.002903f, 0.003145f, 0.004314f, 0.004944f, 0.006607f,
+ 0.008156f, 0.010719f, 0.014297f, 0.018906f, 0.027069f, 0.040070f, 0.062103f, 0.104858f, 0.191162f, 0.355469f, 0.581543f, 0.762695f,
+ 0.863281f, 0.915039f, 0.943848f, 0.960449f, 0.970703f, 0.977051f, 0.981445f, 0.985840f, 0.987793f, 0.989746f, 0.991211f, 0.992676f,
+ 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.997070f, 0.997070f, 0.998047f, 0.997559f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000096f,
+ 0.000239f, 0.000241f, 0.000336f, 0.000482f, 0.000719f, 0.000729f, 0.000831f, 0.001049f, 0.001552f, 0.001576f, 0.001710f, 0.002373f,
+ 0.002846f, 0.003254f, 0.004051f, 0.005035f, 0.006405f, 0.007706f, 0.009987f, 0.013092f, 0.017715f, 0.024872f, 0.035980f, 0.055328f,
+ 0.091248f, 0.163330f, 0.305664f, 0.524902f, 0.726562f, 0.845215f, 0.906250f, 0.938965f, 0.957031f, 0.969238f, 0.976074f, 0.981445f,
+ 0.984863f, 0.987305f, 0.989258f, 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f,
+ 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000118f, 0.000120f, 0.000351f, 0.000364f, 0.000421f, 0.000480f, 0.000606f, 0.000728f, 0.000852f,
+ 0.001175f, 0.001535f, 0.001673f, 0.001671f, 0.002277f, 0.002743f, 0.003220f, 0.003922f, 0.004868f, 0.005951f, 0.007488f, 0.009430f,
+ 0.012527f, 0.016266f, 0.022964f, 0.033142f, 0.049805f, 0.080688f, 0.141846f, 0.265625f, 0.473145f, 0.688477f, 0.825684f, 0.897949f,
+ 0.934082f, 0.954102f, 0.966797f, 0.975098f, 0.980469f, 0.984375f, 0.987305f, 0.989258f, 0.991211f, 0.992676f, 0.993164f, 0.993652f,
+ 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000058f, 0.000235f, 0.000360f, 0.000243f,
+ 0.000440f, 0.000583f, 0.000847f, 0.000851f, 0.000852f, 0.001189f, 0.001411f, 0.001645f, 0.001898f, 0.002417f, 0.002617f, 0.003435f,
+ 0.003695f, 0.004616f, 0.005733f, 0.007278f, 0.009216f, 0.012016f, 0.015701f, 0.021561f, 0.030396f, 0.045746f, 0.073120f, 0.125732f,
+ 0.233521f, 0.428223f, 0.653320f, 0.807617f, 0.887695f, 0.929688f, 0.951660f, 0.965820f, 0.974121f, 0.980469f, 0.984375f, 0.986816f,
+ 0.989746f, 0.991211f, 0.992676f, 0.993164f, 0.994141f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.998047f,
+ 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000237f, 0.000237f, 0.000362f, 0.000365f, 0.000558f, 0.000814f, 0.000727f, 0.000729f, 0.000935f, 0.001189f, 0.001403f,
+ 0.001569f, 0.001989f, 0.002216f, 0.002533f, 0.003307f, 0.003906f, 0.004463f, 0.005646f, 0.006908f, 0.008980f, 0.011230f, 0.014755f,
+ 0.020020f, 0.028320f, 0.041931f, 0.065979f, 0.113098f, 0.209229f, 0.389648f, 0.620605f, 0.789551f, 0.879395f, 0.924805f, 0.950684f,
+ 0.964844f, 0.974121f, 0.979980f, 0.983398f, 0.987305f, 0.989258f, 0.991211f, 0.992676f, 0.993652f, 0.993652f, 0.995117f, 0.995605f,
+ 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000121f, 0.000241f, 0.000486f, 0.000575f, 0.000707f,
+ 0.000726f, 0.000971f, 0.000849f, 0.000966f, 0.001350f, 0.001660f, 0.001678f, 0.002224f, 0.002483f, 0.003197f, 0.003611f, 0.004200f,
+ 0.005318f, 0.006744f, 0.008476f, 0.010506f, 0.014145f, 0.019089f, 0.026627f, 0.039001f, 0.061096f, 0.103333f, 0.189819f, 0.358887f,
+ 0.591309f, 0.773438f, 0.872559f, 0.922363f, 0.948730f, 0.963867f, 0.973145f, 0.979492f, 0.983887f, 0.986816f, 0.989258f, 0.991211f,
+ 0.992188f, 0.993164f, 0.994629f, 0.995117f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000175f, 0.000361f,
+ 0.000481f, 0.000485f, 0.000364f, 0.000562f, 0.000703f, 0.000827f, 0.000842f, 0.000972f, 0.001172f, 0.001321f, 0.001675f, 0.001684f,
+ 0.002153f, 0.002455f, 0.003122f, 0.003391f, 0.004177f, 0.005314f, 0.006325f, 0.007896f, 0.010368f, 0.013527f, 0.018082f, 0.025162f,
+ 0.037140f, 0.057343f, 0.095886f, 0.175659f, 0.334473f, 0.567871f, 0.760742f, 0.866699f, 0.919922f, 0.947754f, 0.963379f, 0.972656f,
+ 0.979492f, 0.984375f, 0.987305f, 0.989258f, 0.991211f, 0.992676f, 0.993652f, 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.997070f,
+ 0.998047f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000325f, 0.000311f, 0.000243f, 0.000484f, 0.000486f, 0.000536f, 0.000698f, 0.000723f, 0.000844f,
+ 0.000972f, 0.001081f, 0.001312f, 0.001658f, 0.001914f, 0.001932f, 0.002390f, 0.003017f, 0.003668f, 0.004353f, 0.005199f, 0.006336f,
+ 0.007812f, 0.009972f, 0.012802f, 0.017029f, 0.024200f, 0.035034f, 0.053833f, 0.090027f, 0.164185f, 0.316162f, 0.549805f, 0.751465f,
+ 0.863281f, 0.918457f, 0.947266f, 0.963379f, 0.974121f, 0.979492f, 0.984375f, 0.987793f, 0.989746f, 0.991699f, 0.993164f, 0.994141f,
+ 0.995117f, 0.995605f, 0.996094f, 0.997070f, 0.997559f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000231f, 0.000453f, 0.000480f, 0.000484f,
+ 0.000485f, 0.000486f, 0.000917f, 0.000963f, 0.000969f, 0.000970f, 0.001043f, 0.001288f, 0.001523f, 0.001684f, 0.001885f, 0.002464f,
+ 0.002531f, 0.003565f, 0.004124f, 0.004745f, 0.006077f, 0.007580f, 0.009605f, 0.012634f, 0.016953f, 0.023346f, 0.033386f, 0.051697f,
+ 0.085632f, 0.156250f, 0.303955f, 0.537598f, 0.746582f, 0.860840f, 0.918457f, 0.947754f, 0.963867f, 0.973633f, 0.979980f, 0.984863f,
+ 0.987793f, 0.990234f, 0.991699f, 0.993652f, 0.994141f, 0.995117f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000235f, 0.000239f, 0.000359f, 0.000484f, 0.000485f, 0.000486f, 0.000628f, 0.000957f, 0.000967f, 0.000969f, 0.001065f,
+ 0.001288f, 0.001602f, 0.001850f, 0.001995f, 0.002409f, 0.002523f, 0.003462f, 0.003838f, 0.004993f, 0.005917f, 0.007233f, 0.009338f,
+ 0.012230f, 0.015610f, 0.022415f, 0.032288f, 0.049805f, 0.082947f, 0.151489f, 0.296631f, 0.532715f, 0.745117f, 0.862793f, 0.919434f,
+ 0.948242f, 0.964844f, 0.974609f, 0.980957f, 0.985352f, 0.988281f, 0.990723f, 0.992676f, 0.994141f, 0.994629f, 0.995605f, 0.996094f,
+ 0.996582f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000187f, 0.000437f, 0.000473f, 0.000483f, 0.000485f, 0.000606f,
+ 0.000583f, 0.000711f, 0.000772f, 0.000968f, 0.001107f, 0.001287f, 0.001434f, 0.001662f, 0.001984f, 0.002449f, 0.002634f, 0.003145f,
+ 0.003777f, 0.004410f, 0.005722f, 0.007114f, 0.008926f, 0.011696f, 0.016006f, 0.021683f, 0.031342f, 0.048309f, 0.080750f, 0.149170f,
+ 0.294678f, 0.534668f, 0.749512f, 0.866211f, 0.922363f, 0.950684f, 0.966309f, 0.975586f, 0.981934f, 0.985840f, 0.989258f, 0.991699f,
+ 0.992676f, 0.994141f, 0.994629f, 0.996094f, 0.996582f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000247f,
+ 0.000238f, 0.000407f, 0.000482f, 0.000484f, 0.000604f, 0.000869f, 0.000909f, 0.000721f, 0.000955f, 0.001000f, 0.001241f, 0.001342f,
+ 0.001655f, 0.001721f, 0.002329f, 0.002623f, 0.003086f, 0.003677f, 0.004349f, 0.005600f, 0.006962f, 0.008835f, 0.011581f, 0.015274f,
+ 0.021286f, 0.030884f, 0.047760f, 0.079895f, 0.148926f, 0.298584f, 0.543945f, 0.758301f, 0.872559f, 0.925781f, 0.953125f, 0.967773f,
+ 0.977051f, 0.982910f, 0.986816f, 0.989258f, 0.991211f, 0.993164f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000237f, 0.000410f, 0.000472f, 0.000481f, 0.000483f, 0.000485f, 0.000687f, 0.000913f,
+ 0.000956f, 0.000966f, 0.000997f, 0.001341f, 0.001415f, 0.001813f, 0.002029f, 0.002043f, 0.002594f, 0.003210f, 0.003641f, 0.004734f,
+ 0.005356f, 0.006882f, 0.008675f, 0.011360f, 0.014816f, 0.020920f, 0.030380f, 0.047485f, 0.080200f, 0.151733f, 0.308105f, 0.561523f,
+ 0.772949f, 0.881348f, 0.931152f, 0.956055f, 0.969727f, 0.978516f, 0.983887f, 0.987793f, 0.990234f, 0.992188f, 0.993652f, 0.994629f,
+ 0.995605f, 0.996094f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000254f, 0.000345f, 0.000468f,
+ 0.000585f, 0.000482f, 0.000603f, 0.000485f, 0.000862f, 0.000928f, 0.000965f, 0.001174f, 0.001162f, 0.001405f, 0.001761f, 0.002016f,
+ 0.002182f, 0.002733f, 0.002831f, 0.003504f, 0.004456f, 0.005440f, 0.006775f, 0.008553f, 0.011055f, 0.014694f, 0.020859f, 0.030334f,
+ 0.047852f, 0.081970f, 0.157593f, 0.325439f, 0.586914f, 0.790527f, 0.890137f, 0.936523f, 0.959473f, 0.973145f, 0.980469f, 0.985352f,
+ 0.988770f, 0.990723f, 0.992676f, 0.994141f, 0.995117f, 0.996094f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000241f, 0.000237f, 0.000340f, 0.000457f, 0.000580f, 0.000481f, 0.000601f, 0.000605f, 0.000742f, 0.000951f, 0.000953f,
+ 0.001131f, 0.001257f, 0.001396f, 0.001730f, 0.001936f, 0.002102f, 0.002682f, 0.002762f, 0.003733f, 0.004425f, 0.005344f, 0.006516f,
+ 0.008354f, 0.010971f, 0.014793f, 0.020859f, 0.030640f, 0.048859f, 0.085144f, 0.167358f, 0.350586f, 0.620117f, 0.811035f, 0.900391f,
+ 0.942383f, 0.963379f, 0.975098f, 0.981934f, 0.986816f, 0.989746f, 0.992188f, 0.993164f, 0.994629f, 0.995117f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000131f, 0.000301f, 0.000430f, 0.000470f, 0.000593f,
+ 0.000571f, 0.000587f, 0.000693f, 0.000906f, 0.000959f, 0.000965f, 0.001094f, 0.001364f, 0.001522f, 0.001783f, 0.002094f, 0.002615f,
+ 0.003038f, 0.003365f, 0.004307f, 0.005135f, 0.006493f, 0.008347f, 0.011055f, 0.014824f, 0.020844f, 0.031204f, 0.050507f, 0.090027f,
+ 0.182129f, 0.385498f, 0.659668f, 0.834473f, 0.913086f, 0.949219f, 0.967285f, 0.978027f, 0.983887f, 0.987793f, 0.991211f, 0.992188f,
+ 0.994141f, 0.995117f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000189f, 0.000122f, 0.000122f,
+ 0.000241f, 0.000295f, 0.000425f, 0.000457f, 0.000592f, 0.000481f, 0.000603f, 0.000697f, 0.000926f, 0.000943f, 0.000960f, 0.001022f,
+ 0.001435f, 0.001632f, 0.001658f, 0.002024f, 0.002468f, 0.003010f, 0.003210f, 0.004124f, 0.005219f, 0.006351f, 0.008163f, 0.010933f,
+ 0.015030f, 0.021271f, 0.032257f, 0.053009f, 0.097534f, 0.203003f, 0.432373f, 0.704102f, 0.858887f, 0.924805f, 0.955566f, 0.970703f,
+ 0.979492f, 0.985840f, 0.989258f, 0.991699f, 0.993164f, 0.995117f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000214f, 0.000201f, 0.000239f, 0.000241f, 0.000383f, 0.000461f, 0.000474f, 0.000479f, 0.000598f,
+ 0.000736f, 0.000905f, 0.000947f, 0.001072f, 0.001180f, 0.001376f, 0.001572f, 0.001752f, 0.001900f, 0.002258f, 0.002792f, 0.003487f,
+ 0.004055f, 0.005161f, 0.006424f, 0.008209f, 0.010933f, 0.015030f, 0.021942f, 0.033630f, 0.056671f, 0.107666f, 0.233276f, 0.492188f,
+ 0.752441f, 0.881836f, 0.937012f, 0.961914f, 0.975098f, 0.982910f, 0.987305f, 0.990234f, 0.992676f, 0.994629f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998047f, 0.998535f, 0.998535f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000132f, 0.000224f, 0.000129f, 0.000237f, 0.000240f,
+ 0.000337f, 0.000430f, 0.000468f, 0.000579f, 0.000593f, 0.000602f, 0.000881f, 0.000936f, 0.000956f, 0.000963f, 0.001282f, 0.001519f,
+ 0.001607f, 0.001852f, 0.002150f, 0.002737f, 0.003508f, 0.003990f, 0.005077f, 0.006516f, 0.008179f, 0.011185f, 0.015511f, 0.022446f,
+ 0.035614f, 0.061859f, 0.122681f, 0.275879f, 0.563965f, 0.798828f, 0.903809f, 0.946777f, 0.967773f, 0.978516f, 0.984863f, 0.988770f,
+ 0.991699f, 0.993652f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000149f, 0.000122f, 0.000207f, 0.000371f, 0.000430f, 0.000573f, 0.000591f, 0.000598f, 0.000597f, 0.000804f,
+ 0.000901f, 0.000948f, 0.001053f, 0.001083f, 0.001376f, 0.001584f, 0.001878f, 0.002331f, 0.002529f, 0.003376f, 0.003944f, 0.005230f,
+ 0.006504f, 0.008537f, 0.011459f, 0.015747f, 0.024002f, 0.038361f, 0.069458f, 0.144409f, 0.336914f, 0.644043f, 0.841797f, 0.922363f,
+ 0.957520f, 0.972656f, 0.981934f, 0.987305f, 0.990234f, 0.993164f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000230f, 0.000234f, 0.000235f, 0.000268f, 0.000400f,
+ 0.000448f, 0.000585f, 0.000590f, 0.000599f, 0.000641f, 0.000788f, 0.000930f, 0.000968f, 0.001107f, 0.001251f, 0.001656f, 0.001701f,
+ 0.002047f, 0.002691f, 0.003437f, 0.003998f, 0.004829f, 0.006329f, 0.008492f, 0.011757f, 0.016525f, 0.025345f, 0.042297f, 0.080200f,
+ 0.177490f, 0.420654f, 0.724121f, 0.878906f, 0.938965f, 0.964355f, 0.977539f, 0.984863f, 0.989746f, 0.992188f, 0.997559f, 0.997559f,
+ 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000214f, 0.000235f, 0.000228f, 0.000240f, 0.000429f, 0.000439f, 0.000574f, 0.000654f, 0.000583f, 0.000493f, 0.000788f, 0.000813f,
+ 0.000947f, 0.001062f, 0.001225f, 0.001569f, 0.001721f, 0.002048f, 0.002844f, 0.002979f, 0.003902f, 0.004997f, 0.006454f, 0.008698f,
+ 0.012192f, 0.018143f, 0.027634f, 0.047913f, 0.095886f, 0.228394f, 0.526855f, 0.796875f, 0.910156f, 0.953125f, 0.973145f, 0.982422f,
+ 0.987793f, 0.991699f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000205f, 0.000236f, 0.000232f, 0.000299f, 0.000446f, 0.000417f,
+ 0.000466f, 0.000580f, 0.000508f, 0.000710f, 0.000800f, 0.000940f, 0.000954f, 0.001228f, 0.001496f, 0.001631f, 0.002043f, 0.002798f,
+ 0.003359f, 0.004139f, 0.004951f, 0.006680f, 0.008995f, 0.012764f, 0.018860f, 0.030823f, 0.056061f, 0.120911f, 0.307617f, 0.645508f,
+ 0.855957f, 0.934082f, 0.964355f, 0.978516f, 0.985840f, 0.990234f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000226f,
+ 0.000122f, 0.000226f, 0.000373f, 0.000272f, 0.000325f, 0.000460f, 0.000471f, 0.000477f, 0.000673f, 0.000877f, 0.000929f, 0.000951f,
+ 0.001129f, 0.001446f, 0.001614f, 0.002096f, 0.002619f, 0.002939f, 0.003941f, 0.005363f, 0.006844f, 0.009491f, 0.013596f, 0.020905f,
+ 0.035370f, 0.068420f, 0.161743f, 0.426270f, 0.755859f, 0.900879f, 0.952148f, 0.973145f, 0.983398f, 0.989746f, 0.997070f, 0.997070f,
+ 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000111f, 0.000236f, 0.000297f, 0.000368f, 0.000449f, 0.000467f,
+ 0.000588f, 0.000641f, 0.000813f, 0.000924f, 0.001035f, 0.001124f, 0.001348f, 0.001764f, 0.001922f, 0.002439f, 0.003160f, 0.004005f,
+ 0.005280f, 0.007107f, 0.010109f, 0.014748f, 0.023148f, 0.041595f, 0.088440f, 0.232910f, 0.578125f, 0.841797f, 0.933594f, 0.965820f,
+ 0.980469f, 0.987305f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000000f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000014f, 0.000011f, 0.000116f,
+ 0.000148f, 0.000128f, 0.000369f, 0.000418f, 0.000563f, 0.000470f, 0.000592f, 0.000776f, 0.000901f, 0.000937f, 0.001112f, 0.001348f,
+ 0.001743f, 0.001904f, 0.002470f, 0.003187f, 0.003986f, 0.005360f, 0.007557f, 0.010674f, 0.016068f, 0.026871f, 0.051666f, 0.122925f,
+ 0.356445f, 0.729492f, 0.901855f, 0.955078f, 0.976074f, 0.985840f, 0.996094f, 0.996582f, 0.996094f, 0.996582f, 0.996094f, 0.996582f,
+ 0.000122f, 0.000122f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000028f, 0.000019f, 0.000014f, 0.000011f, 0.000033f, 0.000118f, 0.000247f, 0.000305f, 0.000412f, 0.000447f, 0.000576f, 0.000587f,
+ 0.000693f, 0.000850f, 0.000949f, 0.001083f, 0.001319f, 0.001557f, 0.001957f, 0.002424f, 0.003340f, 0.004417f, 0.005688f, 0.007774f,
+ 0.011497f, 0.017731f, 0.032257f, 0.068604f, 0.189575f, 0.541992f, 0.843262f, 0.938477f, 0.970703f, 0.983887f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000121f, 0.000118f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000067f, 0.000042f, 0.000028f, 0.000020f, 0.000015f, 0.000066f, 0.000009f, 0.000101f, 0.000118f,
+ 0.000260f, 0.000358f, 0.000520f, 0.000456f, 0.000563f, 0.000711f, 0.000872f, 0.000980f, 0.001059f, 0.001309f, 0.001699f, 0.002066f,
+ 0.002708f, 0.003248f, 0.004166f, 0.005836f, 0.008224f, 0.012619f, 0.021484f, 0.041260f, 0.101074f, 0.323486f, 0.733887f, 0.912109f,
+ 0.962402f, 0.980957f, 0.995117f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.000000f, 0.000000f, 0.000119f, 0.000119f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000105f, 0.000067f, 0.000042f, 0.000029f, 0.000022f,
+ 0.000015f, 0.000011f, 0.000040f, 0.000033f, 0.000153f, 0.000204f, 0.000313f, 0.000501f, 0.000554f, 0.000575f, 0.000585f, 0.000778f,
+ 0.000925f, 0.000980f, 0.001245f, 0.001634f, 0.001989f, 0.002413f, 0.003433f, 0.004028f, 0.005989f, 0.008911f, 0.014374f, 0.026443f,
+ 0.057495f, 0.170166f, 0.549805f, 0.864746f, 0.951172f, 0.977051f, 0.994629f, 0.994629f, 0.994629f, 0.994629f, 0.995605f, 0.994629f,
+ 0.000000f, 0.000046f, 0.000088f, 0.000118f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000108f, 0.000069f, 0.000047f, 0.000030f, 0.000022f, 0.000016f, 0.000012f, 0.000052f, 0.000081f, 0.000100f, 0.000184f, 0.000226f,
+ 0.000400f, 0.000467f, 0.000452f, 0.000597f, 0.000807f, 0.000895f, 0.000942f, 0.001219f, 0.001611f, 0.002022f, 0.002352f, 0.003222f,
+ 0.004177f, 0.006481f, 0.009850f, 0.017517f, 0.034668f, 0.090637f, 0.331055f, 0.776367f, 0.932129f, 0.972656f, 0.994141f, 0.994141f,
+ 0.994629f, 0.994141f, 0.994629f, 0.994629f, 0.000000f, 0.000000f, 0.000000f, 0.000107f, 0.000115f, 0.000112f, 0.000119f, 0.000118f,
+ 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000117f, 0.000072f, 0.000049f, 0.000032f, 0.000023f, 0.000017f, 0.000013f,
+ 0.000011f, 0.000008f, 0.000075f, 0.000151f, 0.000207f, 0.000305f, 0.000509f, 0.000499f, 0.000560f, 0.000704f, 0.000863f, 0.000917f,
+ 0.001220f, 0.001505f, 0.001740f, 0.002174f, 0.003153f, 0.004559f, 0.007095f, 0.011826f, 0.022247f, 0.051147f, 0.173462f, 0.618652f,
+ 0.902344f, 0.966309f, 0.993164f, 0.993652f, 0.992676f, 0.992676f, 0.993164f, 0.993164f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000060f, 0.000102f, 0.000113f, 0.000117f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000120f,
+ 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000078f,
+ 0.000052f, 0.000038f, 0.000027f, 0.000019f, 0.000015f, 0.000011f, 0.000054f, 0.000007f, 0.000085f, 0.000108f, 0.000258f, 0.000466f,
+ 0.000533f, 0.000560f, 0.000662f, 0.000849f, 0.000856f, 0.000965f, 0.001180f, 0.001678f, 0.002075f, 0.003193f, 0.005016f, 0.008095f,
+ 0.014343f, 0.030899f, 0.090820f, 0.401367f, 0.848145f, 0.956543f, 0.992188f, 0.992188f, 0.992188f, 0.992676f, 0.991699f, 0.992188f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000059f, 0.000096f, 0.000107f, 0.000112f, 0.000115f, 0.000116f,
+ 0.000117f, 0.000118f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f,
+ 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000088f, 0.000059f, 0.000041f, 0.000031f, 0.000022f, 0.000017f, 0.000013f, 0.000010f,
+ 0.000056f, 0.000091f, 0.000183f, 0.000201f, 0.000309f, 0.000506f, 0.000547f, 0.000525f, 0.000629f, 0.000613f, 0.000817f, 0.001012f,
+ 0.001640f, 0.002420f, 0.003588f, 0.005520f, 0.009453f, 0.019119f, 0.050415f, 0.214722f, 0.751465f, 0.943848f, 0.990723f, 0.990723f,
+ 0.991211f, 0.991211f, 0.991211f, 0.991211f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000055f, 0.000095f, 0.000103f, 0.000105f, 0.000112f, 0.000114f, 0.000115f, 0.000117f, 0.000117f, 0.000117f, 0.000118f,
+ 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000105f, 0.000069f, 0.000048f,
+ 0.000035f, 0.000025f, 0.000019f, 0.000015f, 0.000011f, 0.000014f, 0.000008f, 0.000071f, 0.000193f, 0.000311f, 0.000315f, 0.000524f,
+ 0.000483f, 0.000558f, 0.000591f, 0.000705f, 0.000950f, 0.001389f, 0.002428f, 0.003494f, 0.006321f, 0.012306f, 0.029480f, 0.108948f,
+ 0.581543f, 0.924316f, 0.989746f, 0.989746f, 0.989258f, 0.989746f, 0.989258f, 0.989746f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000069f, 0.000096f, 0.000103f, 0.000107f,
+ 0.000109f, 0.000112f, 0.000113f, 0.000115f, 0.000115f, 0.000116f, 0.000117f, 0.000117f, 0.000118f, 0.000118f, 0.000118f, 0.000118f,
+ 0.000119f, 0.000119f, 0.000119f, 0.000084f, 0.000061f, 0.000042f, 0.000031f, 0.000023f, 0.000018f, 0.000014f, 0.000011f, 0.000009f,
+ 0.000095f, 0.000127f, 0.000223f, 0.000402f, 0.000432f, 0.000399f, 0.000494f, 0.000535f, 0.000557f, 0.000933f, 0.001474f, 0.002300f,
+ 0.004192f, 0.007919f, 0.017838f, 0.057068f, 0.360840f, 0.890625f, 0.986816f, 0.987793f, 0.987305f, 0.987305f, 0.987793f, 0.987305f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000035f, 0.000041f, 0.000088f, 0.000098f, 0.000103f, 0.000106f, 0.000110f, 0.000110f, 0.000113f, 0.000113f,
+ 0.000115f, 0.000116f, 0.000116f, 0.000117f, 0.000117f, 0.000117f, 0.000117f, 0.000118f, 0.000111f, 0.000074f, 0.000053f, 0.000038f,
+ 0.000029f, 0.000022f, 0.000016f, 0.000013f, 0.000010f, 0.000008f, 0.000073f, 0.000152f, 0.000296f, 0.000369f, 0.000365f, 0.000437f,
+ 0.000507f, 0.000661f, 0.000876f, 0.001451f, 0.002531f, 0.004898f, 0.010384f, 0.031113f, 0.183838f, 0.833008f, 0.984375f, 0.984863f,
+ 0.984863f, 0.984375f, 0.984863f, 0.984863f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000024f, 0.000044f, 0.000073f,
+ 0.000087f, 0.000097f, 0.000102f, 0.000105f, 0.000108f, 0.000110f, 0.000111f, 0.000113f, 0.000114f, 0.000114f, 0.000115f, 0.000115f,
+ 0.000116f, 0.000116f, 0.000101f, 0.000070f, 0.000052f, 0.000037f, 0.000027f, 0.000021f, 0.000016f, 0.000013f, 0.000010f, 0.000008f,
+ 0.000083f, 0.000183f, 0.000352f, 0.000355f, 0.000362f, 0.000365f, 0.000528f, 0.000790f, 0.001469f, 0.003029f, 0.005970f, 0.017242f,
+ 0.089050f, 0.728516f, 0.980957f, 0.981445f, 0.981445f, 0.980957f, 0.980957f, 0.981445f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000033f, 0.000041f, 0.000073f, 0.000083f, 0.000088f, 0.000097f, 0.000102f,
+ 0.000105f, 0.000108f, 0.000108f, 0.000111f, 0.000112f, 0.000113f, 0.000113f, 0.000114f, 0.000097f, 0.000068f, 0.000049f, 0.000038f,
+ 0.000028f, 0.000021f, 0.000016f, 0.000013f, 0.000010f, 0.000056f, 0.000151f, 0.000243f, 0.000264f, 0.000221f, 0.000328f, 0.000449f,
+ 0.000850f, 0.001612f, 0.003340f, 0.009361f, 0.043121f, 0.548340f, 0.976074f, 0.976562f, 0.975586f, 0.976074f, 0.976074f, 0.976562f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000019f, 0.000052f, 0.000065f, 0.000077f, 0.000088f, 0.000094f, 0.000098f, 0.000100f, 0.000104f, 0.000106f, 0.000108f,
+ 0.000109f, 0.000110f, 0.000095f, 0.000069f, 0.000052f, 0.000037f, 0.000028f, 0.000021f, 0.000017f, 0.000013f, 0.000025f, 0.000063f,
+ 0.000195f, 0.000233f, 0.000205f, 0.000264f, 0.000401f, 0.000789f, 0.001532f, 0.004520f, 0.020844f, 0.321289f, 0.969238f, 0.968750f,
+ 0.969238f, 0.968750f, 0.969238f, 0.969238f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000018f, 0.000039f, 0.000053f,
+ 0.000066f, 0.000079f, 0.000086f, 0.000090f, 0.000096f, 0.000100f, 0.000102f, 0.000105f, 0.000098f, 0.000074f, 0.000053f, 0.000041f,
+ 0.000031f, 0.000023f, 0.000017f, 0.000013f, 0.000028f, 0.000139f, 0.000189f, 0.000179f, 0.000219f, 0.000333f, 0.000840f, 0.002119f,
+ 0.009193f, 0.144775f, 0.958496f, 0.958496f, 0.958008f, 0.958496f, 0.958008f, 0.958008f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000025f, 0.000040f, 0.000052f, 0.000067f, 0.000077f, 0.000082f,
+ 0.000089f, 0.000093f, 0.000097f, 0.000079f, 0.000059f, 0.000044f, 0.000033f, 0.000024f, 0.000018f, 0.000014f, 0.000034f, 0.000084f,
+ 0.000157f, 0.000199f, 0.000309f, 0.000817f, 0.003424f, 0.054901f, 0.940918f, 0.940918f, 0.940918f, 0.940918f, 0.941406f, 0.940430f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000021f, 0.000040f, 0.000054f, 0.000063f, 0.000072f, 0.000078f, 0.000085f, 0.000065f, 0.000049f,
+ 0.000036f, 0.000026f, 0.000019f, 0.000014f, 0.000042f, 0.000114f, 0.000122f, 0.000276f, 0.001024f, 0.016357f, 0.912109f, 0.912598f,
+ 0.911621f, 0.912598f, 0.911621f, 0.913086f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000016f, 0.000032f, 0.000045f, 0.000056f, 0.000065f, 0.000054f, 0.000039f, 0.000028f, 0.000019f, 0.000013f, 0.000049f, 0.000079f,
+ 0.000226f, 0.003199f, 0.860840f, 0.859863f, 0.860352f, 0.860840f, 0.860840f, 0.860352f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000021f, 0.000035f,
+ 0.000040f, 0.000027f, 0.000018f, 0.000013f, 0.000033f, 0.000333f, 0.764160f, 0.765137f, 0.764648f, 0.764648f, 0.764648f, 0.765137f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000011f, 0.000009f, 0.600586f, 0.602051f,
+ 0.602051f, 0.601562f, 0.601074f, 0.601074f,
+ },
+ {
+ 0.142456f, 0.713867f, 0.883789f, 0.933105f, 0.953613f, 0.964844f, 0.972168f, 0.977539f, 0.980957f, 0.983398f, 0.985352f, 0.987305f,
+ 0.989258f, 0.989746f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.995605f,
+ 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.012886f, 0.087646f, 0.360840f, 0.709473f, 0.859863f, 0.916992f, 0.943848f, 0.958496f,
+ 0.967773f, 0.973633f, 0.978516f, 0.980957f, 0.984375f, 0.986328f, 0.987793f, 0.988770f, 0.990234f, 0.991211f, 0.992188f, 0.993164f,
+ 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f,
+ 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.003895f, 0.020126f, 0.063599f, 0.188721f,
+ 0.464844f, 0.727539f, 0.853027f, 0.909668f, 0.938477f, 0.954590f, 0.965332f, 0.971680f, 0.976562f, 0.979980f, 0.982910f, 0.985840f,
+ 0.986816f, 0.988770f, 0.990234f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f,
+ 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f,
+ 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.002062f, 0.008438f, 0.021774f, 0.049713f, 0.117676f, 0.279541f, 0.541016f, 0.751465f, 0.855469f, 0.909180f, 0.936035f, 0.952637f,
+ 0.963379f, 0.970703f, 0.975098f, 0.979492f, 0.982910f, 0.984863f, 0.986328f, 0.987793f, 0.989258f, 0.990234f, 0.990723f, 0.992188f,
+ 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f,
+ 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.001335f, 0.004597f, 0.010628f, 0.020844f, 0.040283f, 0.082764f, 0.177612f, 0.366211f,
+ 0.605469f, 0.773926f, 0.863281f, 0.910156f, 0.936035f, 0.952148f, 0.962402f, 0.969727f, 0.975098f, 0.979004f, 0.982422f, 0.984863f,
+ 0.986328f, 0.988281f, 0.988770f, 0.989746f, 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995117f,
+ 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f,
+ 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000851f, 0.002769f, 0.006130f, 0.010994f,
+ 0.019394f, 0.034943f, 0.063293f, 0.122253f, 0.244019f, 0.448242f, 0.660156f, 0.798828f, 0.872559f, 0.914062f, 0.937988f, 0.954102f,
+ 0.961914f, 0.970215f, 0.974609f, 0.978516f, 0.981934f, 0.984375f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.991211f, 0.991699f,
+ 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f,
+ 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000466f, 0.001933f, 0.003809f, 0.007095f, 0.011353f, 0.018204f, 0.030029f, 0.050568f, 0.090759f, 0.170898f, 0.318848f, 0.526367f,
+ 0.708496f, 0.820801f, 0.884277f, 0.918457f, 0.940918f, 0.954102f, 0.963867f, 0.970215f, 0.975098f, 0.978516f, 0.981934f, 0.984863f,
+ 0.986328f, 0.988281f, 0.988770f, 0.990234f, 0.991211f, 0.991699f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.994629f, 0.995605f,
+ 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000487f, 0.001685f, 0.002766f, 0.004467f, 0.007305f, 0.011215f, 0.017136f, 0.026489f,
+ 0.042419f, 0.071716f, 0.125244f, 0.228271f, 0.399658f, 0.599609f, 0.751953f, 0.842773f, 0.894531f, 0.924805f, 0.943359f, 0.955566f,
+ 0.965820f, 0.971191f, 0.976562f, 0.979980f, 0.981934f, 0.984863f, 0.986816f, 0.988281f, 0.989258f, 0.990723f, 0.991211f, 0.992188f,
+ 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f,
+ 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000965f, 0.002024f, 0.003202f,
+ 0.005009f, 0.007050f, 0.011070f, 0.015869f, 0.023987f, 0.036835f, 0.058563f, 0.097168f, 0.169800f, 0.297852f, 0.484131f, 0.664062f,
+ 0.789062f, 0.861816f, 0.905273f, 0.930176f, 0.947266f, 0.958984f, 0.967285f, 0.972168f, 0.976562f, 0.980469f, 0.982910f, 0.984863f,
+ 0.986816f, 0.988770f, 0.989746f, 0.990723f, 0.992188f, 0.992188f, 0.993652f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.995605f,
+ 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000244f, 0.000974f, 0.001576f, 0.002403f, 0.003510f, 0.005344f, 0.007332f, 0.010567f, 0.015099f, 0.022064f, 0.032104f, 0.048706f,
+ 0.078003f, 0.130249f, 0.224243f, 0.378174f, 0.566406f, 0.720703f, 0.820312f, 0.879883f, 0.915039f, 0.936523f, 0.951660f, 0.961426f,
+ 0.968262f, 0.974121f, 0.978027f, 0.980957f, 0.983887f, 0.985840f, 0.987793f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.992676f,
+ 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997070f,
+ 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000240f, 0.000609f, 0.001096f, 0.001580f, 0.002674f, 0.004131f, 0.005245f, 0.007660f,
+ 0.010757f, 0.014221f, 0.019775f, 0.028381f, 0.041870f, 0.064697f, 0.103638f, 0.173706f, 0.293945f, 0.466553f, 0.642090f, 0.769531f,
+ 0.849121f, 0.895996f, 0.924316f, 0.942871f, 0.956055f, 0.963867f, 0.970703f, 0.975098f, 0.979004f, 0.981934f, 0.984863f, 0.986328f,
+ 0.988770f, 0.989746f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000608f, 0.001062f, 0.001268f,
+ 0.002001f, 0.003099f, 0.003937f, 0.005379f, 0.007595f, 0.010078f, 0.013176f, 0.018524f, 0.025787f, 0.036896f, 0.054932f, 0.085327f,
+ 0.137573f, 0.229980f, 0.376953f, 0.555664f, 0.708984f, 0.810547f, 0.873047f, 0.909180f, 0.933594f, 0.948730f, 0.959961f, 0.967285f,
+ 0.973145f, 0.977539f, 0.980469f, 0.983398f, 0.985840f, 0.986816f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.993164f, 0.993652f,
+ 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000244f, 0.000606f, 0.000609f, 0.001317f, 0.001564f, 0.002674f, 0.003273f, 0.004402f, 0.005630f, 0.007141f, 0.009514f, 0.012398f,
+ 0.016678f, 0.023331f, 0.032776f, 0.047363f, 0.071594f, 0.112610f, 0.183960f, 0.303711f, 0.470215f, 0.639648f, 0.766113f, 0.844727f,
+ 0.892090f, 0.921875f, 0.941895f, 0.954590f, 0.963379f, 0.970215f, 0.975098f, 0.979004f, 0.981934f, 0.984863f, 0.986328f, 0.987793f,
+ 0.989746f, 0.991211f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996094f,
+ 0.996582f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000244f, 0.000727f, 0.000803f, 0.001575f, 0.002035f, 0.002821f, 0.003527f,
+ 0.004475f, 0.005421f, 0.007023f, 0.009491f, 0.011879f, 0.015976f, 0.021530f, 0.029587f, 0.041809f, 0.061737f, 0.094360f, 0.150146f,
+ 0.246460f, 0.393066f, 0.566406f, 0.712891f, 0.812500f, 0.872070f, 0.909180f, 0.933105f, 0.948242f, 0.959961f, 0.967773f, 0.972656f,
+ 0.977539f, 0.980957f, 0.982910f, 0.986328f, 0.987305f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994629f,
+ 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000244f, 0.000471f, 0.000727f,
+ 0.000967f, 0.001572f, 0.002161f, 0.002680f, 0.003246f, 0.004337f, 0.005241f, 0.006950f, 0.009087f, 0.011497f, 0.015038f, 0.019913f,
+ 0.026688f, 0.037537f, 0.054352f, 0.080383f, 0.125122f, 0.202515f, 0.327148f, 0.493652f, 0.656250f, 0.774414f, 0.849609f, 0.895508f,
+ 0.923828f, 0.942383f, 0.954590f, 0.963867f, 0.971191f, 0.975586f, 0.979004f, 0.982422f, 0.984863f, 0.987305f, 0.988281f, 0.989746f,
+ 0.990723f, 0.992188f, 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f,
+ 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999023f,
+ 0.000121f, 0.000244f, 0.000244f, 0.000715f, 0.001089f, 0.001278f, 0.001781f, 0.002275f, 0.002548f, 0.003334f, 0.004150f, 0.005314f,
+ 0.006824f, 0.008430f, 0.011200f, 0.014145f, 0.018631f, 0.024750f, 0.033905f, 0.047760f, 0.069885f, 0.106445f, 0.169312f, 0.273682f,
+ 0.426270f, 0.596191f, 0.732422f, 0.823242f, 0.879883f, 0.914062f, 0.936035f, 0.950684f, 0.960938f, 0.968750f, 0.973633f, 0.978516f,
+ 0.981934f, 0.984375f, 0.986328f, 0.988281f, 0.989258f, 0.990234f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995117f,
+ 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999512f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999023f, 0.000241f, 0.000244f, 0.000365f, 0.000600f, 0.000961f, 0.000972f, 0.001621f, 0.001697f,
+ 0.002274f, 0.002684f, 0.003359f, 0.004238f, 0.005573f, 0.006691f, 0.008057f, 0.010529f, 0.013832f, 0.017593f, 0.022812f, 0.031174f,
+ 0.042786f, 0.061462f, 0.092407f, 0.143799f, 0.231201f, 0.366943f, 0.535645f, 0.688477f, 0.794922f, 0.861816f, 0.902832f, 0.928711f,
+ 0.945801f, 0.957520f, 0.966797f, 0.972656f, 0.976562f, 0.980469f, 0.983398f, 0.985840f, 0.987793f, 0.989258f, 0.990234f, 0.991699f,
+ 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.997070f, 0.997070f, 0.997559f, 0.997559f,
+ 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000243f, 0.000365f, 0.000365f,
+ 0.000798f, 0.000968f, 0.001249f, 0.001528f, 0.001798f, 0.002457f, 0.002798f, 0.003494f, 0.004353f, 0.005306f, 0.006363f, 0.008141f,
+ 0.010147f, 0.012596f, 0.016006f, 0.021423f, 0.028503f, 0.039185f, 0.055420f, 0.081116f, 0.124390f, 0.198120f, 0.316895f, 0.478516f,
+ 0.641113f, 0.763672f, 0.842773f, 0.891113f, 0.921387f, 0.941406f, 0.954590f, 0.963867f, 0.970215f, 0.975586f, 0.979492f, 0.982910f,
+ 0.985352f, 0.987305f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f,
+ 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000238f, 0.000365f, 0.000365f, 0.000598f, 0.000820f, 0.001200f, 0.001279f, 0.001631f, 0.001736f, 0.002172f, 0.002874f,
+ 0.003576f, 0.004391f, 0.005096f, 0.006176f, 0.007545f, 0.009674f, 0.012505f, 0.015945f, 0.020187f, 0.026550f, 0.035706f, 0.049835f,
+ 0.072510f, 0.109253f, 0.171631f, 0.275391f, 0.426514f, 0.594238f, 0.730469f, 0.822754f, 0.877930f, 0.913574f, 0.936523f, 0.951172f,
+ 0.961426f, 0.969727f, 0.974609f, 0.978027f, 0.982422f, 0.984863f, 0.986816f, 0.988770f, 0.989746f, 0.991699f, 0.992188f, 0.993164f,
+ 0.993652f, 0.994629f, 0.994629f, 0.995117f, 0.996094f, 0.996094f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000364f, 0.000486f, 0.000487f, 0.000562f, 0.000822f, 0.000967f,
+ 0.001213f, 0.001871f, 0.001803f, 0.002485f, 0.002796f, 0.003410f, 0.004242f, 0.005070f, 0.006153f, 0.007698f, 0.009262f, 0.011635f,
+ 0.014709f, 0.019104f, 0.024521f, 0.033295f, 0.045746f, 0.065674f, 0.096741f, 0.150635f, 0.241455f, 0.380127f, 0.548828f, 0.698242f,
+ 0.802246f, 0.867188f, 0.906738f, 0.931152f, 0.948242f, 0.959473f, 0.967285f, 0.973633f, 0.978516f, 0.981445f, 0.984375f, 0.986328f,
+ 0.988281f, 0.989258f, 0.990723f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.996582f,
+ 0.997559f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000350f, 0.000483f,
+ 0.000486f, 0.000604f, 0.000743f, 0.001093f, 0.001187f, 0.001297f, 0.001601f, 0.001921f, 0.002501f, 0.002922f, 0.003296f, 0.004200f,
+ 0.005211f, 0.006054f, 0.007603f, 0.008904f, 0.011169f, 0.014091f, 0.017685f, 0.023331f, 0.030991f, 0.042358f, 0.059326f, 0.087646f,
+ 0.134521f, 0.213867f, 0.341309f, 0.506348f, 0.665039f, 0.780762f, 0.854492f, 0.899414f, 0.927246f, 0.945312f, 0.957520f, 0.966309f,
+ 0.973145f, 0.977539f, 0.981445f, 0.984375f, 0.986328f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994629f,
+ 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000000f, 0.000120f, 0.000360f, 0.000485f, 0.000486f, 0.000487f, 0.000604f, 0.000947f, 0.001201f, 0.001374f, 0.001715f,
+ 0.002127f, 0.002239f, 0.002876f, 0.003426f, 0.004063f, 0.005276f, 0.005810f, 0.006744f, 0.008713f, 0.010597f, 0.013680f, 0.016754f,
+ 0.021744f, 0.028778f, 0.039093f, 0.054901f, 0.079956f, 0.121399f, 0.191895f, 0.307861f, 0.468262f, 0.633301f, 0.760742f, 0.842285f,
+ 0.892090f, 0.923340f, 0.942383f, 0.956543f, 0.965332f, 0.972168f, 0.977539f, 0.980469f, 0.983887f, 0.985840f, 0.988281f, 0.989746f,
+ 0.990723f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000121f, 0.000219f, 0.000474f, 0.000484f, 0.000486f, 0.000487f,
+ 0.000720f, 0.001108f, 0.001199f, 0.001209f, 0.001689f, 0.002253f, 0.002489f, 0.002916f, 0.003714f, 0.004040f, 0.005054f, 0.006001f,
+ 0.006737f, 0.008713f, 0.010376f, 0.012665f, 0.016251f, 0.020615f, 0.027145f, 0.036499f, 0.050720f, 0.073181f, 0.110474f, 0.174072f,
+ 0.280518f, 0.434570f, 0.604980f, 0.742188f, 0.830566f, 0.885742f, 0.918945f, 0.940918f, 0.954102f, 0.964355f, 0.971680f, 0.977051f,
+ 0.980957f, 0.984375f, 0.986816f, 0.988281f, 0.989746f, 0.990723f, 0.992188f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f,
+ 0.996582f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000120f, 0.000239f,
+ 0.000319f, 0.000475f, 0.000484f, 0.000485f, 0.000618f, 0.000844f, 0.001094f, 0.001201f, 0.001570f, 0.001782f, 0.002010f, 0.002407f,
+ 0.003046f, 0.003099f, 0.004208f, 0.004700f, 0.005882f, 0.006878f, 0.007980f, 0.009949f, 0.012344f, 0.015358f, 0.019821f, 0.026047f,
+ 0.034271f, 0.047455f, 0.067993f, 0.102112f, 0.160034f, 0.258057f, 0.406494f, 0.578613f, 0.723633f, 0.820312f, 0.880371f, 0.916016f,
+ 0.938965f, 0.953125f, 0.963867f, 0.971191f, 0.976562f, 0.980469f, 0.983887f, 0.985840f, 0.988770f, 0.989746f, 0.991699f, 0.992676f,
+ 0.993652f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.999023f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000242f, 0.000455f, 0.000481f, 0.000583f, 0.000601f, 0.000804f, 0.000912f, 0.001247f,
+ 0.001319f, 0.001571f, 0.001793f, 0.002337f, 0.002464f, 0.003099f, 0.003164f, 0.003809f, 0.004627f, 0.005764f, 0.006397f, 0.008118f,
+ 0.009605f, 0.011917f, 0.015083f, 0.018692f, 0.024384f, 0.032806f, 0.044983f, 0.063477f, 0.095337f, 0.148560f, 0.240112f, 0.382324f,
+ 0.556641f, 0.708984f, 0.812500f, 0.875488f, 0.913574f, 0.937500f, 0.953125f, 0.963867f, 0.971191f, 0.977051f, 0.980957f, 0.983887f,
+ 0.986816f, 0.988281f, 0.990234f, 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.995605f, 0.995605f, 0.996094f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000240f, 0.000242f, 0.000524f, 0.000597f,
+ 0.000604f, 0.000606f, 0.000674f, 0.001040f, 0.001238f, 0.001427f, 0.001637f, 0.001670f, 0.002104f, 0.002432f, 0.002775f, 0.003416f,
+ 0.003860f, 0.004482f, 0.005573f, 0.006374f, 0.007828f, 0.009384f, 0.011635f, 0.014175f, 0.018219f, 0.023224f, 0.031052f, 0.042603f,
+ 0.060730f, 0.089661f, 0.139526f, 0.225464f, 0.363525f, 0.538574f, 0.696289f, 0.806152f, 0.872559f, 0.912109f, 0.937012f, 0.952637f,
+ 0.963867f, 0.971191f, 0.976562f, 0.981445f, 0.984863f, 0.987305f, 0.988770f, 0.990723f, 0.992188f, 0.993164f, 0.994141f, 0.994629f,
+ 0.995117f, 0.996094f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000119f,
+ 0.000192f, 0.000240f, 0.000242f, 0.000535f, 0.000478f, 0.000600f, 0.000843f, 0.000925f, 0.001027f, 0.001236f, 0.001502f, 0.001490f,
+ 0.001658f, 0.002256f, 0.002430f, 0.002880f, 0.003056f, 0.003983f, 0.004292f, 0.005333f, 0.006264f, 0.007393f, 0.009064f, 0.011131f,
+ 0.013741f, 0.017242f, 0.022690f, 0.029922f, 0.040680f, 0.057831f, 0.085022f, 0.132446f, 0.214844f, 0.349121f, 0.524414f, 0.688477f,
+ 0.801758f, 0.871094f, 0.912109f, 0.937500f, 0.953125f, 0.964355f, 0.971680f, 0.977539f, 0.981445f, 0.985352f, 0.987305f, 0.989258f,
+ 0.991211f, 0.992188f, 0.993652f, 0.994629f, 0.995117f, 0.995605f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000232f, 0.000233f, 0.000363f, 0.000457f, 0.000714f, 0.000724f, 0.000727f,
+ 0.000847f, 0.000992f, 0.001177f, 0.001525f, 0.001560f, 0.001740f, 0.002090f, 0.002329f, 0.002718f, 0.003372f, 0.003902f, 0.004307f,
+ 0.005184f, 0.005886f, 0.007446f, 0.008667f, 0.010574f, 0.013588f, 0.016556f, 0.021744f, 0.028854f, 0.039124f, 0.055176f, 0.081726f,
+ 0.127075f, 0.206421f, 0.338867f, 0.515625f, 0.683105f, 0.800293f, 0.870605f, 0.912598f, 0.937500f, 0.954590f, 0.965332f, 0.973145f,
+ 0.978516f, 0.982422f, 0.985840f, 0.988281f, 0.989746f, 0.991211f, 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000103f, 0.000120f, 0.000240f, 0.000240f,
+ 0.000484f, 0.000574f, 0.000596f, 0.000837f, 0.000820f, 0.000859f, 0.000985f, 0.001070f, 0.001509f, 0.001554f, 0.001785f, 0.002214f,
+ 0.002476f, 0.002754f, 0.002991f, 0.003487f, 0.004303f, 0.005074f, 0.005920f, 0.007126f, 0.008743f, 0.010361f, 0.013023f, 0.016403f,
+ 0.021011f, 0.027817f, 0.037811f, 0.053375f, 0.079041f, 0.123291f, 0.201172f, 0.333252f, 0.511719f, 0.682129f, 0.801270f, 0.872070f,
+ 0.914062f, 0.939941f, 0.955078f, 0.966309f, 0.973633f, 0.979004f, 0.982910f, 0.986328f, 0.988770f, 0.990234f, 0.991699f, 0.992676f,
+ 0.993652f, 0.995117f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000079f, 0.000053f, 0.000118f, 0.000418f, 0.000358f, 0.000363f, 0.000678f, 0.000708f, 0.000825f, 0.000838f, 0.000878f, 0.001146f,
+ 0.000978f, 0.001483f, 0.001541f, 0.001769f, 0.001812f, 0.002434f, 0.002699f, 0.003225f, 0.003298f, 0.004002f, 0.004948f, 0.005932f,
+ 0.007084f, 0.008461f, 0.010414f, 0.012665f, 0.015915f, 0.020615f, 0.027023f, 0.036743f, 0.051941f, 0.077332f, 0.120789f, 0.198608f,
+ 0.331543f, 0.512695f, 0.686523f, 0.805664f, 0.875488f, 0.917480f, 0.941406f, 0.957031f, 0.968262f, 0.975098f, 0.980469f, 0.983887f,
+ 0.986816f, 0.989258f, 0.990723f, 0.992188f, 0.993164f, 0.994629f, 0.998047f, 0.998047f, 0.998535f, 0.998047f, 0.998535f, 0.998535f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000109f, 0.000232f, 0.000349f, 0.000478f, 0.000483f, 0.000483f, 0.000609f,
+ 0.000795f, 0.000835f, 0.000806f, 0.000726f, 0.001022f, 0.001222f, 0.001442f, 0.001536f, 0.001650f, 0.001714f, 0.002377f, 0.002588f,
+ 0.003159f, 0.003643f, 0.004036f, 0.004929f, 0.005718f, 0.006813f, 0.008072f, 0.009880f, 0.012527f, 0.015854f, 0.020035f, 0.026352f,
+ 0.035950f, 0.051178f, 0.076416f, 0.119751f, 0.198730f, 0.334229f, 0.519531f, 0.694824f, 0.812988f, 0.880859f, 0.920898f, 0.944336f,
+ 0.958984f, 0.969727f, 0.976562f, 0.980957f, 0.984863f, 0.987793f, 0.989746f, 0.991211f, 0.992676f, 0.993652f, 0.997559f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000068f, 0.000265f,
+ 0.000361f, 0.000478f, 0.000480f, 0.000479f, 0.000568f, 0.000693f, 0.000714f, 0.000806f, 0.000843f, 0.000919f, 0.001222f, 0.001376f,
+ 0.001531f, 0.001554f, 0.001987f, 0.002342f, 0.002558f, 0.002798f, 0.003132f, 0.004021f, 0.004864f, 0.005455f, 0.006664f, 0.008110f,
+ 0.009613f, 0.011955f, 0.015335f, 0.019608f, 0.025879f, 0.035522f, 0.050629f, 0.075623f, 0.120239f, 0.201416f, 0.342041f, 0.533203f,
+ 0.707031f, 0.821777f, 0.887695f, 0.925293f, 0.946777f, 0.961914f, 0.971680f, 0.977539f, 0.982422f, 0.985352f, 0.988281f, 0.989746f,
+ 0.992188f, 0.993164f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000122f, 0.000000f, 0.000122f, 0.000322f, 0.000241f, 0.000478f, 0.000480f, 0.000480f, 0.000510f, 0.000695f, 0.000710f,
+ 0.000958f, 0.000765f, 0.001075f, 0.001116f, 0.001318f, 0.001606f, 0.001546f, 0.001916f, 0.002306f, 0.002499f, 0.002905f, 0.003202f,
+ 0.003914f, 0.004498f, 0.005459f, 0.006611f, 0.007687f, 0.009331f, 0.011757f, 0.014923f, 0.019241f, 0.025833f, 0.035492f, 0.050507f,
+ 0.076233f, 0.122131f, 0.207153f, 0.355225f, 0.551758f, 0.724609f, 0.833496f, 0.894531f, 0.930664f, 0.951660f, 0.964844f, 0.973145f,
+ 0.979492f, 0.983887f, 0.986816f, 0.989258f, 0.991211f, 0.993164f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.997559f, 0.997559f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000351f, 0.000458f, 0.000476f,
+ 0.000480f, 0.000482f, 0.000528f, 0.000650f, 0.000704f, 0.000956f, 0.000828f, 0.000963f, 0.001111f, 0.001265f, 0.001474f, 0.001806f,
+ 0.001872f, 0.002308f, 0.002445f, 0.002701f, 0.003229f, 0.003851f, 0.004375f, 0.005356f, 0.006317f, 0.007458f, 0.009300f, 0.011574f,
+ 0.014725f, 0.019165f, 0.025696f, 0.035461f, 0.050812f, 0.077637f, 0.125977f, 0.216797f, 0.374756f, 0.576660f, 0.745117f, 0.848145f,
+ 0.904785f, 0.936523f, 0.956055f, 0.967773f, 0.975586f, 0.980957f, 0.984863f, 0.987793f, 0.990234f, 0.992188f, 0.997070f, 0.997559f,
+ 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000292f, 0.000224f, 0.000452f, 0.000453f, 0.000479f, 0.000480f, 0.000517f, 0.000614f, 0.000902f, 0.000712f, 0.000959f,
+ 0.000978f, 0.001100f, 0.001276f, 0.001461f, 0.001524f, 0.001651f, 0.002041f, 0.002350f, 0.002853f, 0.003433f, 0.003622f, 0.004166f,
+ 0.005043f, 0.006187f, 0.007534f, 0.009209f, 0.011551f, 0.014908f, 0.019012f, 0.025406f, 0.035461f, 0.051575f, 0.079651f, 0.131714f,
+ 0.230957f, 0.401367f, 0.607910f, 0.769531f, 0.863281f, 0.914062f, 0.942871f, 0.959961f, 0.970703f, 0.978027f, 0.982910f, 0.986816f,
+ 0.988770f, 0.991699f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000238f, 0.000355f, 0.000449f, 0.000462f, 0.000474f, 0.000477f,
+ 0.000482f, 0.000846f, 0.000726f, 0.000706f, 0.000953f, 0.000889f, 0.001012f, 0.001259f, 0.001390f, 0.001755f, 0.001658f, 0.002060f,
+ 0.002369f, 0.002539f, 0.003170f, 0.003460f, 0.004131f, 0.004993f, 0.006008f, 0.007431f, 0.009109f, 0.011444f, 0.014252f, 0.019058f,
+ 0.025574f, 0.036011f, 0.053162f, 0.083435f, 0.140381f, 0.250488f, 0.436035f, 0.645996f, 0.795898f, 0.880371f, 0.924316f, 0.949219f,
+ 0.963867f, 0.973145f, 0.980469f, 0.984863f, 0.988281f, 0.990723f, 0.997070f, 0.997559f, 0.997070f, 0.997559f, 0.997559f, 0.997070f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000239f,
+ 0.000306f, 0.000440f, 0.000437f, 0.000474f, 0.000478f, 0.000481f, 0.000523f, 0.000664f, 0.000731f, 0.000802f, 0.000935f, 0.001022f,
+ 0.001173f, 0.001314f, 0.001504f, 0.001831f, 0.001984f, 0.002317f, 0.002472f, 0.003199f, 0.003370f, 0.004189f, 0.004868f, 0.005924f,
+ 0.007320f, 0.008926f, 0.011421f, 0.014595f, 0.019119f, 0.026260f, 0.036987f, 0.055176f, 0.088440f, 0.152466f, 0.277832f, 0.479980f,
+ 0.686523f, 0.823242f, 0.895508f, 0.933105f, 0.955566f, 0.969238f, 0.976562f, 0.982422f, 0.986816f, 0.989746f, 0.996582f, 0.997070f,
+ 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000194f, 0.000280f, 0.000417f, 0.000448f, 0.000468f, 0.000476f, 0.000479f, 0.000490f,
+ 0.000845f, 0.000688f, 0.000740f, 0.000945f, 0.000998f, 0.001148f, 0.001266f, 0.001414f, 0.001475f, 0.001667f, 0.002262f, 0.002537f,
+ 0.003019f, 0.003288f, 0.004223f, 0.004768f, 0.005890f, 0.007259f, 0.009026f, 0.011360f, 0.014297f, 0.019272f, 0.026474f, 0.038116f,
+ 0.058197f, 0.095032f, 0.168945f, 0.313965f, 0.533203f, 0.731445f, 0.850098f, 0.911133f, 0.942871f, 0.961914f, 0.972656f, 0.979980f,
+ 0.984863f, 0.988770f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000000f, 0.000000f, 0.000122f, 0.000000f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000187f, 0.000233f, 0.000141f, 0.000271f, 0.000341f,
+ 0.000380f, 0.000465f, 0.000473f, 0.000590f, 0.000605f, 0.000798f, 0.000847f, 0.000934f, 0.000946f, 0.000836f, 0.001009f, 0.001142f,
+ 0.001430f, 0.001495f, 0.001850f, 0.002111f, 0.002541f, 0.003035f, 0.003300f, 0.004139f, 0.004913f, 0.005718f, 0.007141f, 0.008934f,
+ 0.011475f, 0.014832f, 0.019653f, 0.027573f, 0.039917f, 0.062225f, 0.104919f, 0.192017f, 0.362305f, 0.594238f, 0.775879f, 0.875977f,
+ 0.925293f, 0.952148f, 0.967773f, 0.977051f, 0.983398f, 0.988281f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996094f, 0.996582f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000238f, 0.000243f, 0.000238f, 0.000424f, 0.000453f, 0.000467f, 0.000475f, 0.000581f, 0.000689f, 0.000795f,
+ 0.000634f, 0.000823f, 0.001014f, 0.000900f, 0.001083f, 0.001485f, 0.001731f, 0.001851f, 0.002056f, 0.002373f, 0.002621f, 0.003445f,
+ 0.004082f, 0.004578f, 0.005821f, 0.007217f, 0.008881f, 0.011330f, 0.014778f, 0.020416f, 0.028473f, 0.042419f, 0.067993f, 0.118286f,
+ 0.225342f, 0.425293f, 0.661621f, 0.818848f, 0.899902f, 0.939453f, 0.960449f, 0.973145f, 0.980957f, 0.985840f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000205f, 0.000224f, 0.000122f, 0.000231f, 0.000245f, 0.000411f, 0.000520f,
+ 0.000463f, 0.000470f, 0.000587f, 0.000361f, 0.000712f, 0.000694f, 0.000815f, 0.000978f, 0.001055f, 0.001105f, 0.001390f, 0.001438f,
+ 0.001705f, 0.001984f, 0.002333f, 0.002546f, 0.003408f, 0.003876f, 0.004627f, 0.005783f, 0.007198f, 0.008995f, 0.011383f, 0.015396f,
+ 0.020828f, 0.030029f, 0.045654f, 0.075439f, 0.137451f, 0.271973f, 0.503418f, 0.728516f, 0.857910f, 0.920410f, 0.951172f, 0.968262f,
+ 0.977539f, 0.984375f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.000000f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000173f, 0.000150f, 0.000278f, 0.000376f, 0.000427f, 0.000470f, 0.000352f, 0.000356f, 0.000475f, 0.000441f, 0.000709f, 0.000774f,
+ 0.000970f, 0.001013f, 0.000998f, 0.001193f, 0.001397f, 0.001677f, 0.001957f, 0.002268f, 0.002529f, 0.003353f, 0.003874f, 0.004555f,
+ 0.005692f, 0.007160f, 0.008987f, 0.011543f, 0.015732f, 0.021896f, 0.032135f, 0.050140f, 0.086548f, 0.165894f, 0.337646f, 0.593750f,
+ 0.791504f, 0.892090f, 0.938477f, 0.961914f, 0.974609f, 0.982422f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.995117f, 0.995605f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000187f, 0.000130f, 0.000231f, 0.000315f, 0.000298f, 0.000332f, 0.000343f,
+ 0.000465f, 0.000472f, 0.000579f, 0.000717f, 0.000839f, 0.000932f, 0.000817f, 0.001086f, 0.001090f, 0.001545f, 0.001735f, 0.001837f,
+ 0.002485f, 0.002493f, 0.003288f, 0.003828f, 0.004520f, 0.005833f, 0.007156f, 0.009193f, 0.012123f, 0.015839f, 0.022934f, 0.034760f,
+ 0.056488f, 0.102600f, 0.208862f, 0.427734f, 0.687988f, 0.846191f, 0.919434f, 0.952637f, 0.969727f, 0.979980f, 0.993652f, 0.994629f,
+ 0.994141f, 0.994629f, 0.994629f, 0.994629f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000133f,
+ 0.000141f, 0.000234f, 0.000300f, 0.000397f, 0.000436f, 0.000456f, 0.000465f, 0.000534f, 0.000663f, 0.000810f, 0.000796f, 0.000812f,
+ 0.001062f, 0.001237f, 0.001428f, 0.001565f, 0.001818f, 0.002182f, 0.002783f, 0.002943f, 0.003773f, 0.004715f, 0.005482f, 0.007195f,
+ 0.009285f, 0.012207f, 0.016922f, 0.024567f, 0.038483f, 0.066101f, 0.127563f, 0.274170f, 0.540527f, 0.774414f, 0.891113f, 0.940430f,
+ 0.965332f, 0.977539f, 0.993652f, 0.994141f, 0.994629f, 0.994141f, 0.994629f, 0.994141f, 0.000000f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000124f, 0.000116f, 0.000119f, 0.000125f, 0.000121f, 0.000197f, 0.000323f, 0.000418f, 0.000446f, 0.000433f,
+ 0.000467f, 0.000612f, 0.000710f, 0.000783f, 0.000911f, 0.000817f, 0.001161f, 0.001343f, 0.001514f, 0.001707f, 0.002081f, 0.002386f,
+ 0.002882f, 0.003609f, 0.004627f, 0.005478f, 0.007011f, 0.009384f, 0.012695f, 0.017960f, 0.026901f, 0.044067f, 0.080078f, 0.167114f,
+ 0.374023f, 0.664062f, 0.845703f, 0.923340f, 0.957031f, 0.974121f, 0.992676f, 0.993652f, 0.993164f, 0.993652f, 0.993652f, 0.993164f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000121f, 0.000052f, 0.000039f, 0.000029f, 0.000054f, 0.000045f, 0.000118f,
+ 0.000128f, 0.000231f, 0.000387f, 0.000429f, 0.000446f, 0.000544f, 0.000539f, 0.000648f, 0.000749f, 0.000790f, 0.000978f, 0.001102f,
+ 0.001195f, 0.001501f, 0.001761f, 0.001978f, 0.002661f, 0.003170f, 0.003519f, 0.004509f, 0.005344f, 0.007004f, 0.009361f, 0.013229f,
+ 0.019196f, 0.030258f, 0.052002f, 0.102661f, 0.234131f, 0.511230f, 0.774902f, 0.898438f, 0.947754f, 0.970215f, 0.992188f, 0.992676f,
+ 0.993164f, 0.992676f, 0.992188f, 0.992188f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000070f, 0.000052f,
+ 0.000038f, 0.000030f, 0.000023f, 0.000060f, 0.000116f, 0.000121f, 0.000252f, 0.000337f, 0.000306f, 0.000435f, 0.000450f, 0.000562f,
+ 0.000584f, 0.000722f, 0.000858f, 0.000888f, 0.000969f, 0.001230f, 0.001429f, 0.001576f, 0.001827f, 0.002361f, 0.002863f, 0.003267f,
+ 0.004047f, 0.005394f, 0.007256f, 0.009781f, 0.013855f, 0.021439f, 0.035034f, 0.065063f, 0.141724f, 0.346680f, 0.665527f, 0.859375f,
+ 0.934570f, 0.965820f, 0.991699f, 0.991699f, 0.991699f, 0.992188f, 0.991699f, 0.991699f, 0.000000f, 0.000000f, 0.000122f, 0.000121f,
+ 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000099f, 0.000069f, 0.000051f, 0.000039f, 0.000030f, 0.000023f, 0.000024f, 0.000115f, 0.000103f, 0.000224f,
+ 0.000204f, 0.000339f, 0.000407f, 0.000437f, 0.000452f, 0.000489f, 0.000663f, 0.000821f, 0.000922f, 0.001004f, 0.001086f, 0.001279f,
+ 0.001554f, 0.001651f, 0.001997f, 0.002390f, 0.003136f, 0.004223f, 0.005508f, 0.007339f, 0.010094f, 0.014854f, 0.024048f, 0.042664f,
+ 0.087036f, 0.213867f, 0.516113f, 0.799805f, 0.915527f, 0.958984f, 0.990723f, 0.991211f, 0.990723f, 0.990723f, 0.990723f, 0.991211f,
+ 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000096f, 0.000073f, 0.000053f, 0.000040f, 0.000031f,
+ 0.000025f, 0.000020f, 0.000017f, 0.000105f, 0.000110f, 0.000135f, 0.000235f, 0.000380f, 0.000462f, 0.000513f, 0.000556f, 0.000638f,
+ 0.000804f, 0.000868f, 0.000897f, 0.001002f, 0.001079f, 0.001246f, 0.001596f, 0.002153f, 0.002213f, 0.003094f, 0.004158f, 0.005306f,
+ 0.007458f, 0.010887f, 0.017166f, 0.028748f, 0.055176f, 0.128174f, 0.350586f, 0.703613f, 0.888184f, 0.951172f, 0.988770f, 0.989746f,
+ 0.989746f, 0.989746f, 0.989746f, 0.989746f, 0.000122f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000101f, 0.000073f, 0.000057f, 0.000043f, 0.000033f, 0.000027f, 0.000021f, 0.000018f, 0.000105f, 0.000112f, 0.000111f, 0.000161f,
+ 0.000320f, 0.000390f, 0.000421f, 0.000438f, 0.000559f, 0.000665f, 0.000735f, 0.000719f, 0.000704f, 0.000887f, 0.001223f, 0.001384f,
+ 0.001867f, 0.002462f, 0.003216f, 0.004032f, 0.005367f, 0.007988f, 0.012054f, 0.019943f, 0.035919f, 0.078064f, 0.215332f, 0.566895f,
+ 0.845703f, 0.939941f, 0.987793f, 0.988281f, 0.987793f, 0.987793f, 0.988281f, 0.988281f, 0.000000f, 0.000120f, 0.000120f, 0.000120f,
+ 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f,
+ 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000103f, 0.000077f, 0.000061f, 0.000046f, 0.000037f, 0.000030f, 0.000023f,
+ 0.000019f, 0.000016f, 0.000039f, 0.000094f, 0.000181f, 0.000205f, 0.000350f, 0.000392f, 0.000423f, 0.000510f, 0.000619f, 0.000672f,
+ 0.000705f, 0.000632f, 0.000807f, 0.001038f, 0.001278f, 0.001894f, 0.002245f, 0.002758f, 0.003883f, 0.005863f, 0.008636f, 0.013672f,
+ 0.023880f, 0.048828f, 0.127441f, 0.400879f, 0.779297f, 0.925781f, 0.985840f, 0.986328f, 0.986328f, 0.985840f, 0.986328f, 0.986328f,
+ 0.000000f, 0.000100f, 0.000108f, 0.000118f, 0.000119f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f,
+ 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000111f, 0.000086f,
+ 0.000066f, 0.000051f, 0.000041f, 0.000032f, 0.000026f, 0.000021f, 0.000018f, 0.000015f, 0.000086f, 0.000131f, 0.000190f, 0.000293f,
+ 0.000419f, 0.000481f, 0.000477f, 0.000438f, 0.000542f, 0.000564f, 0.000599f, 0.000700f, 0.000916f, 0.001122f, 0.001589f, 0.001997f,
+ 0.002678f, 0.004017f, 0.005814f, 0.009361f, 0.015808f, 0.031250f, 0.075989f, 0.250732f, 0.676758f, 0.904297f, 0.983887f, 0.983887f,
+ 0.983887f, 0.984375f, 0.984375f, 0.983887f, 0.000000f, 0.000000f, 0.000077f, 0.000112f, 0.000104f, 0.000115f, 0.000115f, 0.000117f,
+ 0.000117f, 0.000117f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000119f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000119f,
+ 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000097f, 0.000076f, 0.000060f, 0.000046f, 0.000037f, 0.000030f, 0.000024f, 0.000020f,
+ 0.000045f, 0.000063f, 0.000091f, 0.000140f, 0.000202f, 0.000333f, 0.000305f, 0.000399f, 0.000462f, 0.000452f, 0.000535f, 0.000531f,
+ 0.000631f, 0.000866f, 0.000858f, 0.001307f, 0.001844f, 0.002823f, 0.004070f, 0.006264f, 0.010536f, 0.020035f, 0.045990f, 0.145996f,
+ 0.532227f, 0.874023f, 0.980957f, 0.981445f, 0.980957f, 0.981445f, 0.980957f, 0.981445f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000091f, 0.000103f, 0.000105f, 0.000106f, 0.000111f, 0.000113f, 0.000115f, 0.000114f, 0.000116f, 0.000116f, 0.000117f, 0.000117f,
+ 0.000117f, 0.000117f, 0.000117f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000112f, 0.000084f, 0.000069f,
+ 0.000055f, 0.000043f, 0.000036f, 0.000028f, 0.000024f, 0.000020f, 0.000028f, 0.000039f, 0.000083f, 0.000141f, 0.000211f, 0.000262f,
+ 0.000413f, 0.000305f, 0.000370f, 0.000358f, 0.000489f, 0.000564f, 0.000599f, 0.000893f, 0.001084f, 0.001696f, 0.002697f, 0.004074f,
+ 0.006836f, 0.012878f, 0.028122f, 0.083496f, 0.364014f, 0.826660f, 0.976562f, 0.977539f, 0.977051f, 0.977539f, 0.978027f, 0.977051f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000015f, 0.000086f, 0.000077f, 0.000103f, 0.000100f, 0.000109f,
+ 0.000110f, 0.000111f, 0.000112f, 0.000112f, 0.000114f, 0.000114f, 0.000115f, 0.000115f, 0.000116f, 0.000115f, 0.000116f, 0.000116f,
+ 0.000117f, 0.000117f, 0.000117f, 0.000100f, 0.000079f, 0.000066f, 0.000053f, 0.000041f, 0.000035f, 0.000028f, 0.000023f, 0.000019f,
+ 0.000017f, 0.000034f, 0.000113f, 0.000174f, 0.000257f, 0.000325f, 0.000356f, 0.000324f, 0.000409f, 0.000454f, 0.000474f, 0.000659f,
+ 0.000778f, 0.001243f, 0.001575f, 0.002472f, 0.004105f, 0.007957f, 0.016800f, 0.047852f, 0.217529f, 0.755371f, 0.972656f, 0.973145f,
+ 0.973145f, 0.973145f, 0.973145f, 0.973145f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000028f, 0.000049f, 0.000085f, 0.000081f, 0.000096f, 0.000101f, 0.000104f, 0.000106f, 0.000108f, 0.000109f, 0.000110f,
+ 0.000111f, 0.000112f, 0.000113f, 0.000113f, 0.000114f, 0.000114f, 0.000114f, 0.000115f, 0.000115f, 0.000096f, 0.000078f, 0.000064f,
+ 0.000051f, 0.000043f, 0.000035f, 0.000029f, 0.000024f, 0.000020f, 0.000026f, 0.000055f, 0.000087f, 0.000135f, 0.000248f, 0.000261f,
+ 0.000274f, 0.000258f, 0.000296f, 0.000359f, 0.000474f, 0.000627f, 0.001012f, 0.001484f, 0.002630f, 0.004536f, 0.010277f, 0.027405f,
+ 0.119507f, 0.645996f, 0.966797f, 0.967285f, 0.967285f, 0.967285f, 0.966797f, 0.966797f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000014f, 0.000021f, 0.000065f, 0.000074f,
+ 0.000077f, 0.000091f, 0.000091f, 0.000099f, 0.000098f, 0.000103f, 0.000103f, 0.000106f, 0.000107f, 0.000108f, 0.000109f, 0.000110f,
+ 0.000111f, 0.000111f, 0.000112f, 0.000096f, 0.000079f, 0.000064f, 0.000053f, 0.000043f, 0.000036f, 0.000030f, 0.000024f, 0.000021f,
+ 0.000018f, 0.000028f, 0.000072f, 0.000125f, 0.000233f, 0.000243f, 0.000220f, 0.000258f, 0.000320f, 0.000353f, 0.000630f, 0.000932f,
+ 0.001324f, 0.002357f, 0.005402f, 0.014534f, 0.062561f, 0.493164f, 0.958008f, 0.958008f, 0.958984f, 0.958496f, 0.958496f, 0.958008f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000011f, 0.000035f, 0.000041f, 0.000064f, 0.000074f, 0.000081f, 0.000082f, 0.000090f,
+ 0.000092f, 0.000096f, 0.000099f, 0.000100f, 0.000102f, 0.000104f, 0.000105f, 0.000106f, 0.000107f, 0.000099f, 0.000082f, 0.000067f,
+ 0.000055f, 0.000047f, 0.000038f, 0.000031f, 0.000026f, 0.000022f, 0.000018f, 0.000037f, 0.000071f, 0.000111f, 0.000190f, 0.000204f,
+ 0.000153f, 0.000245f, 0.000299f, 0.000482f, 0.000790f, 0.001330f, 0.002619f, 0.007282f, 0.031097f, 0.318115f, 0.946289f, 0.946777f,
+ 0.946777f, 0.946777f, 0.946777f, 0.946777f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000008f, 0.000029f, 0.000044f, 0.000055f, 0.000063f, 0.000073f, 0.000075f, 0.000081f, 0.000087f, 0.000090f, 0.000092f,
+ 0.000094f, 0.000097f, 0.000099f, 0.000100f, 0.000087f, 0.000071f, 0.000059f, 0.000049f, 0.000040f, 0.000034f, 0.000028f, 0.000024f,
+ 0.000020f, 0.000016f, 0.000072f, 0.000114f, 0.000169f, 0.000147f, 0.000181f, 0.000246f, 0.000367f, 0.000626f, 0.001325f, 0.003117f,
+ 0.013741f, 0.167480f, 0.929688f, 0.929688f, 0.929688f, 0.930176f, 0.930664f, 0.930176f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000019f,
+ 0.000030f, 0.000044f, 0.000049f, 0.000062f, 0.000068f, 0.000072f, 0.000078f, 0.000081f, 0.000084f, 0.000087f, 0.000090f, 0.000079f,
+ 0.000065f, 0.000054f, 0.000044f, 0.000037f, 0.000030f, 0.000025f, 0.000021f, 0.000017f, 0.000052f, 0.000100f, 0.000132f, 0.000130f,
+ 0.000164f, 0.000297f, 0.000552f, 0.001273f, 0.005009f, 0.071594f, 0.903809f, 0.905273f, 0.904297f, 0.904785f, 0.904785f, 0.904785f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000013f, 0.000028f, 0.000036f,
+ 0.000045f, 0.000053f, 0.000060f, 0.000066f, 0.000071f, 0.000075f, 0.000071f, 0.000058f, 0.000049f, 0.000040f, 0.000033f, 0.000027f,
+ 0.000022f, 0.000018f, 0.000032f, 0.000078f, 0.000090f, 0.000123f, 0.000175f, 0.000441f, 0.001637f, 0.022537f, 0.865234f, 0.865234f,
+ 0.865723f, 0.865723f, 0.865234f, 0.864746f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000017f, 0.000027f, 0.000036f, 0.000042f,
+ 0.000050f, 0.000056f, 0.000052f, 0.000043f, 0.000035f, 0.000028f, 0.000022f, 0.000018f, 0.000049f, 0.000055f, 0.000047f, 0.000108f,
+ 0.000342f, 0.004566f, 0.802734f, 0.803711f, 0.803711f, 0.803711f, 0.803711f, 0.803711f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000013f, 0.000022f, 0.000030f, 0.000033f, 0.000027f,
+ 0.000021f, 0.000015f, 0.000011f, 0.000031f, 0.000045f, 0.000449f, 0.708496f, 0.707520f, 0.708984f, 0.708496f, 0.707520f, 0.708008f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000011f, 0.000006f, 0.000007f, 0.575195f, 0.575195f,
+ 0.575195f, 0.575195f, 0.575195f, 0.575195f,
+ },
+ {
+ 0.158813f, 0.632812f, 0.824219f, 0.891602f, 0.924805f, 0.942383f, 0.954102f, 0.962402f, 0.968262f, 0.972656f, 0.976074f, 0.978516f,
+ 0.980957f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.988770f, 0.989746f, 0.989746f, 0.990234f, 0.991211f, 0.992188f, 0.992676f,
+ 0.993652f, 0.993652f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.996582f,
+ 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.019775f, 0.115845f, 0.361084f, 0.642578f, 0.798340f, 0.872559f, 0.911133f, 0.933594f,
+ 0.947266f, 0.957031f, 0.964355f, 0.968750f, 0.973145f, 0.976562f, 0.979492f, 0.981934f, 0.983398f, 0.984863f, 0.986816f, 0.987793f,
+ 0.988770f, 0.989258f, 0.990234f, 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995117f,
+ 0.995605f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.006638f, 0.031082f, 0.089661f, 0.222168f,
+ 0.448242f, 0.663086f, 0.794434f, 0.864258f, 0.903320f, 0.926758f, 0.942383f, 0.953613f, 0.961426f, 0.966797f, 0.972168f, 0.975586f,
+ 0.978027f, 0.980469f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.988281f, 0.989258f, 0.990234f, 0.991211f, 0.991699f, 0.992188f,
+ 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.996582f,
+ 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.003246f, 0.013367f, 0.032806f, 0.072754f, 0.152954f, 0.304199f, 0.509766f, 0.687500f, 0.797852f, 0.862305f, 0.900391f, 0.923828f,
+ 0.940430f, 0.950684f, 0.959473f, 0.965820f, 0.970703f, 0.974121f, 0.977051f, 0.979492f, 0.981934f, 0.983887f, 0.985840f, 0.987305f,
+ 0.987793f, 0.989258f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.992188f, 0.993164f, 0.993652f, 0.993652f, 0.994629f, 0.995117f,
+ 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f,
+ 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.002029f, 0.007267f, 0.016678f, 0.032288f, 0.061462f, 0.115051f, 0.215088f, 0.376709f,
+ 0.562988f, 0.712891f, 0.807617f, 0.865234f, 0.901367f, 0.923828f, 0.939453f, 0.950684f, 0.958984f, 0.965332f, 0.970215f, 0.974609f,
+ 0.977051f, 0.979980f, 0.981934f, 0.983887f, 0.984863f, 0.986328f, 0.988281f, 0.988770f, 0.989746f, 0.990723f, 0.990723f, 0.991699f,
+ 0.992188f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996582f,
+ 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.001274f, 0.004623f, 0.009880f, 0.017792f,
+ 0.030869f, 0.052673f, 0.091431f, 0.160645f, 0.277832f, 0.442383f, 0.610352f, 0.737793f, 0.819824f, 0.870605f, 0.902832f, 0.924805f,
+ 0.939941f, 0.950195f, 0.958496f, 0.964844f, 0.970215f, 0.973633f, 0.977051f, 0.979980f, 0.981934f, 0.983398f, 0.984863f, 0.986328f,
+ 0.987305f, 0.988770f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f,
+ 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.997559f, 0.998047f,
+ 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000943f, 0.003231f, 0.006317f, 0.011040f, 0.018051f, 0.029190f, 0.046936f, 0.075867f, 0.125488f, 0.210449f, 0.341797f, 0.503906f,
+ 0.652344f, 0.761230f, 0.832031f, 0.877441f, 0.906738f, 0.927734f, 0.940918f, 0.951172f, 0.959473f, 0.965820f, 0.970703f, 0.974121f,
+ 0.977051f, 0.979492f, 0.981934f, 0.983398f, 0.985352f, 0.987305f, 0.988281f, 0.989258f, 0.990234f, 0.990723f, 0.991211f, 0.992188f,
+ 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f,
+ 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000731f, 0.001970f, 0.004425f, 0.007351f, 0.011627f, 0.017975f, 0.027161f, 0.041779f,
+ 0.064270f, 0.101685f, 0.164917f, 0.265137f, 0.406494f, 0.561035f, 0.692383f, 0.785156f, 0.845703f, 0.884766f, 0.911621f, 0.930176f,
+ 0.942871f, 0.953125f, 0.959961f, 0.965332f, 0.970703f, 0.974121f, 0.977539f, 0.979492f, 0.982422f, 0.983887f, 0.985840f, 0.987305f,
+ 0.987793f, 0.989258f, 0.990234f, 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.995605f,
+ 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000487f, 0.001872f, 0.003445f, 0.005367f,
+ 0.008400f, 0.012405f, 0.017822f, 0.025345f, 0.037964f, 0.056244f, 0.085327f, 0.132935f, 0.210327f, 0.325928f, 0.471924f, 0.615723f,
+ 0.729004f, 0.807617f, 0.859375f, 0.894043f, 0.916504f, 0.934570f, 0.945801f, 0.955078f, 0.961426f, 0.967285f, 0.972168f, 0.975586f,
+ 0.978516f, 0.980957f, 0.982422f, 0.984863f, 0.985840f, 0.986816f, 0.988770f, 0.989258f, 0.990723f, 0.991699f, 0.992188f, 0.992676f,
+ 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.997070f, 0.997070f, 0.997559f,
+ 0.997559f, 0.998047f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.000363f, 0.001300f, 0.002499f, 0.003784f, 0.006153f, 0.008896f, 0.012367f, 0.017227f, 0.024185f, 0.034241f, 0.049591f, 0.072754f,
+ 0.111023f, 0.170776f, 0.263184f, 0.391113f, 0.535645f, 0.665527f, 0.761719f, 0.828613f, 0.871582f, 0.902344f, 0.922852f, 0.937988f,
+ 0.949219f, 0.957031f, 0.963867f, 0.968750f, 0.972656f, 0.976074f, 0.979004f, 0.981445f, 0.983887f, 0.984863f, 0.986328f, 0.988281f,
+ 0.989258f, 0.990234f, 0.991211f, 0.991699f, 0.992676f, 0.993652f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999023f, 0.999023f, 0.000365f, 0.000972f, 0.001874f, 0.003323f, 0.004669f, 0.006599f, 0.008919f, 0.012360f,
+ 0.016785f, 0.022720f, 0.031616f, 0.044647f, 0.064026f, 0.094055f, 0.141235f, 0.215332f, 0.323486f, 0.459229f, 0.597168f, 0.710449f,
+ 0.791992f, 0.847656f, 0.885254f, 0.910645f, 0.929199f, 0.941895f, 0.952148f, 0.960449f, 0.965332f, 0.970703f, 0.974121f, 0.977539f,
+ 0.979980f, 0.981934f, 0.984375f, 0.985840f, 0.987305f, 0.988770f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.993164f, 0.993164f,
+ 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f,
+ 0.998047f, 0.998535f, 0.999023f, 0.999512f, 0.999023f, 0.999512f, 0.999512f, 0.999023f, 0.000244f, 0.000764f, 0.001375f, 0.002415f,
+ 0.003582f, 0.004963f, 0.006973f, 0.008751f, 0.011726f, 0.016113f, 0.021683f, 0.029129f, 0.040283f, 0.057098f, 0.081421f, 0.119019f,
+ 0.178955f, 0.268311f, 0.390625f, 0.528809f, 0.654785f, 0.751465f, 0.820312f, 0.866211f, 0.896973f, 0.919434f, 0.935547f, 0.946777f,
+ 0.956055f, 0.962402f, 0.968262f, 0.972168f, 0.975098f, 0.979004f, 0.981445f, 0.983398f, 0.985352f, 0.986816f, 0.987793f, 0.989258f,
+ 0.990723f, 0.991211f, 0.992188f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996094f,
+ 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000122f, 0.000606f, 0.001439f, 0.002058f, 0.002743f, 0.004169f, 0.005035f, 0.006775f, 0.009010f, 0.012085f, 0.015717f, 0.020813f,
+ 0.027573f, 0.037170f, 0.050812f, 0.071472f, 0.102905f, 0.151489f, 0.225708f, 0.332031f, 0.463623f, 0.596191f, 0.707031f, 0.787598f,
+ 0.844238f, 0.881348f, 0.908691f, 0.927246f, 0.940918f, 0.951660f, 0.958984f, 0.965820f, 0.970215f, 0.974121f, 0.977539f, 0.979980f,
+ 0.982422f, 0.984375f, 0.985840f, 0.987305f, 0.988281f, 0.990234f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f,
+ 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000118f, 0.000846f, 0.001303f, 0.001593f, 0.002180f, 0.003050f, 0.004353f, 0.005577f,
+ 0.006954f, 0.009331f, 0.011826f, 0.015007f, 0.019653f, 0.025391f, 0.034119f, 0.046112f, 0.063660f, 0.090210f, 0.130737f, 0.192139f,
+ 0.283203f, 0.404053f, 0.537598f, 0.658691f, 0.753418f, 0.818848f, 0.865234f, 0.896973f, 0.918945f, 0.934570f, 0.946289f, 0.955566f,
+ 0.962402f, 0.967285f, 0.972168f, 0.976074f, 0.979004f, 0.981445f, 0.983398f, 0.985840f, 0.986816f, 0.988281f, 0.989258f, 0.990723f,
+ 0.991211f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f,
+ 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000117f, 0.000487f, 0.000957f, 0.001514f,
+ 0.002008f, 0.002619f, 0.003424f, 0.004551f, 0.005836f, 0.007381f, 0.009155f, 0.011459f, 0.014366f, 0.018646f, 0.024017f, 0.031281f,
+ 0.042664f, 0.057068f, 0.080139f, 0.113586f, 0.165894f, 0.243164f, 0.352051f, 0.481934f, 0.610840f, 0.716309f, 0.793945f, 0.847168f,
+ 0.884766f, 0.910645f, 0.928223f, 0.942383f, 0.952637f, 0.959961f, 0.965332f, 0.970703f, 0.975098f, 0.978027f, 0.980957f, 0.983398f,
+ 0.984863f, 0.986816f, 0.988281f, 0.989258f, 0.990723f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.995117f,
+ 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997559f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000000f, 0.000608f, 0.000952f, 0.001111f, 0.001660f, 0.002102f, 0.002817f, 0.003517f, 0.004742f, 0.005585f, 0.007080f, 0.008980f,
+ 0.011078f, 0.014191f, 0.017838f, 0.022614f, 0.029404f, 0.038940f, 0.052551f, 0.071533f, 0.100769f, 0.145020f, 0.211548f, 0.307373f,
+ 0.430176f, 0.561523f, 0.676758f, 0.764648f, 0.828613f, 0.872070f, 0.900879f, 0.921875f, 0.937012f, 0.948730f, 0.957520f, 0.964355f,
+ 0.969238f, 0.973633f, 0.977539f, 0.979980f, 0.982422f, 0.984863f, 0.986328f, 0.987793f, 0.988770f, 0.990234f, 0.991211f, 0.991699f,
+ 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000244f, 0.000576f, 0.000727f, 0.001083f, 0.001186f, 0.001810f, 0.002558f, 0.002968f,
+ 0.003725f, 0.004913f, 0.005955f, 0.007011f, 0.008759f, 0.010918f, 0.013718f, 0.016953f, 0.021423f, 0.027832f, 0.035980f, 0.047913f,
+ 0.064941f, 0.090332f, 0.128174f, 0.185791f, 0.270264f, 0.384033f, 0.514160f, 0.638184f, 0.736328f, 0.807617f, 0.856934f, 0.891602f,
+ 0.915039f, 0.932617f, 0.945801f, 0.954102f, 0.962402f, 0.968262f, 0.972168f, 0.976562f, 0.979492f, 0.981445f, 0.983887f, 0.985840f,
+ 0.987305f, 0.988281f, 0.990234f, 0.990723f, 0.992188f, 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f,
+ 0.996582f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000244f, 0.000708f, 0.000903f,
+ 0.001129f, 0.001511f, 0.002031f, 0.002565f, 0.003189f, 0.004112f, 0.004696f, 0.005989f, 0.006954f, 0.008865f, 0.010826f, 0.013031f,
+ 0.016312f, 0.020493f, 0.026154f, 0.033966f, 0.044159f, 0.059845f, 0.081665f, 0.114929f, 0.164917f, 0.239624f, 0.343750f, 0.469971f,
+ 0.598145f, 0.706055f, 0.786133f, 0.842773f, 0.881348f, 0.908203f, 0.927246f, 0.941895f, 0.952148f, 0.959961f, 0.966797f, 0.971191f,
+ 0.976074f, 0.978516f, 0.981445f, 0.983887f, 0.985352f, 0.987305f, 0.988281f, 0.989258f, 0.990723f, 0.991699f, 0.992676f, 0.993652f,
+ 0.994141f, 0.994629f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.000122f, 0.000244f, 0.000482f, 0.000674f, 0.001029f, 0.001440f, 0.001746f, 0.002153f, 0.002804f, 0.003206f, 0.003859f, 0.004948f,
+ 0.005722f, 0.007206f, 0.008568f, 0.010498f, 0.012413f, 0.015793f, 0.019989f, 0.024826f, 0.031799f, 0.041382f, 0.054932f, 0.074768f,
+ 0.103882f, 0.147949f, 0.213867f, 0.308838f, 0.429932f, 0.560059f, 0.675781f, 0.765625f, 0.827148f, 0.871582f, 0.901367f, 0.923340f,
+ 0.937988f, 0.949707f, 0.958496f, 0.965820f, 0.969727f, 0.974609f, 0.978027f, 0.980469f, 0.983398f, 0.985840f, 0.986816f, 0.988281f,
+ 0.989258f, 0.990723f, 0.992188f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996582f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000244f, 0.000244f, 0.000363f, 0.000604f, 0.000834f, 0.001020f, 0.001548f, 0.001970f,
+ 0.002262f, 0.002548f, 0.003157f, 0.003914f, 0.004681f, 0.005962f, 0.006943f, 0.008263f, 0.010277f, 0.012589f, 0.015144f, 0.018951f,
+ 0.023788f, 0.030014f, 0.039001f, 0.051056f, 0.069092f, 0.094666f, 0.133911f, 0.192993f, 0.279053f, 0.394287f, 0.524414f, 0.646484f,
+ 0.743652f, 0.812988f, 0.861328f, 0.895020f, 0.917969f, 0.935547f, 0.947754f, 0.957520f, 0.963867f, 0.969238f, 0.974121f, 0.978027f,
+ 0.980469f, 0.983398f, 0.984863f, 0.987305f, 0.988281f, 0.989258f, 0.990723f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.994629f,
+ 0.995117f, 0.996094f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000118f, 0.000244f, 0.000244f, 0.000584f,
+ 0.000837f, 0.000847f, 0.001295f, 0.001681f, 0.002018f, 0.002348f, 0.003014f, 0.003157f, 0.004124f, 0.004547f, 0.005432f, 0.006607f,
+ 0.008163f, 0.010071f, 0.011925f, 0.014786f, 0.017990f, 0.022659f, 0.028824f, 0.036621f, 0.047882f, 0.063477f, 0.087158f, 0.122559f,
+ 0.175781f, 0.254639f, 0.363037f, 0.492188f, 0.618652f, 0.722168f, 0.799805f, 0.852051f, 0.889648f, 0.914551f, 0.932129f, 0.944824f,
+ 0.955078f, 0.962891f, 0.968262f, 0.973633f, 0.977051f, 0.980469f, 0.982910f, 0.984863f, 0.987305f, 0.988281f, 0.990234f, 0.991211f,
+ 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.000242f, 0.000243f, 0.000243f, 0.000481f, 0.000742f, 0.000843f, 0.000969f, 0.001348f, 0.001726f, 0.001791f, 0.002348f, 0.002853f,
+ 0.003452f, 0.003735f, 0.004757f, 0.005516f, 0.006744f, 0.008102f, 0.009621f, 0.011948f, 0.014320f, 0.017365f, 0.021698f, 0.027298f,
+ 0.034546f, 0.044891f, 0.059875f, 0.081055f, 0.112915f, 0.161255f, 0.234009f, 0.335693f, 0.462646f, 0.592285f, 0.702637f, 0.785645f,
+ 0.843750f, 0.883301f, 0.911133f, 0.929688f, 0.944336f, 0.954590f, 0.961914f, 0.967773f, 0.973633f, 0.977539f, 0.980469f, 0.982910f,
+ 0.985352f, 0.986816f, 0.988770f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000100f, 0.000216f, 0.000243f, 0.000365f, 0.000517f, 0.000836f, 0.000964f, 0.001148f,
+ 0.001472f, 0.001674f, 0.001785f, 0.002438f, 0.002815f, 0.003490f, 0.004070f, 0.004837f, 0.005608f, 0.006630f, 0.008095f, 0.009483f,
+ 0.011551f, 0.013847f, 0.016953f, 0.020584f, 0.025879f, 0.033051f, 0.042664f, 0.055817f, 0.075500f, 0.105103f, 0.149536f, 0.216553f,
+ 0.312988f, 0.436768f, 0.568359f, 0.685059f, 0.773926f, 0.835449f, 0.878418f, 0.907227f, 0.927734f, 0.943359f, 0.953125f, 0.962402f,
+ 0.967285f, 0.973145f, 0.977051f, 0.980469f, 0.983887f, 0.985352f, 0.987305f, 0.989258f, 0.990234f, 0.991699f, 0.992188f, 0.993164f,
+ 0.994141f, 0.994629f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000150f, 0.000242f, 0.000364f,
+ 0.000441f, 0.000627f, 0.000916f, 0.000959f, 0.000968f, 0.001463f, 0.001671f, 0.002222f, 0.002577f, 0.002714f, 0.003479f, 0.004208f,
+ 0.004723f, 0.005669f, 0.006886f, 0.007637f, 0.009315f, 0.011154f, 0.013596f, 0.016205f, 0.019821f, 0.024963f, 0.031250f, 0.040375f,
+ 0.053009f, 0.071167f, 0.098511f, 0.139648f, 0.202271f, 0.293457f, 0.414307f, 0.548340f, 0.669434f, 0.762695f, 0.829590f, 0.874512f,
+ 0.904785f, 0.926758f, 0.941895f, 0.953613f, 0.961914f, 0.968262f, 0.973633f, 0.977539f, 0.980957f, 0.983398f, 0.985352f, 0.987793f,
+ 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.994629f, 0.998047f, 0.998535f, 0.998047f, 0.998047f, 0.998047f, 0.998047f,
+ 0.000000f, 0.000231f, 0.000232f, 0.000363f, 0.000486f, 0.000503f, 0.000724f, 0.001104f, 0.001080f, 0.001271f, 0.001509f, 0.001976f,
+ 0.002247f, 0.002476f, 0.002895f, 0.003553f, 0.004192f, 0.004871f, 0.005623f, 0.006332f, 0.007584f, 0.008957f, 0.010849f, 0.012917f,
+ 0.015396f, 0.019226f, 0.023941f, 0.030060f, 0.038513f, 0.050385f, 0.067627f, 0.093140f, 0.131714f, 0.190674f, 0.278076f, 0.395752f,
+ 0.530273f, 0.655762f, 0.753906f, 0.823242f, 0.870605f, 0.903320f, 0.925781f, 0.941406f, 0.953125f, 0.961914f, 0.969238f, 0.974121f,
+ 0.978027f, 0.980957f, 0.983887f, 0.985840f, 0.988281f, 0.989258f, 0.990723f, 0.991699f, 0.992676f, 0.993652f, 0.997559f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000009f, 0.000116f, 0.000360f, 0.000484f, 0.000485f, 0.000536f, 0.000827f,
+ 0.000935f, 0.001077f, 0.001204f, 0.001561f, 0.001974f, 0.002136f, 0.002777f, 0.002964f, 0.003517f, 0.004192f, 0.004711f, 0.005505f,
+ 0.006283f, 0.007408f, 0.008713f, 0.010674f, 0.012375f, 0.015099f, 0.018677f, 0.022797f, 0.028732f, 0.036835f, 0.047974f, 0.064270f,
+ 0.088318f, 0.124634f, 0.180664f, 0.264893f, 0.380615f, 0.516113f, 0.645020f, 0.747559f, 0.819824f, 0.870117f, 0.902344f, 0.925293f,
+ 0.941406f, 0.953613f, 0.962402f, 0.969238f, 0.974121f, 0.978027f, 0.981934f, 0.984375f, 0.986328f, 0.988281f, 0.989746f, 0.990723f,
+ 0.992676f, 0.993164f, 0.997559f, 0.998047f, 0.998047f, 0.997559f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000074f, 0.000337f,
+ 0.000481f, 0.000484f, 0.000485f, 0.000556f, 0.000823f, 0.001143f, 0.001187f, 0.001391f, 0.001781f, 0.002155f, 0.002327f, 0.002760f,
+ 0.003008f, 0.003433f, 0.004101f, 0.004681f, 0.005417f, 0.006443f, 0.007393f, 0.008560f, 0.010345f, 0.012177f, 0.014496f, 0.018127f,
+ 0.022125f, 0.027740f, 0.035736f, 0.046173f, 0.061920f, 0.084717f, 0.119324f, 0.173218f, 0.254883f, 0.368652f, 0.505371f, 0.637207f,
+ 0.742676f, 0.818359f, 0.868164f, 0.902832f, 0.925781f, 0.942383f, 0.953613f, 0.963379f, 0.970215f, 0.975098f, 0.979004f, 0.982422f,
+ 0.984863f, 0.986328f, 0.988770f, 0.990723f, 0.991699f, 0.992676f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000188f, 0.000358f, 0.000481f, 0.000484f, 0.000484f, 0.000704f, 0.000852f, 0.001165f, 0.001316f,
+ 0.001500f, 0.001685f, 0.001933f, 0.002079f, 0.002720f, 0.003136f, 0.003727f, 0.003723f, 0.004513f, 0.005207f, 0.006275f, 0.007236f,
+ 0.008453f, 0.010056f, 0.011848f, 0.014191f, 0.017212f, 0.021652f, 0.026978f, 0.034241f, 0.044678f, 0.058990f, 0.081421f, 0.114929f,
+ 0.167236f, 0.247070f, 0.360596f, 0.498291f, 0.632812f, 0.741211f, 0.818359f, 0.869629f, 0.903809f, 0.927734f, 0.943848f, 0.955566f,
+ 0.964355f, 0.970703f, 0.976074f, 0.979492f, 0.982422f, 0.985840f, 0.987793f, 0.989258f, 0.990723f, 0.992188f, 0.997070f, 0.997559f,
+ 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000121f, 0.000120f, 0.000288f, 0.000357f, 0.000479f, 0.000483f,
+ 0.000535f, 0.000711f, 0.000862f, 0.001256f, 0.001351f, 0.001502f, 0.001719f, 0.002146f, 0.002037f, 0.002653f, 0.003248f, 0.003222f,
+ 0.003820f, 0.004456f, 0.005173f, 0.006008f, 0.007072f, 0.008247f, 0.009758f, 0.011826f, 0.013771f, 0.016861f, 0.020935f, 0.025986f,
+ 0.032928f, 0.043030f, 0.057587f, 0.078918f, 0.111755f, 0.162964f, 0.241943f, 0.355713f, 0.495117f, 0.632324f, 0.742676f, 0.819336f,
+ 0.871582f, 0.905762f, 0.929688f, 0.945312f, 0.957031f, 0.965332f, 0.972168f, 0.976562f, 0.980957f, 0.983887f, 0.986328f, 0.988281f,
+ 0.990234f, 0.991699f, 0.997070f, 0.997559f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000121f,
+ 0.000200f, 0.000412f, 0.000471f, 0.000599f, 0.000598f, 0.000596f, 0.000805f, 0.001099f, 0.001334f, 0.001417f, 0.001456f, 0.001723f,
+ 0.002102f, 0.002283f, 0.002579f, 0.003208f, 0.003233f, 0.003740f, 0.004574f, 0.005287f, 0.006012f, 0.006870f, 0.008018f, 0.009354f,
+ 0.011208f, 0.013542f, 0.016495f, 0.020370f, 0.025284f, 0.032410f, 0.041901f, 0.056183f, 0.077087f, 0.109558f, 0.160278f, 0.239380f,
+ 0.354492f, 0.496094f, 0.635254f, 0.747070f, 0.823730f, 0.875488f, 0.908691f, 0.931641f, 0.947266f, 0.958008f, 0.966309f, 0.972656f,
+ 0.978027f, 0.981445f, 0.984863f, 0.986816f, 0.989258f, 0.990723f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000117f, 0.000237f, 0.000239f, 0.000430f, 0.000465f, 0.000599f, 0.000724f, 0.000716f, 0.000815f,
+ 0.000981f, 0.001334f, 0.001299f, 0.001545f, 0.001617f, 0.001935f, 0.002110f, 0.002501f, 0.002823f, 0.003408f, 0.003790f, 0.004467f,
+ 0.005112f, 0.005848f, 0.006718f, 0.007942f, 0.009514f, 0.011093f, 0.013092f, 0.015945f, 0.019608f, 0.024689f, 0.031494f, 0.041046f,
+ 0.054901f, 0.075989f, 0.108032f, 0.158936f, 0.239014f, 0.356201f, 0.500488f, 0.642090f, 0.753418f, 0.830566f, 0.880859f, 0.912598f,
+ 0.935059f, 0.950195f, 0.960449f, 0.968262f, 0.975098f, 0.979980f, 0.982910f, 0.985352f, 0.987793f, 0.990234f, 0.996582f, 0.997070f,
+ 0.997070f, 0.996582f, 0.997070f, 0.996582f, 0.000000f, 0.000000f, 0.000000f, 0.000117f, 0.000120f, 0.000121f, 0.000312f, 0.000407f,
+ 0.000707f, 0.000597f, 0.000648f, 0.000720f, 0.000941f, 0.001008f, 0.001229f, 0.001289f, 0.001423f, 0.001726f, 0.002060f, 0.002211f,
+ 0.002506f, 0.002985f, 0.003036f, 0.003683f, 0.004066f, 0.004833f, 0.005592f, 0.006611f, 0.007675f, 0.008965f, 0.010811f, 0.012833f,
+ 0.015854f, 0.019485f, 0.024429f, 0.031036f, 0.040466f, 0.054108f, 0.074890f, 0.107727f, 0.159180f, 0.241699f, 0.362549f, 0.510742f,
+ 0.653809f, 0.763184f, 0.837891f, 0.887207f, 0.917480f, 0.938477f, 0.953613f, 0.962891f, 0.970703f, 0.976562f, 0.980469f, 0.984375f,
+ 0.986816f, 0.988770f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000000f, 0.000000f, 0.000000f, 0.000117f,
+ 0.000118f, 0.000120f, 0.000129f, 0.000434f, 0.000536f, 0.000613f, 0.000716f, 0.000799f, 0.000720f, 0.000768f, 0.001024f, 0.001202f,
+ 0.001501f, 0.001530f, 0.001568f, 0.001897f, 0.002190f, 0.002502f, 0.002893f, 0.003105f, 0.003551f, 0.004021f, 0.004791f, 0.005405f,
+ 0.006313f, 0.007309f, 0.008720f, 0.010712f, 0.012657f, 0.015472f, 0.018982f, 0.023697f, 0.030579f, 0.040009f, 0.054138f, 0.075012f,
+ 0.107849f, 0.161377f, 0.247070f, 0.373047f, 0.525391f, 0.667969f, 0.776855f, 0.847656f, 0.894043f, 0.923340f, 0.942871f, 0.956543f,
+ 0.965820f, 0.973145f, 0.978027f, 0.982422f, 0.985352f, 0.987793f, 0.996094f, 0.996094f, 0.996582f, 0.996094f, 0.996582f, 0.996094f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000081f, 0.000116f, 0.000227f, 0.000360f, 0.000366f, 0.000642f, 0.000691f, 0.000711f,
+ 0.000806f, 0.000721f, 0.000925f, 0.000947f, 0.001155f, 0.001478f, 0.001554f, 0.001612f, 0.001929f, 0.002354f, 0.002291f, 0.002712f,
+ 0.003029f, 0.003441f, 0.003876f, 0.004452f, 0.005276f, 0.006256f, 0.007149f, 0.008568f, 0.010040f, 0.012566f, 0.015160f, 0.018677f,
+ 0.023376f, 0.030411f, 0.039642f, 0.053986f, 0.075134f, 0.109436f, 0.165527f, 0.255127f, 0.387695f, 0.544434f, 0.686523f, 0.791016f,
+ 0.858398f, 0.901367f, 0.928711f, 0.947266f, 0.959961f, 0.968262f, 0.975098f, 0.980469f, 0.983887f, 0.987305f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000088f, 0.000085f, 0.000338f, 0.000351f,
+ 0.000359f, 0.000480f, 0.000539f, 0.000698f, 0.000798f, 0.000793f, 0.000834f, 0.000891f, 0.000941f, 0.001143f, 0.001422f, 0.001512f,
+ 0.001833f, 0.001955f, 0.002144f, 0.002426f, 0.002716f, 0.003262f, 0.003572f, 0.003860f, 0.004456f, 0.005173f, 0.006191f, 0.006939f,
+ 0.008545f, 0.010162f, 0.012375f, 0.014969f, 0.018555f, 0.023376f, 0.029953f, 0.039673f, 0.054077f, 0.076477f, 0.112000f, 0.171509f,
+ 0.268066f, 0.408203f, 0.569336f, 0.709961f, 0.808105f, 0.872070f, 0.910645f, 0.935059f, 0.951660f, 0.963379f, 0.971680f, 0.977539f,
+ 0.982422f, 0.985840f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000122f, 0.000116f, 0.000340f, 0.000353f, 0.000349f, 0.000480f, 0.000576f, 0.000668f, 0.000700f, 0.000818f, 0.000833f,
+ 0.000787f, 0.001125f, 0.001110f, 0.001407f, 0.001489f, 0.001563f, 0.001804f, 0.002073f, 0.002285f, 0.002409f, 0.002985f, 0.003052f,
+ 0.003853f, 0.004433f, 0.005100f, 0.006046f, 0.007046f, 0.008156f, 0.009827f, 0.012138f, 0.014740f, 0.018311f, 0.023071f, 0.029770f,
+ 0.040009f, 0.054810f, 0.078003f, 0.116150f, 0.180176f, 0.284668f, 0.434570f, 0.599121f, 0.735352f, 0.827637f, 0.885254f, 0.919922f,
+ 0.941895f, 0.957031f, 0.967285f, 0.975098f, 0.979980f, 0.984375f, 0.995117f, 0.995117f, 0.995117f, 0.995117f, 0.995117f, 0.995605f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000000f, 0.000122f, 0.000235f, 0.000320f, 0.000351f, 0.000353f, 0.000478f,
+ 0.000602f, 0.000651f, 0.000793f, 0.000706f, 0.000816f, 0.000814f, 0.000898f, 0.001062f, 0.001259f, 0.001441f, 0.001564f, 0.001772f,
+ 0.001743f, 0.002134f, 0.002512f, 0.002668f, 0.003193f, 0.003746f, 0.004341f, 0.004902f, 0.005909f, 0.006920f, 0.008125f, 0.009605f,
+ 0.011711f, 0.014549f, 0.018280f, 0.023163f, 0.030334f, 0.040375f, 0.055939f, 0.080566f, 0.122070f, 0.192383f, 0.307373f, 0.467773f,
+ 0.634277f, 0.763184f, 0.846191f, 0.897461f, 0.928711f, 0.948730f, 0.962402f, 0.971680f, 0.978516f, 0.982422f, 0.994141f, 0.994629f,
+ 0.994629f, 0.995117f, 0.995117f, 0.995117f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000185f, 0.000190f,
+ 0.000272f, 0.000281f, 0.000464f, 0.000466f, 0.000476f, 0.000521f, 0.000654f, 0.000680f, 0.000699f, 0.000815f, 0.000814f, 0.000890f,
+ 0.001110f, 0.001283f, 0.001311f, 0.001590f, 0.001727f, 0.001801f, 0.002020f, 0.002312f, 0.002897f, 0.003267f, 0.003592f, 0.004143f,
+ 0.004810f, 0.005844f, 0.006618f, 0.008018f, 0.009697f, 0.011597f, 0.014374f, 0.018127f, 0.023056f, 0.030258f, 0.041107f, 0.057373f,
+ 0.084045f, 0.129517f, 0.208618f, 0.337646f, 0.508789f, 0.673828f, 0.793457f, 0.866211f, 0.911133f, 0.938965f, 0.955566f, 0.967285f,
+ 0.975586f, 0.980469f, 0.994141f, 0.994141f, 0.994629f, 0.994629f, 0.994629f, 0.994141f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000226f, 0.000431f, 0.000456f, 0.000467f, 0.000352f, 0.000496f, 0.000588f,
+ 0.000891f, 0.000771f, 0.000803f, 0.000947f, 0.000972f, 0.001078f, 0.001033f, 0.001279f, 0.001436f, 0.001483f, 0.001831f, 0.002033f,
+ 0.002264f, 0.002710f, 0.002996f, 0.003582f, 0.004032f, 0.004665f, 0.005592f, 0.006527f, 0.007820f, 0.009323f, 0.011581f, 0.014328f,
+ 0.018219f, 0.023239f, 0.030777f, 0.042084f, 0.059448f, 0.089233f, 0.140869f, 0.230713f, 0.375977f, 0.556641f, 0.715332f, 0.822266f,
+ 0.885742f, 0.924316f, 0.947266f, 0.962402f, 0.972656f, 0.978516f, 0.993164f, 0.994141f, 0.994141f, 0.994141f, 0.994141f, 0.994141f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000283f, 0.000229f, 0.000425f,
+ 0.000303f, 0.000336f, 0.000469f, 0.000474f, 0.000728f, 0.000663f, 0.000883f, 0.000695f, 0.000679f, 0.000858f, 0.000919f, 0.000980f,
+ 0.001218f, 0.001330f, 0.001665f, 0.001637f, 0.002054f, 0.002335f, 0.002508f, 0.002880f, 0.003323f, 0.004055f, 0.004730f, 0.005463f,
+ 0.006485f, 0.007740f, 0.009293f, 0.011566f, 0.014175f, 0.017944f, 0.023346f, 0.031433f, 0.043304f, 0.063232f, 0.096313f, 0.155518f,
+ 0.260498f, 0.424561f, 0.611328f, 0.758789f, 0.852051f, 0.904785f, 0.937012f, 0.955566f, 0.968262f, 0.977051f, 0.992676f, 0.992676f,
+ 0.993164f, 0.993652f, 0.993164f, 0.993652f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000256f, 0.000216f, 0.000406f, 0.000426f, 0.000457f, 0.000453f, 0.000472f, 0.000651f, 0.000593f, 0.000876f,
+ 0.000571f, 0.000590f, 0.000819f, 0.000809f, 0.001000f, 0.001224f, 0.001293f, 0.001637f, 0.001790f, 0.001863f, 0.002298f, 0.002550f,
+ 0.002995f, 0.003201f, 0.003933f, 0.004677f, 0.005360f, 0.006447f, 0.007763f, 0.009377f, 0.011330f, 0.014420f, 0.017944f, 0.023560f,
+ 0.032196f, 0.045380f, 0.067383f, 0.105469f, 0.175659f, 0.301025f, 0.484375f, 0.669922f, 0.801270f, 0.879395f, 0.922852f, 0.948242f,
+ 0.963379f, 0.974121f, 0.992188f, 0.992188f, 0.992188f, 0.993164f, 0.992188f, 0.993164f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000230f, 0.000206f, 0.000355f, 0.000335f, 0.000305f,
+ 0.000461f, 0.000565f, 0.000474f, 0.000429f, 0.000520f, 0.000758f, 0.000777f, 0.000668f, 0.000821f, 0.001013f, 0.001089f, 0.001325f,
+ 0.001570f, 0.001787f, 0.001707f, 0.002037f, 0.002457f, 0.002892f, 0.003359f, 0.003881f, 0.004616f, 0.005203f, 0.006336f, 0.007477f,
+ 0.009048f, 0.011345f, 0.014015f, 0.018356f, 0.024307f, 0.033661f, 0.048279f, 0.073303f, 0.118774f, 0.204102f, 0.354492f, 0.554688f,
+ 0.729492f, 0.840332f, 0.902832f, 0.937988f, 0.958008f, 0.971191f, 0.991699f, 0.992188f, 0.992188f, 0.991699f, 0.992188f, 0.991699f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000205f, 0.000248f, 0.000213f, 0.000344f, 0.000437f, 0.000351f, 0.000352f, 0.000359f, 0.000389f, 0.000482f, 0.000676f, 0.000560f,
+ 0.000806f, 0.000813f, 0.000927f, 0.001230f, 0.001392f, 0.001526f, 0.001627f, 0.001629f, 0.002047f, 0.002321f, 0.002661f, 0.003317f,
+ 0.003752f, 0.004406f, 0.005119f, 0.005936f, 0.007156f, 0.009003f, 0.010941f, 0.013985f, 0.018539f, 0.025131f, 0.035248f, 0.051880f,
+ 0.081543f, 0.137207f, 0.244507f, 0.424561f, 0.632812f, 0.787598f, 0.876465f, 0.924805f, 0.951172f, 0.966797f, 0.990723f, 0.991211f,
+ 0.991211f, 0.991211f, 0.991211f, 0.991211f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000224f, 0.000171f, 0.000276f, 0.000278f, 0.000288f, 0.000329f, 0.000365f,
+ 0.000459f, 0.000483f, 0.000626f, 0.000716f, 0.000767f, 0.000793f, 0.000800f, 0.000897f, 0.000976f, 0.001156f, 0.001322f, 0.001427f,
+ 0.001799f, 0.001997f, 0.002256f, 0.002773f, 0.002806f, 0.003515f, 0.004040f, 0.004910f, 0.005730f, 0.007046f, 0.008858f, 0.011124f,
+ 0.014374f, 0.018982f, 0.026123f, 0.037659f, 0.057129f, 0.093445f, 0.164062f, 0.301514f, 0.511230f, 0.712402f, 0.838867f, 0.906738f,
+ 0.942383f, 0.961914f, 0.989746f, 0.990234f, 0.989746f, 0.990234f, 0.989746f, 0.990234f, 0.000000f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000173f, 0.000140f,
+ 0.000138f, 0.000232f, 0.000291f, 0.000318f, 0.000338f, 0.000346f, 0.000422f, 0.000368f, 0.000680f, 0.000722f, 0.000765f, 0.000766f,
+ 0.000803f, 0.001069f, 0.001103f, 0.001185f, 0.001611f, 0.001593f, 0.001939f, 0.002211f, 0.002569f, 0.003008f, 0.003239f, 0.003952f,
+ 0.004681f, 0.005630f, 0.007008f, 0.008720f, 0.011200f, 0.014587f, 0.019653f, 0.027527f, 0.040955f, 0.064514f, 0.110413f, 0.204224f,
+ 0.381104f, 0.609863f, 0.785645f, 0.881836f, 0.931152f, 0.956543f, 0.988770f, 0.989258f, 0.989258f, 0.989258f, 0.989258f, 0.988770f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000121f,
+ 0.000121f, 0.000123f, 0.000121f, 0.000090f, 0.000102f, 0.000063f, 0.000156f, 0.000248f, 0.000333f, 0.000321f, 0.000431f, 0.000392f,
+ 0.000349f, 0.000434f, 0.000674f, 0.000741f, 0.000776f, 0.000936f, 0.000888f, 0.001049f, 0.001179f, 0.001326f, 0.001686f, 0.001732f,
+ 0.002050f, 0.002150f, 0.002453f, 0.003016f, 0.003601f, 0.004444f, 0.005692f, 0.006741f, 0.008324f, 0.011093f, 0.014709f, 0.020752f,
+ 0.029800f, 0.045654f, 0.074951f, 0.136108f, 0.264893f, 0.486816f, 0.710938f, 0.848145f, 0.916992f, 0.950684f, 0.987305f, 0.987793f,
+ 0.987793f, 0.988281f, 0.987793f, 0.987793f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000100f, 0.000049f, 0.000039f, 0.000125f, 0.000121f,
+ 0.000184f, 0.000280f, 0.000366f, 0.000392f, 0.000333f, 0.000341f, 0.000477f, 0.000597f, 0.000607f, 0.000747f, 0.000767f, 0.000961f,
+ 0.000936f, 0.001056f, 0.001306f, 0.001388f, 0.001633f, 0.001836f, 0.001997f, 0.002348f, 0.002878f, 0.003332f, 0.004131f, 0.005165f,
+ 0.006519f, 0.008568f, 0.011444f, 0.015419f, 0.021881f, 0.032532f, 0.052032f, 0.091187f, 0.177246f, 0.357910f, 0.610352f, 0.800781f,
+ 0.897461f, 0.942871f, 0.985352f, 0.986328f, 0.986816f, 0.986328f, 0.986328f, 0.986328f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000099f, 0.000076f,
+ 0.000060f, 0.000108f, 0.000040f, 0.000127f, 0.000127f, 0.000121f, 0.000200f, 0.000265f, 0.000360f, 0.000316f, 0.000428f, 0.000455f,
+ 0.000456f, 0.000583f, 0.000682f, 0.000750f, 0.000773f, 0.000824f, 0.000937f, 0.001220f, 0.001262f, 0.001384f, 0.001622f, 0.001862f,
+ 0.002157f, 0.002817f, 0.003414f, 0.004082f, 0.004993f, 0.006561f, 0.008560f, 0.011696f, 0.016022f, 0.023529f, 0.036469f, 0.062286f,
+ 0.117126f, 0.245605f, 0.487549f, 0.732910f, 0.870605f, 0.933105f, 0.983887f, 0.984863f, 0.984863f, 0.984863f, 0.984375f, 0.984863f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000096f, 0.000075f, 0.000061f, 0.000083f, 0.000096f, 0.000034f, 0.000101f, 0.000121f, 0.000137f,
+ 0.000211f, 0.000324f, 0.000381f, 0.000373f, 0.000420f, 0.000472f, 0.000494f, 0.000690f, 0.000793f, 0.000768f, 0.000853f, 0.000867f,
+ 0.000978f, 0.001003f, 0.001145f, 0.001416f, 0.001888f, 0.002125f, 0.002491f, 0.003004f, 0.003864f, 0.005028f, 0.006500f, 0.008682f,
+ 0.011856f, 0.016922f, 0.025757f, 0.042603f, 0.078247f, 0.161743f, 0.358398f, 0.641602f, 0.833496f, 0.920410f, 0.981934f, 0.982910f,
+ 0.982910f, 0.982910f, 0.982910f, 0.982910f, 0.000122f, 0.000000f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000097f, 0.000078f, 0.000062f, 0.000051f,
+ 0.000043f, 0.000072f, 0.000030f, 0.000060f, 0.000109f, 0.000206f, 0.000216f, 0.000333f, 0.000347f, 0.000395f, 0.000415f, 0.000458f,
+ 0.000568f, 0.000664f, 0.000709f, 0.000598f, 0.000781f, 0.000628f, 0.001053f, 0.001046f, 0.001179f, 0.001579f, 0.001649f, 0.002386f,
+ 0.002857f, 0.003727f, 0.004894f, 0.006363f, 0.008789f, 0.012314f, 0.018616f, 0.029709f, 0.052429f, 0.105652f, 0.244385f, 0.524414f,
+ 0.782715f, 0.904785f, 0.979492f, 0.980957f, 0.979980f, 0.979980f, 0.980469f, 0.980469f, 0.000000f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f,
+ 0.000120f, 0.000097f, 0.000079f, 0.000065f, 0.000054f, 0.000045f, 0.000073f, 0.000032f, 0.000089f, 0.000038f, 0.000134f, 0.000138f,
+ 0.000211f, 0.000333f, 0.000370f, 0.000400f, 0.000420f, 0.000496f, 0.000566f, 0.000494f, 0.000584f, 0.000714f, 0.000708f, 0.000843f,
+ 0.001056f, 0.001019f, 0.001327f, 0.001812f, 0.001908f, 0.002798f, 0.003479f, 0.004578f, 0.006195f, 0.008881f, 0.012901f, 0.020599f,
+ 0.035339f, 0.069214f, 0.159058f, 0.394531f, 0.709961f, 0.882812f, 0.977051f, 0.978027f, 0.977539f, 0.976562f, 0.977051f, 0.977539f,
+ 0.000000f, 0.000121f, 0.000120f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f,
+ 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000119f, 0.000120f, 0.000102f, 0.000084f, 0.000071f, 0.000059f, 0.000048f, 0.000041f,
+ 0.000035f, 0.000062f, 0.000026f, 0.000098f, 0.000103f, 0.000136f, 0.000230f, 0.000327f, 0.000356f, 0.000338f, 0.000387f, 0.000499f,
+ 0.000577f, 0.000627f, 0.000669f, 0.000611f, 0.000699f, 0.000904f, 0.000893f, 0.001340f, 0.001666f, 0.002068f, 0.002377f, 0.003105f,
+ 0.004345f, 0.006218f, 0.009178f, 0.013962f, 0.024170f, 0.045441f, 0.101868f, 0.271973f, 0.612305f, 0.853027f, 0.973145f, 0.974121f,
+ 0.973633f, 0.974121f, 0.973633f, 0.974121f, 0.000121f, 0.000120f, 0.000119f, 0.000120f, 0.000119f, 0.000119f, 0.000119f, 0.000119f,
+ 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000108f,
+ 0.000091f, 0.000075f, 0.000063f, 0.000053f, 0.000045f, 0.000039f, 0.000034f, 0.000040f, 0.000090f, 0.000068f, 0.000104f, 0.000127f,
+ 0.000220f, 0.000302f, 0.000412f, 0.000316f, 0.000444f, 0.000495f, 0.000428f, 0.000510f, 0.000463f, 0.000614f, 0.000726f, 0.000719f,
+ 0.001164f, 0.001533f, 0.001707f, 0.002079f, 0.002848f, 0.004189f, 0.006142f, 0.009491f, 0.016113f, 0.029343f, 0.064758f, 0.175415f,
+ 0.490723f, 0.812012f, 0.968750f, 0.969727f, 0.969238f, 0.969727f, 0.969727f, 0.969727f, 0.000000f, 0.000117f, 0.000117f, 0.000115f,
+ 0.000118f, 0.000118f, 0.000117f, 0.000117f, 0.000117f, 0.000117f, 0.000118f, 0.000117f, 0.000117f, 0.000118f, 0.000117f, 0.000117f,
+ 0.000117f, 0.000117f, 0.000117f, 0.000118f, 0.000117f, 0.000100f, 0.000082f, 0.000070f, 0.000060f, 0.000051f, 0.000043f, 0.000038f,
+ 0.000033f, 0.000053f, 0.000027f, 0.000089f, 0.000105f, 0.000137f, 0.000227f, 0.000277f, 0.000293f, 0.000284f, 0.000300f, 0.000420f,
+ 0.000367f, 0.000473f, 0.000467f, 0.000555f, 0.000625f, 0.000870f, 0.001177f, 0.001563f, 0.001982f, 0.002714f, 0.004051f, 0.006134f,
+ 0.010384f, 0.018967f, 0.040314f, 0.108887f, 0.358643f, 0.755859f, 0.962891f, 0.963867f, 0.964355f, 0.963867f, 0.963379f, 0.963379f,
+ 0.000000f, 0.000000f, 0.000098f, 0.000103f, 0.000111f, 0.000112f, 0.000112f, 0.000114f, 0.000113f, 0.000115f, 0.000114f, 0.000115f,
+ 0.000115f, 0.000115f, 0.000115f, 0.000115f, 0.000116f, 0.000116f, 0.000116f, 0.000116f, 0.000116f, 0.000116f, 0.000109f, 0.000094f,
+ 0.000078f, 0.000067f, 0.000058f, 0.000050f, 0.000043f, 0.000038f, 0.000033f, 0.000054f, 0.000025f, 0.000078f, 0.000091f, 0.000173f,
+ 0.000203f, 0.000252f, 0.000331f, 0.000277f, 0.000264f, 0.000407f, 0.000342f, 0.000444f, 0.000470f, 0.000542f, 0.000773f, 0.001081f,
+ 0.001245f, 0.001682f, 0.002602f, 0.003744f, 0.006248f, 0.011566f, 0.025040f, 0.065491f, 0.236938f, 0.678223f, 0.956055f, 0.956543f,
+ 0.956543f, 0.956543f, 0.957031f, 0.957031f, 0.000000f, 0.000000f, 0.000021f, 0.000080f, 0.000072f, 0.000089f, 0.000100f, 0.000099f,
+ 0.000105f, 0.000107f, 0.000107f, 0.000110f, 0.000109f, 0.000110f, 0.000111f, 0.000111f, 0.000112f, 0.000112f, 0.000112f, 0.000113f,
+ 0.000113f, 0.000113f, 0.000113f, 0.000113f, 0.000105f, 0.000090f, 0.000078f, 0.000067f, 0.000057f, 0.000050f, 0.000043f, 0.000038f,
+ 0.000033f, 0.000029f, 0.000025f, 0.000055f, 0.000091f, 0.000130f, 0.000225f, 0.000275f, 0.000254f, 0.000290f, 0.000259f, 0.000378f,
+ 0.000333f, 0.000362f, 0.000458f, 0.000587f, 0.000876f, 0.001062f, 0.001382f, 0.002398f, 0.003763f, 0.006603f, 0.014496f, 0.038300f,
+ 0.143677f, 0.573730f, 0.946777f, 0.947266f, 0.947266f, 0.947266f, 0.948242f, 0.947266f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000014f, 0.000036f, 0.000072f, 0.000082f, 0.000080f, 0.000094f, 0.000096f, 0.000099f, 0.000098f, 0.000103f, 0.000103f,
+ 0.000103f, 0.000106f, 0.000105f, 0.000107f, 0.000107f, 0.000108f, 0.000108f, 0.000109f, 0.000109f, 0.000109f, 0.000105f, 0.000090f,
+ 0.000078f, 0.000067f, 0.000059f, 0.000051f, 0.000045f, 0.000039f, 0.000034f, 0.000030f, 0.000026f, 0.000045f, 0.000086f, 0.000108f,
+ 0.000143f, 0.000212f, 0.000227f, 0.000204f, 0.000231f, 0.000263f, 0.000315f, 0.000354f, 0.000481f, 0.000702f, 0.000888f, 0.001257f,
+ 0.002018f, 0.003738f, 0.007675f, 0.021317f, 0.080933f, 0.444336f, 0.934082f, 0.935059f, 0.935059f, 0.935059f, 0.935059f, 0.935059f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000024f, 0.000038f, 0.000059f,
+ 0.000063f, 0.000076f, 0.000080f, 0.000085f, 0.000089f, 0.000091f, 0.000092f, 0.000095f, 0.000097f, 0.000099f, 0.000098f, 0.000101f,
+ 0.000101f, 0.000102f, 0.000103f, 0.000104f, 0.000104f, 0.000091f, 0.000080f, 0.000069f, 0.000062f, 0.000053f, 0.000046f, 0.000041f,
+ 0.000035f, 0.000032f, 0.000027f, 0.000039f, 0.000052f, 0.000103f, 0.000139f, 0.000178f, 0.000190f, 0.000178f, 0.000185f, 0.000247f,
+ 0.000274f, 0.000368f, 0.000528f, 0.000637f, 0.001027f, 0.001937f, 0.003853f, 0.010445f, 0.041718f, 0.304199f, 0.917480f, 0.917480f,
+ 0.917969f, 0.917480f, 0.918457f, 0.917969f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000023f, 0.000037f, 0.000048f, 0.000048f, 0.000063f, 0.000063f,
+ 0.000074f, 0.000077f, 0.000080f, 0.000083f, 0.000086f, 0.000088f, 0.000090f, 0.000091f, 0.000092f, 0.000094f, 0.000095f, 0.000096f,
+ 0.000084f, 0.000073f, 0.000064f, 0.000057f, 0.000049f, 0.000043f, 0.000037f, 0.000033f, 0.000029f, 0.000025f, 0.000060f, 0.000061f,
+ 0.000087f, 0.000118f, 0.000156f, 0.000131f, 0.000175f, 0.000226f, 0.000230f, 0.000373f, 0.000507f, 0.000992f, 0.001814f, 0.004639f,
+ 0.018799f, 0.176758f, 0.894043f, 0.894531f, 0.895508f, 0.895020f, 0.895020f, 0.895996f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000019f, 0.000028f, 0.000034f, 0.000043f, 0.000052f, 0.000057f, 0.000062f, 0.000067f,
+ 0.000070f, 0.000074f, 0.000075f, 0.000079f, 0.000081f, 0.000083f, 0.000085f, 0.000076f, 0.000068f, 0.000059f, 0.000051f, 0.000046f,
+ 0.000040f, 0.000035f, 0.000030f, 0.000026f, 0.000028f, 0.000038f, 0.000072f, 0.000100f, 0.000120f, 0.000107f, 0.000152f, 0.000156f,
+ 0.000254f, 0.000436f, 0.000722f, 0.001875f, 0.007088f, 0.083069f, 0.863281f, 0.862305f, 0.863281f, 0.862305f, 0.863281f, 0.862793f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000005f, 0.000015f, 0.000022f, 0.000030f, 0.000037f, 0.000042f, 0.000048f, 0.000053f, 0.000058f, 0.000060f,
+ 0.000064f, 0.000067f, 0.000069f, 0.000061f, 0.000053f, 0.000047f, 0.000041f, 0.000036f, 0.000031f, 0.000027f, 0.000023f, 0.000020f,
+ 0.000036f, 0.000063f, 0.000082f, 0.000081f, 0.000104f, 0.000149f, 0.000263f, 0.000616f, 0.002337f, 0.028168f, 0.816406f, 0.816895f,
+ 0.816895f, 0.816895f, 0.817383f, 0.816895f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000003f, 0.000011f, 0.000019f, 0.000026f, 0.000031f, 0.000036f, 0.000041f, 0.000045f, 0.000050f, 0.000047f,
+ 0.000041f, 0.000036f, 0.000031f, 0.000027f, 0.000023f, 0.000019f, 0.000028f, 0.000029f, 0.000053f, 0.000052f, 0.000072f, 0.000165f,
+ 0.000511f, 0.006050f, 0.751465f, 0.752441f, 0.752930f, 0.752441f, 0.752441f, 0.752930f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000011f, 0.000017f, 0.000021f, 0.000027f, 0.000028f, 0.000024f, 0.000020f, 0.000017f,
+ 0.000013f, 0.000020f, 0.000021f, 0.000029f, 0.000057f, 0.000588f, 0.665039f, 0.664551f, 0.665527f, 0.665039f, 0.665039f, 0.665039f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000009f, 0.000006f, 0.000004f, 0.000007f, 0.557129f, 0.558105f,
+ 0.557617f, 0.557617f, 0.558594f, 0.558105f,
+ },
+ {
+ 0.163818f, 0.558105f, 0.755859f, 0.841797f, 0.886230f, 0.912109f, 0.929199f, 0.941406f, 0.950195f, 0.957031f, 0.961914f, 0.966309f,
+ 0.970215f, 0.972656f, 0.975586f, 0.978027f, 0.979492f, 0.981445f, 0.982910f, 0.984375f, 0.985840f, 0.986328f, 0.987305f, 0.988770f,
+ 0.989258f, 0.989746f, 0.990234f, 0.991211f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.993652f, 0.993652f, 0.994141f, 0.995117f,
+ 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f,
+ 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.027023f, 0.138184f, 0.353760f, 0.583984f, 0.735352f, 0.819336f, 0.868652f, 0.898926f,
+ 0.918945f, 0.933594f, 0.943848f, 0.952148f, 0.958984f, 0.963867f, 0.967773f, 0.971680f, 0.974121f, 0.976562f, 0.978516f, 0.980469f,
+ 0.982422f, 0.983398f, 0.984863f, 0.986328f, 0.986816f, 0.988281f, 0.989258f, 0.989746f, 0.990723f, 0.990723f, 0.991699f, 0.992676f,
+ 0.993164f, 0.993164f, 0.993652f, 0.994141f, 0.994141f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f,
+ 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.009819f, 0.044250f, 0.113525f, 0.244995f,
+ 0.430420f, 0.608887f, 0.733887f, 0.810547f, 0.860352f, 0.892578f, 0.913086f, 0.929688f, 0.940918f, 0.949219f, 0.956055f, 0.961426f,
+ 0.966309f, 0.970215f, 0.972656f, 0.975586f, 0.977539f, 0.979980f, 0.980957f, 0.983398f, 0.983887f, 0.985352f, 0.986328f, 0.987793f,
+ 0.988281f, 0.989746f, 0.989746f, 0.991211f, 0.991699f, 0.992188f, 0.992676f, 0.993164f, 0.993652f, 0.993652f, 0.994141f, 0.995117f,
+ 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.004848f, 0.020447f, 0.046814f, 0.096313f, 0.183228f, 0.319092f, 0.484375f, 0.631836f, 0.739258f, 0.810547f, 0.857422f, 0.888672f,
+ 0.910645f, 0.925781f, 0.938965f, 0.947754f, 0.954590f, 0.960449f, 0.964355f, 0.968750f, 0.971191f, 0.974609f, 0.977051f, 0.979004f,
+ 0.980957f, 0.982422f, 0.983887f, 0.985840f, 0.986816f, 0.987793f, 0.988770f, 0.989258f, 0.990234f, 0.990723f, 0.991211f, 0.991699f,
+ 0.992676f, 0.992676f, 0.993652f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996582f,
+ 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.003096f, 0.011017f, 0.024399f, 0.046600f, 0.083191f, 0.145386f, 0.243774f, 0.379395f,
+ 0.529297f, 0.656738f, 0.750977f, 0.813965f, 0.857910f, 0.887695f, 0.909668f, 0.925293f, 0.937500f, 0.946289f, 0.953613f, 0.959473f,
+ 0.964355f, 0.968262f, 0.971191f, 0.974121f, 0.976562f, 0.979004f, 0.980957f, 0.982910f, 0.984375f, 0.985840f, 0.986328f, 0.987793f,
+ 0.988281f, 0.989258f, 0.989746f, 0.991211f, 0.991699f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f,
+ 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f,
+ 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.001808f, 0.006992f, 0.014923f, 0.026413f,
+ 0.044403f, 0.073120f, 0.119446f, 0.193115f, 0.300537f, 0.433594f, 0.568848f, 0.680664f, 0.763184f, 0.821289f, 0.860840f, 0.890137f,
+ 0.909668f, 0.925293f, 0.937500f, 0.945801f, 0.953613f, 0.959473f, 0.963867f, 0.968262f, 0.971680f, 0.974609f, 0.977051f, 0.979004f,
+ 0.980957f, 0.982422f, 0.983887f, 0.984863f, 0.986816f, 0.987305f, 0.987793f, 0.989746f, 0.989746f, 0.991211f, 0.991699f, 0.992188f,
+ 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.994629f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f,
+ 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.001668f, 0.005253f, 0.010010f, 0.016602f, 0.026459f, 0.042023f, 0.065369f, 0.101868f, 0.158081f, 0.241455f, 0.354248f, 0.483887f,
+ 0.606934f, 0.706055f, 0.777832f, 0.830566f, 0.867188f, 0.893066f, 0.912109f, 0.926270f, 0.938477f, 0.946289f, 0.953125f, 0.959473f,
+ 0.964355f, 0.968750f, 0.971680f, 0.975098f, 0.977051f, 0.979492f, 0.980957f, 0.982910f, 0.984375f, 0.985840f, 0.986328f, 0.987305f,
+ 0.988770f, 0.989746f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.993164f, 0.994141f, 0.994629f, 0.994629f, 0.995117f, 0.995605f,
+ 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999023f, 0.001086f, 0.003477f, 0.006756f, 0.011604f, 0.018066f, 0.027222f, 0.039978f, 0.059448f,
+ 0.088257f, 0.132690f, 0.198120f, 0.291504f, 0.408447f, 0.531250f, 0.641602f, 0.728516f, 0.793457f, 0.839844f, 0.873047f, 0.896973f,
+ 0.915527f, 0.929199f, 0.939941f, 0.948730f, 0.955566f, 0.960938f, 0.965332f, 0.969238f, 0.972168f, 0.975098f, 0.977539f, 0.979492f,
+ 0.981445f, 0.983398f, 0.984375f, 0.985840f, 0.986816f, 0.988281f, 0.989258f, 0.989746f, 0.990723f, 0.991699f, 0.992188f, 0.993164f,
+ 0.993652f, 0.994141f, 0.994629f, 0.994629f, 0.995605f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.997559f,
+ 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000982f, 0.002764f, 0.004925f, 0.008194f,
+ 0.012703f, 0.018417f, 0.026154f, 0.037964f, 0.053894f, 0.078552f, 0.113770f, 0.166626f, 0.242310f, 0.343262f, 0.460449f, 0.576660f,
+ 0.675293f, 0.753418f, 0.809570f, 0.851074f, 0.879883f, 0.902344f, 0.919434f, 0.931152f, 0.941895f, 0.950195f, 0.956055f, 0.960938f,
+ 0.965820f, 0.969727f, 0.973145f, 0.976074f, 0.978027f, 0.980469f, 0.981934f, 0.983887f, 0.985352f, 0.986328f, 0.987793f, 0.988770f,
+ 0.989746f, 0.990234f, 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000723f, 0.002268f, 0.003639f, 0.006371f, 0.009392f, 0.013046f, 0.018570f, 0.026016f, 0.035919f, 0.049957f, 0.070618f, 0.099609f,
+ 0.142212f, 0.204590f, 0.290039f, 0.396973f, 0.512207f, 0.619141f, 0.707520f, 0.775391f, 0.825195f, 0.860352f, 0.887207f, 0.907715f,
+ 0.923340f, 0.935547f, 0.944824f, 0.951660f, 0.958496f, 0.963379f, 0.967773f, 0.971191f, 0.974121f, 0.977051f, 0.979492f, 0.980957f,
+ 0.982910f, 0.984375f, 0.985352f, 0.987305f, 0.988281f, 0.989258f, 0.989746f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993164f,
+ 0.994141f, 0.994629f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000364f, 0.001690f, 0.003056f, 0.004982f, 0.007217f, 0.010124f, 0.013931f, 0.018738f,
+ 0.025177f, 0.034332f, 0.045990f, 0.063599f, 0.088501f, 0.124146f, 0.175781f, 0.248047f, 0.341797f, 0.451416f, 0.562012f, 0.659668f,
+ 0.738281f, 0.797852f, 0.841797f, 0.872559f, 0.896484f, 0.914062f, 0.928711f, 0.938477f, 0.947266f, 0.954590f, 0.959473f, 0.964844f,
+ 0.969238f, 0.972168f, 0.975098f, 0.977539f, 0.979980f, 0.981934f, 0.983398f, 0.985352f, 0.986816f, 0.987793f, 0.988770f, 0.989746f,
+ 0.990723f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996582f,
+ 0.997070f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000365f, 0.001221f, 0.002531f, 0.003979f,
+ 0.005829f, 0.007874f, 0.010475f, 0.013962f, 0.018402f, 0.024368f, 0.032257f, 0.042847f, 0.057983f, 0.079346f, 0.109375f, 0.153198f,
+ 0.214233f, 0.295898f, 0.397705f, 0.506836f, 0.609863f, 0.698730f, 0.767578f, 0.817871f, 0.854980f, 0.883301f, 0.903809f, 0.920410f,
+ 0.933105f, 0.942871f, 0.950195f, 0.957031f, 0.962402f, 0.966797f, 0.970703f, 0.973633f, 0.976562f, 0.979004f, 0.981445f, 0.982910f,
+ 0.984375f, 0.985840f, 0.986816f, 0.988281f, 0.989746f, 0.989746f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, 0.993652f, 0.994141f,
+ 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.000343f, 0.001357f, 0.002039f, 0.003130f, 0.004398f, 0.006432f, 0.008141f, 0.010925f, 0.014008f, 0.018326f, 0.023331f, 0.030655f,
+ 0.040558f, 0.053680f, 0.071960f, 0.098206f, 0.134644f, 0.187012f, 0.258057f, 0.349854f, 0.455566f, 0.562012f, 0.656738f, 0.734863f,
+ 0.792969f, 0.836914f, 0.868652f, 0.894043f, 0.912598f, 0.926758f, 0.937988f, 0.947266f, 0.954590f, 0.960449f, 0.964355f, 0.968750f,
+ 0.972656f, 0.975586f, 0.978027f, 0.980469f, 0.981934f, 0.983398f, 0.985840f, 0.986816f, 0.988281f, 0.989258f, 0.990723f, 0.990723f,
+ 0.991699f, 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000244f, 0.001185f, 0.001561f, 0.002504f, 0.003990f, 0.005272f, 0.006573f, 0.008606f,
+ 0.010933f, 0.013878f, 0.017715f, 0.022415f, 0.029068f, 0.038086f, 0.049774f, 0.066162f, 0.088257f, 0.120361f, 0.164917f, 0.227173f,
+ 0.308838f, 0.407959f, 0.515137f, 0.615723f, 0.700684f, 0.767090f, 0.817383f, 0.854492f, 0.882812f, 0.904297f, 0.920898f, 0.932617f,
+ 0.943359f, 0.951172f, 0.957520f, 0.962891f, 0.967773f, 0.971191f, 0.974121f, 0.977539f, 0.979492f, 0.981445f, 0.983887f, 0.985352f,
+ 0.986816f, 0.988281f, 0.988770f, 0.989258f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995605f,
+ 0.995605f, 0.996582f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000243f, 0.000847f, 0.001555f, 0.002224f,
+ 0.003141f, 0.004093f, 0.005264f, 0.006817f, 0.008850f, 0.010948f, 0.014053f, 0.017456f, 0.022339f, 0.028351f, 0.036011f, 0.046326f,
+ 0.060791f, 0.080444f, 0.107788f, 0.146851f, 0.201660f, 0.274658f, 0.366699f, 0.470215f, 0.574707f, 0.666016f, 0.740234f, 0.797363f,
+ 0.839355f, 0.871094f, 0.895508f, 0.913574f, 0.927734f, 0.938965f, 0.947754f, 0.955566f, 0.960449f, 0.965332f, 0.969727f, 0.973145f,
+ 0.976074f, 0.979004f, 0.981445f, 0.982910f, 0.984863f, 0.986328f, 0.987305f, 0.988770f, 0.989258f, 0.990723f, 0.991699f, 0.992188f,
+ 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.996094f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.000244f, 0.000767f, 0.001042f, 0.001934f, 0.002502f, 0.003588f, 0.004292f, 0.005558f, 0.006824f, 0.008667f, 0.010872f, 0.013802f,
+ 0.017426f, 0.021637f, 0.027176f, 0.033936f, 0.043304f, 0.056549f, 0.073914f, 0.098083f, 0.132446f, 0.180664f, 0.245239f, 0.330078f,
+ 0.429199f, 0.533203f, 0.631348f, 0.711914f, 0.775879f, 0.823242f, 0.860352f, 0.886230f, 0.907227f, 0.923340f, 0.935059f, 0.944824f,
+ 0.952148f, 0.958984f, 0.964844f, 0.968750f, 0.972168f, 0.975586f, 0.978516f, 0.980957f, 0.982422f, 0.983887f, 0.985840f, 0.987305f,
+ 0.988770f, 0.989746f, 0.990234f, 0.992188f, 0.992676f, 0.992676f, 0.994141f, 0.994141f, 0.995117f, 0.995605f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000485f, 0.001062f, 0.001658f, 0.002398f, 0.002998f, 0.003805f, 0.004723f,
+ 0.006004f, 0.007084f, 0.009102f, 0.011093f, 0.013489f, 0.016876f, 0.020813f, 0.025803f, 0.032257f, 0.040924f, 0.052673f, 0.068298f,
+ 0.090149f, 0.120239f, 0.162598f, 0.221313f, 0.298096f, 0.392822f, 0.496582f, 0.597656f, 0.684082f, 0.754883f, 0.807617f, 0.848145f,
+ 0.877930f, 0.900391f, 0.917969f, 0.931641f, 0.941406f, 0.950684f, 0.957031f, 0.962402f, 0.967773f, 0.971680f, 0.974609f, 0.978027f,
+ 0.980469f, 0.982422f, 0.984375f, 0.985840f, 0.987305f, 0.988281f, 0.989746f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993652f,
+ 0.994141f, 0.995117f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000244f, 0.000477f, 0.000852f, 0.001439f,
+ 0.002045f, 0.002424f, 0.003101f, 0.004093f, 0.004887f, 0.005989f, 0.007751f, 0.008606f, 0.011002f, 0.013420f, 0.016251f, 0.020035f,
+ 0.024628f, 0.030579f, 0.039093f, 0.049255f, 0.063599f, 0.083191f, 0.109924f, 0.148071f, 0.200928f, 0.270996f, 0.359863f, 0.461670f,
+ 0.564453f, 0.656738f, 0.732910f, 0.791992f, 0.836426f, 0.869629f, 0.894531f, 0.913086f, 0.928223f, 0.939453f, 0.949219f, 0.956055f,
+ 0.961914f, 0.966797f, 0.970703f, 0.975098f, 0.977051f, 0.979492f, 0.982422f, 0.983887f, 0.985352f, 0.987305f, 0.988770f, 0.989746f,
+ 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.998047f, 0.998535f, 0.998535f, 0.998047f, 0.998047f, 0.998535f,
+ 0.000242f, 0.000650f, 0.000847f, 0.001138f, 0.001621f, 0.002239f, 0.002527f, 0.003325f, 0.004227f, 0.005165f, 0.006462f, 0.007389f,
+ 0.008904f, 0.011024f, 0.013130f, 0.015915f, 0.019272f, 0.023819f, 0.029205f, 0.036652f, 0.046417f, 0.059418f, 0.077209f, 0.101562f,
+ 0.136230f, 0.183350f, 0.248047f, 0.331055f, 0.429688f, 0.533203f, 0.630859f, 0.711426f, 0.776367f, 0.824219f, 0.861328f, 0.887695f,
+ 0.908691f, 0.924805f, 0.937500f, 0.946777f, 0.954102f, 0.960938f, 0.966309f, 0.970215f, 0.974121f, 0.977539f, 0.979492f, 0.981934f,
+ 0.983887f, 0.985840f, 0.987305f, 0.989258f, 0.989746f, 0.990723f, 0.991211f, 0.992676f, 0.993164f, 0.994141f, 0.997559f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000089f, 0.000243f, 0.000827f, 0.000964f, 0.001418f, 0.001579f, 0.002296f, 0.002914f,
+ 0.003632f, 0.004280f, 0.005344f, 0.006130f, 0.007545f, 0.008949f, 0.010498f, 0.012733f, 0.015686f, 0.018646f, 0.023010f, 0.028229f,
+ 0.034851f, 0.044098f, 0.056122f, 0.072388f, 0.094788f, 0.125610f, 0.168945f, 0.228271f, 0.306396f, 0.401123f, 0.504883f, 0.604492f,
+ 0.691895f, 0.760742f, 0.813477f, 0.853027f, 0.881836f, 0.904297f, 0.921387f, 0.934570f, 0.944824f, 0.953125f, 0.959961f, 0.964844f,
+ 0.969727f, 0.973633f, 0.976562f, 0.979492f, 0.981934f, 0.983887f, 0.986328f, 0.987305f, 0.988281f, 0.989258f, 0.991211f, 0.992188f,
+ 0.992676f, 0.993652f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000069f, 0.000461f, 0.000609f, 0.000933f,
+ 0.001088f, 0.001488f, 0.001900f, 0.002378f, 0.003101f, 0.003687f, 0.004547f, 0.005276f, 0.006233f, 0.007282f, 0.008820f, 0.010239f,
+ 0.012581f, 0.015312f, 0.018341f, 0.022095f, 0.027344f, 0.034027f, 0.041687f, 0.053467f, 0.067810f, 0.088440f, 0.117126f, 0.156616f,
+ 0.211426f, 0.284180f, 0.375977f, 0.478760f, 0.581543f, 0.672363f, 0.746094f, 0.802734f, 0.845703f, 0.877441f, 0.900879f, 0.918457f,
+ 0.933105f, 0.943848f, 0.951660f, 0.959473f, 0.964355f, 0.968750f, 0.974121f, 0.977051f, 0.979492f, 0.982422f, 0.984375f, 0.985840f,
+ 0.987305f, 0.988770f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f,
+ 0.000244f, 0.000348f, 0.000606f, 0.000737f, 0.001079f, 0.001458f, 0.001783f, 0.002192f, 0.002924f, 0.003231f, 0.003862f, 0.004551f,
+ 0.005169f, 0.006367f, 0.007381f, 0.008682f, 0.010590f, 0.012199f, 0.014900f, 0.017761f, 0.021530f, 0.026108f, 0.032349f, 0.039642f,
+ 0.050446f, 0.064392f, 0.083313f, 0.109436f, 0.145996f, 0.197021f, 0.266357f, 0.354248f, 0.455811f, 0.560059f, 0.654785f, 0.732910f,
+ 0.793457f, 0.837891f, 0.873047f, 0.897461f, 0.917480f, 0.931641f, 0.941895f, 0.951172f, 0.958984f, 0.964844f, 0.969727f, 0.973633f,
+ 0.977051f, 0.979980f, 0.981934f, 0.984375f, 0.985840f, 0.988281f, 0.989258f, 0.990234f, 0.991211f, 0.992676f, 0.997070f, 0.997559f,
+ 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000244f, 0.000520f, 0.000592f, 0.000720f, 0.000812f, 0.001174f, 0.001500f, 0.001884f,
+ 0.002178f, 0.002831f, 0.003321f, 0.003885f, 0.004471f, 0.005436f, 0.006275f, 0.007584f, 0.008675f, 0.010521f, 0.012238f, 0.014557f,
+ 0.017197f, 0.020874f, 0.025467f, 0.030960f, 0.038208f, 0.047821f, 0.061249f, 0.078552f, 0.103149f, 0.136841f, 0.184937f, 0.249878f,
+ 0.334473f, 0.435059f, 0.539551f, 0.638184f, 0.720215f, 0.784668f, 0.832031f, 0.868164f, 0.894531f, 0.914062f, 0.929688f, 0.942383f,
+ 0.950684f, 0.958984f, 0.964844f, 0.970215f, 0.974121f, 0.977539f, 0.979980f, 0.982422f, 0.984863f, 0.985840f, 0.988281f, 0.989258f,
+ 0.990723f, 0.992188f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.000000f, 0.000243f, 0.000351f, 0.000603f,
+ 0.000708f, 0.001079f, 0.001493f, 0.001752f, 0.001936f, 0.002171f, 0.002911f, 0.003382f, 0.003906f, 0.004578f, 0.005222f, 0.006161f,
+ 0.007362f, 0.008850f, 0.010010f, 0.011971f, 0.014145f, 0.016983f, 0.020477f, 0.024582f, 0.029739f, 0.036804f, 0.045837f, 0.057648f,
+ 0.074829f, 0.097534f, 0.130127f, 0.174438f, 0.236572f, 0.318604f, 0.416992f, 0.523926f, 0.624023f, 0.709961f, 0.777344f, 0.827148f,
+ 0.865234f, 0.893066f, 0.914062f, 0.929688f, 0.941406f, 0.951660f, 0.958496f, 0.965820f, 0.969238f, 0.974609f, 0.977539f, 0.980469f,
+ 0.983398f, 0.985352f, 0.986816f, 0.988281f, 0.989746f, 0.990723f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f,
+ 0.000243f, 0.000244f, 0.000456f, 0.000592f, 0.000602f, 0.001025f, 0.001282f, 0.001656f, 0.001856f, 0.002073f, 0.002535f, 0.002768f,
+ 0.003487f, 0.003822f, 0.004574f, 0.005589f, 0.006519f, 0.007336f, 0.008453f, 0.009911f, 0.011581f, 0.013985f, 0.016373f, 0.019638f,
+ 0.023819f, 0.028473f, 0.035339f, 0.043945f, 0.055939f, 0.071350f, 0.093140f, 0.123474f, 0.165771f, 0.225342f, 0.304199f, 0.402344f,
+ 0.509277f, 0.612305f, 0.702148f, 0.771973f, 0.824219f, 0.863281f, 0.891113f, 0.913086f, 0.930176f, 0.942383f, 0.951660f, 0.959473f,
+ 0.965820f, 0.970215f, 0.974609f, 0.977539f, 0.980957f, 0.983887f, 0.985352f, 0.987305f, 0.988770f, 0.990723f, 0.996582f, 0.996582f,
+ 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000000f, 0.000243f, 0.000276f, 0.000557f, 0.000594f, 0.000849f, 0.000845f, 0.001282f,
+ 0.001520f, 0.001774f, 0.002119f, 0.002499f, 0.002840f, 0.003252f, 0.004005f, 0.004555f, 0.005245f, 0.006168f, 0.007233f, 0.008301f,
+ 0.009911f, 0.011330f, 0.013748f, 0.015945f, 0.019089f, 0.023071f, 0.027786f, 0.034058f, 0.042542f, 0.053619f, 0.068237f, 0.089539f,
+ 0.117798f, 0.158325f, 0.215698f, 0.293213f, 0.389893f, 0.498291f, 0.603027f, 0.694824f, 0.767090f, 0.821777f, 0.862305f, 0.891113f,
+ 0.914062f, 0.930176f, 0.942383f, 0.952148f, 0.959473f, 0.965820f, 0.971680f, 0.975098f, 0.978516f, 0.981445f, 0.983887f, 0.985840f,
+ 0.988281f, 0.989258f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996094f, 0.996582f, 0.000240f, 0.000240f, 0.000242f, 0.000365f,
+ 0.000678f, 0.000779f, 0.000957f, 0.001003f, 0.001390f, 0.001656f, 0.001828f, 0.002274f, 0.002455f, 0.003210f, 0.003704f, 0.004097f,
+ 0.004616f, 0.005409f, 0.006180f, 0.007092f, 0.008453f, 0.009521f, 0.011154f, 0.013397f, 0.015656f, 0.018509f, 0.022247f, 0.026810f,
+ 0.032928f, 0.041046f, 0.051727f, 0.065613f, 0.085205f, 0.113098f, 0.152832f, 0.208496f, 0.284424f, 0.380371f, 0.489258f, 0.596680f,
+ 0.690918f, 0.764648f, 0.821777f, 0.862305f, 0.892578f, 0.914551f, 0.931152f, 0.943848f, 0.953613f, 0.960938f, 0.967773f, 0.971680f,
+ 0.976074f, 0.979492f, 0.982422f, 0.984863f, 0.986816f, 0.988281f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996094f,
+ 0.000000f, 0.000242f, 0.000242f, 0.000364f, 0.000465f, 0.000803f, 0.000927f, 0.000956f, 0.001275f, 0.001335f, 0.001570f, 0.001968f,
+ 0.002184f, 0.002726f, 0.003069f, 0.003294f, 0.003906f, 0.004662f, 0.005245f, 0.006027f, 0.007191f, 0.008202f, 0.009460f, 0.010735f,
+ 0.012970f, 0.015404f, 0.018051f, 0.021484f, 0.026321f, 0.032135f, 0.039581f, 0.049805f, 0.063538f, 0.082458f, 0.109497f, 0.147827f,
+ 0.202393f, 0.277344f, 0.373535f, 0.483887f, 0.593262f, 0.688477f, 0.764648f, 0.821289f, 0.863281f, 0.894043f, 0.916016f, 0.932129f,
+ 0.944336f, 0.954590f, 0.962402f, 0.968262f, 0.973633f, 0.977051f, 0.980957f, 0.983398f, 0.985352f, 0.987793f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.000000f, 0.000239f, 0.000360f, 0.000362f, 0.000363f, 0.000475f, 0.000767f, 0.000931f,
+ 0.000951f, 0.001211f, 0.001491f, 0.001634f, 0.002129f, 0.002457f, 0.002678f, 0.002995f, 0.003393f, 0.003922f, 0.004711f, 0.005135f,
+ 0.005955f, 0.006935f, 0.008072f, 0.009270f, 0.010841f, 0.012558f, 0.014618f, 0.017502f, 0.020828f, 0.025269f, 0.030884f, 0.038269f,
+ 0.048218f, 0.061554f, 0.080505f, 0.106567f, 0.144287f, 0.197998f, 0.272705f, 0.369141f, 0.480469f, 0.591797f, 0.690430f, 0.767090f,
+ 0.824707f, 0.866699f, 0.896484f, 0.918457f, 0.934570f, 0.946777f, 0.956543f, 0.963379f, 0.969727f, 0.974609f, 0.978027f, 0.981934f,
+ 0.984375f, 0.986328f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.000000f, 0.000208f, 0.000238f, 0.000362f,
+ 0.000363f, 0.000555f, 0.000600f, 0.000888f, 0.001140f, 0.001140f, 0.001272f, 0.001661f, 0.001811f, 0.002041f, 0.002550f, 0.002636f,
+ 0.002941f, 0.003492f, 0.004032f, 0.004593f, 0.005062f, 0.005875f, 0.007015f, 0.007965f, 0.009079f, 0.010300f, 0.012291f, 0.014229f,
+ 0.016937f, 0.020248f, 0.024689f, 0.030151f, 0.037354f, 0.047028f, 0.060211f, 0.078491f, 0.104431f, 0.141602f, 0.195068f, 0.270264f,
+ 0.367676f, 0.480957f, 0.594238f, 0.693848f, 0.770996f, 0.828613f, 0.869629f, 0.898438f, 0.921875f, 0.937012f, 0.949219f, 0.958008f,
+ 0.964844f, 0.971680f, 0.976074f, 0.979980f, 0.982422f, 0.985840f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.995117f, 0.995117f,
+ 0.000000f, 0.000000f, 0.000229f, 0.000358f, 0.000479f, 0.000362f, 0.000498f, 0.000634f, 0.000836f, 0.000927f, 0.001288f, 0.001244f,
+ 0.001605f, 0.001732f, 0.002106f, 0.002478f, 0.002613f, 0.003183f, 0.003510f, 0.004021f, 0.004528f, 0.005047f, 0.005768f, 0.006859f,
+ 0.007759f, 0.008865f, 0.009933f, 0.011742f, 0.013741f, 0.016678f, 0.019897f, 0.024017f, 0.029297f, 0.036469f, 0.045990f, 0.058990f,
+ 0.077026f, 0.102722f, 0.140015f, 0.193604f, 0.269531f, 0.369141f, 0.485107f, 0.600098f, 0.700195f, 0.777344f, 0.833984f, 0.873535f,
+ 0.903809f, 0.924316f, 0.940430f, 0.951172f, 0.960938f, 0.968262f, 0.973145f, 0.978027f, 0.980957f, 0.983887f, 0.994629f, 0.995117f,
+ 0.995117f, 0.995605f, 0.995117f, 0.995117f, 0.000000f, 0.000000f, 0.000078f, 0.000353f, 0.000354f, 0.000360f, 0.000482f, 0.000573f,
+ 0.000757f, 0.000923f, 0.001230f, 0.001266f, 0.001485f, 0.001679f, 0.001963f, 0.002161f, 0.002235f, 0.002739f, 0.003115f, 0.003563f,
+ 0.003933f, 0.004436f, 0.004917f, 0.005623f, 0.006599f, 0.007469f, 0.008484f, 0.010101f, 0.011665f, 0.013695f, 0.016403f, 0.019531f,
+ 0.023300f, 0.028870f, 0.035889f, 0.045135f, 0.058014f, 0.075928f, 0.101746f, 0.139160f, 0.193848f, 0.271729f, 0.374023f, 0.492920f,
+ 0.609863f, 0.709473f, 0.786133f, 0.842285f, 0.880859f, 0.908691f, 0.928711f, 0.943848f, 0.954102f, 0.963867f, 0.969727f, 0.975098f,
+ 0.979004f, 0.982422f, 0.994141f, 0.994629f, 0.994141f, 0.994141f, 0.994141f, 0.994629f, 0.000000f, 0.000000f, 0.000000f, 0.000330f,
+ 0.000336f, 0.000352f, 0.000478f, 0.000481f, 0.000676f, 0.000822f, 0.001072f, 0.001228f, 0.001283f, 0.001417f, 0.001621f, 0.001938f,
+ 0.001953f, 0.002377f, 0.002737f, 0.002914f, 0.003624f, 0.003721f, 0.004555f, 0.004845f, 0.005531f, 0.006325f, 0.007244f, 0.008255f,
+ 0.009911f, 0.011467f, 0.013496f, 0.016068f, 0.018951f, 0.022888f, 0.028183f, 0.035126f, 0.044617f, 0.057220f, 0.075134f, 0.101501f,
+ 0.139526f, 0.195679f, 0.276123f, 0.381592f, 0.503418f, 0.622070f, 0.721680f, 0.796387f, 0.850098f, 0.887207f, 0.914551f, 0.933594f,
+ 0.947266f, 0.957520f, 0.966797f, 0.972656f, 0.977539f, 0.980957f, 0.993164f, 0.994141f, 0.994141f, 0.994141f, 0.994141f, 0.994141f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000243f, 0.000466f, 0.000474f, 0.000475f, 0.000600f, 0.000740f, 0.000796f, 0.001130f,
+ 0.001333f, 0.001339f, 0.001440f, 0.001575f, 0.001961f, 0.002031f, 0.002388f, 0.002563f, 0.003174f, 0.003345f, 0.003555f, 0.004143f,
+ 0.004681f, 0.005333f, 0.006191f, 0.007111f, 0.008278f, 0.009666f, 0.011177f, 0.013451f, 0.015511f, 0.018707f, 0.022629f, 0.027847f,
+ 0.034515f, 0.043976f, 0.056671f, 0.075012f, 0.101685f, 0.140869f, 0.199341f, 0.282959f, 0.393311f, 0.519043f, 0.639160f, 0.736328f,
+ 0.809082f, 0.860352f, 0.896484f, 0.920898f, 0.939453f, 0.951660f, 0.961914f, 0.969238f, 0.975098f, 0.979492f, 0.993164f, 0.993652f,
+ 0.994141f, 0.993652f, 0.993652f, 0.993652f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000120f, 0.000367f, 0.000448f, 0.000589f,
+ 0.000595f, 0.000719f, 0.000707f, 0.000809f, 0.000966f, 0.001217f, 0.001369f, 0.001405f, 0.001579f, 0.001786f, 0.002100f, 0.002260f,
+ 0.002600f, 0.002762f, 0.003023f, 0.003531f, 0.004219f, 0.004810f, 0.005409f, 0.006092f, 0.007053f, 0.008064f, 0.009163f, 0.010941f,
+ 0.012733f, 0.015251f, 0.018280f, 0.022202f, 0.027573f, 0.034271f, 0.043732f, 0.056458f, 0.075134f, 0.102661f, 0.143433f, 0.205078f,
+ 0.293701f, 0.409668f, 0.538574f, 0.658203f, 0.753418f, 0.823242f, 0.870605f, 0.905273f, 0.927734f, 0.943848f, 0.956055f, 0.964844f,
+ 0.972168f, 0.977539f, 0.992188f, 0.992676f, 0.993164f, 0.993652f, 0.993164f, 0.992676f, 0.000000f, 0.000000f, 0.000000f, 0.000111f,
+ 0.000224f, 0.000231f, 0.000314f, 0.000562f, 0.000589f, 0.000699f, 0.000717f, 0.000776f, 0.000926f, 0.000968f, 0.001242f, 0.001360f,
+ 0.001487f, 0.001564f, 0.001713f, 0.002073f, 0.002169f, 0.002380f, 0.002941f, 0.003229f, 0.003534f, 0.003914f, 0.004509f, 0.005127f,
+ 0.005939f, 0.006596f, 0.007812f, 0.009354f, 0.010559f, 0.012581f, 0.015007f, 0.018021f, 0.022079f, 0.027191f, 0.034119f, 0.043427f,
+ 0.057190f, 0.075623f, 0.104492f, 0.147949f, 0.213135f, 0.308105f, 0.430664f, 0.562500f, 0.681641f, 0.772949f, 0.839355f, 0.884277f,
+ 0.913574f, 0.934570f, 0.950195f, 0.961426f, 0.969238f, 0.975098f, 0.991211f, 0.992676f, 0.992676f, 0.992676f, 0.992676f, 0.992188f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000084f, 0.000117f, 0.000119f, 0.000367f, 0.000473f, 0.000555f, 0.000576f, 0.000674f, 0.000713f,
+ 0.000816f, 0.000913f, 0.001049f, 0.001168f, 0.001263f, 0.001473f, 0.001580f, 0.001781f, 0.002005f, 0.002123f, 0.002316f, 0.002674f,
+ 0.003094f, 0.003475f, 0.003967f, 0.004318f, 0.004833f, 0.005798f, 0.006699f, 0.007801f, 0.008888f, 0.010429f, 0.012268f, 0.014824f,
+ 0.017792f, 0.021790f, 0.026978f, 0.033844f, 0.043518f, 0.057068f, 0.077148f, 0.107605f, 0.154053f, 0.224609f, 0.326904f, 0.456543f,
+ 0.591797f, 0.708984f, 0.795410f, 0.855957f, 0.895508f, 0.923340f, 0.942383f, 0.955566f, 0.965332f, 0.973145f, 0.991211f, 0.991699f,
+ 0.992188f, 0.992188f, 0.992188f, 0.991699f, 0.000000f, 0.000000f, 0.000000f, 0.000092f, 0.000070f, 0.000236f, 0.000119f, 0.000376f,
+ 0.000433f, 0.000561f, 0.000688f, 0.000586f, 0.000742f, 0.000842f, 0.000881f, 0.000937f, 0.001141f, 0.001300f, 0.001434f, 0.001464f,
+ 0.001598f, 0.001829f, 0.002062f, 0.002338f, 0.002583f, 0.003036f, 0.003460f, 0.003704f, 0.004383f, 0.004986f, 0.005615f, 0.006439f,
+ 0.007267f, 0.008797f, 0.010330f, 0.012146f, 0.014473f, 0.017532f, 0.021622f, 0.026535f, 0.033539f, 0.043579f, 0.058044f, 0.079041f,
+ 0.111572f, 0.162109f, 0.239746f, 0.350830f, 0.488770f, 0.625000f, 0.737305f, 0.817871f, 0.871582f, 0.908203f, 0.932129f, 0.949219f,
+ 0.961914f, 0.970215f, 0.990234f, 0.991211f, 0.991211f, 0.991211f, 0.991211f, 0.991211f, 0.000000f, 0.000000f, 0.000000f, 0.000080f,
+ 0.000100f, 0.000115f, 0.000335f, 0.000350f, 0.000355f, 0.000473f, 0.000633f, 0.000678f, 0.000695f, 0.000694f, 0.000812f, 0.000733f,
+ 0.001109f, 0.001098f, 0.001260f, 0.001452f, 0.001377f, 0.001534f, 0.001972f, 0.001982f, 0.002232f, 0.002567f, 0.002764f, 0.003273f,
+ 0.003542f, 0.004181f, 0.004738f, 0.005466f, 0.006268f, 0.007126f, 0.008614f, 0.010170f, 0.012093f, 0.014359f, 0.017075f, 0.021042f,
+ 0.026459f, 0.033722f, 0.044159f, 0.059113f, 0.082092f, 0.117249f, 0.173218f, 0.259766f, 0.382080f, 0.526367f, 0.662598f, 0.768066f,
+ 0.840332f, 0.889648f, 0.920410f, 0.940918f, 0.956543f, 0.966309f, 0.989746f, 0.990234f, 0.990723f, 0.990723f, 0.990723f, 0.990723f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000191f, 0.000236f, 0.000335f, 0.000337f, 0.000466f, 0.000399f, 0.000608f,
+ 0.000626f, 0.000669f, 0.000696f, 0.000808f, 0.000859f, 0.000915f, 0.000903f, 0.001168f, 0.001245f, 0.001500f, 0.001525f, 0.001863f,
+ 0.001941f, 0.002121f, 0.002399f, 0.002861f, 0.002953f, 0.003632f, 0.004105f, 0.004745f, 0.005333f, 0.006317f, 0.007236f, 0.008255f,
+ 0.009857f, 0.011414f, 0.014015f, 0.016922f, 0.020828f, 0.026321f, 0.034149f, 0.044861f, 0.061279f, 0.085571f, 0.124878f, 0.187866f,
+ 0.285645f, 0.420654f, 0.570801f, 0.703125f, 0.799805f, 0.864258f, 0.905273f, 0.932129f, 0.950684f, 0.963379f, 0.988770f, 0.989258f,
+ 0.989746f, 0.989746f, 0.989746f, 0.989746f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000000f, 0.000122f, 0.000125f, 0.000232f,
+ 0.000360f, 0.000342f, 0.000463f, 0.000388f, 0.000569f, 0.000638f, 0.000671f, 0.000791f, 0.000774f, 0.000943f, 0.000774f, 0.001018f,
+ 0.001044f, 0.001245f, 0.001377f, 0.001410f, 0.001643f, 0.001970f, 0.002041f, 0.002316f, 0.002758f, 0.003023f, 0.003433f, 0.003859f,
+ 0.004444f, 0.005180f, 0.006134f, 0.006920f, 0.008102f, 0.009354f, 0.011475f, 0.013649f, 0.016739f, 0.021011f, 0.026566f, 0.034454f,
+ 0.046051f, 0.063843f, 0.090942f, 0.135498f, 0.207642f, 0.319580f, 0.467529f, 0.620605f, 0.745605f, 0.830566f, 0.886230f, 0.920898f,
+ 0.943848f, 0.958984f, 0.987793f, 0.988281f, 0.988770f, 0.988770f, 0.988281f, 0.988770f, 0.000000f, 0.000000f, 0.000000f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000188f, 0.000200f, 0.000332f, 0.000417f, 0.000338f, 0.000459f, 0.000349f, 0.000558f, 0.000642f, 0.000636f,
+ 0.000629f, 0.000807f, 0.000695f, 0.000747f, 0.000827f, 0.001058f, 0.001182f, 0.001269f, 0.001422f, 0.001472f, 0.001921f, 0.002100f,
+ 0.002337f, 0.002462f, 0.003073f, 0.003374f, 0.003708f, 0.004265f, 0.004826f, 0.005646f, 0.006596f, 0.007710f, 0.008926f, 0.011063f,
+ 0.013580f, 0.016495f, 0.020737f, 0.026459f, 0.035126f, 0.047791f, 0.066833f, 0.097778f, 0.149170f, 0.233887f, 0.363037f, 0.523438f,
+ 0.674805f, 0.788086f, 0.860352f, 0.906250f, 0.935547f, 0.954102f, 0.986328f, 0.987305f, 0.987305f, 0.987305f, 0.987305f, 0.987793f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000175f, 0.000155f, 0.000319f, 0.000241f, 0.000318f,
+ 0.000455f, 0.000462f, 0.000496f, 0.000593f, 0.000516f, 0.000564f, 0.000667f, 0.000668f, 0.000715f, 0.000749f, 0.000925f, 0.001111f,
+ 0.001246f, 0.001381f, 0.001443f, 0.001856f, 0.001997f, 0.002264f, 0.002363f, 0.002880f, 0.003212f, 0.003727f, 0.004208f, 0.004673f,
+ 0.005394f, 0.006367f, 0.007404f, 0.009003f, 0.010651f, 0.013138f, 0.016312f, 0.020767f, 0.027054f, 0.036377f, 0.050262f, 0.071655f,
+ 0.107361f, 0.167969f, 0.269287f, 0.418457f, 0.587402f, 0.730957f, 0.828125f, 0.888184f, 0.924805f, 0.948242f, 0.984863f, 0.986328f,
+ 0.986328f, 0.985840f, 0.986328f, 0.986328f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f,
+ 0.000202f, 0.000133f, 0.000215f, 0.000263f, 0.000304f, 0.000442f, 0.000332f, 0.000365f, 0.000403f, 0.000549f, 0.000607f, 0.000750f,
+ 0.000788f, 0.000802f, 0.000841f, 0.000958f, 0.001049f, 0.001188f, 0.001354f, 0.001318f, 0.001582f, 0.001928f, 0.002064f, 0.002321f,
+ 0.002594f, 0.003042f, 0.003222f, 0.003796f, 0.004440f, 0.005112f, 0.006081f, 0.007259f, 0.008736f, 0.010612f, 0.013077f, 0.016464f,
+ 0.020950f, 0.027664f, 0.037506f, 0.052795f, 0.077698f, 0.120361f, 0.194336f, 0.317627f, 0.486572f, 0.657227f, 0.785156f, 0.865234f,
+ 0.913086f, 0.942871f, 0.983887f, 0.984863f, 0.984375f, 0.984863f, 0.984375f, 0.984863f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000152f, 0.000257f, 0.000243f, 0.000288f, 0.000345f, 0.000228f,
+ 0.000358f, 0.000363f, 0.000432f, 0.000494f, 0.000530f, 0.000582f, 0.000762f, 0.000771f, 0.000913f, 0.000978f, 0.001100f, 0.001305f,
+ 0.001373f, 0.001706f, 0.001712f, 0.001922f, 0.002155f, 0.002569f, 0.002573f, 0.003094f, 0.003401f, 0.004272f, 0.004978f, 0.005829f,
+ 0.006924f, 0.008453f, 0.010452f, 0.012871f, 0.016617f, 0.021072f, 0.028427f, 0.039429f, 0.056732f, 0.086243f, 0.138916f, 0.231812f,
+ 0.381592f, 0.566406f, 0.726562f, 0.833496f, 0.896973f, 0.933594f, 0.981934f, 0.982910f, 0.982910f, 0.982910f, 0.982910f, 0.982910f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000127f, 0.000215f,
+ 0.000159f, 0.000233f, 0.000284f, 0.000326f, 0.000339f, 0.000339f, 0.000352f, 0.000394f, 0.000623f, 0.000622f, 0.000731f, 0.000730f,
+ 0.000741f, 0.000829f, 0.000914f, 0.001017f, 0.001151f, 0.001469f, 0.001263f, 0.001480f, 0.001740f, 0.002069f, 0.002104f, 0.002443f,
+ 0.002831f, 0.003519f, 0.003929f, 0.004627f, 0.005455f, 0.006634f, 0.008316f, 0.009949f, 0.012596f, 0.016495f, 0.021729f, 0.029877f,
+ 0.042084f, 0.062805f, 0.098694f, 0.165283f, 0.284668f, 0.465088f, 0.654297f, 0.793945f, 0.877930f, 0.924805f, 0.979980f, 0.980957f,
+ 0.980957f, 0.981445f, 0.981445f, 0.980957f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000150f, 0.000163f, 0.000069f, 0.000057f, 0.000121f, 0.000231f, 0.000291f, 0.000304f, 0.000334f, 0.000339f,
+ 0.000346f, 0.000569f, 0.000648f, 0.000674f, 0.000649f, 0.000697f, 0.000772f, 0.000834f, 0.000972f, 0.001005f, 0.001189f, 0.001359f,
+ 0.001237f, 0.001567f, 0.001794f, 0.001963f, 0.002378f, 0.002712f, 0.002867f, 0.003853f, 0.004330f, 0.005196f, 0.006516f, 0.008026f,
+ 0.009888f, 0.012703f, 0.016479f, 0.022110f, 0.031158f, 0.045746f, 0.070557f, 0.117004f, 0.204956f, 0.360596f, 0.564453f, 0.740723f,
+ 0.852051f, 0.912598f, 0.977539f, 0.979492f, 0.979492f, 0.979004f, 0.979492f, 0.979004f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000098f, 0.000082f, 0.000067f, 0.000056f, 0.000124f,
+ 0.000193f, 0.000240f, 0.000258f, 0.000310f, 0.000326f, 0.000335f, 0.000341f, 0.000471f, 0.000613f, 0.000494f, 0.000716f, 0.000742f,
+ 0.000804f, 0.000873f, 0.000832f, 0.001070f, 0.001120f, 0.001146f, 0.001225f, 0.001696f, 0.001814f, 0.002041f, 0.002419f, 0.002941f,
+ 0.003433f, 0.004154f, 0.004818f, 0.006077f, 0.007652f, 0.009521f, 0.012444f, 0.017029f, 0.023193f, 0.033539f, 0.050690f, 0.082092f,
+ 0.144043f, 0.265869f, 0.463379f, 0.672363f, 0.818848f, 0.898438f, 0.975586f, 0.976562f, 0.976562f, 0.976562f, 0.976074f, 0.976562f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000114f,
+ 0.000096f, 0.000079f, 0.000125f, 0.000056f, 0.000142f, 0.000120f, 0.000195f, 0.000246f, 0.000321f, 0.000305f, 0.000319f, 0.000395f,
+ 0.000442f, 0.000540f, 0.000642f, 0.000638f, 0.000696f, 0.000674f, 0.000687f, 0.000857f, 0.000955f, 0.001128f, 0.001224f, 0.001364f,
+ 0.001347f, 0.001555f, 0.001910f, 0.002245f, 0.002714f, 0.003229f, 0.003824f, 0.004673f, 0.005676f, 0.007225f, 0.009293f, 0.012802f,
+ 0.017273f, 0.024368f, 0.036682f, 0.058075f, 0.100952f, 0.188721f, 0.358154f, 0.587891f, 0.775879f, 0.881348f, 0.972168f, 0.972656f,
+ 0.972656f, 0.973145f, 0.973145f, 0.973633f, 0.000000f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000112f, 0.000093f, 0.000079f, 0.000067f, 0.000057f, 0.000049f, 0.000133f, 0.000137f,
+ 0.000163f, 0.000244f, 0.000328f, 0.000366f, 0.000356f, 0.000415f, 0.000436f, 0.000543f, 0.000555f, 0.000638f, 0.000597f, 0.000702f,
+ 0.000786f, 0.000648f, 0.000891f, 0.000804f, 0.001218f, 0.001070f, 0.001355f, 0.001731f, 0.002171f, 0.002352f, 0.002796f, 0.003546f,
+ 0.004189f, 0.005558f, 0.006939f, 0.009209f, 0.012337f, 0.017776f, 0.026016f, 0.040833f, 0.069946f, 0.130981f, 0.262207f, 0.489258f,
+ 0.719238f, 0.859375f, 0.968262f, 0.969238f, 0.969727f, 0.969727f, 0.969727f, 0.969727f, 0.000000f, 0.000122f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000110f, 0.000093f, 0.000080f,
+ 0.000068f, 0.000094f, 0.000119f, 0.000117f, 0.000120f, 0.000123f, 0.000173f, 0.000263f, 0.000263f, 0.000359f, 0.000386f, 0.000390f,
+ 0.000401f, 0.000556f, 0.000549f, 0.000573f, 0.000502f, 0.000707f, 0.000789f, 0.000629f, 0.000847f, 0.001003f, 0.001024f, 0.001242f,
+ 0.001423f, 0.001877f, 0.002012f, 0.002571f, 0.003071f, 0.003925f, 0.005131f, 0.006767f, 0.009140f, 0.012672f, 0.018509f, 0.028992f,
+ 0.048309f, 0.089233f, 0.183838f, 0.383545f, 0.646973f, 0.830078f, 0.963867f, 0.964844f, 0.964844f, 0.965820f, 0.965820f, 0.965820f,
+ 0.000000f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f,
+ 0.000119f, 0.000119f, 0.000113f, 0.000095f, 0.000083f, 0.000070f, 0.000061f, 0.000054f, 0.000048f, 0.000042f, 0.000115f, 0.000112f,
+ 0.000151f, 0.000213f, 0.000309f, 0.000298f, 0.000359f, 0.000337f, 0.000382f, 0.000440f, 0.000576f, 0.000477f, 0.000453f, 0.000690f,
+ 0.000687f, 0.000795f, 0.000776f, 0.000911f, 0.001117f, 0.001119f, 0.001352f, 0.002001f, 0.002140f, 0.002832f, 0.003609f, 0.004715f,
+ 0.006302f, 0.008835f, 0.013115f, 0.020004f, 0.032867f, 0.060333f, 0.124512f, 0.281982f, 0.557617f, 0.794434f, 0.959473f, 0.959961f,
+ 0.960449f, 0.960449f, 0.960449f, 0.959961f, 0.000122f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000119f, 0.000119f,
+ 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000118f, 0.000118f, 0.000118f, 0.000116f, 0.000098f, 0.000087f, 0.000076f, 0.000065f,
+ 0.000057f, 0.000050f, 0.000045f, 0.000091f, 0.000074f, 0.000106f, 0.000185f, 0.000193f, 0.000228f, 0.000328f, 0.000323f, 0.000399f,
+ 0.000429f, 0.000498f, 0.000552f, 0.000432f, 0.000542f, 0.000592f, 0.000599f, 0.000729f, 0.000734f, 0.000885f, 0.001304f, 0.001273f,
+ 0.001756f, 0.001931f, 0.002445f, 0.003120f, 0.004456f, 0.006165f, 0.008751f, 0.013466f, 0.022141f, 0.040192f, 0.082397f, 0.195679f,
+ 0.455322f, 0.745117f, 0.952637f, 0.953613f, 0.953613f, 0.954102f, 0.952637f, 0.953613f, 0.000000f, 0.000120f, 0.000120f, 0.000119f,
+ 0.000119f, 0.000119f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000117f, 0.000117f, 0.000117f, 0.000117f, 0.000117f,
+ 0.000117f, 0.000104f, 0.000092f, 0.000079f, 0.000071f, 0.000062f, 0.000055f, 0.000049f, 0.000044f, 0.000039f, 0.000099f, 0.000106f,
+ 0.000158f, 0.000169f, 0.000241f, 0.000274f, 0.000293f, 0.000389f, 0.000360f, 0.000399f, 0.000387f, 0.000446f, 0.000401f, 0.000530f,
+ 0.000565f, 0.000691f, 0.000722f, 0.000848f, 0.001147f, 0.001418f, 0.001677f, 0.002087f, 0.002972f, 0.004169f, 0.005623f, 0.008835f,
+ 0.014404f, 0.026077f, 0.053467f, 0.129395f, 0.346924f, 0.685059f, 0.943848f, 0.945801f, 0.945801f, 0.945312f, 0.945801f, 0.945801f,
+ 0.000000f, 0.000000f, 0.000117f, 0.000116f, 0.000117f, 0.000117f, 0.000116f, 0.000116f, 0.000115f, 0.000116f, 0.000115f, 0.000116f,
+ 0.000115f, 0.000115f, 0.000115f, 0.000115f, 0.000115f, 0.000115f, 0.000110f, 0.000097f, 0.000086f, 0.000077f, 0.000067f, 0.000060f,
+ 0.000053f, 0.000048f, 0.000043f, 0.000061f, 0.000090f, 0.000083f, 0.000139f, 0.000139f, 0.000216f, 0.000254f, 0.000307f, 0.000358f,
+ 0.000269f, 0.000377f, 0.000324f, 0.000369f, 0.000405f, 0.000455f, 0.000524f, 0.000706f, 0.000701f, 0.001012f, 0.001206f, 0.001316f,
+ 0.001663f, 0.002350f, 0.003571f, 0.005505f, 0.008873f, 0.016006f, 0.033234f, 0.081848f, 0.244751f, 0.605469f, 0.934082f, 0.935059f,
+ 0.936035f, 0.935547f, 0.935547f, 0.935547f, 0.000105f, 0.000114f, 0.000113f, 0.000113f, 0.000111f, 0.000111f, 0.000112f, 0.000111f,
+ 0.000112f, 0.000112f, 0.000112f, 0.000112f, 0.000111f, 0.000112f, 0.000112f, 0.000112f, 0.000112f, 0.000112f, 0.000112f, 0.000112f,
+ 0.000105f, 0.000093f, 0.000083f, 0.000074f, 0.000066f, 0.000059f, 0.000053f, 0.000048f, 0.000043f, 0.000062f, 0.000052f, 0.000063f,
+ 0.000092f, 0.000146f, 0.000176f, 0.000216f, 0.000227f, 0.000263f, 0.000244f, 0.000267f, 0.000370f, 0.000326f, 0.000360f, 0.000391f,
+ 0.000505f, 0.000618f, 0.000726f, 0.000969f, 0.001117f, 0.001651f, 0.002131f, 0.003090f, 0.005188f, 0.009499f, 0.019836f, 0.049042f,
+ 0.159180f, 0.509766f, 0.921875f, 0.922852f, 0.922852f, 0.922363f, 0.923340f, 0.922852f, 0.000000f, 0.000000f, 0.000065f, 0.000098f,
+ 0.000096f, 0.000101f, 0.000100f, 0.000104f, 0.000104f, 0.000103f, 0.000106f, 0.000106f, 0.000106f, 0.000105f, 0.000107f, 0.000107f,
+ 0.000106f, 0.000107f, 0.000107f, 0.000108f, 0.000107f, 0.000108f, 0.000104f, 0.000092f, 0.000082f, 0.000075f, 0.000067f, 0.000059f,
+ 0.000054f, 0.000048f, 0.000044f, 0.000039f, 0.000037f, 0.000058f, 0.000066f, 0.000122f, 0.000137f, 0.000175f, 0.000208f, 0.000194f,
+ 0.000208f, 0.000240f, 0.000270f, 0.000281f, 0.000323f, 0.000364f, 0.000479f, 0.000591f, 0.000712f, 0.000986f, 0.001224f, 0.001896f,
+ 0.002996f, 0.005196f, 0.010506f, 0.027527f, 0.095581f, 0.399658f, 0.905762f, 0.906738f, 0.906250f, 0.905762f, 0.905762f, 0.907227f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000017f, 0.000030f, 0.000054f, 0.000061f, 0.000081f, 0.000087f, 0.000088f, 0.000089f, 0.000093f,
+ 0.000093f, 0.000096f, 0.000096f, 0.000097f, 0.000098f, 0.000099f, 0.000098f, 0.000100f, 0.000100f, 0.000101f, 0.000100f, 0.000101f,
+ 0.000101f, 0.000092f, 0.000082f, 0.000074f, 0.000067f, 0.000060f, 0.000054f, 0.000049f, 0.000045f, 0.000040f, 0.000036f, 0.000037f,
+ 0.000059f, 0.000077f, 0.000093f, 0.000143f, 0.000155f, 0.000188f, 0.000178f, 0.000184f, 0.000231f, 0.000234f, 0.000272f, 0.000352f,
+ 0.000420f, 0.000525f, 0.000764f, 0.001091f, 0.001653f, 0.002705f, 0.005474f, 0.013939f, 0.051880f, 0.283691f, 0.883789f, 0.884766f,
+ 0.885254f, 0.885254f, 0.885742f, 0.885254f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000013f,
+ 0.000032f, 0.000046f, 0.000050f, 0.000060f, 0.000065f, 0.000065f, 0.000075f, 0.000078f, 0.000080f, 0.000079f, 0.000084f, 0.000083f,
+ 0.000087f, 0.000087f, 0.000089f, 0.000090f, 0.000091f, 0.000091f, 0.000092f, 0.000092f, 0.000083f, 0.000075f, 0.000068f, 0.000062f,
+ 0.000056f, 0.000050f, 0.000046f, 0.000042f, 0.000037f, 0.000039f, 0.000044f, 0.000072f, 0.000068f, 0.000089f, 0.000125f, 0.000124f,
+ 0.000126f, 0.000153f, 0.000183f, 0.000212f, 0.000219f, 0.000311f, 0.000363f, 0.000566f, 0.000846f, 0.001332f, 0.002522f, 0.006252f,
+ 0.023834f, 0.175415f, 0.855957f, 0.856934f, 0.856934f, 0.856934f, 0.857422f, 0.856934f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000007f, 0.000024f, 0.000028f,
+ 0.000040f, 0.000044f, 0.000051f, 0.000053f, 0.000060f, 0.000063f, 0.000064f, 0.000067f, 0.000071f, 0.000072f, 0.000074f, 0.000076f,
+ 0.000077f, 0.000079f, 0.000079f, 0.000075f, 0.000068f, 0.000062f, 0.000056f, 0.000051f, 0.000046f, 0.000042f, 0.000038f, 0.000034f,
+ 0.000031f, 0.000030f, 0.000045f, 0.000079f, 0.000081f, 0.000107f, 0.000114f, 0.000106f, 0.000144f, 0.000136f, 0.000171f, 0.000254f,
+ 0.000377f, 0.000531f, 0.001037f, 0.002504f, 0.009140f, 0.088379f, 0.818848f, 0.820801f, 0.819824f, 0.820312f, 0.819336f, 0.820801f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000007f, 0.000014f, 0.000021f, 0.000028f,
+ 0.000034f, 0.000036f, 0.000042f, 0.000046f, 0.000049f, 0.000052f, 0.000054f, 0.000056f, 0.000059f, 0.000061f, 0.000064f, 0.000061f,
+ 0.000055f, 0.000050f, 0.000045f, 0.000041f, 0.000037f, 0.000033f, 0.000030f, 0.000027f, 0.000024f, 0.000033f, 0.000060f, 0.000059f,
+ 0.000075f, 0.000073f, 0.000101f, 0.000089f, 0.000144f, 0.000226f, 0.000384f, 0.000847f, 0.003033f, 0.031860f, 0.770020f, 0.770996f,
+ 0.772461f, 0.771973f, 0.772461f, 0.771973f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000010f, 0.000016f,
+ 0.000021f, 0.000023f, 0.000029f, 0.000032f, 0.000036f, 0.000039f, 0.000042f, 0.000044f, 0.000042f, 0.000038f, 0.000035f, 0.000031f,
+ 0.000028f, 0.000025f, 0.000022f, 0.000020f, 0.000017f, 0.000024f, 0.000040f, 0.000047f, 0.000053f, 0.000063f, 0.000087f, 0.000190f,
+ 0.000666f, 0.007278f, 0.708496f, 0.709961f, 0.710449f, 0.710938f, 0.710938f, 0.710449f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f,
+ 0.000005f, 0.000010f, 0.000014f, 0.000018f, 0.000021f, 0.000024f, 0.000024f, 0.000021f, 0.000018f, 0.000016f, 0.000014f, 0.000012f,
+ 0.000008f, 0.000020f, 0.000022f, 0.000025f, 0.000073f, 0.000744f, 0.632324f, 0.632812f, 0.633789f, 0.633789f, 0.633301f, 0.632812f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000007f, 0.000006f, 0.000004f, 0.000005f, 0.000007f, 0.543945f, 0.545410f,
+ 0.545410f, 0.545410f, 0.546387f, 0.545898f,
+ },
+ {
+ 0.159546f, 0.492676f, 0.684570f, 0.783203f, 0.838379f, 0.873535f, 0.897949f, 0.913574f, 0.926270f, 0.936035f, 0.943359f, 0.950195f,
+ 0.955566f, 0.959473f, 0.963379f, 0.966797f, 0.969238f, 0.972168f, 0.973633f, 0.976562f, 0.978027f, 0.979492f, 0.980957f, 0.982422f,
+ 0.983887f, 0.984863f, 0.985840f, 0.986816f, 0.987793f, 0.988770f, 0.989258f, 0.989746f, 0.990234f, 0.990723f, 0.991699f, 0.992676f,
+ 0.993164f, 0.993652f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997070f,
+ 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.034119f, 0.154175f, 0.341309f, 0.532227f, 0.672363f, 0.763184f, 0.820801f, 0.858398f,
+ 0.885742f, 0.904297f, 0.918945f, 0.929199f, 0.938965f, 0.945801f, 0.951660f, 0.956543f, 0.961426f, 0.964355f, 0.968262f, 0.970703f,
+ 0.973145f, 0.975586f, 0.977539f, 0.979004f, 0.980469f, 0.981934f, 0.983398f, 0.984375f, 0.985352f, 0.986328f, 0.987305f, 0.988281f,
+ 0.988770f, 0.989746f, 0.990234f, 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f,
+ 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f,
+ 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.013390f, 0.056915f, 0.134155f, 0.257080f,
+ 0.412109f, 0.560547f, 0.675781f, 0.755859f, 0.812012f, 0.851074f, 0.877930f, 0.898926f, 0.913574f, 0.925781f, 0.935059f, 0.942871f,
+ 0.949707f, 0.954590f, 0.959473f, 0.963379f, 0.966797f, 0.969238f, 0.971680f, 0.975098f, 0.976562f, 0.978516f, 0.979980f, 0.980957f,
+ 0.982422f, 0.984375f, 0.985352f, 0.985840f, 0.987305f, 0.987793f, 0.988770f, 0.989746f, 0.990723f, 0.991211f, 0.991699f, 0.992188f,
+ 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995605f, 0.995605f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997070f,
+ 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f,
+ 0.006939f, 0.027863f, 0.061951f, 0.117859f, 0.204834f, 0.324707f, 0.460205f, 0.585449f, 0.684570f, 0.757324f, 0.810059f, 0.847168f,
+ 0.874023f, 0.895996f, 0.910645f, 0.922852f, 0.933105f, 0.940918f, 0.947754f, 0.953613f, 0.958496f, 0.961914f, 0.965820f, 0.968750f,
+ 0.971680f, 0.974121f, 0.976074f, 0.978027f, 0.979492f, 0.981445f, 0.982910f, 0.983887f, 0.984863f, 0.986328f, 0.987305f, 0.988281f,
+ 0.988770f, 0.989746f, 0.990234f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.993652f, 0.994141f, 0.995117f, 0.995605f,
+ 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.004211f, 0.016022f, 0.034119f, 0.061432f, 0.104797f, 0.170288f, 0.262695f, 0.377686f,
+ 0.499756f, 0.608887f, 0.696777f, 0.762207f, 0.810547f, 0.847168f, 0.873535f, 0.893066f, 0.910156f, 0.922852f, 0.932617f, 0.939941f,
+ 0.946777f, 0.953125f, 0.958496f, 0.961914f, 0.965332f, 0.968750f, 0.971680f, 0.973633f, 0.975586f, 0.977539f, 0.979492f, 0.981445f,
+ 0.982910f, 0.984375f, 0.985840f, 0.986328f, 0.987793f, 0.987793f, 0.989258f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.992676f,
+ 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f,
+ 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999023f, 0.999512f, 0.999023f, 0.999023f, 0.002724f, 0.010384f, 0.020813f, 0.036285f,
+ 0.059784f, 0.093933f, 0.145508f, 0.218018f, 0.313232f, 0.424072f, 0.534180f, 0.632812f, 0.709961f, 0.769531f, 0.815918f, 0.848145f,
+ 0.874512f, 0.894043f, 0.909668f, 0.922363f, 0.932129f, 0.939941f, 0.946777f, 0.953125f, 0.958008f, 0.961914f, 0.965332f, 0.968750f,
+ 0.971680f, 0.973633f, 0.976562f, 0.978516f, 0.979980f, 0.981445f, 0.982910f, 0.984863f, 0.985352f, 0.986816f, 0.987793f, 0.988281f,
+ 0.988770f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f,
+ 0.002113f, 0.007004f, 0.014091f, 0.023895f, 0.037811f, 0.057373f, 0.085632f, 0.127075f, 0.185425f, 0.263672f, 0.360596f, 0.465576f,
+ 0.566895f, 0.655762f, 0.725586f, 0.779297f, 0.822266f, 0.853516f, 0.877441f, 0.895996f, 0.911621f, 0.923828f, 0.933105f, 0.940918f,
+ 0.947754f, 0.953613f, 0.957520f, 0.962402f, 0.965820f, 0.968750f, 0.972168f, 0.974121f, 0.976074f, 0.978027f, 0.980469f, 0.981934f,
+ 0.983398f, 0.984863f, 0.985352f, 0.986328f, 0.988281f, 0.988281f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.992676f, 0.993164f,
+ 0.993652f, 0.994629f, 0.994629f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.001575f, 0.005211f, 0.010040f, 0.016220f, 0.025665f, 0.037415f, 0.054138f, 0.078491f,
+ 0.112915f, 0.160156f, 0.225464f, 0.308594f, 0.405029f, 0.506348f, 0.599121f, 0.678711f, 0.743164f, 0.791016f, 0.829590f, 0.859375f,
+ 0.881836f, 0.899414f, 0.913086f, 0.924805f, 0.934570f, 0.942383f, 0.948730f, 0.955078f, 0.958984f, 0.963379f, 0.966797f, 0.970215f,
+ 0.972168f, 0.974609f, 0.977051f, 0.979004f, 0.980957f, 0.981934f, 0.983398f, 0.984863f, 0.986328f, 0.987305f, 0.988281f, 0.989258f,
+ 0.990234f, 0.991211f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f,
+ 0.996582f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000985f, 0.004086f, 0.007362f, 0.011887f,
+ 0.018127f, 0.026199f, 0.036804f, 0.052002f, 0.072754f, 0.101318f, 0.140747f, 0.195190f, 0.266113f, 0.352539f, 0.448730f, 0.543945f,
+ 0.630371f, 0.702637f, 0.759277f, 0.803711f, 0.839355f, 0.865234f, 0.886719f, 0.903320f, 0.916504f, 0.927734f, 0.936523f, 0.944336f,
+ 0.950195f, 0.955566f, 0.959961f, 0.964355f, 0.967773f, 0.970215f, 0.973145f, 0.975586f, 0.978027f, 0.979004f, 0.980957f, 0.982910f,
+ 0.984375f, 0.985352f, 0.987305f, 0.987305f, 0.988770f, 0.990234f, 0.990234f, 0.991699f, 0.991699f, 0.993164f, 0.993164f, 0.993652f,
+ 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.998535f, 0.999023f,
+ 0.000829f, 0.002878f, 0.005596f, 0.009109f, 0.013359f, 0.019089f, 0.026901f, 0.036774f, 0.049347f, 0.067200f, 0.091736f, 0.125854f,
+ 0.171631f, 0.232544f, 0.308594f, 0.397461f, 0.491455f, 0.581055f, 0.659668f, 0.724609f, 0.775879f, 0.817383f, 0.848633f, 0.873047f,
+ 0.892090f, 0.907715f, 0.920410f, 0.930664f, 0.939453f, 0.946289f, 0.951660f, 0.957520f, 0.960938f, 0.965820f, 0.968750f, 0.972168f,
+ 0.974609f, 0.976562f, 0.978516f, 0.980469f, 0.981934f, 0.983887f, 0.984863f, 0.986328f, 0.986816f, 0.988770f, 0.989746f, 0.990234f,
+ 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996582f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000836f, 0.002403f, 0.004837f, 0.006950f, 0.010269f, 0.014679f, 0.019699f, 0.026291f,
+ 0.035431f, 0.046875f, 0.062744f, 0.084045f, 0.113403f, 0.152588f, 0.204712f, 0.271729f, 0.353271f, 0.443115f, 0.532715f, 0.617188f,
+ 0.688477f, 0.748047f, 0.793945f, 0.829102f, 0.857422f, 0.880371f, 0.898438f, 0.912598f, 0.924316f, 0.934082f, 0.941406f, 0.948242f,
+ 0.954590f, 0.959473f, 0.963379f, 0.967285f, 0.970215f, 0.973145f, 0.975586f, 0.977539f, 0.979980f, 0.981445f, 0.982910f, 0.984375f,
+ 0.985840f, 0.987305f, 0.988281f, 0.988770f, 0.990234f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.995117f,
+ 0.995605f, 0.996094f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000698f, 0.002052f, 0.003618f, 0.005703f,
+ 0.008430f, 0.011230f, 0.015083f, 0.019821f, 0.026474f, 0.034393f, 0.044922f, 0.059204f, 0.077698f, 0.102661f, 0.136963f, 0.182373f,
+ 0.241089f, 0.314941f, 0.398926f, 0.489014f, 0.575195f, 0.652344f, 0.717285f, 0.769043f, 0.810059f, 0.842773f, 0.869141f, 0.888672f,
+ 0.904785f, 0.917969f, 0.928711f, 0.936523f, 0.945312f, 0.951660f, 0.957031f, 0.961426f, 0.964844f, 0.968750f, 0.971680f, 0.974121f,
+ 0.976562f, 0.979004f, 0.980469f, 0.982422f, 0.983887f, 0.985352f, 0.986816f, 0.987793f, 0.988770f, 0.990234f, 0.990723f, 0.991699f,
+ 0.992676f, 0.993164f, 0.994141f, 0.994141f, 0.994629f, 0.995605f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f,
+ 0.000244f, 0.001565f, 0.002975f, 0.004433f, 0.006596f, 0.008957f, 0.012215f, 0.015533f, 0.020294f, 0.026062f, 0.033722f, 0.042816f,
+ 0.055237f, 0.071960f, 0.094543f, 0.124023f, 0.164185f, 0.216309f, 0.281738f, 0.360352f, 0.446533f, 0.534180f, 0.615234f, 0.686523f,
+ 0.743652f, 0.790527f, 0.825684f, 0.855957f, 0.878418f, 0.895996f, 0.911133f, 0.923340f, 0.933105f, 0.941406f, 0.948242f, 0.953613f,
+ 0.959473f, 0.963379f, 0.966797f, 0.970703f, 0.973145f, 0.976074f, 0.978516f, 0.980469f, 0.982422f, 0.983398f, 0.984863f, 0.986328f,
+ 0.987305f, 0.989258f, 0.989746f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.998047f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998047f, 0.000365f, 0.001394f, 0.002546f, 0.004055f, 0.005394f, 0.007465f, 0.009674f, 0.012070f,
+ 0.015556f, 0.019913f, 0.025696f, 0.032623f, 0.041046f, 0.052643f, 0.067383f, 0.087463f, 0.113708f, 0.148315f, 0.194946f, 0.254395f,
+ 0.326416f, 0.408691f, 0.495117f, 0.579102f, 0.654297f, 0.716797f, 0.768066f, 0.809570f, 0.843262f, 0.868652f, 0.888184f, 0.904785f,
+ 0.918457f, 0.929199f, 0.937500f, 0.945801f, 0.951660f, 0.957520f, 0.961914f, 0.965820f, 0.969238f, 0.972656f, 0.975098f, 0.978027f,
+ 0.979492f, 0.981934f, 0.983398f, 0.984863f, 0.986328f, 0.987793f, 0.989258f, 0.989746f, 0.991211f, 0.991211f, 0.992188f, 0.993164f,
+ 0.993652f, 0.994629f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000596f, 0.001077f, 0.001882f, 0.003033f,
+ 0.004559f, 0.006241f, 0.007805f, 0.010002f, 0.012840f, 0.015900f, 0.019974f, 0.025131f, 0.031250f, 0.039337f, 0.049988f, 0.063843f,
+ 0.080933f, 0.105164f, 0.135986f, 0.176880f, 0.230103f, 0.296631f, 0.374268f, 0.459961f, 0.544434f, 0.623535f, 0.691895f, 0.748535f,
+ 0.792969f, 0.829102f, 0.857422f, 0.880371f, 0.897949f, 0.913086f, 0.924805f, 0.934570f, 0.942383f, 0.949219f, 0.955566f, 0.960938f,
+ 0.964844f, 0.968750f, 0.971191f, 0.974121f, 0.977051f, 0.979004f, 0.980957f, 0.982910f, 0.984863f, 0.985840f, 0.987305f, 0.989258f,
+ 0.989746f, 0.991211f, 0.991211f, 0.992676f, 0.993164f, 0.993652f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f,
+ 0.000243f, 0.001173f, 0.001889f, 0.002661f, 0.003933f, 0.005131f, 0.006496f, 0.008324f, 0.010574f, 0.013115f, 0.015839f, 0.019913f,
+ 0.024445f, 0.030609f, 0.037781f, 0.047333f, 0.059906f, 0.075928f, 0.097229f, 0.124939f, 0.161743f, 0.209595f, 0.271240f, 0.343994f,
+ 0.426758f, 0.511719f, 0.592773f, 0.666504f, 0.727051f, 0.776855f, 0.815918f, 0.847656f, 0.871582f, 0.892090f, 0.907715f, 0.920898f,
+ 0.931152f, 0.940918f, 0.947754f, 0.953613f, 0.958496f, 0.963867f, 0.967773f, 0.970703f, 0.974121f, 0.976074f, 0.979004f, 0.980469f,
+ 0.982910f, 0.984375f, 0.985840f, 0.987305f, 0.988770f, 0.990234f, 0.990234f, 0.992188f, 0.992188f, 0.993164f, 0.997070f, 0.997559f,
+ 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000351f, 0.000842f, 0.001560f, 0.002363f, 0.003258f, 0.004131f, 0.005272f, 0.007179f,
+ 0.008682f, 0.010643f, 0.013016f, 0.016037f, 0.019516f, 0.024078f, 0.029602f, 0.036591f, 0.045044f, 0.056641f, 0.071350f, 0.090576f,
+ 0.116211f, 0.149414f, 0.193237f, 0.248779f, 0.317871f, 0.396973f, 0.481201f, 0.564453f, 0.640137f, 0.705566f, 0.759766f, 0.802734f,
+ 0.836914f, 0.863281f, 0.885742f, 0.902832f, 0.916992f, 0.927734f, 0.937012f, 0.945801f, 0.952637f, 0.958008f, 0.961914f, 0.966309f,
+ 0.970703f, 0.974121f, 0.976074f, 0.978516f, 0.980957f, 0.982910f, 0.984863f, 0.985840f, 0.987305f, 0.988281f, 0.989746f, 0.990723f,
+ 0.991211f, 0.992676f, 0.997070f, 0.997559f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000886f, 0.001405f, 0.001915f,
+ 0.002651f, 0.003870f, 0.004845f, 0.006035f, 0.006912f, 0.008812f, 0.010887f, 0.013229f, 0.016022f, 0.019196f, 0.023590f, 0.028992f,
+ 0.035248f, 0.043304f, 0.053711f, 0.066956f, 0.085083f, 0.107727f, 0.138428f, 0.178589f, 0.229980f, 0.293945f, 0.370117f, 0.453369f,
+ 0.537109f, 0.616699f, 0.685059f, 0.743164f, 0.790039f, 0.826660f, 0.856445f, 0.878906f, 0.897949f, 0.913574f, 0.925293f, 0.935547f,
+ 0.943848f, 0.951172f, 0.957031f, 0.961914f, 0.966797f, 0.970215f, 0.973145f, 0.976562f, 0.979004f, 0.980469f, 0.982910f, 0.984375f,
+ 0.985840f, 0.987305f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f,
+ 0.000104f, 0.000719f, 0.001065f, 0.001970f, 0.002544f, 0.003149f, 0.004230f, 0.005138f, 0.006119f, 0.007580f, 0.009201f, 0.010902f,
+ 0.013260f, 0.015526f, 0.019272f, 0.022858f, 0.027512f, 0.033569f, 0.041199f, 0.050873f, 0.063782f, 0.079895f, 0.101135f, 0.128906f,
+ 0.165771f, 0.213745f, 0.273193f, 0.345703f, 0.427002f, 0.511719f, 0.592773f, 0.666016f, 0.727051f, 0.776367f, 0.817871f, 0.848633f,
+ 0.875000f, 0.894531f, 0.909668f, 0.922852f, 0.934082f, 0.942383f, 0.949707f, 0.956055f, 0.961914f, 0.966309f, 0.970215f, 0.973145f,
+ 0.976562f, 0.978516f, 0.980957f, 0.982910f, 0.984375f, 0.986328f, 0.987305f, 0.988281f, 0.989746f, 0.991211f, 0.996582f, 0.997070f,
+ 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000240f, 0.000686f, 0.001052f, 0.001375f, 0.002308f, 0.002735f, 0.003510f, 0.004269f,
+ 0.005173f, 0.006649f, 0.007442f, 0.009109f, 0.011246f, 0.012886f, 0.015732f, 0.018829f, 0.022354f, 0.026672f, 0.032867f, 0.039764f,
+ 0.048492f, 0.060455f, 0.075806f, 0.095276f, 0.121033f, 0.155273f, 0.199097f, 0.255859f, 0.324463f, 0.404053f, 0.488525f, 0.571289f,
+ 0.646484f, 0.711426f, 0.765625f, 0.808105f, 0.841797f, 0.869141f, 0.890137f, 0.907227f, 0.920898f, 0.931641f, 0.940918f, 0.948730f,
+ 0.955078f, 0.960449f, 0.965820f, 0.969727f, 0.972656f, 0.976562f, 0.978516f, 0.980957f, 0.982910f, 0.984863f, 0.986328f, 0.987793f,
+ 0.989746f, 0.990723f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.000244f, 0.000597f, 0.000939f, 0.001369f,
+ 0.001999f, 0.002329f, 0.003105f, 0.003786f, 0.004395f, 0.005413f, 0.006474f, 0.007793f, 0.009254f, 0.010971f, 0.012970f, 0.015526f,
+ 0.018112f, 0.022049f, 0.026581f, 0.031586f, 0.038666f, 0.046967f, 0.057617f, 0.071777f, 0.089783f, 0.113953f, 0.145264f, 0.186646f,
+ 0.239990f, 0.305908f, 0.383301f, 0.467285f, 0.551270f, 0.629883f, 0.697266f, 0.754883f, 0.799805f, 0.835938f, 0.864258f, 0.886719f,
+ 0.905273f, 0.918945f, 0.931152f, 0.940918f, 0.948242f, 0.955078f, 0.961426f, 0.965332f, 0.969727f, 0.973633f, 0.976074f, 0.979004f,
+ 0.980957f, 0.983398f, 0.984863f, 0.987305f, 0.988281f, 0.989258f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.996582f,
+ 0.000000f, 0.000475f, 0.000891f, 0.001390f, 0.001730f, 0.002060f, 0.002501f, 0.003109f, 0.003836f, 0.004837f, 0.005852f, 0.006859f,
+ 0.007740f, 0.009216f, 0.010918f, 0.012863f, 0.014915f, 0.017731f, 0.021317f, 0.025482f, 0.030930f, 0.037262f, 0.044891f, 0.055115f,
+ 0.068298f, 0.085510f, 0.107910f, 0.137207f, 0.176025f, 0.226929f, 0.289551f, 0.364746f, 0.447998f, 0.532715f, 0.613770f, 0.685547f,
+ 0.744629f, 0.791992f, 0.830078f, 0.860352f, 0.884277f, 0.903320f, 0.917969f, 0.930176f, 0.939941f, 0.947754f, 0.954590f, 0.961426f,
+ 0.966309f, 0.970215f, 0.973145f, 0.976562f, 0.979492f, 0.981445f, 0.983398f, 0.985352f, 0.987793f, 0.988281f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996582f, 0.996094f, 0.996094f, 0.000102f, 0.000243f, 0.000844f, 0.001124f, 0.001554f, 0.002077f, 0.002098f, 0.002682f,
+ 0.003357f, 0.004280f, 0.005035f, 0.005764f, 0.006805f, 0.007633f, 0.009354f, 0.010872f, 0.012665f, 0.015099f, 0.017258f, 0.020599f,
+ 0.024887f, 0.029495f, 0.035522f, 0.042999f, 0.053070f, 0.065125f, 0.081299f, 0.102661f, 0.130371f, 0.166992f, 0.215088f, 0.275635f,
+ 0.348877f, 0.431641f, 0.517578f, 0.600098f, 0.672852f, 0.735352f, 0.785645f, 0.826172f, 0.856934f, 0.881836f, 0.900879f, 0.916992f,
+ 0.930176f, 0.940430f, 0.947754f, 0.955078f, 0.960938f, 0.966309f, 0.969238f, 0.973633f, 0.977051f, 0.979492f, 0.981934f, 0.983887f,
+ 0.986328f, 0.987793f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000241f, 0.000242f, 0.000823f, 0.000956f,
+ 0.001225f, 0.001549f, 0.002031f, 0.002613f, 0.003124f, 0.003574f, 0.004467f, 0.004955f, 0.005672f, 0.006752f, 0.007603f, 0.009186f,
+ 0.010704f, 0.012741f, 0.014366f, 0.017487f, 0.020142f, 0.024002f, 0.028915f, 0.034943f, 0.041656f, 0.050964f, 0.062622f, 0.077881f,
+ 0.097961f, 0.124207f, 0.158936f, 0.204590f, 0.263184f, 0.334961f, 0.416748f, 0.502930f, 0.587891f, 0.664062f, 0.728516f, 0.780762f,
+ 0.822266f, 0.854492f, 0.879395f, 0.900879f, 0.916504f, 0.928711f, 0.940430f, 0.948730f, 0.955566f, 0.961914f, 0.967285f, 0.970215f,
+ 0.974121f, 0.977539f, 0.979980f, 0.982422f, 0.984863f, 0.986816f, 0.994629f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f,
+ 0.000000f, 0.000473f, 0.000607f, 0.000921f, 0.000957f, 0.001448f, 0.001884f, 0.002270f, 0.002703f, 0.002998f, 0.003862f, 0.004307f,
+ 0.005074f, 0.005665f, 0.006737f, 0.007851f, 0.009216f, 0.010735f, 0.012459f, 0.014572f, 0.016998f, 0.019821f, 0.023605f, 0.027969f,
+ 0.033783f, 0.040192f, 0.049286f, 0.060303f, 0.074829f, 0.093750f, 0.118774f, 0.152222f, 0.195801f, 0.252441f, 0.322754f, 0.404053f,
+ 0.491943f, 0.577637f, 0.655273f, 0.722168f, 0.776367f, 0.820312f, 0.854004f, 0.878906f, 0.900879f, 0.916992f, 0.929688f, 0.940430f,
+ 0.949707f, 0.956055f, 0.962402f, 0.967285f, 0.971191f, 0.975586f, 0.978516f, 0.980957f, 0.983398f, 0.985352f, 0.994141f, 0.995117f,
+ 0.995117f, 0.995605f, 0.995117f, 0.995605f, 0.000000f, 0.000444f, 0.000605f, 0.000649f, 0.000926f, 0.001096f, 0.001624f, 0.001669f,
+ 0.002373f, 0.002716f, 0.003231f, 0.003769f, 0.004395f, 0.005005f, 0.005878f, 0.006710f, 0.007793f, 0.008957f, 0.010712f, 0.012230f,
+ 0.014244f, 0.016693f, 0.019531f, 0.022827f, 0.027100f, 0.032318f, 0.038971f, 0.047302f, 0.058105f, 0.072021f, 0.089966f, 0.114319f,
+ 0.146362f, 0.188965f, 0.244019f, 0.312988f, 0.394287f, 0.482178f, 0.569824f, 0.650391f, 0.718262f, 0.774414f, 0.819336f, 0.853027f,
+ 0.880371f, 0.900879f, 0.917969f, 0.930664f, 0.940918f, 0.950684f, 0.957031f, 0.962891f, 0.968262f, 0.972656f, 0.976562f, 0.979004f,
+ 0.981934f, 0.984375f, 0.994141f, 0.994629f, 0.994629f, 0.995117f, 0.994629f, 0.995117f, 0.000000f, 0.000336f, 0.000601f, 0.000712f,
+ 0.000810f, 0.001174f, 0.001286f, 0.001618f, 0.002037f, 0.002592f, 0.002920f, 0.003223f, 0.003847f, 0.004463f, 0.005119f, 0.006020f,
+ 0.006783f, 0.007957f, 0.008888f, 0.010590f, 0.012230f, 0.013885f, 0.016220f, 0.019318f, 0.022278f, 0.026474f, 0.031403f, 0.037781f,
+ 0.046021f, 0.055969f, 0.069397f, 0.086975f, 0.110413f, 0.140991f, 0.182739f, 0.236694f, 0.304932f, 0.385986f, 0.475586f, 0.563965f,
+ 0.646484f, 0.716797f, 0.772461f, 0.818359f, 0.853027f, 0.880859f, 0.901855f, 0.918945f, 0.932129f, 0.942383f, 0.951172f, 0.958496f,
+ 0.964355f, 0.969238f, 0.973633f, 0.977051f, 0.979980f, 0.982910f, 0.993652f, 0.994141f, 0.994629f, 0.994141f, 0.994141f, 0.994629f,
+ 0.000000f, 0.000244f, 0.000418f, 0.000597f, 0.000600f, 0.001085f, 0.001236f, 0.001535f, 0.001970f, 0.002096f, 0.002354f, 0.002834f,
+ 0.003323f, 0.003822f, 0.004463f, 0.005146f, 0.005798f, 0.006859f, 0.007587f, 0.008827f, 0.009956f, 0.011833f, 0.013725f, 0.015945f,
+ 0.018585f, 0.021988f, 0.025665f, 0.030807f, 0.036774f, 0.044373f, 0.054108f, 0.067383f, 0.084229f, 0.106812f, 0.137207f, 0.177734f,
+ 0.230835f, 0.299072f, 0.380127f, 0.470215f, 0.560547f, 0.644531f, 0.715820f, 0.774414f, 0.820312f, 0.854980f, 0.882324f, 0.903809f,
+ 0.921387f, 0.933594f, 0.944824f, 0.952637f, 0.960449f, 0.965820f, 0.971191f, 0.974609f, 0.978027f, 0.981934f, 0.993164f, 0.994629f,
+ 0.994141f, 0.994141f, 0.994141f, 0.994141f, 0.000000f, 0.000244f, 0.000411f, 0.000589f, 0.000820f, 0.000729f, 0.001086f, 0.001301f,
+ 0.001677f, 0.001935f, 0.002312f, 0.002678f, 0.002846f, 0.003590f, 0.003914f, 0.004578f, 0.005020f, 0.005753f, 0.006706f, 0.007710f,
+ 0.008911f, 0.010155f, 0.011528f, 0.013504f, 0.015747f, 0.018036f, 0.021408f, 0.024994f, 0.029816f, 0.035858f, 0.043152f, 0.053009f,
+ 0.065491f, 0.082031f, 0.104065f, 0.133789f, 0.174072f, 0.226929f, 0.294434f, 0.376465f, 0.467773f, 0.560059f, 0.644531f, 0.717285f,
+ 0.777344f, 0.823242f, 0.857910f, 0.885742f, 0.906738f, 0.922852f, 0.936523f, 0.947266f, 0.955078f, 0.961426f, 0.967285f, 0.972656f,
+ 0.976562f, 0.979980f, 0.992676f, 0.993164f, 0.993652f, 0.993652f, 0.993652f, 0.993652f, 0.000000f, 0.000243f, 0.000243f, 0.000442f,
+ 0.000695f, 0.000759f, 0.000837f, 0.001089f, 0.001625f, 0.001702f, 0.002045f, 0.002176f, 0.002756f, 0.003063f, 0.003687f, 0.003893f,
+ 0.004456f, 0.005337f, 0.006062f, 0.006523f, 0.007572f, 0.008430f, 0.009880f, 0.011612f, 0.013237f, 0.015114f, 0.017487f, 0.020584f,
+ 0.024445f, 0.028931f, 0.034729f, 0.042023f, 0.051788f, 0.063843f, 0.079956f, 0.102295f, 0.131592f, 0.171021f, 0.223877f, 0.292236f,
+ 0.375000f, 0.468018f, 0.562012f, 0.648438f, 0.721191f, 0.781250f, 0.826660f, 0.862305f, 0.888672f, 0.909668f, 0.926270f, 0.938965f,
+ 0.949707f, 0.957520f, 0.964355f, 0.969727f, 0.974121f, 0.978027f, 0.992676f, 0.993164f, 0.993164f, 0.992676f, 0.993164f, 0.993164f,
+ 0.000000f, 0.000242f, 0.000242f, 0.000242f, 0.000564f, 0.000692f, 0.000826f, 0.001094f, 0.001280f, 0.001457f, 0.001673f, 0.002232f,
+ 0.002411f, 0.002789f, 0.003174f, 0.003649f, 0.003859f, 0.004349f, 0.004990f, 0.005898f, 0.006622f, 0.007496f, 0.008209f, 0.009583f,
+ 0.011284f, 0.013062f, 0.014763f, 0.017120f, 0.020020f, 0.023804f, 0.028412f, 0.033905f, 0.041016f, 0.050140f, 0.062469f, 0.078552f,
+ 0.100159f, 0.129272f, 0.169067f, 0.222290f, 0.291504f, 0.376465f, 0.470703f, 0.566406f, 0.653320f, 0.728027f, 0.786621f, 0.832031f,
+ 0.866699f, 0.893555f, 0.914062f, 0.929688f, 0.942383f, 0.952148f, 0.959961f, 0.966797f, 0.972168f, 0.976074f, 0.991211f, 0.992188f,
+ 0.992676f, 0.992188f, 0.992676f, 0.992676f, 0.000241f, 0.000241f, 0.000240f, 0.000242f, 0.000486f, 0.000637f, 0.000916f, 0.000933f,
+ 0.001003f, 0.001284f, 0.001584f, 0.001925f, 0.002134f, 0.002502f, 0.002731f, 0.003134f, 0.003435f, 0.004036f, 0.004379f, 0.005077f,
+ 0.005688f, 0.006557f, 0.007347f, 0.007942f, 0.009506f, 0.010712f, 0.012527f, 0.014603f, 0.016693f, 0.019592f, 0.023285f, 0.027512f,
+ 0.033173f, 0.040283f, 0.049347f, 0.061432f, 0.077271f, 0.098938f, 0.128052f, 0.168091f, 0.222168f, 0.292725f, 0.379150f, 0.476807f,
+ 0.573730f, 0.662598f, 0.735840f, 0.794434f, 0.839844f, 0.873535f, 0.898926f, 0.918945f, 0.934082f, 0.945312f, 0.955566f, 0.962402f,
+ 0.969238f, 0.974609f, 0.990723f, 0.991699f, 0.992188f, 0.992188f, 0.992188f, 0.992188f, 0.000000f, 0.000238f, 0.000240f, 0.000362f,
+ 0.000362f, 0.000521f, 0.000631f, 0.000909f, 0.000937f, 0.001249f, 0.001373f, 0.001693f, 0.001746f, 0.002184f, 0.002436f, 0.002680f,
+ 0.003094f, 0.003576f, 0.003828f, 0.004463f, 0.004990f, 0.005589f, 0.006439f, 0.006943f, 0.008217f, 0.009384f, 0.010719f, 0.012184f,
+ 0.014130f, 0.016373f, 0.019241f, 0.022675f, 0.027161f, 0.032379f, 0.039307f, 0.048645f, 0.060455f, 0.076416f, 0.097778f, 0.127441f,
+ 0.168213f, 0.223633f, 0.296387f, 0.385986f, 0.485107f, 0.583984f, 0.673340f, 0.746582f, 0.804199f, 0.848633f, 0.880371f, 0.905273f,
+ 0.923828f, 0.938477f, 0.949707f, 0.958984f, 0.965820f, 0.972656f, 0.990234f, 0.991211f, 0.991211f, 0.991211f, 0.991211f, 0.991211f,
+ 0.000000f, 0.000234f, 0.000238f, 0.000236f, 0.000360f, 0.000482f, 0.000614f, 0.000786f, 0.000900f, 0.001056f, 0.001336f, 0.001466f,
+ 0.001671f, 0.001907f, 0.002333f, 0.002546f, 0.002871f, 0.003067f, 0.003500f, 0.003813f, 0.004425f, 0.004574f, 0.005459f, 0.006092f,
+ 0.006660f, 0.007660f, 0.008987f, 0.010071f, 0.011841f, 0.013847f, 0.016022f, 0.018829f, 0.022339f, 0.026779f, 0.031677f, 0.038910f,
+ 0.047913f, 0.059601f, 0.075684f, 0.097290f, 0.127319f, 0.169189f, 0.226807f, 0.302490f, 0.394775f, 0.497314f, 0.598633f, 0.686523f,
+ 0.759766f, 0.814941f, 0.857422f, 0.888672f, 0.912109f, 0.930176f, 0.943359f, 0.954102f, 0.962402f, 0.968750f, 0.988770f, 0.990234f,
+ 0.990234f, 0.990234f, 0.991211f, 0.990723f, 0.000000f, 0.000036f, 0.000166f, 0.000357f, 0.000356f, 0.000478f, 0.000566f, 0.000638f,
+ 0.000893f, 0.001146f, 0.001242f, 0.001330f, 0.001502f, 0.001773f, 0.001918f, 0.002024f, 0.002501f, 0.002604f, 0.003067f, 0.003334f,
+ 0.003708f, 0.004044f, 0.004646f, 0.005268f, 0.006241f, 0.006931f, 0.007774f, 0.008911f, 0.010277f, 0.011475f, 0.013542f, 0.015732f,
+ 0.018417f, 0.022049f, 0.026154f, 0.031189f, 0.038269f, 0.047119f, 0.059265f, 0.075256f, 0.097534f, 0.128906f, 0.172119f, 0.231934f,
+ 0.311035f, 0.407715f, 0.513184f, 0.615723f, 0.703613f, 0.773926f, 0.827637f, 0.867188f, 0.897461f, 0.919434f, 0.936035f, 0.948730f,
+ 0.958984f, 0.966309f, 0.988770f, 0.989746f, 0.989746f, 0.990234f, 0.989746f, 0.989746f, 0.000000f, 0.000028f, 0.000093f, 0.000334f,
+ 0.000465f, 0.000472f, 0.000373f, 0.000685f, 0.000695f, 0.001027f, 0.001128f, 0.001155f, 0.001419f, 0.001435f, 0.001760f, 0.001850f,
+ 0.002241f, 0.002373f, 0.002604f, 0.002821f, 0.003334f, 0.003666f, 0.004139f, 0.004627f, 0.005207f, 0.005886f, 0.006596f, 0.007580f,
+ 0.008705f, 0.009911f, 0.011520f, 0.013237f, 0.015427f, 0.017944f, 0.021423f, 0.025497f, 0.030945f, 0.037537f, 0.046692f, 0.058624f,
+ 0.075317f, 0.098267f, 0.130493f, 0.176025f, 0.239136f, 0.323242f, 0.424561f, 0.533691f, 0.636230f, 0.723145f, 0.790039f, 0.841797f,
+ 0.880371f, 0.906738f, 0.926758f, 0.941406f, 0.953613f, 0.963379f, 0.987793f, 0.988770f, 0.988770f, 0.989258f, 0.989258f, 0.989258f,
+ 0.000000f, 0.000000f, 0.000047f, 0.000321f, 0.000332f, 0.000351f, 0.000470f, 0.000596f, 0.000655f, 0.000727f, 0.001008f, 0.001112f,
+ 0.001350f, 0.001379f, 0.001380f, 0.001751f, 0.002008f, 0.002151f, 0.002327f, 0.002548f, 0.002691f, 0.003056f, 0.003475f, 0.003925f,
+ 0.004749f, 0.005161f, 0.005863f, 0.006538f, 0.007153f, 0.008453f, 0.009789f, 0.010986f, 0.013168f, 0.015121f, 0.017563f, 0.020966f,
+ 0.025009f, 0.030151f, 0.037048f, 0.046570f, 0.058624f, 0.075623f, 0.099243f, 0.133667f, 0.181641f, 0.249756f, 0.338623f, 0.445312f,
+ 0.556641f, 0.659180f, 0.744141f, 0.808594f, 0.855957f, 0.890137f, 0.916992f, 0.934570f, 0.949219f, 0.959473f, 0.986816f, 0.987793f,
+ 0.987793f, 0.987793f, 0.987793f, 0.988281f, 0.000000f, 0.000000f, 0.000000f, 0.000244f, 0.000429f, 0.000440f, 0.000348f, 0.000592f,
+ 0.000606f, 0.000755f, 0.000690f, 0.000935f, 0.001172f, 0.001257f, 0.001368f, 0.001458f, 0.001786f, 0.001809f, 0.002060f, 0.002274f,
+ 0.002478f, 0.002642f, 0.002987f, 0.003435f, 0.003866f, 0.004337f, 0.005066f, 0.005409f, 0.006355f, 0.007111f, 0.008011f, 0.009392f,
+ 0.011032f, 0.012321f, 0.014717f, 0.017319f, 0.020432f, 0.024551f, 0.029953f, 0.036835f, 0.045929f, 0.058716f, 0.076416f, 0.101562f,
+ 0.137695f, 0.189453f, 0.262451f, 0.358154f, 0.470215f, 0.584961f, 0.686523f, 0.767578f, 0.828125f, 0.871582f, 0.903809f, 0.926270f,
+ 0.941895f, 0.956055f, 0.985352f, 0.986328f, 0.986816f, 0.986816f, 0.986816f, 0.986816f, 0.000000f, 0.000000f, 0.000000f, 0.000119f,
+ 0.000237f, 0.000314f, 0.000570f, 0.000575f, 0.000583f, 0.000632f, 0.000651f, 0.000789f, 0.000947f, 0.001097f, 0.001300f, 0.001320f,
+ 0.001384f, 0.001443f, 0.001641f, 0.001869f, 0.002047f, 0.002396f, 0.002634f, 0.003025f, 0.003412f, 0.003757f, 0.004238f, 0.004620f,
+ 0.005463f, 0.006168f, 0.007072f, 0.008080f, 0.009155f, 0.010590f, 0.012306f, 0.014175f, 0.016769f, 0.020081f, 0.023972f, 0.029495f,
+ 0.036560f, 0.045959f, 0.059265f, 0.078125f, 0.104797f, 0.143677f, 0.199951f, 0.279785f, 0.382812f, 0.500977f, 0.616699f, 0.716309f,
+ 0.791992f, 0.847168f, 0.887207f, 0.915527f, 0.936523f, 0.950684f, 0.984375f, 0.985352f, 0.986328f, 0.985840f, 0.986328f, 0.985840f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000205f, 0.000239f, 0.000299f, 0.000537f, 0.000574f, 0.000696f, 0.000583f, 0.000740f,
+ 0.000778f, 0.000867f, 0.001013f, 0.001257f, 0.001325f, 0.001277f, 0.001416f, 0.001718f, 0.001965f, 0.002079f, 0.002356f, 0.002577f,
+ 0.002771f, 0.003305f, 0.003693f, 0.004028f, 0.004593f, 0.005234f, 0.005905f, 0.006802f, 0.007698f, 0.008553f, 0.009995f, 0.011635f,
+ 0.013824f, 0.016174f, 0.019547f, 0.023544f, 0.029114f, 0.036377f, 0.046417f, 0.060211f, 0.080017f, 0.108643f, 0.151611f, 0.213379f,
+ 0.301758f, 0.414062f, 0.537598f, 0.653320f, 0.748047f, 0.817871f, 0.868164f, 0.903320f, 0.928711f, 0.945801f, 0.982910f, 0.983887f,
+ 0.984375f, 0.984375f, 0.984863f, 0.984375f, 0.000000f, 0.000000f, 0.000045f, 0.000105f, 0.000114f, 0.000340f, 0.000371f, 0.000501f,
+ 0.000639f, 0.000554f, 0.000687f, 0.000675f, 0.000711f, 0.000738f, 0.000824f, 0.001092f, 0.001040f, 0.001185f, 0.001212f, 0.001408f,
+ 0.001624f, 0.001813f, 0.001982f, 0.002182f, 0.002634f, 0.002748f, 0.003252f, 0.003540f, 0.004089f, 0.004505f, 0.005001f, 0.005657f,
+ 0.006500f, 0.007195f, 0.008286f, 0.009750f, 0.011208f, 0.013420f, 0.015762f, 0.019226f, 0.023209f, 0.029144f, 0.036591f, 0.047150f,
+ 0.061615f, 0.082947f, 0.114014f, 0.161621f, 0.231323f, 0.329834f, 0.451416f, 0.579590f, 0.692871f, 0.780273f, 0.844238f, 0.888184f,
+ 0.917969f, 0.939453f, 0.981445f, 0.982422f, 0.982910f, 0.982910f, 0.982910f, 0.982910f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000208f, 0.000311f, 0.000238f, 0.000337f, 0.000524f, 0.000617f, 0.000533f, 0.000675f, 0.000665f, 0.000776f, 0.000840f, 0.000819f,
+ 0.000902f, 0.001169f, 0.001130f, 0.001178f, 0.001382f, 0.001571f, 0.001941f, 0.001932f, 0.002138f, 0.002306f, 0.002586f, 0.002937f,
+ 0.003468f, 0.003740f, 0.004292f, 0.004704f, 0.005444f, 0.006081f, 0.007019f, 0.008255f, 0.009521f, 0.010796f, 0.012840f, 0.015503f,
+ 0.018784f, 0.023178f, 0.029129f, 0.036774f, 0.047699f, 0.063416f, 0.086548f, 0.121399f, 0.175293f, 0.254883f, 0.365234f, 0.496582f,
+ 0.626953f, 0.733398f, 0.813477f, 0.869629f, 0.906738f, 0.933105f, 0.979980f, 0.980957f, 0.981445f, 0.981445f, 0.980957f, 0.981445f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000208f, 0.000312f, 0.000236f, 0.000343f, 0.000475f, 0.000496f, 0.000528f,
+ 0.000659f, 0.000582f, 0.000685f, 0.000710f, 0.000761f, 0.000784f, 0.000941f, 0.001013f, 0.001117f, 0.001339f, 0.001500f, 0.001623f,
+ 0.001769f, 0.002039f, 0.002298f, 0.002565f, 0.002802f, 0.003119f, 0.003471f, 0.003857f, 0.004658f, 0.005177f, 0.005836f, 0.006752f,
+ 0.007324f, 0.008911f, 0.010422f, 0.012527f, 0.015373f, 0.018585f, 0.022964f, 0.029037f, 0.037231f, 0.049072f, 0.066345f, 0.091492f,
+ 0.131470f, 0.193359f, 0.285645f, 0.409912f, 0.548828f, 0.676758f, 0.776367f, 0.845703f, 0.893066f, 0.924805f, 0.978027f, 0.979492f,
+ 0.979492f, 0.979004f, 0.979492f, 0.979492f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000166f, 0.000228f, 0.000227f,
+ 0.000369f, 0.000337f, 0.000368f, 0.000452f, 0.000500f, 0.000547f, 0.000543f, 0.000575f, 0.000623f, 0.000723f, 0.000783f, 0.000874f,
+ 0.001141f, 0.001226f, 0.001279f, 0.001336f, 0.001499f, 0.001655f, 0.001922f, 0.002090f, 0.002453f, 0.002298f, 0.003139f, 0.003181f,
+ 0.003674f, 0.004166f, 0.004814f, 0.005447f, 0.006348f, 0.007179f, 0.008736f, 0.010406f, 0.012321f, 0.014984f, 0.018219f, 0.022934f,
+ 0.028824f, 0.037598f, 0.050476f, 0.069397f, 0.098694f, 0.144775f, 0.218018f, 0.325439f, 0.464111f, 0.607910f, 0.729492f, 0.817383f,
+ 0.876953f, 0.915527f, 0.976562f, 0.977539f, 0.977539f, 0.977051f, 0.977051f, 0.977539f, 0.000000f, 0.000000f, 0.000000f, 0.000122f,
+ 0.000122f, 0.000122f, 0.000154f, 0.000200f, 0.000267f, 0.000316f, 0.000324f, 0.000449f, 0.000319f, 0.000379f, 0.000515f, 0.000519f,
+ 0.000558f, 0.000628f, 0.000645f, 0.000690f, 0.000777f, 0.000940f, 0.001096f, 0.001204f, 0.001278f, 0.001485f, 0.001670f, 0.001929f,
+ 0.001961f, 0.002016f, 0.002367f, 0.002785f, 0.003025f, 0.003248f, 0.003805f, 0.004539f, 0.004845f, 0.005733f, 0.006851f, 0.008278f,
+ 0.010017f, 0.011841f, 0.014542f, 0.017807f, 0.022705f, 0.029190f, 0.038544f, 0.052612f, 0.073853f, 0.108093f, 0.162842f, 0.250977f,
+ 0.377930f, 0.529785f, 0.672363f, 0.782715f, 0.855957f, 0.904297f, 0.973145f, 0.974121f, 0.974609f, 0.975586f, 0.974609f, 0.975098f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000158f, 0.000121f, 0.000190f, 0.000238f, 0.000397f, 0.000354f,
+ 0.000364f, 0.000365f, 0.000440f, 0.000474f, 0.000509f, 0.000612f, 0.000611f, 0.000648f, 0.000804f, 0.000755f, 0.000943f, 0.001050f,
+ 0.001221f, 0.001340f, 0.001338f, 0.001443f, 0.001635f, 0.001822f, 0.002083f, 0.002226f, 0.002480f, 0.002682f, 0.003185f, 0.003609f,
+ 0.003948f, 0.005074f, 0.005558f, 0.006741f, 0.007904f, 0.009384f, 0.011360f, 0.014000f, 0.017883f, 0.022675f, 0.029648f, 0.039917f,
+ 0.055695f, 0.080261f, 0.120728f, 0.188354f, 0.296143f, 0.443848f, 0.603027f, 0.737793f, 0.831055f, 0.891113f, 0.970703f, 0.971680f,
+ 0.972168f, 0.972656f, 0.971680f, 0.972168f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000251f, 0.000260f, 0.000278f, 0.000315f, 0.000334f, 0.000235f, 0.000357f, 0.000442f, 0.000513f, 0.000504f, 0.000598f,
+ 0.000556f, 0.000771f, 0.000831f, 0.000886f, 0.000977f, 0.001145f, 0.001105f, 0.001244f, 0.001281f, 0.001431f, 0.001544f, 0.001850f,
+ 0.001986f, 0.002131f, 0.002537f, 0.002737f, 0.003252f, 0.003826f, 0.004555f, 0.005184f, 0.006199f, 0.007195f, 0.009041f, 0.011337f,
+ 0.013878f, 0.017395f, 0.022552f, 0.030502f, 0.041962f, 0.059875f, 0.089111f, 0.139404f, 0.224609f, 0.357910f, 0.524902f, 0.684082f,
+ 0.800781f, 0.875977f, 0.967773f, 0.968750f, 0.968262f, 0.968750f, 0.969238f, 0.969238f, 0.000000f, 0.000000f, 0.000122f, 0.000122f,
+ 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000095f, 0.000081f, 0.000217f, 0.000149f, 0.000204f, 0.000212f, 0.000338f,
+ 0.000345f, 0.000348f, 0.000456f, 0.000463f, 0.000495f, 0.000570f, 0.000583f, 0.000748f, 0.000799f, 0.000731f, 0.000965f, 0.001041f,
+ 0.001071f, 0.001210f, 0.001318f, 0.001238f, 0.001410f, 0.001631f, 0.001932f, 0.002327f, 0.002577f, 0.003057f, 0.003452f, 0.003956f,
+ 0.004639f, 0.005714f, 0.006817f, 0.008446f, 0.010605f, 0.013443f, 0.017319f, 0.022964f, 0.031021f, 0.044281f, 0.065857f, 0.102112f,
+ 0.166504f, 0.277344f, 0.439941f, 0.617188f, 0.762207f, 0.856445f, 0.963379f, 0.964355f, 0.965332f, 0.964844f, 0.965332f, 0.965332f,
+ 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000107f, 0.000091f, 0.000161f,
+ 0.000119f, 0.000184f, 0.000266f, 0.000284f, 0.000314f, 0.000319f, 0.000334f, 0.000344f, 0.000565f, 0.000455f, 0.000488f, 0.000667f,
+ 0.000710f, 0.000713f, 0.000787f, 0.000755f, 0.000849f, 0.000972f, 0.001097f, 0.001286f, 0.001427f, 0.001556f, 0.001667f, 0.001687f,
+ 0.002155f, 0.002369f, 0.002674f, 0.003086f, 0.003710f, 0.004536f, 0.005585f, 0.006783f, 0.007957f, 0.010262f, 0.013115f, 0.017212f,
+ 0.023102f, 0.032715f, 0.047943f, 0.074158f, 0.121155f, 0.207520f, 0.353027f, 0.541504f, 0.715332f, 0.834473f, 0.959473f, 0.960449f,
+ 0.960938f, 0.960938f, 0.960938f, 0.961426f, 0.000000f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f,
+ 0.000120f, 0.000120f, 0.000103f, 0.000089f, 0.000077f, 0.000080f, 0.000121f, 0.000218f, 0.000209f, 0.000245f, 0.000303f, 0.000316f,
+ 0.000388f, 0.000341f, 0.000549f, 0.000594f, 0.000604f, 0.000679f, 0.000625f, 0.000628f, 0.000795f, 0.000883f, 0.000857f, 0.000991f,
+ 0.001166f, 0.000955f, 0.001194f, 0.001347f, 0.001548f, 0.001804f, 0.002048f, 0.002388f, 0.002911f, 0.003130f, 0.003933f, 0.004845f,
+ 0.006031f, 0.007385f, 0.009705f, 0.012688f, 0.017044f, 0.023788f, 0.034882f, 0.053284f, 0.086670f, 0.151123f, 0.271484f, 0.457031f,
+ 0.658203f, 0.805176f, 0.954102f, 0.955078f, 0.956055f, 0.956055f, 0.956055f, 0.955566f, 0.000000f, 0.000122f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000116f, 0.000101f, 0.000088f, 0.000077f, 0.000131f, 0.000071f,
+ 0.000146f, 0.000200f, 0.000237f, 0.000270f, 0.000289f, 0.000302f, 0.000311f, 0.000441f, 0.000396f, 0.000588f, 0.000630f, 0.000570f,
+ 0.000575f, 0.000537f, 0.000589f, 0.000750f, 0.000721f, 0.001048f, 0.001122f, 0.000951f, 0.001243f, 0.001346f, 0.001703f, 0.001592f,
+ 0.001880f, 0.002340f, 0.002804f, 0.003637f, 0.004356f, 0.005329f, 0.006805f, 0.009094f, 0.012566f, 0.017181f, 0.025040f, 0.038147f,
+ 0.061249f, 0.107788f, 0.200195f, 0.369629f, 0.587891f, 0.771973f, 0.948242f, 0.949707f, 0.950195f, 0.949707f, 0.950195f, 0.950195f,
+ 0.000000f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000119f, 0.000119f, 0.000114f,
+ 0.000101f, 0.000088f, 0.000079f, 0.000070f, 0.000063f, 0.000136f, 0.000136f, 0.000183f, 0.000207f, 0.000277f, 0.000271f, 0.000291f,
+ 0.000369f, 0.000344f, 0.000494f, 0.000459f, 0.000515f, 0.000509f, 0.000532f, 0.000504f, 0.000716f, 0.000589f, 0.000691f, 0.000902f,
+ 0.000972f, 0.000968f, 0.001067f, 0.001483f, 0.001780f, 0.001652f, 0.002090f, 0.002602f, 0.003113f, 0.003738f, 0.004738f, 0.006420f,
+ 0.008522f, 0.012100f, 0.017334f, 0.026489f, 0.042786f, 0.074524f, 0.142578f, 0.283936f, 0.509277f, 0.729492f, 0.940918f, 0.941895f,
+ 0.942383f, 0.942383f, 0.942383f, 0.942871f, 0.000122f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000119f, 0.000119f,
+ 0.000119f, 0.000118f, 0.000118f, 0.000118f, 0.000116f, 0.000102f, 0.000090f, 0.000081f, 0.000091f, 0.000066f, 0.000059f, 0.000110f,
+ 0.000109f, 0.000155f, 0.000184f, 0.000227f, 0.000297f, 0.000333f, 0.000355f, 0.000349f, 0.000344f, 0.000421f, 0.000459f, 0.000561f,
+ 0.000600f, 0.000563f, 0.000630f, 0.000563f, 0.000682f, 0.000737f, 0.000892f, 0.001037f, 0.001026f, 0.001163f, 0.001743f, 0.001782f,
+ 0.002117f, 0.002573f, 0.003389f, 0.004429f, 0.005871f, 0.007942f, 0.011841f, 0.018066f, 0.029190f, 0.050842f, 0.098511f, 0.207397f,
+ 0.422363f, 0.677734f, 0.932129f, 0.933594f, 0.933594f, 0.934082f, 0.934082f, 0.934082f, 0.000000f, 0.000121f, 0.000120f, 0.000119f,
+ 0.000119f, 0.000119f, 0.000118f, 0.000118f, 0.000118f, 0.000117f, 0.000117f, 0.000117f, 0.000117f, 0.000116f, 0.000104f, 0.000093f,
+ 0.000084f, 0.000076f, 0.000069f, 0.000091f, 0.000057f, 0.000051f, 0.000112f, 0.000120f, 0.000179f, 0.000232f, 0.000225f, 0.000283f,
+ 0.000301f, 0.000308f, 0.000353f, 0.000437f, 0.000395f, 0.000523f, 0.000486f, 0.000504f, 0.000469f, 0.000614f, 0.000581f, 0.000755f,
+ 0.000789f, 0.001121f, 0.000981f, 0.001218f, 0.001565f, 0.001795f, 0.002296f, 0.002958f, 0.003866f, 0.005329f, 0.007675f, 0.011658f,
+ 0.019043f, 0.033478f, 0.065430f, 0.144043f, 0.331299f, 0.613770f, 0.921387f, 0.922852f, 0.923340f, 0.923340f, 0.923340f, 0.923340f,
+ 0.000000f, 0.000000f, 0.000119f, 0.000118f, 0.000118f, 0.000117f, 0.000116f, 0.000116f, 0.000116f, 0.000116f, 0.000115f, 0.000115f,
+ 0.000115f, 0.000115f, 0.000114f, 0.000108f, 0.000097f, 0.000087f, 0.000079f, 0.000072f, 0.000065f, 0.000060f, 0.000094f, 0.000050f,
+ 0.000104f, 0.000104f, 0.000121f, 0.000164f, 0.000195f, 0.000247f, 0.000265f, 0.000328f, 0.000290f, 0.000355f, 0.000395f, 0.000356f,
+ 0.000361f, 0.000459f, 0.000470f, 0.000515f, 0.000580f, 0.000624f, 0.000751f, 0.000964f, 0.001105f, 0.001279f, 0.001413f, 0.001823f,
+ 0.002441f, 0.003407f, 0.004852f, 0.007210f, 0.011803f, 0.021225f, 0.041473f, 0.095032f, 0.244019f, 0.537598f, 0.907715f, 0.910156f,
+ 0.910156f, 0.909180f, 0.909668f, 0.911133f, 0.000120f, 0.000118f, 0.000117f, 0.000116f, 0.000114f, 0.000114f, 0.000114f, 0.000113f,
+ 0.000113f, 0.000112f, 0.000112f, 0.000112f, 0.000111f, 0.000112f, 0.000111f, 0.000111f, 0.000111f, 0.000101f, 0.000093f, 0.000084f,
+ 0.000077f, 0.000070f, 0.000064f, 0.000059f, 0.000074f, 0.000079f, 0.000059f, 0.000087f, 0.000097f, 0.000128f, 0.000185f, 0.000213f,
+ 0.000265f, 0.000235f, 0.000239f, 0.000288f, 0.000299f, 0.000371f, 0.000341f, 0.000369f, 0.000460f, 0.000446f, 0.000490f, 0.000602f,
+ 0.000694f, 0.000904f, 0.001012f, 0.001234f, 0.001544f, 0.002096f, 0.002989f, 0.004299f, 0.006840f, 0.012383f, 0.024948f, 0.059204f,
+ 0.166626f, 0.452637f, 0.892578f, 0.894043f, 0.894043f, 0.894531f, 0.894531f, 0.894043f, 0.000115f, 0.000107f, 0.000108f, 0.000111f,
+ 0.000108f, 0.000109f, 0.000108f, 0.000108f, 0.000108f, 0.000107f, 0.000108f, 0.000107f, 0.000107f, 0.000106f, 0.000107f, 0.000107f,
+ 0.000106f, 0.000107f, 0.000106f, 0.000097f, 0.000090f, 0.000082f, 0.000075f, 0.000069f, 0.000063f, 0.000058f, 0.000053f, 0.000070f,
+ 0.000073f, 0.000085f, 0.000077f, 0.000088f, 0.000136f, 0.000168f, 0.000190f, 0.000204f, 0.000199f, 0.000252f, 0.000233f, 0.000270f,
+ 0.000325f, 0.000295f, 0.000348f, 0.000383f, 0.000435f, 0.000534f, 0.000581f, 0.000803f, 0.001004f, 0.001330f, 0.001812f, 0.002489f,
+ 0.003944f, 0.006832f, 0.013748f, 0.033997f, 0.104858f, 0.356689f, 0.873047f, 0.873047f, 0.875000f, 0.874023f, 0.874023f, 0.874023f,
+ 0.000000f, 0.000071f, 0.000063f, 0.000094f, 0.000092f, 0.000094f, 0.000093f, 0.000098f, 0.000098f, 0.000098f, 0.000098f, 0.000099f,
+ 0.000098f, 0.000099f, 0.000099f, 0.000099f, 0.000099f, 0.000099f, 0.000099f, 0.000100f, 0.000100f, 0.000094f, 0.000087f, 0.000080f,
+ 0.000074f, 0.000068f, 0.000062f, 0.000058f, 0.000053f, 0.000049f, 0.000059f, 0.000059f, 0.000045f, 0.000078f, 0.000082f, 0.000118f,
+ 0.000155f, 0.000160f, 0.000174f, 0.000180f, 0.000226f, 0.000213f, 0.000248f, 0.000258f, 0.000288f, 0.000352f, 0.000396f, 0.000465f,
+ 0.000566f, 0.000789f, 0.000941f, 0.001343f, 0.002199f, 0.003616f, 0.006912f, 0.017380f, 0.058960f, 0.259521f, 0.847656f, 0.849121f,
+ 0.850586f, 0.850098f, 0.849121f, 0.850586f, 0.000000f, 0.000000f, 0.000019f, 0.000044f, 0.000048f, 0.000061f, 0.000071f, 0.000073f,
+ 0.000076f, 0.000079f, 0.000079f, 0.000082f, 0.000082f, 0.000082f, 0.000085f, 0.000086f, 0.000087f, 0.000086f, 0.000088f, 0.000087f,
+ 0.000089f, 0.000089f, 0.000089f, 0.000090f, 0.000084f, 0.000078f, 0.000072f, 0.000067f, 0.000062f, 0.000057f, 0.000052f, 0.000049f,
+ 0.000045f, 0.000041f, 0.000038f, 0.000040f, 0.000062f, 0.000092f, 0.000100f, 0.000121f, 0.000144f, 0.000133f, 0.000137f, 0.000170f,
+ 0.000181f, 0.000168f, 0.000215f, 0.000286f, 0.000327f, 0.000397f, 0.000504f, 0.000738f, 0.001039f, 0.001729f, 0.003317f, 0.007721f,
+ 0.028458f, 0.166626f, 0.815430f, 0.818359f, 0.818359f, 0.817383f, 0.818848f, 0.818359f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000008f, 0.000016f, 0.000031f, 0.000035f, 0.000048f, 0.000050f, 0.000053f, 0.000058f, 0.000059f,
+ 0.000063f, 0.000064f, 0.000067f, 0.000067f, 0.000070f, 0.000071f, 0.000072f, 0.000073f, 0.000075f, 0.000075f, 0.000076f, 0.000075f,
+ 0.000069f, 0.000064f, 0.000060f, 0.000055f, 0.000051f, 0.000047f, 0.000043f, 0.000040f, 0.000037f, 0.000034f, 0.000040f, 0.000041f,
+ 0.000054f, 0.000069f, 0.000096f, 0.000111f, 0.000109f, 0.000113f, 0.000142f, 0.000136f, 0.000158f, 0.000196f, 0.000237f, 0.000349f,
+ 0.000423f, 0.000744f, 0.001380f, 0.003214f, 0.011124f, 0.088135f, 0.777344f, 0.779297f, 0.780273f, 0.779785f, 0.779785f, 0.779785f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000003f, 0.000007f, 0.000021f, 0.000023f, 0.000031f, 0.000034f, 0.000038f, 0.000041f, 0.000043f, 0.000047f,
+ 0.000049f, 0.000050f, 0.000053f, 0.000055f, 0.000056f, 0.000057f, 0.000059f, 0.000060f, 0.000055f, 0.000051f, 0.000048f, 0.000044f,
+ 0.000041f, 0.000038f, 0.000035f, 0.000032f, 0.000029f, 0.000028f, 0.000028f, 0.000037f, 0.000044f, 0.000064f, 0.000078f, 0.000072f,
+ 0.000089f, 0.000098f, 0.000104f, 0.000146f, 0.000200f, 0.000272f, 0.000479f, 0.001077f, 0.003733f, 0.033752f, 0.729492f, 0.730957f,
+ 0.732422f, 0.731934f, 0.732422f, 0.732422f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000002f, 0.000006f, 0.000009f, 0.000013f, 0.000019f, 0.000021f, 0.000025f, 0.000027f, 0.000030f,
+ 0.000033f, 0.000034f, 0.000037f, 0.000039f, 0.000041f, 0.000039f, 0.000036f, 0.000033f, 0.000031f, 0.000028f, 0.000026f, 0.000024f,
+ 0.000021f, 0.000019f, 0.000017f, 0.000023f, 0.000033f, 0.000041f, 0.000043f, 0.000058f, 0.000061f, 0.000081f, 0.000121f, 0.000248f,
+ 0.000821f, 0.008255f, 0.673340f, 0.674805f, 0.674316f, 0.674805f, 0.674805f, 0.673828f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000006f, 0.000010f, 0.000013f,
+ 0.000015f, 0.000017f, 0.000020f, 0.000022f, 0.000021f, 0.000019f, 0.000017f, 0.000015f, 0.000013f, 0.000012f, 0.000010f, 0.000011f,
+ 0.000016f, 0.000019f, 0.000019f, 0.000036f, 0.000090f, 0.000897f, 0.606934f, 0.609863f, 0.609375f, 0.609863f, 0.609863f, 0.610352f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000001f, 0.000003f, 0.000006f, 0.000005f, 0.000004f, 0.000003f, 0.000004f, 0.000008f, 0.534668f, 0.536621f,
+ 0.537109f, 0.537109f, 0.536621f, 0.536621f,
+ },
+ {
+ 0.149292f, 0.432373f, 0.614258f, 0.719238f, 0.784180f, 0.826660f, 0.856934f, 0.879883f, 0.896484f, 0.909180f, 0.919922f, 0.928711f,
+ 0.936035f, 0.942383f, 0.947266f, 0.952148f, 0.956055f, 0.959473f, 0.962891f, 0.965820f, 0.968262f, 0.970703f, 0.972656f, 0.974609f,
+ 0.976562f, 0.978027f, 0.979492f, 0.980469f, 0.981934f, 0.983398f, 0.984863f, 0.985352f, 0.986328f, 0.987305f, 0.988281f, 0.989258f,
+ 0.989746f, 0.990234f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.996094f,
+ 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999512f, 0.999512f, 0.999512f, 0.999023f, 0.040161f, 0.161255f, 0.324951f, 0.486572f, 0.612305f, 0.704590f, 0.767090f, 0.811523f,
+ 0.844238f, 0.868652f, 0.887695f, 0.902344f, 0.913574f, 0.924316f, 0.932129f, 0.937988f, 0.944336f, 0.949707f, 0.954102f, 0.957520f,
+ 0.960938f, 0.964355f, 0.966797f, 0.969727f, 0.971191f, 0.973633f, 0.975586f, 0.977539f, 0.979004f, 0.980469f, 0.981445f, 0.982910f,
+ 0.983887f, 0.985352f, 0.985840f, 0.987305f, 0.987793f, 0.988770f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.992676f, 0.993164f,
+ 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f,
+ 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999023f, 0.017395f, 0.068542f, 0.149292f, 0.262451f,
+ 0.392822f, 0.518066f, 0.621582f, 0.700195f, 0.759766f, 0.803711f, 0.836426f, 0.862305f, 0.880859f, 0.896484f, 0.909668f, 0.919434f,
+ 0.929199f, 0.935547f, 0.941895f, 0.947754f, 0.952637f, 0.956055f, 0.959961f, 0.963867f, 0.965820f, 0.968750f, 0.970703f, 0.973145f,
+ 0.975098f, 0.977051f, 0.979004f, 0.979980f, 0.981934f, 0.983398f, 0.983887f, 0.984863f, 0.985840f, 0.986816f, 0.987793f, 0.989258f,
+ 0.989746f, 0.990234f, 0.991211f, 0.991699f, 0.992188f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995605f, 0.996094f, 0.996094f,
+ 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999023f,
+ 0.009125f, 0.035492f, 0.075806f, 0.135864f, 0.219971f, 0.324707f, 0.437012f, 0.543457f, 0.633789f, 0.704102f, 0.758789f, 0.802246f,
+ 0.833496f, 0.857910f, 0.878418f, 0.894043f, 0.906738f, 0.917480f, 0.925781f, 0.933594f, 0.940918f, 0.946777f, 0.951172f, 0.954590f,
+ 0.959473f, 0.962891f, 0.965820f, 0.968262f, 0.971191f, 0.973145f, 0.975098f, 0.976562f, 0.978516f, 0.979980f, 0.981445f, 0.982422f,
+ 0.983887f, 0.985840f, 0.986328f, 0.987305f, 0.988281f, 0.988770f, 0.989746f, 0.990234f, 0.991699f, 0.992188f, 0.992676f, 0.993652f,
+ 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.005848f, 0.021225f, 0.043640f, 0.076782f, 0.124084f, 0.189575f, 0.274414f, 0.372559f,
+ 0.473633f, 0.567383f, 0.646973f, 0.711426f, 0.761230f, 0.801758f, 0.833496f, 0.857422f, 0.876953f, 0.893066f, 0.905273f, 0.916504f,
+ 0.925293f, 0.932617f, 0.939941f, 0.945801f, 0.950684f, 0.955566f, 0.958984f, 0.962402f, 0.965820f, 0.968262f, 0.970703f, 0.972656f,
+ 0.975098f, 0.977051f, 0.978516f, 0.980469f, 0.981934f, 0.982422f, 0.983887f, 0.985840f, 0.986328f, 0.987305f, 0.988281f, 0.989258f,
+ 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.996094f, 0.996094f, 0.997070f,
+ 0.997559f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.998535f, 0.998535f, 0.003937f, 0.014107f, 0.027664f, 0.047211f,
+ 0.075195f, 0.113953f, 0.166748f, 0.236328f, 0.320312f, 0.412354f, 0.504395f, 0.589844f, 0.661621f, 0.719727f, 0.768066f, 0.805664f,
+ 0.834961f, 0.858398f, 0.877441f, 0.893066f, 0.906738f, 0.916992f, 0.926270f, 0.933105f, 0.940430f, 0.946289f, 0.951172f, 0.955566f,
+ 0.959473f, 0.962891f, 0.965820f, 0.968262f, 0.970703f, 0.973145f, 0.975098f, 0.977051f, 0.979004f, 0.980469f, 0.981934f, 0.983398f,
+ 0.984375f, 0.985840f, 0.986328f, 0.987305f, 0.988770f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.992676f, 0.993652f, 0.994629f,
+ 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996582f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.998535f, 0.998535f,
+ 0.002962f, 0.009674f, 0.019348f, 0.031708f, 0.049255f, 0.072754f, 0.105164f, 0.149048f, 0.206665f, 0.278076f, 0.361572f, 0.448730f,
+ 0.534668f, 0.611816f, 0.677734f, 0.730957f, 0.775879f, 0.809570f, 0.837891f, 0.861328f, 0.879395f, 0.894531f, 0.907227f, 0.916992f,
+ 0.926270f, 0.934082f, 0.940918f, 0.946289f, 0.951172f, 0.956055f, 0.959473f, 0.962891f, 0.966797f, 0.969238f, 0.971191f, 0.973633f,
+ 0.976074f, 0.977539f, 0.979492f, 0.980957f, 0.982422f, 0.983398f, 0.984863f, 0.986328f, 0.986816f, 0.988281f, 0.989746f, 0.989746f,
+ 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.994629f, 0.995605f, 0.996094f, 0.997070f, 0.998535f, 0.999023f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.001900f, 0.007225f, 0.013733f, 0.022552f, 0.033661f, 0.049164f, 0.070374f, 0.097534f,
+ 0.135132f, 0.183350f, 0.244507f, 0.317871f, 0.400146f, 0.483643f, 0.562988f, 0.633301f, 0.693848f, 0.743652f, 0.784180f, 0.816895f,
+ 0.842773f, 0.865234f, 0.882812f, 0.896973f, 0.908691f, 0.919434f, 0.927734f, 0.935547f, 0.942383f, 0.947266f, 0.952637f, 0.957031f,
+ 0.960938f, 0.964355f, 0.967285f, 0.969727f, 0.971680f, 0.974609f, 0.976074f, 0.978027f, 0.979980f, 0.981445f, 0.982910f, 0.984375f,
+ 0.985840f, 0.986328f, 0.988281f, 0.988770f, 0.989746f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.995117f,
+ 0.995605f, 0.996094f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998047f, 0.001921f, 0.005543f, 0.010223f, 0.016312f,
+ 0.024918f, 0.035217f, 0.049164f, 0.067017f, 0.091125f, 0.122986f, 0.164673f, 0.217896f, 0.282471f, 0.356934f, 0.436768f, 0.516602f,
+ 0.590820f, 0.656250f, 0.711426f, 0.757812f, 0.794922f, 0.825684f, 0.850098f, 0.870605f, 0.885742f, 0.900879f, 0.912109f, 0.921387f,
+ 0.929688f, 0.937500f, 0.943848f, 0.949219f, 0.953125f, 0.958496f, 0.961426f, 0.964844f, 0.967773f, 0.970703f, 0.973145f, 0.975098f,
+ 0.977539f, 0.979004f, 0.980957f, 0.982422f, 0.983887f, 0.985352f, 0.986328f, 0.987793f, 0.988770f, 0.989258f, 0.990723f, 0.991211f,
+ 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998047f, 0.998047f,
+ 0.001360f, 0.004257f, 0.007988f, 0.013092f, 0.018753f, 0.026352f, 0.035645f, 0.048096f, 0.064270f, 0.085449f, 0.113770f, 0.149292f,
+ 0.195190f, 0.251953f, 0.320557f, 0.395020f, 0.474121f, 0.549316f, 0.618652f, 0.678223f, 0.729492f, 0.770996f, 0.805176f, 0.833496f,
+ 0.855957f, 0.875977f, 0.891113f, 0.904785f, 0.915039f, 0.924316f, 0.933105f, 0.939453f, 0.945312f, 0.950684f, 0.955078f, 0.959473f,
+ 0.962891f, 0.966309f, 0.969727f, 0.972168f, 0.974121f, 0.976562f, 0.978516f, 0.979980f, 0.981934f, 0.983398f, 0.984375f, 0.986328f,
+ 0.986816f, 0.988281f, 0.989746f, 0.990234f, 0.991699f, 0.992188f, 0.992676f, 0.994141f, 0.994141f, 0.994629f, 0.998047f, 0.998047f,
+ 0.998535f, 0.998047f, 0.998047f, 0.998047f, 0.001075f, 0.003492f, 0.006275f, 0.010223f, 0.014473f, 0.019821f, 0.026581f, 0.035492f,
+ 0.046967f, 0.061829f, 0.080750f, 0.105164f, 0.136475f, 0.177246f, 0.227783f, 0.288818f, 0.358154f, 0.433594f, 0.509277f, 0.581543f,
+ 0.645508f, 0.701172f, 0.747070f, 0.783691f, 0.817383f, 0.842773f, 0.864258f, 0.881836f, 0.896484f, 0.908691f, 0.918945f, 0.928223f,
+ 0.935547f, 0.941895f, 0.948730f, 0.952637f, 0.957031f, 0.962402f, 0.964844f, 0.967773f, 0.970703f, 0.973633f, 0.975586f, 0.977539f,
+ 0.979492f, 0.981445f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.988281f, 0.988770f, 0.990234f, 0.991211f, 0.992188f, 0.992676f,
+ 0.993164f, 0.994141f, 0.997559f, 0.997559f, 0.998047f, 0.997559f, 0.997559f, 0.998047f, 0.000967f, 0.002928f, 0.005283f, 0.007759f,
+ 0.011612f, 0.015823f, 0.020966f, 0.027802f, 0.035461f, 0.045959f, 0.059235f, 0.075928f, 0.097778f, 0.126099f, 0.162598f, 0.207153f,
+ 0.261963f, 0.326416f, 0.398193f, 0.471680f, 0.543945f, 0.612305f, 0.671875f, 0.722656f, 0.765137f, 0.799805f, 0.828125f, 0.854004f,
+ 0.872070f, 0.888184f, 0.902344f, 0.914062f, 0.923340f, 0.931641f, 0.938965f, 0.945312f, 0.950684f, 0.955566f, 0.958984f, 0.962891f,
+ 0.966309f, 0.969727f, 0.972168f, 0.974609f, 0.977051f, 0.978516f, 0.980469f, 0.982422f, 0.984375f, 0.985352f, 0.987305f, 0.987793f,
+ 0.988770f, 0.990234f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.997559f, 0.998047f,
+ 0.000602f, 0.002605f, 0.004345f, 0.006706f, 0.009590f, 0.012650f, 0.016617f, 0.021423f, 0.027893f, 0.035004f, 0.044495f, 0.056610f,
+ 0.072327f, 0.092285f, 0.116821f, 0.148926f, 0.189697f, 0.238892f, 0.298340f, 0.365723f, 0.437988f, 0.511230f, 0.579590f, 0.642090f,
+ 0.698242f, 0.744141f, 0.781738f, 0.814453f, 0.840332f, 0.861816f, 0.880371f, 0.895996f, 0.907715f, 0.918945f, 0.928223f, 0.935547f,
+ 0.942871f, 0.948730f, 0.953125f, 0.958008f, 0.961914f, 0.965332f, 0.968750f, 0.971680f, 0.973633f, 0.976562f, 0.978516f, 0.979980f,
+ 0.981934f, 0.983398f, 0.985352f, 0.986816f, 0.988281f, 0.988770f, 0.989746f, 0.990723f, 0.991699f, 0.992676f, 0.997070f, 0.997559f,
+ 0.997559f, 0.997070f, 0.997070f, 0.997070f, 0.000607f, 0.001955f, 0.003616f, 0.005772f, 0.007656f, 0.010269f, 0.013496f, 0.017273f,
+ 0.022018f, 0.027466f, 0.034729f, 0.043488f, 0.054932f, 0.068359f, 0.086365f, 0.108765f, 0.137939f, 0.174316f, 0.219360f, 0.273926f,
+ 0.336670f, 0.406494f, 0.478516f, 0.549316f, 0.614746f, 0.673340f, 0.722656f, 0.765137f, 0.800293f, 0.828125f, 0.853516f, 0.872070f,
+ 0.888672f, 0.902832f, 0.914551f, 0.924316f, 0.932129f, 0.940430f, 0.946289f, 0.951660f, 0.956055f, 0.960449f, 0.964355f, 0.967773f,
+ 0.970703f, 0.972656f, 0.975586f, 0.978027f, 0.980469f, 0.981934f, 0.983398f, 0.985352f, 0.986328f, 0.988281f, 0.988770f, 0.990234f,
+ 0.990723f, 0.992188f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000600f, 0.001813f, 0.003101f, 0.004559f,
+ 0.006580f, 0.008873f, 0.011047f, 0.014091f, 0.017639f, 0.022049f, 0.027557f, 0.033997f, 0.042297f, 0.052704f, 0.065369f, 0.081238f,
+ 0.101929f, 0.127930f, 0.161255f, 0.202515f, 0.252686f, 0.311523f, 0.378174f, 0.449707f, 0.519531f, 0.587891f, 0.647949f, 0.701660f,
+ 0.746582f, 0.784668f, 0.817383f, 0.843262f, 0.864746f, 0.882324f, 0.896973f, 0.910156f, 0.920898f, 0.929688f, 0.937012f, 0.943848f,
+ 0.949707f, 0.955078f, 0.959473f, 0.963379f, 0.966797f, 0.970215f, 0.973145f, 0.975098f, 0.978027f, 0.980469f, 0.982422f, 0.983887f,
+ 0.984863f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.991211f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f,
+ 0.000604f, 0.001429f, 0.002676f, 0.003708f, 0.005745f, 0.006973f, 0.009270f, 0.011452f, 0.014503f, 0.018295f, 0.022369f, 0.027222f,
+ 0.033417f, 0.040833f, 0.050171f, 0.062744f, 0.077454f, 0.095886f, 0.119995f, 0.150391f, 0.187622f, 0.234253f, 0.289307f, 0.353027f,
+ 0.421631f, 0.492676f, 0.561523f, 0.625488f, 0.681152f, 0.730469f, 0.770996f, 0.806152f, 0.833984f, 0.857422f, 0.876465f, 0.893066f,
+ 0.906250f, 0.916992f, 0.926758f, 0.935059f, 0.942871f, 0.948242f, 0.954102f, 0.958496f, 0.962891f, 0.966309f, 0.969727f, 0.972168f,
+ 0.975098f, 0.977539f, 0.979492f, 0.981934f, 0.983398f, 0.984863f, 0.986328f, 0.987793f, 0.989258f, 0.990234f, 0.996094f, 0.996582f,
+ 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000365f, 0.001367f, 0.002123f, 0.003353f, 0.004692f, 0.006054f, 0.007675f, 0.009819f,
+ 0.012314f, 0.014862f, 0.018066f, 0.022064f, 0.026901f, 0.032471f, 0.039764f, 0.048584f, 0.060089f, 0.073730f, 0.090698f, 0.112854f,
+ 0.140381f, 0.175415f, 0.218018f, 0.269775f, 0.329834f, 0.396240f, 0.467285f, 0.537598f, 0.603516f, 0.662109f, 0.712891f, 0.757324f,
+ 0.793945f, 0.823730f, 0.849121f, 0.869629f, 0.887695f, 0.902344f, 0.914062f, 0.924805f, 0.932129f, 0.940430f, 0.947266f, 0.952148f,
+ 0.957031f, 0.962402f, 0.966309f, 0.969238f, 0.972656f, 0.975586f, 0.977051f, 0.979492f, 0.981934f, 0.983398f, 0.984863f, 0.986328f,
+ 0.988281f, 0.988770f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000356f, 0.001341f, 0.001913f, 0.002897f,
+ 0.003983f, 0.005322f, 0.006607f, 0.008514f, 0.010399f, 0.012451f, 0.015282f, 0.018356f, 0.021912f, 0.026443f, 0.031982f, 0.038635f,
+ 0.047150f, 0.057495f, 0.070007f, 0.086609f, 0.106689f, 0.131714f, 0.164429f, 0.203613f, 0.252441f, 0.310059f, 0.374512f, 0.444092f,
+ 0.514160f, 0.582031f, 0.643066f, 0.697266f, 0.743652f, 0.783691f, 0.814941f, 0.842773f, 0.865234f, 0.882812f, 0.897949f, 0.910645f,
+ 0.922363f, 0.931152f, 0.938965f, 0.945801f, 0.952148f, 0.957520f, 0.961426f, 0.965820f, 0.969727f, 0.972168f, 0.975098f, 0.977539f,
+ 0.979980f, 0.981934f, 0.983887f, 0.985352f, 0.986816f, 0.988281f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996094f,
+ 0.000243f, 0.000937f, 0.001662f, 0.002617f, 0.003527f, 0.004555f, 0.005642f, 0.007217f, 0.008820f, 0.010483f, 0.012383f, 0.015175f,
+ 0.018341f, 0.022049f, 0.026245f, 0.031067f, 0.037903f, 0.045563f, 0.054962f, 0.066956f, 0.082092f, 0.101074f, 0.124939f, 0.154663f,
+ 0.191528f, 0.237305f, 0.291992f, 0.354492f, 0.422852f, 0.492676f, 0.562012f, 0.625488f, 0.682617f, 0.731934f, 0.772949f, 0.807129f,
+ 0.835449f, 0.859863f, 0.878906f, 0.895020f, 0.908203f, 0.920898f, 0.929199f, 0.937988f, 0.945312f, 0.951660f, 0.957031f, 0.961914f,
+ 0.965332f, 0.968750f, 0.972656f, 0.975098f, 0.977539f, 0.979980f, 0.982422f, 0.983887f, 0.986328f, 0.987793f, 0.995117f, 0.995605f,
+ 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.000362f, 0.000970f, 0.001489f, 0.002251f, 0.002892f, 0.003727f, 0.004978f, 0.006264f,
+ 0.007530f, 0.009125f, 0.010551f, 0.012756f, 0.015259f, 0.018097f, 0.021637f, 0.025986f, 0.030594f, 0.036804f, 0.044006f, 0.053162f,
+ 0.064148f, 0.078003f, 0.096130f, 0.118042f, 0.146118f, 0.181030f, 0.224487f, 0.276123f, 0.336670f, 0.403320f, 0.473633f, 0.543457f,
+ 0.609375f, 0.667480f, 0.719238f, 0.763184f, 0.799316f, 0.829590f, 0.854492f, 0.875488f, 0.892578f, 0.906738f, 0.918945f, 0.928711f,
+ 0.937012f, 0.944336f, 0.951172f, 0.956543f, 0.961426f, 0.965820f, 0.968750f, 0.972656f, 0.975098f, 0.978027f, 0.980469f, 0.982910f,
+ 0.984375f, 0.985840f, 0.994629f, 0.995117f, 0.995117f, 0.995117f, 0.995117f, 0.995117f, 0.000346f, 0.000923f, 0.001273f, 0.002010f,
+ 0.002619f, 0.003689f, 0.004452f, 0.005177f, 0.006290f, 0.007561f, 0.009033f, 0.010902f, 0.012970f, 0.015495f, 0.018280f, 0.021576f,
+ 0.024948f, 0.030304f, 0.035400f, 0.042480f, 0.051086f, 0.061401f, 0.074890f, 0.091187f, 0.112427f, 0.138794f, 0.171631f, 0.212158f,
+ 0.262451f, 0.320557f, 0.385986f, 0.456055f, 0.525391f, 0.593262f, 0.654297f, 0.708984f, 0.754883f, 0.792969f, 0.824707f, 0.850098f,
+ 0.872070f, 0.890137f, 0.904785f, 0.917480f, 0.927734f, 0.937012f, 0.944336f, 0.951172f, 0.956055f, 0.961914f, 0.966309f, 0.969727f,
+ 0.973145f, 0.976074f, 0.978516f, 0.980469f, 0.982910f, 0.984863f, 0.993652f, 0.995117f, 0.994629f, 0.994629f, 0.994629f, 0.994629f,
+ 0.000242f, 0.000666f, 0.001081f, 0.001806f, 0.002512f, 0.003397f, 0.003866f, 0.004894f, 0.005566f, 0.006859f, 0.007957f, 0.009506f,
+ 0.011009f, 0.013046f, 0.015266f, 0.018173f, 0.021027f, 0.024811f, 0.029526f, 0.034790f, 0.041443f, 0.049835f, 0.059265f, 0.071899f,
+ 0.087769f, 0.107422f, 0.132202f, 0.163208f, 0.201782f, 0.249512f, 0.305908f, 0.370361f, 0.440430f, 0.511230f, 0.578613f, 0.642090f,
+ 0.698730f, 0.746582f, 0.787109f, 0.819824f, 0.848145f, 0.869141f, 0.888672f, 0.903809f, 0.916992f, 0.927246f, 0.936523f, 0.943848f,
+ 0.951660f, 0.957031f, 0.961426f, 0.965820f, 0.970215f, 0.973145f, 0.976074f, 0.979004f, 0.981445f, 0.983398f, 0.994141f, 0.994141f,
+ 0.994629f, 0.994141f, 0.994629f, 0.994141f, 0.000242f, 0.000709f, 0.000917f, 0.001194f, 0.002018f, 0.002634f, 0.003504f, 0.003918f,
+ 0.005020f, 0.005726f, 0.006935f, 0.008141f, 0.009666f, 0.011040f, 0.012848f, 0.014961f, 0.017624f, 0.020660f, 0.024368f, 0.028381f,
+ 0.033905f, 0.040283f, 0.047760f, 0.057312f, 0.069214f, 0.083984f, 0.102539f, 0.126221f, 0.155640f, 0.193359f, 0.238892f, 0.293701f,
+ 0.356689f, 0.425537f, 0.497070f, 0.568359f, 0.632812f, 0.690918f, 0.739746f, 0.782227f, 0.816406f, 0.845703f, 0.868652f, 0.887695f,
+ 0.903320f, 0.916992f, 0.927734f, 0.937012f, 0.944824f, 0.951660f, 0.957031f, 0.962891f, 0.966797f, 0.971191f, 0.973633f, 0.976562f,
+ 0.979492f, 0.981934f, 0.992676f, 0.993652f, 0.994141f, 0.993652f, 0.993652f, 0.994141f, 0.000244f, 0.000660f, 0.000918f, 0.001343f,
+ 0.002117f, 0.002407f, 0.002779f, 0.003626f, 0.004246f, 0.005207f, 0.005913f, 0.007145f, 0.008163f, 0.009438f, 0.011101f, 0.012871f,
+ 0.014999f, 0.017426f, 0.020096f, 0.024185f, 0.027725f, 0.032623f, 0.038910f, 0.046387f, 0.055298f, 0.066467f, 0.080627f, 0.098328f,
+ 0.120972f, 0.149658f, 0.184814f, 0.229492f, 0.282715f, 0.344727f, 0.414062f, 0.486084f, 0.556641f, 0.624023f, 0.683594f, 0.735352f,
+ 0.778320f, 0.814453f, 0.843750f, 0.867188f, 0.887207f, 0.903320f, 0.916504f, 0.928223f, 0.937500f, 0.945312f, 0.953125f, 0.958008f,
+ 0.964355f, 0.967285f, 0.971680f, 0.975098f, 0.978516f, 0.980957f, 0.992676f, 0.993652f, 0.994141f, 0.993652f, 0.993652f, 0.993164f,
+ 0.000200f, 0.000480f, 0.000808f, 0.001303f, 0.001680f, 0.002104f, 0.002510f, 0.002934f, 0.003468f, 0.004429f, 0.005539f, 0.006046f,
+ 0.006889f, 0.008438f, 0.009415f, 0.011108f, 0.012787f, 0.014572f, 0.017517f, 0.020279f, 0.023483f, 0.027359f, 0.031860f, 0.037964f,
+ 0.045227f, 0.053711f, 0.064148f, 0.077759f, 0.095093f, 0.116272f, 0.143311f, 0.177856f, 0.221191f, 0.273193f, 0.334473f, 0.403320f,
+ 0.476318f, 0.548828f, 0.617188f, 0.677734f, 0.730957f, 0.775879f, 0.812500f, 0.842285f, 0.866699f, 0.887695f, 0.903809f, 0.916992f,
+ 0.928711f, 0.938477f, 0.946777f, 0.953125f, 0.959473f, 0.963867f, 0.968750f, 0.972656f, 0.976074f, 0.979004f, 0.992188f, 0.992676f,
+ 0.993164f, 0.993164f, 0.992676f, 0.993164f, 0.000243f, 0.000469f, 0.000878f, 0.001158f, 0.001382f, 0.001801f, 0.002220f, 0.002699f,
+ 0.003273f, 0.004063f, 0.004715f, 0.005447f, 0.005917f, 0.007099f, 0.008385f, 0.009521f, 0.011032f, 0.012627f, 0.014870f, 0.016922f,
+ 0.019836f, 0.023010f, 0.026642f, 0.031174f, 0.036926f, 0.043549f, 0.051941f, 0.062561f, 0.075317f, 0.091553f, 0.112427f, 0.138428f,
+ 0.172485f, 0.213867f, 0.265381f, 0.326172f, 0.394775f, 0.467773f, 0.541504f, 0.610840f, 0.673340f, 0.728516f, 0.774414f, 0.812012f,
+ 0.842773f, 0.867676f, 0.887695f, 0.904297f, 0.918457f, 0.929688f, 0.939453f, 0.948242f, 0.955078f, 0.959961f, 0.965820f, 0.970215f,
+ 0.974121f, 0.977051f, 0.991211f, 0.993164f, 0.993164f, 0.992188f, 0.993164f, 0.992188f, 0.000000f, 0.000242f, 0.000799f, 0.000998f,
+ 0.001273f, 0.001671f, 0.002069f, 0.002485f, 0.003212f, 0.003578f, 0.003948f, 0.004559f, 0.005524f, 0.006321f, 0.007046f, 0.008438f,
+ 0.009438f, 0.010986f, 0.012390f, 0.014320f, 0.016663f, 0.019165f, 0.022476f, 0.025833f, 0.030487f, 0.035675f, 0.042358f, 0.050018f,
+ 0.060211f, 0.072693f, 0.088379f, 0.108948f, 0.134766f, 0.166626f, 0.208008f, 0.258545f, 0.318848f, 0.387451f, 0.461670f, 0.536621f,
+ 0.606934f, 0.671387f, 0.727539f, 0.773438f, 0.811523f, 0.843750f, 0.868164f, 0.889160f, 0.906250f, 0.920410f, 0.932617f, 0.941895f,
+ 0.949707f, 0.956055f, 0.962402f, 0.967285f, 0.971680f, 0.975586f, 0.990723f, 0.991699f, 0.991699f, 0.992188f, 0.992188f, 0.991699f,
+ 0.000237f, 0.000482f, 0.000772f, 0.000877f, 0.001109f, 0.001494f, 0.001991f, 0.002041f, 0.002537f, 0.002975f, 0.003469f, 0.004128f,
+ 0.004841f, 0.005550f, 0.006306f, 0.007359f, 0.008369f, 0.009415f, 0.010788f, 0.012306f, 0.014160f, 0.016571f, 0.018921f, 0.021896f,
+ 0.025497f, 0.029587f, 0.034576f, 0.041260f, 0.049011f, 0.058319f, 0.070557f, 0.086060f, 0.105774f, 0.130737f, 0.162720f, 0.203247f,
+ 0.252930f, 0.313477f, 0.382568f, 0.457275f, 0.532715f, 0.605469f, 0.671387f, 0.728027f, 0.774902f, 0.814453f, 0.844727f, 0.870605f,
+ 0.891113f, 0.909180f, 0.922852f, 0.934082f, 0.943359f, 0.951660f, 0.958008f, 0.964355f, 0.968750f, 0.973145f, 0.990234f, 0.990723f,
+ 0.991699f, 0.991211f, 0.991211f, 0.991211f, 0.000235f, 0.000461f, 0.000484f, 0.000891f, 0.001105f, 0.001346f, 0.001634f, 0.001936f,
+ 0.002438f, 0.002874f, 0.003353f, 0.003925f, 0.004189f, 0.004887f, 0.005684f, 0.006279f, 0.007298f, 0.008339f, 0.009384f, 0.010674f,
+ 0.012360f, 0.013901f, 0.016113f, 0.018677f, 0.021469f, 0.024841f, 0.029144f, 0.033783f, 0.039948f, 0.047272f, 0.056915f, 0.068726f,
+ 0.083801f, 0.102905f, 0.127563f, 0.159058f, 0.199341f, 0.248901f, 0.309570f, 0.379395f, 0.454834f, 0.532715f, 0.606934f, 0.672852f,
+ 0.729980f, 0.778320f, 0.817383f, 0.849121f, 0.874512f, 0.895020f, 0.911621f, 0.924805f, 0.937012f, 0.946289f, 0.954102f, 0.960938f,
+ 0.965820f, 0.971191f, 0.989258f, 0.990234f, 0.990723f, 0.991211f, 0.990723f, 0.990723f, 0.000000f, 0.000360f, 0.000477f, 0.000756f,
+ 0.000896f, 0.001065f, 0.001570f, 0.001622f, 0.002064f, 0.002525f, 0.002819f, 0.003004f, 0.003700f, 0.004356f, 0.005077f, 0.005428f,
+ 0.006283f, 0.007370f, 0.008339f, 0.009323f, 0.010567f, 0.012070f, 0.013672f, 0.015839f, 0.018066f, 0.020844f, 0.024002f, 0.028183f,
+ 0.033051f, 0.039246f, 0.046417f, 0.055450f, 0.067200f, 0.082031f, 0.100586f, 0.125122f, 0.156250f, 0.196167f, 0.245972f, 0.307129f,
+ 0.378174f, 0.454834f, 0.533203f, 0.608398f, 0.675781f, 0.734375f, 0.782715f, 0.821777f, 0.853516f, 0.878906f, 0.898926f, 0.915039f,
+ 0.929199f, 0.939941f, 0.948730f, 0.956055f, 0.963379f, 0.968262f, 0.988770f, 0.989746f, 0.990234f, 0.989746f, 0.989746f, 0.990234f,
+ 0.000000f, 0.000256f, 0.000467f, 0.000590f, 0.000772f, 0.001095f, 0.001356f, 0.001781f, 0.001984f, 0.002161f, 0.002546f, 0.002956f,
+ 0.003338f, 0.003899f, 0.004440f, 0.004986f, 0.005486f, 0.006310f, 0.006969f, 0.008148f, 0.009148f, 0.010284f, 0.011902f, 0.013573f,
+ 0.015465f, 0.017853f, 0.020340f, 0.023590f, 0.027298f, 0.032227f, 0.038208f, 0.045563f, 0.054047f, 0.065796f, 0.080322f, 0.098999f,
+ 0.122864f, 0.153809f, 0.193970f, 0.244629f, 0.306396f, 0.378662f, 0.457031f, 0.536621f, 0.613770f, 0.681641f, 0.740723f, 0.788574f,
+ 0.827637f, 0.858398f, 0.884277f, 0.903320f, 0.919922f, 0.932129f, 0.942871f, 0.951660f, 0.959961f, 0.965820f, 0.987305f, 0.988281f,
+ 0.989258f, 0.989258f, 0.989258f, 0.989258f, 0.000244f, 0.000243f, 0.000583f, 0.000585f, 0.000822f, 0.001073f, 0.001159f, 0.001452f,
+ 0.001525f, 0.002001f, 0.002201f, 0.002714f, 0.002932f, 0.003525f, 0.003904f, 0.004482f, 0.004997f, 0.005581f, 0.006233f, 0.006954f,
+ 0.007820f, 0.008949f, 0.009941f, 0.011482f, 0.013168f, 0.015099f, 0.017151f, 0.020111f, 0.022949f, 0.026947f, 0.031647f, 0.037354f,
+ 0.044342f, 0.053375f, 0.064331f, 0.078857f, 0.097351f, 0.121033f, 0.152588f, 0.192749f, 0.244263f, 0.307129f, 0.380615f, 0.461426f,
+ 0.543457f, 0.621582f, 0.690430f, 0.748047f, 0.796387f, 0.834961f, 0.865723f, 0.889160f, 0.908691f, 0.924316f, 0.937500f, 0.946777f,
+ 0.955078f, 0.962891f, 0.986328f, 0.987793f, 0.988770f, 0.988770f, 0.988770f, 0.988770f, 0.000000f, 0.000243f, 0.000308f, 0.000541f,
+ 0.000801f, 0.000827f, 0.001057f, 0.001280f, 0.001460f, 0.001781f, 0.002090f, 0.002481f, 0.002756f, 0.003054f, 0.003321f, 0.003948f,
+ 0.004303f, 0.004898f, 0.005306f, 0.006405f, 0.006954f, 0.007851f, 0.008537f, 0.009918f, 0.011208f, 0.012825f, 0.014534f, 0.016861f,
+ 0.019379f, 0.022629f, 0.026276f, 0.030838f, 0.036407f, 0.043488f, 0.051819f, 0.063416f, 0.077209f, 0.095825f, 0.119812f, 0.151489f,
+ 0.192749f, 0.245361f, 0.309814f, 0.385986f, 0.469238f, 0.552246f, 0.630859f, 0.699707f, 0.757324f, 0.805176f, 0.842773f, 0.873047f,
+ 0.895508f, 0.914062f, 0.929688f, 0.941406f, 0.952148f, 0.959473f, 0.985840f, 0.986816f, 0.987305f, 0.987305f, 0.987305f, 0.987305f,
+ 0.000000f, 0.000243f, 0.000242f, 0.000548f, 0.000695f, 0.000803f, 0.001053f, 0.001198f, 0.001363f, 0.001513f, 0.001886f, 0.002069f,
+ 0.002447f, 0.002676f, 0.003138f, 0.003551f, 0.003868f, 0.004261f, 0.004936f, 0.005337f, 0.005852f, 0.006615f, 0.007519f, 0.008575f,
+ 0.009705f, 0.010872f, 0.012688f, 0.014397f, 0.016479f, 0.019119f, 0.022064f, 0.025589f, 0.030304f, 0.035828f, 0.042603f, 0.050812f,
+ 0.062012f, 0.076355f, 0.094971f, 0.119263f, 0.151367f, 0.193726f, 0.247925f, 0.314941f, 0.393311f, 0.478271f, 0.563965f, 0.642578f,
+ 0.711914f, 0.769043f, 0.815430f, 0.851562f, 0.881348f, 0.902832f, 0.921387f, 0.934570f, 0.945801f, 0.955078f, 0.984375f, 0.986328f,
+ 0.986328f, 0.986328f, 0.986328f, 0.986328f, 0.000000f, 0.000234f, 0.000239f, 0.000308f, 0.000597f, 0.000690f, 0.000868f, 0.000937f,
+ 0.001189f, 0.001404f, 0.001696f, 0.001854f, 0.002180f, 0.002249f, 0.002672f, 0.002979f, 0.003494f, 0.003761f, 0.004257f, 0.004745f,
+ 0.005154f, 0.005821f, 0.006561f, 0.007557f, 0.008575f, 0.009575f, 0.010963f, 0.012238f, 0.014130f, 0.016113f, 0.018539f, 0.021545f,
+ 0.025162f, 0.029404f, 0.034851f, 0.041626f, 0.050354f, 0.061218f, 0.075562f, 0.094482f, 0.119507f, 0.152344f, 0.196167f, 0.252197f,
+ 0.322266f, 0.404053f, 0.490967f, 0.577637f, 0.658203f, 0.726074f, 0.782715f, 0.827637f, 0.861816f, 0.889648f, 0.910645f, 0.926758f,
+ 0.940918f, 0.950684f, 0.983398f, 0.985352f, 0.984863f, 0.985352f, 0.985840f, 0.985352f, 0.000000f, 0.000240f, 0.000237f, 0.000239f,
+ 0.000436f, 0.000648f, 0.000661f, 0.000892f, 0.001089f, 0.001484f, 0.001446f, 0.001586f, 0.001896f, 0.002176f, 0.002325f, 0.002634f,
+ 0.003057f, 0.003315f, 0.003561f, 0.004150f, 0.004578f, 0.005180f, 0.005768f, 0.006485f, 0.007286f, 0.008400f, 0.009453f, 0.010429f,
+ 0.011795f, 0.013680f, 0.015671f, 0.018005f, 0.020981f, 0.024521f, 0.028748f, 0.034119f, 0.040863f, 0.049622f, 0.060303f, 0.074829f,
+ 0.094116f, 0.119995f, 0.154297f, 0.199341f, 0.258301f, 0.331787f, 0.416504f, 0.507812f, 0.595703f, 0.675781f, 0.743164f, 0.797852f,
+ 0.840820f, 0.873535f, 0.899414f, 0.919434f, 0.934082f, 0.947266f, 0.982422f, 0.983887f, 0.983887f, 0.984375f, 0.984375f, 0.983887f,
+ 0.000136f, 0.000115f, 0.000237f, 0.000238f, 0.000358f, 0.000452f, 0.000759f, 0.000961f, 0.001026f, 0.001113f, 0.001433f, 0.001564f,
+ 0.001659f, 0.001955f, 0.002024f, 0.002384f, 0.002647f, 0.002974f, 0.003267f, 0.003611f, 0.003971f, 0.004498f, 0.005043f, 0.005539f,
+ 0.006344f, 0.007168f, 0.007942f, 0.009010f, 0.010353f, 0.011711f, 0.013458f, 0.015213f, 0.017548f, 0.020279f, 0.023926f, 0.028061f,
+ 0.033356f, 0.040283f, 0.048615f, 0.060455f, 0.074890f, 0.094727f, 0.121216f, 0.156860f, 0.204102f, 0.266846f, 0.344238f, 0.433105f,
+ 0.526855f, 0.616699f, 0.696289f, 0.761230f, 0.813965f, 0.854492f, 0.884766f, 0.909180f, 0.927734f, 0.941895f, 0.980957f, 0.982422f,
+ 0.982910f, 0.982422f, 0.982422f, 0.982910f, 0.000000f, 0.000103f, 0.000208f, 0.000356f, 0.000355f, 0.000400f, 0.000454f, 0.000861f,
+ 0.000922f, 0.001202f, 0.001088f, 0.001401f, 0.001493f, 0.001779f, 0.001881f, 0.002180f, 0.002329f, 0.002483f, 0.002846f, 0.003178f,
+ 0.003542f, 0.003914f, 0.004406f, 0.004871f, 0.005352f, 0.006119f, 0.006927f, 0.007904f, 0.008759f, 0.009972f, 0.011284f, 0.013046f,
+ 0.014938f, 0.016998f, 0.019943f, 0.023224f, 0.027161f, 0.032776f, 0.039917f, 0.048218f, 0.059937f, 0.075134f, 0.095642f, 0.123169f,
+ 0.160767f, 0.211670f, 0.278320f, 0.360352f, 0.454102f, 0.550293f, 0.640625f, 0.718262f, 0.781738f, 0.831055f, 0.869141f, 0.897461f,
+ 0.919434f, 0.936035f, 0.979492f, 0.980957f, 0.980957f, 0.981934f, 0.981445f, 0.981445f, 0.000000f, 0.000192f, 0.000191f, 0.000350f,
+ 0.000352f, 0.000354f, 0.000599f, 0.000721f, 0.000835f, 0.001044f, 0.000988f, 0.001141f, 0.001255f, 0.001479f, 0.001705f, 0.001815f,
+ 0.001843f, 0.002151f, 0.002369f, 0.002831f, 0.003067f, 0.003431f, 0.003698f, 0.004295f, 0.004738f, 0.005352f, 0.005859f, 0.006615f,
+ 0.007587f, 0.008583f, 0.009682f, 0.010735f, 0.012405f, 0.014381f, 0.016708f, 0.018921f, 0.022736f, 0.026947f, 0.032104f, 0.039032f,
+ 0.048004f, 0.059784f, 0.075500f, 0.096924f, 0.125977f, 0.166626f, 0.221069f, 0.292969f, 0.380371f, 0.479004f, 0.577637f, 0.667969f,
+ 0.743164f, 0.803711f, 0.849609f, 0.883789f, 0.910645f, 0.930176f, 0.977539f, 0.979492f, 0.979492f, 0.979492f, 0.979980f, 0.979492f,
+ 0.000000f, 0.000000f, 0.000191f, 0.000214f, 0.000441f, 0.000465f, 0.000351f, 0.000656f, 0.000672f, 0.000957f, 0.000881f, 0.001092f,
+ 0.001209f, 0.001259f, 0.001315f, 0.001583f, 0.001630f, 0.001834f, 0.002033f, 0.002367f, 0.002596f, 0.002924f, 0.003387f, 0.003693f,
+ 0.004063f, 0.004601f, 0.004986f, 0.005676f, 0.006557f, 0.006973f, 0.007801f, 0.008781f, 0.010475f, 0.012100f, 0.013817f, 0.015625f,
+ 0.018784f, 0.021927f, 0.026260f, 0.031677f, 0.038879f, 0.048004f, 0.059845f, 0.076233f, 0.098633f, 0.130005f, 0.173950f, 0.233032f,
+ 0.311035f, 0.405518f, 0.507812f, 0.608887f, 0.698242f, 0.769531f, 0.826172f, 0.868164f, 0.899414f, 0.922852f, 0.976074f, 0.977539f,
+ 0.977539f, 0.977051f, 0.978027f, 0.978027f, 0.000000f, 0.000000f, 0.000117f, 0.000211f, 0.000326f, 0.000573f, 0.000574f, 0.000583f,
+ 0.000584f, 0.000659f, 0.000901f, 0.001014f, 0.001064f, 0.001033f, 0.001163f, 0.001234f, 0.001546f, 0.001585f, 0.001894f, 0.002085f,
+ 0.002361f, 0.002504f, 0.003023f, 0.003147f, 0.003580f, 0.004032f, 0.004314f, 0.004936f, 0.005215f, 0.006081f, 0.006725f, 0.007927f,
+ 0.008743f, 0.009918f, 0.011642f, 0.013367f, 0.015404f, 0.018219f, 0.021545f, 0.025787f, 0.031174f, 0.038361f, 0.047577f, 0.060425f,
+ 0.077881f, 0.102051f, 0.135376f, 0.182861f, 0.249023f, 0.333984f, 0.436035f, 0.542969f, 0.644043f, 0.730469f, 0.798340f, 0.848633f,
+ 0.886719f, 0.914062f, 0.973633f, 0.974609f, 0.975098f, 0.976074f, 0.975098f, 0.976074f, 0.000000f, 0.000000f, 0.000114f, 0.000112f,
+ 0.000271f, 0.000510f, 0.000450f, 0.000565f, 0.000572f, 0.000581f, 0.000654f, 0.000825f, 0.000954f, 0.001085f, 0.001050f, 0.001087f,
+ 0.001282f, 0.001547f, 0.001585f, 0.001825f, 0.002066f, 0.002182f, 0.002384f, 0.002659f, 0.003172f, 0.003357f, 0.003721f, 0.004238f,
+ 0.004505f, 0.005024f, 0.005878f, 0.006512f, 0.007324f, 0.008293f, 0.009201f, 0.011040f, 0.012993f, 0.015007f, 0.017639f, 0.020920f,
+ 0.025131f, 0.030899f, 0.038269f, 0.047760f, 0.061188f, 0.079651f, 0.105469f, 0.142944f, 0.195801f, 0.268799f, 0.363525f, 0.472168f,
+ 0.582520f, 0.683594f, 0.765137f, 0.826660f, 0.872070f, 0.905273f, 0.972168f, 0.973633f, 0.973145f, 0.973633f, 0.973633f, 0.973633f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000111f, 0.000224f, 0.000412f, 0.000494f, 0.000543f, 0.000561f, 0.000680f, 0.000665f, 0.000675f,
+ 0.000679f, 0.000797f, 0.000926f, 0.001122f, 0.001132f, 0.001207f, 0.001375f, 0.001606f, 0.001838f, 0.001963f, 0.002163f, 0.002314f,
+ 0.002480f, 0.002956f, 0.003189f, 0.003489f, 0.003744f, 0.004311f, 0.004749f, 0.005276f, 0.005867f, 0.006962f, 0.008186f, 0.008987f,
+ 0.010498f, 0.012283f, 0.014374f, 0.017075f, 0.020355f, 0.024719f, 0.030640f, 0.037720f, 0.048309f, 0.062134f, 0.082336f, 0.110840f,
+ 0.151978f, 0.212891f, 0.294922f, 0.399170f, 0.515137f, 0.628418f, 0.724609f, 0.799805f, 0.854980f, 0.894043f, 0.968750f, 0.970215f,
+ 0.970703f, 0.971191f, 0.970703f, 0.970703f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000228f, 0.000233f, 0.000436f, 0.000457f,
+ 0.000621f, 0.000546f, 0.000622f, 0.000633f, 0.000576f, 0.000644f, 0.000717f, 0.000909f, 0.000994f, 0.001127f, 0.001179f, 0.001267f,
+ 0.001513f, 0.001628f, 0.001742f, 0.001974f, 0.002111f, 0.002403f, 0.002810f, 0.003139f, 0.003231f, 0.003466f, 0.004021f, 0.004459f,
+ 0.004971f, 0.005581f, 0.006809f, 0.007568f, 0.008759f, 0.010002f, 0.011665f, 0.013847f, 0.016342f, 0.019714f, 0.024368f, 0.030106f,
+ 0.037811f, 0.048706f, 0.063843f, 0.085327f, 0.118042f, 0.164917f, 0.234131f, 0.328125f, 0.443359f, 0.565430f, 0.677246f, 0.767578f,
+ 0.833496f, 0.882812f, 0.965820f, 0.967285f, 0.967773f, 0.968262f, 0.967773f, 0.968262f, 0.000000f, 0.000000f, 0.000000f, 0.000214f,
+ 0.000210f, 0.000296f, 0.000309f, 0.000386f, 0.000462f, 0.000482f, 0.000525f, 0.000572f, 0.000525f, 0.000558f, 0.000689f, 0.000685f,
+ 0.000841f, 0.000934f, 0.001008f, 0.001182f, 0.001271f, 0.001412f, 0.001757f, 0.001787f, 0.001769f, 0.002110f, 0.002321f, 0.002331f,
+ 0.002737f, 0.002951f, 0.003189f, 0.003588f, 0.004253f, 0.004627f, 0.005505f, 0.006119f, 0.006969f, 0.008018f, 0.009583f, 0.010971f,
+ 0.013245f, 0.015915f, 0.019257f, 0.023651f, 0.030014f, 0.038086f, 0.049683f, 0.066406f, 0.091125f, 0.127441f, 0.182617f, 0.262939f,
+ 0.370605f, 0.497070f, 0.623047f, 0.729004f, 0.810547f, 0.867188f, 0.962891f, 0.963867f, 0.964844f, 0.964844f, 0.964355f, 0.964355f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000200f, 0.000215f, 0.000229f, 0.000319f, 0.000330f, 0.000411f, 0.000491f, 0.000527f,
+ 0.000547f, 0.000560f, 0.000634f, 0.000648f, 0.000716f, 0.000778f, 0.000855f, 0.000998f, 0.001182f, 0.001111f, 0.001274f, 0.001625f,
+ 0.001584f, 0.001559f, 0.001864f, 0.002037f, 0.002296f, 0.002438f, 0.002600f, 0.002993f, 0.003290f, 0.003801f, 0.004467f, 0.005085f,
+ 0.005508f, 0.006519f, 0.007645f, 0.008743f, 0.010757f, 0.012558f, 0.014946f, 0.018661f, 0.023422f, 0.029556f, 0.038574f, 0.050964f,
+ 0.069702f, 0.097351f, 0.140015f, 0.205566f, 0.301025f, 0.424561f, 0.559082f, 0.683594f, 0.781250f, 0.852051f, 0.958496f, 0.960449f,
+ 0.960938f, 0.960938f, 0.960938f, 0.960449f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000194f, 0.000214f, 0.000251f,
+ 0.000302f, 0.000365f, 0.000370f, 0.000429f, 0.000495f, 0.000521f, 0.000504f, 0.000547f, 0.000632f, 0.000656f, 0.000695f, 0.000795f,
+ 0.000922f, 0.001074f, 0.001125f, 0.001192f, 0.001166f, 0.001303f, 0.001555f, 0.001575f, 0.001763f, 0.001970f, 0.002232f, 0.002560f,
+ 0.002657f, 0.003082f, 0.003559f, 0.003799f, 0.004620f, 0.005241f, 0.006081f, 0.007103f, 0.008385f, 0.009796f, 0.012192f, 0.014702f,
+ 0.018234f, 0.022934f, 0.029556f, 0.039307f, 0.053009f, 0.073547f, 0.106628f, 0.157715f, 0.237793f, 0.351318f, 0.490479f, 0.629883f,
+ 0.746094f, 0.832031f, 0.954590f, 0.956055f, 0.956055f, 0.957031f, 0.956543f, 0.956055f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000121f, 0.000146f, 0.000191f, 0.000200f, 0.000255f, 0.000232f, 0.000252f, 0.000359f, 0.000291f, 0.000342f, 0.000406f, 0.000498f,
+ 0.000520f, 0.000533f, 0.000632f, 0.000605f, 0.000689f, 0.000768f, 0.000908f, 0.001013f, 0.001087f, 0.001030f, 0.001211f, 0.001318f,
+ 0.001497f, 0.001609f, 0.001753f, 0.001957f, 0.002234f, 0.002352f, 0.002663f, 0.003040f, 0.003635f, 0.004082f, 0.004723f, 0.005516f,
+ 0.006367f, 0.007675f, 0.009224f, 0.011360f, 0.013695f, 0.017868f, 0.022598f, 0.029724f, 0.040222f, 0.055542f, 0.080078f, 0.119202f,
+ 0.182617f, 0.281738f, 0.417725f, 0.568848f, 0.705566f, 0.807129f, 0.948730f, 0.951172f, 0.951172f, 0.951172f, 0.951660f, 0.951660f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000203f, 0.000186f, 0.000184f, 0.000321f,
+ 0.000231f, 0.000337f, 0.000359f, 0.000430f, 0.000455f, 0.000531f, 0.000502f, 0.000517f, 0.000728f, 0.000643f, 0.000673f, 0.000816f,
+ 0.000930f, 0.000991f, 0.001028f, 0.001161f, 0.001284f, 0.001369f, 0.001474f, 0.001719f, 0.001781f, 0.001883f, 0.002258f, 0.002518f,
+ 0.002831f, 0.003201f, 0.003744f, 0.004349f, 0.005127f, 0.006130f, 0.007210f, 0.008423f, 0.010696f, 0.013405f, 0.017136f, 0.022522f,
+ 0.030029f, 0.041321f, 0.059631f, 0.089050f, 0.138062f, 0.218994f, 0.343750f, 0.500488f, 0.657227f, 0.780762f, 0.943848f, 0.945312f,
+ 0.945312f, 0.945801f, 0.945801f, 0.946289f, 0.000000f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f,
+ 0.000118f, 0.000137f, 0.000139f, 0.000241f, 0.000202f, 0.000304f, 0.000313f, 0.000332f, 0.000357f, 0.000420f, 0.000435f, 0.000463f,
+ 0.000645f, 0.000544f, 0.000700f, 0.000717f, 0.000669f, 0.000834f, 0.000865f, 0.000916f, 0.001109f, 0.001193f, 0.001246f, 0.001300f,
+ 0.001488f, 0.001538f, 0.001806f, 0.001929f, 0.002001f, 0.002462f, 0.002666f, 0.003260f, 0.003904f, 0.004364f, 0.005325f, 0.006306f,
+ 0.008041f, 0.009720f, 0.012718f, 0.016525f, 0.022217f, 0.030579f, 0.043854f, 0.065247f, 0.101929f, 0.166016f, 0.273193f, 0.428223f,
+ 0.600586f, 0.748047f, 0.936523f, 0.938477f, 0.938965f, 0.939453f, 0.938965f, 0.938965f, 0.000000f, 0.000122f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000114f, 0.000102f, 0.000090f, 0.000096f, 0.000131f, 0.000245f, 0.000276f, 0.000257f,
+ 0.000307f, 0.000316f, 0.000322f, 0.000373f, 0.000411f, 0.000440f, 0.000433f, 0.000650f, 0.000578f, 0.000704f, 0.000746f, 0.000723f,
+ 0.000819f, 0.000756f, 0.000758f, 0.000878f, 0.001009f, 0.001270f, 0.001399f, 0.001530f, 0.001798f, 0.001803f, 0.002151f, 0.002317f,
+ 0.002728f, 0.003222f, 0.003782f, 0.004612f, 0.005951f, 0.006985f, 0.009308f, 0.011955f, 0.016052f, 0.022324f, 0.031525f, 0.047272f,
+ 0.073853f, 0.122192f, 0.209717f, 0.352783f, 0.537109f, 0.709473f, 0.928223f, 0.930664f, 0.931152f, 0.930664f, 0.931641f, 0.931152f,
+ 0.000000f, 0.000000f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000119f, 0.000119f, 0.000111f, 0.000100f, 0.000139f,
+ 0.000082f, 0.000154f, 0.000121f, 0.000216f, 0.000147f, 0.000271f, 0.000288f, 0.000298f, 0.000386f, 0.000463f, 0.000370f, 0.000485f,
+ 0.000555f, 0.000530f, 0.000578f, 0.000574f, 0.000612f, 0.000712f, 0.000776f, 0.000716f, 0.000931f, 0.000831f, 0.000967f, 0.001154f,
+ 0.001176f, 0.001284f, 0.001497f, 0.001884f, 0.002270f, 0.002415f, 0.002947f, 0.003412f, 0.004032f, 0.005066f, 0.006485f, 0.008400f,
+ 0.011215f, 0.015404f, 0.022079f, 0.033264f, 0.052124f, 0.087646f, 0.155029f, 0.279297f, 0.465820f, 0.664062f, 0.918945f, 0.921387f,
+ 0.921875f, 0.922363f, 0.922363f, 0.921875f, 0.000000f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000119f, 0.000119f, 0.000119f,
+ 0.000118f, 0.000118f, 0.000110f, 0.000100f, 0.000091f, 0.000082f, 0.000075f, 0.000095f, 0.000166f, 0.000113f, 0.000163f, 0.000248f,
+ 0.000258f, 0.000277f, 0.000336f, 0.000301f, 0.000445f, 0.000495f, 0.000473f, 0.000505f, 0.000494f, 0.000470f, 0.000584f, 0.000752f,
+ 0.000821f, 0.000814f, 0.000845f, 0.000807f, 0.000932f, 0.000996f, 0.001380f, 0.001481f, 0.001507f, 0.001757f, 0.002146f, 0.002443f,
+ 0.002869f, 0.003546f, 0.004559f, 0.005878f, 0.007561f, 0.010475f, 0.015320f, 0.022675f, 0.036133f, 0.060883f, 0.110352f, 0.211670f,
+ 0.389160f, 0.610352f, 0.908691f, 0.909180f, 0.910645f, 0.912109f, 0.909668f, 0.910156f, 0.000000f, 0.000121f, 0.000120f, 0.000119f,
+ 0.000119f, 0.000118f, 0.000118f, 0.000117f, 0.000117f, 0.000117f, 0.000116f, 0.000110f, 0.000100f, 0.000099f, 0.000083f, 0.000077f,
+ 0.000071f, 0.000081f, 0.000087f, 0.000166f, 0.000177f, 0.000233f, 0.000238f, 0.000273f, 0.000325f, 0.000357f, 0.000292f, 0.000406f,
+ 0.000418f, 0.000440f, 0.000428f, 0.000568f, 0.000459f, 0.000628f, 0.000678f, 0.000688f, 0.000647f, 0.000830f, 0.000925f, 0.001111f,
+ 0.001011f, 0.001420f, 0.001504f, 0.001771f, 0.001997f, 0.002495f, 0.003147f, 0.003944f, 0.005077f, 0.006958f, 0.010040f, 0.015053f,
+ 0.023727f, 0.040680f, 0.075989f, 0.153076f, 0.312012f, 0.547363f, 0.894531f, 0.897461f, 0.897949f, 0.897949f, 0.897949f, 0.898438f,
+ 0.000000f, 0.000000f, 0.000119f, 0.000118f, 0.000118f, 0.000117f, 0.000116f, 0.000116f, 0.000115f, 0.000115f, 0.000114f, 0.000114f,
+ 0.000111f, 0.000101f, 0.000093f, 0.000086f, 0.000079f, 0.000095f, 0.000095f, 0.000090f, 0.000117f, 0.000109f, 0.000158f, 0.000199f,
+ 0.000207f, 0.000223f, 0.000286f, 0.000288f, 0.000267f, 0.000347f, 0.000368f, 0.000450f, 0.000377f, 0.000460f, 0.000504f, 0.000498f,
+ 0.000494f, 0.000616f, 0.000632f, 0.000699f, 0.000755f, 0.000938f, 0.000978f, 0.001222f, 0.001355f, 0.001673f, 0.002016f, 0.002539f,
+ 0.003258f, 0.004410f, 0.006332f, 0.009285f, 0.014847f, 0.025864f, 0.049042f, 0.104736f, 0.236572f, 0.477295f, 0.879395f, 0.881348f,
+ 0.882324f, 0.881836f, 0.882324f, 0.882324f, 0.000000f, 0.000119f, 0.000118f, 0.000116f, 0.000115f, 0.000114f, 0.000114f, 0.000113f,
+ 0.000112f, 0.000112f, 0.000111f, 0.000111f, 0.000110f, 0.000110f, 0.000103f, 0.000095f, 0.000088f, 0.000081f, 0.000076f, 0.000070f,
+ 0.000065f, 0.000100f, 0.000104f, 0.000099f, 0.000120f, 0.000145f, 0.000190f, 0.000204f, 0.000213f, 0.000230f, 0.000241f, 0.000279f,
+ 0.000325f, 0.000322f, 0.000328f, 0.000381f, 0.000351f, 0.000466f, 0.000452f, 0.000516f, 0.000591f, 0.000622f, 0.000733f, 0.000882f,
+ 0.000895f, 0.001092f, 0.001456f, 0.001765f, 0.002069f, 0.002821f, 0.003851f, 0.005558f, 0.008865f, 0.015579f, 0.029999f, 0.066895f,
+ 0.167480f, 0.400391f, 0.860352f, 0.862793f, 0.863281f, 0.864258f, 0.863281f, 0.863770f, 0.000119f, 0.000114f, 0.000113f, 0.000113f,
+ 0.000111f, 0.000110f, 0.000109f, 0.000109f, 0.000108f, 0.000107f, 0.000107f, 0.000107f, 0.000106f, 0.000105f, 0.000106f, 0.000105f,
+ 0.000098f, 0.000090f, 0.000084f, 0.000078f, 0.000073f, 0.000068f, 0.000063f, 0.000063f, 0.000066f, 0.000053f, 0.000080f, 0.000107f,
+ 0.000126f, 0.000150f, 0.000188f, 0.000187f, 0.000206f, 0.000205f, 0.000235f, 0.000242f, 0.000277f, 0.000340f, 0.000323f, 0.000308f,
+ 0.000417f, 0.000411f, 0.000445f, 0.000536f, 0.000622f, 0.000673f, 0.000887f, 0.000985f, 0.001289f, 0.001623f, 0.002337f, 0.003241f,
+ 0.004929f, 0.008560f, 0.016739f, 0.039307f, 0.109619f, 0.317383f, 0.837402f, 0.840332f, 0.841309f, 0.840820f, 0.840820f, 0.841309f,
+ 0.000000f, 0.000106f, 0.000099f, 0.000104f, 0.000102f, 0.000101f, 0.000100f, 0.000101f, 0.000101f, 0.000100f, 0.000099f, 0.000100f,
+ 0.000099f, 0.000099f, 0.000099f, 0.000098f, 0.000098f, 0.000098f, 0.000093f, 0.000086f, 0.000080f, 0.000075f, 0.000070f, 0.000065f,
+ 0.000061f, 0.000057f, 0.000059f, 0.000054f, 0.000061f, 0.000080f, 0.000087f, 0.000101f, 0.000136f, 0.000147f, 0.000163f, 0.000171f,
+ 0.000179f, 0.000205f, 0.000223f, 0.000237f, 0.000281f, 0.000272f, 0.000299f, 0.000364f, 0.000373f, 0.000448f, 0.000507f, 0.000643f,
+ 0.000801f, 0.001000f, 0.001276f, 0.001765f, 0.002712f, 0.004585f, 0.008492f, 0.020462f, 0.063721f, 0.233643f, 0.811035f, 0.813477f,
+ 0.814453f, 0.813965f, 0.813965f, 0.814453f, 0.000000f, 0.000057f, 0.000085f, 0.000085f, 0.000083f, 0.000085f, 0.000087f, 0.000086f,
+ 0.000087f, 0.000087f, 0.000086f, 0.000087f, 0.000087f, 0.000086f, 0.000087f, 0.000087f, 0.000088f, 0.000086f, 0.000088f, 0.000087f,
+ 0.000087f, 0.000081f, 0.000076f, 0.000071f, 0.000067f, 0.000063f, 0.000058f, 0.000055f, 0.000051f, 0.000048f, 0.000046f, 0.000042f,
+ 0.000051f, 0.000063f, 0.000081f, 0.000101f, 0.000122f, 0.000137f, 0.000147f, 0.000143f, 0.000157f, 0.000183f, 0.000205f, 0.000188f,
+ 0.000196f, 0.000249f, 0.000310f, 0.000329f, 0.000413f, 0.000534f, 0.000679f, 0.000944f, 0.001365f, 0.002199f, 0.004150f, 0.009369f,
+ 0.031677f, 0.153564f, 0.779297f, 0.781250f, 0.782227f, 0.782715f, 0.781738f, 0.781250f, 0.000000f, 0.000000f, 0.000000f, 0.000009f,
+ 0.000030f, 0.000048f, 0.000051f, 0.000054f, 0.000055f, 0.000059f, 0.000060f, 0.000065f, 0.000065f, 0.000066f, 0.000068f, 0.000068f,
+ 0.000070f, 0.000070f, 0.000071f, 0.000071f, 0.000072f, 0.000073f, 0.000073f, 0.000073f, 0.000071f, 0.000066f, 0.000062f, 0.000058f,
+ 0.000055f, 0.000051f, 0.000048f, 0.000045f, 0.000042f, 0.000039f, 0.000044f, 0.000036f, 0.000046f, 0.000056f, 0.000067f, 0.000085f,
+ 0.000099f, 0.000108f, 0.000107f, 0.000113f, 0.000139f, 0.000144f, 0.000165f, 0.000169f, 0.000196f, 0.000266f, 0.000311f, 0.000426f,
+ 0.000598f, 0.000948f, 0.001744f, 0.003975f, 0.012856f, 0.084351f, 0.739746f, 0.743164f, 0.743652f, 0.743652f, 0.743652f, 0.743164f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000012f, 0.000012f, 0.000020f,
+ 0.000028f, 0.000030f, 0.000033f, 0.000034f, 0.000041f, 0.000041f, 0.000045f, 0.000047f, 0.000048f, 0.000049f, 0.000051f, 0.000052f,
+ 0.000054f, 0.000054f, 0.000056f, 0.000057f, 0.000056f, 0.000052f, 0.000049f, 0.000046f, 0.000043f, 0.000041f, 0.000038f, 0.000035f,
+ 0.000033f, 0.000031f, 0.000029f, 0.000029f, 0.000036f, 0.000055f, 0.000048f, 0.000067f, 0.000067f, 0.000073f, 0.000075f, 0.000097f,
+ 0.000085f, 0.000111f, 0.000137f, 0.000191f, 0.000233f, 0.000371f, 0.000609f, 0.001319f, 0.004341f, 0.033844f, 0.696289f, 0.698730f,
+ 0.699219f, 0.698242f, 0.698730f, 0.698730f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000007f,
+ 0.000009f, 0.000012f, 0.000015f, 0.000020f, 0.000022f, 0.000023f, 0.000026f, 0.000029f, 0.000030f, 0.000032f, 0.000033f, 0.000035f,
+ 0.000037f, 0.000037f, 0.000036f, 0.000034f, 0.000032f, 0.000030f, 0.000028f, 0.000026f, 0.000024f, 0.000022f, 0.000021f, 0.000019f,
+ 0.000024f, 0.000024f, 0.000029f, 0.000037f, 0.000043f, 0.000046f, 0.000059f, 0.000058f, 0.000075f, 0.000095f, 0.000160f, 0.000306f,
+ 0.001006f, 0.008865f, 0.643066f, 0.647461f, 0.647949f, 0.647461f, 0.647949f, 0.648438f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000003f, 0.000005f, 0.000007f, 0.000010f, 0.000012f, 0.000013f, 0.000015f, 0.000017f,
+ 0.000019f, 0.000020f, 0.000018f, 0.000017f, 0.000015f, 0.000014f, 0.000013f, 0.000012f, 0.000010f, 0.000012f, 0.000014f, 0.000018f,
+ 0.000018f, 0.000025f, 0.000028f, 0.000045f, 0.000110f, 0.001030f, 0.586914f, 0.589844f, 0.590820f, 0.591309f, 0.591309f, 0.590820f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000002f, 0.000004f, 0.000005f, 0.000004f, 0.000004f, 0.000003f, 0.000003f, 0.000004f, 0.000009f, 0.527344f, 0.529785f,
+ 0.529785f, 0.530273f, 0.530762f, 0.530762f,
+ },
+ {
+ 0.135132f, 0.377441f, 0.544434f, 0.653320f, 0.724609f, 0.773926f, 0.811035f, 0.838867f, 0.860840f, 0.876465f, 0.891113f, 0.902832f,
+ 0.912109f, 0.920898f, 0.928223f, 0.934082f, 0.938965f, 0.943848f, 0.948242f, 0.952637f, 0.955566f, 0.958984f, 0.961914f, 0.964844f,
+ 0.966797f, 0.969238f, 0.971191f, 0.973145f, 0.975098f, 0.976562f, 0.978027f, 0.979492f, 0.980469f, 0.982422f, 0.983398f, 0.984863f,
+ 0.985840f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.989746f, 0.990234f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f,
+ 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f,
+ 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.044891f, 0.163330f, 0.306885f, 0.444336f, 0.559570f, 0.645020f, 0.710938f, 0.760742f,
+ 0.797852f, 0.827148f, 0.850098f, 0.868652f, 0.883789f, 0.895996f, 0.907227f, 0.916016f, 0.923340f, 0.930176f, 0.936523f, 0.941406f,
+ 0.946777f, 0.950684f, 0.954102f, 0.957031f, 0.960938f, 0.963379f, 0.965820f, 0.968262f, 0.970703f, 0.972168f, 0.974609f, 0.976562f,
+ 0.977539f, 0.979492f, 0.980469f, 0.981934f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.987793f, 0.988770f, 0.988770f, 0.990234f,
+ 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993164f, 0.994141f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f,
+ 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999023f, 0.999023f, 0.999023f, 0.020325f, 0.077820f, 0.158936f, 0.260498f,
+ 0.372314f, 0.479736f, 0.572754f, 0.648438f, 0.707520f, 0.754883f, 0.791016f, 0.820312f, 0.843750f, 0.862793f, 0.878906f, 0.891602f,
+ 0.903320f, 0.912598f, 0.920898f, 0.928223f, 0.933594f, 0.939941f, 0.944824f, 0.949219f, 0.952637f, 0.956543f, 0.959961f, 0.962402f,
+ 0.965332f, 0.967773f, 0.970215f, 0.971680f, 0.974121f, 0.976074f, 0.977539f, 0.979004f, 0.980957f, 0.981445f, 0.983398f, 0.984375f,
+ 0.985352f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.990234f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, 0.994141f, 0.994629f,
+ 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.998535f, 0.998535f,
+ 0.012032f, 0.042908f, 0.088196f, 0.149292f, 0.228027f, 0.319824f, 0.415527f, 0.506348f, 0.586914f, 0.653809f, 0.709473f, 0.752441f,
+ 0.787598f, 0.817383f, 0.840820f, 0.860352f, 0.876465f, 0.889648f, 0.900879f, 0.910156f, 0.918945f, 0.926270f, 0.933105f, 0.938965f,
+ 0.944336f, 0.948730f, 0.952637f, 0.956055f, 0.958984f, 0.962402f, 0.965332f, 0.967773f, 0.970215f, 0.972656f, 0.974609f, 0.976562f,
+ 0.978027f, 0.979492f, 0.980957f, 0.982422f, 0.983887f, 0.984375f, 0.985352f, 0.986816f, 0.987793f, 0.988770f, 0.989746f, 0.990234f,
+ 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.996094f, 0.996094f, 0.996582f, 0.997559f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.007637f, 0.026825f, 0.053436f, 0.090759f, 0.140137f, 0.203125f, 0.279053f, 0.363281f,
+ 0.449463f, 0.529785f, 0.601562f, 0.663574f, 0.713379f, 0.756348f, 0.789551f, 0.816895f, 0.840332f, 0.858887f, 0.875488f, 0.887695f,
+ 0.900391f, 0.909668f, 0.918945f, 0.926270f, 0.932617f, 0.938477f, 0.943848f, 0.948242f, 0.952148f, 0.955566f, 0.959473f, 0.962402f,
+ 0.965332f, 0.967773f, 0.970215f, 0.972168f, 0.974121f, 0.976562f, 0.978516f, 0.979492f, 0.980957f, 0.981934f, 0.984375f, 0.985352f,
+ 0.985840f, 0.987793f, 0.988281f, 0.989258f, 0.990723f, 0.991211f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995605f,
+ 0.996094f, 0.997070f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998047f, 0.004784f, 0.018082f, 0.035400f, 0.058868f,
+ 0.089783f, 0.130981f, 0.183716f, 0.248047f, 0.321289f, 0.400391f, 0.478760f, 0.552734f, 0.617188f, 0.673828f, 0.720703f, 0.759766f,
+ 0.792480f, 0.818359f, 0.840820f, 0.859863f, 0.875000f, 0.888184f, 0.899902f, 0.910645f, 0.918945f, 0.926270f, 0.931641f, 0.938965f,
+ 0.943848f, 0.948242f, 0.952148f, 0.957031f, 0.959473f, 0.962891f, 0.965332f, 0.968262f, 0.970215f, 0.972656f, 0.975098f, 0.977051f,
+ 0.978516f, 0.979980f, 0.981445f, 0.982910f, 0.984863f, 0.985352f, 0.986328f, 0.987305f, 0.988770f, 0.989746f, 0.990723f, 0.991699f,
+ 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995605f, 0.996094f, 0.998047f, 0.998535f, 0.998047f, 0.998047f, 0.998047f, 0.998047f,
+ 0.004044f, 0.012550f, 0.024628f, 0.040466f, 0.060760f, 0.087708f, 0.122742f, 0.167236f, 0.222534f, 0.287109f, 0.358643f, 0.432617f,
+ 0.506348f, 0.573242f, 0.632812f, 0.685059f, 0.728516f, 0.766602f, 0.797363f, 0.822266f, 0.843750f, 0.861328f, 0.877441f, 0.890625f,
+ 0.901367f, 0.910645f, 0.919434f, 0.926758f, 0.933105f, 0.940430f, 0.944824f, 0.948730f, 0.953125f, 0.957520f, 0.960449f, 0.963867f,
+ 0.966309f, 0.969238f, 0.970703f, 0.973633f, 0.976074f, 0.977539f, 0.979004f, 0.980469f, 0.982422f, 0.983398f, 0.984863f, 0.986816f,
+ 0.986816f, 0.988281f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.998047f, 0.998047f,
+ 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.002975f, 0.009315f, 0.017868f, 0.029129f, 0.043243f, 0.062012f, 0.084961f, 0.115540f,
+ 0.154419f, 0.201660f, 0.257812f, 0.322754f, 0.391846f, 0.463135f, 0.530762f, 0.594727f, 0.650391f, 0.698730f, 0.739258f, 0.773926f,
+ 0.803711f, 0.826660f, 0.847656f, 0.865723f, 0.879883f, 0.892090f, 0.903809f, 0.913086f, 0.921387f, 0.928223f, 0.935059f, 0.940918f,
+ 0.945801f, 0.950684f, 0.954102f, 0.958008f, 0.961426f, 0.964844f, 0.967285f, 0.970215f, 0.972168f, 0.974609f, 0.976074f, 0.978027f,
+ 0.979980f, 0.981934f, 0.983398f, 0.984375f, 0.985352f, 0.987305f, 0.988281f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.993164f,
+ 0.993652f, 0.994629f, 0.997559f, 0.998047f, 0.998047f, 0.997559f, 0.997559f, 0.997559f, 0.002329f, 0.007256f, 0.013611f, 0.021790f,
+ 0.032043f, 0.044617f, 0.061554f, 0.082336f, 0.108765f, 0.142578f, 0.184448f, 0.234375f, 0.292725f, 0.357422f, 0.424805f, 0.493164f,
+ 0.556641f, 0.615723f, 0.666504f, 0.711914f, 0.750977f, 0.782715f, 0.809570f, 0.832520f, 0.853516f, 0.868652f, 0.882812f, 0.895508f,
+ 0.905762f, 0.916016f, 0.923340f, 0.931152f, 0.936523f, 0.942383f, 0.947266f, 0.951172f, 0.956055f, 0.958984f, 0.962402f, 0.965820f,
+ 0.968750f, 0.971191f, 0.973633f, 0.975586f, 0.977539f, 0.979980f, 0.980957f, 0.982422f, 0.983887f, 0.985352f, 0.985840f, 0.988281f,
+ 0.989746f, 0.990234f, 0.991211f, 0.991699f, 0.993164f, 0.993652f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f,
+ 0.001871f, 0.006084f, 0.010963f, 0.016953f, 0.024277f, 0.033722f, 0.046234f, 0.060669f, 0.079224f, 0.103638f, 0.132812f, 0.169678f,
+ 0.214478f, 0.267090f, 0.326172f, 0.390137f, 0.456543f, 0.519531f, 0.581543f, 0.636230f, 0.685547f, 0.726562f, 0.762207f, 0.792969f,
+ 0.818359f, 0.839844f, 0.858398f, 0.874023f, 0.887695f, 0.898926f, 0.909668f, 0.918945f, 0.926270f, 0.933105f, 0.938965f, 0.944336f,
+ 0.949219f, 0.953613f, 0.958008f, 0.961426f, 0.964844f, 0.967773f, 0.969727f, 0.972168f, 0.974609f, 0.976074f, 0.979004f, 0.979980f,
+ 0.981934f, 0.983887f, 0.985352f, 0.986328f, 0.987793f, 0.989746f, 0.989746f, 0.990723f, 0.991211f, 0.992676f, 0.996582f, 0.997070f,
+ 0.997559f, 0.997070f, 0.997070f, 0.997070f, 0.001322f, 0.004795f, 0.008530f, 0.013504f, 0.018921f, 0.026154f, 0.035065f, 0.045807f,
+ 0.059662f, 0.076416f, 0.098267f, 0.124512f, 0.157715f, 0.197388f, 0.244873f, 0.299805f, 0.359619f, 0.423096f, 0.487549f, 0.549316f,
+ 0.605957f, 0.657715f, 0.703125f, 0.741211f, 0.774902f, 0.802734f, 0.827148f, 0.847656f, 0.865234f, 0.879883f, 0.893066f, 0.903320f,
+ 0.913086f, 0.920898f, 0.929199f, 0.935547f, 0.941406f, 0.947266f, 0.951172f, 0.956055f, 0.959473f, 0.962891f, 0.965332f, 0.969238f,
+ 0.971191f, 0.974121f, 0.976562f, 0.977539f, 0.979980f, 0.981445f, 0.982910f, 0.984863f, 0.986328f, 0.988281f, 0.988281f, 0.989746f,
+ 0.990723f, 0.991699f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.996582f, 0.001077f, 0.003971f, 0.006985f, 0.010750f,
+ 0.015579f, 0.020920f, 0.027420f, 0.035522f, 0.045776f, 0.058228f, 0.074097f, 0.093140f, 0.117310f, 0.146851f, 0.182495f, 0.225952f,
+ 0.276611f, 0.332764f, 0.394287f, 0.456543f, 0.518555f, 0.577637f, 0.630371f, 0.679199f, 0.720703f, 0.756836f, 0.787598f, 0.813477f,
+ 0.836426f, 0.855469f, 0.872070f, 0.885742f, 0.897949f, 0.908203f, 0.917480f, 0.925293f, 0.933105f, 0.939453f, 0.944336f, 0.949219f,
+ 0.954590f, 0.957520f, 0.961426f, 0.964844f, 0.968262f, 0.970703f, 0.974121f, 0.975586f, 0.978027f, 0.979492f, 0.981445f, 0.983398f,
+ 0.984863f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.991211f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f,
+ 0.000954f, 0.003330f, 0.005733f, 0.008904f, 0.012505f, 0.016617f, 0.022446f, 0.028351f, 0.036041f, 0.045807f, 0.056854f, 0.071350f,
+ 0.088867f, 0.110596f, 0.137451f, 0.170654f, 0.209717f, 0.256592f, 0.309326f, 0.366943f, 0.427979f, 0.489502f, 0.549316f, 0.604980f,
+ 0.655762f, 0.700195f, 0.738770f, 0.772461f, 0.801270f, 0.825195f, 0.845703f, 0.864258f, 0.879395f, 0.893066f, 0.903809f, 0.914062f,
+ 0.922363f, 0.929688f, 0.936523f, 0.942871f, 0.947266f, 0.952148f, 0.956055f, 0.960449f, 0.963867f, 0.966797f, 0.969727f, 0.972656f,
+ 0.975586f, 0.976562f, 0.979004f, 0.981445f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.988770f, 0.989746f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000949f, 0.002804f, 0.004730f, 0.007236f, 0.010384f, 0.014160f, 0.018478f, 0.023102f,
+ 0.028992f, 0.036346f, 0.044647f, 0.055542f, 0.068481f, 0.085144f, 0.105286f, 0.130005f, 0.159668f, 0.195557f, 0.238647f, 0.287842f,
+ 0.343018f, 0.402588f, 0.463135f, 0.522949f, 0.580566f, 0.632812f, 0.680664f, 0.721680f, 0.757812f, 0.788574f, 0.814453f, 0.836914f,
+ 0.856934f, 0.872070f, 0.887207f, 0.899414f, 0.909668f, 0.918945f, 0.926758f, 0.933594f, 0.940430f, 0.946289f, 0.950684f, 0.954590f,
+ 0.959473f, 0.963379f, 0.966797f, 0.969238f, 0.972168f, 0.975098f, 0.977051f, 0.979492f, 0.980957f, 0.982910f, 0.984375f, 0.986328f,
+ 0.987793f, 0.988770f, 0.995117f, 0.996094f, 0.995605f, 0.996094f, 0.996094f, 0.995605f, 0.000828f, 0.002361f, 0.004116f, 0.006119f,
+ 0.008797f, 0.011391f, 0.014854f, 0.018890f, 0.023666f, 0.029083f, 0.036011f, 0.044434f, 0.053986f, 0.066589f, 0.081543f, 0.100159f,
+ 0.122314f, 0.149536f, 0.183350f, 0.222900f, 0.269043f, 0.321533f, 0.378418f, 0.438477f, 0.499023f, 0.556641f, 0.611328f, 0.661133f,
+ 0.703613f, 0.742188f, 0.775391f, 0.804199f, 0.828613f, 0.849121f, 0.866211f, 0.881348f, 0.894043f, 0.905762f, 0.916016f, 0.924316f,
+ 0.931641f, 0.938477f, 0.944336f, 0.949707f, 0.954590f, 0.958496f, 0.962402f, 0.966309f, 0.969238f, 0.972168f, 0.974121f, 0.977051f,
+ 0.979004f, 0.980957f, 0.982910f, 0.984863f, 0.985840f, 0.987793f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f,
+ 0.000606f, 0.001948f, 0.003483f, 0.005394f, 0.007290f, 0.009735f, 0.012352f, 0.015747f, 0.019485f, 0.023788f, 0.029358f, 0.035706f,
+ 0.043732f, 0.053162f, 0.064331f, 0.077942f, 0.094971f, 0.116089f, 0.140991f, 0.172485f, 0.209473f, 0.252686f, 0.302002f, 0.356934f,
+ 0.415283f, 0.475830f, 0.534180f, 0.589844f, 0.641602f, 0.687500f, 0.728516f, 0.763184f, 0.792969f, 0.819336f, 0.841309f, 0.860840f,
+ 0.876953f, 0.890625f, 0.902344f, 0.913086f, 0.921875f, 0.930176f, 0.937012f, 0.943359f, 0.948242f, 0.954102f, 0.958008f, 0.961914f,
+ 0.965820f, 0.969238f, 0.971680f, 0.974609f, 0.977051f, 0.979004f, 0.981445f, 0.983398f, 0.984863f, 0.986816f, 0.994141f, 0.994629f,
+ 0.995117f, 0.995117f, 0.995117f, 0.994629f, 0.000672f, 0.001569f, 0.002895f, 0.004528f, 0.006180f, 0.008324f, 0.010864f, 0.013161f,
+ 0.016357f, 0.020096f, 0.024216f, 0.029327f, 0.035583f, 0.042664f, 0.051453f, 0.062073f, 0.075012f, 0.091125f, 0.110291f, 0.134155f,
+ 0.162476f, 0.197266f, 0.238037f, 0.285156f, 0.337646f, 0.395020f, 0.454590f, 0.513672f, 0.570312f, 0.624023f, 0.672363f, 0.714844f,
+ 0.750977f, 0.783691f, 0.811035f, 0.834473f, 0.854004f, 0.872070f, 0.886230f, 0.899414f, 0.911133f, 0.918945f, 0.928223f, 0.936035f,
+ 0.942871f, 0.948242f, 0.953613f, 0.957031f, 0.961426f, 0.965820f, 0.968750f, 0.972168f, 0.974121f, 0.976562f, 0.979492f, 0.981445f,
+ 0.983398f, 0.985352f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995117f, 0.994629f, 0.000413f, 0.001430f, 0.002577f, 0.004269f,
+ 0.005703f, 0.007137f, 0.008888f, 0.011124f, 0.013885f, 0.016891f, 0.020355f, 0.024384f, 0.029221f, 0.035217f, 0.041748f, 0.049988f,
+ 0.060059f, 0.072083f, 0.086914f, 0.105286f, 0.126953f, 0.154175f, 0.186523f, 0.224731f, 0.269287f, 0.320557f, 0.375732f, 0.434570f,
+ 0.493896f, 0.552246f, 0.606934f, 0.655762f, 0.701660f, 0.740723f, 0.774902f, 0.803711f, 0.827637f, 0.848633f, 0.867188f, 0.882812f,
+ 0.895996f, 0.908203f, 0.917969f, 0.926758f, 0.934570f, 0.941895f, 0.947266f, 0.952637f, 0.957520f, 0.960938f, 0.965820f, 0.968750f,
+ 0.971680f, 0.974609f, 0.977051f, 0.979980f, 0.981934f, 0.983887f, 0.993652f, 0.994629f, 0.994141f, 0.994141f, 0.994141f, 0.994141f,
+ 0.000240f, 0.001406f, 0.002373f, 0.003283f, 0.004620f, 0.006264f, 0.007744f, 0.009552f, 0.011711f, 0.014069f, 0.017273f, 0.020584f,
+ 0.024429f, 0.028946f, 0.034393f, 0.041046f, 0.048798f, 0.058289f, 0.070312f, 0.083618f, 0.100403f, 0.121338f, 0.146118f, 0.177002f,
+ 0.213257f, 0.255371f, 0.304443f, 0.358887f, 0.416504f, 0.476562f, 0.534668f, 0.590332f, 0.642090f, 0.688965f, 0.729492f, 0.766113f,
+ 0.796387f, 0.822754f, 0.844727f, 0.862305f, 0.880371f, 0.894043f, 0.905762f, 0.916992f, 0.926270f, 0.934082f, 0.940918f, 0.946777f,
+ 0.953125f, 0.956543f, 0.961426f, 0.964844f, 0.969238f, 0.972656f, 0.974609f, 0.977539f, 0.979980f, 0.982422f, 0.992676f, 0.994141f,
+ 0.993652f, 0.993652f, 0.993652f, 0.993652f, 0.000242f, 0.001257f, 0.001991f, 0.003138f, 0.004299f, 0.005302f, 0.006584f, 0.008308f,
+ 0.010048f, 0.012283f, 0.014526f, 0.017578f, 0.020340f, 0.023972f, 0.028671f, 0.033661f, 0.040161f, 0.047821f, 0.056213f, 0.067261f,
+ 0.080444f, 0.096191f, 0.115784f, 0.139771f, 0.168457f, 0.203125f, 0.243286f, 0.290527f, 0.343506f, 0.400879f, 0.459473f, 0.519043f,
+ 0.576172f, 0.629395f, 0.678223f, 0.721191f, 0.757324f, 0.789062f, 0.816895f, 0.839844f, 0.859863f, 0.877930f, 0.892578f, 0.904297f,
+ 0.915527f, 0.925293f, 0.933105f, 0.940430f, 0.946777f, 0.952148f, 0.957031f, 0.961914f, 0.965820f, 0.969238f, 0.973145f, 0.975586f,
+ 0.978516f, 0.980469f, 0.992188f, 0.993652f, 0.993164f, 0.993164f, 0.993652f, 0.993164f, 0.000434f, 0.001172f, 0.001865f, 0.002825f,
+ 0.003633f, 0.004757f, 0.005722f, 0.007175f, 0.009010f, 0.010651f, 0.012520f, 0.014412f, 0.017532f, 0.020599f, 0.024139f, 0.028488f,
+ 0.033356f, 0.039001f, 0.046295f, 0.054749f, 0.064758f, 0.077209f, 0.092834f, 0.111084f, 0.134033f, 0.160767f, 0.193604f, 0.233032f,
+ 0.278320f, 0.329590f, 0.386230f, 0.445068f, 0.504395f, 0.563477f, 0.617188f, 0.666504f, 0.711426f, 0.750000f, 0.783691f, 0.812500f,
+ 0.836426f, 0.857422f, 0.875488f, 0.891113f, 0.903809f, 0.915039f, 0.924805f, 0.933105f, 0.940430f, 0.947266f, 0.953125f, 0.958496f,
+ 0.962402f, 0.966309f, 0.969727f, 0.973145f, 0.976562f, 0.978516f, 0.991699f, 0.992188f, 0.992676f, 0.993164f, 0.993164f, 0.992676f,
+ 0.000358f, 0.000835f, 0.001738f, 0.002270f, 0.002996f, 0.004078f, 0.005157f, 0.006416f, 0.007904f, 0.009331f, 0.010826f, 0.012245f,
+ 0.014938f, 0.017303f, 0.020233f, 0.023926f, 0.027954f, 0.032715f, 0.038147f, 0.045166f, 0.053070f, 0.062561f, 0.074768f, 0.089661f,
+ 0.106689f, 0.128052f, 0.154175f, 0.185547f, 0.223022f, 0.266846f, 0.317383f, 0.373047f, 0.431152f, 0.491943f, 0.550293f, 0.606445f,
+ 0.658203f, 0.704102f, 0.744141f, 0.779297f, 0.809082f, 0.833984f, 0.855957f, 0.875000f, 0.889648f, 0.903320f, 0.915039f, 0.924805f,
+ 0.933594f, 0.940918f, 0.947754f, 0.954102f, 0.958984f, 0.962402f, 0.966797f, 0.970703f, 0.974121f, 0.977539f, 0.990723f, 0.992188f,
+ 0.992676f, 0.992676f, 0.992188f, 0.992676f, 0.000428f, 0.000789f, 0.001460f, 0.002172f, 0.002695f, 0.003561f, 0.004608f, 0.005848f,
+ 0.006886f, 0.007736f, 0.009560f, 0.011078f, 0.012817f, 0.015015f, 0.017563f, 0.020157f, 0.023666f, 0.027145f, 0.031891f, 0.037384f,
+ 0.044189f, 0.051788f, 0.061188f, 0.072327f, 0.085999f, 0.102966f, 0.123413f, 0.148071f, 0.178101f, 0.214478f, 0.256836f, 0.306396f,
+ 0.360840f, 0.419678f, 0.479736f, 0.540527f, 0.597656f, 0.649902f, 0.697754f, 0.738770f, 0.775391f, 0.805664f, 0.831543f, 0.854004f,
+ 0.873535f, 0.889160f, 0.902832f, 0.915039f, 0.925293f, 0.934082f, 0.941895f, 0.948730f, 0.954102f, 0.959961f, 0.963867f, 0.968262f,
+ 0.971680f, 0.975586f, 0.990723f, 0.991699f, 0.991699f, 0.991699f, 0.991699f, 0.991211f, 0.000237f, 0.000782f, 0.001245f, 0.001923f,
+ 0.002417f, 0.003225f, 0.004101f, 0.005062f, 0.005920f, 0.007030f, 0.008102f, 0.009743f, 0.011009f, 0.013054f, 0.015190f, 0.017380f,
+ 0.020126f, 0.023346f, 0.027161f, 0.031464f, 0.036316f, 0.042664f, 0.050110f, 0.058807f, 0.069946f, 0.083191f, 0.099121f, 0.118835f,
+ 0.142822f, 0.171997f, 0.206665f, 0.248413f, 0.296143f, 0.350586f, 0.408936f, 0.469727f, 0.530762f, 0.589844f, 0.643555f, 0.691895f,
+ 0.734375f, 0.772461f, 0.803223f, 0.830566f, 0.854492f, 0.873047f, 0.889648f, 0.903809f, 0.916016f, 0.926270f, 0.935059f, 0.943359f,
+ 0.949219f, 0.955566f, 0.960938f, 0.965332f, 0.969727f, 0.973145f, 0.989746f, 0.990723f, 0.990723f, 0.990723f, 0.991211f, 0.990723f,
+ 0.000243f, 0.000793f, 0.001210f, 0.001616f, 0.002260f, 0.003069f, 0.003649f, 0.004444f, 0.005322f, 0.006088f, 0.006954f, 0.008278f,
+ 0.009766f, 0.011139f, 0.012970f, 0.014908f, 0.016968f, 0.019897f, 0.023193f, 0.026962f, 0.030792f, 0.035522f, 0.041931f, 0.048920f,
+ 0.057404f, 0.067993f, 0.080383f, 0.095825f, 0.114929f, 0.137695f, 0.165771f, 0.199585f, 0.241089f, 0.287842f, 0.341553f, 0.400391f,
+ 0.462402f, 0.523438f, 0.583008f, 0.638184f, 0.687988f, 0.732422f, 0.770020f, 0.802246f, 0.830566f, 0.854004f, 0.873047f, 0.891113f,
+ 0.904785f, 0.916992f, 0.926758f, 0.936523f, 0.943848f, 0.951172f, 0.956543f, 0.961914f, 0.966797f, 0.971191f, 0.989258f, 0.990234f,
+ 0.990234f, 0.990234f, 0.990234f, 0.989746f, 0.000000f, 0.000484f, 0.000973f, 0.001453f, 0.001999f, 0.002689f, 0.003359f, 0.003864f,
+ 0.004726f, 0.005444f, 0.006516f, 0.007404f, 0.008461f, 0.009720f, 0.011261f, 0.012985f, 0.014908f, 0.017120f, 0.019699f, 0.022614f,
+ 0.026093f, 0.030228f, 0.034668f, 0.040619f, 0.047699f, 0.055756f, 0.066284f, 0.078308f, 0.092834f, 0.111328f, 0.133423f, 0.160889f,
+ 0.194214f, 0.233765f, 0.281006f, 0.334473f, 0.392822f, 0.455078f, 0.517090f, 0.578125f, 0.634766f, 0.686035f, 0.730957f, 0.768555f,
+ 0.803223f, 0.831055f, 0.854492f, 0.875488f, 0.892090f, 0.906250f, 0.918457f, 0.929688f, 0.937988f, 0.945801f, 0.952148f, 0.958496f,
+ 0.963867f, 0.968750f, 0.988281f, 0.989258f, 0.989746f, 0.989258f, 0.989746f, 0.989258f, 0.000241f, 0.000699f, 0.000835f, 0.001354f,
+ 0.002066f, 0.002405f, 0.003073f, 0.003466f, 0.003847f, 0.004868f, 0.005798f, 0.006325f, 0.007446f, 0.008553f, 0.009789f, 0.011375f,
+ 0.013031f, 0.014702f, 0.016937f, 0.019455f, 0.022171f, 0.025467f, 0.029541f, 0.034271f, 0.039734f, 0.046295f, 0.054291f, 0.063904f,
+ 0.075745f, 0.089966f, 0.107727f, 0.129395f, 0.156250f, 0.188965f, 0.228394f, 0.274658f, 0.327637f, 0.386963f, 0.449219f, 0.512695f,
+ 0.574707f, 0.632324f, 0.684570f, 0.730469f, 0.770508f, 0.804688f, 0.832520f, 0.857422f, 0.876953f, 0.893066f, 0.908691f, 0.920410f,
+ 0.931152f, 0.940430f, 0.947754f, 0.954590f, 0.960938f, 0.965820f, 0.986816f, 0.988770f, 0.988770f, 0.988770f, 0.988770f, 0.988770f,
+ 0.000122f, 0.000480f, 0.000793f, 0.001184f, 0.001847f, 0.002220f, 0.002459f, 0.003109f, 0.003740f, 0.004234f, 0.005127f, 0.005730f,
+ 0.006557f, 0.007458f, 0.008469f, 0.009911f, 0.011162f, 0.012848f, 0.014519f, 0.016693f, 0.019135f, 0.021820f, 0.025024f, 0.028931f,
+ 0.033508f, 0.038757f, 0.045135f, 0.052856f, 0.062042f, 0.073547f, 0.087646f, 0.104736f, 0.126099f, 0.152588f, 0.184570f, 0.223511f,
+ 0.269775f, 0.323242f, 0.382324f, 0.445801f, 0.510254f, 0.573242f, 0.631348f, 0.685059f, 0.731934f, 0.772461f, 0.806641f, 0.834961f,
+ 0.859375f, 0.879883f, 0.897461f, 0.911133f, 0.923828f, 0.933594f, 0.942383f, 0.950195f, 0.956055f, 0.962402f, 0.985840f, 0.987305f,
+ 0.987793f, 0.987793f, 0.988281f, 0.987793f, 0.000244f, 0.000471f, 0.000666f, 0.001267f, 0.001592f, 0.001838f, 0.002251f, 0.002855f,
+ 0.003225f, 0.003828f, 0.004372f, 0.005112f, 0.005695f, 0.006340f, 0.007534f, 0.008797f, 0.009895f, 0.011215f, 0.012604f, 0.014503f,
+ 0.016602f, 0.018738f, 0.021408f, 0.024567f, 0.028305f, 0.032654f, 0.037872f, 0.043732f, 0.051239f, 0.060669f, 0.071716f, 0.085510f,
+ 0.102356f, 0.123230f, 0.149170f, 0.180664f, 0.219849f, 0.265869f, 0.319092f, 0.379150f, 0.443604f, 0.508789f, 0.572754f, 0.633301f,
+ 0.686523f, 0.734863f, 0.775391f, 0.809570f, 0.838379f, 0.862305f, 0.883301f, 0.900391f, 0.914551f, 0.926270f, 0.937012f, 0.944824f,
+ 0.953125f, 0.959473f, 0.985352f, 0.986816f, 0.986816f, 0.986816f, 0.986816f, 0.986816f, 0.000242f, 0.000346f, 0.000827f, 0.001065f,
+ 0.001428f, 0.001572f, 0.001984f, 0.002367f, 0.002851f, 0.003277f, 0.003786f, 0.004501f, 0.005253f, 0.005955f, 0.006573f, 0.007736f,
+ 0.008659f, 0.009880f, 0.011177f, 0.012459f, 0.014153f, 0.016403f, 0.018173f, 0.020859f, 0.024017f, 0.027496f, 0.031708f, 0.036682f,
+ 0.042877f, 0.050446f, 0.059174f, 0.070068f, 0.083374f, 0.100159f, 0.120728f, 0.145874f, 0.177612f, 0.216187f, 0.262695f, 0.316650f,
+ 0.377686f, 0.443115f, 0.509766f, 0.575195f, 0.635742f, 0.691406f, 0.738281f, 0.779785f, 0.813965f, 0.843750f, 0.866699f, 0.887207f,
+ 0.904297f, 0.918945f, 0.930176f, 0.940918f, 0.948730f, 0.956055f, 0.984375f, 0.985840f, 0.985840f, 0.985840f, 0.986328f, 0.985840f,
+ 0.000242f, 0.000540f, 0.000708f, 0.000830f, 0.001143f, 0.001451f, 0.001861f, 0.002249f, 0.002661f, 0.003010f, 0.003435f, 0.003922f,
+ 0.004707f, 0.005165f, 0.005787f, 0.006840f, 0.007374f, 0.008545f, 0.009651f, 0.011147f, 0.012581f, 0.014084f, 0.015991f, 0.017899f,
+ 0.020325f, 0.023392f, 0.026978f, 0.031113f, 0.035919f, 0.042023f, 0.049103f, 0.057831f, 0.068420f, 0.081543f, 0.098145f, 0.118530f,
+ 0.143921f, 0.175293f, 0.213989f, 0.260742f, 0.316162f, 0.377441f, 0.444336f, 0.512207f, 0.579590f, 0.641113f, 0.696289f, 0.744629f,
+ 0.786621f, 0.820801f, 0.849609f, 0.872559f, 0.892578f, 0.908691f, 0.922363f, 0.934570f, 0.944336f, 0.951660f, 0.982910f, 0.984375f,
+ 0.984863f, 0.984863f, 0.985352f, 0.984863f, 0.000106f, 0.000477f, 0.000649f, 0.000901f, 0.001110f, 0.001206f, 0.001630f, 0.002121f,
+ 0.002192f, 0.002743f, 0.003128f, 0.003538f, 0.003941f, 0.004688f, 0.005276f, 0.005905f, 0.006546f, 0.007568f, 0.008461f, 0.009483f,
+ 0.010674f, 0.011864f, 0.013649f, 0.015549f, 0.017731f, 0.020111f, 0.023010f, 0.026199f, 0.030304f, 0.035278f, 0.040833f, 0.047821f,
+ 0.056580f, 0.066895f, 0.079895f, 0.096191f, 0.116760f, 0.141968f, 0.173584f, 0.212646f, 0.260498f, 0.316162f, 0.379883f, 0.447754f,
+ 0.517578f, 0.584961f, 0.647949f, 0.704102f, 0.752930f, 0.792969f, 0.827148f, 0.855957f, 0.877930f, 0.898438f, 0.914062f, 0.928223f,
+ 0.938965f, 0.948242f, 0.981445f, 0.983398f, 0.983887f, 0.983887f, 0.983887f, 0.983398f, 0.000208f, 0.000456f, 0.000582f, 0.000788f,
+ 0.001016f, 0.001428f, 0.001507f, 0.001769f, 0.002203f, 0.002525f, 0.002718f, 0.003187f, 0.003761f, 0.004238f, 0.004635f, 0.005348f,
+ 0.005901f, 0.006805f, 0.007500f, 0.008545f, 0.009270f, 0.010437f, 0.011742f, 0.013344f, 0.015198f, 0.017242f, 0.019516f, 0.022430f,
+ 0.025665f, 0.029922f, 0.034180f, 0.040161f, 0.046936f, 0.055420f, 0.065735f, 0.078552f, 0.094666f, 0.114563f, 0.140503f, 0.172485f,
+ 0.212646f, 0.260986f, 0.318359f, 0.383545f, 0.453125f, 0.524414f, 0.593750f, 0.656738f, 0.712891f, 0.761230f, 0.801270f, 0.835938f,
+ 0.862305f, 0.885742f, 0.904785f, 0.919922f, 0.933594f, 0.943359f, 0.980469f, 0.982422f, 0.982422f, 0.981934f, 0.982422f, 0.982422f,
+ 0.000170f, 0.000350f, 0.000583f, 0.000682f, 0.000845f, 0.001036f, 0.001265f, 0.001821f, 0.001953f, 0.002163f, 0.002525f, 0.002771f,
+ 0.003418f, 0.003729f, 0.004040f, 0.004871f, 0.005188f, 0.005726f, 0.006512f, 0.007130f, 0.008087f, 0.009018f, 0.010216f, 0.011490f,
+ 0.013084f, 0.014565f, 0.016891f, 0.019073f, 0.021851f, 0.025253f, 0.029022f, 0.033539f, 0.039124f, 0.045563f, 0.054230f, 0.064270f,
+ 0.077271f, 0.093323f, 0.113403f, 0.139648f, 0.172485f, 0.213379f, 0.262939f, 0.322266f, 0.389404f, 0.461426f, 0.534180f, 0.604492f,
+ 0.668457f, 0.724609f, 0.772461f, 0.812500f, 0.845703f, 0.872070f, 0.894043f, 0.911621f, 0.926758f, 0.938477f, 0.979004f, 0.980469f,
+ 0.980957f, 0.980957f, 0.980957f, 0.980957f, 0.000000f, 0.000332f, 0.000583f, 0.000583f, 0.000848f, 0.000959f, 0.001125f, 0.001425f,
+ 0.001810f, 0.001899f, 0.002300f, 0.002529f, 0.002996f, 0.003162f, 0.003607f, 0.004150f, 0.004761f, 0.005146f, 0.005791f, 0.006329f,
+ 0.007099f, 0.008110f, 0.008949f, 0.009941f, 0.011253f, 0.012756f, 0.014565f, 0.016434f, 0.018707f, 0.021271f, 0.024475f, 0.028290f,
+ 0.032745f, 0.037964f, 0.044769f, 0.052795f, 0.063416f, 0.076050f, 0.092102f, 0.113464f, 0.139526f, 0.172974f, 0.214600f, 0.266602f,
+ 0.327637f, 0.397461f, 0.471191f, 0.546387f, 0.617188f, 0.682129f, 0.737793f, 0.784668f, 0.823730f, 0.854980f, 0.881348f, 0.902344f,
+ 0.918945f, 0.933105f, 0.977539f, 0.979492f, 0.979492f, 0.979492f, 0.979492f, 0.979492f, 0.000000f, 0.000243f, 0.000553f, 0.000575f,
+ 0.000591f, 0.000798f, 0.000991f, 0.001234f, 0.001419f, 0.001812f, 0.001935f, 0.002186f, 0.002518f, 0.002975f, 0.003202f, 0.003614f,
+ 0.004047f, 0.004425f, 0.005013f, 0.005718f, 0.006172f, 0.007046f, 0.007740f, 0.008835f, 0.009819f, 0.011192f, 0.012444f, 0.014114f,
+ 0.015884f, 0.018204f, 0.020844f, 0.023392f, 0.027420f, 0.031921f, 0.037170f, 0.043610f, 0.052032f, 0.062408f, 0.075256f, 0.091675f,
+ 0.112610f, 0.140015f, 0.173950f, 0.217651f, 0.271973f, 0.335693f, 0.407715f, 0.484619f, 0.561035f, 0.633789f, 0.698242f, 0.752930f,
+ 0.798828f, 0.836426f, 0.867676f, 0.891602f, 0.911621f, 0.926270f, 0.975098f, 0.977539f, 0.978516f, 0.977539f, 0.977539f, 0.978027f,
+ 0.000121f, 0.000121f, 0.000241f, 0.000385f, 0.000684f, 0.000693f, 0.000932f, 0.001156f, 0.001410f, 0.001648f, 0.001893f, 0.002184f,
+ 0.002367f, 0.002579f, 0.002872f, 0.003319f, 0.003653f, 0.003922f, 0.004425f, 0.004925f, 0.005436f, 0.006180f, 0.006836f, 0.007645f,
+ 0.008278f, 0.009476f, 0.010788f, 0.012169f, 0.013695f, 0.015305f, 0.017319f, 0.020111f, 0.022858f, 0.026718f, 0.030975f, 0.036255f,
+ 0.042938f, 0.051270f, 0.061493f, 0.074768f, 0.091187f, 0.112976f, 0.140747f, 0.176392f, 0.222168f, 0.278809f, 0.345703f, 0.421387f,
+ 0.500488f, 0.578613f, 0.651855f, 0.715820f, 0.769531f, 0.813965f, 0.850586f, 0.878418f, 0.901855f, 0.920410f, 0.973633f, 0.975586f,
+ 0.976074f, 0.976562f, 0.976562f, 0.975098f, 0.000240f, 0.000120f, 0.000281f, 0.000333f, 0.000498f, 0.000680f, 0.000684f, 0.001083f,
+ 0.001312f, 0.001618f, 0.001606f, 0.001834f, 0.002087f, 0.002316f, 0.002735f, 0.002792f, 0.003084f, 0.003386f, 0.003944f, 0.004353f,
+ 0.004761f, 0.005390f, 0.005997f, 0.006615f, 0.007389f, 0.008324f, 0.008987f, 0.010284f, 0.011703f, 0.013382f, 0.014717f, 0.016953f,
+ 0.019424f, 0.022278f, 0.026047f, 0.030029f, 0.035492f, 0.042145f, 0.050446f, 0.060608f, 0.073975f, 0.091187f, 0.113831f, 0.142700f,
+ 0.180176f, 0.228271f, 0.288086f, 0.359131f, 0.437988f, 0.519531f, 0.600098f, 0.673340f, 0.735352f, 0.787598f, 0.830566f, 0.865234f,
+ 0.891602f, 0.913086f, 0.971680f, 0.974121f, 0.974121f, 0.974121f, 0.974121f, 0.974609f, 0.000000f, 0.000239f, 0.000236f, 0.000425f,
+ 0.000487f, 0.000608f, 0.000850f, 0.001012f, 0.001140f, 0.001260f, 0.001410f, 0.001640f, 0.001953f, 0.002003f, 0.002342f, 0.002434f,
+ 0.002686f, 0.002934f, 0.003305f, 0.003771f, 0.004169f, 0.004692f, 0.005028f, 0.005817f, 0.006371f, 0.007179f, 0.007919f, 0.008965f,
+ 0.009857f, 0.011261f, 0.012703f, 0.014229f, 0.016312f, 0.018494f, 0.021744f, 0.025024f, 0.029633f, 0.034790f, 0.041199f, 0.049561f,
+ 0.060242f, 0.073608f, 0.091675f, 0.114502f, 0.144897f, 0.185547f, 0.236328f, 0.300049f, 0.375732f, 0.458496f, 0.542969f, 0.624023f,
+ 0.696289f, 0.758301f, 0.808105f, 0.847656f, 0.879395f, 0.903809f, 0.968750f, 0.971191f, 0.972168f, 0.971680f, 0.972168f, 0.971680f,
+ 0.000000f, 0.000217f, 0.000235f, 0.000235f, 0.000321f, 0.000560f, 0.000588f, 0.000897f, 0.001034f, 0.001040f, 0.001246f, 0.001369f,
+ 0.001611f, 0.001692f, 0.001942f, 0.002153f, 0.002337f, 0.002638f, 0.002878f, 0.003330f, 0.003672f, 0.003986f, 0.004498f, 0.004826f,
+ 0.005535f, 0.006176f, 0.006561f, 0.007538f, 0.008362f, 0.009544f, 0.010612f, 0.011879f, 0.013794f, 0.015839f, 0.018326f, 0.020889f,
+ 0.024567f, 0.028625f, 0.033783f, 0.040527f, 0.049133f, 0.059998f, 0.073608f, 0.092041f, 0.116394f, 0.148682f, 0.191528f, 0.246582f,
+ 0.315186f, 0.395508f, 0.482910f, 0.570312f, 0.651367f, 0.722168f, 0.781738f, 0.828613f, 0.866211f, 0.895508f, 0.966797f, 0.968750f,
+ 0.969238f, 0.969727f, 0.969238f, 0.969238f, 0.000000f, 0.000108f, 0.000215f, 0.000346f, 0.000352f, 0.000501f, 0.000783f, 0.000828f,
+ 0.000954f, 0.000980f, 0.001130f, 0.001353f, 0.001429f, 0.001522f, 0.001690f, 0.001760f, 0.002172f, 0.002363f, 0.002522f, 0.002777f,
+ 0.003202f, 0.003550f, 0.004040f, 0.004364f, 0.004734f, 0.005192f, 0.005909f, 0.006271f, 0.007015f, 0.007957f, 0.008774f, 0.010185f,
+ 0.011681f, 0.013306f, 0.015327f, 0.017517f, 0.020264f, 0.023636f, 0.027740f, 0.033234f, 0.039856f, 0.048340f, 0.059387f, 0.074097f,
+ 0.093567f, 0.118896f, 0.153931f, 0.200073f, 0.260254f, 0.334473f, 0.420410f, 0.511719f, 0.601562f, 0.682129f, 0.750488f, 0.807617f,
+ 0.851074f, 0.884277f, 0.963867f, 0.966309f, 0.966797f, 0.966797f, 0.966797f, 0.966797f, 0.000000f, 0.000059f, 0.000292f, 0.000331f,
+ 0.000344f, 0.000613f, 0.000532f, 0.000703f, 0.000853f, 0.000915f, 0.000936f, 0.001102f, 0.001284f, 0.001430f, 0.001417f, 0.001475f,
+ 0.001791f, 0.001989f, 0.002161f, 0.002388f, 0.002775f, 0.003017f, 0.003357f, 0.003763f, 0.004124f, 0.004383f, 0.004917f, 0.005436f,
+ 0.005840f, 0.006733f, 0.007511f, 0.008667f, 0.009567f, 0.011032f, 0.012474f, 0.014610f, 0.016739f, 0.019379f, 0.022873f, 0.027252f,
+ 0.032410f, 0.039062f, 0.048065f, 0.059296f, 0.074646f, 0.094971f, 0.123108f, 0.161011f, 0.211426f, 0.277344f, 0.358154f, 0.450195f,
+ 0.545410f, 0.636230f, 0.715332f, 0.781250f, 0.832520f, 0.872070f, 0.960449f, 0.962402f, 0.963867f, 0.963379f, 0.962891f, 0.963379f,
+ 0.000000f, 0.000000f, 0.000098f, 0.000301f, 0.000315f, 0.000566f, 0.000587f, 0.000627f, 0.000643f, 0.000795f, 0.000974f, 0.001023f,
+ 0.000987f, 0.001031f, 0.001245f, 0.001470f, 0.001637f, 0.001820f, 0.001884f, 0.002146f, 0.002357f, 0.002630f, 0.002913f, 0.003164f,
+ 0.003380f, 0.003824f, 0.004189f, 0.004353f, 0.004940f, 0.005688f, 0.006409f, 0.007347f, 0.008018f, 0.009163f, 0.010559f, 0.012039f,
+ 0.013695f, 0.016144f, 0.018723f, 0.022354f, 0.026337f, 0.031433f, 0.038818f, 0.047546f, 0.059662f, 0.075623f, 0.097473f, 0.127808f,
+ 0.169556f, 0.225830f, 0.299072f, 0.387451f, 0.486084f, 0.583984f, 0.674805f, 0.751465f, 0.812012f, 0.859375f, 0.957031f, 0.958984f,
+ 0.959473f, 0.959961f, 0.959961f, 0.959961f, 0.000000f, 0.000000f, 0.000004f, 0.000078f, 0.000408f, 0.000432f, 0.000563f, 0.000560f,
+ 0.000566f, 0.000623f, 0.000782f, 0.000829f, 0.000896f, 0.000956f, 0.001056f, 0.001249f, 0.001414f, 0.001473f, 0.001646f, 0.001764f,
+ 0.002066f, 0.002230f, 0.002436f, 0.002651f, 0.003012f, 0.003252f, 0.003414f, 0.004055f, 0.004143f, 0.004784f, 0.005356f, 0.006077f,
+ 0.006870f, 0.007538f, 0.008728f, 0.009834f, 0.011322f, 0.013130f, 0.015427f, 0.017914f, 0.021271f, 0.025436f, 0.030960f, 0.038086f,
+ 0.047485f, 0.060303f, 0.077087f, 0.101196f, 0.134521f, 0.180786f, 0.244507f, 0.326172f, 0.423584f, 0.527832f, 0.628418f, 0.716797f,
+ 0.788086f, 0.843262f, 0.953125f, 0.955566f, 0.955566f, 0.956543f, 0.956055f, 0.956543f, 0.000000f, 0.000000f, 0.000000f, 0.000236f,
+ 0.000320f, 0.000484f, 0.000521f, 0.000549f, 0.000556f, 0.000584f, 0.000574f, 0.000690f, 0.000758f, 0.000841f, 0.001003f, 0.001013f,
+ 0.001169f, 0.001292f, 0.001437f, 0.001658f, 0.001830f, 0.002001f, 0.002081f, 0.002146f, 0.002434f, 0.002712f, 0.002964f, 0.003220f,
+ 0.003513f, 0.003963f, 0.004410f, 0.004875f, 0.005608f, 0.006245f, 0.007179f, 0.008118f, 0.009201f, 0.010582f, 0.012360f, 0.014343f,
+ 0.016968f, 0.020401f, 0.024628f, 0.030365f, 0.037567f, 0.047455f, 0.060913f, 0.079529f, 0.105774f, 0.143555f, 0.196167f, 0.268799f,
+ 0.361084f, 0.467041f, 0.576172f, 0.676758f, 0.760254f, 0.825195f, 0.948242f, 0.951660f, 0.951660f, 0.951660f, 0.951660f, 0.951660f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000257f, 0.000334f, 0.000390f, 0.000496f, 0.000520f, 0.000539f, 0.000590f, 0.000602f,
+ 0.000646f, 0.000725f, 0.000909f, 0.000949f, 0.001023f, 0.001121f, 0.001181f, 0.001308f, 0.001474f, 0.001457f, 0.001714f, 0.002007f,
+ 0.001929f, 0.002039f, 0.002468f, 0.002672f, 0.003025f, 0.003317f, 0.003635f, 0.004047f, 0.004433f, 0.004864f, 0.005756f, 0.006493f,
+ 0.007515f, 0.008331f, 0.009697f, 0.011383f, 0.014000f, 0.016235f, 0.019653f, 0.024185f, 0.029465f, 0.037109f, 0.047699f, 0.062164f,
+ 0.082642f, 0.112488f, 0.155151f, 0.216919f, 0.300049f, 0.404541f, 0.520020f, 0.631836f, 0.728516f, 0.805664f, 0.943848f, 0.946289f,
+ 0.946777f, 0.946777f, 0.947266f, 0.947266f, 0.000000f, 0.000000f, 0.000122f, 0.000088f, 0.000219f, 0.000229f, 0.000355f, 0.000414f,
+ 0.000482f, 0.000545f, 0.000559f, 0.000568f, 0.000481f, 0.000668f, 0.000636f, 0.000728f, 0.000924f, 0.000980f, 0.001017f, 0.001109f,
+ 0.001258f, 0.001353f, 0.001451f, 0.001564f, 0.001621f, 0.001740f, 0.002066f, 0.002289f, 0.002459f, 0.002621f, 0.002975f, 0.003349f,
+ 0.003588f, 0.003998f, 0.004723f, 0.005116f, 0.006035f, 0.006859f, 0.007957f, 0.009064f, 0.010658f, 0.012711f, 0.015511f, 0.018555f,
+ 0.023026f, 0.028854f, 0.037140f, 0.048035f, 0.064026f, 0.086914f, 0.121033f, 0.171387f, 0.244141f, 0.341797f, 0.458740f, 0.580078f,
+ 0.691895f, 0.780762f, 0.937988f, 0.940430f, 0.941406f, 0.940918f, 0.941895f, 0.941406f, 0.000000f, 0.000000f, 0.000000f, 0.000080f,
+ 0.000211f, 0.000221f, 0.000225f, 0.000192f, 0.000352f, 0.000368f, 0.000397f, 0.000529f, 0.000510f, 0.000504f, 0.000540f, 0.000671f,
+ 0.000694f, 0.000763f, 0.000902f, 0.000998f, 0.001063f, 0.001074f, 0.001128f, 0.001407f, 0.001370f, 0.001449f, 0.001682f, 0.001635f,
+ 0.001976f, 0.002108f, 0.002335f, 0.002558f, 0.002905f, 0.003176f, 0.003637f, 0.003948f, 0.004650f, 0.005341f, 0.006237f, 0.007034f,
+ 0.008415f, 0.009811f, 0.012032f, 0.014565f, 0.017731f, 0.022324f, 0.028427f, 0.036713f, 0.048859f, 0.066406f, 0.092957f, 0.133057f,
+ 0.193848f, 0.281250f, 0.395508f, 0.524902f, 0.648926f, 0.754395f, 0.931152f, 0.934570f, 0.934570f, 0.934570f, 0.935547f, 0.935059f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000181f, 0.000196f, 0.000236f, 0.000250f, 0.000226f, 0.000281f, 0.000335f, 0.000457f,
+ 0.000406f, 0.000511f, 0.000522f, 0.000593f, 0.000539f, 0.000663f, 0.000661f, 0.000779f, 0.000978f, 0.000855f, 0.000937f, 0.001128f,
+ 0.001163f, 0.001253f, 0.001241f, 0.001531f, 0.001595f, 0.001796f, 0.001888f, 0.002226f, 0.002350f, 0.002609f, 0.002787f, 0.003260f,
+ 0.003656f, 0.004303f, 0.004910f, 0.005577f, 0.006683f, 0.007603f, 0.009102f, 0.011017f, 0.013603f, 0.016968f, 0.021652f, 0.027939f,
+ 0.037109f, 0.050262f, 0.070374f, 0.101624f, 0.150391f, 0.225220f, 0.331543f, 0.463867f, 0.601074f, 0.723145f, 0.923828f, 0.927246f,
+ 0.927246f, 0.928223f, 0.927734f, 0.928223f, 0.000000f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000174f, 0.000156f, 0.000204f,
+ 0.000180f, 0.000221f, 0.000246f, 0.000346f, 0.000313f, 0.000426f, 0.000468f, 0.000482f, 0.000559f, 0.000582f, 0.000536f, 0.000611f,
+ 0.000770f, 0.000666f, 0.000919f, 0.000947f, 0.001013f, 0.000948f, 0.001129f, 0.001169f, 0.001463f, 0.001579f, 0.001540f, 0.001555f,
+ 0.001888f, 0.002007f, 0.002390f, 0.002623f, 0.002708f, 0.003235f, 0.003584f, 0.004223f, 0.005001f, 0.005791f, 0.006905f, 0.008118f,
+ 0.010117f, 0.012512f, 0.015961f, 0.020798f, 0.027374f, 0.037628f, 0.052673f, 0.076172f, 0.114197f, 0.175659f, 0.270752f, 0.399658f,
+ 0.546875f, 0.687012f, 0.915527f, 0.918457f, 0.919434f, 0.919434f, 0.919434f, 0.919434f, 0.000000f, 0.000000f, 0.000121f, 0.000121f,
+ 0.000121f, 0.000120f, 0.000139f, 0.000141f, 0.000152f, 0.000186f, 0.000209f, 0.000222f, 0.000297f, 0.000330f, 0.000367f, 0.000403f,
+ 0.000433f, 0.000456f, 0.000457f, 0.000484f, 0.000521f, 0.000544f, 0.000594f, 0.000807f, 0.000790f, 0.000841f, 0.000784f, 0.001025f,
+ 0.001112f, 0.001014f, 0.001146f, 0.001287f, 0.001485f, 0.001541f, 0.001740f, 0.002014f, 0.002264f, 0.002460f, 0.002825f, 0.003124f,
+ 0.003683f, 0.004177f, 0.005024f, 0.006004f, 0.007454f, 0.009041f, 0.011833f, 0.014839f, 0.019791f, 0.027283f, 0.038361f, 0.055817f,
+ 0.084656f, 0.133057f, 0.213013f, 0.334717f, 0.488770f, 0.645996f, 0.905762f, 0.909668f, 0.909668f, 0.909180f, 0.910645f, 0.908691f,
+ 0.000000f, 0.000000f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000119f, 0.000115f, 0.000104f, 0.000105f, 0.000203f, 0.000235f,
+ 0.000185f, 0.000290f, 0.000201f, 0.000306f, 0.000259f, 0.000370f, 0.000401f, 0.000428f, 0.000596f, 0.000617f, 0.000474f, 0.000593f,
+ 0.000641f, 0.000676f, 0.000682f, 0.000826f, 0.000897f, 0.000934f, 0.000972f, 0.000972f, 0.001213f, 0.001281f, 0.001410f, 0.001451f,
+ 0.001562f, 0.001786f, 0.002031f, 0.002417f, 0.002764f, 0.003162f, 0.003763f, 0.004406f, 0.005310f, 0.006454f, 0.008156f, 0.010849f,
+ 0.014305f, 0.019318f, 0.027328f, 0.039856f, 0.061310f, 0.097717f, 0.162354f, 0.270752f, 0.424805f, 0.599609f, 0.894043f, 0.897949f,
+ 0.898438f, 0.898438f, 0.898926f, 0.898438f, 0.000000f, 0.000121f, 0.000121f, 0.000120f, 0.000119f, 0.000119f, 0.000118f, 0.000118f,
+ 0.000112f, 0.000102f, 0.000094f, 0.000109f, 0.000131f, 0.000145f, 0.000232f, 0.000171f, 0.000278f, 0.000230f, 0.000347f, 0.000331f,
+ 0.000379f, 0.000381f, 0.000512f, 0.000427f, 0.000541f, 0.000566f, 0.000547f, 0.000613f, 0.000706f, 0.000660f, 0.000809f, 0.000941f,
+ 0.000950f, 0.001035f, 0.001069f, 0.001220f, 0.001149f, 0.001314f, 0.001603f, 0.001801f, 0.002062f, 0.002394f, 0.002737f, 0.003057f,
+ 0.003771f, 0.004471f, 0.005875f, 0.007217f, 0.009651f, 0.013344f, 0.018829f, 0.027710f, 0.043091f, 0.069214f, 0.119141f, 0.210571f,
+ 0.358398f, 0.544922f, 0.881348f, 0.883789f, 0.885254f, 0.885742f, 0.885254f, 0.885254f, 0.000000f, 0.000121f, 0.000120f, 0.000119f,
+ 0.000119f, 0.000118f, 0.000117f, 0.000116f, 0.000116f, 0.000110f, 0.000101f, 0.000094f, 0.000087f, 0.000157f, 0.000151f, 0.000168f,
+ 0.000146f, 0.000219f, 0.000214f, 0.000261f, 0.000313f, 0.000363f, 0.000311f, 0.000415f, 0.000476f, 0.000448f, 0.000429f, 0.000460f,
+ 0.000481f, 0.000560f, 0.000544f, 0.000695f, 0.000626f, 0.000789f, 0.000877f, 0.000894f, 0.000948f, 0.001177f, 0.001175f, 0.001366f,
+ 0.001487f, 0.001738f, 0.002008f, 0.002304f, 0.002663f, 0.003250f, 0.004002f, 0.004932f, 0.006416f, 0.008636f, 0.012344f, 0.018127f,
+ 0.028610f, 0.047150f, 0.083923f, 0.156860f, 0.291260f, 0.487305f, 0.866211f, 0.869141f, 0.870605f, 0.870117f, 0.871094f, 0.870117f,
+ 0.000000f, 0.000000f, 0.000119f, 0.000118f, 0.000117f, 0.000116f, 0.000115f, 0.000115f, 0.000114f, 0.000114f, 0.000109f, 0.000101f,
+ 0.000094f, 0.000087f, 0.000081f, 0.000085f, 0.000129f, 0.000150f, 0.000176f, 0.000193f, 0.000216f, 0.000257f, 0.000241f, 0.000302f,
+ 0.000259f, 0.000299f, 0.000397f, 0.000403f, 0.000384f, 0.000402f, 0.000425f, 0.000582f, 0.000467f, 0.000614f, 0.000660f, 0.000625f,
+ 0.000650f, 0.000819f, 0.000790f, 0.000879f, 0.001001f, 0.001140f, 0.001403f, 0.001555f, 0.001844f, 0.002213f, 0.002636f, 0.003235f,
+ 0.004082f, 0.005604f, 0.007896f, 0.011292f, 0.018005f, 0.030472f, 0.055786f, 0.109985f, 0.224976f, 0.421875f, 0.848145f, 0.852539f,
+ 0.853027f, 0.852539f, 0.852539f, 0.853027f, 0.000000f, 0.000119f, 0.000118f, 0.000116f, 0.000115f, 0.000114f, 0.000113f, 0.000112f,
+ 0.000111f, 0.000111f, 0.000110f, 0.000108f, 0.000101f, 0.000094f, 0.000088f, 0.000082f, 0.000077f, 0.000109f, 0.000068f, 0.000102f,
+ 0.000127f, 0.000158f, 0.000177f, 0.000192f, 0.000207f, 0.000214f, 0.000249f, 0.000278f, 0.000296f, 0.000320f, 0.000330f, 0.000342f,
+ 0.000415f, 0.000371f, 0.000389f, 0.000508f, 0.000463f, 0.000586f, 0.000606f, 0.000649f, 0.000724f, 0.000841f, 0.000910f, 0.001065f,
+ 0.001236f, 0.001475f, 0.001807f, 0.002138f, 0.002716f, 0.003622f, 0.004921f, 0.006950f, 0.010574f, 0.018433f, 0.034607f, 0.072449f,
+ 0.163818f, 0.352295f, 0.827637f, 0.831055f, 0.831543f, 0.832031f, 0.833008f, 0.832520f, 0.000120f, 0.000116f, 0.000114f, 0.000113f,
+ 0.000111f, 0.000110f, 0.000109f, 0.000108f, 0.000107f, 0.000106f, 0.000106f, 0.000105f, 0.000104f, 0.000101f, 0.000094f, 0.000088f,
+ 0.000083f, 0.000078f, 0.000073f, 0.000092f, 0.000064f, 0.000097f, 0.000073f, 0.000105f, 0.000125f, 0.000162f, 0.000179f, 0.000177f,
+ 0.000191f, 0.000221f, 0.000241f, 0.000235f, 0.000270f, 0.000277f, 0.000287f, 0.000329f, 0.000319f, 0.000428f, 0.000417f, 0.000409f,
+ 0.000524f, 0.000537f, 0.000612f, 0.000750f, 0.000770f, 0.000961f, 0.001153f, 0.001347f, 0.001702f, 0.002081f, 0.002903f, 0.003956f,
+ 0.006184f, 0.010368f, 0.019592f, 0.043427f, 0.109924f, 0.280518f, 0.803223f, 0.806152f, 0.807617f, 0.808594f, 0.809082f, 0.808105f,
+ 0.000000f, 0.000111f, 0.000106f, 0.000107f, 0.000104f, 0.000103f, 0.000101f, 0.000101f, 0.000101f, 0.000100f, 0.000099f, 0.000098f,
+ 0.000097f, 0.000097f, 0.000097f, 0.000094f, 0.000088f, 0.000083f, 0.000078f, 0.000073f, 0.000069f, 0.000070f, 0.000061f, 0.000068f,
+ 0.000059f, 0.000067f, 0.000084f, 0.000097f, 0.000128f, 0.000137f, 0.000165f, 0.000160f, 0.000176f, 0.000185f, 0.000217f, 0.000239f,
+ 0.000237f, 0.000238f, 0.000272f, 0.000281f, 0.000314f, 0.000372f, 0.000395f, 0.000430f, 0.000504f, 0.000578f, 0.000665f, 0.000856f,
+ 0.000969f, 0.001210f, 0.001594f, 0.002216f, 0.003370f, 0.005527f, 0.010170f, 0.023239f, 0.066101f, 0.207275f, 0.775391f, 0.779785f,
+ 0.780273f, 0.780762f, 0.780273f, 0.780762f, 0.000000f, 0.000094f, 0.000097f, 0.000095f, 0.000092f, 0.000091f, 0.000091f, 0.000090f,
+ 0.000089f, 0.000089f, 0.000088f, 0.000088f, 0.000087f, 0.000086f, 0.000087f, 0.000086f, 0.000086f, 0.000085f, 0.000081f, 0.000076f,
+ 0.000072f, 0.000068f, 0.000064f, 0.000060f, 0.000057f, 0.000054f, 0.000058f, 0.000048f, 0.000048f, 0.000069f, 0.000068f, 0.000092f,
+ 0.000110f, 0.000122f, 0.000133f, 0.000136f, 0.000146f, 0.000154f, 0.000175f, 0.000194f, 0.000204f, 0.000206f, 0.000238f, 0.000262f,
+ 0.000266f, 0.000338f, 0.000361f, 0.000432f, 0.000527f, 0.000659f, 0.000848f, 0.001183f, 0.001713f, 0.002661f, 0.004921f, 0.010887f,
+ 0.033936f, 0.138428f, 0.743652f, 0.747559f, 0.748047f, 0.748535f, 0.749512f, 0.749023f, 0.000045f, 0.000047f, 0.000059f, 0.000059f,
+ 0.000063f, 0.000068f, 0.000068f, 0.000068f, 0.000067f, 0.000069f, 0.000068f, 0.000070f, 0.000070f, 0.000070f, 0.000071f, 0.000070f,
+ 0.000071f, 0.000071f, 0.000071f, 0.000071f, 0.000071f, 0.000069f, 0.000065f, 0.000062f, 0.000058f, 0.000055f, 0.000052f, 0.000049f,
+ 0.000046f, 0.000044f, 0.000041f, 0.000050f, 0.000051f, 0.000048f, 0.000061f, 0.000070f, 0.000084f, 0.000095f, 0.000107f, 0.000104f,
+ 0.000111f, 0.000128f, 0.000143f, 0.000154f, 0.000157f, 0.000186f, 0.000198f, 0.000216f, 0.000268f, 0.000315f, 0.000414f, 0.000537f,
+ 0.000735f, 0.001149f, 0.002075f, 0.004669f, 0.014175f, 0.077881f, 0.707031f, 0.710449f, 0.712402f, 0.711914f, 0.712891f, 0.712402f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000012f, 0.000013f, 0.000029f, 0.000028f, 0.000037f, 0.000035f, 0.000039f,
+ 0.000043f, 0.000043f, 0.000045f, 0.000045f, 0.000048f, 0.000048f, 0.000050f, 0.000051f, 0.000052f, 0.000052f, 0.000053f, 0.000054f,
+ 0.000054f, 0.000053f, 0.000050f, 0.000048f, 0.000045f, 0.000043f, 0.000040f, 0.000038f, 0.000036f, 0.000034f, 0.000032f, 0.000030f,
+ 0.000028f, 0.000030f, 0.000038f, 0.000043f, 0.000057f, 0.000069f, 0.000072f, 0.000073f, 0.000082f, 0.000095f, 0.000101f, 0.000099f,
+ 0.000116f, 0.000130f, 0.000184f, 0.000211f, 0.000301f, 0.000443f, 0.000737f, 0.001601f, 0.004978f, 0.032593f, 0.666504f, 0.669922f,
+ 0.669922f, 0.672363f, 0.670898f, 0.670410f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000010f, 0.000012f, 0.000015f, 0.000018f, 0.000021f,
+ 0.000022f, 0.000023f, 0.000025f, 0.000028f, 0.000029f, 0.000029f, 0.000031f, 0.000033f, 0.000033f, 0.000035f, 0.000035f, 0.000035f,
+ 0.000033f, 0.000031f, 0.000029f, 0.000028f, 0.000026f, 0.000024f, 0.000023f, 0.000021f, 0.000020f, 0.000019f, 0.000022f, 0.000022f,
+ 0.000030f, 0.000038f, 0.000042f, 0.000041f, 0.000052f, 0.000047f, 0.000064f, 0.000072f, 0.000078f, 0.000129f, 0.000201f, 0.000382f,
+ 0.001180f, 0.009117f, 0.620605f, 0.624512f, 0.625000f, 0.625000f, 0.625000f, 0.625488f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000003f, 0.000005f, 0.000007f, 0.000008f, 0.000010f, 0.000011f, 0.000012f, 0.000014f, 0.000016f, 0.000016f, 0.000018f, 0.000017f,
+ 0.000016f, 0.000015f, 0.000014f, 0.000013f, 0.000012f, 0.000011f, 0.000010f, 0.000009f, 0.000011f, 0.000014f, 0.000018f, 0.000018f,
+ 0.000021f, 0.000028f, 0.000035f, 0.000053f, 0.000136f, 0.001152f, 0.571777f, 0.575684f, 0.575684f, 0.576172f, 0.576660f, 0.576660f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f,
+ 0.000002f, 0.000004f, 0.000004f, 0.000004f, 0.000003f, 0.000003f, 0.000002f, 0.000004f, 0.000003f, 0.000011f, 0.520020f, 0.523926f,
+ 0.524902f, 0.524902f, 0.524902f, 0.524902f,
+ },
+ {
+ 0.119934f, 0.328857f, 0.480713f, 0.586914f, 0.663086f, 0.717773f, 0.759766f, 0.791504f, 0.818359f, 0.838867f, 0.856934f, 0.871094f,
+ 0.883301f, 0.894043f, 0.902832f, 0.911621f, 0.917969f, 0.924805f, 0.930664f, 0.936035f, 0.939941f, 0.944824f, 0.948242f, 0.951660f,
+ 0.954590f, 0.958008f, 0.961426f, 0.962891f, 0.966309f, 0.967285f, 0.970215f, 0.972656f, 0.973633f, 0.975586f, 0.977539f, 0.978516f,
+ 0.979980f, 0.981445f, 0.982910f, 0.984375f, 0.985352f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.990234f, 0.991699f, 0.992676f,
+ 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999512f, 0.999023f,
+ 0.999023f, 0.998535f, 0.998535f, 0.998047f, 0.046875f, 0.160400f, 0.286621f, 0.405518f, 0.507812f, 0.590820f, 0.656250f, 0.708008f,
+ 0.748535f, 0.781250f, 0.809082f, 0.830566f, 0.848633f, 0.864258f, 0.877441f, 0.888672f, 0.898926f, 0.906738f, 0.915039f, 0.921387f,
+ 0.928223f, 0.933105f, 0.937988f, 0.942871f, 0.946777f, 0.950684f, 0.954102f, 0.957031f, 0.959961f, 0.962402f, 0.965332f, 0.966797f,
+ 0.969727f, 0.971191f, 0.973145f, 0.975098f, 0.977539f, 0.978027f, 0.980469f, 0.981934f, 0.982910f, 0.984375f, 0.985352f, 0.986816f,
+ 0.987793f, 0.988770f, 0.989258f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.995605f, 0.996582f, 0.996582f,
+ 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.998535f, 0.998535f, 0.998047f, 0.023788f, 0.084473f, 0.163696f, 0.255615f,
+ 0.351807f, 0.445312f, 0.527832f, 0.597656f, 0.656738f, 0.703613f, 0.742676f, 0.775879f, 0.802734f, 0.824707f, 0.843262f, 0.858887f,
+ 0.873047f, 0.884766f, 0.895508f, 0.903809f, 0.913086f, 0.919434f, 0.925781f, 0.931641f, 0.937012f, 0.941406f, 0.945801f, 0.949707f,
+ 0.953125f, 0.956543f, 0.959473f, 0.962402f, 0.964844f, 0.967285f, 0.969238f, 0.972168f, 0.973633f, 0.975098f, 0.977539f, 0.979492f,
+ 0.980469f, 0.981445f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.988281f, 0.988770f, 0.989746f, 0.990723f, 0.992188f, 0.992676f,
+ 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.997559f, 0.998535f, 0.998535f, 0.998535f, 0.998047f, 0.998047f, 0.997559f,
+ 0.014595f, 0.050110f, 0.097717f, 0.158569f, 0.230347f, 0.311523f, 0.394531f, 0.473145f, 0.544922f, 0.606934f, 0.660645f, 0.705566f,
+ 0.743164f, 0.775391f, 0.800781f, 0.822266f, 0.841309f, 0.856934f, 0.870605f, 0.883301f, 0.894043f, 0.902832f, 0.911133f, 0.918945f,
+ 0.925293f, 0.931152f, 0.936035f, 0.941406f, 0.945801f, 0.949707f, 0.953125f, 0.956055f, 0.959473f, 0.962402f, 0.964844f, 0.967285f,
+ 0.970215f, 0.972168f, 0.974121f, 0.975098f, 0.977539f, 0.979004f, 0.980957f, 0.981934f, 0.983398f, 0.984375f, 0.985840f, 0.987305f,
+ 0.988281f, 0.989258f, 0.990723f, 0.991699f, 0.992676f, 0.993652f, 0.994629f, 0.995117f, 0.995605f, 0.996582f, 0.998535f, 0.998535f,
+ 0.998535f, 0.998047f, 0.998047f, 0.997559f, 0.009178f, 0.032379f, 0.062561f, 0.102417f, 0.151611f, 0.210938f, 0.279785f, 0.352783f,
+ 0.426758f, 0.496826f, 0.561035f, 0.618164f, 0.666992f, 0.708496f, 0.744141f, 0.773926f, 0.800781f, 0.821777f, 0.840820f, 0.856445f,
+ 0.870117f, 0.882324f, 0.893066f, 0.901855f, 0.910645f, 0.918457f, 0.925293f, 0.930176f, 0.935547f, 0.941406f, 0.946289f, 0.949707f,
+ 0.953125f, 0.956543f, 0.959961f, 0.962891f, 0.965332f, 0.967773f, 0.969727f, 0.972656f, 0.974121f, 0.976074f, 0.977539f, 0.979492f,
+ 0.981445f, 0.982422f, 0.984375f, 0.985840f, 0.986328f, 0.987793f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.994141f,
+ 0.994629f, 0.995605f, 0.998047f, 0.998047f, 0.998047f, 0.997559f, 0.997559f, 0.997559f, 0.006382f, 0.022430f, 0.042908f, 0.068970f,
+ 0.102844f, 0.144653f, 0.195557f, 0.253906f, 0.318848f, 0.386230f, 0.454590f, 0.518066f, 0.577148f, 0.628906f, 0.675293f, 0.714844f,
+ 0.748535f, 0.777344f, 0.802246f, 0.823730f, 0.841797f, 0.856934f, 0.871094f, 0.882812f, 0.893555f, 0.902832f, 0.911133f, 0.918457f,
+ 0.925293f, 0.930176f, 0.937012f, 0.940918f, 0.945801f, 0.950195f, 0.953613f, 0.957031f, 0.960449f, 0.963379f, 0.966309f, 0.968262f,
+ 0.970703f, 0.973145f, 0.974609f, 0.976562f, 0.978516f, 0.980469f, 0.981934f, 0.983398f, 0.984375f, 0.985840f, 0.988281f, 0.988770f,
+ 0.989746f, 0.990723f, 0.991699f, 0.992676f, 0.993652f, 0.994629f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997070f,
+ 0.004585f, 0.015961f, 0.030930f, 0.049133f, 0.072144f, 0.101013f, 0.137451f, 0.181519f, 0.232544f, 0.290039f, 0.352539f, 0.416748f,
+ 0.479736f, 0.538574f, 0.592773f, 0.641602f, 0.684570f, 0.723145f, 0.754395f, 0.782715f, 0.805176f, 0.825195f, 0.843750f, 0.859863f,
+ 0.872559f, 0.884766f, 0.895020f, 0.904297f, 0.912109f, 0.919922f, 0.926270f, 0.932129f, 0.937500f, 0.942383f, 0.946289f, 0.950195f,
+ 0.955078f, 0.958008f, 0.961426f, 0.964355f, 0.967285f, 0.969238f, 0.971680f, 0.974121f, 0.975586f, 0.977539f, 0.979492f, 0.980957f,
+ 0.982910f, 0.984375f, 0.985840f, 0.986328f, 0.988281f, 0.989746f, 0.990723f, 0.992188f, 0.992676f, 0.993164f, 0.997559f, 0.997559f,
+ 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.003483f, 0.012291f, 0.023209f, 0.036041f, 0.052429f, 0.073486f, 0.099182f, 0.131226f,
+ 0.169678f, 0.214844f, 0.266846f, 0.323242f, 0.383545f, 0.444580f, 0.503418f, 0.559082f, 0.609375f, 0.655762f, 0.695312f, 0.730957f,
+ 0.760254f, 0.788086f, 0.810059f, 0.829590f, 0.847168f, 0.862793f, 0.875488f, 0.886719f, 0.896973f, 0.906250f, 0.914551f, 0.921387f,
+ 0.927734f, 0.933594f, 0.938965f, 0.944336f, 0.948242f, 0.952148f, 0.956543f, 0.958984f, 0.961914f, 0.965332f, 0.968262f, 0.970703f,
+ 0.972656f, 0.974609f, 0.977051f, 0.979004f, 0.980469f, 0.981934f, 0.983887f, 0.985352f, 0.986328f, 0.987793f, 0.989746f, 0.990234f,
+ 0.991699f, 0.992676f, 0.996582f, 0.997070f, 0.997070f, 0.996582f, 0.996582f, 0.996094f, 0.002962f, 0.009613f, 0.017792f, 0.027481f,
+ 0.039429f, 0.055176f, 0.073914f, 0.096985f, 0.125610f, 0.159180f, 0.199707f, 0.246216f, 0.297607f, 0.353760f, 0.412842f, 0.470215f,
+ 0.526367f, 0.578613f, 0.626953f, 0.669434f, 0.707031f, 0.740723f, 0.769043f, 0.794922f, 0.814941f, 0.835449f, 0.851074f, 0.866699f,
+ 0.879395f, 0.890137f, 0.899902f, 0.909180f, 0.916992f, 0.924316f, 0.929688f, 0.936035f, 0.941406f, 0.945312f, 0.950195f, 0.953613f,
+ 0.957520f, 0.960938f, 0.963867f, 0.966797f, 0.969238f, 0.971680f, 0.974121f, 0.976562f, 0.979004f, 0.979980f, 0.981934f, 0.982910f,
+ 0.984375f, 0.986816f, 0.987793f, 0.988770f, 0.990234f, 0.991699f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996094f, 0.996094f,
+ 0.002077f, 0.007637f, 0.013802f, 0.021606f, 0.031006f, 0.042419f, 0.055969f, 0.073242f, 0.094055f, 0.119446f, 0.150513f, 0.186401f,
+ 0.228638f, 0.276123f, 0.328857f, 0.384277f, 0.440674f, 0.496338f, 0.549805f, 0.598633f, 0.644043f, 0.683594f, 0.719727f, 0.750977f,
+ 0.779297f, 0.802246f, 0.823730f, 0.840820f, 0.855957f, 0.871582f, 0.882324f, 0.893555f, 0.903809f, 0.911621f, 0.920410f, 0.926758f,
+ 0.932617f, 0.938477f, 0.943359f, 0.947754f, 0.953125f, 0.955566f, 0.959473f, 0.962402f, 0.965332f, 0.968262f, 0.970703f, 0.972656f,
+ 0.976074f, 0.977051f, 0.979492f, 0.981445f, 0.983398f, 0.984863f, 0.986328f, 0.987793f, 0.989258f, 0.990723f, 0.995605f, 0.996094f,
+ 0.996094f, 0.996094f, 0.996094f, 0.995605f, 0.002014f, 0.006035f, 0.011299f, 0.017410f, 0.024368f, 0.033020f, 0.043701f, 0.056458f,
+ 0.072205f, 0.091431f, 0.114807f, 0.141968f, 0.174316f, 0.213257f, 0.256836f, 0.306152f, 0.358887f, 0.413330f, 0.468018f, 0.520996f,
+ 0.572266f, 0.618652f, 0.661621f, 0.699707f, 0.732910f, 0.762695f, 0.788574f, 0.810547f, 0.830078f, 0.848145f, 0.862305f, 0.875977f,
+ 0.887695f, 0.898438f, 0.907227f, 0.915527f, 0.922852f, 0.929199f, 0.936035f, 0.940918f, 0.946289f, 0.950684f, 0.953613f, 0.958496f,
+ 0.960938f, 0.964355f, 0.967285f, 0.970215f, 0.972656f, 0.975586f, 0.977539f, 0.979492f, 0.980957f, 0.982910f, 0.984863f, 0.986328f,
+ 0.987793f, 0.988770f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.001496f, 0.005196f, 0.009201f, 0.013985f,
+ 0.019806f, 0.026413f, 0.034943f, 0.044647f, 0.056641f, 0.070923f, 0.088623f, 0.109680f, 0.135254f, 0.164795f, 0.200073f, 0.240845f,
+ 0.285645f, 0.335449f, 0.387939f, 0.441650f, 0.495850f, 0.546875f, 0.595215f, 0.639160f, 0.679199f, 0.715820f, 0.746582f, 0.774414f,
+ 0.798828f, 0.819824f, 0.837402f, 0.854492f, 0.869629f, 0.881348f, 0.893066f, 0.902832f, 0.912109f, 0.918945f, 0.926758f, 0.933105f,
+ 0.938477f, 0.943359f, 0.948730f, 0.952637f, 0.956055f, 0.960449f, 0.963379f, 0.966797f, 0.969238f, 0.972656f, 0.975098f, 0.977051f,
+ 0.979004f, 0.981445f, 0.982910f, 0.984375f, 0.986328f, 0.987305f, 0.994629f, 0.995605f, 0.995117f, 0.995117f, 0.995117f, 0.994629f,
+ 0.001187f, 0.004314f, 0.007740f, 0.011337f, 0.016373f, 0.021759f, 0.028198f, 0.035889f, 0.045197f, 0.056580f, 0.069946f, 0.085938f,
+ 0.105408f, 0.128784f, 0.155884f, 0.187866f, 0.225830f, 0.268066f, 0.315186f, 0.365479f, 0.418213f, 0.471680f, 0.522949f, 0.572754f,
+ 0.617676f, 0.659668f, 0.697754f, 0.730957f, 0.760742f, 0.787109f, 0.809570f, 0.830078f, 0.846680f, 0.862793f, 0.875488f, 0.888184f,
+ 0.898926f, 0.907715f, 0.916016f, 0.923340f, 0.930664f, 0.936523f, 0.941895f, 0.947754f, 0.951660f, 0.955566f, 0.959473f, 0.963867f,
+ 0.966309f, 0.969238f, 0.972168f, 0.974121f, 0.976562f, 0.979004f, 0.980957f, 0.982910f, 0.984863f, 0.986816f, 0.994141f, 0.994629f,
+ 0.994629f, 0.994629f, 0.994629f, 0.994141f, 0.001187f, 0.003733f, 0.006496f, 0.009918f, 0.013634f, 0.017899f, 0.023026f, 0.029343f,
+ 0.036621f, 0.045227f, 0.055786f, 0.068298f, 0.083740f, 0.101135f, 0.122314f, 0.147827f, 0.177612f, 0.212891f, 0.252686f, 0.297119f,
+ 0.345215f, 0.395996f, 0.448730f, 0.500488f, 0.550781f, 0.597656f, 0.641113f, 0.680664f, 0.716309f, 0.747559f, 0.774414f, 0.799316f,
+ 0.820312f, 0.838867f, 0.855957f, 0.870117f, 0.883301f, 0.894531f, 0.904785f, 0.913086f, 0.920898f, 0.928223f, 0.935059f, 0.940430f,
+ 0.945312f, 0.950684f, 0.955566f, 0.958496f, 0.962891f, 0.965820f, 0.968750f, 0.971680f, 0.974609f, 0.976562f, 0.978516f, 0.980957f,
+ 0.982910f, 0.984863f, 0.994141f, 0.994141f, 0.994629f, 0.994141f, 0.994141f, 0.994629f, 0.000998f, 0.003178f, 0.005444f, 0.008179f,
+ 0.011337f, 0.015091f, 0.019058f, 0.024368f, 0.029587f, 0.037140f, 0.045197f, 0.055115f, 0.066772f, 0.080688f, 0.097229f, 0.117371f,
+ 0.140869f, 0.169312f, 0.201538f, 0.238770f, 0.280762f, 0.326660f, 0.376709f, 0.427490f, 0.479248f, 0.530273f, 0.578613f, 0.623535f,
+ 0.664551f, 0.701660f, 0.733887f, 0.763672f, 0.790039f, 0.812500f, 0.832520f, 0.849121f, 0.865234f, 0.878906f, 0.890625f, 0.901367f,
+ 0.910645f, 0.919434f, 0.926758f, 0.933105f, 0.939453f, 0.944824f, 0.949707f, 0.954590f, 0.958008f, 0.961914f, 0.965332f, 0.968750f,
+ 0.971680f, 0.974121f, 0.977051f, 0.979004f, 0.980957f, 0.982910f, 0.993164f, 0.993164f, 0.994141f, 0.993652f, 0.993652f, 0.993164f,
+ 0.000948f, 0.002638f, 0.004784f, 0.007153f, 0.009590f, 0.012505f, 0.016388f, 0.020599f, 0.025299f, 0.031097f, 0.037323f, 0.045197f,
+ 0.054047f, 0.065002f, 0.078674f, 0.094055f, 0.112305f, 0.134399f, 0.160889f, 0.191040f, 0.226318f, 0.265869f, 0.310303f, 0.358154f,
+ 0.409180f, 0.459473f, 0.510254f, 0.559082f, 0.606445f, 0.648926f, 0.687500f, 0.722168f, 0.753418f, 0.781250f, 0.804199f, 0.825684f,
+ 0.843262f, 0.860840f, 0.874512f, 0.886719f, 0.898926f, 0.907227f, 0.916992f, 0.924805f, 0.932129f, 0.937988f, 0.943848f, 0.949219f,
+ 0.954102f, 0.958496f, 0.961426f, 0.965332f, 0.968750f, 0.972168f, 0.974609f, 0.977051f, 0.979492f, 0.981445f, 0.992188f, 0.993164f,
+ 0.993164f, 0.993164f, 0.993164f, 0.992676f, 0.000696f, 0.002352f, 0.004002f, 0.006138f, 0.008446f, 0.010826f, 0.013840f, 0.017258f,
+ 0.021194f, 0.025970f, 0.031128f, 0.037140f, 0.044281f, 0.053436f, 0.063660f, 0.076050f, 0.090271f, 0.107727f, 0.128662f, 0.152832f,
+ 0.182007f, 0.214111f, 0.252930f, 0.295166f, 0.341553f, 0.390625f, 0.442139f, 0.492676f, 0.541992f, 0.589844f, 0.633301f, 0.674316f,
+ 0.710938f, 0.743652f, 0.772461f, 0.796875f, 0.819824f, 0.839355f, 0.854980f, 0.870605f, 0.884277f, 0.895508f, 0.906738f, 0.915527f,
+ 0.923828f, 0.931152f, 0.937500f, 0.944336f, 0.949219f, 0.953613f, 0.958008f, 0.962402f, 0.965332f, 0.968750f, 0.972168f, 0.974609f,
+ 0.977051f, 0.979980f, 0.991211f, 0.992676f, 0.992188f, 0.992188f, 0.992188f, 0.992676f, 0.000838f, 0.002033f, 0.003664f, 0.005077f,
+ 0.007282f, 0.009415f, 0.011749f, 0.014931f, 0.017853f, 0.021606f, 0.025864f, 0.031219f, 0.037231f, 0.044464f, 0.052338f, 0.062500f,
+ 0.073853f, 0.087463f, 0.104065f, 0.123230f, 0.146362f, 0.173340f, 0.205078f, 0.240845f, 0.281982f, 0.326660f, 0.374756f, 0.425049f,
+ 0.476807f, 0.526855f, 0.574219f, 0.620117f, 0.662598f, 0.699219f, 0.733398f, 0.764160f, 0.791016f, 0.813965f, 0.833984f, 0.851074f,
+ 0.867676f, 0.880859f, 0.893555f, 0.904785f, 0.914062f, 0.922852f, 0.930176f, 0.937012f, 0.942383f, 0.948242f, 0.953125f, 0.957520f,
+ 0.962402f, 0.966309f, 0.969238f, 0.973145f, 0.975098f, 0.978027f, 0.991699f, 0.991699f, 0.992676f, 0.992188f, 0.991699f, 0.992188f,
+ 0.000600f, 0.001687f, 0.003023f, 0.004963f, 0.006405f, 0.008163f, 0.010368f, 0.012718f, 0.015480f, 0.018311f, 0.022064f, 0.026169f,
+ 0.031097f, 0.036926f, 0.043457f, 0.051392f, 0.060669f, 0.071350f, 0.084473f, 0.100220f, 0.118103f, 0.140259f, 0.166016f, 0.195679f,
+ 0.230469f, 0.269531f, 0.313232f, 0.360596f, 0.410156f, 0.460693f, 0.511719f, 0.560547f, 0.607422f, 0.650879f, 0.689941f, 0.724609f,
+ 0.756348f, 0.784180f, 0.808594f, 0.828613f, 0.847656f, 0.864258f, 0.879395f, 0.892090f, 0.903320f, 0.912598f, 0.921875f, 0.929688f,
+ 0.936523f, 0.942871f, 0.947754f, 0.953125f, 0.957520f, 0.961914f, 0.966309f, 0.969238f, 0.972656f, 0.975586f, 0.990234f, 0.991211f,
+ 0.991211f, 0.991699f, 0.991211f, 0.991211f, 0.000269f, 0.001538f, 0.002800f, 0.003868f, 0.005524f, 0.007179f, 0.008987f, 0.011063f,
+ 0.013084f, 0.015747f, 0.019211f, 0.022324f, 0.026474f, 0.031311f, 0.036530f, 0.042969f, 0.050201f, 0.059174f, 0.069641f, 0.081543f,
+ 0.096680f, 0.114075f, 0.134644f, 0.158691f, 0.187622f, 0.220581f, 0.258301f, 0.300781f, 0.347168f, 0.395996f, 0.447266f, 0.498291f,
+ 0.547852f, 0.595215f, 0.640625f, 0.680176f, 0.717285f, 0.749512f, 0.778320f, 0.803223f, 0.825684f, 0.845215f, 0.862793f, 0.877441f,
+ 0.890625f, 0.901855f, 0.912109f, 0.920898f, 0.929688f, 0.937012f, 0.942871f, 0.949707f, 0.954102f, 0.958496f, 0.962402f, 0.966309f,
+ 0.970215f, 0.974121f, 0.989746f, 0.990234f, 0.990723f, 0.990723f, 0.990723f, 0.990234f, 0.000341f, 0.001337f, 0.002573f, 0.003475f,
+ 0.004765f, 0.006329f, 0.007717f, 0.009499f, 0.011642f, 0.014107f, 0.016556f, 0.019470f, 0.022491f, 0.026169f, 0.030945f, 0.036011f,
+ 0.042389f, 0.049042f, 0.057678f, 0.067993f, 0.079468f, 0.093384f, 0.110046f, 0.129883f, 0.152710f, 0.180420f, 0.212158f, 0.248291f,
+ 0.289551f, 0.334961f, 0.383301f, 0.434570f, 0.485596f, 0.536133f, 0.584473f, 0.630371f, 0.671875f, 0.710449f, 0.743652f, 0.773926f,
+ 0.799316f, 0.823242f, 0.843262f, 0.860352f, 0.875977f, 0.889648f, 0.901367f, 0.911621f, 0.921387f, 0.929688f, 0.937012f, 0.943848f,
+ 0.950195f, 0.955078f, 0.959473f, 0.963379f, 0.967773f, 0.971191f, 0.988770f, 0.989746f, 0.990234f, 0.990234f, 0.990234f, 0.990234f,
+ 0.000564f, 0.001324f, 0.002092f, 0.003191f, 0.004471f, 0.005348f, 0.007069f, 0.008438f, 0.010201f, 0.011810f, 0.014297f, 0.016586f,
+ 0.019470f, 0.022644f, 0.026428f, 0.030579f, 0.035797f, 0.041718f, 0.048248f, 0.056213f, 0.065857f, 0.076782f, 0.090271f, 0.106262f,
+ 0.125122f, 0.147095f, 0.173462f, 0.204224f, 0.239746f, 0.279785f, 0.323730f, 0.372314f, 0.422607f, 0.474121f, 0.526367f, 0.575195f,
+ 0.621582f, 0.664062f, 0.703613f, 0.738770f, 0.769043f, 0.796387f, 0.820312f, 0.841797f, 0.858887f, 0.875488f, 0.889648f, 0.900879f,
+ 0.912598f, 0.921875f, 0.930664f, 0.937500f, 0.944336f, 0.950195f, 0.955566f, 0.959961f, 0.964844f, 0.968750f, 0.987305f, 0.989258f,
+ 0.989258f, 0.989258f, 0.989258f, 0.988770f, 0.000369f, 0.001128f, 0.001871f, 0.002792f, 0.003712f, 0.004723f, 0.006016f, 0.007542f,
+ 0.008896f, 0.010773f, 0.012421f, 0.014381f, 0.016632f, 0.019791f, 0.022354f, 0.025955f, 0.030609f, 0.035065f, 0.040924f, 0.047333f,
+ 0.055084f, 0.064209f, 0.075012f, 0.087769f, 0.102966f, 0.120911f, 0.142456f, 0.167358f, 0.197144f, 0.231812f, 0.270752f, 0.314209f,
+ 0.362549f, 0.412598f, 0.464844f, 0.515625f, 0.566895f, 0.614258f, 0.657715f, 0.698730f, 0.734863f, 0.766602f, 0.794922f, 0.818848f,
+ 0.839844f, 0.858887f, 0.875000f, 0.889648f, 0.901855f, 0.912598f, 0.922852f, 0.931152f, 0.938965f, 0.945312f, 0.951660f, 0.957520f,
+ 0.961426f, 0.966309f, 0.986816f, 0.988281f, 0.988281f, 0.988770f, 0.988281f, 0.988281f, 0.000466f, 0.000900f, 0.001792f, 0.002695f,
+ 0.003458f, 0.004204f, 0.005356f, 0.006512f, 0.007896f, 0.009300f, 0.010895f, 0.012459f, 0.014786f, 0.016739f, 0.019424f, 0.022461f,
+ 0.026062f, 0.029831f, 0.034851f, 0.039764f, 0.046417f, 0.053711f, 0.062164f, 0.072388f, 0.085205f, 0.099365f, 0.117004f, 0.137573f,
+ 0.162231f, 0.190674f, 0.224121f, 0.262451f, 0.305664f, 0.353027f, 0.403809f, 0.456055f, 0.508301f, 0.559082f, 0.608398f, 0.652832f,
+ 0.694824f, 0.731445f, 0.764160f, 0.793945f, 0.817871f, 0.839355f, 0.858398f, 0.875488f, 0.890137f, 0.902832f, 0.913574f, 0.923828f,
+ 0.932617f, 0.940918f, 0.946777f, 0.953613f, 0.958984f, 0.963379f, 0.985840f, 0.987305f, 0.987305f, 0.987793f, 0.987305f, 0.987305f,
+ 0.000234f, 0.001040f, 0.001661f, 0.002392f, 0.003101f, 0.003681f, 0.004944f, 0.005844f, 0.007065f, 0.008217f, 0.009247f, 0.010925f,
+ 0.012894f, 0.014549f, 0.017090f, 0.019455f, 0.022385f, 0.025650f, 0.029449f, 0.033936f, 0.039215f, 0.045135f, 0.052612f, 0.060944f,
+ 0.070312f, 0.082397f, 0.096924f, 0.113525f, 0.133179f, 0.156860f, 0.184814f, 0.217773f, 0.255127f, 0.298340f, 0.345215f, 0.395996f,
+ 0.448242f, 0.501953f, 0.553223f, 0.603516f, 0.649414f, 0.691895f, 0.729980f, 0.763184f, 0.792480f, 0.818359f, 0.841309f, 0.858887f,
+ 0.877441f, 0.891113f, 0.904785f, 0.915527f, 0.925781f, 0.933594f, 0.941895f, 0.949219f, 0.955566f, 0.960449f, 0.984863f, 0.985840f,
+ 0.986328f, 0.986816f, 0.986328f, 0.986816f, 0.000241f, 0.000808f, 0.001395f, 0.001986f, 0.002731f, 0.003429f, 0.004131f, 0.005402f,
+ 0.006077f, 0.007347f, 0.008522f, 0.009544f, 0.011345f, 0.013046f, 0.014534f, 0.016953f, 0.019241f, 0.022339f, 0.025208f, 0.029175f,
+ 0.033691f, 0.038300f, 0.044067f, 0.051331f, 0.059143f, 0.068726f, 0.080322f, 0.093567f, 0.109802f, 0.129883f, 0.152466f, 0.179810f,
+ 0.211792f, 0.249390f, 0.291748f, 0.338623f, 0.389404f, 0.442139f, 0.496338f, 0.548340f, 0.599121f, 0.645996f, 0.689941f, 0.728516f,
+ 0.762695f, 0.792969f, 0.818848f, 0.842285f, 0.862793f, 0.878906f, 0.894043f, 0.906250f, 0.917969f, 0.927734f, 0.935547f, 0.944336f,
+ 0.951172f, 0.957031f, 0.983398f, 0.985352f, 0.985840f, 0.985352f, 0.985840f, 0.985352f, 0.000340f, 0.000735f, 0.001377f, 0.001853f,
+ 0.002382f, 0.003159f, 0.004021f, 0.004642f, 0.005604f, 0.006340f, 0.007298f, 0.008591f, 0.009895f, 0.011154f, 0.012871f, 0.014580f,
+ 0.016876f, 0.019180f, 0.022141f, 0.024979f, 0.028748f, 0.032745f, 0.037964f, 0.043213f, 0.050171f, 0.057831f, 0.066833f, 0.078247f,
+ 0.091553f, 0.107178f, 0.125977f, 0.148315f, 0.175415f, 0.207153f, 0.244019f, 0.286377f, 0.333008f, 0.383789f, 0.437744f, 0.491943f,
+ 0.545410f, 0.597168f, 0.645508f, 0.688965f, 0.729004f, 0.764160f, 0.794434f, 0.821289f, 0.843750f, 0.864258f, 0.881348f, 0.895996f,
+ 0.909180f, 0.920898f, 0.929199f, 0.938965f, 0.946777f, 0.952637f, 0.982910f, 0.983887f, 0.984863f, 0.984863f, 0.984375f, 0.984863f,
+ 0.000236f, 0.000605f, 0.001135f, 0.001415f, 0.002329f, 0.002747f, 0.003551f, 0.004158f, 0.004723f, 0.005535f, 0.006687f, 0.007534f,
+ 0.008545f, 0.009979f, 0.011375f, 0.012993f, 0.014656f, 0.016754f, 0.018921f, 0.021759f, 0.024506f, 0.028183f, 0.032043f, 0.036743f,
+ 0.042236f, 0.048645f, 0.056030f, 0.065125f, 0.075928f, 0.089050f, 0.104370f, 0.122681f, 0.145142f, 0.171509f, 0.202759f, 0.239258f,
+ 0.281250f, 0.328369f, 0.379639f, 0.433838f, 0.489014f, 0.543945f, 0.596191f, 0.645020f, 0.690430f, 0.730957f, 0.766113f, 0.797852f,
+ 0.824219f, 0.846680f, 0.867188f, 0.884766f, 0.899414f, 0.912109f, 0.923828f, 0.933105f, 0.942383f, 0.949707f, 0.980957f, 0.982910f,
+ 0.983398f, 0.983398f, 0.983887f, 0.982910f, 0.000214f, 0.000710f, 0.001021f, 0.001429f, 0.001858f, 0.002607f, 0.003220f, 0.003738f,
+ 0.004459f, 0.005032f, 0.005726f, 0.006748f, 0.007748f, 0.008659f, 0.010002f, 0.011368f, 0.012985f, 0.014656f, 0.016525f, 0.018921f,
+ 0.021286f, 0.024231f, 0.027649f, 0.031464f, 0.035858f, 0.041321f, 0.047363f, 0.054840f, 0.063538f, 0.074097f, 0.086609f, 0.101990f,
+ 0.120117f, 0.141846f, 0.168213f, 0.199219f, 0.235352f, 0.277344f, 0.324707f, 0.376953f, 0.432373f, 0.488037f, 0.543457f, 0.597168f,
+ 0.646973f, 0.692871f, 0.732910f, 0.769531f, 0.801270f, 0.828125f, 0.850586f, 0.871582f, 0.888184f, 0.903809f, 0.915527f, 0.927246f,
+ 0.936523f, 0.946289f, 0.979492f, 0.981445f, 0.981934f, 0.982422f, 0.981934f, 0.981934f, 0.000000f, 0.000468f, 0.001076f, 0.001489f,
+ 0.002048f, 0.002413f, 0.002853f, 0.003468f, 0.003952f, 0.004444f, 0.005211f, 0.005917f, 0.006733f, 0.007763f, 0.008713f, 0.010262f,
+ 0.011368f, 0.012733f, 0.014458f, 0.016296f, 0.018478f, 0.021072f, 0.023666f, 0.026810f, 0.030746f, 0.035278f, 0.040131f, 0.046295f,
+ 0.053711f, 0.062195f, 0.072327f, 0.084717f, 0.099487f, 0.117371f, 0.139038f, 0.164795f, 0.195923f, 0.232422f, 0.274414f, 0.322266f,
+ 0.374756f, 0.431641f, 0.488525f, 0.545410f, 0.599121f, 0.650879f, 0.697754f, 0.738770f, 0.774414f, 0.806641f, 0.832520f, 0.856445f,
+ 0.875488f, 0.893555f, 0.907715f, 0.920410f, 0.931152f, 0.940918f, 0.978027f, 0.980469f, 0.980469f, 0.980957f, 0.980957f, 0.980957f,
+ 0.000279f, 0.000497f, 0.000763f, 0.001353f, 0.001794f, 0.002079f, 0.002451f, 0.002956f, 0.003498f, 0.004150f, 0.004589f, 0.005310f,
+ 0.006130f, 0.006958f, 0.007828f, 0.008888f, 0.009895f, 0.011124f, 0.012772f, 0.014282f, 0.016235f, 0.018127f, 0.020630f, 0.022873f,
+ 0.026321f, 0.029938f, 0.034241f, 0.039368f, 0.045319f, 0.052338f, 0.060852f, 0.070801f, 0.082947f, 0.097595f, 0.115051f, 0.136353f,
+ 0.162231f, 0.193481f, 0.229858f, 0.272217f, 0.321777f, 0.375000f, 0.432373f, 0.490479f, 0.548340f, 0.604004f, 0.655762f, 0.702637f,
+ 0.743652f, 0.780273f, 0.812500f, 0.838867f, 0.862305f, 0.881348f, 0.897949f, 0.912598f, 0.925293f, 0.935547f, 0.976562f, 0.978516f,
+ 0.979492f, 0.979980f, 0.979492f, 0.979004f, 0.000110f, 0.000473f, 0.000781f, 0.001262f, 0.001584f, 0.001890f, 0.002270f, 0.002607f,
+ 0.003241f, 0.003704f, 0.004055f, 0.004795f, 0.005356f, 0.005997f, 0.006760f, 0.007896f, 0.008896f, 0.009918f, 0.011200f, 0.012451f,
+ 0.013802f, 0.015556f, 0.017838f, 0.020065f, 0.022751f, 0.025864f, 0.029358f, 0.033600f, 0.038574f, 0.044342f, 0.050995f, 0.059296f,
+ 0.069214f, 0.081116f, 0.095459f, 0.113159f, 0.133911f, 0.160400f, 0.191406f, 0.228638f, 0.272217f, 0.321289f, 0.375732f, 0.434326f,
+ 0.493896f, 0.552734f, 0.609863f, 0.662109f, 0.709961f, 0.750977f, 0.787598f, 0.819336f, 0.846680f, 0.868164f, 0.887695f, 0.904297f,
+ 0.917969f, 0.930176f, 0.975098f, 0.977539f, 0.977051f, 0.977539f, 0.977539f, 0.977539f, 0.000242f, 0.000464f, 0.000831f, 0.001027f,
+ 0.001271f, 0.001722f, 0.001965f, 0.002243f, 0.002714f, 0.003036f, 0.003651f, 0.004025f, 0.004902f, 0.005638f, 0.006176f, 0.006943f,
+ 0.007763f, 0.008789f, 0.009804f, 0.010872f, 0.012070f, 0.013695f, 0.015381f, 0.017395f, 0.019608f, 0.022232f, 0.025009f, 0.028885f,
+ 0.032623f, 0.037659f, 0.043182f, 0.050018f, 0.058167f, 0.067810f, 0.079224f, 0.093811f, 0.111328f, 0.132324f, 0.158569f, 0.190063f,
+ 0.228149f, 0.271973f, 0.322510f, 0.378906f, 0.438477f, 0.499756f, 0.560059f, 0.618164f, 0.671387f, 0.718750f, 0.760742f, 0.796875f,
+ 0.826660f, 0.854492f, 0.875000f, 0.894531f, 0.911133f, 0.923828f, 0.973145f, 0.976074f, 0.975586f, 0.976074f, 0.976074f, 0.977051f,
+ 0.000242f, 0.000552f, 0.000701f, 0.001063f, 0.001186f, 0.001462f, 0.001690f, 0.002340f, 0.002703f, 0.002728f, 0.003325f, 0.003828f,
+ 0.004333f, 0.004913f, 0.005474f, 0.006077f, 0.006943f, 0.007607f, 0.008553f, 0.009460f, 0.010582f, 0.011871f, 0.013451f, 0.015091f,
+ 0.016983f, 0.019165f, 0.021637f, 0.024673f, 0.027863f, 0.031525f, 0.036713f, 0.041962f, 0.048615f, 0.056396f, 0.066162f, 0.077942f,
+ 0.092590f, 0.110046f, 0.130981f, 0.157593f, 0.189331f, 0.228394f, 0.273926f, 0.325684f, 0.383301f, 0.444580f, 0.507324f, 0.569824f,
+ 0.627441f, 0.682129f, 0.729980f, 0.770508f, 0.807129f, 0.837402f, 0.863281f, 0.884766f, 0.902832f, 0.917969f, 0.971191f, 0.973633f,
+ 0.974609f, 0.974121f, 0.974609f, 0.974609f, 0.000239f, 0.000239f, 0.000658f, 0.000899f, 0.001204f, 0.001252f, 0.001629f, 0.001815f,
+ 0.002470f, 0.002430f, 0.003134f, 0.003321f, 0.003925f, 0.004238f, 0.004856f, 0.005341f, 0.006161f, 0.006615f, 0.007511f, 0.008224f,
+ 0.009277f, 0.010445f, 0.011818f, 0.013046f, 0.014473f, 0.016510f, 0.018814f, 0.021057f, 0.023834f, 0.027237f, 0.030853f, 0.035675f,
+ 0.040894f, 0.047241f, 0.055145f, 0.064758f, 0.076782f, 0.090942f, 0.108398f, 0.130371f, 0.157104f, 0.189819f, 0.229248f, 0.276367f,
+ 0.329834f, 0.390137f, 0.453125f, 0.517578f, 0.580566f, 0.640625f, 0.694336f, 0.741699f, 0.782715f, 0.817871f, 0.848145f, 0.872559f,
+ 0.893555f, 0.910645f, 0.969727f, 0.971191f, 0.972656f, 0.972168f, 0.972168f, 0.972168f, 0.000222f, 0.000463f, 0.000620f, 0.000837f,
+ 0.000900f, 0.001048f, 0.001381f, 0.001820f, 0.001957f, 0.002329f, 0.002747f, 0.002964f, 0.003330f, 0.003986f, 0.004322f, 0.004677f,
+ 0.005302f, 0.005760f, 0.006569f, 0.007359f, 0.008141f, 0.009293f, 0.010101f, 0.011452f, 0.012779f, 0.014496f, 0.016144f, 0.018097f,
+ 0.020157f, 0.023148f, 0.026611f, 0.029785f, 0.034515f, 0.039856f, 0.046478f, 0.054016f, 0.063843f, 0.075378f, 0.089233f, 0.107666f,
+ 0.129639f, 0.156860f, 0.190674f, 0.231445f, 0.280518f, 0.336426f, 0.398193f, 0.463379f, 0.530273f, 0.595215f, 0.654785f, 0.708984f,
+ 0.755371f, 0.796875f, 0.831543f, 0.860352f, 0.883789f, 0.903809f, 0.966797f, 0.968750f, 0.969727f, 0.970215f, 0.970215f, 0.969727f,
+ 0.000000f, 0.000345f, 0.000464f, 0.000686f, 0.000782f, 0.001030f, 0.001139f, 0.001598f, 0.001846f, 0.002237f, 0.002489f, 0.002684f,
+ 0.003067f, 0.003344f, 0.003895f, 0.004158f, 0.004845f, 0.005131f, 0.005886f, 0.006561f, 0.007195f, 0.007912f, 0.008965f, 0.009941f,
+ 0.010956f, 0.012383f, 0.013893f, 0.015602f, 0.017303f, 0.019623f, 0.022156f, 0.025452f, 0.028976f, 0.033722f, 0.038910f, 0.045288f,
+ 0.052887f, 0.062561f, 0.074097f, 0.088623f, 0.106812f, 0.129639f, 0.157715f, 0.192261f, 0.235107f, 0.285889f, 0.344482f, 0.408691f,
+ 0.476807f, 0.545410f, 0.610840f, 0.671387f, 0.725098f, 0.771484f, 0.811035f, 0.843750f, 0.871582f, 0.894043f, 0.964355f, 0.967285f,
+ 0.967285f, 0.967773f, 0.967773f, 0.967773f, 0.000000f, 0.000320f, 0.000576f, 0.000572f, 0.000767f, 0.000945f, 0.001066f, 0.001375f,
+ 0.001848f, 0.001980f, 0.002190f, 0.002399f, 0.002695f, 0.002943f, 0.003397f, 0.003664f, 0.004063f, 0.004566f, 0.005119f, 0.005688f,
+ 0.006130f, 0.007057f, 0.007778f, 0.008675f, 0.009590f, 0.010666f, 0.011971f, 0.013443f, 0.015129f, 0.016953f, 0.018875f, 0.021576f,
+ 0.024658f, 0.028488f, 0.032959f, 0.037811f, 0.043793f, 0.051819f, 0.061371f, 0.073181f, 0.088257f, 0.106506f, 0.129883f, 0.159180f,
+ 0.195679f, 0.240479f, 0.293457f, 0.355225f, 0.422852f, 0.492432f, 0.563477f, 0.629883f, 0.690918f, 0.743652f, 0.789062f, 0.827148f,
+ 0.858398f, 0.884277f, 0.961914f, 0.964844f, 0.964355f, 0.964844f, 0.964355f, 0.965332f, 0.000000f, 0.000242f, 0.000435f, 0.000547f,
+ 0.000688f, 0.000803f, 0.001175f, 0.001318f, 0.001593f, 0.001652f, 0.001961f, 0.002209f, 0.002481f, 0.002716f, 0.002911f, 0.003210f,
+ 0.003595f, 0.004005f, 0.004490f, 0.004894f, 0.005508f, 0.006107f, 0.006714f, 0.007462f, 0.008438f, 0.009277f, 0.010170f, 0.011436f,
+ 0.012756f, 0.014145f, 0.016205f, 0.018433f, 0.020966f, 0.023819f, 0.027405f, 0.031464f, 0.036713f, 0.043152f, 0.050842f, 0.060577f,
+ 0.071960f, 0.087219f, 0.106689f, 0.130371f, 0.161377f, 0.199585f, 0.246948f, 0.303467f, 0.367920f, 0.439697f, 0.512207f, 0.584473f,
+ 0.651855f, 0.712402f, 0.764160f, 0.808105f, 0.844727f, 0.875000f, 0.958008f, 0.961426f, 0.961914f, 0.961914f, 0.962402f, 0.961914f,
+ 0.000000f, 0.000237f, 0.000266f, 0.000387f, 0.000557f, 0.000691f, 0.000774f, 0.001221f, 0.001455f, 0.001492f, 0.001769f, 0.001896f,
+ 0.002151f, 0.002386f, 0.002529f, 0.002911f, 0.003147f, 0.003523f, 0.003862f, 0.004311f, 0.004848f, 0.005260f, 0.005795f, 0.006416f,
+ 0.007114f, 0.007942f, 0.008667f, 0.009666f, 0.010818f, 0.012184f, 0.013718f, 0.015541f, 0.017685f, 0.020126f, 0.023056f, 0.026306f,
+ 0.030853f, 0.035797f, 0.042053f, 0.049683f, 0.059784f, 0.072144f, 0.086914f, 0.106873f, 0.132202f, 0.164429f, 0.205200f, 0.255615f,
+ 0.315918f, 0.384521f, 0.458984f, 0.534668f, 0.607910f, 0.676758f, 0.735840f, 0.785645f, 0.828125f, 0.862305f, 0.955566f, 0.958008f,
+ 0.958984f, 0.958496f, 0.958984f, 0.958984f, 0.000000f, 0.000119f, 0.000234f, 0.000484f, 0.000603f, 0.000758f, 0.000934f, 0.000999f,
+ 0.001200f, 0.001343f, 0.001534f, 0.001725f, 0.001860f, 0.002056f, 0.002235f, 0.002445f, 0.002783f, 0.003115f, 0.003448f, 0.003757f,
+ 0.004192f, 0.004723f, 0.005077f, 0.005653f, 0.006172f, 0.006527f, 0.007328f, 0.008247f, 0.009140f, 0.010368f, 0.011711f, 0.013351f,
+ 0.014702f, 0.016937f, 0.019226f, 0.022156f, 0.025604f, 0.029877f, 0.034668f, 0.040710f, 0.048920f, 0.058624f, 0.071289f, 0.087219f,
+ 0.107727f, 0.134521f, 0.168701f, 0.212769f, 0.267090f, 0.331543f, 0.404785f, 0.482910f, 0.561523f, 0.635742f, 0.702637f, 0.760742f,
+ 0.809570f, 0.849121f, 0.951660f, 0.954590f, 0.955566f, 0.955566f, 0.956055f, 0.955566f, 0.000238f, 0.000218f, 0.000229f, 0.000242f,
+ 0.000313f, 0.000859f, 0.000623f, 0.000978f, 0.001021f, 0.001150f, 0.001320f, 0.001431f, 0.001546f, 0.001746f, 0.001895f, 0.002106f,
+ 0.002502f, 0.002630f, 0.002926f, 0.003296f, 0.003651f, 0.003918f, 0.004391f, 0.004910f, 0.005249f, 0.005558f, 0.006413f, 0.007114f,
+ 0.007866f, 0.008789f, 0.009872f, 0.011093f, 0.012413f, 0.013939f, 0.015945f, 0.018692f, 0.021225f, 0.024643f, 0.028687f, 0.033936f,
+ 0.040192f, 0.047791f, 0.058014f, 0.070923f, 0.087585f, 0.109131f, 0.137573f, 0.174683f, 0.222290f, 0.280762f, 0.350830f, 0.428955f,
+ 0.511230f, 0.592285f, 0.666992f, 0.733398f, 0.789062f, 0.834473f, 0.947754f, 0.951172f, 0.951660f, 0.951172f, 0.951660f, 0.951172f,
+ 0.000000f, 0.000205f, 0.000222f, 0.000344f, 0.000301f, 0.000775f, 0.000827f, 0.000719f, 0.000944f, 0.000976f, 0.001306f, 0.001249f,
+ 0.001404f, 0.001569f, 0.001604f, 0.001819f, 0.002182f, 0.002354f, 0.002569f, 0.002857f, 0.003113f, 0.003426f, 0.003649f, 0.004112f,
+ 0.004307f, 0.004925f, 0.005508f, 0.005802f, 0.006565f, 0.007450f, 0.008125f, 0.009079f, 0.010269f, 0.011665f, 0.013565f, 0.015213f,
+ 0.017410f, 0.020203f, 0.023743f, 0.028168f, 0.032684f, 0.039062f, 0.047058f, 0.057404f, 0.070984f, 0.088623f, 0.111389f, 0.142090f,
+ 0.182373f, 0.234253f, 0.298828f, 0.375000f, 0.458008f, 0.543945f, 0.627441f, 0.702148f, 0.765137f, 0.818359f, 0.942871f, 0.946289f,
+ 0.947266f, 0.947266f, 0.946777f, 0.947266f, 0.000064f, 0.000095f, 0.000197f, 0.000213f, 0.000459f, 0.000491f, 0.000647f, 0.000696f,
+ 0.000884f, 0.000911f, 0.001121f, 0.001115f, 0.001234f, 0.001371f, 0.001410f, 0.001743f, 0.001905f, 0.002016f, 0.002207f, 0.002438f,
+ 0.002714f, 0.002939f, 0.003183f, 0.003323f, 0.003727f, 0.004143f, 0.004555f, 0.005276f, 0.005531f, 0.006264f, 0.006702f, 0.007572f,
+ 0.008705f, 0.009712f, 0.011238f, 0.012650f, 0.014320f, 0.016815f, 0.019516f, 0.022400f, 0.026566f, 0.031799f, 0.038055f, 0.046417f,
+ 0.057037f, 0.071350f, 0.089722f, 0.114868f, 0.148193f, 0.192749f, 0.249878f, 0.321045f, 0.404053f, 0.493408f, 0.583008f, 0.666016f,
+ 0.739258f, 0.799316f, 0.937988f, 0.941406f, 0.941895f, 0.942383f, 0.942383f, 0.942383f, 0.000000f, 0.000007f, 0.000144f, 0.000427f,
+ 0.000443f, 0.000566f, 0.000589f, 0.000615f, 0.000725f, 0.000731f, 0.000896f, 0.000953f, 0.001062f, 0.001167f, 0.001344f, 0.001345f,
+ 0.001636f, 0.001774f, 0.001893f, 0.002069f, 0.002350f, 0.002457f, 0.002678f, 0.002743f, 0.003105f, 0.003513f, 0.003830f, 0.004227f,
+ 0.004589f, 0.005047f, 0.005669f, 0.006176f, 0.007153f, 0.007896f, 0.008911f, 0.010231f, 0.011818f, 0.013618f, 0.015465f, 0.018188f,
+ 0.021576f, 0.025452f, 0.030533f, 0.037048f, 0.045685f, 0.056915f, 0.071533f, 0.091675f, 0.118958f, 0.156006f, 0.205444f, 0.270020f,
+ 0.349609f, 0.439941f, 0.533691f, 0.625977f, 0.708984f, 0.778320f, 0.931641f, 0.936035f, 0.936523f, 0.937012f, 0.937012f, 0.937012f,
+ 0.000000f, 0.000000f, 0.000137f, 0.000262f, 0.000432f, 0.000437f, 0.000444f, 0.000590f, 0.000558f, 0.000606f, 0.000817f, 0.000877f,
+ 0.000909f, 0.000951f, 0.001191f, 0.001244f, 0.001373f, 0.001506f, 0.001702f, 0.001690f, 0.001955f, 0.001940f, 0.002283f, 0.002340f,
+ 0.002571f, 0.002871f, 0.003265f, 0.003475f, 0.003910f, 0.004181f, 0.004608f, 0.005112f, 0.005833f, 0.006416f, 0.007145f, 0.008209f,
+ 0.009636f, 0.010750f, 0.012642f, 0.014481f, 0.017197f, 0.020203f, 0.024353f, 0.029694f, 0.036041f, 0.045105f, 0.056702f, 0.072388f,
+ 0.094482f, 0.124329f, 0.166504f, 0.223022f, 0.295898f, 0.384766f, 0.482910f, 0.582031f, 0.675293f, 0.754883f, 0.926270f, 0.929688f,
+ 0.930664f, 0.930664f, 0.931152f, 0.930664f, 0.000000f, 0.000000f, 0.000000f, 0.000232f, 0.000357f, 0.000411f, 0.000513f, 0.000527f,
+ 0.000490f, 0.000504f, 0.000653f, 0.000750f, 0.000780f, 0.000976f, 0.000942f, 0.000967f, 0.001180f, 0.001252f, 0.001385f, 0.001425f,
+ 0.001559f, 0.001801f, 0.001886f, 0.002144f, 0.002111f, 0.002354f, 0.002645f, 0.002827f, 0.003187f, 0.003414f, 0.003792f, 0.004360f,
+ 0.004662f, 0.005146f, 0.005875f, 0.006783f, 0.007610f, 0.008797f, 0.010033f, 0.011566f, 0.013565f, 0.016006f, 0.019165f, 0.023163f,
+ 0.028320f, 0.035400f, 0.044647f, 0.057129f, 0.074402f, 0.098572f, 0.132812f, 0.180542f, 0.245728f, 0.330078f, 0.428955f, 0.535156f,
+ 0.638184f, 0.728516f, 0.919434f, 0.922852f, 0.923828f, 0.923828f, 0.923828f, 0.924316f, 0.000000f, 0.000000f, 0.000000f, 0.000114f,
+ 0.000248f, 0.000359f, 0.000386f, 0.000342f, 0.000465f, 0.000461f, 0.000490f, 0.000609f, 0.000638f, 0.000694f, 0.000807f, 0.000923f,
+ 0.000961f, 0.001074f, 0.001123f, 0.001268f, 0.001311f, 0.001494f, 0.001537f, 0.001754f, 0.001899f, 0.001917f, 0.002199f, 0.002241f,
+ 0.002583f, 0.002769f, 0.003101f, 0.003441f, 0.003775f, 0.004200f, 0.004787f, 0.005272f, 0.006062f, 0.006702f, 0.007732f, 0.009102f,
+ 0.010582f, 0.012466f, 0.014984f, 0.017990f, 0.021957f, 0.027222f, 0.034332f, 0.044128f, 0.057434f, 0.076538f, 0.104126f, 0.143799f,
+ 0.199829f, 0.275879f, 0.373047f, 0.482422f, 0.594727f, 0.698730f, 0.910645f, 0.914551f, 0.916504f, 0.916016f, 0.916504f, 0.915527f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000221f, 0.000222f, 0.000392f, 0.000402f, 0.000396f, 0.000434f, 0.000476f, 0.000548f,
+ 0.000536f, 0.000644f, 0.000642f, 0.000793f, 0.000795f, 0.000912f, 0.000953f, 0.000989f, 0.001164f, 0.001197f, 0.001285f, 0.001480f,
+ 0.001511f, 0.001674f, 0.001703f, 0.001901f, 0.002075f, 0.002340f, 0.002499f, 0.002800f, 0.003019f, 0.003296f, 0.003695f, 0.004093f,
+ 0.004780f, 0.005260f, 0.006207f, 0.006939f, 0.008034f, 0.009598f, 0.011353f, 0.013702f, 0.016678f, 0.020874f, 0.026062f, 0.033539f,
+ 0.044006f, 0.058746f, 0.080139f, 0.111877f, 0.158447f, 0.226318f, 0.317627f, 0.428711f, 0.548828f, 0.665039f, 0.901367f, 0.907227f,
+ 0.907715f, 0.908203f, 0.908203f, 0.907227f, 0.000000f, 0.000000f, 0.000122f, 0.000173f, 0.000191f, 0.000215f, 0.000224f, 0.000261f,
+ 0.000340f, 0.000374f, 0.000380f, 0.000496f, 0.000416f, 0.000535f, 0.000592f, 0.000622f, 0.000701f, 0.000772f, 0.000742f, 0.000774f,
+ 0.000990f, 0.000945f, 0.001088f, 0.001105f, 0.001348f, 0.001231f, 0.001460f, 0.001620f, 0.001758f, 0.001941f, 0.002008f, 0.002092f,
+ 0.002430f, 0.002615f, 0.002886f, 0.003208f, 0.003519f, 0.004112f, 0.004704f, 0.005371f, 0.006149f, 0.007351f, 0.008659f, 0.010201f,
+ 0.012550f, 0.015549f, 0.019577f, 0.025436f, 0.032928f, 0.044220f, 0.060608f, 0.084961f, 0.123474f, 0.180664f, 0.263184f, 0.372314f,
+ 0.498291f, 0.626465f, 0.892578f, 0.895996f, 0.896973f, 0.896973f, 0.897949f, 0.897949f, 0.000000f, 0.000000f, 0.000121f, 0.000121f,
+ 0.000120f, 0.000192f, 0.000201f, 0.000222f, 0.000222f, 0.000276f, 0.000295f, 0.000344f, 0.000433f, 0.000470f, 0.000485f, 0.000549f,
+ 0.000555f, 0.000558f, 0.000566f, 0.000639f, 0.000678f, 0.000757f, 0.000840f, 0.000905f, 0.000999f, 0.000946f, 0.001018f, 0.001309f,
+ 0.001402f, 0.001417f, 0.001624f, 0.001692f, 0.001869f, 0.002003f, 0.002184f, 0.002602f, 0.002851f, 0.003157f, 0.003595f, 0.004063f,
+ 0.004734f, 0.005398f, 0.006275f, 0.007542f, 0.009148f, 0.011383f, 0.014275f, 0.018250f, 0.024063f, 0.032135f, 0.044922f, 0.063721f,
+ 0.093811f, 0.139648f, 0.211914f, 0.314697f, 0.444092f, 0.584961f, 0.879883f, 0.884766f, 0.885254f, 0.885742f, 0.886230f, 0.885742f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000120f, 0.000154f, 0.000150f, 0.000160f, 0.000202f, 0.000217f, 0.000308f, 0.000319f,
+ 0.000278f, 0.000392f, 0.000362f, 0.000432f, 0.000416f, 0.000448f, 0.000495f, 0.000526f, 0.000710f, 0.000754f, 0.000657f, 0.000755f,
+ 0.000806f, 0.000919f, 0.000815f, 0.001080f, 0.001152f, 0.001207f, 0.001218f, 0.001373f, 0.001320f, 0.001685f, 0.001764f, 0.001819f,
+ 0.002068f, 0.002380f, 0.002668f, 0.003033f, 0.003584f, 0.003979f, 0.004829f, 0.005402f, 0.006630f, 0.008080f, 0.010254f, 0.013069f,
+ 0.017044f, 0.023422f, 0.031647f, 0.046417f, 0.068604f, 0.104919f, 0.165161f, 0.258789f, 0.387207f, 0.537598f, 0.867188f, 0.871582f,
+ 0.872559f, 0.872559f, 0.872559f, 0.873047f, 0.000000f, 0.000121f, 0.000120f, 0.000120f, 0.000119f, 0.000118f, 0.000122f, 0.000108f,
+ 0.000143f, 0.000149f, 0.000184f, 0.000194f, 0.000189f, 0.000210f, 0.000321f, 0.000282f, 0.000376f, 0.000420f, 0.000533f, 0.000437f,
+ 0.000467f, 0.000477f, 0.000587f, 0.000519f, 0.000673f, 0.000662f, 0.000679f, 0.000845f, 0.000881f, 0.000863f, 0.001016f, 0.001093f,
+ 0.001176f, 0.001191f, 0.001336f, 0.001561f, 0.001573f, 0.001754f, 0.001919f, 0.002264f, 0.002596f, 0.002911f, 0.003372f, 0.003870f,
+ 0.004723f, 0.005733f, 0.007092f, 0.008965f, 0.011650f, 0.015701f, 0.022339f, 0.032043f, 0.048370f, 0.076050f, 0.124084f, 0.204834f,
+ 0.328369f, 0.485596f, 0.852539f, 0.856934f, 0.858887f, 0.858887f, 0.858887f, 0.858398f, 0.000000f, 0.000121f, 0.000120f, 0.000119f,
+ 0.000118f, 0.000117f, 0.000116f, 0.000114f, 0.000105f, 0.000110f, 0.000165f, 0.000133f, 0.000157f, 0.000240f, 0.000256f, 0.000257f,
+ 0.000249f, 0.000303f, 0.000342f, 0.000346f, 0.000485f, 0.000510f, 0.000398f, 0.000493f, 0.000492f, 0.000524f, 0.000590f, 0.000585f,
+ 0.000601f, 0.000740f, 0.000647f, 0.000871f, 0.000834f, 0.000969f, 0.001020f, 0.001190f, 0.001244f, 0.001432f, 0.001393f, 0.001702f,
+ 0.001912f, 0.002171f, 0.002445f, 0.002958f, 0.003330f, 0.004025f, 0.004860f, 0.006161f, 0.007896f, 0.010742f, 0.014671f, 0.021378f,
+ 0.032928f, 0.052612f, 0.089050f, 0.155884f, 0.268555f, 0.430664f, 0.836426f, 0.841309f, 0.841309f, 0.842285f, 0.842773f, 0.842285f,
+ 0.000000f, 0.000000f, 0.000119f, 0.000117f, 0.000116f, 0.000115f, 0.000114f, 0.000114f, 0.000111f, 0.000103f, 0.000097f, 0.000118f,
+ 0.000115f, 0.000130f, 0.000176f, 0.000130f, 0.000223f, 0.000235f, 0.000244f, 0.000252f, 0.000274f, 0.000389f, 0.000309f, 0.000430f,
+ 0.000340f, 0.000399f, 0.000408f, 0.000459f, 0.000514f, 0.000501f, 0.000519f, 0.000657f, 0.000588f, 0.000775f, 0.000813f, 0.000789f,
+ 0.000904f, 0.001076f, 0.001027f, 0.001170f, 0.001342f, 0.001425f, 0.001662f, 0.002005f, 0.002298f, 0.002699f, 0.003227f, 0.003990f,
+ 0.005062f, 0.006855f, 0.009415f, 0.013504f, 0.020905f, 0.034424f, 0.060333f, 0.112000f, 0.210693f, 0.371094f, 0.816406f, 0.822754f,
+ 0.822754f, 0.823242f, 0.823242f, 0.823730f, 0.000000f, 0.000119f, 0.000117f, 0.000116f, 0.000114f, 0.000113f, 0.000112f, 0.000111f,
+ 0.000110f, 0.000109f, 0.000102f, 0.000095f, 0.000090f, 0.000084f, 0.000093f, 0.000103f, 0.000118f, 0.000165f, 0.000162f, 0.000190f,
+ 0.000204f, 0.000218f, 0.000223f, 0.000237f, 0.000256f, 0.000272f, 0.000344f, 0.000365f, 0.000365f, 0.000396f, 0.000386f, 0.000412f,
+ 0.000530f, 0.000466f, 0.000492f, 0.000615f, 0.000611f, 0.000748f, 0.000712f, 0.000795f, 0.000908f, 0.000971f, 0.001106f, 0.001353f,
+ 0.001572f, 0.001822f, 0.002251f, 0.002676f, 0.003290f, 0.004349f, 0.005951f, 0.008316f, 0.012543f, 0.021149f, 0.038025f, 0.075500f,
+ 0.156006f, 0.308838f, 0.794922f, 0.800293f, 0.800781f, 0.801270f, 0.801758f, 0.802246f, 0.000121f, 0.000116f, 0.000114f, 0.000113f,
+ 0.000111f, 0.000109f, 0.000108f, 0.000107f, 0.000106f, 0.000104f, 0.000104f, 0.000100f, 0.000094f, 0.000088f, 0.000083f, 0.000078f,
+ 0.000074f, 0.000105f, 0.000078f, 0.000122f, 0.000113f, 0.000153f, 0.000174f, 0.000175f, 0.000207f, 0.000216f, 0.000225f, 0.000215f,
+ 0.000262f, 0.000308f, 0.000297f, 0.000287f, 0.000307f, 0.000342f, 0.000363f, 0.000411f, 0.000401f, 0.000453f, 0.000522f, 0.000555f,
+ 0.000680f, 0.000701f, 0.000751f, 0.000873f, 0.000966f, 0.001181f, 0.001445f, 0.001666f, 0.002077f, 0.002512f, 0.003359f, 0.004856f,
+ 0.007347f, 0.012001f, 0.022049f, 0.046417f, 0.107117f, 0.245361f, 0.770508f, 0.775879f, 0.776367f, 0.776855f, 0.777344f, 0.777832f,
+ 0.000000f, 0.000113f, 0.000108f, 0.000107f, 0.000104f, 0.000103f, 0.000101f, 0.000100f, 0.000099f, 0.000098f, 0.000097f, 0.000096f,
+ 0.000095f, 0.000091f, 0.000086f, 0.000081f, 0.000077f, 0.000073f, 0.000069f, 0.000079f, 0.000084f, 0.000091f, 0.000074f, 0.000100f,
+ 0.000117f, 0.000140f, 0.000144f, 0.000166f, 0.000174f, 0.000178f, 0.000225f, 0.000197f, 0.000234f, 0.000239f, 0.000273f, 0.000289f,
+ 0.000283f, 0.000293f, 0.000338f, 0.000386f, 0.000386f, 0.000432f, 0.000459f, 0.000525f, 0.000625f, 0.000691f, 0.000800f, 0.001004f,
+ 0.001227f, 0.001479f, 0.001984f, 0.002745f, 0.003983f, 0.006413f, 0.011642f, 0.025269f, 0.066040f, 0.182495f, 0.743164f, 0.748535f,
+ 0.749023f, 0.749512f, 0.750000f, 0.749512f, 0.000000f, 0.000102f, 0.000101f, 0.000098f, 0.000094f, 0.000093f, 0.000092f, 0.000090f,
+ 0.000089f, 0.000088f, 0.000087f, 0.000086f, 0.000085f, 0.000084f, 0.000085f, 0.000082f, 0.000078f, 0.000074f, 0.000070f, 0.000066f,
+ 0.000063f, 0.000060f, 0.000057f, 0.000056f, 0.000061f, 0.000060f, 0.000073f, 0.000087f, 0.000100f, 0.000105f, 0.000124f, 0.000136f,
+ 0.000140f, 0.000140f, 0.000159f, 0.000179f, 0.000186f, 0.000205f, 0.000214f, 0.000229f, 0.000248f, 0.000267f, 0.000299f, 0.000344f,
+ 0.000367f, 0.000422f, 0.000496f, 0.000557f, 0.000639f, 0.000837f, 0.001037f, 0.001419f, 0.002081f, 0.003202f, 0.005730f, 0.012199f,
+ 0.034943f, 0.122925f, 0.711426f, 0.716797f, 0.718750f, 0.718262f, 0.718262f, 0.718750f, 0.000094f, 0.000079f, 0.000078f, 0.000074f,
+ 0.000074f, 0.000075f, 0.000074f, 0.000073f, 0.000071f, 0.000072f, 0.000070f, 0.000071f, 0.000071f, 0.000070f, 0.000070f, 0.000069f,
+ 0.000070f, 0.000069f, 0.000068f, 0.000065f, 0.000062f, 0.000059f, 0.000056f, 0.000053f, 0.000050f, 0.000048f, 0.000045f, 0.000044f,
+ 0.000041f, 0.000050f, 0.000050f, 0.000061f, 0.000068f, 0.000085f, 0.000091f, 0.000101f, 0.000102f, 0.000107f, 0.000119f, 0.000129f,
+ 0.000144f, 0.000151f, 0.000160f, 0.000184f, 0.000212f, 0.000213f, 0.000235f, 0.000294f, 0.000315f, 0.000392f, 0.000505f, 0.000637f,
+ 0.000880f, 0.001400f, 0.002462f, 0.005333f, 0.015160f, 0.070312f, 0.678223f, 0.683105f, 0.684082f, 0.684570f, 0.684570f, 0.684570f,
+ 0.000000f, 0.000000f, 0.000023f, 0.000034f, 0.000032f, 0.000038f, 0.000037f, 0.000044f, 0.000043f, 0.000047f, 0.000045f, 0.000047f,
+ 0.000049f, 0.000049f, 0.000049f, 0.000048f, 0.000051f, 0.000050f, 0.000051f, 0.000051f, 0.000052f, 0.000052f, 0.000052f, 0.000049f,
+ 0.000047f, 0.000045f, 0.000042f, 0.000040f, 0.000038f, 0.000036f, 0.000035f, 0.000033f, 0.000031f, 0.000029f, 0.000038f, 0.000037f,
+ 0.000042f, 0.000051f, 0.000055f, 0.000067f, 0.000074f, 0.000073f, 0.000083f, 0.000093f, 0.000088f, 0.000102f, 0.000122f, 0.000122f,
+ 0.000142f, 0.000169f, 0.000206f, 0.000265f, 0.000355f, 0.000531f, 0.000897f, 0.001822f, 0.005493f, 0.030579f, 0.640137f, 0.644531f,
+ 0.647461f, 0.647949f, 0.647461f, 0.648438f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000001f, 0.000000f, 0.000008f, 0.000012f, 0.000014f, 0.000014f, 0.000019f, 0.000021f, 0.000022f, 0.000024f, 0.000026f, 0.000027f,
+ 0.000027f, 0.000028f, 0.000029f, 0.000031f, 0.000031f, 0.000032f, 0.000032f, 0.000033f, 0.000033f, 0.000032f, 0.000030f, 0.000029f,
+ 0.000027f, 0.000026f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, 0.000019f, 0.000018f, 0.000021f, 0.000024f, 0.000028f, 0.000033f,
+ 0.000043f, 0.000041f, 0.000046f, 0.000053f, 0.000050f, 0.000059f, 0.000068f, 0.000094f, 0.000096f, 0.000140f, 0.000239f, 0.000447f,
+ 0.001340f, 0.009087f, 0.600098f, 0.605957f, 0.606934f, 0.606934f, 0.607422f, 0.606934f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000002f, 0.000004f, 0.000006f, 0.000006f,
+ 0.000009f, 0.000010f, 0.000011f, 0.000012f, 0.000013f, 0.000014f, 0.000015f, 0.000016f, 0.000017f, 0.000016f, 0.000015f, 0.000014f,
+ 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000010f, 0.000009f, 0.000008f, 0.000012f, 0.000014f, 0.000018f, 0.000017f, 0.000022f,
+ 0.000022f, 0.000026f, 0.000040f, 0.000060f, 0.000157f, 0.001244f, 0.557129f, 0.563477f, 0.563477f, 0.564941f, 0.564941f, 0.564941f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000002f, 0.000003f,
+ 0.000003f, 0.000004f, 0.000003f, 0.000003f, 0.000003f, 0.000002f, 0.000003f, 0.000003f, 0.000003f, 0.000012f, 0.513672f, 0.520020f,
+ 0.520020f, 0.520508f, 0.521484f, 0.521484f,
+ },
+ {
+ 0.103943f, 0.284912f, 0.422119f, 0.523438f, 0.600586f, 0.659668f, 0.705078f, 0.741699f, 0.771484f, 0.795898f, 0.816895f, 0.834961f,
+ 0.850586f, 0.862793f, 0.874512f, 0.884277f, 0.894043f, 0.901855f, 0.909180f, 0.915039f, 0.921387f, 0.926270f, 0.932129f, 0.936035f,
+ 0.940430f, 0.944336f, 0.948242f, 0.951660f, 0.954590f, 0.957520f, 0.959961f, 0.962891f, 0.965332f, 0.967285f, 0.969727f, 0.971680f,
+ 0.973145f, 0.975586f, 0.977051f, 0.979004f, 0.979980f, 0.981934f, 0.983887f, 0.984375f, 0.985840f, 0.986816f, 0.988770f, 0.989258f,
+ 0.990723f, 0.992188f, 0.992676f, 0.993652f, 0.994629f, 0.995605f, 0.996582f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999023f,
+ 0.998535f, 0.998047f, 0.997559f, 0.997070f, 0.046997f, 0.153564f, 0.264160f, 0.369385f, 0.460205f, 0.538574f, 0.602051f, 0.654785f,
+ 0.697754f, 0.733398f, 0.762695f, 0.787598f, 0.809082f, 0.827637f, 0.843262f, 0.856934f, 0.868652f, 0.880859f, 0.889648f, 0.898438f,
+ 0.906738f, 0.912598f, 0.918945f, 0.924805f, 0.929688f, 0.935059f, 0.938965f, 0.943359f, 0.947266f, 0.951172f, 0.954102f, 0.956543f,
+ 0.959961f, 0.961914f, 0.964844f, 0.966797f, 0.969727f, 0.971191f, 0.974121f, 0.975098f, 0.977051f, 0.979492f, 0.980469f, 0.981934f,
+ 0.983887f, 0.985352f, 0.985840f, 0.987305f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.995117f, 0.996094f,
+ 0.996582f, 0.997559f, 0.999023f, 0.998535f, 0.998047f, 0.997559f, 0.997070f, 0.997070f, 0.025940f, 0.088501f, 0.162964f, 0.246094f,
+ 0.331055f, 0.411865f, 0.486328f, 0.550293f, 0.606934f, 0.655762f, 0.695312f, 0.729980f, 0.758301f, 0.783691f, 0.804199f, 0.823730f,
+ 0.838867f, 0.853027f, 0.865723f, 0.877441f, 0.887207f, 0.895996f, 0.904785f, 0.911133f, 0.916992f, 0.923828f, 0.928223f, 0.933594f,
+ 0.937988f, 0.942871f, 0.946777f, 0.950195f, 0.953613f, 0.956543f, 0.959473f, 0.962402f, 0.964844f, 0.967285f, 0.970215f, 0.971680f,
+ 0.973633f, 0.976074f, 0.977539f, 0.979492f, 0.980469f, 0.982422f, 0.984863f, 0.985352f, 0.986816f, 0.987793f, 0.989258f, 0.990234f,
+ 0.991699f, 0.992676f, 0.994141f, 0.995117f, 0.995605f, 0.996582f, 0.998535f, 0.998047f, 0.998047f, 0.997559f, 0.997070f, 0.996582f,
+ 0.016159f, 0.055176f, 0.104126f, 0.162720f, 0.229126f, 0.300781f, 0.372803f, 0.442871f, 0.506836f, 0.563477f, 0.613281f, 0.657715f,
+ 0.696289f, 0.729004f, 0.757324f, 0.782227f, 0.802734f, 0.821289f, 0.837402f, 0.852539f, 0.865234f, 0.875977f, 0.885742f, 0.895508f,
+ 0.903320f, 0.910156f, 0.917480f, 0.922852f, 0.928711f, 0.934082f, 0.937988f, 0.942871f, 0.947266f, 0.950195f, 0.954102f, 0.957031f,
+ 0.959473f, 0.962402f, 0.964844f, 0.968262f, 0.969727f, 0.972168f, 0.974121f, 0.976562f, 0.978516f, 0.979980f, 0.981934f, 0.982910f,
+ 0.983887f, 0.985840f, 0.986816f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.993652f, 0.994141f, 0.995117f, 0.998047f, 0.997559f,
+ 0.997559f, 0.997070f, 0.996582f, 0.996582f, 0.010841f, 0.036865f, 0.070007f, 0.110962f, 0.159546f, 0.214355f, 0.276367f, 0.340576f,
+ 0.405029f, 0.465820f, 0.523926f, 0.576172f, 0.623535f, 0.664062f, 0.699707f, 0.731445f, 0.758301f, 0.782227f, 0.803223f, 0.821289f,
+ 0.837891f, 0.852051f, 0.864258f, 0.875488f, 0.884766f, 0.894531f, 0.903320f, 0.910156f, 0.916992f, 0.923828f, 0.928223f, 0.933594f,
+ 0.938477f, 0.943359f, 0.947266f, 0.950684f, 0.954102f, 0.957520f, 0.960449f, 0.962891f, 0.965820f, 0.968750f, 0.971191f, 0.973145f,
+ 0.975586f, 0.977539f, 0.978516f, 0.980957f, 0.982422f, 0.984375f, 0.985352f, 0.987305f, 0.988281f, 0.989746f, 0.990723f, 0.992188f,
+ 0.993164f, 0.994141f, 0.997559f, 0.997559f, 0.997070f, 0.996582f, 0.996582f, 0.996094f, 0.007637f, 0.026566f, 0.049896f, 0.078247f,
+ 0.113403f, 0.154663f, 0.202637f, 0.255371f, 0.313232f, 0.372314f, 0.431152f, 0.488037f, 0.540039f, 0.588867f, 0.633301f, 0.670898f,
+ 0.704102f, 0.734375f, 0.761230f, 0.785156f, 0.804688f, 0.822754f, 0.838867f, 0.852539f, 0.864746f, 0.876953f, 0.886230f, 0.895996f,
+ 0.903320f, 0.910645f, 0.917480f, 0.923828f, 0.929199f, 0.935059f, 0.938965f, 0.943359f, 0.948730f, 0.952148f, 0.954590f, 0.958496f,
+ 0.961426f, 0.964355f, 0.966797f, 0.969238f, 0.971680f, 0.974121f, 0.976074f, 0.978027f, 0.979980f, 0.981445f, 0.982910f, 0.984863f,
+ 0.986816f, 0.987793f, 0.989258f, 0.990723f, 0.991699f, 0.993164f, 0.996582f, 0.996582f, 0.996094f, 0.996094f, 0.996094f, 0.995605f,
+ 0.005714f, 0.019485f, 0.036194f, 0.056976f, 0.082336f, 0.113342f, 0.149048f, 0.191284f, 0.238770f, 0.290039f, 0.344727f, 0.400391f,
+ 0.454590f, 0.507324f, 0.557129f, 0.602539f, 0.642578f, 0.679199f, 0.711426f, 0.740234f, 0.766602f, 0.788574f, 0.807617f, 0.825195f,
+ 0.841309f, 0.854980f, 0.867676f, 0.877930f, 0.888184f, 0.896484f, 0.904785f, 0.912109f, 0.918945f, 0.925293f, 0.930176f, 0.935547f,
+ 0.940918f, 0.944336f, 0.948730f, 0.952637f, 0.956055f, 0.959473f, 0.962402f, 0.965332f, 0.967773f, 0.970703f, 0.972656f, 0.975098f,
+ 0.977051f, 0.979004f, 0.981445f, 0.982910f, 0.984375f, 0.985840f, 0.987793f, 0.989258f, 0.990234f, 0.991211f, 0.996094f, 0.996094f,
+ 0.996094f, 0.996094f, 0.995605f, 0.995117f, 0.004505f, 0.014908f, 0.027634f, 0.043274f, 0.061707f, 0.084045f, 0.111694f, 0.143921f,
+ 0.180542f, 0.223877f, 0.270996f, 0.320557f, 0.373291f, 0.425781f, 0.478027f, 0.526855f, 0.573242f, 0.615723f, 0.654785f, 0.688965f,
+ 0.720215f, 0.747559f, 0.771973f, 0.793457f, 0.812500f, 0.829102f, 0.844238f, 0.858398f, 0.870117f, 0.881348f, 0.890625f, 0.898926f,
+ 0.906738f, 0.914062f, 0.921387f, 0.926758f, 0.932617f, 0.937500f, 0.942383f, 0.945801f, 0.950684f, 0.954102f, 0.958008f, 0.960938f,
+ 0.964355f, 0.966797f, 0.969727f, 0.972656f, 0.974609f, 0.976562f, 0.978516f, 0.980469f, 0.981934f, 0.984375f, 0.985840f, 0.987793f,
+ 0.988281f, 0.990234f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995117f, 0.994629f, 0.003691f, 0.011925f, 0.021622f, 0.033203f,
+ 0.047241f, 0.065247f, 0.085266f, 0.109558f, 0.138550f, 0.172363f, 0.210205f, 0.253418f, 0.299805f, 0.348877f, 0.400146f, 0.450195f,
+ 0.499512f, 0.546387f, 0.589844f, 0.629883f, 0.666016f, 0.700195f, 0.728516f, 0.755371f, 0.778320f, 0.798828f, 0.817383f, 0.833984f,
+ 0.848145f, 0.861816f, 0.874023f, 0.883789f, 0.893555f, 0.902344f, 0.910645f, 0.916992f, 0.922852f, 0.929688f, 0.934570f, 0.938965f,
+ 0.944336f, 0.948730f, 0.951660f, 0.956543f, 0.959473f, 0.962891f, 0.965820f, 0.968262f, 0.970703f, 0.974121f, 0.976074f, 0.978516f,
+ 0.979980f, 0.981934f, 0.983887f, 0.985840f, 0.987305f, 0.988281f, 0.994629f, 0.995117f, 0.995117f, 0.994629f, 0.994629f, 0.994141f,
+ 0.002726f, 0.009560f, 0.017136f, 0.026871f, 0.037415f, 0.050079f, 0.066406f, 0.084717f, 0.107849f, 0.133423f, 0.164062f, 0.198853f,
+ 0.238281f, 0.281250f, 0.327148f, 0.375977f, 0.424805f, 0.473877f, 0.521973f, 0.564941f, 0.606934f, 0.644531f, 0.679199f, 0.710449f,
+ 0.738770f, 0.764160f, 0.786133f, 0.805664f, 0.824219f, 0.838867f, 0.853516f, 0.866211f, 0.876953f, 0.887695f, 0.896484f, 0.905762f,
+ 0.912598f, 0.919922f, 0.925781f, 0.932129f, 0.937500f, 0.942383f, 0.946777f, 0.951660f, 0.955078f, 0.958984f, 0.961426f, 0.965332f,
+ 0.967773f, 0.970703f, 0.972656f, 0.975586f, 0.978027f, 0.979492f, 0.981934f, 0.983887f, 0.984863f, 0.986816f, 0.994629f, 0.994629f,
+ 0.994629f, 0.994141f, 0.994141f, 0.993652f, 0.002487f, 0.007553f, 0.013863f, 0.021439f, 0.029755f, 0.040771f, 0.052643f, 0.067444f,
+ 0.084473f, 0.104980f, 0.128784f, 0.157227f, 0.189087f, 0.224609f, 0.265381f, 0.308838f, 0.354004f, 0.401611f, 0.450439f, 0.496582f,
+ 0.541992f, 0.583984f, 0.623047f, 0.660645f, 0.693359f, 0.722168f, 0.749512f, 0.772949f, 0.793457f, 0.812988f, 0.830078f, 0.845215f,
+ 0.859375f, 0.871094f, 0.882812f, 0.892090f, 0.900879f, 0.908691f, 0.916504f, 0.922852f, 0.930176f, 0.935547f, 0.940430f, 0.944824f,
+ 0.949219f, 0.952637f, 0.956543f, 0.960449f, 0.963867f, 0.967285f, 0.970215f, 0.972656f, 0.974609f, 0.977539f, 0.979492f, 0.981934f,
+ 0.983887f, 0.985352f, 0.993652f, 0.994141f, 0.994141f, 0.993652f, 0.993652f, 0.993164f, 0.001893f, 0.006641f, 0.011551f, 0.017319f,
+ 0.024612f, 0.032959f, 0.042023f, 0.053772f, 0.067444f, 0.083435f, 0.102356f, 0.123840f, 0.150024f, 0.179688f, 0.213501f, 0.250488f,
+ 0.291992f, 0.335938f, 0.381592f, 0.427246f, 0.473877f, 0.518555f, 0.563477f, 0.603027f, 0.640625f, 0.676270f, 0.707031f, 0.735352f,
+ 0.760254f, 0.782715f, 0.802734f, 0.821777f, 0.838379f, 0.851562f, 0.865234f, 0.876953f, 0.886719f, 0.896484f, 0.905273f, 0.913086f,
+ 0.921387f, 0.927734f, 0.933105f, 0.938477f, 0.942871f, 0.948242f, 0.951660f, 0.955566f, 0.959961f, 0.963867f, 0.966309f, 0.969238f,
+ 0.972168f, 0.975098f, 0.977539f, 0.979492f, 0.981934f, 0.983887f, 0.993164f, 0.993652f, 0.993164f, 0.993164f, 0.993164f, 0.992676f,
+ 0.001740f, 0.005634f, 0.009407f, 0.014992f, 0.020157f, 0.026840f, 0.035156f, 0.043793f, 0.054718f, 0.067505f, 0.082092f, 0.099731f,
+ 0.120239f, 0.143921f, 0.171265f, 0.202393f, 0.237915f, 0.276367f, 0.318848f, 0.362793f, 0.407959f, 0.454346f, 0.499023f, 0.542480f,
+ 0.583984f, 0.623535f, 0.659180f, 0.691895f, 0.721680f, 0.748047f, 0.772461f, 0.793457f, 0.812988f, 0.829102f, 0.845215f, 0.859863f,
+ 0.872559f, 0.883789f, 0.893555f, 0.902344f, 0.911133f, 0.918457f, 0.924805f, 0.930664f, 0.937012f, 0.941895f, 0.947266f, 0.951172f,
+ 0.956055f, 0.959473f, 0.962402f, 0.966309f, 0.968750f, 0.972168f, 0.974609f, 0.977051f, 0.979492f, 0.981934f, 0.992188f, 0.992676f,
+ 0.992676f, 0.992676f, 0.992188f, 0.992676f, 0.001502f, 0.004482f, 0.008278f, 0.012276f, 0.016800f, 0.022644f, 0.029129f, 0.036194f,
+ 0.045197f, 0.055298f, 0.067017f, 0.080750f, 0.096863f, 0.115906f, 0.138184f, 0.163940f, 0.192993f, 0.225952f, 0.262695f, 0.302490f,
+ 0.344971f, 0.389648f, 0.434814f, 0.480469f, 0.523926f, 0.566406f, 0.605957f, 0.643066f, 0.677246f, 0.708496f, 0.736816f, 0.761719f,
+ 0.784668f, 0.804688f, 0.823242f, 0.840332f, 0.854004f, 0.867188f, 0.878906f, 0.890137f, 0.898438f, 0.907715f, 0.916016f, 0.922852f,
+ 0.930176f, 0.935547f, 0.940918f, 0.946289f, 0.950684f, 0.955078f, 0.959473f, 0.961914f, 0.966309f, 0.969238f, 0.972168f, 0.974609f,
+ 0.977539f, 0.979492f, 0.991211f, 0.992188f, 0.991699f, 0.992188f, 0.991699f, 0.991211f, 0.001411f, 0.003645f, 0.007160f, 0.010414f,
+ 0.014397f, 0.018677f, 0.024338f, 0.030426f, 0.037384f, 0.045654f, 0.055054f, 0.066101f, 0.079529f, 0.094543f, 0.112793f, 0.133057f,
+ 0.157227f, 0.183960f, 0.215210f, 0.250488f, 0.288086f, 0.329102f, 0.372314f, 0.416992f, 0.461914f, 0.505859f, 0.549316f, 0.589355f,
+ 0.627930f, 0.664062f, 0.695801f, 0.725098f, 0.752441f, 0.775879f, 0.797363f, 0.815918f, 0.833984f, 0.849121f, 0.863281f, 0.875488f,
+ 0.886230f, 0.895996f, 0.904785f, 0.914062f, 0.920898f, 0.928223f, 0.935059f, 0.940918f, 0.945312f, 0.950195f, 0.954102f, 0.958984f,
+ 0.962402f, 0.966309f, 0.969238f, 0.972656f, 0.974609f, 0.977539f, 0.990234f, 0.992188f, 0.991211f, 0.991211f, 0.990723f, 0.991211f,
+ 0.000926f, 0.003523f, 0.006207f, 0.008949f, 0.012718f, 0.016312f, 0.020447f, 0.025467f, 0.031128f, 0.037994f, 0.045532f, 0.054901f,
+ 0.065430f, 0.077576f, 0.091797f, 0.109131f, 0.128418f, 0.151245f, 0.176636f, 0.206055f, 0.238525f, 0.275146f, 0.314697f, 0.357178f,
+ 0.400391f, 0.445312f, 0.489746f, 0.531738f, 0.574219f, 0.613281f, 0.650391f, 0.683594f, 0.714355f, 0.742188f, 0.768066f, 0.790039f,
+ 0.810059f, 0.828125f, 0.843262f, 0.858398f, 0.871582f, 0.883789f, 0.893555f, 0.903809f, 0.912598f, 0.919434f, 0.926758f, 0.933594f,
+ 0.939453f, 0.944336f, 0.950195f, 0.954590f, 0.958008f, 0.962402f, 0.966309f, 0.969727f, 0.972656f, 0.975586f, 0.989746f, 0.990723f,
+ 0.990723f, 0.990234f, 0.990234f, 0.990234f, 0.001140f, 0.003021f, 0.005527f, 0.008102f, 0.010445f, 0.013977f, 0.017349f, 0.021637f,
+ 0.026535f, 0.031677f, 0.038330f, 0.045776f, 0.054382f, 0.064392f, 0.076233f, 0.089844f, 0.105713f, 0.123840f, 0.145020f, 0.169556f,
+ 0.196899f, 0.229248f, 0.263672f, 0.302002f, 0.342529f, 0.385986f, 0.429932f, 0.473877f, 0.517578f, 0.560547f, 0.600586f, 0.638184f,
+ 0.672852f, 0.704590f, 0.733398f, 0.759277f, 0.782715f, 0.803711f, 0.823242f, 0.840820f, 0.854980f, 0.869141f, 0.881348f, 0.892090f,
+ 0.902344f, 0.910645f, 0.919922f, 0.927246f, 0.933105f, 0.938965f, 0.944824f, 0.949707f, 0.954102f, 0.959473f, 0.962891f, 0.966309f,
+ 0.969727f, 0.972168f, 0.988770f, 0.990234f, 0.989746f, 0.989746f, 0.989746f, 0.989258f, 0.000870f, 0.002666f, 0.004578f, 0.006737f,
+ 0.009430f, 0.012077f, 0.015381f, 0.018463f, 0.022293f, 0.027313f, 0.032654f, 0.038727f, 0.045746f, 0.053619f, 0.063232f, 0.074524f,
+ 0.087219f, 0.102356f, 0.119324f, 0.139648f, 0.162842f, 0.189941f, 0.219482f, 0.253174f, 0.289795f, 0.329346f, 0.372070f, 0.415039f,
+ 0.459717f, 0.503418f, 0.546387f, 0.587402f, 0.625977f, 0.661621f, 0.694336f, 0.725586f, 0.752441f, 0.776855f, 0.798828f, 0.818359f,
+ 0.837402f, 0.852539f, 0.866699f, 0.878906f, 0.891113f, 0.900879f, 0.910156f, 0.918457f, 0.926270f, 0.932617f, 0.938965f, 0.944824f,
+ 0.950195f, 0.955078f, 0.958984f, 0.962891f, 0.966797f, 0.970703f, 0.987793f, 0.988770f, 0.989258f, 0.989258f, 0.988770f, 0.988770f,
+ 0.000835f, 0.002302f, 0.004078f, 0.005802f, 0.008026f, 0.010490f, 0.013153f, 0.016235f, 0.019485f, 0.023636f, 0.027847f, 0.033081f,
+ 0.038849f, 0.045441f, 0.053253f, 0.062500f, 0.072571f, 0.085205f, 0.098999f, 0.115662f, 0.135254f, 0.156860f, 0.182373f, 0.211060f,
+ 0.243042f, 0.279053f, 0.318115f, 0.359619f, 0.402832f, 0.447021f, 0.490234f, 0.533691f, 0.575195f, 0.615234f, 0.651855f, 0.686035f,
+ 0.717285f, 0.746094f, 0.771484f, 0.793945f, 0.813965f, 0.833496f, 0.848633f, 0.864258f, 0.877930f, 0.889648f, 0.900391f, 0.909180f,
+ 0.918945f, 0.926270f, 0.932129f, 0.939453f, 0.945312f, 0.950684f, 0.955566f, 0.959473f, 0.963867f, 0.967773f, 0.987305f, 0.988281f,
+ 0.988281f, 0.988281f, 0.988281f, 0.987793f, 0.000815f, 0.001984f, 0.003475f, 0.005302f, 0.007103f, 0.009354f, 0.011528f, 0.013977f,
+ 0.017197f, 0.020111f, 0.023788f, 0.027771f, 0.033447f, 0.038452f, 0.045013f, 0.052704f, 0.061066f, 0.071228f, 0.082886f, 0.096313f,
+ 0.112488f, 0.130737f, 0.151245f, 0.175659f, 0.203125f, 0.234619f, 0.269043f, 0.306885f, 0.347656f, 0.390381f, 0.434570f, 0.478760f,
+ 0.522461f, 0.564453f, 0.605957f, 0.644043f, 0.678223f, 0.710449f, 0.739746f, 0.766602f, 0.791016f, 0.811035f, 0.831055f, 0.847168f,
+ 0.862793f, 0.875977f, 0.888672f, 0.899414f, 0.909180f, 0.917480f, 0.926270f, 0.933105f, 0.939941f, 0.945801f, 0.950684f, 0.955566f,
+ 0.960938f, 0.964844f, 0.985840f, 0.987305f, 0.987793f, 0.987305f, 0.987305f, 0.987305f, 0.000587f, 0.002005f, 0.003122f, 0.004707f,
+ 0.006283f, 0.007778f, 0.009972f, 0.012581f, 0.014435f, 0.017426f, 0.020691f, 0.024475f, 0.028519f, 0.033203f, 0.038513f, 0.044708f,
+ 0.051727f, 0.060028f, 0.069763f, 0.080627f, 0.093506f, 0.109009f, 0.125977f, 0.146362f, 0.169678f, 0.196533f, 0.226685f, 0.259766f,
+ 0.297119f, 0.337646f, 0.380127f, 0.424072f, 0.468018f, 0.512207f, 0.555176f, 0.596680f, 0.635254f, 0.671387f, 0.704590f, 0.734863f,
+ 0.762207f, 0.787109f, 0.809082f, 0.828613f, 0.846191f, 0.860840f, 0.875977f, 0.888184f, 0.899902f, 0.908691f, 0.918457f, 0.926270f,
+ 0.934082f, 0.940430f, 0.947266f, 0.951660f, 0.958008f, 0.961914f, 0.984863f, 0.986328f, 0.986816f, 0.986816f, 0.986328f, 0.986328f,
+ 0.000475f, 0.001671f, 0.003019f, 0.004379f, 0.005592f, 0.006882f, 0.008682f, 0.010757f, 0.012856f, 0.015343f, 0.018112f, 0.021164f,
+ 0.024353f, 0.028595f, 0.033020f, 0.038086f, 0.044006f, 0.050812f, 0.058594f, 0.067993f, 0.078735f, 0.091248f, 0.105530f, 0.122009f,
+ 0.142212f, 0.164062f, 0.189697f, 0.219238f, 0.251953f, 0.288330f, 0.328125f, 0.369629f, 0.413818f, 0.458008f, 0.503418f, 0.547363f,
+ 0.588867f, 0.628418f, 0.665039f, 0.699707f, 0.730469f, 0.758301f, 0.784668f, 0.807129f, 0.826660f, 0.844727f, 0.862305f, 0.875977f,
+ 0.888672f, 0.900879f, 0.910156f, 0.919434f, 0.927734f, 0.935059f, 0.941406f, 0.947754f, 0.953125f, 0.958496f, 0.983887f, 0.985352f,
+ 0.985352f, 0.985352f, 0.984863f, 0.985352f, 0.000325f, 0.001517f, 0.002554f, 0.003811f, 0.004990f, 0.006638f, 0.007706f, 0.009399f,
+ 0.011177f, 0.013580f, 0.015671f, 0.018478f, 0.021393f, 0.024612f, 0.028442f, 0.032990f, 0.037750f, 0.043427f, 0.050354f, 0.057861f,
+ 0.066101f, 0.076294f, 0.088684f, 0.102417f, 0.119080f, 0.137451f, 0.159058f, 0.183838f, 0.212524f, 0.244385f, 0.280273f, 0.319336f,
+ 0.361084f, 0.405029f, 0.449707f, 0.494873f, 0.539551f, 0.582031f, 0.622559f, 0.660156f, 0.695801f, 0.727539f, 0.756348f, 0.782715f,
+ 0.805664f, 0.826172f, 0.845215f, 0.861328f, 0.875977f, 0.889648f, 0.901367f, 0.910645f, 0.920410f, 0.928711f, 0.937012f, 0.942871f,
+ 0.949219f, 0.955078f, 0.982422f, 0.983887f, 0.984375f, 0.984375f, 0.983887f, 0.983887f, 0.000349f, 0.001533f, 0.002413f, 0.003326f,
+ 0.004463f, 0.005524f, 0.006954f, 0.008202f, 0.010025f, 0.011864f, 0.013924f, 0.015884f, 0.018478f, 0.021484f, 0.024658f, 0.028671f,
+ 0.032562f, 0.037170f, 0.042969f, 0.049194f, 0.056641f, 0.065063f, 0.074951f, 0.086182f, 0.099731f, 0.115662f, 0.133789f, 0.154175f,
+ 0.178589f, 0.206421f, 0.237671f, 0.272949f, 0.312012f, 0.352783f, 0.396973f, 0.442627f, 0.487793f, 0.532227f, 0.576660f, 0.617188f,
+ 0.657227f, 0.692383f, 0.725586f, 0.754395f, 0.780762f, 0.805664f, 0.826172f, 0.845215f, 0.861816f, 0.876465f, 0.890137f, 0.902344f,
+ 0.912598f, 0.921875f, 0.930176f, 0.937988f, 0.945312f, 0.952148f, 0.981445f, 0.982910f, 0.982910f, 0.983398f, 0.983398f, 0.983398f,
+ 0.000475f, 0.001141f, 0.002058f, 0.002846f, 0.004120f, 0.005013f, 0.006207f, 0.007664f, 0.009193f, 0.010368f, 0.012222f, 0.014404f,
+ 0.016403f, 0.018799f, 0.021439f, 0.024567f, 0.028076f, 0.032379f, 0.036652f, 0.042145f, 0.048157f, 0.055389f, 0.063660f, 0.073059f,
+ 0.083740f, 0.097046f, 0.112366f, 0.129517f, 0.149780f, 0.173584f, 0.200684f, 0.231812f, 0.266357f, 0.304688f, 0.346680f, 0.390137f,
+ 0.435547f, 0.481445f, 0.526367f, 0.572266f, 0.613770f, 0.653320f, 0.690430f, 0.723633f, 0.754395f, 0.781250f, 0.806152f, 0.826172f,
+ 0.847168f, 0.862793f, 0.878906f, 0.892090f, 0.904297f, 0.914551f, 0.924316f, 0.933105f, 0.940430f, 0.947754f, 0.979492f, 0.981934f,
+ 0.981934f, 0.981934f, 0.981445f, 0.981445f, 0.000239f, 0.000882f, 0.001744f, 0.002878f, 0.003819f, 0.004532f, 0.005550f, 0.006653f,
+ 0.007942f, 0.009277f, 0.010628f, 0.012421f, 0.014397f, 0.016312f, 0.018845f, 0.021576f, 0.024536f, 0.027817f, 0.031860f, 0.036346f,
+ 0.041595f, 0.047333f, 0.054138f, 0.062317f, 0.071350f, 0.081970f, 0.094299f, 0.109070f, 0.126221f, 0.146118f, 0.169067f, 0.195801f,
+ 0.226196f, 0.260742f, 0.298584f, 0.340088f, 0.384277f, 0.429688f, 0.476807f, 0.522461f, 0.568359f, 0.611328f, 0.651855f, 0.689453f,
+ 0.723633f, 0.754395f, 0.782715f, 0.807617f, 0.829590f, 0.848145f, 0.865723f, 0.880859f, 0.894531f, 0.906738f, 0.917969f, 0.927246f,
+ 0.936035f, 0.943359f, 0.978027f, 0.979980f, 0.980469f, 0.980469f, 0.980469f, 0.980469f, 0.000240f, 0.000948f, 0.001495f, 0.002592f,
+ 0.003241f, 0.004055f, 0.004856f, 0.006111f, 0.007133f, 0.008125f, 0.009445f, 0.011108f, 0.012474f, 0.014374f, 0.016586f, 0.018784f,
+ 0.021286f, 0.024475f, 0.027481f, 0.031403f, 0.035828f, 0.040710f, 0.046204f, 0.052704f, 0.060577f, 0.069519f, 0.079651f, 0.092224f,
+ 0.106506f, 0.122986f, 0.142456f, 0.165161f, 0.191284f, 0.221924f, 0.255615f, 0.293457f, 0.335205f, 0.379395f, 0.425537f, 0.472900f,
+ 0.519531f, 0.566406f, 0.610840f, 0.652344f, 0.689941f, 0.724609f, 0.755371f, 0.784180f, 0.808594f, 0.831055f, 0.851562f, 0.869141f,
+ 0.884277f, 0.897461f, 0.909668f, 0.920410f, 0.930176f, 0.937988f, 0.976562f, 0.979004f, 0.979492f, 0.979492f, 0.979492f, 0.979492f,
+ 0.000302f, 0.000863f, 0.001315f, 0.002195f, 0.002905f, 0.003592f, 0.004784f, 0.005478f, 0.006199f, 0.007389f, 0.008545f, 0.009811f,
+ 0.011185f, 0.012787f, 0.014603f, 0.016342f, 0.018784f, 0.021347f, 0.024033f, 0.027496f, 0.031006f, 0.034790f, 0.039856f, 0.045288f,
+ 0.051636f, 0.059052f, 0.067566f, 0.078003f, 0.089905f, 0.103760f, 0.119934f, 0.139282f, 0.161865f, 0.187622f, 0.217407f, 0.251221f,
+ 0.288818f, 0.330811f, 0.375244f, 0.422607f, 0.470703f, 0.518066f, 0.565430f, 0.609863f, 0.651855f, 0.691406f, 0.726562f, 0.758301f,
+ 0.787109f, 0.812500f, 0.835449f, 0.855957f, 0.872559f, 0.887695f, 0.901367f, 0.913574f, 0.923828f, 0.933105f, 0.975098f, 0.977539f,
+ 0.977539f, 0.977539f, 0.978027f, 0.977051f, 0.000240f, 0.000808f, 0.001537f, 0.002106f, 0.002493f, 0.003729f, 0.004036f, 0.004982f,
+ 0.005539f, 0.006454f, 0.007526f, 0.008690f, 0.009987f, 0.011421f, 0.012894f, 0.014618f, 0.016464f, 0.018539f, 0.021118f, 0.023865f,
+ 0.026794f, 0.030487f, 0.034241f, 0.038879f, 0.044067f, 0.050690f, 0.057678f, 0.066040f, 0.076111f, 0.087524f, 0.101379f, 0.117737f,
+ 0.136353f, 0.158325f, 0.183594f, 0.213501f, 0.247192f, 0.284912f, 0.327393f, 0.372803f, 0.420410f, 0.468750f, 0.518066f, 0.565430f,
+ 0.611328f, 0.654297f, 0.694336f, 0.729980f, 0.762207f, 0.791504f, 0.817383f, 0.839844f, 0.859863f, 0.876953f, 0.891602f, 0.905762f,
+ 0.917480f, 0.928711f, 0.973633f, 0.975098f, 0.976562f, 0.975586f, 0.976562f, 0.976562f, 0.000240f, 0.000587f, 0.001223f, 0.001691f,
+ 0.002499f, 0.003008f, 0.003643f, 0.004295f, 0.004795f, 0.005726f, 0.006649f, 0.007671f, 0.008766f, 0.010002f, 0.011307f, 0.012764f,
+ 0.014465f, 0.016388f, 0.018387f, 0.020599f, 0.023453f, 0.026291f, 0.029572f, 0.033417f, 0.037964f, 0.043427f, 0.049316f, 0.056519f,
+ 0.064819f, 0.074219f, 0.085693f, 0.099121f, 0.115112f, 0.133301f, 0.155273f, 0.180420f, 0.210205f, 0.244751f, 0.282715f, 0.324951f,
+ 0.371338f, 0.419434f, 0.468994f, 0.518555f, 0.566895f, 0.613770f, 0.658203f, 0.698242f, 0.735352f, 0.766602f, 0.796875f, 0.821289f,
+ 0.844238f, 0.863770f, 0.881836f, 0.896973f, 0.910156f, 0.922363f, 0.971191f, 0.974121f, 0.974609f, 0.974121f, 0.974609f, 0.974609f,
+ 0.000228f, 0.000671f, 0.001122f, 0.001607f, 0.002291f, 0.002836f, 0.003319f, 0.003817f, 0.004509f, 0.005253f, 0.005894f, 0.006840f,
+ 0.007820f, 0.008972f, 0.010086f, 0.011391f, 0.012848f, 0.014328f, 0.016266f, 0.018158f, 0.020447f, 0.022720f, 0.026031f, 0.029053f,
+ 0.032593f, 0.037109f, 0.042236f, 0.048340f, 0.055115f, 0.063049f, 0.072632f, 0.083801f, 0.097351f, 0.112488f, 0.130493f, 0.152222f,
+ 0.178101f, 0.208008f, 0.241943f, 0.280762f, 0.323730f, 0.370117f, 0.419434f, 0.470459f, 0.520996f, 0.570801f, 0.617676f, 0.663086f,
+ 0.704102f, 0.740234f, 0.773438f, 0.802246f, 0.829102f, 0.850098f, 0.870117f, 0.887695f, 0.902832f, 0.916016f, 0.969238f, 0.972168f,
+ 0.972168f, 0.972656f, 0.972656f, 0.972168f, 0.000121f, 0.000526f, 0.001092f, 0.001670f, 0.001744f, 0.002420f, 0.002945f, 0.003237f,
+ 0.004013f, 0.004894f, 0.005421f, 0.005932f, 0.006996f, 0.007904f, 0.008873f, 0.009995f, 0.011391f, 0.012756f, 0.014053f, 0.015884f,
+ 0.017715f, 0.019775f, 0.022324f, 0.025406f, 0.028290f, 0.032349f, 0.036560f, 0.041412f, 0.047058f, 0.053772f, 0.061493f, 0.070862f,
+ 0.081848f, 0.094666f, 0.110229f, 0.128662f, 0.150024f, 0.175903f, 0.205566f, 0.239990f, 0.279785f, 0.323486f, 0.370850f, 0.421143f,
+ 0.473633f, 0.524902f, 0.576172f, 0.625000f, 0.668457f, 0.710938f, 0.748535f, 0.781250f, 0.810059f, 0.835449f, 0.857910f, 0.877441f,
+ 0.894531f, 0.908691f, 0.966797f, 0.970215f, 0.970703f, 0.970703f, 0.970703f, 0.970215f, 0.000127f, 0.000521f, 0.001083f, 0.001460f,
+ 0.001684f, 0.002111f, 0.002563f, 0.003048f, 0.003618f, 0.004124f, 0.004936f, 0.005543f, 0.006340f, 0.007111f, 0.008049f, 0.008774f,
+ 0.009865f, 0.011162f, 0.012360f, 0.013840f, 0.015465f, 0.017181f, 0.019531f, 0.021973f, 0.024582f, 0.027847f, 0.031342f, 0.035706f,
+ 0.040100f, 0.045990f, 0.052521f, 0.060089f, 0.069214f, 0.080017f, 0.093079f, 0.108521f, 0.126709f, 0.148071f, 0.174072f, 0.204224f,
+ 0.239502f, 0.279541f, 0.324219f, 0.373047f, 0.424805f, 0.477295f, 0.530762f, 0.583008f, 0.632324f, 0.677246f, 0.719727f, 0.756348f,
+ 0.789551f, 0.819336f, 0.842773f, 0.866211f, 0.885742f, 0.901855f, 0.965332f, 0.967773f, 0.968262f, 0.967773f, 0.968750f, 0.968262f,
+ 0.000244f, 0.000397f, 0.001001f, 0.001181f, 0.001642f, 0.001872f, 0.002460f, 0.002712f, 0.003061f, 0.003723f, 0.004520f, 0.005043f,
+ 0.005547f, 0.006451f, 0.007057f, 0.007828f, 0.008942f, 0.009872f, 0.010857f, 0.012131f, 0.013557f, 0.015198f, 0.017059f, 0.019241f,
+ 0.021454f, 0.024048f, 0.027069f, 0.030594f, 0.034332f, 0.039001f, 0.044952f, 0.050873f, 0.058716f, 0.067505f, 0.078369f, 0.091309f,
+ 0.106506f, 0.124695f, 0.146484f, 0.172852f, 0.203369f, 0.239014f, 0.280273f, 0.326172f, 0.376465f, 0.429443f, 0.483643f, 0.538574f,
+ 0.591309f, 0.641602f, 0.687500f, 0.729492f, 0.766602f, 0.800293f, 0.828613f, 0.854004f, 0.874512f, 0.893555f, 0.961914f, 0.965332f,
+ 0.965820f, 0.966309f, 0.966309f, 0.965820f, 0.000243f, 0.000453f, 0.000888f, 0.001245f, 0.001342f, 0.001847f, 0.002060f, 0.002541f,
+ 0.002991f, 0.003355f, 0.003679f, 0.004379f, 0.005177f, 0.005413f, 0.006283f, 0.007038f, 0.007896f, 0.008507f, 0.009552f, 0.010628f,
+ 0.011909f, 0.013306f, 0.015038f, 0.016388f, 0.018433f, 0.020752f, 0.023254f, 0.026413f, 0.029617f, 0.033447f, 0.037842f, 0.043701f,
+ 0.049896f, 0.057190f, 0.066101f, 0.076660f, 0.089600f, 0.104553f, 0.123230f, 0.145386f, 0.171387f, 0.202637f, 0.239624f, 0.281982f,
+ 0.329346f, 0.380859f, 0.436035f, 0.491943f, 0.547852f, 0.602539f, 0.653809f, 0.699707f, 0.741699f, 0.778320f, 0.811035f, 0.838867f,
+ 0.862793f, 0.884766f, 0.959961f, 0.963379f, 0.963379f, 0.963379f, 0.964355f, 0.963379f, 0.000241f, 0.000452f, 0.000798f, 0.001119f,
+ 0.001220f, 0.001430f, 0.001902f, 0.002277f, 0.002737f, 0.002893f, 0.003624f, 0.003937f, 0.004436f, 0.005089f, 0.005669f, 0.006226f,
+ 0.006680f, 0.007519f, 0.008568f, 0.009384f, 0.010422f, 0.011795f, 0.012840f, 0.014526f, 0.016235f, 0.017929f, 0.020218f, 0.022736f,
+ 0.025146f, 0.028580f, 0.032684f, 0.036896f, 0.042511f, 0.048431f, 0.055634f, 0.064453f, 0.075317f, 0.088196f, 0.103333f, 0.121948f,
+ 0.144287f, 0.171143f, 0.203491f, 0.241577f, 0.285156f, 0.334229f, 0.387939f, 0.444580f, 0.501953f, 0.559570f, 0.614746f, 0.666504f,
+ 0.712402f, 0.755371f, 0.791504f, 0.823242f, 0.851074f, 0.875000f, 0.956543f, 0.959961f, 0.960938f, 0.960449f, 0.960449f, 0.960449f,
+ 0.000000f, 0.000263f, 0.000693f, 0.000873f, 0.001183f, 0.001447f, 0.001476f, 0.002068f, 0.002171f, 0.002857f, 0.003164f, 0.003542f,
+ 0.003778f, 0.004326f, 0.004906f, 0.005436f, 0.006126f, 0.006687f, 0.007229f, 0.008377f, 0.009232f, 0.010223f, 0.011436f, 0.012527f,
+ 0.013832f, 0.015747f, 0.017365f, 0.019363f, 0.021667f, 0.024231f, 0.027695f, 0.031769f, 0.035889f, 0.041016f, 0.047028f, 0.054504f,
+ 0.063110f, 0.073975f, 0.086487f, 0.101807f, 0.120972f, 0.143555f, 0.171753f, 0.204956f, 0.244263f, 0.289551f, 0.340576f, 0.396484f,
+ 0.455078f, 0.514648f, 0.573730f, 0.630371f, 0.681152f, 0.729004f, 0.770020f, 0.806641f, 0.837402f, 0.863770f, 0.953613f, 0.956543f,
+ 0.957520f, 0.957031f, 0.957031f, 0.958008f, 0.000000f, 0.000356f, 0.000641f, 0.000870f, 0.000998f, 0.001134f, 0.001495f, 0.001724f,
+ 0.002436f, 0.002478f, 0.002775f, 0.003113f, 0.003435f, 0.003864f, 0.004314f, 0.004704f, 0.005276f, 0.005886f, 0.006599f, 0.007309f,
+ 0.008003f, 0.008987f, 0.009987f, 0.010941f, 0.012192f, 0.013466f, 0.015030f, 0.016708f, 0.018906f, 0.021103f, 0.023788f, 0.026886f,
+ 0.030457f, 0.034943f, 0.040009f, 0.045959f, 0.053162f, 0.061920f, 0.072144f, 0.085205f, 0.101257f, 0.120422f, 0.143555f, 0.172363f,
+ 0.206909f, 0.248047f, 0.295410f, 0.349121f, 0.407715f, 0.468750f, 0.530762f, 0.589844f, 0.647949f, 0.699707f, 0.746094f, 0.786621f,
+ 0.823242f, 0.852051f, 0.950195f, 0.953125f, 0.954102f, 0.954102f, 0.954102f, 0.954102f, 0.000231f, 0.000449f, 0.000516f, 0.000760f,
+ 0.000868f, 0.001152f, 0.001403f, 0.001773f, 0.002165f, 0.002245f, 0.002550f, 0.002783f, 0.003277f, 0.003660f, 0.003782f, 0.004120f,
+ 0.004631f, 0.005268f, 0.005795f, 0.006344f, 0.007053f, 0.007835f, 0.008598f, 0.009460f, 0.010689f, 0.011551f, 0.012726f, 0.014359f,
+ 0.016052f, 0.017975f, 0.020218f, 0.022812f, 0.025803f, 0.029251f, 0.033386f, 0.038574f, 0.044556f, 0.051941f, 0.060577f, 0.071045f,
+ 0.084106f, 0.100342f, 0.119751f, 0.144043f, 0.174194f, 0.209961f, 0.253418f, 0.303467f, 0.359619f, 0.420898f, 0.483887f, 0.547852f,
+ 0.609375f, 0.667480f, 0.719727f, 0.765625f, 0.804688f, 0.839844f, 0.946289f, 0.949707f, 0.950195f, 0.950684f, 0.950684f, 0.950195f,
+ 0.000201f, 0.000336f, 0.000452f, 0.000627f, 0.000793f, 0.000966f, 0.001134f, 0.001578f, 0.001790f, 0.001896f, 0.002254f, 0.002464f,
+ 0.002825f, 0.003012f, 0.003414f, 0.003626f, 0.004131f, 0.004608f, 0.005058f, 0.005642f, 0.006191f, 0.006771f, 0.007378f, 0.008057f,
+ 0.009132f, 0.009918f, 0.010826f, 0.012314f, 0.013794f, 0.015381f, 0.017197f, 0.019257f, 0.021912f, 0.024841f, 0.028259f, 0.032318f,
+ 0.037262f, 0.043427f, 0.050537f, 0.059021f, 0.070007f, 0.083191f, 0.099609f, 0.120239f, 0.145508f, 0.176636f, 0.214600f, 0.260254f,
+ 0.313232f, 0.372803f, 0.437012f, 0.503418f, 0.568359f, 0.631836f, 0.688965f, 0.741211f, 0.786621f, 0.825195f, 0.941406f, 0.946289f,
+ 0.946289f, 0.946777f, 0.946289f, 0.947266f, 0.000000f, 0.000317f, 0.000445f, 0.000453f, 0.000781f, 0.000794f, 0.001183f, 0.001289f,
+ 0.001479f, 0.001832f, 0.001874f, 0.002256f, 0.002270f, 0.002716f, 0.002960f, 0.003273f, 0.003630f, 0.003948f, 0.004467f, 0.004833f,
+ 0.005451f, 0.005962f, 0.006367f, 0.007088f, 0.007717f, 0.008400f, 0.009506f, 0.010445f, 0.011658f, 0.012993f, 0.014618f, 0.016357f,
+ 0.018524f, 0.021210f, 0.023712f, 0.027252f, 0.031219f, 0.036041f, 0.041962f, 0.049194f, 0.057892f, 0.068604f, 0.082642f, 0.099304f,
+ 0.120728f, 0.147217f, 0.180054f, 0.221191f, 0.269287f, 0.325928f, 0.388916f, 0.457275f, 0.525391f, 0.593262f, 0.657715f, 0.714355f,
+ 0.766113f, 0.809082f, 0.937500f, 0.940918f, 0.941895f, 0.941895f, 0.941895f, 0.942383f, 0.000243f, 0.000238f, 0.000411f, 0.000532f,
+ 0.000530f, 0.000764f, 0.000853f, 0.001171f, 0.001417f, 0.001545f, 0.001799f, 0.001900f, 0.002094f, 0.002354f, 0.002577f, 0.002703f,
+ 0.003155f, 0.003428f, 0.003809f, 0.004227f, 0.004677f, 0.004997f, 0.005386f, 0.005913f, 0.006741f, 0.007225f, 0.008057f, 0.008873f,
+ 0.009819f, 0.011101f, 0.012253f, 0.013725f, 0.015488f, 0.017410f, 0.019791f, 0.022598f, 0.025635f, 0.030014f, 0.034973f, 0.040527f,
+ 0.047729f, 0.056702f, 0.067505f, 0.081848f, 0.099609f, 0.121521f, 0.149902f, 0.185181f, 0.228516f, 0.280762f, 0.341553f, 0.408936f,
+ 0.480225f, 0.552246f, 0.622070f, 0.686035f, 0.742188f, 0.792480f, 0.932129f, 0.935547f, 0.937012f, 0.937012f, 0.936523f, 0.937500f,
+ 0.000000f, 0.000232f, 0.000330f, 0.000512f, 0.000523f, 0.000907f, 0.000953f, 0.001018f, 0.001234f, 0.001344f, 0.001610f, 0.001612f,
+ 0.001845f, 0.002054f, 0.002218f, 0.002453f, 0.002829f, 0.003105f, 0.003300f, 0.003712f, 0.003853f, 0.004280f, 0.004631f, 0.005112f,
+ 0.005665f, 0.006279f, 0.006779f, 0.007481f, 0.008362f, 0.009270f, 0.010338f, 0.011505f, 0.012848f, 0.014549f, 0.016403f, 0.018936f,
+ 0.021622f, 0.024750f, 0.028900f, 0.033447f, 0.039185f, 0.046448f, 0.055603f, 0.067078f, 0.081238f, 0.100037f, 0.123230f, 0.153564f,
+ 0.191284f, 0.238525f, 0.295166f, 0.361084f, 0.432861f, 0.507812f, 0.582520f, 0.653320f, 0.717285f, 0.772461f, 0.926270f, 0.931152f,
+ 0.931152f, 0.932129f, 0.932129f, 0.932129f, 0.000118f, 0.000219f, 0.000227f, 0.000405f, 0.000689f, 0.000726f, 0.000910f, 0.000847f,
+ 0.001072f, 0.001114f, 0.001388f, 0.001447f, 0.001656f, 0.001811f, 0.001897f, 0.002253f, 0.002373f, 0.002617f, 0.002796f, 0.003054f,
+ 0.003414f, 0.003681f, 0.003929f, 0.004353f, 0.004902f, 0.005322f, 0.005863f, 0.006424f, 0.007000f, 0.007755f, 0.008675f, 0.009506f,
+ 0.010704f, 0.012215f, 0.013557f, 0.015686f, 0.017807f, 0.020630f, 0.023376f, 0.027328f, 0.032013f, 0.038177f, 0.045288f, 0.054626f,
+ 0.066284f, 0.081543f, 0.100891f, 0.125977f, 0.158447f, 0.199951f, 0.251465f, 0.313965f, 0.384521f, 0.461670f, 0.540527f, 0.617188f,
+ 0.688965f, 0.750977f, 0.920410f, 0.924805f, 0.925781f, 0.926270f, 0.926758f, 0.925781f, 0.000230f, 0.000198f, 0.000217f, 0.000338f,
+ 0.000584f, 0.000786f, 0.000699f, 0.000893f, 0.000954f, 0.000959f, 0.001153f, 0.001165f, 0.001375f, 0.001545f, 0.001752f, 0.001752f,
+ 0.002062f, 0.002235f, 0.002399f, 0.002699f, 0.002853f, 0.002995f, 0.003372f, 0.003603f, 0.003944f, 0.004513f, 0.004704f, 0.005226f,
+ 0.005878f, 0.006527f, 0.006992f, 0.007889f, 0.008919f, 0.010002f, 0.011124f, 0.012604f, 0.014526f, 0.016510f, 0.019104f, 0.022308f,
+ 0.026077f, 0.030701f, 0.036774f, 0.044098f, 0.053558f, 0.065735f, 0.081299f, 0.101990f, 0.129517f, 0.164917f, 0.210938f, 0.268066f,
+ 0.336914f, 0.413818f, 0.496094f, 0.579102f, 0.657227f, 0.727539f, 0.913574f, 0.917969f, 0.918945f, 0.919434f, 0.919922f, 0.919922f,
+ 0.000000f, 0.000101f, 0.000214f, 0.000208f, 0.000339f, 0.000461f, 0.000577f, 0.000780f, 0.000777f, 0.000840f, 0.000853f, 0.001064f,
+ 0.001198f, 0.001327f, 0.001489f, 0.001687f, 0.001809f, 0.001884f, 0.002008f, 0.002129f, 0.002434f, 0.002514f, 0.002949f, 0.003000f,
+ 0.003351f, 0.003674f, 0.003918f, 0.004356f, 0.004875f, 0.005310f, 0.005768f, 0.006458f, 0.007244f, 0.008255f, 0.008949f, 0.010361f,
+ 0.011589f, 0.013290f, 0.015335f, 0.017776f, 0.020828f, 0.024521f, 0.029236f, 0.035431f, 0.042694f, 0.052490f, 0.065369f, 0.082336f,
+ 0.104492f, 0.134277f, 0.173828f, 0.225464f, 0.290039f, 0.365234f, 0.449707f, 0.536133f, 0.623047f, 0.702637f, 0.905273f, 0.911133f,
+ 0.912598f, 0.913086f, 0.913086f, 0.913086f, 0.000000f, 0.000167f, 0.000167f, 0.000316f, 0.000432f, 0.000444f, 0.000608f, 0.000611f,
+ 0.000678f, 0.000750f, 0.000899f, 0.000925f, 0.001043f, 0.001125f, 0.001222f, 0.001343f, 0.001470f, 0.001608f, 0.001679f, 0.001804f,
+ 0.001976f, 0.002234f, 0.002361f, 0.002710f, 0.002748f, 0.003035f, 0.003290f, 0.003647f, 0.003990f, 0.004295f, 0.004745f, 0.005318f,
+ 0.005920f, 0.006618f, 0.007347f, 0.008270f, 0.009361f, 0.010719f, 0.012291f, 0.014221f, 0.016693f, 0.019592f, 0.023239f, 0.027969f,
+ 0.033752f, 0.041534f, 0.051666f, 0.065369f, 0.083618f, 0.108276f, 0.141357f, 0.186035f, 0.244141f, 0.316650f, 0.400635f, 0.491699f,
+ 0.585938f, 0.672852f, 0.897461f, 0.903320f, 0.904297f, 0.903809f, 0.903809f, 0.904297f, 0.000000f, 0.000098f, 0.000145f, 0.000289f,
+ 0.000399f, 0.000424f, 0.000429f, 0.000382f, 0.000529f, 0.000613f, 0.000660f, 0.000836f, 0.000907f, 0.000940f, 0.001005f, 0.001188f,
+ 0.001306f, 0.001451f, 0.001420f, 0.001554f, 0.001667f, 0.001783f, 0.001955f, 0.002125f, 0.002357f, 0.002493f, 0.002760f, 0.002867f,
+ 0.003298f, 0.003626f, 0.003878f, 0.004341f, 0.004704f, 0.005356f, 0.005905f, 0.006512f, 0.007435f, 0.008377f, 0.009598f, 0.011055f,
+ 0.012978f, 0.015388f, 0.018036f, 0.021698f, 0.026337f, 0.032532f, 0.040192f, 0.050995f, 0.065125f, 0.085510f, 0.113037f, 0.150513f,
+ 0.201538f, 0.268799f, 0.351318f, 0.444824f, 0.543457f, 0.641602f, 0.888672f, 0.894043f, 0.894531f, 0.895508f, 0.895020f, 0.895508f,
+ 0.000000f, 0.000000f, 0.000032f, 0.000169f, 0.000338f, 0.000372f, 0.000468f, 0.000471f, 0.000460f, 0.000493f, 0.000588f, 0.000715f,
+ 0.000762f, 0.000912f, 0.000831f, 0.001001f, 0.001043f, 0.001133f, 0.001242f, 0.001312f, 0.001446f, 0.001529f, 0.001647f, 0.001829f,
+ 0.001982f, 0.002121f, 0.002165f, 0.002438f, 0.002628f, 0.002865f, 0.003113f, 0.003424f, 0.003622f, 0.004131f, 0.004639f, 0.005222f,
+ 0.005875f, 0.006622f, 0.007496f, 0.008575f, 0.009987f, 0.011665f, 0.013985f, 0.016617f, 0.019913f, 0.024704f, 0.030960f, 0.039185f,
+ 0.050323f, 0.066284f, 0.088196f, 0.119568f, 0.163208f, 0.223511f, 0.302002f, 0.395752f, 0.499756f, 0.605957f, 0.878418f, 0.883301f,
+ 0.884766f, 0.884766f, 0.885254f, 0.885254f, 0.000000f, 0.000000f, 0.000000f, 0.000216f, 0.000237f, 0.000338f, 0.000387f, 0.000341f,
+ 0.000435f, 0.000441f, 0.000461f, 0.000577f, 0.000544f, 0.000720f, 0.000813f, 0.000823f, 0.000912f, 0.000936f, 0.000994f, 0.001026f,
+ 0.001240f, 0.001268f, 0.001365f, 0.001415f, 0.001590f, 0.001565f, 0.001870f, 0.001929f, 0.002123f, 0.002377f, 0.002430f, 0.002565f,
+ 0.002947f, 0.003384f, 0.003662f, 0.004105f, 0.004513f, 0.005047f, 0.005741f, 0.006550f, 0.007549f, 0.008865f, 0.010612f, 0.012466f,
+ 0.015350f, 0.018677f, 0.023270f, 0.029800f, 0.038361f, 0.050323f, 0.067932f, 0.092590f, 0.129395f, 0.181274f, 0.253418f, 0.345459f,
+ 0.452637f, 0.567383f, 0.866699f, 0.872559f, 0.873047f, 0.873535f, 0.873047f, 0.873535f, 0.000000f, 0.000000f, 0.000121f, 0.000182f,
+ 0.000187f, 0.000237f, 0.000264f, 0.000360f, 0.000360f, 0.000397f, 0.000398f, 0.000412f, 0.000432f, 0.000546f, 0.000575f, 0.000690f,
+ 0.000731f, 0.000727f, 0.000807f, 0.000843f, 0.000924f, 0.001034f, 0.001093f, 0.001111f, 0.001251f, 0.001249f, 0.001334f, 0.001612f,
+ 0.001717f, 0.001820f, 0.002090f, 0.002161f, 0.002354f, 0.002600f, 0.002787f, 0.003119f, 0.003586f, 0.003878f, 0.004452f, 0.004913f,
+ 0.005772f, 0.006508f, 0.007679f, 0.009285f, 0.011086f, 0.013840f, 0.016968f, 0.021820f, 0.028259f, 0.037628f, 0.050812f, 0.070129f,
+ 0.099670f, 0.143433f, 0.207031f, 0.294922f, 0.403076f, 0.525879f, 0.853516f, 0.859375f, 0.860840f, 0.860352f, 0.862305f, 0.861328f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000181f, 0.000198f, 0.000181f, 0.000240f, 0.000275f, 0.000311f, 0.000427f, 0.000447f,
+ 0.000395f, 0.000472f, 0.000456f, 0.000557f, 0.000518f, 0.000562f, 0.000635f, 0.000664f, 0.000868f, 0.000887f, 0.000865f, 0.001025f,
+ 0.001014f, 0.001164f, 0.001096f, 0.001317f, 0.001382f, 0.001432f, 0.001445f, 0.001765f, 0.001744f, 0.002100f, 0.002144f, 0.002350f,
+ 0.002655f, 0.002947f, 0.003294f, 0.003780f, 0.004265f, 0.004971f, 0.005699f, 0.006786f, 0.007957f, 0.009636f, 0.011932f, 0.015823f,
+ 0.020142f, 0.026749f, 0.036530f, 0.051392f, 0.073792f, 0.109375f, 0.164185f, 0.244629f, 0.351562f, 0.479980f, 0.839355f, 0.844727f,
+ 0.846680f, 0.847656f, 0.847168f, 0.846680f, 0.000000f, 0.000121f, 0.000120f, 0.000119f, 0.000162f, 0.000133f, 0.000170f, 0.000201f,
+ 0.000204f, 0.000222f, 0.000258f, 0.000285f, 0.000324f, 0.000327f, 0.000422f, 0.000395f, 0.000431f, 0.000517f, 0.000632f, 0.000529f,
+ 0.000589f, 0.000592f, 0.000735f, 0.000714f, 0.000795f, 0.000778f, 0.000823f, 0.001063f, 0.001080f, 0.001141f, 0.001154f, 0.001308f,
+ 0.001439f, 0.001546f, 0.001689f, 0.001886f, 0.001978f, 0.002174f, 0.002377f, 0.002798f, 0.003277f, 0.003519f, 0.004181f, 0.004780f,
+ 0.005768f, 0.006863f, 0.008644f, 0.010750f, 0.014030f, 0.018448f, 0.025635f, 0.036194f, 0.053223f, 0.080811f, 0.125610f, 0.196533f,
+ 0.299316f, 0.430176f, 0.822754f, 0.830078f, 0.831055f, 0.831543f, 0.832031f, 0.831543f, 0.000000f, 0.000121f, 0.000120f, 0.000118f,
+ 0.000117f, 0.000120f, 0.000123f, 0.000151f, 0.000154f, 0.000175f, 0.000254f, 0.000190f, 0.000211f, 0.000306f, 0.000335f, 0.000358f,
+ 0.000394f, 0.000417f, 0.000443f, 0.000410f, 0.000565f, 0.000565f, 0.000491f, 0.000623f, 0.000616f, 0.000631f, 0.000738f, 0.000676f,
+ 0.000759f, 0.000924f, 0.000895f, 0.001030f, 0.001064f, 0.001176f, 0.001267f, 0.001438f, 0.001518f, 0.001704f, 0.001742f, 0.002028f,
+ 0.002384f, 0.002703f, 0.002972f, 0.003393f, 0.004051f, 0.004959f, 0.005993f, 0.007271f, 0.009277f, 0.012390f, 0.016968f, 0.024368f,
+ 0.036560f, 0.056610f, 0.091797f, 0.151245f, 0.246460f, 0.379639f, 0.805664f, 0.812500f, 0.813477f, 0.813965f, 0.813965f, 0.813965f,
+ 0.000000f, 0.000000f, 0.000118f, 0.000117f, 0.000116f, 0.000114f, 0.000113f, 0.000108f, 0.000127f, 0.000153f, 0.000133f, 0.000202f,
+ 0.000217f, 0.000223f, 0.000242f, 0.000186f, 0.000280f, 0.000304f, 0.000318f, 0.000342f, 0.000338f, 0.000473f, 0.000360f, 0.000484f,
+ 0.000422f, 0.000514f, 0.000527f, 0.000571f, 0.000633f, 0.000568f, 0.000639f, 0.000816f, 0.000789f, 0.000889f, 0.000891f, 0.000966f,
+ 0.001125f, 0.001276f, 0.001316f, 0.001496f, 0.001658f, 0.001818f, 0.002047f, 0.002502f, 0.002781f, 0.003201f, 0.003914f, 0.004795f,
+ 0.006096f, 0.007996f, 0.010918f, 0.015617f, 0.023697f, 0.037567f, 0.063477f, 0.111084f, 0.194824f, 0.324951f, 0.786133f, 0.792969f,
+ 0.794434f, 0.793945f, 0.794922f, 0.794434f, 0.000000f, 0.000119f, 0.000117f, 0.000115f, 0.000113f, 0.000112f, 0.000110f, 0.000109f,
+ 0.000104f, 0.000098f, 0.000099f, 0.000136f, 0.000112f, 0.000126f, 0.000175f, 0.000189f, 0.000196f, 0.000220f, 0.000216f, 0.000247f,
+ 0.000258f, 0.000274f, 0.000285f, 0.000309f, 0.000308f, 0.000321f, 0.000381f, 0.000390f, 0.000475f, 0.000511f, 0.000485f, 0.000501f,
+ 0.000641f, 0.000588f, 0.000652f, 0.000764f, 0.000808f, 0.000952f, 0.000906f, 0.001037f, 0.001110f, 0.001249f, 0.001411f, 0.001647f,
+ 0.001894f, 0.002159f, 0.002687f, 0.003223f, 0.004036f, 0.005150f, 0.006989f, 0.009644f, 0.014420f, 0.023361f, 0.040802f, 0.076050f,
+ 0.146362f, 0.269287f, 0.763184f, 0.770996f, 0.771973f, 0.771973f, 0.772461f, 0.772461f, 0.000121f, 0.000116f, 0.000114f, 0.000112f,
+ 0.000109f, 0.000108f, 0.000106f, 0.000105f, 0.000104f, 0.000101f, 0.000095f, 0.000090f, 0.000085f, 0.000083f, 0.000104f, 0.000097f,
+ 0.000094f, 0.000154f, 0.000127f, 0.000178f, 0.000197f, 0.000194f, 0.000233f, 0.000213f, 0.000279f, 0.000294f, 0.000293f, 0.000258f,
+ 0.000319f, 0.000394f, 0.000344f, 0.000369f, 0.000394f, 0.000410f, 0.000438f, 0.000509f, 0.000514f, 0.000580f, 0.000617f, 0.000684f,
+ 0.000807f, 0.000812f, 0.000914f, 0.001094f, 0.001183f, 0.001436f, 0.001639f, 0.002033f, 0.002523f, 0.003073f, 0.004063f, 0.005680f,
+ 0.008560f, 0.013466f, 0.024109f, 0.047791f, 0.102051f, 0.213867f, 0.740234f, 0.746582f, 0.748047f, 0.748535f, 0.749023f, 0.749023f,
+ 0.000000f, 0.000113f, 0.000108f, 0.000107f, 0.000104f, 0.000102f, 0.000099f, 0.000099f, 0.000097f, 0.000096f, 0.000095f, 0.000091f,
+ 0.000086f, 0.000081f, 0.000077f, 0.000073f, 0.000085f, 0.000091f, 0.000070f, 0.000102f, 0.000117f, 0.000131f, 0.000145f, 0.000148f,
+ 0.000171f, 0.000178f, 0.000178f, 0.000207f, 0.000225f, 0.000209f, 0.000285f, 0.000238f, 0.000260f, 0.000298f, 0.000331f, 0.000360f,
+ 0.000371f, 0.000346f, 0.000407f, 0.000443f, 0.000494f, 0.000516f, 0.000578f, 0.000662f, 0.000767f, 0.000847f, 0.001004f, 0.001149f,
+ 0.001451f, 0.001783f, 0.002310f, 0.003262f, 0.004593f, 0.007309f, 0.012985f, 0.026703f, 0.064026f, 0.158813f, 0.712891f, 0.719238f,
+ 0.722168f, 0.721680f, 0.722168f, 0.722656f, 0.000000f, 0.000105f, 0.000102f, 0.000098f, 0.000094f, 0.000092f, 0.000091f, 0.000089f,
+ 0.000088f, 0.000086f, 0.000085f, 0.000084f, 0.000083f, 0.000080f, 0.000076f, 0.000073f, 0.000069f, 0.000065f, 0.000062f, 0.000059f,
+ 0.000068f, 0.000063f, 0.000069f, 0.000074f, 0.000087f, 0.000102f, 0.000112f, 0.000130f, 0.000137f, 0.000129f, 0.000143f, 0.000168f,
+ 0.000180f, 0.000178f, 0.000189f, 0.000198f, 0.000222f, 0.000240f, 0.000262f, 0.000285f, 0.000304f, 0.000317f, 0.000339f, 0.000399f,
+ 0.000439f, 0.000490f, 0.000570f, 0.000658f, 0.000781f, 0.000988f, 0.001235f, 0.001674f, 0.002407f, 0.003725f, 0.006485f, 0.013199f,
+ 0.034546f, 0.107605f, 0.682129f, 0.691406f, 0.692871f, 0.691406f, 0.692871f, 0.692871f, 0.000105f, 0.000089f, 0.000085f, 0.000080f,
+ 0.000078f, 0.000078f, 0.000075f, 0.000074f, 0.000072f, 0.000072f, 0.000070f, 0.000071f, 0.000069f, 0.000069f, 0.000069f, 0.000068f,
+ 0.000066f, 0.000063f, 0.000060f, 0.000057f, 0.000054f, 0.000052f, 0.000049f, 0.000047f, 0.000046f, 0.000045f, 0.000048f, 0.000055f,
+ 0.000060f, 0.000068f, 0.000083f, 0.000087f, 0.000092f, 0.000103f, 0.000109f, 0.000117f, 0.000130f, 0.000150f, 0.000148f, 0.000142f,
+ 0.000167f, 0.000186f, 0.000210f, 0.000213f, 0.000232f, 0.000280f, 0.000292f, 0.000329f, 0.000391f, 0.000456f, 0.000596f, 0.000764f,
+ 0.001065f, 0.001633f, 0.002806f, 0.005909f, 0.015488f, 0.062378f, 0.651367f, 0.659668f, 0.661133f, 0.661133f, 0.660645f, 0.661621f,
+ 0.000034f, 0.000037f, 0.000048f, 0.000051f, 0.000047f, 0.000049f, 0.000047f, 0.000051f, 0.000049f, 0.000051f, 0.000049f, 0.000050f,
+ 0.000051f, 0.000050f, 0.000050f, 0.000049f, 0.000051f, 0.000050f, 0.000051f, 0.000050f, 0.000049f, 0.000047f, 0.000045f, 0.000043f,
+ 0.000041f, 0.000039f, 0.000037f, 0.000035f, 0.000033f, 0.000032f, 0.000030f, 0.000029f, 0.000034f, 0.000041f, 0.000046f, 0.000057f,
+ 0.000063f, 0.000067f, 0.000065f, 0.000072f, 0.000083f, 0.000093f, 0.000096f, 0.000102f, 0.000102f, 0.000135f, 0.000134f, 0.000151f,
+ 0.000184f, 0.000198f, 0.000245f, 0.000306f, 0.000425f, 0.000607f, 0.001032f, 0.002081f, 0.005886f, 0.027924f, 0.617188f, 0.625977f,
+ 0.627441f, 0.627930f, 0.626953f, 0.628418f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000010f, 0.000014f,
+ 0.000016f, 0.000014f, 0.000019f, 0.000022f, 0.000022f, 0.000022f, 0.000025f, 0.000026f, 0.000027f, 0.000028f, 0.000029f, 0.000029f,
+ 0.000029f, 0.000030f, 0.000030f, 0.000031f, 0.000032f, 0.000032f, 0.000031f, 0.000030f, 0.000028f, 0.000027f, 0.000026f, 0.000024f,
+ 0.000023f, 0.000022f, 0.000021f, 0.000020f, 0.000019f, 0.000021f, 0.000022f, 0.000024f, 0.000027f, 0.000035f, 0.000041f, 0.000034f,
+ 0.000041f, 0.000052f, 0.000051f, 0.000051f, 0.000058f, 0.000070f, 0.000074f, 0.000103f, 0.000119f, 0.000169f, 0.000277f, 0.000510f,
+ 0.001495f, 0.008766f, 0.583008f, 0.590332f, 0.591797f, 0.591797f, 0.592285f, 0.592285f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000002f, 0.000003f, 0.000005f, 0.000006f, 0.000008f, 0.000009f, 0.000010f, 0.000010f,
+ 0.000012f, 0.000012f, 0.000013f, 0.000014f, 0.000015f, 0.000015f, 0.000015f, 0.000015f, 0.000014f, 0.000013f, 0.000013f, 0.000012f,
+ 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000014f, 0.000011f, 0.000015f, 0.000017f, 0.000017f, 0.000021f, 0.000020f,
+ 0.000026f, 0.000026f, 0.000042f, 0.000069f, 0.000178f, 0.001302f, 0.544434f, 0.553711f, 0.554688f, 0.554688f, 0.556152f, 0.556641f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000002f, 0.000003f, 0.000003f,
+ 0.000003f, 0.000003f, 0.000003f, 0.000002f, 0.000002f, 0.000001f, 0.000003f, 0.000003f, 0.000004f, 0.000014f, 0.506836f, 0.515137f,
+ 0.516113f, 0.516602f, 0.517090f, 0.517578f,
+ },
+ {
+ 0.089539f, 0.244873f, 0.368164f, 0.464355f, 0.539551f, 0.599121f, 0.648438f, 0.688477f, 0.721680f, 0.749512f, 0.772461f, 0.793945f,
+ 0.811523f, 0.826172f, 0.841309f, 0.854004f, 0.863770f, 0.874512f, 0.883301f, 0.891602f, 0.898438f, 0.906250f, 0.912109f, 0.917969f,
+ 0.922852f, 0.928223f, 0.932617f, 0.937012f, 0.940918f, 0.944336f, 0.948242f, 0.951660f, 0.954590f, 0.957520f, 0.960449f, 0.962891f,
+ 0.965820f, 0.967773f, 0.970215f, 0.972656f, 0.974609f, 0.976074f, 0.978516f, 0.979492f, 0.981934f, 0.983398f, 0.984863f, 0.986328f,
+ 0.987793f, 0.988770f, 0.990234f, 0.991699f, 0.993164f, 0.994141f, 0.995117f, 0.996582f, 0.997559f, 0.998535f, 0.999023f, 0.998535f,
+ 0.997559f, 0.997070f, 0.996582f, 0.995605f, 0.045563f, 0.143921f, 0.242798f, 0.334717f, 0.417969f, 0.489258f, 0.550293f, 0.602051f,
+ 0.646484f, 0.683594f, 0.715820f, 0.743652f, 0.767090f, 0.788086f, 0.805664f, 0.822266f, 0.836426f, 0.849609f, 0.861328f, 0.870117f,
+ 0.879883f, 0.889160f, 0.896973f, 0.903320f, 0.909668f, 0.916016f, 0.921875f, 0.926758f, 0.931641f, 0.936523f, 0.940430f, 0.943848f,
+ 0.947266f, 0.951172f, 0.954102f, 0.957520f, 0.960449f, 0.962891f, 0.965820f, 0.968262f, 0.970215f, 0.973145f, 0.974121f, 0.976074f,
+ 0.979004f, 0.980469f, 0.982422f, 0.983887f, 0.985352f, 0.986816f, 0.988281f, 0.989746f, 0.991211f, 0.992188f, 0.994141f, 0.995117f,
+ 0.996094f, 0.997070f, 0.998535f, 0.997559f, 0.997070f, 0.996582f, 0.996094f, 0.995117f, 0.026855f, 0.089233f, 0.159790f, 0.234619f,
+ 0.308838f, 0.381348f, 0.447754f, 0.507812f, 0.561035f, 0.606934f, 0.646484f, 0.683105f, 0.712402f, 0.740234f, 0.763184f, 0.784668f,
+ 0.802246f, 0.819336f, 0.833984f, 0.846680f, 0.857910f, 0.868652f, 0.878418f, 0.886719f, 0.895508f, 0.903320f, 0.909668f, 0.915527f,
+ 0.920410f, 0.926270f, 0.931152f, 0.935547f, 0.940430f, 0.943848f, 0.947754f, 0.951172f, 0.954590f, 0.958008f, 0.960449f, 0.963379f,
+ 0.966309f, 0.968750f, 0.971191f, 0.973145f, 0.975586f, 0.977051f, 0.979004f, 0.981445f, 0.982910f, 0.983887f, 0.985840f, 0.987305f,
+ 0.988770f, 0.990723f, 0.992188f, 0.993164f, 0.994629f, 0.996094f, 0.998047f, 0.997070f, 0.996582f, 0.996094f, 0.995605f, 0.995117f,
+ 0.017746f, 0.058746f, 0.108276f, 0.163818f, 0.224365f, 0.288086f, 0.351562f, 0.413086f, 0.470947f, 0.522949f, 0.569824f, 0.612793f,
+ 0.650879f, 0.684570f, 0.713867f, 0.739258f, 0.762695f, 0.783203f, 0.800781f, 0.817871f, 0.833008f, 0.845215f, 0.857422f, 0.868164f,
+ 0.877441f, 0.886230f, 0.894043f, 0.902832f, 0.908691f, 0.915039f, 0.921387f, 0.925781f, 0.930664f, 0.936035f, 0.939941f, 0.944336f,
+ 0.948242f, 0.951660f, 0.955078f, 0.957520f, 0.961426f, 0.964355f, 0.967285f, 0.968750f, 0.971680f, 0.974121f, 0.975586f, 0.978027f,
+ 0.979980f, 0.981934f, 0.983887f, 0.985352f, 0.987305f, 0.988770f, 0.989746f, 0.991211f, 0.992676f, 0.993652f, 0.997070f, 0.996582f,
+ 0.996582f, 0.996094f, 0.995117f, 0.994629f, 0.012337f, 0.041229f, 0.075928f, 0.117065f, 0.163208f, 0.214478f, 0.270020f, 0.327148f,
+ 0.383301f, 0.437500f, 0.490234f, 0.536621f, 0.581543f, 0.621094f, 0.656250f, 0.688477f, 0.716797f, 0.741699f, 0.763672f, 0.784668f,
+ 0.802246f, 0.818359f, 0.832520f, 0.845703f, 0.857422f, 0.868164f, 0.877930f, 0.886230f, 0.895020f, 0.902344f, 0.909668f, 0.915039f,
+ 0.921875f, 0.926758f, 0.931641f, 0.937012f, 0.940430f, 0.946289f, 0.949219f, 0.952637f, 0.956055f, 0.958984f, 0.961914f, 0.964844f,
+ 0.967773f, 0.970215f, 0.972656f, 0.974609f, 0.976562f, 0.979004f, 0.980957f, 0.982910f, 0.984863f, 0.986816f, 0.987793f, 0.989746f,
+ 0.990723f, 0.992676f, 0.996582f, 0.996094f, 0.995605f, 0.995117f, 0.994629f, 0.994141f, 0.009315f, 0.030411f, 0.055756f, 0.085632f,
+ 0.121094f, 0.160889f, 0.206055f, 0.254150f, 0.305664f, 0.357422f, 0.408447f, 0.459717f, 0.506836f, 0.551270f, 0.592773f, 0.629395f,
+ 0.662598f, 0.692871f, 0.719727f, 0.745117f, 0.767090f, 0.786133f, 0.804688f, 0.819336f, 0.834473f, 0.847168f, 0.858398f, 0.869629f,
+ 0.879395f, 0.888672f, 0.895020f, 0.903320f, 0.910156f, 0.916016f, 0.922363f, 0.928223f, 0.933105f, 0.937012f, 0.941406f, 0.946289f,
+ 0.950195f, 0.954102f, 0.957031f, 0.960449f, 0.963379f, 0.965820f, 0.969238f, 0.971191f, 0.974121f, 0.976074f, 0.978027f, 0.979980f,
+ 0.982422f, 0.984375f, 0.985840f, 0.987793f, 0.989258f, 0.990723f, 0.995605f, 0.995605f, 0.995117f, 0.994629f, 0.994629f, 0.993652f,
+ 0.006634f, 0.022736f, 0.041962f, 0.064026f, 0.090759f, 0.122192f, 0.157593f, 0.197510f, 0.240356f, 0.287354f, 0.335693f, 0.384766f,
+ 0.432373f, 0.479736f, 0.523438f, 0.565430f, 0.604004f, 0.639160f, 0.670898f, 0.699219f, 0.726562f, 0.749023f, 0.770508f, 0.790527f,
+ 0.806641f, 0.822754f, 0.836426f, 0.848633f, 0.859863f, 0.871582f, 0.881348f, 0.889160f, 0.897949f, 0.905273f, 0.912598f, 0.918945f,
+ 0.924316f, 0.929199f, 0.935059f, 0.938965f, 0.943848f, 0.947266f, 0.951660f, 0.955078f, 0.958496f, 0.961914f, 0.964844f, 0.967773f,
+ 0.970703f, 0.973145f, 0.975098f, 0.977539f, 0.979492f, 0.981445f, 0.983887f, 0.985352f, 0.987305f, 0.989258f, 0.995117f, 0.994629f,
+ 0.994141f, 0.994141f, 0.993652f, 0.993164f, 0.005428f, 0.017807f, 0.032166f, 0.049652f, 0.070007f, 0.093811f, 0.121765f, 0.153564f,
+ 0.189087f, 0.228516f, 0.270752f, 0.316162f, 0.362061f, 0.408936f, 0.453857f, 0.498779f, 0.540527f, 0.579590f, 0.615723f, 0.649902f,
+ 0.679688f, 0.707520f, 0.732422f, 0.755371f, 0.775391f, 0.794922f, 0.811035f, 0.826172f, 0.839844f, 0.852051f, 0.864258f, 0.875000f,
+ 0.883301f, 0.892578f, 0.899902f, 0.907715f, 0.914062f, 0.920410f, 0.926270f, 0.931641f, 0.936035f, 0.940918f, 0.945312f, 0.949219f,
+ 0.954102f, 0.957031f, 0.960938f, 0.963379f, 0.966797f, 0.969238f, 0.972168f, 0.974609f, 0.977051f, 0.979492f, 0.980957f, 0.983398f,
+ 0.985352f, 0.987305f, 0.994141f, 0.994141f, 0.994141f, 0.993652f, 0.993164f, 0.992676f, 0.004223f, 0.014046f, 0.025452f, 0.039062f,
+ 0.055115f, 0.073608f, 0.095642f, 0.120239f, 0.149292f, 0.182251f, 0.217529f, 0.257080f, 0.298828f, 0.342773f, 0.387207f, 0.431152f,
+ 0.474609f, 0.516602f, 0.556641f, 0.593750f, 0.628418f, 0.660156f, 0.689453f, 0.715820f, 0.740723f, 0.762207f, 0.782227f, 0.799805f,
+ 0.816406f, 0.830566f, 0.844727f, 0.855469f, 0.867188f, 0.877441f, 0.886230f, 0.895020f, 0.903809f, 0.910645f, 0.917480f, 0.923340f,
+ 0.928711f, 0.934570f, 0.939453f, 0.943848f, 0.948242f, 0.952148f, 0.956055f, 0.959473f, 0.961914f, 0.965820f, 0.968750f, 0.971680f,
+ 0.974121f, 0.975586f, 0.979004f, 0.980957f, 0.983398f, 0.985352f, 0.993652f, 0.993652f, 0.993164f, 0.993164f, 0.992676f, 0.991699f,
+ 0.003532f, 0.011536f, 0.020645f, 0.031342f, 0.044098f, 0.058624f, 0.075989f, 0.096252f, 0.119141f, 0.145386f, 0.175049f, 0.208130f,
+ 0.244385f, 0.283203f, 0.324463f, 0.367432f, 0.410400f, 0.453369f, 0.495361f, 0.534668f, 0.572266f, 0.607910f, 0.641602f, 0.672852f,
+ 0.700195f, 0.725098f, 0.748047f, 0.769531f, 0.789062f, 0.806152f, 0.821777f, 0.835938f, 0.848633f, 0.860352f, 0.872070f, 0.881836f,
+ 0.890625f, 0.898926f, 0.906738f, 0.913086f, 0.919922f, 0.925781f, 0.931641f, 0.936523f, 0.941406f, 0.946289f, 0.950684f, 0.954590f,
+ 0.958008f, 0.961426f, 0.964844f, 0.968262f, 0.970703f, 0.973633f, 0.976074f, 0.978516f, 0.980469f, 0.982910f, 0.992676f, 0.992676f,
+ 0.992188f, 0.992188f, 0.991699f, 0.990723f, 0.002850f, 0.009483f, 0.016647f, 0.025833f, 0.035889f, 0.047424f, 0.061646f, 0.076660f,
+ 0.095642f, 0.117065f, 0.141113f, 0.168457f, 0.198975f, 0.233032f, 0.269775f, 0.308838f, 0.349854f, 0.391357f, 0.432861f, 0.474121f,
+ 0.515625f, 0.552734f, 0.589355f, 0.622559f, 0.654785f, 0.683594f, 0.710938f, 0.735352f, 0.757812f, 0.777344f, 0.795898f, 0.812988f,
+ 0.827637f, 0.842285f, 0.854492f, 0.866211f, 0.876953f, 0.886719f, 0.895508f, 0.902832f, 0.911133f, 0.917969f, 0.924316f, 0.929688f,
+ 0.935059f, 0.940430f, 0.945312f, 0.949219f, 0.953125f, 0.958008f, 0.961426f, 0.964844f, 0.967285f, 0.970703f, 0.973633f, 0.975586f,
+ 0.978516f, 0.981445f, 0.991699f, 0.992188f, 0.991699f, 0.991211f, 0.991211f, 0.990723f, 0.002628f, 0.007713f, 0.014069f, 0.021484f,
+ 0.029709f, 0.038910f, 0.050201f, 0.063171f, 0.078186f, 0.094849f, 0.114563f, 0.137329f, 0.162720f, 0.190918f, 0.222656f, 0.257568f,
+ 0.293945f, 0.332764f, 0.372803f, 0.414551f, 0.455078f, 0.495361f, 0.533691f, 0.571289f, 0.606445f, 0.639160f, 0.668457f, 0.697754f,
+ 0.723633f, 0.746094f, 0.767090f, 0.787598f, 0.804199f, 0.820801f, 0.834473f, 0.848633f, 0.860352f, 0.872559f, 0.882324f, 0.891602f,
+ 0.899902f, 0.907715f, 0.915039f, 0.921387f, 0.927734f, 0.934082f, 0.938965f, 0.944824f, 0.948730f, 0.953125f, 0.956543f, 0.960938f,
+ 0.963867f, 0.967285f, 0.970215f, 0.973145f, 0.976074f, 0.978516f, 0.990234f, 0.990723f, 0.990723f, 0.991211f, 0.990234f, 0.990234f,
+ 0.002131f, 0.006535f, 0.012016f, 0.017670f, 0.024780f, 0.032837f, 0.041199f, 0.051819f, 0.063904f, 0.077759f, 0.093689f, 0.112610f,
+ 0.133057f, 0.156860f, 0.183472f, 0.213257f, 0.245605f, 0.281006f, 0.318115f, 0.357422f, 0.397217f, 0.437500f, 0.478271f, 0.516602f,
+ 0.554688f, 0.589844f, 0.623535f, 0.654785f, 0.684082f, 0.710938f, 0.734375f, 0.757812f, 0.777832f, 0.795898f, 0.813477f, 0.828613f,
+ 0.843262f, 0.855957f, 0.867676f, 0.878906f, 0.888184f, 0.897461f, 0.905273f, 0.912598f, 0.919922f, 0.926758f, 0.932129f, 0.937988f,
+ 0.942871f, 0.947754f, 0.951660f, 0.955566f, 0.960449f, 0.964355f, 0.967285f, 0.970215f, 0.973145f, 0.976074f, 0.989746f, 0.990234f,
+ 0.990234f, 0.990234f, 0.989746f, 0.988770f, 0.001566f, 0.005798f, 0.010231f, 0.015259f, 0.020920f, 0.027176f, 0.034607f, 0.043335f,
+ 0.052887f, 0.064392f, 0.077576f, 0.092712f, 0.109802f, 0.129639f, 0.151611f, 0.176758f, 0.204346f, 0.235474f, 0.269043f, 0.304688f,
+ 0.342529f, 0.381836f, 0.421143f, 0.460449f, 0.500488f, 0.538086f, 0.574219f, 0.608887f, 0.640625f, 0.670898f, 0.699219f, 0.725098f,
+ 0.748535f, 0.769043f, 0.788574f, 0.807129f, 0.823242f, 0.837402f, 0.850586f, 0.863281f, 0.874512f, 0.885254f, 0.894043f, 0.902832f,
+ 0.910645f, 0.917969f, 0.924805f, 0.931152f, 0.936523f, 0.941895f, 0.947266f, 0.951172f, 0.955566f, 0.960449f, 0.963867f, 0.966797f,
+ 0.970703f, 0.973145f, 0.988281f, 0.989258f, 0.989258f, 0.989258f, 0.988770f, 0.988281f, 0.001427f, 0.004749f, 0.008934f, 0.012833f,
+ 0.017670f, 0.023483f, 0.029114f, 0.036438f, 0.044556f, 0.054047f, 0.064453f, 0.077148f, 0.091309f, 0.107544f, 0.125854f, 0.146729f,
+ 0.170776f, 0.197266f, 0.226440f, 0.257568f, 0.292236f, 0.329346f, 0.367188f, 0.405762f, 0.445557f, 0.484619f, 0.522949f, 0.559570f,
+ 0.595215f, 0.627441f, 0.659180f, 0.687012f, 0.714355f, 0.739258f, 0.761719f, 0.781738f, 0.800781f, 0.817383f, 0.833984f, 0.847168f,
+ 0.859375f, 0.872070f, 0.882324f, 0.891602f, 0.900879f, 0.909668f, 0.916504f, 0.923828f, 0.930176f, 0.936523f, 0.941895f, 0.946777f,
+ 0.951172f, 0.956055f, 0.960449f, 0.963867f, 0.967285f, 0.970703f, 0.987305f, 0.988770f, 0.988281f, 0.987793f, 0.987793f, 0.987793f,
+ 0.001357f, 0.004501f, 0.007557f, 0.011284f, 0.015236f, 0.019791f, 0.025101f, 0.030838f, 0.037628f, 0.045532f, 0.054596f, 0.064636f,
+ 0.076355f, 0.089905f, 0.105042f, 0.122498f, 0.142334f, 0.164307f, 0.189697f, 0.217896f, 0.248413f, 0.281494f, 0.316406f, 0.354004f,
+ 0.391846f, 0.430664f, 0.469971f, 0.508301f, 0.545898f, 0.582031f, 0.615723f, 0.647461f, 0.677734f, 0.704590f, 0.731445f, 0.754395f,
+ 0.775391f, 0.794922f, 0.811523f, 0.829102f, 0.842773f, 0.856934f, 0.868652f, 0.880371f, 0.891113f, 0.899414f, 0.908203f, 0.915527f,
+ 0.922852f, 0.930176f, 0.936035f, 0.941406f, 0.947266f, 0.951660f, 0.957031f, 0.960449f, 0.963867f, 0.968262f, 0.986328f, 0.987305f,
+ 0.987793f, 0.987305f, 0.987305f, 0.986816f, 0.001239f, 0.003864f, 0.006699f, 0.009621f, 0.013008f, 0.017059f, 0.021805f, 0.026703f,
+ 0.032562f, 0.039185f, 0.045807f, 0.054352f, 0.064514f, 0.075439f, 0.088257f, 0.102478f, 0.119263f, 0.138306f, 0.159546f, 0.183228f,
+ 0.209961f, 0.239258f, 0.271484f, 0.305176f, 0.341797f, 0.379639f, 0.417480f, 0.456787f, 0.495605f, 0.532227f, 0.570801f, 0.604980f,
+ 0.637207f, 0.666992f, 0.696289f, 0.722656f, 0.746582f, 0.768555f, 0.789062f, 0.808105f, 0.824219f, 0.839844f, 0.854492f, 0.865723f,
+ 0.878418f, 0.888672f, 0.897461f, 0.906738f, 0.915039f, 0.922363f, 0.929199f, 0.935547f, 0.941895f, 0.946289f, 0.952148f, 0.956543f,
+ 0.960449f, 0.964844f, 0.985352f, 0.986816f, 0.986816f, 0.986328f, 0.986328f, 0.985840f, 0.001151f, 0.003429f, 0.005753f, 0.008400f,
+ 0.011391f, 0.014877f, 0.018494f, 0.022858f, 0.028046f, 0.033112f, 0.039642f, 0.046661f, 0.054565f, 0.064026f, 0.074280f, 0.086243f,
+ 0.100403f, 0.116150f, 0.133789f, 0.154053f, 0.176636f, 0.202393f, 0.230957f, 0.261719f, 0.295166f, 0.330322f, 0.367432f, 0.405518f,
+ 0.445312f, 0.483398f, 0.520996f, 0.558105f, 0.594238f, 0.626465f, 0.659668f, 0.688477f, 0.714844f, 0.740723f, 0.763672f, 0.784180f,
+ 0.804199f, 0.821289f, 0.837402f, 0.852051f, 0.864258f, 0.876465f, 0.886719f, 0.897949f, 0.906250f, 0.915039f, 0.922363f, 0.929199f,
+ 0.935547f, 0.941406f, 0.946777f, 0.952637f, 0.958008f, 0.961914f, 0.983887f, 0.985840f, 0.985352f, 0.985352f, 0.984863f, 0.984863f,
+ 0.001000f, 0.002768f, 0.005127f, 0.007515f, 0.010155f, 0.013283f, 0.016205f, 0.019714f, 0.023987f, 0.028854f, 0.033905f, 0.040161f,
+ 0.046814f, 0.054199f, 0.063110f, 0.073303f, 0.084839f, 0.098145f, 0.112854f, 0.129883f, 0.149292f, 0.171387f, 0.195435f, 0.222778f,
+ 0.252686f, 0.285400f, 0.320312f, 0.356689f, 0.394531f, 0.433105f, 0.471924f, 0.510742f, 0.547852f, 0.584473f, 0.617676f, 0.650879f,
+ 0.680664f, 0.708984f, 0.734375f, 0.759277f, 0.780762f, 0.799805f, 0.817383f, 0.834473f, 0.849121f, 0.862793f, 0.875488f, 0.886719f,
+ 0.896484f, 0.906250f, 0.915039f, 0.923828f, 0.930176f, 0.936035f, 0.942871f, 0.948242f, 0.953613f, 0.958008f, 0.982910f, 0.983887f,
+ 0.984375f, 0.983887f, 0.984375f, 0.983398f, 0.000799f, 0.002705f, 0.004459f, 0.006573f, 0.008842f, 0.011375f, 0.014099f, 0.017487f,
+ 0.020798f, 0.024963f, 0.029465f, 0.034637f, 0.039703f, 0.046478f, 0.054047f, 0.062256f, 0.072388f, 0.082947f, 0.095764f, 0.110229f,
+ 0.126099f, 0.144775f, 0.165771f, 0.189697f, 0.216187f, 0.244995f, 0.276123f, 0.310303f, 0.346191f, 0.384521f, 0.422607f, 0.461670f,
+ 0.500000f, 0.538574f, 0.575195f, 0.609863f, 0.643555f, 0.673828f, 0.702637f, 0.730469f, 0.754395f, 0.777344f, 0.797363f, 0.815430f,
+ 0.833008f, 0.848633f, 0.861328f, 0.875000f, 0.886719f, 0.896973f, 0.906738f, 0.915039f, 0.923340f, 0.930176f, 0.936523f, 0.943848f,
+ 0.948730f, 0.954102f, 0.981445f, 0.983398f, 0.982910f, 0.983398f, 0.982910f, 0.982910f, 0.000774f, 0.002554f, 0.003899f, 0.005875f,
+ 0.007759f, 0.009949f, 0.012733f, 0.015060f, 0.018280f, 0.021667f, 0.025574f, 0.029678f, 0.034698f, 0.040405f, 0.046570f, 0.053650f,
+ 0.061462f, 0.071106f, 0.081360f, 0.093323f, 0.107300f, 0.122864f, 0.140747f, 0.160522f, 0.183960f, 0.209229f, 0.237305f, 0.268799f,
+ 0.302002f, 0.337402f, 0.374023f, 0.413330f, 0.451904f, 0.490967f, 0.529785f, 0.567383f, 0.603027f, 0.636719f, 0.668457f, 0.698242f,
+ 0.725586f, 0.750977f, 0.773926f, 0.793945f, 0.813965f, 0.831543f, 0.847656f, 0.861816f, 0.874512f, 0.886719f, 0.897461f, 0.906738f,
+ 0.915527f, 0.923828f, 0.931641f, 0.937988f, 0.944824f, 0.949707f, 0.979980f, 0.981934f, 0.981934f, 0.981934f, 0.981934f, 0.981445f,
+ 0.000657f, 0.001934f, 0.003330f, 0.005280f, 0.006748f, 0.009079f, 0.010994f, 0.013763f, 0.015945f, 0.019150f, 0.022003f, 0.026001f,
+ 0.030350f, 0.034790f, 0.040253f, 0.045898f, 0.052795f, 0.060852f, 0.069641f, 0.079346f, 0.091187f, 0.104492f, 0.119751f, 0.136963f,
+ 0.156372f, 0.178345f, 0.203247f, 0.230957f, 0.260742f, 0.294189f, 0.328613f, 0.365723f, 0.403564f, 0.443115f, 0.482910f, 0.521484f,
+ 0.559570f, 0.596680f, 0.630859f, 0.664062f, 0.694336f, 0.722168f, 0.747559f, 0.771484f, 0.793457f, 0.813477f, 0.830078f, 0.846191f,
+ 0.861816f, 0.874023f, 0.887207f, 0.898438f, 0.908691f, 0.916992f, 0.925293f, 0.933594f, 0.939941f, 0.946777f, 0.978516f, 0.980469f,
+ 0.980469f, 0.980469f, 0.980469f, 0.980469f, 0.000818f, 0.001935f, 0.003246f, 0.004658f, 0.006229f, 0.007912f, 0.010017f, 0.012093f,
+ 0.014259f, 0.016586f, 0.019653f, 0.022659f, 0.026413f, 0.030289f, 0.034790f, 0.039917f, 0.045441f, 0.052338f, 0.059479f, 0.068115f,
+ 0.077759f, 0.089050f, 0.102051f, 0.116272f, 0.133179f, 0.152344f, 0.173340f, 0.197876f, 0.224243f, 0.254150f, 0.286621f, 0.321533f,
+ 0.357666f, 0.396729f, 0.436279f, 0.475830f, 0.514648f, 0.553711f, 0.590332f, 0.626465f, 0.659180f, 0.689941f, 0.719238f, 0.746094f,
+ 0.770020f, 0.792480f, 0.812500f, 0.830566f, 0.846680f, 0.862305f, 0.875977f, 0.888184f, 0.899414f, 0.910156f, 0.918945f, 0.927246f,
+ 0.935059f, 0.941895f, 0.977051f, 0.979004f, 0.979492f, 0.979004f, 0.979492f, 0.979004f, 0.000583f, 0.001696f, 0.003044f, 0.004276f,
+ 0.005394f, 0.007111f, 0.009048f, 0.010727f, 0.012802f, 0.014549f, 0.017319f, 0.019943f, 0.023132f, 0.026459f, 0.030212f, 0.034576f,
+ 0.039612f, 0.045105f, 0.051422f, 0.058594f, 0.066833f, 0.076416f, 0.087341f, 0.099792f, 0.113647f, 0.130005f, 0.147827f, 0.168945f,
+ 0.192261f, 0.218750f, 0.247803f, 0.280029f, 0.314209f, 0.351074f, 0.389404f, 0.429199f, 0.468750f, 0.508301f, 0.547852f, 0.585938f,
+ 0.622070f, 0.655762f, 0.687988f, 0.718262f, 0.744629f, 0.769531f, 0.792480f, 0.812500f, 0.832520f, 0.848633f, 0.863770f, 0.877441f,
+ 0.890137f, 0.901367f, 0.912109f, 0.921387f, 0.929199f, 0.937500f, 0.975586f, 0.978027f, 0.978027f, 0.977539f, 0.977539f, 0.977051f,
+ 0.000463f, 0.001634f, 0.002899f, 0.003574f, 0.004932f, 0.006233f, 0.007866f, 0.009644f, 0.011055f, 0.012894f, 0.015518f, 0.017792f,
+ 0.020279f, 0.023178f, 0.026657f, 0.030136f, 0.034271f, 0.039062f, 0.044586f, 0.050446f, 0.057739f, 0.065613f, 0.074646f, 0.084900f,
+ 0.097107f, 0.111023f, 0.126099f, 0.143921f, 0.164673f, 0.187500f, 0.213257f, 0.242065f, 0.273926f, 0.308594f, 0.344971f, 0.383301f,
+ 0.423340f, 0.463623f, 0.503906f, 0.543945f, 0.582520f, 0.619629f, 0.653809f, 0.686523f, 0.717285f, 0.744629f, 0.770020f, 0.792969f,
+ 0.814453f, 0.833496f, 0.850098f, 0.866211f, 0.879395f, 0.893066f, 0.904297f, 0.914551f, 0.923828f, 0.932129f, 0.973145f, 0.976074f,
+ 0.976562f, 0.976074f, 0.976074f, 0.976074f, 0.000472f, 0.001289f, 0.002508f, 0.003481f, 0.004459f, 0.005894f, 0.007042f, 0.008232f,
+ 0.009972f, 0.011719f, 0.013435f, 0.015884f, 0.017899f, 0.020386f, 0.023422f, 0.026428f, 0.030411f, 0.034180f, 0.038757f, 0.043854f,
+ 0.049652f, 0.056549f, 0.064270f, 0.073303f, 0.083252f, 0.095093f, 0.107910f, 0.123169f, 0.141113f, 0.160645f, 0.183472f, 0.208618f,
+ 0.237305f, 0.268799f, 0.302734f, 0.339600f, 0.377930f, 0.418457f, 0.459473f, 0.500000f, 0.540527f, 0.579102f, 0.617188f, 0.652832f,
+ 0.685547f, 0.716309f, 0.745117f, 0.771484f, 0.794922f, 0.815918f, 0.834961f, 0.853027f, 0.868652f, 0.882324f, 0.895996f, 0.907227f,
+ 0.916992f, 0.927246f, 0.972168f, 0.974121f, 0.975098f, 0.973633f, 0.974609f, 0.973633f, 0.000238f, 0.001453f, 0.002047f, 0.002985f,
+ 0.004227f, 0.005272f, 0.006096f, 0.007309f, 0.008957f, 0.010437f, 0.012184f, 0.014214f, 0.015793f, 0.018082f, 0.020538f, 0.023270f,
+ 0.026505f, 0.029648f, 0.033813f, 0.038300f, 0.043457f, 0.049042f, 0.055298f, 0.062744f, 0.070984f, 0.081299f, 0.092590f, 0.105591f,
+ 0.120361f, 0.137695f, 0.156982f, 0.179443f, 0.204346f, 0.232788f, 0.263672f, 0.297363f, 0.334229f, 0.373047f, 0.414307f, 0.455322f,
+ 0.497314f, 0.538086f, 0.578613f, 0.616211f, 0.653320f, 0.686523f, 0.718262f, 0.747559f, 0.773438f, 0.797363f, 0.818848f, 0.838867f,
+ 0.856934f, 0.871582f, 0.885742f, 0.898926f, 0.910645f, 0.920410f, 0.970215f, 0.971680f, 0.972656f, 0.972656f, 0.972168f, 0.972168f,
+ 0.000376f, 0.001075f, 0.002052f, 0.002823f, 0.003603f, 0.004509f, 0.005619f, 0.007008f, 0.008064f, 0.009132f, 0.010849f, 0.012314f,
+ 0.013817f, 0.015945f, 0.018188f, 0.020676f, 0.022995f, 0.026230f, 0.029587f, 0.033234f, 0.037598f, 0.042328f, 0.048004f, 0.054230f,
+ 0.061188f, 0.069824f, 0.079468f, 0.090454f, 0.103271f, 0.117493f, 0.134644f, 0.153931f, 0.175293f, 0.200806f, 0.228149f, 0.259277f,
+ 0.293945f, 0.330566f, 0.370117f, 0.410889f, 0.453369f, 0.495605f, 0.537109f, 0.578125f, 0.616699f, 0.653809f, 0.689453f, 0.721191f,
+ 0.750000f, 0.776855f, 0.800293f, 0.822754f, 0.841309f, 0.859863f, 0.876465f, 0.890137f, 0.902832f, 0.914062f, 0.967773f, 0.970703f,
+ 0.970703f, 0.970703f, 0.970703f, 0.970703f, 0.000237f, 0.000972f, 0.001674f, 0.002413f, 0.003336f, 0.003956f, 0.005093f, 0.006039f,
+ 0.007069f, 0.008202f, 0.009613f, 0.011017f, 0.012520f, 0.014282f, 0.016068f, 0.017853f, 0.020508f, 0.023117f, 0.025986f, 0.029160f,
+ 0.032898f, 0.036865f, 0.041565f, 0.046997f, 0.052887f, 0.060089f, 0.068176f, 0.077515f, 0.088257f, 0.100586f, 0.114929f, 0.131592f,
+ 0.150635f, 0.172241f, 0.196411f, 0.224731f, 0.255859f, 0.290039f, 0.327393f, 0.367188f, 0.409180f, 0.451172f, 0.493896f, 0.536621f,
+ 0.578613f, 0.618164f, 0.655762f, 0.691406f, 0.724121f, 0.753906f, 0.781738f, 0.805176f, 0.827637f, 0.847656f, 0.864746f, 0.880859f,
+ 0.895508f, 0.907715f, 0.965332f, 0.968262f, 0.968750f, 0.969238f, 0.967773f, 0.967773f, 0.000450f, 0.001033f, 0.001554f, 0.002131f,
+ 0.002939f, 0.003662f, 0.004551f, 0.005722f, 0.006405f, 0.007542f, 0.008484f, 0.009750f, 0.011017f, 0.012596f, 0.014046f, 0.015854f,
+ 0.017975f, 0.020264f, 0.022736f, 0.025497f, 0.028671f, 0.031952f, 0.036011f, 0.040741f, 0.045746f, 0.051910f, 0.058868f, 0.066772f,
+ 0.075867f, 0.086304f, 0.098328f, 0.112244f, 0.128784f, 0.147217f, 0.168945f, 0.193848f, 0.221558f, 0.252441f, 0.287109f, 0.324951f,
+ 0.365234f, 0.407715f, 0.450684f, 0.494629f, 0.539062f, 0.580566f, 0.621094f, 0.659668f, 0.695801f, 0.729004f, 0.758789f, 0.786133f,
+ 0.810547f, 0.833008f, 0.852539f, 0.870117f, 0.886719f, 0.900879f, 0.962891f, 0.966309f, 0.966309f, 0.966797f, 0.966797f, 0.966309f,
+ 0.000304f, 0.001050f, 0.001257f, 0.002295f, 0.002689f, 0.003885f, 0.004284f, 0.004726f, 0.005547f, 0.006721f, 0.007595f, 0.008667f,
+ 0.009811f, 0.011330f, 0.012642f, 0.014130f, 0.016098f, 0.017975f, 0.019867f, 0.022247f, 0.024811f, 0.028030f, 0.031403f, 0.035461f,
+ 0.039642f, 0.044800f, 0.050720f, 0.057495f, 0.065002f, 0.073914f, 0.084290f, 0.095947f, 0.109985f, 0.126343f, 0.144409f, 0.166138f,
+ 0.190918f, 0.218750f, 0.250244f, 0.285400f, 0.323730f, 0.364258f, 0.407471f, 0.452148f, 0.496338f, 0.540527f, 0.584473f, 0.625977f,
+ 0.665039f, 0.701172f, 0.735352f, 0.765137f, 0.792480f, 0.817383f, 0.840332f, 0.859863f, 0.876953f, 0.893066f, 0.959961f, 0.963379f,
+ 0.963867f, 0.964355f, 0.963867f, 0.963867f, 0.000228f, 0.000682f, 0.001293f, 0.001717f, 0.002352f, 0.003160f, 0.003626f, 0.004360f,
+ 0.005348f, 0.005871f, 0.006870f, 0.007660f, 0.008957f, 0.010002f, 0.011299f, 0.012375f, 0.014099f, 0.015900f, 0.017670f, 0.019363f,
+ 0.022034f, 0.024216f, 0.027420f, 0.030930f, 0.034454f, 0.038910f, 0.044006f, 0.049530f, 0.055878f, 0.063477f, 0.072083f, 0.082275f,
+ 0.094177f, 0.107666f, 0.123840f, 0.142090f, 0.163452f, 0.188477f, 0.216919f, 0.248047f, 0.283447f, 0.322754f, 0.364990f, 0.408447f,
+ 0.453613f, 0.500000f, 0.544922f, 0.589355f, 0.631348f, 0.671387f, 0.708008f, 0.742188f, 0.773438f, 0.800781f, 0.824219f, 0.846680f,
+ 0.866699f, 0.884277f, 0.958008f, 0.960938f, 0.961426f, 0.962402f, 0.961914f, 0.960938f, 0.000239f, 0.000731f, 0.001204f, 0.001637f,
+ 0.002144f, 0.002913f, 0.003521f, 0.003828f, 0.004517f, 0.005291f, 0.006203f, 0.006954f, 0.007740f, 0.008911f, 0.010239f, 0.011017f,
+ 0.012413f, 0.013863f, 0.015396f, 0.017181f, 0.019196f, 0.021439f, 0.024078f, 0.026993f, 0.030182f, 0.033752f, 0.038055f, 0.042664f,
+ 0.048004f, 0.054657f, 0.061920f, 0.070312f, 0.080688f, 0.092041f, 0.105774f, 0.121094f, 0.140015f, 0.161255f, 0.186523f, 0.214966f,
+ 0.246948f, 0.283203f, 0.322998f, 0.365967f, 0.410400f, 0.457275f, 0.503906f, 0.550781f, 0.596191f, 0.638672f, 0.678711f, 0.716797f,
+ 0.750488f, 0.781738f, 0.809082f, 0.833496f, 0.855469f, 0.874512f, 0.954590f, 0.958008f, 0.958984f, 0.958984f, 0.958984f, 0.958984f,
+ 0.000226f, 0.000663f, 0.001073f, 0.001420f, 0.002163f, 0.002567f, 0.003052f, 0.003433f, 0.004181f, 0.004734f, 0.005516f, 0.006424f,
+ 0.007050f, 0.008003f, 0.008659f, 0.009827f, 0.011086f, 0.012398f, 0.013649f, 0.015266f, 0.016891f, 0.018921f, 0.021118f, 0.023560f,
+ 0.026505f, 0.029556f, 0.032715f, 0.036865f, 0.041077f, 0.046570f, 0.053314f, 0.060150f, 0.068787f, 0.078552f, 0.090027f, 0.103638f,
+ 0.119690f, 0.138184f, 0.159546f, 0.184692f, 0.213745f, 0.245972f, 0.283203f, 0.324219f, 0.367920f, 0.414062f, 0.461914f, 0.509766f,
+ 0.557129f, 0.604492f, 0.647461f, 0.688965f, 0.727051f, 0.761230f, 0.791504f, 0.819824f, 0.844238f, 0.865234f, 0.951660f, 0.955566f,
+ 0.955566f, 0.956055f, 0.955078f, 0.956543f, 0.000156f, 0.000587f, 0.001056f, 0.001499f, 0.001647f, 0.002380f, 0.002594f, 0.003469f,
+ 0.003777f, 0.004112f, 0.004925f, 0.005699f, 0.006180f, 0.007019f, 0.007957f, 0.008942f, 0.009560f, 0.010727f, 0.011963f, 0.013123f,
+ 0.014885f, 0.016556f, 0.018494f, 0.020355f, 0.022766f, 0.025330f, 0.028320f, 0.031830f, 0.035736f, 0.040161f, 0.045532f, 0.052032f,
+ 0.059113f, 0.066833f, 0.076782f, 0.088501f, 0.101868f, 0.117310f, 0.136108f, 0.157959f, 0.183105f, 0.212769f, 0.247070f, 0.284424f,
+ 0.326660f, 0.371338f, 0.419189f, 0.468994f, 0.518066f, 0.567383f, 0.613770f, 0.658691f, 0.700684f, 0.738770f, 0.771973f, 0.803223f,
+ 0.829590f, 0.854492f, 0.947266f, 0.952637f, 0.952637f, 0.952637f, 0.953125f, 0.952637f, 0.000155f, 0.000358f, 0.000859f, 0.001402f,
+ 0.001830f, 0.002092f, 0.002499f, 0.002672f, 0.003410f, 0.003763f, 0.004375f, 0.005077f, 0.005535f, 0.006554f, 0.007004f, 0.007874f,
+ 0.008537f, 0.009529f, 0.010742f, 0.011749f, 0.013016f, 0.014427f, 0.015945f, 0.017929f, 0.019775f, 0.022018f, 0.024460f, 0.027618f,
+ 0.030640f, 0.034668f, 0.039154f, 0.044250f, 0.050293f, 0.057068f, 0.065491f, 0.074951f, 0.086487f, 0.099670f, 0.115906f, 0.134277f,
+ 0.156860f, 0.182495f, 0.213135f, 0.248047f, 0.286621f, 0.329834f, 0.376709f, 0.426025f, 0.476562f, 0.527832f, 0.577637f, 0.626465f,
+ 0.671387f, 0.713379f, 0.752441f, 0.784668f, 0.815430f, 0.841797f, 0.944336f, 0.948242f, 0.949219f, 0.949219f, 0.949219f, 0.949707f,
+ 0.000233f, 0.000639f, 0.000930f, 0.001277f, 0.001579f, 0.001916f, 0.002041f, 0.002625f, 0.003035f, 0.003571f, 0.004124f, 0.004375f,
+ 0.004978f, 0.005379f, 0.006348f, 0.006886f, 0.007526f, 0.008430f, 0.009216f, 0.010262f, 0.011436f, 0.012779f, 0.014160f, 0.015549f,
+ 0.017120f, 0.019089f, 0.021164f, 0.023621f, 0.026352f, 0.029724f, 0.033447f, 0.037842f, 0.042603f, 0.048737f, 0.055573f, 0.063721f,
+ 0.073364f, 0.084778f, 0.098206f, 0.114197f, 0.133423f, 0.155762f, 0.182739f, 0.213623f, 0.249512f, 0.289795f, 0.335205f, 0.383789f,
+ 0.434814f, 0.487305f, 0.540039f, 0.591797f, 0.640137f, 0.686035f, 0.727539f, 0.765137f, 0.800293f, 0.830078f, 0.940430f, 0.944336f,
+ 0.945312f, 0.946289f, 0.945801f, 0.945312f, 0.000217f, 0.000519f, 0.000848f, 0.001180f, 0.001366f, 0.001589f, 0.001986f, 0.002354f,
+ 0.002987f, 0.003170f, 0.003576f, 0.003901f, 0.004440f, 0.004738f, 0.005543f, 0.006058f, 0.006508f, 0.007511f, 0.008163f, 0.009132f,
+ 0.010078f, 0.011246f, 0.012390f, 0.013412f, 0.014938f, 0.016632f, 0.018433f, 0.020676f, 0.022995f, 0.025726f, 0.028702f, 0.032227f,
+ 0.036377f, 0.041992f, 0.047394f, 0.053986f, 0.062195f, 0.071716f, 0.082825f, 0.096802f, 0.112732f, 0.132202f, 0.155273f, 0.182861f,
+ 0.215210f, 0.252441f, 0.294678f, 0.341553f, 0.392090f, 0.445557f, 0.499512f, 0.553711f, 0.606445f, 0.656250f, 0.703125f, 0.745605f,
+ 0.782715f, 0.816895f, 0.935547f, 0.939941f, 0.941406f, 0.941406f, 0.941406f, 0.940918f, 0.000242f, 0.000678f, 0.000781f, 0.000928f,
+ 0.001200f, 0.001592f, 0.001694f, 0.002096f, 0.002703f, 0.002903f, 0.003170f, 0.003531f, 0.003918f, 0.004433f, 0.004955f, 0.005390f,
+ 0.005939f, 0.006454f, 0.007298f, 0.007782f, 0.008759f, 0.009567f, 0.010559f, 0.011650f, 0.013046f, 0.014420f, 0.015793f, 0.017715f,
+ 0.019699f, 0.021774f, 0.024460f, 0.027481f, 0.031082f, 0.035065f, 0.039917f, 0.045715f, 0.052246f, 0.060486f, 0.070129f, 0.081482f,
+ 0.095093f, 0.111755f, 0.131714f, 0.155273f, 0.183838f, 0.217285f, 0.256348f, 0.300781f, 0.350342f, 0.403076f, 0.458252f, 0.514160f,
+ 0.570312f, 0.624512f, 0.675781f, 0.722168f, 0.763672f, 0.800293f, 0.930664f, 0.935547f, 0.937500f, 0.937012f, 0.937500f, 0.937012f,
+ 0.000239f, 0.000297f, 0.000667f, 0.000785f, 0.001044f, 0.001269f, 0.001569f, 0.001950f, 0.002224f, 0.002419f, 0.002810f, 0.003063f,
+ 0.003626f, 0.003895f, 0.004261f, 0.004749f, 0.005066f, 0.005726f, 0.006260f, 0.007019f, 0.007771f, 0.008369f, 0.008919f, 0.009941f,
+ 0.011101f, 0.012375f, 0.013519f, 0.015190f, 0.016891f, 0.018631f, 0.021011f, 0.023590f, 0.026581f, 0.029892f, 0.033875f, 0.038757f,
+ 0.044281f, 0.051147f, 0.058746f, 0.068481f, 0.079834f, 0.094116f, 0.110779f, 0.131348f, 0.155884f, 0.185669f, 0.220825f, 0.261963f,
+ 0.308594f, 0.360352f, 0.416260f, 0.473877f, 0.532715f, 0.589844f, 0.645508f, 0.696289f, 0.743652f, 0.784668f, 0.925781f, 0.930664f,
+ 0.932129f, 0.932129f, 0.932129f, 0.932129f, 0.000226f, 0.000351f, 0.000434f, 0.000624f, 0.000887f, 0.001040f, 0.001246f, 0.001665f,
+ 0.001856f, 0.002384f, 0.002420f, 0.002842f, 0.002874f, 0.003471f, 0.003735f, 0.004078f, 0.004639f, 0.004910f, 0.005531f, 0.006065f,
+ 0.006664f, 0.007370f, 0.007690f, 0.008690f, 0.009544f, 0.010536f, 0.011795f, 0.012833f, 0.014183f, 0.015900f, 0.017899f, 0.019684f,
+ 0.022430f, 0.025253f, 0.028412f, 0.032410f, 0.037201f, 0.042633f, 0.049316f, 0.057159f, 0.066772f, 0.078186f, 0.092590f, 0.110107f,
+ 0.131348f, 0.156982f, 0.188232f, 0.225342f, 0.269043f, 0.318604f, 0.373535f, 0.431641f, 0.492188f, 0.554199f, 0.613281f, 0.668945f,
+ 0.720703f, 0.766602f, 0.919922f, 0.925781f, 0.926758f, 0.926758f, 0.927246f, 0.926758f, 0.000000f, 0.000340f, 0.000458f, 0.000715f,
+ 0.000823f, 0.000895f, 0.001165f, 0.001518f, 0.001636f, 0.001876f, 0.002190f, 0.002472f, 0.002640f, 0.002964f, 0.003340f, 0.003527f,
+ 0.004005f, 0.004227f, 0.004803f, 0.005260f, 0.005878f, 0.006042f, 0.006805f, 0.007500f, 0.008469f, 0.009132f, 0.009949f, 0.011009f,
+ 0.012077f, 0.013687f, 0.014938f, 0.016785f, 0.018997f, 0.021194f, 0.023895f, 0.027283f, 0.030945f, 0.035583f, 0.040955f, 0.047760f,
+ 0.055573f, 0.065247f, 0.077209f, 0.091736f, 0.109619f, 0.131470f, 0.159058f, 0.192017f, 0.231812f, 0.278076f, 0.331543f, 0.389404f,
+ 0.450928f, 0.513672f, 0.577637f, 0.638672f, 0.695801f, 0.746582f, 0.914062f, 0.919922f, 0.920898f, 0.921387f, 0.921387f, 0.921387f,
+ 0.000146f, 0.000319f, 0.000443f, 0.000458f, 0.000704f, 0.000894f, 0.001199f, 0.001324f, 0.001549f, 0.001592f, 0.002081f, 0.002092f,
+ 0.002237f, 0.002604f, 0.002815f, 0.003159f, 0.003510f, 0.003937f, 0.004147f, 0.004425f, 0.004814f, 0.005318f, 0.005878f, 0.006413f,
+ 0.006924f, 0.007782f, 0.008408f, 0.009239f, 0.010414f, 0.011505f, 0.012642f, 0.014015f, 0.015884f, 0.017563f, 0.019852f, 0.022598f,
+ 0.025650f, 0.029663f, 0.033875f, 0.039307f, 0.045898f, 0.053955f, 0.063782f, 0.075928f, 0.090820f, 0.109497f, 0.132690f, 0.161621f,
+ 0.196777f, 0.239624f, 0.290039f, 0.346436f, 0.408203f, 0.473633f, 0.540527f, 0.605957f, 0.667969f, 0.725586f, 0.907715f, 0.914062f,
+ 0.914062f, 0.915039f, 0.915039f, 0.915039f, 0.000121f, 0.000251f, 0.000506f, 0.000532f, 0.000665f, 0.000830f, 0.001190f, 0.001164f,
+ 0.001290f, 0.001413f, 0.001755f, 0.001900f, 0.002157f, 0.002319f, 0.002422f, 0.002853f, 0.003042f, 0.003254f, 0.003529f, 0.003725f,
+ 0.004288f, 0.004585f, 0.005043f, 0.005539f, 0.005970f, 0.006386f, 0.007126f, 0.007812f, 0.008652f, 0.009598f, 0.010651f, 0.011803f,
+ 0.013130f, 0.014702f, 0.016510f, 0.018814f, 0.021011f, 0.024368f, 0.028122f, 0.032379f, 0.037506f, 0.044128f, 0.052277f, 0.062042f,
+ 0.075073f, 0.090088f, 0.110107f, 0.134766f, 0.165405f, 0.203613f, 0.249268f, 0.303955f, 0.365234f, 0.431396f, 0.501465f, 0.571777f,
+ 0.638672f, 0.702148f, 0.900879f, 0.906738f, 0.907227f, 0.908203f, 0.907227f, 0.908203f, 0.000241f, 0.000122f, 0.000417f, 0.000505f,
+ 0.000741f, 0.000782f, 0.000916f, 0.001145f, 0.001189f, 0.001289f, 0.001331f, 0.001565f, 0.001779f, 0.002020f, 0.002171f, 0.002228f,
+ 0.002623f, 0.002752f, 0.002949f, 0.003157f, 0.003515f, 0.003847f, 0.004082f, 0.004429f, 0.004990f, 0.005405f, 0.006008f, 0.006603f,
+ 0.007103f, 0.007889f, 0.008789f, 0.009766f, 0.010605f, 0.012177f, 0.013672f, 0.015305f, 0.017487f, 0.019913f, 0.022781f, 0.026245f,
+ 0.030670f, 0.035980f, 0.042389f, 0.050812f, 0.060883f, 0.073792f, 0.090088f, 0.111145f, 0.138062f, 0.171143f, 0.212524f, 0.262695f,
+ 0.322266f, 0.388184f, 0.460205f, 0.533203f, 0.606445f, 0.676758f, 0.893066f, 0.898926f, 0.899414f, 0.899414f, 0.900879f, 0.900391f,
+ 0.000000f, 0.000114f, 0.000227f, 0.000407f, 0.000532f, 0.000732f, 0.000714f, 0.000922f, 0.000993f, 0.001072f, 0.001190f, 0.001412f,
+ 0.001569f, 0.001726f, 0.001959f, 0.002071f, 0.002159f, 0.002350f, 0.002565f, 0.002729f, 0.003090f, 0.003248f, 0.003702f, 0.003761f,
+ 0.004192f, 0.004585f, 0.004925f, 0.005272f, 0.005966f, 0.006405f, 0.007275f, 0.007965f, 0.008850f, 0.009872f, 0.011017f, 0.012383f,
+ 0.014275f, 0.015900f, 0.018463f, 0.021194f, 0.024673f, 0.028870f, 0.034271f, 0.040955f, 0.048981f, 0.059723f, 0.073059f, 0.090149f,
+ 0.112549f, 0.141357f, 0.178467f, 0.223755f, 0.280029f, 0.345215f, 0.417969f, 0.494385f, 0.572266f, 0.648438f, 0.884277f, 0.890137f,
+ 0.891602f, 0.891602f, 0.893066f, 0.892090f, 0.000000f, 0.000219f, 0.000211f, 0.000333f, 0.000559f, 0.000609f, 0.000788f, 0.000805f,
+ 0.000869f, 0.000903f, 0.001101f, 0.001166f, 0.001302f, 0.001399f, 0.001456f, 0.001668f, 0.001853f, 0.001999f, 0.002102f, 0.002256f,
+ 0.002447f, 0.002728f, 0.002943f, 0.003178f, 0.003515f, 0.003836f, 0.004074f, 0.004475f, 0.004745f, 0.005325f, 0.005970f, 0.006569f,
+ 0.007248f, 0.008102f, 0.008888f, 0.010132f, 0.011169f, 0.012947f, 0.014763f, 0.016891f, 0.019760f, 0.023087f, 0.027176f, 0.032562f,
+ 0.038940f, 0.047516f, 0.058167f, 0.072754f, 0.090698f, 0.114929f, 0.146851f, 0.187744f, 0.239258f, 0.301514f, 0.373291f, 0.452637f,
+ 0.535645f, 0.617676f, 0.874512f, 0.880859f, 0.882324f, 0.883301f, 0.883301f, 0.882324f, 0.000204f, 0.000207f, 0.000204f, 0.000322f,
+ 0.000435f, 0.000480f, 0.000556f, 0.000615f, 0.000747f, 0.000782f, 0.000844f, 0.001006f, 0.001159f, 0.001191f, 0.001231f, 0.001450f,
+ 0.001585f, 0.001633f, 0.001790f, 0.001919f, 0.002117f, 0.002298f, 0.002432f, 0.002651f, 0.002939f, 0.003172f, 0.003399f, 0.003614f,
+ 0.003944f, 0.004421f, 0.004704f, 0.005203f, 0.005886f, 0.006454f, 0.007160f, 0.008049f, 0.009041f, 0.010201f, 0.011627f, 0.013237f,
+ 0.015404f, 0.018097f, 0.021469f, 0.025284f, 0.030884f, 0.036987f, 0.045990f, 0.056915f, 0.072083f, 0.092163f, 0.119141f, 0.154419f,
+ 0.200928f, 0.259277f, 0.328857f, 0.409424f, 0.495605f, 0.584473f, 0.864258f, 0.871094f, 0.872070f, 0.873047f, 0.872559f, 0.873047f,
+ 0.000000f, 0.000044f, 0.000176f, 0.000290f, 0.000410f, 0.000390f, 0.000513f, 0.000546f, 0.000647f, 0.000680f, 0.000827f, 0.000858f,
+ 0.000958f, 0.001131f, 0.001102f, 0.001223f, 0.001367f, 0.001401f, 0.001525f, 0.001610f, 0.001826f, 0.001821f, 0.002039f, 0.002253f,
+ 0.002459f, 0.002617f, 0.002708f, 0.003036f, 0.003279f, 0.003431f, 0.003805f, 0.004219f, 0.004471f, 0.004929f, 0.005569f, 0.006310f,
+ 0.007107f, 0.007988f, 0.009003f, 0.010384f, 0.011856f, 0.014015f, 0.016418f, 0.019669f, 0.023666f, 0.028809f, 0.035583f, 0.044159f,
+ 0.056458f, 0.072571f, 0.094604f, 0.124329f, 0.164917f, 0.218018f, 0.284912f, 0.364746f, 0.454102f, 0.549316f, 0.853027f, 0.859863f,
+ 0.861328f, 0.861816f, 0.861816f, 0.861816f, 0.000000f, 0.000069f, 0.000120f, 0.000345f, 0.000371f, 0.000398f, 0.000452f, 0.000396f,
+ 0.000498f, 0.000530f, 0.000596f, 0.000648f, 0.000781f, 0.000921f, 0.000995f, 0.001007f, 0.001101f, 0.001146f, 0.001282f, 0.001278f,
+ 0.001471f, 0.001554f, 0.001710f, 0.001811f, 0.001995f, 0.001986f, 0.002314f, 0.002399f, 0.002499f, 0.002903f, 0.002975f, 0.003305f,
+ 0.003605f, 0.004086f, 0.004425f, 0.005081f, 0.005402f, 0.006035f, 0.006889f, 0.007755f, 0.009041f, 0.010422f, 0.012672f, 0.014885f,
+ 0.017746f, 0.021530f, 0.026733f, 0.033691f, 0.043060f, 0.055847f, 0.073181f, 0.097473f, 0.132324f, 0.179077f, 0.241821f, 0.320068f,
+ 0.410400f, 0.510742f, 0.839844f, 0.847656f, 0.849121f, 0.849609f, 0.849121f, 0.849609f, 0.000000f, 0.000000f, 0.000121f, 0.000243f,
+ 0.000321f, 0.000354f, 0.000341f, 0.000431f, 0.000423f, 0.000444f, 0.000473f, 0.000508f, 0.000595f, 0.000706f, 0.000737f, 0.000861f,
+ 0.000869f, 0.000926f, 0.001055f, 0.001104f, 0.001199f, 0.001306f, 0.001360f, 0.001433f, 0.001530f, 0.001555f, 0.001673f, 0.001942f,
+ 0.002138f, 0.002247f, 0.002562f, 0.002609f, 0.002911f, 0.003204f, 0.003466f, 0.003757f, 0.004192f, 0.004845f, 0.005482f, 0.006008f,
+ 0.006874f, 0.007904f, 0.009171f, 0.011124f, 0.013260f, 0.015839f, 0.019821f, 0.024872f, 0.031982f, 0.041534f, 0.055054f, 0.075012f,
+ 0.103516f, 0.143677f, 0.199951f, 0.273438f, 0.364502f, 0.469482f, 0.825684f, 0.834473f, 0.834961f, 0.835938f, 0.835938f, 0.835938f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000199f, 0.000272f, 0.000265f, 0.000363f, 0.000379f, 0.000388f, 0.000489f, 0.000500f,
+ 0.000488f, 0.000569f, 0.000604f, 0.000700f, 0.000683f, 0.000720f, 0.000784f, 0.000844f, 0.001009f, 0.001047f, 0.001108f, 0.001258f,
+ 0.001276f, 0.001388f, 0.001410f, 0.001565f, 0.001592f, 0.001814f, 0.001800f, 0.002167f, 0.002192f, 0.002556f, 0.002665f, 0.002905f,
+ 0.003195f, 0.003574f, 0.004028f, 0.004513f, 0.005127f, 0.005859f, 0.006847f, 0.008018f, 0.009491f, 0.011452f, 0.014099f, 0.017792f,
+ 0.022995f, 0.030258f, 0.040588f, 0.055878f, 0.078308f, 0.111450f, 0.160278f, 0.229248f, 0.318359f, 0.425781f, 0.810547f, 0.818359f,
+ 0.820312f, 0.821777f, 0.821777f, 0.820801f, 0.000000f, 0.000121f, 0.000120f, 0.000172f, 0.000195f, 0.000171f, 0.000208f, 0.000272f,
+ 0.000316f, 0.000333f, 0.000348f, 0.000355f, 0.000412f, 0.000410f, 0.000515f, 0.000485f, 0.000545f, 0.000656f, 0.000777f, 0.000659f,
+ 0.000705f, 0.000762f, 0.000874f, 0.000927f, 0.000959f, 0.000978f, 0.001045f, 0.001228f, 0.001294f, 0.001398f, 0.001443f, 0.001637f,
+ 0.001752f, 0.001925f, 0.002005f, 0.002230f, 0.002407f, 0.002670f, 0.002895f, 0.003267f, 0.003933f, 0.004280f, 0.005051f, 0.005772f,
+ 0.006718f, 0.008141f, 0.010117f, 0.012383f, 0.015930f, 0.020920f, 0.028671f, 0.039673f, 0.056702f, 0.083313f, 0.124695f, 0.185791f,
+ 0.270996f, 0.379639f, 0.793457f, 0.801270f, 0.803711f, 0.803711f, 0.804688f, 0.804688f, 0.000000f, 0.000121f, 0.000119f, 0.000144f,
+ 0.000149f, 0.000166f, 0.000173f, 0.000167f, 0.000214f, 0.000245f, 0.000334f, 0.000287f, 0.000303f, 0.000391f, 0.000401f, 0.000440f,
+ 0.000469f, 0.000493f, 0.000534f, 0.000513f, 0.000690f, 0.000682f, 0.000645f, 0.000712f, 0.000715f, 0.000747f, 0.000842f, 0.000849f,
+ 0.000967f, 0.000995f, 0.001178f, 0.001167f, 0.001273f, 0.001395f, 0.001586f, 0.001748f, 0.001796f, 0.001986f, 0.002132f, 0.002476f,
+ 0.002893f, 0.003294f, 0.003653f, 0.004086f, 0.004890f, 0.005821f, 0.006927f, 0.008553f, 0.010857f, 0.014137f, 0.019211f, 0.027084f,
+ 0.039642f, 0.059448f, 0.092468f, 0.144775f, 0.224487f, 0.332764f, 0.775391f, 0.784668f, 0.786133f, 0.786133f, 0.787109f, 0.786621f,
+ 0.000000f, 0.000000f, 0.000118f, 0.000116f, 0.000115f, 0.000113f, 0.000140f, 0.000140f, 0.000149f, 0.000220f, 0.000171f, 0.000255f,
+ 0.000274f, 0.000292f, 0.000318f, 0.000295f, 0.000346f, 0.000352f, 0.000380f, 0.000406f, 0.000401f, 0.000533f, 0.000490f, 0.000551f,
+ 0.000558f, 0.000648f, 0.000628f, 0.000723f, 0.000788f, 0.000749f, 0.000836f, 0.000941f, 0.000997f, 0.001065f, 0.001112f, 0.001207f,
+ 0.001328f, 0.001535f, 0.001621f, 0.001840f, 0.002022f, 0.002163f, 0.002522f, 0.002825f, 0.003391f, 0.003830f, 0.004616f, 0.005665f,
+ 0.007172f, 0.009247f, 0.012482f, 0.017532f, 0.025970f, 0.040161f, 0.064941f, 0.107422f, 0.178833f, 0.283447f, 0.754883f, 0.764648f,
+ 0.766113f, 0.767090f, 0.767578f, 0.767090f, 0.000000f, 0.000119f, 0.000116f, 0.000114f, 0.000112f, 0.000110f, 0.000109f, 0.000117f,
+ 0.000114f, 0.000117f, 0.000125f, 0.000193f, 0.000141f, 0.000196f, 0.000221f, 0.000235f, 0.000259f, 0.000278f, 0.000308f, 0.000316f,
+ 0.000323f, 0.000315f, 0.000329f, 0.000351f, 0.000388f, 0.000422f, 0.000465f, 0.000512f, 0.000571f, 0.000568f, 0.000588f, 0.000633f,
+ 0.000747f, 0.000751f, 0.000829f, 0.000958f, 0.000914f, 0.001104f, 0.001145f, 0.001255f, 0.001337f, 0.001499f, 0.001701f, 0.001966f,
+ 0.002275f, 0.002609f, 0.003119f, 0.003773f, 0.004658f, 0.005920f, 0.007935f, 0.010948f, 0.015900f, 0.025284f, 0.042511f, 0.075012f,
+ 0.135010f, 0.234619f, 0.733398f, 0.743164f, 0.744629f, 0.745117f, 0.745605f, 0.745605f, 0.000000f, 0.000116f, 0.000113f, 0.000111f,
+ 0.000108f, 0.000106f, 0.000104f, 0.000103f, 0.000098f, 0.000092f, 0.000099f, 0.000085f, 0.000098f, 0.000105f, 0.000163f, 0.000162f,
+ 0.000128f, 0.000193f, 0.000203f, 0.000214f, 0.000284f, 0.000239f, 0.000303f, 0.000268f, 0.000327f, 0.000326f, 0.000329f, 0.000330f,
+ 0.000407f, 0.000486f, 0.000406f, 0.000454f, 0.000465f, 0.000495f, 0.000535f, 0.000592f, 0.000648f, 0.000727f, 0.000753f, 0.000807f,
+ 0.000956f, 0.000992f, 0.001108f, 0.001294f, 0.001418f, 0.001703f, 0.001978f, 0.002390f, 0.002930f, 0.003643f, 0.004753f, 0.006519f,
+ 0.009499f, 0.014824f, 0.025497f, 0.048065f, 0.095154f, 0.185425f, 0.709961f, 0.719727f, 0.721191f, 0.721191f, 0.721680f, 0.721680f,
+ 0.000000f, 0.000113f, 0.000107f, 0.000106f, 0.000102f, 0.000100f, 0.000097f, 0.000096f, 0.000095f, 0.000092f, 0.000087f, 0.000083f,
+ 0.000078f, 0.000098f, 0.000077f, 0.000091f, 0.000114f, 0.000128f, 0.000114f, 0.000147f, 0.000154f, 0.000162f, 0.000186f, 0.000174f,
+ 0.000220f, 0.000233f, 0.000235f, 0.000245f, 0.000250f, 0.000253f, 0.000321f, 0.000296f, 0.000311f, 0.000354f, 0.000417f, 0.000419f,
+ 0.000438f, 0.000443f, 0.000495f, 0.000513f, 0.000585f, 0.000634f, 0.000705f, 0.000778f, 0.000912f, 0.001002f, 0.001163f, 0.001379f,
+ 0.001745f, 0.002092f, 0.002697f, 0.003721f, 0.005230f, 0.008194f, 0.013870f, 0.027359f, 0.061066f, 0.138062f, 0.685547f, 0.694336f,
+ 0.696777f, 0.696289f, 0.697754f, 0.697754f, 0.000000f, 0.000106f, 0.000102f, 0.000097f, 0.000093f, 0.000091f, 0.000089f, 0.000087f,
+ 0.000085f, 0.000084f, 0.000082f, 0.000080f, 0.000076f, 0.000072f, 0.000069f, 0.000074f, 0.000076f, 0.000059f, 0.000075f, 0.000062f,
+ 0.000085f, 0.000091f, 0.000103f, 0.000111f, 0.000121f, 0.000135f, 0.000128f, 0.000159f, 0.000171f, 0.000160f, 0.000178f, 0.000193f,
+ 0.000196f, 0.000202f, 0.000220f, 0.000230f, 0.000273f, 0.000289f, 0.000312f, 0.000330f, 0.000335f, 0.000397f, 0.000408f, 0.000463f,
+ 0.000517f, 0.000577f, 0.000691f, 0.000771f, 0.000919f, 0.001150f, 0.001436f, 0.001955f, 0.002737f, 0.004185f, 0.007103f, 0.013863f,
+ 0.033661f, 0.093628f, 0.657227f, 0.667480f, 0.668945f, 0.669434f, 0.670898f, 0.669922f, 0.000108f, 0.000093f, 0.000087f, 0.000082f,
+ 0.000079f, 0.000078f, 0.000075f, 0.000073f, 0.000071f, 0.000070f, 0.000069f, 0.000069f, 0.000067f, 0.000066f, 0.000064f, 0.000061f,
+ 0.000059f, 0.000056f, 0.000053f, 0.000051f, 0.000053f, 0.000049f, 0.000044f, 0.000047f, 0.000055f, 0.000058f, 0.000071f, 0.000077f,
+ 0.000093f, 0.000094f, 0.000103f, 0.000102f, 0.000110f, 0.000126f, 0.000130f, 0.000138f, 0.000143f, 0.000166f, 0.000166f, 0.000178f,
+ 0.000194f, 0.000217f, 0.000228f, 0.000231f, 0.000265f, 0.000330f, 0.000341f, 0.000411f, 0.000459f, 0.000549f, 0.000705f, 0.000867f,
+ 0.001228f, 0.001863f, 0.003143f, 0.006283f, 0.015594f, 0.054993f, 0.628418f, 0.638184f, 0.640137f, 0.640137f, 0.641602f, 0.641602f,
+ 0.000071f, 0.000058f, 0.000059f, 0.000058f, 0.000054f, 0.000054f, 0.000051f, 0.000053f, 0.000051f, 0.000052f, 0.000050f, 0.000050f,
+ 0.000051f, 0.000050f, 0.000049f, 0.000049f, 0.000049f, 0.000049f, 0.000047f, 0.000045f, 0.000043f, 0.000041f, 0.000039f, 0.000038f,
+ 0.000036f, 0.000034f, 0.000035f, 0.000037f, 0.000033f, 0.000034f, 0.000038f, 0.000047f, 0.000054f, 0.000061f, 0.000064f, 0.000068f,
+ 0.000069f, 0.000076f, 0.000083f, 0.000092f, 0.000098f, 0.000103f, 0.000112f, 0.000129f, 0.000113f, 0.000139f, 0.000152f, 0.000185f,
+ 0.000204f, 0.000238f, 0.000282f, 0.000365f, 0.000503f, 0.000685f, 0.001178f, 0.002274f, 0.006100f, 0.025162f, 0.597656f, 0.607910f,
+ 0.610840f, 0.611816f, 0.610352f, 0.611328f, 0.000000f, 0.000000f, 0.000004f, 0.000012f, 0.000014f, 0.000020f, 0.000022f, 0.000023f,
+ 0.000024f, 0.000022f, 0.000025f, 0.000027f, 0.000027f, 0.000026f, 0.000028f, 0.000029f, 0.000029f, 0.000029f, 0.000030f, 0.000030f,
+ 0.000030f, 0.000030f, 0.000030f, 0.000030f, 0.000029f, 0.000028f, 0.000027f, 0.000026f, 0.000024f, 0.000023f, 0.000022f, 0.000021f,
+ 0.000020f, 0.000019f, 0.000018f, 0.000019f, 0.000023f, 0.000024f, 0.000027f, 0.000032f, 0.000038f, 0.000040f, 0.000041f, 0.000045f,
+ 0.000054f, 0.000052f, 0.000055f, 0.000060f, 0.000068f, 0.000089f, 0.000089f, 0.000115f, 0.000146f, 0.000198f, 0.000318f, 0.000586f,
+ 0.001614f, 0.008278f, 0.565918f, 0.576660f, 0.578125f, 0.579102f, 0.579590f, 0.580078f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f,
+ 0.000003f, 0.000003f, 0.000005f, 0.000005f, 0.000006f, 0.000007f, 0.000009f, 0.000009f, 0.000010f, 0.000011f, 0.000012f, 0.000012f,
+ 0.000013f, 0.000014f, 0.000014f, 0.000015f, 0.000014f, 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f,
+ 0.000009f, 0.000009f, 0.000008f, 0.000010f, 0.000013f, 0.000013f, 0.000013f, 0.000017f, 0.000017f, 0.000022f, 0.000021f, 0.000023f,
+ 0.000031f, 0.000032f, 0.000049f, 0.000079f, 0.000204f, 0.001328f, 0.533203f, 0.543945f, 0.545410f, 0.546387f, 0.546875f, 0.546875f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000003f,
+ 0.000003f, 0.000003f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000016f, 0.499756f, 0.510254f,
+ 0.513184f, 0.513672f, 0.514160f, 0.514160f,
+ },
+ {
+ 0.076172f, 0.209839f, 0.320312f, 0.408691f, 0.481689f, 0.541016f, 0.591309f, 0.633789f, 0.668945f, 0.699707f, 0.727051f, 0.749512f,
+ 0.770020f, 0.788086f, 0.803711f, 0.817871f, 0.832520f, 0.843750f, 0.854492f, 0.864258f, 0.873535f, 0.881836f, 0.889160f, 0.895996f,
+ 0.903320f, 0.909180f, 0.914551f, 0.920410f, 0.925781f, 0.929199f, 0.933594f, 0.938965f, 0.942383f, 0.946289f, 0.949219f, 0.953125f,
+ 0.955566f, 0.959473f, 0.961914f, 0.964355f, 0.967285f, 0.970215f, 0.971680f, 0.974609f, 0.976562f, 0.978516f, 0.980469f, 0.982422f,
+ 0.984375f, 0.986328f, 0.987793f, 0.989746f, 0.990723f, 0.992676f, 0.993652f, 0.995117f, 0.996582f, 0.998047f, 0.999023f, 0.997559f,
+ 0.996582f, 0.995605f, 0.994629f, 0.993652f, 0.043396f, 0.133301f, 0.221313f, 0.303223f, 0.377441f, 0.442871f, 0.500000f, 0.550781f,
+ 0.595215f, 0.632812f, 0.666992f, 0.696777f, 0.723145f, 0.745605f, 0.765137f, 0.783691f, 0.799805f, 0.815430f, 0.828613f, 0.839844f,
+ 0.851562f, 0.861328f, 0.871582f, 0.879395f, 0.887207f, 0.894531f, 0.901855f, 0.907227f, 0.914062f, 0.919434f, 0.924316f, 0.928711f,
+ 0.933594f, 0.937988f, 0.942383f, 0.945801f, 0.949219f, 0.953125f, 0.956055f, 0.959473f, 0.962402f, 0.964355f, 0.967773f, 0.970215f,
+ 0.972656f, 0.975098f, 0.977051f, 0.979492f, 0.980957f, 0.983398f, 0.985352f, 0.986816f, 0.988281f, 0.990234f, 0.991699f, 0.993652f,
+ 0.995117f, 0.996094f, 0.998047f, 0.997070f, 0.996094f, 0.995117f, 0.994141f, 0.993164f, 0.027832f, 0.088440f, 0.153198f, 0.221313f,
+ 0.288086f, 0.352051f, 0.411621f, 0.466797f, 0.515625f, 0.561523f, 0.601074f, 0.637207f, 0.667969f, 0.695312f, 0.721680f, 0.743652f,
+ 0.763184f, 0.781738f, 0.797852f, 0.812500f, 0.826172f, 0.838867f, 0.850098f, 0.859863f, 0.869141f, 0.877930f, 0.886230f, 0.893555f,
+ 0.900879f, 0.907227f, 0.912598f, 0.918457f, 0.922852f, 0.928711f, 0.934082f, 0.938477f, 0.942383f, 0.946289f, 0.950195f, 0.953125f,
+ 0.956543f, 0.959961f, 0.962402f, 0.965820f, 0.968262f, 0.970703f, 0.973145f, 0.975586f, 0.978027f, 0.979980f, 0.982422f, 0.984375f,
+ 0.985840f, 0.987793f, 0.989746f, 0.991211f, 0.993164f, 0.994141f, 0.997559f, 0.996582f, 0.995605f, 0.994629f, 0.993652f, 0.993164f,
+ 0.018921f, 0.061493f, 0.109497f, 0.161987f, 0.217041f, 0.273438f, 0.330811f, 0.384521f, 0.437500f, 0.486084f, 0.530273f, 0.570312f,
+ 0.607910f, 0.640137f, 0.670410f, 0.697266f, 0.722656f, 0.743652f, 0.763672f, 0.781250f, 0.797363f, 0.812012f, 0.825684f, 0.837891f,
+ 0.848633f, 0.859863f, 0.869141f, 0.878418f, 0.886719f, 0.893066f, 0.900879f, 0.906738f, 0.913574f, 0.919434f, 0.924316f, 0.930176f,
+ 0.934082f, 0.939453f, 0.942871f, 0.946777f, 0.950684f, 0.954590f, 0.958008f, 0.960449f, 0.963379f, 0.966797f, 0.969238f, 0.971680f,
+ 0.974121f, 0.977051f, 0.978516f, 0.980957f, 0.983398f, 0.985352f, 0.987305f, 0.989258f, 0.991211f, 0.992676f, 0.996094f, 0.995605f,
+ 0.994629f, 0.993652f, 0.993164f, 0.992188f, 0.013596f, 0.044495f, 0.080017f, 0.119873f, 0.164307f, 0.211670f, 0.261475f, 0.311523f,
+ 0.362793f, 0.410645f, 0.458008f, 0.501953f, 0.542969f, 0.580078f, 0.614746f, 0.645996f, 0.674805f, 0.701172f, 0.723633f, 0.745117f,
+ 0.765625f, 0.782227f, 0.798828f, 0.812988f, 0.826172f, 0.838867f, 0.849609f, 0.861328f, 0.870605f, 0.878906f, 0.887695f, 0.895020f,
+ 0.901855f, 0.907715f, 0.914551f, 0.920898f, 0.925781f, 0.930664f, 0.934570f, 0.940918f, 0.943848f, 0.947754f, 0.951660f, 0.955566f,
+ 0.958984f, 0.961914f, 0.964844f, 0.967773f, 0.970703f, 0.973145f, 0.975586f, 0.978027f, 0.979980f, 0.982422f, 0.984863f, 0.986328f,
+ 0.988770f, 0.990234f, 0.995117f, 0.995117f, 0.994141f, 0.993652f, 0.992676f, 0.991699f, 0.010414f, 0.033203f, 0.060364f, 0.090942f,
+ 0.125610f, 0.163818f, 0.206421f, 0.250488f, 0.295898f, 0.341797f, 0.388428f, 0.433350f, 0.475830f, 0.517090f, 0.555176f, 0.589844f,
+ 0.622559f, 0.652344f, 0.680176f, 0.704590f, 0.729004f, 0.748535f, 0.767578f, 0.784668f, 0.800293f, 0.814941f, 0.828125f, 0.839844f,
+ 0.852051f, 0.861816f, 0.871582f, 0.879883f, 0.888672f, 0.895996f, 0.903320f, 0.909180f, 0.916016f, 0.921387f, 0.927246f, 0.931641f,
+ 0.937012f, 0.940918f, 0.946289f, 0.950195f, 0.953125f, 0.957520f, 0.960449f, 0.963867f, 0.966309f, 0.969238f, 0.972168f, 0.975098f,
+ 0.976562f, 0.979492f, 0.981934f, 0.983887f, 0.985840f, 0.988281f, 0.994629f, 0.994141f, 0.993652f, 0.992676f, 0.991699f, 0.990723f,
+ 0.007889f, 0.025772f, 0.046539f, 0.070312f, 0.097168f, 0.128540f, 0.162354f, 0.200195f, 0.239868f, 0.281738f, 0.325195f, 0.368896f,
+ 0.411621f, 0.453125f, 0.493652f, 0.531738f, 0.566406f, 0.601074f, 0.631836f, 0.659668f, 0.687988f, 0.709961f, 0.732422f, 0.753418f,
+ 0.770996f, 0.788086f, 0.804199f, 0.818359f, 0.831543f, 0.843750f, 0.854492f, 0.864746f, 0.873535f, 0.882812f, 0.890137f, 0.898438f,
+ 0.905273f, 0.912598f, 0.917969f, 0.923828f, 0.929199f, 0.934570f, 0.938477f, 0.942871f, 0.948242f, 0.951660f, 0.955078f, 0.958496f,
+ 0.961914f, 0.965332f, 0.968262f, 0.971680f, 0.973633f, 0.976562f, 0.979492f, 0.981445f, 0.983398f, 0.985352f, 0.993164f, 0.993164f,
+ 0.992676f, 0.991699f, 0.991211f, 0.990234f, 0.006332f, 0.020325f, 0.036438f, 0.055573f, 0.077026f, 0.101562f, 0.129028f, 0.160278f,
+ 0.194458f, 0.230347f, 0.268555f, 0.309326f, 0.350830f, 0.391846f, 0.432373f, 0.472412f, 0.509277f, 0.545410f, 0.579102f, 0.611816f,
+ 0.640625f, 0.668945f, 0.693848f, 0.716797f, 0.739258f, 0.758789f, 0.775879f, 0.793945f, 0.807617f, 0.821777f, 0.834961f, 0.846680f,
+ 0.857422f, 0.867676f, 0.877441f, 0.885742f, 0.893555f, 0.900391f, 0.908203f, 0.915039f, 0.920898f, 0.926270f, 0.931152f, 0.937012f,
+ 0.940918f, 0.946289f, 0.949219f, 0.954102f, 0.958008f, 0.960938f, 0.964355f, 0.967773f, 0.970703f, 0.973145f, 0.975586f, 0.978516f,
+ 0.981445f, 0.983398f, 0.992188f, 0.992188f, 0.991699f, 0.990723f, 0.990723f, 0.989746f, 0.005226f, 0.016647f, 0.029556f, 0.044434f,
+ 0.061523f, 0.081543f, 0.103760f, 0.129150f, 0.157837f, 0.188477f, 0.221924f, 0.257812f, 0.295654f, 0.334473f, 0.374023f, 0.412842f,
+ 0.451904f, 0.489990f, 0.525391f, 0.560059f, 0.593262f, 0.623047f, 0.651855f, 0.678223f, 0.702148f, 0.725098f, 0.745605f, 0.764160f,
+ 0.781738f, 0.799316f, 0.812500f, 0.827148f, 0.838867f, 0.851074f, 0.861328f, 0.871582f, 0.880371f, 0.889648f, 0.896973f, 0.904297f,
+ 0.911621f, 0.917480f, 0.923340f, 0.929688f, 0.934570f, 0.939941f, 0.943848f, 0.948242f, 0.951660f, 0.957031f, 0.959473f, 0.963379f,
+ 0.966797f, 0.969727f, 0.972656f, 0.976074f, 0.979004f, 0.980957f, 0.991699f, 0.991211f, 0.990723f, 0.990234f, 0.989746f, 0.988770f,
+ 0.004108f, 0.013542f, 0.023819f, 0.036194f, 0.050262f, 0.066223f, 0.084717f, 0.104797f, 0.128174f, 0.153809f, 0.182861f, 0.213989f,
+ 0.247437f, 0.282471f, 0.319580f, 0.357422f, 0.395508f, 0.433350f, 0.470947f, 0.506348f, 0.542480f, 0.575684f, 0.605957f, 0.635254f,
+ 0.662109f, 0.687988f, 0.711426f, 0.732910f, 0.753418f, 0.771973f, 0.789062f, 0.804688f, 0.819336f, 0.831543f, 0.843750f, 0.855469f,
+ 0.866211f, 0.875488f, 0.884766f, 0.893066f, 0.901367f, 0.907715f, 0.914062f, 0.921387f, 0.927246f, 0.932129f, 0.937012f, 0.942383f,
+ 0.946777f, 0.951660f, 0.956055f, 0.959473f, 0.962891f, 0.966309f, 0.969238f, 0.972168f, 0.975098f, 0.978027f, 0.989746f, 0.990234f,
+ 0.990234f, 0.989258f, 0.989258f, 0.988281f, 0.003597f, 0.011330f, 0.020065f, 0.029938f, 0.041412f, 0.054504f, 0.068970f, 0.086182f,
+ 0.105469f, 0.126709f, 0.151123f, 0.177612f, 0.206909f, 0.237915f, 0.271484f, 0.305664f, 0.342529f, 0.378906f, 0.416748f, 0.453125f,
+ 0.489502f, 0.524414f, 0.558105f, 0.589844f, 0.619629f, 0.646973f, 0.673828f, 0.698242f, 0.721191f, 0.742676f, 0.761230f, 0.778809f,
+ 0.796387f, 0.810547f, 0.824707f, 0.837891f, 0.850098f, 0.861328f, 0.871094f, 0.881348f, 0.889648f, 0.896973f, 0.904785f, 0.912109f,
+ 0.919434f, 0.924316f, 0.931152f, 0.936523f, 0.941895f, 0.946289f, 0.951172f, 0.955078f, 0.959473f, 0.962402f, 0.965820f, 0.969238f,
+ 0.972656f, 0.975586f, 0.988770f, 0.989258f, 0.989258f, 0.988770f, 0.987793f, 0.987305f, 0.002836f, 0.009857f, 0.016693f, 0.025208f,
+ 0.034668f, 0.045288f, 0.057617f, 0.071106f, 0.087463f, 0.104858f, 0.125000f, 0.147461f, 0.172119f, 0.199829f, 0.229248f, 0.260742f,
+ 0.294434f, 0.329102f, 0.365479f, 0.400879f, 0.437012f, 0.472656f, 0.508301f, 0.541992f, 0.574219f, 0.604980f, 0.634766f, 0.660645f,
+ 0.686523f, 0.709473f, 0.731445f, 0.751953f, 0.770996f, 0.789062f, 0.804199f, 0.817871f, 0.832520f, 0.844727f, 0.856445f, 0.867188f,
+ 0.876953f, 0.886719f, 0.895020f, 0.902832f, 0.909668f, 0.916504f, 0.923340f, 0.929688f, 0.935547f, 0.939941f, 0.944824f, 0.949707f,
+ 0.954102f, 0.958496f, 0.961914f, 0.965820f, 0.969238f, 0.972656f, 0.987793f, 0.988281f, 0.988281f, 0.987793f, 0.986816f, 0.986328f,
+ 0.002541f, 0.008118f, 0.014244f, 0.021194f, 0.029480f, 0.037811f, 0.048584f, 0.060028f, 0.073242f, 0.088196f, 0.104370f, 0.123047f,
+ 0.144531f, 0.167114f, 0.193237f, 0.220947f, 0.250977f, 0.282227f, 0.316162f, 0.351074f, 0.386719f, 0.422119f, 0.457520f, 0.492432f,
+ 0.526367f, 0.559082f, 0.590332f, 0.621094f, 0.648438f, 0.674316f, 0.698730f, 0.721191f, 0.742188f, 0.762207f, 0.780762f, 0.797363f,
+ 0.812500f, 0.826172f, 0.840332f, 0.852051f, 0.863770f, 0.873535f, 0.883301f, 0.892090f, 0.900391f, 0.908203f, 0.915039f, 0.922363f,
+ 0.928711f, 0.933594f, 0.939453f, 0.944824f, 0.950195f, 0.953125f, 0.958008f, 0.962402f, 0.965332f, 0.969238f, 0.986816f, 0.987305f,
+ 0.986816f, 0.986328f, 0.985840f, 0.984863f, 0.002115f, 0.007030f, 0.012138f, 0.017944f, 0.024521f, 0.032318f, 0.040955f, 0.050476f,
+ 0.061676f, 0.073914f, 0.087769f, 0.103271f, 0.121033f, 0.140747f, 0.162598f, 0.187256f, 0.213379f, 0.242065f, 0.272705f, 0.305176f,
+ 0.338623f, 0.373047f, 0.408691f, 0.443848f, 0.478760f, 0.512695f, 0.545898f, 0.577637f, 0.607910f, 0.636719f, 0.663086f, 0.688965f,
+ 0.712402f, 0.734863f, 0.754395f, 0.774414f, 0.791016f, 0.806641f, 0.822266f, 0.835449f, 0.848145f, 0.859863f, 0.870605f, 0.880371f,
+ 0.890137f, 0.898438f, 0.906250f, 0.914551f, 0.921387f, 0.926758f, 0.933594f, 0.938965f, 0.944336f, 0.949219f, 0.954102f, 0.958984f,
+ 0.961914f, 0.965820f, 0.985840f, 0.986328f, 0.985840f, 0.985352f, 0.985352f, 0.984375f, 0.001999f, 0.006226f, 0.010384f, 0.015594f,
+ 0.021027f, 0.027435f, 0.034637f, 0.042969f, 0.052124f, 0.062469f, 0.074097f, 0.087646f, 0.102173f, 0.119141f, 0.137695f, 0.158203f,
+ 0.181396f, 0.206543f, 0.233643f, 0.263184f, 0.295166f, 0.327148f, 0.360596f, 0.395264f, 0.430420f, 0.464600f, 0.499023f, 0.532227f,
+ 0.564941f, 0.595703f, 0.625000f, 0.651855f, 0.679199f, 0.703613f, 0.726074f, 0.747559f, 0.766602f, 0.784668f, 0.801758f, 0.816895f,
+ 0.831055f, 0.843750f, 0.856934f, 0.867188f, 0.878418f, 0.887207f, 0.896484f, 0.904785f, 0.913086f, 0.919922f, 0.926270f, 0.932617f,
+ 0.938477f, 0.944336f, 0.949707f, 0.953613f, 0.958496f, 0.962891f, 0.983887f, 0.984863f, 0.984863f, 0.984375f, 0.983887f, 0.983398f,
+ 0.001891f, 0.004959f, 0.009300f, 0.013786f, 0.018433f, 0.023560f, 0.029892f, 0.037018f, 0.044586f, 0.053284f, 0.062805f, 0.074341f,
+ 0.086975f, 0.100586f, 0.116760f, 0.133789f, 0.154175f, 0.176025f, 0.200317f, 0.226318f, 0.254395f, 0.284424f, 0.316650f, 0.349365f,
+ 0.383301f, 0.418213f, 0.452393f, 0.487061f, 0.520508f, 0.553223f, 0.584473f, 0.613770f, 0.643066f, 0.668945f, 0.695312f, 0.718262f,
+ 0.740234f, 0.761230f, 0.778809f, 0.797363f, 0.812988f, 0.827148f, 0.840332f, 0.854004f, 0.865723f, 0.875977f, 0.886230f, 0.895020f,
+ 0.904297f, 0.912598f, 0.919922f, 0.926270f, 0.932617f, 0.938965f, 0.943359f, 0.949219f, 0.955078f, 0.958984f, 0.982422f, 0.983887f,
+ 0.983398f, 0.982910f, 0.982910f, 0.981934f, 0.001368f, 0.004715f, 0.008041f, 0.011948f, 0.016235f, 0.020889f, 0.025848f, 0.031921f,
+ 0.038391f, 0.045563f, 0.054108f, 0.063477f, 0.074036f, 0.085815f, 0.099304f, 0.114563f, 0.131104f, 0.150146f, 0.170654f, 0.193970f,
+ 0.219360f, 0.246338f, 0.275146f, 0.306396f, 0.338867f, 0.372559f, 0.406494f, 0.440918f, 0.474609f, 0.508789f, 0.541992f, 0.574219f,
+ 0.604492f, 0.634277f, 0.661133f, 0.687500f, 0.710938f, 0.733887f, 0.754883f, 0.774414f, 0.792480f, 0.809570f, 0.824707f, 0.838379f,
+ 0.852051f, 0.862793f, 0.874023f, 0.885254f, 0.895020f, 0.903320f, 0.912109f, 0.919434f, 0.926758f, 0.932617f, 0.939941f, 0.945312f,
+ 0.951172f, 0.955078f, 0.980957f, 0.982910f, 0.982422f, 0.982422f, 0.981445f, 0.981445f, 0.001393f, 0.004227f, 0.007011f, 0.010323f,
+ 0.014107f, 0.018234f, 0.022766f, 0.027649f, 0.032898f, 0.039581f, 0.046539f, 0.054230f, 0.063293f, 0.073608f, 0.085144f, 0.097961f,
+ 0.112305f, 0.127930f, 0.146362f, 0.166260f, 0.188599f, 0.212524f, 0.238647f, 0.266846f, 0.297363f, 0.328369f, 0.361816f, 0.395752f,
+ 0.429932f, 0.464844f, 0.498535f, 0.531250f, 0.564453f, 0.596191f, 0.625488f, 0.653320f, 0.680176f, 0.704590f, 0.728027f, 0.750977f,
+ 0.770020f, 0.788574f, 0.805176f, 0.821289f, 0.835449f, 0.849609f, 0.862793f, 0.874023f, 0.884277f, 0.894043f, 0.903320f, 0.911621f,
+ 0.919434f, 0.926758f, 0.933594f, 0.939453f, 0.945312f, 0.951172f, 0.979492f, 0.980957f, 0.980957f, 0.980957f, 0.980469f, 0.979980f,
+ 0.001163f, 0.003527f, 0.006229f, 0.009323f, 0.012199f, 0.015808f, 0.019928f, 0.024200f, 0.028870f, 0.033997f, 0.040161f, 0.046967f,
+ 0.054871f, 0.063477f, 0.073181f, 0.083618f, 0.096252f, 0.109863f, 0.125122f, 0.142334f, 0.161743f, 0.182739f, 0.206421f, 0.232300f,
+ 0.259277f, 0.288086f, 0.320068f, 0.352783f, 0.386475f, 0.420410f, 0.454590f, 0.489258f, 0.521973f, 0.555176f, 0.586914f, 0.617188f,
+ 0.646484f, 0.673828f, 0.699707f, 0.723633f, 0.746094f, 0.766113f, 0.785645f, 0.803223f, 0.819336f, 0.834961f, 0.848633f, 0.861328f,
+ 0.873535f, 0.884766f, 0.893555f, 0.903809f, 0.911621f, 0.920410f, 0.928223f, 0.934082f, 0.939941f, 0.946777f, 0.978027f, 0.979492f,
+ 0.979492f, 0.979004f, 0.979004f, 0.978516f, 0.000981f, 0.002987f, 0.005329f, 0.008186f, 0.010895f, 0.013832f, 0.017532f, 0.021149f,
+ 0.025253f, 0.029999f, 0.035034f, 0.040985f, 0.047485f, 0.054993f, 0.063049f, 0.072510f, 0.082581f, 0.094421f, 0.107727f, 0.122498f,
+ 0.138794f, 0.157471f, 0.178467f, 0.200562f, 0.225586f, 0.251953f, 0.281250f, 0.311279f, 0.343750f, 0.377197f, 0.411621f, 0.445557f,
+ 0.479736f, 0.513672f, 0.546875f, 0.579590f, 0.610352f, 0.640625f, 0.668457f, 0.694336f, 0.718750f, 0.742188f, 0.762695f, 0.782715f,
+ 0.801270f, 0.817871f, 0.833496f, 0.847168f, 0.860840f, 0.872559f, 0.884277f, 0.894531f, 0.904297f, 0.912598f, 0.920898f, 0.928711f,
+ 0.935547f, 0.942383f, 0.976074f, 0.978027f, 0.978516f, 0.978027f, 0.977539f, 0.977051f, 0.000880f, 0.002707f, 0.005089f, 0.007305f,
+ 0.010147f, 0.012596f, 0.015160f, 0.018616f, 0.022507f, 0.026230f, 0.030777f, 0.035767f, 0.041351f, 0.047455f, 0.054565f, 0.062256f,
+ 0.071289f, 0.081299f, 0.092346f, 0.105408f, 0.119812f, 0.135620f, 0.153320f, 0.173462f, 0.195068f, 0.219482f, 0.245361f, 0.273682f,
+ 0.303711f, 0.335938f, 0.368896f, 0.402588f, 0.437500f, 0.472168f, 0.505859f, 0.539551f, 0.573242f, 0.604492f, 0.634766f, 0.663086f,
+ 0.689453f, 0.714844f, 0.738770f, 0.760254f, 0.780762f, 0.799316f, 0.817383f, 0.833496f, 0.847168f, 0.860840f, 0.873535f, 0.884766f,
+ 0.895508f, 0.905273f, 0.914062f, 0.922363f, 0.930176f, 0.937012f, 0.974609f, 0.976074f, 0.976074f, 0.976562f, 0.976074f, 0.975586f,
+ 0.000851f, 0.002659f, 0.004692f, 0.006466f, 0.008545f, 0.011055f, 0.013649f, 0.016403f, 0.019714f, 0.023056f, 0.026962f, 0.031235f,
+ 0.035828f, 0.041656f, 0.047699f, 0.054077f, 0.061859f, 0.070496f, 0.080200f, 0.091125f, 0.103088f, 0.116882f, 0.132446f, 0.149780f,
+ 0.168701f, 0.190430f, 0.213379f, 0.239258f, 0.267334f, 0.296631f, 0.328369f, 0.360840f, 0.395020f, 0.429932f, 0.464355f, 0.499512f,
+ 0.533203f, 0.566406f, 0.599121f, 0.629883f, 0.658203f, 0.687012f, 0.712402f, 0.735840f, 0.758789f, 0.779297f, 0.798828f, 0.816406f,
+ 0.832520f, 0.847168f, 0.861328f, 0.874023f, 0.886230f, 0.896973f, 0.907227f, 0.915527f, 0.924805f, 0.931641f, 0.972168f, 0.975586f,
+ 0.975586f, 0.974609f, 0.974121f, 0.973633f, 0.000762f, 0.002214f, 0.004040f, 0.005859f, 0.007790f, 0.009689f, 0.012161f, 0.014786f,
+ 0.017441f, 0.020493f, 0.023956f, 0.027618f, 0.031860f, 0.036255f, 0.041595f, 0.047394f, 0.053894f, 0.061188f, 0.069214f, 0.078735f,
+ 0.089050f, 0.101135f, 0.114441f, 0.129150f, 0.145874f, 0.164673f, 0.185303f, 0.208862f, 0.233765f, 0.260742f, 0.290283f, 0.321045f,
+ 0.354248f, 0.388184f, 0.422607f, 0.457764f, 0.493652f, 0.526855f, 0.561523f, 0.594238f, 0.625977f, 0.655273f, 0.683594f, 0.710449f,
+ 0.734863f, 0.758301f, 0.779297f, 0.798828f, 0.817383f, 0.833984f, 0.848145f, 0.862793f, 0.875488f, 0.887207f, 0.899414f, 0.908691f,
+ 0.917969f, 0.926270f, 0.970215f, 0.972656f, 0.974121f, 0.973145f, 0.972656f, 0.972168f, 0.000732f, 0.001928f, 0.003513f, 0.005234f,
+ 0.007042f, 0.008629f, 0.010620f, 0.012985f, 0.015244f, 0.018158f, 0.020935f, 0.024475f, 0.027908f, 0.032013f, 0.036316f, 0.041290f,
+ 0.046661f, 0.053040f, 0.060089f, 0.068115f, 0.077087f, 0.087463f, 0.099121f, 0.111633f, 0.126221f, 0.142578f, 0.160767f, 0.181396f,
+ 0.203003f, 0.228149f, 0.255127f, 0.284180f, 0.315186f, 0.347900f, 0.381836f, 0.416748f, 0.451904f, 0.487549f, 0.522949f, 0.556641f,
+ 0.590332f, 0.623047f, 0.652832f, 0.682129f, 0.708984f, 0.733887f, 0.757324f, 0.779785f, 0.799316f, 0.818359f, 0.835449f, 0.850586f,
+ 0.865234f, 0.877441f, 0.890137f, 0.901367f, 0.912109f, 0.920410f, 0.968262f, 0.970703f, 0.971191f, 0.970703f, 0.971191f, 0.971191f,
+ 0.000524f, 0.001758f, 0.003185f, 0.004864f, 0.006081f, 0.007820f, 0.009705f, 0.011467f, 0.013634f, 0.016068f, 0.018707f, 0.021378f,
+ 0.024597f, 0.028030f, 0.032135f, 0.036224f, 0.041016f, 0.046692f, 0.052399f, 0.059265f, 0.067505f, 0.076050f, 0.085510f, 0.096558f,
+ 0.109253f, 0.123657f, 0.138794f, 0.157227f, 0.176880f, 0.198730f, 0.223267f, 0.250000f, 0.278809f, 0.309326f, 0.342041f, 0.375977f,
+ 0.410889f, 0.447021f, 0.483154f, 0.518555f, 0.554199f, 0.586914f, 0.620117f, 0.650879f, 0.681641f, 0.708496f, 0.734375f, 0.757324f,
+ 0.780762f, 0.801270f, 0.819336f, 0.837891f, 0.852539f, 0.867188f, 0.880371f, 0.893066f, 0.903809f, 0.914551f, 0.966309f, 0.968750f,
+ 0.969238f, 0.969727f, 0.968750f, 0.968750f, 0.000503f, 0.001896f, 0.002653f, 0.004128f, 0.005627f, 0.007004f, 0.008797f, 0.010361f,
+ 0.012230f, 0.014175f, 0.016647f, 0.019348f, 0.021454f, 0.024872f, 0.028290f, 0.031830f, 0.036163f, 0.040649f, 0.045715f, 0.051941f,
+ 0.058319f, 0.065979f, 0.074402f, 0.083618f, 0.094360f, 0.106812f, 0.120239f, 0.135742f, 0.153320f, 0.172974f, 0.194824f, 0.218506f,
+ 0.245117f, 0.273926f, 0.304688f, 0.336426f, 0.371094f, 0.406982f, 0.442627f, 0.479492f, 0.514648f, 0.550781f, 0.584961f, 0.618652f,
+ 0.650879f, 0.681152f, 0.709473f, 0.735352f, 0.760742f, 0.782715f, 0.803711f, 0.821777f, 0.838867f, 0.855957f, 0.870605f, 0.884277f,
+ 0.895996f, 0.906738f, 0.964355f, 0.966309f, 0.967285f, 0.966797f, 0.966309f, 0.966309f, 0.000636f, 0.001421f, 0.002768f, 0.003761f,
+ 0.004944f, 0.006462f, 0.007889f, 0.009262f, 0.010780f, 0.013000f, 0.014946f, 0.017029f, 0.019516f, 0.022049f, 0.024933f, 0.028091f,
+ 0.031616f, 0.035553f, 0.040161f, 0.045380f, 0.051239f, 0.057281f, 0.064270f, 0.072693f, 0.081970f, 0.092468f, 0.104736f, 0.117859f,
+ 0.132690f, 0.150391f, 0.169189f, 0.190796f, 0.214233f, 0.240601f, 0.268555f, 0.299561f, 0.332520f, 0.367188f, 0.402344f, 0.438965f,
+ 0.476074f, 0.512695f, 0.549805f, 0.584473f, 0.619141f, 0.651367f, 0.681152f, 0.709961f, 0.737305f, 0.762695f, 0.785156f, 0.806641f,
+ 0.826172f, 0.843262f, 0.859375f, 0.874023f, 0.888184f, 0.900391f, 0.961426f, 0.964355f, 0.965332f, 0.964844f, 0.964355f, 0.964844f,
+ 0.000295f, 0.001419f, 0.002342f, 0.003471f, 0.004539f, 0.005821f, 0.006882f, 0.008354f, 0.010155f, 0.011574f, 0.013283f, 0.015129f,
+ 0.017090f, 0.019333f, 0.022125f, 0.024643f, 0.028122f, 0.031586f, 0.035522f, 0.039825f, 0.044586f, 0.050110f, 0.056091f, 0.063354f,
+ 0.071045f, 0.080078f, 0.090637f, 0.102112f, 0.115479f, 0.130127f, 0.147217f, 0.165649f, 0.186768f, 0.210571f, 0.236694f, 0.265137f,
+ 0.295654f, 0.328857f, 0.363770f, 0.399902f, 0.436523f, 0.474365f, 0.511230f, 0.548828f, 0.584961f, 0.619141f, 0.652344f, 0.684082f,
+ 0.712891f, 0.741211f, 0.766113f, 0.789062f, 0.810547f, 0.830078f, 0.848633f, 0.864258f, 0.879395f, 0.892578f, 0.958496f, 0.962402f,
+ 0.962402f, 0.962402f, 0.961914f, 0.962402f, 0.000464f, 0.001313f, 0.002159f, 0.003134f, 0.004463f, 0.005001f, 0.006466f, 0.007595f,
+ 0.008842f, 0.010277f, 0.011971f, 0.013550f, 0.015434f, 0.017242f, 0.019348f, 0.021805f, 0.024734f, 0.027817f, 0.031174f, 0.034821f,
+ 0.039124f, 0.043823f, 0.049164f, 0.055237f, 0.062164f, 0.069336f, 0.078430f, 0.088501f, 0.099976f, 0.112854f, 0.127319f, 0.143555f,
+ 0.162354f, 0.183350f, 0.207031f, 0.233032f, 0.260986f, 0.291992f, 0.325195f, 0.361084f, 0.397217f, 0.435059f, 0.473389f, 0.510742f,
+ 0.549316f, 0.586426f, 0.620605f, 0.654785f, 0.686523f, 0.716797f, 0.744629f, 0.769043f, 0.793945f, 0.815918f, 0.834961f, 0.852539f,
+ 0.869141f, 0.884277f, 0.955078f, 0.959473f, 0.959473f, 0.959473f, 0.959961f, 0.959961f, 0.000541f, 0.001223f, 0.002172f, 0.002886f,
+ 0.003679f, 0.004681f, 0.005512f, 0.006683f, 0.008049f, 0.009346f, 0.010704f, 0.012024f, 0.013626f, 0.015213f, 0.017227f, 0.019516f,
+ 0.022079f, 0.024612f, 0.027313f, 0.030731f, 0.034180f, 0.038239f, 0.042969f, 0.048187f, 0.053864f, 0.060516f, 0.068298f, 0.076843f,
+ 0.086670f, 0.097473f, 0.110107f, 0.124268f, 0.140869f, 0.159302f, 0.180420f, 0.203613f, 0.229614f, 0.258057f, 0.289062f, 0.323486f,
+ 0.358398f, 0.395996f, 0.434082f, 0.472900f, 0.511719f, 0.550293f, 0.587402f, 0.624023f, 0.658203f, 0.690918f, 0.721191f, 0.749512f,
+ 0.774902f, 0.799316f, 0.821289f, 0.840820f, 0.859375f, 0.875488f, 0.952637f, 0.956543f, 0.957520f, 0.957520f, 0.957520f, 0.957031f,
+ 0.000252f, 0.001056f, 0.001923f, 0.002523f, 0.003414f, 0.003960f, 0.005146f, 0.006172f, 0.007130f, 0.008179f, 0.009567f, 0.010735f,
+ 0.012077f, 0.013878f, 0.015640f, 0.017456f, 0.019638f, 0.021622f, 0.024170f, 0.026978f, 0.030121f, 0.033630f, 0.037445f, 0.042053f,
+ 0.047119f, 0.052826f, 0.059174f, 0.066711f, 0.075012f, 0.084473f, 0.095276f, 0.107727f, 0.122070f, 0.138184f, 0.156250f, 0.177246f,
+ 0.200928f, 0.226929f, 0.255371f, 0.286865f, 0.321289f, 0.356934f, 0.395264f, 0.434326f, 0.473877f, 0.514160f, 0.553711f, 0.591797f,
+ 0.628418f, 0.663574f, 0.696777f, 0.728027f, 0.755859f, 0.782715f, 0.806152f, 0.829102f, 0.847656f, 0.867188f, 0.949707f, 0.954102f,
+ 0.954590f, 0.954590f, 0.954102f, 0.954590f, 0.000365f, 0.000963f, 0.001581f, 0.002337f, 0.002996f, 0.003952f, 0.004608f, 0.005459f,
+ 0.006489f, 0.007351f, 0.008484f, 0.009544f, 0.011108f, 0.012413f, 0.013901f, 0.015388f, 0.017181f, 0.019012f, 0.021439f, 0.023727f,
+ 0.026520f, 0.029449f, 0.032898f, 0.036835f, 0.041046f, 0.045868f, 0.051575f, 0.058075f, 0.064758f, 0.073120f, 0.082520f, 0.093079f,
+ 0.105652f, 0.119385f, 0.135620f, 0.153687f, 0.174683f, 0.198364f, 0.224365f, 0.253662f, 0.285400f, 0.320557f, 0.357178f, 0.395752f,
+ 0.435791f, 0.476318f, 0.516602f, 0.557129f, 0.596191f, 0.633789f, 0.669434f, 0.703613f, 0.734375f, 0.763672f, 0.790039f, 0.812988f,
+ 0.836914f, 0.855957f, 0.946289f, 0.949707f, 0.951172f, 0.951172f, 0.951172f, 0.951172f, 0.000404f, 0.001028f, 0.001410f, 0.002098f,
+ 0.002657f, 0.003445f, 0.004391f, 0.005039f, 0.005665f, 0.006569f, 0.007549f, 0.008614f, 0.009743f, 0.011108f, 0.012390f, 0.013611f,
+ 0.015396f, 0.017044f, 0.018921f, 0.020874f, 0.023453f, 0.025833f, 0.028809f, 0.032501f, 0.036011f, 0.040161f, 0.044952f, 0.050018f,
+ 0.056091f, 0.063477f, 0.071533f, 0.080200f, 0.091064f, 0.103027f, 0.117065f, 0.133057f, 0.151489f, 0.171997f, 0.196045f, 0.222290f,
+ 0.251709f, 0.284424f, 0.319824f, 0.357422f, 0.397217f, 0.438232f, 0.479492f, 0.521484f, 0.562500f, 0.602051f, 0.641113f, 0.677734f,
+ 0.711914f, 0.743164f, 0.772461f, 0.799316f, 0.822754f, 0.845215f, 0.942383f, 0.946777f, 0.947754f, 0.947754f, 0.948242f, 0.948242f,
+ 0.000406f, 0.000992f, 0.001447f, 0.001986f, 0.002499f, 0.003149f, 0.003769f, 0.004272f, 0.005016f, 0.005981f, 0.006924f, 0.007675f,
+ 0.008766f, 0.009727f, 0.010765f, 0.011986f, 0.013588f, 0.014915f, 0.016724f, 0.018478f, 0.020508f, 0.022873f, 0.025497f, 0.028336f,
+ 0.031525f, 0.034882f, 0.038818f, 0.043243f, 0.048615f, 0.054626f, 0.061707f, 0.069214f, 0.078430f, 0.089111f, 0.101013f, 0.115112f,
+ 0.130859f, 0.148926f, 0.170166f, 0.193604f, 0.220947f, 0.250732f, 0.283936f, 0.320068f, 0.358887f, 0.400391f, 0.442139f, 0.483887f,
+ 0.527344f, 0.569824f, 0.610352f, 0.649414f, 0.686523f, 0.722168f, 0.753906f, 0.782227f, 0.809570f, 0.833496f, 0.938477f, 0.942871f,
+ 0.944824f, 0.944336f, 0.943848f, 0.943848f, 0.000235f, 0.000984f, 0.001204f, 0.001706f, 0.002239f, 0.002998f, 0.003462f, 0.004093f,
+ 0.004372f, 0.005371f, 0.006149f, 0.006962f, 0.007736f, 0.008766f, 0.009804f, 0.010780f, 0.011887f, 0.013336f, 0.014618f, 0.016159f,
+ 0.018158f, 0.020050f, 0.022232f, 0.024597f, 0.027313f, 0.030334f, 0.033752f, 0.037872f, 0.042389f, 0.047516f, 0.053192f, 0.059937f,
+ 0.067749f, 0.076599f, 0.086975f, 0.098755f, 0.112610f, 0.128662f, 0.146973f, 0.168091f, 0.192383f, 0.220215f, 0.250732f, 0.284668f,
+ 0.322021f, 0.361572f, 0.403564f, 0.446777f, 0.490723f, 0.534668f, 0.577637f, 0.619629f, 0.660156f, 0.697754f, 0.731934f, 0.764648f,
+ 0.794922f, 0.820312f, 0.934082f, 0.939453f, 0.939941f, 0.941406f, 0.940430f, 0.940918f, 0.000237f, 0.000591f, 0.001098f, 0.001619f,
+ 0.002241f, 0.002636f, 0.003176f, 0.003521f, 0.004101f, 0.004631f, 0.005398f, 0.006378f, 0.007000f, 0.007767f, 0.008713f, 0.009758f,
+ 0.010475f, 0.011734f, 0.013016f, 0.014404f, 0.015762f, 0.017517f, 0.019440f, 0.021469f, 0.023651f, 0.026199f, 0.029495f, 0.033112f,
+ 0.036499f, 0.040955f, 0.045959f, 0.051849f, 0.058197f, 0.065552f, 0.074585f, 0.085022f, 0.096680f, 0.110535f, 0.126709f, 0.145264f,
+ 0.166626f, 0.191406f, 0.219482f, 0.250488f, 0.286133f, 0.323975f, 0.365723f, 0.408447f, 0.453125f, 0.498779f, 0.542969f, 0.588379f,
+ 0.631836f, 0.671387f, 0.709473f, 0.745117f, 0.777344f, 0.807617f, 0.930176f, 0.935059f, 0.936523f, 0.936523f, 0.936523f, 0.936035f,
+ 0.000242f, 0.000761f, 0.000943f, 0.001624f, 0.001858f, 0.002390f, 0.002638f, 0.003054f, 0.003805f, 0.004559f, 0.005035f, 0.005493f,
+ 0.006157f, 0.006878f, 0.007687f, 0.008530f, 0.009178f, 0.010406f, 0.011406f, 0.012520f, 0.014053f, 0.015579f, 0.017105f, 0.018661f,
+ 0.020737f, 0.022903f, 0.025650f, 0.028259f, 0.031433f, 0.035065f, 0.039581f, 0.044342f, 0.049988f, 0.056366f, 0.064026f, 0.072632f,
+ 0.082825f, 0.094666f, 0.108582f, 0.124634f, 0.143799f, 0.165405f, 0.190796f, 0.219360f, 0.251953f, 0.287842f, 0.328125f, 0.370605f,
+ 0.415283f, 0.461670f, 0.507812f, 0.555176f, 0.600586f, 0.645020f, 0.685547f, 0.724121f, 0.759277f, 0.792969f, 0.924805f, 0.931152f,
+ 0.931641f, 0.932129f, 0.932129f, 0.931641f, 0.000240f, 0.000685f, 0.000955f, 0.001395f, 0.001768f, 0.002157f, 0.002533f, 0.002970f,
+ 0.003223f, 0.003813f, 0.004601f, 0.004993f, 0.005428f, 0.005981f, 0.006878f, 0.007484f, 0.008110f, 0.009132f, 0.009964f, 0.011208f,
+ 0.012138f, 0.013374f, 0.015099f, 0.016190f, 0.018112f, 0.020187f, 0.022202f, 0.024780f, 0.027573f, 0.030411f, 0.034119f, 0.037964f,
+ 0.042755f, 0.048553f, 0.054474f, 0.061890f, 0.070984f, 0.080688f, 0.092590f, 0.106812f, 0.123291f, 0.142456f, 0.164551f, 0.190430f,
+ 0.220459f, 0.253418f, 0.291504f, 0.332520f, 0.376709f, 0.423340f, 0.471436f, 0.520508f, 0.567383f, 0.614746f, 0.660156f, 0.702148f,
+ 0.741211f, 0.776367f, 0.920410f, 0.925293f, 0.926270f, 0.926758f, 0.927246f, 0.926758f, 0.000244f, 0.000431f, 0.000799f, 0.001309f,
+ 0.001587f, 0.001945f, 0.002317f, 0.002514f, 0.003290f, 0.003548f, 0.004082f, 0.004349f, 0.004707f, 0.005348f, 0.006027f, 0.006565f,
+ 0.007141f, 0.008011f, 0.008850f, 0.009552f, 0.010757f, 0.011650f, 0.012794f, 0.014145f, 0.015778f, 0.017303f, 0.019028f, 0.021088f,
+ 0.023575f, 0.026169f, 0.029175f, 0.032562f, 0.036713f, 0.041382f, 0.046448f, 0.052948f, 0.060303f, 0.068787f, 0.079041f, 0.090942f,
+ 0.105103f, 0.121643f, 0.141113f, 0.164185f, 0.190308f, 0.221191f, 0.256836f, 0.295898f, 0.339355f, 0.385010f, 0.433838f, 0.484619f,
+ 0.534668f, 0.583496f, 0.631348f, 0.678223f, 0.719727f, 0.759766f, 0.913574f, 0.920410f, 0.921387f, 0.921875f, 0.921875f, 0.921387f,
+ 0.000243f, 0.000496f, 0.000847f, 0.001157f, 0.001426f, 0.001634f, 0.002020f, 0.002338f, 0.002607f, 0.003035f, 0.003502f, 0.003872f,
+ 0.004459f, 0.004726f, 0.005402f, 0.005779f, 0.006325f, 0.007095f, 0.007767f, 0.008568f, 0.009331f, 0.010086f, 0.011009f, 0.012314f,
+ 0.013611f, 0.015060f, 0.016312f, 0.018158f, 0.020401f, 0.022476f, 0.024979f, 0.027863f, 0.031036f, 0.034943f, 0.039581f, 0.044830f,
+ 0.050903f, 0.058289f, 0.066895f, 0.076782f, 0.088989f, 0.103210f, 0.120422f, 0.140259f, 0.164185f, 0.191772f, 0.223877f, 0.260742f,
+ 0.301758f, 0.347168f, 0.395508f, 0.446533f, 0.497803f, 0.551270f, 0.601562f, 0.651855f, 0.697754f, 0.741211f, 0.908203f, 0.915039f,
+ 0.916016f, 0.916016f, 0.916504f, 0.915527f, 0.000239f, 0.000345f, 0.000690f, 0.000913f, 0.001250f, 0.001343f, 0.001579f, 0.002050f,
+ 0.002331f, 0.002861f, 0.003048f, 0.003616f, 0.003696f, 0.004211f, 0.004723f, 0.005074f, 0.005657f, 0.006100f, 0.006893f, 0.007290f,
+ 0.008118f, 0.008659f, 0.009552f, 0.010704f, 0.011681f, 0.012764f, 0.014114f, 0.015533f, 0.017227f, 0.018982f, 0.021286f, 0.023560f,
+ 0.026489f, 0.029861f, 0.033417f, 0.037933f, 0.043121f, 0.049286f, 0.056519f, 0.065002f, 0.075073f, 0.087158f, 0.101624f, 0.118835f,
+ 0.139648f, 0.164185f, 0.193481f, 0.226929f, 0.265625f, 0.309570f, 0.356934f, 0.408203f, 0.461426f, 0.516113f, 0.569824f, 0.623047f,
+ 0.674316f, 0.720703f, 0.902344f, 0.908203f, 0.909668f, 0.910645f, 0.910645f, 0.911133f, 0.000000f, 0.000281f, 0.000560f, 0.000977f,
+ 0.001063f, 0.001171f, 0.001569f, 0.001903f, 0.002075f, 0.002413f, 0.002695f, 0.003004f, 0.003399f, 0.003553f, 0.003998f, 0.004333f,
+ 0.004971f, 0.005314f, 0.005806f, 0.006340f, 0.007015f, 0.007492f, 0.008377f, 0.009186f, 0.010094f, 0.010910f, 0.012199f, 0.013351f,
+ 0.014618f, 0.016266f, 0.018082f, 0.019852f, 0.022491f, 0.025085f, 0.028168f, 0.031799f, 0.036041f, 0.041107f, 0.047394f, 0.054321f,
+ 0.062866f, 0.073181f, 0.085327f, 0.100525f, 0.118408f, 0.139648f, 0.165527f, 0.196411f, 0.231812f, 0.273193f, 0.318848f, 0.369629f,
+ 0.423828f, 0.480225f, 0.536621f, 0.592773f, 0.647949f, 0.699707f, 0.894043f, 0.900879f, 0.903809f, 0.903320f, 0.903320f, 0.902832f,
+ 0.000232f, 0.000227f, 0.000555f, 0.000656f, 0.000937f, 0.000985f, 0.001351f, 0.001723f, 0.001925f, 0.002010f, 0.002445f, 0.002625f,
+ 0.002760f, 0.003220f, 0.003551f, 0.003870f, 0.004303f, 0.004826f, 0.005028f, 0.005451f, 0.005985f, 0.006523f, 0.007000f, 0.007744f,
+ 0.008499f, 0.009361f, 0.010109f, 0.011185f, 0.012413f, 0.013603f, 0.015121f, 0.016891f, 0.018753f, 0.020920f, 0.023407f, 0.026764f,
+ 0.030197f, 0.034302f, 0.039429f, 0.044891f, 0.052368f, 0.060822f, 0.071167f, 0.083557f, 0.098877f, 0.117493f, 0.139893f, 0.167725f,
+ 0.200195f, 0.238037f, 0.281982f, 0.331543f, 0.385010f, 0.442627f, 0.501465f, 0.561523f, 0.620605f, 0.675781f, 0.887207f, 0.894531f,
+ 0.895020f, 0.896484f, 0.896484f, 0.895996f, 0.000000f, 0.000332f, 0.000577f, 0.000723f, 0.000720f, 0.001210f, 0.001469f, 0.001456f,
+ 0.001546f, 0.001775f, 0.002159f, 0.002291f, 0.002659f, 0.002916f, 0.003046f, 0.003439f, 0.003752f, 0.003883f, 0.004375f, 0.004635f,
+ 0.005241f, 0.005638f, 0.006054f, 0.006630f, 0.007191f, 0.007744f, 0.008545f, 0.009178f, 0.010498f, 0.011536f, 0.012802f, 0.013931f,
+ 0.015808f, 0.017548f, 0.019379f, 0.022110f, 0.025040f, 0.028473f, 0.032471f, 0.037323f, 0.043152f, 0.050476f, 0.058807f, 0.069214f,
+ 0.082520f, 0.098145f, 0.116821f, 0.141602f, 0.170044f, 0.204834f, 0.245728f, 0.293213f, 0.346436f, 0.403564f, 0.464111f, 0.527832f,
+ 0.589844f, 0.650879f, 0.878418f, 0.886719f, 0.888184f, 0.887695f, 0.888672f, 0.888672f, 0.000243f, 0.000307f, 0.000526f, 0.000561f,
+ 0.000923f, 0.000980f, 0.001143f, 0.001386f, 0.001414f, 0.001683f, 0.001735f, 0.001972f, 0.002232f, 0.002481f, 0.002657f, 0.002754f,
+ 0.003193f, 0.003359f, 0.003603f, 0.003956f, 0.004368f, 0.004692f, 0.005119f, 0.005596f, 0.005955f, 0.006634f, 0.007256f, 0.007881f,
+ 0.008652f, 0.009552f, 0.010376f, 0.011719f, 0.012634f, 0.014595f, 0.016113f, 0.018219f, 0.020554f, 0.023254f, 0.026520f, 0.030502f,
+ 0.035553f, 0.041168f, 0.048065f, 0.057190f, 0.067261f, 0.080811f, 0.097107f, 0.117737f, 0.143066f, 0.173950f, 0.211182f, 0.256592f,
+ 0.307129f, 0.364502f, 0.427002f, 0.491943f, 0.557617f, 0.624023f, 0.869629f, 0.877930f, 0.879883f, 0.879883f, 0.879883f, 0.880371f,
+ 0.000000f, 0.000270f, 0.000342f, 0.000509f, 0.000668f, 0.000989f, 0.000945f, 0.001105f, 0.001230f, 0.001335f, 0.001492f, 0.001757f,
+ 0.001917f, 0.002140f, 0.002386f, 0.002501f, 0.002644f, 0.002884f, 0.003199f, 0.003441f, 0.003620f, 0.003891f, 0.004337f, 0.004631f,
+ 0.005119f, 0.005520f, 0.006100f, 0.006504f, 0.007301f, 0.007771f, 0.008751f, 0.009521f, 0.010658f, 0.011765f, 0.013145f, 0.014641f,
+ 0.016785f, 0.018829f, 0.021545f, 0.024719f, 0.028381f, 0.033203f, 0.038849f, 0.046112f, 0.055084f, 0.065552f, 0.079529f, 0.096985f,
+ 0.118530f, 0.145630f, 0.179321f, 0.220337f, 0.269287f, 0.325439f, 0.387207f, 0.454102f, 0.524414f, 0.595215f, 0.859863f, 0.868652f,
+ 0.870605f, 0.869629f, 0.870117f, 0.870605f, 0.000000f, 0.000230f, 0.000334f, 0.000416f, 0.000700f, 0.000726f, 0.000921f, 0.001008f,
+ 0.001065f, 0.001186f, 0.001365f, 0.001471f, 0.001627f, 0.001796f, 0.001843f, 0.002069f, 0.002266f, 0.002438f, 0.002596f, 0.002831f,
+ 0.003000f, 0.003298f, 0.003597f, 0.003887f, 0.004265f, 0.004581f, 0.004986f, 0.005505f, 0.005947f, 0.006454f, 0.007069f, 0.007801f,
+ 0.008621f, 0.009575f, 0.010612f, 0.011848f, 0.013321f, 0.015259f, 0.017410f, 0.019775f, 0.022934f, 0.026550f, 0.031464f, 0.036713f,
+ 0.043945f, 0.052887f, 0.064209f, 0.078735f, 0.096924f, 0.120361f, 0.149536f, 0.186768f, 0.232422f, 0.285889f, 0.347656f, 0.415527f,
+ 0.488281f, 0.563965f, 0.849121f, 0.857910f, 0.859375f, 0.860840f, 0.860840f, 0.860352f, 0.000233f, 0.000225f, 0.000219f, 0.000431f,
+ 0.000579f, 0.000648f, 0.000671f, 0.000744f, 0.000946f, 0.000994f, 0.001091f, 0.001307f, 0.001364f, 0.001490f, 0.001561f, 0.001712f,
+ 0.001892f, 0.001999f, 0.002190f, 0.002369f, 0.002512f, 0.002733f, 0.003014f, 0.003145f, 0.003553f, 0.003822f, 0.004135f, 0.004326f,
+ 0.004799f, 0.005344f, 0.005718f, 0.006378f, 0.007008f, 0.007721f, 0.008400f, 0.009537f, 0.010597f, 0.011917f, 0.013542f, 0.015579f,
+ 0.018051f, 0.020889f, 0.024765f, 0.029236f, 0.034668f, 0.041779f, 0.051056f, 0.062439f, 0.077576f, 0.097595f, 0.122864f, 0.155273f,
+ 0.196655f, 0.247437f, 0.307617f, 0.375977f, 0.450684f, 0.531250f, 0.837891f, 0.847168f, 0.848633f, 0.849609f, 0.849121f, 0.849609f,
+ 0.000202f, 0.000180f, 0.000206f, 0.000339f, 0.000479f, 0.000536f, 0.000687f, 0.000739f, 0.000771f, 0.000849f, 0.001051f, 0.001060f,
+ 0.001154f, 0.001219f, 0.001389f, 0.001505f, 0.001469f, 0.001729f, 0.001858f, 0.001980f, 0.002209f, 0.002243f, 0.002483f, 0.002695f,
+ 0.002951f, 0.003149f, 0.003374f, 0.003654f, 0.004002f, 0.004154f, 0.004539f, 0.005032f, 0.005428f, 0.005989f, 0.006760f, 0.007549f,
+ 0.008423f, 0.009499f, 0.010620f, 0.012016f, 0.013992f, 0.016434f, 0.019135f, 0.022583f, 0.026840f, 0.032501f, 0.039551f, 0.048828f,
+ 0.061066f, 0.077393f, 0.098755f, 0.127075f, 0.163208f, 0.209717f, 0.267578f, 0.334961f, 0.411133f, 0.494629f, 0.825684f, 0.834473f,
+ 0.836426f, 0.837402f, 0.837402f, 0.837402f, 0.000000f, 0.000185f, 0.000184f, 0.000404f, 0.000408f, 0.000454f, 0.000480f, 0.000506f,
+ 0.000660f, 0.000694f, 0.000742f, 0.000801f, 0.000989f, 0.001111f, 0.001167f, 0.001250f, 0.001311f, 0.001424f, 0.001541f, 0.001574f,
+ 0.001712f, 0.001930f, 0.001982f, 0.002201f, 0.002375f, 0.002439f, 0.002792f, 0.002905f, 0.003065f, 0.003412f, 0.003653f, 0.003952f,
+ 0.004463f, 0.004723f, 0.005230f, 0.005936f, 0.006386f, 0.007092f, 0.008240f, 0.009247f, 0.010765f, 0.012344f, 0.014420f, 0.017090f,
+ 0.020493f, 0.024551f, 0.030014f, 0.037689f, 0.047302f, 0.060028f, 0.077820f, 0.100830f, 0.132812f, 0.174561f, 0.228516f, 0.294434f,
+ 0.371582f, 0.457031f, 0.812012f, 0.820801f, 0.823730f, 0.824219f, 0.824707f, 0.824219f, 0.000000f, 0.000053f, 0.000206f, 0.000360f,
+ 0.000379f, 0.000391f, 0.000379f, 0.000478f, 0.000549f, 0.000589f, 0.000626f, 0.000674f, 0.000762f, 0.000832f, 0.000894f, 0.001050f,
+ 0.001111f, 0.001155f, 0.001286f, 0.001345f, 0.001449f, 0.001564f, 0.001666f, 0.001750f, 0.001856f, 0.001925f, 0.002056f, 0.002359f,
+ 0.002542f, 0.002728f, 0.003042f, 0.003164f, 0.003460f, 0.003786f, 0.004116f, 0.004578f, 0.005116f, 0.005688f, 0.006508f, 0.007229f,
+ 0.008125f, 0.009232f, 0.010796f, 0.012741f, 0.015137f, 0.018158f, 0.022186f, 0.028030f, 0.035248f, 0.045593f, 0.059052f, 0.078308f,
+ 0.105042f, 0.141602f, 0.190308f, 0.252930f, 0.329102f, 0.417969f, 0.797852f, 0.807129f, 0.810059f, 0.810547f, 0.811035f, 0.810547f,
+ 0.000000f, 0.000000f, 0.000082f, 0.000195f, 0.000309f, 0.000336f, 0.000324f, 0.000414f, 0.000439f, 0.000460f, 0.000599f, 0.000643f,
+ 0.000637f, 0.000690f, 0.000733f, 0.000834f, 0.000821f, 0.000922f, 0.000989f, 0.001067f, 0.001207f, 0.001293f, 0.001327f, 0.001476f,
+ 0.001581f, 0.001663f, 0.001725f, 0.001906f, 0.001934f, 0.002180f, 0.002258f, 0.002602f, 0.002701f, 0.003019f, 0.003229f, 0.003502f,
+ 0.003847f, 0.004261f, 0.004795f, 0.005318f, 0.006130f, 0.007008f, 0.008118f, 0.009277f, 0.011024f, 0.013229f, 0.016205f, 0.020203f,
+ 0.025620f, 0.033020f, 0.043854f, 0.059021f, 0.080383f, 0.111206f, 0.154419f, 0.212646f, 0.287354f, 0.378418f, 0.781250f, 0.792480f,
+ 0.793457f, 0.795410f, 0.795898f, 0.794922f, 0.000000f, 0.000121f, 0.000120f, 0.000198f, 0.000275f, 0.000249f, 0.000290f, 0.000360f,
+ 0.000375f, 0.000379f, 0.000391f, 0.000438f, 0.000505f, 0.000534f, 0.000669f, 0.000629f, 0.000659f, 0.000754f, 0.000890f, 0.000833f,
+ 0.000849f, 0.000975f, 0.001029f, 0.001117f, 0.001193f, 0.001203f, 0.001269f, 0.001424f, 0.001594f, 0.001675f, 0.001737f, 0.001957f,
+ 0.002094f, 0.002319f, 0.002342f, 0.002609f, 0.002928f, 0.003248f, 0.003523f, 0.003967f, 0.004547f, 0.005138f, 0.005871f, 0.006760f,
+ 0.007912f, 0.009430f, 0.011528f, 0.014236f, 0.017899f, 0.023346f, 0.031235f, 0.042694f, 0.059235f, 0.084229f, 0.120972f, 0.173950f,
+ 0.245239f, 0.334473f, 0.764160f, 0.775391f, 0.777344f, 0.778809f, 0.777832f, 0.778809f, 0.000000f, 0.000121f, 0.000119f, 0.000182f,
+ 0.000177f, 0.000179f, 0.000262f, 0.000239f, 0.000309f, 0.000322f, 0.000404f, 0.000370f, 0.000361f, 0.000430f, 0.000458f, 0.000540f,
+ 0.000589f, 0.000615f, 0.000648f, 0.000632f, 0.000777f, 0.000782f, 0.000798f, 0.000871f, 0.000857f, 0.000925f, 0.001000f, 0.001045f,
+ 0.001191f, 0.001223f, 0.001426f, 0.001419f, 0.001512f, 0.001635f, 0.001884f, 0.002092f, 0.002100f, 0.002293f, 0.002577f, 0.003012f,
+ 0.003258f, 0.003761f, 0.004253f, 0.004814f, 0.005619f, 0.006676f, 0.008064f, 0.009750f, 0.012268f, 0.015854f, 0.021255f, 0.029282f,
+ 0.041687f, 0.061005f, 0.091370f, 0.136230f, 0.202759f, 0.291504f, 0.746582f, 0.757324f, 0.759277f, 0.760254f, 0.760254f, 0.760254f,
+ 0.000000f, 0.000000f, 0.000117f, 0.000126f, 0.000113f, 0.000146f, 0.000158f, 0.000155f, 0.000189f, 0.000288f, 0.000254f, 0.000336f,
+ 0.000347f, 0.000353f, 0.000370f, 0.000355f, 0.000390f, 0.000417f, 0.000456f, 0.000480f, 0.000525f, 0.000587f, 0.000596f, 0.000620f,
+ 0.000676f, 0.000740f, 0.000758f, 0.000852f, 0.000907f, 0.000947f, 0.001057f, 0.001122f, 0.001170f, 0.001293f, 0.001316f, 0.001437f,
+ 0.001531f, 0.001813f, 0.001952f, 0.002090f, 0.002346f, 0.002560f, 0.002974f, 0.003334f, 0.003899f, 0.004547f, 0.005360f, 0.006516f,
+ 0.008179f, 0.010468f, 0.013947f, 0.019241f, 0.027832f, 0.041443f, 0.064941f, 0.102600f, 0.162231f, 0.247437f, 0.726074f, 0.737793f,
+ 0.739258f, 0.740723f, 0.741211f, 0.741211f, 0.000000f, 0.000118f, 0.000115f, 0.000113f, 0.000110f, 0.000126f, 0.000121f, 0.000139f,
+ 0.000147f, 0.000160f, 0.000161f, 0.000233f, 0.000199f, 0.000266f, 0.000286f, 0.000297f, 0.000329f, 0.000313f, 0.000347f, 0.000358f,
+ 0.000364f, 0.000394f, 0.000435f, 0.000446f, 0.000489f, 0.000506f, 0.000546f, 0.000625f, 0.000648f, 0.000674f, 0.000723f, 0.000782f,
+ 0.000865f, 0.000918f, 0.000979f, 0.001104f, 0.001100f, 0.001196f, 0.001352f, 0.001488f, 0.001586f, 0.001749f, 0.001955f, 0.002275f,
+ 0.002644f, 0.003054f, 0.003563f, 0.004322f, 0.005314f, 0.006786f, 0.008980f, 0.012115f, 0.017319f, 0.026520f, 0.043121f, 0.072693f,
+ 0.123535f, 0.203613f, 0.705566f, 0.716797f, 0.719238f, 0.719727f, 0.720703f, 0.721191f, 0.000000f, 0.000000f, 0.000112f, 0.000109f,
+ 0.000106f, 0.000104f, 0.000102f, 0.000096f, 0.000091f, 0.000113f, 0.000147f, 0.000129f, 0.000155f, 0.000134f, 0.000196f, 0.000205f,
+ 0.000181f, 0.000239f, 0.000297f, 0.000255f, 0.000317f, 0.000273f, 0.000335f, 0.000299f, 0.000379f, 0.000385f, 0.000398f, 0.000402f,
+ 0.000473f, 0.000552f, 0.000489f, 0.000543f, 0.000557f, 0.000606f, 0.000662f, 0.000698f, 0.000747f, 0.000810f, 0.000902f, 0.000961f,
+ 0.001063f, 0.001166f, 0.001312f, 0.001523f, 0.001662f, 0.001908f, 0.002298f, 0.002758f, 0.003365f, 0.004135f, 0.005394f, 0.007290f,
+ 0.010490f, 0.015991f, 0.026215f, 0.047180f, 0.087646f, 0.160645f, 0.682617f, 0.695801f, 0.697266f, 0.697266f, 0.697266f, 0.698730f,
+ 0.000000f, 0.000112f, 0.000106f, 0.000104f, 0.000100f, 0.000098f, 0.000095f, 0.000094f, 0.000090f, 0.000085f, 0.000080f, 0.000081f,
+ 0.000085f, 0.000123f, 0.000123f, 0.000138f, 0.000151f, 0.000158f, 0.000147f, 0.000171f, 0.000183f, 0.000192f, 0.000242f, 0.000215f,
+ 0.000253f, 0.000256f, 0.000269f, 0.000278f, 0.000293f, 0.000315f, 0.000377f, 0.000357f, 0.000357f, 0.000423f, 0.000479f, 0.000493f,
+ 0.000489f, 0.000535f, 0.000579f, 0.000628f, 0.000683f, 0.000731f, 0.000833f, 0.000935f, 0.001068f, 0.001200f, 0.001347f, 0.001581f,
+ 0.001995f, 0.002419f, 0.003109f, 0.004147f, 0.005829f, 0.008919f, 0.014641f, 0.027405f, 0.056885f, 0.119385f, 0.658691f, 0.669922f,
+ 0.673828f, 0.673828f, 0.675293f, 0.675293f, 0.000000f, 0.000105f, 0.000101f, 0.000096f, 0.000092f, 0.000089f, 0.000087f, 0.000085f,
+ 0.000083f, 0.000081f, 0.000077f, 0.000073f, 0.000070f, 0.000066f, 0.000080f, 0.000084f, 0.000089f, 0.000068f, 0.000101f, 0.000094f,
+ 0.000116f, 0.000118f, 0.000125f, 0.000129f, 0.000150f, 0.000168f, 0.000153f, 0.000192f, 0.000195f, 0.000185f, 0.000200f, 0.000217f,
+ 0.000226f, 0.000247f, 0.000257f, 0.000262f, 0.000319f, 0.000334f, 0.000347f, 0.000376f, 0.000395f, 0.000447f, 0.000504f, 0.000544f,
+ 0.000590f, 0.000670f, 0.000789f, 0.000887f, 0.001069f, 0.001345f, 0.001670f, 0.002167f, 0.003065f, 0.004562f, 0.007660f, 0.014290f,
+ 0.032135f, 0.081299f, 0.632812f, 0.645996f, 0.648926f, 0.649414f, 0.648926f, 0.649902f, 0.000109f, 0.000094f, 0.000087f, 0.000082f,
+ 0.000078f, 0.000076f, 0.000074f, 0.000071f, 0.000069f, 0.000068f, 0.000067f, 0.000066f, 0.000064f, 0.000061f, 0.000058f, 0.000055f,
+ 0.000053f, 0.000050f, 0.000051f, 0.000046f, 0.000059f, 0.000056f, 0.000057f, 0.000068f, 0.000078f, 0.000088f, 0.000096f, 0.000096f,
+ 0.000105f, 0.000107f, 0.000128f, 0.000121f, 0.000133f, 0.000141f, 0.000156f, 0.000151f, 0.000160f, 0.000200f, 0.000209f, 0.000198f,
+ 0.000222f, 0.000242f, 0.000258f, 0.000275f, 0.000314f, 0.000352f, 0.000410f, 0.000468f, 0.000537f, 0.000639f, 0.000799f, 0.001002f,
+ 0.001390f, 0.002092f, 0.003466f, 0.006653f, 0.015305f, 0.048004f, 0.606934f, 0.618652f, 0.622559f, 0.623047f, 0.623535f, 0.624023f,
+ 0.000084f, 0.000067f, 0.000064f, 0.000062f, 0.000057f, 0.000056f, 0.000053f, 0.000054f, 0.000051f, 0.000052f, 0.000050f, 0.000050f,
+ 0.000050f, 0.000049f, 0.000048f, 0.000047f, 0.000046f, 0.000044f, 0.000042f, 0.000040f, 0.000039f, 0.000037f, 0.000035f, 0.000036f,
+ 0.000037f, 0.000031f, 0.000040f, 0.000041f, 0.000042f, 0.000051f, 0.000058f, 0.000063f, 0.000067f, 0.000069f, 0.000072f, 0.000079f,
+ 0.000085f, 0.000092f, 0.000093f, 0.000101f, 0.000107f, 0.000123f, 0.000125f, 0.000139f, 0.000147f, 0.000154f, 0.000181f, 0.000204f,
+ 0.000229f, 0.000270f, 0.000327f, 0.000425f, 0.000559f, 0.000772f, 0.001265f, 0.002462f, 0.006191f, 0.022415f, 0.578613f, 0.592285f,
+ 0.595215f, 0.596191f, 0.596191f, 0.597656f, 0.000008f, 0.000022f, 0.000022f, 0.000024f, 0.000024f, 0.000027f, 0.000028f, 0.000028f,
+ 0.000028f, 0.000026f, 0.000028f, 0.000029f, 0.000029f, 0.000028f, 0.000029f, 0.000029f, 0.000029f, 0.000029f, 0.000030f, 0.000030f,
+ 0.000030f, 0.000029f, 0.000028f, 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, 0.000020f, 0.000019f,
+ 0.000021f, 0.000020f, 0.000022f, 0.000026f, 0.000028f, 0.000033f, 0.000037f, 0.000036f, 0.000039f, 0.000045f, 0.000051f, 0.000046f,
+ 0.000056f, 0.000059f, 0.000061f, 0.000071f, 0.000084f, 0.000098f, 0.000110f, 0.000133f, 0.000169f, 0.000223f, 0.000356f, 0.000648f,
+ 0.001702f, 0.007713f, 0.550293f, 0.564453f, 0.566895f, 0.567871f, 0.568359f, 0.568848f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000002f, 0.000003f, 0.000004f, 0.000006f,
+ 0.000007f, 0.000007f, 0.000008f, 0.000008f, 0.000009f, 0.000010f, 0.000011f, 0.000011f, 0.000012f, 0.000012f, 0.000013f, 0.000013f,
+ 0.000013f, 0.000014f, 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f,
+ 0.000008f, 0.000008f, 0.000009f, 0.000011f, 0.000014f, 0.000017f, 0.000015f, 0.000018f, 0.000021f, 0.000022f, 0.000023f, 0.000026f,
+ 0.000035f, 0.000040f, 0.000056f, 0.000089f, 0.000225f, 0.001332f, 0.520996f, 0.535156f, 0.538086f, 0.540039f, 0.540039f, 0.540039f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000003f, 0.000003f,
+ 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000017f, 0.491211f, 0.506348f,
+ 0.508789f, 0.510254f, 0.510254f, 0.510742f,
+ },
+ {
+ 0.064758f, 0.179688f, 0.277344f, 0.358398f, 0.427002f, 0.485107f, 0.535156f, 0.578613f, 0.615234f, 0.647949f, 0.677734f, 0.703125f,
+ 0.725586f, 0.745605f, 0.763672f, 0.780273f, 0.795410f, 0.810059f, 0.821777f, 0.833496f, 0.843750f, 0.854004f, 0.862793f, 0.871582f,
+ 0.879883f, 0.886719f, 0.894043f, 0.900879f, 0.906250f, 0.912109f, 0.917969f, 0.922852f, 0.927246f, 0.932129f, 0.936523f, 0.940918f,
+ 0.944824f, 0.948242f, 0.951660f, 0.955078f, 0.958496f, 0.961426f, 0.964844f, 0.967773f, 0.970215f, 0.973145f, 0.975586f, 0.977539f,
+ 0.979980f, 0.982422f, 0.984863f, 0.986328f, 0.988770f, 0.990234f, 0.992676f, 0.993652f, 0.995605f, 0.997559f, 0.998535f, 0.996582f,
+ 0.995117f, 0.993652f, 0.992188f, 0.990723f, 0.040344f, 0.121460f, 0.199341f, 0.272949f, 0.339600f, 0.401123f, 0.455078f, 0.501953f,
+ 0.546875f, 0.583984f, 0.618164f, 0.648926f, 0.676270f, 0.700195f, 0.723145f, 0.743164f, 0.761230f, 0.776855f, 0.793457f, 0.806641f,
+ 0.819336f, 0.831543f, 0.842285f, 0.852051f, 0.861328f, 0.869629f, 0.877930f, 0.886230f, 0.892578f, 0.899902f, 0.905273f, 0.911621f,
+ 0.917480f, 0.922852f, 0.927246f, 0.932129f, 0.936035f, 0.940430f, 0.945312f, 0.949219f, 0.952148f, 0.956055f, 0.958984f, 0.961914f,
+ 0.965332f, 0.967773f, 0.970703f, 0.973633f, 0.976074f, 0.978516f, 0.980957f, 0.983398f, 0.985840f, 0.987305f, 0.989258f, 0.991699f,
+ 0.993652f, 0.995117f, 0.997070f, 0.995605f, 0.994141f, 0.993164f, 0.991699f, 0.990234f, 0.027191f, 0.084961f, 0.145630f, 0.206177f,
+ 0.266113f, 0.323242f, 0.377930f, 0.428711f, 0.474609f, 0.517090f, 0.554688f, 0.591309f, 0.621582f, 0.650391f, 0.676758f, 0.700684f,
+ 0.723145f, 0.741699f, 0.760254f, 0.776855f, 0.791504f, 0.805664f, 0.818359f, 0.830566f, 0.841309f, 0.851074f, 0.861816f, 0.870117f,
+ 0.878418f, 0.885254f, 0.892090f, 0.899414f, 0.906250f, 0.912598f, 0.916992f, 0.922363f, 0.928223f, 0.932617f, 0.937500f, 0.941895f,
+ 0.945801f, 0.949219f, 0.953613f, 0.957031f, 0.960449f, 0.963379f, 0.966797f, 0.969727f, 0.971680f, 0.974609f, 0.977539f, 0.979980f,
+ 0.981934f, 0.984375f, 0.986328f, 0.989258f, 0.991211f, 0.992676f, 0.996094f, 0.994629f, 0.993652f, 0.992188f, 0.990723f, 0.989746f,
+ 0.019577f, 0.061340f, 0.108337f, 0.156860f, 0.207153f, 0.258789f, 0.310059f, 0.358887f, 0.405762f, 0.450928f, 0.491211f, 0.530273f,
+ 0.565430f, 0.597656f, 0.627441f, 0.654297f, 0.680176f, 0.702637f, 0.724121f, 0.743164f, 0.760742f, 0.776855f, 0.791992f, 0.806152f,
+ 0.817871f, 0.830078f, 0.841797f, 0.852539f, 0.861816f, 0.870117f, 0.878906f, 0.886230f, 0.893066f, 0.900391f, 0.906738f, 0.912598f,
+ 0.918457f, 0.923340f, 0.928223f, 0.933594f, 0.938477f, 0.942871f, 0.946777f, 0.950684f, 0.954590f, 0.958496f, 0.960938f, 0.964844f,
+ 0.967773f, 0.970703f, 0.973633f, 0.976074f, 0.979004f, 0.981445f, 0.983398f, 0.985840f, 0.987793f, 0.990234f, 0.995117f, 0.993652f,
+ 0.992676f, 0.991699f, 0.990234f, 0.989258f, 0.014397f, 0.046295f, 0.081543f, 0.120728f, 0.162842f, 0.206177f, 0.250977f, 0.296143f,
+ 0.342041f, 0.385986f, 0.427979f, 0.468262f, 0.506348f, 0.542480f, 0.575195f, 0.605469f, 0.633789f, 0.660156f, 0.684570f, 0.706543f,
+ 0.727539f, 0.745117f, 0.763184f, 0.778809f, 0.793945f, 0.807617f, 0.820312f, 0.833008f, 0.842773f, 0.852539f, 0.862305f, 0.872070f,
+ 0.879395f, 0.887207f, 0.894531f, 0.900879f, 0.907227f, 0.914551f, 0.919922f, 0.925293f, 0.930176f, 0.935547f, 0.938965f, 0.943359f,
+ 0.948730f, 0.952637f, 0.956055f, 0.959473f, 0.962891f, 0.966309f, 0.969238f, 0.972656f, 0.975098f, 0.977539f, 0.980957f, 0.982910f,
+ 0.984863f, 0.987793f, 0.994141f, 0.993164f, 0.991699f, 0.990723f, 0.989746f, 0.988281f, 0.010925f, 0.035828f, 0.063660f, 0.094360f,
+ 0.128174f, 0.164551f, 0.203247f, 0.244385f, 0.285645f, 0.326416f, 0.367432f, 0.409424f, 0.447998f, 0.484131f, 0.520508f, 0.553711f,
+ 0.584473f, 0.614258f, 0.641113f, 0.666016f, 0.689453f, 0.710938f, 0.730469f, 0.750488f, 0.766602f, 0.781250f, 0.796387f, 0.809570f,
+ 0.822266f, 0.833496f, 0.844727f, 0.854980f, 0.864258f, 0.873047f, 0.881348f, 0.889648f, 0.895996f, 0.903809f, 0.910156f, 0.916504f,
+ 0.921387f, 0.926758f, 0.932129f, 0.937500f, 0.941895f, 0.946777f, 0.950684f, 0.954102f, 0.958008f, 0.960938f, 0.965332f, 0.968262f,
+ 0.971680f, 0.975098f, 0.977539f, 0.979492f, 0.982422f, 0.984863f, 0.992676f, 0.991699f, 0.990723f, 0.989746f, 0.988770f, 0.987793f,
+ 0.008698f, 0.028244f, 0.049866f, 0.074463f, 0.102295f, 0.132935f, 0.165161f, 0.200073f, 0.236206f, 0.275391f, 0.313477f, 0.352051f,
+ 0.391113f, 0.428955f, 0.465088f, 0.500977f, 0.534180f, 0.565430f, 0.593750f, 0.622559f, 0.648438f, 0.671875f, 0.694824f, 0.715820f,
+ 0.734863f, 0.753906f, 0.771484f, 0.784668f, 0.799805f, 0.813477f, 0.825195f, 0.836914f, 0.847656f, 0.857910f, 0.866699f, 0.875488f,
+ 0.884766f, 0.892090f, 0.898438f, 0.906250f, 0.913086f, 0.918457f, 0.923828f, 0.929688f, 0.935059f, 0.939941f, 0.944336f, 0.948730f,
+ 0.952637f, 0.956055f, 0.959961f, 0.963379f, 0.967285f, 0.970703f, 0.973633f, 0.976074f, 0.979492f, 0.982422f, 0.991211f, 0.990723f,
+ 0.990234f, 0.988770f, 0.987793f, 0.986328f, 0.007210f, 0.022797f, 0.040039f, 0.060181f, 0.082153f, 0.107300f, 0.134155f, 0.164673f,
+ 0.196167f, 0.229492f, 0.265381f, 0.301025f, 0.338379f, 0.374756f, 0.411133f, 0.446533f, 0.481201f, 0.515625f, 0.546387f, 0.576660f,
+ 0.605957f, 0.631348f, 0.656738f, 0.681152f, 0.702148f, 0.722168f, 0.741699f, 0.758789f, 0.775391f, 0.791016f, 0.803711f, 0.817383f,
+ 0.829102f, 0.840820f, 0.851562f, 0.860840f, 0.871094f, 0.879395f, 0.887695f, 0.895020f, 0.901855f, 0.909180f, 0.915527f, 0.921387f,
+ 0.927734f, 0.932129f, 0.937500f, 0.941895f, 0.947266f, 0.950684f, 0.955078f, 0.958984f, 0.962891f, 0.966797f, 0.969727f, 0.973145f,
+ 0.976562f, 0.979004f, 0.990234f, 0.989746f, 0.988770f, 0.987793f, 0.986816f, 0.985840f, 0.005863f, 0.018936f, 0.032898f, 0.049377f,
+ 0.067261f, 0.088257f, 0.110535f, 0.135254f, 0.162231f, 0.191895f, 0.223389f, 0.255371f, 0.290039f, 0.324707f, 0.359863f, 0.395996f,
+ 0.429932f, 0.464355f, 0.497314f, 0.529297f, 0.559570f, 0.587891f, 0.616699f, 0.642090f, 0.665527f, 0.688965f, 0.709961f, 0.729492f,
+ 0.747559f, 0.765625f, 0.780762f, 0.794922f, 0.809082f, 0.822754f, 0.833984f, 0.844727f, 0.855957f, 0.864746f, 0.875000f, 0.883789f,
+ 0.891113f, 0.898926f, 0.906250f, 0.912598f, 0.918457f, 0.925293f, 0.930664f, 0.935059f, 0.940918f, 0.945312f, 0.950195f, 0.954590f,
+ 0.958496f, 0.962402f, 0.965820f, 0.969238f, 0.972656f, 0.976074f, 0.988770f, 0.988770f, 0.987793f, 0.986816f, 0.985840f, 0.984863f,
+ 0.004925f, 0.015518f, 0.027451f, 0.041199f, 0.055786f, 0.072998f, 0.091492f, 0.112427f, 0.135254f, 0.160767f, 0.187500f, 0.216919f,
+ 0.247314f, 0.280273f, 0.313477f, 0.346680f, 0.381592f, 0.415283f, 0.448730f, 0.481201f, 0.513184f, 0.543945f, 0.573242f, 0.601562f,
+ 0.627441f, 0.652344f, 0.675293f, 0.697754f, 0.718262f, 0.737793f, 0.754883f, 0.771973f, 0.787109f, 0.800781f, 0.815430f, 0.828125f,
+ 0.839844f, 0.851074f, 0.860840f, 0.870117f, 0.879883f, 0.887695f, 0.896484f, 0.902832f, 0.911133f, 0.916992f, 0.922852f, 0.928711f,
+ 0.934082f, 0.939941f, 0.944336f, 0.948730f, 0.954102f, 0.958008f, 0.961426f, 0.965332f, 0.969238f, 0.972168f, 0.987305f, 0.987305f,
+ 0.986816f, 0.985840f, 0.984863f, 0.983887f, 0.004139f, 0.012955f, 0.022781f, 0.034088f, 0.046997f, 0.061005f, 0.076538f, 0.094360f,
+ 0.113464f, 0.134888f, 0.158203f, 0.183716f, 0.210693f, 0.239990f, 0.270264f, 0.302734f, 0.334961f, 0.367676f, 0.400635f, 0.434082f,
+ 0.467041f, 0.497803f, 0.528809f, 0.558105f, 0.586426f, 0.614258f, 0.638672f, 0.663574f, 0.686035f, 0.707520f, 0.728027f, 0.745605f,
+ 0.762695f, 0.779297f, 0.794434f, 0.808594f, 0.821777f, 0.834473f, 0.845215f, 0.855957f, 0.866699f, 0.876465f, 0.884766f, 0.892090f,
+ 0.900391f, 0.908203f, 0.915039f, 0.920898f, 0.927246f, 0.932617f, 0.937988f, 0.943848f, 0.948730f, 0.952637f, 0.957520f, 0.961426f,
+ 0.965820f, 0.968750f, 0.985840f, 0.985840f, 0.985840f, 0.984375f, 0.983887f, 0.982910f, 0.003492f, 0.011307f, 0.019608f, 0.028793f,
+ 0.039246f, 0.051544f, 0.064392f, 0.078796f, 0.095337f, 0.113953f, 0.134033f, 0.155396f, 0.179688f, 0.205200f, 0.232300f, 0.261475f,
+ 0.291748f, 0.323730f, 0.355225f, 0.387939f, 0.420410f, 0.452637f, 0.483887f, 0.514648f, 0.544922f, 0.573730f, 0.601074f, 0.626953f,
+ 0.651367f, 0.675293f, 0.697266f, 0.717285f, 0.736816f, 0.755371f, 0.771973f, 0.786621f, 0.803223f, 0.815430f, 0.828613f, 0.840820f,
+ 0.851562f, 0.863281f, 0.873047f, 0.880859f, 0.890625f, 0.898438f, 0.905762f, 0.913086f, 0.919434f, 0.925781f, 0.931641f, 0.937500f,
+ 0.942871f, 0.947754f, 0.952637f, 0.957520f, 0.960938f, 0.965820f, 0.984375f, 0.984863f, 0.984375f, 0.983398f, 0.982422f, 0.981445f,
+ 0.002977f, 0.009415f, 0.016708f, 0.024811f, 0.033356f, 0.043457f, 0.054535f, 0.067017f, 0.080322f, 0.096130f, 0.113708f, 0.132080f,
+ 0.152710f, 0.175415f, 0.199829f, 0.226440f, 0.253662f, 0.282959f, 0.313232f, 0.343750f, 0.375000f, 0.406982f, 0.439453f, 0.471191f,
+ 0.501465f, 0.531738f, 0.560547f, 0.587891f, 0.615234f, 0.640625f, 0.664062f, 0.687500f, 0.708496f, 0.728516f, 0.747559f, 0.765137f,
+ 0.781738f, 0.795898f, 0.811523f, 0.824707f, 0.836426f, 0.847656f, 0.858887f, 0.869141f, 0.878906f, 0.887695f, 0.895996f, 0.904297f,
+ 0.911133f, 0.917969f, 0.925293f, 0.931152f, 0.937012f, 0.942383f, 0.947266f, 0.953125f, 0.957031f, 0.961426f, 0.982910f, 0.983398f,
+ 0.982910f, 0.982422f, 0.981445f, 0.980957f, 0.002743f, 0.008568f, 0.014305f, 0.021378f, 0.028732f, 0.037201f, 0.046387f, 0.057068f,
+ 0.068848f, 0.082336f, 0.096924f, 0.113159f, 0.130859f, 0.150146f, 0.171509f, 0.194824f, 0.219482f, 0.246338f, 0.273926f, 0.302734f,
+ 0.333496f, 0.364502f, 0.395752f, 0.426758f, 0.458252f, 0.489990f, 0.519531f, 0.548340f, 0.576660f, 0.604004f, 0.630859f, 0.654297f,
+ 0.678223f, 0.700684f, 0.720215f, 0.740234f, 0.758301f, 0.775391f, 0.790527f, 0.805176f, 0.818848f, 0.833008f, 0.844238f, 0.855469f,
+ 0.866699f, 0.876953f, 0.886230f, 0.894043f, 0.902832f, 0.910645f, 0.917480f, 0.924316f, 0.930664f, 0.937012f, 0.941895f, 0.947266f,
+ 0.952148f, 0.957031f, 0.981445f, 0.982422f, 0.981445f, 0.980957f, 0.980469f, 0.979004f, 0.002504f, 0.007004f, 0.012634f, 0.018555f,
+ 0.024933f, 0.032654f, 0.040283f, 0.048920f, 0.059357f, 0.070007f, 0.082642f, 0.096741f, 0.112122f, 0.128906f, 0.147339f, 0.167603f,
+ 0.189697f, 0.213257f, 0.238770f, 0.265869f, 0.293701f, 0.323242f, 0.354004f, 0.384766f, 0.415283f, 0.447021f, 0.478516f, 0.507812f,
+ 0.536621f, 0.565918f, 0.593750f, 0.620605f, 0.645508f, 0.668945f, 0.692383f, 0.712891f, 0.733398f, 0.751465f, 0.769531f, 0.785156f,
+ 0.801270f, 0.814941f, 0.828125f, 0.841797f, 0.853516f, 0.864746f, 0.874512f, 0.883789f, 0.893555f, 0.900879f, 0.910156f, 0.917480f,
+ 0.923340f, 0.930664f, 0.936523f, 0.942383f, 0.947754f, 0.952637f, 0.979492f, 0.980469f, 0.980469f, 0.979492f, 0.978516f, 0.978027f,
+ 0.002039f, 0.006287f, 0.010864f, 0.016129f, 0.021637f, 0.027786f, 0.034485f, 0.042450f, 0.051331f, 0.060760f, 0.071594f, 0.082886f,
+ 0.096313f, 0.110840f, 0.126587f, 0.145020f, 0.164185f, 0.185181f, 0.207520f, 0.232300f, 0.258301f, 0.285889f, 0.314941f, 0.344238f,
+ 0.374268f, 0.405029f, 0.436035f, 0.466797f, 0.498291f, 0.527344f, 0.555664f, 0.583984f, 0.611328f, 0.636230f, 0.661133f, 0.684082f,
+ 0.705566f, 0.726562f, 0.745605f, 0.764648f, 0.781250f, 0.797852f, 0.812500f, 0.825195f, 0.838867f, 0.851074f, 0.862305f, 0.873535f,
+ 0.883301f, 0.892578f, 0.901367f, 0.908203f, 0.916992f, 0.923828f, 0.931152f, 0.937012f, 0.942383f, 0.947266f, 0.978027f, 0.978516f,
+ 0.979004f, 0.978027f, 0.977051f, 0.977051f, 0.001762f, 0.005489f, 0.009804f, 0.013931f, 0.019028f, 0.024445f, 0.030518f, 0.036865f,
+ 0.044189f, 0.052460f, 0.061432f, 0.071960f, 0.083008f, 0.095642f, 0.109558f, 0.124756f, 0.141602f, 0.160156f, 0.180664f, 0.202148f,
+ 0.225952f, 0.250977f, 0.278076f, 0.305664f, 0.334961f, 0.364990f, 0.394775f, 0.425537f, 0.456543f, 0.487061f, 0.517090f, 0.546387f,
+ 0.575195f, 0.602539f, 0.627930f, 0.653809f, 0.676758f, 0.699707f, 0.721191f, 0.740723f, 0.759766f, 0.777832f, 0.793945f, 0.809082f,
+ 0.823242f, 0.836426f, 0.849609f, 0.861328f, 0.872070f, 0.881836f, 0.892578f, 0.900391f, 0.908691f, 0.916992f, 0.924316f, 0.931152f,
+ 0.937500f, 0.943359f, 0.976074f, 0.977051f, 0.977051f, 0.976562f, 0.976074f, 0.975098f, 0.001675f, 0.005020f, 0.008400f, 0.012253f,
+ 0.016724f, 0.021469f, 0.026428f, 0.032104f, 0.039062f, 0.045563f, 0.053741f, 0.062103f, 0.072205f, 0.082947f, 0.094666f, 0.107727f,
+ 0.122681f, 0.139038f, 0.156250f, 0.176514f, 0.197388f, 0.220581f, 0.244629f, 0.270752f, 0.297607f, 0.326172f, 0.355957f, 0.386475f,
+ 0.416748f, 0.447754f, 0.478027f, 0.507812f, 0.538086f, 0.566406f, 0.594727f, 0.621582f, 0.647461f, 0.671387f, 0.694336f, 0.716797f,
+ 0.737305f, 0.755859f, 0.773438f, 0.791016f, 0.807129f, 0.820801f, 0.834961f, 0.848145f, 0.860352f, 0.871582f, 0.881836f, 0.891602f,
+ 0.901367f, 0.909180f, 0.917480f, 0.925293f, 0.932129f, 0.938965f, 0.974609f, 0.975586f, 0.976074f, 0.974609f, 0.974121f, 0.973633f,
+ 0.001437f, 0.004513f, 0.007427f, 0.010994f, 0.014526f, 0.018829f, 0.023331f, 0.028229f, 0.034058f, 0.040192f, 0.046844f, 0.054321f,
+ 0.062683f, 0.071716f, 0.082397f, 0.093933f, 0.106567f, 0.120728f, 0.136230f, 0.153320f, 0.172485f, 0.192627f, 0.214233f, 0.237915f,
+ 0.263672f, 0.290527f, 0.318115f, 0.347412f, 0.377197f, 0.408203f, 0.438477f, 0.469482f, 0.499512f, 0.529785f, 0.558594f, 0.586914f,
+ 0.614258f, 0.641602f, 0.665527f, 0.689941f, 0.711914f, 0.732422f, 0.752930f, 0.771484f, 0.789062f, 0.805664f, 0.819824f, 0.833984f,
+ 0.847656f, 0.860840f, 0.871094f, 0.881836f, 0.891602f, 0.902344f, 0.910156f, 0.918457f, 0.926270f, 0.932617f, 0.972168f, 0.973633f,
+ 0.973633f, 0.973145f, 0.973145f, 0.971680f, 0.001390f, 0.003952f, 0.006779f, 0.009941f, 0.013062f, 0.017029f, 0.020905f, 0.024994f,
+ 0.029877f, 0.035187f, 0.041077f, 0.047119f, 0.055145f, 0.062500f, 0.071594f, 0.081543f, 0.092712f, 0.104736f, 0.118530f, 0.133179f,
+ 0.150024f, 0.168091f, 0.187378f, 0.209717f, 0.232178f, 0.256836f, 0.283447f, 0.311279f, 0.339844f, 0.369873f, 0.399658f, 0.429932f,
+ 0.461426f, 0.492188f, 0.521973f, 0.551758f, 0.580566f, 0.608887f, 0.635254f, 0.660645f, 0.685059f, 0.708008f, 0.729492f, 0.750488f,
+ 0.769043f, 0.786621f, 0.802734f, 0.818848f, 0.832520f, 0.846680f, 0.860352f, 0.871582f, 0.882324f, 0.892578f, 0.902832f, 0.911133f,
+ 0.919922f, 0.926758f, 0.970703f, 0.971680f, 0.971680f, 0.971680f, 0.971680f, 0.969238f, 0.001328f, 0.003641f, 0.006138f, 0.008690f,
+ 0.011444f, 0.014786f, 0.018311f, 0.022125f, 0.026337f, 0.031403f, 0.036011f, 0.041809f, 0.047943f, 0.054901f, 0.062622f, 0.071106f,
+ 0.081299f, 0.091614f, 0.103455f, 0.116333f, 0.130493f, 0.146484f, 0.164307f, 0.183228f, 0.204224f, 0.226685f, 0.251221f, 0.277100f,
+ 0.303711f, 0.332764f, 0.361572f, 0.391846f, 0.422852f, 0.454102f, 0.485352f, 0.515625f, 0.545410f, 0.574707f, 0.603027f, 0.630371f,
+ 0.656250f, 0.681641f, 0.705078f, 0.726562f, 0.747070f, 0.767578f, 0.784668f, 0.803223f, 0.818848f, 0.833008f, 0.847656f, 0.860352f,
+ 0.872559f, 0.883301f, 0.894043f, 0.903809f, 0.913574f, 0.921387f, 0.967773f, 0.970215f, 0.970215f, 0.968750f, 0.969238f, 0.968750f,
+ 0.001053f, 0.002905f, 0.005432f, 0.007912f, 0.010658f, 0.012901f, 0.016464f, 0.019363f, 0.023376f, 0.027237f, 0.031799f, 0.036346f,
+ 0.042145f, 0.048248f, 0.054871f, 0.062256f, 0.070618f, 0.079834f, 0.089844f, 0.101440f, 0.113831f, 0.128174f, 0.143433f, 0.160156f,
+ 0.179077f, 0.199707f, 0.222046f, 0.245483f, 0.271240f, 0.297363f, 0.325684f, 0.355469f, 0.385254f, 0.416016f, 0.447754f, 0.479004f,
+ 0.508789f, 0.539551f, 0.570312f, 0.598145f, 0.626465f, 0.652344f, 0.678223f, 0.702148f, 0.725098f, 0.746094f, 0.765625f, 0.785645f,
+ 0.803223f, 0.819336f, 0.834961f, 0.848145f, 0.861328f, 0.873535f, 0.884766f, 0.895508f, 0.905762f, 0.915527f, 0.965332f, 0.967773f,
+ 0.968262f, 0.967773f, 0.967285f, 0.966309f, 0.001106f, 0.002684f, 0.004913f, 0.006733f, 0.009300f, 0.011955f, 0.014435f, 0.017700f,
+ 0.020477f, 0.024124f, 0.028091f, 0.032532f, 0.037231f, 0.042511f, 0.048309f, 0.054596f, 0.061798f, 0.069885f, 0.078857f, 0.089050f,
+ 0.099915f, 0.112183f, 0.125488f, 0.140503f, 0.157104f, 0.175293f, 0.195068f, 0.216309f, 0.240356f, 0.265381f, 0.291748f, 0.319580f,
+ 0.348633f, 0.379150f, 0.410156f, 0.441406f, 0.472900f, 0.503418f, 0.534668f, 0.565430f, 0.594727f, 0.622070f, 0.649902f, 0.676270f,
+ 0.700195f, 0.723633f, 0.746094f, 0.766602f, 0.786133f, 0.802734f, 0.819824f, 0.835449f, 0.849609f, 0.863281f, 0.875977f, 0.887695f,
+ 0.898438f, 0.908203f, 0.962891f, 0.965820f, 0.966309f, 0.965332f, 0.964844f, 0.964355f, 0.000782f, 0.002707f, 0.004574f, 0.006184f,
+ 0.008286f, 0.010681f, 0.012878f, 0.015640f, 0.018478f, 0.021912f, 0.025208f, 0.028976f, 0.032867f, 0.037598f, 0.042938f, 0.048370f,
+ 0.054443f, 0.061432f, 0.069214f, 0.077515f, 0.087402f, 0.098145f, 0.109497f, 0.122803f, 0.137329f, 0.153564f, 0.171509f, 0.190918f,
+ 0.212158f, 0.235352f, 0.259766f, 0.286133f, 0.314209f, 0.343262f, 0.373535f, 0.404297f, 0.436279f, 0.467773f, 0.499512f, 0.530273f,
+ 0.561523f, 0.590820f, 0.620117f, 0.647461f, 0.674316f, 0.699219f, 0.722656f, 0.745605f, 0.766602f, 0.785645f, 0.804688f, 0.821777f,
+ 0.836426f, 0.852051f, 0.865234f, 0.878418f, 0.890625f, 0.901855f, 0.959961f, 0.962891f, 0.963867f, 0.963379f, 0.962402f, 0.962402f,
+ 0.000787f, 0.002195f, 0.004250f, 0.005775f, 0.007774f, 0.009445f, 0.011795f, 0.013725f, 0.016678f, 0.019531f, 0.022018f, 0.025665f,
+ 0.029495f, 0.033142f, 0.037598f, 0.042664f, 0.048248f, 0.053772f, 0.060699f, 0.067993f, 0.076416f, 0.085815f, 0.095764f, 0.107422f,
+ 0.120239f, 0.134277f, 0.150269f, 0.167358f, 0.186646f, 0.207764f, 0.230347f, 0.255127f, 0.281250f, 0.308838f, 0.337891f, 0.368408f,
+ 0.399414f, 0.431396f, 0.463135f, 0.495605f, 0.526855f, 0.558594f, 0.588379f, 0.618652f, 0.646973f, 0.673828f, 0.699707f, 0.723633f,
+ 0.746094f, 0.767090f, 0.788086f, 0.806641f, 0.823730f, 0.840332f, 0.854980f, 0.869141f, 0.881836f, 0.893555f, 0.957520f, 0.960938f,
+ 0.960938f, 0.961426f, 0.960449f, 0.959961f, 0.000765f, 0.002207f, 0.003666f, 0.005177f, 0.006973f, 0.008301f, 0.010704f, 0.012794f,
+ 0.015015f, 0.017303f, 0.020309f, 0.022568f, 0.026123f, 0.029587f, 0.033325f, 0.037659f, 0.042206f, 0.047516f, 0.053223f, 0.059814f,
+ 0.067017f, 0.075195f, 0.083801f, 0.094055f, 0.105042f, 0.117737f, 0.131470f, 0.146851f, 0.163940f, 0.182739f, 0.203369f, 0.225952f,
+ 0.250244f, 0.276367f, 0.304199f, 0.333008f, 0.364258f, 0.395264f, 0.427002f, 0.459961f, 0.491699f, 0.524414f, 0.555664f, 0.586914f,
+ 0.617676f, 0.645996f, 0.673340f, 0.699707f, 0.724121f, 0.748047f, 0.770020f, 0.790039f, 0.809082f, 0.827148f, 0.842773f, 0.858398f,
+ 0.873047f, 0.885742f, 0.954102f, 0.958008f, 0.958496f, 0.958496f, 0.958496f, 0.957520f, 0.000586f, 0.001937f, 0.003107f, 0.004745f,
+ 0.006168f, 0.007610f, 0.009590f, 0.011345f, 0.013321f, 0.015587f, 0.017593f, 0.020294f, 0.023346f, 0.026154f, 0.029205f, 0.033234f,
+ 0.037415f, 0.041962f, 0.046906f, 0.052673f, 0.058533f, 0.065796f, 0.073669f, 0.082642f, 0.092346f, 0.103027f, 0.115234f, 0.128784f,
+ 0.143799f, 0.160889f, 0.179199f, 0.199585f, 0.221802f, 0.246094f, 0.271973f, 0.299805f, 0.329102f, 0.359863f, 0.391357f, 0.423340f,
+ 0.456299f, 0.490234f, 0.522949f, 0.555176f, 0.586426f, 0.617188f, 0.645996f, 0.675293f, 0.701660f, 0.726074f, 0.750488f, 0.773926f,
+ 0.793945f, 0.812988f, 0.831543f, 0.847656f, 0.862793f, 0.877441f, 0.951660f, 0.955078f, 0.955566f, 0.955566f, 0.955078f, 0.954590f,
+ 0.000678f, 0.001864f, 0.003138f, 0.004333f, 0.005707f, 0.006893f, 0.008224f, 0.009850f, 0.012215f, 0.013954f, 0.015747f, 0.018219f,
+ 0.020584f, 0.023148f, 0.026047f, 0.029434f, 0.033020f, 0.037018f, 0.041626f, 0.046509f, 0.051910f, 0.058105f, 0.064636f, 0.072510f,
+ 0.080750f, 0.090149f, 0.100891f, 0.112549f, 0.126343f, 0.141113f, 0.157593f, 0.175537f, 0.195801f, 0.218018f, 0.242554f, 0.268311f,
+ 0.295898f, 0.325195f, 0.355713f, 0.388184f, 0.421143f, 0.454834f, 0.488281f, 0.522949f, 0.554199f, 0.587402f, 0.618164f, 0.648438f,
+ 0.676758f, 0.704102f, 0.730957f, 0.754395f, 0.776855f, 0.798340f, 0.817871f, 0.836426f, 0.852051f, 0.868164f, 0.948242f, 0.952637f,
+ 0.953125f, 0.952637f, 0.952148f, 0.951660f, 0.000470f, 0.001578f, 0.002934f, 0.003838f, 0.005032f, 0.006310f, 0.007725f, 0.008972f,
+ 0.010826f, 0.012657f, 0.014359f, 0.015991f, 0.018402f, 0.020721f, 0.023102f, 0.026230f, 0.029495f, 0.032867f, 0.036743f, 0.040680f,
+ 0.045654f, 0.050812f, 0.056763f, 0.063477f, 0.071045f, 0.078918f, 0.088440f, 0.098938f, 0.110657f, 0.123535f, 0.138062f, 0.154175f,
+ 0.172363f, 0.192627f, 0.214478f, 0.238770f, 0.264404f, 0.292236f, 0.322266f, 0.353271f, 0.385742f, 0.419189f, 0.453857f, 0.487549f,
+ 0.521484f, 0.555664f, 0.588867f, 0.621094f, 0.651367f, 0.680176f, 0.708008f, 0.733887f, 0.759766f, 0.780762f, 0.802734f, 0.821289f,
+ 0.840820f, 0.858398f, 0.943848f, 0.949219f, 0.949707f, 0.949707f, 0.949707f, 0.949219f, 0.000485f, 0.001689f, 0.002386f, 0.003698f,
+ 0.004547f, 0.005936f, 0.006851f, 0.008217f, 0.009834f, 0.011055f, 0.012810f, 0.014473f, 0.016449f, 0.018509f, 0.020950f, 0.023209f,
+ 0.025940f, 0.029114f, 0.032410f, 0.036133f, 0.040161f, 0.044861f, 0.050018f, 0.055664f, 0.061859f, 0.069153f, 0.077515f, 0.086365f,
+ 0.096680f, 0.108093f, 0.120605f, 0.135132f, 0.151489f, 0.169556f, 0.189209f, 0.211426f, 0.235352f, 0.261475f, 0.289307f, 0.319580f,
+ 0.351074f, 0.384521f, 0.418701f, 0.452881f, 0.487549f, 0.522461f, 0.556641f, 0.591309f, 0.623535f, 0.653809f, 0.684570f, 0.712891f,
+ 0.739258f, 0.764160f, 0.787109f, 0.809570f, 0.829102f, 0.847168f, 0.940918f, 0.945801f, 0.946289f, 0.946777f, 0.946777f, 0.945312f,
+ 0.000620f, 0.001351f, 0.002413f, 0.003273f, 0.004307f, 0.004971f, 0.006138f, 0.007542f, 0.008835f, 0.009972f, 0.011581f, 0.013069f,
+ 0.014717f, 0.016495f, 0.018738f, 0.020691f, 0.023315f, 0.025879f, 0.028793f, 0.031860f, 0.035309f, 0.039246f, 0.043762f, 0.048950f,
+ 0.054474f, 0.060669f, 0.067932f, 0.075378f, 0.084351f, 0.094055f, 0.105774f, 0.118469f, 0.132690f, 0.148315f, 0.166504f, 0.186401f,
+ 0.208130f, 0.232544f, 0.258789f, 0.287109f, 0.317627f, 0.349854f, 0.383057f, 0.417725f, 0.453125f, 0.488770f, 0.523926f, 0.559082f,
+ 0.594238f, 0.627441f, 0.659180f, 0.689941f, 0.719238f, 0.745117f, 0.770508f, 0.794434f, 0.815430f, 0.836914f, 0.936523f, 0.941895f,
+ 0.942871f, 0.942871f, 0.942871f, 0.942383f, 0.000404f, 0.001095f, 0.002087f, 0.002983f, 0.003986f, 0.004673f, 0.005844f, 0.006878f,
+ 0.007740f, 0.008873f, 0.010323f, 0.011757f, 0.013176f, 0.014915f, 0.016586f, 0.018585f, 0.020523f, 0.022720f, 0.025391f, 0.028244f,
+ 0.031219f, 0.034821f, 0.038788f, 0.042908f, 0.047943f, 0.053040f, 0.058960f, 0.066162f, 0.073547f, 0.082397f, 0.092285f, 0.102844f,
+ 0.115234f, 0.129883f, 0.146118f, 0.163452f, 0.183350f, 0.205688f, 0.229614f, 0.256592f, 0.285156f, 0.316162f, 0.348633f, 0.383057f,
+ 0.418457f, 0.454590f, 0.490967f, 0.526855f, 0.563477f, 0.598633f, 0.632812f, 0.665527f, 0.696777f, 0.726074f, 0.752930f, 0.779297f,
+ 0.803223f, 0.825684f, 0.933105f, 0.938477f, 0.938477f, 0.938965f, 0.938477f, 0.938477f, 0.000415f, 0.000864f, 0.001907f, 0.002775f,
+ 0.003519f, 0.004204f, 0.005352f, 0.006237f, 0.007019f, 0.008064f, 0.009239f, 0.010483f, 0.011742f, 0.013130f, 0.014877f, 0.016571f,
+ 0.018494f, 0.020126f, 0.022537f, 0.024826f, 0.027649f, 0.030701f, 0.033875f, 0.037964f, 0.042114f, 0.046356f, 0.051605f, 0.057587f,
+ 0.064209f, 0.071777f, 0.080261f, 0.089722f, 0.100952f, 0.113220f, 0.127075f, 0.143066f, 0.160767f, 0.180664f, 0.202759f, 0.227417f,
+ 0.254395f, 0.284180f, 0.315674f, 0.348633f, 0.383789f, 0.420166f, 0.457275f, 0.494385f, 0.531250f, 0.569336f, 0.605469f, 0.639160f,
+ 0.672363f, 0.705078f, 0.735352f, 0.762207f, 0.788574f, 0.811523f, 0.928711f, 0.934082f, 0.934570f, 0.935059f, 0.935059f, 0.935059f,
+ 0.000236f, 0.001136f, 0.001664f, 0.002502f, 0.003187f, 0.004082f, 0.004631f, 0.005386f, 0.006275f, 0.007385f, 0.008217f, 0.009453f,
+ 0.010567f, 0.011787f, 0.013115f, 0.014420f, 0.016083f, 0.017944f, 0.019867f, 0.022079f, 0.024414f, 0.026962f, 0.029755f, 0.033112f,
+ 0.036926f, 0.040771f, 0.045258f, 0.050232f, 0.056183f, 0.062500f, 0.069946f, 0.078430f, 0.087708f, 0.098389f, 0.110779f, 0.124634f,
+ 0.140259f, 0.158203f, 0.178223f, 0.200928f, 0.225708f, 0.253174f, 0.282715f, 0.315430f, 0.349365f, 0.385254f, 0.422363f, 0.460938f,
+ 0.499023f, 0.537109f, 0.574707f, 0.612305f, 0.646484f, 0.682129f, 0.713867f, 0.745117f, 0.772461f, 0.799316f, 0.923828f, 0.930176f,
+ 0.930664f, 0.931152f, 0.930664f, 0.930664f, 0.000229f, 0.000964f, 0.001582f, 0.002182f, 0.002838f, 0.003653f, 0.004341f, 0.004921f,
+ 0.005615f, 0.006626f, 0.007423f, 0.008545f, 0.009483f, 0.010666f, 0.011612f, 0.013000f, 0.014275f, 0.015900f, 0.017487f, 0.019333f,
+ 0.021484f, 0.023773f, 0.026276f, 0.028992f, 0.032135f, 0.035492f, 0.039398f, 0.044037f, 0.049072f, 0.054443f, 0.061035f, 0.067871f,
+ 0.076111f, 0.085632f, 0.096252f, 0.108154f, 0.122253f, 0.138306f, 0.156006f, 0.175903f, 0.199219f, 0.224243f, 0.251953f, 0.282715f,
+ 0.315918f, 0.350830f, 0.387451f, 0.425781f, 0.465332f, 0.504395f, 0.544434f, 0.583008f, 0.620117f, 0.657715f, 0.692383f, 0.725098f,
+ 0.755371f, 0.783691f, 0.919434f, 0.925781f, 0.926270f, 0.926758f, 0.926758f, 0.925781f, 0.000410f, 0.000856f, 0.001542f, 0.001844f,
+ 0.002565f, 0.003380f, 0.003971f, 0.004246f, 0.005047f, 0.005863f, 0.006653f, 0.007744f, 0.008568f, 0.009407f, 0.010529f, 0.011482f,
+ 0.012657f, 0.013924f, 0.015602f, 0.017105f, 0.018997f, 0.020859f, 0.022980f, 0.025192f, 0.028030f, 0.031036f, 0.034515f, 0.038300f,
+ 0.042236f, 0.047180f, 0.052795f, 0.059113f, 0.065857f, 0.074097f, 0.083374f, 0.094360f, 0.105896f, 0.119873f, 0.135620f, 0.154175f,
+ 0.174072f, 0.197632f, 0.223267f, 0.251465f, 0.283447f, 0.317139f, 0.353760f, 0.391113f, 0.431152f, 0.470703f, 0.512207f, 0.552734f,
+ 0.592285f, 0.631348f, 0.669434f, 0.704590f, 0.737793f, 0.768555f, 0.913574f, 0.919922f, 0.920898f, 0.920898f, 0.921387f, 0.921387f,
+ 0.000214f, 0.000619f, 0.001172f, 0.001941f, 0.002228f, 0.002960f, 0.003490f, 0.003994f, 0.004761f, 0.005180f, 0.005806f, 0.006622f,
+ 0.007565f, 0.008301f, 0.009262f, 0.010170f, 0.011208f, 0.012482f, 0.013855f, 0.015060f, 0.016739f, 0.018311f, 0.020248f, 0.022034f,
+ 0.024597f, 0.027084f, 0.030045f, 0.033051f, 0.036743f, 0.041016f, 0.045807f, 0.050964f, 0.056946f, 0.063904f, 0.071899f, 0.080994f,
+ 0.091675f, 0.103699f, 0.117920f, 0.133667f, 0.151978f, 0.172729f, 0.196533f, 0.222534f, 0.252197f, 0.284424f, 0.319580f, 0.356689f,
+ 0.396973f, 0.437500f, 0.479492f, 0.521484f, 0.562500f, 0.604004f, 0.644043f, 0.682129f, 0.718262f, 0.751465f, 0.907715f, 0.915039f,
+ 0.916016f, 0.916504f, 0.916504f, 0.916504f, 0.000405f, 0.000760f, 0.001116f, 0.001688f, 0.002180f, 0.002670f, 0.003313f, 0.003569f,
+ 0.003979f, 0.004543f, 0.005466f, 0.005985f, 0.006699f, 0.007359f, 0.008102f, 0.009094f, 0.009949f, 0.011055f, 0.012047f, 0.013412f,
+ 0.014488f, 0.016068f, 0.017532f, 0.019348f, 0.021210f, 0.023834f, 0.025986f, 0.028854f, 0.031891f, 0.035339f, 0.039490f, 0.043976f,
+ 0.049347f, 0.055084f, 0.061951f, 0.069763f, 0.078918f, 0.089478f, 0.101379f, 0.115479f, 0.131592f, 0.150024f, 0.171387f, 0.195068f,
+ 0.222900f, 0.252686f, 0.286621f, 0.323242f, 0.362061f, 0.402588f, 0.445312f, 0.488770f, 0.532715f, 0.575684f, 0.618652f, 0.659180f,
+ 0.698242f, 0.734375f, 0.901367f, 0.909180f, 0.911133f, 0.910645f, 0.911133f, 0.910645f, 0.000218f, 0.000539f, 0.001187f, 0.001617f,
+ 0.001987f, 0.002316f, 0.002666f, 0.003176f, 0.003841f, 0.004425f, 0.004917f, 0.005402f, 0.005768f, 0.006462f, 0.007233f, 0.008018f,
+ 0.008575f, 0.009758f, 0.010582f, 0.011520f, 0.012756f, 0.013832f, 0.015312f, 0.016968f, 0.018509f, 0.020279f, 0.022644f, 0.024857f,
+ 0.027740f, 0.030472f, 0.033783f, 0.037567f, 0.042175f, 0.047150f, 0.052979f, 0.059601f, 0.067505f, 0.076538f, 0.087158f, 0.099243f,
+ 0.113281f, 0.129272f, 0.148315f, 0.170532f, 0.194702f, 0.223267f, 0.254639f, 0.289795f, 0.327393f, 0.368408f, 0.410889f, 0.455322f,
+ 0.499756f, 0.544434f, 0.590332f, 0.633789f, 0.676270f, 0.716309f, 0.895508f, 0.902344f, 0.903809f, 0.905762f, 0.903809f, 0.904297f,
+ 0.000184f, 0.000612f, 0.001122f, 0.001464f, 0.001848f, 0.002150f, 0.002514f, 0.002651f, 0.003391f, 0.003666f, 0.004368f, 0.004677f,
+ 0.005219f, 0.005882f, 0.006531f, 0.007019f, 0.007675f, 0.008530f, 0.009224f, 0.010269f, 0.011017f, 0.012146f, 0.013321f, 0.014626f,
+ 0.016098f, 0.017639f, 0.019440f, 0.021317f, 0.023773f, 0.026123f, 0.029144f, 0.032410f, 0.036072f, 0.040314f, 0.045013f, 0.051086f,
+ 0.057587f, 0.065308f, 0.074402f, 0.084961f, 0.097107f, 0.111267f, 0.127930f, 0.147217f, 0.169556f, 0.195312f, 0.224365f, 0.257568f,
+ 0.294189f, 0.333496f, 0.375977f, 0.420166f, 0.467041f, 0.514160f, 0.561035f, 0.607422f, 0.652344f, 0.695312f, 0.888672f, 0.896484f,
+ 0.897461f, 0.897461f, 0.897949f, 0.897949f, 0.000159f, 0.000537f, 0.000830f, 0.001206f, 0.001578f, 0.001760f, 0.002050f, 0.002504f,
+ 0.002951f, 0.003397f, 0.003674f, 0.004238f, 0.004520f, 0.005245f, 0.005692f, 0.006138f, 0.006748f, 0.007240f, 0.008087f, 0.008728f,
+ 0.009636f, 0.010437f, 0.011543f, 0.012611f, 0.013763f, 0.015266f, 0.016617f, 0.018433f, 0.020248f, 0.022354f, 0.024887f, 0.027390f,
+ 0.030716f, 0.034454f, 0.038422f, 0.043365f, 0.048950f, 0.055511f, 0.062988f, 0.072021f, 0.082336f, 0.094727f, 0.109375f, 0.125977f,
+ 0.145874f, 0.169556f, 0.195679f, 0.226929f, 0.260986f, 0.299805f, 0.341309f, 0.385498f, 0.432129f, 0.480957f, 0.529297f, 0.579102f,
+ 0.627441f, 0.673828f, 0.881348f, 0.889160f, 0.890625f, 0.891113f, 0.891602f, 0.891113f, 0.000204f, 0.000566f, 0.000741f, 0.001033f,
+ 0.001378f, 0.001599f, 0.001961f, 0.002354f, 0.002609f, 0.002974f, 0.003300f, 0.003609f, 0.004101f, 0.004463f, 0.004906f, 0.005337f,
+ 0.006020f, 0.006290f, 0.007023f, 0.007656f, 0.008301f, 0.009140f, 0.009918f, 0.010933f, 0.011940f, 0.013107f, 0.014252f, 0.015656f,
+ 0.017136f, 0.019058f, 0.021057f, 0.023209f, 0.025940f, 0.029190f, 0.032715f, 0.036591f, 0.041138f, 0.046661f, 0.053253f, 0.060944f,
+ 0.069702f, 0.080444f, 0.092651f, 0.107788f, 0.124695f, 0.145630f, 0.169189f, 0.197632f, 0.229736f, 0.266113f, 0.306396f, 0.350586f,
+ 0.397217f, 0.447021f, 0.497803f, 0.549805f, 0.600586f, 0.650391f, 0.872559f, 0.881836f, 0.882812f, 0.883301f, 0.884277f, 0.884277f,
+ 0.000240f, 0.000349f, 0.000795f, 0.000892f, 0.001151f, 0.001377f, 0.001773f, 0.001984f, 0.002415f, 0.002602f, 0.002932f, 0.003168f,
+ 0.003483f, 0.003906f, 0.004257f, 0.004681f, 0.005173f, 0.005596f, 0.006119f, 0.006550f, 0.007126f, 0.007759f, 0.008522f, 0.009270f,
+ 0.010086f, 0.011108f, 0.012138f, 0.013199f, 0.014549f, 0.015884f, 0.017776f, 0.019623f, 0.022003f, 0.024384f, 0.027237f, 0.030624f,
+ 0.034515f, 0.039215f, 0.044342f, 0.050873f, 0.058411f, 0.067017f, 0.078003f, 0.090332f, 0.105530f, 0.123718f, 0.144775f, 0.170410f,
+ 0.200195f, 0.234131f, 0.272461f, 0.315674f, 0.362305f, 0.412354f, 0.465332f, 0.518555f, 0.572754f, 0.626465f, 0.863770f, 0.873047f,
+ 0.875488f, 0.875488f, 0.875977f, 0.875977f, 0.000102f, 0.000298f, 0.000604f, 0.000950f, 0.001089f, 0.001472f, 0.001760f, 0.001823f,
+ 0.001903f, 0.002325f, 0.002611f, 0.002775f, 0.003185f, 0.003405f, 0.003674f, 0.004005f, 0.004406f, 0.004814f, 0.005203f, 0.005665f,
+ 0.006062f, 0.006702f, 0.007317f, 0.007881f, 0.008560f, 0.009239f, 0.010193f, 0.010994f, 0.012161f, 0.013588f, 0.015068f, 0.016479f,
+ 0.018250f, 0.020386f, 0.022781f, 0.025665f, 0.028809f, 0.032501f, 0.037048f, 0.042297f, 0.048553f, 0.055908f, 0.065491f, 0.075378f,
+ 0.088501f, 0.104248f, 0.122742f, 0.145874f, 0.171997f, 0.203247f, 0.239990f, 0.281250f, 0.326904f, 0.376953f, 0.430176f, 0.486328f,
+ 0.542480f, 0.600586f, 0.855469f, 0.864746f, 0.866211f, 0.867188f, 0.867188f, 0.867188f, 0.000000f, 0.000357f, 0.000576f, 0.000692f,
+ 0.001013f, 0.001069f, 0.001383f, 0.001702f, 0.001789f, 0.002102f, 0.002182f, 0.002377f, 0.002686f, 0.002985f, 0.003347f, 0.003359f,
+ 0.003782f, 0.004036f, 0.004436f, 0.004749f, 0.005169f, 0.005672f, 0.006145f, 0.006649f, 0.007187f, 0.007828f, 0.008644f, 0.009529f,
+ 0.010269f, 0.011200f, 0.012337f, 0.013596f, 0.015038f, 0.017044f, 0.018784f, 0.021011f, 0.023727f, 0.026871f, 0.030457f, 0.034637f,
+ 0.039978f, 0.046478f, 0.053436f, 0.062622f, 0.073730f, 0.086792f, 0.102661f, 0.122437f, 0.146240f, 0.174561f, 0.208252f, 0.247437f,
+ 0.291748f, 0.341064f, 0.395020f, 0.451904f, 0.511230f, 0.571777f, 0.844238f, 0.854980f, 0.857422f, 0.858887f, 0.857910f, 0.857910f,
+ 0.000101f, 0.000326f, 0.000535f, 0.000683f, 0.000848f, 0.001161f, 0.001184f, 0.001284f, 0.001576f, 0.001701f, 0.001839f, 0.002167f,
+ 0.002321f, 0.002584f, 0.002645f, 0.002941f, 0.003141f, 0.003538f, 0.003817f, 0.004112f, 0.004395f, 0.004646f, 0.005165f, 0.005531f,
+ 0.006096f, 0.006496f, 0.007217f, 0.007767f, 0.008629f, 0.009163f, 0.010239f, 0.011276f, 0.012611f, 0.013779f, 0.015213f, 0.017120f,
+ 0.019379f, 0.021606f, 0.024994f, 0.028351f, 0.032379f, 0.037201f, 0.043640f, 0.050903f, 0.060120f, 0.071045f, 0.084900f, 0.101868f,
+ 0.122559f, 0.147827f, 0.178223f, 0.214722f, 0.257080f, 0.305664f, 0.358887f, 0.416992f, 0.478027f, 0.542969f, 0.834473f, 0.845215f,
+ 0.847656f, 0.847656f, 0.847656f, 0.848633f, 0.000092f, 0.000316f, 0.000410f, 0.000556f, 0.000808f, 0.000918f, 0.001094f, 0.001287f,
+ 0.001309f, 0.001411f, 0.001671f, 0.001780f, 0.001909f, 0.002092f, 0.002274f, 0.002523f, 0.002733f, 0.002974f, 0.003101f, 0.003401f,
+ 0.003677f, 0.003956f, 0.004311f, 0.004551f, 0.004940f, 0.005444f, 0.005768f, 0.006451f, 0.006977f, 0.007568f, 0.008270f, 0.009201f,
+ 0.010170f, 0.011230f, 0.012566f, 0.013939f, 0.015503f, 0.017761f, 0.020111f, 0.022873f, 0.025940f, 0.029938f, 0.035217f, 0.040985f,
+ 0.048431f, 0.057770f, 0.069092f, 0.083618f, 0.100891f, 0.123047f, 0.150146f, 0.183838f, 0.223633f, 0.269531f, 0.322510f, 0.381348f,
+ 0.444824f, 0.511719f, 0.823730f, 0.834473f, 0.835938f, 0.836914f, 0.836914f, 0.837402f, 0.000240f, 0.000273f, 0.000326f, 0.000564f,
+ 0.000682f, 0.000807f, 0.000854f, 0.000949f, 0.001139f, 0.001238f, 0.001404f, 0.001548f, 0.001637f, 0.001840f, 0.001893f, 0.002077f,
+ 0.002321f, 0.002434f, 0.002642f, 0.002821f, 0.003044f, 0.003271f, 0.003649f, 0.003763f, 0.004208f, 0.004448f, 0.004986f, 0.005169f,
+ 0.005657f, 0.006279f, 0.006680f, 0.007442f, 0.008194f, 0.008881f, 0.009895f, 0.010918f, 0.012138f, 0.013924f, 0.015915f, 0.018112f,
+ 0.020645f, 0.023743f, 0.027817f, 0.032745f, 0.038361f, 0.045990f, 0.055481f, 0.066895f, 0.082031f, 0.100769f, 0.124573f, 0.154541f,
+ 0.190796f, 0.235107f, 0.286133f, 0.344238f, 0.408936f, 0.478271f, 0.810547f, 0.822266f, 0.824707f, 0.825195f, 0.825684f, 0.825684f,
+ 0.000115f, 0.000222f, 0.000252f, 0.000524f, 0.000574f, 0.000673f, 0.000869f, 0.000928f, 0.000963f, 0.001022f, 0.001246f, 0.001292f,
+ 0.001404f, 0.001477f, 0.001652f, 0.001811f, 0.001822f, 0.002058f, 0.002237f, 0.002371f, 0.002588f, 0.002645f, 0.003019f, 0.003080f,
+ 0.003506f, 0.003689f, 0.003904f, 0.004383f, 0.004707f, 0.005020f, 0.005386f, 0.006023f, 0.006451f, 0.007038f, 0.007809f, 0.008911f,
+ 0.009949f, 0.011200f, 0.012222f, 0.014137f, 0.016068f, 0.018692f, 0.021683f, 0.025314f, 0.029861f, 0.035889f, 0.043335f, 0.052582f,
+ 0.065186f, 0.080627f, 0.101501f, 0.127441f, 0.159912f, 0.200806f, 0.250000f, 0.307129f, 0.371582f, 0.444580f, 0.798340f, 0.809570f,
+ 0.811523f, 0.812988f, 0.812988f, 0.812988f, 0.000000f, 0.000211f, 0.000204f, 0.000474f, 0.000555f, 0.000583f, 0.000600f, 0.000593f,
+ 0.000812f, 0.000865f, 0.000941f, 0.001013f, 0.001162f, 0.001348f, 0.001418f, 0.001465f, 0.001616f, 0.001722f, 0.001856f, 0.001888f,
+ 0.002048f, 0.002321f, 0.002396f, 0.002632f, 0.002821f, 0.002974f, 0.003265f, 0.003477f, 0.003632f, 0.004051f, 0.004299f, 0.004700f,
+ 0.005238f, 0.005592f, 0.006199f, 0.006756f, 0.007614f, 0.008324f, 0.009727f, 0.010811f, 0.012337f, 0.014168f, 0.016434f, 0.019257f,
+ 0.022858f, 0.027451f, 0.033295f, 0.040619f, 0.050690f, 0.063416f, 0.080261f, 0.102295f, 0.131104f, 0.168335f, 0.214355f, 0.270508f,
+ 0.334717f, 0.408936f, 0.783691f, 0.795898f, 0.798340f, 0.799316f, 0.800293f, 0.800293f, 0.000174f, 0.000090f, 0.000281f, 0.000397f,
+ 0.000401f, 0.000450f, 0.000488f, 0.000640f, 0.000674f, 0.000713f, 0.000753f, 0.000845f, 0.000872f, 0.001020f, 0.001115f, 0.001264f,
+ 0.001327f, 0.001373f, 0.001520f, 0.001616f, 0.001767f, 0.001875f, 0.001968f, 0.002090f, 0.002232f, 0.002333f, 0.002472f, 0.002802f,
+ 0.002926f, 0.003189f, 0.003569f, 0.003752f, 0.004009f, 0.004513f, 0.004860f, 0.005375f, 0.005997f, 0.006561f, 0.007378f, 0.008347f,
+ 0.009384f, 0.010612f, 0.012466f, 0.014526f, 0.017075f, 0.020447f, 0.024887f, 0.030533f, 0.038300f, 0.048584f, 0.062042f, 0.080383f,
+ 0.104736f, 0.137329f, 0.180176f, 0.232544f, 0.296875f, 0.371338f, 0.769043f, 0.781250f, 0.784180f, 0.784668f, 0.786133f, 0.786133f,
+ 0.000025f, 0.000135f, 0.000154f, 0.000260f, 0.000353f, 0.000364f, 0.000380f, 0.000520f, 0.000548f, 0.000587f, 0.000712f, 0.000735f,
+ 0.000772f, 0.000822f, 0.000886f, 0.001004f, 0.000946f, 0.001115f, 0.001177f, 0.001266f, 0.001454f, 0.001527f, 0.001575f, 0.001680f,
+ 0.001883f, 0.001961f, 0.002043f, 0.002193f, 0.002281f, 0.002520f, 0.002712f, 0.003021f, 0.003147f, 0.003561f, 0.003786f, 0.004116f,
+ 0.004570f, 0.005058f, 0.005634f, 0.006165f, 0.007095f, 0.008049f, 0.009201f, 0.010674f, 0.012550f, 0.014854f, 0.018051f, 0.022385f,
+ 0.027908f, 0.035522f, 0.046295f, 0.061035f, 0.081238f, 0.109131f, 0.146729f, 0.197021f, 0.258301f, 0.333008f, 0.752441f, 0.766113f,
+ 0.768555f, 0.769531f, 0.770020f, 0.769531f, 0.000000f, 0.000121f, 0.000209f, 0.000291f, 0.000337f, 0.000307f, 0.000324f, 0.000415f,
+ 0.000426f, 0.000453f, 0.000491f, 0.000573f, 0.000644f, 0.000650f, 0.000781f, 0.000746f, 0.000830f, 0.000803f, 0.000997f, 0.001017f,
+ 0.001020f, 0.001158f, 0.001241f, 0.001317f, 0.001375f, 0.001432f, 0.001524f, 0.001656f, 0.001858f, 0.001955f, 0.002050f, 0.002274f,
+ 0.002460f, 0.002724f, 0.002831f, 0.003050f, 0.003441f, 0.003790f, 0.004162f, 0.004623f, 0.005219f, 0.005951f, 0.006721f, 0.007729f,
+ 0.008926f, 0.010620f, 0.013000f, 0.015686f, 0.019852f, 0.025436f, 0.033295f, 0.044617f, 0.060608f, 0.083313f, 0.116211f, 0.161499f,
+ 0.220093f, 0.293945f, 0.734863f, 0.749512f, 0.752441f, 0.752930f, 0.753906f, 0.753906f, 0.000000f, 0.000121f, 0.000118f, 0.000246f,
+ 0.000233f, 0.000252f, 0.000338f, 0.000282f, 0.000353f, 0.000355f, 0.000448f, 0.000435f, 0.000464f, 0.000530f, 0.000578f, 0.000649f,
+ 0.000677f, 0.000710f, 0.000749f, 0.000792f, 0.000881f, 0.000903f, 0.000967f, 0.001049f, 0.001041f, 0.001100f, 0.001176f, 0.001254f,
+ 0.001402f, 0.001451f, 0.001697f, 0.001674f, 0.001804f, 0.001914f, 0.002195f, 0.002451f, 0.002474f, 0.002758f, 0.003029f, 0.003483f,
+ 0.003824f, 0.004272f, 0.004833f, 0.005573f, 0.006477f, 0.007629f, 0.009041f, 0.010918f, 0.013573f, 0.017319f, 0.022842f, 0.031036f,
+ 0.043030f, 0.061096f, 0.088440f, 0.127563f, 0.182861f, 0.254395f, 0.717285f, 0.731934f, 0.734863f, 0.735352f, 0.735840f, 0.736328f,
+ 0.000000f, 0.000000f, 0.000117f, 0.000163f, 0.000109f, 0.000208f, 0.000212f, 0.000208f, 0.000270f, 0.000356f, 0.000324f, 0.000377f,
+ 0.000391f, 0.000420f, 0.000449f, 0.000440f, 0.000484f, 0.000504f, 0.000534f, 0.000561f, 0.000639f, 0.000667f, 0.000715f, 0.000722f,
+ 0.000799f, 0.000845f, 0.000939f, 0.000945f, 0.001053f, 0.001149f, 0.001252f, 0.001310f, 0.001392f, 0.001507f, 0.001526f, 0.001710f,
+ 0.001773f, 0.002111f, 0.002300f, 0.002443f, 0.002661f, 0.002996f, 0.003376f, 0.003880f, 0.004482f, 0.005150f, 0.006115f, 0.007401f,
+ 0.009132f, 0.011696f, 0.015076f, 0.020416f, 0.029236f, 0.042389f, 0.063782f, 0.096802f, 0.146362f, 0.215576f, 0.698242f, 0.712891f,
+ 0.715332f, 0.716797f, 0.717285f, 0.717285f, 0.000000f, 0.000118f, 0.000115f, 0.000133f, 0.000144f, 0.000147f, 0.000162f, 0.000150f,
+ 0.000194f, 0.000215f, 0.000228f, 0.000299f, 0.000271f, 0.000313f, 0.000328f, 0.000358f, 0.000378f, 0.000360f, 0.000407f, 0.000438f,
+ 0.000441f, 0.000488f, 0.000515f, 0.000544f, 0.000576f, 0.000617f, 0.000659f, 0.000715f, 0.000741f, 0.000773f, 0.000850f, 0.000921f,
+ 0.000979f, 0.001066f, 0.001128f, 0.001292f, 0.001279f, 0.001400f, 0.001572f, 0.001668f, 0.001869f, 0.002029f, 0.002295f, 0.002607f,
+ 0.002985f, 0.003464f, 0.004066f, 0.004913f, 0.006023f, 0.007519f, 0.009827f, 0.013016f, 0.018524f, 0.027481f, 0.042847f, 0.068970f,
+ 0.111938f, 0.176392f, 0.675781f, 0.692871f, 0.695801f, 0.696777f, 0.698242f, 0.697754f, 0.000000f, 0.000000f, 0.000111f, 0.000108f,
+ 0.000104f, 0.000102f, 0.000118f, 0.000120f, 0.000134f, 0.000128f, 0.000188f, 0.000154f, 0.000197f, 0.000188f, 0.000245f, 0.000256f,
+ 0.000233f, 0.000266f, 0.000345f, 0.000281f, 0.000355f, 0.000322f, 0.000392f, 0.000358f, 0.000437f, 0.000425f, 0.000458f, 0.000477f,
+ 0.000564f, 0.000636f, 0.000578f, 0.000607f, 0.000668f, 0.000719f, 0.000769f, 0.000832f, 0.000880f, 0.000953f, 0.001060f, 0.001116f,
+ 0.001226f, 0.001363f, 0.001486f, 0.001760f, 0.001944f, 0.002216f, 0.002605f, 0.003107f, 0.003778f, 0.004715f, 0.005989f, 0.007942f,
+ 0.011292f, 0.016632f, 0.026550f, 0.045532f, 0.079956f, 0.138550f, 0.655762f, 0.671875f, 0.674805f, 0.675293f, 0.675781f, 0.678223f,
+ 0.000000f, 0.000112f, 0.000105f, 0.000102f, 0.000098f, 0.000095f, 0.000093f, 0.000088f, 0.000089f, 0.000085f, 0.000095f, 0.000126f,
+ 0.000109f, 0.000154f, 0.000153f, 0.000162f, 0.000176f, 0.000190f, 0.000202f, 0.000204f, 0.000212f, 0.000214f, 0.000266f, 0.000239f,
+ 0.000279f, 0.000293f, 0.000329f, 0.000329f, 0.000339f, 0.000365f, 0.000437f, 0.000424f, 0.000429f, 0.000474f, 0.000525f, 0.000596f,
+ 0.000572f, 0.000612f, 0.000666f, 0.000723f, 0.000791f, 0.000850f, 0.000977f, 0.001066f, 0.001225f, 0.001351f, 0.001555f, 0.001837f,
+ 0.002279f, 0.002760f, 0.003445f, 0.004612f, 0.006386f, 0.009438f, 0.015221f, 0.027008f, 0.052551f, 0.102966f, 0.633789f, 0.649414f,
+ 0.652832f, 0.653809f, 0.655273f, 0.655273f, 0.000000f, 0.000105f, 0.000099f, 0.000094f, 0.000090f, 0.000087f, 0.000084f, 0.000082f,
+ 0.000079f, 0.000075f, 0.000071f, 0.000068f, 0.000064f, 0.000072f, 0.000096f, 0.000105f, 0.000112f, 0.000088f, 0.000123f, 0.000129f,
+ 0.000132f, 0.000140f, 0.000147f, 0.000170f, 0.000188f, 0.000192f, 0.000171f, 0.000210f, 0.000217f, 0.000223f, 0.000237f, 0.000251f,
+ 0.000258f, 0.000294f, 0.000298f, 0.000316f, 0.000350f, 0.000382f, 0.000400f, 0.000437f, 0.000479f, 0.000514f, 0.000576f, 0.000620f,
+ 0.000688f, 0.000782f, 0.000916f, 0.001026f, 0.001219f, 0.001502f, 0.001892f, 0.002424f, 0.003359f, 0.004974f, 0.008118f, 0.014343f,
+ 0.030075f, 0.070068f, 0.610352f, 0.626953f, 0.629883f, 0.631348f, 0.632324f, 0.632324f, 0.000110f, 0.000094f, 0.000087f, 0.000081f,
+ 0.000077f, 0.000075f, 0.000072f, 0.000069f, 0.000067f, 0.000066f, 0.000064f, 0.000062f, 0.000058f, 0.000056f, 0.000053f, 0.000051f,
+ 0.000054f, 0.000047f, 0.000057f, 0.000055f, 0.000075f, 0.000078f, 0.000086f, 0.000093f, 0.000093f, 0.000102f, 0.000112f, 0.000113f,
+ 0.000130f, 0.000128f, 0.000142f, 0.000145f, 0.000156f, 0.000153f, 0.000180f, 0.000178f, 0.000183f, 0.000223f, 0.000230f, 0.000240f,
+ 0.000265f, 0.000276f, 0.000300f, 0.000332f, 0.000357f, 0.000411f, 0.000449f, 0.000540f, 0.000615f, 0.000741f, 0.000916f, 0.001144f,
+ 0.001566f, 0.002310f, 0.003731f, 0.006905f, 0.014793f, 0.041779f, 0.585938f, 0.603027f, 0.605957f, 0.608398f, 0.608398f, 0.609375f,
+ 0.000090f, 0.000071f, 0.000066f, 0.000062f, 0.000058f, 0.000056f, 0.000053f, 0.000053f, 0.000051f, 0.000051f, 0.000049f, 0.000048f,
+ 0.000048f, 0.000047f, 0.000045f, 0.000043f, 0.000042f, 0.000040f, 0.000038f, 0.000036f, 0.000036f, 0.000033f, 0.000034f, 0.000040f,
+ 0.000040f, 0.000040f, 0.000048f, 0.000053f, 0.000060f, 0.000064f, 0.000067f, 0.000070f, 0.000075f, 0.000081f, 0.000085f, 0.000090f,
+ 0.000091f, 0.000103f, 0.000106f, 0.000120f, 0.000134f, 0.000138f, 0.000142f, 0.000156f, 0.000174f, 0.000180f, 0.000212f, 0.000239f,
+ 0.000253f, 0.000310f, 0.000377f, 0.000479f, 0.000627f, 0.000875f, 0.001396f, 0.002623f, 0.006184f, 0.019897f, 0.560547f, 0.578125f,
+ 0.581543f, 0.583008f, 0.583984f, 0.583984f, 0.000038f, 0.000035f, 0.000031f, 0.000031f, 0.000030f, 0.000031f, 0.000031f, 0.000030f,
+ 0.000030f, 0.000028f, 0.000029f, 0.000030f, 0.000029f, 0.000028f, 0.000029f, 0.000029f, 0.000029f, 0.000029f, 0.000029f, 0.000028f,
+ 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, 0.000020f, 0.000019f, 0.000021f, 0.000019f, 0.000022f,
+ 0.000023f, 0.000027f, 0.000031f, 0.000035f, 0.000037f, 0.000039f, 0.000039f, 0.000043f, 0.000049f, 0.000052f, 0.000056f, 0.000050f,
+ 0.000068f, 0.000062f, 0.000070f, 0.000087f, 0.000094f, 0.000107f, 0.000122f, 0.000140f, 0.000191f, 0.000247f, 0.000388f, 0.000710f,
+ 0.001781f, 0.007076f, 0.535156f, 0.553223f, 0.556152f, 0.558105f, 0.559082f, 0.559082f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000003f, 0.000005f, 0.000006f, 0.000007f, 0.000007f, 0.000009f,
+ 0.000009f, 0.000009f, 0.000010f, 0.000010f, 0.000011f, 0.000011f, 0.000012f, 0.000012f, 0.000012f, 0.000013f, 0.000013f, 0.000013f,
+ 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000009f,
+ 0.000009f, 0.000010f, 0.000011f, 0.000015f, 0.000017f, 0.000016f, 0.000018f, 0.000021f, 0.000020f, 0.000024f, 0.000024f, 0.000032f,
+ 0.000035f, 0.000045f, 0.000065f, 0.000105f, 0.000246f, 0.001313f, 0.508789f, 0.527344f, 0.530762f, 0.531738f, 0.532715f, 0.533691f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000002f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000005f, 0.000018f, 0.481934f, 0.500977f,
+ 0.504883f, 0.505859f, 0.507324f, 0.507812f,
+ },
+ {
+ 0.053833f, 0.152832f, 0.239014f, 0.313477f, 0.377686f, 0.433838f, 0.481689f, 0.524414f, 0.562988f, 0.596680f, 0.626953f, 0.654785f,
+ 0.678711f, 0.700684f, 0.720703f, 0.739746f, 0.755859f, 0.771973f, 0.787109f, 0.798828f, 0.812012f, 0.823730f, 0.833984f, 0.844238f,
+ 0.853027f, 0.862793f, 0.870605f, 0.878418f, 0.885254f, 0.892090f, 0.898926f, 0.904297f, 0.910645f, 0.916504f, 0.921875f, 0.926270f,
+ 0.931641f, 0.936035f, 0.939941f, 0.944336f, 0.948242f, 0.952148f, 0.955566f, 0.959961f, 0.962402f, 0.966309f, 0.969238f, 0.972168f,
+ 0.975098f, 0.978027f, 0.980957f, 0.983398f, 0.985840f, 0.988281f, 0.990723f, 0.992676f, 0.995117f, 0.996582f, 0.998047f, 0.995117f,
+ 0.993164f, 0.990723f, 0.988770f, 0.986816f, 0.036804f, 0.109497f, 0.178589f, 0.244751f, 0.305908f, 0.361084f, 0.411621f, 0.457275f,
+ 0.498535f, 0.536133f, 0.569824f, 0.601562f, 0.629883f, 0.655273f, 0.679688f, 0.700195f, 0.720215f, 0.737793f, 0.755859f, 0.770508f,
+ 0.785645f, 0.798340f, 0.811035f, 0.822754f, 0.833008f, 0.843750f, 0.852539f, 0.861328f, 0.869629f, 0.877441f, 0.885742f, 0.892578f,
+ 0.898926f, 0.905273f, 0.911133f, 0.916504f, 0.921875f, 0.926758f, 0.931641f, 0.936523f, 0.940430f, 0.945312f, 0.949219f, 0.953613f,
+ 0.956543f, 0.960449f, 0.963867f, 0.967285f, 0.970703f, 0.973633f, 0.976562f, 0.979004f, 0.981934f, 0.984375f, 0.986816f, 0.989746f,
+ 0.992188f, 0.994141f, 0.996582f, 0.994141f, 0.992188f, 0.990234f, 0.988281f, 0.986328f, 0.025787f, 0.080383f, 0.136230f, 0.191650f,
+ 0.245239f, 0.297119f, 0.345947f, 0.392822f, 0.436035f, 0.476807f, 0.513184f, 0.547363f, 0.578125f, 0.607910f, 0.634766f, 0.658203f,
+ 0.681152f, 0.702637f, 0.721191f, 0.738770f, 0.755371f, 0.770508f, 0.784668f, 0.798828f, 0.810547f, 0.821777f, 0.833984f, 0.843262f,
+ 0.852539f, 0.861816f, 0.869629f, 0.877930f, 0.885254f, 0.893555f, 0.898926f, 0.906250f, 0.911621f, 0.917969f, 0.923340f, 0.928223f,
+ 0.933105f, 0.937500f, 0.941406f, 0.946289f, 0.950195f, 0.954102f, 0.958496f, 0.961914f, 0.965820f, 0.968750f, 0.971680f, 0.975098f,
+ 0.978027f, 0.980469f, 0.983887f, 0.985840f, 0.988770f, 0.991211f, 0.995117f, 0.993164f, 0.991211f, 0.989258f, 0.987305f, 0.985352f,
+ 0.019455f, 0.060944f, 0.104553f, 0.150513f, 0.196411f, 0.243164f, 0.289062f, 0.333740f, 0.376709f, 0.417725f, 0.454346f, 0.491211f,
+ 0.524414f, 0.556641f, 0.585938f, 0.613770f, 0.639160f, 0.662598f, 0.682617f, 0.703613f, 0.723633f, 0.740723f, 0.756836f, 0.771973f,
+ 0.787109f, 0.798828f, 0.812012f, 0.823242f, 0.833984f, 0.844238f, 0.853516f, 0.863281f, 0.871094f, 0.879395f, 0.886719f, 0.893555f,
+ 0.899902f, 0.907227f, 0.913086f, 0.918945f, 0.924805f, 0.928711f, 0.934082f, 0.938965f, 0.943848f, 0.947754f, 0.952637f, 0.955566f,
+ 0.959961f, 0.963867f, 0.966797f, 0.970215f, 0.973633f, 0.977051f, 0.979004f, 0.982422f, 0.985840f, 0.987793f, 0.993652f, 0.991699f,
+ 0.989746f, 0.988281f, 0.986328f, 0.984375f, 0.015221f, 0.047363f, 0.082092f, 0.119202f, 0.159058f, 0.199219f, 0.239380f, 0.280762f,
+ 0.321533f, 0.362061f, 0.400146f, 0.436768f, 0.472900f, 0.504883f, 0.536621f, 0.566406f, 0.594238f, 0.621094f, 0.645508f, 0.667969f,
+ 0.688477f, 0.707520f, 0.726562f, 0.742676f, 0.759277f, 0.773926f, 0.787598f, 0.800781f, 0.812988f, 0.825195f, 0.835938f, 0.846191f,
+ 0.856445f, 0.865234f, 0.872559f, 0.880859f, 0.888672f, 0.895020f, 0.902832f, 0.908203f, 0.914551f, 0.919922f, 0.926758f, 0.931152f,
+ 0.937012f, 0.941406f, 0.945312f, 0.949707f, 0.954102f, 0.958496f, 0.962402f, 0.965820f, 0.969238f, 0.972168f, 0.976074f, 0.978516f,
+ 0.981934f, 0.984863f, 0.992188f, 0.990723f, 0.988770f, 0.987305f, 0.985352f, 0.983887f, 0.011658f, 0.037170f, 0.065430f, 0.096008f,
+ 0.128784f, 0.162842f, 0.198975f, 0.235596f, 0.273926f, 0.310791f, 0.348145f, 0.385010f, 0.420410f, 0.454834f, 0.488037f, 0.519043f,
+ 0.548828f, 0.577148f, 0.603516f, 0.627441f, 0.650879f, 0.672363f, 0.693848f, 0.712402f, 0.729980f, 0.748535f, 0.762207f, 0.778809f,
+ 0.791504f, 0.804199f, 0.815918f, 0.827637f, 0.838867f, 0.848145f, 0.857910f, 0.866211f, 0.875977f, 0.883301f, 0.891602f, 0.898438f,
+ 0.905273f, 0.911133f, 0.917480f, 0.923340f, 0.928711f, 0.933594f, 0.938477f, 0.942871f, 0.948242f, 0.952637f, 0.956543f, 0.960449f,
+ 0.964355f, 0.968262f, 0.971191f, 0.974609f, 0.978027f, 0.980957f, 0.990723f, 0.989258f, 0.987793f, 0.985840f, 0.984375f, 0.983398f,
+ 0.009758f, 0.030121f, 0.052490f, 0.077576f, 0.104309f, 0.134277f, 0.164917f, 0.197510f, 0.231812f, 0.266113f, 0.301025f, 0.336426f,
+ 0.372070f, 0.405762f, 0.438721f, 0.471436f, 0.502441f, 0.531738f, 0.560059f, 0.587402f, 0.612793f, 0.634766f, 0.658691f, 0.679199f,
+ 0.699219f, 0.718262f, 0.735352f, 0.751953f, 0.767090f, 0.780762f, 0.794922f, 0.808105f, 0.820801f, 0.831055f, 0.842285f, 0.851562f,
+ 0.861328f, 0.870117f, 0.878906f, 0.886719f, 0.893555f, 0.900879f, 0.907715f, 0.913574f, 0.919434f, 0.926270f, 0.932129f, 0.936523f,
+ 0.941895f, 0.945801f, 0.951172f, 0.955078f, 0.959473f, 0.963867f, 0.966797f, 0.970703f, 0.974121f, 0.977539f, 0.989746f, 0.988281f,
+ 0.986328f, 0.984863f, 0.983398f, 0.982422f, 0.007744f, 0.024567f, 0.043365f, 0.063782f, 0.086487f, 0.111389f, 0.137451f, 0.166260f,
+ 0.195435f, 0.226929f, 0.259033f, 0.291748f, 0.324951f, 0.358398f, 0.391113f, 0.424316f, 0.456299f, 0.486328f, 0.516113f, 0.543945f,
+ 0.571289f, 0.597656f, 0.621094f, 0.644531f, 0.666504f, 0.686523f, 0.705078f, 0.724121f, 0.741211f, 0.757324f, 0.773438f, 0.786621f,
+ 0.801270f, 0.812988f, 0.823730f, 0.835938f, 0.846191f, 0.855957f, 0.865723f, 0.873047f, 0.882324f, 0.889648f, 0.897949f, 0.905762f,
+ 0.911133f, 0.917969f, 0.923828f, 0.929199f, 0.934082f, 0.940430f, 0.944824f, 0.949707f, 0.954102f, 0.958008f, 0.962891f, 0.966309f,
+ 0.970215f, 0.974121f, 0.987793f, 0.986816f, 0.985352f, 0.983887f, 0.981934f, 0.980469f, 0.006672f, 0.020828f, 0.035950f, 0.053345f,
+ 0.071594f, 0.092834f, 0.114624f, 0.139282f, 0.165649f, 0.192627f, 0.222290f, 0.252197f, 0.283203f, 0.314941f, 0.346680f, 0.377930f,
+ 0.409668f, 0.441650f, 0.471680f, 0.500977f, 0.529297f, 0.557129f, 0.583008f, 0.607422f, 0.630859f, 0.654297f, 0.674805f, 0.694824f,
+ 0.713867f, 0.731445f, 0.748535f, 0.763672f, 0.778320f, 0.791992f, 0.805664f, 0.817871f, 0.829590f, 0.840332f, 0.850098f, 0.860352f,
+ 0.869141f, 0.878906f, 0.886719f, 0.894043f, 0.901855f, 0.909180f, 0.915527f, 0.920898f, 0.927246f, 0.933105f, 0.938477f, 0.943848f,
+ 0.948730f, 0.953125f, 0.957520f, 0.961914f, 0.965820f, 0.970215f, 0.985840f, 0.985352f, 0.983887f, 0.981934f, 0.980957f, 0.979492f,
+ 0.005592f, 0.017181f, 0.030457f, 0.044739f, 0.060638f, 0.077454f, 0.097046f, 0.117981f, 0.140625f, 0.164673f, 0.190552f, 0.217896f,
+ 0.246582f, 0.275635f, 0.305176f, 0.336426f, 0.366943f, 0.397949f, 0.428711f, 0.457764f, 0.487061f, 0.515137f, 0.542480f, 0.568848f,
+ 0.593750f, 0.619141f, 0.641602f, 0.662598f, 0.683594f, 0.703613f, 0.721191f, 0.738281f, 0.755859f, 0.770996f, 0.784180f, 0.799316f,
+ 0.811035f, 0.823730f, 0.833984f, 0.845703f, 0.855957f, 0.865234f, 0.875000f, 0.883301f, 0.891602f, 0.898926f, 0.906738f, 0.912598f,
+ 0.919922f, 0.926270f, 0.931152f, 0.937988f, 0.942871f, 0.948242f, 0.952148f, 0.957520f, 0.961914f, 0.966309f, 0.984375f, 0.983398f,
+ 0.982422f, 0.981445f, 0.979492f, 0.978027f, 0.004829f, 0.014816f, 0.025711f, 0.037964f, 0.051300f, 0.065796f, 0.082458f, 0.100037f,
+ 0.120178f, 0.141357f, 0.163330f, 0.187622f, 0.213013f, 0.240601f, 0.268311f, 0.296387f, 0.325928f, 0.356445f, 0.385742f, 0.415771f,
+ 0.445557f, 0.474121f, 0.501465f, 0.530762f, 0.556152f, 0.581543f, 0.606445f, 0.630859f, 0.651855f, 0.672852f, 0.693359f, 0.712402f,
+ 0.730469f, 0.746582f, 0.762695f, 0.777832f, 0.791992f, 0.806152f, 0.818359f, 0.830566f, 0.840820f, 0.852051f, 0.862305f, 0.871094f,
+ 0.880371f, 0.888184f, 0.896484f, 0.904297f, 0.910645f, 0.917969f, 0.924316f, 0.931152f, 0.936035f, 0.942383f, 0.947266f, 0.951660f,
+ 0.957031f, 0.960938f, 0.982422f, 0.982422f, 0.981445f, 0.979492f, 0.978516f, 0.977051f, 0.004040f, 0.012436f, 0.022064f, 0.032440f,
+ 0.044006f, 0.056549f, 0.070068f, 0.085999f, 0.102539f, 0.120239f, 0.140625f, 0.161621f, 0.184448f, 0.208496f, 0.234253f, 0.260742f,
+ 0.288086f, 0.316406f, 0.345215f, 0.374512f, 0.404297f, 0.433350f, 0.462402f, 0.490234f, 0.518066f, 0.543945f, 0.570312f, 0.594727f,
+ 0.618652f, 0.642090f, 0.663086f, 0.683594f, 0.703613f, 0.721680f, 0.739258f, 0.755859f, 0.772461f, 0.786621f, 0.798828f, 0.812500f,
+ 0.825195f, 0.836914f, 0.848633f, 0.858887f, 0.869141f, 0.877441f, 0.886230f, 0.894531f, 0.902832f, 0.909668f, 0.916992f, 0.923340f,
+ 0.929688f, 0.935547f, 0.941406f, 0.947266f, 0.951660f, 0.957031f, 0.980469f, 0.980469f, 0.979492f, 0.978516f, 0.977051f, 0.976074f,
+ 0.003536f, 0.010872f, 0.018829f, 0.027893f, 0.037872f, 0.048492f, 0.060883f, 0.073425f, 0.088074f, 0.103638f, 0.120789f, 0.139038f,
+ 0.159912f, 0.181274f, 0.204102f, 0.227905f, 0.253906f, 0.280518f, 0.307861f, 0.335938f, 0.364746f, 0.393311f, 0.421631f, 0.451416f,
+ 0.479004f, 0.505859f, 0.533203f, 0.560059f, 0.584473f, 0.608398f, 0.631836f, 0.653320f, 0.674805f, 0.695801f, 0.714355f, 0.731934f,
+ 0.749512f, 0.765137f, 0.781250f, 0.794434f, 0.808594f, 0.821289f, 0.833496f, 0.844238f, 0.855469f, 0.866211f, 0.875000f, 0.883789f,
+ 0.892578f, 0.901855f, 0.908691f, 0.915527f, 0.922852f, 0.929199f, 0.935059f, 0.941406f, 0.947266f, 0.951172f, 0.978516f, 0.979004f,
+ 0.978027f, 0.977051f, 0.975586f, 0.974121f, 0.002989f, 0.009476f, 0.016785f, 0.024246f, 0.032745f, 0.041809f, 0.052246f, 0.063782f,
+ 0.076111f, 0.089722f, 0.104675f, 0.120605f, 0.138306f, 0.157959f, 0.178101f, 0.200073f, 0.223145f, 0.247192f, 0.273193f, 0.300293f,
+ 0.327148f, 0.354736f, 0.383545f, 0.411621f, 0.439941f, 0.468018f, 0.495605f, 0.522949f, 0.548828f, 0.574219f, 0.598145f, 0.622559f,
+ 0.645508f, 0.666016f, 0.687500f, 0.706543f, 0.725586f, 0.743164f, 0.759766f, 0.775391f, 0.791016f, 0.803711f, 0.817871f, 0.829590f,
+ 0.841797f, 0.852539f, 0.863281f, 0.873047f, 0.882812f, 0.891113f, 0.900391f, 0.906738f, 0.915039f, 0.922852f, 0.929688f, 0.936035f,
+ 0.941895f, 0.946777f, 0.976074f, 0.977051f, 0.976074f, 0.975586f, 0.974121f, 0.972656f, 0.002846f, 0.008568f, 0.014557f, 0.021484f,
+ 0.028442f, 0.036377f, 0.045074f, 0.055054f, 0.066101f, 0.077759f, 0.090759f, 0.104797f, 0.120483f, 0.136719f, 0.155029f, 0.175171f,
+ 0.196045f, 0.218262f, 0.241943f, 0.266357f, 0.292480f, 0.319336f, 0.345703f, 0.373535f, 0.402100f, 0.429932f, 0.457764f, 0.484863f,
+ 0.512207f, 0.539062f, 0.564941f, 0.589844f, 0.613281f, 0.636719f, 0.659180f, 0.680664f, 0.700684f, 0.718750f, 0.736816f, 0.754883f,
+ 0.770508f, 0.785645f, 0.799805f, 0.813965f, 0.826172f, 0.838867f, 0.850586f, 0.861328f, 0.871582f, 0.881836f, 0.890625f, 0.898926f,
+ 0.906738f, 0.915039f, 0.922363f, 0.928711f, 0.936035f, 0.941895f, 0.974609f, 0.975098f, 0.974609f, 0.973633f, 0.972656f, 0.971191f,
+ 0.002285f, 0.007290f, 0.012634f, 0.018280f, 0.024918f, 0.032074f, 0.039673f, 0.048157f, 0.057220f, 0.067810f, 0.078735f, 0.091248f,
+ 0.104370f, 0.119873f, 0.135742f, 0.152344f, 0.171631f, 0.191650f, 0.213501f, 0.236206f, 0.260010f, 0.285156f, 0.310547f, 0.338135f,
+ 0.364746f, 0.392578f, 0.420410f, 0.448242f, 0.476562f, 0.502441f, 0.529785f, 0.555664f, 0.581543f, 0.605469f, 0.629395f, 0.652344f,
+ 0.673340f, 0.693848f, 0.713867f, 0.732910f, 0.750000f, 0.767090f, 0.782715f, 0.797852f, 0.811035f, 0.825195f, 0.836914f, 0.848633f,
+ 0.860840f, 0.870605f, 0.880371f, 0.890137f, 0.898926f, 0.907227f, 0.915527f, 0.923340f, 0.929688f, 0.936523f, 0.972168f, 0.973145f,
+ 0.972656f, 0.972168f, 0.970703f, 0.969727f, 0.002064f, 0.006584f, 0.011154f, 0.016266f, 0.022263f, 0.028397f, 0.034973f, 0.042145f,
+ 0.050232f, 0.059235f, 0.069031f, 0.079346f, 0.091736f, 0.104553f, 0.118652f, 0.133789f, 0.150635f, 0.168457f, 0.188110f, 0.208984f,
+ 0.230225f, 0.253906f, 0.278076f, 0.303955f, 0.329346f, 0.356689f, 0.384033f, 0.411865f, 0.439941f, 0.467285f, 0.493896f, 0.520996f,
+ 0.547363f, 0.573730f, 0.597168f, 0.622559f, 0.645508f, 0.667969f, 0.688965f, 0.709473f, 0.728027f, 0.746094f, 0.762695f, 0.778809f,
+ 0.794922f, 0.809082f, 0.822754f, 0.834961f, 0.847168f, 0.858887f, 0.870117f, 0.880371f, 0.889648f, 0.898926f, 0.907227f, 0.915039f,
+ 0.923828f, 0.930176f, 0.970215f, 0.971680f, 0.970215f, 0.970215f, 0.968750f, 0.968262f, 0.001935f, 0.005634f, 0.010078f, 0.014389f,
+ 0.019669f, 0.024658f, 0.030716f, 0.037201f, 0.044098f, 0.051941f, 0.060333f, 0.070129f, 0.080383f, 0.091370f, 0.103638f, 0.116943f,
+ 0.131714f, 0.148193f, 0.165161f, 0.183838f, 0.203979f, 0.225220f, 0.247803f, 0.271240f, 0.296631f, 0.322510f, 0.349121f, 0.376221f,
+ 0.403076f, 0.431152f, 0.458984f, 0.485596f, 0.513672f, 0.540039f, 0.564941f, 0.590820f, 0.616211f, 0.638672f, 0.662109f, 0.683105f,
+ 0.704102f, 0.723633f, 0.741699f, 0.759766f, 0.776855f, 0.792480f, 0.807617f, 0.821777f, 0.833496f, 0.847168f, 0.858887f, 0.870117f,
+ 0.880859f, 0.889648f, 0.899414f, 0.908203f, 0.916992f, 0.924316f, 0.967285f, 0.968262f, 0.968750f, 0.968262f, 0.967285f, 0.966309f,
+ 0.001805f, 0.005119f, 0.009079f, 0.013023f, 0.017487f, 0.022278f, 0.027130f, 0.032684f, 0.038666f, 0.045959f, 0.052826f, 0.061401f,
+ 0.070801f, 0.080139f, 0.090698f, 0.102844f, 0.115845f, 0.130005f, 0.145264f, 0.162476f, 0.180176f, 0.199951f, 0.220459f, 0.242188f,
+ 0.265869f, 0.290283f, 0.315430f, 0.341309f, 0.368652f, 0.395752f, 0.423584f, 0.451416f, 0.479248f, 0.505859f, 0.532227f, 0.559082f,
+ 0.584961f, 0.609863f, 0.634277f, 0.656738f, 0.678711f, 0.700195f, 0.720703f, 0.738281f, 0.757324f, 0.774414f, 0.790527f, 0.805664f,
+ 0.820312f, 0.834473f, 0.846680f, 0.858887f, 0.869629f, 0.880859f, 0.890625f, 0.899902f, 0.909668f, 0.917969f, 0.964844f, 0.966797f,
+ 0.967285f, 0.965820f, 0.964844f, 0.963867f, 0.001437f, 0.004662f, 0.007919f, 0.011681f, 0.015404f, 0.019272f, 0.024261f, 0.029205f,
+ 0.034515f, 0.040619f, 0.046967f, 0.054138f, 0.061737f, 0.070496f, 0.080200f, 0.090271f, 0.101807f, 0.114136f, 0.127686f, 0.143188f,
+ 0.159058f, 0.176514f, 0.195190f, 0.215454f, 0.237305f, 0.260010f, 0.283936f, 0.309326f, 0.334717f, 0.361328f, 0.389160f, 0.416260f,
+ 0.444336f, 0.471436f, 0.499512f, 0.525879f, 0.552734f, 0.579590f, 0.604004f, 0.628906f, 0.651855f, 0.674805f, 0.696777f, 0.717773f,
+ 0.737305f, 0.755859f, 0.772949f, 0.789551f, 0.805664f, 0.819336f, 0.833984f, 0.847168f, 0.859375f, 0.871094f, 0.881836f, 0.892090f,
+ 0.902344f, 0.910156f, 0.962402f, 0.964355f, 0.964355f, 0.963867f, 0.962891f, 0.961914f, 0.001264f, 0.004036f, 0.007088f, 0.010170f,
+ 0.013672f, 0.017365f, 0.021423f, 0.025955f, 0.030533f, 0.035614f, 0.041321f, 0.047791f, 0.054626f, 0.062195f, 0.070679f, 0.080017f,
+ 0.089600f, 0.100769f, 0.112854f, 0.125977f, 0.139893f, 0.156128f, 0.172852f, 0.191650f, 0.211060f, 0.232056f, 0.254883f, 0.278076f,
+ 0.302979f, 0.328125f, 0.355225f, 0.381836f, 0.409912f, 0.437256f, 0.464844f, 0.492676f, 0.520508f, 0.547852f, 0.573242f, 0.599609f,
+ 0.625000f, 0.649414f, 0.672363f, 0.694336f, 0.714844f, 0.734863f, 0.753418f, 0.771484f, 0.788574f, 0.804688f, 0.820312f, 0.833496f,
+ 0.847656f, 0.859863f, 0.873047f, 0.883301f, 0.894043f, 0.903809f, 0.959961f, 0.961914f, 0.962402f, 0.960938f, 0.960449f, 0.959961f,
+ 0.001297f, 0.003721f, 0.006397f, 0.009308f, 0.012260f, 0.015808f, 0.019302f, 0.023010f, 0.027267f, 0.032013f, 0.037109f, 0.042419f,
+ 0.048523f, 0.054962f, 0.061920f, 0.070435f, 0.079407f, 0.088318f, 0.099121f, 0.111084f, 0.124023f, 0.137695f, 0.152832f, 0.169434f,
+ 0.187378f, 0.206421f, 0.227783f, 0.249268f, 0.272461f, 0.297363f, 0.322754f, 0.348389f, 0.376221f, 0.403809f, 0.431396f, 0.459229f,
+ 0.487305f, 0.515137f, 0.542480f, 0.569336f, 0.595215f, 0.621094f, 0.645996f, 0.669434f, 0.691406f, 0.712891f, 0.733887f, 0.753418f,
+ 0.770996f, 0.789062f, 0.805176f, 0.820801f, 0.835449f, 0.849121f, 0.861328f, 0.874512f, 0.885742f, 0.895508f, 0.956543f, 0.959473f,
+ 0.958984f, 0.958984f, 0.958008f, 0.957031f, 0.001267f, 0.003481f, 0.005955f, 0.008568f, 0.011185f, 0.014030f, 0.017151f, 0.020294f,
+ 0.024246f, 0.028427f, 0.032654f, 0.037476f, 0.042603f, 0.048523f, 0.054871f, 0.062408f, 0.070129f, 0.078552f, 0.087769f, 0.097534f,
+ 0.109192f, 0.121399f, 0.135010f, 0.150513f, 0.165894f, 0.183960f, 0.202881f, 0.222656f, 0.244385f, 0.267334f, 0.291260f, 0.317139f,
+ 0.343506f, 0.370605f, 0.397949f, 0.426025f, 0.454346f, 0.482666f, 0.511230f, 0.538086f, 0.565918f, 0.592285f, 0.618164f, 0.642578f,
+ 0.667480f, 0.690918f, 0.711914f, 0.732910f, 0.752930f, 0.771484f, 0.790039f, 0.806641f, 0.821777f, 0.837402f, 0.850586f, 0.864746f,
+ 0.875977f, 0.887695f, 0.953613f, 0.956543f, 0.957031f, 0.956055f, 0.956055f, 0.955078f, 0.001068f, 0.003025f, 0.005283f, 0.007442f,
+ 0.009857f, 0.012665f, 0.015930f, 0.018570f, 0.021820f, 0.025314f, 0.028931f, 0.033325f, 0.038147f, 0.042908f, 0.049011f, 0.055176f,
+ 0.061859f, 0.069397f, 0.077637f, 0.086792f, 0.096252f, 0.107117f, 0.119385f, 0.132690f, 0.147095f, 0.162720f, 0.180054f, 0.198486f,
+ 0.218384f, 0.239990f, 0.262207f, 0.287109f, 0.311523f, 0.337891f, 0.364990f, 0.392822f, 0.420654f, 0.449219f, 0.478027f, 0.505859f,
+ 0.535156f, 0.562012f, 0.588867f, 0.615723f, 0.641602f, 0.666016f, 0.688965f, 0.711914f, 0.732910f, 0.753906f, 0.773438f, 0.791016f,
+ 0.808594f, 0.823730f, 0.839355f, 0.854004f, 0.867188f, 0.879883f, 0.950195f, 0.954102f, 0.954102f, 0.953125f, 0.952637f, 0.952148f,
+ 0.000884f, 0.003082f, 0.004631f, 0.006931f, 0.008942f, 0.011513f, 0.013779f, 0.016663f, 0.019806f, 0.022934f, 0.026215f, 0.029999f,
+ 0.033813f, 0.038544f, 0.043365f, 0.048615f, 0.054352f, 0.061005f, 0.068420f, 0.076477f, 0.085022f, 0.095032f, 0.105469f, 0.117432f,
+ 0.130127f, 0.143799f, 0.159790f, 0.176270f, 0.194580f, 0.214478f, 0.235229f, 0.257568f, 0.281982f, 0.306641f, 0.332764f, 0.359863f,
+ 0.388184f, 0.416016f, 0.445557f, 0.474854f, 0.502441f, 0.531738f, 0.559570f, 0.586914f, 0.614258f, 0.640625f, 0.665039f, 0.689453f,
+ 0.712891f, 0.734863f, 0.755371f, 0.774902f, 0.793945f, 0.810547f, 0.827637f, 0.842773f, 0.857910f, 0.871094f, 0.946777f, 0.950684f,
+ 0.951172f, 0.950684f, 0.949707f, 0.949707f, 0.000848f, 0.002630f, 0.004330f, 0.006386f, 0.008148f, 0.010437f, 0.012436f, 0.014977f,
+ 0.017731f, 0.020645f, 0.023529f, 0.026413f, 0.030289f, 0.034302f, 0.038391f, 0.043365f, 0.048737f, 0.054413f, 0.060455f, 0.067383f,
+ 0.075134f, 0.083801f, 0.093262f, 0.103821f, 0.114746f, 0.127441f, 0.140991f, 0.156372f, 0.172729f, 0.190918f, 0.210449f, 0.231201f,
+ 0.253662f, 0.277344f, 0.302734f, 0.328857f, 0.355225f, 0.384033f, 0.413086f, 0.440918f, 0.471191f, 0.500488f, 0.529785f, 0.558594f,
+ 0.586426f, 0.613770f, 0.640137f, 0.666016f, 0.689453f, 0.714355f, 0.736328f, 0.757812f, 0.777832f, 0.796875f, 0.813965f, 0.831543f,
+ 0.847168f, 0.860840f, 0.943848f, 0.948242f, 0.947754f, 0.948242f, 0.946777f, 0.946777f, 0.000747f, 0.002462f, 0.004192f, 0.005573f,
+ 0.007454f, 0.009430f, 0.011253f, 0.013588f, 0.015762f, 0.018112f, 0.020859f, 0.023758f, 0.027084f, 0.030426f, 0.034332f, 0.038635f,
+ 0.042999f, 0.048340f, 0.053772f, 0.060028f, 0.066589f, 0.074402f, 0.082764f, 0.091553f, 0.101685f, 0.112854f, 0.125122f, 0.138184f,
+ 0.153320f, 0.169556f, 0.187500f, 0.206543f, 0.227539f, 0.249512f, 0.273193f, 0.298340f, 0.324463f, 0.351562f, 0.379883f, 0.409424f,
+ 0.438477f, 0.468750f, 0.498047f, 0.527832f, 0.556641f, 0.585449f, 0.614258f, 0.641113f, 0.666992f, 0.692383f, 0.716309f, 0.738281f,
+ 0.760742f, 0.780273f, 0.799805f, 0.818848f, 0.834473f, 0.851074f, 0.939941f, 0.944824f, 0.944336f, 0.944336f, 0.944336f, 0.943359f,
+ 0.000670f, 0.002079f, 0.003538f, 0.005146f, 0.006508f, 0.008247f, 0.010223f, 0.012260f, 0.014153f, 0.016479f, 0.018677f, 0.021515f,
+ 0.024323f, 0.027313f, 0.030518f, 0.034302f, 0.038422f, 0.042725f, 0.047760f, 0.053101f, 0.059113f, 0.065613f, 0.072937f, 0.080444f,
+ 0.089722f, 0.099426f, 0.110596f, 0.122314f, 0.135742f, 0.150513f, 0.166260f, 0.183716f, 0.202759f, 0.223633f, 0.245728f, 0.269287f,
+ 0.294189f, 0.320557f, 0.348633f, 0.376709f, 0.406494f, 0.436523f, 0.467285f, 0.497070f, 0.528320f, 0.557129f, 0.586426f, 0.614746f,
+ 0.642090f, 0.668945f, 0.694824f, 0.718750f, 0.742676f, 0.764648f, 0.786133f, 0.805176f, 0.823242f, 0.840820f, 0.936035f, 0.940918f,
+ 0.941406f, 0.941406f, 0.940430f, 0.939941f, 0.000645f, 0.001963f, 0.003384f, 0.004719f, 0.006042f, 0.007614f, 0.009384f, 0.011192f,
+ 0.012665f, 0.015083f, 0.016861f, 0.019165f, 0.021393f, 0.024445f, 0.027451f, 0.030716f, 0.034149f, 0.038116f, 0.042389f, 0.047028f,
+ 0.052277f, 0.058014f, 0.064270f, 0.071289f, 0.079041f, 0.087830f, 0.097351f, 0.108337f, 0.119995f, 0.132812f, 0.147217f, 0.163452f,
+ 0.180420f, 0.199585f, 0.219849f, 0.242065f, 0.265625f, 0.291260f, 0.318115f, 0.345703f, 0.375000f, 0.404541f, 0.434326f, 0.465820f,
+ 0.496582f, 0.526855f, 0.557617f, 0.587402f, 0.616699f, 0.645508f, 0.672363f, 0.698242f, 0.723145f, 0.747559f, 0.770020f, 0.791504f,
+ 0.810059f, 0.828613f, 0.931641f, 0.937012f, 0.937500f, 0.937500f, 0.937012f, 0.936523f, 0.000692f, 0.001705f, 0.003000f, 0.004238f,
+ 0.005798f, 0.006805f, 0.008659f, 0.009933f, 0.011681f, 0.013191f, 0.015259f, 0.017166f, 0.019379f, 0.021729f, 0.024796f, 0.027328f,
+ 0.030380f, 0.033661f, 0.037598f, 0.041718f, 0.046539f, 0.051270f, 0.056946f, 0.062988f, 0.069885f, 0.077271f, 0.085999f, 0.095398f,
+ 0.105652f, 0.117859f, 0.129883f, 0.144409f, 0.159912f, 0.177002f, 0.196045f, 0.216553f, 0.239014f, 0.262451f, 0.288086f, 0.314941f,
+ 0.343262f, 0.372314f, 0.403076f, 0.433594f, 0.465332f, 0.496826f, 0.527832f, 0.559082f, 0.589355f, 0.619629f, 0.648926f, 0.676758f,
+ 0.703125f, 0.728516f, 0.752930f, 0.775391f, 0.797363f, 0.817871f, 0.927246f, 0.933105f, 0.934082f, 0.933594f, 0.933594f, 0.933105f,
+ 0.000460f, 0.001622f, 0.002705f, 0.003983f, 0.004925f, 0.006363f, 0.007652f, 0.008965f, 0.010521f, 0.011963f, 0.013664f, 0.015480f,
+ 0.017258f, 0.019440f, 0.021912f, 0.024338f, 0.027084f, 0.030212f, 0.033356f, 0.037018f, 0.040833f, 0.045380f, 0.050110f, 0.055573f,
+ 0.061829f, 0.068359f, 0.075928f, 0.083984f, 0.093140f, 0.103333f, 0.115112f, 0.127441f, 0.141602f, 0.156982f, 0.174316f, 0.192871f,
+ 0.213257f, 0.235596f, 0.259766f, 0.285400f, 0.312256f, 0.341797f, 0.371094f, 0.402100f, 0.434082f, 0.465332f, 0.497314f, 0.529297f,
+ 0.562012f, 0.592773f, 0.623535f, 0.652832f, 0.681641f, 0.709473f, 0.735352f, 0.759766f, 0.783203f, 0.803711f, 0.922363f, 0.929199f,
+ 0.929688f, 0.929199f, 0.929688f, 0.928711f, 0.000341f, 0.001686f, 0.002537f, 0.003769f, 0.004745f, 0.005764f, 0.007034f, 0.008286f,
+ 0.009369f, 0.010742f, 0.012161f, 0.013931f, 0.015671f, 0.017563f, 0.019440f, 0.021851f, 0.024231f, 0.026672f, 0.029556f, 0.032776f,
+ 0.036255f, 0.040283f, 0.044464f, 0.049194f, 0.054413f, 0.060059f, 0.066589f, 0.074036f, 0.081909f, 0.091187f, 0.100769f, 0.112000f,
+ 0.124512f, 0.139038f, 0.154297f, 0.171265f, 0.189819f, 0.210571f, 0.232788f, 0.257324f, 0.283203f, 0.311035f, 0.339844f, 0.370850f,
+ 0.402100f, 0.433838f, 0.466797f, 0.499268f, 0.532227f, 0.565430f, 0.598145f, 0.628418f, 0.659180f, 0.687988f, 0.715820f, 0.742188f,
+ 0.767090f, 0.791504f, 0.917969f, 0.924805f, 0.925293f, 0.925293f, 0.924805f, 0.924805f, 0.000405f, 0.001282f, 0.002298f, 0.003269f,
+ 0.004448f, 0.005043f, 0.006294f, 0.007233f, 0.008606f, 0.009727f, 0.010849f, 0.012421f, 0.013885f, 0.015465f, 0.017426f, 0.019394f,
+ 0.021667f, 0.023819f, 0.026154f, 0.029175f, 0.032227f, 0.035706f, 0.039062f, 0.043427f, 0.047913f, 0.052856f, 0.058502f, 0.064880f,
+ 0.071960f, 0.079895f, 0.088867f, 0.098633f, 0.109619f, 0.122192f, 0.135742f, 0.151489f, 0.168457f, 0.187134f, 0.207764f, 0.230835f,
+ 0.254883f, 0.281494f, 0.310059f, 0.339355f, 0.370361f, 0.402588f, 0.435547f, 0.468994f, 0.502930f, 0.537109f, 0.569824f, 0.602051f,
+ 0.634766f, 0.665527f, 0.695801f, 0.724121f, 0.750488f, 0.776855f, 0.912598f, 0.919434f, 0.920410f, 0.920410f, 0.919922f, 0.920410f,
+ 0.000529f, 0.001217f, 0.002171f, 0.003035f, 0.003790f, 0.004784f, 0.005711f, 0.006756f, 0.007782f, 0.008987f, 0.009773f, 0.011185f,
+ 0.012650f, 0.013771f, 0.015656f, 0.017181f, 0.018890f, 0.021057f, 0.023239f, 0.025848f, 0.028488f, 0.031525f, 0.034607f, 0.038147f,
+ 0.042023f, 0.046539f, 0.051605f, 0.056793f, 0.063049f, 0.069946f, 0.078064f, 0.086548f, 0.096313f, 0.107117f, 0.119446f, 0.133301f,
+ 0.148560f, 0.165405f, 0.184570f, 0.205811f, 0.228394f, 0.253174f, 0.280029f, 0.308594f, 0.339111f, 0.370605f, 0.404053f, 0.437988f,
+ 0.471680f, 0.506348f, 0.541504f, 0.576172f, 0.609375f, 0.642578f, 0.674316f, 0.705078f, 0.734375f, 0.761719f, 0.907227f, 0.914062f,
+ 0.915527f, 0.915527f, 0.916016f, 0.915039f, 0.000402f, 0.001247f, 0.001841f, 0.002651f, 0.003414f, 0.004200f, 0.005337f, 0.005821f,
+ 0.006733f, 0.008041f, 0.008942f, 0.010201f, 0.011261f, 0.012749f, 0.013893f, 0.015472f, 0.016663f, 0.018829f, 0.020615f, 0.022873f,
+ 0.025299f, 0.027893f, 0.030533f, 0.033600f, 0.037140f, 0.040924f, 0.044983f, 0.049927f, 0.055359f, 0.061340f, 0.068176f, 0.075500f,
+ 0.084106f, 0.093933f, 0.104370f, 0.116638f, 0.130249f, 0.145996f, 0.162842f, 0.181885f, 0.203735f, 0.226562f, 0.251465f, 0.279297f,
+ 0.308594f, 0.339355f, 0.373047f, 0.406982f, 0.440918f, 0.477051f, 0.511719f, 0.548340f, 0.583496f, 0.618164f, 0.652344f, 0.684570f,
+ 0.715332f, 0.745605f, 0.901855f, 0.909180f, 0.910156f, 0.910645f, 0.910156f, 0.910156f, 0.000371f, 0.001090f, 0.001752f, 0.002409f,
+ 0.003042f, 0.003963f, 0.004898f, 0.005295f, 0.006077f, 0.006992f, 0.008102f, 0.009338f, 0.010101f, 0.011078f, 0.012375f, 0.013718f,
+ 0.015099f, 0.016403f, 0.018402f, 0.020203f, 0.022354f, 0.024475f, 0.026825f, 0.029388f, 0.032623f, 0.035522f, 0.039429f, 0.043762f,
+ 0.048462f, 0.053558f, 0.059265f, 0.065552f, 0.073120f, 0.081787f, 0.091431f, 0.102112f, 0.114136f, 0.127930f, 0.143066f, 0.160767f,
+ 0.179810f, 0.200928f, 0.224854f, 0.250732f, 0.279053f, 0.308838f, 0.340820f, 0.374756f, 0.410156f, 0.446045f, 0.482666f, 0.520020f,
+ 0.556152f, 0.593262f, 0.628906f, 0.663574f, 0.695801f, 0.728027f, 0.895508f, 0.903809f, 0.904297f, 0.904297f, 0.904297f, 0.904785f,
+ 0.000425f, 0.000937f, 0.001529f, 0.002129f, 0.002674f, 0.003696f, 0.004257f, 0.004990f, 0.005726f, 0.006161f, 0.007118f, 0.007919f,
+ 0.009109f, 0.009941f, 0.011055f, 0.011993f, 0.013191f, 0.014832f, 0.016281f, 0.017868f, 0.019562f, 0.021362f, 0.023514f, 0.025909f,
+ 0.028549f, 0.031189f, 0.034637f, 0.037994f, 0.042145f, 0.046570f, 0.051453f, 0.057129f, 0.063965f, 0.070984f, 0.079285f, 0.088806f,
+ 0.099426f, 0.111267f, 0.125366f, 0.140747f, 0.158203f, 0.178101f, 0.199585f, 0.223755f, 0.250732f, 0.279297f, 0.310059f, 0.343994f,
+ 0.377686f, 0.414307f, 0.451904f, 0.489258f, 0.527832f, 0.565918f, 0.603027f, 0.640137f, 0.675781f, 0.710449f, 0.888672f, 0.897461f,
+ 0.899902f, 0.900391f, 0.899414f, 0.899414f, 0.000317f, 0.000823f, 0.001386f, 0.002108f, 0.002684f, 0.003239f, 0.003883f, 0.004303f,
+ 0.004730f, 0.005569f, 0.006626f, 0.007214f, 0.008003f, 0.008865f, 0.009590f, 0.010948f, 0.011856f, 0.012871f, 0.014381f, 0.015640f,
+ 0.017075f, 0.018799f, 0.020569f, 0.022537f, 0.024704f, 0.027405f, 0.030090f, 0.033142f, 0.036346f, 0.040436f, 0.044830f, 0.049835f,
+ 0.055450f, 0.061584f, 0.068665f, 0.076904f, 0.086060f, 0.096741f, 0.109192f, 0.122559f, 0.138428f, 0.155762f, 0.176270f, 0.198242f,
+ 0.223145f, 0.250244f, 0.280518f, 0.312500f, 0.346680f, 0.382324f, 0.420410f, 0.458740f, 0.498779f, 0.538086f, 0.577637f, 0.616211f,
+ 0.654297f, 0.690918f, 0.881348f, 0.890625f, 0.892578f, 0.893066f, 0.893066f, 0.892578f, 0.000385f, 0.000766f, 0.001544f, 0.001925f,
+ 0.002359f, 0.002947f, 0.003176f, 0.003691f, 0.004288f, 0.005215f, 0.005917f, 0.006214f, 0.007019f, 0.007843f, 0.008469f, 0.009598f,
+ 0.010345f, 0.011559f, 0.012497f, 0.013634f, 0.014992f, 0.016373f, 0.017853f, 0.019608f, 0.021515f, 0.023788f, 0.026260f, 0.028931f,
+ 0.031860f, 0.034912f, 0.038635f, 0.042633f, 0.047638f, 0.053070f, 0.059540f, 0.066284f, 0.074524f, 0.083679f, 0.094177f, 0.106445f,
+ 0.120361f, 0.135620f, 0.154053f, 0.174072f, 0.197144f, 0.222900f, 0.251221f, 0.281982f, 0.315430f, 0.351318f, 0.388672f, 0.427734f,
+ 0.468506f, 0.508301f, 0.549805f, 0.591309f, 0.631348f, 0.670410f, 0.874512f, 0.884766f, 0.885742f, 0.886230f, 0.886230f, 0.886230f,
+ 0.000230f, 0.000832f, 0.001281f, 0.001865f, 0.002207f, 0.002605f, 0.003212f, 0.003284f, 0.004124f, 0.004597f, 0.005222f, 0.005703f,
+ 0.006260f, 0.007095f, 0.007790f, 0.008377f, 0.009010f, 0.010078f, 0.011009f, 0.011925f, 0.013153f, 0.014282f, 0.015610f, 0.017151f,
+ 0.018951f, 0.020416f, 0.022583f, 0.024826f, 0.027328f, 0.030136f, 0.033508f, 0.036835f, 0.040985f, 0.045410f, 0.050812f, 0.056854f,
+ 0.063965f, 0.071777f, 0.081177f, 0.091858f, 0.103699f, 0.117615f, 0.133423f, 0.152588f, 0.172974f, 0.196777f, 0.222900f, 0.252686f,
+ 0.284912f, 0.319824f, 0.356934f, 0.395996f, 0.436768f, 0.478516f, 0.521484f, 0.564453f, 0.607422f, 0.649414f, 0.866699f, 0.876953f,
+ 0.877930f, 0.879395f, 0.879883f, 0.878418f, 0.000228f, 0.000734f, 0.000993f, 0.001416f, 0.001935f, 0.002293f, 0.002541f, 0.003174f,
+ 0.003508f, 0.004040f, 0.004337f, 0.005039f, 0.005505f, 0.006054f, 0.006840f, 0.007366f, 0.008041f, 0.008644f, 0.009544f, 0.010460f,
+ 0.011238f, 0.012329f, 0.013542f, 0.014755f, 0.016083f, 0.017624f, 0.019424f, 0.021408f, 0.023422f, 0.025803f, 0.028366f, 0.031311f,
+ 0.034912f, 0.039124f, 0.043304f, 0.048492f, 0.054291f, 0.061188f, 0.069397f, 0.078552f, 0.089233f, 0.101074f, 0.115540f, 0.131226f,
+ 0.150757f, 0.172119f, 0.196533f, 0.224243f, 0.254883f, 0.288574f, 0.324707f, 0.364014f, 0.405029f, 0.447510f, 0.491699f, 0.536133f,
+ 0.581543f, 0.627441f, 0.858398f, 0.869141f, 0.870605f, 0.871582f, 0.871094f, 0.871582f, 0.000118f, 0.000713f, 0.000985f, 0.001328f,
+ 0.001612f, 0.001999f, 0.002399f, 0.002913f, 0.003139f, 0.003567f, 0.004055f, 0.004406f, 0.004986f, 0.005226f, 0.005856f, 0.006332f,
+ 0.007042f, 0.007553f, 0.008286f, 0.009064f, 0.009834f, 0.010696f, 0.011658f, 0.012726f, 0.013817f, 0.015289f, 0.016693f, 0.018265f,
+ 0.019699f, 0.021835f, 0.024307f, 0.026642f, 0.029770f, 0.033234f, 0.037048f, 0.041351f, 0.046478f, 0.052032f, 0.058960f, 0.066589f,
+ 0.075745f, 0.086182f, 0.099121f, 0.113037f, 0.129517f, 0.149048f, 0.171387f, 0.196899f, 0.225464f, 0.257812f, 0.293457f, 0.331787f,
+ 0.373291f, 0.416748f, 0.460938f, 0.507812f, 0.554688f, 0.602051f, 0.849609f, 0.859863f, 0.862793f, 0.863281f, 0.862793f, 0.862793f,
+ 0.000211f, 0.000522f, 0.000877f, 0.001204f, 0.001507f, 0.001724f, 0.002062f, 0.002426f, 0.002867f, 0.003157f, 0.003443f, 0.003752f,
+ 0.004192f, 0.004753f, 0.005154f, 0.005428f, 0.006065f, 0.006546f, 0.007210f, 0.007725f, 0.008530f, 0.009247f, 0.010025f, 0.010887f,
+ 0.011909f, 0.012970f, 0.014069f, 0.015335f, 0.017105f, 0.018433f, 0.020554f, 0.022552f, 0.025116f, 0.027802f, 0.031158f, 0.034485f,
+ 0.038971f, 0.044037f, 0.049469f, 0.055847f, 0.063843f, 0.072815f, 0.083618f, 0.095947f, 0.110840f, 0.128174f, 0.147949f, 0.171387f,
+ 0.198242f, 0.228271f, 0.262207f, 0.299805f, 0.340332f, 0.384277f, 0.430176f, 0.477295f, 0.527344f, 0.577637f, 0.839844f, 0.851074f,
+ 0.853516f, 0.854492f, 0.854980f, 0.854980f, 0.000218f, 0.000479f, 0.000706f, 0.001109f, 0.001245f, 0.001763f, 0.001800f, 0.002211f,
+ 0.002377f, 0.002783f, 0.003103f, 0.003223f, 0.003782f, 0.004089f, 0.004326f, 0.004711f, 0.005306f, 0.005569f, 0.006199f, 0.006653f,
+ 0.007168f, 0.007919f, 0.008560f, 0.009254f, 0.009979f, 0.010872f, 0.012054f, 0.012810f, 0.014221f, 0.015793f, 0.017181f, 0.018967f,
+ 0.021088f, 0.023361f, 0.026001f, 0.028915f, 0.032257f, 0.036469f, 0.040924f, 0.046875f, 0.053375f, 0.061218f, 0.070435f, 0.080811f,
+ 0.093628f, 0.108704f, 0.126709f, 0.147461f, 0.172241f, 0.199951f, 0.232788f, 0.268799f, 0.308594f, 0.351562f, 0.397705f, 0.447266f,
+ 0.498291f, 0.550293f, 0.830078f, 0.841797f, 0.843750f, 0.845215f, 0.845215f, 0.845703f, 0.000139f, 0.000379f, 0.000704f, 0.000896f,
+ 0.001095f, 0.001392f, 0.001649f, 0.002058f, 0.002235f, 0.002483f, 0.002621f, 0.002878f, 0.003214f, 0.003580f, 0.003820f, 0.004055f,
+ 0.004498f, 0.004791f, 0.005173f, 0.005692f, 0.006145f, 0.006691f, 0.007175f, 0.007874f, 0.008499f, 0.009239f, 0.010117f, 0.011032f,
+ 0.011864f, 0.012901f, 0.014282f, 0.015701f, 0.017242f, 0.019516f, 0.021469f, 0.024002f, 0.026749f, 0.029953f, 0.034027f, 0.038727f,
+ 0.044250f, 0.050568f, 0.058136f, 0.067139f, 0.078247f, 0.091614f, 0.106689f, 0.125366f, 0.147339f, 0.172974f, 0.202881f, 0.237671f,
+ 0.275879f, 0.318359f, 0.365234f, 0.415283f, 0.468018f, 0.521973f, 0.819336f, 0.832031f, 0.834473f, 0.834961f, 0.835449f, 0.835938f,
+ 0.000115f, 0.000396f, 0.000688f, 0.000885f, 0.000917f, 0.001393f, 0.001478f, 0.001590f, 0.001944f, 0.002123f, 0.002291f, 0.002644f,
+ 0.002666f, 0.003023f, 0.003197f, 0.003546f, 0.003714f, 0.004246f, 0.004551f, 0.004837f, 0.005108f, 0.005577f, 0.006054f, 0.006504f,
+ 0.007023f, 0.007633f, 0.008362f, 0.009148f, 0.009926f, 0.010742f, 0.011917f, 0.013062f, 0.014351f, 0.015991f, 0.017639f, 0.019455f,
+ 0.021729f, 0.024689f, 0.027740f, 0.031708f, 0.036102f, 0.041260f, 0.047882f, 0.055450f, 0.064392f, 0.075500f, 0.088928f, 0.104797f,
+ 0.124756f, 0.147949f, 0.175415f, 0.207275f, 0.244507f, 0.286133f, 0.332520f, 0.381836f, 0.436279f, 0.492432f, 0.808105f, 0.821289f,
+ 0.822754f, 0.824707f, 0.825195f, 0.824219f, 0.000209f, 0.000435f, 0.000493f, 0.000669f, 0.001040f, 0.001076f, 0.001254f, 0.001398f,
+ 0.001603f, 0.001697f, 0.001987f, 0.002140f, 0.002268f, 0.002472f, 0.002769f, 0.002991f, 0.003302f, 0.003572f, 0.003685f, 0.004002f,
+ 0.004337f, 0.004654f, 0.005062f, 0.005379f, 0.005871f, 0.006363f, 0.006733f, 0.007416f, 0.008102f, 0.008812f, 0.009727f, 0.010689f,
+ 0.011566f, 0.013145f, 0.014053f, 0.015762f, 0.017899f, 0.020096f, 0.022552f, 0.025528f, 0.028992f, 0.033325f, 0.038635f, 0.044952f,
+ 0.052582f, 0.061554f, 0.072998f, 0.086670f, 0.103577f, 0.124329f, 0.148804f, 0.178467f, 0.213501f, 0.253174f, 0.298828f, 0.348877f,
+ 0.403076f, 0.461914f, 0.795898f, 0.809570f, 0.812012f, 0.813477f, 0.813477f, 0.814453f, 0.000243f, 0.000322f, 0.000466f, 0.000710f,
+ 0.000863f, 0.000942f, 0.001051f, 0.001182f, 0.001369f, 0.001451f, 0.001716f, 0.001851f, 0.001968f, 0.002192f, 0.002323f, 0.002470f,
+ 0.002773f, 0.002850f, 0.003056f, 0.003399f, 0.003624f, 0.003832f, 0.004192f, 0.004467f, 0.004955f, 0.005276f, 0.005772f, 0.006084f,
+ 0.006672f, 0.007191f, 0.007828f, 0.008720f, 0.009575f, 0.010292f, 0.011505f, 0.012535f, 0.014114f, 0.016006f, 0.017838f, 0.020462f,
+ 0.023193f, 0.026489f, 0.030807f, 0.035858f, 0.041840f, 0.049652f, 0.059174f, 0.070435f, 0.084839f, 0.102783f, 0.124146f, 0.151489f,
+ 0.183472f, 0.221802f, 0.265137f, 0.315186f, 0.369629f, 0.430664f, 0.782715f, 0.796875f, 0.799805f, 0.800293f, 0.801758f, 0.801758f,
+ 0.000119f, 0.000369f, 0.000340f, 0.000595f, 0.000667f, 0.000841f, 0.001010f, 0.001086f, 0.001179f, 0.001225f, 0.001494f, 0.001555f,
+ 0.001654f, 0.001754f, 0.001965f, 0.002142f, 0.002197f, 0.002432f, 0.002619f, 0.002811f, 0.003021f, 0.003139f, 0.003567f, 0.003708f,
+ 0.004066f, 0.004360f, 0.004612f, 0.005123f, 0.005489f, 0.005878f, 0.006306f, 0.006824f, 0.007576f, 0.008286f, 0.008949f, 0.010155f,
+ 0.011322f, 0.012756f, 0.014046f, 0.015976f, 0.018250f, 0.020874f, 0.024094f, 0.027878f, 0.032867f, 0.039154f, 0.046509f, 0.055908f,
+ 0.068054f, 0.082886f, 0.102356f, 0.125732f, 0.155029f, 0.190674f, 0.232422f, 0.281006f, 0.335693f, 0.397949f, 0.770020f, 0.783691f,
+ 0.786621f, 0.787598f, 0.788086f, 0.789551f, 0.000000f, 0.000220f, 0.000275f, 0.000562f, 0.000618f, 0.000683f, 0.000733f, 0.000761f,
+ 0.000966f, 0.001022f, 0.001184f, 0.001237f, 0.001382f, 0.001552f, 0.001688f, 0.001724f, 0.001918f, 0.002024f, 0.002115f, 0.002243f,
+ 0.002403f, 0.002718f, 0.002840f, 0.003052f, 0.003330f, 0.003508f, 0.003860f, 0.004097f, 0.004314f, 0.004719f, 0.005074f, 0.005535f,
+ 0.006058f, 0.006584f, 0.007168f, 0.007874f, 0.008759f, 0.009651f, 0.011086f, 0.012459f, 0.013992f, 0.015945f, 0.018433f, 0.021408f,
+ 0.025192f, 0.029861f, 0.035950f, 0.043396f, 0.053406f, 0.065735f, 0.082031f, 0.102234f, 0.128052f, 0.160645f, 0.200073f, 0.247192f,
+ 0.301025f, 0.363281f, 0.755371f, 0.770996f, 0.772949f, 0.773926f, 0.775879f, 0.775879f, 0.000216f, 0.000102f, 0.000381f, 0.000487f,
+ 0.000429f, 0.000552f, 0.000579f, 0.000788f, 0.000804f, 0.000854f, 0.000937f, 0.000996f, 0.001078f, 0.001218f, 0.001315f, 0.001499f,
+ 0.001532f, 0.001642f, 0.001805f, 0.001825f, 0.002077f, 0.002178f, 0.002312f, 0.002396f, 0.002575f, 0.002735f, 0.002947f, 0.003317f,
+ 0.003428f, 0.003721f, 0.004185f, 0.004379f, 0.004704f, 0.005253f, 0.005650f, 0.006145f, 0.006870f, 0.007515f, 0.008415f, 0.009430f,
+ 0.010612f, 0.012093f, 0.013954f, 0.016052f, 0.018967f, 0.022476f, 0.027115f, 0.032898f, 0.040649f, 0.050690f, 0.063599f, 0.080811f,
+ 0.103210f, 0.132202f, 0.168823f, 0.213501f, 0.266602f, 0.329102f, 0.740234f, 0.756348f, 0.758789f, 0.760254f, 0.761230f, 0.761230f,
+ 0.000179f, 0.000181f, 0.000180f, 0.000289f, 0.000413f, 0.000458f, 0.000497f, 0.000620f, 0.000646f, 0.000688f, 0.000830f, 0.000868f,
+ 0.000904f, 0.000981f, 0.001024f, 0.001178f, 0.001146f, 0.001302f, 0.001382f, 0.001523f, 0.001679f, 0.001737f, 0.001824f, 0.001959f,
+ 0.002195f, 0.002283f, 0.002438f, 0.002579f, 0.002703f, 0.002939f, 0.003181f, 0.003454f, 0.003677f, 0.004051f, 0.004395f, 0.004738f,
+ 0.005283f, 0.005783f, 0.006420f, 0.007095f, 0.007988f, 0.009094f, 0.010384f, 0.011955f, 0.013939f, 0.016434f, 0.019836f, 0.024292f,
+ 0.030029f, 0.037659f, 0.048065f, 0.061890f, 0.080811f, 0.105774f, 0.138672f, 0.180542f, 0.231934f, 0.293213f, 0.724121f, 0.740234f,
+ 0.744141f, 0.745117f, 0.745605f, 0.746094f, 0.000000f, 0.000056f, 0.000263f, 0.000339f, 0.000369f, 0.000357f, 0.000376f, 0.000508f,
+ 0.000519f, 0.000558f, 0.000581f, 0.000678f, 0.000767f, 0.000775f, 0.000905f, 0.000849f, 0.000992f, 0.000942f, 0.001192f, 0.001169f,
+ 0.001204f, 0.001375f, 0.001439f, 0.001532f, 0.001634f, 0.001676f, 0.001799f, 0.001904f, 0.002165f, 0.002262f, 0.002377f, 0.002611f,
+ 0.002836f, 0.003103f, 0.003321f, 0.003550f, 0.004005f, 0.004356f, 0.004772f, 0.005295f, 0.005962f, 0.006756f, 0.007690f, 0.008690f,
+ 0.010078f, 0.011871f, 0.014252f, 0.017242f, 0.021393f, 0.027100f, 0.034851f, 0.046051f, 0.060455f, 0.081848f, 0.110474f, 0.148682f,
+ 0.197632f, 0.257568f, 0.706543f, 0.724121f, 0.727539f, 0.729492f, 0.729980f, 0.729492f, 0.000000f, 0.000130f, 0.000174f, 0.000312f,
+ 0.000290f, 0.000293f, 0.000372f, 0.000319f, 0.000397f, 0.000433f, 0.000550f, 0.000552f, 0.000564f, 0.000593f, 0.000638f, 0.000758f,
+ 0.000784f, 0.000797f, 0.000842f, 0.000937f, 0.001011f, 0.001068f, 0.001125f, 0.001231f, 0.001228f, 0.001288f, 0.001409f, 0.001465f,
+ 0.001644f, 0.001697f, 0.001965f, 0.001924f, 0.002136f, 0.002270f, 0.002436f, 0.002697f, 0.002916f, 0.003202f, 0.003492f, 0.003929f,
+ 0.004391f, 0.004887f, 0.005516f, 0.006233f, 0.007240f, 0.008461f, 0.010094f, 0.012070f, 0.014854f, 0.018585f, 0.024338f, 0.032379f,
+ 0.043884f, 0.060516f, 0.084656f, 0.118469f, 0.164185f, 0.222168f, 0.689941f, 0.708008f, 0.710449f, 0.711914f, 0.712891f, 0.712402f,
+ 0.000000f, 0.000000f, 0.000122f, 0.000226f, 0.000145f, 0.000282f, 0.000255f, 0.000247f, 0.000323f, 0.000389f, 0.000379f, 0.000435f,
+ 0.000461f, 0.000509f, 0.000535f, 0.000517f, 0.000557f, 0.000604f, 0.000649f, 0.000690f, 0.000757f, 0.000773f, 0.000836f, 0.000865f,
+ 0.000924f, 0.000957f, 0.001095f, 0.001104f, 0.001243f, 0.001361f, 0.001458f, 0.001486f, 0.001619f, 0.001745f, 0.001791f, 0.001993f,
+ 0.002100f, 0.002321f, 0.002539f, 0.002771f, 0.003084f, 0.003412f, 0.003866f, 0.004368f, 0.005062f, 0.005821f, 0.006882f, 0.008278f,
+ 0.010071f, 0.012756f, 0.016327f, 0.021774f, 0.029785f, 0.042206f, 0.061462f, 0.090149f, 0.131348f, 0.187378f, 0.669434f, 0.688965f,
+ 0.692383f, 0.694824f, 0.695801f, 0.695312f, 0.000000f, 0.000118f, 0.000113f, 0.000158f, 0.000158f, 0.000176f, 0.000224f, 0.000202f,
+ 0.000251f, 0.000260f, 0.000280f, 0.000332f, 0.000316f, 0.000365f, 0.000389f, 0.000419f, 0.000454f, 0.000435f, 0.000476f, 0.000494f,
+ 0.000516f, 0.000576f, 0.000609f, 0.000656f, 0.000678f, 0.000712f, 0.000792f, 0.000800f, 0.000852f, 0.000919f, 0.000961f, 0.001070f,
+ 0.001120f, 0.001238f, 0.001300f, 0.001480f, 0.001459f, 0.001634f, 0.001798f, 0.001947f, 0.002111f, 0.002377f, 0.002615f, 0.002966f,
+ 0.003410f, 0.003933f, 0.004585f, 0.005489f, 0.006706f, 0.008148f, 0.010757f, 0.013962f, 0.019257f, 0.027771f, 0.041931f, 0.065125f,
+ 0.101135f, 0.152832f, 0.650391f, 0.670898f, 0.674316f, 0.675293f, 0.675781f, 0.677246f, 0.000000f, 0.000000f, 0.000109f, 0.000106f,
+ 0.000121f, 0.000117f, 0.000130f, 0.000151f, 0.000161f, 0.000174f, 0.000234f, 0.000197f, 0.000205f, 0.000236f, 0.000272f, 0.000296f,
+ 0.000267f, 0.000296f, 0.000397f, 0.000344f, 0.000413f, 0.000395f, 0.000433f, 0.000434f, 0.000504f, 0.000488f, 0.000532f, 0.000550f,
+ 0.000602f, 0.000711f, 0.000675f, 0.000704f, 0.000752f, 0.000817f, 0.000896f, 0.000955f, 0.001009f, 0.001091f, 0.001223f, 0.001271f,
+ 0.001415f, 0.001560f, 0.001721f, 0.001989f, 0.002214f, 0.002508f, 0.002930f, 0.003504f, 0.004208f, 0.005169f, 0.006603f, 0.008606f,
+ 0.011864f, 0.017090f, 0.026367f, 0.043396f, 0.072571f, 0.119751f, 0.630859f, 0.650879f, 0.653809f, 0.656250f, 0.657227f, 0.657227f,
+ 0.000000f, 0.000111f, 0.000104f, 0.000100f, 0.000096f, 0.000094f, 0.000105f, 0.000096f, 0.000101f, 0.000115f, 0.000119f, 0.000155f,
+ 0.000129f, 0.000180f, 0.000186f, 0.000199f, 0.000208f, 0.000214f, 0.000232f, 0.000230f, 0.000237f, 0.000247f, 0.000303f, 0.000276f,
+ 0.000324f, 0.000332f, 0.000381f, 0.000371f, 0.000393f, 0.000428f, 0.000490f, 0.000468f, 0.000512f, 0.000540f, 0.000598f, 0.000670f,
+ 0.000673f, 0.000711f, 0.000767f, 0.000842f, 0.000894f, 0.000985f, 0.001120f, 0.001200f, 0.001416f, 0.001544f, 0.001768f, 0.002052f,
+ 0.002510f, 0.003044f, 0.003796f, 0.005016f, 0.006870f, 0.009918f, 0.015335f, 0.026077f, 0.048004f, 0.088745f, 0.610352f, 0.630859f,
+ 0.634277f, 0.636230f, 0.637207f, 0.638184f, 0.000000f, 0.000104f, 0.000098f, 0.000092f, 0.000087f, 0.000084f, 0.000081f, 0.000078f,
+ 0.000074f, 0.000070f, 0.000073f, 0.000075f, 0.000081f, 0.000081f, 0.000119f, 0.000124f, 0.000129f, 0.000115f, 0.000142f, 0.000169f,
+ 0.000155f, 0.000169f, 0.000172f, 0.000196f, 0.000209f, 0.000211f, 0.000203f, 0.000238f, 0.000245f, 0.000260f, 0.000282f, 0.000281f,
+ 0.000297f, 0.000333f, 0.000343f, 0.000374f, 0.000398f, 0.000428f, 0.000473f, 0.000494f, 0.000534f, 0.000591f, 0.000643f, 0.000708f,
+ 0.000790f, 0.000893f, 0.001040f, 0.001169f, 0.001381f, 0.001676f, 0.002123f, 0.002686f, 0.003658f, 0.005329f, 0.008347f, 0.014244f,
+ 0.027954f, 0.060638f, 0.587891f, 0.609375f, 0.613281f, 0.614746f, 0.616699f, 0.616211f, 0.000110f, 0.000094f, 0.000085f, 0.000079f,
+ 0.000075f, 0.000072f, 0.000069f, 0.000067f, 0.000065f, 0.000063f, 0.000059f, 0.000059f, 0.000054f, 0.000051f, 0.000055f, 0.000051f,
+ 0.000066f, 0.000066f, 0.000078f, 0.000074f, 0.000089f, 0.000091f, 0.000102f, 0.000109f, 0.000114f, 0.000126f, 0.000133f, 0.000130f,
+ 0.000141f, 0.000141f, 0.000156f, 0.000172f, 0.000180f, 0.000179f, 0.000206f, 0.000199f, 0.000214f, 0.000254f, 0.000247f, 0.000282f,
+ 0.000300f, 0.000324f, 0.000349f, 0.000374f, 0.000413f, 0.000459f, 0.000513f, 0.000619f, 0.000711f, 0.000823f, 0.001030f, 0.001269f,
+ 0.001724f, 0.002487f, 0.003948f, 0.007015f, 0.014122f, 0.036346f, 0.565430f, 0.586426f, 0.592285f, 0.592773f, 0.594238f, 0.594727f,
+ 0.000092f, 0.000073f, 0.000067f, 0.000062f, 0.000057f, 0.000055f, 0.000052f, 0.000052f, 0.000049f, 0.000049f, 0.000047f, 0.000046f,
+ 0.000046f, 0.000043f, 0.000041f, 0.000039f, 0.000038f, 0.000036f, 0.000039f, 0.000036f, 0.000039f, 0.000037f, 0.000039f, 0.000047f,
+ 0.000051f, 0.000057f, 0.000059f, 0.000060f, 0.000067f, 0.000071f, 0.000078f, 0.000085f, 0.000087f, 0.000091f, 0.000098f, 0.000095f,
+ 0.000102f, 0.000122f, 0.000122f, 0.000137f, 0.000143f, 0.000145f, 0.000168f, 0.000171f, 0.000197f, 0.000209f, 0.000234f, 0.000264f,
+ 0.000295f, 0.000349f, 0.000418f, 0.000520f, 0.000678f, 0.000958f, 0.001512f, 0.002745f, 0.006092f, 0.017456f, 0.542969f, 0.565430f,
+ 0.568848f, 0.569824f, 0.572266f, 0.572266f, 0.000052f, 0.000042f, 0.000037f, 0.000035f, 0.000033f, 0.000033f, 0.000032f, 0.000031f,
+ 0.000031f, 0.000029f, 0.000030f, 0.000030f, 0.000029f, 0.000028f, 0.000028f, 0.000028f, 0.000028f, 0.000028f, 0.000027f, 0.000026f,
+ 0.000024f, 0.000023f, 0.000022f, 0.000022f, 0.000021f, 0.000020f, 0.000019f, 0.000022f, 0.000020f, 0.000023f, 0.000024f, 0.000026f,
+ 0.000028f, 0.000035f, 0.000037f, 0.000038f, 0.000039f, 0.000043f, 0.000048f, 0.000050f, 0.000053f, 0.000055f, 0.000062f, 0.000059f,
+ 0.000072f, 0.000070f, 0.000087f, 0.000099f, 0.000100f, 0.000119f, 0.000142f, 0.000162f, 0.000217f, 0.000283f, 0.000425f, 0.000760f,
+ 0.001818f, 0.006405f, 0.519043f, 0.541504f, 0.546387f, 0.548828f, 0.549316f, 0.550781f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000004f, 0.000006f, 0.000006f, 0.000008f, 0.000009f, 0.000009f, 0.000009f, 0.000010f,
+ 0.000010f, 0.000010f, 0.000011f, 0.000011f, 0.000011f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000013f, 0.000012f, 0.000012f,
+ 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000008f, 0.000011f,
+ 0.000011f, 0.000012f, 0.000015f, 0.000016f, 0.000016f, 0.000018f, 0.000018f, 0.000020f, 0.000022f, 0.000024f, 0.000028f, 0.000035f,
+ 0.000036f, 0.000052f, 0.000071f, 0.000117f, 0.000260f, 0.001269f, 0.495605f, 0.518555f, 0.523926f, 0.525879f, 0.526855f, 0.527344f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000005f, 0.000021f, 0.473145f, 0.495605f,
+ 0.500000f, 0.502441f, 0.503418f, 0.503906f,
+ },
+ {
+ 0.045868f, 0.130493f, 0.205322f, 0.272705f, 0.331787f, 0.384521f, 0.431885f, 0.473389f, 0.511719f, 0.545898f, 0.576660f, 0.605469f,
+ 0.631348f, 0.654785f, 0.676758f, 0.696289f, 0.714355f, 0.732422f, 0.749023f, 0.763184f, 0.777832f, 0.790527f, 0.802734f, 0.813477f,
+ 0.824219f, 0.834961f, 0.844238f, 0.853027f, 0.862305f, 0.869629f, 0.877441f, 0.884277f, 0.892090f, 0.898926f, 0.904297f, 0.910645f,
+ 0.916992f, 0.921875f, 0.926758f, 0.931641f, 0.937012f, 0.941406f, 0.945801f, 0.950195f, 0.954102f, 0.958496f, 0.962402f, 0.966309f,
+ 0.969238f, 0.973145f, 0.976074f, 0.979492f, 0.982422f, 0.985352f, 0.988281f, 0.991211f, 0.993652f, 0.996094f, 0.997070f, 0.993164f,
+ 0.990234f, 0.987305f, 0.984375f, 0.981445f, 0.033447f, 0.097717f, 0.160400f, 0.219238f, 0.273438f, 0.323486f, 0.371582f, 0.414062f,
+ 0.454834f, 0.491211f, 0.524414f, 0.555176f, 0.583984f, 0.610840f, 0.635254f, 0.658203f, 0.678223f, 0.697754f, 0.716309f, 0.732422f,
+ 0.749023f, 0.763184f, 0.776855f, 0.790527f, 0.802734f, 0.812988f, 0.824707f, 0.834473f, 0.844238f, 0.853516f, 0.862305f, 0.870117f,
+ 0.877930f, 0.884766f, 0.892090f, 0.897949f, 0.905762f, 0.910645f, 0.917480f, 0.923340f, 0.927734f, 0.933105f, 0.937988f, 0.942871f,
+ 0.947266f, 0.951172f, 0.955566f, 0.960449f, 0.963379f, 0.967285f, 0.970703f, 0.974609f, 0.978027f, 0.981445f, 0.984863f, 0.986816f,
+ 0.989746f, 0.993164f, 0.995605f, 0.992188f, 0.988770f, 0.986328f, 0.983398f, 0.980957f, 0.024796f, 0.075195f, 0.126221f, 0.176025f,
+ 0.224976f, 0.271729f, 0.317383f, 0.359375f, 0.399902f, 0.437744f, 0.472656f, 0.505371f, 0.536133f, 0.565430f, 0.591797f, 0.615723f,
+ 0.639648f, 0.660156f, 0.681152f, 0.699219f, 0.718262f, 0.734375f, 0.749512f, 0.764648f, 0.777832f, 0.791016f, 0.802734f, 0.813965f,
+ 0.825195f, 0.835449f, 0.844727f, 0.854004f, 0.862305f, 0.871094f, 0.878418f, 0.886230f, 0.893555f, 0.900391f, 0.906738f, 0.912598f,
+ 0.917969f, 0.923828f, 0.929688f, 0.935059f, 0.939941f, 0.943848f, 0.949219f, 0.953613f, 0.958008f, 0.961914f, 0.965332f, 0.969238f,
+ 0.972656f, 0.976074f, 0.979492f, 0.982910f, 0.986328f, 0.989258f, 0.993652f, 0.990723f, 0.987793f, 0.985352f, 0.982910f, 0.979980f,
+ 0.019119f, 0.058624f, 0.100220f, 0.142578f, 0.185303f, 0.227417f, 0.269287f, 0.310059f, 0.348877f, 0.385254f, 0.421875f, 0.455566f,
+ 0.489014f, 0.518555f, 0.546875f, 0.574707f, 0.598633f, 0.624023f, 0.645508f, 0.666016f, 0.684082f, 0.702637f, 0.720703f, 0.736816f,
+ 0.751465f, 0.766113f, 0.779785f, 0.792969f, 0.804199f, 0.815918f, 0.826660f, 0.836426f, 0.846191f, 0.855957f, 0.864746f, 0.872559f,
+ 0.880371f, 0.888184f, 0.895508f, 0.902344f, 0.908691f, 0.914062f, 0.919922f, 0.925293f, 0.932129f, 0.936035f, 0.941895f, 0.946289f,
+ 0.951172f, 0.955566f, 0.959473f, 0.963867f, 0.967773f, 0.970703f, 0.975586f, 0.978516f, 0.981934f, 0.985352f, 0.991699f, 0.988770f,
+ 0.986328f, 0.983887f, 0.981445f, 0.979004f, 0.015175f, 0.046997f, 0.080688f, 0.116028f, 0.152466f, 0.189819f, 0.227417f, 0.264404f,
+ 0.301758f, 0.338623f, 0.374268f, 0.407471f, 0.439941f, 0.471924f, 0.501465f, 0.529785f, 0.556641f, 0.582031f, 0.606445f, 0.629395f,
+ 0.649902f, 0.670898f, 0.688965f, 0.708496f, 0.725098f, 0.740723f, 0.755371f, 0.769531f, 0.782715f, 0.795410f, 0.807129f, 0.818848f,
+ 0.829590f, 0.839844f, 0.849121f, 0.857910f, 0.866699f, 0.875488f, 0.882812f, 0.890625f, 0.897461f, 0.904297f, 0.910645f, 0.916992f,
+ 0.922363f, 0.928223f, 0.933594f, 0.938477f, 0.944824f, 0.949707f, 0.953613f, 0.958008f, 0.962402f, 0.966309f, 0.970703f, 0.974121f,
+ 0.977539f, 0.981934f, 0.990234f, 0.987793f, 0.984863f, 0.982910f, 0.980469f, 0.978516f, 0.012215f, 0.038452f, 0.066101f, 0.095825f,
+ 0.126831f, 0.159180f, 0.192749f, 0.226685f, 0.260986f, 0.294922f, 0.328857f, 0.363037f, 0.394531f, 0.426270f, 0.457520f, 0.486572f,
+ 0.514648f, 0.541016f, 0.567871f, 0.590820f, 0.614746f, 0.636230f, 0.657227f, 0.676270f, 0.694336f, 0.711914f, 0.729492f, 0.744141f,
+ 0.759277f, 0.773438f, 0.786621f, 0.798340f, 0.811523f, 0.822266f, 0.833496f, 0.842773f, 0.851562f, 0.861816f, 0.869629f, 0.878418f,
+ 0.885742f, 0.893066f, 0.900879f, 0.907715f, 0.913574f, 0.919922f, 0.925781f, 0.932129f, 0.937012f, 0.942871f, 0.946777f, 0.951660f,
+ 0.957031f, 0.960938f, 0.965332f, 0.969727f, 0.973633f, 0.977051f, 0.988281f, 0.986328f, 0.983887f, 0.981445f, 0.979492f, 0.976562f,
+ 0.009903f, 0.031525f, 0.054626f, 0.078979f, 0.105408f, 0.133789f, 0.162720f, 0.192993f, 0.224976f, 0.256592f, 0.288330f, 0.320312f,
+ 0.352295f, 0.383545f, 0.414062f, 0.443848f, 0.473389f, 0.500488f, 0.526367f, 0.553223f, 0.577637f, 0.600586f, 0.622070f, 0.644043f,
+ 0.664551f, 0.683105f, 0.701660f, 0.718262f, 0.734375f, 0.750000f, 0.764648f, 0.778320f, 0.791016f, 0.802734f, 0.815430f, 0.826172f,
+ 0.836426f, 0.845703f, 0.855957f, 0.864258f, 0.874023f, 0.881348f, 0.889648f, 0.896973f, 0.904297f, 0.911621f, 0.917480f, 0.922852f,
+ 0.929199f, 0.935059f, 0.939941f, 0.944824f, 0.950195f, 0.954590f, 0.959961f, 0.964355f, 0.968262f, 0.972656f, 0.986328f, 0.984375f,
+ 0.981934f, 0.979980f, 0.978027f, 0.975586f, 0.008385f, 0.026154f, 0.045319f, 0.066467f, 0.089111f, 0.113220f, 0.138916f, 0.165405f,
+ 0.192871f, 0.222290f, 0.252197f, 0.281494f, 0.311279f, 0.342285f, 0.372314f, 0.402832f, 0.431641f, 0.459473f, 0.486572f, 0.513672f,
+ 0.539062f, 0.562988f, 0.587402f, 0.609863f, 0.631348f, 0.652344f, 0.671875f, 0.689941f, 0.708008f, 0.724609f, 0.740234f, 0.755371f,
+ 0.768066f, 0.783203f, 0.795410f, 0.808105f, 0.819336f, 0.830078f, 0.840332f, 0.851074f, 0.860352f, 0.869141f, 0.877930f, 0.885742f,
+ 0.893555f, 0.900879f, 0.907715f, 0.915039f, 0.920410f, 0.926758f, 0.933105f, 0.938965f, 0.944336f, 0.949707f, 0.953613f, 0.958984f,
+ 0.962891f, 0.967285f, 0.984375f, 0.982910f, 0.980957f, 0.978516f, 0.976562f, 0.974609f, 0.006992f, 0.022324f, 0.038544f, 0.056396f,
+ 0.075317f, 0.095947f, 0.117981f, 0.141968f, 0.166504f, 0.192627f, 0.219238f, 0.246704f, 0.275879f, 0.304443f, 0.333252f, 0.362305f,
+ 0.390869f, 0.419678f, 0.447266f, 0.474121f, 0.500977f, 0.525879f, 0.551270f, 0.574219f, 0.597656f, 0.620117f, 0.641602f, 0.661133f,
+ 0.680664f, 0.698242f, 0.715332f, 0.731934f, 0.746582f, 0.761230f, 0.775391f, 0.789551f, 0.802246f, 0.813477f, 0.825195f, 0.835938f,
+ 0.846191f, 0.855957f, 0.865723f, 0.873535f, 0.882324f, 0.890625f, 0.898438f, 0.905762f, 0.912598f, 0.918945f, 0.925781f, 0.931641f,
+ 0.937012f, 0.943848f, 0.948730f, 0.954102f, 0.957520f, 0.963379f, 0.981934f, 0.980957f, 0.979004f, 0.977051f, 0.975098f, 0.973145f,
+ 0.006260f, 0.018387f, 0.032684f, 0.047821f, 0.064636f, 0.082153f, 0.101318f, 0.122009f, 0.143921f, 0.166870f, 0.191406f, 0.216187f,
+ 0.243164f, 0.269287f, 0.297119f, 0.324951f, 0.352783f, 0.380859f, 0.408691f, 0.435547f, 0.462402f, 0.489258f, 0.514160f, 0.540039f,
+ 0.563965f, 0.585938f, 0.608398f, 0.629395f, 0.649414f, 0.669434f, 0.689453f, 0.705566f, 0.722656f, 0.739258f, 0.753418f, 0.769043f,
+ 0.783203f, 0.795898f, 0.807617f, 0.819824f, 0.830566f, 0.842285f, 0.852051f, 0.862305f, 0.871094f, 0.878906f, 0.888184f, 0.895996f,
+ 0.902832f, 0.910645f, 0.917480f, 0.924316f, 0.930176f, 0.936523f, 0.942383f, 0.946777f, 0.953613f, 0.958496f, 0.979980f, 0.979004f,
+ 0.977539f, 0.975586f, 0.973633f, 0.972168f, 0.005268f, 0.016418f, 0.028091f, 0.041107f, 0.055420f, 0.070435f, 0.087341f, 0.105347f,
+ 0.124512f, 0.144531f, 0.166260f, 0.189453f, 0.213989f, 0.238037f, 0.263184f, 0.290039f, 0.317139f, 0.344238f, 0.370850f, 0.398438f,
+ 0.425293f, 0.451660f, 0.477539f, 0.503418f, 0.528320f, 0.551270f, 0.576172f, 0.598145f, 0.619629f, 0.640137f, 0.659668f, 0.680176f,
+ 0.697754f, 0.714844f, 0.731934f, 0.748047f, 0.762695f, 0.776367f, 0.790039f, 0.803223f, 0.814453f, 0.827148f, 0.837891f, 0.847656f,
+ 0.858398f, 0.868164f, 0.876953f, 0.885742f, 0.893066f, 0.901855f, 0.908691f, 0.916504f, 0.922852f, 0.929199f, 0.935059f, 0.941895f,
+ 0.947754f, 0.953125f, 0.978027f, 0.977539f, 0.975586f, 0.973633f, 0.971680f, 0.969727f, 0.004372f, 0.013802f, 0.024185f, 0.036011f,
+ 0.047729f, 0.060944f, 0.075684f, 0.090820f, 0.107788f, 0.125488f, 0.144653f, 0.165771f, 0.187012f, 0.210205f, 0.233643f, 0.258545f,
+ 0.283447f, 0.309326f, 0.335449f, 0.362305f, 0.388672f, 0.415771f, 0.441650f, 0.468018f, 0.492920f, 0.518066f, 0.542480f, 0.564941f,
+ 0.587891f, 0.609863f, 0.630859f, 0.651855f, 0.670898f, 0.689453f, 0.707520f, 0.724609f, 0.740723f, 0.755859f, 0.770996f, 0.785156f,
+ 0.799316f, 0.809570f, 0.822754f, 0.834473f, 0.845215f, 0.855469f, 0.865723f, 0.874023f, 0.883301f, 0.892090f, 0.899902f, 0.907715f,
+ 0.915039f, 0.922363f, 0.928711f, 0.935059f, 0.941406f, 0.947266f, 0.975586f, 0.975098f, 0.973633f, 0.971680f, 0.969727f, 0.968262f,
+ 0.003809f, 0.012253f, 0.021240f, 0.030884f, 0.041473f, 0.052887f, 0.065308f, 0.079224f, 0.094177f, 0.109558f, 0.126709f, 0.145142f,
+ 0.163940f, 0.184814f, 0.207397f, 0.229736f, 0.252686f, 0.276855f, 0.302246f, 0.327881f, 0.353271f, 0.380127f, 0.405762f, 0.432129f,
+ 0.457520f, 0.482422f, 0.507324f, 0.531250f, 0.556152f, 0.578125f, 0.600586f, 0.622559f, 0.642578f, 0.662109f, 0.681641f, 0.700195f,
+ 0.716797f, 0.734375f, 0.750000f, 0.766113f, 0.779297f, 0.793457f, 0.807129f, 0.819336f, 0.830078f, 0.842285f, 0.853027f, 0.862793f,
+ 0.872559f, 0.881348f, 0.890625f, 0.899414f, 0.907227f, 0.914551f, 0.920898f, 0.928223f, 0.935059f, 0.941406f, 0.973633f, 0.973145f,
+ 0.971680f, 0.970215f, 0.968262f, 0.966797f, 0.003462f, 0.010796f, 0.018646f, 0.026962f, 0.036377f, 0.046173f, 0.057190f, 0.068665f,
+ 0.081726f, 0.095520f, 0.110962f, 0.127563f, 0.144897f, 0.162476f, 0.182373f, 0.202881f, 0.225342f, 0.248291f, 0.271729f, 0.294922f,
+ 0.320312f, 0.345459f, 0.370850f, 0.397217f, 0.422607f, 0.447998f, 0.473145f, 0.498291f, 0.522461f, 0.546875f, 0.569824f, 0.591797f,
+ 0.614258f, 0.635742f, 0.655273f, 0.674805f, 0.693359f, 0.711426f, 0.729492f, 0.745605f, 0.760742f, 0.775391f, 0.789551f, 0.803223f,
+ 0.816406f, 0.828125f, 0.839844f, 0.850586f, 0.861328f, 0.871094f, 0.880371f, 0.889648f, 0.898438f, 0.906250f, 0.915039f, 0.921875f,
+ 0.928223f, 0.935547f, 0.970703f, 0.970215f, 0.970215f, 0.967773f, 0.966309f, 0.965332f, 0.002872f, 0.009338f, 0.016174f, 0.024231f,
+ 0.031525f, 0.040558f, 0.050140f, 0.060455f, 0.071472f, 0.084167f, 0.097168f, 0.111450f, 0.127197f, 0.143433f, 0.160889f, 0.179565f,
+ 0.199463f, 0.220825f, 0.242554f, 0.265625f, 0.288818f, 0.312744f, 0.338135f, 0.362793f, 0.387939f, 0.414307f, 0.439453f, 0.464355f,
+ 0.489014f, 0.514648f, 0.537598f, 0.561523f, 0.583984f, 0.606445f, 0.627930f, 0.648926f, 0.667480f, 0.687988f, 0.705566f, 0.723633f,
+ 0.740234f, 0.756348f, 0.771484f, 0.786621f, 0.799805f, 0.812012f, 0.825195f, 0.836426f, 0.849121f, 0.859375f, 0.870605f, 0.879883f,
+ 0.888672f, 0.897461f, 0.905762f, 0.915039f, 0.921387f, 0.928711f, 0.967773f, 0.969238f, 0.966797f, 0.966797f, 0.964355f, 0.963379f,
+ 0.002750f, 0.008202f, 0.014519f, 0.021301f, 0.028183f, 0.035828f, 0.044342f, 0.053375f, 0.063354f, 0.074219f, 0.085876f, 0.098083f,
+ 0.111938f, 0.126343f, 0.142212f, 0.158936f, 0.177124f, 0.196411f, 0.216553f, 0.237427f, 0.260010f, 0.282715f, 0.306641f, 0.330811f,
+ 0.355957f, 0.381104f, 0.405518f, 0.431152f, 0.456543f, 0.480957f, 0.504883f, 0.529785f, 0.553223f, 0.577148f, 0.599121f, 0.620605f,
+ 0.642090f, 0.662598f, 0.682617f, 0.701172f, 0.718750f, 0.735352f, 0.751953f, 0.768066f, 0.783691f, 0.796875f, 0.810547f, 0.822754f,
+ 0.835938f, 0.847656f, 0.858398f, 0.869141f, 0.879395f, 0.888672f, 0.897949f, 0.906250f, 0.914551f, 0.922363f, 0.965820f, 0.966797f,
+ 0.965820f, 0.963867f, 0.963379f, 0.961426f, 0.002264f, 0.007446f, 0.012741f, 0.018494f, 0.024536f, 0.031769f, 0.039154f, 0.047424f,
+ 0.056122f, 0.065308f, 0.075623f, 0.087219f, 0.098755f, 0.111328f, 0.125854f, 0.140869f, 0.157349f, 0.174805f, 0.193115f, 0.212402f,
+ 0.233643f, 0.254883f, 0.276855f, 0.300293f, 0.324463f, 0.348389f, 0.374023f, 0.398193f, 0.423340f, 0.448242f, 0.473877f, 0.498291f,
+ 0.521973f, 0.545898f, 0.569824f, 0.592773f, 0.614258f, 0.635742f, 0.657227f, 0.676270f, 0.695801f, 0.714844f, 0.731445f, 0.749512f,
+ 0.765137f, 0.779785f, 0.793945f, 0.808594f, 0.821777f, 0.833496f, 0.846191f, 0.858398f, 0.868652f, 0.879395f, 0.888672f, 0.897949f,
+ 0.906738f, 0.916016f, 0.962402f, 0.963867f, 0.962891f, 0.961914f, 0.960938f, 0.958984f, 0.002377f, 0.006668f, 0.011467f, 0.016693f,
+ 0.021820f, 0.028091f, 0.034485f, 0.041748f, 0.049347f, 0.057678f, 0.066589f, 0.076538f, 0.086975f, 0.098816f, 0.111816f, 0.125366f,
+ 0.139404f, 0.155151f, 0.171875f, 0.190186f, 0.208496f, 0.228760f, 0.250244f, 0.271973f, 0.294189f, 0.317871f, 0.341797f, 0.365479f,
+ 0.391357f, 0.415771f, 0.440430f, 0.466797f, 0.491699f, 0.515625f, 0.539551f, 0.563477f, 0.585938f, 0.608887f, 0.630371f, 0.651855f,
+ 0.672363f, 0.692383f, 0.710449f, 0.729492f, 0.745605f, 0.762695f, 0.778320f, 0.792480f, 0.807129f, 0.820801f, 0.833984f, 0.846680f,
+ 0.857910f, 0.869141f, 0.879395f, 0.889648f, 0.899414f, 0.907715f, 0.959473f, 0.961426f, 0.960449f, 0.959961f, 0.958496f, 0.957031f,
+ 0.002062f, 0.006180f, 0.010201f, 0.015053f, 0.019531f, 0.025116f, 0.030960f, 0.037292f, 0.043915f, 0.051117f, 0.059570f, 0.067749f,
+ 0.076843f, 0.087708f, 0.099060f, 0.110352f, 0.123413f, 0.138062f, 0.153198f, 0.169067f, 0.186768f, 0.204956f, 0.224487f, 0.244873f,
+ 0.265625f, 0.288330f, 0.311768f, 0.335205f, 0.359863f, 0.384521f, 0.409668f, 0.434082f, 0.459717f, 0.483887f, 0.508789f, 0.533203f,
+ 0.557617f, 0.580566f, 0.603516f, 0.626465f, 0.646484f, 0.667969f, 0.687500f, 0.708008f, 0.726074f, 0.744141f, 0.760742f, 0.776367f,
+ 0.791504f, 0.806641f, 0.820312f, 0.833496f, 0.846191f, 0.858398f, 0.869629f, 0.879883f, 0.890625f, 0.900879f, 0.956543f, 0.958496f,
+ 0.958008f, 0.956543f, 0.955566f, 0.954102f, 0.001774f, 0.005459f, 0.009155f, 0.013290f, 0.017807f, 0.022537f, 0.027527f, 0.033081f,
+ 0.038818f, 0.045380f, 0.052643f, 0.060516f, 0.068420f, 0.077942f, 0.087952f, 0.098572f, 0.109863f, 0.122925f, 0.136230f, 0.150146f,
+ 0.166382f, 0.183105f, 0.201172f, 0.219482f, 0.240112f, 0.261230f, 0.283203f, 0.305664f, 0.329590f, 0.353027f, 0.377930f, 0.402344f,
+ 0.427490f, 0.453369f, 0.478516f, 0.502930f, 0.527832f, 0.552246f, 0.575684f, 0.598145f, 0.621094f, 0.643555f, 0.664551f, 0.685547f,
+ 0.704590f, 0.723633f, 0.742188f, 0.759277f, 0.775879f, 0.791016f, 0.806152f, 0.820801f, 0.833496f, 0.847168f, 0.859375f, 0.870605f,
+ 0.881348f, 0.893066f, 0.953125f, 0.956055f, 0.955566f, 0.954102f, 0.953125f, 0.951660f, 0.001655f, 0.004757f, 0.008308f, 0.011993f,
+ 0.015808f, 0.020187f, 0.024780f, 0.029434f, 0.034851f, 0.040741f, 0.046997f, 0.053650f, 0.061096f, 0.069397f, 0.078064f, 0.087280f,
+ 0.097351f, 0.108887f, 0.121033f, 0.134277f, 0.148560f, 0.163330f, 0.180054f, 0.197144f, 0.215332f, 0.235718f, 0.255859f, 0.277588f,
+ 0.300049f, 0.323730f, 0.347656f, 0.371826f, 0.396729f, 0.422607f, 0.447021f, 0.472168f, 0.497803f, 0.521973f, 0.547363f, 0.571289f,
+ 0.594238f, 0.618164f, 0.640137f, 0.662109f, 0.682617f, 0.702637f, 0.722168f, 0.739746f, 0.758301f, 0.774902f, 0.790527f, 0.806641f,
+ 0.820801f, 0.834961f, 0.848633f, 0.860352f, 0.872559f, 0.883789f, 0.949707f, 0.953125f, 0.952148f, 0.951172f, 0.950684f, 0.948730f,
+ 0.001418f, 0.004456f, 0.007584f, 0.010803f, 0.014450f, 0.018005f, 0.022186f, 0.026398f, 0.031342f, 0.036224f, 0.041687f, 0.048126f,
+ 0.054382f, 0.061676f, 0.069641f, 0.077759f, 0.086914f, 0.097168f, 0.107910f, 0.119263f, 0.132446f, 0.145752f, 0.161011f, 0.176758f,
+ 0.193726f, 0.211914f, 0.231201f, 0.251709f, 0.272705f, 0.294922f, 0.318604f, 0.342041f, 0.366455f, 0.390869f, 0.416992f, 0.441895f,
+ 0.467285f, 0.493164f, 0.517578f, 0.541992f, 0.566895f, 0.590820f, 0.614746f, 0.637207f, 0.660156f, 0.681152f, 0.701172f, 0.720703f,
+ 0.739746f, 0.758301f, 0.775391f, 0.791992f, 0.807617f, 0.821289f, 0.836426f, 0.850586f, 0.863281f, 0.874512f, 0.946777f, 0.949707f,
+ 0.949707f, 0.948730f, 0.947266f, 0.946289f, 0.001213f, 0.003864f, 0.006721f, 0.009796f, 0.012932f, 0.016037f, 0.020218f, 0.024231f,
+ 0.028275f, 0.032379f, 0.037567f, 0.042603f, 0.048584f, 0.054993f, 0.061798f, 0.069519f, 0.077637f, 0.086182f, 0.095703f, 0.106323f,
+ 0.117676f, 0.130127f, 0.143555f, 0.158203f, 0.173462f, 0.189941f, 0.207886f, 0.226807f, 0.247192f, 0.267822f, 0.290527f, 0.312500f,
+ 0.336670f, 0.360352f, 0.385742f, 0.410889f, 0.437256f, 0.462646f, 0.488281f, 0.513184f, 0.539062f, 0.563477f, 0.588379f, 0.612305f,
+ 0.636230f, 0.657715f, 0.679199f, 0.700195f, 0.720703f, 0.740234f, 0.758301f, 0.775879f, 0.793945f, 0.809082f, 0.824219f, 0.838867f,
+ 0.852539f, 0.865234f, 0.942871f, 0.946777f, 0.946777f, 0.945312f, 0.944824f, 0.943359f, 0.001063f, 0.003754f, 0.005909f, 0.008789f,
+ 0.011780f, 0.014671f, 0.017792f, 0.021378f, 0.025238f, 0.029221f, 0.033417f, 0.038300f, 0.043488f, 0.048828f, 0.054779f, 0.061554f,
+ 0.068604f, 0.076721f, 0.085388f, 0.094482f, 0.104614f, 0.115845f, 0.128296f, 0.141113f, 0.155029f, 0.170044f, 0.186401f, 0.204224f,
+ 0.222778f, 0.242188f, 0.263916f, 0.285156f, 0.308350f, 0.331787f, 0.355957f, 0.381348f, 0.407227f, 0.432617f, 0.459229f, 0.484619f,
+ 0.509277f, 0.536133f, 0.560547f, 0.585938f, 0.609863f, 0.633301f, 0.657715f, 0.678711f, 0.699707f, 0.721191f, 0.740723f, 0.759277f,
+ 0.777344f, 0.794922f, 0.811035f, 0.826660f, 0.841797f, 0.855469f, 0.939453f, 0.943359f, 0.943359f, 0.942871f, 0.941895f, 0.940918f,
+ 0.001175f, 0.003069f, 0.005558f, 0.007912f, 0.010712f, 0.013199f, 0.016235f, 0.019547f, 0.022659f, 0.026138f, 0.030151f, 0.034424f,
+ 0.038940f, 0.044067f, 0.049255f, 0.054993f, 0.061493f, 0.068359f, 0.075928f, 0.084290f, 0.093262f, 0.103760f, 0.114319f, 0.126099f,
+ 0.138550f, 0.152466f, 0.167114f, 0.183472f, 0.200439f, 0.219238f, 0.239014f, 0.259277f, 0.281250f, 0.303711f, 0.327148f, 0.351807f,
+ 0.376709f, 0.402344f, 0.428955f, 0.453857f, 0.480713f, 0.507324f, 0.533203f, 0.558594f, 0.583984f, 0.609375f, 0.633301f, 0.656738f,
+ 0.678711f, 0.700195f, 0.722168f, 0.742188f, 0.761719f, 0.780273f, 0.797852f, 0.813477f, 0.830078f, 0.845703f, 0.935547f, 0.939453f,
+ 0.939453f, 0.938965f, 0.937988f, 0.937012f, 0.001089f, 0.002945f, 0.005066f, 0.007225f, 0.009575f, 0.012016f, 0.014656f, 0.017288f,
+ 0.020142f, 0.023712f, 0.026764f, 0.030640f, 0.034637f, 0.039490f, 0.043854f, 0.048706f, 0.054688f, 0.060913f, 0.067871f, 0.075256f,
+ 0.083191f, 0.092163f, 0.101868f, 0.111938f, 0.123657f, 0.136108f, 0.149658f, 0.164185f, 0.179932f, 0.196777f, 0.215454f, 0.234375f,
+ 0.255371f, 0.276611f, 0.299805f, 0.323486f, 0.347656f, 0.373047f, 0.398682f, 0.425293f, 0.451172f, 0.477783f, 0.504883f, 0.530762f,
+ 0.557617f, 0.583008f, 0.607910f, 0.632812f, 0.657227f, 0.680664f, 0.702637f, 0.724121f, 0.743652f, 0.764160f, 0.783691f, 0.800781f,
+ 0.818848f, 0.833984f, 0.930664f, 0.936035f, 0.936035f, 0.935547f, 0.934570f, 0.933594f, 0.000847f, 0.002800f, 0.004562f, 0.006786f,
+ 0.008804f, 0.011017f, 0.013145f, 0.015640f, 0.018509f, 0.021255f, 0.024277f, 0.027603f, 0.030991f, 0.035248f, 0.039642f, 0.043854f,
+ 0.048798f, 0.054504f, 0.060516f, 0.067017f, 0.073914f, 0.082092f, 0.090515f, 0.099854f, 0.109863f, 0.121521f, 0.133545f, 0.146851f,
+ 0.161133f, 0.176514f, 0.192993f, 0.211426f, 0.230957f, 0.251465f, 0.272705f, 0.295410f, 0.319092f, 0.343994f, 0.369385f, 0.395020f,
+ 0.421631f, 0.448242f, 0.475342f, 0.501953f, 0.529785f, 0.556152f, 0.582031f, 0.608887f, 0.633789f, 0.658203f, 0.681152f, 0.704590f,
+ 0.726074f, 0.748535f, 0.768555f, 0.787109f, 0.804199f, 0.822754f, 0.926758f, 0.931641f, 0.932129f, 0.931641f, 0.931152f, 0.930176f,
+ 0.001035f, 0.002598f, 0.004147f, 0.006062f, 0.007942f, 0.009933f, 0.012405f, 0.014565f, 0.016174f, 0.019135f, 0.021988f, 0.024811f,
+ 0.028259f, 0.031616f, 0.035065f, 0.039429f, 0.043884f, 0.048615f, 0.053833f, 0.059723f, 0.065796f, 0.072693f, 0.080383f, 0.088745f,
+ 0.098206f, 0.107727f, 0.119080f, 0.130981f, 0.143677f, 0.157959f, 0.173218f, 0.189941f, 0.207642f, 0.226929f, 0.247437f, 0.269043f,
+ 0.291748f, 0.315674f, 0.340576f, 0.366211f, 0.392578f, 0.419434f, 0.446533f, 0.473877f, 0.502441f, 0.528320f, 0.556152f, 0.583008f,
+ 0.609375f, 0.635254f, 0.660156f, 0.684082f, 0.706543f, 0.729980f, 0.751953f, 0.771973f, 0.792480f, 0.810547f, 0.922363f, 0.927734f,
+ 0.928223f, 0.928223f, 0.927246f, 0.926758f, 0.000775f, 0.002325f, 0.003843f, 0.005573f, 0.007397f, 0.009163f, 0.010857f, 0.012939f,
+ 0.015312f, 0.017273f, 0.019684f, 0.022537f, 0.025070f, 0.028183f, 0.031616f, 0.035461f, 0.038940f, 0.043671f, 0.048096f, 0.053131f,
+ 0.058411f, 0.064941f, 0.071777f, 0.078857f, 0.086731f, 0.096130f, 0.105835f, 0.116760f, 0.128296f, 0.140747f, 0.154907f, 0.170410f,
+ 0.186646f, 0.204834f, 0.223633f, 0.243896f, 0.265625f, 0.288330f, 0.312012f, 0.337402f, 0.363037f, 0.389648f, 0.417480f, 0.444824f,
+ 0.473633f, 0.500000f, 0.529297f, 0.556641f, 0.583984f, 0.610840f, 0.638184f, 0.662598f, 0.687988f, 0.711914f, 0.734375f, 0.755859f,
+ 0.777832f, 0.798828f, 0.916992f, 0.922852f, 0.923828f, 0.923828f, 0.923340f, 0.922363f, 0.000617f, 0.002234f, 0.003510f, 0.005035f,
+ 0.006397f, 0.008156f, 0.010033f, 0.011665f, 0.013481f, 0.015717f, 0.017700f, 0.020004f, 0.022766f, 0.025391f, 0.028214f, 0.031586f,
+ 0.035217f, 0.038757f, 0.042999f, 0.047668f, 0.052368f, 0.057434f, 0.063538f, 0.070190f, 0.077698f, 0.085449f, 0.094299f, 0.103394f,
+ 0.113953f, 0.125610f, 0.137817f, 0.151855f, 0.167236f, 0.183228f, 0.200806f, 0.219971f, 0.240479f, 0.262451f, 0.285645f, 0.309570f,
+ 0.334961f, 0.360596f, 0.387939f, 0.416016f, 0.444092f, 0.473145f, 0.501465f, 0.529785f, 0.558105f, 0.585938f, 0.614258f, 0.640137f,
+ 0.666992f, 0.692383f, 0.716797f, 0.739746f, 0.763184f, 0.784180f, 0.912109f, 0.918457f, 0.919434f, 0.919434f, 0.918457f, 0.917969f,
+ 0.000665f, 0.002039f, 0.003386f, 0.004520f, 0.005989f, 0.007511f, 0.009262f, 0.010902f, 0.012314f, 0.014320f, 0.015869f, 0.018127f,
+ 0.020248f, 0.022476f, 0.025284f, 0.028122f, 0.030991f, 0.034668f, 0.038239f, 0.042206f, 0.046539f, 0.051361f, 0.056610f, 0.062347f,
+ 0.068604f, 0.075623f, 0.083313f, 0.092041f, 0.101379f, 0.111572f, 0.122986f, 0.135132f, 0.148926f, 0.164062f, 0.180054f, 0.197510f,
+ 0.216797f, 0.237183f, 0.259521f, 0.282227f, 0.307129f, 0.332764f, 0.358887f, 0.386475f, 0.415527f, 0.443604f, 0.473389f, 0.501465f,
+ 0.530762f, 0.560059f, 0.588867f, 0.617676f, 0.645020f, 0.671387f, 0.698242f, 0.722656f, 0.746094f, 0.770020f, 0.906738f, 0.913574f,
+ 0.915039f, 0.914551f, 0.914062f, 0.914062f, 0.000661f, 0.001754f, 0.002831f, 0.004066f, 0.005333f, 0.006668f, 0.008286f, 0.009773f,
+ 0.011124f, 0.012794f, 0.014320f, 0.016357f, 0.018036f, 0.020386f, 0.022766f, 0.025192f, 0.027924f, 0.030807f, 0.034027f, 0.037628f,
+ 0.041321f, 0.045349f, 0.050262f, 0.055328f, 0.060699f, 0.066833f, 0.073669f, 0.081360f, 0.089600f, 0.099060f, 0.108826f, 0.119995f,
+ 0.132324f, 0.145874f, 0.160889f, 0.176880f, 0.194702f, 0.213379f, 0.234497f, 0.256104f, 0.280029f, 0.304688f, 0.330811f, 0.358154f,
+ 0.385986f, 0.415039f, 0.444092f, 0.474609f, 0.503418f, 0.534180f, 0.563965f, 0.592773f, 0.621094f, 0.650391f, 0.678223f, 0.704590f,
+ 0.730469f, 0.754883f, 0.901855f, 0.908691f, 0.910156f, 0.909668f, 0.909668f, 0.908691f, 0.000653f, 0.001667f, 0.002666f, 0.003887f,
+ 0.004986f, 0.006359f, 0.007202f, 0.008751f, 0.010300f, 0.011757f, 0.012939f, 0.014595f, 0.016281f, 0.018234f, 0.020142f, 0.022415f,
+ 0.025101f, 0.027466f, 0.030182f, 0.033539f, 0.036865f, 0.040680f, 0.044342f, 0.048798f, 0.053619f, 0.059479f, 0.065491f, 0.071716f,
+ 0.079285f, 0.087341f, 0.096497f, 0.106445f, 0.117615f, 0.129395f, 0.142822f, 0.157959f, 0.174194f, 0.192139f, 0.210938f, 0.231567f,
+ 0.253906f, 0.277832f, 0.302979f, 0.329590f, 0.357422f, 0.385986f, 0.415283f, 0.446045f, 0.475830f, 0.506348f, 0.537109f, 0.567871f,
+ 0.599121f, 0.628418f, 0.657227f, 0.685547f, 0.712891f, 0.739746f, 0.895508f, 0.902344f, 0.904297f, 0.904785f, 0.904297f, 0.904297f,
+ 0.000372f, 0.001397f, 0.002384f, 0.003529f, 0.004509f, 0.005505f, 0.007015f, 0.008026f, 0.009201f, 0.010292f, 0.011536f, 0.013130f,
+ 0.014915f, 0.016266f, 0.018387f, 0.020218f, 0.022034f, 0.024399f, 0.026901f, 0.029617f, 0.032623f, 0.035950f, 0.039032f, 0.043030f,
+ 0.047577f, 0.052612f, 0.057556f, 0.063477f, 0.070007f, 0.077209f, 0.085083f, 0.094177f, 0.103821f, 0.114563f, 0.126709f, 0.140015f,
+ 0.154785f, 0.171143f, 0.188477f, 0.208252f, 0.229004f, 0.251709f, 0.275879f, 0.302002f, 0.328613f, 0.356445f, 0.385986f, 0.416504f,
+ 0.447510f, 0.478760f, 0.510254f, 0.542480f, 0.573730f, 0.604980f, 0.635742f, 0.665527f, 0.694336f, 0.722656f, 0.887695f, 0.897949f,
+ 0.898926f, 0.899414f, 0.897949f, 0.898438f, 0.000661f, 0.001222f, 0.002275f, 0.003313f, 0.004181f, 0.005119f, 0.006275f, 0.007126f,
+ 0.007988f, 0.009354f, 0.010300f, 0.012062f, 0.013313f, 0.014786f, 0.016251f, 0.018021f, 0.019516f, 0.021896f, 0.024017f, 0.026428f,
+ 0.029022f, 0.031799f, 0.034698f, 0.038422f, 0.042236f, 0.046265f, 0.050598f, 0.055786f, 0.061493f, 0.067871f, 0.074951f, 0.082458f,
+ 0.091187f, 0.101135f, 0.111694f, 0.123779f, 0.137207f, 0.151978f, 0.167969f, 0.186157f, 0.205688f, 0.226929f, 0.249756f, 0.274658f,
+ 0.301025f, 0.328613f, 0.357178f, 0.387207f, 0.418457f, 0.450195f, 0.482422f, 0.516113f, 0.548340f, 0.580566f, 0.612305f, 0.644043f,
+ 0.674805f, 0.705566f, 0.882812f, 0.890625f, 0.892578f, 0.893066f, 0.892578f, 0.893066f, 0.000379f, 0.001211f, 0.002066f, 0.003040f,
+ 0.003834f, 0.004616f, 0.005608f, 0.006550f, 0.007347f, 0.008408f, 0.009529f, 0.010452f, 0.011940f, 0.013039f, 0.014313f, 0.015961f,
+ 0.017746f, 0.019180f, 0.021210f, 0.023239f, 0.025482f, 0.028030f, 0.030640f, 0.033661f, 0.036987f, 0.040466f, 0.044617f, 0.048828f,
+ 0.053894f, 0.059235f, 0.065674f, 0.072632f, 0.079956f, 0.089050f, 0.098267f, 0.109009f, 0.120789f, 0.134521f, 0.148926f, 0.165405f,
+ 0.183228f, 0.202881f, 0.224731f, 0.248779f, 0.273193f, 0.300049f, 0.329346f, 0.358887f, 0.390381f, 0.421387f, 0.454590f, 0.488770f,
+ 0.521484f, 0.555176f, 0.588379f, 0.621582f, 0.654785f, 0.686523f, 0.875488f, 0.885254f, 0.886719f, 0.886230f, 0.886719f, 0.886230f,
+ 0.000282f, 0.001126f, 0.002010f, 0.002661f, 0.003340f, 0.004269f, 0.005192f, 0.005711f, 0.006638f, 0.007278f, 0.008377f, 0.009483f,
+ 0.010567f, 0.011742f, 0.012871f, 0.014061f, 0.015480f, 0.017242f, 0.018799f, 0.020584f, 0.022461f, 0.024490f, 0.027100f, 0.029434f,
+ 0.032532f, 0.035706f, 0.038971f, 0.042969f, 0.047241f, 0.052094f, 0.057373f, 0.063232f, 0.070007f, 0.077637f, 0.086243f, 0.095764f,
+ 0.106323f, 0.118164f, 0.131470f, 0.146118f, 0.162720f, 0.181030f, 0.200928f, 0.223022f, 0.247070f, 0.272705f, 0.300537f, 0.330322f,
+ 0.360107f, 0.393066f, 0.426270f, 0.459473f, 0.494629f, 0.529297f, 0.564453f, 0.598633f, 0.633789f, 0.666504f, 0.868652f, 0.878418f,
+ 0.879395f, 0.880371f, 0.879883f, 0.879395f, 0.000340f, 0.000963f, 0.001826f, 0.002459f, 0.003307f, 0.003847f, 0.004719f, 0.004936f,
+ 0.005802f, 0.006695f, 0.007748f, 0.008522f, 0.009506f, 0.010376f, 0.011383f, 0.012787f, 0.013901f, 0.015182f, 0.016663f, 0.018051f,
+ 0.019821f, 0.021759f, 0.023590f, 0.025818f, 0.028519f, 0.030975f, 0.034210f, 0.037811f, 0.040802f, 0.045349f, 0.050201f, 0.055298f,
+ 0.061310f, 0.067688f, 0.074768f, 0.083557f, 0.092590f, 0.103149f, 0.115479f, 0.128906f, 0.142944f, 0.160278f, 0.178345f, 0.198975f,
+ 0.221802f, 0.246094f, 0.272949f, 0.301514f, 0.331543f, 0.363525f, 0.396729f, 0.430908f, 0.466553f, 0.501953f, 0.538086f, 0.574707f,
+ 0.610840f, 0.646973f, 0.860352f, 0.870605f, 0.873047f, 0.873047f, 0.873535f, 0.872559f, 0.000225f, 0.001021f, 0.001653f, 0.002302f,
+ 0.002827f, 0.003448f, 0.003937f, 0.004486f, 0.004986f, 0.006252f, 0.007000f, 0.007416f, 0.008224f, 0.009300f, 0.009972f, 0.011322f,
+ 0.012115f, 0.013428f, 0.014557f, 0.015991f, 0.017532f, 0.018982f, 0.020706f, 0.022781f, 0.024567f, 0.027161f, 0.029770f, 0.032623f,
+ 0.035828f, 0.039551f, 0.043030f, 0.047852f, 0.052795f, 0.058716f, 0.065125f, 0.072266f, 0.080566f, 0.089661f, 0.100403f, 0.112854f,
+ 0.125732f, 0.140991f, 0.157349f, 0.176514f, 0.197510f, 0.220581f, 0.245850f, 0.273438f, 0.302979f, 0.334717f, 0.367676f, 0.401855f,
+ 0.437256f, 0.474609f, 0.512695f, 0.549316f, 0.588379f, 0.625000f, 0.853027f, 0.863281f, 0.866211f, 0.866211f, 0.866699f, 0.866211f,
+ 0.000324f, 0.000845f, 0.001534f, 0.002172f, 0.002474f, 0.003115f, 0.003824f, 0.003937f, 0.004848f, 0.005417f, 0.006222f, 0.006760f,
+ 0.007446f, 0.008186f, 0.009102f, 0.009888f, 0.010620f, 0.011551f, 0.012878f, 0.013954f, 0.015106f, 0.016495f, 0.018143f, 0.019669f,
+ 0.021713f, 0.023468f, 0.025818f, 0.028183f, 0.031021f, 0.033783f, 0.037445f, 0.041534f, 0.045532f, 0.050598f, 0.056152f, 0.062500f,
+ 0.069580f, 0.077698f, 0.086914f, 0.097717f, 0.108948f, 0.123047f, 0.138184f, 0.155273f, 0.174438f, 0.196167f, 0.219604f, 0.246094f,
+ 0.274902f, 0.305420f, 0.338379f, 0.372314f, 0.408936f, 0.445801f, 0.484131f, 0.523438f, 0.562988f, 0.604492f, 0.843262f, 0.856445f,
+ 0.857422f, 0.857910f, 0.858398f, 0.858398f, 0.000331f, 0.000944f, 0.001288f, 0.001833f, 0.002388f, 0.002769f, 0.003216f, 0.003664f,
+ 0.004276f, 0.004822f, 0.005173f, 0.005951f, 0.006531f, 0.007156f, 0.007896f, 0.008438f, 0.009430f, 0.010117f, 0.011208f, 0.012253f,
+ 0.012970f, 0.014297f, 0.015572f, 0.017059f, 0.018692f, 0.020264f, 0.022125f, 0.024323f, 0.026474f, 0.029343f, 0.032288f, 0.035461f,
+ 0.039062f, 0.043335f, 0.047821f, 0.053558f, 0.059509f, 0.067078f, 0.074341f, 0.083862f, 0.094360f, 0.106323f, 0.120117f, 0.135254f,
+ 0.153442f, 0.172852f, 0.195190f, 0.220337f, 0.246948f, 0.276611f, 0.308594f, 0.343262f, 0.379150f, 0.416992f, 0.455811f, 0.496582f,
+ 0.537598f, 0.579590f, 0.834473f, 0.847656f, 0.850098f, 0.850098f, 0.849609f, 0.850098f, 0.000316f, 0.000824f, 0.001088f, 0.001693f,
+ 0.002062f, 0.002403f, 0.003027f, 0.003460f, 0.003712f, 0.004166f, 0.004765f, 0.005138f, 0.005871f, 0.006218f, 0.006924f, 0.007431f,
+ 0.008255f, 0.008850f, 0.009781f, 0.010590f, 0.011391f, 0.012367f, 0.013474f, 0.014709f, 0.015823f, 0.017685f, 0.018982f, 0.020844f,
+ 0.022629f, 0.025070f, 0.027496f, 0.030380f, 0.033447f, 0.037140f, 0.041168f, 0.045654f, 0.050720f, 0.057251f, 0.063965f, 0.071777f,
+ 0.080811f, 0.091248f, 0.103638f, 0.117126f, 0.133179f, 0.151001f, 0.171631f, 0.194580f, 0.220337f, 0.248413f, 0.279785f, 0.313965f,
+ 0.349365f, 0.386963f, 0.426514f, 0.468262f, 0.510742f, 0.555176f, 0.825684f, 0.838379f, 0.839844f, 0.841309f, 0.841309f, 0.841309f,
+ 0.000210f, 0.000717f, 0.001084f, 0.001454f, 0.001882f, 0.002096f, 0.002468f, 0.002996f, 0.003395f, 0.003632f, 0.004066f, 0.004467f,
+ 0.005020f, 0.005569f, 0.005917f, 0.006474f, 0.006958f, 0.007576f, 0.008453f, 0.009140f, 0.010002f, 0.010689f, 0.011520f, 0.012596f,
+ 0.013695f, 0.014938f, 0.016220f, 0.017593f, 0.019424f, 0.020996f, 0.023331f, 0.025696f, 0.028427f, 0.031067f, 0.034668f, 0.038422f,
+ 0.042908f, 0.048096f, 0.054016f, 0.060699f, 0.068909f, 0.077515f, 0.088501f, 0.100464f, 0.114624f, 0.130615f, 0.149048f, 0.170654f,
+ 0.194214f, 0.222046f, 0.251465f, 0.283936f, 0.319580f, 0.357422f, 0.397461f, 0.440186f, 0.484375f, 0.528320f, 0.814941f, 0.828613f,
+ 0.830078f, 0.832031f, 0.831543f, 0.833008f, 0.000234f, 0.000576f, 0.000939f, 0.001362f, 0.001481f, 0.001999f, 0.002228f, 0.002714f,
+ 0.002846f, 0.003218f, 0.003555f, 0.003933f, 0.004356f, 0.004787f, 0.005169f, 0.005604f, 0.006145f, 0.006554f, 0.007275f, 0.007675f,
+ 0.008293f, 0.009201f, 0.009979f, 0.010651f, 0.011497f, 0.012527f, 0.013893f, 0.014771f, 0.016373f, 0.017975f, 0.019455f, 0.021683f,
+ 0.023895f, 0.026077f, 0.029114f, 0.032257f, 0.036072f, 0.040405f, 0.045197f, 0.050903f, 0.057770f, 0.065613f, 0.074524f, 0.085388f,
+ 0.097656f, 0.111694f, 0.128540f, 0.147949f, 0.170166f, 0.195435f, 0.223389f, 0.255127f, 0.289551f, 0.327393f, 0.367432f, 0.410400f,
+ 0.455078f, 0.502441f, 0.804199f, 0.818848f, 0.821289f, 0.822266f, 0.822754f, 0.822266f, 0.000213f, 0.000506f, 0.000756f, 0.001184f,
+ 0.001396f, 0.001697f, 0.002010f, 0.002474f, 0.002569f, 0.002918f, 0.003090f, 0.003496f, 0.003855f, 0.004139f, 0.004478f, 0.004852f,
+ 0.005253f, 0.005665f, 0.006100f, 0.006638f, 0.007080f, 0.007744f, 0.008293f, 0.009132f, 0.009750f, 0.010658f, 0.011536f, 0.012413f,
+ 0.013779f, 0.014908f, 0.016510f, 0.017990f, 0.019623f, 0.021637f, 0.024109f, 0.026718f, 0.029922f, 0.033539f, 0.037567f, 0.042572f,
+ 0.048279f, 0.054413f, 0.062042f, 0.071472f, 0.081909f, 0.094604f, 0.109436f, 0.127075f, 0.146484f, 0.170044f, 0.196533f, 0.226929f,
+ 0.260254f, 0.296875f, 0.337402f, 0.380615f, 0.426025f, 0.475342f, 0.792969f, 0.807617f, 0.811035f, 0.811523f, 0.812012f, 0.813477f,
+ 0.000119f, 0.000422f, 0.000883f, 0.001027f, 0.001189f, 0.001604f, 0.001783f, 0.001913f, 0.002228f, 0.002522f, 0.002645f, 0.003086f,
+ 0.003199f, 0.003534f, 0.003790f, 0.004105f, 0.004421f, 0.004902f, 0.005283f, 0.005589f, 0.006039f, 0.006401f, 0.007088f, 0.007519f,
+ 0.008217f, 0.008812f, 0.009712f, 0.010460f, 0.011337f, 0.012413f, 0.013596f, 0.014687f, 0.016159f, 0.018051f, 0.019913f, 0.022018f,
+ 0.024551f, 0.027359f, 0.030792f, 0.035065f, 0.039703f, 0.044983f, 0.051392f, 0.059204f, 0.068176f, 0.079102f, 0.092041f, 0.106873f,
+ 0.125000f, 0.145874f, 0.170532f, 0.198975f, 0.230835f, 0.267090f, 0.306641f, 0.349854f, 0.395508f, 0.445801f, 0.780762f, 0.796875f,
+ 0.799805f, 0.801270f, 0.801270f, 0.801270f, 0.000227f, 0.000521f, 0.000698f, 0.000817f, 0.001236f, 0.001359f, 0.001540f, 0.001619f,
+ 0.001940f, 0.002089f, 0.002430f, 0.002552f, 0.002655f, 0.002932f, 0.003241f, 0.003532f, 0.003841f, 0.004120f, 0.004292f, 0.004761f,
+ 0.005051f, 0.005459f, 0.005886f, 0.006290f, 0.006821f, 0.007320f, 0.007889f, 0.008652f, 0.009399f, 0.010063f, 0.010887f, 0.012215f,
+ 0.013206f, 0.014648f, 0.016037f, 0.017853f, 0.019958f, 0.022491f, 0.024994f, 0.028091f, 0.032135f, 0.036530f, 0.041809f, 0.048096f,
+ 0.055908f, 0.064941f, 0.076050f, 0.089050f, 0.104980f, 0.123596f, 0.146118f, 0.172363f, 0.203003f, 0.237183f, 0.276123f, 0.318359f,
+ 0.365479f, 0.416504f, 0.768555f, 0.784668f, 0.788086f, 0.789551f, 0.790039f, 0.790039f, 0.000000f, 0.000448f, 0.000566f, 0.000688f,
+ 0.000985f, 0.001144f, 0.001305f, 0.001437f, 0.001622f, 0.001731f, 0.001989f, 0.002174f, 0.002338f, 0.002552f, 0.002739f, 0.002924f,
+ 0.003239f, 0.003405f, 0.003628f, 0.003933f, 0.004200f, 0.004463f, 0.004948f, 0.005245f, 0.005615f, 0.006138f, 0.006699f, 0.006989f,
+ 0.007793f, 0.008247f, 0.008980f, 0.009918f, 0.010857f, 0.011795f, 0.013016f, 0.014244f, 0.015930f, 0.017868f, 0.019882f, 0.022659f,
+ 0.025543f, 0.029160f, 0.033417f, 0.038635f, 0.044983f, 0.052338f, 0.061859f, 0.072693f, 0.086487f, 0.102966f, 0.122864f, 0.146973f,
+ 0.175049f, 0.207764f, 0.245605f, 0.287842f, 0.334229f, 0.385986f, 0.755371f, 0.771973f, 0.775879f, 0.777344f, 0.777832f, 0.778809f,
+ 0.000000f, 0.000303f, 0.000512f, 0.000752f, 0.000828f, 0.001036f, 0.001184f, 0.001292f, 0.001281f, 0.001460f, 0.001717f, 0.001843f,
+ 0.001955f, 0.002060f, 0.002317f, 0.002476f, 0.002542f, 0.002869f, 0.003088f, 0.003313f, 0.003559f, 0.003693f, 0.004082f, 0.004318f,
+ 0.004696f, 0.005070f, 0.005245f, 0.005741f, 0.006126f, 0.006771f, 0.007298f, 0.007828f, 0.008583f, 0.009338f, 0.010246f, 0.011528f,
+ 0.012794f, 0.014160f, 0.015717f, 0.017853f, 0.019958f, 0.022995f, 0.026291f, 0.030533f, 0.035553f, 0.041565f, 0.048981f, 0.058350f,
+ 0.069824f, 0.083801f, 0.101685f, 0.122437f, 0.148438f, 0.178833f, 0.215454f, 0.256104f, 0.302490f, 0.354736f, 0.741699f, 0.758789f,
+ 0.762695f, 0.763672f, 0.764648f, 0.765625f, 0.000097f, 0.000306f, 0.000370f, 0.000618f, 0.000713f, 0.000810f, 0.000953f, 0.000920f,
+ 0.001167f, 0.001238f, 0.001406f, 0.001483f, 0.001540f, 0.001794f, 0.001970f, 0.002028f, 0.002264f, 0.002354f, 0.002459f, 0.002636f,
+ 0.002827f, 0.003096f, 0.003342f, 0.003544f, 0.003881f, 0.003948f, 0.004459f, 0.004742f, 0.005005f, 0.005394f, 0.005867f, 0.006374f,
+ 0.006901f, 0.007507f, 0.008202f, 0.008881f, 0.010017f, 0.010986f, 0.012451f, 0.013809f, 0.015511f, 0.017776f, 0.020325f, 0.023453f,
+ 0.027390f, 0.032349f, 0.038330f, 0.045624f, 0.055359f, 0.067078f, 0.082275f, 0.101013f, 0.123657f, 0.151611f, 0.185791f, 0.225342f,
+ 0.270752f, 0.322754f, 0.727051f, 0.746094f, 0.749512f, 0.750977f, 0.751953f, 0.751953f, 0.000228f, 0.000211f, 0.000504f, 0.000443f,
+ 0.000523f, 0.000672f, 0.000703f, 0.000902f, 0.000975f, 0.001010f, 0.001122f, 0.001178f, 0.001257f, 0.001424f, 0.001575f, 0.001631f,
+ 0.001789f, 0.001910f, 0.002090f, 0.002144f, 0.002411f, 0.002520f, 0.002703f, 0.002827f, 0.003010f, 0.003195f, 0.003403f, 0.003750f,
+ 0.003960f, 0.004276f, 0.004780f, 0.005005f, 0.005432f, 0.005981f, 0.006428f, 0.007015f, 0.007812f, 0.008537f, 0.009415f, 0.010658f,
+ 0.011963f, 0.013443f, 0.015396f, 0.017731f, 0.020782f, 0.024414f, 0.029083f, 0.034912f, 0.042572f, 0.052216f, 0.064392f, 0.080017f,
+ 0.100220f, 0.126099f, 0.157227f, 0.194946f, 0.239136f, 0.290283f, 0.712402f, 0.731445f, 0.734863f, 0.736816f, 0.737305f, 0.737793f,
+ 0.000211f, 0.000198f, 0.000195f, 0.000413f, 0.000517f, 0.000531f, 0.000586f, 0.000736f, 0.000769f, 0.000809f, 0.000970f, 0.001007f,
+ 0.001067f, 0.001134f, 0.001211f, 0.001348f, 0.001341f, 0.001534f, 0.001617f, 0.001734f, 0.001942f, 0.002010f, 0.002110f, 0.002268f,
+ 0.002523f, 0.002607f, 0.002829f, 0.003004f, 0.003113f, 0.003403f, 0.003681f, 0.003990f, 0.004257f, 0.004601f, 0.005039f, 0.005444f,
+ 0.005993f, 0.006561f, 0.007278f, 0.008026f, 0.009041f, 0.010124f, 0.011513f, 0.013222f, 0.015320f, 0.017914f, 0.021408f, 0.025833f,
+ 0.031433f, 0.039429f, 0.049255f, 0.062286f, 0.079102f, 0.101135f, 0.130005f, 0.164917f, 0.207764f, 0.258057f, 0.696289f, 0.716309f,
+ 0.720215f, 0.722168f, 0.722656f, 0.723145f, 0.000000f, 0.000080f, 0.000286f, 0.000374f, 0.000434f, 0.000457f, 0.000460f, 0.000568f,
+ 0.000610f, 0.000669f, 0.000715f, 0.000773f, 0.000877f, 0.000918f, 0.001030f, 0.000998f, 0.001148f, 0.001134f, 0.001305f, 0.001369f,
+ 0.001410f, 0.001534f, 0.001688f, 0.001780f, 0.001899f, 0.001963f, 0.002081f, 0.002199f, 0.002470f, 0.002563f, 0.002758f, 0.003006f,
+ 0.003273f, 0.003531f, 0.003817f, 0.004093f, 0.004532f, 0.004993f, 0.005463f, 0.006027f, 0.006657f, 0.007492f, 0.008537f, 0.009689f,
+ 0.011246f, 0.012985f, 0.015518f, 0.018539f, 0.022827f, 0.028534f, 0.036072f, 0.046234f, 0.060028f, 0.078918f, 0.103943f, 0.136353f,
+ 0.176514f, 0.225952f, 0.679199f, 0.699707f, 0.703613f, 0.706055f, 0.706543f, 0.708008f, 0.000089f, 0.000176f, 0.000232f, 0.000342f,
+ 0.000317f, 0.000319f, 0.000420f, 0.000382f, 0.000494f, 0.000515f, 0.000612f, 0.000650f, 0.000671f, 0.000701f, 0.000732f, 0.000859f,
+ 0.000888f, 0.000923f, 0.001002f, 0.001048f, 0.001170f, 0.001234f, 0.001292f, 0.001426f, 0.001414f, 0.001476f, 0.001622f, 0.001723f,
+ 0.001892f, 0.001976f, 0.002237f, 0.002239f, 0.002476f, 0.002645f, 0.002817f, 0.003092f, 0.003355f, 0.003626f, 0.003979f, 0.004459f,
+ 0.004948f, 0.005527f, 0.006256f, 0.007027f, 0.008026f, 0.009270f, 0.010918f, 0.013184f, 0.016098f, 0.019913f, 0.025253f, 0.033112f,
+ 0.043762f, 0.059113f, 0.079956f, 0.109009f, 0.146729f, 0.193726f, 0.660645f, 0.682129f, 0.688477f, 0.690430f, 0.689941f, 0.690918f,
+ 0.000000f, 0.000063f, 0.000194f, 0.000281f, 0.000187f, 0.000325f, 0.000278f, 0.000272f, 0.000386f, 0.000466f, 0.000462f, 0.000510f,
+ 0.000519f, 0.000587f, 0.000613f, 0.000603f, 0.000671f, 0.000709f, 0.000744f, 0.000808f, 0.000858f, 0.000913f, 0.000963f, 0.000999f,
+ 0.001062f, 0.001106f, 0.001262f, 0.001266f, 0.001431f, 0.001562f, 0.001672f, 0.001693f, 0.001810f, 0.001976f, 0.002090f, 0.002289f,
+ 0.002422f, 0.002666f, 0.002916f, 0.003166f, 0.003513f, 0.003862f, 0.004318f, 0.004936f, 0.005646f, 0.006493f, 0.007626f, 0.009048f,
+ 0.010826f, 0.013519f, 0.017166f, 0.022476f, 0.030258f, 0.041687f, 0.058807f, 0.083435f, 0.117737f, 0.162598f, 0.644043f, 0.666504f,
+ 0.670410f, 0.673340f, 0.674316f, 0.675293f, 0.000000f, 0.000117f, 0.000112f, 0.000178f, 0.000216f, 0.000222f, 0.000271f, 0.000229f,
+ 0.000280f, 0.000283f, 0.000326f, 0.000376f, 0.000376f, 0.000443f, 0.000456f, 0.000470f, 0.000499f, 0.000507f, 0.000547f, 0.000566f,
+ 0.000613f, 0.000667f, 0.000692f, 0.000749f, 0.000773f, 0.000803f, 0.000917f, 0.000924f, 0.000997f, 0.001055f, 0.001096f, 0.001236f,
+ 0.001261f, 0.001376f, 0.001466f, 0.001693f, 0.001695f, 0.001826f, 0.002077f, 0.002226f, 0.002411f, 0.002686f, 0.002985f, 0.003368f,
+ 0.003801f, 0.004353f, 0.005131f, 0.005974f, 0.007370f, 0.008842f, 0.011345f, 0.014717f, 0.019699f, 0.027893f, 0.040619f, 0.060730f,
+ 0.090454f, 0.132080f, 0.625488f, 0.649414f, 0.653809f, 0.655273f, 0.656250f, 0.658203f, 0.000000f, 0.000000f, 0.000108f, 0.000121f,
+ 0.000136f, 0.000154f, 0.000158f, 0.000191f, 0.000203f, 0.000213f, 0.000270f, 0.000223f, 0.000232f, 0.000270f, 0.000296f, 0.000342f,
+ 0.000324f, 0.000352f, 0.000453f, 0.000407f, 0.000450f, 0.000459f, 0.000486f, 0.000524f, 0.000545f, 0.000565f, 0.000630f, 0.000620f,
+ 0.000678f, 0.000803f, 0.000763f, 0.000813f, 0.000860f, 0.000937f, 0.001035f, 0.001101f, 0.001141f, 0.001254f, 0.001399f, 0.001449f,
+ 0.001616f, 0.001779f, 0.001942f, 0.002220f, 0.002493f, 0.002808f, 0.003258f, 0.003895f, 0.004623f, 0.005714f, 0.007111f, 0.009178f,
+ 0.012367f, 0.017319f, 0.025879f, 0.040741f, 0.065552f, 0.103577f, 0.606934f, 0.630371f, 0.635254f, 0.637695f, 0.638672f, 0.639648f,
+ 0.000000f, 0.000109f, 0.000102f, 0.000098f, 0.000105f, 0.000110f, 0.000113f, 0.000122f, 0.000117f, 0.000132f, 0.000147f, 0.000189f,
+ 0.000163f, 0.000212f, 0.000213f, 0.000222f, 0.000224f, 0.000233f, 0.000258f, 0.000262f, 0.000274f, 0.000305f, 0.000340f, 0.000329f,
+ 0.000358f, 0.000376f, 0.000445f, 0.000418f, 0.000447f, 0.000478f, 0.000546f, 0.000530f, 0.000594f, 0.000626f, 0.000679f, 0.000745f,
+ 0.000763f, 0.000804f, 0.000869f, 0.000952f, 0.001025f, 0.001119f, 0.001254f, 0.001359f, 0.001584f, 0.001728f, 0.001993f, 0.002295f,
+ 0.002790f, 0.003298f, 0.004135f, 0.005363f, 0.007267f, 0.010277f, 0.015350f, 0.024994f, 0.043518f, 0.076599f, 0.585938f, 0.611816f,
+ 0.616211f, 0.619141f, 0.619629f, 0.620605f, 0.000000f, 0.000102f, 0.000095f, 0.000090f, 0.000085f, 0.000081f, 0.000078f, 0.000073f,
+ 0.000075f, 0.000079f, 0.000087f, 0.000092f, 0.000095f, 0.000094f, 0.000133f, 0.000143f, 0.000152f, 0.000155f, 0.000161f, 0.000195f,
+ 0.000174f, 0.000183f, 0.000188f, 0.000216f, 0.000233f, 0.000241f, 0.000241f, 0.000257f, 0.000269f, 0.000302f, 0.000325f, 0.000321f,
+ 0.000350f, 0.000363f, 0.000405f, 0.000426f, 0.000456f, 0.000486f, 0.000539f, 0.000560f, 0.000614f, 0.000671f, 0.000722f, 0.000811f,
+ 0.000891f, 0.000989f, 0.001162f, 0.001312f, 0.001545f, 0.001863f, 0.002340f, 0.002920f, 0.003963f, 0.005615f, 0.008499f, 0.013931f,
+ 0.025833f, 0.052094f, 0.566406f, 0.591797f, 0.597168f, 0.599609f, 0.601074f, 0.601562f, 0.000110f, 0.000092f, 0.000084f, 0.000077f,
+ 0.000073f, 0.000070f, 0.000067f, 0.000064f, 0.000061f, 0.000058f, 0.000055f, 0.000064f, 0.000051f, 0.000054f, 0.000071f, 0.000059f,
+ 0.000082f, 0.000081f, 0.000090f, 0.000087f, 0.000099f, 0.000103f, 0.000127f, 0.000131f, 0.000135f, 0.000139f, 0.000142f, 0.000143f,
+ 0.000156f, 0.000162f, 0.000173f, 0.000194f, 0.000206f, 0.000201f, 0.000233f, 0.000225f, 0.000246f, 0.000294f, 0.000279f, 0.000313f,
+ 0.000333f, 0.000356f, 0.000395f, 0.000432f, 0.000459f, 0.000511f, 0.000577f, 0.000664f, 0.000770f, 0.000916f, 0.001114f, 0.001400f,
+ 0.001881f, 0.002665f, 0.004093f, 0.006966f, 0.013290f, 0.031525f, 0.545410f, 0.571777f, 0.577637f, 0.579102f, 0.580566f, 0.581055f,
+ 0.000093f, 0.000073f, 0.000066f, 0.000061f, 0.000056f, 0.000054f, 0.000051f, 0.000050f, 0.000048f, 0.000047f, 0.000045f, 0.000044f,
+ 0.000042f, 0.000040f, 0.000038f, 0.000036f, 0.000039f, 0.000033f, 0.000041f, 0.000040f, 0.000046f, 0.000048f, 0.000051f, 0.000057f,
+ 0.000060f, 0.000066f, 0.000062f, 0.000067f, 0.000080f, 0.000085f, 0.000088f, 0.000092f, 0.000092f, 0.000097f, 0.000109f, 0.000109f,
+ 0.000117f, 0.000132f, 0.000134f, 0.000147f, 0.000154f, 0.000156f, 0.000188f, 0.000197f, 0.000219f, 0.000234f, 0.000266f, 0.000286f,
+ 0.000335f, 0.000397f, 0.000472f, 0.000566f, 0.000751f, 0.001039f, 0.001626f, 0.002834f, 0.005909f, 0.015411f, 0.524414f, 0.551270f,
+ 0.557129f, 0.559570f, 0.561035f, 0.561523f, 0.000060f, 0.000046f, 0.000039f, 0.000037f, 0.000034f, 0.000034f, 0.000032f, 0.000032f,
+ 0.000031f, 0.000029f, 0.000029f, 0.000029f, 0.000028f, 0.000028f, 0.000028f, 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f,
+ 0.000022f, 0.000021f, 0.000020f, 0.000021f, 0.000020f, 0.000018f, 0.000018f, 0.000023f, 0.000024f, 0.000028f, 0.000032f, 0.000033f,
+ 0.000032f, 0.000038f, 0.000039f, 0.000043f, 0.000046f, 0.000050f, 0.000052f, 0.000053f, 0.000057f, 0.000067f, 0.000073f, 0.000068f,
+ 0.000076f, 0.000083f, 0.000097f, 0.000110f, 0.000116f, 0.000127f, 0.000157f, 0.000185f, 0.000246f, 0.000319f, 0.000466f, 0.000810f,
+ 0.001841f, 0.005795f, 0.503418f, 0.531250f, 0.536621f, 0.539062f, 0.540039f, 0.540527f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000004f, 0.000005f, 0.000005f, 0.000008f, 0.000008f, 0.000009f, 0.000009f, 0.000010f, 0.000010f, 0.000010f, 0.000010f, 0.000011f,
+ 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000011f,
+ 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000009f, 0.000009f, 0.000010f, 0.000012f,
+ 0.000013f, 0.000014f, 0.000015f, 0.000017f, 0.000020f, 0.000021f, 0.000018f, 0.000023f, 0.000023f, 0.000025f, 0.000030f, 0.000038f,
+ 0.000043f, 0.000059f, 0.000079f, 0.000131f, 0.000279f, 0.001210f, 0.481934f, 0.510254f, 0.516113f, 0.518555f, 0.520020f, 0.520508f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f,
+ 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000004f, 0.000006f, 0.000022f, 0.460449f, 0.489258f,
+ 0.495850f, 0.498291f, 0.499512f, 0.500000f,
+ },
+ {
+ 0.038544f, 0.111450f, 0.177368f, 0.237061f, 0.290771f, 0.339600f, 0.384277f, 0.425293f, 0.462402f, 0.497070f, 0.527344f, 0.556152f,
+ 0.583496f, 0.607910f, 0.630859f, 0.652344f, 0.672852f, 0.690918f, 0.708496f, 0.724609f, 0.740723f, 0.754883f, 0.768066f, 0.780273f,
+ 0.792480f, 0.803711f, 0.815430f, 0.825684f, 0.835449f, 0.844727f, 0.853516f, 0.861816f, 0.870117f, 0.877930f, 0.885254f, 0.892578f,
+ 0.899414f, 0.905762f, 0.912109f, 0.918945f, 0.923828f, 0.928711f, 0.934082f, 0.939941f, 0.944824f, 0.949707f, 0.953613f, 0.958496f,
+ 0.962402f, 0.967285f, 0.971191f, 0.974609f, 0.979004f, 0.982422f, 0.985352f, 0.989258f, 0.992188f, 0.996094f, 0.996094f, 0.990723f,
+ 0.986328f, 0.982422f, 0.978516f, 0.975098f, 0.029068f, 0.087219f, 0.142578f, 0.195190f, 0.244629f, 0.291016f, 0.334717f, 0.375000f,
+ 0.412842f, 0.446533f, 0.481201f, 0.511230f, 0.539062f, 0.565918f, 0.590820f, 0.614258f, 0.636719f, 0.656250f, 0.675293f, 0.693359f,
+ 0.710449f, 0.726562f, 0.741699f, 0.755371f, 0.769043f, 0.781738f, 0.793457f, 0.805176f, 0.815918f, 0.826660f, 0.835938f, 0.845703f,
+ 0.854980f, 0.862793f, 0.871582f, 0.879395f, 0.885742f, 0.894531f, 0.900879f, 0.907227f, 0.913086f, 0.919434f, 0.925293f, 0.931152f,
+ 0.936523f, 0.941406f, 0.946777f, 0.951172f, 0.956055f, 0.960449f, 0.964355f, 0.968750f, 0.972656f, 0.976562f, 0.980469f, 0.984375f,
+ 0.987793f, 0.991211f, 0.994141f, 0.989258f, 0.984863f, 0.981445f, 0.977539f, 0.974121f, 0.023346f, 0.069641f, 0.115601f, 0.160767f,
+ 0.205078f, 0.248047f, 0.289062f, 0.328125f, 0.365723f, 0.401367f, 0.435059f, 0.466309f, 0.495361f, 0.523926f, 0.550781f, 0.574707f,
+ 0.597168f, 0.620117f, 0.641113f, 0.660156f, 0.679688f, 0.696777f, 0.713379f, 0.728516f, 0.743652f, 0.757324f, 0.770996f, 0.784180f,
+ 0.795410f, 0.806641f, 0.817383f, 0.828125f, 0.837891f, 0.847168f, 0.855957f, 0.864258f, 0.873047f, 0.880859f, 0.888672f, 0.895996f,
+ 0.902832f, 0.909668f, 0.915039f, 0.921875f, 0.927246f, 0.934082f, 0.937988f, 0.943848f, 0.948242f, 0.953613f, 0.958496f, 0.962402f,
+ 0.967285f, 0.971191f, 0.975098f, 0.979492f, 0.983398f, 0.985840f, 0.992188f, 0.987305f, 0.983398f, 0.979980f, 0.977051f, 0.973633f,
+ 0.018600f, 0.056366f, 0.094299f, 0.133545f, 0.172729f, 0.211670f, 0.249756f, 0.285889f, 0.322021f, 0.356934f, 0.390869f, 0.421875f,
+ 0.452148f, 0.481201f, 0.509277f, 0.535156f, 0.560059f, 0.583496f, 0.605957f, 0.626465f, 0.647949f, 0.665527f, 0.684570f, 0.700684f,
+ 0.717285f, 0.731934f, 0.746582f, 0.760254f, 0.773926f, 0.786621f, 0.799316f, 0.809082f, 0.820312f, 0.830566f, 0.840332f, 0.850098f,
+ 0.858887f, 0.867188f, 0.875000f, 0.883789f, 0.890625f, 0.898926f, 0.904297f, 0.912109f, 0.916992f, 0.924316f, 0.930176f, 0.935547f,
+ 0.941406f, 0.945801f, 0.951172f, 0.956055f, 0.960938f, 0.964844f, 0.969727f, 0.974609f, 0.978516f, 0.981934f, 0.989746f, 0.985840f,
+ 0.981934f, 0.978516f, 0.975586f, 0.972168f, 0.015068f, 0.046143f, 0.077881f, 0.111816f, 0.145264f, 0.179688f, 0.214600f, 0.249023f,
+ 0.282715f, 0.316406f, 0.348389f, 0.380615f, 0.411133f, 0.440430f, 0.468018f, 0.494873f, 0.520508f, 0.546387f, 0.568848f, 0.591309f,
+ 0.613281f, 0.634277f, 0.653809f, 0.670898f, 0.688477f, 0.706055f, 0.721191f, 0.736328f, 0.751465f, 0.764648f, 0.776855f, 0.789551f,
+ 0.801270f, 0.812500f, 0.823730f, 0.833496f, 0.843262f, 0.853027f, 0.861328f, 0.869629f, 0.878418f, 0.885742f, 0.893555f, 0.900391f,
+ 0.908203f, 0.914551f, 0.921387f, 0.927246f, 0.932617f, 0.938965f, 0.943848f, 0.949219f, 0.953613f, 0.959473f, 0.963867f, 0.968262f,
+ 0.972656f, 0.977051f, 0.987305f, 0.983887f, 0.980957f, 0.977051f, 0.974121f, 0.970703f, 0.012444f, 0.037933f, 0.065613f, 0.093811f,
+ 0.123474f, 0.153809f, 0.185059f, 0.215820f, 0.247559f, 0.279297f, 0.310547f, 0.341309f, 0.370361f, 0.399658f, 0.428467f, 0.457031f,
+ 0.482910f, 0.507812f, 0.533203f, 0.556152f, 0.579590f, 0.600098f, 0.621094f, 0.641113f, 0.659668f, 0.676270f, 0.695312f, 0.710449f,
+ 0.726074f, 0.740723f, 0.756348f, 0.769043f, 0.780762f, 0.794434f, 0.805176f, 0.816895f, 0.827637f, 0.837891f, 0.847168f, 0.855957f,
+ 0.865723f, 0.873535f, 0.882324f, 0.889648f, 0.897949f, 0.904297f, 0.911133f, 0.917480f, 0.924316f, 0.930176f, 0.936523f, 0.941895f,
+ 0.947266f, 0.952637f, 0.958008f, 0.962891f, 0.967285f, 0.971680f, 0.984863f, 0.981934f, 0.978516f, 0.975586f, 0.972656f, 0.969238f,
+ 0.010353f, 0.032043f, 0.055359f, 0.079529f, 0.104980f, 0.131836f, 0.159424f, 0.187866f, 0.216431f, 0.245239f, 0.275146f, 0.304199f,
+ 0.333496f, 0.362061f, 0.390869f, 0.417969f, 0.445068f, 0.471191f, 0.496582f, 0.520508f, 0.543457f, 0.566895f, 0.588867f, 0.608398f,
+ 0.628906f, 0.648438f, 0.666992f, 0.684570f, 0.701660f, 0.716797f, 0.732422f, 0.746582f, 0.760254f, 0.773438f, 0.786133f, 0.798340f,
+ 0.810547f, 0.821777f, 0.832520f, 0.842773f, 0.851074f, 0.860352f, 0.869629f, 0.878906f, 0.886230f, 0.894043f, 0.901855f, 0.908691f,
+ 0.915527f, 0.922363f, 0.928223f, 0.935059f, 0.939941f, 0.945312f, 0.950684f, 0.956055f, 0.962402f, 0.966797f, 0.982910f, 0.979980f,
+ 0.977051f, 0.973633f, 0.970703f, 0.968262f, 0.008598f, 0.027328f, 0.046417f, 0.067871f, 0.089905f, 0.113220f, 0.137695f, 0.163330f,
+ 0.189087f, 0.216064f, 0.243164f, 0.270752f, 0.298340f, 0.326416f, 0.354004f, 0.381348f, 0.407715f, 0.434082f, 0.460205f, 0.484863f,
+ 0.508789f, 0.532227f, 0.555176f, 0.577637f, 0.598145f, 0.618652f, 0.637695f, 0.657227f, 0.674805f, 0.691406f, 0.708008f, 0.723633f,
+ 0.738770f, 0.751953f, 0.766113f, 0.779785f, 0.791992f, 0.804199f, 0.815918f, 0.825684f, 0.836914f, 0.846680f, 0.856934f, 0.866211f,
+ 0.874512f, 0.882324f, 0.890625f, 0.898438f, 0.905273f, 0.913086f, 0.919922f, 0.926758f, 0.933105f, 0.938477f, 0.944824f, 0.951172f,
+ 0.955566f, 0.960938f, 0.980469f, 0.978027f, 0.974609f, 0.972168f, 0.969238f, 0.966797f, 0.007561f, 0.023315f, 0.040344f, 0.058228f,
+ 0.077148f, 0.097534f, 0.119995f, 0.142212f, 0.165649f, 0.190063f, 0.214722f, 0.240601f, 0.266846f, 0.293457f, 0.319824f, 0.346924f,
+ 0.372314f, 0.398438f, 0.424561f, 0.449463f, 0.474609f, 0.498535f, 0.521973f, 0.544434f, 0.566895f, 0.587402f, 0.608398f, 0.628418f,
+ 0.645996f, 0.665039f, 0.683105f, 0.699219f, 0.716309f, 0.731445f, 0.745117f, 0.760254f, 0.772949f, 0.786133f, 0.799316f, 0.809570f,
+ 0.820801f, 0.832031f, 0.843262f, 0.852051f, 0.861816f, 0.871094f, 0.880371f, 0.887695f, 0.895996f, 0.904297f, 0.911133f, 0.917969f,
+ 0.924805f, 0.931641f, 0.937012f, 0.943848f, 0.949707f, 0.954590f, 0.978027f, 0.976074f, 0.973145f, 0.970215f, 0.967773f, 0.965332f,
+ 0.006416f, 0.020065f, 0.034943f, 0.050537f, 0.067078f, 0.084900f, 0.104065f, 0.123962f, 0.145264f, 0.166748f, 0.189575f, 0.213501f,
+ 0.237305f, 0.262451f, 0.288574f, 0.313477f, 0.338623f, 0.364502f, 0.389893f, 0.414551f, 0.440186f, 0.464600f, 0.487549f, 0.510742f,
+ 0.534668f, 0.556641f, 0.578613f, 0.598145f, 0.618652f, 0.637207f, 0.655273f, 0.674805f, 0.690430f, 0.707031f, 0.724121f, 0.739258f,
+ 0.752930f, 0.767090f, 0.779785f, 0.792969f, 0.805176f, 0.816895f, 0.827637f, 0.838379f, 0.849121f, 0.858398f, 0.868652f, 0.876465f,
+ 0.885742f, 0.894043f, 0.901855f, 0.909180f, 0.916992f, 0.923828f, 0.930176f, 0.937012f, 0.943359f, 0.949707f, 0.975586f, 0.973633f,
+ 0.971191f, 0.968262f, 0.965820f, 0.963379f, 0.005802f, 0.017502f, 0.030045f, 0.043823f, 0.058014f, 0.074280f, 0.090759f, 0.108459f,
+ 0.127197f, 0.146484f, 0.167725f, 0.189087f, 0.211304f, 0.234497f, 0.258301f, 0.282471f, 0.307373f, 0.331299f, 0.356689f, 0.381104f,
+ 0.405762f, 0.430420f, 0.455078f, 0.478516f, 0.502441f, 0.524414f, 0.545898f, 0.568359f, 0.588867f, 0.608887f, 0.628906f, 0.646973f,
+ 0.665527f, 0.684082f, 0.701172f, 0.715820f, 0.731934f, 0.746582f, 0.760742f, 0.774414f, 0.787598f, 0.800781f, 0.812500f, 0.823730f,
+ 0.834961f, 0.845703f, 0.855469f, 0.865234f, 0.874512f, 0.883789f, 0.892090f, 0.899902f, 0.908203f, 0.916016f, 0.922852f, 0.930176f,
+ 0.936523f, 0.942871f, 0.972656f, 0.971191f, 0.968750f, 0.966309f, 0.963867f, 0.961426f, 0.004734f, 0.014984f, 0.026169f, 0.038177f,
+ 0.051208f, 0.065186f, 0.079468f, 0.095276f, 0.111633f, 0.129639f, 0.148071f, 0.167969f, 0.188599f, 0.208984f, 0.231689f, 0.254639f,
+ 0.277832f, 0.301025f, 0.325439f, 0.349854f, 0.373779f, 0.397705f, 0.422607f, 0.446045f, 0.469727f, 0.492676f, 0.514648f, 0.537598f,
+ 0.559570f, 0.580078f, 0.600586f, 0.620117f, 0.639648f, 0.658203f, 0.676758f, 0.692871f, 0.708984f, 0.725586f, 0.740723f, 0.755859f,
+ 0.769531f, 0.783691f, 0.796875f, 0.808594f, 0.820801f, 0.832520f, 0.842285f, 0.852539f, 0.862793f, 0.872070f, 0.881836f, 0.890137f,
+ 0.898926f, 0.906738f, 0.915039f, 0.922363f, 0.929199f, 0.936523f, 0.969727f, 0.968750f, 0.966797f, 0.964355f, 0.961914f, 0.959473f,
+ 0.004055f, 0.013588f, 0.023132f, 0.033722f, 0.044891f, 0.057343f, 0.069763f, 0.083923f, 0.098389f, 0.114441f, 0.131226f, 0.148682f,
+ 0.167603f, 0.186768f, 0.207031f, 0.228516f, 0.250732f, 0.272949f, 0.295410f, 0.318604f, 0.342285f, 0.365967f, 0.390381f, 0.413574f,
+ 0.437744f, 0.460938f, 0.484131f, 0.506348f, 0.528320f, 0.550781f, 0.572266f, 0.592773f, 0.613281f, 0.632812f, 0.651367f, 0.669922f,
+ 0.687500f, 0.704102f, 0.720215f, 0.735840f, 0.751465f, 0.764160f, 0.778809f, 0.792480f, 0.803711f, 0.816895f, 0.829102f, 0.840332f,
+ 0.850586f, 0.860352f, 0.870605f, 0.880371f, 0.889648f, 0.897949f, 0.905762f, 0.914551f, 0.922363f, 0.929199f, 0.967285f, 0.966797f,
+ 0.964844f, 0.961426f, 0.959473f, 0.958008f, 0.003611f, 0.011971f, 0.020401f, 0.030029f, 0.039185f, 0.050415f, 0.061737f, 0.074341f,
+ 0.086975f, 0.101074f, 0.115845f, 0.131958f, 0.148682f, 0.166626f, 0.185059f, 0.205200f, 0.224854f, 0.245483f, 0.267334f, 0.290771f,
+ 0.312988f, 0.335449f, 0.359619f, 0.382080f, 0.406250f, 0.429443f, 0.452881f, 0.475830f, 0.498779f, 0.520996f, 0.542480f, 0.563477f,
+ 0.584473f, 0.604980f, 0.625977f, 0.643555f, 0.663086f, 0.681152f, 0.698242f, 0.714355f, 0.729980f, 0.746582f, 0.760742f, 0.774902f,
+ 0.788086f, 0.801758f, 0.814941f, 0.826660f, 0.838867f, 0.848633f, 0.859863f, 0.869141f, 0.879395f, 0.889160f, 0.897949f, 0.906250f,
+ 0.914551f, 0.922363f, 0.963867f, 0.964355f, 0.961914f, 0.959961f, 0.957520f, 0.955078f, 0.003393f, 0.010361f, 0.018494f, 0.026337f,
+ 0.035187f, 0.044556f, 0.054596f, 0.065186f, 0.077515f, 0.089783f, 0.102783f, 0.117249f, 0.132446f, 0.148071f, 0.165649f, 0.183838f,
+ 0.202026f, 0.221313f, 0.241943f, 0.262939f, 0.285156f, 0.307129f, 0.329102f, 0.352539f, 0.375977f, 0.398438f, 0.421875f, 0.445312f,
+ 0.468750f, 0.490723f, 0.512695f, 0.534668f, 0.556641f, 0.577637f, 0.598633f, 0.619141f, 0.637695f, 0.656738f, 0.674805f, 0.692383f,
+ 0.709473f, 0.726074f, 0.742188f, 0.756836f, 0.771973f, 0.786133f, 0.799316f, 0.812012f, 0.824707f, 0.835938f, 0.848145f, 0.858887f,
+ 0.868164f, 0.878906f, 0.888184f, 0.897949f, 0.906250f, 0.914551f, 0.960938f, 0.960938f, 0.959473f, 0.957520f, 0.955078f, 0.953125f,
+ 0.003084f, 0.009521f, 0.016144f, 0.023346f, 0.031204f, 0.039520f, 0.048523f, 0.057953f, 0.068359f, 0.079895f, 0.091309f, 0.104126f,
+ 0.117920f, 0.132324f, 0.147949f, 0.164062f, 0.181396f, 0.199219f, 0.218872f, 0.238403f, 0.258545f, 0.279541f, 0.301758f, 0.323486f,
+ 0.346191f, 0.368408f, 0.391846f, 0.414795f, 0.437256f, 0.460693f, 0.483643f, 0.505371f, 0.527832f, 0.550293f, 0.571289f, 0.591797f,
+ 0.612305f, 0.632324f, 0.651855f, 0.670898f, 0.687500f, 0.705566f, 0.722168f, 0.737793f, 0.753418f, 0.768555f, 0.783691f, 0.796875f,
+ 0.811035f, 0.823242f, 0.834473f, 0.846191f, 0.857422f, 0.868652f, 0.878418f, 0.887695f, 0.897949f, 0.906250f, 0.958008f, 0.958008f,
+ 0.957031f, 0.954590f, 0.952637f, 0.950684f, 0.002666f, 0.008293f, 0.014297f, 0.021225f, 0.027847f, 0.035156f, 0.043274f, 0.051666f,
+ 0.060791f, 0.070801f, 0.081543f, 0.092407f, 0.104858f, 0.118530f, 0.131836f, 0.146606f, 0.162598f, 0.179443f, 0.196777f, 0.215210f,
+ 0.234375f, 0.254150f, 0.274414f, 0.295898f, 0.317871f, 0.340088f, 0.362549f, 0.385010f, 0.407959f, 0.430664f, 0.454590f, 0.476562f,
+ 0.499268f, 0.521484f, 0.543945f, 0.564941f, 0.585938f, 0.606934f, 0.626465f, 0.646484f, 0.665527f, 0.683594f, 0.701660f, 0.717773f,
+ 0.735352f, 0.751465f, 0.766113f, 0.781738f, 0.794922f, 0.808105f, 0.821289f, 0.833496f, 0.846191f, 0.857910f, 0.868164f, 0.878906f,
+ 0.889160f, 0.899414f, 0.954102f, 0.955566f, 0.953613f, 0.952148f, 0.950195f, 0.948730f, 0.002396f, 0.007427f, 0.012978f, 0.018646f,
+ 0.025024f, 0.031403f, 0.038788f, 0.046112f, 0.054260f, 0.063354f, 0.072693f, 0.082886f, 0.093689f, 0.105469f, 0.118164f, 0.130859f,
+ 0.145996f, 0.161011f, 0.177124f, 0.193359f, 0.211670f, 0.230225f, 0.249634f, 0.270020f, 0.290771f, 0.311768f, 0.333740f, 0.356201f,
+ 0.378906f, 0.401855f, 0.424561f, 0.447754f, 0.470215f, 0.493408f, 0.515137f, 0.537109f, 0.559570f, 0.580078f, 0.601074f, 0.621582f,
+ 0.642090f, 0.661621f, 0.679688f, 0.697754f, 0.715820f, 0.732422f, 0.749512f, 0.765137f, 0.779785f, 0.794434f, 0.808594f, 0.821289f,
+ 0.833496f, 0.846191f, 0.857910f, 0.869141f, 0.879883f, 0.889648f, 0.950195f, 0.952637f, 0.950684f, 0.948730f, 0.947266f, 0.945801f,
+ 0.002029f, 0.006672f, 0.011658f, 0.016937f, 0.022476f, 0.028305f, 0.034332f, 0.041351f, 0.048584f, 0.056671f, 0.064697f, 0.073853f,
+ 0.083923f, 0.094482f, 0.105225f, 0.117798f, 0.130615f, 0.144287f, 0.159302f, 0.174683f, 0.190430f, 0.208740f, 0.226318f, 0.245483f,
+ 0.264893f, 0.285400f, 0.307129f, 0.328369f, 0.350342f, 0.372803f, 0.395264f, 0.418701f, 0.441650f, 0.462891f, 0.486816f, 0.509277f,
+ 0.532227f, 0.553711f, 0.575684f, 0.596680f, 0.617676f, 0.638672f, 0.657715f, 0.676758f, 0.695312f, 0.712402f, 0.729492f, 0.746582f,
+ 0.762695f, 0.778320f, 0.793457f, 0.807129f, 0.820801f, 0.833984f, 0.846191f, 0.858887f, 0.869629f, 0.881836f, 0.947266f, 0.949219f,
+ 0.947754f, 0.946289f, 0.944824f, 0.942871f, 0.002142f, 0.006401f, 0.010841f, 0.015251f, 0.019760f, 0.025055f, 0.031113f, 0.037201f,
+ 0.043671f, 0.050598f, 0.057892f, 0.066101f, 0.075012f, 0.084351f, 0.093994f, 0.105164f, 0.117432f, 0.129517f, 0.142822f, 0.157104f,
+ 0.172119f, 0.188110f, 0.204956f, 0.223145f, 0.241577f, 0.260498f, 0.280762f, 0.301758f, 0.322998f, 0.345215f, 0.366943f, 0.389893f,
+ 0.412842f, 0.435791f, 0.458008f, 0.482178f, 0.504395f, 0.526855f, 0.548828f, 0.571289f, 0.592285f, 0.612793f, 0.634277f, 0.654297f,
+ 0.673340f, 0.692383f, 0.710938f, 0.729004f, 0.745117f, 0.762207f, 0.777832f, 0.792480f, 0.807129f, 0.821289f, 0.834961f, 0.847168f,
+ 0.859863f, 0.871582f, 0.943359f, 0.946289f, 0.944824f, 0.943359f, 0.941895f, 0.940430f, 0.001760f, 0.005562f, 0.009621f, 0.013710f,
+ 0.018417f, 0.022736f, 0.027939f, 0.033264f, 0.039185f, 0.045166f, 0.052460f, 0.059143f, 0.067261f, 0.075745f, 0.084106f, 0.094177f,
+ 0.104980f, 0.116455f, 0.128174f, 0.141113f, 0.155151f, 0.169922f, 0.184937f, 0.201660f, 0.219238f, 0.237549f, 0.256348f, 0.276367f,
+ 0.296875f, 0.317871f, 0.339844f, 0.361572f, 0.383789f, 0.407227f, 0.430908f, 0.453857f, 0.476807f, 0.498779f, 0.521973f, 0.543945f,
+ 0.567383f, 0.589355f, 0.609863f, 0.631348f, 0.651855f, 0.671875f, 0.690918f, 0.709961f, 0.727539f, 0.744141f, 0.761719f, 0.777344f,
+ 0.793457f, 0.808594f, 0.823242f, 0.835449f, 0.848633f, 0.861328f, 0.938965f, 0.941895f, 0.941406f, 0.940430f, 0.938477f, 0.937012f,
+ 0.001594f, 0.005283f, 0.008789f, 0.012383f, 0.016342f, 0.020523f, 0.025284f, 0.029968f, 0.035217f, 0.040741f, 0.046417f, 0.052948f,
+ 0.060120f, 0.067566f, 0.076294f, 0.084534f, 0.093750f, 0.104614f, 0.115173f, 0.126831f, 0.139160f, 0.152832f, 0.166748f, 0.181885f,
+ 0.198853f, 0.215698f, 0.233521f, 0.252197f, 0.271973f, 0.291992f, 0.313477f, 0.334717f, 0.357178f, 0.379395f, 0.401855f, 0.425537f,
+ 0.448242f, 0.471924f, 0.495361f, 0.517578f, 0.541016f, 0.562988f, 0.585938f, 0.607422f, 0.627930f, 0.649414f, 0.670410f, 0.688965f,
+ 0.708496f, 0.727539f, 0.744629f, 0.761719f, 0.778809f, 0.794922f, 0.809082f, 0.824219f, 0.838379f, 0.851074f, 0.935059f, 0.938965f,
+ 0.937988f, 0.937012f, 0.936035f, 0.933594f, 0.001564f, 0.004665f, 0.007973f, 0.011276f, 0.014908f, 0.018600f, 0.022675f, 0.027176f,
+ 0.031464f, 0.036621f, 0.042023f, 0.047974f, 0.054108f, 0.060822f, 0.068237f, 0.075684f, 0.084229f, 0.093567f, 0.103210f, 0.113892f,
+ 0.125000f, 0.137329f, 0.150269f, 0.164307f, 0.179810f, 0.194946f, 0.212158f, 0.229248f, 0.247925f, 0.267578f, 0.287842f, 0.308350f,
+ 0.330322f, 0.352051f, 0.374756f, 0.397461f, 0.420654f, 0.444092f, 0.466797f, 0.490723f, 0.514160f, 0.537109f, 0.560059f, 0.582031f,
+ 0.604980f, 0.626953f, 0.648926f, 0.668457f, 0.688477f, 0.708008f, 0.727539f, 0.745117f, 0.763672f, 0.779297f, 0.795410f, 0.811523f,
+ 0.826660f, 0.840332f, 0.930664f, 0.934570f, 0.934082f, 0.933594f, 0.932129f, 0.930664f, 0.001424f, 0.004261f, 0.007122f, 0.010239f,
+ 0.013374f, 0.016693f, 0.020401f, 0.024368f, 0.028595f, 0.033325f, 0.037964f, 0.043152f, 0.048340f, 0.054962f, 0.060730f, 0.067749f,
+ 0.075684f, 0.083862f, 0.092041f, 0.102051f, 0.112305f, 0.123657f, 0.135376f, 0.148071f, 0.161987f, 0.176270f, 0.192139f, 0.208252f,
+ 0.226196f, 0.244141f, 0.263672f, 0.283447f, 0.304199f, 0.325195f, 0.346924f, 0.370605f, 0.392822f, 0.416260f, 0.439209f, 0.463623f,
+ 0.486084f, 0.511230f, 0.534180f, 0.558105f, 0.580566f, 0.603516f, 0.625000f, 0.647461f, 0.668457f, 0.688965f, 0.708496f, 0.727539f,
+ 0.746582f, 0.764160f, 0.781738f, 0.798340f, 0.813477f, 0.829590f, 0.926758f, 0.931152f, 0.930664f, 0.929199f, 0.928223f, 0.927246f,
+ 0.001294f, 0.004196f, 0.006538f, 0.009346f, 0.012306f, 0.015335f, 0.018845f, 0.022003f, 0.025558f, 0.029816f, 0.034149f, 0.038605f,
+ 0.043915f, 0.049042f, 0.054810f, 0.061188f, 0.067993f, 0.075256f, 0.083130f, 0.091553f, 0.100769f, 0.110779f, 0.121643f, 0.133057f,
+ 0.145630f, 0.159058f, 0.173218f, 0.188721f, 0.204590f, 0.222290f, 0.240234f, 0.259277f, 0.279053f, 0.299561f, 0.321533f, 0.343506f,
+ 0.365723f, 0.389404f, 0.412354f, 0.436035f, 0.459961f, 0.484131f, 0.508301f, 0.532227f, 0.555176f, 0.579102f, 0.601562f, 0.624512f,
+ 0.646484f, 0.668457f, 0.688965f, 0.709473f, 0.729004f, 0.748047f, 0.766602f, 0.784668f, 0.800293f, 0.817383f, 0.921875f, 0.926270f,
+ 0.926270f, 0.925781f, 0.924316f, 0.923340f, 0.001081f, 0.003603f, 0.006027f, 0.008575f, 0.010979f, 0.013847f, 0.016937f, 0.020020f,
+ 0.023315f, 0.026917f, 0.030930f, 0.035156f, 0.039429f, 0.044098f, 0.049622f, 0.054779f, 0.060791f, 0.067566f, 0.074341f, 0.082336f,
+ 0.090515f, 0.099548f, 0.109070f, 0.119263f, 0.130981f, 0.143188f, 0.156250f, 0.170288f, 0.185303f, 0.201294f, 0.218262f, 0.236450f,
+ 0.255615f, 0.275391f, 0.295654f, 0.316895f, 0.339111f, 0.362061f, 0.385498f, 0.408936f, 0.432861f, 0.457275f, 0.481689f, 0.505371f,
+ 0.529785f, 0.553711f, 0.577637f, 0.601074f, 0.624023f, 0.646484f, 0.669434f, 0.689941f, 0.711426f, 0.731445f, 0.750977f, 0.770020f,
+ 0.787598f, 0.804688f, 0.916992f, 0.922363f, 0.922363f, 0.921875f, 0.920898f, 0.918945f, 0.001064f, 0.003231f, 0.005322f, 0.007710f,
+ 0.010323f, 0.012489f, 0.015244f, 0.018051f, 0.020798f, 0.024338f, 0.027893f, 0.031738f, 0.035553f, 0.039795f, 0.044495f, 0.049133f,
+ 0.054657f, 0.060608f, 0.066895f, 0.073792f, 0.081421f, 0.089050f, 0.097717f, 0.106934f, 0.117554f, 0.128540f, 0.140503f, 0.153442f,
+ 0.167236f, 0.182129f, 0.197998f, 0.214966f, 0.232422f, 0.251465f, 0.271240f, 0.291992f, 0.313232f, 0.335693f, 0.358643f, 0.382080f,
+ 0.406006f, 0.430176f, 0.454590f, 0.479004f, 0.503906f, 0.528320f, 0.552734f, 0.577637f, 0.601562f, 0.625000f, 0.648438f, 0.670898f,
+ 0.691895f, 0.713867f, 0.733887f, 0.754883f, 0.774414f, 0.791992f, 0.912109f, 0.917969f, 0.918457f, 0.916992f, 0.916016f, 0.915039f,
+ 0.000998f, 0.003012f, 0.005123f, 0.007114f, 0.009438f, 0.011360f, 0.013763f, 0.016510f, 0.018951f, 0.022171f, 0.025101f, 0.028305f,
+ 0.031830f, 0.035736f, 0.039795f, 0.044067f, 0.048950f, 0.053864f, 0.059601f, 0.066345f, 0.072815f, 0.079956f, 0.087402f, 0.096375f,
+ 0.105835f, 0.115479f, 0.126343f, 0.138184f, 0.150635f, 0.164062f, 0.178711f, 0.194214f, 0.210815f, 0.229004f, 0.247314f, 0.267090f,
+ 0.288330f, 0.309570f, 0.332275f, 0.355469f, 0.378418f, 0.402832f, 0.427490f, 0.452637f, 0.477783f, 0.501953f, 0.527832f, 0.552734f,
+ 0.577637f, 0.602051f, 0.626465f, 0.649902f, 0.672852f, 0.695312f, 0.717773f, 0.737793f, 0.758789f, 0.778809f, 0.906250f, 0.913086f,
+ 0.913574f, 0.912598f, 0.911621f, 0.910645f, 0.001059f, 0.002985f, 0.004475f, 0.006496f, 0.008545f, 0.010300f, 0.012581f, 0.014969f,
+ 0.017471f, 0.019852f, 0.022507f, 0.025864f, 0.028824f, 0.032135f, 0.036041f, 0.039795f, 0.043884f, 0.048706f, 0.053680f, 0.059113f,
+ 0.064819f, 0.071472f, 0.078491f, 0.086365f, 0.094360f, 0.103577f, 0.113403f, 0.124023f, 0.135620f, 0.147705f, 0.160889f, 0.175537f,
+ 0.191284f, 0.207764f, 0.225464f, 0.244263f, 0.264160f, 0.284912f, 0.306641f, 0.329102f, 0.352295f, 0.376465f, 0.400635f, 0.426025f,
+ 0.451416f, 0.476562f, 0.502930f, 0.527344f, 0.553711f, 0.579102f, 0.603027f, 0.627930f, 0.652344f, 0.675781f, 0.700195f, 0.722168f,
+ 0.742676f, 0.764648f, 0.901367f, 0.907715f, 0.908691f, 0.908203f, 0.907227f, 0.906250f, 0.000988f, 0.002577f, 0.004124f, 0.006042f,
+ 0.007603f, 0.009506f, 0.011299f, 0.013680f, 0.015778f, 0.017883f, 0.020554f, 0.023102f, 0.025940f, 0.028946f, 0.031891f, 0.035431f,
+ 0.039825f, 0.043671f, 0.048157f, 0.053009f, 0.058075f, 0.063782f, 0.069885f, 0.077087f, 0.084839f, 0.092712f, 0.101379f, 0.110779f,
+ 0.121155f, 0.132446f, 0.144775f, 0.157837f, 0.172363f, 0.187744f, 0.204590f, 0.222290f, 0.240601f, 0.260254f, 0.281494f, 0.303223f,
+ 0.325439f, 0.349609f, 0.373535f, 0.399170f, 0.424561f, 0.450439f, 0.475586f, 0.501953f, 0.528320f, 0.554688f, 0.580566f, 0.605957f,
+ 0.630859f, 0.656250f, 0.680176f, 0.704102f, 0.727051f, 0.749512f, 0.895508f, 0.902344f, 0.903320f, 0.902832f, 0.901855f, 0.901855f,
+ 0.000842f, 0.002253f, 0.003597f, 0.005352f, 0.007195f, 0.008804f, 0.010460f, 0.012100f, 0.014130f, 0.016281f, 0.018341f, 0.021057f,
+ 0.023193f, 0.025742f, 0.029022f, 0.031830f, 0.035278f, 0.039246f, 0.042999f, 0.047211f, 0.052032f, 0.056946f, 0.062744f, 0.068848f,
+ 0.075195f, 0.082642f, 0.090332f, 0.099060f, 0.108215f, 0.118469f, 0.129517f, 0.141724f, 0.154907f, 0.169434f, 0.184448f, 0.201172f,
+ 0.218506f, 0.237427f, 0.257324f, 0.278320f, 0.300293f, 0.323242f, 0.347412f, 0.372070f, 0.397217f, 0.423340f, 0.449707f, 0.476807f,
+ 0.502930f, 0.529785f, 0.556641f, 0.582520f, 0.609863f, 0.635254f, 0.660645f, 0.686035f, 0.710938f, 0.733887f, 0.889648f, 0.897461f,
+ 0.898926f, 0.896973f, 0.896973f, 0.896484f, 0.000660f, 0.002014f, 0.003531f, 0.004951f, 0.006424f, 0.007935f, 0.009392f, 0.011322f,
+ 0.012924f, 0.014824f, 0.016754f, 0.018906f, 0.020935f, 0.023376f, 0.026245f, 0.028809f, 0.031860f, 0.034821f, 0.038330f, 0.042236f,
+ 0.046387f, 0.050812f, 0.056061f, 0.061279f, 0.066956f, 0.073547f, 0.080566f, 0.088074f, 0.096802f, 0.106079f, 0.116089f, 0.127075f,
+ 0.138672f, 0.151855f, 0.165649f, 0.180908f, 0.197754f, 0.215332f, 0.234375f, 0.254150f, 0.275391f, 0.298096f, 0.321533f, 0.344971f,
+ 0.370361f, 0.396973f, 0.422852f, 0.449219f, 0.477295f, 0.504395f, 0.532227f, 0.558594f, 0.586914f, 0.614258f, 0.640625f, 0.666016f,
+ 0.692871f, 0.718262f, 0.882812f, 0.891602f, 0.892578f, 0.892090f, 0.892090f, 0.890625f, 0.000623f, 0.002073f, 0.003298f, 0.004292f,
+ 0.005589f, 0.007401f, 0.008377f, 0.010315f, 0.011871f, 0.013596f, 0.015213f, 0.016632f, 0.018829f, 0.020920f, 0.023239f, 0.025726f,
+ 0.028381f, 0.031250f, 0.034241f, 0.037781f, 0.041473f, 0.045349f, 0.049469f, 0.054199f, 0.059448f, 0.065186f, 0.071716f, 0.078613f,
+ 0.085999f, 0.093872f, 0.103516f, 0.112976f, 0.123840f, 0.135620f, 0.148804f, 0.162720f, 0.178223f, 0.194824f, 0.212280f, 0.231079f,
+ 0.251953f, 0.273193f, 0.295410f, 0.319580f, 0.343994f, 0.370117f, 0.396729f, 0.422852f, 0.450684f, 0.478516f, 0.507324f, 0.534668f,
+ 0.562988f, 0.591797f, 0.619629f, 0.646484f, 0.674316f, 0.700195f, 0.875488f, 0.885254f, 0.886719f, 0.886719f, 0.885742f, 0.885254f,
+ 0.000583f, 0.001746f, 0.002840f, 0.004143f, 0.005234f, 0.006516f, 0.007835f, 0.009460f, 0.010788f, 0.012062f, 0.013428f, 0.015053f,
+ 0.017349f, 0.018753f, 0.021271f, 0.023163f, 0.025284f, 0.027924f, 0.030655f, 0.033478f, 0.036957f, 0.040527f, 0.044037f, 0.048309f,
+ 0.053223f, 0.058319f, 0.063660f, 0.069763f, 0.076172f, 0.083679f, 0.091431f, 0.100647f, 0.110229f, 0.120667f, 0.132690f, 0.145386f,
+ 0.159668f, 0.174805f, 0.191284f, 0.208984f, 0.228516f, 0.248535f, 0.270996f, 0.293701f, 0.317383f, 0.342529f, 0.369629f, 0.396240f,
+ 0.424072f, 0.452148f, 0.480957f, 0.509277f, 0.539551f, 0.567871f, 0.596680f, 0.625977f, 0.654785f, 0.682129f, 0.868652f, 0.878906f,
+ 0.880371f, 0.879883f, 0.879883f, 0.879395f, 0.000535f, 0.001538f, 0.002930f, 0.003725f, 0.004986f, 0.005920f, 0.006973f, 0.008247f,
+ 0.009575f, 0.010841f, 0.012115f, 0.013550f, 0.015343f, 0.016983f, 0.018814f, 0.020523f, 0.022568f, 0.024887f, 0.027206f, 0.029907f,
+ 0.032959f, 0.035828f, 0.039185f, 0.042877f, 0.046967f, 0.051605f, 0.056213f, 0.061432f, 0.067749f, 0.073730f, 0.081238f, 0.089111f,
+ 0.097656f, 0.107300f, 0.118042f, 0.129883f, 0.142334f, 0.156250f, 0.171875f, 0.187866f, 0.206665f, 0.225708f, 0.246704f, 0.268799f,
+ 0.291992f, 0.316650f, 0.342529f, 0.369629f, 0.397217f, 0.425537f, 0.454590f, 0.484131f, 0.513672f, 0.544434f, 0.574219f, 0.604492f,
+ 0.633789f, 0.664062f, 0.861328f, 0.871582f, 0.873535f, 0.874512f, 0.873047f, 0.872559f, 0.000581f, 0.001668f, 0.002563f, 0.003471f,
+ 0.004494f, 0.005562f, 0.006580f, 0.007782f, 0.008690f, 0.009766f, 0.011261f, 0.012314f, 0.013901f, 0.014969f, 0.016479f, 0.018265f,
+ 0.020294f, 0.022156f, 0.024353f, 0.026505f, 0.029053f, 0.031799f, 0.034607f, 0.037964f, 0.041382f, 0.045471f, 0.049591f, 0.054047f,
+ 0.059326f, 0.065186f, 0.071411f, 0.078735f, 0.086304f, 0.094971f, 0.104126f, 0.114807f, 0.126587f, 0.138916f, 0.153564f, 0.169067f,
+ 0.185669f, 0.203613f, 0.223389f, 0.244629f, 0.266602f, 0.291260f, 0.316406f, 0.342773f, 0.370361f, 0.398926f, 0.427734f, 0.458008f,
+ 0.488770f, 0.520020f, 0.550293f, 0.582031f, 0.613281f, 0.645020f, 0.854004f, 0.865234f, 0.866699f, 0.867188f, 0.866699f, 0.866699f,
+ 0.000571f, 0.001365f, 0.002483f, 0.003033f, 0.004120f, 0.005054f, 0.005981f, 0.006737f, 0.007603f, 0.008675f, 0.009789f, 0.011078f,
+ 0.012413f, 0.013626f, 0.014908f, 0.016174f, 0.017792f, 0.019699f, 0.021591f, 0.023499f, 0.025635f, 0.028000f, 0.030533f, 0.033417f,
+ 0.036499f, 0.039948f, 0.043762f, 0.047943f, 0.052460f, 0.057465f, 0.062622f, 0.068848f, 0.076111f, 0.083557f, 0.092102f, 0.101562f,
+ 0.111816f, 0.123230f, 0.135864f, 0.150024f, 0.165771f, 0.182373f, 0.200806f, 0.221191f, 0.242920f, 0.265869f, 0.290283f, 0.316406f,
+ 0.343262f, 0.371582f, 0.400879f, 0.431396f, 0.463623f, 0.494629f, 0.526367f, 0.558105f, 0.591309f, 0.624023f, 0.845215f, 0.856934f,
+ 0.859375f, 0.859375f, 0.859863f, 0.860352f, 0.000411f, 0.001296f, 0.002012f, 0.002808f, 0.003754f, 0.004543f, 0.005215f, 0.006012f,
+ 0.006725f, 0.007851f, 0.008888f, 0.009979f, 0.010994f, 0.012009f, 0.013062f, 0.014549f, 0.016113f, 0.017441f, 0.019073f, 0.020767f,
+ 0.022598f, 0.024689f, 0.026764f, 0.029358f, 0.032043f, 0.034760f, 0.038391f, 0.041779f, 0.045380f, 0.050110f, 0.055054f, 0.060394f,
+ 0.066650f, 0.073120f, 0.080688f, 0.089233f, 0.098450f, 0.108582f, 0.120178f, 0.133057f, 0.146973f, 0.162354f, 0.179565f, 0.198364f,
+ 0.218750f, 0.240967f, 0.264648f, 0.290039f, 0.316650f, 0.344971f, 0.374023f, 0.404541f, 0.435791f, 0.467773f, 0.500977f, 0.535156f,
+ 0.569336f, 0.601562f, 0.836914f, 0.850098f, 0.852051f, 0.852539f, 0.852539f, 0.852051f, 0.000408f, 0.001071f, 0.001857f, 0.002573f,
+ 0.003338f, 0.004078f, 0.004692f, 0.005379f, 0.006046f, 0.007275f, 0.007957f, 0.008606f, 0.009598f, 0.010864f, 0.011658f, 0.013084f,
+ 0.013977f, 0.015366f, 0.016724f, 0.018402f, 0.019669f, 0.021759f, 0.023697f, 0.025726f, 0.027954f, 0.030640f, 0.033356f, 0.036530f,
+ 0.039948f, 0.043701f, 0.047791f, 0.052704f, 0.057770f, 0.063782f, 0.070129f, 0.077881f, 0.085999f, 0.095337f, 0.105591f, 0.116882f,
+ 0.130005f, 0.143921f, 0.159302f, 0.177246f, 0.196411f, 0.217163f, 0.239746f, 0.263916f, 0.290039f, 0.317871f, 0.346924f, 0.377441f,
+ 0.408936f, 0.442139f, 0.476074f, 0.509766f, 0.545410f, 0.580078f, 0.828613f, 0.841309f, 0.843262f, 0.844238f, 0.843750f, 0.844238f,
+ 0.000322f, 0.001009f, 0.001674f, 0.002262f, 0.002949f, 0.003633f, 0.004250f, 0.004780f, 0.005478f, 0.006256f, 0.007248f, 0.007919f,
+ 0.008720f, 0.009552f, 0.010277f, 0.011391f, 0.012291f, 0.013466f, 0.014786f, 0.015976f, 0.017288f, 0.019043f, 0.020477f, 0.022385f,
+ 0.024292f, 0.026276f, 0.029175f, 0.031769f, 0.034546f, 0.037842f, 0.041626f, 0.045868f, 0.050293f, 0.055084f, 0.060669f, 0.067688f,
+ 0.074585f, 0.083008f, 0.092102f, 0.102234f, 0.113525f, 0.126587f, 0.140869f, 0.156860f, 0.174805f, 0.194214f, 0.215698f, 0.239014f,
+ 0.264404f, 0.291016f, 0.320068f, 0.350098f, 0.382080f, 0.414551f, 0.449463f, 0.485107f, 0.520996f, 0.557617f, 0.818848f, 0.833496f,
+ 0.836426f, 0.836914f, 0.836426f, 0.835938f, 0.000483f, 0.000841f, 0.001632f, 0.002142f, 0.002678f, 0.003359f, 0.003830f, 0.004333f,
+ 0.005077f, 0.005527f, 0.006104f, 0.006908f, 0.007675f, 0.008392f, 0.009216f, 0.009789f, 0.010880f, 0.011719f, 0.012817f, 0.013809f,
+ 0.015068f, 0.016357f, 0.017883f, 0.019485f, 0.021271f, 0.022995f, 0.025162f, 0.027359f, 0.029755f, 0.032806f, 0.036133f, 0.039459f,
+ 0.043091f, 0.047821f, 0.052368f, 0.058258f, 0.064514f, 0.071472f, 0.079224f, 0.088623f, 0.098694f, 0.109924f, 0.123230f, 0.137817f,
+ 0.154053f, 0.172363f, 0.192261f, 0.214478f, 0.238647f, 0.265137f, 0.292725f, 0.322998f, 0.354492f, 0.387695f, 0.422363f, 0.458740f,
+ 0.495605f, 0.533691f, 0.809570f, 0.824219f, 0.826660f, 0.827148f, 0.828125f, 0.827148f, 0.000240f, 0.000906f, 0.001379f, 0.001807f,
+ 0.002495f, 0.002916f, 0.003490f, 0.004139f, 0.004471f, 0.004898f, 0.005638f, 0.005978f, 0.006874f, 0.007313f, 0.007957f, 0.008698f,
+ 0.009560f, 0.010178f, 0.011345f, 0.012177f, 0.012985f, 0.014214f, 0.015274f, 0.016708f, 0.017929f, 0.019882f, 0.021393f, 0.023560f,
+ 0.025406f, 0.028137f, 0.030472f, 0.033752f, 0.036896f, 0.040619f, 0.044952f, 0.049622f, 0.055298f, 0.061249f, 0.068420f, 0.075928f,
+ 0.084900f, 0.095398f, 0.107300f, 0.119934f, 0.134766f, 0.151733f, 0.170410f, 0.191284f, 0.213867f, 0.238647f, 0.265869f, 0.295654f,
+ 0.326660f, 0.359863f, 0.394775f, 0.432129f, 0.469482f, 0.508789f, 0.798340f, 0.814941f, 0.817871f, 0.818359f, 0.818848f, 0.818848f,
+ 0.000376f, 0.000870f, 0.001291f, 0.001619f, 0.002251f, 0.002520f, 0.003016f, 0.003502f, 0.004036f, 0.004299f, 0.004723f, 0.005234f,
+ 0.005840f, 0.006512f, 0.006908f, 0.007595f, 0.008003f, 0.008797f, 0.009773f, 0.010536f, 0.011284f, 0.012161f, 0.013237f, 0.014465f,
+ 0.015579f, 0.016968f, 0.018402f, 0.019882f, 0.021759f, 0.023621f, 0.026138f, 0.028488f, 0.031738f, 0.034668f, 0.038239f, 0.042389f,
+ 0.046783f, 0.052094f, 0.058319f, 0.064941f, 0.072815f, 0.081726f, 0.092102f, 0.103516f, 0.117188f, 0.132202f, 0.149048f, 0.168091f,
+ 0.189941f, 0.213745f, 0.239990f, 0.268311f, 0.299316f, 0.332275f, 0.367188f, 0.403076f, 0.442871f, 0.483398f, 0.788086f, 0.805176f,
+ 0.808105f, 0.808594f, 0.809082f, 0.809082f, 0.000386f, 0.000765f, 0.000998f, 0.001537f, 0.001833f, 0.002407f, 0.002529f, 0.003113f,
+ 0.003334f, 0.003841f, 0.004192f, 0.004585f, 0.005096f, 0.005543f, 0.006073f, 0.006405f, 0.007118f, 0.007641f, 0.008278f, 0.008957f,
+ 0.009651f, 0.010498f, 0.011307f, 0.012184f, 0.013199f, 0.014343f, 0.015671f, 0.016678f, 0.018585f, 0.019852f, 0.021881f, 0.023987f,
+ 0.026398f, 0.029099f, 0.032227f, 0.035339f, 0.039246f, 0.043915f, 0.048859f, 0.054688f, 0.061554f, 0.069519f, 0.078247f, 0.088379f,
+ 0.100037f, 0.113770f, 0.129272f, 0.146606f, 0.166626f, 0.189575f, 0.214111f, 0.241577f, 0.271973f, 0.304199f, 0.339844f, 0.375977f,
+ 0.415527f, 0.457275f, 0.776855f, 0.794434f, 0.797363f, 0.797852f, 0.798828f, 0.799316f, 0.000232f, 0.000636f, 0.000996f, 0.001201f,
+ 0.001721f, 0.002029f, 0.002340f, 0.002802f, 0.003012f, 0.003462f, 0.003693f, 0.004059f, 0.004295f, 0.004822f, 0.005077f, 0.005623f,
+ 0.006126f, 0.006653f, 0.007027f, 0.007561f, 0.008049f, 0.008904f, 0.009399f, 0.010300f, 0.011200f, 0.012115f, 0.013092f, 0.014221f,
+ 0.015671f, 0.016891f, 0.018433f, 0.020294f, 0.022064f, 0.024277f, 0.026688f, 0.029678f, 0.032654f, 0.036499f, 0.040955f, 0.045715f,
+ 0.051514f, 0.058014f, 0.065674f, 0.074707f, 0.084717f, 0.096802f, 0.111023f, 0.126709f, 0.144775f, 0.165771f, 0.189209f, 0.215820f,
+ 0.244385f, 0.275879f, 0.310547f, 0.348145f, 0.387695f, 0.429932f, 0.765137f, 0.783203f, 0.787109f, 0.788574f, 0.788574f, 0.789551f,
+ 0.000171f, 0.000518f, 0.001106f, 0.001242f, 0.001475f, 0.001939f, 0.002092f, 0.002254f, 0.002607f, 0.002930f, 0.003084f, 0.003382f,
+ 0.003674f, 0.004040f, 0.004395f, 0.004780f, 0.005157f, 0.005653f, 0.006088f, 0.006355f, 0.006870f, 0.007420f, 0.008057f, 0.008667f,
+ 0.009361f, 0.010040f, 0.011101f, 0.011803f, 0.012711f, 0.013962f, 0.015343f, 0.016586f, 0.018036f, 0.020142f, 0.022079f, 0.024399f,
+ 0.027023f, 0.030075f, 0.033569f, 0.037750f, 0.042603f, 0.048096f, 0.054718f, 0.062134f, 0.071045f, 0.081299f, 0.093445f, 0.107605f,
+ 0.124268f, 0.142944f, 0.165405f, 0.189941f, 0.218262f, 0.249268f, 0.282227f, 0.319336f, 0.359375f, 0.402832f, 0.752930f, 0.771973f,
+ 0.775879f, 0.776855f, 0.777832f, 0.777832f, 0.000204f, 0.000608f, 0.000865f, 0.001011f, 0.001362f, 0.001632f, 0.001817f, 0.001930f,
+ 0.002274f, 0.002491f, 0.002796f, 0.002932f, 0.003139f, 0.003429f, 0.003736f, 0.004055f, 0.004448f, 0.004829f, 0.004971f, 0.005497f,
+ 0.005859f, 0.006298f, 0.006741f, 0.007080f, 0.007687f, 0.008308f, 0.009087f, 0.009880f, 0.010735f, 0.011528f, 0.012375f, 0.013664f,
+ 0.014862f, 0.016464f, 0.017868f, 0.019852f, 0.022156f, 0.024490f, 0.027435f, 0.030853f, 0.034637f, 0.039154f, 0.044495f, 0.050964f,
+ 0.058441f, 0.067383f, 0.077759f, 0.090332f, 0.104797f, 0.121826f, 0.142334f, 0.164795f, 0.191528f, 0.221313f, 0.254150f, 0.290771f,
+ 0.330078f, 0.374268f, 0.740234f, 0.759277f, 0.763672f, 0.766113f, 0.766602f, 0.766113f, 0.000150f, 0.000514f, 0.000666f, 0.000865f,
+ 0.001163f, 0.001389f, 0.001540f, 0.001672f, 0.001940f, 0.002110f, 0.002302f, 0.002419f, 0.002745f, 0.002974f, 0.003120f, 0.003366f,
+ 0.003695f, 0.003815f, 0.004173f, 0.004574f, 0.004879f, 0.005165f, 0.005646f, 0.006058f, 0.006481f, 0.006969f, 0.007626f, 0.007881f,
+ 0.008751f, 0.009445f, 0.010231f, 0.011246f, 0.012222f, 0.013268f, 0.014641f, 0.015976f, 0.017792f, 0.019867f, 0.021912f, 0.024704f,
+ 0.027786f, 0.031494f, 0.036011f, 0.041229f, 0.047363f, 0.054962f, 0.063904f, 0.074463f, 0.087036f, 0.102295f, 0.120483f, 0.141113f,
+ 0.166260f, 0.194214f, 0.226196f, 0.261719f, 0.301514f, 0.345459f, 0.727051f, 0.747070f, 0.751953f, 0.753418f, 0.754395f, 0.754883f,
+ 0.000103f, 0.000251f, 0.000628f, 0.000912f, 0.000978f, 0.001191f, 0.001365f, 0.001507f, 0.001513f, 0.001757f, 0.001980f, 0.002121f,
+ 0.002316f, 0.002373f, 0.002645f, 0.002909f, 0.003012f, 0.003305f, 0.003538f, 0.003775f, 0.004070f, 0.004246f, 0.004642f, 0.004986f,
+ 0.005394f, 0.005802f, 0.006031f, 0.006565f, 0.006969f, 0.007618f, 0.008293f, 0.008980f, 0.009766f, 0.010612f, 0.011528f, 0.012802f,
+ 0.014198f, 0.015671f, 0.017517f, 0.019592f, 0.021957f, 0.024918f, 0.028442f, 0.032562f, 0.037567f, 0.043762f, 0.051025f, 0.059753f,
+ 0.071045f, 0.084412f, 0.099792f, 0.119385f, 0.141846f, 0.167969f, 0.199341f, 0.233521f, 0.272461f, 0.315674f, 0.712891f, 0.733887f,
+ 0.738770f, 0.740234f, 0.741211f, 0.741699f, 0.000185f, 0.000434f, 0.000489f, 0.000732f, 0.000874f, 0.000968f, 0.001122f, 0.001124f,
+ 0.001371f, 0.001423f, 0.001639f, 0.001693f, 0.001805f, 0.002094f, 0.002241f, 0.002356f, 0.002567f, 0.002691f, 0.002871f, 0.003063f,
+ 0.003195f, 0.003582f, 0.003790f, 0.004089f, 0.004372f, 0.004536f, 0.005085f, 0.005314f, 0.005699f, 0.006153f, 0.006672f, 0.007202f,
+ 0.007805f, 0.008522f, 0.009216f, 0.010071f, 0.011086f, 0.012184f, 0.013596f, 0.015297f, 0.017014f, 0.019363f, 0.021988f, 0.025299f,
+ 0.029282f, 0.033936f, 0.040070f, 0.047028f, 0.056519f, 0.067932f, 0.080872f, 0.098083f, 0.118469f, 0.143188f, 0.171753f, 0.205200f,
+ 0.243286f, 0.286133f, 0.698730f, 0.721680f, 0.725098f, 0.727051f, 0.728027f, 0.728516f, 0.000116f, 0.000267f, 0.000565f, 0.000505f,
+ 0.000648f, 0.000772f, 0.000813f, 0.001031f, 0.001107f, 0.001184f, 0.001335f, 0.001391f, 0.001451f, 0.001633f, 0.001798f, 0.001874f,
+ 0.002090f, 0.002192f, 0.002392f, 0.002464f, 0.002707f, 0.002895f, 0.003044f, 0.003206f, 0.003468f, 0.003666f, 0.003887f, 0.004261f,
+ 0.004524f, 0.004898f, 0.005379f, 0.005711f, 0.006130f, 0.006721f, 0.007267f, 0.007912f, 0.008659f, 0.009575f, 0.010475f, 0.011749f,
+ 0.013252f, 0.014717f, 0.016815f, 0.019302f, 0.022369f, 0.025955f, 0.030502f, 0.036285f, 0.043579f, 0.052795f, 0.064453f, 0.078735f,
+ 0.096497f, 0.118591f, 0.145508f, 0.177368f, 0.213989f, 0.256592f, 0.683105f, 0.707031f, 0.710938f, 0.713379f, 0.714844f, 0.714844f,
+ 0.000223f, 0.000239f, 0.000286f, 0.000476f, 0.000580f, 0.000647f, 0.000715f, 0.000843f, 0.000914f, 0.000950f, 0.001090f, 0.001163f,
+ 0.001259f, 0.001328f, 0.001392f, 0.001560f, 0.001549f, 0.001775f, 0.001868f, 0.001999f, 0.002199f, 0.002235f, 0.002436f, 0.002575f,
+ 0.002842f, 0.002892f, 0.003111f, 0.003401f, 0.003563f, 0.003887f, 0.004196f, 0.004505f, 0.004791f, 0.005142f, 0.005684f, 0.006153f,
+ 0.006710f, 0.007378f, 0.008064f, 0.008881f, 0.009979f, 0.011177f, 0.012779f, 0.014435f, 0.016647f, 0.019150f, 0.022583f, 0.027252f,
+ 0.033051f, 0.040039f, 0.049561f, 0.061340f, 0.076843f, 0.096313f, 0.120544f, 0.150513f, 0.185547f, 0.227173f, 0.668457f, 0.692383f,
+ 0.696289f, 0.698242f, 0.699219f, 0.701172f, 0.000000f, 0.000109f, 0.000315f, 0.000449f, 0.000511f, 0.000507f, 0.000538f, 0.000653f,
+ 0.000724f, 0.000749f, 0.000830f, 0.000893f, 0.001007f, 0.001079f, 0.001189f, 0.001163f, 0.001335f, 0.001307f, 0.001502f, 0.001575f,
+ 0.001627f, 0.001778f, 0.001933f, 0.002029f, 0.002155f, 0.002254f, 0.002401f, 0.002535f, 0.002829f, 0.002943f, 0.003143f, 0.003422f,
+ 0.003710f, 0.003990f, 0.004318f, 0.004627f, 0.005108f, 0.005585f, 0.006142f, 0.006641f, 0.007378f, 0.008354f, 0.009430f, 0.010628f,
+ 0.012123f, 0.014015f, 0.016541f, 0.019836f, 0.023849f, 0.029312f, 0.036774f, 0.046356f, 0.058868f, 0.075562f, 0.097107f, 0.124634f,
+ 0.157837f, 0.197754f, 0.653320f, 0.677734f, 0.682129f, 0.684082f, 0.685547f, 0.684570f, 0.000166f, 0.000195f, 0.000256f, 0.000372f,
+ 0.000386f, 0.000415f, 0.000515f, 0.000432f, 0.000579f, 0.000606f, 0.000706f, 0.000745f, 0.000764f, 0.000837f, 0.000853f, 0.000993f,
+ 0.001034f, 0.001066f, 0.001156f, 0.001203f, 0.001339f, 0.001418f, 0.001470f, 0.001612f, 0.001614f, 0.001707f, 0.001850f, 0.001986f,
+ 0.002151f, 0.002254f, 0.002499f, 0.002560f, 0.002794f, 0.003000f, 0.003212f, 0.003510f, 0.003761f, 0.004086f, 0.004475f, 0.004967f,
+ 0.005428f, 0.006134f, 0.006840f, 0.007786f, 0.008858f, 0.010033f, 0.011909f, 0.014137f, 0.016907f, 0.020767f, 0.025894f, 0.033386f,
+ 0.043274f, 0.056854f, 0.075439f, 0.099548f, 0.130737f, 0.169434f, 0.634277f, 0.661133f, 0.667480f, 0.668945f, 0.669922f, 0.670898f,
+ 0.000115f, 0.000119f, 0.000230f, 0.000304f, 0.000221f, 0.000380f, 0.000322f, 0.000351f, 0.000453f, 0.000527f, 0.000535f, 0.000558f,
+ 0.000595f, 0.000675f, 0.000707f, 0.000670f, 0.000776f, 0.000812f, 0.000839f, 0.000911f, 0.000974f, 0.001033f, 0.001082f, 0.001154f,
+ 0.001209f, 0.001268f, 0.001416f, 0.001432f, 0.001607f, 0.001775f, 0.001877f, 0.001911f, 0.002041f, 0.002207f, 0.002380f, 0.002563f,
+ 0.002741f, 0.002956f, 0.003281f, 0.003513f, 0.003902f, 0.004353f, 0.004803f, 0.005405f, 0.006256f, 0.007072f, 0.008263f, 0.009659f,
+ 0.011627f, 0.014221f, 0.017792f, 0.022919f, 0.030075f, 0.040497f, 0.055878f, 0.076721f, 0.104980f, 0.141357f, 0.618652f, 0.644531f,
+ 0.650391f, 0.652832f, 0.653320f, 0.654785f, 0.000000f, 0.000122f, 0.000142f, 0.000227f, 0.000248f, 0.000246f, 0.000296f, 0.000254f,
+ 0.000308f, 0.000329f, 0.000387f, 0.000437f, 0.000443f, 0.000504f, 0.000515f, 0.000535f, 0.000566f, 0.000592f, 0.000618f, 0.000641f,
+ 0.000706f, 0.000746f, 0.000787f, 0.000839f, 0.000878f, 0.000920f, 0.001043f, 0.001041f, 0.001136f, 0.001199f, 0.001258f, 0.001393f,
+ 0.001428f, 0.001549f, 0.001632f, 0.001856f, 0.001945f, 0.002079f, 0.002310f, 0.002489f, 0.002708f, 0.002996f, 0.003315f, 0.003759f,
+ 0.004177f, 0.004803f, 0.005619f, 0.006527f, 0.007793f, 0.009468f, 0.011917f, 0.015152f, 0.019897f, 0.027298f, 0.038910f, 0.055908f,
+ 0.080811f, 0.114563f, 0.600586f, 0.628906f, 0.634277f, 0.636719f, 0.637207f, 0.638672f, 0.000000f, 0.000000f, 0.000106f, 0.000137f,
+ 0.000172f, 0.000211f, 0.000189f, 0.000226f, 0.000230f, 0.000248f, 0.000293f, 0.000251f, 0.000264f, 0.000321f, 0.000343f, 0.000399f,
+ 0.000368f, 0.000401f, 0.000499f, 0.000479f, 0.000498f, 0.000526f, 0.000550f, 0.000595f, 0.000631f, 0.000645f, 0.000726f, 0.000717f,
+ 0.000786f, 0.000902f, 0.000865f, 0.000916f, 0.000989f, 0.001059f, 0.001165f, 0.001246f, 0.001279f, 0.001408f, 0.001566f, 0.001628f,
+ 0.001808f, 0.001991f, 0.002165f, 0.002466f, 0.002766f, 0.003084f, 0.003534f, 0.004250f, 0.005016f, 0.006130f, 0.007584f, 0.009605f,
+ 0.012718f, 0.017395f, 0.025131f, 0.038269f, 0.058899f, 0.089661f, 0.582031f, 0.611328f, 0.616699f, 0.620117f, 0.621094f, 0.622559f,
+ 0.000000f, 0.000108f, 0.000104f, 0.000095f, 0.000117f, 0.000117f, 0.000122f, 0.000143f, 0.000147f, 0.000164f, 0.000174f, 0.000216f,
+ 0.000191f, 0.000227f, 0.000241f, 0.000250f, 0.000257f, 0.000271f, 0.000301f, 0.000298f, 0.000317f, 0.000344f, 0.000370f, 0.000392f,
+ 0.000404f, 0.000427f, 0.000491f, 0.000491f, 0.000519f, 0.000535f, 0.000611f, 0.000601f, 0.000668f, 0.000698f, 0.000767f, 0.000838f,
+ 0.000865f, 0.000895f, 0.000993f, 0.001066f, 0.001161f, 0.001242f, 0.001415f, 0.001521f, 0.001743f, 0.001901f, 0.002209f, 0.002523f,
+ 0.003038f, 0.003601f, 0.004478f, 0.005699f, 0.007545f, 0.010437f, 0.015175f, 0.023682f, 0.039429f, 0.066406f, 0.563477f, 0.593262f,
+ 0.598633f, 0.602051f, 0.602539f, 0.603516f, 0.000000f, 0.000101f, 0.000093f, 0.000087f, 0.000082f, 0.000078f, 0.000084f, 0.000087f,
+ 0.000093f, 0.000094f, 0.000099f, 0.000104f, 0.000114f, 0.000123f, 0.000158f, 0.000163f, 0.000166f, 0.000178f, 0.000177f, 0.000214f,
+ 0.000191f, 0.000208f, 0.000212f, 0.000247f, 0.000268f, 0.000263f, 0.000272f, 0.000287f, 0.000310f, 0.000336f, 0.000353f, 0.000368f,
+ 0.000396f, 0.000408f, 0.000453f, 0.000476f, 0.000511f, 0.000540f, 0.000615f, 0.000635f, 0.000682f, 0.000751f, 0.000812f, 0.000908f,
+ 0.000987f, 0.001116f, 0.001278f, 0.001431f, 0.001702f, 0.002047f, 0.002512f, 0.003126f, 0.004181f, 0.005817f, 0.008553f, 0.013489f,
+ 0.023697f, 0.045288f, 0.544922f, 0.575684f, 0.581543f, 0.584473f, 0.585938f, 0.587402f, 0.000109f, 0.000091f, 0.000081f, 0.000075f,
+ 0.000070f, 0.000067f, 0.000064f, 0.000061f, 0.000057f, 0.000054f, 0.000058f, 0.000075f, 0.000062f, 0.000064f, 0.000085f, 0.000068f,
+ 0.000092f, 0.000094f, 0.000103f, 0.000110f, 0.000113f, 0.000119f, 0.000141f, 0.000141f, 0.000148f, 0.000152f, 0.000159f, 0.000164f,
+ 0.000175f, 0.000188f, 0.000184f, 0.000218f, 0.000233f, 0.000223f, 0.000253f, 0.000265f, 0.000282f, 0.000321f, 0.000322f, 0.000351f,
+ 0.000371f, 0.000405f, 0.000443f, 0.000478f, 0.000515f, 0.000571f, 0.000652f, 0.000733f, 0.000856f, 0.001011f, 0.001227f, 0.001531f,
+ 0.002029f, 0.002817f, 0.004215f, 0.006874f, 0.012390f, 0.027405f, 0.525879f, 0.557129f, 0.563477f, 0.566895f, 0.568848f, 0.569824f,
+ 0.000094f, 0.000073f, 0.000065f, 0.000060f, 0.000055f, 0.000052f, 0.000049f, 0.000048f, 0.000046f, 0.000045f, 0.000042f, 0.000040f,
+ 0.000040f, 0.000037f, 0.000035f, 0.000035f, 0.000042f, 0.000036f, 0.000049f, 0.000051f, 0.000055f, 0.000056f, 0.000059f, 0.000062f,
+ 0.000064f, 0.000078f, 0.000071f, 0.000079f, 0.000088f, 0.000091f, 0.000093f, 0.000099f, 0.000103f, 0.000110f, 0.000125f, 0.000123f,
+ 0.000127f, 0.000151f, 0.000151f, 0.000161f, 0.000169f, 0.000179f, 0.000204f, 0.000219f, 0.000240f, 0.000267f, 0.000294f, 0.000321f,
+ 0.000378f, 0.000438f, 0.000524f, 0.000628f, 0.000818f, 0.001125f, 0.001693f, 0.002888f, 0.005638f, 0.013580f, 0.505859f, 0.539062f,
+ 0.544922f, 0.548340f, 0.550293f, 0.550781f, 0.000064f, 0.000048f, 0.000041f, 0.000037f, 0.000035f, 0.000034f, 0.000032f, 0.000031f,
+ 0.000030f, 0.000029f, 0.000028f, 0.000028f, 0.000027f, 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000022f, 0.000021f,
+ 0.000020f, 0.000019f, 0.000019f, 0.000023f, 0.000021f, 0.000022f, 0.000026f, 0.000029f, 0.000032f, 0.000031f, 0.000036f, 0.000037f,
+ 0.000036f, 0.000044f, 0.000046f, 0.000048f, 0.000052f, 0.000054f, 0.000056f, 0.000061f, 0.000070f, 0.000073f, 0.000076f, 0.000081f,
+ 0.000082f, 0.000095f, 0.000105f, 0.000120f, 0.000126f, 0.000143f, 0.000173f, 0.000203f, 0.000267f, 0.000346f, 0.000505f, 0.000853f,
+ 0.001829f, 0.005222f, 0.487061f, 0.519531f, 0.527344f, 0.529785f, 0.531738f, 0.532715f, 0.000000f, 0.000002f, 0.000003f, 0.000004f,
+ 0.000008f, 0.000008f, 0.000008f, 0.000010f, 0.000009f, 0.000010f, 0.000010f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f,
+ 0.000012f, 0.000011f, 0.000012f, 0.000011f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f,
+ 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000007f, 0.000008f, 0.000009f, 0.000010f, 0.000012f, 0.000012f, 0.000015f,
+ 0.000013f, 0.000015f, 0.000018f, 0.000020f, 0.000021f, 0.000022f, 0.000022f, 0.000024f, 0.000026f, 0.000027f, 0.000034f, 0.000043f,
+ 0.000049f, 0.000065f, 0.000089f, 0.000138f, 0.000293f, 0.001143f, 0.466553f, 0.500488f, 0.508301f, 0.510742f, 0.512207f, 0.513672f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000004f, 0.000006f, 0.000023f, 0.446777f, 0.482178f,
+ 0.489746f, 0.492676f, 0.494629f, 0.496094f,
+ },
+ {
+ 0.032318f, 0.095032f, 0.152344f, 0.205322f, 0.254883f, 0.299316f, 0.342041f, 0.380859f, 0.416504f, 0.449707f, 0.481201f, 0.508789f,
+ 0.537109f, 0.562012f, 0.584961f, 0.608398f, 0.628418f, 0.648926f, 0.666504f, 0.684570f, 0.701172f, 0.716797f, 0.731934f, 0.746094f,
+ 0.759766f, 0.770996f, 0.784668f, 0.795898f, 0.806641f, 0.817871f, 0.827637f, 0.837402f, 0.846680f, 0.855469f, 0.863770f, 0.872559f,
+ 0.879883f, 0.887695f, 0.895508f, 0.901367f, 0.909180f, 0.915527f, 0.921387f, 0.927734f, 0.934082f, 0.939453f, 0.944824f, 0.950684f,
+ 0.955566f, 0.960449f, 0.965332f, 0.969238f, 0.974121f, 0.978516f, 0.982910f, 0.986816f, 0.990723f, 0.994629f, 0.994629f, 0.987793f,
+ 0.981934f, 0.976562f, 0.971680f, 0.966797f, 0.025833f, 0.076965f, 0.125854f, 0.173096f, 0.217896f, 0.259766f, 0.299561f, 0.338135f,
+ 0.372559f, 0.407471f, 0.437500f, 0.468262f, 0.496582f, 0.522949f, 0.547852f, 0.571289f, 0.593750f, 0.614746f, 0.633789f, 0.652832f,
+ 0.671387f, 0.687988f, 0.705078f, 0.719727f, 0.734863f, 0.749023f, 0.761719f, 0.774414f, 0.786621f, 0.797363f, 0.808594f, 0.818848f,
+ 0.829590f, 0.838867f, 0.848633f, 0.858398f, 0.865723f, 0.874512f, 0.881836f, 0.890137f, 0.897949f, 0.904297f, 0.910645f, 0.917480f,
+ 0.923828f, 0.929688f, 0.935547f, 0.941895f, 0.947266f, 0.952637f, 0.957520f, 0.962402f, 0.967285f, 0.971680f, 0.976562f, 0.980957f,
+ 0.984863f, 0.989258f, 0.992676f, 0.985840f, 0.979980f, 0.975098f, 0.970703f, 0.966309f, 0.020828f, 0.063049f, 0.104797f, 0.146606f,
+ 0.187134f, 0.225464f, 0.263916f, 0.299072f, 0.333252f, 0.366943f, 0.398438f, 0.429199f, 0.457031f, 0.484131f, 0.509766f, 0.534668f,
+ 0.559082f, 0.579590f, 0.600586f, 0.622070f, 0.640625f, 0.659180f, 0.676758f, 0.692383f, 0.708984f, 0.722656f, 0.737793f, 0.751465f,
+ 0.764648f, 0.776367f, 0.789062f, 0.801270f, 0.811523f, 0.821289f, 0.832031f, 0.841309f, 0.850586f, 0.860352f, 0.868652f, 0.876953f,
+ 0.884766f, 0.892090f, 0.899902f, 0.906738f, 0.913086f, 0.920410f, 0.927246f, 0.933105f, 0.938477f, 0.944336f, 0.950195f, 0.955078f,
+ 0.959961f, 0.965332f, 0.970215f, 0.975098f, 0.979492f, 0.983887f, 0.989746f, 0.983398f, 0.978516f, 0.973633f, 0.969238f, 0.964844f,
+ 0.017273f, 0.052429f, 0.088745f, 0.124207f, 0.160034f, 0.195068f, 0.230103f, 0.263916f, 0.297119f, 0.329102f, 0.360596f, 0.390625f,
+ 0.418945f, 0.446289f, 0.472656f, 0.498535f, 0.521973f, 0.545898f, 0.567871f, 0.588867f, 0.609375f, 0.629395f, 0.646973f, 0.664551f,
+ 0.681641f, 0.698242f, 0.712402f, 0.727539f, 0.741699f, 0.755371f, 0.768555f, 0.780762f, 0.792480f, 0.803711f, 0.814941f, 0.825195f,
+ 0.834961f, 0.844727f, 0.854004f, 0.863281f, 0.871094f, 0.879883f, 0.887695f, 0.895508f, 0.902832f, 0.909668f, 0.916504f, 0.923828f,
+ 0.929688f, 0.936035f, 0.941895f, 0.947754f, 0.952637f, 0.958496f, 0.963379f, 0.968750f, 0.973633f, 0.978027f, 0.986816f, 0.980957f,
+ 0.976562f, 0.972168f, 0.967285f, 0.963379f, 0.014076f, 0.043915f, 0.074951f, 0.106140f, 0.137573f, 0.169189f, 0.201416f, 0.233154f,
+ 0.264648f, 0.295166f, 0.324707f, 0.354248f, 0.381836f, 0.410156f, 0.436279f, 0.462891f, 0.487793f, 0.510742f, 0.534180f, 0.556152f,
+ 0.576660f, 0.598145f, 0.616211f, 0.636719f, 0.653320f, 0.670410f, 0.687500f, 0.703125f, 0.718262f, 0.733398f, 0.746582f, 0.760742f,
+ 0.772949f, 0.785156f, 0.796875f, 0.808105f, 0.818848f, 0.829590f, 0.838867f, 0.848145f, 0.857910f, 0.867188f, 0.875977f, 0.883301f,
+ 0.891602f, 0.899414f, 0.906738f, 0.913086f, 0.919922f, 0.926270f, 0.932617f, 0.938477f, 0.944824f, 0.951660f, 0.957520f, 0.961914f,
+ 0.967285f, 0.972168f, 0.984863f, 0.979004f, 0.974609f, 0.970215f, 0.966309f, 0.961914f, 0.012077f, 0.037445f, 0.063660f, 0.090881f,
+ 0.118774f, 0.147827f, 0.176636f, 0.206055f, 0.234253f, 0.262939f, 0.291504f, 0.320312f, 0.347168f, 0.374756f, 0.401367f, 0.427734f,
+ 0.451904f, 0.477051f, 0.500488f, 0.523438f, 0.545898f, 0.566406f, 0.587402f, 0.605957f, 0.624512f, 0.643555f, 0.662109f, 0.676758f,
+ 0.693848f, 0.708984f, 0.724609f, 0.738770f, 0.751465f, 0.765137f, 0.777344f, 0.790039f, 0.800781f, 0.812500f, 0.823242f, 0.833984f,
+ 0.842773f, 0.853027f, 0.861816f, 0.871094f, 0.879395f, 0.887695f, 0.895508f, 0.903320f, 0.910156f, 0.917969f, 0.924316f, 0.931152f,
+ 0.937988f, 0.943848f, 0.949219f, 0.955566f, 0.960449f, 0.966309f, 0.981445f, 0.977051f, 0.972168f, 0.968262f, 0.964355f, 0.960938f,
+ 0.010445f, 0.032562f, 0.054657f, 0.078613f, 0.103333f, 0.128540f, 0.153564f, 0.181274f, 0.207520f, 0.234619f, 0.261475f, 0.288818f,
+ 0.315674f, 0.342041f, 0.368408f, 0.394287f, 0.418945f, 0.443604f, 0.467773f, 0.490479f, 0.512695f, 0.534180f, 0.555664f, 0.575684f,
+ 0.596191f, 0.616211f, 0.633301f, 0.651855f, 0.668457f, 0.685547f, 0.701172f, 0.714844f, 0.729492f, 0.743652f, 0.758301f, 0.770996f,
+ 0.783203f, 0.794922f, 0.806641f, 0.817383f, 0.827637f, 0.838867f, 0.847656f, 0.857422f, 0.866699f, 0.875000f, 0.884277f, 0.892578f,
+ 0.900391f, 0.907227f, 0.914551f, 0.922363f, 0.929199f, 0.935059f, 0.941895f, 0.948242f, 0.953125f, 0.959473f, 0.978516f, 0.974609f,
+ 0.970215f, 0.966309f, 0.962402f, 0.958984f, 0.009117f, 0.027466f, 0.047424f, 0.067871f, 0.089783f, 0.112244f, 0.135376f, 0.159668f,
+ 0.184082f, 0.209106f, 0.233887f, 0.259277f, 0.285400f, 0.311523f, 0.336182f, 0.360840f, 0.385986f, 0.410889f, 0.435059f, 0.458252f,
+ 0.480713f, 0.503418f, 0.524902f, 0.546387f, 0.566895f, 0.586426f, 0.605469f, 0.624512f, 0.642578f, 0.659668f, 0.676758f, 0.692383f,
+ 0.708008f, 0.722168f, 0.736816f, 0.749512f, 0.763184f, 0.776855f, 0.789062f, 0.800781f, 0.812012f, 0.823730f, 0.833496f, 0.843750f,
+ 0.854004f, 0.863281f, 0.872559f, 0.880371f, 0.889648f, 0.896973f, 0.905762f, 0.912598f, 0.919922f, 0.927734f, 0.934082f, 0.940918f,
+ 0.946289f, 0.952637f, 0.976074f, 0.972168f, 0.967773f, 0.963867f, 0.960938f, 0.957031f, 0.007561f, 0.024231f, 0.041077f, 0.059631f,
+ 0.078369f, 0.098145f, 0.119507f, 0.140747f, 0.163208f, 0.185913f, 0.209839f, 0.233154f, 0.257324f, 0.281494f, 0.305908f, 0.330566f,
+ 0.354736f, 0.378906f, 0.402588f, 0.425781f, 0.449219f, 0.471924f, 0.494385f, 0.516602f, 0.536621f, 0.557617f, 0.576660f, 0.596680f,
+ 0.616211f, 0.632812f, 0.650879f, 0.668457f, 0.684082f, 0.700684f, 0.715332f, 0.729492f, 0.744141f, 0.757812f, 0.771973f, 0.783691f,
+ 0.796387f, 0.807129f, 0.818359f, 0.829590f, 0.840820f, 0.850098f, 0.859375f, 0.868652f, 0.877930f, 0.886719f, 0.894531f, 0.903320f,
+ 0.910645f, 0.918945f, 0.925781f, 0.932617f, 0.939453f, 0.945801f, 0.972656f, 0.969727f, 0.965820f, 0.961914f, 0.958496f, 0.955078f,
+ 0.006832f, 0.020676f, 0.036224f, 0.051758f, 0.069214f, 0.086609f, 0.105225f, 0.124146f, 0.144653f, 0.165527f, 0.186646f, 0.209106f,
+ 0.232178f, 0.254883f, 0.277588f, 0.301758f, 0.325195f, 0.348633f, 0.371826f, 0.395264f, 0.418213f, 0.440674f, 0.463135f, 0.485596f,
+ 0.506348f, 0.527832f, 0.548340f, 0.567871f, 0.587891f, 0.606934f, 0.625977f, 0.642578f, 0.660645f, 0.677734f, 0.692871f, 0.708008f,
+ 0.723633f, 0.737793f, 0.752441f, 0.765137f, 0.778320f, 0.791504f, 0.802734f, 0.814453f, 0.825684f, 0.835449f, 0.847168f, 0.856934f,
+ 0.866699f, 0.875488f, 0.884766f, 0.893066f, 0.901367f, 0.910156f, 0.917480f, 0.924805f, 0.932129f, 0.938965f, 0.970215f, 0.966797f,
+ 0.963379f, 0.959961f, 0.956543f, 0.953125f, 0.006050f, 0.018585f, 0.031860f, 0.045807f, 0.060883f, 0.076538f, 0.093323f, 0.109985f,
+ 0.128174f, 0.147949f, 0.167480f, 0.186768f, 0.208496f, 0.230591f, 0.252441f, 0.274170f, 0.297363f, 0.319824f, 0.342773f, 0.365723f,
+ 0.388672f, 0.411133f, 0.433350f, 0.455811f, 0.477295f, 0.498291f, 0.519531f, 0.539551f, 0.560059f, 0.580566f, 0.599121f, 0.617676f,
+ 0.635254f, 0.653320f, 0.669434f, 0.686523f, 0.702148f, 0.717773f, 0.732422f, 0.747070f, 0.760742f, 0.773926f, 0.786621f, 0.798340f,
+ 0.811035f, 0.822754f, 0.833008f, 0.843750f, 0.854004f, 0.863770f, 0.873047f, 0.882812f, 0.891602f, 0.900879f, 0.908691f, 0.916504f,
+ 0.924316f, 0.931152f, 0.966309f, 0.964355f, 0.961426f, 0.957520f, 0.954102f, 0.951172f, 0.005352f, 0.016388f, 0.027985f, 0.040222f,
+ 0.053436f, 0.067261f, 0.082520f, 0.098022f, 0.114319f, 0.131836f, 0.150146f, 0.167969f, 0.187744f, 0.208008f, 0.228271f, 0.249634f,
+ 0.270996f, 0.292969f, 0.314697f, 0.337158f, 0.359375f, 0.380859f, 0.403809f, 0.426025f, 0.447510f, 0.469482f, 0.490967f, 0.511719f,
+ 0.532227f, 0.552734f, 0.571777f, 0.591309f, 0.609375f, 0.628418f, 0.645508f, 0.663086f, 0.680664f, 0.696289f, 0.711426f, 0.727051f,
+ 0.741699f, 0.755859f, 0.768555f, 0.782227f, 0.795410f, 0.807617f, 0.818359f, 0.830078f, 0.841309f, 0.851074f, 0.861816f, 0.871582f,
+ 0.880859f, 0.890625f, 0.898438f, 0.907715f, 0.915527f, 0.923828f, 0.962402f, 0.961914f, 0.958496f, 0.955078f, 0.951172f, 0.948730f,
+ 0.004700f, 0.014397f, 0.025208f, 0.035675f, 0.047485f, 0.060120f, 0.073242f, 0.087097f, 0.102173f, 0.117249f, 0.133789f, 0.150513f,
+ 0.168823f, 0.186890f, 0.206665f, 0.225830f, 0.246216f, 0.267334f, 0.288574f, 0.309814f, 0.331299f, 0.353271f, 0.375244f, 0.396729f,
+ 0.418701f, 0.440674f, 0.461182f, 0.483398f, 0.504883f, 0.524902f, 0.544434f, 0.564941f, 0.584473f, 0.603027f, 0.621582f, 0.639648f,
+ 0.656738f, 0.673828f, 0.690430f, 0.705566f, 0.721680f, 0.736816f, 0.750977f, 0.764648f, 0.778809f, 0.791016f, 0.804688f, 0.815918f,
+ 0.826660f, 0.838867f, 0.850098f, 0.860840f, 0.870605f, 0.879883f, 0.889648f, 0.898438f, 0.907227f, 0.915527f, 0.959961f, 0.958496f,
+ 0.955078f, 0.952148f, 0.949219f, 0.946777f, 0.004238f, 0.013138f, 0.022202f, 0.031769f, 0.042358f, 0.053040f, 0.065613f, 0.077637f,
+ 0.090759f, 0.104980f, 0.119995f, 0.135498f, 0.151855f, 0.167725f, 0.186646f, 0.205078f, 0.224121f, 0.243042f, 0.263672f, 0.283936f,
+ 0.305176f, 0.326416f, 0.347168f, 0.369629f, 0.390625f, 0.411865f, 0.433350f, 0.454590f, 0.475830f, 0.497314f, 0.517578f, 0.537109f,
+ 0.557617f, 0.577637f, 0.596191f, 0.615723f, 0.632812f, 0.651367f, 0.668945f, 0.685059f, 0.701172f, 0.716797f, 0.732422f, 0.747559f,
+ 0.761230f, 0.775391f, 0.788574f, 0.800781f, 0.813965f, 0.824707f, 0.837402f, 0.848145f, 0.859375f, 0.869141f, 0.879395f, 0.889160f,
+ 0.897949f, 0.906250f, 0.956055f, 0.955566f, 0.952148f, 0.950195f, 0.947266f, 0.943848f, 0.003944f, 0.011490f, 0.019943f, 0.028748f,
+ 0.037964f, 0.047485f, 0.058014f, 0.069702f, 0.081360f, 0.093994f, 0.107361f, 0.121277f, 0.136353f, 0.151978f, 0.167480f, 0.185669f,
+ 0.202637f, 0.222168f, 0.240601f, 0.259766f, 0.279541f, 0.300293f, 0.321533f, 0.342285f, 0.362549f, 0.384033f, 0.405762f, 0.427002f,
+ 0.447998f, 0.469238f, 0.490479f, 0.510742f, 0.532227f, 0.551758f, 0.570312f, 0.589844f, 0.609375f, 0.628418f, 0.645508f, 0.662598f,
+ 0.680664f, 0.696777f, 0.712402f, 0.728516f, 0.744141f, 0.757812f, 0.771973f, 0.785156f, 0.798828f, 0.811523f, 0.824707f, 0.835449f,
+ 0.847168f, 0.858887f, 0.869141f, 0.878906f, 0.888672f, 0.897949f, 0.952148f, 0.952148f, 0.949219f, 0.946777f, 0.944336f, 0.941406f,
+ 0.003448f, 0.010574f, 0.017807f, 0.025558f, 0.033875f, 0.042633f, 0.052307f, 0.062134f, 0.073059f, 0.084045f, 0.096375f, 0.109192f,
+ 0.122803f, 0.136475f, 0.151367f, 0.167603f, 0.183960f, 0.201416f, 0.218506f, 0.237427f, 0.256104f, 0.275635f, 0.295410f, 0.315918f,
+ 0.336426f, 0.357178f, 0.378906f, 0.399414f, 0.421143f, 0.442139f, 0.462891f, 0.484375f, 0.504883f, 0.524902f, 0.544922f, 0.564941f,
+ 0.583984f, 0.603516f, 0.622070f, 0.640625f, 0.658691f, 0.675781f, 0.692871f, 0.709473f, 0.725098f, 0.740234f, 0.754883f, 0.769531f,
+ 0.783203f, 0.796875f, 0.809570f, 0.823242f, 0.834473f, 0.846191f, 0.857422f, 0.868164f, 0.878906f, 0.889160f, 0.948730f, 0.948242f,
+ 0.946289f, 0.944336f, 0.940918f, 0.938477f, 0.003017f, 0.009422f, 0.015900f, 0.023041f, 0.030380f, 0.038574f, 0.047150f, 0.055969f,
+ 0.065735f, 0.075684f, 0.086426f, 0.098267f, 0.110535f, 0.123047f, 0.136841f, 0.151489f, 0.166138f, 0.182495f, 0.198975f, 0.216553f,
+ 0.233765f, 0.252930f, 0.271484f, 0.291016f, 0.310547f, 0.331299f, 0.351562f, 0.372559f, 0.393555f, 0.415039f, 0.435059f, 0.457275f,
+ 0.477539f, 0.498047f, 0.519043f, 0.538574f, 0.559570f, 0.579102f, 0.598633f, 0.617188f, 0.635742f, 0.654297f, 0.672363f, 0.688965f,
+ 0.706055f, 0.721191f, 0.737793f, 0.752930f, 0.768066f, 0.782227f, 0.795898f, 0.809082f, 0.821289f, 0.833496f, 0.846191f, 0.857422f,
+ 0.869141f, 0.879883f, 0.944824f, 0.945312f, 0.942871f, 0.940918f, 0.938477f, 0.936035f, 0.002802f, 0.008575f, 0.014763f, 0.020844f,
+ 0.027557f, 0.034576f, 0.042084f, 0.050476f, 0.058990f, 0.067993f, 0.077942f, 0.087952f, 0.098999f, 0.111267f, 0.122803f, 0.136719f,
+ 0.150269f, 0.165527f, 0.180542f, 0.196533f, 0.213257f, 0.230591f, 0.248779f, 0.267334f, 0.286865f, 0.306152f, 0.325928f, 0.346436f,
+ 0.367188f, 0.387695f, 0.409424f, 0.429199f, 0.450195f, 0.471680f, 0.492920f, 0.513184f, 0.534180f, 0.553711f, 0.573730f, 0.593750f,
+ 0.612793f, 0.631836f, 0.649414f, 0.668457f, 0.685059f, 0.703125f, 0.719238f, 0.735352f, 0.750000f, 0.766113f, 0.781738f, 0.794434f,
+ 0.808105f, 0.821777f, 0.833984f, 0.846191f, 0.858398f, 0.870117f, 0.940918f, 0.941895f, 0.939941f, 0.937500f, 0.935059f, 0.932617f,
+ 0.002573f, 0.007603f, 0.013100f, 0.018799f, 0.024719f, 0.031372f, 0.038147f, 0.045105f, 0.052795f, 0.061127f, 0.069519f, 0.079529f,
+ 0.089355f, 0.099976f, 0.111084f, 0.123718f, 0.136353f, 0.148926f, 0.163574f, 0.178345f, 0.194214f, 0.210083f, 0.227783f, 0.245361f,
+ 0.263672f, 0.282471f, 0.301758f, 0.321533f, 0.341797f, 0.361816f, 0.383057f, 0.403320f, 0.424316f, 0.445557f, 0.466797f, 0.487061f,
+ 0.507812f, 0.528809f, 0.549805f, 0.569336f, 0.589844f, 0.608887f, 0.627930f, 0.646973f, 0.665527f, 0.682129f, 0.700195f, 0.717773f,
+ 0.732910f, 0.749512f, 0.765137f, 0.779785f, 0.794434f, 0.808105f, 0.821777f, 0.834473f, 0.847168f, 0.859375f, 0.936523f, 0.937988f,
+ 0.936035f, 0.933594f, 0.932129f, 0.929688f, 0.002409f, 0.007107f, 0.011833f, 0.017075f, 0.022278f, 0.028351f, 0.034088f, 0.040558f,
+ 0.047943f, 0.055389f, 0.063232f, 0.072021f, 0.080322f, 0.090454f, 0.100220f, 0.111389f, 0.122986f, 0.135010f, 0.148438f, 0.162109f,
+ 0.176270f, 0.191772f, 0.207642f, 0.224121f, 0.241699f, 0.259277f, 0.278076f, 0.297363f, 0.316650f, 0.336670f, 0.356934f, 0.377686f,
+ 0.397949f, 0.418701f, 0.439941f, 0.461914f, 0.482178f, 0.502930f, 0.524414f, 0.544922f, 0.565918f, 0.585938f, 0.605957f, 0.625000f,
+ 0.643066f, 0.662109f, 0.680176f, 0.698730f, 0.715820f, 0.731934f, 0.748047f, 0.764648f, 0.780273f, 0.794434f, 0.808594f, 0.821777f,
+ 0.836914f, 0.848145f, 0.932129f, 0.934082f, 0.932617f, 0.930176f, 0.928711f, 0.926270f, 0.002066f, 0.006329f, 0.010986f, 0.015541f,
+ 0.020294f, 0.025452f, 0.030975f, 0.037201f, 0.043152f, 0.049835f, 0.056824f, 0.064331f, 0.072998f, 0.081177f, 0.090637f, 0.100525f,
+ 0.110718f, 0.122131f, 0.134033f, 0.146851f, 0.159912f, 0.173584f, 0.189331f, 0.204468f, 0.221191f, 0.237671f, 0.255615f, 0.273682f,
+ 0.292969f, 0.312012f, 0.331543f, 0.352295f, 0.372314f, 0.393311f, 0.413818f, 0.435547f, 0.456055f, 0.477539f, 0.499023f, 0.520508f,
+ 0.540039f, 0.561523f, 0.581543f, 0.602051f, 0.622070f, 0.641113f, 0.659668f, 0.678223f, 0.697266f, 0.714844f, 0.731445f, 0.748535f,
+ 0.765137f, 0.778809f, 0.794922f, 0.810059f, 0.824219f, 0.837402f, 0.926758f, 0.930176f, 0.928711f, 0.926758f, 0.924805f, 0.922852f,
+ 0.001840f, 0.005703f, 0.009918f, 0.014099f, 0.018311f, 0.023026f, 0.028000f, 0.033508f, 0.038971f, 0.045044f, 0.051880f, 0.058289f,
+ 0.065796f, 0.073425f, 0.081482f, 0.090698f, 0.100464f, 0.110413f, 0.121216f, 0.132812f, 0.145142f, 0.158203f, 0.171997f, 0.186401f,
+ 0.201538f, 0.217651f, 0.234497f, 0.251465f, 0.269287f, 0.288330f, 0.307129f, 0.327148f, 0.346924f, 0.367920f, 0.388428f, 0.409668f,
+ 0.430420f, 0.451416f, 0.474121f, 0.494873f, 0.516113f, 0.537598f, 0.558105f, 0.579102f, 0.598633f, 0.619629f, 0.639160f, 0.657715f,
+ 0.677734f, 0.695801f, 0.713867f, 0.731934f, 0.748047f, 0.764160f, 0.781738f, 0.796875f, 0.810547f, 0.826172f, 0.922363f, 0.925781f,
+ 0.924805f, 0.922852f, 0.921387f, 0.919434f, 0.001621f, 0.005188f, 0.008888f, 0.012939f, 0.016724f, 0.021271f, 0.025772f, 0.029984f,
+ 0.035553f, 0.040741f, 0.046417f, 0.052490f, 0.059265f, 0.066528f, 0.074097f, 0.081482f, 0.090271f, 0.100220f, 0.109741f, 0.120178f,
+ 0.131226f, 0.143188f, 0.156006f, 0.169189f, 0.183716f, 0.198486f, 0.214233f, 0.230713f, 0.247925f, 0.265381f, 0.284424f, 0.303711f,
+ 0.322754f, 0.342773f, 0.363525f, 0.384277f, 0.405518f, 0.427002f, 0.447754f, 0.469727f, 0.491455f, 0.512207f, 0.534180f, 0.554688f,
+ 0.576172f, 0.597168f, 0.617188f, 0.636719f, 0.657227f, 0.677734f, 0.695312f, 0.713379f, 0.731934f, 0.749512f, 0.766113f, 0.782715f,
+ 0.798340f, 0.813477f, 0.917480f, 0.920898f, 0.920410f, 0.919922f, 0.916992f, 0.915039f, 0.001581f, 0.004616f, 0.008049f, 0.011917f,
+ 0.015556f, 0.019547f, 0.023270f, 0.027908f, 0.031860f, 0.036652f, 0.041992f, 0.047577f, 0.053528f, 0.060150f, 0.066772f, 0.073914f,
+ 0.082153f, 0.090088f, 0.099304f, 0.108887f, 0.118835f, 0.129517f, 0.141357f, 0.154297f, 0.166992f, 0.180908f, 0.195557f, 0.210815f,
+ 0.227173f, 0.244141f, 0.261963f, 0.279785f, 0.299072f, 0.318359f, 0.338379f, 0.358887f, 0.380127f, 0.401123f, 0.422607f, 0.443848f,
+ 0.466309f, 0.487793f, 0.509277f, 0.530762f, 0.553223f, 0.573730f, 0.594727f, 0.616699f, 0.636719f, 0.656250f, 0.676270f, 0.695801f,
+ 0.713867f, 0.733398f, 0.750488f, 0.767090f, 0.784180f, 0.801270f, 0.912598f, 0.916992f, 0.916504f, 0.914551f, 0.913086f, 0.911133f,
+ 0.001476f, 0.004410f, 0.007374f, 0.010620f, 0.013931f, 0.017258f, 0.021057f, 0.024979f, 0.029144f, 0.033478f, 0.037872f, 0.042969f,
+ 0.048737f, 0.053986f, 0.060150f, 0.066895f, 0.074036f, 0.081665f, 0.089417f, 0.098083f, 0.107361f, 0.117371f, 0.127930f, 0.139648f,
+ 0.151489f, 0.164062f, 0.178589f, 0.192627f, 0.208130f, 0.223755f, 0.240601f, 0.258057f, 0.275879f, 0.295654f, 0.314697f, 0.334961f,
+ 0.354980f, 0.375977f, 0.396729f, 0.418945f, 0.440430f, 0.462402f, 0.484619f, 0.506348f, 0.528809f, 0.550781f, 0.572266f, 0.593750f,
+ 0.615234f, 0.637207f, 0.656738f, 0.676758f, 0.696289f, 0.716309f, 0.734863f, 0.752930f, 0.770508f, 0.788574f, 0.906738f, 0.911621f,
+ 0.912109f, 0.910156f, 0.908691f, 0.907227f, 0.001204f, 0.003998f, 0.006786f, 0.009850f, 0.012642f, 0.015762f, 0.019226f, 0.022751f,
+ 0.026749f, 0.030502f, 0.034698f, 0.038940f, 0.044006f, 0.048615f, 0.054352f, 0.060608f, 0.066711f, 0.073059f, 0.080505f, 0.088318f,
+ 0.097290f, 0.105835f, 0.115845f, 0.126343f, 0.137085f, 0.148804f, 0.161377f, 0.175049f, 0.189331f, 0.204346f, 0.219604f, 0.236816f,
+ 0.253662f, 0.272217f, 0.291260f, 0.310547f, 0.330811f, 0.350830f, 0.372314f, 0.393799f, 0.415771f, 0.437500f, 0.459717f, 0.481934f,
+ 0.504883f, 0.527344f, 0.549316f, 0.571777f, 0.593750f, 0.615723f, 0.636230f, 0.657715f, 0.678223f, 0.697754f, 0.718262f, 0.737793f,
+ 0.756348f, 0.774902f, 0.900879f, 0.907227f, 0.906738f, 0.905762f, 0.904297f, 0.902832f, 0.001290f, 0.003807f, 0.006207f, 0.008652f,
+ 0.011368f, 0.014618f, 0.017792f, 0.020813f, 0.023849f, 0.027588f, 0.031036f, 0.035400f, 0.039917f, 0.044250f, 0.049408f, 0.054321f,
+ 0.059937f, 0.065918f, 0.072937f, 0.079773f, 0.087463f, 0.095703f, 0.104553f, 0.113892f, 0.124146f, 0.134888f, 0.146606f, 0.159058f,
+ 0.171753f, 0.185913f, 0.201416f, 0.216309f, 0.232910f, 0.250000f, 0.268555f, 0.287354f, 0.306885f, 0.326904f, 0.347412f, 0.369141f,
+ 0.390381f, 0.412842f, 0.434570f, 0.457764f, 0.479736f, 0.502930f, 0.525879f, 0.547852f, 0.570801f, 0.592773f, 0.615723f, 0.637207f,
+ 0.659180f, 0.680176f, 0.700684f, 0.720703f, 0.740234f, 0.759766f, 0.895996f, 0.901855f, 0.901855f, 0.900879f, 0.899414f, 0.897949f,
+ 0.001030f, 0.003561f, 0.005718f, 0.008301f, 0.010582f, 0.013283f, 0.015839f, 0.018753f, 0.022156f, 0.025314f, 0.028427f, 0.032318f,
+ 0.035889f, 0.040039f, 0.044434f, 0.048737f, 0.054077f, 0.059723f, 0.065613f, 0.072083f, 0.079224f, 0.086426f, 0.094238f, 0.102966f,
+ 0.111938f, 0.122253f, 0.132568f, 0.143555f, 0.155884f, 0.168945f, 0.182861f, 0.197510f, 0.213379f, 0.229492f, 0.246948f, 0.264648f,
+ 0.283203f, 0.303467f, 0.322998f, 0.343994f, 0.365479f, 0.387451f, 0.409912f, 0.432129f, 0.455078f, 0.478760f, 0.501465f, 0.523926f,
+ 0.547852f, 0.570801f, 0.593750f, 0.616211f, 0.639160f, 0.661133f, 0.682617f, 0.703613f, 0.725098f, 0.745117f, 0.888672f, 0.896484f,
+ 0.896973f, 0.895020f, 0.895508f, 0.893555f, 0.001051f, 0.002956f, 0.005398f, 0.007523f, 0.009613f, 0.012024f, 0.014725f, 0.017059f,
+ 0.019714f, 0.022537f, 0.025681f, 0.029236f, 0.032715f, 0.036102f, 0.040100f, 0.043945f, 0.048859f, 0.053772f, 0.058838f, 0.064880f,
+ 0.070862f, 0.077576f, 0.084839f, 0.092712f, 0.101013f, 0.110229f, 0.119446f, 0.130005f, 0.141113f, 0.153198f, 0.166016f, 0.179565f,
+ 0.193970f, 0.209351f, 0.225830f, 0.242920f, 0.261230f, 0.280273f, 0.299316f, 0.320068f, 0.341309f, 0.363037f, 0.384521f, 0.407227f,
+ 0.429443f, 0.453369f, 0.477051f, 0.500977f, 0.524414f, 0.547852f, 0.571777f, 0.595215f, 0.619141f, 0.641602f, 0.664062f, 0.686035f,
+ 0.707520f, 0.729004f, 0.882812f, 0.891602f, 0.891113f, 0.890625f, 0.889160f, 0.888184f, 0.000934f, 0.002998f, 0.004883f, 0.006859f,
+ 0.009102f, 0.010925f, 0.012871f, 0.015656f, 0.017853f, 0.020767f, 0.023422f, 0.026413f, 0.029251f, 0.032593f, 0.036011f, 0.039825f,
+ 0.044495f, 0.048645f, 0.053284f, 0.058258f, 0.063782f, 0.069885f, 0.076111f, 0.083313f, 0.090881f, 0.099060f, 0.107788f, 0.117126f,
+ 0.127075f, 0.138428f, 0.150391f, 0.162720f, 0.176270f, 0.190796f, 0.206177f, 0.222290f, 0.239624f, 0.257568f, 0.276367f, 0.296387f,
+ 0.316895f, 0.338623f, 0.360352f, 0.382812f, 0.404785f, 0.428467f, 0.452148f, 0.476562f, 0.500488f, 0.524902f, 0.548828f, 0.572754f,
+ 0.597168f, 0.621094f, 0.644531f, 0.667480f, 0.689941f, 0.712402f, 0.875977f, 0.883789f, 0.884766f, 0.884766f, 0.883301f, 0.883789f,
+ 0.001108f, 0.002474f, 0.004707f, 0.006248f, 0.007744f, 0.009888f, 0.011787f, 0.014244f, 0.016205f, 0.018631f, 0.021286f, 0.023758f,
+ 0.026535f, 0.029510f, 0.032654f, 0.035919f, 0.039825f, 0.043762f, 0.047852f, 0.052368f, 0.057373f, 0.062561f, 0.068604f, 0.074707f,
+ 0.081360f, 0.088623f, 0.096802f, 0.105103f, 0.114624f, 0.124573f, 0.135498f, 0.147217f, 0.159424f, 0.172729f, 0.187378f, 0.202881f,
+ 0.219116f, 0.235962f, 0.254639f, 0.273438f, 0.293945f, 0.314453f, 0.335449f, 0.358154f, 0.380371f, 0.403564f, 0.428223f, 0.452148f,
+ 0.476074f, 0.500977f, 0.525879f, 0.550293f, 0.575195f, 0.599609f, 0.625000f, 0.649414f, 0.672852f, 0.695801f, 0.870117f, 0.879395f,
+ 0.879883f, 0.879395f, 0.878906f, 0.877441f, 0.000877f, 0.002495f, 0.003918f, 0.005669f, 0.007484f, 0.009148f, 0.010895f, 0.012634f,
+ 0.014717f, 0.017014f, 0.019302f, 0.021347f, 0.023849f, 0.026443f, 0.029388f, 0.032532f, 0.035492f, 0.039185f, 0.042816f, 0.046906f,
+ 0.051453f, 0.056122f, 0.061310f, 0.066895f, 0.072937f, 0.079590f, 0.086548f, 0.094360f, 0.103027f, 0.111938f, 0.121643f, 0.132568f,
+ 0.144043f, 0.156006f, 0.169434f, 0.184204f, 0.199341f, 0.215698f, 0.233032f, 0.251221f, 0.269531f, 0.290039f, 0.311768f, 0.333740f,
+ 0.355957f, 0.379395f, 0.402344f, 0.426758f, 0.451172f, 0.476562f, 0.501465f, 0.526855f, 0.552246f, 0.578613f, 0.603516f, 0.629395f,
+ 0.653809f, 0.679199f, 0.863281f, 0.872559f, 0.874023f, 0.873535f, 0.872559f, 0.871094f, 0.000779f, 0.002241f, 0.003813f, 0.005371f,
+ 0.006763f, 0.008186f, 0.009827f, 0.011574f, 0.013260f, 0.015274f, 0.017303f, 0.019119f, 0.021362f, 0.023972f, 0.026505f, 0.029144f,
+ 0.031860f, 0.035126f, 0.038422f, 0.041809f, 0.045929f, 0.050323f, 0.054840f, 0.059631f, 0.065002f, 0.070984f, 0.077759f, 0.084656f,
+ 0.091736f, 0.100037f, 0.109436f, 0.118835f, 0.129272f, 0.140625f, 0.152832f, 0.166138f, 0.180786f, 0.195679f, 0.211914f, 0.229736f,
+ 0.247803f, 0.267822f, 0.287598f, 0.309326f, 0.331055f, 0.354492f, 0.377686f, 0.401855f, 0.426270f, 0.451660f, 0.477051f, 0.503418f,
+ 0.529785f, 0.555664f, 0.583008f, 0.608887f, 0.635254f, 0.661133f, 0.855957f, 0.865234f, 0.866699f, 0.867188f, 0.866211f, 0.865723f,
+ 0.000778f, 0.002155f, 0.003584f, 0.004871f, 0.006149f, 0.007519f, 0.008858f, 0.010498f, 0.012100f, 0.013977f, 0.015511f, 0.017303f,
+ 0.019363f, 0.021515f, 0.023880f, 0.026230f, 0.028564f, 0.031555f, 0.034241f, 0.037476f, 0.041138f, 0.044983f, 0.048859f, 0.053436f,
+ 0.058014f, 0.063232f, 0.069214f, 0.075195f, 0.081848f, 0.089417f, 0.097168f, 0.106201f, 0.115479f, 0.126343f, 0.137695f, 0.149658f,
+ 0.162476f, 0.177002f, 0.192993f, 0.209473f, 0.226440f, 0.245239f, 0.264404f, 0.285156f, 0.306885f, 0.330078f, 0.353271f, 0.376465f,
+ 0.402100f, 0.426758f, 0.453857f, 0.479492f, 0.505859f, 0.532715f, 0.560547f, 0.587402f, 0.614258f, 0.640137f, 0.847168f, 0.858398f,
+ 0.860352f, 0.859863f, 0.859863f, 0.858887f, 0.000673f, 0.002026f, 0.003120f, 0.004242f, 0.005390f, 0.006874f, 0.008087f, 0.009346f,
+ 0.011192f, 0.012642f, 0.013855f, 0.015511f, 0.017502f, 0.019394f, 0.021301f, 0.023331f, 0.025681f, 0.028137f, 0.030792f, 0.033295f,
+ 0.036804f, 0.039917f, 0.043488f, 0.047363f, 0.051880f, 0.056580f, 0.061646f, 0.066956f, 0.072998f, 0.079407f, 0.086609f, 0.094971f,
+ 0.103027f, 0.112793f, 0.122742f, 0.134399f, 0.146118f, 0.159058f, 0.173828f, 0.188599f, 0.205444f, 0.223633f, 0.241943f, 0.262451f,
+ 0.283203f, 0.304932f, 0.328369f, 0.352051f, 0.376953f, 0.402100f, 0.428467f, 0.454834f, 0.481934f, 0.509766f, 0.537598f, 0.566406f,
+ 0.594238f, 0.622559f, 0.838867f, 0.852051f, 0.853516f, 0.853027f, 0.853027f, 0.852051f, 0.000419f, 0.001721f, 0.003044f, 0.003881f,
+ 0.005161f, 0.006329f, 0.007500f, 0.009117f, 0.009941f, 0.011147f, 0.013023f, 0.014053f, 0.015869f, 0.017181f, 0.018906f, 0.020889f,
+ 0.023026f, 0.025085f, 0.027435f, 0.029724f, 0.032440f, 0.035492f, 0.038605f, 0.042175f, 0.045898f, 0.049988f, 0.054504f, 0.059143f,
+ 0.064697f, 0.070435f, 0.076721f, 0.083984f, 0.091675f, 0.100037f, 0.109009f, 0.119629f, 0.130737f, 0.143066f, 0.156250f, 0.170654f,
+ 0.186157f, 0.202393f, 0.220825f, 0.239990f, 0.259521f, 0.281250f, 0.303467f, 0.327148f, 0.351318f, 0.376953f, 0.402832f, 0.430664f,
+ 0.458252f, 0.485596f, 0.514648f, 0.543457f, 0.572754f, 0.602051f, 0.830566f, 0.844238f, 0.845703f, 0.845703f, 0.845703f, 0.845215f,
+ 0.000503f, 0.001644f, 0.002455f, 0.003765f, 0.004906f, 0.005901f, 0.006805f, 0.007744f, 0.008789f, 0.009972f, 0.011314f, 0.012688f,
+ 0.014160f, 0.015480f, 0.016953f, 0.018555f, 0.020325f, 0.022232f, 0.024338f, 0.026535f, 0.028717f, 0.031403f, 0.034119f, 0.037384f,
+ 0.040680f, 0.044128f, 0.047943f, 0.052551f, 0.057098f, 0.062134f, 0.067871f, 0.074158f, 0.081543f, 0.088684f, 0.097107f, 0.106262f,
+ 0.116028f, 0.127563f, 0.139404f, 0.152344f, 0.167358f, 0.182739f, 0.199951f, 0.217773f, 0.237427f, 0.257812f, 0.279541f, 0.303223f,
+ 0.327148f, 0.351807f, 0.377441f, 0.405518f, 0.433105f, 0.460449f, 0.491211f, 0.520020f, 0.550293f, 0.581543f, 0.821777f, 0.835938f,
+ 0.837891f, 0.838867f, 0.838867f, 0.837891f, 0.000649f, 0.001432f, 0.002455f, 0.003469f, 0.004162f, 0.005192f, 0.006046f, 0.007053f,
+ 0.007919f, 0.009148f, 0.010185f, 0.011490f, 0.012558f, 0.013748f, 0.015083f, 0.016663f, 0.018341f, 0.019897f, 0.021561f, 0.023376f,
+ 0.025513f, 0.027725f, 0.030075f, 0.032745f, 0.035583f, 0.038544f, 0.041901f, 0.045898f, 0.049896f, 0.054443f, 0.059784f, 0.065186f,
+ 0.071228f, 0.078247f, 0.085632f, 0.093872f, 0.103088f, 0.113098f, 0.123840f, 0.135986f, 0.148682f, 0.163696f, 0.179321f, 0.196533f,
+ 0.214722f, 0.234985f, 0.256104f, 0.278320f, 0.302246f, 0.326660f, 0.352783f, 0.379395f, 0.406738f, 0.436279f, 0.465820f, 0.496338f,
+ 0.527344f, 0.559082f, 0.813477f, 0.827148f, 0.829590f, 0.830566f, 0.830566f, 0.829590f, 0.000427f, 0.001431f, 0.002077f, 0.002947f,
+ 0.004009f, 0.004860f, 0.005501f, 0.006416f, 0.007008f, 0.008171f, 0.009155f, 0.010063f, 0.011154f, 0.012474f, 0.013336f, 0.014793f,
+ 0.016006f, 0.017471f, 0.019119f, 0.020630f, 0.022079f, 0.024078f, 0.026505f, 0.028687f, 0.031128f, 0.033813f, 0.036804f, 0.040283f,
+ 0.043732f, 0.047882f, 0.052094f, 0.057281f, 0.062500f, 0.068726f, 0.075012f, 0.082581f, 0.090393f, 0.099487f, 0.109375f, 0.120728f,
+ 0.131958f, 0.145508f, 0.160278f, 0.176025f, 0.193848f, 0.212891f, 0.232788f, 0.253906f, 0.277344f, 0.302002f, 0.327637f, 0.354248f,
+ 0.382080f, 0.411621f, 0.441162f, 0.472656f, 0.504395f, 0.536621f, 0.803223f, 0.818359f, 0.821777f, 0.821777f, 0.822266f, 0.821777f,
+ 0.000574f, 0.001416f, 0.001961f, 0.002621f, 0.003527f, 0.004250f, 0.004894f, 0.005653f, 0.006340f, 0.007263f, 0.008255f, 0.008965f,
+ 0.009819f, 0.010857f, 0.011864f, 0.012917f, 0.014114f, 0.015358f, 0.016678f, 0.018005f, 0.019669f, 0.021347f, 0.023239f, 0.025070f,
+ 0.027267f, 0.029434f, 0.032318f, 0.035156f, 0.038269f, 0.041534f, 0.045624f, 0.049469f, 0.054321f, 0.059479f, 0.065369f, 0.071655f,
+ 0.078857f, 0.086853f, 0.095886f, 0.105652f, 0.116943f, 0.128662f, 0.142090f, 0.156860f, 0.173096f, 0.190918f, 0.210327f, 0.231201f,
+ 0.253418f, 0.277100f, 0.302490f, 0.328369f, 0.356445f, 0.385254f, 0.415771f, 0.446533f, 0.479736f, 0.513184f, 0.794434f, 0.810547f,
+ 0.812500f, 0.813477f, 0.812988f, 0.813477f, 0.000417f, 0.001152f, 0.002066f, 0.002480f, 0.003115f, 0.003778f, 0.004543f, 0.005001f,
+ 0.005936f, 0.006420f, 0.007130f, 0.007881f, 0.008789f, 0.009666f, 0.010605f, 0.011276f, 0.012352f, 0.013367f, 0.014626f, 0.015732f,
+ 0.017090f, 0.018509f, 0.020096f, 0.021759f, 0.023895f, 0.025681f, 0.027740f, 0.030121f, 0.032776f, 0.036011f, 0.039276f, 0.042694f,
+ 0.046906f, 0.051575f, 0.056488f, 0.061951f, 0.068481f, 0.075684f, 0.083191f, 0.092102f, 0.101990f, 0.112915f, 0.125122f, 0.138672f,
+ 0.153564f, 0.170410f, 0.188477f, 0.208008f, 0.229980f, 0.252441f, 0.276855f, 0.303711f, 0.331055f, 0.360596f, 0.391357f, 0.422607f,
+ 0.456299f, 0.490234f, 0.783203f, 0.799805f, 0.803223f, 0.804688f, 0.804199f, 0.805176f, 0.000422f, 0.000885f, 0.001743f, 0.002075f,
+ 0.002930f, 0.003460f, 0.004105f, 0.004696f, 0.005257f, 0.005753f, 0.006550f, 0.006916f, 0.007805f, 0.008308f, 0.009109f, 0.010056f,
+ 0.010918f, 0.011627f, 0.012787f, 0.013725f, 0.014732f, 0.016113f, 0.017319f, 0.018906f, 0.020264f, 0.022324f, 0.023911f, 0.026230f,
+ 0.028183f, 0.030884f, 0.033661f, 0.036865f, 0.040314f, 0.044189f, 0.048615f, 0.053284f, 0.058838f, 0.065491f, 0.072205f, 0.079651f,
+ 0.088379f, 0.098389f, 0.109314f, 0.121765f, 0.135010f, 0.150513f, 0.167358f, 0.186035f, 0.206543f, 0.228516f, 0.252197f, 0.278320f,
+ 0.305176f, 0.333496f, 0.364746f, 0.396973f, 0.430176f, 0.465820f, 0.772949f, 0.790527f, 0.794434f, 0.794922f, 0.795410f, 0.794922f,
+ 0.000211f, 0.000970f, 0.001484f, 0.002035f, 0.002586f, 0.003040f, 0.003540f, 0.004086f, 0.004696f, 0.005016f, 0.005508f, 0.006100f,
+ 0.006763f, 0.007401f, 0.008011f, 0.008675f, 0.009247f, 0.010071f, 0.011009f, 0.011940f, 0.012802f, 0.013870f, 0.014771f, 0.016281f,
+ 0.017487f, 0.018890f, 0.020584f, 0.022171f, 0.024200f, 0.026505f, 0.028870f, 0.031372f, 0.034363f, 0.037659f, 0.041412f, 0.045685f,
+ 0.050262f, 0.055664f, 0.061768f, 0.068359f, 0.076172f, 0.084717f, 0.094666f, 0.105835f, 0.117798f, 0.131958f, 0.147095f, 0.164795f,
+ 0.184326f, 0.204956f, 0.228271f, 0.253174f, 0.279785f, 0.307861f, 0.338379f, 0.370361f, 0.404785f, 0.440430f, 0.761230f, 0.780273f,
+ 0.783691f, 0.785645f, 0.786133f, 0.785156f, 0.000281f, 0.000954f, 0.001275f, 0.001745f, 0.002159f, 0.002810f, 0.003002f, 0.003622f,
+ 0.003918f, 0.004471f, 0.004776f, 0.005352f, 0.005852f, 0.006298f, 0.006989f, 0.007339f, 0.008087f, 0.008698f, 0.009499f, 0.010208f,
+ 0.010986f, 0.011871f, 0.012802f, 0.013809f, 0.014923f, 0.016129f, 0.017624f, 0.018753f, 0.020645f, 0.022156f, 0.024399f, 0.026382f,
+ 0.029037f, 0.031769f, 0.034851f, 0.038513f, 0.042542f, 0.047180f, 0.052063f, 0.058136f, 0.064819f, 0.072205f, 0.080933f, 0.090698f,
+ 0.101685f, 0.114441f, 0.128784f, 0.144287f, 0.162476f, 0.182617f, 0.203979f, 0.228149f, 0.253906f, 0.282227f, 0.312744f, 0.344482f,
+ 0.378418f, 0.415039f, 0.749023f, 0.770020f, 0.773438f, 0.774902f, 0.775391f, 0.776367f, 0.000200f, 0.000790f, 0.001209f, 0.001475f,
+ 0.002022f, 0.002375f, 0.002754f, 0.003136f, 0.003532f, 0.003851f, 0.004253f, 0.004719f, 0.004864f, 0.005455f, 0.005749f, 0.006435f,
+ 0.007053f, 0.007557f, 0.007988f, 0.008614f, 0.009216f, 0.010101f, 0.010712f, 0.011604f, 0.012596f, 0.013588f, 0.014877f, 0.016052f,
+ 0.017334f, 0.018753f, 0.020401f, 0.022415f, 0.024338f, 0.026642f, 0.029282f, 0.032196f, 0.035461f, 0.039215f, 0.043854f, 0.048706f,
+ 0.054413f, 0.060913f, 0.068237f, 0.076965f, 0.086792f, 0.097961f, 0.110657f, 0.125488f, 0.141846f, 0.160278f, 0.180542f, 0.203857f,
+ 0.229004f, 0.256348f, 0.286133f, 0.317627f, 0.351807f, 0.388184f, 0.737305f, 0.757812f, 0.762695f, 0.763672f, 0.764160f, 0.764648f,
+ 0.000214f, 0.000700f, 0.001134f, 0.001480f, 0.001724f, 0.002056f, 0.002468f, 0.002672f, 0.003069f, 0.003412f, 0.003618f, 0.003883f,
+ 0.004265f, 0.004627f, 0.004971f, 0.005508f, 0.005817f, 0.006397f, 0.006866f, 0.007244f, 0.007812f, 0.008446f, 0.009003f, 0.009872f,
+ 0.010544f, 0.011345f, 0.012375f, 0.013321f, 0.014275f, 0.015587f, 0.017075f, 0.018372f, 0.020050f, 0.022186f, 0.024246f, 0.026596f,
+ 0.029388f, 0.032562f, 0.036285f, 0.040344f, 0.045197f, 0.050568f, 0.056946f, 0.064514f, 0.072876f, 0.082886f, 0.093933f, 0.107056f,
+ 0.122070f, 0.139404f, 0.158325f, 0.180176f, 0.204590f, 0.231201f, 0.260010f, 0.290771f, 0.325195f, 0.361816f, 0.726074f, 0.747070f,
+ 0.751465f, 0.753418f, 0.753906f, 0.754395f, 0.000187f, 0.000637f, 0.001095f, 0.001133f, 0.001488f, 0.001872f, 0.002007f, 0.002253f,
+ 0.002590f, 0.002880f, 0.003010f, 0.003420f, 0.003593f, 0.003914f, 0.004322f, 0.004650f, 0.005051f, 0.005424f, 0.005733f, 0.006134f,
+ 0.006683f, 0.007183f, 0.007671f, 0.008072f, 0.008720f, 0.009483f, 0.010201f, 0.011070f, 0.011871f, 0.012863f, 0.013924f, 0.015167f,
+ 0.016434f, 0.018143f, 0.019669f, 0.021851f, 0.024109f, 0.026749f, 0.029587f, 0.033020f, 0.037109f, 0.041718f, 0.047119f, 0.053192f,
+ 0.060516f, 0.068848f, 0.078857f, 0.090149f, 0.104004f, 0.119202f, 0.136841f, 0.157471f, 0.180420f, 0.205322f, 0.234009f, 0.264648f,
+ 0.297852f, 0.335449f, 0.711914f, 0.735352f, 0.740234f, 0.741211f, 0.742676f, 0.742676f, 0.000201f, 0.000676f, 0.000884f, 0.001044f,
+ 0.001369f, 0.001633f, 0.001786f, 0.002001f, 0.002237f, 0.002460f, 0.002680f, 0.002777f, 0.003117f, 0.003408f, 0.003632f, 0.003910f,
+ 0.004211f, 0.004375f, 0.004772f, 0.005226f, 0.005520f, 0.005909f, 0.006302f, 0.006882f, 0.007385f, 0.007858f, 0.008553f, 0.008919f,
+ 0.009827f, 0.010582f, 0.011398f, 0.012520f, 0.013611f, 0.014725f, 0.016190f, 0.017593f, 0.019424f, 0.021622f, 0.023941f, 0.026703f,
+ 0.029938f, 0.033539f, 0.038055f, 0.043243f, 0.049408f, 0.056519f, 0.065002f, 0.074951f, 0.086548f, 0.100403f, 0.116394f, 0.135132f,
+ 0.156860f, 0.181030f, 0.208252f, 0.238281f, 0.271240f, 0.307861f, 0.698730f, 0.722656f, 0.727539f, 0.729980f, 0.730957f, 0.730469f,
+ 0.000185f, 0.000371f, 0.000784f, 0.001028f, 0.001153f, 0.001304f, 0.001567f, 0.001792f, 0.001790f, 0.002028f, 0.002283f, 0.002424f,
+ 0.002640f, 0.002764f, 0.003044f, 0.003313f, 0.003445f, 0.003748f, 0.004044f, 0.004337f, 0.004677f, 0.004879f, 0.005207f, 0.005661f,
+ 0.006027f, 0.006481f, 0.006870f, 0.007454f, 0.007874f, 0.008583f, 0.009239f, 0.009880f, 0.010849f, 0.011871f, 0.012833f, 0.014153f,
+ 0.015656f, 0.017151f, 0.018967f, 0.021118f, 0.023621f, 0.026703f, 0.030197f, 0.034576f, 0.039368f, 0.045441f, 0.052460f, 0.061157f,
+ 0.070862f, 0.083069f, 0.097290f, 0.114441f, 0.134155f, 0.157104f, 0.182983f, 0.212158f, 0.244507f, 0.281250f, 0.684570f, 0.710449f,
+ 0.715332f, 0.717285f, 0.717773f, 0.718750f, 0.000109f, 0.000455f, 0.000558f, 0.000757f, 0.000986f, 0.001166f, 0.001298f, 0.001310f,
+ 0.001566f, 0.001614f, 0.001852f, 0.001933f, 0.002062f, 0.002327f, 0.002571f, 0.002699f, 0.002909f, 0.003057f, 0.003254f, 0.003496f,
+ 0.003643f, 0.004066f, 0.004295f, 0.004665f, 0.004822f, 0.005161f, 0.005722f, 0.006008f, 0.006424f, 0.006897f, 0.007435f, 0.008049f,
+ 0.008789f, 0.009529f, 0.010284f, 0.011177f, 0.012321f, 0.013466f, 0.014885f, 0.016586f, 0.018417f, 0.020844f, 0.023575f, 0.026810f,
+ 0.030655f, 0.035400f, 0.041412f, 0.048462f, 0.056976f, 0.067322f, 0.079712f, 0.094543f, 0.112610f, 0.133789f, 0.158691f, 0.186279f,
+ 0.217896f, 0.253418f, 0.670898f, 0.696777f, 0.702148f, 0.704590f, 0.705078f, 0.705566f, 0.000000f, 0.000317f, 0.000556f, 0.000619f,
+ 0.000759f, 0.000889f, 0.001012f, 0.001163f, 0.001282f, 0.001353f, 0.001531f, 0.001621f, 0.001681f, 0.001862f, 0.001976f, 0.002140f,
+ 0.002392f, 0.002502f, 0.002745f, 0.002838f, 0.003019f, 0.003311f, 0.003477f, 0.003639f, 0.003889f, 0.004166f, 0.004429f, 0.004784f,
+ 0.005119f, 0.005547f, 0.006042f, 0.006317f, 0.006901f, 0.007442f, 0.008110f, 0.008751f, 0.009583f, 0.010590f, 0.011566f, 0.012894f,
+ 0.014404f, 0.015930f, 0.018158f, 0.020569f, 0.023697f, 0.027374f, 0.031830f, 0.037567f, 0.044434f, 0.053009f, 0.063599f, 0.076538f,
+ 0.092346f, 0.111511f, 0.134521f, 0.161133f, 0.191772f, 0.227173f, 0.654297f, 0.684082f, 0.687988f, 0.690918f, 0.691895f, 0.691895f,
+ 0.000000f, 0.000275f, 0.000368f, 0.000572f, 0.000683f, 0.000731f, 0.000877f, 0.000979f, 0.001039f, 0.001091f, 0.001234f, 0.001332f,
+ 0.001447f, 0.001547f, 0.001601f, 0.001760f, 0.001790f, 0.002007f, 0.002119f, 0.002245f, 0.002493f, 0.002565f, 0.002747f, 0.002920f,
+ 0.003168f, 0.003235f, 0.003551f, 0.003830f, 0.004040f, 0.004368f, 0.004658f, 0.005001f, 0.005337f, 0.005798f, 0.006287f, 0.006794f,
+ 0.007488f, 0.008087f, 0.008865f, 0.009773f, 0.010963f, 0.012199f, 0.013649f, 0.015610f, 0.017822f, 0.020493f, 0.023849f, 0.028320f,
+ 0.033752f, 0.040466f, 0.049377f, 0.060028f, 0.073853f, 0.090698f, 0.111572f, 0.136841f, 0.166016f, 0.199341f, 0.640137f, 0.667969f,
+ 0.675781f, 0.676758f, 0.678223f, 0.678223f, 0.000017f, 0.000193f, 0.000383f, 0.000487f, 0.000586f, 0.000597f, 0.000618f, 0.000733f,
+ 0.000826f, 0.000863f, 0.000902f, 0.001037f, 0.001121f, 0.001244f, 0.001342f, 0.001329f, 0.001514f, 0.001506f, 0.001719f, 0.001793f,
+ 0.001851f, 0.002016f, 0.002182f, 0.002281f, 0.002432f, 0.002554f, 0.002708f, 0.002859f, 0.003168f, 0.003344f, 0.003563f, 0.003845f,
+ 0.004158f, 0.004478f, 0.004852f, 0.005154f, 0.005714f, 0.006207f, 0.006752f, 0.007370f, 0.008186f, 0.009155f, 0.010193f, 0.011490f,
+ 0.013016f, 0.015144f, 0.017517f, 0.020752f, 0.024811f, 0.029922f, 0.036835f, 0.045593f, 0.056946f, 0.071533f, 0.090576f, 0.113159f,
+ 0.140991f, 0.173340f, 0.624023f, 0.653809f, 0.660156f, 0.663574f, 0.664551f, 0.664062f, 0.000194f, 0.000227f, 0.000316f, 0.000451f,
+ 0.000449f, 0.000482f, 0.000610f, 0.000511f, 0.000654f, 0.000673f, 0.000804f, 0.000844f, 0.000880f, 0.000955f, 0.000961f, 0.001127f,
+ 0.001169f, 0.001210f, 0.001318f, 0.001330f, 0.001507f, 0.001592f, 0.001657f, 0.001771f, 0.001839f, 0.001953f, 0.002083f, 0.002214f,
+ 0.002399f, 0.002518f, 0.002815f, 0.002882f, 0.003132f, 0.003361f, 0.003605f, 0.003925f, 0.004177f, 0.004528f, 0.004963f, 0.005527f,
+ 0.006027f, 0.006783f, 0.007381f, 0.008469f, 0.009644f, 0.010849f, 0.012772f, 0.014748f, 0.017578f, 0.021332f, 0.026367f, 0.033142f,
+ 0.042389f, 0.054413f, 0.070129f, 0.091064f, 0.116943f, 0.147339f, 0.608887f, 0.640137f, 0.645996f, 0.647461f, 0.650391f, 0.651367f,
+ 0.000166f, 0.000146f, 0.000248f, 0.000320f, 0.000288f, 0.000446f, 0.000375f, 0.000407f, 0.000468f, 0.000514f, 0.000629f, 0.000638f,
+ 0.000681f, 0.000773f, 0.000806f, 0.000766f, 0.000883f, 0.000927f, 0.000959f, 0.001036f, 0.001097f, 0.001172f, 0.001224f, 0.001297f,
+ 0.001392f, 0.001425f, 0.001592f, 0.001631f, 0.001793f, 0.001965f, 0.002089f, 0.002157f, 0.002321f, 0.002495f, 0.002680f, 0.002874f,
+ 0.003054f, 0.003305f, 0.003632f, 0.003902f, 0.004314f, 0.004753f, 0.005306f, 0.005901f, 0.006828f, 0.007645f, 0.008896f, 0.010323f,
+ 0.012283f, 0.014816f, 0.018234f, 0.023010f, 0.029678f, 0.039276f, 0.052307f, 0.070190f, 0.093811f, 0.123474f, 0.591797f, 0.623535f,
+ 0.631348f, 0.633301f, 0.634766f, 0.635254f, 0.000000f, 0.000154f, 0.000184f, 0.000257f, 0.000265f, 0.000266f, 0.000323f, 0.000291f,
+ 0.000369f, 0.000384f, 0.000450f, 0.000472f, 0.000505f, 0.000572f, 0.000577f, 0.000604f, 0.000636f, 0.000675f, 0.000699f, 0.000736f,
+ 0.000787f, 0.000840f, 0.000890f, 0.000945f, 0.000988f, 0.001039f, 0.001165f, 0.001165f, 0.001266f, 0.001318f, 0.001410f, 0.001550f,
+ 0.001618f, 0.001743f, 0.001866f, 0.001997f, 0.002151f, 0.002319f, 0.002562f, 0.002779f, 0.002975f, 0.003298f, 0.003674f, 0.004131f,
+ 0.004604f, 0.005268f, 0.006065f, 0.007027f, 0.008316f, 0.009949f, 0.012390f, 0.015526f, 0.019852f, 0.026733f, 0.036682f, 0.051666f,
+ 0.072449f, 0.099792f, 0.574707f, 0.608398f, 0.614746f, 0.618164f, 0.619629f, 0.621094f, 0.000000f, 0.000008f, 0.000146f, 0.000181f,
+ 0.000203f, 0.000243f, 0.000206f, 0.000250f, 0.000257f, 0.000283f, 0.000335f, 0.000293f, 0.000304f, 0.000368f, 0.000373f, 0.000435f,
+ 0.000418f, 0.000468f, 0.000539f, 0.000540f, 0.000564f, 0.000598f, 0.000628f, 0.000657f, 0.000716f, 0.000724f, 0.000797f, 0.000807f,
+ 0.000883f, 0.001002f, 0.000974f, 0.001037f, 0.001104f, 0.001196f, 0.001316f, 0.001394f, 0.001445f, 0.001574f, 0.001746f, 0.001829f,
+ 0.002005f, 0.002222f, 0.002401f, 0.002699f, 0.003057f, 0.003372f, 0.003874f, 0.004505f, 0.005360f, 0.006500f, 0.007927f, 0.009972f,
+ 0.012878f, 0.017258f, 0.024155f, 0.035339f, 0.052795f, 0.077637f, 0.558105f, 0.592285f, 0.600586f, 0.602539f, 0.604004f, 0.605469f,
+ 0.000000f, 0.000107f, 0.000122f, 0.000093f, 0.000133f, 0.000142f, 0.000149f, 0.000174f, 0.000174f, 0.000184f, 0.000190f, 0.000234f,
+ 0.000214f, 0.000250f, 0.000273f, 0.000286f, 0.000292f, 0.000302f, 0.000329f, 0.000336f, 0.000366f, 0.000391f, 0.000408f, 0.000444f,
+ 0.000452f, 0.000495f, 0.000531f, 0.000559f, 0.000578f, 0.000611f, 0.000659f, 0.000675f, 0.000757f, 0.000771f, 0.000854f, 0.000906f,
+ 0.000957f, 0.001004f, 0.001102f, 0.001187f, 0.001267f, 0.001394f, 0.001546f, 0.001683f, 0.001922f, 0.002094f, 0.002420f, 0.002754f,
+ 0.003254f, 0.003878f, 0.004757f, 0.005997f, 0.007812f, 0.010544f, 0.014786f, 0.022324f, 0.035522f, 0.057465f, 0.541504f, 0.576172f,
+ 0.583984f, 0.585938f, 0.588379f, 0.590332f, 0.000000f, 0.000099f, 0.000091f, 0.000084f, 0.000084f, 0.000086f, 0.000089f, 0.000101f,
+ 0.000105f, 0.000109f, 0.000122f, 0.000124f, 0.000132f, 0.000146f, 0.000171f, 0.000172f, 0.000176f, 0.000198f, 0.000197f, 0.000239f,
+ 0.000218f, 0.000235f, 0.000240f, 0.000281f, 0.000309f, 0.000301f, 0.000312f, 0.000321f, 0.000347f, 0.000370f, 0.000387f, 0.000419f,
+ 0.000444f, 0.000458f, 0.000513f, 0.000536f, 0.000570f, 0.000607f, 0.000688f, 0.000703f, 0.000754f, 0.000834f, 0.000890f, 0.000997f,
+ 0.001100f, 0.001238f, 0.001410f, 0.001584f, 0.001859f, 0.002207f, 0.002665f, 0.003323f, 0.004353f, 0.005947f, 0.008492f, 0.012909f,
+ 0.021606f, 0.039368f, 0.522461f, 0.559082f, 0.566406f, 0.569824f, 0.572266f, 0.572754f, 0.000108f, 0.000089f, 0.000079f, 0.000072f,
+ 0.000068f, 0.000065f, 0.000061f, 0.000057f, 0.000061f, 0.000062f, 0.000063f, 0.000086f, 0.000070f, 0.000071f, 0.000095f, 0.000080f,
+ 0.000107f, 0.000113f, 0.000115f, 0.000124f, 0.000121f, 0.000130f, 0.000151f, 0.000154f, 0.000164f, 0.000170f, 0.000176f, 0.000189f,
+ 0.000193f, 0.000215f, 0.000211f, 0.000242f, 0.000252f, 0.000260f, 0.000280f, 0.000293f, 0.000312f, 0.000350f, 0.000359f, 0.000389f,
+ 0.000410f, 0.000452f, 0.000481f, 0.000535f, 0.000578f, 0.000643f, 0.000718f, 0.000812f, 0.000939f, 0.001107f, 0.001329f, 0.001644f,
+ 0.002155f, 0.002930f, 0.004284f, 0.006706f, 0.011452f, 0.023895f, 0.504395f, 0.542480f, 0.550293f, 0.553711f, 0.555664f, 0.557129f,
+ 0.000093f, 0.000072f, 0.000063f, 0.000058f, 0.000053f, 0.000050f, 0.000047f, 0.000046f, 0.000044f, 0.000042f, 0.000039f, 0.000037f,
+ 0.000042f, 0.000035f, 0.000036f, 0.000037f, 0.000051f, 0.000046f, 0.000057f, 0.000058f, 0.000061f, 0.000062f, 0.000066f, 0.000069f,
+ 0.000072f, 0.000087f, 0.000077f, 0.000088f, 0.000093f, 0.000099f, 0.000103f, 0.000109f, 0.000115f, 0.000122f, 0.000139f, 0.000134f,
+ 0.000142f, 0.000170f, 0.000175f, 0.000179f, 0.000192f, 0.000203f, 0.000228f, 0.000245f, 0.000265f, 0.000291f, 0.000326f, 0.000360f,
+ 0.000420f, 0.000481f, 0.000574f, 0.000686f, 0.000887f, 0.001203f, 0.001759f, 0.002892f, 0.005318f, 0.011955f, 0.487305f, 0.524902f,
+ 0.534180f, 0.538086f, 0.539551f, 0.540527f, 0.000066f, 0.000049f, 0.000041f, 0.000037f, 0.000034f, 0.000033f, 0.000032f, 0.000030f,
+ 0.000029f, 0.000028f, 0.000028f, 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, 0.000022f, 0.000023f,
+ 0.000019f, 0.000018f, 0.000019f, 0.000024f, 0.000026f, 0.000029f, 0.000032f, 0.000032f, 0.000036f, 0.000034f, 0.000040f, 0.000041f,
+ 0.000043f, 0.000049f, 0.000049f, 0.000050f, 0.000056f, 0.000059f, 0.000067f, 0.000067f, 0.000074f, 0.000078f, 0.000082f, 0.000092f,
+ 0.000094f, 0.000103f, 0.000120f, 0.000130f, 0.000141f, 0.000163f, 0.000191f, 0.000230f, 0.000286f, 0.000374f, 0.000543f, 0.000890f,
+ 0.001802f, 0.004650f, 0.468994f, 0.507812f, 0.516602f, 0.520508f, 0.522461f, 0.523926f, 0.000007f, 0.000008f, 0.000008f, 0.000008f,
+ 0.000011f, 0.000010f, 0.000010f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000012f,
+ 0.000012f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, 0.000009f, 0.000009f,
+ 0.000008f, 0.000008f, 0.000009f, 0.000009f, 0.000009f, 0.000009f, 0.000010f, 0.000011f, 0.000012f, 0.000014f, 0.000013f, 0.000016f,
+ 0.000015f, 0.000018f, 0.000020f, 0.000021f, 0.000022f, 0.000025f, 0.000024f, 0.000025f, 0.000030f, 0.000031f, 0.000040f, 0.000046f,
+ 0.000052f, 0.000071f, 0.000099f, 0.000147f, 0.000306f, 0.001072f, 0.450439f, 0.491211f, 0.499756f, 0.503418f, 0.505859f, 0.507324f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000007f, 0.000024f, 0.432129f, 0.474121f,
+ 0.482666f, 0.486572f, 0.489014f, 0.490234f,
+ },
+ {
+ 0.027573f, 0.080750f, 0.130981f, 0.177734f, 0.222290f, 0.263672f, 0.302002f, 0.338623f, 0.373291f, 0.405029f, 0.435791f, 0.464111f,
+ 0.490967f, 0.516602f, 0.540039f, 0.563477f, 0.584961f, 0.605469f, 0.625000f, 0.644043f, 0.660645f, 0.677246f, 0.693848f, 0.708496f,
+ 0.724121f, 0.738281f, 0.751465f, 0.764648f, 0.776855f, 0.789062f, 0.799805f, 0.810547f, 0.821289f, 0.831055f, 0.840820f, 0.850098f,
+ 0.859863f, 0.867676f, 0.876953f, 0.884277f, 0.892578f, 0.900391f, 0.907227f, 0.914551f, 0.921875f, 0.928223f, 0.934082f, 0.940430f,
+ 0.946777f, 0.952637f, 0.957520f, 0.964355f, 0.968262f, 0.974121f, 0.979004f, 0.983887f, 0.989258f, 0.994141f, 0.993164f, 0.983398f,
+ 0.976074f, 0.969238f, 0.962891f, 0.957031f, 0.022873f, 0.067871f, 0.111511f, 0.153809f, 0.193359f, 0.232788f, 0.268799f, 0.303223f,
+ 0.337402f, 0.368652f, 0.399414f, 0.427734f, 0.455078f, 0.481201f, 0.506348f, 0.529785f, 0.552246f, 0.573242f, 0.593750f, 0.613281f,
+ 0.632324f, 0.650391f, 0.667480f, 0.683105f, 0.698730f, 0.713867f, 0.728516f, 0.741211f, 0.755371f, 0.767578f, 0.779785f, 0.791504f,
+ 0.803223f, 0.813477f, 0.823242f, 0.834473f, 0.843750f, 0.853027f, 0.861816f, 0.870605f, 0.878906f, 0.887695f, 0.895996f, 0.901855f,
+ 0.910645f, 0.917480f, 0.923828f, 0.930176f, 0.937012f, 0.943359f, 0.949707f, 0.955078f, 0.960938f, 0.966797f, 0.972656f, 0.977051f,
+ 0.982422f, 0.987305f, 0.989746f, 0.981445f, 0.973633f, 0.967773f, 0.961426f, 0.956055f, 0.019089f, 0.057007f, 0.095215f, 0.132202f,
+ 0.168823f, 0.204712f, 0.238281f, 0.272217f, 0.304688f, 0.334717f, 0.364502f, 0.392822f, 0.420898f, 0.446533f, 0.471924f, 0.495850f,
+ 0.518555f, 0.541992f, 0.562988f, 0.582520f, 0.602539f, 0.621094f, 0.639160f, 0.655762f, 0.672852f, 0.687988f, 0.703613f, 0.718262f,
+ 0.732422f, 0.746094f, 0.758789f, 0.771484f, 0.783203f, 0.795898f, 0.807129f, 0.817383f, 0.827637f, 0.837402f, 0.846680f, 0.856445f,
+ 0.865234f, 0.874023f, 0.882324f, 0.890137f, 0.898438f, 0.905273f, 0.913574f, 0.920410f, 0.927246f, 0.934082f, 0.940918f, 0.946777f,
+ 0.953125f, 0.958496f, 0.964844f, 0.969727f, 0.975586f, 0.980957f, 0.986816f, 0.979004f, 0.971680f, 0.965332f, 0.959961f, 0.954590f,
+ 0.016327f, 0.048676f, 0.081787f, 0.114807f, 0.147705f, 0.180176f, 0.211426f, 0.243652f, 0.273438f, 0.303223f, 0.332031f, 0.360107f,
+ 0.386963f, 0.412598f, 0.438477f, 0.462891f, 0.487305f, 0.510254f, 0.530762f, 0.552246f, 0.572754f, 0.590820f, 0.610352f, 0.629883f,
+ 0.647461f, 0.662598f, 0.679688f, 0.693848f, 0.709961f, 0.723633f, 0.737305f, 0.750977f, 0.763672f, 0.776367f, 0.788086f, 0.799316f,
+ 0.810059f, 0.820801f, 0.832031f, 0.841309f, 0.851074f, 0.860352f, 0.868652f, 0.877930f, 0.886230f, 0.894531f, 0.902832f, 0.910156f,
+ 0.916504f, 0.924316f, 0.930664f, 0.937500f, 0.943848f, 0.950684f, 0.957031f, 0.962891f, 0.968262f, 0.974121f, 0.983887f, 0.976074f,
+ 0.969727f, 0.963867f, 0.958496f, 0.953125f, 0.013573f, 0.041901f, 0.070801f, 0.100098f, 0.129517f, 0.159058f, 0.187866f, 0.217041f,
+ 0.246216f, 0.274414f, 0.302002f, 0.328857f, 0.354980f, 0.381592f, 0.406738f, 0.431641f, 0.455322f, 0.478271f, 0.500000f, 0.521484f,
+ 0.541992f, 0.563477f, 0.583008f, 0.600098f, 0.619141f, 0.636719f, 0.653320f, 0.671387f, 0.684570f, 0.699707f, 0.715332f, 0.729492f,
+ 0.743164f, 0.755371f, 0.768555f, 0.780762f, 0.792480f, 0.804199f, 0.814453f, 0.824707f, 0.835449f, 0.845215f, 0.854980f, 0.864746f,
+ 0.874023f, 0.882812f, 0.890137f, 0.898438f, 0.905762f, 0.914062f, 0.921387f, 0.928223f, 0.935059f, 0.941406f, 0.948242f, 0.955078f,
+ 0.961426f, 0.966797f, 0.980957f, 0.973633f, 0.967773f, 0.961914f, 0.956543f, 0.951660f, 0.011681f, 0.036316f, 0.061584f, 0.087524f,
+ 0.113342f, 0.140259f, 0.167358f, 0.194214f, 0.220947f, 0.247437f, 0.273926f, 0.300537f, 0.325684f, 0.351074f, 0.375732f, 0.400146f,
+ 0.423828f, 0.446533f, 0.469482f, 0.491943f, 0.512695f, 0.532715f, 0.553223f, 0.573242f, 0.592285f, 0.609863f, 0.627930f, 0.644531f,
+ 0.660156f, 0.676758f, 0.691406f, 0.706055f, 0.720215f, 0.734863f, 0.749023f, 0.762207f, 0.774414f, 0.786133f, 0.797852f, 0.809082f,
+ 0.820801f, 0.831055f, 0.840332f, 0.850098f, 0.859863f, 0.869629f, 0.878418f, 0.886719f, 0.895508f, 0.903809f, 0.910645f, 0.918945f,
+ 0.925781f, 0.932617f, 0.939453f, 0.947754f, 0.953613f, 0.958984f, 0.977539f, 0.970703f, 0.964844f, 0.959473f, 0.954102f, 0.949707f,
+ 0.010330f, 0.031525f, 0.053406f, 0.076538f, 0.100159f, 0.124084f, 0.148193f, 0.173096f, 0.197998f, 0.223267f, 0.247681f, 0.273193f,
+ 0.297607f, 0.322021f, 0.346924f, 0.370117f, 0.394043f, 0.417236f, 0.439697f, 0.462158f, 0.483887f, 0.504883f, 0.524902f, 0.545410f,
+ 0.563477f, 0.583008f, 0.602539f, 0.618652f, 0.636230f, 0.652344f, 0.669922f, 0.685059f, 0.699219f, 0.714355f, 0.729004f, 0.741211f,
+ 0.755371f, 0.767578f, 0.780762f, 0.792480f, 0.803711f, 0.815918f, 0.825195f, 0.836914f, 0.846191f, 0.855957f, 0.864746f, 0.874512f,
+ 0.883301f, 0.891602f, 0.900391f, 0.908203f, 0.916016f, 0.923828f, 0.931152f, 0.937988f, 0.945801f, 0.952148f, 0.974121f, 0.967773f,
+ 0.962891f, 0.957520f, 0.952637f, 0.947754f, 0.009186f, 0.027359f, 0.047302f, 0.067505f, 0.088806f, 0.109924f, 0.132202f, 0.154907f,
+ 0.177246f, 0.201050f, 0.224121f, 0.247925f, 0.271240f, 0.295410f, 0.318359f, 0.341797f, 0.365234f, 0.387939f, 0.410156f, 0.432861f,
+ 0.454590f, 0.475586f, 0.495850f, 0.517090f, 0.536621f, 0.556152f, 0.575195f, 0.592773f, 0.609863f, 0.628418f, 0.645020f, 0.661133f,
+ 0.677246f, 0.692383f, 0.707520f, 0.721191f, 0.735352f, 0.748047f, 0.762207f, 0.774414f, 0.786621f, 0.798828f, 0.810547f, 0.820801f,
+ 0.831543f, 0.842285f, 0.852539f, 0.862305f, 0.871094f, 0.880859f, 0.889648f, 0.898438f, 0.906738f, 0.914551f, 0.921875f, 0.929199f,
+ 0.936035f, 0.944824f, 0.971191f, 0.965332f, 0.959473f, 0.955078f, 0.950195f, 0.945801f, 0.008041f, 0.024384f, 0.041321f, 0.059631f,
+ 0.078003f, 0.097656f, 0.117554f, 0.138428f, 0.159912f, 0.181152f, 0.203003f, 0.224976f, 0.247070f, 0.269531f, 0.292480f, 0.314697f,
+ 0.337891f, 0.360352f, 0.382324f, 0.403809f, 0.426025f, 0.447998f, 0.468018f, 0.488770f, 0.508301f, 0.528320f, 0.547852f, 0.567383f,
+ 0.585449f, 0.603516f, 0.620605f, 0.637695f, 0.654297f, 0.670410f, 0.686523f, 0.700195f, 0.715820f, 0.729980f, 0.743164f, 0.756836f,
+ 0.769531f, 0.782715f, 0.794434f, 0.805664f, 0.816895f, 0.827637f, 0.838379f, 0.848633f, 0.859375f, 0.868164f, 0.877930f, 0.887695f,
+ 0.895996f, 0.905273f, 0.912598f, 0.920898f, 0.928711f, 0.936035f, 0.966797f, 0.962402f, 0.957031f, 0.952637f, 0.947754f, 0.943848f,
+ 0.007095f, 0.021515f, 0.036926f, 0.052704f, 0.069641f, 0.087463f, 0.105347f, 0.123413f, 0.143188f, 0.163452f, 0.183105f, 0.204102f,
+ 0.225220f, 0.246704f, 0.268066f, 0.290283f, 0.311768f, 0.333740f, 0.355225f, 0.376465f, 0.397949f, 0.419434f, 0.440430f, 0.461670f,
+ 0.481445f, 0.500977f, 0.520020f, 0.540527f, 0.559570f, 0.578125f, 0.595703f, 0.613770f, 0.630371f, 0.646973f, 0.663086f, 0.678223f,
+ 0.694336f, 0.709473f, 0.723145f, 0.736328f, 0.750000f, 0.764648f, 0.777344f, 0.790039f, 0.801270f, 0.812988f, 0.824707f, 0.834961f,
+ 0.846191f, 0.856934f, 0.865723f, 0.875977f, 0.884766f, 0.894531f, 0.903320f, 0.911621f, 0.919922f, 0.927734f, 0.962891f, 0.959473f,
+ 0.954102f, 0.949219f, 0.945312f, 0.941406f, 0.006138f, 0.019150f, 0.033051f, 0.047089f, 0.061829f, 0.077515f, 0.094299f, 0.111084f,
+ 0.128174f, 0.146729f, 0.165771f, 0.185059f, 0.205200f, 0.224731f, 0.245361f, 0.265625f, 0.286865f, 0.307861f, 0.328857f, 0.350098f,
+ 0.370605f, 0.392090f, 0.413086f, 0.433594f, 0.454346f, 0.474609f, 0.493896f, 0.513672f, 0.532227f, 0.552734f, 0.569824f, 0.588867f,
+ 0.605957f, 0.623047f, 0.640625f, 0.656738f, 0.672852f, 0.688477f, 0.703613f, 0.717773f, 0.732910f, 0.746582f, 0.759766f, 0.772461f,
+ 0.786621f, 0.798340f, 0.810059f, 0.820312f, 0.832520f, 0.842773f, 0.853516f, 0.863770f, 0.873535f, 0.883789f, 0.892578f, 0.901367f,
+ 0.910645f, 0.919434f, 0.958984f, 0.955566f, 0.951172f, 0.946777f, 0.942871f, 0.938965f, 0.005424f, 0.017059f, 0.029541f, 0.042023f,
+ 0.055389f, 0.069397f, 0.083984f, 0.099670f, 0.115601f, 0.132324f, 0.149292f, 0.167114f, 0.185547f, 0.204468f, 0.224121f, 0.243896f,
+ 0.262939f, 0.283691f, 0.304443f, 0.323486f, 0.345459f, 0.365479f, 0.386230f, 0.407471f, 0.426758f, 0.448486f, 0.467529f, 0.487061f,
+ 0.506348f, 0.526367f, 0.545410f, 0.563965f, 0.581543f, 0.600098f, 0.617676f, 0.634277f, 0.650391f, 0.666016f, 0.682617f, 0.697754f,
+ 0.712891f, 0.727539f, 0.741211f, 0.755859f, 0.769043f, 0.782227f, 0.793945f, 0.806152f, 0.818848f, 0.830566f, 0.840332f, 0.851074f,
+ 0.861328f, 0.872070f, 0.881836f, 0.892090f, 0.900879f, 0.910645f, 0.955566f, 0.952637f, 0.948730f, 0.943359f, 0.939941f, 0.935547f,
+ 0.004833f, 0.015442f, 0.026169f, 0.037689f, 0.049683f, 0.062164f, 0.075806f, 0.089539f, 0.103760f, 0.119263f, 0.134888f, 0.151978f,
+ 0.168335f, 0.186646f, 0.204102f, 0.223022f, 0.242065f, 0.260986f, 0.280518f, 0.300537f, 0.320801f, 0.340820f, 0.360107f, 0.381104f,
+ 0.401367f, 0.421387f, 0.441650f, 0.460449f, 0.480957f, 0.500000f, 0.519531f, 0.538574f, 0.557129f, 0.575684f, 0.593262f, 0.610840f,
+ 0.628906f, 0.645508f, 0.662109f, 0.677246f, 0.692871f, 0.708008f, 0.723145f, 0.738281f, 0.751465f, 0.766113f, 0.778320f, 0.791504f,
+ 0.802246f, 0.816406f, 0.827637f, 0.838867f, 0.850098f, 0.860352f, 0.871582f, 0.881348f, 0.890137f, 0.899902f, 0.951660f, 0.948730f,
+ 0.944824f, 0.940918f, 0.937012f, 0.933594f, 0.004269f, 0.013809f, 0.023911f, 0.033569f, 0.044342f, 0.056213f, 0.068054f, 0.080811f,
+ 0.093933f, 0.107910f, 0.122131f, 0.137451f, 0.152710f, 0.169434f, 0.185791f, 0.203979f, 0.221436f, 0.239990f, 0.257812f, 0.277344f,
+ 0.296631f, 0.316162f, 0.335693f, 0.355713f, 0.375244f, 0.395996f, 0.416016f, 0.436035f, 0.455078f, 0.474365f, 0.494629f, 0.513184f,
+ 0.532715f, 0.550781f, 0.569336f, 0.586914f, 0.604980f, 0.622559f, 0.639648f, 0.655762f, 0.672363f, 0.688477f, 0.704102f, 0.718750f,
+ 0.733887f, 0.747559f, 0.761230f, 0.775391f, 0.788574f, 0.800781f, 0.814453f, 0.825684f, 0.837402f, 0.848633f, 0.859375f, 0.870605f,
+ 0.880371f, 0.891113f, 0.947754f, 0.945312f, 0.941895f, 0.937988f, 0.934082f, 0.931152f, 0.004028f, 0.012581f, 0.021133f, 0.030396f,
+ 0.039948f, 0.050323f, 0.061523f, 0.072815f, 0.084961f, 0.096985f, 0.110535f, 0.124756f, 0.138916f, 0.153687f, 0.169800f, 0.185669f,
+ 0.202881f, 0.219116f, 0.237305f, 0.255615f, 0.273926f, 0.293213f, 0.311768f, 0.331055f, 0.351074f, 0.370605f, 0.390381f, 0.409668f,
+ 0.429688f, 0.449707f, 0.468994f, 0.487549f, 0.506836f, 0.526367f, 0.545898f, 0.562988f, 0.581543f, 0.599121f, 0.616699f, 0.634766f,
+ 0.651367f, 0.667480f, 0.683594f, 0.699707f, 0.714844f, 0.730957f, 0.744141f, 0.758789f, 0.772949f, 0.785645f, 0.799316f, 0.812500f,
+ 0.823730f, 0.836914f, 0.847168f, 0.859375f, 0.869629f, 0.880371f, 0.942383f, 0.941406f, 0.937500f, 0.934570f, 0.931152f, 0.927734f,
+ 0.003613f, 0.011391f, 0.018875f, 0.027679f, 0.036133f, 0.045624f, 0.055420f, 0.065491f, 0.076416f, 0.088135f, 0.099487f, 0.112427f,
+ 0.126099f, 0.139771f, 0.154419f, 0.169556f, 0.184814f, 0.201050f, 0.218262f, 0.234985f, 0.252441f, 0.271484f, 0.289062f, 0.308594f,
+ 0.326660f, 0.346924f, 0.365234f, 0.384521f, 0.404541f, 0.424072f, 0.443359f, 0.463135f, 0.482422f, 0.501953f, 0.521484f, 0.539551f,
+ 0.558594f, 0.576660f, 0.595215f, 0.612793f, 0.629883f, 0.647949f, 0.663574f, 0.679688f, 0.695801f, 0.711426f, 0.727539f, 0.741699f,
+ 0.757324f, 0.770996f, 0.785156f, 0.798828f, 0.811035f, 0.823730f, 0.835449f, 0.848145f, 0.858887f, 0.870605f, 0.937988f, 0.937988f,
+ 0.934570f, 0.931152f, 0.927734f, 0.924805f, 0.003248f, 0.010185f, 0.017395f, 0.025055f, 0.032928f, 0.041321f, 0.049957f, 0.059265f,
+ 0.069092f, 0.079407f, 0.090820f, 0.101746f, 0.113770f, 0.126953f, 0.140381f, 0.154053f, 0.168701f, 0.184082f, 0.199951f, 0.216431f,
+ 0.232788f, 0.250000f, 0.267578f, 0.285645f, 0.303955f, 0.322998f, 0.341553f, 0.361084f, 0.379150f, 0.399414f, 0.418701f, 0.437988f,
+ 0.457275f, 0.477051f, 0.496094f, 0.515137f, 0.534180f, 0.553223f, 0.571289f, 0.589844f, 0.606934f, 0.625488f, 0.643066f, 0.659668f,
+ 0.676758f, 0.692871f, 0.708984f, 0.725098f, 0.740234f, 0.753906f, 0.769043f, 0.782227f, 0.796387f, 0.810059f, 0.822266f, 0.834961f,
+ 0.847168f, 0.859375f, 0.933594f, 0.933594f, 0.931152f, 0.927246f, 0.923828f, 0.921387f, 0.002914f, 0.009361f, 0.015793f, 0.022659f,
+ 0.029938f, 0.037354f, 0.045593f, 0.053406f, 0.062988f, 0.072083f, 0.081665f, 0.092712f, 0.103943f, 0.114990f, 0.128174f, 0.140503f,
+ 0.153809f, 0.167725f, 0.182251f, 0.198242f, 0.213623f, 0.230225f, 0.246826f, 0.263672f, 0.281494f, 0.300049f, 0.318604f, 0.337158f,
+ 0.356201f, 0.374756f, 0.394531f, 0.413574f, 0.433105f, 0.451904f, 0.471680f, 0.491211f, 0.509766f, 0.529297f, 0.547852f, 0.566895f,
+ 0.584961f, 0.603516f, 0.621094f, 0.638672f, 0.656738f, 0.673340f, 0.689453f, 0.706543f, 0.722656f, 0.737793f, 0.752930f, 0.767578f,
+ 0.781250f, 0.796875f, 0.809082f, 0.823242f, 0.835449f, 0.847656f, 0.929199f, 0.929199f, 0.927246f, 0.923828f, 0.920898f, 0.917969f,
+ 0.002766f, 0.008736f, 0.014442f, 0.020691f, 0.027054f, 0.033905f, 0.040924f, 0.048645f, 0.056976f, 0.065674f, 0.074951f, 0.084229f,
+ 0.094116f, 0.105225f, 0.116333f, 0.127563f, 0.139771f, 0.153564f, 0.166626f, 0.181030f, 0.196411f, 0.211182f, 0.227417f, 0.243896f,
+ 0.260742f, 0.277588f, 0.295898f, 0.314209f, 0.332031f, 0.351562f, 0.370117f, 0.389404f, 0.408203f, 0.428223f, 0.447266f, 0.467041f,
+ 0.486084f, 0.505859f, 0.524414f, 0.543945f, 0.562012f, 0.581543f, 0.600098f, 0.617676f, 0.636230f, 0.654297f, 0.670898f, 0.687500f,
+ 0.704102f, 0.720703f, 0.736816f, 0.751465f, 0.766113f, 0.781738f, 0.796387f, 0.809082f, 0.823242f, 0.835938f, 0.923828f, 0.925781f,
+ 0.922852f, 0.920410f, 0.916992f, 0.914551f, 0.002483f, 0.007599f, 0.013161f, 0.018555f, 0.024551f, 0.030670f, 0.037476f, 0.044464f,
+ 0.051636f, 0.059174f, 0.067688f, 0.075928f, 0.085693f, 0.095093f, 0.105591f, 0.116394f, 0.127441f, 0.139648f, 0.152344f, 0.165527f,
+ 0.179565f, 0.193970f, 0.208862f, 0.224487f, 0.240356f, 0.256836f, 0.274658f, 0.291748f, 0.310059f, 0.328369f, 0.346680f, 0.365234f,
+ 0.384521f, 0.404297f, 0.423340f, 0.442139f, 0.462646f, 0.481445f, 0.500977f, 0.520020f, 0.540039f, 0.559082f, 0.577148f, 0.596191f,
+ 0.614746f, 0.632812f, 0.651367f, 0.669434f, 0.685059f, 0.702637f, 0.718750f, 0.734375f, 0.750488f, 0.766113f, 0.780762f, 0.795410f,
+ 0.811035f, 0.823730f, 0.919434f, 0.920898f, 0.918457f, 0.916016f, 0.913086f, 0.910645f, 0.002457f, 0.007114f, 0.011757f, 0.016708f,
+ 0.022125f, 0.027786f, 0.033752f, 0.040375f, 0.046661f, 0.053864f, 0.061584f, 0.069336f, 0.077515f, 0.086365f, 0.095947f, 0.105896f,
+ 0.116638f, 0.127075f, 0.138916f, 0.151245f, 0.164062f, 0.177490f, 0.191528f, 0.206177f, 0.221802f, 0.237427f, 0.253906f, 0.270508f,
+ 0.287842f, 0.305664f, 0.323730f, 0.342285f, 0.361572f, 0.379639f, 0.399170f, 0.418457f, 0.438965f, 0.458252f, 0.477295f, 0.497559f,
+ 0.516113f, 0.536133f, 0.554688f, 0.574707f, 0.593750f, 0.612305f, 0.630859f, 0.648926f, 0.666504f, 0.684082f, 0.701660f, 0.717773f,
+ 0.734863f, 0.751465f, 0.766602f, 0.781738f, 0.797852f, 0.812012f, 0.913086f, 0.916016f, 0.913574f, 0.911621f, 0.909180f, 0.906250f,
+ 0.002132f, 0.006493f, 0.010750f, 0.015717f, 0.020569f, 0.025604f, 0.030823f, 0.036682f, 0.043060f, 0.049286f, 0.055786f, 0.062988f,
+ 0.070557f, 0.078918f, 0.086914f, 0.096191f, 0.105530f, 0.116028f, 0.126953f, 0.138306f, 0.149902f, 0.162231f, 0.175537f, 0.189453f,
+ 0.203491f, 0.218628f, 0.234131f, 0.250000f, 0.266602f, 0.284180f, 0.301514f, 0.319580f, 0.338135f, 0.356689f, 0.375977f, 0.395020f,
+ 0.413818f, 0.434082f, 0.452881f, 0.473145f, 0.492920f, 0.512207f, 0.532227f, 0.552246f, 0.570801f, 0.591309f, 0.609375f, 0.629395f,
+ 0.646973f, 0.665527f, 0.683105f, 0.700684f, 0.717773f, 0.734863f, 0.751465f, 0.767578f, 0.782715f, 0.799316f, 0.908203f, 0.911133f,
+ 0.909180f, 0.907227f, 0.904785f, 0.902832f, 0.001891f, 0.006008f, 0.010025f, 0.014122f, 0.018616f, 0.023239f, 0.028442f, 0.033691f,
+ 0.038757f, 0.044556f, 0.050964f, 0.057465f, 0.064087f, 0.071167f, 0.079224f, 0.087463f, 0.096008f, 0.105591f, 0.115356f, 0.125488f,
+ 0.136597f, 0.148193f, 0.160278f, 0.173218f, 0.186768f, 0.200684f, 0.215332f, 0.231323f, 0.246338f, 0.262939f, 0.279785f, 0.297607f,
+ 0.314941f, 0.333984f, 0.353271f, 0.371094f, 0.391357f, 0.409668f, 0.430420f, 0.448975f, 0.469482f, 0.489746f, 0.509277f, 0.528809f,
+ 0.549316f, 0.568848f, 0.588379f, 0.607910f, 0.626953f, 0.645996f, 0.664062f, 0.683105f, 0.700684f, 0.718262f, 0.735840f, 0.751953f,
+ 0.768555f, 0.785645f, 0.902344f, 0.906250f, 0.904785f, 0.902832f, 0.900391f, 0.898438f, 0.001732f, 0.005573f, 0.009193f, 0.012932f,
+ 0.017075f, 0.021286f, 0.025406f, 0.030289f, 0.035675f, 0.040344f, 0.046326f, 0.052032f, 0.058411f, 0.064575f, 0.072205f, 0.079834f,
+ 0.087708f, 0.095947f, 0.104797f, 0.114380f, 0.124451f, 0.134888f, 0.146606f, 0.158691f, 0.170776f, 0.184082f, 0.197510f, 0.212524f,
+ 0.227417f, 0.243164f, 0.259521f, 0.276367f, 0.293457f, 0.311768f, 0.329590f, 0.348633f, 0.367188f, 0.386230f, 0.406006f, 0.425781f,
+ 0.446533f, 0.465332f, 0.486084f, 0.505859f, 0.526367f, 0.545898f, 0.567383f, 0.585938f, 0.605957f, 0.625977f, 0.645508f, 0.664551f,
+ 0.683105f, 0.701172f, 0.718750f, 0.736816f, 0.754395f, 0.770508f, 0.896484f, 0.900879f, 0.900391f, 0.897949f, 0.895996f, 0.894043f,
+ 0.001713f, 0.004684f, 0.008339f, 0.011818f, 0.015450f, 0.019409f, 0.023605f, 0.027832f, 0.032349f, 0.036865f, 0.041809f, 0.047302f,
+ 0.052673f, 0.058838f, 0.065613f, 0.072083f, 0.079407f, 0.087280f, 0.095337f, 0.104126f, 0.113037f, 0.122986f, 0.133667f, 0.144897f,
+ 0.156250f, 0.168579f, 0.181396f, 0.195068f, 0.208984f, 0.224243f, 0.239624f, 0.255859f, 0.272461f, 0.289551f, 0.307617f, 0.326172f,
+ 0.344482f, 0.363770f, 0.383301f, 0.402588f, 0.422607f, 0.443115f, 0.463135f, 0.483154f, 0.503418f, 0.523926f, 0.544434f, 0.564941f,
+ 0.584473f, 0.604980f, 0.624512f, 0.645508f, 0.664551f, 0.683594f, 0.701660f, 0.721191f, 0.738281f, 0.755859f, 0.889648f, 0.895996f,
+ 0.895020f, 0.893066f, 0.891602f, 0.889160f, 0.001545f, 0.004745f, 0.007710f, 0.010979f, 0.014450f, 0.017807f, 0.021469f, 0.025238f,
+ 0.029282f, 0.033661f, 0.038177f, 0.043182f, 0.048157f, 0.053436f, 0.059326f, 0.065674f, 0.072205f, 0.078857f, 0.086548f, 0.094604f,
+ 0.102905f, 0.111816f, 0.121521f, 0.131592f, 0.142334f, 0.153442f, 0.165894f, 0.178345f, 0.192139f, 0.205933f, 0.220703f, 0.236084f,
+ 0.251709f, 0.268555f, 0.285645f, 0.303467f, 0.321777f, 0.340332f, 0.359619f, 0.379150f, 0.398682f, 0.419189f, 0.440430f, 0.460449f,
+ 0.480957f, 0.501465f, 0.521973f, 0.543457f, 0.563477f, 0.584961f, 0.604492f, 0.625488f, 0.645508f, 0.665039f, 0.684082f, 0.704102f,
+ 0.723145f, 0.741211f, 0.885254f, 0.890137f, 0.889160f, 0.887695f, 0.886719f, 0.884277f, 0.001487f, 0.004356f, 0.006828f, 0.010162f,
+ 0.012993f, 0.016022f, 0.019333f, 0.023087f, 0.026886f, 0.030518f, 0.034668f, 0.039062f, 0.043671f, 0.048370f, 0.053741f, 0.059326f,
+ 0.065308f, 0.071655f, 0.078125f, 0.085693f, 0.093323f, 0.101807f, 0.110657f, 0.119507f, 0.129517f, 0.140137f, 0.151367f, 0.163330f,
+ 0.175781f, 0.188843f, 0.202759f, 0.217163f, 0.232666f, 0.248413f, 0.264893f, 0.282227f, 0.299805f, 0.318115f, 0.336914f, 0.356445f,
+ 0.375488f, 0.395996f, 0.416504f, 0.436279f, 0.457520f, 0.479004f, 0.499023f, 0.520508f, 0.541504f, 0.562988f, 0.583984f, 0.604492f,
+ 0.625488f, 0.646973f, 0.666504f, 0.687012f, 0.706055f, 0.725098f, 0.877441f, 0.885254f, 0.884766f, 0.882324f, 0.881836f, 0.880371f,
+ 0.001443f, 0.003807f, 0.006336f, 0.009171f, 0.011909f, 0.015007f, 0.018097f, 0.020905f, 0.024384f, 0.027893f, 0.031555f, 0.035370f,
+ 0.039581f, 0.044128f, 0.048889f, 0.053894f, 0.059174f, 0.065125f, 0.070984f, 0.077698f, 0.084656f, 0.091919f, 0.100037f, 0.108093f,
+ 0.117493f, 0.127563f, 0.137817f, 0.148438f, 0.159912f, 0.172485f, 0.185547f, 0.199585f, 0.213867f, 0.229248f, 0.244995f, 0.261230f,
+ 0.278564f, 0.296387f, 0.314697f, 0.333252f, 0.353271f, 0.372314f, 0.393311f, 0.413330f, 0.433594f, 0.455078f, 0.476318f, 0.497314f,
+ 0.519531f, 0.540527f, 0.562500f, 0.583496f, 0.605469f, 0.626953f, 0.648438f, 0.669434f, 0.689941f, 0.709961f, 0.870605f, 0.878906f,
+ 0.878418f, 0.877441f, 0.875488f, 0.873535f, 0.001302f, 0.003712f, 0.005859f, 0.008286f, 0.010910f, 0.013779f, 0.016235f, 0.019135f,
+ 0.021912f, 0.025345f, 0.029022f, 0.032166f, 0.036011f, 0.040131f, 0.044128f, 0.048492f, 0.053528f, 0.058533f, 0.064209f, 0.070129f,
+ 0.076355f, 0.083191f, 0.090149f, 0.098328f, 0.106628f, 0.115662f, 0.124817f, 0.134766f, 0.145630f, 0.157104f, 0.169678f, 0.182495f,
+ 0.195801f, 0.210205f, 0.225342f, 0.241455f, 0.257812f, 0.274902f, 0.292725f, 0.311035f, 0.330322f, 0.349365f, 0.369873f, 0.390137f,
+ 0.411133f, 0.432373f, 0.453369f, 0.474609f, 0.496826f, 0.519043f, 0.541504f, 0.563477f, 0.585449f, 0.606445f, 0.629395f, 0.650391f,
+ 0.672363f, 0.693848f, 0.863281f, 0.872070f, 0.872070f, 0.871582f, 0.869629f, 0.868164f, 0.001170f, 0.003151f, 0.005295f, 0.007812f,
+ 0.010132f, 0.012466f, 0.015076f, 0.017517f, 0.019943f, 0.023178f, 0.026443f, 0.029312f, 0.032471f, 0.036041f, 0.039978f, 0.044037f,
+ 0.048828f, 0.053070f, 0.057983f, 0.063232f, 0.068909f, 0.075378f, 0.081909f, 0.088745f, 0.096375f, 0.104309f, 0.113281f, 0.122437f,
+ 0.132202f, 0.142944f, 0.154419f, 0.166138f, 0.178955f, 0.192505f, 0.206421f, 0.221558f, 0.237183f, 0.253906f, 0.270996f, 0.289062f,
+ 0.308105f, 0.326904f, 0.346924f, 0.366455f, 0.387695f, 0.408936f, 0.430176f, 0.451416f, 0.474365f, 0.496582f, 0.518066f, 0.541016f,
+ 0.563965f, 0.585938f, 0.608887f, 0.630859f, 0.654297f, 0.675781f, 0.856934f, 0.865234f, 0.866211f, 0.864746f, 0.863281f, 0.862793f,
+ 0.001049f, 0.003254f, 0.005234f, 0.007263f, 0.009270f, 0.011307f, 0.013596f, 0.015869f, 0.018555f, 0.020844f, 0.023972f, 0.026566f,
+ 0.029739f, 0.033020f, 0.036316f, 0.039856f, 0.044159f, 0.048096f, 0.052277f, 0.057281f, 0.062439f, 0.067871f, 0.073792f, 0.079956f,
+ 0.087158f, 0.094055f, 0.102234f, 0.110535f, 0.119934f, 0.129517f, 0.140259f, 0.151245f, 0.162842f, 0.175537f, 0.189209f, 0.203369f,
+ 0.218262f, 0.233643f, 0.250488f, 0.268066f, 0.285645f, 0.304443f, 0.324219f, 0.343750f, 0.364014f, 0.385254f, 0.406494f, 0.428223f,
+ 0.450928f, 0.472656f, 0.495605f, 0.519043f, 0.541504f, 0.565918f, 0.588379f, 0.612305f, 0.635742f, 0.659180f, 0.850098f, 0.859863f,
+ 0.859863f, 0.858398f, 0.857910f, 0.856934f, 0.000914f, 0.002861f, 0.004742f, 0.006569f, 0.008415f, 0.010521f, 0.012596f, 0.014648f,
+ 0.016708f, 0.019089f, 0.021515f, 0.023865f, 0.026688f, 0.029572f, 0.032928f, 0.036377f, 0.039337f, 0.043365f, 0.047333f, 0.051544f,
+ 0.056305f, 0.061066f, 0.066406f, 0.071960f, 0.078247f, 0.084961f, 0.092163f, 0.099426f, 0.108215f, 0.116943f, 0.126831f, 0.136719f,
+ 0.148193f, 0.159302f, 0.171875f, 0.185669f, 0.199585f, 0.214478f, 0.230469f, 0.247070f, 0.264160f, 0.282471f, 0.301270f, 0.321045f,
+ 0.341553f, 0.362061f, 0.383545f, 0.404785f, 0.427734f, 0.449951f, 0.473389f, 0.496582f, 0.520020f, 0.543457f, 0.568359f, 0.592285f,
+ 0.615723f, 0.639648f, 0.840820f, 0.851074f, 0.853027f, 0.853027f, 0.852051f, 0.850586f, 0.000679f, 0.002518f, 0.004173f, 0.006149f,
+ 0.008064f, 0.009369f, 0.011551f, 0.013222f, 0.015175f, 0.017212f, 0.019592f, 0.021835f, 0.024048f, 0.026932f, 0.029846f, 0.032623f,
+ 0.035675f, 0.038940f, 0.042542f, 0.046295f, 0.050354f, 0.055054f, 0.059601f, 0.064880f, 0.070190f, 0.076233f, 0.082703f, 0.089661f,
+ 0.097229f, 0.105103f, 0.113831f, 0.123474f, 0.133423f, 0.144409f, 0.156006f, 0.168335f, 0.182495f, 0.196411f, 0.211304f, 0.227295f,
+ 0.243530f, 0.260986f, 0.279053f, 0.298828f, 0.318359f, 0.339111f, 0.360107f, 0.381348f, 0.403809f, 0.427490f, 0.449463f, 0.473633f,
+ 0.497803f, 0.521484f, 0.546875f, 0.570801f, 0.595703f, 0.620605f, 0.833008f, 0.845215f, 0.845703f, 0.845703f, 0.845215f, 0.843750f,
+ 0.000719f, 0.002470f, 0.003975f, 0.005337f, 0.007275f, 0.008713f, 0.010376f, 0.012032f, 0.013580f, 0.015793f, 0.017609f, 0.019501f,
+ 0.021530f, 0.024277f, 0.026657f, 0.029312f, 0.031982f, 0.035187f, 0.038086f, 0.041565f, 0.045288f, 0.049103f, 0.053436f, 0.058136f,
+ 0.062927f, 0.068054f, 0.073853f, 0.080383f, 0.087341f, 0.094666f, 0.102173f, 0.111084f, 0.120300f, 0.130859f, 0.141235f, 0.152954f,
+ 0.164429f, 0.178223f, 0.192749f, 0.207642f, 0.223145f, 0.239868f, 0.258301f, 0.276611f, 0.295654f, 0.316162f, 0.337402f, 0.358643f,
+ 0.380859f, 0.403320f, 0.427002f, 0.450684f, 0.474609f, 0.499756f, 0.523926f, 0.550781f, 0.575195f, 0.600586f, 0.824707f, 0.836914f,
+ 0.838379f, 0.838867f, 0.837402f, 0.837402f, 0.000683f, 0.002361f, 0.003649f, 0.005116f, 0.006416f, 0.008202f, 0.009460f, 0.010941f,
+ 0.012817f, 0.014099f, 0.015839f, 0.017593f, 0.019867f, 0.021988f, 0.023926f, 0.026276f, 0.028824f, 0.031311f, 0.034363f, 0.036957f,
+ 0.040375f, 0.043823f, 0.047546f, 0.051758f, 0.056183f, 0.061249f, 0.066162f, 0.071777f, 0.077942f, 0.084534f, 0.091553f, 0.099487f,
+ 0.107910f, 0.116882f, 0.127075f, 0.137451f, 0.148804f, 0.161499f, 0.174805f, 0.188721f, 0.203735f, 0.220093f, 0.237427f, 0.254639f,
+ 0.273926f, 0.293457f, 0.313965f, 0.334961f, 0.357666f, 0.379883f, 0.403076f, 0.427002f, 0.451660f, 0.476807f, 0.501953f, 0.527344f,
+ 0.553711f, 0.581055f, 0.815918f, 0.829102f, 0.831055f, 0.831055f, 0.831055f, 0.830566f, 0.000607f, 0.001863f, 0.003416f, 0.004528f,
+ 0.005943f, 0.007191f, 0.008781f, 0.009964f, 0.011337f, 0.012939f, 0.014458f, 0.015808f, 0.018051f, 0.019394f, 0.021332f, 0.023529f,
+ 0.025803f, 0.028168f, 0.030502f, 0.033020f, 0.036072f, 0.039032f, 0.042419f, 0.046082f, 0.049927f, 0.054321f, 0.058411f, 0.063538f,
+ 0.069336f, 0.075684f, 0.081787f, 0.088562f, 0.096436f, 0.104553f, 0.113281f, 0.123596f, 0.133667f, 0.145386f, 0.157471f, 0.171021f,
+ 0.185547f, 0.200562f, 0.216553f, 0.234619f, 0.251709f, 0.271240f, 0.291504f, 0.312012f, 0.333496f, 0.355957f, 0.379395f, 0.403076f,
+ 0.428223f, 0.453857f, 0.479492f, 0.506348f, 0.532715f, 0.560059f, 0.805664f, 0.820801f, 0.823730f, 0.822754f, 0.822754f, 0.822266f,
+ 0.000593f, 0.001862f, 0.002966f, 0.004341f, 0.005600f, 0.006516f, 0.007626f, 0.008995f, 0.010223f, 0.011292f, 0.012848f, 0.014427f,
+ 0.016098f, 0.017532f, 0.019165f, 0.021027f, 0.022842f, 0.024918f, 0.027115f, 0.029739f, 0.032013f, 0.034637f, 0.037506f, 0.040955f,
+ 0.044220f, 0.048065f, 0.051941f, 0.056305f, 0.061768f, 0.066528f, 0.072327f, 0.078979f, 0.085571f, 0.092834f, 0.101135f, 0.110229f,
+ 0.119690f, 0.130127f, 0.141602f, 0.153564f, 0.167114f, 0.181763f, 0.196899f, 0.213623f, 0.230957f, 0.249268f, 0.268555f, 0.289062f,
+ 0.310059f, 0.333252f, 0.355957f, 0.379883f, 0.404541f, 0.430176f, 0.456055f, 0.483887f, 0.510254f, 0.539062f, 0.797852f, 0.812988f,
+ 0.814941f, 0.815430f, 0.815918f, 0.814453f, 0.000556f, 0.001811f, 0.002998f, 0.003815f, 0.004658f, 0.005905f, 0.007099f, 0.008232f,
+ 0.009239f, 0.010483f, 0.011559f, 0.013016f, 0.014305f, 0.015671f, 0.017090f, 0.018646f, 0.020370f, 0.022369f, 0.024124f, 0.026062f,
+ 0.028458f, 0.030624f, 0.033264f, 0.036041f, 0.039307f, 0.042053f, 0.045807f, 0.049530f, 0.054016f, 0.058441f, 0.063904f, 0.069641f,
+ 0.075745f, 0.082520f, 0.089539f, 0.097717f, 0.106750f, 0.116150f, 0.126587f, 0.137817f, 0.150024f, 0.163452f, 0.177490f, 0.193359f,
+ 0.209717f, 0.227539f, 0.246704f, 0.266602f, 0.287598f, 0.309326f, 0.332520f, 0.355713f, 0.380371f, 0.406494f, 0.432861f, 0.459961f,
+ 0.488525f, 0.517090f, 0.787598f, 0.804199f, 0.806641f, 0.807617f, 0.807617f, 0.807129f, 0.000507f, 0.001697f, 0.002468f, 0.003351f,
+ 0.004425f, 0.005486f, 0.006325f, 0.007412f, 0.008156f, 0.009270f, 0.010239f, 0.011497f, 0.012520f, 0.013954f, 0.015182f, 0.016617f,
+ 0.018036f, 0.019714f, 0.021362f, 0.022934f, 0.024704f, 0.026886f, 0.029419f, 0.031525f, 0.034302f, 0.037292f, 0.040558f, 0.043701f,
+ 0.047577f, 0.051849f, 0.056183f, 0.061249f, 0.066467f, 0.072876f, 0.078918f, 0.086548f, 0.094116f, 0.102844f, 0.112427f, 0.122620f,
+ 0.133667f, 0.146362f, 0.159668f, 0.174438f, 0.190063f, 0.207153f, 0.225098f, 0.244263f, 0.264648f, 0.286377f, 0.308350f, 0.332275f,
+ 0.357178f, 0.382080f, 0.408936f, 0.436035f, 0.465820f, 0.495361f, 0.776855f, 0.794922f, 0.797852f, 0.799316f, 0.798828f, 0.798340f,
+ 0.000366f, 0.001644f, 0.002289f, 0.003046f, 0.004082f, 0.005032f, 0.005550f, 0.006599f, 0.007389f, 0.008369f, 0.009201f, 0.010315f,
+ 0.011276f, 0.012405f, 0.013466f, 0.014587f, 0.015991f, 0.017303f, 0.018692f, 0.020081f, 0.021851f, 0.023865f, 0.025726f, 0.027771f,
+ 0.030136f, 0.032532f, 0.035309f, 0.038422f, 0.041626f, 0.045044f, 0.048767f, 0.053375f, 0.057861f, 0.063477f, 0.069031f, 0.075684f,
+ 0.082336f, 0.090515f, 0.099182f, 0.107849f, 0.118958f, 0.130005f, 0.142212f, 0.156128f, 0.170898f, 0.186890f, 0.203857f, 0.222534f,
+ 0.241821f, 0.263428f, 0.285156f, 0.308105f, 0.332275f, 0.359131f, 0.385010f, 0.413086f, 0.441895f, 0.472168f, 0.767090f, 0.785645f,
+ 0.789062f, 0.789551f, 0.790527f, 0.789551f, 0.000340f, 0.001434f, 0.002129f, 0.002827f, 0.003696f, 0.004463f, 0.005112f, 0.005730f,
+ 0.006836f, 0.007465f, 0.008217f, 0.008972f, 0.009972f, 0.010887f, 0.011948f, 0.012794f, 0.013947f, 0.015030f, 0.016266f, 0.017670f,
+ 0.019165f, 0.020813f, 0.022415f, 0.024216f, 0.026047f, 0.028336f, 0.030594f, 0.033142f, 0.035858f, 0.039154f, 0.042328f, 0.046265f,
+ 0.050537f, 0.055237f, 0.059998f, 0.065918f, 0.072083f, 0.078918f, 0.086243f, 0.094788f, 0.104309f, 0.114807f, 0.125854f, 0.138672f,
+ 0.152222f, 0.166992f, 0.183716f, 0.200928f, 0.220459f, 0.240112f, 0.261719f, 0.284668f, 0.308838f, 0.333740f, 0.360840f, 0.388672f,
+ 0.418213f, 0.448730f, 0.756348f, 0.775391f, 0.779297f, 0.780273f, 0.781250f, 0.780273f, 0.000511f, 0.001174f, 0.002163f, 0.002554f,
+ 0.003391f, 0.003990f, 0.004547f, 0.005211f, 0.005993f, 0.006653f, 0.007462f, 0.007942f, 0.008781f, 0.009476f, 0.010323f, 0.011444f,
+ 0.012207f, 0.013062f, 0.014336f, 0.015427f, 0.016464f, 0.017929f, 0.019287f, 0.021164f, 0.022461f, 0.024567f, 0.026474f, 0.028885f,
+ 0.031067f, 0.033630f, 0.036835f, 0.040070f, 0.043488f, 0.047394f, 0.051910f, 0.056732f, 0.062378f, 0.068481f, 0.075073f, 0.082764f,
+ 0.090881f, 0.100403f, 0.110779f, 0.122009f, 0.134399f, 0.148560f, 0.163940f, 0.180298f, 0.198120f, 0.218140f, 0.239014f, 0.260986f,
+ 0.285645f, 0.310059f, 0.336182f, 0.364502f, 0.393311f, 0.424316f, 0.744629f, 0.765137f, 0.769531f, 0.770508f, 0.771484f, 0.771484f,
+ 0.000374f, 0.000983f, 0.001696f, 0.002279f, 0.002924f, 0.003571f, 0.004139f, 0.004742f, 0.005390f, 0.005817f, 0.006371f, 0.006981f,
+ 0.007648f, 0.008354f, 0.009041f, 0.009727f, 0.010536f, 0.011375f, 0.012398f, 0.013535f, 0.014389f, 0.015541f, 0.016602f, 0.018112f,
+ 0.019516f, 0.020996f, 0.022644f, 0.024582f, 0.026627f, 0.028748f, 0.031586f, 0.034210f, 0.037415f, 0.040588f, 0.044464f, 0.048676f,
+ 0.053192f, 0.058472f, 0.064880f, 0.070984f, 0.078674f, 0.086914f, 0.096191f, 0.106445f, 0.117859f, 0.130859f, 0.144775f, 0.160522f,
+ 0.177490f, 0.196411f, 0.215942f, 0.237793f, 0.261475f, 0.285645f, 0.312012f, 0.339111f, 0.368652f, 0.400391f, 0.733887f, 0.755371f,
+ 0.759766f, 0.760742f, 0.761719f, 0.761719f, 0.000298f, 0.000924f, 0.001542f, 0.002125f, 0.002439f, 0.003153f, 0.003502f, 0.004196f,
+ 0.004585f, 0.005039f, 0.005531f, 0.006054f, 0.006531f, 0.007217f, 0.007935f, 0.008362f, 0.009171f, 0.009773f, 0.010704f, 0.011505f,
+ 0.012207f, 0.013321f, 0.014381f, 0.015556f, 0.016586f, 0.017792f, 0.019608f, 0.020844f, 0.022583f, 0.024536f, 0.026566f, 0.028885f,
+ 0.031494f, 0.034332f, 0.037689f, 0.041260f, 0.045258f, 0.049927f, 0.054901f, 0.060699f, 0.067322f, 0.074768f, 0.082764f, 0.091675f,
+ 0.102173f, 0.113831f, 0.126831f, 0.141113f, 0.157104f, 0.175049f, 0.194580f, 0.215210f, 0.237305f, 0.261475f, 0.287598f, 0.314697f,
+ 0.344482f, 0.375977f, 0.721680f, 0.744629f, 0.749512f, 0.751465f, 0.751465f, 0.751465f, 0.000275f, 0.001002f, 0.001335f, 0.001704f,
+ 0.002264f, 0.002790f, 0.003202f, 0.003555f, 0.004017f, 0.004368f, 0.004894f, 0.005318f, 0.005592f, 0.006241f, 0.006611f, 0.007317f,
+ 0.007851f, 0.008560f, 0.009071f, 0.009758f, 0.010429f, 0.011375f, 0.011986f, 0.013130f, 0.013916f, 0.015205f, 0.016403f, 0.017624f,
+ 0.019119f, 0.020660f, 0.022278f, 0.024582f, 0.026474f, 0.029007f, 0.031738f, 0.034668f, 0.038025f, 0.041962f, 0.046417f, 0.051270f,
+ 0.056915f, 0.063110f, 0.070312f, 0.078369f, 0.087769f, 0.098145f, 0.109863f, 0.123352f, 0.137451f, 0.154785f, 0.172363f, 0.192261f,
+ 0.214233f, 0.237793f, 0.262939f, 0.289795f, 0.319336f, 0.351074f, 0.708984f, 0.733398f, 0.738281f, 0.740234f, 0.741211f, 0.740723f,
+ 0.000334f, 0.000805f, 0.001231f, 0.001640f, 0.002033f, 0.002277f, 0.002871f, 0.003115f, 0.003481f, 0.003895f, 0.004147f, 0.004379f,
+ 0.004841f, 0.005306f, 0.005653f, 0.006241f, 0.006630f, 0.007217f, 0.007721f, 0.008133f, 0.008842f, 0.009529f, 0.010010f, 0.011017f,
+ 0.011780f, 0.012733f, 0.013626f, 0.014824f, 0.015656f, 0.017212f, 0.018829f, 0.020248f, 0.021973f, 0.023926f, 0.026306f, 0.028900f,
+ 0.031616f, 0.034973f, 0.038605f, 0.042816f, 0.047424f, 0.052765f, 0.059021f, 0.066162f, 0.074219f, 0.083435f, 0.093994f, 0.105835f,
+ 0.119385f, 0.134277f, 0.151611f, 0.170532f, 0.191284f, 0.214233f, 0.239014f, 0.265381f, 0.293701f, 0.325684f, 0.696289f, 0.722168f,
+ 0.727051f, 0.729004f, 0.729980f, 0.729980f, 0.000215f, 0.000635f, 0.001184f, 0.001348f, 0.001758f, 0.002171f, 0.002249f, 0.002596f,
+ 0.003004f, 0.003325f, 0.003487f, 0.003906f, 0.004108f, 0.004494f, 0.004955f, 0.005241f, 0.005726f, 0.006134f, 0.006485f, 0.006916f,
+ 0.007496f, 0.008072f, 0.008629f, 0.009071f, 0.009857f, 0.010651f, 0.011375f, 0.012283f, 0.013283f, 0.014320f, 0.015350f, 0.016739f,
+ 0.017975f, 0.019852f, 0.021454f, 0.023712f, 0.025925f, 0.028717f, 0.031769f, 0.035217f, 0.038910f, 0.043396f, 0.048767f, 0.054901f,
+ 0.061707f, 0.069824f, 0.078613f, 0.089783f, 0.101685f, 0.115479f, 0.131104f, 0.149292f, 0.168823f, 0.190674f, 0.214844f, 0.241211f,
+ 0.269775f, 0.299561f, 0.683594f, 0.709961f, 0.715332f, 0.717773f, 0.718262f, 0.718750f, 0.000199f, 0.000826f, 0.001047f, 0.001288f,
+ 0.001600f, 0.001857f, 0.002014f, 0.002329f, 0.002535f, 0.002785f, 0.003027f, 0.003210f, 0.003580f, 0.003788f, 0.004025f, 0.004444f,
+ 0.004791f, 0.004974f, 0.005417f, 0.005909f, 0.006248f, 0.006672f, 0.007118f, 0.007664f, 0.008232f, 0.008759f, 0.009598f, 0.009964f,
+ 0.010956f, 0.011650f, 0.012665f, 0.013702f, 0.014832f, 0.016144f, 0.017654f, 0.019211f, 0.021118f, 0.023102f, 0.025681f, 0.028320f,
+ 0.031708f, 0.035370f, 0.039673f, 0.044739f, 0.050812f, 0.057800f, 0.065796f, 0.074768f, 0.085510f, 0.097961f, 0.112000f, 0.128662f,
+ 0.147217f, 0.168213f, 0.190796f, 0.216309f, 0.244751f, 0.274902f, 0.669922f, 0.698730f, 0.703613f, 0.705566f, 0.707031f, 0.707031f,
+ 0.000212f, 0.000458f, 0.000959f, 0.001192f, 0.001321f, 0.001500f, 0.001823f, 0.002064f, 0.002073f, 0.002293f, 0.002512f, 0.002768f,
+ 0.002981f, 0.003138f, 0.003431f, 0.003765f, 0.003918f, 0.004238f, 0.004482f, 0.004814f, 0.005245f, 0.005531f, 0.005871f, 0.006214f,
+ 0.006660f, 0.007236f, 0.007664f, 0.008331f, 0.008812f, 0.009628f, 0.010277f, 0.010979f, 0.012016f, 0.012978f, 0.014084f, 0.015495f,
+ 0.016937f, 0.018494f, 0.020386f, 0.022659f, 0.025208f, 0.028183f, 0.031860f, 0.036072f, 0.040894f, 0.046326f, 0.053009f, 0.061127f,
+ 0.070374f, 0.081238f, 0.094238f, 0.109314f, 0.126343f, 0.145874f, 0.167847f, 0.192505f, 0.219604f, 0.249634f, 0.656738f, 0.686035f,
+ 0.690430f, 0.694336f, 0.694336f, 0.696777f, 0.000151f, 0.000529f, 0.000692f, 0.000883f, 0.001153f, 0.001337f, 0.001380f, 0.001520f,
+ 0.001753f, 0.001886f, 0.002077f, 0.002243f, 0.002386f, 0.002556f, 0.002832f, 0.003029f, 0.003277f, 0.003447f, 0.003683f, 0.003952f,
+ 0.004135f, 0.004578f, 0.004833f, 0.005222f, 0.005417f, 0.005810f, 0.006355f, 0.006718f, 0.007076f, 0.007652f, 0.008293f, 0.008980f,
+ 0.009674f, 0.010422f, 0.011276f, 0.012283f, 0.013443f, 0.014664f, 0.016113f, 0.017853f, 0.019897f, 0.022156f, 0.024826f, 0.028275f,
+ 0.032135f, 0.036865f, 0.042389f, 0.049011f, 0.056732f, 0.066223f, 0.077576f, 0.090820f, 0.106384f, 0.124512f, 0.145264f, 0.169067f,
+ 0.195190f, 0.224976f, 0.642578f, 0.671387f, 0.679688f, 0.682617f, 0.682617f, 0.683594f, 0.000127f, 0.000376f, 0.000600f, 0.000721f,
+ 0.000901f, 0.001066f, 0.001180f, 0.001332f, 0.001455f, 0.001549f, 0.001709f, 0.001831f, 0.001947f, 0.002150f, 0.002245f, 0.002443f,
+ 0.002682f, 0.002844f, 0.002989f, 0.003201f, 0.003403f, 0.003683f, 0.003883f, 0.004097f, 0.004372f, 0.004665f, 0.004963f, 0.005348f,
+ 0.005711f, 0.006165f, 0.006672f, 0.007004f, 0.007610f, 0.008278f, 0.008873f, 0.009636f, 0.010475f, 0.011475f, 0.012634f, 0.014053f,
+ 0.015404f, 0.017242f, 0.019104f, 0.021774f, 0.024750f, 0.028458f, 0.032745f, 0.038391f, 0.044861f, 0.052795f, 0.062103f, 0.073914f,
+ 0.087830f, 0.104553f, 0.123718f, 0.145996f, 0.171509f, 0.200439f, 0.627930f, 0.658691f, 0.666504f, 0.668945f, 0.671387f, 0.671387f,
+ 0.000013f, 0.000374f, 0.000443f, 0.000688f, 0.000819f, 0.000844f, 0.001004f, 0.001132f, 0.001216f, 0.001259f, 0.001405f, 0.001523f,
+ 0.001566f, 0.001753f, 0.001842f, 0.001997f, 0.002022f, 0.002287f, 0.002377f, 0.002541f, 0.002787f, 0.002878f, 0.003096f, 0.003283f,
+ 0.003551f, 0.003651f, 0.003971f, 0.004272f, 0.004524f, 0.004887f, 0.005196f, 0.005527f, 0.005939f, 0.006386f, 0.006977f, 0.007526f,
+ 0.008148f, 0.008835f, 0.009689f, 0.010689f, 0.011810f, 0.013000f, 0.014641f, 0.016388f, 0.018799f, 0.021469f, 0.024734f, 0.029022f,
+ 0.034210f, 0.040588f, 0.048401f, 0.058319f, 0.070435f, 0.085205f, 0.102905f, 0.123901f, 0.147827f, 0.175903f, 0.612793f, 0.645508f,
+ 0.653320f, 0.656250f, 0.657227f, 0.657227f, 0.000113f, 0.000234f, 0.000465f, 0.000547f, 0.000646f, 0.000684f, 0.000711f, 0.000832f,
+ 0.000963f, 0.000999f, 0.001042f, 0.001183f, 0.001279f, 0.001402f, 0.001494f, 0.001513f, 0.001688f, 0.001716f, 0.001919f, 0.001993f,
+ 0.002081f, 0.002253f, 0.002441f, 0.002575f, 0.002714f, 0.002876f, 0.003050f, 0.003214f, 0.003531f, 0.003714f, 0.003956f, 0.004276f,
+ 0.004604f, 0.004967f, 0.005386f, 0.005718f, 0.006283f, 0.006790f, 0.007290f, 0.008133f, 0.008957f, 0.009987f, 0.010956f, 0.012375f,
+ 0.013916f, 0.015991f, 0.018311f, 0.021347f, 0.025253f, 0.030289f, 0.036560f, 0.044586f, 0.054779f, 0.067749f, 0.083252f, 0.102722f,
+ 0.125732f, 0.152100f, 0.597168f, 0.631836f, 0.639160f, 0.643555f, 0.643066f, 0.645508f, 0.000207f, 0.000175f, 0.000364f, 0.000507f,
+ 0.000496f, 0.000569f, 0.000683f, 0.000584f, 0.000737f, 0.000764f, 0.000885f, 0.000964f, 0.000999f, 0.001076f, 0.001085f, 0.001272f,
+ 0.001327f, 0.001354f, 0.001491f, 0.001494f, 0.001677f, 0.001781f, 0.001862f, 0.001976f, 0.002079f, 0.002190f, 0.002338f, 0.002481f,
+ 0.002691f, 0.002811f, 0.003117f, 0.003214f, 0.003422f, 0.003706f, 0.003990f, 0.004314f, 0.004608f, 0.004982f, 0.005379f, 0.006027f,
+ 0.006580f, 0.007351f, 0.008049f, 0.009041f, 0.010323f, 0.011551f, 0.013428f, 0.015419f, 0.018219f, 0.021713f, 0.026550f, 0.032715f,
+ 0.040833f, 0.051605f, 0.065552f, 0.082458f, 0.104004f, 0.129395f, 0.582031f, 0.618652f, 0.625488f, 0.627930f, 0.630859f, 0.631348f,
+ 0.000189f, 0.000160f, 0.000272f, 0.000387f, 0.000335f, 0.000486f, 0.000424f, 0.000469f, 0.000551f, 0.000589f, 0.000700f, 0.000727f,
+ 0.000772f, 0.000859f, 0.000891f, 0.000872f, 0.001000f, 0.001048f, 0.001076f, 0.001172f, 0.001224f, 0.001311f, 0.001376f, 0.001450f,
+ 0.001554f, 0.001591f, 0.001760f, 0.001838f, 0.001999f, 0.002180f, 0.002333f, 0.002388f, 0.002584f, 0.002777f, 0.002907f, 0.003162f,
+ 0.003368f, 0.003677f, 0.003979f, 0.004303f, 0.004715f, 0.005188f, 0.005787f, 0.006378f, 0.007313f, 0.008194f, 0.009407f, 0.010887f,
+ 0.012779f, 0.015198f, 0.018494f, 0.022888f, 0.029037f, 0.037659f, 0.048920f, 0.064270f, 0.083740f, 0.107300f, 0.565918f, 0.603516f,
+ 0.611328f, 0.614746f, 0.617188f, 0.618164f, 0.000000f, 0.000170f, 0.000207f, 0.000274f, 0.000292f, 0.000309f, 0.000381f, 0.000326f,
+ 0.000418f, 0.000439f, 0.000519f, 0.000519f, 0.000560f, 0.000574f, 0.000652f, 0.000678f, 0.000717f, 0.000756f, 0.000782f, 0.000820f,
+ 0.000893f, 0.000937f, 0.000991f, 0.001063f, 0.001112f, 0.001174f, 0.001284f, 0.001302f, 0.001408f, 0.001460f, 0.001586f, 0.001711f,
+ 0.001826f, 0.001959f, 0.002058f, 0.002207f, 0.002388f, 0.002565f, 0.002836f, 0.003046f, 0.003284f, 0.003567f, 0.004009f, 0.004463f,
+ 0.005001f, 0.005661f, 0.006451f, 0.007473f, 0.008751f, 0.010368f, 0.012611f, 0.015587f, 0.019730f, 0.025787f, 0.034729f, 0.047272f,
+ 0.064392f, 0.087097f, 0.550293f, 0.587891f, 0.596680f, 0.600586f, 0.602539f, 0.603516f, 0.000000f, 0.000057f, 0.000175f, 0.000210f,
+ 0.000221f, 0.000261f, 0.000224f, 0.000285f, 0.000296f, 0.000329f, 0.000374f, 0.000329f, 0.000344f, 0.000416f, 0.000421f, 0.000479f,
+ 0.000455f, 0.000530f, 0.000552f, 0.000598f, 0.000640f, 0.000670f, 0.000695f, 0.000740f, 0.000798f, 0.000806f, 0.000883f, 0.000908f,
+ 0.000983f, 0.001094f, 0.001083f, 0.001169f, 0.001242f, 0.001340f, 0.001440f, 0.001536f, 0.001601f, 0.001752f, 0.001893f, 0.002029f,
+ 0.002218f, 0.002424f, 0.002651f, 0.002934f, 0.003294f, 0.003681f, 0.004200f, 0.004833f, 0.005688f, 0.006863f, 0.008202f, 0.010178f,
+ 0.012955f, 0.016846f, 0.023163f, 0.032745f, 0.047150f, 0.067383f, 0.534180f, 0.574219f, 0.582031f, 0.584961f, 0.586914f, 0.589844f,
+ 0.000000f, 0.000105f, 0.000145f, 0.000101f, 0.000161f, 0.000163f, 0.000165f, 0.000193f, 0.000190f, 0.000202f, 0.000205f, 0.000260f,
+ 0.000251f, 0.000281f, 0.000305f, 0.000316f, 0.000323f, 0.000346f, 0.000364f, 0.000383f, 0.000413f, 0.000436f, 0.000461f, 0.000486f,
+ 0.000515f, 0.000564f, 0.000594f, 0.000616f, 0.000639f, 0.000677f, 0.000729f, 0.000748f, 0.000842f, 0.000861f, 0.000943f, 0.000970f,
+ 0.001054f, 0.001120f, 0.001219f, 0.001310f, 0.001398f, 0.001534f, 0.001709f, 0.001852f, 0.002096f, 0.002291f, 0.002594f, 0.002987f,
+ 0.003481f, 0.004128f, 0.004997f, 0.006218f, 0.007950f, 0.010445f, 0.014313f, 0.020874f, 0.032166f, 0.049866f, 0.517578f, 0.558105f,
+ 0.567383f, 0.570801f, 0.573730f, 0.574707f, 0.000000f, 0.000097f, 0.000089f, 0.000082f, 0.000092f, 0.000096f, 0.000092f, 0.000118f,
+ 0.000126f, 0.000130f, 0.000138f, 0.000138f, 0.000143f, 0.000163f, 0.000181f, 0.000187f, 0.000195f, 0.000228f, 0.000221f, 0.000261f,
+ 0.000243f, 0.000254f, 0.000274f, 0.000299f, 0.000334f, 0.000332f, 0.000345f, 0.000362f, 0.000394f, 0.000410f, 0.000433f, 0.000463f,
+ 0.000497f, 0.000510f, 0.000562f, 0.000594f, 0.000636f, 0.000670f, 0.000731f, 0.000777f, 0.000832f, 0.000927f, 0.000991f, 0.001101f,
+ 0.001210f, 0.001350f, 0.001513f, 0.001720f, 0.001999f, 0.002373f, 0.002815f, 0.003498f, 0.004478f, 0.006001f, 0.008347f, 0.012299f,
+ 0.019669f, 0.034210f, 0.501465f, 0.542969f, 0.552246f, 0.556641f, 0.559082f, 0.559570f, 0.000107f, 0.000087f, 0.000077f, 0.000070f,
+ 0.000065f, 0.000066f, 0.000059f, 0.000064f, 0.000065f, 0.000071f, 0.000070f, 0.000095f, 0.000081f, 0.000085f, 0.000110f, 0.000097f,
+ 0.000117f, 0.000126f, 0.000127f, 0.000133f, 0.000132f, 0.000141f, 0.000169f, 0.000173f, 0.000185f, 0.000183f, 0.000192f, 0.000215f,
+ 0.000216f, 0.000235f, 0.000236f, 0.000265f, 0.000278f, 0.000290f, 0.000313f, 0.000317f, 0.000347f, 0.000365f, 0.000400f, 0.000422f,
+ 0.000457f, 0.000494f, 0.000535f, 0.000586f, 0.000639f, 0.000700f, 0.000786f, 0.000888f, 0.001019f, 0.001207f, 0.001435f, 0.001746f,
+ 0.002258f, 0.003019f, 0.004299f, 0.006523f, 0.010612f, 0.020859f, 0.484619f, 0.527344f, 0.536621f, 0.541504f, 0.542969f, 0.544922f,
+ 0.000092f, 0.000070f, 0.000062f, 0.000056f, 0.000051f, 0.000048f, 0.000045f, 0.000044f, 0.000041f, 0.000039f, 0.000038f, 0.000037f,
+ 0.000047f, 0.000039f, 0.000041f, 0.000041f, 0.000058f, 0.000053f, 0.000062f, 0.000064f, 0.000068f, 0.000072f, 0.000076f, 0.000076f,
+ 0.000078f, 0.000092f, 0.000085f, 0.000101f, 0.000104f, 0.000110f, 0.000115f, 0.000118f, 0.000127f, 0.000133f, 0.000152f, 0.000150f,
+ 0.000163f, 0.000190f, 0.000190f, 0.000202f, 0.000213f, 0.000225f, 0.000249f, 0.000268f, 0.000296f, 0.000321f, 0.000354f, 0.000402f,
+ 0.000458f, 0.000520f, 0.000618f, 0.000744f, 0.000950f, 0.001263f, 0.001822f, 0.002865f, 0.005028f, 0.010544f, 0.468018f, 0.511230f,
+ 0.521484f, 0.524902f, 0.529297f, 0.529785f, 0.000067f, 0.000049f, 0.000041f, 0.000037f, 0.000034f, 0.000032f, 0.000031f, 0.000029f,
+ 0.000028f, 0.000027f, 0.000027f, 0.000026f, 0.000025f, 0.000023f, 0.000022f, 0.000021f, 0.000020f, 0.000020f, 0.000023f, 0.000024f,
+ 0.000021f, 0.000022f, 0.000025f, 0.000029f, 0.000030f, 0.000034f, 0.000036f, 0.000034f, 0.000039f, 0.000038f, 0.000045f, 0.000045f,
+ 0.000048f, 0.000051f, 0.000053f, 0.000055f, 0.000063f, 0.000070f, 0.000073f, 0.000073f, 0.000080f, 0.000084f, 0.000089f, 0.000102f,
+ 0.000107f, 0.000115f, 0.000128f, 0.000145f, 0.000156f, 0.000178f, 0.000213f, 0.000253f, 0.000311f, 0.000400f, 0.000572f, 0.000916f,
+ 0.001751f, 0.004158f, 0.450439f, 0.496338f, 0.505859f, 0.510742f, 0.513184f, 0.514648f, 0.000016f, 0.000013f, 0.000011f, 0.000010f,
+ 0.000012f, 0.000012f, 0.000011f, 0.000012f, 0.000011f, 0.000012f, 0.000011f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f,
+ 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f,
+ 0.000008f, 0.000009f, 0.000009f, 0.000009f, 0.000009f, 0.000011f, 0.000012f, 0.000012f, 0.000015f, 0.000014f, 0.000014f, 0.000017f,
+ 0.000018f, 0.000020f, 0.000020f, 0.000022f, 0.000026f, 0.000027f, 0.000028f, 0.000027f, 0.000033f, 0.000036f, 0.000044f, 0.000051f,
+ 0.000057f, 0.000078f, 0.000103f, 0.000159f, 0.000315f, 0.000997f, 0.433350f, 0.479980f, 0.490234f, 0.495605f, 0.498291f, 0.499512f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000004f, 0.000004f, 0.000007f, 0.000025f, 0.416016f, 0.464111f,
+ 0.474854f, 0.479248f, 0.481934f, 0.484375f,
+ },
+ {
+ 0.023209f, 0.069336f, 0.113037f, 0.154663f, 0.193726f, 0.231812f, 0.267578f, 0.301758f, 0.333740f, 0.364258f, 0.393555f, 0.421631f,
+ 0.447510f, 0.473145f, 0.497070f, 0.520020f, 0.541992f, 0.562988f, 0.583008f, 0.602539f, 0.620605f, 0.638184f, 0.655762f, 0.671387f,
+ 0.687500f, 0.702637f, 0.716309f, 0.729980f, 0.744141f, 0.757812f, 0.769531f, 0.782227f, 0.793945f, 0.804688f, 0.815918f, 0.826172f,
+ 0.836426f, 0.846191f, 0.855957f, 0.865234f, 0.874023f, 0.882812f, 0.891113f, 0.898926f, 0.907227f, 0.915039f, 0.922852f, 0.929688f,
+ 0.937012f, 0.943848f, 0.950684f, 0.956543f, 0.963379f, 0.969238f, 0.976074f, 0.981445f, 0.986816f, 0.992676f, 0.991211f, 0.978516f,
+ 0.968750f, 0.960449f, 0.952637f, 0.945312f, 0.019730f, 0.059631f, 0.098206f, 0.135864f, 0.172119f, 0.206421f, 0.239624f, 0.272461f,
+ 0.304932f, 0.333984f, 0.362549f, 0.389648f, 0.416016f, 0.441406f, 0.466309f, 0.489502f, 0.511230f, 0.533203f, 0.554199f, 0.573242f,
+ 0.593262f, 0.611816f, 0.629395f, 0.645508f, 0.662598f, 0.678711f, 0.693359f, 0.708496f, 0.722168f, 0.735840f, 0.750000f, 0.762207f,
+ 0.773926f, 0.786133f, 0.796875f, 0.808594f, 0.818848f, 0.829590f, 0.839355f, 0.850098f, 0.859863f, 0.868652f, 0.877441f, 0.886230f,
+ 0.895020f, 0.903809f, 0.911133f, 0.918457f, 0.925781f, 0.933105f, 0.940430f, 0.946777f, 0.954590f, 0.960938f, 0.966797f, 0.973145f,
+ 0.979004f, 0.984863f, 0.987793f, 0.976074f, 0.966797f, 0.958496f, 0.951172f, 0.943848f, 0.017151f, 0.051636f, 0.085510f, 0.119202f,
+ 0.152466f, 0.184814f, 0.216187f, 0.246582f, 0.276855f, 0.305664f, 0.332764f, 0.360107f, 0.385986f, 0.411621f, 0.435791f, 0.459473f,
+ 0.481445f, 0.502441f, 0.524414f, 0.546387f, 0.565430f, 0.583496f, 0.602051f, 0.619629f, 0.636719f, 0.653320f, 0.669434f, 0.684082f,
+ 0.699707f, 0.713867f, 0.728027f, 0.741211f, 0.754883f, 0.767090f, 0.779297f, 0.791016f, 0.802734f, 0.813965f, 0.824219f, 0.833984f,
+ 0.843750f, 0.854492f, 0.863281f, 0.873535f, 0.882324f, 0.890137f, 0.898926f, 0.906738f, 0.915039f, 0.922852f, 0.930176f, 0.937012f,
+ 0.944336f, 0.951172f, 0.958008f, 0.964844f, 0.970703f, 0.977051f, 0.983887f, 0.972656f, 0.964355f, 0.956543f, 0.949219f, 0.942383f,
+ 0.014885f, 0.044678f, 0.075195f, 0.104919f, 0.135254f, 0.165649f, 0.194702f, 0.223633f, 0.251221f, 0.279053f, 0.305420f, 0.331543f,
+ 0.357422f, 0.382568f, 0.406982f, 0.430420f, 0.453369f, 0.475586f, 0.496582f, 0.517090f, 0.536133f, 0.556641f, 0.575684f, 0.592773f,
+ 0.611328f, 0.628418f, 0.643555f, 0.661621f, 0.676270f, 0.691406f, 0.705566f, 0.720215f, 0.733887f, 0.746582f, 0.759766f, 0.772949f,
+ 0.784668f, 0.795898f, 0.807129f, 0.818359f, 0.828125f, 0.838867f, 0.848633f, 0.858887f, 0.867676f, 0.877441f, 0.886230f, 0.894531f,
+ 0.903320f, 0.911621f, 0.919434f, 0.927734f, 0.934570f, 0.940918f, 0.948730f, 0.956543f, 0.962402f, 0.969238f, 0.979980f, 0.970215f,
+ 0.961914f, 0.954102f, 0.947266f, 0.940918f, 0.013046f, 0.038940f, 0.066162f, 0.093323f, 0.120544f, 0.147583f, 0.174683f, 0.201538f,
+ 0.228516f, 0.254639f, 0.280518f, 0.304932f, 0.330566f, 0.354492f, 0.379395f, 0.402100f, 0.424561f, 0.446533f, 0.467529f, 0.488525f,
+ 0.509277f, 0.529297f, 0.547852f, 0.566895f, 0.585449f, 0.602539f, 0.620605f, 0.636230f, 0.653809f, 0.667480f, 0.684570f, 0.698242f,
+ 0.712891f, 0.726562f, 0.739746f, 0.753418f, 0.765625f, 0.777344f, 0.789551f, 0.801270f, 0.812500f, 0.823730f, 0.833984f, 0.844238f,
+ 0.854004f, 0.863770f, 0.874023f, 0.882324f, 0.891113f, 0.899902f, 0.908203f, 0.916504f, 0.924805f, 0.932129f, 0.939453f, 0.947266f,
+ 0.954102f, 0.960938f, 0.976562f, 0.967285f, 0.958984f, 0.951660f, 0.944824f, 0.938965f, 0.011696f, 0.034698f, 0.058807f, 0.083130f,
+ 0.107727f, 0.132324f, 0.156982f, 0.182251f, 0.207153f, 0.232178f, 0.256836f, 0.280762f, 0.304688f, 0.328369f, 0.352295f, 0.375244f,
+ 0.397461f, 0.419434f, 0.440430f, 0.461914f, 0.482178f, 0.501953f, 0.522461f, 0.540527f, 0.559570f, 0.577148f, 0.595703f, 0.613281f,
+ 0.628418f, 0.644531f, 0.661621f, 0.676270f, 0.691406f, 0.705078f, 0.719727f, 0.733887f, 0.746094f, 0.759766f, 0.771973f, 0.784180f,
+ 0.795898f, 0.807617f, 0.818359f, 0.829102f, 0.839844f, 0.850098f, 0.859375f, 0.869629f, 0.878906f, 0.887695f, 0.896484f, 0.905273f,
+ 0.914062f, 0.921875f, 0.929688f, 0.937988f, 0.944824f, 0.952637f, 0.973145f, 0.963379f, 0.956055f, 0.949219f, 0.942871f, 0.937012f,
+ 0.010094f, 0.030975f, 0.052063f, 0.073975f, 0.096069f, 0.118713f, 0.141479f, 0.164551f, 0.187866f, 0.211182f, 0.234985f, 0.258057f,
+ 0.280518f, 0.303467f, 0.326172f, 0.348145f, 0.370117f, 0.392822f, 0.413574f, 0.434814f, 0.455322f, 0.476074f, 0.495361f, 0.515137f,
+ 0.533203f, 0.551758f, 0.569824f, 0.586426f, 0.604492f, 0.621582f, 0.637695f, 0.654297f, 0.668945f, 0.683594f, 0.699219f, 0.712402f,
+ 0.728516f, 0.741699f, 0.753906f, 0.767090f, 0.778320f, 0.790527f, 0.802246f, 0.813965f, 0.824219f, 0.835449f, 0.846680f, 0.855957f,
+ 0.865723f, 0.875488f, 0.884766f, 0.894043f, 0.902832f, 0.911133f, 0.919434f, 0.927734f, 0.935547f, 0.943359f, 0.968750f, 0.960449f,
+ 0.953125f, 0.946289f, 0.940430f, 0.934570f, 0.008797f, 0.027466f, 0.045959f, 0.066223f, 0.086304f, 0.106506f, 0.127441f, 0.149170f,
+ 0.170532f, 0.192261f, 0.213867f, 0.236206f, 0.258057f, 0.280273f, 0.301758f, 0.323486f, 0.344727f, 0.367188f, 0.388184f, 0.408447f,
+ 0.429443f, 0.450439f, 0.469727f, 0.489014f, 0.508301f, 0.526855f, 0.545410f, 0.562500f, 0.581055f, 0.597656f, 0.613770f, 0.630859f,
+ 0.647461f, 0.663574f, 0.677734f, 0.693359f, 0.707031f, 0.720703f, 0.735352f, 0.748047f, 0.760254f, 0.772461f, 0.785156f, 0.797363f,
+ 0.810059f, 0.819824f, 0.831543f, 0.842285f, 0.852051f, 0.862793f, 0.873047f, 0.882324f, 0.891113f, 0.899902f, 0.909180f, 0.917969f,
+ 0.925781f, 0.934082f, 0.964355f, 0.957031f, 0.949707f, 0.943359f, 0.937988f, 0.932129f, 0.007927f, 0.024414f, 0.041077f, 0.059204f,
+ 0.077148f, 0.095581f, 0.115479f, 0.134644f, 0.154785f, 0.175293f, 0.196045f, 0.216553f, 0.236694f, 0.258057f, 0.278809f, 0.300049f,
+ 0.321289f, 0.342529f, 0.363281f, 0.383545f, 0.403564f, 0.424072f, 0.444092f, 0.463135f, 0.483154f, 0.501953f, 0.519531f, 0.539062f,
+ 0.555664f, 0.574707f, 0.591309f, 0.608398f, 0.624512f, 0.640137f, 0.655762f, 0.671875f, 0.686523f, 0.701172f, 0.715820f, 0.729004f,
+ 0.742676f, 0.755859f, 0.769043f, 0.781738f, 0.792969f, 0.805176f, 0.816895f, 0.827637f, 0.838867f, 0.849121f, 0.859375f, 0.870117f,
+ 0.879395f, 0.889160f, 0.898926f, 0.906738f, 0.916504f, 0.924805f, 0.960938f, 0.953125f, 0.947266f, 0.940430f, 0.935547f, 0.929688f,
+ 0.007080f, 0.022247f, 0.037445f, 0.053070f, 0.069336f, 0.086975f, 0.103577f, 0.121948f, 0.140503f, 0.158936f, 0.178833f, 0.198242f,
+ 0.217651f, 0.237793f, 0.257812f, 0.278076f, 0.297607f, 0.318604f, 0.338623f, 0.358643f, 0.378662f, 0.399170f, 0.418213f, 0.438721f,
+ 0.457520f, 0.477051f, 0.495361f, 0.513672f, 0.531250f, 0.549316f, 0.567383f, 0.583984f, 0.601562f, 0.617676f, 0.634277f, 0.650391f,
+ 0.666016f, 0.680176f, 0.695801f, 0.710449f, 0.723633f, 0.737305f, 0.750977f, 0.764648f, 0.776367f, 0.789551f, 0.802246f, 0.813477f,
+ 0.824219f, 0.835938f, 0.846680f, 0.857422f, 0.867188f, 0.876953f, 0.887207f, 0.895996f, 0.905762f, 0.915527f, 0.955566f, 0.949707f,
+ 0.943359f, 0.937988f, 0.932129f, 0.927246f, 0.006363f, 0.019516f, 0.033691f, 0.047577f, 0.062469f, 0.078186f, 0.093933f, 0.110657f,
+ 0.127563f, 0.144653f, 0.162598f, 0.181152f, 0.199707f, 0.218384f, 0.237427f, 0.257324f, 0.276367f, 0.295166f, 0.315674f, 0.335205f,
+ 0.355225f, 0.374756f, 0.393799f, 0.413574f, 0.432617f, 0.451904f, 0.470459f, 0.489258f, 0.508301f, 0.525879f, 0.543945f, 0.560059f,
+ 0.578613f, 0.595703f, 0.612793f, 0.628418f, 0.644531f, 0.659668f, 0.675293f, 0.689941f, 0.704590f, 0.719238f, 0.732910f, 0.747070f,
+ 0.759766f, 0.773438f, 0.785156f, 0.797852f, 0.809570f, 0.821289f, 0.833008f, 0.843750f, 0.854980f, 0.865723f, 0.875977f, 0.886230f,
+ 0.895508f, 0.904785f, 0.951660f, 0.945801f, 0.939941f, 0.934570f, 0.929199f, 0.924805f, 0.005985f, 0.017776f, 0.030212f, 0.043030f,
+ 0.056488f, 0.070190f, 0.085205f, 0.100342f, 0.115723f, 0.132446f, 0.148438f, 0.165771f, 0.183228f, 0.200684f, 0.218994f, 0.237183f,
+ 0.255859f, 0.274170f, 0.292725f, 0.313477f, 0.331299f, 0.351318f, 0.369873f, 0.389160f, 0.408936f, 0.426758f, 0.446533f, 0.464844f,
+ 0.483154f, 0.501465f, 0.519531f, 0.537598f, 0.555664f, 0.572754f, 0.589844f, 0.605957f, 0.622070f, 0.639648f, 0.654297f, 0.670898f,
+ 0.685059f, 0.700195f, 0.714844f, 0.728516f, 0.742188f, 0.754883f, 0.769043f, 0.781738f, 0.795410f, 0.808105f, 0.818359f, 0.830566f,
+ 0.841797f, 0.853027f, 0.863770f, 0.874023f, 0.884766f, 0.893555f, 0.947266f, 0.942383f, 0.936523f, 0.930664f, 0.926270f, 0.921387f,
+ 0.005173f, 0.016083f, 0.027359f, 0.038849f, 0.051056f, 0.063843f, 0.077026f, 0.091064f, 0.105591f, 0.120422f, 0.135498f, 0.150879f,
+ 0.167480f, 0.184326f, 0.201172f, 0.218384f, 0.236084f, 0.254395f, 0.272949f, 0.291260f, 0.309570f, 0.328125f, 0.346680f, 0.365967f,
+ 0.384766f, 0.403320f, 0.422119f, 0.440918f, 0.458984f, 0.477783f, 0.496094f, 0.513672f, 0.531738f, 0.548828f, 0.566406f, 0.583984f,
+ 0.600098f, 0.617188f, 0.632812f, 0.649902f, 0.665527f, 0.681152f, 0.694824f, 0.709473f, 0.724121f, 0.738770f, 0.752441f, 0.765137f,
+ 0.778809f, 0.791992f, 0.803711f, 0.815918f, 0.828125f, 0.839844f, 0.851562f, 0.862793f, 0.873535f, 0.883789f, 0.941895f, 0.938477f,
+ 0.933105f, 0.927246f, 0.922363f, 0.918457f, 0.004791f, 0.014610f, 0.024475f, 0.035126f, 0.046478f, 0.057922f, 0.069885f, 0.083008f,
+ 0.096069f, 0.109253f, 0.123840f, 0.137939f, 0.153076f, 0.168701f, 0.185059f, 0.200928f, 0.218262f, 0.234985f, 0.252686f, 0.270264f,
+ 0.288086f, 0.306396f, 0.324951f, 0.343018f, 0.362305f, 0.379883f, 0.398926f, 0.417236f, 0.435547f, 0.454346f, 0.472656f, 0.491211f,
+ 0.508301f, 0.526855f, 0.543457f, 0.561523f, 0.578125f, 0.595215f, 0.612305f, 0.628418f, 0.644043f, 0.660645f, 0.675781f, 0.691406f,
+ 0.706055f, 0.720215f, 0.735840f, 0.749023f, 0.762695f, 0.776855f, 0.789551f, 0.800781f, 0.814941f, 0.826172f, 0.838867f, 0.851074f,
+ 0.862305f, 0.872070f, 0.937500f, 0.933594f, 0.929199f, 0.923828f, 0.919434f, 0.915527f, 0.004387f, 0.013268f, 0.022385f, 0.031860f,
+ 0.041962f, 0.052612f, 0.063171f, 0.075073f, 0.086792f, 0.099854f, 0.113037f, 0.125977f, 0.140381f, 0.154663f, 0.169678f, 0.184814f,
+ 0.200562f, 0.217773f, 0.234131f, 0.250732f, 0.268066f, 0.284912f, 0.303223f, 0.321289f, 0.339355f, 0.357666f, 0.375488f, 0.394043f,
+ 0.411865f, 0.430664f, 0.448730f, 0.467041f, 0.485352f, 0.503418f, 0.520508f, 0.539062f, 0.556152f, 0.573242f, 0.590820f, 0.606934f,
+ 0.624512f, 0.640625f, 0.655762f, 0.672363f, 0.687500f, 0.702148f, 0.718750f, 0.731934f, 0.746582f, 0.759766f, 0.772949f, 0.787109f,
+ 0.800781f, 0.813477f, 0.825195f, 0.838379f, 0.850098f, 0.861816f, 0.932617f, 0.929688f, 0.925293f, 0.919922f, 0.915527f, 0.912109f,
+ 0.003941f, 0.011986f, 0.020630f, 0.029144f, 0.038544f, 0.048035f, 0.058075f, 0.068542f, 0.079590f, 0.090942f, 0.102661f, 0.115295f,
+ 0.128296f, 0.141602f, 0.155518f, 0.170654f, 0.185425f, 0.200684f, 0.216309f, 0.231812f, 0.249146f, 0.265137f, 0.282471f, 0.299072f,
+ 0.317139f, 0.334717f, 0.352783f, 0.371338f, 0.388916f, 0.406982f, 0.425537f, 0.443848f, 0.461914f, 0.479980f, 0.498291f, 0.515625f,
+ 0.533203f, 0.550293f, 0.568359f, 0.585449f, 0.603027f, 0.618652f, 0.635742f, 0.652344f, 0.668457f, 0.684082f, 0.699219f, 0.713867f,
+ 0.729004f, 0.743652f, 0.757812f, 0.771484f, 0.785645f, 0.798828f, 0.812012f, 0.824219f, 0.836914f, 0.850098f, 0.927246f, 0.925293f,
+ 0.920410f, 0.916504f, 0.912598f, 0.908203f, 0.003790f, 0.011009f, 0.018829f, 0.026779f, 0.035339f, 0.043762f, 0.053223f, 0.062408f,
+ 0.072693f, 0.082947f, 0.093689f, 0.105469f, 0.117554f, 0.130005f, 0.142822f, 0.156494f, 0.170166f, 0.184448f, 0.198975f, 0.213745f,
+ 0.230469f, 0.246460f, 0.262939f, 0.279541f, 0.296143f, 0.313721f, 0.331299f, 0.348633f, 0.367188f, 0.384521f, 0.402344f, 0.420410f,
+ 0.438965f, 0.457275f, 0.475830f, 0.493164f, 0.510742f, 0.528809f, 0.546387f, 0.564453f, 0.581055f, 0.598145f, 0.615234f, 0.631836f,
+ 0.647461f, 0.665527f, 0.680664f, 0.696289f, 0.711914f, 0.728027f, 0.741211f, 0.756836f, 0.770508f, 0.783691f, 0.798340f, 0.811523f,
+ 0.824219f, 0.837402f, 0.921387f, 0.920410f, 0.916504f, 0.913086f, 0.908691f, 0.904785f, 0.003479f, 0.009949f, 0.016937f, 0.024445f,
+ 0.031708f, 0.039948f, 0.048218f, 0.056793f, 0.066223f, 0.075928f, 0.085632f, 0.096313f, 0.107178f, 0.118958f, 0.130493f, 0.143311f,
+ 0.156494f, 0.170044f, 0.183960f, 0.197876f, 0.213501f, 0.228027f, 0.244019f, 0.260010f, 0.276611f, 0.293213f, 0.309814f, 0.327393f,
+ 0.344482f, 0.363037f, 0.379883f, 0.398438f, 0.416504f, 0.434082f, 0.451904f, 0.470215f, 0.488525f, 0.505859f, 0.523926f, 0.541504f,
+ 0.559570f, 0.577637f, 0.594238f, 0.611328f, 0.628418f, 0.645020f, 0.661133f, 0.677246f, 0.693848f, 0.709961f, 0.725586f, 0.739746f,
+ 0.755371f, 0.769531f, 0.783203f, 0.797852f, 0.810547f, 0.824707f, 0.916016f, 0.915527f, 0.912109f, 0.908691f, 0.904785f, 0.900879f,
+ 0.003014f, 0.008842f, 0.015640f, 0.022018f, 0.028885f, 0.036163f, 0.044250f, 0.051819f, 0.059967f, 0.069031f, 0.078247f, 0.088135f,
+ 0.098267f, 0.108337f, 0.119751f, 0.131470f, 0.143433f, 0.156006f, 0.169189f, 0.183105f, 0.196655f, 0.211304f, 0.226196f, 0.241211f,
+ 0.257080f, 0.273438f, 0.289307f, 0.306396f, 0.323975f, 0.340576f, 0.358398f, 0.375732f, 0.393799f, 0.411133f, 0.429688f, 0.447998f,
+ 0.466064f, 0.483887f, 0.501465f, 0.519531f, 0.537598f, 0.555664f, 0.573242f, 0.590820f, 0.607910f, 0.625000f, 0.642578f, 0.658203f,
+ 0.675293f, 0.691406f, 0.707520f, 0.724121f, 0.738770f, 0.753418f, 0.769531f, 0.783203f, 0.797363f, 0.811523f, 0.910156f, 0.910645f,
+ 0.907715f, 0.904785f, 0.900879f, 0.896973f, 0.002861f, 0.008591f, 0.014000f, 0.020203f, 0.026962f, 0.033203f, 0.040161f, 0.047485f,
+ 0.055237f, 0.062988f, 0.071594f, 0.080750f, 0.089905f, 0.099854f, 0.109741f, 0.120056f, 0.131592f, 0.143311f, 0.155640f, 0.167969f,
+ 0.181763f, 0.195190f, 0.209229f, 0.223877f, 0.238647f, 0.254150f, 0.269531f, 0.285889f, 0.302979f, 0.319824f, 0.336426f, 0.354004f,
+ 0.372070f, 0.389893f, 0.406982f, 0.424805f, 0.443359f, 0.461182f, 0.479492f, 0.498047f, 0.515625f, 0.533691f, 0.551270f, 0.569336f,
+ 0.587402f, 0.604492f, 0.622070f, 0.639160f, 0.656738f, 0.673828f, 0.689941f, 0.705566f, 0.722168f, 0.737793f, 0.753418f, 0.768066f,
+ 0.783203f, 0.798340f, 0.904297f, 0.905762f, 0.902832f, 0.899414f, 0.895996f, 0.893066f, 0.002535f, 0.007812f, 0.013252f, 0.018738f,
+ 0.024384f, 0.030548f, 0.036774f, 0.043427f, 0.050476f, 0.057556f, 0.065491f, 0.073425f, 0.082458f, 0.091370f, 0.100525f, 0.110413f,
+ 0.120605f, 0.131592f, 0.142822f, 0.154663f, 0.166870f, 0.180176f, 0.193237f, 0.207031f, 0.221191f, 0.236084f, 0.250732f, 0.266602f,
+ 0.282959f, 0.299072f, 0.315430f, 0.332520f, 0.350342f, 0.367676f, 0.385010f, 0.403076f, 0.421631f, 0.439209f, 0.457520f, 0.475342f,
+ 0.494141f, 0.512695f, 0.530273f, 0.547852f, 0.565918f, 0.584473f, 0.602051f, 0.619629f, 0.637207f, 0.655273f, 0.671387f, 0.688965f,
+ 0.706055f, 0.721191f, 0.737305f, 0.752930f, 0.769531f, 0.784668f, 0.898438f, 0.900879f, 0.897949f, 0.894531f, 0.891602f, 0.888672f,
+ 0.002411f, 0.007103f, 0.012161f, 0.017105f, 0.022385f, 0.027985f, 0.033203f, 0.039581f, 0.045532f, 0.052521f, 0.059814f, 0.067261f,
+ 0.074768f, 0.083313f, 0.092041f, 0.101013f, 0.110291f, 0.120361f, 0.130615f, 0.141724f, 0.153076f, 0.165283f, 0.177612f, 0.190918f,
+ 0.204346f, 0.218506f, 0.233154f, 0.247559f, 0.263428f, 0.279053f, 0.295166f, 0.312256f, 0.328857f, 0.345947f, 0.363281f, 0.381348f,
+ 0.398926f, 0.417236f, 0.435547f, 0.453369f, 0.471191f, 0.489502f, 0.508301f, 0.525879f, 0.545410f, 0.563477f, 0.581055f, 0.600098f,
+ 0.617676f, 0.635254f, 0.653809f, 0.670410f, 0.687500f, 0.705078f, 0.720703f, 0.736816f, 0.753418f, 0.769531f, 0.892090f, 0.895020f,
+ 0.892578f, 0.889648f, 0.887207f, 0.884277f, 0.002344f, 0.006565f, 0.011322f, 0.015686f, 0.020630f, 0.025574f, 0.030807f, 0.035980f,
+ 0.042084f, 0.048279f, 0.054352f, 0.061432f, 0.068848f, 0.076172f, 0.083618f, 0.092590f, 0.101135f, 0.109619f, 0.120178f, 0.130249f,
+ 0.140991f, 0.151978f, 0.163696f, 0.175781f, 0.188721f, 0.202026f, 0.215820f, 0.230103f, 0.244873f, 0.259766f, 0.275635f, 0.291504f,
+ 0.307617f, 0.324219f, 0.342041f, 0.358887f, 0.376709f, 0.394775f, 0.412354f, 0.431152f, 0.448975f, 0.468018f, 0.486328f, 0.504883f,
+ 0.523438f, 0.541992f, 0.560547f, 0.579102f, 0.597656f, 0.615234f, 0.633789f, 0.651855f, 0.669434f, 0.687500f, 0.704590f, 0.721680f,
+ 0.738770f, 0.755859f, 0.886719f, 0.889648f, 0.887695f, 0.884766f, 0.882812f, 0.879883f, 0.002003f, 0.006268f, 0.009987f, 0.014198f,
+ 0.018875f, 0.023605f, 0.028259f, 0.033203f, 0.038513f, 0.044495f, 0.049866f, 0.056152f, 0.062500f, 0.069458f, 0.076660f, 0.084473f,
+ 0.092163f, 0.100586f, 0.109741f, 0.119324f, 0.128662f, 0.139526f, 0.150146f, 0.161499f, 0.173706f, 0.185791f, 0.199341f, 0.212891f,
+ 0.227051f, 0.241455f, 0.256592f, 0.271729f, 0.288330f, 0.304199f, 0.321045f, 0.337891f, 0.355469f, 0.373291f, 0.391113f, 0.408936f,
+ 0.426758f, 0.446289f, 0.464600f, 0.483643f, 0.500977f, 0.520996f, 0.539551f, 0.558594f, 0.577148f, 0.595703f, 0.614746f, 0.632324f,
+ 0.650879f, 0.669434f, 0.687012f, 0.704590f, 0.722656f, 0.740234f, 0.880371f, 0.883301f, 0.881836f, 0.879883f, 0.877441f, 0.875000f,
+ 0.001739f, 0.005779f, 0.009598f, 0.013245f, 0.017334f, 0.021637f, 0.025955f, 0.030121f, 0.035217f, 0.040131f, 0.045990f, 0.051453f,
+ 0.056915f, 0.063354f, 0.070007f, 0.076965f, 0.084351f, 0.091980f, 0.100281f, 0.108826f, 0.117981f, 0.127441f, 0.137939f, 0.148315f,
+ 0.160034f, 0.171753f, 0.183594f, 0.196167f, 0.209961f, 0.223511f, 0.238037f, 0.252930f, 0.268066f, 0.284180f, 0.300537f, 0.317139f,
+ 0.333740f, 0.351074f, 0.368896f, 0.386719f, 0.405273f, 0.423584f, 0.442871f, 0.460938f, 0.479736f, 0.499512f, 0.517578f, 0.537109f,
+ 0.555664f, 0.575195f, 0.594238f, 0.613770f, 0.632324f, 0.650879f, 0.669922f, 0.687988f, 0.706055f, 0.724121f, 0.873047f, 0.876953f,
+ 0.875488f, 0.874023f, 0.872559f, 0.869141f, 0.001648f, 0.005039f, 0.008675f, 0.012161f, 0.015823f, 0.019760f, 0.023865f, 0.028015f,
+ 0.032318f, 0.036865f, 0.041504f, 0.046906f, 0.051758f, 0.057922f, 0.064087f, 0.070435f, 0.077209f, 0.084290f, 0.091736f, 0.099243f,
+ 0.108215f, 0.117004f, 0.126343f, 0.135620f, 0.146484f, 0.157349f, 0.168823f, 0.180908f, 0.193848f, 0.206909f, 0.220459f, 0.234619f,
+ 0.249634f, 0.264404f, 0.280273f, 0.296631f, 0.313232f, 0.329834f, 0.347412f, 0.365479f, 0.383545f, 0.401855f, 0.420166f, 0.438721f,
+ 0.458252f, 0.477783f, 0.496826f, 0.516602f, 0.535156f, 0.554199f, 0.574219f, 0.593750f, 0.612305f, 0.631836f, 0.651367f, 0.670410f,
+ 0.689453f, 0.708984f, 0.865234f, 0.872070f, 0.870605f, 0.868652f, 0.866699f, 0.863770f, 0.001492f, 0.004704f, 0.007973f, 0.011124f,
+ 0.014603f, 0.017792f, 0.021652f, 0.025314f, 0.029526f, 0.033722f, 0.038147f, 0.042694f, 0.047668f, 0.052673f, 0.057983f, 0.064209f,
+ 0.070068f, 0.076233f, 0.083313f, 0.090942f, 0.098572f, 0.106750f, 0.115295f, 0.124512f, 0.134277f, 0.144287f, 0.154663f, 0.166504f,
+ 0.178345f, 0.190063f, 0.203247f, 0.217041f, 0.231079f, 0.245850f, 0.260986f, 0.276611f, 0.293213f, 0.309570f, 0.326172f, 0.343994f,
+ 0.361816f, 0.379395f, 0.397949f, 0.417480f, 0.436523f, 0.455322f, 0.474854f, 0.493896f, 0.514160f, 0.533691f, 0.553711f, 0.573730f,
+ 0.593262f, 0.612793f, 0.632812f, 0.651855f, 0.672363f, 0.690918f, 0.857910f, 0.865723f, 0.864746f, 0.863281f, 0.860352f, 0.858887f,
+ 0.001657f, 0.004684f, 0.007290f, 0.010201f, 0.013657f, 0.016541f, 0.019989f, 0.023636f, 0.026932f, 0.030548f, 0.034576f, 0.039154f,
+ 0.043793f, 0.048126f, 0.053162f, 0.058319f, 0.063721f, 0.069885f, 0.076355f, 0.082947f, 0.089844f, 0.097046f, 0.105286f, 0.113281f,
+ 0.122559f, 0.131348f, 0.141357f, 0.152100f, 0.163330f, 0.175415f, 0.187256f, 0.199951f, 0.213501f, 0.227051f, 0.241943f, 0.257324f,
+ 0.273193f, 0.288818f, 0.305420f, 0.322754f, 0.340576f, 0.358643f, 0.375732f, 0.394775f, 0.414307f, 0.433105f, 0.453613f, 0.472168f,
+ 0.492188f, 0.512695f, 0.532715f, 0.552246f, 0.573242f, 0.593262f, 0.613770f, 0.632812f, 0.654785f, 0.673828f, 0.851074f, 0.859375f,
+ 0.858398f, 0.856934f, 0.855469f, 0.853027f, 0.001457f, 0.003944f, 0.006870f, 0.009392f, 0.012543f, 0.015190f, 0.018417f, 0.021576f,
+ 0.024811f, 0.028122f, 0.031708f, 0.035278f, 0.039398f, 0.043793f, 0.048218f, 0.052887f, 0.058044f, 0.063477f, 0.069397f, 0.075256f,
+ 0.081360f, 0.088318f, 0.095398f, 0.103210f, 0.111084f, 0.120361f, 0.129150f, 0.139038f, 0.149292f, 0.160645f, 0.172241f, 0.183716f,
+ 0.196533f, 0.209595f, 0.224121f, 0.238647f, 0.253174f, 0.268799f, 0.286133f, 0.302490f, 0.319092f, 0.337158f, 0.355225f, 0.373535f,
+ 0.392090f, 0.411133f, 0.430908f, 0.450928f, 0.470947f, 0.490967f, 0.511719f, 0.531250f, 0.551758f, 0.573730f, 0.594238f, 0.614746f,
+ 0.636230f, 0.656738f, 0.842773f, 0.852051f, 0.851562f, 0.851074f, 0.848633f, 0.846680f, 0.001404f, 0.003891f, 0.006233f, 0.008751f,
+ 0.011353f, 0.014175f, 0.017075f, 0.019592f, 0.022842f, 0.025772f, 0.028839f, 0.032410f, 0.036011f, 0.039764f, 0.043671f, 0.048126f,
+ 0.052704f, 0.057373f, 0.062561f, 0.067688f, 0.074158f, 0.080200f, 0.086853f, 0.093445f, 0.101379f, 0.109192f, 0.117432f, 0.126709f,
+ 0.136353f, 0.146484f, 0.157227f, 0.168823f, 0.180542f, 0.193115f, 0.206299f, 0.219727f, 0.234375f, 0.249756f, 0.265869f, 0.281738f,
+ 0.298096f, 0.315674f, 0.333252f, 0.352051f, 0.370850f, 0.389160f, 0.409180f, 0.428955f, 0.448730f, 0.469971f, 0.489502f, 0.510742f,
+ 0.531738f, 0.552246f, 0.574707f, 0.595215f, 0.617676f, 0.639160f, 0.835449f, 0.845215f, 0.845215f, 0.844238f, 0.843262f, 0.840332f,
+ 0.001275f, 0.003536f, 0.005600f, 0.007881f, 0.010628f, 0.012878f, 0.015610f, 0.018097f, 0.020996f, 0.023376f, 0.026443f, 0.029556f,
+ 0.032867f, 0.036163f, 0.039581f, 0.043915f, 0.047943f, 0.052216f, 0.056763f, 0.061981f, 0.067322f, 0.072449f, 0.078796f, 0.084717f,
+ 0.091919f, 0.098999f, 0.106995f, 0.115417f, 0.124084f, 0.133667f, 0.143433f, 0.154297f, 0.165161f, 0.177124f, 0.189697f, 0.202759f,
+ 0.216309f, 0.230713f, 0.245728f, 0.261719f, 0.278320f, 0.295410f, 0.312256f, 0.330566f, 0.349365f, 0.367676f, 0.386719f, 0.406494f,
+ 0.427246f, 0.447266f, 0.468506f, 0.489746f, 0.510742f, 0.532227f, 0.553711f, 0.575684f, 0.597656f, 0.619141f, 0.826172f, 0.837402f,
+ 0.837891f, 0.837402f, 0.835449f, 0.833984f, 0.001134f, 0.003105f, 0.005337f, 0.007462f, 0.009628f, 0.011833f, 0.014137f, 0.016113f,
+ 0.018875f, 0.021484f, 0.024063f, 0.026581f, 0.029709f, 0.032623f, 0.036194f, 0.039703f, 0.043335f, 0.047058f, 0.051422f, 0.055908f,
+ 0.060608f, 0.065491f, 0.071167f, 0.076843f, 0.083313f, 0.089661f, 0.097168f, 0.104492f, 0.112122f, 0.121155f, 0.130615f, 0.140137f,
+ 0.150757f, 0.161499f, 0.173462f, 0.185547f, 0.199341f, 0.212524f, 0.227051f, 0.242310f, 0.258057f, 0.274414f, 0.291016f, 0.309082f,
+ 0.327148f, 0.345459f, 0.364990f, 0.384521f, 0.404297f, 0.425781f, 0.445801f, 0.467285f, 0.489258f, 0.510254f, 0.533203f, 0.555664f,
+ 0.578125f, 0.601074f, 0.817871f, 0.830078f, 0.831055f, 0.830078f, 0.829102f, 0.828125f, 0.001101f, 0.003019f, 0.004818f, 0.006725f,
+ 0.008781f, 0.010864f, 0.013069f, 0.014801f, 0.017151f, 0.019531f, 0.021973f, 0.024429f, 0.026917f, 0.030121f, 0.033112f, 0.036041f,
+ 0.039337f, 0.042542f, 0.046509f, 0.050537f, 0.054596f, 0.058990f, 0.064209f, 0.069519f, 0.075134f, 0.080994f, 0.087158f, 0.094177f,
+ 0.102051f, 0.109741f, 0.117981f, 0.127319f, 0.136963f, 0.147095f, 0.158081f, 0.169434f, 0.182251f, 0.195557f, 0.208984f, 0.223267f,
+ 0.238281f, 0.254639f, 0.270996f, 0.288330f, 0.305908f, 0.324219f, 0.343018f, 0.362549f, 0.382324f, 0.402832f, 0.424805f, 0.445312f,
+ 0.467529f, 0.489258f, 0.511230f, 0.535645f, 0.558594f, 0.582031f, 0.809082f, 0.822266f, 0.824219f, 0.823242f, 0.821777f, 0.820801f,
+ 0.000987f, 0.002644f, 0.004562f, 0.006344f, 0.008133f, 0.009918f, 0.011696f, 0.013527f, 0.015572f, 0.017746f, 0.019714f, 0.021942f,
+ 0.024155f, 0.027069f, 0.029678f, 0.032288f, 0.035156f, 0.038574f, 0.041779f, 0.045319f, 0.049225f, 0.053284f, 0.057678f, 0.062225f,
+ 0.067505f, 0.072571f, 0.078613f, 0.084961f, 0.092041f, 0.098938f, 0.106506f, 0.115112f, 0.123779f, 0.133667f, 0.143311f, 0.154541f,
+ 0.165894f, 0.178345f, 0.191406f, 0.205200f, 0.219238f, 0.234985f, 0.250977f, 0.267578f, 0.284912f, 0.302734f, 0.321289f, 0.340332f,
+ 0.360352f, 0.380615f, 0.401611f, 0.423340f, 0.445312f, 0.467529f, 0.490967f, 0.514160f, 0.537598f, 0.561035f, 0.800293f, 0.814453f,
+ 0.815918f, 0.815918f, 0.814941f, 0.813965f, 0.000932f, 0.002567f, 0.004009f, 0.005722f, 0.007538f, 0.008812f, 0.010864f, 0.012413f,
+ 0.014290f, 0.015991f, 0.018051f, 0.019836f, 0.022247f, 0.024506f, 0.026520f, 0.029175f, 0.031769f, 0.034332f, 0.037689f, 0.040466f,
+ 0.043945f, 0.047607f, 0.051605f, 0.055817f, 0.060486f, 0.065125f, 0.070557f, 0.076111f, 0.081909f, 0.088806f, 0.095886f, 0.103210f,
+ 0.111755f, 0.120422f, 0.130249f, 0.140137f, 0.150513f, 0.162109f, 0.174561f, 0.187256f, 0.200928f, 0.215698f, 0.231323f, 0.246582f,
+ 0.264160f, 0.281982f, 0.299561f, 0.319092f, 0.338623f, 0.358643f, 0.379883f, 0.400879f, 0.423096f, 0.445557f, 0.468750f, 0.492188f,
+ 0.516113f, 0.541504f, 0.791016f, 0.805664f, 0.808105f, 0.808594f, 0.807129f, 0.806641f, 0.000871f, 0.002337f, 0.003727f, 0.005474f,
+ 0.006641f, 0.008377f, 0.009567f, 0.011154f, 0.012848f, 0.014610f, 0.016235f, 0.017960f, 0.019958f, 0.021729f, 0.023926f, 0.026154f,
+ 0.028351f, 0.030975f, 0.033722f, 0.036407f, 0.039459f, 0.042694f, 0.046082f, 0.049896f, 0.053833f, 0.058167f, 0.062744f, 0.067932f,
+ 0.073608f, 0.079468f, 0.085632f, 0.092651f, 0.100098f, 0.108521f, 0.116699f, 0.126099f, 0.136108f, 0.146606f, 0.157959f, 0.170410f,
+ 0.183594f, 0.197510f, 0.212280f, 0.227295f, 0.243652f, 0.260986f, 0.278564f, 0.297607f, 0.316406f, 0.336426f, 0.357178f, 0.378662f,
+ 0.400146f, 0.422852f, 0.446045f, 0.470215f, 0.494873f, 0.520020f, 0.781250f, 0.796875f, 0.800293f, 0.800781f, 0.799805f, 0.799316f,
+ 0.000782f, 0.002131f, 0.003649f, 0.004715f, 0.006054f, 0.007458f, 0.008759f, 0.010269f, 0.011711f, 0.012970f, 0.014664f, 0.016327f,
+ 0.017914f, 0.019699f, 0.021423f, 0.023499f, 0.025391f, 0.027374f, 0.029999f, 0.032501f, 0.035156f, 0.037872f, 0.040710f, 0.044403f,
+ 0.047791f, 0.051880f, 0.055969f, 0.060364f, 0.065247f, 0.070496f, 0.076172f, 0.082825f, 0.089294f, 0.096497f, 0.104431f, 0.112854f,
+ 0.122375f, 0.132202f, 0.142700f, 0.153931f, 0.166260f, 0.179565f, 0.193481f, 0.208008f, 0.223877f, 0.240479f, 0.257568f, 0.275879f,
+ 0.294922f, 0.314453f, 0.334961f, 0.355957f, 0.377686f, 0.400391f, 0.423828f, 0.448730f, 0.472900f, 0.498535f, 0.771484f, 0.789062f,
+ 0.791504f, 0.792480f, 0.791016f, 0.791016f, 0.000742f, 0.001822f, 0.003183f, 0.004444f, 0.005600f, 0.006550f, 0.008087f, 0.009247f,
+ 0.010559f, 0.011650f, 0.013184f, 0.014565f, 0.016083f, 0.017548f, 0.019119f, 0.020737f, 0.022644f, 0.024597f, 0.026627f, 0.028809f,
+ 0.031281f, 0.033539f, 0.036469f, 0.039429f, 0.042480f, 0.045654f, 0.049561f, 0.053406f, 0.057739f, 0.062469f, 0.067749f, 0.073364f,
+ 0.079773f, 0.086121f, 0.093262f, 0.100647f, 0.109253f, 0.118042f, 0.128174f, 0.138550f, 0.150024f, 0.162231f, 0.175171f, 0.189087f,
+ 0.204468f, 0.220215f, 0.236938f, 0.254639f, 0.273438f, 0.292236f, 0.312012f, 0.333252f, 0.355957f, 0.377686f, 0.401367f, 0.425781f,
+ 0.451416f, 0.476318f, 0.761230f, 0.779785f, 0.782227f, 0.782715f, 0.782715f, 0.782715f, 0.000632f, 0.001970f, 0.003042f, 0.004025f,
+ 0.005173f, 0.006435f, 0.007343f, 0.008522f, 0.009369f, 0.010475f, 0.011726f, 0.012962f, 0.014145f, 0.015411f, 0.016922f, 0.018478f,
+ 0.020111f, 0.021835f, 0.023682f, 0.025253f, 0.027466f, 0.029678f, 0.032196f, 0.034607f, 0.037415f, 0.040497f, 0.043610f, 0.047089f,
+ 0.051178f, 0.055573f, 0.059845f, 0.064758f, 0.070068f, 0.076111f, 0.082275f, 0.089417f, 0.096863f, 0.105286f, 0.114441f, 0.123535f,
+ 0.134399f, 0.145508f, 0.157959f, 0.171387f, 0.185425f, 0.200806f, 0.216919f, 0.233521f, 0.251953f, 0.270508f, 0.290527f, 0.310791f,
+ 0.332275f, 0.355469f, 0.378418f, 0.403564f, 0.428223f, 0.455322f, 0.750977f, 0.770996f, 0.774414f, 0.774414f, 0.774902f, 0.773926f,
+ 0.000517f, 0.001554f, 0.002741f, 0.003695f, 0.004669f, 0.005417f, 0.006466f, 0.007545f, 0.008453f, 0.009499f, 0.010468f, 0.011490f,
+ 0.012718f, 0.013985f, 0.014977f, 0.016235f, 0.017868f, 0.019211f, 0.020630f, 0.022263f, 0.024078f, 0.026291f, 0.028275f, 0.030380f,
+ 0.032928f, 0.035675f, 0.038513f, 0.041656f, 0.044769f, 0.048523f, 0.052216f, 0.057007f, 0.061493f, 0.066711f, 0.072510f, 0.078735f,
+ 0.085327f, 0.093201f, 0.101135f, 0.109619f, 0.119690f, 0.130371f, 0.141602f, 0.154053f, 0.167480f, 0.181396f, 0.197021f, 0.213623f,
+ 0.230835f, 0.248901f, 0.268066f, 0.289062f, 0.310303f, 0.332520f, 0.355225f, 0.379639f, 0.405273f, 0.432373f, 0.740234f, 0.760742f,
+ 0.763672f, 0.765625f, 0.765625f, 0.765625f, 0.000588f, 0.001405f, 0.002306f, 0.003370f, 0.004375f, 0.005116f, 0.005817f, 0.006630f,
+ 0.007797f, 0.008507f, 0.009216f, 0.010254f, 0.011246f, 0.012154f, 0.013191f, 0.014366f, 0.015503f, 0.016785f, 0.018127f, 0.019562f,
+ 0.021072f, 0.022919f, 0.024643f, 0.026749f, 0.028564f, 0.031006f, 0.033203f, 0.036072f, 0.039032f, 0.042114f, 0.045654f, 0.049561f,
+ 0.053650f, 0.058380f, 0.063049f, 0.068848f, 0.075256f, 0.081543f, 0.088562f, 0.096924f, 0.105652f, 0.115173f, 0.125977f, 0.137207f,
+ 0.149902f, 0.163208f, 0.177979f, 0.193726f, 0.210205f, 0.228027f, 0.247070f, 0.266602f, 0.287842f, 0.309326f, 0.333008f, 0.356934f,
+ 0.382568f, 0.408691f, 0.729004f, 0.751953f, 0.755371f, 0.756348f, 0.757324f, 0.756348f, 0.000431f, 0.001562f, 0.002253f, 0.003088f,
+ 0.003944f, 0.004536f, 0.005066f, 0.006020f, 0.006840f, 0.007542f, 0.008347f, 0.008949f, 0.009827f, 0.010719f, 0.011696f, 0.012756f,
+ 0.013649f, 0.014679f, 0.015808f, 0.017288f, 0.018356f, 0.019913f, 0.021332f, 0.023148f, 0.024719f, 0.026840f, 0.029007f, 0.031250f,
+ 0.033661f, 0.036469f, 0.039490f, 0.042969f, 0.046326f, 0.050293f, 0.054901f, 0.059845f, 0.064941f, 0.071289f, 0.077454f, 0.084656f,
+ 0.092529f, 0.101562f, 0.111145f, 0.121460f, 0.132935f, 0.145386f, 0.159302f, 0.174438f, 0.190186f, 0.206909f, 0.225098f, 0.244751f,
+ 0.265381f, 0.287109f, 0.310059f, 0.333984f, 0.359131f, 0.386230f, 0.716797f, 0.740723f, 0.744629f, 0.746582f, 0.747070f, 0.747070f,
+ 0.000576f, 0.001266f, 0.002028f, 0.002766f, 0.003317f, 0.004051f, 0.004742f, 0.005459f, 0.006054f, 0.006641f, 0.007240f, 0.007919f,
+ 0.008644f, 0.009300f, 0.010170f, 0.010925f, 0.011795f, 0.012733f, 0.013855f, 0.014885f, 0.015900f, 0.017212f, 0.018326f, 0.019684f,
+ 0.021469f, 0.023178f, 0.024734f, 0.026794f, 0.028946f, 0.031204f, 0.033844f, 0.036682f, 0.039948f, 0.043335f, 0.047150f, 0.051422f,
+ 0.055969f, 0.061066f, 0.067139f, 0.073242f, 0.080444f, 0.088440f, 0.096985f, 0.106445f, 0.116943f, 0.128906f, 0.141479f, 0.154907f,
+ 0.170410f, 0.186523f, 0.204102f, 0.222900f, 0.243774f, 0.264160f, 0.286865f, 0.310791f, 0.336182f, 0.362793f, 0.705078f, 0.730469f,
+ 0.735352f, 0.736816f, 0.737793f, 0.736816f, 0.000307f, 0.001126f, 0.001758f, 0.002436f, 0.002911f, 0.003540f, 0.004047f, 0.004711f,
+ 0.005245f, 0.005749f, 0.006302f, 0.006844f, 0.007355f, 0.008095f, 0.008835f, 0.009438f, 0.010139f, 0.010941f, 0.011963f, 0.012878f,
+ 0.013519f, 0.014847f, 0.015945f, 0.017029f, 0.018250f, 0.019669f, 0.021362f, 0.022675f, 0.024750f, 0.026657f, 0.028854f, 0.031219f,
+ 0.033844f, 0.036804f, 0.040222f, 0.043793f, 0.047791f, 0.052185f, 0.057251f, 0.062866f, 0.069275f, 0.075867f, 0.083923f, 0.092407f,
+ 0.102295f, 0.112366f, 0.124207f, 0.137085f, 0.151489f, 0.167114f, 0.183838f, 0.202148f, 0.221558f, 0.242065f, 0.263916f, 0.287842f,
+ 0.312256f, 0.339111f, 0.693848f, 0.719727f, 0.724609f, 0.726074f, 0.727539f, 0.727051f, 0.000428f, 0.000939f, 0.001581f, 0.002033f,
+ 0.002665f, 0.003222f, 0.003660f, 0.004059f, 0.004475f, 0.004997f, 0.005554f, 0.006031f, 0.006371f, 0.007080f, 0.007511f, 0.008263f,
+ 0.008820f, 0.009552f, 0.010124f, 0.010948f, 0.011665f, 0.012550f, 0.013397f, 0.014526f, 0.015388f, 0.016754f, 0.017960f, 0.019257f,
+ 0.020844f, 0.022583f, 0.024246f, 0.026642f, 0.028656f, 0.031128f, 0.033783f, 0.036865f, 0.040253f, 0.044312f, 0.048523f, 0.053314f,
+ 0.058655f, 0.064880f, 0.071594f, 0.079102f, 0.087891f, 0.097107f, 0.108276f, 0.119751f, 0.133179f, 0.148071f, 0.163818f, 0.180908f,
+ 0.199951f, 0.219849f, 0.241699f, 0.264160f, 0.288818f, 0.315918f, 0.680176f, 0.708496f, 0.713867f, 0.716309f, 0.716797f, 0.717285f,
+ 0.000467f, 0.001054f, 0.001476f, 0.001825f, 0.002386f, 0.002644f, 0.003218f, 0.003553f, 0.003866f, 0.004433f, 0.004700f, 0.004948f,
+ 0.005505f, 0.006023f, 0.006405f, 0.006920f, 0.007484f, 0.008057f, 0.008598f, 0.009178f, 0.009857f, 0.010551f, 0.011169f, 0.012199f,
+ 0.013092f, 0.014084f, 0.015091f, 0.016205f, 0.017303f, 0.018845f, 0.020538f, 0.021957f, 0.023773f, 0.025833f, 0.028152f, 0.030716f,
+ 0.033661f, 0.036896f, 0.040405f, 0.044708f, 0.049286f, 0.054321f, 0.060333f, 0.067322f, 0.074890f, 0.083435f, 0.092651f, 0.103516f,
+ 0.115784f, 0.129028f, 0.144287f, 0.160278f, 0.178345f, 0.197632f, 0.218994f, 0.241089f, 0.265869f, 0.292725f, 0.667969f, 0.697266f,
+ 0.702637f, 0.704590f, 0.706055f, 0.707031f, 0.000348f, 0.000841f, 0.001292f, 0.001580f, 0.001961f, 0.002508f, 0.002630f, 0.002993f,
+ 0.003458f, 0.003738f, 0.003952f, 0.004425f, 0.004639f, 0.005070f, 0.005547f, 0.005840f, 0.006462f, 0.006844f, 0.007214f, 0.007698f,
+ 0.008339f, 0.008980f, 0.009560f, 0.010094f, 0.010941f, 0.011711f, 0.012550f, 0.013565f, 0.014404f, 0.015579f, 0.016754f, 0.018082f,
+ 0.019592f, 0.021439f, 0.023209f, 0.025375f, 0.027863f, 0.030411f, 0.033478f, 0.037018f, 0.040680f, 0.045105f, 0.050476f, 0.056183f,
+ 0.062805f, 0.070251f, 0.078613f, 0.088196f, 0.099060f, 0.111450f, 0.125122f, 0.140869f, 0.158203f, 0.176880f, 0.197266f, 0.218506f,
+ 0.242798f, 0.268555f, 0.655273f, 0.686035f, 0.691406f, 0.694336f, 0.695312f, 0.695801f, 0.000170f, 0.000976f, 0.001161f, 0.001441f,
+ 0.001846f, 0.002144f, 0.002367f, 0.002632f, 0.002892f, 0.003178f, 0.003435f, 0.003618f, 0.004021f, 0.004292f, 0.004562f, 0.005028f,
+ 0.005405f, 0.005623f, 0.006069f, 0.006577f, 0.006973f, 0.007431f, 0.007904f, 0.008484f, 0.009018f, 0.009659f, 0.010559f, 0.010994f,
+ 0.012009f, 0.012840f, 0.013901f, 0.014915f, 0.016129f, 0.017502f, 0.019089f, 0.020676f, 0.022568f, 0.024673f, 0.027252f, 0.029984f,
+ 0.033234f, 0.037079f, 0.041016f, 0.045868f, 0.051758f, 0.058014f, 0.065613f, 0.073853f, 0.083801f, 0.094727f, 0.107483f, 0.121826f,
+ 0.137573f, 0.156006f, 0.175049f, 0.196167f, 0.219482f, 0.245850f, 0.641113f, 0.673340f, 0.679688f, 0.681641f, 0.683594f, 0.684082f,
+ 0.000293f, 0.000601f, 0.001049f, 0.001358f, 0.001532f, 0.001719f, 0.001882f, 0.002298f, 0.002317f, 0.002628f, 0.002750f, 0.003143f,
+ 0.003363f, 0.003559f, 0.003866f, 0.004204f, 0.004383f, 0.004753f, 0.005028f, 0.005348f, 0.005863f, 0.006176f, 0.006569f, 0.006954f,
+ 0.007401f, 0.008057f, 0.008537f, 0.009178f, 0.009735f, 0.010521f, 0.011208f, 0.011978f, 0.013130f, 0.014099f, 0.015289f, 0.016739f,
+ 0.018219f, 0.019821f, 0.021713f, 0.024200f, 0.026749f, 0.029785f, 0.033386f, 0.036987f, 0.041840f, 0.047089f, 0.053253f, 0.060760f,
+ 0.069214f, 0.079224f, 0.090515f, 0.103638f, 0.118652f, 0.135376f, 0.154175f, 0.174561f, 0.196777f, 0.222534f, 0.628906f, 0.660645f,
+ 0.668457f, 0.670410f, 0.672852f, 0.673340f, 0.000258f, 0.000656f, 0.000811f, 0.001049f, 0.001288f, 0.001462f, 0.001599f, 0.001740f,
+ 0.002012f, 0.002171f, 0.002367f, 0.002535f, 0.002705f, 0.002880f, 0.003115f, 0.003429f, 0.003666f, 0.003897f, 0.004116f, 0.004398f,
+ 0.004635f, 0.005066f, 0.005341f, 0.005779f, 0.006042f, 0.006454f, 0.006954f, 0.007450f, 0.007835f, 0.008400f, 0.009132f, 0.009819f,
+ 0.010536f, 0.011307f, 0.012245f, 0.013229f, 0.014580f, 0.015900f, 0.017303f, 0.019119f, 0.021103f, 0.023468f, 0.026123f, 0.029495f,
+ 0.033112f, 0.037628f, 0.042938f, 0.048859f, 0.056152f, 0.064941f, 0.074829f, 0.086548f, 0.100281f, 0.115967f, 0.133545f, 0.153198f,
+ 0.175171f, 0.199341f, 0.613770f, 0.648926f, 0.655273f, 0.658691f, 0.660645f, 0.662598f, 0.000176f, 0.000474f, 0.000602f, 0.000854f,
+ 0.001030f, 0.001240f, 0.001349f, 0.001505f, 0.001580f, 0.001738f, 0.001957f, 0.002068f, 0.002230f, 0.002420f, 0.002556f, 0.002705f,
+ 0.002998f, 0.003178f, 0.003345f, 0.003567f, 0.003811f, 0.004105f, 0.004284f, 0.004593f, 0.004848f, 0.005173f, 0.005527f, 0.005939f,
+ 0.006306f, 0.006817f, 0.007366f, 0.007729f, 0.008339f, 0.008995f, 0.009644f, 0.010551f, 0.011360f, 0.012344f, 0.013710f, 0.015030f,
+ 0.016510f, 0.018143f, 0.020279f, 0.022751f, 0.025650f, 0.029144f, 0.033508f, 0.038452f, 0.044556f, 0.052032f, 0.060364f, 0.070923f,
+ 0.082642f, 0.097290f, 0.113525f, 0.132446f, 0.153442f, 0.176880f, 0.600586f, 0.636719f, 0.644531f, 0.647461f, 0.648926f, 0.649414f,
+ 0.000121f, 0.000426f, 0.000509f, 0.000778f, 0.000931f, 0.000992f, 0.001135f, 0.001303f, 0.001359f, 0.001410f, 0.001519f, 0.001722f,
+ 0.001751f, 0.001951f, 0.002060f, 0.002218f, 0.002287f, 0.002487f, 0.002670f, 0.002848f, 0.003061f, 0.003233f, 0.003452f, 0.003664f,
+ 0.003883f, 0.004078f, 0.004379f, 0.004692f, 0.004982f, 0.005329f, 0.005756f, 0.006081f, 0.006504f, 0.007019f, 0.007599f, 0.008217f,
+ 0.008850f, 0.009628f, 0.010437f, 0.011597f, 0.012650f, 0.013931f, 0.015480f, 0.017380f, 0.019577f, 0.022247f, 0.025513f, 0.029617f,
+ 0.034363f, 0.040314f, 0.047241f, 0.056274f, 0.066711f, 0.079773f, 0.094482f, 0.112488f, 0.132446f, 0.154907f, 0.585449f, 0.624023f,
+ 0.630371f, 0.634277f, 0.636230f, 0.637207f, 0.000161f, 0.000263f, 0.000526f, 0.000627f, 0.000723f, 0.000775f, 0.000856f, 0.000960f,
+ 0.001079f, 0.001158f, 0.001208f, 0.001272f, 0.001441f, 0.001557f, 0.001657f, 0.001702f, 0.001897f, 0.001918f, 0.002151f, 0.002232f,
+ 0.002337f, 0.002522f, 0.002720f, 0.002865f, 0.003029f, 0.003193f, 0.003387f, 0.003601f, 0.003887f, 0.004124f, 0.004356f, 0.004639f,
+ 0.005070f, 0.005466f, 0.005863f, 0.006298f, 0.006874f, 0.007290f, 0.007965f, 0.008774f, 0.009560f, 0.010666f, 0.011719f, 0.013077f,
+ 0.014679f, 0.016693f, 0.019058f, 0.021881f, 0.025528f, 0.030121f, 0.036011f, 0.043396f, 0.052460f, 0.063477f, 0.076721f, 0.093079f,
+ 0.112305f, 0.133667f, 0.572266f, 0.609375f, 0.618164f, 0.622070f, 0.623535f, 0.625488f, 0.000109f, 0.000212f, 0.000404f, 0.000578f,
+ 0.000567f, 0.000655f, 0.000763f, 0.000676f, 0.000824f, 0.000869f, 0.000971f, 0.001064f, 0.001132f, 0.001210f, 0.001212f, 0.001398f,
+ 0.001486f, 0.001525f, 0.001653f, 0.001676f, 0.001867f, 0.001953f, 0.002062f, 0.002199f, 0.002295f, 0.002443f, 0.002586f, 0.002766f,
+ 0.002979f, 0.003128f, 0.003429f, 0.003551f, 0.003763f, 0.004074f, 0.004349f, 0.004688f, 0.005032f, 0.005470f, 0.005894f, 0.006519f,
+ 0.007092f, 0.007896f, 0.008629f, 0.009659f, 0.010910f, 0.012215f, 0.013962f, 0.015991f, 0.018646f, 0.021881f, 0.026428f, 0.032074f,
+ 0.039276f, 0.048645f, 0.060455f, 0.075256f, 0.092773f, 0.113220f, 0.554688f, 0.596191f, 0.605957f, 0.608887f, 0.610352f, 0.612305f,
+ 0.000202f, 0.000186f, 0.000312f, 0.000433f, 0.000382f, 0.000543f, 0.000482f, 0.000546f, 0.000621f, 0.000666f, 0.000789f, 0.000802f,
+ 0.000859f, 0.000950f, 0.000970f, 0.000975f, 0.001113f, 0.001162f, 0.001207f, 0.001312f, 0.001362f, 0.001433f, 0.001541f, 0.001618f,
+ 0.001720f, 0.001791f, 0.001966f, 0.002035f, 0.002199f, 0.002413f, 0.002546f, 0.002626f, 0.002855f, 0.003063f, 0.003204f, 0.003448f,
+ 0.003693f, 0.003986f, 0.004364f, 0.004684f, 0.005127f, 0.005619f, 0.006271f, 0.006870f, 0.007748f, 0.008713f, 0.009911f, 0.011368f,
+ 0.013191f, 0.015518f, 0.018646f, 0.022644f, 0.028107f, 0.035645f, 0.045471f, 0.058502f, 0.074646f, 0.093994f, 0.541016f, 0.583008f,
+ 0.591797f, 0.596191f, 0.599121f, 0.600098f, 0.000000f, 0.000179f, 0.000242f, 0.000318f, 0.000341f, 0.000345f, 0.000432f, 0.000364f,
+ 0.000475f, 0.000483f, 0.000572f, 0.000576f, 0.000619f, 0.000640f, 0.000716f, 0.000737f, 0.000791f, 0.000845f, 0.000871f, 0.000907f,
+ 0.000998f, 0.001025f, 0.001107f, 0.001181f, 0.001244f, 0.001303f, 0.001391f, 0.001462f, 0.001549f, 0.001631f, 0.001756f, 0.001906f,
+ 0.001984f, 0.002161f, 0.002264f, 0.002419f, 0.002613f, 0.002825f, 0.003103f, 0.003321f, 0.003584f, 0.003893f, 0.004349f, 0.004799f,
+ 0.005383f, 0.006020f, 0.006836f, 0.007858f, 0.009117f, 0.010674f, 0.012825f, 0.015533f, 0.019363f, 0.024780f, 0.032593f, 0.043274f,
+ 0.057770f, 0.076111f, 0.525879f, 0.569336f, 0.578613f, 0.583008f, 0.585449f, 0.586426f, 0.000000f, 0.000088f, 0.000192f, 0.000227f,
+ 0.000230f, 0.000286f, 0.000255f, 0.000317f, 0.000321f, 0.000371f, 0.000401f, 0.000373f, 0.000391f, 0.000457f, 0.000474f, 0.000530f,
+ 0.000509f, 0.000585f, 0.000625f, 0.000664f, 0.000707f, 0.000746f, 0.000772f, 0.000817f, 0.000877f, 0.000887f, 0.000978f, 0.001007f,
+ 0.001069f, 0.001202f, 0.001192f, 0.001290f, 0.001356f, 0.001464f, 0.001583f, 0.001678f, 0.001771f, 0.001929f, 0.002050f, 0.002230f,
+ 0.002424f, 0.002651f, 0.002888f, 0.003176f, 0.003534f, 0.003967f, 0.004475f, 0.005154f, 0.005993f, 0.007118f, 0.008469f, 0.010338f,
+ 0.012794f, 0.016403f, 0.021957f, 0.030090f, 0.042419f, 0.059052f, 0.510254f, 0.554199f, 0.564453f, 0.570312f, 0.572754f, 0.573242f,
+ 0.000000f, 0.000126f, 0.000180f, 0.000121f, 0.000178f, 0.000176f, 0.000177f, 0.000212f, 0.000210f, 0.000228f, 0.000238f, 0.000291f,
+ 0.000280f, 0.000298f, 0.000336f, 0.000350f, 0.000369f, 0.000387f, 0.000395f, 0.000427f, 0.000460f, 0.000476f, 0.000515f, 0.000536f,
+ 0.000573f, 0.000619f, 0.000650f, 0.000670f, 0.000703f, 0.000746f, 0.000798f, 0.000836f, 0.000902f, 0.000949f, 0.001031f, 0.001062f,
+ 0.001162f, 0.001227f, 0.001349f, 0.001442f, 0.001533f, 0.001690f, 0.001865f, 0.001995f, 0.002228f, 0.002495f, 0.002800f, 0.003191f,
+ 0.003653f, 0.004349f, 0.005203f, 0.006393f, 0.008026f, 0.010307f, 0.013710f, 0.019379f, 0.028854f, 0.043457f, 0.494873f, 0.541016f,
+ 0.550781f, 0.555664f, 0.558105f, 0.559570f, 0.000000f, 0.000095f, 0.000086f, 0.000079f, 0.000105f, 0.000124f, 0.000111f, 0.000137f,
+ 0.000141f, 0.000142f, 0.000147f, 0.000151f, 0.000160f, 0.000181f, 0.000202f, 0.000207f, 0.000214f, 0.000248f, 0.000244f, 0.000282f,
+ 0.000273f, 0.000283f, 0.000306f, 0.000334f, 0.000367f, 0.000378f, 0.000376f, 0.000399f, 0.000437f, 0.000459f, 0.000474f, 0.000516f,
+ 0.000552f, 0.000567f, 0.000616f, 0.000649f, 0.000693f, 0.000743f, 0.000805f, 0.000851f, 0.000918f, 0.000999f, 0.001085f, 0.001195f,
+ 0.001309f, 0.001466f, 0.001644f, 0.001850f, 0.002151f, 0.002487f, 0.002974f, 0.003654f, 0.004574f, 0.006001f, 0.008156f, 0.011452f,
+ 0.017853f, 0.029739f, 0.478271f, 0.526367f, 0.537109f, 0.541504f, 0.544434f, 0.545898f, 0.000106f, 0.000085f, 0.000074f, 0.000067f,
+ 0.000066f, 0.000070f, 0.000069f, 0.000073f, 0.000073f, 0.000080f, 0.000084f, 0.000109f, 0.000093f, 0.000098f, 0.000119f, 0.000108f,
+ 0.000128f, 0.000135f, 0.000137f, 0.000149f, 0.000150f, 0.000157f, 0.000182f, 0.000185f, 0.000207f, 0.000206f, 0.000214f, 0.000234f,
+ 0.000237f, 0.000253f, 0.000267f, 0.000289f, 0.000306f, 0.000313f, 0.000344f, 0.000352f, 0.000384f, 0.000406f, 0.000445f, 0.000467f,
+ 0.000503f, 0.000543f, 0.000593f, 0.000634f, 0.000697f, 0.000764f, 0.000850f, 0.000963f, 0.001105f, 0.001298f, 0.001536f, 0.001856f,
+ 0.002333f, 0.003069f, 0.004299f, 0.006271f, 0.009789f, 0.018234f, 0.462402f, 0.511719f, 0.522949f, 0.527344f, 0.530762f, 0.532715f,
+ 0.000091f, 0.000069f, 0.000060f, 0.000054f, 0.000049f, 0.000046f, 0.000043f, 0.000041f, 0.000040f, 0.000044f, 0.000040f, 0.000040f,
+ 0.000054f, 0.000044f, 0.000045f, 0.000044f, 0.000062f, 0.000062f, 0.000069f, 0.000071f, 0.000074f, 0.000079f, 0.000081f, 0.000081f,
+ 0.000085f, 0.000099f, 0.000098f, 0.000115f, 0.000115f, 0.000119f, 0.000125f, 0.000130f, 0.000140f, 0.000144f, 0.000165f, 0.000172f,
+ 0.000178f, 0.000191f, 0.000205f, 0.000222f, 0.000234f, 0.000251f, 0.000276f, 0.000293f, 0.000327f, 0.000354f, 0.000392f, 0.000437f,
+ 0.000494f, 0.000562f, 0.000662f, 0.000800f, 0.001005f, 0.001315f, 0.001852f, 0.002825f, 0.004723f, 0.009285f, 0.446533f, 0.497803f,
+ 0.508301f, 0.514160f, 0.516602f, 0.519043f, 0.000067f, 0.000048f, 0.000040f, 0.000036f, 0.000033f, 0.000031f, 0.000030f, 0.000028f,
+ 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, 0.000020f, 0.000019f, 0.000020f, 0.000024f, 0.000026f,
+ 0.000025f, 0.000027f, 0.000031f, 0.000032f, 0.000032f, 0.000037f, 0.000041f, 0.000038f, 0.000045f, 0.000042f, 0.000048f, 0.000049f,
+ 0.000053f, 0.000055f, 0.000059f, 0.000062f, 0.000071f, 0.000074f, 0.000077f, 0.000081f, 0.000086f, 0.000091f, 0.000098f, 0.000109f,
+ 0.000116f, 0.000125f, 0.000137f, 0.000158f, 0.000173f, 0.000193f, 0.000230f, 0.000273f, 0.000335f, 0.000425f, 0.000603f, 0.000935f,
+ 0.001694f, 0.003727f, 0.431396f, 0.481934f, 0.493652f, 0.499512f, 0.502930f, 0.504883f, 0.000021f, 0.000016f, 0.000013f, 0.000012f,
+ 0.000013f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f,
+ 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000007f,
+ 0.000008f, 0.000009f, 0.000009f, 0.000010f, 0.000010f, 0.000013f, 0.000014f, 0.000013f, 0.000015f, 0.000016f, 0.000017f, 0.000019f,
+ 0.000019f, 0.000020f, 0.000023f, 0.000026f, 0.000027f, 0.000027f, 0.000032f, 0.000030f, 0.000036f, 0.000039f, 0.000050f, 0.000056f,
+ 0.000063f, 0.000082f, 0.000109f, 0.000168f, 0.000317f, 0.000922f, 0.415283f, 0.467773f, 0.479980f, 0.486328f, 0.489014f, 0.490723f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000005f, 0.000008f, 0.000026f, 0.398926f, 0.452881f,
+ 0.465576f, 0.471436f, 0.474854f, 0.477051f,
+ },
+ {
+ 0.019653f, 0.058990f, 0.097473f, 0.134277f, 0.169189f, 0.203491f, 0.236450f, 0.267578f, 0.297852f, 0.326416f, 0.354004f, 0.380859f,
+ 0.406250f, 0.431641f, 0.455078f, 0.477539f, 0.500000f, 0.520996f, 0.541504f, 0.560547f, 0.580566f, 0.598633f, 0.615723f, 0.633301f,
+ 0.649902f, 0.666016f, 0.681641f, 0.695801f, 0.709961f, 0.724609f, 0.738770f, 0.751953f, 0.765137f, 0.775879f, 0.788574f, 0.799805f,
+ 0.812012f, 0.822754f, 0.833496f, 0.844238f, 0.854004f, 0.864258f, 0.874023f, 0.883301f, 0.891602f, 0.900391f, 0.909668f, 0.917969f,
+ 0.925781f, 0.934570f, 0.941895f, 0.949707f, 0.956543f, 0.963379f, 0.970703f, 0.977539f, 0.984863f, 0.991211f, 0.988770f, 0.972656f,
+ 0.960449f, 0.949707f, 0.940430f, 0.931641f, 0.017303f, 0.052399f, 0.086548f, 0.119446f, 0.153076f, 0.183594f, 0.214722f, 0.245117f,
+ 0.273193f, 0.301270f, 0.328613f, 0.354492f, 0.379883f, 0.404541f, 0.427979f, 0.450195f, 0.472656f, 0.494629f, 0.515137f, 0.534668f,
+ 0.554199f, 0.573242f, 0.591309f, 0.608887f, 0.625977f, 0.642578f, 0.658203f, 0.672852f, 0.688477f, 0.704102f, 0.717285f, 0.731445f,
+ 0.744629f, 0.756836f, 0.769531f, 0.782715f, 0.793945f, 0.805664f, 0.816406f, 0.828125f, 0.838379f, 0.849121f, 0.858887f, 0.868652f,
+ 0.877930f, 0.888184f, 0.896973f, 0.905762f, 0.915039f, 0.921875f, 0.930176f, 0.937988f, 0.946777f, 0.954102f, 0.960938f, 0.968750f,
+ 0.975586f, 0.982422f, 0.984375f, 0.969238f, 0.957520f, 0.947754f, 0.938477f, 0.930176f, 0.015221f, 0.045837f, 0.076843f, 0.107666f,
+ 0.136719f, 0.166504f, 0.196045f, 0.223999f, 0.250244f, 0.278320f, 0.303711f, 0.329346f, 0.353271f, 0.378906f, 0.401367f, 0.424316f,
+ 0.447266f, 0.468018f, 0.487793f, 0.508301f, 0.529297f, 0.547363f, 0.566406f, 0.583984f, 0.601562f, 0.618652f, 0.634766f, 0.650879f,
+ 0.666016f, 0.681641f, 0.695801f, 0.710449f, 0.724121f, 0.737305f, 0.750488f, 0.762695f, 0.775391f, 0.788086f, 0.799316f, 0.811035f,
+ 0.821777f, 0.833008f, 0.844238f, 0.854004f, 0.864258f, 0.874023f, 0.882812f, 0.892578f, 0.901367f, 0.910156f, 0.918457f, 0.926758f,
+ 0.936035f, 0.942871f, 0.950684f, 0.958496f, 0.965820f, 0.973145f, 0.980469f, 0.965820f, 0.955078f, 0.945312f, 0.936523f, 0.928223f,
+ 0.013420f, 0.041138f, 0.068359f, 0.096436f, 0.124023f, 0.150879f, 0.177246f, 0.204224f, 0.230103f, 0.255859f, 0.281494f, 0.305420f,
+ 0.329834f, 0.352783f, 0.376709f, 0.398682f, 0.420654f, 0.442627f, 0.462646f, 0.483887f, 0.502441f, 0.521484f, 0.540527f, 0.559082f,
+ 0.576172f, 0.595703f, 0.611328f, 0.627930f, 0.644043f, 0.659668f, 0.674316f, 0.688965f, 0.703613f, 0.717285f, 0.730957f, 0.744629f,
+ 0.756836f, 0.770020f, 0.781738f, 0.793945f, 0.805176f, 0.816895f, 0.828125f, 0.838379f, 0.849121f, 0.859375f, 0.869141f, 0.878418f,
+ 0.888184f, 0.897461f, 0.906738f, 0.915039f, 0.923828f, 0.932129f, 0.940430f, 0.947754f, 0.956543f, 0.963867f, 0.976074f, 0.962402f,
+ 0.951660f, 0.942383f, 0.934082f, 0.926758f, 0.012001f, 0.036591f, 0.061737f, 0.086670f, 0.112000f, 0.136719f, 0.161743f, 0.186768f,
+ 0.211792f, 0.235840f, 0.259521f, 0.283203f, 0.307129f, 0.329590f, 0.352295f, 0.374268f, 0.395996f, 0.416992f, 0.437744f, 0.457520f,
+ 0.477295f, 0.497314f, 0.515625f, 0.534180f, 0.553223f, 0.570312f, 0.588379f, 0.604492f, 0.621582f, 0.636719f, 0.653320f, 0.666992f,
+ 0.683105f, 0.697266f, 0.710449f, 0.724609f, 0.737793f, 0.750977f, 0.764160f, 0.775879f, 0.788086f, 0.799805f, 0.812012f, 0.823242f,
+ 0.833496f, 0.844238f, 0.854492f, 0.864746f, 0.875000f, 0.884277f, 0.894043f, 0.902832f, 0.911621f, 0.920898f, 0.929688f, 0.937500f,
+ 0.945801f, 0.953613f, 0.971191f, 0.958984f, 0.949219f, 0.939941f, 0.932129f, 0.924316f, 0.010612f, 0.032684f, 0.054810f, 0.077759f,
+ 0.100952f, 0.124023f, 0.146851f, 0.171021f, 0.193604f, 0.217163f, 0.239380f, 0.261963f, 0.284424f, 0.307129f, 0.328613f, 0.351318f,
+ 0.371826f, 0.392334f, 0.413574f, 0.432617f, 0.453613f, 0.472656f, 0.491943f, 0.510254f, 0.528320f, 0.546387f, 0.563965f, 0.580078f,
+ 0.598633f, 0.613770f, 0.629883f, 0.645996f, 0.661621f, 0.675293f, 0.688965f, 0.705078f, 0.718262f, 0.731934f, 0.745605f, 0.757812f,
+ 0.770996f, 0.782715f, 0.795410f, 0.807129f, 0.818359f, 0.829102f, 0.839844f, 0.851074f, 0.860840f, 0.871094f, 0.880859f, 0.891113f,
+ 0.900391f, 0.909668f, 0.917969f, 0.927246f, 0.935547f, 0.943848f, 0.966797f, 0.955566f, 0.945801f, 0.937012f, 0.929199f, 0.921875f,
+ 0.009483f, 0.029556f, 0.050140f, 0.070129f, 0.091797f, 0.112549f, 0.134155f, 0.156372f, 0.177368f, 0.198975f, 0.220825f, 0.243286f,
+ 0.263916f, 0.285645f, 0.306885f, 0.327393f, 0.348145f, 0.368896f, 0.389404f, 0.409424f, 0.429199f, 0.448730f, 0.467529f, 0.486572f,
+ 0.505371f, 0.522461f, 0.540039f, 0.558105f, 0.574219f, 0.591309f, 0.607422f, 0.623535f, 0.639648f, 0.654785f, 0.669922f, 0.685547f,
+ 0.698730f, 0.712891f, 0.726074f, 0.740234f, 0.752441f, 0.765625f, 0.778320f, 0.789551f, 0.802246f, 0.813477f, 0.825195f, 0.836426f,
+ 0.847168f, 0.856934f, 0.868164f, 0.877930f, 0.888184f, 0.897461f, 0.906738f, 0.915527f, 0.925293f, 0.935059f, 0.962402f, 0.951660f,
+ 0.942383f, 0.933594f, 0.926270f, 0.919434f, 0.008934f, 0.026581f, 0.044708f, 0.063354f, 0.082825f, 0.102844f, 0.122437f, 0.141968f,
+ 0.162720f, 0.183105f, 0.202515f, 0.224609f, 0.244995f, 0.265381f, 0.285645f, 0.306152f, 0.326416f, 0.346680f, 0.365967f, 0.385498f,
+ 0.406006f, 0.425293f, 0.444092f, 0.461914f, 0.480225f, 0.499268f, 0.517090f, 0.535156f, 0.552246f, 0.568359f, 0.585449f, 0.601562f,
+ 0.616699f, 0.633789f, 0.649414f, 0.663574f, 0.678711f, 0.693848f, 0.706543f, 0.721680f, 0.734375f, 0.746582f, 0.760742f, 0.773438f,
+ 0.786133f, 0.797852f, 0.809082f, 0.821777f, 0.832031f, 0.843262f, 0.854492f, 0.864746f, 0.875000f, 0.884766f, 0.895020f, 0.904785f,
+ 0.914062f, 0.922852f, 0.957520f, 0.947266f, 0.938965f, 0.930664f, 0.923340f, 0.916992f, 0.007668f, 0.024017f, 0.040405f, 0.057831f,
+ 0.075195f, 0.093079f, 0.111694f, 0.130127f, 0.148926f, 0.168213f, 0.187500f, 0.206543f, 0.226440f, 0.246460f, 0.265869f, 0.285400f,
+ 0.305176f, 0.324707f, 0.344238f, 0.363281f, 0.383057f, 0.401123f, 0.420166f, 0.439941f, 0.457764f, 0.475586f, 0.493164f, 0.511719f,
+ 0.528809f, 0.545898f, 0.562988f, 0.579590f, 0.596191f, 0.612305f, 0.627441f, 0.643555f, 0.658203f, 0.672363f, 0.687988f, 0.702637f,
+ 0.715332f, 0.728516f, 0.742676f, 0.756348f, 0.768555f, 0.781250f, 0.794434f, 0.806152f, 0.818359f, 0.828613f, 0.840332f, 0.851074f,
+ 0.861816f, 0.872559f, 0.882812f, 0.892578f, 0.903320f, 0.912598f, 0.952637f, 0.943848f, 0.935059f, 0.927246f, 0.920410f, 0.914062f,
+ 0.007263f, 0.021530f, 0.037048f, 0.052429f, 0.068909f, 0.084961f, 0.102112f, 0.119568f, 0.136475f, 0.154541f, 0.172852f, 0.191528f,
+ 0.209717f, 0.228638f, 0.246948f, 0.265869f, 0.284912f, 0.304199f, 0.322510f, 0.341309f, 0.360596f, 0.379639f, 0.397461f, 0.416504f,
+ 0.434570f, 0.452881f, 0.470947f, 0.489014f, 0.505859f, 0.523438f, 0.541016f, 0.557129f, 0.574219f, 0.590332f, 0.606445f, 0.622070f,
+ 0.637695f, 0.653809f, 0.667969f, 0.682129f, 0.697754f, 0.711426f, 0.724609f, 0.737793f, 0.750977f, 0.765625f, 0.777832f, 0.790039f,
+ 0.801270f, 0.813477f, 0.825684f, 0.837402f, 0.848145f, 0.859375f, 0.870117f, 0.880859f, 0.891602f, 0.900391f, 0.947754f, 0.938965f,
+ 0.931152f, 0.923828f, 0.917480f, 0.911133f, 0.006401f, 0.019730f, 0.033813f, 0.047729f, 0.062561f, 0.077515f, 0.093140f, 0.108948f,
+ 0.125366f, 0.141968f, 0.159058f, 0.175781f, 0.193726f, 0.212036f, 0.229980f, 0.247681f, 0.265869f, 0.284424f, 0.302734f, 0.320557f,
+ 0.339111f, 0.357910f, 0.376221f, 0.394287f, 0.412109f, 0.429688f, 0.448486f, 0.466064f, 0.483398f, 0.500977f, 0.517090f, 0.535156f,
+ 0.552246f, 0.568359f, 0.583984f, 0.600586f, 0.616699f, 0.632324f, 0.647949f, 0.662598f, 0.677246f, 0.692383f, 0.706543f, 0.719727f,
+ 0.734375f, 0.747070f, 0.761230f, 0.773926f, 0.786621f, 0.797852f, 0.811523f, 0.823242f, 0.834961f, 0.846680f, 0.857422f, 0.868652f,
+ 0.879395f, 0.890137f, 0.942383f, 0.934082f, 0.927246f, 0.919922f, 0.913574f, 0.908203f, 0.005836f, 0.018158f, 0.030746f, 0.043335f,
+ 0.057007f, 0.070801f, 0.085754f, 0.099548f, 0.115112f, 0.130127f, 0.146362f, 0.162354f, 0.178711f, 0.195801f, 0.212769f, 0.230103f,
+ 0.247925f, 0.264893f, 0.283203f, 0.300293f, 0.318604f, 0.336426f, 0.354492f, 0.372314f, 0.390137f, 0.408203f, 0.425537f, 0.443848f,
+ 0.461182f, 0.478271f, 0.496094f, 0.513184f, 0.529297f, 0.546387f, 0.563477f, 0.580566f, 0.595703f, 0.611816f, 0.626465f, 0.642090f,
+ 0.658691f, 0.671875f, 0.686523f, 0.702148f, 0.716797f, 0.729980f, 0.744629f, 0.757324f, 0.770020f, 0.783203f, 0.796875f, 0.808105f,
+ 0.820312f, 0.832520f, 0.844727f, 0.855957f, 0.867188f, 0.877930f, 0.937012f, 0.930176f, 0.922852f, 0.916504f, 0.910645f, 0.904785f,
+ 0.005486f, 0.016525f, 0.028030f, 0.039612f, 0.052185f, 0.064636f, 0.077576f, 0.091553f, 0.105347f, 0.119568f, 0.134521f, 0.149536f,
+ 0.164917f, 0.180664f, 0.197388f, 0.213623f, 0.230347f, 0.246826f, 0.264160f, 0.280518f, 0.298584f, 0.315674f, 0.334229f, 0.350830f,
+ 0.369141f, 0.386963f, 0.404053f, 0.422119f, 0.438477f, 0.456299f, 0.474121f, 0.491211f, 0.507812f, 0.524902f, 0.541504f, 0.557617f,
+ 0.574707f, 0.590820f, 0.606934f, 0.622559f, 0.637207f, 0.652832f, 0.668945f, 0.683105f, 0.698730f, 0.711914f, 0.726074f, 0.740723f,
+ 0.753906f, 0.766602f, 0.780273f, 0.792969f, 0.805664f, 0.818848f, 0.830566f, 0.842285f, 0.854492f, 0.866211f, 0.931641f, 0.925781f,
+ 0.918945f, 0.913086f, 0.907227f, 0.900879f, 0.004810f, 0.014847f, 0.025604f, 0.036621f, 0.047577f, 0.059174f, 0.071472f, 0.084106f,
+ 0.096985f, 0.109863f, 0.124146f, 0.137939f, 0.152954f, 0.167358f, 0.182495f, 0.197754f, 0.213745f, 0.230103f, 0.246216f, 0.262939f,
+ 0.279297f, 0.296387f, 0.313477f, 0.329834f, 0.348145f, 0.365479f, 0.382080f, 0.399658f, 0.417480f, 0.434082f, 0.452148f, 0.469238f,
+ 0.486084f, 0.502441f, 0.520020f, 0.536621f, 0.552734f, 0.569336f, 0.585938f, 0.601562f, 0.617676f, 0.632812f, 0.648438f, 0.664062f,
+ 0.679688f, 0.693848f, 0.708008f, 0.722656f, 0.735840f, 0.750488f, 0.765137f, 0.777832f, 0.791016f, 0.803711f, 0.816895f, 0.829102f,
+ 0.841309f, 0.853027f, 0.925781f, 0.921387f, 0.914551f, 0.908203f, 0.903320f, 0.897461f, 0.004494f, 0.013809f, 0.023331f, 0.033264f,
+ 0.043549f, 0.053833f, 0.065369f, 0.076660f, 0.088684f, 0.100708f, 0.113464f, 0.127075f, 0.140381f, 0.154419f, 0.169067f, 0.183472f,
+ 0.198975f, 0.213623f, 0.229370f, 0.245117f, 0.261475f, 0.277832f, 0.294678f, 0.311523f, 0.327148f, 0.344727f, 0.362061f, 0.378418f,
+ 0.395996f, 0.413086f, 0.430176f, 0.447021f, 0.464111f, 0.481689f, 0.498047f, 0.514648f, 0.531738f, 0.547363f, 0.565430f, 0.582031f,
+ 0.597656f, 0.612793f, 0.628418f, 0.644043f, 0.660645f, 0.674805f, 0.689941f, 0.705078f, 0.718750f, 0.734375f, 0.747559f, 0.761719f,
+ 0.775391f, 0.788086f, 0.803223f, 0.814453f, 0.828125f, 0.840332f, 0.919434f, 0.916504f, 0.909668f, 0.904785f, 0.898926f, 0.894043f,
+ 0.004120f, 0.012512f, 0.021423f, 0.030655f, 0.039673f, 0.049500f, 0.059845f, 0.070374f, 0.081543f, 0.093323f, 0.104614f, 0.116577f,
+ 0.129395f, 0.142456f, 0.156250f, 0.169434f, 0.183594f, 0.198364f, 0.213257f, 0.228638f, 0.244141f, 0.259766f, 0.275635f, 0.291748f,
+ 0.308105f, 0.324707f, 0.341309f, 0.359131f, 0.375244f, 0.391846f, 0.408447f, 0.426025f, 0.442871f, 0.459473f, 0.477051f, 0.494141f,
+ 0.510254f, 0.527344f, 0.543457f, 0.560059f, 0.577148f, 0.592773f, 0.608887f, 0.625977f, 0.640625f, 0.656738f, 0.671875f, 0.686523f,
+ 0.702637f, 0.716797f, 0.731445f, 0.746582f, 0.759277f, 0.773926f, 0.787598f, 0.800293f, 0.814453f, 0.827148f, 0.914062f, 0.911133f,
+ 0.905273f, 0.899902f, 0.895508f, 0.890625f, 0.004120f, 0.011566f, 0.019180f, 0.027969f, 0.036255f, 0.045746f, 0.054901f, 0.064941f,
+ 0.074707f, 0.085327f, 0.096436f, 0.107239f, 0.119324f, 0.131470f, 0.144165f, 0.157104f, 0.169922f, 0.183594f, 0.198242f, 0.212769f,
+ 0.227295f, 0.242188f, 0.257568f, 0.273193f, 0.289307f, 0.305420f, 0.321289f, 0.337891f, 0.354492f, 0.371094f, 0.387451f, 0.405029f,
+ 0.421143f, 0.438477f, 0.455322f, 0.472656f, 0.488525f, 0.505859f, 0.521973f, 0.539551f, 0.555664f, 0.572754f, 0.588867f, 0.605469f,
+ 0.621582f, 0.637207f, 0.653320f, 0.668945f, 0.684570f, 0.698242f, 0.714844f, 0.729492f, 0.745117f, 0.758301f, 0.771973f, 0.787109f,
+ 0.800781f, 0.813477f, 0.907715f, 0.905762f, 0.900879f, 0.895508f, 0.890625f, 0.886719f, 0.003464f, 0.010536f, 0.018143f, 0.025604f,
+ 0.033600f, 0.041992f, 0.050659f, 0.059631f, 0.068481f, 0.078552f, 0.088196f, 0.099060f, 0.110107f, 0.121033f, 0.133057f, 0.145020f,
+ 0.157349f, 0.170166f, 0.183838f, 0.197632f, 0.210938f, 0.225464f, 0.241089f, 0.255371f, 0.270508f, 0.286377f, 0.302246f, 0.317871f,
+ 0.334229f, 0.349854f, 0.367188f, 0.383789f, 0.399414f, 0.417236f, 0.433838f, 0.450928f, 0.468018f, 0.484131f, 0.501465f, 0.519043f,
+ 0.535156f, 0.551758f, 0.568359f, 0.585449f, 0.601074f, 0.617676f, 0.634277f, 0.649902f, 0.666016f, 0.681152f, 0.695801f, 0.711914f,
+ 0.727539f, 0.741699f, 0.756836f, 0.770508f, 0.785645f, 0.800293f, 0.901855f, 0.900391f, 0.895996f, 0.891113f, 0.886230f, 0.881836f,
+ 0.003197f, 0.009903f, 0.016525f, 0.023849f, 0.030853f, 0.038605f, 0.046265f, 0.054657f, 0.063232f, 0.072266f, 0.081543f, 0.090881f,
+ 0.100769f, 0.112061f, 0.123047f, 0.134155f, 0.145752f, 0.157471f, 0.170166f, 0.182861f, 0.196289f, 0.210327f, 0.223755f, 0.238525f,
+ 0.253418f, 0.268066f, 0.283203f, 0.299316f, 0.314697f, 0.330811f, 0.346680f, 0.363281f, 0.379639f, 0.396484f, 0.412842f, 0.429443f,
+ 0.446289f, 0.462891f, 0.480225f, 0.497559f, 0.514648f, 0.531250f, 0.547852f, 0.564453f, 0.581055f, 0.598145f, 0.615234f, 0.631836f,
+ 0.646484f, 0.663086f, 0.679199f, 0.694824f, 0.710449f, 0.726074f, 0.740234f, 0.755859f, 0.770508f, 0.784668f, 0.895020f, 0.894531f,
+ 0.890625f, 0.886719f, 0.881836f, 0.877441f, 0.003071f, 0.009163f, 0.015602f, 0.021729f, 0.028412f, 0.035522f, 0.042755f, 0.050598f,
+ 0.057983f, 0.066284f, 0.075317f, 0.083862f, 0.092773f, 0.102905f, 0.113342f, 0.123840f, 0.134399f, 0.145752f, 0.157593f, 0.169556f,
+ 0.182129f, 0.194702f, 0.207886f, 0.222046f, 0.235840f, 0.250977f, 0.265137f, 0.280273f, 0.295898f, 0.311279f, 0.326660f, 0.342773f,
+ 0.359375f, 0.375732f, 0.392090f, 0.409180f, 0.425049f, 0.441895f, 0.459473f, 0.476318f, 0.493652f, 0.510742f, 0.527344f, 0.544434f,
+ 0.561035f, 0.578125f, 0.595215f, 0.611328f, 0.628418f, 0.645020f, 0.661133f, 0.677246f, 0.693359f, 0.708496f, 0.724609f, 0.740723f,
+ 0.755859f, 0.771484f, 0.889160f, 0.889160f, 0.885254f, 0.881348f, 0.876953f, 0.873047f, 0.002748f, 0.008171f, 0.014084f, 0.019638f,
+ 0.026108f, 0.032318f, 0.039154f, 0.045990f, 0.053619f, 0.061066f, 0.068665f, 0.076477f, 0.085632f, 0.094727f, 0.104187f, 0.113831f,
+ 0.123535f, 0.134888f, 0.145508f, 0.157104f, 0.168701f, 0.181030f, 0.193481f, 0.206665f, 0.220093f, 0.233398f, 0.248169f, 0.262695f,
+ 0.277344f, 0.292236f, 0.307617f, 0.322998f, 0.339355f, 0.355469f, 0.371582f, 0.388184f, 0.404541f, 0.420410f, 0.438477f, 0.455322f,
+ 0.472656f, 0.489014f, 0.506348f, 0.523926f, 0.541016f, 0.557617f, 0.575195f, 0.591309f, 0.608887f, 0.625977f, 0.643555f, 0.659180f,
+ 0.674805f, 0.691406f, 0.707520f, 0.724121f, 0.739746f, 0.755371f, 0.882812f, 0.883789f, 0.879883f, 0.875977f, 0.872559f, 0.868652f,
+ 0.002491f, 0.007809f, 0.012764f, 0.018448f, 0.024094f, 0.029861f, 0.036102f, 0.042572f, 0.049500f, 0.056091f, 0.063293f, 0.070984f,
+ 0.079285f, 0.087036f, 0.095825f, 0.104858f, 0.114441f, 0.124084f, 0.133789f, 0.144653f, 0.156250f, 0.167480f, 0.179199f, 0.191650f,
+ 0.204102f, 0.217896f, 0.231445f, 0.245239f, 0.259521f, 0.274170f, 0.289307f, 0.304199f, 0.319580f, 0.334961f, 0.351074f, 0.367676f,
+ 0.384277f, 0.400635f, 0.417480f, 0.434570f, 0.451660f, 0.468994f, 0.485352f, 0.502441f, 0.520508f, 0.537109f, 0.554688f, 0.571777f,
+ 0.588867f, 0.605957f, 0.623047f, 0.639648f, 0.656738f, 0.673828f, 0.690430f, 0.708008f, 0.723633f, 0.739746f, 0.874023f, 0.876953f,
+ 0.874023f, 0.871582f, 0.867188f, 0.862793f, 0.002279f, 0.007130f, 0.012291f, 0.016922f, 0.022171f, 0.027847f, 0.033325f, 0.039185f,
+ 0.045349f, 0.051849f, 0.058411f, 0.064880f, 0.072144f, 0.080017f, 0.087891f, 0.096313f, 0.105103f, 0.114197f, 0.123779f, 0.134155f,
+ 0.144043f, 0.155151f, 0.166016f, 0.177246f, 0.189697f, 0.202271f, 0.214722f, 0.228271f, 0.242310f, 0.256592f, 0.270752f, 0.285400f,
+ 0.300537f, 0.315674f, 0.331543f, 0.347656f, 0.363525f, 0.379639f, 0.396729f, 0.414307f, 0.430908f, 0.447754f, 0.465088f, 0.482178f,
+ 0.499512f, 0.517090f, 0.533203f, 0.552246f, 0.568848f, 0.586426f, 0.603516f, 0.621582f, 0.639648f, 0.656250f, 0.673828f, 0.690918f,
+ 0.707520f, 0.724121f, 0.867676f, 0.870605f, 0.868164f, 0.865723f, 0.861328f, 0.857910f, 0.002220f, 0.006565f, 0.011238f, 0.015961f,
+ 0.020401f, 0.025558f, 0.030853f, 0.036133f, 0.041199f, 0.047180f, 0.053436f, 0.059723f, 0.066162f, 0.073853f, 0.080688f, 0.088440f,
+ 0.096436f, 0.105042f, 0.114319f, 0.123047f, 0.132446f, 0.142822f, 0.153198f, 0.164062f, 0.175659f, 0.187378f, 0.199463f, 0.212402f,
+ 0.225464f, 0.239014f, 0.252686f, 0.266846f, 0.281494f, 0.296631f, 0.312500f, 0.328369f, 0.343750f, 0.359863f, 0.376221f, 0.393066f,
+ 0.409668f, 0.426514f, 0.444336f, 0.461670f, 0.478760f, 0.496826f, 0.513672f, 0.532227f, 0.549316f, 0.567383f, 0.584961f, 0.602051f,
+ 0.620605f, 0.637207f, 0.655273f, 0.672363f, 0.689941f, 0.708008f, 0.860840f, 0.864746f, 0.862793f, 0.859375f, 0.855957f, 0.853027f,
+ 0.002190f, 0.005993f, 0.010117f, 0.014420f, 0.018738f, 0.023361f, 0.028015f, 0.033142f, 0.037781f, 0.043732f, 0.048920f, 0.054840f,
+ 0.061218f, 0.067810f, 0.074219f, 0.081299f, 0.088562f, 0.096130f, 0.104614f, 0.113098f, 0.122253f, 0.131714f, 0.141113f, 0.151245f,
+ 0.162109f, 0.173462f, 0.184692f, 0.196899f, 0.209473f, 0.222534f, 0.236206f, 0.249634f, 0.263672f, 0.277588f, 0.293213f, 0.308350f,
+ 0.323975f, 0.339844f, 0.355957f, 0.372070f, 0.389404f, 0.405762f, 0.422852f, 0.439941f, 0.458008f, 0.475098f, 0.492920f, 0.510742f,
+ 0.528320f, 0.546875f, 0.564453f, 0.583496f, 0.601074f, 0.619141f, 0.636719f, 0.654785f, 0.672852f, 0.691406f, 0.852539f, 0.858398f,
+ 0.856445f, 0.853516f, 0.850586f, 0.847656f, 0.001787f, 0.005753f, 0.009300f, 0.013611f, 0.017410f, 0.021576f, 0.025665f, 0.030533f,
+ 0.035126f, 0.040039f, 0.044952f, 0.050446f, 0.055817f, 0.061890f, 0.068054f, 0.074707f, 0.081482f, 0.088501f, 0.095764f, 0.103943f,
+ 0.112183f, 0.120850f, 0.130249f, 0.139526f, 0.149658f, 0.160400f, 0.171021f, 0.182007f, 0.194336f, 0.206421f, 0.219360f, 0.232666f,
+ 0.245850f, 0.260010f, 0.274170f, 0.289307f, 0.304443f, 0.319580f, 0.335693f, 0.352295f, 0.369141f, 0.385498f, 0.402344f, 0.419189f,
+ 0.437012f, 0.454346f, 0.472412f, 0.490234f, 0.507812f, 0.525879f, 0.545410f, 0.562500f, 0.581055f, 0.600098f, 0.618164f, 0.636719f,
+ 0.655273f, 0.674316f, 0.845703f, 0.852051f, 0.849609f, 0.847168f, 0.845215f, 0.841309f, 0.001766f, 0.005241f, 0.008881f, 0.012024f,
+ 0.016129f, 0.020233f, 0.024124f, 0.027664f, 0.032135f, 0.036835f, 0.041321f, 0.046173f, 0.051392f, 0.056946f, 0.062225f, 0.068604f,
+ 0.074524f, 0.080933f, 0.088135f, 0.095398f, 0.103210f, 0.110779f, 0.119263f, 0.128296f, 0.137695f, 0.147217f, 0.157349f, 0.168091f,
+ 0.179688f, 0.191284f, 0.203613f, 0.215942f, 0.228882f, 0.242554f, 0.255859f, 0.270508f, 0.285400f, 0.300537f, 0.316406f, 0.331787f,
+ 0.348877f, 0.364746f, 0.382080f, 0.398682f, 0.415771f, 0.434082f, 0.451416f, 0.469482f, 0.487793f, 0.505859f, 0.524414f, 0.542969f,
+ 0.562012f, 0.580566f, 0.598145f, 0.618652f, 0.637695f, 0.657227f, 0.837891f, 0.844727f, 0.843750f, 0.841309f, 0.838379f, 0.836426f,
+ 0.001598f, 0.004887f, 0.008217f, 0.011497f, 0.014786f, 0.018326f, 0.021652f, 0.025513f, 0.029541f, 0.033813f, 0.038086f, 0.042236f,
+ 0.046844f, 0.052032f, 0.057251f, 0.062622f, 0.068237f, 0.074280f, 0.080505f, 0.086975f, 0.094116f, 0.101074f, 0.109314f, 0.117554f,
+ 0.126587f, 0.135254f, 0.144775f, 0.155029f, 0.165405f, 0.176392f, 0.187744f, 0.199829f, 0.212646f, 0.224976f, 0.238647f, 0.252441f,
+ 0.267090f, 0.281738f, 0.296631f, 0.312256f, 0.328369f, 0.344971f, 0.361328f, 0.377686f, 0.395264f, 0.412842f, 0.430908f, 0.448730f,
+ 0.467041f, 0.485596f, 0.503906f, 0.522461f, 0.541504f, 0.561523f, 0.580078f, 0.599121f, 0.618164f, 0.639648f, 0.828613f, 0.837891f,
+ 0.836914f, 0.834473f, 0.833008f, 0.830566f, 0.001709f, 0.004494f, 0.007416f, 0.010628f, 0.013680f, 0.016785f, 0.020203f, 0.023712f,
+ 0.027435f, 0.031006f, 0.034424f, 0.038635f, 0.043182f, 0.047668f, 0.052307f, 0.057159f, 0.062042f, 0.067749f, 0.073730f, 0.079956f,
+ 0.086182f, 0.092773f, 0.100159f, 0.107727f, 0.115479f, 0.123962f, 0.132935f, 0.142578f, 0.151978f, 0.162476f, 0.173340f, 0.184570f,
+ 0.196411f, 0.208740f, 0.221436f, 0.235229f, 0.248779f, 0.262939f, 0.277832f, 0.293213f, 0.308105f, 0.324219f, 0.341309f, 0.357178f,
+ 0.374756f, 0.391846f, 0.409424f, 0.427490f, 0.446533f, 0.464844f, 0.483643f, 0.501953f, 0.521484f, 0.541504f, 0.561035f, 0.579590f,
+ 0.599609f, 0.620605f, 0.821289f, 0.830566f, 0.830078f, 0.828125f, 0.825684f, 0.823242f, 0.001367f, 0.004105f, 0.007023f, 0.009552f,
+ 0.012611f, 0.015289f, 0.018341f, 0.021652f, 0.024857f, 0.027878f, 0.031769f, 0.035614f, 0.039276f, 0.043610f, 0.047333f, 0.052155f,
+ 0.056549f, 0.061401f, 0.066895f, 0.072449f, 0.078613f, 0.084778f, 0.091309f, 0.098083f, 0.105774f, 0.113281f, 0.121399f, 0.130371f,
+ 0.139648f, 0.148926f, 0.159546f, 0.169922f, 0.180908f, 0.192749f, 0.204834f, 0.217651f, 0.231567f, 0.244385f, 0.259277f, 0.273926f,
+ 0.289307f, 0.304688f, 0.320557f, 0.336914f, 0.354248f, 0.371338f, 0.388184f, 0.406982f, 0.424316f, 0.443115f, 0.462646f, 0.481445f,
+ 0.501465f, 0.520508f, 0.541016f, 0.559570f, 0.580078f, 0.601074f, 0.812988f, 0.823242f, 0.823242f, 0.821289f, 0.819824f, 0.817383f,
+ 0.001398f, 0.003883f, 0.006351f, 0.008911f, 0.011559f, 0.014343f, 0.017212f, 0.020035f, 0.022797f, 0.026062f, 0.028793f, 0.031891f,
+ 0.035858f, 0.039368f, 0.043213f, 0.047607f, 0.051483f, 0.056030f, 0.060883f, 0.065979f, 0.071350f, 0.076843f, 0.083130f, 0.089172f,
+ 0.096069f, 0.103333f, 0.111023f, 0.119019f, 0.127319f, 0.136719f, 0.145996f, 0.156128f, 0.166138f, 0.177368f, 0.189453f, 0.201416f,
+ 0.213745f, 0.227295f, 0.240601f, 0.255371f, 0.269287f, 0.285400f, 0.301270f, 0.317139f, 0.333740f, 0.350586f, 0.367920f, 0.385986f,
+ 0.404297f, 0.422852f, 0.442383f, 0.460938f, 0.479980f, 0.500488f, 0.520508f, 0.541016f, 0.560547f, 0.582520f, 0.803711f, 0.814941f,
+ 0.815430f, 0.814453f, 0.812500f, 0.810547f, 0.001259f, 0.003464f, 0.006332f, 0.008286f, 0.010384f, 0.013000f, 0.015587f, 0.018234f,
+ 0.021027f, 0.023422f, 0.026566f, 0.029480f, 0.032379f, 0.035919f, 0.039215f, 0.043060f, 0.046997f, 0.050995f, 0.055267f, 0.059998f,
+ 0.065002f, 0.069946f, 0.075317f, 0.081299f, 0.087280f, 0.094116f, 0.101135f, 0.108276f, 0.116150f, 0.124695f, 0.133545f, 0.142700f,
+ 0.152222f, 0.162720f, 0.173950f, 0.185303f, 0.197754f, 0.210205f, 0.223022f, 0.237061f, 0.250732f, 0.265869f, 0.281250f, 0.297119f,
+ 0.313477f, 0.330322f, 0.347656f, 0.364746f, 0.383301f, 0.401367f, 0.420898f, 0.440186f, 0.459229f, 0.479736f, 0.499512f, 0.520996f,
+ 0.541016f, 0.562988f, 0.794434f, 0.807129f, 0.807617f, 0.807129f, 0.805176f, 0.803711f, 0.001070f, 0.003237f, 0.005432f, 0.007359f,
+ 0.009857f, 0.012337f, 0.014191f, 0.016586f, 0.019257f, 0.021561f, 0.024094f, 0.026901f, 0.029724f, 0.032745f, 0.035675f, 0.039368f,
+ 0.042572f, 0.045990f, 0.050354f, 0.054535f, 0.058746f, 0.063232f, 0.068420f, 0.073608f, 0.079529f, 0.085266f, 0.091370f, 0.098083f,
+ 0.105835f, 0.113159f, 0.121094f, 0.129639f, 0.139038f, 0.148926f, 0.159058f, 0.169678f, 0.181274f, 0.193481f, 0.205811f, 0.219482f,
+ 0.233032f, 0.247192f, 0.262207f, 0.277100f, 0.293213f, 0.309814f, 0.326660f, 0.344238f, 0.361816f, 0.380615f, 0.398926f, 0.418945f,
+ 0.438477f, 0.458008f, 0.479004f, 0.499512f, 0.520996f, 0.543945f, 0.784668f, 0.798828f, 0.800293f, 0.799805f, 0.797852f, 0.796875f,
+ 0.001074f, 0.002916f, 0.004955f, 0.007149f, 0.009033f, 0.011055f, 0.013268f, 0.015495f, 0.017365f, 0.019485f, 0.022095f, 0.024002f,
+ 0.026688f, 0.029633f, 0.032593f, 0.035370f, 0.038361f, 0.041870f, 0.045319f, 0.049225f, 0.052948f, 0.057068f, 0.061676f, 0.066345f,
+ 0.071167f, 0.076782f, 0.082581f, 0.088867f, 0.095886f, 0.102539f, 0.109802f, 0.118042f, 0.126709f, 0.135132f, 0.144897f, 0.155151f,
+ 0.165771f, 0.177368f, 0.189209f, 0.201904f, 0.215210f, 0.229370f, 0.242798f, 0.258057f, 0.274170f, 0.290039f, 0.306885f, 0.323242f,
+ 0.341309f, 0.359375f, 0.378418f, 0.397461f, 0.416260f, 0.437500f, 0.457031f, 0.479004f, 0.501465f, 0.522461f, 0.775391f, 0.790527f,
+ 0.791992f, 0.791504f, 0.791016f, 0.789551f, 0.000837f, 0.002916f, 0.004738f, 0.006477f, 0.008575f, 0.010170f, 0.012161f, 0.014023f,
+ 0.015808f, 0.017792f, 0.020111f, 0.022064f, 0.024414f, 0.026794f, 0.029251f, 0.032074f, 0.034698f, 0.037598f, 0.040741f, 0.043915f,
+ 0.047577f, 0.051361f, 0.055389f, 0.059692f, 0.064209f, 0.068787f, 0.074585f, 0.079712f, 0.085632f, 0.092346f, 0.099487f, 0.106323f,
+ 0.114929f, 0.122925f, 0.131958f, 0.141235f, 0.151123f, 0.161865f, 0.172974f, 0.184937f, 0.197632f, 0.210693f, 0.224854f, 0.239136f,
+ 0.254395f, 0.269531f, 0.285889f, 0.302979f, 0.320557f, 0.338623f, 0.356689f, 0.375977f, 0.395752f, 0.415527f, 0.436523f, 0.458252f,
+ 0.479248f, 0.501465f, 0.765137f, 0.781738f, 0.783691f, 0.784180f, 0.783203f, 0.781250f, 0.000854f, 0.002817f, 0.004089f, 0.005684f,
+ 0.007675f, 0.009277f, 0.010864f, 0.012413f, 0.014427f, 0.016235f, 0.017838f, 0.019913f, 0.021805f, 0.023987f, 0.026276f, 0.028915f,
+ 0.030960f, 0.033875f, 0.036652f, 0.039551f, 0.042816f, 0.045837f, 0.049591f, 0.053589f, 0.057526f, 0.061829f, 0.066650f, 0.071655f,
+ 0.077393f, 0.083008f, 0.088989f, 0.096008f, 0.103210f, 0.110657f, 0.119141f, 0.127930f, 0.137085f, 0.146973f, 0.157593f, 0.169312f,
+ 0.181274f, 0.193481f, 0.207031f, 0.220581f, 0.235229f, 0.250732f, 0.266357f, 0.282227f, 0.299805f, 0.317627f, 0.335449f, 0.354736f,
+ 0.374268f, 0.394531f, 0.415527f, 0.436279f, 0.458252f, 0.481689f, 0.754883f, 0.773438f, 0.775391f, 0.775879f, 0.774902f, 0.773926f,
+ 0.000852f, 0.002520f, 0.003937f, 0.005527f, 0.006836f, 0.008408f, 0.009773f, 0.011620f, 0.013039f, 0.014687f, 0.016327f, 0.017944f,
+ 0.019760f, 0.021774f, 0.023697f, 0.025894f, 0.027969f, 0.030121f, 0.032501f, 0.035370f, 0.038208f, 0.041046f, 0.044098f, 0.047791f,
+ 0.051453f, 0.055176f, 0.059570f, 0.064026f, 0.068787f, 0.074158f, 0.079834f, 0.085938f, 0.092590f, 0.099304f, 0.106873f, 0.114990f,
+ 0.124023f, 0.133301f, 0.143066f, 0.153687f, 0.164551f, 0.176392f, 0.189209f, 0.202637f, 0.216553f, 0.231323f, 0.246704f, 0.262451f,
+ 0.279297f, 0.296387f, 0.314697f, 0.333496f, 0.353516f, 0.373047f, 0.394775f, 0.415039f, 0.437500f, 0.460449f, 0.745117f, 0.763672f,
+ 0.766602f, 0.767090f, 0.767090f, 0.765625f, 0.000762f, 0.002342f, 0.003563f, 0.004787f, 0.006447f, 0.007648f, 0.009193f, 0.010353f,
+ 0.012016f, 0.013138f, 0.014557f, 0.016312f, 0.017929f, 0.019470f, 0.021103f, 0.023056f, 0.024918f, 0.026886f, 0.029099f, 0.031586f,
+ 0.034058f, 0.036499f, 0.039307f, 0.042450f, 0.045685f, 0.049072f, 0.052826f, 0.056915f, 0.061096f, 0.065918f, 0.070984f, 0.076538f,
+ 0.082520f, 0.088928f, 0.095520f, 0.102905f, 0.111206f, 0.119629f, 0.128662f, 0.138184f, 0.148682f, 0.160156f, 0.171997f, 0.184937f,
+ 0.198364f, 0.212524f, 0.227173f, 0.243042f, 0.259277f, 0.276611f, 0.294189f, 0.312500f, 0.331055f, 0.350830f, 0.372070f, 0.392334f,
+ 0.415771f, 0.438232f, 0.734375f, 0.754395f, 0.758789f, 0.758789f, 0.758789f, 0.757812f, 0.000848f, 0.002024f, 0.003553f, 0.004646f,
+ 0.005726f, 0.007050f, 0.008362f, 0.009438f, 0.010536f, 0.011810f, 0.013123f, 0.014481f, 0.015778f, 0.017242f, 0.018753f, 0.020447f,
+ 0.022278f, 0.023819f, 0.025940f, 0.027771f, 0.029999f, 0.032410f, 0.034851f, 0.037354f, 0.040375f, 0.043610f, 0.046631f, 0.050354f,
+ 0.054108f, 0.058563f, 0.062805f, 0.067871f, 0.073242f, 0.078796f, 0.085083f, 0.091797f, 0.098816f, 0.106689f, 0.115540f, 0.124207f,
+ 0.134155f, 0.144409f, 0.155762f, 0.167725f, 0.180664f, 0.193848f, 0.208618f, 0.223389f, 0.239746f, 0.256104f, 0.273438f, 0.291260f,
+ 0.310059f, 0.330078f, 0.349854f, 0.370850f, 0.393555f, 0.416992f, 0.724121f, 0.744629f, 0.748535f, 0.750000f, 0.749512f, 0.749512f,
+ 0.000736f, 0.001780f, 0.002937f, 0.004314f, 0.005211f, 0.006214f, 0.007423f, 0.008537f, 0.009392f, 0.010773f, 0.011726f, 0.012970f,
+ 0.014183f, 0.015373f, 0.016724f, 0.017990f, 0.019730f, 0.021194f, 0.022644f, 0.024368f, 0.026443f, 0.028610f, 0.030685f, 0.032898f,
+ 0.035583f, 0.038300f, 0.041351f, 0.044556f, 0.047638f, 0.051422f, 0.055359f, 0.059875f, 0.064392f, 0.069580f, 0.075195f, 0.080872f,
+ 0.087646f, 0.094849f, 0.102173f, 0.110596f, 0.119690f, 0.129761f, 0.139893f, 0.151367f, 0.163452f, 0.176147f, 0.190063f, 0.204590f,
+ 0.219238f, 0.235718f, 0.252441f, 0.270264f, 0.289062f, 0.307861f, 0.328613f, 0.350098f, 0.372314f, 0.395020f, 0.712402f, 0.734863f,
+ 0.739746f, 0.740723f, 0.740723f, 0.740234f, 0.000589f, 0.001616f, 0.002674f, 0.003841f, 0.004940f, 0.005676f, 0.006554f, 0.007442f,
+ 0.008812f, 0.009537f, 0.010277f, 0.011528f, 0.012634f, 0.013527f, 0.014671f, 0.016037f, 0.017136f, 0.018631f, 0.019943f, 0.021530f,
+ 0.023071f, 0.025146f, 0.026825f, 0.029037f, 0.030853f, 0.033447f, 0.035736f, 0.038849f, 0.041656f, 0.044922f, 0.048462f, 0.052277f,
+ 0.056519f, 0.061127f, 0.065796f, 0.071411f, 0.077148f, 0.083435f, 0.090393f, 0.097900f, 0.106079f, 0.115356f, 0.125122f, 0.135132f,
+ 0.146729f, 0.158936f, 0.171509f, 0.185059f, 0.200439f, 0.215576f, 0.232056f, 0.249756f, 0.267822f, 0.286621f, 0.306885f, 0.328125f,
+ 0.349854f, 0.373291f, 0.701172f, 0.725586f, 0.729980f, 0.730957f, 0.731934f, 0.730957f, 0.000547f, 0.001666f, 0.002367f, 0.003559f,
+ 0.004238f, 0.005028f, 0.005852f, 0.006859f, 0.007755f, 0.008530f, 0.009163f, 0.010056f, 0.010956f, 0.011978f, 0.013062f, 0.014076f,
+ 0.015053f, 0.016251f, 0.017471f, 0.018921f, 0.020233f, 0.021774f, 0.023315f, 0.025162f, 0.026871f, 0.029007f, 0.031204f, 0.033661f,
+ 0.036102f, 0.039062f, 0.042053f, 0.045380f, 0.048859f, 0.053040f, 0.057343f, 0.062225f, 0.067261f, 0.073120f, 0.079407f, 0.086243f,
+ 0.093567f, 0.101868f, 0.110596f, 0.120239f, 0.130859f, 0.141968f, 0.154053f, 0.167358f, 0.181274f, 0.196045f, 0.212158f, 0.229248f,
+ 0.247192f, 0.265381f, 0.285400f, 0.305664f, 0.327637f, 0.350586f, 0.689453f, 0.715820f, 0.720215f, 0.722168f, 0.722168f, 0.722168f,
+ 0.000492f, 0.001634f, 0.002342f, 0.003111f, 0.003866f, 0.004574f, 0.005417f, 0.005928f, 0.006588f, 0.007393f, 0.008041f, 0.008873f,
+ 0.009689f, 0.010391f, 0.011375f, 0.012146f, 0.013100f, 0.014183f, 0.015274f, 0.016479f, 0.017456f, 0.018768f, 0.020157f, 0.021606f,
+ 0.023300f, 0.024933f, 0.026855f, 0.028885f, 0.031143f, 0.033417f, 0.036133f, 0.039032f, 0.042236f, 0.045776f, 0.049713f, 0.053680f,
+ 0.058228f, 0.063232f, 0.069092f, 0.074829f, 0.081482f, 0.089050f, 0.096924f, 0.105591f, 0.115417f, 0.126221f, 0.137329f, 0.149658f,
+ 0.162964f, 0.176880f, 0.192505f, 0.208740f, 0.226318f, 0.244873f, 0.263428f, 0.283936f, 0.306396f, 0.329346f, 0.676270f, 0.705078f,
+ 0.709961f, 0.711914f, 0.712891f, 0.711914f, 0.000506f, 0.001342f, 0.002157f, 0.002813f, 0.003353f, 0.004105f, 0.004658f, 0.005344f,
+ 0.005871f, 0.006538f, 0.007050f, 0.007751f, 0.008247f, 0.009109f, 0.009865f, 0.010559f, 0.011269f, 0.012169f, 0.013290f, 0.014191f,
+ 0.015015f, 0.016312f, 0.017395f, 0.018570f, 0.019989f, 0.021439f, 0.023102f, 0.024536f, 0.026535f, 0.028702f, 0.030899f, 0.033356f,
+ 0.035980f, 0.039093f, 0.042328f, 0.046051f, 0.049927f, 0.054199f, 0.059052f, 0.064575f, 0.070496f, 0.076782f, 0.084412f, 0.092285f,
+ 0.100708f, 0.110779f, 0.121399f, 0.132690f, 0.145508f, 0.158813f, 0.173584f, 0.189453f, 0.205688f, 0.223755f, 0.242554f, 0.263184f,
+ 0.284180f, 0.306641f, 0.664551f, 0.693848f, 0.699707f, 0.702148f, 0.702637f, 0.703125f, 0.000500f, 0.001122f, 0.001810f, 0.002363f,
+ 0.002987f, 0.003576f, 0.004158f, 0.004620f, 0.005032f, 0.005627f, 0.006161f, 0.006721f, 0.007179f, 0.007790f, 0.008385f, 0.009163f,
+ 0.009758f, 0.010536f, 0.011284f, 0.011986f, 0.012878f, 0.013710f, 0.014725f, 0.015823f, 0.016937f, 0.018326f, 0.019547f, 0.020874f,
+ 0.022522f, 0.024399f, 0.026077f, 0.028427f, 0.030609f, 0.032990f, 0.035736f, 0.038788f, 0.042236f, 0.045990f, 0.050354f, 0.054901f,
+ 0.059967f, 0.065918f, 0.072205f, 0.079468f, 0.087219f, 0.096252f, 0.105713f, 0.116272f, 0.128174f, 0.140747f, 0.154419f, 0.169556f,
+ 0.186279f, 0.203125f, 0.221313f, 0.240601f, 0.261719f, 0.284424f, 0.652344f, 0.683105f, 0.688965f, 0.691406f, 0.692383f, 0.693359f,
+ 0.000482f, 0.001184f, 0.001604f, 0.002171f, 0.002562f, 0.003029f, 0.003656f, 0.003941f, 0.004410f, 0.004948f, 0.005325f, 0.005577f,
+ 0.006157f, 0.006702f, 0.007172f, 0.007751f, 0.008331f, 0.008904f, 0.009514f, 0.010063f, 0.010925f, 0.011719f, 0.012306f, 0.013321f,
+ 0.014275f, 0.015465f, 0.016510f, 0.017593f, 0.018845f, 0.020401f, 0.022095f, 0.023682f, 0.025513f, 0.027679f, 0.029968f, 0.032593f,
+ 0.035461f, 0.038757f, 0.042175f, 0.046326f, 0.050873f, 0.055939f, 0.061462f, 0.067444f, 0.074402f, 0.082520f, 0.091125f, 0.100830f,
+ 0.111572f, 0.123413f, 0.136719f, 0.150513f, 0.165894f, 0.182251f, 0.200684f, 0.219727f, 0.240234f, 0.261963f, 0.640137f, 0.671387f,
+ 0.679199f, 0.680664f, 0.682617f, 0.683105f, 0.000501f, 0.000919f, 0.001424f, 0.001853f, 0.002266f, 0.002789f, 0.002998f, 0.003397f,
+ 0.003902f, 0.004192f, 0.004417f, 0.004974f, 0.005207f, 0.005676f, 0.006134f, 0.006527f, 0.007179f, 0.007465f, 0.008018f, 0.008537f,
+ 0.009178f, 0.009888f, 0.010544f, 0.011093f, 0.011986f, 0.012794f, 0.013664f, 0.014717f, 0.015747f, 0.016983f, 0.018127f, 0.019470f,
+ 0.021103f, 0.022919f, 0.024826f, 0.026962f, 0.029358f, 0.031769f, 0.035065f, 0.038239f, 0.042297f, 0.046570f, 0.051422f, 0.056671f,
+ 0.062805f, 0.069763f, 0.077698f, 0.086182f, 0.095825f, 0.106812f, 0.119080f, 0.132568f, 0.147217f, 0.162598f, 0.180176f, 0.198730f,
+ 0.218628f, 0.241211f, 0.627441f, 0.660156f, 0.668457f, 0.669922f, 0.672363f, 0.671875f, 0.000235f, 0.001120f, 0.001356f, 0.001651f,
+ 0.002117f, 0.002441f, 0.002678f, 0.002993f, 0.003244f, 0.003519f, 0.003876f, 0.004086f, 0.004505f, 0.004787f, 0.005085f, 0.005604f,
+ 0.005985f, 0.006271f, 0.006783f, 0.007145f, 0.007679f, 0.008217f, 0.008728f, 0.009277f, 0.009956f, 0.010605f, 0.011490f, 0.012062f,
+ 0.013084f, 0.013962f, 0.014984f, 0.016113f, 0.017395f, 0.018829f, 0.020416f, 0.022125f, 0.023972f, 0.025955f, 0.028625f, 0.031616f,
+ 0.034515f, 0.038147f, 0.042114f, 0.046783f, 0.052094f, 0.058075f, 0.065002f, 0.072510f, 0.081604f, 0.091125f, 0.102539f, 0.114807f,
+ 0.128662f, 0.143921f, 0.160034f, 0.178467f, 0.198364f, 0.218750f, 0.613281f, 0.648926f, 0.657227f, 0.659668f, 0.661621f, 0.661621f,
+ 0.000382f, 0.000704f, 0.001099f, 0.001557f, 0.001774f, 0.001976f, 0.002132f, 0.002575f, 0.002634f, 0.002916f, 0.003103f, 0.003494f,
+ 0.003754f, 0.003956f, 0.004269f, 0.004684f, 0.004902f, 0.005234f, 0.005569f, 0.005890f, 0.006416f, 0.006786f, 0.007160f, 0.007645f,
+ 0.008118f, 0.008781f, 0.009346f, 0.010025f, 0.010658f, 0.011475f, 0.012230f, 0.013016f, 0.014122f, 0.015251f, 0.016342f, 0.017807f,
+ 0.019424f, 0.021103f, 0.023026f, 0.025436f, 0.027817f, 0.030914f, 0.034210f, 0.037750f, 0.042450f, 0.047455f, 0.053101f, 0.059998f,
+ 0.067688f, 0.076660f, 0.086670f, 0.097961f, 0.110779f, 0.125366f, 0.140747f, 0.158081f, 0.176880f, 0.197632f, 0.600098f, 0.637207f,
+ 0.644531f, 0.647949f, 0.649414f, 0.651855f, 0.000182f, 0.000738f, 0.000942f, 0.001220f, 0.001469f, 0.001634f, 0.001820f, 0.002005f,
+ 0.002291f, 0.002441f, 0.002636f, 0.002832f, 0.003019f, 0.003242f, 0.003502f, 0.003824f, 0.004017f, 0.004333f, 0.004570f, 0.004883f,
+ 0.005173f, 0.005615f, 0.005909f, 0.006317f, 0.006649f, 0.007160f, 0.007656f, 0.008156f, 0.008583f, 0.009209f, 0.009857f, 0.010696f,
+ 0.011322f, 0.012367f, 0.013229f, 0.014259f, 0.015686f, 0.016815f, 0.018402f, 0.020126f, 0.022095f, 0.024414f, 0.027176f, 0.030273f,
+ 0.033722f, 0.038086f, 0.042969f, 0.048645f, 0.055237f, 0.063171f, 0.071960f, 0.082031f, 0.093994f, 0.107300f, 0.122131f, 0.138550f,
+ 0.156494f, 0.177002f, 0.586426f, 0.625488f, 0.633789f, 0.637207f, 0.638672f, 0.639648f, 0.000199f, 0.000534f, 0.000745f, 0.000995f,
+ 0.001190f, 0.001387f, 0.001516f, 0.001691f, 0.001790f, 0.001941f, 0.002214f, 0.002346f, 0.002449f, 0.002686f, 0.002832f, 0.003042f,
+ 0.003304f, 0.003531f, 0.003662f, 0.003952f, 0.004181f, 0.004517f, 0.004704f, 0.005074f, 0.005352f, 0.005718f, 0.006096f, 0.006481f,
+ 0.006947f, 0.007454f, 0.007988f, 0.008484f, 0.009140f, 0.009804f, 0.010475f, 0.011307f, 0.012299f, 0.013268f, 0.014511f, 0.015823f,
+ 0.017410f, 0.018936f, 0.021225f, 0.023621f, 0.026367f, 0.029770f, 0.033661f, 0.038452f, 0.044067f, 0.050812f, 0.058411f, 0.067444f,
+ 0.077942f, 0.090149f, 0.104187f, 0.119812f, 0.137085f, 0.156372f, 0.572754f, 0.613770f, 0.621582f, 0.625977f, 0.627441f, 0.628906f,
+ 0.000165f, 0.000486f, 0.000618f, 0.000880f, 0.001063f, 0.001140f, 0.001258f, 0.001464f, 0.001498f, 0.001561f, 0.001707f, 0.001899f,
+ 0.001976f, 0.002171f, 0.002285f, 0.002474f, 0.002571f, 0.002764f, 0.002968f, 0.003170f, 0.003389f, 0.003580f, 0.003822f, 0.004036f,
+ 0.004269f, 0.004505f, 0.004738f, 0.005157f, 0.005474f, 0.005821f, 0.006279f, 0.006649f, 0.007107f, 0.007610f, 0.008240f, 0.008835f,
+ 0.009598f, 0.010361f, 0.011276f, 0.012299f, 0.013466f, 0.014740f, 0.016251f, 0.018021f, 0.020294f, 0.022797f, 0.025833f, 0.029739f,
+ 0.034058f, 0.039612f, 0.046021f, 0.053833f, 0.063110f, 0.074158f, 0.086914f, 0.101562f, 0.118164f, 0.136841f, 0.558594f, 0.601074f,
+ 0.608887f, 0.613281f, 0.615234f, 0.617188f, 0.000096f, 0.000348f, 0.000585f, 0.000707f, 0.000837f, 0.000866f, 0.000972f, 0.001095f,
+ 0.001198f, 0.001309f, 0.001355f, 0.001417f, 0.001615f, 0.001740f, 0.001863f, 0.001880f, 0.002048f, 0.002159f, 0.002380f, 0.002487f,
+ 0.002613f, 0.002777f, 0.003000f, 0.003143f, 0.003353f, 0.003521f, 0.003748f, 0.003963f, 0.004265f, 0.004490f, 0.004776f, 0.005093f,
+ 0.005577f, 0.005966f, 0.006321f, 0.006828f, 0.007320f, 0.007904f, 0.008575f, 0.009392f, 0.010231f, 0.011276f, 0.012321f, 0.013832f,
+ 0.015343f, 0.017242f, 0.019501f, 0.022247f, 0.025696f, 0.029922f, 0.035187f, 0.041779f, 0.049683f, 0.059387f, 0.070801f, 0.084106f,
+ 0.100037f, 0.117798f, 0.544434f, 0.588867f, 0.597656f, 0.602539f, 0.604492f, 0.605469f, 0.000123f, 0.000248f, 0.000443f, 0.000625f,
+ 0.000663f, 0.000733f, 0.000843f, 0.000780f, 0.000921f, 0.000986f, 0.001081f, 0.001178f, 0.001254f, 0.001348f, 0.001364f, 0.001515f,
+ 0.001565f, 0.001705f, 0.001824f, 0.001870f, 0.002066f, 0.002155f, 0.002274f, 0.002422f, 0.002525f, 0.002695f, 0.002863f, 0.003038f,
+ 0.003271f, 0.003441f, 0.003736f, 0.003901f, 0.004112f, 0.004478f, 0.004719f, 0.005093f, 0.005482f, 0.005913f, 0.006413f, 0.007019f,
+ 0.007626f, 0.008408f, 0.009201f, 0.010201f, 0.011436f, 0.012749f, 0.014389f, 0.016373f, 0.018906f, 0.022034f, 0.025909f, 0.031082f,
+ 0.037628f, 0.045715f, 0.055939f, 0.068176f, 0.082764f, 0.099365f, 0.529785f, 0.574707f, 0.584961f, 0.589844f, 0.591797f, 0.593750f,
+ 0.000210f, 0.000212f, 0.000365f, 0.000494f, 0.000438f, 0.000597f, 0.000538f, 0.000623f, 0.000638f, 0.000736f, 0.000866f, 0.000882f,
+ 0.000954f, 0.001040f, 0.001070f, 0.001086f, 0.001220f, 0.001274f, 0.001341f, 0.001457f, 0.001513f, 0.001598f, 0.001697f, 0.001781f,
+ 0.001898f, 0.001970f, 0.002131f, 0.002241f, 0.002401f, 0.002645f, 0.002783f, 0.002892f, 0.003120f, 0.003347f, 0.003508f, 0.003757f,
+ 0.004032f, 0.004314f, 0.004688f, 0.005066f, 0.005520f, 0.006012f, 0.006702f, 0.007332f, 0.008171f, 0.009140f, 0.010399f, 0.011787f,
+ 0.013496f, 0.015732f, 0.018509f, 0.022278f, 0.027267f, 0.033813f, 0.042328f, 0.053070f, 0.066406f, 0.082825f, 0.516602f, 0.562500f,
+ 0.573242f, 0.577637f, 0.580078f, 0.581543f, 0.000000f, 0.000216f, 0.000281f, 0.000346f, 0.000374f, 0.000388f, 0.000491f, 0.000416f,
+ 0.000516f, 0.000535f, 0.000635f, 0.000625f, 0.000681f, 0.000719f, 0.000790f, 0.000813f, 0.000879f, 0.000926f, 0.000968f, 0.001004f,
+ 0.001097f, 0.001135f, 0.001229f, 0.001300f, 0.001361f, 0.001431f, 0.001541f, 0.001610f, 0.001711f, 0.001802f, 0.001922f, 0.002094f,
+ 0.002169f, 0.002346f, 0.002468f, 0.002644f, 0.002844f, 0.003094f, 0.003368f, 0.003586f, 0.003883f, 0.004223f, 0.004662f, 0.005093f,
+ 0.005680f, 0.006348f, 0.007206f, 0.008202f, 0.009392f, 0.010895f, 0.012939f, 0.015465f, 0.018906f, 0.023682f, 0.030502f, 0.039825f,
+ 0.051331f, 0.066528f, 0.500977f, 0.548828f, 0.560059f, 0.564453f, 0.567871f, 0.569336f, 0.000000f, 0.000106f, 0.000201f, 0.000252f,
+ 0.000251f, 0.000322f, 0.000281f, 0.000340f, 0.000359f, 0.000428f, 0.000443f, 0.000419f, 0.000444f, 0.000500f, 0.000524f, 0.000590f,
+ 0.000574f, 0.000650f, 0.000693f, 0.000732f, 0.000778f, 0.000821f, 0.000848f, 0.000900f, 0.000965f, 0.000982f, 0.001072f, 0.001109f,
+ 0.001169f, 0.001307f, 0.001301f, 0.001409f, 0.001483f, 0.001610f, 0.001734f, 0.001835f, 0.001940f, 0.002098f, 0.002241f, 0.002426f,
+ 0.002634f, 0.002865f, 0.003136f, 0.003431f, 0.003763f, 0.004211f, 0.004742f, 0.005417f, 0.006229f, 0.007298f, 0.008621f, 0.010330f,
+ 0.012650f, 0.015808f, 0.020569f, 0.027908f, 0.037994f, 0.051514f, 0.485840f, 0.536133f, 0.547363f, 0.551758f, 0.554688f, 0.557617f,
+ 0.000026f, 0.000156f, 0.000201f, 0.000136f, 0.000188f, 0.000187f, 0.000192f, 0.000240f, 0.000245f, 0.000254f, 0.000262f, 0.000311f,
+ 0.000309f, 0.000331f, 0.000374f, 0.000385f, 0.000411f, 0.000431f, 0.000443f, 0.000461f, 0.000507f, 0.000522f, 0.000562f, 0.000596f,
+ 0.000634f, 0.000684f, 0.000718f, 0.000735f, 0.000776f, 0.000815f, 0.000875f, 0.000927f, 0.000982f, 0.001053f, 0.001123f, 0.001162f,
+ 0.001271f, 0.001346f, 0.001473f, 0.001577f, 0.001670f, 0.001838f, 0.002005f, 0.002161f, 0.002405f, 0.002670f, 0.002993f, 0.003399f,
+ 0.003860f, 0.004528f, 0.005386f, 0.006523f, 0.008003f, 0.010063f, 0.013206f, 0.017990f, 0.026031f, 0.038086f, 0.471191f, 0.522949f,
+ 0.534668f, 0.540039f, 0.543457f, 0.544922f, 0.000000f, 0.000093f, 0.000084f, 0.000085f, 0.000124f, 0.000145f, 0.000122f, 0.000149f,
+ 0.000152f, 0.000152f, 0.000158f, 0.000167f, 0.000186f, 0.000209f, 0.000217f, 0.000225f, 0.000231f, 0.000272f, 0.000273f, 0.000301f,
+ 0.000303f, 0.000310f, 0.000338f, 0.000361f, 0.000387f, 0.000423f, 0.000413f, 0.000436f, 0.000478f, 0.000503f, 0.000525f, 0.000570f,
+ 0.000608f, 0.000626f, 0.000677f, 0.000706f, 0.000753f, 0.000813f, 0.000884f, 0.000929f, 0.001000f, 0.001094f, 0.001183f, 0.001302f,
+ 0.001412f, 0.001563f, 0.001769f, 0.001974f, 0.002277f, 0.002626f, 0.003124f, 0.003761f, 0.004665f, 0.005993f, 0.007935f, 0.010818f,
+ 0.016205f, 0.026138f, 0.456299f, 0.509277f, 0.520996f, 0.527344f, 0.530762f, 0.532715f, 0.000105f, 0.000083f, 0.000072f, 0.000065f,
+ 0.000071f, 0.000072f, 0.000077f, 0.000084f, 0.000088f, 0.000093f, 0.000095f, 0.000120f, 0.000100f, 0.000108f, 0.000126f, 0.000118f,
+ 0.000139f, 0.000149f, 0.000153f, 0.000165f, 0.000169f, 0.000172f, 0.000194f, 0.000203f, 0.000233f, 0.000225f, 0.000233f, 0.000253f,
+ 0.000266f, 0.000275f, 0.000299f, 0.000319f, 0.000338f, 0.000345f, 0.000374f, 0.000384f, 0.000415f, 0.000448f, 0.000483f, 0.000511f,
+ 0.000543f, 0.000585f, 0.000647f, 0.000692f, 0.000755f, 0.000827f, 0.000924f, 0.001041f, 0.001186f, 0.001372f, 0.001608f, 0.001953f,
+ 0.002411f, 0.003098f, 0.004238f, 0.005989f, 0.009003f, 0.016006f, 0.441406f, 0.495361f, 0.508301f, 0.514160f, 0.518066f, 0.520508f,
+ 0.000090f, 0.000067f, 0.000058f, 0.000052f, 0.000047f, 0.000044f, 0.000044f, 0.000040f, 0.000042f, 0.000049f, 0.000042f, 0.000045f,
+ 0.000059f, 0.000047f, 0.000050f, 0.000054f, 0.000071f, 0.000073f, 0.000075f, 0.000078f, 0.000079f, 0.000084f, 0.000087f, 0.000090f,
+ 0.000097f, 0.000109f, 0.000108f, 0.000124f, 0.000124f, 0.000131f, 0.000138f, 0.000143f, 0.000155f, 0.000164f, 0.000178f, 0.000182f,
+ 0.000192f, 0.000209f, 0.000225f, 0.000244f, 0.000259f, 0.000274f, 0.000303f, 0.000321f, 0.000357f, 0.000385f, 0.000429f, 0.000470f,
+ 0.000537f, 0.000608f, 0.000710f, 0.000852f, 0.001052f, 0.001371f, 0.001877f, 0.002762f, 0.004406f, 0.008202f, 0.426270f, 0.483154f,
+ 0.495605f, 0.500977f, 0.505371f, 0.507324f, 0.000067f, 0.000047f, 0.000039f, 0.000035f, 0.000032f, 0.000030f, 0.000029f, 0.000027f,
+ 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000021f, 0.000020f, 0.000019f, 0.000021f, 0.000020f, 0.000024f, 0.000028f, 0.000030f,
+ 0.000029f, 0.000032f, 0.000035f, 0.000034f, 0.000036f, 0.000044f, 0.000046f, 0.000040f, 0.000048f, 0.000047f, 0.000051f, 0.000053f,
+ 0.000059f, 0.000059f, 0.000064f, 0.000066f, 0.000077f, 0.000079f, 0.000081f, 0.000091f, 0.000094f, 0.000100f, 0.000108f, 0.000119f,
+ 0.000129f, 0.000137f, 0.000148f, 0.000173f, 0.000191f, 0.000210f, 0.000249f, 0.000292f, 0.000357f, 0.000448f, 0.000629f, 0.000943f,
+ 0.001630f, 0.003332f, 0.411377f, 0.468506f, 0.482910f, 0.488770f, 0.492188f, 0.495117f, 0.000025f, 0.000018f, 0.000015f, 0.000013f,
+ 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f,
+ 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000008f, 0.000008f, 0.000007f,
+ 0.000008f, 0.000010f, 0.000010f, 0.000010f, 0.000012f, 0.000014f, 0.000014f, 0.000014f, 0.000016f, 0.000018f, 0.000019f, 0.000021f,
+ 0.000020f, 0.000023f, 0.000025f, 0.000027f, 0.000027f, 0.000029f, 0.000035f, 0.000033f, 0.000040f, 0.000044f, 0.000052f, 0.000061f,
+ 0.000069f, 0.000087f, 0.000117f, 0.000174f, 0.000319f, 0.000847f, 0.395996f, 0.454834f, 0.468750f, 0.475586f, 0.479004f, 0.481689f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f,
+ 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000004f, 0.000004f, 0.000005f, 0.000009f, 0.000027f, 0.381348f, 0.441406f,
+ 0.455566f, 0.462891f, 0.466309f, 0.468994f,
+ },
+ {
+ 0.016769f, 0.050629f, 0.083740f, 0.116638f, 0.148071f, 0.178955f, 0.208374f, 0.236938f, 0.265137f, 0.291992f, 0.317871f, 0.343994f,
+ 0.368164f, 0.391846f, 0.415527f, 0.437988f, 0.459717f, 0.480469f, 0.501465f, 0.520996f, 0.540527f, 0.559082f, 0.577637f, 0.594727f,
+ 0.612305f, 0.628418f, 0.644531f, 0.661133f, 0.676270f, 0.691406f, 0.705566f, 0.719727f, 0.734375f, 0.747070f, 0.760254f, 0.773438f,
+ 0.786133f, 0.798828f, 0.810059f, 0.821777f, 0.833008f, 0.843262f, 0.854492f, 0.865234f, 0.875488f, 0.885254f, 0.895508f, 0.904297f,
+ 0.913574f, 0.923340f, 0.932617f, 0.940918f, 0.949707f, 0.958008f, 0.966309f, 0.974609f, 0.981934f, 0.990234f, 0.985352f, 0.965332f,
+ 0.950195f, 0.937500f, 0.926270f, 0.915527f, 0.015083f, 0.045929f, 0.075806f, 0.105408f, 0.135254f, 0.163208f, 0.191772f, 0.219238f,
+ 0.245239f, 0.271973f, 0.297363f, 0.321045f, 0.345947f, 0.369141f, 0.391846f, 0.414062f, 0.435791f, 0.456787f, 0.477295f, 0.497314f,
+ 0.516113f, 0.535645f, 0.554199f, 0.571777f, 0.588867f, 0.606445f, 0.623047f, 0.639160f, 0.654785f, 0.669434f, 0.685059f, 0.699219f,
+ 0.713379f, 0.728027f, 0.741211f, 0.754883f, 0.767578f, 0.780273f, 0.792480f, 0.804688f, 0.815918f, 0.826660f, 0.838867f, 0.850098f,
+ 0.859863f, 0.871094f, 0.880859f, 0.891113f, 0.900879f, 0.909180f, 0.919434f, 0.929688f, 0.937500f, 0.946289f, 0.954590f, 0.963379f,
+ 0.971191f, 0.979004f, 0.980469f, 0.961426f, 0.947266f, 0.935059f, 0.924316f, 0.914062f, 0.013573f, 0.040955f, 0.068848f, 0.096313f,
+ 0.123169f, 0.150635f, 0.175537f, 0.202026f, 0.228271f, 0.251709f, 0.276367f, 0.300781f, 0.323730f, 0.347168f, 0.369385f, 0.390625f,
+ 0.412354f, 0.433594f, 0.454346f, 0.473145f, 0.491943f, 0.512207f, 0.529785f, 0.549316f, 0.566406f, 0.583008f, 0.600586f, 0.616211f,
+ 0.633301f, 0.648438f, 0.663574f, 0.679199f, 0.693359f, 0.708008f, 0.721680f, 0.735840f, 0.748535f, 0.762207f, 0.773926f, 0.786621f,
+ 0.798340f, 0.811035f, 0.822754f, 0.833984f, 0.845215f, 0.855957f, 0.865723f, 0.876465f, 0.886719f, 0.895508f, 0.906738f, 0.916016f,
+ 0.925293f, 0.934570f, 0.943848f, 0.952148f, 0.960449f, 0.969238f, 0.976074f, 0.958008f, 0.944336f, 0.932617f, 0.921875f, 0.912109f,
+ 0.012329f, 0.037201f, 0.062164f, 0.087646f, 0.112488f, 0.137451f, 0.161865f, 0.187134f, 0.210938f, 0.234253f, 0.258301f, 0.281006f,
+ 0.303467f, 0.325195f, 0.347656f, 0.368652f, 0.389648f, 0.410400f, 0.430664f, 0.450928f, 0.470215f, 0.488770f, 0.507812f, 0.525391f,
+ 0.543457f, 0.560059f, 0.579102f, 0.593750f, 0.611816f, 0.627441f, 0.643066f, 0.658203f, 0.672363f, 0.687500f, 0.702148f, 0.715820f,
+ 0.729004f, 0.742676f, 0.755371f, 0.768066f, 0.781738f, 0.792969f, 0.805176f, 0.816895f, 0.829102f, 0.839844f, 0.850586f, 0.861816f,
+ 0.872559f, 0.882812f, 0.893066f, 0.902832f, 0.912109f, 0.921875f, 0.930664f, 0.940430f, 0.948242f, 0.958008f, 0.970703f, 0.953613f,
+ 0.940430f, 0.929199f, 0.919434f, 0.910156f, 0.010979f, 0.033752f, 0.056763f, 0.080139f, 0.103516f, 0.126221f, 0.149414f, 0.172485f,
+ 0.195435f, 0.218262f, 0.240356f, 0.261719f, 0.284180f, 0.306396f, 0.326416f, 0.347900f, 0.368408f, 0.389160f, 0.408691f, 0.427979f,
+ 0.447754f, 0.467041f, 0.484863f, 0.502441f, 0.520996f, 0.538086f, 0.555664f, 0.573242f, 0.589355f, 0.604980f, 0.622559f, 0.637207f,
+ 0.652832f, 0.666992f, 0.680664f, 0.695801f, 0.710938f, 0.724121f, 0.737305f, 0.750977f, 0.763672f, 0.776855f, 0.789062f, 0.799805f,
+ 0.812012f, 0.824219f, 0.835449f, 0.846680f, 0.857910f, 0.868164f, 0.878418f, 0.889160f, 0.898926f, 0.909180f, 0.917969f, 0.928223f,
+ 0.937012f, 0.946777f, 0.965820f, 0.949707f, 0.937012f, 0.926270f, 0.916504f, 0.907715f, 0.009941f, 0.030746f, 0.051514f, 0.073181f,
+ 0.094116f, 0.116028f, 0.137817f, 0.158691f, 0.180664f, 0.202637f, 0.223511f, 0.244873f, 0.265869f, 0.285889f, 0.307129f, 0.327881f,
+ 0.347412f, 0.367188f, 0.387207f, 0.405762f, 0.425537f, 0.444092f, 0.462646f, 0.481201f, 0.499756f, 0.516602f, 0.533691f, 0.550781f,
+ 0.567383f, 0.583984f, 0.599609f, 0.616211f, 0.630859f, 0.647461f, 0.661621f, 0.676758f, 0.689453f, 0.704590f, 0.718750f, 0.731934f,
+ 0.745117f, 0.757812f, 0.770996f, 0.783691f, 0.796387f, 0.807617f, 0.819824f, 0.831543f, 0.842773f, 0.854004f, 0.864258f, 0.875488f,
+ 0.885742f, 0.895508f, 0.905762f, 0.915527f, 0.925781f, 0.934570f, 0.960449f, 0.945312f, 0.933594f, 0.922852f, 0.913574f, 0.905273f,
+ 0.009003f, 0.027756f, 0.046997f, 0.066711f, 0.085999f, 0.106506f, 0.127075f, 0.146973f, 0.166992f, 0.187500f, 0.207886f, 0.228149f,
+ 0.248169f, 0.268311f, 0.287842f, 0.307861f, 0.327393f, 0.347656f, 0.365967f, 0.385010f, 0.404541f, 0.422363f, 0.441162f, 0.458740f,
+ 0.477783f, 0.495117f, 0.512207f, 0.529297f, 0.546387f, 0.562012f, 0.578613f, 0.595215f, 0.610840f, 0.625977f, 0.641113f, 0.656738f,
+ 0.670410f, 0.685059f, 0.699707f, 0.714355f, 0.727051f, 0.741699f, 0.752441f, 0.767090f, 0.778809f, 0.791504f, 0.803711f, 0.815430f,
+ 0.827148f, 0.838867f, 0.850098f, 0.860840f, 0.872070f, 0.881836f, 0.893066f, 0.903809f, 0.913574f, 0.923828f, 0.955078f, 0.940918f,
+ 0.929199f, 0.919922f, 0.911133f, 0.902344f, 0.008469f, 0.025375f, 0.043121f, 0.060944f, 0.079468f, 0.097961f, 0.116394f, 0.135620f,
+ 0.154541f, 0.174072f, 0.193115f, 0.212280f, 0.231689f, 0.250732f, 0.270264f, 0.289307f, 0.307861f, 0.327148f, 0.345215f, 0.364990f,
+ 0.382812f, 0.401123f, 0.418945f, 0.437012f, 0.455811f, 0.472900f, 0.490234f, 0.507812f, 0.524414f, 0.541016f, 0.558105f, 0.573242f,
+ 0.590332f, 0.605469f, 0.620117f, 0.636230f, 0.651367f, 0.665039f, 0.679688f, 0.694336f, 0.708496f, 0.722168f, 0.735840f, 0.750000f,
+ 0.762695f, 0.774902f, 0.787598f, 0.798828f, 0.811523f, 0.823730f, 0.834473f, 0.846191f, 0.857910f, 0.868652f, 0.879883f, 0.891113f,
+ 0.900391f, 0.911133f, 0.949219f, 0.937012f, 0.925293f, 0.916016f, 0.907227f, 0.899414f, 0.007618f, 0.023178f, 0.039490f, 0.055542f,
+ 0.072937f, 0.090271f, 0.107605f, 0.125122f, 0.142944f, 0.160889f, 0.178955f, 0.197510f, 0.216553f, 0.234497f, 0.252686f, 0.271240f,
+ 0.289795f, 0.307861f, 0.326172f, 0.344238f, 0.362549f, 0.380859f, 0.398438f, 0.416504f, 0.433838f, 0.452393f, 0.468994f, 0.485840f,
+ 0.502930f, 0.519531f, 0.536133f, 0.553223f, 0.569336f, 0.584473f, 0.599609f, 0.615234f, 0.631348f, 0.646484f, 0.659668f, 0.675293f,
+ 0.689941f, 0.703125f, 0.716797f, 0.730957f, 0.744141f, 0.756836f, 0.771484f, 0.782227f, 0.795898f, 0.807617f, 0.819824f, 0.831543f,
+ 0.843750f, 0.854980f, 0.866211f, 0.877441f, 0.888672f, 0.898438f, 0.943359f, 0.931641f, 0.921387f, 0.912109f, 0.903809f, 0.896484f,
+ 0.007118f, 0.021255f, 0.035889f, 0.051514f, 0.066895f, 0.083191f, 0.098999f, 0.115540f, 0.132324f, 0.149292f, 0.166260f, 0.183716f,
+ 0.200928f, 0.218628f, 0.236084f, 0.253906f, 0.272217f, 0.289795f, 0.307617f, 0.325439f, 0.342529f, 0.360596f, 0.378906f, 0.395996f,
+ 0.413330f, 0.430908f, 0.447510f, 0.465332f, 0.481934f, 0.497803f, 0.514648f, 0.531738f, 0.547852f, 0.562988f, 0.579102f, 0.595215f,
+ 0.610840f, 0.625977f, 0.641113f, 0.655273f, 0.670410f, 0.685059f, 0.698730f, 0.712891f, 0.726074f, 0.739258f, 0.753418f, 0.766113f,
+ 0.779785f, 0.791992f, 0.803711f, 0.816406f, 0.829102f, 0.839844f, 0.852539f, 0.863770f, 0.874512f, 0.886719f, 0.937988f, 0.926758f,
+ 0.917480f, 0.908203f, 0.900391f, 0.893066f, 0.006481f, 0.019775f, 0.032928f, 0.047272f, 0.061371f, 0.076233f, 0.091064f, 0.107117f,
+ 0.122559f, 0.138062f, 0.154663f, 0.170532f, 0.187256f, 0.204346f, 0.220947f, 0.237915f, 0.254883f, 0.272217f, 0.289062f, 0.306641f,
+ 0.323730f, 0.341064f, 0.358643f, 0.375732f, 0.393555f, 0.410645f, 0.426758f, 0.444580f, 0.461182f, 0.477783f, 0.494141f, 0.510254f,
+ 0.526855f, 0.543457f, 0.559082f, 0.574219f, 0.590332f, 0.605957f, 0.621094f, 0.634766f, 0.650879f, 0.665039f, 0.679688f, 0.694824f,
+ 0.708008f, 0.722656f, 0.736816f, 0.749023f, 0.762695f, 0.775391f, 0.788086f, 0.801270f, 0.813965f, 0.826172f, 0.838379f, 0.849121f,
+ 0.861328f, 0.873535f, 0.932129f, 0.921875f, 0.912598f, 0.904297f, 0.896484f, 0.889160f, 0.005924f, 0.017899f, 0.030426f, 0.043427f,
+ 0.056824f, 0.070435f, 0.084106f, 0.098755f, 0.112976f, 0.128052f, 0.143311f, 0.158936f, 0.174072f, 0.189575f, 0.206421f, 0.222534f,
+ 0.238403f, 0.255615f, 0.271729f, 0.288818f, 0.305908f, 0.322021f, 0.339355f, 0.356445f, 0.373291f, 0.390137f, 0.407227f, 0.423584f,
+ 0.440430f, 0.457031f, 0.472900f, 0.489502f, 0.506836f, 0.521973f, 0.538574f, 0.554688f, 0.570312f, 0.585449f, 0.601074f, 0.616211f,
+ 0.631348f, 0.646484f, 0.661621f, 0.675781f, 0.690430f, 0.704590f, 0.717285f, 0.731934f, 0.746094f, 0.759277f, 0.771973f, 0.785156f,
+ 0.798340f, 0.810547f, 0.823242f, 0.835938f, 0.848145f, 0.860352f, 0.925781f, 0.916504f, 0.908203f, 0.900391f, 0.893066f, 0.886719f,
+ 0.005573f, 0.016693f, 0.028366f, 0.040192f, 0.052277f, 0.064880f, 0.078064f, 0.090698f, 0.105042f, 0.118591f, 0.133057f, 0.147461f,
+ 0.162231f, 0.177612f, 0.192383f, 0.207886f, 0.223633f, 0.239502f, 0.255615f, 0.272217f, 0.288330f, 0.304932f, 0.320312f, 0.337646f,
+ 0.354004f, 0.369873f, 0.386719f, 0.403320f, 0.419922f, 0.437012f, 0.453369f, 0.469482f, 0.485596f, 0.501465f, 0.517578f, 0.534180f,
+ 0.549316f, 0.565918f, 0.581055f, 0.595703f, 0.611328f, 0.626953f, 0.641602f, 0.657227f, 0.671387f, 0.686523f, 0.699707f, 0.714355f,
+ 0.729004f, 0.742676f, 0.756348f, 0.769043f, 0.782715f, 0.795410f, 0.809082f, 0.821289f, 0.833984f, 0.846680f, 0.919434f, 0.911133f,
+ 0.903320f, 0.895508f, 0.888672f, 0.882324f, 0.005016f, 0.015396f, 0.026169f, 0.037231f, 0.048126f, 0.059937f, 0.071716f, 0.084167f,
+ 0.096680f, 0.109558f, 0.123169f, 0.136719f, 0.150269f, 0.164917f, 0.179077f, 0.194580f, 0.208984f, 0.223877f, 0.239746f, 0.255127f,
+ 0.270996f, 0.286377f, 0.302490f, 0.319336f, 0.335205f, 0.351318f, 0.367432f, 0.383545f, 0.399902f, 0.415771f, 0.432373f, 0.448975f,
+ 0.465088f, 0.481934f, 0.497314f, 0.513672f, 0.529785f, 0.544434f, 0.561035f, 0.576660f, 0.592285f, 0.607422f, 0.622559f, 0.638184f,
+ 0.652344f, 0.667480f, 0.681641f, 0.696777f, 0.711426f, 0.725586f, 0.738770f, 0.753418f, 0.766602f, 0.779297f, 0.793945f, 0.807129f,
+ 0.819824f, 0.833008f, 0.913086f, 0.906738f, 0.898438f, 0.890625f, 0.884277f, 0.878418f, 0.004738f, 0.014053f, 0.024017f, 0.033752f,
+ 0.044495f, 0.055328f, 0.066467f, 0.078064f, 0.089661f, 0.102051f, 0.114258f, 0.126831f, 0.139771f, 0.153564f, 0.167114f, 0.181030f,
+ 0.195190f, 0.209839f, 0.224731f, 0.239136f, 0.253906f, 0.269531f, 0.285156f, 0.300293f, 0.317139f, 0.332520f, 0.348145f, 0.364990f,
+ 0.380859f, 0.396240f, 0.412109f, 0.428711f, 0.444336f, 0.460938f, 0.477295f, 0.492676f, 0.509277f, 0.524902f, 0.540527f, 0.556641f,
+ 0.572266f, 0.587402f, 0.604004f, 0.618164f, 0.633301f, 0.648438f, 0.664062f, 0.678223f, 0.693359f, 0.708008f, 0.722656f, 0.736328f,
+ 0.750000f, 0.764160f, 0.777832f, 0.791016f, 0.805176f, 0.817871f, 0.907227f, 0.900879f, 0.894043f, 0.886719f, 0.880371f, 0.874512f,
+ 0.004105f, 0.012741f, 0.022491f, 0.031769f, 0.041107f, 0.051208f, 0.061249f, 0.071777f, 0.083069f, 0.093811f, 0.105896f, 0.117554f,
+ 0.129761f, 0.142212f, 0.155273f, 0.168579f, 0.182251f, 0.196167f, 0.210449f, 0.223755f, 0.238525f, 0.253662f, 0.268799f, 0.283447f,
+ 0.298828f, 0.313965f, 0.329834f, 0.344971f, 0.361328f, 0.376953f, 0.393066f, 0.408691f, 0.424561f, 0.441406f, 0.457031f, 0.472656f,
+ 0.488770f, 0.504883f, 0.520996f, 0.536133f, 0.551758f, 0.567871f, 0.583496f, 0.599121f, 0.614258f, 0.629395f, 0.645996f, 0.660156f,
+ 0.675781f, 0.689453f, 0.704102f, 0.719727f, 0.733398f, 0.747559f, 0.761719f, 0.776367f, 0.789062f, 0.803223f, 0.899902f, 0.895020f,
+ 0.888184f, 0.881836f, 0.875488f, 0.870117f, 0.003925f, 0.011978f, 0.020538f, 0.028763f, 0.038269f, 0.047028f, 0.056732f, 0.066223f,
+ 0.076904f, 0.086731f, 0.097900f, 0.109314f, 0.120483f, 0.132324f, 0.144653f, 0.156982f, 0.169678f, 0.183228f, 0.196289f, 0.209961f,
+ 0.223633f, 0.237427f, 0.251953f, 0.266602f, 0.281982f, 0.296875f, 0.312012f, 0.326660f, 0.342041f, 0.357910f, 0.373779f, 0.389404f,
+ 0.404785f, 0.420166f, 0.436768f, 0.452637f, 0.468506f, 0.484863f, 0.500977f, 0.516602f, 0.531738f, 0.546875f, 0.563965f, 0.579102f,
+ 0.595215f, 0.610840f, 0.625977f, 0.641602f, 0.657227f, 0.671387f, 0.687500f, 0.702148f, 0.716309f, 0.731445f, 0.746094f, 0.760742f,
+ 0.774414f, 0.788086f, 0.893066f, 0.889648f, 0.882812f, 0.876953f, 0.870605f, 0.865723f, 0.003704f, 0.011169f, 0.019165f, 0.026550f,
+ 0.035339f, 0.043488f, 0.052277f, 0.061066f, 0.071045f, 0.080933f, 0.090576f, 0.101074f, 0.111877f, 0.122925f, 0.134277f, 0.146118f,
+ 0.157837f, 0.170288f, 0.183105f, 0.195557f, 0.209351f, 0.222900f, 0.236328f, 0.250732f, 0.264893f, 0.279297f, 0.294189f, 0.308838f,
+ 0.323975f, 0.339844f, 0.354736f, 0.370117f, 0.385986f, 0.401367f, 0.416504f, 0.432861f, 0.448486f, 0.463867f, 0.480469f, 0.497070f,
+ 0.511719f, 0.527832f, 0.544434f, 0.559570f, 0.575684f, 0.591797f, 0.606934f, 0.623047f, 0.638184f, 0.654297f, 0.668945f, 0.684570f,
+ 0.699219f, 0.714355f, 0.729492f, 0.744629f, 0.758789f, 0.773926f, 0.886230f, 0.883301f, 0.877441f, 0.871582f, 0.866211f, 0.860840f,
+ 0.003500f, 0.010292f, 0.017395f, 0.024963f, 0.032440f, 0.040344f, 0.048462f, 0.057098f, 0.065063f, 0.074646f, 0.083679f, 0.093445f,
+ 0.103882f, 0.114136f, 0.124451f, 0.135498f, 0.146606f, 0.158447f, 0.170410f, 0.182739f, 0.195435f, 0.208008f, 0.221558f, 0.234863f,
+ 0.248657f, 0.262695f, 0.276855f, 0.291748f, 0.306152f, 0.320801f, 0.335693f, 0.350830f, 0.365967f, 0.382080f, 0.396973f, 0.413330f,
+ 0.429199f, 0.444336f, 0.459473f, 0.476074f, 0.492188f, 0.507812f, 0.524414f, 0.540039f, 0.555664f, 0.571777f, 0.586914f, 0.604004f,
+ 0.619629f, 0.635742f, 0.650391f, 0.666504f, 0.682129f, 0.697754f, 0.712891f, 0.728027f, 0.743164f, 0.758301f, 0.878906f, 0.877441f,
+ 0.871582f, 0.866699f, 0.860840f, 0.856445f, 0.003084f, 0.009697f, 0.016403f, 0.022659f, 0.029892f, 0.037354f, 0.044281f, 0.052338f,
+ 0.060516f, 0.068970f, 0.077515f, 0.086243f, 0.096069f, 0.105713f, 0.115356f, 0.125610f, 0.136353f, 0.147339f, 0.158081f, 0.170410f,
+ 0.181396f, 0.194458f, 0.207275f, 0.219482f, 0.232910f, 0.246704f, 0.260010f, 0.274170f, 0.288330f, 0.302979f, 0.317383f, 0.332764f,
+ 0.347656f, 0.363037f, 0.378174f, 0.392578f, 0.408936f, 0.424316f, 0.440430f, 0.456299f, 0.472656f, 0.488525f, 0.503906f, 0.519531f,
+ 0.535645f, 0.552734f, 0.568359f, 0.584961f, 0.600586f, 0.616699f, 0.633301f, 0.648438f, 0.663574f, 0.679199f, 0.694824f, 0.710938f,
+ 0.726074f, 0.742188f, 0.872559f, 0.870605f, 0.865723f, 0.860840f, 0.855957f, 0.851074f, 0.002913f, 0.008781f, 0.014938f, 0.021759f,
+ 0.027878f, 0.034393f, 0.041412f, 0.048737f, 0.055969f, 0.063599f, 0.072021f, 0.080200f, 0.088928f, 0.097839f, 0.106934f, 0.116150f,
+ 0.126587f, 0.136353f, 0.147095f, 0.157715f, 0.169189f, 0.181519f, 0.193481f, 0.205933f, 0.217773f, 0.231323f, 0.244629f, 0.257812f,
+ 0.271240f, 0.285400f, 0.299561f, 0.314453f, 0.329590f, 0.343506f, 0.358887f, 0.373779f, 0.389648f, 0.405029f, 0.420410f, 0.437012f,
+ 0.452393f, 0.468262f, 0.484375f, 0.500000f, 0.516113f, 0.532227f, 0.548828f, 0.564941f, 0.581055f, 0.597168f, 0.612793f, 0.629883f,
+ 0.645508f, 0.662109f, 0.678223f, 0.694336f, 0.709473f, 0.726074f, 0.863770f, 0.864258f, 0.859863f, 0.854980f, 0.850586f, 0.846191f,
+ 0.002815f, 0.008194f, 0.013954f, 0.019653f, 0.025696f, 0.031982f, 0.038177f, 0.044830f, 0.051819f, 0.058502f, 0.066162f, 0.073792f,
+ 0.082031f, 0.090393f, 0.098999f, 0.107605f, 0.117493f, 0.126709f, 0.137207f, 0.146729f, 0.157593f, 0.168579f, 0.179810f, 0.191772f,
+ 0.203369f, 0.215820f, 0.228882f, 0.241455f, 0.254395f, 0.268311f, 0.282227f, 0.296631f, 0.310303f, 0.325439f, 0.339844f, 0.354736f,
+ 0.370361f, 0.385742f, 0.400879f, 0.416504f, 0.432617f, 0.448486f, 0.464355f, 0.479980f, 0.496094f, 0.513184f, 0.528809f, 0.545410f,
+ 0.561035f, 0.578613f, 0.594727f, 0.611328f, 0.626953f, 0.643555f, 0.660156f, 0.676270f, 0.693359f, 0.709473f, 0.856445f, 0.858398f,
+ 0.854492f, 0.849121f, 0.845215f, 0.841309f, 0.002583f, 0.007492f, 0.012878f, 0.018417f, 0.023941f, 0.029495f, 0.035339f, 0.041779f,
+ 0.047577f, 0.054047f, 0.061523f, 0.068787f, 0.075562f, 0.083313f, 0.091858f, 0.099792f, 0.108521f, 0.117615f, 0.126709f, 0.136108f,
+ 0.146851f, 0.156860f, 0.166992f, 0.178345f, 0.189819f, 0.202148f, 0.213623f, 0.225830f, 0.238892f, 0.252197f, 0.265137f, 0.278809f,
+ 0.292480f, 0.306885f, 0.321045f, 0.336914f, 0.350830f, 0.366943f, 0.381348f, 0.396240f, 0.412354f, 0.428223f, 0.444336f, 0.460449f,
+ 0.476318f, 0.493408f, 0.509277f, 0.525879f, 0.542480f, 0.559082f, 0.574707f, 0.591797f, 0.608398f, 0.625488f, 0.642090f, 0.659180f,
+ 0.675781f, 0.691406f, 0.848145f, 0.851562f, 0.848145f, 0.843750f, 0.838867f, 0.835449f, 0.002512f, 0.007374f, 0.012115f, 0.016983f,
+ 0.022064f, 0.027359f, 0.032715f, 0.038147f, 0.044373f, 0.050354f, 0.056641f, 0.063293f, 0.070190f, 0.077026f, 0.084717f, 0.092041f,
+ 0.100342f, 0.108398f, 0.117554f, 0.126221f, 0.135742f, 0.145142f, 0.155151f, 0.165771f, 0.176758f, 0.187988f, 0.199341f, 0.210815f,
+ 0.223389f, 0.236206f, 0.249023f, 0.261719f, 0.275879f, 0.289062f, 0.303467f, 0.317627f, 0.332520f, 0.347412f, 0.361816f, 0.377197f,
+ 0.393066f, 0.407959f, 0.424072f, 0.440186f, 0.457031f, 0.473145f, 0.489502f, 0.505859f, 0.522461f, 0.540039f, 0.555664f, 0.572754f,
+ 0.589844f, 0.606445f, 0.623535f, 0.640625f, 0.658203f, 0.675781f, 0.840820f, 0.843750f, 0.841309f, 0.836914f, 0.833984f, 0.830566f,
+ 0.002369f, 0.006668f, 0.011093f, 0.015778f, 0.020523f, 0.025223f, 0.030701f, 0.035339f, 0.040710f, 0.046600f, 0.051971f, 0.058075f,
+ 0.064819f, 0.071228f, 0.077942f, 0.085205f, 0.092224f, 0.100464f, 0.108398f, 0.116882f, 0.125610f, 0.134155f, 0.143555f, 0.153564f,
+ 0.164062f, 0.174316f, 0.185303f, 0.196899f, 0.208496f, 0.220093f, 0.232666f, 0.245239f, 0.258057f, 0.271729f, 0.285645f, 0.299561f,
+ 0.313721f, 0.328613f, 0.342773f, 0.358154f, 0.373535f, 0.388916f, 0.405518f, 0.419922f, 0.437012f, 0.453125f, 0.469238f, 0.486328f,
+ 0.502930f, 0.519531f, 0.536133f, 0.553223f, 0.571289f, 0.588379f, 0.605469f, 0.623047f, 0.640137f, 0.656250f, 0.833008f, 0.837402f,
+ 0.834473f, 0.831055f, 0.827637f, 0.824219f, 0.002188f, 0.006027f, 0.010582f, 0.014297f, 0.018921f, 0.023270f, 0.028183f, 0.032593f,
+ 0.037781f, 0.042999f, 0.048584f, 0.053650f, 0.059601f, 0.065369f, 0.071899f, 0.078369f, 0.085449f, 0.092407f, 0.099609f, 0.107788f,
+ 0.115601f, 0.124451f, 0.133301f, 0.142212f, 0.151978f, 0.161865f, 0.172363f, 0.182617f, 0.193970f, 0.205566f, 0.217407f, 0.229858f,
+ 0.241943f, 0.254639f, 0.268311f, 0.281494f, 0.295654f, 0.310059f, 0.324219f, 0.339600f, 0.353760f, 0.369629f, 0.385010f, 0.400879f,
+ 0.417725f, 0.433594f, 0.449219f, 0.465820f, 0.482910f, 0.499512f, 0.517090f, 0.534180f, 0.551270f, 0.568848f, 0.586426f, 0.604004f,
+ 0.622559f, 0.639160f, 0.824219f, 0.830078f, 0.827637f, 0.824707f, 0.821777f, 0.818359f, 0.002098f, 0.005634f, 0.009354f, 0.013557f,
+ 0.017685f, 0.021576f, 0.025604f, 0.030380f, 0.034943f, 0.039429f, 0.044281f, 0.049255f, 0.055023f, 0.060577f, 0.066101f, 0.072144f,
+ 0.078491f, 0.085083f, 0.091858f, 0.098999f, 0.106873f, 0.114502f, 0.122498f, 0.131592f, 0.140137f, 0.149536f, 0.159424f, 0.169556f,
+ 0.180054f, 0.191162f, 0.202026f, 0.213989f, 0.226318f, 0.239136f, 0.250977f, 0.264648f, 0.278320f, 0.291748f, 0.305908f, 0.320557f,
+ 0.334961f, 0.350342f, 0.365479f, 0.381592f, 0.397461f, 0.413818f, 0.429199f, 0.446289f, 0.462891f, 0.479736f, 0.496338f, 0.514160f,
+ 0.530762f, 0.548828f, 0.566406f, 0.584473f, 0.602539f, 0.621582f, 0.815918f, 0.823730f, 0.821289f, 0.817871f, 0.815430f, 0.812500f,
+ 0.001772f, 0.005249f, 0.008995f, 0.012260f, 0.016251f, 0.020020f, 0.024216f, 0.027603f, 0.032196f, 0.036377f, 0.041199f, 0.045410f,
+ 0.050110f, 0.055603f, 0.061005f, 0.066406f, 0.072327f, 0.077820f, 0.084290f, 0.090942f, 0.098083f, 0.105164f, 0.113037f, 0.120789f,
+ 0.129272f, 0.138062f, 0.147339f, 0.156982f, 0.166626f, 0.176758f, 0.187866f, 0.199097f, 0.210449f, 0.222412f, 0.234985f, 0.247559f,
+ 0.260742f, 0.273682f, 0.287598f, 0.302002f, 0.316650f, 0.331299f, 0.346191f, 0.362061f, 0.377686f, 0.393066f, 0.409668f, 0.426514f,
+ 0.443115f, 0.459717f, 0.476807f, 0.494629f, 0.511230f, 0.529785f, 0.547852f, 0.565430f, 0.583984f, 0.602539f, 0.806152f, 0.814453f,
+ 0.813965f, 0.811035f, 0.809082f, 0.806641f, 0.001631f, 0.005131f, 0.008186f, 0.011673f, 0.014938f, 0.018463f, 0.021957f, 0.025635f,
+ 0.029083f, 0.033325f, 0.037445f, 0.041840f, 0.046478f, 0.050751f, 0.055634f, 0.060760f, 0.065979f, 0.071472f, 0.077515f, 0.083801f,
+ 0.090027f, 0.096802f, 0.104065f, 0.110840f, 0.119080f, 0.127197f, 0.135498f, 0.144775f, 0.153931f, 0.163574f, 0.173462f, 0.184570f,
+ 0.195312f, 0.207153f, 0.218506f, 0.230591f, 0.243652f, 0.256348f, 0.270020f, 0.283691f, 0.297852f, 0.312744f, 0.326904f, 0.342529f,
+ 0.357910f, 0.373535f, 0.389404f, 0.406494f, 0.421875f, 0.439941f, 0.457275f, 0.474365f, 0.492432f, 0.509766f, 0.527832f, 0.546875f,
+ 0.564941f, 0.584473f, 0.797852f, 0.807129f, 0.807129f, 0.804199f, 0.801758f, 0.799316f, 0.001632f, 0.004704f, 0.007912f, 0.010788f,
+ 0.013870f, 0.017105f, 0.020187f, 0.023483f, 0.026932f, 0.030563f, 0.034332f, 0.038086f, 0.042694f, 0.046631f, 0.050995f, 0.055725f,
+ 0.060486f, 0.065674f, 0.070862f, 0.076721f, 0.082825f, 0.088623f, 0.094910f, 0.102112f, 0.109070f, 0.116516f, 0.124695f, 0.133057f,
+ 0.141968f, 0.151001f, 0.160522f, 0.170776f, 0.181030f, 0.191650f, 0.202881f, 0.214722f, 0.227417f, 0.239624f, 0.252686f, 0.265625f,
+ 0.279785f, 0.293213f, 0.308350f, 0.323242f, 0.338867f, 0.354248f, 0.370117f, 0.386475f, 0.403076f, 0.420410f, 0.437012f, 0.454102f,
+ 0.471924f, 0.490234f, 0.508789f, 0.526855f, 0.545410f, 0.564453f, 0.788086f, 0.799316f, 0.798828f, 0.797852f, 0.794434f, 0.791992f,
+ 0.001594f, 0.004177f, 0.007122f, 0.010201f, 0.012344f, 0.015839f, 0.018372f, 0.021683f, 0.024857f, 0.028534f, 0.031464f, 0.035034f,
+ 0.038879f, 0.042572f, 0.046295f, 0.051056f, 0.055389f, 0.059723f, 0.064697f, 0.069763f, 0.075073f, 0.080750f, 0.087219f, 0.093445f,
+ 0.099548f, 0.107056f, 0.114136f, 0.121887f, 0.130249f, 0.138794f, 0.147217f, 0.157104f, 0.166748f, 0.177124f, 0.187988f, 0.199097f,
+ 0.210693f, 0.222778f, 0.235352f, 0.248169f, 0.261719f, 0.275635f, 0.289062f, 0.303955f, 0.319336f, 0.334717f, 0.350098f, 0.365479f,
+ 0.382324f, 0.398926f, 0.416016f, 0.433594f, 0.451904f, 0.469238f, 0.487549f, 0.506348f, 0.525391f, 0.544922f, 0.779297f, 0.791504f,
+ 0.791504f, 0.789551f, 0.788086f, 0.786133f, 0.001365f, 0.004173f, 0.006222f, 0.008842f, 0.011703f, 0.014366f, 0.017242f, 0.020218f,
+ 0.022903f, 0.025787f, 0.028824f, 0.032227f, 0.035522f, 0.038818f, 0.042511f, 0.046326f, 0.050507f, 0.054657f, 0.058594f, 0.063660f,
+ 0.068359f, 0.073914f, 0.078918f, 0.085083f, 0.091125f, 0.097534f, 0.104126f, 0.111511f, 0.118896f, 0.126831f, 0.135742f, 0.144043f,
+ 0.153564f, 0.163330f, 0.173462f, 0.184082f, 0.195068f, 0.206787f, 0.218628f, 0.231079f, 0.243896f, 0.257080f, 0.270996f, 0.285645f,
+ 0.300049f, 0.314941f, 0.330322f, 0.346191f, 0.362305f, 0.379395f, 0.395508f, 0.412842f, 0.431641f, 0.448975f, 0.468262f, 0.487549f,
+ 0.505371f, 0.525391f, 0.769531f, 0.783691f, 0.783691f, 0.782715f, 0.781250f, 0.778809f, 0.001230f, 0.003925f, 0.006268f, 0.008659f,
+ 0.010796f, 0.013145f, 0.015617f, 0.018234f, 0.021133f, 0.023682f, 0.026215f, 0.029251f, 0.032349f, 0.035400f, 0.038696f, 0.042206f,
+ 0.045807f, 0.049377f, 0.053925f, 0.057953f, 0.062500f, 0.067078f, 0.071777f, 0.077271f, 0.082703f, 0.088806f, 0.094910f, 0.101379f,
+ 0.109192f, 0.115967f, 0.123779f, 0.131470f, 0.140259f, 0.149536f, 0.159302f, 0.169312f, 0.180054f, 0.190674f, 0.202515f, 0.214722f,
+ 0.226562f, 0.239624f, 0.253174f, 0.266602f, 0.281738f, 0.295898f, 0.311035f, 0.326904f, 0.342529f, 0.359131f, 0.375732f, 0.393066f,
+ 0.410400f, 0.428467f, 0.447510f, 0.466064f, 0.485596f, 0.504883f, 0.759277f, 0.774902f, 0.775879f, 0.774902f, 0.773438f, 0.771973f,
+ 0.001031f, 0.003601f, 0.005604f, 0.007858f, 0.009880f, 0.012146f, 0.014549f, 0.016998f, 0.019043f, 0.021362f, 0.024475f, 0.026566f,
+ 0.029358f, 0.032196f, 0.035248f, 0.038391f, 0.041656f, 0.045044f, 0.048553f, 0.052582f, 0.056213f, 0.060669f, 0.065186f, 0.070068f,
+ 0.074768f, 0.080322f, 0.086060f, 0.092102f, 0.098877f, 0.105408f, 0.112366f, 0.120239f, 0.128540f, 0.136597f, 0.145874f, 0.155396f,
+ 0.165283f, 0.175537f, 0.186401f, 0.198120f, 0.210083f, 0.222534f, 0.235229f, 0.248657f, 0.262451f, 0.277344f, 0.291504f, 0.307617f,
+ 0.322998f, 0.339111f, 0.354980f, 0.372559f, 0.390625f, 0.408936f, 0.426758f, 0.445312f, 0.466064f, 0.485840f, 0.749512f, 0.765137f,
+ 0.767578f, 0.767090f, 0.765137f, 0.764648f, 0.001161f, 0.003078f, 0.005310f, 0.007282f, 0.009201f, 0.011330f, 0.013214f, 0.015404f,
+ 0.017273f, 0.019409f, 0.021988f, 0.024078f, 0.026550f, 0.029358f, 0.032043f, 0.034454f, 0.037415f, 0.040710f, 0.043854f, 0.047272f,
+ 0.050659f, 0.054840f, 0.058777f, 0.063293f, 0.067566f, 0.072449f, 0.077759f, 0.083069f, 0.088928f, 0.095886f, 0.102478f, 0.109070f,
+ 0.116760f, 0.124390f, 0.132935f, 0.141479f, 0.151123f, 0.161011f, 0.171143f, 0.182007f, 0.193726f, 0.205688f, 0.218018f, 0.230835f,
+ 0.244507f, 0.258789f, 0.272949f, 0.287109f, 0.303467f, 0.319336f, 0.335449f, 0.352539f, 0.369873f, 0.387939f, 0.406250f, 0.425049f,
+ 0.444824f, 0.464844f, 0.739258f, 0.756348f, 0.758789f, 0.758789f, 0.757324f, 0.756836f, 0.001004f, 0.002939f, 0.005005f, 0.006779f,
+ 0.008453f, 0.010323f, 0.012177f, 0.013870f, 0.016052f, 0.018051f, 0.019638f, 0.022141f, 0.023956f, 0.026413f, 0.028870f, 0.031281f,
+ 0.033661f, 0.036591f, 0.039429f, 0.042542f, 0.045776f, 0.049011f, 0.053009f, 0.056885f, 0.061035f, 0.065186f, 0.069885f, 0.075134f,
+ 0.080505f, 0.085999f, 0.091858f, 0.098633f, 0.105591f, 0.112732f, 0.120667f, 0.128662f, 0.137573f, 0.146729f, 0.156372f, 0.166748f,
+ 0.177490f, 0.189331f, 0.201294f, 0.213501f, 0.226807f, 0.239746f, 0.254150f, 0.268555f, 0.283936f, 0.298828f, 0.316162f, 0.332275f,
+ 0.349609f, 0.367432f, 0.385498f, 0.404053f, 0.423828f, 0.443848f, 0.728516f, 0.747559f, 0.750488f, 0.750488f, 0.749512f, 0.748047f,
+ 0.000970f, 0.002523f, 0.004665f, 0.006203f, 0.007759f, 0.009491f, 0.011070f, 0.012802f, 0.014336f, 0.016266f, 0.017944f, 0.019852f,
+ 0.021805f, 0.023911f, 0.025818f, 0.028137f, 0.030579f, 0.032837f, 0.035248f, 0.038055f, 0.041046f, 0.044189f, 0.047333f, 0.050842f,
+ 0.054504f, 0.058502f, 0.062866f, 0.067383f, 0.071960f, 0.077393f, 0.082642f, 0.088928f, 0.095093f, 0.101685f, 0.108765f, 0.116272f,
+ 0.124451f, 0.133423f, 0.142212f, 0.152100f, 0.162354f, 0.172729f, 0.184692f, 0.196411f, 0.209106f, 0.221802f, 0.235718f, 0.250000f,
+ 0.265137f, 0.280029f, 0.296143f, 0.312012f, 0.329346f, 0.346924f, 0.364990f, 0.384277f, 0.403564f, 0.423340f, 0.718262f, 0.738770f,
+ 0.741211f, 0.742188f, 0.741211f, 0.740234f, 0.000785f, 0.002600f, 0.004028f, 0.005390f, 0.007275f, 0.008774f, 0.010124f, 0.011620f,
+ 0.013306f, 0.014427f, 0.015991f, 0.017838f, 0.019577f, 0.021469f, 0.023254f, 0.024902f, 0.027115f, 0.029190f, 0.031677f, 0.034088f,
+ 0.036682f, 0.039307f, 0.042175f, 0.045410f, 0.048553f, 0.052002f, 0.055908f, 0.060028f, 0.064270f, 0.068909f, 0.074097f, 0.079163f,
+ 0.085022f, 0.091309f, 0.097473f, 0.104797f, 0.112183f, 0.120239f, 0.128662f, 0.137451f, 0.146973f, 0.157471f, 0.168213f, 0.179810f,
+ 0.191650f, 0.204468f, 0.217529f, 0.231201f, 0.245605f, 0.260254f, 0.275879f, 0.292236f, 0.308838f, 0.326416f, 0.344238f, 0.363037f,
+ 0.382080f, 0.403076f, 0.707031f, 0.729980f, 0.732422f, 0.733398f, 0.733398f, 0.732910f, 0.000775f, 0.002190f, 0.003696f, 0.005081f,
+ 0.006397f, 0.007858f, 0.009239f, 0.010323f, 0.011803f, 0.012978f, 0.014328f, 0.015915f, 0.017349f, 0.019058f, 0.020630f, 0.022339f,
+ 0.024445f, 0.025909f, 0.028275f, 0.030151f, 0.032532f, 0.035065f, 0.037476f, 0.040283f, 0.042969f, 0.046448f, 0.049469f, 0.053314f,
+ 0.056976f, 0.061371f, 0.065613f, 0.070435f, 0.075623f, 0.081360f, 0.087341f, 0.093628f, 0.100220f, 0.107788f, 0.115845f, 0.123901f,
+ 0.133057f, 0.142456f, 0.152832f, 0.163574f, 0.174561f, 0.187012f, 0.199463f, 0.212646f, 0.226562f, 0.241455f, 0.256836f, 0.272705f,
+ 0.288818f, 0.305664f, 0.323486f, 0.341797f, 0.362305f, 0.382080f, 0.695312f, 0.719238f, 0.722656f, 0.724121f, 0.724121f, 0.723633f,
+ 0.000906f, 0.002022f, 0.003521f, 0.004963f, 0.005756f, 0.006847f, 0.008446f, 0.009392f, 0.010437f, 0.012039f, 0.012863f, 0.014343f,
+ 0.015457f, 0.016876f, 0.018295f, 0.019730f, 0.021484f, 0.023102f, 0.024689f, 0.026581f, 0.028717f, 0.030945f, 0.032928f, 0.035370f,
+ 0.037872f, 0.040894f, 0.043915f, 0.047028f, 0.050415f, 0.054169f, 0.058167f, 0.062286f, 0.067078f, 0.071960f, 0.077209f, 0.082947f,
+ 0.089417f, 0.096008f, 0.103271f, 0.110718f, 0.119324f, 0.128052f, 0.137817f, 0.147705f, 0.158691f, 0.169922f, 0.181519f, 0.195435f,
+ 0.208496f, 0.222534f, 0.237305f, 0.252441f, 0.268799f, 0.285645f, 0.302979f, 0.322266f, 0.340332f, 0.360840f, 0.683594f, 0.708984f,
+ 0.714355f, 0.715332f, 0.715820f, 0.715332f, 0.000700f, 0.002043f, 0.003139f, 0.004219f, 0.005417f, 0.006477f, 0.007442f, 0.008415f,
+ 0.009499f, 0.010475f, 0.011497f, 0.012619f, 0.013824f, 0.014969f, 0.016190f, 0.017639f, 0.018799f, 0.020386f, 0.021896f, 0.023560f,
+ 0.025131f, 0.027176f, 0.028900f, 0.031067f, 0.033295f, 0.035919f, 0.038239f, 0.041229f, 0.044373f, 0.047394f, 0.050934f, 0.054871f,
+ 0.058838f, 0.063293f, 0.068115f, 0.073303f, 0.078857f, 0.084839f, 0.091309f, 0.098328f, 0.106079f, 0.114136f, 0.123230f, 0.132690f,
+ 0.143066f, 0.153442f, 0.165161f, 0.177368f, 0.190186f, 0.203979f, 0.218262f, 0.232910f, 0.248901f, 0.265381f, 0.282227f, 0.301025f,
+ 0.319580f, 0.339355f, 0.672852f, 0.699707f, 0.704590f, 0.706055f, 0.706543f, 0.706055f, 0.000762f, 0.001804f, 0.002762f, 0.003914f,
+ 0.004791f, 0.005764f, 0.006542f, 0.007622f, 0.008606f, 0.009232f, 0.010178f, 0.011093f, 0.012108f, 0.013191f, 0.014412f, 0.015289f,
+ 0.016510f, 0.017731f, 0.019119f, 0.020615f, 0.022049f, 0.023483f, 0.025345f, 0.027100f, 0.028885f, 0.031067f, 0.033417f, 0.035797f,
+ 0.038422f, 0.041382f, 0.044495f, 0.047638f, 0.051178f, 0.055267f, 0.059387f, 0.064026f, 0.069092f, 0.074585f, 0.080566f, 0.087097f,
+ 0.093811f, 0.101624f, 0.109619f, 0.117798f, 0.127319f, 0.137817f, 0.148682f, 0.160278f, 0.172607f, 0.185669f, 0.199097f, 0.214233f,
+ 0.229492f, 0.245850f, 0.261963f, 0.280273f, 0.299316f, 0.319580f, 0.660645f, 0.689453f, 0.694824f, 0.696777f, 0.697266f, 0.697266f,
+ 0.000499f, 0.001527f, 0.002565f, 0.003622f, 0.004429f, 0.005138f, 0.005955f, 0.006691f, 0.007317f, 0.008156f, 0.008949f, 0.009903f,
+ 0.010635f, 0.011452f, 0.012512f, 0.013451f, 0.014503f, 0.015610f, 0.016632f, 0.017746f, 0.019073f, 0.020355f, 0.021957f, 0.023453f,
+ 0.025208f, 0.026932f, 0.028732f, 0.030945f, 0.033142f, 0.035614f, 0.038300f, 0.041199f, 0.044464f, 0.047760f, 0.051514f, 0.055573f,
+ 0.059998f, 0.064819f, 0.070312f, 0.075867f, 0.082275f, 0.088806f, 0.096436f, 0.104797f, 0.113342f, 0.122559f, 0.132568f, 0.143799f,
+ 0.155396f, 0.167725f, 0.181274f, 0.195068f, 0.209961f, 0.225708f, 0.242310f, 0.259766f, 0.277832f, 0.297363f, 0.648926f, 0.678711f,
+ 0.685059f, 0.687500f, 0.687500f, 0.687988f, 0.000653f, 0.001627f, 0.002562f, 0.003166f, 0.003872f, 0.004562f, 0.005287f, 0.005905f,
+ 0.006557f, 0.007309f, 0.007835f, 0.008621f, 0.009140f, 0.010109f, 0.010773f, 0.011627f, 0.012428f, 0.013351f, 0.014488f, 0.015472f,
+ 0.016479f, 0.017578f, 0.018845f, 0.020157f, 0.021591f, 0.023132f, 0.024765f, 0.026337f, 0.028473f, 0.030594f, 0.032867f, 0.035309f,
+ 0.037933f, 0.041107f, 0.044403f, 0.047852f, 0.051666f, 0.055756f, 0.060455f, 0.065552f, 0.070740f, 0.077454f, 0.083862f, 0.091125f,
+ 0.099304f, 0.107971f, 0.117859f, 0.127808f, 0.139038f, 0.150757f, 0.163574f, 0.176880f, 0.191162f, 0.206665f, 0.222656f, 0.239258f,
+ 0.257568f, 0.277100f, 0.636230f, 0.667969f, 0.675293f, 0.677734f, 0.678223f, 0.678711f, 0.000393f, 0.001375f, 0.002174f, 0.002773f,
+ 0.003334f, 0.004070f, 0.004692f, 0.005047f, 0.005672f, 0.006298f, 0.006893f, 0.007454f, 0.007957f, 0.008636f, 0.009171f, 0.010002f,
+ 0.010674f, 0.011574f, 0.012451f, 0.013145f, 0.014091f, 0.014893f, 0.016083f, 0.017151f, 0.018402f, 0.019714f, 0.021042f, 0.022415f,
+ 0.024155f, 0.026108f, 0.027786f, 0.030212f, 0.032379f, 0.034698f, 0.037415f, 0.040436f, 0.043793f, 0.047455f, 0.051727f, 0.056030f,
+ 0.061218f, 0.066284f, 0.072571f, 0.079041f, 0.086121f, 0.094299f, 0.102844f, 0.112305f, 0.122925f, 0.134033f, 0.145752f, 0.158569f,
+ 0.172729f, 0.187378f, 0.203003f, 0.219238f, 0.237671f, 0.255859f, 0.624023f, 0.657227f, 0.664062f, 0.666992f, 0.668457f, 0.668457f,
+ 0.000379f, 0.001404f, 0.001893f, 0.002403f, 0.002840f, 0.003458f, 0.004021f, 0.004459f, 0.004894f, 0.005527f, 0.005844f, 0.006256f,
+ 0.006866f, 0.007423f, 0.007957f, 0.008476f, 0.009155f, 0.009735f, 0.010422f, 0.011078f, 0.011925f, 0.012787f, 0.013458f, 0.014526f,
+ 0.015541f, 0.016632f, 0.017838f, 0.019028f, 0.020248f, 0.021851f, 0.023514f, 0.024979f, 0.027054f, 0.029236f, 0.031555f, 0.034180f,
+ 0.036713f, 0.040375f, 0.043854f, 0.047607f, 0.051727f, 0.056549f, 0.061768f, 0.067627f, 0.073792f, 0.081116f, 0.089111f, 0.097595f,
+ 0.107056f, 0.117371f, 0.128906f, 0.141113f, 0.154053f, 0.168579f, 0.183960f, 0.199585f, 0.216309f, 0.235352f, 0.612793f, 0.647949f,
+ 0.652832f, 0.656250f, 0.658691f, 0.658203f, 0.000506f, 0.001164f, 0.001575f, 0.002136f, 0.002600f, 0.003054f, 0.003405f, 0.003735f,
+ 0.004364f, 0.004681f, 0.004944f, 0.005569f, 0.005810f, 0.006187f, 0.006813f, 0.007233f, 0.007881f, 0.008217f, 0.008850f, 0.009293f,
+ 0.010109f, 0.010788f, 0.011543f, 0.012161f, 0.012993f, 0.013931f, 0.014809f, 0.015945f, 0.016983f, 0.018234f, 0.019440f, 0.020813f,
+ 0.022491f, 0.024261f, 0.026169f, 0.028458f, 0.030701f, 0.033295f, 0.036560f, 0.039520f, 0.043121f, 0.047333f, 0.052032f, 0.056885f,
+ 0.062561f, 0.068909f, 0.076111f, 0.083496f, 0.092407f, 0.101929f, 0.112671f, 0.124451f, 0.136719f, 0.150146f, 0.165039f, 0.180786f,
+ 0.197510f, 0.215210f, 0.597656f, 0.636230f, 0.642578f, 0.647461f, 0.647949f, 0.649902f, 0.000344f, 0.001057f, 0.001456f, 0.001907f,
+ 0.002377f, 0.002735f, 0.002983f, 0.003359f, 0.003651f, 0.003960f, 0.004311f, 0.004471f, 0.005009f, 0.005283f, 0.005653f, 0.006145f,
+ 0.006592f, 0.006889f, 0.007469f, 0.007889f, 0.008423f, 0.008911f, 0.009567f, 0.010124f, 0.010788f, 0.011574f, 0.012466f, 0.013123f,
+ 0.014053f, 0.015091f, 0.016159f, 0.017288f, 0.018539f, 0.020111f, 0.021698f, 0.023285f, 0.025024f, 0.027405f, 0.029800f, 0.032501f,
+ 0.035583f, 0.039001f, 0.042908f, 0.047302f, 0.052185f, 0.057465f, 0.063843f, 0.070984f, 0.078857f, 0.087463f, 0.097168f, 0.108215f,
+ 0.120117f, 0.132812f, 0.146851f, 0.161865f, 0.177856f, 0.195557f, 0.585449f, 0.624023f, 0.633301f, 0.636230f, 0.637695f, 0.638672f,
+ 0.000516f, 0.000847f, 0.001210f, 0.001663f, 0.002012f, 0.002218f, 0.002424f, 0.002861f, 0.002947f, 0.003275f, 0.003469f, 0.003819f,
+ 0.004169f, 0.004337f, 0.004658f, 0.005169f, 0.005424f, 0.005795f, 0.006138f, 0.006500f, 0.007057f, 0.007458f, 0.007874f, 0.008369f,
+ 0.008888f, 0.009583f, 0.010147f, 0.010864f, 0.011589f, 0.012428f, 0.013161f, 0.013931f, 0.015076f, 0.016266f, 0.017456f, 0.018845f,
+ 0.020432f, 0.022232f, 0.024094f, 0.026459f, 0.028809f, 0.031586f, 0.034973f, 0.038513f, 0.042755f, 0.047485f, 0.052643f, 0.058929f,
+ 0.065796f, 0.073792f, 0.082581f, 0.092407f, 0.103516f, 0.115723f, 0.128906f, 0.142944f, 0.158813f, 0.175781f, 0.572266f, 0.613770f,
+ 0.621094f, 0.625977f, 0.626953f, 0.628418f, 0.000262f, 0.000864f, 0.001096f, 0.001409f, 0.001576f, 0.001852f, 0.002047f, 0.002247f,
+ 0.002518f, 0.002741f, 0.002956f, 0.003157f, 0.003359f, 0.003597f, 0.003872f, 0.004230f, 0.004406f, 0.004772f, 0.005035f, 0.005379f,
+ 0.005695f, 0.006153f, 0.006485f, 0.006935f, 0.007275f, 0.007801f, 0.008301f, 0.008789f, 0.009300f, 0.009949f, 0.010727f, 0.011482f,
+ 0.012245f, 0.013145f, 0.014236f, 0.015236f, 0.016525f, 0.017838f, 0.019348f, 0.021088f, 0.023010f, 0.025253f, 0.027878f, 0.031128f,
+ 0.034149f, 0.038269f, 0.042694f, 0.047852f, 0.053833f, 0.060852f, 0.068665f, 0.077698f, 0.087891f, 0.099182f, 0.111633f, 0.125732f,
+ 0.140381f, 0.157227f, 0.558105f, 0.601562f, 0.610840f, 0.614746f, 0.617188f, 0.619141f, 0.000270f, 0.000683f, 0.000851f, 0.001138f,
+ 0.001346f, 0.001561f, 0.001701f, 0.001884f, 0.001984f, 0.002193f, 0.002455f, 0.002609f, 0.002743f, 0.002993f, 0.003159f, 0.003361f,
+ 0.003593f, 0.003883f, 0.004044f, 0.004360f, 0.004532f, 0.004971f, 0.005169f, 0.005573f, 0.005863f, 0.006252f, 0.006653f, 0.007095f,
+ 0.007572f, 0.008110f, 0.008713f, 0.009056f, 0.009827f, 0.010574f, 0.011307f, 0.012070f, 0.013069f, 0.014122f, 0.015297f, 0.016678f,
+ 0.018234f, 0.019775f, 0.021835f, 0.024216f, 0.026917f, 0.030151f, 0.033875f, 0.038147f, 0.043121f, 0.049408f, 0.056091f, 0.064026f,
+ 0.073059f, 0.083801f, 0.095276f, 0.108459f, 0.122803f, 0.138794f, 0.545410f, 0.590332f, 0.599609f, 0.603516f, 0.606445f, 0.607422f,
+ 0.000190f, 0.000607f, 0.000724f, 0.000989f, 0.001171f, 0.001265f, 0.001416f, 0.001602f, 0.001666f, 0.001761f, 0.001893f, 0.002102f,
+ 0.002199f, 0.002413f, 0.002537f, 0.002743f, 0.002850f, 0.003027f, 0.003258f, 0.003494f, 0.003729f, 0.003937f, 0.004204f, 0.004410f,
+ 0.004616f, 0.004921f, 0.005192f, 0.005604f, 0.005936f, 0.006298f, 0.006836f, 0.007233f, 0.007694f, 0.008224f, 0.008827f, 0.009506f,
+ 0.010262f, 0.011055f, 0.011978f, 0.012955f, 0.014099f, 0.015434f, 0.017029f, 0.018677f, 0.020813f, 0.023193f, 0.026169f, 0.029541f,
+ 0.033783f, 0.038513f, 0.044403f, 0.051208f, 0.059387f, 0.068665f, 0.079468f, 0.091858f, 0.105774f, 0.120728f, 0.530762f, 0.578125f,
+ 0.588379f, 0.592773f, 0.595215f, 0.597168f, 0.000151f, 0.000443f, 0.000673f, 0.000793f, 0.000937f, 0.000987f, 0.001092f, 0.001192f,
+ 0.001324f, 0.001460f, 0.001495f, 0.001565f, 0.001778f, 0.001944f, 0.002054f, 0.002096f, 0.002254f, 0.002338f, 0.002594f, 0.002737f,
+ 0.002886f, 0.003048f, 0.003294f, 0.003460f, 0.003679f, 0.003868f, 0.004086f, 0.004322f, 0.004642f, 0.004894f, 0.005199f, 0.005554f,
+ 0.006035f, 0.006451f, 0.006836f, 0.007359f, 0.007820f, 0.008461f, 0.009163f, 0.009956f, 0.010803f, 0.011871f, 0.012917f, 0.014343f,
+ 0.015900f, 0.017670f, 0.019791f, 0.022400f, 0.025589f, 0.029404f, 0.034210f, 0.039948f, 0.046936f, 0.055298f, 0.064941f, 0.076172f,
+ 0.089172f, 0.103821f, 0.517090f, 0.565918f, 0.576172f, 0.582031f, 0.584961f, 0.586426f, 0.000203f, 0.000287f, 0.000531f, 0.000688f,
+ 0.000738f, 0.000820f, 0.000915f, 0.000875f, 0.001036f, 0.001117f, 0.001215f, 0.001317f, 0.001374f, 0.001476f, 0.001524f, 0.001682f,
+ 0.001726f, 0.001867f, 0.002014f, 0.002056f, 0.002209f, 0.002365f, 0.002495f, 0.002663f, 0.002775f, 0.002953f, 0.003134f, 0.003325f,
+ 0.003567f, 0.003736f, 0.004070f, 0.004261f, 0.004494f, 0.004845f, 0.005116f, 0.005459f, 0.005928f, 0.006329f, 0.006863f, 0.007458f,
+ 0.008087f, 0.008873f, 0.009689f, 0.010651f, 0.011826f, 0.013130f, 0.014732f, 0.016617f, 0.018890f, 0.021912f, 0.025482f, 0.029938f,
+ 0.035736f, 0.042847f, 0.051453f, 0.061615f, 0.074158f, 0.087952f, 0.504395f, 0.554199f, 0.565918f, 0.569336f, 0.573242f, 0.574219f,
+ 0.000215f, 0.000259f, 0.000423f, 0.000534f, 0.000499f, 0.000649f, 0.000622f, 0.000690f, 0.000717f, 0.000817f, 0.000937f, 0.000984f,
+ 0.001045f, 0.001148f, 0.001182f, 0.001211f, 0.001339f, 0.001406f, 0.001463f, 0.001590f, 0.001666f, 0.001759f, 0.001867f, 0.001949f,
+ 0.002064f, 0.002176f, 0.002342f, 0.002453f, 0.002619f, 0.002871f, 0.003033f, 0.003101f, 0.003389f, 0.003620f, 0.003794f, 0.004059f,
+ 0.004368f, 0.004681f, 0.005035f, 0.005466f, 0.005917f, 0.006405f, 0.007092f, 0.007744f, 0.008591f, 0.009506f, 0.010567f, 0.011993f,
+ 0.013710f, 0.015762f, 0.018326f, 0.021759f, 0.026077f, 0.031891f, 0.039124f, 0.048462f, 0.059570f, 0.072571f, 0.489258f, 0.542480f,
+ 0.553223f, 0.558594f, 0.562012f, 0.563965f, 0.000067f, 0.000253f, 0.000305f, 0.000367f, 0.000422f, 0.000431f, 0.000530f, 0.000466f,
+ 0.000565f, 0.000590f, 0.000702f, 0.000690f, 0.000746f, 0.000795f, 0.000859f, 0.000897f, 0.000962f, 0.001021f, 0.001069f, 0.001105f,
+ 0.001207f, 0.001257f, 0.001354f, 0.001424f, 0.001483f, 0.001570f, 0.001687f, 0.001750f, 0.001857f, 0.001982f, 0.002071f, 0.002281f,
+ 0.002361f, 0.002527f, 0.002684f, 0.002846f, 0.003092f, 0.003342f, 0.003622f, 0.003866f, 0.004173f, 0.004520f, 0.004955f, 0.005428f,
+ 0.006023f, 0.006687f, 0.007481f, 0.008446f, 0.009628f, 0.011047f, 0.012840f, 0.015205f, 0.018326f, 0.022629f, 0.028442f, 0.036102f,
+ 0.046051f, 0.058197f, 0.476318f, 0.529785f, 0.541992f, 0.547852f, 0.550293f, 0.553223f, 0.000000f, 0.000118f, 0.000216f, 0.000288f,
+ 0.000272f, 0.000350f, 0.000312f, 0.000374f, 0.000395f, 0.000470f, 0.000488f, 0.000477f, 0.000495f, 0.000548f, 0.000573f, 0.000646f,
+ 0.000636f, 0.000714f, 0.000763f, 0.000803f, 0.000852f, 0.000897f, 0.000930f, 0.000985f, 0.001056f, 0.001089f, 0.001163f, 0.001210f,
+ 0.001281f, 0.001432f, 0.001431f, 0.001548f, 0.001622f, 0.001743f, 0.001869f, 0.001991f, 0.002104f, 0.002262f, 0.002428f, 0.002632f,
+ 0.002815f, 0.003077f, 0.003344f, 0.003656f, 0.004002f, 0.004478f, 0.004974f, 0.005627f, 0.006435f, 0.007481f, 0.008713f, 0.010307f,
+ 0.012291f, 0.015289f, 0.019409f, 0.025497f, 0.033966f, 0.045013f, 0.461914f, 0.517090f, 0.529297f, 0.536133f, 0.539551f, 0.541504f,
+ 0.000073f, 0.000175f, 0.000165f, 0.000149f, 0.000200f, 0.000208f, 0.000215f, 0.000260f, 0.000268f, 0.000277f, 0.000292f, 0.000341f,
+ 0.000334f, 0.000370f, 0.000413f, 0.000424f, 0.000449f, 0.000474f, 0.000488f, 0.000507f, 0.000555f, 0.000574f, 0.000616f, 0.000652f,
+ 0.000696f, 0.000746f, 0.000780f, 0.000804f, 0.000849f, 0.000888f, 0.000949f, 0.001011f, 0.001075f, 0.001151f, 0.001225f, 0.001266f,
+ 0.001385f, 0.001466f, 0.001596f, 0.001699f, 0.001808f, 0.001980f, 0.002157f, 0.002329f, 0.002544f, 0.002850f, 0.003178f, 0.003593f,
+ 0.004047f, 0.004658f, 0.005508f, 0.006565f, 0.007935f, 0.009819f, 0.012527f, 0.016647f, 0.023514f, 0.033173f, 0.447510f, 0.503906f,
+ 0.517578f, 0.523926f, 0.527344f, 0.529297f, 0.000000f, 0.000106f, 0.000097f, 0.000099f, 0.000136f, 0.000157f, 0.000129f, 0.000162f,
+ 0.000167f, 0.000172f, 0.000180f, 0.000186f, 0.000209f, 0.000227f, 0.000232f, 0.000248f, 0.000260f, 0.000291f, 0.000300f, 0.000327f,
+ 0.000335f, 0.000343f, 0.000363f, 0.000395f, 0.000428f, 0.000459f, 0.000458f, 0.000477f, 0.000515f, 0.000549f, 0.000578f, 0.000621f,
+ 0.000659f, 0.000683f, 0.000741f, 0.000767f, 0.000818f, 0.000877f, 0.000952f, 0.001010f, 0.001085f, 0.001177f, 0.001275f, 0.001406f,
+ 0.001516f, 0.001664f, 0.001884f, 0.002096f, 0.002415f, 0.002745f, 0.003231f, 0.003843f, 0.004715f, 0.005936f, 0.007629f, 0.010139f,
+ 0.014763f, 0.022812f, 0.433350f, 0.491455f, 0.506348f, 0.511719f, 0.515625f, 0.518066f, 0.000104f, 0.000080f, 0.000069f, 0.000062f,
+ 0.000074f, 0.000074f, 0.000089f, 0.000097f, 0.000099f, 0.000102f, 0.000105f, 0.000126f, 0.000106f, 0.000119f, 0.000139f, 0.000135f,
+ 0.000154f, 0.000164f, 0.000166f, 0.000175f, 0.000188f, 0.000194f, 0.000211f, 0.000220f, 0.000252f, 0.000248f, 0.000260f, 0.000272f,
+ 0.000293f, 0.000301f, 0.000328f, 0.000347f, 0.000365f, 0.000371f, 0.000401f, 0.000422f, 0.000447f, 0.000489f, 0.000524f, 0.000553f,
+ 0.000588f, 0.000635f, 0.000701f, 0.000751f, 0.000816f, 0.000897f, 0.000997f, 0.001109f, 0.001265f, 0.001460f, 0.001686f, 0.002035f,
+ 0.002457f, 0.003130f, 0.004124f, 0.005676f, 0.008263f, 0.014114f, 0.418945f, 0.479492f, 0.493652f, 0.500000f, 0.503418f, 0.506836f,
+ 0.000089f, 0.000065f, 0.000056f, 0.000050f, 0.000045f, 0.000042f, 0.000046f, 0.000042f, 0.000043f, 0.000055f, 0.000046f, 0.000049f,
+ 0.000065f, 0.000055f, 0.000057f, 0.000063f, 0.000075f, 0.000080f, 0.000078f, 0.000084f, 0.000085f, 0.000092f, 0.000097f, 0.000102f,
+ 0.000108f, 0.000117f, 0.000118f, 0.000138f, 0.000135f, 0.000142f, 0.000151f, 0.000160f, 0.000172f, 0.000180f, 0.000195f, 0.000197f,
+ 0.000210f, 0.000230f, 0.000244f, 0.000266f, 0.000279f, 0.000299f, 0.000324f, 0.000352f, 0.000383f, 0.000414f, 0.000457f, 0.000509f,
+ 0.000575f, 0.000650f, 0.000756f, 0.000904f, 0.001103f, 0.001410f, 0.001880f, 0.002668f, 0.004112f, 0.007290f, 0.404541f, 0.466309f,
+ 0.481201f, 0.488037f, 0.492432f, 0.495361f, 0.000066f, 0.000046f, 0.000038f, 0.000034f, 0.000031f, 0.000029f, 0.000027f, 0.000026f,
+ 0.000025f, 0.000023f, 0.000022f, 0.000024f, 0.000020f, 0.000021f, 0.000021f, 0.000026f, 0.000024f, 0.000028f, 0.000031f, 0.000032f,
+ 0.000032f, 0.000035f, 0.000040f, 0.000038f, 0.000041f, 0.000047f, 0.000049f, 0.000043f, 0.000050f, 0.000052f, 0.000056f, 0.000059f,
+ 0.000066f, 0.000062f, 0.000067f, 0.000071f, 0.000082f, 0.000083f, 0.000089f, 0.000098f, 0.000104f, 0.000107f, 0.000116f, 0.000125f,
+ 0.000141f, 0.000149f, 0.000160f, 0.000183f, 0.000207f, 0.000228f, 0.000264f, 0.000311f, 0.000376f, 0.000469f, 0.000646f, 0.000937f,
+ 0.001554f, 0.002983f, 0.390381f, 0.454346f, 0.469727f, 0.476318f, 0.480713f, 0.484131f, 0.000028f, 0.000019f, 0.000015f, 0.000014f,
+ 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000010f,
+ 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000007f, 0.000008f, 0.000009f, 0.000009f, 0.000010f,
+ 0.000010f, 0.000011f, 0.000012f, 0.000011f, 0.000014f, 0.000015f, 0.000016f, 0.000016f, 0.000018f, 0.000019f, 0.000019f, 0.000022f,
+ 0.000023f, 0.000024f, 0.000026f, 0.000028f, 0.000029f, 0.000032f, 0.000037f, 0.000037f, 0.000042f, 0.000048f, 0.000056f, 0.000066f,
+ 0.000077f, 0.000091f, 0.000124f, 0.000183f, 0.000318f, 0.000779f, 0.376465f, 0.441406f, 0.457275f, 0.464600f, 0.468994f, 0.471924f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f,
+ 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000005f, 0.000010f, 0.000027f, 0.363037f, 0.428223f,
+ 0.444580f, 0.452881f, 0.457031f, 0.459961f,
+ },
+ {
+ 0.014420f, 0.043488f, 0.072388f, 0.100830f, 0.129150f, 0.156494f, 0.183350f, 0.210327f, 0.235352f, 0.260986f, 0.285645f, 0.309082f,
+ 0.332764f, 0.355713f, 0.377441f, 0.399658f, 0.420898f, 0.441650f, 0.461914f, 0.481445f, 0.500977f, 0.520508f, 0.538574f, 0.556641f,
+ 0.574707f, 0.591797f, 0.608398f, 0.624512f, 0.641602f, 0.657227f, 0.672363f, 0.687500f, 0.702148f, 0.717285f, 0.730957f, 0.745117f,
+ 0.758789f, 0.772461f, 0.783203f, 0.797363f, 0.810547f, 0.822266f, 0.833984f, 0.845703f, 0.857422f, 0.868652f, 0.879395f, 0.890625f,
+ 0.901367f, 0.911621f, 0.921875f, 0.932129f, 0.941895f, 0.951660f, 0.960938f, 0.970215f, 0.979492f, 0.987793f, 0.981934f, 0.957031f,
+ 0.938965f, 0.923340f, 0.909668f, 0.897461f, 0.013199f, 0.039978f, 0.066284f, 0.093445f, 0.119324f, 0.145386f, 0.170410f, 0.195801f,
+ 0.220581f, 0.244019f, 0.268066f, 0.291260f, 0.314453f, 0.335938f, 0.358154f, 0.379639f, 0.399902f, 0.420898f, 0.441406f, 0.460938f,
+ 0.480225f, 0.498291f, 0.516602f, 0.535156f, 0.553223f, 0.570312f, 0.587891f, 0.603516f, 0.620117f, 0.636719f, 0.652832f, 0.667480f,
+ 0.682617f, 0.696777f, 0.711914f, 0.726074f, 0.739746f, 0.753418f, 0.766602f, 0.779785f, 0.791992f, 0.804688f, 0.817871f, 0.829102f,
+ 0.841309f, 0.852539f, 0.864258f, 0.875488f, 0.886230f, 0.896973f, 0.907227f, 0.917969f, 0.928223f, 0.937500f, 0.947266f, 0.957520f,
+ 0.966797f, 0.975586f, 0.976562f, 0.952637f, 0.935547f, 0.920898f, 0.907715f, 0.895996f, 0.011932f, 0.036499f, 0.061554f, 0.085999f,
+ 0.110962f, 0.135010f, 0.158813f, 0.182373f, 0.206421f, 0.229004f, 0.251221f, 0.274170f, 0.295654f, 0.317871f, 0.339111f, 0.360107f,
+ 0.379395f, 0.399414f, 0.420654f, 0.440430f, 0.458252f, 0.477295f, 0.496094f, 0.513672f, 0.531738f, 0.549805f, 0.566406f, 0.583984f,
+ 0.599121f, 0.616211f, 0.631348f, 0.647461f, 0.662598f, 0.677734f, 0.692383f, 0.705566f, 0.720703f, 0.734863f, 0.748047f, 0.761230f,
+ 0.774414f, 0.787598f, 0.799805f, 0.812500f, 0.824707f, 0.837402f, 0.848633f, 0.859375f, 0.871094f, 0.882324f, 0.892578f, 0.904297f,
+ 0.913574f, 0.924316f, 0.934570f, 0.943848f, 0.954102f, 0.963867f, 0.970703f, 0.948242f, 0.931641f, 0.917480f, 0.905273f, 0.894043f,
+ 0.011070f, 0.033478f, 0.056396f, 0.079529f, 0.101990f, 0.125244f, 0.147705f, 0.170410f, 0.192139f, 0.214111f, 0.235596f, 0.257812f,
+ 0.279053f, 0.300293f, 0.320557f, 0.340576f, 0.360596f, 0.381104f, 0.400635f, 0.420166f, 0.438965f, 0.458008f, 0.476562f, 0.493652f,
+ 0.511230f, 0.527832f, 0.545898f, 0.562012f, 0.579102f, 0.595703f, 0.610840f, 0.627930f, 0.642578f, 0.657227f, 0.672363f, 0.686523f,
+ 0.701660f, 0.715332f, 0.729492f, 0.742676f, 0.756348f, 0.769531f, 0.782227f, 0.795898f, 0.807617f, 0.820312f, 0.832031f, 0.843262f,
+ 0.855469f, 0.866699f, 0.877441f, 0.889648f, 0.899414f, 0.910156f, 0.920410f, 0.930664f, 0.940430f, 0.950684f, 0.964844f, 0.943848f,
+ 0.927734f, 0.914551f, 0.902344f, 0.891602f, 0.010010f, 0.031067f, 0.051880f, 0.073303f, 0.094421f, 0.116577f, 0.136963f, 0.157959f,
+ 0.180542f, 0.200684f, 0.221436f, 0.242676f, 0.262939f, 0.283447f, 0.303467f, 0.323242f, 0.342529f, 0.362305f, 0.381348f, 0.399414f,
+ 0.418701f, 0.437256f, 0.455322f, 0.472412f, 0.490479f, 0.507812f, 0.524902f, 0.541992f, 0.558105f, 0.574219f, 0.591309f, 0.606445f,
+ 0.622070f, 0.637695f, 0.652344f, 0.666504f, 0.683594f, 0.695801f, 0.710449f, 0.724121f, 0.737305f, 0.751465f, 0.765137f, 0.777344f,
+ 0.790039f, 0.802734f, 0.814941f, 0.827637f, 0.839355f, 0.851074f, 0.862305f, 0.874512f, 0.885254f, 0.895996f, 0.906738f, 0.917480f,
+ 0.927246f, 0.937988f, 0.958984f, 0.939453f, 0.923828f, 0.911133f, 0.899414f, 0.889160f, 0.009491f, 0.028305f, 0.047699f, 0.067810f,
+ 0.087341f, 0.107849f, 0.127686f, 0.147827f, 0.167725f, 0.187744f, 0.207886f, 0.227051f, 0.247314f, 0.266846f, 0.286377f, 0.305908f,
+ 0.324463f, 0.343262f, 0.361572f, 0.380371f, 0.399658f, 0.416748f, 0.435547f, 0.452881f, 0.470703f, 0.488281f, 0.503906f, 0.522461f,
+ 0.538086f, 0.554199f, 0.571289f, 0.586914f, 0.602051f, 0.617676f, 0.633789f, 0.647949f, 0.663086f, 0.677246f, 0.692871f, 0.705078f,
+ 0.718750f, 0.732910f, 0.746582f, 0.759766f, 0.773438f, 0.785645f, 0.798340f, 0.811035f, 0.823242f, 0.834961f, 0.847168f, 0.859863f,
+ 0.870117f, 0.881348f, 0.893066f, 0.903320f, 0.914551f, 0.924316f, 0.953125f, 0.934082f, 0.919434f, 0.906738f, 0.896484f, 0.885742f,
+ 0.008598f, 0.026245f, 0.044495f, 0.062622f, 0.081177f, 0.100098f, 0.119019f, 0.137817f, 0.156616f, 0.175903f, 0.194946f, 0.213745f,
+ 0.232788f, 0.251221f, 0.269775f, 0.288330f, 0.307129f, 0.325928f, 0.344238f, 0.362305f, 0.380371f, 0.397705f, 0.415771f, 0.433105f,
+ 0.450928f, 0.468262f, 0.484863f, 0.501953f, 0.518555f, 0.534668f, 0.550293f, 0.566406f, 0.582520f, 0.598145f, 0.612305f, 0.627930f,
+ 0.643555f, 0.657715f, 0.672852f, 0.687500f, 0.700684f, 0.715332f, 0.728516f, 0.742188f, 0.755371f, 0.769531f, 0.781738f, 0.794434f,
+ 0.807129f, 0.818359f, 0.831543f, 0.843262f, 0.855469f, 0.865723f, 0.877930f, 0.889160f, 0.900391f, 0.911621f, 0.946777f, 0.929199f,
+ 0.915039f, 0.903320f, 0.892578f, 0.883301f, 0.007896f, 0.024490f, 0.041138f, 0.057892f, 0.075439f, 0.092712f, 0.110229f, 0.128296f,
+ 0.146118f, 0.164429f, 0.181885f, 0.200562f, 0.218628f, 0.236572f, 0.255127f, 0.272949f, 0.291016f, 0.308594f, 0.326172f, 0.343994f,
+ 0.361816f, 0.380127f, 0.396973f, 0.414551f, 0.430908f, 0.447998f, 0.465576f, 0.481445f, 0.497559f, 0.514160f, 0.529785f, 0.546387f,
+ 0.562988f, 0.578613f, 0.593262f, 0.609375f, 0.623047f, 0.638672f, 0.653809f, 0.667480f, 0.681641f, 0.697266f, 0.710938f, 0.724121f,
+ 0.737305f, 0.752441f, 0.765625f, 0.776367f, 0.790527f, 0.803223f, 0.815918f, 0.827637f, 0.839844f, 0.851562f, 0.863281f, 0.875000f,
+ 0.886719f, 0.898926f, 0.940430f, 0.923828f, 0.910645f, 0.899414f, 0.889160f, 0.879883f, 0.007320f, 0.022369f, 0.038055f, 0.053925f,
+ 0.070190f, 0.086609f, 0.103027f, 0.119568f, 0.136475f, 0.153320f, 0.170532f, 0.187988f, 0.204834f, 0.223022f, 0.240112f, 0.257324f,
+ 0.275391f, 0.291504f, 0.308838f, 0.326904f, 0.344727f, 0.361572f, 0.378662f, 0.395020f, 0.411865f, 0.428711f, 0.445068f, 0.462646f,
+ 0.478271f, 0.494141f, 0.510254f, 0.525879f, 0.542480f, 0.557129f, 0.573242f, 0.588867f, 0.603516f, 0.618164f, 0.633789f, 0.648438f,
+ 0.663086f, 0.678223f, 0.691895f, 0.706543f, 0.720215f, 0.733398f, 0.746582f, 0.759766f, 0.774414f, 0.786621f, 0.799805f, 0.811523f,
+ 0.823730f, 0.836914f, 0.848145f, 0.860840f, 0.872070f, 0.884277f, 0.933594f, 0.918945f, 0.906250f, 0.895020f, 0.885254f, 0.876953f,
+ 0.006760f, 0.021011f, 0.034973f, 0.050049f, 0.065369f, 0.080261f, 0.095337f, 0.111633f, 0.127319f, 0.142822f, 0.159668f, 0.176514f,
+ 0.192383f, 0.209106f, 0.225586f, 0.242554f, 0.259277f, 0.275635f, 0.292480f, 0.309326f, 0.326904f, 0.343750f, 0.359619f, 0.376465f,
+ 0.393066f, 0.409424f, 0.426514f, 0.442871f, 0.458252f, 0.475586f, 0.490967f, 0.505859f, 0.522461f, 0.539062f, 0.554199f, 0.569336f,
+ 0.583984f, 0.600586f, 0.614258f, 0.630371f, 0.643555f, 0.658691f, 0.673340f, 0.687500f, 0.702148f, 0.715332f, 0.729980f, 0.743652f,
+ 0.756348f, 0.770020f, 0.782715f, 0.796387f, 0.808105f, 0.820801f, 0.833008f, 0.846680f, 0.857910f, 0.870117f, 0.927246f, 0.913574f,
+ 0.901367f, 0.891113f, 0.881348f, 0.873047f, 0.006367f, 0.019165f, 0.032379f, 0.046295f, 0.060089f, 0.074463f, 0.088867f, 0.103821f,
+ 0.118835f, 0.133911f, 0.149048f, 0.164673f, 0.180298f, 0.196289f, 0.212524f, 0.228516f, 0.244385f, 0.260742f, 0.277344f, 0.293213f,
+ 0.309570f, 0.326416f, 0.342773f, 0.358887f, 0.374512f, 0.391113f, 0.406982f, 0.423340f, 0.439453f, 0.455078f, 0.470947f, 0.487793f,
+ 0.502441f, 0.519043f, 0.533691f, 0.550293f, 0.564941f, 0.580078f, 0.595703f, 0.610840f, 0.625488f, 0.640137f, 0.654785f, 0.669434f,
+ 0.683594f, 0.696777f, 0.710938f, 0.725586f, 0.738770f, 0.752441f, 0.766113f, 0.778320f, 0.791016f, 0.805176f, 0.818359f, 0.830566f,
+ 0.842773f, 0.854980f, 0.920410f, 0.908203f, 0.896484f, 0.886230f, 0.877441f, 0.868652f, 0.005981f, 0.017914f, 0.030350f, 0.042908f,
+ 0.056213f, 0.069092f, 0.083008f, 0.096619f, 0.111084f, 0.124634f, 0.139526f, 0.154297f, 0.169312f, 0.184570f, 0.199951f, 0.215454f,
+ 0.230713f, 0.245728f, 0.261963f, 0.277588f, 0.293213f, 0.309326f, 0.325195f, 0.340820f, 0.356934f, 0.373047f, 0.388916f, 0.404785f,
+ 0.420410f, 0.436279f, 0.452148f, 0.468506f, 0.483154f, 0.499756f, 0.515137f, 0.530762f, 0.545898f, 0.560059f, 0.576172f, 0.590820f,
+ 0.606445f, 0.621094f, 0.635254f, 0.649902f, 0.663574f, 0.678223f, 0.692383f, 0.706543f, 0.720703f, 0.733887f, 0.748535f, 0.762695f,
+ 0.775391f, 0.789551f, 0.801758f, 0.814941f, 0.828125f, 0.840332f, 0.913574f, 0.902344f, 0.890625f, 0.881836f, 0.872559f, 0.865234f,
+ 0.005402f, 0.016617f, 0.028061f, 0.039948f, 0.051758f, 0.064270f, 0.076782f, 0.089600f, 0.102600f, 0.116455f, 0.130371f, 0.144165f,
+ 0.158936f, 0.172607f, 0.187744f, 0.201904f, 0.216431f, 0.232422f, 0.247192f, 0.261719f, 0.277100f, 0.292480f, 0.308838f, 0.323975f,
+ 0.339355f, 0.355469f, 0.371338f, 0.386230f, 0.402344f, 0.417725f, 0.433350f, 0.448486f, 0.464600f, 0.480225f, 0.495361f, 0.510742f,
+ 0.525879f, 0.541992f, 0.557129f, 0.571777f, 0.586914f, 0.601562f, 0.616211f, 0.631836f, 0.645508f, 0.661621f, 0.674805f, 0.688965f,
+ 0.703125f, 0.717773f, 0.731934f, 0.745605f, 0.757812f, 0.772949f, 0.785156f, 0.799316f, 0.812012f, 0.826172f, 0.906738f, 0.896484f,
+ 0.886230f, 0.876465f, 0.868164f, 0.860840f, 0.005264f, 0.015457f, 0.026474f, 0.037170f, 0.048157f, 0.059845f, 0.071594f, 0.083984f,
+ 0.096191f, 0.109070f, 0.121887f, 0.134766f, 0.148193f, 0.161255f, 0.175781f, 0.189209f, 0.203369f, 0.218384f, 0.233032f, 0.247681f,
+ 0.261963f, 0.277100f, 0.292480f, 0.307129f, 0.322998f, 0.337891f, 0.352539f, 0.368652f, 0.384033f, 0.399170f, 0.414307f, 0.430420f,
+ 0.445801f, 0.460693f, 0.475342f, 0.491211f, 0.506836f, 0.521973f, 0.537598f, 0.551758f, 0.567383f, 0.582520f, 0.598145f, 0.612305f,
+ 0.627441f, 0.642090f, 0.656738f, 0.670898f, 0.685059f, 0.698730f, 0.713867f, 0.728516f, 0.742188f, 0.755371f, 0.770020f, 0.782715f,
+ 0.796387f, 0.810547f, 0.899414f, 0.889648f, 0.879883f, 0.872070f, 0.863770f, 0.856445f, 0.004719f, 0.014229f, 0.024384f, 0.034607f,
+ 0.044708f, 0.055756f, 0.066895f, 0.077942f, 0.089600f, 0.101624f, 0.113525f, 0.125854f, 0.138428f, 0.151245f, 0.164673f, 0.177734f,
+ 0.191650f, 0.205078f, 0.219360f, 0.233154f, 0.247925f, 0.261475f, 0.276367f, 0.291504f, 0.305908f, 0.320312f, 0.335449f, 0.350098f,
+ 0.365723f, 0.380615f, 0.395996f, 0.411133f, 0.427002f, 0.441895f, 0.456543f, 0.472656f, 0.487793f, 0.502441f, 0.518555f, 0.533203f,
+ 0.547852f, 0.562988f, 0.577637f, 0.593262f, 0.607910f, 0.623535f, 0.638184f, 0.652344f, 0.666992f, 0.681641f, 0.696777f, 0.711426f,
+ 0.725098f, 0.738281f, 0.753418f, 0.766113f, 0.782227f, 0.794922f, 0.892090f, 0.884277f, 0.875000f, 0.866699f, 0.858887f, 0.852539f,
+ 0.004280f, 0.013329f, 0.022476f, 0.031982f, 0.042114f, 0.051849f, 0.062225f, 0.072449f, 0.083679f, 0.095032f, 0.105530f, 0.117676f,
+ 0.129517f, 0.141357f, 0.154297f, 0.166748f, 0.178711f, 0.192505f, 0.205933f, 0.219727f, 0.233521f, 0.247070f, 0.260986f, 0.275391f,
+ 0.290039f, 0.303955f, 0.319580f, 0.333740f, 0.347412f, 0.363037f, 0.377686f, 0.392822f, 0.408203f, 0.422852f, 0.437988f, 0.453125f,
+ 0.468506f, 0.483398f, 0.498779f, 0.514160f, 0.527832f, 0.543945f, 0.559570f, 0.574707f, 0.588867f, 0.604492f, 0.619141f, 0.634277f,
+ 0.648438f, 0.663086f, 0.678223f, 0.692383f, 0.707520f, 0.721680f, 0.735352f, 0.749512f, 0.764648f, 0.778320f, 0.884277f, 0.877441f,
+ 0.868652f, 0.861328f, 0.854492f, 0.847656f, 0.004280f, 0.012138f, 0.021103f, 0.029999f, 0.038940f, 0.048279f, 0.057831f, 0.067566f,
+ 0.077454f, 0.087524f, 0.098816f, 0.109558f, 0.120728f, 0.131958f, 0.143799f, 0.155762f, 0.168091f, 0.180176f, 0.193359f, 0.206177f,
+ 0.219360f, 0.232910f, 0.246338f, 0.260254f, 0.273682f, 0.287598f, 0.302246f, 0.316650f, 0.331299f, 0.344971f, 0.359863f, 0.374268f,
+ 0.389648f, 0.404297f, 0.419434f, 0.434326f, 0.449463f, 0.464844f, 0.479492f, 0.494141f, 0.509766f, 0.524414f, 0.540039f, 0.555176f,
+ 0.569824f, 0.584961f, 0.600098f, 0.615723f, 0.629883f, 0.645508f, 0.659668f, 0.675293f, 0.689453f, 0.704590f, 0.719238f, 0.732422f,
+ 0.748535f, 0.762207f, 0.876953f, 0.871582f, 0.863281f, 0.855957f, 0.849609f, 0.842773f, 0.003744f, 0.011436f, 0.019348f, 0.027893f,
+ 0.036102f, 0.044739f, 0.053711f, 0.063110f, 0.072205f, 0.081970f, 0.091919f, 0.101746f, 0.112732f, 0.122864f, 0.134521f, 0.145996f,
+ 0.157715f, 0.169434f, 0.181519f, 0.193848f, 0.206665f, 0.219360f, 0.231445f, 0.245361f, 0.259033f, 0.272217f, 0.286621f, 0.299805f,
+ 0.314209f, 0.328125f, 0.342285f, 0.357178f, 0.371826f, 0.386475f, 0.400635f, 0.415527f, 0.430420f, 0.445068f, 0.459717f, 0.476074f,
+ 0.490234f, 0.505371f, 0.521484f, 0.536133f, 0.551758f, 0.565430f, 0.581543f, 0.595703f, 0.611816f, 0.626465f, 0.641602f, 0.656738f,
+ 0.671875f, 0.686523f, 0.701172f, 0.715820f, 0.731445f, 0.746582f, 0.868652f, 0.864746f, 0.856934f, 0.851074f, 0.844727f, 0.837891f,
+ 0.003595f, 0.011093f, 0.018265f, 0.025711f, 0.033600f, 0.041656f, 0.050140f, 0.058350f, 0.067505f, 0.076416f, 0.085632f, 0.095093f,
+ 0.104919f, 0.115295f, 0.125610f, 0.136108f, 0.147583f, 0.157959f, 0.169800f, 0.181519f, 0.193359f, 0.205933f, 0.218140f, 0.231323f,
+ 0.243652f, 0.257324f, 0.270508f, 0.283447f, 0.297363f, 0.311523f, 0.325928f, 0.339111f, 0.353516f, 0.367432f, 0.382812f, 0.396973f,
+ 0.412109f, 0.426758f, 0.441406f, 0.456055f, 0.471436f, 0.486328f, 0.501953f, 0.516113f, 0.531738f, 0.546875f, 0.562500f, 0.577637f,
+ 0.592773f, 0.607910f, 0.622559f, 0.638184f, 0.653809f, 0.669434f, 0.684082f, 0.699219f, 0.714355f, 0.729492f, 0.860840f, 0.857422f,
+ 0.852051f, 0.844727f, 0.839355f, 0.832520f, 0.003349f, 0.009933f, 0.016754f, 0.024063f, 0.031204f, 0.038849f, 0.046356f, 0.054413f,
+ 0.062744f, 0.070984f, 0.080017f, 0.088989f, 0.097778f, 0.107361f, 0.117004f, 0.127197f, 0.137451f, 0.148071f, 0.159180f, 0.169922f,
+ 0.181519f, 0.192993f, 0.204956f, 0.217407f, 0.229980f, 0.242188f, 0.254883f, 0.267578f, 0.281494f, 0.294434f, 0.307861f, 0.321533f,
+ 0.335693f, 0.350098f, 0.364258f, 0.379150f, 0.393066f, 0.407715f, 0.422607f, 0.437500f, 0.452148f, 0.467041f, 0.482422f, 0.497314f,
+ 0.512695f, 0.527832f, 0.542969f, 0.558594f, 0.573730f, 0.589844f, 0.604004f, 0.619629f, 0.635254f, 0.651367f, 0.665527f, 0.681152f,
+ 0.696289f, 0.711914f, 0.852539f, 0.851562f, 0.846191f, 0.838867f, 0.832520f, 0.827637f, 0.003290f, 0.009415f, 0.015976f, 0.022095f,
+ 0.028946f, 0.036255f, 0.043396f, 0.050598f, 0.058502f, 0.066284f, 0.074036f, 0.082275f, 0.091187f, 0.099731f, 0.108826f, 0.118652f,
+ 0.128296f, 0.137939f, 0.148193f, 0.159302f, 0.170166f, 0.180786f, 0.191895f, 0.203491f, 0.215210f, 0.227661f, 0.240112f, 0.252686f,
+ 0.265625f, 0.278564f, 0.291748f, 0.305176f, 0.318604f, 0.332764f, 0.346924f, 0.360352f, 0.375000f, 0.389160f, 0.404297f, 0.418213f,
+ 0.433105f, 0.448486f, 0.463135f, 0.477783f, 0.493408f, 0.508301f, 0.523438f, 0.540039f, 0.554199f, 0.570312f, 0.585938f, 0.601074f,
+ 0.617188f, 0.633301f, 0.648926f, 0.664062f, 0.679688f, 0.695312f, 0.844727f, 0.844238f, 0.838867f, 0.833008f, 0.827148f, 0.822266f,
+ 0.002913f, 0.008621f, 0.014595f, 0.020950f, 0.027496f, 0.033600f, 0.040558f, 0.047119f, 0.054260f, 0.061615f, 0.068970f, 0.076782f,
+ 0.084717f, 0.093140f, 0.101562f, 0.109985f, 0.118591f, 0.129150f, 0.138306f, 0.148682f, 0.158447f, 0.169189f, 0.180054f, 0.191162f,
+ 0.202148f, 0.213379f, 0.225586f, 0.237305f, 0.250488f, 0.262939f, 0.275391f, 0.288086f, 0.302490f, 0.315186f, 0.329346f, 0.342529f,
+ 0.356934f, 0.370117f, 0.385742f, 0.400146f, 0.414795f, 0.429199f, 0.444336f, 0.459473f, 0.473389f, 0.489258f, 0.503906f, 0.519531f,
+ 0.535645f, 0.551270f, 0.566895f, 0.582520f, 0.598145f, 0.614258f, 0.629395f, 0.645996f, 0.661621f, 0.677734f, 0.837402f, 0.836914f,
+ 0.832520f, 0.826660f, 0.821777f, 0.816406f, 0.002748f, 0.008018f, 0.014168f, 0.019196f, 0.025040f, 0.031250f, 0.037506f, 0.043732f,
+ 0.050415f, 0.057098f, 0.063721f, 0.071167f, 0.078979f, 0.086609f, 0.094299f, 0.102783f, 0.111145f, 0.119812f, 0.128296f, 0.138306f,
+ 0.147583f, 0.157593f, 0.168213f, 0.178711f, 0.188843f, 0.200317f, 0.211792f, 0.223511f, 0.235352f, 0.247192f, 0.259521f, 0.272461f,
+ 0.285156f, 0.298584f, 0.312012f, 0.324707f, 0.339111f, 0.352783f, 0.366943f, 0.381348f, 0.395996f, 0.410889f, 0.425537f, 0.439941f,
+ 0.454834f, 0.470459f, 0.485352f, 0.501953f, 0.516113f, 0.531738f, 0.547363f, 0.563477f, 0.579102f, 0.595703f, 0.611328f, 0.626953f,
+ 0.642578f, 0.659668f, 0.828125f, 0.830566f, 0.825684f, 0.820801f, 0.815430f, 0.811035f, 0.002630f, 0.007412f, 0.012978f, 0.018356f,
+ 0.023758f, 0.028931f, 0.034729f, 0.040894f, 0.046631f, 0.053101f, 0.059143f, 0.065979f, 0.073669f, 0.080200f, 0.087585f, 0.095276f,
+ 0.102844f, 0.111633f, 0.119812f, 0.128296f, 0.137573f, 0.146729f, 0.156128f, 0.166382f, 0.176880f, 0.187256f, 0.197998f, 0.209351f,
+ 0.220581f, 0.232422f, 0.244385f, 0.256592f, 0.268799f, 0.281982f, 0.294922f, 0.308105f, 0.321045f, 0.334717f, 0.348633f, 0.363525f,
+ 0.378174f, 0.391846f, 0.406006f, 0.420898f, 0.436279f, 0.451660f, 0.466064f, 0.481934f, 0.496826f, 0.513184f, 0.528320f, 0.543945f,
+ 0.560059f, 0.576660f, 0.592285f, 0.608887f, 0.625000f, 0.640625f, 0.819336f, 0.822266f, 0.818848f, 0.813965f, 0.810059f, 0.805664f,
+ 0.002201f, 0.007240f, 0.011803f, 0.016617f, 0.021622f, 0.027344f, 0.032288f, 0.037598f, 0.043427f, 0.049194f, 0.055267f, 0.061462f,
+ 0.067566f, 0.073853f, 0.080872f, 0.088013f, 0.095703f, 0.103821f, 0.111145f, 0.119446f, 0.127563f, 0.136597f, 0.145752f, 0.155273f,
+ 0.165039f, 0.174683f, 0.185181f, 0.195801f, 0.206543f, 0.218140f, 0.229370f, 0.241455f, 0.253174f, 0.265381f, 0.278564f, 0.291504f,
+ 0.304199f, 0.317383f, 0.331299f, 0.344971f, 0.358643f, 0.373291f, 0.386963f, 0.402100f, 0.416016f, 0.431641f, 0.447266f, 0.462646f,
+ 0.477295f, 0.493652f, 0.509277f, 0.524902f, 0.541504f, 0.557617f, 0.574219f, 0.589844f, 0.605957f, 0.623047f, 0.810059f, 0.814453f,
+ 0.811035f, 0.807129f, 0.803223f, 0.798828f, 0.002293f, 0.006927f, 0.010994f, 0.015617f, 0.020584f, 0.025131f, 0.029663f, 0.034760f,
+ 0.040192f, 0.045532f, 0.050964f, 0.056793f, 0.062805f, 0.068726f, 0.074890f, 0.081482f, 0.088806f, 0.096069f, 0.103333f, 0.110535f,
+ 0.118896f, 0.126709f, 0.135254f, 0.144165f, 0.153442f, 0.162720f, 0.172119f, 0.182495f, 0.192749f, 0.203735f, 0.214600f, 0.225952f,
+ 0.237793f, 0.250000f, 0.261719f, 0.274170f, 0.287354f, 0.300293f, 0.313477f, 0.326904f, 0.340820f, 0.354980f, 0.369385f, 0.383545f,
+ 0.396973f, 0.411865f, 0.427734f, 0.442871f, 0.458740f, 0.473633f, 0.489502f, 0.505859f, 0.522461f, 0.537598f, 0.553711f, 0.572754f,
+ 0.588379f, 0.604492f, 0.802246f, 0.807617f, 0.804199f, 0.800781f, 0.797363f, 0.792969f, 0.002081f, 0.006172f, 0.010460f, 0.014503f,
+ 0.019104f, 0.023163f, 0.027832f, 0.032410f, 0.037354f, 0.041992f, 0.047211f, 0.052490f, 0.057831f, 0.063232f, 0.069458f, 0.075317f,
+ 0.082153f, 0.088257f, 0.094910f, 0.102295f, 0.110107f, 0.117554f, 0.125122f, 0.133667f, 0.142456f, 0.151001f, 0.160767f, 0.169922f,
+ 0.179443f, 0.190430f, 0.200562f, 0.211914f, 0.222412f, 0.234009f, 0.245850f, 0.258545f, 0.270752f, 0.283203f, 0.296387f, 0.309082f,
+ 0.322998f, 0.336670f, 0.350098f, 0.364990f, 0.378906f, 0.393311f, 0.408936f, 0.423096f, 0.438965f, 0.454834f, 0.470703f, 0.486572f,
+ 0.502441f, 0.518555f, 0.534668f, 0.551270f, 0.569336f, 0.585938f, 0.792480f, 0.799316f, 0.797363f, 0.793457f, 0.790039f, 0.786621f,
+ 0.002028f, 0.005669f, 0.009705f, 0.013565f, 0.017532f, 0.021286f, 0.025574f, 0.030197f, 0.034180f, 0.038757f, 0.043488f, 0.048737f,
+ 0.053497f, 0.058594f, 0.064026f, 0.070007f, 0.075623f, 0.081360f, 0.088135f, 0.094238f, 0.101379f, 0.108643f, 0.116028f, 0.123718f,
+ 0.131592f, 0.140137f, 0.149048f, 0.157715f, 0.167114f, 0.176636f, 0.187012f, 0.197388f, 0.208130f, 0.219238f, 0.230347f, 0.241943f,
+ 0.254150f, 0.266113f, 0.279053f, 0.291504f, 0.304932f, 0.318848f, 0.332031f, 0.345947f, 0.360107f, 0.375000f, 0.389404f, 0.404541f,
+ 0.419922f, 0.434814f, 0.450684f, 0.466553f, 0.482910f, 0.499023f, 0.516113f, 0.533203f, 0.550293f, 0.567383f, 0.783203f, 0.790527f,
+ 0.789551f, 0.786621f, 0.783691f, 0.780762f, 0.001852f, 0.005554f, 0.008957f, 0.012642f, 0.016296f, 0.020172f, 0.024033f, 0.027878f,
+ 0.031677f, 0.035919f, 0.040253f, 0.044952f, 0.049255f, 0.053955f, 0.058960f, 0.063965f, 0.069336f, 0.074951f, 0.080933f, 0.087219f,
+ 0.093201f, 0.100159f, 0.106689f, 0.114197f, 0.121521f, 0.129517f, 0.137817f, 0.146118f, 0.155151f, 0.164307f, 0.173462f, 0.183472f,
+ 0.193970f, 0.204224f, 0.215210f, 0.226562f, 0.238037f, 0.250244f, 0.262451f, 0.274902f, 0.287598f, 0.301025f, 0.314209f, 0.327393f,
+ 0.342041f, 0.356445f, 0.370850f, 0.385254f, 0.400879f, 0.415771f, 0.431396f, 0.446777f, 0.463379f, 0.480469f, 0.497314f, 0.514160f,
+ 0.530273f, 0.547363f, 0.774414f, 0.783203f, 0.782715f, 0.779297f, 0.776367f, 0.773438f, 0.001690f, 0.005207f, 0.008278f, 0.011696f,
+ 0.015068f, 0.018784f, 0.022186f, 0.025909f, 0.029221f, 0.033508f, 0.037109f, 0.041321f, 0.045471f, 0.049774f, 0.054108f, 0.058838f,
+ 0.063843f, 0.069214f, 0.074280f, 0.080078f, 0.086243f, 0.091980f, 0.098083f, 0.105164f, 0.111877f, 0.119446f, 0.126953f, 0.134888f,
+ 0.143555f, 0.151978f, 0.161133f, 0.170532f, 0.180176f, 0.189697f, 0.200684f, 0.211182f, 0.222412f, 0.234009f, 0.245972f, 0.257568f,
+ 0.270508f, 0.282959f, 0.295898f, 0.309570f, 0.323486f, 0.337158f, 0.351562f, 0.366211f, 0.381104f, 0.396729f, 0.411865f, 0.427490f,
+ 0.443604f, 0.459961f, 0.477051f, 0.494385f, 0.510742f, 0.529297f, 0.763184f, 0.774902f, 0.773438f, 0.771973f, 0.769043f, 0.767578f,
+ 0.001528f, 0.004692f, 0.007587f, 0.010956f, 0.014221f, 0.016907f, 0.020218f, 0.023407f, 0.027283f, 0.030273f, 0.033997f, 0.038055f,
+ 0.041809f, 0.045959f, 0.049683f, 0.053955f, 0.058838f, 0.063171f, 0.068176f, 0.073120f, 0.078491f, 0.084473f, 0.090332f, 0.096619f,
+ 0.102905f, 0.109619f, 0.116699f, 0.124207f, 0.131958f, 0.140503f, 0.148438f, 0.157349f, 0.166626f, 0.176392f, 0.186157f, 0.196045f,
+ 0.207031f, 0.218018f, 0.229736f, 0.241699f, 0.253174f, 0.265381f, 0.278320f, 0.291748f, 0.305176f, 0.318848f, 0.333496f, 0.347412f,
+ 0.362305f, 0.376709f, 0.392822f, 0.407715f, 0.424072f, 0.440430f, 0.457031f, 0.473633f, 0.491211f, 0.508789f, 0.753906f, 0.766602f,
+ 0.767090f, 0.764160f, 0.761719f, 0.759766f, 0.001261f, 0.004250f, 0.007389f, 0.010185f, 0.013023f, 0.015976f, 0.018692f, 0.021713f,
+ 0.024734f, 0.028183f, 0.031464f, 0.034943f, 0.038452f, 0.041870f, 0.045410f, 0.049561f, 0.054047f, 0.058044f, 0.062164f, 0.067017f,
+ 0.071838f, 0.077332f, 0.082581f, 0.088318f, 0.094360f, 0.100525f, 0.107117f, 0.114258f, 0.121643f, 0.128540f, 0.136841f, 0.144897f,
+ 0.153931f, 0.162476f, 0.171875f, 0.182007f, 0.192139f, 0.202637f, 0.213623f, 0.224854f, 0.237183f, 0.248657f, 0.260986f, 0.274170f,
+ 0.287354f, 0.300781f, 0.314453f, 0.328613f, 0.343018f, 0.358643f, 0.373291f, 0.388916f, 0.404785f, 0.420654f, 0.437744f, 0.454590f,
+ 0.471924f, 0.489990f, 0.744629f, 0.757812f, 0.757812f, 0.756836f, 0.754395f, 0.752441f, 0.001527f, 0.004047f, 0.006680f, 0.009369f,
+ 0.012024f, 0.014618f, 0.017288f, 0.020248f, 0.022705f, 0.025803f, 0.028778f, 0.031769f, 0.034912f, 0.038330f, 0.041595f, 0.045166f,
+ 0.048737f, 0.052673f, 0.056885f, 0.061218f, 0.065552f, 0.070251f, 0.075012f, 0.080505f, 0.086060f, 0.091614f, 0.097656f, 0.104065f,
+ 0.110901f, 0.118225f, 0.125366f, 0.133179f, 0.141357f, 0.149902f, 0.158569f, 0.168213f, 0.177734f, 0.187866f, 0.198364f, 0.208984f,
+ 0.220581f, 0.232422f, 0.244019f, 0.256836f, 0.269287f, 0.282471f, 0.296143f, 0.309326f, 0.324463f, 0.338379f, 0.353760f, 0.368652f,
+ 0.385498f, 0.400635f, 0.417725f, 0.434570f, 0.451660f, 0.469482f, 0.733887f, 0.749023f, 0.750977f, 0.749023f, 0.747070f, 0.744629f,
+ 0.001313f, 0.003803f, 0.006126f, 0.008507f, 0.011185f, 0.013550f, 0.015839f, 0.018219f, 0.021027f, 0.023438f, 0.026520f, 0.029129f,
+ 0.031738f, 0.034821f, 0.037964f, 0.041138f, 0.044434f, 0.048035f, 0.051636f, 0.055420f, 0.059540f, 0.063782f, 0.068176f, 0.073181f,
+ 0.077881f, 0.083496f, 0.088989f, 0.094849f, 0.101440f, 0.107849f, 0.114441f, 0.121887f, 0.129395f, 0.137207f, 0.145874f, 0.154419f,
+ 0.163574f, 0.173462f, 0.183228f, 0.193726f, 0.204712f, 0.216064f, 0.227661f, 0.239624f, 0.251709f, 0.264648f, 0.277832f, 0.291504f,
+ 0.305664f, 0.320312f, 0.334473f, 0.349854f, 0.365479f, 0.380615f, 0.397217f, 0.414551f, 0.432129f, 0.449951f, 0.722656f, 0.740234f,
+ 0.741699f, 0.741211f, 0.739746f, 0.737793f, 0.001137f, 0.003654f, 0.005871f, 0.007881f, 0.010262f, 0.012268f, 0.014496f, 0.017059f,
+ 0.018890f, 0.021317f, 0.023605f, 0.026291f, 0.029007f, 0.031494f, 0.034515f, 0.036987f, 0.040375f, 0.043457f, 0.046936f, 0.050385f,
+ 0.053925f, 0.058044f, 0.061981f, 0.066650f, 0.070679f, 0.075562f, 0.080994f, 0.085938f, 0.091919f, 0.098450f, 0.104370f, 0.110840f,
+ 0.118164f, 0.125366f, 0.133301f, 0.141357f, 0.150024f, 0.159546f, 0.168457f, 0.178711f, 0.189453f, 0.199707f, 0.211060f, 0.222656f,
+ 0.234741f, 0.247314f, 0.260010f, 0.272705f, 0.287354f, 0.300781f, 0.315674f, 0.330322f, 0.345947f, 0.362061f, 0.377441f, 0.394775f,
+ 0.412109f, 0.429199f, 0.712891f, 0.730957f, 0.733398f, 0.733398f, 0.731445f, 0.729492f, 0.001163f, 0.003218f, 0.005329f, 0.007542f,
+ 0.009331f, 0.011330f, 0.013367f, 0.015434f, 0.017685f, 0.019714f, 0.021515f, 0.024139f, 0.026062f, 0.028763f, 0.031204f, 0.033722f,
+ 0.036163f, 0.039398f, 0.041992f, 0.045624f, 0.048553f, 0.051971f, 0.056000f, 0.059937f, 0.063904f, 0.068054f, 0.072876f, 0.077820f,
+ 0.083374f, 0.088623f, 0.094116f, 0.100830f, 0.107117f, 0.114197f, 0.121399f, 0.129272f, 0.136963f, 0.145630f, 0.154785f, 0.163696f,
+ 0.173828f, 0.184204f, 0.194946f, 0.205933f, 0.217529f, 0.229614f, 0.242676f, 0.255859f, 0.269043f, 0.282471f, 0.296387f, 0.311523f,
+ 0.326172f, 0.341553f, 0.357910f, 0.374756f, 0.391846f, 0.409180f, 0.701660f, 0.721680f, 0.723633f, 0.724609f, 0.723145f, 0.722656f,
+ 0.001008f, 0.003147f, 0.004818f, 0.006882f, 0.008530f, 0.010468f, 0.012390f, 0.013832f, 0.016006f, 0.017899f, 0.019608f, 0.021866f,
+ 0.023849f, 0.025940f, 0.027847f, 0.030350f, 0.032806f, 0.035187f, 0.037994f, 0.040619f, 0.043732f, 0.046875f, 0.050110f, 0.053833f,
+ 0.057617f, 0.061371f, 0.065613f, 0.070068f, 0.074768f, 0.079895f, 0.085144f, 0.090637f, 0.096863f, 0.103149f, 0.110107f, 0.116943f,
+ 0.124634f, 0.132568f, 0.140991f, 0.149536f, 0.159302f, 0.169189f, 0.179443f, 0.189575f, 0.201538f, 0.213013f, 0.225342f, 0.236938f,
+ 0.250244f, 0.264160f, 0.278320f, 0.292236f, 0.307617f, 0.322021f, 0.337891f, 0.354248f, 0.371582f, 0.389160f, 0.689941f, 0.712891f,
+ 0.715820f, 0.715820f, 0.715820f, 0.714355f, 0.001126f, 0.002708f, 0.004486f, 0.006313f, 0.007927f, 0.009659f, 0.011238f, 0.012833f,
+ 0.014435f, 0.015823f, 0.017670f, 0.019485f, 0.021347f, 0.023453f, 0.025101f, 0.027161f, 0.029160f, 0.031525f, 0.033752f, 0.036560f,
+ 0.039154f, 0.041687f, 0.044891f, 0.047943f, 0.051453f, 0.054871f, 0.058655f, 0.062622f, 0.067078f, 0.071411f, 0.076355f, 0.081665f,
+ 0.086792f, 0.092957f, 0.098877f, 0.105713f, 0.112549f, 0.119995f, 0.127563f, 0.135864f, 0.144897f, 0.154297f, 0.164185f, 0.173828f,
+ 0.185059f, 0.196045f, 0.208008f, 0.219849f, 0.232666f, 0.245483f, 0.259033f, 0.273438f, 0.287842f, 0.302734f, 0.318604f, 0.334473f,
+ 0.351318f, 0.369385f, 0.679688f, 0.702637f, 0.707031f, 0.707031f, 0.707031f, 0.705566f, 0.000980f, 0.002733f, 0.004021f, 0.005688f,
+ 0.007084f, 0.008553f, 0.010345f, 0.011513f, 0.012962f, 0.014297f, 0.015823f, 0.017609f, 0.019119f, 0.020721f, 0.022568f, 0.024200f,
+ 0.026291f, 0.028000f, 0.030457f, 0.032410f, 0.034912f, 0.037476f, 0.039734f, 0.042786f, 0.045563f, 0.048920f, 0.052185f, 0.055817f,
+ 0.059662f, 0.063660f, 0.067993f, 0.072632f, 0.077759f, 0.083191f, 0.088623f, 0.094971f, 0.101135f, 0.107849f, 0.115479f, 0.122864f,
+ 0.131592f, 0.139893f, 0.149414f, 0.158447f, 0.169067f, 0.179443f, 0.191040f, 0.202393f, 0.214478f, 0.227539f, 0.240723f, 0.255127f,
+ 0.268555f, 0.283447f, 0.298828f, 0.315186f, 0.331787f, 0.348389f, 0.667480f, 0.693359f, 0.697754f, 0.698730f, 0.698242f, 0.697754f,
+ 0.000870f, 0.002420f, 0.003994f, 0.005165f, 0.006584f, 0.007763f, 0.009209f, 0.010468f, 0.011604f, 0.013336f, 0.013977f, 0.015442f,
+ 0.016830f, 0.018509f, 0.020065f, 0.021606f, 0.023224f, 0.024933f, 0.026672f, 0.028656f, 0.030914f, 0.033112f, 0.035187f, 0.037689f,
+ 0.040344f, 0.043335f, 0.046234f, 0.049438f, 0.052948f, 0.056427f, 0.060394f, 0.064331f, 0.069031f, 0.073853f, 0.078735f, 0.084412f,
+ 0.090271f, 0.096436f, 0.103455f, 0.110229f, 0.118042f, 0.126099f, 0.134766f, 0.143921f, 0.153198f, 0.163696f, 0.174438f, 0.185913f,
+ 0.197754f, 0.210083f, 0.222778f, 0.235962f, 0.250000f, 0.264648f, 0.279053f, 0.294922f, 0.311279f, 0.328613f, 0.655273f, 0.684082f,
+ 0.688477f, 0.689941f, 0.689941f, 0.689941f, 0.000790f, 0.002153f, 0.003576f, 0.004726f, 0.005966f, 0.007172f, 0.008186f, 0.009453f,
+ 0.010521f, 0.011482f, 0.012772f, 0.013771f, 0.015144f, 0.016434f, 0.017792f, 0.019226f, 0.020355f, 0.022049f, 0.023666f, 0.025375f,
+ 0.027145f, 0.029297f, 0.030975f, 0.033142f, 0.035339f, 0.037964f, 0.040405f, 0.043365f, 0.046478f, 0.049744f, 0.053101f, 0.057068f,
+ 0.060944f, 0.065063f, 0.069763f, 0.074646f, 0.079956f, 0.085938f, 0.091675f, 0.098083f, 0.105164f, 0.112732f, 0.121033f, 0.129395f,
+ 0.138428f, 0.148560f, 0.158325f, 0.169067f, 0.180664f, 0.192139f, 0.205078f, 0.217529f, 0.231934f, 0.246094f, 0.260010f, 0.275391f,
+ 0.292236f, 0.309570f, 0.644043f, 0.673340f, 0.678711f, 0.680664f, 0.680664f, 0.680176f, 0.000538f, 0.002022f, 0.003185f, 0.004456f,
+ 0.005360f, 0.006321f, 0.007286f, 0.008484f, 0.009422f, 0.010185f, 0.011177f, 0.012283f, 0.013191f, 0.014435f, 0.015587f, 0.016769f,
+ 0.017914f, 0.019302f, 0.020584f, 0.022171f, 0.023819f, 0.025391f, 0.027222f, 0.028992f, 0.030914f, 0.033234f, 0.035461f, 0.037903f,
+ 0.040649f, 0.043396f, 0.046326f, 0.049561f, 0.053131f, 0.056946f, 0.061279f, 0.065613f, 0.070374f, 0.075439f, 0.080811f, 0.086731f,
+ 0.093140f, 0.100037f, 0.107544f, 0.115662f, 0.124023f, 0.132935f, 0.143066f, 0.153320f, 0.163696f, 0.175415f, 0.187012f, 0.200195f,
+ 0.213013f, 0.227173f, 0.241455f, 0.256592f, 0.272461f, 0.288330f, 0.632812f, 0.663574f, 0.669434f, 0.670898f, 0.671387f, 0.671875f,
+ 0.000686f, 0.001864f, 0.002884f, 0.003883f, 0.004829f, 0.005592f, 0.006504f, 0.007454f, 0.008064f, 0.008995f, 0.009850f, 0.010948f,
+ 0.011711f, 0.012581f, 0.013763f, 0.014618f, 0.015701f, 0.016953f, 0.018112f, 0.019180f, 0.020691f, 0.021973f, 0.023560f, 0.025192f,
+ 0.026962f, 0.028717f, 0.030624f, 0.032959f, 0.035004f, 0.037567f, 0.040314f, 0.043121f, 0.046204f, 0.049713f, 0.053284f, 0.057129f,
+ 0.061157f, 0.065796f, 0.071167f, 0.076477f, 0.082214f, 0.088379f, 0.095276f, 0.102600f, 0.110596f, 0.118652f, 0.127808f, 0.137817f,
+ 0.147705f, 0.158569f, 0.170166f, 0.182251f, 0.195068f, 0.208008f, 0.222656f, 0.237671f, 0.252686f, 0.269287f, 0.620605f, 0.653320f,
+ 0.659180f, 0.661621f, 0.663086f, 0.663574f, 0.000782f, 0.001828f, 0.002949f, 0.003487f, 0.004421f, 0.005032f, 0.005878f, 0.006557f,
+ 0.007332f, 0.008110f, 0.008591f, 0.009537f, 0.010094f, 0.011147f, 0.011864f, 0.012779f, 0.013573f, 0.014549f, 0.015625f, 0.016846f,
+ 0.017822f, 0.018936f, 0.020279f, 0.021729f, 0.023117f, 0.024704f, 0.026505f, 0.028183f, 0.030289f, 0.032349f, 0.034546f, 0.037109f,
+ 0.039703f, 0.042786f, 0.045837f, 0.049133f, 0.053009f, 0.056763f, 0.061584f, 0.066284f, 0.071411f, 0.076843f, 0.083191f, 0.089722f,
+ 0.097290f, 0.104919f, 0.113647f, 0.122498f, 0.132324f, 0.142578f, 0.153809f, 0.164917f, 0.177612f, 0.190430f, 0.203857f, 0.218506f,
+ 0.233887f, 0.249390f, 0.606934f, 0.642578f, 0.649414f, 0.653320f, 0.652832f, 0.654785f, 0.000604f, 0.001636f, 0.002550f, 0.003180f,
+ 0.003799f, 0.004498f, 0.005051f, 0.005573f, 0.006325f, 0.006836f, 0.007607f, 0.008087f, 0.008820f, 0.009483f, 0.010132f, 0.010918f,
+ 0.011665f, 0.012527f, 0.013535f, 0.014297f, 0.015251f, 0.016190f, 0.017288f, 0.018433f, 0.019791f, 0.021133f, 0.022400f, 0.023865f,
+ 0.025742f, 0.027664f, 0.029373f, 0.031677f, 0.034027f, 0.036255f, 0.039032f, 0.042023f, 0.045197f, 0.048798f, 0.052643f, 0.056824f,
+ 0.061493f, 0.066467f, 0.072327f, 0.078308f, 0.084473f, 0.091858f, 0.099609f, 0.108032f, 0.117249f, 0.126831f, 0.137451f, 0.148193f,
+ 0.160034f, 0.172729f, 0.186035f, 0.199829f, 0.214722f, 0.229980f, 0.596680f, 0.632812f, 0.638672f, 0.642578f, 0.644531f, 0.645020f,
+ 0.000447f, 0.001384f, 0.001986f, 0.002697f, 0.003225f, 0.003828f, 0.004501f, 0.005009f, 0.005459f, 0.006027f, 0.006474f, 0.006935f,
+ 0.007591f, 0.008217f, 0.008644f, 0.009308f, 0.010025f, 0.010498f, 0.011330f, 0.012100f, 0.012909f, 0.013924f, 0.014618f, 0.015610f,
+ 0.016739f, 0.017807f, 0.019043f, 0.020340f, 0.021622f, 0.023178f, 0.024979f, 0.026520f, 0.028366f, 0.030640f, 0.032959f, 0.035492f,
+ 0.038239f, 0.041260f, 0.044495f, 0.048340f, 0.052399f, 0.056732f, 0.061768f, 0.067017f, 0.072754f, 0.079224f, 0.086304f, 0.093994f,
+ 0.102478f, 0.111511f, 0.121521f, 0.132080f, 0.143311f, 0.155518f, 0.168213f, 0.181763f, 0.196411f, 0.211548f, 0.583008f, 0.621094f,
+ 0.629395f, 0.632324f, 0.634766f, 0.635742f, 0.000375f, 0.001324f, 0.001728f, 0.002466f, 0.002872f, 0.003384f, 0.003685f, 0.004185f,
+ 0.004845f, 0.005184f, 0.005444f, 0.006130f, 0.006401f, 0.006844f, 0.007446f, 0.007957f, 0.008636f, 0.008965f, 0.009659f, 0.010139f,
+ 0.010971f, 0.011742f, 0.012497f, 0.013138f, 0.014099f, 0.014992f, 0.015900f, 0.017166f, 0.018143f, 0.019485f, 0.020676f, 0.022156f,
+ 0.023697f, 0.025528f, 0.027374f, 0.029556f, 0.031921f, 0.034424f, 0.037445f, 0.040375f, 0.044067f, 0.047577f, 0.052155f, 0.056824f,
+ 0.062042f, 0.067688f, 0.074158f, 0.081055f, 0.088745f, 0.097351f, 0.106323f, 0.116455f, 0.127075f, 0.138672f, 0.151123f, 0.164062f,
+ 0.177856f, 0.192871f, 0.570801f, 0.610840f, 0.619629f, 0.623047f, 0.625488f, 0.625977f, 0.000432f, 0.000921f, 0.001664f, 0.002056f,
+ 0.002697f, 0.003061f, 0.003326f, 0.003757f, 0.004044f, 0.004379f, 0.004761f, 0.004948f, 0.005463f, 0.005791f, 0.006199f, 0.006752f,
+ 0.007229f, 0.007526f, 0.008156f, 0.008621f, 0.009193f, 0.009712f, 0.010330f, 0.010994f, 0.011688f, 0.012466f, 0.013374f, 0.014153f,
+ 0.015099f, 0.016083f, 0.017212f, 0.018250f, 0.019623f, 0.021210f, 0.022614f, 0.024445f, 0.026321f, 0.028351f, 0.030762f, 0.033325f,
+ 0.036377f, 0.039642f, 0.043304f, 0.047485f, 0.051880f, 0.056885f, 0.062469f, 0.068542f, 0.075623f, 0.083374f, 0.091919f, 0.101135f,
+ 0.111389f, 0.122559f, 0.134277f, 0.146606f, 0.160278f, 0.174683f, 0.557617f, 0.600098f, 0.609375f, 0.612793f, 0.615723f, 0.616699f,
+ 0.000255f, 0.000997f, 0.001393f, 0.001908f, 0.002239f, 0.002512f, 0.002720f, 0.003166f, 0.003283f, 0.003616f, 0.003866f, 0.004223f,
+ 0.004597f, 0.004795f, 0.005127f, 0.005573f, 0.005939f, 0.006359f, 0.006657f, 0.007133f, 0.007687f, 0.008041f, 0.008545f, 0.009087f,
+ 0.009636f, 0.010300f, 0.010910f, 0.011757f, 0.012489f, 0.013313f, 0.014153f, 0.014954f, 0.016037f, 0.017258f, 0.018555f, 0.019867f,
+ 0.021530f, 0.023239f, 0.025055f, 0.027252f, 0.029663f, 0.032379f, 0.035339f, 0.038666f, 0.042664f, 0.047058f, 0.051849f, 0.057465f,
+ 0.063416f, 0.070557f, 0.078369f, 0.086731f, 0.096313f, 0.106384f, 0.117798f, 0.129761f, 0.143311f, 0.156982f, 0.544922f, 0.588867f,
+ 0.599121f, 0.602539f, 0.605469f, 0.606445f, 0.000353f, 0.000879f, 0.001276f, 0.001613f, 0.001785f, 0.002075f, 0.002300f, 0.002501f,
+ 0.002808f, 0.003010f, 0.003283f, 0.003487f, 0.003714f, 0.003967f, 0.004269f, 0.004597f, 0.004837f, 0.005230f, 0.005512f, 0.005878f,
+ 0.006203f, 0.006626f, 0.007030f, 0.007519f, 0.007866f, 0.008354f, 0.009010f, 0.009468f, 0.010017f, 0.010765f, 0.011444f, 0.012291f,
+ 0.013100f, 0.014030f, 0.015030f, 0.016098f, 0.017441f, 0.018646f, 0.020157f, 0.021912f, 0.023804f, 0.026047f, 0.028488f, 0.031342f,
+ 0.034424f, 0.037994f, 0.042206f, 0.046997f, 0.052338f, 0.058533f, 0.065369f, 0.073364f, 0.081787f, 0.091492f, 0.102356f, 0.113647f,
+ 0.126343f, 0.139526f, 0.531250f, 0.579102f, 0.587891f, 0.592773f, 0.595703f, 0.596680f, 0.000295f, 0.000784f, 0.000912f, 0.001261f,
+ 0.001517f, 0.001761f, 0.001893f, 0.002113f, 0.002211f, 0.002432f, 0.002676f, 0.002861f, 0.002993f, 0.003294f, 0.003479f, 0.003700f,
+ 0.003933f, 0.004242f, 0.004452f, 0.004745f, 0.004974f, 0.005428f, 0.005642f, 0.006081f, 0.006401f, 0.006817f, 0.007240f, 0.007641f,
+ 0.008209f, 0.008667f, 0.009361f, 0.009720f, 0.010506f, 0.011261f, 0.012024f, 0.012794f, 0.013840f, 0.014893f, 0.016113f, 0.017395f,
+ 0.018860f, 0.020493f, 0.022446f, 0.024658f, 0.027283f, 0.030228f, 0.033691f, 0.037659f, 0.042145f, 0.047546f, 0.053467f, 0.060547f,
+ 0.068359f, 0.077332f, 0.087158f, 0.098145f, 0.109741f, 0.123230f, 0.517090f, 0.566895f, 0.576660f, 0.581543f, 0.584961f, 0.587402f,
+ 0.000247f, 0.000702f, 0.000849f, 0.001033f, 0.001304f, 0.001416f, 0.001576f, 0.001754f, 0.001860f, 0.001953f, 0.002104f, 0.002327f,
+ 0.002419f, 0.002651f, 0.002785f, 0.003014f, 0.003134f, 0.003315f, 0.003584f, 0.003813f, 0.004078f, 0.004295f, 0.004555f, 0.004784f,
+ 0.005013f, 0.005329f, 0.005669f, 0.006069f, 0.006439f, 0.006821f, 0.007381f, 0.007797f, 0.008301f, 0.008812f, 0.009430f, 0.010139f,
+ 0.010948f, 0.011642f, 0.012573f, 0.013664f, 0.014671f, 0.016052f, 0.017502f, 0.019135f, 0.021255f, 0.023438f, 0.026199f, 0.029312f,
+ 0.033203f, 0.037476f, 0.042725f, 0.048828f, 0.055695f, 0.063721f, 0.072937f, 0.082947f, 0.094666f, 0.107117f, 0.504883f, 0.555664f,
+ 0.566406f, 0.572754f, 0.574707f, 0.577148f, 0.000217f, 0.000516f, 0.000750f, 0.000898f, 0.001011f, 0.001117f, 0.001203f, 0.001307f,
+ 0.001470f, 0.001604f, 0.001659f, 0.001750f, 0.001945f, 0.002121f, 0.002249f, 0.002316f, 0.002478f, 0.002581f, 0.002832f, 0.003000f,
+ 0.003164f, 0.003334f, 0.003593f, 0.003784f, 0.003990f, 0.004196f, 0.004440f, 0.004673f, 0.005035f, 0.005329f, 0.005642f, 0.005981f,
+ 0.006462f, 0.006916f, 0.007313f, 0.007805f, 0.008377f, 0.008987f, 0.009727f, 0.010521f, 0.011314f, 0.012421f, 0.013466f, 0.014755f,
+ 0.016235f, 0.017914f, 0.019913f, 0.022461f, 0.025330f, 0.028778f, 0.033081f, 0.038239f, 0.044189f, 0.051422f, 0.059662f, 0.069336f,
+ 0.080200f, 0.091980f, 0.492676f, 0.543945f, 0.555664f, 0.561035f, 0.564453f, 0.566406f, 0.000131f, 0.000355f, 0.000605f, 0.000759f,
+ 0.000832f, 0.000904f, 0.001018f, 0.000975f, 0.001144f, 0.001235f, 0.001336f, 0.001447f, 0.001518f, 0.001620f, 0.001668f, 0.001835f,
+ 0.001901f, 0.002045f, 0.002188f, 0.002270f, 0.002424f, 0.002577f, 0.002707f, 0.002893f, 0.003002f, 0.003223f, 0.003407f, 0.003572f,
+ 0.003851f, 0.004017f, 0.004391f, 0.004608f, 0.004833f, 0.005203f, 0.005497f, 0.005886f, 0.006351f, 0.006771f, 0.007278f, 0.007858f,
+ 0.008560f, 0.009315f, 0.010086f, 0.011078f, 0.012222f, 0.013443f, 0.015022f, 0.016769f, 0.018967f, 0.021591f, 0.024780f, 0.028931f,
+ 0.033875f, 0.039734f, 0.047241f, 0.056122f, 0.066101f, 0.077637f, 0.477783f, 0.532715f, 0.544922f, 0.551270f, 0.553711f, 0.555664f,
+ 0.000245f, 0.000303f, 0.000473f, 0.000498f, 0.000544f, 0.000707f, 0.000700f, 0.000767f, 0.000802f, 0.000892f, 0.001021f, 0.001086f,
+ 0.001140f, 0.001260f, 0.001303f, 0.001325f, 0.001462f, 0.001553f, 0.001603f, 0.001746f, 0.001816f, 0.001904f, 0.002043f, 0.002127f,
+ 0.002254f, 0.002356f, 0.002548f, 0.002672f, 0.002851f, 0.003092f, 0.003265f, 0.003374f, 0.003647f, 0.003891f, 0.004097f, 0.004360f,
+ 0.004669f, 0.004997f, 0.005390f, 0.005810f, 0.006226f, 0.006756f, 0.007450f, 0.008095f, 0.008934f, 0.009827f, 0.010902f, 0.012268f,
+ 0.013840f, 0.015701f, 0.018036f, 0.021072f, 0.024948f, 0.029800f, 0.035980f, 0.043945f, 0.053345f, 0.063843f, 0.465576f, 0.520996f,
+ 0.535645f, 0.540039f, 0.543457f, 0.545898f, 0.000108f, 0.000275f, 0.000332f, 0.000402f, 0.000462f, 0.000468f, 0.000580f, 0.000522f,
+ 0.000616f, 0.000657f, 0.000758f, 0.000762f, 0.000812f, 0.000870f, 0.000945f, 0.000978f, 0.001054f, 0.001109f, 0.001179f, 0.001213f,
+ 0.001311f, 0.001371f, 0.001473f, 0.001558f, 0.001629f, 0.001718f, 0.001837f, 0.001903f, 0.002016f, 0.002159f, 0.002258f, 0.002478f,
+ 0.002548f, 0.002731f, 0.002909f, 0.003086f, 0.003317f, 0.003580f, 0.003885f, 0.004116f, 0.004421f, 0.004818f, 0.005264f, 0.005745f,
+ 0.006294f, 0.006966f, 0.007748f, 0.008667f, 0.009766f, 0.011086f, 0.012787f, 0.014908f, 0.017746f, 0.021271f, 0.026382f, 0.032990f,
+ 0.041199f, 0.051239f, 0.452393f, 0.509277f, 0.522461f, 0.529297f, 0.533203f, 0.535156f, 0.000016f, 0.000143f, 0.000244f, 0.000315f,
+ 0.000309f, 0.000391f, 0.000344f, 0.000402f, 0.000429f, 0.000517f, 0.000522f, 0.000526f, 0.000546f, 0.000606f, 0.000628f, 0.000705f,
+ 0.000692f, 0.000781f, 0.000837f, 0.000868f, 0.000923f, 0.000969f, 0.001013f, 0.001070f, 0.001142f, 0.001186f, 0.001273f, 0.001326f,
+ 0.001397f, 0.001534f, 0.001561f, 0.001685f, 0.001775f, 0.001873f, 0.002024f, 0.002153f, 0.002272f, 0.002443f, 0.002611f, 0.002800f,
+ 0.003014f, 0.003250f, 0.003529f, 0.003868f, 0.004227f, 0.004692f, 0.005192f, 0.005836f, 0.006603f, 0.007587f, 0.008751f, 0.010193f,
+ 0.012001f, 0.014610f, 0.018219f, 0.023392f, 0.030594f, 0.039795f, 0.437744f, 0.498291f, 0.512207f, 0.517578f, 0.521484f, 0.525391f,
+ 0.000102f, 0.000186f, 0.000171f, 0.000181f, 0.000227f, 0.000229f, 0.000231f, 0.000278f, 0.000293f, 0.000304f, 0.000314f, 0.000375f,
+ 0.000365f, 0.000411f, 0.000446f, 0.000457f, 0.000496f, 0.000513f, 0.000533f, 0.000554f, 0.000603f, 0.000622f, 0.000669f, 0.000708f,
+ 0.000757f, 0.000789f, 0.000843f, 0.000875f, 0.000925f, 0.000964f, 0.001037f, 0.001094f, 0.001172f, 0.001243f, 0.001324f, 0.001373f,
+ 0.001497f, 0.001570f, 0.001712f, 0.001829f, 0.001947f, 0.002123f, 0.002291f, 0.002472f, 0.002703f, 0.003008f, 0.003342f, 0.003757f,
+ 0.004204f, 0.004810f, 0.005539f, 0.006554f, 0.007828f, 0.009537f, 0.011894f, 0.015442f, 0.021072f, 0.029282f, 0.424561f, 0.486084f,
+ 0.500488f, 0.506836f, 0.512207f, 0.514648f, 0.000014f, 0.000127f, 0.000112f, 0.000109f, 0.000143f, 0.000165f, 0.000141f, 0.000180f,
+ 0.000185f, 0.000191f, 0.000196f, 0.000203f, 0.000233f, 0.000252f, 0.000260f, 0.000274f, 0.000288f, 0.000314f, 0.000328f, 0.000363f,
+ 0.000362f, 0.000374f, 0.000400f, 0.000436f, 0.000464f, 0.000501f, 0.000504f, 0.000521f, 0.000563f, 0.000593f, 0.000635f, 0.000671f,
+ 0.000712f, 0.000740f, 0.000800f, 0.000837f, 0.000892f, 0.000955f, 0.001030f, 0.001092f, 0.001167f, 0.001270f, 0.001369f, 0.001491f,
+ 0.001626f, 0.001769f, 0.001993f, 0.002209f, 0.002523f, 0.002863f, 0.003325f, 0.003880f, 0.004715f, 0.005764f, 0.007320f, 0.009468f,
+ 0.013344f, 0.020187f, 0.410645f, 0.473877f, 0.489258f, 0.496826f, 0.500488f, 0.503906f, 0.000103f, 0.000078f, 0.000067f, 0.000065f,
+ 0.000086f, 0.000085f, 0.000101f, 0.000106f, 0.000106f, 0.000107f, 0.000115f, 0.000133f, 0.000118f, 0.000133f, 0.000154f, 0.000150f,
+ 0.000167f, 0.000177f, 0.000180f, 0.000190f, 0.000207f, 0.000213f, 0.000228f, 0.000238f, 0.000267f, 0.000277f, 0.000287f, 0.000298f,
+ 0.000313f, 0.000325f, 0.000347f, 0.000375f, 0.000393f, 0.000405f, 0.000440f, 0.000463f, 0.000486f, 0.000527f, 0.000562f, 0.000599f,
+ 0.000639f, 0.000688f, 0.000757f, 0.000807f, 0.000879f, 0.000961f, 0.001059f, 0.001180f, 0.001342f, 0.001533f, 0.001762f, 0.002102f,
+ 0.002502f, 0.003128f, 0.004028f, 0.005379f, 0.007591f, 0.012505f, 0.397217f, 0.462891f, 0.478760f, 0.485840f, 0.490479f, 0.492676f,
+ 0.000087f, 0.000063f, 0.000054f, 0.000048f, 0.000047f, 0.000044f, 0.000046f, 0.000047f, 0.000047f, 0.000060f, 0.000053f, 0.000056f,
+ 0.000072f, 0.000060f, 0.000064f, 0.000069f, 0.000078f, 0.000085f, 0.000084f, 0.000090f, 0.000094f, 0.000102f, 0.000105f, 0.000111f,
+ 0.000116f, 0.000126f, 0.000132f, 0.000150f, 0.000147f, 0.000158f, 0.000167f, 0.000178f, 0.000185f, 0.000192f, 0.000211f, 0.000216f,
+ 0.000226f, 0.000246f, 0.000265f, 0.000284f, 0.000299f, 0.000325f, 0.000349f, 0.000381f, 0.000415f, 0.000448f, 0.000490f, 0.000544f,
+ 0.000612f, 0.000694f, 0.000798f, 0.000943f, 0.001139f, 0.001436f, 0.001870f, 0.002586f, 0.003817f, 0.006474f, 0.383545f, 0.450195f,
+ 0.467041f, 0.474365f, 0.478760f, 0.482422f, 0.000065f, 0.000045f, 0.000037f, 0.000033f, 0.000030f, 0.000028f, 0.000026f, 0.000025f,
+ 0.000024f, 0.000022f, 0.000021f, 0.000025f, 0.000020f, 0.000021f, 0.000025f, 0.000029f, 0.000028f, 0.000031f, 0.000033f, 0.000034f,
+ 0.000036f, 0.000041f, 0.000045f, 0.000040f, 0.000045f, 0.000049f, 0.000051f, 0.000048f, 0.000055f, 0.000057f, 0.000061f, 0.000066f,
+ 0.000072f, 0.000068f, 0.000073f, 0.000078f, 0.000087f, 0.000089f, 0.000097f, 0.000104f, 0.000113f, 0.000115f, 0.000128f, 0.000137f,
+ 0.000148f, 0.000160f, 0.000174f, 0.000194f, 0.000221f, 0.000248f, 0.000283f, 0.000324f, 0.000396f, 0.000496f, 0.000657f, 0.000928f,
+ 0.001479f, 0.002684f, 0.371094f, 0.438477f, 0.455078f, 0.463867f, 0.468750f, 0.471191f, 0.000029f, 0.000019f, 0.000016f, 0.000014f,
+ 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f,
+ 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000007f, 0.000008f, 0.000007f, 0.000008f, 0.000009f, 0.000010f, 0.000011f,
+ 0.000012f, 0.000011f, 0.000012f, 0.000013f, 0.000015f, 0.000017f, 0.000018f, 0.000018f, 0.000020f, 0.000019f, 0.000021f, 0.000024f,
+ 0.000024f, 0.000026f, 0.000028f, 0.000031f, 0.000031f, 0.000035f, 0.000040f, 0.000041f, 0.000045f, 0.000052f, 0.000059f, 0.000071f,
+ 0.000083f, 0.000099f, 0.000132f, 0.000188f, 0.000315f, 0.000712f, 0.356934f, 0.426514f, 0.444824f, 0.452637f, 0.457520f, 0.460938f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000001f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000006f, 0.000010f, 0.000027f, 0.343750f, 0.414795f,
+ 0.433105f, 0.441895f, 0.446289f, 0.449951f,
+ },
+ {
+ 0.012436f, 0.037598f, 0.062805f, 0.087891f, 0.113037f, 0.137329f, 0.161621f, 0.185425f, 0.209717f, 0.232544f, 0.255371f, 0.278076f,
+ 0.300049f, 0.321289f, 0.343506f, 0.364014f, 0.385010f, 0.404785f, 0.424561f, 0.444824f, 0.463623f, 0.482422f, 0.501465f, 0.520020f,
+ 0.537598f, 0.554688f, 0.572266f, 0.589355f, 0.605957f, 0.622070f, 0.639648f, 0.655273f, 0.670410f, 0.685547f, 0.700684f, 0.715332f,
+ 0.730469f, 0.744629f, 0.758301f, 0.771973f, 0.785156f, 0.799316f, 0.812012f, 0.825684f, 0.837891f, 0.850586f, 0.863281f, 0.875000f,
+ 0.887207f, 0.898926f, 0.910156f, 0.921387f, 0.933105f, 0.944336f, 0.954102f, 0.964844f, 0.976074f, 0.985840f, 0.978027f, 0.947266f,
+ 0.925781f, 0.907715f, 0.892090f, 0.877930f, 0.011276f, 0.034546f, 0.058289f, 0.082031f, 0.105469f, 0.128662f, 0.152344f, 0.174805f,
+ 0.197876f, 0.219604f, 0.241455f, 0.263672f, 0.284912f, 0.306152f, 0.326416f, 0.347168f, 0.366699f, 0.387695f, 0.406494f, 0.426025f,
+ 0.444824f, 0.463379f, 0.481934f, 0.500000f, 0.518066f, 0.535645f, 0.552246f, 0.569824f, 0.586426f, 0.603027f, 0.619141f, 0.634766f,
+ 0.650391f, 0.666016f, 0.681152f, 0.695801f, 0.710938f, 0.725586f, 0.739258f, 0.753906f, 0.768066f, 0.781250f, 0.794922f, 0.807617f,
+ 0.821289f, 0.833496f, 0.846191f, 0.858398f, 0.870605f, 0.882812f, 0.894531f, 0.906250f, 0.917480f, 0.929199f, 0.939453f, 0.951660f,
+ 0.961426f, 0.972656f, 0.971680f, 0.942871f, 0.921875f, 0.904785f, 0.889160f, 0.875977f, 0.010628f, 0.032288f, 0.054932f, 0.076172f,
+ 0.099060f, 0.121216f, 0.142700f, 0.164795f, 0.186279f, 0.207642f, 0.229248f, 0.249756f, 0.269531f, 0.291016f, 0.310791f, 0.331543f,
+ 0.349609f, 0.369385f, 0.388916f, 0.409180f, 0.427246f, 0.444824f, 0.463135f, 0.480713f, 0.499512f, 0.516602f, 0.533203f, 0.550293f,
+ 0.567383f, 0.583496f, 0.599609f, 0.615723f, 0.630859f, 0.646973f, 0.661621f, 0.677246f, 0.691895f, 0.705566f, 0.720703f, 0.735352f,
+ 0.749512f, 0.763184f, 0.776367f, 0.790039f, 0.803223f, 0.816406f, 0.828613f, 0.842285f, 0.854492f, 0.867676f, 0.878418f, 0.890137f,
+ 0.902832f, 0.913086f, 0.925293f, 0.936035f, 0.947754f, 0.958008f, 0.964844f, 0.937500f, 0.917480f, 0.901367f, 0.886719f, 0.873535f,
+ 0.009926f, 0.030167f, 0.050995f, 0.071594f, 0.092346f, 0.113892f, 0.134399f, 0.154663f, 0.175537f, 0.195679f, 0.216309f, 0.235840f,
+ 0.256104f, 0.276611f, 0.295654f, 0.314453f, 0.333496f, 0.353027f, 0.370850f, 0.389404f, 0.408936f, 0.427490f, 0.445312f, 0.462891f,
+ 0.480225f, 0.497803f, 0.513672f, 0.531250f, 0.547363f, 0.563965f, 0.580078f, 0.597168f, 0.612305f, 0.627930f, 0.642578f, 0.658691f,
+ 0.673340f, 0.687500f, 0.702637f, 0.717285f, 0.731445f, 0.744629f, 0.758301f, 0.772461f, 0.786133f, 0.799316f, 0.811523f, 0.824707f,
+ 0.837891f, 0.849121f, 0.861816f, 0.874023f, 0.887207f, 0.898438f, 0.910156f, 0.920898f, 0.932617f, 0.943848f, 0.958008f, 0.932129f,
+ 0.913086f, 0.897461f, 0.883301f, 0.871094f, 0.009178f, 0.028107f, 0.047729f, 0.066895f, 0.086182f, 0.106384f, 0.125977f, 0.145386f,
+ 0.165527f, 0.184937f, 0.203857f, 0.224121f, 0.242676f, 0.261475f, 0.281006f, 0.300049f, 0.318604f, 0.336426f, 0.355469f, 0.372314f,
+ 0.391113f, 0.409424f, 0.426514f, 0.444092f, 0.461426f, 0.477783f, 0.495850f, 0.512207f, 0.528809f, 0.544434f, 0.561035f, 0.576660f,
+ 0.593262f, 0.608398f, 0.623047f, 0.638184f, 0.655273f, 0.668945f, 0.682617f, 0.697754f, 0.712402f, 0.726562f, 0.740234f, 0.753906f,
+ 0.768066f, 0.781250f, 0.794434f, 0.807617f, 0.820312f, 0.833496f, 0.845215f, 0.858398f, 0.870605f, 0.881836f, 0.894043f, 0.906738f,
+ 0.917480f, 0.928711f, 0.951172f, 0.926758f, 0.909180f, 0.893555f, 0.880859f, 0.868164f, 0.008667f, 0.025986f, 0.044922f, 0.062805f,
+ 0.081421f, 0.099854f, 0.118347f, 0.137085f, 0.155518f, 0.173828f, 0.193115f, 0.211304f, 0.229858f, 0.248413f, 0.266602f, 0.285400f,
+ 0.303223f, 0.321045f, 0.339111f, 0.357178f, 0.373779f, 0.391357f, 0.409424f, 0.426270f, 0.443115f, 0.460449f, 0.476807f, 0.494141f,
+ 0.510254f, 0.526855f, 0.541992f, 0.559082f, 0.574219f, 0.589355f, 0.605469f, 0.620117f, 0.636230f, 0.649902f, 0.664551f, 0.678711f,
+ 0.693848f, 0.707031f, 0.723145f, 0.736328f, 0.750977f, 0.762695f, 0.776855f, 0.790039f, 0.803223f, 0.816406f, 0.828613f, 0.842285f,
+ 0.853516f, 0.866211f, 0.878906f, 0.890625f, 0.902832f, 0.913574f, 0.944336f, 0.921875f, 0.903809f, 0.889160f, 0.876953f, 0.865234f,
+ 0.008057f, 0.024658f, 0.041321f, 0.058411f, 0.075989f, 0.093811f, 0.110535f, 0.128784f, 0.146729f, 0.164307f, 0.182007f, 0.200073f,
+ 0.217773f, 0.234619f, 0.252930f, 0.271240f, 0.288086f, 0.306152f, 0.322998f, 0.341064f, 0.357910f, 0.374756f, 0.391357f, 0.409180f,
+ 0.425293f, 0.442383f, 0.458496f, 0.475342f, 0.491455f, 0.507324f, 0.523438f, 0.539551f, 0.555176f, 0.570312f, 0.585938f, 0.601074f,
+ 0.616699f, 0.631836f, 0.646484f, 0.660645f, 0.676270f, 0.688477f, 0.704102f, 0.718262f, 0.731445f, 0.745117f, 0.760254f, 0.771484f,
+ 0.785156f, 0.799316f, 0.812500f, 0.824707f, 0.836914f, 0.850098f, 0.862793f, 0.874512f, 0.886719f, 0.898438f, 0.937500f, 0.915527f,
+ 0.899414f, 0.885254f, 0.872559f, 0.861816f, 0.007477f, 0.022919f, 0.038971f, 0.054901f, 0.070801f, 0.087646f, 0.104065f, 0.121155f,
+ 0.137573f, 0.155029f, 0.171875f, 0.188721f, 0.206177f, 0.222778f, 0.240112f, 0.257080f, 0.274170f, 0.290283f, 0.308350f, 0.324463f,
+ 0.342041f, 0.358154f, 0.375488f, 0.391113f, 0.407471f, 0.424561f, 0.440430f, 0.456787f, 0.474121f, 0.489746f, 0.505371f, 0.521484f,
+ 0.536133f, 0.552246f, 0.565918f, 0.582031f, 0.597168f, 0.613281f, 0.626953f, 0.642578f, 0.656738f, 0.670898f, 0.684570f, 0.699219f,
+ 0.712891f, 0.727539f, 0.741211f, 0.754395f, 0.768066f, 0.781738f, 0.794434f, 0.808105f, 0.820312f, 0.833984f, 0.846680f, 0.858887f,
+ 0.871582f, 0.883301f, 0.930176f, 0.910156f, 0.894043f, 0.880371f, 0.868652f, 0.858398f, 0.007023f, 0.021240f, 0.036224f, 0.051300f,
+ 0.066467f, 0.082092f, 0.097900f, 0.113892f, 0.129517f, 0.145752f, 0.161743f, 0.178223f, 0.194702f, 0.210327f, 0.227661f, 0.243408f,
+ 0.260986f, 0.276855f, 0.292725f, 0.309814f, 0.326172f, 0.342041f, 0.358398f, 0.375732f, 0.391113f, 0.406982f, 0.422852f, 0.438965f,
+ 0.454590f, 0.471191f, 0.486816f, 0.502441f, 0.517578f, 0.533203f, 0.548340f, 0.562988f, 0.578613f, 0.593750f, 0.609375f, 0.623535f,
+ 0.638184f, 0.652832f, 0.666992f, 0.680664f, 0.695312f, 0.708984f, 0.722656f, 0.736816f, 0.750000f, 0.764160f, 0.777344f, 0.789551f,
+ 0.803223f, 0.816895f, 0.830078f, 0.842773f, 0.854980f, 0.868652f, 0.922852f, 0.904297f, 0.889160f, 0.875977f, 0.864746f, 0.854492f,
+ 0.006458f, 0.019913f, 0.033691f, 0.048126f, 0.062744f, 0.077026f, 0.092224f, 0.106567f, 0.122192f, 0.137207f, 0.152222f, 0.167725f,
+ 0.183838f, 0.199951f, 0.215088f, 0.231323f, 0.246826f, 0.262695f, 0.279053f, 0.294678f, 0.310547f, 0.326172f, 0.342041f, 0.358887f,
+ 0.374268f, 0.389893f, 0.405518f, 0.421143f, 0.437012f, 0.452637f, 0.467773f, 0.483643f, 0.499512f, 0.513672f, 0.529785f, 0.545410f,
+ 0.560059f, 0.575195f, 0.590332f, 0.604980f, 0.618652f, 0.634277f, 0.648438f, 0.662598f, 0.676270f, 0.690918f, 0.704102f, 0.718750f,
+ 0.732422f, 0.745605f, 0.760254f, 0.773438f, 0.786621f, 0.801270f, 0.812988f, 0.826172f, 0.839844f, 0.851562f, 0.915527f, 0.897949f,
+ 0.883789f, 0.871094f, 0.860352f, 0.850586f, 0.006077f, 0.018921f, 0.031464f, 0.045258f, 0.058411f, 0.072144f, 0.085999f, 0.100220f,
+ 0.114258f, 0.129028f, 0.143677f, 0.158691f, 0.173584f, 0.188477f, 0.203247f, 0.219238f, 0.234497f, 0.249634f, 0.264893f, 0.280273f,
+ 0.295410f, 0.310791f, 0.326904f, 0.342285f, 0.357910f, 0.373535f, 0.388428f, 0.404053f, 0.420166f, 0.435303f, 0.450195f, 0.465332f,
+ 0.481201f, 0.496338f, 0.511230f, 0.525879f, 0.540527f, 0.556641f, 0.570312f, 0.585938f, 0.600098f, 0.614746f, 0.629883f, 0.644531f,
+ 0.657715f, 0.672363f, 0.687012f, 0.700684f, 0.714355f, 0.729004f, 0.742188f, 0.755371f, 0.769531f, 0.782227f, 0.796875f, 0.810059f,
+ 0.823242f, 0.836426f, 0.907715f, 0.891602f, 0.877930f, 0.866211f, 0.855957f, 0.846680f, 0.005596f, 0.017654f, 0.029587f, 0.041840f,
+ 0.055115f, 0.067871f, 0.080566f, 0.093994f, 0.107361f, 0.120911f, 0.134766f, 0.149414f, 0.163452f, 0.177979f, 0.192261f, 0.206787f,
+ 0.221191f, 0.236816f, 0.250732f, 0.266113f, 0.281250f, 0.295898f, 0.311279f, 0.326904f, 0.342041f, 0.356201f, 0.371826f, 0.387451f,
+ 0.402344f, 0.417236f, 0.432373f, 0.447266f, 0.462891f, 0.477539f, 0.492432f, 0.506836f, 0.522949f, 0.536621f, 0.551758f, 0.566895f,
+ 0.582031f, 0.596191f, 0.610352f, 0.625488f, 0.640625f, 0.653320f, 0.668457f, 0.682617f, 0.696777f, 0.710449f, 0.724609f, 0.739258f,
+ 0.751465f, 0.765625f, 0.780273f, 0.792480f, 0.806152f, 0.820801f, 0.899902f, 0.885742f, 0.872070f, 0.861328f, 0.851562f, 0.842285f,
+ 0.005451f, 0.016479f, 0.028259f, 0.039856f, 0.051331f, 0.063416f, 0.075867f, 0.088196f, 0.100952f, 0.113770f, 0.126953f, 0.140747f,
+ 0.153564f, 0.167847f, 0.181519f, 0.195679f, 0.210083f, 0.223633f, 0.237427f, 0.252197f, 0.267334f, 0.281738f, 0.296143f, 0.311035f,
+ 0.325928f, 0.340332f, 0.355469f, 0.370361f, 0.385010f, 0.400635f, 0.415039f, 0.429688f, 0.444092f, 0.459717f, 0.474121f, 0.489258f,
+ 0.503906f, 0.519043f, 0.533203f, 0.548828f, 0.562012f, 0.577637f, 0.591797f, 0.606445f, 0.621582f, 0.635742f, 0.650391f, 0.664551f,
+ 0.678223f, 0.692871f, 0.706055f, 0.721191f, 0.733887f, 0.747559f, 0.762207f, 0.775879f, 0.791016f, 0.804199f, 0.892090f, 0.878906f,
+ 0.866699f, 0.855957f, 0.846191f, 0.837891f, 0.004963f, 0.015343f, 0.026169f, 0.037079f, 0.047943f, 0.059570f, 0.070801f, 0.083008f,
+ 0.095093f, 0.106750f, 0.119507f, 0.132080f, 0.145142f, 0.158569f, 0.171143f, 0.184692f, 0.198730f, 0.211792f, 0.225830f, 0.239380f,
+ 0.253662f, 0.267578f, 0.281738f, 0.295898f, 0.309814f, 0.324219f, 0.340088f, 0.353760f, 0.368164f, 0.383057f, 0.397705f, 0.412842f,
+ 0.426758f, 0.441406f, 0.456787f, 0.470947f, 0.485352f, 0.500000f, 0.515137f, 0.529785f, 0.543945f, 0.559082f, 0.572754f, 0.588379f,
+ 0.602539f, 0.616699f, 0.631348f, 0.645996f, 0.659180f, 0.674805f, 0.689453f, 0.703125f, 0.716797f, 0.729980f, 0.744629f, 0.758789f,
+ 0.772461f, 0.786621f, 0.883789f, 0.872070f, 0.860840f, 0.850586f, 0.841309f, 0.833008f, 0.004726f, 0.014549f, 0.024109f, 0.034668f,
+ 0.044708f, 0.055573f, 0.066467f, 0.077820f, 0.088928f, 0.100342f, 0.112000f, 0.124390f, 0.136230f, 0.148804f, 0.161621f, 0.173950f,
+ 0.186768f, 0.200439f, 0.213623f, 0.226074f, 0.239868f, 0.253418f, 0.267090f, 0.281250f, 0.295410f, 0.309570f, 0.323486f, 0.337891f,
+ 0.352295f, 0.365967f, 0.381104f, 0.394775f, 0.409180f, 0.423828f, 0.438477f, 0.452881f, 0.467773f, 0.481689f, 0.496582f, 0.511230f,
+ 0.525391f, 0.539551f, 0.554199f, 0.568848f, 0.583984f, 0.599121f, 0.612305f, 0.627441f, 0.641113f, 0.656250f, 0.669922f, 0.684570f,
+ 0.699219f, 0.713379f, 0.727539f, 0.741699f, 0.755859f, 0.771484f, 0.875488f, 0.865723f, 0.854492f, 0.845215f, 0.836426f, 0.828613f,
+ 0.004452f, 0.013359f, 0.022690f, 0.032745f, 0.042297f, 0.051910f, 0.061920f, 0.072693f, 0.083496f, 0.094177f, 0.105408f, 0.116760f,
+ 0.128174f, 0.140137f, 0.151855f, 0.164185f, 0.176758f, 0.189087f, 0.201660f, 0.214478f, 0.227173f, 0.240356f, 0.253906f, 0.267578f,
+ 0.280273f, 0.294922f, 0.307373f, 0.321045f, 0.336670f, 0.350098f, 0.363770f, 0.378174f, 0.392334f, 0.406006f, 0.420410f, 0.434082f,
+ 0.448975f, 0.463623f, 0.478271f, 0.492676f, 0.506836f, 0.520996f, 0.536133f, 0.550781f, 0.565430f, 0.580078f, 0.593750f, 0.608887f,
+ 0.623047f, 0.638184f, 0.651367f, 0.666016f, 0.681152f, 0.695312f, 0.709473f, 0.723145f, 0.738281f, 0.752930f, 0.867676f, 0.858398f,
+ 0.848633f, 0.839355f, 0.831055f, 0.823730f, 0.004143f, 0.012794f, 0.021713f, 0.030396f, 0.039551f, 0.048645f, 0.058563f, 0.068176f,
+ 0.078308f, 0.088928f, 0.098328f, 0.109924f, 0.120728f, 0.131592f, 0.142944f, 0.154175f, 0.165771f, 0.178223f, 0.190186f, 0.202881f,
+ 0.214844f, 0.227417f, 0.240845f, 0.253906f, 0.265869f, 0.279541f, 0.293213f, 0.305908f, 0.320068f, 0.333496f, 0.347168f, 0.361816f,
+ 0.375000f, 0.389160f, 0.403320f, 0.417236f, 0.431396f, 0.444824f, 0.459473f, 0.473633f, 0.488525f, 0.503418f, 0.517578f, 0.532227f,
+ 0.545410f, 0.560547f, 0.575684f, 0.590332f, 0.604004f, 0.618652f, 0.632812f, 0.647949f, 0.663086f, 0.676758f, 0.691895f, 0.706543f,
+ 0.721191f, 0.735840f, 0.859375f, 0.852539f, 0.842773f, 0.833496f, 0.824707f, 0.818848f, 0.003839f, 0.012062f, 0.020126f, 0.028366f,
+ 0.036774f, 0.045593f, 0.054718f, 0.063416f, 0.073120f, 0.082825f, 0.092957f, 0.102966f, 0.113464f, 0.123535f, 0.134277f, 0.145020f,
+ 0.155762f, 0.167847f, 0.179199f, 0.190796f, 0.202393f, 0.214844f, 0.227417f, 0.239868f, 0.252197f, 0.264648f, 0.277588f, 0.291016f,
+ 0.304199f, 0.317383f, 0.330811f, 0.343750f, 0.357422f, 0.371826f, 0.385254f, 0.399902f, 0.413574f, 0.427246f, 0.441162f, 0.455566f,
+ 0.469971f, 0.484375f, 0.498535f, 0.514160f, 0.527344f, 0.541992f, 0.556152f, 0.570312f, 0.585449f, 0.600098f, 0.614746f, 0.629883f,
+ 0.645508f, 0.658203f, 0.673340f, 0.688477f, 0.703125f, 0.718262f, 0.851074f, 0.844727f, 0.835938f, 0.827637f, 0.820312f, 0.812988f,
+ 0.003786f, 0.011147f, 0.018921f, 0.026550f, 0.034729f, 0.042664f, 0.051117f, 0.060028f, 0.068298f, 0.077454f, 0.086914f, 0.096130f,
+ 0.105835f, 0.115662f, 0.126343f, 0.136475f, 0.146606f, 0.157715f, 0.168457f, 0.180176f, 0.191528f, 0.202759f, 0.215088f, 0.226929f,
+ 0.239014f, 0.251221f, 0.263428f, 0.275391f, 0.289062f, 0.301514f, 0.314941f, 0.328369f, 0.341797f, 0.354736f, 0.367676f, 0.382324f,
+ 0.395264f, 0.409912f, 0.423340f, 0.437012f, 0.451660f, 0.465576f, 0.480469f, 0.494629f, 0.508301f, 0.522949f, 0.538086f, 0.551758f,
+ 0.567383f, 0.582031f, 0.596191f, 0.610840f, 0.625977f, 0.639648f, 0.655273f, 0.670410f, 0.685547f, 0.700684f, 0.842285f, 0.837402f,
+ 0.829590f, 0.821289f, 0.813965f, 0.808105f, 0.003504f, 0.010445f, 0.017609f, 0.025131f, 0.032349f, 0.040314f, 0.047485f, 0.055756f,
+ 0.064026f, 0.072571f, 0.080872f, 0.089661f, 0.099426f, 0.108459f, 0.118286f, 0.127930f, 0.137817f, 0.147583f, 0.158203f, 0.169189f,
+ 0.180908f, 0.191040f, 0.203003f, 0.214111f, 0.225708f, 0.237549f, 0.249023f, 0.261475f, 0.273926f, 0.286865f, 0.299316f, 0.311768f,
+ 0.325684f, 0.338623f, 0.351562f, 0.364746f, 0.378418f, 0.392578f, 0.405518f, 0.419678f, 0.433105f, 0.447998f, 0.461670f, 0.475830f,
+ 0.490479f, 0.503906f, 0.519531f, 0.533203f, 0.547852f, 0.562988f, 0.576660f, 0.591797f, 0.606445f, 0.622070f, 0.636719f, 0.652344f,
+ 0.666504f, 0.682617f, 0.833496f, 0.830078f, 0.822754f, 0.815918f, 0.808594f, 0.802734f, 0.003447f, 0.009941f, 0.016373f, 0.023300f,
+ 0.030228f, 0.037689f, 0.044128f, 0.052551f, 0.059845f, 0.068115f, 0.076538f, 0.083862f, 0.092896f, 0.101440f, 0.110596f, 0.119995f,
+ 0.129028f, 0.138916f, 0.148926f, 0.158936f, 0.169189f, 0.180176f, 0.190308f, 0.201416f, 0.212769f, 0.224365f, 0.235962f, 0.247192f,
+ 0.259033f, 0.271973f, 0.283936f, 0.296631f, 0.309570f, 0.321777f, 0.334961f, 0.348389f, 0.361572f, 0.374756f, 0.388184f, 0.401611f,
+ 0.415771f, 0.429443f, 0.443359f, 0.457520f, 0.471436f, 0.486084f, 0.500977f, 0.514648f, 0.528809f, 0.543457f, 0.558594f, 0.573242f,
+ 0.588867f, 0.603516f, 0.617676f, 0.633301f, 0.648926f, 0.664551f, 0.824219f, 0.823242f, 0.815918f, 0.809082f, 0.802246f, 0.796387f,
+ 0.003141f, 0.009407f, 0.015251f, 0.021851f, 0.028107f, 0.034882f, 0.041779f, 0.048340f, 0.056244f, 0.062988f, 0.071106f, 0.078796f,
+ 0.087036f, 0.094910f, 0.103149f, 0.112305f, 0.121460f, 0.130371f, 0.139404f, 0.149048f, 0.159180f, 0.169189f, 0.179565f, 0.189087f,
+ 0.200317f, 0.211548f, 0.222412f, 0.233765f, 0.245117f, 0.257324f, 0.269043f, 0.281006f, 0.293213f, 0.305664f, 0.318848f, 0.331055f,
+ 0.343750f, 0.358398f, 0.369873f, 0.384033f, 0.397217f, 0.411865f, 0.424805f, 0.438965f, 0.453125f, 0.467529f, 0.481689f, 0.495850f,
+ 0.510254f, 0.524414f, 0.539551f, 0.554688f, 0.569824f, 0.584961f, 0.599121f, 0.614258f, 0.629883f, 0.645020f, 0.815430f, 0.814453f,
+ 0.809570f, 0.802734f, 0.796875f, 0.791504f, 0.002838f, 0.008461f, 0.014236f, 0.020676f, 0.026749f, 0.032593f, 0.039032f, 0.045715f,
+ 0.052216f, 0.059479f, 0.066467f, 0.073608f, 0.080933f, 0.088623f, 0.096619f, 0.104919f, 0.113098f, 0.121521f, 0.130493f, 0.139526f,
+ 0.148560f, 0.158203f, 0.167969f, 0.177979f, 0.187988f, 0.198730f, 0.208862f, 0.220093f, 0.231323f, 0.242798f, 0.253906f, 0.265869f,
+ 0.278320f, 0.289551f, 0.302246f, 0.314941f, 0.327393f, 0.340088f, 0.353516f, 0.365967f, 0.379883f, 0.392822f, 0.406738f, 0.420898f,
+ 0.434814f, 0.447998f, 0.462891f, 0.477539f, 0.491455f, 0.506836f, 0.520996f, 0.536133f, 0.550781f, 0.565918f, 0.581055f, 0.596680f,
+ 0.611816f, 0.627441f, 0.806152f, 0.807617f, 0.801270f, 0.796387f, 0.790039f, 0.784668f, 0.002689f, 0.008102f, 0.013618f, 0.019058f,
+ 0.024719f, 0.030548f, 0.036560f, 0.042725f, 0.048615f, 0.054779f, 0.061615f, 0.068604f, 0.075012f, 0.082703f, 0.090271f, 0.097900f,
+ 0.105530f, 0.113586f, 0.121826f, 0.130371f, 0.139282f, 0.147705f, 0.157349f, 0.166504f, 0.176147f, 0.186401f, 0.196289f, 0.207520f,
+ 0.217651f, 0.228394f, 0.239868f, 0.251465f, 0.262451f, 0.274414f, 0.286377f, 0.298828f, 0.311035f, 0.323730f, 0.336670f, 0.349121f,
+ 0.362549f, 0.375244f, 0.389160f, 0.402344f, 0.417236f, 0.429932f, 0.443848f, 0.458984f, 0.472168f, 0.487793f, 0.501953f, 0.517578f,
+ 0.531738f, 0.546875f, 0.561523f, 0.576660f, 0.593262f, 0.608398f, 0.797852f, 0.798828f, 0.794922f, 0.789551f, 0.784668f, 0.779297f,
+ 0.002666f, 0.007462f, 0.012596f, 0.018066f, 0.023026f, 0.028412f, 0.033813f, 0.039398f, 0.045166f, 0.051239f, 0.057587f, 0.063721f,
+ 0.070312f, 0.077148f, 0.084167f, 0.090820f, 0.098267f, 0.105591f, 0.113159f, 0.121460f, 0.129761f, 0.138428f, 0.147217f, 0.156128f,
+ 0.165283f, 0.174438f, 0.183960f, 0.194092f, 0.204834f, 0.214844f, 0.225830f, 0.236816f, 0.247925f, 0.259033f, 0.270752f, 0.282227f,
+ 0.294678f, 0.306641f, 0.319336f, 0.332031f, 0.344482f, 0.357910f, 0.371094f, 0.384033f, 0.398682f, 0.412109f, 0.425781f, 0.440186f,
+ 0.454102f, 0.468018f, 0.482910f, 0.497314f, 0.512207f, 0.528320f, 0.542969f, 0.558594f, 0.573242f, 0.589355f, 0.787598f, 0.791016f,
+ 0.787109f, 0.781738f, 0.777344f, 0.772461f, 0.002569f, 0.007069f, 0.012199f, 0.016739f, 0.021393f, 0.026672f, 0.031189f, 0.037109f,
+ 0.042480f, 0.047729f, 0.053345f, 0.059387f, 0.065430f, 0.071838f, 0.078186f, 0.084167f, 0.091492f, 0.098816f, 0.105774f, 0.112976f,
+ 0.121155f, 0.129028f, 0.136963f, 0.145508f, 0.153687f, 0.163086f, 0.172363f, 0.181885f, 0.191406f, 0.201782f, 0.211670f, 0.222412f,
+ 0.233032f, 0.244263f, 0.255371f, 0.266846f, 0.278809f, 0.290527f, 0.302734f, 0.314697f, 0.327393f, 0.340820f, 0.353027f, 0.366455f,
+ 0.380127f, 0.393799f, 0.406006f, 0.421143f, 0.435059f, 0.449707f, 0.463623f, 0.479248f, 0.494141f, 0.509277f, 0.523438f, 0.539551f,
+ 0.555176f, 0.570801f, 0.778320f, 0.783203f, 0.779785f, 0.775879f, 0.770996f, 0.767090f, 0.002398f, 0.006733f, 0.010918f, 0.015495f,
+ 0.020203f, 0.024963f, 0.029663f, 0.034485f, 0.039246f, 0.044678f, 0.049896f, 0.055267f, 0.060486f, 0.066345f, 0.072693f, 0.078857f,
+ 0.085083f, 0.091370f, 0.097961f, 0.105530f, 0.112244f, 0.119629f, 0.127563f, 0.135376f, 0.143799f, 0.152100f, 0.160889f, 0.169922f,
+ 0.178833f, 0.188843f, 0.198608f, 0.208496f, 0.218628f, 0.229492f, 0.240479f, 0.251953f, 0.262695f, 0.274902f, 0.286377f, 0.298340f,
+ 0.310547f, 0.323242f, 0.335693f, 0.349365f, 0.362061f, 0.375000f, 0.388916f, 0.402832f, 0.416748f, 0.430420f, 0.445068f, 0.459473f,
+ 0.474854f, 0.489258f, 0.504883f, 0.519531f, 0.535645f, 0.551758f, 0.769043f, 0.774902f, 0.771973f, 0.768555f, 0.764160f, 0.759766f,
+ 0.002062f, 0.006191f, 0.010384f, 0.014786f, 0.018402f, 0.023270f, 0.027435f, 0.031891f, 0.036163f, 0.041199f, 0.045685f, 0.051208f,
+ 0.056244f, 0.061371f, 0.066772f, 0.072510f, 0.078369f, 0.084656f, 0.091125f, 0.097290f, 0.104309f, 0.111145f, 0.118164f, 0.126221f,
+ 0.133301f, 0.141724f, 0.149658f, 0.157837f, 0.167236f, 0.176025f, 0.185547f, 0.195190f, 0.205444f, 0.215332f, 0.225830f, 0.236084f,
+ 0.247314f, 0.259033f, 0.270020f, 0.281982f, 0.293701f, 0.305908f, 0.318848f, 0.331787f, 0.344482f, 0.357178f, 0.370361f, 0.384521f,
+ 0.397461f, 0.411621f, 0.426025f, 0.440674f, 0.455322f, 0.470703f, 0.485596f, 0.500977f, 0.517578f, 0.532227f, 0.759277f, 0.766602f,
+ 0.764160f, 0.761230f, 0.757324f, 0.753418f, 0.002064f, 0.005859f, 0.009613f, 0.013626f, 0.017456f, 0.021606f, 0.025574f, 0.029526f,
+ 0.034302f, 0.038422f, 0.042938f, 0.047485f, 0.052155f, 0.056763f, 0.061951f, 0.067139f, 0.072754f, 0.078308f, 0.084167f, 0.090149f,
+ 0.096191f, 0.102722f, 0.109558f, 0.116699f, 0.123901f, 0.131104f, 0.139160f, 0.146729f, 0.155273f, 0.163940f, 0.173096f, 0.182129f,
+ 0.192017f, 0.201172f, 0.211060f, 0.221558f, 0.232544f, 0.243530f, 0.254150f, 0.266113f, 0.277588f, 0.289307f, 0.301758f, 0.313965f,
+ 0.326904f, 0.338867f, 0.352051f, 0.366211f, 0.379150f, 0.393066f, 0.407471f, 0.421875f, 0.436768f, 0.450439f, 0.466553f, 0.481201f,
+ 0.497314f, 0.513184f, 0.749512f, 0.758301f, 0.756348f, 0.753906f, 0.750000f, 0.746582f, 0.001851f, 0.005405f, 0.009109f, 0.012589f,
+ 0.016129f, 0.020020f, 0.023926f, 0.027481f, 0.031738f, 0.035492f, 0.039734f, 0.044128f, 0.048065f, 0.052765f, 0.057373f, 0.061859f,
+ 0.066711f, 0.072388f, 0.077393f, 0.083130f, 0.088745f, 0.094727f, 0.101135f, 0.107666f, 0.114380f, 0.121704f, 0.128540f, 0.136108f,
+ 0.144043f, 0.151733f, 0.160522f, 0.169678f, 0.178589f, 0.187622f, 0.197998f, 0.207397f, 0.217285f, 0.227905f, 0.238892f, 0.250000f,
+ 0.261230f, 0.272461f, 0.284180f, 0.296387f, 0.308838f, 0.321533f, 0.334473f, 0.347656f, 0.361328f, 0.375000f, 0.388672f, 0.402588f,
+ 0.417969f, 0.432617f, 0.447021f, 0.461914f, 0.478516f, 0.493652f, 0.739258f, 0.749512f, 0.749023f, 0.745605f, 0.742188f, 0.739746f,
+ 0.001666f, 0.005405f, 0.008575f, 0.011696f, 0.015327f, 0.018646f, 0.022293f, 0.025650f, 0.029327f, 0.032776f, 0.036530f, 0.040619f,
+ 0.044128f, 0.048828f, 0.052887f, 0.057098f, 0.061829f, 0.066467f, 0.071350f, 0.076355f, 0.081909f, 0.087341f, 0.092896f, 0.099304f,
+ 0.105469f, 0.112000f, 0.118835f, 0.125977f, 0.133545f, 0.140991f, 0.148438f, 0.156982f, 0.165771f, 0.174805f, 0.183960f, 0.193115f,
+ 0.203369f, 0.212891f, 0.223389f, 0.234497f, 0.244751f, 0.256348f, 0.268066f, 0.279541f, 0.291260f, 0.303955f, 0.316406f, 0.329590f,
+ 0.342529f, 0.355957f, 0.369385f, 0.384766f, 0.398926f, 0.413330f, 0.428467f, 0.442383f, 0.458740f, 0.474609f, 0.728516f, 0.740723f,
+ 0.740234f, 0.738281f, 0.735352f, 0.732910f, 0.001534f, 0.004936f, 0.007980f, 0.011223f, 0.013893f, 0.017212f, 0.020294f, 0.023361f,
+ 0.026688f, 0.030182f, 0.033600f, 0.037537f, 0.040924f, 0.044495f, 0.048340f, 0.052155f, 0.056732f, 0.061035f, 0.065430f, 0.069824f,
+ 0.075073f, 0.080078f, 0.085571f, 0.091003f, 0.096863f, 0.103271f, 0.109009f, 0.115723f, 0.123230f, 0.129639f, 0.137207f, 0.145264f,
+ 0.153320f, 0.161499f, 0.170410f, 0.179688f, 0.189087f, 0.198364f, 0.208740f, 0.218750f, 0.229126f, 0.240356f, 0.251465f, 0.263184f,
+ 0.274902f, 0.286621f, 0.299072f, 0.311768f, 0.324463f, 0.337402f, 0.351074f, 0.364746f, 0.378662f, 0.394287f, 0.408936f, 0.423096f,
+ 0.439453f, 0.455322f, 0.716797f, 0.731934f, 0.732422f, 0.729980f, 0.728027f, 0.725586f, 0.001639f, 0.004337f, 0.007439f, 0.009888f,
+ 0.013092f, 0.015717f, 0.018921f, 0.021805f, 0.024612f, 0.027542f, 0.030762f, 0.034088f, 0.037598f, 0.041107f, 0.044189f, 0.047699f,
+ 0.051666f, 0.055664f, 0.059723f, 0.064148f, 0.068542f, 0.073425f, 0.078003f, 0.083435f, 0.088806f, 0.094360f, 0.100159f, 0.106079f,
+ 0.112915f, 0.119690f, 0.125977f, 0.133667f, 0.141357f, 0.149414f, 0.157349f, 0.166260f, 0.175049f, 0.184326f, 0.193970f, 0.203735f,
+ 0.214355f, 0.224609f, 0.235352f, 0.246460f, 0.257568f, 0.269287f, 0.281738f, 0.294189f, 0.305908f, 0.319824f, 0.332520f, 0.346680f,
+ 0.360596f, 0.375244f, 0.389648f, 0.404297f, 0.419189f, 0.435791f, 0.707520f, 0.723145f, 0.723633f, 0.722656f, 0.720703f, 0.717773f,
+ 0.001469f, 0.004345f, 0.006844f, 0.009483f, 0.012428f, 0.014679f, 0.017166f, 0.019989f, 0.022949f, 0.025574f, 0.028320f, 0.031525f,
+ 0.034088f, 0.037323f, 0.040710f, 0.043762f, 0.047119f, 0.050873f, 0.054352f, 0.058441f, 0.062561f, 0.066711f, 0.071167f, 0.075989f,
+ 0.080627f, 0.086426f, 0.091553f, 0.097473f, 0.103210f, 0.109680f, 0.115723f, 0.122986f, 0.129761f, 0.137451f, 0.145142f, 0.153198f,
+ 0.161621f, 0.170654f, 0.179688f, 0.189087f, 0.198730f, 0.209229f, 0.219604f, 0.230225f, 0.241211f, 0.252197f, 0.264404f, 0.276367f,
+ 0.288574f, 0.301270f, 0.314453f, 0.328125f, 0.341309f, 0.354980f, 0.370117f, 0.385498f, 0.399902f, 0.415771f, 0.696289f, 0.714355f,
+ 0.715820f, 0.714355f, 0.712891f, 0.710449f, 0.001227f, 0.003862f, 0.006245f, 0.008644f, 0.010796f, 0.013344f, 0.015823f, 0.018448f,
+ 0.020645f, 0.023331f, 0.025681f, 0.028305f, 0.030975f, 0.033722f, 0.036987f, 0.039673f, 0.043121f, 0.046112f, 0.049774f, 0.053406f,
+ 0.056854f, 0.060760f, 0.064697f, 0.069397f, 0.073364f, 0.078369f, 0.083313f, 0.088257f, 0.094116f, 0.100098f, 0.105957f, 0.112122f,
+ 0.118774f, 0.125854f, 0.133057f, 0.140869f, 0.148682f, 0.157227f, 0.165405f, 0.174927f, 0.184082f, 0.193726f, 0.204102f, 0.214111f,
+ 0.225098f, 0.236328f, 0.247314f, 0.259277f, 0.270752f, 0.282959f, 0.296143f, 0.309082f, 0.322510f, 0.336426f, 0.350830f, 0.365479f,
+ 0.380371f, 0.396240f, 0.684570f, 0.705078f, 0.706543f, 0.706543f, 0.705078f, 0.703125f, 0.001069f, 0.003525f, 0.006062f, 0.008286f,
+ 0.010178f, 0.012589f, 0.014542f, 0.017075f, 0.019241f, 0.021179f, 0.023499f, 0.026047f, 0.028137f, 0.030762f, 0.033417f, 0.035889f,
+ 0.038757f, 0.041779f, 0.044586f, 0.048309f, 0.051056f, 0.054810f, 0.058777f, 0.062347f, 0.066528f, 0.070740f, 0.075256f, 0.080261f,
+ 0.085205f, 0.090393f, 0.095886f, 0.102478f, 0.108154f, 0.114441f, 0.121399f, 0.128784f, 0.135742f, 0.144165f, 0.151978f, 0.160767f,
+ 0.169434f, 0.178833f, 0.188721f, 0.198608f, 0.208984f, 0.220215f, 0.230957f, 0.241943f, 0.253906f, 0.265869f, 0.278564f, 0.291260f,
+ 0.304443f, 0.318359f, 0.332031f, 0.346680f, 0.361572f, 0.377197f, 0.673828f, 0.695801f, 0.698242f, 0.697754f, 0.697266f, 0.695312f,
+ 0.001211f, 0.003250f, 0.005112f, 0.007195f, 0.009651f, 0.011414f, 0.013641f, 0.015205f, 0.017334f, 0.019608f, 0.021164f, 0.023712f,
+ 0.025726f, 0.027863f, 0.029984f, 0.032410f, 0.035034f, 0.037689f, 0.040466f, 0.042938f, 0.046478f, 0.049591f, 0.052856f, 0.056274f,
+ 0.060089f, 0.063721f, 0.068115f, 0.072266f, 0.076904f, 0.081970f, 0.087036f, 0.092285f, 0.097961f, 0.104309f, 0.110535f, 0.117126f,
+ 0.124084f, 0.131226f, 0.139038f, 0.147095f, 0.155884f, 0.164429f, 0.174194f, 0.183228f, 0.192749f, 0.203491f, 0.214233f, 0.224976f,
+ 0.236206f, 0.247925f, 0.260498f, 0.272705f, 0.285889f, 0.299805f, 0.312988f, 0.327637f, 0.342529f, 0.356934f, 0.662598f, 0.686523f,
+ 0.689453f, 0.689453f, 0.688965f, 0.687500f, 0.001138f, 0.003206f, 0.005180f, 0.007309f, 0.008377f, 0.010635f, 0.012352f, 0.014153f,
+ 0.015640f, 0.017487f, 0.019272f, 0.021164f, 0.023026f, 0.025314f, 0.027222f, 0.029282f, 0.031433f, 0.033600f, 0.036041f, 0.038788f,
+ 0.041626f, 0.044281f, 0.047455f, 0.050507f, 0.054047f, 0.057556f, 0.061188f, 0.065063f, 0.069214f, 0.073486f, 0.078369f, 0.083191f,
+ 0.088196f, 0.093811f, 0.099609f, 0.106018f, 0.112305f, 0.119385f, 0.126343f, 0.134033f, 0.142090f, 0.150635f, 0.159546f, 0.168579f,
+ 0.177734f, 0.187500f, 0.198242f, 0.208618f, 0.219604f, 0.231812f, 0.242188f, 0.254883f, 0.267578f, 0.281494f, 0.294434f, 0.308350f,
+ 0.322998f, 0.338379f, 0.651367f, 0.676758f, 0.681152f, 0.680664f, 0.680664f, 0.679688f, 0.000977f, 0.002806f, 0.004559f, 0.006176f,
+ 0.008034f, 0.009476f, 0.011131f, 0.012741f, 0.014275f, 0.015732f, 0.017334f, 0.019104f, 0.020767f, 0.022293f, 0.024323f, 0.026016f,
+ 0.028198f, 0.030197f, 0.032257f, 0.034515f, 0.036957f, 0.039856f, 0.042084f, 0.044891f, 0.047791f, 0.051147f, 0.054535f, 0.058197f,
+ 0.061768f, 0.065674f, 0.069946f, 0.074585f, 0.079102f, 0.084412f, 0.089600f, 0.095398f, 0.101196f, 0.107544f, 0.114258f, 0.121094f,
+ 0.128662f, 0.137085f, 0.145020f, 0.153687f, 0.162720f, 0.172607f, 0.182129f, 0.192749f, 0.203125f, 0.214111f, 0.226074f, 0.237671f,
+ 0.249878f, 0.262207f, 0.275635f, 0.289551f, 0.304199f, 0.318848f, 0.639160f, 0.666992f, 0.671387f, 0.671875f, 0.671875f, 0.671387f,
+ 0.000968f, 0.002722f, 0.004318f, 0.005634f, 0.007393f, 0.008667f, 0.010139f, 0.011383f, 0.012856f, 0.014389f, 0.015427f, 0.016907f,
+ 0.018387f, 0.020081f, 0.021683f, 0.023315f, 0.025085f, 0.026840f, 0.028641f, 0.030624f, 0.032837f, 0.035065f, 0.037445f, 0.039948f,
+ 0.042542f, 0.045410f, 0.048340f, 0.051514f, 0.054840f, 0.058502f, 0.062408f, 0.066223f, 0.070679f, 0.075134f, 0.080078f, 0.085388f,
+ 0.090515f, 0.096436f, 0.102722f, 0.109314f, 0.116333f, 0.123352f, 0.131592f, 0.139526f, 0.147949f, 0.156860f, 0.166748f, 0.176758f,
+ 0.187134f, 0.197632f, 0.209106f, 0.220337f, 0.232666f, 0.244751f, 0.257568f, 0.270996f, 0.284912f, 0.300537f, 0.627441f, 0.657227f,
+ 0.662598f, 0.663574f, 0.663574f, 0.663086f, 0.001081f, 0.002466f, 0.003862f, 0.005348f, 0.006447f, 0.007927f, 0.009018f, 0.010490f,
+ 0.011436f, 0.012627f, 0.013916f, 0.015015f, 0.016449f, 0.017563f, 0.019165f, 0.020706f, 0.021973f, 0.023834f, 0.025467f, 0.027130f,
+ 0.029175f, 0.030991f, 0.033081f, 0.035156f, 0.037384f, 0.040039f, 0.042603f, 0.045502f, 0.048492f, 0.051636f, 0.054962f, 0.058716f,
+ 0.062439f, 0.066467f, 0.071045f, 0.075378f, 0.080811f, 0.085815f, 0.091492f, 0.098022f, 0.103943f, 0.111023f, 0.118164f, 0.125732f,
+ 0.133911f, 0.142456f, 0.151367f, 0.161011f, 0.170898f, 0.181396f, 0.192139f, 0.203247f, 0.214844f, 0.227173f, 0.239380f, 0.252441f,
+ 0.266602f, 0.281006f, 0.616699f, 0.647949f, 0.653320f, 0.655273f, 0.654785f, 0.655273f, 0.000735f, 0.002331f, 0.003601f, 0.005005f,
+ 0.005825f, 0.007061f, 0.008049f, 0.009148f, 0.010315f, 0.011131f, 0.012230f, 0.013367f, 0.014328f, 0.015541f, 0.016968f, 0.018234f,
+ 0.019257f, 0.020798f, 0.022202f, 0.023666f, 0.025452f, 0.027115f, 0.028885f, 0.030792f, 0.032715f, 0.035034f, 0.037323f, 0.039825f,
+ 0.042419f, 0.045258f, 0.048157f, 0.051422f, 0.054810f, 0.058411f, 0.062378f, 0.066528f, 0.071106f, 0.076233f, 0.081116f, 0.086853f,
+ 0.092407f, 0.098938f, 0.105469f, 0.112854f, 0.120361f, 0.128418f, 0.136841f, 0.145752f, 0.155273f, 0.165283f, 0.175537f, 0.186646f,
+ 0.197510f, 0.209473f, 0.221558f, 0.234619f, 0.248047f, 0.261719f, 0.603516f, 0.636719f, 0.644531f, 0.645020f, 0.645508f, 0.646484f,
+ 0.000837f, 0.002073f, 0.003357f, 0.004292f, 0.005409f, 0.006271f, 0.007271f, 0.007973f, 0.008873f, 0.009956f, 0.010811f, 0.012032f,
+ 0.012848f, 0.013664f, 0.014870f, 0.015839f, 0.017090f, 0.018280f, 0.019333f, 0.020691f, 0.022186f, 0.023453f, 0.025223f, 0.026779f,
+ 0.028595f, 0.030441f, 0.032410f, 0.034729f, 0.036743f, 0.039307f, 0.042023f, 0.044434f, 0.047791f, 0.050781f, 0.054413f, 0.058075f,
+ 0.061951f, 0.066711f, 0.071106f, 0.076355f, 0.081848f, 0.087341f, 0.093872f, 0.099854f, 0.107483f, 0.114441f, 0.122925f, 0.131104f,
+ 0.140381f, 0.149414f, 0.159180f, 0.170166f, 0.181152f, 0.192139f, 0.204468f, 0.216553f, 0.230103f, 0.244507f, 0.592773f, 0.626953f,
+ 0.635254f, 0.637207f, 0.636719f, 0.637695f, 0.000524f, 0.001863f, 0.003014f, 0.003777f, 0.004852f, 0.005516f, 0.006428f, 0.007111f,
+ 0.008095f, 0.008888f, 0.009476f, 0.010345f, 0.011063f, 0.012016f, 0.012810f, 0.013786f, 0.014648f, 0.015717f, 0.016891f, 0.017929f,
+ 0.019150f, 0.020401f, 0.021606f, 0.023193f, 0.024597f, 0.026276f, 0.027939f, 0.029770f, 0.031738f, 0.033936f, 0.036194f, 0.038574f,
+ 0.041107f, 0.043945f, 0.047180f, 0.050385f, 0.054291f, 0.057770f, 0.061981f, 0.066345f, 0.071167f, 0.076355f, 0.082153f, 0.088074f,
+ 0.094666f, 0.101685f, 0.109131f, 0.117249f, 0.125610f, 0.134399f, 0.143921f, 0.154175f, 0.164795f, 0.175659f, 0.187256f, 0.199341f,
+ 0.211670f, 0.225464f, 0.580078f, 0.617676f, 0.625000f, 0.627930f, 0.628906f, 0.628906f, 0.000657f, 0.001829f, 0.002909f, 0.003525f,
+ 0.004295f, 0.005051f, 0.005592f, 0.006123f, 0.006920f, 0.007553f, 0.008339f, 0.008888f, 0.009689f, 0.010262f, 0.011017f, 0.011848f,
+ 0.012634f, 0.013489f, 0.014572f, 0.015427f, 0.016449f, 0.017426f, 0.018539f, 0.019852f, 0.021133f, 0.022507f, 0.023834f, 0.025375f,
+ 0.027084f, 0.028976f, 0.030792f, 0.032959f, 0.035400f, 0.037720f, 0.040405f, 0.043243f, 0.046356f, 0.049530f, 0.053314f, 0.057190f,
+ 0.061554f, 0.066223f, 0.071472f, 0.076782f, 0.082825f, 0.089417f, 0.096191f, 0.103210f, 0.111633f, 0.119934f, 0.128662f, 0.138550f,
+ 0.148315f, 0.158813f, 0.170288f, 0.182373f, 0.194458f, 0.207642f, 0.567383f, 0.606445f, 0.615234f, 0.619141f, 0.620117f, 0.620117f,
+ 0.000584f, 0.001548f, 0.002333f, 0.003086f, 0.003660f, 0.004303f, 0.005020f, 0.005543f, 0.006042f, 0.006538f, 0.007118f, 0.007641f,
+ 0.008301f, 0.008919f, 0.009499f, 0.010147f, 0.010918f, 0.011414f, 0.012222f, 0.013084f, 0.013901f, 0.014954f, 0.015671f, 0.016724f,
+ 0.017914f, 0.019012f, 0.020325f, 0.021698f, 0.022949f, 0.024445f, 0.026215f, 0.027954f, 0.029755f, 0.032043f, 0.034210f, 0.036591f,
+ 0.039215f, 0.042297f, 0.045441f, 0.048676f, 0.052612f, 0.056580f, 0.061432f, 0.066040f, 0.071350f, 0.077332f, 0.083496f, 0.090393f,
+ 0.097717f, 0.105835f, 0.114380f, 0.123413f, 0.133301f, 0.143066f, 0.153931f, 0.165039f, 0.177124f, 0.190308f, 0.555176f, 0.597656f,
+ 0.604980f, 0.609375f, 0.609863f, 0.611328f, 0.000438f, 0.001456f, 0.001925f, 0.002811f, 0.003246f, 0.003731f, 0.004108f, 0.004669f,
+ 0.005344f, 0.005535f, 0.005913f, 0.006641f, 0.007038f, 0.007473f, 0.008049f, 0.008675f, 0.009361f, 0.009689f, 0.010513f, 0.011032f,
+ 0.011894f, 0.012695f, 0.013390f, 0.014183f, 0.015114f, 0.016037f, 0.016998f, 0.018280f, 0.019272f, 0.020645f, 0.022003f, 0.023361f,
+ 0.024796f, 0.026779f, 0.028656f, 0.030685f, 0.032928f, 0.035370f, 0.038147f, 0.040955f, 0.044403f, 0.047821f, 0.052032f, 0.056183f,
+ 0.060974f, 0.066162f, 0.071777f, 0.078125f, 0.084656f, 0.092102f, 0.100159f, 0.109009f, 0.117981f, 0.127563f, 0.138306f, 0.148804f,
+ 0.160645f, 0.173218f, 0.542969f, 0.586914f, 0.594727f, 0.599609f, 0.601074f, 0.601074f, 0.000520f, 0.001104f, 0.001921f, 0.002256f,
+ 0.002886f, 0.003389f, 0.003689f, 0.004063f, 0.004440f, 0.004829f, 0.005230f, 0.005466f, 0.005966f, 0.006332f, 0.006786f, 0.007347f,
+ 0.007835f, 0.008232f, 0.008812f, 0.009216f, 0.009865f, 0.010490f, 0.011124f, 0.011803f, 0.012573f, 0.013390f, 0.014275f, 0.015121f,
+ 0.016144f, 0.016953f, 0.018234f, 0.019257f, 0.020782f, 0.022064f, 0.023743f, 0.025360f, 0.027176f, 0.029327f, 0.031616f, 0.034058f,
+ 0.036957f, 0.039917f, 0.043182f, 0.047272f, 0.051025f, 0.055695f, 0.060913f, 0.066345f, 0.072693f, 0.079285f, 0.086548f, 0.094543f,
+ 0.103271f, 0.112793f, 0.122864f, 0.132812f, 0.144531f, 0.156616f, 0.530273f, 0.576660f, 0.585449f, 0.590332f, 0.592285f, 0.593262f,
+ 0.000366f, 0.001040f, 0.001583f, 0.002129f, 0.002522f, 0.002792f, 0.003012f, 0.003420f, 0.003630f, 0.003967f, 0.004246f, 0.004623f,
+ 0.005039f, 0.005253f, 0.005627f, 0.006096f, 0.006447f, 0.006939f, 0.007179f, 0.007710f, 0.008324f, 0.008698f, 0.009247f, 0.009796f,
+ 0.010414f, 0.011063f, 0.011627f, 0.012543f, 0.013191f, 0.014099f, 0.014938f, 0.015930f, 0.016983f, 0.018219f, 0.019440f, 0.020813f,
+ 0.022324f, 0.024002f, 0.025818f, 0.027969f, 0.030289f, 0.032898f, 0.035583f, 0.038727f, 0.042450f, 0.046234f, 0.050781f, 0.055695f,
+ 0.061157f, 0.067383f, 0.074158f, 0.081360f, 0.089478f, 0.098267f, 0.107788f, 0.117737f, 0.129028f, 0.140503f, 0.517578f, 0.566406f,
+ 0.575195f, 0.581055f, 0.582520f, 0.584473f, 0.000482f, 0.001008f, 0.001481f, 0.001818f, 0.002001f, 0.002296f, 0.002569f, 0.002781f,
+ 0.002998f, 0.003319f, 0.003620f, 0.003828f, 0.004082f, 0.004364f, 0.004658f, 0.004978f, 0.005257f, 0.005665f, 0.005993f, 0.006340f,
+ 0.006725f, 0.007160f, 0.007576f, 0.008095f, 0.008522f, 0.008980f, 0.009621f, 0.010170f, 0.010765f, 0.011543f, 0.012161f, 0.013023f,
+ 0.013840f, 0.014801f, 0.015869f, 0.016861f, 0.018127f, 0.019379f, 0.020859f, 0.022583f, 0.024261f, 0.026596f, 0.028839f, 0.031555f,
+ 0.034271f, 0.037628f, 0.041504f, 0.045837f, 0.050598f, 0.056000f, 0.062134f, 0.068726f, 0.076172f, 0.084656f, 0.093567f, 0.103088f,
+ 0.113586f, 0.125000f, 0.504883f, 0.554688f, 0.565918f, 0.570801f, 0.573242f, 0.574219f, 0.000400f, 0.000803f, 0.001046f, 0.001427f,
+ 0.001657f, 0.001952f, 0.002033f, 0.002337f, 0.002453f, 0.002678f, 0.002871f, 0.003120f, 0.003286f, 0.003605f, 0.003817f, 0.004036f,
+ 0.004299f, 0.004604f, 0.004848f, 0.005142f, 0.005428f, 0.005871f, 0.006107f, 0.006584f, 0.006908f, 0.007332f, 0.007736f, 0.008186f,
+ 0.008820f, 0.009308f, 0.009964f, 0.010422f, 0.011200f, 0.011993f, 0.012726f, 0.013512f, 0.014511f, 0.015610f, 0.016724f, 0.017914f,
+ 0.019440f, 0.021057f, 0.022827f, 0.024933f, 0.027466f, 0.030197f, 0.033295f, 0.036896f, 0.041077f, 0.045776f, 0.050995f, 0.056976f,
+ 0.063721f, 0.071167f, 0.079773f, 0.089172f, 0.098633f, 0.109314f, 0.491699f, 0.543457f, 0.555176f, 0.561035f, 0.563477f, 0.565430f,
+ 0.000279f, 0.000821f, 0.000974f, 0.001161f, 0.001382f, 0.001583f, 0.001670f, 0.001934f, 0.002064f, 0.002153f, 0.002306f, 0.002544f,
+ 0.002670f, 0.002909f, 0.003052f, 0.003288f, 0.003429f, 0.003624f, 0.003893f, 0.004082f, 0.004406f, 0.004635f, 0.004925f, 0.005196f,
+ 0.005444f, 0.005764f, 0.006134f, 0.006546f, 0.006947f, 0.007343f, 0.007858f, 0.008270f, 0.008858f, 0.009346f, 0.010010f, 0.010757f,
+ 0.011475f, 0.012260f, 0.013206f, 0.014214f, 0.015236f, 0.016479f, 0.017975f, 0.019623f, 0.021515f, 0.023590f, 0.026062f, 0.028976f,
+ 0.032471f, 0.036224f, 0.040833f, 0.046082f, 0.052094f, 0.059052f, 0.066650f, 0.075684f, 0.084778f, 0.094971f, 0.479492f, 0.532715f,
+ 0.545898f, 0.551270f, 0.553711f, 0.555664f, 0.000253f, 0.000612f, 0.000835f, 0.000998f, 0.001111f, 0.001228f, 0.001334f, 0.001452f,
+ 0.001619f, 0.001757f, 0.001837f, 0.001920f, 0.002140f, 0.002321f, 0.002453f, 0.002544f, 0.002670f, 0.002790f, 0.003086f, 0.003260f,
+ 0.003422f, 0.003620f, 0.003893f, 0.004101f, 0.004326f, 0.004528f, 0.004761f, 0.005051f, 0.005444f, 0.005756f, 0.006065f, 0.006435f,
+ 0.006882f, 0.007378f, 0.007763f, 0.008286f, 0.008865f, 0.009506f, 0.010162f, 0.011024f, 0.011826f, 0.012917f, 0.013916f, 0.015175f,
+ 0.016602f, 0.018204f, 0.020035f, 0.022293f, 0.024948f, 0.028076f, 0.031921f, 0.036377f, 0.041565f, 0.047577f, 0.054535f, 0.062622f,
+ 0.071777f, 0.081787f, 0.465576f, 0.522461f, 0.535645f, 0.541992f, 0.544922f, 0.546875f, 0.000155f, 0.000398f, 0.000680f, 0.000828f,
+ 0.000907f, 0.000989f, 0.001113f, 0.001081f, 0.001253f, 0.001350f, 0.001453f, 0.001573f, 0.001661f, 0.001777f, 0.001829f, 0.001978f,
+ 0.002062f, 0.002216f, 0.002346f, 0.002470f, 0.002644f, 0.002804f, 0.002930f, 0.003134f, 0.003265f, 0.003485f, 0.003674f, 0.003866f,
+ 0.004154f, 0.004333f, 0.004707f, 0.004910f, 0.005180f, 0.005581f, 0.005875f, 0.006283f, 0.006729f, 0.007164f, 0.007713f, 0.008270f,
+ 0.008934f, 0.009727f, 0.010513f, 0.011482f, 0.012520f, 0.013710f, 0.015152f, 0.016815f, 0.018799f, 0.021118f, 0.024048f, 0.027756f,
+ 0.032104f, 0.037201f, 0.043518f, 0.050903f, 0.059418f, 0.068420f, 0.453125f, 0.511719f, 0.525391f, 0.530762f, 0.535156f, 0.536621f,
+ 0.000303f, 0.000337f, 0.000498f, 0.000560f, 0.000603f, 0.000721f, 0.000782f, 0.000845f, 0.000880f, 0.000988f, 0.001119f, 0.001184f,
+ 0.001258f, 0.001377f, 0.001420f, 0.001446f, 0.001590f, 0.001666f, 0.001754f, 0.001889f, 0.001980f, 0.002073f, 0.002216f, 0.002308f,
+ 0.002447f, 0.002562f, 0.002758f, 0.002899f, 0.003084f, 0.003328f, 0.003506f, 0.003641f, 0.003922f, 0.004147f, 0.004391f, 0.004665f,
+ 0.004959f, 0.005322f, 0.005695f, 0.006119f, 0.006588f, 0.007072f, 0.007790f, 0.008392f, 0.009178f, 0.010056f, 0.011124f, 0.012383f,
+ 0.013832f, 0.015587f, 0.017685f, 0.020309f, 0.023926f, 0.028076f, 0.033447f, 0.039978f, 0.047638f, 0.056335f, 0.440186f, 0.500000f,
+ 0.514160f, 0.520996f, 0.524414f, 0.526855f, 0.000132f, 0.000296f, 0.000368f, 0.000444f, 0.000501f, 0.000519f, 0.000631f, 0.000580f,
+ 0.000675f, 0.000735f, 0.000820f, 0.000840f, 0.000882f, 0.000946f, 0.001029f, 0.001070f, 0.001164f, 0.001221f, 0.001286f, 0.001317f,
+ 0.001416f, 0.001494f, 0.001607f, 0.001681f, 0.001763f, 0.001863f, 0.001978f, 0.002069f, 0.002169f, 0.002348f, 0.002451f, 0.002661f,
+ 0.002754f, 0.002943f, 0.003130f, 0.003323f, 0.003553f, 0.003813f, 0.004124f, 0.004364f, 0.004669f, 0.005062f, 0.005493f, 0.005985f,
+ 0.006546f, 0.007172f, 0.007950f, 0.008850f, 0.009857f, 0.011116f, 0.012695f, 0.014603f, 0.016983f, 0.020157f, 0.024490f, 0.029968f,
+ 0.036957f, 0.045166f, 0.426025f, 0.488770f, 0.503906f, 0.511719f, 0.515137f, 0.517578f, 0.000063f, 0.000160f, 0.000267f, 0.000282f,
+ 0.000339f, 0.000417f, 0.000377f, 0.000433f, 0.000472f, 0.000570f, 0.000563f, 0.000578f, 0.000599f, 0.000663f, 0.000681f, 0.000759f,
+ 0.000760f, 0.000845f, 0.000910f, 0.000941f, 0.000997f, 0.001057f, 0.001110f, 0.001169f, 0.001238f, 0.001288f, 0.001381f, 0.001441f,
+ 0.001514f, 0.001655f, 0.001693f, 0.001815f, 0.001910f, 0.002028f, 0.002153f, 0.002308f, 0.002441f, 0.002607f, 0.002783f, 0.002962f,
+ 0.003214f, 0.003458f, 0.003744f, 0.004051f, 0.004444f, 0.004883f, 0.005402f, 0.006031f, 0.006699f, 0.007610f, 0.008766f, 0.009933f,
+ 0.011688f, 0.013931f, 0.017075f, 0.021454f, 0.027313f, 0.035004f, 0.414307f, 0.478271f, 0.493652f, 0.501465f, 0.505859f, 0.508301f,
+ 0.000120f, 0.000194f, 0.000194f, 0.000205f, 0.000245f, 0.000246f, 0.000251f, 0.000301f, 0.000322f, 0.000332f, 0.000343f, 0.000413f,
+ 0.000397f, 0.000448f, 0.000481f, 0.000494f, 0.000545f, 0.000556f, 0.000582f, 0.000601f, 0.000653f, 0.000676f, 0.000726f, 0.000767f,
+ 0.000821f, 0.000840f, 0.000919f, 0.000952f, 0.001011f, 0.001054f, 0.001116f, 0.001186f, 0.001263f, 0.001337f, 0.001418f, 0.001482f,
+ 0.001607f, 0.001685f, 0.001842f, 0.001965f, 0.002090f, 0.002235f, 0.002420f, 0.002613f, 0.002851f, 0.003159f, 0.003492f, 0.003887f,
+ 0.004345f, 0.004906f, 0.005600f, 0.006474f, 0.007645f, 0.009186f, 0.011230f, 0.014305f, 0.019135f, 0.025848f, 0.400635f, 0.466797f,
+ 0.483398f, 0.490967f, 0.495117f, 0.498047f, 0.000030f, 0.000140f, 0.000121f, 0.000114f, 0.000147f, 0.000178f, 0.000159f, 0.000195f,
+ 0.000199f, 0.000204f, 0.000216f, 0.000223f, 0.000255f, 0.000271f, 0.000288f, 0.000302f, 0.000314f, 0.000346f, 0.000357f, 0.000395f,
+ 0.000397f, 0.000408f, 0.000436f, 0.000470f, 0.000501f, 0.000542f, 0.000547f, 0.000566f, 0.000612f, 0.000641f, 0.000692f, 0.000722f,
+ 0.000767f, 0.000798f, 0.000861f, 0.000898f, 0.000963f, 0.001030f, 0.001107f, 0.001164f, 0.001255f, 0.001361f, 0.001464f, 0.001591f,
+ 0.001719f, 0.001871f, 0.002111f, 0.002312f, 0.002617f, 0.002964f, 0.003368f, 0.003902f, 0.004654f, 0.005653f, 0.006958f, 0.008888f,
+ 0.012161f, 0.017822f, 0.388672f, 0.456543f, 0.473389f, 0.481201f, 0.486328f, 0.489014f, 0.000102f, 0.000076f, 0.000076f, 0.000075f,
+ 0.000095f, 0.000092f, 0.000109f, 0.000111f, 0.000112f, 0.000113f, 0.000126f, 0.000147f, 0.000135f, 0.000144f, 0.000165f, 0.000161f,
+ 0.000179f, 0.000192f, 0.000198f, 0.000202f, 0.000224f, 0.000232f, 0.000248f, 0.000259f, 0.000278f, 0.000295f, 0.000308f, 0.000320f,
+ 0.000340f, 0.000353f, 0.000379f, 0.000402f, 0.000423f, 0.000440f, 0.000472f, 0.000503f, 0.000526f, 0.000564f, 0.000610f, 0.000644f,
+ 0.000690f, 0.000741f, 0.000810f, 0.000862f, 0.000946f, 0.001024f, 0.001121f, 0.001247f, 0.001407f, 0.001603f, 0.001822f, 0.002144f,
+ 0.002539f, 0.003098f, 0.003901f, 0.005096f, 0.006931f, 0.011024f, 0.375244f, 0.444092f, 0.462158f, 0.470215f, 0.475586f, 0.478760f,
+ 0.000085f, 0.000061f, 0.000052f, 0.000047f, 0.000049f, 0.000046f, 0.000047f, 0.000050f, 0.000055f, 0.000069f, 0.000060f, 0.000062f,
+ 0.000077f, 0.000066f, 0.000069f, 0.000075f, 0.000084f, 0.000093f, 0.000093f, 0.000098f, 0.000102f, 0.000108f, 0.000111f, 0.000121f,
+ 0.000129f, 0.000136f, 0.000142f, 0.000154f, 0.000162f, 0.000172f, 0.000182f, 0.000187f, 0.000197f, 0.000209f, 0.000225f, 0.000231f,
+ 0.000246f, 0.000262f, 0.000290f, 0.000306f, 0.000321f, 0.000349f, 0.000380f, 0.000402f, 0.000437f, 0.000480f, 0.000525f, 0.000579f,
+ 0.000649f, 0.000735f, 0.000842f, 0.000984f, 0.001173f, 0.001451f, 0.001855f, 0.002485f, 0.003542f, 0.005753f, 0.362305f, 0.434326f,
+ 0.451904f, 0.460693f, 0.465576f, 0.468506f, 0.000064f, 0.000044f, 0.000036f, 0.000032f, 0.000029f, 0.000027f, 0.000025f, 0.000024f,
+ 0.000022f, 0.000023f, 0.000021f, 0.000027f, 0.000023f, 0.000022f, 0.000028f, 0.000031f, 0.000030f, 0.000034f, 0.000036f, 0.000038f,
+ 0.000040f, 0.000045f, 0.000048f, 0.000042f, 0.000047f, 0.000053f, 0.000055f, 0.000054f, 0.000060f, 0.000062f, 0.000065f, 0.000072f,
+ 0.000078f, 0.000075f, 0.000079f, 0.000087f, 0.000093f, 0.000098f, 0.000106f, 0.000113f, 0.000121f, 0.000126f, 0.000136f, 0.000150f,
+ 0.000159f, 0.000173f, 0.000190f, 0.000209f, 0.000235f, 0.000265f, 0.000302f, 0.000343f, 0.000416f, 0.000515f, 0.000665f, 0.000917f,
+ 0.001396f, 0.002401f, 0.349854f, 0.421875f, 0.440918f, 0.449951f, 0.455811f, 0.458008f, 0.000030f, 0.000020f, 0.000016f, 0.000014f,
+ 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f,
+ 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000007f, 0.000007f, 0.000008f, 0.000008f, 0.000009f, 0.000011f, 0.000011f, 0.000013f,
+ 0.000013f, 0.000012f, 0.000013f, 0.000014f, 0.000016f, 0.000018f, 0.000018f, 0.000019f, 0.000021f, 0.000021f, 0.000023f, 0.000027f,
+ 0.000025f, 0.000028f, 0.000031f, 0.000032f, 0.000033f, 0.000038f, 0.000043f, 0.000046f, 0.000050f, 0.000055f, 0.000062f, 0.000074f,
+ 0.000088f, 0.000106f, 0.000138f, 0.000191f, 0.000312f, 0.000653f, 0.337402f, 0.410645f, 0.431152f, 0.438965f, 0.445068f, 0.448975f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000004f, 0.000006f, 0.000010f, 0.000026f, 0.324219f, 0.399902f,
+ 0.419922f, 0.429688f, 0.435059f, 0.438965f,
+ },
+ {
+ 0.010521f, 0.032043f, 0.054443f, 0.076843f, 0.098572f, 0.121216f, 0.142700f, 0.164062f, 0.185913f, 0.207275f, 0.229004f, 0.249268f,
+ 0.270508f, 0.290527f, 0.311035f, 0.331055f, 0.350586f, 0.370361f, 0.389648f, 0.408936f, 0.428223f, 0.446533f, 0.465088f, 0.482666f,
+ 0.500977f, 0.519043f, 0.536133f, 0.553223f, 0.570801f, 0.587891f, 0.604980f, 0.621582f, 0.637207f, 0.653320f, 0.668945f, 0.685547f,
+ 0.700684f, 0.716309f, 0.730957f, 0.745605f, 0.760254f, 0.774902f, 0.789551f, 0.803711f, 0.816895f, 0.831543f, 0.845703f, 0.858887f,
+ 0.871582f, 0.885254f, 0.897949f, 0.910645f, 0.923340f, 0.936035f, 0.948242f, 0.959961f, 0.972168f, 0.984375f, 0.972656f, 0.936035f,
+ 0.910645f, 0.890137f, 0.872070f, 0.855957f, 0.010048f, 0.030350f, 0.051392f, 0.072266f, 0.093506f, 0.114319f, 0.135620f, 0.155273f,
+ 0.177124f, 0.197144f, 0.217773f, 0.237915f, 0.257568f, 0.277588f, 0.298096f, 0.316895f, 0.336182f, 0.355225f, 0.374268f, 0.393311f,
+ 0.411865f, 0.430176f, 0.448486f, 0.466309f, 0.483398f, 0.501465f, 0.519043f, 0.535645f, 0.552734f, 0.570312f, 0.586426f, 0.602539f,
+ 0.618652f, 0.635254f, 0.650879f, 0.666016f, 0.682129f, 0.697266f, 0.712402f, 0.727539f, 0.741699f, 0.756836f, 0.770996f, 0.785645f,
+ 0.799805f, 0.812988f, 0.826660f, 0.840332f, 0.854004f, 0.867676f, 0.881348f, 0.893066f, 0.907715f, 0.919434f, 0.932617f, 0.943848f,
+ 0.955566f, 0.968262f, 0.965332f, 0.930664f, 0.906738f, 0.886719f, 0.869629f, 0.854004f, 0.009254f, 0.028961f, 0.048615f, 0.068054f,
+ 0.088562f, 0.108093f, 0.128540f, 0.147705f, 0.167236f, 0.188599f, 0.207886f, 0.227295f, 0.244873f, 0.265625f, 0.284668f, 0.303955f,
+ 0.322510f, 0.340820f, 0.358887f, 0.378662f, 0.396484f, 0.414307f, 0.431885f, 0.448975f, 0.466797f, 0.484619f, 0.500977f, 0.519043f,
+ 0.535645f, 0.551758f, 0.568359f, 0.584961f, 0.600586f, 0.616699f, 0.632324f, 0.647949f, 0.663086f, 0.678223f, 0.693848f, 0.708984f,
+ 0.723633f, 0.738281f, 0.752930f, 0.767578f, 0.780762f, 0.794922f, 0.809082f, 0.822754f, 0.835938f, 0.849609f, 0.863770f, 0.875488f,
+ 0.888672f, 0.902344f, 0.915527f, 0.927246f, 0.939453f, 0.952637f, 0.958008f, 0.925293f, 0.901855f, 0.882812f, 0.866211f, 0.851562f,
+ 0.008736f, 0.027039f, 0.045807f, 0.064514f, 0.083801f, 0.102844f, 0.121826f, 0.140869f, 0.159302f, 0.179077f, 0.197388f, 0.216064f,
+ 0.234741f, 0.253662f, 0.271729f, 0.290283f, 0.308350f, 0.327148f, 0.344238f, 0.362061f, 0.381836f, 0.398926f, 0.416016f, 0.432373f,
+ 0.450195f, 0.466797f, 0.484375f, 0.500977f, 0.517090f, 0.533691f, 0.550781f, 0.567871f, 0.582031f, 0.598145f, 0.613770f, 0.629395f,
+ 0.645020f, 0.659668f, 0.675781f, 0.689941f, 0.705566f, 0.719727f, 0.734375f, 0.749512f, 0.763184f, 0.776855f, 0.791016f, 0.804688f,
+ 0.818848f, 0.832031f, 0.845215f, 0.858398f, 0.872559f, 0.884766f, 0.897949f, 0.909668f, 0.922852f, 0.936035f, 0.950684f, 0.919434f,
+ 0.896973f, 0.878906f, 0.862793f, 0.848633f, 0.008339f, 0.025543f, 0.043427f, 0.060974f, 0.078979f, 0.097168f, 0.115051f, 0.133179f,
+ 0.151367f, 0.169678f, 0.187988f, 0.206055f, 0.223999f, 0.241821f, 0.260742f, 0.277832f, 0.295166f, 0.313232f, 0.331299f, 0.347412f,
+ 0.365479f, 0.383057f, 0.399902f, 0.416992f, 0.433350f, 0.450195f, 0.467773f, 0.484863f, 0.499756f, 0.515625f, 0.532715f, 0.548340f,
+ 0.564941f, 0.580566f, 0.596191f, 0.610840f, 0.626953f, 0.641602f, 0.656738f, 0.671875f, 0.686035f, 0.701660f, 0.714844f, 0.730469f,
+ 0.745117f, 0.759766f, 0.772461f, 0.786621f, 0.801270f, 0.814453f, 0.827637f, 0.841309f, 0.854004f, 0.867676f, 0.880859f, 0.893555f,
+ 0.907227f, 0.919434f, 0.943359f, 0.913086f, 0.891602f, 0.874512f, 0.858887f, 0.845703f, 0.008102f, 0.024002f, 0.040802f, 0.057098f,
+ 0.074768f, 0.091553f, 0.108826f, 0.126343f, 0.143921f, 0.161377f, 0.179077f, 0.195923f, 0.213745f, 0.230835f, 0.248047f, 0.265869f,
+ 0.282227f, 0.299561f, 0.316895f, 0.334473f, 0.350586f, 0.367920f, 0.384277f, 0.400391f, 0.417725f, 0.434326f, 0.450195f, 0.467285f,
+ 0.482910f, 0.498291f, 0.514648f, 0.530762f, 0.546387f, 0.561523f, 0.577637f, 0.593262f, 0.608398f, 0.623535f, 0.637695f, 0.654297f,
+ 0.668457f, 0.682617f, 0.698242f, 0.711914f, 0.727051f, 0.741211f, 0.754395f, 0.768066f, 0.782715f, 0.796387f, 0.810547f, 0.823730f,
+ 0.836426f, 0.849609f, 0.863770f, 0.876465f, 0.889648f, 0.902344f, 0.934570f, 0.907715f, 0.887207f, 0.870117f, 0.854980f, 0.842285f,
+ 0.007504f, 0.022812f, 0.038727f, 0.054871f, 0.070312f, 0.087097f, 0.103088f, 0.119446f, 0.136475f, 0.153442f, 0.169556f, 0.186523f,
+ 0.203369f, 0.219971f, 0.236450f, 0.253418f, 0.270264f, 0.287109f, 0.302979f, 0.319824f, 0.336182f, 0.353271f, 0.369141f, 0.386230f,
+ 0.402100f, 0.417725f, 0.433594f, 0.450684f, 0.466553f, 0.482178f, 0.498047f, 0.513184f, 0.528809f, 0.543945f, 0.559082f, 0.575195f,
+ 0.589844f, 0.605469f, 0.621094f, 0.634277f, 0.649414f, 0.665039f, 0.679688f, 0.694824f, 0.708496f, 0.722168f, 0.736816f, 0.750000f,
+ 0.763184f, 0.778809f, 0.791504f, 0.805664f, 0.819336f, 0.832520f, 0.845703f, 0.858887f, 0.872070f, 0.885742f, 0.927246f, 0.900879f,
+ 0.881836f, 0.864746f, 0.851074f, 0.838867f, 0.006836f, 0.021683f, 0.036224f, 0.051666f, 0.066772f, 0.081970f, 0.098022f, 0.113831f,
+ 0.129517f, 0.145264f, 0.161011f, 0.177856f, 0.193359f, 0.209106f, 0.226196f, 0.241821f, 0.257812f, 0.274414f, 0.290283f, 0.306641f,
+ 0.322754f, 0.338623f, 0.354492f, 0.370361f, 0.386230f, 0.402100f, 0.417725f, 0.433838f, 0.449463f, 0.465088f, 0.480469f, 0.495605f,
+ 0.511719f, 0.527344f, 0.541016f, 0.556641f, 0.571777f, 0.587402f, 0.601562f, 0.617676f, 0.631836f, 0.646484f, 0.660645f, 0.674805f,
+ 0.689941f, 0.704102f, 0.718262f, 0.731934f, 0.746582f, 0.760254f, 0.774414f, 0.786621f, 0.801758f, 0.815430f, 0.828125f, 0.842285f,
+ 0.854980f, 0.868652f, 0.918457f, 0.894531f, 0.875977f, 0.859863f, 0.846680f, 0.834961f, 0.006672f, 0.020401f, 0.034088f, 0.048462f,
+ 0.062927f, 0.077820f, 0.092529f, 0.107666f, 0.122803f, 0.137695f, 0.152954f, 0.169067f, 0.183716f, 0.199829f, 0.214722f, 0.230347f,
+ 0.246704f, 0.262207f, 0.277832f, 0.292969f, 0.308105f, 0.324219f, 0.339600f, 0.354492f, 0.371094f, 0.386963f, 0.401855f, 0.418457f,
+ 0.432861f, 0.449219f, 0.463379f, 0.478271f, 0.494385f, 0.508301f, 0.523438f, 0.539551f, 0.553711f, 0.568848f, 0.583984f, 0.598633f,
+ 0.612793f, 0.627441f, 0.642578f, 0.656250f, 0.670898f, 0.685547f, 0.698730f, 0.714355f, 0.728027f, 0.742188f, 0.755859f, 0.769531f,
+ 0.783691f, 0.795898f, 0.810059f, 0.824707f, 0.838379f, 0.850586f, 0.910645f, 0.887695f, 0.870117f, 0.854980f, 0.842285f, 0.831055f,
+ 0.006207f, 0.019211f, 0.032623f, 0.046112f, 0.059662f, 0.073181f, 0.087585f, 0.102051f, 0.116577f, 0.130249f, 0.145142f, 0.159790f,
+ 0.175171f, 0.189575f, 0.205322f, 0.219238f, 0.235474f, 0.249634f, 0.265137f, 0.280029f, 0.294678f, 0.310547f, 0.325928f, 0.340820f,
+ 0.356201f, 0.371094f, 0.386230f, 0.401367f, 0.416504f, 0.431885f, 0.446533f, 0.461670f, 0.476074f, 0.492188f, 0.507324f, 0.520996f,
+ 0.535645f, 0.550781f, 0.564941f, 0.580078f, 0.594727f, 0.609863f, 0.623535f, 0.637695f, 0.652832f, 0.667480f, 0.681152f, 0.695312f,
+ 0.709473f, 0.723633f, 0.737793f, 0.751953f, 0.765137f, 0.779297f, 0.793945f, 0.807129f, 0.819824f, 0.833496f, 0.901855f, 0.880859f,
+ 0.864258f, 0.850098f, 0.837891f, 0.826660f, 0.006020f, 0.018219f, 0.030579f, 0.043365f, 0.055908f, 0.069153f, 0.082336f, 0.096802f,
+ 0.109497f, 0.123535f, 0.137451f, 0.151855f, 0.165649f, 0.180054f, 0.194702f, 0.208252f, 0.223999f, 0.238037f, 0.252930f, 0.267334f,
+ 0.281982f, 0.296875f, 0.312012f, 0.326904f, 0.340820f, 0.355957f, 0.370850f, 0.385986f, 0.400391f, 0.415039f, 0.430176f, 0.445801f,
+ 0.459229f, 0.474365f, 0.489014f, 0.502441f, 0.518066f, 0.533203f, 0.547363f, 0.562012f, 0.576660f, 0.590820f, 0.605469f, 0.619629f,
+ 0.633789f, 0.647949f, 0.663574f, 0.676758f, 0.690918f, 0.705566f, 0.719238f, 0.733398f, 0.746582f, 0.760254f, 0.774414f, 0.788574f,
+ 0.802246f, 0.816406f, 0.894043f, 0.874023f, 0.858398f, 0.844238f, 0.832031f, 0.822266f, 0.005520f, 0.017059f, 0.028625f, 0.040649f,
+ 0.053131f, 0.065552f, 0.077698f, 0.091187f, 0.104065f, 0.117371f, 0.130859f, 0.143677f, 0.157349f, 0.171021f, 0.184814f, 0.198730f,
+ 0.213135f, 0.226807f, 0.241211f, 0.255127f, 0.269775f, 0.283691f, 0.298096f, 0.312744f, 0.326660f, 0.341553f, 0.355957f, 0.370117f,
+ 0.384766f, 0.399170f, 0.414307f, 0.427979f, 0.442627f, 0.457764f, 0.471924f, 0.486084f, 0.500488f, 0.515137f, 0.529785f, 0.543945f,
+ 0.558594f, 0.572754f, 0.587402f, 0.601074f, 0.615234f, 0.629395f, 0.644043f, 0.657715f, 0.672852f, 0.685547f, 0.700684f, 0.714844f,
+ 0.728027f, 0.743164f, 0.756348f, 0.770508f, 0.785645f, 0.798340f, 0.885254f, 0.867676f, 0.852051f, 0.839355f, 0.828125f, 0.817871f,
+ 0.005241f, 0.015854f, 0.027481f, 0.038605f, 0.050171f, 0.061859f, 0.073853f, 0.085693f, 0.098328f, 0.111206f, 0.123474f, 0.136475f,
+ 0.149658f, 0.162598f, 0.175293f, 0.188477f, 0.202148f, 0.216431f, 0.229858f, 0.242798f, 0.256104f, 0.270264f, 0.284668f, 0.298828f,
+ 0.312744f, 0.326904f, 0.341064f, 0.355469f, 0.369141f, 0.383057f, 0.396729f, 0.411621f, 0.426025f, 0.439697f, 0.454590f, 0.468506f,
+ 0.482666f, 0.497070f, 0.512207f, 0.525391f, 0.540527f, 0.555176f, 0.567871f, 0.582031f, 0.596191f, 0.610840f, 0.625488f, 0.639648f,
+ 0.653809f, 0.668457f, 0.681641f, 0.695801f, 0.710449f, 0.724121f, 0.738770f, 0.751953f, 0.766602f, 0.780273f, 0.876465f, 0.860352f,
+ 0.845703f, 0.833984f, 0.822754f, 0.812988f, 0.004982f, 0.015274f, 0.025681f, 0.036438f, 0.047119f, 0.058167f, 0.069397f, 0.081055f,
+ 0.092957f, 0.104492f, 0.116577f, 0.128418f, 0.141113f, 0.153442f, 0.166504f, 0.179321f, 0.192261f, 0.205200f, 0.218506f, 0.231934f,
+ 0.244629f, 0.258301f, 0.271729f, 0.284912f, 0.299072f, 0.312988f, 0.325684f, 0.340088f, 0.353271f, 0.367676f, 0.381836f, 0.395508f,
+ 0.408936f, 0.423584f, 0.438232f, 0.451416f, 0.466309f, 0.479736f, 0.493896f, 0.507812f, 0.521973f, 0.536133f, 0.550293f, 0.563965f,
+ 0.578613f, 0.592773f, 0.606934f, 0.620605f, 0.635254f, 0.649414f, 0.663086f, 0.677246f, 0.691406f, 0.706543f, 0.720703f, 0.734375f,
+ 0.748047f, 0.762695f, 0.868164f, 0.853027f, 0.839355f, 0.828125f, 0.817383f, 0.808105f, 0.004745f, 0.014290f, 0.024506f, 0.034393f,
+ 0.044617f, 0.054749f, 0.065308f, 0.076538f, 0.087646f, 0.098938f, 0.110535f, 0.121582f, 0.134155f, 0.145264f, 0.157837f, 0.170166f,
+ 0.182373f, 0.194824f, 0.207153f, 0.220337f, 0.233276f, 0.245728f, 0.259277f, 0.271973f, 0.285645f, 0.298584f, 0.311768f, 0.325684f,
+ 0.338623f, 0.352539f, 0.365967f, 0.379395f, 0.393066f, 0.406738f, 0.421143f, 0.434326f, 0.448730f, 0.462402f, 0.475586f, 0.490479f,
+ 0.503906f, 0.518066f, 0.532227f, 0.546387f, 0.560059f, 0.574219f, 0.588379f, 0.602539f, 0.616211f, 0.630371f, 0.644531f, 0.658691f,
+ 0.673340f, 0.686523f, 0.701660f, 0.715332f, 0.730469f, 0.745117f, 0.858887f, 0.845215f, 0.833008f, 0.821777f, 0.812012f, 0.802734f,
+ 0.004494f, 0.013550f, 0.022675f, 0.032227f, 0.042145f, 0.052002f, 0.061554f, 0.072205f, 0.082520f, 0.093323f, 0.104614f, 0.115112f,
+ 0.126099f, 0.137817f, 0.149536f, 0.160767f, 0.172607f, 0.184692f, 0.196167f, 0.208862f, 0.221924f, 0.233765f, 0.246216f, 0.258545f,
+ 0.272461f, 0.284424f, 0.297119f, 0.310547f, 0.323242f, 0.336914f, 0.350586f, 0.363281f, 0.376953f, 0.390869f, 0.403564f, 0.416992f,
+ 0.431152f, 0.444824f, 0.458496f, 0.472656f, 0.486084f, 0.500000f, 0.513672f, 0.527832f, 0.541504f, 0.555664f, 0.569824f, 0.583496f,
+ 0.598145f, 0.611816f, 0.626465f, 0.639648f, 0.654297f, 0.668457f, 0.683594f, 0.697754f, 0.711914f, 0.726562f, 0.849609f, 0.838867f,
+ 0.826172f, 0.815918f, 0.806641f, 0.796875f, 0.004288f, 0.012619f, 0.021713f, 0.030945f, 0.039368f, 0.048737f, 0.058533f, 0.067932f,
+ 0.077759f, 0.088013f, 0.098755f, 0.108398f, 0.119080f, 0.129639f, 0.141235f, 0.152466f, 0.163940f, 0.174927f, 0.186768f, 0.198608f,
+ 0.210205f, 0.222290f, 0.234131f, 0.246094f, 0.258789f, 0.270508f, 0.283203f, 0.296631f, 0.309326f, 0.321777f, 0.335449f, 0.348145f,
+ 0.361084f, 0.374023f, 0.386963f, 0.400391f, 0.414062f, 0.427734f, 0.441162f, 0.455078f, 0.467773f, 0.482422f, 0.495117f, 0.509277f,
+ 0.523926f, 0.536621f, 0.550781f, 0.564941f, 0.579102f, 0.593262f, 0.607422f, 0.621582f, 0.635742f, 0.649902f, 0.664551f, 0.678711f,
+ 0.693848f, 0.708008f, 0.840820f, 0.831055f, 0.819336f, 0.809570f, 0.801270f, 0.792969f, 0.004013f, 0.012070f, 0.019989f, 0.029190f,
+ 0.037415f, 0.045776f, 0.055023f, 0.064392f, 0.073669f, 0.083374f, 0.092224f, 0.102295f, 0.112610f, 0.122742f, 0.133057f, 0.143799f,
+ 0.155273f, 0.165527f, 0.176880f, 0.188110f, 0.199463f, 0.210815f, 0.222534f, 0.234619f, 0.245972f, 0.258301f, 0.270508f, 0.282715f,
+ 0.294678f, 0.307129f, 0.320557f, 0.333008f, 0.345947f, 0.358398f, 0.371826f, 0.384277f, 0.397461f, 0.410889f, 0.424561f, 0.437256f,
+ 0.451416f, 0.464600f, 0.477783f, 0.491455f, 0.504395f, 0.518555f, 0.532715f, 0.546875f, 0.560547f, 0.574219f, 0.588379f, 0.604004f,
+ 0.617188f, 0.631348f, 0.645020f, 0.660645f, 0.674316f, 0.689941f, 0.832031f, 0.823242f, 0.813477f, 0.803711f, 0.794922f, 0.787109f,
+ 0.003790f, 0.011559f, 0.019119f, 0.027069f, 0.035034f, 0.043762f, 0.052032f, 0.060059f, 0.069153f, 0.078369f, 0.087280f, 0.096741f,
+ 0.105957f, 0.115967f, 0.125732f, 0.135620f, 0.146118f, 0.156128f, 0.166992f, 0.177612f, 0.188965f, 0.199829f, 0.210815f, 0.222290f,
+ 0.233887f, 0.244873f, 0.257324f, 0.268799f, 0.281006f, 0.292969f, 0.305420f, 0.317627f, 0.329834f, 0.341797f, 0.355469f, 0.368164f,
+ 0.380859f, 0.393311f, 0.407227f, 0.419434f, 0.433350f, 0.446533f, 0.459961f, 0.473633f, 0.486328f, 0.500488f, 0.515625f, 0.528320f,
+ 0.541504f, 0.556152f, 0.570312f, 0.584473f, 0.598633f, 0.612305f, 0.626465f, 0.640625f, 0.655762f, 0.670410f, 0.822266f, 0.815918f,
+ 0.805664f, 0.796387f, 0.788574f, 0.782227f, 0.003599f, 0.010727f, 0.018219f, 0.025177f, 0.033203f, 0.041046f, 0.048981f, 0.057220f,
+ 0.065247f, 0.073792f, 0.082764f, 0.091064f, 0.100220f, 0.108826f, 0.118591f, 0.128052f, 0.137573f, 0.147705f, 0.158081f, 0.167603f,
+ 0.177979f, 0.188721f, 0.198975f, 0.210205f, 0.221924f, 0.232544f, 0.243774f, 0.255615f, 0.267090f, 0.278564f, 0.290039f, 0.302490f,
+ 0.314941f, 0.327393f, 0.338623f, 0.352295f, 0.364014f, 0.377441f, 0.390381f, 0.403564f, 0.415039f, 0.428955f, 0.441895f, 0.455078f,
+ 0.468994f, 0.482666f, 0.496094f, 0.509277f, 0.523926f, 0.537598f, 0.551270f, 0.565430f, 0.579590f, 0.594238f, 0.608887f, 0.622559f,
+ 0.637207f, 0.651855f, 0.813477f, 0.807617f, 0.798340f, 0.790527f, 0.782715f, 0.775391f, 0.003355f, 0.009918f, 0.017105f, 0.023911f,
+ 0.031281f, 0.038147f, 0.045990f, 0.053284f, 0.061493f, 0.069214f, 0.077026f, 0.085571f, 0.093567f, 0.102600f, 0.111755f, 0.120728f,
+ 0.129761f, 0.138916f, 0.148804f, 0.158447f, 0.167725f, 0.177979f, 0.188965f, 0.198608f, 0.209473f, 0.220215f, 0.231567f, 0.242554f,
+ 0.253906f, 0.264160f, 0.276123f, 0.287109f, 0.300049f, 0.312012f, 0.323975f, 0.336182f, 0.348145f, 0.360840f, 0.372803f, 0.385986f,
+ 0.398438f, 0.411621f, 0.424316f, 0.437256f, 0.450439f, 0.464844f, 0.478027f, 0.490723f, 0.504395f, 0.518066f, 0.532715f, 0.546387f,
+ 0.561523f, 0.575684f, 0.589355f, 0.604004f, 0.618164f, 0.632324f, 0.802246f, 0.800293f, 0.792480f, 0.783691f, 0.776367f, 0.769531f,
+ 0.003265f, 0.009575f, 0.016144f, 0.022415f, 0.029510f, 0.036316f, 0.042755f, 0.050812f, 0.057556f, 0.065002f, 0.072388f, 0.080200f,
+ 0.087952f, 0.096680f, 0.104858f, 0.113281f, 0.122070f, 0.130493f, 0.139771f, 0.148926f, 0.158447f, 0.168335f, 0.177612f, 0.187500f,
+ 0.198120f, 0.208130f, 0.218750f, 0.229492f, 0.240234f, 0.250732f, 0.262207f, 0.273682f, 0.285156f, 0.296143f, 0.308594f, 0.320068f,
+ 0.332520f, 0.344482f, 0.357178f, 0.368652f, 0.381836f, 0.394043f, 0.406494f, 0.420410f, 0.433105f, 0.445801f, 0.459717f, 0.473633f,
+ 0.486816f, 0.500000f, 0.513672f, 0.527832f, 0.541992f, 0.556152f, 0.570312f, 0.585449f, 0.598633f, 0.613770f, 0.794434f, 0.791504f,
+ 0.784180f, 0.776855f, 0.770020f, 0.764160f, 0.002954f, 0.008904f, 0.014961f, 0.021210f, 0.027420f, 0.033905f, 0.040619f, 0.047363f,
+ 0.053986f, 0.060883f, 0.068054f, 0.075378f, 0.082703f, 0.090515f, 0.098022f, 0.105896f, 0.114319f, 0.122742f, 0.131592f, 0.139771f,
+ 0.149170f, 0.157959f, 0.167480f, 0.177124f, 0.186768f, 0.196411f, 0.206543f, 0.216919f, 0.227539f, 0.237671f, 0.248413f, 0.259277f,
+ 0.270264f, 0.281738f, 0.292725f, 0.304443f, 0.315918f, 0.327637f, 0.340576f, 0.352539f, 0.364746f, 0.377930f, 0.390137f, 0.401855f,
+ 0.415039f, 0.428223f, 0.441406f, 0.454834f, 0.468506f, 0.481689f, 0.494873f, 0.509277f, 0.523438f, 0.537598f, 0.551758f, 0.565918f,
+ 0.580078f, 0.594727f, 0.783691f, 0.783203f, 0.776855f, 0.770508f, 0.763672f, 0.757324f, 0.002836f, 0.008659f, 0.014351f, 0.019913f,
+ 0.025772f, 0.032074f, 0.037933f, 0.044128f, 0.050903f, 0.057159f, 0.064026f, 0.070496f, 0.077698f, 0.085022f, 0.091919f, 0.099426f,
+ 0.107727f, 0.114990f, 0.123169f, 0.131226f, 0.140015f, 0.148682f, 0.157349f, 0.166260f, 0.175171f, 0.184692f, 0.194214f, 0.203979f,
+ 0.214355f, 0.224487f, 0.234985f, 0.245728f, 0.256104f, 0.267334f, 0.278320f, 0.288818f, 0.301025f, 0.312256f, 0.324219f, 0.335938f,
+ 0.347900f, 0.360596f, 0.372070f, 0.384521f, 0.397217f, 0.410400f, 0.423340f, 0.436279f, 0.449463f, 0.463135f, 0.476807f, 0.490723f,
+ 0.503906f, 0.517578f, 0.532227f, 0.546875f, 0.561035f, 0.575684f, 0.773926f, 0.775391f, 0.769043f, 0.763672f, 0.757812f, 0.751953f,
+ 0.002506f, 0.008080f, 0.013100f, 0.018738f, 0.024384f, 0.029953f, 0.035797f, 0.041473f, 0.047485f, 0.053558f, 0.059265f, 0.065918f,
+ 0.072693f, 0.079468f, 0.086426f, 0.093384f, 0.100708f, 0.108032f, 0.115417f, 0.122986f, 0.130615f, 0.139038f, 0.147827f, 0.156494f,
+ 0.165039f, 0.173828f, 0.182617f, 0.192139f, 0.201782f, 0.211426f, 0.221558f, 0.231323f, 0.242188f, 0.252686f, 0.263672f, 0.274414f,
+ 0.284912f, 0.296143f, 0.308105f, 0.319824f, 0.331543f, 0.343750f, 0.355225f, 0.367432f, 0.379883f, 0.393066f, 0.405273f, 0.418457f,
+ 0.431641f, 0.444580f, 0.457764f, 0.471924f, 0.485840f, 0.499268f, 0.512695f, 0.527344f, 0.542480f, 0.556641f, 0.764160f, 0.766602f,
+ 0.761719f, 0.756348f, 0.750488f, 0.745605f, 0.002640f, 0.007809f, 0.012497f, 0.017593f, 0.023102f, 0.028122f, 0.033569f, 0.038879f,
+ 0.044250f, 0.049988f, 0.055908f, 0.061615f, 0.067627f, 0.074036f, 0.080566f, 0.087524f, 0.093262f, 0.100769f, 0.107910f, 0.114929f,
+ 0.121948f, 0.130371f, 0.137939f, 0.146362f, 0.154297f, 0.163208f, 0.171509f, 0.180664f, 0.189697f, 0.199341f, 0.208618f, 0.218506f,
+ 0.228394f, 0.238892f, 0.248779f, 0.259277f, 0.270752f, 0.281250f, 0.292236f, 0.303467f, 0.315186f, 0.326660f, 0.338867f, 0.351074f,
+ 0.362305f, 0.374756f, 0.387939f, 0.400146f, 0.413330f, 0.426514f, 0.439209f, 0.452881f, 0.466553f, 0.480225f, 0.494141f, 0.508301f,
+ 0.522949f, 0.537109f, 0.753906f, 0.758301f, 0.754395f, 0.749023f, 0.743652f, 0.739258f, 0.002441f, 0.007088f, 0.011993f, 0.016266f,
+ 0.021255f, 0.026031f, 0.031189f, 0.036072f, 0.041260f, 0.046753f, 0.052155f, 0.057587f, 0.063232f, 0.068787f, 0.075623f, 0.081055f,
+ 0.087341f, 0.094177f, 0.100647f, 0.106689f, 0.113892f, 0.121399f, 0.129028f, 0.136841f, 0.144287f, 0.152222f, 0.160522f, 0.169312f,
+ 0.178101f, 0.186523f, 0.196045f, 0.205200f, 0.214966f, 0.224487f, 0.234863f, 0.244751f, 0.255371f, 0.265625f, 0.276367f, 0.287842f,
+ 0.298828f, 0.310303f, 0.321533f, 0.333984f, 0.345459f, 0.357666f, 0.370117f, 0.382568f, 0.394287f, 0.407959f, 0.421875f, 0.433838f,
+ 0.446777f, 0.461426f, 0.475098f, 0.488525f, 0.504395f, 0.517578f, 0.744141f, 0.749512f, 0.746094f, 0.741699f, 0.736816f, 0.732422f,
+ 0.002172f, 0.006695f, 0.011093f, 0.015266f, 0.020081f, 0.024521f, 0.029388f, 0.033966f, 0.038727f, 0.043427f, 0.048706f, 0.053772f,
+ 0.059418f, 0.064270f, 0.069580f, 0.075500f, 0.081421f, 0.087280f, 0.093262f, 0.099670f, 0.106567f, 0.113220f, 0.119995f, 0.127197f,
+ 0.134644f, 0.142212f, 0.150146f, 0.157959f, 0.166382f, 0.174927f, 0.184082f, 0.192505f, 0.201904f, 0.211792f, 0.220825f, 0.230713f,
+ 0.240601f, 0.251221f, 0.261719f, 0.272461f, 0.282715f, 0.294434f, 0.305420f, 0.316650f, 0.328369f, 0.340088f, 0.352783f, 0.364746f,
+ 0.377197f, 0.389648f, 0.402832f, 0.416016f, 0.429443f, 0.442627f, 0.456055f, 0.469971f, 0.484863f, 0.499268f, 0.733887f, 0.741211f,
+ 0.737793f, 0.734375f, 0.729980f, 0.725586f, 0.002045f, 0.006187f, 0.010406f, 0.014664f, 0.018570f, 0.022675f, 0.027176f, 0.031586f,
+ 0.035858f, 0.040253f, 0.045227f, 0.049774f, 0.054504f, 0.059692f, 0.065186f, 0.070374f, 0.075500f, 0.080627f, 0.086792f, 0.092285f,
+ 0.098999f, 0.104675f, 0.111816f, 0.118286f, 0.125610f, 0.132324f, 0.139771f, 0.147339f, 0.155029f, 0.163696f, 0.171631f, 0.180420f,
+ 0.189087f, 0.197754f, 0.207275f, 0.216309f, 0.226440f, 0.236694f, 0.246338f, 0.256836f, 0.267334f, 0.278320f, 0.289062f, 0.300537f,
+ 0.312012f, 0.323975f, 0.335449f, 0.347168f, 0.359375f, 0.372314f, 0.384521f, 0.396973f, 0.410400f, 0.423584f, 0.437500f, 0.450928f,
+ 0.465332f, 0.479736f, 0.723145f, 0.732422f, 0.729980f, 0.726562f, 0.722656f, 0.718750f, 0.002148f, 0.005802f, 0.009811f, 0.013565f,
+ 0.017578f, 0.021179f, 0.025040f, 0.029053f, 0.033417f, 0.037445f, 0.042114f, 0.046112f, 0.050720f, 0.055511f, 0.060028f, 0.065002f,
+ 0.069458f, 0.075134f, 0.080078f, 0.085693f, 0.091492f, 0.097290f, 0.103394f, 0.109802f, 0.116089f, 0.122925f, 0.129883f, 0.136963f,
+ 0.144165f, 0.151733f, 0.160156f, 0.167847f, 0.176392f, 0.184692f, 0.193848f, 0.203003f, 0.212402f, 0.221680f, 0.231689f, 0.242065f,
+ 0.251953f, 0.262207f, 0.273193f, 0.283936f, 0.295410f, 0.306152f, 0.318359f, 0.329590f, 0.342285f, 0.354248f, 0.366455f, 0.379150f,
+ 0.391846f, 0.405273f, 0.418701f, 0.432617f, 0.446289f, 0.460205f, 0.712891f, 0.723633f, 0.722168f, 0.718750f, 0.715332f, 0.712402f,
+ 0.001963f, 0.005642f, 0.009071f, 0.012756f, 0.016006f, 0.020020f, 0.023422f, 0.027679f, 0.030762f, 0.034943f, 0.038605f, 0.042969f,
+ 0.047028f, 0.051178f, 0.055542f, 0.060120f, 0.064575f, 0.069153f, 0.074280f, 0.079041f, 0.084595f, 0.089905f, 0.095276f, 0.101440f,
+ 0.107300f, 0.113586f, 0.119751f, 0.127075f, 0.134033f, 0.141357f, 0.148438f, 0.155884f, 0.164062f, 0.172729f, 0.180542f, 0.190063f,
+ 0.198364f, 0.207764f, 0.217163f, 0.226807f, 0.236938f, 0.247070f, 0.257324f, 0.268066f, 0.278320f, 0.289795f, 0.301025f, 0.312744f,
+ 0.324707f, 0.336182f, 0.347900f, 0.360840f, 0.372803f, 0.386230f, 0.399902f, 0.413574f, 0.427246f, 0.441162f, 0.702148f, 0.714355f,
+ 0.713867f, 0.711426f, 0.707520f, 0.704590f, 0.001995f, 0.005245f, 0.008553f, 0.011543f, 0.015015f, 0.018326f, 0.021881f, 0.025131f,
+ 0.028641f, 0.032349f, 0.035675f, 0.039520f, 0.043549f, 0.047089f, 0.051086f, 0.054962f, 0.059265f, 0.063782f, 0.068054f, 0.072571f,
+ 0.077759f, 0.082520f, 0.088013f, 0.093323f, 0.098755f, 0.104858f, 0.111145f, 0.117371f, 0.123840f, 0.130615f, 0.137207f, 0.144897f,
+ 0.152344f, 0.160278f, 0.167969f, 0.176514f, 0.185425f, 0.193848f, 0.202881f, 0.212524f, 0.221924f, 0.231323f, 0.241821f, 0.251953f,
+ 0.262451f, 0.272949f, 0.284424f, 0.295166f, 0.306396f, 0.319092f, 0.329590f, 0.343018f, 0.355225f, 0.368652f, 0.381348f, 0.393799f,
+ 0.408447f, 0.422852f, 0.691406f, 0.706055f, 0.706055f, 0.703125f, 0.700684f, 0.697754f, 0.001692f, 0.004898f, 0.007828f, 0.011070f,
+ 0.013992f, 0.017227f, 0.020187f, 0.023499f, 0.026520f, 0.029526f, 0.033081f, 0.036377f, 0.039459f, 0.043396f, 0.047028f, 0.050323f,
+ 0.054199f, 0.058350f, 0.062317f, 0.066711f, 0.071106f, 0.075928f, 0.080750f, 0.085510f, 0.090820f, 0.096497f, 0.102234f, 0.107727f,
+ 0.114075f, 0.120300f, 0.126587f, 0.133789f, 0.141113f, 0.148193f, 0.156006f, 0.163696f, 0.171753f, 0.180542f, 0.188965f, 0.198120f,
+ 0.207275f, 0.216797f, 0.226318f, 0.236206f, 0.246338f, 0.256836f, 0.267334f, 0.278809f, 0.289795f, 0.300781f, 0.313232f, 0.324707f,
+ 0.337402f, 0.349365f, 0.362305f, 0.376221f, 0.389404f, 0.403809f, 0.680176f, 0.696289f, 0.697266f, 0.695312f, 0.692871f, 0.689941f,
+ 0.001606f, 0.004543f, 0.007450f, 0.010269f, 0.012962f, 0.015900f, 0.018677f, 0.021591f, 0.024628f, 0.027618f, 0.030182f, 0.033783f,
+ 0.036194f, 0.039734f, 0.042725f, 0.046478f, 0.049652f, 0.053253f, 0.057251f, 0.060883f, 0.065186f, 0.069336f, 0.073730f, 0.078247f,
+ 0.083252f, 0.088501f, 0.093628f, 0.099182f, 0.104553f, 0.110718f, 0.116577f, 0.123108f, 0.129883f, 0.136719f, 0.143921f, 0.151367f,
+ 0.159302f, 0.167114f, 0.175415f, 0.183960f, 0.192871f, 0.202148f, 0.210938f, 0.221436f, 0.230713f, 0.240723f, 0.250977f, 0.261963f,
+ 0.272461f, 0.283691f, 0.295166f, 0.306885f, 0.319092f, 0.331055f, 0.343750f, 0.356689f, 0.370361f, 0.383545f, 0.669434f, 0.687500f,
+ 0.688965f, 0.687500f, 0.685547f, 0.682617f, 0.001701f, 0.004345f, 0.006802f, 0.009514f, 0.012283f, 0.014793f, 0.017288f, 0.019958f,
+ 0.022614f, 0.025177f, 0.027695f, 0.030487f, 0.033081f, 0.035858f, 0.039185f, 0.042236f, 0.045319f, 0.048523f, 0.051941f, 0.055847f,
+ 0.059326f, 0.063171f, 0.067139f, 0.071594f, 0.075928f, 0.080566f, 0.085571f, 0.090454f, 0.095520f, 0.101196f, 0.106567f, 0.112427f,
+ 0.119019f, 0.125610f, 0.132324f, 0.139282f, 0.146973f, 0.154419f, 0.161987f, 0.170532f, 0.178833f, 0.187134f, 0.196777f, 0.206177f,
+ 0.214966f, 0.225220f, 0.235352f, 0.246094f, 0.255615f, 0.266846f, 0.278320f, 0.290039f, 0.301270f, 0.313477f, 0.325195f, 0.338867f,
+ 0.352539f, 0.365234f, 0.657715f, 0.678711f, 0.679688f, 0.679199f, 0.677734f, 0.675293f, 0.001310f, 0.003979f, 0.006393f, 0.008522f,
+ 0.011223f, 0.013557f, 0.015976f, 0.018433f, 0.020737f, 0.022842f, 0.025421f, 0.027649f, 0.030289f, 0.032806f, 0.035645f, 0.038025f,
+ 0.041199f, 0.044220f, 0.047058f, 0.050720f, 0.053589f, 0.057281f, 0.061157f, 0.064941f, 0.068787f, 0.072998f, 0.077698f, 0.082153f,
+ 0.086975f, 0.092102f, 0.097229f, 0.103027f, 0.108826f, 0.114746f, 0.121094f, 0.127930f, 0.134521f, 0.141846f, 0.149292f, 0.157227f,
+ 0.164673f, 0.173218f, 0.182007f, 0.190552f, 0.199951f, 0.209717f, 0.219360f, 0.229004f, 0.239502f, 0.250244f, 0.260986f, 0.272461f,
+ 0.282959f, 0.295166f, 0.307373f, 0.320557f, 0.333252f, 0.346436f, 0.646973f, 0.668945f, 0.670898f, 0.671387f, 0.669922f, 0.668457f,
+ 0.001348f, 0.003523f, 0.005863f, 0.008133f, 0.010338f, 0.012520f, 0.014511f, 0.016464f, 0.018768f, 0.020920f, 0.022888f, 0.025665f,
+ 0.027588f, 0.029861f, 0.032135f, 0.034485f, 0.037140f, 0.040039f, 0.042725f, 0.045532f, 0.048859f, 0.051971f, 0.055237f, 0.058594f,
+ 0.062408f, 0.066101f, 0.070251f, 0.074280f, 0.078735f, 0.083435f, 0.088318f, 0.093567f, 0.098633f, 0.104431f, 0.110291f, 0.116455f,
+ 0.122986f, 0.129517f, 0.136963f, 0.143921f, 0.152222f, 0.159546f, 0.167358f, 0.176514f, 0.185181f, 0.194214f, 0.203857f, 0.213623f,
+ 0.223389f, 0.233521f, 0.244385f, 0.255127f, 0.266602f, 0.277832f, 0.289307f, 0.301758f, 0.314697f, 0.328613f, 0.635254f, 0.659668f,
+ 0.663086f, 0.663086f, 0.662109f, 0.660156f, 0.001084f, 0.003263f, 0.005554f, 0.007416f, 0.009445f, 0.011185f, 0.013161f, 0.015366f,
+ 0.017136f, 0.019058f, 0.020935f, 0.022781f, 0.024857f, 0.026886f, 0.029160f, 0.031097f, 0.033569f, 0.035858f, 0.038361f, 0.040924f,
+ 0.043427f, 0.046478f, 0.049500f, 0.052948f, 0.056122f, 0.059418f, 0.063293f, 0.067139f, 0.070923f, 0.075073f, 0.079712f, 0.084229f,
+ 0.089233f, 0.094604f, 0.100037f, 0.105774f, 0.111694f, 0.117798f, 0.124634f, 0.131226f, 0.139038f, 0.146484f, 0.154175f, 0.162231f,
+ 0.170654f, 0.179199f, 0.188599f, 0.197754f, 0.207153f, 0.217407f, 0.227295f, 0.238159f, 0.248657f, 0.260986f, 0.271973f, 0.284912f,
+ 0.296631f, 0.308838f, 0.623535f, 0.650391f, 0.653809f, 0.654297f, 0.653809f, 0.652832f, 0.001070f, 0.003069f, 0.005108f, 0.006855f,
+ 0.008522f, 0.010384f, 0.011993f, 0.013847f, 0.015549f, 0.016968f, 0.018677f, 0.020660f, 0.022079f, 0.024048f, 0.026077f, 0.027954f,
+ 0.030014f, 0.032135f, 0.034210f, 0.036560f, 0.038971f, 0.041840f, 0.044434f, 0.047089f, 0.049896f, 0.053284f, 0.056763f, 0.060120f,
+ 0.063477f, 0.067505f, 0.071533f, 0.075928f, 0.080261f, 0.085205f, 0.089905f, 0.095520f, 0.100830f, 0.106567f, 0.113159f, 0.119385f,
+ 0.126221f, 0.133301f, 0.140259f, 0.148560f, 0.156494f, 0.165039f, 0.173462f, 0.182861f, 0.192017f, 0.201172f, 0.211548f, 0.221802f,
+ 0.232666f, 0.243286f, 0.254639f, 0.265869f, 0.278809f, 0.291260f, 0.611816f, 0.640625f, 0.645508f, 0.645996f, 0.645508f, 0.645020f,
+ 0.001057f, 0.002815f, 0.004646f, 0.006187f, 0.007935f, 0.009583f, 0.011139f, 0.012428f, 0.013878f, 0.015404f, 0.016830f, 0.018433f,
+ 0.019836f, 0.021637f, 0.023300f, 0.024857f, 0.026855f, 0.028519f, 0.030533f, 0.032593f, 0.034790f, 0.037140f, 0.039520f, 0.041748f,
+ 0.044525f, 0.047302f, 0.050232f, 0.053497f, 0.056580f, 0.059998f, 0.063721f, 0.067627f, 0.071777f, 0.076111f, 0.080627f, 0.085571f,
+ 0.090698f, 0.096130f, 0.101624f, 0.107849f, 0.114258f, 0.120544f, 0.127686f, 0.135132f, 0.142700f, 0.150269f, 0.158813f, 0.167725f,
+ 0.176392f, 0.185791f, 0.195312f, 0.205444f, 0.216064f, 0.226562f, 0.237793f, 0.248657f, 0.260254f, 0.272949f, 0.600098f, 0.631348f,
+ 0.636230f, 0.637207f, 0.637695f, 0.636719f, 0.001022f, 0.002628f, 0.004486f, 0.005684f, 0.007179f, 0.008636f, 0.009911f, 0.011307f,
+ 0.012428f, 0.013771f, 0.015152f, 0.016342f, 0.017822f, 0.018997f, 0.020584f, 0.022263f, 0.023651f, 0.025482f, 0.027191f, 0.028793f,
+ 0.030960f, 0.032715f, 0.034912f, 0.036987f, 0.039368f, 0.041840f, 0.044495f, 0.047180f, 0.050110f, 0.053314f, 0.056580f, 0.060059f,
+ 0.063660f, 0.067383f, 0.071777f, 0.075928f, 0.081055f, 0.085938f, 0.091187f, 0.096619f, 0.102356f, 0.108826f, 0.115051f, 0.121948f,
+ 0.129150f, 0.136475f, 0.144653f, 0.152832f, 0.161621f, 0.170288f, 0.179932f, 0.189209f, 0.198730f, 0.209595f, 0.220459f, 0.231201f,
+ 0.242798f, 0.255615f, 0.588867f, 0.621094f, 0.626953f, 0.629883f, 0.629395f, 0.629883f, 0.001016f, 0.002304f, 0.003975f, 0.005024f,
+ 0.006584f, 0.007812f, 0.008926f, 0.009987f, 0.011024f, 0.012199f, 0.013321f, 0.014595f, 0.015617f, 0.016830f, 0.018326f, 0.019577f,
+ 0.020798f, 0.022293f, 0.023758f, 0.025253f, 0.027145f, 0.028656f, 0.030640f, 0.032501f, 0.034546f, 0.036682f, 0.039001f, 0.041412f,
+ 0.044037f, 0.046875f, 0.049622f, 0.052917f, 0.056030f, 0.059387f, 0.063354f, 0.067383f, 0.071655f, 0.075928f, 0.080750f, 0.085876f,
+ 0.091248f, 0.097168f, 0.102905f, 0.109497f, 0.116272f, 0.123413f, 0.130859f, 0.138550f, 0.147217f, 0.155518f, 0.164551f, 0.173828f,
+ 0.183350f, 0.193481f, 0.204102f, 0.214600f, 0.225342f, 0.237915f, 0.575684f, 0.611816f, 0.617188f, 0.621094f, 0.621582f, 0.620605f,
+ 0.000768f, 0.002398f, 0.003801f, 0.004875f, 0.005848f, 0.006889f, 0.008072f, 0.008820f, 0.009758f, 0.010910f, 0.011810f, 0.013023f,
+ 0.013878f, 0.014786f, 0.016083f, 0.017166f, 0.018402f, 0.019577f, 0.020691f, 0.022125f, 0.023743f, 0.025009f, 0.026779f, 0.028336f,
+ 0.030075f, 0.031921f, 0.033997f, 0.036255f, 0.038452f, 0.040833f, 0.043488f, 0.045959f, 0.049011f, 0.052216f, 0.055634f, 0.059052f,
+ 0.062744f, 0.066956f, 0.071289f, 0.075745f, 0.080566f, 0.086060f, 0.091614f, 0.097351f, 0.103821f, 0.110291f, 0.117432f, 0.124939f,
+ 0.132568f, 0.140869f, 0.149414f, 0.158325f, 0.168213f, 0.177368f, 0.187744f, 0.197876f, 0.208984f, 0.219849f, 0.563965f, 0.602051f,
+ 0.608887f, 0.610840f, 0.613770f, 0.612305f, 0.000764f, 0.002028f, 0.003302f, 0.004276f, 0.005325f, 0.006035f, 0.007034f, 0.007843f,
+ 0.008904f, 0.009628f, 0.010323f, 0.011192f, 0.012039f, 0.013092f, 0.013924f, 0.014854f, 0.015793f, 0.016953f, 0.018036f, 0.019211f,
+ 0.020355f, 0.021667f, 0.023010f, 0.024582f, 0.026016f, 0.027771f, 0.029434f, 0.031235f, 0.033264f, 0.035217f, 0.037628f, 0.039886f,
+ 0.042084f, 0.044952f, 0.048126f, 0.051392f, 0.054779f, 0.058197f, 0.062164f, 0.066223f, 0.070740f, 0.075439f, 0.080566f, 0.086182f,
+ 0.091919f, 0.098145f, 0.104431f, 0.111633f, 0.119080f, 0.126587f, 0.134888f, 0.143311f, 0.152710f, 0.162109f, 0.171631f, 0.182129f,
+ 0.192139f, 0.203491f, 0.552246f, 0.591309f, 0.599609f, 0.602539f, 0.604004f, 0.604980f, 0.000782f, 0.001970f, 0.003082f, 0.003859f,
+ 0.004635f, 0.005611f, 0.006123f, 0.006767f, 0.007595f, 0.008270f, 0.009140f, 0.009674f, 0.010490f, 0.011040f, 0.011902f, 0.012749f,
+ 0.013573f, 0.014526f, 0.015656f, 0.016541f, 0.017548f, 0.018631f, 0.019730f, 0.021103f, 0.022446f, 0.023758f, 0.025162f, 0.026611f,
+ 0.028458f, 0.030441f, 0.032074f, 0.034302f, 0.036316f, 0.038727f, 0.041138f, 0.044098f, 0.046997f, 0.050232f, 0.053711f, 0.057281f,
+ 0.061340f, 0.065491f, 0.070435f, 0.075256f, 0.080688f, 0.086426f, 0.092346f, 0.098694f, 0.105896f, 0.113098f, 0.120911f, 0.129028f,
+ 0.137695f, 0.146606f, 0.155884f, 0.165894f, 0.175903f, 0.186768f, 0.540527f, 0.582520f, 0.590332f, 0.593750f, 0.594727f, 0.596191f,
+ 0.000711f, 0.001649f, 0.002529f, 0.003332f, 0.004036f, 0.004799f, 0.005444f, 0.006050f, 0.006638f, 0.007160f, 0.007771f, 0.008331f,
+ 0.008980f, 0.009644f, 0.010307f, 0.010887f, 0.011787f, 0.012306f, 0.013176f, 0.014099f, 0.014915f, 0.015839f, 0.016708f, 0.017822f,
+ 0.019073f, 0.020233f, 0.021423f, 0.022690f, 0.024033f, 0.025589f, 0.027344f, 0.028976f, 0.030930f, 0.032990f, 0.035156f, 0.037445f,
+ 0.040131f, 0.042847f, 0.045776f, 0.049042f, 0.052551f, 0.056519f, 0.060486f, 0.064941f, 0.069458f, 0.074951f, 0.080444f, 0.086487f,
+ 0.092957f, 0.099915f, 0.107361f, 0.114929f, 0.123535f, 0.131714f, 0.140747f, 0.150513f, 0.160767f, 0.171265f, 0.527832f, 0.572754f,
+ 0.581543f, 0.583496f, 0.586426f, 0.587402f, 0.000504f, 0.001575f, 0.002235f, 0.003147f, 0.003641f, 0.004150f, 0.004570f, 0.005173f,
+ 0.005863f, 0.006016f, 0.006462f, 0.007111f, 0.007660f, 0.008156f, 0.008736f, 0.009354f, 0.010094f, 0.010475f, 0.011253f, 0.011879f,
+ 0.012657f, 0.013603f, 0.014267f, 0.015099f, 0.016144f, 0.017014f, 0.017990f, 0.019104f, 0.020416f, 0.021652f, 0.022919f, 0.024353f,
+ 0.025986f, 0.027710f, 0.029602f, 0.031494f, 0.033722f, 0.036102f, 0.038635f, 0.041412f, 0.044525f, 0.047729f, 0.051636f, 0.055511f,
+ 0.059540f, 0.064331f, 0.069580f, 0.075073f, 0.080750f, 0.087341f, 0.094116f, 0.101379f, 0.109558f, 0.117676f, 0.126221f, 0.135376f,
+ 0.145874f, 0.155518f, 0.516113f, 0.562012f, 0.571777f, 0.576172f, 0.578125f, 0.579102f, 0.000445f, 0.001304f, 0.002201f, 0.002535f,
+ 0.003126f, 0.003664f, 0.004047f, 0.004463f, 0.004887f, 0.005234f, 0.005711f, 0.005997f, 0.006500f, 0.006901f, 0.007389f, 0.007904f,
+ 0.008293f, 0.008919f, 0.009499f, 0.009941f, 0.010635f, 0.011269f, 0.011948f, 0.012589f, 0.013435f, 0.014252f, 0.015091f, 0.016052f,
+ 0.017059f, 0.017960f, 0.019241f, 0.020264f, 0.021667f, 0.022995f, 0.024628f, 0.026230f, 0.027985f, 0.029984f, 0.032288f, 0.034515f,
+ 0.037140f, 0.040009f, 0.043152f, 0.046722f, 0.050354f, 0.054504f, 0.059143f, 0.064026f, 0.069458f, 0.075256f, 0.081726f, 0.088562f,
+ 0.095825f, 0.103516f, 0.112000f, 0.120850f, 0.130005f, 0.140381f, 0.502441f, 0.551758f, 0.562012f, 0.566406f, 0.568848f, 0.571289f,
+ 0.000396f, 0.001226f, 0.001812f, 0.002357f, 0.002796f, 0.003094f, 0.003328f, 0.003763f, 0.003979f, 0.004364f, 0.004642f, 0.005051f,
+ 0.005489f, 0.005745f, 0.006126f, 0.006611f, 0.007004f, 0.007473f, 0.007771f, 0.008293f, 0.008919f, 0.009392f, 0.009941f, 0.010483f,
+ 0.011169f, 0.011765f, 0.012436f, 0.013344f, 0.014030f, 0.014908f, 0.015778f, 0.016769f, 0.017838f, 0.018997f, 0.020279f, 0.021622f,
+ 0.023056f, 0.024704f, 0.026474f, 0.028580f, 0.030579f, 0.033051f, 0.035706f, 0.038605f, 0.041840f, 0.045380f, 0.049500f, 0.053986f,
+ 0.058685f, 0.063843f, 0.069885f, 0.076050f, 0.083191f, 0.090576f, 0.098511f, 0.107056f, 0.115479f, 0.125122f, 0.491211f, 0.541504f,
+ 0.552734f, 0.557617f, 0.560547f, 0.562012f, 0.000559f, 0.001152f, 0.001668f, 0.001955f, 0.002234f, 0.002550f, 0.002821f, 0.003057f,
+ 0.003296f, 0.003635f, 0.003948f, 0.004189f, 0.004448f, 0.004761f, 0.005077f, 0.005417f, 0.005699f, 0.006142f, 0.006458f, 0.006844f,
+ 0.007271f, 0.007717f, 0.008156f, 0.008675f, 0.009132f, 0.009590f, 0.010277f, 0.010864f, 0.011482f, 0.012131f, 0.012901f, 0.013741f,
+ 0.014595f, 0.015549f, 0.016525f, 0.017563f, 0.018799f, 0.020111f, 0.021484f, 0.023087f, 0.024765f, 0.026840f, 0.028992f, 0.031403f,
+ 0.034119f, 0.037323f, 0.040680f, 0.044464f, 0.048584f, 0.053345f, 0.058838f, 0.064514f, 0.071045f, 0.078247f, 0.085571f, 0.093567f,
+ 0.101685f, 0.111023f, 0.477539f, 0.531738f, 0.542969f, 0.548340f, 0.552246f, 0.553711f, 0.000459f, 0.000939f, 0.001184f, 0.001600f,
+ 0.001761f, 0.002144f, 0.002258f, 0.002546f, 0.002708f, 0.002922f, 0.003157f, 0.003414f, 0.003588f, 0.003918f, 0.004154f, 0.004387f,
+ 0.004662f, 0.004993f, 0.005249f, 0.005566f, 0.005867f, 0.006252f, 0.006573f, 0.007061f, 0.007408f, 0.007858f, 0.008270f, 0.008713f,
+ 0.009361f, 0.009911f, 0.010513f, 0.011047f, 0.011841f, 0.012566f, 0.013252f, 0.014175f, 0.015182f, 0.016220f, 0.017258f, 0.018524f,
+ 0.019882f, 0.021454f, 0.023132f, 0.025146f, 0.027405f, 0.029877f, 0.032745f, 0.035919f, 0.039642f, 0.043823f, 0.048492f, 0.053619f,
+ 0.059235f, 0.065735f, 0.072693f, 0.080383f, 0.088867f, 0.097412f, 0.466309f, 0.520508f, 0.533691f, 0.539062f, 0.542480f, 0.543945f,
+ 0.000369f, 0.000915f, 0.001124f, 0.001297f, 0.001534f, 0.001741f, 0.001833f, 0.002111f, 0.002272f, 0.002369f, 0.002516f, 0.002766f,
+ 0.002920f, 0.003162f, 0.003317f, 0.003551f, 0.003723f, 0.003941f, 0.004211f, 0.004425f, 0.004757f, 0.004993f, 0.005306f, 0.005581f,
+ 0.005859f, 0.006203f, 0.006592f, 0.007015f, 0.007450f, 0.007828f, 0.008377f, 0.008797f, 0.009361f, 0.009895f, 0.010582f, 0.011322f,
+ 0.012016f, 0.012772f, 0.013687f, 0.014748f, 0.015778f, 0.016907f, 0.018326f, 0.019821f, 0.021622f, 0.023483f, 0.025742f, 0.028473f,
+ 0.031525f, 0.034943f, 0.038910f, 0.043457f, 0.048645f, 0.054749f, 0.061279f, 0.068420f, 0.076111f, 0.084778f, 0.453613f, 0.510742f,
+ 0.523926f, 0.529785f, 0.533203f, 0.536133f, 0.000186f, 0.000582f, 0.000925f, 0.001026f, 0.001228f, 0.001351f, 0.001470f, 0.001606f,
+ 0.001765f, 0.001908f, 0.001999f, 0.002104f, 0.002281f, 0.002476f, 0.002659f, 0.002766f, 0.002911f, 0.003040f, 0.003344f, 0.003475f,
+ 0.003683f, 0.003922f, 0.004185f, 0.004417f, 0.004673f, 0.004890f, 0.005123f, 0.005440f, 0.005817f, 0.006126f, 0.006481f, 0.006859f,
+ 0.007275f, 0.007740f, 0.008202f, 0.008728f, 0.009315f, 0.009972f, 0.010597f, 0.011391f, 0.012268f, 0.013252f, 0.014221f, 0.015388f,
+ 0.016724f, 0.018265f, 0.020004f, 0.022049f, 0.024445f, 0.027206f, 0.030762f, 0.034424f, 0.038971f, 0.044220f, 0.050262f, 0.056976f,
+ 0.064575f, 0.072083f, 0.441650f, 0.500488f, 0.514160f, 0.520020f, 0.524414f, 0.526855f, 0.000194f, 0.000467f, 0.000775f, 0.000911f,
+ 0.000994f, 0.001081f, 0.001221f, 0.001204f, 0.001368f, 0.001479f, 0.001582f, 0.001707f, 0.001801f, 0.001921f, 0.001993f, 0.002146f,
+ 0.002245f, 0.002398f, 0.002531f, 0.002674f, 0.002871f, 0.003033f, 0.003172f, 0.003374f, 0.003519f, 0.003742f, 0.003963f, 0.004158f,
+ 0.004448f, 0.004650f, 0.005032f, 0.005230f, 0.005550f, 0.005932f, 0.006241f, 0.006634f, 0.007088f, 0.007572f, 0.008110f, 0.008636f,
+ 0.009323f, 0.010071f, 0.010834f, 0.011757f, 0.012779f, 0.013863f, 0.015190f, 0.016769f, 0.018555f, 0.020706f, 0.023331f, 0.026352f,
+ 0.030182f, 0.034760f, 0.040039f, 0.046356f, 0.053406f, 0.060638f, 0.427979f, 0.489502f, 0.504883f, 0.511719f, 0.515137f, 0.518066f,
+ 0.000339f, 0.000388f, 0.000559f, 0.000617f, 0.000667f, 0.000795f, 0.000853f, 0.000938f, 0.000972f, 0.001079f, 0.001217f, 0.001274f,
+ 0.001369f, 0.001480f, 0.001536f, 0.001581f, 0.001711f, 0.001804f, 0.001900f, 0.002047f, 0.002129f, 0.002245f, 0.002394f, 0.002493f,
+ 0.002645f, 0.002773f, 0.002974f, 0.003124f, 0.003307f, 0.003559f, 0.003757f, 0.003893f, 0.004169f, 0.004353f, 0.004684f, 0.004963f,
+ 0.005272f, 0.005615f, 0.005981f, 0.006420f, 0.006878f, 0.007378f, 0.008080f, 0.008682f, 0.009438f, 0.010239f, 0.011299f, 0.012459f,
+ 0.013809f, 0.015305f, 0.017212f, 0.019501f, 0.022583f, 0.026245f, 0.030838f, 0.036255f, 0.042938f, 0.049988f, 0.416504f, 0.479492f,
+ 0.495361f, 0.501465f, 0.505859f, 0.508789f, 0.000148f, 0.000349f, 0.000414f, 0.000480f, 0.000554f, 0.000575f, 0.000675f, 0.000641f,
+ 0.000743f, 0.000809f, 0.000882f, 0.000919f, 0.000967f, 0.001019f, 0.001122f, 0.001156f, 0.001264f, 0.001322f, 0.001392f, 0.001431f,
+ 0.001529f, 0.001625f, 0.001735f, 0.001802f, 0.001912f, 0.002007f, 0.002131f, 0.002237f, 0.002338f, 0.002525f, 0.002638f, 0.002850f,
+ 0.002962f, 0.003130f, 0.003347f, 0.003536f, 0.003784f, 0.004063f, 0.004364f, 0.004623f, 0.004929f, 0.005314f, 0.005714f, 0.006191f,
+ 0.006760f, 0.007385f, 0.008080f, 0.008919f, 0.009933f, 0.011078f, 0.012390f, 0.014130f, 0.016251f, 0.019012f, 0.022720f, 0.027496f,
+ 0.033234f, 0.040192f, 0.403320f, 0.468994f, 0.485352f, 0.491943f, 0.497070f, 0.500000f, 0.000093f, 0.000191f, 0.000299f, 0.000284f,
+ 0.000367f, 0.000453f, 0.000420f, 0.000467f, 0.000519f, 0.000611f, 0.000607f, 0.000626f, 0.000647f, 0.000722f, 0.000741f, 0.000815f,
+ 0.000829f, 0.000910f, 0.000967f, 0.001023f, 0.001076f, 0.001138f, 0.001197f, 0.001260f, 0.001334f, 0.001393f, 0.001490f, 0.001562f,
+ 0.001633f, 0.001772f, 0.001831f, 0.001949f, 0.002056f, 0.002167f, 0.002312f, 0.002472f, 0.002607f, 0.002781f, 0.002972f, 0.003145f,
+ 0.003387f, 0.003647f, 0.003941f, 0.004253f, 0.004604f, 0.005051f, 0.005558f, 0.006165f, 0.006836f, 0.007660f, 0.008652f, 0.009796f,
+ 0.011284f, 0.013260f, 0.015945f, 0.019608f, 0.024734f, 0.031082f, 0.390625f, 0.459229f, 0.475586f, 0.482910f, 0.488037f, 0.490723f,
+ 0.000132f, 0.000208f, 0.000217f, 0.000221f, 0.000267f, 0.000272f, 0.000277f, 0.000320f, 0.000356f, 0.000372f, 0.000372f, 0.000446f,
+ 0.000436f, 0.000487f, 0.000514f, 0.000531f, 0.000587f, 0.000601f, 0.000629f, 0.000658f, 0.000707f, 0.000736f, 0.000784f, 0.000816f,
+ 0.000880f, 0.000909f, 0.000978f, 0.001035f, 0.001084f, 0.001135f, 0.001200f, 0.001278f, 0.001357f, 0.001429f, 0.001516f, 0.001588f,
+ 0.001724f, 0.001802f, 0.001949f, 0.002085f, 0.002230f, 0.002373f, 0.002554f, 0.002743f, 0.003000f, 0.003300f, 0.003611f, 0.003963f,
+ 0.004425f, 0.004967f, 0.005630f, 0.006424f, 0.007462f, 0.008812f, 0.010551f, 0.013184f, 0.017258f, 0.022980f, 0.377686f, 0.448242f,
+ 0.465820f, 0.474121f, 0.478760f, 0.481934f, 0.000041f, 0.000149f, 0.000126f, 0.000128f, 0.000158f, 0.000196f, 0.000174f, 0.000206f,
+ 0.000216f, 0.000223f, 0.000231f, 0.000244f, 0.000276f, 0.000291f, 0.000312f, 0.000326f, 0.000338f, 0.000374f, 0.000387f, 0.000423f,
+ 0.000430f, 0.000447f, 0.000471f, 0.000509f, 0.000538f, 0.000583f, 0.000591f, 0.000613f, 0.000659f, 0.000688f, 0.000743f, 0.000779f,
+ 0.000833f, 0.000865f, 0.000924f, 0.000966f, 0.001033f, 0.001106f, 0.001186f, 0.001245f, 0.001336f, 0.001453f, 0.001559f, 0.001685f,
+ 0.001807f, 0.001980f, 0.002207f, 0.002417f, 0.002689f, 0.003027f, 0.003418f, 0.003933f, 0.004604f, 0.005482f, 0.006641f, 0.008263f,
+ 0.011017f, 0.015778f, 0.364746f, 0.437256f, 0.456055f, 0.463623f, 0.469238f, 0.472656f, 0.000100f, 0.000089f, 0.000085f, 0.000081f,
+ 0.000101f, 0.000096f, 0.000116f, 0.000116f, 0.000119f, 0.000126f, 0.000141f, 0.000157f, 0.000149f, 0.000158f, 0.000179f, 0.000176f,
+ 0.000195f, 0.000206f, 0.000216f, 0.000222f, 0.000240f, 0.000246f, 0.000269f, 0.000279f, 0.000303f, 0.000320f, 0.000333f, 0.000345f,
+ 0.000365f, 0.000379f, 0.000409f, 0.000434f, 0.000453f, 0.000477f, 0.000511f, 0.000541f, 0.000569f, 0.000608f, 0.000656f, 0.000689f,
+ 0.000738f, 0.000795f, 0.000867f, 0.000918f, 0.001005f, 0.001087f, 0.001189f, 0.001312f, 0.001465f, 0.001656f, 0.001873f, 0.002171f,
+ 0.002546f, 0.003056f, 0.003767f, 0.004765f, 0.006390f, 0.009811f, 0.353516f, 0.426758f, 0.446045f, 0.455078f, 0.459717f, 0.464111f,
+ 0.000084f, 0.000059f, 0.000050f, 0.000049f, 0.000049f, 0.000047f, 0.000052f, 0.000058f, 0.000061f, 0.000075f, 0.000065f, 0.000066f,
+ 0.000080f, 0.000071f, 0.000076f, 0.000082f, 0.000092f, 0.000102f, 0.000100f, 0.000105f, 0.000110f, 0.000115f, 0.000121f, 0.000133f,
+ 0.000140f, 0.000146f, 0.000152f, 0.000164f, 0.000177f, 0.000185f, 0.000192f, 0.000202f, 0.000213f, 0.000224f, 0.000241f, 0.000252f,
+ 0.000268f, 0.000283f, 0.000310f, 0.000328f, 0.000348f, 0.000374f, 0.000406f, 0.000431f, 0.000470f, 0.000515f, 0.000560f, 0.000614f,
+ 0.000688f, 0.000771f, 0.000884f, 0.001019f, 0.001202f, 0.001466f, 0.001827f, 0.002369f, 0.003269f, 0.005184f, 0.341797f, 0.416016f,
+ 0.435791f, 0.445557f, 0.450928f, 0.455078f, 0.000062f, 0.000042f, 0.000035f, 0.000030f, 0.000028f, 0.000026f, 0.000024f, 0.000023f,
+ 0.000023f, 0.000023f, 0.000023f, 0.000030f, 0.000024f, 0.000024f, 0.000031f, 0.000034f, 0.000035f, 0.000037f, 0.000039f, 0.000040f,
+ 0.000043f, 0.000048f, 0.000050f, 0.000046f, 0.000051f, 0.000057f, 0.000059f, 0.000058f, 0.000063f, 0.000068f, 0.000070f, 0.000077f,
+ 0.000082f, 0.000082f, 0.000086f, 0.000093f, 0.000100f, 0.000106f, 0.000114f, 0.000120f, 0.000131f, 0.000136f, 0.000145f, 0.000161f,
+ 0.000171f, 0.000186f, 0.000204f, 0.000222f, 0.000251f, 0.000281f, 0.000318f, 0.000364f, 0.000430f, 0.000530f, 0.000672f, 0.000902f,
+ 0.001316f, 0.002153f, 0.329346f, 0.406006f, 0.426758f, 0.436035f, 0.441650f, 0.445801f, 0.000031f, 0.000020f, 0.000016f, 0.000014f,
+ 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f,
+ 0.000008f, 0.000008f, 0.000007f, 0.000007f, 0.000007f, 0.000008f, 0.000009f, 0.000010f, 0.000011f, 0.000012f, 0.000012f, 0.000014f,
+ 0.000014f, 0.000013f, 0.000015f, 0.000016f, 0.000018f, 0.000019f, 0.000019f, 0.000020f, 0.000023f, 0.000023f, 0.000025f, 0.000027f,
+ 0.000028f, 0.000031f, 0.000034f, 0.000034f, 0.000037f, 0.000041f, 0.000045f, 0.000049f, 0.000053f, 0.000059f, 0.000066f, 0.000079f,
+ 0.000093f, 0.000112f, 0.000144f, 0.000196f, 0.000307f, 0.000598f, 0.317383f, 0.394531f, 0.416504f, 0.425781f, 0.432129f, 0.436279f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000004f, 0.000007f, 0.000010f, 0.000026f, 0.305420f, 0.384277f,
+ 0.405762f, 0.416504f, 0.423340f, 0.427246f,
+ },
+ {
+ 0.009338f, 0.028412f, 0.047394f, 0.066895f, 0.086548f, 0.105774f, 0.125854f, 0.145142f, 0.165039f, 0.184570f, 0.204712f, 0.223389f,
+ 0.243164f, 0.261719f, 0.280762f, 0.299805f, 0.318848f, 0.338135f, 0.356445f, 0.374512f, 0.393066f, 0.412354f, 0.429932f, 0.447510f,
+ 0.465576f, 0.483887f, 0.501465f, 0.518555f, 0.536133f, 0.553711f, 0.570312f, 0.587402f, 0.604492f, 0.621094f, 0.637695f, 0.653809f,
+ 0.670898f, 0.687012f, 0.702637f, 0.719238f, 0.734863f, 0.750488f, 0.765137f, 0.780762f, 0.795898f, 0.811523f, 0.825684f, 0.840820f,
+ 0.855469f, 0.870605f, 0.884277f, 0.899414f, 0.913086f, 0.926758f, 0.940918f, 0.955078f, 0.967773f, 0.981934f, 0.966797f, 0.923828f,
+ 0.894531f, 0.870605f, 0.850586f, 0.832520f, 0.008652f, 0.026825f, 0.045380f, 0.063965f, 0.082703f, 0.101807f, 0.120544f, 0.139282f,
+ 0.158569f, 0.177246f, 0.196167f, 0.214722f, 0.233521f, 0.252197f, 0.270508f, 0.289062f, 0.307861f, 0.325928f, 0.343994f, 0.361328f,
+ 0.380615f, 0.397705f, 0.415771f, 0.433594f, 0.450928f, 0.469238f, 0.485596f, 0.502930f, 0.520020f, 0.537598f, 0.553223f, 0.570801f,
+ 0.586914f, 0.603516f, 0.620117f, 0.636719f, 0.652832f, 0.668945f, 0.683594f, 0.700684f, 0.716309f, 0.731934f, 0.746582f, 0.762695f,
+ 0.777344f, 0.792480f, 0.807617f, 0.821777f, 0.836914f, 0.850586f, 0.865723f, 0.880371f, 0.894043f, 0.908691f, 0.921875f, 0.937012f,
+ 0.950195f, 0.963867f, 0.958496f, 0.917969f, 0.889648f, 0.867188f, 0.847656f, 0.830566f, 0.008293f, 0.025620f, 0.042999f, 0.061035f,
+ 0.079163f, 0.097656f, 0.115112f, 0.132812f, 0.151367f, 0.170532f, 0.188599f, 0.206787f, 0.223999f, 0.242920f, 0.259766f, 0.278809f,
+ 0.296143f, 0.313232f, 0.331055f, 0.349609f, 0.367432f, 0.385010f, 0.401611f, 0.418945f, 0.435791f, 0.453369f, 0.469727f, 0.487061f,
+ 0.503906f, 0.520508f, 0.537598f, 0.553223f, 0.569824f, 0.586426f, 0.603027f, 0.619141f, 0.634277f, 0.650879f, 0.666504f, 0.682129f,
+ 0.697754f, 0.713379f, 0.729004f, 0.743164f, 0.758301f, 0.773926f, 0.789062f, 0.803711f, 0.818359f, 0.833008f, 0.847168f, 0.862305f,
+ 0.875488f, 0.890137f, 0.903809f, 0.917480f, 0.931152f, 0.945801f, 0.950195f, 0.911133f, 0.884766f, 0.862793f, 0.844238f, 0.828125f,
+ 0.008148f, 0.024506f, 0.041016f, 0.058289f, 0.075256f, 0.092712f, 0.109802f, 0.127319f, 0.145020f, 0.162964f, 0.180298f, 0.198120f,
+ 0.215454f, 0.232300f, 0.250244f, 0.267822f, 0.285400f, 0.302734f, 0.318848f, 0.335693f, 0.354004f, 0.371582f, 0.388672f, 0.405029f,
+ 0.421143f, 0.438965f, 0.455078f, 0.472168f, 0.487549f, 0.503906f, 0.521484f, 0.537598f, 0.551758f, 0.568359f, 0.584961f, 0.601562f,
+ 0.616211f, 0.633301f, 0.648926f, 0.664062f, 0.679199f, 0.694824f, 0.709473f, 0.725098f, 0.740234f, 0.755371f, 0.770020f, 0.785156f,
+ 0.799805f, 0.813965f, 0.828125f, 0.842773f, 0.856934f, 0.871582f, 0.884766f, 0.898926f, 0.912598f, 0.926270f, 0.941895f, 0.905273f,
+ 0.879883f, 0.858887f, 0.840332f, 0.824707f, 0.007523f, 0.023010f, 0.039246f, 0.055542f, 0.072021f, 0.088257f, 0.105347f, 0.122070f,
+ 0.138306f, 0.155273f, 0.172852f, 0.189575f, 0.206421f, 0.223145f, 0.240112f, 0.256592f, 0.274170f, 0.291260f, 0.307617f, 0.323730f,
+ 0.340576f, 0.358154f, 0.374023f, 0.390137f, 0.406738f, 0.422852f, 0.440430f, 0.456543f, 0.472656f, 0.489014f, 0.504395f, 0.520996f,
+ 0.537109f, 0.552734f, 0.568848f, 0.584473f, 0.599121f, 0.615234f, 0.630859f, 0.645020f, 0.660645f, 0.677246f, 0.690918f, 0.706055f,
+ 0.721680f, 0.736328f, 0.750977f, 0.766113f, 0.780273f, 0.794922f, 0.809570f, 0.823730f, 0.837891f, 0.852539f, 0.866211f, 0.880371f,
+ 0.894531f, 0.908691f, 0.933105f, 0.898438f, 0.874023f, 0.853516f, 0.836426f, 0.821289f, 0.007339f, 0.021912f, 0.037170f, 0.052948f,
+ 0.068665f, 0.084412f, 0.100281f, 0.116333f, 0.133057f, 0.149048f, 0.164795f, 0.181274f, 0.198242f, 0.214233f, 0.230835f, 0.247314f,
+ 0.262939f, 0.279053f, 0.295898f, 0.312500f, 0.328613f, 0.344971f, 0.360107f, 0.376953f, 0.392578f, 0.408691f, 0.425293f, 0.441406f,
+ 0.456787f, 0.472656f, 0.488525f, 0.504883f, 0.520020f, 0.535156f, 0.550781f, 0.567383f, 0.582520f, 0.597656f, 0.612793f, 0.628418f,
+ 0.642578f, 0.657715f, 0.673340f, 0.688477f, 0.702637f, 0.718750f, 0.731445f, 0.748047f, 0.762207f, 0.775879f, 0.791016f, 0.804199f,
+ 0.818848f, 0.833008f, 0.847656f, 0.861328f, 0.875000f, 0.890625f, 0.924316f, 0.891602f, 0.868164f, 0.849121f, 0.832520f, 0.817871f,
+ 0.006817f, 0.021133f, 0.035675f, 0.050018f, 0.065186f, 0.080505f, 0.096069f, 0.111389f, 0.126831f, 0.142456f, 0.158203f, 0.174194f,
+ 0.189819f, 0.205444f, 0.220703f, 0.237183f, 0.253174f, 0.268555f, 0.284668f, 0.300049f, 0.316406f, 0.332275f, 0.347656f, 0.363281f,
+ 0.379395f, 0.394775f, 0.409668f, 0.426270f, 0.442139f, 0.457275f, 0.472656f, 0.488037f, 0.503906f, 0.518555f, 0.534668f, 0.548828f,
+ 0.564941f, 0.579590f, 0.595215f, 0.610352f, 0.625000f, 0.640137f, 0.654785f, 0.669434f, 0.685059f, 0.699707f, 0.713379f, 0.728027f,
+ 0.742676f, 0.758301f, 0.770996f, 0.786621f, 0.799316f, 0.813965f, 0.828613f, 0.842285f, 0.856445f, 0.871094f, 0.915527f, 0.884766f,
+ 0.862305f, 0.843750f, 0.827637f, 0.813965f, 0.006611f, 0.020111f, 0.033752f, 0.047974f, 0.062378f, 0.076843f, 0.091431f, 0.106262f,
+ 0.120911f, 0.136230f, 0.151123f, 0.166382f, 0.181396f, 0.196899f, 0.211670f, 0.227295f, 0.242554f, 0.257812f, 0.272705f, 0.288086f,
+ 0.304199f, 0.318848f, 0.334473f, 0.349609f, 0.365967f, 0.379883f, 0.395996f, 0.410889f, 0.426270f, 0.441895f, 0.457764f, 0.472412f,
+ 0.487061f, 0.502930f, 0.517090f, 0.532227f, 0.547363f, 0.563477f, 0.577637f, 0.592285f, 0.606934f, 0.621582f, 0.636230f, 0.651367f,
+ 0.665039f, 0.679688f, 0.694336f, 0.709473f, 0.724121f, 0.738770f, 0.752930f, 0.767578f, 0.780762f, 0.795410f, 0.809082f, 0.823242f,
+ 0.837891f, 0.852539f, 0.906250f, 0.877441f, 0.855957f, 0.838379f, 0.823242f, 0.809570f, 0.006153f, 0.019150f, 0.031952f, 0.045624f,
+ 0.059326f, 0.073303f, 0.087158f, 0.101562f, 0.115540f, 0.129395f, 0.144653f, 0.159180f, 0.173584f, 0.187866f, 0.203613f, 0.217651f,
+ 0.232300f, 0.247559f, 0.262207f, 0.277344f, 0.292969f, 0.307617f, 0.322021f, 0.336914f, 0.352051f, 0.367188f, 0.381592f, 0.396729f,
+ 0.411377f, 0.427002f, 0.440918f, 0.456787f, 0.471436f, 0.486572f, 0.500977f, 0.514648f, 0.530273f, 0.545410f, 0.560059f, 0.574219f,
+ 0.589355f, 0.604004f, 0.618164f, 0.632324f, 0.647461f, 0.661133f, 0.676270f, 0.691406f, 0.705078f, 0.719727f, 0.733887f, 0.748047f,
+ 0.763184f, 0.777344f, 0.791016f, 0.805176f, 0.819336f, 0.833496f, 0.896973f, 0.870117f, 0.849609f, 0.833008f, 0.818359f, 0.805176f,
+ 0.005947f, 0.018311f, 0.030731f, 0.043243f, 0.056732f, 0.069580f, 0.083435f, 0.096558f, 0.110474f, 0.123962f, 0.137695f, 0.152100f,
+ 0.166016f, 0.180054f, 0.194092f, 0.208862f, 0.222656f, 0.236816f, 0.251465f, 0.266113f, 0.281250f, 0.294922f, 0.309814f, 0.324219f,
+ 0.338623f, 0.352783f, 0.368164f, 0.382568f, 0.397461f, 0.411377f, 0.426025f, 0.441162f, 0.455078f, 0.469971f, 0.484131f, 0.499268f,
+ 0.513672f, 0.528320f, 0.542969f, 0.557129f, 0.571289f, 0.585449f, 0.599609f, 0.614258f, 0.628418f, 0.643066f, 0.657227f, 0.671875f,
+ 0.686523f, 0.700195f, 0.714355f, 0.729004f, 0.743164f, 0.756836f, 0.770996f, 0.785645f, 0.800293f, 0.814453f, 0.888184f, 0.862305f,
+ 0.843262f, 0.827148f, 0.813477f, 0.800781f, 0.005646f, 0.017136f, 0.029388f, 0.041534f, 0.053802f, 0.066162f, 0.078979f, 0.092285f,
+ 0.104980f, 0.118408f, 0.130981f, 0.144897f, 0.158203f, 0.172363f, 0.185547f, 0.199951f, 0.213501f, 0.226440f, 0.240356f, 0.254883f,
+ 0.269287f, 0.283691f, 0.297607f, 0.311279f, 0.325439f, 0.339600f, 0.353760f, 0.368408f, 0.382812f, 0.396973f, 0.410645f, 0.425049f,
+ 0.439697f, 0.454102f, 0.468262f, 0.482178f, 0.496094f, 0.510742f, 0.524902f, 0.539551f, 0.554199f, 0.568359f, 0.582031f, 0.596191f,
+ 0.610352f, 0.624023f, 0.639160f, 0.652832f, 0.667969f, 0.681152f, 0.696289f, 0.709961f, 0.723633f, 0.738770f, 0.752441f, 0.765625f,
+ 0.780273f, 0.794922f, 0.878418f, 0.855469f, 0.836914f, 0.821289f, 0.808105f, 0.796387f, 0.005478f, 0.016174f, 0.027740f, 0.038849f,
+ 0.051270f, 0.063293f, 0.075317f, 0.087402f, 0.099854f, 0.112793f, 0.125366f, 0.138184f, 0.151001f, 0.164307f, 0.177734f, 0.190918f,
+ 0.204102f, 0.217529f, 0.231079f, 0.244141f, 0.257324f, 0.271240f, 0.284668f, 0.299072f, 0.312744f, 0.326660f, 0.339600f, 0.354004f,
+ 0.368408f, 0.382324f, 0.395264f, 0.410156f, 0.423096f, 0.437500f, 0.452148f, 0.465332f, 0.480469f, 0.493408f, 0.507812f, 0.521484f,
+ 0.535645f, 0.549316f, 0.563477f, 0.578125f, 0.592285f, 0.605957f, 0.620605f, 0.634766f, 0.647949f, 0.662109f, 0.676758f, 0.691406f,
+ 0.705078f, 0.718750f, 0.732910f, 0.747559f, 0.762207f, 0.777344f, 0.869141f, 0.847656f, 0.830078f, 0.815430f, 0.802734f, 0.791504f,
+ 0.005005f, 0.015762f, 0.026657f, 0.037384f, 0.048218f, 0.059998f, 0.071594f, 0.083618f, 0.095215f, 0.107666f, 0.119141f, 0.131958f,
+ 0.144043f, 0.156128f, 0.169800f, 0.182129f, 0.194824f, 0.207031f, 0.219849f, 0.233032f, 0.247559f, 0.260010f, 0.272949f, 0.286133f,
+ 0.300293f, 0.313477f, 0.326172f, 0.339844f, 0.353516f, 0.367188f, 0.381592f, 0.394531f, 0.407959f, 0.422363f, 0.436279f, 0.449463f,
+ 0.462891f, 0.477539f, 0.490723f, 0.504395f, 0.518066f, 0.532227f, 0.545898f, 0.560059f, 0.574219f, 0.586914f, 0.602051f, 0.616211f,
+ 0.629395f, 0.644531f, 0.657227f, 0.671875f, 0.685547f, 0.699707f, 0.713867f, 0.728516f, 0.742676f, 0.756836f, 0.859375f, 0.840332f,
+ 0.823730f, 0.809082f, 0.797363f, 0.786621f, 0.004894f, 0.014786f, 0.025269f, 0.035614f, 0.045990f, 0.057129f, 0.068420f, 0.079224f,
+ 0.090698f, 0.102112f, 0.113708f, 0.125610f, 0.137817f, 0.149536f, 0.161377f, 0.174316f, 0.185791f, 0.198486f, 0.211670f, 0.223389f,
+ 0.236816f, 0.249512f, 0.261230f, 0.274414f, 0.287598f, 0.300537f, 0.313232f, 0.326904f, 0.340576f, 0.353027f, 0.366211f, 0.379883f,
+ 0.393066f, 0.406006f, 0.419678f, 0.433350f, 0.446289f, 0.460205f, 0.473633f, 0.487305f, 0.500977f, 0.515137f, 0.528320f, 0.542480f,
+ 0.554688f, 0.569824f, 0.583008f, 0.597656f, 0.610840f, 0.625488f, 0.638672f, 0.652832f, 0.666504f, 0.681152f, 0.694824f, 0.708984f,
+ 0.723145f, 0.737793f, 0.850098f, 0.833008f, 0.817383f, 0.802734f, 0.791992f, 0.780762f, 0.004536f, 0.014160f, 0.023972f, 0.033630f,
+ 0.043823f, 0.053955f, 0.064697f, 0.075195f, 0.086365f, 0.096802f, 0.108276f, 0.119751f, 0.130493f, 0.142212f, 0.153687f, 0.165405f,
+ 0.177246f, 0.189331f, 0.201538f, 0.213501f, 0.225464f, 0.237915f, 0.250244f, 0.262939f, 0.274902f, 0.288086f, 0.300781f, 0.312988f,
+ 0.326172f, 0.339600f, 0.352051f, 0.365479f, 0.377930f, 0.390625f, 0.403564f, 0.417480f, 0.430420f, 0.444092f, 0.457520f, 0.470215f,
+ 0.483643f, 0.497559f, 0.510742f, 0.524414f, 0.537598f, 0.551270f, 0.564941f, 0.579102f, 0.592285f, 0.605957f, 0.619629f, 0.633789f,
+ 0.647949f, 0.661621f, 0.675293f, 0.689453f, 0.704102f, 0.718262f, 0.840332f, 0.825195f, 0.809570f, 0.797363f, 0.786133f, 0.776367f,
+ 0.004433f, 0.013138f, 0.022720f, 0.032013f, 0.041199f, 0.051147f, 0.061462f, 0.071716f, 0.082336f, 0.091919f, 0.102722f, 0.113586f,
+ 0.124390f, 0.135010f, 0.145996f, 0.157837f, 0.168823f, 0.180054f, 0.192383f, 0.203491f, 0.215332f, 0.227417f, 0.239502f, 0.251221f,
+ 0.263672f, 0.275635f, 0.287842f, 0.300537f, 0.312500f, 0.324707f, 0.338135f, 0.350342f, 0.363037f, 0.375977f, 0.388672f, 0.401611f,
+ 0.413818f, 0.427246f, 0.440186f, 0.453613f, 0.466064f, 0.479736f, 0.492920f, 0.506836f, 0.519531f, 0.533203f, 0.546875f, 0.560059f,
+ 0.573242f, 0.587402f, 0.600098f, 0.614746f, 0.628418f, 0.642578f, 0.657227f, 0.670898f, 0.685059f, 0.699707f, 0.830566f, 0.816406f,
+ 0.802734f, 0.791016f, 0.780273f, 0.770996f, 0.004372f, 0.012619f, 0.021393f, 0.030350f, 0.039276f, 0.048523f, 0.058289f, 0.067505f,
+ 0.077393f, 0.087585f, 0.097290f, 0.107727f, 0.118225f, 0.128296f, 0.138550f, 0.149414f, 0.160278f, 0.171631f, 0.182739f, 0.193359f,
+ 0.205200f, 0.216187f, 0.228027f, 0.240234f, 0.251465f, 0.263428f, 0.275146f, 0.287598f, 0.298828f, 0.311523f, 0.323242f, 0.336182f,
+ 0.348633f, 0.360107f, 0.372803f, 0.385986f, 0.398682f, 0.411621f, 0.424072f, 0.436523f, 0.449951f, 0.462891f, 0.475098f, 0.488525f,
+ 0.501953f, 0.514648f, 0.527344f, 0.541992f, 0.555176f, 0.569336f, 0.582031f, 0.596191f, 0.609863f, 0.623047f, 0.637695f, 0.651855f,
+ 0.665527f, 0.679688f, 0.821289f, 0.808105f, 0.795410f, 0.784180f, 0.774902f, 0.765137f, 0.003937f, 0.012169f, 0.020477f, 0.028641f,
+ 0.037781f, 0.046448f, 0.055481f, 0.064209f, 0.073181f, 0.082458f, 0.092651f, 0.101990f, 0.111572f, 0.121948f, 0.132202f, 0.142212f,
+ 0.151978f, 0.162720f, 0.173340f, 0.184326f, 0.195312f, 0.206055f, 0.217163f, 0.228516f, 0.239990f, 0.250977f, 0.262695f, 0.274658f,
+ 0.285889f, 0.297363f, 0.308838f, 0.321045f, 0.333496f, 0.345459f, 0.357422f, 0.370117f, 0.382324f, 0.395020f, 0.407227f, 0.419922f,
+ 0.432617f, 0.444336f, 0.458008f, 0.470703f, 0.483398f, 0.497559f, 0.510254f, 0.522949f, 0.536133f, 0.550293f, 0.562988f, 0.577637f,
+ 0.590820f, 0.603516f, 0.618164f, 0.632324f, 0.645508f, 0.660645f, 0.811035f, 0.800293f, 0.788086f, 0.777832f, 0.768555f, 0.760254f,
+ 0.003868f, 0.011368f, 0.019257f, 0.027512f, 0.035431f, 0.043274f, 0.051880f, 0.060852f, 0.069214f, 0.078003f, 0.087524f, 0.096924f,
+ 0.105896f, 0.115112f, 0.124817f, 0.134766f, 0.144409f, 0.154663f, 0.164673f, 0.175415f, 0.184814f, 0.196289f, 0.206299f, 0.216797f,
+ 0.228394f, 0.239380f, 0.250244f, 0.260986f, 0.273193f, 0.284424f, 0.295410f, 0.307373f, 0.319092f, 0.331299f, 0.342285f, 0.354248f,
+ 0.366455f, 0.378662f, 0.390869f, 0.403809f, 0.415771f, 0.427734f, 0.440430f, 0.453369f, 0.466309f, 0.479736f, 0.492188f, 0.504883f,
+ 0.518066f, 0.531250f, 0.544922f, 0.558105f, 0.571777f, 0.584473f, 0.598633f, 0.612305f, 0.626465f, 0.641602f, 0.801758f, 0.792480f,
+ 0.781738f, 0.770508f, 0.761230f, 0.753906f, 0.003616f, 0.010872f, 0.018387f, 0.026077f, 0.033875f, 0.041351f, 0.049591f, 0.057434f,
+ 0.065674f, 0.073669f, 0.082153f, 0.091064f, 0.100098f, 0.109009f, 0.117981f, 0.127563f, 0.137207f, 0.146362f, 0.156494f, 0.165894f,
+ 0.176025f, 0.186157f, 0.196655f, 0.206421f, 0.216919f, 0.227539f, 0.237915f, 0.249268f, 0.260254f, 0.270752f, 0.282471f, 0.293945f,
+ 0.305176f, 0.316406f, 0.328125f, 0.338867f, 0.350342f, 0.361816f, 0.375244f, 0.387207f, 0.398926f, 0.411133f, 0.423584f, 0.436523f,
+ 0.448730f, 0.461182f, 0.474121f, 0.485840f, 0.499756f, 0.513672f, 0.525391f, 0.539062f, 0.552734f, 0.565918f, 0.580566f, 0.593750f,
+ 0.608398f, 0.621094f, 0.790527f, 0.783691f, 0.773926f, 0.764160f, 0.755859f, 0.747559f, 0.003450f, 0.010429f, 0.017487f, 0.024445f,
+ 0.031860f, 0.039581f, 0.046631f, 0.054718f, 0.061951f, 0.070251f, 0.078003f, 0.086121f, 0.094910f, 0.102905f, 0.111572f, 0.120300f,
+ 0.129761f, 0.138428f, 0.147217f, 0.156982f, 0.166992f, 0.176147f, 0.186157f, 0.196045f, 0.206299f, 0.216187f, 0.226318f, 0.236938f,
+ 0.247437f, 0.258301f, 0.268311f, 0.279785f, 0.290527f, 0.301758f, 0.312744f, 0.324219f, 0.335449f, 0.346680f, 0.359131f, 0.370605f,
+ 0.382812f, 0.394531f, 0.406982f, 0.419189f, 0.430908f, 0.443604f, 0.456055f, 0.468506f, 0.481445f, 0.494873f, 0.506836f, 0.520996f,
+ 0.534180f, 0.547363f, 0.561035f, 0.573730f, 0.588379f, 0.601074f, 0.780762f, 0.775879f, 0.766602f, 0.757324f, 0.748535f, 0.741699f,
+ 0.003281f, 0.009811f, 0.016174f, 0.023438f, 0.030060f, 0.037109f, 0.044464f, 0.051239f, 0.058441f, 0.066345f, 0.073792f, 0.081238f,
+ 0.089539f, 0.097229f, 0.105286f, 0.113647f, 0.122498f, 0.130615f, 0.139526f, 0.148438f, 0.157837f, 0.166626f, 0.176636f, 0.185547f,
+ 0.195312f, 0.204956f, 0.215088f, 0.224976f, 0.234863f, 0.245239f, 0.255859f, 0.266113f, 0.276367f, 0.287354f, 0.298096f, 0.309326f,
+ 0.320801f, 0.331787f, 0.343018f, 0.355225f, 0.366211f, 0.378418f, 0.389893f, 0.401611f, 0.413574f, 0.425781f, 0.438721f, 0.451416f,
+ 0.463135f, 0.476074f, 0.489014f, 0.501465f, 0.514648f, 0.528809f, 0.541992f, 0.554688f, 0.568848f, 0.582520f, 0.770508f, 0.767090f,
+ 0.758789f, 0.750488f, 0.743164f, 0.735352f, 0.002901f, 0.009422f, 0.015488f, 0.021729f, 0.028290f, 0.035278f, 0.041321f, 0.048523f,
+ 0.055420f, 0.062195f, 0.069336f, 0.076477f, 0.084412f, 0.091858f, 0.099609f, 0.107361f, 0.115112f, 0.123535f, 0.131592f, 0.140137f,
+ 0.148438f, 0.157715f, 0.166382f, 0.174927f, 0.184692f, 0.193970f, 0.203369f, 0.212646f, 0.222656f, 0.232910f, 0.242920f, 0.252197f,
+ 0.263184f, 0.273438f, 0.284180f, 0.294922f, 0.305664f, 0.316895f, 0.327881f, 0.338867f, 0.349854f, 0.361328f, 0.373291f, 0.385254f,
+ 0.397461f, 0.408691f, 0.420898f, 0.433350f, 0.445801f, 0.458252f, 0.470703f, 0.483154f, 0.496826f, 0.510254f, 0.522461f, 0.535645f,
+ 0.549805f, 0.562988f, 0.760742f, 0.758789f, 0.750488f, 0.743652f, 0.736328f, 0.729492f, 0.002861f, 0.008606f, 0.014488f, 0.021057f,
+ 0.026810f, 0.032898f, 0.038879f, 0.045532f, 0.051666f, 0.058319f, 0.065125f, 0.072449f, 0.079224f, 0.086426f, 0.093689f, 0.100830f,
+ 0.108276f, 0.116089f, 0.123962f, 0.131958f, 0.140625f, 0.148560f, 0.156494f, 0.164795f, 0.174194f, 0.183228f, 0.192017f, 0.201294f,
+ 0.210815f, 0.220093f, 0.229858f, 0.239746f, 0.249390f, 0.260010f, 0.270508f, 0.280518f, 0.290771f, 0.301758f, 0.312744f, 0.323486f,
+ 0.334473f, 0.345215f, 0.356934f, 0.368408f, 0.379883f, 0.391846f, 0.403564f, 0.416016f, 0.427490f, 0.439453f, 0.452881f, 0.465332f,
+ 0.478271f, 0.490234f, 0.503906f, 0.517090f, 0.529785f, 0.543945f, 0.750000f, 0.750000f, 0.743164f, 0.736328f, 0.729492f, 0.723145f,
+ 0.002977f, 0.008492f, 0.013931f, 0.019745f, 0.024948f, 0.030991f, 0.036804f, 0.042755f, 0.048889f, 0.055267f, 0.061737f, 0.067932f,
+ 0.074829f, 0.081116f, 0.087646f, 0.095215f, 0.102356f, 0.109436f, 0.116760f, 0.124023f, 0.131714f, 0.139648f, 0.147461f, 0.155762f,
+ 0.164185f, 0.172485f, 0.181152f, 0.189697f, 0.198730f, 0.208130f, 0.217285f, 0.226685f, 0.236572f, 0.245850f, 0.255859f, 0.265869f,
+ 0.276367f, 0.286377f, 0.297607f, 0.307861f, 0.318359f, 0.329102f, 0.340576f, 0.351807f, 0.363281f, 0.374023f, 0.386230f, 0.397949f,
+ 0.409668f, 0.422119f, 0.434082f, 0.446777f, 0.459229f, 0.471924f, 0.484863f, 0.497803f, 0.511230f, 0.525391f, 0.739746f, 0.741211f,
+ 0.735352f, 0.729004f, 0.722656f, 0.717285f, 0.002441f, 0.007896f, 0.013443f, 0.018402f, 0.023911f, 0.029343f, 0.034454f, 0.040375f,
+ 0.045868f, 0.051453f, 0.057800f, 0.063721f, 0.070068f, 0.075928f, 0.082520f, 0.089233f, 0.095703f, 0.102478f, 0.109314f, 0.116638f,
+ 0.123596f, 0.131348f, 0.138550f, 0.145996f, 0.153809f, 0.162109f, 0.170044f, 0.179199f, 0.187866f, 0.196045f, 0.205078f, 0.213745f,
+ 0.223389f, 0.233032f, 0.242554f, 0.252197f, 0.261963f, 0.271973f, 0.281982f, 0.292236f, 0.303223f, 0.312988f, 0.324463f, 0.335693f,
+ 0.346191f, 0.357910f, 0.368652f, 0.380371f, 0.391846f, 0.404541f, 0.415527f, 0.428467f, 0.440674f, 0.453369f, 0.466553f, 0.479248f,
+ 0.491455f, 0.505371f, 0.729492f, 0.732422f, 0.727539f, 0.721191f, 0.716309f, 0.709961f, 0.002457f, 0.007553f, 0.012489f, 0.017548f,
+ 0.022217f, 0.027405f, 0.032471f, 0.037689f, 0.043060f, 0.048553f, 0.054230f, 0.059631f, 0.065369f, 0.071533f, 0.077393f, 0.083069f,
+ 0.089417f, 0.096069f, 0.102356f, 0.108398f, 0.115417f, 0.122925f, 0.130127f, 0.137451f, 0.144531f, 0.152100f, 0.160156f, 0.168091f,
+ 0.176514f, 0.184570f, 0.192871f, 0.201660f, 0.210571f, 0.219238f, 0.229126f, 0.238281f, 0.248413f, 0.257812f, 0.267578f, 0.277588f,
+ 0.287354f, 0.298096f, 0.308594f, 0.319336f, 0.329590f, 0.340820f, 0.351318f, 0.363770f, 0.375732f, 0.386963f, 0.397949f, 0.409912f,
+ 0.422363f, 0.434326f, 0.446533f, 0.459473f, 0.473145f, 0.486084f, 0.718750f, 0.723633f, 0.719727f, 0.713867f, 0.708984f, 0.703613f,
+ 0.002436f, 0.006939f, 0.011612f, 0.016113f, 0.021072f, 0.025497f, 0.030640f, 0.035339f, 0.040222f, 0.045441f, 0.050690f, 0.055725f,
+ 0.060669f, 0.066589f, 0.072144f, 0.077881f, 0.083740f, 0.089294f, 0.095215f, 0.101501f, 0.108032f, 0.114868f, 0.121643f, 0.128052f,
+ 0.135010f, 0.142334f, 0.150024f, 0.157349f, 0.164917f, 0.173340f, 0.181274f, 0.189697f, 0.198120f, 0.206909f, 0.215698f, 0.224365f,
+ 0.234497f, 0.243652f, 0.252930f, 0.262695f, 0.272461f, 0.282471f, 0.292480f, 0.302979f, 0.313721f, 0.324463f, 0.335205f, 0.346436f,
+ 0.357666f, 0.369141f, 0.380859f, 0.391602f, 0.404541f, 0.416016f, 0.428467f, 0.440918f, 0.454102f, 0.466553f, 0.708496f, 0.715820f,
+ 0.711426f, 0.706055f, 0.701660f, 0.696777f, 0.002188f, 0.006599f, 0.011032f, 0.015068f, 0.019897f, 0.024048f, 0.028656f, 0.033264f,
+ 0.037720f, 0.042236f, 0.047028f, 0.051941f, 0.056824f, 0.062012f, 0.067444f, 0.072449f, 0.077942f, 0.083374f, 0.088867f, 0.094727f,
+ 0.100769f, 0.106750f, 0.112732f, 0.119263f, 0.126099f, 0.133179f, 0.139648f, 0.146729f, 0.154175f, 0.161987f, 0.170044f, 0.177612f,
+ 0.185791f, 0.194214f, 0.203125f, 0.211670f, 0.220581f, 0.229370f, 0.238770f, 0.248047f, 0.257812f, 0.267822f, 0.277344f, 0.287109f,
+ 0.297363f, 0.307861f, 0.318848f, 0.329590f, 0.341064f, 0.351562f, 0.363037f, 0.374512f, 0.385498f, 0.397461f, 0.409668f, 0.422363f,
+ 0.434326f, 0.447021f, 0.697266f, 0.706543f, 0.703125f, 0.698730f, 0.694336f, 0.689941f, 0.002024f, 0.006165f, 0.010399f, 0.014481f,
+ 0.018555f, 0.022797f, 0.026627f, 0.030869f, 0.035187f, 0.039459f, 0.043732f, 0.047943f, 0.052917f, 0.057434f, 0.062622f, 0.067261f,
+ 0.071838f, 0.077454f, 0.082581f, 0.087891f, 0.093628f, 0.099182f, 0.105469f, 0.111206f, 0.117126f, 0.123779f, 0.130371f, 0.137085f,
+ 0.143921f, 0.151001f, 0.158691f, 0.166016f, 0.173950f, 0.181641f, 0.190063f, 0.198120f, 0.206909f, 0.215698f, 0.224976f, 0.233398f,
+ 0.242798f, 0.252197f, 0.262207f, 0.271973f, 0.281738f, 0.291992f, 0.302734f, 0.313477f, 0.323242f, 0.334229f, 0.345459f, 0.355957f,
+ 0.368652f, 0.380615f, 0.391602f, 0.403809f, 0.415771f, 0.428467f, 0.686523f, 0.696777f, 0.695312f, 0.691895f, 0.687500f, 0.683105f,
+ 0.001931f, 0.005970f, 0.009651f, 0.013557f, 0.017136f, 0.021088f, 0.024902f, 0.028748f, 0.032623f, 0.036743f, 0.040833f, 0.044983f,
+ 0.049591f, 0.053467f, 0.057800f, 0.062500f, 0.066833f, 0.071533f, 0.076538f, 0.081238f, 0.086670f, 0.092224f, 0.097290f, 0.103088f,
+ 0.108887f, 0.114990f, 0.120972f, 0.127197f, 0.134277f, 0.140503f, 0.147705f, 0.154663f, 0.162231f, 0.169922f, 0.177612f, 0.185303f,
+ 0.193604f, 0.201904f, 0.210815f, 0.219238f, 0.228516f, 0.237427f, 0.247070f, 0.256592f, 0.265869f, 0.275879f, 0.285645f, 0.295898f,
+ 0.306396f, 0.317139f, 0.328369f, 0.338623f, 0.350342f, 0.362305f, 0.374023f, 0.385010f, 0.397461f, 0.410156f, 0.675781f, 0.687988f,
+ 0.687012f, 0.683594f, 0.680664f, 0.676270f, 0.001725f, 0.005436f, 0.009171f, 0.012589f, 0.016190f, 0.019485f, 0.023132f, 0.026978f,
+ 0.030899f, 0.034180f, 0.037659f, 0.041565f, 0.045074f, 0.049438f, 0.053345f, 0.057739f, 0.061768f, 0.065918f, 0.070679f, 0.075073f,
+ 0.080078f, 0.084656f, 0.089966f, 0.095215f, 0.100464f, 0.106445f, 0.112000f, 0.117615f, 0.124207f, 0.130737f, 0.136719f, 0.144043f,
+ 0.151123f, 0.158081f, 0.165405f, 0.173096f, 0.181152f, 0.189087f, 0.197510f, 0.205688f, 0.214600f, 0.223145f, 0.232178f, 0.241699f,
+ 0.250732f, 0.260254f, 0.270264f, 0.279785f, 0.289795f, 0.300293f, 0.310791f, 0.322510f, 0.333496f, 0.344238f, 0.355713f, 0.367188f,
+ 0.379395f, 0.392090f, 0.664551f, 0.678711f, 0.678223f, 0.675781f, 0.672852f, 0.669922f, 0.001741f, 0.005077f, 0.008522f, 0.011810f,
+ 0.014946f, 0.018524f, 0.021332f, 0.024872f, 0.028519f, 0.031799f, 0.034973f, 0.038727f, 0.041992f, 0.045654f, 0.049072f, 0.052856f,
+ 0.056671f, 0.060638f, 0.064819f, 0.069092f, 0.073425f, 0.078125f, 0.082886f, 0.087280f, 0.092651f, 0.098206f, 0.103638f, 0.109192f,
+ 0.114563f, 0.120667f, 0.126709f, 0.133057f, 0.139771f, 0.146851f, 0.153931f, 0.160767f, 0.168457f, 0.175903f, 0.183838f, 0.192505f,
+ 0.200195f, 0.208618f, 0.217407f, 0.226562f, 0.236084f, 0.245239f, 0.254639f, 0.263672f, 0.273926f, 0.283447f, 0.294189f, 0.304932f,
+ 0.315674f, 0.326172f, 0.337402f, 0.348877f, 0.360107f, 0.373291f, 0.653809f, 0.670410f, 0.669922f, 0.667480f, 0.665527f, 0.662109f,
+ 0.001639f, 0.004951f, 0.007996f, 0.010857f, 0.013779f, 0.016968f, 0.019974f, 0.023392f, 0.026001f, 0.029373f, 0.032013f, 0.035370f,
+ 0.038513f, 0.041992f, 0.044586f, 0.048706f, 0.052124f, 0.055634f, 0.059723f, 0.063354f, 0.067444f, 0.071289f, 0.075745f, 0.080444f,
+ 0.085022f, 0.089722f, 0.095032f, 0.100220f, 0.105347f, 0.111206f, 0.117126f, 0.123108f, 0.129395f, 0.135620f, 0.142090f, 0.148682f,
+ 0.156372f, 0.163574f, 0.170898f, 0.178711f, 0.186890f, 0.194580f, 0.203613f, 0.211426f, 0.220459f, 0.229492f, 0.238281f, 0.248169f,
+ 0.257324f, 0.267578f, 0.277832f, 0.287354f, 0.298340f, 0.308350f, 0.319824f, 0.331543f, 0.342041f, 0.354248f, 0.641602f, 0.660645f,
+ 0.662109f, 0.660645f, 0.658203f, 0.654785f, 0.001569f, 0.004539f, 0.007538f, 0.010368f, 0.013359f, 0.016006f, 0.018539f, 0.021210f,
+ 0.024384f, 0.026855f, 0.029892f, 0.032471f, 0.035034f, 0.038177f, 0.041199f, 0.044434f, 0.047485f, 0.050781f, 0.054321f, 0.057953f,
+ 0.061523f, 0.065430f, 0.069275f, 0.073547f, 0.077820f, 0.082092f, 0.086731f, 0.091736f, 0.096985f, 0.101990f, 0.107361f, 0.112549f,
+ 0.118774f, 0.124878f, 0.131104f, 0.137573f, 0.144409f, 0.150635f, 0.157837f, 0.165283f, 0.173340f, 0.181274f, 0.188599f, 0.197510f,
+ 0.205933f, 0.214600f, 0.223633f, 0.232056f, 0.241577f, 0.251709f, 0.261230f, 0.270996f, 0.281250f, 0.291260f, 0.302246f, 0.313477f,
+ 0.323730f, 0.336182f, 0.630859f, 0.651855f, 0.652832f, 0.652344f, 0.650391f, 0.647461f, 0.001558f, 0.004139f, 0.007103f, 0.009560f,
+ 0.012077f, 0.014313f, 0.016983f, 0.019653f, 0.021988f, 0.024490f, 0.027023f, 0.029526f, 0.031891f, 0.034821f, 0.037903f, 0.040192f,
+ 0.043457f, 0.046417f, 0.049316f, 0.052795f, 0.055725f, 0.059357f, 0.063354f, 0.066895f, 0.070740f, 0.074890f, 0.078979f, 0.083801f,
+ 0.088440f, 0.093018f, 0.097961f, 0.103394f, 0.108704f, 0.114563f, 0.120239f, 0.126343f, 0.132690f, 0.139038f, 0.145874f, 0.152710f,
+ 0.159912f, 0.168091f, 0.175537f, 0.183228f, 0.191650f, 0.199707f, 0.208130f, 0.216797f, 0.226074f, 0.235352f, 0.244507f, 0.254395f,
+ 0.264404f, 0.274414f, 0.285156f, 0.296631f, 0.307373f, 0.318604f, 0.619141f, 0.643066f, 0.644531f, 0.644043f, 0.642578f, 0.639648f,
+ 0.001314f, 0.004002f, 0.006603f, 0.009056f, 0.011490f, 0.013184f, 0.015587f, 0.017883f, 0.020157f, 0.022415f, 0.024582f, 0.027206f,
+ 0.029160f, 0.031677f, 0.034088f, 0.036530f, 0.039337f, 0.042206f, 0.044891f, 0.047729f, 0.050751f, 0.053955f, 0.057312f, 0.060486f,
+ 0.064148f, 0.068054f, 0.071960f, 0.075867f, 0.079895f, 0.084595f, 0.089172f, 0.094238f, 0.098999f, 0.104492f, 0.109802f, 0.115173f,
+ 0.121338f, 0.127686f, 0.134033f, 0.140991f, 0.147095f, 0.154541f, 0.161865f, 0.169800f, 0.177368f, 0.185547f, 0.193848f, 0.201904f,
+ 0.211060f, 0.219116f, 0.229004f, 0.238525f, 0.248047f, 0.257812f, 0.267822f, 0.277832f, 0.289062f, 0.300537f, 0.607910f, 0.633301f,
+ 0.636230f, 0.635742f, 0.634766f, 0.633301f, 0.001217f, 0.003571f, 0.005947f, 0.008011f, 0.010391f, 0.012207f, 0.014313f, 0.016617f,
+ 0.018280f, 0.020523f, 0.022537f, 0.024475f, 0.026443f, 0.028778f, 0.030884f, 0.032867f, 0.035553f, 0.037872f, 0.040375f, 0.042938f,
+ 0.045593f, 0.048431f, 0.051605f, 0.054688f, 0.057953f, 0.061279f, 0.065002f, 0.068665f, 0.072266f, 0.076294f, 0.080872f, 0.085083f,
+ 0.089783f, 0.094482f, 0.099915f, 0.104736f, 0.110901f, 0.116272f, 0.122314f, 0.128784f, 0.134888f, 0.142090f, 0.148560f, 0.155884f,
+ 0.163574f, 0.171753f, 0.179077f, 0.187500f, 0.195679f, 0.204346f, 0.213745f, 0.222656f, 0.231812f, 0.241455f, 0.250977f, 0.261230f,
+ 0.272461f, 0.282959f, 0.596680f, 0.623535f, 0.627441f, 0.627930f, 0.627441f, 0.625000f, 0.001111f, 0.003542f, 0.005569f, 0.007504f,
+ 0.009338f, 0.011452f, 0.012939f, 0.015030f, 0.016678f, 0.018326f, 0.020203f, 0.022217f, 0.023788f, 0.025604f, 0.027771f, 0.029877f,
+ 0.031860f, 0.033813f, 0.036102f, 0.038605f, 0.040985f, 0.043579f, 0.046448f, 0.049042f, 0.051849f, 0.055054f, 0.058319f, 0.061615f,
+ 0.065125f, 0.068909f, 0.072815f, 0.076843f, 0.080872f, 0.085571f, 0.089905f, 0.095398f, 0.100159f, 0.105713f, 0.111206f, 0.116882f,
+ 0.122925f, 0.129517f, 0.135742f, 0.142822f, 0.149902f, 0.157349f, 0.165161f, 0.172852f, 0.181152f, 0.189331f, 0.198120f, 0.206909f,
+ 0.215820f, 0.225342f, 0.235474f, 0.245239f, 0.254883f, 0.266602f, 0.584473f, 0.614746f, 0.619141f, 0.619629f, 0.619141f, 0.618164f,
+ 0.001149f, 0.003147f, 0.004826f, 0.006886f, 0.008629f, 0.010452f, 0.012024f, 0.013359f, 0.015175f, 0.016647f, 0.018143f, 0.019882f,
+ 0.021332f, 0.023026f, 0.024902f, 0.026550f, 0.028397f, 0.030045f, 0.032318f, 0.034393f, 0.036682f, 0.038910f, 0.041107f, 0.043671f,
+ 0.046295f, 0.048950f, 0.051819f, 0.054993f, 0.058258f, 0.061523f, 0.065063f, 0.068481f, 0.072510f, 0.076965f, 0.081055f, 0.085510f,
+ 0.090393f, 0.095093f, 0.100342f, 0.105774f, 0.111694f, 0.117371f, 0.124084f, 0.130371f, 0.136963f, 0.143921f, 0.151245f, 0.159058f,
+ 0.166626f, 0.174927f, 0.182983f, 0.191650f, 0.200195f, 0.209473f, 0.218750f, 0.228149f, 0.238037f, 0.249146f, 0.572266f, 0.604980f,
+ 0.609863f, 0.611328f, 0.610352f, 0.611328f, 0.001009f, 0.003059f, 0.004620f, 0.006283f, 0.007881f, 0.009415f, 0.010864f, 0.011940f,
+ 0.013443f, 0.014847f, 0.016403f, 0.017700f, 0.019012f, 0.020493f, 0.021927f, 0.023697f, 0.025177f, 0.026947f, 0.028732f, 0.030472f,
+ 0.032654f, 0.034302f, 0.036591f, 0.038757f, 0.041046f, 0.043488f, 0.045837f, 0.048706f, 0.051544f, 0.054810f, 0.057770f, 0.061188f,
+ 0.064331f, 0.068237f, 0.072083f, 0.076416f, 0.080872f, 0.085388f, 0.090149f, 0.095276f, 0.100403f, 0.105896f, 0.111877f, 0.117798f,
+ 0.124329f, 0.130859f, 0.138062f, 0.145020f, 0.152710f, 0.160034f, 0.168335f, 0.176514f, 0.185059f, 0.193481f, 0.203125f, 0.212158f,
+ 0.221924f, 0.232178f, 0.562500f, 0.594727f, 0.601074f, 0.602539f, 0.603516f, 0.602539f, 0.000865f, 0.002674f, 0.004444f, 0.005615f,
+ 0.007233f, 0.008430f, 0.009827f, 0.010880f, 0.011917f, 0.013206f, 0.014412f, 0.015717f, 0.016876f, 0.018173f, 0.019501f, 0.020950f,
+ 0.022217f, 0.023773f, 0.025284f, 0.026749f, 0.028610f, 0.030151f, 0.032166f, 0.034149f, 0.036041f, 0.038330f, 0.040558f, 0.042877f,
+ 0.045532f, 0.048157f, 0.050934f, 0.053894f, 0.056946f, 0.060303f, 0.063843f, 0.067566f, 0.071472f, 0.075806f, 0.080261f, 0.084778f,
+ 0.089600f, 0.094971f, 0.100220f, 0.105896f, 0.111877f, 0.118103f, 0.125000f, 0.131348f, 0.138550f, 0.146362f, 0.153687f, 0.161987f,
+ 0.169678f, 0.178223f, 0.187134f, 0.196045f, 0.205811f, 0.215698f, 0.549805f, 0.584961f, 0.592773f, 0.594238f, 0.593750f, 0.595215f,
+ 0.000951f, 0.002476f, 0.003956f, 0.005062f, 0.006268f, 0.007637f, 0.008888f, 0.009666f, 0.010628f, 0.011810f, 0.012856f, 0.013878f,
+ 0.014946f, 0.015900f, 0.017227f, 0.018356f, 0.019592f, 0.020889f, 0.022003f, 0.023438f, 0.025101f, 0.026489f, 0.028122f, 0.029739f,
+ 0.031555f, 0.033295f, 0.035431f, 0.037537f, 0.039795f, 0.041962f, 0.044647f, 0.047302f, 0.049957f, 0.052979f, 0.056122f, 0.059387f,
+ 0.062927f, 0.066956f, 0.070679f, 0.074951f, 0.079468f, 0.084167f, 0.089294f, 0.094482f, 0.100098f, 0.106018f, 0.112061f, 0.118835f,
+ 0.125366f, 0.132446f, 0.139893f, 0.147827f, 0.155762f, 0.163574f, 0.172607f, 0.180786f, 0.190063f, 0.199951f, 0.536621f, 0.576172f,
+ 0.583496f, 0.586914f, 0.587402f, 0.586914f, 0.000788f, 0.002115f, 0.003592f, 0.004780f, 0.005939f, 0.006615f, 0.007740f, 0.008598f,
+ 0.009514f, 0.010376f, 0.011200f, 0.012138f, 0.013016f, 0.014069f, 0.014977f, 0.015961f, 0.016922f, 0.018036f, 0.019043f, 0.020447f,
+ 0.021606f, 0.022995f, 0.024323f, 0.025864f, 0.027344f, 0.028946f, 0.030731f, 0.032593f, 0.034515f, 0.036530f, 0.038910f, 0.041016f,
+ 0.043274f, 0.046021f, 0.048981f, 0.051819f, 0.055176f, 0.058472f, 0.062012f, 0.065857f, 0.069946f, 0.074219f, 0.078796f, 0.083801f,
+ 0.088806f, 0.094299f, 0.100281f, 0.106018f, 0.112793f, 0.119446f, 0.126343f, 0.133545f, 0.141357f, 0.149292f, 0.157104f, 0.165894f,
+ 0.174683f, 0.184326f, 0.524902f, 0.566895f, 0.575195f, 0.576660f, 0.579102f, 0.579590f, 0.000661f, 0.001961f, 0.003382f, 0.004311f,
+ 0.005161f, 0.006062f, 0.006737f, 0.007427f, 0.008286f, 0.008995f, 0.009857f, 0.010368f, 0.011230f, 0.011955f, 0.012833f, 0.013786f,
+ 0.014565f, 0.015480f, 0.016647f, 0.017578f, 0.018677f, 0.019806f, 0.020950f, 0.022263f, 0.023651f, 0.024994f, 0.026306f, 0.027863f,
+ 0.029724f, 0.031525f, 0.033325f, 0.035370f, 0.037292f, 0.039673f, 0.042114f, 0.044769f, 0.047546f, 0.050537f, 0.053680f, 0.057098f,
+ 0.060852f, 0.064514f, 0.069031f, 0.073303f, 0.078064f, 0.083069f, 0.088379f, 0.094238f, 0.100220f, 0.106689f, 0.113342f, 0.120300f,
+ 0.127563f, 0.135132f, 0.142700f, 0.151245f, 0.160034f, 0.168823f, 0.512695f, 0.557129f, 0.566406f, 0.569824f, 0.569824f, 0.571289f,
+ 0.000757f, 0.001709f, 0.002844f, 0.003582f, 0.004448f, 0.005192f, 0.005989f, 0.006519f, 0.007038f, 0.007801f, 0.008453f, 0.009071f,
+ 0.009727f, 0.010391f, 0.011009f, 0.011726f, 0.012650f, 0.013184f, 0.014107f, 0.014977f, 0.015900f, 0.016800f, 0.017776f, 0.018936f,
+ 0.020172f, 0.021271f, 0.022446f, 0.023697f, 0.025055f, 0.026703f, 0.028397f, 0.030014f, 0.031921f, 0.033905f, 0.035919f, 0.038177f,
+ 0.040680f, 0.043243f, 0.045898f, 0.049072f, 0.052216f, 0.055725f, 0.059784f, 0.063538f, 0.067688f, 0.072327f, 0.077271f, 0.082764f,
+ 0.088379f, 0.094299f, 0.100708f, 0.107239f, 0.114136f, 0.121582f, 0.128906f, 0.136963f, 0.145630f, 0.153564f, 0.500977f, 0.547852f,
+ 0.556641f, 0.561523f, 0.562500f, 0.563965f, 0.000704f, 0.001769f, 0.002542f, 0.003523f, 0.004036f, 0.004562f, 0.005032f, 0.005661f,
+ 0.006176f, 0.006542f, 0.007072f, 0.007698f, 0.008339f, 0.008827f, 0.009323f, 0.010094f, 0.010757f, 0.011276f, 0.012093f, 0.012733f,
+ 0.013489f, 0.014488f, 0.015244f, 0.016006f, 0.017151f, 0.017975f, 0.018967f, 0.020142f, 0.021255f, 0.022552f, 0.023880f, 0.025314f,
+ 0.026840f, 0.028503f, 0.030441f, 0.032166f, 0.034424f, 0.036438f, 0.039001f, 0.041656f, 0.044464f, 0.047455f, 0.050842f, 0.054443f,
+ 0.058167f, 0.062286f, 0.066956f, 0.071899f, 0.076904f, 0.082458f, 0.088501f, 0.094482f, 0.101196f, 0.108337f, 0.115662f, 0.123352f,
+ 0.130981f, 0.139282f, 0.489746f, 0.538574f, 0.547852f, 0.551270f, 0.554688f, 0.555176f, 0.000579f, 0.001450f, 0.002396f, 0.002857f,
+ 0.003454f, 0.004032f, 0.004356f, 0.004791f, 0.005333f, 0.005718f, 0.006130f, 0.006485f, 0.007042f, 0.007473f, 0.007988f, 0.008476f,
+ 0.008865f, 0.009613f, 0.010086f, 0.010651f, 0.011345f, 0.012047f, 0.012764f, 0.013435f, 0.014282f, 0.015144f, 0.015884f, 0.016846f,
+ 0.017868f, 0.018814f, 0.020050f, 0.021164f, 0.022507f, 0.023773f, 0.025192f, 0.026978f, 0.028564f, 0.030640f, 0.032623f, 0.034882f,
+ 0.037231f, 0.039886f, 0.042786f, 0.046143f, 0.049286f, 0.052979f, 0.057098f, 0.061279f, 0.066223f, 0.071167f, 0.076660f, 0.082581f,
+ 0.088989f, 0.095581f, 0.102661f, 0.109863f, 0.117737f, 0.125488f, 0.476807f, 0.528320f, 0.538574f, 0.543945f, 0.546875f, 0.546875f,
+ 0.000510f, 0.001428f, 0.002037f, 0.002613f, 0.003086f, 0.003290f, 0.003672f, 0.004108f, 0.004345f, 0.004768f, 0.005035f, 0.005470f,
+ 0.005959f, 0.006207f, 0.006599f, 0.007095f, 0.007568f, 0.008003f, 0.008377f, 0.008904f, 0.009575f, 0.010010f, 0.010643f, 0.011131f,
+ 0.011871f, 0.012535f, 0.013199f, 0.014038f, 0.014839f, 0.015640f, 0.016586f, 0.017502f, 0.018585f, 0.019745f, 0.021088f, 0.022354f,
+ 0.023727f, 0.025253f, 0.026962f, 0.028870f, 0.030762f, 0.033051f, 0.035492f, 0.038177f, 0.041229f, 0.044403f, 0.048004f, 0.051880f,
+ 0.056213f, 0.060516f, 0.065857f, 0.071045f, 0.077271f, 0.083374f, 0.090027f, 0.096863f, 0.104492f, 0.112183f, 0.463623f, 0.518066f,
+ 0.529785f, 0.535156f, 0.538086f, 0.540039f, 0.000473f, 0.001222f, 0.001771f, 0.002117f, 0.002323f, 0.002796f, 0.003096f, 0.003355f,
+ 0.003601f, 0.003975f, 0.004295f, 0.004543f, 0.004833f, 0.005142f, 0.005455f, 0.005848f, 0.006165f, 0.006535f, 0.006947f, 0.007370f,
+ 0.007809f, 0.008240f, 0.008690f, 0.009216f, 0.009758f, 0.010223f, 0.010925f, 0.011536f, 0.012146f, 0.012833f, 0.013573f, 0.014389f,
+ 0.015244f, 0.016220f, 0.017120f, 0.018219f, 0.019379f, 0.020599f, 0.021988f, 0.023514f, 0.025131f, 0.027054f, 0.029037f, 0.031311f,
+ 0.033752f, 0.036591f, 0.039520f, 0.042999f, 0.046661f, 0.050873f, 0.055603f, 0.060333f, 0.066101f, 0.071960f, 0.078491f, 0.084961f,
+ 0.091797f, 0.099426f, 0.452148f, 0.508301f, 0.520508f, 0.526367f, 0.528809f, 0.530273f, 0.000299f, 0.001057f, 0.001329f, 0.001771f,
+ 0.001957f, 0.002350f, 0.002483f, 0.002697f, 0.002964f, 0.003181f, 0.003441f, 0.003653f, 0.003904f, 0.004238f, 0.004501f, 0.004738f,
+ 0.005024f, 0.005390f, 0.005657f, 0.005985f, 0.006279f, 0.006714f, 0.007053f, 0.007507f, 0.007881f, 0.008369f, 0.008774f, 0.009300f,
+ 0.009888f, 0.010483f, 0.011093f, 0.011627f, 0.012398f, 0.013130f, 0.013855f, 0.014717f, 0.015686f, 0.016739f, 0.017761f, 0.018890f,
+ 0.020248f, 0.021698f, 0.023376f, 0.025131f, 0.027237f, 0.029556f, 0.032166f, 0.035004f, 0.038208f, 0.041962f, 0.045868f, 0.050507f,
+ 0.055359f, 0.060852f, 0.066772f, 0.073242f, 0.080017f, 0.087097f, 0.440674f, 0.498047f, 0.511719f, 0.517090f, 0.520508f, 0.522949f,
+ 0.000427f, 0.001020f, 0.001253f, 0.001431f, 0.001690f, 0.001900f, 0.002018f, 0.002304f, 0.002481f, 0.002569f, 0.002731f, 0.002998f,
+ 0.003157f, 0.003424f, 0.003592f, 0.003838f, 0.004017f, 0.004253f, 0.004551f, 0.004776f, 0.005100f, 0.005379f, 0.005699f, 0.005932f,
+ 0.006290f, 0.006630f, 0.007038f, 0.007465f, 0.007927f, 0.008286f, 0.008858f, 0.009293f, 0.009888f, 0.010429f, 0.011086f, 0.011765f,
+ 0.012482f, 0.013298f, 0.014168f, 0.015068f, 0.016129f, 0.017288f, 0.018585f, 0.019943f, 0.021622f, 0.023361f, 0.025436f, 0.027847f,
+ 0.030655f, 0.033447f, 0.037079f, 0.041229f, 0.045776f, 0.050568f, 0.056061f, 0.062317f, 0.068726f, 0.075684f, 0.427734f, 0.488525f,
+ 0.502441f, 0.508789f, 0.513184f, 0.513672f, 0.000255f, 0.000597f, 0.001032f, 0.001150f, 0.001353f, 0.001493f, 0.001608f, 0.001750f,
+ 0.001933f, 0.002062f, 0.002178f, 0.002302f, 0.002474f, 0.002670f, 0.002872f, 0.002995f, 0.003147f, 0.003298f, 0.003565f, 0.003729f,
+ 0.003941f, 0.004219f, 0.004436f, 0.004719f, 0.005005f, 0.005230f, 0.005489f, 0.005806f, 0.006191f, 0.006496f, 0.006897f, 0.007267f,
+ 0.007671f, 0.008179f, 0.008636f, 0.009163f, 0.009766f, 0.010368f, 0.011047f, 0.011810f, 0.012611f, 0.013527f, 0.014519f, 0.015640f,
+ 0.016800f, 0.018265f, 0.019897f, 0.021698f, 0.023895f, 0.026260f, 0.029175f, 0.032715f, 0.036682f, 0.041168f, 0.045929f, 0.051758f,
+ 0.057922f, 0.064575f, 0.415771f, 0.478271f, 0.493652f, 0.500000f, 0.503906f, 0.505859f, 0.000255f, 0.000544f, 0.000863f, 0.000994f,
+ 0.001086f, 0.001183f, 0.001317f, 0.001328f, 0.001491f, 0.001608f, 0.001716f, 0.001851f, 0.001943f, 0.002075f, 0.002161f, 0.002319f,
+ 0.002426f, 0.002596f, 0.002741f, 0.002884f, 0.003088f, 0.003265f, 0.003391f, 0.003620f, 0.003777f, 0.004005f, 0.004215f, 0.004452f,
+ 0.004734f, 0.004963f, 0.005341f, 0.005577f, 0.005875f, 0.006271f, 0.006603f, 0.006996f, 0.007450f, 0.007919f, 0.008446f, 0.009003f,
+ 0.009674f, 0.010338f, 0.011101f, 0.011909f, 0.012917f, 0.013977f, 0.015190f, 0.016495f, 0.018112f, 0.020325f, 0.022415f, 0.025146f,
+ 0.028473f, 0.032349f, 0.036804f, 0.041992f, 0.047913f, 0.054077f, 0.404541f, 0.468506f, 0.484131f, 0.490967f, 0.495361f, 0.498291f,
+ 0.000377f, 0.000440f, 0.000606f, 0.000685f, 0.000735f, 0.000876f, 0.000929f, 0.001035f, 0.001068f, 0.001157f, 0.001307f, 0.001381f,
+ 0.001473f, 0.001595f, 0.001664f, 0.001708f, 0.001850f, 0.001957f, 0.002043f, 0.002195f, 0.002291f, 0.002422f, 0.002571f, 0.002687f,
+ 0.002842f, 0.002979f, 0.003183f, 0.003345f, 0.003532f, 0.003794f, 0.004002f, 0.004154f, 0.004429f, 0.004635f, 0.004967f, 0.005253f,
+ 0.005573f, 0.005909f, 0.006275f, 0.006695f, 0.007183f, 0.007660f, 0.008316f, 0.008934f, 0.009644f, 0.010429f, 0.011360f, 0.012497f,
+ 0.013634f, 0.014977f, 0.016663f, 0.018875f, 0.021423f, 0.024643f, 0.028549f, 0.033020f, 0.038483f, 0.044525f, 0.391602f, 0.458984f,
+ 0.474854f, 0.482178f, 0.488037f, 0.489990f, 0.000159f, 0.000401f, 0.000450f, 0.000522f, 0.000605f, 0.000634f, 0.000728f, 0.000702f,
+ 0.000808f, 0.000882f, 0.000959f, 0.000991f, 0.001043f, 0.001112f, 0.001205f, 0.001245f, 0.001357f, 0.001419f, 0.001513f, 0.001546f,
+ 0.001648f, 0.001752f, 0.001863f, 0.001942f, 0.002056f, 0.002159f, 0.002289f, 0.002392f, 0.002506f, 0.002697f, 0.002827f, 0.003023f,
+ 0.003172f, 0.003330f, 0.003542f, 0.003750f, 0.004017f, 0.004292f, 0.004559f, 0.004871f, 0.005161f, 0.005539f, 0.005932f, 0.006416f,
+ 0.006973f, 0.007526f, 0.008232f, 0.008980f, 0.009918f, 0.010895f, 0.012085f, 0.013680f, 0.015472f, 0.017975f, 0.021103f, 0.025146f,
+ 0.029938f, 0.035645f, 0.379395f, 0.448486f, 0.465820f, 0.473633f, 0.478760f, 0.481689f, 0.000112f, 0.000220f, 0.000321f, 0.000322f,
+ 0.000401f, 0.000489f, 0.000469f, 0.000510f, 0.000568f, 0.000653f, 0.000659f, 0.000676f, 0.000703f, 0.000789f, 0.000811f, 0.000886f,
+ 0.000888f, 0.000994f, 0.001048f, 0.001096f, 0.001155f, 0.001220f, 0.001289f, 0.001357f, 0.001431f, 0.001496f, 0.001599f, 0.001675f,
+ 0.001759f, 0.001894f, 0.001965f, 0.002083f, 0.002193f, 0.002310f, 0.002464f, 0.002634f, 0.002758f, 0.002949f, 0.003134f, 0.003319f,
+ 0.003551f, 0.003830f, 0.004120f, 0.004440f, 0.004784f, 0.005188f, 0.005680f, 0.006222f, 0.006886f, 0.007614f, 0.008461f, 0.009529f,
+ 0.010864f, 0.012596f, 0.014961f, 0.018097f, 0.022263f, 0.027466f, 0.367920f, 0.438232f, 0.456543f, 0.465332f, 0.470215f, 0.472900f,
+ 0.000140f, 0.000219f, 0.000241f, 0.000245f, 0.000290f, 0.000291f, 0.000302f, 0.000342f, 0.000380f, 0.000409f, 0.000408f, 0.000485f,
+ 0.000473f, 0.000527f, 0.000556f, 0.000575f, 0.000630f, 0.000642f, 0.000673f, 0.000711f, 0.000762f, 0.000800f, 0.000852f, 0.000886f,
+ 0.000952f, 0.000982f, 0.001049f, 0.001108f, 0.001159f, 0.001220f, 0.001281f, 0.001369f, 0.001454f, 0.001522f, 0.001595f, 0.001695f,
+ 0.001839f, 0.001928f, 0.002068f, 0.002209f, 0.002337f, 0.002504f, 0.002686f, 0.002876f, 0.003139f, 0.003437f, 0.003723f, 0.004078f,
+ 0.004509f, 0.005009f, 0.005615f, 0.006332f, 0.007317f, 0.008461f, 0.009926f, 0.012154f, 0.015640f, 0.020325f, 0.356445f, 0.429199f,
+ 0.447266f, 0.456299f, 0.462158f, 0.464844f, 0.000048f, 0.000154f, 0.000141f, 0.000147f, 0.000174f, 0.000207f, 0.000188f, 0.000221f,
+ 0.000233f, 0.000242f, 0.000248f, 0.000271f, 0.000299f, 0.000312f, 0.000337f, 0.000350f, 0.000367f, 0.000403f, 0.000416f, 0.000458f,
+ 0.000465f, 0.000483f, 0.000507f, 0.000546f, 0.000576f, 0.000625f, 0.000637f, 0.000659f, 0.000705f, 0.000742f, 0.000797f, 0.000837f,
+ 0.000890f, 0.000925f, 0.000978f, 0.001036f, 0.001103f, 0.001181f, 0.001253f, 0.001329f, 0.001421f, 0.001529f, 0.001647f, 0.001782f,
+ 0.001906f, 0.002075f, 0.002291f, 0.002483f, 0.002758f, 0.003059f, 0.003450f, 0.003906f, 0.004536f, 0.005306f, 0.006325f, 0.007713f,
+ 0.010101f, 0.014084f, 0.343262f, 0.418457f, 0.437744f, 0.447510f, 0.452881f, 0.456543f, 0.000099f, 0.000100f, 0.000091f, 0.000085f,
+ 0.000105f, 0.000099f, 0.000127f, 0.000127f, 0.000130f, 0.000137f, 0.000152f, 0.000164f, 0.000164f, 0.000172f, 0.000195f, 0.000186f,
+ 0.000209f, 0.000222f, 0.000231f, 0.000241f, 0.000258f, 0.000266f, 0.000290f, 0.000301f, 0.000324f, 0.000343f, 0.000357f, 0.000369f,
+ 0.000392f, 0.000409f, 0.000440f, 0.000463f, 0.000484f, 0.000513f, 0.000544f, 0.000578f, 0.000607f, 0.000650f, 0.000702f, 0.000737f,
+ 0.000787f, 0.000846f, 0.000918f, 0.000977f, 0.001062f, 0.001146f, 0.001259f, 0.001379f, 0.001524f, 0.001701f, 0.001924f, 0.002207f,
+ 0.002542f, 0.003006f, 0.003628f, 0.004494f, 0.005821f, 0.008774f, 0.332031f, 0.409180f, 0.428467f, 0.438965f, 0.444336f, 0.447998f,
+ 0.000082f, 0.000057f, 0.000048f, 0.000051f, 0.000055f, 0.000054f, 0.000057f, 0.000064f, 0.000066f, 0.000079f, 0.000070f, 0.000070f,
+ 0.000084f, 0.000078f, 0.000084f, 0.000091f, 0.000099f, 0.000108f, 0.000108f, 0.000114f, 0.000119f, 0.000124f, 0.000129f, 0.000144f,
+ 0.000151f, 0.000158f, 0.000163f, 0.000176f, 0.000188f, 0.000196f, 0.000208f, 0.000220f, 0.000227f, 0.000239f, 0.000259f, 0.000273f,
+ 0.000290f, 0.000303f, 0.000331f, 0.000351f, 0.000376f, 0.000402f, 0.000432f, 0.000460f, 0.000500f, 0.000547f, 0.000593f, 0.000648f,
+ 0.000720f, 0.000805f, 0.000918f, 0.001045f, 0.001225f, 0.001462f, 0.001788f, 0.002264f, 0.003029f, 0.004623f, 0.320801f, 0.398682f,
+ 0.419922f, 0.430420f, 0.436279f, 0.440674f, 0.000061f, 0.000041f, 0.000033f, 0.000029f, 0.000026f, 0.000025f, 0.000024f, 0.000024f,
+ 0.000023f, 0.000023f, 0.000025f, 0.000032f, 0.000026f, 0.000027f, 0.000035f, 0.000037f, 0.000039f, 0.000041f, 0.000041f, 0.000041f,
+ 0.000044f, 0.000050f, 0.000054f, 0.000051f, 0.000055f, 0.000060f, 0.000061f, 0.000062f, 0.000069f, 0.000074f, 0.000075f, 0.000081f,
+ 0.000087f, 0.000090f, 0.000093f, 0.000098f, 0.000108f, 0.000114f, 0.000123f, 0.000130f, 0.000142f, 0.000144f, 0.000156f, 0.000173f,
+ 0.000179f, 0.000200f, 0.000218f, 0.000237f, 0.000267f, 0.000299f, 0.000335f, 0.000382f, 0.000448f, 0.000544f, 0.000677f, 0.000883f,
+ 0.001233f, 0.001933f, 0.309570f, 0.388672f, 0.410889f, 0.421143f, 0.427246f, 0.431885f, 0.000031f, 0.000020f, 0.000016f, 0.000014f,
+ 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000008f, 0.000009f,
+ 0.000009f, 0.000007f, 0.000007f, 0.000007f, 0.000008f, 0.000009f, 0.000011f, 0.000012f, 0.000012f, 0.000012f, 0.000013f, 0.000015f,
+ 0.000015f, 0.000014f, 0.000016f, 0.000017f, 0.000019f, 0.000020f, 0.000020f, 0.000022f, 0.000025f, 0.000023f, 0.000026f, 0.000029f,
+ 0.000031f, 0.000034f, 0.000036f, 0.000037f, 0.000040f, 0.000044f, 0.000048f, 0.000052f, 0.000056f, 0.000063f, 0.000068f, 0.000083f,
+ 0.000098f, 0.000117f, 0.000149f, 0.000201f, 0.000301f, 0.000544f, 0.297607f, 0.379150f, 0.400879f, 0.411865f, 0.419189f, 0.423340f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000002f, 0.000003f, 0.000004f, 0.000004f, 0.000004f, 0.000005f, 0.000007f, 0.000011f, 0.000026f, 0.286621f, 0.368896f,
+ 0.391846f, 0.402588f, 0.409912f, 0.414551f,
+ },
+ {
+ 0.007935f, 0.024429f, 0.041290f, 0.058838f, 0.076355f, 0.093933f, 0.111145f, 0.128174f, 0.146606f, 0.164429f, 0.182617f, 0.200562f,
+ 0.218750f, 0.236206f, 0.254150f, 0.271729f, 0.289551f, 0.308105f, 0.325684f, 0.342773f, 0.360596f, 0.379150f, 0.396240f, 0.414795f,
+ 0.431641f, 0.450439f, 0.468018f, 0.484619f, 0.502441f, 0.520020f, 0.536621f, 0.554688f, 0.571777f, 0.588379f, 0.605469f, 0.622559f,
+ 0.640137f, 0.657227f, 0.672852f, 0.689941f, 0.707031f, 0.723633f, 0.740234f, 0.756836f, 0.773926f, 0.789551f, 0.805664f, 0.821777f,
+ 0.838379f, 0.854980f, 0.870117f, 0.885742f, 0.901855f, 0.917480f, 0.932617f, 0.948730f, 0.963379f, 0.979492f, 0.960449f, 0.909668f,
+ 0.876465f, 0.850098f, 0.827637f, 0.807617f, 0.007530f, 0.023422f, 0.039764f, 0.056610f, 0.073303f, 0.090149f, 0.107300f, 0.124084f,
+ 0.141968f, 0.158569f, 0.176392f, 0.193604f, 0.210815f, 0.228760f, 0.246094f, 0.262695f, 0.280518f, 0.298340f, 0.315430f, 0.333252f,
+ 0.350586f, 0.367432f, 0.384766f, 0.402344f, 0.419678f, 0.436768f, 0.453613f, 0.471436f, 0.488037f, 0.504883f, 0.521973f, 0.538574f,
+ 0.556641f, 0.573242f, 0.589844f, 0.605957f, 0.623535f, 0.639160f, 0.656250f, 0.673340f, 0.688477f, 0.706055f, 0.721680f, 0.738770f,
+ 0.754883f, 0.770508f, 0.786133f, 0.803711f, 0.817871f, 0.834473f, 0.850586f, 0.866211f, 0.881348f, 0.896973f, 0.913086f, 0.928223f,
+ 0.942871f, 0.958984f, 0.951172f, 0.903320f, 0.871094f, 0.845703f, 0.824219f, 0.805664f, 0.007320f, 0.022552f, 0.038391f, 0.054260f,
+ 0.070312f, 0.086792f, 0.103271f, 0.120178f, 0.136841f, 0.153564f, 0.170410f, 0.187256f, 0.203735f, 0.220825f, 0.237793f, 0.255127f,
+ 0.271240f, 0.288086f, 0.305420f, 0.322021f, 0.339844f, 0.356689f, 0.373047f, 0.390137f, 0.406738f, 0.423340f, 0.440186f, 0.456787f,
+ 0.474121f, 0.490967f, 0.507324f, 0.523926f, 0.540527f, 0.557129f, 0.573242f, 0.590332f, 0.606445f, 0.623047f, 0.638672f, 0.655273f,
+ 0.671875f, 0.687500f, 0.703613f, 0.720215f, 0.735840f, 0.751953f, 0.767578f, 0.783203f, 0.799316f, 0.814941f, 0.830078f, 0.845703f,
+ 0.861328f, 0.877441f, 0.892090f, 0.908203f, 0.922852f, 0.938477f, 0.941895f, 0.895996f, 0.865723f, 0.841309f, 0.820801f, 0.802734f,
+ 0.007008f, 0.021667f, 0.036865f, 0.052216f, 0.067871f, 0.083862f, 0.099426f, 0.115479f, 0.131470f, 0.148315f, 0.164551f, 0.180298f,
+ 0.196899f, 0.213379f, 0.229370f, 0.246460f, 0.262695f, 0.279541f, 0.295410f, 0.311523f, 0.329102f, 0.345215f, 0.360840f, 0.378174f,
+ 0.394043f, 0.410156f, 0.427246f, 0.443115f, 0.459717f, 0.476318f, 0.493652f, 0.508789f, 0.524902f, 0.541016f, 0.557129f, 0.573242f,
+ 0.589844f, 0.605469f, 0.621582f, 0.638672f, 0.652832f, 0.669434f, 0.685547f, 0.701660f, 0.717285f, 0.731934f, 0.749023f, 0.764160f,
+ 0.779785f, 0.794922f, 0.810059f, 0.826172f, 0.841309f, 0.856445f, 0.872070f, 0.886719f, 0.902344f, 0.917480f, 0.932129f, 0.889648f,
+ 0.859863f, 0.835938f, 0.816895f, 0.799316f, 0.006817f, 0.020645f, 0.035156f, 0.050110f, 0.065247f, 0.080383f, 0.096313f, 0.111450f,
+ 0.126587f, 0.142456f, 0.158447f, 0.174316f, 0.189819f, 0.205566f, 0.221802f, 0.237427f, 0.253662f, 0.269775f, 0.285889f, 0.301514f,
+ 0.317627f, 0.333740f, 0.349609f, 0.366211f, 0.381348f, 0.397705f, 0.414307f, 0.429932f, 0.447266f, 0.462646f, 0.477539f, 0.494385f,
+ 0.509766f, 0.525879f, 0.541992f, 0.557617f, 0.571777f, 0.588379f, 0.605469f, 0.619629f, 0.636230f, 0.651855f, 0.666992f, 0.681152f,
+ 0.698242f, 0.714355f, 0.729980f, 0.745117f, 0.759766f, 0.775391f, 0.790527f, 0.806152f, 0.821289f, 0.835938f, 0.850586f, 0.866211f,
+ 0.882324f, 0.896484f, 0.922363f, 0.882324f, 0.854004f, 0.831543f, 0.812500f, 0.795898f, 0.006378f, 0.019989f, 0.034027f, 0.048004f,
+ 0.062744f, 0.077148f, 0.091980f, 0.107178f, 0.122192f, 0.137207f, 0.152466f, 0.167603f, 0.183960f, 0.199097f, 0.214111f, 0.229736f,
+ 0.244995f, 0.260254f, 0.276367f, 0.291504f, 0.306641f, 0.322998f, 0.338623f, 0.354248f, 0.369629f, 0.385254f, 0.400879f, 0.416504f,
+ 0.432617f, 0.447510f, 0.464111f, 0.479492f, 0.494141f, 0.511230f, 0.525879f, 0.541016f, 0.556641f, 0.572754f, 0.586914f, 0.602051f,
+ 0.617676f, 0.633789f, 0.648926f, 0.665039f, 0.679688f, 0.695312f, 0.710449f, 0.726074f, 0.739746f, 0.755859f, 0.771484f, 0.785645f,
+ 0.800781f, 0.815918f, 0.831055f, 0.846680f, 0.860840f, 0.875977f, 0.912598f, 0.874512f, 0.847656f, 0.826172f, 0.807617f, 0.791504f,
+ 0.006603f, 0.019287f, 0.032776f, 0.046356f, 0.060272f, 0.073914f, 0.088135f, 0.102905f, 0.117554f, 0.132690f, 0.147095f, 0.161377f,
+ 0.176636f, 0.191162f, 0.205444f, 0.221680f, 0.236572f, 0.251465f, 0.267090f, 0.281250f, 0.296875f, 0.312256f, 0.327393f, 0.342285f,
+ 0.357666f, 0.373291f, 0.388184f, 0.403076f, 0.418457f, 0.433838f, 0.448975f, 0.465088f, 0.479980f, 0.494385f, 0.509277f, 0.525879f,
+ 0.540039f, 0.555176f, 0.570801f, 0.586426f, 0.601074f, 0.616211f, 0.631348f, 0.646484f, 0.661133f, 0.676270f, 0.692383f, 0.705078f,
+ 0.720215f, 0.735352f, 0.751953f, 0.766602f, 0.781250f, 0.796387f, 0.810059f, 0.825684f, 0.840820f, 0.855469f, 0.902344f, 0.866699f,
+ 0.841797f, 0.820312f, 0.803223f, 0.787598f, 0.006111f, 0.018433f, 0.031097f, 0.044739f, 0.057892f, 0.071472f, 0.085205f, 0.099304f,
+ 0.113037f, 0.127319f, 0.141357f, 0.156128f, 0.169678f, 0.183838f, 0.198608f, 0.213745f, 0.227661f, 0.243652f, 0.257324f, 0.272705f,
+ 0.286865f, 0.301025f, 0.316406f, 0.331543f, 0.345703f, 0.360107f, 0.375000f, 0.390625f, 0.405762f, 0.420410f, 0.435303f, 0.449951f,
+ 0.465088f, 0.479492f, 0.494141f, 0.509277f, 0.523926f, 0.538574f, 0.553711f, 0.569336f, 0.583496f, 0.598145f, 0.612793f, 0.628418f,
+ 0.642578f, 0.657227f, 0.671387f, 0.687012f, 0.702637f, 0.716797f, 0.731934f, 0.745605f, 0.761230f, 0.775391f, 0.790527f, 0.805176f,
+ 0.819824f, 0.834961f, 0.892578f, 0.858887f, 0.834473f, 0.814941f, 0.798340f, 0.783203f, 0.005756f, 0.017761f, 0.029907f, 0.042572f,
+ 0.055481f, 0.068420f, 0.081482f, 0.095276f, 0.108826f, 0.122070f, 0.135620f, 0.149902f, 0.163330f, 0.177368f, 0.191284f, 0.206421f,
+ 0.219482f, 0.233521f, 0.247925f, 0.262451f, 0.277100f, 0.290771f, 0.304688f, 0.319580f, 0.334229f, 0.348389f, 0.362549f, 0.377441f,
+ 0.391602f, 0.406250f, 0.421143f, 0.435791f, 0.450439f, 0.463867f, 0.478760f, 0.493164f, 0.507812f, 0.521973f, 0.537109f, 0.551270f,
+ 0.565430f, 0.580078f, 0.594727f, 0.609863f, 0.624023f, 0.638672f, 0.653320f, 0.668457f, 0.682129f, 0.697266f, 0.711914f, 0.726562f,
+ 0.740723f, 0.755859f, 0.770996f, 0.785156f, 0.799805f, 0.814453f, 0.882812f, 0.851562f, 0.827148f, 0.808594f, 0.792969f, 0.778809f,
+ 0.005741f, 0.017166f, 0.029053f, 0.041138f, 0.053345f, 0.065796f, 0.078674f, 0.091248f, 0.104614f, 0.117004f, 0.130737f, 0.143921f,
+ 0.156860f, 0.170288f, 0.183960f, 0.197754f, 0.211304f, 0.224976f, 0.238892f, 0.251953f, 0.266357f, 0.280273f, 0.294922f, 0.308594f,
+ 0.322021f, 0.336914f, 0.350098f, 0.364502f, 0.378174f, 0.393066f, 0.407471f, 0.420166f, 0.435059f, 0.449219f, 0.463135f, 0.477295f,
+ 0.491699f, 0.506348f, 0.520996f, 0.534668f, 0.549316f, 0.563477f, 0.577148f, 0.591309f, 0.605469f, 0.620605f, 0.634766f, 0.648438f,
+ 0.663086f, 0.677734f, 0.691895f, 0.706543f, 0.720215f, 0.734863f, 0.750488f, 0.765137f, 0.779297f, 0.793945f, 0.872559f, 0.843262f,
+ 0.820801f, 0.803223f, 0.787598f, 0.773926f, 0.005283f, 0.016052f, 0.028030f, 0.039246f, 0.050751f, 0.063232f, 0.074829f, 0.087341f,
+ 0.099976f, 0.112732f, 0.125122f, 0.138062f, 0.150757f, 0.163696f, 0.176758f, 0.189697f, 0.203125f, 0.216553f, 0.229614f, 0.243286f,
+ 0.256592f, 0.269775f, 0.283203f, 0.297119f, 0.310547f, 0.324463f, 0.337891f, 0.351807f, 0.365234f, 0.378662f, 0.392822f, 0.406738f,
+ 0.419922f, 0.434814f, 0.448730f, 0.461182f, 0.476562f, 0.489746f, 0.502930f, 0.517578f, 0.531738f, 0.545410f, 0.559082f, 0.573730f,
+ 0.587402f, 0.602051f, 0.615723f, 0.629395f, 0.644043f, 0.658203f, 0.672363f, 0.686523f, 0.701660f, 0.714844f, 0.729980f, 0.743652f,
+ 0.758301f, 0.774414f, 0.862305f, 0.835449f, 0.813965f, 0.796875f, 0.782227f, 0.769043f, 0.005272f, 0.015427f, 0.026230f, 0.037506f,
+ 0.049164f, 0.060516f, 0.072021f, 0.083740f, 0.095825f, 0.108521f, 0.120361f, 0.132324f, 0.144897f, 0.156738f, 0.169922f, 0.182373f,
+ 0.195068f, 0.208008f, 0.220459f, 0.233887f, 0.246948f, 0.260254f, 0.272461f, 0.285889f, 0.299561f, 0.312500f, 0.325684f, 0.338867f,
+ 0.352783f, 0.365479f, 0.378906f, 0.392334f, 0.406006f, 0.419189f, 0.432861f, 0.446777f, 0.460693f, 0.473877f, 0.486572f, 0.500977f,
+ 0.515137f, 0.528809f, 0.542480f, 0.555176f, 0.569824f, 0.583984f, 0.597656f, 0.611328f, 0.625000f, 0.639648f, 0.653320f, 0.667480f,
+ 0.681641f, 0.695801f, 0.709961f, 0.723633f, 0.738281f, 0.752930f, 0.852539f, 0.827148f, 0.807129f, 0.790527f, 0.776367f, 0.764160f,
+ 0.004822f, 0.014885f, 0.025360f, 0.035767f, 0.046570f, 0.057587f, 0.068726f, 0.080139f, 0.091736f, 0.103577f, 0.115479f, 0.126709f,
+ 0.138672f, 0.150879f, 0.162231f, 0.174805f, 0.187622f, 0.199951f, 0.212524f, 0.224854f, 0.236694f, 0.249878f, 0.262207f, 0.275391f,
+ 0.287842f, 0.300293f, 0.313477f, 0.326904f, 0.340088f, 0.353027f, 0.365479f, 0.378174f, 0.391602f, 0.404541f, 0.417236f, 0.431641f,
+ 0.444336f, 0.457764f, 0.470703f, 0.484375f, 0.497803f, 0.510742f, 0.524902f, 0.537598f, 0.552246f, 0.564941f, 0.579590f, 0.592285f,
+ 0.606445f, 0.621094f, 0.634277f, 0.646973f, 0.662109f, 0.675781f, 0.689453f, 0.704102f, 0.718262f, 0.733398f, 0.842285f, 0.818848f,
+ 0.799805f, 0.784180f, 0.770996f, 0.758301f, 0.004745f, 0.014427f, 0.024277f, 0.034546f, 0.044800f, 0.055176f, 0.066040f, 0.076477f,
+ 0.087341f, 0.099060f, 0.110474f, 0.121216f, 0.132690f, 0.144165f, 0.156006f, 0.167358f, 0.179688f, 0.191284f, 0.203247f, 0.216187f,
+ 0.227905f, 0.239868f, 0.252441f, 0.264648f, 0.277100f, 0.289307f, 0.301270f, 0.314453f, 0.326660f, 0.338867f, 0.352539f, 0.364990f,
+ 0.377686f, 0.390137f, 0.403076f, 0.416016f, 0.428467f, 0.441406f, 0.453857f, 0.468262f, 0.480957f, 0.494385f, 0.507324f, 0.520020f,
+ 0.534180f, 0.547363f, 0.560059f, 0.573730f, 0.586914f, 0.601074f, 0.615234f, 0.628418f, 0.641602f, 0.656250f, 0.669434f, 0.683594f,
+ 0.697754f, 0.712402f, 0.832520f, 0.809570f, 0.792480f, 0.778320f, 0.764160f, 0.753906f, 0.004612f, 0.013840f, 0.023483f, 0.033081f,
+ 0.042999f, 0.052490f, 0.063049f, 0.073303f, 0.083801f, 0.094238f, 0.105042f, 0.115967f, 0.127319f, 0.138062f, 0.149048f, 0.160645f,
+ 0.171875f, 0.183228f, 0.194946f, 0.206665f, 0.218384f, 0.230347f, 0.241699f, 0.253906f, 0.265869f, 0.277832f, 0.290039f, 0.301758f,
+ 0.314209f, 0.326660f, 0.339111f, 0.351074f, 0.363281f, 0.375977f, 0.388428f, 0.401123f, 0.413330f, 0.426270f, 0.439453f, 0.451904f,
+ 0.464111f, 0.478027f, 0.489746f, 0.503418f, 0.515625f, 0.529297f, 0.542480f, 0.556152f, 0.569336f, 0.582031f, 0.595215f, 0.608887f,
+ 0.622559f, 0.636230f, 0.649902f, 0.663574f, 0.677246f, 0.691895f, 0.821289f, 0.802246f, 0.785645f, 0.771484f, 0.758789f, 0.748047f,
+ 0.004345f, 0.012985f, 0.022156f, 0.030884f, 0.040802f, 0.050568f, 0.060303f, 0.069946f, 0.079956f, 0.090393f, 0.100403f, 0.111084f,
+ 0.120667f, 0.131714f, 0.142700f, 0.153198f, 0.164429f, 0.175659f, 0.186523f, 0.197876f, 0.208496f, 0.220337f, 0.231567f, 0.243286f,
+ 0.254639f, 0.266113f, 0.277832f, 0.289795f, 0.301758f, 0.313477f, 0.325439f, 0.337402f, 0.349609f, 0.361328f, 0.373779f, 0.385986f,
+ 0.398193f, 0.410889f, 0.423340f, 0.435059f, 0.447998f, 0.460205f, 0.473389f, 0.486084f, 0.499023f, 0.511230f, 0.524414f, 0.537109f,
+ 0.549805f, 0.563477f, 0.576172f, 0.589355f, 0.603027f, 0.616699f, 0.629883f, 0.644531f, 0.658691f, 0.670898f, 0.811035f, 0.792969f,
+ 0.777832f, 0.764648f, 0.752441f, 0.742676f, 0.004002f, 0.012718f, 0.021210f, 0.029877f, 0.039246f, 0.048431f, 0.057281f, 0.067078f,
+ 0.076538f, 0.086121f, 0.096008f, 0.105957f, 0.115540f, 0.125732f, 0.136475f, 0.146729f, 0.157227f, 0.167236f, 0.177979f, 0.189819f,
+ 0.200195f, 0.210693f, 0.221802f, 0.232788f, 0.243896f, 0.255127f, 0.266602f, 0.278320f, 0.289062f, 0.300293f, 0.312012f, 0.323975f,
+ 0.335449f, 0.347168f, 0.359131f, 0.371094f, 0.382812f, 0.394775f, 0.406982f, 0.419434f, 0.431152f, 0.443604f, 0.455566f, 0.468506f,
+ 0.481445f, 0.493408f, 0.506348f, 0.519043f, 0.531738f, 0.544922f, 0.558105f, 0.570801f, 0.583984f, 0.597168f, 0.610352f, 0.624512f,
+ 0.637695f, 0.651855f, 0.800293f, 0.785156f, 0.770508f, 0.757812f, 0.747070f, 0.737305f, 0.003967f, 0.011940f, 0.020203f, 0.028931f,
+ 0.037109f, 0.045898f, 0.054840f, 0.063477f, 0.073059f, 0.082214f, 0.090942f, 0.100647f, 0.110535f, 0.120178f, 0.129639f, 0.139648f,
+ 0.149902f, 0.160156f, 0.170044f, 0.180786f, 0.190674f, 0.201416f, 0.211792f, 0.222412f, 0.233521f, 0.244751f, 0.255615f, 0.266113f,
+ 0.276855f, 0.288574f, 0.299561f, 0.311279f, 0.322266f, 0.333984f, 0.344727f, 0.356934f, 0.368164f, 0.379395f, 0.390869f, 0.403076f,
+ 0.415283f, 0.427246f, 0.439453f, 0.451172f, 0.464111f, 0.476807f, 0.488281f, 0.500977f, 0.513672f, 0.526367f, 0.538574f, 0.551758f,
+ 0.564453f, 0.577637f, 0.590820f, 0.604492f, 0.618164f, 0.631836f, 0.790039f, 0.775879f, 0.763184f, 0.750977f, 0.740723f, 0.731445f,
+ 0.003679f, 0.011749f, 0.019135f, 0.027237f, 0.035431f, 0.043884f, 0.052399f, 0.060577f, 0.069153f, 0.077881f, 0.086731f, 0.095947f,
+ 0.104797f, 0.114380f, 0.123535f, 0.133057f, 0.142700f, 0.152588f, 0.162231f, 0.171753f, 0.182129f, 0.192261f, 0.202026f, 0.212524f,
+ 0.222900f, 0.233643f, 0.243896f, 0.254395f, 0.264893f, 0.276123f, 0.286621f, 0.297119f, 0.308105f, 0.319336f, 0.331299f, 0.341553f,
+ 0.353027f, 0.364258f, 0.375977f, 0.387451f, 0.399414f, 0.410645f, 0.422607f, 0.434814f, 0.445801f, 0.458984f, 0.470703f, 0.482910f,
+ 0.495361f, 0.508301f, 0.520020f, 0.532227f, 0.545410f, 0.558594f, 0.570801f, 0.584961f, 0.597656f, 0.611816f, 0.778809f, 0.768066f,
+ 0.754883f, 0.743652f, 0.733887f, 0.725098f, 0.003525f, 0.010956f, 0.018433f, 0.026260f, 0.033295f, 0.041870f, 0.049377f, 0.057709f,
+ 0.065735f, 0.074463f, 0.082764f, 0.091736f, 0.099976f, 0.108582f, 0.118103f, 0.126465f, 0.135742f, 0.144775f, 0.154175f, 0.164307f,
+ 0.173218f, 0.182983f, 0.192505f, 0.202759f, 0.212646f, 0.221924f, 0.232910f, 0.242188f, 0.252930f, 0.262939f, 0.273926f, 0.284180f,
+ 0.294922f, 0.305420f, 0.316162f, 0.327637f, 0.338867f, 0.349609f, 0.361084f, 0.371826f, 0.382812f, 0.395020f, 0.406494f, 0.417725f,
+ 0.429688f, 0.441406f, 0.452637f, 0.465088f, 0.477783f, 0.489258f, 0.501953f, 0.514160f, 0.527344f, 0.539062f, 0.551758f, 0.564941f,
+ 0.578125f, 0.591797f, 0.768555f, 0.759277f, 0.748047f, 0.736816f, 0.728027f, 0.718750f, 0.003363f, 0.010353f, 0.017548f, 0.024765f,
+ 0.032196f, 0.039673f, 0.046936f, 0.054565f, 0.062561f, 0.070496f, 0.078308f, 0.086731f, 0.094910f, 0.103333f, 0.111633f, 0.120422f,
+ 0.129150f, 0.137695f, 0.146973f, 0.155762f, 0.164673f, 0.173950f, 0.183228f, 0.193359f, 0.201782f, 0.212036f, 0.221436f, 0.231323f,
+ 0.241699f, 0.251221f, 0.261719f, 0.271729f, 0.281494f, 0.291992f, 0.302734f, 0.312988f, 0.323730f, 0.334961f, 0.345459f, 0.357666f,
+ 0.367432f, 0.378662f, 0.389893f, 0.401855f, 0.412842f, 0.424316f, 0.435791f, 0.447266f, 0.459473f, 0.471436f, 0.482910f, 0.495605f,
+ 0.507324f, 0.520508f, 0.533203f, 0.545898f, 0.558594f, 0.570801f, 0.757812f, 0.750488f, 0.740234f, 0.729980f, 0.720703f, 0.712402f,
+ 0.003254f, 0.010048f, 0.016815f, 0.023453f, 0.030609f, 0.037537f, 0.044617f, 0.051971f, 0.059265f, 0.066833f, 0.074280f, 0.082153f,
+ 0.089905f, 0.097717f, 0.106018f, 0.113770f, 0.122131f, 0.131104f, 0.139282f, 0.147705f, 0.155762f, 0.165161f, 0.173950f, 0.183228f,
+ 0.192139f, 0.200928f, 0.210693f, 0.220093f, 0.229736f, 0.239258f, 0.248657f, 0.259277f, 0.268799f, 0.279053f, 0.288574f, 0.299561f,
+ 0.309814f, 0.319580f, 0.330322f, 0.340820f, 0.352783f, 0.362549f, 0.374023f, 0.385010f, 0.395752f, 0.407471f, 0.418701f, 0.429688f,
+ 0.441650f, 0.453125f, 0.465088f, 0.477539f, 0.489014f, 0.500977f, 0.513184f, 0.526855f, 0.539062f, 0.552246f, 0.747559f, 0.741699f,
+ 0.731934f, 0.722656f, 0.714355f, 0.707031f, 0.003345f, 0.009262f, 0.015900f, 0.022614f, 0.029282f, 0.035522f, 0.042633f, 0.048981f,
+ 0.056000f, 0.063110f, 0.070801f, 0.077454f, 0.084839f, 0.092590f, 0.100281f, 0.107849f, 0.116089f, 0.123169f, 0.131348f, 0.139648f,
+ 0.148193f, 0.156616f, 0.164795f, 0.173584f, 0.182617f, 0.191284f, 0.200073f, 0.208740f, 0.218140f, 0.227417f, 0.236694f, 0.246338f,
+ 0.255859f, 0.265381f, 0.275146f, 0.285889f, 0.294922f, 0.305420f, 0.315918f, 0.325928f, 0.336670f, 0.347412f, 0.358154f, 0.368652f,
+ 0.378662f, 0.390381f, 0.402100f, 0.412842f, 0.424316f, 0.435059f, 0.447021f, 0.458984f, 0.470459f, 0.482422f, 0.494873f, 0.508301f,
+ 0.520020f, 0.532227f, 0.737305f, 0.732910f, 0.723633f, 0.715820f, 0.708008f, 0.700195f, 0.003195f, 0.009010f, 0.015137f, 0.021225f,
+ 0.027466f, 0.033844f, 0.040161f, 0.046417f, 0.053497f, 0.059875f, 0.066711f, 0.073425f, 0.080505f, 0.087280f, 0.094788f, 0.102173f,
+ 0.109070f, 0.117004f, 0.124634f, 0.132446f, 0.139893f, 0.147705f, 0.155884f, 0.163940f, 0.172729f, 0.180908f, 0.189697f, 0.198242f,
+ 0.206665f, 0.215820f, 0.225220f, 0.233765f, 0.243408f, 0.251953f, 0.262207f, 0.271484f, 0.281494f, 0.291260f, 0.300537f, 0.311035f,
+ 0.320801f, 0.332520f, 0.341797f, 0.352051f, 0.362305f, 0.373535f, 0.384521f, 0.395264f, 0.406494f, 0.417480f, 0.429443f, 0.440430f,
+ 0.451904f, 0.463867f, 0.476074f, 0.487793f, 0.499268f, 0.513184f, 0.726562f, 0.723633f, 0.716309f, 0.708496f, 0.700684f, 0.694336f,
+ 0.002859f, 0.008507f, 0.014366f, 0.020203f, 0.026123f, 0.031891f, 0.038025f, 0.044281f, 0.050354f, 0.056519f, 0.062683f, 0.069275f,
+ 0.075195f, 0.082458f, 0.088806f, 0.095947f, 0.102783f, 0.110046f, 0.117065f, 0.124878f, 0.132080f, 0.139282f, 0.146851f, 0.154907f,
+ 0.162598f, 0.171265f, 0.178833f, 0.187500f, 0.195435f, 0.204590f, 0.213013f, 0.221680f, 0.231079f, 0.239502f, 0.248047f, 0.258301f,
+ 0.267334f, 0.277100f, 0.286133f, 0.296387f, 0.306641f, 0.316162f, 0.326416f, 0.336426f, 0.346924f, 0.357422f, 0.367188f, 0.378418f,
+ 0.389160f, 0.400391f, 0.411865f, 0.422852f, 0.433594f, 0.445557f, 0.457520f, 0.468994f, 0.481445f, 0.493408f, 0.715332f, 0.715332f,
+ 0.708984f, 0.700684f, 0.693848f, 0.687988f, 0.002701f, 0.008080f, 0.013718f, 0.019058f, 0.024582f, 0.030197f, 0.035675f, 0.041748f,
+ 0.047302f, 0.053589f, 0.059082f, 0.065308f, 0.071777f, 0.077576f, 0.084106f, 0.090332f, 0.097107f, 0.103577f, 0.110046f, 0.117493f,
+ 0.124146f, 0.131470f, 0.138550f, 0.145508f, 0.153564f, 0.161377f, 0.169067f, 0.176880f, 0.184814f, 0.192627f, 0.201294f, 0.209717f,
+ 0.218140f, 0.226929f, 0.235229f, 0.245117f, 0.253418f, 0.262939f, 0.272705f, 0.281738f, 0.290771f, 0.300781f, 0.310791f, 0.321289f,
+ 0.330566f, 0.341064f, 0.351562f, 0.361572f, 0.372559f, 0.382568f, 0.393066f, 0.405273f, 0.415771f, 0.426758f, 0.438721f, 0.450439f,
+ 0.461670f, 0.474121f, 0.704102f, 0.706543f, 0.700195f, 0.693359f, 0.687012f, 0.681152f, 0.002546f, 0.007771f, 0.012985f, 0.017975f,
+ 0.023392f, 0.028976f, 0.034180f, 0.039368f, 0.044556f, 0.050110f, 0.055847f, 0.061218f, 0.066895f, 0.072815f, 0.078674f, 0.085083f,
+ 0.091309f, 0.097168f, 0.103516f, 0.110107f, 0.116821f, 0.123413f, 0.130371f, 0.137329f, 0.144165f, 0.151733f, 0.158813f, 0.166382f,
+ 0.174438f, 0.182129f, 0.190063f, 0.197510f, 0.206055f, 0.214355f, 0.222778f, 0.231812f, 0.240723f, 0.249023f, 0.258789f, 0.267578f,
+ 0.276855f, 0.285889f, 0.295654f, 0.305420f, 0.315430f, 0.324463f, 0.334961f, 0.345215f, 0.354492f, 0.365234f, 0.376221f, 0.387451f,
+ 0.398926f, 0.409424f, 0.419678f, 0.432129f, 0.443848f, 0.455566f, 0.693848f, 0.697266f, 0.691895f, 0.686523f, 0.680176f, 0.674805f,
+ 0.002542f, 0.007271f, 0.012337f, 0.017181f, 0.021744f, 0.026840f, 0.031555f, 0.037231f, 0.042236f, 0.046906f, 0.051941f, 0.057709f,
+ 0.063049f, 0.068542f, 0.073853f, 0.079712f, 0.085266f, 0.091064f, 0.096985f, 0.103027f, 0.109009f, 0.115417f, 0.122192f, 0.128540f,
+ 0.135132f, 0.141846f, 0.148926f, 0.156250f, 0.163696f, 0.171387f, 0.178223f, 0.186035f, 0.194580f, 0.202271f, 0.210327f, 0.218994f,
+ 0.227173f, 0.235596f, 0.244385f, 0.252930f, 0.262451f, 0.271240f, 0.280762f, 0.290771f, 0.299805f, 0.309082f, 0.318359f, 0.329102f,
+ 0.338623f, 0.348633f, 0.358643f, 0.370117f, 0.379639f, 0.390869f, 0.401611f, 0.413330f, 0.425293f, 0.436523f, 0.682129f, 0.688477f,
+ 0.684082f, 0.678711f, 0.673340f, 0.667969f, 0.002300f, 0.007076f, 0.011505f, 0.016251f, 0.020401f, 0.025665f, 0.029816f, 0.034790f,
+ 0.039368f, 0.044159f, 0.048798f, 0.053955f, 0.059174f, 0.064148f, 0.069153f, 0.074463f, 0.079346f, 0.085266f, 0.090759f, 0.096191f,
+ 0.102112f, 0.108032f, 0.114075f, 0.120117f, 0.126587f, 0.133057f, 0.139648f, 0.146240f, 0.153442f, 0.160400f, 0.167725f, 0.174683f,
+ 0.182739f, 0.190308f, 0.198120f, 0.206177f, 0.214355f, 0.222656f, 0.230713f, 0.239258f, 0.248413f, 0.257080f, 0.265869f, 0.274658f,
+ 0.284424f, 0.292725f, 0.302490f, 0.313232f, 0.321777f, 0.331787f, 0.341797f, 0.352295f, 0.363281f, 0.373535f, 0.383545f, 0.395264f,
+ 0.405762f, 0.416992f, 0.671387f, 0.679688f, 0.675293f, 0.670898f, 0.666016f, 0.661133f, 0.002104f, 0.006474f, 0.010506f, 0.015099f,
+ 0.018875f, 0.023911f, 0.028534f, 0.032715f, 0.036652f, 0.041290f, 0.046021f, 0.050171f, 0.054535f, 0.059570f, 0.064575f, 0.069458f,
+ 0.074341f, 0.079346f, 0.084351f, 0.089844f, 0.095032f, 0.100830f, 0.106628f, 0.112122f, 0.117859f, 0.124084f, 0.130249f, 0.136841f,
+ 0.143188f, 0.149780f, 0.157349f, 0.163940f, 0.171021f, 0.178345f, 0.186279f, 0.193848f, 0.201172f, 0.209717f, 0.217529f, 0.225464f,
+ 0.233765f, 0.242676f, 0.251221f, 0.260254f, 0.268311f, 0.278076f, 0.287109f, 0.296143f, 0.305908f, 0.315674f, 0.325195f, 0.335449f,
+ 0.344971f, 0.355469f, 0.365967f, 0.377441f, 0.387939f, 0.398193f, 0.660645f, 0.670410f, 0.667969f, 0.663086f, 0.659180f, 0.654785f,
+ 0.002085f, 0.006306f, 0.010506f, 0.014107f, 0.018448f, 0.022293f, 0.026215f, 0.029953f, 0.034515f, 0.038391f, 0.042786f, 0.046844f,
+ 0.051361f, 0.055573f, 0.059784f, 0.064331f, 0.068970f, 0.073425f, 0.078430f, 0.083313f, 0.088318f, 0.093567f, 0.098816f, 0.104126f,
+ 0.109924f, 0.115662f, 0.121521f, 0.127197f, 0.133545f, 0.139771f, 0.146729f, 0.153076f, 0.160278f, 0.166992f, 0.174316f, 0.181274f,
+ 0.188965f, 0.196045f, 0.204468f, 0.212036f, 0.220459f, 0.228638f, 0.237183f, 0.245483f, 0.254150f, 0.262451f, 0.271484f, 0.281250f,
+ 0.290283f, 0.299561f, 0.308350f, 0.318115f, 0.328369f, 0.337158f, 0.349121f, 0.358887f, 0.370117f, 0.380615f, 0.649414f, 0.661133f,
+ 0.659668f, 0.655762f, 0.651855f, 0.647949f, 0.001922f, 0.005867f, 0.009399f, 0.013565f, 0.017380f, 0.020859f, 0.024551f, 0.028442f,
+ 0.032318f, 0.035980f, 0.039551f, 0.043488f, 0.047333f, 0.051239f, 0.055573f, 0.059875f, 0.063660f, 0.067810f, 0.072876f, 0.077087f,
+ 0.081726f, 0.086304f, 0.091370f, 0.096863f, 0.101746f, 0.107483f, 0.112732f, 0.117920f, 0.124329f, 0.130005f, 0.136108f, 0.142822f,
+ 0.149170f, 0.155396f, 0.162598f, 0.169434f, 0.176636f, 0.183838f, 0.191772f, 0.198975f, 0.206665f, 0.214478f, 0.222290f, 0.230835f,
+ 0.239258f, 0.247803f, 0.256836f, 0.264893f, 0.274414f, 0.283203f, 0.292725f, 0.301758f, 0.311035f, 0.321289f, 0.332275f, 0.340820f,
+ 0.351562f, 0.363037f, 0.637695f, 0.652832f, 0.651367f, 0.647949f, 0.644531f, 0.641602f, 0.002052f, 0.005253f, 0.009117f, 0.012482f,
+ 0.016113f, 0.019302f, 0.022842f, 0.026230f, 0.029831f, 0.033447f, 0.036682f, 0.040588f, 0.044189f, 0.047333f, 0.051178f, 0.055267f,
+ 0.058807f, 0.062683f, 0.067200f, 0.070984f, 0.075195f, 0.079895f, 0.084534f, 0.088806f, 0.093933f, 0.098999f, 0.104309f, 0.109619f,
+ 0.114807f, 0.120422f, 0.126587f, 0.132080f, 0.138550f, 0.144775f, 0.151245f, 0.157837f, 0.164551f, 0.171387f, 0.178467f, 0.186157f,
+ 0.193359f, 0.201294f, 0.208740f, 0.216797f, 0.224854f, 0.233398f, 0.241211f, 0.250000f, 0.258545f, 0.267822f, 0.276855f, 0.286133f,
+ 0.295410f, 0.304932f, 0.314697f, 0.324463f, 0.334229f, 0.344238f, 0.626953f, 0.642578f, 0.643066f, 0.641113f, 0.637695f, 0.634277f,
+ 0.001711f, 0.005424f, 0.008347f, 0.012024f, 0.014977f, 0.018066f, 0.021500f, 0.024399f, 0.027756f, 0.030869f, 0.034058f, 0.037048f,
+ 0.040558f, 0.044006f, 0.046906f, 0.050690f, 0.054169f, 0.057983f, 0.061584f, 0.065247f, 0.069336f, 0.073425f, 0.077576f, 0.082092f,
+ 0.086670f, 0.091064f, 0.095886f, 0.101196f, 0.105957f, 0.111267f, 0.116943f, 0.122559f, 0.128174f, 0.133789f, 0.140259f, 0.146118f,
+ 0.153076f, 0.159424f, 0.166016f, 0.173462f, 0.180542f, 0.187744f, 0.195435f, 0.203003f, 0.209961f, 0.218994f, 0.226562f, 0.234619f,
+ 0.243286f, 0.251709f, 0.260742f, 0.269531f, 0.277832f, 0.287354f, 0.297363f, 0.306885f, 0.316406f, 0.326660f, 0.615234f, 0.633789f,
+ 0.634277f, 0.632812f, 0.630371f, 0.626953f, 0.001721f, 0.004829f, 0.008034f, 0.010857f, 0.013893f, 0.016953f, 0.019806f, 0.022705f,
+ 0.025589f, 0.028793f, 0.031616f, 0.034180f, 0.036926f, 0.039978f, 0.043213f, 0.046356f, 0.049744f, 0.052887f, 0.056305f, 0.059906f,
+ 0.063416f, 0.067322f, 0.070862f, 0.075134f, 0.079285f, 0.083435f, 0.088074f, 0.092712f, 0.097534f, 0.102173f, 0.107544f, 0.112305f,
+ 0.118225f, 0.123657f, 0.129272f, 0.135376f, 0.141602f, 0.147705f, 0.153931f, 0.160889f, 0.167847f, 0.174683f, 0.181885f, 0.189209f,
+ 0.196533f, 0.204224f, 0.212524f, 0.219727f, 0.228271f, 0.236572f, 0.245483f, 0.253418f, 0.261719f, 0.270996f, 0.280029f, 0.289307f,
+ 0.300537f, 0.309326f, 0.604004f, 0.625000f, 0.626953f, 0.625000f, 0.622559f, 0.620117f, 0.001624f, 0.004730f, 0.007412f, 0.010300f,
+ 0.013199f, 0.015717f, 0.018448f, 0.020935f, 0.023163f, 0.026138f, 0.028687f, 0.031204f, 0.033875f, 0.036743f, 0.039825f, 0.042389f,
+ 0.045166f, 0.048523f, 0.051422f, 0.054535f, 0.057953f, 0.061249f, 0.064880f, 0.068542f, 0.072388f, 0.076355f, 0.080505f, 0.084534f,
+ 0.089294f, 0.093750f, 0.098389f, 0.103210f, 0.108337f, 0.113647f, 0.118896f, 0.124817f, 0.130737f, 0.135986f, 0.142212f, 0.148560f,
+ 0.155151f, 0.162109f, 0.168579f, 0.175415f, 0.183105f, 0.190552f, 0.197998f, 0.205322f, 0.213623f, 0.221436f, 0.229370f, 0.237915f,
+ 0.246216f, 0.254883f, 0.264160f, 0.273438f, 0.282471f, 0.292236f, 0.593262f, 0.615723f, 0.618164f, 0.617188f, 0.615234f, 0.612793f,
+ 0.001355f, 0.004463f, 0.007061f, 0.009506f, 0.011612f, 0.014381f, 0.016830f, 0.019394f, 0.021576f, 0.023697f, 0.026428f, 0.028778f,
+ 0.030975f, 0.033386f, 0.035950f, 0.038513f, 0.041260f, 0.044067f, 0.046967f, 0.049622f, 0.052612f, 0.055847f, 0.059052f, 0.062164f,
+ 0.065918f, 0.069397f, 0.073242f, 0.077271f, 0.081055f, 0.085327f, 0.089661f, 0.094177f, 0.098877f, 0.103455f, 0.108582f, 0.113647f,
+ 0.119812f, 0.125000f, 0.130981f, 0.137085f, 0.142944f, 0.149414f, 0.156006f, 0.162354f, 0.169434f, 0.176514f, 0.183716f, 0.191284f,
+ 0.198975f, 0.206421f, 0.214844f, 0.222412f, 0.231323f, 0.238647f, 0.247437f, 0.256592f, 0.265625f, 0.276367f, 0.581055f, 0.606445f,
+ 0.609863f, 0.608887f, 0.607910f, 0.606445f, 0.001413f, 0.004128f, 0.006180f, 0.008781f, 0.010994f, 0.013496f, 0.015427f, 0.017654f,
+ 0.019684f, 0.021881f, 0.024139f, 0.025879f, 0.028137f, 0.030334f, 0.032471f, 0.034821f, 0.037354f, 0.039642f, 0.042236f, 0.044708f,
+ 0.047394f, 0.050079f, 0.053223f, 0.056244f, 0.059479f, 0.062622f, 0.066223f, 0.069946f, 0.073608f, 0.077209f, 0.081604f, 0.085632f,
+ 0.089722f, 0.094360f, 0.098999f, 0.103943f, 0.108826f, 0.114319f, 0.119568f, 0.125122f, 0.131104f, 0.137085f, 0.143433f, 0.150024f,
+ 0.156494f, 0.163330f, 0.170044f, 0.177490f, 0.184326f, 0.191895f, 0.199707f, 0.207764f, 0.215698f, 0.223755f, 0.231812f, 0.240845f,
+ 0.249756f, 0.258789f, 0.568848f, 0.598145f, 0.601562f, 0.600586f, 0.600586f, 0.599121f, 0.001182f, 0.003773f, 0.005970f, 0.008293f,
+ 0.010277f, 0.012512f, 0.014030f, 0.016129f, 0.017929f, 0.019791f, 0.021683f, 0.023590f, 0.025452f, 0.027328f, 0.029404f, 0.031677f,
+ 0.033539f, 0.035583f, 0.037903f, 0.040314f, 0.042877f, 0.045319f, 0.048126f, 0.050690f, 0.053436f, 0.056519f, 0.059723f, 0.062744f,
+ 0.066284f, 0.069702f, 0.073608f, 0.077209f, 0.081055f, 0.085754f, 0.089783f, 0.094421f, 0.099060f, 0.103821f, 0.109192f, 0.114563f,
+ 0.119934f, 0.125488f, 0.131104f, 0.137695f, 0.144043f, 0.149780f, 0.156738f, 0.163940f, 0.170654f, 0.177856f, 0.185181f, 0.192871f,
+ 0.200439f, 0.208740f, 0.216675f, 0.225342f, 0.233521f, 0.242554f, 0.557617f, 0.587891f, 0.592285f, 0.592773f, 0.592285f, 0.592285f,
+ 0.001198f, 0.003677f, 0.005547f, 0.007561f, 0.009468f, 0.011253f, 0.012833f, 0.014465f, 0.016205f, 0.017792f, 0.019394f, 0.021240f,
+ 0.022751f, 0.024475f, 0.026260f, 0.028015f, 0.030136f, 0.031708f, 0.034088f, 0.036102f, 0.038361f, 0.040497f, 0.042816f, 0.045288f,
+ 0.047882f, 0.050476f, 0.053284f, 0.056183f, 0.059174f, 0.062500f, 0.065796f, 0.069153f, 0.072998f, 0.076904f, 0.080994f, 0.085083f,
+ 0.089478f, 0.094116f, 0.098633f, 0.103394f, 0.108704f, 0.113953f, 0.119934f, 0.125366f, 0.131348f, 0.137329f, 0.143555f, 0.150391f,
+ 0.157227f, 0.163818f, 0.170776f, 0.178467f, 0.185791f, 0.193359f, 0.201538f, 0.209717f, 0.218018f, 0.226807f, 0.544922f, 0.578613f,
+ 0.583984f, 0.584961f, 0.585449f, 0.584473f, 0.001067f, 0.003101f, 0.004974f, 0.006855f, 0.008522f, 0.009949f, 0.011635f, 0.012985f,
+ 0.014595f, 0.016052f, 0.017685f, 0.019012f, 0.020264f, 0.021851f, 0.023346f, 0.025146f, 0.026688f, 0.028336f, 0.030304f, 0.031860f,
+ 0.034119f, 0.035889f, 0.038025f, 0.040283f, 0.042450f, 0.044952f, 0.047302f, 0.050049f, 0.052765f, 0.055908f, 0.058594f, 0.061859f,
+ 0.064880f, 0.068481f, 0.072327f, 0.076172f, 0.080200f, 0.084290f, 0.088684f, 0.093262f, 0.098145f, 0.102905f, 0.108337f, 0.113708f,
+ 0.119080f, 0.125000f, 0.131348f, 0.137329f, 0.143921f, 0.150391f, 0.157593f, 0.164551f, 0.171753f, 0.179077f, 0.186768f, 0.194702f,
+ 0.203003f, 0.210815f, 0.534180f, 0.569336f, 0.575684f, 0.577637f, 0.577637f, 0.577148f, 0.001196f, 0.003178f, 0.004601f, 0.006241f,
+ 0.007782f, 0.009262f, 0.010391f, 0.011795f, 0.012955f, 0.014198f, 0.015518f, 0.016785f, 0.018097f, 0.019409f, 0.020782f, 0.022247f,
+ 0.023544f, 0.025269f, 0.026749f, 0.028152f, 0.030045f, 0.031555f, 0.033630f, 0.035645f, 0.037567f, 0.039642f, 0.041992f, 0.044281f,
+ 0.046692f, 0.049042f, 0.052094f, 0.054779f, 0.057831f, 0.060760f, 0.064209f, 0.067627f, 0.071228f, 0.075256f, 0.079224f, 0.083557f,
+ 0.087891f, 0.092468f, 0.097168f, 0.102356f, 0.107605f, 0.113098f, 0.119019f, 0.124878f, 0.130859f, 0.137451f, 0.144287f, 0.150635f,
+ 0.157471f, 0.164917f, 0.171997f, 0.179932f, 0.187378f, 0.196899f, 0.521973f, 0.560547f, 0.566895f, 0.569824f, 0.570312f, 0.568848f,
+ 0.001242f, 0.002674f, 0.004421f, 0.005573f, 0.006882f, 0.008354f, 0.009491f, 0.010559f, 0.011406f, 0.012695f, 0.013893f, 0.014908f,
+ 0.015854f, 0.017044f, 0.018234f, 0.019501f, 0.020752f, 0.022003f, 0.023254f, 0.024689f, 0.026154f, 0.027802f, 0.029434f, 0.031113f,
+ 0.032898f, 0.034668f, 0.036774f, 0.038910f, 0.040802f, 0.043030f, 0.045593f, 0.048065f, 0.050873f, 0.053680f, 0.056458f, 0.059692f,
+ 0.062866f, 0.066467f, 0.069946f, 0.074036f, 0.077942f, 0.082275f, 0.086731f, 0.091614f, 0.096313f, 0.101562f, 0.106934f, 0.112671f,
+ 0.118591f, 0.124634f, 0.130859f, 0.137207f, 0.144043f, 0.151123f, 0.157593f, 0.165283f, 0.173218f, 0.180664f, 0.510254f, 0.550781f,
+ 0.558105f, 0.561035f, 0.562012f, 0.562012f, 0.000842f, 0.002552f, 0.003769f, 0.005333f, 0.006149f, 0.007298f, 0.008362f, 0.009224f,
+ 0.010254f, 0.011230f, 0.012108f, 0.013092f, 0.014000f, 0.014992f, 0.016006f, 0.016953f, 0.017990f, 0.019196f, 0.020142f, 0.021622f,
+ 0.022827f, 0.024216f, 0.025513f, 0.026993f, 0.028564f, 0.030212f, 0.032013f, 0.033813f, 0.035706f, 0.037598f, 0.039703f, 0.041840f,
+ 0.044159f, 0.046539f, 0.049347f, 0.052155f, 0.055084f, 0.058228f, 0.061554f, 0.065002f, 0.068909f, 0.072693f, 0.076599f, 0.081238f,
+ 0.085388f, 0.090515f, 0.095764f, 0.100891f, 0.106689f, 0.112366f, 0.118103f, 0.124634f, 0.130859f, 0.137573f, 0.144287f, 0.151855f,
+ 0.158447f, 0.166260f, 0.498535f, 0.541992f, 0.549805f, 0.553711f, 0.554199f, 0.554688f, 0.000874f, 0.002186f, 0.003445f, 0.004807f,
+ 0.005562f, 0.006607f, 0.007378f, 0.008102f, 0.008919f, 0.009666f, 0.010513f, 0.011131f, 0.012039f, 0.012848f, 0.013779f, 0.014671f,
+ 0.015465f, 0.016464f, 0.017517f, 0.018585f, 0.019730f, 0.020798f, 0.022018f, 0.023300f, 0.024612f, 0.026093f, 0.027374f, 0.029022f,
+ 0.030624f, 0.032440f, 0.034180f, 0.036285f, 0.038116f, 0.040344f, 0.042725f, 0.045349f, 0.047913f, 0.050476f, 0.053406f, 0.056488f,
+ 0.059998f, 0.063354f, 0.067383f, 0.071289f, 0.075562f, 0.079834f, 0.084656f, 0.089478f, 0.094849f, 0.100342f, 0.106140f, 0.111877f,
+ 0.118042f, 0.124573f, 0.130981f, 0.137451f, 0.144653f, 0.152588f, 0.486816f, 0.531738f, 0.541016f, 0.545410f, 0.547363f, 0.546875f,
+ 0.000667f, 0.002001f, 0.003244f, 0.003895f, 0.004936f, 0.005608f, 0.006477f, 0.006901f, 0.007648f, 0.008354f, 0.009132f, 0.009766f,
+ 0.010490f, 0.011177f, 0.011780f, 0.012543f, 0.013420f, 0.014084f, 0.015045f, 0.015961f, 0.016876f, 0.017822f, 0.018768f, 0.019958f,
+ 0.021255f, 0.022232f, 0.023560f, 0.024780f, 0.026108f, 0.027634f, 0.029221f, 0.030762f, 0.032684f, 0.034576f, 0.036621f, 0.038605f,
+ 0.040985f, 0.043488f, 0.046021f, 0.049042f, 0.051727f, 0.054901f, 0.058441f, 0.061981f, 0.065552f, 0.069885f, 0.074097f, 0.078857f,
+ 0.083923f, 0.088623f, 0.094360f, 0.099854f, 0.105957f, 0.111694f, 0.118164f, 0.124817f, 0.131836f, 0.138794f, 0.474365f, 0.522949f,
+ 0.532227f, 0.536621f, 0.538574f, 0.539062f, 0.000876f, 0.002020f, 0.002857f, 0.003855f, 0.004436f, 0.005009f, 0.005482f, 0.006130f,
+ 0.006588f, 0.007084f, 0.007656f, 0.008286f, 0.008949f, 0.009506f, 0.010025f, 0.010803f, 0.011444f, 0.012047f, 0.012802f, 0.013512f,
+ 0.014305f, 0.015282f, 0.016052f, 0.016846f, 0.017914f, 0.018829f, 0.019882f, 0.021027f, 0.022232f, 0.023453f, 0.024689f, 0.026169f,
+ 0.027573f, 0.029327f, 0.031036f, 0.032806f, 0.034882f, 0.036743f, 0.039032f, 0.041626f, 0.044312f, 0.046936f, 0.050018f, 0.053253f,
+ 0.056610f, 0.060272f, 0.064392f, 0.068542f, 0.072937f, 0.078003f, 0.082886f, 0.088318f, 0.093933f, 0.099670f, 0.106140f, 0.112000f,
+ 0.118713f, 0.125732f, 0.463135f, 0.513672f, 0.524414f, 0.528809f, 0.530762f, 0.532227f, 0.000573f, 0.001698f, 0.002670f, 0.003082f,
+ 0.003735f, 0.004318f, 0.004673f, 0.005161f, 0.005779f, 0.006203f, 0.006565f, 0.007015f, 0.007591f, 0.007965f, 0.008583f, 0.009094f,
+ 0.009491f, 0.010239f, 0.010780f, 0.011353f, 0.012047f, 0.012787f, 0.013504f, 0.014206f, 0.015060f, 0.015915f, 0.016708f, 0.017685f,
+ 0.018677f, 0.019653f, 0.020828f, 0.021866f, 0.023224f, 0.024445f, 0.025818f, 0.027557f, 0.029114f, 0.030991f, 0.032928f, 0.035034f,
+ 0.037201f, 0.039581f, 0.042328f, 0.045166f, 0.048157f, 0.051392f, 0.054962f, 0.058685f, 0.062988f, 0.067444f, 0.072021f, 0.077148f,
+ 0.082520f, 0.088196f, 0.093750f, 0.100403f, 0.106201f, 0.112976f, 0.450928f, 0.503906f, 0.515137f, 0.520020f, 0.522949f, 0.524414f,
+ 0.000643f, 0.001637f, 0.002197f, 0.002800f, 0.003376f, 0.003613f, 0.003914f, 0.004391f, 0.004742f, 0.005150f, 0.005466f, 0.005924f,
+ 0.006344f, 0.006645f, 0.007046f, 0.007591f, 0.008118f, 0.008560f, 0.008934f, 0.009529f, 0.010147f, 0.010651f, 0.011276f, 0.011787f,
+ 0.012543f, 0.013229f, 0.013916f, 0.014740f, 0.015564f, 0.016388f, 0.017258f, 0.018188f, 0.019257f, 0.020355f, 0.021729f, 0.022766f,
+ 0.024277f, 0.025696f, 0.027237f, 0.029022f, 0.030945f, 0.033020f, 0.035248f, 0.037689f, 0.040405f, 0.043182f, 0.046295f, 0.049866f,
+ 0.053528f, 0.057526f, 0.061920f, 0.066284f, 0.071716f, 0.077209f, 0.082703f, 0.088196f, 0.094177f, 0.101074f, 0.438965f, 0.494629f,
+ 0.507324f, 0.512207f, 0.515137f, 0.516113f, 0.000484f, 0.001272f, 0.001968f, 0.002327f, 0.002573f, 0.003054f, 0.003338f, 0.003660f,
+ 0.003906f, 0.004303f, 0.004658f, 0.004921f, 0.005222f, 0.005547f, 0.005878f, 0.006290f, 0.006542f, 0.007015f, 0.007442f, 0.007851f,
+ 0.008339f, 0.008713f, 0.009247f, 0.009811f, 0.010345f, 0.010849f, 0.011490f, 0.012123f, 0.012733f, 0.013428f, 0.014183f, 0.014961f,
+ 0.015839f, 0.016815f, 0.017731f, 0.018768f, 0.019821f, 0.021072f, 0.022385f, 0.023727f, 0.025345f, 0.027084f, 0.028946f, 0.030914f,
+ 0.033295f, 0.035614f, 0.038513f, 0.041473f, 0.044678f, 0.048462f, 0.052338f, 0.056671f, 0.061310f, 0.066101f, 0.071533f, 0.077148f,
+ 0.083069f, 0.089172f, 0.427246f, 0.485352f, 0.498535f, 0.503906f, 0.508301f, 0.509766f, 0.000416f, 0.001121f, 0.001410f, 0.001959f,
+ 0.002159f, 0.002558f, 0.002724f, 0.002939f, 0.003220f, 0.003447f, 0.003733f, 0.003944f, 0.004219f, 0.004578f, 0.004810f, 0.005100f,
+ 0.005402f, 0.005783f, 0.006077f, 0.006382f, 0.006729f, 0.007141f, 0.007526f, 0.007965f, 0.008354f, 0.008858f, 0.009300f, 0.009789f,
+ 0.010452f, 0.010986f, 0.011658f, 0.012131f, 0.012833f, 0.013702f, 0.014435f, 0.015266f, 0.016113f, 0.017136f, 0.018143f, 0.019241f,
+ 0.020493f, 0.021820f, 0.023346f, 0.025085f, 0.027023f, 0.028976f, 0.031174f, 0.033966f, 0.036743f, 0.039856f, 0.043396f, 0.047180f,
+ 0.051605f, 0.056152f, 0.061127f, 0.066284f, 0.072021f, 0.078247f, 0.415283f, 0.475586f, 0.490234f, 0.496338f, 0.499756f, 0.501953f,
+ 0.000493f, 0.001126f, 0.001391f, 0.001574f, 0.001786f, 0.002073f, 0.002188f, 0.002417f, 0.002657f, 0.002785f, 0.002964f, 0.003189f,
+ 0.003384f, 0.003687f, 0.003859f, 0.004124f, 0.004330f, 0.004555f, 0.004890f, 0.005119f, 0.005451f, 0.005749f, 0.006054f, 0.006348f,
+ 0.006683f, 0.007050f, 0.007458f, 0.007889f, 0.008339f, 0.008751f, 0.009323f, 0.009766f, 0.010353f, 0.010887f, 0.011520f, 0.012192f,
+ 0.012932f, 0.013748f, 0.014542f, 0.015434f, 0.016434f, 0.017471f, 0.018723f, 0.019989f, 0.021500f, 0.023117f, 0.024948f, 0.027100f,
+ 0.029770f, 0.032166f, 0.035248f, 0.038696f, 0.042633f, 0.046875f, 0.051605f, 0.056427f, 0.061859f, 0.067688f, 0.403320f, 0.467041f,
+ 0.480957f, 0.487793f, 0.491699f, 0.494385f, 0.000336f, 0.000673f, 0.001150f, 0.001274f, 0.001482f, 0.001630f, 0.001748f, 0.001904f,
+ 0.002087f, 0.002232f, 0.002306f, 0.002497f, 0.002672f, 0.002872f, 0.003092f, 0.003225f, 0.003387f, 0.003553f, 0.003819f, 0.003979f,
+ 0.004230f, 0.004517f, 0.004738f, 0.005016f, 0.005322f, 0.005569f, 0.005848f, 0.006184f, 0.006573f, 0.006851f, 0.007271f, 0.007660f,
+ 0.008064f, 0.008568f, 0.009048f, 0.009567f, 0.010139f, 0.010788f, 0.011391f, 0.012161f, 0.012939f, 0.013763f, 0.014694f, 0.015717f,
+ 0.016815f, 0.018097f, 0.019714f, 0.021149f, 0.023270f, 0.025421f, 0.028015f, 0.030991f, 0.034271f, 0.038116f, 0.042328f, 0.046997f,
+ 0.052094f, 0.057770f, 0.391113f, 0.457031f, 0.472412f, 0.479736f, 0.484375f, 0.486816f, 0.000309f, 0.000612f, 0.000953f, 0.001086f,
+ 0.001191f, 0.001281f, 0.001351f, 0.001442f, 0.001610f, 0.001733f, 0.001783f, 0.001991f, 0.002087f, 0.002232f, 0.002337f, 0.002495f,
+ 0.002611f, 0.002775f, 0.002935f, 0.003101f, 0.003302f, 0.003496f, 0.003622f, 0.003839f, 0.004047f, 0.004265f, 0.004494f, 0.004738f,
+ 0.005039f, 0.005272f, 0.005650f, 0.005898f, 0.006210f, 0.006588f, 0.006950f, 0.007332f, 0.007782f, 0.008240f, 0.008766f, 0.009331f,
+ 0.009964f, 0.010612f, 0.011314f, 0.012062f, 0.013023f, 0.014038f, 0.015007f, 0.016251f, 0.017761f, 0.019501f, 0.021530f, 0.023926f,
+ 0.026718f, 0.030106f, 0.033905f, 0.038361f, 0.043060f, 0.048370f, 0.379395f, 0.446777f, 0.464111f, 0.471191f, 0.475586f, 0.479492f,
+ 0.000439f, 0.000476f, 0.000672f, 0.000752f, 0.000810f, 0.000949f, 0.001011f, 0.001121f, 0.001160f, 0.001249f, 0.001408f, 0.001493f,
+ 0.001591f, 0.001719f, 0.001788f, 0.001845f, 0.001982f, 0.002106f, 0.002201f, 0.002357f, 0.002460f, 0.002598f, 0.002724f, 0.002869f,
+ 0.003036f, 0.003187f, 0.003397f, 0.003569f, 0.003763f, 0.004017f, 0.004211f, 0.004414f, 0.004704f, 0.004890f, 0.005234f, 0.005524f,
+ 0.005825f, 0.006187f, 0.006535f, 0.006977f, 0.007423f, 0.007874f, 0.008553f, 0.009079f, 0.009857f, 0.010567f, 0.011360f, 0.012306f,
+ 0.013390f, 0.014702f, 0.016220f, 0.017960f, 0.020157f, 0.022995f, 0.026352f, 0.030212f, 0.034790f, 0.039459f, 0.368408f, 0.437744f,
+ 0.455322f, 0.463379f, 0.468018f, 0.471436f, 0.000202f, 0.000437f, 0.000488f, 0.000579f, 0.000664f, 0.000692f, 0.000792f, 0.000762f,
+ 0.000875f, 0.000949f, 0.001038f, 0.001068f, 0.001116f, 0.001196f, 0.001300f, 0.001352f, 0.001458f, 0.001529f, 0.001623f, 0.001667f,
+ 0.001770f, 0.001884f, 0.001989f, 0.002071f, 0.002203f, 0.002310f, 0.002445f, 0.002556f, 0.002680f, 0.002876f, 0.002991f, 0.003206f,
+ 0.003365f, 0.003531f, 0.003759f, 0.003956f, 0.004227f, 0.004513f, 0.004768f, 0.005074f, 0.005402f, 0.005756f, 0.006142f, 0.006603f,
+ 0.007160f, 0.007645f, 0.008339f, 0.008987f, 0.009819f, 0.010780f, 0.011803f, 0.013153f, 0.014763f, 0.016876f, 0.019623f, 0.022995f,
+ 0.026978f, 0.031708f, 0.356445f, 0.428223f, 0.446533f, 0.455078f, 0.460449f, 0.463379f, 0.000126f, 0.000241f, 0.000344f, 0.000353f,
+ 0.000437f, 0.000522f, 0.000513f, 0.000552f, 0.000613f, 0.000699f, 0.000717f, 0.000727f, 0.000763f, 0.000848f, 0.000877f, 0.000956f,
+ 0.000963f, 0.001068f, 0.001128f, 0.001170f, 0.001238f, 0.001311f, 0.001385f, 0.001454f, 0.001534f, 0.001603f, 0.001714f, 0.001779f,
+ 0.001885f, 0.002016f, 0.002092f, 0.002214f, 0.002331f, 0.002460f, 0.002613f, 0.002777f, 0.002924f, 0.003120f, 0.003298f, 0.003496f,
+ 0.003708f, 0.004009f, 0.004292f, 0.004601f, 0.004951f, 0.005341f, 0.005772f, 0.006260f, 0.006901f, 0.007572f, 0.008324f, 0.009300f,
+ 0.010445f, 0.011848f, 0.013870f, 0.016678f, 0.020218f, 0.024536f, 0.345703f, 0.419189f, 0.437500f, 0.447021f, 0.452393f, 0.455811f,
+ 0.000146f, 0.000240f, 0.000268f, 0.000268f, 0.000310f, 0.000311f, 0.000331f, 0.000366f, 0.000410f, 0.000447f, 0.000446f, 0.000517f,
+ 0.000511f, 0.000571f, 0.000596f, 0.000618f, 0.000674f, 0.000691f, 0.000723f, 0.000762f, 0.000822f, 0.000856f, 0.000912f, 0.000950f,
+ 0.001014f, 0.001049f, 0.001128f, 0.001188f, 0.001237f, 0.001303f, 0.001371f, 0.001466f, 0.001532f, 0.001623f, 0.001701f, 0.001805f,
+ 0.001945f, 0.002035f, 0.002186f, 0.002329f, 0.002460f, 0.002632f, 0.002819f, 0.003012f, 0.003271f, 0.003550f, 0.003819f, 0.004162f,
+ 0.004539f, 0.005024f, 0.005585f, 0.006233f, 0.007050f, 0.008072f, 0.009331f, 0.011269f, 0.014160f, 0.018112f, 0.333740f, 0.408447f,
+ 0.428711f, 0.438232f, 0.443359f, 0.447510f, 0.000053f, 0.000163f, 0.000155f, 0.000160f, 0.000191f, 0.000228f, 0.000206f, 0.000233f,
+ 0.000248f, 0.000263f, 0.000267f, 0.000294f, 0.000324f, 0.000335f, 0.000364f, 0.000378f, 0.000396f, 0.000435f, 0.000445f, 0.000490f,
+ 0.000502f, 0.000522f, 0.000543f, 0.000582f, 0.000619f, 0.000665f, 0.000679f, 0.000705f, 0.000755f, 0.000797f, 0.000856f, 0.000887f,
+ 0.000953f, 0.000988f, 0.001043f, 0.001103f, 0.001177f, 0.001256f, 0.001331f, 0.001410f, 0.001508f, 0.001612f, 0.001734f, 0.001873f,
+ 0.001999f, 0.002163f, 0.002378f, 0.002565f, 0.002827f, 0.003119f, 0.003479f, 0.003899f, 0.004463f, 0.005116f, 0.005951f, 0.007153f,
+ 0.009163f, 0.012535f, 0.322510f, 0.400146f, 0.420654f, 0.430176f, 0.436523f, 0.440430f, 0.000097f, 0.000107f, 0.000095f, 0.000087f,
+ 0.000107f, 0.000110f, 0.000137f, 0.000139f, 0.000140f, 0.000147f, 0.000168f, 0.000175f, 0.000177f, 0.000184f, 0.000210f, 0.000200f,
+ 0.000224f, 0.000239f, 0.000246f, 0.000258f, 0.000278f, 0.000288f, 0.000312f, 0.000324f, 0.000347f, 0.000368f, 0.000382f, 0.000395f,
+ 0.000418f, 0.000440f, 0.000471f, 0.000495f, 0.000521f, 0.000547f, 0.000577f, 0.000620f, 0.000649f, 0.000695f, 0.000749f, 0.000785f,
+ 0.000838f, 0.000897f, 0.000972f, 0.001028f, 0.001118f, 0.001204f, 0.001316f, 0.001432f, 0.001580f, 0.001748f, 0.001961f, 0.002207f,
+ 0.002533f, 0.002941f, 0.003487f, 0.004223f, 0.005371f, 0.007809f, 0.311523f, 0.390381f, 0.411377f, 0.421875f, 0.428467f, 0.432617f,
+ 0.000000f, 0.000055f, 0.000046f, 0.000054f, 0.000060f, 0.000058f, 0.000060f, 0.000068f, 0.000068f, 0.000082f, 0.000076f, 0.000078f,
+ 0.000092f, 0.000087f, 0.000091f, 0.000097f, 0.000105f, 0.000115f, 0.000118f, 0.000124f, 0.000128f, 0.000133f, 0.000139f, 0.000154f,
+ 0.000160f, 0.000172f, 0.000175f, 0.000191f, 0.000201f, 0.000211f, 0.000221f, 0.000238f, 0.000242f, 0.000257f, 0.000277f, 0.000295f,
+ 0.000309f, 0.000326f, 0.000351f, 0.000375f, 0.000400f, 0.000428f, 0.000459f, 0.000490f, 0.000535f, 0.000579f, 0.000626f, 0.000683f,
+ 0.000754f, 0.000836f, 0.000952f, 0.001064f, 0.001237f, 0.001460f, 0.001751f, 0.002157f, 0.002800f, 0.004189f, 0.299561f, 0.380127f,
+ 0.403076f, 0.413574f, 0.419922f, 0.424072f, 0.000059f, 0.000039f, 0.000032f, 0.000028f, 0.000025f, 0.000025f, 0.000025f, 0.000024f,
+ 0.000023f, 0.000024f, 0.000026f, 0.000034f, 0.000029f, 0.000031f, 0.000038f, 0.000040f, 0.000042f, 0.000043f, 0.000042f, 0.000043f,
+ 0.000048f, 0.000054f, 0.000058f, 0.000056f, 0.000060f, 0.000062f, 0.000066f, 0.000069f, 0.000072f, 0.000078f, 0.000082f, 0.000085f,
+ 0.000093f, 0.000096f, 0.000099f, 0.000106f, 0.000116f, 0.000123f, 0.000132f, 0.000140f, 0.000150f, 0.000154f, 0.000167f, 0.000184f,
+ 0.000192f, 0.000212f, 0.000231f, 0.000251f, 0.000282f, 0.000314f, 0.000350f, 0.000401f, 0.000463f, 0.000554f, 0.000679f, 0.000861f,
+ 0.001157f, 0.001750f, 0.289307f, 0.371582f, 0.394043f, 0.406006f, 0.412109f, 0.417236f, 0.000031f, 0.000020f, 0.000016f, 0.000014f,
+ 0.000013f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000009f,
+ 0.000009f, 0.000007f, 0.000008f, 0.000008f, 0.000010f, 0.000011f, 0.000012f, 0.000013f, 0.000013f, 0.000013f, 0.000014f, 0.000017f,
+ 0.000017f, 0.000016f, 0.000018f, 0.000019f, 0.000021f, 0.000021f, 0.000022f, 0.000025f, 0.000027f, 0.000025f, 0.000028f, 0.000030f,
+ 0.000033f, 0.000036f, 0.000038f, 0.000040f, 0.000042f, 0.000047f, 0.000052f, 0.000057f, 0.000060f, 0.000068f, 0.000073f, 0.000089f,
+ 0.000104f, 0.000124f, 0.000153f, 0.000204f, 0.000293f, 0.000497f, 0.278076f, 0.362793f, 0.385498f, 0.397705f, 0.405029f, 0.409912f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000005f, 0.000005f, 0.000008f, 0.000012f, 0.000026f, 0.267822f, 0.353027f,
+ 0.376953f, 0.388916f, 0.395996f, 0.401367f,
+ },
+ {
+ 0.006824f, 0.021286f, 0.036285f, 0.051208f, 0.066467f, 0.082825f, 0.098694f, 0.114563f, 0.130737f, 0.146973f, 0.162720f, 0.179932f,
+ 0.196411f, 0.212646f, 0.229370f, 0.246338f, 0.263184f, 0.279785f, 0.297363f, 0.314209f, 0.331055f, 0.348389f, 0.365479f, 0.383301f,
+ 0.400146f, 0.417725f, 0.435303f, 0.451904f, 0.469971f, 0.486816f, 0.503906f, 0.521484f, 0.539551f, 0.556641f, 0.573730f, 0.592285f,
+ 0.609375f, 0.627441f, 0.644531f, 0.662598f, 0.679688f, 0.696777f, 0.714355f, 0.731934f, 0.749512f, 0.768066f, 0.784180f, 0.802246f,
+ 0.820312f, 0.837891f, 0.854980f, 0.871582f, 0.889648f, 0.906738f, 0.924805f, 0.941406f, 0.959473f, 0.976074f, 0.953125f, 0.895020f,
+ 0.857422f, 0.827637f, 0.803223f, 0.781738f, 0.006741f, 0.020706f, 0.035187f, 0.049866f, 0.065125f, 0.079895f, 0.095581f, 0.111206f,
+ 0.126953f, 0.142822f, 0.158569f, 0.174561f, 0.190796f, 0.207031f, 0.223511f, 0.239380f, 0.256104f, 0.272705f, 0.289307f, 0.305664f,
+ 0.322754f, 0.338867f, 0.356201f, 0.372314f, 0.389404f, 0.406494f, 0.423828f, 0.440430f, 0.457520f, 0.474854f, 0.491211f, 0.508789f,
+ 0.525391f, 0.541992f, 0.559082f, 0.576660f, 0.594238f, 0.610840f, 0.627930f, 0.645508f, 0.662598f, 0.679199f, 0.696289f, 0.713379f,
+ 0.731445f, 0.747559f, 0.765137f, 0.782715f, 0.799805f, 0.816895f, 0.834473f, 0.851074f, 0.868164f, 0.884766f, 0.902344f, 0.919434f,
+ 0.936523f, 0.953613f, 0.942871f, 0.887695f, 0.851562f, 0.823730f, 0.799805f, 0.779297f, 0.006504f, 0.020004f, 0.033875f, 0.048676f,
+ 0.063110f, 0.077759f, 0.092712f, 0.108032f, 0.123230f, 0.138672f, 0.153931f, 0.170044f, 0.185791f, 0.200806f, 0.217041f, 0.233276f,
+ 0.248901f, 0.265137f, 0.280762f, 0.297363f, 0.313721f, 0.329834f, 0.346680f, 0.363037f, 0.378418f, 0.395752f, 0.411621f, 0.428467f,
+ 0.445312f, 0.461670f, 0.479004f, 0.494873f, 0.511230f, 0.527832f, 0.544434f, 0.561523f, 0.578613f, 0.594727f, 0.611328f, 0.628906f,
+ 0.645508f, 0.662109f, 0.679199f, 0.695312f, 0.712402f, 0.729004f, 0.746094f, 0.762695f, 0.779297f, 0.796387f, 0.812500f, 0.829590f,
+ 0.846191f, 0.863281f, 0.879395f, 0.896973f, 0.914062f, 0.930176f, 0.932129f, 0.879395f, 0.845703f, 0.818848f, 0.795898f, 0.776367f,
+ 0.006226f, 0.019318f, 0.032959f, 0.046631f, 0.060699f, 0.075745f, 0.089966f, 0.104553f, 0.119385f, 0.134277f, 0.149292f, 0.164917f,
+ 0.179932f, 0.195190f, 0.210693f, 0.226562f, 0.242188f, 0.257568f, 0.273438f, 0.289062f, 0.304932f, 0.320557f, 0.336426f, 0.352539f,
+ 0.368652f, 0.384766f, 0.400391f, 0.417236f, 0.433105f, 0.448730f, 0.465088f, 0.481689f, 0.497559f, 0.513672f, 0.528809f, 0.546875f,
+ 0.562500f, 0.578613f, 0.595215f, 0.612793f, 0.627930f, 0.645508f, 0.661621f, 0.677246f, 0.693848f, 0.709961f, 0.726562f, 0.743164f,
+ 0.759766f, 0.774902f, 0.791992f, 0.808594f, 0.825195f, 0.841309f, 0.856934f, 0.874023f, 0.890625f, 0.907715f, 0.921387f, 0.872070f,
+ 0.839355f, 0.813477f, 0.791504f, 0.772461f, 0.005928f, 0.018997f, 0.031830f, 0.045380f, 0.059235f, 0.072754f, 0.087463f, 0.101562f,
+ 0.115723f, 0.130371f, 0.145264f, 0.159668f, 0.175049f, 0.189453f, 0.204468f, 0.219482f, 0.234497f, 0.250000f, 0.266113f, 0.280273f,
+ 0.295410f, 0.311768f, 0.327393f, 0.343018f, 0.357422f, 0.373779f, 0.389404f, 0.404785f, 0.421143f, 0.437012f, 0.452881f, 0.468262f,
+ 0.484375f, 0.499512f, 0.515137f, 0.531738f, 0.546875f, 0.562500f, 0.579102f, 0.595215f, 0.610840f, 0.627441f, 0.643555f, 0.659180f,
+ 0.674805f, 0.691406f, 0.708008f, 0.723145f, 0.738770f, 0.755371f, 0.771484f, 0.787598f, 0.803711f, 0.819824f, 0.835449f, 0.851562f,
+ 0.867676f, 0.884277f, 0.910156f, 0.864258f, 0.832520f, 0.808105f, 0.787109f, 0.769043f, 0.005939f, 0.018066f, 0.030991f, 0.043488f,
+ 0.057312f, 0.070557f, 0.084473f, 0.098328f, 0.112610f, 0.126587f, 0.140259f, 0.154907f, 0.169678f, 0.184326f, 0.198608f, 0.213379f,
+ 0.227783f, 0.242065f, 0.257568f, 0.272705f, 0.287109f, 0.302246f, 0.318115f, 0.333252f, 0.347656f, 0.362549f, 0.378418f, 0.393555f,
+ 0.408936f, 0.423828f, 0.439697f, 0.455078f, 0.471191f, 0.484863f, 0.500488f, 0.517578f, 0.532227f, 0.547363f, 0.562500f, 0.579102f,
+ 0.594727f, 0.610352f, 0.625488f, 0.641602f, 0.657227f, 0.671875f, 0.687500f, 0.704102f, 0.719238f, 0.733887f, 0.750488f, 0.767090f,
+ 0.782715f, 0.798340f, 0.813965f, 0.830566f, 0.845215f, 0.862305f, 0.899902f, 0.855469f, 0.825684f, 0.801758f, 0.782227f, 0.764648f,
+ 0.005684f, 0.017639f, 0.030334f, 0.042572f, 0.055298f, 0.068054f, 0.081787f, 0.095276f, 0.108765f, 0.122192f, 0.136353f, 0.150513f,
+ 0.164307f, 0.178467f, 0.192627f, 0.206665f, 0.221436f, 0.234985f, 0.249634f, 0.264404f, 0.278564f, 0.293213f, 0.308350f, 0.321533f,
+ 0.337646f, 0.353027f, 0.367432f, 0.381592f, 0.395996f, 0.411865f, 0.426758f, 0.441895f, 0.456543f, 0.471680f, 0.485840f, 0.501465f,
+ 0.517090f, 0.531738f, 0.546387f, 0.562012f, 0.576660f, 0.592773f, 0.608398f, 0.623047f, 0.638672f, 0.654297f, 0.668457f, 0.684082f,
+ 0.699707f, 0.714844f, 0.730469f, 0.745605f, 0.761230f, 0.777832f, 0.791504f, 0.807617f, 0.823242f, 0.839355f, 0.889160f, 0.847656f,
+ 0.818848f, 0.796387f, 0.776855f, 0.760254f, 0.005417f, 0.017136f, 0.028778f, 0.041016f, 0.054047f, 0.066528f, 0.079590f, 0.092102f,
+ 0.105225f, 0.118652f, 0.131714f, 0.145630f, 0.158813f, 0.172607f, 0.186523f, 0.200317f, 0.213745f, 0.227905f, 0.242188f, 0.256104f,
+ 0.270020f, 0.283936f, 0.299072f, 0.312744f, 0.327148f, 0.341797f, 0.355957f, 0.369629f, 0.384766f, 0.399414f, 0.413574f, 0.427490f,
+ 0.443115f, 0.457764f, 0.472656f, 0.487061f, 0.501465f, 0.516602f, 0.530762f, 0.545898f, 0.560547f, 0.574707f, 0.589844f, 0.605469f,
+ 0.619629f, 0.633301f, 0.648926f, 0.665527f, 0.679688f, 0.694824f, 0.709961f, 0.725586f, 0.739746f, 0.755371f, 0.770020f, 0.786133f,
+ 0.802246f, 0.817383f, 0.877930f, 0.838867f, 0.812012f, 0.790039f, 0.771973f, 0.755371f, 0.005520f, 0.016464f, 0.027695f, 0.039948f,
+ 0.051575f, 0.063965f, 0.076660f, 0.089111f, 0.101807f, 0.114319f, 0.126953f, 0.140381f, 0.153564f, 0.166992f, 0.180298f, 0.193970f,
+ 0.207153f, 0.220337f, 0.234131f, 0.248169f, 0.261475f, 0.275146f, 0.288818f, 0.302734f, 0.316162f, 0.330566f, 0.345459f, 0.358887f,
+ 0.372803f, 0.386719f, 0.401367f, 0.415527f, 0.429199f, 0.443848f, 0.458008f, 0.472412f, 0.486572f, 0.500977f, 0.515137f, 0.529785f,
+ 0.544434f, 0.558105f, 0.572754f, 0.587891f, 0.601074f, 0.617188f, 0.631836f, 0.645020f, 0.660645f, 0.674805f, 0.689453f, 0.704590f,
+ 0.719727f, 0.734375f, 0.750000f, 0.764160f, 0.780273f, 0.794922f, 0.866699f, 0.830566f, 0.804688f, 0.784180f, 0.766113f, 0.750977f,
+ 0.005222f, 0.016022f, 0.026962f, 0.038086f, 0.050049f, 0.061798f, 0.074158f, 0.085876f, 0.098145f, 0.110718f, 0.122986f, 0.135864f,
+ 0.148438f, 0.161133f, 0.173584f, 0.187378f, 0.199707f, 0.213501f, 0.226440f, 0.240112f, 0.252441f, 0.266113f, 0.279785f, 0.292725f,
+ 0.306152f, 0.320068f, 0.333984f, 0.347900f, 0.361572f, 0.374512f, 0.387695f, 0.402344f, 0.416504f, 0.429688f, 0.443604f, 0.458008f,
+ 0.471680f, 0.485596f, 0.499023f, 0.513184f, 0.527832f, 0.541016f, 0.555664f, 0.569336f, 0.583984f, 0.598633f, 0.612793f, 0.626465f,
+ 0.641602f, 0.656250f, 0.669922f, 0.684570f, 0.698730f, 0.713867f, 0.728516f, 0.742188f, 0.757812f, 0.771484f, 0.855957f, 0.822266f,
+ 0.797852f, 0.777832f, 0.760742f, 0.746094f, 0.004944f, 0.015327f, 0.026230f, 0.037201f, 0.048187f, 0.059448f, 0.071167f, 0.082642f,
+ 0.094727f, 0.106506f, 0.119019f, 0.130371f, 0.143555f, 0.155640f, 0.167725f, 0.180908f, 0.193604f, 0.206177f, 0.218506f, 0.231812f,
+ 0.244873f, 0.257568f, 0.270996f, 0.283203f, 0.296387f, 0.309814f, 0.322754f, 0.336670f, 0.348877f, 0.362061f, 0.376465f, 0.389893f,
+ 0.402588f, 0.415283f, 0.429443f, 0.443115f, 0.457031f, 0.470459f, 0.483887f, 0.497314f, 0.511230f, 0.524414f, 0.538574f, 0.551758f,
+ 0.565918f, 0.579590f, 0.593750f, 0.606934f, 0.621094f, 0.635254f, 0.649902f, 0.664062f, 0.678223f, 0.692871f, 0.707031f, 0.721191f,
+ 0.735840f, 0.750488f, 0.846191f, 0.813477f, 0.790527f, 0.770996f, 0.754883f, 0.740723f, 0.004951f, 0.014656f, 0.025253f, 0.035309f,
+ 0.046417f, 0.057465f, 0.068665f, 0.079773f, 0.091370f, 0.102844f, 0.114441f, 0.126099f, 0.138062f, 0.150391f, 0.161987f, 0.174561f,
+ 0.186523f, 0.198730f, 0.211060f, 0.223267f, 0.235352f, 0.248779f, 0.260986f, 0.274414f, 0.286621f, 0.298584f, 0.312256f, 0.324463f,
+ 0.337158f, 0.350342f, 0.363281f, 0.376953f, 0.389404f, 0.402344f, 0.415283f, 0.428955f, 0.441162f, 0.455322f, 0.467285f, 0.481201f,
+ 0.493896f, 0.507324f, 0.520996f, 0.534668f, 0.547852f, 0.561035f, 0.575195f, 0.588867f, 0.603027f, 0.616211f, 0.630371f, 0.643555f,
+ 0.658203f, 0.671875f, 0.686035f, 0.699707f, 0.714844f, 0.729492f, 0.833984f, 0.804688f, 0.782227f, 0.764160f, 0.749512f, 0.735352f,
+ 0.004700f, 0.014343f, 0.024200f, 0.034515f, 0.044586f, 0.055176f, 0.066162f, 0.077209f, 0.087830f, 0.098816f, 0.110413f, 0.121826f,
+ 0.132690f, 0.144897f, 0.156372f, 0.168213f, 0.179443f, 0.191650f, 0.203369f, 0.215088f, 0.227661f, 0.239990f, 0.251709f, 0.263916f,
+ 0.276611f, 0.289551f, 0.301270f, 0.313965f, 0.325928f, 0.338135f, 0.350586f, 0.363037f, 0.376465f, 0.388428f, 0.401123f, 0.414062f,
+ 0.426514f, 0.439209f, 0.452393f, 0.465088f, 0.478271f, 0.491455f, 0.503906f, 0.517090f, 0.530273f, 0.543457f, 0.556641f, 0.570312f,
+ 0.583008f, 0.597168f, 0.610352f, 0.624512f, 0.638184f, 0.651367f, 0.665527f, 0.679199f, 0.692871f, 0.708496f, 0.823242f, 0.796387f,
+ 0.774902f, 0.757812f, 0.742676f, 0.729980f, 0.004395f, 0.013802f, 0.023499f, 0.033173f, 0.043121f, 0.053345f, 0.063538f, 0.073730f,
+ 0.085083f, 0.095581f, 0.106140f, 0.116760f, 0.127930f, 0.139160f, 0.150757f, 0.161621f, 0.173096f, 0.184814f, 0.196289f, 0.207520f,
+ 0.219971f, 0.231201f, 0.242920f, 0.254150f, 0.266602f, 0.278320f, 0.290527f, 0.302490f, 0.314209f, 0.326904f, 0.338867f, 0.349854f,
+ 0.362305f, 0.375488f, 0.387451f, 0.400146f, 0.412354f, 0.424805f, 0.436768f, 0.449219f, 0.461914f, 0.475098f, 0.487061f, 0.500000f,
+ 0.512695f, 0.525391f, 0.538574f, 0.551758f, 0.564453f, 0.577148f, 0.590820f, 0.604004f, 0.618164f, 0.631348f, 0.644531f, 0.658203f,
+ 0.672363f, 0.686523f, 0.812500f, 0.786621f, 0.767090f, 0.750977f, 0.736816f, 0.724609f, 0.004425f, 0.013405f, 0.022385f, 0.032043f,
+ 0.041565f, 0.051605f, 0.061340f, 0.071106f, 0.081116f, 0.091125f, 0.101868f, 0.112671f, 0.123169f, 0.133667f, 0.144897f, 0.155029f,
+ 0.166748f, 0.177246f, 0.188599f, 0.199585f, 0.211182f, 0.222046f, 0.233643f, 0.245361f, 0.255615f, 0.268066f, 0.279053f, 0.291260f,
+ 0.303223f, 0.314209f, 0.325684f, 0.338379f, 0.349854f, 0.361572f, 0.374023f, 0.385254f, 0.397949f, 0.409912f, 0.421143f, 0.434082f,
+ 0.445801f, 0.457764f, 0.470215f, 0.482910f, 0.495361f, 0.508301f, 0.520996f, 0.534180f, 0.546387f, 0.560059f, 0.572266f, 0.584961f,
+ 0.597168f, 0.610840f, 0.624023f, 0.638184f, 0.650879f, 0.666016f, 0.801270f, 0.778320f, 0.760254f, 0.744141f, 0.730469f, 0.719238f,
+ 0.004261f, 0.012543f, 0.021591f, 0.031052f, 0.039734f, 0.049164f, 0.058838f, 0.068420f, 0.077881f, 0.087402f, 0.098145f, 0.108276f,
+ 0.118225f, 0.128784f, 0.138550f, 0.149292f, 0.159790f, 0.170654f, 0.181519f, 0.191772f, 0.203003f, 0.213623f, 0.225098f, 0.235107f,
+ 0.247070f, 0.257324f, 0.269287f, 0.280273f, 0.291260f, 0.302246f, 0.313721f, 0.325439f, 0.336670f, 0.348145f, 0.359619f, 0.371338f,
+ 0.382812f, 0.395020f, 0.406738f, 0.418213f, 0.429932f, 0.442139f, 0.454102f, 0.466309f, 0.479004f, 0.490723f, 0.502930f, 0.515625f,
+ 0.526855f, 0.540527f, 0.552246f, 0.565918f, 0.578613f, 0.591309f, 0.604492f, 0.617188f, 0.630859f, 0.644043f, 0.790039f, 0.769531f,
+ 0.751953f, 0.737305f, 0.724121f, 0.713379f, 0.003983f, 0.012329f, 0.020538f, 0.029312f, 0.038452f, 0.047241f, 0.056244f, 0.065552f,
+ 0.075195f, 0.084290f, 0.094238f, 0.103638f, 0.113403f, 0.123413f, 0.133057f, 0.143066f, 0.153076f, 0.163696f, 0.173584f, 0.184204f,
+ 0.194580f, 0.204834f, 0.215332f, 0.225952f, 0.237305f, 0.247803f, 0.258545f, 0.269531f, 0.280518f, 0.291260f, 0.301758f, 0.312988f,
+ 0.324219f, 0.335205f, 0.346191f, 0.357178f, 0.368896f, 0.380127f, 0.391113f, 0.403076f, 0.414551f, 0.426270f, 0.437500f, 0.449951f,
+ 0.460938f, 0.473389f, 0.485596f, 0.497314f, 0.509277f, 0.522461f, 0.533691f, 0.546875f, 0.558594f, 0.571289f, 0.583496f, 0.596680f,
+ 0.608887f, 0.623047f, 0.778809f, 0.761230f, 0.744141f, 0.730957f, 0.718262f, 0.707031f, 0.003717f, 0.012016f, 0.020142f, 0.028137f,
+ 0.036682f, 0.045441f, 0.053711f, 0.062927f, 0.071777f, 0.080627f, 0.090210f, 0.099060f, 0.108643f, 0.118164f, 0.127808f, 0.137329f,
+ 0.147095f, 0.156128f, 0.166748f, 0.175903f, 0.186157f, 0.196655f, 0.206909f, 0.216797f, 0.227417f, 0.236816f, 0.247559f, 0.258301f,
+ 0.268799f, 0.278809f, 0.289795f, 0.299805f, 0.310547f, 0.321777f, 0.333008f, 0.343262f, 0.354492f, 0.365234f, 0.376953f, 0.387939f,
+ 0.398438f, 0.410400f, 0.421387f, 0.433105f, 0.444824f, 0.455811f, 0.467529f, 0.479736f, 0.491943f, 0.502930f, 0.515625f, 0.527344f,
+ 0.540039f, 0.551758f, 0.563965f, 0.576660f, 0.589844f, 0.602539f, 0.767578f, 0.751465f, 0.736328f, 0.723633f, 0.711914f, 0.701660f,
+ 0.003813f, 0.011337f, 0.019028f, 0.027252f, 0.035583f, 0.043396f, 0.051849f, 0.060028f, 0.068481f, 0.077026f, 0.086121f, 0.095093f,
+ 0.103821f, 0.112610f, 0.121765f, 0.131470f, 0.140503f, 0.149780f, 0.159058f, 0.168701f, 0.178711f, 0.187744f, 0.197998f, 0.207397f,
+ 0.217651f, 0.227661f, 0.236694f, 0.246704f, 0.257080f, 0.267334f, 0.277832f, 0.288330f, 0.298584f, 0.308838f, 0.319336f, 0.329590f,
+ 0.340332f, 0.351318f, 0.361816f, 0.372559f, 0.383301f, 0.395020f, 0.405273f, 0.416260f, 0.427734f, 0.439209f, 0.450195f, 0.462158f,
+ 0.473389f, 0.485107f, 0.497314f, 0.508301f, 0.520996f, 0.533203f, 0.544922f, 0.557617f, 0.568848f, 0.582031f, 0.757324f, 0.742676f,
+ 0.729004f, 0.716309f, 0.705566f, 0.695801f, 0.003633f, 0.011040f, 0.018280f, 0.026062f, 0.033569f, 0.041229f, 0.049591f, 0.057373f,
+ 0.065308f, 0.073975f, 0.082214f, 0.090393f, 0.099243f, 0.107544f, 0.116028f, 0.125854f, 0.134155f, 0.143311f, 0.151978f, 0.160767f,
+ 0.170410f, 0.179321f, 0.188477f, 0.198242f, 0.207764f, 0.217896f, 0.227051f, 0.236328f, 0.246338f, 0.256104f, 0.265869f, 0.276123f,
+ 0.285645f, 0.295898f, 0.306152f, 0.316162f, 0.326172f, 0.336914f, 0.347412f, 0.358154f, 0.368164f, 0.378906f, 0.389648f, 0.400146f,
+ 0.410889f, 0.421631f, 0.432861f, 0.444824f, 0.456055f, 0.466797f, 0.479004f, 0.490234f, 0.501465f, 0.514160f, 0.525879f, 0.537598f,
+ 0.549316f, 0.561523f, 0.745605f, 0.733887f, 0.721191f, 0.708496f, 0.699219f, 0.689453f, 0.003469f, 0.010429f, 0.017609f, 0.024612f,
+ 0.032135f, 0.039520f, 0.047516f, 0.055206f, 0.062347f, 0.070618f, 0.078308f, 0.085938f, 0.094727f, 0.102417f, 0.111511f, 0.119446f,
+ 0.127441f, 0.136475f, 0.144897f, 0.154175f, 0.162476f, 0.171509f, 0.180054f, 0.189697f, 0.198486f, 0.207886f, 0.216553f, 0.225830f,
+ 0.235229f, 0.244873f, 0.254395f, 0.263428f, 0.273193f, 0.283203f, 0.292969f, 0.302734f, 0.312744f, 0.322510f, 0.333008f, 0.342773f,
+ 0.353027f, 0.363037f, 0.374023f, 0.384521f, 0.395264f, 0.405762f, 0.416260f, 0.427002f, 0.438232f, 0.449219f, 0.460449f, 0.471924f,
+ 0.482910f, 0.494629f, 0.506348f, 0.517578f, 0.529785f, 0.541504f, 0.734375f, 0.725098f, 0.712891f, 0.701660f, 0.692383f, 0.683594f,
+ 0.003328f, 0.009804f, 0.016373f, 0.023727f, 0.030746f, 0.037994f, 0.044952f, 0.052032f, 0.059998f, 0.067383f, 0.074707f, 0.082214f,
+ 0.089783f, 0.097961f, 0.105774f, 0.114197f, 0.122131f, 0.129517f, 0.137695f, 0.146118f, 0.154419f, 0.163330f, 0.171997f, 0.180664f,
+ 0.188477f, 0.197388f, 0.206055f, 0.215332f, 0.224365f, 0.233765f, 0.242798f, 0.251709f, 0.260986f, 0.270020f, 0.279785f, 0.289062f,
+ 0.299561f, 0.308594f, 0.318115f, 0.328613f, 0.338135f, 0.348877f, 0.358154f, 0.368408f, 0.378174f, 0.388916f, 0.399658f, 0.410156f,
+ 0.420898f, 0.431885f, 0.442871f, 0.453369f, 0.463867f, 0.475342f, 0.486572f, 0.498535f, 0.510742f, 0.521973f, 0.723633f, 0.715820f,
+ 0.705078f, 0.694336f, 0.686035f, 0.677246f, 0.003090f, 0.009628f, 0.016129f, 0.022644f, 0.029068f, 0.036407f, 0.042633f, 0.049866f,
+ 0.056946f, 0.063904f, 0.071167f, 0.078186f, 0.085327f, 0.092896f, 0.100098f, 0.107788f, 0.115662f, 0.123230f, 0.131104f, 0.139160f,
+ 0.146973f, 0.154907f, 0.162964f, 0.171265f, 0.179565f, 0.188110f, 0.196777f, 0.204834f, 0.213745f, 0.222168f, 0.231079f, 0.239868f,
+ 0.248779f, 0.258057f, 0.267090f, 0.276611f, 0.285645f, 0.294434f, 0.304688f, 0.314209f, 0.323242f, 0.332520f, 0.342773f, 0.353027f,
+ 0.362549f, 0.373047f, 0.383057f, 0.393311f, 0.404053f, 0.414307f, 0.424561f, 0.435059f, 0.445801f, 0.456787f, 0.467773f, 0.479004f,
+ 0.490479f, 0.501953f, 0.712891f, 0.707031f, 0.696777f, 0.687500f, 0.679199f, 0.671387f, 0.003096f, 0.009026f, 0.015450f, 0.021606f,
+ 0.027695f, 0.034302f, 0.040833f, 0.047455f, 0.054077f, 0.060669f, 0.067444f, 0.074097f, 0.081604f, 0.088501f, 0.095337f, 0.102295f,
+ 0.109375f, 0.116821f, 0.124146f, 0.131592f, 0.139404f, 0.147217f, 0.155029f, 0.162231f, 0.170288f, 0.177979f, 0.186646f, 0.194092f,
+ 0.203247f, 0.211670f, 0.219604f, 0.228149f, 0.236816f, 0.245605f, 0.254639f, 0.263184f, 0.272217f, 0.281250f, 0.290527f, 0.299805f,
+ 0.308838f, 0.318604f, 0.327637f, 0.337646f, 0.347900f, 0.356934f, 0.367432f, 0.376953f, 0.387451f, 0.397217f, 0.407227f, 0.417480f,
+ 0.427979f, 0.439209f, 0.449463f, 0.459717f, 0.470947f, 0.482666f, 0.701172f, 0.698242f, 0.688477f, 0.680176f, 0.671875f, 0.665039f,
+ 0.002831f, 0.008789f, 0.014702f, 0.020523f, 0.026642f, 0.032684f, 0.038757f, 0.044708f, 0.051666f, 0.057312f, 0.063660f, 0.070190f,
+ 0.076904f, 0.083435f, 0.090454f, 0.097046f, 0.103821f, 0.110535f, 0.117981f, 0.124817f, 0.131714f, 0.138916f, 0.146606f, 0.153687f,
+ 0.161011f, 0.168823f, 0.176270f, 0.184570f, 0.192139f, 0.200317f, 0.208008f, 0.216309f, 0.224609f, 0.233032f, 0.241821f, 0.250244f,
+ 0.258789f, 0.268066f, 0.276611f, 0.285400f, 0.294678f, 0.303223f, 0.312500f, 0.322021f, 0.331787f, 0.340088f, 0.350830f, 0.360596f,
+ 0.369385f, 0.380371f, 0.389893f, 0.399658f, 0.410645f, 0.420654f, 0.430908f, 0.442383f, 0.452148f, 0.464111f, 0.690430f, 0.688965f,
+ 0.681152f, 0.672852f, 0.665039f, 0.658691f, 0.002712f, 0.008553f, 0.013878f, 0.019638f, 0.025360f, 0.030716f, 0.037231f, 0.042633f,
+ 0.048615f, 0.054810f, 0.060638f, 0.066650f, 0.072205f, 0.078796f, 0.085083f, 0.091492f, 0.097961f, 0.104065f, 0.110718f, 0.117859f,
+ 0.124207f, 0.130981f, 0.138550f, 0.145142f, 0.152588f, 0.160156f, 0.166992f, 0.174561f, 0.181885f, 0.189453f, 0.197754f, 0.205444f,
+ 0.213013f, 0.220825f, 0.229004f, 0.237061f, 0.246094f, 0.254639f, 0.262939f, 0.271484f, 0.280273f, 0.288818f, 0.298584f, 0.307129f,
+ 0.316162f, 0.325195f, 0.334229f, 0.344482f, 0.353516f, 0.363525f, 0.372803f, 0.382812f, 0.392822f, 0.402344f, 0.412842f, 0.423096f,
+ 0.433350f, 0.444092f, 0.679199f, 0.679688f, 0.672852f, 0.665039f, 0.658203f, 0.651855f, 0.002674f, 0.007828f, 0.013290f, 0.018723f,
+ 0.023743f, 0.029160f, 0.034790f, 0.040100f, 0.045929f, 0.051544f, 0.057068f, 0.063110f, 0.068359f, 0.074280f, 0.080078f, 0.086243f,
+ 0.092346f, 0.098206f, 0.104919f, 0.110779f, 0.117493f, 0.123291f, 0.130005f, 0.136963f, 0.143677f, 0.150635f, 0.157471f, 0.164307f,
+ 0.171631f, 0.179199f, 0.186279f, 0.193604f, 0.201904f, 0.209229f, 0.217163f, 0.224976f, 0.233154f, 0.240967f, 0.249634f, 0.258301f,
+ 0.266113f, 0.274414f, 0.283691f, 0.291748f, 0.301025f, 0.310059f, 0.319336f, 0.327148f, 0.337402f, 0.347168f, 0.355957f, 0.364746f,
+ 0.375488f, 0.385498f, 0.394043f, 0.405273f, 0.415283f, 0.426025f, 0.667969f, 0.670410f, 0.664551f, 0.657227f, 0.651367f, 0.645508f,
+ 0.002731f, 0.007622f, 0.012627f, 0.017868f, 0.022781f, 0.028107f, 0.032959f, 0.037811f, 0.043121f, 0.048615f, 0.053925f, 0.059235f,
+ 0.064514f, 0.070007f, 0.075562f, 0.080688f, 0.086914f, 0.092102f, 0.098083f, 0.104309f, 0.110107f, 0.115906f, 0.122314f, 0.128540f,
+ 0.135010f, 0.141479f, 0.147949f, 0.154663f, 0.161865f, 0.168579f, 0.175415f, 0.182739f, 0.191040f, 0.197510f, 0.205200f, 0.212891f,
+ 0.219971f, 0.228638f, 0.236328f, 0.244263f, 0.252686f, 0.260498f, 0.268799f, 0.278076f, 0.286133f, 0.294434f, 0.303223f, 0.312500f,
+ 0.320801f, 0.329834f, 0.339844f, 0.347656f, 0.357910f, 0.367676f, 0.376709f, 0.386963f, 0.396729f, 0.406982f, 0.656738f, 0.662598f,
+ 0.656738f, 0.649902f, 0.644531f, 0.638672f, 0.002411f, 0.007168f, 0.012238f, 0.016739f, 0.021957f, 0.026184f, 0.031311f, 0.035583f,
+ 0.041016f, 0.045685f, 0.050568f, 0.055573f, 0.060791f, 0.065735f, 0.070557f, 0.076111f, 0.081238f, 0.086792f, 0.092163f, 0.097534f,
+ 0.103271f, 0.108887f, 0.114563f, 0.120605f, 0.126587f, 0.132446f, 0.139038f, 0.145508f, 0.152100f, 0.158447f, 0.165527f, 0.171997f,
+ 0.178833f, 0.186035f, 0.193481f, 0.200928f, 0.207886f, 0.215820f, 0.222900f, 0.230713f, 0.238770f, 0.246948f, 0.255127f, 0.262695f,
+ 0.271484f, 0.280029f, 0.287842f, 0.296631f, 0.305420f, 0.313965f, 0.322754f, 0.331787f, 0.340576f, 0.350342f, 0.359375f, 0.369385f,
+ 0.379150f, 0.388184f, 0.645508f, 0.652832f, 0.648438f, 0.643066f, 0.637695f, 0.632324f, 0.002480f, 0.006691f, 0.011452f, 0.015900f,
+ 0.020828f, 0.024734f, 0.029327f, 0.033752f, 0.038513f, 0.042999f, 0.047638f, 0.052429f, 0.056671f, 0.061859f, 0.066040f, 0.071289f,
+ 0.075684f, 0.080688f, 0.086243f, 0.091248f, 0.096436f, 0.101562f, 0.107300f, 0.112366f, 0.118347f, 0.124146f, 0.130249f, 0.135864f,
+ 0.141968f, 0.148438f, 0.155029f, 0.161377f, 0.167969f, 0.174683f, 0.181641f, 0.188599f, 0.195679f, 0.203247f, 0.210449f, 0.217529f,
+ 0.225342f, 0.233398f, 0.241577f, 0.249023f, 0.256592f, 0.264893f, 0.273193f, 0.281494f, 0.289795f, 0.297607f, 0.306885f, 0.315430f,
+ 0.323730f, 0.333496f, 0.342529f, 0.351318f, 0.360840f, 0.370605f, 0.634766f, 0.643555f, 0.640625f, 0.635742f, 0.630859f, 0.625488f,
+ 0.002230f, 0.006477f, 0.010582f, 0.014870f, 0.019073f, 0.023270f, 0.027893f, 0.031860f, 0.036072f, 0.040253f, 0.044373f, 0.048706f,
+ 0.052856f, 0.057312f, 0.061859f, 0.066406f, 0.070984f, 0.075317f, 0.080139f, 0.084839f, 0.089661f, 0.094910f, 0.099792f, 0.104858f,
+ 0.110718f, 0.115356f, 0.121399f, 0.126831f, 0.132690f, 0.138672f, 0.145142f, 0.151001f, 0.157471f, 0.164185f, 0.170532f, 0.177002f,
+ 0.184082f, 0.191040f, 0.197876f, 0.205200f, 0.212402f, 0.219604f, 0.227295f, 0.234985f, 0.242188f, 0.250244f, 0.257812f, 0.266113f,
+ 0.274170f, 0.282471f, 0.290771f, 0.299072f, 0.307373f, 0.316162f, 0.326416f, 0.333984f, 0.343750f, 0.353271f, 0.622070f, 0.634277f,
+ 0.631836f, 0.627930f, 0.623535f, 0.619141f, 0.002220f, 0.006039f, 0.010353f, 0.014328f, 0.017838f, 0.022141f, 0.025742f, 0.029510f,
+ 0.033600f, 0.037781f, 0.041443f, 0.045502f, 0.049469f, 0.053436f, 0.057190f, 0.061462f, 0.065735f, 0.069946f, 0.074524f, 0.078674f,
+ 0.083069f, 0.087830f, 0.092468f, 0.097412f, 0.102783f, 0.107910f, 0.112793f, 0.118164f, 0.123901f, 0.129395f, 0.135132f, 0.140991f,
+ 0.147339f, 0.152954f, 0.159302f, 0.165527f, 0.172363f, 0.178589f, 0.185425f, 0.191895f, 0.199219f, 0.206665f, 0.213989f, 0.221069f,
+ 0.228516f, 0.236206f, 0.243042f, 0.251709f, 0.258789f, 0.266846f, 0.275146f, 0.283203f, 0.291260f, 0.300537f, 0.308350f, 0.317627f,
+ 0.326904f, 0.335938f, 0.611816f, 0.625000f, 0.624023f, 0.620117f, 0.616211f, 0.612793f, 0.001965f, 0.005882f, 0.009613f, 0.013184f,
+ 0.016785f, 0.020370f, 0.024384f, 0.027664f, 0.031311f, 0.035126f, 0.038727f, 0.042572f, 0.046112f, 0.049347f, 0.053253f, 0.056915f,
+ 0.060883f, 0.064697f, 0.068909f, 0.072693f, 0.076843f, 0.081055f, 0.085754f, 0.090088f, 0.094849f, 0.099609f, 0.104614f, 0.109741f,
+ 0.114746f, 0.119995f, 0.125488f, 0.130981f, 0.136719f, 0.142700f, 0.148315f, 0.154541f, 0.160522f, 0.166870f, 0.173828f, 0.179932f,
+ 0.186768f, 0.193604f, 0.200439f, 0.207764f, 0.214844f, 0.221802f, 0.228882f, 0.236328f, 0.244385f, 0.252197f, 0.259277f, 0.268066f,
+ 0.275635f, 0.283447f, 0.292236f, 0.301270f, 0.309570f, 0.318848f, 0.600098f, 0.616211f, 0.615234f, 0.612793f, 0.609375f, 0.605469f,
+ 0.001966f, 0.005653f, 0.009109f, 0.012428f, 0.015945f, 0.018967f, 0.022537f, 0.025894f, 0.029175f, 0.032440f, 0.035797f, 0.038818f,
+ 0.042389f, 0.046051f, 0.049072f, 0.052521f, 0.056335f, 0.059906f, 0.063293f, 0.067017f, 0.070923f, 0.075134f, 0.078979f, 0.083496f,
+ 0.087646f, 0.091980f, 0.096619f, 0.101196f, 0.105957f, 0.111145f, 0.116028f, 0.121277f, 0.126831f, 0.132080f, 0.137817f, 0.143311f,
+ 0.149780f, 0.155029f, 0.161621f, 0.167847f, 0.173950f, 0.180786f, 0.187622f, 0.194214f, 0.201050f, 0.207764f, 0.215210f, 0.222046f,
+ 0.229370f, 0.236816f, 0.244751f, 0.251953f, 0.260010f, 0.268311f, 0.276123f, 0.284180f, 0.293213f, 0.301514f, 0.588379f, 0.606934f,
+ 0.607422f, 0.604980f, 0.602051f, 0.599609f, 0.001963f, 0.005333f, 0.008377f, 0.011589f, 0.014450f, 0.017593f, 0.021133f, 0.023972f,
+ 0.027145f, 0.030075f, 0.033295f, 0.035858f, 0.038818f, 0.041992f, 0.045288f, 0.048279f, 0.051849f, 0.054840f, 0.058289f, 0.061737f,
+ 0.065186f, 0.068848f, 0.072632f, 0.076721f, 0.080505f, 0.084717f, 0.088806f, 0.093079f, 0.097717f, 0.102356f, 0.106934f, 0.111755f,
+ 0.116882f, 0.121887f, 0.127319f, 0.132935f, 0.138306f, 0.144287f, 0.149902f, 0.156250f, 0.162109f, 0.168579f, 0.174316f, 0.180908f,
+ 0.187500f, 0.194458f, 0.201538f, 0.208252f, 0.215210f, 0.222656f, 0.229980f, 0.237061f, 0.244629f, 0.252441f, 0.260254f, 0.267334f,
+ 0.276123f, 0.284180f, 0.576660f, 0.597656f, 0.599609f, 0.598145f, 0.595215f, 0.591797f, 0.001631f, 0.004906f, 0.007805f, 0.010826f,
+ 0.013802f, 0.016983f, 0.019485f, 0.022079f, 0.024750f, 0.027939f, 0.030136f, 0.033112f, 0.035797f, 0.038727f, 0.041443f, 0.044281f,
+ 0.047058f, 0.050018f, 0.053253f, 0.056396f, 0.059662f, 0.063049f, 0.066406f, 0.069946f, 0.073730f, 0.077454f, 0.081360f, 0.085388f,
+ 0.089417f, 0.093750f, 0.098267f, 0.102844f, 0.107727f, 0.112244f, 0.117615f, 0.122253f, 0.127441f, 0.133057f, 0.138550f, 0.144287f,
+ 0.150024f, 0.156250f, 0.161987f, 0.167969f, 0.174805f, 0.181274f, 0.187744f, 0.194580f, 0.201294f, 0.208374f, 0.215210f, 0.222412f,
+ 0.229736f, 0.237183f, 0.244629f, 0.252197f, 0.260010f, 0.269287f, 0.566406f, 0.588867f, 0.590820f, 0.590332f, 0.587891f, 0.585938f,
+ 0.001858f, 0.004318f, 0.007465f, 0.010246f, 0.012550f, 0.015793f, 0.018143f, 0.020782f, 0.022980f, 0.025116f, 0.027924f, 0.030106f,
+ 0.032623f, 0.035126f, 0.037720f, 0.040283f, 0.042847f, 0.045380f, 0.048492f, 0.051300f, 0.054321f, 0.057373f, 0.060516f, 0.063599f,
+ 0.067139f, 0.070496f, 0.074219f, 0.078003f, 0.081848f, 0.085754f, 0.089783f, 0.093994f, 0.098267f, 0.102783f, 0.107239f, 0.112366f,
+ 0.117371f, 0.122498f, 0.127686f, 0.132935f, 0.138428f, 0.144043f, 0.150024f, 0.155884f, 0.161865f, 0.168091f, 0.174316f, 0.180664f,
+ 0.187622f, 0.194214f, 0.200928f, 0.207520f, 0.214966f, 0.221680f, 0.229370f, 0.236816f, 0.244751f, 0.252441f, 0.553223f, 0.579102f,
+ 0.583496f, 0.582031f, 0.581055f, 0.579590f, 0.001425f, 0.004284f, 0.007019f, 0.009521f, 0.011894f, 0.014191f, 0.016632f, 0.018723f,
+ 0.021210f, 0.023209f, 0.025482f, 0.027344f, 0.029617f, 0.032043f, 0.034210f, 0.036407f, 0.039001f, 0.041077f, 0.043976f, 0.046448f,
+ 0.049133f, 0.051819f, 0.054932f, 0.057770f, 0.060730f, 0.063965f, 0.067322f, 0.070862f, 0.074280f, 0.077698f, 0.082031f, 0.085571f,
+ 0.089844f, 0.093994f, 0.098022f, 0.102722f, 0.107178f, 0.111877f, 0.116821f, 0.121887f, 0.127075f, 0.132446f, 0.138062f, 0.143799f,
+ 0.149414f, 0.155518f, 0.161377f, 0.167480f, 0.173950f, 0.180176f, 0.186890f, 0.193481f, 0.200562f, 0.207397f, 0.214355f, 0.221313f,
+ 0.229492f, 0.237427f, 0.541504f, 0.570801f, 0.575195f, 0.575195f, 0.573730f, 0.572266f, 0.001613f, 0.004181f, 0.006252f, 0.008774f,
+ 0.011108f, 0.013054f, 0.015152f, 0.016937f, 0.019150f, 0.021011f, 0.023163f, 0.024826f, 0.026993f, 0.028793f, 0.030823f, 0.033081f,
+ 0.035156f, 0.037201f, 0.039612f, 0.041748f, 0.044464f, 0.046814f, 0.049438f, 0.052155f, 0.054840f, 0.057831f, 0.060699f, 0.063599f,
+ 0.067078f, 0.070374f, 0.073853f, 0.077087f, 0.081177f, 0.085083f, 0.089111f, 0.093262f, 0.097473f, 0.101929f, 0.106689f, 0.111023f,
+ 0.116455f, 0.121277f, 0.126343f, 0.132080f, 0.137573f, 0.142700f, 0.148682f, 0.154907f, 0.161133f, 0.167236f, 0.173340f, 0.179688f,
+ 0.186768f, 0.193115f, 0.200684f, 0.207275f, 0.214233f, 0.221924f, 0.530273f, 0.561523f, 0.565430f, 0.567383f, 0.564941f, 0.564941f,
+ 0.001237f, 0.003775f, 0.006348f, 0.008141f, 0.010117f, 0.012184f, 0.013763f, 0.015656f, 0.017319f, 0.018967f, 0.020645f, 0.022507f,
+ 0.023926f, 0.025757f, 0.027573f, 0.029449f, 0.031677f, 0.033325f, 0.035645f, 0.037659f, 0.039734f, 0.041809f, 0.044189f, 0.046692f,
+ 0.049133f, 0.051697f, 0.054504f, 0.057251f, 0.060059f, 0.063110f, 0.066467f, 0.069763f, 0.072937f, 0.076477f, 0.080505f, 0.084290f,
+ 0.088013f, 0.092407f, 0.096436f, 0.101013f, 0.105713f, 0.110352f, 0.115356f, 0.120605f, 0.125488f, 0.130981f, 0.136353f, 0.142090f,
+ 0.148438f, 0.153931f, 0.159912f, 0.166260f, 0.172485f, 0.179321f, 0.185791f, 0.193115f, 0.199463f, 0.206665f, 0.520020f, 0.552246f,
+ 0.558105f, 0.559570f, 0.559082f, 0.557617f, 0.001151f, 0.003399f, 0.005611f, 0.007439f, 0.009354f, 0.010925f, 0.012489f, 0.014061f,
+ 0.015610f, 0.017258f, 0.018845f, 0.020248f, 0.021484f, 0.023193f, 0.024796f, 0.026459f, 0.028183f, 0.029785f, 0.031738f, 0.033386f,
+ 0.035309f, 0.037384f, 0.039368f, 0.041626f, 0.043701f, 0.046204f, 0.048553f, 0.051178f, 0.053955f, 0.056488f, 0.059418f, 0.062256f,
+ 0.065308f, 0.068542f, 0.071899f, 0.075623f, 0.079224f, 0.082947f, 0.087097f, 0.091064f, 0.095520f, 0.099854f, 0.104736f, 0.109314f,
+ 0.114136f, 0.119324f, 0.124756f, 0.130127f, 0.135498f, 0.141113f, 0.146973f, 0.153198f, 0.159180f, 0.165527f, 0.172241f, 0.178711f,
+ 0.185425f, 0.192749f, 0.507324f, 0.543945f, 0.549316f, 0.552246f, 0.551270f, 0.551270f, 0.001070f, 0.002996f, 0.004986f, 0.006851f,
+ 0.008514f, 0.009850f, 0.011330f, 0.012596f, 0.014015f, 0.015259f, 0.016586f, 0.017731f, 0.019287f, 0.020676f, 0.022079f, 0.023468f,
+ 0.024765f, 0.026489f, 0.028030f, 0.029465f, 0.031311f, 0.032898f, 0.034851f, 0.036743f, 0.038940f, 0.040833f, 0.043091f, 0.045074f,
+ 0.047729f, 0.050079f, 0.052673f, 0.055389f, 0.058136f, 0.061188f, 0.064087f, 0.067261f, 0.070618f, 0.074158f, 0.077942f, 0.081726f,
+ 0.085815f, 0.089783f, 0.094055f, 0.098572f, 0.103088f, 0.107971f, 0.113037f, 0.118164f, 0.123413f, 0.128784f, 0.134521f, 0.140137f,
+ 0.146118f, 0.152100f, 0.158325f, 0.164307f, 0.171387f, 0.177368f, 0.496094f, 0.534668f, 0.541992f, 0.543945f, 0.544434f, 0.544434f,
+ 0.001086f, 0.003069f, 0.004463f, 0.006256f, 0.007393f, 0.009026f, 0.010178f, 0.011276f, 0.012260f, 0.013542f, 0.014648f, 0.015808f,
+ 0.016861f, 0.017899f, 0.019333f, 0.020599f, 0.021942f, 0.023117f, 0.024384f, 0.025833f, 0.027344f, 0.028992f, 0.030579f, 0.032318f,
+ 0.034149f, 0.035828f, 0.037842f, 0.039764f, 0.041901f, 0.044037f, 0.046539f, 0.048645f, 0.051147f, 0.053894f, 0.056641f, 0.059631f,
+ 0.062500f, 0.065735f, 0.069031f, 0.072754f, 0.076294f, 0.080139f, 0.083984f, 0.088379f, 0.092712f, 0.097229f, 0.101929f, 0.106873f,
+ 0.111694f, 0.117004f, 0.122314f, 0.127930f, 0.133789f, 0.139282f, 0.145142f, 0.151367f, 0.157349f, 0.163818f, 0.484619f, 0.525391f,
+ 0.534180f, 0.536621f, 0.536133f, 0.536621f, 0.001125f, 0.002892f, 0.003883f, 0.005867f, 0.006603f, 0.007935f, 0.009026f, 0.009911f,
+ 0.010956f, 0.012077f, 0.012909f, 0.013901f, 0.014977f, 0.015671f, 0.016983f, 0.018021f, 0.019058f, 0.020279f, 0.021225f, 0.022598f,
+ 0.023941f, 0.025299f, 0.026535f, 0.028107f, 0.029755f, 0.031113f, 0.033020f, 0.034668f, 0.036682f, 0.038483f, 0.040527f, 0.042511f,
+ 0.044708f, 0.046936f, 0.049744f, 0.052216f, 0.054840f, 0.057800f, 0.060791f, 0.064087f, 0.067505f, 0.071045f, 0.074463f, 0.078491f,
+ 0.082397f, 0.086609f, 0.091248f, 0.095581f, 0.100342f, 0.105530f, 0.110474f, 0.116272f, 0.120972f, 0.126953f, 0.132812f, 0.138672f,
+ 0.144287f, 0.150513f, 0.472412f, 0.516113f, 0.524902f, 0.528809f, 0.529785f, 0.529785f, 0.000859f, 0.002470f, 0.003815f, 0.005226f,
+ 0.005913f, 0.007206f, 0.007942f, 0.008652f, 0.009583f, 0.010406f, 0.011223f, 0.011971f, 0.012856f, 0.013664f, 0.014664f, 0.015549f,
+ 0.016464f, 0.017487f, 0.018478f, 0.019592f, 0.020767f, 0.021774f, 0.023117f, 0.024338f, 0.025604f, 0.027008f, 0.028519f, 0.029953f,
+ 0.031525f, 0.033173f, 0.034943f, 0.036865f, 0.038696f, 0.040863f, 0.042969f, 0.045471f, 0.048004f, 0.050293f, 0.052979f, 0.055847f,
+ 0.058960f, 0.062042f, 0.065491f, 0.069153f, 0.072937f, 0.076660f, 0.080750f, 0.085144f, 0.089539f, 0.094177f, 0.099304f, 0.104187f,
+ 0.109741f, 0.114807f, 0.120483f, 0.125977f, 0.131836f, 0.138306f, 0.460449f, 0.507812f, 0.516602f, 0.520020f, 0.522461f, 0.522949f,
+ 0.000906f, 0.002359f, 0.003643f, 0.004356f, 0.005310f, 0.005989f, 0.007030f, 0.007507f, 0.008255f, 0.009010f, 0.009834f, 0.010483f,
+ 0.011230f, 0.011887f, 0.012573f, 0.013367f, 0.014252f, 0.014954f, 0.015900f, 0.016785f, 0.017776f, 0.018631f, 0.019775f, 0.020874f,
+ 0.022110f, 0.023117f, 0.024368f, 0.025589f, 0.026932f, 0.028549f, 0.029938f, 0.031525f, 0.033325f, 0.035187f, 0.037109f, 0.038971f,
+ 0.041138f, 0.043396f, 0.045715f, 0.048370f, 0.051025f, 0.053772f, 0.057129f, 0.060089f, 0.063416f, 0.067261f, 0.070679f, 0.075012f,
+ 0.079285f, 0.083618f, 0.088379f, 0.093018f, 0.098083f, 0.102478f, 0.108093f, 0.114380f, 0.119507f, 0.125488f, 0.448975f, 0.498291f,
+ 0.508789f, 0.513672f, 0.514648f, 0.516113f, 0.000728f, 0.001932f, 0.003067f, 0.003990f, 0.004784f, 0.005295f, 0.005974f, 0.006584f,
+ 0.007099f, 0.007652f, 0.008255f, 0.008904f, 0.009491f, 0.010109f, 0.010658f, 0.011497f, 0.012131f, 0.012718f, 0.013535f, 0.014336f,
+ 0.015083f, 0.016083f, 0.016785f, 0.017761f, 0.018738f, 0.019669f, 0.020691f, 0.021805f, 0.023010f, 0.024170f, 0.025467f, 0.026794f,
+ 0.028336f, 0.029922f, 0.031555f, 0.033203f, 0.035034f, 0.036987f, 0.039062f, 0.041290f, 0.043671f, 0.046143f, 0.048920f, 0.051880f,
+ 0.054901f, 0.058228f, 0.061615f, 0.065369f, 0.069214f, 0.073425f, 0.077637f, 0.082214f, 0.087097f, 0.091797f, 0.096497f, 0.102356f,
+ 0.107483f, 0.113464f, 0.437256f, 0.489746f, 0.500977f, 0.504883f, 0.507812f, 0.509277f, 0.000724f, 0.001842f, 0.002728f, 0.003332f,
+ 0.004101f, 0.004707f, 0.005020f, 0.005497f, 0.006245f, 0.006603f, 0.007027f, 0.007515f, 0.008156f, 0.008537f, 0.009125f, 0.009659f,
+ 0.010101f, 0.010864f, 0.011482f, 0.012070f, 0.012756f, 0.013496f, 0.014236f, 0.014931f, 0.015808f, 0.016632f, 0.017487f, 0.018433f,
+ 0.019379f, 0.020416f, 0.021530f, 0.022583f, 0.023804f, 0.024979f, 0.026443f, 0.027939f, 0.029526f, 0.031235f, 0.033020f, 0.035004f,
+ 0.037018f, 0.039185f, 0.041595f, 0.044159f, 0.046783f, 0.049866f, 0.052856f, 0.056274f, 0.059906f, 0.063721f, 0.067749f, 0.072327f,
+ 0.076172f, 0.081299f, 0.085938f, 0.091309f, 0.096558f, 0.101807f, 0.426270f, 0.480469f, 0.492676f, 0.498047f, 0.500488f, 0.501953f,
+ 0.000673f, 0.001715f, 0.002426f, 0.002953f, 0.003588f, 0.003944f, 0.004200f, 0.004776f, 0.005131f, 0.005527f, 0.005886f, 0.006371f,
+ 0.006790f, 0.007076f, 0.007538f, 0.008133f, 0.008644f, 0.009140f, 0.009483f, 0.010071f, 0.010689f, 0.011230f, 0.011879f, 0.012474f,
+ 0.013222f, 0.013916f, 0.014587f, 0.015411f, 0.016190f, 0.016983f, 0.017883f, 0.018845f, 0.019867f, 0.020935f, 0.022141f, 0.023270f,
+ 0.024567f, 0.026001f, 0.027481f, 0.029114f, 0.030777f, 0.032684f, 0.034698f, 0.036865f, 0.039337f, 0.041748f, 0.044647f, 0.047882f,
+ 0.050964f, 0.054260f, 0.058258f, 0.062195f, 0.066528f, 0.070679f, 0.075623f, 0.080505f, 0.085510f, 0.090515f, 0.414307f, 0.472168f,
+ 0.484131f, 0.490234f, 0.492920f, 0.495850f, 0.000484f, 0.001445f, 0.002169f, 0.002569f, 0.002836f, 0.003317f, 0.003569f, 0.003952f,
+ 0.004215f, 0.004623f, 0.004959f, 0.005306f, 0.005592f, 0.005951f, 0.006306f, 0.006737f, 0.007004f, 0.007492f, 0.007942f, 0.008331f,
+ 0.008865f, 0.009270f, 0.009781f, 0.010338f, 0.010887f, 0.011429f, 0.012047f, 0.012726f, 0.013336f, 0.014030f, 0.014771f, 0.015572f,
+ 0.016418f, 0.017258f, 0.018234f, 0.019196f, 0.020279f, 0.021423f, 0.022675f, 0.023987f, 0.025375f, 0.027039f, 0.028702f, 0.030563f,
+ 0.032623f, 0.034698f, 0.037262f, 0.040039f, 0.042664f, 0.046051f, 0.049194f, 0.052948f, 0.057129f, 0.061371f, 0.065613f, 0.070007f,
+ 0.075317f, 0.080200f, 0.402588f, 0.462402f, 0.476807f, 0.482666f, 0.485107f, 0.487061f, 0.000459f, 0.001265f, 0.001572f, 0.002138f,
+ 0.002365f, 0.002775f, 0.002920f, 0.003189f, 0.003454f, 0.003723f, 0.003986f, 0.004250f, 0.004536f, 0.004906f, 0.005150f, 0.005463f,
+ 0.005787f, 0.006172f, 0.006481f, 0.006794f, 0.007156f, 0.007542f, 0.007980f, 0.008430f, 0.008827f, 0.009361f, 0.009796f, 0.010300f,
+ 0.010910f, 0.011497f, 0.012161f, 0.012672f, 0.013336f, 0.014183f, 0.014893f, 0.015640f, 0.016541f, 0.017517f, 0.018448f, 0.019485f,
+ 0.020676f, 0.021912f, 0.023392f, 0.024979f, 0.026627f, 0.028351f, 0.030457f, 0.032806f, 0.035034f, 0.037933f, 0.041229f, 0.044373f,
+ 0.047821f, 0.052002f, 0.056244f, 0.060547f, 0.065247f, 0.069885f, 0.390869f, 0.453857f, 0.468018f, 0.475098f, 0.478027f, 0.480469f,
+ 0.000332f, 0.001075f, 0.001464f, 0.001721f, 0.001911f, 0.002235f, 0.002375f, 0.002558f, 0.002834f, 0.002998f, 0.003185f, 0.003441f,
+ 0.003647f, 0.003952f, 0.004139f, 0.004421f, 0.004631f, 0.004879f, 0.005180f, 0.005447f, 0.005795f, 0.006115f, 0.006416f, 0.006718f,
+ 0.007099f, 0.007462f, 0.007881f, 0.008331f, 0.008797f, 0.009140f, 0.009735f, 0.010223f, 0.010803f, 0.011337f, 0.011986f, 0.012611f,
+ 0.013283f, 0.014076f, 0.014847f, 0.015732f, 0.016693f, 0.017700f, 0.018784f, 0.019897f, 0.021317f, 0.022873f, 0.024429f, 0.026306f,
+ 0.028473f, 0.030960f, 0.033600f, 0.036407f, 0.039856f, 0.043549f, 0.047119f, 0.051392f, 0.055969f, 0.060394f, 0.379639f, 0.444580f,
+ 0.458984f, 0.467529f, 0.470947f, 0.472900f, 0.000408f, 0.000770f, 0.001271f, 0.001390f, 0.001601f, 0.001762f, 0.001848f, 0.002052f,
+ 0.002247f, 0.002401f, 0.002491f, 0.002684f, 0.002878f, 0.003086f, 0.003304f, 0.003452f, 0.003626f, 0.003805f, 0.004074f, 0.004257f,
+ 0.004513f, 0.004807f, 0.005039f, 0.005299f, 0.005638f, 0.005905f, 0.006191f, 0.006516f, 0.006927f, 0.007206f, 0.007645f, 0.008034f,
+ 0.008415f, 0.008911f, 0.009384f, 0.009941f, 0.010483f, 0.011116f, 0.011711f, 0.012428f, 0.013191f, 0.013969f, 0.014862f, 0.015854f,
+ 0.016785f, 0.017975f, 0.019348f, 0.020721f, 0.022461f, 0.024445f, 0.026733f, 0.029175f, 0.032227f, 0.035248f, 0.038788f, 0.042755f,
+ 0.046967f, 0.051636f, 0.367920f, 0.435059f, 0.452148f, 0.459229f, 0.463623f, 0.466797f, 0.000382f, 0.000669f, 0.001037f, 0.001185f,
+ 0.001293f, 0.001379f, 0.001470f, 0.001565f, 0.001729f, 0.001864f, 0.001928f, 0.002138f, 0.002237f, 0.002398f, 0.002510f, 0.002672f,
+ 0.002802f, 0.002966f, 0.003134f, 0.003319f, 0.003517f, 0.003723f, 0.003870f, 0.004089f, 0.004311f, 0.004532f, 0.004772f, 0.005013f,
+ 0.005314f, 0.005573f, 0.005924f, 0.006203f, 0.006523f, 0.006897f, 0.007240f, 0.007660f, 0.008041f, 0.008530f, 0.009048f, 0.009621f,
+ 0.010201f, 0.010841f, 0.011467f, 0.012192f, 0.013138f, 0.013969f, 0.014931f, 0.016113f, 0.017380f, 0.018936f, 0.020630f, 0.022751f,
+ 0.025208f, 0.027924f, 0.031311f, 0.034851f, 0.038879f, 0.043274f, 0.356689f, 0.426270f, 0.443848f, 0.451660f, 0.456055f, 0.459473f,
+ 0.000482f, 0.000542f, 0.000723f, 0.000822f, 0.000881f, 0.001025f, 0.001100f, 0.001209f, 0.001249f, 0.001355f, 0.001522f, 0.001599f,
+ 0.001708f, 0.001836f, 0.001918f, 0.001970f, 0.002129f, 0.002251f, 0.002357f, 0.002522f, 0.002636f, 0.002768f, 0.002911f, 0.003056f,
+ 0.003237f, 0.003393f, 0.003605f, 0.003771f, 0.003994f, 0.004234f, 0.004444f, 0.004635f, 0.004932f, 0.005150f, 0.005486f, 0.005779f,
+ 0.006081f, 0.006458f, 0.006775f, 0.007179f, 0.007668f, 0.008110f, 0.008690f, 0.009209f, 0.009926f, 0.010551f, 0.011330f, 0.012184f,
+ 0.013184f, 0.014297f, 0.015610f, 0.017181f, 0.019165f, 0.021500f, 0.024384f, 0.027618f, 0.031372f, 0.035614f, 0.345459f, 0.417236f,
+ 0.435303f, 0.443604f, 0.448730f, 0.451904f, 0.000240f, 0.000479f, 0.000533f, 0.000625f, 0.000716f, 0.000746f, 0.000857f, 0.000835f,
+ 0.000941f, 0.001024f, 0.001104f, 0.001155f, 0.001204f, 0.001282f, 0.001396f, 0.001453f, 0.001554f, 0.001627f, 0.001737f, 0.001787f,
+ 0.001894f, 0.002012f, 0.002119f, 0.002218f, 0.002335f, 0.002453f, 0.002611f, 0.002714f, 0.002848f, 0.003050f, 0.003168f, 0.003395f,
+ 0.003529f, 0.003740f, 0.003963f, 0.004158f, 0.004429f, 0.004688f, 0.004982f, 0.005280f, 0.005600f, 0.005959f, 0.006340f, 0.006775f,
+ 0.007252f, 0.007748f, 0.008369f, 0.008980f, 0.009705f, 0.010513f, 0.011513f, 0.012665f, 0.014069f, 0.015869f, 0.018158f, 0.020950f,
+ 0.024338f, 0.028366f, 0.335205f, 0.408203f, 0.427002f, 0.435547f, 0.441162f, 0.445312f, 0.000138f, 0.000265f, 0.000381f, 0.000386f,
+ 0.000465f, 0.000556f, 0.000558f, 0.000597f, 0.000659f, 0.000748f, 0.000770f, 0.000786f, 0.000829f, 0.000904f, 0.000940f, 0.001021f,
+ 0.001043f, 0.001139f, 0.001201f, 0.001253f, 0.001327f, 0.001396f, 0.001481f, 0.001555f, 0.001637f, 0.001712f, 0.001813f, 0.001899f,
+ 0.002005f, 0.002140f, 0.002220f, 0.002348f, 0.002462f, 0.002600f, 0.002733f, 0.002932f, 0.003075f, 0.003279f, 0.003452f, 0.003630f,
+ 0.003872f, 0.004166f, 0.004436f, 0.004742f, 0.005077f, 0.005459f, 0.005848f, 0.006310f, 0.006874f, 0.007492f, 0.008171f, 0.009026f,
+ 0.009995f, 0.011307f, 0.013008f, 0.015343f, 0.018265f, 0.021881f, 0.323486f, 0.399170f, 0.418945f, 0.428467f, 0.434326f, 0.437988f,
+ 0.000165f, 0.000260f, 0.000287f, 0.000296f, 0.000331f, 0.000339f, 0.000360f, 0.000395f, 0.000442f, 0.000482f, 0.000487f, 0.000551f,
+ 0.000546f, 0.000611f, 0.000640f, 0.000667f, 0.000711f, 0.000742f, 0.000775f, 0.000816f, 0.000876f, 0.000916f, 0.000974f, 0.001015f,
+ 0.001081f, 0.001123f, 0.001195f, 0.001267f, 0.001317f, 0.001388f, 0.001459f, 0.001558f, 0.001630f, 0.001718f, 0.001804f, 0.001916f,
+ 0.002033f, 0.002148f, 0.002295f, 0.002455f, 0.002583f, 0.002754f, 0.002941f, 0.003134f, 0.003386f, 0.003639f, 0.003910f, 0.004215f,
+ 0.004597f, 0.005013f, 0.005520f, 0.006130f, 0.006821f, 0.007690f, 0.008789f, 0.010452f, 0.012909f, 0.016174f, 0.312012f, 0.390381f,
+ 0.410645f, 0.420654f, 0.426270f, 0.430664f, 0.000057f, 0.000171f, 0.000164f, 0.000170f, 0.000211f, 0.000213f, 0.000229f, 0.000247f,
+ 0.000267f, 0.000279f, 0.000289f, 0.000317f, 0.000349f, 0.000364f, 0.000390f, 0.000407f, 0.000427f, 0.000467f, 0.000476f, 0.000521f,
+ 0.000537f, 0.000561f, 0.000578f, 0.000626f, 0.000667f, 0.000714f, 0.000729f, 0.000753f, 0.000806f, 0.000855f, 0.000911f, 0.000945f,
+ 0.001004f, 0.001054f, 0.001112f, 0.001172f, 0.001251f, 0.001333f, 0.001406f, 0.001489f, 0.001595f, 0.001694f, 0.001811f, 0.001952f,
+ 0.002090f, 0.002243f, 0.002453f, 0.002638f, 0.002888f, 0.003143f, 0.003489f, 0.003870f, 0.004353f, 0.004921f, 0.005672f, 0.006664f,
+ 0.008423f, 0.011230f, 0.301758f, 0.381104f, 0.402832f, 0.413330f, 0.418457f, 0.423828f, 0.000096f, 0.000112f, 0.000097f, 0.000090f,
+ 0.000113f, 0.000119f, 0.000144f, 0.000149f, 0.000151f, 0.000158f, 0.000181f, 0.000184f, 0.000179f, 0.000201f, 0.000224f, 0.000216f,
+ 0.000237f, 0.000255f, 0.000263f, 0.000276f, 0.000297f, 0.000308f, 0.000332f, 0.000347f, 0.000369f, 0.000395f, 0.000408f, 0.000422f,
+ 0.000447f, 0.000471f, 0.000500f, 0.000531f, 0.000554f, 0.000583f, 0.000617f, 0.000660f, 0.000690f, 0.000739f, 0.000795f, 0.000833f,
+ 0.000885f, 0.000948f, 0.001022f, 0.001085f, 0.001175f, 0.001262f, 0.001371f, 0.001487f, 0.001633f, 0.001778f, 0.001986f, 0.002218f,
+ 0.002502f, 0.002865f, 0.003330f, 0.003979f, 0.004932f, 0.007000f, 0.291260f, 0.372070f, 0.394043f, 0.404541f, 0.412109f, 0.416260f,
+ 0.000000f, 0.000056f, 0.000049f, 0.000061f, 0.000064f, 0.000061f, 0.000062f, 0.000071f, 0.000072f, 0.000088f, 0.000083f, 0.000086f,
+ 0.000097f, 0.000094f, 0.000098f, 0.000105f, 0.000116f, 0.000122f, 0.000126f, 0.000134f, 0.000137f, 0.000143f, 0.000150f, 0.000164f,
+ 0.000171f, 0.000183f, 0.000188f, 0.000204f, 0.000214f, 0.000224f, 0.000236f, 0.000255f, 0.000258f, 0.000277f, 0.000293f, 0.000315f,
+ 0.000328f, 0.000349f, 0.000376f, 0.000396f, 0.000426f, 0.000454f, 0.000486f, 0.000521f, 0.000563f, 0.000605f, 0.000657f, 0.000714f,
+ 0.000791f, 0.000866f, 0.000977f, 0.001085f, 0.001243f, 0.001441f, 0.001703f, 0.002058f, 0.002573f, 0.003740f, 0.280029f, 0.362793f,
+ 0.385742f, 0.397217f, 0.404297f, 0.408936f, 0.000058f, 0.000038f, 0.000031f, 0.000027f, 0.000025f, 0.000026f, 0.000025f, 0.000024f,
+ 0.000024f, 0.000027f, 0.000030f, 0.000038f, 0.000032f, 0.000035f, 0.000040f, 0.000041f, 0.000044f, 0.000045f, 0.000045f, 0.000047f,
+ 0.000052f, 0.000058f, 0.000061f, 0.000059f, 0.000065f, 0.000067f, 0.000069f, 0.000073f, 0.000078f, 0.000083f, 0.000089f, 0.000091f,
+ 0.000099f, 0.000103f, 0.000106f, 0.000114f, 0.000124f, 0.000132f, 0.000141f, 0.000150f, 0.000158f, 0.000164f, 0.000180f, 0.000193f,
+ 0.000205f, 0.000225f, 0.000245f, 0.000267f, 0.000297f, 0.000329f, 0.000365f, 0.000416f, 0.000479f, 0.000563f, 0.000676f, 0.000839f,
+ 0.001088f, 0.001589f, 0.270264f, 0.353760f, 0.377197f, 0.390137f, 0.396973f, 0.402100f, 0.000030f, 0.000019f, 0.000016f, 0.000014f,
+ 0.000013f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000007f, 0.000009f,
+ 0.000009f, 0.000008f, 0.000009f, 0.000010f, 0.000011f, 0.000012f, 0.000012f, 0.000014f, 0.000014f, 0.000014f, 0.000015f, 0.000018f,
+ 0.000017f, 0.000017f, 0.000019f, 0.000020f, 0.000022f, 0.000022f, 0.000023f, 0.000026f, 0.000028f, 0.000027f, 0.000030f, 0.000032f,
+ 0.000035f, 0.000038f, 0.000040f, 0.000042f, 0.000045f, 0.000049f, 0.000055f, 0.000060f, 0.000065f, 0.000074f, 0.000078f, 0.000095f,
+ 0.000109f, 0.000129f, 0.000160f, 0.000205f, 0.000284f, 0.000452f, 0.259766f, 0.345703f, 0.369629f, 0.382812f, 0.390625f, 0.395264f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f,
+ 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f,
+ 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000005f, 0.000006f, 0.000009f, 0.000012f, 0.000026f, 0.249878f, 0.336182f,
+ 0.362061f, 0.374512f, 0.382080f, 0.387695f,
+ }
+};
+
+/* 4 different blue noise, one per channel */
+static float blue_noise[64 * 64][4] = {
+ {0.367188f, 0.855469f, 0.523438f, 0.375000f}, {0.242188f, 0.699219f, 0.164062f, 0.292969f},
+ {0.828125f, 0.257812f, 0.449219f, 0.679688f}, {0.128906f, 0.523438f, 0.058594f, 0.164062f},
+ {0.214844f, 0.648438f, 0.750000f, 0.492188f}, {0.535156f, 0.226562f, 0.492188f, 0.429688f},
+ {0.050781f, 0.425781f, 0.886719f, 0.019531f}, {0.199219f, 0.785156f, 0.378906f, 0.984375f},
+ {0.390625f, 0.039062f, 0.222656f, 0.777344f}, {0.574219f, 0.460938f, 0.687500f, 0.085938f},
+ {0.757812f, 0.117188f, 0.968750f, 0.343750f}, {0.109375f, 0.398438f, 0.500000f, 0.871094f},
+ {0.871094f, 0.796875f, 0.628906f, 0.132812f}, {0.289062f, 0.480469f, 0.851562f, 0.484375f},
+ {0.519531f, 0.035156f, 0.234375f, 0.832031f}, {0.390625f, 0.558594f, 0.738281f, 0.636719f},
+ {0.015625f, 0.648438f, 0.910156f, 0.507812f}, {0.199219f, 0.257812f, 0.640625f, 0.578125f},
+ {0.359375f, 0.976562f, 0.855469f, 0.726562f}, {0.523438f, 0.445312f, 0.335938f, 0.304688f},
+ {0.046875f, 0.296875f, 0.921875f, 0.687500f}, {0.476562f, 0.929688f, 0.777344f, 0.164062f},
+ {0.726562f, 0.515625f, 0.398438f, 0.781250f}, {0.652344f, 0.156250f, 0.191406f, 0.015625f},
+ {0.300781f, 0.695312f, 0.011719f, 0.417969f}, {0.433594f, 0.882812f, 0.738281f, 0.843750f},
+ {0.890625f, 0.308594f, 0.523438f, 0.496094f}, {0.589844f, 0.730469f, 0.050781f, 0.886719f},
+ {0.738281f, 0.539062f, 0.683594f, 0.640625f}, {0.421875f, 0.191406f, 0.265625f, 0.996094f},
+ {0.609375f, 0.339844f, 0.617188f, 0.066406f}, {0.371094f, 0.398438f, 0.378906f, 0.898438f},
+ {0.937500f, 0.578125f, 0.136719f, 0.136719f}, {0.453125f, 0.820312f, 0.664062f, 0.968750f},
+ {0.828125f, 0.070312f, 0.316406f, 0.328125f}, {0.558594f, 0.714844f, 0.593750f, 0.714844f},
+ {0.351562f, 0.781250f, 0.355469f, 0.804688f}, {0.203125f, 0.398438f, 0.214844f, 0.519531f},
+ {0.785156f, 0.207031f, 0.398438f, 0.453125f}, {0.617188f, 0.289062f, 0.281250f, 0.257812f},
+ {0.171875f, 0.609375f, 0.792969f, 0.027344f}, {0.539062f, 0.871094f, 0.007812f, 0.886719f},
+ {0.019531f, 0.246094f, 0.226562f, 0.363281f}, {0.988281f, 0.582031f, 0.777344f, 0.054688f},
+ {0.468750f, 0.933594f, 0.312500f, 0.246094f}, {0.218750f, 0.015625f, 0.851562f, 0.167969f},
+ {0.566406f, 0.699219f, 0.519531f, 0.902344f}, {0.125000f, 0.507812f, 0.136719f, 0.386719f},
+ {0.296875f, 0.812500f, 0.558594f, 0.203125f}, {0.402344f, 0.199219f, 0.058594f, 0.875000f},
+ {0.898438f, 0.386719f, 0.664062f, 0.660156f}, {0.027344f, 0.078125f, 0.296875f, 0.453125f},
+ {0.667969f, 0.828125f, 0.808594f, 0.171875f}, {0.257812f, 0.535156f, 0.464844f, 0.914062f},
+ {0.597656f, 0.363281f, 0.886719f, 0.718750f}, {0.332031f, 0.042969f, 0.683594f, 0.003906f},
+ {0.632812f, 0.480469f, 0.429688f, 0.425781f}, {0.226562f, 0.910156f, 0.566406f, 0.558594f},
+ {0.496094f, 0.062500f, 0.863281f, 0.226562f}, {0.105469f, 0.976562f, 0.707031f, 0.941406f},
+ {0.394531f, 0.203125f, 0.285156f, 0.277344f}, {0.003906f, 0.804688f, 0.781250f, 0.050781f},
+ {0.210938f, 0.289062f, 0.117188f, 0.601562f}, {0.972656f, 0.179688f, 0.589844f, 0.144531f},
+ {0.152344f, 0.359375f, 0.730469f, 0.449219f}, {0.765625f, 0.105469f, 0.292969f, 0.101562f},
+ {0.519531f, 0.812500f, 0.617188f, 0.976562f}, {0.988281f, 0.960938f, 0.902344f, 0.054688f},
+ {0.457031f, 0.738281f, 0.335938f, 0.875000f}, {0.871094f, 0.121094f, 0.195312f, 0.210938f},
+ {0.781250f, 0.296875f, 0.539062f, 0.585938f}, {0.636719f, 0.667969f, 0.621094f, 0.328125f},
+ {0.324219f, 0.929688f, 0.855469f, 0.148438f}, {0.984375f, 0.718750f, 0.421875f, 0.824219f},
+ {0.500000f, 0.308594f, 0.757812f, 0.699219f}, {0.664062f, 0.214844f, 0.269531f, 0.558594f},
+ {0.414062f, 0.984375f, 0.074219f, 0.757812f}, {0.589844f, 0.339844f, 0.925781f, 0.273438f},
+ {0.089844f, 0.847656f, 0.316406f, 0.398438f}, {0.695312f, 0.921875f, 0.460938f, 0.890625f},
+ {0.894531f, 0.093750f, 0.113281f, 0.347656f}, {0.562500f, 0.386719f, 0.289062f, 0.964844f},
+ {0.121094f, 0.820312f, 0.003906f, 0.214844f}, {0.765625f, 0.187500f, 0.710938f, 0.914062f},
+ {0.878906f, 0.773438f, 0.445312f, 0.078125f}, {0.218750f, 0.117188f, 0.613281f, 0.617188f},
+ {0.085938f, 0.652344f, 0.996094f, 0.339844f}, {0.863281f, 0.359375f, 0.496094f, 0.531250f},
+ {0.148438f, 0.437500f, 0.320312f, 0.695312f}, {0.503906f, 0.613281f, 0.792969f, 0.082031f},
+ {0.097656f, 0.109375f, 0.960938f, 0.238281f}, {0.246094f, 0.914062f, 0.414062f, 0.328125f},
+ {0.011719f, 0.648438f, 0.828125f, 0.738281f}, {0.980469f, 0.457031f, 0.343750f, 0.117188f},
+ {0.140625f, 0.937500f, 0.976562f, 0.601562f}, {0.234375f, 0.867188f, 0.574219f, 0.230469f},
+ {0.542969f, 0.519531f, 0.902344f, 0.402344f}, {0.027344f, 0.300781f, 0.253906f, 0.503906f},
+ {0.757812f, 0.964844f, 0.949219f, 0.058594f}, {0.152344f, 0.234375f, 0.039062f, 0.925781f},
+ {0.687500f, 0.628906f, 0.492188f, 0.386719f}, {0.929688f, 0.546875f, 0.667969f, 0.109375f},
+ {0.269531f, 0.136719f, 0.964844f, 0.617188f}, {0.320312f, 0.464844f, 0.542969f, 0.972656f},
+ {0.960938f, 0.960938f, 0.171875f, 0.093750f}, {0.355469f, 0.523438f, 0.429688f, 0.765625f},
+ {0.246094f, 0.328125f, 0.992188f, 0.496094f}, {0.648438f, 0.074219f, 0.097656f, 0.605469f},
+ {0.144531f, 0.648438f, 0.476562f, 0.808594f}, {0.855469f, 0.832031f, 0.195312f, 0.546875f},
+ {0.925781f, 0.414062f, 0.960938f, 0.675781f}, {0.000000f, 0.113281f, 0.746094f, 0.835938f},
+ {0.828125f, 0.324219f, 0.613281f, 0.500000f}, {0.699219f, 0.738281f, 0.332031f, 0.125000f},
+ {0.542969f, 0.906250f, 0.898438f, 0.250000f}, {0.105469f, 0.632812f, 0.511719f, 0.062500f},
+ {0.433594f, 0.273438f, 0.097656f, 0.816406f}, {0.511719f, 0.707031f, 0.593750f, 0.632812f},
+ {0.179688f, 0.980469f, 0.367188f, 0.335938f}, {0.882812f, 0.113281f, 0.031250f, 0.980469f},
+ {0.410156f, 0.656250f, 0.253906f, 0.675781f}, {0.039062f, 0.300781f, 0.785156f, 0.800781f},
+ {0.695312f, 0.382812f, 0.386719f, 0.156250f}, {0.847656f, 0.457031f, 0.000000f, 0.847656f},
+ {0.945312f, 0.542969f, 0.664062f, 0.683594f}, {0.730469f, 0.707031f, 0.238281f, 0.535156f},
+ {0.472656f, 0.921875f, 0.871094f, 0.910156f}, {0.867188f, 0.601562f, 0.031250f, 0.812500f},
+ {0.632812f, 0.769531f, 0.925781f, 0.625000f}, {0.433594f, 0.558594f, 0.078125f, 0.851562f},
+ {0.015625f, 0.187500f, 0.792969f, 0.515625f}, {0.343750f, 0.386719f, 0.562500f, 0.773438f},
+ {0.679688f, 0.035156f, 0.121094f, 0.347656f}, {0.300781f, 0.582031f, 0.703125f, 0.660156f},
+ {0.152344f, 0.878906f, 0.929688f, 0.902344f}, {0.433594f, 0.507812f, 0.093750f, 0.460938f},
+ {0.714844f, 0.171875f, 0.042969f, 0.531250f}, {0.828125f, 0.550781f, 0.312500f, 0.945312f},
+ {0.011719f, 0.894531f, 0.136719f, 0.417969f}, {0.257812f, 0.046875f, 0.562500f, 0.226562f},
+ {0.187500f, 0.601562f, 0.800781f, 0.929688f}, {0.949219f, 0.128906f, 0.437500f, 0.613281f},
+ {0.816406f, 0.277344f, 0.054688f, 0.035156f}, {0.226562f, 0.425781f, 0.542969f, 0.183594f},
+ {0.628906f, 0.750000f, 0.984375f, 0.113281f}, {0.839844f, 0.003906f, 0.792969f, 0.796875f},
+ {0.269531f, 0.324219f, 0.496094f, 0.003906f}, {0.683594f, 0.601562f, 0.574219f, 0.546875f},
+ {0.957031f, 0.703125f, 0.164062f, 0.378906f}, {0.605469f, 0.398438f, 0.078125f, 0.855469f},
+ {0.449219f, 0.250000f, 0.257812f, 0.988281f}, {0.367188f, 0.964844f, 0.859375f, 0.195312f},
+ {0.820312f, 0.007812f, 0.125000f, 0.753906f}, {0.625000f, 0.832031f, 0.453125f, 0.609375f},
+ {0.929688f, 0.230469f, 0.246094f, 0.925781f}, {0.394531f, 0.375000f, 0.097656f, 0.550781f},
+ {0.558594f, 0.148438f, 0.183594f, 0.191406f}, {0.480469f, 0.796875f, 0.488281f, 0.785156f},
+ {0.714844f, 0.250000f, 0.011719f, 0.296875f}, {0.660156f, 0.085938f, 0.804688f, 0.691406f},
+ {0.890625f, 0.695312f, 0.101562f, 0.855469f}, {0.320312f, 0.195312f, 0.441406f, 0.761719f},
+ {0.265625f, 0.375000f, 0.765625f, 0.191406f}, {0.996094f, 0.113281f, 0.832031f, 0.585938f},
+ {0.101562f, 0.882812f, 0.152344f, 0.285156f}, {0.468750f, 0.332031f, 0.722656f, 0.882812f},
+ {0.656250f, 0.816406f, 0.105469f, 0.339844f}, {0.035156f, 0.703125f, 0.855469f, 0.687500f},
+ {0.738281f, 0.003906f, 0.601562f, 0.566406f}, {0.441406f, 0.664062f, 0.703125f, 0.843750f},
+ {0.875000f, 0.789062f, 0.839844f, 0.187500f}, {0.781250f, 0.457031f, 0.640625f, 0.996094f},
+ {0.050781f, 0.210938f, 0.355469f, 0.332031f}, {0.363281f, 0.351562f, 0.039062f, 0.421875f},
+ {0.429688f, 0.550781f, 0.699219f, 0.089844f}, {0.753906f, 0.917969f, 0.269531f, 0.285156f},
+ {0.496094f, 0.058594f, 0.929688f, 0.980469f}, {0.343750f, 0.445312f, 0.445312f, 0.566406f},
+ {0.152344f, 0.160156f, 0.003906f, 0.750000f}, {0.738281f, 0.570312f, 0.847656f, 0.941406f},
+ {0.808594f, 0.027344f, 0.167969f, 0.292969f}, {0.992188f, 0.867188f, 0.921875f, 0.519531f},
+ {0.074219f, 0.187500f, 0.761719f, 0.199219f}, {0.750000f, 0.597656f, 0.312500f, 0.472656f},
+ {0.277344f, 0.753906f, 0.945312f, 0.089844f}, {0.796875f, 0.820312f, 0.511719f, 0.375000f},
+ {0.542969f, 0.878906f, 0.191406f, 0.503906f}, {0.175781f, 0.632812f, 0.597656f, 0.109375f},
+ {0.257812f, 0.335938f, 0.980469f, 0.339844f}, {0.664062f, 0.000000f, 0.542969f, 0.417969f},
+ {0.324219f, 0.144531f, 0.410156f, 0.078125f}, {0.062500f, 0.437500f, 0.472656f, 0.250000f},
+ {0.925781f, 0.058594f, 0.636719f, 0.332031f}, {0.269531f, 0.671875f, 0.234375f, 0.175781f},
+ {0.714844f, 0.285156f, 0.382812f, 0.574219f}, {0.570312f, 0.906250f, 0.988281f, 0.414062f},
+ {0.097656f, 0.460938f, 0.425781f, 0.257812f}, {0.953125f, 0.796875f, 0.265625f, 0.117188f},
+ {0.589844f, 0.367188f, 0.777344f, 0.746094f}, {0.035156f, 0.082031f, 0.457031f, 0.062500f},
+ {0.226562f, 0.253906f, 0.953125f, 0.628906f}, {0.527344f, 0.417969f, 0.519531f, 0.261719f},
+ {0.132812f, 0.812500f, 0.828125f, 0.000000f}, {0.906250f, 0.660156f, 0.386719f, 0.367188f},
+ {0.742188f, 0.500000f, 0.207031f, 0.093750f}, {0.359375f, 0.769531f, 0.609375f, 0.718750f},
+ {0.480469f, 0.695312f, 0.679688f, 0.539062f}, {0.144531f, 0.179688f, 0.757812f, 0.765625f},
+ {0.332031f, 0.625000f, 0.179688f, 0.679688f}, {0.445312f, 0.492188f, 0.378906f, 0.425781f},
+ {0.035156f, 0.550781f, 0.230469f, 0.476562f}, {0.402344f, 0.898438f, 0.898438f, 0.652344f},
+ {0.156250f, 0.046875f, 0.820312f, 0.132812f}, {0.328125f, 0.484375f, 0.679688f, 0.246094f},
+ {0.746094f, 0.750000f, 0.363281f, 0.453125f}, {0.238281f, 0.863281f, 0.558594f, 0.105469f},
+ {0.023438f, 0.289062f, 0.648438f, 0.292969f}, {0.683594f, 0.566406f, 0.906250f, 0.804688f},
+ {0.335938f, 0.773438f, 0.601562f, 0.375000f}, {0.781250f, 0.496094f, 0.710938f, 0.023438f},
+ {0.847656f, 0.996094f, 0.929688f, 0.425781f}, {0.308594f, 0.027344f, 0.656250f, 0.871094f},
+ {0.183594f, 0.625000f, 0.292969f, 0.480469f}, {0.089844f, 0.753906f, 0.164062f, 0.363281f},
+ {0.804688f, 0.476562f, 0.687500f, 0.011719f}, {0.503906f, 0.910156f, 0.523438f, 0.644531f},
+ {0.605469f, 0.609375f, 0.203125f, 0.441406f}, {0.417969f, 0.742188f, 0.621094f, 0.085938f},
+ {0.839844f, 0.441406f, 0.296875f, 0.679688f}, {0.531250f, 0.042969f, 0.929688f, 0.781250f},
+ {0.378906f, 0.929688f, 0.460938f, 0.148438f}, {0.902344f, 0.238281f, 0.050781f, 0.222656f},
+ {0.570312f, 0.378906f, 0.328125f, 0.390625f}, {0.105469f, 0.121094f, 0.253906f, 0.460938f},
+ {0.500000f, 0.906250f, 0.515625f, 0.281250f}, {0.296875f, 0.160156f, 0.148438f, 0.664062f},
+ {0.699219f, 0.722656f, 0.757812f, 0.007812f}, {0.539062f, 0.968750f, 0.589844f, 0.914062f},
+ {0.253906f, 0.246094f, 0.406250f, 0.769531f}, {0.609375f, 0.613281f, 0.105469f, 0.707031f},
+ {0.195312f, 0.687500f, 0.179688f, 0.031250f}, {0.949219f, 0.523438f, 0.785156f, 0.339844f},
+ {0.863281f, 0.804688f, 0.234375f, 0.433594f}, {0.230469f, 0.355469f, 0.648438f, 0.687500f},
+ {0.304688f, 0.757812f, 0.421875f, 0.378906f}, {0.375000f, 0.464844f, 0.539062f, 0.046875f},
+ {0.558594f, 0.324219f, 0.214844f, 0.761719f}, {0.679688f, 0.410156f, 0.074219f, 0.839844f},
+ {0.464844f, 0.519531f, 0.710938f, 0.281250f}, {0.968750f, 0.152344f, 0.140625f, 0.925781f},
+ {0.359375f, 0.230469f, 0.902344f, 0.609375f}, {0.593750f, 0.097656f, 0.457031f, 0.761719f},
+ {0.441406f, 0.785156f, 0.058594f, 0.960938f}, {0.125000f, 0.890625f, 0.312500f, 0.203125f},
+ {0.812500f, 0.488281f, 0.804688f, 0.878906f}, {0.558594f, 0.992188f, 0.175781f, 0.742188f},
+ {0.179688f, 0.222656f, 0.343750f, 0.039062f}, {0.789062f, 0.871094f, 0.843750f, 0.949219f},
+ {0.902344f, 0.503906f, 0.507812f, 0.718750f}, {0.402344f, 0.625000f, 0.027344f, 0.011719f},
+ {0.195312f, 0.152344f, 0.605469f, 0.929688f}, {0.753906f, 0.214844f, 0.160156f, 0.839844f},
+ {0.488281f, 0.687500f, 0.671875f, 0.390625f}, {0.851562f, 0.992188f, 0.363281f, 0.191406f},
+ {0.933594f, 0.617188f, 0.230469f, 0.308594f}, {0.375000f, 0.746094f, 0.656250f, 0.867188f},
+ {0.613281f, 0.105469f, 0.898438f, 0.671875f}, {0.316406f, 0.371094f, 0.714844f, 0.503906f},
+ {0.687500f, 0.234375f, 0.031250f, 0.808594f}, {0.550781f, 0.957031f, 0.957031f, 0.433594f},
+ {0.023438f, 0.539062f, 0.351562f, 0.308594f}, {0.964844f, 0.359375f, 0.261719f, 0.980469f},
+ {0.750000f, 0.941406f, 0.863281f, 0.234375f}, {0.906250f, 0.863281f, 0.605469f, 0.863281f},
+ {0.503906f, 0.109375f, 0.093750f, 0.289062f}, {0.582031f, 0.238281f, 0.414062f, 0.949219f},
+ {0.792969f, 0.992188f, 0.308594f, 0.757812f}, {0.062500f, 0.164062f, 0.039062f, 0.816406f},
+ {0.902344f, 0.542969f, 0.933594f, 0.675781f}, {0.554688f, 0.085938f, 0.726562f, 0.507812f},
+ {0.984375f, 0.460938f, 0.175781f, 0.890625f}, {0.468750f, 0.179688f, 0.027344f, 0.140625f},
+ {0.125000f, 0.679688f, 0.304688f, 0.468750f}, {0.203125f, 0.058594f, 0.531250f, 0.953125f},
+ {0.070312f, 0.328125f, 0.375000f, 0.667969f}, {0.746094f, 0.554688f, 0.785156f, 0.578125f},
+ {0.917969f, 0.421875f, 0.558594f, 0.089844f}, {0.445312f, 0.289062f, 0.855469f, 0.937500f},
+ {0.378906f, 0.156250f, 0.398438f, 0.539062f}, {0.066406f, 0.015625f, 0.335938f, 0.265625f},
+ {0.730469f, 0.812500f, 0.878906f, 0.820312f}, {0.191406f, 0.535156f, 0.015625f, 0.988281f},
+ {0.046875f, 0.171875f, 0.554688f, 0.484375f}, {0.777344f, 0.656250f, 0.375000f, 0.015625f},
+ {0.230469f, 0.488281f, 0.238281f, 0.535156f}, {0.144531f, 0.578125f, 0.750000f, 0.910156f},
+ {0.812500f, 0.757812f, 0.910156f, 0.714844f}, {0.207031f, 0.429688f, 0.386719f, 0.042969f},
+ {0.945312f, 0.292969f, 0.023438f, 0.136719f}, {0.597656f, 0.859375f, 0.941406f, 0.742188f},
+ {0.171875f, 0.593750f, 0.289062f, 0.519531f}, {0.914062f, 0.031250f, 0.886719f, 0.234375f},
+ {0.808594f, 0.773438f, 0.824219f, 0.160156f}, {0.082031f, 0.132812f, 0.496094f, 0.464844f},
+ {0.664062f, 0.871094f, 0.675781f, 0.597656f}, {0.042969f, 0.289062f, 0.546875f, 0.195312f},
+ {0.453125f, 0.996094f, 0.363281f, 0.859375f}, {0.585938f, 0.226562f, 0.718750f, 0.140625f},
+ {0.648438f, 0.093750f, 0.277344f, 0.609375f}, {0.035156f, 0.933594f, 0.980469f, 0.898438f},
+ {0.910156f, 0.671875f, 0.625000f, 0.410156f}, {0.210938f, 0.246094f, 0.472656f, 0.578125f},
+ {0.136719f, 0.960938f, 0.832031f, 0.031250f}, {0.066406f, 0.054688f, 0.656250f, 0.660156f},
+ {0.898438f, 0.714844f, 0.347656f, 0.218750f}, {0.765625f, 0.589844f, 0.820312f, 0.449219f},
+ {0.023438f, 0.398438f, 0.734375f, 0.011719f}, {0.960938f, 0.253906f, 0.132812f, 0.582031f},
+ {0.378906f, 0.644531f, 0.945312f, 0.480469f}, {0.496094f, 0.320312f, 0.683594f, 0.656250f},
+ {0.085938f, 0.722656f, 0.105469f, 0.386719f}, {0.316406f, 0.414062f, 0.753906f, 0.226562f},
+ {0.046875f, 0.011719f, 0.199219f, 0.464844f}, {0.621094f, 0.968750f, 0.714844f, 0.300781f},
+ {0.878906f, 0.726562f, 0.863281f, 0.593750f}, {0.257812f, 0.312500f, 0.324219f, 0.523438f},
+ {0.347656f, 0.835938f, 0.816406f, 0.687500f}, {0.074219f, 0.480469f, 0.000000f, 0.972656f},
+ {0.656250f, 0.007812f, 0.578125f, 0.785156f}, {0.792969f, 0.914062f, 0.152344f, 0.570312f},
+ {0.464844f, 0.292969f, 0.292969f, 0.152344f}, {0.863281f, 0.843750f, 0.101562f, 0.957031f},
+ {0.066406f, 0.449219f, 0.484375f, 0.199219f}, {0.437500f, 0.019531f, 0.878906f, 0.886719f},
+ {0.800781f, 0.074219f, 0.132812f, 0.136719f}, {0.296875f, 0.800781f, 0.511719f, 0.488281f},
+ {0.656250f, 0.253906f, 0.019531f, 0.371094f}, {0.101562f, 0.148438f, 0.726562f, 0.609375f},
+ {0.203125f, 0.664062f, 0.660156f, 0.089844f}, {0.976562f, 0.437500f, 0.972656f, 0.175781f},
+ {0.289062f, 0.781250f, 0.765625f, 0.578125f}, {0.660156f, 0.343750f, 0.519531f, 0.312500f},
+ {0.507812f, 0.625000f, 0.441406f, 0.019531f}, {0.175781f, 0.933594f, 0.230469f, 0.394531f},
+ {0.796875f, 0.722656f, 0.824219f, 0.570312f}, {0.277344f, 0.410156f, 0.406250f, 0.226562f},
+ {0.597656f, 0.949219f, 0.761719f, 0.707031f}, {0.949219f, 0.609375f, 0.882812f, 0.070312f},
+ {0.519531f, 0.859375f, 0.128906f, 0.273438f}, {0.632812f, 0.203125f, 0.042969f, 0.156250f},
+ {0.265625f, 0.890625f, 0.449219f, 0.812500f}, {0.585938f, 0.664062f, 0.230469f, 0.210938f},
+ {0.968750f, 0.960938f, 0.742188f, 0.726562f}, {0.226562f, 0.339844f, 0.992188f, 0.117188f},
+ {0.875000f, 0.410156f, 0.093750f, 0.894531f}, {0.640625f, 0.261719f, 0.710938f, 0.324219f},
+ {0.917969f, 0.980469f, 0.425781f, 0.234375f}, {0.308594f, 0.300781f, 0.804688f, 0.628906f},
+ {0.589844f, 0.105469f, 0.648438f, 0.421875f}, {0.714844f, 0.847656f, 0.125000f, 0.808594f},
+ {0.406250f, 0.187500f, 0.480469f, 0.300781f}, {0.667969f, 0.992188f, 0.679688f, 0.960938f},
+ {0.070312f, 0.542969f, 0.800781f, 0.859375f}, {0.835938f, 0.082031f, 0.554688f, 0.578125f},
+ {0.398438f, 0.496094f, 0.449219f, 0.402344f}, {0.113281f, 0.398438f, 0.222656f, 0.828125f},
+ {0.460938f, 0.308594f, 0.054688f, 0.625000f}, {0.976562f, 0.472656f, 0.984375f, 0.375000f},
+ {0.281250f, 0.203125f, 0.312500f, 0.937500f}, {0.386719f, 0.000000f, 0.875000f, 0.785156f},
+ {0.785156f, 0.402344f, 0.078125f, 0.527344f}, {0.117188f, 0.644531f, 0.812500f, 0.082031f},
+ {0.941406f, 0.503906f, 0.132812f, 0.972656f}, {0.488281f, 0.140625f, 0.023438f, 0.238281f},
+ {0.832031f, 0.843750f, 0.859375f, 0.167969f}, {0.335938f, 0.011719f, 0.382812f, 0.730469f},
+ {0.628906f, 0.777344f, 0.570312f, 0.875000f}, {0.527344f, 0.355469f, 0.285156f, 0.132812f},
+ {0.234375f, 0.472656f, 0.093750f, 0.312500f}, {0.308594f, 0.941406f, 0.214844f, 0.820312f},
+ {0.640625f, 0.164062f, 0.628906f, 0.714844f}, {0.871094f, 0.832031f, 0.390625f, 0.156250f},
+ {0.218750f, 0.531250f, 0.265625f, 0.289062f}, {0.699219f, 0.117188f, 0.550781f, 0.796875f},
+ {0.980469f, 0.578125f, 0.890625f, 0.125000f}, {0.523438f, 0.824219f, 0.460938f, 0.890625f},
+ {0.445312f, 0.347656f, 0.285156f, 0.675781f}, {0.816406f, 0.097656f, 0.949219f, 0.781250f},
+ {0.140625f, 0.550781f, 0.089844f, 0.160156f}, {0.675781f, 0.421875f, 0.484375f, 0.074219f},
+ {0.542969f, 0.062500f, 0.535156f, 0.230469f}, {0.421875f, 0.570312f, 0.886719f, 0.484375f},
+ {0.167969f, 0.339844f, 0.734375f, 0.035156f}, {0.277344f, 0.199219f, 0.425781f, 0.441406f},
+ {0.093750f, 0.527344f, 0.996094f, 0.714844f}, {0.214844f, 0.148438f, 0.632812f, 0.335938f},
+ {0.941406f, 0.585938f, 0.242188f, 0.593750f}, {0.160156f, 0.886719f, 0.410156f, 0.652344f},
+ {0.597656f, 0.679688f, 0.812500f, 0.019531f}, {0.242188f, 0.312500f, 0.585938f, 0.562500f},
+ {0.531250f, 0.460938f, 0.937500f, 0.921875f}, {0.375000f, 0.734375f, 0.328125f, 0.054688f},
+ {0.703125f, 0.382812f, 0.472656f, 0.734375f}, {0.824219f, 0.835938f, 0.140625f, 0.519531f},
+ {0.441406f, 0.289062f, 0.203125f, 0.414062f}, {0.121094f, 0.691406f, 0.628906f, 0.925781f},
+ {0.378906f, 0.019531f, 0.105469f, 0.082031f}, {0.714844f, 0.222656f, 0.347656f, 0.734375f},
+ {0.046875f, 0.816406f, 0.968750f, 0.976562f}, {0.421875f, 0.320312f, 0.078125f, 0.628906f},
+ {0.871094f, 0.097656f, 0.484375f, 0.835938f}, {0.695312f, 0.265625f, 0.207031f, 0.332031f},
+ {0.351562f, 0.718750f, 0.273438f, 0.761719f}, {0.406250f, 0.382812f, 0.957031f, 0.511719f},
+ {0.042969f, 0.785156f, 0.628906f, 0.980469f}, {0.832031f, 0.117188f, 0.910156f, 0.343750f},
+ {0.144531f, 0.500000f, 0.058594f, 0.421875f}, {0.699219f, 0.843750f, 0.589844f, 0.601562f},
+ {0.546875f, 0.574219f, 0.488281f, 0.164062f}, {0.363281f, 0.054688f, 0.265625f, 0.390625f},
+ {0.128906f, 0.785156f, 0.949219f, 0.746094f}, {0.492188f, 0.691406f, 0.175781f, 0.949219f},
+ {0.972656f, 0.902344f, 0.894531f, 0.183594f}, {0.027344f, 0.359375f, 0.570312f, 0.070312f},
+ {0.273438f, 0.062500f, 0.207031f, 0.500000f}, {0.472656f, 0.730469f, 0.972656f, 0.613281f},
+ {0.351562f, 0.640625f, 0.089844f, 0.363281f}, {0.742188f, 0.226562f, 0.187500f, 0.195312f},
+ {0.234375f, 0.699219f, 0.730469f, 0.945312f}, {0.625000f, 0.945312f, 0.636719f, 0.082031f},
+ {0.328125f, 0.839844f, 0.378906f, 0.312500f}, {0.707031f, 0.652344f, 0.574219f, 0.875000f},
+ {0.566406f, 0.742188f, 0.148438f, 0.050781f}, {0.882812f, 0.921875f, 0.460938f, 0.246094f},
+ {0.519531f, 0.585938f, 0.917969f, 0.656250f}, {0.730469f, 0.718750f, 0.597656f, 0.316406f},
+ {0.261719f, 0.808594f, 0.500000f, 0.460938f}, {0.171875f, 0.285156f, 0.324219f, 0.796875f},
+ {0.773438f, 0.562500f, 0.746094f, 0.546875f}, {0.433594f, 0.429688f, 0.183594f, 0.343750f},
+ {0.726562f, 0.628906f, 0.050781f, 0.488281f}, {0.859375f, 0.898438f, 0.972656f, 0.996094f},
+ {0.402344f, 0.542969f, 0.429688f, 0.402344f}, {0.101562f, 0.304688f, 0.535156f, 0.542969f},
+ {0.476562f, 0.675781f, 0.863281f, 0.902344f}, {0.734375f, 0.035156f, 0.488281f, 0.359375f},
+ {0.289062f, 0.761719f, 0.773438f, 0.976562f}, {0.589844f, 0.949219f, 0.007812f, 0.519531f},
+ {0.843750f, 0.269531f, 0.417969f, 0.835938f}, {0.664062f, 0.183594f, 0.144531f, 0.554688f},
+ {0.226562f, 0.652344f, 0.656250f, 0.085938f}, {0.367188f, 0.789062f, 0.562500f, 0.957031f},
+ {0.972656f, 0.238281f, 0.394531f, 0.433594f}, {0.000000f, 0.894531f, 0.207031f, 0.644531f},
+ {0.777344f, 0.136719f, 0.968750f, 0.820312f}, {0.910156f, 0.949219f, 0.261719f, 0.355469f},
+ {0.722656f, 0.785156f, 0.070312f, 0.917969f}, {0.996094f, 0.707031f, 0.792969f, 0.105469f},
+ {0.562500f, 0.644531f, 0.511719f, 0.246094f}, {0.648438f, 0.937500f, 0.335938f, 0.851562f},
+ {0.398438f, 0.738281f, 0.777344f, 0.078125f}, {0.832031f, 0.410156f, 0.695312f, 0.285156f},
+ {0.722656f, 0.210938f, 0.167969f, 0.785156f}, {0.042969f, 0.609375f, 0.296875f, 0.214844f},
+ {0.863281f, 0.976562f, 0.441406f, 0.824219f}, {0.167969f, 0.027344f, 0.066406f, 0.664062f},
+ {0.609375f, 0.562500f, 0.828125f, 0.347656f}, {0.000000f, 0.191406f, 0.562500f, 0.839844f},
+ {0.250000f, 0.070312f, 0.281250f, 0.207031f}, {0.875000f, 0.875000f, 0.917969f, 0.644531f},
+ {0.941406f, 0.523438f, 0.781250f, 0.867188f}, {0.617188f, 0.378906f, 0.687500f, 0.343750f},
+ {0.316406f, 0.132812f, 0.546875f, 0.171875f}, {0.542969f, 0.574219f, 0.609375f, 0.101562f},
+ {0.230469f, 0.484375f, 0.851562f, 0.433594f}, {0.007812f, 0.828125f, 0.671875f, 0.910156f},
+ {0.160156f, 0.160156f, 0.734375f, 0.605469f}, {0.890625f, 0.527344f, 0.351562f, 0.394531f},
+ {0.757812f, 0.042969f, 0.511719f, 0.039062f}, {0.507812f, 0.593750f, 0.144531f, 0.640625f},
+ {0.335938f, 0.238281f, 0.316406f, 0.781250f}, {0.464844f, 0.726562f, 0.191406f, 0.500000f},
+ {0.000000f, 0.093750f, 0.667969f, 0.707031f}, {0.273438f, 0.636719f, 0.843750f, 0.031250f},
+ {0.746094f, 0.210938f, 0.101562f, 0.570312f}, {0.437500f, 0.421875f, 0.343750f, 0.832031f},
+ {0.625000f, 0.519531f, 0.027344f, 0.355469f}, {0.824219f, 0.613281f, 0.777344f, 0.667969f},
+ {0.886719f, 0.261719f, 0.296875f, 0.121094f}, {0.554688f, 0.476562f, 0.609375f, 0.777344f},
+ {0.992188f, 0.328125f, 0.417969f, 0.253906f}, {0.007812f, 0.812500f, 0.339844f, 0.050781f},
+ {0.519531f, 0.371094f, 0.921875f, 0.476562f}, {0.867188f, 0.167969f, 0.121094f, 0.660156f},
+ {0.773438f, 0.054688f, 0.789062f, 0.718750f}, {0.066406f, 0.535156f, 0.253906f, 0.128906f},
+ {0.156250f, 0.343750f, 0.753906f, 0.503906f}, {0.218750f, 0.437500f, 0.027344f, 0.410156f},
+ {0.347656f, 0.070312f, 0.398438f, 0.839844f}, {0.019531f, 0.175781f, 0.222656f, 0.714844f},
+ {0.410156f, 0.375000f, 0.953125f, 0.011719f}, {0.605469f, 0.886719f, 0.652344f, 0.640625f},
+ {0.093750f, 0.082031f, 0.414062f, 0.097656f}, {0.289062f, 0.707031f, 0.886719f, 0.269531f},
+ {0.003906f, 0.195312f, 0.242188f, 0.691406f}, {0.980469f, 0.261719f, 0.781250f, 0.070312f},
+ {0.671875f, 0.070312f, 0.722656f, 0.621094f}, {0.820312f, 0.851562f, 0.914062f, 0.250000f},
+ {0.550781f, 0.429688f, 0.164062f, 0.097656f}, {0.140625f, 0.210938f, 0.082031f, 0.671875f},
+ {0.042969f, 0.367188f, 0.996094f, 0.054688f}, {0.394531f, 0.457031f, 0.605469f, 0.613281f},
+ {0.164062f, 0.695312f, 0.312500f, 0.417969f}, {0.109375f, 0.132812f, 0.929688f, 0.320312f},
+ {0.734375f, 0.937500f, 0.800781f, 0.207031f}, {0.578125f, 0.476562f, 0.039062f, 0.367188f},
+ {0.500000f, 0.382812f, 0.761719f, 0.859375f}, {0.304688f, 0.750000f, 0.628906f, 0.273438f},
+ {0.207031f, 0.617188f, 0.121094f, 0.730469f}, {0.597656f, 0.269531f, 0.683594f, 0.140625f},
+ {0.324219f, 0.445312f, 0.371094f, 0.613281f}, {0.027344f, 0.386719f, 0.187500f, 0.761719f},
+ {0.507812f, 0.093750f, 0.597656f, 0.546875f}, {0.769531f, 0.250000f, 0.015625f, 0.386719f},
+ {0.265625f, 0.335938f, 0.914062f, 0.472656f}, {0.335938f, 0.113281f, 0.539062f, 0.972656f},
+ {0.496094f, 0.828125f, 0.078125f, 0.730469f}, {0.980469f, 0.507812f, 0.656250f, 0.410156f},
+ {0.410156f, 0.093750f, 0.871094f, 0.148438f}, {0.777344f, 0.910156f, 0.238281f, 0.464844f},
+ {0.929688f, 0.644531f, 0.746094f, 0.253906f}, {0.343750f, 0.488281f, 0.394531f, 0.992188f},
+ {0.566406f, 0.949219f, 0.011719f, 0.117188f}, {0.476562f, 0.597656f, 0.859375f, 0.476562f},
+ {0.210938f, 0.449219f, 0.476562f, 0.273438f}, {0.816406f, 0.902344f, 0.156250f, 0.542969f},
+ {0.093750f, 0.738281f, 0.253906f, 0.773438f}, {0.964844f, 0.640625f, 0.316406f, 0.500000f},
+ {0.738281f, 0.925781f, 0.007812f, 0.257812f}, {0.828125f, 0.066406f, 0.433594f, 0.000000f},
+ {0.457031f, 0.437500f, 0.578125f, 0.187500f}, {0.667969f, 0.980469f, 0.089844f, 0.699219f},
+ {0.207031f, 0.351562f, 0.824219f, 0.886719f}, {0.105469f, 0.902344f, 0.703125f, 0.246094f},
+ {0.933594f, 0.183594f, 0.796875f, 0.070312f}, {0.796875f, 0.449219f, 0.457031f, 0.925781f},
+ {0.656250f, 0.945312f, 0.378906f, 0.289062f}, {0.957031f, 0.878906f, 0.769531f, 0.875000f},
+ {0.847656f, 0.335938f, 0.531250f, 0.097656f}, {0.089844f, 0.128906f, 0.628906f, 0.464844f},
+ {0.199219f, 0.824219f, 0.437500f, 0.273438f}, {0.335938f, 0.035156f, 0.507812f, 0.925781f},
+ {0.113281f, 0.773438f, 0.839844f, 0.554688f}, {0.160156f, 0.925781f, 0.042969f, 0.437500f},
+ {0.695312f, 0.132812f, 0.875000f, 0.687500f}, {0.300781f, 0.007812f, 0.519531f, 0.878906f},
+ {0.921875f, 0.898438f, 0.671875f, 0.800781f}, {0.187500f, 0.582031f, 0.000000f, 0.539062f},
+ {0.421875f, 0.253906f, 0.484375f, 0.265625f}, {0.503906f, 0.800781f, 0.945312f, 0.988281f},
+ {0.917969f, 0.117188f, 0.625000f, 0.753906f}, {0.812500f, 0.859375f, 0.707031f, 0.578125f},
+ {0.671875f, 0.269531f, 0.296875f, 0.171875f}, {0.984375f, 0.949219f, 0.769531f, 0.367188f},
+ {0.847656f, 0.476562f, 0.156250f, 0.957031f}, {0.703125f, 0.613281f, 0.554688f, 0.867188f},
+ {0.890625f, 0.328125f, 0.101562f, 0.421875f}, {0.503906f, 0.976562f, 0.687500f, 0.910156f},
+ {0.570312f, 0.511719f, 0.503906f, 0.777344f}, {0.156250f, 0.808594f, 0.597656f, 0.179688f},
+ {0.355469f, 0.125000f, 0.019531f, 0.839844f}, {0.199219f, 0.730469f, 0.308594f, 0.738281f},
+ {0.949219f, 0.984375f, 0.671875f, 0.496094f}, {0.429688f, 0.613281f, 0.246094f, 0.199219f},
+ {0.910156f, 0.085938f, 0.363281f, 0.765625f}, {0.769531f, 0.878906f, 0.707031f, 0.261719f},
+ {0.472656f, 0.519531f, 0.187500f, 0.000000f}, {0.894531f, 0.328125f, 0.519531f, 0.750000f},
+ {0.277344f, 0.593750f, 0.238281f, 0.632812f}, {0.058594f, 0.855469f, 0.359375f, 0.500000f},
+ {0.855469f, 0.023438f, 0.910156f, 0.027344f}, {0.699219f, 0.523438f, 0.449219f, 0.562500f},
+ {0.457031f, 0.667969f, 0.308594f, 0.980469f}, {0.125000f, 0.175781f, 0.824219f, 0.312500f},
+ {0.867188f, 0.867188f, 0.476562f, 0.414062f}, {0.375000f, 0.027344f, 0.929688f, 0.882812f},
+ {0.683594f, 0.812500f, 0.851562f, 0.175781f}, {0.117188f, 0.480469f, 0.125000f, 0.804688f},
+ {0.878906f, 0.980469f, 0.210938f, 0.679688f}, {0.058594f, 0.554688f, 0.378906f, 0.042969f},
+ {0.628906f, 0.167969f, 0.976562f, 0.527344f}, {0.132812f, 0.757812f, 0.769531f, 0.621094f},
+ {0.308594f, 0.371094f, 0.191406f, 0.312500f}, {0.464844f, 0.273438f, 0.527344f, 0.898438f},
+ {0.085938f, 0.808594f, 0.960938f, 0.007812f}, {0.734375f, 0.324219f, 0.691406f, 0.757812f},
+ {0.671875f, 0.105469f, 0.339844f, 0.593750f}, {0.058594f, 0.765625f, 0.585938f, 0.703125f},
+ {0.761719f, 0.246094f, 0.062500f, 0.031250f}, {0.156250f, 0.167969f, 0.417969f, 0.917969f},
+ {0.355469f, 0.035156f, 0.800781f, 0.382812f}, {0.644531f, 0.281250f, 0.925781f, 0.683594f},
+ {0.496094f, 0.773438f, 0.136719f, 0.957031f}, {0.121094f, 0.226562f, 0.890625f, 0.562500f},
+ {0.304688f, 0.699219f, 0.187500f, 0.824219f}, {0.992188f, 0.628906f, 0.980469f, 0.457031f},
+ {0.550781f, 0.300781f, 0.410156f, 0.308594f}, {0.621094f, 0.761719f, 0.242188f, 0.148438f},
+ {0.292969f, 0.671875f, 0.609375f, 0.816406f}, {0.414062f, 0.386719f, 0.000000f, 0.445312f},
+ {0.167969f, 0.289062f, 0.890625f, 0.207031f}, {0.238281f, 0.542969f, 0.140625f, 0.523438f},
+ {0.566406f, 0.710938f, 0.218750f, 0.625000f}, {0.382812f, 0.464844f, 0.980469f, 0.156250f},
+ {0.785156f, 0.972656f, 0.695312f, 0.730469f}, {0.535156f, 0.199219f, 0.246094f, 0.863281f},
+ {0.648438f, 0.390625f, 0.371094f, 0.210938f}, {0.425781f, 0.550781f, 0.722656f, 0.000000f},
+ {0.773438f, 0.671875f, 0.140625f, 0.980469f}, {0.585938f, 0.425781f, 0.234375f, 0.304688f},
+ {0.105469f, 0.734375f, 0.812500f, 0.164062f}, {0.656250f, 0.460938f, 0.281250f, 0.421875f},
+ {0.277344f, 0.632812f, 0.863281f, 0.351562f}, {0.031250f, 0.968750f, 0.347656f, 0.015625f},
+ {0.613281f, 0.195312f, 0.195312f, 0.214844f}, {0.445312f, 0.507812f, 0.527344f, 0.906250f},
+ {0.296875f, 0.777344f, 0.855469f, 0.093750f}, {0.132812f, 0.660156f, 0.062500f, 0.285156f},
+ {0.546875f, 0.031250f, 0.457031f, 0.496094f}, {0.195312f, 0.230469f, 0.808594f, 0.144531f},
+ {0.375000f, 0.750000f, 0.273438f, 0.210938f}, {0.933594f, 0.156250f, 0.941406f, 0.601562f},
+ {0.230469f, 0.402344f, 0.355469f, 0.367188f}, {0.753906f, 0.656250f, 0.128906f, 0.449219f},
+ {0.058594f, 0.351562f, 0.464844f, 0.015625f}, {0.597656f, 0.570312f, 0.398438f, 0.957031f},
+ {0.789062f, 0.289062f, 0.824219f, 0.386719f}, {0.246094f, 0.492188f, 0.578125f, 0.863281f},
+ {0.636719f, 0.792969f, 0.046875f, 0.457031f}, {0.332031f, 0.019531f, 0.839844f, 0.929688f},
+ {0.207031f, 0.410156f, 0.109375f, 0.707031f}, {0.617188f, 0.765625f, 0.621094f, 0.992188f},
+ {0.960938f, 0.066406f, 0.691406f, 0.132812f}, {0.417969f, 0.289062f, 0.074219f, 0.906250f},
+ {0.789062f, 0.207031f, 0.851562f, 0.769531f}, {0.093750f, 0.972656f, 0.171875f, 0.183594f},
+ {0.937500f, 0.101562f, 0.726562f, 0.066406f}, {0.253906f, 0.324219f, 0.554688f, 0.527344f},
+ {0.820312f, 0.503906f, 0.062500f, 0.656250f}, {0.476562f, 0.593750f, 0.648438f, 0.007812f},
+ {0.179688f, 0.910156f, 0.281250f, 0.289062f}, {0.957031f, 0.062500f, 0.445312f, 0.921875f},
+ {0.441406f, 0.632812f, 0.726562f, 0.128906f}, {0.574219f, 0.292969f, 0.621094f, 0.234375f},
+ {0.203125f, 0.875000f, 0.476562f, 0.363281f}, {0.679688f, 0.667969f, 0.031250f, 0.945312f},
+ {0.914062f, 0.441406f, 0.347656f, 0.097656f}, {0.546875f, 0.214844f, 0.609375f, 0.687500f},
+ {0.191406f, 0.718750f, 0.113281f, 0.550781f}, {0.269531f, 0.148438f, 0.164062f, 0.375000f},
+ {0.992188f, 0.414062f, 0.898438f, 0.164062f}, {0.398438f, 0.652344f, 0.652344f, 0.429688f},
+ {0.523438f, 0.351562f, 0.210938f, 0.800781f}, {0.863281f, 0.820312f, 0.992188f, 0.218750f},
+ {0.437500f, 0.988281f, 0.707031f, 0.066406f}, {0.261719f, 0.421875f, 0.382812f, 0.859375f},
+ {0.921875f, 0.339844f, 0.644531f, 0.132812f}, {0.585938f, 0.539062f, 0.746094f, 0.359375f},
+ {0.386719f, 0.855469f, 0.488281f, 0.738281f}, {0.804688f, 0.019531f, 0.289062f, 0.105469f},
+ {0.253906f, 0.480469f, 0.050781f, 0.539062f}, {0.027344f, 0.109375f, 0.867188f, 0.945312f},
+ {0.898438f, 0.828125f, 0.523438f, 0.582031f}, {0.718750f, 0.046875f, 0.964844f, 0.339844f},
+ {0.519531f, 0.152344f, 0.281250f, 0.675781f}, {0.062500f, 0.765625f, 0.570312f, 0.984375f},
+ {0.886719f, 0.003906f, 0.738281f, 0.792969f}, {0.687500f, 0.257812f, 0.316406f, 0.410156f},
+ {0.019531f, 0.585938f, 0.078125f, 0.039062f}, {0.964844f, 0.660156f, 0.164062f, 0.320312f},
+ {0.257812f, 0.863281f, 0.941406f, 0.597656f}, {0.906250f, 0.292969f, 0.640625f, 0.386719f},
+ {0.214844f, 0.960938f, 0.472656f, 0.746094f}, {0.464844f, 0.214844f, 0.996094f, 0.628906f},
+ {0.378906f, 0.851562f, 0.558594f, 0.097656f}, {0.820312f, 0.300781f, 0.394531f, 0.898438f},
+ {0.718750f, 0.066406f, 0.597656f, 0.566406f}, {0.968750f, 0.406250f, 0.085938f, 0.843750f},
+ {0.363281f, 0.687500f, 0.433594f, 0.683594f}, {0.750000f, 0.574219f, 0.125000f, 0.437500f},
+ {0.078125f, 0.316406f, 0.980469f, 0.617188f}, {0.636719f, 0.136719f, 0.675781f, 0.812500f},
+ {0.468750f, 0.910156f, 0.367188f, 0.757812f}, {0.324219f, 0.546875f, 0.910156f, 0.554688f},
+ {0.050781f, 0.832031f, 0.003906f, 0.671875f}, {0.808594f, 0.054688f, 0.203125f, 0.042969f},
+ {0.625000f, 0.929688f, 0.632812f, 0.937500f}, {0.460938f, 0.468750f, 0.796875f, 0.523438f},
+ {0.882812f, 0.003906f, 0.964844f, 0.292969f}, {0.304688f, 0.902344f, 0.195312f, 0.589844f},
+ {0.503906f, 0.160156f, 0.515625f, 0.128906f}, {0.011719f, 0.671875f, 0.933594f, 0.328125f},
+ {0.714844f, 0.250000f, 0.765625f, 0.570312f}, {0.539062f, 0.921875f, 0.472656f, 0.167969f},
+ {0.820312f, 0.187500f, 0.871094f, 0.355469f}, {0.031250f, 0.996094f, 0.953125f, 0.476562f},
+ {0.355469f, 0.628906f, 0.425781f, 0.289062f}, {0.554688f, 0.449219f, 0.578125f, 0.593750f},
+ {0.183594f, 0.710938f, 0.273438f, 0.398438f}, {0.644531f, 0.359375f, 0.511719f, 0.695312f},
+ {0.398438f, 0.820312f, 0.015625f, 0.464844f}, {0.535156f, 0.925781f, 0.941406f, 0.933594f},
+ {0.628906f, 0.691406f, 0.238281f, 0.222656f}, {0.074219f, 0.222656f, 0.402344f, 0.707031f},
+ {0.785156f, 0.757812f, 0.761719f, 0.496094f}, {0.242188f, 0.367188f, 0.570312f, 0.589844f},
+ {0.726562f, 0.718750f, 0.320312f, 0.445312f}, {0.925781f, 0.417969f, 0.890625f, 0.863281f},
+ {0.382812f, 0.000000f, 0.261719f, 0.753906f}, {0.753906f, 0.953125f, 0.839844f, 0.179688f},
+ {0.023438f, 0.078125f, 0.414062f, 0.832031f}, {0.843750f, 0.597656f, 0.906250f, 0.496094f},
+ {0.617188f, 0.894531f, 0.492188f, 0.792969f}, {0.886719f, 0.542969f, 0.261719f, 0.289062f},
+ {0.140625f, 0.968750f, 0.437500f, 0.960938f}, {0.296875f, 0.046875f, 0.757812f, 0.851562f},
+ {0.601562f, 0.710938f, 0.300781f, 0.324219f}, {0.699219f, 0.500000f, 0.496094f, 0.574219f},
+ {0.019531f, 0.558594f, 0.035156f, 0.648438f}, {0.785156f, 0.675781f, 0.535156f, 0.449219f},
+ {0.078125f, 0.089844f, 0.234375f, 0.300781f}, {0.191406f, 0.175781f, 0.339844f, 0.617188f},
+ {0.714844f, 0.398438f, 0.785156f, 0.222656f}, {0.054688f, 0.921875f, 0.562500f, 0.875000f},
+ {0.488281f, 0.257812f, 0.683594f, 0.652344f}, {0.765625f, 0.566406f, 0.335938f, 0.386719f},
+ {0.371094f, 0.957031f, 0.121094f, 0.750000f}, {0.117188f, 0.511719f, 0.718750f, 0.007812f},
+ {0.820312f, 0.871094f, 0.421875f, 0.125000f}, {0.453125f, 0.617188f, 0.062500f, 0.371094f},
+ {0.613281f, 0.937500f, 0.914062f, 0.246094f}, {0.300781f, 0.371094f, 0.460938f, 0.703125f},
+ {0.480469f, 0.078125f, 0.863281f, 0.957031f}, {0.730469f, 0.746094f, 0.785156f, 0.488281f},
+ {0.363281f, 0.164062f, 0.566406f, 0.812500f}, {0.074219f, 0.093750f, 0.093750f, 0.140625f},
+ {0.859375f, 0.503906f, 0.320312f, 0.527344f}, {0.039062f, 0.050781f, 0.765625f, 0.464844f},
+ {0.953125f, 0.566406f, 0.058594f, 0.222656f}, {0.531250f, 0.156250f, 0.156250f, 0.773438f},
+ {0.230469f, 0.914062f, 0.738281f, 0.644531f}, {0.117188f, 0.750000f, 0.898438f, 0.152344f},
+ {0.574219f, 0.363281f, 0.656250f, 0.484375f}, {0.179688f, 0.011719f, 0.808594f, 0.312500f},
+ {0.894531f, 0.980469f, 0.328125f, 0.941406f}, {0.246094f, 0.730469f, 0.242188f, 0.066406f},
+ {0.949219f, 0.386719f, 0.609375f, 0.398438f}, {0.781250f, 0.445312f, 0.511719f, 0.257812f},
+ {0.675781f, 0.679688f, 0.730469f, 0.843750f}, {0.121094f, 0.273438f, 0.433594f, 0.324219f},
+ {0.273438f, 0.582031f, 0.855469f, 0.726562f}, {0.390625f, 0.863281f, 0.289062f, 0.816406f},
+ {0.699219f, 0.226562f, 0.707031f, 0.218750f}, {0.925781f, 0.757812f, 0.078125f, 0.687500f},
+ {0.128906f, 0.382812f, 0.640625f, 0.906250f}, {0.382812f, 0.101562f, 0.140625f, 0.789062f},
+ {0.988281f, 0.843750f, 0.273438f, 0.074219f}, {0.093750f, 0.562500f, 0.386719f, 0.660156f},
+ {0.441406f, 0.726562f, 0.230469f, 0.218750f}, {0.746094f, 0.238281f, 0.023438f, 0.875000f},
+ {0.683594f, 0.109375f, 0.750000f, 0.042969f}, {0.238281f, 0.898438f, 0.328125f, 0.812500f},
+ {0.902344f, 0.796875f, 0.988281f, 0.230469f}, {0.335938f, 0.574219f, 0.792969f, 0.335938f},
+ {0.015625f, 0.035156f, 0.613281f, 0.835938f}, {0.738281f, 0.414062f, 0.343750f, 0.101562f},
+ {0.976562f, 0.128906f, 0.867188f, 0.789062f}, {0.308594f, 0.285156f, 0.148438f, 0.371094f},
+ {0.554688f, 0.535156f, 0.980469f, 0.964844f}, {0.351562f, 0.191406f, 0.046875f, 0.074219f},
+ {0.003906f, 0.140625f, 0.812500f, 0.324219f}, {0.515625f, 0.804688f, 0.101562f, 0.644531f},
+ {0.292969f, 0.242188f, 0.152344f, 0.546875f}, {0.816406f, 0.527344f, 0.554688f, 0.277344f},
+ {0.246094f, 0.343750f, 0.664062f, 0.050781f}, {0.425781f, 0.839844f, 0.058594f, 0.425781f},
+ {0.347656f, 0.031250f, 0.714844f, 0.207031f}, {0.496094f, 0.460938f, 0.804688f, 0.652344f},
+ {0.800781f, 0.226562f, 0.078125f, 0.058594f}, {0.039062f, 0.859375f, 0.546875f, 0.484375f},
+ {0.945312f, 0.300781f, 0.847656f, 0.109375f}, {0.226562f, 0.121094f, 0.121094f, 0.933594f},
+ {0.906250f, 0.210938f, 0.878906f, 0.746094f}, {0.546875f, 0.875000f, 0.601562f, 0.187500f},
+ {0.675781f, 0.953125f, 0.085938f, 0.804688f}, {0.339844f, 0.601562f, 0.933594f, 0.507812f},
+ {0.859375f, 0.792969f, 0.023438f, 0.996094f}, {0.429688f, 0.128906f, 0.156250f, 0.031250f},
+ {0.929688f, 0.742188f, 0.906250f, 0.269531f}, {0.179688f, 0.203125f, 0.453125f, 0.484375f},
+ {0.671875f, 0.640625f, 0.644531f, 0.195312f}, {0.582031f, 0.328125f, 0.191406f, 0.847656f},
+ {0.976562f, 0.425781f, 0.832031f, 0.601562f}, {0.343750f, 0.191406f, 0.347656f, 0.906250f},
+ {0.210938f, 0.488281f, 0.605469f, 0.062500f}, {0.941406f, 0.804688f, 0.023438f, 0.546875f},
+ {0.101562f, 0.910156f, 0.527344f, 0.191406f}, {0.175781f, 0.437500f, 0.402344f, 0.648438f},
+ {0.820312f, 0.332031f, 0.265625f, 0.914062f}, {0.515625f, 0.636719f, 0.882812f, 0.062500f},
+ {0.621094f, 0.785156f, 0.429688f, 0.253906f}, {0.746094f, 0.707031f, 0.199219f, 0.937500f},
+ {0.152344f, 0.355469f, 0.683594f, 0.332031f}, {0.332031f, 0.804688f, 0.457031f, 0.074219f},
+ {0.878906f, 0.492188f, 0.964844f, 0.968750f}, {0.480469f, 0.109375f, 0.226562f, 0.382812f},
+ {0.792969f, 0.867188f, 0.035156f, 0.042969f}, {0.417969f, 0.234375f, 0.480469f, 0.734375f},
+ {0.843750f, 0.464844f, 0.566406f, 0.539062f}, {0.511719f, 0.609375f, 0.171875f, 0.187500f},
+ {0.011719f, 0.062500f, 0.046875f, 0.703125f}, {0.582031f, 0.191406f, 0.871094f, 0.968750f},
+ {0.429688f, 0.347656f, 0.308594f, 0.121094f}, {0.988281f, 0.777344f, 0.578125f, 0.484375f},
+ {0.527344f, 0.109375f, 0.152344f, 0.078125f}, {0.085938f, 0.320312f, 0.050781f, 0.160156f},
+ {0.835938f, 0.699219f, 0.539062f, 0.640625f}, {0.558594f, 0.531250f, 0.890625f, 0.433594f},
+ {0.183594f, 0.968750f, 0.332031f, 0.031250f}, {0.660156f, 0.449219f, 0.433594f, 0.269531f},
+ {0.851562f, 0.640625f, 0.722656f, 0.503906f}, {0.289062f, 0.347656f, 0.558594f, 0.835938f},
+ {0.156250f, 0.488281f, 0.171875f, 0.101562f}, {0.878906f, 0.828125f, 0.804688f, 0.550781f},
+ {0.511719f, 0.386719f, 0.492188f, 0.437500f}, {0.132812f, 0.531250f, 0.148438f, 0.671875f},
+ {0.765625f, 0.144531f, 0.101562f, 0.117188f}, {0.484375f, 0.257812f, 0.210938f, 0.910156f},
+ {0.835938f, 0.480469f, 0.433594f, 0.574219f}, {0.152344f, 0.628906f, 0.699219f, 0.269531f},
+ {0.214844f, 0.773438f, 0.089844f, 0.441406f}, {0.417969f, 0.992188f, 0.535156f, 0.152344f},
+ {0.898438f, 0.453125f, 0.667969f, 0.746094f}, {0.640625f, 0.867188f, 0.195312f, 0.207031f},
+ {0.148438f, 0.578125f, 0.507812f, 0.796875f}, {0.855469f, 0.921875f, 0.699219f, 0.027344f},
+ {0.097656f, 0.468750f, 0.960938f, 0.988281f}, {0.585938f, 0.625000f, 0.757812f, 0.382812f},
+ {0.160156f, 0.773438f, 0.300781f, 0.613281f}, {0.714844f, 0.183594f, 0.214844f, 0.875000f},
+ {0.070312f, 0.691406f, 0.980469f, 0.937500f}, {0.656250f, 0.375000f, 0.332031f, 0.125000f},
+ {0.746094f, 0.789062f, 0.621094f, 0.738281f}, {0.457031f, 0.585938f, 0.949219f, 0.605469f},
+ {0.335938f, 0.933594f, 0.179688f, 0.253906f}, {0.171875f, 0.625000f, 0.359375f, 0.523438f},
+ {0.386719f, 0.457031f, 0.730469f, 0.394531f}, {0.472656f, 0.003906f, 0.273438f, 0.039062f},
+ {0.281250f, 0.726562f, 0.457031f, 0.902344f}, {0.972656f, 0.488281f, 0.832031f, 0.093750f},
+ {0.617188f, 0.312500f, 0.406250f, 0.414062f}, {0.136719f, 0.660156f, 0.613281f, 0.687500f},
+ {0.562500f, 0.441406f, 0.226562f, 0.781250f}, {0.324219f, 0.375000f, 0.800781f, 0.074219f},
+ {0.871094f, 0.808594f, 0.082031f, 0.964844f}, {0.269531f, 0.089844f, 0.941406f, 0.699219f},
+ {0.011719f, 0.250000f, 0.503906f, 0.503906f}, {0.148438f, 0.671875f, 0.242188f, 0.300781f},
+ {0.707031f, 0.125000f, 0.679688f, 0.453125f}, {0.843750f, 0.296875f, 0.812500f, 0.835938f},
+ {0.417969f, 0.566406f, 0.187500f, 0.113281f}, {0.578125f, 0.226562f, 0.652344f, 0.285156f},
+ {0.675781f, 0.523438f, 0.718750f, 0.363281f}, {0.312500f, 0.894531f, 0.039062f, 0.691406f},
+ {0.406250f, 0.398438f, 0.605469f, 0.781250f}, {0.265625f, 0.246094f, 0.917969f, 0.851562f},
+ {0.570312f, 0.992188f, 0.843750f, 0.589844f}, {0.644531f, 0.605469f, 0.339844f, 0.714844f},
+ {0.003906f, 0.269531f, 0.531250f, 0.511719f}, {0.699219f, 0.652344f, 0.296875f, 0.277344f},
+ {0.312500f, 0.546875f, 0.710938f, 0.824219f}, {0.054688f, 0.152344f, 0.402344f, 0.238281f},
+ {0.667969f, 0.796875f, 0.914062f, 0.875000f}, {0.351562f, 0.281250f, 0.769531f, 0.351562f},
+ {0.730469f, 0.839844f, 0.691406f, 0.000000f}, {0.289062f, 0.894531f, 0.394531f, 0.632812f},
+ {0.152344f, 0.519531f, 0.113281f, 0.429688f}, {0.867188f, 0.988281f, 0.992188f, 0.582031f},
+ {0.210938f, 0.636719f, 0.480469f, 0.878906f}, {0.640625f, 0.171875f, 0.753906f, 0.984375f},
+ {0.023438f, 0.425781f, 0.371094f, 0.343750f}, {0.437500f, 0.039062f, 0.222656f, 0.539062f},
+ {0.257812f, 0.800781f, 0.835938f, 0.718750f}, {0.777344f, 0.300781f, 0.007812f, 0.964844f},
+ {0.484375f, 0.054688f, 0.984375f, 0.406250f}, {0.582031f, 0.140625f, 0.664062f, 0.617188f},
+ {0.398438f, 0.597656f, 0.906250f, 0.933594f}, {0.933594f, 0.019531f, 0.367188f, 0.726562f},
+ {0.312500f, 0.691406f, 0.601562f, 0.164062f}, {0.074219f, 0.320312f, 0.882812f, 0.964844f},
+ {0.589844f, 0.644531f, 0.679688f, 0.515625f}, {0.949219f, 0.964844f, 0.375000f, 0.742188f},
+ {0.281250f, 0.187500f, 0.910156f, 0.023438f}, {0.687500f, 0.886719f, 0.773438f, 0.640625f},
+ {0.597656f, 0.343750f, 0.292969f, 0.871094f}, {0.054688f, 0.089844f, 0.464844f, 0.535156f},
+ {0.808594f, 0.015625f, 0.839844f, 0.613281f}, {0.710938f, 0.675781f, 0.339844f, 0.902344f},
+ {0.484375f, 0.320312f, 0.429688f, 0.406250f}, {0.988281f, 0.062500f, 0.242188f, 0.687500f},
+ {0.664062f, 0.707031f, 0.375000f, 0.140625f}, {0.460938f, 0.128906f, 0.019531f, 0.480469f},
+ {0.960938f, 0.296875f, 0.453125f, 0.707031f}, {0.535156f, 0.980469f, 0.828125f, 0.246094f},
+ {0.894531f, 0.101562f, 0.578125f, 0.570312f}, {0.218750f, 0.273438f, 0.398438f, 0.335938f},
+ {0.113281f, 0.507812f, 0.000000f, 0.406250f}, {0.554688f, 0.160156f, 0.242188f, 0.890625f},
+ {0.828125f, 0.066406f, 0.671875f, 0.695312f}, {0.632812f, 0.398438f, 0.425781f, 0.148438f},
+ {0.730469f, 0.781250f, 0.785156f, 0.968750f}, {0.125000f, 0.273438f, 0.964844f, 0.281250f},
+ {0.820312f, 0.371094f, 0.191406f, 0.707031f}, {0.031250f, 0.218750f, 0.695312f, 0.585938f},
+ {0.507812f, 0.054688f, 0.511719f, 0.343750f}, {0.242188f, 0.890625f, 0.988281f, 0.167969f},
+ {0.734375f, 0.972656f, 0.730469f, 0.531250f}, {0.070312f, 0.011719f, 0.285156f, 0.316406f},
+ {0.460938f, 0.707031f, 0.394531f, 0.417969f}, {0.781250f, 0.546875f, 0.585938f, 0.234375f},
+ {0.402344f, 0.992188f, 0.769531f, 0.152344f}, {0.644531f, 0.738281f, 0.148438f, 0.773438f},
+ {0.757812f, 0.855469f, 0.976562f, 0.636719f}, {0.539062f, 0.050781f, 0.382812f, 0.390625f},
+ {0.246094f, 0.714844f, 0.296875f, 0.742188f}, {0.910156f, 0.972656f, 0.125000f, 0.886719f},
+ {0.128906f, 0.011719f, 0.960938f, 0.445312f}, {0.984375f, 0.828125f, 0.351562f, 0.554688f},
+ {0.054688f, 0.132812f, 0.511719f, 0.175781f}, {0.800781f, 0.464844f, 0.117188f, 0.398438f},
+ {0.921875f, 0.027344f, 0.257812f, 0.019531f}, {0.437500f, 0.191406f, 0.015625f, 0.441406f},
+ {0.203125f, 0.433594f, 0.785156f, 0.195312f}, {0.996094f, 0.953125f, 0.632812f, 0.917969f},
+ {0.257812f, 0.335938f, 0.144531f, 0.652344f}, {0.617188f, 0.703125f, 0.835938f, 0.101562f},
+ {0.941406f, 0.929688f, 0.265625f, 0.597656f}, {0.109375f, 0.503906f, 0.097656f, 0.468750f},
+ {0.195312f, 0.093750f, 0.957031f, 0.785156f}, {0.917969f, 0.714844f, 0.218750f, 0.906250f},
+ {0.761719f, 0.242188f, 0.648438f, 0.281250f}, {0.367188f, 0.019531f, 0.789062f, 0.195312f},
+ {0.707031f, 0.480469f, 0.253906f, 0.386719f}, {0.328125f, 0.828125f, 0.917969f, 0.757812f},
+ {0.960938f, 0.941406f, 0.667969f, 0.242188f}, {0.742188f, 0.601562f, 0.601562f, 0.105469f},
+ {0.347656f, 0.203125f, 0.496094f, 0.871094f}, {0.886719f, 0.687500f, 0.777344f, 0.152344f},
+ {0.046875f, 0.886719f, 0.089844f, 0.316406f}, {0.222656f, 0.957031f, 0.316406f, 0.773438f},
+ {0.625000f, 0.750000f, 0.527344f, 0.253906f}, {0.003906f, 0.277344f, 0.050781f, 0.382812f},
+ {0.660156f, 0.937500f, 0.250000f, 0.328125f}, {0.808594f, 0.078125f, 0.734375f, 0.625000f},
+ {0.437500f, 0.425781f, 0.460938f, 0.281250f}, {0.386719f, 0.738281f, 0.566406f, 0.394531f},
+ {0.039062f, 0.050781f, 0.035156f, 0.175781f}, {0.523438f, 0.546875f, 0.175781f, 0.996094f},
+ {0.925781f, 0.714844f, 0.957031f, 0.347656f}, {0.453125f, 0.843750f, 0.585938f, 0.039062f},
+ {0.109375f, 0.617188f, 0.003906f, 0.296875f}, {0.269531f, 0.406250f, 0.750000f, 0.109375f},
+ {0.390625f, 0.949219f, 0.933594f, 0.519531f}, {0.207031f, 0.222656f, 0.597656f, 0.238281f},
+ {0.332031f, 0.378906f, 0.640625f, 0.820312f}, {0.785156f, 0.898438f, 0.914062f, 0.906250f},
+ {0.054688f, 0.496094f, 0.523438f, 0.085938f}, {0.386719f, 0.417969f, 0.089844f, 0.777344f},
+ {0.304688f, 0.562500f, 0.148438f, 0.031250f}, {0.929688f, 0.925781f, 0.773438f, 0.519531f},
+ {0.414062f, 0.667969f, 0.468750f, 0.195312f}, {0.257812f, 0.738281f, 0.835938f, 0.800781f},
+ {0.972656f, 0.332031f, 0.519531f, 0.003906f}, {0.078125f, 0.847656f, 0.062500f, 0.359375f},
+ {0.882812f, 0.691406f, 0.566406f, 0.625000f}, {0.585938f, 0.148438f, 0.140625f, 0.777344f},
+ {0.214844f, 0.941406f, 0.652344f, 0.476562f}, {0.757812f, 0.824219f, 0.308594f, 0.238281f},
+ {0.402344f, 0.527344f, 0.113281f, 0.867188f}, {0.945312f, 0.585938f, 0.359375f, 0.937500f},
+ {0.839844f, 0.277344f, 0.062500f, 0.621094f}, {0.632812f, 0.167969f, 0.550781f, 0.804688f},
+ {0.222656f, 0.464844f, 0.894531f, 0.914062f}, {0.535156f, 0.882812f, 0.011719f, 0.566406f},
+ {0.886719f, 0.039062f, 0.312500f, 0.085938f}, {0.496094f, 0.394531f, 0.449219f, 0.875000f},
+ {0.085938f, 0.593750f, 0.097656f, 0.972656f}, {0.289062f, 0.343750f, 0.742188f, 0.011719f},
+ {0.031250f, 0.460938f, 0.894531f, 0.589844f}, {0.777344f, 0.156250f, 0.488281f, 0.222656f},
+ {0.468750f, 0.679688f, 0.835938f, 0.042969f}, {0.195312f, 0.281250f, 0.230469f, 0.992188f},
+ {0.718750f, 0.589844f, 0.796875f, 0.109375f}, {0.492188f, 0.921875f, 0.667969f, 0.667969f},
+ {0.097656f, 0.667969f, 0.390625f, 0.292969f}, {0.835938f, 0.871094f, 0.582031f, 0.871094f},
+ {0.378906f, 0.097656f, 0.878906f, 0.128906f}, {0.753906f, 0.765625f, 0.078125f, 0.558594f},
+ {0.503906f, 0.039062f, 0.937500f, 0.761719f}, {0.148438f, 0.207031f, 0.515625f, 0.425781f},
+ {0.816406f, 0.421875f, 0.593750f, 0.996094f}, {0.390625f, 0.367188f, 0.335938f, 0.136719f},
+ {0.550781f, 0.656250f, 0.441406f, 0.226562f}, {0.488281f, 0.144531f, 0.828125f, 0.523438f},
+ {0.605469f, 0.593750f, 0.531250f, 0.734375f}, {0.035156f, 0.390625f, 0.347656f, 0.671875f},
+ {0.464844f, 0.742188f, 0.019531f, 0.023438f}, {0.812500f, 0.265625f, 0.421875f, 0.492188f},
+ {0.164062f, 0.359375f, 0.101562f, 0.605469f}, {0.507812f, 0.121094f, 0.171875f, 0.800781f},
+ {0.605469f, 0.503906f, 0.933594f, 0.453125f}, {0.082031f, 0.250000f, 0.261719f, 0.203125f},
+ {0.968750f, 0.550781f, 0.460938f, 0.570312f}, {0.718750f, 0.410156f, 0.628906f, 0.054688f},
+ {0.835938f, 0.105469f, 0.710938f, 0.468750f}, {0.359375f, 0.457031f, 0.421875f, 0.894531f},
+ {0.250000f, 0.875000f, 0.968750f, 0.015625f}, {0.996094f, 0.210938f, 0.074219f, 0.855469f},
+ {0.179688f, 0.785156f, 0.304688f, 0.074219f}, {0.714844f, 0.855469f, 0.832031f, 0.804688f},
+ {0.230469f, 0.296875f, 0.500000f, 0.488281f}, {0.859375f, 0.394531f, 0.253906f, 0.222656f},
+ {0.324219f, 0.230469f, 0.640625f, 0.679688f}, {0.765625f, 0.511719f, 0.390625f, 0.820312f},
+ {0.179688f, 0.269531f, 0.222656f, 0.726562f}, {0.843750f, 0.121094f, 0.128906f, 0.468750f},
+ {0.609375f, 0.781250f, 0.859375f, 0.960938f}, {0.035156f, 0.531250f, 0.066406f, 0.335938f},
+ {0.734375f, 0.855469f, 0.167969f, 0.578125f}, {0.261719f, 0.023438f, 0.324219f, 0.175781f},
+ {0.867188f, 0.652344f, 0.875000f, 0.304688f}, {0.632812f, 0.746094f, 0.683594f, 0.371094f},
+ {0.183594f, 0.214844f, 0.273438f, 0.851562f}, {0.773438f, 0.832031f, 0.921875f, 0.667969f},
+ {0.589844f, 0.011719f, 0.703125f, 0.992188f}, {0.691406f, 0.433594f, 0.113281f, 0.300781f},
+ {0.003906f, 0.246094f, 0.933594f, 0.457031f}, {0.511719f, 0.984375f, 0.320312f, 0.843750f},
+ {0.300781f, 0.496094f, 0.886719f, 0.203125f}, {0.433594f, 0.578125f, 0.390625f, 0.539062f},
+ {0.914062f, 0.648438f, 0.007812f, 0.121094f}, {0.085938f, 0.421875f, 0.867188f, 0.824219f},
+ {0.683594f, 0.117188f, 0.753906f, 0.015625f}, {0.304688f, 0.750000f, 0.210938f, 0.460938f},
+ {0.113281f, 0.355469f, 0.828125f, 0.113281f}, {0.367188f, 0.843750f, 0.472656f, 0.718750f},
+ {0.988281f, 0.621094f, 0.167969f, 0.035156f}, {0.050781f, 0.308594f, 0.710938f, 0.363281f},
+ {0.171875f, 0.144531f, 0.871094f, 0.667969f}, {0.929688f, 0.515625f, 0.648438f, 0.265625f},
+ {0.363281f, 0.781250f, 0.542969f, 0.183594f}, {0.859375f, 0.203125f, 0.226562f, 0.335938f},
+ {0.609375f, 0.878906f, 0.574219f, 0.496094f}, {0.386719f, 0.621094f, 0.003906f, 0.800781f},
+ {0.644531f, 0.378906f, 0.628906f, 0.625000f}, {0.871094f, 0.757812f, 0.437500f, 0.324219f},
+ {0.238281f, 0.082031f, 0.160156f, 0.750000f}, {0.355469f, 0.535156f, 0.984375f, 0.519531f},
+ {0.691406f, 0.308594f, 0.734375f, 0.960938f}, {0.167969f, 0.722656f, 0.480469f, 0.628906f},
+ {0.550781f, 0.390625f, 0.179688f, 0.792969f}, {0.070312f, 0.511719f, 0.441406f, 0.347656f},
+ {0.906250f, 0.843750f, 0.363281f, 0.023438f}, {0.589844f, 0.636719f, 0.203125f, 0.289062f},
+ {0.449219f, 0.070312f, 0.007812f, 0.695312f}, {0.238281f, 0.566406f, 0.746094f, 0.382812f},
+ {0.683594f, 0.953125f, 0.492188f, 0.832031f}, {0.855469f, 0.324219f, 0.062500f, 0.328125f},
+ {0.093750f, 0.812500f, 0.156250f, 0.093750f}, {0.253906f, 0.917969f, 0.609375f, 0.929688f},
+ {0.925781f, 0.550781f, 0.710938f, 0.812500f}, {0.574219f, 0.082031f, 0.843750f, 0.304688f},
+ {0.109375f, 0.894531f, 0.308594f, 0.066406f}, {0.234375f, 0.718750f, 0.550781f, 0.941406f},
+ {0.683594f, 0.851562f, 0.699219f, 0.371094f}, {0.410156f, 0.773438f, 0.402344f, 0.636719f},
+ {0.308594f, 0.335938f, 0.136719f, 0.843750f}, {0.519531f, 0.175781f, 0.820312f, 0.687500f},
+ {0.109375f, 0.820312f, 0.292969f, 0.527344f}, {0.457031f, 0.539062f, 0.183594f, 0.191406f},
+ {0.742188f, 0.617188f, 0.847656f, 0.750000f}, {0.539062f, 0.363281f, 0.617188f, 0.566406f},
+ {0.085938f, 0.500000f, 0.140625f, 0.449219f}, {0.890625f, 0.578125f, 0.937500f, 0.699219f},
+ {0.632812f, 0.113281f, 0.664062f, 0.917969f}, {0.128906f, 0.660156f, 0.105469f, 0.582031f},
+ {0.375000f, 0.933594f, 0.812500f, 0.410156f}, {0.652344f, 0.160156f, 0.882812f, 0.132812f},
+ {0.503906f, 0.820312f, 0.691406f, 0.253906f}, {0.941406f, 0.457031f, 0.300781f, 0.851562f},
+ {0.550781f, 0.734375f, 0.546875f, 0.656250f}, {0.902344f, 0.175781f, 0.488281f, 0.000000f},
+ {0.437500f, 0.593750f, 0.730469f, 0.753906f}, {0.125000f, 0.261719f, 0.785156f, 0.437500f},
+ {0.570312f, 0.816406f, 0.203125f, 0.632812f}, {0.500000f, 0.074219f, 0.417969f, 0.949219f},
+ {0.031250f, 0.351562f, 0.632812f, 0.472656f}, {0.839844f, 0.601562f, 0.343750f, 0.152344f},
+ {0.136719f, 0.128906f, 0.187500f, 0.753906f}, {0.476562f, 0.886719f, 0.597656f, 0.101562f},
+ {0.371094f, 0.550781f, 0.265625f, 0.578125f}, {0.792969f, 0.187500f, 0.722656f, 0.925781f},
+ {0.164062f, 0.089844f, 0.203125f, 0.070312f}, {0.660156f, 0.035156f, 0.617188f, 0.417969f},
+ {0.359375f, 0.324219f, 0.476562f, 0.671875f}, {0.539062f, 0.871094f, 0.542969f, 0.300781f},
+ {0.812500f, 0.195312f, 0.925781f, 0.750000f}, {0.171875f, 0.675781f, 0.433594f, 0.394531f},
+ {0.492188f, 0.066406f, 0.597656f, 0.210938f}, {0.710938f, 0.507812f, 0.675781f, 0.281250f},
+ {0.574219f, 0.765625f, 0.964844f, 0.851562f}, {0.808594f, 0.226562f, 0.250000f, 0.468750f},
+ {0.316406f, 0.925781f, 0.367188f, 0.757812f}, {0.675781f, 0.656250f, 0.816406f, 0.429688f},
+ {0.214844f, 0.265625f, 0.062500f, 0.539062f}, {0.457031f, 0.953125f, 0.937500f, 0.722656f},
+ {0.972656f, 0.101562f, 0.410156f, 0.132812f}, {0.070312f, 0.800781f, 0.320312f, 0.929688f},
+ {0.320312f, 0.500000f, 0.769531f, 0.261719f}, {0.527344f, 0.218750f, 0.085938f, 0.472656f},
+ {0.015625f, 0.851562f, 0.550781f, 0.820312f}, {0.960938f, 0.359375f, 0.285156f, 0.210938f},
+ {0.609375f, 0.144531f, 0.062500f, 0.371094f}, {0.292969f, 0.812500f, 0.925781f, 0.058594f},
+ {0.664062f, 0.226562f, 0.308594f, 0.242188f}, {0.863281f, 0.582031f, 0.671875f, 0.488281f},
+ {0.332031f, 0.292969f, 0.765625f, 0.945312f}, {0.023438f, 0.910156f, 0.988281f, 0.183594f},
+ {0.726562f, 0.734375f, 0.621094f, 0.531250f}, {0.968750f, 0.261719f, 0.898438f, 0.902344f},
+ {0.058594f, 0.851562f, 0.675781f, 0.046875f}, {0.320312f, 0.187500f, 0.292969f, 0.609375f},
+ {0.781250f, 0.449219f, 0.949219f, 0.167969f}, {0.410156f, 0.054688f, 0.882812f, 0.441406f},
+ {0.667969f, 0.210938f, 0.207031f, 0.542969f}, {0.296875f, 0.667969f, 0.468750f, 0.855469f},
+ {0.871094f, 0.417969f, 0.980469f, 0.148438f}, {0.761719f, 0.164062f, 0.765625f, 0.699219f},
+ {0.914062f, 0.460938f, 0.035156f, 0.511719f}, {0.148438f, 0.027344f, 0.871094f, 0.007812f},
+ {0.800781f, 0.929688f, 0.210938f, 0.988281f}, {0.199219f, 0.675781f, 0.945312f, 0.128906f},
+ {0.574219f, 0.230469f, 0.027344f, 0.796875f}, {0.875000f, 0.980469f, 0.781250f, 0.648438f},
+ {0.140625f, 0.144531f, 0.542969f, 0.968750f}, {0.609375f, 0.003906f, 0.359375f, 0.238281f},
+ {0.335938f, 0.683594f, 0.222656f, 0.148438f}, {0.476562f, 0.171875f, 0.761719f, 0.308594f},
+ {0.757812f, 0.902344f, 0.402344f, 0.105469f}, {0.562500f, 0.445312f, 0.324219f, 0.757812f},
+ {0.972656f, 0.039062f, 0.527344f, 0.050781f}, {0.019531f, 0.570312f, 0.054688f, 0.933594f},
+ {0.296875f, 0.964844f, 0.457031f, 0.562500f}, {0.695312f, 0.351562f, 0.984375f, 0.183594f},
+ {0.078125f, 0.636719f, 0.800781f, 0.382812f}, {0.347656f, 0.082031f, 0.402344f, 0.093750f},
+ {0.804688f, 0.988281f, 0.257812f, 0.921875f}, {0.191406f, 0.316406f, 0.101562f, 0.535156f},
+ {0.707031f, 0.453125f, 0.570312f, 0.722656f}, {0.937500f, 0.160156f, 0.996094f, 0.050781f},
+ {0.363281f, 0.960938f, 0.023438f, 0.230469f}, {0.671875f, 0.480469f, 0.496094f, 0.414062f},
+ {0.320312f, 0.296875f, 0.859375f, 0.554688f}, {0.949219f, 0.644531f, 0.386719f, 0.261719f},
+ {0.867188f, 0.757812f, 0.035156f, 0.648438f}, {0.226562f, 0.359375f, 0.460938f, 0.726562f},
+ {0.714844f, 0.804688f, 0.816406f, 0.328125f}, {0.996094f, 0.914062f, 0.980469f, 0.886719f},
+ {0.023438f, 0.257812f, 0.250000f, 0.976562f}, {0.265625f, 0.773438f, 0.789062f, 0.171875f},
+ {0.605469f, 0.472656f, 0.046875f, 0.636719f}, {0.449219f, 0.945312f, 0.273438f, 0.957031f},
+ {0.902344f, 0.250000f, 0.128906f, 0.582031f}, {0.000000f, 0.906250f, 0.332031f, 0.519531f},
+ {0.273438f, 0.101562f, 0.042969f, 0.175781f}, {0.421875f, 0.386719f, 0.515625f, 0.988281f},
+ {0.742188f, 0.820312f, 0.605469f, 0.605469f}, {0.589844f, 0.453125f, 0.132812f, 0.066406f},
+ {0.128906f, 0.066406f, 0.285156f, 0.910156f}, {0.800781f, 0.550781f, 0.714844f, 0.835938f},
+ {0.699219f, 0.421875f, 0.855469f, 0.398438f}, {0.175781f, 0.304688f, 0.175781f, 0.664062f},
+ {0.738281f, 0.039062f, 0.683594f, 0.074219f}, {0.832031f, 0.984375f, 0.898438f, 0.867188f},
+ {0.574219f, 0.437500f, 0.363281f, 0.144531f}, {0.421875f, 0.640625f, 0.859375f, 0.597656f},
+ {0.898438f, 0.937500f, 0.640625f, 0.906250f}, {0.125000f, 0.484375f, 0.214844f, 0.449219f},
+ {0.472656f, 0.000000f, 0.808594f, 0.675781f}, {0.218750f, 0.960938f, 0.109375f, 0.847656f},
+ {0.425781f, 0.167969f, 0.539062f, 0.585938f}, {0.800781f, 0.460938f, 0.257812f, 0.734375f},
+ {0.289062f, 0.125000f, 0.402344f, 0.070312f}, {0.179688f, 0.777344f, 0.125000f, 0.648438f},
+ {0.890625f, 0.011719f, 0.187500f, 0.480469f}, {0.628906f, 0.492188f, 0.558594f, 0.761719f},
+ {0.144531f, 0.691406f, 0.769531f, 0.957031f}, {0.957031f, 0.765625f, 0.378906f, 0.351562f},
+ {0.187500f, 0.292969f, 0.074219f, 0.222656f}, {0.496094f, 0.957031f, 0.589844f, 0.652344f},
+ {0.378906f, 0.597656f, 0.128906f, 0.410156f}, {0.007812f, 0.316406f, 0.269531f, 0.273438f},
+ {0.449219f, 0.644531f, 0.367188f, 0.777344f}, {0.542969f, 0.093750f, 0.648438f, 0.234375f},
+ {0.660156f, 0.582031f, 0.503906f, 0.335938f}, {0.941406f, 0.382812f, 0.585938f, 0.421875f},
+ {0.031250f, 0.042969f, 0.117188f, 0.285156f}, {0.414062f, 0.304688f, 0.679688f, 0.082031f},
+ {0.781250f, 0.722656f, 0.484375f, 0.351562f}, {0.277344f, 0.800781f, 0.875000f, 0.496094f},
+ {0.914062f, 0.265625f, 0.007812f, 0.816406f}, {0.406250f, 0.968750f, 0.445312f, 0.628906f},
+ {0.066406f, 0.339844f, 0.710938f, 0.375000f}, {0.261719f, 0.746094f, 0.968750f, 0.878906f},
+ {0.203125f, 0.800781f, 0.160156f, 0.511719f}, {0.812500f, 0.312500f, 0.613281f, 0.328125f},
+ {0.414062f, 0.691406f, 0.359375f, 0.445312f}, {0.148438f, 0.007812f, 0.179688f, 0.625000f},
+ {0.238281f, 0.226562f, 0.027344f, 0.785156f}, {0.476562f, 0.507812f, 0.664062f, 0.875000f},
+ {0.648438f, 0.390625f, 0.945312f, 0.210938f}, {0.972656f, 0.710938f, 0.367188f, 0.269531f},
+ {0.285156f, 0.558594f, 0.464844f, 0.128906f}, {0.082031f, 0.679688f, 0.816406f, 0.832031f},
+ {0.457031f, 0.769531f, 0.078125f, 0.601562f}, {0.242188f, 0.867188f, 0.738281f, 0.898438f},
+ {0.750000f, 0.394531f, 0.554688f, 0.019531f}, {0.101562f, 0.042969f, 0.968750f, 0.367188f},
+ {0.621094f, 0.957031f, 0.769531f, 0.820312f}, {0.046875f, 0.449219f, 0.660156f, 0.492188f},
+ {0.562500f, 0.613281f, 0.089844f, 0.234375f}, {0.480469f, 0.710938f, 0.335938f, 0.027344f},
+ {0.851562f, 0.402344f, 0.156250f, 0.566406f}, {0.144531f, 0.554688f, 0.691406f, 0.507812f},
+ {0.957031f, 0.023438f, 0.378906f, 0.355469f}, {0.750000f, 0.605469f, 0.640625f, 0.054688f},
+ {0.207031f, 0.722656f, 0.941406f, 0.878906f}, {0.644531f, 0.429688f, 0.847656f, 0.660156f},
+ {0.847656f, 0.558594f, 0.773438f, 0.328125f}, {0.089844f, 0.691406f, 0.425781f, 0.125000f},
+ {0.480469f, 0.000000f, 0.195312f, 0.816406f}, {0.960938f, 0.332031f, 0.992188f, 0.226562f},
+ {0.019531f, 0.750000f, 0.457031f, 0.304688f}, {0.546875f, 0.175781f, 0.503906f, 0.027344f},
+ {0.253906f, 0.703125f, 0.046875f, 0.566406f}, {0.433594f, 0.898438f, 0.601562f, 0.199219f},
+ {0.925781f, 0.582031f, 0.972656f, 0.359375f}, {0.136719f, 0.687500f, 0.250000f, 0.699219f},
+ {0.269531f, 0.183594f, 0.468750f, 0.417969f}, {0.792969f, 0.066406f, 0.031250f, 0.003906f},
+ {0.050781f, 0.566406f, 0.578125f, 0.718750f}, {0.710938f, 0.273438f, 0.414062f, 0.093750f},
+ {0.769531f, 0.695312f, 0.500000f, 0.300781f}, {0.976562f, 0.792969f, 0.867188f, 0.152344f},
+ {0.093750f, 0.613281f, 0.054688f, 0.410156f}, {0.652344f, 0.339844f, 0.722656f, 0.808594f},
+ {0.570312f, 0.527344f, 0.804688f, 0.214844f}, {0.480469f, 0.398438f, 0.324219f, 0.312500f},
+ {0.371094f, 0.996094f, 0.851562f, 0.867188f}, {0.531250f, 0.621094f, 0.429688f, 0.250000f},
+ {0.441406f, 0.117188f, 0.039062f, 0.574219f}, {0.718750f, 0.355469f, 0.250000f, 0.703125f},
+ {0.843750f, 0.867188f, 0.515625f, 0.050781f}, {0.078125f, 0.511719f, 0.816406f, 0.976562f},
+ {0.621094f, 0.000000f, 0.667969f, 0.589844f}, {0.992188f, 0.800781f, 0.441406f, 0.882812f},
+ {0.277344f, 0.988281f, 0.898438f, 0.093750f}, {0.058594f, 0.277344f, 0.070312f, 0.722656f},
+ {0.351562f, 0.867188f, 0.746094f, 0.914062f}, {0.246094f, 0.507812f, 0.343750f, 0.601562f},
+ {0.707031f, 0.433594f, 0.996094f, 0.875000f}, {0.972656f, 0.640625f, 0.394531f, 0.406250f},
+ {0.664062f, 0.894531f, 0.253906f, 0.710938f}, {0.195312f, 0.406250f, 0.640625f, 0.906250f},
+ {0.015625f, 0.480469f, 0.921875f, 0.035156f}, {0.800781f, 0.070312f, 0.582031f, 0.953125f},
+ {0.679688f, 0.628906f, 0.062500f, 0.199219f}, {0.855469f, 0.218750f, 0.273438f, 0.265625f},
+ {0.449219f, 0.492188f, 0.792969f, 0.664062f}, {0.714844f, 0.101562f, 0.906250f, 0.808594f},
+ {0.578125f, 0.894531f, 0.714844f, 0.980469f}, {0.957031f, 0.421875f, 0.246094f, 0.058594f},
+ {0.757812f, 0.851562f, 0.578125f, 0.304688f}, {0.886719f, 0.789062f, 0.839844f, 0.488281f},
+ {0.000000f, 0.925781f, 0.140625f, 0.679688f}, {0.523438f, 0.121094f, 0.617188f, 0.355469f},
+ {0.406250f, 0.886719f, 0.710938f, 0.984375f}, {0.769531f, 0.035156f, 0.285156f, 0.503906f},
+ {0.890625f, 0.242188f, 0.906250f, 0.292969f}, {0.574219f, 0.531250f, 0.242188f, 0.703125f},
+ {0.171875f, 0.179688f, 0.121094f, 0.769531f}, {0.527344f, 0.718750f, 0.308594f, 0.968750f},
+ {0.433594f, 0.226562f, 0.171875f, 0.171875f}, {0.281250f, 0.105469f, 0.523438f, 0.125000f},
+ {0.761719f, 0.285156f, 0.417969f, 0.402344f}, {0.328125f, 0.515625f, 0.574219f, 0.691406f},
+ {0.406250f, 0.164062f, 0.910156f, 0.792969f}, {0.652344f, 0.996094f, 0.101562f, 0.109375f},
+ {0.062500f, 0.121094f, 0.507812f, 0.832031f}, {0.320312f, 0.378906f, 0.742188f, 0.242188f},
+ {0.390625f, 0.316406f, 0.175781f, 0.703125f}, {0.527344f, 0.156250f, 0.558594f, 0.417969f},
+ {0.933594f, 0.972656f, 0.085938f, 0.000000f}, {0.160156f, 0.199219f, 0.722656f, 0.734375f},
+ {0.242188f, 0.589844f, 0.898438f, 0.378906f}, {0.386719f, 0.941406f, 0.664062f, 0.503906f},
+ {0.652344f, 0.851562f, 0.339844f, 0.695312f}, {0.910156f, 0.628906f, 0.765625f, 0.953125f},
+ {0.343750f, 0.367188f, 0.218750f, 0.460938f}, {0.503906f, 0.136719f, 0.386719f, 0.769531f},
+ {0.078125f, 0.816406f, 0.117188f, 0.976562f}, {0.632812f, 0.257812f, 0.523438f, 0.511719f},
+ {0.378906f, 0.335938f, 0.722656f, 0.281250f}, {0.203125f, 0.769531f, 0.789062f, 0.558594f},
+ {0.511719f, 0.882812f, 0.144531f, 0.953125f}, {0.347656f, 0.117188f, 0.695312f, 0.769531f},
+ {0.253906f, 0.371094f, 0.964844f, 0.523438f}, {0.542969f, 0.425781f, 0.355469f, 0.878906f},
+ {0.382812f, 0.082031f, 0.167969f, 0.109375f}, {0.910156f, 0.894531f, 0.582031f, 0.363281f},
+ {0.132812f, 0.707031f, 0.472656f, 0.980469f}, {0.765625f, 0.210938f, 0.023438f, 0.445312f},
+ {0.000000f, 0.304688f, 0.976562f, 0.148438f}, {0.820312f, 0.542969f, 0.695312f, 0.023438f},
+ {0.230469f, 0.925781f, 0.625000f, 0.398438f}, {0.042969f, 0.429688f, 0.902344f, 0.792969f},
+ {0.554688f, 0.152344f, 0.738281f, 0.117188f}, {0.339844f, 0.730469f, 0.320312f, 0.480469f},
+ {0.804688f, 0.234375f, 0.960938f, 0.187500f}, {0.714844f, 0.375000f, 0.183594f, 0.347656f},
+ {0.578125f, 0.492188f, 0.539062f, 0.457031f}, {0.859375f, 0.203125f, 0.230469f, 0.550781f},
+ {0.769531f, 0.730469f, 0.832031f, 0.175781f}, {0.484375f, 0.789062f, 0.453125f, 0.031250f},
+ {0.308594f, 0.953125f, 0.718750f, 0.746094f}, {0.066406f, 0.554688f, 0.890625f, 0.214844f},
+ {0.378906f, 0.105469f, 0.085938f, 0.121094f}, {0.503906f, 0.195312f, 0.316406f, 0.605469f},
+ {0.949219f, 0.867188f, 0.167969f, 0.429688f}, {0.546875f, 0.531250f, 0.824219f, 0.542969f},
+ {0.316406f, 0.832031f, 0.207031f, 0.718750f}, {0.117188f, 0.390625f, 0.554688f, 0.460938f},
+ {0.515625f, 0.152344f, 0.492188f, 0.011719f}, {0.906250f, 0.597656f, 0.117188f, 0.156250f},
+ {0.046875f, 0.261719f, 0.417969f, 0.234375f}, {0.625000f, 0.542969f, 0.773438f, 0.707031f},
+ {0.386719f, 0.667969f, 0.476562f, 0.121094f}, {0.308594f, 0.062500f, 0.320312f, 0.593750f},
+ {0.167969f, 0.285156f, 0.886719f, 0.417969f}, {0.601562f, 0.199219f, 0.042969f, 0.777344f},
+ {0.835938f, 0.425781f, 0.187500f, 0.082031f}, {0.214844f, 0.343750f, 0.539062f, 0.648438f},
+ {0.023438f, 0.632812f, 0.398438f, 0.390625f}, {0.640625f, 0.093750f, 0.671875f, 0.195312f},
+ {0.984375f, 0.820312f, 0.445312f, 0.074219f}, {0.382812f, 0.921875f, 0.617188f, 0.449219f},
+ {0.910156f, 0.492188f, 0.828125f, 0.531250f}, {0.832031f, 0.683594f, 0.941406f, 0.859375f},
+ {0.125000f, 0.859375f, 0.046875f, 0.941406f}, {0.929688f, 0.058594f, 0.750000f, 0.617188f},
+ {0.218750f, 0.816406f, 0.835938f, 0.273438f}, {0.730469f, 0.222656f, 0.296875f, 0.441406f},
+ {0.574219f, 0.652344f, 0.441406f, 0.921875f}, {0.832031f, 0.886719f, 0.878906f, 0.484375f},
+ {0.117188f, 0.835938f, 0.226562f, 0.085938f}, {0.773438f, 0.050781f, 0.476562f, 0.781250f},
+ {0.343750f, 0.789062f, 0.292969f, 0.929688f}, {0.695312f, 0.468750f, 0.382812f, 0.535156f},
+ {0.882812f, 0.281250f, 0.019531f, 0.898438f}, {0.785156f, 0.125000f, 0.804688f, 0.160156f},
+ {0.304688f, 0.507812f, 0.101562f, 0.640625f}, {0.093750f, 0.230469f, 0.546875f, 0.105469f},
+ {0.839844f, 0.968750f, 0.929688f, 0.253906f}, {0.593750f, 0.476562f, 0.652344f, 0.605469f},
+ {0.773438f, 0.011719f, 0.816406f, 0.046875f}, {0.976562f, 0.527344f, 0.304688f, 0.890625f},
+ {0.464844f, 0.941406f, 0.187500f, 0.183594f}, {0.660156f, 0.460938f, 0.921875f, 0.804688f},
+ {0.875000f, 0.718750f, 0.328125f, 0.335938f}, {0.933594f, 0.175781f, 0.246094f, 0.214844f},
+ {0.011719f, 0.636719f, 0.000000f, 0.640625f}, {0.628906f, 0.980469f, 0.632812f, 0.925781f},
+ {0.187500f, 0.246094f, 0.281250f, 0.261719f}, {0.835938f, 0.046875f, 0.921875f, 0.617188f},
+ {0.273438f, 0.832031f, 0.660156f, 0.542969f}, {0.691406f, 0.648438f, 0.226562f, 0.726562f},
+ {0.988281f, 0.882812f, 0.527344f, 0.675781f}, {0.597656f, 0.039062f, 0.351562f, 0.921875f},
+ {0.304688f, 0.253906f, 0.152344f, 0.515625f}, {0.902344f, 0.804688f, 0.484375f, 0.277344f},
+ {0.656250f, 0.632812f, 0.113281f, 0.898438f}, {0.257812f, 0.078125f, 0.410156f, 0.742188f},
+ {0.132812f, 0.566406f, 0.000000f, 0.828125f}, {0.210938f, 0.914062f, 0.781250f, 0.042969f},
+ {0.394531f, 0.675781f, 0.613281f, 0.949219f}, {0.171875f, 0.117188f, 0.929688f, 0.664062f},
+ {0.910156f, 0.351562f, 0.300781f, 0.808594f}, {0.605469f, 0.160156f, 0.160156f, 0.503906f},
+ {0.214844f, 0.695312f, 0.597656f, 0.980469f}, {0.550781f, 0.246094f, 0.207031f, 0.562500f},
+ {0.847656f, 0.335938f, 0.789062f, 0.851562f}, {0.152344f, 0.601562f, 0.519531f, 0.277344f},
+ {0.722656f, 0.738281f, 0.742188f, 0.171875f}, {0.226562f, 0.296875f, 0.375000f, 0.777344f},
+ {0.625000f, 0.031250f, 0.683594f, 0.078125f}, {0.984375f, 0.917969f, 0.867188f, 0.851562f},
+ {0.171875f, 0.710938f, 0.339844f, 0.585938f}, {0.351562f, 0.996094f, 0.011719f, 0.746094f},
+ {0.277344f, 0.765625f, 0.636719f, 0.406250f}, {0.101562f, 0.183594f, 0.964844f, 0.890625f},
+ {0.539062f, 0.332031f, 0.089844f, 0.542969f}, {0.847656f, 0.472656f, 0.218750f, 0.960938f},
+ {0.722656f, 0.621094f, 0.515625f, 0.015625f}, {0.109375f, 0.750000f, 0.750000f, 0.859375f},
+ {0.355469f, 0.835938f, 0.347656f, 0.167969f}, {0.679688f, 0.976562f, 0.949219f, 0.562500f},
+ {0.496094f, 0.468750f, 0.148438f, 0.812500f}, {0.292969f, 0.281250f, 0.789062f, 0.945312f},
+ {0.789062f, 0.585938f, 0.882812f, 0.335938f}, {0.062500f, 0.324219f, 0.007812f, 0.679688f},
+ {0.695312f, 0.410156f, 0.214844f, 0.597656f}, {0.191406f, 0.140625f, 0.371094f, 0.292969f},
+ {0.636719f, 0.933594f, 0.261719f, 0.054688f}, {0.078125f, 0.351562f, 0.675781f, 0.753906f},
+ {0.515625f, 0.585938f, 0.191406f, 0.195312f}, {0.886719f, 0.742188f, 0.625000f, 0.332031f},
+ {0.441406f, 0.457031f, 0.988281f, 0.726562f}, {0.253906f, 0.265625f, 0.015625f, 0.156250f},
+ {0.980469f, 0.511719f, 0.355469f, 0.570312f}, {0.031250f, 0.628906f, 0.824219f, 0.296875f},
+ {0.617188f, 0.347656f, 0.949219f, 0.203125f}, {0.566406f, 0.875000f, 0.636719f, 0.621094f},
+ {0.058594f, 0.664062f, 0.246094f, 0.257812f}, {0.515625f, 0.734375f, 0.574219f, 0.437500f},
+ {0.183594f, 0.406250f, 0.167969f, 0.796875f}, {0.414062f, 0.062500f, 0.273438f, 0.343750f},
+ {0.703125f, 0.292969f, 0.843750f, 0.855469f}, {0.222656f, 0.781250f, 0.011719f, 0.152344f},
+ {0.023438f, 0.648438f, 0.437500f, 0.312500f}, {0.292969f, 0.382812f, 0.582031f, 0.738281f},
+ {0.726562f, 0.851562f, 0.074219f, 0.628906f}, {0.066406f, 0.050781f, 0.406250f, 0.121094f},
+ {0.171875f, 0.300781f, 0.843750f, 0.464844f}, {0.585938f, 0.542969f, 0.539062f, 0.386719f},
+ {0.804688f, 0.839844f, 0.750000f, 0.039062f}, {0.453125f, 0.500000f, 0.882812f, 0.707031f},
+ {0.722656f, 0.757812f, 0.445312f, 0.484375f}, {0.066406f, 0.578125f, 0.382812f, 0.007812f},
+ {0.429688f, 0.449219f, 0.835938f, 0.789062f}, {0.347656f, 0.109375f, 0.085938f, 0.089844f},
+ {0.203125f, 0.378906f, 0.781250f, 0.343750f}, {0.085938f, 0.742188f, 0.269531f, 0.835938f},
+ {0.742188f, 0.585938f, 0.929688f, 0.179688f}, {0.394531f, 0.191406f, 0.839844f, 0.632812f},
+ {0.964844f, 0.960938f, 0.210938f, 0.328125f}, {0.515625f, 0.464844f, 0.570312f, 0.539062f},
+ {0.460938f, 0.828125f, 0.710938f, 0.226562f}, {0.941406f, 0.042969f, 0.351562f, 0.613281f},
+ {0.671875f, 0.425781f, 0.085938f, 0.386719f}, {0.085938f, 0.882812f, 0.484375f, 0.128906f},
+ {0.437500f, 0.617188f, 0.660156f, 0.253906f}, {0.125000f, 0.058594f, 0.015625f, 0.324219f},
+ {0.929688f, 0.468750f, 0.550781f, 0.632812f}, {0.792969f, 0.824219f, 0.425781f, 0.468750f},
+ {0.636719f, 0.023438f, 0.949219f, 0.007812f}, {0.335938f, 0.937500f, 0.046875f, 0.667969f},
+ {0.882812f, 0.437500f, 0.468750f, 0.339844f}, {0.437500f, 0.125000f, 0.976562f, 0.976562f},
+ {0.085938f, 0.671875f, 0.082031f, 0.394531f}, {0.398438f, 0.562500f, 0.433594f, 0.308594f},
+ {0.773438f, 0.351562f, 0.937500f, 0.925781f}, {0.664062f, 0.453125f, 0.742188f, 0.523438f},
+ {0.871094f, 0.046875f, 0.289062f, 0.351562f}, {0.792969f, 0.871094f, 0.847656f, 0.832031f},
+ {0.195312f, 0.132812f, 0.378906f, 0.261719f}, {0.425781f, 0.964844f, 0.687500f, 0.187500f},
+ {0.996094f, 0.570312f, 0.933594f, 0.734375f}, {0.253906f, 0.011719f, 0.429688f, 0.316406f},
+ {0.906250f, 0.519531f, 0.820312f, 0.457031f}, {0.140625f, 0.132812f, 0.644531f, 0.250000f},
+ {0.820312f, 0.667969f, 0.074219f, 0.035156f}, {0.089844f, 0.902344f, 0.500000f, 0.488281f},
+ {0.449219f, 0.781250f, 0.324219f, 0.871094f}, {0.339844f, 0.000000f, 0.562500f, 0.230469f},
+ {0.246094f, 0.546875f, 0.695312f, 0.101562f}, {0.578125f, 0.644531f, 0.898438f, 0.804688f},
+ {0.460938f, 0.757812f, 0.496094f, 0.367188f}, {0.796875f, 0.437500f, 0.117188f, 0.476562f},
+ {0.359375f, 0.304688f, 0.347656f, 0.984375f}, {0.015625f, 0.906250f, 0.542969f, 0.015625f},
+ {0.175781f, 0.007812f, 0.074219f, 0.605469f}, {0.660156f, 0.703125f, 0.718750f, 0.882812f},
+ {0.496094f, 0.183594f, 0.582031f, 0.382812f}, {0.410156f, 0.761719f, 0.687500f, 0.968750f},
+ {0.199219f, 0.093750f, 0.117188f, 0.460938f}, {0.285156f, 0.222656f, 0.519531f, 0.070312f},
+ {0.445312f, 0.539062f, 0.855469f, 0.859375f}, {0.746094f, 0.023438f, 0.445312f, 0.039062f},
+ {0.996094f, 0.828125f, 0.957031f, 0.558594f}, {0.625000f, 0.914062f, 0.714844f, 0.707031f},
+ {0.890625f, 0.574219f, 0.484375f, 0.917969f}, {0.144531f, 0.089844f, 0.355469f, 0.527344f},
+ {0.367188f, 0.710938f, 0.894531f, 0.390625f}, {0.906250f, 0.160156f, 0.746094f, 0.441406f},
+ {0.531250f, 0.218750f, 0.671875f, 0.062500f}, {0.828125f, 0.605469f, 0.957031f, 0.851562f},
+ {0.324219f, 0.414062f, 0.617188f, 0.992188f}, {0.406250f, 0.917969f, 0.113281f, 0.601562f},
+ {0.125000f, 0.023438f, 0.480469f, 0.160156f}, {0.296875f, 0.328125f, 0.199219f, 0.828125f},
+ {0.953125f, 0.191406f, 0.070312f, 0.429688f}, {0.527344f, 0.941406f, 0.730469f, 0.199219f},
+ {0.609375f, 0.289062f, 0.140625f, 0.894531f}, {0.929688f, 0.160156f, 0.949219f, 0.285156f},
+ {0.503906f, 0.812500f, 0.601562f, 0.582031f}, {0.863281f, 0.484375f, 0.421875f, 0.464844f},
+ {0.457031f, 0.082031f, 0.058594f, 0.078125f}, {0.164062f, 0.398438f, 0.644531f, 0.968750f},
+ {0.097656f, 0.281250f, 0.300781f, 0.425781f}, {0.781250f, 0.695312f, 0.945312f, 0.003906f},
+ {0.015625f, 0.328125f, 0.871094f, 0.695312f}, {0.851562f, 0.179688f, 0.257812f, 0.292969f},
+ {0.531250f, 0.777344f, 0.144531f, 0.765625f}, {0.328125f, 0.527344f, 0.859375f, 0.863281f},
+ {0.824219f, 0.296875f, 0.375000f, 0.437500f}, {0.726562f, 0.917969f, 0.808594f, 0.062500f},
+ {0.273438f, 0.394531f, 0.109375f, 0.164062f}, {0.417969f, 0.515625f, 0.332031f, 0.378906f},
+ {0.097656f, 0.761719f, 0.695312f, 0.792969f}, {0.472656f, 0.652344f, 0.609375f, 0.898438f},
+ {0.039062f, 0.171875f, 0.277344f, 0.511719f}, {0.261719f, 0.976562f, 0.136719f, 0.695312f},
+ {0.828125f, 0.238281f, 0.648438f, 0.140625f}, {0.585938f, 0.792969f, 0.234375f, 0.632812f},
+ {0.007812f, 0.082031f, 0.593750f, 0.218750f}, {0.492188f, 0.281250f, 0.152344f, 0.097656f},
+ {0.234375f, 0.636719f, 0.199219f, 0.652344f}, {0.457031f, 0.402344f, 0.542969f, 0.035156f},
+ {0.691406f, 0.714844f, 0.050781f, 0.476562f}, {0.054688f, 0.808594f, 0.625000f, 0.382812f},
+ {0.628906f, 0.371094f, 0.125000f, 0.617188f}, {0.480469f, 0.253906f, 0.261719f, 0.933594f},
+ {0.558594f, 0.699219f, 0.015625f, 0.667969f}, {0.414062f, 0.394531f, 0.585938f, 0.902344f},
+ {0.964844f, 0.214844f, 0.230469f, 0.746094f}, {0.726562f, 0.070312f, 0.968750f, 0.136719f},
+ {0.609375f, 0.714844f, 0.742188f, 0.628906f}, {0.871094f, 0.171875f, 0.109375f, 0.425781f},
+ {0.035156f, 0.988281f, 0.421875f, 0.917969f}, {0.742188f, 0.253906f, 0.781250f, 0.710938f},
+ {0.972656f, 0.039062f, 0.605469f, 0.554688f}, {0.285156f, 0.191406f, 0.968750f, 0.140625f},
+ {0.554688f, 0.531250f, 0.851562f, 0.656250f}, {0.949219f, 0.101562f, 0.406250f, 0.828125f},
+ {0.710938f, 0.394531f, 0.242188f, 0.507812f}, {0.312500f, 0.953125f, 0.796875f, 0.265625f},
+ {0.816406f, 0.566406f, 0.156250f, 0.683594f}, {0.902344f, 0.433594f, 0.425781f, 0.121094f},
+ {0.726562f, 0.921875f, 0.210938f, 0.820312f}, {0.953125f, 0.386719f, 0.054688f, 0.726562f},
+ {0.132812f, 0.988281f, 0.761719f, 0.320312f}, {0.847656f, 0.167969f, 0.320312f, 0.996094f},
+ {0.007812f, 0.445312f, 0.398438f, 0.406250f}, {0.261719f, 0.621094f, 0.632812f, 0.210938f},
+ {0.472656f, 0.343750f, 0.082031f, 0.011719f}, {0.804688f, 0.882812f, 0.207031f, 0.656250f},
+ {0.574219f, 0.429688f, 0.140625f, 0.816406f}, {0.429688f, 0.988281f, 0.265625f, 0.937500f},
+ {0.246094f, 0.757812f, 0.488281f, 0.242188f}, {0.109375f, 0.109375f, 0.042969f, 0.675781f},
+ {0.691406f, 0.675781f, 0.367188f, 0.507812f}, {0.992188f, 0.234375f, 0.292969f, 0.269531f},
+ {0.500000f, 0.730469f, 0.808594f, 0.753906f}, {0.761719f, 0.128906f, 0.984375f, 0.312500f},
+ {0.234375f, 0.667969f, 0.648438f, 0.964844f}, {0.851562f, 0.398438f, 0.550781f, 0.664062f},
+ {0.039062f, 0.523438f, 0.312500f, 0.136719f}, {0.152344f, 0.699219f, 0.492188f, 0.406250f},
+ {0.644531f, 0.976562f, 0.187500f, 0.945312f}, {0.253906f, 0.320312f, 0.710938f, 0.210938f},
+ {0.687500f, 0.667969f, 0.546875f, 0.761719f}, {0.570312f, 0.898438f, 0.757812f, 0.667969f},
+ {0.882812f, 0.769531f, 0.097656f, 0.144531f}, {0.359375f, 0.519531f, 0.460938f, 0.878906f},
+ {0.597656f, 0.105469f, 0.675781f, 0.472656f}, {0.285156f, 0.976562f, 0.523438f, 0.996094f},
+ {0.750000f, 0.250000f, 0.421875f, 0.082031f}, {0.050781f, 0.578125f, 0.980469f, 0.523438f},
+ {0.625000f, 0.738281f, 0.742188f, 0.683594f}, {0.500000f, 0.214844f, 0.269531f, 0.937500f},
+ {0.000000f, 0.992188f, 0.917969f, 0.296875f}, {0.187500f, 0.144531f, 0.832031f, 0.726562f},
+ {0.988281f, 0.277344f, 0.156250f, 0.226562f}, {0.769531f, 0.363281f, 0.398438f, 0.097656f},
+ {0.562500f, 0.570312f, 0.898438f, 0.437500f}, {0.687500f, 0.851562f, 0.531250f, 0.246094f},
+ {0.941406f, 0.410156f, 0.839844f, 0.027344f}, {0.730469f, 0.511719f, 0.308594f, 0.867188f},
+ {0.300781f, 0.199219f, 0.796875f, 0.492188f}, {0.914062f, 0.828125f, 0.496094f, 0.781250f},
+ {0.132812f, 0.949219f, 0.703125f, 0.171875f}, {0.953125f, 0.527344f, 0.445312f, 0.941406f},
+ {0.582031f, 0.230469f, 0.878906f, 0.691406f}, {0.339844f, 0.085938f, 0.781250f, 0.816406f},
+ {0.804688f, 0.890625f, 0.570312f, 0.062500f}, {0.082031f, 0.164062f, 0.312500f, 0.523438f},
+ {0.765625f, 0.785156f, 0.859375f, 0.101562f}, {0.312500f, 0.925781f, 0.453125f, 0.359375f},
+ {0.230469f, 0.558594f, 0.691406f, 0.578125f}, {0.535156f, 0.335938f, 0.378906f, 0.277344f},
+ {0.167969f, 0.441406f, 0.273438f, 0.777344f}, {0.941406f, 0.875000f, 0.855469f, 0.000000f},
+ {0.507812f, 0.371094f, 0.160156f, 0.507812f}, {0.394531f, 0.800781f, 0.050781f, 0.191406f},
+ {0.148438f, 0.597656f, 0.304688f, 0.261719f}, {0.679688f, 0.960938f, 0.457031f, 0.894531f},
+ {0.226562f, 0.855469f, 0.027344f, 0.410156f}, {0.843750f, 0.675781f, 0.765625f, 0.093750f},
+ {0.601562f, 0.796875f, 0.937500f, 0.222656f}, {0.097656f, 0.148438f, 0.488281f, 0.785156f},
+ {0.148438f, 0.300781f, 0.320312f, 0.035156f}, {0.539062f, 0.039062f, 0.906250f, 0.632812f},
+ {0.070312f, 0.609375f, 0.609375f, 0.363281f}, {0.671875f, 0.816406f, 0.972656f, 0.500000f},
+ {0.371094f, 0.312500f, 0.699219f, 0.585938f}, {0.589844f, 0.699219f, 0.136719f, 0.148438f},
+ {0.328125f, 0.261719f, 0.031250f, 0.773438f}, {0.546875f, 0.746094f, 0.910156f, 0.277344f},
+ {0.105469f, 0.195312f, 0.589844f, 0.472656f}, {0.679688f, 0.519531f, 0.773438f, 0.109375f},
+ {0.937500f, 0.246094f, 0.996094f, 0.722656f}, {0.179688f, 0.324219f, 0.558594f, 0.195312f},
+ {0.753906f, 0.562500f, 0.878906f, 0.562500f}, {0.601562f, 0.488281f, 0.222656f, 0.355469f},
+ {0.867188f, 0.949219f, 0.773438f, 0.105469f}, {0.210938f, 0.808594f, 0.167969f, 0.867188f},
+ {0.648438f, 0.363281f, 0.574219f, 0.058594f}, {0.078125f, 0.468750f, 0.410156f, 0.574219f},
+ {0.375000f, 0.878906f, 0.035156f, 0.515625f}, {0.679688f, 0.796875f, 0.234375f, 0.351562f},
+ {0.316406f, 0.007812f, 0.765625f, 0.742188f}, {0.792969f, 0.609375f, 0.375000f, 0.625000f},
+ {0.402344f, 0.234375f, 0.890625f, 0.808594f}, {0.019531f, 0.871094f, 0.007812f, 0.054688f},
+ {0.824219f, 0.546875f, 0.332031f, 0.546875f}, {0.320312f, 0.015625f, 0.812500f, 0.363281f},
+ {0.222656f, 0.144531f, 0.390625f, 0.246094f}, {0.722656f, 0.363281f, 0.167969f, 0.597656f},
+ {0.417969f, 0.859375f, 0.031250f, 0.792969f}, {0.179688f, 0.648438f, 0.800781f, 0.167969f},
+ {0.917969f, 0.402344f, 0.632812f, 0.351562f}, {0.246094f, 0.007812f, 0.058594f, 0.207031f},
+ {0.964844f, 0.839844f, 0.191406f, 0.585938f}, {0.367188f, 0.097656f, 0.503906f, 0.820312f},
+ {0.878906f, 0.609375f, 0.039062f, 0.117188f}, {0.589844f, 0.871094f, 0.640625f, 0.914062f},
+ {0.675781f, 0.058594f, 0.230469f, 0.542969f}, {0.296875f, 0.796875f, 0.773438f, 0.613281f},
+ {0.898438f, 0.484375f, 0.019531f, 0.828125f}, {0.140625f, 0.007812f, 0.730469f, 0.937500f},
+ {0.355469f, 0.304688f, 0.363281f, 0.578125f}, {0.191406f, 0.753906f, 0.070312f, 0.722656f},
+ {0.535156f, 0.906250f, 0.902344f, 0.433594f}, {0.636719f, 0.578125f, 0.031250f, 0.992188f},
+ {0.367188f, 0.019531f, 0.992188f, 0.332031f}, {0.738281f, 0.683594f, 0.343750f, 0.554688f},
+ {0.027344f, 0.320312f, 0.250000f, 0.128906f}, {0.285156f, 0.441406f, 0.167969f, 0.296875f},
+ {0.933594f, 0.605469f, 0.488281f, 0.234375f}, {0.179688f, 0.500000f, 0.980469f, 0.785156f},
+ {0.660156f, 0.304688f, 0.734375f, 0.433594f}, {0.011719f, 0.035156f, 0.183594f, 0.207031f},
+ {0.855469f, 0.843750f, 0.906250f, 0.703125f}, {0.371094f, 0.617188f, 0.042969f, 0.988281f},
+ {0.105469f, 0.269531f, 0.480469f, 0.398438f}, {0.656250f, 0.519531f, 0.640625f, 0.328125f},
+ {0.773438f, 0.097656f, 0.941406f, 0.843750f}, {0.312500f, 0.472656f, 0.539062f, 0.964844f},
+ {0.894531f, 0.703125f, 0.238281f, 0.046875f}, {0.109375f, 0.132812f, 0.703125f, 0.769531f},
+ {0.429688f, 0.273438f, 0.175781f, 0.585938f}, {0.046875f, 0.492188f, 0.574219f, 0.347656f},
+ {0.382812f, 0.355469f, 0.285156f, 0.953125f}, {0.472656f, 0.636719f, 0.660156f, 0.437500f},
+ {0.769531f, 0.847656f, 0.093750f, 0.542969f}, {0.347656f, 0.246094f, 0.832031f, 0.910156f},
+ {0.250000f, 0.726562f, 0.371094f, 0.175781f}, {0.875000f, 0.136719f, 0.273438f, 0.238281f},
+ {0.492188f, 0.484375f, 0.500000f, 0.671875f}, {0.210938f, 0.562500f, 0.871094f, 0.089844f},
+ {0.820312f, 0.078125f, 0.234375f, 0.890625f}, {0.718750f, 0.957031f, 0.812500f, 0.621094f},
+ {0.398438f, 0.121094f, 0.515625f, 0.949219f}, {0.035156f, 0.804688f, 0.300781f, 0.367188f},
+ {0.308594f, 0.015625f, 0.386719f, 0.589844f}, {0.640625f, 0.636719f, 0.707031f, 0.296875f},
+ {0.054688f, 0.898438f, 0.101562f, 0.023438f}, {0.468750f, 0.042969f, 0.445312f, 0.789062f},
+ {0.359375f, 0.285156f, 0.652344f, 0.714844f}, {0.027344f, 0.167969f, 0.925781f, 0.421875f},
+ {0.554688f, 0.539062f, 0.710938f, 0.929688f}, {0.890625f, 0.621094f, 0.332031f, 0.226562f},
+ {0.164062f, 0.093750f, 0.906250f, 0.109375f}, {0.578125f, 0.265625f, 0.855469f, 0.882812f},
+ {0.460938f, 0.910156f, 0.671875f, 0.042969f}, {0.914062f, 0.367188f, 0.105469f, 0.250000f},
+ {0.734375f, 0.070312f, 0.621094f, 0.492188f}, {0.542969f, 0.183594f, 0.996094f, 0.308594f},
+ {0.980469f, 0.421875f, 0.238281f, 0.703125f}, {0.128906f, 0.621094f, 0.503906f, 0.933594f},
+ {0.632812f, 0.925781f, 0.906250f, 0.839844f}, {0.953125f, 0.218750f, 0.597656f, 0.109375f},
+ {0.039062f, 0.589844f, 0.960938f, 0.402344f}, {0.667969f, 0.714844f, 0.218750f, 0.550781f},
+ {0.472656f, 0.484375f, 0.312500f, 0.718750f}, {0.558594f, 0.152344f, 0.582031f, 0.894531f},
+ {0.152344f, 0.355469f, 0.691406f, 0.023438f}, {0.691406f, 0.671875f, 0.445312f, 0.410156f},
+ {0.753906f, 0.316406f, 0.867188f, 0.496094f}, {0.527344f, 0.546875f, 0.562500f, 0.656250f},
+ {0.125000f, 0.714844f, 0.304688f, 0.042969f}, {0.390625f, 0.218750f, 0.988281f, 0.320312f},
+ {0.218750f, 0.894531f, 0.585938f, 0.183594f}, {0.511719f, 0.691406f, 0.187500f, 0.761719f},
+ {0.457031f, 0.101562f, 0.457031f, 0.296875f}, {0.050781f, 0.628906f, 0.671875f, 0.371094f},
+ {0.816406f, 0.148438f, 0.554688f, 0.054688f}, {0.082031f, 0.371094f, 0.386719f, 0.269531f},
+ {0.417969f, 0.472656f, 0.753906f, 0.617188f}, {0.839844f, 0.175781f, 0.109375f, 0.750000f},
+ {0.218750f, 0.933594f, 0.656250f, 0.421875f}, {0.527344f, 0.742188f, 0.910156f, 0.910156f},
+ {0.875000f, 0.050781f, 0.402344f, 0.589844f}, {0.390625f, 0.988281f, 0.082031f, 0.972656f},
+ {0.460938f, 0.652344f, 0.355469f, 0.148438f}, {0.921875f, 0.464844f, 0.546875f, 0.847656f},
+ {0.601562f, 0.113281f, 0.132812f, 0.484375f}, {0.710938f, 0.964844f, 0.773438f, 0.089844f},
+ {0.273438f, 0.761719f, 0.593750f, 0.550781f}, {0.433594f, 0.664062f, 0.199219f, 0.156250f},
+ {0.203125f, 0.222656f, 0.355469f, 0.664062f}, {0.000000f, 0.835938f, 0.812500f, 0.609375f},
+ {0.625000f, 0.320312f, 0.738281f, 0.445312f}, {0.804688f, 0.410156f, 0.914062f, 0.304688f},
+ {0.523438f, 0.617188f, 0.644531f, 0.695312f}, {0.738281f, 0.070312f, 0.121094f, 0.179688f},
+ {0.886719f, 0.210938f, 0.890625f, 0.859375f}, {0.210938f, 0.984375f, 0.531250f, 0.730469f},
+ {0.988281f, 0.464844f, 0.000000f, 0.312500f}, {0.628906f, 0.527344f, 0.726562f, 0.078125f},
+ {0.433594f, 0.902344f, 0.472656f, 0.765625f}, {0.789062f, 0.058594f, 0.171875f, 0.957031f},
+ {0.042969f, 0.656250f, 0.570312f, 0.441406f}, {0.652344f, 0.796875f, 0.656250f, 0.832031f},
+ {0.914062f, 0.371094f, 0.339844f, 0.332031f}, {0.164062f, 0.875000f, 0.453125f, 0.515625f},
+ {0.968750f, 0.476562f, 0.167969f, 0.750000f}, {0.777344f, 0.683594f, 0.683594f, 0.160156f},
+ {0.492188f, 0.851562f, 0.019531f, 0.843750f}, {0.855469f, 0.144531f, 0.808594f, 0.972656f},
+ {0.960938f, 0.449219f, 0.332031f, 0.453125f}, {0.265625f, 0.781250f, 0.531250f, 0.898438f},
+ {0.781250f, 0.394531f, 0.851562f, 0.183594f}, {0.921875f, 0.855469f, 0.015625f, 0.628906f},
+ {0.285156f, 0.066406f, 0.132812f, 0.378906f}, {0.421875f, 0.992188f, 0.507812f, 0.796875f},
+ {0.816406f, 0.753906f, 0.269531f, 0.695312f}, {0.972656f, 0.570312f, 0.468750f, 0.449219f},
+ {0.113281f, 0.148438f, 0.160156f, 0.554688f}, {0.199219f, 0.726562f, 0.796875f, 0.992188f},
+ {0.285156f, 0.464844f, 0.289062f, 0.164062f}, {0.070312f, 0.785156f, 0.453125f, 0.875000f},
+ {0.375000f, 0.832031f, 0.843750f, 0.437500f}, {0.500000f, 0.269531f, 0.125000f, 0.023438f},
+ {0.445312f, 0.726562f, 0.687500f, 0.507812f}, {0.089844f, 0.457031f, 0.277344f, 0.289062f},
+ {0.839844f, 0.046875f, 0.359375f, 0.917969f}, {0.773438f, 0.300781f, 0.761719f, 0.050781f},
+ {0.347656f, 0.945312f, 0.882812f, 0.640625f}, {0.101562f, 0.902344f, 0.117188f, 0.460938f},
+ {0.816406f, 0.785156f, 0.937500f, 0.265625f}, {0.445312f, 0.453125f, 0.351562f, 0.765625f},
+ {0.226562f, 0.171875f, 0.726562f, 0.351562f}, {0.324219f, 0.921875f, 0.082031f, 0.839844f},
+ {0.808594f, 0.402344f, 0.421875f, 0.988281f}, {0.027344f, 0.113281f, 0.492188f, 0.398438f},
+ {0.855469f, 0.589844f, 0.109375f, 0.480469f}, {0.648438f, 0.339844f, 0.878906f, 0.066406f},
+ {0.976562f, 0.945312f, 0.257812f, 0.539062f}, {0.765625f, 0.433594f, 0.953125f, 0.160156f},
+ {0.250000f, 0.726562f, 0.140625f, 0.820312f}, {0.570312f, 0.261719f, 0.210938f, 0.894531f},
+ {0.964844f, 0.789062f, 0.613281f, 0.097656f}, {0.160156f, 0.117188f, 0.300781f, 0.210938f},
+ {0.488281f, 0.839844f, 0.820312f, 0.859375f}, {0.707031f, 0.542969f, 0.019531f, 0.496094f},
+ {0.605469f, 0.273438f, 0.714844f, 0.007812f}, {0.125000f, 0.820312f, 0.222656f, 0.718750f},
+ {0.750000f, 0.363281f, 0.652344f, 0.339844f}, {0.207031f, 0.195312f, 0.804688f, 0.636719f},
+ {0.050781f, 0.718750f, 0.300781f, 0.039062f}, {0.492188f, 0.406250f, 0.406250f, 0.906250f},
+ {0.910156f, 0.152344f, 0.992188f, 0.796875f}, {0.832031f, 0.015625f, 0.683594f, 0.214844f},
+ {0.570312f, 0.937500f, 0.085938f, 0.738281f}, {0.984375f, 0.570312f, 0.472656f, 0.371094f},
+ {0.468750f, 0.050781f, 0.394531f, 0.121094f}, {0.253906f, 0.886719f, 0.066406f, 0.820312f},
+ {0.328125f, 0.769531f, 0.332031f, 0.535156f}, {0.937500f, 0.921875f, 0.441406f, 0.011719f},
+ {0.640625f, 0.718750f, 0.199219f, 0.488281f}, {0.289062f, 0.031250f, 0.390625f, 0.136719f},
+ {0.007812f, 0.773438f, 0.992188f, 0.601562f}, {0.566406f, 0.398438f, 0.230469f, 0.406250f},
+ {0.171875f, 0.191406f, 0.785156f, 0.855469f}, {0.933594f, 0.343750f, 0.046875f, 0.285156f},
+ {0.121094f, 0.949219f, 0.921875f, 0.003906f}, {0.292969f, 0.218750f, 0.097656f, 0.558594f},
+ {0.441406f, 0.027344f, 0.734375f, 0.199219f}, {0.515625f, 0.597656f, 0.976562f, 0.050781f},
+ {0.250000f, 0.402344f, 0.066406f, 0.425781f}, {0.363281f, 0.300781f, 0.859375f, 0.250000f},
+ {0.203125f, 0.546875f, 0.433594f, 0.066406f}, {0.117188f, 0.363281f, 0.613281f, 0.644531f},
+ {0.542969f, 0.726562f, 0.191406f, 0.535156f}, {0.410156f, 0.199219f, 0.964844f, 0.125000f},
+ {0.140625f, 0.578125f, 0.261719f, 0.316406f}, {0.667969f, 0.660156f, 0.394531f, 0.496094f},
+ {0.488281f, 0.441406f, 0.625000f, 0.003906f}, {0.734375f, 0.304688f, 0.820312f, 0.601562f},
+ {0.007812f, 0.203125f, 0.082031f, 0.292969f}, {0.250000f, 0.417969f, 0.593750f, 0.191406f},
+ {0.511719f, 0.503906f, 0.953125f, 0.832031f}, {0.703125f, 0.960938f, 0.417969f, 0.656250f},
+ {0.605469f, 0.656250f, 0.566406f, 0.386719f}, {0.886719f, 0.312500f, 0.070312f, 0.097656f},
+ {0.753906f, 0.511719f, 0.640625f, 0.777344f}, {0.191406f, 0.109375f, 0.203125f, 0.621094f},
+ {0.917969f, 0.992188f, 0.738281f, 0.175781f}, {0.300781f, 0.390625f, 0.437500f, 0.664062f},
+ {0.515625f, 0.816406f, 0.078125f, 0.742188f}, {0.230469f, 0.085938f, 0.488281f, 0.226562f},
+ {0.589844f, 0.203125f, 0.546875f, 0.324219f}, {0.894531f, 0.558594f, 0.406250f, 0.832031f},
+ {0.292969f, 0.261719f, 0.250000f, 0.964844f}, {0.058594f, 0.027344f, 0.789062f, 0.179688f},
+ {0.968750f, 0.812500f, 0.515625f, 0.554688f}, {0.484375f, 0.496094f, 0.207031f, 0.242188f},
+ {0.914062f, 0.253906f, 0.921875f, 0.144531f}, {0.605469f, 0.968750f, 0.816406f, 0.714844f},
+ {0.734375f, 0.457031f, 0.699219f, 0.648438f}, {0.097656f, 0.183594f, 0.332031f, 0.882812f},
+ {0.410156f, 0.832031f, 0.605469f, 0.957031f}, {0.292969f, 0.542969f, 0.761719f, 0.679688f},
+ {0.691406f, 0.039062f, 0.421875f, 0.597656f}, {0.878906f, 0.984375f, 0.859375f, 0.468750f},
+ {0.324219f, 0.601562f, 0.507812f, 0.710938f}, {0.664062f, 0.343750f, 0.925781f, 0.363281f},
+ {0.785156f, 0.640625f, 0.453125f, 0.070312f}, {0.093750f, 0.214844f, 0.582031f, 0.652344f},
+ {0.347656f, 0.417969f, 0.519531f, 0.390625f}, {0.949219f, 0.140625f, 0.843750f, 0.277344f},
+ {0.261719f, 0.769531f, 0.937500f, 0.546875f}, {0.566406f, 0.535156f, 0.066406f, 0.757812f},
+ {0.328125f, 0.250000f, 0.503906f, 0.253906f}, {0.796875f, 0.589844f, 0.871094f, 0.445312f},
+ {0.144531f, 0.898438f, 0.003906f, 0.304688f}, {0.074219f, 0.308594f, 0.261719f, 0.953125f},
+ {0.355469f, 0.390625f, 0.839844f, 0.492188f}, {0.691406f, 0.742188f, 0.144531f, 0.062500f},
+ {0.863281f, 0.183594f, 0.589844f, 0.917969f}, {0.175781f, 0.527344f, 0.976562f, 0.230469f},
+ {0.582031f, 0.238281f, 0.511719f, 0.992188f}, {0.074219f, 0.441406f, 0.855469f, 0.644531f},
+ {0.140625f, 0.554688f, 0.750000f, 0.277344f}, {0.488281f, 0.328125f, 0.687500f, 0.941406f},
+ {0.824219f, 0.121094f, 0.582031f, 0.210938f}, {0.703125f, 0.687500f, 0.332031f, 0.699219f},
+ {0.324219f, 0.593750f, 0.625000f, 0.519531f}, {0.734375f, 0.859375f, 0.429688f, 0.644531f},
+ {0.390625f, 0.433594f, 0.839844f, 0.378906f}, {0.609375f, 0.515625f, 0.390625f, 0.738281f},
+ {0.761719f, 0.714844f, 0.539062f, 0.976562f}, {0.074219f, 0.269531f, 0.277344f, 0.679688f},
+ {0.882812f, 0.167969f, 0.636719f, 0.796875f}, {0.667969f, 0.769531f, 0.226562f, 0.886719f},
+ {0.593750f, 0.925781f, 0.941406f, 0.492188f}, {0.734375f, 0.078125f, 0.128906f, 0.386719f},
+ {0.332031f, 0.980469f, 0.722656f, 0.765625f}, {0.699219f, 0.269531f, 0.058594f, 0.265625f},
+ {0.835938f, 0.105469f, 0.476562f, 0.699219f}, {0.058594f, 0.917969f, 0.753906f, 0.984375f},
+ {0.191406f, 0.710938f, 0.214844f, 0.847656f}, {0.609375f, 0.023438f, 0.976562f, 0.144531f},
+ {0.332031f, 0.894531f, 0.683594f, 0.953125f}, {0.640625f, 0.339844f, 0.355469f, 0.761719f},
+ {0.867188f, 0.839844f, 0.023438f, 0.027344f}, {0.359375f, 0.117188f, 0.222656f, 0.328125f},
+ {0.441406f, 0.242188f, 0.718750f, 0.726562f}, {0.136719f, 0.933594f, 0.878906f, 0.585938f},
+ {0.656250f, 0.027344f, 0.382812f, 0.218750f}, {0.796875f, 0.566406f, 0.531250f, 0.976562f},
+ {0.582031f, 0.160156f, 0.023438f, 0.339844f}, {0.703125f, 0.664062f, 0.921875f, 0.425781f},
+ {0.390625f, 0.765625f, 0.851562f, 0.812500f}, {0.132812f, 0.515625f, 0.156250f, 0.945312f},
+ {0.996094f, 0.871094f, 0.718750f, 0.140625f}, {0.718750f, 0.417969f, 0.003906f, 0.593750f},
+ {0.406250f, 0.632812f, 0.621094f, 0.066406f}, {0.652344f, 0.738281f, 0.148438f, 0.679688f},
+ {0.167969f, 0.363281f, 0.285156f, 0.929688f}, {0.082031f, 0.078125f, 0.667969f, 0.000000f},
+ {0.429688f, 0.675781f, 0.027344f, 0.453125f}, {0.261719f, 0.617188f, 0.382812f, 0.796875f},
+ {0.339844f, 0.785156f, 0.234375f, 0.265625f}, {0.546875f, 0.050781f, 0.523438f, 0.105469f},
+ {0.164062f, 0.273438f, 0.007812f, 0.222656f}, {0.910156f, 0.667969f, 0.804688f, 0.390625f},
+ {0.492188f, 0.203125f, 0.082031f, 0.011719f}, {0.121094f, 0.863281f, 0.269531f, 0.242188f},
+ {0.011719f, 0.414062f, 0.695312f, 0.519531f}, {0.449219f, 0.496094f, 0.058594f, 0.972656f},
+ {0.238281f, 0.914062f, 0.191406f, 0.765625f}, {0.855469f, 0.078125f, 0.367188f, 0.179688f},
+ {0.046875f, 0.882812f, 0.281250f, 0.828125f}, {0.437500f, 0.687500f, 0.148438f, 0.113281f},
+ {0.816406f, 0.015625f, 0.613281f, 0.949219f}, {0.683594f, 0.937500f, 0.437500f, 0.187500f},
+ {0.988281f, 0.859375f, 0.238281f, 0.867188f}, {0.398438f, 0.085938f, 0.574219f, 0.597656f},
+ {0.636719f, 0.496094f, 0.722656f, 0.683594f}, {0.742188f, 0.808594f, 0.339844f, 0.019531f},
+ {0.234375f, 0.625000f, 0.531250f, 0.574219f}, {0.535156f, 0.460938f, 0.890625f, 0.269531f},
+ {0.050781f, 0.976562f, 0.289062f, 0.781250f}, {0.730469f, 0.109375f, 0.214844f, 0.460938f},
+ {0.371094f, 0.363281f, 0.789062f, 0.390625f}, {0.789062f, 0.656250f, 0.042969f, 0.074219f},
+ {0.679688f, 0.164062f, 0.269531f, 0.757812f}, {0.402344f, 0.839844f, 0.105469f, 0.359375f},
+ {0.875000f, 0.261719f, 0.875000f, 0.808594f}, {0.234375f, 0.933594f, 0.144531f, 0.046875f},
+ {0.062500f, 0.082031f, 0.945312f, 0.125000f}, {0.523438f, 0.285156f, 0.289062f, 0.937500f},
+ {0.855469f, 0.753906f, 0.691406f, 0.164062f}, {0.984375f, 0.148438f, 0.207031f, 0.464844f},
+ {0.027344f, 0.894531f, 0.132812f, 0.265625f}, {0.562500f, 0.976562f, 0.785156f, 0.593750f},
+ {0.144531f, 0.625000f, 0.476562f, 0.136719f}, {0.824219f, 0.046875f, 0.355469f, 0.320312f},
+ {0.445312f, 0.226562f, 0.558594f, 0.710938f}, {0.000000f, 0.664062f, 0.289062f, 0.207031f},
+ {0.910156f, 0.468750f, 0.835938f, 0.921875f}, {0.222656f, 0.609375f, 0.589844f, 0.039062f},
+ {0.582031f, 0.820312f, 0.898438f, 0.812500f}, {0.984375f, 0.347656f, 0.308594f, 0.445312f},
+ {0.378906f, 0.238281f, 0.550781f, 0.238281f}, {0.796875f, 0.523438f, 0.437500f, 0.542969f},
+ {0.937500f, 0.792969f, 0.179688f, 0.355469f}, {0.097656f, 0.687500f, 0.742188f, 0.429688f},
+ {0.761719f, 0.597656f, 0.523438f, 0.511719f}, {0.035156f, 0.050781f, 0.929688f, 0.132812f},
+ {0.957031f, 0.406250f, 0.328125f, 0.921875f}, {0.230469f, 0.609375f, 0.148438f, 0.472656f},
+ {0.335938f, 0.707031f, 0.777344f, 0.285156f}, {0.019531f, 0.351562f, 0.976562f, 0.824219f},
+ {0.261719f, 0.859375f, 0.316406f, 0.058594f}, {0.058594f, 0.230469f, 0.570312f, 0.570312f},
+ {0.882812f, 0.324219f, 0.652344f, 0.484375f}, {0.628906f, 0.601562f, 0.210938f, 0.015625f},
+ {0.195312f, 0.132812f, 0.988281f, 0.371094f}, {0.015625f, 0.699219f, 0.832031f, 0.527344f},
+ {0.535156f, 0.066406f, 0.335938f, 0.433594f}, {0.851562f, 0.976562f, 0.953125f, 0.742188f},
+ {0.574219f, 0.578125f, 0.468750f, 0.621094f}, {0.773438f, 0.855469f, 0.843750f, 0.316406f},
+ {0.703125f, 0.148438f, 0.750000f, 0.898438f}, {0.187500f, 0.300781f, 0.136719f, 0.582031f},
+ {0.960938f, 0.742188f, 0.644531f, 0.359375f}, {0.796875f, 0.378906f, 0.972656f, 0.523438f},
+ {0.031250f, 0.917969f, 0.171875f, 0.847656f}, {0.593750f, 0.507812f, 0.468750f, 0.445312f},
+ {0.207031f, 0.332031f, 0.359375f, 0.785156f}, {0.753906f, 0.105469f, 0.566406f, 0.914062f},
+ {0.386719f, 0.695312f, 0.960938f, 0.128906f}, {0.613281f, 0.000000f, 0.128906f, 0.308594f},
+ {0.914062f, 0.296875f, 0.792969f, 0.570312f}, {0.300781f, 0.730469f, 0.734375f, 0.457031f},
+ {0.550781f, 0.574219f, 0.972656f, 0.890625f}, {0.644531f, 0.480469f, 0.046875f, 0.687500f},
+ {0.160156f, 0.312500f, 0.335938f, 0.500000f}, {0.507812f, 0.625000f, 0.765625f, 0.417969f},
+ {0.093750f, 0.433594f, 0.164062f, 0.082031f}, {0.195312f, 0.347656f, 0.953125f, 0.355469f},
+ {0.468750f, 0.699219f, 0.109375f, 0.140625f}, {0.941406f, 0.210938f, 0.449219f, 0.832031f},
+ {0.296875f, 0.039062f, 0.656250f, 0.410156f}, {0.417969f, 0.277344f, 0.761719f, 0.878906f},
+ {0.121094f, 0.679688f, 0.027344f, 0.625000f}, {0.910156f, 0.792969f, 0.699219f, 0.156250f},
+ {0.449219f, 0.863281f, 0.625000f, 0.710938f}, {0.968750f, 0.011719f, 0.367188f, 0.871094f},
+ {0.199219f, 0.964844f, 0.554688f, 0.546875f}, {0.531250f, 0.605469f, 0.816406f, 0.441406f},
+ {0.105469f, 0.496094f, 0.460938f, 0.906250f}, {0.960938f, 0.804688f, 0.062500f, 0.484375f},
+ {0.457031f, 0.546875f, 0.515625f, 0.324219f}, {0.660156f, 0.003906f, 0.753906f, 0.578125f},
+ {0.199219f, 0.636719f, 0.035156f, 0.804688f}, {0.265625f, 0.320312f, 0.593750f, 0.093750f},
+ {0.347656f, 0.101562f, 0.957031f, 0.906250f}, {0.710938f, 0.453125f, 0.875000f, 0.363281f},
+ {0.402344f, 0.824219f, 0.027344f, 0.019531f}, {0.292969f, 0.531250f, 0.750000f, 0.554688f},
+ {0.976562f, 0.414062f, 0.910156f, 0.949219f}, {0.078125f, 0.863281f, 0.507812f, 0.089844f},
+ {0.792969f, 0.312500f, 0.390625f, 0.609375f}, {0.500000f, 0.000000f, 0.664062f, 0.347656f},
+ {0.304688f, 0.507812f, 0.160156f, 0.570312f}, {0.089844f, 0.152344f, 0.109375f, 0.097656f},
+ {0.457031f, 0.957031f, 0.800781f, 0.664062f}, {0.539062f, 0.636719f, 0.066406f, 0.738281f},
+ {0.144531f, 0.085938f, 0.878906f, 0.082031f}, {0.414062f, 0.175781f, 0.277344f, 0.886719f},
+ {0.292969f, 0.285156f, 0.835938f, 0.636719f}, {0.570312f, 0.750000f, 0.617188f, 0.257812f},
+ {0.812500f, 0.886719f, 0.058594f, 0.851562f}, {0.527344f, 0.199219f, 0.464844f, 0.082031f},
+ {0.851562f, 0.773438f, 0.664062f, 0.535156f}, {0.414062f, 0.441406f, 0.257812f, 0.679688f},
+ {0.976562f, 0.914062f, 0.109375f, 0.148438f}, {0.539062f, 0.488281f, 0.812500f, 0.886719f},
+ {0.816406f, 0.000000f, 0.371094f, 0.257812f}, {0.316406f, 0.960938f, 0.285156f, 0.703125f},
+ {0.484375f, 0.382812f, 0.457031f, 0.785156f}, {0.785156f, 0.277344f, 0.675781f, 0.875000f},
+ {0.265625f, 0.476562f, 0.070312f, 0.289062f}, {0.355469f, 0.207031f, 0.585938f, 0.109375f},
+ {0.636719f, 0.917969f, 0.179688f, 0.851562f}, {0.929688f, 0.519531f, 0.347656f, 0.515625f},
+ {0.007812f, 0.425781f, 0.554688f, 0.199219f}, {0.507812f, 0.011719f, 0.445312f, 0.085938f},
+ {0.667969f, 0.886719f, 0.859375f, 0.976562f}, {0.382812f, 0.476562f, 0.300781f, 0.738281f},
+ {0.843750f, 0.128906f, 0.726562f, 0.613281f}, {0.437500f, 0.808594f, 0.898438f, 0.183594f},
+ {0.652344f, 0.582031f, 0.667969f, 0.332031f}, {0.984375f, 0.753906f, 0.835938f, 0.699219f},
+ {0.812500f, 0.242188f, 0.320312f, 0.636719f}, {0.511719f, 0.945312f, 0.625000f, 0.816406f},
+ {0.183594f, 0.796875f, 0.421875f, 0.027344f}, {0.742188f, 0.179688f, 0.882812f, 0.253906f},
+ {0.972656f, 0.375000f, 0.660156f, 0.613281f}, {0.378906f, 0.964844f, 0.480469f, 0.324219f},
+ {0.015625f, 0.222656f, 0.863281f, 0.046875f}, {0.871094f, 0.058594f, 0.695312f, 0.800781f},
+ {0.289062f, 0.792969f, 0.382812f, 0.644531f}, {0.765625f, 0.171875f, 0.636719f, 0.929688f},
+ {0.554688f, 0.988281f, 0.808594f, 0.531250f}, {0.023438f, 0.546875f, 0.218750f, 0.730469f},
+ {0.882812f, 0.886719f, 0.929688f, 0.191406f}, {0.605469f, 0.136719f, 0.167969f, 0.332031f},
+ {0.812500f, 0.335938f, 0.414062f, 0.519531f}, {0.652344f, 0.585938f, 0.953125f, 0.093750f},
+ {0.269531f, 0.488281f, 0.132812f, 0.312500f}, {0.019531f, 0.292969f, 0.472656f, 0.589844f},
+ {0.316406f, 0.410156f, 0.914062f, 0.195312f}, {0.613281f, 0.742188f, 0.175781f, 0.023438f},
+ {0.761719f, 0.207031f, 0.398438f, 0.660156f}, {0.363281f, 0.363281f, 0.664062f, 0.253906f},
+ {0.585938f, 0.449219f, 0.246094f, 0.746094f}, {0.796875f, 0.996094f, 0.902344f, 0.882812f},
+ {0.136719f, 0.835938f, 0.367188f, 0.230469f}, {0.492188f, 0.390625f, 0.492188f, 0.707031f},
+ {0.812500f, 0.562500f, 0.316406f, 0.515625f}, {0.636719f, 0.687500f, 0.421875f, 0.839844f},
+ {0.898438f, 0.343750f, 0.164062f, 0.664062f}, {0.179688f, 0.125000f, 0.695312f, 0.453125f},
+ {0.527344f, 0.746094f, 0.097656f, 0.816406f}, {0.625000f, 0.183594f, 0.207031f, 0.156250f},
+ {0.371094f, 0.906250f, 0.003906f, 0.421875f}, {0.160156f, 0.707031f, 0.781250f, 0.683594f},
+ {0.656250f, 0.773438f, 0.343750f, 0.894531f}, {0.875000f, 0.406250f, 0.945312f, 0.171875f},
+ {0.242188f, 0.859375f, 0.699219f, 0.394531f}, {0.703125f, 0.460938f, 0.375000f, 0.281250f},
+ {0.902344f, 0.371094f, 0.636719f, 0.937500f}, {0.207031f, 0.558594f, 0.476562f, 0.574219f},
+ {0.679688f, 0.980469f, 0.121094f, 0.203125f}, {0.476562f, 0.484375f, 0.402344f, 0.773438f},
+ {0.171875f, 0.332031f, 0.808594f, 0.699219f}, {0.718750f, 0.144531f, 0.906250f, 0.417969f},
+ {0.113281f, 0.527344f, 0.195312f, 0.351562f}, {0.617188f, 0.066406f, 0.507812f, 0.933594f},
+ {0.460938f, 0.277344f, 0.417969f, 0.734375f}, {0.160156f, 0.640625f, 0.613281f, 0.394531f},
+ {0.730469f, 0.738281f, 0.039062f, 0.105469f}, {0.078125f, 0.187500f, 0.777344f, 0.617188f},
+ {0.425781f, 0.824219f, 0.527344f, 0.171875f}, {0.679688f, 0.898438f, 0.128906f, 0.984375f},
+ {0.949219f, 0.769531f, 0.414062f, 0.230469f}, {0.128906f, 0.320312f, 0.886719f, 0.402344f},
+ {0.234375f, 0.648438f, 0.046875f, 0.160156f}, {0.394531f, 0.242188f, 0.964844f, 0.691406f},
+ {0.312500f, 0.800781f, 0.265625f, 0.769531f}, {0.875000f, 0.695312f, 0.785156f, 0.414062f},
+ {0.132812f, 0.562500f, 0.085938f, 0.046875f}, {0.238281f, 0.218750f, 0.574219f, 0.292969f},
+ {0.722656f, 0.640625f, 0.394531f, 0.136719f}, {0.304688f, 0.062500f, 0.222656f, 0.941406f},
+ {0.074219f, 0.972656f, 0.039062f, 0.078125f}, {0.351562f, 0.445312f, 0.152344f, 0.542969f},
+ {0.265625f, 0.148438f, 0.500000f, 0.417969f}, {0.054688f, 0.531250f, 0.246094f, 0.203125f},
+ {0.687500f, 0.621094f, 0.007812f, 0.937500f}, {0.113281f, 0.457031f, 0.535156f, 0.378906f},
+ {0.472656f, 0.105469f, 0.210938f, 0.144531f}, {0.218750f, 0.664062f, 0.113281f, 0.996094f},
+ {0.703125f, 0.843750f, 0.261719f, 0.218750f}, {0.925781f, 0.523438f, 0.550781f, 0.722656f},
+ {0.613281f, 0.730469f, 0.019531f, 0.289062f}, {0.367188f, 0.269531f, 0.886719f, 0.472656f},
+ {0.843750f, 0.074219f, 0.304688f, 0.238281f}, {0.703125f, 0.648438f, 0.054688f, 0.984375f},
+ {0.171875f, 0.425781f, 0.371094f, 0.078125f}, {0.335938f, 0.734375f, 0.566406f, 0.660156f},
+ {0.496094f, 0.949219f, 0.500000f, 0.906250f}, {0.214844f, 0.058594f, 0.312500f, 0.750000f},
+ {0.554688f, 0.203125f, 0.867188f, 0.964844f}, {0.839844f, 0.707031f, 0.238281f, 0.257812f},
+ {0.707031f, 0.113281f, 0.679688f, 0.828125f}, {0.890625f, 0.890625f, 0.296875f, 0.144531f},
+ {0.164062f, 0.042969f, 0.968750f, 0.972656f}, {0.273438f, 0.671875f, 0.796875f, 0.609375f},
+ {0.019531f, 0.156250f, 0.562500f, 0.078125f}, {0.910156f, 0.246094f, 0.183594f, 0.371094f},
+ {0.414062f, 0.707031f, 0.824219f, 0.437500f}, {0.085938f, 0.195312f, 0.082031f, 0.046875f},
+ {0.945312f, 0.781250f, 0.683594f, 0.308594f}, {0.218750f, 0.023438f, 0.621094f, 0.175781f},
+ {0.464844f, 0.234375f, 0.261719f, 0.964844f}, {0.105469f, 0.957031f, 0.582031f, 0.234375f},
+ {0.750000f, 0.488281f, 0.808594f, 0.738281f}, {0.253906f, 0.582031f, 0.457031f, 0.285156f},
+ {0.855469f, 0.367188f, 0.984375f, 0.859375f}, {0.425781f, 0.121094f, 0.250000f, 0.492188f},
+ {0.945312f, 0.550781f, 0.433594f, 0.222656f}, {0.738281f, 0.214844f, 0.503906f, 0.953125f},
+ {0.019531f, 0.046875f, 0.226562f, 0.515625f}, {0.324219f, 0.734375f, 0.574219f, 0.785156f},
+ {0.589844f, 0.257812f, 0.011719f, 0.015625f}, {0.843750f, 0.812500f, 0.988281f, 0.468750f},
+ {0.992188f, 0.007812f, 0.238281f, 0.312500f}, {0.082031f, 0.425781f, 0.699219f, 0.054688f},
+ {0.382812f, 0.843750f, 0.304688f, 0.972656f}, {0.890625f, 0.667969f, 0.558594f, 0.183594f},
+ {0.281250f, 0.968750f, 0.000000f, 0.003906f}, {0.687500f, 0.812500f, 0.742188f, 0.632812f},
+ {0.910156f, 0.121094f, 0.867188f, 0.207031f}, {0.347656f, 0.574219f, 0.957031f, 0.511719f},
+ {0.238281f, 0.421875f, 0.183594f, 0.957031f}, {0.960938f, 0.097656f, 0.707031f, 0.316406f},
+ {0.585938f, 0.667969f, 0.921875f, 0.445312f}, {0.835938f, 0.535156f, 0.238281f, 0.660156f},
+ {0.039062f, 0.031250f, 0.800781f, 0.074219f}, {0.464844f, 0.125000f, 0.734375f, 0.808594f},
+ {0.742188f, 0.390625f, 0.503906f, 0.367188f}, {0.828125f, 0.054688f, 0.113281f, 0.953125f},
+ {0.550781f, 0.996094f, 0.621094f, 0.472656f}, {0.625000f, 0.175781f, 0.203125f, 0.636719f},
+ {0.472656f, 0.347656f, 0.941406f, 0.871094f}, {0.046875f, 0.945312f, 0.050781f, 0.675781f},
+ {0.937500f, 0.414062f, 0.503906f, 0.492188f}, {0.500000f, 0.265625f, 0.632812f, 0.832031f},
+ {0.894531f, 0.683594f, 0.992188f, 0.753906f}, {0.148438f, 0.367188f, 0.437500f, 0.277344f},
+ {0.550781f, 0.890625f, 0.777344f, 0.050781f}, {0.945312f, 0.316406f, 0.710938f, 0.871094f},
+ {0.410156f, 0.046875f, 0.343750f, 0.484375f}, {0.597656f, 0.855469f, 0.949219f, 0.671875f},
+ {0.843750f, 0.261719f, 0.398438f, 0.781250f}, {0.781250f, 0.769531f, 0.597656f, 0.515625f},
+ {0.320312f, 0.140625f, 0.796875f, 0.578125f}, {0.425781f, 0.406250f, 0.988281f, 0.894531f},
+ {0.062500f, 0.593750f, 0.191406f, 0.160156f}, {0.246094f, 0.875000f, 0.515625f, 0.824219f},
+ {0.132812f, 0.484375f, 0.468750f, 0.031250f}, {0.437500f, 0.367188f, 0.605469f, 0.375000f},
+ {0.976562f, 0.835938f, 0.859375f, 0.785156f}, {0.046875f, 0.242188f, 0.726562f, 0.433594f},
+ {0.765625f, 0.519531f, 0.089844f, 0.226562f}, {0.921875f, 0.394531f, 0.824219f, 0.003906f},
+ {0.105469f, 0.921875f, 0.585938f, 0.382812f}, {0.390625f, 0.824219f, 0.007812f, 0.476562f},
+ {0.484375f, 0.558594f, 0.738281f, 0.683594f}, {0.070312f, 0.441406f, 0.082031f, 0.347656f},
+ {0.433594f, 0.332031f, 0.605469f, 0.417969f}, {0.949219f, 0.765625f, 0.339844f, 0.789062f},
+ {0.738281f, 0.906250f, 0.015625f, 0.183594f}, {0.312500f, 0.601562f, 0.441406f, 0.527344f},
+ {0.695312f, 0.089844f, 0.722656f, 0.992188f}, {0.605469f, 0.867188f, 0.925781f, 0.644531f},
+ {0.539062f, 0.500000f, 0.218750f, 0.769531f}, {0.011719f, 0.929688f, 0.847656f, 0.414062f},
+ {0.777344f, 0.296875f, 0.972656f, 0.613281f}, {0.332031f, 0.644531f, 0.398438f, 0.058594f},
+ {0.937500f, 0.835938f, 0.328125f, 0.378906f}, {0.691406f, 0.042969f, 0.867188f, 0.542969f},
+ {0.039062f, 0.257812f, 0.625000f, 0.011719f}, {0.546875f, 0.964844f, 0.562500f, 0.753906f},
+ {0.117188f, 0.632812f, 0.738281f, 0.320312f}, {0.605469f, 0.296875f, 0.054688f, 0.050781f},
+ {0.824219f, 0.902344f, 0.820312f, 0.621094f}, {0.507812f, 0.589844f, 0.906250f, 0.863281f},
+ {0.058594f, 0.136719f, 0.324219f, 0.152344f}, {0.445312f, 0.929688f, 0.753906f, 0.671875f},
+ {0.253906f, 0.703125f, 0.167969f, 0.828125f}, {0.644531f, 0.218750f, 0.593750f, 0.375000f},
+ {0.781250f, 0.574219f, 0.085938f, 0.609375f}, {0.000000f, 0.042969f, 0.964844f, 0.550781f},
+ {0.500000f, 0.296875f, 0.359375f, 0.871094f}, {0.207031f, 0.394531f, 0.683594f, 0.457031f},
+ {0.062500f, 0.214844f, 0.136719f, 0.277344f}, {0.777344f, 0.933594f, 0.480469f, 0.847656f},
+ {0.648438f, 0.863281f, 0.332031f, 0.765625f}, {0.121094f, 0.351562f, 0.089844f, 0.042969f},
+ {0.367188f, 0.250000f, 0.390625f, 0.554688f}, {0.183594f, 0.433594f, 0.566406f, 0.730469f},
+ {0.300781f, 0.593750f, 0.300781f, 0.500000f}, {0.894531f, 0.726562f, 0.636719f, 0.589844f},
+ {0.105469f, 0.839844f, 0.375000f, 0.296875f}, {0.199219f, 0.468750f, 0.710938f, 0.125000f},
+ {0.062500f, 0.289062f, 0.902344f, 0.027344f}, {0.992188f, 0.609375f, 0.410156f, 0.250000f},
+ {0.281250f, 0.101562f, 0.687500f, 0.343750f}, {0.789062f, 0.718750f, 0.343750f, 0.558594f},
+ {0.578125f, 0.832031f, 0.878906f, 0.214844f}, {0.187500f, 0.539062f, 0.746094f, 0.378906f},
+ {0.691406f, 0.187500f, 0.277344f, 0.457031f}, {0.621094f, 0.031250f, 0.105469f, 0.984375f},
+ {0.859375f, 0.812500f, 0.917969f, 0.597656f}, {0.757812f, 0.656250f, 0.558594f, 0.343750f},
+ {0.332031f, 0.402344f, 0.179688f, 0.726562f}, {0.027344f, 0.996094f, 0.812500f, 0.085938f},
+ {0.261719f, 0.554688f, 0.074219f, 0.851562f}, {0.144531f, 0.351562f, 0.742188f, 0.003906f},
+ {0.519531f, 0.925781f, 0.449219f, 0.406250f}, {0.585938f, 0.027344f, 0.324219f, 0.347656f},
+ {0.824219f, 0.320312f, 0.097656f, 0.109375f}, {0.953125f, 0.953125f, 0.707031f, 0.558594f},
+ {0.671875f, 0.121094f, 0.773438f, 0.695312f}, {0.523438f, 0.773438f, 0.128906f, 0.609375f},
+ {0.273438f, 0.003906f, 0.964844f, 0.496094f}, {0.621094f, 0.617188f, 0.265625f, 0.132812f},
+ {0.367188f, 0.167969f, 0.199219f, 0.847656f}, {0.722656f, 0.761719f, 0.652344f, 0.539062f},
+ {0.156250f, 0.652344f, 0.437500f, 0.621094f}, {0.996094f, 0.253906f, 0.359375f, 0.777344f},
+ {0.648438f, 0.148438f, 0.937500f, 0.109375f}, {0.242188f, 0.632812f, 0.496094f, 0.902344f},
+ {0.828125f, 0.957031f, 0.769531f, 0.562500f}, {0.558594f, 0.074219f, 0.136719f, 0.289062f},
+ {0.503906f, 0.531250f, 0.878906f, 0.703125f}, {0.175781f, 0.476562f, 0.636719f, 0.843750f},
+ {0.878906f, 0.277344f, 0.292969f, 0.132812f}, {0.367188f, 0.417969f, 0.125000f, 0.574219f},
+ {0.281250f, 0.062500f, 0.550781f, 0.910156f}, {0.847656f, 0.589844f, 0.054688f, 0.273438f},
+ {0.664062f, 0.730469f, 0.511719f, 0.121094f}, {0.394531f, 0.402344f, 0.140625f, 0.503906f},
+ {0.578125f, 0.089844f, 0.039062f, 0.914062f}, {0.480469f, 0.777344f, 0.714844f, 0.652344f},
+ {0.195312f, 0.445312f, 0.179688f, 0.976562f}, {0.785156f, 0.675781f, 0.113281f, 0.132812f},
+ {0.351562f, 0.816406f, 0.886719f, 0.835938f}, {0.265625f, 0.488281f, 0.296875f, 0.453125f},
+ {0.175781f, 0.093750f, 0.144531f, 0.722656f}, {0.386719f, 0.335938f, 0.656250f, 0.339844f},
+ {0.753906f, 0.656250f, 0.531250f, 0.234375f}, {0.132812f, 0.398438f, 0.421875f, 0.421875f},
+ {0.351562f, 0.515625f, 0.929688f, 0.925781f}, {0.917969f, 0.105469f, 0.500000f, 0.492188f},
+ {0.601562f, 0.914062f, 0.773438f, 0.136719f}, {0.324219f, 0.613281f, 0.441406f, 0.750000f},
+ {0.949219f, 0.730469f, 0.222656f, 0.324219f}, {0.578125f, 0.480469f, 0.824219f, 0.808594f},
+ {0.402344f, 0.660156f, 0.289062f, 0.062500f}, {0.863281f, 0.761719f, 0.585938f, 0.578125f},
+ {0.488281f, 0.515625f, 0.898438f, 0.132812f}, {0.550781f, 0.050781f, 0.644531f, 0.355469f},
+ {0.921875f, 0.968750f, 0.832031f, 0.882812f}, {0.710938f, 0.796875f, 0.011719f, 0.261719f},
+ {0.511719f, 0.160156f, 0.980469f, 0.019531f}, {0.605469f, 0.945312f, 0.199219f, 0.921875f},
+ {0.343750f, 0.214844f, 0.789062f, 0.218750f}, {0.675781f, 0.550781f, 0.019531f, 0.570312f},
+ {0.437500f, 0.746094f, 0.468750f, 0.734375f}, {0.707031f, 0.875000f, 0.542969f, 0.804688f},
+ {0.144531f, 0.503906f, 0.285156f, 0.910156f}, {0.406250f, 0.019531f, 0.121094f, 0.101562f},
+ {0.742188f, 0.312500f, 0.816406f, 0.714844f}, {0.097656f, 0.933594f, 0.183594f, 0.007812f},
+ {0.371094f, 0.761719f, 0.589844f, 0.648438f}, {0.453125f, 0.492188f, 0.378906f, 0.167969f},
+ {0.222656f, 0.585938f, 0.847656f, 0.796875f}, {0.121094f, 0.214844f, 0.058594f, 0.128906f},
+ {0.484375f, 0.730469f, 0.632812f, 0.546875f}, {0.914062f, 0.078125f, 0.871094f, 0.296875f},
+ {0.640625f, 0.191406f, 0.304688f, 0.441406f}, {0.886719f, 0.714844f, 0.148438f, 0.242188f},
+ {0.082031f, 0.464844f, 0.933594f, 0.750000f}, {0.742188f, 0.632812f, 0.640625f, 0.667969f},
+ {0.183594f, 0.230469f, 0.386719f, 0.953125f}, {0.484375f, 0.687500f, 0.917969f, 0.445312f},
+ {0.007812f, 0.187500f, 0.226562f, 0.308594f}, {0.804688f, 0.570312f, 0.417969f, 0.914062f},
+ {0.195312f, 0.304688f, 0.671875f, 0.253906f}, {0.878906f, 0.902344f, 0.351562f, 0.960938f},
+ {0.078125f, 0.082031f, 0.042969f, 0.710938f}, {0.460938f, 0.449219f, 0.988281f, 0.292969f},
+ {0.300781f, 0.320312f, 0.781250f, 0.058594f}, {0.593750f, 0.023438f, 0.171875f, 0.949219f},
+ {0.796875f, 0.500000f, 0.539062f, 0.207031f}, {0.339844f, 0.839844f, 0.218750f, 0.503906f},
+ {0.132812f, 0.289062f, 0.417969f, 0.070312f}, {0.675781f, 0.218750f, 0.269531f, 0.871094f},
+ {0.042969f, 0.378906f, 0.996094f, 0.035156f}, {0.230469f, 0.816406f, 0.515625f, 0.472656f},
+ {0.453125f, 0.964844f, 0.375000f, 0.332031f}, {0.746094f, 0.664062f, 0.792969f, 0.214844f},
+ {0.058594f, 0.351562f, 0.457031f, 0.000000f}, {0.968750f, 0.882812f, 0.343750f, 0.718750f},
+ {0.160156f, 0.140625f, 0.765625f, 0.878906f}, {0.238281f, 0.207031f, 0.675781f, 0.789062f},
+ {0.070312f, 0.535156f, 0.945312f, 0.335938f}, {0.894531f, 0.917969f, 0.277344f, 0.179688f},
+ {0.296875f, 0.332031f, 0.535156f, 0.597656f}, {0.988281f, 0.167969f, 0.359375f, 0.398438f},
+ {0.718750f, 0.015625f, 0.671875f, 0.257812f}, {0.472656f, 0.414062f, 0.960938f, 0.554688f},
+ {0.890625f, 0.996094f, 0.460938f, 0.109375f}, {0.964844f, 0.789062f, 0.199219f, 0.996094f},
+ {0.667969f, 0.875000f, 0.089844f, 0.585938f}, {0.804688f, 0.183594f, 0.859375f, 0.703125f},
+ {0.546875f, 0.312500f, 0.261719f, 0.089844f}, {0.050781f, 0.769531f, 0.046875f, 0.273438f},
+ {0.187500f, 0.253906f, 0.843750f, 0.894531f}, {0.441406f, 0.367188f, 0.644531f, 0.230469f},
+ {0.742188f, 0.171875f, 0.105469f, 0.097656f}, {0.824219f, 0.890625f, 0.535156f, 0.984375f},
+ {0.144531f, 0.015625f, 0.394531f, 0.656250f}, {0.296875f, 0.316406f, 0.058594f, 0.402344f},
+ {0.019531f, 0.144531f, 0.210938f, 0.691406f}, {0.753906f, 0.621094f, 0.730469f, 0.929688f},
+ {0.250000f, 0.703125f, 0.492188f, 0.191406f}, {0.054688f, 0.292969f, 0.152344f, 0.414062f},
+ {0.410156f, 0.492188f, 0.445312f, 0.777344f}, {0.796875f, 0.339844f, 0.871094f, 0.855469f},
+ {0.902344f, 0.085938f, 0.250000f, 0.632812f}, {0.531250f, 0.906250f, 0.324219f, 0.394531f},
+ {0.250000f, 0.132812f, 0.839844f, 0.976562f}, {0.917969f, 0.375000f, 0.160156f, 0.523438f},
+ {0.859375f, 0.792969f, 0.601562f, 0.160156f}, {0.335938f, 0.453125f, 0.714844f, 0.425781f},
+ {0.523438f, 0.152344f, 0.464844f, 0.949219f}, {0.957031f, 0.625000f, 0.000000f, 0.863281f},
+ {0.800781f, 0.089844f, 0.531250f, 0.257812f}, {0.000000f, 0.863281f, 0.316406f, 0.511719f},
+ {0.308594f, 0.285156f, 0.679688f, 0.906250f}, {0.824219f, 0.132812f, 0.472656f, 0.230469f},
+ {0.535156f, 0.917969f, 0.265625f, 0.656250f}, {0.683594f, 0.503906f, 0.429688f, 0.960938f},
+ {0.363281f, 0.609375f, 0.515625f, 0.171875f}, {0.445312f, 0.289062f, 0.683594f, 0.917969f},
+ {0.964844f, 0.808594f, 0.238281f, 0.617188f}, {0.277344f, 0.085938f, 0.042969f, 0.062500f},
+ {0.394531f, 0.511719f, 0.839844f, 0.203125f}, {0.636719f, 0.753906f, 0.585938f, 0.843750f},
+ {0.343750f, 0.417969f, 0.289062f, 0.761719f}, {0.746094f, 0.933594f, 0.011719f, 0.171875f},
+ {0.566406f, 0.472656f, 0.816406f, 0.066406f}, {0.398438f, 0.671875f, 0.550781f, 0.566406f},
+ {0.675781f, 0.855469f, 0.750000f, 0.351562f}, {0.832031f, 0.546875f, 0.488281f, 0.179688f},
+ {0.222656f, 0.992188f, 0.285156f, 0.449219f}, {0.531250f, 0.792969f, 0.117188f, 0.839844f},
+ {0.003906f, 0.382812f, 0.875000f, 0.320312f}, {0.718750f, 0.722656f, 0.625000f, 0.718750f},
+ {0.925781f, 0.574219f, 0.843750f, 0.636719f}, {0.382812f, 0.878906f, 0.070312f, 0.238281f},
+ {0.621094f, 0.015625f, 0.707031f, 0.398438f}, {0.988281f, 0.738281f, 0.195312f, 0.925781f},
+ {0.796875f, 0.125000f, 0.039062f, 0.667969f}, {0.136719f, 0.179688f, 0.953125f, 0.796875f},
+ {0.632812f, 0.542969f, 0.648438f, 0.382812f}, {0.496094f, 0.804688f, 0.253906f, 0.550781f},
+ {0.433594f, 0.449219f, 0.894531f, 0.457031f}, {0.730469f, 0.988281f, 0.203125f, 0.675781f},
+ {0.800781f, 0.273438f, 0.484375f, 0.222656f}, {0.136719f, 0.710938f, 0.414062f, 0.074219f},
+ {0.617188f, 0.597656f, 0.789062f, 0.472656f}, {0.417969f, 0.851562f, 0.843750f, 0.800781f},
+ {0.027344f, 0.242188f, 0.031250f, 0.695312f}, {0.566406f, 0.699219f, 0.398438f, 0.898438f},
+ {0.089844f, 0.195312f, 0.593750f, 0.187500f}, {0.617188f, 0.531250f, 0.792969f, 0.382812f},
+ {0.199219f, 0.445312f, 0.351562f, 0.769531f}, {0.289062f, 0.074219f, 0.675781f, 0.035156f},
+ {0.492188f, 0.632812f, 0.730469f, 0.535156f}, {0.699219f, 0.976562f, 0.382812f, 0.800781f},
+ {0.875000f, 0.464844f, 0.308594f, 0.640625f}, {0.121094f, 0.800781f, 0.171875f, 0.437500f},
+ {0.257812f, 0.078125f, 0.925781f, 0.714844f}, {0.523438f, 0.550781f, 0.718750f, 0.507812f},
+ {0.625000f, 0.992188f, 0.996094f, 0.171875f}, {0.968750f, 0.238281f, 0.781250f, 0.246094f},
+ {0.191406f, 0.453125f, 0.433594f, 0.468750f}, {0.441406f, 0.839844f, 0.269531f, 0.812500f},
+ {0.855469f, 0.203125f, 0.941406f, 0.621094f}, {0.652344f, 0.890625f, 0.347656f, 0.113281f},
+ {0.972656f, 0.007812f, 0.687500f, 0.480469f}, {0.156250f, 0.679688f, 0.585938f, 0.683594f},
+ {0.015625f, 0.617188f, 0.519531f, 0.078125f}, {0.761719f, 0.437500f, 0.945312f, 0.453125f},
+ {0.371094f, 0.261719f, 0.078125f, 0.320312f}, {0.585938f, 0.652344f, 0.757812f, 0.054688f},
+ {0.031250f, 0.207031f, 0.972656f, 0.609375f}, {0.644531f, 0.585938f, 0.375000f, 0.292969f},
+ {0.210938f, 0.894531f, 0.242188f, 0.769531f}, {0.269531f, 0.246094f, 0.902344f, 0.574219f},
+ {0.882812f, 0.390625f, 0.957031f, 0.355469f}, {0.570312f, 0.457031f, 0.769531f, 0.062500f},
+ {0.726562f, 0.953125f, 0.214844f, 0.406250f}, {0.988281f, 0.347656f, 0.136719f, 0.742188f},
+ {0.066406f, 0.785156f, 0.972656f, 0.035156f}, {0.156250f, 0.425781f, 0.726562f, 0.375000f},
+ {0.207031f, 0.015625f, 0.015625f, 0.589844f}, {0.710938f, 0.898438f, 0.894531f, 0.480469f},
+ {0.031250f, 0.160156f, 0.562500f, 0.792969f}, {0.546875f, 0.980469f, 0.480469f, 0.273438f},
+ {0.863281f, 0.859375f, 0.738281f, 0.535156f}, {0.101562f, 0.355469f, 0.171875f, 0.371094f},
+ {0.910156f, 0.054688f, 0.523438f, 0.011719f}, {0.296875f, 0.808594f, 0.894531f, 0.640625f},
+ {0.937500f, 0.257812f, 0.457031f, 0.414062f}, {0.125000f, 0.113281f, 0.152344f, 0.804688f},
+ {0.507812f, 0.363281f, 0.617188f, 0.882812f}, {0.957031f, 0.195312f, 0.394531f, 0.656250f},
+ {0.054688f, 0.695312f, 0.906250f, 0.750000f}, {0.902344f, 0.070312f, 0.703125f, 0.582031f},
+ {0.421875f, 0.929688f, 0.031250f, 0.140625f}, {0.187500f, 0.167969f, 0.671875f, 0.433594f},
+ {0.476562f, 0.101562f, 0.363281f, 0.980469f}, {0.281250f, 0.683594f, 0.570312f, 0.765625f},
+ {0.847656f, 0.437500f, 0.472656f, 0.167969f}, {0.078125f, 0.628906f, 0.832031f, 0.605469f},
+ {0.570312f, 0.328125f, 0.593750f, 0.101562f}, {0.261719f, 0.765625f, 0.738281f, 0.503906f},
+ {0.906250f, 0.242188f, 0.164062f, 0.960938f}, {0.324219f, 0.007812f, 0.824219f, 0.164062f},
+ {0.593750f, 0.683594f, 0.570312f, 0.089844f}, {0.921875f, 0.617188f, 0.105469f, 0.296875f},
+ {0.527344f, 0.050781f, 0.632812f, 0.851562f}, {0.359375f, 0.375000f, 0.910156f, 0.726562f},
+ {0.835938f, 0.128906f, 0.070312f, 0.937500f}, {0.664062f, 0.515625f, 0.226562f, 0.027344f},
+ {0.226562f, 0.890625f, 0.500000f, 0.300781f}, {0.851562f, 0.574219f, 0.757812f, 0.648438f},
+ {0.316406f, 0.753906f, 0.257812f, 0.058594f}, {0.429688f, 0.277344f, 0.937500f, 0.507812f},
+ {0.007812f, 0.031250f, 0.019531f, 0.878906f}, {0.933594f, 0.714844f, 0.550781f, 0.308594f},
+ {0.835938f, 0.847656f, 0.136719f, 0.164062f}, {0.234375f, 0.546875f, 0.617188f, 0.968750f},
+ {0.394531f, 0.132812f, 0.902344f, 0.355469f}, {0.980469f, 0.679688f, 0.566406f, 0.019531f},
+ {0.671875f, 0.839844f, 0.468750f, 0.585938f}, {0.046875f, 0.417969f, 0.250000f, 0.378906f},
+ {0.375000f, 0.597656f, 0.023438f, 0.898438f}, {0.695312f, 0.789062f, 0.625000f, 0.753906f},
+ {0.898438f, 0.375000f, 0.875000f, 0.007812f}, {0.328125f, 0.542969f, 0.113281f, 0.531250f},
+ {0.578125f, 0.109375f, 0.542969f, 0.300781f}, {0.085938f, 0.406250f, 0.765625f, 0.988281f},
+ {0.285156f, 0.566406f, 0.062500f, 0.339844f}, {0.472656f, 0.777344f, 0.128906f, 0.164062f},
+ {0.636719f, 0.363281f, 0.628906f, 0.750000f}, {0.832031f, 0.035156f, 0.394531f, 0.835938f},
+ {0.109375f, 0.972656f, 0.667969f, 0.195312f}, {0.183594f, 0.710938f, 0.222656f, 0.890625f},
+ {0.808594f, 0.066406f, 0.046875f, 0.707031f}, {0.460938f, 0.953125f, 0.855469f, 0.476562f},
+ {0.082031f, 0.335938f, 0.652344f, 0.203125f}, {0.667969f, 0.738281f, 0.093750f, 0.121094f},
+ {0.425781f, 0.664062f, 0.417969f, 0.683594f}, {0.164062f, 0.007812f, 0.613281f, 0.964844f},
+ {0.632812f, 0.703125f, 0.042969f, 0.617188f}, {0.250000f, 0.554688f, 0.804688f, 0.464844f},
+ {0.394531f, 0.242188f, 0.371094f, 0.878906f}, {0.937500f, 0.847656f, 0.601562f, 0.816406f},
+ {0.804688f, 0.679688f, 0.195312f, 0.113281f}, {0.601562f, 0.378906f, 0.335938f, 0.320312f},
+ {0.339844f, 0.562500f, 0.812500f, 0.867188f}, {0.785156f, 0.437500f, 0.125000f, 0.140625f},
+ {0.230469f, 0.273438f, 0.355469f, 0.980469f}, {0.687500f, 0.656250f, 0.957031f, 0.468750f},
+ {0.156250f, 0.148438f, 0.082031f, 0.726562f}, {0.464844f, 0.535156f, 0.703125f, 0.898438f},
+ {0.039062f, 0.722656f, 0.324219f, 0.285156f}, {0.250000f, 0.945312f, 0.945312f, 0.117188f},
+ {0.777344f, 0.589844f, 0.093750f, 0.484375f}, {0.328125f, 0.285156f, 0.222656f, 0.023438f},
+ {0.609375f, 0.421875f, 0.828125f, 0.390625f}, {0.746094f, 0.617188f, 0.335938f, 0.929688f},
+ {0.261719f, 0.238281f, 0.449219f, 0.265625f}, {0.863281f, 0.472656f, 0.953125f, 0.031250f},
+ {0.105469f, 0.316406f, 0.292969f, 0.355469f}, {0.765625f, 0.976562f, 0.152344f, 0.531250f},
+ {0.523438f, 0.195312f, 0.933594f, 0.828125f}, {0.343750f, 0.554688f, 0.242188f, 0.304688f},
+ {0.414062f, 0.890625f, 0.414062f, 0.742188f}, {0.695312f, 0.496094f, 0.085938f, 0.250000f},
+ {0.824219f, 0.933594f, 0.316406f, 0.832031f}, {0.109375f, 0.386719f, 0.433594f, 0.347656f},
+ {0.199219f, 0.304688f, 0.000000f, 0.632812f}, {0.023438f, 0.843750f, 0.378906f, 0.988281f},
+ {0.679688f, 0.480469f, 0.746094f, 0.429688f}, {0.265625f, 0.769531f, 0.312500f, 0.574219f},
+ {0.058594f, 0.941406f, 0.593750f, 0.359375f}, {0.507812f, 0.074219f, 0.992188f, 0.527344f},
+ {0.160156f, 0.308594f, 0.167969f, 0.214844f}, {0.945312f, 0.382812f, 0.644531f, 0.964844f},
+ {0.789062f, 0.105469f, 0.117188f, 0.441406f}, {0.523438f, 0.613281f, 0.875000f, 0.812500f},
+ {0.722656f, 0.953125f, 0.492188f, 0.226562f}, {0.371094f, 0.347656f, 0.226562f, 0.617188f},
+ {0.101562f, 0.214844f, 0.984375f, 0.464844f}, {0.628906f, 0.406250f, 0.433594f, 0.742188f},
+ {0.777344f, 0.011719f, 0.035156f, 0.199219f}, {0.480469f, 0.277344f, 0.753906f, 0.855469f},
+ {0.339844f, 0.332031f, 0.347656f, 0.281250f}, {0.093750f, 0.207031f, 0.671875f, 0.792969f},
+ {0.808594f, 0.699219f, 0.156250f, 0.121094f}, {0.226562f, 0.097656f, 0.507812f, 0.335938f},
+ {0.476562f, 0.941406f, 0.367188f, 0.945312f}, {0.109375f, 0.660156f, 0.187500f, 0.210938f},
+ {0.800781f, 0.750000f, 0.609375f, 0.066406f}, {0.382812f, 0.984375f, 0.824219f, 0.714844f},
+ {0.738281f, 0.242188f, 0.296875f, 0.554688f}, {0.222656f, 0.832031f, 0.917969f, 0.906250f},
+ {0.320312f, 0.929688f, 0.464844f, 0.503906f}, {0.980469f, 0.519531f, 0.175781f, 0.277344f},
+ {0.500000f, 0.312500f, 0.808594f, 0.664062f}, {0.285156f, 0.816406f, 0.562500f, 0.789062f},
+ {0.929688f, 0.542969f, 0.437500f, 0.382812f}, {0.542969f, 0.414062f, 0.507812f, 0.023438f},
+ {0.777344f, 0.847656f, 0.308594f, 0.843750f}, {0.976562f, 0.121094f, 0.738281f, 0.527344f},
+ {0.042969f, 0.511719f, 0.164062f, 0.316406f}, {0.507812f, 0.812500f, 0.492188f, 0.824219f},
+ {0.339844f, 0.183594f, 0.875000f, 0.089844f}, {0.773438f, 0.074219f, 0.546875f, 0.281250f},
+ {0.460938f, 0.640625f, 0.929688f, 0.195312f}, {0.558594f, 0.121094f, 0.105469f, 0.695312f},
+ {0.285156f, 0.316406f, 0.781250f, 0.523438f}, {0.875000f, 0.769531f, 0.414062f, 0.019531f},
+ {0.121094f, 0.222656f, 0.984375f, 0.710938f}, {0.488281f, 0.710938f, 0.269531f, 0.398438f},
+ {0.992188f, 0.031250f, 0.625000f, 0.656250f}, {0.421875f, 0.597656f, 0.437500f, 0.101562f},
+ {0.593750f, 0.890625f, 0.777344f, 0.226562f}, {0.839844f, 0.214844f, 0.601562f, 0.589844f},
+ {0.718750f, 0.402344f, 0.253906f, 0.523438f}, {0.644531f, 0.019531f, 0.855469f, 0.687500f},
+ {0.433594f, 0.820312f, 0.667969f, 0.992188f}, {0.167969f, 0.746094f, 0.050781f, 0.238281f},
+ {0.109375f, 0.128906f, 0.582031f, 0.105469f}, {0.363281f, 0.847656f, 0.527344f, 0.527344f},
+ {0.687500f, 0.531250f, 0.191406f, 0.804688f}, {0.562500f, 0.777344f, 0.101562f, 0.683594f},
+ {0.636719f, 0.597656f, 0.796875f, 0.890625f}, {0.953125f, 0.402344f, 0.726562f, 0.113281f},
+ {0.164062f, 0.832031f, 0.011719f, 0.453125f}, {0.734375f, 0.265625f, 0.343750f, 0.019531f},
+ {0.210938f, 0.046875f, 0.675781f, 0.941406f}, {0.003906f, 0.089844f, 0.910156f, 0.421875f},
+ {0.535156f, 0.703125f, 0.523438f, 0.058594f}, {0.382812f, 0.578125f, 0.980469f, 0.582031f},
+ {0.984375f, 0.113281f, 0.699219f, 0.761719f}, {0.304688f, 0.906250f, 0.851562f, 0.023438f},
+ {0.859375f, 0.167969f, 0.250000f, 0.261719f}, {0.453125f, 0.230469f, 0.144531f, 0.113281f},
+ {0.960938f, 0.429688f, 0.453125f, 0.828125f}, {0.757812f, 0.628906f, 0.695312f, 0.156250f},
+ {0.375000f, 0.792969f, 0.343750f, 0.757812f}, {0.691406f, 0.476562f, 0.558594f, 0.593750f},
+ {0.250000f, 0.906250f, 0.300781f, 0.332031f}, {0.140625f, 0.152344f, 0.707031f, 0.136719f},
+ {0.871094f, 0.824219f, 0.394531f, 0.667969f}, {0.582031f, 0.496094f, 0.828125f, 0.941406f},
+ {0.453125f, 0.589844f, 0.769531f, 0.394531f}, {0.167969f, 0.910156f, 0.285156f, 0.058594f},
+ {0.027344f, 0.750000f, 0.195312f, 0.675781f}, {0.570312f, 0.949219f, 0.867188f, 0.515625f},
+ {0.843750f, 0.519531f, 0.078125f, 0.933594f}, {0.937500f, 0.878906f, 0.835938f, 0.070312f},
+ {0.539062f, 0.039062f, 0.292969f, 0.625000f}, {0.761719f, 0.492188f, 0.796875f, 0.558594f},
+ {0.597656f, 0.285156f, 0.703125f, 0.828125f}, {0.160156f, 0.171875f, 0.957031f, 0.656250f},
+ {0.671875f, 0.058594f, 0.035156f, 0.433594f}, {0.503906f, 0.324219f, 0.417969f, 0.863281f},
+ {0.925781f, 0.453125f, 0.230469f, 0.250000f}, {0.566406f, 0.136719f, 0.742188f, 0.031250f},
+ {0.066406f, 0.195312f, 0.097656f, 0.968750f}, {0.417969f, 0.753906f, 0.988281f, 0.097656f},
+ {0.675781f, 0.113281f, 0.273438f, 0.546875f}, {0.726562f, 0.468750f, 0.339844f, 0.136719f},
+ {0.394531f, 0.171875f, 0.914062f, 0.253906f}, {0.144531f, 0.277344f, 0.128906f, 0.996094f},
+ {0.316406f, 0.039062f, 0.578125f, 0.644531f}, {0.714844f, 0.574219f, 0.820312f, 0.910156f},
+ {0.378906f, 0.222656f, 0.269531f, 0.437500f}, {0.906250f, 0.984375f, 0.707031f, 0.175781f},
+ {0.113281f, 0.371094f, 0.339844f, 0.765625f}, {0.851562f, 0.882812f, 0.242188f, 0.570312f},
+ {0.015625f, 0.472656f, 0.453125f, 0.343750f}, {0.664062f, 0.972656f, 0.292969f, 0.984375f},
+ {0.097656f, 0.523438f, 0.660156f, 0.421875f}, {0.429688f, 0.058594f, 0.527344f, 0.234375f},
+ {0.187500f, 0.933594f, 0.070312f, 0.925781f}, {0.628906f, 0.132812f, 0.679688f, 0.558594f},
+ {0.753906f, 0.796875f, 0.203125f, 0.773438f}, {0.070312f, 0.484375f, 0.847656f, 0.328125f},
+ {0.355469f, 0.964844f, 0.035156f, 0.855469f}, {0.527344f, 0.335938f, 0.390625f, 0.933594f},
+ {0.210938f, 0.625000f, 0.191406f, 0.367188f}, {0.976562f, 0.460938f, 0.507812f, 0.191406f},
+ {0.582031f, 0.171875f, 0.425781f, 0.765625f}, {0.882812f, 0.507812f, 0.761719f, 0.332031f},
+ {0.812500f, 0.914062f, 0.265625f, 0.636719f}, {0.496094f, 0.050781f, 0.976562f, 0.875000f},
+ {0.980469f, 0.355469f, 0.738281f, 0.187500f}, {0.031250f, 0.898438f, 0.605469f, 0.476562f},
+ {0.320312f, 0.027344f, 0.410156f, 0.597656f}, {0.441406f, 0.734375f, 0.507812f, 0.218750f},
+ {0.066406f, 0.140625f, 0.894531f, 0.714844f}, {0.894531f, 0.468750f, 0.550781f, 0.562500f},
+ {0.652344f, 0.789062f, 0.785156f, 0.648438f}, {0.863281f, 0.972656f, 0.132812f, 0.191406f},
+ {0.457031f, 0.425781f, 0.277344f, 0.894531f}, {0.738281f, 0.203125f, 0.605469f, 0.683594f},
+ {0.640625f, 0.808594f, 0.480469f, 0.472656f}, {0.777344f, 0.515625f, 0.183594f, 0.199219f},
+ {0.125000f, 0.339844f, 0.953125f, 0.921875f}, {0.570312f, 0.671875f, 0.539062f, 0.500000f},
+ {0.210938f, 0.730469f, 0.781250f, 0.671875f}, {0.097656f, 0.019531f, 0.019531f, 0.890625f},
+ {0.597656f, 0.968750f, 0.835938f, 0.406250f}, {0.468750f, 0.191406f, 0.914062f, 0.082031f},
+ {0.042969f, 0.667969f, 0.445312f, 0.847656f}, {0.648438f, 0.421875f, 0.050781f, 0.722656f},
+ {0.335938f, 0.773438f, 0.179688f, 0.000000f}, {0.992188f, 0.300781f, 0.636719f, 0.257812f},
+ {0.273438f, 0.066406f, 0.093750f, 0.562500f}, {0.750000f, 0.171875f, 0.476562f, 0.902344f},
+ {0.902344f, 0.660156f, 0.691406f, 0.320312f}, {0.300781f, 0.445312f, 0.527344f, 0.144531f},
+ {0.195312f, 0.621094f, 0.406250f, 0.457031f}, {0.429688f, 0.152344f, 0.968750f, 0.707031f},
+ {0.273438f, 0.734375f, 0.453125f, 0.414062f}, {0.003906f, 0.914062f, 0.578125f, 0.265625f},
+ {0.410156f, 0.355469f, 0.093750f, 0.484375f}, {0.996094f, 0.847656f, 0.316406f, 0.148438f},
+ {0.839844f, 0.605469f, 0.484375f, 0.359375f}, {0.031250f, 0.511719f, 0.898438f, 0.773438f},
+ {0.187500f, 0.726562f, 0.679688f, 0.589844f}, {0.867188f, 0.644531f, 0.355469f, 0.390625f},
+ {0.136719f, 0.878906f, 0.843750f, 0.640625f}, {0.597656f, 0.589844f, 0.597656f, 0.441406f},
+ {0.222656f, 0.394531f, 0.714844f, 0.355469f}, {0.003906f, 0.863281f, 0.031250f, 0.925781f},
+ {0.871094f, 0.691406f, 0.761719f, 0.597656f}, {0.621094f, 0.628906f, 0.195312f, 0.414062f},
+ {0.230469f, 0.769531f, 0.941406f, 0.074219f}, {0.582031f, 0.929688f, 0.023438f, 0.230469f},
+ {0.812500f, 0.433594f, 0.398438f, 0.722656f}, {0.195312f, 0.304688f, 0.996094f, 0.000000f},
+ {0.679688f, 0.761719f, 0.089844f, 0.496094f}, {0.593750f, 0.605469f, 0.636719f, 0.925781f},
+ {0.222656f, 0.277344f, 0.750000f, 0.136719f}, {0.902344f, 0.730469f, 0.164062f, 0.644531f},
+ {0.515625f, 0.191406f, 0.863281f, 0.785156f}, {0.722656f, 0.585938f, 0.031250f, 0.601562f},
+ {0.949219f, 0.457031f, 0.921875f, 0.183594f}, {0.312500f, 0.851562f, 0.468750f, 0.066406f},
+ {0.003906f, 0.390625f, 0.750000f, 0.257812f}, {0.265625f, 0.304688f, 0.308594f, 0.496094f},
+ {0.808594f, 0.097656f, 0.542969f, 0.035156f}, {0.894531f, 0.761719f, 0.136719f, 0.152344f},
+ {0.089844f, 0.691406f, 0.992188f, 0.445312f}, {0.382812f, 0.070312f, 0.792969f, 0.070312f},
+ {0.011719f, 0.984375f, 0.355469f, 0.843750f}, {0.281250f, 0.308594f, 0.910156f, 0.593750f},
+ {0.660156f, 0.648438f, 0.152344f, 0.429688f}, {0.210938f, 0.210938f, 0.468750f, 0.722656f},
+ {0.406250f, 0.703125f, 0.019531f, 0.304688f}, {0.148438f, 0.273438f, 0.882812f, 0.078125f},
+ {0.832031f, 0.089844f, 0.250000f, 0.968750f}, {0.242188f, 0.863281f, 0.652344f, 0.335938f},
+ {0.601562f, 0.371094f, 0.199219f, 0.847656f}, {0.484375f, 0.679688f, 0.062500f, 0.277344f},
+ {0.289062f, 0.617188f, 0.453125f, 0.378906f}, {0.941406f, 0.343750f, 0.863281f, 0.515625f},
+ {0.152344f, 0.281250f, 0.218750f, 0.128906f}, {0.238281f, 0.746094f, 0.039062f, 0.316406f},
+ {0.046875f, 0.636719f, 0.792969f, 0.871094f}, {0.496094f, 0.031250f, 0.351562f, 0.390625f},
+ {0.406250f, 0.980469f, 0.660156f, 0.789062f}, {0.707031f, 0.558594f, 0.054688f, 0.609375f},
+ {0.886719f, 0.859375f, 0.890625f, 0.320312f}, {0.312500f, 0.132812f, 0.394531f, 0.039062f},
+ {0.816406f, 0.265625f, 0.250000f, 0.242188f}, {0.906250f, 0.355469f, 0.097656f, 0.488281f},
+ {0.410156f, 0.539062f, 0.746094f, 0.921875f}, {0.769531f, 0.093750f, 0.972656f, 0.539062f},
+ {0.203125f, 0.246094f, 0.527344f, 0.425781f}, {0.070312f, 0.695312f, 0.324219f, 0.800781f},
+ {0.820312f, 0.878906f, 0.906250f, 0.117188f}, {0.515625f, 0.375000f, 0.574219f, 0.761719f},
+ {0.660156f, 0.238281f, 0.941406f, 0.605469f}, {0.113281f, 0.105469f, 0.132812f, 0.835938f},
+ {0.710938f, 0.820312f, 0.652344f, 0.238281f}, {0.621094f, 0.394531f, 0.214844f, 0.992188f},
+ {0.136719f, 0.253906f, 0.011719f, 0.187500f}, {0.921875f, 0.578125f, 0.902344f, 0.046875f},
+ {0.730469f, 0.441406f, 0.246094f, 0.886719f}, {0.300781f, 0.800781f, 0.847656f, 0.957031f},
+ {0.238281f, 0.222656f, 0.648438f, 0.687500f}, {0.355469f, 0.894531f, 0.136719f, 0.109375f},
+ {0.707031f, 0.027344f, 0.554688f, 0.199219f}, {0.453125f, 0.285156f, 0.003906f, 0.800781f},
+ {0.953125f, 0.074219f, 0.511719f, 0.156250f}, {0.750000f, 0.671875f, 0.152344f, 0.863281f},
+ {0.824219f, 0.238281f, 0.402344f, 0.699219f}, {0.339844f, 0.003906f, 0.492188f, 0.042969f},
+ {0.964844f, 0.980469f, 0.867188f, 0.753906f}, {0.101562f, 0.367188f, 0.617188f, 0.511719f},
+ {0.492188f, 0.488281f, 0.363281f, 0.300781f}, {0.062500f, 0.156250f, 0.667969f, 0.800781f},
+ {0.277344f, 0.652344f, 0.550781f, 0.355469f}, {0.441406f, 0.062500f, 0.847656f, 0.601562f},
+ {0.953125f, 0.535156f, 0.199219f, 0.847656f}, {0.316406f, 0.140625f, 0.011719f, 0.250000f},
+ {0.757812f, 0.019531f, 0.910156f, 0.390625f}, {0.359375f, 0.390625f, 0.570312f, 0.042969f},
+ {0.054688f, 0.902344f, 0.386719f, 0.863281f}, {0.824219f, 0.339844f, 0.714844f, 0.304688f},
+ {0.390625f, 0.632812f, 0.242188f, 0.457031f}, {0.562500f, 0.238281f, 0.589844f, 0.734375f},
+ {0.921875f, 0.683594f, 0.097656f, 0.953125f}, {0.507812f, 0.550781f, 0.949219f, 0.816406f},
+ {0.671875f, 0.191406f, 0.878906f, 0.617188f}, {0.175781f, 0.835938f, 0.644531f, 0.703125f},
+ {0.316406f, 0.273438f, 0.718750f, 0.789062f}, {0.757812f, 0.871094f, 0.000000f, 0.550781f},
+ {0.546875f, 0.566406f, 0.113281f, 0.265625f}, {0.472656f, 0.382812f, 0.621094f, 0.941406f},
+ {0.925781f, 0.796875f, 0.699219f, 0.156250f}, {0.058594f, 0.437500f, 0.386719f, 0.050781f},
+ {0.777344f, 0.945312f, 0.308594f, 0.781250f}, {0.535156f, 0.496094f, 0.820312f, 0.394531f},
+ {0.906250f, 0.644531f, 0.125000f, 0.656250f}, {0.703125f, 0.542969f, 0.371094f, 0.144531f},
+ {0.804688f, 0.226562f, 0.988281f, 0.914062f}, {0.378906f, 0.906250f, 0.300781f, 0.046875f},
+ {0.035156f, 0.175781f, 0.753906f, 0.785156f}, {0.570312f, 0.566406f, 0.628906f, 0.976562f},
+ {0.343750f, 0.125000f, 0.390625f, 0.730469f}, {0.804688f, 0.878906f, 0.722656f, 0.238281f},
+ {0.605469f, 0.453125f, 0.921875f, 0.539062f}, {0.953125f, 0.257812f, 0.089844f, 0.093750f},
+ {0.179688f, 0.085938f, 0.429688f, 0.714844f}, {0.347656f, 0.402344f, 0.281250f, 0.167969f},
+ {0.628906f, 0.300781f, 0.613281f, 0.449219f}, {0.007812f, 0.503906f, 0.507812f, 0.984375f},
+ {0.539062f, 0.601562f, 0.187500f, 0.710938f}, {0.281250f, 0.835938f, 0.660156f, 0.632812f},
+ {0.113281f, 0.738281f, 0.363281f, 0.285156f}, {0.953125f, 0.933594f, 0.593750f, 0.191406f},
+ {0.554688f, 0.007812f, 0.238281f, 0.355469f}, {0.683594f, 0.625000f, 0.800781f, 0.980469f},
+ {0.417969f, 0.472656f, 0.000000f, 0.500000f}, {0.222656f, 0.984375f, 0.371094f, 0.218750f},
+ {0.382812f, 0.777344f, 0.253906f, 0.070312f}, {0.972656f, 0.566406f, 0.808594f, 0.378906f},
+ {0.472656f, 0.308594f, 0.316406f, 0.542969f}, {0.789062f, 0.058594f, 0.609375f, 0.781250f},
+ {0.855469f, 0.972656f, 0.726562f, 0.648438f}, {0.359375f, 0.652344f, 0.519531f, 0.746094f},
+ {0.511719f, 0.000000f, 0.425781f, 0.582031f}, {0.074219f, 0.125000f, 0.750000f, 0.296875f},
+ {0.625000f, 0.683594f, 0.382812f, 0.027344f}, {0.546875f, 0.960938f, 0.199219f, 0.523438f},
+ {0.792969f, 0.414062f, 0.964844f, 0.917969f}, {0.269531f, 0.488281f, 0.773438f, 0.308594f},
+ {0.375000f, 0.332031f, 0.312500f, 0.007812f}, {0.519531f, 0.941406f, 0.894531f, 0.570312f},
+ {0.175781f, 0.777344f, 0.226562f, 0.210938f}, {0.558594f, 0.558594f, 0.687500f, 0.324219f},
+ {0.449219f, 0.316406f, 0.078125f, 0.828125f}, {0.656250f, 0.101562f, 0.449219f, 0.164062f},
+ {0.839844f, 0.832031f, 0.250000f, 0.683594f}, {0.914062f, 0.253906f, 0.777344f, 0.554688f},
+ {0.738281f, 0.906250f, 0.144531f, 0.125000f}, {0.550781f, 0.714844f, 0.472656f, 0.945312f},
+ {0.039062f, 0.863281f, 0.695312f, 0.660156f}, {0.140625f, 0.445312f, 0.421875f, 0.453125f},
+ {0.476562f, 0.832031f, 0.796875f, 0.738281f}, {0.980469f, 0.679688f, 0.496094f, 0.101562f},
+ {0.269531f, 0.792969f, 0.121094f, 0.500000f}, {0.160156f, 0.101562f, 0.324219f, 0.152344f},
+ {0.656250f, 0.960938f, 0.820312f, 0.894531f}, {0.226562f, 0.000000f, 0.406250f, 0.640625f},
+ {0.851562f, 0.742188f, 0.156250f, 0.343750f}, {0.136719f, 0.917969f, 0.359375f, 0.425781f},
+ {0.414062f, 0.054688f, 0.492188f, 0.210938f}, {0.613281f, 0.441406f, 0.257812f, 0.300781f},
+ {0.941406f, 0.511719f, 0.449219f, 0.972656f}, {0.699219f, 0.128906f, 0.570312f, 0.652344f},
+ {0.847656f, 0.226562f, 0.281250f, 0.003906f}, {0.128906f, 0.734375f, 0.871094f, 0.375000f},
+ {0.339844f, 0.007812f, 0.535156f, 0.507812f}, {0.726562f, 0.117188f, 0.074219f, 0.894531f},
+ {0.257812f, 0.582031f, 0.933594f, 0.570312f}, {0.593750f, 0.171875f, 0.566406f, 0.250000f},
+ {0.351562f, 0.410156f, 0.484375f, 0.488281f}, {0.117188f, 0.996094f, 0.703125f, 0.761719f},
+ {0.191406f, 0.308594f, 0.843750f, 0.425781f}, {0.992188f, 0.003906f, 0.578125f, 0.609375f},
+ {0.769531f, 0.503906f, 0.164062f, 0.097656f}, {0.105469f, 0.816406f, 0.945312f, 0.460938f},
+ {0.699219f, 0.046875f, 0.109375f, 0.824219f}, {0.421875f, 0.957031f, 0.535156f, 0.007812f},
+ {0.898438f, 0.359375f, 0.312500f, 0.636719f}, {0.281250f, 0.718750f, 0.582031f, 0.964844f},
+ {0.082031f, 0.605469f, 0.863281f, 0.285156f}, {0.847656f, 0.800781f, 0.757812f, 0.070312f},
+ {0.445312f, 0.203125f, 0.125000f, 0.820312f}, {0.980469f, 0.902344f, 0.714844f, 0.562500f},
+ {0.164062f, 0.691406f, 0.921875f, 0.359375f}, {0.734375f, 0.046875f, 0.812500f, 0.144531f},
+ {0.613281f, 0.457031f, 0.480469f, 0.777344f}, {0.359375f, 0.320312f, 0.140625f, 0.089844f},
+ {0.488281f, 0.574219f, 0.886719f, 0.863281f}, {0.152344f, 0.855469f, 0.703125f, 0.636719f},
+ {0.921875f, 0.136719f, 0.421875f, 0.296875f}, {0.011719f, 0.527344f, 0.167969f, 0.710938f},
+ {0.601562f, 0.027344f, 0.742188f, 0.441406f}, {0.328125f, 0.707031f, 0.066406f, 0.882812f},
+ {0.050781f, 0.906250f, 0.875000f, 0.015625f}, {0.246094f, 0.500000f, 0.378906f, 0.339844f},
+ {0.566406f, 0.769531f, 0.117188f, 0.121094f}, {0.179688f, 0.195312f, 0.175781f, 0.386719f},
+ {0.656250f, 0.527344f, 0.988281f, 0.816406f}, {0.882812f, 0.304688f, 0.042969f, 0.449219f},
+ {0.425781f, 0.375000f, 0.601562f, 0.242188f}, {0.929688f, 0.562500f, 0.812500f, 0.617188f},
+ {0.101562f, 0.164062f, 0.261719f, 0.468750f}, {0.644531f, 0.820312f, 0.441406f, 0.718750f},
+ {0.023438f, 0.523438f, 0.632812f, 0.261719f}, {0.898438f, 0.437500f, 0.945312f, 0.953125f},
+ {0.066406f, 0.140625f, 0.109375f, 0.492188f}, {0.281250f, 0.882812f, 0.832031f, 0.902344f},
+ {0.781250f, 0.207031f, 0.292969f, 0.445312f}, {0.148438f, 0.722656f, 0.976562f, 0.089844f},
+ {0.402344f, 0.593750f, 0.523438f, 0.960938f}, {0.351562f, 0.046875f, 0.066406f, 0.871094f},
+ {0.175781f, 0.402344f, 0.316406f, 0.402344f}, {0.640625f, 0.339844f, 0.937500f, 0.046875f},
+ {0.871094f, 0.199219f, 0.589844f, 0.203125f}, {0.414062f, 0.945312f, 0.355469f, 0.316406f},
+ {0.691406f, 0.246094f, 0.277344f, 0.902344f}, {0.539062f, 0.507812f, 0.980469f, 0.566406f},
+ {0.609375f, 0.167969f, 0.214844f, 0.679688f}, {0.781250f, 0.429688f, 0.617188f, 0.820312f},
+ {0.464844f, 0.285156f, 0.875000f, 0.375000f}, {0.101562f, 0.488281f, 0.511719f, 0.019531f},
+ {0.710938f, 0.156250f, 0.691406f, 0.121094f}, {0.363281f, 0.359375f, 0.792969f, 0.578125f},
+ {0.792969f, 0.593750f, 0.046875f, 0.906250f}, {0.476562f, 0.972656f, 0.199219f, 0.089844f},
+ {0.031250f, 0.667969f, 0.824219f, 0.390625f}, {0.242188f, 0.343750f, 0.933594f, 0.480469f},
+ {0.421875f, 0.937500f, 0.339844f, 0.132812f}, {0.191406f, 0.613281f, 0.183594f, 0.750000f},
+ {0.617188f, 0.472656f, 0.800781f, 0.675781f}, {0.867188f, 0.855469f, 0.230469f, 0.203125f},
+ {0.449219f, 0.328125f, 0.660156f, 0.953125f}, {0.964844f, 0.746094f, 0.769531f, 0.828125f},
+ {0.007812f, 0.824219f, 0.179688f, 0.011719f}, {0.503906f, 0.125000f, 0.085938f, 0.531250f},
+ {0.421875f, 0.777344f, 0.433594f, 0.199219f}, {0.660156f, 0.710938f, 0.027344f, 0.679688f},
+ {0.261719f, 0.941406f, 0.347656f, 0.257812f}, {0.527344f, 0.386719f, 0.492188f, 0.351562f},
+ {0.843750f, 0.660156f, 0.671875f, 0.179688f}, {0.195312f, 0.195312f, 0.246094f, 0.578125f},
+ {0.062500f, 0.539062f, 0.828125f, 0.429688f}, {0.519531f, 0.847656f, 0.156250f, 0.363281f},
+ {0.730469f, 0.156250f, 0.472656f, 0.855469f}, {0.789062f, 0.941406f, 0.210938f, 0.527344f},
+ {0.250000f, 0.445312f, 0.960938f, 0.218750f}, {0.671875f, 0.078125f, 0.320312f, 0.753906f},
+ {0.500000f, 0.378906f, 0.417969f, 0.015625f}, {0.222656f, 0.988281f, 0.066406f, 0.949219f},
+ {0.828125f, 0.164062f, 0.285156f, 0.453125f}, {0.031250f, 0.222656f, 0.761719f, 0.589844f},
+ {0.878906f, 0.800781f, 0.042969f, 0.691406f}, {0.308594f, 0.351562f, 0.460938f, 0.027344f},
+ {0.789062f, 0.417969f, 0.656250f, 0.160156f}, {0.726562f, 0.285156f, 0.972656f, 0.941406f},
+ {0.859375f, 0.207031f, 0.597656f, 0.796875f}, {0.535156f, 0.839844f, 0.496094f, 0.621094f},
+ {0.941406f, 0.343750f, 0.445312f, 0.285156f}, {0.097656f, 0.164062f, 0.949219f, 0.914062f},
+ {0.687500f, 0.421875f, 0.789062f, 0.492188f}, {0.453125f, 0.871094f, 0.675781f, 0.214844f},
+ {0.035156f, 0.710938f, 0.289062f, 0.078125f}, {0.781250f, 0.941406f, 0.542969f, 0.703125f},
+ {0.207031f, 0.777344f, 0.101562f, 0.867188f}, {0.152344f, 0.089844f, 0.339844f, 0.984375f},
+ {0.480469f, 0.257812f, 0.707031f, 0.371094f}, {0.843750f, 0.722656f, 0.070312f, 0.835938f},
+ {0.230469f, 0.199219f, 0.750000f, 0.417969f}, {0.417969f, 0.054688f, 0.542969f, 0.773438f},
+ {0.617188f, 0.632812f, 0.375000f, 0.070312f}, {0.710938f, 0.386719f, 0.578125f, 0.613281f},
+ {0.921875f, 0.500000f, 0.652344f, 0.281250f}, {0.246094f, 0.921875f, 0.164062f, 0.644531f},
+ {0.687500f, 0.445312f, 0.890625f, 0.218750f}, {0.023438f, 0.789062f, 0.718750f, 0.476562f},
+ {0.996094f, 0.523438f, 0.820312f, 0.269531f}, {0.507812f, 0.117188f, 0.234375f, 0.710938f},
+ {0.253906f, 0.628906f, 0.105469f, 0.531250f}, {0.824219f, 0.574219f, 0.886719f, 0.800781f},
+ {0.070312f, 0.316406f, 0.050781f, 0.164062f}, {0.199219f, 0.039062f, 0.664062f, 0.964844f},
+ {0.867188f, 0.652344f, 0.769531f, 0.277344f}, {0.023438f, 0.867188f, 0.078125f, 0.222656f},
+ {0.335938f, 0.769531f, 0.960938f, 0.535156f}, {0.898438f, 0.535156f, 0.015625f, 0.996094f},
+ {0.585938f, 0.890625f, 0.269531f, 0.691406f}, {0.054688f, 0.644531f, 0.925781f, 0.175781f},
+ {0.980469f, 0.261719f, 0.585938f, 0.511719f}, {0.285156f, 0.789062f, 0.667969f, 0.742188f},
+ {0.113281f, 0.023438f, 0.402344f, 0.859375f}, {0.578125f, 0.417969f, 0.066406f, 0.230469f},
+ {0.800781f, 0.816406f, 0.753906f, 0.921875f}, {0.992188f, 0.164062f, 0.492188f, 0.816406f},
+ {0.519531f, 0.281250f, 0.414062f, 0.289062f}, {0.085938f, 0.675781f, 0.968750f, 0.449219f},
+ {0.167969f, 0.964844f, 0.046875f, 0.347656f}, {0.671875f, 0.035156f, 0.347656f, 0.113281f},
+ {0.761719f, 0.257812f, 0.277344f, 0.714844f}, {0.300781f, 0.457031f, 0.925781f, 0.316406f},
+ {0.578125f, 0.605469f, 0.617188f, 0.984375f}, {0.875000f, 0.082031f, 0.789062f, 0.851562f},
+ {0.156250f, 0.437500f, 0.265625f, 0.558594f}, {0.453125f, 0.253906f, 0.738281f, 0.898438f},
+ {0.968750f, 0.761719f, 0.882812f, 0.703125f}, {0.312500f, 0.480469f, 0.406250f, 0.949219f},
+ {0.679688f, 0.097656f, 0.031250f, 0.773438f}, {0.589844f, 0.308594f, 0.996094f, 0.125000f},
+ {0.375000f, 0.679688f, 0.691406f, 0.675781f}, {0.128906f, 0.000000f, 0.375000f, 0.929688f},
+ {0.562500f, 0.753906f, 0.570312f, 0.421875f}, {0.050781f, 0.562500f, 0.003906f, 0.304688f},
+ {0.386719f, 0.250000f, 0.531250f, 0.648438f}, {0.937500f, 0.781250f, 0.621094f, 0.843750f},
+ {0.437500f, 0.636719f, 0.953125f, 0.515625f}, {0.695312f, 0.515625f, 0.214844f, 0.242188f},
+ {0.253906f, 0.949219f, 0.562500f, 0.910156f}, {0.636719f, 0.097656f, 0.296875f, 0.406250f},
+ {0.453125f, 0.746094f, 0.109375f, 0.566406f}, {0.121094f, 0.917969f, 0.832031f, 0.480469f},
+ {0.269531f, 0.632812f, 0.207031f, 0.105469f}, {0.183594f, 0.449219f, 0.281250f, 0.179688f},
+ {0.746094f, 0.675781f, 0.031250f, 0.691406f}, {0.402344f, 0.113281f, 0.558594f, 0.574219f},
+ {0.894531f, 0.613281f, 0.238281f, 0.839844f}, {0.277344f, 0.277344f, 0.351562f, 0.964844f},
+ {0.976562f, 0.074219f, 0.832031f, 0.535156f}, {0.332031f, 0.472656f, 0.464844f, 0.335938f},
+ {0.738281f, 0.597656f, 0.882812f, 0.171875f}, {0.601562f, 0.855469f, 0.937500f, 0.125000f},
+ {0.292969f, 0.648438f, 0.500000f, 0.058594f}, {0.687500f, 0.996094f, 0.175781f, 0.660156f},
+ {0.984375f, 0.582031f, 0.820312f, 0.527344f}, {0.757812f, 0.761719f, 0.253906f, 0.339844f},
+ {0.488281f, 0.843750f, 0.472656f, 0.128906f}, {0.324219f, 0.265625f, 0.007812f, 0.726562f},
+ {0.085938f, 0.023438f, 0.792969f, 0.386719f}, {0.519531f, 0.664062f, 0.414062f, 0.789062f},
+ {0.578125f, 0.175781f, 0.351562f, 0.015625f}, {0.792969f, 0.292969f, 0.035156f, 0.585938f},
+ {0.308594f, 0.992188f, 0.441406f, 0.769531f}, {0.105469f, 0.683594f, 0.648438f, 0.988281f},
+ {0.765625f, 0.804688f, 0.519531f, 0.093750f}, {0.371094f, 0.074219f, 0.734375f, 0.621094f},
+ {0.929688f, 0.746094f, 0.156250f, 0.359375f}, {0.296875f, 0.964844f, 0.546875f, 0.011719f},
+ {0.722656f, 0.554688f, 0.453125f, 0.414062f}, {0.402344f, 0.347656f, 0.371094f, 0.761719f},
+ {0.964844f, 0.207031f, 0.187500f, 0.078125f}, {0.511719f, 0.074219f, 0.558594f, 0.476562f},
+ {0.257812f, 0.808594f, 0.433594f, 0.781250f}, {0.191406f, 0.410156f, 0.746094f, 0.839844f},
+ {0.750000f, 0.109375f, 0.117188f, 0.281250f}, {0.531250f, 0.195312f, 0.312500f, 0.031250f},
+ {0.859375f, 0.562500f, 0.976562f, 0.570312f}, {0.664062f, 0.703125f, 0.148438f, 0.320312f},
+ {0.363281f, 0.078125f, 0.687500f, 0.613281f}, {0.062500f, 0.531250f, 0.593750f, 0.082031f},
+ {0.703125f, 0.886719f, 0.105469f, 0.539062f}, {0.316406f, 0.382812f, 0.632812f, 0.035156f},
+ {0.390625f, 0.218750f, 0.453125f, 0.644531f}, {0.835938f, 0.562500f, 0.718750f, 0.582031f},
+ {0.214844f, 0.660156f, 0.546875f, 0.886719f}, {0.933594f, 0.359375f, 0.875000f, 0.160156f},
+ {0.089844f, 0.890625f, 0.218750f, 0.378906f}, {0.730469f, 0.210938f, 0.519531f, 0.062500f},
+ {0.359375f, 0.558594f, 0.972656f, 0.480469f}, {0.621094f, 0.324219f, 0.074219f, 0.136719f},
+ {0.042969f, 0.871094f, 0.191406f, 0.304688f}, {0.761719f, 0.589844f, 0.449219f, 0.050781f},
+ {0.476562f, 0.914062f, 0.750000f, 0.253906f}, {0.929688f, 0.414062f, 0.621094f, 0.476562f},
+ {0.218750f, 0.234375f, 0.269531f, 0.195312f}, {0.867188f, 0.519531f, 0.082031f, 0.042969f},
+ {0.320312f, 0.648438f, 0.773438f, 0.613281f}, {0.898438f, 0.328125f, 0.882812f, 0.882812f},
+ {0.769531f, 0.882812f, 0.175781f, 0.113281f}, {0.093750f, 0.109375f, 0.828125f, 0.183594f},
+ {0.566406f, 0.406250f, 0.687500f, 0.378906f}, {0.179688f, 0.714844f, 0.394531f, 0.054688f},
+ {0.984375f, 0.042969f, 0.863281f, 0.316406f}, {0.066406f, 0.671875f, 0.937500f, 0.824219f},
+ {0.574219f, 0.183594f, 0.351562f, 0.757812f}, {0.371094f, 0.570312f, 0.531250f, 0.347656f},
+ {0.675781f, 0.070312f, 0.718750f, 0.261719f}, {0.480469f, 0.949219f, 0.902344f, 0.976562f},
+ {0.808594f, 0.250000f, 0.648438f, 0.398438f}, {0.343750f, 0.539062f, 0.761719f, 0.054688f},
+ {0.601562f, 0.984375f, 0.082031f, 0.152344f}, {0.828125f, 0.828125f, 0.917969f, 0.730469f},
+ {0.121094f, 0.355469f, 0.625000f, 0.636719f}, {0.554688f, 0.226562f, 0.148438f, 0.406250f},
+ {0.398438f, 0.148438f, 0.222656f, 0.792969f}, {0.945312f, 0.429688f, 0.664062f, 0.562500f},
+ {0.082031f, 0.015625f, 0.410156f, 0.753906f}, {0.351562f, 0.367188f, 0.039062f, 0.187500f},
+ {0.562500f, 0.121094f, 0.359375f, 0.238281f}, {0.191406f, 0.308594f, 0.992188f, 0.886719f},
+ {0.128906f, 0.703125f, 0.144531f, 0.988281f}, {0.812500f, 0.539062f, 0.707031f, 0.558594f},
+ {0.968750f, 0.968750f, 0.933594f, 0.179688f}, {0.429688f, 0.335938f, 0.214844f, 0.929688f},
+ {0.195312f, 0.753906f, 0.554688f, 0.859375f}, {0.902344f, 0.867188f, 0.613281f, 0.363281f},
+ {0.468750f, 0.031250f, 0.960938f, 0.152344f}, {0.613281f, 0.234375f, 0.183594f, 0.304688f},
+ {0.210938f, 0.417969f, 0.292969f, 0.429688f}, {0.570312f, 0.476562f, 0.855469f, 0.882812f},
+ {0.652344f, 0.828125f, 0.406250f, 0.480469f}, {0.453125f, 0.386719f, 0.941406f, 0.722656f},
+ {0.085938f, 0.117188f, 0.246094f, 0.585938f}, {0.558594f, 0.710938f, 0.730469f, 0.933594f},
+ {0.140625f, 0.609375f, 0.804688f, 0.632812f}, {0.828125f, 0.996094f, 0.652344f, 0.320312f},
+ {0.687500f, 0.312500f, 0.335938f, 0.234375f}, {0.441406f, 0.472656f, 0.222656f, 0.402344f},
+ {0.632812f, 0.730469f, 0.890625f, 0.937500f}, {0.332031f, 0.871094f, 0.531250f, 0.675781f},
+ {0.164062f, 0.304688f, 0.464844f, 0.445312f}, {0.906250f, 0.914062f, 0.851562f, 0.160156f},
+ {0.460938f, 0.238281f, 0.246094f, 0.722656f}, {0.273438f, 0.753906f, 0.917969f, 0.398438f},
+ {0.777344f, 0.046875f, 0.304688f, 0.992188f}, {0.941406f, 0.496094f, 0.863281f, 0.847656f},
+ {0.554688f, 0.781250f, 0.144531f, 0.179688f}, {0.050781f, 0.097656f, 0.816406f, 0.406250f},
+ {0.621094f, 0.925781f, 0.003906f, 0.789062f}, {0.468750f, 0.515625f, 0.406250f, 0.273438f},
+ {0.820312f, 0.156250f, 0.679688f, 0.621094f}, {0.027344f, 0.691406f, 0.140625f, 0.734375f},
+ {0.234375f, 0.828125f, 0.382812f, 0.808594f}, {0.890625f, 0.054688f, 0.640625f, 0.410156f},
+ {0.398438f, 0.144531f, 0.582031f, 0.652344f}, {0.117188f, 0.722656f, 0.804688f, 0.519531f},
+ {0.265625f, 0.035156f, 0.132812f, 0.835938f}, {0.824219f, 0.781250f, 0.335938f, 0.589844f},
+ {0.015625f, 0.972656f, 0.503906f, 0.324219f}, {0.644531f, 0.367188f, 0.843750f, 0.792969f},
+ {0.460938f, 0.839844f, 0.656250f, 0.375000f}, {0.707031f, 0.179688f, 0.445312f, 0.496094f},
+ {0.148438f, 0.484375f, 0.253906f, 0.269531f}, {0.292969f, 0.585938f, 0.347656f, 0.710938f},
+ {0.800781f, 0.292969f, 0.101562f, 0.792969f}, {0.343750f, 0.847656f, 0.503906f, 0.992188f},
+ {0.511719f, 0.453125f, 0.160156f, 0.542969f}, {0.843750f, 0.261719f, 0.628906f, 0.207031f},
+ {0.214844f, 0.878906f, 0.777344f, 0.082031f}, {0.957031f, 0.492188f, 0.054688f, 0.855469f},
+ {0.890625f, 0.382812f, 0.136719f, 0.656250f}, {0.019531f, 0.804688f, 0.328125f, 0.519531f},
+ {0.636719f, 0.042969f, 0.402344f, 0.753906f}, {0.148438f, 0.753906f, 0.179688f, 0.449219f},
+ {0.046875f, 0.398438f, 0.507812f, 0.320312f}, {0.511719f, 0.019531f, 0.429688f, 0.253906f},
+ {0.222656f, 0.660156f, 0.003906f, 0.003906f}, {0.707031f, 0.910156f, 0.726562f, 0.933594f},
+ {0.011719f, 0.742188f, 0.781250f, 0.281250f}, {0.863281f, 0.316406f, 0.281250f, 0.445312f},
+ {0.515625f, 0.496094f, 0.570312f, 0.910156f}, {0.785156f, 0.875000f, 0.867188f, 0.605469f},
+ {0.042969f, 0.230469f, 0.207031f, 0.824219f}, {0.667969f, 0.468750f, 0.605469f, 0.472656f},
+ {0.878906f, 0.906250f, 0.316406f, 0.046875f}, {0.382812f, 0.164062f, 0.765625f, 0.671875f},
+ {0.015625f, 0.093750f, 0.070312f, 0.312500f}, {0.640625f, 0.425781f, 0.277344f, 0.457031f},
+ {0.847656f, 0.613281f, 0.859375f, 0.113281f}, {0.062500f, 0.128906f, 0.128906f, 0.691406f},
+ {0.726562f, 0.558594f, 0.761719f, 0.503906f}, {0.398438f, 0.355469f, 0.382812f, 0.917969f},
+ {0.886719f, 0.925781f, 0.000000f, 0.667969f}, {0.000000f, 0.148438f, 0.792969f, 0.062500f},
+ {0.156250f, 0.277344f, 0.597656f, 0.242188f}, {0.808594f, 0.191406f, 0.316406f, 0.855469f},
+ {0.945312f, 0.910156f, 0.042969f, 0.117188f}, {0.226562f, 0.453125f, 0.914062f, 0.191406f},
+ {0.761719f, 0.250000f, 0.109375f, 0.441406f}, {0.308594f, 0.015625f, 0.480469f, 0.882812f},
+ {0.015625f, 0.671875f, 0.847656f, 0.132812f}, {0.878906f, 0.144531f, 0.074219f, 0.605469f},
+ {0.933594f, 0.945312f, 0.613281f, 0.074219f}, {0.074219f, 0.503906f, 0.777344f, 0.359375f},
+ {0.406250f, 0.378906f, 0.050781f, 0.796875f}, {0.718750f, 0.605469f, 0.367188f, 0.886719f},
+ {0.003906f, 0.449219f, 0.554688f, 0.500000f}, {0.218750f, 0.988281f, 0.015625f, 0.218750f},
+ {0.640625f, 0.636719f, 0.730469f, 0.769531f}, {0.117188f, 0.144531f, 0.375000f, 0.269531f},
+ {0.429688f, 0.429688f, 0.250000f, 0.691406f}, {0.902344f, 0.839844f, 0.488281f, 0.957031f},
+ {0.261719f, 0.316406f, 0.949219f, 0.460938f}, {0.339844f, 0.738281f, 0.304688f, 0.085938f},
+ {0.531250f, 0.015625f, 0.101562f, 0.507812f}, {0.691406f, 0.984375f, 0.832031f, 0.941406f},
+ {0.945312f, 0.378906f, 0.890625f, 0.015625f}, {0.562500f, 0.628906f, 0.324219f, 0.203125f},
+ {0.796875f, 0.953125f, 0.011719f, 0.921875f}, {0.656250f, 0.285156f, 0.953125f, 0.730469f},
+ {0.167969f, 0.183594f, 0.542969f, 0.085938f}, {0.542969f, 0.468750f, 0.906250f, 0.890625f},
+ {0.410156f, 0.617188f, 0.046875f, 0.695312f}, {0.996094f, 0.128906f, 0.199219f, 0.972656f},
+ {0.191406f, 0.050781f, 0.945312f, 0.148438f}, {0.511719f, 0.937500f, 0.117188f, 0.738281f},
+ {0.613281f, 0.734375f, 0.722656f, 0.910156f}, {0.921875f, 0.019531f, 0.988281f, 0.429688f},
+ {0.652344f, 0.972656f, 0.601562f, 0.601562f}, {0.003906f, 0.136719f, 0.746094f, 0.664062f},
+ {0.722656f, 0.359375f, 0.011719f, 0.148438f}, {0.402344f, 0.609375f, 0.257812f, 0.718750f},
+ {0.765625f, 0.785156f, 0.414062f, 0.437500f}, {0.082031f, 0.296875f, 0.480469f, 0.605469f},
+ {0.542969f, 0.144531f, 0.996094f, 0.011719f}, {0.312500f, 0.699219f, 0.589844f, 0.882812f},
+ {0.242188f, 0.328125f, 0.859375f, 0.222656f}, {0.968750f, 0.593750f, 0.699219f, 0.804688f},
+ {0.425781f, 0.156250f, 0.964844f, 0.902344f}, {0.753906f, 0.492188f, 0.296875f, 0.605469f},
+ {0.917969f, 0.792969f, 0.582031f, 0.472656f}, {0.468750f, 0.546875f, 0.382812f, 0.847656f},
+ {0.632812f, 0.058594f, 0.074219f, 0.066406f}, {0.261719f, 0.937500f, 0.968750f, 0.683594f},
+ {0.160156f, 0.687500f, 0.125000f, 0.320312f}, {0.441406f, 0.781250f, 0.648438f, 0.019531f},
+ {0.320312f, 0.972656f, 0.023438f, 0.710938f}, {0.937500f, 0.070312f, 0.429688f, 0.164062f},
+ {0.273438f, 0.406250f, 0.886719f, 0.414062f}, {0.585938f, 0.789062f, 0.511719f, 0.804688f},
+ {0.234375f, 0.574219f, 0.636719f, 0.230469f}, {0.750000f, 0.832031f, 0.460938f, 0.531250f},
+ {0.355469f, 0.250000f, 0.695312f, 0.750000f}, {0.281250f, 0.480469f, 0.328125f, 0.250000f},
+ {0.132812f, 0.726562f, 0.500000f, 0.035156f}, {0.671875f, 0.886719f, 0.917969f, 0.601562f},
+ {0.972656f, 0.621094f, 0.664062f, 0.199219f}, {0.328125f, 0.699219f, 0.472656f, 0.789062f},
+ {0.511719f, 0.519531f, 0.121094f, 0.519531f}, {0.695312f, 0.593750f, 0.699219f, 0.300781f},
+ {0.351562f, 0.054688f, 0.503906f, 0.683594f}, {0.621094f, 0.757812f, 0.628906f, 0.351562f},
+ {0.484375f, 0.882812f, 0.285156f, 0.808594f}, {0.660156f, 0.394531f, 0.152344f, 0.046875f},
+ {0.386719f, 0.574219f, 0.992188f, 0.660156f}, {0.121094f, 0.824219f, 0.691406f, 0.738281f},
+ {0.242188f, 0.234375f, 0.410156f, 0.531250f}, {0.601562f, 0.031250f, 0.171875f, 0.191406f},
+ {0.773438f, 0.085938f, 0.277344f, 0.960938f}, {0.507812f, 0.839844f, 0.656250f, 0.113281f},
+ {0.968750f, 0.179688f, 0.812500f, 0.023438f}, {0.566406f, 0.351562f, 0.203125f, 0.632812f},
+ {0.878906f, 0.289062f, 0.515625f, 0.343750f}, {0.484375f, 0.710938f, 0.996094f, 0.121094f},
+ {0.183594f, 0.957031f, 0.589844f, 0.519531f}, {0.734375f, 0.191406f, 0.187500f, 0.042969f},
+ {0.804688f, 0.621094f, 0.644531f, 0.222656f}, {0.148438f, 0.269531f, 0.757812f, 0.898438f},
+ {0.406250f, 0.480469f, 0.574219f, 0.664062f}, {0.109375f, 0.789062f, 0.457031f, 0.328125f},
+ {0.296875f, 0.234375f, 0.718750f, 0.246094f}, {0.191406f, 0.523438f, 0.500000f, 0.570312f},
+ {0.500000f, 0.449219f, 0.281250f, 0.351562f}, {0.324219f, 0.347656f, 0.218750f, 0.160156f},
+ {0.953125f, 0.683594f, 0.378906f, 0.441406f}, {0.710938f, 0.539062f, 0.703125f, 0.382812f},
+ {0.097656f, 0.886719f, 0.425781f, 0.003906f}, {0.347656f, 0.281250f, 0.296875f, 0.546875f},
+ {0.761719f, 0.695312f, 0.554688f, 0.246094f}, {0.039062f, 0.433594f, 0.386719f, 0.078125f},
+ {0.253906f, 0.230469f, 0.496094f, 0.566406f}, {0.378906f, 0.804688f, 0.058594f, 0.023438f},
+ {0.449219f, 0.648438f, 0.304688f, 0.335938f}, {0.875000f, 0.199219f, 0.437500f, 0.101562f},
+ {0.136719f, 0.917969f, 0.917969f, 0.476562f}, {0.285156f, 0.539062f, 0.847656f, 0.902344f},
+ {0.617188f, 0.003906f, 0.703125f, 0.250000f}, {0.167969f, 0.996094f, 0.210938f, 0.953125f},
+ {0.429688f, 0.437500f, 0.800781f, 0.308594f}, {0.738281f, 0.847656f, 0.265625f, 0.140625f},
+ {0.847656f, 0.210938f, 0.019531f, 0.566406f}, {0.558594f, 0.929688f, 0.125000f, 0.085938f},
+ {0.660156f, 0.878906f, 0.808594f, 0.363281f}, {0.179688f, 0.289062f, 0.203125f, 0.671875f},
+ {0.308594f, 0.203125f, 0.851562f, 0.117188f}, {0.367188f, 0.414062f, 0.902344f, 0.746094f},
+ {0.101562f, 0.621094f, 0.527344f, 0.210938f}, {0.804688f, 0.265625f, 0.332031f, 0.500000f},
+ {0.914062f, 0.175781f, 0.464844f, 0.960938f}, {0.726562f, 0.535156f, 0.734375f, 0.378906f},
+ {0.628906f, 0.656250f, 0.539062f, 0.628906f}, {0.074219f, 0.601562f, 0.804688f, 0.273438f},
+ {0.453125f, 0.347656f, 0.109375f, 0.578125f}, {0.531250f, 0.210938f, 0.378906f, 0.867188f},
+ {0.699219f, 0.683594f, 0.175781f, 0.085938f}, {0.156250f, 0.050781f, 0.832031f, 0.972656f},
+ {0.492188f, 0.945312f, 0.972656f, 0.625000f}, {0.953125f, 0.382812f, 0.085938f, 0.820312f},
+ {0.550781f, 0.199219f, 0.253906f, 0.417969f}, {0.246094f, 0.082031f, 0.566406f, 0.847656f},
+ {0.449219f, 0.308594f, 0.070312f, 0.371094f}, {0.785156f, 0.003906f, 0.234375f, 0.132812f},
+ {0.097656f, 0.984375f, 0.984375f, 0.746094f}, {0.269531f, 0.847656f, 0.187500f, 0.980469f},
+ {0.871094f, 0.656250f, 0.824219f, 0.031250f}, {0.039062f, 0.296875f, 0.398438f, 0.550781f},
+ {0.187500f, 0.503906f, 0.882812f, 0.917969f}, {0.992188f, 0.179688f, 0.589844f, 0.500000f},
+ {0.789062f, 0.718750f, 0.363281f, 0.289062f}, {0.558594f, 0.332031f, 0.007812f, 0.980469f},
+ {0.464844f, 0.531250f, 0.507812f, 0.460938f}, {0.824219f, 0.640625f, 0.902344f, 0.253906f},
+ {0.203125f, 0.781250f, 0.722656f, 0.593750f}, {0.304688f, 0.687500f, 0.960938f, 0.308594f},
+ {0.136719f, 0.117188f, 0.125000f, 0.707031f}, {0.839844f, 0.550781f, 0.410156f, 0.917969f},
+ {0.351562f, 0.808594f, 0.769531f, 0.468750f}, {0.289062f, 0.000000f, 0.074219f, 0.863281f},
+ {0.667969f, 0.582031f, 0.691406f, 0.597656f}, {0.015625f, 0.375000f, 0.117188f, 0.371094f},
+ {0.578125f, 0.054688f, 0.902344f, 0.765625f}, {0.957031f, 0.882812f, 0.351562f, 0.558594f},
+ {0.644531f, 0.417969f, 0.058594f, 0.128906f}, {0.847656f, 0.664062f, 0.238281f, 0.429688f},
+ {0.464844f, 0.070312f, 0.171875f, 0.773438f}, {0.746094f, 0.917969f, 0.929688f, 0.855469f},
+ {0.000000f, 0.109375f, 0.777344f, 0.613281f}, {0.867188f, 0.851562f, 0.660156f, 0.996094f},
+ {0.609375f, 0.796875f, 0.851562f, 0.273438f}, {0.445312f, 0.222656f, 0.160156f, 0.777344f},
+ {0.808594f, 0.078125f, 0.597656f, 0.199219f}, {0.277344f, 0.394531f, 0.800781f, 0.636719f},
+ {0.582031f, 0.824219f, 0.753906f, 0.464844f}, {0.945312f, 0.511719f, 0.632812f, 0.851562f},
+ {0.835938f, 0.316406f, 0.226562f, 0.941406f}, {0.082031f, 0.554688f, 0.863281f, 0.210938f},
+ {0.546875f, 0.378906f, 0.785156f, 0.812500f}, {0.222656f, 0.468750f, 0.191406f, 0.289062f},
+ {0.953125f, 0.753906f, 0.535156f, 0.843750f}, {0.484375f, 0.089844f, 0.652344f, 0.367188f},
+ {0.828125f, 0.226562f, 0.089844f, 0.042969f}, {0.687500f, 0.722656f, 0.566406f, 0.746094f},
+ {0.937500f, 0.640625f, 0.375000f, 0.488281f}, {0.496094f, 0.105469f, 0.675781f, 0.386719f},
+ {0.113281f, 0.527344f, 0.460938f, 0.699219f}, {0.375000f, 0.453125f, 0.546875f, 0.945312f},
+ {0.878906f, 0.679688f, 0.343750f, 0.511719f}, {0.070312f, 0.085938f, 0.644531f, 0.179688f},
+ {0.820312f, 0.718750f, 0.480469f, 0.996094f}, {0.992188f, 0.957031f, 0.160156f, 0.390625f},
+ {0.683594f, 0.121094f, 0.695312f, 0.582031f}, {0.582031f, 0.824219f, 0.242188f, 0.148438f},
+ {0.203125f, 0.382812f, 0.835938f, 0.867188f}, {0.386719f, 0.042969f, 0.925781f, 0.105469f},
+ {0.832031f, 0.285156f, 0.296875f, 0.792969f}, {0.152344f, 0.738281f, 0.671875f, 0.945312f},
+ {0.765625f, 0.855469f, 0.234375f, 0.347656f}, {0.855469f, 0.511719f, 0.914062f, 0.734375f},
+ {0.101562f, 0.917969f, 0.582031f, 0.000000f}, {0.917969f, 0.316406f, 0.019531f, 0.394531f},
+ {0.804688f, 0.636719f, 0.410156f, 0.328125f}, {0.601562f, 0.765625f, 0.199219f, 0.171875f},
+ {0.027344f, 0.515625f, 0.800781f, 0.949219f}, {0.761719f, 0.835938f, 0.890625f, 0.285156f},
+ {0.183594f, 0.429688f, 0.734375f, 0.554688f}, {0.855469f, 0.773438f, 0.433594f, 0.925781f},
+ {0.593750f, 0.222656f, 0.871094f, 0.457031f}, {0.402344f, 0.351562f, 0.351562f, 0.625000f},
+ {0.917969f, 0.414062f, 0.554688f, 0.402344f}, {0.539062f, 0.136719f, 0.023438f, 0.257812f},
+ {0.433594f, 0.792969f, 0.718750f, 0.757812f}, {0.082031f, 0.960938f, 0.210938f, 0.160156f},
+ {0.281250f, 0.097656f, 0.789062f, 0.378906f}, {0.714844f, 0.863281f, 0.304688f, 0.859375f},
+ {0.343750f, 0.433594f, 0.828125f, 0.000000f}, {0.953125f, 0.976562f, 0.226562f, 0.769531f},
+ {0.042969f, 0.273438f, 0.566406f, 0.843750f}, {0.691406f, 0.402344f, 0.335938f, 0.425781f},
+ {0.394531f, 0.937500f, 0.476562f, 0.550781f}, {0.613281f, 0.476562f, 0.636719f, 0.808594f},
+ {0.093750f, 0.878906f, 0.890625f, 0.167969f}, {0.789062f, 0.234375f, 0.324219f, 0.066406f},
+ {0.980469f, 0.511719f, 0.441406f, 0.933594f}, {0.382812f, 0.675781f, 0.796875f, 0.710938f},
+ {0.500000f, 0.765625f, 0.273438f, 0.312500f}, {0.078125f, 0.125000f, 0.527344f, 0.839844f},
+ {0.757812f, 0.554688f, 0.980469f, 0.187500f}, {0.246094f, 0.332031f, 0.816406f, 0.960938f},
+ {0.589844f, 0.167969f, 0.421875f, 0.687500f}, {0.984375f, 0.582031f, 0.609375f, 0.074219f},
+ {0.089844f, 0.746094f, 0.097656f, 0.472656f}, {0.375000f, 0.406250f, 0.046875f, 0.117188f},
+ {0.238281f, 0.023438f, 0.468750f, 0.664062f}, {0.042969f, 0.570312f, 0.984375f, 0.527344f},
+ {0.894531f, 0.988281f, 0.097656f, 0.917969f}, {0.679688f, 0.750000f, 0.882812f, 0.824219f},
+ {0.121094f, 0.156250f, 0.015625f, 0.296875f}, {0.417969f, 0.601562f, 0.152344f, 0.675781f},
+ {0.714844f, 0.062500f, 0.925781f, 0.367188f}, {0.187500f, 0.878906f, 0.679688f, 0.515625f},
+ {0.789062f, 0.097656f, 0.574219f, 0.632812f}, {0.671875f, 0.683594f, 0.132812f, 0.968750f},
+ {0.593750f, 0.828125f, 0.363281f, 0.695312f}, {0.332031f, 0.324219f, 0.281250f, 0.535156f},
+ {0.058594f, 0.406250f, 0.957031f, 0.585938f}, {0.250000f, 0.871094f, 0.164062f, 0.800781f},
+ {0.355469f, 0.574219f, 0.894531f, 0.187500f}, {0.042969f, 0.359375f, 0.070312f, 0.625000f},
+ {0.207031f, 0.265625f, 0.949219f, 0.839844f}, {0.703125f, 0.031250f, 0.746094f, 0.039062f},
+ {0.273438f, 0.609375f, 0.242188f, 0.246094f}, {0.601562f, 0.371094f, 0.093750f, 0.781250f},
+ {0.535156f, 0.859375f, 0.765625f, 0.542969f}, {0.140625f, 0.324219f, 0.035156f, 0.292969f},
+ {0.425781f, 0.476562f, 0.605469f, 0.812500f}, {0.292969f, 0.585938f, 0.417969f, 0.660156f},
+ {0.023438f, 0.890625f, 0.066406f, 0.246094f}, {0.542969f, 0.445312f, 0.183594f, 0.539062f},
+ {0.484375f, 0.152344f, 0.976562f, 0.027344f}, {0.226562f, 0.953125f, 0.480469f, 0.488281f},
+ {0.988281f, 0.003906f, 0.054688f, 0.128906f}, {0.339844f, 0.125000f, 0.703125f, 0.648438f},
+ {0.406250f, 0.265625f, 0.281250f, 0.511719f}, {0.203125f, 0.453125f, 0.746094f, 0.890625f},
+ {0.308594f, 0.164062f, 0.535156f, 0.105469f}, {0.425781f, 0.023438f, 0.679688f, 0.574219f},
+ {0.871094f, 0.976562f, 0.609375f, 0.718750f}, {0.371094f, 0.664062f, 0.367188f, 0.078125f},
+ {0.531250f, 0.140625f, 0.160156f, 0.660156f}, {0.050781f, 0.570312f, 0.289062f, 0.007812f},
+ {0.710938f, 0.488281f, 0.636719f, 0.332031f}, {0.214844f, 0.089844f, 0.773438f, 0.207031f},
+ {0.132812f, 0.937500f, 0.097656f, 0.871094f}, {0.746094f, 0.554688f, 0.257812f, 0.097656f},
+ {0.832031f, 0.039062f, 0.964844f, 0.601562f}, {0.597656f, 0.625000f, 0.464844f, 0.703125f},
+ {0.898438f, 0.371094f, 0.539062f, 0.218750f}, {0.160156f, 0.207031f, 0.132812f, 0.574219f},
+ {0.515625f, 0.050781f, 0.937500f, 0.121094f}, {0.089844f, 0.734375f, 0.449219f, 0.343750f},
+ {0.640625f, 0.156250f, 0.093750f, 0.671875f}, {0.894531f, 0.578125f, 0.039062f, 0.058594f},
+ {0.449219f, 0.218750f, 0.847656f, 0.226562f}, {0.753906f, 0.726562f, 0.175781f, 0.382812f},
+ {0.035156f, 0.082031f, 0.261719f, 0.281250f}, {0.542969f, 0.328125f, 0.023438f, 0.652344f},
+ {0.234375f, 0.910156f, 0.562500f, 0.433594f}, {0.707031f, 0.449219f, 0.855469f, 0.242188f},
+ {0.312500f, 0.941406f, 0.394531f, 0.003906f}, {0.203125f, 0.218750f, 0.035156f, 0.625000f},
+ {0.917969f, 0.835938f, 0.628906f, 0.492188f}, {0.363281f, 0.972656f, 0.699219f, 0.382812f},
+ {0.156250f, 0.710938f, 0.125000f, 0.035156f}, {0.425781f, 0.265625f, 0.367188f, 0.535156f},
+ {0.667969f, 0.875000f, 0.535156f, 0.300781f}, {0.527344f, 0.640625f, 0.742188f, 0.753906f},
+ {0.769531f, 0.148438f, 0.328125f, 0.871094f}, {0.152344f, 0.484375f, 0.230469f, 0.046875f},
+ {0.488281f, 0.332031f, 0.511719f, 0.339844f}, {0.214844f, 0.656250f, 0.265625f, 0.105469f},
+ {0.539062f, 0.906250f, 0.363281f, 0.417969f}, {0.878906f, 0.207031f, 0.464844f, 0.167969f},
+ {0.304688f, 0.957031f, 0.324219f, 0.769531f}, {0.496094f, 0.726562f, 0.039062f, 0.117188f},
+ {0.980469f, 0.273438f, 0.406250f, 0.453125f}, {0.031250f, 0.167969f, 0.976562f, 0.058594f},
+ {0.414062f, 0.585938f, 0.804688f, 0.156250f}, {0.117188f, 0.960938f, 0.023438f, 0.222656f},
+ {0.882812f, 0.507812f, 0.449219f, 0.414062f}, {0.554688f, 0.066406f, 0.757812f, 0.113281f},
+ {0.808594f, 0.175781f, 0.515625f, 0.984375f}, {0.621094f, 0.937500f, 0.304688f, 0.269531f},
+ {0.769531f, 0.824219f, 0.609375f, 0.449219f}, {0.906250f, 0.750000f, 0.386719f, 0.738281f},
+ {0.464844f, 0.980469f, 0.878906f, 0.335938f}, {0.000000f, 0.542969f, 0.441406f, 0.429688f},
+ {0.781250f, 0.179688f, 0.984375f, 0.027344f}, {0.238281f, 0.765625f, 0.304688f, 0.914062f},
+ {0.500000f, 0.011719f, 0.914062f, 0.082031f}, {0.871094f, 0.238281f, 0.792969f, 0.355469f},
+ {0.750000f, 0.707031f, 0.632812f, 0.742188f}, {0.945312f, 0.796875f, 0.382812f, 0.433594f},
+ {0.109375f, 0.207031f, 0.570312f, 0.316406f}, {0.707031f, 0.492188f, 0.761719f, 0.203125f},
+ {0.597656f, 0.390625f, 0.328125f, 0.917969f}, {0.003906f, 0.554688f, 0.941406f, 0.261719f},
+ {0.519531f, 0.777344f, 0.453125f, 0.445312f}, {0.628906f, 0.699219f, 0.144531f, 0.679688f},
+ {0.066406f, 0.867188f, 0.878906f, 0.226562f}, {0.683594f, 0.589844f, 0.308594f, 0.777344f},
+ {0.117188f, 0.246094f, 0.464844f, 0.437500f}, {0.933594f, 0.339844f, 0.027344f, 0.488281f},
+ {0.632812f, 0.917969f, 0.925781f, 0.234375f}, {0.320312f, 0.273438f, 0.535156f, 0.886719f},
+ {0.980469f, 0.816406f, 0.050781f, 0.734375f}, {0.476562f, 0.734375f, 0.488281f, 0.152344f},
+ {0.648438f, 0.187500f, 0.687500f, 0.824219f}, {0.308594f, 0.875000f, 0.847656f, 0.460938f},
+ {0.367188f, 0.695312f, 0.417969f, 0.949219f}, {0.234375f, 0.281250f, 0.097656f, 0.035156f},
+ {0.007812f, 0.468750f, 0.667969f, 0.421875f}, {0.664062f, 0.921875f, 0.753906f, 0.914062f},
+ {0.863281f, 0.597656f, 0.605469f, 0.718750f}, {0.378906f, 0.320312f, 0.386719f, 0.476562f},
+ {0.273438f, 0.492188f, 0.683594f, 0.953125f}, {0.550781f, 0.851562f, 0.781250f, 0.144531f},
+ {0.167969f, 0.027344f, 0.593750f, 0.613281f}, {0.250000f, 0.367188f, 0.925781f, 0.976562f},
+ {0.941406f, 0.656250f, 0.511719f, 0.746094f}, {0.468750f, 0.757812f, 0.675781f, 0.531250f},
+ {0.156250f, 0.140625f, 0.953125f, 0.132812f}, {0.890625f, 0.269531f, 0.164062f, 0.792969f},
+ {0.820312f, 0.074219f, 0.734375f, 0.988281f}, {0.449219f, 0.605469f, 0.476562f, 0.105469f},
+ {0.546875f, 0.503906f, 0.210938f, 0.738281f}, {0.058594f, 0.019531f, 0.320312f, 0.277344f},
+ {0.875000f, 0.390625f, 0.867188f, 0.914062f}, {0.718750f, 0.468750f, 0.261719f, 0.808594f},
+ {0.281250f, 0.207031f, 0.953125f, 0.175781f}, {0.832031f, 0.312500f, 0.835938f, 0.402344f},
+ {0.914062f, 0.945312f, 0.640625f, 0.230469f}, {0.316406f, 0.816406f, 0.402344f, 0.457031f},
+ {0.648438f, 0.257812f, 0.730469f, 0.593750f}, {0.976562f, 0.441406f, 0.667969f, 0.730469f},
+ {0.363281f, 0.011719f, 0.957031f, 0.984375f}, {0.015625f, 0.363281f, 0.820312f, 0.019531f},
+ {0.636719f, 0.476562f, 0.531250f, 0.574219f}, {0.144531f, 0.632812f, 0.734375f, 0.878906f},
+ {0.355469f, 0.421875f, 0.253906f, 0.269531f}, {0.269531f, 0.929688f, 0.484375f, 0.730469f},
+ {0.773438f, 0.027344f, 0.621094f, 0.339844f}, {0.921875f, 0.253906f, 0.707031f, 0.925781f},
+ {0.722656f, 0.660156f, 0.328125f, 0.867188f}, {0.453125f, 0.777344f, 0.839844f, 0.679688f},
+ {0.156250f, 0.292969f, 0.234375f, 0.324219f}, {0.988281f, 0.699219f, 0.128906f, 0.062500f},
+ {0.523438f, 0.402344f, 0.820312f, 0.898438f}, {0.128906f, 0.140625f, 0.183594f, 0.160156f},
+ {0.394531f, 0.238281f, 0.050781f, 0.597656f}, {0.964844f, 0.062500f, 0.660156f, 0.855469f},
+ {0.339844f, 0.429688f, 0.558594f, 0.707031f}, {0.722656f, 0.648438f, 0.363281f, 0.628906f},
+ {0.921875f, 0.515625f, 0.207031f, 0.460938f}, {0.054688f, 0.988281f, 0.503906f, 0.878906f},
+ {0.652344f, 0.089844f, 0.718750f, 0.179688f}, {0.351562f, 0.339844f, 0.140625f, 0.980469f},
+ {0.800781f, 0.902344f, 0.085938f, 0.679688f}, {0.429688f, 0.679688f, 0.859375f, 0.765625f},
+ {0.296875f, 0.820312f, 0.195312f, 0.546875f}, {0.675781f, 0.613281f, 0.621094f, 0.839844f},
+ {0.882812f, 0.933594f, 0.816406f, 0.167969f}, {0.769531f, 0.070312f, 0.363281f, 0.812500f},
+ {0.964844f, 0.367188f, 0.062500f, 0.937500f}, {0.480469f, 0.421875f, 0.988281f, 0.351562f},
+ {0.226562f, 0.113281f, 0.121094f, 0.144531f}, {0.277344f, 0.726562f, 0.828125f, 0.992188f},
+ {0.742188f, 0.464844f, 0.695312f, 0.804688f}, {0.152344f, 0.058594f, 0.398438f, 0.382812f},
+ {0.421875f, 0.675781f, 0.960938f, 0.574219f}, {0.792969f, 0.601562f, 0.144531f, 0.511719f},
+ {0.031250f, 0.320312f, 0.332031f, 0.648438f}, {0.933594f, 0.441406f, 0.578125f, 0.292969f},
+ {0.703125f, 0.230469f, 0.179688f, 0.789062f}, {0.492188f, 0.773438f, 0.925781f, 0.527344f},
+ {0.960938f, 0.535156f, 0.339844f, 0.324219f}, {0.425781f, 0.671875f, 0.035156f, 0.820312f},
+ {0.734375f, 0.804688f, 0.257812f, 0.628906f}, {0.207031f, 0.113281f, 0.164062f, 0.187500f},
+ {0.808594f, 0.902344f, 0.984375f, 0.289062f}, {0.988281f, 0.636719f, 0.300781f, 0.886719f},
+ {0.707031f, 0.441406f, 0.214844f, 0.507812f}, {0.328125f, 0.968750f, 0.371094f, 0.015625f},
+ {0.859375f, 0.183594f, 0.742188f, 0.839844f}, {0.656250f, 0.570312f, 0.121094f, 0.332031f},
+ {0.398438f, 0.414062f, 0.343750f, 0.882812f}, {0.113281f, 0.816406f, 0.234375f, 0.476562f},
+ {0.613281f, 0.703125f, 0.656250f, 0.398438f}, {0.027344f, 0.359375f, 0.093750f, 0.550781f},
+ {0.683594f, 0.292969f, 0.789062f, 0.855469f}, {0.785156f, 0.804688f, 0.917969f, 0.214844f},
+ {0.328125f, 0.910156f, 0.574219f, 0.617188f}, {0.621094f, 0.085938f, 0.007812f, 0.359375f},
+ {0.199219f, 0.687500f, 0.445312f, 0.964844f}, {0.117188f, 0.519531f, 0.183594f, 0.699219f},
+ {0.574219f, 0.066406f, 0.121094f, 0.628906f}, {0.394531f, 0.605469f, 0.914062f, 0.945312f},
+ {0.730469f, 0.718750f, 0.574219f, 0.144531f}, {0.078125f, 0.105469f, 0.066406f, 0.265625f},
+ {0.800781f, 0.546875f, 0.191406f, 0.523438f}, {0.460938f, 0.792969f, 0.609375f, 0.703125f},
+ {0.746094f, 0.847656f, 0.101562f, 0.218750f}, {0.582031f, 0.125000f, 0.914062f, 0.945312f},
+ {0.859375f, 0.335938f, 0.851562f, 0.402344f}, {0.695312f, 0.535156f, 0.070312f, 0.785156f},
+ {0.523438f, 0.792969f, 0.207031f, 0.593750f}, {0.210938f, 0.445312f, 0.886719f, 0.464844f},
+ {0.628906f, 0.132812f, 0.582031f, 0.000000f}, {0.285156f, 0.902344f, 0.054688f, 0.515625f},
+ {0.019531f, 0.472656f, 0.648438f, 0.773438f}, {0.410156f, 0.011719f, 0.414062f, 0.558594f},
+ {0.312500f, 0.632812f, 0.699219f, 0.652344f}, {0.230469f, 0.500000f, 0.527344f, 0.500000f},
+ {0.656250f, 0.789062f, 0.921875f, 0.109375f}, {0.843750f, 0.308594f, 0.265625f, 0.960938f},
+ {0.183594f, 0.835938f, 0.734375f, 0.218750f}, {0.632812f, 0.925781f, 0.109375f, 0.140625f},
+ {0.093750f, 0.136719f, 0.847656f, 0.269531f}, {0.394531f, 0.371094f, 0.011719f, 0.523438f},
+ {0.191406f, 0.625000f, 0.273438f, 0.046875f}, {0.269531f, 0.566406f, 0.894531f, 0.593750f},
+ {0.574219f, 0.035156f, 0.359375f, 0.906250f}, {0.164062f, 0.300781f, 0.523438f, 0.085938f},
+ {0.925781f, 0.101562f, 0.425781f, 0.359375f}, {0.089844f, 0.230469f, 0.003906f, 0.054688f},
+ {0.257812f, 0.332031f, 0.550781f, 0.589844f}, {0.378906f, 0.187500f, 0.242188f, 0.300781f},
+ {0.167969f, 0.531250f, 0.785156f, 0.023438f}, {0.722656f, 0.824219f, 0.640625f, 0.628906f},
+ {0.578125f, 0.898438f, 0.519531f, 0.546875f}, {0.835938f, 0.621094f, 0.257812f, 0.054688f},
+ {0.503906f, 0.175781f, 0.195312f, 0.691406f}, {0.074219f, 0.394531f, 0.601562f, 0.304688f},
+ {0.882812f, 0.953125f, 0.796875f, 0.085938f}, {0.574219f, 0.015625f, 0.230469f, 0.968750f},
+ {0.273438f, 0.515625f, 0.886719f, 0.050781f}, {0.113281f, 0.828125f, 0.742188f, 0.367188f},
+ {0.816406f, 0.101562f, 0.281250f, 0.183594f}, {0.187500f, 0.968750f, 0.625000f, 0.671875f},
+ {0.562500f, 0.003906f, 0.796875f, 0.113281f}, {0.320312f, 0.164062f, 0.898438f, 0.257812f},
+ {0.128906f, 0.257812f, 0.503906f, 0.062500f}, {0.593750f, 0.390625f, 0.843750f, 0.542969f},
+ {0.472656f, 0.757812f, 0.726562f, 0.402344f}, {0.023438f, 0.062500f, 0.539062f, 0.792969f},
+ {0.113281f, 0.296875f, 0.425781f, 0.722656f}, {0.523438f, 0.808594f, 0.054688f, 0.449219f},
+ {0.800781f, 0.515625f, 0.816406f, 0.093750f}, {0.054688f, 0.867188f, 0.460938f, 0.207031f},
+ {0.566406f, 0.019531f, 0.605469f, 0.582031f}, {0.742188f, 0.992188f, 0.882812f, 0.671875f},
+ {0.265625f, 0.472656f, 0.546875f, 0.171875f}, {0.992188f, 0.171875f, 0.964844f, 0.316406f},
+ {0.406250f, 0.746094f, 0.429688f, 0.695312f}, {0.132812f, 0.628906f, 0.160156f, 0.453125f},
+ {0.488281f, 0.140625f, 0.507812f, 0.136719f}, {0.937500f, 0.562500f, 0.679688f, 0.566406f},
+ {0.019531f, 0.789062f, 0.769531f, 0.085938f}, {0.464844f, 0.898438f, 0.597656f, 0.492188f},
+ {0.957031f, 0.378906f, 0.304688f, 0.011719f}, {0.050781f, 0.179688f, 0.027344f, 0.765625f},
+ {0.261719f, 0.859375f, 0.875000f, 0.375000f}, {0.609375f, 0.964844f, 0.437500f, 0.812500f},
+ {0.175781f, 0.296875f, 0.781250f, 0.894531f}, {0.929688f, 0.691406f, 0.289062f, 0.468750f},
+ {0.238281f, 0.234375f, 0.382812f, 0.347656f}, {0.093750f, 0.054688f, 0.160156f, 0.652344f},
+ {0.914062f, 0.750000f, 0.656250f, 0.035156f}, {0.445312f, 0.863281f, 0.320312f, 0.187500f},
+ {0.167969f, 0.199219f, 0.519531f, 0.828125f}, {0.070312f, 0.703125f, 0.117188f, 0.644531f},
+ {0.371094f, 0.382812f, 0.386719f, 0.289062f}, {0.949219f, 0.601562f, 0.917969f, 0.144531f},
+ {0.675781f, 0.218750f, 0.476562f, 0.394531f}, {0.867188f, 0.550781f, 0.988281f, 0.933594f},
+ {0.585938f, 0.960938f, 0.003906f, 0.199219f}, {0.753906f, 0.339844f, 0.328125f, 0.371094f},
+ {0.078125f, 0.914062f, 0.773438f, 0.796875f}, {0.542969f, 0.593750f, 0.488281f, 0.308594f},
+ {0.449219f, 0.683594f, 0.148438f, 0.558594f}, {0.289062f, 0.218750f, 0.406250f, 0.402344f},
+ {0.582031f, 0.281250f, 0.589844f, 0.929688f}, {0.828125f, 0.734375f, 0.941406f, 0.714844f},
+ {0.460938f, 0.867188f, 0.449219f, 0.832031f}, {0.960938f, 0.453125f, 0.660156f, 0.398438f},
+ {0.027344f, 0.757812f, 0.234375f, 0.230469f}, {0.742188f, 0.972656f, 0.730469f, 0.468750f},
+ {0.488281f, 0.429688f, 0.128906f, 0.640625f}, {0.839844f, 0.722656f, 0.968750f, 0.960938f},
+ {0.558594f, 0.484375f, 0.664062f, 0.742188f}, {0.039062f, 0.964844f, 0.894531f, 0.390625f},
+ {0.812500f, 0.753906f, 0.183594f, 0.503906f}, {0.335938f, 0.281250f, 0.417969f, 0.757812f},
+ {0.441406f, 0.035156f, 0.726562f, 0.878906f}, {0.019531f, 0.496094f, 0.347656f, 0.269531f},
+ {0.921875f, 0.777344f, 0.867188f, 0.175781f}, {0.679688f, 0.859375f, 0.074219f, 0.605469f},
+ {0.355469f, 0.242188f, 0.449219f, 0.433594f}, {0.175781f, 0.363281f, 0.656250f, 0.765625f},
+ {0.515625f, 0.898438f, 0.003906f, 0.246094f}, {0.613281f, 0.152344f, 0.468750f, 0.894531f},
+ {0.386719f, 0.402344f, 0.523438f, 0.566406f}, {0.066406f, 0.613281f, 0.062500f, 0.988281f},
+ {0.765625f, 0.347656f, 0.390625f, 0.449219f}, {0.851562f, 0.843750f, 0.203125f, 0.875000f},
+ {0.054688f, 0.445312f, 0.441406f, 0.750000f}, {0.929688f, 0.992188f, 0.644531f, 0.937500f},
+ {0.769531f, 0.554688f, 0.000000f, 0.597656f}, {0.632812f, 0.234375f, 0.132812f, 0.101562f},
+ {0.367188f, 0.691406f, 0.867188f, 0.347656f}, {0.425781f, 0.125000f, 0.632812f, 0.261719f},
+ {0.183594f, 0.613281f, 0.968750f, 0.691406f}, {0.285156f, 0.250000f, 0.078125f, 0.929688f},
+ {0.917969f, 0.320312f, 0.292969f, 0.039062f}, {0.347656f, 0.644531f, 0.800781f, 0.269531f},
+ {0.851562f, 0.539062f, 0.019531f, 0.945312f}, {0.515625f, 0.882812f, 0.359375f, 0.070312f},
+ {0.218750f, 0.050781f, 0.277344f, 0.886719f}, {0.898438f, 0.242188f, 0.714844f, 0.019531f},
+ {0.558594f, 0.441406f, 0.062500f, 0.773438f}, {0.250000f, 0.964844f, 0.390625f, 0.902344f},
+ {0.820312f, 0.343750f, 0.226562f, 0.265625f}, {0.343750f, 0.003906f, 0.972656f, 0.832031f},
+ {0.757812f, 0.753906f, 0.484375f, 0.316406f}, {0.507812f, 0.234375f, 0.808594f, 0.554688f},
+ {0.859375f, 0.410156f, 0.347656f, 0.203125f}, {0.425781f, 0.503906f, 0.140625f, 0.062500f},
+ {0.687500f, 0.140625f, 0.496094f, 0.601562f}, {0.292969f, 0.582031f, 0.996094f, 0.093750f},
+ {0.828125f, 0.386719f, 0.707031f, 0.300781f}, {0.398438f, 0.980469f, 0.578125f, 0.859375f},
+ {0.042969f, 0.496094f, 0.441406f, 0.500000f}, {0.320312f, 0.609375f, 0.777344f, 0.550781f},
+ {0.601562f, 0.304688f, 0.945312f, 0.089844f}, {0.851562f, 0.093750f, 0.269531f, 0.234375f},
+ {0.492188f, 0.988281f, 0.753906f, 0.953125f}, {0.792969f, 0.332031f, 0.175781f, 0.847656f},
+ {0.089844f, 0.843750f, 0.726562f, 0.710938f}, {0.183594f, 0.082031f, 0.277344f, 0.246094f},
+ {0.476562f, 0.714844f, 0.566406f, 0.039062f}, {0.925781f, 0.187500f, 0.835938f, 0.878906f},
+ {0.035156f, 0.109375f, 0.214844f, 0.691406f}, {0.695312f, 0.464844f, 0.621094f, 0.007812f},
+ {0.949219f, 0.023438f, 0.968750f, 0.472656f}, {0.136719f, 0.558594f, 0.800781f, 0.769531f},
+ {0.773438f, 0.410156f, 0.679688f, 0.066406f}, {0.519531f, 0.816406f, 0.320312f, 0.644531f},
+ {0.683594f, 0.066406f, 0.171875f, 0.296875f}, {0.867188f, 0.253906f, 0.820312f, 0.125000f},
+ {0.386719f, 0.523438f, 0.054688f, 0.562500f}, {0.332031f, 0.156250f, 0.601562f, 0.863281f},
+ {0.648438f, 0.851562f, 0.796875f, 0.281250f}, {0.214844f, 0.644531f, 0.269531f, 0.425781f},
+ {0.417969f, 0.023438f, 0.390625f, 0.140625f}, {0.917969f, 0.132812f, 0.082031f, 0.902344f},
+ {0.617188f, 0.664062f, 0.496094f, 0.093750f}, {0.101562f, 0.578125f, 0.589844f, 0.207031f},
+ {0.996094f, 0.222656f, 0.015625f, 0.414062f}, {0.199219f, 0.996094f, 0.949219f, 0.824219f},
+ {0.398438f, 0.316406f, 0.757812f, 0.480469f}, {0.605469f, 0.550781f, 0.562500f, 0.929688f},
+ {0.246094f, 0.085938f, 0.300781f, 0.855469f}, {0.832031f, 0.648438f, 0.363281f, 0.128906f},
+ {0.914062f, 0.757812f, 0.914062f, 0.699219f}, {0.691406f, 0.566406f, 0.828125f, 0.410156f},
+ {0.980469f, 0.292969f, 0.121094f, 0.007812f}, {0.457031f, 0.742188f, 0.949219f, 0.730469f},
+ {0.648438f, 0.914062f, 0.714844f, 0.148438f}, {0.257812f, 0.511719f, 0.566406f, 0.503906f},
+ {0.527344f, 0.082031f, 0.105469f, 0.375000f}, {0.398438f, 0.707031f, 0.285156f, 0.019531f},
+ {0.300781f, 0.183594f, 0.359375f, 0.230469f}, {0.222656f, 0.355469f, 0.933594f, 0.867188f},
+ {0.867188f, 0.500000f, 0.476562f, 0.167969f}, {0.964844f, 0.945312f, 0.257812f, 0.636719f},
+ {0.683594f, 0.386719f, 0.171875f, 0.535156f}, {0.601562f, 0.074219f, 0.710938f, 0.781250f},
+ {0.484375f, 0.785156f, 0.414062f, 0.359375f}, {0.074219f, 0.214844f, 0.503906f, 0.742188f},
+ {0.167969f, 0.113281f, 0.144531f, 0.609375f}, {0.640625f, 0.378906f, 0.746094f, 0.800781f},
+ {0.304688f, 0.949219f, 0.851562f, 0.507812f}, {0.750000f, 0.507812f, 0.613281f, 0.339844f},
+ {0.082031f, 0.671875f, 0.894531f, 0.656250f}, {0.660156f, 0.195312f, 0.324219f, 0.410156f},
+ {0.414062f, 0.281250f, 0.824219f, 0.722656f}, {0.703125f, 0.640625f, 0.085938f, 0.167969f},
+ {0.597656f, 0.464844f, 0.718750f, 0.437500f}, {0.140625f, 0.578125f, 0.253906f, 0.863281f},
+ {0.207031f, 0.667969f, 0.546875f, 0.921875f}, {0.968750f, 0.042969f, 0.679688f, 0.667969f},
+ {0.531250f, 0.875000f, 0.218750f, 0.410156f}, {0.117188f, 0.761719f, 0.000000f, 0.164062f},
+ {0.488281f, 0.179688f, 0.894531f, 0.800781f}, {0.562500f, 0.660156f, 0.238281f, 0.722656f},
+ {0.789062f, 0.265625f, 0.050781f, 0.125000f}, {0.664062f, 0.007812f, 0.835938f, 0.992188f},
+ {0.996094f, 0.894531f, 0.410156f, 0.375000f}, {0.753906f, 0.566406f, 0.636719f, 0.757812f},
+ {0.234375f, 0.804688f, 0.550781f, 0.437500f}, {0.562500f, 0.046875f, 0.082031f, 0.074219f},
+ {0.343750f, 0.757812f, 0.359375f, 0.597656f}, {0.726562f, 0.429688f, 0.863281f, 0.480469f},
+ {0.257812f, 0.875000f, 0.136719f, 0.753906f}, {0.816406f, 0.261719f, 0.437500f, 0.429688f},
+ {0.332031f, 0.390625f, 0.089844f, 0.273438f}, {0.382812f, 0.742188f, 0.351562f, 0.621094f},
+ {0.222656f, 0.890625f, 0.027344f, 0.839844f}, {0.890625f, 0.093750f, 0.246094f, 0.988281f},
+ {0.011719f, 0.968750f, 0.539062f, 0.203125f}, {0.316406f, 0.484375f, 0.074219f, 0.363281f},
+ {0.238281f, 0.187500f, 0.500000f, 0.496094f}, {0.105469f, 0.660156f, 0.996094f, 0.796875f},
+ {0.777344f, 0.386719f, 0.414062f, 0.167969f}, {0.531250f, 0.589844f, 0.308594f, 0.730469f},
+ {0.976562f, 0.347656f, 0.871094f, 0.027344f}, {0.125000f, 0.261719f, 0.468750f, 0.691406f},
+ {0.710938f, 0.910156f, 0.703125f, 0.531250f}, {0.468750f, 0.812500f, 0.328125f, 0.250000f},
+ {0.277344f, 0.441406f, 0.765625f, 0.667969f}, {0.535156f, 0.375000f, 0.917969f, 0.972656f},
+ {0.648438f, 0.074219f, 0.292969f, 0.324219f}, {0.785156f, 0.687500f, 0.156250f, 0.710938f},
+ {0.304688f, 0.136719f, 0.484375f, 0.011719f}, {0.089844f, 0.714844f, 0.113281f, 0.652344f},
+ {0.769531f, 0.453125f, 0.992188f, 0.214844f}, {0.437500f, 0.199219f, 0.703125f, 0.328125f},
+ {0.003906f, 0.980469f, 0.171875f, 0.488281f}, {0.300781f, 0.476562f, 0.410156f, 0.621094f},
+ {0.218750f, 0.695312f, 0.218750f, 0.843750f}, {0.140625f, 0.058594f, 0.652344f, 0.222656f},
+ {0.347656f, 0.199219f, 0.320312f, 0.335938f}, {0.945312f, 0.652344f, 0.863281f, 0.652344f},
+ {0.703125f, 0.312500f, 0.976562f, 0.808594f}, {0.171875f, 0.585938f, 0.753906f, 0.292969f},
+ {0.906250f, 0.863281f, 0.808594f, 0.683594f}, {0.082031f, 0.781250f, 0.582031f, 0.488281f},
+ {0.562500f, 0.007812f, 0.691406f, 0.988281f}, {0.734375f, 0.886719f, 0.332031f, 0.406250f},
+ {0.000000f, 0.730469f, 0.550781f, 0.894531f}, {0.234375f, 0.460938f, 0.894531f, 0.117188f},
+ {0.761719f, 0.929688f, 0.207031f, 0.492188f}, {0.957031f, 0.683594f, 0.933594f, 0.441406f},
+ {0.386719f, 0.828125f, 0.644531f, 0.152344f}, {0.718750f, 0.593750f, 0.246094f, 0.394531f},
+ {0.011719f, 0.308594f, 0.484375f, 0.242188f}, {0.839844f, 0.851562f, 0.113281f, 0.972656f},
+ {0.359375f, 0.765625f, 0.195312f, 0.199219f}, {0.957031f, 0.406250f, 0.933594f, 0.531250f},
+ {0.175781f, 0.117188f, 0.535156f, 0.054688f}, {0.039062f, 0.863281f, 0.648438f, 0.992188f},
+ {0.285156f, 0.996094f, 0.152344f, 0.648438f}, {0.898438f, 0.074219f, 0.410156f, 0.117188f},
+ {0.375000f, 0.808594f, 0.929688f, 0.507812f}, {0.777344f, 0.347656f, 0.761719f, 0.277344f},
+ {0.007812f, 0.937500f, 0.617188f, 0.757812f}, {0.339844f, 0.433594f, 0.816406f, 0.972656f},
+ {0.718750f, 0.085938f, 0.328125f, 0.621094f}, {0.957031f, 0.921875f, 0.542969f, 0.250000f},
+ {0.214844f, 0.460938f, 0.132812f, 0.421875f}, {0.128906f, 0.734375f, 0.691406f, 0.882812f},
+ {0.277344f, 0.398438f, 0.195312f, 0.312500f}, {0.011719f, 0.179688f, 0.011719f, 0.667969f},
+ {0.406250f, 0.476562f, 0.960938f, 0.566406f}, {0.140625f, 0.644531f, 0.796875f, 0.175781f},
+ {0.898438f, 0.277344f, 0.222656f, 0.343750f}, {0.433594f, 0.156250f, 0.675781f, 0.980469f},
+ {0.613281f, 0.664062f, 0.601562f, 0.125000f}, {0.117188f, 0.539062f, 0.953125f, 0.546875f},
+ {0.511719f, 0.820312f, 0.722656f, 0.914062f}, {0.859375f, 0.625000f, 0.902344f, 0.156250f},
+ {0.593750f, 0.355469f, 0.464844f, 0.332031f}, {0.421875f, 0.167969f, 0.871094f, 0.101562f},
+ {0.730469f, 0.707031f, 0.714844f, 0.582031f}, {0.996094f, 0.613281f, 0.375000f, 0.746094f},
+ {0.156250f, 0.328125f, 0.769531f, 0.039062f}, {0.625000f, 0.929688f, 0.628906f, 0.949219f},
+ {0.449219f, 0.113281f, 0.910156f, 0.625000f}, {0.257812f, 0.800781f, 0.562500f, 0.339844f},
+ {0.046875f, 0.054688f, 0.031250f, 0.996094f}, {0.792969f, 0.496094f, 0.160156f, 0.195312f},
+ {0.324219f, 0.562500f, 0.929688f, 0.847656f}, {0.175781f, 0.203125f, 0.210938f, 0.789062f},
+ {0.863281f, 0.304688f, 0.847656f, 0.468750f}, {0.746094f, 0.925781f, 0.070312f, 0.609375f},
+ {0.136719f, 0.843750f, 0.675781f, 0.156250f}, {0.886719f, 0.605469f, 0.390625f, 0.562500f},
+ {0.519531f, 0.414062f, 0.636719f, 0.113281f}, {0.710938f, 0.910156f, 0.214844f, 0.375000f},
+ {0.964844f, 0.808594f, 0.785156f, 0.531250f}, {0.128906f, 0.281250f, 0.066406f, 0.957031f},
+ {0.488281f, 0.031250f, 0.609375f, 0.816406f}, {0.750000f, 0.128906f, 0.542969f, 0.101562f},
+ {0.550781f, 0.878906f, 0.757812f, 0.281250f}, {0.886719f, 0.250000f, 0.261719f, 0.917969f},
+ {0.808594f, 0.417969f, 0.476562f, 0.585938f}, {0.585938f, 0.812500f, 0.156250f, 0.085938f},
+ {0.011719f, 0.027344f, 0.042969f, 0.968750f}, {0.445312f, 0.941406f, 0.515625f, 0.429688f},
+ {0.671875f, 0.136719f, 0.179688f, 0.136719f}, {0.812500f, 0.640625f, 0.230469f, 0.832031f},
+ {0.480469f, 0.433594f, 0.070312f, 0.562500f}, {0.144531f, 0.281250f, 0.789062f, 0.031250f},
+ {0.320312f, 0.179688f, 0.023438f, 0.304688f}, {0.886719f, 0.558594f, 0.757812f, 0.234375f},
+ {0.445312f, 0.347656f, 0.371094f, 0.968750f}, {0.121094f, 0.039062f, 0.585938f, 0.863281f},
+ {0.816406f, 0.421875f, 0.054688f, 0.648438f}, {0.578125f, 0.160156f, 0.992188f, 0.089844f},
+ {0.429688f, 0.722656f, 0.402344f, 0.574219f}, {0.148438f, 0.097656f, 0.562500f, 0.835938f},
+ {0.613281f, 0.035156f, 0.785156f, 0.117188f}, {0.468750f, 0.605469f, 0.449219f, 0.296875f},
+ {0.851562f, 0.800781f, 0.035156f, 0.609375f}, {0.535156f, 0.523438f, 0.367188f, 0.789062f},
+ {0.796875f, 0.152344f, 0.863281f, 0.238281f}, {0.667969f, 0.300781f, 0.585938f, 0.343750f},
+ {0.074219f, 0.722656f, 0.042969f, 0.714844f}, {0.574219f, 0.199219f, 0.300781f, 0.039062f},
+ {0.648438f, 0.269531f, 0.089844f, 0.464844f}, {0.847656f, 0.621094f, 0.402344f, 0.367188f},
+ {0.164062f, 0.527344f, 0.457031f, 0.003906f}, {0.617188f, 0.328125f, 0.742188f, 0.566406f},
+ {0.367188f, 0.835938f, 0.972656f, 0.195312f}, {0.468750f, 0.136719f, 0.351562f, 0.695312f},
+ {0.542969f, 0.679688f, 0.496094f, 0.480469f}, {0.695312f, 0.941406f, 0.855469f, 0.046875f},
+ {0.933594f, 0.234375f, 0.312500f, 0.902344f}, {0.640625f, 0.527344f, 0.429688f, 0.804688f},
+ {0.832031f, 0.375000f, 0.500000f, 0.640625f}, {0.046875f, 0.949219f, 0.066406f, 0.292969f},
+ {0.984375f, 0.460938f, 0.390625f, 0.824219f}, {0.675781f, 0.066406f, 0.179688f, 0.058594f},
+ {0.175781f, 0.992188f, 0.531250f, 0.664062f}, {0.785156f, 0.230469f, 0.660156f, 0.511719f},
+ {0.089844f, 0.792969f, 0.300781f, 0.242188f}, {0.652344f, 0.292969f, 0.121094f, 0.699219f},
+ {0.480469f, 0.535156f, 0.195312f, 0.433594f}, {0.363281f, 0.777344f, 0.933594f, 0.894531f},
+ {0.550781f, 0.011719f, 0.273438f, 0.265625f}, {0.886719f, 0.871094f, 0.144531f, 0.410156f},
+ {0.937500f, 0.679688f, 0.699219f, 0.515625f}, {0.183594f, 0.214844f, 0.218750f, 0.097656f},
+ {0.855469f, 0.988281f, 0.777344f, 0.457031f}, {0.566406f, 0.761719f, 0.519531f, 0.593750f},
+ {0.664062f, 0.394531f, 0.593750f, 0.308594f}, {0.960938f, 0.695312f, 0.113281f, 0.070312f},
+ {0.007812f, 0.101562f, 0.425781f, 0.359375f}, {0.242188f, 0.742188f, 0.546875f, 0.042969f},
+ {0.355469f, 0.480469f, 0.250000f, 0.921875f}, {0.433594f, 0.187500f, 0.828125f, 0.859375f},
+ {0.035156f, 0.000000f, 0.894531f, 0.789062f}, {0.218750f, 0.343750f, 0.535156f, 0.285156f},
+ {0.558594f, 0.523438f, 0.433594f, 0.734375f}, {0.371094f, 0.625000f, 0.273438f, 0.031250f},
+ {0.652344f, 0.835938f, 0.875000f, 0.171875f}, {0.851562f, 0.375000f, 0.332031f, 0.550781f},
+ {0.062500f, 0.605469f, 0.968750f, 0.371094f}, {0.417969f, 0.539062f, 0.031250f, 0.460938f},
+ {0.097656f, 0.957031f, 0.820312f, 0.761719f}, {0.500000f, 0.750000f, 0.601562f, 0.191406f},
+ {0.242188f, 0.472656f, 0.371094f, 0.535156f}, {0.757812f, 0.269531f, 0.660156f, 0.625000f},
+ {0.343750f, 0.394531f, 0.453125f, 0.730469f}, {0.613281f, 0.535156f, 0.914062f, 0.332031f},
+ {0.265625f, 0.085938f, 0.410156f, 0.097656f}, {0.410156f, 0.835938f, 0.980469f, 0.757812f},
+ {0.832031f, 0.664062f, 0.484375f, 0.812500f}, {0.644531f, 0.128906f, 0.664062f, 0.593750f},
+ {0.546875f, 0.761719f, 0.109375f, 0.191406f}, {0.207031f, 0.503906f, 0.304688f, 0.007812f},
+ {0.667969f, 0.898438f, 0.812500f, 0.300781f}, {0.253906f, 0.230469f, 0.687500f, 0.921875f},
+ {0.976562f, 0.468750f, 0.339844f, 0.687500f}, {0.519531f, 0.554688f, 0.003906f, 0.468750f},
+ {0.769531f, 0.359375f, 0.632812f, 0.746094f}, {0.230469f, 0.929688f, 0.289062f, 0.933594f},
+ {0.109375f, 0.695312f, 0.691406f, 0.367188f}, {0.328125f, 0.242188f, 0.246094f, 0.484375f},
+ {0.984375f, 0.429688f, 0.984375f, 0.082031f}, {0.242188f, 0.910156f, 0.464844f, 0.582031f},
+ {0.480469f, 0.488281f, 0.199219f, 0.957031f}, {0.300781f, 0.558594f, 0.835938f, 0.816406f},
+ {0.437500f, 0.023438f, 0.957031f, 0.214844f}, {0.933594f, 0.687500f, 0.527344f, 0.859375f},
+ {0.269531f, 0.800781f, 0.179688f, 0.511719f}, {0.039062f, 0.222656f, 0.871094f, 0.921875f},
+ {0.894531f, 0.062500f, 0.628906f, 0.074219f}, {0.746094f, 0.546875f, 0.277344f, 0.820312f},
+ {0.863281f, 0.343750f, 0.589844f, 0.265625f}, {0.335938f, 0.855469f, 0.105469f, 0.140625f},
+ {0.078125f, 0.109375f, 0.707031f, 0.515625f}, {0.515625f, 0.722656f, 0.617188f, 0.226562f},
+ {0.292969f, 0.886719f, 0.878906f, 0.027344f}, {0.214844f, 0.003906f, 0.937500f, 0.699219f},
+ {0.554688f, 0.601562f, 0.757812f, 0.402344f}, {0.390625f, 0.324219f, 0.281250f, 0.207031f},
+ {0.304688f, 0.128906f, 0.039062f, 0.957031f}, {0.960938f, 0.500000f, 0.808594f, 0.367188f},
+ {0.265625f, 0.031250f, 0.406250f, 0.808594f}, {0.054688f, 0.925781f, 0.613281f, 0.871094f},
+ {0.195312f, 0.429688f, 0.558594f, 0.539062f}, {0.835938f, 0.136719f, 0.828125f, 0.121094f},
+ {0.699219f, 0.242188f, 0.015625f, 0.660156f}, {0.035156f, 0.464844f, 0.480469f, 0.835938f},
+ {0.312500f, 0.554688f, 0.320312f, 0.003906f}, {0.738281f, 0.308594f, 0.093750f, 0.785156f},
+ {0.484375f, 0.621094f, 0.406250f, 0.890625f}, {0.375000f, 0.160156f, 0.957031f, 0.386719f},
+ {0.093750f, 0.882812f, 0.355469f, 0.125000f}, {0.410156f, 0.015625f, 0.644531f, 0.941406f},
+ {0.593750f, 0.597656f, 0.722656f, 0.542969f}, {0.492188f, 0.531250f, 0.984375f, 0.734375f},
+ {0.683594f, 0.265625f, 0.464844f, 0.398438f}, {0.835938f, 0.968750f, 0.035156f, 0.242188f},
+ {0.945312f, 0.761719f, 0.328125f, 0.453125f}, {0.625000f, 0.246094f, 0.730469f, 0.910156f},
+ {0.328125f, 0.078125f, 0.937500f, 0.593750f}, {0.902344f, 0.945312f, 0.015625f, 0.425781f},
+ {0.171875f, 0.433594f, 0.488281f, 0.687500f}, {0.250000f, 0.312500f, 0.804688f, 0.781250f},
+ {0.609375f, 0.781250f, 0.093750f, 0.941406f}, {0.312500f, 0.097656f, 0.687500f, 0.667969f},
+ {0.710938f, 0.160156f, 0.425781f, 0.031250f}, {0.164062f, 0.355469f, 0.945312f, 0.878906f},
+ {0.968750f, 0.628906f, 0.738281f, 0.261719f}, {0.839844f, 0.218750f, 0.296875f, 0.058594f},
+ {0.128906f, 0.902344f, 0.875000f, 0.933594f}, {0.035156f, 0.726562f, 0.113281f, 0.207031f},
+ {0.996094f, 0.335938f, 0.625000f, 0.464844f}, {0.531250f, 0.984375f, 0.277344f, 0.660156f},
+ {0.066406f, 0.589844f, 0.148438f, 0.367188f}, {0.363281f, 0.242188f, 0.867188f, 0.707031f},
+ {0.945312f, 0.953125f, 0.437500f, 0.527344f}, {0.042969f, 0.292969f, 0.535156f, 0.828125f},
+ {0.492188f, 0.617188f, 0.175781f, 0.730469f}, {0.332031f, 0.785156f, 0.886719f, 0.351562f},
+ {0.875000f, 0.984375f, 0.226562f, 0.179688f}, {0.062500f, 0.269531f, 0.839844f, 0.039062f},
+ {0.292969f, 0.875000f, 0.960938f, 0.421875f}, {0.917969f, 0.175781f, 0.167969f, 0.867188f},
+ {0.714844f, 0.324219f, 0.753906f, 0.000000f}, {0.593750f, 0.582031f, 0.523438f, 0.671875f},
+ {0.421875f, 0.089844f, 0.117188f, 0.910156f}, {0.136719f, 0.652344f, 0.730469f, 0.402344f},
+ {0.750000f, 0.363281f, 0.335938f, 0.179688f}, {0.906250f, 0.824219f, 0.660156f, 0.550781f},
+ {0.199219f, 0.976562f, 0.128906f, 0.128906f}, {0.101562f, 0.125000f, 0.714844f, 0.664062f},
+ {0.800781f, 0.378906f, 0.257812f, 0.296875f}, {0.515625f, 0.890625f, 0.027344f, 0.773438f},
+ {0.414062f, 0.605469f, 0.082031f, 0.351562f}, {0.070312f, 0.765625f, 0.804688f, 0.585938f},
+ {0.187500f, 0.433594f, 0.910156f, 0.968750f}, {0.796875f, 0.031250f, 0.468750f, 0.726562f},
+ {0.457031f, 0.589844f, 0.156250f, 0.410156f}, {0.160156f, 0.312500f, 0.257812f, 0.949219f},
+ {0.718750f, 0.785156f, 0.027344f, 0.363281f}, {0.773438f, 0.210938f, 0.554688f, 0.863281f},
+ {0.476562f, 0.683594f, 0.335938f, 0.488281f}, {0.007812f, 0.765625f, 0.839844f, 0.769531f},
+ {0.707031f, 0.859375f, 0.488281f, 0.605469f}, {0.445312f, 0.406250f, 0.230469f, 0.082031f},
+ {0.566406f, 0.675781f, 0.746094f, 0.464844f}, {0.757812f, 0.582031f, 0.957031f, 0.023438f},
+ {0.925781f, 0.843750f, 0.066406f, 0.183594f}, {0.281250f, 0.367188f, 0.429688f, 0.976562f},
+ {0.125000f, 0.957031f, 0.644531f, 0.324219f}, {0.421875f, 0.746094f, 0.757812f, 0.214844f},
+ {0.675781f, 0.410156f, 0.976562f, 0.933594f}, {0.074219f, 0.914062f, 0.851562f, 0.558594f},
+ {0.617188f, 0.070312f, 0.667969f, 0.238281f}, {0.910156f, 0.457031f, 0.246094f, 0.742188f},
+ {0.285156f, 0.335938f, 0.824219f, 0.636719f}, {0.722656f, 0.832031f, 0.007812f, 0.828125f},
+ {0.816406f, 0.949219f, 0.289062f, 0.273438f}, {0.925781f, 0.152344f, 0.148438f, 0.675781f},
+ {0.085938f, 0.359375f, 0.789062f, 0.187500f}, {0.277344f, 0.640625f, 0.585938f, 0.507812f},
+ {0.164062f, 0.867188f, 0.105469f, 0.640625f}, {0.457031f, 0.570312f, 0.183594f, 0.050781f},
+ {0.789062f, 0.675781f, 0.371094f, 0.203125f}, {0.050781f, 0.164062f, 0.675781f, 0.996094f},
+ {0.726562f, 0.718750f, 0.152344f, 0.316406f}, {0.992188f, 0.210938f, 0.578125f, 0.066406f},
+ {0.464844f, 0.894531f, 0.386719f, 0.242188f}, {0.792969f, 0.500000f, 0.203125f, 0.140625f},
+ {0.925781f, 0.687500f, 0.527344f, 0.414062f}, {0.644531f, 0.062500f, 0.132812f, 0.824219f},
+ {0.289062f, 0.847656f, 0.234375f, 0.492188f}, {0.390625f, 0.570312f, 0.054688f, 0.394531f},
+ {0.554688f, 0.042969f, 0.546875f, 0.890625f}, {0.917969f, 0.796875f, 0.695312f, 0.589844f},
+ {0.203125f, 0.207031f, 0.839844f, 0.273438f}, {0.773438f, 0.484375f, 0.355469f, 0.960938f},
+ {0.699219f, 0.035156f, 0.593750f, 0.152344f}, {0.171875f, 0.410156f, 0.218750f, 0.050781f},
+ {0.289062f, 0.824219f, 0.921875f, 0.406250f}, {0.851562f, 0.078125f, 0.765625f, 0.261719f},
+ {0.781250f, 0.703125f, 0.066406f, 0.457031f}, {0.105469f, 0.000000f, 0.460938f, 0.546875f},
+ {0.695312f, 0.140625f, 0.734375f, 0.792969f}, {0.187500f, 0.660156f, 0.515625f, 0.632812f},
+ {0.636719f, 0.433594f, 0.085938f, 0.257812f}, {0.402344f, 0.500000f, 0.425781f, 0.562500f},
+ {0.003906f, 0.019531f, 0.890625f, 0.214844f}, {0.878906f, 0.953125f, 0.816406f, 0.156250f},
+ {0.503906f, 0.847656f, 0.058594f, 0.835938f}, {0.062500f, 0.746094f, 0.617188f, 0.738281f},
+ {0.839844f, 0.058594f, 0.902344f, 0.312500f}, {0.691406f, 0.171875f, 0.496094f, 0.640625f},
+ {0.390625f, 0.417969f, 0.378906f, 0.433594f}, {0.593750f, 0.742188f, 0.578125f, 0.945312f},
+ {0.734375f, 0.484375f, 0.917969f, 0.722656f}, {0.316406f, 0.289062f, 0.667969f, 0.113281f},
+ {0.675781f, 0.164062f, 0.429688f, 0.460938f}, {0.972656f, 0.984375f, 0.371094f, 0.628906f},
+ {0.628906f, 0.257812f, 0.218750f, 0.015625f}, {0.242188f, 0.656250f, 0.773438f, 0.320312f},
+ {0.589844f, 0.957031f, 0.984375f, 0.777344f}, {0.957031f, 0.492188f, 0.402344f, 0.550781f},
+ {0.359375f, 0.144531f, 0.726562f, 0.105469f}, {0.859375f, 0.425781f, 0.203125f, 0.582031f},
+ {0.113281f, 0.921875f, 0.128906f, 0.261719f}, {0.933594f, 0.253906f, 0.628906f, 0.144531f},
+ {0.812500f, 0.570312f, 0.992188f, 0.890625f}, {0.148438f, 0.179688f, 0.093750f, 0.308594f},
+ {0.894531f, 0.734375f, 0.160156f, 0.734375f}, {0.339844f, 0.269531f, 0.343750f, 0.628906f},
+ {0.621094f, 0.089844f, 0.500000f, 0.394531f}, {0.523438f, 0.644531f, 0.906250f, 0.773438f},
+ {0.796875f, 0.507812f, 0.203125f, 0.480469f}, {0.582031f, 0.042969f, 0.367188f, 0.710938f},
+};
+
+#endif /* __EEVEE_LUT_H__ */
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
new file mode 100644
index 00000000000..c25ab1e7859
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -0,0 +1,1451 @@
+/*
+ * 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 eevee_materials.c
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_dynstr.h"
+#include "BLI_ghash.h"
+#include "BLI_alloca.h"
+
+#include "BKE_particle.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+
+#include "DNA_world_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_view3d_types.h"
+
+#include "GPU_material.h"
+
+#include "eevee_engine.h"
+#include "eevee_lut.h"
+#include "eevee_private.h"
+
+/* *********** STATIC *********** */
+static struct {
+ char *frag_shader_lib;
+ char *volume_shader_lib;
+
+ struct GPUShader *default_prepass_sh;
+ struct GPUShader *default_prepass_clip_sh;
+ struct GPUShader *default_lit[VAR_MAT_MAX];
+
+ struct GPUShader *default_background;
+
+ /* 64*64 array texture containing all LUTs and other utilitarian arrays.
+ * Packing enables us to same precious textures slots. */
+ struct GPUTexture *util_tex;
+
+ unsigned int sss_count;
+
+ float viewvecs[2][4];
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_lamps_lib_glsl[];
+extern char datatoc_lightprobe_lib_glsl[];
+extern char datatoc_ambient_occlusion_lib_glsl[];
+extern char datatoc_prepass_frag_glsl[];
+extern char datatoc_prepass_vert_glsl[];
+extern char datatoc_default_frag_glsl[];
+extern char datatoc_default_world_frag_glsl[];
+extern char datatoc_ltc_lib_glsl[];
+extern char datatoc_bsdf_lut_frag_glsl[];
+extern char datatoc_btdf_lut_frag_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_bsdf_direct_lib_glsl[];
+extern char datatoc_bsdf_sampling_lib_glsl[];
+extern char datatoc_irradiance_lib_glsl[];
+extern char datatoc_octahedron_lib_glsl[];
+extern char datatoc_lit_surface_frag_glsl[];
+extern char datatoc_lit_surface_vert_glsl[];
+extern char datatoc_raytrace_lib_glsl[];
+extern char datatoc_ssr_lib_glsl[];
+extern char datatoc_shadow_vert_glsl[];
+extern char datatoc_shadow_geom_glsl[];
+extern char datatoc_lightprobe_geom_glsl[];
+extern char datatoc_lightprobe_vert_glsl[];
+extern char datatoc_background_vert_glsl[];
+extern char datatoc_volumetric_vert_glsl[];
+extern char datatoc_volumetric_geom_glsl[];
+extern char datatoc_volumetric_frag_glsl[];
+extern char datatoc_volumetric_lib_glsl[];
+
+extern Material defmaterial;
+extern GlobalsUboStorage ts;
+
+/* *********** FUNCTIONS *********** */
+
+#if 0 /* Used only to generate the LUT values */
+static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
+{
+ struct GPUTexture *tex;
+ struct GPUFrameBuffer *fb = NULL;
+ static float samples_ct = 8192.0f;
+ static float inv_samples_ct = 1.0f / 8192.0f;
+
+ char *lib_str = NULL;
+
+ DynStr *ds_vert = BLI_dynstr_new();
+ BLI_dynstr_append(ds_vert, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_vert, datatoc_bsdf_sampling_lib_glsl);
+ lib_str = BLI_dynstr_get_cstring(ds_vert);
+ BLI_dynstr_free(ds_vert);
+
+ struct GPUShader *sh = DRW_shader_create_with_lib(
+ datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, datatoc_bsdf_lut_frag_glsl, lib_str,
+ "#define HAMMERSLEY_SIZE 8192\n"
+ "#define BRDF_LUT_SIZE 64\n"
+ "#define NOISE_SIZE 64\n");
+
+ DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_ct, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
+ DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
+
+ struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call_add(grp, geom, NULL);
+
+ float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
+
+ tex = DRW_texture_create_2D(w, h, DRW_TEX_RG_16, DRW_TEX_FILTER, (float *)texels);
+
+ DRWFboTexture tex_filter = {&tex, DRW_TEX_RG_16, DRW_TEX_FILTER};
+ DRW_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+
+ DRW_framebuffer_bind(fb);
+ DRW_draw_pass(pass);
+
+ float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data);
+
+ printf("{");
+ for (int i = 0; i < w*h * 3; i+=3) {
+ printf("%ff, %ff, ", data[i], data[i+1]); i+=3;
+ printf("%ff, %ff, ", data[i], data[i+1]); i+=3;
+ printf("%ff, %ff, ", data[i], data[i+1]); i+=3;
+ printf("%ff, %ff, \n", data[i], data[i+1]);
+ }
+ printf("}");
+
+ MEM_freeN(texels);
+ MEM_freeN(data);
+
+ return tex;
+}
+
+static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
+{
+ struct GPUTexture *tex;
+ struct GPUTexture *hammersley = create_hammersley_sample_texture(8192);
+ struct GPUFrameBuffer *fb = NULL;
+ static float samples_ct = 8192.0f;
+ static float a2 = 0.0f;
+ static float inv_samples_ct = 1.0f / 8192.0f;
+
+ char *frag_str = NULL;
+
+ DynStr *ds_vert = BLI_dynstr_new();
+ BLI_dynstr_append(ds_vert, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_vert, datatoc_bsdf_sampling_lib_glsl);
+ BLI_dynstr_append(ds_vert, datatoc_btdf_lut_frag_glsl);
+ frag_str = BLI_dynstr_get_cstring(ds_vert);
+ BLI_dynstr_free(ds_vert);
+
+ struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str,
+ "#define HAMMERSLEY_SIZE 8192\n"
+ "#define BRDF_LUT_SIZE 64\n"
+ "#define NOISE_SIZE 64\n"
+ "#define LUT_SIZE 64\n");
+
+ MEM_freeN(frag_str);
+
+ DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_float(grp, "a2", &a2, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_ct, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley);
+ DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
+
+ struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call_add(grp, geom, NULL);
+
+ float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
+
+ tex = DRW_texture_create_2D(w, h, DRW_TEX_R_16, DRW_TEX_FILTER, (float *)texels);
+
+ DRWFboTexture tex_filter = {&tex, DRW_TEX_R_16, DRW_TEX_FILTER};
+ DRW_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+
+ DRW_framebuffer_bind(fb);
+
+ float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
+
+ float inc = 1.0f / 31.0f;
+ float roughness = 1e-8f - inc;
+ FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w");
+ fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n");
+ do {
+ roughness += inc;
+ CLAMP(roughness, 1e-4f, 1.0f);
+ a2 = powf(roughness, 4.0f);
+ DRW_draw_pass(pass);
+
+ DRW_framebuffer_read_data(0, 0, w, h, 3, 0, data);
+
+#if 1
+ fprintf(f, "\t{\n\t\t");
+ for (int i = 0; i < w*h * 3; i+=3) {
+ fprintf(f, "%ff,", data[i]);
+ if (((i/3)+1) % 12 == 0) fprintf(f, "\n\t\t");
+ else fprintf(f, " ");
+ }
+ fprintf(f, "\n\t},\n");
+#else
+ for (int i = 0; i < w*h * 3; i+=3) {
+ if (data[i] < 0.01) printf(" ");
+ else if (data[i] < 0.3) printf(".");
+ else if (data[i] < 0.6) printf("+");
+ else if (data[i] < 0.9) printf("%%");
+ else printf("#");
+ if ((i/3+1) % 64 == 0) printf("\n");
+ }
+#endif
+
+ } while (roughness < 1.0f);
+ fprintf(f, "\n};\n");
+
+ fclose(f);
+
+ MEM_freeN(texels);
+ MEM_freeN(data);
+
+ return tex;
+}
+#endif
+/* XXX TODO define all shared resources in a shared place without duplication */
+struct GPUTexture *EEVEE_materials_get_util_tex(void)
+{
+ return e_data.util_tex;
+}
+
+static int eevee_material_shadow_option(int shadow_method)
+{
+ switch (shadow_method) {
+ case SHADOW_ESM: return VAR_MAT_ESM;
+ case SHADOW_VSM: return VAR_MAT_VSM;
+ default:
+ BLI_assert(!"Incorrect Shadow Method");
+ break;
+ }
+
+ return 0;
+}
+
+static char *eevee_get_defines(int options)
+{
+ char *str = NULL;
+
+ DynStr *ds = BLI_dynstr_new();
+ BLI_dynstr_appendf(ds, SHADER_DEFINES);
+
+ if ((options & VAR_MAT_MESH) != 0) {
+ BLI_dynstr_appendf(ds, "#define MESH_SHADER\n");
+ }
+ if ((options & VAR_MAT_HAIR) != 0) {
+ BLI_dynstr_appendf(ds, "#define HAIR_SHADER\n");
+ }
+ if ((options & VAR_MAT_PROBE) != 0) {
+ BLI_dynstr_appendf(ds, "#define PROBE_CAPTURE\n");
+ }
+ if ((options & VAR_MAT_FLAT) != 0) {
+ BLI_dynstr_appendf(ds, "#define USE_FLAT_NORMAL\n");
+ }
+ if ((options & VAR_MAT_CLIP) != 0) {
+ BLI_dynstr_appendf(ds, "#define USE_ALPHA_CLIP\n");
+ }
+ if ((options & VAR_MAT_SHADOW) != 0) {
+ BLI_dynstr_appendf(ds, "#define SHADOW_SHADER\n");
+ }
+ if ((options & VAR_MAT_HASH) != 0) {
+ BLI_dynstr_appendf(ds, "#define USE_ALPHA_HASH\n");
+ }
+ if ((options & VAR_MAT_BLEND) != 0) {
+ BLI_dynstr_appendf(ds, "#define USE_ALPHA_BLEND\n");
+ }
+ if ((options & VAR_MAT_MULT) != 0) {
+ BLI_dynstr_appendf(ds, "#define USE_MULTIPLY\n");
+ }
+ if ((options & VAR_MAT_REFRACT) != 0) {
+ BLI_dynstr_appendf(ds, "#define USE_REFRACTION\n");
+ }
+ if ((options & VAR_MAT_SSS) != 0) {
+ BLI_dynstr_appendf(ds, "#define USE_SSS\n");
+ }
+ if ((options & VAR_MAT_SSSALBED) != 0) {
+ BLI_dynstr_appendf(ds, "#define USE_SSS_ALBEDO\n");
+ }
+ if ((options & VAR_MAT_TRANSLUC) != 0) {
+ BLI_dynstr_appendf(ds, "#define USE_TRANSLUCENCY\n");
+ }
+ if ((options & VAR_MAT_VSM) != 0) {
+ BLI_dynstr_appendf(ds, "#define SHADOW_VSM\n");
+ }
+ if ((options & VAR_MAT_ESM) != 0) {
+ BLI_dynstr_appendf(ds, "#define SHADOW_ESM\n");
+ }
+ if (((options & VAR_MAT_VOLUME) != 0) && ((options & VAR_MAT_BLEND) != 0)) {
+ BLI_dynstr_appendf(ds, "#define USE_ALPHA_BLEND_VOLUMETRICS\n");
+ }
+
+ str = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return str;
+}
+
+static char *eevee_get_volume_defines(int options)
+{
+ char *str = NULL;
+
+ DynStr *ds = BLI_dynstr_new();
+ BLI_dynstr_appendf(ds, SHADER_DEFINES);
+ BLI_dynstr_appendf(ds, "#define VOLUMETRICS\n");
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ BLI_dynstr_appendf(ds, "#define MESH_SHADER\n");
+ }
+
+ str = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return str;
+}
+
+/**
+ * ssr_id can be null to disable ssr contribution.
+ **/
+static void add_standard_uniforms(
+ DRWShadingGroup *shgrp, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
+ int *ssr_id, float *refract_depth, bool use_ssrefraction, bool use_alpha_blend, bool use_sss)
+{
+ if (ssr_id == NULL || !vedata->stl->g_data->valid_double_buffer) {
+ static int no_ssr = -1.0f;
+ ssr_id = &no_ssr;
+ }
+ DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_int(shgrp, "light_count", &sldata->lamps->num_light, 1);
+ DRW_shgroup_uniform_int(shgrp, "probe_count", &sldata->probes->num_render_cube, 1);
+ DRW_shgroup_uniform_int(shgrp, "grid_count", &sldata->probes->num_render_grid, 1);
+ DRW_shgroup_uniform_int(shgrp, "planar_count", &sldata->probes->num_planar, 1);
+ DRW_shgroup_uniform_bool(shgrp, "specToggle", &sldata->probes->specular_toggle, 1);
+ DRW_shgroup_uniform_bool(shgrp, "ssrToggle", &sldata->probes->ssr_toggle, 1);
+ DRW_shgroup_uniform_float(shgrp, "lodCubeMax", &sldata->probes->lod_cube_max, 1);
+ DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
+ DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool);
+ DRW_shgroup_uniform_buffer(shgrp, "probePlanars", &vedata->txl->planar_pool);
+ DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool);
+ DRW_shgroup_uniform_int(shgrp, "irradianceVisibilitySize", &sldata->probes->irradiance_vis_size, 1);
+ DRW_shgroup_uniform_buffer(shgrp, "shadowTexture", &sldata->shadow_pool);
+ DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1);
+ DRW_shgroup_uniform_vec4(shgrp, "aoParameters[0]", &vedata->stl->effects->ao_dist, 2);
+ DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_buffer(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
+ DRW_shgroup_uniform_vec2(shgrp, "mipRatio[0]", (float *)vedata->stl->g_data->mip_ratio, 10);
+ DRW_shgroup_uniform_vec4(shgrp, "ssrParameters", &vedata->stl->effects->ssr_quality, 1);
+
+ if (refract_depth != NULL) {
+ DRW_shgroup_uniform_float(shgrp, "refractionDepth", refract_depth, 1);
+ }
+
+ if (use_ssrefraction) {
+ DRW_shgroup_uniform_buffer(shgrp, "colorBuffer", &vedata->txl->refract_color);
+ DRW_shgroup_uniform_float(shgrp, "borderFadeFactor", &vedata->stl->effects->ssr_border_fac, 1);
+ DRW_shgroup_uniform_float(shgrp, "maxRoughness", &vedata->stl->effects->ssr_max_roughness, 1);
+ DRW_shgroup_uniform_int(shgrp, "rayCount", &vedata->stl->effects->ssr_ray_count, 1);
+ }
+
+ if (vedata->stl->effects->use_ao) {
+ DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->gtao_horizons);
+ DRW_shgroup_uniform_ivec2(shgrp, "aoHorizonTexSize", (int *)vedata->stl->effects->ao_texsize, 1);
+ }
+ else {
+ /* Use shadow_pool as fallback to avoid sampling problem on certain platform, see: T52593 */
+ DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &sldata->shadow_pool);
+ }
+
+ if (vedata->stl->effects->use_volumetrics && use_alpha_blend) {
+ /* Do not use history buffers as they already have been swapped */
+ DRW_shgroup_uniform_buffer(shgrp, "inScattering", &vedata->txl->volume_scatter);
+ DRW_shgroup_uniform_buffer(shgrp, "inTransmittance", &vedata->txl->volume_transmittance);
+ DRW_shgroup_uniform_vec2(shgrp, "volume_uv_ratio", (float *)sldata->volumetrics->volume_coord_scale, 1);
+ DRW_shgroup_uniform_vec3(shgrp, "volume_param", (float *)sldata->volumetrics->depth_param, 1);
+ }
+
+ if (use_sss) {
+ DRW_shgroup_uniform_bool(shgrp, "sssToggle", &sldata->probes->sss_toggle, 1);
+ }
+}
+
+static void create_default_shader(int options)
+{
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, e_data.frag_shader_lib);
+ BLI_dynstr_append(ds_frag, datatoc_default_frag_glsl);
+ char *frag_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ char *defines = eevee_get_defines(options);
+
+ e_data.default_lit[options] = DRW_shader_create(datatoc_lit_surface_vert_glsl, NULL, frag_str, defines);
+
+ MEM_freeN(defines);
+ MEM_freeN(frag_str);
+}
+
+void EEVEE_update_util_texture(float offset)
+{
+
+ /* TODO: split this into 2 functions : one for init,
+ * and the other one that updates the noise with the offset. */
+ const int layers = 3 + 16;
+ float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * 64 * 64 * layers, "utils texels");
+ float (*texels_layer)[4] = texels;
+
+ /* Copy ltc_mat_ggx into 1st layer */
+ memcpy(texels_layer, ltc_mat_ggx, sizeof(float[4]) * 64 * 64);
+ texels_layer += 64 * 64;
+
+ /* Copy bsdf_split_sum_ggx into 2nd layer red and green channels.
+ Copy ltc_mag_ggx into 2nd layer blue channel. */
+ for (int i = 0; i < 64 * 64; i++) {
+ texels_layer[i][0] = bsdf_split_sum_ggx[i * 2 + 0];
+ texels_layer[i][1] = bsdf_split_sum_ggx[i * 2 + 1];
+ texels_layer[i][2] = ltc_mag_ggx[i];
+ }
+ texels_layer += 64 * 64;
+
+ /* Copy blue noise in 3rd layer */
+ for (int i = 0; i < 64 * 64; i++) {
+ float noise;
+ noise = fmod(blue_noise[i][0] + offset, 1.0f);
+ texels_layer[i][0] = noise;
+
+ noise = fmod(blue_noise[i][1] + offset, 1.0f);
+ texels_layer[i][1] = noise * 0.5f + 0.5f;
+ texels_layer[i][2] = cosf(noise * 2.0f * M_PI);
+ texels_layer[i][3] = sinf(noise * 2.0f * M_PI);
+ }
+ texels_layer += 64 * 64;
+
+ /* Copy Refraction GGX LUT in layer 4 - 20 */
+ for (int j = 0; j < 16; ++j) {
+ for (int i = 0; i < 64 * 64; i++) {
+ texels_layer[i][0] = btdf_split_sum_ggx[j * 2][i];
+ texels_layer[i][1] = btdf_split_sum_ggx[j * 2][i];
+ texels_layer[i][2] = btdf_split_sum_ggx[j * 2][i];
+ texels_layer[i][3] = btdf_split_sum_ggx[j * 2][i];
+ }
+ texels_layer += 64 * 64;
+ }
+
+ if (e_data.util_tex == NULL) {
+ e_data.util_tex = DRW_texture_create_2D_array(
+ 64, 64, layers, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_WRAP, (float *)texels);
+ }
+ else {
+ DRW_texture_update(e_data.util_tex, (float *)texels);
+ }
+
+ MEM_freeN(texels);
+}
+
+void EEVEE_materials_init(EEVEE_StorageList *stl)
+{
+ if (!e_data.frag_shader_lib) {
+ char *frag_str = NULL;
+
+ /* Shaders */
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_raytrace_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_ssr_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lamps_lib_glsl);
+ for (int i = 0; i < 7; ++i) {
+ /* Add one for each Closure */
+ BLI_dynstr_append(ds_frag, datatoc_lit_surface_frag_glsl);
+ }
+ BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl);
+ e_data.frag_shader_lib = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lamps_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_volumetric_frag_glsl);
+ e_data.volume_shader_lib = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, e_data.frag_shader_lib);
+ BLI_dynstr_append(ds_frag, datatoc_default_frag_glsl);
+ frag_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.default_background = DRW_shader_create(
+ datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl,
+ NULL);
+
+ e_data.default_prepass_sh = DRW_shader_create(
+ datatoc_prepass_vert_glsl, NULL, datatoc_prepass_frag_glsl,
+ NULL);
+
+ e_data.default_prepass_clip_sh = DRW_shader_create(
+ datatoc_prepass_vert_glsl, NULL, datatoc_prepass_frag_glsl,
+ "#define CLIP_PLANES\n");
+
+ MEM_freeN(frag_str);
+
+ EEVEE_update_util_texture(0.0f);
+ }
+
+ {
+ /* Update viewvecs */
+ const bool is_persp = DRW_viewport_is_persp_get();
+ float invproj[4][4], winmat[4][4];
+ /* 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}
+ };
+
+ /* invert the view matrix */
+ DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
+ invert_m4_m4(invproj, winmat);
+
+ /* convert the view vectors to view space */
+ for (int 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(stl->g_data->viewvecs[0], viewvecs[0]);
+ copy_v4_v4(stl->g_data->viewvecs[1], viewvecs[1]);
+
+ /* we need to store the differences */
+ stl->g_data->viewvecs[1][0] -= viewvecs[0][0];
+ stl->g_data->viewvecs[1][1] = viewvecs[2][1] - 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]);
+ stl->g_data->viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
+ }
+ }
+}
+
+struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, World *wo)
+{
+ const void *engine = &DRW_engine_viewport_eevee_type;
+ const int options = VAR_WORLD_PROBE;
+
+ GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine, options);
+ if (mat != NULL) {
+ return mat;
+ }
+ return GPU_material_from_nodetree(
+ scene, wo->nodetree, &wo->gpumaterial, engine, options,
+ datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib,
+ SHADER_DEFINES "#define PROBE_CAPTURE\n");
+}
+
+struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, World *wo)
+{
+ const void *engine = &DRW_engine_viewport_eevee_type;
+ int options = VAR_WORLD_BACKGROUND;
+
+ GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine, options);
+ if (mat != NULL) {
+ return mat;
+ }
+ return GPU_material_from_nodetree(
+ scene, wo->nodetree, &wo->gpumaterial, engine, options,
+ datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib,
+ SHADER_DEFINES "#define WORLD_BACKGROUND\n");
+}
+
+struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *wo)
+{
+ const void *engine = &DRW_engine_viewport_eevee_type;
+ int options = VAR_WORLD_VOLUME;
+
+ GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine, options);
+ if (mat != NULL) {
+ return mat;
+ }
+
+ char *defines = eevee_get_volume_defines(options);
+
+ mat = GPU_material_from_nodetree(
+ scene, wo->nodetree, &wo->gpumaterial, engine, options,
+ datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, e_data.volume_shader_lib,
+ defines);
+
+ MEM_freeN(defines);
+
+ return mat;
+}
+
+struct GPUMaterial *EEVEE_material_mesh_get(
+ struct Scene *scene, Material *ma, EEVEE_Data *vedata,
+ bool use_blend, bool use_multiply, bool use_refract, bool use_sss, bool use_translucency, int shadow_method)
+{
+ const void *engine = &DRW_engine_viewport_eevee_type;
+ int options = VAR_MAT_MESH;
+
+ if (use_blend) options |= VAR_MAT_BLEND;
+ if (use_multiply) options |= VAR_MAT_MULT;
+ if (use_refract) options |= VAR_MAT_REFRACT;
+ if (use_sss) options |= VAR_MAT_SSS;
+ if (use_sss && vedata->stl->effects->sss_separate_albedo) options |= VAR_MAT_SSSALBED;
+ if (use_translucency) options |= VAR_MAT_TRANSLUC;
+ if (vedata->stl->effects->use_volumetrics && use_blend) options |= VAR_MAT_VOLUME;
+
+ options |= eevee_material_shadow_option(shadow_method);
+
+ GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine, options);
+ if (mat) {
+ return mat;
+ }
+
+ char *defines = eevee_get_defines(options);
+
+ mat = GPU_material_from_nodetree(
+ scene, ma->nodetree, &ma->gpumaterial, engine, options,
+ datatoc_lit_surface_vert_glsl, NULL, e_data.frag_shader_lib,
+ defines);
+
+ MEM_freeN(defines);
+
+ return mat;
+}
+
+struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma)
+{
+ const void *engine = &DRW_engine_viewport_eevee_type;
+ int options = VAR_MAT_VOLUME;
+
+ GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine, options);
+ if (mat != NULL) {
+ return mat;
+ }
+
+ char *defines = eevee_get_volume_defines(options);
+
+ mat = GPU_material_from_nodetree(
+ scene, ma->nodetree, &ma->gpumaterial, engine, options,
+ datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, e_data.volume_shader_lib,
+ defines);
+
+ MEM_freeN(defines);
+
+ return mat;
+}
+
+struct GPUMaterial *EEVEE_material_mesh_depth_get(
+ struct Scene *scene, Material *ma,
+ bool use_hashed_alpha, bool is_shadow)
+{
+ const void *engine = &DRW_engine_viewport_eevee_type;
+ int options = VAR_MAT_MESH;
+
+ if (use_hashed_alpha) {
+ options |= VAR_MAT_HASH;
+ }
+ else {
+ options |= VAR_MAT_CLIP;
+ }
+
+ if (is_shadow)
+ options |= VAR_MAT_SHADOW;
+
+ GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine, options);
+ if (mat) {
+ return mat;
+ }
+
+ char *defines = eevee_get_defines(options);
+
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, e_data.frag_shader_lib);
+ BLI_dynstr_append(ds_frag, datatoc_prepass_frag_glsl);
+ char *frag_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ mat = GPU_material_from_nodetree(
+ scene, ma->nodetree, &ma->gpumaterial, engine, options,
+ (is_shadow) ? datatoc_shadow_vert_glsl : datatoc_lit_surface_vert_glsl,
+ (is_shadow) ? datatoc_shadow_geom_glsl : NULL,
+ frag_str,
+ defines);
+
+ MEM_freeN(frag_str);
+ MEM_freeN(defines);
+
+ return mat;
+}
+
+struct GPUMaterial *EEVEE_material_hair_get(
+ struct Scene *scene, Material *ma, int shadow_method)
+{
+ const void *engine = &DRW_engine_viewport_eevee_type;
+ int options = VAR_MAT_MESH | VAR_MAT_HAIR;
+
+ options |= eevee_material_shadow_option(shadow_method);
+
+ GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine, options);
+ if (mat) {
+ return mat;
+ }
+
+ char *defines = eevee_get_defines(options);
+
+ mat = GPU_material_from_nodetree(
+ scene, ma->nodetree, &ma->gpumaterial, engine, options,
+ datatoc_lit_surface_vert_glsl, NULL, e_data.frag_shader_lib,
+ defines);
+
+ MEM_freeN(defines);
+
+ return mat;
+}
+
+/**
+ * Create a default shading group inside the given pass.
+ **/
+static struct DRWShadingGroup *EEVEE_default_shading_group_create(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWPass *pass,
+ bool is_hair, bool is_flat_normal, bool use_blend, bool use_ssr, int shadow_method)
+{
+ static int ssr_id;
+ ssr_id = (use_ssr) ? 1 : -1;
+ int options = VAR_MAT_MESH;
+
+ if (is_hair) options |= VAR_MAT_HAIR;
+ if (is_flat_normal) options |= VAR_MAT_FLAT;
+ if (use_blend) options |= VAR_MAT_BLEND;
+ if (vedata->stl->effects->use_volumetrics && use_blend) options |= VAR_MAT_VOLUME;
+
+ options |= eevee_material_shadow_option(shadow_method);
+
+ if (e_data.default_lit[options] == NULL) {
+ create_default_shader(options);
+ }
+
+ DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, use_blend, false);
+
+ return shgrp;
+}
+
+/**
+ * Create a default shading group inside the default pass without standard uniforms.
+ **/
+static struct DRWShadingGroup *EEVEE_default_shading_group_get(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
+ bool is_hair, bool is_flat_normal, bool use_ssr, int shadow_method)
+{
+ static int ssr_id;
+ ssr_id = (use_ssr) ? 1 : -1;
+ int options = VAR_MAT_MESH;
+
+ if (is_hair) options |= VAR_MAT_HAIR;
+ if (is_flat_normal) options |= VAR_MAT_FLAT;
+
+ options |= eevee_material_shadow_option(shadow_method);
+
+ if (e_data.default_lit[options] == NULL) {
+ create_default_shader(options);
+ }
+
+ if (vedata->psl->default_pass[options] == NULL) {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE;
+ vedata->psl->default_pass[options] = DRW_pass_create("Default Lit Pass", state);
+
+ DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false, false);
+ }
+
+ return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
+}
+
+void EEVEE_materials_cache_init(EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+
+ {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+ /* Global AO Switch*/
+ stl->effects->use_ao = BKE_collection_engine_property_value_get_bool(props, "gtao_enable");
+ stl->effects->use_bent_normals = BKE_collection_engine_property_value_get_bool(props, "gtao_use_bent_normals");
+ /* SSR switch */
+ stl->effects->use_ssr = BKE_collection_engine_property_value_get_bool(props, "ssr_enable");
+ /* Volumetrics */
+ stl->effects->use_volumetrics = BKE_collection_engine_property_value_get_bool(props, "volumetric_enable");
+ }
+
+ /* Create Material Ghash */
+ {
+ stl->g_data->material_hash = BLI_ghash_ptr_new("Eevee_material ghash");
+ stl->g_data->hair_material_hash = BLI_ghash_ptr_new("Eevee_hair_material ghash");
+ }
+
+ {
+ psl->background_pass = DRW_pass_create("Background Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+
+ struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+ DRWShadingGroup *grp = NULL;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ World *wo = scene->world;
+
+ float *col = ts.colorBackground;
+
+ if (wo) {
+ col = &wo->horr;
+
+ if (wo->use_nodes && wo->nodetree) {
+ struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo);
+ grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
+
+ if (grp) {
+ DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ DRW_shgroup_call_add(grp, geom, NULL);
+ }
+ else {
+ /* Shader failed : pink background */
+ static float pink[3] = {1.0f, 0.0f, 1.0f};
+ col = pink;
+ }
+ }
+ }
+
+ /* Fallback if shader fails or if not using nodetree. */
+ if (grp == NULL) {
+ grp = DRW_shgroup_create(e_data.default_background, psl->background_pass);
+ DRW_shgroup_uniform_vec3(grp, "color", col, 1);
+ DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ DRW_shgroup_call_add(grp, geom, NULL);
+ }
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE;
+ psl->depth_pass = DRW_pass_create("Depth Pass", state);
+ stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh, psl->depth_pass);
+
+ state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK;
+ psl->depth_pass_cull = DRW_pass_create("Depth Pass Cull", state);
+ stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh, psl->depth_pass_cull);
+
+ state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE;
+ psl->depth_pass_clip = DRW_pass_create("Depth Pass Clip", state);
+ stl->g_data->depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->depth_pass_clip);
+
+ state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK;
+ psl->depth_pass_clip_cull = DRW_pass_create("Depth Pass Cull Clip", state);
+ stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->depth_pass_clip_cull);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE;
+ psl->material_pass = DRW_pass_create("Material Shader Pass", state);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE;
+ psl->refract_depth_pass = DRW_pass_create("Refract Depth Pass", state);
+ stl->g_data->refract_depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh, psl->refract_depth_pass);
+
+ state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK;
+ psl->refract_depth_pass_cull = DRW_pass_create("Refract Depth Pass Cull", state);
+ stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh, psl->refract_depth_pass_cull);
+
+ state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE;
+ psl->refract_depth_pass_clip = DRW_pass_create("Refract Depth Pass Clip", state);
+ stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip);
+
+ state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK;
+ psl->refract_depth_pass_clip_cull = DRW_pass_create("Refract Depth Pass Cull Clip", state);
+ stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE;
+ psl->refract_pass = DRW_pass_create("Opaque Refraction Pass", state);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL;
+ psl->sss_pass = DRW_pass_create("Subsurface Pass", state);
+ e_data.sss_count = 0;
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE;
+ psl->transparent_pass = DRW_pass_create("Material Transparent Pass", state);
+ }
+}
+
+#define ADD_SHGROUP_CALL(shgrp, ob, geom) do { \
+ if (is_sculpt_mode_draw) { \
+ DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat); \
+ } \
+ else { \
+ DRW_shgroup_call_object_add(shgrp, geom, ob); \
+ } \
+} while (0)
+
+#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom) do { \
+ if (shgrp) { \
+ ADD_SHGROUP_CALL(shgrp, ob, geom); \
+ } \
+} while (0)
+
+typedef struct EeveeMaterialShadingGroups {
+ struct DRWShadingGroup *shading_grp;
+ struct DRWShadingGroup *depth_grp;
+ struct DRWShadingGroup *depth_clip_grp;
+} EeveeMaterialShadingGroups;
+
+static void material_opaque(
+ Material *ma, GHash *material_hash, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
+ bool do_cull, bool use_flat_nor, struct GPUMaterial **gpumat, struct GPUMaterial **gpumat_depth,
+ struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth, struct DRWShadingGroup **shgrp_depth_clip)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_LampsInfo *linfo = sldata->lamps;
+
+ float *color_p = &ma->r;
+ float *metal_p = &ma->ray_mirror;
+ float *spec_p = &ma->spec;
+ float *rough_p = &ma->gloss_mir;
+
+ const bool use_gpumat = (ma->use_nodes && ma->nodetree);
+ const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0);
+ const bool use_sss = ((ma->blend_flag & MA_BL_SS_SUBSURFACE) != 0) && ((stl->effects->enabled_effects & EFFECT_SSS) != 0);
+ const bool use_translucency = ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0) && ((stl->effects->enabled_effects & EFFECT_SSS) != 0);
+
+ EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma);
+
+ if (emsg) {
+ *shgrp = emsg->shading_grp;
+ *shgrp_depth = emsg->depth_grp;
+ *shgrp_depth_clip = emsg->depth_clip_grp;
+
+ /* This will have been created already, just perform a lookup. */
+ *gpumat = (use_gpumat) ? EEVEE_material_mesh_get(
+ scene, ma, vedata, false, false, use_refract, use_sss, use_translucency, linfo->shadow_method) : NULL;
+ *gpumat_depth = (use_gpumat) ? EEVEE_material_mesh_depth_get(
+ scene, ma, (ma->blend_method == MA_BM_HASHED), false) : NULL;
+ return;
+ }
+
+ if (use_gpumat) {
+ /* Shading */
+ *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, false, use_refract,
+ use_sss, use_translucency, linfo->shadow_method);
+
+ *shgrp = DRW_shgroup_material_create(*gpumat,
+ (use_refract) ? psl->refract_pass :
+ (use_sss) ? psl->sss_pass : psl->material_pass);
+ if (*shgrp) {
+ static int no_ssr = -1;
+ static int first_ssr = 1;
+ int *ssr_id = (stl->effects->use_ssr && !use_refract) ? &first_ssr : &no_ssr;
+ add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false, use_sss);
+
+ if (use_sss) {
+ struct GPUTexture *sss_tex_profile = NULL;
+ struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(*gpumat,
+ stl->effects->sss_sample_count,
+ &sss_tex_profile);
+
+ if (sss_profile) {
+ if (use_translucency) {
+ DRW_shgroup_uniform_block(*shgrp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_texture(*shgrp, "sssTexProfile", sss_tex_profile);
+ }
+
+ DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1);
+ EEVEE_subsurface_add_pass(vedata, e_data.sss_count + 1, sss_profile);
+ e_data.sss_count++;
+ }
+ }
+ }
+ else {
+ /* Shader failed : pink color */
+ static float col[3] = {1.0f, 0.0f, 1.0f};
+ static float half = 0.5f;
+
+ color_p = col;
+ metal_p = spec_p = rough_p = &half;
+ }
+
+ /* Alpha CLipped : Discard pixel from depth pass, then
+ * fail the depth test for shading. */
+ if (ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED)) {
+ *gpumat_depth = EEVEE_material_mesh_depth_get(scene, ma,
+ (ma->blend_method == MA_BM_HASHED), false);
+
+ if (use_refract) {
+ *shgrp_depth = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass);
+ *shgrp_depth_clip = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip);
+ }
+ else {
+ *shgrp_depth = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass);
+ *shgrp_depth_clip = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip);
+ }
+
+ if (*shgrp_depth != NULL) {
+ add_standard_uniforms(*shgrp_depth, sldata, vedata, NULL, NULL, false, false, false);
+
+ if (ma->blend_method == MA_BM_CLIP) {
+ DRW_shgroup_uniform_float(*shgrp_depth, "alphaThreshold", &ma->alpha_threshold, 1);
+ DRW_shgroup_uniform_float(*shgrp_depth_clip, "alphaThreshold", &ma->alpha_threshold, 1);
+ }
+ }
+ }
+ }
+
+ /* Fallback to default shader */
+ if (*shgrp == NULL) {
+ *shgrp = EEVEE_default_shading_group_get(sldata, vedata, false, use_flat_nor, stl->effects->use_ssr, linfo->shadow_method);
+ DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1);
+ DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1);
+ DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1);
+ DRW_shgroup_uniform_float(*shgrp, "roughness", rough_p, 1);
+ }
+
+ /* Fallback default depth prepass */
+ if (*shgrp_depth == NULL) {
+ if (use_refract) {
+ *shgrp_depth = (do_cull) ? stl->g_data->refract_depth_shgrp_cull : stl->g_data->refract_depth_shgrp;
+ *shgrp_depth_clip = (do_cull) ? stl->g_data->refract_depth_shgrp_clip_cull : stl->g_data->refract_depth_shgrp_clip;
+ }
+ else {
+ *shgrp_depth = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp;
+ *shgrp_depth_clip = (do_cull) ? stl->g_data->depth_shgrp_clip_cull : stl->g_data->depth_shgrp_clip;
+ }
+ }
+
+ emsg = MEM_mallocN(sizeof("EeveeMaterialShadingGroups"), "EeveeMaterialShadingGroups");
+ emsg->shading_grp = *shgrp;
+ emsg->depth_grp = *shgrp_depth;
+ emsg->depth_clip_grp = *shgrp_depth_clip;
+ BLI_ghash_insert(material_hash, ma, emsg);
+}
+
+static void material_transparent(
+ Material *ma, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
+ bool do_cull, bool use_flat_nor, struct GPUMaterial **gpumat, struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_LampsInfo *linfo = sldata->lamps;
+
+ const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0);
+
+ float *color_p = &ma->r;
+ float *metal_p = &ma->ray_mirror;
+ float *spec_p = &ma->spec;
+ float *rough_p = &ma->gloss_mir;
+
+ if (ma->use_nodes && ma->nodetree) {
+ /* Shading */
+ *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, (ma->blend_method == MA_BM_MULTIPLY), use_refract,
+ false, false, linfo->shadow_method);
+
+ *shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass);
+ if (*shgrp) {
+ static int ssr_id = -1; /* TODO transparent SSR */
+ bool use_blend = (ma->blend_method & MA_BM_BLEND) != 0;
+ add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend, false);
+ }
+ else {
+ /* Shader failed : pink color */
+ static float col[3] = {1.0f, 0.0f, 1.0f};
+ static float half = 0.5f;
+
+ color_p = col;
+ metal_p = spec_p = rough_p = &half;
+ }
+ }
+
+ /* Fallback to default shader */
+ if (*shgrp == NULL) {
+ *shgrp = EEVEE_default_shading_group_create(
+ sldata, vedata, psl->transparent_pass,
+ false, use_flat_nor, true, false, linfo->shadow_method);
+ DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1);
+ DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1);
+ DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1);
+ DRW_shgroup_uniform_float(*shgrp, "roughness", rough_p, 1);
+ }
+
+ const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKSIDE) != 0);
+
+ DRWState all_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_CULL_BACK | DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_EQUAL |
+ DRW_STATE_BLEND | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY;
+
+ DRWState cur_state = DRW_STATE_WRITE_COLOR;
+ cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS;
+ cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
+
+ switch (ma->blend_method) {
+ case MA_BM_ADD:
+ cur_state |= DRW_STATE_ADDITIVE;
+ break;
+ case MA_BM_MULTIPLY:
+ cur_state |= DRW_STATE_MULTIPLY;
+ break;
+ case MA_BM_BLEND:
+ cur_state |= DRW_STATE_BLEND;
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ /* Disable other blend modes and use the one we want. */
+ DRW_shgroup_state_disable(*shgrp, all_state);
+ DRW_shgroup_state_enable(*shgrp, cur_state);
+
+ /* Depth prepass */
+ if (use_prepass) {
+ *shgrp_depth = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass);
+
+ cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
+
+ DRW_shgroup_state_disable(*shgrp_depth, all_state);
+ DRW_shgroup_state_enable(*shgrp_depth, cur_state);
+ }
+}
+
+void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob)
+{
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ GHash *material_hash = stl->g_data->material_hash;
+
+ IDProperty *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, "");
+ const bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
+ const bool is_active = (ob == draw_ctx->obact);
+ const bool is_sculpt_mode = is_active && (ob->mode & OB_MODE_SCULPT) != 0;
+#if 0
+ const bool is_sculpt_mode_draw = is_sculpt_mode && (draw_ctx->v3d->flag2 & V3D_SHOW_MODE_SHADE_OVERRIDE) == 0;
+#else
+ /* For now just force fully shaded with eevee when supported. */
+ const bool is_sculpt_mode_draw =
+ is_sculpt_mode &&
+ ((ob->sculpt && ob->sculpt->pbvh) && (BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES));
+#endif
+ const bool is_default_mode_shader = is_sculpt_mode;
+
+ /* First get materials for this mesh. */
+ if (ELEM(ob->type, OB_MESH)) {
+ const int materials_len = MAX2(1, (is_sculpt_mode_draw ? 1 : ob->totcol));
+
+ struct DRWShadingGroup **shgrp_array = BLI_array_alloca(shgrp_array, materials_len);
+ struct DRWShadingGroup **shgrp_depth_array = BLI_array_alloca(shgrp_depth_array, materials_len);
+ struct DRWShadingGroup **shgrp_depth_clip_array = BLI_array_alloca(shgrp_depth_clip_array, materials_len);
+
+ struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
+ struct GPUMaterial **gpumat_depth_array = BLI_array_alloca(gpumat_array, materials_len);
+
+ bool use_flat_nor = false;
+
+ if (is_default_mode_shader) {
+ if (is_sculpt_mode_draw) {
+ use_flat_nor = DRW_object_is_flat_normal(ob);
+ }
+ }
+
+ for (int i = 0; i < materials_len; ++i) {
+ Material *ma;
+
+ if (is_sculpt_mode_draw) {
+ ma = NULL;
+ }
+ else {
+ ma = give_current_material(ob, i + 1);
+ }
+
+ gpumat_array[i] = NULL;
+ gpumat_depth_array[i] = NULL;
+ shgrp_array[i] = NULL;
+ shgrp_depth_array[i] = NULL;
+ shgrp_depth_clip_array[i] = NULL;
+
+ if (ma == NULL)
+ ma = &defmaterial;
+
+ switch (ma->blend_method) {
+ case MA_BM_SOLID:
+ case MA_BM_CLIP:
+ case MA_BM_HASHED:
+ material_opaque(ma, material_hash, sldata, vedata, do_cull, use_flat_nor,
+ &gpumat_array[i], &gpumat_depth_array[i],
+ &shgrp_array[i], &shgrp_depth_array[i], &shgrp_depth_clip_array[i]);
+ break;
+ case MA_BM_ADD:
+ case MA_BM_MULTIPLY:
+ case MA_BM_BLEND:
+ material_transparent(ma, sldata, vedata, do_cull, use_flat_nor,
+ &gpumat_array[i], &shgrp_array[i], &shgrp_depth_array[i]);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+ }
+
+ if (is_sculpt_mode && is_sculpt_mode_draw == false) {
+ DRW_cache_mesh_sculpt_coords_ensure(ob);
+ }
+
+ /* Only support single volume material for now. */
+ /* XXX We rely on the previously compiled surface shader
+ * to know if the material has a "volume nodetree".
+ */
+ bool use_volume_material = (gpumat_array[0] && GPU_material_use_domain_volume(gpumat_array[0]));
+
+ /* Get per-material split surface */
+ struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len);
+ if (mat_geom) {
+ for (int i = 0; i < materials_len; ++i) {
+ Material *ma = give_current_material(ob, i + 1);
+
+ if (ma == NULL)
+ ma = &defmaterial;
+
+ /* Do not render surface if we are rendering a volume object
+ * and do not have a surface closure. */
+ if (use_volume_material &&
+ (gpumat_array[i] && !GPU_material_use_domain_surface(gpumat_array[i])))
+ {
+ continue;
+ }
+
+ /* Shading pass */
+ ADD_SHGROUP_CALL(shgrp_array[i], ob, mat_geom[i]);
+
+ /* Depth Prepass */
+ ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, mat_geom[i]);
+ ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, mat_geom[i]);
+
+ /* Shadow Pass */
+ if (ma->use_nodes && ma->nodetree && (ma->blend_method != MA_BM_SOLID)) {
+ struct GPUMaterial *gpumat;
+ switch (ma->blend_shadow) {
+ case MA_BS_SOLID:
+ EEVEE_lights_cache_shcaster_add(sldata, psl, mat_geom[i], ob->obmat);
+ break;
+ case MA_BS_CLIP:
+ gpumat = EEVEE_material_mesh_depth_get(scene, ma, false, true);
+ EEVEE_lights_cache_shcaster_material_add(sldata, psl, gpumat, mat_geom[i], ob, ob->obmat, &ma->alpha_threshold);
+ break;
+ case MA_BS_HASHED:
+ gpumat = EEVEE_material_mesh_depth_get(scene, ma, true, true);
+ EEVEE_lights_cache_shcaster_material_add(sldata, psl, gpumat, mat_geom[i], ob, ob->obmat, NULL);
+ break;
+ case MA_BS_NONE:
+ default:
+ break;
+ }
+ }
+ else {
+ EEVEE_lights_cache_shcaster_add(sldata, psl, mat_geom[i], ob->obmat);
+ }
+ }
+ }
+
+ /* Volumetrics */
+ if (vedata->stl->effects->use_volumetrics && use_volume_material) {
+ EEVEE_volumes_cache_object_add(sldata, vedata, scene, ob);
+ }
+ }
+
+ if (ob->type == OB_MESH) {
+ if (ob != draw_ctx->scene->obedit) {
+ material_hash = stl->g_data->hair_material_hash;
+
+ for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_ParticleSystem) {
+ ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
+
+ if (psys_check_enabled(ob, psys, false)) {
+ ParticleSettings *part = psys->part;
+ int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
+
+ if (draw_as == PART_DRAW_PATH && (psys->pathcache || psys->childcache)) {
+ struct Gwn_Batch *hair_geom = DRW_cache_particles_get_hair(psys, md);
+ DRWShadingGroup *shgrp = NULL;
+ Material *ma = give_current_material(ob, part->omat);
+ static float mat[4][4];
+
+ unit_m4(mat);
+
+ if (ma == NULL) {
+ ma = &defmaterial;
+ }
+
+ float *color_p = &ma->r;
+ float *metal_p = &ma->ray_mirror;
+ float *spec_p = &ma->spec;
+ float *rough_p = &ma->gloss_mir;
+
+ DRW_shgroup_call_add(stl->g_data->depth_shgrp, hair_geom, mat);
+ DRW_shgroup_call_add(stl->g_data->depth_shgrp_clip, hair_geom, mat);
+
+ shgrp = BLI_ghash_lookup(material_hash, (const void *)ma);
+
+ if (shgrp) {
+ DRW_shgroup_call_add(shgrp, hair_geom, mat);
+ }
+ else {
+ if (ma->use_nodes && ma->nodetree) {
+ struct GPUMaterial *gpumat = EEVEE_material_hair_get(scene, ma, sldata->lamps->shadow_method);
+
+ shgrp = DRW_shgroup_material_create(gpumat, psl->material_pass);
+ if (shgrp) {
+ add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false, false, false);
+
+ BLI_ghash_insert(material_hash, ma, shgrp);
+
+ DRW_shgroup_call_add(shgrp, hair_geom, mat);
+ }
+ else {
+ /* Shader failed : pink color */
+ static float col[3] = {1.0f, 0.0f, 1.0f};
+ static float half = 0.5f;
+
+ color_p = col;
+ metal_p = spec_p = rough_p = &half;
+ }
+ }
+
+ /* Fallback to default shader */
+ if (shgrp == NULL) {
+ shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, false, stl->effects->use_ssr, sldata->lamps->shadow_method);
+ DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
+ DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
+ DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
+ DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1);
+
+ BLI_ghash_insert(material_hash, ma, shgrp);
+
+ DRW_shgroup_call_add(shgrp, hair_geom, mat);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void EEVEE_materials_cache_finish(EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+
+ BLI_ghash_free(stl->g_data->material_hash, NULL, MEM_freeN);
+ BLI_ghash_free(stl->g_data->hair_material_hash, NULL, NULL);
+}
+
+void EEVEE_materials_free(void)
+{
+ for (int i = 0; i < VAR_MAT_MAX; ++i) {
+ DRW_SHADER_FREE_SAFE(e_data.default_lit[i]);
+ }
+ MEM_SAFE_FREE(e_data.frag_shader_lib);
+ MEM_SAFE_FREE(e_data.volume_shader_lib);
+ DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh);
+ DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh);
+ DRW_SHADER_FREE_SAFE(e_data.default_background);
+ DRW_TEXTURE_FREE_SAFE(e_data.util_tex);
+}
+
+void EEVEE_draw_default_passes(EEVEE_PassList *psl)
+{
+ for (int i = 0; i < VAR_MAT_MAX; ++i) {
+ if (psl->default_pass[i]) {
+ DRW_draw_pass(psl->default_pass[i]);
+ }
+ }
+}
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
new file mode 100644
index 00000000000..d5e0a05f9ed
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -0,0 +1,206 @@
+/*
+ * 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 eevee_motion_blur.c
+ * \ingroup draw_engine
+ *
+ * Gather all screen space effects technique such as Bloom, Motion Blur, DoF, SSAO, SSR, ...
+ */
+
+#include "DRW_render.h"
+
+#include "BKE_global.h" /* for G.debug_value */
+#include "BKE_camera.h"
+#include "BKE_object.h"
+#include "BKE_animsys.h"
+#include "BKE_screen.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_screen_types.h"
+
+#include "ED_screen.h"
+
+#include "DEG_depsgraph.h"
+
+#include "eevee_private.h"
+#include "GPU_texture.h"
+
+static struct {
+ /* Motion Blur */
+ struct GPUShader *motion_blur_sh;
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_effect_motion_blur_frag_glsl[];
+
+static void eevee_motion_blur_camera_get_matrix_at_time(
+ const bContext *C, Scene *scene, ARegion *ar, RegionView3D *rv3d, View3D *v3d, Object *camera, float time, float r_mat[4][4])
+{
+ EvaluationContext eval_ctx;
+ float obmat[4][4];
+
+ /* HACK */
+ Object cam_cpy; Camera camdata_cpy;
+ memcpy(&cam_cpy, camera, sizeof(cam_cpy));
+ memcpy(&camdata_cpy, camera->data, sizeof(camdata_cpy));
+ cam_cpy.data = &camdata_cpy;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ /* Past matrix */
+ /* FIXME : This is a temporal solution that does not take care of parent animations */
+ /* Recalc Anim manualy */
+ BKE_animsys_evaluate_animdata(scene, &cam_cpy.id, cam_cpy.adt, time, ADT_RECALC_ALL);
+ BKE_animsys_evaluate_animdata(scene, &camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL);
+ BKE_object_where_is_calc_time(&eval_ctx, scene, &cam_cpy, time);
+
+ /* Compute winmat */
+ CameraParams params;
+ BKE_camera_params_init(&params);
+
+ /* copy of BKE_camera_params_from_view3d */
+ {
+ params.lens = v3d->lens;
+ params.clipsta = v3d->near;
+ params.clipend = v3d->far;
+
+ /* camera view */
+ BKE_camera_params_from_object(&params, &cam_cpy);
+
+ params.zoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
+
+ params.offsetx = 2.0f * rv3d->camdx * params.zoom;
+ params.offsety = 2.0f * rv3d->camdy * params.zoom;
+
+ params.shiftx *= params.zoom;
+ params.shifty *= params.zoom;
+
+ params.zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB / params.zoom;
+ }
+
+ BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
+ BKE_camera_params_compute_matrix(&params);
+
+ /* FIXME Should be done per view (MULTIVIEW) */
+ normalize_m4_m4(obmat, cam_cpy.obmat);
+ invert_m4(obmat);
+ mul_m4_m4m4(r_mat, params.winmat, obmat);
+}
+
+static void eevee_create_shader_motion_blur(void)
+{
+ e_data.motion_blur_sh = DRW_shader_create_fullscreen(datatoc_effect_motion_blur_frag_glsl, NULL);
+}
+
+int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ Scene *scene = draw_ctx->scene;
+ View3D *v3d = draw_ctx->v3d;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ ARegion *ar = draw_ctx->ar;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ if (BKE_collection_engine_property_value_get_bool(props, "motion_blur_enable") && (draw_ctx->evil_C != NULL)) {
+ /* Update Motion Blur Matrices */
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ float persmat[4][4];
+ float ctime = BKE_scene_frame_get(scene);
+ float delta = BKE_collection_engine_property_value_get_float(props, "motion_blur_shutter");
+
+ /* Current matrix */
+ eevee_motion_blur_camera_get_matrix_at_time(draw_ctx->evil_C, scene, ar, rv3d, v3d, v3d->camera, ctime, effects->current_ndc_to_world);
+
+ /* Viewport Matrix */
+ DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
+
+ /* Only continue if camera is not being keyed */
+ if (compare_m4m4(persmat, effects->current_ndc_to_world, 0.0001f)) {
+
+ /* Past matrix */
+ eevee_motion_blur_camera_get_matrix_at_time(draw_ctx->evil_C, scene, ar, rv3d, v3d, v3d->camera, ctime - delta, effects->past_world_to_ndc);
+
+#if 0 /* for future high quality blur */
+ /* Future matrix */
+ eevee_motion_blur_camera_get_matrix_at_time(scene, ar, rv3d, v3d, v3d->camera, ctime + delta, effects->future_world_to_ndc);
+#endif
+ invert_m4(effects->current_ndc_to_world);
+
+ effects->motion_blur_samples = BKE_collection_engine_property_value_get_int(props, "motion_blur_samples");
+
+ if (!e_data.motion_blur_sh) {
+ eevee_create_shader_motion_blur();
+ }
+
+ return EFFECT_MOTION_BLUR | EFFECT_POST_BUFFER;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+
+ if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) {
+ psl->motion_blur = DRW_pass_create("Motion Blur", DRW_STATE_WRITE_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.motion_blur_sh, psl->motion_blur);
+ DRW_shgroup_uniform_int(grp, "samples", &effects->motion_blur_samples, 1);
+ DRW_shgroup_uniform_mat4(grp, "currInvViewProjMatrix", (float *)effects->current_ndc_to_world);
+ DRW_shgroup_uniform_mat4(grp, "pastViewProjMatrix", (float *)effects->past_world_to_ndc);
+ DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_call_add(grp, quad, NULL);
+ }
+}
+
+void EEVEE_motion_blur_draw(EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ /* Motion Blur */
+ if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) {
+ DRW_framebuffer_bind(effects->target_buffer);
+ DRW_draw_pass(psl->motion_blur);
+ SWAP_BUFFERS();
+ }
+}
+
+void EEVEE_motion_blur_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.motion_blur_sh);
+}
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
new file mode 100644
index 00000000000..c1dde385284
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -0,0 +1,251 @@
+/*
+ * 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 eevee_occlusion.c
+ * \ingroup draw_engine
+ *
+ * Implementation of the screen space Ground Truth Ambient Occlusion.
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_dynstr.h"
+
+#include "DNA_anim_types.h"
+
+#include "BKE_global.h" /* for G.debug_value */
+
+#include "eevee_private.h"
+
+static struct {
+ /* Ground Truth Ambient Occlusion */
+ struct GPUShader *gtao_sh;
+ struct GPUShader *gtao_debug_sh;
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_ambient_occlusion_lib_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_effect_gtao_frag_glsl[];
+
+static void eevee_create_shader_occlusion(void)
+{
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_effect_gtao_frag_glsl);
+ char *frag_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.gtao_sh = DRW_shader_create_fullscreen(frag_str, NULL);
+ e_data.gtao_debug_sh = DRW_shader_create_fullscreen(frag_str, "#define DEBUG_AO\n");
+
+ MEM_freeN(frag_str);
+}
+
+int EEVEE_occlusion_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ if (BKE_collection_engine_property_value_get_bool(props, "gtao_enable")) {
+ const float *viewport_size = DRW_viewport_size_get();
+
+ /* Shaders */
+ if (!e_data.gtao_sh) {
+ eevee_create_shader_occlusion();
+ }
+
+ effects->ao_dist = BKE_collection_engine_property_value_get_float(props, "gtao_distance");
+ effects->ao_factor = BKE_collection_engine_property_value_get_float(props, "gtao_factor");
+ effects->ao_quality = 1.0f - BKE_collection_engine_property_value_get_float(props, "gtao_quality");
+ effects->ao_samples = BKE_collection_engine_property_value_get_int(props, "gtao_samples");
+ effects->ao_samples_inv = 1.0f / effects->ao_samples;
+
+ effects->ao_settings = 1.0; /* USE_AO */
+ if (BKE_collection_engine_property_value_get_bool(props, "gtao_use_bent_normals")) {
+ effects->ao_settings += 2.0; /* USE_BENT_NORMAL */
+ }
+ if (BKE_collection_engine_property_value_get_bool(props, "gtao_denoise")) {
+ effects->ao_settings += 4.0; /* USE_DENOISE */
+ }
+
+ effects->ao_bounce_fac = (float)BKE_collection_engine_property_value_get_bool(props, "gtao_bounce");
+
+ effects->ao_texsize[0] = ((int)viewport_size[0]);
+ effects->ao_texsize[1] = ((int)viewport_size[1]);
+
+ /* Round up to multiple of 2 */
+ if ((effects->ao_texsize[0] & 0x1) != 0) {
+ effects->ao_texsize[0] += 1;
+ }
+ if ((effects->ao_texsize[1] & 0x1) != 0) {
+ effects->ao_texsize[1] += 1;
+ }
+
+ CLAMP(effects->ao_samples, 1, 32);
+
+ if (effects->hori_tex_layers != effects->ao_samples) {
+ DRW_TEXTURE_FREE_SAFE(txl->gtao_horizons);
+ }
+
+ if (txl->gtao_horizons == NULL) {
+ effects->hori_tex_layers = effects->ao_samples;
+ txl->gtao_horizons = DRW_texture_create_2D_array((int)viewport_size[0], (int)viewport_size[1], effects->hori_tex_layers, DRW_TEX_RG_8, 0, NULL);
+ }
+
+ DRWFboTexture tex = {&txl->gtao_horizons, DRW_TEX_RG_8, 0};
+
+ DRW_framebuffer_init(&fbl->gtao_fb, &draw_engine_eevee_type,
+ effects->ao_texsize[0], effects->ao_texsize[1],
+ &tex, 1);
+
+ if (G.debug_value == 6) {
+ DRWFboTexture tex_debug = {&stl->g_data->gtao_horizons_debug, DRW_TEX_RGBA_8, DRW_TEX_TEMP};
+
+ DRW_framebuffer_init(&fbl->gtao_debug_fb, &draw_engine_eevee_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex_debug, 1);
+ }
+
+ return EFFECT_GTAO | EFFECT_NORMAL_BUFFER;
+ }
+
+ /* Cleanup */
+ DRW_TEXTURE_FREE_SAFE(txl->gtao_horizons);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->gtao_fb);
+ effects->ao_settings = 0.0f;
+
+ return 0;
+}
+
+void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+
+ if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
+ /** Occlusion algorithm overview
+ *
+ * We separate the computation into 2 steps.
+ *
+ * - First we scan the neighborhood pixels to find the maximum horizon angle.
+ * We save this angle in a RG8 array texture.
+ *
+ * - Then we use this angle to compute occlusion with the shading normal at
+ * the shading stage. This let us do correct shadowing for each diffuse / specular
+ * lobe present in the shader using the correct normal.
+ **/
+ psl->ao_horizon_search = DRW_pass_create("GTAO Horizon Search", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.gtao_sh, psl->ao_horizon_search);
+ DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
+ DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &stl->effects->ao_dist, 2);
+ DRW_shgroup_uniform_float(grp, "sampleNbr", &stl->effects->ao_sample_nbr, 1);
+ DRW_shgroup_uniform_ivec2(grp, "aoHorizonTexSize", (int *)stl->effects->ao_texsize, 1);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ if (G.debug_value == 6) {
+ psl->ao_horizon_debug = DRW_pass_create("GTAO Horizon Debug", DRW_STATE_WRITE_COLOR);
+ grp = DRW_shgroup_create(e_data.gtao_debug_sh, psl->ao_horizon_debug);
+ DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
+ DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &txl->gtao_horizons);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
+ DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &stl->effects->ao_dist, 2);
+ DRW_shgroup_uniform_ivec2(grp, "aoHorizonTexSize", (int *)stl->effects->ao_texsize, 1);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_call_add(grp, quad, NULL);
+ }
+ }
+}
+
+void EEVEE_occlusion_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
+ DRW_stats_group_start("GTAO Horizon Scan");
+ for (effects->ao_sample_nbr = 0.0;
+ effects->ao_sample_nbr < effects->ao_samples;
+ ++effects->ao_sample_nbr)
+ {
+ DRW_framebuffer_texture_detach(txl->gtao_horizons);
+ DRW_framebuffer_texture_layer_attach(fbl->gtao_fb, txl->gtao_horizons, 0, (int)effects->ao_sample_nbr, 0);
+ DRW_framebuffer_bind(fbl->gtao_fb);
+
+ DRW_draw_pass(psl->ao_horizon_search);
+ }
+
+ /* Restore */
+ DRW_framebuffer_bind(fbl->main);
+
+ DRW_stats_group_end();
+ }
+}
+
+void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if (((effects->enabled_effects & EFFECT_GTAO) != 0) && (G.debug_value == 6)) {
+ DRW_stats_group_start("GTAO Debug");
+
+ DRW_framebuffer_texture_attach(fbl->gtao_debug_fb, stl->g_data->gtao_horizons_debug, 0, 0);
+ DRW_framebuffer_bind(fbl->gtao_debug_fb);
+
+ DRW_draw_pass(psl->ao_horizon_debug);
+
+ /* Restore */
+ DRW_framebuffer_texture_detach(stl->g_data->gtao_horizons_debug);
+ DRW_framebuffer_bind(fbl->main);
+
+ DRW_stats_group_end();
+ }
+}
+
+void EEVEE_occlusion_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.gtao_sh);
+ DRW_SHADER_FREE_SAFE(e_data.gtao_debug_sh);
+}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
new file mode 100644
index 00000000000..98fc6d6a6e4
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -0,0 +1,811 @@
+/*
+ * 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 eevee_private.h
+ * \ingroup DNA
+ */
+
+#ifndef __EEVEE_PRIVATE_H__
+#define __EEVEE_PRIVATE_H__
+
+struct Object;
+
+extern struct DrawEngineType draw_engine_eevee_type;
+
+/* Minimum UBO is 16384 bytes */
+#define MAX_PROBE 128 /* TODO : find size by dividing UBO max size by probe data size */
+#define MAX_GRID 64 /* TODO : find size by dividing UBO max size by grid data size */
+#define MAX_PLANAR 16 /* TODO : find size by dividing UBO max size by grid data size */
+#define MAX_LIGHT 128 /* TODO : find size by dividing UBO max size by light data size */
+#define MAX_CASCADE_NUM 4
+#define MAX_SHADOW 256 /* TODO : Make this depends on GL_MAX_ARRAY_TEXTURE_LAYERS */
+#define MAX_SHADOW_CASCADE 8
+#define MAX_SHADOW_CUBE (MAX_SHADOW - MAX_CASCADE_NUM * MAX_SHADOW_CASCADE)
+#define MAX_BLOOM_STEP 16
+
+/* Only define one of these. */
+// #define IRRADIANCE_SH_L2
+// #define IRRADIANCE_CUBEMAP
+#define IRRADIANCE_HL2
+
+#if defined(IRRADIANCE_SH_L2)
+# define SHADER_IRRADIANCE "#define IRRADIANCE_SH_L2\n"
+#elif defined(IRRADIANCE_CUBEMAP)
+# define SHADER_IRRADIANCE "#define IRRADIANCE_CUBEMAP\n"
+#elif defined(IRRADIANCE_HL2)
+# define SHADER_IRRADIANCE "#define IRRADIANCE_HL2\n"
+#endif
+
+#define SHADER_DEFINES \
+ "#define EEVEE_ENGINE\n" \
+ "#define MAX_PROBE " STRINGIFY(MAX_PROBE) "\n" \
+ "#define MAX_GRID " STRINGIFY(MAX_GRID) "\n" \
+ "#define MAX_PLANAR " STRINGIFY(MAX_PLANAR) "\n" \
+ "#define MAX_LIGHT " STRINGIFY(MAX_LIGHT) "\n" \
+ "#define MAX_SHADOW " STRINGIFY(MAX_SHADOW) "\n" \
+ "#define MAX_SHADOW_CUBE " STRINGIFY(MAX_SHADOW_CUBE) "\n" \
+ "#define MAX_SHADOW_CASCADE " STRINGIFY(MAX_SHADOW_CASCADE) "\n" \
+ "#define MAX_CASCADE_NUM " STRINGIFY(MAX_CASCADE_NUM) "\n" \
+ SHADER_IRRADIANCE
+
+#define SWAP_DOUBLE_BUFFERS() { \
+ if (effects->swap_double_buffer) { \
+ SWAP(struct GPUFrameBuffer *, fbl->main, fbl->double_buffer); \
+ SWAP(GPUTexture *, txl->color, txl->color_double_buffer); \
+ effects->swap_double_buffer = false; \
+ } \
+} ((void)0)
+
+#define SWAP_BUFFERS() { \
+ if (effects->target_buffer != fbl->main) { \
+ SWAP_DOUBLE_BUFFERS(); \
+ effects->source_buffer = txl->color_post; \
+ effects->target_buffer = fbl->main; \
+ } \
+ else { \
+ SWAP_DOUBLE_BUFFERS(); \
+ effects->source_buffer = txl->color; \
+ effects->target_buffer = fbl->effect_fb; \
+ } \
+} ((void)0)
+
+/* World shader variations */
+enum {
+ VAR_WORLD_BACKGROUND = 0,
+ VAR_WORLD_PROBE = 1,
+ VAR_WORLD_VOLUME = 2,
+};
+
+/* Material shader variations */
+enum {
+ VAR_MAT_MESH = (1 << 0),
+ VAR_MAT_PROBE = (1 << 1),
+ VAR_MAT_HAIR = (1 << 2),
+ VAR_MAT_FLAT = (1 << 3),
+ VAR_MAT_BLEND = (1 << 4),
+ VAR_MAT_VSM = (1 << 5),
+ VAR_MAT_ESM = (1 << 6),
+ /* Max number of variation */
+ /* IMPORTANT : Leave it last and set
+ * it's value accordingly. */
+ VAR_MAT_MAX = (1 << 7),
+ /* These are options that are not counted in VAR_MAT_MAX
+ * because they are not cumulative with the others above. */
+ VAR_MAT_CLIP = (1 << 8),
+ VAR_MAT_HASH = (1 << 9),
+ VAR_MAT_MULT = (1 << 10),
+ VAR_MAT_SHADOW = (1 << 11),
+ VAR_MAT_REFRACT = (1 << 12),
+ VAR_MAT_VOLUME = (1 << 13),
+ VAR_MAT_SSS = (1 << 14),
+ VAR_MAT_TRANSLUC = (1 << 15),
+ VAR_MAT_SSSALBED = (1 << 16),
+};
+
+/* Shadow Technique */
+enum {
+ SHADOW_ESM = 1,
+ SHADOW_VSM = 2,
+ SHADOW_METHOD_MAX = 3,
+};
+
+typedef struct EEVEE_PassList {
+ /* Shadows */
+ struct DRWPass *shadow_pass;
+ struct DRWPass *shadow_cube_pass;
+ struct DRWPass *shadow_cube_copy_pass;
+ struct DRWPass *shadow_cube_store_pass;
+ struct DRWPass *shadow_cascade_pass;
+ struct DRWPass *shadow_cascade_copy_pass;
+ struct DRWPass *shadow_cascade_store_pass;
+
+ /* Probes */
+ struct DRWPass *probe_background;
+ struct DRWPass *probe_glossy_compute;
+ struct DRWPass *probe_diffuse_compute;
+ struct DRWPass *probe_visibility_compute;
+ struct DRWPass *probe_grid_fill;
+ struct DRWPass *probe_display;
+ struct DRWPass *probe_planar_downsample_ps;
+
+ /* Effects */
+ struct DRWPass *ao_horizon_search;
+ struct DRWPass *ao_horizon_debug;
+ struct DRWPass *motion_blur;
+ struct DRWPass *bloom_blit;
+ struct DRWPass *bloom_downsample_first;
+ struct DRWPass *bloom_downsample;
+ struct DRWPass *bloom_upsample;
+ struct DRWPass *bloom_resolve;
+ struct DRWPass *dof_down;
+ struct DRWPass *dof_scatter;
+ struct DRWPass *dof_resolve;
+ struct DRWPass *volumetric_world_ps;
+ struct DRWPass *volumetric_objects_ps;
+ struct DRWPass *volumetric_scatter_ps;
+ struct DRWPass *volumetric_integration_ps;
+ struct DRWPass *volumetric_resolve_ps;
+ struct DRWPass *ssr_raytrace;
+ struct DRWPass *ssr_resolve;
+ struct DRWPass *sss_blur_ps;
+ struct DRWPass *sss_resolve_ps;
+ struct DRWPass *color_downsample_ps;
+ struct DRWPass *color_downsample_cube_ps;
+ struct DRWPass *taa_resolve;
+
+ /* HiZ */
+ struct DRWPass *minz_downlevel_ps;
+ struct DRWPass *maxz_downlevel_ps;
+ struct DRWPass *minz_downdepth_ps;
+ struct DRWPass *maxz_downdepth_ps;
+ struct DRWPass *minz_downdepth_layer_ps;
+ struct DRWPass *maxz_downdepth_layer_ps;
+ struct DRWPass *minz_copydepth_ps;
+ struct DRWPass *maxz_copydepth_ps;
+
+ struct DRWPass *depth_pass;
+ struct DRWPass *depth_pass_cull;
+ struct DRWPass *depth_pass_clip;
+ struct DRWPass *depth_pass_clip_cull;
+ struct DRWPass *refract_depth_pass;
+ struct DRWPass *refract_depth_pass_cull;
+ struct DRWPass *refract_depth_pass_clip;
+ struct DRWPass *refract_depth_pass_clip_cull;
+ struct DRWPass *default_pass[VAR_MAT_MAX];
+ struct DRWPass *sss_pass;
+ struct DRWPass *material_pass;
+ struct DRWPass *refract_pass;
+ struct DRWPass *transparent_pass;
+ struct DRWPass *background_pass;
+} EEVEE_PassList;
+
+typedef struct EEVEE_FramebufferList {
+ /* Effects */
+ struct GPUFrameBuffer *gtao_fb;
+ struct GPUFrameBuffer *gtao_debug_fb;
+ struct GPUFrameBuffer *downsample_fb;
+ struct GPUFrameBuffer *effect_fb;
+ struct GPUFrameBuffer *bloom_blit_fb;
+ struct GPUFrameBuffer *bloom_down_fb[MAX_BLOOM_STEP];
+ struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP - 1];
+ struct GPUFrameBuffer *sss_blur_fb;
+ struct GPUFrameBuffer *sss_clear_fb;
+ struct GPUFrameBuffer *dof_down_fb;
+ struct GPUFrameBuffer *dof_scatter_far_fb;
+ struct GPUFrameBuffer *dof_scatter_near_fb;
+ struct GPUFrameBuffer *volumetric_fb;
+ struct GPUFrameBuffer *volumetric_scat_fb;
+ struct GPUFrameBuffer *volumetric_integ_fb;
+ struct GPUFrameBuffer *screen_tracing_fb;
+ struct GPUFrameBuffer *refract_fb;
+
+ struct GPUFrameBuffer *planarref_fb;
+
+ struct GPUFrameBuffer *main;
+ struct GPUFrameBuffer *double_buffer;
+ struct GPUFrameBuffer *depth_double_buffer_fb;
+} EEVEE_FramebufferList;
+
+typedef struct EEVEE_TextureList {
+ /* Effects */
+ struct GPUTexture *color_post; /* R16_G16_B16 */
+ struct GPUTexture *dof_down_near; /* R16_G16_B16_A16 */
+ struct GPUTexture *dof_down_far; /* R16_G16_B16_A16 */
+ struct GPUTexture *dof_coc; /* R16_G16 */
+ struct GPUTexture *dof_near_blur; /* R16_G16_B16_A16 */
+ struct GPUTexture *dof_far_blur; /* R16_G16_B16_A16 */
+ struct GPUTexture *bloom_blit; /* R16_G16_B16 */
+ struct GPUTexture *bloom_downsample[MAX_BLOOM_STEP]; /* R16_G16_B16 */
+ struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP - 1]; /* R16_G16_B16 */
+ struct GPUTexture *ssr_normal_input;
+ struct GPUTexture *ssr_specrough_input;
+ struct GPUTexture *refract_color;
+
+ struct GPUTexture *volume_prop_scattering;
+ struct GPUTexture *volume_prop_extinction;
+ struct GPUTexture *volume_prop_emission;
+ struct GPUTexture *volume_prop_phase;
+ struct GPUTexture *volume_scatter;
+ struct GPUTexture *volume_transmittance;
+ struct GPUTexture *volume_scatter_history;
+ struct GPUTexture *volume_transmittance_history;
+
+ struct GPUTexture *planar_pool;
+ struct GPUTexture *planar_depth;
+
+ struct GPUTexture *gtao_horizons;
+
+ struct GPUTexture *sss_data;
+ struct GPUTexture *sss_albedo;
+ struct GPUTexture *sss_blur;
+ struct GPUTexture *sss_stencil;
+
+ struct GPUTexture *maxzbuffer;
+
+ struct GPUTexture *color; /* R16_G16_B16 */
+ struct GPUTexture *color_double_buffer;
+ struct GPUTexture *depth_double_buffer;
+} EEVEE_TextureList;
+
+typedef struct EEVEE_StorageList {
+ /* Effects */
+ struct EEVEE_EffectsInfo *effects;
+
+ struct EEVEE_PrivateData *g_data;
+} EEVEE_StorageList;
+
+/* ************ LIGHT UBO ************* */
+typedef struct EEVEE_Light {
+ float position[3], dist;
+ float color[3], spec;
+ float spotsize, spotblend, radius, shadowid;
+ float rightvec[3], sizex;
+ float upvec[3], sizey;
+ float forwardvec[3], lamptype;
+} EEVEE_Light;
+
+typedef struct EEVEE_Shadow {
+ float near, far, bias, exp;
+ float shadow_start, data_start, multi_shadow_count, shadow_blur;
+ float contact_dist, contact_bias, contact_spread, contact_thickness;
+} EEVEE_Shadow;
+
+typedef struct EEVEE_ShadowCube {
+ float position[3], pad;
+} EEVEE_ShadowCube;
+
+typedef struct EEVEE_ShadowCascade {
+ float shadowmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC->Tex : used for sampling the shadow map. */
+ float split_start[4];
+ float split_end[4];
+} EEVEE_ShadowCascade;
+
+typedef struct EEVEE_ShadowRender {
+ float shadowmat[6][4][4]; /* World->Lamp->NDC : used to render the shadow map. 6 frustum for cubemap shadow */
+ float viewmat[6][4][4]; /* World->Lamp : used to render the shadow map. 6 viewmat for cubemap shadow */
+ float position[3], pad;
+ float cube_texel_size;
+ float stored_texel_size;
+ float clip_near;
+ float clip_far;
+ int shadow_samples_ct;
+ float shadow_inv_samples_ct;
+} EEVEE_ShadowRender;
+
+/* ************ VOLUME DATA ************ */
+typedef struct EEVEE_VolumetricsInfo {
+ float integration_step_count, shadow_step_count, sample_distribution, light_clamp;
+ float integration_start, integration_end;
+ float depth_param[3], history_alpha;
+ bool use_lights, use_volume_shadows;
+ int froxel_tex_size[3];
+ float inv_tex_size[3];
+ float volume_coord_scale[2];
+ float jitter[3];
+} EEVEE_VolumetricsInfo;
+
+/* ************ LIGHT DATA ************* */
+typedef struct EEVEE_LampsInfo {
+ int num_light, cache_num_light;
+ int num_layer, cache_num_layer;
+ int gpu_cube_ct, gpu_cascade_ct, gpu_shadow_ct;
+ int cpu_cube_ct, cpu_cascade_ct;
+ int update_flag;
+ int shadow_size, shadow_method;
+ bool shadow_high_bitdepth;
+ int shadow_cube_target_size;
+ int current_shadow_cascade;
+ int current_shadow_face;
+ float filter_size;
+ /* List of lights in the scene. */
+ /* XXX This is fragile, can get out of sync quickly. */
+ struct Object *light_ref[MAX_LIGHT];
+ struct Object *shadow_cube_ref[MAX_SHADOW_CUBE];
+ struct Object *shadow_cascade_ref[MAX_SHADOW_CASCADE];
+ /* UBO Storage : data used by UBO */
+ struct EEVEE_Light light_data[MAX_LIGHT];
+ struct EEVEE_ShadowRender shadow_render_data;
+ struct EEVEE_Shadow shadow_data[MAX_SHADOW];
+ struct EEVEE_ShadowCube shadow_cube_data[MAX_SHADOW_CUBE];
+ struct EEVEE_ShadowCascade shadow_cascade_data[MAX_SHADOW_CASCADE];
+} EEVEE_LampsInfo;
+
+/* EEVEE_LampsInfo->update_flag */
+enum {
+ LIGHT_UPDATE_SHADOW_CUBE = (1 << 0),
+};
+
+/* ************ PROBE UBO ************* */
+typedef struct EEVEE_LightProbe {
+ float position[3], parallax_type;
+ float attenuation_fac;
+ float attenuation_type;
+ float pad3[2];
+ float attenuationmat[4][4];
+ float parallaxmat[4][4];
+} EEVEE_LightProbe;
+
+typedef struct EEVEE_LightGrid {
+ float mat[4][4];
+ int resolution[3], offset;
+ float corner[3], attenuation_scale;
+ float increment_x[3], attenuation_bias; /* world space vector between 2 opposite cells */
+ float increment_y[3], level_bias;
+ float increment_z[3], pad4;
+ float visibility_bias, visibility_bleed, visibility_range, pad5;
+} EEVEE_LightGrid;
+
+typedef struct EEVEE_PlanarReflection {
+ float plane_equation[4];
+ float clip_vec_x[3], attenuation_scale;
+ float clip_vec_y[3], attenuation_bias;
+ float clip_edge_x_pos, clip_edge_x_neg;
+ float clip_edge_y_pos, clip_edge_y_neg;
+ float facing_scale, facing_bias, pad[2];
+ float reflectionmat[4][4];
+} EEVEE_PlanarReflection;
+
+/* ************ PROBE DATA ************* */
+typedef struct EEVEE_LightProbesInfo {
+ int num_cube, cache_num_cube;
+ int num_grid, cache_num_grid;
+ int num_planar, cache_num_planar;
+ int total_irradiance_samples; /* Total for all grids */
+ int cache_irradiance_size[3];
+ int update_flag;
+ int updated_bounce;
+ int num_bounce;
+ int cubemap_res;
+ int target_size;
+ int irradiance_vis_size;
+ int grid_initialized;
+ /* Actual number of probes that have datas. */
+ int num_render_cube;
+ int num_render_grid;
+ /* For rendering probes */
+ float probemat[6][4][4];
+ int layer;
+ float texel_size;
+ float padding_size;
+ float samples_ct;
+ float invsamples_ct;
+ float near_clip;
+ float far_clip;
+ float roughness;
+ float lodfactor;
+ float lod_rt_max, lod_cube_max, lod_planar_max;
+ float visibility_range;
+ float visibility_blur;
+ int shres;
+ int shnbr;
+ bool specular_toggle;
+ bool ssr_toggle;
+ bool sss_toggle;
+ /* List of probes in the scene. */
+ /* XXX This is fragile, can get out of sync quickly. */
+ struct Object *probes_cube_ref[MAX_PROBE];
+ struct Object *probes_grid_ref[MAX_GRID];
+ struct Object *probes_planar_ref[MAX_PLANAR];
+ /* UBO Storage : data used by UBO */
+ struct EEVEE_LightProbe probe_data[MAX_PROBE];
+ struct EEVEE_LightGrid grid_data[MAX_GRID];
+ struct EEVEE_PlanarReflection planar_data[MAX_PLANAR];
+} EEVEE_LightProbesInfo;
+
+/* EEVEE_LightProbesInfo->update_flag */
+enum {
+ PROBE_UPDATE_CUBE = (1 << 0),
+ PROBE_UPDATE_GRID = (1 << 1),
+ PROBE_UPDATE_ALL = 0xFFFFFF,
+};
+
+/* ************ EFFECTS DATA ************* */
+typedef struct EEVEE_EffectsInfo {
+ int enabled_effects;
+ bool swap_double_buffer;
+
+ /* SSSS */
+ int sss_sample_count;
+ float sss_jitter_threshold;
+ bool sss_separate_albedo;
+
+ /* Volumetrics */
+ bool use_volumetrics;
+ int volume_current_sample;
+
+ /* SSR */
+ bool use_ssr;
+ bool reflection_trace_full;
+ bool ssr_use_normalization;
+ int ssr_ray_count;
+ float ssr_firefly_fac;
+ float ssr_border_fac;
+ float ssr_max_roughness;
+ float ssr_quality;
+ float ssr_thickness;
+ float ssr_pixelsize[2];
+
+ /* Temporal Anti Aliasing */
+ int taa_current_sample;
+ int taa_total_sample;
+ float taa_alpha;
+ bool prev_drw_support;
+ float prev_drw_persmat[4][4];
+ float overide_persmat[4][4];
+ float overide_persinv[4][4];
+ float overide_winmat[4][4];
+ float overide_wininv[4][4];
+
+ /* Ambient Occlusion */
+ bool use_ao, use_bent_normals;
+ float ao_dist, ao_samples, ao_factor, ao_samples_inv;
+ float ao_offset, ao_bounce_fac, ao_quality, ao_settings;
+ float ao_sample_nbr;
+ int ao_texsize[2], hori_tex_layers;
+
+ /* Motion Blur */
+ float current_ndc_to_world[4][4];
+ float past_world_to_ndc[4][4];
+ float tmp_mat[4][4];
+ int motion_blur_samples;
+
+ /* Depth Of Field */
+ float dof_near_far[2];
+ float dof_params[3];
+ float dof_bokeh[4];
+ float dof_layer_select[2];
+ int dof_target_size[2];
+
+ /* Bloom */
+ int bloom_iteration_ct;
+ float source_texel_size[2];
+ float blit_texel_size[2];
+ float downsamp_texel_size[MAX_BLOOM_STEP][2];
+ float bloom_color[3];
+ float bloom_clamp;
+ float bloom_sample_scale;
+ float bloom_curve_threshold[4];
+ float unf_source_texel_size[2];
+ struct GPUTexture *unf_source_buffer; /* pointer copy */
+ struct GPUTexture *unf_base_buffer; /* pointer copy */
+
+ /* Not alloced, just a copy of a *GPUtexture in EEVEE_TextureList. */
+ struct GPUTexture *source_buffer; /* latest updated texture */
+ struct GPUFrameBuffer *target_buffer; /* next target to render to */
+} EEVEE_EffectsInfo;
+
+enum {
+ EFFECT_MOTION_BLUR = (1 << 0),
+ EFFECT_BLOOM = (1 << 1),
+ EFFECT_DOF = (1 << 2),
+ EFFECT_VOLUMETRIC = (1 << 3),
+ EFFECT_SSR = (1 << 4),
+ EFFECT_DOUBLE_BUFFER = (1 << 5), /* Not really an effect but a feature */
+ EFFECT_REFRACT = (1 << 6),
+ EFFECT_GTAO = (1 << 7),
+ EFFECT_TAA = (1 << 8),
+ EFFECT_POST_BUFFER = (1 << 9), /* Not really an effect but a feature */
+ EFFECT_NORMAL_BUFFER = (1 << 10), /* Not really an effect but a feature */
+ EFFECT_SSS = (1 << 11),
+};
+
+/* ************** SCENE LAYER DATA ************** */
+typedef struct EEVEE_ViewLayerData {
+ /* Lamps */
+ struct EEVEE_LampsInfo *lamps;
+
+ struct GPUUniformBuffer *light_ubo;
+ struct GPUUniformBuffer *shadow_ubo;
+ struct GPUUniformBuffer *shadow_render_ubo;
+ struct GPUUniformBuffer *shadow_samples_ubo;
+
+ struct GPUFrameBuffer *shadow_target_fb;
+ struct GPUFrameBuffer *shadow_store_fb;
+
+ struct GPUTexture *shadow_cube_target;
+ struct GPUTexture *shadow_cube_blur;
+ struct GPUTexture *shadow_cascade_target;
+ struct GPUTexture *shadow_cascade_blur;
+ struct GPUTexture *shadow_pool;
+
+ struct ListBase shadow_casters; /* Shadow casters gathered during cache iteration */
+
+ /* Probes */
+ struct EEVEE_LightProbesInfo *probes;
+
+ struct GPUUniformBuffer *probe_ubo;
+ struct GPUUniformBuffer *grid_ubo;
+ struct GPUUniformBuffer *planar_ubo;
+
+ struct GPUFrameBuffer *probe_fb;
+ struct GPUFrameBuffer *probe_filter_fb;
+
+ struct GPUTexture *probe_rt;
+ struct GPUTexture *probe_depth_rt;
+ struct GPUTexture *probe_pool;
+ struct GPUTexture *irradiance_pool;
+ struct GPUTexture *irradiance_rt;
+
+ struct ListBase probe_queue; /* List of probes to update */
+
+ /* Volumetrics */
+ struct EEVEE_VolumetricsInfo *volumetrics;
+} EEVEE_ViewLayerData;
+
+/* ************ OBJECT DATA ************ */
+typedef struct EEVEE_LampEngineData {
+ bool need_update;
+ struct ListBase shadow_caster_list;
+ void *storage; /* either EEVEE_LightData, EEVEE_ShadowCubeData, EEVEE_ShadowCascadeData */
+} EEVEE_LampEngineData;
+
+typedef struct EEVEE_LightProbeEngineData {
+ /* NOTE: need_full_update is set by dependency graph when the probe or it's
+ * object is updated. This triggers full probe update, including it's
+ * "progressive" GI refresh.
+ *
+ * need_update is always set to truth when need_full_update is tagged, but
+ * might also be forced to be kept truth during GI refresh stages.
+ *
+ * TODO(sergey): Is there a way to avoid two flags here, or at least make
+ * it more clear what's going on here?
+ */
+ bool need_full_update;
+ bool need_update;
+
+ bool ready_to_shade;
+ int updated_cells;
+ int updated_lvl;
+ int num_cell;
+ int max_lvl;
+ int probe_id; /* Only used for display data */
+ float probe_size; /* Only used for display data */
+ /* For planar reflection rendering */
+ float viewmat[4][4];
+ float persmat[4][4];
+ float planer_eq_offset[4];
+ struct ListBase captured_object_list;
+} EEVEE_LightProbeEngineData;
+
+typedef struct EEVEE_ObjectEngineData {
+ bool need_update;
+} EEVEE_ObjectEngineData;
+
+/* *********************************** */
+
+typedef struct EEVEE_Data {
+ void *engine_type;
+ EEVEE_FramebufferList *fbl;
+ EEVEE_TextureList *txl;
+ EEVEE_PassList *psl;
+ EEVEE_StorageList *stl;
+} EEVEE_Data;
+
+typedef struct EEVEE_PrivateData {
+ struct DRWShadingGroup *shadow_shgrp;
+ struct DRWShadingGroup *depth_shgrp;
+ struct DRWShadingGroup *depth_shgrp_cull;
+ struct DRWShadingGroup *depth_shgrp_clip;
+ struct DRWShadingGroup *depth_shgrp_clip_cull;
+ struct DRWShadingGroup *refract_depth_shgrp;
+ struct DRWShadingGroup *refract_depth_shgrp_cull;
+ struct DRWShadingGroup *refract_depth_shgrp_clip;
+ struct DRWShadingGroup *refract_depth_shgrp_clip_cull;
+ struct DRWShadingGroup *cube_display_shgrp;
+ struct DRWShadingGroup *planar_display_shgrp;
+ struct DRWShadingGroup *planar_downsample;
+ struct GHash *material_hash;
+ struct GHash *hair_material_hash;
+ struct GPUTexture *minzbuffer;
+ struct GPUTexture *ssr_hit_output[4];
+ struct GPUTexture *gtao_horizons_debug;
+ float background_alpha; /* TODO find a better place for this. */
+ float viewvecs[2][4];
+ /* For planar probes */
+ float texel_size[2];
+ /* To correct mip level texel mis-alignement */
+ float mip_ratio[10][2]; /* TODO put in a UBO */
+ /* For double buffering */
+ bool view_updated;
+ bool valid_double_buffer;
+ float prev_persmat[4][4];
+} EEVEE_PrivateData; /* Transient data */
+
+/* eevee_data.c */
+EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void);
+EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void);
+EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob);
+EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob);
+EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob);
+EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob);
+EEVEE_LampEngineData *EEVEE_lamp_data_get(Object *ob);
+EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob);
+
+/* eevee_materials.c */
+struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */
+void EEVEE_materials_init(EEVEE_StorageList *stl);
+void EEVEE_materials_cache_init(EEVEE_Data *vedata);
+void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob);
+void EEVEE_materials_cache_finish(EEVEE_Data *vedata);
+struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo);
+struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo);
+struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo);
+struct GPUMaterial *EEVEE_material_mesh_get(
+ struct Scene *scene, Material *ma, EEVEE_Data *vedata,
+ bool use_blend, bool use_multiply, bool use_refract, bool use_sss, bool use_translucency, int shadow_method);
+struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma);
+struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material *ma, bool use_hashed_alpha, bool is_shadow);
+struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, int shadow_method);
+void EEVEE_materials_free(void);
+void EEVEE_draw_default_passes(EEVEE_PassList *psl);
+void EEVEE_update_util_texture(float offset);
+
+/* eevee_lights.c */
+void EEVEE_lights_init(EEVEE_ViewLayerData *sldata);
+void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl);
+void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, struct Object *ob);
+void EEVEE_lights_cache_shcaster_add(
+ EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, struct Gwn_Batch *geom, float (*obmat)[4]);
+void EEVEE_lights_cache_shcaster_material_add(
+ EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl,
+ struct GPUMaterial *gpumat, struct Gwn_Batch *geom, struct Object *ob,
+ float (*obmat)[4], float *alpha_threshold);
+void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata);
+void EEVEE_lights_update(EEVEE_ViewLayerData *sldata);
+void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl);
+void EEVEE_lights_free(void);
+
+/* eevee_lightprobes.c */
+void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob);
+void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_lightprobes_free(void);
+
+/* eevee_depth_of_field.c */
+int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_depth_of_field_draw(EEVEE_Data *vedata);
+void EEVEE_depth_of_field_free(void);
+
+/* eevee_bloom.c */
+int EEVEE_bloom_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_bloom_draw(EEVEE_Data *vedata);
+void EEVEE_bloom_free(void);
+
+/* eevee_occlusion.c */
+int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_occlusion_free(void);
+
+/* eevee_screen_raytrace.c */
+int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_refraction_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_reflection_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_screen_raytrace_free(void);
+
+/* eevee_subsurface.c */
+int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile);
+void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_subsurface_free(void);
+
+/* eevee_motion_blur.c */
+int EEVEE_motion_blur_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_motion_blur_draw(EEVEE_Data *vedata);
+void EEVEE_motion_blur_free(void);
+
+/* eevee_temporal_sampling.c */
+int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata);
+void EEVEE_temporal_sampling_free(void);
+
+/* eevee_volumes.c */
+int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct Scene *scene, Object *ob);
+void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_volumes_resolve(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_volumes_free_smoke_textures(void);
+void EEVEE_volumes_free(void);
+
+/* eevee_effects.c */
+void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer);
+void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level);
+void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level);
+void EEVEE_effects_do_gtao(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_draw_effects(EEVEE_Data *vedata);
+void EEVEE_effects_free(void);
+
+/* Shadow Matrix */
+static const float texcomat[4][4] = { /* From NDC to TexCo */
+ {0.5f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 0.5f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.5f, 0.0f},
+ {0.5f, 0.5f, 0.5f, 1.0f}
+};
+
+/* Cubemap Matrices */
+static const float cubefacemat[6][4][4] = {
+ /* Pos X */
+ {{0.0f, 0.0f, -1.0f, 0.0f},
+ {0.0f, -1.0f, 0.0f, 0.0f},
+ {-1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}},
+ /* Neg X */
+ {{0.0f, 0.0f, 1.0f, 0.0f},
+ {0.0f, -1.0f, 0.0f, 0.0f},
+ {1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}},
+ /* Pos Y */
+ {{1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, -1.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}},
+ /* Neg Y */
+ {{1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 1.0f, 0.0f},
+ {0.0f, -1.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}},
+ /* Pos Z */
+ {{1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, -1.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, -1.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}},
+ /* Neg Z */
+ {{-1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, -1.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 1.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}},
+};
+
+#endif /* __EEVEE_PRIVATE_H__ */
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
new file mode 100644
index 00000000000..35669968337
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -0,0 +1,341 @@
+/*
+ * 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 eevee_screen_raytrace.c
+ * \ingroup draw_engine
+ *
+ * Screen space reflections and refractions techniques.
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_dynstr.h"
+
+#include "eevee_private.h"
+#include "GPU_texture.h"
+
+/* SSR shader variations */
+enum {
+ SSR_SAMPLES = (1 << 0) | (1 << 1),
+ SSR_RESOLVE = (1 << 2),
+ SSR_FULL_TRACE = (1 << 3),
+ SSR_MAX_SHADER = (1 << 4),
+};
+
+static struct {
+ /* Screen Space Reflection */
+ struct GPUShader *ssr_sh[SSR_MAX_SHADER];
+
+ /* Theses are just references, not actually allocated */
+ struct GPUTexture *depth_src;
+ struct GPUTexture *color_src;
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_ambient_occlusion_lib_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_bsdf_sampling_lib_glsl[];
+extern char datatoc_octahedron_lib_glsl[];
+extern char datatoc_effect_ssr_frag_glsl[];
+extern char datatoc_lightprobe_lib_glsl[];
+extern char datatoc_raytrace_lib_glsl[];
+
+static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
+{
+ if (e_data.ssr_sh[options] == NULL) {
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_raytrace_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_effect_ssr_frag_glsl);
+ char *ssr_shader_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ int samples = (SSR_SAMPLES & options) + 1;
+
+ DynStr *ds_defines = BLI_dynstr_new();
+ BLI_dynstr_appendf(ds_defines, SHADER_DEFINES);
+ BLI_dynstr_appendf(ds_defines, "#define RAY_COUNT %d\n", samples);
+ if (options & SSR_RESOLVE) {
+ BLI_dynstr_appendf(ds_defines, "#define STEP_RESOLVE\n");
+ }
+ else {
+ BLI_dynstr_appendf(ds_defines, "#define STEP_RAYTRACE\n");
+ BLI_dynstr_appendf(ds_defines, "#define PLANAR_PROBE_RAYTRACE\n");
+ }
+ if (options & SSR_FULL_TRACE) {
+ BLI_dynstr_appendf(ds_defines, "#define FULLRES\n");
+ }
+ char *ssr_define_str = BLI_dynstr_get_cstring(ds_defines);
+ BLI_dynstr_free(ds_defines);
+
+ e_data.ssr_sh[options] = DRW_shader_create_fullscreen(ssr_shader_str, ssr_define_str);
+
+ MEM_freeN(ssr_shader_str);
+ MEM_freeN(ssr_define_str);
+ }
+
+ return e_data.ssr_sh[options];
+}
+
+int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ const float *viewport_size = DRW_viewport_size_get();
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ /* Compute pixel size, (shared with contact shadows) */
+ copy_v2_v2(effects->ssr_pixelsize, viewport_size);
+ invert_v2(effects->ssr_pixelsize);
+
+ if (BKE_collection_engine_property_value_get_bool(props, "ssr_enable")) {
+ const bool use_refraction = BKE_collection_engine_property_value_get_bool(props, "ssr_refraction");
+
+ if (use_refraction) {
+ DRWFboTexture tex = {&txl->refract_color, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
+
+ DRW_framebuffer_init(&fbl->refract_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1], &tex, 1);
+ }
+
+ effects->ssr_ray_count = BKE_collection_engine_property_value_get_int(props, "ssr_ray_count");
+ effects->reflection_trace_full = !BKE_collection_engine_property_value_get_bool(props, "ssr_halfres");
+ effects->ssr_use_normalization = BKE_collection_engine_property_value_get_bool(props, "ssr_normalize_weight");
+ effects->ssr_quality = 1.0f - BKE_collection_engine_property_value_get_float(props, "ssr_quality");
+ effects->ssr_thickness = BKE_collection_engine_property_value_get_float(props, "ssr_thickness");
+ effects->ssr_border_fac = BKE_collection_engine_property_value_get_float(props, "ssr_border_fade");
+ effects->ssr_firefly_fac = BKE_collection_engine_property_value_get_float(props, "ssr_firefly_fac");
+ effects->ssr_max_roughness = BKE_collection_engine_property_value_get_float(props, "ssr_max_roughness");
+
+ if (effects->ssr_firefly_fac < 1e-8f) {
+ effects->ssr_firefly_fac = FLT_MAX;
+ }
+
+ /* Important, can lead to breakage otherwise. */
+ CLAMP(effects->ssr_ray_count, 1, 4);
+
+ const int divisor = (effects->reflection_trace_full) ? 1 : 2;
+ int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor};
+ const bool high_qual_input = true; /* TODO dither low quality input */
+
+ /* MRT for the shading pass in order to output needed data for the SSR pass. */
+ /* TODO create one texture layer per lobe */
+ if (txl->ssr_specrough_input == NULL) {
+ DRWTextureFormat specrough_format = (high_qual_input) ? DRW_TEX_RGBA_16 : DRW_TEX_RGBA_8;
+ txl->ssr_specrough_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], specrough_format, 0, NULL);
+ }
+
+ /* Reattach textures to the right buffer (because we are alternating between buffers) */
+ /* TODO multiple FBO per texture!!!! */
+ DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
+ DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
+
+ /* Raytracing output */
+ /* TODO try integer format for hit coord to increase precision */
+ DRWFboTexture tex_output[4] = {
+ {&stl->g_data->ssr_hit_output[0], DRW_TEX_RGBA_16, DRW_TEX_TEMP},
+ {&stl->g_data->ssr_hit_output[1], DRW_TEX_RGBA_16, DRW_TEX_TEMP},
+ {&stl->g_data->ssr_hit_output[2], DRW_TEX_RGBA_16, DRW_TEX_TEMP},
+ {&stl->g_data->ssr_hit_output[3], DRW_TEX_RGBA_16, DRW_TEX_TEMP},
+ };
+
+ DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type, tracing_res[0], tracing_res[1], tex_output, effects->ssr_ray_count);
+
+ /* Enable double buffering to be able to read previous frame color */
+ return EFFECT_SSR | EFFECT_NORMAL_BUFFER | EFFECT_DOUBLE_BUFFER | ((use_refraction) ? EFFECT_REFRACT : 0);
+ }
+
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->ssr_specrough_input);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb);
+ for (int i = 0; i < 4; ++i) {
+ stl->g_data->ssr_hit_output[i] = NULL;
+ }
+
+ return 0;
+}
+
+void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+
+ if ((effects->enabled_effects & EFFECT_SSR) != 0) {
+ int options = (effects->reflection_trace_full) ? SSR_FULL_TRACE : 0;
+ options |= (effects->ssr_ray_count - 1);
+
+ struct GPUShader *trace_shader = eevee_effects_screen_raytrace_shader_get(options);
+ struct GPUShader *resolve_shader = eevee_effects_screen_raytrace_shader_get(SSR_RESOLVE | options);
+
+ /** Screen space raytracing overview
+ *
+ * Following Frostbite stochastic SSR.
+ *
+ * - First pass Trace rays accross the depth buffer. The hit position and pdf are
+ * recorded in a RGBA16F render target for each ray (sample).
+ *
+ * - We downsample the previous frame color buffer.
+ *
+ * - For each final pixel, we gather neighboors rays and choose a color buffer
+ * mipmap for each ray using its pdf. (filtered importance sampling)
+ * We then evaluate the lighting from the probes and mix the results together.
+ */
+ psl->ssr_raytrace = DRW_pass_create("SSR Raytrace", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(trace_shader, psl->ssr_raytrace);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
+ DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
+ DRW_shgroup_uniform_vec4(grp, "ssrParameters", &effects->ssr_quality, 1);
+ DRW_shgroup_uniform_int(grp, "planar_count", &sldata->probes->num_planar, 1);
+ DRW_shgroup_uniform_float(grp, "maxRoughness", &effects->ssr_max_roughness, 1);
+ DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+ grp = DRW_shgroup_create(resolve_shader, psl->ssr_resolve);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
+ DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
+ DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_buffer(grp, "prevColorBuffer", &txl->color_double_buffer);
+ DRW_shgroup_uniform_mat4(grp, "PastViewProjectionMatrix", (float *)stl->g_data->prev_persmat);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_int(grp, "planar_count", &sldata->probes->num_planar, 1);
+ DRW_shgroup_uniform_int(grp, "probe_count", &sldata->probes->num_render_cube, 1);
+ DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
+ DRW_shgroup_uniform_float(grp, "borderFadeFactor", &effects->ssr_border_fac, 1);
+ DRW_shgroup_uniform_float(grp, "maxRoughness", &effects->ssr_max_roughness, 1);
+ DRW_shgroup_uniform_float(grp, "lodCubeMax", &sldata->probes->lod_cube_max, 1);
+ DRW_shgroup_uniform_float(grp, "lodPlanarMax", &sldata->probes->lod_planar_max, 1);
+ DRW_shgroup_uniform_float(grp, "fireflyFactor", &effects->ssr_firefly_fac, 1);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool);
+ DRW_shgroup_uniform_buffer(grp, "probePlanars", &vedata->txl->planar_pool);
+ DRW_shgroup_uniform_buffer(grp, "hitBuffer0", &stl->g_data->ssr_hit_output[0]);
+ if (effects->ssr_ray_count > 1) {
+ DRW_shgroup_uniform_buffer(grp, "hitBuffer1", &stl->g_data->ssr_hit_output[1]);
+ }
+ if (effects->ssr_ray_count > 2) {
+ DRW_shgroup_uniform_buffer(grp, "hitBuffer2", &stl->g_data->ssr_hit_output[2]);
+ }
+ if (effects->ssr_ray_count > 3) {
+ DRW_shgroup_uniform_buffer(grp, "hitBuffer3", &stl->g_data->ssr_hit_output[3]);
+ }
+
+ DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &effects->ao_dist, 2);
+ if (effects->use_ao) {
+ DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &vedata->txl->gtao_horizons);
+ DRW_shgroup_uniform_ivec2(grp, "aoHorizonTexSize", (int *)vedata->stl->effects->ao_texsize, 1);
+ }
+ else {
+ /* Use shadow_pool as fallback to avoid sampling problem on certain platform, see: T52593 */
+ DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &sldata->shadow_pool);
+ }
+
+ DRW_shgroup_call_add(grp, quad, NULL);
+ }
+}
+
+void EEVEE_refraction_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if ((effects->enabled_effects & EFFECT_REFRACT) != 0) {
+ DRW_framebuffer_texture_attach(fbl->refract_fb, txl->refract_color, 0, 0);
+ DRW_framebuffer_blit(fbl->main, fbl->refract_fb, false, false);
+ EEVEE_downsample_buffer(vedata, fbl->downsample_fb, txl->refract_color, 9);
+
+ /* Restore */
+ DRW_framebuffer_bind(fbl->main);
+ }
+}
+
+void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if (((effects->enabled_effects & EFFECT_SSR) != 0) && stl->g_data->valid_double_buffer) {
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ e_data.depth_src = dtxl->depth;
+
+ DRW_stats_group_start("SSR");
+
+ for (int i = 0; i < effects->ssr_ray_count; ++i) {
+ DRW_framebuffer_texture_attach(fbl->screen_tracing_fb, stl->g_data->ssr_hit_output[i], i, 0);
+ }
+ DRW_framebuffer_bind(fbl->screen_tracing_fb);
+
+ /* Raytrace. */
+ DRW_draw_pass(psl->ssr_raytrace);
+
+ for (int i = 0; i < effects->ssr_ray_count; ++i) {
+ DRW_framebuffer_texture_detach(stl->g_data->ssr_hit_output[i]);
+ }
+
+ EEVEE_downsample_buffer(vedata, fbl->downsample_fb, txl->color_double_buffer, 9);
+
+ /* Resolve at fullres */
+ DRW_framebuffer_texture_detach(dtxl->depth);
+ DRW_framebuffer_texture_detach(txl->ssr_normal_input);
+ DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
+ DRW_framebuffer_bind(fbl->main);
+ DRW_draw_pass(psl->ssr_resolve);
+
+ /* Restore */
+ DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
+ DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
+ DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
+ DRW_framebuffer_bind(fbl->main);
+
+ DRW_stats_group_end();
+ }
+}
+
+void EEVEE_screen_raytrace_free(void)
+{
+ for (int i = 0; i < SSR_MAX_SHADER; ++i) {
+ DRW_SHADER_FREE_SAFE(e_data.ssr_sh[i]);
+ }
+}
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
new file mode 100644
index 00000000000..4efdfb0fb84
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -0,0 +1,260 @@
+/*
+ * 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 eevee_subsurface.c
+ * \ingroup draw_engine
+ *
+ * Screen space subsurface scattering technique.
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_dynstr.h"
+
+#include "eevee_private.h"
+#include "GPU_texture.h"
+
+static struct {
+ struct GPUShader *sss_sh[3];
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_effect_subsurface_frag_glsl[];
+
+static void eevee_create_shader_subsurface(void)
+{
+ e_data.sss_sh[0] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define FIRST_PASS\n");
+ e_data.sss_sh[1] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define SECOND_PASS\n");
+ e_data.sss_sh[2] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define SECOND_PASS\n"
+ "#define USE_SEP_ALBEDO\n");
+}
+
+int EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ const float *viewport_size = DRW_viewport_size_get();
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ if (BKE_collection_engine_property_value_get_bool(props, "sss_enable")) {
+ effects->sss_sample_count = 1 + BKE_collection_engine_property_value_get_int(props, "sss_samples") * 2;
+ effects->sss_jitter_threshold = BKE_collection_engine_property_value_get_float(props, "sss_jitter_threshold");
+ effects->sss_separate_albedo = BKE_collection_engine_property_value_get_bool(props, "sss_separate_albedo");
+
+ /* Shaders */
+ if (!e_data.sss_sh[0]) {
+ eevee_create_shader_subsurface();
+ }
+
+ /* NOTE : we need another stencil because the stencil buffer is on the same texture
+ * as the depth buffer we are sampling from. This could be avoided if the stencil is
+ * a separate texture but that needs OpenGL 4.4 or ARB_texture_stencil8.
+ * OR OpenGL 4.3 / ARB_ES3_compatibility if using a renderbuffer instead */
+ DRWFboTexture texs[2] = {{&txl->sss_stencil, DRW_TEX_DEPTH_24_STENCIL_8, 0},
+ {&txl->sss_blur, DRW_TEX_RGBA_16, DRW_TEX_FILTER}};
+
+ DRW_framebuffer_init(&fbl->sss_blur_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1],
+ texs, 2);
+
+ DRWFboTexture tex_data = {&txl->sss_data, DRW_TEX_RGBA_16, DRW_TEX_FILTER};
+ DRW_framebuffer_init(&fbl->sss_clear_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1],
+ &tex_data, 1);
+
+ if (effects->sss_separate_albedo && (txl->sss_albedo == NULL)) {
+ txl->sss_albedo = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1],
+ DRW_TEX_RGB_11_11_10, 0, NULL);
+ }
+
+ return EFFECT_SSS;
+ }
+
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->sss_albedo);
+ DRW_TEXTURE_FREE_SAFE(txl->sss_data);
+ DRW_TEXTURE_FREE_SAFE(txl->sss_blur);
+ DRW_TEXTURE_FREE_SAFE(txl->sss_stencil);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
+
+ return 0;
+}
+
+void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if ((effects->enabled_effects & EFFECT_SSS) != 0) {
+ /** Screen Space SubSurface Scattering overview
+ * TODO
+ */
+ psl->sss_blur_ps = DRW_pass_create("Blur Horiz", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL);
+
+ psl->sss_resolve_ps = DRW_pass_create("Blur Vert", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE | DRW_STATE_STENCIL_EQUAL);
+ }
+}
+
+void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile)
+{
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_data);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1];
+ grp = DRW_shgroup_create(sh, psl->sss_resolve_ps);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_blur);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ if (effects->sss_separate_albedo) {
+ DRW_shgroup_uniform_buffer(grp, "sssAlbedo", &txl->sss_albedo);
+ }
+}
+
+void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if ((effects->enabled_effects & EFFECT_SSS) != 0) {
+ float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* Clear sss_data texture only... can this be done in a more clever way? */
+ DRW_framebuffer_bind(fbl->sss_clear_fb);
+ DRW_framebuffer_clear(true, false, false, clear, 0.0f);
+
+
+ DRW_framebuffer_texture_detach(txl->sss_data);
+ if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
+ DRW_framebuffer_texture_detach(txl->ssr_normal_input);
+ }
+ if ((effects->enabled_effects & EFFECT_SSR) != 0) {
+ DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
+ }
+
+ /* Start at slot 1 because slot 0 is txl->color */
+ int tex_slot = 1;
+ DRW_framebuffer_texture_attach(fbl->main, txl->sss_data, tex_slot++, 0);
+ if (effects->sss_separate_albedo) {
+ DRW_framebuffer_texture_attach(fbl->main, txl->sss_albedo, tex_slot++, 0);
+ }
+ if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
+ DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, tex_slot++, 0);
+ }
+ if ((effects->enabled_effects & EFFECT_SSR) != 0) {
+ DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, tex_slot++, 0);
+ }
+ DRW_framebuffer_bind(fbl->main);
+
+ DRW_draw_pass(psl->sss_pass);
+
+ /* Restore */
+ DRW_framebuffer_texture_detach(txl->sss_data);
+ if (effects->sss_separate_albedo) {
+ DRW_framebuffer_texture_detach(txl->sss_albedo);
+ }
+ if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
+ DRW_framebuffer_texture_detach(txl->ssr_normal_input);
+ }
+ if ((effects->enabled_effects & EFFECT_SSR) != 0) {
+ DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
+ }
+
+ DRW_framebuffer_texture_attach(fbl->sss_clear_fb, txl->sss_data, 0, 0);
+ if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) {
+ DRW_framebuffer_texture_attach(fbl->main, txl->ssr_normal_input, 1, 0);
+ }
+ if ((effects->enabled_effects & EFFECT_SSR) != 0) {
+ DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
+ }
+ }
+}
+
+void EEVEE_subsurface_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if ((effects->enabled_effects & EFFECT_SSS) != 0) {
+ float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ DRW_stats_group_start("SSS");
+
+ /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
+ DRW_framebuffer_blit(fbl->main, fbl->sss_blur_fb, false, true);
+
+ DRW_framebuffer_texture_detach(dtxl->depth);
+
+ /* First horizontal pass */
+ DRW_framebuffer_bind(fbl->sss_blur_fb);
+ DRW_framebuffer_clear(true, false, false, clear, 0.0f);
+ DRW_draw_pass(psl->sss_blur_ps);
+
+ /* First vertical pass + Resolve */
+ DRW_framebuffer_texture_detach(txl->sss_stencil);
+ DRW_framebuffer_texture_attach(fbl->main, txl->sss_stencil, 0, 0);
+ DRW_framebuffer_bind(fbl->main);
+ DRW_draw_pass(psl->sss_resolve_ps);
+
+ /* Restore */
+ DRW_framebuffer_texture_detach(txl->sss_stencil);
+ DRW_framebuffer_texture_attach(fbl->sss_blur_fb, txl->sss_stencil, 0, 0);
+ DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
+
+ DRW_stats_group_end();
+ }
+}
+
+void EEVEE_subsurface_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.sss_sh[0]);
+ DRW_SHADER_FREE_SAFE(e_data.sss_sh[1]);
+ DRW_SHADER_FREE_SAFE(e_data.sss_sh[2]);
+}
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
new file mode 100644
index 00000000000..5faac4c42cc
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -0,0 +1,196 @@
+/*
+ * 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 eevee_temporal_sampling.c
+ * \ingroup draw_engine
+ *
+ * Temporal super sampling technique
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_rand.h"
+
+#include "eevee_private.h"
+#include "GPU_texture.h"
+
+static struct {
+ /* Temporal Anti Aliasing */
+ struct GPUShader *taa_resolve_sh;
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_effect_temporal_aa_glsl[];
+
+static void eevee_create_shader_temporal_sampling(void)
+{
+ e_data.taa_resolve_sh = DRW_shader_create_fullscreen(datatoc_effect_temporal_aa_glsl, NULL);
+}
+
+int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ if (BKE_collection_engine_property_value_get_int(props, "taa_samples") != 1 &&
+ /* FIXME the motion blur camera evaluation is tagging view_updated
+ * thus making the TAA always reset and never stopping rendering. */
+ (effects->enabled_effects & EFFECT_MOTION_BLUR) == 0)
+ {
+ const float *viewport_size = DRW_viewport_size_get();
+ float persmat[4][4], viewmat[4][4];
+
+ if (!e_data.taa_resolve_sh) {
+ eevee_create_shader_temporal_sampling();
+ }
+
+ /* Until we support reprojection, we need to make sure
+ * that the history buffer contains correct information. */
+ bool view_is_valid = stl->g_data->valid_double_buffer;
+
+ view_is_valid = view_is_valid && (stl->g_data->view_updated == false);
+
+ effects->taa_total_sample = BKE_collection_engine_property_value_get_int(props, "taa_samples");
+ MAX2(effects->taa_total_sample, 0);
+
+ DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_get(effects->overide_winmat, DRW_MAT_WIN);
+ view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN);
+ copy_m4_m4(effects->prev_drw_persmat, persmat);
+
+ /* Prevent ghosting from probe data. */
+ view_is_valid = view_is_valid && (effects->prev_drw_support == DRW_state_draw_support());
+ effects->prev_drw_support = DRW_state_draw_support();
+
+ if (view_is_valid &&
+ ((effects->taa_total_sample == 0) ||
+ (effects->taa_current_sample < effects->taa_total_sample)))
+ {
+ effects->taa_current_sample += 1;
+
+ effects->taa_alpha = 1.0f / (float)(effects->taa_current_sample);
+
+ double ht_point[2];
+ double ht_offset[2] = {0.0, 0.0};
+ unsigned int ht_primes[2] = {2, 3};
+
+ BLI_halton_2D(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point);
+
+ window_translate_m4(
+ effects->overide_winmat, persmat,
+ ((float)(ht_point[0]) * 2.0f - 1.0f) / viewport_size[0],
+ ((float)(ht_point[1]) * 2.0f - 1.0f) / viewport_size[1]);
+
+ mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat);
+ invert_m4_m4(effects->overide_persinv, effects->overide_persmat);
+ invert_m4_m4(effects->overide_wininv, effects->overide_winmat);
+
+ DRW_viewport_matrix_override_set(effects->overide_persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(effects->overide_persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(effects->overide_winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(effects->overide_wininv, DRW_MAT_WININV);
+ }
+ else {
+ effects->taa_current_sample = 1;
+ }
+
+ DRWFboTexture tex_double_buffer = {&txl->depth_double_buffer, DRW_TEX_DEPTH_24_STENCIL_8, 0};
+
+ DRW_framebuffer_init(&fbl->depth_double_buffer_fb, &draw_engine_eevee_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex_double_buffer, 1);
+
+ return EFFECT_TAA | EFFECT_DOUBLE_BUFFER | EFFECT_POST_BUFFER;
+ }
+
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->depth_double_buffer);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->depth_double_buffer_fb);
+
+ return 0;
+}
+
+void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if ((effects->enabled_effects & EFFECT_TAA) != 0) {
+ psl->taa_resolve = DRW_pass_create("Temporal AA Resolve", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.taa_resolve_sh, psl->taa_resolve);
+
+ DRW_shgroup_uniform_buffer(grp, "historyBuffer", &txl->color_double_buffer);
+ DRW_shgroup_uniform_buffer(grp, "colorBuffer", &txl->color);
+ DRW_shgroup_uniform_float(grp, "alpha", &effects->taa_alpha, 1);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ }
+}
+
+void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if ((effects->enabled_effects & EFFECT_TAA) != 0) {
+ if (effects->taa_current_sample != 1) {
+ DRW_framebuffer_bind(fbl->effect_fb);
+ DRW_draw_pass(psl->taa_resolve);
+
+ /* Restore the depth from sample 1. */
+ DRW_framebuffer_blit(fbl->depth_double_buffer_fb, fbl->main, true, false);
+
+ /* Special Swap */
+ SWAP(struct GPUFrameBuffer *, fbl->effect_fb, fbl->double_buffer);
+ SWAP(GPUTexture *, txl->color_post, txl->color_double_buffer);
+ effects->swap_double_buffer = false;
+ effects->source_buffer = txl->color_double_buffer;
+ effects->target_buffer = fbl->main;
+ }
+ else {
+ /* Save the depth buffer for the next frame.
+ * This saves us from doing anything special
+ * in the other mode engines. */
+ DRW_framebuffer_blit(fbl->main, fbl->depth_double_buffer_fb, true, false);
+ }
+
+ if ((effects->taa_total_sample == 0) ||
+ (effects->taa_current_sample < effects->taa_total_sample))
+ {
+ DRW_viewport_request_redraw();
+ }
+ }
+}
+
+void EEVEE_temporal_sampling_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.taa_resolve_sh);
+}
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
new file mode 100644
index 00000000000..dae4503dc32
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -0,0 +1,581 @@
+/*
+ * 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 eevee_volumes.c
+ * \ingroup draw_engine
+ *
+ * Volumetric effects rendering using frostbite approach.
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_dynstr.h"
+#include "BLI_rand.h"
+
+#include "DNA_object_force.h"
+#include "DNA_smoke_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_global.h" /* for G.debug_value */
+#include "BKE_modifier.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+
+#include "ED_screen.h"
+
+#include "eevee_private.h"
+#include "GPU_draw.h"
+#include "GPU_texture.h"
+
+static struct {
+ char *volumetric_common_lib;
+ char *volumetric_common_lamps_lib;
+
+ struct GPUShader *volumetric_clear_sh;
+ struct GPUShader *volumetric_scatter_sh;
+ struct GPUShader *volumetric_integration_sh;
+ struct GPUShader *volumetric_resolve_sh;
+
+ GPUTexture *color_src;
+ GPUTexture *depth_src;
+
+ /* List of all smoke domains rendered within this frame. */
+ ListBase smoke_domains;
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_bsdf_direct_lib_glsl[];
+extern char datatoc_octahedron_lib_glsl[];
+extern char datatoc_irradiance_lib_glsl[];
+extern char datatoc_lamps_lib_glsl[];
+extern char datatoc_volumetric_frag_glsl[];
+extern char datatoc_volumetric_geom_glsl[];
+extern char datatoc_volumetric_vert_glsl[];
+extern char datatoc_volumetric_resolve_frag_glsl[];
+extern char datatoc_volumetric_scatter_frag_glsl[];
+extern char datatoc_volumetric_integration_frag_glsl[];
+extern char datatoc_volumetric_lib_glsl[];
+extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
+
+static void eevee_create_shader_volumes(void)
+{
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl);
+ e_data.volumetric_common_lib = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lamps_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl);
+ e_data.volumetric_common_lamps_lib = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ e_data.volumetric_clear_sh = DRW_shader_create_with_lib(
+ datatoc_volumetric_vert_glsl,
+ datatoc_volumetric_geom_glsl,
+ datatoc_volumetric_frag_glsl,
+ e_data.volumetric_common_lib,
+ "#define VOLUMETRICS\n"
+ "#define CLEAR\n");
+ e_data.volumetric_scatter_sh = DRW_shader_create_with_lib(
+ datatoc_volumetric_vert_glsl,
+ datatoc_volumetric_geom_glsl,
+ datatoc_volumetric_scatter_frag_glsl,
+ e_data.volumetric_common_lamps_lib,
+ SHADER_DEFINES
+ "#define VOLUMETRICS\n"
+ "#define VOLUME_SHADOW\n");
+ e_data.volumetric_integration_sh = DRW_shader_create_with_lib(
+ datatoc_volumetric_vert_glsl,
+ datatoc_volumetric_geom_glsl,
+ datatoc_volumetric_integration_frag_glsl,
+ e_data.volumetric_common_lib, NULL);
+ e_data.volumetric_resolve_sh = DRW_shader_create_with_lib(
+ datatoc_gpu_shader_fullscreen_vert_glsl, NULL,
+ datatoc_volumetric_resolve_frag_glsl,
+ e_data.volumetric_common_lib, NULL);
+}
+
+int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+
+ const float *viewport_size = DRW_viewport_size_get();
+
+ BLI_listbase_clear(&e_data.smoke_domains);
+
+ if (BKE_collection_engine_property_value_get_bool(props, "volumetric_enable")) {
+
+ /* Shaders */
+ if (!e_data.volumetric_scatter_sh) {
+ eevee_create_shader_volumes();
+ }
+
+ if (sldata->volumetrics == NULL) {
+ sldata->volumetrics = MEM_callocN(sizeof(EEVEE_VolumetricsInfo), "EEVEE_VolumetricsInfo");
+ }
+
+ EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics;
+
+ int tile_size = BKE_collection_engine_property_value_get_int(props, "volumetric_tile_size");
+
+ /* Find Froxel Texture resolution. */
+ int froxel_tex_size[3];
+
+ froxel_tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
+ froxel_tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
+ froxel_tex_size[2] = max_ii(BKE_collection_engine_property_value_get_int(props, "volumetric_samples"), 1);
+
+ volumetrics->volume_coord_scale[0] = viewport_size[0] / (float)(tile_size * froxel_tex_size[0]);
+ volumetrics->volume_coord_scale[1] = viewport_size[1] / (float)(tile_size * froxel_tex_size[1]);
+
+ /* TODO compute snap to maxZBuffer for clustered rendering */
+
+ if ((volumetrics->froxel_tex_size[0] != froxel_tex_size[0]) ||
+ (volumetrics->froxel_tex_size[1] != froxel_tex_size[1]) ||
+ (volumetrics->froxel_tex_size[2] != froxel_tex_size[2]))
+ {
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
+ volumetrics->froxel_tex_size[0] = froxel_tex_size[0];
+ volumetrics->froxel_tex_size[1] = froxel_tex_size[1];
+ volumetrics->froxel_tex_size[2] = froxel_tex_size[2];
+
+ volumetrics->inv_tex_size[0] = 1.0f / (float)(volumetrics->froxel_tex_size[0]);
+ volumetrics->inv_tex_size[1] = 1.0f / (float)(volumetrics->froxel_tex_size[1]);
+ volumetrics->inv_tex_size[2] = 1.0f / (float)(volumetrics->froxel_tex_size[2]);
+ }
+
+ /* Like frostbite's paper, 5% blend of the new frame. */
+ volumetrics->history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
+
+ if (txl->volume_prop_scattering == NULL) {
+ /* Volume properties: We evaluate all volumetric objects
+ * and store their final properties into each froxel */
+ txl->volume_prop_scattering = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_extinction = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_emission = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_phase = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RG_16, DRW_TEX_FILTER, NULL);
+
+ /* Volume scattering: We compute for each froxel the
+ * Scattered light towards the view. We also resolve temporal
+ * super sampling during this stage. */
+ txl->volume_scatter = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_transmittance = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+
+ /* Final integration: We compute for each froxel the
+ * amount of scattered light and extinction coef at this
+ * given depth. We use theses textures as double buffer
+ * for the volumetric history. */
+ txl->volume_scatter_history = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_transmittance_history = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ }
+
+ /* Temporal Super sampling jitter */
+ double ht_point[3];
+ double ht_offset[3] = {0.0, 0.0};
+ unsigned int ht_primes[3] = {3, 7, 2};
+ unsigned int current_sample = 0;
+
+ /* If TAA is in use do not use the history buffer. */
+ bool do_taa = ((effects->enabled_effects & EFFECT_TAA) != 0);
+
+ if (draw_ctx->evil_C != NULL) {
+ struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
+ do_taa = do_taa && (ED_screen_animation_no_scrub(wm) == NULL);
+ }
+
+ if (do_taa) {
+ volumetrics->history_alpha = 0.0f;
+ current_sample = effects->taa_current_sample - 1;
+ effects->volume_current_sample = -1;
+ }
+ else {
+ const unsigned int max_sample = (ht_primes[0] * ht_primes[1] * ht_primes[2]);
+ current_sample = effects->volume_current_sample = (effects->volume_current_sample + 1) % max_sample;
+ if (current_sample != max_sample - 1) {
+ DRW_viewport_request_redraw();
+ }
+ }
+ BLI_halton_3D(ht_primes, ht_offset, current_sample, ht_point);
+
+ volumetrics->jitter[0] = (float)ht_point[0];
+ volumetrics->jitter[1] = (float)ht_point[1];
+ volumetrics->jitter[2] = (float)ht_point[2];
+
+ /* Framebuffer setup */
+ DRWFboTexture tex_vol[4] = {{&txl->volume_prop_scattering, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
+ {&txl->volume_prop_extinction, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
+ {&txl->volume_prop_emission, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
+ {&txl->volume_prop_phase, DRW_TEX_RG_16, DRW_TEX_FILTER}};
+
+ DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type,
+ (int)froxel_tex_size[0], (int)froxel_tex_size[1],
+ tex_vol, 4);
+
+ DRWFboTexture tex_vol_scat[2] = {{&txl->volume_scatter, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
+ {&txl->volume_transmittance, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}};
+
+ DRW_framebuffer_init(&fbl->volumetric_scat_fb, &draw_engine_eevee_type,
+ (int)froxel_tex_size[0], (int)froxel_tex_size[1],
+ tex_vol_scat, 2);
+
+ DRWFboTexture tex_vol_integ[2] = {{&txl->volume_scatter_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
+ {&txl->volume_transmittance_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}};
+
+ DRW_framebuffer_init(&fbl->volumetric_integ_fb, &draw_engine_eevee_type,
+ (int)froxel_tex_size[0], (int)froxel_tex_size[1],
+ tex_vol_integ, 2);
+
+ volumetrics->integration_start = BKE_collection_engine_property_value_get_float(props, "volumetric_start");
+ volumetrics->integration_end = BKE_collection_engine_property_value_get_float(props, "volumetric_end");
+ volumetrics->sample_distribution = 4.0f * (1.00001f - BKE_collection_engine_property_value_get_float(props, "volumetric_sample_distribution"));
+ volumetrics->use_volume_shadows = BKE_collection_engine_property_value_get_bool(props, "volumetric_shadows");
+ volumetrics->light_clamp = BKE_collection_engine_property_value_get_float(props, "volumetric_light_clamp");
+
+ if (volumetrics->use_volume_shadows) {
+ volumetrics->shadow_step_count = (float)BKE_collection_engine_property_value_get_int(props, "volumetric_shadow_samples");
+ }
+ else {
+ volumetrics->shadow_step_count = 0;
+ }
+
+ if (DRW_viewport_is_persp_get()) {
+ const float clip_start = stl->g_data->viewvecs[0][2];
+ /* Negate */
+ float near = volumetrics->integration_start = min_ff(-volumetrics->integration_start, clip_start - 1e-4f);
+ float far = volumetrics->integration_end = min_ff(-volumetrics->integration_end, near - 1e-4f);
+
+ volumetrics->depth_param[0] = (far - near * exp2(1.0f / volumetrics->sample_distribution)) / (far - near);
+ volumetrics->depth_param[1] = (1.0f - volumetrics->depth_param[0]) / near;
+ volumetrics->depth_param[2] = volumetrics->sample_distribution;
+ }
+ else {
+ const float clip_start = stl->g_data->viewvecs[0][2];
+ const float clip_end = stl->g_data->viewvecs[1][2];
+ volumetrics->integration_start = min_ff(volumetrics->integration_end, clip_start);
+ volumetrics->integration_end = max_ff(-volumetrics->integration_end, clip_end);
+
+ volumetrics->depth_param[0] = volumetrics->integration_start;
+ volumetrics->depth_param[1] = volumetrics->integration_end;
+ volumetrics->depth_param[2] = 1.0f / (volumetrics->integration_end - volumetrics->integration_start);
+ }
+
+ /* Disable clamp if equal to 0. */
+ if (volumetrics->light_clamp == 0.0) {
+ volumetrics->light_clamp = FLT_MAX;
+ }
+
+ volumetrics->use_lights = BKE_collection_engine_property_value_get_bool(props, "volumetric_lights");
+
+ return EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER;
+ }
+
+ /* Cleanup to release memory */
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
+ DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
+
+ return 0;
+}
+
+void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics;
+ static int zero = 0;
+ DRWShadingGroup *grp;
+
+ /* Quick breakdown of the Volumetric rendering:
+ *
+ * The rendering is separated in 4 stages:
+ *
+ * - Material Parameters : we collect volume properties of
+ * all participating media in the scene and store them in
+ * a 3D texture aligned with the 3D frustum.
+ * This is done in 2 passes, one that clear the texture
+ * and/or evaluate the world volumes, and the 2nd one that
+ * additively render object volumes.
+ *
+ * - Light Scattering : the volume properties then are sampled
+ * and light scattering is evaluated for each cell of the
+ * volume texture. Temporal supersampling (if enabled) occurs here.
+ *
+ * - Volume Integration : the scattered light and extinction is
+ * integrated (accumulated) along the viewrays. The result is stored
+ * for every cell in another texture.
+ *
+ * - Fullscreen Resolve : From the previous stage, we get two
+ * 3D textures that contains integrated scatered light and extinction
+ * for "every" positions in the frustum. We only need to sample
+ * them and blend the scene color with thoses factors. This also
+ * work for alpha blended materials.
+ **/
+
+ /* World pass is not additive as it also clear the buffer. */
+ psl->volumetric_world_ps = DRW_pass_create("Volumetric World", DRW_STATE_WRITE_COLOR);
+
+ /* World Volumetric */
+ struct World *wo = scene->world;
+ if (wo != NULL && wo->use_nodes && wo->nodetree) {
+ struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
+
+ grp = DRW_shgroup_material_empty_tri_batch_create(mat, psl->volumetric_world_ps, volumetrics->froxel_tex_size[2]);
+
+ if (grp) {
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1);
+ DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
+ DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
+ DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1);
+ }
+ }
+ else {
+ /* If no world or volume material is present just clear the buffer with this drawcall */
+ grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps, volumetrics->froxel_tex_size[2]);
+
+ DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1);
+ }
+
+ /* Volumetric Objects */
+ psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+
+ psl->volumetric_scatter_ps = DRW_pass_create("Volumetric Scattering", DRW_STATE_WRITE_COLOR);
+ grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_scatter_sh, psl->volumetric_scatter_ps, volumetrics->froxel_tex_size[2]);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
+ DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
+ DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1);
+ DRW_shgroup_uniform_mat4(grp, "PastViewProjectionMatrix", (float *)stl->g_data->prev_persmat);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_int(grp, "light_count", (volumetrics->use_lights) ? &sldata->lamps->num_light : &zero, 1);
+ DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool);
+ DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_pool);
+ DRW_shgroup_uniform_float(grp, "volume_light_clamp", &volumetrics->light_clamp, 1);
+ DRW_shgroup_uniform_float(grp, "volume_shadows_steps", &volumetrics->shadow_step_count, 1);
+ DRW_shgroup_uniform_float(grp, "volume_history_alpha", &volumetrics->history_alpha, 1);
+ DRW_shgroup_uniform_buffer(grp, "volumeScattering", &txl->volume_prop_scattering);
+ DRW_shgroup_uniform_buffer(grp, "volumeExtinction", &txl->volume_prop_extinction);
+ DRW_shgroup_uniform_buffer(grp, "volumeEmission", &txl->volume_prop_emission);
+ DRW_shgroup_uniform_buffer(grp, "volumePhase", &txl->volume_prop_phase);
+ DRW_shgroup_uniform_buffer(grp, "historyScattering", &txl->volume_scatter_history);
+ DRW_shgroup_uniform_buffer(grp, "historyTransmittance", &txl->volume_transmittance_history);
+
+ psl->volumetric_integration_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR);
+ grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh, psl->volumetric_integration_ps, volumetrics->froxel_tex_size[2]);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
+ DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
+ DRW_shgroup_uniform_buffer(grp, "volumeScattering", &txl->volume_scatter);
+ DRW_shgroup_uniform_buffer(grp, "volumeExtinction", &txl->volume_transmittance);
+
+ psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR);
+ grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
+ DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
+ DRW_shgroup_uniform_buffer(grp, "inScattering", &txl->volume_scatter);
+ DRW_shgroup_uniform_buffer(grp, "inTransmittance", &txl->volume_transmittance);
+ DRW_shgroup_uniform_buffer(grp, "inSceneColor", &e_data.color_src);
+ DRW_shgroup_uniform_buffer(grp, "inSceneDepth", &e_data.depth_src);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ }
+}
+
+void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Scene *scene, Object *ob)
+{
+ float *texcoloc = NULL;
+ float *texcosize = NULL;
+ struct ModifierData *md = NULL;
+ EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics;
+ Material *ma = give_current_material(ob, 1);
+
+ if (ma == NULL) {
+ return;
+ }
+
+ struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
+
+ DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, volumetrics->froxel_tex_size[2]);
+
+ /* Making sure it's updated. */
+ invert_m4_m4(ob->imat, ob->obmat);
+
+ BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize);
+
+ if (grp) {
+ DRW_shgroup_uniform_mat4(grp, "volumeObjectMatrix", (float *)ob->imat);
+ DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
+ DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
+ DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1);
+ DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
+ DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
+ DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1);
+ }
+
+ /* Smoke Simulation */
+ if (((ob->base_flag & BASE_FROMDUPLI) == 0) &&
+ (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
+ (modifier_isEnabled(scene, md, eModifierMode_Realtime)))
+ {
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ SmokeDomainSettings *sds = smd->domain;
+ /* Don't show smoke before simulation starts, this could be made an option in the future. */
+ const bool show_smoke = (CFRA >= sds->point_cache[0]->startframe);
+
+ if (sds->fluid && show_smoke) {
+ if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
+ GPU_create_smoke(smd, 0);
+ }
+ else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) {
+ GPU_create_smoke(smd, 1);
+ }
+ BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(smd));
+ }
+
+ if (sds->tex != NULL) {
+ DRW_shgroup_uniform_buffer(grp, "sampdensity", &sds->tex);
+ }
+ if (sds->tex_flame != NULL) {
+ DRW_shgroup_uniform_buffer(grp, "sampflame", &sds->tex_flame);
+ }
+ }
+}
+
+void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+ if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
+ DRW_stats_group_start("Volumetrics");
+
+ /* Step 1: Participating Media Properties */
+ DRW_framebuffer_bind(fbl->volumetric_fb);
+ DRW_draw_pass(psl->volumetric_world_ps);
+ DRW_draw_pass(psl->volumetric_objects_ps);
+
+ /* Step 2: Scatter Light */
+ DRW_framebuffer_bind(fbl->volumetric_scat_fb);
+ DRW_draw_pass(psl->volumetric_scatter_ps);
+
+ /* Step 3: Integration */
+ DRW_framebuffer_bind(fbl->volumetric_integ_fb);
+ DRW_draw_pass(psl->volumetric_integration_ps);
+
+ /* Swap volume history buffers */
+ SWAP(struct GPUFrameBuffer *, fbl->volumetric_scat_fb, fbl->volumetric_integ_fb);
+ SWAP(GPUTexture *, txl->volume_scatter, txl->volume_scatter_history);
+ SWAP(GPUTexture *, txl->volume_transmittance, txl->volume_transmittance_history);
+
+ /* Restore */
+ DRW_framebuffer_bind(fbl->main);
+
+ DRW_stats_group_end();
+ }
+}
+
+void EEVEE_volumes_resolve(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ e_data.color_src = txl->color;
+ e_data.depth_src = dtxl->depth;
+
+ /* Step 4: Apply for opaque */
+ DRW_framebuffer_bind(fbl->effect_fb);
+ DRW_draw_pass(psl->volumetric_resolve_ps);
+
+ /* Swap the buffers and rebind depth to the current buffer */
+ DRW_framebuffer_texture_detach(dtxl->depth);
+ SWAP(struct GPUFrameBuffer *, fbl->main, fbl->effect_fb);
+ SWAP(GPUTexture *, txl->color, txl->color_post);
+ DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
+ }
+}
+
+void EEVEE_volumes_free_smoke_textures(void)
+{
+ /* Free Smoke Textures after rendering */
+ for (LinkData *link = e_data.smoke_domains.first; link; link = link->next) {
+ SmokeModifierData *smd = (SmokeModifierData *)link->data;
+ GPU_free_smoke(smd);
+ }
+ BLI_freelistN(&e_data.smoke_domains);
+}
+
+void EEVEE_volumes_free(void)
+{
+ MEM_SAFE_FREE(e_data.volumetric_common_lib);
+ MEM_SAFE_FREE(e_data.volumetric_common_lamps_lib);
+
+ DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
+ DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_sh);
+ DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh);
+ DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
new file mode 100644
index 00000000000..5ec72833379
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -0,0 +1,377 @@
+
+/* 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 */
+
+#if defined(MESH_SHADER)
+# if !defined(USE_ALPHA_HASH)
+# if !defined(USE_ALPHA_CLIP)
+# if !defined(SHADOW_SHADER)
+# if !defined(USE_MULTIPLY)
+# if !defined(USE_ALPHA_BLEND)
+# define ENABLE_DEFERED_AO
+# endif
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifndef ENABLE_DEFERED_AO
+# if defined(STEP_RESOLVE)
+# define ENABLE_DEFERED_AO
+# endif
+#endif
+
+#define MAX_PHI_STEP 32
+#define MAX_SEARCH_ITER 32
+#define MAX_LOD 6.0
+
+#ifndef UTIL_TEX
+#define UTIL_TEX
+uniform sampler2DArray utilTex;
+#endif /* UTIL_TEX */
+
+uniform vec4 aoParameters[2];
+uniform sampler2DArray horizonBuffer;
+
+/* Cannot use textureSize(horizonBuffer) when rendering to it */
+uniform ivec2 aoHorizonTexSize;
+
+#define aoDistance aoParameters[0].x
+#define aoSamples aoParameters[0].y
+#define aoFactor aoParameters[0].z
+#define aoInvSamples aoParameters[0].w
+
+#define aoOffset aoParameters[1].x /* UNUSED */
+#define aoBounceFac aoParameters[1].y
+#define aoQuality aoParameters[1].z
+#define aoSettings aoParameters[1].w
+
+#define USE_AO 1
+#define USE_BENT_NORMAL 2
+#define USE_DENOISE 4
+
+vec2 pack_horizons(vec2 v) { return v * 0.5 + 0.5; }
+vec2 unpack_horizons(vec2 v) { return v * 2.0 - 1.0; }
+
+/* Returns the texel coordinate in horizonBuffer
+ * for a given fullscreen coord */
+ivec2 get_hr_co(ivec2 fs_co)
+{
+ bvec2 quarter = notEqual(fs_co & ivec2(1), ivec2(0));
+
+ ivec2 hr_co = fs_co / 2;
+ hr_co += ivec2(quarter) * (aoHorizonTexSize / 2);
+
+ return hr_co;
+}
+
+/* Returns the texel coordinate in fullscreen (depthBuffer)
+ * for a given horizonBuffer coord */
+ivec2 get_fs_co(ivec2 hr_co)
+{
+ hr_co *= 2;
+ bvec2 quarter = greaterThanEqual(hr_co, aoHorizonTexSize);
+
+ hr_co -= ivec2(quarter) * (aoHorizonTexSize - 1);
+
+ return hr_co;
+}
+
+/* Returns the phi angle in horizonBuffer
+ * for a given horizonBuffer coord */
+float get_phi(ivec2 hr_co, ivec2 fs_co, float sample)
+{
+ bvec2 quarter = greaterThanEqual(hr_co, aoHorizonTexSize / 2);
+ ivec2 tex_co = ((int(aoSettings) & USE_DENOISE) != 0) ? hr_co - ivec2(quarter) * (aoHorizonTexSize / 2) : fs_co;
+ float blue_noise = texture(utilTex, vec3((vec2(tex_co) + 0.5) / LUT_SIZE, 2.0)).r;
+
+ float phi = sample * aoInvSamples;
+
+ if ((int(aoSettings) & USE_DENOISE) != 0) {
+ /* Interleaved jitter for spatial 2x2 denoising */
+ phi += 0.25 * aoInvSamples * (float(quarter.x) + 2.0 * float(quarter.y));
+ blue_noise *= 0.25;
+ }
+ /* Blue noise is scaled to cover the rest of the range. */
+ phi += aoInvSamples * blue_noise;
+ phi *= M_PI;
+
+ return phi;
+}
+
+/* Returns direction jittered offset for a given fullscreen coord */
+float get_offset(ivec2 fs_co, float sample)
+{
+ float offset = sample * aoInvSamples;
+
+ /* Interleaved jitter for spatial 2x2 denoising */
+ offset += 0.25 * dot(vec2(1.0), vec2(fs_co & 1));
+ offset += texture(utilTex, vec3((vec2(fs_co / 2) + 0.5 + 16.0) / LUT_SIZE, 2.0)).r;
+ return offset;
+}
+
+/* Returns maximum screen distance an AO ray can travel for a given view depth */
+vec2 get_max_dir(float view_depth)
+{
+ float homcco = ProjectionMatrix[2][3] * view_depth + ProjectionMatrix[3][3];
+ float max_dist = aoDistance / homcco;
+ return vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * max_dist;
+}
+
+void get_max_horizon_grouped(vec4 co1, vec4 co2, vec3 x, float lod, inout float h)
+{
+ co1 *= mipRatio[int(lod + 1.0)].xyxy; /* +1 because we are using half res top level */
+ co2 *= mipRatio[int(lod + 1.0)].xyxy; /* +1 because we are using half res top level */
+
+ float depth1 = textureLod(maxzBuffer, co1.xy, floor(lod)).r;
+ float depth2 = textureLod(maxzBuffer, co1.zw, floor(lod)).r;
+ float depth3 = textureLod(maxzBuffer, co2.xy, floor(lod)).r;
+ float depth4 = textureLod(maxzBuffer, co2.zw, floor(lod)).r;
+
+ vec4 len, s_h;
+
+ vec3 s1 = get_view_space_from_depth(co1.xy, depth1); /* s View coordinate */
+ vec3 omega_s1 = s1 - x;
+ len.x = length(omega_s1);
+ s_h.x = omega_s1.z / len.x;
+
+ vec3 s2 = get_view_space_from_depth(co1.zw, depth2); /* s View coordinate */
+ vec3 omega_s2 = s2 - x;
+ len.y = length(omega_s2);
+ s_h.y = omega_s2.z / len.y;
+
+ vec3 s3 = get_view_space_from_depth(co2.xy, depth3); /* s View coordinate */
+ vec3 omega_s3 = s3 - x;
+ len.z = length(omega_s3);
+ s_h.z = omega_s3.z / len.z;
+
+ vec3 s4 = get_view_space_from_depth(co2.zw, depth4); /* s View coordinate */
+ vec3 omega_s4 = s4 - x;
+ len.w = length(omega_s4);
+ s_h.w = omega_s4.z / len.w;
+
+ /* Blend weight after half the aoDistance to fade artifacts */
+ vec4 blend = saturate((1.0 - len / aoDistance) * 2.0);
+
+ h = mix(h, max(h, s_h.x), blend.x);
+ h = mix(h, max(h, s_h.y), blend.y);
+ h = mix(h, max(h, s_h.z), blend.z);
+ h = mix(h, max(h, s_h.w), blend.w);
+}
+
+vec2 search_horizon_sweep(float phi, vec3 pos, vec2 uvs, float jitter, vec2 max_dir)
+{
+ vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */
+
+ max_dir *= max_v2(abs(t_phi));
+
+ /* Convert to pixel space. */
+ t_phi /= vec2(textureSize(maxzBuffer, 0));
+
+ /* Avoid division by 0 */
+ t_phi += vec2(1e-5);
+
+ jitter *= 0.25;
+
+ /* Compute end points */
+ vec2 corner1 = min(vec2(1.0) - uvs, max_dir); /* Top right */
+ vec2 corner2 = max(vec2(0.0) - uvs, -max_dir); /* Bottom left */
+ vec2 iter1 = corner1 / t_phi;
+ vec2 iter2 = corner2 / t_phi;
+
+ vec2 min_iter = max(-iter1, -iter2);
+ vec2 max_iter = max( iter1, iter2);
+
+ vec2 times = vec2(-min_v2(min_iter), min_v2(max_iter));
+
+ vec2 h = vec2(-1.0); /* init at cos(pi) */
+
+ /* This is freaking sexy optimized. */
+ for (float i = 0.0, ofs = 4.0, time = -1.0;
+ i < MAX_SEARCH_ITER && time > times.x;
+ i++, time -= ofs, ofs = min(exp2(MAX_LOD) * 4.0, ofs + ofs * aoQuality))
+ {
+ vec4 t = max(times.xxxx, vec4(time) - (vec4(0.25, 0.5, 0.75, 1.0) - jitter) * ofs);
+ vec4 cos1 = uvs.xyxy + t_phi.xyxy * t.xxyy;
+ vec4 cos2 = uvs.xyxy + t_phi.xyxy * t.zzww;
+ float lod = min(MAX_LOD, max(i - jitter * 4.0, 0.0) * aoQuality);
+ get_max_horizon_grouped(cos1, cos2, pos, lod, h.y);
+ }
+
+ for (float i = 0.0, ofs = 4.0, time = 1.0;
+ i < MAX_SEARCH_ITER && time < times.y;
+ i++, time += ofs, ofs = min(exp2(MAX_LOD) * 4.0, ofs + ofs * aoQuality))
+ {
+ vec4 t = min(times.yyyy, vec4(time) + (vec4(0.25, 0.5, 0.75, 1.0) - jitter) * ofs);
+ vec4 cos1 = uvs.xyxy + t_phi.xyxy * t.xxyy;
+ vec4 cos2 = uvs.xyxy + t_phi.xyxy * t.zzww;
+ float lod = min(MAX_LOD, max(i - jitter * 4.0, 0.0) * aoQuality);
+ get_max_horizon_grouped(cos1, cos2, pos, lod, h.x);
+ }
+
+ return h;
+}
+
+void integrate_slice(vec3 normal, float phi, vec2 horizons, inout float visibility, inout vec3 bent_normal)
+{
+ /* TODO OPTI Could be precomputed. */
+ vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */
+
+ /* Projecting Normal to Plane P defined by t_phi and omega_o */
+ vec3 np = vec3(t_phi.y, -t_phi.x, 0.0); /* Normal vector to Integration plane */
+ vec3 t = vec3(-t_phi, 0.0);
+ vec3 n_proj = normal - np * dot(np, normal);
+ float n_proj_len = max(1e-16, length(n_proj));
+
+ float cos_n = clamp(n_proj.z / n_proj_len, -1.0, 1.0);
+ float n = sign(dot(n_proj, t)) * fast_acos(cos_n); /* Angle between view vec and normal */
+
+ /* (Slide 54) */
+ vec2 h = fast_acos(horizons);
+ h.x = -h.x;
+
+ /* Clamping thetas (slide 58) */
+ h.x = n + max(h.x - n, -M_PI_2);
+ h.y = n + min(h.y - n, M_PI_2);
+
+ /* Solving inner integral */
+ vec2 h_2 = 2.0 * h;
+ vec2 vd = -cos(h_2 - n) + cos_n + h_2 * sin(n);
+ float vis = (vd.x + vd.y) * 0.25 * n_proj_len;
+
+ visibility += vis;
+
+ /* Finding Bent normal */
+ float b_angle = (h.x + h.y) * 0.5;
+ /* The 0.5 factor below is here to equilibrate the accumulated vectors.
+ * (sin(b_angle) * -t_phi) will accumulate to (phi_step * result_nor.xy * 0.5).
+ * (cos(b_angle) * 0.5) will accumulate to (phi_step * result_nor.z * 0.5). */
+ bent_normal += vec3(sin(b_angle) * -t_phi, cos(b_angle) * 0.5);
+}
+
+void denoise_ao(vec3 normal, float frag_depth, inout float visibility, inout vec3 bent_normal)
+{
+ vec2 d_sign = vec2(ivec2(gl_FragCoord.xy) & 1) - 0.5;
+
+ if ((int(aoSettings) & USE_DENOISE) == 0) {
+ d_sign *= 0.0;
+ }
+
+ /* 2x2 Bilateral Filter using derivatives. */
+ vec2 n_step = step(-0.2, -abs(vec2(length(dFdx(normal)), length(dFdy(normal)))));
+ vec2 z_step = step(-0.1, -abs(vec2(dFdx(frag_depth), dFdy(frag_depth))));
+
+ visibility -= dFdx(visibility) * d_sign.x * z_step.x * n_step.x;
+ visibility -= dFdy(visibility) * d_sign.y * z_step.y * n_step.y;
+
+ bent_normal -= dFdx(bent_normal) * d_sign.x * z_step.x * n_step.x;
+ bent_normal -= dFdy(bent_normal) * d_sign.y * z_step.y * n_step.y;
+}
+
+void gtao_deferred(vec3 normal, vec3 position, float frag_depth, out float visibility, out vec3 bent_normal)
+{
+ vec2 uvs = get_uvs_from_view(position);
+
+ vec4 texel_size = vec4(-1.0, -1.0, 1.0, 1.0) / vec2(textureSize(depthBuffer, 0)).xyxy;
+
+ ivec2 fs_co = ivec2(gl_FragCoord.xy);
+ ivec2 hr_co = get_hr_co(fs_co);
+
+ bent_normal = vec3(0.0);
+ visibility = 0.0;
+
+ for (float i = 0.0; i < MAX_PHI_STEP; i++) {
+ if (i >= aoSamples) break;
+
+ vec2 horiz = unpack_horizons(texelFetch(horizonBuffer, ivec3(hr_co, int(i)), 0).rg);
+ float phi = get_phi(hr_co, fs_co, i);
+
+ integrate_slice(normal, phi, horiz.xy, visibility, bent_normal);
+ }
+
+ visibility *= aoInvSamples;
+ bent_normal = normalize(bent_normal);
+}
+
+void gtao(vec3 normal, vec3 position, vec2 noise, out float visibility, out vec3 bent_normal)
+{
+ vec2 uvs = get_uvs_from_view(position);
+
+ float homcco = ProjectionMatrix[2][3] * position.z + ProjectionMatrix[3][3];
+ float max_dist = aoDistance / homcco; /* Search distance */
+ vec2 max_dir = max_dist * vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]);
+
+ bent_normal = vec3(0.0);
+ visibility = 0.0;
+
+ for (float i = 0.0; i < MAX_PHI_STEP; i++) {
+ if (i >= aoSamples) break;
+
+ float phi = M_PI * (i + noise.x) * aoInvSamples;
+ vec2 horizons = search_horizon_sweep(phi, position, uvs, noise.g, max_dir);
+
+ integrate_slice(normal, phi, horizons, visibility, bent_normal);
+ }
+
+ visibility *= aoInvSamples;
+ bent_normal = normalize(bent_normal);
+}
+
+/* Multibounce approximation base on surface albedo.
+ * Page 78 in the .pdf version. */
+float gtao_multibounce(float visibility, vec3 albedo)
+{
+ if (aoBounceFac == 0.0) return visibility;
+
+ /* Median luminance. Because Colored multibounce looks bad. */
+ float lum = dot(albedo, vec3(0.3333));
+
+ float a = 2.0404 * lum - 0.3324;
+ float b = -4.7951 * lum + 0.6417;
+ float c = 2.7552 * lum + 0.6903;
+
+ float x = visibility;
+ return max(x, ((x * a + b) * x + c) * x);
+}
+
+/* Use the right occlusion */
+float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec2 randuv, out vec3 bent_normal)
+{
+#ifndef USE_REFRACTION
+ if ((int(aoSettings) & USE_AO) > 0) {
+ float visibility;
+ vec3 vnor = mat3(ViewMatrix) * N;
+
+#ifdef ENABLE_DEFERED_AO
+ gtao_deferred(vnor, vpos, gl_FragCoord.z, visibility, bent_normal);
+#else
+ gtao(vnor, vpos, randuv, visibility, bent_normal);
+#endif
+ denoise_ao(vnor, gl_FragCoord.z, visibility, bent_normal);
+
+ /* Prevent some problems down the road. */
+ visibility = max(1e-3, visibility);
+
+ if ((int(aoSettings) & USE_BENT_NORMAL) != 0) {
+ /* The bent normal will show the facet look of the mesh. Try to minimize this. */
+ float mix_fac = visibility * visibility;
+ bent_normal = normalize(mix(bent_normal, vnor, mix_fac));
+
+ bent_normal = transform_direction(ViewMatrixInverse, bent_normal);
+ }
+ else {
+ bent_normal = N;
+ }
+
+ /* Scale by user factor */
+ visibility = pow(visibility, aoFactor);
+
+ return min(visibility, user_occlusion);
+ }
+#endif
+
+ bent_normal = N;
+ return user_occlusion;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/background_vert.glsl b/source/blender/draw/engines/eevee/shaders/background_vert.glsl
new file mode 100644
index 00000000000..b81aae9bcda
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/background_vert.glsl
@@ -0,0 +1,20 @@
+
+in vec2 pos;
+
+out vec3 varposition;
+out vec3 varnormal;
+out vec3 viewPosition;
+
+#ifndef VOLUMETRICS
+/* necessary for compilation*/
+out vec3 worldPosition;
+out vec3 worldNormal;
+out vec3 viewNormal;
+#endif
+
+void main()
+{
+ gl_Position = vec4(pos, 1.0, 1.0);
+ varposition = viewPosition = vec3(pos, -1.0);
+ varnormal = normalize(-varposition);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
new file mode 100644
index 00000000000..37ed2235c6f
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -0,0 +1,822 @@
+
+#define M_PI 3.14159265358979323846 /* pi */
+#define M_2PI 6.28318530717958647692 /* 2*pi */
+#define M_PI_2 1.57079632679489661923 /* pi/2 */
+#define M_1_PI 0.318309886183790671538 /* 1/pi */
+#define M_1_2PI 0.159154943091895335768 /* 1/(2*pi) */
+#define M_1_PI2 0.101321183642337771443 /* 1/(pi^2) */
+
+#define LUT_SIZE 64
+
+uniform mat4 ProjectionMatrix;
+uniform mat4 ViewProjectionMatrix;
+uniform mat4 ViewMatrixInverse;
+uniform vec4 viewvecs[2];
+#ifndef SHADOW_SHADER
+uniform mat4 ViewMatrix;
+#else
+layout(std140) uniform shadow_render_block {
+ mat4 ShadowMatrix[6];
+ mat4 FaceViewMatrix[6];
+ vec4 lampPosition;
+ float cubeTexelSize;
+ float storedTexelSize;
+ float nearClip;
+ float farClip;
+ int shadowSampleCount;
+ float shadowInvSampleCount;
+};
+
+flat in int shFace; /* Shadow layer we are rendering to. */
+#define ViewMatrix FaceViewMatrix[shFace]
+#endif
+
+uniform vec2 mipRatio[10];
+
+/* Buffers */
+uniform sampler2D colorBuffer;
+uniform sampler2D depthBuffer;
+uniform sampler2D maxzBuffer;
+uniform sampler2D minzBuffer;
+uniform sampler2DArray planarDepth;
+
+#define cameraForward normalize(ViewMatrixInverse[2].xyz)
+#define cameraPos ViewMatrixInverse[3].xyz
+#define cameraVec ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward)
+#define viewCameraVec ((ProjectionMatrix[3][3] == 0.0) ? normalize(-viewPosition) : vec3(0.0, 0.0, 1.0))
+
+/* ------- Structures -------- */
+
+/* ------ Lights ----- */
+struct LightData {
+ vec4 position_influence; /* w : InfluenceRadius */
+ vec4 color_spec; /* w : Spec Intensity */
+ vec4 spotdata_radius_shadow; /* x : spot size, y : spot blend, z : radius, w: shadow id */
+ vec4 rightvec_sizex; /* xyz: Normalized up vector, w: area size X or spot scale X */
+ vec4 upvec_sizey; /* xyz: Normalized right vector, w: area size Y or spot scale Y */
+ vec4 forwardvec_type; /* xyz: Normalized forward vector, w: Lamp Type */
+};
+
+/* convenience aliases */
+#define l_color color_spec.rgb
+#define l_spec color_spec.a
+#define l_position position_influence.xyz
+#define l_influence position_influence.w
+#define l_sizex rightvec_sizex.w
+#define l_sizey upvec_sizey.w
+#define l_right rightvec_sizex.xyz
+#define l_up upvec_sizey.xyz
+#define l_forward forwardvec_type.xyz
+#define l_type forwardvec_type.w
+#define l_spot_size spotdata_radius_shadow.x
+#define l_spot_blend spotdata_radius_shadow.y
+#define l_radius spotdata_radius_shadow.z
+#define l_shadowid spotdata_radius_shadow.w
+
+/* ------ Shadows ----- */
+#ifndef MAX_CASCADE_NUM
+#define MAX_CASCADE_NUM 4
+#endif
+
+struct ShadowData {
+ vec4 near_far_bias_exp;
+ vec4 shadow_data_start_end;
+ vec4 contact_shadow_data;
+};
+
+struct ShadowCubeData {
+ vec4 position;
+};
+
+struct ShadowCascadeData {
+ mat4 shadowmat[MAX_CASCADE_NUM];
+ vec4 split_start_distances;
+ vec4 split_end_distances;
+};
+
+/* convenience aliases */
+#define sh_near near_far_bias_exp.x
+#define sh_far near_far_bias_exp.y
+#define sh_bias near_far_bias_exp.z
+#define sh_exp near_far_bias_exp.w
+#define sh_bleed near_far_bias_exp.w
+#define sh_tex_start shadow_data_start_end.x
+#define sh_data_start shadow_data_start_end.y
+#define sh_multi_nbr shadow_data_start_end.z
+#define sh_blur shadow_data_start_end.w
+#define sh_contact_dist contact_shadow_data.x
+#define sh_contact_offset contact_shadow_data.y
+#define sh_contact_spread contact_shadow_data.z
+#define sh_contact_thickness contact_shadow_data.w
+
+/* ------- Convenience functions --------- */
+
+vec3 mul(mat3 m, vec3 v) { return m * v; }
+mat3 mul(mat3 m1, mat3 m2) { return m1 * m2; }
+vec3 transform_direction(mat4 m, vec3 v) { return mat3(m) * v; }
+vec3 transform_point(mat4 m, vec3 v) { return (m * vec4(v, 1.0)).xyz; }
+vec3 project_point(mat4 m, vec3 v) {
+ vec4 tmp = m * vec4(v, 1.0);
+ return tmp.xyz / tmp.w;
+}
+
+float min_v2(vec2 v) { return min(v.x, v.y); }
+float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); }
+float max_v2(vec2 v) { return max(v.x, v.y); }
+float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); }
+
+float saturate(float a) { return clamp(a, 0.0, 1.0); }
+vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); }
+vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); }
+vec4 saturate(vec4 a) { return clamp(a, 0.0, 1.0); }
+
+float distance_squared(vec2 a, vec2 b) { a -= b; return dot(a, a); }
+float distance_squared(vec3 a, vec3 b) { a -= b; return dot(a, a); }
+float len_squared(vec3 a) { return dot(a, a); }
+
+float inverse_distance(vec3 V) { return max( 1 / length(V), 1e-8); }
+
+vec2 mip_ratio_interp(float mip) {
+ float low_mip = floor(mip);
+ return mix(mipRatio[int(low_mip)], mipRatio[int(low_mip + 1.0)], mip - low_mip);
+}
+/* ------- Fast Math ------- */
+
+/* [Drobot2014a] Low Level Optimizations for GCN */
+float fast_sqrt(float v)
+{
+ return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1));
+}
+
+vec2 fast_sqrt(vec2 v)
+{
+ return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1));
+}
+
+/* [Eberly2014] GPGPU Programming for Games and Science */
+float fast_acos(float v)
+{
+ float res = -0.156583 * abs(v) + M_PI_2;
+ res *= fast_sqrt(1.0 - abs(v));
+ return (v >= 0) ? res : M_PI - res;
+}
+
+vec2 fast_acos(vec2 v)
+{
+ vec2 res = -0.156583 * abs(v) + M_PI_2;
+ res *= fast_sqrt(1.0 - abs(v));
+ v.x = (v.x >= 0) ? res.x : M_PI - res.x;
+ v.y = (v.y >= 0) ? res.y : M_PI - res.y;
+ return v;
+}
+
+float point_plane_projection_dist(vec3 lineorigin, vec3 planeorigin, vec3 planenormal)
+{
+ return dot(planenormal, planeorigin - lineorigin);
+}
+
+float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal)
+{
+ return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection);
+}
+
+float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec4 plane)
+{
+ vec3 plane_co = plane.xyz * (-plane.w / len_squared(plane.xyz));
+ vec3 h = lineorigin - plane_co;
+ return -dot(plane.xyz, h) / dot(plane.xyz, linedirection);
+}
+
+vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal)
+{
+ float dist = line_plane_intersect_dist(lineorigin, linedirection, planeorigin, planenormal);
+ return lineorigin + linedirection * dist;
+}
+
+vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec4 plane)
+{
+ float dist = line_plane_intersect_dist(lineorigin, linedirection, plane);
+ return lineorigin + linedirection * dist;
+}
+
+float line_aligned_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin)
+{
+ /* aligned plane normal */
+ vec3 L = planeorigin - lineorigin;
+ float diskdist = length(L);
+ vec3 planenormal = -normalize(L);
+ return -diskdist / dot(planenormal, linedirection);
+}
+
+vec3 line_aligned_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin)
+{
+ float dist = line_aligned_plane_intersect_dist(lineorigin, linedirection, planeorigin);
+ if (dist < 0) {
+ /* if intersection is behind we fake the intersection to be
+ * really far and (hopefully) not inside the radius of interest */
+ dist = 1e16;
+ }
+ return lineorigin + linedirection * dist;
+}
+
+float line_unit_sphere_intersect_dist(vec3 lineorigin, vec3 linedirection)
+{
+ float a = dot(linedirection, linedirection);
+ float b = dot(linedirection, lineorigin);
+ float c = dot(lineorigin, lineorigin) - 1;
+
+ float dist = 1e15;
+ float determinant = b * b - a * c;
+ if (determinant >= 0)
+ dist = (sqrt(determinant) - b) / a;
+
+ return dist;
+}
+
+float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection)
+{
+ /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ */
+ vec3 firstplane = (vec3( 1.0) - lineorigin) / linedirection;
+ vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection;
+ vec3 furthestplane = max(firstplane, secondplane);
+
+ return min_v3(furthestplane);
+}
+
+
+/* Return texture coordinates to sample Surface LUT */
+vec2 lut_coords(float cosTheta, float roughness)
+{
+ float theta = acos(cosTheta);
+ vec2 coords = vec2(roughness, theta / M_PI_2);
+
+ /* scale and bias coordinates, for correct filtered lookup */
+ return coords * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE;
+}
+
+/* -- Tangent Space conversion -- */
+vec3 tangent_to_world(vec3 vector, vec3 N, vec3 T, vec3 B)
+{
+ return T * vector.x + B * vector.y + N * vector.z;
+}
+
+vec3 world_to_tangent(vec3 vector, vec3 N, vec3 T, vec3 B)
+{
+ return vec3( dot(T, vector), dot(B, vector), dot(N, vector));
+}
+
+void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B)
+{
+ vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0,0.0,1.0) : vec3(1.0,0.0,0.0);
+ T = normalize( cross(UpVector, N) );
+ B = cross(N, T);
+}
+
+/* ---- Opengl Depth conversion ---- */
+float linear_depth(bool is_persp, float z, float zf, float zn)
+{
+ if (is_persp) {
+ return (zn * zf) / (z * (zn - zf) + zf);
+ }
+ else {
+ return (z * 2.0 - 1.0) * zf;
+ }
+}
+
+float buffer_depth(bool is_persp, float z, float zf, float zn)
+{
+ if (is_persp) {
+ return (zf * (zn - z)) / (z * (zn - zf));
+ }
+ else {
+ return (z / (zf * 2.0)) + 0.5;
+ }
+}
+
+float get_view_z_from_depth(float depth)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ float d = 2.0 * depth - 1.0;
+ return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
+ }
+ else {
+ return viewvecs[0].z + depth * viewvecs[1].z;
+ }
+}
+
+float get_depth_from_view_z(float z)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ float d = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2];
+ return d * 0.5 + 0.5;
+ }
+ else {
+ return (z - viewvecs[0].z) / viewvecs[1].z;
+ }
+}
+
+vec2 get_uvs_from_view(vec3 view)
+{
+ vec3 ndc = project_point(ProjectionMatrix, view);
+ return ndc.xy * 0.5 + 0.5;
+}
+
+vec3 get_view_space_from_depth(vec2 uvcoords, float depth)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ return (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz) * get_view_z_from_depth(depth);
+ }
+ else {
+ return viewvecs[0].xyz + vec3(uvcoords, depth) * viewvecs[1].xyz;
+ }
+}
+
+vec3 get_world_space_from_depth(vec2 uvcoords, float depth)
+{
+ return (ViewMatrixInverse * vec4(get_view_space_from_depth(uvcoords, depth), 1.0)).xyz;
+}
+
+vec3 get_specular_reflection_dominant_dir(vec3 N, vec3 V, float roughness)
+{
+ vec3 R = -reflect(V, N);
+ float smoothness = 1.0 - roughness;
+ float fac = smoothness * (sqrt(smoothness) + roughness);
+ return normalize(mix(N, R, fac));
+}
+
+float specular_occlusion(float NV, float AO, float roughness)
+{
+ return saturate(pow(NV + AO, roughness) - 1.0 + AO);
+}
+
+/* --- Refraction utils --- */
+
+float ior_from_f0(float f0)
+{
+ float f = sqrt(f0);
+ return (-f - 1.0) / (f - 1.0);
+}
+
+float f0_from_ior(float eta)
+{
+ float A = (eta - 1.0) / (eta + 1.0);
+ return A * A;
+}
+
+vec3 get_specular_refraction_dominant_dir(vec3 N, vec3 V, float roughness, float ior)
+{
+ /* TODO: This a bad approximation. Better approximation should fit
+ * the refracted vector and roughness into the best prefiltered reflection
+ * lobe. */
+ /* Correct the IOR for ior < 1.0 to not see the abrupt delimitation or the TIR */
+ ior = (ior < 1.0) ? mix(ior, 1.0, roughness) : ior;
+ float eta = 1.0 / ior;
+
+ float NV = dot(N, -V);
+
+ /* Custom Refraction. */
+ float k = 1.0 - eta * eta * (1.0 - NV * NV);
+ k = max(0.0, k); /* Only this changes. */
+ vec3 R = eta * -V - (eta * NV + sqrt(k)) * N;
+
+ return R;
+}
+
+float get_btdf_lut(sampler2DArray btdf_lut_tex, float NV, float roughness, float ior)
+{
+ const vec3 lut_scale_bias_texel_size = vec3((LUT_SIZE - 1.0), 0.5, 1.5) / LUT_SIZE;
+
+ vec3 coords;
+ /* Try to compensate for the low resolution and interpolation error. */
+ coords.x = (ior > 1.0)
+ ? (0.9 + lut_scale_bias_texel_size.z) + (0.1 - lut_scale_bias_texel_size.z) * f0_from_ior(ior)
+ : (0.9 + lut_scale_bias_texel_size.z) * ior * ior;
+ coords.y = 1.0 - saturate(NV);
+ coords.xy *= lut_scale_bias_texel_size.x;
+ coords.xy += lut_scale_bias_texel_size.y;
+
+ const float lut_lvl_ofs = 4.0; /* First texture lvl of roughness. */
+ const float lut_lvl_scale = 16.0; /* How many lvl of roughness in the lut. */
+
+ float mip = roughness * lut_lvl_scale;
+ float mip_floor = floor(mip);
+
+ coords.z = lut_lvl_ofs + mip_floor + 1.0;
+ float btdf_high = textureLod(btdf_lut_tex, coords, 0.0).r;
+
+ coords.z -= 1.0;
+ float btdf_low = textureLod(btdf_lut_tex, coords, 0.0).r;
+
+ float btdf = (ior == 1.0) ? 1.0 : mix(btdf_low, btdf_high, mip - coords.z);
+
+ return btdf;
+}
+
+/* ---- Encode / Decode Normal buffer data ---- */
+/* From http://aras-p.info/texts/CompactNormalStorage.html
+ * Using Method #4: Spheremap Transform */
+vec2 normal_encode(vec3 n, vec3 view)
+{
+ float p = sqrt(n.z * 8.0 + 8.0);
+ return n.xy / p + 0.5;
+}
+
+vec3 normal_decode(vec2 enc, vec3 view)
+{
+ vec2 fenc = enc * 4.0 - 2.0;
+ float f = dot(fenc, fenc);
+ float g = sqrt(1.0 - f / 4.0);
+ vec3 n;
+ n.xy = fenc*g;
+ n.z = 1 - f / 2;
+ return n;
+}
+
+/* ---- RGBM (shared multiplier) encoding ---- */
+/* From http://iwasbeingirony.blogspot.fr/2010/06/difference-between-rgbm-and-rgbd.html */
+
+/* Higher RGBM_MAX_RANGE gives imprecision issues in low intensity. */
+#define RGBM_MAX_RANGE 512.0
+
+vec4 rgbm_encode(vec3 rgb)
+{
+ float maxRGB = max_v3(rgb);
+ float M = maxRGB / RGBM_MAX_RANGE;
+ M = ceil(M * 255.0) / 255.0;
+ return vec4(rgb / (M * RGBM_MAX_RANGE), M);
+}
+
+vec3 rgbm_decode(vec4 data)
+{
+ return data.rgb * (data.a * RGBM_MAX_RANGE);
+}
+
+/* ---- RGBE (shared exponent) encoding ---- */
+vec4 rgbe_encode(vec3 rgb)
+{
+ float maxRGB = max_v3(rgb);
+ float fexp = ceil(log2(maxRGB));
+ return vec4(rgb / exp2(fexp), (fexp + 128.0) / 255.0);
+}
+
+vec3 rgbe_decode(vec4 data)
+{
+ float fexp = data.a * 255.0 - 128.0;
+ return data.rgb * exp2(fexp);
+}
+
+#if 1
+#define irradiance_encode rgbe_encode
+#define irradiance_decode rgbe_decode
+#else /* No ecoding (when using floating point format) */
+#define irradiance_encode(X) (X).rgbb
+#define irradiance_decode(X) (X).rgb
+#endif
+
+/* Irradiance Visibility Encoding */
+#if 1
+vec4 visibility_encode(vec2 accum, float range)
+{
+ accum /= range;
+
+ vec4 data;
+ data.x = fract(accum.x);
+ data.y = floor(accum.x) / 255.0;
+ data.z = fract(accum.y);
+ data.w = floor(accum.y) / 255.0;
+
+ return data;
+}
+
+vec2 visibility_decode(vec4 data, float range)
+{
+ return (data.xz + data.yw * 255.0) * range;
+}
+#else /* No ecoding (when using floating point format) */
+vec4 visibility_encode(vec2 accum, float range)
+{
+ return accum.xyxy;
+}
+
+vec2 visibility_decode(vec4 data, float range)
+{
+ return data.xy;
+}
+#endif
+
+/* Fresnel monochromatic, perfect mirror */
+float F_eta(float eta, float cos_theta)
+{
+ /* compute fresnel reflectance without explicitly computing
+ * the refracted direction */
+ float c = abs(cos_theta);
+ float g = eta * eta - 1.0 + c * c;
+ float result;
+
+ if (g > 0.0) {
+ g = sqrt(g);
+ vec2 g_c = vec2(g) + vec2(c, -c);
+ float A = g_c.y / g_c.x;
+ A *= A;
+ g_c *= c;
+ float B = (g_c.y - 1.0) / (g_c.x + 1.0);
+ B *= B;
+ result = 0.5 * A * (1.0 + B);
+ }
+ else {
+ result = 1.0; /* TIR (no refracted component) */
+ }
+
+ return result;
+}
+
+/* Fresnel */
+vec3 F_schlick(vec3 f0, float cos_theta)
+{
+ float fac = 1.0 - cos_theta;
+ float fac2 = fac * fac;
+ fac = fac2 * fac2 * fac;
+
+ /* Unreal specular matching : if specular color is below 2% intensity,
+ * (using green channel for intensity) treat as shadowning */
+ return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * fac + (1.0 - fac) * f0;
+}
+
+/* Fresnel approximation for LTC area lights (not MRP) */
+vec3 F_area(vec3 f0, vec2 lut)
+{
+ vec2 fac = normalize(lut.xy);
+
+ /* Unreal specular matching : if specular color is below 2% intensity,
+ * treat as shadowning */
+ return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * fac.y + fac.x * f0;
+}
+
+/* Fresnel approximation for IBL */
+vec3 F_ibl(vec3 f0, vec2 lut)
+{
+ /* Unreal specular matching : if specular color is below 2% intensity,
+ * treat as shadowning */
+ return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * lut.y + lut.x * f0;
+}
+
+/* GGX */
+float D_ggx_opti(float NH, float a2)
+{
+ float tmp = (NH * a2 - NH) * NH + 1.0;
+ return M_PI * tmp*tmp; /* Doing RCP and mul a2 at the end */
+}
+
+float G1_Smith_GGX(float NX, float a2)
+{
+ /* Using Brian Karis approach and refactoring by NX/NX
+ * this way the (2*NL)*(2*NV) in G = G1(V) * G1(L) gets canceled by the brdf denominator 4*NL*NV
+ * Rcp is done on the whole G later
+ * Note that this is not convenient for the transmition formula */
+ return NX + sqrt(NX * (NX - NX * a2) + a2);
+ /* return 2 / (1 + sqrt(1 + a2 * (1 - NX*NX) / (NX*NX) ) ); /* Reference function */
+}
+
+float bsdf_ggx(vec3 N, vec3 L, vec3 V, float roughness)
+{
+ float a = roughness;
+ float a2 = a * a;
+
+ vec3 H = normalize(L + V);
+ float NH = max(dot(N, H), 1e-8);
+ float NL = max(dot(N, L), 1e-8);
+ float NV = max(dot(N, V), 1e-8);
+
+ float G = G1_Smith_GGX(NV, a2) * G1_Smith_GGX(NL, a2); /* Doing RCP at the end */
+ float D = D_ggx_opti(NH, a2);
+
+ /* Denominator is canceled by G1_Smith */
+ /* bsdf = D * G / (4.0 * NL * NV); /* Reference function */
+ return NL * a2 / (D * G); /* NL to Fit cycles Equation : line. 345 in bsdf_microfacet.h */
+}
+
+void accumulate_light(vec3 light, float fac, inout vec4 accum)
+{
+ accum += vec4(light, 1.0) * min(fac, (1.0 - accum.a));
+}
+
+/* ----------- Cone Apperture Approximation --------- */
+
+/* Return a fitted cone angle given the input roughness */
+float cone_cosine(float r)
+{
+ /* Using phong gloss
+ * roughness = sqrt(2/(gloss+2)) */
+ float gloss = -2 + 2 / (r * r);
+ /* Drobot 2014 in GPUPro5 */
+ // return cos(2.0 * sqrt(2.0 / (gloss + 2)));
+ /* Uludag 2014 in GPUPro5 */
+ // return pow(0.244, 1 / (gloss + 1));
+ /* Jimenez 2016 in Practical Realtime Strategies for Accurate Indirect Occlusion*/
+ return exp2(-3.32193 * r * r);
+}
+
+/* --------- Closure ---------- */
+#ifdef VOLUMETRICS
+
+struct Closure {
+ vec3 absorption;
+ vec3 scatter;
+ vec3 emission;
+ float anisotropy;
+};
+
+#define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), vec3(0.0), 0.0)
+
+Closure closure_mix(Closure cl1, Closure cl2, float fac)
+{
+ Closure cl;
+ cl.absorption = mix(cl1.absorption, cl2.absorption, fac);
+ cl.scatter = mix(cl1.scatter, cl2.scatter, fac);
+ cl.emission = mix(cl1.emission, cl2.emission, fac);
+ cl.anisotropy = mix(cl1.anisotropy, cl2.anisotropy, fac);
+ return cl;
+}
+
+Closure closure_add(Closure cl1, Closure cl2)
+{
+ Closure cl;
+ cl.absorption = cl1.absorption + cl2.absorption;
+ cl.scatter = cl1.scatter + cl2.scatter;
+ cl.emission = cl1.emission + cl2.emission;
+ cl.anisotropy = (cl1.anisotropy + cl2.anisotropy) / 2.0; /* Average phase (no multi lobe) */
+ return cl;
+}
+
+#else /* VOLUMETRICS */
+
+struct Closure {
+ vec3 radiance;
+ float opacity;
+#ifdef USE_SSS
+ vec4 sss_data;
+#ifdef USE_SSS_ALBEDO
+ vec3 sss_albedo;
+#endif
+#endif
+ vec4 ssr_data;
+ vec2 ssr_normal;
+ int ssr_id;
+};
+
+/* This is hacking ssr_id to tag transparent bsdf */
+#define TRANSPARENT_CLOSURE_FLAG -2
+#define REFRACT_CLOSURE_FLAG -3
+
+#ifdef USE_SSS
+#ifdef USE_SSS_ALBEDO
+#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec3(0.0), vec4(0.0), vec2(0.0), -1)
+#else
+#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec4(0.0), vec2(0.0), -1)
+#endif
+#else
+#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec2(0.0), -1)
+#endif
+
+uniform int outputSsrId;
+
+Closure closure_mix(Closure cl1, Closure cl2, float fac)
+{
+ Closure cl;
+
+ if (cl1.ssr_id == outputSsrId) {
+ cl.ssr_data = mix(cl1.ssr_data.xyzw, vec4(vec3(0.0), cl1.ssr_data.w), fac); /* do not blend roughness */
+ cl.ssr_normal = cl1.ssr_normal;
+ cl.ssr_id = cl1.ssr_id;
+ }
+ else {
+ cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */
+ cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */
+ cl.ssr_normal = cl2.ssr_normal;
+ cl.ssr_id = cl2.ssr_id;
+ }
+ if (cl1.ssr_id == TRANSPARENT_CLOSURE_FLAG) {
+ cl1.radiance = cl2.radiance;
+#ifdef USE_SSS
+ cl1.sss_data = cl2.sss_data;
+#ifdef USE_SSS_ALBEDO
+ cl1.sss_albedo = cl2.sss_albedo;
+#endif
+#endif
+ }
+ if (cl2.ssr_id == TRANSPARENT_CLOSURE_FLAG) {
+ cl2.radiance = cl1.radiance;
+#ifdef USE_SSS
+ cl2.sss_data = cl1.sss_data;
+#ifdef USE_SSS_ALBEDO
+ cl2.sss_albedo = cl1.sss_albedo;
+#endif
+#endif
+ }
+ cl.radiance = mix(cl1.radiance, cl2.radiance, fac);
+ cl.opacity = mix(cl1.opacity, cl2.opacity, fac);
+
+#ifdef USE_SSS
+ cl.sss_data.rgb = mix(cl1.sss_data.rgb, cl2.sss_data.rgb, fac);
+ cl.sss_data.a = (cl1.sss_data.a > 0.0) ? cl1.sss_data.a : cl2.sss_data.a;
+#ifdef USE_SSS_ALBEDO
+ /* TODO Find a solution to this. Dither? */
+ cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo;
+#endif
+#endif
+
+ return cl;
+}
+
+Closure closure_add(Closure cl1, Closure cl2)
+{
+ Closure cl = (cl1.ssr_id == outputSsrId) ? cl1 : cl2;
+#ifdef USE_SSS
+ cl.sss_data = (cl1.sss_data.a > 0.0) ? cl1.sss_data : cl2.sss_data;
+#ifdef USE_SSS_ALBEDO
+ /* TODO Find a solution to this. Dither? */
+ cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo;
+#endif
+#endif
+ cl.radiance = cl1.radiance + cl2.radiance;
+ cl.opacity = cl1.opacity + cl2.opacity;
+ return cl;
+}
+
+uniform bool sssToggle;
+
+#if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY)
+layout(location = 0) out vec4 fragColor;
+#ifdef USE_SSS
+#ifdef USE_SSS_ALBEDO
+layout(location = 1) out vec4 sssData;
+layout(location = 2) out vec4 sssAlbedo;
+layout(location = 3) out vec4 ssrNormals;
+layout(location = 4) out vec4 ssrData;
+#else
+layout(location = 1) out vec4 sssData;
+layout(location = 2) out vec4 ssrNormals;
+layout(location = 3) out vec4 ssrData;
+#endif /* USE_SSS_ALBEDO */
+#else
+layout(location = 1) out vec4 ssrNormals;
+layout(location = 2) out vec4 ssrData;
+#endif /* USE_SSS */
+
+Closure nodetree_exec(void); /* Prototype */
+
+#if defined(USE_ALPHA_BLEND_VOLUMETRICS)
+/* Prototype because this file is included before volumetric_lib.glsl */
+vec4 volumetric_resolve(vec4 scene_color, vec2 frag_uvs, float frag_depth);
+#endif
+
+#define NODETREE_EXEC
+void main()
+{
+ Closure cl = nodetree_exec();
+
+#if defined(USE_ALPHA_BLEND_VOLUMETRICS)
+ /* XXX fragile, better use real viewport resolution */
+ vec2 uvs = gl_FragCoord.xy / vec2(2 * textureSize(maxzBuffer, 0).xy);
+ fragColor = volumetric_resolve(vec4(cl.radiance, cl.opacity), uvs, gl_FragCoord.z);
+#else
+ fragColor = vec4(cl.radiance, cl.opacity);
+#endif
+
+ ssrNormals = cl.ssr_normal.xyyy;
+ ssrData = cl.ssr_data;
+#ifdef USE_SSS
+ sssData = cl.sss_data;
+#ifdef USE_SSS_ALBEDO
+ sssAlbedo = cl.sss_albedo.rgbb;
+#endif
+#endif
+
+ /* For Probe capture */
+#ifdef USE_SSS
+#ifdef USE_SSS_ALBEDO
+ fragColor.rgb += cl.sss_data.rgb * cl.sss_albedo.rgb * float(!sssToggle);
+#else
+ fragColor.rgb += cl.sss_data.rgb * float(!sssToggle);
+#endif
+#endif
+}
+
+#endif /* MESH_SHADER && !SHADOW_SHADER */
+
+#endif /* VOLUMETRICS */
+
+Closure nodetree_exec(void); /* Prototype */
+
+/* TODO find a better place */
+#ifdef USE_MULTIPLY
+
+out vec4 fragColor;
+
+#define NODETREE_EXEC
+void main()
+{
+ Closure cl = nodetree_exec();
+ fragColor = vec4(mix(vec3(1.0), cl.radiance, cl.opacity), 1.0);
+}
+#endif \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl
new file mode 100644
index 00000000000..ae03f22ac14
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl
@@ -0,0 +1,183 @@
+/* Bsdf direct light function */
+/* in other word, how materials react to scene lamps */
+
+/* Naming convention
+ * V View vector (normalized)
+ * N World Normal (normalized)
+ * L Outgoing Light Vector (Surface to Light in World Space) (normalized)
+ * Ldist Distance from surface to the light
+ * W World Pos
+ */
+
+/* ------------ Diffuse ------------- */
+
+float direct_diffuse_point(vec3 N, vec4 l_vector)
+{
+ float dist = l_vector.w;
+ vec3 L = l_vector.xyz / dist;
+ float bsdf = max(0.0, dot(N, L));
+ bsdf /= dist * dist;
+ return bsdf;
+}
+
+/* infinitly far away point source, no decay */
+float direct_diffuse_sun(LightData ld, vec3 N)
+{
+ float bsdf = max(0.0, dot(N, -ld.l_forward));
+ bsdf *= M_1_PI; /* Normalize */
+ return bsdf;
+}
+
+/* From Frostbite PBR Course
+ * Analytical irradiance from a sphere with correct horizon handling
+ * http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */
+float direct_diffuse_sphere(LightData ld, vec3 N, vec4 l_vector)
+{
+ float dist = l_vector.w;
+ vec3 L = l_vector.xyz / dist;
+ float radius = max(ld.l_sizex, 0.0001);
+ float costheta = clamp(dot(N, L), -0.999, 0.999);
+ float h = min(ld.l_radius / dist , 0.9999);
+ float h2 = h*h;
+ float costheta2 = costheta * costheta;
+ float bsdf;
+
+ if (costheta2 > h2) {
+ bsdf = M_PI * h2 * clamp(costheta, 0.0, 1.0);
+ }
+ else {
+ float sintheta = sqrt(1.0 - costheta2);
+ float x = sqrt(1.0 / h2 - 1.0);
+ float y = -x * (costheta / sintheta);
+ float sinthetasqrty = sintheta * sqrt(1.0 - y * y);
+ bsdf = (costheta * acos(y) - x * sinthetasqrty) * h2 + atan(sinthetasqrty / x);
+ }
+
+ bsdf = max(bsdf, 0.0);
+ bsdf *= M_1_PI2;
+
+ return bsdf;
+}
+
+#ifdef USE_LTC
+float direct_diffuse_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector)
+{
+ vec3 corners[4];
+ corners[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey;
+ corners[1] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey;
+ corners[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey;
+ corners[3] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey;
+
+ float bsdf = ltc_evaluate(N, V, mat3(1.0), corners);
+ bsdf *= M_1_2PI;
+ return bsdf;
+}
+#endif
+
+#if 0
+float direct_diffuse_unit_disc(vec3 N, vec3 L)
+{
+
+}
+#endif
+
+/* ----------- GGx ------------ */
+vec3 direct_ggx_point(vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0)
+{
+ roughness = max(1e-3, roughness);
+ float dist = l_vector.w;
+ vec3 L = l_vector.xyz / dist;
+ float bsdf = bsdf_ggx(N, L, V, roughness);
+ bsdf /= dist * dist;
+
+ /* Fresnel */
+ float VH = max(dot(V, normalize(V + L)), 0.0);
+ return F_schlick(f0, VH) * bsdf;
+}
+
+vec3 direct_ggx_sun(LightData ld, vec3 N, vec3 V, float roughness, vec3 f0)
+{
+ roughness = max(1e-3, roughness);
+ float bsdf = bsdf_ggx(N, -ld.l_forward, V, roughness);
+ float VH = dot(V, -ld.l_forward) * 0.5 + 0.5;
+ return F_schlick(f0, VH) * bsdf;
+}
+
+#ifdef USE_LTC
+vec3 direct_ggx_sphere(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0)
+{
+ vec3 L = l_vector.xyz / l_vector.w;
+ vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughness);
+ vec3 P = line_aligned_plane_intersect(vec3(0.0), spec_dir, l_vector.xyz);
+
+ vec3 Px = normalize(P - l_vector.xyz) * ld.l_radius;
+ vec3 Py = cross(Px, L);
+
+ vec2 uv = lut_coords(dot(N, V), sqrt(roughness));
+ vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb;
+ vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba;
+ mat3 ltc_mat = ltc_matrix(ltc_lut);
+
+// #define HIGHEST_QUALITY
+#ifdef HIGHEST_QUALITY
+ vec3 Pxy1 = normalize( Px + Py) * ld.l_radius;
+ vec3 Pxy2 = normalize(-Px + Py) * ld.l_radius;
+
+ /* counter clockwise */
+ vec3 points[8];
+ points[0] = l_vector.xyz + Px;
+ points[1] = l_vector.xyz - Pxy2;
+ points[2] = l_vector.xyz - Py;
+ points[3] = l_vector.xyz - Pxy1;
+ points[4] = l_vector.xyz - Px;
+ points[5] = l_vector.xyz + Pxy2;
+ points[6] = l_vector.xyz + Py;
+ points[7] = l_vector.xyz + Pxy1;
+ float bsdf = ltc_evaluate_circle(N, V, ltc_mat, points);
+#else
+ vec3 points[4];
+ points[0] = l_vector.xyz + Px;
+ points[1] = l_vector.xyz - Py;
+ points[2] = l_vector.xyz - Px;
+ points[3] = l_vector.xyz + Py;
+ float bsdf = ltc_evaluate(N, V, ltc_mat, points);
+ /* sqrt(pi/2) difference between square and disk area */
+ bsdf *= 1.25331413731;
+#endif
+
+ bsdf *= brdf_lut.b; /* Bsdf intensity */
+ bsdf *= M_1_2PI * M_1_PI;
+
+ vec3 spec = F_area(f0, brdf_lut.xy) * bsdf;
+
+ return spec;
+}
+
+vec3 direct_ggx_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0)
+{
+ vec3 corners[4];
+ corners[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey;
+ corners[1] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey;
+ corners[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey;
+ corners[3] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey;
+
+ vec2 uv = lut_coords(dot(N, V), sqrt(roughness));
+ vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb;
+ vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba;
+ mat3 ltc_mat = ltc_matrix(ltc_lut);
+ float bsdf = ltc_evaluate(N, V, ltc_mat, corners);
+ bsdf *= brdf_lut.b; /* Bsdf intensity */
+ bsdf *= M_1_2PI;
+
+ vec3 spec = F_area(f0, brdf_lut.xy) * bsdf;
+
+ return spec;
+}
+#endif
+
+#if 0
+float direct_ggx_disc(vec3 N, vec3 L)
+{
+
+}
+#endif \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_lut_frag.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_lut_frag.glsl
new file mode 100644
index 00000000000..b8fac61519e
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_lut_frag.glsl
@@ -0,0 +1,46 @@
+
+out vec4 FragColor;
+
+void main() {
+ vec3 N, T, B, V;
+
+ float NV = ( 1.0 - (clamp(gl_FragCoord.y / BRDF_LUT_SIZE, 1e-4, 0.9999)));
+ float sqrtRoughness = clamp(gl_FragCoord.x / BRDF_LUT_SIZE, 1e-4, 0.9999);
+ float a = sqrtRoughness * sqrtRoughness;
+ float a2 = a * a;
+
+ N = vec3(0.0, 0.0, 1.0);
+ T = vec3(1.0, 0.0, 0.0);
+ B = vec3(0.0, 1.0, 0.0);
+ V = vec3(sqrt(1.0 - NV * NV), 0.0, NV);
+
+ setup_noise();
+
+ /* Integrating BRDF */
+ float brdf_accum = 0.0;
+ float fresnel_accum = 0.0;
+ for (float i = 0; i < sampleCount; i++) {
+ vec3 H = sample_ggx(i, a2, N, T, B); /* Microfacet normal */
+ vec3 L = -reflect(V, H);
+ float NL = L.z;
+
+ if (NL > 0.0) {
+ float NH = max(H.z, 0.0);
+ float VH = max(dot(V, H), 0.0);
+
+ float G1_v = G1_Smith_GGX(NV, a2);
+ float G1_l = G1_Smith_GGX(NL, a2);
+ float G_smith = 4.0 * NV * NL / (G1_v * G1_l); /* See G1_Smith_GGX for explanations. */
+
+ float brdf = (G_smith * VH) / (NH * NV);
+ float Fc = pow(1.0 - VH, 5.0);
+
+ brdf_accum += (1.0 - Fc) * brdf;
+ fresnel_accum += Fc * brdf;
+ }
+ }
+ brdf_accum /= sampleCount;
+ fresnel_accum /= sampleCount;
+
+ FragColor = vec4(brdf_accum, fresnel_accum, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
new file mode 100644
index 00000000000..13586619fe9
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
@@ -0,0 +1,107 @@
+
+uniform sampler1D texHammersley;
+uniform sampler2D texJitter;
+uniform float sampleCount;
+uniform float invSampleCount;
+
+vec2 jitternoise = vec2(0.0);
+
+#ifndef UTIL_TEX
+#define UTIL_TEX
+uniform sampler2DArray utilTex;
+#endif /* UTIL_TEX */
+
+void setup_noise(void)
+{
+ jitternoise = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).rg; /* Global variable */
+ jitternoise.g = (jitternoise.g - 0.5) * 2.0;
+}
+
+#ifdef HAMMERSLEY_SIZE
+vec3 hammersley_3d(float i, float invsamplenbr)
+{
+ vec3 Xi; /* Theta, cos(Phi), sin(Phi) */
+
+ Xi.x = i * invsamplenbr; /* i/samples */
+ Xi.x = fract(Xi.x + jitternoise.x);
+
+ int u = int(mod(i + jitternoise.y * HAMMERSLEY_SIZE, HAMMERSLEY_SIZE));
+
+ Xi.yz = texelFetch(texHammersley, u, 0).rg;
+
+ return Xi;
+}
+
+vec3 hammersley_3d(float i)
+{
+ return hammersley_3d(i, invSampleCount);
+}
+#endif
+
+/* -------------- BSDFS -------------- */
+
+float pdf_ggx_reflect(float NH, float a2)
+{
+ return NH * a2 / D_ggx_opti(NH, a2);
+}
+
+float pdf_hemisphere()
+{
+ return 0.5 * M_1_PI;
+}
+
+vec3 sample_ggx(vec3 rand, float a2)
+{
+ /* Theta is the aperture angle of the cone */
+ float z = sqrt( (1.0 - rand.x) / ( 1.0 + a2 * rand.x - rand.x ) ); /* cos theta */
+ float r = sqrt(max(0.0, 1.0f - z*z)); /* sin theta */
+ float x = r * rand.y;
+ float y = r * rand.z;
+
+ /* Microfacet Normal */
+ return vec3(x, y, z);
+}
+
+vec3 sample_ggx(vec3 rand, float a2, vec3 N, vec3 T, vec3 B, out float NH)
+{
+ vec3 Ht = sample_ggx(rand, a2);
+ NH = Ht.z;
+ return tangent_to_world(Ht, N, T, B);
+}
+
+#ifdef HAMMERSLEY_SIZE
+vec3 sample_ggx(float nsample, float a2, vec3 N, vec3 T, vec3 B)
+{
+ vec3 Xi = hammersley_3d(nsample);
+ vec3 Ht = sample_ggx(Xi, a2);
+ return tangent_to_world(Ht, N, T, B);
+}
+
+vec3 sample_hemisphere(float nsample, vec3 N, vec3 T, vec3 B)
+{
+ vec3 Xi = hammersley_3d(nsample);
+
+ float z = Xi.x; /* cos theta */
+ float r = sqrt(max(0.0, 1.0f - z*z)); /* sin theta */
+ float x = r * Xi.y;
+ float y = r * Xi.z;
+
+ vec3 Ht = vec3(x, y, z);
+
+ return tangent_to_world(Ht, N, T, B);
+}
+
+vec3 sample_cone(float nsample, float angle, vec3 N, vec3 T, vec3 B)
+{
+ vec3 Xi = hammersley_3d(nsample);
+
+ float z = cos(angle * Xi.x); /* cos theta */
+ float r = sqrt(max(0.0, 1.0f - z*z)); /* sin theta */
+ float x = r * Xi.y;
+ float y = r * Xi.z;
+
+ vec3 Ht = vec3(x, y, z);
+
+ return tangent_to_world(Ht, N, T, B);
+}
+#endif \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl b/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl
new file mode 100644
index 00000000000..2c604d69641
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl
@@ -0,0 +1,59 @@
+
+uniform float a2;
+
+out vec4 FragColor;
+
+void main() {
+ vec3 N, T, B, V;
+
+ float x = gl_FragCoord.x / BRDF_LUT_SIZE;
+ float y = gl_FragCoord.y / BRDF_LUT_SIZE;
+ /* There is little variation if ior > 1.0 so we
+ * maximize LUT precision for ior < 1.0 */
+ x = x * 1.1;
+ float ior = (x > 1.0) ? ior_from_f0((x-1.0) * 10.0) : sqrt(x);
+ float NV = (1.0 - (clamp(y, 1e-4, 0.9999)));
+
+ N = vec3(0.0, 0.0, 1.0);
+ T = vec3(1.0, 0.0, 0.0);
+ B = vec3(0.0, 1.0, 0.0);
+ V = vec3(sqrt(1.0 - NV * NV), 0.0, NV);
+
+ setup_noise();
+
+ /* Integrating BTDF */
+ float btdf_accum = 0.0;
+ for (float i = 0.0; i < sampleCount; i++) {
+ vec3 H = sample_ggx(i, a2, N, T, B); /* Microfacet normal */
+
+ float VH = dot(V, H);
+
+ /* Check if there is total internal reflections. */
+ float c = abs(VH);
+ float g = ior * ior - 1.0 + c * c;
+
+ float eta = 1.0/ior;
+ if (dot(H, V) < 0.0) {
+ H = -H;
+ eta = ior;
+ }
+
+ vec3 L = refract(-V, H, eta);
+ float NL = -dot(N, L);
+
+ if ((NL > 0.0) && (g > 0.0)) {
+ float LH = dot(L, H);
+
+ float G1_l = NL * 2.0 / G1_Smith_GGX(NL, a2); /* Balancing the adjustments made in G1_Smith */
+
+ /* btdf = abs(VH*LH) * (ior*ior) * D * G(V) * G(L) / (Ht2 * NV)
+ * pdf = (VH * abs(LH)) * (ior*ior) * D * G(V) / (Ht2 * NV) */
+ float btdf = G1_l * abs(VH*LH) / (VH * abs(LH));
+
+ btdf_accum += btdf;
+ }
+ }
+ btdf_accum /= sampleCount;
+
+ FragColor = vec4(btdf_accum, 0.0, 0.0, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl b/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl
new file mode 100644
index 00000000000..67bcf603a81
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl
@@ -0,0 +1,267 @@
+/* Precomputed table of concentric samples.
+ * Generated using this algorithm http://l2program.co.uk/900/concentric-disk-sampling
+ * Sorted by radius then by rotation angle.
+ * This way it's better for cache usage and for
+ * easily restricting to a certain number of
+ * sample while still having a circular kernel. */
+
+#define CONCENTRIC_SAMPLE_NUM 256
+const vec2 concentric[CONCENTRIC_SAMPLE_NUM] =
+vec2[CONCENTRIC_SAMPLE_NUM](
+ vec2(0.0441941738242, 0.0441941738242),
+ vec2(-0.0441941738242, -0.0441941738242),
+ vec2(-0.0441941738242, 0.0441941738242),
+ vec2(0.0441941738242, -0.0441941738242),
+ vec2(0.181111092429, 0.0485285709567),
+ vec2(0.132582521472, 0.132582521472),
+ vec2(-0.181111092429, 0.0485285709567),
+ vec2(0.0485285709567, 0.181111092429),
+ vec2(-0.181111092429, -0.0485285709567),
+ vec2(-0.0485285709567, 0.181111092429),
+ vec2(-0.132582521472, -0.132582521472),
+ vec2(-0.132582521472, 0.132582521472),
+ vec2(-0.0485285709567, -0.181111092429),
+ vec2(0.0485285709567, -0.181111092429),
+ vec2(0.132582521472, -0.132582521472),
+ vec2(0.181111092429, -0.0485285709567),
+ vec2(0.308652606436, 0.0488857703251),
+ vec2(0.278439538809, 0.141872031169),
+ vec2(0.220970869121, 0.220970869121),
+ vec2(-0.278439538809, 0.141872031169),
+ vec2(0.141872031169, 0.278439538809),
+ vec2(-0.308652606436, 0.0488857703251),
+ vec2(0.0488857703251, 0.308652606436),
+ vec2(-0.308652606436, -0.0488857703251),
+ vec2(-0.0488857703251, 0.308652606436),
+ vec2(-0.278439538809, -0.141872031169),
+ vec2(-0.141872031169, 0.278439538809),
+ vec2(-0.220970869121, -0.220970869121),
+ vec2(-0.220970869121, 0.220970869121),
+ vec2(-0.141872031169, -0.278439538809),
+ vec2(-0.0488857703251, -0.308652606436),
+ vec2(0.0488857703251, -0.308652606436),
+ vec2(0.141872031169, -0.278439538809),
+ vec2(0.220970869121, -0.220970869121),
+ vec2(0.278439538809, -0.141872031169),
+ vec2(0.308652606436, -0.0488857703251),
+ vec2(0.434749091828, 0.0489844582952),
+ vec2(0.41294895701, 0.144497089605),
+ vec2(0.370441837162, 0.232764033475),
+ vec2(0.309359216769, 0.309359216769),
+ vec2(-0.370441837162, 0.232764033475),
+ vec2(0.232764033475, 0.370441837162),
+ vec2(-0.41294895701, 0.144497089605),
+ vec2(0.144497089605, 0.41294895701),
+ vec2(-0.434749091828, 0.0489844582952),
+ vec2(0.0489844582952, 0.434749091828),
+ vec2(-0.434749091828, -0.0489844582952),
+ vec2(-0.0489844582952, 0.434749091828),
+ vec2(-0.41294895701, -0.144497089605),
+ vec2(-0.144497089605, 0.41294895701),
+ vec2(-0.370441837162, -0.232764033475),
+ vec2(-0.232764033475, 0.370441837162),
+ vec2(-0.309359216769, -0.309359216769),
+ vec2(-0.309359216769, 0.309359216769),
+ vec2(-0.232764033475, -0.370441837162),
+ vec2(-0.144497089605, -0.41294895701),
+ vec2(-0.0489844582952, -0.434749091828),
+ vec2(0.0489844582952, -0.434749091828),
+ vec2(0.144497089605, -0.41294895701),
+ vec2(0.232764033475, -0.370441837162),
+ vec2(0.309359216769, -0.309359216769),
+ vec2(0.370441837162, -0.232764033475),
+ vec2(0.41294895701, -0.144497089605),
+ vec2(0.434749091828, -0.0489844582952),
+ vec2(0.560359517677, 0.0490251052956),
+ vec2(0.543333277288, 0.14558571287),
+ vec2(0.509798130208, 0.237722772229),
+ vec2(0.460773024913, 0.322636745447),
+ vec2(0.397747564417, 0.397747564417),
+ vec2(-0.460773024913, 0.322636745447),
+ vec2(0.322636745447, 0.460773024913),
+ vec2(-0.509798130208, 0.237722772229),
+ vec2(0.237722772229, 0.509798130208),
+ vec2(-0.543333277288, 0.14558571287),
+ vec2(0.14558571287, 0.543333277288),
+ vec2(-0.560359517677, 0.0490251052956),
+ vec2(0.0490251052956, 0.560359517677),
+ vec2(-0.560359517677, -0.0490251052956),
+ vec2(-0.0490251052956, 0.560359517677),
+ vec2(-0.543333277288, -0.14558571287),
+ vec2(-0.14558571287, 0.543333277288),
+ vec2(-0.509798130208, -0.237722772229),
+ vec2(-0.237722772229, 0.509798130208),
+ vec2(-0.460773024913, -0.322636745447),
+ vec2(-0.322636745447, 0.460773024913),
+ vec2(-0.397747564417, -0.397747564417),
+ vec2(-0.397747564417, 0.397747564417),
+ vec2(-0.322636745447, -0.460773024913),
+ vec2(-0.237722772229, -0.509798130208),
+ vec2(-0.14558571287, -0.543333277288),
+ vec2(-0.0490251052956, -0.560359517677),
+ vec2(0.0490251052956, -0.560359517677),
+ vec2(0.14558571287, -0.543333277288),
+ vec2(0.237722772229, -0.509798130208),
+ vec2(0.322636745447, -0.460773024913),
+ vec2(0.397747564417, -0.397747564417),
+ vec2(0.460773024913, -0.322636745447),
+ vec2(0.509798130208, -0.237722772229),
+ vec2(0.543333277288, -0.14558571287),
+ vec2(0.560359517677, -0.0490251052956),
+ vec2(0.685748328795, 0.0490456884495),
+ vec2(0.671788470355, 0.146138636568),
+ vec2(0.644152935937, 0.240256623474),
+ vec2(0.603404305327, 0.32948367837),
+ vec2(0.550372103135, 0.412003395727),
+ vec2(0.486135912066, 0.486135912066),
+ vec2(-0.550372103135, 0.412003395727),
+ vec2(0.412003395727, 0.550372103135),
+ vec2(-0.603404305327, 0.32948367837),
+ vec2(0.32948367837, 0.603404305327),
+ vec2(-0.644152935937, 0.240256623474),
+ vec2(0.240256623474, 0.644152935937),
+ vec2(-0.671788470355, 0.146138636568),
+ vec2(0.146138636568, 0.671788470355),
+ vec2(-0.685748328795, 0.0490456884495),
+ vec2(0.0490456884495, 0.685748328795),
+ vec2(-0.685748328795, -0.0490456884495),
+ vec2(-0.0490456884495, 0.685748328795),
+ vec2(-0.671788470355, -0.146138636568),
+ vec2(-0.146138636568, 0.671788470355),
+ vec2(-0.644152935937, -0.240256623474),
+ vec2(-0.240256623474, 0.644152935937),
+ vec2(-0.603404305327, -0.32948367837),
+ vec2(-0.32948367837, 0.603404305327),
+ vec2(-0.550372103135, -0.412003395727),
+ vec2(-0.412003395727, 0.550372103135),
+ vec2(-0.486135912066, -0.486135912066),
+ vec2(-0.486135912066, 0.486135912066),
+ vec2(-0.412003395727, -0.550372103135),
+ vec2(-0.32948367837, -0.603404305327),
+ vec2(-0.240256623474, -0.644152935937),
+ vec2(-0.146138636568, -0.671788470355),
+ vec2(-0.0490456884495, -0.685748328795),
+ vec2(0.0490456884495, -0.685748328795),
+ vec2(0.146138636568, -0.671788470355),
+ vec2(0.240256623474, -0.644152935937),
+ vec2(0.32948367837, -0.603404305327),
+ vec2(0.412003395727, -0.550372103135),
+ vec2(0.486135912066, -0.486135912066),
+ vec2(0.550372103135, -0.412003395727),
+ vec2(0.603404305327, -0.32948367837),
+ vec2(0.644152935937, -0.240256623474),
+ vec2(0.671788470355, -0.146138636568),
+ vec2(0.685748328795, -0.0490456884495),
+ vec2(0.811017637806, 0.0490575291556),
+ vec2(0.799191174395, 0.146457218224),
+ vec2(0.775710704038, 0.241721231257),
+ vec2(0.740918624869, 0.33346040443),
+ vec2(0.695322283745, 0.420336974019),
+ vec2(0.639586577995, 0.501084084011),
+ vec2(0.574524259714, 0.574524259714),
+ vec2(-0.639586577995, 0.501084084011),
+ vec2(0.501084084011, 0.639586577995),
+ vec2(-0.695322283745, 0.420336974019),
+ vec2(0.420336974019, 0.695322283745),
+ vec2(-0.740918624869, 0.33346040443),
+ vec2(0.33346040443, 0.740918624869),
+ vec2(-0.775710704038, 0.241721231257),
+ vec2(0.241721231257, 0.775710704038),
+ vec2(-0.799191174395, 0.146457218224),
+ vec2(0.146457218224, 0.799191174395),
+ vec2(-0.811017637806, 0.0490575291556),
+ vec2(0.0490575291556, 0.811017637806),
+ vec2(-0.811017637806, -0.0490575291556),
+ vec2(-0.0490575291556, 0.811017637806),
+ vec2(-0.799191174395, -0.146457218224),
+ vec2(-0.146457218224, 0.799191174395),
+ vec2(-0.775710704038, -0.241721231257),
+ vec2(-0.241721231257, 0.775710704038),
+ vec2(-0.740918624869, -0.33346040443),
+ vec2(-0.33346040443, 0.740918624869),
+ vec2(-0.695322283745, -0.420336974019),
+ vec2(-0.420336974019, 0.695322283745),
+ vec2(-0.639586577995, -0.501084084011),
+ vec2(-0.501084084011, 0.639586577995),
+ vec2(-0.574524259714, -0.574524259714),
+ vec2(-0.574524259714, 0.574524259714),
+ vec2(-0.501084084011, -0.639586577995),
+ vec2(-0.420336974019, -0.695322283745),
+ vec2(-0.33346040443, -0.740918624869),
+ vec2(-0.241721231257, -0.775710704038),
+ vec2(-0.146457218224, -0.799191174395),
+ vec2(-0.0490575291556, -0.811017637806),
+ vec2(0.0490575291556, -0.811017637806),
+ vec2(0.146457218224, -0.799191174395),
+ vec2(0.241721231257, -0.775710704038),
+ vec2(0.33346040443, -0.740918624869),
+ vec2(0.420336974019, -0.695322283745),
+ vec2(0.501084084011, -0.639586577995),
+ vec2(0.574524259714, -0.574524259714),
+ vec2(0.639586577995, -0.501084084011),
+ vec2(0.695322283745, -0.420336974019),
+ vec2(0.740918624869, -0.33346040443),
+ vec2(0.775710704038, -0.241721231257),
+ vec2(0.799191174395, -0.146457218224),
+ vec2(0.811017637806, -0.0490575291556),
+ vec2(0.936215188832, 0.0490649589778),
+ vec2(0.925957819308, 0.146657310975),
+ vec2(0.905555462146, 0.242642854784),
+ vec2(0.875231649841, 0.335969952699),
+ vec2(0.835318616427, 0.425616093506),
+ vec2(0.786253657449, 0.510599095327),
+ vec2(0.728574338866, 0.589987866609),
+ vec2(0.662912607362, 0.662912607362),
+ vec2(-0.728574338866, 0.589987866609),
+ vec2(0.589987866609, 0.728574338866),
+ vec2(-0.786253657449, 0.510599095327),
+ vec2(0.510599095327, 0.786253657449),
+ vec2(-0.835318616427, 0.425616093506),
+ vec2(0.425616093506, 0.835318616427),
+ vec2(-0.875231649841, 0.335969952699),
+ vec2(0.335969952699, 0.875231649841),
+ vec2(-0.905555462146, 0.242642854784),
+ vec2(0.242642854784, 0.905555462146),
+ vec2(-0.925957819308, 0.146657310975),
+ vec2(0.146657310975, 0.925957819308),
+ vec2(-0.936215188832, 0.0490649589778),
+ vec2(0.0490649589778, 0.936215188832),
+ vec2(-0.936215188832, -0.0490649589778),
+ vec2(-0.0490649589778, 0.936215188832),
+ vec2(-0.925957819308, -0.146657310975),
+ vec2(-0.146657310975, 0.925957819308),
+ vec2(-0.905555462146, -0.242642854784),
+ vec2(-0.242642854784, 0.905555462146),
+ vec2(-0.875231649841, -0.335969952699),
+ vec2(-0.335969952699, 0.875231649841),
+ vec2(-0.835318616427, -0.425616093506),
+ vec2(-0.425616093506, 0.835318616427),
+ vec2(-0.786253657449, -0.510599095327),
+ vec2(-0.510599095327, 0.786253657449),
+ vec2(-0.728574338866, -0.589987866609),
+ vec2(-0.589987866609, 0.728574338866),
+ vec2(-0.662912607362, -0.662912607362),
+ vec2(-0.662912607362, 0.662912607362),
+ vec2(-0.589987866609, -0.728574338866),
+ vec2(-0.510599095327, -0.786253657449),
+ vec2(-0.425616093506, -0.835318616427),
+ vec2(-0.335969952699, -0.875231649841),
+ vec2(-0.242642854784, -0.905555462146),
+ vec2(-0.146657310975, -0.925957819308),
+ vec2(-0.0490649589778, -0.936215188832),
+ vec2(0.0490649589778, -0.936215188832),
+ vec2(0.146657310975, -0.925957819308),
+ vec2(0.242642854784, -0.905555462146),
+ vec2(0.335969952699, -0.875231649841),
+ vec2(0.425616093506, -0.835318616427),
+ vec2(0.510599095327, -0.786253657449),
+ vec2(0.589987866609, -0.728574338866),
+ vec2(0.662912607362, -0.662912607362),
+ vec2(0.728574338866, -0.589987866609),
+ vec2(0.786253657449, -0.510599095327),
+ vec2(0.835318616427, -0.425616093506),
+ vec2(0.875231649841, -0.335969952699),
+ vec2(0.905555462146, -0.242642854784),
+ vec2(0.925957819308, -0.146657310975),
+ vec2(0.936215188832, -0.0490649589778)
+); \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
new file mode 100644
index 00000000000..45c5c88e763
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
@@ -0,0 +1,19 @@
+
+uniform vec3 basecol;
+uniform float metallic;
+uniform float specular;
+uniform float roughness;
+
+Closure nodetree_exec(void)
+{
+ vec3 dielectric = vec3(0.034) * specular * 2.0;
+ vec3 albedo = mix(basecol, vec3(0.0), metallic);
+ vec3 f0 = mix(dielectric, basecol, metallic);
+ vec3 N = (gl_FrontFacing) ? worldNormal : -worldNormal;
+ vec3 out_diff, out_spec, ssr_spec;
+ eevee_closure_default(N, albedo, f0, 0, roughness, 1.0, out_diff, out_spec, ssr_spec);
+
+ Closure result = Closure(out_spec + out_diff * albedo, 1.0, vec4(ssr_spec, roughness), normal_encode(normalize(viewNormal), viewCameraVec), 0);
+
+ return result;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl
new file mode 100644
index 00000000000..90af87756f0
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl
@@ -0,0 +1,9 @@
+
+uniform float backgroundAlpha;
+uniform vec3 color;
+
+out vec4 FragColor;
+
+void main() {
+ FragColor = vec4(color, backgroundAlpha);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl
new file mode 100644
index 00000000000..29543e82f43
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl
@@ -0,0 +1,218 @@
+/* Original implementation by Keijiro Takahashi
+ * Blender integration by Clément Foucault
+ *
+ * Original License :
+ *
+ * Kino/Bloom v2 - Bloom filter for Unity
+ *
+ * Copyright (C) 2015, 2016 Keijiro Takahashi
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ **/
+
+uniform sampler2D sourceBuffer; /* Buffer to filter */
+uniform vec2 sourceBufferTexelSize;
+
+/* Step Blit */
+uniform vec4 curveThreshold;
+uniform float clampIntensity;
+
+/* Step Upsample */
+uniform sampler2D baseBuffer; /* Previous accumulation buffer */
+uniform vec2 baseBufferTexelSize;
+uniform float sampleScale;
+
+/* Step Resolve */
+uniform vec3 bloomColor;
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+/* -------------- Utils ------------- */
+
+vec3 safe_color(vec3 c)
+{
+ /* Clamp to avoid black square artifacts if a pixel goes NaN. */
+ return clamp(c, vec3(0.0), vec3(1e20)); /* 1e20 arbitrary. */
+}
+
+float brightness(vec3 c)
+{
+ return max(max(c.r, c.g), c.b);
+}
+
+/* 3-tap median filter */
+vec3 median(vec3 a, vec3 b, vec3 c)
+{
+ return a + b + c - min(min(a, b), c) - max(max(a, b), c);
+}
+
+/* ------------- Filters ------------ */
+
+vec3 downsample_filter_high(sampler2D tex, vec2 uv, vec2 texelSize)
+{
+ /* Downsample with a 4x4 box filter + anti-flicker filter */
+ vec4 d = texelSize.xyxy * vec4(-1, -1, +1, +1);
+
+ vec3 s1 = textureLod(tex, uv + d.xy, 0.0).rgb;
+ vec3 s2 = textureLod(tex, uv + d.zy, 0.0).rgb;
+ vec3 s3 = textureLod(tex, uv + d.xw, 0.0).rgb;
+ vec3 s4 = textureLod(tex, uv + d.zw, 0.0).rgb;
+
+ /* Karis's luma weighted average (using brightness instead of luma) */
+ float s1w = 1.0 / (brightness(s1) + 1.0);
+ float s2w = 1.0 / (brightness(s2) + 1.0);
+ float s3w = 1.0 / (brightness(s3) + 1.0);
+ float s4w = 1.0 / (brightness(s4) + 1.0);
+ float one_div_wsum = 1.0 / (s1w + s2w + s3w + s4w);
+
+ return (s1 * s1w + s2 * s2w + s3 * s3w + s4 * s4w) * one_div_wsum;
+}
+
+vec3 downsample_filter(sampler2D tex, vec2 uv, vec2 texelSize)
+{
+ /* Downsample with a 4x4 box filter */
+ vec4 d = texelSize.xyxy * vec4(-1, -1, +1, +1);
+
+ vec3 s;
+ s = textureLod(tex, uv + d.xy, 0.0).rgb;
+ s += textureLod(tex, uv + d.zy, 0.0).rgb;
+ s += textureLod(tex, uv + d.xw, 0.0).rgb;
+ s += textureLod(tex, uv + d.zw, 0.0).rgb;
+
+ return s * (1.0 / 4);
+}
+
+vec3 upsample_filter_high(sampler2D tex, vec2 uv, vec2 texelSize)
+{
+ /* 9-tap bilinear upsampler (tent filter) */
+ vec4 d = texelSize.xyxy * vec4(1, 1, -1, 0) * sampleScale;
+
+ vec3 s;
+ s = textureLod(tex, uv - d.xy, 0.0).rgb;
+ s += textureLod(tex, uv - d.wy, 0.0).rgb * 2;
+ s += textureLod(tex, uv - d.zy, 0.0).rgb;
+
+ s += textureLod(tex, uv + d.zw, 0.0).rgb * 2;
+ s += textureLod(tex, uv , 0.0).rgb * 4;
+ s += textureLod(tex, uv + d.xw, 0.0).rgb * 2;
+
+ s += textureLod(tex, uv + d.zy, 0.0).rgb;
+ s += textureLod(tex, uv + d.wy, 0.0).rgb * 2;
+ s += textureLod(tex, uv + d.xy, 0.0).rgb;
+
+ return s * (1.0 / 16.0);
+}
+
+vec3 upsample_filter(sampler2D tex, vec2 uv, vec2 texelSize)
+{
+ /* 4-tap bilinear upsampler */
+ vec4 d = texelSize.xyxy * vec4(-1, -1, +1, +1) * (sampleScale * 0.5);
+
+ vec3 s;
+ s = textureLod(tex, uv + d.xy, 0.0).rgb;
+ s += textureLod(tex, uv + d.zy, 0.0).rgb;
+ s += textureLod(tex, uv + d.xw, 0.0).rgb;
+ s += textureLod(tex, uv + d.zw, 0.0).rgb;
+
+ return s * (1.0 / 4.0);
+}
+
+/* ----------- Steps ----------- */
+
+vec4 step_blit(void)
+{
+ vec2 uv = uvcoordsvar.xy + sourceBufferTexelSize.xy * 0.5;
+
+#ifdef HIGH_QUALITY /* Anti flicker */
+ vec3 d = sourceBufferTexelSize.xyx * vec3(1, 1, 0);
+ vec3 s0 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy, 0.0).rgb);
+ vec3 s1 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy - d.xz, 0.0).rgb);
+ vec3 s2 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy + d.xz, 0.0).rgb);
+ vec3 s3 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy - d.zy, 0.0).rgb);
+ vec3 s4 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy + d.zy, 0.0).rgb);
+ vec3 m = median(median(s0.rgb, s1, s2), s3, s4);
+#else
+ vec3 s0 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy, 0.0).rgb);
+ vec3 m = s0.rgb;
+#endif
+
+ /* Pixel brightness */
+ float br = brightness(m);
+
+ /* Under-threshold part: quadratic curve */
+ float rq = clamp(br - curveThreshold.x, 0, curveThreshold.y);
+ rq = curveThreshold.z * rq * rq;
+
+ /* Combine and apply the brightness response curve. */
+ m *= max(rq, br - curveThreshold.w) / max(1e-5, br);
+
+ /* Clamp pixel intensity */
+ br = max(1e-5, brightness(m));
+ m *= 1.0 - max(0.0, br - clampIntensity) / br;
+
+ return vec4(m, 1.0);
+}
+
+vec4 step_downsample(void)
+{
+#ifdef HIGH_QUALITY /* Anti flicker */
+ vec3 sample = downsample_filter_high(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize);
+#else
+ vec3 sample = downsample_filter(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize);
+#endif
+ return vec4(sample, 1.0);
+}
+
+vec4 step_upsample(void)
+{
+#ifdef HIGH_QUALITY
+ vec3 blur = upsample_filter_high(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize);
+#else
+ vec3 blur = upsample_filter(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize);
+#endif
+ vec3 base = textureLod(baseBuffer, uvcoordsvar.xy, 0.0).rgb;
+ return vec4(base + blur, 1.0);
+}
+
+vec4 step_resolve(void)
+{
+#ifdef HIGH_QUALITY
+ vec3 blur = upsample_filter_high(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize);
+#else
+ vec3 blur = upsample_filter(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize);
+#endif
+ vec4 base = textureLod(baseBuffer, uvcoordsvar.xy, 0.0);
+ vec3 cout = base.rgb + blur * bloomColor;
+ return vec4(cout, base.a);
+}
+
+void main(void)
+{
+#if defined(STEP_BLIT)
+ FragColor = step_blit();
+#elif defined(STEP_DOWNSAMPLE)
+ FragColor = step_downsample();
+#elif defined(STEP_UPSAMPLE)
+ FragColor = step_upsample();
+#elif defined(STEP_RESOLVE)
+ FragColor = step_resolve();
+#endif
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
new file mode 100644
index 00000000000..04648f62688
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
@@ -0,0 +1,261 @@
+
+uniform mat4 ProjectionMatrix;
+
+uniform sampler2D colorBuffer;
+uniform sampler2D depthBuffer;
+
+uniform vec3 dofParams;
+
+#define dof_aperturesize dofParams.x
+#define dof_distance dofParams.y
+#define dof_invsensorsize dofParams.z
+
+uniform vec4 bokehParams;
+
+#define bokeh_sides bokehParams.x /* Polygon Bokeh shape number of sides */
+#define bokeh_rotation bokehParams.y
+#define bokeh_ratio bokehParams.z
+#define bokeh_maxsize bokehParams.w
+
+uniform vec2 nearFar; /* Near & far view depths values */
+
+/* initial uv coordinate */
+in vec2 uvcoord;
+
+layout(location = 0) out vec4 fragData0;
+layout(location = 1) out vec4 fragData1;
+layout(location = 2) out vec4 fragData2;
+
+#define M_PI 3.1415926535897932384626433832795
+#define M_2PI 6.2831853071795864769252868
+
+/* -------------- Utils ------------- */
+
+/* calculate 4 samples at once */
+float calculate_coc(in float zdepth)
+{
+ float coc = dof_aperturesize * (dof_distance / zdepth - 1.0);
+
+ /* multiply by 1.0 / sensor size to get the normalized size */
+ return coc * dof_invsensorsize;
+}
+
+vec4 calculate_coc(in vec4 zdepth)
+{
+ vec4 coc = dof_aperturesize * (vec4(dof_distance) / zdepth - vec4(1.0));
+
+ /* multiply by 1.0 / sensor size to get the normalized size */
+ return coc * dof_invsensorsize;
+}
+
+float max4(vec4 x)
+{
+ return max(max(x.x, x.y), max(x.z, x.w));
+}
+
+float linear_depth(float z)
+{
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ return (nearFar.x * nearFar.y) / (z * (nearFar.x - nearFar.y) + nearFar.y);
+ }
+ else {
+ return (z * 2.0 - 1.0) * nearFar.y;
+ }
+}
+
+vec4 linear_depth(vec4 z)
+{
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ return (nearFar.xxxx * nearFar.yyyy) / (z * (nearFar.xxxx - nearFar.yyyy) + nearFar.yyyy);
+ }
+ else {
+ return (z * 2.0 - 1.0) * nearFar.yyyy;
+ }
+}
+
+#define THRESHOLD 0.0
+
+/* ----------- Steps ----------- */
+
+/* Downsample the color buffer to half resolution.
+ * Weight color samples by
+ * Compute maximum CoC for near and far blur. */
+void step_downsample(void)
+{
+ ivec4 uvs = ivec4(gl_FragCoord.xyxy) * 2 + ivec4(0, 0, 1, 1);
+
+ /* custom downsampling */
+ vec4 color1 = texelFetch(colorBuffer, uvs.xy, 0);
+ vec4 color2 = texelFetch(colorBuffer, uvs.zw, 0);
+ vec4 color3 = texelFetch(colorBuffer, uvs.zy, 0);
+ vec4 color4 = texelFetch(colorBuffer, uvs.xw, 0);
+
+ /* Leverage SIMD by combining 4 depth samples into a vec4 */
+ vec4 depth;
+ depth.r = texelFetch(depthBuffer, uvs.xy, 0).r;
+ depth.g = texelFetch(depthBuffer, uvs.zw, 0).r;
+ depth.b = texelFetch(depthBuffer, uvs.zy, 0).r;
+ depth.a = texelFetch(depthBuffer, uvs.xw, 0).r;
+
+ vec4 zdepth = linear_depth(depth);
+
+ /* Compute signed CoC for each depth samples */
+ vec4 coc_near = calculate_coc(zdepth);
+ vec4 coc_far = -coc_near;
+
+ /* now we need to write the near-far fields premultiplied by the coc */
+ vec4 near_weights = step(THRESHOLD, coc_near);
+ vec4 far_weights = step(THRESHOLD, coc_far);
+
+ /* now write output to weighted buffers. */
+ fragData0 = color1 * near_weights.x +
+ color2 * near_weights.y +
+ color3 * near_weights.z +
+ color4 * near_weights.w;
+
+ fragData1 = color1 * far_weights.x +
+ color2 * far_weights.y +
+ color3 * far_weights.z +
+ color4 * far_weights.w;
+
+ float norm_near = dot(near_weights, near_weights);
+ float norm_far = dot(far_weights, far_weights);
+
+ if (norm_near > 0.0) {
+ fragData0 /= norm_near;
+ }
+
+ if (norm_far > 0.0) {
+ fragData1 /= norm_far;
+ }
+
+ float max_near_coc = max(max4(coc_near), 0.0);
+ float max_far_coc = max(max4(coc_far), 0.0);
+
+ fragData2 = vec4(max_near_coc, max_far_coc, 0.0, 1.0);
+}
+
+/* coordinate used for calculating radius et al set in geometry shader */
+in vec2 particlecoord;
+flat in vec4 color;
+
+/* accumulate color in the near/far blur buffers */
+void step_scatter(void)
+{
+ /* Early out */
+ float dist_sqrd = dot(particlecoord, particlecoord);
+
+ /* Circle Dof */
+ if (dist_sqrd > 1.0) {
+ discard;
+ }
+
+ /* Regular Polygon Dof */
+ if (bokeh_sides > 0.0) {
+ /* Circle parametrization */
+ float theta = atan(particlecoord.y, particlecoord.x) + bokeh_rotation;
+ float r;
+
+ r = cos(M_PI / bokeh_sides) /
+ (cos(theta - (M_2PI / bokeh_sides) * floor((bokeh_sides * theta + M_PI) / M_2PI)));
+
+ if (dist_sqrd > r * r) {
+ discard;
+ }
+ }
+
+ fragData0 = color;
+}
+
+#define MERGE_THRESHOLD 4.0
+
+uniform sampler2D farBuffer;
+uniform sampler2D nearBuffer;
+
+vec4 upsample_filter_high(sampler2D tex, vec2 uv, vec2 texelSize)
+{
+ /* 9-tap bilinear upsampler (tent filter) */
+ vec4 d = texelSize.xyxy * vec4(1, 1, -1, 0);
+
+ vec4 s;
+ s = textureLod(tex, uv - d.xy, 0.0);
+ s += textureLod(tex, uv - d.wy, 0.0) * 2;
+ s += textureLod(tex, uv - d.zy, 0.0);
+
+ s += textureLod(tex, uv + d.zw, 0.0) * 2;
+ s += textureLod(tex, uv , 0.0) * 4;
+ s += textureLod(tex, uv + d.xw, 0.0) * 2;
+
+ s += textureLod(tex, uv + d.zy, 0.0);
+ s += textureLod(tex, uv + d.wy, 0.0) * 2;
+ s += textureLod(tex, uv + d.xy, 0.0);
+
+ return s * (1.0 / 16.0);
+}
+
+vec4 upsample_filter(sampler2D tex, vec2 uv, vec2 texelSize)
+{
+ /* 4-tap bilinear upsampler */
+ vec4 d = texelSize.xyxy * vec4(-1, -1, +1, +1) * 0.5;
+
+ vec4 s;
+ s = textureLod(tex, uv + d.xy, 0.0);
+ s += textureLod(tex, uv + d.zy, 0.0);
+ s += textureLod(tex, uv + d.xw, 0.0);
+ s += textureLod(tex, uv + d.zw, 0.0);
+
+ return s * (1.0 / 4.0);
+}
+
+/* Combine the Far and Near color buffers */
+void step_resolve(void)
+{
+ /* Recompute Near / Far CoC */
+ float depth = textureLod(depthBuffer, uvcoord, 0.0).r;
+ float zdepth = linear_depth(depth);
+ float coc_signed = calculate_coc(zdepth);
+ float coc_far = max(-coc_signed, 0.0);
+ float coc_near = max(coc_signed, 0.0);
+
+ /* Recompute Near / Far CoC */
+ vec2 texelSize = 1.0 / vec2(textureSize(farBuffer, 0));
+ vec4 srccolor = textureLod(colorBuffer, uvcoord, 0.0);
+ vec4 farcolor = upsample_filter_high(farBuffer, uvcoord, texelSize);
+ vec4 nearcolor = upsample_filter_high(nearBuffer, uvcoord, texelSize);
+
+ float farweight = farcolor.a;
+ if (farweight > 0.0)
+ farcolor /= farweight;
+
+ float mixfac = smoothstep(1.0, MERGE_THRESHOLD, coc_far);
+
+ farweight = mix(1.0, farweight, mixfac);
+
+ float nearweight = nearcolor.a;
+ if (nearweight > 0.0) {
+ nearcolor /= nearweight;
+ }
+
+ if (coc_near > 1.0) {
+ mixfac = smoothstep(1.0, MERGE_THRESHOLD, coc_near);
+ fragData0 = mix(srccolor, nearcolor, mixfac);
+ }
+ else {
+ float totalweight = nearweight + farweight;
+ vec4 finalcolor = mix(srccolor, farcolor, mixfac);
+ fragData0 = mix(finalcolor, nearcolor, nearweight / totalweight);
+ }
+}
+
+void main()
+{
+#ifdef STEP_DOWNSAMPLE
+ step_downsample();
+#elif defined(STEP_SCATTER)
+ step_scatter();
+#elif defined(STEP_RESOLVE)
+ step_resolve();
+#endif
+}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_geom.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_geom.glsl
new file mode 100644
index 00000000000..1c774885a32
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_geom.glsl
@@ -0,0 +1,55 @@
+uniform ivec2 targetBufferSize;
+
+uniform vec2 layerSelection;
+
+uniform sampler2D colorBuffer;
+uniform sampler2D cocBuffer;
+
+layout(points) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+#define POS gl_in[0].gl_Position
+
+in vec2 uvcoord[];
+out vec2 particlecoord;
+flat out vec4 color;
+
+#define M_PI 3.1415926535897932384626433832795
+
+void main()
+{
+ vec4 coc = textureLod(cocBuffer, uvcoord[0], 0.0);
+
+ float offset_val = dot(coc.rg, layerSelection);
+ if (offset_val < 1.0)
+ return;
+
+ vec4 colortex = textureLod(colorBuffer, uvcoord[0], 0.0);
+
+ /* find the area the pixel will cover and divide the color by it */
+ float alpha = 1.0 / (offset_val * offset_val * M_PI);
+ colortex *= alpha;
+ colortex.a = alpha;
+
+ vec2 offset_far = vec2(offset_val * 0.5) / vec2(targetBufferSize.x, targetBufferSize.y);
+
+ color = colortex;
+
+ gl_Position = POS + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0);
+ particlecoord = vec2(-1.0, -1.0);
+ EmitVertex();
+
+ gl_Position = POS + vec4(-offset_far.x, offset_far.y, 0.0, 0.0);
+ particlecoord = vec2(-1.0, 1.0);
+ EmitVertex();
+
+ gl_Position = POS + vec4(offset_far.x, -offset_far.y, 0.0, 0.0);
+ particlecoord = vec2(1.0, -1.0);
+ EmitVertex();
+
+ gl_Position = POS + vec4(offset_far.x, offset_far.y, 0.0, 0.0);
+ particlecoord = vec2(1.0, 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl
new file mode 100644
index 00000000000..0f5c5e5b16b
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl
@@ -0,0 +1,99 @@
+
+in vec2 pos;
+in vec2 uvs;
+
+uniform vec2 layerSelection;
+
+uniform vec4 bokehParams;
+
+#define bokeh_sides bokehParams.x /* Polygon Bokeh shape number of sides */
+#define bokeh_rotation bokehParams.y
+#define bokeh_ratio bokehParams.z
+#define bokeh_maxsize bokehParams.w
+
+uniform sampler2D colorBuffer;
+uniform sampler2D cocBuffer;
+
+flat out vec4 color;
+out vec2 particlecoord;
+
+#define M_PI 3.1415926535897932384626433832795
+
+/* geometry shading pass, calculate a texture coordinate based on the indexed id */
+void step_scatter()
+{
+ ivec2 tex_size = textureSize(cocBuffer, 0);
+ vec2 texel_size = 1.0 / vec2(tex_size);
+
+ int t_id = gl_VertexID / 3; /* Triangle Id */
+
+ ivec2 texelco = ivec2(0);
+ /* some math to get the target pixel */
+ texelco.x = t_id % tex_size.x;
+ texelco.y = t_id / tex_size.x;
+
+ float coc = dot(layerSelection, texelFetch(cocBuffer, texelco, 0).rg);
+
+ /* Clamp to max size for performance */
+ coc = min(coc, bokeh_maxsize);
+
+ if (coc >= 1.0) {
+ color = texelFetch(colorBuffer, texelco, 0);
+ /* find the area the pixel will cover and divide the color by it */
+ float alpha = 1.0 / (coc * coc * M_PI);
+ color *= alpha;
+ color.a = alpha;
+ }
+ else {
+ color = vec4(0.0);
+ }
+
+ /* Generate Triangle : less memory fetches from a VBO */
+ int v_id = gl_VertexID % 3; /* Vertex Id */
+
+ /* Extend to cover at least the unit circle */
+ const float extend = (cos(M_PI / 4.0) + 1.0) * 2.0;
+ /* Crappy diagram
+ * ex 1
+ * | \
+ * | \
+ * 1 | \
+ * | \
+ * | \
+ * 0 | x \
+ * | Circle \
+ * | Origin \
+ * -1 0 --------------- 2
+ * -1 0 1 ex
+ **/
+ gl_Position.x = float(v_id / 2) * extend - 1.0; /* int divisor round down */
+ gl_Position.y = float(v_id % 2) * extend - 1.0;
+ gl_Position.z = 0.0;
+ gl_Position.w = 1.0;
+
+ /* Generate Triangle */
+ particlecoord = gl_Position.xy;
+
+ gl_Position.xy *= coc * texel_size * vec2(bokeh_ratio, 1.0);
+ gl_Position.xy -= 1.0 - 0.5 * texel_size; /* NDC Bottom left */
+ gl_Position.xy += (0.5 + vec2(texelco) * 2.0) * texel_size;
+}
+
+out vec2 uvcoord;
+
+void passthrough()
+{
+ uvcoord = uvs;
+ gl_Position = vec4(pos, 0.0, 1.0);
+}
+
+void main()
+{
+#if defined(STEP_DOWNSAMPLE)
+ passthrough();
+#elif defined(STEP_SCATTER)
+ step_scatter();
+#elif defined(STEP_RESOLVE)
+ passthrough();
+#endif
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/effect_downsample_cube_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_downsample_cube_frag.glsl
new file mode 100644
index 00000000000..eb463d51146
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_downsample_cube_frag.glsl
@@ -0,0 +1,30 @@
+/**
+ * Simple downsample shader. Takes the average of the 4 texels of lower mip.
+ **/
+
+uniform samplerCube source;
+uniform float texelSize;
+
+flat in int fFace;
+
+out vec4 FragColor;
+
+const vec3 maj_axes[6] = vec3[6](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3( 0.0, 0.0, 1.0), vec3( 0.0, 0.0, -1.0));
+const vec3 x_axis[6] = vec3[6](vec3(0.0, 0.0, -1.0), vec3( 0.0, 0.0, 1.0), vec3(1.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), vec3( 1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0));
+const vec3 y_axis[6] = vec3[6](vec3(0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0), vec3( 0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0));
+
+float brightness(vec3 c)
+{
+ return max(max(c.r, c.g), c.b);
+}
+
+void main()
+{
+ vec2 uvs = gl_FragCoord.xy * texelSize;
+
+ uvs = 2.0 * uvs - 1.0;
+
+ vec3 cubevec = x_axis[fFace] * uvs.x + y_axis[fFace] * uvs.y + maj_axes[fFace];
+
+ FragColor = textureLod(source, cubevec, 0.0);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl
new file mode 100644
index 00000000000..156be108a14
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl
@@ -0,0 +1,37 @@
+/**
+ * Simple downsample shader. Takes the average of the 4 texels of lower mip.
+ **/
+
+uniform sampler2D source;
+uniform float fireflyFactor;
+
+out vec4 FragColor;
+
+float brightness(vec3 c)
+{
+ return max(max(c.r, c.g), c.b);
+}
+
+void main()
+{
+#if 0
+ /* Reconstructing Target uvs like this avoid missing pixels if NPO2 */
+ vec2 uvs = gl_FragCoord.xy * 2.0 / vec2(textureSize(source, 0));
+
+ FragColor = textureLod(source, uvs, 0.0);
+#else
+ vec2 texel_size = 1.0 / vec2(textureSize(source, 0));
+ vec2 uvs = gl_FragCoord.xy * 2.0 * texel_size;
+ vec4 ofs = texel_size.xyxy * vec4(0.75, 0.75, -0.75, -0.75);
+
+ FragColor = textureLod(source, uvs + ofs.xy, 0.0);
+ FragColor += textureLod(source, uvs + ofs.xw, 0.0);
+ FragColor += textureLod(source, uvs + ofs.zy, 0.0);
+ FragColor += textureLod(source, uvs + ofs.zw, 0.0);
+ FragColor *= 0.25;
+
+ /* Clamped brightness. */
+ float luma = max(1e-8, brightness(FragColor.rgb));
+ FragColor *= 1.0 - max(0.0, luma - fireflyFactor) / luma;
+#endif
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
new file mode 100644
index 00000000000..1c63051c65b
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
@@ -0,0 +1,69 @@
+/**
+ * This shader only compute maximum horizon angles for each directions.
+ * The final integration is done at the resolve stage with the shading normal.
+ **/
+
+uniform float rotationOffset;
+
+out vec4 FragColor;
+
+#ifdef DEBUG_AO
+uniform sampler2D normalBuffer;
+
+void main()
+{
+ vec4 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0)).xyxy;
+ vec2 uvs = saturate(gl_FragCoord.xy * texel_size.xy);
+
+ float depth = textureLod(depthBuffer, uvs, 0.0).r;
+
+ vec3 viewPosition = get_view_space_from_depth(uvs, depth);
+ vec3 V = viewCameraVec;
+ vec3 normal = normal_decode(texture(normalBuffer, uvs).rg, V);
+
+ vec3 bent_normal;
+ float visibility;
+#if 1
+ gtao_deferred(normal, viewPosition, depth, visibility, bent_normal);
+#else
+ vec2 rand = vec2((1.0 / 4.0) * float((int(gl_FragCoord.y) & 0x1) * 2 + (int(gl_FragCoord.x) & 0x1)), 0.5);
+ rand = fract(rand.x + texture(utilTex, vec3(floor(gl_FragCoord.xy * 0.5) / LUT_SIZE, 2.0)).rg);
+ gtao(normal, viewPosition, rand, visibility, bent_normal);
+#endif
+ denoise_ao(normal, depth, visibility, bent_normal);
+
+ FragColor = vec4(visibility);
+}
+
+#else
+uniform float sampleNbr;
+
+void main()
+{
+ ivec2 hr_co = ivec2(gl_FragCoord.xy);
+ ivec2 fs_co = get_fs_co(hr_co);
+
+ vec2 uvs = saturate((vec2(fs_co) + 0.5) / vec2(textureSize(depthBuffer, 0)));
+ float depth = textureLod(depthBuffer, uvs, 0.0).r;
+
+ if (depth == 1.0) {
+ /* Do not trace for background */
+ FragColor = vec4(0.0);
+ return;
+ }
+
+ /* Avoid self shadowing. */
+ depth = saturate(depth - 3e-6); /* Tweaked for 24bit depth buffer. */
+
+ vec3 viewPosition = get_view_space_from_depth(uvs, depth);
+
+ float phi = get_phi(hr_co, fs_co, sampleNbr);
+ float offset = get_offset(fs_co, sampleNbr);
+ vec2 max_dir = get_max_dir(viewPosition.z);
+
+ FragColor.xy = search_horizon_sweep(phi, viewPosition, uvs, offset, max_dir);
+
+ /* Resize output for integer texture. */
+ FragColor = pack_horizons(FragColor.xy).xyxy;
+}
+#endif
diff --git a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl
new file mode 100644
index 00000000000..ce6f3568cdf
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl
@@ -0,0 +1,65 @@
+/**
+ * Shader that downsample depth buffer,
+ * saving min and max value of each texel in the above mipmaps.
+ * Adapted from http://rastergrid.com/blog/2010/10/hierarchical-z-map-based-occlusion-culling/
+ **/
+
+#ifdef LAYERED
+uniform sampler2DArray depthBuffer;
+uniform int depthLayer;
+#else
+uniform sampler2D depthBuffer;
+#endif
+
+#ifdef LAYERED
+#define sampleLowerMip(t) texelFetch(depthBuffer, ivec3(t, depthLayer), 0).r
+#else
+#define sampleLowerMip(t) texelFetch(depthBuffer, t, 0).r
+#endif
+
+#ifdef MIN_PASS
+#define minmax(a, b) min(a, b)
+#else /* MAX_PASS */
+#define minmax(a, b) max(a, b)
+#endif
+
+void main()
+{
+ ivec2 texelPos = ivec2(gl_FragCoord.xy);
+ ivec2 mipsize = textureSize(depthBuffer, 0).xy;
+
+#ifndef COPY_DEPTH
+ texelPos *= 2;
+#endif
+
+ float val = sampleLowerMip(texelPos);
+#ifndef COPY_DEPTH
+ float val2 = sampleLowerMip(texelPos + ivec2(1, 0));
+ float val3 = sampleLowerMip(texelPos + ivec2(1, 1));
+ float val4 = sampleLowerMip(texelPos + ivec2(0, 1));
+ val = minmax(val, val2);
+ val = minmax(val, val3);
+ val = minmax(val, val4);
+
+ /* if we are reducing an odd-width texture then fetch the edge texels */
+ if (((mipsize.x & 1) != 0) && (texelPos.x == mipsize.x - 3)) {
+ /* if both edges are odd, fetch the top-left corner texel */
+ if (((mipsize.y & 1) != 0) && (texelPos.y == mipsize.y - 3)) {
+ val = minmax(val, sampleLowerMip(texelPos + ivec2(2, 2)));
+ }
+ float val2 = sampleLowerMip(texelPos + ivec2(2, 0));
+ float val3 = sampleLowerMip(texelPos + ivec2(2, 1));
+ val = minmax(val, val2);
+ val = minmax(val, val3);
+ }
+ /* if we are reducing an odd-height texture then fetch the edge texels */
+ if (((mipsize.y & 1) != 0) && (texelPos.y == mipsize.y - 3)) {
+ float val2 = sampleLowerMip(texelPos + ivec2(0, 2));
+ float val3 = sampleLowerMip(texelPos + ivec2(1, 2));
+ val = minmax(val, val2);
+ val = minmax(val, val3);
+ }
+#endif
+
+ gl_FragDepth = val;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl
new file mode 100644
index 00000000000..1a01db3a1a3
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl
@@ -0,0 +1,65 @@
+
+uniform sampler2D colorBuffer;
+uniform sampler2D depthBuffer;
+
+
+/* current frame */
+uniform mat4 currInvViewProjMatrix;
+
+/* past frame frame */
+uniform mat4 pastViewProjMatrix;
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+#define MAX_SAMPLE 64
+
+uniform int samples;
+
+float wang_hash_noise(uint s)
+{
+ uint seed = (uint(gl_FragCoord.x) * 1664525u + uint(gl_FragCoord.y)) + s;
+
+ seed = (seed ^ 61u) ^ (seed >> 16u);
+ seed *= 9u;
+ seed = seed ^ (seed >> 4u);
+ seed *= 0x27d4eb2du;
+ seed = seed ^ (seed >> 15u);
+
+ float value = float(seed);
+ value *= 1.0 / 4294967296.0;
+ return fract(value);
+}
+
+void main()
+{
+ vec3 ndc_pos;
+ ndc_pos.xy = uvcoordsvar.xy;
+ ndc_pos.z = texture(depthBuffer, uvcoordsvar.xy).x;
+
+ float inv_samples = 1.0 / float(samples);
+ float noise = 2.0 * wang_hash_noise(0u) * inv_samples;
+
+ /* Normalize Device Coordinates are [-1, +1]. */
+ ndc_pos = ndc_pos * 2.0 - 1.0;
+
+ vec4 p = currInvViewProjMatrix * vec4(ndc_pos, 1.0);
+ vec3 world_pos = p.xyz / p.w; /* Perspective divide */
+
+ /* Now find where was this pixel position
+ * inside the past camera viewport */
+ vec4 old_ndc = pastViewProjMatrix * vec4(world_pos, 1.0);
+ old_ndc.xyz /= old_ndc.w; /* Perspective divide */
+
+ vec2 motion = (ndc_pos.xy - old_ndc.xy) * 0.25; /* 0.25 fit cycles ref */
+
+ float inc = 2.0 * inv_samples;
+ float i = -1.0 + noise;
+
+ FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ for (int j = 0; j < samples && j < MAX_SAMPLE; j++) {
+ FragColor += textureLod(colorBuffer, uvcoordsvar.xy + motion * i, 0.0) * inv_samples;
+ i += inc;
+ }
+}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
new file mode 100644
index 00000000000..2dc8dfa0d1c
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
@@ -0,0 +1,453 @@
+
+/* Based on Stochastic Screen Space Reflections
+ * https://www.ea.com/frostbite/news/stochastic-screen-space-reflections */
+
+#ifndef UTIL_TEX
+#define UTIL_TEX
+uniform sampler2DArray utilTex;
+#endif /* UTIL_TEX */
+
+#define BRDF_BIAS 0.7
+#define MAX_MIP 9.0
+
+uniform float fireflyFactor;
+uniform float maxRoughness;
+
+#ifdef STEP_RAYTRACE
+
+uniform sampler2D normalBuffer;
+uniform sampler2D specroughBuffer;
+
+uniform int planar_count;
+uniform float noiseOffset;
+
+layout(location = 0) out vec4 hitData0;
+layout(location = 1) out vec4 hitData1;
+layout(location = 2) out vec4 hitData2;
+layout(location = 3) out vec4 hitData3;
+
+vec4 do_planar_ssr(int index, vec3 V, vec3 N, vec3 T, vec3 B, vec3 planeNormal, vec3 viewPosition, float a2, vec3 rand, float ofs)
+{
+ float pdf, NH;
+ float jitter = fract(rand.x + ofs);
+
+ /* Importance sampling bias */
+ rand.x = mix(rand.x, 0.0, BRDF_BIAS);
+
+ vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */
+ pdf = pdf_ggx_reflect(NH, a2);
+
+ vec3 R = reflect(-V, H);
+ R = reflect(R, planeNormal);
+
+ /* If ray is bad (i.e. going below the plane) regenerate. */
+ if (dot(R, planeNormal) > 0.0) {
+ vec3 H = sample_ggx(rand * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */
+ pdf = pdf_ggx_reflect(NH, a2);
+
+ R = reflect(-V, H);
+ R = reflect(R, planeNormal);
+ }
+
+ pdf = min(1024e32, pdf); /* Theoretical limit of 16bit float */
+ pdf *= -1.0; /* Tag as planar ray. */
+
+ /* Since viewspace hit position can land behind the camera in this case,
+ * we save the reflected view position (visualize it as the hit position
+ * below the reflection plane). This way it's garanted that the hit will
+ * be in front of the camera. That let us tag the bad rays with a negative
+ * sign in the Z component. */
+ vec3 hit_pos = raycast(index, viewPosition, R * 1e16, 1e16, jitter, ssrQuality, a2, false);
+
+ return vec4(hit_pos, pdf);
+}
+
+vec4 do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 viewPosition, float a2, vec3 rand, float ofs)
+{
+ float pdf, NH;
+ float jitter = fract(rand.x + ofs);
+
+ /* Importance sampling bias */
+ rand.x = mix(rand.x, 0.0, BRDF_BIAS);
+
+ vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */
+ pdf = pdf_ggx_reflect(NH, a2);
+
+ vec3 R = reflect(-V, H);
+ pdf = min(1024e32, pdf); /* Theoretical limit of 16bit float */
+
+ vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, jitter, ssrQuality, a2, true);
+
+ return vec4(hit_pos, pdf);
+}
+
+void main()
+{
+#ifdef FULLRES
+ ivec2 fullres_texel = ivec2(gl_FragCoord.xy);
+ ivec2 halfres_texel = fullres_texel;
+#else
+ ivec2 fullres_texel = ivec2(gl_FragCoord.xy) * 2;
+ ivec2 halfres_texel = ivec2(gl_FragCoord.xy);
+#endif
+
+ float depth = texelFetch(depthBuffer, fullres_texel, 0).r;
+
+ /* Early out */
+ if (depth == 1.0)
+ discard;
+
+ vec2 uvs = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0));
+#ifndef FULLRES
+ uvs *= 2.0;
+#endif
+
+ /* Using view space */
+ vec3 viewPosition = get_view_space_from_depth(uvs, depth);
+ vec3 V = viewCameraVec;
+ vec3 N = normal_decode(texelFetch(normalBuffer, fullres_texel, 0).rg, V);
+
+ /* Retrieve pixel data */
+ vec4 speccol_roughness = texelFetch(specroughBuffer, fullres_texel, 0).rgba;
+
+ /* Early out */
+ if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0)
+ discard;
+
+ float roughness = speccol_roughness.a;
+ float roughnessSquared = max(1e-3, roughness * roughness);
+ float a2 = roughnessSquared * roughnessSquared;
+
+ if (roughness > maxRoughness + 0.2) {
+ hitData0 = hitData1 = hitData2 = hitData3 = vec4(0.0);
+ return;
+ }
+
+ vec3 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0).rba;
+
+ vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition);
+ vec3 wN = transform_direction(ViewMatrixInverse, N);
+
+ vec3 T, B;
+ make_orthonormal_basis(N, T, B); /* Generate tangent space */
+
+ /* Planar Reflections */
+ for (int i = 0; i < MAX_PLANAR && i < planar_count; ++i) {
+ PlanarData pd = planars_data[i];
+
+ float fade = probe_attenuation_planar(pd, worldPosition, wN, 0.0);
+
+ if (fade > 0.5) {
+ /* Find view vector / reflection plane intersection. */
+ /* TODO optimize, use view space for all. */
+ vec3 tracePosition = line_plane_intersect(worldPosition, cameraVec, pd.pl_plane_eq);
+ tracePosition = transform_point(ViewMatrix, tracePosition);
+ vec3 planeNormal = transform_direction(ViewMatrix, pd.pl_normal);
+
+ hitData0 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand, 0.0);
+#if (RAY_COUNT > 1)
+ hitData1 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 / float(RAY_COUNT));
+#endif
+#if (RAY_COUNT > 2)
+ hitData2 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 / float(RAY_COUNT));
+#endif
+#if (RAY_COUNT > 3)
+ hitData3 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 / float(RAY_COUNT));
+#endif
+ return;
+ }
+ }
+
+ /* TODO : Raytrace together if textureGather is supported. */
+ hitData0 = do_ssr(V, N, T, B, viewPosition, a2, rand, 0.0);
+#if (RAY_COUNT > 1)
+ hitData1 = do_ssr(V, N, T, B, viewPosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 / float(RAY_COUNT));
+#endif
+#if (RAY_COUNT > 2)
+ hitData2 = do_ssr(V, N, T, B, viewPosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 / float(RAY_COUNT));
+#endif
+#if (RAY_COUNT > 3)
+ hitData3 = do_ssr(V, N, T, B, viewPosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 / float(RAY_COUNT));
+#endif
+}
+
+#else /* STEP_RESOLVE */
+
+uniform sampler2D prevColorBuffer; /* previous frame */
+uniform sampler2D normalBuffer;
+uniform sampler2D specroughBuffer;
+
+uniform sampler2D hitBuffer0;
+uniform sampler2D hitBuffer1;
+uniform sampler2D hitBuffer2;
+uniform sampler2D hitBuffer3;
+
+uniform int probe_count;
+uniform int planar_count;
+
+uniform mat4 PastViewProjectionMatrix;
+
+out vec4 fragColor;
+
+void fallback_cubemap(vec3 N, vec3 V, vec3 W, vec3 viewPosition, float roughness, float roughnessSquared, inout vec4 spec_accum)
+{
+ /* Specular probes */
+ vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
+
+ vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
+ vec3 bent_normal;
+ float final_ao = occlusion_compute(N, viewPosition, 1.0, rand.rg, bent_normal);
+ final_ao = specular_occlusion(dot(N, V), final_ao, roughness);
+
+ /* Starts at 1 because 0 is world probe */
+ for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) {
+ CubeData cd = probes_data[i];
+
+ float fade = probe_attenuation_cube(cd, W);
+
+ if (fade > 0.0) {
+ vec3 spec = final_ao * probe_evaluate_cube(float(i), cd, W, spec_dir, roughness);
+ accumulate_light(spec, fade, spec_accum);
+ }
+ }
+
+ /* World Specular */
+ if (spec_accum.a < 0.999) {
+ vec3 spec = final_ao * probe_evaluate_world_spec(spec_dir, roughness);
+ accumulate_light(spec, 1.0, spec_accum);
+ }
+}
+
+#if 0 /* Finish reprojection with motion vectors */
+vec3 get_motion_vector(vec3 pos)
+{
+}
+
+/* http://bitsquid.blogspot.fr/2017/06/reprojecting-reflections_22.html */
+vec3 find_reflection_incident_point(vec3 cam, vec3 hit, vec3 pos, vec3 N)
+{
+ float d_cam = point_plane_projection_dist(cam, pos, N);
+ float d_hit = point_plane_projection_dist(hit, pos, N);
+
+ if (d_hit < d_cam) {
+ /* Swap */
+ float tmp = d_cam;
+ d_cam = d_hit;
+ d_hit = tmp;
+ }
+
+ vec3 proj_cam = cam - (N * d_cam);
+ vec3 proj_hit = hit - (N * d_hit);
+
+ return (proj_hit - proj_cam) * d_cam / (d_cam + d_hit) + proj_cam;
+}
+#endif
+
+float brightness(vec3 c)
+{
+ return max(max(c.r, c.g), c.b);
+}
+
+vec2 get_reprojected_reflection(vec3 hit, vec3 pos, vec3 N)
+{
+ /* TODO real reprojection with motion vectors, etc... */
+ return project_point(PastViewProjectionMatrix, hit).xy * 0.5 + 0.5;
+}
+
+vec4 get_ssr_sample(
+ sampler2D hitBuffer, PlanarData pd, float planar_index, vec3 worldPosition, vec3 N, vec3 V, float roughnessSquared,
+ float cone_tan, vec2 source_uvs, vec2 texture_size, ivec2 target_texel,
+ inout float weight_acc)
+{
+ vec4 hit_co_pdf = texelFetch(hitBuffer, target_texel, 0).rgba;
+ bool has_hit = (hit_co_pdf.z > 0.0);
+ bool is_planar = (hit_co_pdf.w < 0.0);
+ hit_co_pdf.z = abs(hit_co_pdf.z);
+ hit_co_pdf.w = abs(hit_co_pdf.w);
+
+ /* Hit position in world space. */
+ hit_co_pdf.xyz = get_view_space_from_depth(hit_co_pdf.xy, hit_co_pdf.z);
+ vec3 hit_pos = transform_point(ViewMatrixInverse, hit_co_pdf.xyz);
+
+ vec2 ref_uvs;
+ vec3 hit_vec;
+ float mask = 1.0;
+ if (is_planar) {
+ /* Reflect back the hit position to have it in non-reflected world space */
+ vec3 trace_pos = line_plane_intersect(worldPosition, V, pd.pl_plane_eq);
+ hit_vec = hit_pos - trace_pos;
+ hit_vec = reflect(hit_vec, pd.pl_normal);
+ ref_uvs = project_point(ProjectionMatrix, hit_co_pdf.xyz).xy * 0.5 + 0.5;
+ }
+ else {
+ /* Find hit position in previous frame. */
+ ref_uvs = get_reprojected_reflection(hit_pos, worldPosition, N);
+ hit_vec = hit_pos - worldPosition;
+ mask = screen_border_mask(gl_FragCoord.xy / texture_size);
+ }
+ mask = min(mask, screen_border_mask(ref_uvs));
+ mask *= float(has_hit);
+
+ float hit_dist = max(1e-8, length(hit_vec));
+ vec3 L = hit_vec / hit_dist;
+
+ float cone_footprint = hit_dist * cone_tan;
+
+ /* Compute cone footprint in screen space. */
+ float homcoord = ProjectionMatrix[2][3] * hit_co_pdf.z + ProjectionMatrix[3][3];
+ cone_footprint = BRDF_BIAS * 0.5 * cone_footprint * max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) / homcoord;
+
+ /* Estimate a cone footprint to sample a corresponding mipmap level. */
+ float mip = clamp(log2(cone_footprint * max(texture_size.x, texture_size.y)), 0.0, MAX_MIP);
+
+ /* Correct UVs for mipmaping mis-alignment */
+ ref_uvs *= mip_ratio_interp(mip);
+
+ /* Slide 54 */
+ float bsdf = bsdf_ggx(N, L, V, roughnessSquared);
+ float weight = step(1e-8, hit_co_pdf.w) * bsdf / max(1e-8, hit_co_pdf.w);
+ weight_acc += weight;
+
+ vec3 sample;
+ if (is_planar) {
+ sample = textureLod(probePlanars, vec3(ref_uvs, planar_index), min(mip, lodPlanarMax)).rgb;
+ }
+ else {
+ sample = textureLod(prevColorBuffer, ref_uvs, mip).rgb;
+ }
+
+ /* Clamped brightness. */
+ float luma = max(1e-8, brightness(sample));
+ sample *= 1.0 - max(0.0, luma - fireflyFactor) / luma;
+
+ /* Do not add light if ray has failed. */
+ sample *= float(has_hit);
+
+ /* Protection against NaNs in the history buffer.
+ * This could be removed if some previous pass has already
+ * sanitized the input. */
+ if (any(isnan(sample))) {
+ sample = vec3(0.0);
+ weight = 0.0;
+ }
+
+ return vec4(sample, mask) * weight;
+}
+
+#define NUM_NEIGHBORS 4
+
+void main()
+{
+ ivec2 fullres_texel = ivec2(gl_FragCoord.xy);
+#ifdef FULLRES
+ ivec2 halfres_texel = fullres_texel;
+#else
+ ivec2 halfres_texel = ivec2(gl_FragCoord.xy / 2.0);
+#endif
+ vec2 texture_size = vec2(textureSize(depthBuffer, 0));
+ vec2 uvs = gl_FragCoord.xy / texture_size;
+ vec3 rand = texelFetch(utilTex, ivec3(fullres_texel % LUT_SIZE, 2), 0).rba;
+
+ float depth = textureLod(depthBuffer, uvs, 0.0).r;
+
+ /* Early out */
+ if (depth == 1.0)
+ discard;
+
+ /* Using world space */
+ vec3 viewPosition = get_view_space_from_depth(uvs, depth); /* Needed for viewCameraVec */
+ vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition);
+ vec3 V = cameraVec;
+ vec3 vN = normal_decode(texelFetch(normalBuffer, fullres_texel, 0).rg, viewCameraVec);
+ vec3 N = transform_direction(ViewMatrixInverse, vN);
+ vec4 speccol_roughness = texelFetch(specroughBuffer, fullres_texel, 0).rgba;
+
+ /* Early out */
+ if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0)
+ discard;
+
+ /* Find Planar Reflections affecting this pixel */
+ PlanarData pd;
+ float planar_index;
+ for (int i = 0; i < MAX_PLANAR && i < planar_count; ++i) {
+ pd = planars_data[i];
+
+ float fade = probe_attenuation_planar(pd, worldPosition, N, 0.0);
+
+ if (fade > 0.5) {
+ planar_index = float(i);
+ break;
+ }
+ }
+
+ float roughness = speccol_roughness.a;
+ float roughnessSquared = max(1e-3, roughness * roughness);
+
+ vec4 spec_accum = vec4(0.0);
+
+ /* Resolve SSR */
+ float cone_cos = cone_cosine(roughnessSquared);
+ float cone_tan = sqrt(1 - cone_cos * cone_cos) / cone_cos;
+ cone_tan *= mix(saturate(dot(N, -V) * 2.0), 1.0, roughness); /* Elongation fit */
+
+ vec2 source_uvs = project_point(PastViewProjectionMatrix, worldPosition).xy * 0.5 + 0.5;
+
+ vec4 ssr_accum = vec4(0.0);
+ float weight_acc = 0.0;
+ const ivec2 neighbors[9] = ivec2[9](
+ ivec2(0, 0),
+
+ ivec2(0, 1),
+ ivec2(-1, -1), ivec2(1, -1),
+
+ ivec2(-1, 1), ivec2(1, 1),
+ ivec2(0, -1),
+
+ ivec2(-1, 0), ivec2(1, 0)
+ );
+ ivec2 invert_neighbor;
+ invert_neighbor.x = ((fullres_texel.x & 0x1) == 0) ? 1 : -1;
+ invert_neighbor.y = ((fullres_texel.y & 0x1) == 0) ? 1 : -1;
+
+ if (roughness < maxRoughness + 0.2) {
+ for (int i = 0; i < NUM_NEIGHBORS; i++) {
+ ivec2 target_texel = halfres_texel + neighbors[i] * invert_neighbor;
+
+ ssr_accum += get_ssr_sample(hitBuffer0, pd, planar_index, worldPosition, N, V,
+ roughnessSquared, cone_tan, source_uvs,
+ texture_size, target_texel, weight_acc);
+#if (RAY_COUNT > 1)
+ ssr_accum += get_ssr_sample(hitBuffer1, pd, planar_index, worldPosition, N, V,
+ roughnessSquared, cone_tan, source_uvs,
+ texture_size, target_texel, weight_acc);
+#endif
+#if (RAY_COUNT > 2)
+ ssr_accum += get_ssr_sample(hitBuffer2, pd, planar_index, worldPosition, N, V,
+ roughnessSquared, cone_tan, source_uvs,
+ texture_size, target_texel, weight_acc);
+#endif
+#if (RAY_COUNT > 3)
+ ssr_accum += get_ssr_sample(hitBuffer3, pd, planar_index, worldPosition, N, V,
+ roughnessSquared, cone_tan, source_uvs,
+ texture_size, target_texel, weight_acc);
+#endif
+ }
+ }
+
+ /* Compute SSR contribution */
+ if (weight_acc > 0.0) {
+ ssr_accum /= weight_acc;
+ /* fade between 0.5 and 1.0 roughness */
+ ssr_accum.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness);
+ accumulate_light(ssr_accum.rgb, ssr_accum.a, spec_accum);
+ }
+
+ /* If SSR contribution is not 1.0, blend with cubemaps */
+ if (spec_accum.a < 1.0) {
+ fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum);
+ }
+
+ fragColor = vec4(spec_accum.rgb * speccol_roughness.rgb, 1.0);
+}
+
+#endif
diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
new file mode 100644
index 00000000000..88e71a060c5
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -0,0 +1,90 @@
+
+/* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */
+
+#define MAX_SSS_SAMPLES 65
+layout(std140) uniform sssProfile {
+ vec4 kernel[MAX_SSS_SAMPLES];
+ vec4 radii_max_radius;
+ int sss_samples;
+};
+
+uniform float jitterThreshold;
+uniform sampler2D depthBuffer;
+uniform sampler2D sssData;
+uniform sampler2D sssAlbedo;
+uniform sampler2DArray utilTex;
+
+out vec4 FragColor;
+
+uniform mat4 ProjectionMatrix;
+uniform vec4 viewvecs[2];
+
+float get_view_z_from_depth(float depth)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ float d = 2.0 * depth - 1.0;
+ return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
+ }
+ else {
+ return viewvecs[0].z + depth * viewvecs[1].z;
+ }
+}
+
+#define LUT_SIZE 64
+#define M_PI_2 1.5707963267948966 /* pi/2 */
+#define M_2PI 6.2831853071795865 /* 2*pi */
+
+void main(void)
+{
+ vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO precompute */
+ vec2 uvs = gl_FragCoord.xy * pixel_size;
+ vec4 sss_data = texture(sssData, uvs).rgba;
+ float depth_view = get_view_z_from_depth(texture(depthBuffer, uvs).r);
+
+ float rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2), 0).r;
+#ifdef FIRST_PASS
+ float angle = M_2PI * rand + M_PI_2;
+ vec2 dir = vec2(1.0, 0.0);
+#else /* SECOND_PASS */
+ float angle = M_2PI * rand;
+ vec2 dir = vec2(0.0, 1.0);
+#endif
+ vec2 dir_rand = vec2(cos(angle), sin(angle));
+
+ /* Compute kernel bounds in 2D. */
+ float homcoord = ProjectionMatrix[2][3] * depth_view + ProjectionMatrix[3][3];
+ vec2 scale = vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * sss_data.aa / homcoord;
+ vec2 finalStep = scale * radii_max_radius.w;
+ finalStep *= 0.5; /* samples range -1..1 */
+
+ /* Center sample */
+ vec3 accum = sss_data.rgb * kernel[0].rgb;
+
+ for (int i = 1; i < sss_samples && i < MAX_SSS_SAMPLES; i++) {
+ vec2 sample_uv = uvs + kernel[i].a * finalStep * ((abs(kernel[i].a) > jitterThreshold) ? dir : dir_rand);
+ vec3 color = texture(sssData, sample_uv).rgb;
+ float sample_depth = texture(depthBuffer, sample_uv).r;
+ sample_depth = get_view_z_from_depth(sample_depth);
+
+ /* Depth correction factor. */
+ float depth_delta = depth_view - sample_depth;
+ float s = clamp(1.0 - exp(-(depth_delta * depth_delta) / (2.0 * sss_data.a)), 0.0, 1.0);
+
+ /* Out of view samples. */
+ if (any(lessThan(sample_uv, vec2(0.0))) || any(greaterThan(sample_uv, vec2(1.0)))) {
+ s = 1.0;
+ }
+
+ accum += kernel[i].rgb * mix(color, sss_data.rgb, s);
+ }
+
+#ifdef FIRST_PASS
+ FragColor = vec4(accum, sss_data.a);
+#else /* SECOND_PASS */
+ #ifdef USE_SEP_ALBEDO
+ FragColor = vec4(accum * texture(sssAlbedo, uvs).rgb, 1.0);
+ #else
+ FragColor = vec4(accum, 1.0);
+ #endif
+#endif
+}
diff --git a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
new file mode 100644
index 00000000000..f3df1864317
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
@@ -0,0 +1,14 @@
+
+uniform sampler2D colorBuffer;
+uniform sampler2D historyBuffer;
+uniform float alpha;
+
+out vec4 FragColor;
+
+void main()
+{
+ /* TODO History buffer Reprojection */
+ vec4 history = texelFetch(historyBuffer, ivec2(gl_FragCoord.xy), 0).rgba;
+ vec4 color = texelFetch(colorBuffer, ivec2(gl_FragCoord.xy), 0).rgba;
+ FragColor = mix(history, color, alpha);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
new file mode 100644
index 00000000000..76d20486d3d
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
@@ -0,0 +1,178 @@
+
+uniform sampler2DArray irradianceGrid;
+uniform int irradianceVisibilitySize;
+
+#define IRRADIANCE_LIB
+
+#ifdef IRRADIANCE_CUBEMAP
+struct IrradianceData {
+ vec3 color;
+};
+#elif defined(IRRADIANCE_SH_L2)
+struct IrradianceData {
+ vec3 shcoefs[9];
+};
+#else /* defined(IRRADIANCE_HL2) */
+struct IrradianceData {
+ vec3 cubesides[3];
+};
+#endif
+
+IrradianceData load_irradiance_cell(int cell, vec3 N)
+{
+ /* Keep in sync with diffuse_filter_probe() */
+
+#if defined(IRRADIANCE_CUBEMAP)
+
+ #define AMBIANT_CUBESIZE 8
+ ivec2 cell_co = ivec2(AMBIANT_CUBESIZE);
+ int cell_per_row = textureSize(irradianceGrid, 0).x / cell_co.x;
+ cell_co.x *= cell % cell_per_row;
+ cell_co.y *= cell / cell_per_row;
+
+ vec2 texelSize = 1.0 / vec2(AMBIANT_CUBESIZE);
+
+ vec2 uvs = mapping_octahedron(N, texelSize);
+ uvs *= vec2(AMBIANT_CUBESIZE) / vec2(textureSize(irradianceGrid, 0));
+ uvs += vec2(cell_co) / vec2(textureSize(irradianceGrid, 0));
+
+ IrradianceData ir;
+ ir.color = texture(irradianceGrid, vec3(uvs, 0.0)).rgb;
+
+#elif defined(IRRADIANCE_SH_L2)
+
+ ivec2 cell_co = ivec2(3, 3);
+ int cell_per_row = textureSize(irradianceGrid, 0).x / cell_co.x;
+ cell_co.x *= cell % cell_per_row;
+ cell_co.y *= cell / cell_per_row;
+
+ ivec3 ofs = ivec3(0, 1, 2);
+
+ IrradianceData ir;
+ ir.shcoefs[0] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xx, 0), 0).rgb;
+ ir.shcoefs[1] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yx, 0), 0).rgb;
+ ir.shcoefs[2] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zx, 0), 0).rgb;
+ ir.shcoefs[3] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xy, 0), 0).rgb;
+ ir.shcoefs[4] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yy, 0), 0).rgb;
+ ir.shcoefs[5] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zy, 0), 0).rgb;
+ ir.shcoefs[6] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xz, 0), 0).rgb;
+ ir.shcoefs[7] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yz, 0), 0).rgb;
+ ir.shcoefs[8] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zz, 0), 0).rgb;
+
+#else /* defined(IRRADIANCE_HL2) */
+
+ ivec2 cell_co = ivec2(3, 2);
+ int cell_per_row = textureSize(irradianceGrid, 0).x / cell_co.x;
+ cell_co.x *= cell % cell_per_row;
+ cell_co.y *= cell / cell_per_row;
+
+ ivec3 is_negative = ivec3(step(0.0, -N));
+
+ IrradianceData ir;
+ ir.cubesides[0] = irradiance_decode(texelFetch(irradianceGrid, ivec3(cell_co + ivec2(0, is_negative.x), 0), 0));
+ ir.cubesides[1] = irradiance_decode(texelFetch(irradianceGrid, ivec3(cell_co + ivec2(1, is_negative.y), 0), 0));
+ ir.cubesides[2] = irradiance_decode(texelFetch(irradianceGrid, ivec3(cell_co + ivec2(2, is_negative.z), 0), 0));
+
+#endif
+
+ return ir;
+}
+
+float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed_bias, float range)
+{
+ /* Keep in sync with diffuse_filter_probe() */
+ ivec2 cell_co = ivec2(irradianceVisibilitySize);
+ ivec2 cell_per_row_col = textureSize(irradianceGrid, 0).xy / irradianceVisibilitySize;
+ cell_co.x *= (cell % cell_per_row_col.x);
+ cell_co.y *= (cell / cell_per_row_col.x) % cell_per_row_col.y;
+ float layer = 1.0 + float((cell / cell_per_row_col.x) / cell_per_row_col.y);
+
+ vec2 texel_size = 1.0 / vec2(textureSize(irradianceGrid, 0).xy);
+ vec2 co = vec2(cell_co) * texel_size;
+
+ vec2 uv = mapping_octahedron(-L, vec2(1.0 / float(irradianceVisibilitySize)));
+ uv *= vec2(irradianceVisibilitySize) * texel_size;
+
+ vec4 data = texture(irradianceGrid, vec3(co + uv, layer));
+
+ /* Decoding compressed data */
+ vec2 moments = visibility_decode(data, range);
+
+ /* Doing chebishev test */
+ float variance = abs(moments.x * moments.x - moments.y);
+ variance = max(variance, bias / 10.0);
+
+ float d = dist - moments.x;
+ float p_max = variance / (variance + d * d);
+
+ /* Increase contrast in the weight by squaring it */
+ p_max *= p_max;
+
+ /* Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1] */
+ p_max = clamp((p_max - bleed_bias) / (1.0 - bleed_bias), 0.0, 1.0);
+
+ return (dist <= moments.x) ? 1.0 : p_max;
+}
+
+/* http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ */
+vec3 spherical_harmonics_L1(vec3 N, vec3 shcoefs[4])
+{
+ vec3 sh = vec3(0.0);
+
+ sh += 0.282095 * shcoefs[0];
+
+ sh += -0.488603 * N.z * shcoefs[1];
+ sh += 0.488603 * N.y * shcoefs[2];
+ sh += -0.488603 * N.x * shcoefs[3];
+
+ return sh;
+}
+
+vec3 spherical_harmonics_L2(vec3 N, vec3 shcoefs[9])
+{
+ vec3 sh = vec3(0.0);
+
+ sh += 0.282095 * shcoefs[0];
+
+ sh += -0.488603 * N.z * shcoefs[1];
+ sh += 0.488603 * N.y * shcoefs[2];
+ sh += -0.488603 * N.x * shcoefs[3];
+
+ sh += 1.092548 * N.x * N.z * shcoefs[4];
+ sh += -1.092548 * N.z * N.y * shcoefs[5];
+ sh += 0.315392 * (3.0 * N.y * N.y - 1.0) * shcoefs[6];
+ sh += -1.092548 * N.x * N.y * shcoefs[7];
+ sh += 0.546274 * (N.x * N.x - N.z * N.z) * shcoefs[8];
+
+ return sh;
+}
+
+vec3 hl2_basis(vec3 N, vec3 cubesides[3])
+{
+ vec3 irradiance = vec3(0.0);
+
+ vec3 n_squared = N * N;
+
+ irradiance += n_squared.x * cubesides[0];
+ irradiance += n_squared.y * cubesides[1];
+ irradiance += n_squared.z * cubesides[2];
+
+ return irradiance;
+}
+
+vec3 compute_irradiance(vec3 N, IrradianceData ird)
+{
+#if defined(IRRADIANCE_CUBEMAP)
+ return ird.color;
+#elif defined(IRRADIANCE_SH_L2)
+ return spherical_harmonics_L2(N, ird.shcoefs);
+#else /* defined(IRRADIANCE_HL2) */
+ return hl2_basis(N, ird.cubesides);
+#endif
+}
+
+vec3 irradiance_from_cell_get(int cell, vec3 ir_dir)
+{
+ IrradianceData ir_data = load_irradiance_cell(cell, ir_dir);
+ return compute_irradiance(ir_dir, ir_data);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
new file mode 100644
index 00000000000..933f056c401
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
@@ -0,0 +1,448 @@
+
+uniform sampler2DArray shadowTexture;
+
+#define LAMPS_LIB
+
+layout(std140) uniform shadow_block {
+ ShadowData shadows_data[MAX_SHADOW];
+ ShadowCubeData shadows_cube_data[MAX_SHADOW_CUBE];
+ ShadowCascadeData shadows_cascade_data[MAX_SHADOW_CASCADE];
+};
+
+layout(std140) uniform light_block {
+ LightData lights_data[MAX_LIGHT];
+};
+
+/* type */
+#define POINT 0.0
+#define SUN 1.0
+#define SPOT 2.0
+#define HEMI 3.0
+#define AREA 4.0
+
+/* ----------------------------------------------------------- */
+/* ----------------------- Shadow tests ---------------------- */
+/* ----------------------------------------------------------- */
+
+float shadow_test_esm(float z, float dist, float exponent)
+{
+ return saturate(exp(exponent * (z - dist)));
+}
+
+float shadow_test_pcf(float z, float dist)
+{
+ return step(0, z - dist);
+}
+
+float shadow_test_vsm(vec2 moments, float dist, float bias, float bleed_bias)
+{
+ float p = 0.0;
+
+ if (dist <= moments.x)
+ p = 1.0;
+
+ float variance = moments.y - (moments.x * moments.x);
+ variance = max(variance, bias / 10.0);
+
+ float d = moments.x - dist;
+ float p_max = variance / (variance + d * d);
+
+ /* Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1] */
+ p_max = clamp((p_max - bleed_bias) / (1.0 - bleed_bias), 0.0, 1.0);
+
+ return max(p, p_max);
+}
+
+
+/* ----------------------------------------------------------- */
+/* ----------------------- Shadow types ---------------------- */
+/* ----------------------------------------------------------- */
+
+float shadow_cubemap(ShadowData sd, ShadowCubeData scd, float texid, vec3 W)
+{
+ vec3 cubevec = W - scd.position.xyz;
+ float dist = length(cubevec);
+
+ /* If fragment is out of shadowmap range, do not occlude */
+ /* XXX : we check radial distance against a cubeface distance.
+ * We loose quite a bit of valid area. */
+ if (dist > sd.sh_far)
+ return 1.0;
+
+ cubevec /= dist;
+
+#if defined(SHADOW_VSM)
+ vec2 moments = texture_octahedron(shadowTexture, vec4(cubevec, texid)).rg;
+#else
+ float z = texture_octahedron(shadowTexture, vec4(cubevec, texid)).r;
+#endif
+
+#if defined(SHADOW_VSM)
+ return shadow_test_vsm(moments, dist, sd.sh_bias, sd.sh_bleed);
+#elif defined(SHADOW_ESM)
+ return shadow_test_esm(z, dist - sd.sh_bias, sd.sh_exp);
+#else
+ return shadow_test_pcf(z, dist - sd.sh_bias);
+#endif
+}
+
+float evaluate_cascade(ShadowData sd, mat4 shadowmat, vec3 W, float range, float texid)
+{
+ vec4 shpos = shadowmat * vec4(W, 1.0);
+ float dist = shpos.z * range;
+
+#if defined(SHADOW_VSM)
+ vec2 moments = texture(shadowTexture, vec3(shpos.xy, texid)).rg;
+#else
+ float z = texture(shadowTexture, vec3(shpos.xy, texid)).r;
+#endif
+
+ float vis;
+#if defined(SHADOW_VSM)
+ vis = shadow_test_vsm(moments, dist, sd.sh_bias, sd.sh_bleed);
+#elif defined(SHADOW_ESM)
+ vis = shadow_test_esm(z, dist - sd.sh_bias, sd.sh_exp);
+#else
+ vis = shadow_test_pcf(z, dist - sd.sh_bias);
+#endif
+
+ /* If fragment is out of shadowmap range, do not occlude */
+ if (shpos.z < 1.0 && shpos.z > 0.0) {
+ return vis;
+ }
+ else {
+ return 1.0;
+ }
+}
+
+float shadow_cascade(ShadowData sd, ShadowCascadeData scd, float texid, vec3 W)
+{
+ vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
+ vec4 weights = smoothstep(scd.split_end_distances, scd.split_start_distances.yzwx, view_z);
+ weights.yzw -= weights.xyz;
+
+ vec4 vis = vec4(1.0);
+ float range = abs(sd.sh_far - sd.sh_near); /* Same factor as in get_cascade_world_distance(). */
+
+ /* Branching using (weights > 0.0) is reaally slooow on intel so avoid it for now. */
+ vis.x = evaluate_cascade(sd, scd.shadowmat[0], W, range, texid + 0);
+ vis.y = evaluate_cascade(sd, scd.shadowmat[1], W, range, texid + 1);
+ vis.z = evaluate_cascade(sd, scd.shadowmat[2], W, range, texid + 2);
+ vis.w = evaluate_cascade(sd, scd.shadowmat[3], W, range, texid + 3);
+
+ float weight_sum = dot(vec4(1.0), weights);
+ if (weight_sum > 0.9999) {
+ float vis_sum = dot(vec4(1.0), vis * weights);
+ return vis_sum / weight_sum;
+ }
+ else {
+ float vis_sum = dot(vec4(1.0), vis * step(0.001, weights));
+ return mix(1.0, vis_sum, weight_sum);
+ }
+}
+
+/* ----------------------------------------------------------- */
+/* --------------------- Light Functions --------------------- */
+/* ----------------------------------------------------------- */
+#define MAX_MULTI_SHADOW 4
+
+float light_visibility(LightData ld, vec3 W,
+#ifndef VOLUMETRICS
+ vec3 viewPosition,
+ vec3 viewNormal,
+#endif
+ vec4 l_vector)
+{
+ float vis = 1.0;
+
+ if (ld.l_type == SPOT) {
+ float z = dot(ld.l_forward, l_vector.xyz);
+ vec3 lL = l_vector.xyz / z;
+ float x = dot(ld.l_right, lL) / ld.l_sizex;
+ float y = dot(ld.l_up, lL) / ld.l_sizey;
+
+ float ellipse = 1.0 / sqrt(1.0 + x * x + y * y);
+
+ float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend);
+
+ vis *= spotmask;
+ vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
+ }
+ else if (ld.l_type == AREA) {
+ vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
+ }
+
+#if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW)
+ /* shadowing */
+ if (ld.l_shadowid >= 0.0) {
+ ShadowData data = shadows_data[int(ld.l_shadowid)];
+
+ if (ld.l_type == SUN) {
+ /* TODO : MSM */
+ // for (int i = 0; i < MAX_MULTI_SHADOW; ++i) {
+ vis *= shadow_cascade(
+ data, shadows_cascade_data[int(data.sh_data_start)],
+ data.sh_tex_start, W);
+ // }
+ }
+ else {
+ /* TODO : MSM */
+ // for (int i = 0; i < MAX_MULTI_SHADOW; ++i) {
+ vis *= shadow_cubemap(
+ data, shadows_cube_data[int(data.sh_data_start)],
+ data.sh_tex_start, W);
+ // }
+ }
+
+#ifndef VOLUMETRICS
+ /* Only compute if not already in shadow. */
+ if ((vis > 0.001) && (data.sh_contact_dist > 0.0)) {
+ vec4 L = (ld.l_type != SUN) ? l_vector : vec4(-ld.l_forward, 1.0);
+ float trace_distance = (ld.l_type != SUN) ? min(data.sh_contact_dist, l_vector.w) : data.sh_contact_dist;
+
+ vec3 T, B;
+ make_orthonormal_basis(L.xyz / L.w, T, B);
+
+ vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw;
+ /* XXX This is a hack to not have noise correlation artifacts.
+ * A better solution to have better noise is welcome. */
+ rand.yz *= fast_sqrt(fract(rand.x * 7919.0)) * data.sh_contact_spread;
+
+ /* We use the full l_vector.xyz so that the spread is minimize
+ * if the shading point is further away from the light source */
+ vec3 ray_dir = L.xyz + T * rand.y + B * rand.z;
+ ray_dir = transform_direction(ViewMatrix, ray_dir);
+ ray_dir = normalize(ray_dir);
+ vec3 ray_origin = viewPosition + viewNormal * data.sh_contact_offset;
+ vec3 hit_pos = raycast(-1, ray_origin, ray_dir * trace_distance, data.sh_contact_thickness, rand.x,
+ 0.75, 0.01, false);
+
+ if (hit_pos.z > 0.0) {
+ hit_pos = get_view_space_from_depth(hit_pos.xy, hit_pos.z);
+ float hit_dist = distance(viewPosition, hit_pos);
+ float dist_ratio = hit_dist / trace_distance;
+ return mix(0.0, vis, dist_ratio * dist_ratio * dist_ratio);
+ }
+ }
+#endif
+ }
+#endif
+
+ return vis;
+}
+
+float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector)
+{
+#ifdef USE_LTC
+ if (ld.l_type == SUN) {
+ /* TODO disk area light */
+ return direct_diffuse_sun(ld, N);
+ }
+ else if (ld.l_type == AREA) {
+ return direct_diffuse_rectangle(ld, N, V, l_vector);
+ }
+ else {
+ return direct_diffuse_sphere(ld, N, l_vector);
+ }
+#else
+ if (ld.l_type == SUN) {
+ return direct_diffuse_sun(ld, N);
+ }
+ else {
+ return direct_diffuse_point(N, l_vector);
+ }
+#endif
+}
+
+vec3 light_specular(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0)
+{
+#ifdef USE_LTC
+ if (ld.l_type == SUN) {
+ /* TODO disk area light */
+ return direct_ggx_sun(ld, N, V, roughness, f0);
+ }
+ else if (ld.l_type == AREA) {
+ return direct_ggx_rectangle(ld, N, V, l_vector, roughness, f0);
+ }
+ else {
+ return direct_ggx_sphere(ld, N, V, l_vector, roughness, f0);
+ }
+#else
+ if (ld.l_type == SUN) {
+ return direct_ggx_sun(ld, N, V, roughness, f0);
+ }
+ else {
+ return direct_ggx_point(N, V, l_vector, roughness, f0);
+ }
+#endif
+}
+
+#define MAX_SSS_SAMPLES 65
+#define SSS_LUT_SIZE 64.0
+#define SSS_LUT_SCALE ((SSS_LUT_SIZE - 1.0) / float(SSS_LUT_SIZE))
+#define SSS_LUT_BIAS (0.5 / float(SSS_LUT_SIZE))
+layout(std140) uniform sssProfile {
+ vec4 kernel[MAX_SSS_SAMPLES];
+ vec4 radii_max_radius;
+ int sss_samples;
+};
+
+uniform sampler1D sssTexProfile;
+
+vec3 sss_profile(float s) {
+ s /= radii_max_radius.w;
+ return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb;
+}
+
+vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale)
+{
+#if !defined(USE_TRANSLUCENCY) || defined(VOLUMETRICS)
+ return vec3(0.0);
+#endif
+
+#ifndef VOLUMETRICS
+ vec3 vis = vec3(1.0);
+
+ /* Only shadowed light can produce translucency */
+ if (ld.l_shadowid >= 0.0) {
+ ShadowData data = shadows_data[int(ld.l_shadowid)];
+ float delta;
+
+ vec4 L = (ld.l_type != SUN) ? l_vector : vec4(-ld.l_forward, 1.0);
+
+ vec3 T, B;
+ make_orthonormal_basis(L.xyz / L.w, T, B);
+
+ vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw;
+ /* XXX This is a hack to not have noise correlation artifacts.
+ * A better solution to have better noise is welcome. */
+ rand.yz *= fast_sqrt(fract(rand.x * 7919.0)) * data.sh_blur;
+
+ /* We use the full l_vector.xyz so that the spread is minimize
+ * if the shading point is further away from the light source */
+ W = W + T * rand.y + B * rand.z;
+
+ if (ld.l_type == SUN) {
+ ShadowCascadeData scd = shadows_cascade_data[int(data.sh_data_start)];
+ vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
+
+ vec4 weights = step(scd.split_end_distances, view_z);
+ float id = abs(4.0 - dot(weights, weights));
+
+ if (id > 3.0) {
+ return vec3(0.0);
+ }
+
+ float range = abs(data.sh_far - data.sh_near); /* Same factor as in get_cascade_world_distance(). */
+
+ vec4 shpos = scd.shadowmat[int(id)] * vec4(W, 1.0);
+ float dist = shpos.z * range;
+
+ if (shpos.z > 1.0 || shpos.z < 0.0) {
+ return vec3(0.0);
+ }
+
+#if defined(SHADOW_VSM)
+ vec2 moments = texture(shadowTexture, vec3(shpos.xy, data.sh_tex_start + id)).rg;
+ delta = dist - moments.x;
+#else
+ float z = texture(shadowTexture, vec3(shpos.xy, data.sh_tex_start + id)).r;
+ delta = dist - z;
+#endif
+ }
+ else {
+ vec3 cubevec = W - shadows_cube_data[int(data.sh_data_start)].position.xyz;
+ float dist = length(cubevec);
+
+ /* If fragment is out of shadowmap range, do not occlude */
+ /* XXX : we check radial distance against a cubeface distance.
+ * We loose quite a bit of valid area. */
+ if (dist < data.sh_far) {
+ cubevec /= dist;
+
+#if defined(SHADOW_VSM)
+ vec2 moments = texture_octahedron(shadowTexture, vec4(cubevec, data.sh_tex_start)).rg;
+ delta = dist - moments.x;
+#else
+ float z = texture_octahedron(shadowTexture, vec4(cubevec, data.sh_tex_start)).r;
+ delta = dist - z;
+#endif
+ }
+ }
+
+ /* XXX : Removing Area Power. */
+ /* TODO : put this out of the shader. */
+ float falloff;
+ if (ld.l_type == AREA) {
+ vis *= 0.0962 * (ld.l_sizex * ld.l_sizey * 4.0 * M_PI);
+ vis /= (l_vector.w * l_vector.w);
+ falloff = dot(N, l_vector.xyz / l_vector.w);
+ }
+ else if (ld.l_type == SUN) {
+ falloff = dot(N, -ld.l_forward);
+ }
+ else {
+ vis *= 0.0248 * (4.0 * ld.l_radius * ld.l_radius * M_PI * M_PI);
+ vis /= (l_vector.w * l_vector.w);
+ falloff = dot(N, l_vector.xyz / l_vector.w);
+ }
+ vis *= M_1_PI; /* Normalize */
+
+ /* Applying profile */
+ vis *= sss_profile(abs(delta) / scale);
+
+ /* No transmittance at grazing angle (hide artifacts) */
+ vis *= saturate(falloff * 2.0);
+
+ if (ld.l_type == SPOT) {
+ float z = dot(ld.l_forward, l_vector.xyz);
+ vec3 lL = l_vector.xyz / z;
+ float x = dot(ld.l_right, lL) / ld.l_sizex;
+ float y = dot(ld.l_up, lL) / ld.l_sizey;
+
+ float ellipse = 1.0 / sqrt(1.0 + x * x + y * y);
+
+ float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend);
+
+ vis *= spotmask;
+ vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
+ }
+ else if (ld.l_type == AREA) {
+ vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
+ }
+ }
+ else {
+ vis = vec3(0.0);
+ }
+
+ return vis;
+#endif
+}
+
+#ifdef HAIR_SHADER
+void light_hair_common(
+ LightData ld, vec3 N, vec3 V, vec4 l_vector, vec3 norm_view,
+ out float occlu_trans, out float occlu,
+ out vec3 norm_lamp, out vec3 view_vec)
+{
+ const float transmission = 0.3; /* Uniform internal scattering factor */
+
+ vec3 lamp_vec;
+
+ if (ld.l_type == SUN || ld.l_type == AREA) {
+ lamp_vec = ld.l_forward;
+ }
+ else {
+ lamp_vec = -l_vector.xyz;
+ }
+
+ norm_lamp = cross(lamp_vec, N);
+ norm_lamp = normalize(cross(N, norm_lamp)); /* Normal facing lamp */
+
+ /* Rotate view vector onto the cross(tangent, light) plane */
+ view_vec = normalize(norm_lamp * dot(norm_view, V) + N * dot(N, V));
+
+ occlu = (dot(norm_view, norm_lamp) * 0.5 + 0.5);
+ occlu_trans = transmission + (occlu * (1.0 - transmission)); /* Includes transmission component */
+}
+#endif
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl
new file mode 100644
index 00000000000..fc0b5b9548b
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl
@@ -0,0 +1,15 @@
+
+flat in int pid;
+in vec3 worldNormal;
+in vec3 worldPosition;
+
+out vec4 FragColor;
+
+void main()
+{
+ vec3 V = (ProjectionMatrix[3][3] == 0.0) /* if perspective */
+ ? normalize(cameraPos - worldPosition)
+ : cameraForward;
+ vec3 N = normalize(worldNormal);
+ FragColor = vec4(textureLod_octahedron(probeCubes, vec4(reflect(-V, N), pid), 0.0, lodCubeMax).rgb, 1.0);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl
new file mode 100644
index 00000000000..202b27be0ef
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl
@@ -0,0 +1,28 @@
+
+in vec3 pos;
+
+/* Instance attrib */
+in int probe_id;
+in vec3 probe_location;
+in float sphere_size;
+
+uniform mat4 ViewProjectionMatrix;
+
+flat out int pid;
+out vec3 worldNormal;
+out vec3 worldPosition;
+
+void main()
+{
+ pid = probe_id;
+
+ /* While this is not performant, we do this to
+ * match the object mode engine instancing shader. */
+ mat4 offsetmat = mat4(1.0); /* Identity */
+ offsetmat[3].xyz = probe_location;
+
+ vec4 wpos = offsetmat * vec4(pos * sphere_size, 1.0);
+ worldPosition = wpos.xyz;
+ gl_Position = ViewProjectionMatrix * wpos;
+ worldNormal = normalize(pos);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl
new file mode 100644
index 00000000000..eb4315c93a3
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl
@@ -0,0 +1,197 @@
+
+uniform samplerCube probeHdr;
+uniform int probeSize;
+uniform float lodFactor;
+uniform float lodMax;
+
+in vec3 worldPosition;
+
+out vec4 FragColor;
+
+#define M_4PI 12.5663706143591729
+
+const mat3 CUBE_ROTATIONS[6] = mat3[](
+ mat3(vec3( 0.0, 0.0, -1.0),
+ vec3( 0.0, -1.0, 0.0),
+ vec3(-1.0, 0.0, 0.0)),
+ mat3(vec3( 0.0, 0.0, 1.0),
+ vec3( 0.0, -1.0, 0.0),
+ vec3( 1.0, 0.0, 0.0)),
+ mat3(vec3( 1.0, 0.0, 0.0),
+ vec3( 0.0, 0.0, 1.0),
+ vec3( 0.0, -1.0, 0.0)),
+ mat3(vec3( 1.0, 0.0, 0.0),
+ vec3( 0.0, 0.0, -1.0),
+ vec3( 0.0, 1.0, 0.0)),
+ mat3(vec3( 1.0, 0.0, 0.0),
+ vec3( 0.0, -1.0, 0.0),
+ vec3( 0.0, 0.0, -1.0)),
+ mat3(vec3(-1.0, 0.0, 0.0),
+ vec3( 0.0, -1.0, 0.0),
+ vec3( 0.0, 0.0, 1.0)));
+
+vec3 get_cubemap_vector(vec2 co, int face)
+{
+ return normalize(CUBE_ROTATIONS[face] * vec3(co * 2.0 - 1.0, 1.0));
+}
+
+float area_element(float x, float y)
+{
+ return atan(x * y, sqrt(x * x + y * y + 1));
+}
+
+float texel_solid_angle(vec2 co, float halfpix)
+{
+ vec2 v1 = (co - vec2(halfpix)) * 2.0 - 1.0;
+ vec2 v2 = (co + vec2(halfpix)) * 2.0 - 1.0;
+
+ return area_element(v1.x, v1.y) - area_element(v1.x, v2.y) - area_element(v2.x, v1.y) + area_element(v2.x, v2.y);
+}
+
+vec3 octahedral_to_cubemap_proj(vec2 co)
+{
+ co = co * 2.0 - 1.0;
+
+ vec2 abs_co = abs(co);
+ vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y));
+
+ if ( abs_co.x + abs_co.y > 1.0 ) {
+ v.xy = (abs(co.yx) - 1.0) * -sign(co.xy);
+ }
+
+ return v;
+}
+
+void main()
+{
+#if defined(IRRADIANCE_SH_L2)
+ float pixstep = 1.0 / probeSize;
+ float halfpix = pixstep / 2.0;
+
+ /* Downside: leaks negative values, very bandwidth consuming */
+ int comp = int(gl_FragCoord.x) % 3 + (int(gl_FragCoord.y) % 3) * 3;
+
+ float weight_accum = 0.0;
+ vec3 sh = vec3(0.0);
+
+ for (int face = 0; face < 6; ++face) {
+ for (float x = halfpix; x < 1.0; x += pixstep) {
+ for (float y = halfpix; y < 1.0; y += pixstep) {
+ float weight, coef;
+ vec2 facecoord = vec2(x,y);
+ vec3 cubevec = get_cubemap_vector(facecoord, face);
+
+ if (comp == 0) {
+ coef = 0.282095;
+ }
+ else if (comp == 1) {
+ coef = -0.488603 * cubevec.z * 2.0 / 3.0;
+ }
+ else if (comp == 2) {
+ coef = 0.488603 * cubevec.y * 2.0 / 3.0;
+ }
+ else if (comp == 3) {
+ coef = -0.488603 * cubevec.x * 2.0 / 3.0;
+ }
+ else if (comp == 4) {
+ coef = 1.092548 * cubevec.x * cubevec.z * 1.0 / 4.0;
+ }
+ else if (comp == 5) {
+ coef = -1.092548 * cubevec.z * cubevec.y * 1.0 / 4.0;
+ }
+ else if (comp == 6) {
+ coef = 0.315392 * (3.0 * cubevec.y * cubevec.y - 1.0) * 1.0 / 4.0;
+ }
+ else if (comp == 7) {
+ coef = 1.092548 * cubevec.x * cubevec.y * 1.0 / 4.0;
+ }
+ else { /* (comp == 8) */
+ coef = 0.546274 * (cubevec.x * cubevec.x - cubevec.z * cubevec.z) * 1.0 / 4.0;
+ }
+
+ weight = texel_solid_angle(facecoord, halfpix);
+
+ vec4 sample = textureLod(probeHdr, cubevec, lodMax);
+ sh += sample.rgb * coef * weight;
+ weight_accum += weight;
+ }
+ }
+ }
+ sh *= M_4PI / weight_accum;
+
+ FragColor = vec4(sh, 1.0);
+#else
+#if defined(IRRADIANCE_CUBEMAP)
+ /* Downside: Need lots of memory for storage, distortion due to octahedral mapping */
+ const vec2 map_size = vec2(16.0);
+ const vec2 texelSize = 1.0 / map_size;
+ vec2 uvs = mod(gl_FragCoord.xy, map_size) * texelSize;
+ const float paddingSize = 1.0;
+
+ /* Add a N pixel border to ensure filtering is correct
+ * for N mipmap levels. */
+ uvs += uvs * texelSize * paddingSize * 2.0;
+ uvs -= texelSize * paddingSize;
+
+ /* edge mirroring : only mirror if directly adjacent
+ * (not diagonally adjacent) */
+ vec2 m = abs(uvs - 0.5) + 0.5;
+ vec2 f = floor(m);
+ if (f.x - f.y != 0.0) {
+ uvs = 1.0 - uvs;
+ }
+
+ /* clamp to [0-1] */
+ uvs = fract(uvs);
+
+ /* get cubemap vector */
+ vec3 cubevec = octahedral_to_cubemap_proj(uvs);
+
+#elif defined(IRRADIANCE_HL2)
+ /* Downside: very very low resolution (6 texels), bleed lighting because of interpolation */
+ int x = int(gl_FragCoord.x) % 3;
+ int y = int(gl_FragCoord.y) % 2;
+
+ vec3 cubevec = vec3(1.0, 0.0, 0.0);
+
+ if (x == 1) {
+ cubevec = cubevec.yxy;
+ }
+ else if (x == 2) {
+ cubevec = cubevec.yyx;
+ }
+
+ if (y == 1) {
+ cubevec = -cubevec;
+ }
+#endif
+
+ vec3 N, T, B, V;
+
+ N = normalize(cubevec);
+
+ make_orthonormal_basis(N, T, B); /* Generate tangent space */
+
+ /* Integrating Envmap */
+ float weight = 0.0;
+ vec3 out_radiance = vec3(0.0);
+ for (float i = 0; i < sampleCount; i++) {
+ vec3 L = sample_hemisphere(i, N, T, B); /* Microfacet normal */
+ float NL = dot(N, L);
+
+ if (NL > 0.0) {
+ /* Coarse Approximation of the mapping distortion
+ * Unit Sphere -> Cubemap Face */
+ const float dist = 4.0 * M_PI / 6.0;
+ float pdf = pdf_hemisphere();
+ /* http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html : Equation 13 */
+ float lod = clamp(lodFactor - 0.5 * log2(pdf * dist), 0.0, lodMax) ;
+
+ out_radiance += textureLod(probeHdr, L, lod).rgb * NL;
+ weight += NL;
+ }
+ }
+
+ FragColor = irradiance_encode(out_radiance / weight);
+#endif
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl
new file mode 100644
index 00000000000..33714c5293c
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl
@@ -0,0 +1,86 @@
+
+uniform samplerCube probeHdr;
+uniform float roughnessSquared;
+uniform float texelSize;
+uniform float lodFactor;
+uniform float lodMax;
+uniform float paddingSize;
+
+in vec3 worldPosition;
+
+out vec4 FragColor;
+
+vec3 octahedral_to_cubemap_proj(vec2 co)
+{
+ co = co * 2.0 - 1.0;
+
+ vec2 abs_co = abs(co);
+ vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y));
+
+ if ( abs_co.x + abs_co.y > 1.0 ) {
+ v.xy = (abs(co.yx) - 1.0) * -sign(co.xy);
+ }
+
+ return v;
+}
+
+void main() {
+ vec2 uvs = gl_FragCoord.xy * texelSize;
+
+ /* Add a N pixel border to ensure filtering is correct
+ * for N mipmap levels. */
+ uvs += uvs * texelSize * paddingSize * 2.0;
+ uvs -= texelSize * paddingSize;
+
+ /* edge mirroring : only mirror if directly adjacent
+ * (not diagonally adjacent) */
+ vec2 m = abs(uvs - 0.5) + 0.5;
+ vec2 f = floor(m);
+ if (f.x - f.y != 0.0) {
+ uvs = 1.0 - uvs;
+ }
+
+ /* clamp to [0-1] */
+ uvs = fract(uvs);
+
+ /* get cubemap vector */
+ vec3 cubevec = octahedral_to_cubemap_proj(uvs);
+
+ vec3 N, T, B, V;
+
+ vec3 R = normalize(cubevec);
+
+ /* Isotropic assumption */
+ N = V = R;
+
+ make_orthonormal_basis(N, T, B); /* Generate tangent space */
+
+ /* Noise to dither the samples */
+ /* Note : ghosting is better looking than noise. */
+ // setup_noise();
+
+ /* Integrating Envmap */
+ float weight = 0.0;
+ vec3 out_radiance = vec3(0.0);
+ for (float i = 0; i < sampleCount; i++) {
+ vec3 H = sample_ggx(i, roughnessSquared, N, T, B); /* Microfacet normal */
+ vec3 L = -reflect(V, H);
+ float NL = dot(N, L);
+
+ if (NL > 0.0) {
+ float NH = max(1e-8, dot(N, H)); /* cosTheta */
+
+ /* Coarse Approximation of the mapping distortion
+ * Unit Sphere -> Cubemap Face */
+ const float dist = 4.0 * M_PI / 6.0;
+ float pdf = pdf_ggx_reflect(NH, roughnessSquared);
+ /* http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html : Equation 13 */
+ float lod = clamp(lodFactor - 0.5 * log2(pdf * dist), 0.0, lodMax) ;
+
+ out_radiance += textureLod(probeHdr, L, lod).rgb * NL;
+ weight += NL;
+ }
+ }
+
+ FragColor = vec4(out_radiance / weight, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl
new file mode 100644
index 00000000000..0727e73f507
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl
@@ -0,0 +1,88 @@
+
+uniform samplerCube probeDepth;
+uniform int outputSize;
+uniform float lodFactor;
+uniform float storedTexelSize;
+uniform float lodMax;
+uniform float nearClip;
+uniform float farClip;
+uniform float visibilityRange;
+uniform float visibilityBlur;
+
+out vec4 FragColor;
+
+vec3 octahedral_to_cubemap_proj(vec2 co)
+{
+ co = co * 2.0 - 1.0;
+
+ vec2 abs_co = abs(co);
+ vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y));
+
+ if ( abs_co.x + abs_co.y > 1.0 ) {
+ v.xy = (abs(co.yx) - 1.0) * -sign(co.xy);
+ }
+
+ return v;
+}
+
+float linear_depth(float z)
+{
+ return (nearClip * farClip) / (z * (nearClip - farClip) + farClip);
+}
+
+float get_world_distance(float depth, vec3 cos)
+{
+ float is_background = step(1.0, depth);
+ depth = linear_depth(depth);
+ depth += 1e1 * is_background;
+ cos = normalize(abs(cos));
+ float cos_vec = max(cos.x, max(cos.y, cos.z));
+ return depth / cos_vec;
+}
+
+void main()
+{
+ ivec2 texel = ivec2(gl_FragCoord.xy) % ivec2(outputSize);
+
+ vec3 cos;
+
+ cos.xy = (vec2(texel) + 0.5) * storedTexelSize;
+
+ /* add a 2 pixel border to ensure filtering is correct */
+ cos.xy *= 1.0 + storedTexelSize * 2.0;
+ cos.xy -= storedTexelSize;
+
+ float pattern = 1.0;
+
+ /* edge mirroring : only mirror if directly adjacent
+ * (not diagonally adjacent) */
+ vec2 m = abs(cos.xy - 0.5) + 0.5;
+ vec2 f = floor(m);
+ if (f.x - f.y != 0.0) {
+ cos.xy = 1.0 - cos.xy;
+ }
+
+ /* clamp to [0-1] */
+ cos.xy = fract(cos.xy);
+
+ /* get cubemap vector */
+ cos = normalize(octahedral_to_cubemap_proj(cos.xy));
+
+ vec3 T, B;
+ make_orthonormal_basis(cos, T, B); /* Generate tangent space */
+
+ vec2 accum = vec2(0.0);
+
+ for (float i = 0; i < sampleCount; i++) {
+ vec3 sample = sample_cone(i, M_PI_2 * visibilityBlur, cos, T, B);
+ float depth = texture(probeDepth, sample).r;
+ depth = get_world_distance(depth, sample);
+ accum += vec2(depth, depth * depth);
+ }
+
+ accum *= invSampleCount;
+ accum = abs(accum);
+
+ /* Encode to normalized RGBA 8 */
+ FragColor = visibility_encode(accum, visibilityRange);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl
new file mode 100644
index 00000000000..7e63f4cdaf7
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl
@@ -0,0 +1,34 @@
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices=3) out;
+
+uniform int Layer;
+
+in vec4 vPos[];
+flat in int face[];
+flat out int fFace;
+
+out vec3 worldPosition;
+out vec3 viewPosition; /* Required. otherwise generate linking error. */
+out vec3 worldNormal; /* Required. otherwise generate linking error. */
+out vec3 viewNormal; /* Required. otherwise generate linking error. */
+
+const vec3 maj_axes[6] = vec3[6](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3( 0.0, 0.0, 1.0), vec3( 0.0, 0.0, -1.0));
+const vec3 x_axis[6] = vec3[6](vec3(0.0, 0.0, -1.0), vec3( 0.0, 0.0, 1.0), vec3(1.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), vec3( 1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0));
+const vec3 y_axis[6] = vec3[6](vec3(0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0), vec3( 0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0));
+
+void main() {
+ fFace = face[0];
+ gl_Layer = Layer + fFace;
+
+ for (int v = 0; v < 3; ++v) {
+ gl_Position = vPos[v];
+ worldPosition = x_axis[fFace] * vPos[v].x + y_axis[fFace] * vPos[v].y + maj_axes[fFace];
+#ifdef ATTRIB
+ pass_attrib(v);
+#endif
+ EmitVertex();
+ }
+
+ EndPrimitive();
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl
new file mode 100644
index 00000000000..d333ad34bb0
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl
@@ -0,0 +1,11 @@
+
+flat in int cellOffset;
+in vec3 worldNormal;
+
+out vec4 FragColor;
+
+void main()
+{
+ IrradianceData ir_data = load_irradiance_cell(cellOffset, worldNormal);
+ FragColor = vec4(compute_irradiance(worldNormal, ir_data), 1.0);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl
new file mode 100644
index 00000000000..fd200ec5984
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl
@@ -0,0 +1,34 @@
+
+in vec3 pos;
+
+uniform mat4 ViewProjectionMatrix;
+
+uniform float sphere_size;
+uniform int offset;
+uniform ivec3 grid_resolution;
+uniform vec3 corner;
+uniform vec3 increment_x;
+uniform vec3 increment_y;
+uniform vec3 increment_z;
+
+flat out int cellOffset;
+out vec3 worldNormal;
+
+void main()
+{
+ vec3 ls_cell_location;
+ /* Keep in sync with update_irradiance_probe */
+ ls_cell_location.z = float(gl_InstanceID % grid_resolution.z);
+ ls_cell_location.y = float((gl_InstanceID / grid_resolution.z) % grid_resolution.y);
+ ls_cell_location.x = float(gl_InstanceID / (grid_resolution.z * grid_resolution.y));
+
+ cellOffset = offset + gl_InstanceID;
+
+ vec3 ws_cell_location = corner +
+ (increment_x * ls_cell_location.x +
+ increment_y * ls_cell_location.y +
+ increment_z * ls_cell_location.z);
+
+ gl_Position = ViewProjectionMatrix * vec4(pos * 0.02 * sphere_size + ws_cell_location, 1.0);
+ worldNormal = normalize(pos);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl
new file mode 100644
index 00000000000..c9e66ceffb2
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl
@@ -0,0 +1,20 @@
+uniform sampler2DArray irradianceGrid;
+
+out vec4 FragColor;
+
+void main()
+{
+#if defined(IRRADIANCE_SH_L2)
+ const ivec2 data_size = ivec2(3, 3);
+#elif defined(IRRADIANCE_CUBEMAP)
+ const ivec2 data_size = ivec2(8, 8);
+#elif defined(IRRADIANCE_HL2)
+ const ivec2 data_size = ivec2(3, 2);
+#endif
+ ivec2 coord = ivec2(gl_FragCoord.xy) % data_size;
+ FragColor = texelFetch(irradianceGrid, ivec3(coord, 0), 0);
+
+ if (any(greaterThanEqual(ivec2(gl_FragCoord.xy), data_size))) {
+ FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
new file mode 100644
index 00000000000..e914228aded
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
@@ -0,0 +1,262 @@
+/* ----------- Uniforms --------- */
+
+uniform sampler2DArray probePlanars;
+uniform float lodPlanarMax;
+
+uniform sampler2DArray probeCubes;
+uniform float lodCubeMax;
+
+/* ----------- Structures --------- */
+
+struct CubeData {
+ vec4 position_type;
+ vec4 attenuation_fac_type;
+ mat4 influencemat;
+ mat4 parallaxmat;
+};
+
+#define PROBE_PARALLAX_BOX 1.0
+#define PROBE_ATTENUATION_BOX 1.0
+
+#define p_position position_type.xyz
+#define p_parallax_type position_type.w
+#define p_atten_fac attenuation_fac_type.x
+#define p_atten_type attenuation_fac_type.y
+
+struct PlanarData {
+ vec4 plane_equation;
+ vec4 clip_vec_x_fade_scale;
+ vec4 clip_vec_y_fade_bias;
+ vec4 clip_edges;
+ vec4 facing_scale_bias;
+ mat4 reflectionmat; /* transform world space into reflection texture space */
+};
+
+#define pl_plane_eq plane_equation
+#define pl_normal plane_equation.xyz
+#define pl_facing_scale facing_scale_bias.x
+#define pl_facing_bias facing_scale_bias.y
+#define pl_fade_scale clip_vec_x_fade_scale.w
+#define pl_fade_bias clip_vec_y_fade_bias.w
+#define pl_clip_pos_x clip_vec_x_fade_scale.xyz
+#define pl_clip_pos_y clip_vec_y_fade_bias.xyz
+#define pl_clip_edges clip_edges
+
+struct GridData {
+ mat4 localmat;
+ ivec4 resolution_offset;
+ vec4 ws_corner_atten_scale; /* world space corner position */
+ vec4 ws_increment_x_atten_bias; /* world space vector between 2 opposite cells */
+ vec4 ws_increment_y_lvl_bias;
+ vec4 ws_increment_z;
+ vec4 vis_bias_bleed_range;
+};
+
+#define g_corner ws_corner_atten_scale.xyz
+#define g_atten_scale ws_corner_atten_scale.w
+#define g_atten_bias ws_increment_x_atten_bias.w
+#define g_level_bias ws_increment_y_lvl_bias.w
+#define g_increment_x ws_increment_x_atten_bias.xyz
+#define g_increment_y ws_increment_y_lvl_bias.xyz
+#define g_increment_z ws_increment_z.xyz
+#define g_resolution resolution_offset.xyz
+#define g_offset resolution_offset.w
+#define g_vis_bias vis_bias_bleed_range.x
+#define g_vis_bleed vis_bias_bleed_range.y
+#define g_vis_range vis_bias_bleed_range.z
+
+#ifndef MAX_PROBE
+#define MAX_PROBE 1
+#endif
+#ifndef MAX_GRID
+#define MAX_GRID 1
+#endif
+#ifndef MAX_PLANAR
+#define MAX_PLANAR 1
+#endif
+
+layout(std140) uniform probe_block {
+ CubeData probes_data[MAX_PROBE];
+};
+
+layout(std140) uniform grid_block {
+ GridData grids_data[MAX_GRID];
+};
+
+layout(std140) uniform planar_block {
+ PlanarData planars_data[MAX_PLANAR];
+};
+
+/* ----------- Functions --------- */
+
+float probe_attenuation_cube(CubeData pd, vec3 W)
+{
+ vec3 localpos = transform_point(pd.influencemat, W);
+
+ float fac;
+ if (pd.p_atten_type == PROBE_ATTENUATION_BOX) {
+ vec3 axes_fac = saturate(pd.p_atten_fac - pd.p_atten_fac * abs(localpos));
+ fac = min_v3(axes_fac);
+ }
+ else {
+ fac = saturate(pd.p_atten_fac - pd.p_atten_fac * length(localpos));
+ }
+
+ return fac;
+}
+
+float probe_attenuation_planar(PlanarData pd, vec3 W, vec3 N, float roughness)
+{
+ /* Normal Facing */
+ float fac = saturate(dot(pd.pl_normal, N) * pd.pl_facing_scale + pd.pl_facing_bias);
+
+ /* Distance from plane */
+ fac *= saturate(abs(dot(pd.pl_plane_eq, vec4(W, 1.0))) * pd.pl_fade_scale + pd.pl_fade_bias);
+
+ /* Fancy fast clipping calculation */
+ vec2 dist_to_clip;
+ dist_to_clip.x = dot(pd.pl_clip_pos_x, W);
+ dist_to_clip.y = dot(pd.pl_clip_pos_y, W);
+ fac *= step(2.0, dot(step(pd.pl_clip_edges, dist_to_clip.xxyy), vec2(-1.0, 1.0).xyxy)); /* compare and add all tests */
+
+ /* Decrease influence for high roughness */
+ fac *= saturate(1.0 - roughness * 10.0);
+
+ return fac;
+}
+
+float probe_attenuation_grid(GridData gd, vec3 W, out vec3 localpos)
+{
+ localpos = transform_point(gd.localmat, W);
+
+ float fade = min(1.0, min_v3(1.0 - abs(localpos)));
+ return saturate(fade * gd.g_atten_scale + gd.g_atten_bias);
+}
+
+vec3 probe_evaluate_cube(float id, CubeData cd, vec3 W, vec3 R, float roughness)
+{
+ /* Correct reflection ray using parallax volume intersection. */
+ vec3 localpos = transform_point(cd.parallaxmat, W);
+ vec3 localray = transform_direction(cd.parallaxmat, R);
+
+ float dist;
+ if (cd.p_parallax_type == PROBE_PARALLAX_BOX) {
+ dist = line_unit_box_intersect_dist(localpos, localray);
+ }
+ else {
+ dist = line_unit_sphere_intersect_dist(localpos, localray);
+ }
+
+ /* Use Distance in WS directly to recover intersection */
+ vec3 intersection = W + R * dist - cd.p_position;
+
+ /* From Frostbite PBR Course
+ * Distance based roughness
+ * http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */
+ float original_roughness = roughness;
+ float linear_roughness = sqrt(roughness);
+ float distance_roughness = saturate(dist * linear_roughness / length(intersection));
+ linear_roughness = mix(distance_roughness, linear_roughness, linear_roughness);
+ roughness = linear_roughness * linear_roughness;
+
+ float fac = saturate(original_roughness * 2.0 - 1.0);
+ R = mix(intersection, R, fac * fac);
+
+ return textureLod_octahedron(probeCubes, vec4(R, id), roughness * lodCubeMax, lodCubeMax).rgb;
+}
+
+vec3 probe_evaluate_world_spec(vec3 R, float roughness)
+{
+ return textureLod_octahedron(probeCubes, vec4(R, 0.0), roughness * lodCubeMax, lodCubeMax).rgb;
+}
+
+vec3 probe_evaluate_planar(
+ float id, PlanarData pd, vec3 W, vec3 N, vec3 V,
+ float roughness, inout float fade)
+{
+ /* Find view vector / reflection plane intersection. */
+ vec3 point_on_plane = line_plane_intersect(W, V, pd.pl_plane_eq);
+
+ /* How far the pixel is from the plane. */
+ float ref_depth = 1.0; /* TODO parameter */
+
+ /* Compute distorded reflection vector based on the distance to the reflected object.
+ * In other words find intersection between reflection vector and the sphere center
+ * around point_on_plane. */
+ vec3 proj_ref = reflect(reflect(-V, N) * ref_depth, pd.pl_normal);
+
+ /* Final point in world space. */
+ vec3 ref_pos = point_on_plane + proj_ref;
+
+ /* Reproject to find texture coords. */
+ vec4 refco = ViewProjectionMatrix * vec4(ref_pos, 1.0);
+ refco.xy /= refco.w;
+
+ /* TODO: If we support non-ssr planar reflection, we should blur them with gaussian
+ * and chose the right mip depending on the cone footprint after projection */
+ vec3 sample = textureLod(probePlanars, vec3(refco.xy * 0.5 + 0.5, id), 0.0).rgb;
+
+ return sample;
+}
+
+#ifdef IRRADIANCE_LIB
+vec3 probe_evaluate_grid(GridData gd, vec3 W, vec3 N, vec3 localpos)
+{
+ localpos = localpos * 0.5 + 0.5;
+ localpos = localpos * vec3(gd.g_resolution) - 0.5;
+
+ vec3 localpos_floored = floor(localpos);
+ vec3 trilinear_weight = fract(localpos);
+
+ float weight_accum = 0.0;
+ vec3 irradiance_accum = vec3(0.0);
+
+ /* For each neighboor cells */
+ for (int i = 0; i < 8; ++i) {
+ ivec3 offset = ivec3(i, i >> 1, i >> 2) & ivec3(1);
+ vec3 cell_cos = clamp(localpos_floored + vec3(offset), vec3(0.0), vec3(gd.g_resolution) - 1.0);
+
+ /* Keep in sync with update_irradiance_probe */
+ ivec3 icell_cos = ivec3(gd.g_level_bias * floor(cell_cos / gd.g_level_bias));
+ int cell = gd.g_offset + icell_cos.z
+ + icell_cos.y * gd.g_resolution.z
+ + icell_cos.x * gd.g_resolution.z * gd.g_resolution.y;
+
+ vec3 color = irradiance_from_cell_get(cell, N);
+
+ /* We need this because we render probes in world space (so we need light vector in WS).
+ * And rendering them in local probe space is too much problem. */
+ vec3 ws_cell_location = gd.g_corner +
+ (gd.g_increment_x * cell_cos.x +
+ gd.g_increment_y * cell_cos.y +
+ gd.g_increment_z * cell_cos.z);
+
+ vec3 ws_point_to_cell = ws_cell_location - W;
+ float ws_dist_point_to_cell = length(ws_point_to_cell);
+ vec3 ws_light = ws_point_to_cell / ws_dist_point_to_cell;
+
+ vec3 trilinear = mix(1 - trilinear_weight, trilinear_weight, offset);
+ float weight = trilinear.x * trilinear.y * trilinear.z;
+
+ /* Precomputed visibility */
+ weight *= load_visibility_cell(cell, ws_light, ws_dist_point_to_cell, gd.g_vis_bias, gd.g_vis_bleed, gd.g_vis_range);
+
+ /* Smooth backface test */
+ weight *= sqrt(max(0.002, dot(ws_light, N)));
+
+ /* Avoid zero weight */
+ weight = max(0.00001, weight);
+
+ weight_accum += weight;
+ irradiance_accum += color * weight;
+ }
+
+ return irradiance_accum / weight_accum;
+}
+
+vec3 probe_evaluate_world_diff(vec3 N)
+{
+ return irradiance_from_cell_get(0, N);
+}
+
+#endif /* IRRADIANCE_LIB */
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl
new file mode 100644
index 00000000000..655cc626bba
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl
@@ -0,0 +1,15 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform sampler2DArray probePlanars;
+
+in vec3 worldPosition;
+flat in int probeIdx;
+
+out vec4 FragColor;
+
+void main()
+{
+ vec4 refco = ViewProjectionMatrix * vec4(worldPosition, 1.0);
+ refco.xy /= refco.w;
+ FragColor = vec4(textureLod(probePlanars, vec3(refco.xy * 0.5 + 0.5, float(probeIdx)), 0.0).rgb, 1.0);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl
new file mode 100644
index 00000000000..a9716332eb5
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl
@@ -0,0 +1,17 @@
+
+in vec3 pos;
+
+in int probe_id;
+in mat4 probe_mat;
+
+uniform mat4 ViewProjectionMatrix;
+
+out vec3 worldPosition;
+flat out int probeIdx;
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * probe_mat * vec4(pos, 1.0);
+ worldPosition = (probe_mat * vec4(pos, 1.0)).xyz;
+ probeIdx = probe_id;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl
new file mode 100644
index 00000000000..3b3abdef00c
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl
@@ -0,0 +1,40 @@
+/**
+ * Simple downsample shader. Takes the average of the 4 texels of lower mip.
+ **/
+
+uniform sampler2DArray source;
+uniform float fireflyFactor;
+
+in vec2 uvs;
+flat in float layer;
+
+out vec4 FragColor;
+
+float brightness(vec3 c)
+{
+ return max(max(c.r, c.g), c.b);
+}
+
+void main()
+{
+#if 0
+ /* Reconstructing Target uvs like this avoid missing pixels if NPO2 */
+ vec2 uvs = gl_FragCoord.xy * 2.0 / vec2(textureSize(source, 0));
+
+ FragColor = textureLod(source, vec3(uvs, layer), 0.0);
+#else
+ vec2 texel_size = 1.0 / vec2(textureSize(source, 0));
+ vec2 uvs = gl_FragCoord.xy * 2.0 * texel_size;
+ vec4 ofs = texel_size.xyxy * vec4(0.75, 0.75, -0.75, -0.75);
+
+ FragColor = textureLod(source, vec3(uvs + ofs.xy, layer), 0.0);
+ FragColor += textureLod(source, vec3(uvs + ofs.xw, layer), 0.0);
+ FragColor += textureLod(source, vec3(uvs + ofs.zy, layer), 0.0);
+ FragColor += textureLod(source, vec3(uvs + ofs.zw, layer), 0.0);
+ FragColor *= 0.25;
+
+ /* Clamped brightness. */
+ float luma = max(1e-8, brightness(FragColor.rgb));
+ FragColor *= 1.0 - max(0.0, luma - fireflyFactor) / luma;
+#endif
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl
new file mode 100644
index 00000000000..40b04c986f3
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl
@@ -0,0 +1,24 @@
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices=3) out;
+
+in int instance[];
+in vec2 vPos[];
+
+flat out float layer;
+
+void main() {
+ gl_Layer = instance[0];
+ layer = float(instance[0]);
+
+ gl_Position = vec4(vPos[0], 0.0, 0.0);
+ EmitVertex();
+
+ gl_Position = vec4(vPos[1], 0.0, 0.0);
+ EmitVertex();
+
+ gl_Position = vec4(vPos[2], 0.0, 0.0);
+ EmitVertex();
+
+ EndPrimitive();
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl
new file mode 100644
index 00000000000..ac4e3da4158
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl
@@ -0,0 +1,10 @@
+
+in vec2 pos;
+
+out int instance;
+out vec2 vPos;
+
+void main() {
+ instance = gl_InstanceID;
+ vPos = pos;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_vert.glsl
new file mode 100644
index 00000000000..f5077d52845
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_vert.glsl
@@ -0,0 +1,10 @@
+
+in vec3 pos;
+
+out vec4 vPos;
+flat out int face;
+
+void main() {
+ vPos = vec4(pos, 1.0);
+ face = gl_InstanceID;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
new file mode 100644
index 00000000000..6ecaf0a627b
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -0,0 +1,500 @@
+
+#ifndef LIT_SURFACE_UNIFORM
+#define LIT_SURFACE_UNIFORM
+
+uniform int light_count;
+uniform int probe_count;
+uniform int grid_count;
+uniform int planar_count;
+
+uniform bool specToggle;
+uniform bool ssrToggle;
+
+uniform float refractionDepth;
+
+#ifndef UTIL_TEX
+#define UTIL_TEX
+uniform sampler2DArray utilTex;
+#endif /* UTIL_TEX */
+
+in vec3 worldPosition;
+in vec3 viewPosition;
+
+#ifdef USE_FLAT_NORMAL
+flat in vec3 worldNormal;
+flat in vec3 viewNormal;
+#else
+in vec3 worldNormal;
+in vec3 viewNormal;
+#endif
+
+uniform float maxRoughness;
+uniform int rayCount;
+
+#endif /* LIT_SURFACE_UNIFORM */
+
+/** AUTO CONFIG
+ * We include the file multiple times each time with a different configuration.
+ * This leads to a lot of deadcode. Better idea would be to only generate the one needed.
+ */
+#if !defined(SURFACE_DEFAULT)
+ #define SURFACE_DEFAULT
+ #define CLOSURE_NAME eevee_closure_default
+ #define CLOSURE_DIFFUSE
+ #define CLOSURE_GLOSSY
+#endif /* SURFACE_DEFAULT */
+
+#if !defined(SURFACE_PRINCIPLED) && !defined(CLOSURE_NAME)
+ #define SURFACE_PRINCIPLED
+ #define CLOSURE_NAME eevee_closure_principled
+ #define CLOSURE_DIFFUSE
+ #define CLOSURE_GLOSSY
+ #define CLOSURE_CLEARCOAT
+ #define CLOSURE_REFRACTION
+ #define CLOSURE_SUBSURFACE
+#endif /* SURFACE_PRINCIPLED */
+
+#if !defined(SURFACE_DIFFUSE) && !defined(CLOSURE_NAME)
+ #define SURFACE_DIFFUSE
+ #define CLOSURE_NAME eevee_closure_diffuse
+ #define CLOSURE_DIFFUSE
+#endif /* SURFACE_DIFFUSE */
+
+#if !defined(SURFACE_SUBSURFACE) && !defined(CLOSURE_NAME)
+ #define SURFACE_SUBSURFACE
+ #define CLOSURE_NAME eevee_closure_subsurface
+ #define CLOSURE_DIFFUSE
+ #define CLOSURE_SUBSURFACE
+#endif /* SURFACE_SUBSURFACE */
+
+#if !defined(SURFACE_GLOSSY) && !defined(CLOSURE_NAME)
+ #define SURFACE_GLOSSY
+ #define CLOSURE_NAME eevee_closure_glossy
+ #define CLOSURE_GLOSSY
+#endif /* SURFACE_GLOSSY */
+
+#if !defined(SURFACE_REFRACT) && !defined(CLOSURE_NAME)
+ #define SURFACE_REFRACT
+ #define CLOSURE_NAME eevee_closure_refraction
+ #define CLOSURE_REFRACTION
+#endif /* SURFACE_REFRACT */
+
+#if !defined(SURFACE_GLASS) && !defined(CLOSURE_NAME)
+ #define SURFACE_GLASS
+ #define CLOSURE_NAME eevee_closure_glass
+ #define CLOSURE_GLOSSY
+ #define CLOSURE_REFRACTION
+#endif /* SURFACE_GLASS */
+
+/* Safety : CLOSURE_CLEARCOAT implies CLOSURE_GLOSSY */
+#ifdef CLOSURE_CLEARCOAT
+ #ifndef CLOSURE_GLOSSY
+ #define CLOSURE_GLOSSY
+ #endif
+#endif /* CLOSURE_CLEARCOAT */
+
+void CLOSURE_NAME(
+ vec3 N
+#ifdef CLOSURE_DIFFUSE
+ , vec3 albedo
+#endif
+#ifdef CLOSURE_GLOSSY
+ , vec3 f0, int ssr_id
+#endif
+#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
+ , float roughness
+#endif
+#ifdef CLOSURE_CLEARCOAT
+ , vec3 C_N, float C_intensity, float C_roughness
+#endif
+#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE)
+ , float ao
+#endif
+#ifdef CLOSURE_SUBSURFACE
+ , float sss_scale
+#endif
+#ifdef CLOSURE_REFRACTION
+ , float ior
+#endif
+#ifdef CLOSURE_DIFFUSE
+ , out vec3 out_diff
+#endif
+#ifdef CLOSURE_SUBSURFACE
+ , out vec3 out_trans
+#endif
+#ifdef CLOSURE_GLOSSY
+ , out vec3 out_spec
+#endif
+#ifdef CLOSURE_REFRACTION
+ , out vec3 out_refr
+#endif
+#ifdef CLOSURE_GLOSSY
+ , out vec3 ssr_spec
+#endif
+ )
+{
+#ifdef CLOSURE_DIFFUSE
+ out_diff = vec3(0.0);
+#endif
+
+#ifdef CLOSURE_SUBSURFACE
+ out_trans = vec3(0.0);
+#endif
+
+#ifdef CLOSURE_GLOSSY
+ out_spec = vec3(0.0);
+#endif
+
+#ifdef CLOSURE_REFRACTION
+ out_refr = vec3(0.0);
+#endif
+
+ /* Zero length vectors cause issues, see: T51979. */
+ float len = length(N);
+ if (isnan(len)) {
+ return;
+ }
+ N /= len;
+
+#ifdef CLOSURE_CLEARCOAT
+ len = length(C_N);
+ if (isnan(len)) {
+ return;
+ }
+ C_N /= len;
+#endif
+
+#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
+ roughness = clamp(roughness, 1e-8, 0.9999);
+ float roughnessSquared = roughness * roughness;
+#endif
+
+#ifdef CLOSURE_CLEARCOAT
+ C_roughness = clamp(C_roughness, 1e-8, 0.9999);
+ float C_roughnessSquared = C_roughness * C_roughness;
+#endif
+
+ vec3 V = cameraVec;
+
+ vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
+
+ /* ---------------------------------------------------------------- */
+ /* -------------------- SCENE LAMPS LIGHTING ---------------------- */
+ /* ---------------------------------------------------------------- */
+
+#ifdef HAIR_SHADER
+ vec3 norm_view = cross(V, N);
+ norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
+#endif
+
+ for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
+ LightData ld = lights_data[i];
+
+ vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
+ l_vector.xyz = ld.l_position - worldPosition;
+ l_vector.w = length(l_vector.xyz);
+
+ vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, viewPosition, viewNormal, l_vector);
+
+#ifdef HAIR_SHADER
+ vec3 norm_lamp, view_vec;
+ float occlu_trans, occlu;
+ light_hair_common(ld, N, V, l_vector, norm_view, occlu_trans, occlu, norm_lamp, view_vec);
+
+ #ifdef CLOSURE_DIFFUSE
+ out_diff += l_color_vis * light_diffuse(ld, -norm_lamp, V, l_vector) * occlu_trans;
+ #endif
+
+ #ifdef CLOSURE_SUBSURFACE
+ out_trans += ld.l_color * light_translucent(ld, worldPosition, -norm_lamp, l_vector, sss_scale) * occlu_trans;
+ #endif
+
+ #ifdef CLOSURE_GLOSSY
+ out_spec += l_color_vis * light_specular(ld, N, view_vec, l_vector, roughnessSquared, f0) * occlu;
+ #endif
+
+ #ifdef CLOSURE_CLEARCOAT
+ out_spec += l_color_vis * light_specular(ld, C_N, view_vec, l_vector, C_roughnessSquared, f0) * C_intensity * occlu;
+ #endif
+
+#else /* HAIR_SHADER */
+
+ #ifdef CLOSURE_DIFFUSE
+ out_diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
+ #endif
+
+ #ifdef CLOSURE_SUBSURFACE
+ out_trans += ld.l_color * light_translucent(ld, worldPosition, -N, l_vector, sss_scale);
+ #endif
+
+ #ifdef CLOSURE_GLOSSY
+ out_spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0);
+ #endif
+
+ #ifdef CLOSURE_CLEARCOAT
+ out_spec += l_color_vis * light_specular(ld, C_N, V, l_vector, C_roughnessSquared, f0) * C_intensity;
+ #endif
+
+#endif /* HAIR_SHADER */
+ }
+
+#ifdef HAIR_SHADER
+ N = -norm_view;
+#endif
+
+
+
+ /* ---------------------------------------------------------------- */
+ /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
+ /* ---------------------------------------------------------------- */
+
+ /* Accumulate incomming light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
+#ifdef CLOSURE_GLOSSY
+ vec4 spec_accum = vec4(0.0);
+#endif
+
+#ifdef CLOSURE_CLEARCOAT
+ vec4 C_spec_accum = vec4(0.0);
+#endif
+
+#ifdef CLOSURE_REFRACTION
+ vec4 refr_accum = vec4(0.0);
+#endif
+
+#ifdef CLOSURE_GLOSSY
+ /* ---------------------------- */
+ /* Planar Reflections */
+ /* ---------------------------- */
+
+ for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) {
+ PlanarData pd = planars_data[i];
+
+ /* Fade on geometric normal. */
+ float fade = probe_attenuation_planar(pd, worldPosition, worldNormal, roughness);
+
+ if (fade > 0.0) {
+ if (!(ssrToggle && ssr_id == outputSsrId)) {
+ vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, roughness, fade);
+ accumulate_light(spec, fade, spec_accum);
+ }
+
+ #ifdef CLOSURE_CLEARCOAT
+ vec3 C_spec = probe_evaluate_planar(float(i), pd, worldPosition, C_N, V, C_roughness, fade);
+ accumulate_light(C_spec, fade, C_spec_accum);
+ #endif
+
+ }
+ }
+#endif
+
+
+#ifdef CLOSURE_GLOSSY
+ vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
+#endif
+
+#ifdef CLOSURE_CLEARCOAT
+ vec3 C_spec_dir = get_specular_reflection_dominant_dir(C_N, V, C_roughnessSquared);
+#endif
+
+#ifdef CLOSURE_REFRACTION
+ /* Refract the view vector using the depth heuristic.
+ * Then later Refract a second time the already refracted
+ * ray using the inverse ior. */
+ float final_ior = (refractionDepth > 0.0) ? 1.0 / ior : ior;
+ vec3 refr_V = (refractionDepth > 0.0) ? -refract(-V, N, final_ior) : V;
+ vec3 refr_pos = (refractionDepth > 0.0) ? line_plane_intersect(worldPosition, refr_V, worldPosition - N * refractionDepth, N) : worldPosition;
+ vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior);
+#endif
+
+
+#ifdef CLOSURE_REFRACTION
+ /* ---------------------------- */
+ /* Screen Space Refraction */
+ /* ---------------------------- */
+ #ifdef USE_REFRACTION
+ if (ssrToggle && roughness < maxRoughness + 0.2) {
+ /* Find approximated position of the 2nd refraction event. */
+ vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) : viewPosition;
+
+ float ray_ofs = 1.0 / float(rayCount);
+ vec4 trans = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzw, 0.0);
+ if (rayCount > 1) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzw * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs);
+ if (rayCount > 2) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xwz * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs);
+ if (rayCount > 3) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xwz * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs);
+ trans /= float(rayCount);
+ trans.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness);
+ accumulate_light(trans.rgb, trans.a, refr_accum);
+ }
+ #endif
+
+#endif
+
+
+ /* ---------------------------- */
+ /* Specular probes */
+ /* ---------------------------- */
+#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
+
+ #ifdef CLOSURE_REFRACTION
+ #define ACCUM refr_accum
+ #else
+ #define ACCUM spec_accum
+ #endif
+
+ /* Starts at 1 because 0 is world probe */
+ for (int i = 1; ACCUM.a < 0.999 && i < probe_count && i < MAX_PROBE; ++i) {
+ CubeData cd = probes_data[i];
+
+ float fade = probe_attenuation_cube(cd, worldPosition);
+
+ if (fade > 0.0) {
+
+ #ifdef CLOSURE_GLOSSY
+ if (!(ssrToggle && ssr_id == outputSsrId)) {
+ vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness);
+ accumulate_light(spec, fade, spec_accum);
+ }
+ #endif
+
+ #ifdef CLOSURE_CLEARCOAT
+ vec3 C_spec = probe_evaluate_cube(float(i), cd, worldPosition, C_spec_dir, C_roughness);
+ accumulate_light(C_spec, fade, C_spec_accum);
+ #endif
+
+ #ifdef CLOSURE_REFRACTION
+ vec3 trans = probe_evaluate_cube(float(i), cd, refr_pos, refr_dir, roughnessSquared);
+ accumulate_light(trans, fade, refr_accum);
+ #endif
+ }
+ }
+
+ #undef ACCUM
+
+ /* ---------------------------- */
+ /* World Probe */
+ /* ---------------------------- */
+ #ifdef CLOSURE_GLOSSY
+ if (spec_accum.a < 0.999) {
+ if (!(ssrToggle && ssr_id == outputSsrId)) {
+ vec3 spec = probe_evaluate_world_spec(spec_dir, roughness);
+ accumulate_light(spec, 1.0, spec_accum);
+ }
+
+ #ifdef CLOSURE_CLEARCOAT
+ vec3 C_spec = probe_evaluate_world_spec(C_spec_dir, C_roughness);
+ accumulate_light(C_spec, 1.0, C_spec_accum);
+ #endif
+
+ }
+ #endif
+
+ #ifdef CLOSURE_REFRACTION
+ if (refr_accum.a < 0.999) {
+ vec3 trans = probe_evaluate_world_spec(refr_dir, roughnessSquared);
+ accumulate_light(trans, 1.0, refr_accum);
+ }
+ #endif
+#endif /* Specular probes */
+
+
+ /* ---------------------------- */
+ /* Ambient Occlusion */
+ /* ---------------------------- */
+#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE)
+ vec3 bent_normal;
+ float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
+#endif
+
+
+ /* ---------------------------- */
+ /* Specular Output */
+ /* ---------------------------- */
+ float NV = dot(N, V);
+#ifdef CLOSURE_GLOSSY
+ vec2 uv = lut_coords(NV, roughness);
+ vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
+
+ /* This factor is outputed to be used by SSR in order
+ * to match the intensity of the regular reflections. */
+ ssr_spec = F_ibl(f0, brdf_lut);
+ if (!(ssrToggle && ssr_id == outputSsrId)) {
+ /* The SSR pass recompute the occlusion to not apply it to the SSR */
+ ssr_spec *= specular_occlusion(NV, final_ao, roughness);
+ }
+
+ out_spec += spec_accum.rgb * ssr_spec * float(specToggle);
+#endif
+
+#ifdef CLOSURE_REFRACTION
+ float btdf = get_btdf_lut(utilTex, NV, roughness, ior);
+
+ out_refr += refr_accum.rgb * btdf;
+#endif
+
+#ifdef CLOSURE_CLEARCOAT
+ NV = dot(C_N, V);
+ vec2 C_uv = lut_coords(NV, C_roughness);
+ vec2 C_brdf_lut = texture(utilTex, vec3(C_uv, 1.0)).rg;
+ vec3 C_fresnel = F_ibl(vec3(0.04), brdf_lut) * specular_occlusion(NV, final_ao, C_roughness);
+
+ out_spec += C_spec_accum.rgb * C_fresnel * float(specToggle) * C_intensity;
+#endif
+
+ /* ---------------------------------------------------------------- */
+ /* ---------------- DIFFUSE ENVIRONMENT LIGHTING ------------------ */
+ /* ---------------------------------------------------------------- */
+
+ /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
+#ifdef CLOSURE_DIFFUSE
+ vec4 diff_accum = vec4(0.0);
+
+ /* ---------------------------- */
+ /* Irradiance Grids */
+ /* ---------------------------- */
+ /* Start at 1 because 0 is world irradiance */
+ for (int i = 1; i < MAX_GRID && i < grid_count && diff_accum.a < 0.999; ++i) {
+ GridData gd = grids_data[i];
+
+ vec3 localpos;
+ float fade = probe_attenuation_grid(gd, worldPosition, localpos);
+
+ if (fade > 0.0) {
+ vec3 diff = probe_evaluate_grid(gd, worldPosition, bent_normal, localpos);
+ accumulate_light(diff, fade, diff_accum);
+ }
+ }
+
+ /* ---------------------------- */
+ /* World Diffuse */
+ /* ---------------------------- */
+ if (diff_accum.a < 0.999 && grid_count > 0) {
+ vec3 diff = probe_evaluate_world_diff(bent_normal);
+ accumulate_light(diff, 1.0, diff_accum);
+ }
+
+ out_diff += diff_accum.rgb * gtao_multibounce(final_ao, albedo);
+#endif
+}
+
+/* Cleanup for next configuration */
+#undef CLOSURE_NAME
+
+#ifdef CLOSURE_DIFFUSE
+ #undef CLOSURE_DIFFUSE
+#endif
+
+#ifdef CLOSURE_GLOSSY
+ #undef CLOSURE_GLOSSY
+#endif
+
+#ifdef CLOSURE_CLEARCOAT
+ #undef CLOSURE_CLEARCOAT
+#endif
+
+#ifdef CLOSURE_REFRACTION
+ #undef CLOSURE_REFRACTION
+#endif
+
+#ifdef CLOSURE_SUBSURFACE
+ #undef CLOSURE_SUBSURFACE
+#endif \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
new file mode 100644
index 00000000000..998ccfa453a
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
@@ -0,0 +1,40 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ModelMatrix;
+uniform mat4 ModelViewMatrix;
+uniform mat3 WorldNormalMatrix;
+#ifndef ATTRIB
+uniform mat3 NormalMatrix;
+#endif
+
+in vec3 pos;
+in vec3 nor;
+
+out vec3 worldPosition;
+out vec3 viewPosition;
+
+/* Used for planar reflections */
+uniform vec4 ClipPlanes[1];
+
+#ifdef USE_FLAT_NORMAL
+flat out vec3 worldNormal;
+flat out vec3 viewNormal;
+#else
+out vec3 worldNormal;
+out vec3 viewNormal;
+#endif
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz;
+ worldPosition = (ModelMatrix * vec4(pos, 1.0)).xyz;
+ viewNormal = normalize(NormalMatrix * nor);
+ worldNormal = normalize(WorldNormalMatrix * nor);
+
+ /* Used for planar reflections */
+ gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), ClipPlanes[0]);
+
+#ifdef ATTRIB
+ pass_attrib(pos);
+#endif
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl
new file mode 100644
index 00000000000..ffaa81c3638
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl
@@ -0,0 +1,240 @@
+/* Mainly From https://eheitzresearch.wordpress.com/415-2/ */
+
+#define USE_LTC
+
+#ifndef UTIL_TEX
+#define UTIL_TEX
+uniform sampler2DArray utilTex;
+#endif /* UTIL_TEX */
+
+/* from Real-Time Area Lighting: a Journey from Research to Production
+ * Stephen Hill and Eric Heitz */
+float edge_integral(vec3 p1, vec3 p2)
+{
+#if 0
+ /* more accurate replacement of acos */
+ float x = dot(p1, p2);
+ float y = abs(x);
+
+ float a = 5.42031 + (3.12829 + 0.0902326 * y) * y;
+ float b = 3.45068 + (4.18814 + y) * y;
+ float theta_sintheta = a / b;
+
+ if (x < 0.0) {
+ theta_sintheta = (M_PI / sqrt(1.0 - x * x)) - theta_sintheta;
+ }
+ vec3 u = cross(p1, p2);
+ return theta_sintheta * dot(u, N);
+#endif
+ float cos_theta = dot(p1, p2);
+ cos_theta = clamp(cos_theta, -0.9999, 0.9999);
+
+ float theta = acos(cos_theta);
+ vec3 u = normalize(cross(p1, p2));
+ return theta * cross(p1, p2).z / sin(theta);
+}
+
+int clip_quad_to_horizon(inout vec3 L[5])
+{
+ /* detect clipping config */
+ int config = 0;
+ if (L[0].z > 0.0) config += 1;
+ if (L[1].z > 0.0) config += 2;
+ if (L[2].z > 0.0) config += 4;
+ if (L[3].z > 0.0) config += 8;
+
+ /* clip */
+ int n = 0;
+
+ if (config == 0)
+ {
+ /* clip all */
+ }
+ else if (config == 1) /* V1 clip V2 V3 V4 */
+ {
+ n = 3;
+ L[1] = -L[1].z * L[0] + L[0].z * L[1];
+ L[2] = -L[3].z * L[0] + L[0].z * L[3];
+ }
+ else if (config == 2) /* V2 clip V1 V3 V4 */
+ {
+ n = 3;
+ L[0] = -L[0].z * L[1] + L[1].z * L[0];
+ L[2] = -L[2].z * L[1] + L[1].z * L[2];
+ }
+ else if (config == 3) /* V1 V2 clip V3 V4 */
+ {
+ n = 4;
+ L[2] = -L[2].z * L[1] + L[1].z * L[2];
+ L[3] = -L[3].z * L[0] + L[0].z * L[3];
+ }
+ else if (config == 4) /* V3 clip V1 V2 V4 */
+ {
+ n = 3;
+ L[0] = -L[3].z * L[2] + L[2].z * L[3];
+ L[1] = -L[1].z * L[2] + L[2].z * L[1];
+ }
+ else if (config == 5) /* V1 V3 clip V2 V4) impossible */
+ {
+ n = 0;
+ }
+ else if (config == 6) /* V2 V3 clip V1 V4 */
+ {
+ n = 4;
+ L[0] = -L[0].z * L[1] + L[1].z * L[0];
+ L[3] = -L[3].z * L[2] + L[2].z * L[3];
+ }
+ else if (config == 7) /* V1 V2 V3 clip V4 */
+ {
+ n = 5;
+ L[4] = -L[3].z * L[0] + L[0].z * L[3];
+ L[3] = -L[3].z * L[2] + L[2].z * L[3];
+ }
+ else if (config == 8) /* V4 clip V1 V2 V3 */
+ {
+ n = 3;
+ L[0] = -L[0].z * L[3] + L[3].z * L[0];
+ L[1] = -L[2].z * L[3] + L[3].z * L[2];
+ L[2] = L[3];
+ }
+ else if (config == 9) /* V1 V4 clip V2 V3 */
+ {
+ n = 4;
+ L[1] = -L[1].z * L[0] + L[0].z * L[1];
+ L[2] = -L[2].z * L[3] + L[3].z * L[2];
+ }
+ else if (config == 10) /* V2 V4 clip V1 V3) impossible */
+ {
+ n = 0;
+ }
+ else if (config == 11) /* V1 V2 V4 clip V3 */
+ {
+ n = 5;
+ L[4] = L[3];
+ L[3] = -L[2].z * L[3] + L[3].z * L[2];
+ L[2] = -L[2].z * L[1] + L[1].z * L[2];
+ }
+ else if (config == 12) /* V3 V4 clip V1 V2 */
+ {
+ n = 4;
+ L[1] = -L[1].z * L[2] + L[2].z * L[1];
+ L[0] = -L[0].z * L[3] + L[3].z * L[0];
+ }
+ else if (config == 13) /* V1 V3 V4 clip V2 */
+ {
+ n = 5;
+ L[4] = L[3];
+ L[3] = L[2];
+ L[2] = -L[1].z * L[2] + L[2].z * L[1];
+ L[1] = -L[1].z * L[0] + L[0].z * L[1];
+ }
+ else if (config == 14) /* V2 V3 V4 clip V1 */
+ {
+ n = 5;
+ L[4] = -L[0].z * L[3] + L[3].z * L[0];
+ L[0] = -L[0].z * L[1] + L[1].z * L[0];
+ }
+ else if (config == 15) /* V1 V2 V3 V4 */
+ {
+ n = 4;
+ }
+
+ if (n == 3)
+ L[3] = L[0];
+ if (n == 4)
+ L[4] = L[0];
+
+ return n;
+}
+
+mat3 ltc_matrix(vec4 lut)
+{
+ /* load inverse matrix */
+ mat3 Minv = mat3(
+ vec3( 1, 0, lut.y),
+ vec3( 0, lut.z, 0),
+ vec3(lut.w, 0, lut.x)
+ );
+
+ return Minv;
+}
+
+float ltc_evaluate(vec3 N, vec3 V, mat3 Minv, vec3 corners[4])
+{
+ /* Avoid dot(N, V) == 1 in ortho mode, leading T1 normalize to fail. */
+ V = normalize(V + 1e-8);
+
+ /* construct orthonormal basis around N */
+ vec3 T1, T2;
+ T1 = normalize(V - N * dot(N, V));
+ T2 = cross(N, T1);
+
+ /* rotate area light in (T1, T2, R) basis */
+ Minv = Minv * transpose(mat3(T1, T2, N));
+
+ /* polygon (allocate 5 vertices for clipping) */
+ vec3 L[5];
+ L[0] = Minv * corners[0];
+ L[1] = Minv * corners[1];
+ L[2] = Minv * corners[2];
+ L[3] = Minv * corners[3];
+
+ int n = clip_quad_to_horizon(L);
+
+ if (n == 0)
+ return 0.0;
+
+ /* project onto sphere */
+ L[0] = normalize(L[0]);
+ L[1] = normalize(L[1]);
+ L[2] = normalize(L[2]);
+ L[3] = normalize(L[3]);
+ L[4] = normalize(L[4]);
+
+ /* integrate */
+ float sum = 0.0;
+
+ sum += edge_integral(L[0], L[1]);
+ sum += edge_integral(L[1], L[2]);
+ sum += edge_integral(L[2], L[3]);
+ if (n >= 4)
+ sum += edge_integral(L[3], L[4]);
+ if (n == 5)
+ sum += edge_integral(L[4], L[0]);
+
+ return abs(sum);
+}
+
+/* Aproximate circle with an octogone */
+#define LTC_CIRCLE_RES 8
+float ltc_evaluate_circle(vec3 N, vec3 V, mat3 Minv, vec3 p[LTC_CIRCLE_RES])
+{
+ /* Avoid dot(N, V) == 1 in ortho mode, leading T1 normalize to fail. */
+ V = normalize(V + 1e-8);
+
+ /* construct orthonormal basis around N */
+ vec3 T1, T2;
+ T1 = normalize(V - N * dot(V, N));
+ T2 = cross(N, T1);
+
+ /* rotate area light in (T1, T2, R) basis */
+ Minv = Minv * transpose(mat3(T1, T2, N));
+
+ for (int i = 0; i < LTC_CIRCLE_RES; ++i) {
+ p[i] = Minv * p[i];
+ /* clip to horizon */
+ p[i].z = max(0.0, p[i].z);
+ /* project onto sphere */
+ p[i] = normalize(p[i]);
+ }
+
+ /* integrate */
+ float sum = 0.0;
+ for (int i = 0; i < LTC_CIRCLE_RES - 1; ++i) {
+ sum += edge_integral(p[i], p[i + 1]);
+ }
+ sum += edge_integral(p[LTC_CIRCLE_RES - 1], p[0]);
+
+ return max(0.0, sum);
+}
+
diff --git a/source/blender/draw/engines/eevee/shaders/octahedron_lib.glsl b/source/blender/draw/engines/eevee/shaders/octahedron_lib.glsl
new file mode 100644
index 00000000000..631b325ae37
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/octahedron_lib.glsl
@@ -0,0 +1,38 @@
+
+vec2 mapping_octahedron(vec3 cubevec, vec2 texel_size)
+{
+ /* projection onto octahedron */
+ cubevec /= dot( vec3(1), abs(cubevec) );
+
+ /* out-folding of the downward faces */
+ if ( cubevec.z < 0.0 ) {
+ cubevec.xy = (1.0 - abs(cubevec.yx)) * sign(cubevec.xy);
+ }
+
+ /* mapping to [0;1]ˆ2 texture space */
+ vec2 uvs = cubevec.xy * (0.5) + 0.5;
+
+ /* edge filtering fix */
+ uvs *= 1.0 - 2.0 * texel_size;
+ uvs += texel_size;
+
+ return uvs;
+}
+
+vec4 textureLod_octahedron(sampler2DArray tex, vec4 cubevec, float lod, float lod_max)
+{
+ vec2 texelSize = 1.0 / vec2(textureSize(tex, int(lod_max)));
+
+ vec2 uvs = mapping_octahedron(cubevec.xyz, texelSize);
+
+ return textureLod(tex, vec3(uvs, cubevec.w), lod);
+}
+
+vec4 texture_octahedron(sampler2DArray tex, vec4 cubevec)
+{
+ vec2 texelSize = 1.0 / vec2(textureSize(tex, 0));
+
+ vec2 uvs = mapping_octahedron(cubevec.xyz, texelSize);
+
+ return texture(tex, vec3(uvs, cubevec.w));
+}
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
new file mode 100644
index 00000000000..f921d56e3bc
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
@@ -0,0 +1,85 @@
+
+#ifdef USE_ALPHA_HASH
+
+/* From the paper "Hashed Alpha Testing" by Chris Wyman and Morgan McGuire */
+float hash(vec2 a) {
+ return fract(1e4 * sin(17.0 * a.x + 0.1 * a.y) * (0.1 + abs(sin(13.0 * a.y + a.x))));
+}
+
+float hash3d(vec3 a) {
+ return hash(vec2(hash(a.xy), a.z));
+}
+
+//uniform float hashScale;
+float hashScale = 0.001;
+
+float hashed_alpha_threshold(vec3 co)
+{
+ /* Find the discretized derivatives of our coordinates. */
+ float max_deriv = max(length(dFdx(co)), length(dFdy(co)));
+ float pix_scale = 1.0 / (hashScale * max_deriv);
+
+ /* Find two nearest log-discretized noise scales. */
+ float pix_scale_log = log2(pix_scale);
+ vec2 pix_scales;
+ pix_scales.x = exp2(floor(pix_scale_log));
+ pix_scales.y = exp2(ceil(pix_scale_log));
+
+ /* Compute alpha thresholds at our two noise scales. */
+ vec2 alpha;
+ alpha.x = hash3d(floor(pix_scales.x * co));
+ alpha.y = hash3d(floor(pix_scales.y * co));
+
+ /* Factor to interpolate lerp with. */
+ float fac = fract(log2(pix_scale));
+
+ /* Interpolate alpha threshold from noise at two scales. */
+ float x = mix(alpha.x, alpha.y, fac);
+
+ /* Pass into CDF to compute uniformly distrib threshold. */
+ float a = min(fac, 1.0 - fac);
+ float one_a = 1.0 - a;
+ float denom = 1.0 / (2 * a * one_a);
+ float one_x = (1 - x);
+ vec3 cases = vec3(
+ (x * x) * denom,
+ (x - 0.5 * a) / one_a,
+ 1.0 - (one_x * one_x * denom)
+ );
+
+ /* Find our final, uniformly distributed alpha threshold. */
+ float threshold = (x < one_a) ? ((x < a) ? cases.x : cases.y) : cases.z;
+
+ /* Avoids threshold == 0. */
+ threshold = clamp(threshold, 1.0e-6, 1.0);
+
+ return threshold;
+}
+
+#endif
+
+#ifdef USE_ALPHA_CLIP
+uniform float alphaThreshold;
+#endif
+
+void main()
+{
+ /* For now do nothing.
+ * In the future, output object motion blur. */
+
+#if defined(USE_ALPHA_HASH) || defined(USE_ALPHA_CLIP)
+#define NODETREE_EXEC
+
+ Closure cl = nodetree_exec();
+
+#if defined(USE_ALPHA_HASH)
+ /* Hashed Alpha Testing */
+ if (cl.opacity < hashed_alpha_threshold(worldPosition))
+ discard;
+#elif defined(USE_ALPHA_CLIP)
+ /* Alpha clip */
+ if (cl.opacity <= alphaThreshold)
+ discard;
+#endif
+#endif
+}
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
new file mode 100644
index 00000000000..6f26a815736
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
@@ -0,0 +1,18 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ModelMatrix;
+#ifdef CLIP_PLANES
+uniform vec4 ClipPlanes[1];
+#endif
+
+in vec3 pos;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+#ifdef CLIP_PLANES
+ vec4 worldPosition = (ModelMatrix * vec4(pos, 1.0));
+ gl_ClipDistance[0] = dot(worldPosition, ClipPlanes[0]);
+#endif
+ /* TODO motion vectors */
+}
diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
new file mode 100644
index 00000000000..c593081ce91
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
@@ -0,0 +1,242 @@
+#define MAX_STEP 256
+
+uniform vec4 ssrParameters;
+
+#define ssrQuality ssrParameters.x
+#define ssrThickness ssrParameters.y
+#define ssrPixelSize ssrParameters.zw
+
+uniform float borderFadeFactor;
+
+float sample_depth(vec2 uv, int index, float lod)
+{
+#ifdef PLANAR_PROBE_RAYTRACE
+ if (index > -1) {
+ return textureLod(planarDepth, vec3(uv, index), 0.0).r;
+ }
+ else {
+#endif
+ /* Correct UVs for mipmaping mis-alignment */
+ uv *= mipRatio[int(lod + 1.0)];
+ return textureLod(maxzBuffer, uv, lod).r;
+#ifdef PLANAR_PROBE_RAYTRACE
+ }
+#endif
+}
+
+vec4 sample_depth_grouped(vec4 uv1, vec4 uv2, int index, float lod)
+{
+ vec4 depths;
+#ifdef PLANAR_PROBE_RAYTRACE
+ if (index > -1) {
+ depths.x = textureLod(planarDepth, vec3(uv1.xy, index), 0.0).r;
+ depths.y = textureLod(planarDepth, vec3(uv1.zw, index), 0.0).r;
+ depths.z = textureLod(planarDepth, vec3(uv2.xy, index), 0.0).r;
+ depths.w = textureLod(planarDepth, vec3(uv2.zw, index), 0.0).r;
+ }
+ else {
+#endif
+ depths.x = textureLod(maxzBuffer, uv1.xy, lod).r;
+ depths.y = textureLod(maxzBuffer, uv1.zw, lod).r;
+ depths.z = textureLod(maxzBuffer, uv2.xy, lod).r;
+ depths.w = textureLod(maxzBuffer, uv2.zw, lod).r;
+#ifdef PLANAR_PROBE_RAYTRACE
+ }
+#endif
+ return depths;
+}
+
+float refine_isect(float prev_delta, float curr_delta)
+{
+ /**
+ * Simplification of 2D intersection :
+ * r0 = (0.0, prev_ss_ray.z);
+ * r1 = (1.0, curr_ss_ray.z);
+ * d0 = (0.0, prev_hit_depth_sample);
+ * d1 = (1.0, curr_hit_depth_sample);
+ * vec2 r = r1 - r0;
+ * vec2 d = d1 - d0;
+ * vec2 isect = ((d * cross(r1, r0)) - (r * cross(d1, d0))) / cross(r,d);
+ *
+ * We only want isect.x to know how much stride we need. So it simplifies :
+ *
+ * isect_x = (cross(r1, r0) - cross(d1, d0)) / cross(r,d);
+ * isect_x = (prev_ss_ray.z - prev_hit_depth_sample.z) / cross(r,d);
+ */
+ return saturate(prev_delta / (prev_delta - curr_delta));
+}
+
+void prepare_raycast(vec3 ray_origin, vec3 ray_end, float thickness, out vec4 ss_step, out vec4 ss_ray, out float max_time)
+{
+ /* Negate the ray direction if it goes towards the camera.
+ * This way we don't need to care if the projected point
+ * is behind the near plane. */
+ float z_sign = -sign(ray_end.z);
+ ray_end = z_sign * ray_end + ray_origin;
+
+ /* Project into screen space. */
+ vec4 ss_start, ss_end;
+ ss_start.xyz = project_point(ProjectionMatrix, ray_origin);
+ ss_end.xyz = project_point(ProjectionMatrix, ray_end);
+
+ /* We interpolate the ray Z + thickness values to check if depth is within threshold. */
+ ray_origin.z -= thickness;
+ ray_end.z -= thickness;
+ ss_start.w = project_point(ProjectionMatrix, ray_origin).z;
+ ss_end.w = project_point(ProjectionMatrix, ray_end).z;
+
+ /* XXX This is a hack a better method is welcome ! */
+ /* We take the delta between the offseted depth and the depth and substract it from the ray depth.
+ * This will change the world space thickness appearance a bit but we can have negative
+ * values without worries. We cannot do this in viewspace because of the perspective division. */
+ ss_start.w = 2.0 * ss_start.z - ss_start.w;
+ ss_end.w = 2.0 * ss_end.z - ss_end.w;
+
+ ss_step = ss_end - ss_start;
+ max_time = length(ss_step.xyz);
+ ss_step = z_sign * ss_step / length(ss_step.xyz);
+
+ /* If the line is degenerate, make it cover at least one pixel
+ * to not have to handle zero-pixel extent as a special case later */
+ ss_step.xy += vec2((dot(ss_step.xy, ss_step.xy) < 0.000001) ? 0.001 : 0.0);
+
+ /* Make ss_step cover one pixel. */
+ ss_step /= max(abs(ss_step.x), abs(ss_step.y));
+ ss_step *= ((abs(ss_step.x) > abs(ss_step.y)) ? ssrPixelSize.x : ssrPixelSize.y);
+
+ /* Clip to segment's end. */
+ max_time /= length(ss_step.xyz);
+
+ /* Clipping to frustum sides. */
+ max_time = min(max_time, line_unit_box_intersect_dist(ss_start.xyz, ss_step.xyz));
+
+ /* Convert to texture coords. Z component included
+ * since this is how it's stored in the depth buffer.
+ * 4th component how far we are on the ray */
+ ss_ray = ss_start * 0.5 + 0.5;
+ ss_step *= 0.5;
+}
+
+/* See times_and_deltas. */
+#define curr_time times_and_deltas.x
+#define prev_time times_and_deltas.y
+#define curr_delta times_and_deltas.z
+#define prev_delta times_and_deltas.w
+
+// #define GROUPED_FETCHES /* is still slower, need to see where is the bottleneck. */
+/* Return the hit position, and negate the z component (making it positive) if not hit occured. */
+/* __ray_end__ is the ray direction premultiplied by it's maximum length */
+vec3 raycast(
+ int index, vec3 ray_origin, vec3 ray_end, float thickness, float ray_jitter,
+ float trace_quality, float roughness, const bool discard_backface)
+{
+ vec4 ss_step, ss_start;
+ float max_time;
+ prepare_raycast(ray_origin, ray_end, thickness, ss_step, ss_start, max_time);
+
+ float max_trace_time = max(0.001, max_time - 0.01);
+
+#ifdef GROUPED_FETCHES
+ ray_jitter *= 0.25;
+#endif
+
+ /* x : current_time, y: previous_time, z: current_delta, w: previous_delta */
+ vec4 times_and_deltas = vec4(0.0);
+
+ float ray_time = 0.0;
+ float depth_sample = sample_depth(ss_start.xy, index, 0.0);
+ curr_delta = depth_sample - ss_start.z;
+
+ float lod_fac = saturate(fast_sqrt(roughness) * 2.0 - 0.4);
+ bool hit = false;
+ float iter;
+ for (iter = 1.0; !hit && (ray_time < max_time) && (iter < MAX_STEP); iter++) {
+ /* Minimum stride of 2 because we are using half res minmax zbuffer. */
+ float stride = max(1.0, iter * trace_quality) * 2.0;
+ float lod = log2(stride * 0.5 * trace_quality) * lod_fac;
+ ray_time += stride;
+
+ /* Save previous values. */
+ times_and_deltas.xyzw = times_and_deltas.yxwz;
+
+#ifdef GROUPED_FETCHES
+ stride *= 4.0;
+ vec4 jit_stride = mix(vec4(2.0), vec4(stride), vec4(0.0, 0.25, 0.5, 0.75) + ray_jitter);
+
+ vec4 times = min(vec4(ray_time) + jit_stride, vec4(max_trace_time));
+
+ vec4 uv1 = ss_start.xyxy + ss_step.xyxy * times.xxyy;
+ vec4 uv2 = ss_start.xyxy + ss_step.xyxy * times.zzww;
+
+ vec4 depth_samples = sample_depth_grouped(uv1, uv2, index, lod);
+
+ vec4 ray_z = ss_start.zzzz + ss_step.zzzz * times.xyzw;
+ vec4 ray_w = ss_start.wwww + ss_step.wwww * vec4(prev_time, times.xyz);
+
+ vec4 deltas = depth_samples - ray_z;
+ /* Same as component wise (curr_delta <= 0.0) && (prev_w <= depth_sample). */
+ bvec4 test = equal(step(deltas, vec4(0.0)) * step(ray_w, depth_samples), vec4(1.0));
+ hit = any(test);
+
+ if (hit) {
+ vec2 m = vec2(1.0, 0.0); /* Mask */
+
+ vec4 ret_times_and_deltas = times.wzzz * m.xxyy + deltas.wwwz * m.yyxx;
+ ret_times_and_deltas = (test.z) ? times.zyyy * m.xxyy + deltas.zzzy * m.yyxx : ret_times_and_deltas;
+ ret_times_and_deltas = (test.y) ? times.yxxx * m.xxyy + deltas.yyyx * m.yyxx : ret_times_and_deltas;
+ times_and_deltas = (test.x) ? times.xxxx * m.xyyy + deltas.xxxx * m.yyxy + times_and_deltas.yyww * m.yxyx : ret_times_and_deltas;
+
+ depth_sample = depth_samples.w;
+ depth_sample = (test.z) ? depth_samples.z : depth_sample;
+ depth_sample = (test.y) ? depth_samples.y : depth_sample;
+ depth_sample = (test.x) ? depth_samples.x : depth_sample;
+ }
+ else {
+ curr_time = times.w;
+ curr_delta = deltas.w;
+ }
+#else
+ float jit_stride = mix(2.0, stride, ray_jitter);
+
+ curr_time = min(ray_time + jit_stride, max_trace_time);
+ vec4 ss_ray = ss_start + ss_step * curr_time;
+
+ depth_sample = sample_depth(ss_ray.xy, index, lod);
+
+ float prev_w = ss_start.w + ss_step.w * prev_time;
+ curr_delta = depth_sample - ss_ray.z;
+ hit = (curr_delta <= 0.0) && (prev_w <= depth_sample);
+#endif
+ }
+
+ if (discard_backface) {
+ /* Discard backface hits */
+ hit = hit && (prev_delta > 0.0);
+ }
+
+ /* Reject hit if background. */
+ hit = hit && (depth_sample != 1.0);
+
+ curr_time = (hit) ? mix(prev_time, curr_time, refine_isect(prev_delta, curr_delta)) : curr_time;
+ ray_time = (hit) ? curr_time : ray_time;
+
+ /* Clip to frustum. */
+ ray_time = max(0.001, min(ray_time, max_time - 1.5));
+
+ vec4 ss_ray = ss_start + ss_step * ray_time;
+
+ /* Tag Z if ray failed. */
+ ss_ray.z *= (hit) ? 1.0 : -1.0;
+ return ss_ray.xyz;
+}
+
+float screen_border_mask(vec2 hit_co)
+{
+ const float margin = 0.003;
+ float atten = borderFadeFactor + margin; /* Screen percentage */
+ hit_co = smoothstep(margin, atten, hit_co) * (1 - smoothstep(1.0 - atten, 1.0 - margin, hit_co));
+
+ float screenfade = hit_co.x * hit_co.y;
+
+ return screenfade;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl
new file mode 100644
index 00000000000..67b0fc2bdfc
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl
@@ -0,0 +1,210 @@
+/* Copy the depth only shadowmap into another texture while converting
+ * to linear depth (or other storage method) and doing a 3x3 box filter. */
+
+layout(std140) uniform shadow_render_block {
+ mat4 ShadowMatrix[6];
+ mat4 FaceViewMatrix[6];
+ vec4 lampPosition;
+ float cubeTexelSize;
+ float storedTexelSize;
+ float nearClip;
+ float farClip;
+ int shadowSampleCount;
+ float shadowInvSampleCount;
+};
+
+#ifdef CSM
+uniform sampler2DArray shadowTexture;
+uniform int cascadeId;
+#else
+uniform samplerCube shadowTexture;
+uniform int faceId;
+#endif
+uniform float shadowFilterSize;
+
+out vec4 FragColor;
+
+float linear_depth(float z)
+{
+ return (nearClip * farClip) / (z * (nearClip - farClip) + farClip);
+}
+
+vec4 linear_depth(vec4 z)
+{
+ return (nearClip * farClip) / (z * (nearClip - farClip) + farClip);
+}
+
+#ifdef CSM
+vec4 get_world_distance(vec4 depths, vec3 cos[4])
+{
+ /* Background case */
+ vec4 is_background = step(vec4(0.99999), depths);
+ depths *= abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */
+ depths += 1e1 * is_background;
+ return depths;
+}
+
+float get_world_distance(float depth, vec3 cos)
+{
+ /* Background case */
+ float is_background = step(0.9999, depth);
+ depth *= abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */
+ depth += 1e1 * is_background;
+ return depth;
+}
+#else /* CUBEMAP */
+vec4 get_world_distance(vec4 depths, vec3 cos[4])
+{
+ vec4 is_background = step(vec4(1.0), depths);
+ depths = linear_depth(depths);
+ depths += vec4(1e1) * is_background;
+ cos[0] = normalize(abs(cos[0]));
+ cos[1] = normalize(abs(cos[1]));
+ cos[2] = normalize(abs(cos[2]));
+ cos[3] = normalize(abs(cos[3]));
+ vec4 cos_vec;
+ cos_vec.x = max(cos[0].x, max(cos[0].y, cos[0].z));
+ cos_vec.y = max(cos[1].x, max(cos[1].y, cos[1].z));
+ cos_vec.z = max(cos[2].x, max(cos[2].y, cos[2].z));
+ cos_vec.w = max(cos[3].x, max(cos[3].y, cos[3].z));
+ return depths / cos_vec;
+}
+
+float get_world_distance(float depth, vec3 cos)
+{
+ float is_background = step(1.0, depth);
+ depth = linear_depth(depth);
+ depth += 1e1 * is_background;
+ cos = normalize(abs(cos));
+ float cos_vec = max(cos.x, max(cos.y, cos.z));
+ return depth / cos_vec;
+}
+#endif
+
+/* Marco Salvi's GDC 2008 presentation about shadow maps pre-filtering techniques slide 24 */
+float ln_space_prefilter(float w0, float x, float w1, float y)
+{
+ return x + log(w0 + w1 * exp(y - x));
+}
+
+#define SAMPLE_WEIGHT 0.11111
+
+#ifdef ESM
+void prefilter(vec4 depths, inout float accum)
+{
+ accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.x);
+ accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.y);
+ accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.z);
+ accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.w);
+}
+#else /* VSM */
+void prefilter(vec4 depths, inout vec2 accum)
+{
+ vec4 depths_sqr = depths * depths;
+ accum += vec2(dot(vec4(1.0), depths), dot(vec4(1.0), depths_sqr)) * SAMPLE_WEIGHT;
+}
+#endif
+
+#ifdef CSM
+vec3 get_texco(vec2 uvs, vec2 ofs)
+{
+ return vec3(uvs + ofs, float(cascadeId));
+}
+#else /* CUBEMAP */
+const vec3 minorAxisX[6] = vec3[6](
+ vec3(0.0f, 0.0f, -1.0f),
+ vec3(0.0f, 0.0f, 1.0f),
+ vec3(1.0f, 0.0f, 0.0f),
+ vec3(1.0f, 0.0f, 0.0f),
+ vec3(1.0f, 0.0f, 0.0f),
+ vec3(-1.0f, 0.0f, 0.0f)
+);
+
+const vec3 minorAxisY[6] = vec3[6](
+ vec3(0.0f, -1.0f, 0.0f),
+ vec3(0.0f, -1.0f, 0.0f),
+ vec3(0.0f, 0.0f, 1.0f),
+ vec3(0.0f, 0.0f, -1.0f),
+ vec3(0.0f, -1.0f, 0.0f),
+ vec3(0.0f, -1.0f, 0.0f)
+);
+
+const vec3 majorAxis[6] = vec3[6](
+ vec3(1.0f, 0.0f, 0.0f),
+ vec3(-1.0f, 0.0f, 0.0f),
+ vec3(0.0f, 1.0f, 0.0f),
+ vec3(0.0f, -1.0f, 0.0f),
+ vec3(0.0f, 0.0f, 1.0f),
+ vec3(0.0f, 0.0f, -1.0f)
+);
+
+vec3 get_texco(vec2 uvs, vec2 ofs)
+{
+ uvs += ofs;
+ return majorAxis[faceId] + uvs.x * minorAxisX[faceId] + uvs.y * minorAxisY[faceId];
+}
+#endif
+
+void main() {
+ /* Copy the depth only shadowmap into another texture while converting
+ * to linear depth and do a 3x3 box blur. */
+
+#ifdef CSM
+ vec2 uvs = gl_FragCoord.xy * storedTexelSize;
+#else /* CUBEMAP */
+ vec2 uvs = gl_FragCoord.xy * cubeTexelSize * 2.0 - 1.0;
+#endif
+
+ /* Center texel */
+ vec3 co = get_texco(uvs, vec2(0.0));
+ float depth = texture(shadowTexture, co).r;
+ depth = get_world_distance(depth, co);
+
+ if (shadowFilterSize == 0.0) {
+#ifdef ESM
+ FragColor = vec4(depth);
+#else /* VSM */
+ FragColor = vec2(depth, depth * depth).xyxy;
+#endif
+ return;
+ }
+
+#ifdef ESM
+ float accum = ln_space_prefilter(0.0, 0.0, SAMPLE_WEIGHT, depth);
+#else /* VSM */
+ vec2 accum = vec2(depth, depth * depth) * SAMPLE_WEIGHT;
+#endif
+
+#ifdef CSM
+ vec3 ofs = vec3(1.0, 0.0, -1.0) * shadowFilterSize;
+#else /* CUBEMAP */
+ vec3 ofs = vec3(1.0, 0.0, -1.0) * shadowFilterSize;
+#endif
+
+ vec3 cos[4];
+ cos[0] = get_texco(uvs, ofs.zz);
+ cos[1] = get_texco(uvs, ofs.yz);
+ cos[2] = get_texco(uvs, ofs.xz);
+ cos[3] = get_texco(uvs, ofs.zy);
+
+ vec4 depths;
+ depths.x = texture(shadowTexture, cos[0]).r;
+ depths.y = texture(shadowTexture, cos[1]).r;
+ depths.z = texture(shadowTexture, cos[2]).r;
+ depths.w = texture(shadowTexture, cos[3]).r;
+ depths = get_world_distance(depths, cos);
+ prefilter(depths, accum);
+
+ cos[0] = get_texco(uvs, ofs.xy);
+ cos[1] = get_texco(uvs, ofs.zx);
+ cos[2] = get_texco(uvs, ofs.yx);
+ cos[3] = get_texco(uvs, ofs.xx);
+ depths.x = texture(shadowTexture, cos[0]).r;
+ depths.y = texture(shadowTexture, cos[1]).r;
+ depths.z = texture(shadowTexture, cos[2]).r;
+ depths.w = texture(shadowTexture, cos[3]).r;
+ depths = get_world_distance(depths, cos);
+ prefilter(depths, accum);
+
+ FragColor = vec2(accum).xyxy;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl
new file mode 100644
index 00000000000..160fcee4c73
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl
@@ -0,0 +1,4 @@
+
+void main() {
+ /* Do nothing */
+}
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl b/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl
new file mode 100644
index 00000000000..ea51fa73a65
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl
@@ -0,0 +1,53 @@
+
+layout(std140) uniform shadow_render_block {
+ mat4 ShadowMatrix[6];
+ mat4 FaceViewMatrix[6];
+ vec4 lampPosition;
+ float cubeTexelSize;
+ float storedTexelSize;
+ float nearClip;
+ float farClip;
+ int shadowSampleCount;
+ float shadowInvSampleCount;
+};
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices=3) out;
+
+in vec4 vPos[];
+flat in int face[];
+
+#ifdef MESH_SHADER
+in vec3 vNor[];
+#endif
+
+out vec3 worldPosition;
+#ifdef MESH_SHADER
+out vec3 viewPosition; /* Required. otherwise generate linking error. */
+out vec3 worldNormal; /* Required. otherwise generate linking error. */
+out vec3 viewNormal; /* Required. otherwise generate linking error. */
+flat out int shFace;
+#else
+int shFace;
+#endif
+
+void main() {
+ shFace = face[0];
+ gl_Layer = shFace;
+
+ for (int v = 0; v < 3; ++v) {
+ gl_Position = ShadowMatrix[shFace] * vPos[v];
+ worldPosition = vPos[v].xyz;
+#ifdef MESH_SHADER
+ worldNormal = vNor[v];
+ viewPosition = (FaceViewMatrix[shFace] * vec4(worldPosition, 1.0)).xyz;
+ viewNormal = (FaceViewMatrix[shFace] * vec4(worldNormal, 0.0)).xyz;
+#ifdef ATTRIB
+ pass_attrib(v);
+#endif
+#endif
+ EmitVertex();
+ }
+
+ EndPrimitive();
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl
new file mode 100644
index 00000000000..fcc304ca289
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl
@@ -0,0 +1,146 @@
+
+layout(std140) uniform shadow_render_block {
+ mat4 ShadowMatrix[6];
+ mat4 FaceViewMatrix[6];
+ vec4 lampPosition;
+ float cubeTexelSize;
+ float storedTexelSize;
+ float nearClip;
+ float farClip;
+ int shadowSampleCount;
+ float shadowInvSampleCount;
+};
+
+#ifdef CSM
+uniform sampler2DArray shadowTexture;
+uniform int cascadeId;
+#else
+uniform samplerCube shadowTexture;
+#endif
+uniform float shadowFilterSize;
+
+out vec4 FragColor;
+
+vec3 octahedral_to_cubemap_proj(vec2 co)
+{
+ co = co * 2.0 - 1.0;
+
+ vec2 abs_co = abs(co);
+ vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y));
+
+ if ( abs_co.x + abs_co.y > 1.0 ) {
+ v.xy = (abs(co.yx) - 1.0) * -sign(co.xy);
+ }
+
+ return v;
+}
+
+/* Marco Salvi's GDC 2008 presentation about shadow maps pre-filtering techniques slide 24 */
+float ln_space_prefilter(float w0, float x, float w1, float y)
+{
+ return x + log(w0 + w1 * exp(y - x));
+}
+
+vec4 ln_space_prefilter(float w0, vec4 x, float w1, vec4 y)
+{
+ return x + log(w0 + w1 * exp(y - x));
+}
+
+#ifdef CSM
+vec3 get_texco(vec3 cos, vec2 ofs)
+{
+ cos.xy += ofs * shadowFilterSize;
+ return cos;
+}
+#else /* CUBEMAP */
+/* global vars */
+vec3 T = vec3(0.0);
+vec3 B = vec3(0.0);
+
+void make_orthonormal_basis(vec3 N)
+{
+ vec3 UpVector = (abs(N.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+ T = normalize(cross(UpVector, N));
+ B = cross(N, T);
+}
+
+vec3 get_texco(vec3 cos, vec2 ofs)
+{
+ return cos + ofs.x * T + ofs.y * B;
+}
+
+#endif
+
+void main() {
+ vec3 cos;
+
+ cos.xy = gl_FragCoord.xy * storedTexelSize;
+
+#ifdef CSM
+ cos.z = float(cascadeId);
+#else /* CUBEMAP */
+ /* add a 2 pixel border to ensure filtering is correct */
+ cos.xy *= 1.0 + storedTexelSize * 2.0;
+ cos.xy -= storedTexelSize;
+
+ float pattern = 1.0;
+
+ /* edge mirroring : only mirror if directly adjacent
+ * (not diagonally adjacent) */
+ vec2 m = abs(cos.xy - 0.5) + 0.5;
+ vec2 f = floor(m);
+ if (f.x - f.y != 0.0) {
+ cos.xy = 1.0 - cos.xy;
+ }
+
+ /* clamp to [0-1] */
+ cos.xy = fract(cos.xy);
+
+ /* get cubemap vector */
+ cos = normalize(octahedral_to_cubemap_proj(cos.xy));
+ make_orthonormal_basis(cos);
+
+ T *= shadowFilterSize;
+ B *= shadowFilterSize;
+#endif
+
+#ifdef ESM
+ vec4 accum = vec4(0.0);
+
+ /* disc blur in log space. */
+ vec4 depths;
+ depths.x = texture(shadowTexture, get_texco(cos, concentric[0])).r;
+ depths.y = texture(shadowTexture, get_texco(cos, concentric[1])).r;
+ depths.z = texture(shadowTexture, get_texco(cos, concentric[2])).r;
+ depths.w = texture(shadowTexture, get_texco(cos, concentric[3])).r;
+ accum = ln_space_prefilter(0.0, accum, shadowInvSampleCount, depths);
+
+ for (int i = 4; i < shadowSampleCount && i < CONCENTRIC_SAMPLE_NUM; i += 4) {
+ depths.x = texture(shadowTexture, get_texco(cos, concentric[i+0])).r;
+ depths.y = texture(shadowTexture, get_texco(cos, concentric[i+1])).r;
+ depths.z = texture(shadowTexture, get_texco(cos, concentric[i+2])).r;
+ depths.w = texture(shadowTexture, get_texco(cos, concentric[i+3])).r;
+ accum = ln_space_prefilter(1.0, accum, shadowInvSampleCount, depths);
+ }
+
+ accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.y);
+ accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.z);
+ accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.w);
+ FragColor = accum.xxxx;
+
+#else /* VSM */
+ vec2 accum = vec2(0.0);
+
+ /* disc blur. */
+ vec4 depths1, depths2;
+ for (int i = 0; i < shadowSampleCount && i < CONCENTRIC_SAMPLE_NUM; i += 4) {
+ depths1.xy = texture(shadowTexture, get_texco(cos, concentric[i+0])).rg;
+ depths1.zw = texture(shadowTexture, get_texco(cos, concentric[i+1])).rg;
+ depths2.xy = texture(shadowTexture, get_texco(cos, concentric[i+2])).rg;
+ depths2.zw = texture(shadowTexture, get_texco(cos, concentric[i+3])).rg;
+ accum += depths1.xy + depths1.zw + depths2.xy + depths2.zw;
+ }
+
+ FragColor = accum.xyxy * shadowInvSampleCount;
+#endif
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
new file mode 100644
index 00000000000..777902ccba8
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ShadowModelMatrix;
+#ifdef MESH_SHADER
+uniform mat3 WorldNormalMatrix;
+#endif
+
+in vec3 pos;
+#ifdef MESH_SHADER
+in vec3 nor;
+#endif
+
+out vec4 vPos;
+#ifdef MESH_SHADER
+out vec3 vNor;
+#endif
+
+flat out int face;
+
+void main() {
+ vPos = ShadowModelMatrix * vec4(pos, 1.0);
+ face = gl_InstanceID;
+
+#ifdef MESH_SHADER
+ vNor = WorldNormalMatrix * nor;
+#ifdef ATTRIB
+ pass_attrib(pos);
+#endif
+#endif
+}
diff --git a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl
new file mode 100644
index 00000000000..92287d2ecbc
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl
@@ -0,0 +1,73 @@
+/* ------------ Refraction ------------ */
+
+#define BTDF_BIAS 0.85
+
+vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float roughnessSquared, vec3 rand, float ofs)
+{
+ float a2 = max(5e-6, roughnessSquared * roughnessSquared);
+ float jitter = fract(rand.x + ofs);
+
+ /* Importance sampling bias */
+ rand.x = mix(rand.x, 0.0, BTDF_BIAS);
+
+ vec3 T, B;
+ float NH;
+ make_orthonormal_basis(N, T, B);
+ vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */
+ float pdf = pdf_ggx_reflect(NH, a2);
+
+ /* If ray is bad (i.e. going below the plane) regenerate. */
+ if (F_eta(ior, dot(H, V)) < 1.0) {
+ H = sample_ggx(rand * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */
+ pdf = pdf_ggx_reflect(NH, a2);
+ }
+
+ vec3 vV = viewCameraVec;
+ float eta = 1.0/ior;
+ if (dot(H, V) < 0.0) {
+ H = -H;
+ eta = ior;
+ }
+
+ vec3 R = refract(-V, H, 1.0 / ior);
+
+ R = transform_direction(ViewMatrix, R);
+
+ vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, jitter, ssrQuality, roughnessSquared, false);
+
+ if ((hit_pos.z > 0.0) && (F_eta(ior, dot(H, V)) < 1.0)) {
+ hit_pos = get_view_space_from_depth(hit_pos.xy, hit_pos.z);
+ float hit_dist = distance(hit_pos, viewPosition);
+
+ float cone_cos = cone_cosine(roughnessSquared);
+ float cone_tan = sqrt(1 - cone_cos * cone_cos) / cone_cos;
+
+ /* Empirical fit for refraction. */
+ /* TODO find a better fit or precompute inside the LUT. */
+ cone_tan *= 0.5 * fast_sqrt(f0_from_ior((ior < 1.0) ? 1.0 / ior : ior));
+
+ float cone_footprint = hit_dist * cone_tan;
+
+ /* find the offset in screen space by multiplying a point
+ * in camera space at the depth of the point by the projection matrix. */
+ float homcoord = ProjectionMatrix[2][3] * hit_pos.z + ProjectionMatrix[3][3];
+ /* UV space footprint */
+ cone_footprint = BTDF_BIAS * 0.5 * max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * cone_footprint / homcoord;
+
+ vec2 hit_uvs = project_point(ProjectionMatrix, hit_pos).xy * 0.5 + 0.5;
+
+ /* Texel footprint */
+ vec2 texture_size = vec2(textureSize(colorBuffer, 0).xy);
+ float mip = clamp(log2(cone_footprint * max(texture_size.x, texture_size.y)), 0.0, 9.0);
+
+ /* Correct UVs for mipmaping mis-alignment */
+ hit_uvs *= mip_ratio_interp(mip);
+
+ vec3 spec = textureLod(colorBuffer, hit_uvs, mip).xyz;
+ float mask = screen_border_mask(hit_uvs);
+
+ return vec4(spec, mask);
+ }
+
+ return vec4(0.0);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
new file mode 100644
index 00000000000..00e01e753f9
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
@@ -0,0 +1,66 @@
+
+/* Based on Frosbite Unified Volumetric.
+ * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
+
+#define NODETREE_EXEC
+
+uniform ivec3 volumeTextureSize;
+uniform vec3 volume_jitter;
+
+#ifdef MESH_SHADER
+uniform mat4 volumeObjectMatrix;
+uniform vec3 volumeOrcoLoc;
+uniform vec3 volumeOrcoSize;
+#endif
+
+flat in int slice;
+
+/* Warning: theses are not attributes, theses are global vars. */
+vec3 worldPosition = vec3(0.0);
+vec3 viewPosition = vec3(0.0);
+vec3 viewNormal = vec3(0.0);
+#ifdef MESH_SHADER
+vec3 volumeObjectLocalCoord = vec3(0.0);
+#endif
+
+layout(location = 0) out vec4 volumeScattering;
+layout(location = 1) out vec4 volumeExtinction;
+layout(location = 2) out vec4 volumeEmissive;
+layout(location = 3) out vec4 volumePhase;
+
+/* Store volumetric properties into the froxel textures. */
+
+void main()
+{
+ ivec3 volume_cell = ivec3(gl_FragCoord.xy, slice);
+ vec3 ndc_cell = volume_to_ndc((vec3(volume_cell) + volume_jitter) / volumeTextureSize);
+
+ viewPosition = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z);
+ worldPosition = transform_point(ViewMatrixInverse, viewPosition);
+#ifdef MESH_SHADER
+ volumeObjectLocalCoord = transform_point(volumeObjectMatrix, worldPosition);
+ volumeObjectLocalCoord = (volumeObjectLocalCoord - volumeOrcoLoc + volumeOrcoSize) / (volumeOrcoSize * 2.0);
+
+ if (any(lessThan(volumeObjectLocalCoord, vec3(0.0))) ||
+ any(greaterThan(volumeObjectLocalCoord, vec3(1.0))))
+ discard;
+#endif
+
+#ifdef CLEAR
+ Closure cl = CLOSURE_DEFAULT;
+#else
+ Closure cl = nodetree_exec();
+#endif
+
+ volumeScattering = vec4(cl.scatter, 1.0);
+ volumeExtinction = vec4(max(vec3(1e-4), cl.absorption + cl.scatter), 1.0);
+ volumeEmissive = vec4(cl.emission, 1.0);
+
+ /* Do not add phase weight if no scattering. */
+ if (all(equal(cl.scatter, vec3(0.0)))) {
+ volumePhase = vec4(0.0);
+ }
+ else {
+ volumePhase = vec4(cl.anisotropy, vec3(1.0));
+ }
+}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl
new file mode 100644
index 00000000000..208e8165689
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl
@@ -0,0 +1,52 @@
+
+#ifdef MESH_SHADER
+/* TODO tight slices */
+layout(triangles) in;
+layout(triangle_strip, max_vertices=3) out;
+#else /* World */
+layout(triangles) in;
+layout(triangle_strip, max_vertices=3) out;
+#endif
+
+in vec4 vPos[];
+
+flat out int slice;
+
+#ifdef MESH_SHADER
+/* TODO tight slices */
+void main() {
+ gl_Layer = slice = int(vPos[0].z);
+
+ gl_Position = vPos[0].xyww;
+ EmitVertex();
+
+ gl_Position = vPos[1].xyww;
+ EmitVertex();
+
+ gl_Position = vPos[2].xyww;
+ EmitVertex();
+
+ EndPrimitive();
+}
+
+#else /* World */
+
+/* This is just a pass-through geometry shader that send the geometry
+ * to the layer corresponding to it's depth. */
+
+void main() {
+ gl_Layer = slice = int(vPos[0].z);
+
+ gl_Position = vPos[0].xyww;
+ EmitVertex();
+
+ gl_Position = vPos[1].xyww;
+ EmitVertex();
+
+ gl_Position = vPos[2].xyww;
+ EmitVertex();
+
+ EndPrimitive();
+}
+
+#endif
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
new file mode 100644
index 00000000000..15e9696a4c5
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
@@ -0,0 +1,63 @@
+
+/* Based on Frosbite Unified Volumetric.
+ * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
+
+/* Step 3 : Integrate for each froxel the final amount of light
+ * scattered back to the viewer and the amout of transmittance. */
+
+uniform sampler3D volumeScattering; /* Result of the scatter step */
+uniform sampler3D volumeExtinction;
+
+flat in int slice;
+
+layout(location = 0) out vec4 finalScattering;
+layout(location = 1) out vec4 finalTransmittance;
+
+void main()
+{
+ /* Start with full transmittance and no scattered light. */
+ finalScattering = vec4(0.0);
+ finalTransmittance = vec4(1.0);
+
+ vec3 tex_size = vec3(textureSize(volumeScattering, 0).xyz);
+
+ /* Compute view ray. */
+ vec2 uvs = gl_FragCoord.xy / tex_size.xy;
+ vec3 ndc_cell = volume_to_ndc(vec3(uvs, 1e-5));
+ vec3 view_cell = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z);
+
+ /* Ortho */
+ float prev_ray_len = view_cell.z;
+ float orig_ray_len = 1.0;
+
+ /* Persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ prev_ray_len = length(view_cell);
+ orig_ray_len = prev_ray_len / view_cell.z;
+ }
+
+ /* Without compute shader and arbitrary write we need to
+ * accumulate from the beginning of the ray for each cell. */
+ float integration_end = float(slice);
+ for (int i = 0; i < slice; ++i) {
+ ivec3 volume_cell = ivec3(gl_FragCoord.xy, i);
+
+ vec4 Lscat = texelFetch(volumeScattering, volume_cell, 0);
+ vec4 s_extinction = texelFetch(volumeExtinction, volume_cell, 0);
+
+ float cell_depth = volume_z_to_view_z((float(i) + 1.0) / tex_size.z);
+ float ray_len = orig_ray_len * cell_depth;
+
+ /* Evaluate Scattering */
+ float s_len = abs(ray_len - prev_ray_len);
+ prev_ray_len = ray_len;
+ vec4 Tr = exp(-s_extinction * s_len);
+
+ /* integrate along the current step segment */
+ Lscat = (Lscat - Lscat * Tr) / s_extinction;
+ /* accumulate and also take into account the transmittance from previous steps */
+ finalScattering += finalTransmittance * Lscat;
+
+ finalTransmittance *= Tr;
+ }
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
new file mode 100644
index 00000000000..1376c53d633
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
@@ -0,0 +1,155 @@
+
+/* Based on Frosbite Unified Volumetric.
+ * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
+
+uniform float volume_light_clamp;
+
+uniform vec3 volume_param; /* Parameters to the volume Z equation */
+
+uniform vec2 volume_uv_ratio; /* To convert volume uvs to screen uvs */
+
+/* Volume slice to view space depth. */
+float volume_z_to_view_z(float z)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ /* Exponential distribution */
+ return (exp2(z / volume_param.z) - volume_param.x) / volume_param.y;
+ }
+ else {
+ /* Linear distribution */
+ return mix(volume_param.x, volume_param.y, z);
+ }
+}
+
+float view_z_to_volume_z(float depth)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ /* Exponential distribution */
+ return volume_param.z * log2(depth * volume_param.y + volume_param.x);
+ }
+ else {
+ /* Linear distribution */
+ return (depth - volume_param.x) * volume_param.z;
+ }
+}
+
+/* Volume texture normalized coordinates to NDC (special range [0, 1]). */
+vec3 volume_to_ndc(vec3 cos)
+{
+ cos.z = volume_z_to_view_z(cos.z);
+ cos.z = get_depth_from_view_z(cos.z);
+ cos.xy /= volume_uv_ratio;
+ return cos;
+}
+
+vec3 ndc_to_volume(vec3 cos)
+{
+ cos.z = get_view_z_from_depth(cos.z);
+ cos.z = view_z_to_volume_z(cos.z);
+ cos.xy *= volume_uv_ratio;
+ return cos;
+}
+
+float phase_function_isotropic()
+{
+ return 1.0 / (4.0 * M_PI);
+}
+
+float phase_function(vec3 v, vec3 l, float g)
+{
+ /* Henyey-Greenstein */
+ float cos_theta = dot(v, l);
+ g = clamp(g, -1.0 + 1e-3, 1.0 - 1e-3);
+ float sqr_g = g * g;
+ return (1- sqr_g) / max(1e-8, 4.0 * M_PI * pow(1 + sqr_g - 2 * g * cos_theta, 3.0 / 2.0));
+}
+
+#ifdef LAMPS_LIB
+vec3 light_volume(LightData ld, vec4 l_vector)
+{
+ float power;
+ /* TODO : Area lighting ? */
+ /* XXX : Removing Area Power. */
+ /* TODO : put this out of the shader. */
+ if (ld.l_type == AREA) {
+ power = 0.0962 * (ld.l_sizex * ld.l_sizey * 4.0 * M_PI);
+ }
+ else if (ld.l_type == SUN) {
+ power = 1.0;
+ }
+ else {
+ power = 0.0248 * (4.0 * ld.l_radius * ld.l_radius * M_PI * M_PI);
+ }
+
+ /* OPTI: find a better way than calculating this on the fly */
+ float lum = dot(ld.l_color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
+ vec3 tint = (lum > 0.0) ? ld.l_color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
+
+ power /= (l_vector.w * l_vector.w);
+
+ lum = min(lum * power, volume_light_clamp);
+
+ return tint * lum;
+}
+
+#define VOLUMETRIC_SHADOW_MAX_STEP 32.0
+
+uniform float volume_shadows_steps;
+
+vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction)
+{
+ /* Waiting for proper volume shadowmaps and out of frustum shadow map. */
+ vec3 ndc = project_point(ViewProjectionMatrix, wpos);
+ vec3 volume_co = ndc_to_volume(ndc * 0.5 + 0.5);
+
+ /* Let the texture be clamped to edge. This reduce visual glitches. */
+ return texture(volume_extinction, volume_co).rgb;
+}
+
+vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D volume_extinction)
+{
+#if defined(VOLUME_SHADOW)
+ /* Heterogeneous volume shadows */
+ float dd = l_vector.w / volume_shadows_steps;
+ vec3 L = l_vector.xyz * l_vector.w;
+ vec3 shadow = vec3(1.0);
+ for (float s = 0.5; s < VOLUMETRIC_SHADOW_MAX_STEP && s < (volume_shadows_steps - 0.1); s += 1.0) {
+ vec3 pos = ray_wpos + L * (s / volume_shadows_steps);
+ vec3 s_extinction = participating_media_extinction(pos, volume_extinction);
+ shadow *= exp(-s_extinction * dd);
+ }
+ return shadow;
+#else
+ return vec3(1.0);
+#endif /* VOLUME_SHADOW */
+}
+#endif
+
+#ifdef IRRADIANCE_LIB
+vec3 irradiance_volumetric(vec3 wpos)
+{
+#ifdef IRRADIANCE_HL2
+ IrradianceData ir_data = load_irradiance_cell(0, vec3(1.0));
+ vec3 irradiance = ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2];
+ ir_data = load_irradiance_cell(0, vec3(-1.0));
+ irradiance += ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2];
+ irradiance *= 0.16666666; /* 1/6 */
+ return irradiance;
+#else
+ return vec3(0.0);
+#endif
+}
+#endif
+
+uniform sampler3D inScattering;
+uniform sampler3D inTransmittance;
+
+vec4 volumetric_resolve(vec4 scene_color, vec2 frag_uvs, float frag_depth)
+{
+ vec3 volume_cos = ndc_to_volume(vec3(frag_uvs, frag_depth));
+
+ vec3 scattering = texture(inScattering, volume_cos).rgb;
+ vec3 transmittance = texture(inTransmittance, volume_cos).rgb;
+
+ return vec4(scene_color.rgb * transmittance + scattering, scene_color.a);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl
new file mode 100644
index 00000000000..0115b2cb99e
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl
@@ -0,0 +1,21 @@
+
+/* Based on Frosbite Unified Volumetric.
+ * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
+
+/* Step 4 : Apply final integration on top of the scene color.
+ * Note that we do the blending ourself instead of relying
+ * on hardware blending which would require 2 pass. */
+
+uniform sampler2D inSceneColor;
+uniform sampler2D inSceneDepth;
+
+out vec4 FragColor;
+
+void main()
+{
+ vec2 uvs = gl_FragCoord.xy / vec2(textureSize(inSceneDepth, 0));
+ vec4 scene_color = texture(inSceneColor, uvs);
+ float scene_depth = texture(inSceneDepth, uvs).r;
+
+ FragColor = volumetric_resolve(scene_color, uvs, scene_depth);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl
new file mode 100644
index 00000000000..ea402ff3d99
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl
@@ -0,0 +1,83 @@
+
+/* Based on Frosbite Unified Volumetric.
+ * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
+
+/* Step 2 : Evaluate all light scattering for each froxels.
+ * Also do the temporal reprojection to fight aliasing artifacts. */
+
+uniform sampler3D volumeScattering;
+uniform sampler3D volumeExtinction;
+uniform sampler3D volumeEmission;
+uniform sampler3D volumePhase;
+
+uniform sampler3D historyScattering;
+uniform sampler3D historyTransmittance;
+
+uniform vec3 volume_jitter;
+uniform float volume_history_alpha;
+uniform int light_count;
+uniform mat4 PastViewProjectionMatrix;
+
+flat in int slice;
+
+layout(location = 0) out vec4 outScattering;
+layout(location = 1) out vec4 outTransmittance;
+
+#define VOLUME_LIGHTING
+
+void main()
+{
+ vec3 volume_tex_size = vec3(textureSize(volumeScattering, 0));
+ ivec3 volume_cell = ivec3(gl_FragCoord.xy, slice);
+
+ /* Emission */
+ outScattering = texelFetch(volumeEmission, volume_cell, 0);
+ outTransmittance = texelFetch(volumeExtinction, volume_cell, 0);
+ vec3 s_scattering = texelFetch(volumeScattering, volume_cell, 0).rgb;
+ vec3 volume_ndc = volume_to_ndc((vec3(volume_cell) + volume_jitter) / volume_tex_size);
+ vec3 worldPosition = get_world_space_from_depth(volume_ndc.xy, volume_ndc.z);
+ vec3 wdir = cameraVec;
+
+ vec2 phase = texelFetch(volumePhase, volume_cell, 0).rg;
+ float s_anisotropy = phase.x / max(1.0, phase.y);
+
+ /* Environment : Average color. */
+ outScattering.rgb += irradiance_volumetric(worldPosition) * s_scattering * phase_function_isotropic();
+
+#ifdef VOLUME_LIGHTING /* Lights */
+ for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
+
+ LightData ld = lights_data[i];
+
+ vec4 l_vector;
+ l_vector.xyz = (ld.l_type == SUN) ? -ld.l_forward : ld.l_position - worldPosition;
+ l_vector.w = length(l_vector.xyz);
+
+ float Vis = light_visibility(ld, worldPosition, l_vector);
+
+ vec3 Li = light_volume(ld, l_vector) * light_volume_shadow(ld, worldPosition, l_vector, volumeExtinction);
+
+ outScattering.rgb += Li * Vis * s_scattering * phase_function(-wdir, l_vector.xyz / l_vector.w, s_anisotropy);
+ }
+#endif
+
+ /* Temporal supersampling */
+ /* Note : this uses the cell non-jittered position (texel center). */
+ vec3 curr_ndc = volume_to_ndc(vec3(gl_FragCoord.xy, float(slice) + 0.5) / volume_tex_size);
+ vec3 wpos = get_world_space_from_depth(curr_ndc.xy, curr_ndc.z);
+ vec3 prev_ndc = project_point(PastViewProjectionMatrix, wpos);
+ vec3 prev_volume = ndc_to_volume(prev_ndc * 0.5 + 0.5);
+
+ if ((volume_history_alpha > 0.0) && all(greaterThan(prev_volume, vec3(0.0))) && all(lessThan(prev_volume, vec3(1.0)))) {
+ vec4 h_Scattering = texture(historyScattering, prev_volume);
+ vec4 h_Transmittance = texture(historyTransmittance, prev_volume);
+ outScattering = mix(outScattering, h_Scattering, volume_history_alpha);
+ outTransmittance = mix(outTransmittance, h_Transmittance, volume_history_alpha);
+ }
+
+ /* Catch NaNs */
+ if (any(isnan(outScattering)) || any(isnan(outTransmittance))) {
+ outScattering = vec4(0.0);
+ outTransmittance = vec4(1.0);
+ }
+}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
new file mode 100644
index 00000000000..a99acd41fbd
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
@@ -0,0 +1,27 @@
+
+out vec4 vPos;
+
+void main()
+{
+ /* Generate Triangle : less memory fetches from a VBO */
+ int v_id = gl_VertexID % 3; /* Vertex Id */
+ int t_id = gl_VertexID / 3; /* Triangle Id */
+
+ /* Crappy diagram
+ * ex 1
+ * | \
+ * | \
+ * 1 | \
+ * | \
+ * | \
+ * 0 | \
+ * | \
+ * | \
+ * -1 0 --------------- 2
+ * -1 0 1 ex
+ **/
+ vPos.x = float(v_id / 2) * 4.0 - 1.0; /* int divisor round down */
+ vPos.y = float(v_id % 2) * 4.0 - 1.0;
+ vPos.z = float(t_id);
+ vPos.w = 1.0;
+}
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
new file mode 100644
index 00000000000..851d0ef9eb7
--- /dev/null
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2017, 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 external_engine.c
+ * \ingroup draw_engine
+ *
+ * Base engine for external render engines.
+ * We use it for depth and non-mesh objects.
+ */
+
+#include "DRW_render.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_icons.h"
+#include "BKE_idprop.h"
+#include "BKE_main.h"
+
+#include "ED_view3d.h"
+#include "ED_screen.h"
+
+#include "GPU_glew.h"
+#include "GPU_matrix.h"
+#include "GPU_shader.h"
+#include "GPU_viewport.h"
+
+#include "external_engine.h"
+/* Shaders */
+
+#define EXTERNAL_ENGINE "BLENDER_EXTERNAL"
+
+/* *********** LISTS *********** */
+
+/* GPUViewport.storage
+ * Is freed everytime the viewport engine changes */
+typedef struct EXTERNAL_Storage {
+ int dummy;
+} EXTERNAL_Storage;
+
+typedef struct EXTERNAL_StorageList {
+ struct EXTERNAL_Storage *storage;
+ struct EXTERNAL_PrivateData *g_data;
+} EXTERNAL_StorageList;
+
+typedef struct EXTERNAL_FramebufferList {
+ struct GPUFrameBuffer *default_fb;
+} EXTERNAL_FramebufferList;
+
+typedef struct EXTERNAL_TextureList {
+ /* default */
+ struct GPUTexture *depth;
+} EXTERNAL_TextureList;
+
+typedef struct EXTERNAL_PassList {
+ struct DRWPass *depth_pass;
+} EXTERNAL_PassList;
+
+typedef struct EXTERNAL_Data {
+ void *engine_type;
+ EXTERNAL_FramebufferList *fbl;
+ EXTERNAL_TextureList *txl;
+ EXTERNAL_PassList *psl;
+ EXTERNAL_StorageList *stl;
+ char info[GPU_INFO_SIZE];
+} EXTERNAL_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Depth Pre Pass */
+ struct GPUShader *depth_sh;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct EXTERNAL_PrivateData {
+ DRWShadingGroup *depth_shgrp;
+} EXTERNAL_PrivateData; /* Transient data */
+
+/* Functions */
+
+static void external_engine_init(void *UNUSED(vedata))
+{
+ /* Depth prepass */
+ if (!e_data.depth_sh) {
+ e_data.depth_sh = DRW_shader_create_3D_depth_only();
+ }
+}
+
+static void external_cache_init(void *vedata)
+{
+ EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl;
+ EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ /* Depth Pass */
+ {
+ psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
+ }
+}
+
+static void external_cache_populate(void *vedata, Object *ob)
+{
+ EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl;
+
+ if (!DRW_object_is_renderable(ob))
+ return;
+
+ struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
+ if (geom) {
+ /* Depth Prepass */
+ DRW_shgroup_call_add(stl->g_data->depth_shgrp, geom, ob->obmat);
+ }
+}
+
+static void external_cache_finish(void *UNUSED(vedata))
+{
+}
+
+static void external_draw_scene_do(void *vedata)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ ARegion *ar = draw_ctx->ar;
+ RenderEngineType *type;
+
+ DRW_state_reset_ex(DRW_STATE_DEFAULT & ~DRW_STATE_DEPTH_LESS);
+
+ /* Create render engine. */
+ if (!rv3d->render_engine) {
+ RenderEngineType *engine_type = draw_ctx->engine_type;
+
+ if (!(engine_type->view_update && engine_type->render_to_view)) {
+ return;
+ }
+
+ RenderEngine *engine = RE_engine_create_ex(engine_type, true);
+ engine->tile_x = scene->r.tilex;
+ engine->tile_y = scene->r.tiley;
+ engine_type->view_update(engine, draw_ctx->evil_C);
+ rv3d->render_engine = engine;
+ }
+
+ /* Rendered draw. */
+ gpuPushProjectionMatrix();
+ ED_region_pixelspace(ar);
+
+ /* Render result draw. */
+ type = rv3d->render_engine->type;
+ type->render_to_view(rv3d->render_engine, draw_ctx->evil_C);
+
+ gpuPopProjectionMatrix();
+
+ /* Set render info. */
+ EXTERNAL_Data *data = vedata;
+ if (rv3d->render_engine->text[0] != '\0') {
+ BLI_strncpy(data->info, rv3d->render_engine->text, sizeof(data->info));
+ }
+ else {
+ data->info[0] = '\0';
+ }
+}
+
+static void external_draw_scene(void *vedata)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl;
+
+ /* Will be NULL during OpenGL render.
+ * OpenGL render is used for quick preview (thumbnails or sequencer preview)
+ * where using the rendering engine to preview doesn't make so much sense. */
+ if (draw_ctx->evil_C) {
+ external_draw_scene_do(vedata);
+ }
+ DRW_draw_pass(psl->depth_pass);
+}
+
+static void external_engine_free(void)
+{
+ /* All shaders are builtin. */
+}
+
+static const DrawEngineDataSize external_data_size = DRW_VIEWPORT_DATA_SIZE(EXTERNAL_Data);
+
+DrawEngineType draw_engine_external_type = {
+ NULL, NULL,
+ N_("External"),
+ &external_data_size,
+ &external_engine_init,
+ &external_engine_free,
+ &external_cache_init,
+ &external_cache_populate,
+ &external_cache_finish,
+ NULL,
+ &external_draw_scene,
+ NULL,
+ NULL,
+};
+
+/* Note: currently unused, we should not register unless we want to see this when debugging the view. */
+
+RenderEngineType DRW_engine_viewport_external_type = {
+ NULL, NULL,
+ EXTERNAL_ENGINE, N_("External"), RE_INTERNAL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ &draw_engine_external_type,
+ {NULL, NULL, NULL}
+};
+
+#undef EXTERNAL_ENGINE
diff --git a/source/blender/draw/engines/external/external_engine.h b/source/blender/draw/engines/external/external_engine.h
new file mode 100644
index 00000000000..1789fb67efe
--- /dev/null
+++ b/source/blender/draw/engines/external/external_engine.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017, 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 external_engine.h
+ * \ingroup draw_engine
+ */
+
+#ifndef __EXTERNAL_ENGINE_H__
+#define __EXTERNAL_ENGINE_H__
+
+extern RenderEngineType DRW_engine_viewport_external_type;
+
+#endif /* __EXTERNAL_ENGINE_H__ */
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
new file mode 100644
index 00000000000..0753dbc7a1a
--- /dev/null
+++ b/source/blender/draw/intern/DRW_render.h
@@ -0,0 +1,458 @@
+/*
+ * 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 "BLI_listbase.h"
+#include "BLI_math_matrix.h"
+#include "BLI_math_vector.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_layer.h"
+#include "BKE_material.h"
+#include "BKE_scene.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_common.h"
+#include "draw_cache.h"
+#include "draw_view.h"
+
+#include "draw_manager_profiling.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RE_engine.h"
+
+struct bContext;
+struct GPUFrameBuffer;
+struct GPUShader;
+struct GPUMaterial;
+struct GPUTexture;
+struct GPUUniformBuffer;
+struct Object;
+struct Gwn_Batch;
+struct DefaultFramebufferList;
+struct DefaultTextureList;
+struct DRWTextStore;
+struct LampEngineData;
+struct RenderEngineType;
+struct ViewportEngineData;
+struct ViewportEngineData_Info;
+
+typedef struct DRWUniform DRWUniform;
+typedef struct DRWInterface DRWInterface;
+typedef struct DRWPass DRWPass;
+typedef struct DRWShadingGroup DRWShadingGroup;
+
+/* declare members as empty (unused) */
+typedef char DRWViewportEmptyList;
+
+#define DRW_VIEWPORT_LIST_SIZE(list) \
+ (sizeof(list) == sizeof(DRWViewportEmptyList) ? 0 : ((sizeof(list)) / sizeof(void *)))
+
+/* Unused members must be either pass list or 'char *' when not usd. */
+#define DRW_VIEWPORT_DATA_SIZE(ty) { \
+ DRW_VIEWPORT_LIST_SIZE(*(((ty *)NULL)->fbl)), \
+ DRW_VIEWPORT_LIST_SIZE(*(((ty *)NULL)->txl)), \
+ DRW_VIEWPORT_LIST_SIZE(*(((ty *)NULL)->psl)), \
+ DRW_VIEWPORT_LIST_SIZE(*(((ty *)NULL)->stl)) \
+}
+
+/* Use of multisample framebuffers. */
+#define MULTISAMPLE_SYNC_ENABLE(dfbl) { \
+ if (dfbl->multisample_fb != NULL) { \
+ DRW_stats_query_start("Multisample Blit"); \
+ DRW_framebuffer_blit(dfbl->default_fb, dfbl->multisample_fb, false, false); \
+ DRW_framebuffer_blit(dfbl->default_fb, dfbl->multisample_fb, true, false); \
+ DRW_framebuffer_bind(dfbl->multisample_fb); \
+ DRW_stats_query_end(); \
+ } \
+}
+
+#define MULTISAMPLE_SYNC_DISABLE(dfbl) { \
+ if (dfbl->multisample_fb != NULL) { \
+ DRW_stats_query_start("Multisample Resolve"); \
+ DRW_framebuffer_blit(dfbl->multisample_fb, dfbl->default_fb, false, false); \
+ DRW_framebuffer_blit(dfbl->multisample_fb, dfbl->default_fb, true, false); \
+ DRW_framebuffer_bind(dfbl->default_fb); \
+ DRW_stats_query_end(); \
+ } \
+}
+
+
+
+typedef struct DrawEngineDataSize {
+ int fbl_len;
+ int txl_len;
+ int psl_len;
+ int stl_len;
+} DrawEngineDataSize;
+
+typedef struct DrawEngineType {
+ struct DrawEngineType *next, *prev;
+
+ char idname[32];
+
+ const DrawEngineDataSize *vedata_size;
+
+ void (*engine_init)(void *vedata);
+ void (*engine_free)(void);
+
+ void (*cache_init)(void *vedata);
+ void (*cache_populate)(void *vedata, struct Object *ob);
+ void (*cache_finish)(void *vedata);
+
+ void (*draw_background)(void *vedata);
+ void (*draw_scene)(void *vedata);
+
+ void (*view_update)(void *vedata);
+ void (*id_update)(void *vedata, struct ID *id);
+} DrawEngineType;
+
+#ifndef __DRW_ENGINE_H__
+/* Buffer and textures used by the viewport by default */
+typedef struct DefaultFramebufferList {
+ struct GPUFrameBuffer *default_fb;
+ struct GPUFrameBuffer *multisample_fb;
+} DefaultFramebufferList;
+
+typedef struct DefaultTextureList {
+ struct GPUTexture *color;
+ struct GPUTexture *depth;
+ struct GPUTexture *multisample_color;
+ struct GPUTexture *multisample_depth;
+} DefaultTextureList;
+#endif
+
+/* Textures */
+
+typedef enum {
+ DRW_TEX_RGBA_8,
+ DRW_TEX_RGBA_16,
+ DRW_TEX_RGBA_32,
+ DRW_TEX_RGB_11_11_10,
+ 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_24_STENCIL_8,
+ DRW_TEX_DEPTH_32,
+} DRWTextureFormat;
+
+typedef enum {
+ DRW_TEX_FILTER = (1 << 0),
+ DRW_TEX_WRAP = (1 << 1),
+ DRW_TEX_COMPARE = (1 << 2),
+ DRW_TEX_MIPMAP = (1 << 3),
+ DRW_TEX_TEMP = (1 << 4),
+} 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 format, DRWTextureFlag flags, const float *fpixels);
+struct GPUTexture *DRW_texture_create_3D(
+ int w, int h, int d, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
+struct GPUTexture *DRW_texture_create_cube(
+ int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
+void DRW_texture_generate_mipmaps(struct GPUTexture *tex);
+void DRW_texture_update(struct GPUTexture *tex, const float *pixels);
+void DRW_texture_free(struct GPUTexture *tex);
+#define DRW_TEXTURE_FREE_SAFE(tex) do { \
+ if (tex != NULL) { \
+ DRW_texture_free(tex); \
+ tex = NULL; \
+ } \
+} while (0)
+
+/* 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);
+#define DRW_UBO_FREE_SAFE(ubo) do { \
+ if (ubo != NULL) { \
+ DRW_uniformbuffer_free(ubo); \
+ ubo = NULL; \
+ } \
+} while (0)
+
+/* Buffers */
+#define MAX_FBO_TEX 5
+
+typedef struct DRWFboTexture {
+ struct GPUTexture **tex;
+ int format;
+ DRWTextureFlag flag;
+} DRWFboTexture;
+
+void DRW_framebuffer_init(
+ struct GPUFrameBuffer **fb, void *engine_type, int width, int height,
+ DRWFboTexture textures[MAX_FBO_TEX], int textures_len);
+void DRW_framebuffer_bind(struct GPUFrameBuffer *fb);
+void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth);
+void DRW_framebuffer_read_data(int x, int y, int w, int h, int channels, int slot, float *data);
+void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
+void DRW_framebuffer_texture_layer_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
+void DRW_framebuffer_cubeface_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
+void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
+void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth, bool stencil);
+void DRW_framebuffer_recursive_downsample(
+ struct GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
+ void (*callback)(void *userData, int level), void *userData);
+void DRW_framebuffer_viewport_size(struct GPUFrameBuffer *fb_read, int x, int y, int w, int h);
+void DRW_framebuffer_free(struct GPUFrameBuffer *fb);
+#define DRW_FRAMEBUFFER_FREE_SAFE(fb) do { \
+ if (fb != NULL) { \
+ DRW_framebuffer_free(fb); \
+ fb = NULL; \
+ } \
+} while (0)
+
+void DRW_transform_to_display(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_with_lib(
+ const char *vert, const char *geom, const char *frag, const char *lib, 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_fullscreen(const char *frag, const char *defines);
+struct GPUShader *DRW_shader_create_3D_depth_only(void);
+void DRW_shader_free(struct GPUShader *shader);
+#define DRW_SHADER_FREE_SAFE(shader) do { \
+ if (shader != NULL) { \
+ DRW_shader_free(shader); \
+ shader = NULL; \
+ } \
+} while (0)
+
+/* 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_DEPTH_GREATER = (1 << 4),
+ DRW_STATE_DEPTH_ALWAYS = (1 << 5),
+ DRW_STATE_CULL_BACK = (1 << 6),
+ DRW_STATE_CULL_FRONT = (1 << 7),
+ DRW_STATE_WIRE = (1 << 8),
+ DRW_STATE_WIRE_LARGE = (1 << 9),
+ DRW_STATE_POINT = (1 << 10),
+ DRW_STATE_STIPPLE_2 = (1 << 11),
+ DRW_STATE_STIPPLE_3 = (1 << 12),
+ DRW_STATE_STIPPLE_4 = (1 << 13),
+ DRW_STATE_BLEND = (1 << 14),
+ DRW_STATE_ADDITIVE = (1 << 15),
+ DRW_STATE_MULTIPLY = (1 << 16),
+ DRW_STATE_TRANSMISSION = (1 << 17),
+ DRW_STATE_CLIP_PLANES = (1 << 18),
+
+ DRW_STATE_WRITE_STENCIL = (1 << 27),
+ DRW_STATE_STENCIL_EQUAL = (1 << 28),
+} DRWState;
+
+#define DRW_STATE_DEFAULT (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS)
+
+
+DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
+DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass);
+DRWShadingGroup *DRW_shgroup_material_instance_create(
+ struct GPUMaterial *material, DRWPass *pass, struct Gwn_Batch *geom, struct Object *ob);
+DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(struct GPUMaterial *material, DRWPass *pass, int size);
+DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, struct Gwn_Batch *geom);
+DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass);
+DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass);
+DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int size);
+
+typedef void (DRWCallGenerateFn)(
+ DRWShadingGroup *shgroup,
+ void (*draw_fn)(DRWShadingGroup *shgroup, struct Gwn_Batch *geom),
+ void *user_data);
+
+void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *instances);
+
+void DRW_shgroup_free(struct DRWShadingGroup *shgroup);
+void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4]);
+void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, struct Gwn_Batch *geom, struct Object *ob);
+void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, struct Object *ob, float (*obmat)[4]);
+void DRW_shgroup_call_generate_add(
+ DRWShadingGroup *shgroup, DRWCallGenerateFn *geometry_fn, void *user_data, float (*obmat)[4]);
+void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *attr[], unsigned int attr_len);
+#define DRW_shgroup_call_dynamic_add(shgroup, ...) do { \
+ const void *array[] = {__VA_ARGS__}; \
+ DRW_shgroup_call_dynamic_add_array(shgroup, array, (sizeof(array) / sizeof(*array))); \
+} while (0)
+/* Use this only to make your instances selectable. */
+#define DRW_shgroup_call_dynamic_add_empty(shgroup) do { \
+ DRW_shgroup_call_dynamic_add_array(shgroup, NULL, 0); \
+} while (0)
+/* Use this to set a high number of instances. */
+void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, int count);
+
+void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state);
+void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state);
+void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, unsigned int mask);
+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);
+void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo);
+void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, struct GPUTexture **tex);
+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_short_to_int(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize);
+void DRW_shgroup_uniform_short_to_float(DRWShadingGroup *shgroup, const char *name, const short *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);
+void DRW_pass_foreach_shgroup(DRWPass *pass, void (*callback)(void *userData, DRWShadingGroup *shgrp), void *userData);
+void DRW_pass_sort_shgroup_z(DRWPass *pass);
+
+/* Viewport */
+typedef enum {
+ DRW_MAT_PERS = 0,
+ DRW_MAT_PERSINV,
+ DRW_MAT_VIEW,
+ DRW_MAT_VIEWINV,
+ DRW_MAT_WIN,
+ DRW_MAT_WININV,
+} DRWViewportMatrixType;
+
+void DRW_viewport_init(const bContext *C);
+void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type);
+void DRW_viewport_matrix_override_set(float mat[4][4], DRWViewportMatrixType type);
+void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type);
+const float *DRW_viewport_size_get(void);
+const float *DRW_viewport_screenvecs_get(void);
+const float *DRW_viewport_pixelsize_get(void);
+bool DRW_viewport_is_persp_get(void);
+
+struct DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void);
+struct DefaultTextureList *DRW_viewport_texture_list_get(void);
+
+void DRW_viewport_request_redraw(void);
+
+/* ViewLayers */
+void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type);
+void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*callback)(void *storage));
+
+/* Objects */
+void *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type);
+void **DRW_object_engine_data_ensure(
+ Object *ob, DrawEngineType *engine_type, void (*callback)(void *storage));
+struct LampEngineData *DRW_lamp_engine_data_ensure(Object *ob, struct RenderEngineType *engine_type);
+void DRW_lamp_engine_data_free(struct LampEngineData *led);
+
+/* Settings */
+bool DRW_object_is_renderable(struct Object *ob);
+bool DRW_object_is_flat_normal(const struct Object *ob);
+int DRW_object_is_mode_shade(const struct Object *ob);
+
+/* Draw commands */
+void DRW_draw_pass(DRWPass *pass);
+void DRW_draw_pass_subset(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group);
+
+void DRW_draw_text_cache_queue(struct DRWTextStore *dt);
+
+void DRW_draw_callbacks_pre_scene(void);
+void DRW_draw_callbacks_post_scene(void);
+
+int DRW_draw_region_engine_info_offset(void);
+void DRW_draw_region_engine_info(void);
+
+void DRW_state_reset_ex(DRWState state);
+void DRW_state_reset(void);
+
+void DRW_state_invert_facing(void);
+
+void DRW_state_clip_planes_add(float plane_eq[4]);
+void DRW_state_clip_planes_reset(void);
+
+/* Selection */
+void DRW_select_load_id(unsigned int id);
+
+/* Draw State */
+void DRW_state_dfdy_factors_get(float dfdyfac[2]);
+bool DRW_state_is_fbo(void);
+bool DRW_state_is_select(void);
+bool DRW_state_is_depth(void);
+bool DRW_state_is_image_render(void);
+bool DRW_state_is_scene_render(void);
+bool DRW_state_show_text(void);
+bool DRW_state_draw_support(void);
+
+struct DRWTextStore *DRW_state_text_cache_get(void);
+
+/* Avoid too many lookups while drawing */
+typedef struct DRWContextState {
+ struct ARegion *ar; /* 'CTX_wm_region(C)' */
+ struct RegionView3D *rv3d; /* 'CTX_wm_region_view3d(C)' */
+ struct View3D *v3d; /* 'CTX_wm_view3d(C)' */
+
+ struct Scene *scene; /* 'CTX_data_scene(C)' */
+ struct ViewLayer *view_layer; /* 'CTX_data_view_layer(C)' */
+
+ /* Use 'scene->obedit' for edit-mode */
+ struct Object *obact; /* 'OBACT' */
+
+ struct RenderEngineType *engine_type;
+
+ /* Last resort (some functions take this as an arg so we can't easily avoid).
+ * May be NULL when used for selection or depth buffer. */
+ const struct bContext *evil_C;
+} DRWContextState;
+
+const DRWContextState *DRW_context_state_get(void);
+
+#endif /* __DRW_RENDER_H__ */
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
new file mode 100644
index 00000000000..c7a88f7689e
--- /dev/null
+++ b/source/blender/draw/intern/draw_armature.c
@@ -0,0 +1,1442 @@
+/*
+ * 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_armature.c
+ * \ingroup draw
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_object_types.h"
+
+#include "DRW_render.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_dlrbTree.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_global.h"
+#include "BKE_modifier.h"
+#include "BKE_nla.h"
+#include "BKE_curve.h"
+
+#include "BIF_gl.h"
+
+#include "ED_armature.h"
+#include "ED_keyframes_draw.h"
+
+#include "GPU_select.h"
+
+#include "UI_resources.h"
+
+#include "draw_common.h"
+#include "draw_manager_text.h"
+
+#define BONE_VAR(eBone, pchan, var) ((eBone) ? (eBone->var) : (pchan->var))
+#define BONE_FLAG(eBone, pchan) ((eBone) ? (eBone->flag) : (pchan->bone->flag))
+
+/* For now just match 2.7x where possible. */
+// #define USE_SOLID_COLOR
+
+/* Reset for drawing each armature object */
+static struct {
+ /* Current armature object */
+ Object *ob;
+ /* Reset when changing current_armature */
+ DRWShadingGroup *bone_octahedral_solid;
+ DRWShadingGroup *bone_octahedral_wire;
+ DRWShadingGroup *bone_box_solid;
+ DRWShadingGroup *bone_box_wire;
+ DRWShadingGroup *bone_wire_wire;
+ DRWShadingGroup *bone_envelope_solid;
+ DRWShadingGroup *bone_envelope_distance;
+ DRWShadingGroup *bone_envelope_wire;
+ DRWShadingGroup *bone_envelope_head_wire;
+ DRWShadingGroup *bone_point_solid;
+ DRWShadingGroup *bone_point_wire;
+ DRWShadingGroup *bone_axes;
+ DRWShadingGroup *relationship_lines;
+
+ DRWPass *pass_bone_solid;
+ DRWPass *pass_bone_wire;
+ DRWPass *pass_bone_envelope;
+} g_data = {NULL};
+
+/* -------------------------------------------------------------------- */
+
+/** \name Shader Groups (DRW_shgroup)
+ * \{ */
+
+/* Octahedral */
+static void drw_shgroup_bone_octahedral_solid(const float (*bone_mat)[4], const float color[4])
+{
+ if (g_data.bone_octahedral_solid == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_octahedral_get();
+ g_data.bone_octahedral_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_solid, bone_mat, color);
+}
+
+static void drw_shgroup_bone_octahedral_wire(const float (*bone_mat)[4], const float color[4])
+{
+ if (g_data.bone_octahedral_wire == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_octahedral_wire_outline_get();
+ g_data.bone_octahedral_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_wire, bone_mat, color);
+}
+
+/* Box / B-Bone */
+static void drw_shgroup_bone_box_solid(const float (*bone_mat)[4], const float color[4])
+{
+ if (g_data.bone_box_solid == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_box_get();
+ g_data.bone_box_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_box_solid, bone_mat, color);
+}
+
+static void drw_shgroup_bone_box_wire(const float (*bone_mat)[4], const float color[4])
+{
+ if (g_data.bone_box_wire == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_box_wire_outline_get();
+ g_data.bone_box_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_box_wire, bone_mat, color);
+}
+
+/* Wire */
+static void drw_shgroup_bone_wire_wire(const float (*bone_mat)[4], const float color[4])
+{
+ if (g_data.bone_wire_wire == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_wire_wire_outline_get();
+ g_data.bone_wire_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_wire_wire, bone_mat, color);
+}
+
+/* Envelope */
+static void drw_shgroup_bone_envelope_distance(
+ const float (*bone_mat)[4], const float color[4],
+ const float *radius_head, const float *radius_tail, const float *distance)
+{
+ if (g_data.pass_bone_envelope != NULL) {
+ if (g_data.bone_envelope_distance == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_envelope_distance_outline_get();
+ /* Note: bone_wire draw pass is not really working, think we need another one here? */
+ g_data.bone_envelope_distance = shgroup_instance_bone_envelope_wire(g_data.pass_bone_envelope, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, bone_mat, color, radius_head, radius_tail, distance);
+ }
+}
+
+static void drw_shgroup_bone_envelope_solid(
+ const float (*bone_mat)[4], const float color[4],
+ const float *radius_head, const float *radius_tail)
+{
+ if (g_data.bone_envelope_solid == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_envelope_solid_get();
+ g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_envelope_solid, bone_mat, color, radius_head, radius_tail);
+}
+
+static void drw_shgroup_bone_envelope_wire(
+ const float (*bone_mat)[4], const float color[4],
+ const float *radius_head, const float *radius_tail, const float *distance)
+{
+ if (g_data.bone_envelope_wire == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_envelope_wire_outline_get();
+ g_data.bone_envelope_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_envelope_wire, bone_mat, color, radius_head, radius_tail, distance);
+}
+
+static void drw_shgroup_bone_envelope_head_wire(
+ const float (*bone_mat)[4], const float color[4],
+ const float *radius_head, const float *radius_tail, const float *distance)
+{
+ if (g_data.bone_envelope_head_wire == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_envelope_head_wire_outline_get();
+ g_data.bone_envelope_head_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_envelope_head_wire, bone_mat, color, radius_head, radius_tail, distance);
+}
+
+/* Custom (geometry) */
+
+static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4], const float color[4], Object *custom)
+{
+ /* grr, not re-using instances! */
+ struct Gwn_Batch *geom = DRW_cache_object_surface_get(custom);
+ if (geom) {
+ DRWShadingGroup *shgrp_geom_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
+ DRW_shgroup_call_dynamic_add(shgrp_geom_solid, bone_mat, color);
+ }
+}
+
+static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4], const float color[4], Object *custom)
+{
+ /* grr, not re-using instances! */
+ struct Gwn_Batch *geom = DRW_cache_object_wire_outline_get(custom);
+ if (geom) {
+ DRWShadingGroup *shgrp_geom_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ DRW_shgroup_call_dynamic_add(shgrp_geom_wire, bone_mat, color);
+ }
+}
+
+/* Head and tail sphere */
+static void drw_shgroup_bone_point_solid(const float (*bone_mat)[4], const float color[4])
+{
+ if (g_data.bone_point_solid == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_point_get();
+ g_data.bone_point_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, bone_mat, color);
+}
+
+static void drw_shgroup_bone_point_wire(const float (*bone_mat)[4], const float color[4])
+{
+ if (g_data.bone_point_wire == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_point_wire_outline_get();
+ g_data.bone_point_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, bone_mat, color);
+}
+
+/* Axes */
+static void drw_shgroup_bone_axes(const float (*bone_mat)[4], const float color[4])
+{
+ if (g_data.bone_axes == NULL) {
+ struct Gwn_Batch *geom = DRW_cache_bone_arrows_get();
+ g_data.bone_axes = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(g_data.bone_axes, bone_mat, color);
+}
+
+/* Relationship lines */
+static void UNUSED_FUNCTION(drw_shgroup_bone_relationship_lines)(const float head[3], const float tail[3])
+{
+ DRW_shgroup_call_dynamic_add(g_data.relationship_lines, head);
+ DRW_shgroup_call_dynamic_add(g_data.relationship_lines, tail);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Drawing Theme Helpers
+ *
+ * Note, this section is duplicate of code in 'drawarmature.c'.
+ *
+ * \{ */
+
+/* global here is reset before drawing each bone */
+struct {
+ const ThemeWireColor *bcolor;
+} g_color;
+
+/* values of colCode for set_pchan_color */
+enum {
+ PCHAN_COLOR_NORMAL = 0, /* normal drawing */
+ PCHAN_COLOR_SOLID, /* specific case where "solid" color is needed */
+ PCHAN_COLOR_CONSTS, /* "constraint" colors (which may/may-not be suppressed) */
+
+ PCHAN_COLOR_SPHEREBONE_BASE, /* for the 'stick' of sphere (envelope) bones */
+ PCHAN_COLOR_SPHEREBONE_END, /* for the ends of sphere (envelope) bones */
+ PCHAN_COLOR_LINEBONE /* for the middle of line-bones */
+};
+
+/* This function sets the color-set for coloring a certain bone */
+static void set_pchan_colorset(Object *ob, bPoseChannel *pchan)
+{
+ bPose *pose = (ob) ? ob->pose : NULL;
+ bArmature *arm = (ob) ? ob->data : NULL;
+ bActionGroup *grp = NULL;
+ short color_index = 0;
+
+ /* sanity check */
+ if (ELEM(NULL, ob, arm, pose, pchan)) {
+ g_color.bcolor = NULL;
+ return;
+ }
+
+ /* only try to set custom color if enabled for armature */
+ if (arm->flag & ARM_COL_CUSTOM) {
+ /* currently, a bone can only use a custom color set if it's group (if it has one),
+ * has been set to use one
+ */
+ if (pchan->agrp_index) {
+ grp = (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
+ if (grp)
+ color_index = grp->customCol;
+ }
+ }
+
+ /* bcolor is a pointer to the color set to use. If NULL, then the default
+ * color set (based on the theme colors for 3d-view) is used.
+ */
+ if (color_index > 0) {
+ bTheme *btheme = UI_GetTheme();
+ g_color.bcolor = &btheme->tarm[(color_index - 1)];
+ }
+ else if (color_index == -1) {
+ /* use the group's own custom color set (grp is always != NULL here) */
+ g_color.bcolor = &grp->cs;
+ }
+ else {
+ g_color.bcolor = NULL;
+ }
+}
+
+/* This function is for brightening/darkening a given color (like UI_GetThemeColorShade3ubv()) */
+static void cp_shade_color3ub(unsigned char cp[3], const int offset)
+{
+ int r, g, b;
+
+ 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);
+
+ cp[0] = r;
+ cp[1] = g;
+ cp[2] = b;
+}
+
+/* This function sets the gl-color for coloring a certain bone (based on bcolor) */
+static bool set_pchan_color(short colCode, const int boneflag, const short constflag, float r_color[4])
+{
+ float *fcolor = r_color;
+ const ThemeWireColor *bcolor = g_color.bcolor;
+
+ switch (colCode) {
+ case PCHAN_COLOR_NORMAL:
+ {
+ if (bcolor) {
+ unsigned char cp[4] = {255};
+
+ if (boneflag & BONE_DRAW_ACTIVE) {
+ copy_v3_v3_char((char *)cp, bcolor->active);
+ if (!(boneflag & BONE_SELECTED)) {
+ cp_shade_color3ub(cp, -80);
+ }
+ }
+ else if (boneflag & BONE_SELECTED) {
+ copy_v3_v3_char((char *)cp, bcolor->select);
+ }
+ else {
+ /* a bit darker than solid */
+ copy_v3_v3_char((char *)cp, bcolor->solid);
+ cp_shade_color3ub(cp, -50);
+ }
+
+ rgb_uchar_to_float(fcolor, cp);
+ }
+ else {
+ if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) {
+ UI_GetThemeColor4fv(TH_BONE_POSE_ACTIVE, fcolor);
+ }
+ else if (boneflag & BONE_DRAW_ACTIVE) {
+ UI_GetThemeColorBlendShade4fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, fcolor);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_WIRE, fcolor);
+ }
+ }
+
+ return true;
+ }
+ case PCHAN_COLOR_SOLID:
+ {
+ if (bcolor) {
+ rgb_uchar_to_float(fcolor, (unsigned char *)bcolor->solid);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ }
+
+ return true;
+ }
+ case PCHAN_COLOR_CONSTS:
+ {
+ if ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) {
+ 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);
+
+ rgba_uchar_to_float(fcolor, cp);
+
+ return true;
+ }
+ return false;
+ }
+ case PCHAN_COLOR_SPHEREBONE_BASE:
+ {
+ if (bcolor) {
+ unsigned char cp[4] = {255};
+
+ if (boneflag & BONE_DRAW_ACTIVE) {
+ copy_v3_v3_char((char *)cp, bcolor->active);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ copy_v3_v3_char((char *)cp, bcolor->select);
+ }
+ else {
+ copy_v3_v3_char((char *)cp, bcolor->solid);
+ }
+
+ rgb_uchar_to_float(fcolor, cp);
+ }
+ else {
+ if (boneflag & BONE_DRAW_ACTIVE) {
+ UI_GetThemeColorShade4fv(TH_BONE_POSE, 40, fcolor);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ }
+ }
+
+ return true;
+ }
+ case PCHAN_COLOR_SPHEREBONE_END:
+ {
+ if (bcolor) {
+ unsigned char cp[4] = {255};
+
+ if (boneflag & BONE_DRAW_ACTIVE) {
+ copy_v3_v3_char((char *)cp, bcolor->active);
+ cp_shade_color3ub(cp, 10);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ copy_v3_v3_char((char *)cp, bcolor->select);
+ cp_shade_color3ub(cp, -30);
+ }
+ else {
+ copy_v3_v3_char((char *)cp, bcolor->solid);
+ cp_shade_color3ub(cp, -30);
+ }
+
+ rgb_uchar_to_float(fcolor, cp);
+ }
+ else {
+ if (boneflag & BONE_DRAW_ACTIVE) {
+ UI_GetThemeColorShade4fv(TH_BONE_POSE, 10, fcolor);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ UI_GetThemeColorShade4fv(TH_BONE_POSE, -30, fcolor);
+ }
+ else {
+ UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
+ }
+ }
+ break;
+ }
+ case PCHAN_COLOR_LINEBONE:
+ {
+ /* inner part in background color or constraint */
+ if ((constflag) && ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS))) {
+ 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 */
+
+ rgb_uchar_to_float(fcolor, cp);
+ }
+ else {
+ if (bcolor) {
+ const char *cp = bcolor->solid;
+ rgb_uchar_to_float(fcolor, (unsigned char *)cp);
+ fcolor[3] = 204.f / 255.f;
+ }
+ else {
+ UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor);
+ }
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Drawing Color Helpers
+ * \{ */
+
+/**
+ * Follow `TH_*` naming except for mixed colors.
+ */
+static struct {
+ float select_color[4];
+ float edge_select_color[4];
+ float bone_select_color[4]; /* tint */
+ float wire_color[4];
+ float wire_edit_color[4];
+ float bone_solid_color[4];
+ float bone_active_unselect_color[4]; /* mix */
+ float bone_pose_color[4];
+ float bone_pose_active_color[4];
+ float bone_pose_active_unselect_color[4]; /* mix */
+ float text_hi_color[4];
+ float text_color[4];
+ float vertex_select_color[4];
+ float vertex_color[4];
+
+ /* not a theme, this is an override */
+ const float *const_color;
+} g_theme;
+
+/** See: 'set_pchan_color'*/
+static void update_color(const float const_color[4])
+{
+ g_theme.const_color = const_color;
+
+#define NO_ALPHA(c) (((c)[3] = 1.0f), (c))
+
+ UI_GetThemeColor3fv(TH_SELECT, NO_ALPHA(g_theme.select_color));
+ UI_GetThemeColor3fv(TH_EDGE_SELECT, NO_ALPHA(g_theme.edge_select_color));
+ UI_GetThemeColorShade3fv(TH_EDGE_SELECT, -20, NO_ALPHA(g_theme.bone_select_color));
+ UI_GetThemeColor3fv(TH_WIRE, NO_ALPHA(g_theme.wire_color));
+ UI_GetThemeColor3fv(TH_WIRE_EDIT, NO_ALPHA(g_theme.wire_edit_color));
+ UI_GetThemeColor3fv(TH_BONE_SOLID, NO_ALPHA(g_theme.bone_solid_color));
+ UI_GetThemeColorBlendShade3fv(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f, 0, NO_ALPHA(g_theme.bone_active_unselect_color));
+ UI_GetThemeColor3fv(TH_BONE_POSE, NO_ALPHA(g_theme.bone_pose_color));
+ UI_GetThemeColor3fv(TH_BONE_POSE_ACTIVE, NO_ALPHA(g_theme.bone_pose_active_color));
+ UI_GetThemeColorBlendShade3fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, NO_ALPHA(g_theme.bone_pose_active_unselect_color));
+ UI_GetThemeColor3fv(TH_TEXT_HI, NO_ALPHA(g_theme.text_hi_color));
+ UI_GetThemeColor3fv(TH_TEXT, NO_ALPHA(g_theme.text_color));
+ UI_GetThemeColor3fv(TH_VERTEX_SELECT, NO_ALPHA(g_theme.vertex_select_color));
+ UI_GetThemeColor3fv(TH_VERTEX, NO_ALPHA(g_theme.vertex_color));
+
+#undef NO_ALPHA
+}
+
+static const float *get_bone_solid_color(
+ const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm,
+ const int boneflag, const short constflag)
+{
+ if (g_theme.const_color)
+ return g_theme.bone_solid_color;
+
+#ifdef USE_SOLID_COLOR
+ /* Edit Mode */
+ if (eBone) {
+ bool is_active = (arm->act_edbone == eBone);
+ if (eBone->flag & BONE_SELECTED) {
+ if (is_active) {
+ return g_theme.edge_select_color;
+ }
+ else {
+ return g_theme.bone_select_color;
+ }
+ }
+ }
+ else if (arm->flag & ARM_POSEMODE) {
+ bool is_active = (arm->act_bone == pchan->bone);
+ if (pchan->bone->flag & BONE_SELECTED) {
+ if (is_active) {
+ return g_theme.bone_pose_active_color;
+ }
+ else {
+ return g_theme.bone_pose_color;
+ }
+ }
+ }
+#else
+ if (arm->drawtype == ARM_ENVELOPE) {
+ /* Edit Mode */
+ if (eBone) {
+ bool is_active = (arm->act_edbone == eBone);
+ if (eBone->flag & BONE_SELECTED) {
+ if (is_active) {
+ return g_theme.edge_select_color;
+ }
+ else {
+ return g_theme.bone_select_color;
+ }
+ }
+ }
+ else if (arm->flag & ARM_POSEMODE) {
+ bool is_active = (arm->act_bone == pchan->bone);
+ if (pchan->bone->flag & BONE_SELECTED) {
+ if (is_active) {
+ return g_theme.bone_pose_active_color;
+ }
+ else {
+ return g_theme.bone_pose_color;
+ }
+ }
+ }
+ }
+#endif
+
+ if (arm->flag & ARM_POSEMODE) {
+ float *disp_color = pchan->draw_data->solid_color;
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag, disp_color);
+ disp_color[3] = 1.0;
+ return disp_color;
+ }
+
+ return g_theme.bone_solid_color;
+}
+
+static const float *get_bone_wire_color(
+ const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm,
+ const int boneflag, const short constflag)
+{
+ if (g_theme.const_color)
+ return g_theme.const_color;
+
+ if (eBone) {
+ if (boneflag & BONE_SELECTED) {
+ if (boneflag & BONE_DRAW_ACTIVE) {
+ return g_theme.edge_select_color;
+ }
+ else {
+ return g_theme.bone_select_color;
+ }
+ }
+ else {
+ if (boneflag & BONE_DRAW_ACTIVE) {
+ return g_theme.bone_active_unselect_color;
+ }
+ else {
+ return g_theme.wire_edit_color;
+ }
+ }
+ }
+ else if (arm->flag & ARM_POSEMODE) {
+ float *disp_color = pchan->draw_data->wire_color;
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag, disp_color);
+ disp_color[3] = 1.0;
+ return disp_color;
+
+
+#if 0
+ if (boneflag & BONE_SELECTED) {
+ if (is_active) {
+ return g_theme.bone_pose_active_color;
+ }
+ else {
+ return g_theme.bone_pose_color;
+ }
+ }
+ else {
+ if (is_active) {
+ return g_theme.bone_pose_active_unselect_color;
+ }
+ else {
+ return g_theme.wire_color;
+ }
+ }
+#endif
+ }
+
+ return g_theme.vertex_color;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Helper Utils
+ * \{ */
+
+static void pchan_draw_data_init(bPoseChannel *pchan)
+{
+ if (pchan->draw_data != NULL) {
+ if (pchan->draw_data->bbone_matrix_len != pchan->bone->segments) {
+ MEM_SAFE_FREE(pchan->draw_data);
+ }
+ }
+
+ if (pchan->draw_data == NULL) {
+ pchan->draw_data = MEM_mallocN(sizeof(*pchan->draw_data) + sizeof(Mat4) * pchan->bone->segments, __func__);
+ pchan->draw_data->bbone_matrix_len = pchan->bone->segments;
+ }
+}
+
+static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel *pchan)
+{
+ float s[4][4], ebmat[4][4];
+ float length;
+ float (*bone_mat)[4];
+ float (*disp_mat)[4];
+ float (*disp_tail_mat)[4];
+
+ /* TODO : This should be moved to depsgraph or armature refresh
+ * and not be tight to the draw pass creation.
+ * This would refresh armature without invalidating the draw cache */
+ if (pchan) {
+ length = pchan->bone->length;
+ bone_mat = pchan->pose_mat;
+ disp_mat = pchan->disp_mat;
+ disp_tail_mat = pchan->disp_tail_mat;
+ }
+ else {
+ eBone->length = len_v3v3(eBone->tail, eBone->head);
+ ED_armature_ebone_to_mat4(eBone, ebmat);
+
+ length = eBone->length;
+ bone_mat = ebmat;
+ disp_mat = eBone->disp_mat;
+ disp_tail_mat = eBone->disp_tail_mat;
+ }
+
+ scale_m4_fl(s, length);
+ mul_m4_m4m4(disp_mat, bone_mat, s);
+ copy_m4_m4(disp_tail_mat, disp_mat);
+ translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f);
+}
+
+/* XXX Direct copy from drawarmature.c... This is ugly! */
+/* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings
+ *
+ * This assumes that prev/next bones don't have any impact (since they should all still be in the "straight"
+ * position here anyway), and that we can simply apply the bbone settings to get the desired effect...
+ */
+static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_SUBDIV][4][4])
+{
+ float h1[3], h2[3], length, hlength1, hlength2, roll1 = 0.0f, roll2 = 0.0f;
+ float mat3[3][3];
+ float data[MAX_BBONE_SUBDIV + 1][4], *fp;
+ int a;
+
+ length = ebone->length;
+
+ hlength1 = ebone->ease1 * length * 0.390464f; /* 0.5f * sqrt(2) * kappa, the handle length for near-perfect circles */
+ hlength2 = ebone->ease2 * length * 0.390464f;
+
+ /* find the handle points, since this is inside bone space, the
+ * first point = (0, 0, 0)
+ * last point = (0, length, 0)
+ *
+ * we also just apply all the "extra effects", since they're the whole reason we're doing this...
+ */
+ h1[0] = ebone->curveInX;
+ h1[1] = hlength1;
+ h1[2] = ebone->curveInY;
+ roll1 = ebone->roll1;
+
+ h2[0] = ebone->curveOutX;
+ h2[1] = -hlength2;
+ h2[2] = ebone->curveOutY;
+ roll2 = ebone->roll2;
+
+ /* make curve */
+ if (ebone->segments > MAX_BBONE_SUBDIV)
+ ebone->segments = MAX_BBONE_SUBDIV;
+
+ BKE_curve_forward_diff_bezier(0.0f, h1[0], h2[0], 0.0f, data[0], MAX_BBONE_SUBDIV, 4 * sizeof(float));
+ BKE_curve_forward_diff_bezier(0.0f, h1[1], length + h2[1], length, data[0] + 1, MAX_BBONE_SUBDIV, 4 * sizeof(float));
+ BKE_curve_forward_diff_bezier(0.0f, h1[2], h2[2], 0.0f, data[0] + 2, MAX_BBONE_SUBDIV, 4 * sizeof(float));
+ BKE_curve_forward_diff_bezier(roll1, roll1 + 0.390464f * (roll2 - roll1), roll2 - 0.390464f * (roll2 - roll1), roll2, data[0] + 3, MAX_BBONE_SUBDIV, 4 * sizeof(float));
+
+ equalize_bbone_bezier(data[0], ebone->segments); /* note: does stride 4! */
+
+ /* make transformation matrices for the segments for drawing */
+ for (a = 0, fp = data[0]; a < ebone->segments; a++, fp += 4) {
+ sub_v3_v3v3(h1, fp + 4, fp);
+ vec_roll_to_mat3(h1, fp[3], mat3); /* fp[3] is roll */
+
+ copy_m4_m3(result_array[a], mat3);
+ copy_v3_v3(result_array[a][3], fp);
+
+ /* "extra" scale facs... */
+ {
+ const int num_segments = ebone->segments;
+
+ const float scaleFactorIn = 1.0f + (ebone->scaleIn - 1.0f) * ((float)(num_segments - a) / (float)num_segments);
+ const float scaleFactorOut = 1.0f + (ebone->scaleOut - 1.0f) * ((float)(a + 1) / (float)num_segments);
+
+ const float scalefac = scaleFactorIn * scaleFactorOut;
+ float bscalemat[4][4], bscale[3];
+
+ bscale[0] = scalefac;
+ bscale[1] = 1.0f;
+ bscale[2] = scalefac;
+
+ size_to_mat4(bscalemat, bscale);
+
+ /* Note: don't multiply by inverse scale mat here, as it causes problems with scaling shearing and breaking segment chains */
+ mul_m4_series(result_array[a], result_array[a], bscalemat);
+ }
+ }
+}
+
+static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pchan)
+{
+ float s[4][4], ebmat[4][4];
+ float length, xwidth, zwidth;
+ float (*bone_mat)[4];
+ short bbone_segments;
+
+ /* TODO : This should be moved to depsgraph or armature refresh
+ * and not be tight to the draw pass creation.
+ * This would refresh armature without invalidating the draw cache */
+ if (pchan) {
+ length = pchan->bone->length;
+ xwidth = pchan->bone->xwidth;
+ zwidth = pchan->bone->zwidth;
+ bone_mat = pchan->pose_mat;
+ bbone_segments = pchan->bone->segments;
+ }
+ else {
+ eBone->length = len_v3v3(eBone->tail, eBone->head);
+ ED_armature_ebone_to_mat4(eBone, ebmat);
+
+ length = eBone->length;
+ xwidth = eBone->xwidth;
+ zwidth = eBone->zwidth;
+ bone_mat = ebmat;
+ bbone_segments = eBone->segments;
+ }
+
+ size_to_mat4(s, (const float[3]){xwidth, length / bbone_segments, zwidth});
+
+ /* Compute BBones segment matrices... */
+ /* Note that we need this even for one-segment bones, because box drawing need specific weirdo matrix for the box,
+ * that we cannot use to draw end points & co. */
+ if (pchan) {
+ Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix;
+ if (bbone_segments > 1) {
+ b_bone_spline_setup(pchan, 0, bbones_mat);
+
+ for (int i = bbone_segments; i--; bbones_mat++) {
+ mul_m4_m4m4(bbones_mat->mat, bbones_mat->mat, s);
+ mul_m4_m4m4(bbones_mat->mat, bone_mat, bbones_mat->mat);
+ }
+ }
+ else {
+ mul_m4_m4m4(bbones_mat->mat, bone_mat, s);
+ }
+ }
+ else {
+ float (*bbones_mat)[4][4] = eBone->disp_bbone_mat;
+
+ if (bbone_segments > 1) {
+ ebone_spline_preview(eBone, bbones_mat);
+
+ for (int i = bbone_segments; i--; bbones_mat++) {
+ mul_m4_m4m4(*bbones_mat, *bbones_mat, s);
+ mul_m4_m4m4(*bbones_mat, bone_mat, *bbones_mat);
+ }
+ }
+ else {
+ mul_m4_m4m4(*bbones_mat, bone_mat, s);
+ }
+ }
+
+ /* Grrr... We need default display matrix to draw end points, axes, etc. :( */
+ draw_bone_update_disp_matrix_default(eBone, pchan);
+}
+
+static void draw_bone_update_disp_matrix_custom(bPoseChannel *pchan)
+{
+ float s[4][4];
+ float length;
+ float (*bone_mat)[4];
+ float (*disp_mat)[4];
+ float (*disp_tail_mat)[4];
+
+ /* See TODO above */
+ length = PCHAN_CUSTOM_DRAW_SIZE(pchan);
+ bone_mat = pchan->custom_tx ? pchan->custom_tx->pose_mat : pchan->pose_mat;
+ disp_mat = pchan->disp_mat;
+ disp_tail_mat = pchan->disp_tail_mat;
+
+ scale_m4_fl(s, length);
+ mul_m4_m4m4(disp_mat, bone_mat, s);
+ copy_m4_m4(disp_tail_mat, disp_mat);
+ translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f);
+}
+
+static void draw_axes(EditBone *eBone, bPoseChannel *pchan)
+{
+ const float *col = (g_theme.const_color) ? g_theme.const_color :
+ (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? g_theme.text_hi_color : g_theme.text_color;
+
+ drw_shgroup_bone_axes(BONE_VAR(eBone, pchan, disp_mat), col);
+}
+
+static void draw_points(
+ const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm,
+ const int boneflag, const short constflag,
+ const int select_id)
+{
+ const float *col_solid_root = g_theme.bone_solid_color;
+ const float *col_solid_tail = g_theme.bone_solid_color;
+ const float *col_wire_root = (g_theme.const_color) ? g_theme.const_color : g_theme.vertex_color;
+ const float *col_wire_tail = (g_theme.const_color) ? g_theme.const_color : g_theme.vertex_color;
+
+ const bool is_envelope_draw = (arm->drawtype == ARM_ENVELOPE);
+ static const float envelope_ignore = -1.0f;
+
+ /* Edit bone points can be selected */
+ if (eBone) {
+ if (eBone->flag & BONE_ROOTSEL) {
+#ifdef USE_SOLID_COLOR
+ col_solid_root = g_theme.vertex_select_color;
+#else
+ if (is_envelope_draw) {
+ col_solid_root = g_theme.vertex_select_color;
+ }
+#endif
+ col_wire_root = g_theme.vertex_select_color;
+ }
+ if (eBone->flag & BONE_TIPSEL) {
+#ifdef USE_SOLID_COLOR
+ col_solid_tail = g_theme.vertex_select_color;
+#else
+ if (is_envelope_draw) {
+ col_solid_tail = g_theme.vertex_select_color;
+ }
+#endif
+ col_wire_tail = g_theme.vertex_select_color;
+ }
+ }
+ else if (arm->flag & ARM_POSEMODE) {
+ col_solid_root = col_solid_tail = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
+ col_wire_root = col_wire_tail = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
+ }
+
+ /* Draw root point if we are not connected and parent are not hidden */
+ if ((BONE_FLAG(eBone, pchan) & BONE_CONNECTED) == 0) {
+ if (select_id != -1) {
+ DRW_select_load_id(select_id | BONESEL_ROOT);
+ }
+
+ if (eBone) {
+ if (!((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))) {
+ if (is_envelope_draw) {
+ drw_shgroup_bone_envelope_solid(eBone->disp_mat, col_solid_root,
+ &eBone->rad_head, &envelope_ignore);
+ drw_shgroup_bone_envelope_head_wire(eBone->disp_mat, col_wire_root,
+ &eBone->rad_head, &envelope_ignore, &envelope_ignore);
+ }
+ else {
+ drw_shgroup_bone_point_solid(eBone->disp_mat, col_solid_root);
+ drw_shgroup_bone_point_wire(eBone->disp_mat, col_wire_root);
+ }
+ }
+ }
+ else {
+ Bone *bone = pchan->bone;
+ if (!((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) {
+ if (is_envelope_draw) {
+ drw_shgroup_bone_envelope_solid(pchan->disp_mat, col_solid_root,
+ &bone->rad_head, &envelope_ignore);
+ drw_shgroup_bone_envelope_head_wire(pchan->disp_mat, col_wire_root,
+ &bone->rad_head, &envelope_ignore, &envelope_ignore);
+ }
+ else {
+ drw_shgroup_bone_point_solid(pchan->disp_mat, col_solid_root);
+ drw_shgroup_bone_point_wire(pchan->disp_mat, col_wire_root);
+ }
+ }
+ }
+ }
+
+ /* Draw tip point */
+ if (select_id != -1) {
+ DRW_select_load_id(select_id | BONESEL_TIP);
+ }
+
+ if (is_envelope_draw) {
+ const float *rad_tail = eBone ? &eBone->rad_tail : &pchan->bone->rad_tail;
+ drw_shgroup_bone_envelope_solid(
+ BONE_VAR(eBone, pchan, disp_mat), col_solid_tail, &envelope_ignore, rad_tail);
+ drw_shgroup_bone_envelope_head_wire(
+ BONE_VAR(eBone, pchan, disp_mat), col_wire_tail, &envelope_ignore, rad_tail, &envelope_ignore);
+ }
+ else {
+ drw_shgroup_bone_point_solid(BONE_VAR(eBone, pchan, disp_tail_mat), col_solid_tail);
+ drw_shgroup_bone_point_wire(BONE_VAR(eBone, pchan, disp_tail_mat), col_wire_tail);
+ }
+
+ if (select_id != -1) {
+ DRW_select_load_id(-1);
+ }
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Draw Bones
+ * \{ */
+
+static void draw_bone_custom_shape(
+ EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
+ const int boneflag, const short constflag,
+ const int select_id)
+{
+ const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
+ const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
+ const float (*disp_mat)[4] = pchan->disp_mat;
+
+ if (select_id != -1) {
+ DRW_select_load_id(select_id | BONESEL_BONE);
+ }
+
+ drw_shgroup_bone_custom_solid(disp_mat, col_solid, pchan->custom);
+ drw_shgroup_bone_custom_wire(disp_mat, col_wire, pchan->custom);
+
+ if (select_id != -1) {
+ DRW_select_load_id(-1);
+ }
+}
+
+static void draw_bone_envelope(
+ EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
+ const int boneflag, const short constflag,
+ const int select_id)
+{
+ const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
+ const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
+
+ static const float col_white[4] = {1.0f, 1.0f, 1.0f, 0.2f};
+
+ float *rad_head, *rad_tail, *distance;
+ if (eBone) {
+ rad_tail = &eBone->rad_tail;
+ distance = &eBone->dist;
+ rad_head = (eBone->parent && (boneflag & BONE_CONNECTED)) ? &eBone->parent->rad_tail : &eBone->rad_head;
+ }
+ else {
+ rad_tail = &pchan->bone->rad_tail;
+ distance = &pchan->bone->dist;
+ rad_head = (pchan->parent && (boneflag & BONE_CONNECTED)) ? &pchan->parent->bone->rad_tail : &pchan->bone->rad_head;
+ }
+
+ if ((boneflag & BONE_NO_DEFORM) == 0 &&
+ ((boneflag & BONE_SELECTED) || (eBone && (boneflag & (BONE_ROOTSEL | BONE_TIPSEL)))))
+ {
+ drw_shgroup_bone_envelope_distance(BONE_VAR(eBone, pchan, disp_mat), col_white, rad_head, rad_tail, distance);
+ }
+
+ if (select_id != -1) {
+ DRW_select_load_id(select_id | BONESEL_BONE);
+ }
+
+ drw_shgroup_bone_envelope_solid(BONE_VAR(eBone, pchan, disp_mat), col_solid, rad_head, rad_tail);
+ drw_shgroup_bone_envelope_wire(BONE_VAR(eBone, pchan, disp_mat), col_wire, rad_head, rad_tail, distance);
+
+ if (select_id != -1) {
+ DRW_select_load_id(-1);
+ }
+
+ draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
+}
+
+static void draw_bone_line(
+ EditBone *UNUSED(eBone), bPoseChannel *UNUSED(pchan), bArmature *UNUSED(arm),
+ const int UNUSED(boneflag), const short UNUSED(constflag),
+ const int UNUSED(select_id))
+{
+ /* work in progress -- fclem */
+}
+
+static void draw_bone_wire(
+ EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
+ const int boneflag, const short constflag,
+ const int select_id)
+{
+ const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
+
+ if (select_id != -1) {
+ DRW_select_load_id(select_id | BONESEL_BONE);
+ }
+
+ if (pchan) {
+ Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix;
+ BLI_assert(bbones_mat != NULL);
+
+ for (int i = pchan->bone->segments; i--; bbones_mat++) {
+ drw_shgroup_bone_wire_wire(bbones_mat->mat, col_wire);
+ }
+ }
+ else if (eBone) {
+ for (int i = 0; i < eBone->segments; i++) {
+ drw_shgroup_bone_wire_wire(eBone->disp_bbone_mat[i], col_wire);
+ }
+ }
+
+ if (select_id != -1) {
+ DRW_select_load_id(-1);
+ }
+
+ if (eBone) {
+ draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
+ }
+}
+
+static void draw_bone_box(
+ EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
+ const int boneflag, const short constflag,
+ const int select_id)
+{
+ const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
+ const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
+
+ if (select_id != -1) {
+ DRW_select_load_id(select_id | BONESEL_BONE);
+ }
+
+ if (pchan) {
+ Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix;
+ BLI_assert(bbones_mat != NULL);
+
+ for (int i = pchan->bone->segments; i--; bbones_mat++) {
+ drw_shgroup_bone_box_solid(bbones_mat->mat, col_solid);
+ drw_shgroup_bone_box_wire(bbones_mat->mat, col_wire);
+ }
+ }
+ else if (eBone) {
+ for (int i = 0; i < eBone->segments; i++) {
+ drw_shgroup_bone_box_solid(eBone->disp_bbone_mat[i], col_solid);
+ drw_shgroup_bone_box_wire(eBone->disp_bbone_mat[i], col_wire);
+ }
+ }
+
+ if (select_id != -1) {
+ DRW_select_load_id(-1);
+ }
+
+ if (eBone) {
+ draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
+ }
+}
+
+static void draw_bone_octahedral(
+ EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
+ const int boneflag, const short constflag,
+ const int select_id)
+{
+ const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
+ const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
+
+ if (select_id != -1) {
+ DRW_select_load_id(select_id | BONESEL_BONE);
+ }
+
+ drw_shgroup_bone_octahedral_solid(BONE_VAR(eBone, pchan, disp_mat), col_solid);
+ drw_shgroup_bone_octahedral_wire(BONE_VAR(eBone, pchan, disp_mat), col_wire);
+
+ if (select_id != -1) {
+ DRW_select_load_id(-1);
+ }
+
+ draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Main Draw Loops
+ * \{ */
+
+static void draw_armature_edit(Object *ob)
+{
+ EditBone *eBone;
+ bArmature *arm = ob->data;
+ int index;
+ const bool is_select = DRW_state_is_select();
+
+ update_color(NULL);
+
+ const bool show_text = DRW_state_show_text();
+
+ for (eBone = arm->edbo->first, index = 0; eBone; eBone = eBone->next, index++) {
+ if (eBone->layer & arm->layer) {
+ if ((eBone->flag & BONE_HIDDEN_A) == 0) {
+ const int select_id = is_select ? index : (unsigned int)-1;
+
+ const short constflag = 0;
+
+ /* catch exception for bone with hidden parent */
+ int boneflag = eBone->flag;
+ if ((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) {
+ boneflag &= ~BONE_CONNECTED;
+ }
+
+ /* set temporary flag for drawing bone as active, but only if selected */
+ if (eBone == arm->act_edbone) {
+ boneflag |= BONE_DRAW_ACTIVE;
+ }
+
+ if (arm->drawtype == ARM_ENVELOPE) {
+ draw_bone_update_disp_matrix_default(eBone, NULL);
+ draw_bone_envelope(eBone, NULL, arm, boneflag, constflag, select_id);
+ }
+ else if (arm->drawtype == ARM_LINE) {
+ draw_bone_update_disp_matrix_default(eBone, NULL);
+ draw_bone_line(eBone, NULL, arm, boneflag, constflag, select_id);
+ }
+ else if (arm->drawtype == ARM_WIRE) {
+ draw_bone_update_disp_matrix_bbone(eBone, NULL);
+ draw_bone_wire(eBone, NULL, arm, boneflag, constflag, select_id);
+ }
+ else if (arm->drawtype == ARM_B_BONE) {
+ draw_bone_update_disp_matrix_bbone(eBone, NULL);
+ draw_bone_box(eBone, NULL, arm, boneflag, constflag, select_id);
+ }
+ else {
+ draw_bone_update_disp_matrix_default(eBone, NULL);
+ draw_bone_octahedral(eBone, NULL, arm, boneflag, constflag, select_id);
+ }
+
+ /* Draw names of bone */
+ if (show_text && (arm->flag & ARM_DRAWNAMES)) {
+ unsigned char color[4];
+ UI_GetThemeColor4ubv((eBone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, color);
+
+ float vec[3];
+ mid_v3_v3v3(vec, eBone->head, eBone->tail);
+ mul_m4_v3(ob->obmat, vec);
+
+ struct DRWTextStore *dt = DRW_text_cache_ensure();
+ DRW_text_cache_add(
+ dt, vec, eBone->name, strlen(eBone->name),
+ 10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color);
+ }
+
+ /* Draw additional axes */
+ if (arm->flag & ARM_DRAWAXES) {
+ draw_axes(eBone, NULL);
+ }
+ }
+ }
+ }
+}
+
+/* if const_color is NULL do pose mode coloring */
+static void draw_armature_pose(Object *ob, const float const_color[4])
+{
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+ int index = -1;
+ Bone *bone;
+
+ update_color(const_color);
+
+ /* We can't safely draw non-updated pose, might contain NULL bone pointers... */
+ if (ob->pose->flag & POSE_RECALC) {
+ BKE_pose_rebuild(ob, arm);
+ }
+
+ // if (!(base->flag & OB_FROMDUPLI)) // TODO
+ {
+ if (ob->mode & OB_MODE_POSE) {
+ arm->flag |= ARM_POSEMODE;
+ }
+
+ if (arm->flag & ARM_POSEMODE) {
+ index = ob->select_color;
+ }
+ }
+
+ const bool is_pose_select = (arm->flag & ARM_POSEMODE) && DRW_state_is_select();
+ const bool show_text = DRW_state_show_text();
+
+ /* being set below */
+ arm->layer_used = 0;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ bone = pchan->bone;
+ arm->layer_used |= bone->layer;
+
+ /* bone must be visible */
+ if ((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) {
+ if (bone->layer & arm->layer) {
+ const int select_id = is_pose_select ? index : (unsigned int)-1;
+
+ const short constflag = pchan->constflag;
+
+ pchan_draw_data_init(pchan);
+
+ if (const_color) {
+ /* keep color */
+ }
+ else {
+ /* set color-set to use */
+ set_pchan_colorset(ob, pchan);
+ }
+
+ int boneflag = bone->flag;
+ /* catch exception for bone with hidden parent */
+ boneflag = bone->flag;
+ if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
+ boneflag &= ~BONE_CONNECTED;
+ }
+
+ /* set temporary flag for drawing bone as active, but only if selected */
+ if (bone == arm->act_bone)
+ boneflag |= BONE_DRAW_ACTIVE;
+
+
+ if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) {
+ draw_bone_update_disp_matrix_custom(pchan);
+ draw_bone_custom_shape(NULL, pchan, arm, boneflag, constflag, select_id);
+ }
+ else if (arm->drawtype == ARM_ENVELOPE) {
+ draw_bone_update_disp_matrix_default(NULL, pchan);
+ draw_bone_envelope(NULL, pchan, arm, boneflag, constflag, select_id);
+ }
+ else if (arm->drawtype == ARM_LINE) {
+ draw_bone_update_disp_matrix_default(NULL, pchan);
+ draw_bone_line(NULL, pchan, arm, boneflag, constflag, select_id);
+ }
+ else if (arm->drawtype == ARM_WIRE) {
+ draw_bone_update_disp_matrix_bbone(NULL, pchan);
+ draw_bone_wire(NULL, pchan, arm, boneflag, constflag, select_id);
+ }
+ else if (arm->drawtype == ARM_B_BONE) {
+ draw_bone_update_disp_matrix_bbone(NULL, pchan);
+ draw_bone_box(NULL, pchan, arm, boneflag, constflag, select_id);
+ }
+ else {
+ draw_bone_update_disp_matrix_default(NULL, pchan);
+ draw_bone_octahedral(NULL, pchan, arm, boneflag, constflag, select_id);
+ }
+
+ /* Draw names of bone */
+ if (show_text && (arm->flag & ARM_DRAWNAMES)) {
+ unsigned char color[4];
+ UI_GetThemeColor4ubv((arm->flag & ARM_POSEMODE) &&
+ (bone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, color);
+ float vec[3];
+ mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail);
+ mul_m4_v3(ob->obmat, vec);
+
+ struct DRWTextStore *dt = DRW_text_cache_ensure();
+ DRW_text_cache_add(
+ dt, vec, pchan->name, strlen(pchan->name),
+ 10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color);
+ }
+
+ /* Draw additional axes */
+ if (arm->flag & ARM_DRAWAXES) {
+ draw_axes(NULL, pchan);
+ }
+ }
+ }
+ if (is_pose_select) {
+ index += 0x10000;
+ }
+ }
+
+ arm->flag &= ~ARM_POSEMODE;
+}
+
+/**
+ * This function set the object space to use for all subsequent `DRW_shgroup_bone_*` calls.
+ */
+static void drw_shgroup_armature(
+ Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWPass *pass_bone_envelope,
+ DRWShadingGroup *shgrp_relationship_lines)
+{
+ memset(&g_data, 0x0, sizeof(g_data));
+ g_data.ob = ob;
+
+ g_data.pass_bone_solid = pass_bone_solid;
+ g_data.pass_bone_wire = pass_bone_wire;
+ g_data.pass_bone_envelope = pass_bone_envelope;
+ g_data.relationship_lines = shgrp_relationship_lines;
+
+ memset(&g_color, 0x0, sizeof(g_color));
+}
+
+void DRW_shgroup_armature_object(
+ Object *ob, ViewLayer *view_layer, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWPass *UNUSED(pass_bone_envelope),
+ DRWShadingGroup *shgrp_relationship_lines)
+{
+ float *color;
+ DRW_object_wire_theme_get(ob, view_layer, &color);
+
+ drw_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, NULL, shgrp_relationship_lines);
+ draw_armature_pose(ob, color);
+}
+
+void DRW_shgroup_armature_pose(
+ Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWPass *pass_bone_envelope,
+ DRWShadingGroup *shgrp_relationship_lines)
+{
+ drw_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, pass_bone_envelope, shgrp_relationship_lines);
+ draw_armature_pose(ob, NULL);
+}
+
+void DRW_shgroup_armature_edit(
+ Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWPass *pass_bone_envelope,
+ DRWShadingGroup *shgrp_relationship_lines)
+{
+ drw_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, pass_bone_envelope, shgrp_relationship_lines);
+ draw_armature_edit(ob);
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
new file mode 100644
index 00000000000..8010a232f89
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache.c
@@ -0,0 +1,2591 @@
+/*
+ * 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_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_lattice_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "GPU_batch.h"
+
+#include "draw_cache.h"
+#include "draw_cache_impl.h"
+
+/* Batch's only (free'd as an array) */
+static struct DRWShapeCache {
+ Gwn_Batch *drw_single_vertice;
+ Gwn_Batch *drw_fullscreen_quad;
+ Gwn_Batch *drw_quad;
+ Gwn_Batch *drw_screenspace_circle;
+ Gwn_Batch *drw_plain_axes;
+ Gwn_Batch *drw_single_arrow;
+ Gwn_Batch *drw_cube;
+ Gwn_Batch *drw_circle;
+ Gwn_Batch *drw_square;
+ Gwn_Batch *drw_line;
+ Gwn_Batch *drw_line_endpoints;
+ Gwn_Batch *drw_empty_sphere;
+ Gwn_Batch *drw_empty_cone;
+ Gwn_Batch *drw_arrows;
+ Gwn_Batch *drw_axis_names;
+ Gwn_Batch *drw_image_plane;
+ Gwn_Batch *drw_image_plane_wire;
+ Gwn_Batch *drw_field_wind;
+ Gwn_Batch *drw_field_force;
+ Gwn_Batch *drw_field_vortex;
+ Gwn_Batch *drw_field_tube_limit;
+ Gwn_Batch *drw_field_cone_limit;
+ Gwn_Batch *drw_lamp;
+ Gwn_Batch *drw_lamp_sunrays;
+ Gwn_Batch *drw_lamp_area;
+ Gwn_Batch *drw_lamp_hemi;
+ Gwn_Batch *drw_lamp_spot;
+ Gwn_Batch *drw_lamp_spot_square;
+ Gwn_Batch *drw_speaker;
+ Gwn_Batch *drw_lightprobe_cube;
+ Gwn_Batch *drw_lightprobe_planar;
+ Gwn_Batch *drw_lightprobe_grid;
+ Gwn_Batch *drw_bone_octahedral;
+ Gwn_Batch *drw_bone_octahedral_wire;
+ Gwn_Batch *drw_bone_box;
+ Gwn_Batch *drw_bone_box_wire;
+ Gwn_Batch *drw_bone_wire_wire;
+ Gwn_Batch *drw_bone_envelope;
+ Gwn_Batch *drw_bone_envelope_distance;
+ Gwn_Batch *drw_bone_envelope_wire;
+ Gwn_Batch *drw_bone_envelope_head_wire;
+ Gwn_Batch *drw_bone_point;
+ Gwn_Batch *drw_bone_point_wire;
+ Gwn_Batch *drw_bone_arrows;
+ Gwn_Batch *drw_camera;
+ Gwn_Batch *drw_camera_tria;
+ Gwn_Batch *drw_camera_focus;
+ Gwn_Batch *drw_particle_cross;
+ Gwn_Batch *drw_particle_circle;
+ Gwn_Batch *drw_particle_axis;
+} SHC = {NULL};
+
+void DRW_shape_cache_free(void)
+{
+ uint i = sizeof(SHC) / sizeof(Gwn_Batch *);
+ Gwn_Batch **batch = (Gwn_Batch **)&SHC;
+ while (i--) {
+ GWN_BATCH_DISCARD_SAFE(*batch);
+ batch++;
+ }
+}
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Helper functions
+ * \{ */
+
+static void add_fancy_edge(
+ Gwn_VertBuf *vbo, unsigned int pos_id, unsigned int n1_id, unsigned int n2_id,
+ unsigned int *v_idx, const float co1[3], const float co2[3],
+const float n1[3], const float n2[3])
+{
+ GWN_vertbuf_attr_set(vbo, n1_id, *v_idx, n1);
+ GWN_vertbuf_attr_set(vbo, n2_id, *v_idx, n2);
+ GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co1);
+
+ GWN_vertbuf_attr_set(vbo, n1_id, *v_idx, n1);
+ GWN_vertbuf_attr_set(vbo, n2_id, *v_idx, n2);
+ GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co2);
+}
+
+static void add_lat_lon_vert(
+ Gwn_VertBuf *vbo, unsigned int pos_id, unsigned int nor_id,
+ unsigned int *v_idx, const float rad, const float lat, const float lon)
+{
+ float pos[3], nor[3];
+ nor[0] = sinf(lat) * cosf(lon);
+ nor[1] = cosf(lat);
+ nor[2] = sinf(lat) * sinf(lon);
+ mul_v3_v3fl(pos, nor, rad);
+
+ GWN_vertbuf_attr_set(vbo, nor_id, *v_idx, nor);
+ GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, pos);
+}
+
+static Gwn_VertBuf *fill_arrows_vbo(const float scale)
+{
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ /* Line */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 6 * 3);
+
+ float v1[3] = {0.0, 0.0, 0.0};
+ float v2[3] = {0.0, 0.0, 0.0};
+ float vtmp1[3], vtmp2[3];
+
+ for (int axis = 0; axis < 3; axis++) {
+ const int arrow_axis = (axis == 0) ? 1 : 0;
+
+ v2[axis] = 1.0f;
+ mul_v3_v3fl(vtmp1, v1, scale);
+ mul_v3_v3fl(vtmp2, v2, scale);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 0, vtmp1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 1, vtmp2);
+
+ v1[axis] = 0.85f;
+ v1[arrow_axis] = -0.08f;
+ mul_v3_v3fl(vtmp1, v1, scale);
+ mul_v3_v3fl(vtmp2, v2, scale);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 2, vtmp1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 3, vtmp2);
+
+ v1[arrow_axis] = 0.08f;
+ mul_v3_v3fl(vtmp1, v1, scale);
+ mul_v3_v3fl(vtmp2, v2, scale);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 4, vtmp1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 5, vtmp2);
+
+ /* reset v1 & v2 to zero */
+ v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
+ }
+
+ return vbo;
+}
+
+static Gwn_VertBuf *sphere_wire_vbo(const float rad)
+{
+#define NSEGMENTS 32
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 2 * 3);
+
+ /* 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] = rad * cosf(angle);
+ p[i][1] = rad * sinf(angle);
+ }
+
+ 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];
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 2 + j + (NSEGMENTS * 2 * axis), v);
+ }
+ }
+ }
+
+ return vbo;
+#undef NSEGMENTS
+}
+
+/* Quads */
+/* Use this one for rendering fullscreen passes. For 3D objects use DRW_cache_quad_get(). */
+Gwn_Batch *DRW_cache_fullscreen_quad_get(void)
+{
+ if (!SHC.drw_fullscreen_quad) {
+ /* Use a triangle instead of a real quad */
+ /* https://www.slideshare.net/DevCentralAMD/vertex-shader-tricks-bill-bilodeau - slide 14 */
+ float pos[3][2] = {{-1.0f, -1.0f}, { 3.0f, -1.0f}, {-1.0f, 3.0f}};
+ float uvs[3][2] = {{ 0.0f, 0.0f}, { 2.0f, 0.0f}, { 0.0f, 2.0f}};
+
+ /* Position Only 2D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, uvs; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 3);
+
+ for (int i = 0; i < 3; ++i) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i, pos[i]);
+ GWN_vertbuf_attr_set(vbo, attr_id.uvs, i, uvs[i]);
+ }
+
+ SHC.drw_fullscreen_quad = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_fullscreen_quad;
+}
+
+/* Just a regular quad with 4 vertices. */
+Gwn_Batch *DRW_cache_quad_get(void)
+{
+ if (!SHC.drw_quad) {
+ /* Use a triangle instead of a real quad */
+ float pos[4][2] = {{-1.0f, -1.0f}, { 1.0f, -1.0f}, {1.0f, 1.0f}, {-1.0f, 1.0f}};
+ float uvs[4][2] = {{ 0.0f, 0.0f}, { 1.0f, 0.0f}, {1.0f, 1.0f}, { 0.0f, 1.0f}};
+
+ /* Position Only 2D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, uvs; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 4);
+
+ for (int i = 0; i < 4; ++i) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i, pos[i]);
+ GWN_vertbuf_attr_set(vbo, attr_id.uvs, i, uvs[i]);
+ }
+
+ SHC.drw_quad = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_quad;
+}
+
+/* Sphere */
+Gwn_Batch *DRW_cache_sphere_get(void)
+{
+ return GPU_batch_preset_sphere(2);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Common
+ * \{ */
+
+Gwn_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 Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 24);
+
+ for (int i = 0; i < 24; ++i) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i, verts[indices[i]]);
+ }
+
+ SHC.drw_cube = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_cube;
+}
+
+Gwn_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 Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2);
+
+ for (int a = 0; a < CIRCLE_RESOL; a++) {
+ v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[1] = 0.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2, v);
+
+ v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ v[1] = 0.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2 + 1, v);
+ }
+
+ SHC.drw_circle = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_circle;
+#undef CIRCLE_RESOL
+}
+
+Gwn_Batch *DRW_cache_square_get(void)
+{
+ if (!SHC.drw_square) {
+ float p[4][3] = {{ 1.0f, 0.0f, 1.0f},
+ { 1.0f, 0.0f, -1.0f},
+ {-1.0f, 0.0f, -1.0f},
+ {-1.0f, 0.0f, 1.0f}};
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 8);
+
+ for (int i = 0; i < 4; i++) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 2, p[i % 4]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 2 + 1, p[(i + 1) % 4]);
+ }
+
+ SHC.drw_square = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_square;
+}
+
+Gwn_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 Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 2);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v2);
+
+ SHC.drw_line = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_line;
+}
+
+Gwn_Batch *DRW_cache_single_line_endpoints_get(void)
+{
+ /* Z axis line */
+ if (!SHC.drw_line_endpoints) {
+ float v1[3] = {0.0f, 0.0f, 0.0f};
+ float v2[3] = {0.0f, 0.0f, 1.0f};
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 2);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v2);
+
+ SHC.drw_line_endpoints = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_line_endpoints;
+}
+
+Gwn_Batch *DRW_cache_screenspace_circle_get(void)
+{
+#define CIRCLE_RESOL 32
+ if (!SHC.drw_screenspace_circle) {
+ float v[3] = {0.0f, 0.0f, 0.0f};
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL + 1);
+
+ 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));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v);
+ }
+
+ SHC.drw_screenspace_circle = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_screenspace_circle;
+#undef CIRCLE_RESOL
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Common Object API
+ * \{ */
+
+Gwn_Batch *DRW_cache_object_wire_outline_get(Object *ob)
+{
+ switch (ob->type) {
+ case OB_MESH:
+ return DRW_cache_mesh_wire_outline_get(ob);
+
+ /* TODO, should match 'DRW_cache_object_surface_get' */
+ default:
+ return NULL;
+ }
+}
+
+Gwn_Batch *DRW_cache_object_surface_get(Object *ob)
+{
+ switch (ob->type) {
+ case OB_MESH:
+ return DRW_cache_mesh_surface_get(ob);
+ case OB_CURVE:
+ return DRW_cache_curve_surface_get(ob);
+ case OB_SURF:
+ return DRW_cache_surf_surface_get(ob);
+ case OB_FONT:
+ return DRW_cache_text_surface_get(ob);
+ case OB_MBALL:
+ return DRW_cache_mball_surface_get(ob);
+ default:
+ return NULL;
+ }
+}
+
+Gwn_Batch **DRW_cache_object_surface_material_get(
+ struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
+{
+ switch (ob->type) {
+ case OB_MESH:
+ return DRW_cache_mesh_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
+ default:
+ return NULL;
+ }
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Empties
+ * \{ */
+
+Gwn_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 Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 6);
+
+ for (axis = 0; axis < 3; axis++) {
+ v1[axis] = 1.0f;
+ v2[axis] = -1.0f;
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 2, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 2 + 1, v2);
+
+ /* reset v1 & v2 to zero for next axis */
+ v1[axis] = v2[axis] = 0.0f;
+ }
+
+ SHC.drw_plain_axes = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_plain_axes;
+}
+
+Gwn_Batch *DRW_cache_single_arrow_get(void)
+{
+ if (!SHC.drw_single_arrow) {
+ float v1[3] = {0.0f, 0.0f, 1.0f}, v2[3], v3[3];
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ /* Square Pyramid */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(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];
+ }
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 0, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 1, v2);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 2, v3);
+ }
+
+ SHC.drw_single_arrow = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_single_arrow;
+}
+
+Gwn_Batch *DRW_cache_empty_sphere_get(void)
+{
+ if (!SHC.drw_empty_sphere) {
+ Gwn_VertBuf *vbo = sphere_wire_vbo(1.0f);
+ SHC.drw_empty_sphere = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_empty_sphere;
+}
+
+Gwn_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 Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(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];
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4, v);
+ v[0] = 0.0f, v[1] = 2.0f, v[2] = 0.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 1, v);
+
+ /* end ring */
+ v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 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];
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 3, v);
+ }
+
+ SHC.drw_empty_cone = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_empty_cone;
+#undef NSEGMENTS
+}
+
+Gwn_Batch *DRW_cache_arrows_get(void)
+{
+ if (!SHC.drw_arrows) {
+ Gwn_VertBuf *vbo = fill_arrows_vbo(1.0f);
+
+ SHC.drw_arrows = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_arrows;
+}
+
+Gwn_Batch *DRW_cache_axis_names_get(void)
+{
+ if (!SHC.drw_axis_names) {
+ const float size = 0.1f;
+ float v1[3], v2[3];
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ /* Using 3rd component as axis indicator */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ /* Line */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 14);
+
+ /* X */
+ copy_v3_fl3(v1, -size, size, 0.0f);
+ copy_v3_fl3(v2, size, -size, 0.0f);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v2);
+
+ copy_v3_fl3(v1, size, size, 0.0f);
+ copy_v3_fl3(v2, -size, -size, 0.0f);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 2, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 3, v2);
+
+ /* Y */
+ copy_v3_fl3(v1, -size + 0.25f * size, size, 1.0f);
+ copy_v3_fl3(v2, 0.0f, 0.0f, 1.0f);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 4, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 5, v2);
+
+ copy_v3_fl3(v1, size - 0.25f * size, size, 1.0f);
+ copy_v3_fl3(v2, -size + 0.25f * size, -size, 1.0f);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 6, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 7, v2);
+
+ /* Z */
+ copy_v3_fl3(v1, -size, size, 2.0f);
+ copy_v3_fl3(v2, size, size, 2.0f);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 8, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 9, v2);
+
+ copy_v3_fl3(v1, size, size, 2.0f);
+ copy_v3_fl3(v2, -size, -size, 2.0f);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 10, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 11, v2);
+
+ copy_v3_fl3(v1, -size, -size, 2.0f);
+ copy_v3_fl3(v2, size, -size, 2.0f);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 12, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 13, v2);
+
+ SHC.drw_axis_names = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_axis_names;
+}
+
+Gwn_Batch *DRW_cache_image_plane_get(void)
+{
+ if (!SHC.drw_image_plane) {
+ const float quad[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, texCoords; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.texCoords = GWN_vertformat_attr_add(&format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 4);
+ for (uint j = 0; j < 4; j++) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, j, quad[j]);
+ GWN_vertbuf_attr_set(vbo, attr_id.texCoords, j, quad[j]);
+ }
+ SHC.drw_image_plane = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_image_plane;
+}
+
+Gwn_Batch *DRW_cache_image_plane_wire_get(void)
+{
+ if (!SHC.drw_image_plane_wire) {
+ const float quad[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 4);
+ for (uint j = 0; j < 4; j++) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, j, quad[j]);
+ }
+ SHC.drw_image_plane_wire = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_image_plane_wire;
+}
+
+/* Force Field */
+Gwn_Batch *DRW_cache_field_wind_get(void)
+{
+#define CIRCLE_RESOL 32
+ if (!SHC.drw_field_wind) {
+ float v[3] = {0.0f, 0.0f, 0.0f};
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 4);
+
+ for (int i = 0; i < 4; i++) {
+ float z = 0.05f * (float)i;
+ 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] = z;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + 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] = z;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
+ }
+ }
+
+ SHC.drw_field_wind = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_field_wind;
+#undef CIRCLE_RESOL
+}
+
+Gwn_Batch *DRW_cache_field_force_get(void)
+{
+#define CIRCLE_RESOL 32
+ if (!SHC.drw_field_force) {
+ float v[3] = {0.0f, 0.0f, 0.0f};
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 3);
+
+ for (int i = 0; i < 3; i++) {
+ float radius = 1.0f + 0.5f * (float)i;
+ for (int a = 0; a < CIRCLE_RESOL; a++) {
+ v[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[2] = 0.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2, v);
+
+ v[0] = radius * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ v[1] = radius * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ v[2] = 0.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2 + 1, v);
+ }
+ }
+
+ SHC.drw_field_force = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_field_force;
+#undef CIRCLE_RESOL
+}
+
+Gwn_Batch *DRW_cache_field_vortex_get(void)
+{
+#define SPIRAL_RESOL 32
+ if (!SHC.drw_field_vortex) {
+ float v[3] = {0.0f, 0.0f, 0.0f};
+ unsigned int v_idx = 0;
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, SPIRAL_RESOL * 2 + 1);
+
+ for (int a = SPIRAL_RESOL; a > -1; a--) {
+ v[0] = sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
+ v[1] = cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ }
+
+ for (int a = 1; a <= SPIRAL_RESOL; a++) {
+ v[0] = -sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
+ v[1] = -cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ }
+
+ SHC.drw_field_vortex = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_field_vortex;
+#undef SPIRAL_RESOL
+}
+
+Gwn_Batch *DRW_cache_field_tube_limit_get(void)
+{
+#define CIRCLE_RESOL 32
+ if (!SHC.drw_field_tube_limit) {
+ float v[3] = {0.0f, 0.0f, 0.0f};
+ unsigned int v_idx = 0;
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 + 8);
+
+ /* Caps */
+ for (int i = 0; i < 2; i++) {
+ float z = (float)i * 2.0f - 1.0f;
+ 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] = z;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, 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] = z;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ }
+ }
+ /* Side Edges */
+ for (int a = 0; a < 4; a++) {
+ for (int i = 0; i < 2; i++) {
+ float z = (float)i * 2.0f - 1.0f;
+ v[0] = sinf((2.0f * M_PI * a) / 4.0f);
+ v[1] = cosf((2.0f * M_PI * a) / 4.0f);
+ v[2] = z;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ }
+ }
+
+ SHC.drw_field_tube_limit = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_field_tube_limit;
+#undef CIRCLE_RESOL
+}
+
+Gwn_Batch *DRW_cache_field_cone_limit_get(void)
+{
+#define CIRCLE_RESOL 32
+ if (!SHC.drw_field_cone_limit) {
+ float v[3] = {0.0f, 0.0f, 0.0f};
+ unsigned int v_idx = 0;
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 + 8);
+
+ /* Caps */
+ for (int i = 0; i < 2; i++) {
+ float z = (float)i * 2.0f - 1.0f;
+ 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] = z;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, 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] = z;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ }
+ }
+ /* Side Edges */
+ for (int a = 0; a < 4; a++) {
+ for (int i = 0; i < 2; i++) {
+ float z = (float)i * 2.0f - 1.0f;
+ v[0] = z * sinf((2.0f * M_PI * a) / 4.0f);
+ v[1] = z * cosf((2.0f * M_PI * a) / 4.0f);
+ v[2] = z;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v);
+ }
+ }
+
+ SHC.drw_field_cone_limit = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_field_cone_limit;
+#undef CIRCLE_RESOL
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Lamps
+ * \{ */
+
+Gwn_Batch *DRW_cache_lamp_get(void)
+{
+#define NSEGMENTS 8
+ if (!SHC.drw_lamp) {
+ float v[2];
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(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));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 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));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2 + 1, v);
+ }
+
+ SHC.drw_lamp = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_lamp;
+#undef NSEGMENTS
+}
+
+Gwn_Batch *DRW_cache_lamp_sunrays_get(void)
+{
+ if (!SHC.drw_lamp_sunrays) {
+ float v[2], v1[2], v2[2];
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(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);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2 + 1, v2);
+ }
+
+ SHC.drw_lamp_sunrays = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_lamp_sunrays;
+}
+
+Gwn_Batch *DRW_cache_lamp_area_get(void)
+{
+ if (!SHC.drw_lamp_area) {
+ float v1[3] = {0.0f, 0.0f, 0.0f};
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 8);
+
+ v1[0] = v1[1] = 0.5f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
+ v1[0] = -0.5f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 2, v1);
+ v1[1] = -0.5f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 3, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 4, v1);
+ v1[0] = 0.5f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 5, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 6, v1);
+ v1[1] = 0.5f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 7, v1);
+
+ SHC.drw_lamp_area = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_lamp_area;
+}
+
+Gwn_Batch *DRW_cache_lamp_hemi_get(void)
+{
+#define CIRCLE_RESOL 32
+ if (!SHC.drw_lamp_hemi) {
+ float v[3];
+ int vidx = 0;
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 - 6 * 2 * 2);
+
+ /* XZ plane */
+ for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
+ v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2);
+ v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
+ v[1] = 0.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+
+ v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2);
+ v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
+ v[1] = 0.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ }
+
+ /* XY plane */
+ for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
+ v[2] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)) - 1.0f;
+ v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[0] = 0.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+
+ v[2] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)) - 1.0f;
+ v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ v[0] = 0.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ }
+
+ /* YZ plane full circle */
+ /* lease v[2] as it is */
+ const float rad = cosf((2.0f * M_PI * 3) / ((float)CIRCLE_RESOL));
+ for (int a = 0; a < CIRCLE_RESOL; a++) {
+ v[1] = rad * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[0] = rad * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+
+ v[1] = rad * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ v[0] = rad * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ }
+
+
+ SHC.drw_lamp_hemi = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_lamp_hemi;
+#undef CIRCLE_RESOL
+}
+
+
+Gwn_Batch *DRW_cache_lamp_spot_get(void)
+{
+#define NSEGMENTS 32
+ if (!SHC.drw_lamp_spot) {
+ /* a single ring of vertices */
+ float p[NSEGMENTS][2];
+ float n[NSEGMENTS][3];
+ float neg[NSEGMENTS][3];
+ float half_angle = 2 * M_PI / ((float)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);
+
+ n[i][0] = cosf(angle - half_angle);
+ n[i][1] = sinf(angle - half_angle);
+ n[i][2] = cosf(M_PI / 16.0f); /* slope of the cone */
+ normalize_v3(n[i]); /* necessary ? */
+ negate_v3_v3(neg[i], n[i]);
+ }
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, n1, n2; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.n1 = GWN_vertformat_attr_add(&format, "N1", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.n2 = GWN_vertformat_attr_add(&format, "N2", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(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] = cv[1], v[2] = -1.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4, v);
+ v[0] = 0.0f, v[1] = 0.0f, v[2] = 0.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 1, v);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4, n[(i) % NSEGMENTS]);
+ GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 1, n[(i) % NSEGMENTS]);
+ GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4, n[(i + 1) % NSEGMENTS]);
+ GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 1, n[(i + 1) % NSEGMENTS]);
+
+ /* end ring */
+ v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 2, v);
+ cv[0] = p[(i + 1) % NSEGMENTS][0];
+ cv[1] = p[(i + 1) % NSEGMENTS][1];
+ v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 3, v);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 2, n[(i) % NSEGMENTS]);
+ GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 3, n[(i) % NSEGMENTS]);
+ GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 2, neg[(i) % NSEGMENTS]);
+ GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 3, neg[(i) % NSEGMENTS]);
+ }
+
+ SHC.drw_lamp_spot = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_lamp_spot;
+#undef NSEGMENTS
+}
+
+Gwn_Batch *DRW_cache_lamp_spot_square_get(void)
+{
+ if (!SHC.drw_lamp_spot_square) {
+ float p[5][3] = {{ 0.0f, 0.0f, 0.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}};
+
+ unsigned int v_idx = 0;
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 16);
+
+ /* piramid sides */
+ for (int i = 1; i <= 4; ++i) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[0]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[i]);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[(i % 4) + 1]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[((i + 1) % 4) + 1]);
+ }
+
+ SHC.drw_lamp_spot_square = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_lamp_spot_square;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Speaker
+ * \{ */
+
+Gwn_Batch *DRW_cache_speaker_get(void)
+{
+ if (!SHC.drw_speaker) {
+ float v[3];
+ const int segments = 16;
+ int vidx = 0;
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 3 * segments * 2 + 4 * 4);
+
+ for (int j = 0; j < 3; j++) {
+ float z = 0.25f * j - 0.125f;
+ float r = (j == 0 ? 0.5f : 0.25f);
+
+ copy_v3_fl3(v, r, 0.0f, z);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ for (int i = 1; i < segments; i++) {
+ float x = cosf(2.f * (float)M_PI * i / segments) * r;
+ float y = sinf(2.f * (float)M_PI * i / segments) * r;
+ copy_v3_fl3(v, x, y, z);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ }
+ copy_v3_fl3(v, r, 0.0f, z);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ }
+
+ for (int j = 0; j < 4; j++) {
+ float x = (((j + 1) % 2) * (j - 1)) * 0.5f;
+ float y = ((j % 2) * (j - 2)) * 0.5f;
+ for (int i = 0; i < 3; i++) {
+ if (i == 1) {
+ x *= 0.5f;
+ y *= 0.5f;
+ }
+
+ float z = 0.25f * i - 0.125f;
+ copy_v3_fl3(v, x, y, z);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ if (i == 1) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v);
+ }
+ }
+ }
+
+ SHC.drw_speaker = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_speaker;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Probe
+ * \{ */
+
+Gwn_Batch *DRW_cache_lightprobe_cube_get(void)
+{
+ if (!SHC.drw_lightprobe_cube) {
+ int v_idx = 0;
+ const float sin_pi_3 = 0.86602540378f;
+ const float cos_pi_3 = 0.5f;
+ float v[7][3] = {
+ {0.0f, 1.0f, 0.0f},
+ {sin_pi_3, cos_pi_3, 0.0f},
+ {sin_pi_3, -cos_pi_3, 0.0f},
+ {0.0f, -1.0f, 0.0f},
+ {-sin_pi_3, -cos_pi_3, 0.0f},
+ {-sin_pi_3, cos_pi_3, 0.0f},
+ {0.0f, 0.0f, 0.0f},
+ };
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, (6 + 3) * 2);
+
+ for (int i = 0; i < 6; ++i) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[i]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[(i + 1) % 6]);
+ }
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[1]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[5]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[3]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+
+ SHC.drw_lightprobe_cube = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_lightprobe_cube;
+}
+
+Gwn_Batch *DRW_cache_lightprobe_grid_get(void)
+{
+ if (!SHC.drw_lightprobe_grid) {
+ int v_idx = 0;
+ const float sin_pi_3 = 0.86602540378f;
+ const float cos_pi_3 = 0.5f;
+ const float v[7][3] = {
+ {0.0f, 1.0f, 0.0f},
+ {sin_pi_3, cos_pi_3, 0.0f},
+ {sin_pi_3, -cos_pi_3, 0.0f},
+ {0.0f, -1.0f, 0.0f},
+ {-sin_pi_3, -cos_pi_3, 0.0f},
+ {-sin_pi_3, cos_pi_3, 0.0f},
+ {0.0f, 0.0f, 0.0f},
+ };
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, (6 * 2 + 3) * 2);
+
+ for (int i = 0; i < 6; ++i) {
+ float tmp_v1[3], tmp_v2[3], tmp_tr[3];
+ copy_v3_v3(tmp_v1, v[i]);
+ copy_v3_v3(tmp_v2, v[(i + 1) % 6]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v2);
+
+ /* Internal wires. */
+ for (int j = 1; j < 2; ++j) {
+ mul_v3_v3fl(tmp_tr, v[(i / 2) * 2 + 1], -0.5f * j);
+ add_v3_v3v3(tmp_v1, v[i], tmp_tr);
+ add_v3_v3v3(tmp_v2, v[(i + 1) % 6], tmp_tr);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v2);
+ }
+ }
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[1]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[5]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[3]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]);
+
+ SHC.drw_lightprobe_grid = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_lightprobe_grid;
+}
+
+Gwn_Batch *DRW_cache_lightprobe_planar_get(void)
+{
+ if (!SHC.drw_lightprobe_planar) {
+ int v_idx = 0;
+ const float sin_pi_3 = 0.86602540378f;
+ float v[4][3] = {
+ {0.0f, 0.5f, 0.0f},
+ {sin_pi_3, 0.0f, 0.0f},
+ {0.0f, -0.5f, 0.0f},
+ {-sin_pi_3, 0.0f, 0.0f},
+ };
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 4 * 2);
+
+ for (int i = 0; i < 4; ++i) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[i]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[(i + 1) % 4]);
+ }
+
+ SHC.drw_lightprobe_planar = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_lightprobe_planar;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Armature Bones
+ * \{ */
+
+static const float bone_octahedral_verts[6][3] = {
+ { 0.0f, 0.0f, 0.0f},
+ { 0.1f, 0.1f, 0.1f},
+ { 0.1f, 0.1f, -0.1f},
+ {-0.1f, 0.1f, -0.1f},
+ {-0.1f, 0.1f, 0.1f},
+ { 0.0f, 1.0f, 0.0f}
+};
+
+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,
+};
+
+/* aligned with bone_octahedral_wire
+ * Contains adjacent normal index */
+static const unsigned int bone_octahedral_wire_adjacent_face[24] = {
+ 0, 3, 4, 7, 5, 6, 1, 2,
+ 2, 3, 6, 7, 4, 5, 0, 1,
+ 0, 4, 1, 5, 2, 6, 3, 7,
+};
+
+static const unsigned int bone_octahedral_solid_tris[8][3] = {
+ {2, 1, 0}, /* bottom */
+ {3, 2, 0},
+ {4, 3, 0},
+ {1, 4, 0},
+
+ {5, 1, 2}, /* top */
+ {5, 2, 3},
+ {5, 3, 4},
+ {5, 4, 1}
+};
+
+/* aligned with bone_octahedral_solid_tris */
+static const float bone_octahedral_solid_normals[8][3] = {
+ { M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
+ {-0.00000000f, -M_SQRT1_2, -M_SQRT1_2},
+ {-M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
+ { 0.00000000f, -M_SQRT1_2, M_SQRT1_2},
+ { 0.99388373f, 0.11043154f, -0.00000000f},
+ { 0.00000000f, 0.11043154f, -0.99388373f},
+ {-0.99388373f, 0.11043154f, 0.00000000f},
+ { 0.00000000f, 0.11043154f, 0.99388373f}
+};
+
+Gwn_Batch *DRW_cache_bone_octahedral_get(void)
+{
+ if (!SHC.drw_bone_octahedral) {
+ unsigned int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, nor; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 24);
+
+ for (int i = 0; i < 8; i++) {
+ GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]);
+ GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]);
+ GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]);
+ }
+
+ SHC.drw_bone_octahedral = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_octahedral;
+}
+
+Gwn_Batch *DRW_cache_bone_octahedral_wire_outline_get(void)
+{
+ if (!SHC.drw_bone_octahedral_wire) {
+ unsigned int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, n1, n2; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.n1 = GWN_vertformat_attr_add(&format, "N1", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.n2 = GWN_vertformat_attr_add(&format, "N2", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 12 * 2);
+
+ for (int i = 0; i < 12; i++) {
+ const float *co1 = bone_octahedral_verts[bone_octahedral_wire[i * 2]];
+ const float *co2 = bone_octahedral_verts[bone_octahedral_wire[i * 2 + 1]];
+ const float *n1 = bone_octahedral_solid_normals[bone_octahedral_wire_adjacent_face[i * 2]];
+ const float *n2 = bone_octahedral_solid_normals[bone_octahedral_wire_adjacent_face[i * 2 + 1]];
+ add_fancy_edge(vbo, attr_id.pos, attr_id.n1, attr_id.n2, &v_idx, co1, co2, n1, n2);
+ }
+
+ SHC.drw_bone_octahedral_wire = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_octahedral_wire;
+}
+
+
+/* XXX TODO move that 1 unit cube to more common/generic place? */
+static const float bone_box_verts[8][3] = {
+ { 1.0f, 0.0f, 1.0f},
+ { 1.0f, 0.0f, -1.0f},
+ {-1.0f, 0.0f, -1.0f},
+ {-1.0f, 0.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}
+};
+
+static const unsigned int bone_box_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,
+};
+
+/* aligned with bone_octahedral_wire
+ * Contains adjacent normal index */
+static const unsigned int bone_box_wire_adjacent_face[24] = {
+ 0, 2, 0, 4, 1, 6, 1, 8,
+ 3, 10, 5, 10, 7, 11, 9, 11,
+ 3, 8, 2, 5, 4, 7, 6, 9,
+};
+
+static const unsigned int bone_box_solid_tris[12][3] = {
+ {0, 1, 2}, /* bottom */
+ {0, 2, 3},
+
+ {0, 1, 5}, /* sides */
+ {0, 5, 4},
+
+ {1, 2, 6},
+ {1, 6, 5},
+
+ {2, 3, 7},
+ {2, 7, 6},
+
+ {3, 0, 4},
+ {3, 4, 7},
+
+ {4, 5, 6}, /* top */
+ {4, 6, 7},
+};
+
+/* aligned with bone_octahedral_solid_tris */
+static const float bone_box_solid_normals[12][3] = {
+ { 0.0f, -1.0f, 0.0f},
+ { 0.0f, -1.0f, 0.0f},
+
+ { 1.0f, 0.0f, 0.0f},
+ { 1.0f, 0.0f, 0.0f},
+
+ { 0.0f, 0.0f, -1.0f},
+ { 0.0f, 0.0f, -1.0f},
+
+ {-1.0f, 0.0f, 0.0f},
+ {-1.0f, 0.0f, 0.0f},
+
+ { 0.0f, 0.0f, 1.0f},
+ { 0.0f, 0.0f, 1.0f},
+
+ { 0.0f, 1.0f, 0.0f},
+ { 0.0f, 1.0f, 0.0f},
+};
+
+Gwn_Batch *DRW_cache_bone_box_get(void)
+{
+ if (!SHC.drw_bone_box) {
+ unsigned int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, nor; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 36);
+
+ for (int i = 0; i < 12; i++) {
+ for (int j = 0; j < 3; j++) {
+ GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_box_solid_normals[i]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_box_verts[bone_box_solid_tris[i][j]]);
+ }
+ }
+
+ SHC.drw_bone_box = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_box;
+}
+
+Gwn_Batch *DRW_cache_bone_box_wire_outline_get(void)
+{
+ if (!SHC.drw_bone_box_wire) {
+ unsigned int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, n1, n2; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.n1 = GWN_vertformat_attr_add(&format, "N1", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.n2 = GWN_vertformat_attr_add(&format, "N2", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 12 * 2);
+
+ for (int i = 0; i < 12; i++) {
+ const float *co1 = bone_box_verts[bone_box_wire[i * 2]];
+ const float *co2 = bone_box_verts[bone_box_wire[i * 2 + 1]];
+ const float *n1 = bone_box_solid_normals[bone_box_wire_adjacent_face[i * 2]];
+ const float *n2 = bone_box_solid_normals[bone_box_wire_adjacent_face[i * 2 + 1]];
+ add_fancy_edge(vbo, attr_id.pos, attr_id.n1, attr_id.n2, &v_idx, co1, co2, n1, n2);
+ }
+
+ SHC.drw_bone_box_wire = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_box_wire;
+}
+
+
+Gwn_Batch *DRW_cache_bone_wire_wire_outline_get(void)
+{
+ if (!SHC.drw_bone_wire_wire) {
+ unsigned int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, n1, n2; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.n1 = GWN_vertformat_attr_add(&format, "N1", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.n2 = GWN_vertformat_attr_add(&format, "N2", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 2);
+
+ const float co1[3] = {0.0f, 0.0f, 0.0f};
+ const float co2[3] = {0.0f, 1.0f, 0.0f};
+ const float n[3] = {1.0f, 0.0f, 0.0f};
+ add_fancy_edge(vbo, attr_id.pos, attr_id.n1, attr_id.n2, &v_idx, co1, co2, n, n);
+
+ SHC.drw_bone_wire_wire = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_wire_wire;
+}
+
+
+/* Helpers for envelope bone's solid sphere-with-hidden-equatorial-cylinder.
+ * Note that here we only encode head/tail in forth component of the vector. */
+static void benv_lat_lon_to_co(const float lat, const float lon, float r_nor[3])
+{
+ /* Poles are along Y axis. */
+ r_nor[0] = sinf(lat) * cosf(lon);
+ r_nor[1] = cosf(lat);
+ r_nor[2] = sinf(lat) * sinf(lon);
+}
+
+static void benv_add_tri(Gwn_VertBuf *vbo, uint pos_id, uint *v_idx, float *co1, float *co2, float *co3)
+{
+ /* Given tri and its seven other mirrors along X/Y/Z axes. */
+ for (int x = -1; x <= 1; x += 2) {
+ for (int y = -1; y <= 1; y += 2) {
+ const float head_tail = (y == -1) ? 0.0f : 1.0f;
+ for (int z = -1; z <= 1; z += 2) {
+ GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++,
+ (const float[4]){co1[0] * x, co1[1] * y, co1[2] * z, head_tail});
+ GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++,
+ (const float[4]){co2[0] * x, co2[1] * y, co2[2] * z, head_tail});
+ GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++,
+ (const float[4]){co3[0] * x, co3[1] * y, co3[2] * z, head_tail});
+ }
+ }
+ }
+}
+
+Gwn_Batch *DRW_cache_bone_envelope_solid_get(void)
+{
+#define CIRCLE_RESOL 32 /* Must be multiple of 4 */
+ if (!SHC.drw_bone_envelope) {
+ const int lon_res = CIRCLE_RESOL / 4;
+ const int lat_res = CIRCLE_RESOL / 4;
+ const float lon_inc = M_PI_2 / lon_res;
+ const float lat_inc = M_PI_2 / lat_res;
+ unsigned int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, lat_res * lon_res * 8 * 6);
+
+ float lon = 0.0f;
+ for (int i = 0; i < lon_res; i++, lon += lon_inc) {
+ float lat = 0.0f;
+ float co1[3], co2[3], co3[3], co4[3];
+
+ for (int j = 0; j < lat_res; j++, lat += lat_inc) {
+ benv_lat_lon_to_co(lat, lon, co1);
+ benv_lat_lon_to_co(lat, lon + lon_inc, co2);
+ benv_lat_lon_to_co(lat + lat_inc, lon + lon_inc, co3);
+ benv_lat_lon_to_co(lat + lat_inc, lon, co4);
+
+ if (j != 0) { /* At pole, n1 and n2 are identical. */
+ benv_add_tri(vbo, attr_id.pos, &v_idx, co1, co2, co3);
+ }
+ benv_add_tri(vbo, attr_id.pos, &v_idx, co1, co3, co4);
+ }
+
+ /* lat is at equator (i.e. lat == pi / 2). */
+ /* We need to add 'cylinder' part between the equators (along XZ plane). */
+ for (int x = -1; x <= 1; x += 2) {
+ for (int z = -1; z <= 1; z += 2) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++,
+ (const float[4]){co3[0] * x, co3[1], co3[2] * z, 0.0f});
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++,
+ (const float[4]){co4[0] * x, co4[1], co4[2] * z, 0.0f});
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++,
+ (const float[4]){co4[0] * x, co4[1], co4[2] * z, 1.0f});
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++,
+ (const float[4]){co3[0] * x, co3[1], co3[2] * z, 0.0f});
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++,
+ (const float[4]){co4[0] * x, co4[1], co4[2] * z, 1.0f});
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++,
+ (const float[4]){co3[0] * x, co3[1], co3[2] * z, 1.0f});
+ }
+ }
+ }
+
+ SHC.drw_bone_envelope = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_envelope;
+}
+
+
+Gwn_Batch *DRW_cache_bone_envelope_distance_outline_get(void)
+{
+#define CIRCLE_RESOL 32 /* Must be multiple of 2 */
+ if (!SHC.drw_bone_envelope_distance) {
+ unsigned int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static unsigned int pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 + 6);
+
+ /* Encoded triangle strip, vertex shader gives them final correct value. */
+ for (int i = 0; i < CIRCLE_RESOL + 1; i++) {
+ const bool is_headtail_transition = ELEM(i, CIRCLE_RESOL / 2, CIRCLE_RESOL);
+ const float head_tail = (i > CIRCLE_RESOL / 2) ? 1.0f : 0.0f;
+ const float alpha = 2.0f * M_PI * i / CIRCLE_RESOL;
+ const float x = cosf(alpha);
+ const float y = -sinf(alpha);
+
+ /* { X, Y, head/tail, inner/outer border } */
+ GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){x, y, head_tail, 0.0f});
+ GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){x, y, head_tail, 1.0f});
+ if (is_headtail_transition) {
+ GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){x, y, 1.0f - head_tail, 0.0f});
+ GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){x, y, 1.0f - head_tail, 1.0f});
+ }
+ }
+
+ SHC.drw_bone_envelope_distance = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_envelope_distance;
+#undef CIRCLE_RESOL
+}
+
+
+/* Bone body. */
+Gwn_Batch *DRW_cache_bone_envelope_wire_outline_get(void)
+{
+ if (!SHC.drw_bone_envelope_wire) {
+ unsigned int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static unsigned int pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 4);
+
+ /* Two lines between head and tail circles. */
+ /* Encoded lines, vertex shader gives them final correct value. */
+ /* { X, Y, head/tail, inner/outer border } */
+ GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){ 1.0f, 0.0f, 0.0f, 0.0f});
+ GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){ 1.0f, 0.0f, 1.0f, 0.0f});
+ GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){-1.0f, 0.0f, 0.0f, 0.0f});
+ GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){-1.0f, 0.0f, 1.0f, 0.0f});
+
+ SHC.drw_bone_envelope_wire = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_envelope_wire;
+}
+
+
+/* Bone head and tail. */
+Gwn_Batch *DRW_cache_bone_envelope_head_wire_outline_get(void)
+{
+#define CIRCLE_RESOL 32 /* Must be multiple of 2 */
+ if (!SHC.drw_bone_envelope_head_wire) {
+ unsigned int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static unsigned int pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL);
+
+ /* Encoded lines, vertex shader gives them final correct value. */
+ /* Only head circle (tail is drawn in disp_tail_mat space as a head one by draw_armature.c's draw_point()). */
+ for (int i = 0; i < CIRCLE_RESOL; i++) {
+ const float alpha = 2.0f * M_PI * i / CIRCLE_RESOL;
+ const float x = cosf(alpha);
+ const float y = -sinf(alpha);
+
+ /* { X, Y, head/tail, inner/outer border } */
+ GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){ x, y, 0.0f, 0.0f});
+ }
+
+ SHC.drw_bone_envelope_head_wire = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_envelope_head_wire;
+#undef CIRCLE_RESOL
+}
+
+
+Gwn_Batch *DRW_cache_bone_point_get(void)
+{
+ if (!SHC.drw_bone_point) {
+ const int lon_res = 16;
+ const int lat_res = 8;
+ const float rad = 0.05f;
+ const float lon_inc = 2 * M_PI / lon_res;
+ const float lat_inc = M_PI / lat_res;
+ unsigned int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, nor; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, (lat_res - 1) * lon_res * 6);
+
+ float lon = 0.0f;
+ for (int i = 0; i < lon_res; i++, lon += lon_inc) {
+ float lat = 0.0f;
+ for (int j = 0; j < lat_res; j++, lat += lat_inc) {
+ if (j != lat_res - 1) { /* Pole */
+ add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc);
+ add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon);
+ add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon);
+ }
+
+ if (j != 0) { /* Pole */
+ add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon + lon_inc);
+ add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc);
+ add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon);
+ }
+ }
+ }
+
+ SHC.drw_bone_point = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_point;
+}
+
+Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void)
+{
+ if (!SHC.drw_bone_point_wire) {
+ Gwn_VertBuf *vbo = sphere_wire_vbo(0.05f);
+ SHC.drw_bone_point_wire = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_point_wire;
+}
+
+Gwn_Batch *DRW_cache_bone_arrows_get(void)
+{
+ if (!SHC.drw_bone_arrows) {
+ Gwn_VertBuf *vbo = fill_arrows_vbo(0.25f);
+ SHC.drw_bone_arrows = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_bone_arrows;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Camera
+ * \{ */
+
+Gwn_Batch *DRW_cache_camera_get(void)
+{
+ if (!SHC.drw_camera) {
+ float v0 = 0.0f; /* Center point */
+ float v1 = 1.0f; /* + X + Y */
+ float v2 = 2.0f; /* + X - Y */
+ float v3 = 3.0f; /* - X - Y */
+ float v4 = 4.0f; /* - X + Y */
+ float v5 = 5.0f; /* tria + X */
+ float v6 = 6.0f; /* tria - X */
+ float v7 = 7.0f; /* tria + Y */
+ int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ /* use x coordinate to identify the vertex
+ * the vertex shader take care to place it
+ * appropriatelly */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 22);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v1);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v2);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v3);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v4);
+
+ /* camera frame */
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v2);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v2);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v3);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v3);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v4);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v4);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v1);
+
+ /* tria */
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v5);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v6);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v6);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v7);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v7);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v5);
+
+ SHC.drw_camera = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_camera;
+}
+
+Gwn_Batch *DRW_cache_camera_tria_get(void)
+{
+ if (!SHC.drw_camera_tria) {
+ float v5 = 5.0f; /* tria + X */
+ float v6 = 6.0f; /* tria - X */
+ float v7 = 7.0f; /* tria + Y */
+ int v_idx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ /* use x coordinate to identify the vertex
+ * the vertex shader take care to place it
+ * appropriatelly */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ }
+
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 6);
+
+ /* tria */
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v5);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v6);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v7);
+
+ SHC.drw_camera_tria = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_camera_tria;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Object Mode Helpers
+ * \{ */
+
+/* Object Center */
+Gwn_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 Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 1);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1);
+
+ SHC.drw_single_vertice = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_single_vertice;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Meshes
+ * \{ */
+
+Gwn_Batch *DRW_cache_mesh_surface_overlay_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_all_triangles(me);
+}
+
+void DRW_cache_mesh_wire_overlay_get(
+ Object *ob,
+ Gwn_Batch **r_tris, Gwn_Batch **r_ledges, Gwn_Batch **r_lverts)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+
+ *r_tris = DRW_mesh_batch_cache_get_overlay_triangles(me);
+ *r_ledges = DRW_mesh_batch_cache_get_overlay_loose_edges(me);
+ *r_lverts = DRW_mesh_batch_cache_get_overlay_loose_verts(me);
+}
+
+void DRW_cache_mesh_normals_overlay_get(
+ Object *ob,
+ Gwn_Batch **r_tris, Gwn_Batch **r_ledges, Gwn_Batch **r_lverts)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+
+ *r_tris = DRW_mesh_batch_cache_get_overlay_triangles_nor(me);
+ *r_ledges = DRW_mesh_batch_cache_get_overlay_loose_edges_nor(me);
+ *r_lverts = DRW_mesh_batch_cache_get_overlay_loose_verts(me);
+}
+
+Gwn_Batch *DRW_cache_face_centers_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+
+ return DRW_mesh_batch_cache_get_overlay_facedots(me);
+}
+
+Gwn_Batch *DRW_cache_mesh_wire_outline_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_fancy_edges(me);
+}
+
+Gwn_Batch *DRW_cache_mesh_surface_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_triangles_with_normals(me);
+}
+
+Gwn_Batch *DRW_cache_mesh_surface_weights_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(me, ob->actdef - 1);
+}
+
+Gwn_Batch *DRW_cache_mesh_surface_vert_colors_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(me);
+}
+
+/* Return list of batches */
+Gwn_Batch **DRW_cache_mesh_surface_shaded_get(
+ Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_surface_shaded(me, gpumat_array, gpumat_array_len);
+}
+
+/* Return list of batches */
+Gwn_Batch **DRW_cache_mesh_surface_texpaint_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_surface_texpaint(me);
+}
+
+Gwn_Batch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_surface_texpaint_single(me);
+}
+
+Gwn_Batch *DRW_cache_mesh_surface_verts_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_points_with_normals(me);
+}
+
+Gwn_Batch *DRW_cache_mesh_edges_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_all_edges(me);
+}
+
+Gwn_Batch *DRW_cache_mesh_verts_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_all_verts(me);
+}
+
+Gwn_Batch *DRW_cache_mesh_edges_paint_overlay_get(Object *ob, bool use_wire, bool use_sel)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_weight_overlay_edges(me, use_wire, use_sel);
+}
+
+Gwn_Batch *DRW_cache_mesh_faces_weight_overlay_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_weight_overlay_faces(me);
+}
+
+Gwn_Batch *DRW_cache_mesh_verts_weight_overlay_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_weight_overlay_verts(me);
+}
+
+void DRW_cache_mesh_sculpt_coords_ensure(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ DRW_mesh_cache_sculpt_coords_ensure(me);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Curve
+ * \{ */
+
+Gwn_Batch *DRW_cache_curve_edge_wire_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_CURVE);
+
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_wire_edge(cu, ob->curve_cache);
+}
+
+Gwn_Batch *DRW_cache_curve_edge_normal_get(Object *ob, float normal_size)
+{
+ BLI_assert(ob->type == OB_CURVE);
+
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_normal_edge(cu, ob->curve_cache, normal_size);
+}
+
+Gwn_Batch *DRW_cache_curve_edge_overlay_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_CURVE);
+
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_overlay_edges(cu);
+}
+
+Gwn_Batch *DRW_cache_curve_vert_overlay_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_CURVE);
+
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_overlay_verts(cu);
+}
+
+Gwn_Batch *DRW_cache_curve_surface_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_CURVE);
+
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name MetaBall
+ * \{ */
+
+Gwn_Batch *DRW_cache_mball_surface_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MBALL);
+ return DRW_metaball_batch_cache_get_triangles_with_normals(ob);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Font
+ * \{ */
+
+Gwn_Batch *DRW_cache_text_edge_wire_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_FONT);
+
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_wire_edge(cu, ob->curve_cache);
+}
+
+Gwn_Batch *DRW_cache_text_surface_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_FONT);
+ struct Curve *cu = ob->data;
+ if (cu->editfont && (cu->flag & CU_FAST)) {
+ return NULL;
+ }
+ return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
+}
+
+Gwn_Batch *DRW_cache_text_cursor_overlay_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_FONT);
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_overlay_cursor(cu);
+}
+
+Gwn_Batch *DRW_cache_text_select_overlay_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_FONT);
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_overlay_select(cu);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Surface
+ * \{ */
+
+Gwn_Batch *DRW_cache_surf_surface_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_SURF);
+
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Lattice
+ * \{ */
+
+Gwn_Batch *DRW_cache_lattice_verts_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_LATTICE);
+
+ struct Lattice *lt = ob->data;
+ return DRW_lattice_batch_cache_get_all_verts(lt);
+}
+
+Gwn_Batch *DRW_cache_lattice_wire_get(Object *ob, bool use_weight)
+{
+ BLI_assert(ob->type == OB_LATTICE);
+
+ Lattice *lt = ob->data;
+ int actdef = -1;
+
+ if (use_weight && ob->defbase.first && lt->editlatt->latt->dvert) {
+ actdef = ob->actdef - 1;
+ }
+
+ return DRW_lattice_batch_cache_get_all_edges(lt, use_weight, actdef);
+}
+
+Gwn_Batch *DRW_cache_lattice_vert_overlay_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_LATTICE);
+
+ struct Lattice *lt = ob->data;
+ return DRW_lattice_batch_cache_get_overlay_verts(lt);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Particles
+ * \{ */
+
+Gwn_Batch *DRW_cache_particles_get_hair(ParticleSystem *psys, ModifierData *md)
+{
+ return DRW_particles_batch_cache_get_hair(psys, md);
+}
+
+Gwn_Batch *DRW_cache_particles_get_dots(ParticleSystem *psys)
+{
+ return DRW_particles_batch_cache_get_dots(psys);
+}
+
+Gwn_Batch *DRW_cache_particles_get_prim(int type)
+{
+ switch (type) {
+ case PART_DRAW_CROSS:
+ if (!SHC.drw_particle_cross) {
+ static Gwn_VertFormat format = { 0 };
+ static unsigned pos_id, axis_id;
+
+ if (format.attrib_ct == 0) {
+ pos_id = GWN_vertformat_attr_add(&format, "inst_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ axis_id = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 6);
+
+ /* X axis */
+ float co[3] = {-1.0f, 0.0f, 0.0f};
+ int axis = -1;
+ GWN_vertbuf_attr_set(vbo, pos_id, 0, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 0, &axis);
+
+ co[0] = 1.0f;
+ GWN_vertbuf_attr_set(vbo, pos_id, 1, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 1, &axis);
+
+ /* Y axis */
+ co[0] = 0.0f;
+ co[1] = -1.0f;
+ GWN_vertbuf_attr_set(vbo, pos_id, 2, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 2, &axis);
+
+ co[1] = 1.0f;
+ GWN_vertbuf_attr_set(vbo, pos_id, 3, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 3, &axis);
+
+ /* Z axis */
+ co[1] = 0.0f;
+ co[2] = -1.0f;
+ GWN_vertbuf_attr_set(vbo, pos_id, 4, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 4, &axis);
+
+ co[2] = 1.0f;
+ GWN_vertbuf_attr_set(vbo, pos_id, 5, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 5, &axis);
+
+ SHC.drw_particle_cross = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+
+ return SHC.drw_particle_cross;
+ case PART_DRAW_AXIS:
+ if (!SHC.drw_particle_axis) {
+ static Gwn_VertFormat format = { 0 };
+ static unsigned pos_id, axis_id;
+
+ if (format.attrib_ct == 0) {
+ pos_id = GWN_vertformat_attr_add(&format, "inst_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ axis_id = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 6);
+
+ /* X axis */
+ float co[3] = {0.0f, 0.0f, 0.0f};
+ int axis = 0;
+ GWN_vertbuf_attr_set(vbo, pos_id, 0, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 0, &axis);
+
+ co[0] = 1.0f;
+ GWN_vertbuf_attr_set(vbo, pos_id, 1, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 1, &axis);
+
+ /* Y axis */
+ co[0] = 0.0f;
+ axis = 1;
+ GWN_vertbuf_attr_set(vbo, pos_id, 2, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 2, &axis);
+
+ co[1] = 1.0f;
+ GWN_vertbuf_attr_set(vbo, pos_id, 3, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 3, &axis);
+
+ /* Z axis */
+ co[1] = 0.0f;
+ axis = 2;
+ GWN_vertbuf_attr_set(vbo, pos_id, 4, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 4, &axis);
+
+ co[2] = 1.0f;
+ GWN_vertbuf_attr_set(vbo, pos_id, 5, co);
+ GWN_vertbuf_attr_set(vbo, axis_id, 5, &axis);
+
+ SHC.drw_particle_axis = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+
+ return SHC.drw_particle_axis;
+ case PART_DRAW_CIRC:
+#define CIRCLE_RESOL 32
+ if (!SHC.drw_particle_circle) {
+ float v[3] = {0.0f, 0.0f, 0.0f};
+ int axis = -1;
+
+ static Gwn_VertFormat format = { 0 };
+ static unsigned pos_id, axis_id;
+
+ if (format.attrib_ct == 0) {
+ pos_id = GWN_vertformat_attr_add(&format, "inst_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ axis_id = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL);
+
+ 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;
+ GWN_vertbuf_attr_set(vbo, pos_id, a, v);
+ GWN_vertbuf_attr_set(vbo, axis_id, a, &axis);
+ }
+
+ SHC.drw_particle_circle = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+
+ return SHC.drw_particle_circle;
+#undef CIRCLE_RESOL
+ default:
+ BLI_assert(false);
+ break;
+ }
+
+ return NULL;
+}
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
new file mode 100644
index 00000000000..35ac8f4a35d
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache.h
@@ -0,0 +1,163 @@
+/*
+ * 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 Gwn_Batch;
+struct GPUMaterial;
+struct Object;
+struct ModifierData;
+
+void DRW_shape_cache_free(void);
+
+/* Common Shapes */
+struct Gwn_Batch *DRW_cache_fullscreen_quad_get(void);
+struct Gwn_Batch *DRW_cache_quad_get(void);
+struct Gwn_Batch *DRW_cache_sphere_get(void);
+struct Gwn_Batch *DRW_cache_single_vert_get(void);
+struct Gwn_Batch *DRW_cache_single_line_get(void);
+struct Gwn_Batch *DRW_cache_single_line_endpoints_get(void);
+struct Gwn_Batch *DRW_cache_screenspace_circle_get(void);
+
+/* Common Object */
+struct Gwn_Batch *DRW_cache_object_wire_outline_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_object_surface_get(struct Object *ob);
+struct Gwn_Batch **DRW_cache_object_surface_material_get(
+ struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
+
+/* Empties */
+struct Gwn_Batch *DRW_cache_plain_axes_get(void);
+struct Gwn_Batch *DRW_cache_single_arrow_get(void);
+struct Gwn_Batch *DRW_cache_cube_get(void);
+struct Gwn_Batch *DRW_cache_circle_get(void);
+struct Gwn_Batch *DRW_cache_square_get(void);
+struct Gwn_Batch *DRW_cache_empty_sphere_get(void);
+struct Gwn_Batch *DRW_cache_empty_cone_get(void);
+struct Gwn_Batch *DRW_cache_arrows_get(void);
+struct Gwn_Batch *DRW_cache_axis_names_get(void);
+struct Gwn_Batch *DRW_cache_image_plane_get(void);
+struct Gwn_Batch *DRW_cache_image_plane_wire_get(void);
+
+/* Force Field */
+struct Gwn_Batch *DRW_cache_field_wind_get(void);
+struct Gwn_Batch *DRW_cache_field_force_get(void);
+struct Gwn_Batch *DRW_cache_field_vortex_get(void);
+struct Gwn_Batch *DRW_cache_field_tube_limit_get(void);
+struct Gwn_Batch *DRW_cache_field_cone_limit_get(void);
+
+/* Lamps */
+struct Gwn_Batch *DRW_cache_lamp_get(void);
+struct Gwn_Batch *DRW_cache_lamp_sunrays_get(void);
+struct Gwn_Batch *DRW_cache_lamp_area_get(void);
+struct Gwn_Batch *DRW_cache_lamp_hemi_get(void);
+struct Gwn_Batch *DRW_cache_lamp_spot_get(void);
+struct Gwn_Batch *DRW_cache_lamp_spot_square_get(void);
+
+/* Camera */
+struct Gwn_Batch *DRW_cache_camera_get(void);
+struct Gwn_Batch *DRW_cache_camera_tria_get(void);
+
+/* Speaker */
+struct Gwn_Batch *DRW_cache_speaker_get(void);
+
+/* Probe */
+struct Gwn_Batch *DRW_cache_lightprobe_cube_get(void);
+struct Gwn_Batch *DRW_cache_lightprobe_grid_get(void);
+struct Gwn_Batch *DRW_cache_lightprobe_planar_get(void);
+
+/* Bones */
+struct Gwn_Batch *DRW_cache_bone_octahedral_get(void);
+struct Gwn_Batch *DRW_cache_bone_octahedral_wire_outline_get(void);
+struct Gwn_Batch *DRW_cache_bone_box_get(void);
+struct Gwn_Batch *DRW_cache_bone_box_wire_outline_get(void);
+struct Gwn_Batch *DRW_cache_bone_wire_wire_outline_get(void);
+struct Gwn_Batch *DRW_cache_bone_envelope_solid_get(void);
+struct Gwn_Batch *DRW_cache_bone_envelope_distance_outline_get(void);
+struct Gwn_Batch *DRW_cache_bone_envelope_wire_outline_get(void);
+struct Gwn_Batch *DRW_cache_bone_envelope_head_wire_outline_get(void);
+struct Gwn_Batch *DRW_cache_bone_point_get(void);
+struct Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void);
+struct Gwn_Batch *DRW_cache_bone_arrows_get(void);
+
+/* Meshes */
+struct Gwn_Batch *DRW_cache_mesh_surface_overlay_get(struct Object *ob);
+void DRW_cache_mesh_wire_overlay_get(
+ struct Object *ob,
+ struct Gwn_Batch **r_tris, struct Gwn_Batch **r_ledges, struct Gwn_Batch **r_lverts);
+void DRW_cache_mesh_normals_overlay_get(
+ struct Object *ob,
+ struct Gwn_Batch **r_tris, struct Gwn_Batch **r_ledges, struct Gwn_Batch **r_lverts);
+struct Gwn_Batch *DRW_cache_face_centers_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_mesh_wire_outline_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_mesh_surface_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_mesh_surface_weights_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_mesh_surface_vert_colors_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_mesh_surface_verts_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_mesh_edges_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_mesh_verts_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_mesh_edges_paint_overlay_get(struct Object *ob, bool use_wire, bool use_sel);
+struct Gwn_Batch *DRW_cache_mesh_faces_weight_overlay_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_mesh_verts_weight_overlay_get(struct Object *ob);
+struct Gwn_Batch **DRW_cache_mesh_surface_shaded_get(
+ struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
+struct Gwn_Batch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob);
+
+void DRW_cache_mesh_sculpt_coords_ensure(struct Object *ob);
+
+/* Curve */
+struct Gwn_Batch *DRW_cache_curve_surface_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_curve_surface_verts_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_curve_edge_wire_get(struct Object *ob);
+/* edit-mode */
+struct Gwn_Batch *DRW_cache_curve_edge_normal_get(struct Object *ob, float normal_size);
+struct Gwn_Batch *DRW_cache_curve_edge_overlay_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_curve_vert_overlay_get(struct Object *ob);
+
+/* Font */
+struct Gwn_Batch *DRW_cache_text_edge_wire_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_text_surface_get(struct Object *ob);
+/* edit-mode */
+struct Gwn_Batch *DRW_cache_text_cursor_overlay_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_text_select_overlay_get(struct Object *ob);
+
+/* Surface */
+struct Gwn_Batch *DRW_cache_surf_surface_get(struct Object *ob);
+
+/* Lattice */
+struct Gwn_Batch *DRW_cache_lattice_verts_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_lattice_wire_get(struct Object *ob, bool use_weight);
+struct Gwn_Batch *DRW_cache_lattice_vert_overlay_get(struct Object *ob);
+
+/* Particles */
+struct Gwn_Batch *DRW_cache_particles_get_hair(struct ParticleSystem *psys, struct ModifierData *md);
+struct Gwn_Batch *DRW_cache_particles_get_dots(struct ParticleSystem *psys);
+struct Gwn_Batch *DRW_cache_particles_get_prim(int type);
+
+/* Metaball */
+struct Gwn_Batch *DRW_cache_mball_surface_get(struct Object *ob);
+
+#endif /* __DRAW_CACHE_H__ */
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
new file mode 100644
index 00000000000..c998282ae1f
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -0,0 +1,117 @@
+/*
+ * 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_impl.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_CACHE_IMPL_H__
+#define __DRAW_CACHE_IMPL_H__
+
+struct CurveCache;
+struct GPUMaterial;
+struct Gwn_Batch;
+struct ListBase;
+struct MetaBall;
+struct ModifierData;
+struct ParticleSystem;
+
+struct Curve;
+struct Lattice;
+struct Mesh;
+
+/* Expose via BKE callbacks */
+void DRW_mball_batch_cache_dirty(struct MetaBall *mb, int mode);
+void DRW_mball_batch_cache_free(struct MetaBall *mb);
+
+void DRW_curve_batch_cache_dirty(struct Curve *cu, int mode);
+void DRW_curve_batch_cache_free(struct Curve *cu);
+
+void DRW_mesh_batch_cache_dirty(struct Mesh *me, int mode);
+void DRW_mesh_batch_cache_free(struct Mesh *me);
+
+void DRW_lattice_batch_cache_dirty(struct Lattice *lt, int mode);
+void DRW_lattice_batch_cache_free(struct Lattice *lt);
+
+void DRW_particle_batch_cache_dirty(struct ParticleSystem *psys, int mode);
+void DRW_particle_batch_cache_free(struct ParticleSystem *psys);
+
+/* Curve */
+struct Gwn_Batch *DRW_curve_batch_cache_get_wire_edge(struct Curve *cu, struct CurveCache *ob_curve_cache);
+struct Gwn_Batch *DRW_curve_batch_cache_get_normal_edge(
+ struct Curve *cu, struct CurveCache *ob_curve_cache, float normal_size);
+struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(struct Curve *cu);
+struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(struct Curve *cu);
+
+struct Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(struct Curve *cu, struct CurveCache *ob_curve_cache);
+
+/* Metaball */
+struct Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob);
+
+/* Curve (Font) */
+struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu);
+struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_select(struct Curve *cu);
+
+/* DispList */
+struct Gwn_Batch *BLI_displist_batch_calc_surface(struct ListBase *lb);
+
+/* Lattice */
+struct Gwn_Batch *DRW_lattice_batch_cache_get_all_edges(struct Lattice *lt, bool use_weight, const int actdef);
+struct Gwn_Batch *DRW_lattice_batch_cache_get_all_verts(struct Lattice *lt);
+struct Gwn_Batch *DRW_lattice_batch_cache_get_overlay_verts(struct Lattice *lt);
+
+/* Mesh */
+
+struct Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(
+ struct Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
+struct Gwn_Batch **DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_edges(struct Mesh *me, bool use_wire, bool use_sel);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_faces(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_verts(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_all_edges(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_all_triangles(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(struct Mesh *me, int defgroup);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me, bool use_hide, uint select_id_offset);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me);
+/* edit-mesh selection (use generic function for faces) */
+struct Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(struct Mesh *me, uint select_id_offset);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me, uint select_id_offset);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me, uint select_id_offset);
+
+void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me);
+
+/* Particles */
+struct Gwn_Batch *DRW_particles_batch_cache_get_hair(struct ParticleSystem *psys, struct ModifierData *md);
+struct Gwn_Batch *DRW_particles_batch_cache_get_dots(struct ParticleSystem *psys);
+
+#endif /* __DRAW_CACHE_IMPL_H__ */
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c
new file mode 100644
index 00000000000..e6e52fe4579
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_impl_curve.c
@@ -0,0 +1,1036 @@
+/*
+ * ***** 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) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file draw_cache_impl_curve.c
+ * \ingroup draw
+ *
+ * \brief Curve API for render engines
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+
+#include "DNA_curve_types.h"
+
+#include "BKE_curve.h"
+
+#include "BKE_font.h"
+
+#include "GPU_batch.h"
+
+#include "draw_cache_impl.h" /* own include */
+
+#define SELECT 1
+
+/**
+ * TODO
+ * - Ensure `CurveCache`, `SEQUENCER_DAG_WORKAROUND`.
+ * - Check number of verts/edges to see if cache is valid.
+ * - Check if 'overlay.edges' can use single attribyte per edge, not 2 (for selection drawing).
+ */
+
+static void curve_batch_cache_clear(Curve *cu);
+
+/* ---------------------------------------------------------------------- */
+/* Curve Interface, direct access to basic data. */
+
+static void curve_render_overlay_verts_edges_len_get(
+ ListBase *lb, bool hide_handles,
+ int *r_vert_len, int *r_edge_len)
+{
+ BLI_assert(r_vert_len || r_edge_len);
+ int vert_len = 0;
+ int edge_len = 0;
+ for (Nurb *nu = lb->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ vert_len += hide_handles ? nu->pntsu : (nu->pntsu * 3);
+ /* 2x handles per point*/
+ edge_len += 2 * nu->pntsu;
+ }
+ else if (nu->bp) {
+ vert_len += nu->pntsu;
+ /* segments between points */
+ edge_len += nu->pntsu - 1;
+ }
+ }
+ if (r_vert_len) {
+ *r_vert_len = vert_len;
+ }
+ if (r_edge_len) {
+ *r_edge_len = edge_len;
+ }
+}
+
+static void curve_render_wire_verts_edges_len_get(
+ const CurveCache *ob_curve_cache,
+ int *r_vert_len, int *r_edge_len)
+{
+ BLI_assert(r_vert_len || r_edge_len);
+ int vert_len = 0;
+ int edge_len = 0;
+ for (const BevList *bl = ob_curve_cache->bev.first; bl; bl = bl->next) {
+ if (bl->nr > 0) {
+ const bool is_cyclic = bl->poly != -1;
+
+ /* verts */
+ vert_len += bl->nr;
+
+ /* edges */
+ edge_len += bl->nr;
+ if (!is_cyclic) {
+ edge_len -= 1;
+ }
+ }
+ }
+ if (r_vert_len) {
+ *r_vert_len = vert_len;
+ }
+ if (r_edge_len) {
+ *r_edge_len = edge_len;
+ }
+}
+
+static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache)
+{
+ int normal_len = 0;
+ const BevList *bl;
+ const Nurb *nu;
+ for (bl = ob_curve_cache->bev.first, nu = lb->first; nu && bl; bl = bl->next, nu = nu->next) {
+ int nr = bl->nr;
+ int skip = nu->resolu / 16;
+#if 0
+ while (nr-- > 0) { /* accounts for empty bevel lists */
+ normal_len += 1;
+ nr -= skip;
+ }
+#else
+ normal_len += max_ii((nr + max_ii(skip - 1, 0)) / (skip + 1), 0);
+#endif
+ }
+ return normal_len;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Curve Interface, indirect, partially cached access to complex data. */
+
+typedef struct CurveRenderData {
+ int types;
+
+ struct {
+ int vert_len;
+ int edge_len;
+ } overlay;
+
+ struct {
+ int vert_len;
+ int edge_len;
+ } wire;
+
+ /* edit mode normal's */
+ struct {
+ /* 'edge_len == len * 2'
+ * 'vert_len == len * 3' */
+ int len;
+ } normal;
+
+ struct {
+ EditFont *edit_font;
+ } text;
+
+ bool hide_handles;
+ bool hide_normals;
+
+ /* borrow from 'Object' */
+ CurveCache *ob_curve_cache;
+
+ /* borrow from 'Curve' */
+ ListBase *nurbs;
+
+ /* edit, index in nurb list */
+ int actnu;
+ /* edit, index in active nurb (BPoint or BezTriple) */
+ int actvert;
+} CurveRenderData;
+
+enum {
+ /* Wire center-line */
+ CU_DATATYPE_WIRE = 1 << 0,
+ /* Edit-mode verts and optionally handles */
+ CU_DATATYPE_OVERLAY = 1 << 1,
+ /* Edit-mode normals */
+ CU_DATATYPE_NORMAL = 1 << 2,
+ /* Geometry */
+ CU_DATATYPE_SURFACE = 1 << 3,
+ /* Text */
+ CU_DATATYPE_TEXT_SELECT = 1 << 4,
+};
+
+/*
+ * ob_curve_cache can be NULL, only needed for CU_DATATYPE_WIRE
+ */
+static CurveRenderData *curve_render_data_create(Curve *cu, CurveCache *ob_curve_cache, const int types)
+{
+ CurveRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__);
+ rdata->types = types;
+ ListBase *nurbs;
+
+ rdata->hide_handles = (cu->drawflag & CU_HIDE_HANDLES) != 0;
+ rdata->hide_normals = (cu->drawflag & CU_HIDE_NORMALS) != 0;
+
+ rdata->actnu = cu->actnu;
+ rdata->actvert = cu->actvert;
+
+ rdata->ob_curve_cache = ob_curve_cache;
+
+ if (types & CU_DATATYPE_WIRE) {
+ curve_render_wire_verts_edges_len_get(
+ rdata->ob_curve_cache,
+ &rdata->wire.vert_len, &rdata->wire.edge_len);
+ }
+
+ if (cu->editnurb) {
+ EditNurb *editnurb = cu->editnurb;
+ nurbs = &editnurb->nurbs;
+
+ if (types & CU_DATATYPE_OVERLAY) {
+ curve_render_overlay_verts_edges_len_get(
+ nurbs, rdata->hide_handles,
+ &rdata->overlay.vert_len,
+ rdata->hide_handles ? NULL : &rdata->overlay.edge_len);
+
+ rdata->actnu = cu->actnu;
+ rdata->actvert = cu->actvert;
+ }
+ if (types & CU_DATATYPE_NORMAL) {
+ rdata->normal.len = curve_render_normal_len_get(nurbs, rdata->ob_curve_cache);
+ }
+ }
+ else {
+ nurbs = &cu->nurb;
+ }
+
+ rdata->nurbs = nurbs;
+
+ rdata->text.edit_font = cu->editfont;
+
+ return rdata;
+}
+
+static void curve_render_data_free(CurveRenderData *rdata)
+{
+#if 0
+ if (rdata->loose_verts) {
+ MEM_freeN(rdata->loose_verts);
+ }
+#endif
+ MEM_freeN(rdata);
+}
+
+static int curve_render_data_overlay_verts_len_get(const CurveRenderData *rdata)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_OVERLAY);
+ return rdata->overlay.vert_len;
+}
+
+static int curve_render_data_overlay_edges_len_get(const CurveRenderData *rdata)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_OVERLAY);
+ return rdata->overlay.edge_len;
+}
+
+static int curve_render_data_wire_verts_len_get(const CurveRenderData *rdata)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_WIRE);
+ return rdata->wire.vert_len;
+}
+
+static int curve_render_data_wire_edges_len_get(const CurveRenderData *rdata)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_WIRE);
+ return rdata->wire.edge_len;
+}
+
+static int curve_render_data_normal_len_get(const CurveRenderData *rdata)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_NORMAL);
+ return rdata->normal.len;
+}
+
+enum {
+ VFLAG_VERTEX_SELECTED = 1 << 0,
+ VFLAG_VERTEX_ACTIVE = 1 << 1,
+};
+
+/* ---------------------------------------------------------------------- */
+/* Curve Gwn_Batch Cache */
+
+typedef struct CurveBatchCache {
+ /* center-line */
+ struct {
+ Gwn_VertBuf *verts;
+ Gwn_VertBuf *edges;
+ Gwn_Batch *batch;
+ Gwn_IndexBuf *elem;
+ } wire;
+
+ /* normals */
+ struct {
+ Gwn_VertBuf *verts;
+ Gwn_VertBuf *edges;
+ Gwn_Batch *batch;
+ Gwn_IndexBuf *elem;
+ } normal;
+
+ /* control handles and vertices */
+ struct {
+ Gwn_Batch *edges;
+ Gwn_Batch *verts;
+ } overlay;
+
+ struct {
+ Gwn_Batch *batch;
+ } surface;
+
+ /* 3d text */
+ struct {
+ Gwn_Batch *select;
+ Gwn_Batch *cursor;
+ } text;
+
+ /* settings to determine if cache is invalid */
+ bool is_dirty;
+
+ bool hide_handles;
+ bool hide_normals;
+
+ float normal_size;
+
+ bool is_editmode;
+} CurveBatchCache;
+
+/* Gwn_Batch cache management. */
+
+static bool curve_batch_cache_valid(Curve *cu)
+{
+ CurveBatchCache *cache = cu->batch_cache;
+
+ if (cache == NULL) {
+ return false;
+ }
+
+ if (cache->is_editmode != ((cu->editnurb != NULL) || (cu->editfont != NULL))) {
+ return false;
+ }
+
+ if (cache->is_editmode) {
+ if (cu->editnurb) {
+ if ((cache->hide_handles != ((cu->drawflag & CU_HIDE_HANDLES) != 0))) {
+ return false;
+ }
+ else if ((cache->hide_normals != ((cu->drawflag & CU_HIDE_NORMALS) != 0))) {
+ return false;
+ }
+ }
+ else if (cu->editfont) {
+ /* TODO */
+ }
+ }
+
+ if (cache->is_dirty == false) {
+ return true;
+ }
+ else {
+ /* TODO: check number of vertices/edges? */
+ if (cache->is_editmode) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void curve_batch_cache_init(Curve *cu)
+{
+ CurveBatchCache *cache = cu->batch_cache;
+
+ if (!cache) {
+ cache = cu->batch_cache = MEM_callocN(sizeof(*cache), __func__);
+ }
+ else {
+ memset(cache, 0, sizeof(*cache));
+ }
+
+ cache->hide_handles = (cu->drawflag & CU_HIDE_HANDLES) != 0;
+ cache->hide_normals = (cu->drawflag & CU_HIDE_NORMALS) != 0;
+
+#if 0
+ ListBase *nurbs;
+ if (cu->editnurb) {
+ EditNurb *editnurb = cu->editnurb;
+ nurbs = &editnurb->nurbs;
+ }
+ else {
+ nurbs = &cu->nurb;
+ }
+#endif
+
+ cache->is_editmode = (cu->editnurb != NULL) || (cu->editfont != NULL);
+
+ cache->is_dirty = false;
+}
+
+static CurveBatchCache *curve_batch_cache_get(Curve *cu)
+{
+ if (!curve_batch_cache_valid(cu)) {
+ curve_batch_cache_clear(cu);
+ curve_batch_cache_init(cu);
+ }
+ return cu->batch_cache;
+}
+
+void DRW_curve_batch_cache_dirty(Curve *cu, int mode)
+{
+ CurveBatchCache *cache = cu->batch_cache;
+ if (cache == NULL) {
+ return;
+ }
+ switch (mode) {
+ case BKE_CURVE_BATCH_DIRTY_ALL:
+ cache->is_dirty = true;
+ break;
+ case BKE_CURVE_BATCH_DIRTY_SELECT:
+ /* editnurb */
+ GWN_BATCH_DISCARD_SAFE(cache->overlay.verts);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay.edges);
+
+ /* editfont */
+ GWN_BATCH_DISCARD_SAFE(cache->text.select);
+ GWN_BATCH_DISCARD_SAFE(cache->text.cursor);
+ break;
+ default:
+ BLI_assert(0);
+ }
+}
+
+static void curve_batch_cache_clear(Curve *cu)
+{
+ CurveBatchCache *cache = cu->batch_cache;
+ if (!cache) {
+ return;
+ }
+
+ GWN_BATCH_DISCARD_SAFE(cache->overlay.verts);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay.edges);
+
+ GWN_BATCH_DISCARD_SAFE(cache->surface.batch);
+
+ /* don't own vbo & elems */
+ GWN_BATCH_DISCARD_SAFE(cache->wire.batch);
+ GWN_VERTBUF_DISCARD_SAFE(cache->wire.verts);
+ GWN_VERTBUF_DISCARD_SAFE(cache->wire.edges);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->wire.elem);
+
+ /* don't own vbo & elems */
+ GWN_BATCH_DISCARD_SAFE(cache->normal.batch);
+ GWN_VERTBUF_DISCARD_SAFE(cache->normal.verts);
+ GWN_VERTBUF_DISCARD_SAFE(cache->normal.edges);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->normal.elem);
+
+ /* 3d text */
+ GWN_BATCH_DISCARD_SAFE(cache->text.cursor);
+ GWN_BATCH_DISCARD_SAFE(cache->text.select);
+}
+
+void DRW_curve_batch_cache_free(Curve *cu)
+{
+ curve_batch_cache_clear(cu);
+ MEM_SAFE_FREE(cu->batch_cache);
+}
+
+/* -------------------------------------------------------------------- */
+
+/** \name Private Curve Cache API
+ * \{ */
+
+/* Gwn_Batch cache usage. */
+static Gwn_VertBuf *curve_batch_cache_get_wire_verts(CurveRenderData *rdata, CurveBatchCache *cache)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_WIRE);
+ BLI_assert(rdata->ob_curve_cache != NULL);
+
+ if (cache->wire.verts == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ const int vert_len = curve_render_data_wire_verts_len_get(rdata);
+
+ Gwn_VertBuf *vbo = cache->wire.verts = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vert_len);
+ int vbo_len_used = 0;
+ for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
+ if (bl->nr > 0) {
+ const int i_end = vbo_len_used + bl->nr;
+ for (const BevPoint *bevp = bl->bevpoints; vbo_len_used < i_end; vbo_len_used++, bevp++) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bevp->vec);
+ }
+ }
+ }
+ BLI_assert(vbo_len_used == vert_len);
+ }
+
+ return cache->wire.verts;
+}
+
+static Gwn_IndexBuf *curve_batch_cache_get_wire_edges(CurveRenderData *rdata, CurveBatchCache *cache)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_WIRE);
+ BLI_assert(rdata->ob_curve_cache != NULL);
+
+ if (cache->wire.edges == NULL) {
+ const int vert_len = curve_render_data_wire_verts_len_get(rdata);
+ const int edge_len = curve_render_data_wire_edges_len_get(rdata);
+ int edge_len_used = 0;
+
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
+
+ int i = 0;
+ for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) {
+ if (bl->nr > 0) {
+ const bool is_cyclic = bl->poly != -1;
+ const int i_end = i + (bl->nr);
+ int i_prev;
+ if (is_cyclic) {
+ i_prev = i + (bl->nr - 1);
+ }
+ else {
+ i_prev = i;
+ i += 1;
+ }
+ for (; i < i_end; i_prev = i++) {
+ GWN_indexbuf_add_line_verts(&elb, i_prev, i);
+ edge_len_used += 1;
+ }
+ }
+ }
+
+ if (rdata->hide_handles) {
+ BLI_assert(edge_len_used <= edge_len);
+ }
+ else {
+ BLI_assert(edge_len_used == edge_len);
+ }
+
+ cache->wire.elem = GWN_indexbuf_build(&elb);
+ }
+
+ return cache->wire.elem;
+}
+
+static Gwn_VertBuf *curve_batch_cache_get_normal_verts(CurveRenderData *rdata, CurveBatchCache *cache)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_NORMAL);
+ BLI_assert(rdata->ob_curve_cache != NULL);
+
+ if (cache->normal.verts == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ const int normal_len = curve_render_data_normal_len_get(rdata);
+ const int vert_len = normal_len * 3;
+
+ Gwn_VertBuf *vbo = cache->normal.verts = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vert_len);
+ int vbo_len_used = 0;
+
+ const BevList *bl;
+ const Nurb *nu;
+
+ for (bl = rdata->ob_curve_cache->bev.first, nu = rdata->nurbs->first;
+ nu && bl;
+ bl = bl->next, nu = nu->next)
+ {
+ const BevPoint *bevp = bl->bevpoints;
+ int nr = bl->nr;
+ int skip = nu->resolu / 16;
+
+ while (nr-- > 0) { /* accounts for empty bevel lists */
+ const float fac = bevp->radius * cache->normal_size;
+ float vec_a[3]; /* Offset perpendicular to the curve */
+ float vec_b[3]; /* Delta along the curve */
+
+ vec_a[0] = fac;
+ vec_a[1] = 0.0f;
+ vec_a[2] = 0.0f;
+
+ mul_qt_v3(bevp->quat, vec_a);
+ madd_v3_v3fl(vec_a, bevp->dir, -fac);
+
+ reflect_v3_v3v3(vec_b, vec_a, bevp->dir);
+ negate_v3(vec_b);
+
+ add_v3_v3(vec_a, bevp->vec);
+ add_v3_v3(vec_b, bevp->vec);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_a);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, bevp->vec);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_b);
+
+ bevp += skip + 1;
+ nr -= skip;
+ }
+ }
+ BLI_assert(vbo_len_used == vert_len);
+ }
+
+ return cache->normal.verts;
+}
+
+static Gwn_IndexBuf *curve_batch_cache_get_normal_edges(CurveRenderData *rdata, CurveBatchCache *cache)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_NORMAL);
+ BLI_assert(rdata->ob_curve_cache != NULL);
+
+ if (cache->normal.edges == NULL) {
+ const int normal_len = curve_render_data_normal_len_get(rdata);
+ const int vert_len = normal_len * 3;
+ const int edge_len = normal_len * 2;
+
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
+
+ int vbo_len_used = 0;
+ for (int i = 0; i < normal_len; i++) {
+ GWN_indexbuf_add_line_verts(&elb, vbo_len_used + 0, vbo_len_used + 1);
+ GWN_indexbuf_add_line_verts(&elb, vbo_len_used + 1, vbo_len_used + 2);
+ vbo_len_used += 3;
+ }
+
+ BLI_assert(vbo_len_used == vert_len);
+
+ cache->normal.elem = GWN_indexbuf_build(&elb);
+ }
+
+ return cache->normal.elem;
+}
+
+static void curve_batch_cache_create_overlay_batches(Curve *cu)
+{
+ /* Since CU_DATATYPE_OVERLAY is slow to generate, generate them all at once */
+ int options = CU_DATATYPE_OVERLAY;
+
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+ CurveRenderData *rdata = curve_render_data_create(cu, NULL, options);
+
+ if (cache->overlay.verts == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, data; } attr_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_U8, 1, GWN_FETCH_INT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ const int vbo_len_capacity = curve_render_data_overlay_verts_len_get(rdata);
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ int i = 0;
+ for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ int a = 0;
+ for (const BezTriple *bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (bezt->hide == false) {
+ const bool is_active = (i == rdata->actvert);
+ char vflag;
+
+ if (rdata->hide_handles) {
+ vflag = (bezt->f2 & SELECT) ?
+ (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[1]);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ }
+ else {
+ for (int j = 0; j < 3; j++) {
+ vflag = ((&bezt->f1)[j] & SELECT) ?
+ (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[j]);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ }
+ }
+ }
+ i += 1;
+ }
+ }
+ else if (nu->bp) {
+ int a = 0;
+ for (const BPoint *bp = nu->bp; a < nu->pntsu; a++, bp++) {
+ if (bp->hide == false) {
+ const bool is_active = (i == rdata->actvert);
+ char vflag;
+ vflag = (bp->f1 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp->vec);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ }
+ i += 1;
+ }
+ }
+ i += nu->pntsu;
+ }
+ if (vbo_len_capacity != vbo_len_used) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+
+ cache->overlay.verts = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+
+
+ if ((cache->overlay.edges == NULL) && (rdata->hide_handles == false)) {
+ /* Note: we could reference indices to vertices (above) */
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, data; } attr_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_U8, 1, GWN_FETCH_INT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ const int edge_len = curve_render_data_overlay_edges_len_get(rdata);
+ const int vbo_len_capacity = edge_len * 2;
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ int i = 0;
+ for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ int a = 0;
+ for (const BezTriple *bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (bezt->hide == false) {
+ const bool is_active = (i == rdata->actvert);
+ char vflag;
+
+ vflag = (bezt->f1 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[0]);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+
+ /* same vertex twice, only check different selection */
+ for (int j = 0; j < 2; j++) {
+ vflag = ((j ? bezt->f3 : bezt->f1) & SELECT) ?
+ (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[1]);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ }
+
+ vflag = (bezt->f3 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[2]);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ }
+ i += 1;
+ }
+ }
+ else if (nu->bp) {
+ int a = 1;
+ for (const BPoint *bp_prev = nu->bp, *bp_curr = &nu->bp[1]; a < nu->pntsu; a++, bp_prev = bp_curr++) {
+ if ((bp_prev->hide == false) && (bp_curr->hide == false)) {
+ char vflag;
+ vflag = ((bp_prev->f1 & SELECT) && (bp_curr->f1 & SELECT)) ? VFLAG_VERTEX_SELECTED : 0;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_prev->vec);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_curr->vec);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ vbo_len_used += 1;
+
+ }
+ }
+ }
+ }
+ if (vbo_len_capacity != vbo_len_used) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+
+ cache->overlay.edges = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+
+ curve_render_data_free(rdata);
+}
+
+static Gwn_Batch *curve_batch_cache_get_pos_and_normals(CurveRenderData *rdata, CurveBatchCache *cache)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_SURFACE);
+ if (cache->surface.batch == NULL) {
+ cache->surface.batch = BLI_displist_batch_calc_surface(&rdata->ob_curve_cache->disp);
+ }
+ return cache->surface.batch;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Private Object/Font Cache API
+ * \{ */
+
+
+static Gwn_Batch *curve_batch_cache_get_overlay_select(CurveRenderData *rdata, CurveBatchCache *cache)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_TEXT_SELECT);
+ if (cache->text.select == NULL) {
+ EditFont *ef = rdata->text.edit_font;
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ const int vbo_len_capacity = ef->selboxes_len * 6;
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ float box[4][3];
+
+ /* fill in xy below */
+ box[0][2] = box[1][2] = box[2][2] = box[3][2] = 0.001;
+
+ for (int i = 0; i < ef->selboxes_len; i++) {
+ EditFontSelBox *sb = &ef->selboxes[i];
+
+ float selboxw;
+ if (i + 1 != ef->selboxes_len) {
+ if (ef->selboxes[i + 1].y == sb->y)
+ selboxw = ef->selboxes[i + 1].x - sb->x;
+ else
+ selboxw = sb->w;
+ }
+ else {
+ selboxw = sb->w;
+ }
+
+ if (sb->rot == 0.0f) {
+ copy_v2_fl2(box[0], sb->x, sb->y);
+ copy_v2_fl2(box[1], sb->x + selboxw, sb->y);
+ copy_v2_fl2(box[2], sb->x + selboxw, sb->y + sb->h);
+ copy_v2_fl2(box[3], sb->x, sb->y + sb->h);
+ }
+ else {
+ float mat[2][2];
+
+ angle_to_mat2(mat, sb->rot);
+
+ copy_v2_fl2(box[0], sb->x, sb->y);
+
+ copy_v2_fl2(box[1], selboxw, 0.0f);
+ mul_m2v2(mat, box[1]);
+ add_v2_v2(box[1], &sb->x);
+
+ copy_v2_fl2(box[2], selboxw, sb->h);
+ mul_m2v2(mat, box[2]);
+ add_v2_v2(box[2], &sb->x);
+
+ copy_v2_fl2(box[3], 0.0f, sb->h);
+ mul_m2v2(mat, box[3]);
+ add_v2_v2(box[3], &sb->x);
+ }
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[1]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[3]);
+ }
+ BLI_assert(vbo_len_used == vbo_len_capacity);
+ cache->text.select = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return cache->text.select;
+}
+
+static Gwn_Batch *curve_batch_cache_get_overlay_cursor(CurveRenderData *rdata, CurveBatchCache *cache)
+{
+ BLI_assert(rdata->types & CU_DATATYPE_TEXT_SELECT);
+ if (cache->text.cursor == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ const int vbo_len_capacity = 4;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ for (int i = 0; i < 4; i++) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->text.edit_font->textcurs[i]);
+ }
+ cache->text.cursor = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return cache->text.cursor;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Public Object/Curve API
+ * \{ */
+
+Gwn_Batch *DRW_curve_batch_cache_get_wire_edge(Curve *cu, CurveCache *ob_curve_cache)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+ if (cache->wire.batch == NULL) {
+ /* create batch from Curve */
+ CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_WIRE);
+
+ cache->wire.batch = GWN_batch_create(
+ GWN_PRIM_LINES,
+ curve_batch_cache_get_wire_verts(rdata, cache),
+ curve_batch_cache_get_wire_edges(rdata, cache));
+
+ curve_render_data_free(rdata);
+ }
+ return cache->wire.batch;
+}
+
+Gwn_Batch *DRW_curve_batch_cache_get_normal_edge(Curve *cu, CurveCache *ob_curve_cache, float normal_size)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+ if (cache->normal.batch != NULL) {
+ cache->normal_size = normal_size;
+ if (cache->normal_size != normal_size) {
+ GWN_BATCH_DISCARD_SAFE(cache->normal.batch);
+ GWN_VERTBUF_DISCARD_SAFE(cache->normal.edges);
+ }
+ }
+ cache->normal_size = normal_size;
+
+ if (cache->normal.batch == NULL) {
+ /* create batch from Curve */
+ CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_NORMAL);
+
+ cache->normal.batch = GWN_batch_create(
+ GWN_PRIM_LINES,
+ curve_batch_cache_get_normal_verts(rdata, cache),
+ curve_batch_cache_get_normal_edges(rdata, cache));
+
+ curve_render_data_free(rdata);
+ cache->normal_size = normal_size;
+ }
+ return cache->normal.batch;
+}
+
+Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(Curve *cu)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+ if (cache->overlay.edges == NULL) {
+ curve_batch_cache_create_overlay_batches(cu);
+ }
+
+ return cache->overlay.edges;
+}
+
+Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(Curve *cu)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+ if (cache->overlay.verts == NULL) {
+ curve_batch_cache_create_overlay_batches(cu);
+ }
+
+ return cache->overlay.verts;
+}
+
+Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(
+ struct Curve *cu, struct CurveCache *ob_curve_cache)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+ if (cache->surface.batch == NULL) {
+ CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_SURFACE);
+
+ curve_batch_cache_get_pos_and_normals(rdata, cache);
+
+ curve_render_data_free(rdata);
+ }
+
+ return cache->surface.batch;
+}
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Public Object/Font API
+ * \{ */
+
+Gwn_Batch *DRW_curve_batch_cache_get_overlay_select(Curve *cu)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+ if (cache->text.select == NULL) {
+ CurveRenderData *rdata = curve_render_data_create(cu, NULL, CU_DATATYPE_TEXT_SELECT);
+
+ curve_batch_cache_get_overlay_select(rdata, cache);
+
+ curve_render_data_free(rdata);
+ }
+
+ return cache->text.select;
+}
+
+Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(Curve *cu)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+ if (cache->text.cursor == NULL) {
+ CurveRenderData *rdata = curve_render_data_create(cu, NULL, CU_DATATYPE_TEXT_SELECT);
+
+ curve_batch_cache_get_overlay_cursor(rdata, cache);
+
+ curve_render_data_free(rdata);
+ }
+
+ return cache->text.cursor;
+}
+
+/** \} */ \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
new file mode 100644
index 00000000000..96386f82faf
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -0,0 +1,174 @@
+/*
+ * ***** 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) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file draw_cache_impl_displist.c
+ * \ingroup draw
+ *
+ * \brief DispList API for render engines
+ *
+ * \note DispList may be removed soon! This is a utility for object types that use render.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+
+#include "DNA_curve_types.h"
+
+#include "BKE_displist.h"
+
+#include "GPU_batch.h"
+
+#include "draw_cache_impl.h" /* own include */
+
+static int dl_vert_len(const DispList *dl)
+{
+ switch (dl->type) {
+ case DL_INDEX3:
+ case DL_INDEX4:
+ return dl->nr;
+ case DL_SURF:
+ return dl->parts * dl->nr;
+ }
+ return 0;
+}
+
+static int dl_tri_len(const DispList *dl)
+{
+ switch (dl->type) {
+ case DL_INDEX3:
+ return dl->parts;
+ case DL_INDEX4:
+ return dl->parts * 2;
+ case DL_SURF:
+ return dl->totindex * 2;
+ }
+ return 0;
+}
+
+/* see: displist_get_allverts */
+static int curve_render_surface_vert_len_get(const ListBase *lb)
+{
+ int vert_len = 0;
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ vert_len += dl_vert_len(dl);
+ }
+ return vert_len;
+}
+
+static int curve_render_surface_tri_len_get(const ListBase *lb)
+{
+ int tri_len = 0;
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ tri_len += dl_tri_len(dl);
+ }
+ return tri_len;
+}
+
+Gwn_Batch *BLI_displist_batch_calc_surface(ListBase *lb)
+{
+ const int tri_len = curve_render_surface_tri_len_get(lb);
+ if (tri_len == 0) {
+ return NULL;
+ }
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, nor; } attr_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ const int vert_len = curve_render_surface_vert_len_get(lb);
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ {
+ const int vbo_len_capacity = vert_len;
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ BKE_displist_normals_add(lb);
+
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ const bool ndata_is_single = dl->type == DL_INDEX3;
+ if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
+ const float *fp_co = dl->verts;
+ const float *fp_no = dl->nors;
+ const int vbo_end = vbo_len_used + dl_vert_len(dl);
+ while (vbo_len_used < vbo_end) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, fp_co);
+ if (fp_no) {
+ GWN_vertbuf_attr_set(vbo, attr_id.nor, vbo_len_used, fp_no);
+ if (ndata_is_single == false) {
+ fp_no += 3;
+ }
+ }
+ fp_co += 3;
+ vbo_len_used += 1;
+ }
+ }
+ }
+ }
+
+ {
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
+
+ int ofs = 0;
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
+ const int *idx = dl->index;
+ if (dl->type == DL_INDEX3) {
+ const int i_end = dl->parts;
+ for (int i = 0; i < i_end; i++, idx += 3) {
+ GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
+ }
+ }
+ else if (dl->type == DL_SURF) {
+ const int i_end = dl->totindex;
+ for (int i = 0; i < i_end; i++, idx += 4) {
+ GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
+ GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
+ }
+ }
+ else {
+ BLI_assert(dl->type == DL_INDEX4);
+ const int i_end = dl->parts;
+ for (int i = 0; i < i_end; i++, idx += 4) {
+ GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
+
+ if (idx[2] != idx[3]) {
+ GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
+ }
+ }
+ }
+ ofs += dl_vert_len(dl);
+ }
+ }
+
+ return GWN_batch_create_ex(
+ GWN_PRIM_TRIS, vbo, GWN_indexbuf_build(&elb),
+ GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+ }
+}
diff --git a/source/blender/draw/intern/draw_cache_impl_lattice.c b/source/blender/draw/intern/draw_cache_impl_lattice.c
new file mode 100644
index 00000000000..eed408de3cd
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_impl_lattice.c
@@ -0,0 +1,587 @@
+/*
+ * ***** 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) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file draw_cache_impl_lattice.c
+ * \ingroup draw
+ *
+ * \brief Lattice API for render engines
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_lattice.h"
+#include "BKE_deform.h"
+#include "BKE_colorband.h"
+
+#include "GPU_batch.h"
+
+#include "draw_cache_impl.h" /* own include */
+
+#define SELECT 1
+
+/**
+ * TODO
+ * - 'DispList' is currently not used
+ * (we could avoid using since it will be removed)
+ */
+
+static void lattice_batch_cache_clear(Lattice *lt);
+
+/* ---------------------------------------------------------------------- */
+/* Lattice Interface, direct access to basic data. */
+
+static int vert_len_calc(int u, int v, int w)
+{
+ if (u <= 0 || v <= 0 || w <= 0) {
+ return 0;
+ }
+ return u * v * w;
+}
+
+static int edge_len_calc(int u, int v, int w)
+{
+ if (u <= 0 || v <= 0 || w <= 0) {
+ return 0;
+ }
+ return (((((u - 1) * v) +
+ ((v - 1) * u)) * w) +
+ ((w - 1) * (u * v)));
+}
+
+static int lattice_render_verts_len_get(Lattice *lt)
+{
+ if (lt->editlatt) {
+ lt = lt->editlatt->latt;
+ }
+
+ const int u = lt->pntsu;
+ const int v = lt->pntsv;
+ const int w = lt->pntsw;
+
+ if ((lt->flag & LT_OUTSIDE) == 0) {
+ return vert_len_calc(u, v, w);
+ }
+ else {
+ /* TODO remove internal coords */
+ return vert_len_calc(u, v, w);
+ }
+}
+
+static int lattice_render_edges_len_get(Lattice *lt)
+{
+ if (lt->editlatt) {
+ lt = lt->editlatt->latt;
+ }
+
+ const int u = lt->pntsu;
+ const int v = lt->pntsv;
+ const int w = lt->pntsw;
+
+ if ((lt->flag & LT_OUTSIDE) == 0) {
+ return edge_len_calc(u, v, w);
+ }
+ else {
+ /* TODO remove internal coords */
+ return edge_len_calc(u, v, w);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Lattice Interface, indirect, partially cached access to complex data. */
+
+typedef struct LatticeRenderData {
+ int types;
+
+ int vert_len;
+ int edge_len;
+
+ struct {
+ int u_len, v_len, w_len;
+ } dims;
+ bool show_only_outside;
+
+ struct EditLatt *edit_latt;
+ BPoint *bp;
+
+ int actbp;
+
+ struct MDeformVert *dvert;
+} LatticeRenderData;
+
+enum {
+ LR_DATATYPE_VERT = 1 << 0,
+ LR_DATATYPE_EDGE = 1 << 1,
+ LR_DATATYPE_OVERLAY = 1 << 2,
+};
+
+static LatticeRenderData *lattice_render_data_create(Lattice *lt, const int types)
+{
+ LatticeRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__);
+ rdata->types = types;
+
+ if (lt->editlatt) {
+ EditLatt *editlatt = lt->editlatt;
+ lt = editlatt->latt;
+
+ rdata->edit_latt = editlatt;
+
+ rdata->dvert = lt->dvert;
+
+ if (types & (LR_DATATYPE_VERT)) {
+ rdata->vert_len = lattice_render_verts_len_get(lt);
+ }
+ if (types & (LR_DATATYPE_EDGE)) {
+ rdata->edge_len = lattice_render_edges_len_get(lt);
+ }
+ if (types & LR_DATATYPE_OVERLAY) {
+ rdata->actbp = lt->actbp;
+ }
+ }
+ else {
+ rdata->dvert = NULL;
+
+ if (types & (LR_DATATYPE_VERT)) {
+ rdata->vert_len = lattice_render_verts_len_get(lt);
+ }
+ if (types & (LR_DATATYPE_EDGE)) {
+ rdata->edge_len = lattice_render_edges_len_get(lt);
+ /*no edge data */
+ }
+ }
+
+ rdata->bp = lt->def;
+
+ rdata->dims.u_len = lt->pntsu;
+ rdata->dims.v_len = lt->pntsv;
+ rdata->dims.w_len = lt->pntsw;
+
+ rdata->show_only_outside = (lt->flag & LT_OUTSIDE) != 0;
+ rdata->actbp = lt->actbp;
+
+ return rdata;
+}
+
+static void lattice_render_data_free(LatticeRenderData *rdata)
+{
+#if 0
+ if (rdata->loose_verts) {
+ MEM_freeN(rdata->loose_verts);
+ }
+#endif
+ MEM_freeN(rdata);
+}
+
+static int lattice_render_data_verts_len_get(const LatticeRenderData *rdata)
+{
+ BLI_assert(rdata->types & LR_DATATYPE_VERT);
+ return rdata->vert_len;
+}
+
+static int lattice_render_data_edges_len_get(const LatticeRenderData *rdata)
+{
+ BLI_assert(rdata->types & LR_DATATYPE_EDGE);
+ return rdata->edge_len;
+}
+
+static const BPoint *lattice_render_data_vert_bpoint(const LatticeRenderData *rdata, const int vert_idx)
+{
+ BLI_assert(rdata->types & LR_DATATYPE_VERT);
+ return &rdata->bp[vert_idx];
+}
+
+/* TODO, move into shader? */
+static void rgb_from_weight(float r_rgb[3], const float weight)
+{
+ const float blend = ((weight / 2.0f) + 0.5f);
+
+ if (weight <= 0.25f) { /* blue->cyan */
+ r_rgb[0] = 0.0f;
+ r_rgb[1] = blend * weight * 4.0f;
+ r_rgb[2] = blend;
+ }
+ else if (weight <= 0.50f) { /* cyan->green */
+ r_rgb[0] = 0.0f;
+ r_rgb[1] = blend;
+ r_rgb[2] = blend * (1.0f - ((weight - 0.25f) * 4.0f));
+ }
+ else if (weight <= 0.75f) { /* green->yellow */
+ r_rgb[0] = blend * ((weight - 0.50f) * 4.0f);
+ r_rgb[1] = blend;
+ r_rgb[2] = 0.0f;
+ }
+ else if (weight <= 1.0f) { /* yellow->red */
+ r_rgb[0] = blend;
+ r_rgb[1] = blend * (1.0f - ((weight - 0.75f) * 4.0f));
+ r_rgb[2] = 0.0f;
+ }
+ else {
+ /* exceptional value, unclamped or nan,
+ * avoid uninitialized memory use */
+ r_rgb[0] = 1.0f;
+ r_rgb[1] = 0.0f;
+ r_rgb[2] = 1.0f;
+ }
+}
+
+static void lattice_render_data_weight_col_get(const LatticeRenderData *rdata, const int vert_idx,
+ const int actdef, float r_col[4])
+{
+ if (actdef > -1) {
+ float weight = defvert_find_weight(rdata->dvert + vert_idx, actdef);
+
+ if (U.flag & USER_CUSTOM_RANGE) {
+ BKE_colorband_evaluate(&U.coba_weight, weight, r_col);
+ }
+ else {
+ rgb_from_weight(r_col, weight);
+ }
+
+ r_col[3] = 1.0f;
+ }
+ else {
+ zero_v4(r_col);
+ }
+}
+
+enum {
+ VFLAG_VERTEX_SELECTED = 1 << 0,
+ VFLAG_VERTEX_ACTIVE = 1 << 1,
+};
+
+/* ---------------------------------------------------------------------- */
+/* Lattice Gwn_Batch Cache */
+
+typedef struct LatticeBatchCache {
+ Gwn_VertBuf *pos;
+ Gwn_IndexBuf *edges;
+
+ Gwn_Batch *all_verts;
+ Gwn_Batch *all_edges;
+
+ Gwn_Batch *overlay_verts;
+
+ /* settings to determine if cache is invalid */
+ bool is_dirty;
+
+ struct {
+ int u_len, v_len, w_len;
+ } dims;
+ bool show_only_outside;
+
+ bool is_editmode;
+} LatticeBatchCache;
+
+/* Gwn_Batch cache management. */
+
+static bool lattice_batch_cache_valid(Lattice *lt)
+{
+ LatticeBatchCache *cache = lt->batch_cache;
+
+ if (cache == NULL) {
+ return false;
+ }
+
+ if (cache->is_editmode != (lt->editlatt != NULL)) {
+ return false;
+ }
+
+ if (cache->is_dirty == false) {
+ return true;
+ }
+ else {
+ if (cache->is_editmode) {
+ return false;
+ }
+ else if ((cache->dims.u_len != lt->pntsu) ||
+ (cache->dims.v_len != lt->pntsv) ||
+ (cache->dims.w_len != lt->pntsw) ||
+ ((cache->show_only_outside != ((lt->flag & LT_OUTSIDE) != 0))))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void lattice_batch_cache_init(Lattice *lt)
+{
+ LatticeBatchCache *cache = lt->batch_cache;
+
+ if (!cache) {
+ cache = lt->batch_cache = MEM_callocN(sizeof(*cache), __func__);
+ }
+ else {
+ memset(cache, 0, sizeof(*cache));
+ }
+
+ cache->dims.u_len = lt->pntsu;
+ cache->dims.v_len = lt->pntsv;
+ cache->dims.w_len = lt->pntsw;
+ cache->show_only_outside = (lt->flag & LT_OUTSIDE) != 0;
+
+ cache->is_editmode = lt->editlatt != NULL;
+
+ cache->is_dirty = false;
+}
+
+static LatticeBatchCache *lattice_batch_cache_get(Lattice *lt)
+{
+ if (!lattice_batch_cache_valid(lt)) {
+ lattice_batch_cache_clear(lt);
+ lattice_batch_cache_init(lt);
+ }
+ return lt->batch_cache;
+}
+
+void DRW_lattice_batch_cache_dirty(Lattice *lt, int mode)
+{
+ LatticeBatchCache *cache = lt->batch_cache;
+ if (cache == NULL) {
+ return;
+ }
+ switch (mode) {
+ case BKE_LATTICE_BATCH_DIRTY_ALL:
+ cache->is_dirty = true;
+ break;
+ case BKE_LATTICE_BATCH_DIRTY_SELECT:
+ /* TODO Separate Flag vbo */
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_verts);
+ break;
+ default:
+ BLI_assert(0);
+ }
+}
+
+static void lattice_batch_cache_clear(Lattice *lt)
+{
+ LatticeBatchCache *cache = lt->batch_cache;
+ if (!cache) {
+ return;
+ }
+
+ GWN_BATCH_DISCARD_SAFE(cache->all_verts);
+ GWN_BATCH_DISCARD_SAFE(cache->all_edges);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_verts);
+
+ GWN_VERTBUF_DISCARD_SAFE(cache->pos);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->edges);
+}
+
+void DRW_lattice_batch_cache_free(Lattice *lt)
+{
+ lattice_batch_cache_clear(lt);
+ MEM_SAFE_FREE(lt->batch_cache);
+}
+
+/* Gwn_Batch cache usage. */
+static Gwn_VertBuf *lattice_batch_cache_get_pos(LatticeRenderData *rdata, LatticeBatchCache *cache,
+ bool use_weight, const int actdef)
+{
+ BLI_assert(rdata->types & LR_DATATYPE_VERT);
+
+ if (cache->pos == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, col; } attr_id;
+
+ GWN_vertformat_clear(&format);
+
+ /* initialize vertex format */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ if (use_weight) {
+ attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ }
+
+ const int vert_len = lattice_render_data_verts_len_get(rdata);
+
+ cache->pos = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(cache->pos, vert_len);
+ for (int i = 0; i < vert_len; ++i) {
+ const BPoint *bp = lattice_render_data_vert_bpoint(rdata, i);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.pos, i, bp->vec);
+
+ if (use_weight) {
+ float w_col[4];
+ lattice_render_data_weight_col_get(rdata, i, actdef, w_col);
+
+ GWN_vertbuf_attr_set(cache->pos, attr_id.col, i, w_col);
+ }
+ }
+ }
+
+ return cache->pos;
+}
+
+static Gwn_IndexBuf *lattice_batch_cache_get_edges(LatticeRenderData *rdata, LatticeBatchCache *cache)
+{
+ BLI_assert(rdata->types & (LR_DATATYPE_VERT | LR_DATATYPE_EDGE));
+
+ if (cache->edges == NULL) {
+ const int vert_len = lattice_render_data_verts_len_get(rdata);
+ const int edge_len = lattice_render_data_edges_len_get(rdata);
+ int edge_len_real = 0;
+
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
+
+#define LATT_INDEX(u, v, w) \
+ ((((w) * rdata->dims.v_len + (v)) * rdata->dims.u_len) + (u))
+
+ for (int w = 0; w < rdata->dims.w_len; w++) {
+ int wxt = (w == 0 || w == rdata->dims.w_len - 1);
+ for (int v = 0; v < rdata->dims.v_len; v++) {
+ int vxt = (v == 0 || v == rdata->dims.v_len - 1);
+ for (int u = 0; u < rdata->dims.u_len; u++) {
+ int uxt = (u == 0 || u == rdata->dims.u_len - 1);
+
+ if (w && ((uxt || vxt) || !rdata->show_only_outside)) {
+ GWN_indexbuf_add_line_verts(&elb, LATT_INDEX(u, v, w - 1), LATT_INDEX(u, v, w));
+ BLI_assert(edge_len_real <= edge_len);
+ edge_len_real++;
+ }
+ if (v && ((uxt || wxt) || !rdata->show_only_outside)) {
+ GWN_indexbuf_add_line_verts(&elb, LATT_INDEX(u, v - 1, w), LATT_INDEX(u, v, w));
+ BLI_assert(edge_len_real <= edge_len);
+ edge_len_real++;
+ }
+ if (u && ((vxt || wxt) || !rdata->show_only_outside)) {
+ GWN_indexbuf_add_line_verts(&elb, LATT_INDEX(u - 1, v, w), LATT_INDEX(u, v, w));
+ BLI_assert(edge_len_real <= edge_len);
+ edge_len_real++;
+ }
+ }
+ }
+ }
+
+#undef LATT_INDEX
+
+ if (rdata->show_only_outside) {
+ BLI_assert(edge_len_real <= edge_len);
+ }
+ else {
+ BLI_assert(edge_len_real == edge_len);
+ }
+
+ cache->edges = GWN_indexbuf_build(&elb);
+ }
+
+ return cache->edges;
+}
+
+static void lattice_batch_cache_create_overlay_batches(Lattice *lt)
+{
+ /* Since LR_DATATYPE_OVERLAY is slow to generate, generate them all at once */
+ int options = LR_DATATYPE_VERT | LR_DATATYPE_OVERLAY;
+
+ LatticeBatchCache *cache = lattice_batch_cache_get(lt);
+ LatticeRenderData *rdata = lattice_render_data_create(lt, options);
+
+ if (cache->overlay_verts == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, data; } attr_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_U8, 1, GWN_FETCH_INT);
+ }
+
+ const int vert_len = lattice_render_data_verts_len_get(rdata);
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vert_len);
+ for (int i = 0; i < vert_len; ++i) {
+ const BPoint *bp = lattice_render_data_vert_bpoint(rdata, i);
+
+ char vflag = 0;
+ if (bp->f1 & SELECT) {
+ if (i == rdata->actbp) {
+ vflag |= VFLAG_VERTEX_ACTIVE;
+ }
+ else {
+ vflag |= VFLAG_VERTEX_SELECTED;
+ }
+ }
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i, bp->vec);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, i, &vflag);
+ }
+
+ cache->overlay_verts = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+
+ lattice_render_data_free(rdata);
+}
+
+Gwn_Batch *DRW_lattice_batch_cache_get_all_edges(Lattice *lt, bool use_weight, const int actdef)
+{
+ LatticeBatchCache *cache = lattice_batch_cache_get(lt);
+
+ if (cache->all_edges == NULL) {
+ /* create batch from Lattice */
+ LatticeRenderData *rdata = lattice_render_data_create(lt, LR_DATATYPE_VERT | LR_DATATYPE_EDGE);
+
+ cache->all_edges = GWN_batch_create(GWN_PRIM_LINES, lattice_batch_cache_get_pos(rdata, cache, use_weight, actdef),
+ lattice_batch_cache_get_edges(rdata, cache));
+
+ lattice_render_data_free(rdata);
+ }
+
+ return cache->all_edges;
+}
+
+Gwn_Batch *DRW_lattice_batch_cache_get_all_verts(Lattice *lt)
+{
+ LatticeBatchCache *cache = lattice_batch_cache_get(lt);
+
+ if (cache->all_verts == NULL) {
+ LatticeRenderData *rdata = lattice_render_data_create(lt, LR_DATATYPE_VERT);
+
+ cache->all_verts = GWN_batch_create(GWN_PRIM_POINTS, lattice_batch_cache_get_pos(rdata, cache, false, -1), NULL);
+
+ lattice_render_data_free(rdata);
+ }
+
+ return cache->all_verts;
+}
+
+Gwn_Batch *DRW_lattice_batch_cache_get_overlay_verts(Lattice *lt)
+{
+ LatticeBatchCache *cache = lattice_batch_cache_get(lt);
+
+ if (cache->overlay_verts == NULL) {
+ lattice_batch_cache_create_overlay_batches(lt);
+ }
+
+ return cache->overlay_verts;
+}
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
new file mode 100644
index 00000000000..54021e398c9
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -0,0 +1,3904 @@
+/*
+ * ***** 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) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file draw_cache_impl_mesh.c
+ * \ingroup draw
+ *
+ * \brief Mesh API for render engines
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+#include "BLI_math_bits.h"
+#include "BLI_string.h"
+#include "BLI_alloca.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_deform.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_editmesh.h"
+#include "BKE_editmesh_tangent.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_tangent.h"
+#include "BKE_colorband.h"
+
+#include "bmesh.h"
+
+#include "GPU_batch.h"
+#include "GPU_draw.h"
+#include "GPU_material.h"
+
+#include "draw_cache_impl.h" /* own include */
+
+static void mesh_batch_cache_clear(Mesh *me);
+
+/* ---------------------------------------------------------------------- */
+
+/** \name Mesh/BMesh Interface (direct access to basic data).
+ * \{ */
+
+static int mesh_render_verts_len_get(Mesh *me)
+{
+ return me->edit_btmesh ? me->edit_btmesh->bm->totvert : me->totvert;
+}
+
+static int mesh_render_edges_len_get(Mesh *me)
+{
+ return me->edit_btmesh ? me->edit_btmesh->bm->totedge : me->totedge;
+}
+
+static int mesh_render_looptri_len_get(Mesh *me)
+{
+ return me->edit_btmesh ? me->edit_btmesh->tottri : poly_to_tri_count(me->totpoly, me->totloop);
+}
+
+static int mesh_render_polys_len_get(Mesh *me)
+{
+ return me->edit_btmesh ? me->edit_btmesh->bm->totface : me->totpoly;
+}
+
+static int mesh_render_mat_len_get(Mesh *me)
+{
+ return MAX2(1, me->totcol);
+}
+
+static int UNUSED_FUNCTION(mesh_render_loops_len_get)(Mesh *me)
+{
+ return me->edit_btmesh ? me->edit_btmesh->bm->totloop : me->totloop;
+}
+
+/** \} */
+
+
+/* ---------------------------------------------------------------------- */
+
+/** \name Mesh/BMesh Interface (indirect, partially cached access to complex data).
+ * \{ */
+
+typedef struct EdgeAdjacentPolys {
+ int count;
+ int face_index[2];
+} EdgeAdjacentPolys;
+
+typedef struct EdgeDrawAttr {
+ unsigned char v_flag;
+ unsigned char e_flag;
+ unsigned char crease;
+ unsigned char bweight;
+} EdgeDrawAttr;
+
+typedef struct MeshRenderData {
+ int types;
+
+ int vert_len;
+ int edge_len;
+ int tri_len;
+ int loop_len;
+ int poly_len;
+ int mat_len;
+ int loose_vert_len;
+ int loose_edge_len;
+
+ BMEditMesh *edit_bmesh;
+ MVert *mvert;
+ MEdge *medge;
+ MLoop *mloop;
+ MPoly *mpoly;
+ float (*orco)[3];
+ MDeformVert *dvert;
+ MLoopUV *mloopuv;
+ MLoopCol *mloopcol;
+ float (*loop_normals)[3];
+
+ /* CustomData 'cd' cache for efficient access. */
+ struct {
+ struct {
+ MLoopUV **uv;
+ int uv_len;
+ int uv_active;
+
+ MLoopCol **vcol;
+ int vcol_len;
+ int vcol_active;
+
+ float (**tangent)[4];
+ int tangent_len;
+ int tangent_active;
+
+ bool *auto_vcol;
+ } layers;
+
+ /* Custom-data offsets (only needed for BMesh access) */
+ struct {
+ int crease;
+ int bweight;
+ int *uv;
+ int *vcol;
+ } offset;
+
+ struct {
+ char (*auto_mix)[32];
+ char (*uv)[32];
+ char (*vcol)[32];
+ char (*tangent)[32];
+ } uuid;
+
+ /* for certain cases we need an output loop-data storage (bmesh tangents) */
+ struct {
+ CustomData ldata;
+ /* grr, special case variable (use in place of 'dm->tangent_mask') */
+ short tangent_mask;
+ } output;
+ } cd;
+
+ BMVert *eve_act;
+ BMEdge *eed_act;
+ BMFace *efa_act;
+
+ /* Data created on-demand (usually not for bmesh-based data). */
+ EdgeAdjacentPolys *edges_adjacent_polys;
+ MLoopTri *mlooptri;
+ int *loose_edges;
+ int *loose_verts;
+
+ float (*poly_normals)[3];
+ float (*vert_weight_color)[3];
+ char (*vert_color)[3];
+ Gwn_PackedNormal *poly_normals_pack;
+ Gwn_PackedNormal *vert_normals_pack;
+ bool *edge_select_bool;
+} MeshRenderData;
+
+enum {
+ MR_DATATYPE_VERT = 1 << 0,
+ MR_DATATYPE_EDGE = 1 << 1,
+ MR_DATATYPE_LOOPTRI = 1 << 2,
+ MR_DATATYPE_LOOP = 1 << 3,
+ MR_DATATYPE_POLY = 1 << 4,
+ MR_DATATYPE_OVERLAY = 1 << 5,
+ MR_DATATYPE_SHADING = 1 << 6,
+ MR_DATATYPE_DVERT = 1 << 7,
+ MR_DATATYPE_LOOPCOL = 1 << 8,
+ MR_DATATYPE_LOOPUV = 1 << 9,
+};
+
+/**
+ * These functions look like they would be slow but they will typically return true on the first iteration.
+ * Only false when all attached elements are hidden.
+ */
+static bool bm_vert_has_visible_edge(const BMVert *v)
+{
+ const BMEdge *e_iter, *e_first;
+
+ e_iter = e_first = v->e;
+ do {
+ if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) {
+ return true;
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
+ return false;
+}
+
+static bool bm_edge_has_visible_face(const BMEdge *e)
+{
+ const BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ return false;
+}
+
+
+static void mesh_cd_calc_used_gpu_layers(
+ CustomData *UNUSED(cd_vdata), uchar cd_vused[CD_NUMTYPES],
+ CustomData *cd_ldata, ushort cd_lused[CD_NUMTYPES],
+ struct GPUMaterial **gpumat_array, int gpumat_array_len)
+{
+ /* See: DM_vertex_attributes_from_gpu for similar logic */
+ GPUVertexAttribs gattribs = {{{0}}};
+
+ for (int i = 0; i < gpumat_array_len; i++) {
+ GPUMaterial *gpumat = gpumat_array[i];
+ if (gpumat) {
+ GPU_material_vertex_attributes(gpumat, &gattribs);
+ for (int j = 0; j < gattribs.totlayer; j++) {
+ const char *name = gattribs.layer[j].name;
+ int type = gattribs.layer[j].type;
+ int layer = -1;
+
+ if (type == CD_AUTO_FROM_NAME) {
+ /* We need to deduct what exact layer is used.
+ *
+ * We do it based on the specified name.
+ */
+ if (name[0] != '\0') {
+ layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name);
+ type = CD_MTFACE;
+
+ if (layer == -1) {
+ layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name);
+ type = CD_MCOL;
+ }
+#if 0 /* Tangents are always from UV's - this will never happen. */
+ if (layer == -1) {
+ layer = CustomData_get_named_layer(cd_ldata, CD_TANGENT, name);
+ type = CD_TANGENT;
+ }
+#endif
+ if (layer == -1) {
+ continue;
+ }
+ }
+ else {
+ /* Fall back to the UV layer, which matches old behavior. */
+ type = CD_MTFACE;
+ }
+ }
+
+ switch (type) {
+ case CD_MTFACE:
+ {
+ if (layer == -1) {
+ layer = (name[0] != '\0') ?
+ CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
+ CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ }
+ if (layer != -1) {
+ cd_lused[CD_MLOOPUV] |= (1 << layer);
+ }
+ break;
+ }
+ case CD_TANGENT:
+ {
+ if (layer == -1) {
+ layer = (name[0] != '\0') ?
+ CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
+ CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ }
+ if (layer != -1) {
+ cd_lused[CD_TANGENT] |= (1 << layer);
+ }
+ else {
+ /* no UV layers at all => requesting orco */
+ cd_lused[CD_TANGENT] |= DM_TANGENT_MASK_ORCO;
+ cd_vused[CD_ORCO] |= 1;
+ }
+ break;
+ }
+ case CD_MCOL:
+ {
+ if (layer == -1) {
+ layer = (name[0] != '\0') ?
+ CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name) :
+ CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
+ }
+ if (layer != -1) {
+ cd_lused[CD_MLOOPCOL] |= (1 << layer);
+ }
+ break;
+ }
+ case CD_ORCO:
+ {
+ cd_vused[CD_ORCO] |= 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+static void mesh_render_calc_normals_loop_and_poly(const Mesh *me, const float split_angle, MeshRenderData *rdata)
+{
+ BLI_assert((me->flag & ME_AUTOSMOOTH) != 0);
+
+ int totloop = me->totloop;
+ int totpoly = me->totpoly;
+ float (*loop_normals)[3] = MEM_mallocN(sizeof(*loop_normals) * totloop, __func__);
+ float (*poly_normals)[3] = MEM_mallocN(sizeof(*poly_normals) * totpoly, __func__);
+ short (*clnors)[2] = CustomData_get_layer(&me->ldata, CD_CUSTOMLOOPNORMAL);
+
+ BKE_mesh_calc_normals_poly(
+ me->mvert, NULL, me->totvert,
+ me->mloop, me->mpoly, totloop, totpoly, poly_normals, false);
+
+ BKE_mesh_normals_loop_split(
+ me->mvert, me->totvert, me->medge, me->totedge,
+ me->mloop, loop_normals, totloop, me->mpoly, poly_normals, totpoly,
+ true, split_angle, NULL, clnors, NULL);
+
+ rdata->loop_len = totloop;
+ rdata->poly_len = totpoly;
+ rdata->loop_normals = loop_normals;
+ rdata->poly_normals = poly_normals;
+}
+
+
+/**
+ * TODO(campbell): 'gpumat_array' may include materials linked to the object.
+ * While not default, object materials should be supported.
+ * Although this only impacts the data thats generated, not the materials that display.
+ */
+static MeshRenderData *mesh_render_data_create_ex(
+ Mesh *me, const int types,
+ struct GPUMaterial **gpumat_array, uint gpumat_array_len)
+{
+ MeshRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__);
+ rdata->types = types;
+ rdata->mat_len = mesh_render_mat_len_get(me);
+
+ CustomData_reset(&rdata->cd.output.ldata);
+
+ const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
+ const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
+
+ if (me->edit_btmesh) {
+ BMEditMesh *embm = me->edit_btmesh;
+ BMesh *bm = embm->bm;
+
+ rdata->edit_bmesh = embm;
+
+ int bm_ensure_types = 0;
+ if (types & (MR_DATATYPE_VERT)) {
+ rdata->vert_len = bm->totvert;
+ bm_ensure_types |= BM_VERT;
+ }
+ if (types & (MR_DATATYPE_EDGE)) {
+ rdata->edge_len = bm->totedge;
+ bm_ensure_types |= BM_EDGE;
+ }
+ if (types & MR_DATATYPE_LOOPTRI) {
+ BKE_editmesh_tessface_calc(embm);
+ rdata->tri_len = embm->tottri;
+ }
+ if (types & MR_DATATYPE_LOOP) {
+ int totloop = bm->totloop;
+ if (is_auto_smooth) {
+ rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * totloop, __func__);
+ BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1);
+ }
+ rdata->loop_len = totloop;
+ bm_ensure_types |= BM_LOOP;
+ }
+ if (types & MR_DATATYPE_POLY) {
+ rdata->poly_len = bm->totface;
+ bm_ensure_types |= BM_FACE;
+ }
+ if (types & MR_DATATYPE_OVERLAY) {
+ rdata->efa_act = BM_mesh_active_face_get(bm, false, true);
+ rdata->eed_act = BM_mesh_active_edge_get(bm);
+ rdata->eve_act = BM_mesh_active_vert_get(bm);
+ rdata->cd.offset.crease = CustomData_get_offset(&bm->edata, CD_CREASE);
+ rdata->cd.offset.bweight = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ }
+ if (types & (MR_DATATYPE_DVERT)) {
+ bm_ensure_types |= BM_VERT;
+ }
+
+ BM_mesh_elem_index_ensure(bm, bm_ensure_types);
+ BM_mesh_elem_table_ensure(bm, bm_ensure_types & ~BM_LOOP);
+ if (types & MR_DATATYPE_OVERLAY) {
+ rdata->loose_vert_len = rdata->loose_edge_len = 0;
+
+ int *lverts = rdata->loose_verts = MEM_mallocN(rdata->vert_len * sizeof(int), "Loose Vert");
+ int *ledges = rdata->loose_edges = MEM_mallocN(rdata->edge_len * sizeof(int), "Loose Edges");
+
+ {
+ BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
+ BMVert **vtable = bm->vtable;
+ for (int i = 0; i < bm->totvert; i++) {
+ const BMVert *eve = vtable[i];
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ /* Loose vert */
+ if (eve->e == NULL || !bm_vert_has_visible_edge(eve)) {
+ lverts[rdata->loose_vert_len++] = i;
+ }
+ }
+ }
+ }
+
+ {
+ BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0);
+ BMEdge **etable = bm->etable;
+ for (int i = 0; i < bm->totedge; i++) {
+ const BMEdge *eed = etable[i];
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ /* Loose edge */
+ if (eed->l == NULL || !bm_edge_has_visible_face(eed)) {
+ ledges[rdata->loose_edge_len++] = i;
+ }
+ }
+ }
+ }
+
+ rdata->loose_verts = MEM_reallocN(rdata->loose_verts, rdata->loose_vert_len * sizeof(int));
+ rdata->loose_edges = MEM_reallocN(rdata->loose_edges, rdata->loose_edge_len * sizeof(int));
+ }
+ }
+ else {
+ if (types & (MR_DATATYPE_VERT)) {
+ rdata->vert_len = me->totvert;
+ rdata->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
+ }
+ if (types & (MR_DATATYPE_EDGE)) {
+ rdata->edge_len = me->totedge;
+ rdata->medge = CustomData_get_layer(&me->edata, CD_MEDGE);
+ }
+ if (types & MR_DATATYPE_LOOPTRI) {
+ const int tri_len = rdata->tri_len = poly_to_tri_count(me->totpoly, me->totloop);
+ rdata->mlooptri = MEM_mallocN(sizeof(*rdata->mlooptri) * tri_len, __func__);
+ BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, rdata->mlooptri);
+ }
+ if (types & MR_DATATYPE_LOOP) {
+ rdata->loop_len = me->totloop;
+ rdata->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
+
+ if (is_auto_smooth) {
+ mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata);
+ }
+ }
+ if (types & MR_DATATYPE_POLY) {
+ rdata->poly_len = me->totpoly;
+ rdata->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
+ }
+ if (types & MR_DATATYPE_DVERT) {
+ rdata->vert_len = me->totvert;
+ rdata->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT);
+ }
+ if (types & MR_DATATYPE_LOOPCOL) {
+ rdata->loop_len = me->totloop;
+ rdata->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
+ }
+ if (types & MR_DATATYPE_LOOPUV) {
+ rdata->loop_len = me->totloop;
+ rdata->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
+ }
+ }
+
+ if (types & MR_DATATYPE_SHADING) {
+ CustomData *cd_vdata, *cd_ldata;
+
+ if (me->edit_btmesh) {
+ BMesh *bm = me->edit_btmesh->bm;
+ cd_vdata = &bm->vdata;
+ cd_ldata = &bm->ldata;
+ }
+ else {
+ cd_vdata = &me->vdata;
+ cd_ldata = &me->ldata;
+ }
+
+ /* Add edge/poly if we need them */
+ uchar cd_vused[CD_NUMTYPES] = {0};
+ ushort cd_lused[CD_NUMTYPES] = {0};
+
+ mesh_cd_calc_used_gpu_layers(
+ cd_vdata, cd_vused,
+ cd_ldata, cd_lused,
+ gpumat_array, gpumat_array_len);
+
+
+ rdata->cd.layers.uv_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ rdata->cd.layers.vcol_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
+ rdata->cd.layers.tangent_active = rdata->cd.layers.uv_active;
+
+#define CD_VALIDATE_ACTIVE_LAYER(active_index, used) \
+ if ((active_index != -1) && (used & (1 << active_index)) == 0) { \
+ active_index = -1; \
+ } ((void)0)
+
+ CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.uv_active, cd_lused[CD_MLOOPUV]);
+ CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.tangent_active, cd_lused[CD_TANGENT]);
+ CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.vcol_active, cd_lused[CD_MLOOPCOL]);
+
+#undef CD_VALIDATE_ACTIVE_LAYER
+
+ if (cd_vused[CD_ORCO] & 1) {
+ rdata->orco = CustomData_get_layer(cd_vdata, CD_ORCO);
+ /* If orco is not available compute it ourselves */
+ if (!rdata->orco) {
+ if (me->edit_btmesh) {
+ BMesh *bm = me->edit_btmesh->bm;
+ rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh");
+ BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
+ BMVert **vtable = bm->vtable;
+ for (int i = 0; i < bm->totvert; i++) {
+ copy_v3_v3(rdata->orco[i], vtable[i]->co);
+ }
+ BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0);
+ }
+ else {
+ rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh");
+ MVert *mvert = rdata->mvert;
+ for (int a = 0; a < rdata->vert_len; a++, mvert++) {
+ copy_v3_v3(rdata->orco[a], mvert->co);
+ }
+ BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0);
+ }
+ }
+ }
+ else {
+ rdata->orco = NULL;
+ }
+
+ /* don't access mesh directly, instead use vars taken from BMesh or Mesh */
+#define me DONT_USE_THIS
+#ifdef me /* quiet warning */
+#endif
+ struct {
+ uint uv_len;
+ uint vcol_len;
+ } cd_layers_src = {
+ .uv_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPUV),
+ .vcol_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPCOL),
+ };
+
+ rdata->cd.layers.uv_len = count_bits_i(cd_lused[CD_MLOOPUV]);
+ rdata->cd.layers.tangent_len = count_bits_i(cd_lused[CD_TANGENT]);
+ rdata->cd.layers.vcol_len = count_bits_i(cd_lused[CD_MLOOPCOL]);
+
+ rdata->cd.layers.uv = MEM_mallocN(sizeof(*rdata->cd.layers.uv) * rdata->cd.layers.uv_len, __func__);
+ rdata->cd.layers.vcol = MEM_mallocN(sizeof(*rdata->cd.layers.vcol) * rdata->cd.layers.vcol_len, __func__);
+ rdata->cd.layers.tangent = MEM_mallocN(sizeof(*rdata->cd.layers.tangent) * rdata->cd.layers.tangent_len, __func__);
+
+ rdata->cd.uuid.uv = MEM_mallocN(sizeof(*rdata->cd.uuid.uv) * rdata->cd.layers.uv_len, __func__);
+ rdata->cd.uuid.vcol = MEM_mallocN(sizeof(*rdata->cd.uuid.vcol) * rdata->cd.layers.vcol_len, __func__);
+ rdata->cd.uuid.tangent = MEM_mallocN(sizeof(*rdata->cd.uuid.tangent) * rdata->cd.layers.tangent_len, __func__);
+
+ rdata->cd.offset.uv = MEM_mallocN(sizeof(*rdata->cd.offset.uv) * rdata->cd.layers.uv_len, __func__);
+ rdata->cd.offset.vcol = MEM_mallocN(sizeof(*rdata->cd.offset.vcol) * rdata->cd.layers.vcol_len, __func__);
+
+ /* Allocate max */
+ rdata->cd.layers.auto_vcol = MEM_callocN(
+ sizeof(*rdata->cd.layers.auto_vcol) * rdata->cd.layers.vcol_len, __func__);
+ rdata->cd.uuid.auto_mix = MEM_mallocN(
+ sizeof(*rdata->cd.uuid.auto_mix) * (rdata->cd.layers.vcol_len + rdata->cd.layers.uv_len), __func__);
+
+ /* XXX FIXME XXX */
+ /* We use a hash to identify each data layer based on its name.
+ * Gawain then search for this name in the current shader and bind if it exists.
+ * NOTE : This is prone to hash collision.
+ * One solution to hash collision would be to format the cd layer name
+ * to a safe glsl var name, but without name clash.
+ * NOTE 2 : Replicate changes to code_generate_vertex_new() in gpu_codegen.c */
+ if (rdata->cd.layers.vcol_len != 0) {
+ for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.vcol_len; i_src++, i_dst++) {
+ if ((cd_lused[CD_MLOOPCOL] & (1 << i_src)) == 0) {
+ i_dst--;
+ if (rdata->cd.layers.vcol_active >= i_src) {
+ rdata->cd.layers.vcol_active--;
+ }
+ }
+ else {
+ const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i_src);
+ unsigned int hash = BLI_ghashutil_strhash_p(name);
+ BLI_snprintf(rdata->cd.uuid.vcol[i_dst], sizeof(*rdata->cd.uuid.vcol), "c%u", hash);
+ rdata->cd.layers.vcol[i_dst] = CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i_src);
+ if (rdata->edit_bmesh) {
+ rdata->cd.offset.vcol[i_dst] = CustomData_get_n_offset(
+ &rdata->edit_bmesh->bm->ldata, CD_MLOOPCOL, i_src);
+ }
+
+ /* Gather number of auto layers. */
+ /* We only do vcols that are not overridden by uvs */
+ if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, name) == -1) {
+ BLI_snprintf(
+ rdata->cd.uuid.auto_mix[rdata->cd.layers.uv_len + i_dst],
+ sizeof(*rdata->cd.uuid.auto_mix), "a%u", hash);
+ rdata->cd.layers.auto_vcol[i_dst] = true;
+ }
+ }
+ }
+ }
+
+ /* Start Fresh */
+ CustomData_free_layers(cd_ldata, CD_TANGENT, rdata->loop_len);
+ CustomData_free_layers(cd_ldata, CD_MLOOPTANGENT, rdata->loop_len);
+
+ if (rdata->cd.layers.uv_len != 0) {
+ for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) {
+ if ((cd_lused[CD_MLOOPUV] & (1 << i_src)) == 0) {
+ i_dst--;
+ if (rdata->cd.layers.uv_active >= i_src) {
+ rdata->cd.layers.uv_active--;
+ }
+ }
+ else {
+ const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src);
+ unsigned int hash = BLI_ghashutil_strhash_p(name);
+
+ BLI_snprintf(rdata->cd.uuid.uv[i_dst], sizeof(*rdata->cd.uuid.uv), "u%u", hash);
+ rdata->cd.layers.uv[i_dst] = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i_src);
+ if (rdata->edit_bmesh) {
+ rdata->cd.offset.uv[i_dst] = CustomData_get_n_offset(
+ &rdata->edit_bmesh->bm->ldata, CD_MLOOPUV, i_src);
+ }
+ BLI_snprintf(rdata->cd.uuid.auto_mix[i_dst], sizeof(*rdata->cd.uuid.auto_mix), "a%u", hash);
+ }
+ }
+ }
+
+ if (rdata->cd.layers.tangent_len != 0) {
+
+ /* -------------------------------------------------------------------- */
+ /* Pre-calculate tangents into 'rdata->cd.output.ldata' */
+
+ BLI_assert(!CustomData_has_layer(&rdata->cd.output.ldata, CD_TANGENT));
+
+ /* Tangent Names */
+ char tangent_names[MAX_MTFACE][MAX_NAME];
+ for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) {
+ if ((cd_lused[CD_TANGENT] & (1 << i_src)) == 0) {
+ i_dst--;
+ }
+ else {
+ BLI_strncpy(
+ tangent_names[i_dst],
+ CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src), MAX_NAME);
+ }
+ }
+
+ /* If tangent from orco is requested, decrement tangent_len */
+ int actual_tangent_len = (cd_lused[CD_TANGENT] & DM_TANGENT_MASK_ORCO) ?
+ rdata->cd.layers.tangent_len - 1 : rdata->cd.layers.tangent_len;
+ if (rdata->edit_bmesh) {
+ BMEditMesh *em = rdata->edit_bmesh;
+ BMesh *bm = em->bm;
+
+ if (is_auto_smooth && rdata->loop_normals == NULL) {
+ /* Should we store the previous array of `loop_normals` in somewhere? */
+ rdata->loop_len = bm->totloop;
+ rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * rdata->loop_len, __func__);
+ BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1);
+ }
+
+ bool calc_active_tangent = false;
+
+ BKE_editmesh_loop_tangent_calc(
+ em, calc_active_tangent,
+ tangent_names, actual_tangent_len,
+ rdata->poly_normals, rdata->loop_normals,
+ rdata->orco,
+ &rdata->cd.output.ldata, bm->totloop,
+ &rdata->cd.output.tangent_mask);
+ }
+ else {
+#undef me
+
+ if (is_auto_smooth && rdata->loop_normals == NULL) {
+ /* Should we store the previous array of `loop_normals` in CustomData? */
+ mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata);
+ }
+
+ bool calc_active_tangent = false;
+
+ BKE_mesh_calc_loop_tangent_ex(
+ me->mvert,
+ me->mpoly, me->totpoly,
+ me->mloop,
+ rdata->mlooptri, rdata->tri_len,
+ cd_ldata,
+ calc_active_tangent,
+ tangent_names, actual_tangent_len,
+ rdata->poly_normals, rdata->loop_normals,
+ rdata->orco,
+ &rdata->cd.output.ldata, me->totloop,
+ &rdata->cd.output.tangent_mask);
+
+ /* If we store tangents in the mesh, set temporary. */
+#if 0
+ CustomData_set_layer_flag(cd_ldata, CD_TANGENT, CD_FLAG_TEMPORARY);
+#endif
+
+#define me DONT_USE_THIS
+#ifdef me /* quiet warning */
+#endif
+ }
+
+ /* End tangent calculation */
+ /* -------------------------------------------------------------------- */
+
+ BLI_assert(CustomData_number_of_layers(&rdata->cd.output.ldata, CD_TANGENT) == rdata->cd.layers.tangent_len);
+
+ int i_dst = 0;
+ for (int i_src = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) {
+ if ((cd_lused[CD_TANGENT] & (1 << i_src)) == 0) {
+ i_dst--;
+ if (rdata->cd.layers.tangent_active >= i_src) {
+ rdata->cd.layers.tangent_active--;
+ }
+ }
+ else {
+ const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src);
+ unsigned int hash = BLI_ghashutil_strhash_p(name);
+
+ BLI_snprintf(rdata->cd.uuid.tangent[i_dst], sizeof(*rdata->cd.uuid.tangent), "t%u", hash);
+
+ /* Done adding tangents. */
+
+ /* note: BKE_editmesh_loop_tangent_calc calculates 'CD_TANGENT',
+ * not 'CD_MLOOPTANGENT' (as done below). It's OK, they're compatible. */
+
+ /* note: normally we'd use 'i_src' here, but 'i_dst' is in sync with 'rdata->cd.output' */
+ rdata->cd.layers.tangent[i_dst] = CustomData_get_layer_n(&rdata->cd.output.ldata, CD_TANGENT, i_dst);
+ if (rdata->tri_len != 0) {
+ BLI_assert(rdata->cd.layers.tangent[i_dst] != NULL);
+ }
+ }
+ }
+ if (cd_lused[CD_TANGENT] & DM_TANGENT_MASK_ORCO) {
+ const char *name = CustomData_get_layer_name(&rdata->cd.output.ldata, CD_TANGENT, i_dst);
+ unsigned int hash = BLI_ghashutil_strhash_p(name);
+ BLI_snprintf(rdata->cd.uuid.tangent[i_dst], sizeof(*rdata->cd.uuid.tangent), "t%u", hash);
+
+ rdata->cd.layers.tangent[i_dst] = CustomData_get_layer_n(&rdata->cd.output.ldata, CD_TANGENT, i_dst);
+ }
+ }
+
+#undef me
+ }
+
+ return rdata;
+}
+
+static void mesh_render_data_free(MeshRenderData *rdata)
+{
+ MEM_SAFE_FREE(rdata->orco);
+ MEM_SAFE_FREE(rdata->cd.offset.uv);
+ MEM_SAFE_FREE(rdata->cd.offset.vcol);
+ MEM_SAFE_FREE(rdata->cd.uuid.auto_mix);
+ MEM_SAFE_FREE(rdata->cd.uuid.uv);
+ MEM_SAFE_FREE(rdata->cd.uuid.vcol);
+ MEM_SAFE_FREE(rdata->cd.uuid.tangent);
+ MEM_SAFE_FREE(rdata->cd.layers.uv);
+ MEM_SAFE_FREE(rdata->cd.layers.vcol);
+ MEM_SAFE_FREE(rdata->cd.layers.tangent);
+ MEM_SAFE_FREE(rdata->cd.layers.auto_vcol);
+ MEM_SAFE_FREE(rdata->loose_verts);
+ MEM_SAFE_FREE(rdata->loose_edges);
+ MEM_SAFE_FREE(rdata->edges_adjacent_polys);
+ MEM_SAFE_FREE(rdata->mlooptri);
+ MEM_SAFE_FREE(rdata->loop_normals);
+ MEM_SAFE_FREE(rdata->poly_normals);
+ MEM_SAFE_FREE(rdata->poly_normals_pack);
+ MEM_SAFE_FREE(rdata->vert_normals_pack);
+ MEM_SAFE_FREE(rdata->vert_weight_color);
+ MEM_SAFE_FREE(rdata->edge_select_bool);
+ MEM_SAFE_FREE(rdata->vert_color);
+
+ CustomData_free(&rdata->cd.output.ldata, rdata->loop_len);
+
+ MEM_freeN(rdata);
+}
+
+static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
+{
+ return mesh_render_data_create_ex(me, types, NULL, 0);
+}
+
+/** \} */
+
+
+/* ---------------------------------------------------------------------- */
+
+/** \name Accessor Functions
+ * \{ */
+
+static const char *mesh_render_data_uv_auto_layer_uuid_get(const MeshRenderData *rdata, int layer)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_SHADING);
+ return rdata->cd.uuid.auto_mix[layer];
+}
+
+static const char *mesh_render_data_vcol_auto_layer_uuid_get(const MeshRenderData *rdata, int layer)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_SHADING);
+ return rdata->cd.uuid.auto_mix[rdata->cd.layers.uv_len + layer];
+}
+
+static const char *mesh_render_data_uv_layer_uuid_get(const MeshRenderData *rdata, int layer)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_SHADING);
+ return rdata->cd.uuid.uv[layer];
+}
+
+static const char *mesh_render_data_vcol_layer_uuid_get(const MeshRenderData *rdata, int layer)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_SHADING);
+ return rdata->cd.uuid.vcol[layer];
+}
+
+static const char *mesh_render_data_tangent_layer_uuid_get(const MeshRenderData *rdata, int layer)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_SHADING);
+ return rdata->cd.uuid.tangent[layer];
+}
+
+static int mesh_render_data_verts_len_get(const MeshRenderData *rdata)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+ return rdata->vert_len;
+}
+
+static int mesh_render_data_loose_verts_len_get(const MeshRenderData *rdata)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_OVERLAY);
+ return rdata->loose_vert_len;
+}
+
+static int mesh_render_data_edges_len_get(const MeshRenderData *rdata)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_EDGE);
+ return rdata->edge_len;
+}
+
+static int mesh_render_data_loose_edges_len_get(const MeshRenderData *rdata)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_OVERLAY);
+ return rdata->loose_edge_len;
+}
+
+static int mesh_render_data_looptri_len_get(const MeshRenderData *rdata)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_LOOPTRI);
+ return rdata->tri_len;
+}
+
+static int mesh_render_data_mat_len_get(const MeshRenderData *rdata)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_POLY);
+ return rdata->mat_len;
+}
+
+static int UNUSED_FUNCTION(mesh_render_data_loops_len_get)(const MeshRenderData *rdata)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_LOOP);
+ return rdata->loop_len;
+}
+
+static int mesh_render_data_polys_len_get(const MeshRenderData *rdata)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_POLY);
+ return rdata->poly_len;
+}
+
+/** \} */
+
+
+/* ---------------------------------------------------------------------- */
+
+/** \name Internal Cache (Lazy Initialization)
+ * \{ */
+
+/** Ensure #MeshRenderData.poly_normals_pack */
+static void mesh_render_data_ensure_poly_normals_pack(MeshRenderData *rdata)
+{
+ Gwn_PackedNormal *pnors_pack = rdata->poly_normals_pack;
+ if (pnors_pack == NULL) {
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter fiter;
+ BMFace *efa;
+ int i;
+
+ pnors_pack = rdata->poly_normals_pack = MEM_mallocN(sizeof(*pnors_pack) * rdata->poly_len, __func__);
+ BM_ITER_MESH_INDEX(efa, &fiter, bm, BM_FACES_OF_MESH, i) {
+ pnors_pack[i] = GWN_normal_convert_i10_v3(efa->no);
+ }
+ }
+ else {
+ float (*pnors)[3] = rdata->poly_normals;
+
+ if (!pnors) {
+ pnors = rdata->poly_normals = MEM_mallocN(sizeof(*pnors) * rdata->poly_len, __func__);
+ BKE_mesh_calc_normals_poly(
+ rdata->mvert, NULL, rdata->vert_len,
+ rdata->mloop, rdata->mpoly, rdata->loop_len, rdata->poly_len, pnors, true);
+ }
+
+ pnors_pack = rdata->poly_normals_pack = MEM_mallocN(sizeof(*pnors_pack) * rdata->poly_len, __func__);
+ for (int i = 0; i < rdata->poly_len; i++) {
+ pnors_pack[i] = GWN_normal_convert_i10_v3(pnors[i]);
+ }
+ }
+ }
+}
+
+/** Ensure #MeshRenderData.vert_normals_pack */
+static void mesh_render_data_ensure_vert_normals_pack(MeshRenderData *rdata)
+{
+ Gwn_PackedNormal *vnors_pack = rdata->vert_normals_pack;
+ if (vnors_pack == NULL) {
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter viter;
+ BMVert *eve;
+ int i;
+
+ vnors_pack = rdata->vert_normals_pack = MEM_mallocN(sizeof(*vnors_pack) * rdata->vert_len, __func__);
+ BM_ITER_MESH_INDEX(eve, &viter, bm, BM_VERT, i) {
+ vnors_pack[i] = GWN_normal_convert_i10_v3(eve->no);
+ }
+ }
+ else {
+ /* data from mesh used directly */
+ BLI_assert(0);
+ }
+ }
+}
+
+
+/** Ensure #MeshRenderData.vert_color */
+static void mesh_render_data_ensure_vert_color(MeshRenderData *rdata)
+{
+ char (*vcol)[3] = rdata->vert_color;
+ if (vcol == NULL) {
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
+ if (cd_loop_color_offset == -1) {
+ goto fallback;
+ }
+
+ vcol = rdata->vert_color = MEM_mallocN(sizeof(*vcol) * rdata->loop_len, __func__);
+
+ BMIter fiter;
+ BMFace *efa;
+ int i = 0;
+
+ BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ const MLoopCol *lcol = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_color_offset);
+ vcol[i][0] = lcol->r;
+ vcol[i][1] = lcol->g;
+ vcol[i][2] = lcol->b;
+ i += 1;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ BLI_assert(i == rdata->loop_len);
+ }
+ else {
+ if (rdata->mloopcol == NULL) {
+ goto fallback;
+ }
+
+ vcol = rdata->vert_color = MEM_mallocN(sizeof(*vcol) * rdata->loop_len, __func__);
+
+ for (int i = 0; i < rdata->loop_len; i++) {
+ vcol[i][0] = rdata->mloopcol[i].r;
+ vcol[i][1] = rdata->mloopcol[i].g;
+ vcol[i][2] = rdata->mloopcol[i].b;
+ }
+ }
+ }
+ return;
+
+fallback:
+ vcol = rdata->vert_color = MEM_mallocN(sizeof(*vcol) * rdata->loop_len, __func__);
+
+ for (int i = 0; i < rdata->loop_len; i++) {
+ vcol[i][0] = 255;
+ vcol[i][1] = 255;
+ vcol[i][2] = 255;
+ }
+}
+
+/* TODO, move into shader? */
+static void rgb_from_weight(float r_rgb[3], const float weight)
+{
+ const float blend = ((weight / 2.0f) + 0.5f);
+
+ if (weight <= 0.25f) { /* blue->cyan */
+ r_rgb[0] = 0.0f;
+ r_rgb[1] = blend * weight * 4.0f;
+ r_rgb[2] = blend;
+ }
+ else if (weight <= 0.50f) { /* cyan->green */
+ r_rgb[0] = 0.0f;
+ r_rgb[1] = blend;
+ r_rgb[2] = blend * (1.0f - ((weight - 0.25f) * 4.0f));
+ }
+ else if (weight <= 0.75f) { /* green->yellow */
+ r_rgb[0] = blend * ((weight - 0.50f) * 4.0f);
+ r_rgb[1] = blend;
+ r_rgb[2] = 0.0f;
+ }
+ else if (weight <= 1.0f) { /* yellow->red */
+ r_rgb[0] = blend;
+ r_rgb[1] = blend * (1.0f - ((weight - 0.75f) * 4.0f));
+ r_rgb[2] = 0.0f;
+ }
+ else {
+ /* exceptional value, unclamped or nan,
+ * avoid uninitialized memory use */
+ r_rgb[0] = 1.0f;
+ r_rgb[1] = 0.0f;
+ r_rgb[2] = 1.0f;
+ }
+}
+
+
+/** Ensure #MeshRenderData.vert_weight_color */
+static void mesh_render_data_ensure_vert_weight_color(MeshRenderData *rdata, const int defgroup)
+{
+ float (*vweight)[3] = rdata->vert_weight_color;
+ if (vweight == NULL) {
+ if (defgroup == -1) {
+ goto fallback;
+ }
+
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
+ if (cd_dvert_offset == -1) {
+ goto fallback;
+ }
+
+ BMIter viter;
+ BMVert *eve;
+ int i;
+
+ vweight = rdata->vert_weight_color = MEM_mallocN(sizeof(*vweight) * rdata->vert_len, __func__);
+ BM_ITER_MESH_INDEX(eve, &viter, bm, BM_VERT, i) {
+ const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ float weight = defvert_find_weight(dvert, defgroup);
+ if (U.flag & USER_CUSTOM_RANGE) {
+ BKE_colorband_evaluate(&U.coba_weight, weight, vweight[i]);
+ }
+ else {
+ rgb_from_weight(vweight[i], weight);
+ }
+ }
+ }
+ else {
+ if (rdata->dvert == NULL) {
+ goto fallback;
+ }
+
+ vweight = rdata->vert_weight_color = MEM_mallocN(sizeof(*vweight) * rdata->vert_len, __func__);
+ for (int i = 0; i < rdata->vert_len; i++) {
+ float weight = defvert_find_weight(&rdata->dvert[i], defgroup);
+ if (U.flag & USER_CUSTOM_RANGE) {
+ BKE_colorband_evaluate(&U.coba_weight, weight, vweight[i]);
+ }
+ else {
+ rgb_from_weight(vweight[i], weight);
+ }
+ }
+ }
+ }
+ return;
+
+fallback:
+ vweight = rdata->vert_weight_color = MEM_callocN(sizeof(*vweight) * rdata->vert_len, __func__);
+
+ for (int i = 0; i < rdata->vert_len; i++) {
+ vweight[i][2] = 0.5f;
+ }
+}
+
+/** Ensure #MeshRenderData.edge_select_bool */
+static void mesh_render_data_ensure_edge_select_bool(MeshRenderData *rdata, bool use_wire)
+{
+ bool *edge_select_bool = rdata->edge_select_bool;
+ if (edge_select_bool == NULL) {
+ edge_select_bool = rdata->edge_select_bool =
+ MEM_callocN(sizeof(*edge_select_bool) * rdata->edge_len, __func__);
+
+ for (int i = 0; i < rdata->poly_len; i++) {
+ MPoly *poly = &rdata->mpoly[i];
+
+ if (poly->flag & ME_FACE_SEL) {
+ for (int j = 0; j < poly->totloop; j++) {
+ MLoop *loop = &rdata->mloop[poly->loopstart + j];
+ if (use_wire) {
+ edge_select_bool[loop->e] = true;
+ }
+ else {
+ /* Not totally correct, will cause problems for edges with 3x faces. */
+ edge_select_bool[loop->e] = !edge_select_bool[loop->e];
+ }
+ }
+ }
+ }
+ }
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+
+/** \name Internal Cache Generation
+ * \{ */
+
+static bool mesh_render_data_pnors_pcenter_select_get(
+ MeshRenderData *rdata, const int poly,
+ float r_pnors[3], float r_center[3], bool *r_selected)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ if (rdata->edit_bmesh) {
+ const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, poly);
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+ BM_face_calc_center_mean(efa, r_center);
+ copy_v3_v3(r_pnors, efa->no);
+ *r_selected = (BM_elem_flag_test(efa, BM_ELEM_SELECT) != 0) ? true : false;
+ }
+ else {
+ MVert *mvert = rdata->mvert;
+ const MPoly *mpoly = rdata->mpoly + poly;
+ const MLoop *mloop = rdata->mloop + mpoly->loopstart;
+
+ BKE_mesh_calc_poly_center(mpoly, mloop, mvert, r_center);
+ BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, r_pnors);
+
+ *r_selected = false; /* No selection if not in edit mode */
+ }
+
+ return true;
+}
+
+static bool mesh_render_data_edge_vcos_manifold_pnors(
+ MeshRenderData *rdata, const int edge_index,
+ float **r_vco1, float **r_vco2, float **r_pnor1, float **r_pnor2, bool *r_is_manifold)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMEdge *eed = BM_edge_at_index(bm, edge_index);
+ if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+ *r_vco1 = eed->v1->co;
+ *r_vco2 = eed->v2->co;
+ if (BM_edge_is_manifold(eed)) {
+ *r_pnor1 = eed->l->f->no;
+ *r_pnor2 = eed->l->radial_next->f->no;
+ *r_is_manifold = true;
+ }
+ else {
+ *r_is_manifold = false;
+ }
+ }
+ else {
+ MVert *mvert = rdata->mvert;
+ MEdge *medge = rdata->medge;
+ EdgeAdjacentPolys *eap = rdata->edges_adjacent_polys;
+ float (*pnors)[3] = rdata->poly_normals;
+
+ if (!eap) {
+ const MLoop *mloop = rdata->mloop;
+ const MPoly *mpoly = rdata->mpoly;
+ const int poly_len = rdata->poly_len;
+ const bool do_pnors = (pnors == NULL);
+
+ eap = rdata->edges_adjacent_polys = MEM_callocN(sizeof(*eap) * rdata->edge_len, __func__);
+ if (do_pnors) {
+ pnors = rdata->poly_normals = MEM_mallocN(sizeof(*pnors) * poly_len, __func__);
+ }
+
+ for (int i = 0; i < poly_len; i++, mpoly++) {
+ if (do_pnors) {
+ BKE_mesh_calc_poly_normal(mpoly, mloop + mpoly->loopstart, mvert, pnors[i]);
+ }
+
+ const int loopend = mpoly->loopstart + mpoly->totloop;
+ for (int j = mpoly->loopstart; j < loopend; j++) {
+ const int edge_idx = mloop[j].e;
+ if (eap[edge_idx].count < 2) {
+ eap[edge_idx].face_index[eap[edge_idx].count] = i;
+ }
+ eap[edge_idx].count++;
+ }
+ }
+ }
+ BLI_assert(eap && pnors);
+
+ *r_vco1 = mvert[medge[edge_index].v1].co;
+ *r_vco2 = mvert[medge[edge_index].v2].co;
+ if (eap[edge_index].count == 2) {
+ *r_pnor1 = pnors[eap[edge_index].face_index[0]];
+ *r_pnor2 = pnors[eap[edge_index].face_index[1]];
+ *r_is_manifold = true;
+ }
+ else {
+ *r_is_manifold = false;
+ }
+ }
+
+ return true;
+}
+
+
+/* First 2 bytes are bit flags
+ * 3rd is for sharp edges
+ * 4rd is for creased edges */
+enum {
+ VFLAG_VERTEX_ACTIVE = 1 << 0,
+ VFLAG_VERTEX_SELECTED = 1 << 1,
+ VFLAG_FACE_ACTIVE = 1 << 2,
+ VFLAG_FACE_SELECTED = 1 << 3,
+};
+
+enum {
+ VFLAG_EDGE_EXISTS = 1 << 0,
+ VFLAG_EDGE_ACTIVE = 1 << 1,
+ VFLAG_EDGE_SELECTED = 1 << 2,
+ VFLAG_EDGE_SEAM = 1 << 3,
+ VFLAG_EDGE_SHARP = 1 << 4,
+ /* Beware to not go over 1 << 7
+ * (see gpu_shader_edit_mesh_overlay_geom.glsl) */
+};
+
+static unsigned char mesh_render_data_looptri_flag(MeshRenderData *rdata, const BMFace *efa)
+{
+ unsigned char fflag = 0;
+
+ if (efa == rdata->efa_act)
+ fflag |= VFLAG_FACE_ACTIVE;
+
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ fflag |= VFLAG_FACE_SELECTED;
+
+ return fflag;
+}
+
+static void mesh_render_data_edge_flag(
+ const MeshRenderData *rdata, const BMEdge *eed,
+ EdgeDrawAttr *eattr)
+{
+ eattr->e_flag |= VFLAG_EDGE_EXISTS;
+
+ if (eed == rdata->eed_act)
+ eattr->e_flag |= VFLAG_EDGE_ACTIVE;
+
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT))
+ eattr->e_flag |= VFLAG_EDGE_SELECTED;
+
+ if (BM_elem_flag_test(eed, BM_ELEM_SEAM))
+ eattr->e_flag |= VFLAG_EDGE_SEAM;
+
+ if (!BM_elem_flag_test(eed, BM_ELEM_SMOOTH))
+ eattr->e_flag |= VFLAG_EDGE_SHARP;
+
+ /* Use a byte for value range */
+ if (rdata->cd.offset.crease != -1) {
+ float crease = BM_ELEM_CD_GET_FLOAT(eed, rdata->cd.offset.crease);
+ if (crease > 0) {
+ eattr->crease = (char)(crease * 255.0f);
+ }
+ }
+
+ /* Use a byte for value range */
+ if (rdata->cd.offset.bweight != -1) {
+ float bweight = BM_ELEM_CD_GET_FLOAT(eed, rdata->cd.offset.bweight);
+ if (bweight > 0) {
+ eattr->bweight = (char)(bweight * 255.0f);
+ }
+ }
+}
+
+static unsigned char mesh_render_data_vertex_flag(MeshRenderData *rdata, const BMVert *eve)
+{
+
+ unsigned char vflag = 0;
+
+ /* Current vertex */
+ if (eve == rdata->eve_act)
+ vflag |= VFLAG_VERTEX_ACTIVE;
+
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
+ vflag |= VFLAG_VERTEX_SELECTED;
+
+ return vflag;
+}
+
+static void add_overlay_tri(
+ MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data,
+ const unsigned int pos_id, const unsigned int vnor_id, const unsigned int lnor_id, const unsigned int data_id,
+ const BMLoop **bm_looptri, const int base_vert_idx)
+{
+ unsigned char fflag;
+ unsigned char vflag;
+
+ if (vbo_pos) {
+ for (uint i = 0; i < 3; i++) {
+ const float *pos = bm_looptri[i]->v->co;
+ GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
+ }
+ }
+
+ if (vbo_nor) {
+ /* TODO real loop normal */
+ Gwn_PackedNormal lnor = GWN_normal_convert_i10_v3(bm_looptri[0]->f->no);
+ for (uint i = 0; i < 3; i++) {
+ Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3(bm_looptri[i]->v->no);
+ GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
+ GWN_vertbuf_attr_set(vbo_nor, lnor_id, base_vert_idx + i, &lnor);
+ }
+ }
+
+ if (vbo_data) {
+ fflag = mesh_render_data_looptri_flag(rdata, bm_looptri[0]->f);
+ uint i_prev = 1, i = 2;
+ for (uint i_next = 0; i_next < 3; i_next++) {
+ vflag = mesh_render_data_vertex_flag(rdata, bm_looptri[i]->v);
+ EdgeDrawAttr eattr = {0};
+ if (bm_looptri[i_next] == bm_looptri[i_prev]->prev) {
+ mesh_render_data_edge_flag(rdata, bm_looptri[i_next]->e, &eattr);
+ }
+ eattr.v_flag = fflag | vflag;
+ GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr);
+
+ i_prev = i;
+ i = i_next;
+ }
+ }
+}
+
+static void add_overlay_loose_edge(
+ MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data,
+ const unsigned int pos_id, const unsigned int vnor_id, const unsigned int data_id,
+ const BMEdge *eed, const int base_vert_idx)
+{
+ if (vbo_pos) {
+ for (int i = 0; i < 2; ++i) {
+ const float *pos = (&eed->v1)[i]->co;
+ GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos);
+ }
+ }
+
+ if (vbo_nor) {
+ for (int i = 0; i < 2; ++i) {
+ Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3((&eed->v1)[i]->no);
+ GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
+ }
+ }
+
+ if (vbo_data) {
+ EdgeDrawAttr eattr = {0};
+ mesh_render_data_edge_flag(rdata, eed, &eattr);
+ for (int i = 0; i < 2; ++i) {
+ eattr.v_flag = mesh_render_data_vertex_flag(rdata, (&eed->v1)[i]);
+ GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr);
+ }
+ }
+}
+
+static void add_overlay_loose_vert(
+ MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data,
+ const unsigned int pos_id, const unsigned int vnor_id, const unsigned int data_id,
+ const BMVert *eve, const int base_vert_idx)
+{
+ if (vbo_pos) {
+ const float *pos = eve->co;
+ GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos);
+ }
+
+ if (vbo_nor) {
+ Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3(eve->no);
+ GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx, &vnor);
+ }
+
+ if (vbo_data) {
+ unsigned char vflag[4] = {0, 0, 0, 0};
+ vflag[0] = mesh_render_data_vertex_flag(rdata, eve);
+ GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx, vflag);
+ }
+}
+
+/** \} */
+
+
+/* ---------------------------------------------------------------------- */
+
+/** \name Mesh Gwn_Batch Cache
+ * \{ */
+
+typedef struct MeshBatchCache {
+ Gwn_VertBuf *pos_in_order;
+ Gwn_VertBuf *nor_in_order;
+ Gwn_IndexBuf *edges_in_order;
+ Gwn_IndexBuf *triangles_in_order;
+
+ Gwn_Batch *all_verts;
+ Gwn_Batch *all_edges;
+ Gwn_Batch *all_triangles;
+
+ Gwn_VertBuf *pos_with_normals;
+ Gwn_VertBuf *tri_aligned_uv; /* Active UV layer (mloopuv) */
+
+ /**
+ * Other uses are all positions or loose elements.
+ * This stores all visible elements, needed for selection.
+ */
+ Gwn_VertBuf *ed_fcenter_pos_with_nor_and_sel;
+ Gwn_VertBuf *ed_edge_pos;
+ Gwn_VertBuf *ed_vert_pos;
+
+ Gwn_Batch *triangles_with_normals;
+
+ /* Skip hidden (depending on paint select mode) */
+ Gwn_Batch *triangles_with_weights;
+ Gwn_Batch *triangles_with_vert_colors;
+ /* Always skip hidden */
+ Gwn_Batch *triangles_with_select_mask;
+ Gwn_Batch *triangles_with_select_id;
+ uint triangles_with_select_id_offset;
+
+ Gwn_Batch *facedot_with_select_id; /* shares vbo with 'overlay_facedots' */
+ Gwn_Batch *edges_with_select_id;
+ Gwn_Batch *verts_with_select_id;
+
+ uint facedot_with_select_id_offset;
+ uint edges_with_select_id_offset;
+ uint verts_with_select_id_offset;
+
+ Gwn_Batch *points_with_normals;
+ Gwn_Batch *fancy_edges; /* owns its vertex buffer (not shared) */
+
+ /* Maybe have shaded_triangles_data split into pos_nor and uv_tangent
+ * to minimise data transfer for skinned mesh. */
+ Gwn_VertFormat shaded_triangles_format;
+ Gwn_VertBuf *shaded_triangles_data;
+ Gwn_IndexBuf **shaded_triangles_in_order;
+ Gwn_Batch **shaded_triangles;
+
+ /* Texture Paint.*/
+ /* per-texture batch */
+ Gwn_Batch **texpaint_triangles;
+ Gwn_Batch *texpaint_triangles_single;
+
+ /* Edit Cage Mesh buffers */
+ Gwn_VertBuf *ed_tri_pos;
+ Gwn_VertBuf *ed_tri_nor; /* LoopNor, VertNor */
+ Gwn_VertBuf *ed_tri_data;
+
+ Gwn_VertBuf *ed_ledge_pos;
+ Gwn_VertBuf *ed_ledge_nor; /* VertNor */
+ Gwn_VertBuf *ed_ledge_data;
+
+ Gwn_VertBuf *ed_lvert_pos;
+ Gwn_VertBuf *ed_lvert_nor; /* VertNor */
+ Gwn_VertBuf *ed_lvert_data;
+
+ Gwn_Batch *overlay_triangles;
+ Gwn_Batch *overlay_triangles_nor; /* GWN_PRIM_POINTS */
+ Gwn_Batch *overlay_loose_edges;
+ Gwn_Batch *overlay_loose_edges_nor; /* GWN_PRIM_POINTS */
+ Gwn_Batch *overlay_loose_verts;
+ Gwn_Batch *overlay_facedots;
+
+ Gwn_Batch *overlay_weight_faces;
+ Gwn_Batch *overlay_weight_verts;
+ Gwn_Batch *overlay_paint_edges;
+
+ /* settings to determine if cache is invalid */
+ bool is_maybe_dirty;
+ bool is_dirty; /* Instantly invalidates cache, skipping mesh check */
+ int edge_len;
+ int tri_len;
+ int poly_len;
+ int vert_len;
+ int mat_len;
+ bool is_editmode;
+
+ /* XXX, only keep for as long as sculpt mode uses shaded drawing. */
+ bool is_sculpt_points_tag;
+} MeshBatchCache;
+
+/* Gwn_Batch cache management. */
+
+static bool mesh_batch_cache_valid(Mesh *me)
+{
+ MeshBatchCache *cache = me->batch_cache;
+
+ if (cache == NULL) {
+ return false;
+ }
+
+ /* XXX find another place for this */
+ if (cache->mat_len != mesh_render_mat_len_get(me)) {
+ cache->is_maybe_dirty = true;
+ }
+
+ if (cache->is_editmode != (me->edit_btmesh != NULL)) {
+ return false;
+ }
+
+ if (cache->is_dirty) {
+ return false;
+ }
+
+ if (cache->is_maybe_dirty == false) {
+ return true;
+ }
+ else {
+ if (cache->is_editmode) {
+ return false;
+ }
+ else if ((cache->vert_len != mesh_render_verts_len_get(me)) ||
+ (cache->edge_len != mesh_render_edges_len_get(me)) ||
+ (cache->tri_len != mesh_render_looptri_len_get(me)) ||
+ (cache->poly_len != mesh_render_polys_len_get(me)) ||
+ (cache->mat_len != mesh_render_mat_len_get(me)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void mesh_batch_cache_init(Mesh *me)
+{
+ MeshBatchCache *cache = me->batch_cache;
+
+ if (!cache) {
+ cache = me->batch_cache = MEM_callocN(sizeof(*cache), __func__);
+ }
+ else {
+ memset(cache, 0, sizeof(*cache));
+ }
+
+ cache->is_editmode = me->edit_btmesh != NULL;
+
+ if (cache->is_editmode == false) {
+ cache->edge_len = mesh_render_edges_len_get(me);
+ cache->tri_len = mesh_render_looptri_len_get(me);
+ cache->poly_len = mesh_render_polys_len_get(me);
+ cache->vert_len = mesh_render_verts_len_get(me);
+ }
+
+ cache->mat_len = mesh_render_mat_len_get(me);
+
+ cache->is_maybe_dirty = false;
+ cache->is_dirty = false;
+}
+
+static MeshBatchCache *mesh_batch_cache_get(Mesh *me)
+{
+ if (!mesh_batch_cache_valid(me)) {
+ mesh_batch_cache_clear(me);
+ mesh_batch_cache_init(me);
+ }
+ return me->batch_cache;
+}
+
+void DRW_mesh_batch_cache_dirty(Mesh *me, int mode)
+{
+ MeshBatchCache *cache = me->batch_cache;
+ if (cache == NULL) {
+ return;
+ }
+ switch (mode) {
+ case BKE_MESH_BATCH_DIRTY_MAYBE_ALL:
+ cache->is_maybe_dirty = true;
+ break;
+ case BKE_MESH_BATCH_DIRTY_SELECT:
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_data);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel); /* Contains select flag */
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos);
+
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_facedots);
+ /* Edit mode selection. */
+ GWN_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
+ GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
+ GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
+ break;
+ case BKE_MESH_BATCH_DIRTY_ALL:
+ cache->is_dirty = true;
+ break;
+ case BKE_MESH_BATCH_DIRTY_SHADING:
+ /* TODO: This should only update UV and tangent data,
+ * and not free the entire cache. */
+ cache->is_dirty = true;
+ break;
+ case BKE_MESH_BATCH_DIRTY_SCULPT_COORDS:
+ cache->is_sculpt_points_tag = true;
+ break;
+ default:
+ BLI_assert(0);
+ }
+}
+
+static void mesh_batch_cache_clear(Mesh *me)
+{
+ MeshBatchCache *cache = me->batch_cache;
+ if (!cache) {
+ return;
+ }
+
+ GWN_BATCH_DISCARD_SAFE(cache->all_verts);
+ GWN_BATCH_DISCARD_SAFE(cache->all_edges);
+ GWN_BATCH_DISCARD_SAFE(cache->all_triangles);
+
+ GWN_VERTBUF_DISCARD_SAFE(cache->pos_in_order);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->edges_in_order);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->triangles_in_order);
+
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_pos);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_nor);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_data);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_pos);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_nor);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_pos);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_nor);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles_nor);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges_nor);
+
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_weight_faces);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_weight_verts);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_paint_edges);
+ GWN_BATCH_DISCARD_SAFE(cache->overlay_facedots);
+
+ GWN_BATCH_DISCARD_SAFE(cache->triangles_with_normals);
+ GWN_BATCH_DISCARD_SAFE(cache->points_with_normals);
+ GWN_VERTBUF_DISCARD_SAFE(cache->pos_with_normals);
+ GWN_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
+ GWN_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors);
+ GWN_VERTBUF_DISCARD_SAFE(cache->tri_aligned_uv);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos);
+ GWN_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos);
+ GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask);
+ GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
+ GWN_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
+ GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
+ GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
+
+ GWN_BATCH_DISCARD_SAFE(cache->fancy_edges);
+
+ GWN_VERTBUF_DISCARD_SAFE(cache->shaded_triangles_data);
+ if (cache->shaded_triangles_in_order) {
+ for (int i = 0; i < cache->mat_len; ++i) {
+ GWN_INDEXBUF_DISCARD_SAFE(cache->shaded_triangles_in_order[i]);
+ }
+ }
+ if (cache->shaded_triangles) {
+ for (int i = 0; i < cache->mat_len; ++i) {
+ GWN_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
+ }
+ }
+
+ MEM_SAFE_FREE(cache->shaded_triangles_in_order);
+ MEM_SAFE_FREE(cache->shaded_triangles);
+
+ if (cache->texpaint_triangles) {
+ for (int i = 0; i < cache->mat_len; ++i) {
+ GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
+ }
+ }
+ MEM_SAFE_FREE(cache->texpaint_triangles);
+
+ GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
+
+}
+
+void DRW_mesh_batch_cache_free(Mesh *me)
+{
+ mesh_batch_cache_clear(me);
+ MEM_SAFE_FREE(me->batch_cache);
+}
+
+/* Gwn_Batch cache usage. */
+
+static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+#define USE_COMP_MESH_DATA
+
+ if (cache->shaded_triangles_data == NULL) {
+ const uint uv_len = rdata->cd.layers.uv_len;
+ const uint tangent_len = rdata->cd.layers.tangent_len;
+ const uint vcol_len = rdata->cd.layers.vcol_len;
+ const uint layers_combined_len = uv_len + vcol_len + tangent_len;
+
+ if (layers_combined_len == 0) {
+ return NULL;
+ }
+
+ Gwn_VertFormat *format = &cache->shaded_triangles_format;
+
+ GWN_vertformat_clear(format);
+
+ /* initialize vertex format */
+ uint *layers_combined_id = BLI_array_alloca(layers_combined_id, layers_combined_len);
+ uint *uv_id = layers_combined_id;
+ uint *tangent_id = uv_id + uv_len;
+ uint *vcol_id = tangent_id + tangent_len;
+
+ /* Not needed, just for sanity. */
+ if (uv_len == 0) { uv_id = NULL; }
+ if (tangent_len == 0) { tangent_id = NULL; }
+ if (vcol_len == 0) { vcol_id = NULL; }
+
+ for (uint i = 0; i < uv_len; i++) {
+ /* UV */
+ const char *attrib_name = mesh_render_data_uv_layer_uuid_get(rdata, i);
+#if defined(USE_COMP_MESH_DATA) && 0 /* these are clamped. Maybe use them as an option in the future */
+ uv_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_I16, 2, GWN_FETCH_INT_TO_FLOAT_UNIT);
+#else
+ uv_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+#endif
+
+ /* Auto Name */
+ attrib_name = mesh_render_data_uv_auto_layer_uuid_get(rdata, i);
+ GWN_vertformat_alias_add(format, attrib_name);
+
+ if (i == rdata->cd.layers.uv_active) {
+ GWN_vertformat_alias_add(format, "u");
+ }
+ }
+
+ for (uint i = 0; i < tangent_len; i++) {
+ const char *attrib_name = mesh_render_data_tangent_layer_uuid_get(rdata, i);
+ /* WATCH IT : only specifying 3 component instead of 4 (4th is sign).
+ * That may cause some problem but I could not make it to fail (fclem) */
+#ifdef USE_COMP_MESH_DATA
+ /* Tangents need more precision than 10_10_10 */
+ tangent_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+#else
+ tangent_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+#endif
+
+ if (i == rdata->cd.layers.tangent_active) {
+ GWN_vertformat_alias_add(format, "t");
+ }
+ }
+
+ for (uint i = 0; i < vcol_len; i++) {
+ const char *attrib_name = mesh_render_data_vcol_layer_uuid_get(rdata, i);
+ vcol_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ /* Auto layer */
+ if (rdata->cd.layers.auto_vcol[i]) {
+ attrib_name = mesh_render_data_vcol_auto_layer_uuid_get(rdata, i);
+ GWN_vertformat_alias_add(format, attrib_name);
+ }
+
+ if (i == rdata->cd.layers.vcol_active) {
+ GWN_vertformat_alias_add(format, "c");
+ }
+ }
+
+ const uint tri_len = mesh_render_data_looptri_len_get(rdata);
+
+ Gwn_VertBuf *vbo = cache->shaded_triangles_data = GWN_vertbuf_create_with_format(format);
+
+ const int vbo_len_capacity = tri_len * 3;
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ Gwn_VertBufRaw *layers_combined_step = BLI_array_alloca(layers_combined_step, layers_combined_len);
+
+ Gwn_VertBufRaw *uv_step = layers_combined_step;
+ Gwn_VertBufRaw *tangent_step = uv_step + uv_len;
+ Gwn_VertBufRaw *vcol_step = tangent_step + tangent_len;
+
+ /* Not needed, just for sanity. */
+ if (uv_len == 0) { uv_step = NULL; }
+ if (tangent_len == 0) { tangent_step = NULL; }
+ if (vcol_len == 0) { vcol_step = NULL; }
+
+ for (uint i = 0; i < uv_len; i++) {
+ GWN_vertbuf_attr_get_raw_data(vbo, uv_id[i], &uv_step[i]);
+ }
+ for (uint i = 0; i < tangent_len; i++) {
+ GWN_vertbuf_attr_get_raw_data(vbo, tangent_id[i], &tangent_step[i]);
+ }
+ for (uint i = 0; i < vcol_len; i++) {
+ GWN_vertbuf_attr_get_raw_data(vbo, vcol_id[i], &vcol_step[i]);
+ }
+
+ /* TODO deduplicate all verts and make use of Gwn_IndexBuf in
+ * mesh_batch_cache_get_triangles_in_order_split_by_material. */
+ if (rdata->edit_bmesh) {
+ for (uint i = 0; i < tri_len; i++) {
+ const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
+ if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
+ continue;
+ }
+ /* UVs */
+ for (uint j = 0; j < uv_len; j++) {
+ const uint layer_offset = rdata->cd.offset.uv[j];
+ for (uint t = 0; t < 3; t++) {
+ const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(bm_looptri[t], layer_offset))->uv;
+ copy_v2_v2(GWN_vertbuf_raw_step(&uv_step[j]), elem);
+ }
+ }
+ /* TANGENTs */
+ for (uint j = 0; j < tangent_len; j++) {
+ float (*layer_data)[4] = rdata->cd.layers.tangent[j];
+ for (uint t = 0; t < 3; t++) {
+ const float *elem = layer_data[BM_elem_index_get(bm_looptri[t])];
+ normal_float_to_short_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem);
+ }
+ }
+ /* VCOLs */
+ for (uint j = 0; j < vcol_len; j++) {
+ const uint layer_offset = rdata->cd.offset.vcol[j];
+ for (uint t = 0; t < 3; t++) {
+ const uchar *elem = &((MLoopCol *)BM_ELEM_CD_GET_VOID_P(bm_looptri[t], layer_offset))->r;
+ copy_v3_v3_uchar(GWN_vertbuf_raw_step(&vcol_step[j]), elem);
+ }
+ }
+ }
+ }
+ else {
+ for (uint i = 0; i < tri_len; i++) {
+ const MLoopTri *mlt = &rdata->mlooptri[i];
+
+ /* UVs */
+ for (uint j = 0; j < uv_len; j++) {
+ const MLoopUV *layer_data = rdata->cd.layers.uv[j];
+ for (uint t = 0; t < 3; t++) {
+ const float *elem = layer_data[mlt->tri[t]].uv;
+ copy_v2_v2(GWN_vertbuf_raw_step(&uv_step[j]), elem);
+ }
+ }
+ /* TANGENTs */
+ for (uint j = 0; j < tangent_len; j++) {
+ float (*layer_data)[4] = rdata->cd.layers.tangent[j];
+ for (uint t = 0; t < 3; t++) {
+ const float *elem = layer_data[mlt->tri[t]];
+#ifdef USE_COMP_MESH_DATA
+ normal_float_to_short_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem);
+#else
+ copy_v3_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem);
+#endif
+ }
+ }
+ /* VCOLs */
+ for (uint j = 0; j < vcol_len; j++) {
+ const MLoopCol *layer_data = rdata->cd.layers.vcol[j];
+ for (uint t = 0; t < 3; t++) {
+ const uchar *elem = &layer_data[mlt->tri[t]].r;
+ copy_v3_v3_uchar(GWN_vertbuf_raw_step(&vcol_step[j]), elem);
+ }
+ }
+ }
+ }
+
+ vbo_len_used = GWN_vertbuf_raw_used(&layers_combined_step[0]);
+
+#ifndef NDEBUG
+ /* Check all layers are write aligned. */
+ if (layers_combined_len > 1) {
+ for (uint i = 1; i < layers_combined_len; i++) {
+ BLI_assert(vbo_len_used == GWN_vertbuf_raw_used(&layers_combined_step[i]));
+ }
+ }
+#endif
+
+ if (vbo_len_capacity != vbo_len_used) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ }
+
+#undef USE_COMP_MESH_DATA
+
+ return cache->shaded_triangles_data;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_tri_uv_active(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPUV));
+ BLI_assert(rdata->edit_bmesh == NULL);
+
+ if (cache->tri_aligned_uv == NULL) {
+ unsigned int vidx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint uv; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.uv = GWN_vertformat_attr_add(&format, "uv", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+
+ Gwn_VertBuf *vbo = cache->tri_aligned_uv = GWN_vertbuf_create_with_format(&format);
+
+ const int vbo_len_capacity = tri_len * 3;
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ const MLoopUV *mloopuv = rdata->mloopuv;
+
+ for (int i = 0; i < tri_len; i++) {
+ const MLoopTri *mlt = &rdata->mlooptri[i];
+ GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[0]].uv);
+ GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[1]].uv);
+ GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[2]].uv);
+ }
+ vbo_len_used = vidx;
+
+ BLI_assert(vbo_len_capacity == vbo_len_used);
+ UNUSED_VARS_NDEBUG(vbo_len_used);
+ }
+
+ return cache->tri_aligned_uv;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
+ MeshRenderData *rdata, const bool use_hide,
+ Gwn_VertBuf **r_vbo)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ if (*r_vbo == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, nor; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+
+ Gwn_VertBuf *vbo = *r_vbo = GWN_vertbuf_create_with_format(&format);
+
+ const int vbo_len_capacity = tri_len * 3;
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ Gwn_VertBufRaw pos_step, nor_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+ GWN_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step);
+
+ float (*lnors)[3] = rdata->loop_normals;
+
+ if (rdata->edit_bmesh) {
+ Gwn_PackedNormal *pnors_pack, *vnors_pack;
+
+ if (lnors == NULL) {
+ mesh_render_data_ensure_poly_normals_pack(rdata);
+ mesh_render_data_ensure_vert_normals_pack(rdata);
+
+ pnors_pack = rdata->poly_normals_pack;
+ vnors_pack = rdata->vert_normals_pack;
+ }
+
+ for (int i = 0; i < tri_len; i++) {
+ const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
+ const BMFace *bm_face = bm_looptri[0]->f;
+
+ /* use_hide always for edit-mode */
+ if (BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) {
+ continue;
+ }
+
+ if (lnors) {
+ for (uint t = 0; t < 3; t++) {
+ const float *nor = lnors[BM_elem_index_get(bm_looptri[t])];
+ *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_v3(nor);
+ }
+ }
+ else if (BM_elem_flag_test(bm_face, BM_ELEM_SMOOTH)) {
+ for (uint t = 0; t < 3; t++) {
+ *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = vnors_pack[BM_elem_index_get(bm_looptri[t]->v)];
+ }
+ }
+ else {
+ const Gwn_PackedNormal *snor_pack = &pnors_pack[BM_elem_index_get(bm_face)];
+ for (uint t = 0; t < 3; t++) {
+ *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *snor_pack;
+ }
+ }
+
+ for (uint t = 0; t < 3; t++) {
+ copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), bm_looptri[t]->v->co);
+ }
+ }
+ }
+ else {
+ if (lnors == NULL) {
+ /* Use normals from vertex. */
+ mesh_render_data_ensure_poly_normals_pack(rdata);
+ }
+
+ for (int i = 0; i < tri_len; i++) {
+ const MLoopTri *mlt = &rdata->mlooptri[i];
+ const MPoly *mp = &rdata->mpoly[mlt->poly];
+
+ if (use_hide && (mp->flag & ME_HIDE)) {
+ continue;
+ }
+
+ const uint vtri[3] = {
+ rdata->mloop[mlt->tri[0]].v,
+ rdata->mloop[mlt->tri[1]].v,
+ rdata->mloop[mlt->tri[2]].v,
+ };
+
+ if (lnors) {
+ for (uint t = 0; t < 3; t++) {
+ const float *nor = lnors[mlt->tri[t]];
+ *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_v3(nor);
+ }
+ }
+ else if (mp->flag & ME_SMOOTH) {
+ for (uint t = 0; t < 3; t++) {
+ const MVert *mv = &rdata->mvert[vtri[t]];
+ *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_s3(mv->no);
+ }
+ }
+ else {
+ const Gwn_PackedNormal *pnors_pack = &rdata->poly_normals_pack[mlt->poly];
+ for (uint t = 0; t < 3; t++) {
+ *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *pnors_pack;
+ }
+ }
+
+ for (uint t = 0; t < 3; t++) {
+ const MVert *mv = &rdata->mvert[vtri[t]];
+ copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), mv->co);
+ }
+ }
+ }
+
+ vbo_len_used = GWN_vertbuf_raw_used(&pos_step);
+ BLI_assert(vbo_len_used == GWN_vertbuf_raw_used(&nor_step));
+
+ if (vbo_len_capacity != vbo_len_used) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ }
+ return *r_vbo;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ return mesh_batch_cache_get_tri_pos_and_normals_ex(
+ rdata, false,
+ &cache->pos_with_normals);
+}
+static Gwn_VertBuf *mesh_create_tri_pos_and_normals_visible_only(
+ MeshRenderData *rdata)
+{
+ Gwn_VertBuf *vbo_dummy = NULL;
+ return mesh_batch_cache_get_tri_pos_and_normals_ex(
+ rdata, true,
+ &vbo_dummy);
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_facedot_pos_with_normals_and_flag(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ if (cache->ed_fcenter_pos_with_nor_and_sel == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, data; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.data = GWN_vertformat_attr_add(&format, "norAndFlag", GWN_COMP_I10, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata);
+ int vidx = 0;
+
+ Gwn_VertBuf *vbo = cache->ed_fcenter_pos_with_nor_and_sel = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ for (int i = 0; i < vbo_len_capacity; ++i) {
+ float pcenter[3], pnor[3];
+ bool selected = false;
+
+ if (mesh_render_data_pnors_pcenter_select_get(rdata, i, pnor, pcenter, &selected)) {
+
+ Gwn_PackedNormal nor = { .x = 0, .y = 0, .z = -511 };
+ nor = GWN_normal_convert_i10_v3(pnor);
+ nor.w = selected ? 1 : 0;
+ GWN_vertbuf_attr_set(vbo, attr_id.data, vidx, &nor);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, pcenter);
+
+ vidx += 1;
+ }
+ }
+ const int vbo_len_used = vidx;
+ if (vbo_len_used != vbo_len_capacity) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ BLI_assert(vbo_len_capacity == vbo_len_used);
+ UNUSED_VARS_NDEBUG(vbo_len_used);
+ }
+
+ return cache->ed_fcenter_pos_with_nor_and_sel;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_edges_visible(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE));
+
+ if (cache->ed_edge_pos == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, data; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ const int vbo_len_capacity = mesh_render_data_edges_len_get(rdata) * 2;
+ int vidx = 0;
+
+ Gwn_VertBuf *vbo = cache->ed_edge_pos = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter;
+ BMEdge *eed;
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v1->co);
+ vidx += 1;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v2->co);
+ vidx += 1;
+ }
+ }
+ }
+ else {
+ /* not yet done! */
+ BLI_assert(0);
+ }
+ const int vbo_len_used = vidx;
+ if (vbo_len_used != vbo_len_capacity) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ UNUSED_VARS_NDEBUG(vbo_len_used);
+ }
+
+ return cache->ed_edge_pos;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_verts_visible(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->ed_vert_pos == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, data; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata);
+ uint vidx = 0;
+
+ Gwn_VertBuf *vbo = cache->ed_vert_pos = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter;
+ BMVert *eve;
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eve->co);
+ vidx += 1;
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < vbo_len_capacity; i++) {
+ const MVert *mv = &rdata->mvert[i];
+ if (!(mv->flag & ME_HIDE)) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, mv->co);
+ vidx += 1;
+ }
+ }
+ }
+ const uint vbo_len_used = vidx;
+ if (vbo_len_used != vbo_len_capacity) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+
+ UNUSED_VARS_NDEBUG(vbo_len_used);
+ }
+
+ return cache->ed_vert_pos;
+}
+
+static Gwn_VertBuf *mesh_create_facedot_select_id(
+ MeshRenderData *rdata, uint select_id_offset)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ Gwn_VertBuf *vbo;
+ {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, col; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ }
+
+ const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata);
+ int vidx = 0;
+
+ vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ uint select_index = select_id_offset;
+
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter;
+ BMEdge *efa;
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ int select_id;
+ GPU_select_index_get(select_index, &select_id);
+ GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
+ vidx += 1;
+ }
+ select_index += 1;
+ }
+ }
+ else {
+ /* not yet done! */
+ BLI_assert(0);
+ }
+ const int vbo_len_used = vidx;
+ if (vbo_len_used != vbo_len_capacity) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ }
+
+ return vbo;
+}
+
+static Gwn_VertBuf *mesh_create_edges_select_id(
+ MeshRenderData *rdata, uint select_id_offset)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE));
+
+ Gwn_VertBuf *vbo;
+ {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, col; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ }
+
+ const int vbo_len_capacity = mesh_render_data_edges_len_get(rdata) * 2;
+ int vidx = 0;
+
+ vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ uint select_index = select_id_offset;
+
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter;
+ BMEdge *eed;
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ int select_id;
+ GPU_select_index_get(select_index, &select_id);
+ GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
+ vidx += 1;
+ GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
+ vidx += 1;
+ }
+ select_index += 1;
+ }
+ }
+ else {
+ /* not yet done! */
+ BLI_assert(0);
+ }
+ const int vbo_len_used = vidx;
+ if (vbo_len_used != vbo_len_capacity) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ }
+
+ return vbo;
+}
+
+static Gwn_VertBuf *mesh_create_verts_select_id(
+ MeshRenderData *rdata, uint select_id_offset)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ Gwn_VertBuf *vbo;
+ {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, col; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ }
+
+ const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata);
+ int vidx = 0;
+
+ vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ uint select_index = select_id_offset;
+
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter;
+ BMVert *eve;
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ int select_id;
+ GPU_select_index_get(select_index, &select_id);
+ GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
+ vidx += 1;
+ }
+ select_index += 1;
+ }
+ }
+ else {
+ for (int i = 0; i < vbo_len_capacity; i++) {
+ const MVert *mv = &rdata->mvert[i];
+ if (!(mv->flag & ME_HIDE)) {
+ int select_id;
+ GPU_select_index_get(select_index, &select_id);
+ GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id);
+ vidx += 1;
+ }
+ select_index += 1;
+ }
+ }
+ const int vbo_len_used = vidx;
+ if (vbo_len_used != vbo_len_capacity) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ }
+
+ return vbo;
+}
+
+static Gwn_VertBuf *mesh_create_tri_weights(
+ MeshRenderData *rdata, bool use_hide, int defgroup)
+{
+ BLI_assert(
+ rdata->types &
+ (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_DVERT));
+
+ Gwn_VertBuf *vbo;
+ {
+ unsigned int cidx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint col; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ vbo = GWN_vertbuf_create_with_format(&format);
+
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+ const int vbo_len_capacity = tri_len * 3;
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ mesh_render_data_ensure_vert_weight_color(rdata, defgroup);
+ const float (*vert_weight_color)[3] = rdata->vert_weight_color;
+
+ if (rdata->edit_bmesh) {
+ for (int i = 0; i < tri_len; i++) {
+ const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
+ /* Assume 'use_hide' */
+ if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
+ for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
+ const int v_index = BM_elem_index_get(ltri[tri_corner]->v);
+ GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_weight_color[v_index]);
+ }
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < tri_len; i++) {
+ const MLoopTri *mlt = &rdata->mlooptri[i];
+ if (!(use_hide && (rdata->mpoly[mlt->poly].flag & ME_HIDE))) {
+ for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
+ const uint v_index = rdata->mloop[mlt->tri[tri_corner]].v;
+ GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_weight_color[v_index]);
+ }
+ }
+ }
+ }
+ vbo_len_used = cidx;
+
+ if (vbo_len_capacity != vbo_len_used) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ }
+
+ return vbo;
+}
+
+static Gwn_VertBuf *mesh_create_tri_vert_colors(
+ MeshRenderData *rdata, bool use_hide)
+{
+ BLI_assert(
+ rdata->types &
+ (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPCOL));
+
+ Gwn_VertBuf *vbo;
+ {
+ unsigned int cidx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint col; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+
+ vbo = GWN_vertbuf_create_with_format(&format);
+
+ const uint vbo_len_capacity = tri_len * 3;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ mesh_render_data_ensure_vert_color(rdata);
+ const char (*vert_color)[3] = rdata->vert_color;
+
+ if (rdata->edit_bmesh) {
+ for (int i = 0; i < tri_len; i++) {
+ const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
+ /* Assume 'use_hide' */
+ if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
+ for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
+ const int l_index = BM_elem_index_get(ltri[tri_corner]);
+ GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]);
+ }
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < tri_len; i++) {
+ const MLoopTri *mlt = &rdata->mlooptri[i];
+ if (!(use_hide && (rdata->mpoly[mlt->poly].flag & ME_HIDE))) {
+ for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
+ const uint l_index = mlt->tri[tri_corner];
+ GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]);
+ }
+ }
+ }
+ }
+ const uint vbo_len_used = cidx;
+
+ if (vbo_len_capacity != vbo_len_used) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ }
+
+ return vbo;
+}
+
+static Gwn_VertBuf *mesh_create_tri_select_id(
+ MeshRenderData *rdata, bool use_hide, uint select_id_offset)
+{
+ BLI_assert(
+ rdata->types &
+ (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ Gwn_VertBuf *vbo;
+ {
+ unsigned int cidx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint col; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT);
+ }
+
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+
+ vbo = GWN_vertbuf_create_with_format(&format);
+
+ const int vbo_len_capacity = tri_len * 3;
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ if (rdata->edit_bmesh) {
+ for (int i = 0; i < tri_len; i++) {
+ const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
+ /* Assume 'use_hide' */
+ if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
+ const int poly_index = BM_elem_index_get(ltri[0]->f);
+ int select_id;
+ GPU_select_index_get(poly_index + select_id_offset, &select_id);
+ for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
+ GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id);
+ }
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < tri_len; i++) {
+ const MLoopTri *mlt = &rdata->mlooptri[i];
+ const int poly_index = mlt->poly;
+ if (!(use_hide && (rdata->mpoly[poly_index].flag & ME_HIDE))) {
+ int select_id;
+ GPU_select_index_get(poly_index + select_id_offset, &select_id);
+ for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
+ GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id);
+ }
+ }
+ }
+ }
+ vbo_len_used = cidx;
+
+ if (vbo_len_capacity != vbo_len_used) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ }
+ return vbo;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->pos_in_order == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, nor; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ Gwn_VertBuf *vbo = cache->pos_in_order = GWN_vertbuf_create_with_format(&format);
+ const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata);
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter;
+ BMVert *eve;
+ uint i;
+
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ static short no_short[3];
+ normal_float_to_short_v3(no_short, eve->no);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i, eve->co);
+ GWN_vertbuf_attr_set(vbo, attr_id.nor, i, no_short);
+ }
+ BLI_assert(i == vbo_len_capacity);
+ }
+ else {
+ for (int i = 0; i < vbo_len_capacity; ++i) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->mvert[i].co);
+ GWN_vertbuf_attr_set(vbo, attr_id.nor, i, rdata->mvert[i].no);
+ }
+ }
+ }
+
+ return cache->pos_in_order;
+}
+
+static Gwn_VertFormat *edit_mesh_overlay_pos_format(unsigned int *r_pos_id)
+{
+ static Gwn_VertFormat format_pos = { 0 };
+ static unsigned pos_id;
+ if (format_pos.attrib_ct == 0) {
+ pos_id = GWN_vertformat_attr_add(&format_pos, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+ *r_pos_id = pos_id;
+ return &format_pos;
+}
+
+static Gwn_VertFormat *edit_mesh_overlay_nor_format(unsigned int *r_vnor_id, unsigned int *r_lnor_id)
+{
+ static Gwn_VertFormat format_nor = { 0 };
+ static Gwn_VertFormat format_nor_loop = { 0 };
+ static unsigned vnor_id, vnor_loop_id, lnor_id;
+ if (format_nor.attrib_ct == 0) {
+ vnor_id = GWN_vertformat_attr_add(&format_nor, "vnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ vnor_loop_id = GWN_vertformat_attr_add(&format_nor_loop, "vnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ lnor_id = GWN_vertformat_attr_add(&format_nor_loop, "lnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ }
+ if (r_lnor_id) {
+ *r_vnor_id = vnor_loop_id;
+ *r_lnor_id = lnor_id;
+ return &format_nor_loop;
+ }
+ else {
+ *r_vnor_id = vnor_id;
+ return &format_nor;
+ }
+}
+
+static Gwn_VertFormat *edit_mesh_overlay_data_format(unsigned int *r_data_id)
+{
+ static Gwn_VertFormat format_flag = { 0 };
+ static unsigned data_id;
+ if (format_flag.attrib_ct == 0) {
+ data_id = GWN_vertformat_attr_add(&format_flag, "data", GWN_COMP_U8, 4, GWN_FETCH_INT);
+ }
+ *r_data_id = data_id;
+ return &format_flag;
+}
+
+static void mesh_batch_cache_create_overlay_tri_buffers(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
+
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+
+ const int vbo_len_capacity = tri_len * 3;
+ int vbo_len_used = 0;
+
+ /* Positions */
+ Gwn_VertBuf *vbo_pos = NULL;
+ static struct { uint pos, vnor, lnor, data; } attr_id;
+ if (cache->ed_tri_pos == NULL) {
+ vbo_pos = cache->ed_tri_pos =
+ GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
+ GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
+ }
+
+ /* Normals */
+ Gwn_VertBuf *vbo_nor = NULL;
+ if (cache->ed_tri_nor == NULL) {
+ vbo_nor = cache->ed_tri_nor =
+ GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, &attr_id.lnor));
+ GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
+ }
+
+ /* Data */
+ Gwn_VertBuf *vbo_data = NULL;
+ if (cache->ed_tri_data == NULL) {
+ vbo_data = cache->ed_tri_data =
+ GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
+ GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
+ }
+
+ for (int i = 0; i < tri_len; i++) {
+ const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
+ if (!BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
+ add_overlay_tri(
+ rdata, vbo_pos, vbo_nor, vbo_data,
+ attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data,
+ bm_looptri, vbo_len_used);
+
+ vbo_len_used += 3;
+ }
+ }
+
+ /* Finish */
+ if (vbo_len_used != vbo_len_capacity) {
+ if (vbo_pos != NULL) {
+ GWN_vertbuf_data_resize(vbo_pos, vbo_len_used);
+ }
+ if (vbo_nor != NULL) {
+ GWN_vertbuf_data_resize(vbo_nor, vbo_len_used);
+ }
+ if (vbo_data != NULL) {
+ GWN_vertbuf_data_resize(vbo_data, vbo_len_used);
+ }
+ }
+}
+
+static void mesh_batch_cache_create_overlay_ledge_buffers(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
+
+ const int ledge_len = mesh_render_data_loose_edges_len_get(rdata);
+
+ const int vbo_len_capacity = ledge_len * 2;
+ int vbo_len_used = 0;
+
+ /* Positions */
+ Gwn_VertBuf *vbo_pos = NULL;
+ static struct { uint pos, vnor, data; } attr_id;
+ if (cache->ed_ledge_pos == NULL) {
+ vbo_pos = cache->ed_ledge_pos =
+ GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
+ GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
+ }
+
+ /* Normals */
+ Gwn_VertBuf *vbo_nor = NULL;
+ if (cache->ed_ledge_nor == NULL) {
+ vbo_nor = cache->ed_ledge_nor =
+ GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL));
+ GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
+ }
+
+ /* Data */
+ Gwn_VertBuf *vbo_data = NULL;
+ if (cache->ed_ledge_data == NULL) {
+ vbo_data = cache->ed_ledge_data =
+ GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
+ GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
+ }
+
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ for (uint i = 0; i < ledge_len; i++) {
+ const BMEdge *eed = BM_edge_at_index(bm, rdata->loose_edges[i]);
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ add_overlay_loose_edge(
+ rdata, vbo_pos, vbo_nor, vbo_data,
+ attr_id.pos, attr_id.vnor, attr_id.data,
+ eed, vbo_len_used);
+ vbo_len_used += 2;
+ }
+ }
+ }
+
+ /* Finish */
+ if (vbo_len_used != vbo_len_capacity) {
+ if (vbo_pos != NULL) {
+ GWN_vertbuf_data_resize(vbo_pos, vbo_len_used);
+ }
+ if (vbo_nor != NULL) {
+ GWN_vertbuf_data_resize(vbo_nor, vbo_len_used);
+ }
+ if (vbo_data != NULL) {
+ GWN_vertbuf_data_resize(vbo_data, vbo_len_used);
+ }
+ }
+}
+
+static void mesh_batch_cache_create_overlay_lvert_buffers(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
+
+ BMesh *bm = rdata->edit_bmesh->bm;
+ const int lvert_len = mesh_render_data_loose_verts_len_get(rdata);
+
+ const int vbo_len_capacity = lvert_len;
+ int vbo_len_used = 0;
+
+ static struct { uint pos, vnor, data; } attr_id;
+
+ /* Positions */
+ Gwn_VertBuf *vbo_pos = NULL;
+ if (cache->ed_lvert_pos == NULL) {
+ vbo_pos = cache->ed_lvert_pos =
+ GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos));
+ GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity);
+ }
+
+ /* Normals */
+ Gwn_VertBuf *vbo_nor = NULL;
+ if (cache->ed_lvert_nor == NULL) {
+ vbo_nor = cache->ed_lvert_nor =
+ GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL));
+ GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity);
+ }
+
+ /* Data */
+ Gwn_VertBuf *vbo_data = NULL;
+ if (cache->ed_lvert_data == NULL) {
+ vbo_data = cache->ed_lvert_data =
+ GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data));
+ GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity);
+ }
+
+ for (uint i = 0; i < lvert_len; i++) {
+ BMVert *eve = BM_vert_at_index(bm, rdata->loose_verts[i]);
+ add_overlay_loose_vert(
+ rdata, vbo_pos, vbo_nor, vbo_data,
+ attr_id.pos, attr_id.vnor, attr_id.data,
+ eve, vbo_len_used);
+ vbo_len_used += 1;
+ }
+
+ /* Finish */
+ if (vbo_len_used != vbo_len_capacity) {
+ if (vbo_pos != NULL) {
+ GWN_vertbuf_data_resize(vbo_pos, vbo_len_used);
+ }
+ if (vbo_nor != NULL) {
+ GWN_vertbuf_data_resize(vbo_nor, vbo_len_used);
+ }
+ if (vbo_data != NULL) {
+ GWN_vertbuf_data_resize(vbo_data, vbo_len_used);
+ }
+ }
+}
+
+/* Position */
+static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_pos(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->ed_tri_pos == NULL) {
+ mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
+ }
+
+ return cache->ed_tri_pos;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_pos(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->ed_ledge_pos == NULL) {
+ mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
+ }
+
+ return cache->ed_ledge_pos;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_pos(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->ed_lvert_pos == NULL) {
+ mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
+ }
+
+ return cache->ed_lvert_pos;
+}
+
+/* Normal */
+static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_nor(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->ed_tri_nor == NULL) {
+ mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
+ }
+
+ return cache->ed_tri_nor;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_nor(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->ed_ledge_nor == NULL) {
+ mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
+ }
+
+ return cache->ed_ledge_nor;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_nor(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->ed_lvert_nor == NULL) {
+ mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
+ }
+
+ return cache->ed_lvert_nor;
+}
+
+/* Data */
+static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_data(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->ed_tri_data == NULL) {
+ mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
+ }
+
+ return cache->ed_tri_data;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_data(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->ed_ledge_data == NULL) {
+ mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
+ }
+
+ return cache->ed_ledge_data;
+}
+
+static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_data(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_VERT);
+
+ if (cache->ed_lvert_data == NULL) {
+ mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
+ }
+
+ return cache->ed_lvert_data;
+}
+
+static Gwn_IndexBuf *mesh_batch_cache_get_edges_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE));
+
+ if (cache->edges_in_order == NULL) {
+ const int vert_len = mesh_render_data_verts_len_get(rdata);
+ const int edge_len = mesh_render_data_edges_len_get(rdata);
+
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len);
+
+ BLI_assert(rdata->types & MR_DATATYPE_EDGE);
+
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter eiter;
+ BMEdge *eed;
+ BM_ITER_MESH(eed, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ GWN_indexbuf_add_line_verts(&elb, BM_elem_index_get(eed->v1), BM_elem_index_get(eed->v2));
+ }
+ }
+ }
+ else {
+ const MEdge *ed = rdata->medge;
+ for (int i = 0; i < edge_len; i++, ed++) {
+ GWN_indexbuf_add_line_verts(&elb, ed->v1, ed->v2);
+ }
+ }
+ cache->edges_in_order = GWN_indexbuf_build(&elb);
+ }
+
+ return cache->edges_in_order;
+}
+
+static Gwn_IndexBuf *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
+
+ if (cache->triangles_in_order == NULL) {
+ const int vert_len = mesh_render_data_verts_len_get(rdata);
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
+
+ if (rdata->edit_bmesh) {
+ for (int i = 0; i < tri_len; ++i) {
+ const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
+ if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) {
+ for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
+ GWN_indexbuf_add_generic_vert(&elb, BM_elem_index_get(ltri[tri_corner]->v));
+ }
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < tri_len; ++i) {
+ const MLoopTri *mlt = &rdata->mlooptri[i];
+ for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
+ GWN_indexbuf_add_generic_vert(&elb, mlt->tri[tri_corner]);
+ }
+ }
+ }
+ cache->triangles_in_order = GWN_indexbuf_build(&elb);
+ }
+
+ return cache->triangles_in_order;
+}
+
+static Gwn_IndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
+ MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_POLY));
+
+ if (cache->shaded_triangles_in_order == NULL) {
+ const int poly_len = mesh_render_data_polys_len_get(rdata);
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+ const int mat_len = mesh_render_data_mat_len_get(rdata);
+
+ int *mat_tri_len = MEM_callocN(sizeof(*mat_tri_len) * mat_len, __func__);
+ cache->shaded_triangles_in_order = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__);
+ Gwn_IndexBufBuilder *elb = MEM_callocN(sizeof(*elb) * mat_len, __func__);
+
+ /* Note that polygons (not triangles) are used here.
+ * This OK because result is _guaranteed_ to be the same. */
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter fiter;
+ BMFace *efa;
+
+ BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ const short ma_id = efa->mat_nr < mat_len ? efa->mat_nr : 0;
+ mat_tri_len[ma_id] += (efa->len - 2);
+ }
+ }
+ }
+ else {
+ for (uint i = 0; i < poly_len; i++) {
+ const MPoly *mp = &rdata->mpoly[i]; ;
+ const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0;
+ mat_tri_len[ma_id] += (mp->totloop - 2);
+ }
+ }
+
+ /* Init ELBs. */
+ for (int i = 0; i < mat_len; ++i) {
+ GWN_indexbuf_init(&elb[i], GWN_PRIM_TRIS, mat_tri_len[i], tri_len * 3);
+ }
+
+ /* Populate ELBs. */
+ uint nidx = 0;
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter fiter;
+ BMFace *efa;
+
+ BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ const short ma_id = efa->mat_nr < mat_len ? efa->mat_nr : 0;
+ for (int j = 2; j < efa->len; j++) {
+ GWN_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
+ nidx += 3;
+ }
+ }
+ }
+ }
+ else {
+ for (uint i = 0; i < poly_len; i++) {
+ const MPoly *mp = &rdata->mpoly[i]; ;
+ const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0;
+ for (int j = 2; j < mp->totloop; j++) {
+ GWN_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
+ nidx += 3;
+ }
+ }
+ }
+
+ /* Build ELBs. */
+ for (int i = 0; i < mat_len; ++i) {
+ cache->shaded_triangles_in_order[i] = GWN_indexbuf_build(&elb[i]);
+ }
+
+ MEM_freeN(mat_tri_len);
+ MEM_freeN(elb);
+ }
+
+ return cache->shaded_triangles_in_order;
+}
+
+static Gwn_VertBuf *mesh_create_edge_pos_with_sel(
+ MeshRenderData *rdata, bool use_wire, bool use_select_bool)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP));
+ BLI_assert(rdata->edit_bmesh == NULL);
+
+ Gwn_VertBuf *vbo;
+ {
+ unsigned int vidx = 0, cidx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, sel; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.sel = GWN_vertformat_attr_add(&format, "select", GWN_COMP_U8, 1, GWN_FETCH_INT);
+ }
+
+ const int edge_len = mesh_render_data_edges_len_get(rdata);
+
+ vbo = GWN_vertbuf_create_with_format(&format);
+
+ const int vbo_len_capacity = edge_len * 2;
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ if (use_select_bool) {
+ mesh_render_data_ensure_edge_select_bool(rdata, use_wire);
+ }
+ bool *edge_select_bool = use_select_bool ? rdata->edge_select_bool : NULL;
+
+ for (int i = 0; i < edge_len; i++) {
+ const MEdge *ed = &rdata->medge[i];
+
+ uchar edge_vert_sel;
+ if (use_select_bool && edge_select_bool[i]) {
+ edge_vert_sel = true;
+ }
+ else if (use_wire) {
+ edge_vert_sel = false;
+ }
+ else {
+ continue;
+ }
+
+ GWN_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel);
+ GWN_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v1].co);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v2].co);
+ }
+ vbo_len_used = vidx;
+
+ if (vbo_len_capacity != vbo_len_used) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ }
+
+ return vbo;
+}
+
+static Gwn_IndexBuf *mesh_create_tri_overlay_weight_faces(
+ MeshRenderData *rdata)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
+
+ {
+ const int vert_len = mesh_render_data_verts_len_get(rdata);
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
+
+ for (int i = 0; i < tri_len; ++i) {
+ const MLoopTri *mlt = &rdata->mlooptri[i];
+ if (!(rdata->mpoly[mlt->poly].flag & (ME_FACE_SEL | ME_HIDE))) {
+ for (uint tri_corner = 0; tri_corner < 3; tri_corner++) {
+ GWN_indexbuf_add_generic_vert(&elb, rdata->mloop[mlt->tri[tri_corner]].v);
+ }
+ }
+ }
+ return GWN_indexbuf_build(&elb);
+ }
+}
+
+/**
+ * Non-edit mode vertices (only used for weight-paint mode).
+ */
+static Gwn_VertBuf *mesh_create_vert_pos_with_overlay_data(
+ MeshRenderData *rdata)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT));
+ BLI_assert(rdata->edit_bmesh == NULL);
+
+ Gwn_VertBuf *vbo;
+ {
+ unsigned int cidx = 0;
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint data; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_I8, 1, GWN_FETCH_INT);
+ }
+
+ const int vert_len = mesh_render_data_verts_len_get(rdata);
+
+ vbo = GWN_vertbuf_create_with_format(&format);
+
+ const int vbo_len_capacity = vert_len;
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ for (int i = 0; i < vert_len; i++) {
+ const MVert *mv = &rdata->mvert[i];
+ const char data = mv->flag & (SELECT | ME_HIDE);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, cidx++, &data);
+ }
+ vbo_len_used = cidx;
+
+ if (vbo_len_capacity != vbo_len_used) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+ }
+ return vbo;
+}
+
+/** \} */
+
+
+/* ---------------------------------------------------------------------- */
+
+/** \name Public API
+ * \{ */
+
+Gwn_Batch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->all_edges == NULL) {
+ /* create batch from Mesh */
+ const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_EDGE;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ cache->all_edges = GWN_batch_create(
+ GWN_PRIM_LINES, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
+ mesh_batch_cache_get_edges_in_order(rdata, cache));
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->all_edges;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_all_triangles(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->all_triangles == NULL) {
+ /* create batch from DM */
+ const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ cache->all_triangles = GWN_batch_create(
+ GWN_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
+ mesh_batch_cache_get_triangles_in_order(rdata, cache));
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->all_triangles;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->triangles_with_normals == NULL) {
+ const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ cache->triangles_with_normals = GWN_batch_create(
+ GWN_PRIM_TRIS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->triangles_with_normals;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(Mesh *me, int defgroup)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->triangles_with_weights == NULL) {
+ const bool use_hide = (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL)) != 0;
+ const int datatype =
+ MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_DVERT;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ cache->triangles_with_weights = GWN_batch_create_ex(
+ GWN_PRIM_TRIS, mesh_create_tri_weights(rdata, use_hide, defgroup), NULL, GWN_BATCH_OWNS_VBO);
+
+ Gwn_VertBuf *vbo_tris = use_hide ?
+ mesh_create_tri_pos_and_normals_visible_only(rdata) :
+ mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+
+ GWN_batch_vertbuf_add_ex(cache->triangles_with_weights, vbo_tris, use_hide);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->triangles_with_weights;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->triangles_with_vert_colors == NULL) {
+ const bool use_hide = (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL)) != 0;
+ const int datatype =
+ MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPCOL;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ cache->triangles_with_vert_colors = GWN_batch_create_ex(
+ GWN_PRIM_TRIS, mesh_create_tri_vert_colors(rdata, use_hide), NULL, GWN_BATCH_OWNS_VBO);
+
+ Gwn_VertBuf *vbo_tris = use_hide ?
+ mesh_create_tri_pos_and_normals_visible_only(rdata) :
+ mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+ GWN_batch_vertbuf_add_ex(cache->triangles_with_vert_colors, vbo_tris, use_hide);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->triangles_with_vert_colors;
+}
+
+
+struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(
+ struct Mesh *me, bool use_hide, uint select_id_offset)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->triangles_with_select_id_offset != select_id_offset) {
+ cache->triangles_with_select_id_offset = select_id_offset;
+ GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id);
+ }
+
+ if (cache->triangles_with_select_id == NULL) {
+ const int datatype =
+ MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ cache->triangles_with_select_id = GWN_batch_create_ex(
+ GWN_PRIM_TRIS, mesh_create_tri_select_id(rdata, use_hide, select_id_offset), NULL, GWN_BATCH_OWNS_VBO);
+
+ Gwn_VertBuf *vbo_tris = use_hide ?
+ mesh_create_tri_pos_and_normals_visible_only(rdata) :
+ mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+ GWN_batch_vertbuf_add_ex(cache->triangles_with_select_id, vbo_tris, use_hide);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->triangles_with_select_id;
+}
+
+/**
+ * Same as #DRW_mesh_batch_cache_get_triangles_with_select_id
+ * without the ID's, use to mask out geometry, eg - dont select face-dots behind other faces.
+ */
+struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+ if (cache->triangles_with_select_mask == NULL) {
+ const int datatype =
+ MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ Gwn_VertBuf *vbo_tris = use_hide ?
+ mesh_create_tri_pos_and_normals_visible_only(rdata) :
+ mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+
+ cache->triangles_with_select_mask = GWN_batch_create_ex(
+ GWN_PRIM_TRIS, vbo_tris, NULL, use_hide ? GWN_BATCH_OWNS_VBO : 0);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->triangles_with_select_mask;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->points_with_normals == NULL) {
+ const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ cache->points_with_normals = GWN_batch_create(
+ GWN_PRIM_POINTS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->points_with_normals;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->all_verts == NULL) {
+ /* create batch from DM */
+ MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
+
+ cache->all_verts = GWN_batch_create(
+ GWN_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->all_verts;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->fancy_edges == NULL) {
+ /* create batch from DM */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, n1, n2; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ attr_id.n1 = GWN_vertformat_attr_add(&format, "N1", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ attr_id.n2 = GWN_vertformat_attr_add(&format, "N2", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ }
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+
+ MeshRenderData *rdata = mesh_render_data_create(
+ me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
+
+ const int edge_len = mesh_render_data_edges_len_get(rdata);
+
+ const int vbo_len_capacity = edge_len * 2; /* these are PRIM_LINE verts, not mesh verts */
+ int vbo_len_used = 0;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ for (int i = 0; i < edge_len; ++i) {
+ float *vcos1, *vcos2;
+ float *pnor1 = NULL, *pnor2 = NULL;
+ bool is_manifold;
+
+ if (mesh_render_data_edge_vcos_manifold_pnors(rdata, i, &vcos1, &vcos2, &pnor1, &pnor2, &is_manifold)) {
+
+ Gwn_PackedNormal n1value = { .x = 0, .y = 0, .z = +511 };
+ Gwn_PackedNormal n2value = { .x = 0, .y = 0, .z = -511 };
+
+ if (is_manifold) {
+ n1value = GWN_normal_convert_i10_v3(pnor1);
+ n2value = GWN_normal_convert_i10_v3(pnor2);
+ }
+
+ const Gwn_PackedNormal *n1 = &n1value;
+ const Gwn_PackedNormal *n2 = &n2value;
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * i, vcos1);
+ GWN_vertbuf_attr_set(vbo, attr_id.n1, 2 * i, n1);
+ GWN_vertbuf_attr_set(vbo, attr_id.n2, 2 * i, n2);
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * i + 1, vcos2);
+ GWN_vertbuf_attr_set(vbo, attr_id.n1, 2 * i + 1, n1);
+ GWN_vertbuf_attr_set(vbo, attr_id.n2, 2 * i + 1, n2);
+
+ vbo_len_used += 2;
+ }
+ }
+ if (vbo_len_used != vbo_len_capacity) {
+ GWN_vertbuf_data_resize(vbo, vbo_len_used);
+ }
+
+ cache->fancy_edges = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->fancy_edges;
+}
+
+static void mesh_batch_cache_create_overlay_batches(Mesh *me)
+{
+ BLI_assert(me->edit_btmesh != NULL);
+
+ /* Since MR_DATATYPE_OVERLAY is slow to generate, generate them all at once */
+ const int options =
+ MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY |
+ MR_DATATYPE_LOOPTRI | MR_DATATYPE_OVERLAY;
+
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+ MeshRenderData *rdata = mesh_render_data_create(me, options);
+
+ if (cache->overlay_triangles == NULL) {
+ cache->overlay_triangles = GWN_batch_create(
+ GWN_PRIM_TRIS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
+ GWN_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
+ GWN_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_data(rdata, cache));
+ }
+
+ if (cache->overlay_loose_edges == NULL) {
+ cache->overlay_loose_edges = GWN_batch_create(
+ GWN_PRIM_LINES, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
+ GWN_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
+ GWN_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_data(rdata, cache));
+ }
+
+ if (cache->overlay_loose_verts == NULL) {
+ cache->overlay_loose_verts = GWN_batch_create(
+ GWN_PRIM_POINTS, mesh_batch_cache_get_edit_lvert_pos(rdata, cache), NULL);
+ GWN_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_nor(rdata, cache));
+ GWN_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_data(rdata, cache));
+ }
+
+ if (cache->overlay_triangles_nor == NULL) {
+ cache->overlay_triangles_nor = GWN_batch_create(
+ GWN_PRIM_POINTS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
+ GWN_batch_vertbuf_add(cache->overlay_triangles_nor, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
+ }
+
+ if (cache->overlay_loose_edges_nor == NULL) {
+ cache->overlay_loose_edges_nor = GWN_batch_create(
+ GWN_PRIM_POINTS, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
+ GWN_batch_vertbuf_add(cache->overlay_loose_edges_nor, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
+ }
+
+ mesh_render_data_free(rdata);
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_triangles == NULL) {
+ mesh_batch_cache_create_overlay_batches(me);
+ }
+
+ return cache->overlay_triangles;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_loose_edges == NULL) {
+ mesh_batch_cache_create_overlay_batches(me);
+ }
+
+ return cache->overlay_loose_edges;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_loose_verts == NULL) {
+ mesh_batch_cache_create_overlay_batches(me);
+ }
+
+ return cache->overlay_loose_verts;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_triangles_nor == NULL) {
+ mesh_batch_cache_create_overlay_batches(me);
+ }
+
+ return cache->overlay_triangles_nor;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_loose_edges_nor == NULL) {
+ mesh_batch_cache_create_overlay_batches(me);
+ }
+
+ return cache->overlay_loose_edges_nor;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_facedots == NULL) {
+ MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
+
+ cache->overlay_facedots = GWN_batch_create(
+ GWN_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->overlay_facedots;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me, uint select_id_offset)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->facedot_with_select_id_offset != select_id_offset) {
+ cache->facedot_with_select_id_offset = select_id_offset;
+ GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
+ }
+
+ if (cache->facedot_with_select_id == NULL) {
+ MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
+
+ /* We only want the 'pos', not the normals or flag.
+ * Use since this is almost certainly already created. */
+ cache->facedot_with_select_id = GWN_batch_create(
+ GWN_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL);
+
+ GWN_batch_vertbuf_add_ex(
+ cache->facedot_with_select_id,
+ mesh_create_facedot_select_id(rdata, select_id_offset), true);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->facedot_with_select_id;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me, uint select_id_offset)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->edges_with_select_id_offset != select_id_offset) {
+ cache->edges_with_select_id_offset = select_id_offset;
+ GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
+ }
+
+ if (cache->edges_with_select_id == NULL) {
+ MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE);
+
+ cache->edges_with_select_id = GWN_batch_create(
+ GWN_PRIM_LINES, mesh_batch_cache_get_edges_visible(rdata, cache), NULL);
+
+ GWN_batch_vertbuf_add_ex(
+ cache->edges_with_select_id,
+ mesh_create_edges_select_id(rdata, select_id_offset), true);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->edges_with_select_id;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me, uint select_id_offset)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->verts_with_select_id_offset != select_id_offset) {
+ cache->verts_with_select_id_offset = select_id_offset;
+ GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
+ }
+
+ if (cache->verts_with_select_id == NULL) {
+ MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
+
+ cache->verts_with_select_id = GWN_batch_create(
+ GWN_PRIM_POINTS, mesh_batch_cache_get_verts_visible(rdata, cache), NULL);
+
+ GWN_batch_vertbuf_add_ex(
+ cache->verts_with_select_id,
+ mesh_create_verts_select_id(rdata, select_id_offset), true);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->verts_with_select_id;
+}
+
+Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded(
+ Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->shaded_triangles == NULL) {
+ /* create batch from DM */
+ const int datatype =
+ MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI |
+ MR_DATATYPE_POLY | MR_DATATYPE_SHADING;
+ MeshRenderData *rdata = mesh_render_data_create_ex(me, datatype, gpumat_array, gpumat_array_len);
+
+ const int mat_len = mesh_render_data_mat_len_get(rdata);
+
+ cache->shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__);
+
+ Gwn_IndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache);
+
+ Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+ for (int i = 0; i < mat_len; ++i) {
+ cache->shaded_triangles[i] = GWN_batch_create(
+ GWN_PRIM_TRIS, vbo, el[i]);
+ Gwn_VertBuf *vbo_shading = mesh_batch_cache_get_tri_shading_data(rdata, cache);
+ if (vbo_shading) {
+ GWN_batch_vertbuf_add(cache->shaded_triangles[i], vbo_shading);
+ }
+ }
+
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->shaded_triangles;
+}
+
+Gwn_Batch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->texpaint_triangles == NULL) {
+ /* create batch from DM */
+ const int datatype =
+ MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ const int mat_len = mesh_render_data_mat_len_get(rdata);
+
+ cache->texpaint_triangles = MEM_callocN(sizeof(*cache->texpaint_triangles) * mat_len, __func__);
+
+ Gwn_IndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache);
+
+ Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+ for (int i = 0; i < mat_len; ++i) {
+ cache->texpaint_triangles[i] = GWN_batch_create(
+ GWN_PRIM_TRIS, vbo, el[i]);
+ Gwn_VertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
+ if (vbo_uv) {
+ GWN_batch_vertbuf_add(cache->texpaint_triangles[i], vbo_uv);
+ }
+ }
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->texpaint_triangles;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->texpaint_triangles_single == NULL) {
+ /* create batch from DM */
+ const int datatype =
+ MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+
+ cache->texpaint_triangles_single = GWN_batch_create(
+ GWN_PRIM_TRIS, vbo, NULL);
+ Gwn_VertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
+ if (vbo_uv) {
+ GWN_batch_vertbuf_add(cache->texpaint_triangles_single, vbo_uv);
+ }
+ mesh_render_data_free(rdata);
+ }
+ return cache->texpaint_triangles_single;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_edges(Mesh *me, bool use_wire, bool use_sel)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_paint_edges == NULL) {
+ /* create batch from Mesh */
+ const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ cache->overlay_paint_edges = GWN_batch_create_ex(
+ GWN_PRIM_LINES, mesh_create_edge_pos_with_sel(rdata, use_wire, use_sel), NULL, GWN_BATCH_OWNS_VBO);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->overlay_paint_edges;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_faces(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_weight_faces == NULL) {
+ /* create batch from Mesh */
+ const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ cache->overlay_weight_faces = GWN_batch_create_ex(
+ GWN_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache),
+ mesh_create_tri_overlay_weight_faces(rdata), GWN_BATCH_OWNS_INDEX);
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->overlay_weight_faces;
+}
+
+Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_verts(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_weight_verts == NULL) {
+ /* create batch from Mesh */
+ MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
+
+ cache->overlay_weight_verts = GWN_batch_create(
+ GWN_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL);
+
+ GWN_batch_vertbuf_add_ex(
+ cache->overlay_weight_verts,
+ mesh_create_vert_pos_with_overlay_data(rdata), true);
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->overlay_weight_verts;
+}
+
+/**
+ * Needed for when we draw with shaded data.
+ */
+void DRW_mesh_cache_sculpt_coords_ensure(Mesh *me)
+{
+ if (me->batch_cache) {
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+ if (cache && cache->pos_with_normals && cache->is_sculpt_points_tag) {
+
+ const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY;
+ MeshRenderData *rdata = mesh_render_data_create(me, datatype);
+
+ Gwn_VertBuf *pos_with_normals = cache->pos_with_normals;
+ cache->pos_with_normals = NULL;
+ GWN_vertbuf_clear(pos_with_normals);
+ Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
+ *pos_with_normals = *vbo;
+ GWN_vertformat_copy(&pos_with_normals->format, &vbo->format);
+
+ free(vbo);
+ cache->pos_with_normals = pos_with_normals;
+
+ mesh_render_data_free(rdata);
+ }
+ cache->is_sculpt_points_tag = false;
+ }
+}
+
+/** \} */
+
+#undef MESH_RENDER_FUNCTION
diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c
new file mode 100644
index 00000000000..e2dba8e626e
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_impl_metaball.c
@@ -0,0 +1,139 @@
+/*
+ * ***** 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) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file draw_cache_impl_metaball.c
+ * \ingroup draw
+ *
+ * \brief MetaBall API for render engines
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_curve.h"
+#include "BKE_mball.h"
+
+#include "GPU_batch.h"
+
+#include "draw_cache_impl.h" /* own include */
+
+
+static void metaball_batch_cache_clear(MetaBall *mb);
+
+/* ---------------------------------------------------------------------- */
+/* MetaBall Gwn_Batch Cache */
+
+typedef struct MetaBallBatchCache {
+ Gwn_Batch *batch;
+
+ /* settings to determine if cache is invalid */
+ bool is_dirty;
+} MetaBallBatchCache;
+
+/* Gwn_Batch cache management. */
+
+static bool metaball_batch_cache_valid(MetaBall *mb)
+{
+ MetaBallBatchCache *cache = mb->batch_cache;
+
+ if (cache == NULL) {
+ return false;
+ }
+
+ return cache->is_dirty == false;
+}
+
+static void metaball_batch_cache_init(MetaBall *mb)
+{
+ MetaBallBatchCache *cache = mb->batch_cache;
+
+ if (!cache) {
+ cache = mb->batch_cache = MEM_mallocN(sizeof(*cache), __func__);
+ }
+ cache->batch = NULL;
+ cache->is_dirty = false;
+}
+
+static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb)
+{
+ if (!metaball_batch_cache_valid(mb)) {
+ metaball_batch_cache_clear(mb);
+ metaball_batch_cache_init(mb);
+ }
+ return mb->batch_cache;
+}
+
+void DRW_mball_batch_cache_dirty(MetaBall *mb, int mode)
+{
+ MetaBallBatchCache *cache = mb->batch_cache;
+ if (cache == NULL) {
+ return;
+ }
+ switch (mode) {
+ case BKE_MBALL_BATCH_DIRTY_ALL:
+ cache->is_dirty = true;
+ break;
+ default:
+ BLI_assert(0);
+ }
+}
+
+static void metaball_batch_cache_clear(MetaBall *mb)
+{
+ MetaBallBatchCache *cache = mb->batch_cache;
+ if (!cache) {
+ return;
+ }
+
+ GWN_BATCH_DISCARD_SAFE(cache->batch);
+}
+
+void DRW_mball_batch_cache_free(MetaBall *mb)
+{
+ metaball_batch_cache_clear(mb);
+ MEM_SAFE_FREE(mb->batch_cache);
+}
+
+/* -------------------------------------------------------------------- */
+
+/** \name Public Object/MetaBall API
+ * \{ */
+
+Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
+{
+ if (!BKE_mball_is_basis(ob))
+ return NULL;
+
+ MetaBall *mb = ob->data;
+ MetaBallBatchCache *cache = metaball_batch_cache_get(mb);
+
+ if (cache->batch == NULL) {
+ cache->batch = BLI_displist_batch_calc_surface(&ob->curve_cache->disp);
+ }
+
+ return cache->batch;
+}
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
new file mode 100644
index 00000000000..da0cc457b99
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -0,0 +1,520 @@
+/*
+ * ***** 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) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file draw_cache_impl_particles.c
+ * \ingroup draw
+ *
+ * \brief Particle API for render engines
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+#include "BLI_string.h"
+#include "BLI_ghash.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_particle_types.h"
+
+#include "BKE_particle.h"
+#include "BKE_DerivedMesh.h"
+
+#include "GPU_batch.h"
+
+#include "draw_cache_impl.h" /* own include */
+
+static void particle_batch_cache_clear(ParticleSystem *psys);
+
+/* ---------------------------------------------------------------------- */
+/* Particle Gwn_Batch Cache */
+
+typedef struct ParticleBatchCache {
+ Gwn_VertBuf *pos;
+ Gwn_IndexBuf *segments;
+
+ Gwn_Batch *hairs;
+
+ int segment_count;
+ int point_count;
+
+ /* settings to determine if cache is invalid */
+ bool is_dirty;
+} ParticleBatchCache;
+
+/* Gwn_Batch cache management. */
+
+static bool particle_batch_cache_valid(ParticleSystem *psys)
+{
+ ParticleBatchCache *cache = psys->batch_cache;
+
+ if (cache == NULL) {
+ return false;
+ }
+
+ if (cache->is_dirty == false) {
+ return true;
+ }
+ else {
+ return false;
+ }
+
+ return true;
+}
+
+static void particle_batch_cache_init(ParticleSystem *psys)
+{
+ ParticleBatchCache *cache = psys->batch_cache;
+
+ if (!cache) {
+ cache = psys->batch_cache = MEM_callocN(sizeof(*cache), __func__);
+ }
+ else {
+ memset(cache, 0, sizeof(*cache));
+ }
+
+ cache->is_dirty = false;
+}
+
+static ParticleBatchCache *particle_batch_cache_get(ParticleSystem *psys)
+{
+ if (!particle_batch_cache_valid(psys)) {
+ particle_batch_cache_clear(psys);
+ particle_batch_cache_init(psys);
+ }
+ return psys->batch_cache;
+}
+
+void DRW_particle_batch_cache_dirty(ParticleSystem *psys, int mode)
+{
+ ParticleBatchCache *cache = psys->batch_cache;
+ if (cache == NULL) {
+ return;
+ }
+ switch (mode) {
+ case BKE_PARTICLE_BATCH_DIRTY_ALL:
+ cache->is_dirty = true;
+ break;
+ default:
+ BLI_assert(0);
+ }
+}
+
+static void particle_batch_cache_clear(ParticleSystem *psys)
+{
+ ParticleBatchCache *cache = psys->batch_cache;
+ if (!cache) {
+ return;
+ }
+
+ GWN_BATCH_DISCARD_SAFE(cache->hairs);
+
+ GWN_VERTBUF_DISCARD_SAFE(cache->pos);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->segments);
+}
+
+void DRW_particle_batch_cache_free(ParticleSystem *psys)
+{
+ particle_batch_cache_clear(psys);
+ MEM_SAFE_FREE(psys->batch_cache);
+}
+
+static void ensure_seg_pt_count(ParticleSystem *psys, ParticleBatchCache *cache)
+{
+ if (cache->pos == NULL || cache->segments == NULL) {
+ cache->segment_count = 0;
+ cache->point_count = 0;
+
+ if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
+ for (int i = 0; i < psys->totpart; i++) {
+ ParticleCacheKey *path = psys->pathcache[i];
+
+ if (path->segments > 0) {
+ cache->segment_count += path->segments;
+ cache->point_count += path->segments + 1;
+ }
+ }
+ }
+
+ if (psys->childcache) {
+ int child_count = psys->totchild * psys->part->disp / 100;
+
+ for (int i = 0; i < child_count; i++) {
+ ParticleCacheKey *path = psys->childcache[i];
+
+ if (path->segments > 0) {
+ cache->segment_count += path->segments;
+ cache->point_count += path->segments + 1;
+ }
+ }
+ }
+ }
+}
+
+/* Gwn_Batch cache usage. */
+static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, ModifierData *md, ParticleBatchCache *cache)
+{
+ if (cache->pos == NULL || cache->segments == NULL) {
+ int curr_point = 0;
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
+
+ GWN_VERTBUF_DISCARD_SAFE(cache->pos);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->segments);
+
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos, tan, ind; } attr_id;
+ unsigned int *uv_id = NULL;
+ int uv_layers = 0;
+ MTFace **mtfaces = NULL;
+ float (**parent_uvs)[2] = NULL;
+ bool simple = psys->part->childtype == PART_CHILD_PARTICLES;
+
+ if (psmd) {
+ if (CustomData_has_layer(&psmd->dm_final->loopData, CD_MLOOPUV)) {
+ uv_layers = CustomData_number_of_layers(&psmd->dm_final->loopData, CD_MLOOPUV);
+ }
+ }
+
+ GWN_vertformat_clear(&format);
+
+ /* initialize vertex format */
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.tan = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.ind = GWN_vertformat_attr_add(&format, "ind", GWN_COMP_I32, 1, GWN_FETCH_INT);
+
+ if (psmd) {
+ uv_id = MEM_mallocN(sizeof(*uv_id) * uv_layers, "UV attrib format");
+
+ for (int i = 0; i < uv_layers; i++) {
+ const char *name = CustomData_get_layer_name(&psmd->dm_final->loopData, CD_MLOOPUV, i);
+ char uuid[32];
+
+ BLI_snprintf(uuid, sizeof(uuid), "u%u", BLI_ghashutil_strhash_p(name));
+ uv_id[i] = GWN_vertformat_attr_add(&format, uuid, GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+ }
+
+ cache->pos = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(cache->pos, cache->point_count);
+
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_LINES, cache->segment_count, cache->point_count);
+
+ if (uv_layers) {
+ DM_ensure_tessface(psmd->dm_final);
+
+ mtfaces = MEM_mallocN(sizeof(*mtfaces) * uv_layers, "Faces UV layers");
+
+ for (int i = 0; i < uv_layers; i++) {
+ mtfaces[i] = (MTFace *)CustomData_get_layer_n(&psmd->dm_final->faceData, CD_MTFACE, i);
+ }
+ }
+
+ if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
+ if (simple) {
+ parent_uvs = MEM_callocN(sizeof(*parent_uvs) * psys->totpart, "Parent particle UVs");
+ }
+
+ for (int i = 0; i < psys->totpart; i++) {
+ ParticleCacheKey *path = psys->pathcache[i];
+
+ if (path->segments > 0) {
+ float tangent[3];
+ int from = psmd ? psmd->psys->part->from : 0;
+ float (*uv)[2] = NULL;
+
+ if (psmd) {
+ uv = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs");
+
+ if (simple) {
+ parent_uvs[i] = uv;
+ }
+ }
+
+ if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ ParticleData *particle = &psys->particles[i];
+ int num = particle->num_dmcache;
+
+ if (num == DMCACHE_NOTFOUND) {
+ if (particle->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) {
+ num = particle->num;
+ }
+ }
+
+ if (num != DMCACHE_NOTFOUND) {
+ MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
+
+ for (int j = 0; j < uv_layers; j++) {
+ psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, uv[j]);
+ }
+ }
+ }
+
+ for (int j = 0; j < path->segments; j++) {
+ if (j == 0) {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j].co);
+ }
+ else {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co);
+ }
+
+ GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[j].co);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &i);
+
+ if (psmd) {
+ for (int k = 0; k < uv_layers; k++) {
+ GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, uv[k]);
+ }
+ }
+
+ GWN_indexbuf_add_line_verts(&elb, curr_point, curr_point + 1);
+
+ curr_point++;
+ }
+
+ sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co);
+
+ GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[path->segments].co);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &i);
+
+ if (psmd) {
+ for (int k = 0; k < uv_layers; k++) {
+ GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, uv[k]);
+ }
+
+ if (!simple) {
+ MEM_freeN(uv);
+ }
+ }
+
+ curr_point++;
+ }
+ }
+ }
+
+ if (psys->childcache) {
+ int child_count = psys->totchild * psys->part->disp / 100;
+
+ if (simple && !parent_uvs) {
+ parent_uvs = MEM_callocN(sizeof(*parent_uvs) * psys->totpart, "Parent particle UVs");
+ }
+
+ for (int i = 0, x = psys->totpart; i < child_count; i++, x++) {
+ ParticleCacheKey *path = psys->childcache[i];
+ float tangent[3];
+
+ if (path->segments > 0) {
+ int from = psmd ? psmd->psys->part->from : 0;
+ float (*uv)[2] = NULL;
+
+ if (!simple) {
+ if (psmd) {
+ uv = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs");
+ }
+
+ if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ ChildParticle *particle = &psys->child[i];
+ int num = particle->num;
+
+ if (num != DMCACHE_NOTFOUND) {
+ MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
+
+ for (int j = 0; j < uv_layers; j++) {
+ psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, uv[j]);
+ }
+ }
+ }
+ }
+ else if (!parent_uvs[psys->child[i].parent]) {
+ if (psmd) {
+ parent_uvs[psys->child[i].parent] = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs");
+ }
+
+ if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ ParticleData *particle = &psys->particles[psys->child[i].parent];
+ int num = particle->num_dmcache;
+
+ if (num == DMCACHE_NOTFOUND) {
+ if (particle->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) {
+ num = particle->num;
+ }
+ }
+
+ if (num != DMCACHE_NOTFOUND) {
+ MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
+
+ for (int j = 0; j < uv_layers; j++) {
+ psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, parent_uvs[psys->child[i].parent][j]);
+ }
+ }
+ }
+ }
+
+ for (int j = 0; j < path->segments; j++) {
+ if (j == 0) {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j].co);
+ }
+ else {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co);
+ }
+
+ GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[j].co);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &x);
+
+ if (psmd) {
+ for (int k = 0; k < uv_layers; k++) {
+ GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point,
+ simple ? parent_uvs[psys->child[i].parent][k] : uv[k]);
+ }
+ }
+
+ GWN_indexbuf_add_line_verts(&elb, curr_point, curr_point + 1);
+
+ curr_point++;
+ }
+
+ sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co);
+
+ GWN_vertbuf_attr_set(cache->pos, attr_id.pos, curr_point, path[path->segments].co);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent);
+ GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &x);
+
+ if (psmd) {
+ for (int k = 0; k < uv_layers; k++) {
+ GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point,
+ simple ? parent_uvs[psys->child[i].parent][k] : uv[k]);
+ }
+
+ if (!simple) {
+ MEM_freeN(uv);
+ }
+ }
+
+ curr_point++;
+ }
+ }
+ }
+
+ if (parent_uvs) {
+ for (int i = 0; i < psys->totpart; i++) {
+ MEM_SAFE_FREE(parent_uvs[i]);
+ }
+
+ MEM_freeN(parent_uvs);
+ }
+
+ if (uv_layers) {
+ MEM_freeN(mtfaces);
+ }
+
+ if (psmd) {
+ MEM_freeN(uv_id);
+ }
+
+ cache->segments = GWN_indexbuf_build(&elb);
+ }
+}
+
+static void particle_batch_cache_ensure_pos(ParticleSystem *psys, ParticleBatchCache *cache)
+{
+ if (cache->pos == NULL) {
+ static Gwn_VertFormat format = { 0 };
+ static unsigned pos_id, rot_id, val_id;
+ int i, curr_point;
+ ParticleData *pa;
+
+ GWN_VERTBUF_DISCARD_SAFE(cache->pos);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->segments);
+
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ rot_id = GWN_vertformat_attr_add(&format, "rot", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ val_id = GWN_vertformat_attr_add(&format, "val", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ }
+
+ cache->pos = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(cache->pos, psys->totpart);
+
+ for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
+ if (pa->state.time >= pa->time && pa->state.time < pa->dietime &&
+ !(pa->flag & (PARS_NO_DISP | PARS_UNEXIST)))
+ {
+ float val;
+
+ GWN_vertbuf_attr_set(cache->pos, pos_id, curr_point, pa->state.co);
+ GWN_vertbuf_attr_set(cache->pos, rot_id, curr_point, pa->state.rot);
+
+ switch (psys->part->draw_col) {
+ case PART_DRAW_COL_VEL:
+ val = len_v3(pa->state.vel) / psys->part->color_vec_max;
+ break;
+ case PART_DRAW_COL_ACC:
+ val = len_v3v3(pa->state.vel, pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * psys->part->color_vec_max);
+ break;
+ default:
+ val = -1.0f;
+ break;
+ }
+
+ GWN_vertbuf_attr_set(cache->pos, val_id, curr_point, &val);
+
+ curr_point++;
+ }
+ }
+
+ if (curr_point != psys->totpart) {
+ GWN_vertbuf_data_resize(cache->pos, curr_point);
+ }
+ }
+}
+
+Gwn_Batch *DRW_particles_batch_cache_get_hair(ParticleSystem *psys, ModifierData *md)
+{
+ ParticleBatchCache *cache = particle_batch_cache_get(psys);
+
+ if (cache->hairs == NULL) {
+ ensure_seg_pt_count(psys, cache);
+ particle_batch_cache_ensure_pos_and_seg(psys, md, cache);
+ cache->hairs = GWN_batch_create(GWN_PRIM_LINES, cache->pos, cache->segments);
+ }
+
+ return cache->hairs;
+}
+
+Gwn_Batch *DRW_particles_batch_cache_get_dots(ParticleSystem *psys)
+{
+ ParticleBatchCache *cache = particle_batch_cache_get(psys);
+
+ if (cache->hairs == NULL) {
+ particle_batch_cache_ensure_pos(psys, cache);
+ cache->hairs = GWN_batch_create(GWN_PRIM_POINTS, cache->pos, NULL);
+ }
+
+ return cache->hairs;
+}
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
new file mode 100644
index 00000000000..f24d7d13771
--- /dev/null
+++ b/source/blender/draw/intern/draw_common.c
@@ -0,0 +1,463 @@
+/*
+ * 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/intern/draw_common.c
+ * \ingroup draw
+ */
+
+#include "DRW_render.h"
+
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+#include "UI_resources.h"
+
+#include "BKE_global.h"
+#include "BKE_colorband.h"
+
+#include "draw_common.h"
+
+
+#if 0
+#define UI_COLOR_RGB_FROM_U8(r, g, b, v4) \
+ ARRAY_SET_ITEMS(v4, (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, 1.0)
+#endif
+#define UI_COLOR_RGBA_FROM_U8(r, g, b, a, v4) \
+ ARRAY_SET_ITEMS(v4, (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f)
+
+/* Colors & Constant */
+GlobalsUboStorage ts;
+struct GPUUniformBuffer *globals_ubo = NULL;
+struct GPUTexture *globals_ramp = NULL;
+
+void DRW_globals_update(void)
+{
+ UI_GetThemeColor4fv(TH_WIRE, ts.colorWire);
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, ts.colorWireEdit);
+ UI_GetThemeColor4fv(TH_ACTIVE, ts.colorActive);
+ UI_GetThemeColor4fv(TH_SELECT, ts.colorSelect);
+ UI_GetThemeColor4fv(TH_TRANSFORM, ts.colorTransform);
+ UI_GetThemeColor4fv(TH_GROUP_ACTIVE, ts.colorGroupActive);
+ UI_GetThemeColorShade4fv(TH_GROUP_ACTIVE, -25, ts.colorGroupSelect);
+ UI_GetThemeColor4fv(TH_GROUP, ts.colorGroup);
+ UI_COLOR_RGBA_FROM_U8(0x88, 0xFF, 0xFF, 155, ts.colorLibrarySelect);
+ UI_COLOR_RGBA_FROM_U8(0x55, 0xCC, 0xCC, 155, ts.colorLibrary);
+ UI_GetThemeColor4fv(TH_LAMP, ts.colorLamp);
+ UI_GetThemeColor4fv(TH_SPEAKER, ts.colorSpeaker);
+ UI_GetThemeColor4fv(TH_CAMERA, ts.colorCamera);
+ UI_GetThemeColor4fv(TH_EMPTY, ts.colorEmpty);
+ UI_GetThemeColor4fv(TH_VERTEX, ts.colorVertex);
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, ts.colorVertexSelect);
+ UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, ts.colorEditMeshActive);
+ UI_GetThemeColor4fv(TH_EDGE_SELECT, ts.colorEdgeSelect);
+ UI_GetThemeColor4fv(TH_EDGE_SEAM, ts.colorEdgeSeam);
+ UI_GetThemeColor4fv(TH_EDGE_SHARP, ts.colorEdgeSharp);
+ UI_GetThemeColor4fv(TH_EDGE_CREASE, ts.colorEdgeCrease);
+ UI_GetThemeColor4fv(TH_EDGE_BEVEL, ts.colorEdgeBWeight);
+ UI_GetThemeColor4fv(TH_EDGE_FACESEL, ts.colorEdgeFaceSelect);
+ UI_GetThemeColor4fv(TH_FACE, ts.colorFace);
+ UI_GetThemeColor4fv(TH_FACE_SELECT, ts.colorFaceSelect);
+ UI_GetThemeColor4fv(TH_NORMAL, ts.colorNormal);
+ UI_GetThemeColor4fv(TH_VNORMAL, ts.colorVNormal);
+ UI_GetThemeColor4fv(TH_LNORMAL, ts.colorLNormal);
+ UI_GetThemeColor4fv(TH_FACE_DOT, ts.colorFaceDot);
+ UI_GetThemeColor4fv(TH_BACK, ts.colorBackground);
+
+ /* Grid */
+ UI_GetThemeColorShade4fv(TH_GRID, 10, ts.colorGrid);
+ /* emphasise division lines lighter instead of darker, if background is darker than grid */
+ UI_GetThemeColorShade4fv(
+ TH_GRID,
+ (ts.colorGrid[0] + ts.colorGrid[1] + ts.colorGrid[2] + 0.12f >
+ ts.colorBackground[0] + ts.colorBackground[1] + ts.colorBackground[2]) ?
+ 20 : -10, ts.colorGridEmphasise);
+ /* Grid Axis */
+ UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_X, 0.5f, -10, ts.colorGridAxisX);
+ UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_Y, 0.5f, -10, ts.colorGridAxisY);
+ UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_Z, 0.5f, -10, ts.colorGridAxisZ);
+
+ UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, ts.colorDeselect);
+ UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, ts.colorOutline);
+ UI_GetThemeColorShadeAlpha4fv(TH_LAMP, 0, 255, ts.colorLampNoAlpha);
+
+ ts.sizeLampCenter = (U.obcenter_dia + 1.5f) * U.pixelsize;
+ ts.sizeLampCircle = U.pixelsize * 9.0f;
+ ts.sizeLampCircleShadow = ts.sizeLampCircle + U.pixelsize * 3.0f;
+
+ /* M_SQRT2 to be at least the same size of the old square */
+ ts.sizeVertex = ceilf(UI_GetThemeValuef(TH_VERTEX_SIZE) * (float)M_SQRT2 / 2.0f);
+ ts.sizeFaceDot = ceilf(UI_GetThemeValuef(TH_FACEDOT_SIZE) * (float)M_SQRT2);
+ ts.sizeEdge = 1.0f / 2.0f; /* TODO Theme */
+ ts.sizeEdgeFix = 0.5f + 2.0f * (2.0f * (MAX2(ts.sizeVertex, ts.sizeEdge)) * (float)M_SQRT1_2);
+
+ /* TODO Waiting for notifiers to invalidate cache */
+ if (globals_ubo) {
+ DRW_uniformbuffer_free(globals_ubo);
+ }
+
+ globals_ubo = DRW_uniformbuffer_create(sizeof(GlobalsUboStorage), &ts);
+
+ ColorBand ramp = {0};
+ float *colors;
+ int col_size;
+
+ ramp.tot = 3;
+ ramp.data[0].a = 1.0f;
+ ramp.data[0].b = 1.0f;
+ ramp.data[0].pos = 0.0f;
+ ramp.data[1].a = 1.0f;
+ ramp.data[1].g = 1.0f;
+ ramp.data[1].pos = 0.5f;
+ ramp.data[2].a = 1.0f;
+ ramp.data[2].r = 1.0f;
+ ramp.data[2].pos = 1.0f;
+
+ BKE_colorband_evaluate_table_rgba(&ramp, &colors, &col_size);
+
+ if (globals_ramp) {
+ GPU_texture_free(globals_ramp);
+ }
+ globals_ramp = GPU_texture_create_1D(col_size, colors, NULL);
+
+ MEM_freeN(colors);
+}
+
+/* ********************************* SHGROUP ************************************* */
+
+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;
+}
+
+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_AA);
+
+ 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_enable(grp, DRW_STATE_POINT);
+
+ return grp;
+}
+
+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;
+}
+
+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_enable(grp, DRW_STATE_POINT);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Gwn_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[0]", DRW_viewport_screenvecs_get(), 2);
+ DRW_shgroup_state_enable(grp, DRW_STATE_STIPPLE_3);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_objspace_solid(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
+{
+ static float light[3] = {0.0f, 0.0f, 1.0f};
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_attrib_float(grp, "color", 4);
+ DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
+ DRW_shgroup_uniform_vec3(grp, "light", light, 1);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_objspace_wire(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_attrib_float(grp, "color", 4);
+ DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass, struct Gwn_Batch *geom)
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "size", 1);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Gwn_Batch *geom)
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "size", 1);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass, struct Gwn_Batch *geom)
+{
+ GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "size", 3);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Gwn_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;
+}
+
+DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Gwn_Batch *geom)
+{
+ GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_CAMERA);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "corners", 8);
+ DRW_shgroup_attrib_float(grp, "depth", 1);
+ DRW_shgroup_attrib_float(grp, "tria", 4);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Gwn_Batch *geom)
+{
+ GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES);
+ static float point_size = 4.0f;
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "start", 1);
+ DRW_shgroup_attrib_float(grp, "end", 1);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_uniform_float(grp, "size", &point_size, 1);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom)
+{
+ GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR);
+ static bool True = true;
+ static bool False = false;
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1);
+ DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1);
+ DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_bone_envelope_wire(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_attrib_float(grp, "color", 4);
+ DRW_shgroup_attrib_float(grp, "radius_head", 1);
+ DRW_shgroup_attrib_float(grp, "radius_tail", 1);
+ DRW_shgroup_attrib_float(grp, "distance", 1);
+ DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
+{
+ static float light[3] = {0.0f, 0.0f, 1.0f};
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_attrib_float(grp, "color", 4);
+ DRW_shgroup_attrib_float(grp, "radius_head", 1);
+ DRW_shgroup_attrib_float(grp, "radius_tail", 1);
+ DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
+ DRW_shgroup_uniform_vec3(grp, "light", light, 1);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_mball_helpers(DRWPass *pass, struct Gwn_Batch *geom)
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_MBALL_HELPERS);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "ScaleTranslationMatrix", 12);
+ DRW_shgroup_attrib_float(grp, "radius", 1);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
+
+ return grp;
+}
+
+
+/* ******************************************** COLOR UTILS *********************************************** */
+
+/* TODO FINISH */
+/**
+ * Get the wire color theme_id of an object based on it's state
+ * \a r_color is a way to get a pointer to the static color var associated
+ */
+int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color)
+{
+ const bool is_edit = (ob->mode & OB_MODE_EDIT) != 0;
+ const bool active = (view_layer->basact && view_layer->basact->object == ob);
+ /* 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) {
+ theme_id = TH_GROUP_ACTIVE;
+ }
+ else {
+ theme_id = TH_GROUP;
+ }
+ }
+ else {
+ if ((ob->base_flag & BASE_SELECTED) != 0) {
+ theme_id = (active) ? 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 (r_color != NULL) {
+ switch (theme_id) {
+ case TH_WIRE_EDIT: *r_color = ts.colorTransform; break;
+ case TH_ACTIVE: *r_color = ts.colorActive; break;
+ case TH_SELECT: *r_color = ts.colorSelect; break;
+ case TH_GROUP: *r_color = ts.colorGroup; break;
+ case TH_GROUP_ACTIVE: *r_color = ts.colorGroupActive; break;
+ case TH_TRANSFORM: *r_color = ts.colorTransform; break;
+ case OB_SPEAKER: *r_color = ts.colorSpeaker; break;
+ case OB_CAMERA: *r_color = ts.colorCamera; break;
+ case OB_EMPTY: *r_color = ts.colorEmpty; break;
+ case OB_LAMP: *r_color = ts.colorLamp; break;
+ default: *r_color = ts.colorWire; break;
+ }
+
+ /* uses darker active color for non-active + selected */
+ if ((theme_id == TH_GROUP_ACTIVE) && !active) {
+ *r_color = ts.colorGroupSelect;
+ }
+ }
+
+ return theme_id;
+}
+
+/* XXX This is utter shit, better find something more general */
+float *DRW_color_background_blend_get(int theme_id)
+{
+ static float colors[11][4];
+ float *ret;
+
+ switch (theme_id) {
+ case TH_WIRE_EDIT: ret = colors[0]; break;
+ case TH_ACTIVE: ret = colors[1]; break;
+ case TH_SELECT: ret = colors[2]; break;
+ case TH_GROUP: ret = colors[3]; break;
+ case TH_GROUP_ACTIVE: ret = colors[4]; break;
+ case TH_TRANSFORM: ret = colors[5]; break;
+ case OB_SPEAKER: ret = colors[6]; break;
+ case OB_CAMERA: ret = colors[7]; break;
+ case OB_EMPTY: ret = colors[8]; break;
+ case OB_LAMP: ret = colors[9]; break;
+ default: ret = colors[10]; break;
+ }
+
+ UI_GetThemeColorBlendShade4fv(theme_id, TH_BACK, 0.5, 0, ret);
+
+ return ret;
+}
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
new file mode 100644
index 00000000000..0bdb79b3a40
--- /dev/null
+++ b/source/blender/draw/intern/draw_common.h
@@ -0,0 +1,132 @@
+/*
+ * 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_common.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_COMMON_H__
+#define __DRAW_COMMON_H__
+
+struct DRWPass;
+struct DRWShadingGroup;
+struct Gwn_Batch;
+struct Object;
+struct ViewLayer;
+
+/* Used as ubo but colors can be directly referenced as well */
+/* Keep in sync with: common_globals_lib.glsl (globalsBlock) */
+typedef struct GlobalsUboStorage {
+ /* UBOs data needs to be 16 byte aligned (size of vec4) */
+ float colorWire[4];
+ float colorWireEdit[4];
+ float colorActive[4];
+ float colorSelect[4];
+ float colorTransform[4];
+ float colorGroupActive[4];
+ float colorGroupSelect[4];
+ float colorGroup[4];
+ float colorLibrarySelect[4];
+ float colorLibrary[4];
+ float colorLamp[4];
+ float colorSpeaker[4];
+ float colorCamera[4];
+ float colorEmpty[4];
+ float colorVertex[4];
+ float colorVertexSelect[4];
+ float colorEditMeshActive[4];
+ float colorEdgeSelect[4];
+ float colorEdgeSeam[4];
+ float colorEdgeSharp[4];
+ float colorEdgeCrease[4];
+ float colorEdgeBWeight[4];
+ float colorEdgeFaceSelect[4];
+ float colorFace[4];
+ float colorFaceSelect[4];
+ float colorNormal[4];
+ float colorVNormal[4];
+ float colorLNormal[4];
+ float colorFaceDot[4];
+
+ float colorDeselect[4];
+ float colorOutline[4];
+ float colorLampNoAlpha[4];
+
+ float colorBackground[4];
+
+ float colorGrid[4];
+ float colorGridEmphasise[4];
+ float colorGridAxisX[4];
+ float colorGridAxisY[4];
+ float colorGridAxisZ[4];
+
+ /* Pack individual float at the end of the buffer to avoid alignement errors */
+ float sizeLampCenter, sizeLampCircle, sizeLampCircleShadow;
+ float sizeVertex, sizeEdge, sizeEdgeFix, sizeFaceDot;
+ float gridDistance, gridResolution, gridSubdivisions, gridScale;
+} GlobalsUboStorage;
+/* Keep in sync with globalsBlock in shaders */
+
+void DRW_globals_update(void);
+
+struct DRWShadingGroup *shgroup_dynlines_uniform_color(struct DRWPass *pass, float color[4]);
+struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass, float color[4], float *size);
+struct DRWShadingGroup *shgroup_groundlines_uniform_color(struct DRWPass *pass, float color[4]);
+struct DRWShadingGroup *shgroup_groundpoints_uniform_color(struct DRWPass *pass, float color[4]);
+struct DRWShadingGroup *shgroup_instance_screenspace(struct DRWPass *pass, struct Gwn_Batch *geom, float *size);
+struct DRWShadingGroup *shgroup_instance_objspace_solid(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
+struct DRWShadingGroup *shgroup_instance_objspace_wire(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
+struct DRWShadingGroup *shgroup_instance_screen_aligned(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_instance_axis_names(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_instance_image_plane(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_instance_scaled(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_instance_bone_envelope_wire(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
+struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
+struct DRWShadingGroup *shgroup_instance_mball_helpers(struct DRWPass *pass, struct Gwn_Batch *geom);
+
+int DRW_object_wire_theme_get(struct Object *ob, struct ViewLayer *view_layer, float **r_color);
+float *DRW_color_background_blend_get(int theme_id);
+
+/* draw_armature.c */
+void DRW_shgroup_armature_object(
+ struct Object *ob, struct ViewLayer *view_layer,
+ struct DRWPass *pass_bone_solid, struct DRWPass *pass_bone_wire, struct DRWPass *pass_bone_envelope,
+ struct DRWShadingGroup *shgrp_relationship_lines);
+
+void DRW_shgroup_armature_pose(
+ struct Object *ob,
+ struct DRWPass *pass_bone_solid, struct DRWPass *pass_bone_wire, struct DRWPass *pass_bone_envelope,
+ struct DRWShadingGroup *shgrp_relationship_lines);
+
+void DRW_shgroup_armature_edit(
+ struct Object *ob,
+ struct DRWPass *pass_bone_solid, struct DRWPass *pass_bone_wire, struct DRWPass *pass_bone_envelope,
+ struct DRWShadingGroup *shgrp_relationship_lines);
+
+/* pose_mode.c */
+bool DRW_pose_mode_armature(
+ struct Object *ob, struct Object *active_ob);
+
+#endif /* __DRAW_COMMON_H__ */
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
new file mode 100644
index 00000000000..264fc079e42
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager.c
@@ -0,0 +1,3910 @@
+/*
+ * 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/intern/draw_manager.c
+ * \ingroup draw
+ */
+
+#include <stdio.h>
+
+#include "BLI_dynstr.h"
+#include "BLI_listbase.h"
+#include "BLI_mempool.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
+
+#include "BIF_glutil.h"
+
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_pbvh.h"
+#include "BKE_paint.h"
+#include "BKE_workspace.h"
+
+#include "BLT_translation.h"
+#include "BLF_api.h"
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "intern/gpu_codegen.h"
+#include "GPU_batch.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
+#include "GPU_immediate.h"
+#include "GPU_lamp.h"
+#include "GPU_material.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+#include "GPU_uniformbuffer.h"
+#include "GPU_viewport.h"
+#include "GPU_matrix.h"
+
+#include "IMB_colormanagement.h"
+
+#include "RE_engine.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "draw_manager_text.h"
+#include "draw_manager_profiling.h"
+
+/* only for callbacks */
+#include "draw_cache_impl.h"
+
+#include "draw_mode_engines.h"
+#include "engines/clay/clay_engine.h"
+#include "engines/eevee/eevee_engine.h"
+#include "engines/basic/basic_engine.h"
+#include "engines/external/external_engine.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Local Features
+ * \{ */
+
+#define USE_PROFILE
+
+#ifdef USE_PROFILE
+# include "PIL_time.h"
+
+# define PROFILE_TIMER_FALLOFF 0.1
+
+# define PROFILE_START(time_start) \
+ double time_start = PIL_check_seconds_timer();
+
+# define PROFILE_END_ACCUM(time_accum, time_start) { \
+ time_accum += (PIL_check_seconds_timer() - time_start) * 1e3; \
+} ((void)0)
+
+/* exp average */
+# define PROFILE_END_UPDATE(time_update, time_start) { \
+ double _time_delta = (PIL_check_seconds_timer() - time_start) * 1e3; \
+ time_update = (time_update * (1.0 - PROFILE_TIMER_FALLOFF)) + \
+ (_time_delta * PROFILE_TIMER_FALLOFF); \
+} ((void)0)
+
+#else /* USE_PROFILE */
+
+# define PROFILE_START(time_start) ((void)0)
+# define PROFILE_END_ACCUM(time_accum, time_start) ((void)0)
+# define PROFILE_END_UPDATE(time_update, time_start) ((void)0)
+
+#endif /* USE_PROFILE */
+
+
+/* Use draw manager to call GPU_select, see: DRW_draw_select_loop */
+#define USE_GPU_SELECT
+
+#ifdef USE_GPU_SELECT
+# include "ED_view3d.h"
+# include "ED_armature.h"
+# include "GPU_select.h"
+#endif
+
+/** \} */
+
+
+#define MAX_ATTRIB_NAME 32
+#define MAX_ATTRIB_COUNT 6 /* Can be adjusted for more */
+#define MAX_PASS_NAME 32
+#define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */
+
+extern char datatoc_gpu_shader_2D_vert_glsl[];
+extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
+
+/* Prototypes. */
+static void drw_engines_enable_external(void);
+
+/* Structures */
+typedef enum {
+ DRW_UNIFORM_BOOL,
+ DRW_UNIFORM_SHORT_TO_INT,
+ DRW_UNIFORM_SHORT_TO_FLOAT,
+ 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;
+
+struct DRWUniform {
+ struct DRWUniform *next;
+ DRWUniformType type;
+ int location;
+ int length;
+ int arraysize;
+ const void *value;
+};
+
+typedef struct DRWAttrib {
+ struct DRWAttrib *prev;
+ char name[MAX_ATTRIB_NAME];
+ int location;
+ int format_id;
+ int size; /* number of component */
+ int type;
+} DRWAttrib;
+
+struct DRWInterface {
+ DRWUniform *uniforms; /* DRWUniform, single-linked list */
+ DRWAttrib *attribs; /* DRWAttrib, single-linked list */
+ DRWAttrib *attribs_first; /* First added attrib to traverse in the right order */
+ int attribs_count;
+ int attribs_stride;
+ int attribs_size[16];
+ int attribs_loc[16];
+ /* matrices locations */
+ int model;
+ int modelinverse;
+ int modelview;
+ int modelviewinverse;
+ int projection;
+ int projectioninverse;
+ int view;
+ int viewinverse;
+ int modelviewprojection;
+ int viewprojection;
+ int viewprojectioninverse;
+ int normal;
+ int worldnormal;
+ int camtexfac;
+ int orcotexfac;
+ int eye;
+ int clipplanes;
+ /* Dynamic batch */
+ Gwn_Batch *instance_batch; /* contains instances attributes */
+ GLuint instance_vbo; /* same as instance_batch but generated from DRWCalls */
+ int instance_count;
+ Gwn_VertFormat vbo_format;
+};
+
+struct DRWPass {
+ /* Single linked list with last member to append */
+ DRWShadingGroup *shgroups;
+ DRWShadingGroup *shgroups_last;
+
+ DRWState state;
+ char name[MAX_PASS_NAME];
+};
+
+typedef struct DRWCallHeader {
+ void *prev;
+
+#ifdef USE_GPU_SELECT
+ int select_id;
+#endif
+ uchar type;
+} DRWCallHeader;
+
+typedef struct DRWCall {
+ DRWCallHeader head;
+
+ float obmat[4][4];
+ Gwn_Batch *geometry;
+
+ Object *ob; /* Optional */
+ ID *ob_data; /* Optional. */
+} DRWCall;
+
+typedef struct DRWCallGenerate {
+ DRWCallHeader head;
+
+ float obmat[4][4];
+
+ DRWCallGenerateFn *geometry_fn;
+ void *user_data;
+} DRWCallGenerate;
+
+typedef struct DRWCallDynamic {
+ DRWCallHeader head;
+
+ const void *data[MAX_ATTRIB_COUNT];
+} DRWCallDynamic;
+
+struct DRWShadingGroup {
+ struct DRWShadingGroup *next;
+
+ GPUShader *shader; /* Shader to bind */
+ DRWInterface interface; /* Uniforms pointers */
+
+ /* DRWCall or DRWCallDynamic depending of type */
+ void *calls;
+ void *calls_first; /* To be able to traverse the list in the order of addition */
+
+ DRWState state_extra; /* State changes for this batch only (or'd with the pass's state) */
+ DRWState state_extra_disable; /* State changes for this batch only (and'd with the pass's state) */
+ unsigned int stencil_mask; /* Stencil mask to use for stencil test / write operations */
+ int type;
+
+ ID *instance_data; /* Object->data to instance */
+ Gwn_Batch *instance_geom; /* Geometry to instance */
+ Gwn_Batch *batch_geom; /* Result of call batching */
+
+#ifdef USE_GPU_SELECT
+ /* backlink to pass we're in */
+ DRWPass *pass_parent;
+#endif
+};
+
+/* Used by DRWShadingGroup.type */
+enum {
+ DRW_SHG_NORMAL,
+ DRW_SHG_POINT_BATCH,
+ DRW_SHG_LINE_BATCH,
+ DRW_SHG_TRIANGLE_BATCH,
+ DRW_SHG_INSTANCE,
+};
+
+/* Used by DRWCall.type */
+enum {
+ /* A single batch */
+ DRW_CALL_SINGLE,
+ /* Uses a callback to draw with any number of batches. */
+ DRW_CALL_GENERATE,
+ /* Arbitrary number of multiple args. */
+ DRW_CALL_DYNAMIC,
+};
+
+/* only 16 bits long */
+enum {
+ STENCIL_SELECT = (1 << 0),
+ STENCIL_ACTIVE = (1 << 1),
+};
+
+/** Render State: No persistent data between draw calls. */
+static struct DRWGlobalState {
+ /* Cache generation */
+ ViewportMemoryPool *vmempool;
+ DRWUniform *last_uniform;
+ DRWAttrib *last_attrib;
+ DRWCall *last_call;
+ DRWCallGenerate *last_callgenerate;
+ DRWCallDynamic *last_calldynamic;
+ DRWShadingGroup *last_shgroup;
+
+ /* Rendering state */
+ GPUShader *shader;
+
+ /* Managed by `DRW_state_set`, `DRW_state_reset` */
+ DRWState state;
+ unsigned int stencil_mask;
+
+ /* Per viewport */
+ GPUViewport *viewport;
+ struct GPUFrameBuffer *default_framebuffer;
+ float size[2];
+ float screenvecs[2][3];
+ float pixsize;
+
+ GLenum backface, frontface;
+
+ /* Clip planes */
+ int num_clip_planes;
+ float clip_planes_eq[MAX_CLIP_PLANES][4];
+
+ struct {
+ unsigned int is_select : 1;
+ unsigned int is_depth : 1;
+ unsigned int is_image_render : 1;
+ unsigned int is_scene_render : 1;
+ } options;
+
+ /* Current rendering context */
+ DRWContextState draw_ctx;
+
+ /* Convenience pointer to text_store owned by the viewport */
+ struct DRWTextStore **text_store_p;
+
+ ListBase enabled_engines; /* RenderEngineType */
+
+ /* Profiling */
+ double cache_time;
+} DST = {NULL};
+
+/** GPU Resource State: Memory storage between drawing. */
+static struct DRWResourceState {
+ GPUTexture **bound_texs;
+
+ bool *bound_tex_slots;
+
+ int bind_tex_inc;
+ int bind_ubo_inc;
+} RST = {NULL};
+
+static struct DRWMatrixOveride {
+ float mat[6][4][4];
+ bool override[6];
+} viewport_matrix_override = {{{{0}}}};
+
+ListBase DRW_engines = {NULL, NULL};
+
+#ifdef USE_GPU_SELECT
+static unsigned int g_DRW_select_id = (unsigned int)-1;
+
+void DRW_select_load_id(unsigned int id)
+{
+ BLI_assert(G.f & G_PICKSEL);
+ g_DRW_select_id = id;
+}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Textures (DRW_texture)
+ * \{ */
+
+static void drw_texture_get_format(
+ DRWTextureFormat format,
+ GPUTextureFormat *r_data_type, int *r_channels)
+{
+ switch (format) {
+ case DRW_TEX_RGBA_8: *r_data_type = GPU_RGBA8; break;
+ case DRW_TEX_RGBA_16: *r_data_type = GPU_RGBA16F; break;
+ case DRW_TEX_RGB_16: *r_data_type = GPU_RGB16F; break;
+ case DRW_TEX_RGB_11_11_10: *r_data_type = GPU_R11F_G11F_B10F; break;
+ case DRW_TEX_RG_8: *r_data_type = GPU_RG8; break;
+ case DRW_TEX_RG_16: *r_data_type = GPU_RG16F; break;
+ case DRW_TEX_RG_32: *r_data_type = GPU_RG32F; break;
+ case DRW_TEX_R_8: *r_data_type = GPU_R8; break;
+ case DRW_TEX_R_16: *r_data_type = GPU_R16F; break;
+ case DRW_TEX_R_32: *r_data_type = GPU_R32F; break;
+#if 0
+ case DRW_TEX_RGBA_32: *r_data_type = GPU_RGBA32F; break;
+ case DRW_TEX_RGB_8: *r_data_type = GPU_RGB8; break;
+ case DRW_TEX_RGB_32: *r_data_type = GPU_RGB32F; break;
+#endif
+ case DRW_TEX_DEPTH_16: *r_data_type = GPU_DEPTH_COMPONENT16; break;
+ case DRW_TEX_DEPTH_24: *r_data_type = GPU_DEPTH_COMPONENT24; break;
+ case DRW_TEX_DEPTH_24_STENCIL_8: *r_data_type = GPU_DEPTH24_STENCIL8; break;
+ case DRW_TEX_DEPTH_32: *r_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:
+ *r_channels = 4;
+ break;
+ case DRW_TEX_RGB_8:
+ case DRW_TEX_RGB_16:
+ case DRW_TEX_RGB_32:
+ case DRW_TEX_RGB_11_11_10:
+ *r_channels = 3;
+ break;
+ case DRW_TEX_RG_8:
+ case DRW_TEX_RG_16:
+ case DRW_TEX_RG_32:
+ *r_channels = 2;
+ break;
+ default:
+ *r_channels = 1;
+ break;
+ }
+}
+
+static void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags)
+{
+ GPU_texture_bind(tex, 0);
+ if (flags & DRW_TEX_MIPMAP) {
+ GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER);
+ DRW_texture_generate_mipmaps(tex);
+ }
+ else {
+ 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;
+}
+
+GPUTexture *DRW_texture_create_2D_array(
+ int w, int h, int d, 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_array_custom(w, h, d, channels, data_type, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
+GPUTexture *DRW_texture_create_3D(
+ int w, int h, int d, 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_3D_custom(w, h, d, channels, data_type, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
+GPUTexture *DRW_texture_create_cube(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_cube_custom(w, channels, data_type, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
+void DRW_texture_generate_mipmaps(GPUTexture *tex)
+{
+ GPU_texture_bind(tex, 0);
+ GPU_texture_generate_mipmap(tex);
+ GPU_texture_unbind(tex);
+}
+
+void DRW_texture_update(GPUTexture *tex, const float *pixels)
+{
+ GPU_texture_update(tex, pixels);
+}
+
+void DRW_texture_free(GPUTexture *tex)
+{
+ GPU_texture_free(tex);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Uniform Buffer Object (DRW_uniformbuffer)
+ * \{ */
+
+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);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Shaders (DRW_shader)
+ * \{ */
+
+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);
+}
+
+GPUShader *DRW_shader_create_with_lib(
+ const char *vert, const char *geom, const char *frag, const char *lib, const char *defines)
+{
+ GPUShader *sh;
+ char *vert_with_lib = NULL;
+ char *frag_with_lib = NULL;
+ char *geom_with_lib = NULL;
+
+ DynStr *ds_vert = BLI_dynstr_new();
+ BLI_dynstr_append(ds_vert, lib);
+ BLI_dynstr_append(ds_vert, vert);
+ vert_with_lib = BLI_dynstr_get_cstring(ds_vert);
+ BLI_dynstr_free(ds_vert);
+
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, lib);
+ BLI_dynstr_append(ds_frag, frag);
+ frag_with_lib = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ if (geom) {
+ DynStr *ds_geom = BLI_dynstr_new();
+ BLI_dynstr_append(ds_geom, lib);
+ BLI_dynstr_append(ds_geom, geom);
+ geom_with_lib = BLI_dynstr_get_cstring(ds_geom);
+ BLI_dynstr_free(ds_geom);
+ }
+
+ sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines);
+
+ MEM_freeN(vert_with_lib);
+ MEM_freeN(frag_with_lib);
+ if (geom) {
+ MEM_freeN(geom_with_lib);
+ }
+
+ return sh;
+}
+
+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);
+}
+
+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);
+}
+
+GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines)
+{
+ return GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, frag, NULL, NULL, defines);
+}
+
+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);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Interface (DRW_interface)
+ * \{ */
+
+static void drw_interface_create(DRWInterface *interface, GPUShader *shader)
+{
+ interface->model = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL);
+ interface->modelinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL_INV);
+ interface->modelview = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW);
+ interface->modelviewinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW_INV);
+ interface->projection = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_PROJECTION);
+ interface->projectioninverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_PROJECTION_INV);
+ interface->view = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_VIEW);
+ interface->viewinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_VIEW_INV);
+ interface->viewprojection = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_VIEWPROJECTION);
+ interface->viewprojectioninverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_VIEWPROJECTION_INV);
+ interface->modelviewprojection = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MVP);
+ interface->normal = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_NORMAL);
+ interface->worldnormal = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_WORLDNORMAL);
+ interface->camtexfac = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_CAMERATEXCO);
+ interface->orcotexfac = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_ORCO);
+ interface->clipplanes = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_CLIPPLANES);
+ interface->eye = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_EYE);
+ interface->instance_count = 0;
+ interface->attribs_count = 0;
+ interface->attribs_stride = 0;
+ interface->instance_vbo = 0;
+ interface->instance_batch = NULL;
+
+ memset(&interface->vbo_format, 0, sizeof(Gwn_VertFormat));
+
+ interface->uniforms = NULL;
+ interface->attribs = NULL;
+ interface->attribs_first = NULL;
+}
+
+
+static void drw_interface_uniform(DRWShadingGroup *shgroup, const char *name,
+ DRWUniformType type, const void *value, int length, int arraysize)
+{
+ int location;
+ if (type == DRW_UNIFORM_BLOCK) {
+ location = GPU_shader_get_uniform_block(shgroup->shader, name);
+ }
+ else {
+ location = GPU_shader_get_uniform(shgroup->shader, name);
+ }
+
+ if (location == -1) {
+ if (G.debug & G_DEBUG)
+ fprintf(stderr, "Uniform '%s' not found!\n", name);
+ /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
+ // BLI_assert(0);
+ return;
+ }
+
+ DRWUniform *uni = BLI_mempool_alloc(DST.vmempool->uniforms);
+
+ BLI_assert(arraysize > 0);
+
+ uni->location = location;
+ uni->type = type;
+ uni->value = value;
+ uni->length = length;
+ uni->arraysize = arraysize;
+
+ /* Prepend */
+ uni->next = shgroup->interface.uniforms;
+ shgroup->interface.uniforms = uni;
+}
+
+static void drw_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType type, int size, bool dummy)
+{
+ DRWAttrib *attrib = BLI_mempool_alloc(DST.vmempool->attribs);
+ GLuint program = GPU_shader_get_program(shgroup->shader);
+
+ attrib->location = glGetAttribLocation(program, name);
+ attrib->type = type;
+ attrib->size = size;
+
+/* Adding attribute even if not found for now (to keep memory alignment).
+ * Should ideally take vertex format automatically from batch eventually */
+#if 0
+ if (attrib->location == -1 && !dummy) {
+ if (G.debug & G_DEBUG)
+ fprintf(stderr, "Attribute '%s' not found!\n", name);
+ BLI_assert(0);
+ MEM_freeN(attrib);
+ return;
+ }
+#else
+ UNUSED_VARS(dummy);
+#endif
+
+ BLI_assert(BLI_strnlen(name, 32) < 32);
+ BLI_strncpy(attrib->name, name, 32);
+
+ shgroup->interface.attribs_count += 1;
+ BLI_assert(shgroup->interface.attribs_count < MAX_ATTRIB_COUNT);
+
+ /* Prepend */
+ if (shgroup->interface.attribs == NULL) {
+ shgroup->interface.attribs = attrib;
+ shgroup->interface.attribs_first = attrib;
+ }
+ else {
+ shgroup->interface.attribs->prev = attrib;
+ shgroup->interface.attribs = attrib;
+ }
+ attrib->prev = NULL;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Shading Group (DRW_shgroup)
+ * \{ */
+
+DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
+{
+ DRWShadingGroup *shgroup = BLI_mempool_alloc(DST.vmempool->shgroups);
+
+ /* Append */
+ if (pass->shgroups != NULL) {
+ pass->shgroups_last->next = shgroup;
+ }
+ else {
+ pass->shgroups = shgroup;
+ }
+ pass->shgroups_last = shgroup;
+ shgroup->next = NULL;
+
+ drw_interface_create(&shgroup->interface, shader);
+
+ shgroup->type = DRW_SHG_NORMAL;
+ shgroup->shader = shader;
+ shgroup->state_extra = 0;
+ shgroup->state_extra_disable = ~0x0;
+ shgroup->stencil_mask = 0;
+ shgroup->batch_geom = NULL;
+ shgroup->instance_geom = NULL;
+ shgroup->instance_data = NULL;
+
+ shgroup->calls = NULL;
+ shgroup->calls_first = NULL;
+
+#ifdef USE_GPU_SELECT
+ shgroup->pass_parent = pass;
+#endif
+
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass)
+{
+ double time = 0.0; /* TODO make time variable */
+
+ /* TODO : Ideally we should not convert. But since the whole codegen
+ * is relying on GPUPass we keep it as is for now. */
+ GPUPass *gpupass = GPU_material_get_pass(material);
+
+ if (!gpupass) {
+ /* Shader compilation error */
+ return NULL;
+ }
+
+ struct GPUShader *shader = GPU_pass_shader(gpupass);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
+
+ /* Converting dynamic GPUInput to DRWUniform */
+ ListBase *inputs = &gpupass->inputs;
+
+ for (GPUInput *input = inputs->first; input; input = input->next) {
+ /* Textures */
+ if (input->ima) {
+ GPUTexture *tex = GPU_texture_from_blender(
+ input->ima, input->iuser, input->textarget, input->image_isdata, time, 1);
+
+ if (input->bindtex) {
+ DRW_shgroup_uniform_texture(grp, input->shadername, tex);
+ }
+ }
+ /* Color Ramps */
+ else if (input->tex) {
+ DRW_shgroup_uniform_texture(grp, input->shadername, input->tex);
+ }
+ /* Floats */
+ else {
+ switch (input->type) {
+ case GPU_FLOAT:
+ DRW_shgroup_uniform_float(grp, input->shadername, (float *)input->dynamicvec, 1);
+ break;
+ case GPU_VEC2:
+ DRW_shgroup_uniform_vec2(grp, input->shadername, (float *)input->dynamicvec, 1);
+ break;
+ case GPU_VEC3:
+ DRW_shgroup_uniform_vec3(grp, input->shadername, (float *)input->dynamicvec, 1);
+ break;
+ case GPU_VEC4:
+ DRW_shgroup_uniform_vec4(grp, input->shadername, (float *)input->dynamicvec, 1);
+ break;
+ case GPU_MAT3:
+ DRW_shgroup_uniform_mat3(grp, input->shadername, (float *)input->dynamicvec);
+ break;
+ case GPU_MAT4:
+ DRW_shgroup_uniform_mat4(grp, input->shadername, (float *)input->dynamicvec);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ GPUUniformBuffer *ubo = GPU_material_get_uniform_buffer(material);
+ if (ubo != NULL) {
+ DRW_shgroup_uniform_block(grp, GPU_UBO_BLOCK_NAME, ubo);
+ }
+
+ return grp;
+}
+
+DRWShadingGroup *DRW_shgroup_material_instance_create(
+ struct GPUMaterial *material, DRWPass *pass, Gwn_Batch *geom, Object *ob)
+{
+ DRWShadingGroup *shgroup = DRW_shgroup_material_create(material, pass);
+
+ if (shgroup) {
+ shgroup->type = DRW_SHG_INSTANCE;
+ shgroup->instance_geom = geom;
+ shgroup->instance_data = ob->data;
+ }
+
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(
+ struct GPUMaterial *material, DRWPass *pass, int size)
+{
+ DRWShadingGroup *shgroup = DRW_shgroup_material_create(material, pass);
+
+ if (shgroup) {
+ shgroup->type = DRW_SHG_TRIANGLE_BATCH;
+ shgroup->interface.instance_count = size * 3;
+ drw_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true);
+ }
+
+ return shgroup;
+}
+
+DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, Gwn_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;
+}
+
+/* Very special batch. Use this if you position
+ * your vertices with the vertex shader
+ * and dont need any VBO attrib */
+DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int size)
+{
+ DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
+
+ shgroup->type = DRW_SHG_TRIANGLE_BATCH;
+ shgroup->interface.instance_count = size * 3;
+ drw_interface_attrib(shgroup, "dummy", DRW_ATTRIB_FLOAT, 1, true);
+
+ return shgroup;
+}
+
+void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
+{
+ if (shgroup->interface.instance_vbo &&
+ (shgroup->interface.instance_batch == 0))
+ {
+ glDeleteBuffers(1, &shgroup->interface.instance_vbo);
+ }
+
+ GWN_BATCH_DISCARD_SAFE(shgroup->batch_geom);
+}
+
+void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *instances)
+{
+ BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
+ BLI_assert(shgroup->interface.instance_batch == NULL);
+
+ shgroup->interface.instance_batch = instances;
+}
+
+#define CALL_PREPEND(shgroup, call) { \
+ if (shgroup->calls == NULL) { \
+ shgroup->calls = call; \
+ shgroup->calls_first = call; \
+ } \
+ else { \
+ ((DRWCall *)(shgroup->calls))->head.prev = call; \
+ shgroup->calls = call; \
+ } \
+ call->head.prev = NULL; \
+} ((void)0)
+
+
+void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4])
+{
+ BLI_assert(geom != NULL);
+
+ DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+
+ CALL_PREPEND(shgroup, call);
+
+ call->head.type = DRW_CALL_SINGLE;
+#ifdef USE_GPU_SELECT
+ call->head.select_id = g_DRW_select_id;
+#endif
+
+ if (obmat != NULL) {
+ copy_m4_m4(call->obmat, obmat);
+ }
+
+ call->geometry = geom;
+ call->ob_data = NULL;
+}
+
+void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob)
+{
+ BLI_assert(geom != NULL);
+
+ DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+
+ CALL_PREPEND(shgroup, call);
+
+ call->head.type = DRW_CALL_SINGLE;
+#ifdef USE_GPU_SELECT
+ call->head.select_id = g_DRW_select_id;
+#endif
+
+ copy_m4_m4(call->obmat, ob->obmat);
+ call->geometry = geom;
+ call->ob_data = ob->data;
+}
+
+void DRW_shgroup_call_generate_add(
+ DRWShadingGroup *shgroup,
+ DRWCallGenerateFn *geometry_fn, void *user_data,
+ float (*obmat)[4])
+{
+ BLI_assert(geometry_fn != NULL);
+
+ DRWCallGenerate *call = BLI_mempool_alloc(DST.vmempool->calls_generate);
+
+ CALL_PREPEND(shgroup, call);
+
+ call->head.type = DRW_CALL_GENERATE;
+#ifdef USE_GPU_SELECT
+ call->head.select_id = g_DRW_select_id;
+#endif
+
+ if (obmat != NULL) {
+ copy_m4_m4(call->obmat, obmat);
+ }
+
+ call->geometry_fn = geometry_fn;
+ call->user_data = user_data;
+}
+
+static void sculpt_draw_cb(
+ DRWShadingGroup *shgroup,
+ void (*draw_fn)(DRWShadingGroup *shgroup, Gwn_Batch *geom),
+ void *user_data)
+{
+ Object *ob = user_data;
+ PBVH *pbvh = ob->sculpt->pbvh;
+
+ if (pbvh) {
+ BKE_pbvh_draw_cb(
+ pbvh, NULL, NULL, false,
+ (void (*)(void *, Gwn_Batch *))draw_fn, shgroup);
+ }
+}
+
+void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, Object *ob, float (*obmat)[4])
+{
+ DRW_shgroup_call_generate_add(shgroup, sculpt_draw_cb, ob, obmat);
+}
+
+void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *attr[], unsigned int attr_len)
+{
+ DRWInterface *interface = &shgroup->interface;
+
+#ifdef USE_GPU_SELECT
+ if ((G.f & G_PICKSEL) && (interface->instance_count > 0)) {
+ DRWShadingGroup *original_shgroup = shgroup;
+ shgroup = BLI_mempool_alloc(DST.vmempool->shgroups);
+ memcpy(shgroup, original_shgroup, sizeof(DRWShadingGroup));
+
+ shgroup->calls = NULL;
+ shgroup->calls_first = NULL;
+
+ interface = &shgroup->interface;
+ interface->instance_count = 0;
+
+ /* Append */
+ if (shgroup->pass_parent->shgroups != NULL) {
+ shgroup->pass_parent->shgroups_last->next = shgroup;
+ }
+ else {
+ shgroup->pass_parent->shgroups = shgroup;
+ }
+ shgroup->pass_parent->shgroups_last = shgroup;
+ shgroup->next = NULL;
+ }
+#endif
+
+ DRWCallDynamic *call = BLI_mempool_alloc(DST.vmempool->calls_dynamic);
+
+ CALL_PREPEND(shgroup, call);
+
+ BLI_assert(attr_len == interface->attribs_count);
+ UNUSED_VARS_NDEBUG(attr_len);
+
+ call->head.type = DRW_CALL_DYNAMIC;
+#ifdef USE_GPU_SELECT
+ call->head.select_id = g_DRW_select_id;
+#endif
+
+ if (interface->attribs_count != 0) {
+ memcpy((void *)call->data, attr, sizeof(void *) * interface->attribs_count);
+ }
+
+ interface->instance_count += 1;
+}
+
+/* Used for instancing with no attributes */
+void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, int count)
+{
+ DRWInterface *interface = &shgroup->interface;
+
+ BLI_assert(interface->attribs_count == 0);
+
+ interface->instance_count = count;
+}
+
+/**
+ * State is added to #Pass.state while drawing.
+ * Use to temporarily enable draw options.
+ */
+void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
+{
+ shgroup->state_extra |= state;
+}
+
+void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
+{
+ shgroup->state_extra_disable &= ~state;
+}
+
+void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, unsigned int mask)
+{
+ shgroup->stencil_mask = mask;
+}
+
+void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int size)
+{
+ drw_interface_attrib(shgroup, name, DRW_ATTRIB_FLOAT, size, false);
+}
+
+void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
+{
+ drw_interface_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 1);
+}
+
+void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuffer *ubo)
+{
+ drw_interface_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 1);
+}
+
+void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
+{
+ drw_interface_uniform(shgroup, name, DRW_UNIFORM_BUFFER, tex, 0, 1);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+void DRW_shgroup_uniform_short_to_int(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize)
+{
+ drw_interface_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_INT, value, 1, arraysize);
+}
+
+void DRW_shgroup_uniform_short_to_float(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize)
+{
+ drw_interface_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_FLOAT, value, 1, arraysize);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float *value)
+{
+ drw_interface_uniform(shgroup, name, DRW_UNIFORM_MAT3, value, 9, 1);
+}
+
+void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float *value)
+{
+ drw_interface_uniform(shgroup, name, DRW_UNIFORM_MAT4, value, 16, 1);
+}
+
+/* Creates a VBO containing OGL primitives for all DRWCallDynamic */
+static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
+{
+ DRWInterface *interface = &shgroup->interface;
+ int nbr = interface->instance_count;
+
+ Gwn_PrimType type = (shgroup->type == DRW_SHG_POINT_BATCH) ? GWN_PRIM_POINTS :
+ (shgroup->type == DRW_SHG_TRIANGLE_BATCH) ? GWN_PRIM_TRIS : GWN_PRIM_LINES;
+
+ if (nbr == 0)
+ return;
+
+ /* Upload Data */
+ if (interface->vbo_format.attrib_ct == 0) {
+ for (DRWAttrib *attrib = interface->attribs_first; attrib; attrib = attrib->prev) {
+ BLI_assert(attrib->size <= 4); /* matrices have no place here for now */
+ if (attrib->type == DRW_ATTRIB_FLOAT) {
+ attrib->format_id = GWN_vertformat_attr_add(
+ &interface->vbo_format, attrib->name, GWN_COMP_F32, attrib->size, GWN_FETCH_FLOAT);
+ }
+ else if (attrib->type == DRW_ATTRIB_INT) {
+ attrib->format_id = GWN_vertformat_attr_add(
+ &interface->vbo_format, attrib->name, GWN_COMP_I8, attrib->size, GWN_FETCH_INT);
+ }
+ else {
+ BLI_assert(false);
+ }
+ }
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&interface->vbo_format);
+ GWN_vertbuf_data_alloc(vbo, nbr);
+
+ int j = 0;
+ for (DRWCallDynamic *call = shgroup->calls_first; call; call = call->head.prev, j++) {
+ int i = 0;
+ for (DRWAttrib *attrib = interface->attribs_first; attrib; attrib = attrib->prev, i++) {
+ GWN_vertbuf_attr_set(vbo, attrib->format_id, j, call->data[i]);
+ }
+ }
+
+ /* TODO make the batch dynamic instead of freeing it every times */
+ if (shgroup->batch_geom)
+ GWN_batch_discard(shgroup->batch_geom);
+
+ shgroup->batch_geom = GWN_batch_create_ex(type, vbo, NULL, GWN_BATCH_OWNS_VBO);
+}
+
+static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
+{
+ int i = 0;
+ int offset = 0;
+ DRWInterface *interface = &shgroup->interface;
+ int buffer_size = 0;
+
+ if (interface->instance_batch != NULL) {
+ return;
+ }
+
+ /* TODO We still need this because gawain does not support Matrix attribs. */
+ if (interface->instance_count == 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->prev, 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 * interface->instance_count;
+ float *data = MEM_mallocN(buffer_size, "Instance VBO data");
+
+ for (DRWCallDynamic *call = shgroup->calls_first; call; call = call->head.prev) {
+ 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)
+{
+ if ((shgroup->interface.instance_vbo || shgroup->batch_geom) &&
+ (G.debug_value == 667))
+ {
+ return;
+ }
+
+ if (shgroup->type == DRW_SHG_INSTANCE) {
+ shgroup_dynamic_instance(shgroup);
+ }
+ else {
+ shgroup_dynamic_batch(shgroup);
+ }
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Passes (DRW_pass)
+ * \{ */
+
+DRWPass *DRW_pass_create(const char *name, DRWState state)
+{
+ DRWPass *pass = BLI_mempool_alloc(DST.vmempool->passes);
+ pass->state = state;
+ BLI_strncpy(pass->name, name, MAX_PASS_NAME);
+
+ pass->shgroups = NULL;
+ pass->shgroups_last = NULL;
+
+ return pass;
+}
+
+void DRW_pass_free(DRWPass *pass)
+{
+ for (DRWShadingGroup *shgroup = pass->shgroups; shgroup; shgroup = shgroup->next) {
+ DRW_shgroup_free(shgroup);
+ }
+
+ pass->shgroups = NULL;
+ pass->shgroups_last = NULL;
+}
+
+void DRW_pass_foreach_shgroup(DRWPass *pass, void (*callback)(void *userData, DRWShadingGroup *shgrp), void *userData)
+{
+ for (DRWShadingGroup *shgroup = pass->shgroups; shgroup; shgroup = shgroup->next) {
+ callback(userData, shgroup);
+ }
+}
+
+typedef struct ZSortData {
+ float *axis;
+ float *origin;
+} ZSortData;
+
+static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b)
+{
+ const ZSortData *zsortdata = (ZSortData *)thunk;
+ const DRWShadingGroup *shgrp_a = (const DRWShadingGroup *)a;
+ const DRWShadingGroup *shgrp_b = (const DRWShadingGroup *)b;
+
+ const DRWCall *call_a;
+ const DRWCall *call_b;
+
+ call_a = shgrp_a->calls_first;
+ call_b = shgrp_b->calls_first;
+
+ if (call_a == NULL) return -1;
+ if (call_b == NULL) return -1;
+
+ float tmp[3];
+ sub_v3_v3v3(tmp, zsortdata->origin, call_a->obmat[3]);
+ const float a_sq = dot_v3v3(zsortdata->axis, tmp);
+ sub_v3_v3v3(tmp, zsortdata->origin, call_b->obmat[3]);
+ const float b_sq = dot_v3v3(zsortdata->axis, tmp);
+
+ if (a_sq < b_sq) return 1;
+ else if (a_sq > b_sq) return -1;
+ else {
+ /* If there is a depth prepass put it before */
+ if ((shgrp_a->state_extra & DRW_STATE_WRITE_DEPTH) != 0) {
+ return -1;
+ }
+ else if ((shgrp_b->state_extra & DRW_STATE_WRITE_DEPTH) != 0) {
+ return 1;
+ }
+ else return 0;
+ }
+}
+
+/* ------------------ Shading group sorting --------------------- */
+
+#define SORT_IMPL_LINKTYPE DRWShadingGroup
+
+#define SORT_IMPL_USE_THUNK
+#define SORT_IMPL_FUNC shgroup_sort_fn_r
+#include "../../blenlib/intern/list_sort_impl.h"
+#undef SORT_IMPL_FUNC
+#undef SORT_IMPL_USE_THUNK
+
+#undef SORT_IMPL_LINKTYPE
+
+/**
+ * Sort Shading groups by decreasing Z of their first draw call.
+ * This is usefull for order dependant effect such as transparency.
+ **/
+void DRW_pass_sort_shgroup_z(DRWPass *pass)
+{
+ RegionView3D *rv3d = DST.draw_ctx.rv3d;
+
+ float (*viewinv)[4];
+ viewinv = (viewport_matrix_override.override[DRW_MAT_VIEWINV])
+ ? viewport_matrix_override.mat[DRW_MAT_VIEWINV] : rv3d->viewinv;
+
+ ZSortData zsortdata = {viewinv[2], viewinv[3]};
+
+ if (pass->shgroups && pass->shgroups->next) {
+ pass->shgroups = shgroup_sort_fn_r(pass->shgroups, pass_shgroup_dist_sort, &zsortdata);
+
+ /* Find the next last */
+ DRWShadingGroup *last = pass->shgroups;
+ while ((last = last->next)) {
+ /* Do nothing */
+ }
+ pass->shgroups_last = last;
+ }
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Draw (DRW_draw)
+ * \{ */
+
+static void drw_state_set(DRWState state)
+{
+ if (DST.state == state) {
+ return;
+ }
+
+
+#define CHANGED_TO(f) \
+ ((DST.state & (f)) ? \
+ ((state & (f)) ? 0 : -1) : \
+ ((state & (f)) ? 1 : 0))
+
+#define CHANGED_ANY(f) \
+ ((DST.state & (f)) != (state & (f)))
+
+#define CHANGED_ANY_STORE_VAR(f, enabled) \
+ ((DST.state & (f)) != (enabled = (state & (f))))
+
+ /* Depth Write */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_WRITE_DEPTH))) {
+ if (test == 1) {
+ glDepthMask(GL_TRUE);
+ }
+ else {
+ glDepthMask(GL_FALSE);
+ }
+ }
+ }
+
+ /* Color Write */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_WRITE_COLOR))) {
+ if (test == 1) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+ else {
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ }
+ }
+ }
+
+ /* Cull */
+ {
+ DRWState test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_CULL_BACK | DRW_STATE_CULL_FRONT,
+ test))
+ {
+ if (test) {
+ glEnable(GL_CULL_FACE);
+
+ if ((state & DRW_STATE_CULL_BACK) != 0) {
+ glCullFace(GL_BACK);
+ }
+ else if ((state & DRW_STATE_CULL_FRONT) != 0) {
+ glCullFace(GL_FRONT);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ glDisable(GL_CULL_FACE);
+ }
+ }
+ }
+
+ /* Depth Test */
+ {
+ DRWState test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER | DRW_STATE_DEPTH_ALWAYS,
+ test))
+ {
+ if (test) {
+ glEnable(GL_DEPTH_TEST);
+
+ if (state & DRW_STATE_DEPTH_LESS) {
+ glDepthFunc(GL_LEQUAL);
+ }
+ else if (state & DRW_STATE_DEPTH_EQUAL) {
+ glDepthFunc(GL_EQUAL);
+ }
+ else if (state & DRW_STATE_DEPTH_GREATER) {
+ glDepthFunc(GL_GREATER);
+ }
+ else if (state & DRW_STATE_DEPTH_ALWAYS) {
+ glDepthFunc(GL_ALWAYS);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ glDisable(GL_DEPTH_TEST);
+ }
+ }
+ }
+
+ /* Wire Width */
+ {
+ if (CHANGED_ANY(DRW_STATE_WIRE | DRW_STATE_WIRE_LARGE)) {
+ if ((state & DRW_STATE_WIRE) != 0) {
+ glLineWidth(1.0f);
+ }
+ else if ((state & DRW_STATE_WIRE_LARGE) != 0) {
+ glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+ }
+ else {
+ /* do nothing */
+ }
+ }
+ }
+
+ /* Points Size */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_POINT))) {
+ if (test == 1) {
+ GPU_enable_program_point_size();
+ glPointSize(5.0f);
+ }
+ else {
+ GPU_disable_program_point_size();
+ }
+ }
+ }
+
+ /* Blending (all buffer) */
+ {
+ int test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_BLEND | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY | DRW_STATE_TRANSMISSION,
+ test))
+ {
+ if (test) {
+ glEnable(GL_BLEND);
+
+ if ((state & DRW_STATE_BLEND) != 0) {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else if ((state & DRW_STATE_MULTIPLY) != 0) {
+ glBlendFunc(GL_DST_COLOR, GL_ZERO);
+ }
+ else if ((state & DRW_STATE_TRANSMISSION) != 0) {
+ glBlendFunc(GL_ONE, GL_SRC_ALPHA);
+ }
+ else if ((state & DRW_STATE_ADDITIVE) != 0) {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ glDisable(GL_BLEND);
+ }
+ }
+ }
+
+ /* Clip Planes */
+ {
+ int test;
+ if ((test = CHANGED_TO(DRW_STATE_CLIP_PLANES))) {
+ if (test == 1) {
+ for (int i = 0; i < DST.num_clip_planes; ++i) {
+ glEnable(GL_CLIP_DISTANCE0 + i);
+ }
+ }
+ else {
+ for (int i = 0; i < MAX_CLIP_PLANES; ++i) {
+ glDisable(GL_CLIP_DISTANCE0 + i);
+ }
+ }
+ }
+ }
+
+ /* Line Stipple */
+ {
+ int test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_STIPPLE_2 | DRW_STATE_STIPPLE_3 | DRW_STATE_STIPPLE_4,
+ test))
+ {
+ if (test) {
+ if ((state & DRW_STATE_STIPPLE_2) != 0) {
+ setlinestyle(2);
+ }
+ else if ((state & DRW_STATE_STIPPLE_3) != 0) {
+ setlinestyle(3);
+ }
+ else if ((state & DRW_STATE_STIPPLE_4) != 0) {
+ setlinestyle(4);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ setlinestyle(0);
+ }
+ }
+ }
+
+ /* Stencil */
+ {
+ DRWState test;
+ if (CHANGED_ANY_STORE_VAR(
+ DRW_STATE_WRITE_STENCIL |
+ DRW_STATE_STENCIL_EQUAL,
+ test))
+ {
+ if (test) {
+ glEnable(GL_STENCIL_TEST);
+
+ /* Stencil Write */
+ if ((state & DRW_STATE_WRITE_STENCIL) != 0) {
+ glStencilMask(0xFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ }
+ /* Stencil Test */
+ else if ((state & DRW_STATE_STENCIL_EQUAL) != 0) {
+ glStencilMask(0x00); /* disable write */
+ DST.stencil_mask = 0;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ /* disable write & test */
+ DST.stencil_mask = 0;
+ glStencilMask(0x00);
+ glStencilFunc(GL_ALWAYS, 1, 0xFF);
+ glDisable(GL_STENCIL_TEST);
+ }
+ }
+ }
+
+#undef CHANGED_TO
+#undef CHANGED_ANY
+#undef CHANGED_ANY_STORE_VAR
+
+ DST.state = state;
+}
+
+static void drw_stencil_set(unsigned int mask)
+{
+ if (DST.stencil_mask != mask) {
+ /* Stencil Write */
+ if ((DST.state & DRW_STATE_WRITE_STENCIL) != 0) {
+ glStencilFunc(GL_ALWAYS, mask, 0xFF);
+ DST.stencil_mask = mask;
+ }
+ /* Stencil Test */
+ else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) {
+ glStencilFunc(GL_EQUAL, mask, 0xFF);
+ DST.stencil_mask = mask;
+ }
+ }
+}
+
+typedef struct DRWBoundTexture {
+ struct DRWBoundTexture *next, *prev;
+ GPUTexture *tex;
+} DRWBoundTexture;
+
+static void draw_geometry_prepare(
+ DRWShadingGroup *shgroup, const float (*obmat)[4], const float *texcoloc, const float *texcosize)
+{
+ RegionView3D *rv3d = DST.draw_ctx.rv3d;
+ DRWInterface *interface = &shgroup->interface;
+
+ float mvp[4][4], mv[4][4], mi[4][4], mvi[4][4], pi[4][4], n[3][3], wn[3][3];
+ float orcofacs[2][3] = {{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}};
+ float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */
+
+ bool do_pi = (interface->projectioninverse != -1);
+ bool do_mvp = (interface->modelviewprojection != -1);
+ bool do_mi = (interface->modelinverse != -1);
+ bool do_mv = (interface->modelview != -1);
+ bool do_mvi = (interface->modelviewinverse != -1);
+ bool do_n = (interface->normal != -1);
+ bool do_wn = (interface->worldnormal != -1);
+ bool do_eye = (interface->eye != -1);
+ bool do_orco = (interface->orcotexfac != -1) && (texcoloc != NULL) && (texcosize != NULL);
+
+ /* Matrix override */
+ float (*persmat)[4];
+ float (*persinv)[4];
+ float (*viewmat)[4];
+ float (*viewinv)[4];
+ float (*winmat)[4];
+ float (*wininv)[4];
+
+ persmat = (viewport_matrix_override.override[DRW_MAT_PERS])
+ ? viewport_matrix_override.mat[DRW_MAT_PERS] : rv3d->persmat;
+ persinv = (viewport_matrix_override.override[DRW_MAT_PERSINV])
+ ? viewport_matrix_override.mat[DRW_MAT_PERSINV] : rv3d->persinv;
+ viewmat = (viewport_matrix_override.override[DRW_MAT_VIEW])
+ ? viewport_matrix_override.mat[DRW_MAT_VIEW] : rv3d->viewmat;
+ viewinv = (viewport_matrix_override.override[DRW_MAT_VIEWINV])
+ ? viewport_matrix_override.mat[DRW_MAT_VIEWINV] : rv3d->viewinv;
+ winmat = (viewport_matrix_override.override[DRW_MAT_WIN])
+ ? viewport_matrix_override.mat[DRW_MAT_WIN] : rv3d->winmat;
+ wininv = viewport_matrix_override.mat[DRW_MAT_WININV];
+
+ if (do_pi) {
+ if (!viewport_matrix_override.override[DRW_MAT_WININV]) {
+ invert_m4_m4(pi, winmat);
+ wininv = pi;
+ }
+ }
+ if (do_mi) {
+ invert_m4_m4(mi, obmat);
+ }
+ if (do_mvp) {
+ mul_m4_m4m4(mvp, persmat, obmat);
+ }
+ if (do_mv || do_mvi || do_n || do_eye) {
+ mul_m4_m4m4(mv, viewmat, obmat);
+ }
+ if (do_mvi) {
+ invert_m4_m4(mvi, mv);
+ }
+ if (do_n || do_eye) {
+ copy_m3_m4(n, mv);
+ invert_m3(n);
+ transpose_m3(n);
+ }
+ if (do_wn) {
+ copy_m3_m4(wn, obmat);
+ invert_m3(wn);
+ transpose_m3(wn);
+ }
+ 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);
+ }
+ if (do_orco) {
+ mul_v3_v3fl(orcofacs[1], texcosize, 2.0f);
+ invert_v3(orcofacs[1]);
+ sub_v3_v3v3(orcofacs[0], texcoloc, texcosize);
+ negate_v3(orcofacs[0]);
+ mul_v3_v3(orcofacs[0], orcofacs[1]); /* result in a nice MADD in the shader */
+ }
+
+ /* Should be really simple */
+ /* step 1 : bind object dependent matrices */
+ /* TODO : Some of these are not object dependant.
+ * They should be grouped inside a UBO updated once per redraw.
+ * The rest can also go into a UBO to reduce API calls. */
+ GPU_shader_uniform_vector(shgroup->shader, interface->model, 16, 1, (float *)obmat);
+ GPU_shader_uniform_vector(shgroup->shader, interface->modelinverse, 16, 1, (float *)mi);
+ GPU_shader_uniform_vector(shgroup->shader, interface->modelviewprojection, 16, 1, (float *)mvp);
+ GPU_shader_uniform_vector(shgroup->shader, interface->viewinverse, 16, 1, (float *)viewinv);
+ GPU_shader_uniform_vector(shgroup->shader, interface->viewprojection, 16, 1, (float *)persmat);
+ GPU_shader_uniform_vector(shgroup->shader, interface->viewprojectioninverse, 16, 1, (float *)persinv);
+ GPU_shader_uniform_vector(shgroup->shader, interface->projection, 16, 1, (float *)winmat);
+ GPU_shader_uniform_vector(shgroup->shader, interface->projectioninverse, 16, 1, (float *)wininv);
+ GPU_shader_uniform_vector(shgroup->shader, interface->view, 16, 1, (float *)viewmat);
+ GPU_shader_uniform_vector(shgroup->shader, interface->modelview, 16, 1, (float *)mv);
+ GPU_shader_uniform_vector(shgroup->shader, interface->modelviewinverse, 16, 1, (float *)mvi);
+ GPU_shader_uniform_vector(shgroup->shader, interface->normal, 9, 1, (float *)n);
+ GPU_shader_uniform_vector(shgroup->shader, interface->worldnormal, 9, 1, (float *)wn);
+ GPU_shader_uniform_vector(shgroup->shader, interface->camtexfac, 4, 1, (float *)rv3d->viewcamtexcofac);
+ GPU_shader_uniform_vector(shgroup->shader, interface->orcotexfac, 3, 2, (float *)orcofacs);
+ GPU_shader_uniform_vector(shgroup->shader, interface->eye, 3, 1, (float *)eye);
+ GPU_shader_uniform_vector(shgroup->shader, interface->clipplanes, 4, DST.num_clip_planes, (float *)DST.clip_planes_eq);
+}
+
+static void draw_geometry_execute(DRWShadingGroup *shgroup, Gwn_Batch *geom)
+{
+ DRWInterface *interface = &shgroup->interface;
+ /* step 2 : bind vertex array & draw */
+ GWN_batch_program_set(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
+ if (interface->instance_batch) {
+ GWN_batch_draw_stupid_instanced_with_batch(geom, interface->instance_batch);
+ }
+ else if (interface->instance_vbo) {
+ GWN_batch_draw_stupid_instanced(
+ geom, interface->instance_vbo, interface->instance_count, interface->attribs_count,
+ interface->attribs_stride, interface->attribs_size, interface->attribs_loc);
+ }
+ else {
+ GWN_batch_draw_stupid(geom);
+ }
+ /* XXX this just tells gawain we are done with the shader.
+ * This does not unbind the shader. */
+ GWN_batch_program_unset(geom);
+}
+
+static void draw_geometry(DRWShadingGroup *shgroup, Gwn_Batch *geom, const float (*obmat)[4], ID *ob_data)
+{
+ float *texcoloc = NULL;
+ float *texcosize = NULL;
+
+ if (ob_data != NULL) {
+ switch (GS(ob_data->name)) {
+ case ID_ME:
+ BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, NULL, &texcosize);
+ break;
+ default:
+ /* TODO, curve, metaball? */
+ break;
+ }
+ }
+
+ draw_geometry_prepare(shgroup, obmat, texcoloc, texcosize);
+
+ draw_geometry_execute(shgroup, geom);
+}
+
+static void bind_texture(GPUTexture *tex)
+{
+ int bind_num = GPU_texture_bound_number(tex);
+ if (bind_num == -1) {
+ for (int i = 0; i < GPU_max_textures(); ++i) {
+ RST.bind_tex_inc = (RST.bind_tex_inc + 1) % GPU_max_textures();
+ if (RST.bound_tex_slots[RST.bind_tex_inc] == false) {
+ if (RST.bound_texs[RST.bind_tex_inc] != NULL) {
+ GPU_texture_unbind(RST.bound_texs[RST.bind_tex_inc]);
+ }
+ GPU_texture_bind(tex, RST.bind_tex_inc);
+ RST.bound_texs[RST.bind_tex_inc] = tex;
+ RST.bound_tex_slots[RST.bind_tex_inc] = true;
+ return;
+ }
+ }
+
+ printf("Not enough texture slots! Reduce number of textures used by your shader.\n");
+ }
+ RST.bound_tex_slots[bind_num] = true;
+}
+
+static void bind_ubo(GPUUniformBuffer *ubo)
+{
+ if (RST.bind_ubo_inc < GPU_max_ubo_binds()) {
+ GPU_uniformbuffer_bind(ubo, RST.bind_ubo_inc);
+ RST.bind_ubo_inc++;
+ }
+ else {
+ /* This is not depending on user input.
+ * It is our responsability to make sure there enough slots. */
+ BLI_assert(0 && "Not enough ubo slots! This should not happen!\n");
+
+ /* printf so user can report bad behaviour */
+ printf("Not enough ubo slots! This should not happen!\n");
+ }
+}
+
+static void release_texture_slots(void)
+{
+ memset(RST.bound_tex_slots, 0x0, sizeof(bool) * GPU_max_textures());
+}
+
+static void release_ubo_slots(void)
+{
+ RST.bind_ubo_inc = 0;
+}
+
+static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
+{
+ BLI_assert(shgroup->shader);
+
+ DRWInterface *interface = &shgroup->interface;
+ GPUTexture *tex;
+ GPUUniformBuffer *ubo;
+ int val;
+ float fval;
+
+ if (DST.shader != shgroup->shader) {
+ if (DST.shader) GPU_shader_unbind();
+ GPU_shader_bind(shgroup->shader);
+ DST.shader = shgroup->shader;
+ }
+
+ const bool is_normal = ELEM(shgroup->type, DRW_SHG_NORMAL);
+
+ if (!is_normal) {
+ shgroup_dynamic_batch_from_calls(shgroup);
+ }
+
+ release_texture_slots();
+ release_ubo_slots();
+
+ drw_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra);
+ drw_stencil_set(shgroup->stencil_mask);
+
+ /* Binding Uniform */
+ /* Don't check anything, Interface should already contain the least uniform as possible */
+ for (DRWUniform *uni = interface->uniforms; uni; uni = uni->next) {
+ switch (uni->type) {
+ case DRW_UNIFORM_SHORT_TO_INT:
+ val = (int)*((short *)uni->value);
+ GPU_shader_uniform_vector_int(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)&val);
+ break;
+ case DRW_UNIFORM_SHORT_TO_FLOAT:
+ fval = (float)*((short *)uni->value);
+ GPU_shader_uniform_vector(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)&fval);
+ break;
+ 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:
+ tex = (GPUTexture *)uni->value;
+ BLI_assert(tex);
+ bind_texture(tex);
+ GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
+ break;
+ case DRW_UNIFORM_BUFFER:
+ if (!DRW_state_is_fbo()) {
+ break;
+ }
+ tex = *((GPUTexture **)uni->value);
+ BLI_assert(tex);
+ bind_texture(tex);
+ GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
+ break;
+ case DRW_UNIFORM_BLOCK:
+ ubo = (GPUUniformBuffer *)uni->value;
+ bind_ubo(ubo);
+ GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ break;
+ }
+ }
+
+#ifdef USE_GPU_SELECT
+ /* use the first item because of selection we only ever add one */
+# define GPU_SELECT_LOAD_IF_PICKSEL(_call) \
+ if ((G.f & G_PICKSEL) && (_call)) { \
+ GPU_select_load_id((_call)->head.select_id); \
+ } ((void)0)
+
+# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_call_last, _call_first) \
+ if ((G.f & G_PICKSEL) && _call_first) { \
+ BLI_assert(_call_first && (_call_first == _call_last)); \
+ GPU_select_load_id(((DRWCall *)_call_first)->head.select_id); \
+ } ((void)0)
+
+#else
+# define GPU_SELECT_LOAD_IF_PICKSEL(call)
+# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(call, _call_first)
+#endif
+
+ /* Rendering Calls */
+ if (!is_normal) {
+ /* Replacing multiple calls with only one */
+ float obmat[4][4];
+ unit_m4(obmat);
+
+ if (shgroup->type == DRW_SHG_INSTANCE &&
+ (interface->instance_count > 0 || interface->instance_batch != NULL))
+ {
+ GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup->calls, shgroup->calls_first);
+ draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data);
+ }
+ else {
+ /* Some dynamic batch can have no geom (no call to aggregate) */
+ if (shgroup->batch_geom) {
+ GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup->calls, shgroup->calls_first);
+ draw_geometry(shgroup, shgroup->batch_geom, obmat, NULL);
+ }
+ }
+ }
+ else {
+ for (DRWCall *call = shgroup->calls_first; call; call = call->head.prev) {
+ bool neg_scale = is_negative_m4(call->obmat);
+
+ /* Negative scale objects */
+ if (neg_scale) {
+ glFrontFace(DST.backface);
+ }
+
+ GPU_SELECT_LOAD_IF_PICKSEL(call);
+
+ if (call->head.type == DRW_CALL_SINGLE) {
+ draw_geometry(shgroup, call->geometry, call->obmat, call->ob_data);
+ }
+ else {
+ BLI_assert(call->head.type == DRW_CALL_GENERATE);
+ DRWCallGenerate *callgen = ((DRWCallGenerate *)call);
+ draw_geometry_prepare(shgroup, callgen->obmat, NULL, NULL);
+ callgen->geometry_fn(shgroup, draw_geometry_execute, callgen->user_data);
+ }
+
+ /* Reset state */
+ if (neg_scale) {
+ glFrontFace(DST.frontface);
+ }
+ }
+ }
+
+ /* TODO: remove, (currently causes alpha issue with sculpt, need to investigate) */
+ DRW_state_reset();
+}
+
+static void drw_draw_pass_ex(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group)
+{
+ /* Start fresh */
+ DST.shader = NULL;
+
+ drw_state_set(pass->state);
+
+ DRW_stats_query_start(pass->name);
+
+ for (DRWShadingGroup *shgroup = start_group; shgroup; shgroup = shgroup->next) {
+ draw_shgroup(shgroup, pass->state);
+ /* break if upper limit */
+ if (shgroup == end_group) {
+ break;
+ }
+ }
+
+ /* Clear Bound textures */
+ for (int i = 0; i < GPU_max_textures(); i++) {
+ if (RST.bound_texs[i] != NULL) {
+ GPU_texture_unbind(RST.bound_texs[i]);
+ RST.bound_texs[i] = NULL;
+ }
+ }
+
+ if (DST.shader) {
+ GPU_shader_unbind();
+ DST.shader = NULL;
+ }
+
+ DRW_stats_query_end();
+}
+
+void DRW_draw_pass(DRWPass *pass)
+{
+ drw_draw_pass_ex(pass, pass->shgroups, pass->shgroups_last);
+}
+
+/* Draw only a subset of shgroups. Used in special situations as grease pencil strokes */
+void DRW_draw_pass_subset(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group)
+{
+ drw_draw_pass_ex(pass, start_group, end_group);
+}
+
+void DRW_draw_callbacks_pre_scene(void)
+{
+ RegionView3D *rv3d = DST.draw_ctx.rv3d;
+
+ gpuLoadProjectionMatrix(rv3d->winmat);
+ gpuLoadMatrix(rv3d->viewmat);
+}
+
+void DRW_draw_callbacks_post_scene(void)
+{
+ RegionView3D *rv3d = DST.draw_ctx.rv3d;
+
+ gpuLoadProjectionMatrix(rv3d->winmat);
+ gpuLoadMatrix(rv3d->viewmat);
+}
+
+/* Reset state to not interfer with other UI drawcall */
+void DRW_state_reset_ex(DRWState state)
+{
+ DST.state = ~state;
+ drw_state_set(state);
+}
+
+void DRW_state_reset(void)
+{
+ /* Reset blending function */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ DRW_state_reset_ex(DRW_STATE_DEFAULT);
+}
+
+/* NOTE : Make sure to reset after use! */
+void DRW_state_invert_facing(void)
+{
+ SWAP(GLenum, DST.backface, DST.frontface);
+ glFrontFace(DST.frontface);
+}
+
+/**
+ * This only works if DRWPasses have been tagged with DRW_STATE_CLIP_PLANES,
+ * and if the shaders have support for it (see usage of gl_ClipDistance).
+ * Be sure to call DRW_state_clip_planes_reset() after you finish drawing.
+ **/
+void DRW_state_clip_planes_add(float plane_eq[4])
+{
+ copy_v4_v4(DST.clip_planes_eq[DST.num_clip_planes++], plane_eq);
+}
+
+void DRW_state_clip_planes_reset(void)
+{
+ DST.num_clip_planes = 0;
+}
+
+/** \} */
+
+
+struct DRWTextStore *DRW_text_cache_ensure(void)
+{
+ BLI_assert(DST.text_store_p);
+ if (*DST.text_store_p == NULL) {
+ *DST.text_store_p = DRW_text_cache_create();
+ }
+ return *DST.text_store_p;
+}
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Settings
+ * \{ */
+
+bool DRW_object_is_renderable(Object *ob)
+{
+ Scene *scene = DST.draw_ctx.scene;
+ Object *obedit = scene->obedit;
+
+ if (!BKE_object_is_visible(ob)) {
+ return false;
+ }
+
+ if (ob->type == OB_MESH) {
+ if (ob == obedit) {
+ IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_EDIT, "");
+ bool do_show_occlude_wire = BKE_collection_engine_property_value_get_bool(props, "show_occlude_wire");
+ if (do_show_occlude_wire) {
+ return false;
+ }
+ bool do_show_weight = BKE_collection_engine_property_value_get_bool(props, "show_weight");
+ if (do_show_weight) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool DRW_object_is_flat_normal(const Object *ob)
+{
+ if (ob->type == OB_MESH) {
+ const Mesh *me = ob->data;
+ if (me->mpoly && me->mpoly[0].flag & ME_SMOOTH) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+/**
+ * Return true if the object has its own draw mode.
+ * Caller must check this is active */
+int DRW_object_is_mode_shade(const Object *ob)
+{
+ BLI_assert(ob == DST.draw_ctx.obact);
+ if ((ob->mode & OB_MODE_EDIT) == 0) {
+ if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) {
+ if ((DST.draw_ctx.v3d->flag2 & V3D_SHOW_MODE_SHADE_OVERRIDE) == 0) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ return -1;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Framebuffers (DRW_framebuffer)
+ * \{ */
+
+static GPUTextureFormat convert_tex_format(
+ int fbo_format,
+ int *r_channels, bool *r_is_depth)
+{
+ *r_is_depth = ELEM(fbo_format, DRW_TEX_DEPTH_16, DRW_TEX_DEPTH_24, DRW_TEX_DEPTH_24_STENCIL_8);
+
+ switch (fbo_format) {
+ case DRW_TEX_R_16: *r_channels = 1; return GPU_R16F;
+ case DRW_TEX_R_32: *r_channels = 1; return GPU_R32F;
+ case DRW_TEX_RG_8: *r_channels = 2; return GPU_RG8;
+ case DRW_TEX_RG_16: *r_channels = 2; return GPU_RG16F;
+ case DRW_TEX_RG_32: *r_channels = 2; return GPU_RG32F;
+ case DRW_TEX_RGBA_8: *r_channels = 4; return GPU_RGBA8;
+ case DRW_TEX_RGBA_16: *r_channels = 4; return GPU_RGBA16F;
+ case DRW_TEX_RGBA_32: *r_channels = 4; return GPU_RGBA32F;
+ case DRW_TEX_DEPTH_16: *r_channels = 1; return GPU_DEPTH_COMPONENT16;
+ case DRW_TEX_DEPTH_24: *r_channels = 1; return GPU_DEPTH_COMPONENT24;
+ case DRW_TEX_DEPTH_24_STENCIL_8: *r_channels = 1; return GPU_DEPTH24_STENCIL8;
+ case DRW_TEX_DEPTH_32: *r_channels = 1; return GPU_DEPTH_COMPONENT32F;
+ case DRW_TEX_RGB_11_11_10: *r_channels = 3; return GPU_R11F_G11F_B10F;
+ default:
+ BLI_assert(false && "Texture format unsupported as render target!");
+ *r_channels = 4; return GPU_RGBA8;
+ }
+}
+
+void DRW_framebuffer_init(
+ struct GPUFrameBuffer **fb, void *engine_type, int width, int height,
+ DRWFboTexture textures[MAX_FBO_TEX], int textures_len)
+{
+ BLI_assert(textures_len <= MAX_FBO_TEX);
+
+ bool create_fb = false;
+ int color_attachment = -1;
+
+ if (!*fb) {
+ *fb = GPU_framebuffer_create();
+ create_fb = true;
+ }
+
+ for (int i = 0; i < textures_len; ++i) {
+ int channels;
+ bool is_depth;
+
+ DRWFboTexture fbotex = textures[i];
+ bool is_temp = (fbotex.flag & DRW_TEX_TEMP) != 0;
+
+ GPUTextureFormat gpu_format = convert_tex_format(fbotex.format, &channels, &is_depth);
+
+ if (!*fbotex.tex || is_temp) {
+ /* Temp textures need to be queried each frame, others not. */
+ if (is_temp) {
+ *fbotex.tex = GPU_viewport_texture_pool_query(
+ DST.viewport, engine_type, width, height, channels, gpu_format);
+ }
+ else if (create_fb) {
+ *fbotex.tex = GPU_texture_create_2D_custom(
+ width, height, channels, gpu_format, NULL, NULL);
+ }
+ }
+
+ if (create_fb) {
+ if (!is_depth) {
+ ++color_attachment;
+ }
+ drw_texture_set_parameters(*fbotex.tex, fbotex.flag);
+ GPU_framebuffer_texture_attach(*fb, *fbotex.tex, color_attachment, 0);
+ }
+ }
+
+ if (create_fb && (textures_len > 0)) {
+ if (!GPU_framebuffer_check_valid(*fb, NULL)) {
+ printf("Error invalid framebuffer\n");
+ }
+
+ /* Detach temp textures */
+ for (int i = 0; i < textures_len; ++i) {
+ DRWFboTexture fbotex = textures[i];
+
+ if ((fbotex.flag & DRW_TEX_TEMP) != 0) {
+ GPU_framebuffer_texture_detach(*fbotex.tex);
+ }
+ }
+
+ GPU_framebuffer_bind(DST.default_framebuffer);
+ }
+}
+
+void DRW_framebuffer_free(struct GPUFrameBuffer *fb)
+{
+ GPU_framebuffer_free(fb);
+}
+
+void DRW_framebuffer_bind(struct GPUFrameBuffer *fb)
+{
+ GPU_framebuffer_bind(fb);
+}
+
+void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth)
+{
+ if (color) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
+ }
+ if (depth) {
+ glDepthMask(GL_TRUE);
+ glClearDepth(clear_depth);
+ }
+ if (stencil) {
+ glStencilMask(0xFF);
+ }
+ glClear(((color) ? GL_COLOR_BUFFER_BIT : 0) |
+ ((depth) ? GL_DEPTH_BUFFER_BIT : 0) |
+ ((stencil) ? GL_STENCIL_BUFFER_BIT : 0));
+}
+
+void DRW_framebuffer_read_data(int x, int y, int w, int h, int channels, int slot, float *data)
+{
+ GLenum type;
+ switch (channels) {
+ case 1: type = GL_RED; break;
+ case 2: type = GL_RG; break;
+ case 3: type = GL_RGB; break;
+ case 4: type = GL_RGBA; break;
+ default:
+ BLI_assert(false && "wrong number of read channels");
+ return;
+ }
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
+}
+
+void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
+{
+ GPU_framebuffer_texture_attach(fb, tex, slot, mip);
+}
+
+void DRW_framebuffer_texture_layer_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip)
+{
+ GPU_framebuffer_texture_layer_attach(fb, tex, slot, layer, mip);
+}
+
+void DRW_framebuffer_cubeface_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
+{
+ GPU_framebuffer_texture_cubeface_attach(fb, tex, slot, face, mip);
+}
+
+void DRW_framebuffer_texture_detach(GPUTexture *tex)
+{
+ GPU_framebuffer_texture_detach(tex);
+}
+
+void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth, bool stencil)
+{
+ GPU_framebuffer_blit(fb_read, 0, fb_write, 0, depth, stencil);
+}
+
+void DRW_framebuffer_recursive_downsample(
+ struct GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
+ void (*callback)(void *userData, int level), void *userData)
+{
+ GPU_framebuffer_recursive_downsample(fb, tex, num_iter, callback, userData);
+}
+
+void DRW_framebuffer_viewport_size(struct GPUFrameBuffer *UNUSED(fb_read), int x, int y, int w, int h)
+{
+ glViewport(x, y, w, h);
+}
+
+/* Use color management profile to draw texture to framebuffer */
+void DRW_transform_to_display(GPUTexture *tex)
+{
+ drw_state_set(DRW_STATE_WRITE_COLOR);
+
+ Gwn_VertFormat *vert_format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(vert_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int texco = GWN_vertformat_attr_add(vert_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ const float dither = 1.0f;
+
+ bool use_ocio = false;
+
+ {
+ Scene *scene = DST.draw_ctx.scene;
+ /* View transform is already applied for offscreen, don't apply again, see: T52046 */
+ ColorManagedViewSettings *view_settings =
+ (DST.options.is_image_render && !DST.options.is_scene_render) ?
+ NULL : &scene->view_settings;
+ use_ocio = IMB_colormanagement_setup_glsl_draw_from_space(
+ view_settings, &scene->display_settings, NULL, dither, false);
+ }
+
+ if (!use_ocio) {
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB);
+ immUniform1i("image", 0);
+ }
+
+ GPU_texture_bind(tex, 0); /* OCIO texture bind point is 0 */
+
+ float mat[4][4];
+ unit_m4(mat);
+ immUniformMatrix4fv("ModelViewProjectionMatrix", mat);
+
+ /* Full screen triangle */
+ immBegin(GWN_PRIM_TRIS, 3);
+ immAttrib2f(texco, 0.0f, 0.0f);
+ immVertex2f(pos, -1.0f, -1.0f);
+
+ immAttrib2f(texco, 2.0f, 0.0f);
+ immVertex2f(pos, 3.0f, -1.0f);
+
+ immAttrib2f(texco, 0.0f, 2.0f);
+ immVertex2f(pos, -1.0f, 3.0f);
+ immEnd();
+
+ GPU_texture_unbind(tex);
+
+ if (use_ocio) {
+ IMB_colormanagement_finish_glsl_draw();
+ }
+ else {
+ immUnbindProgram();
+ }
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Viewport (DRW_viewport)
+ * \{ */
+
+static void *DRW_viewport_engine_data_ensure(void *engine_type)
+{
+ void *data = GPU_viewport_engine_data_get(DST.viewport, engine_type);
+
+ if (data == NULL) {
+ data = GPU_viewport_engine_data_create(DST.viewport, engine_type);
+ }
+ return data;
+}
+
+void DRW_engine_viewport_data_size_get(
+ const void *engine_type_v,
+ int *r_fbl_len, int *r_txl_len, int *r_psl_len, int *r_stl_len)
+{
+ const DrawEngineType *engine_type = engine_type_v;
+
+ if (r_fbl_len) {
+ *r_fbl_len = engine_type->vedata_size->fbl_len;
+ }
+ if (r_txl_len) {
+ *r_txl_len = engine_type->vedata_size->txl_len;
+ }
+ if (r_psl_len) {
+ *r_psl_len = engine_type->vedata_size->psl_len;
+ }
+ if (r_stl_len) {
+ *r_stl_len = engine_type->vedata_size->stl_len;
+ }
+}
+
+const float *DRW_viewport_size_get(void)
+{
+ return &DST.size[0];
+}
+
+const float *DRW_viewport_screenvecs_get(void)
+{
+ return &DST.screenvecs[0][0];
+}
+
+const float *DRW_viewport_pixelsize_get(void)
+{
+ return &DST.pixsize;
+}
+
+static void drw_viewport_cache_resize(void)
+{
+ /* Release the memiter before clearing the mempools that references them */
+ GPU_viewport_cache_release(DST.viewport);
+
+ if (DST.vmempool != NULL) {
+ BLI_mempool_clear_ex(DST.vmempool->calls, BLI_mempool_count(DST.vmempool->calls));
+ BLI_mempool_clear_ex(DST.vmempool->calls_generate, BLI_mempool_count(DST.vmempool->calls_generate));
+ BLI_mempool_clear_ex(DST.vmempool->calls_dynamic, BLI_mempool_count(DST.vmempool->calls_dynamic));
+ BLI_mempool_clear_ex(DST.vmempool->shgroups, BLI_mempool_count(DST.vmempool->shgroups));
+ BLI_mempool_clear_ex(DST.vmempool->uniforms, BLI_mempool_count(DST.vmempool->uniforms));
+ BLI_mempool_clear_ex(DST.vmempool->attribs, BLI_mempool_count(DST.vmempool->attribs));
+ BLI_mempool_clear_ex(DST.vmempool->passes, BLI_mempool_count(DST.vmempool->passes));
+ }
+}
+
+/* It also stores viewport variable to an immutable place: DST
+ * This is because a cache uniform only store reference
+ * to its value. And we don't want to invalidate the cache
+ * if this value change per viewport */
+static void drw_viewport_var_init(void)
+{
+ RegionView3D *rv3d = DST.draw_ctx.rv3d;
+
+ /* Refresh DST.size */
+ if (DST.viewport) {
+ int size[2];
+ GPU_viewport_size_get(DST.viewport, size);
+ DST.size[0] = size[0];
+ DST.size[1] = size[1];
+
+ DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(DST.viewport);
+ DST.default_framebuffer = fbl->default_fb;
+
+ DST.vmempool = GPU_viewport_mempool_get(DST.viewport);
+
+ if (DST.vmempool->calls == NULL) {
+ DST.vmempool->calls = BLI_mempool_create(sizeof(DRWCall), 0, 512, 0);
+ }
+ if (DST.vmempool->calls_generate == NULL) {
+ DST.vmempool->calls_generate = BLI_mempool_create(sizeof(DRWCallGenerate), 0, 512, 0);
+ }
+ if (DST.vmempool->calls_dynamic == NULL) {
+ DST.vmempool->calls_dynamic = BLI_mempool_create(sizeof(DRWCallDynamic), 0, 512, 0);
+ }
+ if (DST.vmempool->shgroups == NULL) {
+ DST.vmempool->shgroups = BLI_mempool_create(sizeof(DRWShadingGroup), 0, 256, 0);
+ }
+ if (DST.vmempool->uniforms == NULL) {
+ DST.vmempool->uniforms = BLI_mempool_create(sizeof(DRWUniform), 0, 512, 0);
+ }
+ if (DST.vmempool->attribs == NULL) {
+ DST.vmempool->attribs = BLI_mempool_create(sizeof(DRWAttrib), 0, 256, 0);
+ }
+ if (DST.vmempool->passes == NULL) {
+ DST.vmempool->passes = BLI_mempool_create(sizeof(DRWPass), 0, 64, 0);
+ }
+ }
+ else {
+ DST.size[0] = 0;
+ DST.size[1] = 0;
+
+ DST.default_framebuffer = NULL;
+ DST.vmempool = NULL;
+ }
+ /* 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;
+
+ /* Reset facing */
+ DST.frontface = GL_CCW;
+ DST.backface = GL_CW;
+ glFrontFace(DST.frontface);
+
+ if (DST.draw_ctx.scene->obedit) {
+ ED_view3d_init_mats_rv3d(DST.draw_ctx.scene->obedit, rv3d);
+ }
+
+ /* Alloc array of texture reference. */
+ if (RST.bound_texs == NULL) {
+ RST.bound_texs = MEM_callocN(sizeof(GPUTexture *) * GPU_max_textures(), "Bound GPUTexture refs");
+ }
+ if (RST.bound_tex_slots == NULL) {
+ RST.bound_tex_slots = MEM_callocN(sizeof(bool) * GPU_max_textures(), "Bound Texture Slots");
+ }
+
+ memset(viewport_matrix_override.override, 0x0, sizeof(viewport_matrix_override.override));
+}
+
+void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type)
+{
+ RegionView3D *rv3d = DST.draw_ctx.rv3d;
+ BLI_assert(type >= DRW_MAT_PERS && type <= DRW_MAT_WININV);
+
+ if (viewport_matrix_override.override[type]) {
+ copy_m4_m4(mat, viewport_matrix_override.mat[type]);
+ }
+ else {
+ switch (type) {
+ case DRW_MAT_PERS:
+ copy_m4_m4(mat, rv3d->persmat);
+ break;
+ case DRW_MAT_PERSINV:
+ copy_m4_m4(mat, rv3d->persinv);
+ break;
+ case DRW_MAT_VIEW:
+ copy_m4_m4(mat, rv3d->viewmat);
+ break;
+ case DRW_MAT_VIEWINV:
+ copy_m4_m4(mat, rv3d->viewinv);
+ break;
+ case DRW_MAT_WIN:
+ copy_m4_m4(mat, rv3d->winmat);
+ break;
+ case DRW_MAT_WININV:
+ invert_m4_m4(mat, rv3d->winmat);
+ break;
+ default:
+ BLI_assert(!"Matrix type invalid");
+ break;
+ }
+ }
+}
+
+void DRW_viewport_matrix_override_set(float mat[4][4], DRWViewportMatrixType type)
+{
+ copy_m4_m4(viewport_matrix_override.mat[type], mat);
+ viewport_matrix_override.override[type] = true;
+}
+
+void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type)
+{
+ viewport_matrix_override.override[type] = false;
+}
+
+bool DRW_viewport_is_persp_get(void)
+{
+ RegionView3D *rv3d = DST.draw_ctx.rv3d;
+ return rv3d->is_persp;
+}
+
+DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void)
+{
+ return GPU_viewport_framebuffer_list_get(DST.viewport);
+}
+
+DefaultTextureList *DRW_viewport_texture_list_get(void)
+{
+ return GPU_viewport_texture_list_get(DST.viewport);
+}
+
+void DRW_viewport_request_redraw(void)
+{
+ GPU_viewport_tag_update(DST.viewport);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name ViewLayers (DRW_scenelayer)
+ * \{ */
+
+void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type)
+{
+ for (ViewLayerEngineData *sled = DST.draw_ctx.view_layer->drawdata.first; sled; sled = sled->next) {
+ if (sled->engine_type == engine_type) {
+ return sled->storage;
+ }
+ }
+ return NULL;
+}
+
+void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*callback)(void *storage))
+{
+ ViewLayerEngineData *sled;
+
+ for (sled = DST.draw_ctx.view_layer->drawdata.first; sled; sled = sled->next) {
+ if (sled->engine_type == engine_type) {
+ return &sled->storage;
+ }
+ }
+
+ sled = MEM_callocN(sizeof(ViewLayerEngineData), "ViewLayerEngineData");
+ sled->engine_type = engine_type;
+ sled->free = callback;
+ BLI_addtail(&DST.draw_ctx.view_layer->drawdata, sled);
+
+ return &sled->storage;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Objects (DRW_object)
+ * \{ */
+
+void *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type)
+{
+ for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) {
+ if (oed->engine_type == engine_type) {
+ return oed->storage;
+ }
+ }
+ return NULL;
+}
+
+void **DRW_object_engine_data_ensure(
+ Object *ob, DrawEngineType *engine_type, void (*callback)(void *storage))
+{
+ ObjectEngineData *oed;
+
+ for (oed = ob->drawdata.first; oed; oed = oed->next) {
+ if (oed->engine_type == engine_type) {
+ return &oed->storage;
+ }
+ }
+
+ oed = MEM_callocN(sizeof(ObjectEngineData), "ObjectEngineData");
+ oed->engine_type = engine_type;
+ oed->free = callback;
+ BLI_addtail(&ob->drawdata, oed);
+
+ return &oed->storage;
+}
+
+/* XXX There is definitly some overlap between this and DRW_object_engine_data_ensure.
+ * We should get rid of one of the two. */
+LampEngineData *DRW_lamp_engine_data_ensure(Object *ob, RenderEngineType *engine_type)
+{
+ BLI_assert(ob->type == OB_LAMP);
+
+ Scene *scene = DST.draw_ctx.scene;
+
+ /* TODO Dupliobjects */
+ /* TODO Should be per scenelayer */
+ return GPU_lamp_engine_data_get(scene, ob, NULL, engine_type);
+}
+
+void DRW_lamp_engine_data_free(LampEngineData *led)
+{
+ GPU_lamp_engine_data_free(led);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Rendering (DRW_engines)
+ * \{ */
+
+static void drw_engines_init(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ PROFILE_START(stime);
+
+ if (engine->engine_init) {
+ engine->engine_init(data);
+ }
+
+ PROFILE_END_UPDATE(data->init_time, stime);
+ }
+}
+
+static void drw_engines_cache_init(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+
+ if (data->text_draw_cache) {
+ DRW_text_cache_destroy(data->text_draw_cache);
+ data->text_draw_cache = NULL;
+ }
+ if (DST.text_store_p == NULL) {
+ DST.text_store_p = &data->text_draw_cache;
+ }
+
+ if (engine->cache_init) {
+ engine->cache_init(data);
+ }
+ }
+}
+
+static void drw_engines_cache_populate(Object *ob)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+
+ if (engine->cache_populate) {
+ engine->cache_populate(data, ob);
+ }
+ }
+}
+
+static void drw_engines_cache_finish(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+
+ if (engine->cache_finish) {
+ engine->cache_finish(data);
+ }
+ }
+}
+
+static void drw_engines_draw_background(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+
+ if (engine->draw_background) {
+ PROFILE_START(stime);
+
+ DRW_stats_group_start(engine->idname);
+ engine->draw_background(data);
+ DRW_stats_group_end();
+
+ PROFILE_END_UPDATE(data->background_time, stime);
+ return;
+ }
+ }
+
+ /* No draw_background found, doing default background */
+ DRW_draw_background();
+}
+
+static void drw_engines_draw_scene(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ PROFILE_START(stime);
+
+ if (engine->draw_scene) {
+ DRW_stats_group_start(engine->idname);
+ engine->draw_scene(data);
+ DRW_stats_group_end();
+ }
+
+ PROFILE_END_UPDATE(data->render_time, stime);
+ }
+}
+
+static void drw_engines_draw_text(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ PROFILE_START(stime);
+
+ if (data->text_draw_cache) {
+ DRW_text_cache_draw(data->text_draw_cache, DST.draw_ctx.v3d, DST.draw_ctx.ar, false);
+ }
+
+ PROFILE_END_UPDATE(data->render_time, stime);
+ }
+}
+
+#define MAX_INFO_LINES 10
+
+/**
+ * Returns the offset required for the drawing of engines info.
+ */
+int DRW_draw_region_engine_info_offset(void)
+{
+ int lines = 0;
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+
+ /* Count the number of lines. */
+ if (data->info[0] != '\0') {
+ lines++;
+ char *c = data->info;
+ while (*c++ != '\0') {
+ if (*c == '\n') {
+ lines++;
+ }
+ }
+ }
+ }
+ return MIN2(MAX_INFO_LINES, lines) * UI_UNIT_Y;
+}
+
+/**
+ * Actual drawing;
+ */
+void DRW_draw_region_engine_info(void)
+{
+ const char *info_array_final[MAX_INFO_LINES + 1];
+ /* This should be maxium number of engines running at the same time. */
+ char info_array[MAX_INFO_LINES][GPU_INFO_SIZE];
+ int i = 0;
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ARegion *ar = draw_ctx->ar;
+ float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
+
+ UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color);
+ mul_v3_fl(fill_color, fill_color[3]);
+
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+
+ if (data->info[0] != '\0') {
+ char *chr_current = data->info;
+ char *chr_start = chr_current;
+ int line_len = 0;
+
+ while (*chr_current++ != '\0') {
+ line_len++;
+ if (*chr_current == '\n') {
+ BLI_strncpy(info_array[i++], chr_start, line_len + 1);
+ /* Re-start counting. */
+ chr_start = chr_current + 1;
+ line_len = -1;
+ }
+ }
+
+ BLI_strncpy(info_array[i++], chr_start, line_len + 1);
+
+ if (i >= MAX_INFO_LINES) {
+ break;
+ }
+ }
+ }
+
+ for (int j = 0; j < i; j++) {
+ info_array_final[j] = info_array[j];
+ }
+ info_array_final[i] = NULL;
+
+ if (info_array[0] != NULL) {
+ ED_region_info_draw_multiline(ar, info_array_final, fill_color, true);
+ }
+}
+
+#undef MAX_INFO_LINES
+
+static void use_drw_engine(DrawEngineType *engine)
+{
+ LinkData *ld = MEM_callocN(sizeof(LinkData), "enabled engine link data");
+ ld->data = engine;
+ BLI_addtail(&DST.enabled_engines, ld);
+}
+
+/* TODO revisit this when proper layering is implemented */
+/* Gather all draw engines needed and store them in DST.enabled_engines
+ * That also define the rendering order of engines */
+static void drw_engines_enable_from_engine(RenderEngineType *engine_type)
+{
+ /* TODO layers */
+ if (engine_type->draw_engine != NULL) {
+ use_drw_engine(engine_type->draw_engine);
+ }
+
+ if ((engine_type->flag & RE_INTERNAL) == 0) {
+ drw_engines_enable_external();
+ }
+}
+
+static void drw_engines_enable_from_object_mode(void)
+{
+ use_drw_engine(&draw_engine_object_type);
+}
+
+static void drw_engines_enable_from_mode(int mode)
+{
+ switch (mode) {
+ case CTX_MODE_EDIT_MESH:
+ use_drw_engine(&draw_engine_edit_mesh_type);
+ break;
+ case CTX_MODE_EDIT_CURVE:
+ use_drw_engine(&draw_engine_edit_curve_type);
+ break;
+ case CTX_MODE_EDIT_SURFACE:
+ use_drw_engine(&draw_engine_edit_surface_type);
+ break;
+ case CTX_MODE_EDIT_TEXT:
+ use_drw_engine(&draw_engine_edit_text_type);
+ break;
+ case CTX_MODE_EDIT_ARMATURE:
+ use_drw_engine(&draw_engine_edit_armature_type);
+ break;
+ case CTX_MODE_EDIT_METABALL:
+ use_drw_engine(&draw_engine_edit_metaball_type);
+ break;
+ case CTX_MODE_EDIT_LATTICE:
+ use_drw_engine(&draw_engine_edit_lattice_type);
+ break;
+ case CTX_MODE_POSE:
+ use_drw_engine(&draw_engine_pose_type);
+ break;
+ case CTX_MODE_SCULPT:
+ use_drw_engine(&draw_engine_sculpt_type);
+ break;
+ case CTX_MODE_PAINT_WEIGHT:
+ use_drw_engine(&draw_engine_pose_type);
+ use_drw_engine(&draw_engine_paint_weight_type);
+ break;
+ case CTX_MODE_PAINT_VERTEX:
+ use_drw_engine(&draw_engine_paint_vertex_type);
+ break;
+ case CTX_MODE_PAINT_TEXTURE:
+ use_drw_engine(&draw_engine_paint_texture_type);
+ break;
+ case CTX_MODE_PARTICLE:
+ use_drw_engine(&draw_engine_particle_type);
+ break;
+ case CTX_MODE_OBJECT:
+ break;
+ default:
+ BLI_assert(!"Draw mode invalid");
+ break;
+ }
+}
+
+/**
+ * Use for select and depth-drawing.
+ */
+static void drw_engines_enable_basic(void)
+{
+ use_drw_engine(DRW_engine_viewport_basic_type.draw_engine);
+}
+
+/**
+ * Use for external render engines.
+ */
+static void drw_engines_enable_external(void)
+{
+ use_drw_engine(DRW_engine_viewport_external_type.draw_engine);
+}
+
+static void drw_engines_enable(const Scene *scene, ViewLayer *view_layer, RenderEngineType *engine_type)
+{
+ Object *obact = OBACT(view_layer);
+ const int mode = CTX_data_mode_enum_ex(scene->obedit, obact);
+
+ drw_engines_enable_from_engine(engine_type);
+
+ if (DRW_state_draw_support()) {
+ drw_engines_enable_from_object_mode();
+ drw_engines_enable_from_mode(mode);
+ }
+}
+
+static void drw_engines_disable(void)
+{
+ BLI_freelistN(&DST.enabled_engines);
+}
+
+static unsigned int DRW_engines_get_hash(void)
+{
+ unsigned int hash = 0;
+ /* The cache depends on enabled engines */
+ /* FIXME : if collision occurs ... segfault */
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ hash += BLI_ghashutil_strhash_p(engine->idname);
+ }
+
+ return hash;
+}
+
+static void draw_stat(rcti *rect, int u, int v, const char *txt, const int size)
+{
+ BLF_draw_default_ascii(rect->xmin + (1 + u * 5) * U.widget_unit,
+ rect->ymax - (3 + v) * U.widget_unit, 0.0f,
+ txt, size);
+}
+
+/* CPU stats */
+static void drw_debug_cpu_stats(void)
+{
+ int u, v;
+ double init_tot_time = 0.0, background_tot_time = 0.0, render_tot_time = 0.0, tot_time = 0.0;
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ rcti rect;
+ struct ARegion *ar = DST.draw_ctx.ar;
+ ED_region_visible_rect(ar, &rect);
+
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+
+ /* row by row */
+ v = 0; u = 0;
+ /* Label row */
+ char col_label[32];
+ sprintf(col_label, "Engine");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Init");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Background");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Render");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Total (w/o cache)");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ v++;
+
+ /* Engines rows */
+ char time_to_txt[16];
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ u = 0;
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+
+ draw_stat(&rect, u++, v, engine->idname, sizeof(engine->idname));
+
+ init_tot_time += data->init_time;
+ sprintf(time_to_txt, "%.2fms", data->init_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ background_tot_time += data->background_time;
+ sprintf(time_to_txt, "%.2fms", data->background_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ render_tot_time += data->render_time;
+ sprintf(time_to_txt, "%.2fms", data->render_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ tot_time += data->init_time + data->background_time + data->render_time;
+ sprintf(time_to_txt, "%.2fms", data->init_time + data->background_time + data->render_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ v++;
+ }
+
+ /* Totals row */
+ u = 0;
+ sprintf(col_label, "Sub Total");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(time_to_txt, "%.2fms", init_tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", background_tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", render_tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ v += 2;
+
+ u = 0;
+ sprintf(col_label, "Cache Time");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(time_to_txt, "%.2fms", DST.cache_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+}
+
+/* Display GPU time for each passes */
+static void drw_debug_gpu_stats(void)
+{
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ rcti rect;
+ struct ARegion *ar = DST.draw_ctx.ar;
+ ED_region_visible_rect(ar, &rect);
+
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+
+ int v = BLI_listbase_count(&DST.enabled_engines) + 5;
+
+ char stat_string[32];
+
+ /* Memory Stats */
+ unsigned int tex_mem = GPU_texture_memory_usage_get();
+ unsigned int vbo_mem = GWN_vertbuf_get_memory_usage();
+
+ sprintf(stat_string, "GPU Memory");
+ draw_stat(&rect, 0, v, stat_string, sizeof(stat_string));
+ sprintf(stat_string, "%.2fMB", (double)(tex_mem + vbo_mem) / 1000000.0);
+ draw_stat(&rect, 1, v++, stat_string, sizeof(stat_string));
+ sprintf(stat_string, " |--> Textures");
+ draw_stat(&rect, 0, v, stat_string, sizeof(stat_string));
+ sprintf(stat_string, "%.2fMB", (double)tex_mem / 1000000.0);
+ draw_stat(&rect, 1, v++, stat_string, sizeof(stat_string));
+ sprintf(stat_string, " |--> Meshes");
+ draw_stat(&rect, 0, v, stat_string, sizeof(stat_string));
+ sprintf(stat_string, "%.2fMB", (double)vbo_mem / 1000000.0);
+ draw_stat(&rect, 1, v++, stat_string, sizeof(stat_string));
+
+ /* Pre offset for stats_draw */
+ rect.ymax -= (3 + ++v) * U.widget_unit;
+
+ /* Rendering Stats */
+ DRW_stats_draw(&rect);
+}
+
+/* -------------------------------------------------------------------- */
+
+/** \name View Update
+ * \{ */
+
+void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
+{
+ RenderEngineType *engine_type = update_ctx->engine_type;
+ ARegion *ar = update_ctx->ar;
+ View3D *v3d = update_ctx->v3d;
+ RegionView3D *rv3d = ar->regiondata;
+ Scene *scene = update_ctx->scene;
+ ViewLayer *view_layer = update_ctx->view_layer;
+
+ if (rv3d->viewport == NULL) {
+ return;
+ }
+
+
+ /* Reset before using it. */
+ memset(&DST, 0x0, sizeof(DST));
+
+ DST.viewport = rv3d->viewport;
+ DST.draw_ctx = (DRWContextState){
+ ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, NULL,
+ };
+
+ drw_engines_enable(scene, view_layer, engine_type);
+
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *draw_engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(draw_engine);
+
+ if (draw_engine->view_update) {
+ draw_engine->view_update(data);
+ }
+ }
+
+ DST.viewport = NULL;
+
+ drw_engines_disable();
+}
+
+/** \} */
+
+/** \name ID Update
+ * \{ */
+
+/* TODO(sergey): This code is run for each changed ID (including the ones which
+ * are changed indirectly via update flush. Need to find a way to make this to
+ * run really fast, hopefully without any memory allocations on a heap
+ * Idea here could be to run every known engine's id_update() and make them
+ * do nothing if there is no engine-specific data yet.
+ */
+void DRW_notify_id_update(const DRWUpdateContext *update_ctx, ID *id)
+{
+ RenderEngineType *engine_type = update_ctx->engine_type;
+ ARegion *ar = update_ctx->ar;
+ View3D *v3d = update_ctx->v3d;
+ RegionView3D *rv3d = ar->regiondata;
+ Scene *scene = update_ctx->scene;
+ ViewLayer *view_layer = update_ctx->view_layer;
+ if (rv3d->viewport == NULL) {
+ return;
+ }
+ /* Reset before using it. */
+ memset(&DST, 0x0, sizeof(DST));
+ DST.viewport = rv3d->viewport;
+ DST.draw_ctx = (DRWContextState){
+ ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, NULL,
+ };
+ drw_engines_enable(scene, view_layer, engine_type);
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *draw_engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(draw_engine);
+ if (draw_engine->id_update) {
+ draw_engine->id_update(data, id);
+ }
+ }
+ DST.viewport = NULL;
+ drw_engines_disable();
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Main Draw Loops (DRW_draw)
+ * \{ */
+
+/* Everything starts here.
+ * This function takes care of calling all cache and rendering functions
+ * for each relevant engine / mode engine. */
+void DRW_draw_view(const bContext *C)
+{
+ struct Depsgraph *graph = CTX_data_depsgraph(C);
+ RenderEngineType *engine_type = CTX_data_engine_type(C);
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ /* Reset before using it. */
+ memset(&DST, 0x0, sizeof(DST));
+ DRW_draw_render_loop_ex(graph, engine_type, ar, v3d, C);
+}
+
+/**
+ * Used for both regular and off-screen drawing.
+ * Need to reset DST before calling this function
+ */
+void DRW_draw_render_loop_ex(
+ struct Depsgraph *graph,
+ RenderEngineType *engine_type,
+ ARegion *ar, View3D *v3d,
+ const bContext *evil_C)
+{
+ Scene *scene = DEG_get_evaluated_scene(graph);
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(graph);
+ RegionView3D *rv3d = ar->regiondata;
+
+ DST.draw_ctx.evil_C = evil_C;
+
+ DST.viewport = rv3d->viewport;
+ v3d->zbuf = true;
+
+ /* Setup viewport */
+ GPU_viewport_engines_data_validate(DST.viewport, DRW_engines_get_hash());
+
+ DST.draw_ctx = (DRWContextState){
+ ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type,
+
+ /* reuse if caller sets */
+ DST.draw_ctx.evil_C,
+ };
+
+ drw_viewport_var_init();
+
+ /* Get list of enabled engines */
+ drw_engines_enable(scene, view_layer, engine_type);
+
+ /* Update ubos */
+ DRW_globals_update();
+
+ /* Init engines */
+ drw_engines_init();
+
+ /* TODO : tag to refresh by the deps graph */
+ /* ideally only refresh when objects are added/removed */
+ /* or render properties / materials change */
+ {
+ PROFILE_START(stime);
+ drw_engines_cache_init();
+
+ DEG_OBJECT_ITER(graph, ob, DEG_ITER_OBJECT_FLAG_ALL);
+ {
+ drw_engines_cache_populate(ob);
+ }
+ DEG_OBJECT_ITER_END
+
+ drw_engines_cache_finish();
+ PROFILE_END_ACCUM(DST.cache_time, stime);
+ }
+
+ DRW_stats_begin();
+
+ /* Start Drawing */
+ DRW_state_reset();
+ drw_engines_draw_background();
+
+ /* WIP, single image drawn over the camera view (replace) */
+ bool do_bg_image = false;
+ if (rv3d->persp == RV3D_CAMOB) {
+ Object *cam_ob = v3d->camera;
+ if (cam_ob && cam_ob->type == OB_CAMERA) {
+ Camera *cam = cam_ob->data;
+ if (!BLI_listbase_is_empty(&cam->bg_images)) {
+ do_bg_image = true;
+ }
+ }
+ }
+
+ extern void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
+ const bool do_foreground, const bool do_camera_frame);
+ if (do_bg_image) {
+ view3d_draw_bgpic_test(scene, ar, v3d, false, true);
+ }
+
+
+ DRW_draw_callbacks_pre_scene();
+ if (DST.draw_ctx.evil_C) {
+ ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_PRE_VIEW);
+ }
+
+ drw_engines_draw_scene();
+
+ DRW_draw_callbacks_post_scene();
+ if (DST.draw_ctx.evil_C) {
+ ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_POST_VIEW);
+ }
+
+ DRW_state_reset();
+
+ drw_engines_draw_text();
+
+ if (DST.draw_ctx.evil_C) {
+ /* needed so manipulator isn't obscured */
+ glDisable(GL_DEPTH_TEST);
+ DRW_draw_manipulator();
+ glEnable(GL_DEPTH_TEST);
+
+ DRW_draw_region_info();
+ }
+
+ DRW_stats_reset();
+
+ if (do_bg_image) {
+ view3d_draw_bgpic_test(scene, ar, v3d, true, true);
+ }
+
+ if (G.debug_value > 20) {
+ drw_debug_cpu_stats();
+ drw_debug_gpu_stats();
+ }
+
+ DRW_state_reset();
+ drw_engines_disable();
+
+ drw_viewport_cache_resize();
+
+#ifdef DEBUG
+ /* Avoid accidental reuse. */
+ memset(&DST, 0xFF, sizeof(DST));
+#endif
+}
+
+void DRW_draw_render_loop(
+ struct Depsgraph *graph,
+ ARegion *ar, View3D *v3d)
+{
+ /* Reset before using it. */
+ memset(&DST, 0x0, sizeof(DST));
+
+ Scene *scene = DEG_get_evaluated_scene(graph);
+ RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
+
+ DRW_draw_render_loop_ex(graph, engine_type, ar, v3d, NULL);
+}
+
+void DRW_draw_render_loop_offscreen(
+ struct Depsgraph *graph, RenderEngineType *engine_type,
+ ARegion *ar, View3D *v3d, GPUOffScreen *ofs)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* backup */
+ void *backup_viewport = rv3d->viewport;
+ {
+ /* backup (_never_ use rv3d->viewport) */
+ rv3d->viewport = GPU_viewport_create_from_offscreen(ofs);
+ }
+
+ /* Reset before using it. */
+ memset(&DST, 0x0, sizeof(DST));
+ DST.options.is_image_render = true;
+ DRW_draw_render_loop_ex(graph, engine_type, ar, v3d, NULL);
+
+ /* restore */
+ {
+ /* don't free data owned by 'ofs' */
+ GPU_viewport_clear_from_offscreen(rv3d->viewport);
+ GPU_viewport_free(rv3d->viewport);
+ MEM_freeN(rv3d->viewport);
+
+ rv3d->viewport = backup_viewport;
+ }
+
+ /* we need to re-bind (annoying!) */
+ GPU_offscreen_bind(ofs, false);
+}
+
+/**
+ * object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing).
+ */
+void DRW_draw_select_loop(
+ struct Depsgraph *graph,
+ ARegion *ar, View3D *v3d,
+ bool UNUSED(use_obedit_skip), bool UNUSED(use_nearest), const rcti *rect)
+{
+ Scene *scene = DEG_get_evaluated_scene(graph);
+ RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(graph);
+#ifndef USE_GPU_SELECT
+ UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect);
+#else
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* Reset before using it. */
+ memset(&DST, 0x0, sizeof(DST));
+
+ /* backup (_never_ use rv3d->viewport) */
+ void *backup_viewport = rv3d->viewport;
+ rv3d->viewport = NULL;
+
+ bool use_obedit = false;
+ int obedit_mode = 0;
+ if (scene->obedit && scene->obedit->type == OB_MBALL) {
+ use_obedit = true;
+ obedit_mode = CTX_MODE_EDIT_METABALL;
+ }
+ else if ((scene->obedit && scene->obedit->type == OB_ARMATURE)) {
+ /* if not drawing sketch, draw bones */
+ // if (!BDR_drawSketchNames(vc))
+ {
+ use_obedit = true;
+ obedit_mode = CTX_MODE_EDIT_ARMATURE;
+ }
+ }
+
+ struct GPUViewport *viewport = GPU_viewport_create();
+ GPU_viewport_size_set(viewport, (const int[2]){BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)});
+
+ bool cache_is_dirty;
+ DST.viewport = viewport;
+ v3d->zbuf = true;
+
+ DST.options.is_select = true;
+
+ /* Get list of enabled engines */
+ if (use_obedit) {
+ drw_engines_enable_from_mode(obedit_mode);
+ }
+ else {
+ drw_engines_enable_basic();
+ drw_engines_enable_from_object_mode();
+ }
+
+ /* Setup viewport */
+ cache_is_dirty = true;
+
+ /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
+ DST.draw_ctx = (DRWContextState){
+ ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, (bContext *)NULL,
+ };
+
+ drw_viewport_var_init();
+
+ /* Update ubos */
+ DRW_globals_update();
+
+ /* Init engines */
+ drw_engines_init();
+
+ /* TODO : tag to refresh by the deps graph */
+ /* ideally only refresh when objects are added/removed */
+ /* or render properties / materials change */
+ if (cache_is_dirty) {
+ drw_engines_cache_init();
+
+ if (use_obedit) {
+ drw_engines_cache_populate(scene->obedit);
+ }
+ else {
+ DEG_OBJECT_ITER(graph, ob, DEG_ITER_OBJECT_FLAG_DUPLI)
+ {
+ if ((ob->base_flag & BASE_SELECTABLED) != 0) {
+ DRW_select_load_id(ob->select_color);
+ drw_engines_cache_populate(ob);
+ }
+ }
+ DEG_OBJECT_ITER_END
+ }
+
+ drw_engines_cache_finish();
+ }
+
+ /* Start Drawing */
+ DRW_state_reset();
+ DRW_draw_callbacks_pre_scene();
+ drw_engines_draw_scene();
+ DRW_draw_callbacks_post_scene();
+
+ DRW_state_reset();
+ drw_engines_disable();
+
+#ifdef DEBUG
+ /* Avoid accidental reuse. */
+ memset(&DST, 0xFF, sizeof(DST));
+#endif
+
+ /* Cleanup for selection state */
+ GPU_viewport_free(viewport);
+ MEM_freeN(viewport);
+
+ /* restore */
+ rv3d->viewport = backup_viewport;
+#endif /* USE_GPU_SELECT */
+}
+
+/**
+ * object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing).
+ */
+void DRW_draw_depth_loop(
+ Depsgraph *graph,
+ ARegion *ar, View3D *v3d)
+{
+ Scene *scene = DEG_get_evaluated_scene(graph);
+ RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(graph);
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* backup (_never_ use rv3d->viewport) */
+ void *backup_viewport = rv3d->viewport;
+ rv3d->viewport = NULL;
+
+ /* Reset before using it. */
+ memset(&DST, 0x0, sizeof(DST));
+
+ struct GPUViewport *viewport = GPU_viewport_create();
+ GPU_viewport_size_set(viewport, (const int[2]){ar->winx, ar->winy});
+
+ bool cache_is_dirty;
+ DST.viewport = viewport;
+ v3d->zbuf = true;
+
+ DST.options.is_depth = true;
+
+ /* Get list of enabled engines */
+ {
+ drw_engines_enable_basic();
+ drw_engines_enable_from_object_mode();
+ }
+
+ /* Setup viewport */
+ cache_is_dirty = true;
+
+ /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
+ DST.draw_ctx = (DRWContextState){
+ ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, (bContext *)NULL,
+ };
+
+ drw_viewport_var_init();
+
+ /* Update ubos */
+ DRW_globals_update();
+
+ /* Init engines */
+ drw_engines_init();
+
+ /* TODO : tag to refresh by the deps graph */
+ /* ideally only refresh when objects are added/removed */
+ /* or render properties / materials change */
+ if (cache_is_dirty) {
+ drw_engines_cache_init();
+
+ DEG_OBJECT_ITER(graph, ob, DEG_ITER_OBJECT_FLAG_ALL)
+ {
+ drw_engines_cache_populate(ob);
+ }
+ DEG_OBJECT_ITER_END
+
+ drw_engines_cache_finish();
+ }
+
+ /* Start Drawing */
+ DRW_state_reset();
+ DRW_draw_callbacks_pre_scene();
+ drw_engines_draw_scene();
+ DRW_draw_callbacks_post_scene();
+
+ DRW_state_reset();
+ drw_engines_disable();
+
+#ifdef DEBUG
+ /* Avoid accidental reuse. */
+ memset(&DST, 0xFF, sizeof(DST));
+#endif
+
+ /* Cleanup for selection state */
+ GPU_viewport_free(viewport);
+ MEM_freeN(viewport);
+
+ /* restore */
+ rv3d->viewport = backup_viewport;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Draw Manager State (DRW_state)
+ * \{ */
+
+void DRW_state_dfdy_factors_get(float dfdyfac[2])
+{
+ GPU_get_dfdy_factors(dfdyfac);
+}
+
+/**
+ * When false, drawing doesn't output to a pixel buffer
+ * eg: Occlusion queries, or when we have setup a context to draw in already.
+ */
+bool DRW_state_is_fbo(void)
+{
+ return (DST.default_framebuffer != NULL);
+}
+
+/**
+ * For when engines need to know if this is drawing for selection or not.
+ */
+bool DRW_state_is_select(void)
+{
+ return DST.options.is_select;
+}
+
+bool DRW_state_is_depth(void)
+{
+ return DST.options.is_depth;
+}
+
+/**
+ * Whether we are rendering for an image
+ */
+bool DRW_state_is_image_render(void)
+{
+ return DST.options.is_image_render;
+}
+
+/**
+ * Whether we are rendering only the render engine,
+ * or if we should also render the mode engines.
+ */
+bool DRW_state_is_scene_render(void)
+{
+ BLI_assert(DST.options.is_scene_render ?
+ DST.options.is_image_render : true);
+ return DST.options.is_scene_render;
+}
+
+/**
+ * Should text draw in this mode?
+ */
+bool DRW_state_show_text(void)
+{
+ return (DST.options.is_select) == 0 &&
+ (DST.options.is_depth) == 0 &&
+ (DST.options.is_scene_render) == 0;
+}
+
+/**
+ * Should draw support elements
+ * Objects center, selection outline, probe data, ...
+ */
+bool DRW_state_draw_support(void)
+{
+ View3D *v3d = DST.draw_ctx.v3d;
+ return (DRW_state_is_scene_render() == false) &&
+ (v3d != NULL) &&
+ ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Context State (DRW_context_state)
+ * \{ */
+
+const DRWContextState *DRW_context_state_get(void)
+{
+ return &DST.draw_ctx;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Init/Exit (DRW_engines)
+ * \{ */
+
+void DRW_engine_register(DrawEngineType *draw_engine_type)
+{
+ BLI_addtail(&DRW_engines, draw_engine_type);
+}
+
+void DRW_engines_register(void)
+{
+#ifdef WITH_CLAY_ENGINE
+ RE_engines_register(NULL, &DRW_engine_viewport_clay_type);
+#endif
+ RE_engines_register(NULL, &DRW_engine_viewport_eevee_type);
+
+ DRW_engine_register(&draw_engine_object_type);
+ DRW_engine_register(&draw_engine_edit_armature_type);
+ DRW_engine_register(&draw_engine_edit_curve_type);
+ DRW_engine_register(&draw_engine_edit_lattice_type);
+ DRW_engine_register(&draw_engine_edit_mesh_type);
+ DRW_engine_register(&draw_engine_edit_metaball_type);
+ DRW_engine_register(&draw_engine_edit_surface_type);
+ DRW_engine_register(&draw_engine_edit_text_type);
+ DRW_engine_register(&draw_engine_paint_texture_type);
+ DRW_engine_register(&draw_engine_paint_vertex_type);
+ DRW_engine_register(&draw_engine_paint_weight_type);
+ DRW_engine_register(&draw_engine_particle_type);
+ DRW_engine_register(&draw_engine_pose_type);
+ DRW_engine_register(&draw_engine_sculpt_type);
+
+ /* setup callbacks */
+ {
+ /* BKE: mball.c */
+ extern void *BKE_mball_batch_cache_dirty_cb;
+ extern void *BKE_mball_batch_cache_free_cb;
+ /* BKE: curve.c */
+ extern void *BKE_curve_batch_cache_dirty_cb;
+ extern void *BKE_curve_batch_cache_free_cb;
+ /* BKE: mesh.c */
+ extern void *BKE_mesh_batch_cache_dirty_cb;
+ extern void *BKE_mesh_batch_cache_free_cb;
+ /* BKE: lattice.c */
+ extern void *BKE_lattice_batch_cache_dirty_cb;
+ extern void *BKE_lattice_batch_cache_free_cb;
+ /* BKE: particle.c */
+ extern void *BKE_particle_batch_cache_dirty_cb;
+ extern void *BKE_particle_batch_cache_free_cb;
+
+ BKE_mball_batch_cache_dirty_cb = DRW_mball_batch_cache_dirty;
+ BKE_mball_batch_cache_free_cb = DRW_mball_batch_cache_free;
+
+ BKE_curve_batch_cache_dirty_cb = DRW_curve_batch_cache_dirty;
+ BKE_curve_batch_cache_free_cb = DRW_curve_batch_cache_free;
+
+ BKE_mesh_batch_cache_dirty_cb = DRW_mesh_batch_cache_dirty;
+ BKE_mesh_batch_cache_free_cb = DRW_mesh_batch_cache_free;
+
+ BKE_lattice_batch_cache_dirty_cb = DRW_lattice_batch_cache_dirty;
+ BKE_lattice_batch_cache_free_cb = DRW_lattice_batch_cache_free;
+
+ BKE_particle_batch_cache_dirty_cb = DRW_particle_batch_cache_dirty;
+ BKE_particle_batch_cache_free_cb = DRW_particle_batch_cache_free;
+ }
+}
+
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GPUTexture *globals_ramp; /* draw_common.c */
+void DRW_engines_free(void)
+{
+ DRW_shape_cache_free();
+ DRW_stats_free();
+
+ DrawEngineType *next;
+ for (DrawEngineType *type = DRW_engines.first; type; type = next) {
+ next = type->next;
+ BLI_remlink(&R_engines, type);
+
+ if (type->engine_free) {
+ type->engine_free();
+ }
+ }
+
+ if (globals_ubo)
+ GPU_uniformbuffer_free(globals_ubo);
+
+ if (globals_ramp)
+ GPU_texture_free(globals_ramp);
+
+ MEM_SAFE_FREE(RST.bound_texs);
+ MEM_SAFE_FREE(RST.bound_tex_slots);
+
+#ifdef WITH_CLAY_ENGINE
+ BLI_remlink(&R_engines, &DRW_engine_viewport_clay_type);
+#endif
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_manager_profiling.c b/source/blender/draw/intern/draw_manager_profiling.c
new file mode 100644
index 00000000000..f9fbbac2e2e
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager_profiling.c
@@ -0,0 +1,242 @@
+/*
+ * 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_manager_profiling.c
+ * \ingroup draw
+ */
+
+#include "BLI_rect.h"
+#include "BLI_string.h"
+
+#include "BKE_global.h"
+
+#include "BLF_api.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "GPU_glew.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "draw_manager_profiling.h"
+
+#define MAX_TIMER_NAME 32
+#define MAX_NESTED_TIMER 8
+#define CHUNK_SIZE 8
+#define GPU_TIMER_FALLOFF 0.1
+
+typedef struct DRWTimer {
+ GLuint query[2];
+ GLuint64 time_average;
+ char name[MAX_TIMER_NAME];
+ int lvl; /* Hierarchy level for nested timer. */
+ bool is_query; /* Does this timer actually perform queries or is it just a group. */
+} DRWTimer;
+
+static struct DRWTimerPool {
+ DRWTimer *timers;
+ int chunk_count; /* Number of chunk allocated. */
+ int timer_count; /* chunk_count * CHUNK_SIZE */
+ int timer_increment; /* Keep track of where we are in the stack. */
+ int end_increment; /* Keep track of bad usage. */
+ bool is_recording; /* Are we in the render loop? */
+ bool is_querying; /* Keep track of bad usage. */
+} DTP = {NULL};
+
+void DRW_stats_free(void)
+{
+ if (DTP.timers != NULL) {
+ for (int i = 0; i < DTP.timer_count; ++i) {
+ DRWTimer *timer = &DTP.timers[i];
+ glDeleteQueries(2, timer->query);
+ }
+ MEM_freeN(DTP.timers);
+ DTP.timers = NULL;
+ }
+}
+
+void DRW_stats_begin(void)
+{
+ if (G.debug_value > 20) {
+ DTP.is_recording = true;
+ }
+
+ if (DTP.is_recording && DTP.timers == NULL) {
+ DTP.chunk_count = 1;
+ DTP.timer_count = DTP.chunk_count * CHUNK_SIZE;
+ DTP.timers = MEM_callocN(sizeof(DRWTimer) * DTP.timer_count, "DRWTimer stack");
+ }
+ else if (!DTP.is_recording && DTP.timers != NULL) {
+ DRW_stats_free();
+ }
+
+ DTP.is_querying = false;
+ DTP.timer_increment = 0;
+ DTP.end_increment = 0;
+}
+
+static DRWTimer *drw_stats_timer_get(void)
+{
+ if (UNLIKELY(DTP.timer_increment >= DTP.timer_count)) {
+ /* Resize the stack. */
+ DTP.chunk_count++;
+ DTP.timer_count = DTP.chunk_count * CHUNK_SIZE;
+ DTP.timers = MEM_recallocN(DTP.timers, sizeof(DRWTimer) * DTP.timer_count);
+ }
+
+ return &DTP.timers[DTP.timer_increment++];
+}
+
+static void drw_stats_timer_start_ex(const char *name, const bool is_query)
+{
+ if (DTP.is_recording) {
+ DRWTimer *timer = drw_stats_timer_get();
+ BLI_strncpy(timer->name, name, MAX_TIMER_NAME);
+ timer->lvl = DTP.timer_increment - DTP.end_increment - 1;
+ timer->is_query = is_query;
+
+ /* Queries cannot be nested or interleaved. */
+ BLI_assert(!DTP.is_querying);
+ if (timer->is_query) {
+ if (timer->query[0] == 0) {
+ glGenQueries(1, timer->query);
+ }
+
+ /* Issue query for the next frame */
+ glBeginQuery(GL_TIME_ELAPSED, timer->query[0]);
+ DTP.is_querying = true;
+ }
+ }
+}
+
+/* Use this to group the queries. It does NOT keep track
+ * of the time, it only sum what the queries inside it. */
+void DRW_stats_group_start(const char *name)
+{
+ drw_stats_timer_start_ex(name, false);
+}
+
+void DRW_stats_group_end(void)
+{
+ if (DTP.is_recording) {
+ BLI_assert(!DTP.is_querying);
+ DTP.end_increment++;
+ }
+}
+
+/* NOTE: Only call this when no sub timer will be called. */
+void DRW_stats_query_start(const char *name)
+{
+ drw_stats_timer_start_ex(name, true);
+}
+
+void DRW_stats_query_end(void)
+{
+ if (DTP.is_recording) {
+ DTP.end_increment++;
+ BLI_assert(DTP.is_querying);
+ glEndQuery(GL_TIME_ELAPSED);
+ DTP.is_querying = false;
+ }
+}
+
+void DRW_stats_reset(void)
+{
+ BLI_assert((DTP.timer_increment - DTP.end_increment) <= 0 && "You forgot a DRW_stats_group/query_end somewhere!");
+ BLI_assert((DTP.timer_increment - DTP.end_increment) >= 0 && "You forgot a DRW_stats_group/query_start somewhere!");
+
+ if (DTP.is_recording) {
+ GLuint64 lvl_time[MAX_NESTED_TIMER] = {0};
+
+ /* Swap queries for the next frame and sum up each lvl time. */
+ for (int i = DTP.timer_increment - 1; i >= 0; --i) {
+ DRWTimer *timer = &DTP.timers[i];
+ SWAP(GLuint, timer->query[0], timer->query[1]);
+
+ BLI_assert(timer->lvl < MAX_NESTED_TIMER);
+
+ if (timer->is_query) {
+ GLuint64 time;
+ if (timer->query[0] != 0) {
+ glGetQueryObjectui64v(timer->query[0], GL_QUERY_RESULT, &time);
+ }
+ else {
+ time = 1000000000; /* 1ms default */
+ }
+
+ timer->time_average = timer->time_average * (1.0 - GPU_TIMER_FALLOFF) + time * GPU_TIMER_FALLOFF;
+ timer->time_average = MIN2(timer->time_average, 1000000000);
+ }
+ else {
+ timer->time_average = lvl_time[timer->lvl + 1];
+ lvl_time[timer->lvl + 1] = 0;
+ }
+
+ lvl_time[timer->lvl] += timer->time_average;
+ }
+
+ DTP.is_recording = false;
+ }
+}
+
+void DRW_stats_draw(rcti *rect)
+{
+ char stat_string[64];
+ int lvl_index[MAX_NESTED_TIMER];
+ int v = 0;
+
+ BLI_snprintf(stat_string, sizeof(stat_string), "GPU Render Stats");
+ BLF_draw_default_ascii(rect->xmin + 1 * U.widget_unit, rect->ymax - v++ * U.widget_unit, 0.0f, stat_string, sizeof(stat_string));
+
+ for (int i = 0; i < DTP.timer_increment; ++i) {
+ double time_ms, time_percent;
+ DRWTimer *timer = &DTP.timers[i];
+ DRWTimer *timer_parent = (timer->lvl > 0) ? &DTP.timers[lvl_index[timer->lvl - 1]] : NULL;
+
+ /* Only display a number of lvl at a time */
+ if ((G.debug_value - 21) < timer->lvl) continue;
+
+ BLI_assert(timer->lvl < MAX_NESTED_TIMER);
+ lvl_index[timer->lvl] = i;
+
+ time_ms = timer->time_average / 1000000.0;
+
+ if (timer_parent != NULL) {
+ time_percent = ((double)timer->time_average / (double)timer_parent->time_average) * 100.0;
+ }
+ else {
+ time_percent = 100.0;
+ }
+
+ /* avoid very long number */
+ time_ms = MIN2(time_ms, 999.0);
+ time_percent = MIN2(time_percent, 100.0);
+
+ BLI_snprintf(stat_string, sizeof(stat_string), "%s", timer->name);
+ BLF_draw_default_ascii(rect->xmin + (1 + timer->lvl) * U.widget_unit, rect->ymax - v * U.widget_unit, 0.0f, stat_string, sizeof(stat_string));
+ BLI_snprintf(stat_string, sizeof(stat_string), "%.2fms", time_ms);
+ BLF_draw_default_ascii(rect->xmin + (13 + timer->lvl) * U.widget_unit, rect->ymax - v * U.widget_unit, 0.0f, stat_string, sizeof(stat_string));
+ BLI_snprintf(stat_string, sizeof(stat_string), "%.0f", time_percent);
+ BLF_draw_default_ascii(rect->xmin + (17 + timer->lvl) * U.widget_unit, rect->ymax - v * U.widget_unit, 0.0f, stat_string, sizeof(stat_string));
+ v++;
+ }
+} \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_manager_profiling.h b/source/blender/draw/intern/draw_manager_profiling.h
new file mode 100644
index 00000000000..233cd3878d2
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager_profiling.h
@@ -0,0 +1,43 @@
+/*
+ * 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_manager_profiling.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_MANAGER_PROFILING_H__
+#define __DRAW_MANAGER_PROFILING_H__
+
+struct rcti;
+
+void DRW_stats_free(void);
+void DRW_stats_begin(void);
+void DRW_stats_reset(void);
+
+void DRW_stats_group_start(const char *name);
+void DRW_stats_group_end(void);
+
+void DRW_stats_query_start(const char *name);
+void DRW_stats_query_end(void);
+
+void DRW_stats_draw(rcti *rect);
+
+#endif /* __DRAW_MANAGER_PROFILING_H__ */
diff --git a/source/blender/draw/intern/draw_manager_text.c b/source/blender/draw/intern/draw_manager_text.c
new file mode 100644
index 00000000000..56255af98ce
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager_text.c
@@ -0,0 +1,199 @@
+/*
+ * 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.
+ *
+ */
+
+/** \file blender/draw/intern/draw_manager_text.c
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_math.h"
+
+#include "BIF_gl.h"
+
+#include "GPU_matrix.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "UI_resources.h"
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "BLF_api.h"
+
+#include "draw_manager_text.h"
+
+typedef struct ViewCachedString {
+ struct ViewCachedString *next, *prev;
+ float vec[3];
+ union {
+ unsigned char ub[4];
+ int pack;
+ } col;
+ short sco[2];
+ short xoffs;
+ short flag;
+ int str_len;
+
+ /* str is allocated past the end */
+ char str[0];
+} ViewCachedString;
+
+typedef struct DRWTextStore {
+ ListBase list;
+} DRWTextStore;
+
+DRWTextStore *DRW_text_cache_create(void)
+{
+ DRWTextStore *dt = MEM_callocN(sizeof(*dt), __func__);
+ return dt;
+}
+
+void DRW_text_cache_destroy(struct DRWTextStore *dt)
+{
+ BLI_freelistN(&dt->list);
+ MEM_freeN(dt);
+}
+
+void DRW_text_cache_add(
+ DRWTextStore *dt,
+ const float co[3],
+ const char *str, const int str_len,
+ short xoffs, short flag,
+ const unsigned char col[4])
+{
+ int alloc_len;
+ ViewCachedString *vos;
+
+ if (flag & DRW_TEXT_CACHE_STRING_PTR) {
+ BLI_assert(str_len == strlen(str));
+ alloc_len = sizeof(void *);
+ }
+ else {
+ alloc_len = str_len + 1;
+ }
+
+ vos = MEM_mallocN(sizeof(ViewCachedString) + alloc_len, __func__);
+
+ BLI_addtail(&dt->list, vos);
+
+ copy_v3_v3(vos->vec, co);
+ copy_v4_v4_uchar(vos->col.ub, col);
+ vos->xoffs = xoffs;
+ vos->flag = flag;
+ vos->str_len = str_len;
+
+ /* allocate past the end */
+ if (flag & DRW_TEXT_CACHE_STRING_PTR) {
+ memcpy(vos->str, &str, alloc_len);
+ }
+ else {
+ memcpy(vos->str, str, alloc_len);
+ }
+}
+
+void DRW_text_cache_draw(
+ DRWTextStore *dt,
+ View3D *v3d, ARegion *ar, bool depth_write)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ ViewCachedString *vos;
+ int tot = 0;
+
+ /* project first and test */
+ for (vos = dt->list.first; vos; vos = vos->next) {
+ if (ED_view3d_project_short_ex(
+ ar,
+ (vos->flag & DRW_TEXT_CACHE_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
+ (vos->flag & DRW_TEXT_CACHE_LOCALCLIP) != 0,
+ vos->vec, vos->sco,
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+ {
+ tot++;
+ }
+ else {
+ vos->sco[0] = IS_CLIPPED;
+ }
+ }
+
+ if (tot) {
+ int col_pack_prev = 0;
+
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_disable();
+ }
+
+ float original_proj[4][4];
+ gpuGetProjectionMatrix(original_proj);
+ wmOrtho2_region_pixelspace(ar);
+
+ gpuPushMatrix();
+ gpuLoadIdentity();
+
+ if (depth_write) {
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ }
+ else {
+ glDepthMask(GL_FALSE);
+ }
+
+ const int font_id = BLF_default();
+
+ const uiStyle *style = UI_style_get();
+
+ BLF_size(font_id, style->widget.points * U.pixelsize, U.dpi);
+
+ for (vos = dt->list.first; vos; vos = vos->next) {
+ if (vos->sco[0] != IS_CLIPPED) {
+ if (col_pack_prev != vos->col.pack) {
+ BLF_color4ubv(font_id, vos->col.ub);
+ col_pack_prev = vos->col.pack;
+ }
+
+ BLF_position(
+ font_id,
+ (float)(vos->sco[0] + vos->xoffs), (float)(vos->sco[1]), (depth_write) ? 0.0f : 2.0f);
+
+ ((vos->flag & DRW_TEXT_CACHE_ASCII) ?
+ BLF_draw_ascii :
+ BLF_draw
+ )(font_id,
+ (vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) : vos->str,
+ vos->str_len);
+ }
+ }
+
+ if (depth_write) {
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ }
+ else {
+ glDepthMask(GL_TRUE);
+ }
+
+ gpuPopMatrix();
+ gpuLoadProjectionMatrix(original_proj);
+
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_enable();
+ }
+ }
+}
diff --git a/source/blender/draw/intern/draw_manager_text.h b/source/blender/draw/intern/draw_manager_text.h
new file mode 100644
index 00000000000..a58e167be0d
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager_text.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ *
+ */
+
+/** \file blender/draw/intern/draw_manager_text.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_MANAGER_TEXT_H__
+#define __DRAW_MANAGER_TEXT_H__
+
+struct DRWTextStore;
+
+struct DRWTextStore *DRW_text_cache_create(void);
+void DRW_text_cache_destroy(struct DRWTextStore *dt);
+
+void DRW_text_cache_add(
+ struct DRWTextStore *dt,
+ const float co[3],
+ const char *str, const int str_len,
+ short xoffs, short flag,
+ const unsigned char col[4]);
+
+void DRW_text_cache_draw(
+ struct DRWTextStore *dt,
+ struct View3D *v3d, struct ARegion *ar, bool depth_write);
+
+enum {
+ DRW_TEXT_CACHE_ASCII = (1 << 0),
+ DRW_TEXT_CACHE_GLOBALSPACE = (1 << 1),
+ DRW_TEXT_CACHE_LOCALCLIP = (1 << 2),
+ /* reference the string by pointer */
+ DRW_TEXT_CACHE_STRING_PTR = (1 << 3),
+};
+
+/* draw_manager.c */
+struct DRWTextStore *DRW_text_cache_ensure(void);
+
+#endif /* __DRAW_MANAGER_TEXT_H__ */
diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c
new file mode 100644
index 00000000000..474d6ac8769
--- /dev/null
+++ b/source/blender/draw/intern/draw_view.c
@@ -0,0 +1,756 @@
+/*
+ * 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/intern/draw_view.c
+ * \ingroup draw
+ *
+ * Contains dynamic drawing using immediate mode
+ */
+
+#include "DNA_brush_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+
+#include "ED_screen.h"
+#include "ED_transform.h"
+#include "ED_view3d.h"
+
+#include "GPU_draw.h"
+#include "GPU_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_unit.h"
+
+#include "DRW_render.h"
+
+#include "view3d_intern.h"
+
+#include "draw_view.h"
+
+/* ******************** region info ***************** */
+
+void DRW_draw_region_info(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ARegion *ar = draw_ctx->ar;
+ int offset;
+
+ DRW_draw_cursor();
+
+ offset = DRW_draw_region_engine_info_offset();
+
+ view3d_draw_region_info(draw_ctx->evil_C, ar, offset);
+
+ if (offset > 0) {
+ DRW_draw_region_engine_info();
+ }
+}
+
+/* ************************* Grid ************************** */
+
+static void gridline_range(double x0, double dx, double max, int *r_first, int *r_count)
+{
+ /* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y
+ * x0 is gridline 0, the axis in screen space
+ * Area covers [0 .. max) pixels */
+
+ int first = (int)ceil(-x0 / dx);
+ int last = (int)floor((max - x0) / dx);
+
+ if (first <= last) {
+ *r_first = first;
+ *r_count = last - first + 1;
+ }
+ else {
+ *r_first = 0;
+ *r_count = 0;
+ }
+}
+
+static int gridline_count(ARegion *ar, double x0, double y0, double dx)
+{
+ /* x0 & y0 establish the "phase" of the grid within this 2D region
+ * dx is the frequency, shared by x & y directions
+ * pass in dx of smallest (highest precision) grid we want to draw */
+
+ int first, x_ct, y_ct;
+
+ gridline_range(x0, dx, ar->winx, &first, &x_ct);
+ gridline_range(y0, dx, ar->winy, &first, &y_ct);
+
+ int total_ct = x_ct + y_ct;
+
+ return total_ct;
+}
+
+static bool drawgrid_draw(
+ ARegion *ar, double x0, double y0, double dx, int skip_mod,
+ unsigned pos, unsigned col, GLubyte col_value[3])
+{
+ /* skip every skip_mod lines relative to each axis; they will be overlaid by another drawgrid_draw
+ * always skip exact x0 & y0 axes; they will be drawn later in color
+ *
+ * set grid color once, just before the first line is drawn
+ * it's harmless to set same color for every line, or every vertex
+ * but if no lines are drawn, color must not be set! */
+
+ const float x_max = (float)ar->winx;
+ const float y_max = (float)ar->winy;
+
+ int first, ct;
+ int x_ct = 0, y_ct = 0; /* count of lines actually drawn */
+ int lines_skipped_for_next_unit = 0;
+
+ /* draw vertical lines */
+ gridline_range(x0, dx, x_max, &first, &ct);
+
+ for (int i = first; i < first + ct; ++i) {
+ if (i == 0)
+ continue;
+ else if (skip_mod && (i % skip_mod) == 0) {
+ ++lines_skipped_for_next_unit;
+ continue;
+ }
+
+ if (x_ct == 0)
+ immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
+
+ float x = (float)(x0 + i * dx);
+ immVertex2f(pos, x, 0.0f);
+ immVertex2f(pos, x, y_max);
+ ++x_ct;
+ }
+
+ /* draw horizontal lines */
+ gridline_range(y0, dx, y_max, &first, &ct);
+
+ for (int i = first; i < first + ct; ++i) {
+ if (i == 0)
+ continue;
+ else if (skip_mod && (i % skip_mod) == 0) {
+ ++lines_skipped_for_next_unit;
+ continue;
+ }
+
+ if (x_ct + y_ct == 0)
+ immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
+
+ float y = (float)(y0 + i * dx);
+ immVertex2f(pos, 0.0f, y);
+ immVertex2f(pos, x_max, y);
+ ++y_ct;
+ }
+
+ return lines_skipped_for_next_unit > 0;
+}
+
+#define GRID_MIN_PX_D 6.0
+#define GRID_MIN_PX_F 6.0f
+
+static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ double fx = rv3d->persmat[3][0];
+ double fy = rv3d->persmat[3][1];
+ double fw = rv3d->persmat[3][3];
+
+ const double wx = 0.5 * ar->winx; /* use double precision to avoid rounding errors */
+ const double wy = 0.5 * ar->winy;
+
+ double x = wx * fx / fw;
+ double y = wy * fy / fw;
+
+ double vec4[4] = { v3d->grid, v3d->grid, 0.0, 1.0 };
+ mul_m4_v4d(rv3d->persmat, vec4);
+ fx = vec4[0];
+ fy = vec4[1];
+ fw = vec4[3];
+
+ double dx = fabs(x - wx * fx / fw);
+ if (dx == 0) dx = fabs(y - wy * fy / fw);
+
+ x += wx;
+ y += wy;
+
+ /* now x, y, and dx have their final values
+ * (x,y) is the world origin (0,0,0) mapped to Area-relative screen space
+ * dx is the distance in pixels between grid lines -- same for horiz or vert grid lines */
+
+ glLineWidth(1.0f);
+
+#if 0 /* TODO: write to UI/widget depth buffer, not scene depth */
+ glDepthMask(GL_FALSE); /* disable write in zbuffer */
+#endif
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ unsigned char col[3], col2[3];
+ UI_GetThemeColor3ubv(TH_GRID, col);
+
+ if (unit->system) {
+ const void *usys;
+ int len;
+
+ bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len);
+
+ bool first = true;
+
+ if (usys) {
+ int i = len;
+ while (i--) {
+ double scalar = bUnit_GetScaler(usys, i);
+
+ double dx_scalar = dx * scalar / (double)unit->scale_length;
+ if (dx_scalar < (GRID_MIN_PX_D * 2.0)) {
+ /* very very small grid items are less useful when dealing with units */
+ continue;
+ }
+
+ if (first) {
+ first = false;
+
+ /* Store the smallest drawn grid size units name so users know how big each grid cell is */
+ *grid_unit = bUnit_GetNameDisplay(usys, i);
+ rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length);
+
+ int gridline_ct = gridline_count(ar, x, y, dx_scalar);
+ if (gridline_ct == 0)
+ goto drawgrid_cleanup; /* nothing to draw */
+
+ immBegin(GWN_PRIM_LINES, gridline_ct * 2);
+ }
+
+ float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar);
+ /* tweak to have the fade a bit nicer */
+ blend_fac = (blend_fac * blend_fac) * 2.0f;
+ CLAMP(blend_fac, 0.3f, 1.0f);
+
+ UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, blend_fac, col2);
+
+ const int skip_mod = (i == 0) ? 0 : (int)round(bUnit_GetScaler(usys, i - 1) / scalar);
+ if (!drawgrid_draw(ar, x, y, dx_scalar, skip_mod, pos, color, col2))
+ break;
+ }
+ }
+ }
+ else {
+ const double sublines = v3d->gridsubdiv;
+ const float sublines_fl = v3d->gridsubdiv;
+
+ int grids_to_draw = 2; /* first the faint fine grid, then the bold coarse grid */
+
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ grids_to_draw = (dx < GRID_MIN_PX_D) ? 0 : 1;
+ }
+ }
+ }
+ else {
+ if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
+ rv3d->gridview /= sublines_fl;
+ dx /= sublines;
+ if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
+ rv3d->gridview /= sublines_fl;
+ dx /= sublines;
+ if (dx > (GRID_MIN_PX_D * 10.0)) {
+ grids_to_draw = 1;
+ }
+ }
+ }
+ }
+
+ int gridline_ct = gridline_count(ar, x, y, dx);
+ if (gridline_ct == 0)
+ goto drawgrid_cleanup; /* nothing to draw */
+
+ immBegin(GWN_PRIM_LINES, gridline_ct * 2);
+
+ if (grids_to_draw == 2) {
+ UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2);
+ if (drawgrid_draw(ar, x, y, dx, v3d->gridsubdiv, pos, color, col2)) {
+ drawgrid_draw(ar, x, y, dx * sublines, 0, pos, color, col);
+ }
+ }
+ else if (grids_to_draw == 1) {
+ drawgrid_draw(ar, x, y, dx, 0, pos, color, col);
+ }
+ }
+
+ /* draw visible axes */
+ /* horizontal line */
+ if (0 <= y && y < ar->winy) {
+ UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ? 'Y' : 'X');
+ immAttrib3ub(color, col2[0], col2[1], col2[2]);
+ immVertex2f(pos, 0.0f, y);
+ immVertex2f(pos, (float)ar->winx, y);
+ }
+
+ /* vertical line */
+ if (0 <= x && x < ar->winx) {
+ UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ? 'Y' : 'Z');
+ immAttrib3ub(color, col2[0], col2[1], col2[2]);
+ immVertex2f(pos, x, 0.0f);
+ immVertex2f(pos, x, (float)ar->winy);
+ }
+
+ immEnd();
+
+drawgrid_cleanup:
+ immUnbindProgram();
+
+#if 0 /* depth write is left enabled above */
+ glDepthMask(GL_TRUE); /* enable write in zbuffer */
+#endif
+}
+
+#undef DEBUG_GRID
+#undef GRID_MIN_PX_D
+#undef GRID_MIN_PX_F
+
+static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
+{
+ /* draw only if there is something to draw */
+ if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
+ /* draw how many lines?
+ * trunc(v3d->gridlines / 2) * 4
+ * + 2 for xy axes (possibly with special colors)
+ * + 1 for z axis (the only line not in xy plane)
+ * even v3d->gridlines are honored, odd rounded down */
+ const int gridlines = v3d->gridlines / 2;
+ const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
+ const float grid = gridlines * grid_scale;
+
+ const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1;
+
+ bool show_axis_x = (v3d->gridflag & V3D_SHOW_X) != 0;
+ bool show_axis_y = (v3d->gridflag & V3D_SHOW_Y) != 0;
+ bool show_axis_z = (v3d->gridflag & V3D_SHOW_Z) != 0;
+
+ unsigned char col_grid[3], col_axis[3];
+
+ glLineWidth(1.0f);
+
+ UI_GetThemeColor3ubv(TH_GRID, col_grid);
+
+ if (show_floor) {
+ const unsigned vertex_ct = 2 * (gridlines * 4 + 2);
+ const int sublines = v3d->gridsubdiv;
+
+ unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3];
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ immBegin(GWN_PRIM_LINES, vertex_ct);
+
+ /* draw normal grid lines */
+ UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
+
+ for (int a = 1; a <= gridlines; a++) {
+ /* skip emphasised divider lines */
+ if (a % sublines != 0) {
+ const float line = a * grid_scale;
+
+ immAttrib3ubv(color, col_grid_light);
+
+ immVertex2f(pos, -grid, -line);
+ immVertex2f(pos, +grid, -line);
+ immVertex2f(pos, -grid, +line);
+ immVertex2f(pos, +grid, +line);
+
+ immVertex2f(pos, -line, -grid);
+ immVertex2f(pos, -line, +grid);
+ immVertex2f(pos, +line, -grid);
+ immVertex2f(pos, +line, +grid);
+ }
+ }
+
+ /* draw emphasised grid lines */
+ UI_GetThemeColor3ubv(TH_BACK, col_bg);
+ /* emphasise division lines lighter instead of darker, if background is darker than grid */
+ UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
+ (col_grid[0] + col_grid[1] + col_grid[2] + 30 >
+ col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10);
+
+ if (sublines <= gridlines) {
+ immAttrib3ubv(color, col_grid_emphasise);
+
+ for (int a = sublines; a <= gridlines; a += sublines) {
+ const float line = a * grid_scale;
+
+ immVertex2f(pos, -grid, -line);
+ immVertex2f(pos, +grid, -line);
+ immVertex2f(pos, -grid, +line);
+ immVertex2f(pos, +grid, +line);
+
+ immVertex2f(pos, -line, -grid);
+ immVertex2f(pos, -line, +grid);
+ immVertex2f(pos, +line, -grid);
+ immVertex2f(pos, +line, +grid);
+ }
+ }
+
+ /* draw X axis */
+ if (show_axis_x) {
+ show_axis_x = false; /* drawing now, won't need to draw later */
+ UI_make_axis_color(col_grid, col_axis, 'X');
+ immAttrib3ubv(color, col_axis);
+ }
+ else
+ immAttrib3ubv(color, col_grid_emphasise);
+
+ immVertex2f(pos, -grid, 0.0f);
+ immVertex2f(pos, +grid, 0.0f);
+
+ /* draw Y axis */
+ if (show_axis_y) {
+ show_axis_y = false; /* drawing now, won't need to draw later */
+ UI_make_axis_color(col_grid, col_axis, 'Y');
+ immAttrib3ubv(color, col_axis);
+ }
+ else
+ immAttrib3ubv(color, col_grid_emphasise);
+
+ immVertex2f(pos, 0.0f, -grid);
+ immVertex2f(pos, 0.0f, +grid);
+
+ immEnd();
+ immUnbindProgram();
+
+ /* done with XY plane */
+ }
+
+ if (show_axis_x || show_axis_y || show_axis_z) {
+ /* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2);
+
+ if (show_axis_x) {
+ UI_make_axis_color(col_grid, col_axis, 'X');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, -grid, 0.0f, 0.0f);
+ immVertex3f(pos, +grid, 0.0f, 0.0f);
+ }
+
+ if (show_axis_y) {
+ UI_make_axis_color(col_grid, col_axis, 'Y');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, 0.0f, -grid, 0.0f);
+ immVertex3f(pos, 0.0f, +grid, 0.0f);
+ }
+
+ if (show_axis_z) {
+ UI_make_axis_color(col_grid, col_axis, 'Z');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, 0.0f, 0.0f, -grid);
+ immVertex3f(pos, 0.0f, 0.0f, +grid);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
+ }
+}
+
+void DRW_draw_grid(void)
+{
+ /* TODO viewport
+ * Missing is the flags to check whether to draw it
+ * for now now we are using the flags in v3d itself.
+ *
+ * Also for now always assume depth is there, so we
+ * draw on top of it.
+ */
+ /**
+ * Calculate pixel-size factor once, is used for lamps and object centers.
+ * Used by #ED_view3d_pixel_size and typically not accessed directly.
+ *
+ * \note #BKE_camera_params_compute_viewplane' also calculates a pixel-size value,
+ * passed to #RE_SetPixelSize, in ortho mode this is compatible with this value,
+ * but in perspective mode its offset by the near-clip.
+ *
+ * 'RegionView3D.pixsize' is used for viewport drawing, not rendering.
+ */
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ View3D *v3d = draw_ctx->v3d;
+ ARegion *ar = draw_ctx->ar;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+
+ const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
+ const char *grid_unit = NULL;
+
+ /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
+ * objects if done last
+ * needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views.
+ */
+ rv3d->gridview = ED_view3d_grid_scale(scene, v3d, &grid_unit);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ if (!draw_floor) {
+ /* Do not get in front of overlays */
+ glDepthMask(GL_FALSE);
+
+ ED_region_pixelspace(ar);
+ *(&grid_unit) = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
+ drawgrid(&scene->unit, ar, v3d, &grid_unit);
+
+ gpuLoadProjectionMatrix(rv3d->winmat);
+ gpuLoadMatrix(rv3d->viewmat);
+ }
+ else {
+ glDepthMask(GL_TRUE);
+ drawfloor(scene, v3d, &grid_unit);
+ }
+}
+
+/* ************************* Background ************************** */
+
+void DRW_draw_background(void)
+{
+ /* Just to make sure */
+ glDepthMask(GL_TRUE);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glStencilMask(0xFF);
+
+ if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+ float m[4][4];
+ unit_m4(m);
+
+ /* Gradient background Color */
+ glDisable(GL_DEPTH_TEST);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ unsigned char col_hi[3], col_lo[3];
+
+ gpuPushMatrix();
+ gpuLoadIdentity();
+ gpuLoadProjectionMatrix(m);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
+ UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
+
+ immBegin(GWN_PRIM_TRI_FAN, 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();
+
+ gpuPopMatrix();
+
+ glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ glEnable(GL_DEPTH_TEST);
+ }
+ else {
+ /* Solid background Color */
+ UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ }
+}
+
+/* **************************** 3D Cursor ******************************** */
+
+static bool is_cursor_visible(Scene *scene, ViewLayer *view_layer)
+{
+ Object *ob = OBACT(view_layer);
+
+ /* don't draw cursor in paint modes, but with a few exceptions */
+ if (ob && ob->mode & OB_MODE_ALL_PAINT) {
+ /* exception: object is in weight paint and has deforming armature in pose mode */
+ if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (BKE_object_pose_armature_get(ob) != NULL) {
+ return true;
+ }
+ }
+ /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
+ else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ const Paint *p = BKE_paint_get_active(scene, view_layer);
+
+ if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
+ if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
+ return true;
+ }
+ }
+ }
+
+ /* no exception met? then don't draw cursor! */
+ return false;
+ }
+
+ return true;
+}
+
+void DRW_draw_cursor(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ Scene *scene = draw_ctx->scene;
+ ViewLayer *view_layer = draw_ctx->view_layer;
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_DEPTH_TEST);
+ glLineWidth(1.0f);
+
+ if (is_cursor_visible(scene, view_layer)) {
+ float *co = ED_view3d_cursor3d_get(scene, v3d);
+ unsigned char crosshair_color[3];
+
+ const float f5 = 0.25f;
+ const float f10 = 0.5f;
+ const float f20 = 1.0f;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ unsigned int wpos = GWN_vertformat_attr_add(format, "world_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ /* XXX Using instance shader without instance */
+ immBindBuiltinProgram(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR);
+ immUniform1f("size", U.widget_unit);
+ immUniform1f("pixel_size", *DRW_viewport_pixelsize_get());
+ immUniformArray3fv("screen_vecs", DRW_viewport_screenvecs_get(), 2);
+ immUniformMatrix4fv("ViewProjectionMatrix", rv3d->persmat);
+
+ const int segments = 16;
+
+ immBegin(GWN_PRIM_LINE_LOOP, segments);
+ immAttrib3fv(wpos, co);
+
+ for (int i = 0; i < segments; ++i) {
+ float angle = (float)(2 * M_PI) * ((float)i / (float)segments);
+ float x = f10 * cosf(angle);
+ float y = f10 * sinf(angle);
+
+ if (i % 2 == 0)
+ immAttrib3ub(color, 255, 0, 0);
+ else
+ immAttrib3ub(color, 255, 255, 255);
+
+ immVertex2f(pos, x, y);
+ }
+ immEnd();
+
+ UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color);
+
+ immBegin(GWN_PRIM_LINES, 8);
+ immAttrib3ubv(color, crosshair_color);
+ immAttrib3fv(wpos, co);
+
+ immVertex2f(pos, -f20, 0);
+ immVertex2f(pos, -f5, 0);
+ immVertex2f(pos, +f5, 0);
+ immVertex2f(pos, +f20, 0);
+ immVertex2f(pos, 0, -f20);
+ immVertex2f(pos, 0, -f5);
+ immVertex2f(pos, 0, +f5);
+ immVertex2f(pos, 0, +f20);
+ immEnd();
+
+ immUnbindProgram();
+ }
+}
+
+/* **************************** 3D Manipulator ******************************** */
+
+void DRW_draw_manipulator(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ v3d->zbuf = false;
+ ARegion *ar = draw_ctx->ar;
+
+
+ /* TODO, only draws 3D manipulators right now, need to see how 2D drawing will work in new viewport */
+
+ /* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */
+ /* TODO depth culling manipulators is not yet supported, just drawing _3D here, should
+ * later become _IN_SCENE (and draw _3D separate) */
+ WM_manipulatormap_draw(
+ ar->manipulator_map, draw_ctx->evil_C,
+ WM_MANIPULATORMAP_DRAWSTEP_3D);
+
+ /* We may want to split this into a separate pass.
+ * or maintain a stage in the draw manager where all pixel-space drawing happens. */
+ {
+ float original_proj[4][4];
+ gpuGetProjectionMatrix(original_proj);
+ wmOrtho2_region_pixelspace(ar);
+
+ gpuPushMatrix();
+ gpuLoadIdentity();
+
+ glDepthMask(GL_FALSE);
+
+ WM_manipulatormap_draw(
+ ar->manipulator_map, draw_ctx->evil_C,
+ WM_MANIPULATORMAP_DRAWSTEP_2D);
+
+ glDepthMask(GL_TRUE);
+
+ gpuPopMatrix();
+ gpuLoadProjectionMatrix(original_proj);
+ }
+}
diff --git a/source/blender/draw/intern/draw_view.h b/source/blender/draw/intern/draw_view.h
new file mode 100644
index 00000000000..b400ceeffa2
--- /dev/null
+++ b/source/blender/draw/intern/draw_view.h
@@ -0,0 +1,35 @@
+/*
+ * 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_view.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_VIEW_H__
+#define __DRAW_VIEW_H__
+
+void DRW_draw_grid(void);
+void DRW_draw_region_info(void);
+void DRW_draw_background(void);
+void DRW_draw_cursor(void);
+void DRW_draw_manipulator(void);
+
+#endif /* __DRAW_VIEW_H__ */ \ No newline at end of file
diff --git a/source/blender/draw/modes/draw_mode_engines.h b/source/blender/draw/modes/draw_mode_engines.h
new file mode 100644
index 00000000000..23fedbba5a5
--- /dev/null
+++ b/source/blender/draw/modes/draw_mode_engines.h
@@ -0,0 +1,44 @@
+/*
+ * 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/modes/draw_mode_engines.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_MODE_ENGINES_H__
+#define __DRAW_MODE_ENGINES_H__
+
+extern DrawEngineType draw_engine_object_type;
+extern DrawEngineType draw_engine_edit_armature_type;
+extern DrawEngineType draw_engine_edit_curve_type;
+extern DrawEngineType draw_engine_edit_lattice_type;
+extern DrawEngineType draw_engine_edit_mesh_type;
+extern DrawEngineType draw_engine_edit_metaball_type;
+extern DrawEngineType draw_engine_edit_surface_type;
+extern DrawEngineType draw_engine_edit_text_type;
+extern DrawEngineType draw_engine_paint_texture_type;
+extern DrawEngineType draw_engine_paint_vertex_type;
+extern DrawEngineType draw_engine_paint_weight_type;
+extern DrawEngineType draw_engine_particle_type;
+extern DrawEngineType draw_engine_pose_type;
+extern DrawEngineType draw_engine_sculpt_type;
+
+#endif /* __DRAW_MODE_ENGINES_H__ */ \ No newline at end of file
diff --git a/source/blender/draw/modes/edit_armature_mode.c b/source/blender/draw/modes/edit_armature_mode.c
new file mode 100644
index 00000000000..4deb4f86692
--- /dev/null
+++ b/source/blender/draw/modes/edit_armature_mode.c
@@ -0,0 +1,157 @@
+/*
+ * 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/modes/edit_armature_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_armature_types.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+extern GlobalsUboStorage ts;
+
+/* *********** LISTS *********** */
+typedef struct EDIT_ARMATURE_PassList {
+ struct DRWPass *bone_solid;
+ struct DRWPass *bone_wire;
+ struct DRWPass *bone_envelope;
+ struct DRWPass *relationship;
+} EDIT_ARMATURE_PassList;
+
+typedef struct EDIT_ARMATURE_StorageList {
+ struct EDIT_ARMATURE_PrivateData *g_data;
+} EDIT_ARMATURE_StorageList;
+
+typedef struct EDIT_ARMATURE_Data {
+ void *engine_type;
+ DRWViewportEmptyList *fbl;
+ DRWViewportEmptyList *txl;
+ EDIT_ARMATURE_PassList *psl;
+ EDIT_ARMATURE_StorageList *stl;
+} EDIT_ARMATURE_Data;
+
+/* *********** STATIC *********** */
+
+typedef struct EDIT_ARMATURE_PrivateData {
+ DRWShadingGroup *relationship_lines;
+} EDIT_ARMATURE_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+static void EDIT_ARMATURE_cache_init(void *vedata)
+{
+ EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl;
+ EDIT_ARMATURE_StorageList *stl = ((EDIT_ARMATURE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Solid bones */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ psl->bone_solid = DRW_pass_create("Bone Solid Pass", state);
+ }
+
+ {
+ /* Wire bones */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+ psl->bone_wire = DRW_pass_create("Bone Wire Pass", state);
+ }
+
+ {
+ /* distance outline around envelope bones */
+ DRWState state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+ psl->bone_envelope = DRW_pass_create("Bone Envelope Outline Pass", state);
+ }
+
+ {
+ /* Non Meshes Pass (Camera, empties, lamps ...) */
+ DRWState state =
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS |
+ DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->relationship = DRW_pass_create("Bone Relationship Pass", state);
+
+ /* Relationship Lines */
+ stl->g_data->relationship_lines = shgroup_dynlines_uniform_color(psl->relationship, ts.colorWire);
+ DRW_shgroup_state_enable(stl->g_data->relationship_lines, DRW_STATE_STIPPLE_3);
+ }
+}
+
+static void EDIT_ARMATURE_cache_populate(void *vedata, Object *ob)
+{
+ bArmature *arm = ob->data;
+ EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl;
+ EDIT_ARMATURE_StorageList *stl = ((EDIT_ARMATURE_Data *)vedata)->stl;
+
+ if (ob->type == OB_ARMATURE) {
+ if (arm->edbo) {
+ DRW_shgroup_armature_edit(
+ ob, psl->bone_solid, psl->bone_wire, psl->bone_envelope, stl->g_data->relationship_lines);
+ }
+ }
+}
+
+static void EDIT_ARMATURE_draw_scene(void *vedata)
+{
+ EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+
+ MULTISAMPLE_SYNC_ENABLE(dfbl)
+
+ DRW_draw_pass(psl->bone_envelope);
+ DRW_draw_pass(psl->bone_solid);
+ DRW_draw_pass(psl->bone_wire);
+ DRW_draw_pass(psl->relationship);
+
+ MULTISAMPLE_SYNC_DISABLE(dfbl)
+}
+
+#if 0
+void EDIT_ARMATURE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ //BKE_collection_engine_property_add_int(ces, "show_occlude_wire", false);
+}
+#endif
+
+static const DrawEngineDataSize EDIT_ARMATURE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_ARMATURE_Data);
+
+DrawEngineType draw_engine_edit_armature_type = {
+ NULL, NULL,
+ N_("EditArmatureMode"),
+ &EDIT_ARMATURE_data_size,
+ NULL,
+ NULL,
+ &EDIT_ARMATURE_cache_init,
+ &EDIT_ARMATURE_cache_populate,
+ NULL,
+ NULL,
+ &EDIT_ARMATURE_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c
new file mode 100644
index 00000000000..1ecf1a60a35
--- /dev/null
+++ b/source/blender/draw/modes/edit_curve_mode.c
@@ -0,0 +1,334 @@
+/*
+ * 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/modes/edit_curve_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_curve_types.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+#include "GPU_batch.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_edit_curve_overlay_loosevert_vert_glsl[];
+extern char datatoc_edit_curve_overlay_frag_glsl[];
+
+extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
+extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use EDIT_CURVE_engine_init() to
+ * initialize most of them and EDIT_CURVE_cache_init()
+ * for EDIT_CURVE_PassList */
+
+typedef struct EDIT_CURVE_PassList {
+ /* Declare all passes here and init them in
+ * EDIT_CURVE_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *wire_pass;
+ struct DRWPass *overlay_edge_pass;
+ struct DRWPass *overlay_vert_pass;
+} EDIT_CURVE_PassList;
+
+typedef struct EDIT_CURVE_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} EDIT_CURVE_FramebufferList;
+
+typedef struct EDIT_CURVE_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} EDIT_CURVE_TextureList;
+
+typedef struct EDIT_CURVE_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct EDIT_CURVE_PrivateData *g_data;
+} EDIT_CURVE_StorageList;
+
+typedef struct EDIT_CURVE_Data {
+ /* Struct returned by DRW_viewport_engine_data_ensure.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ EDIT_CURVE_FramebufferList *fbl;
+ EDIT_CURVE_TextureList *txl;
+ EDIT_CURVE_PassList *psl;
+ EDIT_CURVE_StorageList *stl;
+} EDIT_CURVE_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in EDIT_CURVE_engine_init();
+ * free in EDIT_CURVE_engine_free(); */
+
+ GPUShader *wire_sh;
+
+ GPUShader *overlay_edge_sh; /* handles and nurbs control cage */
+ GPUShader *overlay_vert_sh;
+
+} e_data = {NULL}; /* Engine data */
+
+typedef struct EDIT_CURVE_PrivateData {
+ /* This keeps the references of the shading groups for
+ * easy access in EDIT_CURVE_cache_populate() */
+
+ /* resulting curve as 'wire' for curves (and optionally normals) */
+ DRWShadingGroup *wire_shgrp;
+
+ DRWShadingGroup *overlay_edge_shgrp;
+ DRWShadingGroup *overlay_vert_shgrp;
+} EDIT_CURVE_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void EDIT_CURVE_engine_init(void *vedata)
+{
+ EDIT_CURVE_TextureList *txl = ((EDIT_CURVE_Data *)vedata)->txl;
+ EDIT_CURVE_FramebufferList *fbl = ((EDIT_CURVE_Data *)vedata)->fbl;
+ EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_TEX_DEPTH_24, 0},
+ * {&txl->color, DRW_TEX_RGBA_8, DRW_TEX_FILTER}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.wire_sh) {
+ e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+
+ if (!e_data.overlay_edge_sh) {
+ e_data.overlay_edge_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+
+ if (!e_data.overlay_vert_sh) {
+ e_data.overlay_vert_sh = DRW_shader_create_with_lib(
+ datatoc_edit_curve_overlay_loosevert_vert_glsl, NULL,
+ datatoc_edit_curve_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void EDIT_CURVE_cache_init(void *vedata)
+{
+ EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl;
+ EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Center-Line (wire) */
+ psl->wire_pass = DRW_pass_create(
+ "Curve Wire",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE);
+ stl->g_data->wire_shgrp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass);
+
+
+ /* TODO: following handle theme colors,
+ * For now use overlay vert shader for handles (we want them colored):
+ * TH_NURB_ULINE, TH_NURB_SEL_ULINE, TH_HANDLE_* */
+ psl->overlay_edge_pass = DRW_pass_create(
+ "Curve Handle Overlay",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_WIRE);
+ /* TODO: following handle theme colors,
+ * For now use overlay vert shader for handles (we want them colored) */
+ stl->g_data->overlay_edge_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->overlay_edge_pass);
+
+ psl->overlay_vert_pass = DRW_pass_create(
+ "Curve Vert Overlay",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_POINT);
+ stl->g_data->overlay_vert_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->overlay_vert_pass);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void EDIT_CURVE_cache_populate(void *vedata, Object *ob)
+{
+ EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl;
+ EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const Scene *scene = draw_ctx->scene;
+ const Object *obedit = scene->obedit;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_CURVE) {
+ if (ob == obedit) {
+ Curve *cu = ob->data;
+ /* Get geometry cache */
+ struct Gwn_Batch *geom;
+
+ geom = DRW_cache_curve_edge_wire_get(ob);
+ DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
+
+ if ((cu->flag & CU_3D) && (cu->drawflag & CU_HIDE_NORMALS) == 0) {
+ geom = DRW_cache_curve_edge_normal_get(ob, scene->toolsettings->normalsize);
+ DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
+ }
+
+ /* Add geom to a shading group */
+ geom = DRW_cache_curve_edge_overlay_get(ob);
+ if (geom) {
+ DRW_shgroup_call_add(stl->g_data->overlay_edge_shgrp, geom, ob->obmat);
+ }
+
+ geom = DRW_cache_curve_vert_overlay_get(ob);
+ DRW_shgroup_call_add(stl->g_data->overlay_vert_shgrp, geom, ob->obmat);
+ }
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void EDIT_CURVE_cache_finish(void *vedata)
+{
+ EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl;
+ EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void EDIT_CURVE_draw_scene(void *vedata)
+{
+ EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl;
+ EDIT_CURVE_FramebufferList *fbl = ((EDIT_CURVE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dtxl);
+
+ MULTISAMPLE_SYNC_ENABLE(dfbl)
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->wire_pass);
+ DRW_draw_pass(psl->overlay_edge_pass);
+ DRW_draw_pass(psl->overlay_vert_pass);
+
+ MULTISAMPLE_SYNC_DISABLE(dfbl)
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void EDIT_CURVE_engine_free(void)
+{
+ // DRW_SHADER_FREE_SAFE(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void EDIT_CURVE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+static const DrawEngineDataSize EDIT_CURVE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_CURVE_Data);
+
+DrawEngineType draw_engine_edit_curve_type = {
+ NULL, NULL,
+ N_("EditCurveMode"),
+ &EDIT_CURVE_data_size,
+ &EDIT_CURVE_engine_init,
+ &EDIT_CURVE_engine_free,
+ &EDIT_CURVE_cache_init,
+ &EDIT_CURVE_cache_populate,
+ &EDIT_CURVE_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &EDIT_CURVE_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c
new file mode 100644
index 00000000000..ff4c557326e
--- /dev/null
+++ b/source/blender/draw/modes/edit_lattice_mode.c
@@ -0,0 +1,297 @@
+/*
+ * 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/modes/edit_lattice_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_edit_lattice_overlay_loosevert_vert_glsl[];
+extern char datatoc_edit_lattice_overlay_frag_glsl[];
+
+extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
+extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use EDIT_LATTICE_engine_init() to
+ * initialize most of them and EDIT_LATTICE_cache_init()
+ * for EDIT_LATTICE_PassList */
+
+typedef struct EDIT_LATTICE_PassList {
+ /* Declare all passes here and init them in
+ * EDIT_LATTICE_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *wire_pass;
+ struct DRWPass *vert_pass;
+} EDIT_LATTICE_PassList;
+
+typedef struct EDIT_LATTICE_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} EDIT_LATTICE_FramebufferList;
+
+typedef struct EDIT_LATTICE_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} EDIT_LATTICE_TextureList;
+
+typedef struct EDIT_LATTICE_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct EDIT_LATTICE_PrivateData *g_data;
+} EDIT_LATTICE_StorageList;
+
+typedef struct EDIT_LATTICE_Data {
+ /* Struct returned by DRW_viewport_engine_data_ensure.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ EDIT_LATTICE_FramebufferList *fbl;
+ EDIT_LATTICE_TextureList *txl;
+ EDIT_LATTICE_PassList *psl;
+ EDIT_LATTICE_StorageList *stl;
+} EDIT_LATTICE_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in EDIT_LATTICE_engine_init();
+ * free in EDIT_LATTICE_engine_free(); */
+ GPUShader *wire_sh;
+
+ GPUShader *overlay_vert_sh;
+
+} e_data = {NULL}; /* Engine data */
+
+typedef struct EDIT_LATTICE_PrivateData {
+ /* This keeps the references of the shading groups for
+ * easy access in EDIT_LATTICE_cache_populate() */
+ DRWShadingGroup *wire_shgrp;
+ DRWShadingGroup *vert_shgrp;
+} EDIT_LATTICE_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void EDIT_LATTICE_engine_init(void *vedata)
+{
+ EDIT_LATTICE_TextureList *txl = ((EDIT_LATTICE_Data *)vedata)->txl;
+ EDIT_LATTICE_FramebufferList *fbl = ((EDIT_LATTICE_Data *)vedata)->fbl;
+ EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_TEX_DEPTH_24, 0},
+ * {&txl->color, DRW_TEX_RGBA_8, DRW_TEX_FILTER}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.wire_sh) {
+ e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SMOOTH_COLOR);
+ }
+
+ if (!e_data.overlay_vert_sh) {
+ e_data.overlay_vert_sh = DRW_shader_create_with_lib(
+ datatoc_edit_lattice_overlay_loosevert_vert_glsl, NULL,
+ datatoc_edit_lattice_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void EDIT_LATTICE_cache_init(void *vedata)
+{
+ EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl;
+ EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ psl->wire_pass = DRW_pass_create(
+ "Lattice Wire",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE);
+ stl->g_data->wire_shgrp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass);
+
+ psl->vert_pass = DRW_pass_create(
+ "Lattice Verts",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_POINT);
+ stl->g_data->vert_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->vert_pass);
+
+ DRW_shgroup_uniform_block(stl->g_data->vert_shgrp, "globalsBlock", globals_ubo);
+ }
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void EDIT_LATTICE_cache_populate(void *vedata, Object *ob)
+{
+ EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl;
+ EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ Object *obedit = scene->obedit;
+
+ UNUSED_VARS(psl);
+
+ if (ob->type == OB_LATTICE) {
+ if (ob == obedit) {
+ /* Get geometry cache */
+ struct Gwn_Batch *geom;
+
+ geom = DRW_cache_lattice_wire_get(ob, true);
+ DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
+
+ geom = DRW_cache_lattice_vert_overlay_get(ob);
+ DRW_shgroup_call_add(stl->g_data->vert_shgrp, geom, ob->obmat);
+ }
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void EDIT_LATTICE_cache_finish(void *vedata)
+{
+ EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl;
+ EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void EDIT_LATTICE_draw_scene(void *vedata)
+{
+ EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl;
+ EDIT_LATTICE_FramebufferList *fbl = ((EDIT_LATTICE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dtxl);
+
+ MULTISAMPLE_SYNC_ENABLE(dfbl)
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->wire_pass);
+ DRW_draw_pass(psl->vert_pass);
+
+ MULTISAMPLE_SYNC_DISABLE(dfbl)
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void EDIT_LATTICE_engine_free(void)
+{
+ // Currently built-in, dont free
+ DRW_SHADER_FREE_SAFE(e_data.overlay_vert_sh);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void EDIT_LATTICE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+static const DrawEngineDataSize EDIT_LATTICE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_LATTICE_Data);
+
+DrawEngineType draw_engine_edit_lattice_type = {
+ NULL, NULL,
+ N_("EditLatticeMode"),
+ &EDIT_LATTICE_data_size,
+ &EDIT_LATTICE_engine_init,
+ &EDIT_LATTICE_engine_free,
+ &EDIT_LATTICE_cache_init,
+ &EDIT_LATTICE_cache_populate,
+ &EDIT_LATTICE_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &EDIT_LATTICE_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c
new file mode 100644
index 00000000000..1a8c03e3933
--- /dev/null
+++ b/source/blender/draw/modes/edit_mesh_mode.c
@@ -0,0 +1,613 @@
+/*
+ * 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/modes/edit_mesh_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "GPU_shader.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_view3d_types.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+#include "edit_mesh_mode_intern.h" /* own include */
+
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+extern char datatoc_edit_mesh_overlay_frag_glsl[];
+extern char datatoc_edit_mesh_overlay_vert_glsl[];
+extern char datatoc_edit_mesh_overlay_geom_tri_glsl[];
+extern char datatoc_edit_mesh_overlay_geom_edge_glsl[];
+extern char datatoc_edit_mesh_overlay_loosevert_vert_glsl[];
+extern char datatoc_edit_mesh_overlay_facedot_frag_glsl[];
+extern char datatoc_edit_mesh_overlay_facedot_vert_glsl[];
+extern char datatoc_edit_mesh_overlay_mix_vert_glsl[];
+extern char datatoc_edit_mesh_overlay_mix_frag_glsl[];
+extern char datatoc_edit_mesh_overlay_facefill_vert_glsl[];
+extern char datatoc_edit_mesh_overlay_facefill_frag_glsl[];
+extern char datatoc_edit_normals_vert_glsl[];
+extern char datatoc_edit_normals_geom_glsl[];
+extern char datatoc_common_globals_lib_glsl[];
+
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
+
+/* *********** LISTS *********** */
+typedef struct EDIT_MESH_PassList {
+ struct DRWPass *vcolor_faces;
+ struct DRWPass *depth_hidden_wire;
+ struct DRWPass *edit_face_overlay;
+ struct DRWPass *edit_face_occluded;
+ struct DRWPass *mix_occlude;
+ struct DRWPass *facefill_occlude;
+ struct DRWPass *normals;
+} EDIT_MESH_PassList;
+
+typedef struct EDIT_MESH_FramebufferList {
+ struct GPUFrameBuffer *occlude_wire_fb;
+} EDIT_MESH_FramebufferList;
+
+typedef struct EDIT_MESH_StorageList {
+ struct EDIT_MESH_PrivateData *g_data;
+} EDIT_MESH_StorageList;
+
+typedef struct EDIT_MESH_Data {
+ void *engine_type;
+ EDIT_MESH_FramebufferList *fbl;
+ DRWViewportEmptyList *txl;
+ EDIT_MESH_PassList *psl;
+ EDIT_MESH_StorageList *stl;
+} EDIT_MESH_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* weight/vert-color */
+ GPUShader *vcolor_face_shader;
+ GPUShader *overlay_tri_sh;
+ GPUShader *overlay_tri_fast_sh;
+ GPUShader *overlay_tri_vcol_sh;
+ GPUShader *overlay_tri_vcol_fast_sh;
+ GPUShader *overlay_edge_sh;
+ GPUShader *overlay_edge_vcol_sh;
+ GPUShader *overlay_vert_sh;
+ GPUShader *overlay_facedot_sh;
+ GPUShader *overlay_mix_sh;
+ GPUShader *overlay_facefill_sh;
+ GPUShader *normals_face_sh;
+ GPUShader *normals_loop_sh;
+ GPUShader *normals_sh;
+ GPUShader *depth_sh;
+ /* temp buffer texture */
+ struct GPUTexture *occlude_wire_depth_tx;
+ struct GPUTexture *occlude_wire_color_tx;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct EDIT_MESH_PrivateData {
+ /* weight/vert-color */
+ DRWShadingGroup *fvcolor_shgrp;
+ DRWShadingGroup *depth_shgrp_hidden_wire;
+
+ DRWShadingGroup *fnormals_shgrp;
+ DRWShadingGroup *vnormals_shgrp;
+ DRWShadingGroup *lnormals_shgrp;
+
+ DRWShadingGroup *face_overlay_shgrp;
+ DRWShadingGroup *ledges_overlay_shgrp;
+ DRWShadingGroup *lverts_overlay_shgrp;
+ DRWShadingGroup *facedot_overlay_shgrp;
+
+ DRWShadingGroup *face_occluded_shgrp;
+ DRWShadingGroup *ledges_occluded_shgrp;
+ DRWShadingGroup *lverts_occluded_shgrp;
+ DRWShadingGroup *facedot_occluded_shgrp;
+ DRWShadingGroup *facefill_occluded_shgrp;
+
+} EDIT_MESH_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+static void EDIT_MESH_engine_init(void *vedata)
+{
+ EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl;
+
+ const float *viewport_size = DRW_viewport_size_get();
+
+ DRWFboTexture tex[2] = {{
+ &e_data.occlude_wire_depth_tx, DRW_TEX_DEPTH_24, DRW_TEX_TEMP},
+ {&e_data.occlude_wire_color_tx, DRW_TEX_RGBA_8, DRW_TEX_FILTER | DRW_TEX_TEMP}
+ };
+ DRW_framebuffer_init(
+ &fbl->occlude_wire_fb, &draw_engine_edit_mesh_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ tex, ARRAY_SIZE(tex));
+
+ if (!e_data.vcolor_face_shader) {
+ e_data.vcolor_face_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA);
+ }
+
+ if (!e_data.overlay_tri_sh) {
+ e_data.overlay_tri_sh = DRW_shader_create_with_lib(
+ datatoc_edit_mesh_overlay_vert_glsl,
+ datatoc_edit_mesh_overlay_geom_tri_glsl,
+ datatoc_edit_mesh_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define EDGE_FIX\n"
+ "#define ANTI_ALIASING\n"
+ "#define VERTEX_FACING");
+ }
+ if (!e_data.overlay_tri_fast_sh) {
+ e_data.overlay_tri_fast_sh = DRW_shader_create_with_lib(
+ datatoc_edit_mesh_overlay_vert_glsl,
+ datatoc_edit_mesh_overlay_geom_tri_glsl,
+ datatoc_edit_mesh_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define ANTI_ALIASING\n"
+ "#define VERTEX_FACING\n");
+ }
+ if (!e_data.overlay_tri_vcol_sh) {
+ e_data.overlay_tri_vcol_sh = DRW_shader_create_with_lib(
+ datatoc_edit_mesh_overlay_vert_glsl,
+ datatoc_edit_mesh_overlay_geom_tri_glsl,
+ datatoc_edit_mesh_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define EDGE_FIX\n"
+ "#define VERTEX_SELECTION\n"
+ "#define ANTI_ALIASING\n"
+ "#define VERTEX_FACING\n");
+ }
+ if (!e_data.overlay_tri_vcol_fast_sh) {
+ e_data.overlay_tri_vcol_fast_sh = DRW_shader_create_with_lib(
+ datatoc_edit_mesh_overlay_vert_glsl,
+ datatoc_edit_mesh_overlay_geom_tri_glsl,
+ datatoc_edit_mesh_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define VERTEX_SELECTION\n"
+ "#define ANTI_ALIASING\n"
+ "#define VERTEX_FACING\n");
+ }
+ if (!e_data.overlay_edge_sh) {
+ e_data.overlay_edge_sh = DRW_shader_create_with_lib(
+ datatoc_edit_mesh_overlay_vert_glsl,
+ datatoc_edit_mesh_overlay_geom_edge_glsl,
+ datatoc_edit_mesh_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define ANTI_ALIASING\n"
+ "#define VERTEX_FACING\n");
+ }
+ if (!e_data.overlay_edge_vcol_sh) {
+ e_data.overlay_edge_vcol_sh = DRW_shader_create_with_lib(
+ datatoc_edit_mesh_overlay_vert_glsl,
+ datatoc_edit_mesh_overlay_geom_edge_glsl,
+ datatoc_edit_mesh_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define VERTEX_SELECTION\n"
+ "#define VERTEX_FACING\n");
+ }
+ if (!e_data.overlay_vert_sh) {
+ e_data.overlay_vert_sh = DRW_shader_create_with_lib(
+ datatoc_edit_mesh_overlay_loosevert_vert_glsl, NULL,
+ datatoc_edit_mesh_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define VERTEX_SELECTION\n");
+ }
+ if (!e_data.overlay_facedot_sh) {
+ e_data.overlay_facedot_sh = DRW_shader_create_with_lib(
+ datatoc_edit_mesh_overlay_facedot_vert_glsl, NULL,
+ datatoc_edit_mesh_overlay_facedot_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define VERTEX_FACING\n");
+ }
+ if (!e_data.overlay_mix_sh) {
+ e_data.overlay_mix_sh = DRW_shader_create_fullscreen(datatoc_edit_mesh_overlay_mix_frag_glsl, NULL);
+ }
+ if (!e_data.overlay_facefill_sh) {
+ e_data.overlay_facefill_sh = DRW_shader_create_with_lib(
+ datatoc_edit_mesh_overlay_facefill_vert_glsl, NULL,
+ datatoc_edit_mesh_overlay_facefill_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+ }
+ if (!e_data.normals_face_sh) {
+ e_data.normals_face_sh = DRW_shader_create(
+ datatoc_edit_normals_vert_glsl,
+ datatoc_edit_normals_geom_glsl,
+ datatoc_gpu_shader_uniform_color_frag_glsl,
+ "#define FACE_NORMALS\n");
+ }
+ if (!e_data.normals_loop_sh) {
+ e_data.normals_loop_sh = DRW_shader_create(
+ datatoc_edit_normals_vert_glsl,
+ datatoc_edit_normals_geom_glsl,
+ datatoc_gpu_shader_uniform_color_frag_glsl,
+ "#define LOOP_NORMALS\n");
+ }
+ if (!e_data.normals_sh) {
+ e_data.normals_sh = DRW_shader_create(
+ datatoc_edit_normals_vert_glsl,
+ datatoc_edit_normals_geom_glsl,
+ datatoc_gpu_shader_uniform_color_frag_glsl, NULL);
+ }
+ if (!e_data.depth_sh) {
+ e_data.depth_sh = DRW_shader_create_3D_depth_only();
+ }
+}
+
+static DRWPass *edit_mesh_create_overlay_pass(
+ float *faceAlpha, DRWState statemod,
+ DRWShadingGroup **r_face_shgrp, DRWShadingGroup **r_ledges_shgrp,
+ DRWShadingGroup **r_lverts_shgrp, DRWShadingGroup **r_facedot_shgrp)
+{
+ GPUShader *tri_sh, *ledge_sh;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ Scene *scene = draw_ctx->scene;
+ ToolSettings *tsettings = scene->toolsettings;
+
+ if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) {
+ ledge_sh = e_data.overlay_edge_vcol_sh;
+
+ if ((rv3d->rflag & RV3D_NAVIGATING) != 0)
+ tri_sh = e_data.overlay_tri_vcol_fast_sh;
+ else
+ tri_sh = e_data.overlay_tri_vcol_sh;
+ }
+ else {
+ ledge_sh = e_data.overlay_edge_sh;
+
+ if ((rv3d->rflag & RV3D_NAVIGATING) != 0)
+ tri_sh = e_data.overlay_tri_fast_sh;
+ else
+ tri_sh = e_data.overlay_tri_sh;
+ }
+
+ DRWPass *pass = DRW_pass_create(
+ "Edit Mesh Face Overlay Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_POINT | statemod);
+
+ *r_face_shgrp = DRW_shgroup_create(tri_sh, pass);
+ DRW_shgroup_uniform_block(*r_face_shgrp, "globalsBlock", globals_ubo);
+ DRW_shgroup_uniform_vec2(*r_face_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
+ DRW_shgroup_uniform_float(*r_face_shgrp, "faceAlphaMod", faceAlpha, 1);
+
+ *r_ledges_shgrp = DRW_shgroup_create(ledge_sh, pass);
+ DRW_shgroup_uniform_block(*r_ledges_shgrp, "globalsBlock", globals_ubo);
+ DRW_shgroup_uniform_vec2(*r_ledges_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
+
+ if ((tsettings->selectmode & (SCE_SELECT_VERTEX)) != 0) {
+ *r_lverts_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, pass);
+ DRW_shgroup_uniform_block(*r_lverts_shgrp, "globalsBlock", globals_ubo);
+ DRW_shgroup_uniform_vec2(*r_lverts_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
+ }
+
+ if ((tsettings->selectmode & (SCE_SELECT_FACE)) != 0) {
+ *r_facedot_shgrp = DRW_shgroup_create(e_data.overlay_facedot_sh, pass);
+ DRW_shgroup_uniform_block(*r_facedot_shgrp, "globalsBlock", globals_ubo);
+ }
+
+ return pass;
+}
+
+static float backwire_opacity;
+static float face_mod;
+static float size_normal;
+
+static void EDIT_MESH_cache_init(void *vedata)
+{
+ EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl;
+ EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+
+ bool do_zbufclip = ((v3d->flag & V3D_ZBUF_SELECT) == 0);
+
+ static float zero = 0.0f;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ psl->vcolor_faces = DRW_pass_create(
+ "Vert Color Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+
+ stl->g_data->fvcolor_shgrp = DRW_shgroup_create(e_data.vcolor_face_shader, psl->vcolor_faces);
+
+ static float light[3] = {-0.3f, 0.5f, 1.0f};
+ static float alpha = 1.0f;
+ static float world_light = 1.0f; /* XXX, see: paint_vertex_mode.c */
+ DRW_shgroup_uniform_vec3(stl->g_data->fvcolor_shgrp, "light", light, 1);
+ DRW_shgroup_uniform_float(stl->g_data->fvcolor_shgrp, "alpha", &alpha, 1);
+ DRW_shgroup_uniform_float(stl->g_data->fvcolor_shgrp, "global", &world_light, 1);
+ }
+
+ {
+ /* Complementary Depth Pass */
+ psl->depth_hidden_wire = DRW_pass_create(
+ "Depth Pass Hidden Wire",
+ DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
+ stl->g_data->depth_shgrp_hidden_wire = DRW_shgroup_create(e_data.depth_sh, psl->depth_hidden_wire);
+ }
+
+ {
+ /* Normals */
+ psl->normals = DRW_pass_create(
+ "Edit Mesh Normals Pass",
+ DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS);
+
+ stl->g_data->fnormals_shgrp = DRW_shgroup_create(e_data.normals_face_sh, psl->normals);
+ DRW_shgroup_uniform_float(stl->g_data->fnormals_shgrp, "normalSize", &size_normal, 1);
+ DRW_shgroup_uniform_vec4(stl->g_data->fnormals_shgrp, "color", ts.colorNormal, 1);
+
+ stl->g_data->vnormals_shgrp = DRW_shgroup_create(e_data.normals_sh, psl->normals);
+ DRW_shgroup_uniform_float(stl->g_data->vnormals_shgrp, "normalSize", &size_normal, 1);
+ DRW_shgroup_uniform_vec4(stl->g_data->vnormals_shgrp, "color", ts.colorVNormal, 1);
+
+ stl->g_data->lnormals_shgrp = DRW_shgroup_create(e_data.normals_loop_sh, psl->normals);
+ DRW_shgroup_uniform_float(stl->g_data->lnormals_shgrp, "normalSize", &size_normal, 1);
+ DRW_shgroup_uniform_vec4(stl->g_data->lnormals_shgrp, "color", ts.colorLNormal, 1);
+ }
+
+ if (!do_zbufclip) {
+ psl->edit_face_overlay = edit_mesh_create_overlay_pass(
+ &face_mod, DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND,
+ &stl->g_data->face_overlay_shgrp, &stl->g_data->ledges_overlay_shgrp,
+ &stl->g_data->lverts_overlay_shgrp, &stl->g_data->facedot_overlay_shgrp);
+ }
+ else {
+ /* We render all wires with depth and opaque to a new fbo and blend the result based on depth values */
+ psl->edit_face_occluded = edit_mesh_create_overlay_pass(
+ &zero, DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_DEPTH,
+ &stl->g_data->face_occluded_shgrp, &stl->g_data->ledges_occluded_shgrp,
+ &stl->g_data->lverts_occluded_shgrp, &stl->g_data->facedot_occluded_shgrp);
+
+ /* however we loose the front faces value (because we need the depth of occluded wires and
+ * faces are alpha blended ) so we recover them in a new pass. */
+ psl->facefill_occlude = DRW_pass_create(
+ "Front Face Color",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND);
+ stl->g_data->facefill_occluded_shgrp = DRW_shgroup_create(e_data.overlay_facefill_sh, psl->facefill_occlude);
+ DRW_shgroup_uniform_block(stl->g_data->facefill_occluded_shgrp, "globalsBlock", globals_ubo);
+
+ /* we need a full screen pass to combine the result */
+ struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+
+ psl->mix_occlude = DRW_pass_create(
+ "Mix Occluded Wires",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
+ DRWShadingGroup *mix_shgrp = DRW_shgroup_create(e_data.overlay_mix_sh, psl->mix_occlude);
+ DRW_shgroup_call_add(mix_shgrp, quad, NULL);
+ DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1);
+ DRW_shgroup_uniform_buffer(mix_shgrp, "wireColor", &e_data.occlude_wire_color_tx);
+ DRW_shgroup_uniform_buffer(mix_shgrp, "wireDepth", &e_data.occlude_wire_depth_tx);
+ DRW_shgroup_uniform_buffer(mix_shgrp, "sceneDepth", &dtxl->depth);
+ }
+}
+
+static void edit_mesh_add_ob_to_pass(
+ Scene *scene, Object *ob, DRWShadingGroup *face_shgrp, DRWShadingGroup *ledges_shgrp,
+ DRWShadingGroup *lverts_shgrp, DRWShadingGroup *facedot_shgrp, DRWShadingGroup *facefill_shgrp)
+{
+ struct Gwn_Batch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts, *geo_ovl_fcenter;
+ ToolSettings *tsettings = scene->toolsettings;
+
+ DRW_cache_mesh_wire_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts);
+ DRW_shgroup_call_add(face_shgrp, geo_ovl_tris, ob->obmat);
+ DRW_shgroup_call_add(ledges_shgrp, geo_ovl_ledges, ob->obmat);
+
+ if (facefill_shgrp) {
+ DRW_shgroup_call_add(facefill_shgrp, geo_ovl_tris, ob->obmat);
+ }
+
+ if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) {
+ DRW_shgroup_call_add(lverts_shgrp, geo_ovl_lverts, ob->obmat);
+ }
+
+ if ((tsettings->selectmode & SCE_SELECT_FACE) != 0) {
+ geo_ovl_fcenter = DRW_cache_face_centers_get(ob);
+ DRW_shgroup_call_add(facedot_shgrp, geo_ovl_fcenter, ob->obmat);
+ }
+}
+
+static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
+{
+ EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ Scene *scene = draw_ctx->scene;
+ Object *obedit = scene->obedit;
+ struct Gwn_Batch *geom;
+
+ if (ob->type == OB_MESH) {
+ if (ob == obedit) {
+ const Mesh *me = ob->data;
+ IDProperty *ces_mode_ed = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_EDIT, "");
+ bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_occlude_wire");
+ bool do_show_weight = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_weight");
+
+ /* Updating uniform */
+ backwire_opacity = BKE_collection_engine_property_value_get_float(ces_mode_ed, "backwire_opacity");
+
+ bool fnormals_do = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "face_normals_show");
+ bool vnormals_do = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "vert_normals_show");
+ bool lnormals_do = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "loop_normals_show");
+ /* Updating uniform */
+ size_normal = BKE_collection_engine_property_value_get_float(ces_mode_ed, "normals_length");
+
+ face_mod = (do_occlude_wire) ? 0.0f : 1.0f;
+
+ if (do_show_weight) {
+ geom = DRW_cache_mesh_surface_weights_get(ob);
+ DRW_shgroup_call_add(stl->g_data->fvcolor_shgrp, geom, ob->obmat);
+ }
+
+ if (do_occlude_wire) {
+ geom = DRW_cache_mesh_surface_get(ob);
+ DRW_shgroup_call_add(stl->g_data->depth_shgrp_hidden_wire, geom, ob->obmat);
+ }
+
+ if (fnormals_do) {
+ geom = DRW_cache_face_centers_get(ob);
+ DRW_shgroup_call_add(stl->g_data->fnormals_shgrp, geom, ob->obmat);
+ }
+
+ if (vnormals_do || lnormals_do) {
+ struct Gwn_Batch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts;
+ DRW_cache_mesh_normals_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts);
+
+ if (vnormals_do) {
+ DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_tris, ob->obmat);
+ DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_ledges, ob->obmat);
+ DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_lverts, ob->obmat);
+ }
+
+ if (lnormals_do) {
+ DRW_shgroup_call_add(stl->g_data->lnormals_shgrp, geo_ovl_tris, ob->obmat);
+ }
+ }
+
+ if ((v3d->flag & V3D_ZBUF_SELECT) == 0) {
+ edit_mesh_add_ob_to_pass(
+ scene, ob, stl->g_data->face_occluded_shgrp, stl->g_data->ledges_occluded_shgrp,
+ stl->g_data->lverts_occluded_shgrp, stl->g_data->facedot_occluded_shgrp,
+ stl->g_data->facefill_occluded_shgrp);
+ }
+ else {
+ edit_mesh_add_ob_to_pass(
+ scene, ob, stl->g_data->face_overlay_shgrp, stl->g_data->ledges_overlay_shgrp,
+ stl->g_data->lverts_overlay_shgrp, stl->g_data->facedot_overlay_shgrp, NULL);
+ }
+
+ /* 3D text overlay */
+ if (me->drawflag & (ME_DRAWEXTRA_EDGELEN |
+ ME_DRAWEXTRA_FACEAREA |
+ ME_DRAWEXTRA_FACEANG |
+ ME_DRAWEXTRA_EDGEANG))
+ {
+ DRW_edit_mesh_mode_text_measure_stats(
+ draw_ctx->ar, v3d, ob, &scene->unit);
+ }
+ }
+ }
+}
+
+static void EDIT_MESH_draw_scene(void *vedata)
+{
+ EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl;
+ EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ DRW_draw_pass(psl->vcolor_faces);
+
+ DRW_draw_pass(psl->depth_hidden_wire);
+
+ if (psl->edit_face_occluded) {
+ float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* render facefill */
+ DRW_draw_pass(psl->facefill_occlude);
+
+ /* attach temp textures */
+ DRW_framebuffer_texture_attach(fbl->occlude_wire_fb, e_data.occlude_wire_depth_tx, 0, 0);
+ DRW_framebuffer_texture_attach(fbl->occlude_wire_fb, e_data.occlude_wire_color_tx, 0, 0);
+
+ /* Render wires on a separate framebuffer */
+ DRW_framebuffer_bind(fbl->occlude_wire_fb);
+ DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
+ DRW_draw_pass(psl->normals);
+ DRW_draw_pass(psl->edit_face_occluded);
+
+ /* detach textures */
+ DRW_framebuffer_texture_detach(dtxl->depth);
+
+ /* Combine with scene buffer */
+ DRW_framebuffer_bind(dfbl->default_fb);
+ DRW_draw_pass(psl->mix_occlude);
+
+ /* detach temp textures */
+ DRW_framebuffer_texture_detach(e_data.occlude_wire_depth_tx);
+ DRW_framebuffer_texture_detach(e_data.occlude_wire_color_tx);
+
+ /* reattach */
+ DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ }
+ else {
+ DRW_draw_pass(psl->normals);
+ DRW_draw_pass(psl->edit_face_overlay);
+ }
+}
+
+void EDIT_MESH_collection_settings_create(IDProperty *properties)
+{
+ BLI_assert(properties &&
+ properties->type == IDP_GROUP &&
+ properties->subtype == IDP_GROUP_SUB_MODE_EDIT);
+ BKE_collection_engine_property_add_int(properties, "show_occlude_wire", false);
+ BKE_collection_engine_property_add_int(properties, "show_weight", false);
+ BKE_collection_engine_property_add_int(properties, "face_normals_show", false);
+ BKE_collection_engine_property_add_int(properties, "vert_normals_show", false);
+ BKE_collection_engine_property_add_int(properties, "loop_normals_show", false);
+ BKE_collection_engine_property_add_float(properties, "normals_length", 0.1);
+ BKE_collection_engine_property_add_float(properties, "backwire_opacity", 0.5);
+}
+
+static void EDIT_MESH_engine_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.overlay_tri_sh);
+ DRW_SHADER_FREE_SAFE(e_data.overlay_tri_fast_sh);
+ DRW_SHADER_FREE_SAFE(e_data.overlay_tri_vcol_sh);
+ DRW_SHADER_FREE_SAFE(e_data.overlay_tri_vcol_fast_sh);
+ DRW_SHADER_FREE_SAFE(e_data.overlay_edge_sh);
+ DRW_SHADER_FREE_SAFE(e_data.overlay_edge_vcol_sh);
+ DRW_SHADER_FREE_SAFE(e_data.overlay_vert_sh);
+ DRW_SHADER_FREE_SAFE(e_data.overlay_facedot_sh);
+ DRW_SHADER_FREE_SAFE(e_data.overlay_mix_sh);
+ DRW_SHADER_FREE_SAFE(e_data.overlay_facefill_sh);
+ DRW_SHADER_FREE_SAFE(e_data.normals_loop_sh);
+ DRW_SHADER_FREE_SAFE(e_data.normals_face_sh);
+ DRW_SHADER_FREE_SAFE(e_data.normals_sh);
+}
+
+static const DrawEngineDataSize EDIT_MESH_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_MESH_Data);
+
+DrawEngineType draw_engine_edit_mesh_type = {
+ NULL, NULL,
+ N_("EditMeshMode"),
+ &EDIT_MESH_data_size,
+ &EDIT_MESH_engine_init,
+ &EDIT_MESH_engine_free,
+ &EDIT_MESH_cache_init,
+ &EDIT_MESH_cache_populate,
+ NULL,
+ NULL,
+ &EDIT_MESH_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/edit_mesh_mode_intern.h b/source/blender/draw/modes/edit_mesh_mode_intern.h
new file mode 100644
index 00000000000..99298bd41f4
--- /dev/null
+++ b/source/blender/draw/modes/edit_mesh_mode_intern.h
@@ -0,0 +1,38 @@
+/*
+ * ***** 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/draw/modes/edit_mesh_mode_intern.h
+ * \ingroup draw
+ */
+
+#ifndef __EDIT_MESH_MODE_INTERN_H__
+#define __EDIT_MESH_MODE_INTERN_H__
+
+struct ARegion;
+struct Object;
+struct UnitSettings;
+struct View3D;
+
+/* edit_mesh_mode_text.c */
+void DRW_edit_mesh_mode_text_measure_stats(
+ struct ARegion *ar, struct View3D *v3d,
+ struct Object *ob, const UnitSettings *unit);
+
+#endif /* __EDIT_MESH_MODE_INTERN_H__ */
diff --git a/source/blender/draw/modes/edit_mesh_mode_text.c b/source/blender/draw/modes/edit_mesh_mode_text.c
new file mode 100644
index 00000000000..a832c61cab5
--- /dev/null
+++ b/source/blender/draw/modes/edit_mesh_mode_text.c
@@ -0,0 +1,301 @@
+/*
+ * 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/modes/edit_mesh_mode_text.c
+ * \ingroup draw
+ */
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BKE_editmesh.h"
+#include "BKE_global.h"
+#include "BKE_unit.h"
+
+#include "ED_view3d.h"
+
+#include "GPU_shader.h"
+#include "GPU_viewport.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+
+#include "UI_resources.h"
+
+#include "draw_manager_text.h"
+
+#include "edit_mesh_mode_intern.h" /* own include */
+
+/* Copied from drawobject.c */
+void DRW_edit_mesh_mode_text_measure_stats(
+ ARegion *ar, View3D *v3d,
+ Object *ob, const UnitSettings *unit)
+{
+ /* Do not use ascii when using non-default unit system, some unit chars are utf8 (micro, square, etc.).
+ * See bug #36090.
+ */
+ struct DRWTextStore *dt = DRW_text_cache_ensure();
+ const short txt_flag = DRW_TEXT_CACHE_LOCALCLIP | (unit->system ? 0 : DRW_TEXT_CACHE_ASCII);
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ float v1[3], v2[3], v3[3], vmid[3], fvec[3];
+ char numstr[32]; /* Stores the measurement display text here */
+ size_t numstr_len;
+ const char *conv_float; /* Use a float conversion matching the grid size */
+ unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */
+ float area; /* area of the face */
+ float grid = unit->system ? unit->scale_length : v3d->grid;
+ const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
+ const bool do_global = (v3d->flag & V3D_GLOBAL_STATS) != 0;
+ const bool do_moving = (G.moving & G_TRANSFORM_EDIT) != 0;
+ /* when 2 edge-info options are enabled, space apart */
+ const bool do_edge_textpair = (me->drawflag & ME_DRAWEXTRA_EDGELEN) && (me->drawflag & ME_DRAWEXTRA_EDGEANG);
+ const float edge_texpair_sep = 0.4f;
+ float clip_planes[4][4];
+ /* allow for displaying shape keys and deform mods */
+ BMIter iter;
+
+ /* make the precision of the display value proportionate to the gridsize */
+
+ if (grid <= 0.01f) conv_float = "%.6g";
+ else if (grid <= 0.1f) conv_float = "%.5g";
+ else if (grid <= 1.0f) conv_float = "%.4g";
+ else if (grid <= 10.0f) conv_float = "%.3g";
+ else conv_float = "%.2g";
+
+ if (me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_EDGEANG)) {
+ BoundBox bb;
+ const rcti rect = {0, ar->winx, 0, ar->winy};
+
+ ED_view3d_clipping_calc(&bb, clip_planes, ar, em->ob, &rect);
+ }
+
+ if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
+ BMEdge *eed;
+
+ UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ /* draw selected edges, or edges next to selected verts while dragging */
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
+ (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
+ {
+ float v1_clip[3], v2_clip[3];
+
+ copy_v3_v3(v1, eed->v1->co);
+ copy_v3_v3(v2, eed->v2->co);
+
+ if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) {
+
+ if (do_edge_textpair) {
+ interp_v3_v3v3(vmid, v1, v2, edge_texpair_sep);
+ }
+ else {
+ mid_v3_v3v3(vmid, v1_clip, v2_clip);
+ }
+
+ if (do_global) {
+ mul_mat3_m4_v3(ob->obmat, v1);
+ mul_mat3_m4_v3(ob->obmat, v2);
+ }
+
+ if (unit->system) {
+ numstr_len = bUnit_AsString(
+ numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
+ unit->system, B_UNIT_LENGTH, do_split, false);
+ }
+ else {
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2));
+ }
+
+ DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, txt_flag, col);
+ }
+ }
+ }
+ }
+
+ if (me->drawflag & ME_DRAWEXTRA_EDGEANG) {
+ const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS);
+ BMEdge *eed;
+
+ UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGEANG, col);
+
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BMLoop *l_a, *l_b;
+ if (BM_edge_loop_pair(eed, &l_a, &l_b)) {
+ /* draw selected edges, or edges next to selected verts while dragging */
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
+ (do_moving &&
+ (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(eed->v2, BM_ELEM_SELECT) ||
+ /* special case, this is useful to show when verts connected to
+ * this edge via a face are being transformed */
+ BM_elem_flag_test(l_a->next->next->v, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(l_a->prev->v, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(l_b->next->next->v, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(l_b->prev->v, BM_ELEM_SELECT)
+ )))
+ {
+ float v1_clip[3], v2_clip[3];
+
+ copy_v3_v3(v1, eed->v1->co);
+ copy_v3_v3(v2, eed->v2->co);
+
+ if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) {
+ float no_a[3], no_b[3];
+ float angle;
+
+ if (do_edge_textpair) {
+ interp_v3_v3v3(vmid, v2_clip, v1_clip, edge_texpair_sep);
+ }
+ else {
+ mid_v3_v3v3(vmid, v1_clip, v2_clip);
+ }
+
+ copy_v3_v3(no_a, l_a->f->no);
+ copy_v3_v3(no_b, l_b->f->no);
+
+ if (do_global) {
+ mul_mat3_m4_v3(ob->imat, no_a);
+ mul_mat3_m4_v3(ob->imat, no_b);
+ normalize_v3(no_a);
+ normalize_v3(no_b);
+ }
+
+ angle = angle_normalized_v3v3(no_a, no_b);
+
+ numstr_len = BLI_snprintf_rlen(
+ numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
+
+ DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, txt_flag, col);
+ }
+ }
+ }
+ }
+ }
+
+ if (me->drawflag & ME_DRAWEXTRA_FACEAREA) {
+ /* would be nice to use BM_face_calc_area, but that is for 2d faces
+ * so instead add up tessellation triangle areas */
+
+ UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
+
+ int i, n, numtri;
+ BMFace *f = NULL;
+ BM_ITER_MESH_INDEX(f, &iter, em->bm, BM_FACES_OF_MESH, i) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ n = 0;
+ numtri = f->len - 2;
+ area = 0;
+ zero_v3(vmid);
+ BMLoop *(*l)[3] = &em->looptris[poly_to_tri_count(i, BM_elem_index_get(f->l_first))];
+ for (int j = 0; j < numtri; j++) {
+ copy_v3_v3(v1, l[j][0]->v->co);
+ copy_v3_v3(v2, l[j][1]->v->co);
+ copy_v3_v3(v3, l[j][2]->v->co);
+
+ add_v3_v3(vmid, v1);
+ add_v3_v3(vmid, v2);
+ add_v3_v3(vmid, v3);
+ n += 3;
+
+ if (do_global) {
+ mul_mat3_m4_v3(ob->obmat, v1);
+ mul_mat3_m4_v3(ob->obmat, v2);
+ mul_mat3_m4_v3(ob->obmat, v3);
+ }
+
+ area += area_tri_v3(v1, v2, v3);
+ }
+
+ mul_v3_fl(vmid, 1.0f / (float)n);
+
+ if (unit->system) {
+ numstr_len = bUnit_AsString(
+ numstr, sizeof(numstr),
+ (double)(area * unit->scale_length * unit->scale_length),
+ 3, unit->system, B_UNIT_AREA, do_split, false);
+ }
+ else {
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, area);
+ }
+
+ DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, txt_flag, col);
+ }
+ }
+ }
+
+ if (me->drawflag & ME_DRAWEXTRA_FACEANG) {
+ BMFace *efa;
+ const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS);
+
+ UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ const bool is_face_sel = BM_elem_flag_test_bool(efa, BM_ELEM_SELECT);
+
+ if (is_face_sel || do_moving) {
+ BMIter liter;
+ BMLoop *loop;
+ bool is_first = true;
+
+ BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (is_face_sel ||
+ (do_moving &&
+ (BM_elem_flag_test(loop->v, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(loop->prev->v, BM_ELEM_SELECT) ||
+ BM_elem_flag_test(loop->next->v, BM_ELEM_SELECT))))
+ {
+ float v2_local[3];
+
+ /* lazy init center calc */
+ if (is_first) {
+ BM_face_calc_center_bounds(efa, vmid);
+ is_first = false;
+ }
+ copy_v3_v3(v1, loop->prev->v->co);
+ copy_v3_v3(v2, loop->v->co);
+ copy_v3_v3(v3, loop->next->v->co);
+
+ copy_v3_v3(v2_local, v2);
+
+ if (do_global) {
+ mul_mat3_m4_v3(ob->obmat, v1);
+ mul_mat3_m4_v3(ob->obmat, v2);
+ mul_mat3_m4_v3(ob->obmat, v3);
+ }
+
+ float angle = angle_v3v3v3(v1, v2, v3);
+
+ numstr_len = BLI_snprintf_rlen(
+ numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
+ interp_v3_v3v3(fvec, vmid, v2_local, 0.8f);
+ DRW_text_cache_add(dt, fvec, numstr, numstr_len, 0, txt_flag, col);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c
new file mode 100644
index 00000000000..a83f5ae33bc
--- /dev/null
+++ b/source/blender/draw/modes/edit_metaball_mode.c
@@ -0,0 +1,251 @@
+/*
+ * 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/modes/edit_metaball_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_meta_types.h"
+
+#include "BKE_mball.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+#include "GPU_select.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use EDIT_METABALL_engine_init() to
+ * initialize most of them and EDIT_METABALL_cache_init()
+ * for EDIT_METABALL_PassList */
+
+typedef struct EDIT_METABALL_PassList {
+ /* Declare all passes here and init them in
+ * EDIT_METABALL_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} EDIT_METABALL_PassList;
+
+typedef struct EDIT_METABALL_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} EDIT_METABALL_FramebufferList;
+
+typedef struct EDIT_METABALL_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} EDIT_METABALL_TextureList;
+
+typedef struct EDIT_METABALL_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ // struct CustomStruct *block;
+ struct EDIT_METABALL_PrivateData *g_data;
+} EDIT_METABALL_StorageList;
+
+typedef struct EDIT_METABALL_Data {
+ /* Struct returned by DRW_viewport_engine_data_ensure.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ EDIT_METABALL_FramebufferList *fbl;
+ EDIT_METABALL_TextureList *txl;
+ EDIT_METABALL_PassList *psl;
+ EDIT_METABALL_StorageList *stl;
+} EDIT_METABALL_Data;
+
+/* *********** STATIC *********** */
+
+typedef struct EDIT_METABALL_PrivateData {
+ /* This keeps the references of the shading groups for
+ * easy access in EDIT_METABALL_cache_populate() */
+ DRWShadingGroup *group;
+} EDIT_METABALL_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void EDIT_METABALL_cache_init(void *vedata)
+{
+ EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
+ EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ stl->g_data->group = shgroup_instance_mball_helpers(psl->pass, DRW_cache_screenspace_circle_get());
+ }
+}
+
+static void EDIT_METABALL_cache_populate_radius_visualization(
+ DRWShadingGroup *group, MetaElem *ml, const float scale_xform[3][4],
+ const float *radius, const int selection_id)
+{
+ const float *color;
+ static const float col_radius[3] = {0.63, 0.19, 0.19}; /* 0x3030A0 */
+ static const float col_radius_select[3] = {0.94, 0.63, 0.63}; /* 0xA0A0F0 */
+
+ if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) color = col_radius_select;
+ else color = col_radius;
+
+ if (selection_id != -1) {
+ ml->selcol1 = selection_id;
+ DRW_select_load_id(selection_id);
+ }
+
+ DRW_shgroup_call_dynamic_add(group, scale_xform, radius, color);
+}
+
+static void EDIT_METABALL_cache_populate_stiffness_visualization(
+ DRWShadingGroup *group, MetaElem *ml, const float scale_xform[3][4],
+ const float *radius, const int selection_id)
+{
+ const float *color;
+ static const float col_stiffness[3] = {0.19, 0.63, 0.19}; /* 0x30A030 */
+ static const float col_stiffness_select[3] = {0.63, 0.94, 0.63}; /* 0xA0F0A0 */
+
+ if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) color = col_stiffness_select;
+ else color = col_stiffness;
+
+ if (selection_id != -1) {
+ ml->selcol2 = selection_id;
+ DRW_select_load_id(selection_id);
+ }
+
+ DRW_shgroup_call_dynamic_add(group, scale_xform, radius, color);
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
+{
+ //EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
+ EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl;
+
+ if (ob->type == OB_MBALL) {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ Object *obedit = scene->obedit;
+ DRWShadingGroup *group = stl->g_data->group;
+
+ if (ob == obedit) {
+ MetaBall *mb = ob->data;
+
+ const bool is_select = DRW_state_is_select();
+
+ int selection_id = 0;
+
+ for (MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next) {
+ BKE_mball_element_calc_display_m3x4(ml->draw_scale_xform, ob->obmat, &ml->x);
+ ml->draw_stiffness_radius = ml->rad * atanf(ml->s) / (float)M_PI_2;
+
+ EDIT_METABALL_cache_populate_radius_visualization(
+ group, ml, ml->draw_scale_xform, &ml->rad, is_select ? ++selection_id : -1);
+
+ EDIT_METABALL_cache_populate_stiffness_visualization(
+ group, ml, ml->draw_scale_xform, &ml->draw_stiffness_radius, is_select ? ++selection_id : -1);
+ }
+ }
+ }
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void EDIT_METABALL_draw_scene(void *vedata)
+{
+ EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
+ /* render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void EDIT_METABALL_engine_free(void)
+{
+ // DRW_SHADER_FREE_SAFE(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void EDIT_METABALL_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+static const DrawEngineDataSize EDIT_METABALL_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_METABALL_Data);
+
+DrawEngineType draw_engine_edit_metaball_type = {
+ NULL, NULL,
+ N_("EditMetaballMode"),
+ &EDIT_METABALL_data_size,
+ NULL,
+ &EDIT_METABALL_engine_free,
+ &EDIT_METABALL_cache_init,
+ &EDIT_METABALL_cache_populate,
+ NULL,
+ NULL, /* draw_background but not needed by mode engines */
+ &EDIT_METABALL_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/edit_surface_mode.c b/source/blender/draw/modes/edit_surface_mode.c
new file mode 100644
index 00000000000..4e60c4abff5
--- /dev/null
+++ b/source/blender/draw/modes/edit_surface_mode.c
@@ -0,0 +1,269 @@
+/*
+ * 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/modes/edit_surface_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use EDIT_SURFACE_engine_init() to
+ * initialize most of them and EDIT_SURFACE_cache_init()
+ * for EDIT_SURFACE_PassList */
+
+typedef struct EDIT_SURFACE_PassList {
+ /* Declare all passes here and init them in
+ * EDIT_SURFACE_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} EDIT_SURFACE_PassList;
+
+typedef struct EDIT_SURFACE_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} EDIT_SURFACE_FramebufferList;
+
+typedef struct EDIT_SURFACE_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} EDIT_SURFACE_TextureList;
+
+typedef struct EDIT_SURFACE_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct EDIT_SURFACE_PrivateData *g_data;
+} EDIT_SURFACE_StorageList;
+
+typedef struct EDIT_SURFACE_Data {
+ /* Struct returned by DRW_viewport_engine_data_ensure.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ EDIT_SURFACE_FramebufferList *fbl;
+ EDIT_SURFACE_TextureList *txl;
+ EDIT_SURFACE_PassList *psl;
+ EDIT_SURFACE_StorageList *stl;
+} EDIT_SURFACE_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in EDIT_SURFACE_engine_init();
+ * free in EDIT_SURFACE_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct EDIT_SURFACE_PrivateData {
+ /* This keeps the references of the shading groups for
+ * easy access in EDIT_SURFACE_cache_populate() */
+ DRWShadingGroup *group;
+} EDIT_SURFACE_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void EDIT_SURFACE_engine_init(void *vedata)
+{
+ EDIT_SURFACE_TextureList *txl = ((EDIT_SURFACE_Data *)vedata)->txl;
+ EDIT_SURFACE_FramebufferList *fbl = ((EDIT_SURFACE_Data *)vedata)->fbl;
+ EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_TEX_DEPTH_24, 0},
+ * {&txl->color, DRW_TEX_RGBA_8, DRW_TEX_FILTER}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void EDIT_SURFACE_cache_init(void *vedata)
+{
+ EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl;
+ EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {0.0f, 0.0f, 1.0f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void EDIT_SURFACE_cache_populate(void *vedata, Object *ob)
+{
+ EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl;
+ EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Gwn_Batch *geom = DRW_cache_mesh_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void EDIT_SURFACE_cache_finish(void *vedata)
+{
+ EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl;
+ EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void EDIT_SURFACE_draw_scene(void *vedata)
+{
+ EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl;
+ EDIT_SURFACE_FramebufferList *fbl = ((EDIT_SURFACE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void EDIT_SURFACE_engine_free(void)
+{
+ // DRW_SHADER_FREE_SAFE(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void EDIT_SURFACE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+static const DrawEngineDataSize EDIT_SURFACE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_SURFACE_Data);
+
+DrawEngineType draw_engine_edit_surface_type = {
+ NULL, NULL,
+ N_("EditSurfaceMode"),
+ &EDIT_SURFACE_data_size,
+ &EDIT_SURFACE_engine_init,
+ &EDIT_SURFACE_engine_free,
+ &EDIT_SURFACE_cache_init,
+ &EDIT_SURFACE_cache_populate,
+ &EDIT_SURFACE_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &EDIT_SURFACE_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/edit_text_mode.c b/source/blender/draw/modes/edit_text_mode.c
new file mode 100644
index 00000000000..b375bad84b5
--- /dev/null
+++ b/source/blender/draw/modes/edit_text_mode.c
@@ -0,0 +1,312 @@
+/*
+ * 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/modes/edit_text_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_curve_types.h"
+
+#include "BIF_glutil.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+#include "GPU_batch.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use EDIT_TEXT_engine_init() to
+ * initialize most of them and EDIT_TEXT_cache_init()
+ * for EDIT_TEXT_PassList */
+
+typedef struct EDIT_TEXT_PassList {
+ /* Declare all passes here and init them in
+ * EDIT_TEXT_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *wire_pass;
+ struct DRWPass *overlay_select_pass;
+ struct DRWPass *overlay_cursor_pass;
+} EDIT_TEXT_PassList;
+
+typedef struct EDIT_TEXT_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} EDIT_TEXT_FramebufferList;
+
+typedef struct EDIT_TEXT_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} EDIT_TEXT_TextureList;
+
+typedef struct EDIT_TEXT_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct EDIT_TEXT_PrivateData *g_data;
+} EDIT_TEXT_StorageList;
+
+typedef struct EDIT_TEXT_Data {
+ /* Struct returned by DRW_viewport_engine_data_ensure.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ EDIT_TEXT_FramebufferList *fbl;
+ EDIT_TEXT_TextureList *txl;
+ EDIT_TEXT_PassList *psl;
+ EDIT_TEXT_StorageList *stl;
+} EDIT_TEXT_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in EDIT_TEXT_engine_init();
+ * free in EDIT_TEXT_engine_free(); */
+ GPUShader *wire_sh;
+ GPUShader *overlay_select_sh;
+ GPUShader *overlay_cursor_sh;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct EDIT_TEXT_PrivateData {
+ /* resulting curve as 'wire' for fast editmode drawing */
+ DRWShadingGroup *wire_shgrp;
+ DRWShadingGroup *overlay_select_shgrp;
+ DRWShadingGroup *overlay_cursor_shgrp;
+} EDIT_TEXT_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void EDIT_TEXT_engine_init(void *vedata)
+{
+ EDIT_TEXT_TextureList *txl = ((EDIT_TEXT_Data *)vedata)->txl;
+ EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl;
+ EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_TEX_DEPTH_24, 0},
+ * {&txl->color, DRW_TEX_RGBA_8, DRW_TEX_FILTER}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.wire_sh) {
+ e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+
+ if (!e_data.overlay_select_sh) {
+ e_data.overlay_select_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+
+ if (!e_data.overlay_cursor_sh) {
+ e_data.overlay_cursor_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void EDIT_TEXT_cache_init(void *vedata)
+{
+ EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl;
+ EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Text outline (fast drawing!) */
+ psl->wire_pass = DRW_pass_create(
+ "Font Wire",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE);
+ stl->g_data->wire_shgrp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass);
+
+ psl->overlay_select_pass = DRW_pass_create(
+ "Font Select",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH);
+ stl->g_data->overlay_select_shgrp = DRW_shgroup_create(e_data.overlay_select_sh, psl->overlay_select_pass);
+
+ psl->overlay_cursor_pass = DRW_pass_create(
+ "Font Cursor",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH);
+ stl->g_data->overlay_cursor_shgrp = DRW_shgroup_create(e_data.overlay_cursor_sh, psl->overlay_cursor_pass);
+ }
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void EDIT_TEXT_cache_populate(void *vedata, Object *ob)
+{
+ EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl;
+ EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ Object *obedit = scene->obedit;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_FONT) {
+ if (ob == obedit) {
+ const Curve *cu = ob->data;
+ /* Get geometry cache */
+ struct Gwn_Batch *geom;
+
+ if (cu->flag & CU_FAST) {
+ geom = DRW_cache_text_edge_wire_get(ob);
+ if (geom) {
+ DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
+ }
+ }
+ else {
+ /* object mode draws */
+ }
+
+ geom = DRW_cache_text_select_overlay_get(ob);
+ if (geom) {
+ DRW_shgroup_call_add(stl->g_data->overlay_select_shgrp, geom, ob->obmat);
+ }
+
+ geom = DRW_cache_text_cursor_overlay_get(ob);
+ if (geom) {
+ DRW_shgroup_call_add(stl->g_data->overlay_cursor_shgrp, geom, ob->obmat);
+ }
+ }
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void EDIT_TEXT_cache_finish(void *vedata)
+{
+ EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl;
+ EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void EDIT_TEXT_draw_scene(void *vedata)
+{
+ EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl;
+ EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ DRW_draw_pass(psl->wire_pass);
+
+ set_inverted_drawing(1);
+ DRW_draw_pass(psl->overlay_select_pass);
+ DRW_draw_pass(psl->overlay_cursor_pass);
+ set_inverted_drawing(0);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void EDIT_TEXT_engine_free(void)
+{
+ // DRW_SHADER_FREE_SAFE(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void EDIT_TEXT_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+static const DrawEngineDataSize EDIT_TEXT_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_TEXT_Data);
+
+DrawEngineType draw_engine_edit_text_type = {
+ NULL, NULL,
+ N_("EditTextMode"),
+ &EDIT_TEXT_data_size,
+ &EDIT_TEXT_engine_init,
+ &EDIT_TEXT_engine_free,
+ &EDIT_TEXT_cache_init,
+ &EDIT_TEXT_cache_populate,
+ &EDIT_TEXT_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &EDIT_TEXT_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
new file mode 100644
index 00000000000..91b64818eff
--- /dev/null
+++ b/source/blender/draw/modes/object_mode.c
@@ -0,0 +1,2014 @@
+/*
+ * 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/modes/object_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_userdef_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_force.h"
+#include "DNA_lightprobe_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "BIF_gl.h"
+
+#include "BKE_anim.h"
+#include "BKE_camera.h"
+#include "BKE_curve.h"
+#include "BKE_global.h"
+#include "BKE_mball.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_image.h"
+#include "BKE_texture.h"
+
+#include "ED_view3d.h"
+
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+#include "UI_resources.h"
+
+#include "draw_mode_engines.h"
+#include "draw_manager_text.h"
+#include "draw_common.h"
+
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GPUTexture *globals_ramp; /* draw_common.c */
+extern GlobalsUboStorage ts;
+
+extern char datatoc_object_outline_resolve_frag_glsl[];
+extern char datatoc_object_outline_detect_frag_glsl[];
+extern char datatoc_object_outline_expand_frag_glsl[];
+extern char datatoc_object_grid_frag_glsl[];
+extern char datatoc_object_grid_vert_glsl[];
+extern char datatoc_object_empty_image_frag_glsl[];
+extern char datatoc_object_empty_image_vert_glsl[];
+extern char datatoc_object_lightprobe_grid_vert_glsl[];
+extern char datatoc_object_particle_prim_vert_glsl[];
+extern char datatoc_object_particle_prim_frag_glsl[];
+extern char datatoc_object_particle_dot_vert_glsl[];
+extern char datatoc_object_particle_dot_frag_glsl[];
+extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_common_fxaa_lib_glsl[];
+extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
+
+/* *********** LISTS *********** */
+typedef struct OBJECT_PassList {
+ struct DRWPass *non_meshes;
+ struct DRWPass *ob_center;
+ struct DRWPass *outlines;
+ struct DRWPass *outlines_search;
+ struct DRWPass *outlines_expand;
+ struct DRWPass *outlines_bleed;
+ struct DRWPass *outlines_resolve;
+ struct DRWPass *grid;
+ struct DRWPass *bone_solid;
+ struct DRWPass *bone_wire;
+ struct DRWPass *bone_envelope;
+ struct DRWPass *particle;
+ struct DRWPass *lightprobes;
+ /* use for empty/background images */
+ struct DRWPass *reference_image;
+} OBJECT_PassList;
+
+typedef struct OBJECT_FramebufferList {
+ struct GPUFrameBuffer *outlines;
+ struct GPUFrameBuffer *blur;
+} OBJECT_FramebufferList;
+
+typedef struct OBJECT_StorageList {
+ struct OBJECT_PrivateData *g_data;
+} OBJECT_StorageList;
+
+typedef struct OBJECT_Data {
+ void *engine_type;
+ OBJECT_FramebufferList *fbl;
+ DRWViewportEmptyList *txl;
+ OBJECT_PassList *psl;
+ OBJECT_StorageList *stl;
+} OBJECT_Data;
+
+/* *********** STATIC *********** */
+
+typedef struct OBJECT_PrivateData {
+ /* Empties */
+ DRWShadingGroup *plain_axes;
+ DRWShadingGroup *cube;
+ DRWShadingGroup *circle;
+ DRWShadingGroup *sphere;
+ DRWShadingGroup *cone;
+ DRWShadingGroup *single_arrow;
+ DRWShadingGroup *single_arrow_line;
+ DRWShadingGroup *arrows;
+ DRWShadingGroup *axis_names;
+ /* GPUTexture -> EmptyImageShadingGroupData */
+ GHash *image_plane_map;
+
+ /* Force Field */
+ DRWShadingGroup *field_wind;
+ DRWShadingGroup *field_force;
+ DRWShadingGroup *field_vortex;
+ DRWShadingGroup *field_curve_sta;
+ DRWShadingGroup *field_curve_end;
+ DRWShadingGroup *field_tube_limit;
+ DRWShadingGroup *field_cone_limit;
+
+ /* Speaker */
+ DRWShadingGroup *speaker;
+
+ /* Probe */
+ DRWShadingGroup *probe_cube;
+ DRWShadingGroup *probe_planar;
+ DRWShadingGroup *probe_grid;
+
+ /* MetaBalls */
+ DRWShadingGroup *mball_circle;
+
+ /* Lamps */
+ DRWShadingGroup *lamp_center;
+ DRWShadingGroup *lamp_center_group;
+ DRWShadingGroup *lamp_groundpoint;
+ DRWShadingGroup *lamp_groundline;
+ DRWShadingGroup *lamp_circle;
+ DRWShadingGroup *lamp_circle_shadow;
+ DRWShadingGroup *lamp_sunrays;
+ DRWShadingGroup *lamp_distance;
+ DRWShadingGroup *lamp_buflimit;
+ DRWShadingGroup *lamp_buflimit_points;
+ DRWShadingGroup *lamp_area;
+ DRWShadingGroup *lamp_hemi;
+ DRWShadingGroup *lamp_spot_cone;
+ DRWShadingGroup *lamp_spot_blend;
+ DRWShadingGroup *lamp_spot_pyramid;
+ DRWShadingGroup *lamp_spot_blend_rect;
+
+ /* Helpers */
+ DRWShadingGroup *relationship_lines;
+
+ /* Objects Centers */
+ DRWShadingGroup *center_active;
+ DRWShadingGroup *center_selected;
+ DRWShadingGroup *center_deselected;
+ DRWShadingGroup *center_selected_lib;
+ DRWShadingGroup *center_deselected_lib;
+
+ /* Camera */
+ DRWShadingGroup *camera;
+ DRWShadingGroup *camera_tria;
+ DRWShadingGroup *camera_focus;
+ DRWShadingGroup *camera_clip;
+ DRWShadingGroup *camera_clip_points;
+ DRWShadingGroup *camera_mist;
+ DRWShadingGroup *camera_mist_points;
+
+ /* Outlines */
+ DRWShadingGroup *outlines_active;
+ DRWShadingGroup *outlines_active_group;
+ DRWShadingGroup *outlines_select;
+ DRWShadingGroup *outlines_select_group;
+ DRWShadingGroup *outlines_transform;
+
+ /* Lightprobes */
+ DRWShadingGroup *lightprobes_cube;
+ DRWShadingGroup *lightprobes_planar;
+
+ /* Wire */
+ DRWShadingGroup *wire;
+ DRWShadingGroup *wire_active;
+ DRWShadingGroup *wire_active_group;
+ DRWShadingGroup *wire_select;
+ DRWShadingGroup *wire_select_group;
+ DRWShadingGroup *wire_transform;
+} OBJECT_PrivateData; /* Transient data */
+
+static struct {
+ /* fullscreen shaders */
+ GPUShader *outline_resolve_sh;
+ GPUShader *outline_resolve_aa_sh;
+ GPUShader *outline_detect_sh;
+ GPUShader *outline_fade_sh;
+
+ /* regular shaders */
+ GPUShader *object_empty_image_sh;
+ GPUShader *object_empty_image_wire_sh;
+ GPUShader *grid_sh;
+ GPUShader *part_dot_sh;
+ GPUShader *part_prim_sh;
+ GPUShader *part_axis_sh;
+ GPUShader *lightprobe_grid_sh;
+ float camera_pos[3];
+ float screenvecs[3][4];
+ float grid_settings[5];
+ int grid_flag;
+ float grid_normal[3];
+ float grid_axes[3];
+ int zpos_flag;
+ int zneg_flag;
+ float zplane_normal[3];
+ float zplane_axes[3];
+ float inv_viewport_size[2];
+ bool draw_grid;
+ /* Temp buffer textures */
+ struct GPUTexture *outlines_depth_tx;
+ struct GPUTexture *outlines_color_tx;
+ struct GPUTexture *outlines_blur_tx;
+} e_data = {NULL}; /* Engine data */
+
+
+enum {
+ SHOW_AXIS_X = (1 << 0),
+ SHOW_AXIS_Y = (1 << 1),
+ SHOW_AXIS_Z = (1 << 2),
+ SHOW_GRID = (1 << 3),
+ PLANE_XY = (1 << 4),
+ PLANE_XZ = (1 << 5),
+ PLANE_YZ = (1 << 6),
+ CLIP_ZPOS = (1 << 7),
+ CLIP_ZNEG = (1 << 8),
+};
+
+/* *********** FUNCTIONS *********** */
+
+static void OBJECT_engine_init(void *vedata)
+{
+ OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl;
+
+ const float *viewport_size = DRW_viewport_size_get();
+
+ if (DRW_state_is_fbo()) {
+ DRWFboTexture tex[2] = {
+ {&e_data.outlines_depth_tx, DRW_TEX_DEPTH_24, DRW_TEX_TEMP},
+ {&e_data.outlines_color_tx, DRW_TEX_RGBA_8, DRW_TEX_FILTER | DRW_TEX_TEMP},
+ };
+
+ DRW_framebuffer_init(
+ &fbl->outlines, &draw_engine_object_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ tex, 2);
+
+ DRWFboTexture blur_tex = {&e_data.outlines_blur_tx, DRW_TEX_RGBA_8, DRW_TEX_FILTER | DRW_TEX_TEMP};
+ DRW_framebuffer_init(
+ &fbl->blur, &draw_engine_object_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &blur_tex, 1);
+ }
+
+ if (!e_data.outline_resolve_sh) {
+ e_data.outline_resolve_sh = DRW_shader_create_fullscreen(datatoc_object_outline_resolve_frag_glsl, NULL);
+ }
+
+ if (!e_data.outline_resolve_aa_sh) {
+ e_data.outline_resolve_aa_sh = DRW_shader_create_with_lib(
+ datatoc_gpu_shader_fullscreen_vert_glsl, NULL,
+ datatoc_object_outline_resolve_frag_glsl,
+ datatoc_common_fxaa_lib_glsl,
+ "#define FXAA_ALPHA\n"
+ "#define USE_FXAA\n");
+ }
+
+ if (!e_data.outline_detect_sh) {
+ e_data.outline_detect_sh = DRW_shader_create_fullscreen(datatoc_object_outline_detect_frag_glsl, NULL);
+ }
+
+ if (!e_data.outline_fade_sh) {
+ e_data.outline_fade_sh = DRW_shader_create_fullscreen(datatoc_object_outline_expand_frag_glsl, NULL);
+ }
+
+ if (!e_data.object_empty_image_sh) {
+ e_data.object_empty_image_sh = DRW_shader_create_with_lib(
+ datatoc_object_empty_image_vert_glsl, NULL,
+ datatoc_object_empty_image_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+ }
+
+ if (!e_data.object_empty_image_wire_sh) {
+ e_data.object_empty_image_wire_sh = DRW_shader_create_with_lib(
+ datatoc_object_empty_image_vert_glsl, NULL,
+ datatoc_object_empty_image_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define USE_WIRE\n");
+ }
+
+ if (!e_data.grid_sh) {
+ e_data.grid_sh = DRW_shader_create_with_lib(
+ datatoc_object_grid_vert_glsl, NULL,
+ datatoc_object_grid_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+ }
+
+ if (!e_data.part_prim_sh) {
+ e_data.part_prim_sh = DRW_shader_create(
+ datatoc_object_particle_prim_vert_glsl, NULL, datatoc_object_particle_prim_frag_glsl, NULL);
+ }
+
+ if (!e_data.part_axis_sh) {
+ e_data.part_axis_sh = DRW_shader_create(
+ datatoc_object_particle_prim_vert_glsl, NULL, datatoc_object_particle_prim_frag_glsl,
+ "#define USE_AXIS\n");
+ }
+
+ if (!e_data.part_dot_sh) {
+ e_data.part_dot_sh = DRW_shader_create(
+ datatoc_object_particle_dot_vert_glsl, NULL, datatoc_object_particle_dot_frag_glsl, NULL);
+ }
+
+ if (!e_data.lightprobe_grid_sh) {
+ e_data.lightprobe_grid_sh = DRW_shader_create(
+ datatoc_object_lightprobe_grid_vert_glsl, NULL, datatoc_gpu_shader_uniform_color_frag_glsl, NULL);
+ }
+
+ {
+ /* Grid precompute */
+ float invviewmat[4][4], invwinmat[4][4];
+ float viewmat[4][4], winmat[4][4];
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ Scene *scene = draw_ctx->scene;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ float grid_scale = ED_view3d_grid_scale(scene, v3d, NULL);
+ float grid_res;
+
+ const bool show_axis_x = (v3d->gridflag & V3D_SHOW_X) != 0;
+ const bool show_axis_y = (v3d->gridflag & V3D_SHOW_Y) != 0;
+ const bool show_axis_z = (v3d->gridflag & V3D_SHOW_Z) != 0;
+ const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) != 0;
+ e_data.draw_grid = show_axis_x || show_axis_y || show_axis_z || show_floor;
+
+ DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_get(invwinmat, DRW_MAT_WININV);
+ DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV);
+
+ /* Setup camera pos */
+ copy_v3_v3(e_data.camera_pos, invviewmat[3]);
+
+ /* if perps */
+ if (winmat[3][3] == 0.0f) {
+ float fov;
+ float viewvecs[2][4] = {
+ {1.0f, -1.0f, -1.0f, 1.0f},
+ {-1.0f, 1.0f, -1.0f, 1.0f}
+ };
+
+ /* convert the view vectors to view space */
+ for (int i = 0; i < 2; i++) {
+ mul_m4_v4(invwinmat, viewvecs[i]);
+ mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* perspective divide */
+ }
+
+ fov = angle_v3v3(viewvecs[0], viewvecs[1]) / 2.0f;
+ grid_res = fabsf(tanf(fov)) / grid_scale;
+
+ e_data.grid_flag = (1 << 4); /* XY plane */
+ if (show_axis_x)
+ e_data.grid_flag |= SHOW_AXIS_X;
+ if (show_axis_y)
+ e_data.grid_flag |= SHOW_AXIS_Y;
+ if (show_floor)
+ e_data.grid_flag |= SHOW_GRID;
+
+ }
+ else {
+ float viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
+ grid_res = viewdist / grid_scale;
+
+ if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) {
+ e_data.grid_flag = PLANE_YZ;
+ e_data.grid_flag |= SHOW_AXIS_Y;
+ e_data.grid_flag |= SHOW_AXIS_Z;
+ e_data.grid_flag |= SHOW_GRID;
+ }
+ else if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
+ e_data.grid_flag = PLANE_XY;
+ e_data.grid_flag |= SHOW_AXIS_X;
+ e_data.grid_flag |= SHOW_AXIS_Y;
+ e_data.grid_flag |= SHOW_GRID;
+ }
+ else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) {
+ e_data.grid_flag = PLANE_XZ;
+ e_data.grid_flag |= SHOW_AXIS_X;
+ e_data.grid_flag |= SHOW_AXIS_Z;
+ e_data.grid_flag |= SHOW_GRID;
+ }
+ else { /* RV3D_VIEW_USER */
+ e_data.grid_flag = PLANE_XY;
+ if (show_axis_x)
+ e_data.grid_flag |= SHOW_AXIS_X;
+ if (show_axis_y)
+ e_data.grid_flag |= SHOW_AXIS_Y;
+ if (show_floor)
+ e_data.grid_flag |= SHOW_GRID;
+ }
+ }
+
+ e_data.grid_normal[0] = (float)((e_data.grid_flag & PLANE_YZ) != 0);
+ e_data.grid_normal[1] = (float)((e_data.grid_flag & PLANE_XZ) != 0);
+ e_data.grid_normal[2] = (float)((e_data.grid_flag & PLANE_XY) != 0);
+
+ e_data.grid_axes[0] = (float)((e_data.grid_flag & (PLANE_XZ | PLANE_XY)) != 0);
+ e_data.grid_axes[1] = (float)((e_data.grid_flag & (PLANE_YZ | PLANE_XY)) != 0);
+ e_data.grid_axes[2] = (float)((e_data.grid_flag & (PLANE_YZ | PLANE_XZ)) != 0);
+
+ /* Vectors to recover pixel world position. Fix grid precision issue. */
+ /* Using pixel at z = 0.0f in ndc space : gives average precision between
+ * near and far plane. Note that it might not be the best choice. */
+ copy_v4_fl4(e_data.screenvecs[0], 1.0f, -1.0f, 0.0f, 1.0f);
+ copy_v4_fl4(e_data.screenvecs[1], -1.0f, 1.0f, 0.0f, 1.0f);
+ copy_v4_fl4(e_data.screenvecs[2], -1.0f, -1.0f, 0.0f, 1.0f);
+
+ for (int i = 0; i < 3; i++) {
+ /* Doing 2 steps to recover world position of the corners of the frustum.
+ * Using the inverse perspective matrix is giving very low precision output. */
+ mul_m4_v4(invwinmat, e_data.screenvecs[i]);
+ e_data.screenvecs[i][0] /= e_data.screenvecs[i][3]; /* perspective divide */
+ e_data.screenvecs[i][1] /= e_data.screenvecs[i][3]; /* perspective divide */
+ e_data.screenvecs[i][2] /= e_data.screenvecs[i][3]; /* perspective divide */
+ e_data.screenvecs[i][3] = 1.0f;
+ /* main instability come from this one */
+ /* TODO : to make things even more stable, don't use
+ * invviewmat and derive vectors from camera properties */
+ mul_m4_v4(invviewmat, e_data.screenvecs[i]);
+ }
+
+ sub_v3_v3(e_data.screenvecs[0], e_data.screenvecs[2]);
+ sub_v3_v3(e_data.screenvecs[1], e_data.screenvecs[2]);
+
+ /* Z axis if needed */
+ if (((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) && show_axis_z) {
+ e_data.zpos_flag = SHOW_AXIS_Z;
+
+ float zvec[4] = {0.0f, 0.0f, -1.0f, 0.0f};
+ mul_m4_v4(invviewmat, zvec);
+
+ /* z axis : chose the most facing plane */
+ if (fabsf(zvec[0]) < fabsf(zvec[1])) {
+ e_data.zpos_flag |= PLANE_XZ;
+ }
+ else {
+ e_data.zpos_flag |= PLANE_YZ;
+ }
+
+ e_data.zneg_flag = e_data.zpos_flag;
+
+ /* Persp : If camera is below floor plane, we switch clipping
+ * Ortho : If eye vector is looking up, we switch clipping */
+ if (((winmat[3][3] == 0.0f) && (e_data.camera_pos[2] > 0.0f)) ||
+ ((winmat[3][3] != 0.0f) && (zvec[2] < 0.0f)))
+ {
+ e_data.zpos_flag |= CLIP_ZPOS;
+ e_data.zneg_flag |= CLIP_ZNEG;
+ }
+ else {
+ e_data.zpos_flag |= CLIP_ZNEG;
+ e_data.zneg_flag |= CLIP_ZPOS;
+ }
+
+ e_data.zplane_normal[0] = (float)((e_data.zpos_flag & PLANE_YZ) != 0);
+ e_data.zplane_normal[1] = (float)((e_data.zpos_flag & PLANE_XZ) != 0);
+ e_data.zplane_normal[2] = (float)((e_data.zpos_flag & PLANE_XY) != 0);
+
+ e_data.zplane_axes[0] = (float)((e_data.zpos_flag & (PLANE_XZ | PLANE_XY)) != 0);
+ e_data.zplane_axes[1] = (float)((e_data.zpos_flag & (PLANE_YZ | PLANE_XY)) != 0);
+ e_data.zplane_axes[2] = (float)((e_data.zpos_flag & (PLANE_YZ | PLANE_XZ)) != 0);
+
+ }
+ else {
+ e_data.zneg_flag = e_data.zpos_flag = CLIP_ZNEG | CLIP_ZPOS;
+ }
+
+ float dist = (rv3d->persp == RV3D_CAMOB && v3d->camera)
+ ? ((Camera *)v3d->camera)->clipend : v3d->far;
+
+ e_data.grid_settings[0] = dist / 2.0f; /* gridDistance */
+ e_data.grid_settings[1] = grid_res; /* gridResolution */
+ e_data.grid_settings[2] = grid_scale; /* gridScale */
+ e_data.grid_settings[3] = v3d->gridsubdiv; /* gridSubdiv */
+ e_data.grid_settings[4] = (v3d->gridsubdiv > 1) ? 1.0f / logf(v3d->gridsubdiv) : 0.0f; /* 1/log(gridSubdiv) */
+ }
+
+ copy_v2_v2(e_data.inv_viewport_size, DRW_viewport_size_get());
+ invert_v2(e_data.inv_viewport_size);
+}
+
+static void OBJECT_engine_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.outline_resolve_sh);
+ DRW_SHADER_FREE_SAFE(e_data.outline_resolve_aa_sh);
+ DRW_SHADER_FREE_SAFE(e_data.outline_detect_sh);
+ DRW_SHADER_FREE_SAFE(e_data.outline_fade_sh);
+ DRW_SHADER_FREE_SAFE(e_data.object_empty_image_sh);
+ DRW_SHADER_FREE_SAFE(e_data.object_empty_image_wire_sh);
+ DRW_SHADER_FREE_SAFE(e_data.grid_sh);
+ DRW_SHADER_FREE_SAFE(e_data.part_prim_sh);
+ DRW_SHADER_FREE_SAFE(e_data.part_axis_sh);
+ DRW_SHADER_FREE_SAFE(e_data.part_dot_sh);
+ DRW_SHADER_FREE_SAFE(e_data.lightprobe_grid_sh);
+}
+
+static DRWShadingGroup *shgroup_outline(DRWPass *pass, const float col[4], GPUShader *sh)
+{
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", col, 1);
+
+ return grp;
+}
+
+/* currently same as 'shgroup_outline', new function to avoid confustion */
+static DRWShadingGroup *shgroup_wire(DRWPass *pass, const float col[4], GPUShader *sh)
+{
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", col, 1);
+
+ return grp;
+}
+
+static DRWShadingGroup *shgroup_theme_id_to_outline_or(
+ OBJECT_StorageList *stl, int theme_id, DRWShadingGroup *fallback)
+{
+ switch (theme_id) {
+ case TH_ACTIVE:
+ return stl->g_data->outlines_active;
+ case TH_SELECT:
+ return stl->g_data->outlines_select;
+ case TH_GROUP_ACTIVE:
+ return stl->g_data->outlines_select_group;
+ case TH_TRANSFORM:
+ return stl->g_data->outlines_transform;
+ default:
+ return fallback;
+ }
+}
+
+static DRWShadingGroup *shgroup_theme_id_to_wire_or(
+ OBJECT_StorageList *stl, int theme_id, DRWShadingGroup *fallback)
+{
+ switch (theme_id) {
+ case TH_ACTIVE:
+ return stl->g_data->wire_active;
+ case TH_SELECT:
+ return stl->g_data->wire_select;
+ case TH_GROUP_ACTIVE:
+ return stl->g_data->wire_select_group;
+ case TH_TRANSFORM:
+ return stl->g_data->wire_transform;
+ default:
+ return fallback;
+ }
+}
+
+static void image_calc_aspect(Image *ima, ImageUser *iuser, float r_image_aspect[2])
+{
+ float ima_x, ima_y;
+ if (ima) {
+ int w, h;
+ BKE_image_get_size(ima, iuser, &w, &h);
+ ima_x = w;
+ ima_y = h;
+ }
+ else {
+ /* if no image, make it a 1x1 empty square, honor scale & offset */
+ ima_x = ima_y = 1.0f;
+ }
+ /* Get the image aspect even if the buffer is invalid */
+ float sca_x = 1.0f, sca_y = 1.0f;
+ if (ima) {
+ if (ima->aspx > ima->aspy) {
+ sca_y = ima->aspy / ima->aspx;
+ }
+ else if (ima->aspx < ima->aspy) {
+ sca_x = ima->aspx / ima->aspy;
+ }
+ }
+
+ const float scale_x_inv = ima_x * sca_x;
+ const float scale_y_inv = ima_y * sca_y;
+ if (scale_x_inv > scale_y_inv) {
+ r_image_aspect[0] = 1.0f;
+ r_image_aspect[1] = scale_y_inv / scale_x_inv;
+ }
+ else {
+ r_image_aspect[0] = scale_x_inv / scale_y_inv;
+ r_image_aspect[1] = 1.0f;
+ }
+}
+
+/* per-image shading groups for image-type empty objects */
+struct EmptyImageShadingGroupData {
+ DRWShadingGroup *shgrp_image;
+ DRWShadingGroup *shgrp_wire;
+ float image_aspect[2];
+};
+
+static void DRW_shgroup_empty_image(
+ OBJECT_StorageList *stl, OBJECT_PassList *psl, Object *ob, const float color[3])
+{
+ /* TODO: 'StereoViews', see draw_empty_image. */
+
+ if (stl->g_data->image_plane_map == NULL) {
+ stl->g_data->image_plane_map = BLI_ghash_ptr_new(__func__);
+ }
+
+ struct EmptyImageShadingGroupData *empty_image_data;
+
+ GPUTexture *tex = ob->data ?
+ GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false, false, false) : NULL;
+ void **val_p;
+
+ /* Create on demand, 'tex' may be NULL. */
+ if (BLI_ghash_ensure_p(stl->g_data->image_plane_map, tex, &val_p)) {
+ empty_image_data = *val_p;
+ }
+ else {
+ empty_image_data = MEM_mallocN(sizeof(*empty_image_data), __func__);
+
+ image_calc_aspect(ob->data, ob->iuser, empty_image_data->image_aspect);
+
+ if (tex) {
+ struct Gwn_Batch *geom = DRW_cache_image_plane_get();
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(
+ e_data.object_empty_image_sh, psl->non_meshes, geom);
+ DRW_shgroup_attrib_float(grp, "objectColor", 4);
+ DRW_shgroup_attrib_float(grp, "size", 1);
+ DRW_shgroup_attrib_float(grp, "offset", 2);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+
+ DRW_shgroup_uniform_texture(grp, "image", tex);
+ DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1);
+
+ empty_image_data->shgrp_image = grp;
+ }
+ else {
+ empty_image_data->shgrp_image = NULL;
+ }
+
+ {
+ struct Gwn_Batch *geom = DRW_cache_image_plane_wire_get();
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(
+ e_data.object_empty_image_wire_sh, psl->non_meshes, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "size", 1);
+ DRW_shgroup_attrib_float(grp, "offset", 2);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+
+ DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1);
+
+ empty_image_data->shgrp_wire = grp;
+ }
+
+ *val_p = empty_image_data;
+ }
+
+ if (empty_image_data->shgrp_image != NULL) {
+ DRW_shgroup_call_dynamic_add(
+ empty_image_data->shgrp_image,
+ ob->col,
+ &ob->empty_drawsize,
+ ob->ima_ofs,
+ ob->obmat);
+ }
+
+ DRW_shgroup_call_dynamic_add(
+ empty_image_data->shgrp_wire,
+ color,
+ &ob->empty_drawsize,
+ ob->ima_ofs,
+ ob->obmat);
+}
+
+static void OBJECT_cache_init(void *vedata)
+{
+ OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl;
+ OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE;
+ psl->outlines = DRW_pass_create("Outlines Depth Pass", state);
+
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ /* Select */
+ stl->g_data->outlines_select = shgroup_outline(psl->outlines, ts.colorSelect, sh);
+ stl->g_data->outlines_select_group = shgroup_outline(psl->outlines, ts.colorGroupActive, sh);
+
+ /* Transform */
+ stl->g_data->outlines_transform = shgroup_outline(psl->outlines, ts.colorTransform, sh);
+
+ /* Active */
+ stl->g_data->outlines_active = shgroup_outline(psl->outlines, ts.colorActive, sh);
+ stl->g_data->outlines_active_group = shgroup_outline(psl->outlines, ts.colorGroupActive, sh);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ psl->lightprobes = DRW_pass_create("Object Probe Pass", state);
+
+ /* Cubemap */
+ stl->g_data->lightprobes_cube = shgroup_instance(psl->lightprobes, DRW_cache_sphere_get());
+
+ /* Planar */
+ stl->g_data->lightprobes_planar = shgroup_instance(psl->lightprobes, DRW_cache_quad_get());
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ static float alphaOcclu = 0.35f;
+ static bool bTrue = true;
+ static bool bFalse = false;
+
+ psl->outlines_search = DRW_pass_create("Outlines Detect Pass", state);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_detect_sh, psl->outlines_search);
+ DRW_shgroup_uniform_buffer(grp, "outlineColor", &e_data.outlines_color_tx);
+ DRW_shgroup_uniform_buffer(grp, "outlineDepth", &e_data.outlines_depth_tx);
+ DRW_shgroup_uniform_buffer(grp, "sceneDepth", &dtxl->depth);
+ DRW_shgroup_uniform_float(grp, "alphaOcclu", &alphaOcclu, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ psl->outlines_expand = DRW_pass_create("Outlines Expand Pass", state);
+
+ grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_expand);
+ DRW_shgroup_uniform_buffer(grp, "outlineColor", &e_data.outlines_blur_tx);
+ DRW_shgroup_uniform_bool(grp, "doExpand", &bTrue, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ psl->outlines_bleed = DRW_pass_create("Outlines Bleed Pass", state);
+
+ grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_bleed);
+ DRW_shgroup_uniform_buffer(grp, "outlineColor", &e_data.outlines_color_tx);
+ DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND;
+ psl->outlines_resolve = DRW_pass_create("Outlines Resolve Pass", state);
+
+ struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_resolve_aa_sh, psl->outlines_resolve);
+ DRW_shgroup_uniform_buffer(grp, "outlineBluredColor", &e_data.outlines_blur_tx);
+ DRW_shgroup_uniform_vec2(grp, "rcpDimensions", e_data.inv_viewport_size, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+ }
+
+ {
+ /* Grid pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND;
+ psl->grid = DRW_pass_create("Infinite Grid Pass", state);
+
+ struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
+ static float mat[4][4];
+ unit_m4(mat);
+
+ /* Create 3 quads to render ordered transparency Z axis */
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.grid_sh, psl->grid);
+ DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1);
+ DRW_shgroup_uniform_vec3(grp, "planeNormal", e_data.zplane_normal, 1);
+ DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1);
+ DRW_shgroup_uniform_vec3(grp, "cameraPos", e_data.camera_pos, 1);
+ DRW_shgroup_uniform_vec4(grp, "screenvecs[0]", e_data.screenvecs[0], 3);
+ DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 1);
+ DRW_shgroup_uniform_float(grp, "gridOneOverLogSubdiv", &e_data.grid_settings[4], 1);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
+ DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_call_add(grp, quad, mat);
+
+ grp = DRW_shgroup_create(e_data.grid_sh, psl->grid);
+ DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.grid_flag, 1);
+ DRW_shgroup_uniform_vec3(grp, "planeNormal", e_data.grid_normal, 1);
+ DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.grid_axes, 1);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_call_add(grp, quad, mat);
+
+ grp = DRW_shgroup_create(e_data.grid_sh, psl->grid);
+ DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zpos_flag, 1);
+ DRW_shgroup_uniform_vec3(grp, "planeNormal", e_data.zplane_normal, 1);
+ DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_call_add(grp, quad, mat);
+ }
+
+ {
+ /* Solid bones */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ psl->bone_solid = DRW_pass_create("Bone Solid Pass", state);
+ }
+
+ {
+ /* Wire bones */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+ psl->bone_wire = DRW_pass_create("Bone Wire Pass", state);
+ }
+
+ {
+ /* distance outline around envelope bones */
+ DRWState state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+ psl->bone_envelope = DRW_pass_create("Bone Envelope Outline Pass", state);
+ }
+
+ {
+ /* Non Meshes Pass (Camera, empties, lamps ...) */
+ struct Gwn_Batch *geom;
+
+ DRWState state =
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
+ DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_POINT;
+ state |= DRW_STATE_WIRE;
+ psl->non_meshes = DRW_pass_create("Non Meshes Pass", state);
+
+ /* Empties */
+ geom = DRW_cache_plain_axes_get();
+ stl->g_data->plain_axes = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_cube_get();
+ stl->g_data->cube = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_circle_get();
+ stl->g_data->circle = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_empty_sphere_get();
+ stl->g_data->sphere = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_empty_cone_get();
+ stl->g_data->cone = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_arrow_get();
+ stl->g_data->single_arrow = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_line_get();
+ stl->g_data->single_arrow_line = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_arrows_get();
+ stl->g_data->arrows = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_axis_names_get();
+ stl->g_data->axis_names = shgroup_instance_axis_names(psl->non_meshes, geom);
+
+ /* initialize on first use */
+ stl->g_data->image_plane_map = NULL;
+
+ /* Force Field */
+ geom = DRW_cache_field_wind_get();
+ stl->g_data->field_wind = shgroup_instance_scaled(psl->non_meshes, geom);
+
+ geom = DRW_cache_field_force_get();
+ stl->g_data->field_force = shgroup_instance_screen_aligned(psl->non_meshes, geom);
+
+ geom = DRW_cache_field_vortex_get();
+ stl->g_data->field_vortex = shgroup_instance_scaled(psl->non_meshes, geom);
+
+ geom = DRW_cache_screenspace_circle_get();
+ stl->g_data->field_curve_sta = shgroup_instance_screen_aligned(psl->non_meshes, geom);
+
+ /* Speaker */
+ geom = DRW_cache_speaker_get();
+ stl->g_data->speaker = shgroup_instance(psl->non_meshes, geom);
+
+ /* Probe */
+ static float probeSize = 14.0f;
+ geom = DRW_cache_lightprobe_cube_get();
+ stl->g_data->probe_cube = shgroup_instance_screenspace(psl->non_meshes, geom, &probeSize);
+
+ geom = DRW_cache_lightprobe_grid_get();
+ stl->g_data->probe_grid = shgroup_instance_screenspace(psl->non_meshes, geom, &probeSize);
+
+ static float probePlanarSize = 20.0f;
+ geom = DRW_cache_lightprobe_planar_get();
+ stl->g_data->probe_planar = shgroup_instance_screenspace(psl->non_meshes, geom, &probePlanarSize);
+
+ /* Camera */
+ geom = DRW_cache_camera_get();
+ stl->g_data->camera = shgroup_camera_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_camera_tria_get();
+ stl->g_data->camera_tria = shgroup_camera_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_plain_axes_get();
+ stl->g_data->camera_focus = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_line_get();
+ stl->g_data->camera_clip = shgroup_distance_lines_instance(psl->non_meshes, geom);
+ stl->g_data->camera_mist = shgroup_distance_lines_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_line_endpoints_get();
+ stl->g_data->camera_clip_points = shgroup_distance_lines_instance(psl->non_meshes, geom);
+ stl->g_data->camera_mist_points = shgroup_distance_lines_instance(psl->non_meshes, geom);
+
+ }
+
+ {
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ /* Unselected */
+ stl->g_data->wire = shgroup_wire(psl->non_meshes, ts.colorWire, sh);
+
+ /* Select */
+ stl->g_data->wire_select = shgroup_wire(psl->non_meshes, ts.colorSelect, sh);
+ stl->g_data->wire_select_group = shgroup_wire(psl->non_meshes, ts.colorGroupActive, sh);
+
+ /* Transform */
+ stl->g_data->wire_transform = shgroup_wire(psl->non_meshes, ts.colorTransform, sh);
+
+ /* Active */
+ stl->g_data->wire_active = shgroup_wire(psl->non_meshes, ts.colorActive, sh);
+ stl->g_data->wire_active_group = shgroup_wire(psl->non_meshes, ts.colorGroupActive, sh);
+ }
+
+ {
+ /* Metaballs Helpers */
+ struct Gwn_Batch *geom;
+ geom = DRW_cache_screenspace_circle_get();
+ stl->g_data->mball_circle = shgroup_instance_mball_helpers(psl->non_meshes, geom);
+ }
+
+ {
+ /* Lamps */
+ /* TODO
+ * for now we create multiple times the same VBO with only lamp center coordinates
+ * but ideally we would only create it once */
+ struct Gwn_Batch *geom;
+
+ /* start with buflimit because we don't want stipples */
+ geom = DRW_cache_single_line_get();
+ stl->g_data->lamp_buflimit = shgroup_distance_lines_instance(psl->non_meshes, geom);
+
+ stl->g_data->lamp_center = shgroup_dynpoints_uniform_color(psl->non_meshes, ts.colorLampNoAlpha, &ts.sizeLampCenter);
+ stl->g_data->lamp_center_group = shgroup_dynpoints_uniform_color(psl->non_meshes, ts.colorGroup, &ts.sizeLampCenter);
+
+ geom = DRW_cache_lamp_get();
+ stl->g_data->lamp_circle = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircle);
+ stl->g_data->lamp_circle_shadow = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircleShadow);
+
+ geom = DRW_cache_lamp_sunrays_get();
+ stl->g_data->lamp_sunrays = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircle);
+
+ stl->g_data->lamp_groundline = shgroup_groundlines_uniform_color(psl->non_meshes, ts.colorLamp);
+ stl->g_data->lamp_groundpoint = shgroup_groundpoints_uniform_color(psl->non_meshes, ts.colorLamp);
+
+ geom = DRW_cache_lamp_area_get();
+ stl->g_data->lamp_area = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_lamp_hemi_get();
+ stl->g_data->lamp_hemi = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_line_get();
+ stl->g_data->lamp_distance = shgroup_distance_lines_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_line_endpoints_get();
+ stl->g_data->lamp_buflimit_points = shgroup_distance_lines_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_lamp_spot_get();
+ stl->g_data->lamp_spot_cone = shgroup_spot_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_circle_get();
+ stl->g_data->lamp_spot_blend = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_lamp_spot_square_get();
+ stl->g_data->lamp_spot_pyramid = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_square_get();
+ stl->g_data->lamp_spot_blend_rect = shgroup_instance(psl->non_meshes, geom);
+ }
+
+ {
+ /* -------- STIPPLES ------- */
+ /* TODO port to shader stipple */
+ struct Gwn_Batch *geom;
+
+ /* Relationship Lines */
+ stl->g_data->relationship_lines = shgroup_dynlines_uniform_color(psl->non_meshes, ts.colorWire);
+ DRW_shgroup_state_enable(stl->g_data->relationship_lines, DRW_STATE_STIPPLE_3);
+
+ /* Force Field Curve Guide End (here because of stipple) */
+ geom = DRW_cache_screenspace_circle_get();
+ stl->g_data->field_curve_end = shgroup_instance_screen_aligned(psl->non_meshes, geom);
+
+ /* Force Field Limits */
+ geom = DRW_cache_field_tube_limit_get();
+ stl->g_data->field_tube_limit = shgroup_instance_scaled(psl->non_meshes, geom);
+
+ geom = DRW_cache_field_cone_limit_get();
+ stl->g_data->field_cone_limit = shgroup_instance_scaled(psl->non_meshes, geom);
+ }
+
+ {
+ /* Object Center pass grouped by State */
+ DRWShadingGroup *grp;
+ static float outlineWidth, size;
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_POINT;
+ psl->ob_center = DRW_pass_create("Obj Center Pass", state);
+
+ outlineWidth = 1.0f * U.pixelsize;
+ size = U.obcenter_dia * U.pixelsize + outlineWidth;
+
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+
+ /* Active */
+ grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ DRW_shgroup_uniform_float(grp, "size", &size, 1);
+ DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1);
+ DRW_shgroup_uniform_vec4(grp, "color", ts.colorActive, 1);
+ DRW_shgroup_uniform_vec4(grp, "outlineColor", ts.colorOutline, 1);
+ stl->g_data->center_active = grp;
+
+ /* Select */
+ grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ DRW_shgroup_uniform_vec4(grp, "color", ts.colorSelect, 1);
+ stl->g_data->center_selected = grp;
+
+ /* Deselect */
+ grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ DRW_shgroup_uniform_vec4(grp, "color", ts.colorDeselect, 1);
+ stl->g_data->center_deselected = grp;
+
+ /* Select (library) */
+ grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ DRW_shgroup_uniform_vec4(grp, "color", ts.colorLibrarySelect, 1);
+ stl->g_data->center_selected_lib = grp;
+
+ /* Deselect (library) */
+ grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ DRW_shgroup_uniform_vec4(grp, "color", ts.colorLibrary, 1);
+ stl->g_data->center_deselected_lib = grp;
+ }
+
+ {
+ /* Particle Pass */
+ psl->particle = DRW_pass_create(
+ "Particle Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS |
+ DRW_STATE_POINT | DRW_STATE_BLEND);
+ }
+
+ {
+ /* Empty/Background Image Pass */
+ psl->reference_image = DRW_pass_create(
+ "Refrence Image Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND);
+ }
+}
+
+static void DRW_shgroup_mball_helpers(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer)
+{
+ MetaBall *mb = ob->data;
+
+ float *color;
+ DRW_object_wire_theme_get(ob, view_layer, &color);
+
+ for (MetaElem *ml = mb->elems.first; ml != NULL; ml = ml->next) {
+ /* draw radius */
+ BKE_mball_element_calc_display_m3x4(ml->draw_scale_xform, ob->obmat, &ml->x);
+ DRW_shgroup_call_dynamic_add(stl->g_data->mball_circle, ml->draw_scale_xform, &ml->rad, color);
+ }
+}
+
+static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer)
+{
+ Lamp *la = ob->data;
+ float *color;
+ int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color);
+ static float zero = 0.0f;
+
+ float **la_mats = (float **)DRW_object_engine_data_ensure(ob, &draw_engine_object_type, NULL);
+ if (*la_mats == NULL) {
+ /* we need 2 matrices */
+ *la_mats = MEM_mallocN(sizeof(float) * 16 * 2, "Lamp Object Mode Matrices");
+ }
+
+ float (*shapemat)[4], (*spotblendmat)[4];
+ shapemat = (float (*)[4])(*la_mats);
+ spotblendmat = (float (*)[4])(*la_mats + 16);
+
+ /* Don't draw the center if it's selected or active */
+ if (theme_id == TH_GROUP)
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_center_group, ob->obmat[3]);
+ else if (theme_id == TH_LAMP)
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_center, ob->obmat[3]);
+
+ /* First circle */
+ DRW_shgroup_call_dynamic_add(stl->g_data->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) {
+ if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_circle_shadow, ob->obmat[3], color);
+ }
+ }
+
+ /* Distance */
+ if (ELEM(la->type, LA_HEMI, LA_SUN, LA_AREA)) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_distance, color, &zero, &la->dist, ob->obmat);
+ }
+
+ copy_m4_m4(shapemat, ob->obmat);
+
+ if (la->type == LA_SUN) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_sunrays, ob->obmat[3], color);
+ }
+ else if (la->type == LA_SPOT) {
+ float size[3], sizemat[4][4];
+ static float one = 1.0f;
+ float blend = 1.0f - pow2f(la->spotblend);
+
+ size[0] = size[1] = sinf(la->spotsize * 0.5f) * la->dist;
+ size[2] = cosf(la->spotsize * 0.5f) * la->dist;
+
+ size_to_mat4(sizemat, size);
+ mul_m4_m4m4(shapemat, ob->obmat, sizemat);
+
+ size[0] = size[1] = blend; size[2] = 1.0f;
+ size_to_mat4(sizemat, size);
+ translate_m4(sizemat, 0.0f, 0.0f, -1.0f);
+ rotate_m4(sizemat, 'X', (float)(M_PI / 2));
+ mul_m4_m4m4(spotblendmat, shapemat, sizemat);
+
+ if (la->mode & LA_SQUARE) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_spot_pyramid, color, &one, shapemat);
+
+ /* hide line if it is zero size or overlaps with outer border,
+ * previously it adjusted to always to show it but that seems
+ * confusing because it doesn't show the actual blend size */
+ if (blend != 0.0f && blend != 1.0f) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_spot_blend_rect, color, &one, spotblendmat);
+ }
+ }
+ else {
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_spot_cone, color, shapemat);
+
+ /* hide line if it is zero size or overlaps with outer border,
+ * previously it adjusted to always to show it but that seems
+ * confusing because it doesn't show the actual blend size */
+ if (blend != 0.0f && blend != 1.0f) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_spot_blend, color, &one, spotblendmat);
+ }
+ }
+
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_buflimit, color, &la->clipsta, &la->clipend, ob->obmat);
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat);
+ }
+ else if (la->type == LA_HEMI) {
+ static float hemisize = 2.0f;
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_hemi, color, &hemisize, shapemat);
+ }
+ else if (la->type == LA_AREA) {
+ float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4];
+
+ if (la->area_shape == LA_AREA_RECT) {
+ size[1] = la->area_sizey / la->area_size;
+ size_to_mat4(sizemat, size);
+ mul_m4_m4m4(shapemat, shapemat, sizemat);
+ }
+
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_area, color, &la->area_size, shapemat);
+ }
+
+ /* Line and point going to the ground */
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_groundline, ob->obmat[3]);
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_groundpoint, ob->obmat[3]);
+}
+
+static void DRW_shgroup_camera(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ Scene *scene = draw_ctx->scene;
+
+ Camera *cam = ob->data;
+ const bool is_active = (ob == v3d->camera);
+ float *color;
+ DRW_object_wire_theme_get(ob, view_layer, &color);
+
+ float vec[4][3], asp[2], shift[2], scale[3], drawsize;
+
+ scale[0] = 1.0f / len_v3(ob->obmat[0]);
+ scale[1] = 1.0f / len_v3(ob->obmat[1]);
+ scale[2] = 1.0f / len_v3(ob->obmat[2]);
+
+ BKE_camera_view_frame_ex(scene, cam, cam->drawsize, false, scale,
+ asp, shift, &drawsize, vec);
+
+ // /* Frame coords */
+ copy_v2_v2(cam->drwcorners[0], vec[0]);
+ copy_v2_v2(cam->drwcorners[1], vec[1]);
+ copy_v2_v2(cam->drwcorners[2], vec[2]);
+ copy_v2_v2(cam->drwcorners[3], vec[3]);
+
+ /* depth */
+ cam->drwdepth = vec[0][2];
+
+ /* tria */
+ cam->drwtria[0][0] = shift[0] + ((0.7f * drawsize) * scale[0]);
+ cam->drwtria[0][1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
+ cam->drwtria[1][0] = shift[0];
+ cam->drwtria[1][1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
+
+ DRW_shgroup_call_dynamic_add(stl->g_data->camera, color, cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat);
+
+ /* Active cam */
+ if (is_active) {
+ DRW_shgroup_call_dynamic_add(
+ stl->g_data->camera_tria, color,
+ cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat);
+ }
+
+ /* draw the rest in normalize object space */
+ copy_m4_m4(cam->drwnormalmat, ob->obmat);
+ normalize_m4(cam->drwnormalmat);
+
+ if (cam->flag & CAM_SHOWLIMITS) {
+ static float col[3] = {0.5f, 0.5f, 0.25f}, col_hi[3] = {1.0f, 1.0f, 0.5f};
+ float sizemat[4][4], size[3] = {1.0f, 1.0f, 0.0f};
+ float focusdist = BKE_camera_object_dof_distance(ob);
+
+ copy_m4_m4(cam->drwfocusmat, cam->drwnormalmat);
+ translate_m4(cam->drwfocusmat, 0.0f, 0.0f, -focusdist);
+ size_to_mat4(sizemat, size);
+ mul_m4_m4m4(cam->drwfocusmat, cam->drwfocusmat, sizemat);
+
+ DRW_shgroup_call_dynamic_add(
+ stl->g_data->camera_focus, (is_active ? col_hi : col),
+ &cam->drawsize, cam->drwfocusmat);
+
+ DRW_shgroup_call_dynamic_add(
+ stl->g_data->camera_clip, color,
+ &cam->clipsta, &cam->clipend, cam->drwnormalmat);
+ DRW_shgroup_call_dynamic_add(
+ stl->g_data->camera_clip_points, (is_active ? col_hi : col),
+ &cam->clipsta, &cam->clipend, cam->drwnormalmat);
+ }
+
+ if (cam->flag & CAM_SHOWMIST) {
+ World *world = scene->world;
+
+ if (world) {
+ static float col[3] = {0.5f, 0.5f, 0.5f}, col_hi[3] = {1.0f, 1.0f, 1.0f};
+ world->mistend = world->miststa + world->mistdist;
+ DRW_shgroup_call_dynamic_add(
+ stl->g_data->camera_mist, color,
+ &world->miststa, &world->mistend, cam->drwnormalmat);
+ DRW_shgroup_call_dynamic_add(
+ stl->g_data->camera_mist_points, (is_active ? col_hi : col),
+ &world->miststa, &world->mistend, cam->drwnormalmat);
+ }
+ }
+}
+
+static void DRW_shgroup_empty(OBJECT_StorageList *stl, OBJECT_PassList *psl, Object *ob, ViewLayer *view_layer)
+{
+ float *color;
+ DRW_object_wire_theme_get(ob, view_layer, &color);
+
+ switch (ob->empty_drawtype) {
+ case OB_PLAINAXES:
+ DRW_shgroup_call_dynamic_add(stl->g_data->plain_axes, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_SINGLE_ARROW:
+ DRW_shgroup_call_dynamic_add(stl->g_data->single_arrow, color, &ob->empty_drawsize, ob->obmat);
+ DRW_shgroup_call_dynamic_add(stl->g_data->single_arrow_line, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_CUBE:
+ DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_CIRCLE:
+ DRW_shgroup_call_dynamic_add(stl->g_data->circle, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_EMPTY_SPHERE:
+ DRW_shgroup_call_dynamic_add(stl->g_data->sphere, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_EMPTY_CONE:
+ DRW_shgroup_call_dynamic_add(stl->g_data->cone, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_ARROWS:
+ DRW_shgroup_call_dynamic_add(stl->g_data->arrows, color, &ob->empty_drawsize, ob->obmat);
+ DRW_shgroup_call_dynamic_add(stl->g_data->axis_names, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_EMPTY_IMAGE:
+ DRW_shgroup_empty_image(stl, psl, ob, color);
+ break;
+ }
+}
+
+static void DRW_shgroup_forcefield(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer)
+{
+ int theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ float *color = DRW_color_background_blend_get(theme_id);
+ PartDeflect *pd = ob->pd;
+ Curve *cu = (ob->type == OB_CURVE) ? ob->data : NULL;
+
+ /* TODO Move this to depsgraph */
+ float tmp[3];
+ copy_v3_fl(pd->drawvec1, ob->empty_drawsize);
+
+ switch (pd->forcefield) {
+ case PFIELD_WIND:
+ pd->drawvec1[2] = pd->f_strength;
+ break;
+ case PFIELD_VORTEX:
+ if (pd->f_strength < 0.0f) {
+ pd->drawvec1[1] = -pd->drawvec1[1];
+ }
+ break;
+ case PFIELD_GUIDE:
+ if (cu && (cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) {
+ where_on_path(ob, 0.0f, pd->drawvec1, tmp, NULL, NULL, NULL);
+ where_on_path(ob, 1.0f, pd->drawvec2, tmp, NULL, NULL, NULL);
+ }
+ break;
+ }
+
+ if (pd->falloff == PFIELD_FALL_TUBE) {
+ pd->drawvec_falloff_max[0] = pd->drawvec_falloff_max[1] = (pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f;
+ pd->drawvec_falloff_max[2] = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
+
+ pd->drawvec_falloff_min[0] = pd->drawvec_falloff_min[1] = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f;
+ pd->drawvec_falloff_min[2] = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
+ }
+ else if (pd->falloff == PFIELD_FALL_CONE) {
+ float radius, distance;
+
+ radius = DEG2RADF((pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f);
+ distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
+ pd->drawvec_falloff_max[0] = pd->drawvec_falloff_max[1] = distance * sinf(radius);
+ pd->drawvec_falloff_max[2] = distance * cosf(radius);
+
+ radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f);
+ distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
+
+ pd->drawvec_falloff_min[0] = pd->drawvec_falloff_min[1] = distance * sinf(radius);
+ pd->drawvec_falloff_min[2] = distance * cosf(radius);
+ }
+ /* End of things that should go to depthgraph */
+
+ switch (pd->forcefield) {
+ case PFIELD_WIND:
+ DRW_shgroup_call_dynamic_add(stl->g_data->field_wind, color, &pd->drawvec1, ob->obmat);
+ break;
+ case PFIELD_FORCE:
+ DRW_shgroup_call_dynamic_add(stl->g_data->field_force, color, &pd->drawvec1, ob->obmat);
+ break;
+ case PFIELD_VORTEX:
+ DRW_shgroup_call_dynamic_add(stl->g_data->field_vortex, color, &pd->drawvec1, ob->obmat);
+ break;
+ case PFIELD_GUIDE:
+ if (cu && (cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->field_curve_sta, color, &pd->f_strength, ob->obmat);
+ DRW_shgroup_call_dynamic_add(stl->g_data->field_curve_end, color, &pd->f_strength, ob->obmat);
+ }
+ break;
+ }
+
+ if (pd->falloff == PFIELD_FALL_SPHERE) {
+ /* as last, guide curve alters it */
+ if ((pd->flag & PFIELD_USEMAX) != 0) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->field_curve_end, color, &pd->maxdist, ob->obmat);
+ }
+
+ if ((pd->flag & PFIELD_USEMIN) != 0) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->field_curve_end, color, &pd->mindist, ob->obmat);
+ }
+ }
+ else if (pd->falloff == PFIELD_FALL_TUBE) {
+ if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->field_tube_limit, color, &pd->drawvec_falloff_max, ob->obmat);
+ }
+
+ if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->field_tube_limit, color, &pd->drawvec_falloff_min, ob->obmat);
+ }
+ }
+ else if (pd->falloff == PFIELD_FALL_CONE) {
+ if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->field_cone_limit, color, &pd->drawvec_falloff_max, ob->obmat);
+ }
+
+ if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->field_cone_limit, color, &pd->drawvec_falloff_min, ob->obmat);
+ }
+ }
+}
+
+static void DRW_shgroup_speaker(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer)
+{
+ float *color;
+ static float one = 1.0f;
+ DRW_object_wire_theme_get(ob, view_layer, &color);
+
+ DRW_shgroup_call_dynamic_add(stl->g_data->speaker, color, &one, ob->obmat);
+}
+
+typedef struct OBJECT_LightProbeEngineData {
+ float prb_mats[6][4][4];
+ float probe_cube_mat[4][4];
+ float draw_size;
+ float increment_x[3];
+ float increment_y[3];
+ float increment_z[3];
+ float corner[3];
+} OBJECT_LightProbeEngineData;
+
+static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl, Object *ob, ViewLayer *view_layer)
+{
+ float *color;
+ static float one = 1.0f;
+ LightProbe *prb = (LightProbe *)ob->data;
+ bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
+ DRW_object_wire_theme_get(ob, view_layer, &color);
+
+ OBJECT_LightProbeEngineData *prb_data;
+ OBJECT_LightProbeEngineData **prb_data_pt = (OBJECT_LightProbeEngineData **)DRW_object_engine_data_ensure(ob, &draw_engine_object_type, NULL);
+ if (*prb_data_pt == NULL) {
+ *prb_data_pt = MEM_mallocN(sizeof(OBJECT_LightProbeEngineData), "Probe Clip distances Matrices");
+ }
+
+ prb_data = *prb_data_pt;
+
+ if ((DRW_state_is_select() || do_outlines) && ((prb->flag & LIGHTPROBE_FLAG_SHOW_DATA) != 0)) {
+
+ if (prb->type == LIGHTPROBE_TYPE_GRID) {
+ /* Update transforms */
+ float cell_dim[3], half_cell_dim[3];
+ cell_dim[0] = 2.0f / (float)(prb->grid_resolution_x);
+ cell_dim[1] = 2.0f / (float)(prb->grid_resolution_y);
+ cell_dim[2] = 2.0f / (float)(prb->grid_resolution_z);
+
+ mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f);
+
+ /* First cell. */
+ copy_v3_fl(prb_data->corner, -1.0f);
+ add_v3_v3(prb_data->corner, half_cell_dim);
+ mul_m4_v3(ob->obmat, prb_data->corner);
+
+ /* Opposite neighbor cell. */
+ copy_v3_fl3(prb_data->increment_x, cell_dim[0], 0.0f, 0.0f);
+ add_v3_v3(prb_data->increment_x, half_cell_dim);
+ add_v3_fl(prb_data->increment_x, -1.0f);
+ mul_m4_v3(ob->obmat, prb_data->increment_x);
+ sub_v3_v3(prb_data->increment_x, prb_data->corner);
+
+ copy_v3_fl3(prb_data->increment_y, 0.0f, cell_dim[1], 0.0f);
+ add_v3_v3(prb_data->increment_y, half_cell_dim);
+ add_v3_fl(prb_data->increment_y, -1.0f);
+ mul_m4_v3(ob->obmat, prb_data->increment_y);
+ sub_v3_v3(prb_data->increment_y, prb_data->corner);
+
+ copy_v3_fl3(prb_data->increment_z, 0.0f, 0.0f, cell_dim[2]);
+ add_v3_v3(prb_data->increment_z, half_cell_dim);
+ add_v3_fl(prb_data->increment_z, -1.0f);
+ mul_m4_v3(ob->obmat, prb_data->increment_z);
+ sub_v3_v3(prb_data->increment_z, prb_data->corner);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.lightprobe_grid_sh, psl->lightprobes, DRW_cache_sphere_get());
+ /* Dummy call just to save select ID */
+ DRW_shgroup_call_dynamic_add_empty(grp);
+ /* Then overide the instance count */
+ DRW_shgroup_set_instance_count(grp, prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z);
+ DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+ DRW_shgroup_uniform_vec3(grp, "corner", prb_data->corner, 1);
+ DRW_shgroup_uniform_vec3(grp, "increment_x", prb_data->increment_x, 1);
+ DRW_shgroup_uniform_vec3(grp, "increment_y", prb_data->increment_y, 1);
+ DRW_shgroup_uniform_vec3(grp, "increment_z", prb_data->increment_z, 1);
+ DRW_shgroup_uniform_ivec3(grp, "grid_resolution", &prb->grid_resolution_x, 1);
+ DRW_shgroup_uniform_float(grp, "sphere_size", &prb->data_draw_size, 1);
+ }
+ else if (prb->type == LIGHTPROBE_TYPE_CUBE) {
+ prb_data->draw_size = prb->data_draw_size * 0.1f;
+ unit_m4(prb_data->probe_cube_mat);
+ copy_v3_v3(prb_data->probe_cube_mat[3], ob->obmat[3]);
+ DRW_shgroup_call_dynamic_add(stl->g_data->lightprobes_cube, color, &prb_data->draw_size, prb_data->probe_cube_mat);
+ }
+ else {
+ prb_data->draw_size = 1.0f;
+ DRW_shgroup_call_dynamic_add(stl->g_data->lightprobes_planar, color, &prb_data->draw_size, ob->obmat);
+ }
+ }
+
+ switch (prb->type) {
+ case LIGHTPROBE_TYPE_PLANAR:
+ DRW_shgroup_call_dynamic_add(stl->g_data->probe_planar, ob->obmat[3], color);
+ break;
+ case LIGHTPROBE_TYPE_GRID:
+ DRW_shgroup_call_dynamic_add(stl->g_data->probe_grid, ob->obmat[3], color);
+ break;
+ case LIGHTPROBE_TYPE_CUBE:
+ default:
+ DRW_shgroup_call_dynamic_add(stl->g_data->probe_cube, ob->obmat[3], color);
+ break;
+ }
+
+
+
+ if (prb->type == LIGHTPROBE_TYPE_PLANAR) {
+ float (*mat)[4];
+ mat = (float (*)[4])(prb_data->prb_mats[0]);
+ copy_m4_m4(mat, ob->obmat);
+ normalize_m4(mat);
+
+ DRW_shgroup_call_dynamic_add(stl->g_data->single_arrow, color, &ob->empty_drawsize, mat);
+ DRW_shgroup_call_dynamic_add(stl->g_data->single_arrow_line, color, &ob->empty_drawsize, mat);
+
+ mat = (float (*)[4])(prb_data->prb_mats[1]);
+ copy_m4_m4(mat, ob->obmat);
+ zero_v3(mat[2]);
+
+ DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &one, mat);
+ }
+
+ if ((prb->flag & LIGHTPROBE_FLAG_SHOW_INFLUENCE) != 0) {
+
+ prb->distfalloff = (1.0f - prb->falloff) * prb->distinf;
+ prb->distgridinf = prb->distinf;
+
+ if (prb->type == LIGHTPROBE_TYPE_GRID) {
+ prb->distfalloff += 1.0f;
+ prb->distgridinf += 1.0f;
+ }
+
+ if (prb->type == LIGHTPROBE_TYPE_GRID ||
+ prb->attenuation_type == LIGHTPROBE_SHAPE_BOX)
+ {
+ DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &prb->distgridinf, ob->obmat);
+ DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &prb->distfalloff, ob->obmat);
+ }
+ else if (prb->type == LIGHTPROBE_TYPE_PLANAR) {
+ float (*rangemat)[4];
+ rangemat = (float (*)[4])(prb_data->prb_mats[2]);
+ copy_m4_m4(rangemat, ob->obmat);
+ normalize_v3(rangemat[2]);
+ mul_v3_fl(rangemat[2], prb->distinf);
+
+ DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &one, rangemat);
+
+ rangemat = (float (*)[4])(prb_data->prb_mats[3]);
+ copy_m4_m4(rangemat, ob->obmat);
+ normalize_v3(rangemat[2]);
+ mul_v3_fl(rangemat[2], prb->distfalloff);
+
+ DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &one, rangemat);
+ }
+ else {
+ DRW_shgroup_call_dynamic_add(stl->g_data->sphere, color, &prb->distgridinf, ob->obmat);
+ DRW_shgroup_call_dynamic_add(stl->g_data->sphere, color, &prb->distfalloff, ob->obmat);
+ }
+ }
+
+ if ((prb->flag & LIGHTPROBE_FLAG_SHOW_PARALLAX) != 0) {
+ if (prb->type != LIGHTPROBE_TYPE_PLANAR) {
+ float (*obmat)[4], *dist;
+
+ if ((prb->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) {
+ dist = &prb->distpar;
+ /* TODO object parallax */
+ obmat = ob->obmat;
+ }
+ else {
+ dist = &prb->distinf;
+ obmat = ob->obmat;
+ }
+
+ if (prb->parallax_type == LIGHTPROBE_SHAPE_BOX) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, dist, obmat);
+ }
+ else {
+ DRW_shgroup_call_dynamic_add(stl->g_data->sphere, color, dist, obmat);
+ }
+ }
+ }
+
+ if ((prb->flag & LIGHTPROBE_FLAG_SHOW_CLIP_DIST) != 0) {
+ if (prb->type != LIGHTPROBE_TYPE_PLANAR) {
+ static const float cubefacemat[6][4][4] = {
+ {{0.0, 0.0, -1.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {-1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}},
+ {{0.0, 0.0, 1.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}},
+ {{1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, -1.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}},
+ {{1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}},
+ {{1.0, 0.0, 0.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {0.0, 0.0, -1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}},
+ {{-1.0, 0.0, 0.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}},
+ };
+
+ for (int i = 0; i < 6; ++i) {
+ float (*clipmat)[4];
+ clipmat = (float (*)[4])(prb_data->prb_mats[i]);
+
+ normalize_m4_m4(clipmat, ob->obmat);
+ mul_m4_m4m4(clipmat, clipmat, cubefacemat[i]);
+
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_buflimit, color, &prb->clipsta, &prb->clipend, clipmat);
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_buflimit_points, color, &prb->clipsta, &prb->clipend, clipmat);
+ }
+ }
+ }
+
+ /* Line and point going to the ground */
+ if (prb->type == LIGHTPROBE_TYPE_CUBE) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_groundline, ob->obmat[3]);
+ DRW_shgroup_call_dynamic_add(stl->g_data->lamp_groundpoint, ob->obmat[3]);
+ }
+}
+
+static void DRW_shgroup_relationship_lines(OBJECT_StorageList *stl, Object *ob)
+{
+ if (ob->parent && BKE_object_is_visible(ob->parent)) {
+ DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->obmat[3]);
+ DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->parent->obmat[3]);
+ }
+}
+
+static void DRW_shgroup_object_center(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer, View3D *v3d)
+{
+ const bool is_library = ob->id.us > 1 || ID_IS_LINKED(ob);
+ DRWShadingGroup *shgroup;
+
+ if (ob == OBACT(view_layer)) {
+ shgroup = stl->g_data->center_active;
+ }
+ else if (ob->base_flag & BASE_SELECTED) {
+ if (is_library) {
+ shgroup = stl->g_data->center_selected_lib;
+ }
+ else {
+ shgroup = stl->g_data->center_selected;
+ }
+ }
+ else if (v3d->flag & V3D_DRAW_CENTERS) {
+ if (is_library) {
+ shgroup = stl->g_data->center_deselected_lib;
+ }
+ else {
+ shgroup = stl->g_data->center_deselected;
+ }
+ }
+ else {
+ return;
+ }
+
+ DRW_shgroup_call_dynamic_add(shgroup, ob->obmat[3]);
+}
+
+static void OBJECT_cache_populate_particles(Object *ob,
+ OBJECT_PassList *psl)
+{
+ for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) {
+ if (psys_check_enabled(ob, psys, false)) {
+ ParticleSettings *part = psys->part;
+ int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
+
+ if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) {
+ draw_as = PART_DRAW_DOT;
+ }
+
+ static float mat[4][4];
+ unit_m4(mat);
+
+ if (draw_as != PART_DRAW_PATH) {
+ struct Gwn_Batch *geom = DRW_cache_particles_get_dots(psys);
+ DRWShadingGroup *shgrp = NULL;
+ static int screen_space[2] = {0, 1};
+ static float def_prim_col[3] = {0.5f, 0.5f, 0.5f};
+ static float def_sec_col[3] = {1.0f, 1.0f, 1.0f};
+
+ Material *ma = give_current_material(ob, part->omat);
+
+ switch (draw_as) {
+ case PART_DRAW_DOT:
+ shgrp = DRW_shgroup_create(e_data.part_dot_sh, psl->particle);
+ DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1);
+ DRW_shgroup_uniform_vec3(shgrp, "outlineColor", ma ? &ma->specr : def_sec_col, 1);
+ DRW_shgroup_uniform_float(shgrp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
+ DRW_shgroup_uniform_float(shgrp, "size", &part->draw_size, 1);
+ DRW_shgroup_uniform_texture(shgrp, "ramp", globals_ramp);
+ DRW_shgroup_call_add(shgrp, geom, mat);
+ break;
+ case PART_DRAW_CROSS:
+ shgrp = DRW_shgroup_instance_create(
+ e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CROSS));
+ DRW_shgroup_uniform_texture(shgrp, "ramp", globals_ramp);
+ DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1);
+ DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1);
+ break;
+ case PART_DRAW_CIRC:
+ shgrp = DRW_shgroup_instance_create(
+ e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CIRC));
+ DRW_shgroup_uniform_texture(shgrp, "ramp", globals_ramp);
+ DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1);
+ DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[1], 1);
+ break;
+ case PART_DRAW_AXIS:
+ shgrp = DRW_shgroup_instance_create(
+ e_data.part_axis_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_AXIS));
+ DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1);
+ break;
+ default:
+ break;
+ }
+
+ if (shgrp) {
+ if (draw_as != PART_DRAW_DOT) {
+ DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1);
+ DRW_shgroup_instance_batch(shgrp, geom);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void OBJECT_cache_populate(void *vedata, Object *ob)
+{
+ OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl;
+ OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ View3D *v3d = draw_ctx->v3d;
+ int theme_id = TH_UNDEFINED;
+
+ if (!BKE_object_is_visible(ob)) {
+ return;
+ }
+
+ //CollectionEngineSettings *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, "");
+
+ //bool do_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_wire");
+ bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
+
+ if (do_outlines) {
+ Object *obedit = scene->obedit;
+ if (ob != obedit && !((ob == draw_ctx->obact) && (ob->mode & OB_MODE_ALL_PAINT))) {
+ struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
+ if (geom) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ DRWShadingGroup *shgroup = shgroup_theme_id_to_outline_or(stl, theme_id, NULL);
+ if (shgroup != NULL) {
+ DRW_shgroup_call_add(shgroup, geom, ob->obmat);
+ }
+ }
+ }
+ }
+
+ switch (ob->type) {
+ case OB_MESH:
+ {
+ Mesh *me = ob->data;
+ if (me->totpoly == 0) {
+ Object *obedit = scene->obedit;
+ if (ob != obedit) {
+ struct Gwn_Batch *geom = DRW_cache_mesh_edges_get(ob);
+ if (geom) {
+ if (theme_id == TH_UNDEFINED) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ }
+
+ DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire);
+ DRW_shgroup_call_add(shgroup, geom, ob->obmat);
+ }
+ }
+ }
+
+ OBJECT_cache_populate_particles(ob, psl);
+ break;
+ }
+ case OB_SURF:
+ break;
+ case OB_LATTICE:
+ {
+ Object *obedit = scene->obedit;
+ if (ob != obedit) {
+ struct Gwn_Batch *geom = DRW_cache_lattice_wire_get(ob, false);
+ if (theme_id == TH_UNDEFINED) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ }
+
+ DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire);
+ DRW_shgroup_call_add(shgroup, geom, ob->obmat);
+ }
+ break;
+ }
+
+ case OB_CURVE:
+ {
+ Object *obedit = scene->obedit;
+ if (ob != obedit) {
+ struct Gwn_Batch *geom = DRW_cache_curve_edge_wire_get(ob);
+ if (theme_id == TH_UNDEFINED) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ }
+ DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire);
+ DRW_shgroup_call_add(shgroup, geom, ob->obmat);
+ }
+ break;
+ }
+ case OB_MBALL:
+ {
+ Object *obedit = scene->obedit;
+ if (ob != obedit) {
+ DRW_shgroup_mball_helpers(stl, ob, view_layer);
+ }
+ break;
+ }
+ case OB_LAMP:
+ DRW_shgroup_lamp(stl, ob, view_layer);
+ break;
+ case OB_CAMERA:
+ DRW_shgroup_camera(stl, ob, view_layer);
+ break;
+ case OB_EMPTY:
+ DRW_shgroup_empty(stl, psl, ob, view_layer);
+ break;
+ case OB_SPEAKER:
+ DRW_shgroup_speaker(stl, ob, view_layer);
+ break;
+ case OB_LIGHTPROBE:
+ DRW_shgroup_lightprobe(stl, psl, ob, view_layer);
+ break;
+ case OB_ARMATURE:
+ {
+ bArmature *arm = ob->data;
+ if (arm->edbo == NULL) {
+ if (DRW_state_is_select() || !DRW_pose_mode_armature(ob, draw_ctx->obact)) {
+ DRW_shgroup_armature_object(
+ ob, view_layer, psl->bone_solid, psl->bone_wire, psl->bone_envelope,
+ stl->g_data->relationship_lines);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (ob->pd && ob->pd->forcefield) {
+ DRW_shgroup_forcefield(stl, ob, view_layer);
+ }
+
+ /* don't show object extras in set's */
+ if ((ob->base_flag & (BASE_FROM_SET | BASE_FROMDUPLI)) == 0) {
+
+ DRW_shgroup_object_center(stl, ob, view_layer, v3d);
+
+ DRW_shgroup_relationship_lines(stl, ob);
+
+ if ((ob->dtx & OB_DRAWNAME) && DRW_state_show_text()) {
+ struct DRWTextStore *dt = DRW_text_cache_ensure();
+ if (theme_id == TH_UNDEFINED) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ }
+
+ unsigned char color[4];
+ UI_GetThemeColor4ubv(theme_id, color);
+
+ DRW_text_cache_add(
+ dt, ob->obmat[3],
+ ob->id.name + 2, strlen(ob->id.name + 2),
+ 10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color);
+ }
+ }
+}
+
+static void OBJECT_draw_scene(void *vedata)
+{
+
+ OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl;
+ OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl;
+ OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ if (DRW_state_is_fbo()) {
+ DRW_stats_group_start("Outlines");
+ /* attach temp textures */
+ DRW_framebuffer_texture_attach(fbl->outlines, e_data.outlines_depth_tx, 0, 0);
+ DRW_framebuffer_texture_attach(fbl->outlines, e_data.outlines_color_tx, 0, 0);
+ DRW_framebuffer_texture_attach(fbl->blur, e_data.outlines_blur_tx, 0, 0);
+
+ /* Render filled polygon on a separate framebuffer */
+ DRW_framebuffer_bind(fbl->outlines);
+ DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
+ DRW_draw_pass(psl->outlines);
+ DRW_draw_pass(psl->lightprobes);
+
+ /* detach textures */
+ DRW_framebuffer_texture_detach(e_data.outlines_depth_tx);
+
+ /* Search outline pixels */
+ DRW_framebuffer_bind(fbl->blur);
+ DRW_draw_pass(psl->outlines_search);
+
+ /* Expand outline to form a 3px wide line */
+ DRW_framebuffer_bind(fbl->outlines);
+ DRW_draw_pass(psl->outlines_expand);
+
+ /* Bleed color so the AA can do it's stuff */
+ DRW_framebuffer_bind(fbl->blur);
+ DRW_draw_pass(psl->outlines_bleed);
+
+ /* detach temp textures */
+ DRW_framebuffer_texture_detach(e_data.outlines_color_tx);
+ DRW_framebuffer_texture_detach(e_data.outlines_blur_tx);
+
+ /* restore main framebuffer */
+ DRW_framebuffer_bind(dfbl->default_fb);
+ DRW_stats_group_end();
+ }
+ else if (DRW_state_is_select()) {
+ /* Render probes spheres/planes so we can select them. */
+ DRW_draw_pass(psl->lightprobes);
+ }
+
+ MULTISAMPLE_SYNC_ENABLE(dfbl)
+
+ /* This needs to be drawn after the oultine */
+// DRW_draw_pass(psl->bone_envelope); /* Never drawn in Object mode currently. */
+ DRW_draw_pass(psl->bone_wire);
+ DRW_draw_pass(psl->bone_solid);
+ DRW_draw_pass(psl->non_meshes);
+ DRW_draw_pass(psl->particle);
+ DRW_draw_pass(psl->reference_image);
+
+ MULTISAMPLE_SYNC_DISABLE(dfbl)
+
+ DRW_draw_pass(psl->ob_center);
+
+ if (DRW_state_is_fbo()) {
+ if (e_data.draw_grid) {
+ DRW_framebuffer_texture_detach(dtxl->depth);
+ DRW_draw_pass(psl->grid);
+ DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ }
+
+ /* Combine with scene buffer last */
+ DRW_draw_pass(psl->outlines_resolve);
+ }
+
+ /* This has to be freed only after drawing empties! */
+ if (stl->g_data->image_plane_map) {
+ BLI_ghash_free(stl->g_data->image_plane_map, NULL, MEM_freeN);
+ }
+}
+
+void OBJECT_collection_settings_create(IDProperty *props)
+{
+ BLI_assert(props &&
+ props->type == IDP_GROUP &&
+ props->subtype == IDP_GROUP_SUB_MODE_OBJECT);
+ BKE_collection_engine_property_add_int(props, "show_wire", false);
+ BKE_collection_engine_property_add_int(props, "show_backface_culling", false);
+}
+
+static const DrawEngineDataSize OBJECT_data_size = DRW_VIEWPORT_DATA_SIZE(OBJECT_Data);
+
+DrawEngineType draw_engine_object_type = {
+ NULL, NULL,
+ N_("ObjectMode"),
+ &OBJECT_data_size,
+ &OBJECT_engine_init,
+ &OBJECT_engine_free,
+ &OBJECT_cache_init,
+ &OBJECT_cache_populate,
+ NULL,
+ NULL,
+ &OBJECT_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
new file mode 100644
index 00000000000..b49da0cba2f
--- /dev/null
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -0,0 +1,417 @@
+/*
+ * 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/modes/paint_texture_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "BIF_gl.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+#include "DNA_mesh_types.h"
+
+extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_paint_texture_vert_glsl[];
+extern char datatoc_paint_texture_frag_glsl[];
+extern char datatoc_paint_wire_vert_glsl[];
+extern char datatoc_paint_wire_frag_glsl[];
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use PAINT_TEXTURE_engine_init() to
+ * initialize most of them and PAINT_TEXTURE_cache_init()
+ * for PAINT_TEXTURE_PassList */
+
+typedef struct PAINT_TEXTURE_PassList {
+ /* Declare all passes here and init them in
+ * PAINT_TEXTURE_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *image_faces;
+
+ struct DRWPass *wire_overlay;
+ struct DRWPass *face_overlay;
+} PAINT_TEXTURE_PassList;
+
+typedef struct PAINT_TEXTURE_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} PAINT_TEXTURE_FramebufferList;
+
+typedef struct PAINT_TEXTURE_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} PAINT_TEXTURE_TextureList;
+
+typedef struct PAINT_TEXTURE_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct PAINT_TEXTURE_PrivateData *g_data;
+} PAINT_TEXTURE_StorageList;
+
+typedef struct PAINT_TEXTURE_Data {
+ /* Struct returned by DRW_viewport_engine_data_ensure.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ PAINT_TEXTURE_FramebufferList *fbl;
+ PAINT_TEXTURE_TextureList *txl;
+ PAINT_TEXTURE_PassList *psl;
+ PAINT_TEXTURE_StorageList *stl;
+} PAINT_TEXTURE_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in PAINT_TEXTURE_engine_init();
+ * free in PAINT_TEXTURE_engine_free(); */
+ struct GPUShader *fallback_sh;
+ struct GPUShader *image_sh;
+
+ struct GPUShader *wire_overlay_shader;
+ struct GPUShader *face_overlay_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct PAINT_TEXTURE_PrivateData {
+ /* This keeps the references of the shading groups for
+ * easy access in PAINT_TEXTURE_cache_populate() */
+ DRWShadingGroup *shgroup_fallback;
+ DRWShadingGroup **shgroup_image_array;
+
+ /* face-mask */
+ DRWShadingGroup *lwire_shgrp;
+ DRWShadingGroup *face_shgrp;
+} PAINT_TEXTURE_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void PAINT_TEXTURE_engine_init(void *vedata)
+{
+ PAINT_TEXTURE_TextureList *txl = ((PAINT_TEXTURE_Data *)vedata)->txl;
+ PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
+ PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_TEX_DEPTH_24, 0},
+ * {&txl->color, DRW_TEX_RGBA_8, DRW_TEX_FILTER}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.fallback_sh) {
+ e_data.fallback_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+ if (!e_data.image_sh) {
+ e_data.image_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ e_data.image_sh = DRW_shader_create_with_lib(
+ datatoc_paint_texture_vert_glsl, NULL,
+ datatoc_paint_texture_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+
+ }
+
+ if (!e_data.wire_overlay_shader) {
+ e_data.wire_overlay_shader = DRW_shader_create_with_lib(
+ datatoc_paint_wire_vert_glsl, NULL,
+ datatoc_paint_wire_frag_glsl,
+ datatoc_common_globals_lib_glsl,
+ "#define VERTEX_MODE\n");
+ }
+
+ if (!e_data.face_overlay_shader) {
+ e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void PAINT_TEXTURE_cache_init(void *vedata)
+{
+ PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
+ PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ stl->g_data->shgroup_image_array = NULL;
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS |
+ DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->image_faces = DRW_pass_create("Image Color Pass", state);
+
+ stl->g_data->shgroup_fallback = DRW_shgroup_create(e_data.fallback_sh, psl->image_faces);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {1.0f, 0.0f, 1.0f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->shgroup_fallback, "color", color, 1);
+
+ MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Object *ob = draw_ctx->obact;
+ if (ob && ob->type == OB_MESH) {
+ Scene *scene = draw_ctx->scene;
+ const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
+ const Mesh *me = ob->data;
+
+ stl->g_data->shgroup_image_array = MEM_mallocN(
+ sizeof(*stl->g_data->shgroup_image_array) * (use_material_slots ? me->totcol : 1), __func__);
+
+ if (use_material_slots) {
+ for (int i = 0; i < me->totcol; i++) {
+ Material *ma = give_current_material(ob, i + 1);
+ Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
+ GPUTexture *tex = ima ?
+ GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, false, false) : NULL;
+
+ if (tex) {
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
+ DRW_shgroup_uniform_texture(grp, "image", tex);
+ stl->g_data->shgroup_image_array[i] = grp;
+ }
+ else {
+ stl->g_data->shgroup_image_array[i] = NULL;
+ }
+ }
+ }
+ else {
+ Image *ima = scene->toolsettings->imapaint.canvas;
+ GPUTexture *tex = ima ?
+ GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, false, false) : NULL;
+
+ if (tex) {
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
+ DRW_shgroup_uniform_texture(grp, "image", tex);
+ stl->g_data->shgroup_image_array[0] = grp;
+ }
+ else {
+ stl->g_data->shgroup_image_array[0] = NULL;
+ }
+ }
+ }
+ }
+
+ /* Face Mask */
+ {
+ psl->wire_overlay = DRW_pass_create(
+ "Wire Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+
+ stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
+ }
+
+ {
+ psl->face_overlay = DRW_pass_create(
+ "Face Mask Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND);
+
+ stl->g_data->face_shgrp = DRW_shgroup_create(e_data.face_overlay_shader, psl->face_overlay);
+
+ static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f};
+ DRW_shgroup_uniform_vec4(stl->g_data->face_shgrp, "color", col, 1);
+ }
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
+{
+ PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
+ PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ UNUSED_VARS(psl, stl);
+
+ if ((ob->type == OB_MESH) && (draw_ctx->obact == ob)) {
+ /* Get geometry cache */
+ const Mesh *me = ob->data;
+ Scene *scene = draw_ctx->scene;
+ const bool use_surface = DRW_object_is_mode_shade(ob) == true;
+ const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
+ bool ok = false;
+
+ if (use_surface) {
+ if (me->mloopuv != NULL) {
+ if (use_material_slots) {
+ struct Gwn_Batch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
+ if ((me->totcol == 0) || (geom_array == NULL)) {
+ struct Gwn_Batch *geom = DRW_cache_mesh_surface_get(ob);
+ DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
+ ok = true;
+ }
+ else {
+ for (int i = 0; i < me->totcol; i++) {
+ if (stl->g_data->shgroup_image_array[i]) {
+ DRW_shgroup_call_add(stl->g_data->shgroup_image_array[i], geom_array[i], ob->obmat);
+ }
+ else {
+ DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat);
+ }
+ ok = true;
+ }
+ }
+ }
+ else {
+ struct Gwn_Batch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
+ if (geom && stl->g_data->shgroup_image_array[0]) {
+ DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat);
+ ok = true;
+ }
+ }
+ }
+
+ if (!ok) {
+ struct Gwn_Batch *geom = DRW_cache_mesh_surface_get(ob);
+ DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
+ }
+ }
+
+ /* Face Mask */
+ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ if (use_face_sel) {
+ struct Gwn_Batch *geom;
+ /* Note: ideally selected faces wouldn't show interior wire. */
+ const bool use_wire = true;
+ geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel);
+ DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat);
+
+ geom = DRW_cache_mesh_faces_weight_overlay_get(ob);
+ DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat);
+ }
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void PAINT_TEXTURE_cache_finish(void *vedata)
+{
+ PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
+ PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl);
+
+ MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void PAINT_TEXTURE_draw_scene(void *vedata)
+{
+ PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
+ PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ DRW_draw_pass(psl->image_faces);
+
+ DRW_draw_pass(psl->face_overlay);
+ DRW_draw_pass(psl->wire_overlay);
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void PAINT_TEXTURE_engine_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.image_sh);
+ DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void PAINT_TEXTURE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+static const DrawEngineDataSize PAINT_TEXTURE_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_TEXTURE_Data);
+
+DrawEngineType draw_engine_paint_texture_type = {
+ NULL, NULL,
+ N_("PaintTextureMode"),
+ &PAINT_TEXTURE_data_size,
+ &PAINT_TEXTURE_engine_init,
+ &PAINT_TEXTURE_engine_free,
+ &PAINT_TEXTURE_cache_init,
+ &PAINT_TEXTURE_cache_populate,
+ &PAINT_TEXTURE_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &PAINT_TEXTURE_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c
new file mode 100644
index 00000000000..e430fca5742
--- /dev/null
+++ b/source/blender/draw/modes/paint_vertex_mode.c
@@ -0,0 +1,216 @@
+/*
+ * 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/modes/paint_vertex_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+#include "DNA_mesh_types.h"
+
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+extern char datatoc_paint_wire_vert_glsl[];
+extern char datatoc_paint_wire_frag_glsl[];
+extern char datatoc_common_globals_lib_glsl[];
+
+/* *********** LISTS *********** */
+
+typedef struct PAINT_VERTEX_PassList {
+ struct DRWPass *vcolor_faces;
+ struct DRWPass *wire_overlay;
+ struct DRWPass *face_overlay;
+} PAINT_VERTEX_PassList;
+
+typedef struct PAINT_VERTEX_StorageList {
+ struct PAINT_VERTEX_PrivateData *g_data;
+} PAINT_VERTEX_StorageList;
+
+typedef struct PAINT_VERTEX_Data {
+ void *engine_type; /* Required */
+ DRWViewportEmptyList *fbl;
+ DRWViewportEmptyList *txl;
+ PAINT_VERTEX_PassList *psl;
+ PAINT_VERTEX_StorageList *stl;
+} PAINT_VERTEX_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ struct GPUShader *vcolor_face_shader;
+ struct GPUShader *wire_overlay_shader;
+ struct GPUShader *face_overlay_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct PAINT_VERTEX_PrivateData {
+ DRWShadingGroup *fvcolor_shgrp;
+ DRWShadingGroup *lwire_shgrp;
+ DRWShadingGroup *face_shgrp;
+} PAINT_VERTEX_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+static void PAINT_VERTEX_engine_init(void *UNUSED(vedata))
+{
+ if (!e_data.vcolor_face_shader) {
+ e_data.vcolor_face_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA);
+ }
+
+ if (!e_data.wire_overlay_shader) {
+ e_data.wire_overlay_shader = DRW_shader_create_with_lib(
+ datatoc_paint_wire_vert_glsl, NULL,
+ datatoc_paint_wire_frag_glsl,
+ datatoc_common_globals_lib_glsl, "#define VERTEX_MODE\n");
+ }
+
+ if (!e_data.face_overlay_shader) {
+ e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+static float world_light;
+
+static void PAINT_VERTEX_cache_init(void *vedata)
+{
+ PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl;
+ PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Create a pass */
+ psl->vcolor_faces = DRW_pass_create(
+ "Vert Color Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+
+ stl->g_data->fvcolor_shgrp = DRW_shgroup_create(e_data.vcolor_face_shader, psl->vcolor_faces);
+
+ static float light[3] = {-0.3f, 0.5f, 1.0f};
+ static float alpha = 1.0f;
+ DRW_shgroup_uniform_vec3(stl->g_data->fvcolor_shgrp, "light", light, 1);
+ DRW_shgroup_uniform_float(stl->g_data->fvcolor_shgrp, "alpha", &alpha, 1);
+ DRW_shgroup_uniform_float(stl->g_data->fvcolor_shgrp, "global", &world_light, 1);
+ }
+
+ {
+ psl->wire_overlay = DRW_pass_create(
+ "Wire Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+
+ stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
+ }
+
+ {
+ psl->face_overlay = DRW_pass_create(
+ "Face Mask Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND);
+
+ stl->g_data->face_shgrp = DRW_shgroup_create(e_data.face_overlay_shader, psl->face_overlay);
+
+ static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f};
+ DRW_shgroup_uniform_vec4(stl->g_data->face_shgrp, "color", col, 1);
+ }
+}
+
+static void PAINT_VERTEX_cache_populate(void *vedata, Object *ob)
+{
+ PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ if ((ob->type == OB_MESH) && (ob == draw_ctx->obact)) {
+ IDProperty *ces_mode_pw = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_PAINT_VERTEX, "");
+ const Mesh *me = ob->data;
+ const bool use_wire = BKE_collection_engine_property_value_get_bool(ces_mode_pw, "use_wire");
+ const bool use_surface = DRW_object_is_mode_shade(ob) == true;
+ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ struct Gwn_Batch *geom;
+
+ world_light = BKE_collection_engine_property_value_get_bool(ces_mode_pw, "use_shading") ? 0.5f : 1.0f;
+
+ if (use_surface) {
+ geom = DRW_cache_mesh_surface_vert_colors_get(ob);
+ DRW_shgroup_call_add(stl->g_data->fvcolor_shgrp, geom, ob->obmat);
+ }
+
+ if (use_face_sel || use_wire) {
+ geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel);
+ DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat);
+ }
+
+ if (use_face_sel) {
+ geom = DRW_cache_mesh_faces_weight_overlay_get(ob);
+ DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat);
+ }
+ }
+}
+
+static void PAINT_VERTEX_draw_scene(void *vedata)
+{
+ PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl;
+
+ DRW_draw_pass(psl->vcolor_faces);
+ DRW_draw_pass(psl->face_overlay);
+ DRW_draw_pass(psl->wire_overlay);
+}
+
+static void PAINT_VERTEX_engine_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
+}
+
+void PAINT_VERTEX_collection_settings_create(IDProperty *properties)
+{
+ BLI_assert(properties &&
+ properties->type == IDP_GROUP &&
+ properties->subtype == IDP_GROUP_SUB_MODE_PAINT_VERTEX);
+
+ BKE_collection_engine_property_add_bool(properties, "use_shading", true);
+ BKE_collection_engine_property_add_bool(properties, "use_wire", false);
+}
+
+static const DrawEngineDataSize PAINT_VERTEX_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_VERTEX_Data);
+
+DrawEngineType draw_engine_paint_vertex_type = {
+ NULL, NULL,
+ N_("PaintVertexMode"),
+ &PAINT_VERTEX_data_size,
+ &PAINT_VERTEX_engine_init,
+ &PAINT_VERTEX_engine_free,
+ &PAINT_VERTEX_cache_init,
+ &PAINT_VERTEX_cache_populate,
+ NULL,
+ NULL,
+ &PAINT_VERTEX_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/paint_weight_mode.c b/source/blender/draw/modes/paint_weight_mode.c
new file mode 100644
index 00000000000..e139b4af97f
--- /dev/null
+++ b/source/blender/draw/modes/paint_weight_mode.c
@@ -0,0 +1,254 @@
+/*
+ * 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/modes/paint_weight_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+#include "DNA_mesh_types.h"
+
+#include "BKE_mesh.h"
+
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+extern char datatoc_paint_wire_vert_glsl[];
+extern char datatoc_paint_wire_frag_glsl[];
+extern char datatoc_paint_vert_frag_glsl[];
+extern char datatoc_common_globals_lib_glsl[];
+
+/* *********** LISTS *********** */
+
+typedef struct PAINT_WEIGHT_PassList {
+ struct DRWPass *weight_faces;
+ struct DRWPass *wire_overlay;
+ struct DRWPass *face_overlay;
+ struct DRWPass *vert_overlay;
+} PAINT_WEIGHT_PassList;
+
+typedef struct PAINT_WEIGHT_StorageList {
+ struct PAINT_WEIGHT_PrivateData *g_data;
+} PAINT_WEIGHT_StorageList;
+
+typedef struct PAINT_WEIGHT_Data {
+ void *engine_type;
+ DRWViewportEmptyList *fbl;
+ DRWViewportEmptyList *txl;
+ PAINT_WEIGHT_PassList *psl;
+ PAINT_WEIGHT_StorageList *stl;
+} PAINT_WEIGHT_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ struct GPUShader *weight_face_shader;
+ struct GPUShader *wire_overlay_shader;
+ struct GPUShader *face_overlay_shader;
+ struct GPUShader *vert_overlay_shader;
+ int actdef;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct PAINT_WEIGHT_PrivateData {
+ DRWShadingGroup *fweights_shgrp;
+ DRWShadingGroup *lwire_shgrp;
+ DRWShadingGroup *face_shgrp;
+ DRWShadingGroup *vert_shgrp;
+} PAINT_WEIGHT_PrivateData;
+
+/* *********** FUNCTIONS *********** */
+
+static void PAINT_WEIGHT_engine_init(void *UNUSED(vedata))
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ if (e_data.actdef != draw_ctx->obact->actdef) {
+ e_data.actdef = draw_ctx->obact->actdef;
+
+ BKE_mesh_batch_cache_dirty(draw_ctx->obact->data, BKE_MESH_BATCH_DIRTY_ALL);
+ }
+
+ if (!e_data.weight_face_shader) {
+ e_data.weight_face_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA);
+ }
+
+ if (!e_data.wire_overlay_shader) {
+ e_data.wire_overlay_shader = DRW_shader_create_with_lib(
+ datatoc_paint_wire_vert_glsl, NULL,
+ datatoc_paint_wire_frag_glsl,
+ datatoc_common_globals_lib_glsl, "#define WEIGHT_MODE\n");
+ }
+
+ if (!e_data.face_overlay_shader) {
+ e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+
+ if (!e_data.vert_overlay_shader) {
+ e_data.vert_overlay_shader = DRW_shader_create_with_lib(
+ datatoc_paint_wire_vert_glsl, NULL,
+ datatoc_paint_vert_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+ }
+}
+
+static float world_light;
+
+static void PAINT_WEIGHT_cache_init(void *vedata)
+{
+ PAINT_WEIGHT_PassList *psl = ((PAINT_WEIGHT_Data *)vedata)->psl;
+ PAINT_WEIGHT_StorageList *stl = ((PAINT_WEIGHT_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Create a pass */
+ psl->weight_faces = DRW_pass_create(
+ "Weight Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+
+ stl->g_data->fweights_shgrp = DRW_shgroup_create(e_data.weight_face_shader, psl->weight_faces);
+
+ static float light[3] = {-0.3f, 0.5f, 1.0f};
+ static float alpha = 1.0f;
+ DRW_shgroup_uniform_vec3(stl->g_data->fweights_shgrp, "light", light, 1);
+ DRW_shgroup_uniform_float(stl->g_data->fweights_shgrp, "alpha", &alpha, 1);
+ DRW_shgroup_uniform_float(stl->g_data->fweights_shgrp, "global", &world_light, 1);
+ }
+
+ {
+ psl->wire_overlay = DRW_pass_create(
+ "Wire Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+
+ stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
+ }
+
+ {
+ psl->face_overlay = DRW_pass_create(
+ "Face Mask Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND);
+
+ stl->g_data->face_shgrp = DRW_shgroup_create(e_data.face_overlay_shader, psl->face_overlay);
+
+ static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f};
+ DRW_shgroup_uniform_vec4(stl->g_data->face_shgrp, "color", col, 1);
+ }
+
+ {
+ psl->vert_overlay = DRW_pass_create(
+ "Vert Mask Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+
+ stl->g_data->vert_shgrp = DRW_shgroup_create(e_data.vert_overlay_shader, psl->vert_overlay);
+ }
+}
+
+static void PAINT_WEIGHT_cache_populate(void *vedata, Object *ob)
+{
+ PAINT_WEIGHT_StorageList *stl = ((PAINT_WEIGHT_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ if ((ob->type == OB_MESH) && (ob == draw_ctx->obact)) {
+ IDProperty *ces_mode_pw = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_PAINT_WEIGHT, "");
+ const Mesh *me = ob->data;
+ const bool use_wire = BKE_collection_engine_property_value_get_bool(ces_mode_pw, "use_wire");
+ const bool use_surface = DRW_object_is_mode_shade(ob) == true;
+ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ struct Gwn_Batch *geom;
+
+ world_light = BKE_collection_engine_property_value_get_bool(ces_mode_pw, "use_shading") ? 0.5f : 1.0f;
+
+ if (use_surface) {
+ geom = DRW_cache_mesh_surface_weights_get(ob);
+ DRW_shgroup_call_add(stl->g_data->fweights_shgrp, geom, ob->obmat);
+ }
+
+ if (use_face_sel || use_wire) {
+ geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel);
+ DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat);
+ }
+
+ if (use_face_sel) {
+ geom = DRW_cache_mesh_faces_weight_overlay_get(ob);
+ DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat);
+ }
+
+ if (use_vert_sel) {
+ geom = DRW_cache_mesh_verts_weight_overlay_get(ob);
+ DRW_shgroup_call_add(stl->g_data->vert_shgrp, geom, ob->obmat);
+ }
+ }
+}
+
+static void PAINT_WEIGHT_draw_scene(void *vedata)
+{
+ PAINT_WEIGHT_PassList *psl = ((PAINT_WEIGHT_Data *)vedata)->psl;
+
+ DRW_draw_pass(psl->weight_faces);
+ DRW_draw_pass(psl->face_overlay);
+ DRW_draw_pass(psl->wire_overlay);
+ DRW_draw_pass(psl->vert_overlay);
+}
+
+static void PAINT_WEIGHT_engine_free(void)
+{
+ DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
+ DRW_SHADER_FREE_SAFE(e_data.vert_overlay_shader);
+}
+
+void PAINT_WEIGHT_collection_settings_create(IDProperty *properties)
+{
+ BLI_assert(properties &&
+ properties->type == IDP_GROUP &&
+ properties->subtype == IDP_GROUP_SUB_MODE_PAINT_WEIGHT);
+
+ BKE_collection_engine_property_add_bool(properties, "use_shading", true);
+ BKE_collection_engine_property_add_bool(properties, "use_wire", false);
+}
+
+static const DrawEngineDataSize PAINT_WEIGHT_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_WEIGHT_Data);
+
+DrawEngineType draw_engine_paint_weight_type = {
+ NULL, NULL,
+ N_("PaintWeightMode"),
+ &PAINT_WEIGHT_data_size,
+ &PAINT_WEIGHT_engine_init,
+ &PAINT_WEIGHT_engine_free,
+ &PAINT_WEIGHT_cache_init,
+ &PAINT_WEIGHT_cache_populate,
+ NULL,
+ NULL,
+ &PAINT_WEIGHT_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/particle_mode.c b/source/blender/draw/modes/particle_mode.c
new file mode 100644
index 00000000000..6a3e53a72c2
--- /dev/null
+++ b/source/blender/draw/modes/particle_mode.c
@@ -0,0 +1,264 @@
+/*
+ * 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/modes/particle_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use PARTICLE_engine_init() to
+ * initialize most of them and PARTICLE_cache_init()
+ * for PARTICLE_PassList */
+
+typedef struct PARTICLE_PassList {
+ /* Declare all passes here and init them in
+ * PARTICLE_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} PARTICLE_PassList;
+
+typedef struct PARTICLE_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} PARTICLE_FramebufferList;
+
+typedef struct PARTICLE_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} PARTICLE_TextureList;
+
+typedef struct PARTICLE_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct PARTICLE_PrivateData *g_data;
+} PARTICLE_StorageList;
+
+typedef struct PARTICLE_Data {
+ /* Struct returned by DRW_viewport_engine_data_ensure.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ PARTICLE_FramebufferList *fbl;
+ PARTICLE_TextureList *txl;
+ PARTICLE_PassList *psl;
+ PARTICLE_StorageList *stl;
+} PARTICLE_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in PARTICLE_engine_init();
+ * free in PARTICLE_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct PARTICLE_PrivateData {
+ /* This keeps the references of the shading groups for
+ * easy access in PARTICLE_cache_populate() */
+ DRWShadingGroup *group;
+} PARTICLE_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void PARTICLE_engine_init(void *vedata)
+{
+ PARTICLE_TextureList *txl = ((PARTICLE_Data *)vedata)->txl;
+ PARTICLE_FramebufferList *fbl = ((PARTICLE_Data *)vedata)->fbl;
+ PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_TEX_DEPTH_24, 0},
+ * {&txl->color, DRW_TEX_RGBA_8, DRW_TEX_FILTER}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void PARTICLE_cache_init(void *vedata)
+{
+ PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl;
+ PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {0.2f, 0.5f, 0.3f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void PARTICLE_cache_populate(void *vedata, Object *ob)
+{
+ PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl;
+ PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Gwn_Batch *geom = DRW_cache_mesh_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void PARTICLE_cache_finish(void *vedata)
+{
+ PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl;
+ PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void PARTICLE_draw_scene(void *vedata)
+{
+
+ PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl;
+ PARTICLE_FramebufferList *fbl = ((PARTICLE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void PARTICLE_engine_free(void)
+{
+ // DRW_SHADER_FREE_SAFE(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void PARTICLE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+static const DrawEngineDataSize PARTICLE_data_size = DRW_VIEWPORT_DATA_SIZE(PARTICLE_Data);
+
+DrawEngineType draw_engine_particle_type = {
+ NULL, NULL,
+ N_("ParticleMode"),
+ &PARTICLE_data_size,
+ &PARTICLE_engine_init,
+ &PARTICLE_engine_free,
+ &PARTICLE_cache_init,
+ &PARTICLE_cache_populate,
+ &PARTICLE_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &PARTICLE_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c
new file mode 100644
index 00000000000..1c2acd56085
--- /dev/null
+++ b/source/blender/draw/modes/pose_mode.c
@@ -0,0 +1,198 @@
+/*
+ * 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/modes/pose_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+extern GlobalsUboStorage ts;
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use POSE_engine_init() to
+ * initialize most of them and POSE_cache_init()
+ * for POSE_PassList */
+
+typedef struct POSE_PassList {
+ struct DRWPass *bone_solid;
+ struct DRWPass *bone_wire;
+ struct DRWPass *bone_envelope;
+ struct DRWPass *relationship;
+} POSE_PassList;
+
+typedef struct POSE_StorageList {
+ struct POSE_PrivateData *g_data;
+} POSE_StorageList;
+
+typedef struct POSE_Data {
+ void *engine_type;
+ DRWViewportEmptyList *fbl;
+ DRWViewportEmptyList *txl;
+ POSE_PassList *psl;
+ POSE_StorageList *stl;
+} POSE_Data;
+
+/* *********** STATIC *********** */
+
+typedef struct POSE_PrivateData {
+ DRWShadingGroup *relationship_lines;
+} POSE_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void POSE_cache_init(void *vedata)
+{
+ POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
+ POSE_StorageList *stl = ((POSE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Solid bones */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ psl->bone_solid = DRW_pass_create("Bone Solid Pass", state);
+ }
+
+ {
+ /* Wire bones */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+ psl->bone_wire = DRW_pass_create("Bone Wire Pass", state);
+ }
+
+ {
+ /* distance outline around envelope bones */
+ DRWState state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+ psl->bone_envelope = DRW_pass_create("Bone Envelope Outline Pass", state);
+ }
+
+ {
+ /* Non Meshes Pass (Camera, empties, lamps ...) */
+ DRWState state =
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS |
+ DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->relationship = DRW_pass_create("Bone Relationship Pass", state);
+
+ /* Relationship Lines */
+ stl->g_data->relationship_lines = shgroup_dynlines_uniform_color(psl->relationship, ts.colorWire);
+ DRW_shgroup_state_enable(stl->g_data->relationship_lines, DRW_STATE_STIPPLE_3);
+ }
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void POSE_cache_populate(void *vedata, Object *ob)
+{
+ POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
+ POSE_StorageList *stl = ((POSE_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ /* In the future this will allow us to implement face manipulators,
+ * and similar functionalities. For now we handle only pose bones. */
+
+ if (ob->type == OB_ARMATURE) {
+ if (DRW_pose_mode_armature(ob, draw_ctx->obact)) {
+ DRW_shgroup_armature_pose(
+ ob, psl->bone_solid, psl->bone_wire, psl->bone_envelope,
+ stl->g_data->relationship_lines);
+ }
+ }
+}
+
+/**
+ * Return true if armature should be handled by the pose mode engine.
+ */
+bool DRW_pose_mode_armature(Object *ob, Object *active_ob)
+{
+ /* Pode armature is handled by pose mode engine. */
+ if ((ob == active_ob) && ((ob->mode & OB_MODE_POSE) != 0)) {
+ return true;
+ }
+
+ /* Armature parent is also handled by pose mode engine. */
+ if ((active_ob != NULL) && ((active_ob->mode & OB_MODE_WEIGHT_PAINT) != 0)) {
+ if (active_ob->parent == ob) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void POSE_draw_scene(void *vedata)
+{
+ POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
+
+ DRW_draw_pass(psl->bone_envelope);
+ DRW_draw_pass(psl->bone_wire);
+ DRW_draw_pass(psl->bone_solid);
+ DRW_draw_pass(psl->relationship);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void POSE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "foo", 37);
+}
+#endif
+
+static const DrawEngineDataSize POSE_data_size = DRW_VIEWPORT_DATA_SIZE(POSE_Data);
+
+DrawEngineType draw_engine_pose_type = {
+ NULL, NULL,
+ N_("PoseMode"),
+ &POSE_data_size,
+ NULL,
+ NULL,
+ &POSE_cache_init,
+ &POSE_cache_populate,
+ NULL,
+ NULL,
+ &POSE_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c
new file mode 100644
index 00000000000..d9f1f5ebe91
--- /dev/null
+++ b/source/blender/draw/modes/sculpt_mode.c
@@ -0,0 +1,305 @@
+/*
+ * 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/modes/sculpt_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_pbvh.h"
+#include "BKE_paint.h"
+
+#include "DEG_depsgraph.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+#include "GPU_matrix.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use SCULPT_engine_init() to
+ * initialize most of them and SCULPT_cache_init()
+ * for SCULPT_PassList */
+
+typedef struct SCULPT_PassList {
+ /* Declare all passes here and init them in
+ * SCULPT_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} SCULPT_PassList;
+
+typedef struct SCULPT_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} SCULPT_FramebufferList;
+
+typedef struct SCULPT_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} SCULPT_TextureList;
+
+typedef struct SCULPT_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct SCULPT_PrivateData *g_data;
+} SCULPT_StorageList;
+
+typedef struct SCULPT_Data {
+ /* Struct returned by DRW_viewport_engine_data_ensure.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ SCULPT_FramebufferList *fbl;
+ SCULPT_TextureList *txl;
+ SCULPT_PassList *psl;
+ SCULPT_StorageList *stl;
+} SCULPT_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in SCULPT_engine_init();
+ * free in SCULPT_engine_free(); */
+ struct GPUShader *shader_flat;
+ struct GPUShader *shader_smooth;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct SCULPT_PrivateData {
+ /* This keeps the references of the shading groups for
+ * easy access in SCULPT_cache_populate() */
+ DRWShadingGroup *group_flat;
+ DRWShadingGroup *group_smooth;
+} SCULPT_PrivateData; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void SCULPT_engine_init(void *vedata)
+{
+ SCULPT_TextureList *txl = ((SCULPT_Data *)vedata)->txl;
+ SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl;
+ SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_TEX_DEPTH_24, 0},
+ * {&txl->color, DRW_TEX_RGBA_8, DRW_TEX_FILTER}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.shader_flat) {
+ e_data.shader_flat = GPU_shader_get_builtin_shader(GPU_SHADER_3D_FLAT_COLOR);
+ }
+ if (!e_data.shader_smooth) {
+ e_data.shader_smooth = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SMOOTH_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void SCULPT_cache_init(void *vedata)
+{
+ SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
+ SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_MULTIPLY;
+ psl->pass = DRW_pass_create("Sculpt Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group_flat = DRW_shgroup_create(e_data.shader_flat, psl->pass);
+ stl->g_data->group_smooth = DRW_shgroup_create(e_data.shader_smooth, psl->pass);
+ }
+}
+
+static bool object_is_flat(const Object *ob)
+{
+ Mesh *me = ob->data;
+ if (me->mpoly && me->mpoly[0].flag & ME_SMOOTH) {
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void SCULPT_cache_populate(void *vedata, Object *ob)
+{
+ SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
+ SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(draw_ctx->evil_C, &eval_ctx);
+
+ if (ob->sculpt && (ob == draw_ctx->obact)) {
+
+ /* XXX, needed for dyntopo-undo (which clears).
+ * probably depsgraph should handlle? in 2.7x getting derived-mesh does this (mesh_build_data) */
+ if (ob->sculpt->pbvh == NULL) {
+ /* create PBVH immediately (would be created on the fly too,
+ * but this avoids waiting on first stroke) */
+ Scene *scene = draw_ctx->scene;
+
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, scene->toolsettings->sculpt, ob, false, false);
+ }
+
+ PBVH *pbvh = ob->sculpt->pbvh;
+ if (pbvh && pbvh_has_mask(pbvh)) {
+ /* Get geometry cache */
+ DRWShadingGroup *shgroup = object_is_flat(ob) ? stl->g_data->group_flat : stl->g_data->group_smooth;
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_sculpt_add(shgroup, ob, ob->obmat);
+ }
+ }
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void SCULPT_cache_finish(void *vedata)
+{
+ SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
+ SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void SCULPT_draw_scene(void *vedata)
+{
+ SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
+ SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void SCULPT_engine_free(void)
+{
+ // DRW_SHADER_FREE_SAFE(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void SCULPT_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+static const DrawEngineDataSize SCULPT_data_size = DRW_VIEWPORT_DATA_SIZE(SCULPT_Data);
+
+DrawEngineType draw_engine_sculpt_type = {
+ NULL, NULL,
+ N_("SculptMode"),
+ &SCULPT_data_size,
+ &SCULPT_engine_init,
+ &SCULPT_engine_free,
+ &SCULPT_cache_init,
+ &SCULPT_cache_populate,
+ &SCULPT_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &SCULPT_draw_scene,
+ NULL,
+};
diff --git a/source/blender/draw/modes/shaders/common_fxaa_lib.glsl b/source/blender/draw/modes/shaders/common_fxaa_lib.glsl
new file mode 100644
index 00000000000..8158437b943
--- /dev/null
+++ b/source/blender/draw/modes/shaders/common_fxaa_lib.glsl
@@ -0,0 +1,678 @@
+//----------------------------------------------------------------------------------
+// File: es3-kepler\FXAA/FXAA3_11.h
+// SDK Version: v3.00
+// Email: gameworks@nvidia.com
+// Site: http://developer.nvidia.com/
+//
+// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of NVIDIA CORPORATION nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//----------------------------------------------------------------------------------
+
+/* BLENDER MODIFICATIONS:
+ *
+ * - (#B1#) Compute luma on the fly using BT. 709 luma function
+ * - (#B2#) main function instead of #include, due to lack of
+ * ARB_shading_language_include in 3.3
+ * - (#B3#) version and extension directives
+ * - removed "FXAA Console" algorithm support and shader parameters
+ * - removed HLSL support shims
+ * - (#B4#) change luma sampling to compute, not use A channel
+ * (this also removes GATHER4_ALPHA support)
+ * - removed all the console shaders (only remaining algorithm is "FXAA PC
+ * Quality")
+ *
+ * Note that this file doesn't follow the coding style guidelines.
+ */
+
+/*============================================================================
+ FXAA QUALITY - TUNING KNOBS
+------------------------------------------------------------------------------
+NOTE the other tuning knobs are now in the shader function inputs!
+============================================================================*/
+#ifndef FXAA_QUALITY__PRESET
+ //
+ // Choose the quality preset.
+ // This needs to be compiled into the shader as it effects code.
+ // Best option to include multiple presets is to
+ // in each shader define the preset, then include this file.
+ //
+ // OPTIONS
+ // -----------------------------------------------------------------------
+ // 10 to 15 - default medium dither (10=fastest, 15=highest quality)
+ // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)
+ // 39 - no dither, very expensive
+ //
+ // NOTES
+ // -----------------------------------------------------------------------
+ // 12 = slightly faster then FXAA 3.9 and higher edge quality (default)
+ // 13 = about same speed as FXAA 3.9 and better than 12
+ // 23 = closest to FXAA 3.9 visually and performance wise
+ // _ = the lowest digit is directly related to performance
+ // _ = the highest digit is directly related to style
+ //
+ #define FXAA_QUALITY__PRESET 12
+#endif
+
+/*============================================================================
+
+ FXAA QUALITY - PRESETS
+
+============================================================================*/
+
+/*============================================================================
+ FXAA QUALITY - MEDIUM DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 10)
+ #define FXAA_QUALITY__PS 3
+ #define FXAA_QUALITY__P0 1.5
+ #define FXAA_QUALITY__P1 3.0
+ #define FXAA_QUALITY__P2 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 11)
+ #define FXAA_QUALITY__PS 4
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 3.0
+ #define FXAA_QUALITY__P3 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 12)
+ #define FXAA_QUALITY__PS 5
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 4.0
+ #define FXAA_QUALITY__P4 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 13)
+ #define FXAA_QUALITY__PS 6
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 4.0
+ #define FXAA_QUALITY__P5 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 14)
+ #define FXAA_QUALITY__PS 7
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 4.0
+ #define FXAA_QUALITY__P6 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 15)
+ #define FXAA_QUALITY__PS 8
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 4.0
+ #define FXAA_QUALITY__P7 12.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - LOW DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 20)
+ #define FXAA_QUALITY__PS 3
+ #define FXAA_QUALITY__P0 1.5
+ #define FXAA_QUALITY__P1 2.0
+ #define FXAA_QUALITY__P2 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 21)
+ #define FXAA_QUALITY__PS 4
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 22)
+ #define FXAA_QUALITY__PS 5
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 23)
+ #define FXAA_QUALITY__PS 6
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 24)
+ #define FXAA_QUALITY__PS 7
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 3.0
+ #define FXAA_QUALITY__P6 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 25)
+ #define FXAA_QUALITY__PS 8
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 4.0
+ #define FXAA_QUALITY__P7 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 26)
+ #define FXAA_QUALITY__PS 9
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 4.0
+ #define FXAA_QUALITY__P8 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 27)
+ #define FXAA_QUALITY__PS 10
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 4.0
+ #define FXAA_QUALITY__P9 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 28)
+ #define FXAA_QUALITY__PS 11
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 4.0
+ #define FXAA_QUALITY__P10 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 29)
+ #define FXAA_QUALITY__PS 12
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 2.0
+ #define FXAA_QUALITY__P10 4.0
+ #define FXAA_QUALITY__P11 8.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - EXTREME QUALITY
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 39)
+ #define FXAA_QUALITY__PS 12
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.0
+ #define FXAA_QUALITY__P2 1.0
+ #define FXAA_QUALITY__P3 1.0
+ #define FXAA_QUALITY__P4 1.0
+ #define FXAA_QUALITY__P5 1.5
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 2.0
+ #define FXAA_QUALITY__P10 4.0
+ #define FXAA_QUALITY__P11 8.0
+#endif
+
+#define FxaaSat(x) clamp(x, 0.0, 1.0)
+
+#ifdef FXAA_ALPHA
+
+#define FxaaTexTop(t, p) textureLod(t, p, 0.0).aaaa
+#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o).aaaa
+#define FxaaLuma(rgba) rgba.a
+
+#else
+
+#define FxaaTexTop(t, p) textureLod(t, p, 0.0)
+#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
+
+/* (#B1#) */
+float FxaaLuma(vec4 rgba) {
+ // note: sqrt because the sampled colors are in a linear colorspace!
+ // this approximates a perceptual conversion, which is good enough for the
+ // algorithm
+ return sqrt(dot(rgba.rgb, vec3(0.2126, 0.7152, 0.0722)));
+}
+
+#endif
+
+/*============================================================================
+
+ FXAA3 QUALITY - PC
+
+============================================================================*/
+/*--------------------------------------------------------------------------*/
+vec4 FxaaPixelShader(
+ //
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy} = center of pixel
+ vec2 pos,
+ //
+ // Input color texture.
+ // {rgb_} = color in linear or perceptual color space
+ sampler2D tex,
+ //
+ // Only used on FXAA Quality.
+ // This must be from a constant/uniform.
+ // {x_} = 1.0/screenWidthInPixels
+ // {_y} = 1.0/screenHeightInPixels
+ vec2 fxaaQualityRcpFrame,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__SUBPIX define.
+ // It is here now to allow easier tuning.
+ // Choose the amount of sub-pixel aliasing removal.
+ // This can effect sharpness.
+ // 1.00 - upper limit (softer)
+ // 0.75 - default amount of filtering
+ // 0.50 - lower limit (sharper, less sub-pixel aliasing removal)
+ // 0.25 - almost off
+ // 0.00 - completely off
+ float fxaaQualitySubpix,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define.
+ // It is here now to allow easier tuning.
+ // The minimum amount of local contrast required to apply algorithm.
+ // 0.333 - too little (faster)
+ // 0.250 - low quality
+ // 0.166 - default
+ // 0.125 - high quality
+ // 0.063 - overkill (slower)
+ float fxaaQualityEdgeThreshold,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define.
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // 0.0833 - upper limit (default, the start of visible unfiltered edges)
+ // 0.0625 - high quality (faster)
+ // 0.0312 - visible limit (slower)
+ float fxaaQualityEdgeThresholdMin
+) {
+/*--------------------------------------------------------------------------*/
+ vec2 posM;
+ posM.x = pos.x;
+ posM.y = pos.y;
+ vec4 rgbyM = FxaaTexTop(tex, posM);
+ float lumaM = FxaaLuma(rgbyM); // (#B4#)
+ float lumaS = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 0, 1), fxaaQualityRcpFrame.xy));
+ float lumaE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1, 0), fxaaQualityRcpFrame.xy));
+ float lumaN = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 0,-1), fxaaQualityRcpFrame.xy));
+ float lumaW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 0), fxaaQualityRcpFrame.xy));
+/*--------------------------------------------------------------------------*/
+ float maxSM = max(lumaS, lumaM);
+ float minSM = min(lumaS, lumaM);
+ float maxESM = max(lumaE, maxSM);
+ float minESM = min(lumaE, minSM);
+ float maxWN = max(lumaN, lumaW);
+ float minWN = min(lumaN, lumaW);
+ float rangeMax = max(maxWN, maxESM);
+ float rangeMin = min(minWN, minESM);
+ float rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
+ float range = rangeMax - rangeMin;
+ float rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
+ bool earlyExit = range < rangeMaxClamped;
+/*--------------------------------------------------------------------------*/
+ if(earlyExit) {
+ return rgbyM;
+ }
+/*--------------------------------------------------------------------------*/
+ float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1,-1), fxaaQualityRcpFrame.xy));
+ float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1, 1), fxaaQualityRcpFrame.xy));
+ float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1,-1), fxaaQualityRcpFrame.xy));
+ float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 1), fxaaQualityRcpFrame.xy));
+/*--------------------------------------------------------------------------*/
+ float lumaNS = lumaN + lumaS;
+ float lumaWE = lumaW + lumaE;
+ float subpixRcpRange = 1.0/range;
+ float subpixNSWE = lumaNS + lumaWE;
+ float edgeHorz1 = (-2.0 * lumaM) + lumaNS;
+ float edgeVert1 = (-2.0 * lumaM) + lumaWE;
+/*--------------------------------------------------------------------------*/
+ float lumaNESE = lumaNE + lumaSE;
+ float lumaNWNE = lumaNW + lumaNE;
+ float edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
+ float edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
+/*--------------------------------------------------------------------------*/
+ float lumaNWSW = lumaNW + lumaSW;
+ float lumaSWSE = lumaSW + lumaSE;
+ float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
+ float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
+ float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
+ float edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
+ float edgeHorz = abs(edgeHorz3) + edgeHorz4;
+ float edgeVert = abs(edgeVert3) + edgeVert4;
+/*--------------------------------------------------------------------------*/
+ float subpixNWSWNESE = lumaNWSW + lumaNESE;
+ float lengthSign = fxaaQualityRcpFrame.x;
+ bool horzSpan = edgeHorz >= edgeVert;
+ float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
+/*--------------------------------------------------------------------------*/
+ if(!horzSpan) lumaN = lumaW;
+ if(!horzSpan) lumaS = lumaE;
+ if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
+ float subpixB = (subpixA * (1.0/12.0)) - lumaM;
+/*--------------------------------------------------------------------------*/
+ float gradientN = lumaN - lumaM;
+ float gradientS = lumaS - lumaM;
+ float lumaNN = lumaN + lumaM;
+ float lumaSS = lumaS + lumaM;
+ bool pairN = abs(gradientN) >= abs(gradientS);
+ float gradient = max(abs(gradientN), abs(gradientS));
+ if(pairN) lengthSign = -lengthSign;
+ float subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);
+/*--------------------------------------------------------------------------*/
+ vec2 posB;
+ posB.x = posM.x;
+ posB.y = posM.y;
+ vec2 offNP;
+ offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
+ offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
+ if(!horzSpan) posB.x += lengthSign * 0.5;
+ if( horzSpan) posB.y += lengthSign * 0.5;
+/*--------------------------------------------------------------------------*/
+ vec2 posN;
+ posN.x = posB.x - offNP.x * FXAA_QUALITY__P0;
+ posN.y = posB.y - offNP.y * FXAA_QUALITY__P0;
+ vec2 posP;
+ posP.x = posB.x + offNP.x * FXAA_QUALITY__P0;
+ posP.y = posB.y + offNP.y * FXAA_QUALITY__P0;
+ float subpixD = ((-2.0)*subpixC) + 3.0;
+ float lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
+ float subpixE = subpixC * subpixC;
+ float lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
+/*--------------------------------------------------------------------------*/
+ if(!pairN) lumaNN = lumaSS;
+ float gradientScaled = gradient * 1.0/4.0;
+ float lumaMM = lumaM - lumaNN * 0.5;
+ float subpixF = subpixD * subpixE;
+ bool lumaMLTZero = lumaMM < 0.0;
+/*--------------------------------------------------------------------------*/
+ lumaEndN -= lumaNN * 0.5;
+ lumaEndP -= lumaNN * 0.5;
+ bool doneN = abs(lumaEndN) >= gradientScaled;
+ bool doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1;
+ bool doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1;
+/*--------------------------------------------------------------------------*/
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 3)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 4)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 5)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 6)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 7)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 8)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 9)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 10)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 11)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 12)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12;
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+/*--------------------------------------------------------------------------*/
+ float dstN = posM.x - posN.x;
+ float dstP = posP.x - posM.x;
+ if(!horzSpan) dstN = posM.y - posN.y;
+ if(!horzSpan) dstP = posP.y - posM.y;
+/*--------------------------------------------------------------------------*/
+ bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
+ float spanLength = (dstP + dstN);
+ bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
+ float spanLengthRcp = 1.0/spanLength;
+/*--------------------------------------------------------------------------*/
+ bool directionN = dstN < dstP;
+ float dst = min(dstN, dstP);
+ bool goodSpan = directionN ? goodSpanN : goodSpanP;
+ float subpixG = subpixF * subpixF;
+ float pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
+ float subpixH = subpixG * fxaaQualitySubpix;
+/*--------------------------------------------------------------------------*/
+ float pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
+ float pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
+ if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
+ if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
+ return vec4(FxaaTexTop(tex, posM).xyz, lumaM);
+}
+/*==========================================================================*/
+
diff --git a/source/blender/draw/modes/shaders/common_globals_lib.glsl b/source/blender/draw/modes/shaders/common_globals_lib.glsl
new file mode 100644
index 00000000000..dc36d252926
--- /dev/null
+++ b/source/blender/draw/modes/shaders/common_globals_lib.glsl
@@ -0,0 +1,58 @@
+
+/* keep in sync with GlobalsUboStorage */
+layout(std140) uniform globalsBlock {
+ vec4 colorWire;
+ vec4 colorWireEdit;
+ vec4 colorActive;
+ vec4 colorSelect;
+ vec4 colorTransform;
+ vec4 colorGroupActive;
+ vec4 colorGroupSelect;
+ vec4 colorGroup;
+ vec4 colorLibrarySelect;
+ vec4 colorLibrary;
+ vec4 colorLamp;
+ vec4 colorSpeaker;
+ vec4 colorCamera;
+ vec4 colorEmpty;
+ vec4 colorVertex;
+ vec4 colorVertexSelect;
+ vec4 colorEditMeshActive;
+ vec4 colorEdgeSelect;
+ vec4 colorEdgeSeam;
+ vec4 colorEdgeSharp;
+ vec4 colorEdgeCrease;
+ vec4 colorEdgeBWeight;
+ vec4 colorEdgeFaceSelect;
+ vec4 colorFace;
+ vec4 colorFaceSelect;
+ vec4 colorNormal;
+ vec4 colorVNormal;
+ vec4 colorLNormal;
+ vec4 colorFaceDot;
+
+ vec4 colorDeselect;
+ vec4 colorOutline;
+ vec4 colorLampNoAlpha;
+
+ vec4 colorBackground;
+
+ vec4 colorGrid;
+ vec4 colorGridEmphasise;
+ vec4 colorGridAxisX;
+ vec4 colorGridAxisY;
+ vec4 colorGridAxisZ;
+
+ float sizeLampCenter;
+ float sizeLampCircle;
+ float sizeLampCircleShadow;
+ float sizeVertex;
+ float sizeEdge;
+ float sizeEdgeFix;
+ float sizeFaceDot;
+
+ float gridDistance;
+ float gridResolution;
+ float gridSubdivisions;
+ float gridScale;
+};
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_frag.glsl
new file mode 100644
index 00000000000..e78462b6915
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_frag.glsl
@@ -0,0 +1,22 @@
+
+flat in int vertFlag;
+
+#define VERTEX_SELECTED (1 << 0)
+#define VERTEX_ACTIVE (1 << 1)
+
+out vec4 FragColor;
+
+void main()
+{
+ /* TODO: vertex size */
+
+ if ((vertFlag & VERTEX_SELECTED) != 0) {
+ FragColor = colorVertexSelect;
+ }
+ else if ((vertFlag & VERTEX_ACTIVE) != 0) {
+ FragColor = colorEditMeshActive;
+ }
+ else {
+ FragColor = colorVertex;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl
new file mode 100644
index 00000000000..9150ef8cd63
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl
@@ -0,0 +1,39 @@
+
+/* Draw Curve Vertices */
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec3 pos;
+in int data;
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out int vertFlag;
+flat out int clipCase;
+
+/* See fragment shader */
+noperspective out vec4 eData1;
+flat out vec4 eData2;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+void main()
+{
+ clipCase = 0;
+
+ vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ /* only vertex position 0 is used */
+ eData1 = eData2 = vec4(1e10);
+ eData2.zw = proj(pPos);
+
+ vertFlag = data;
+
+ gl_Position = pPos;
+ gl_PointSize = sizeVertex;
+}
diff --git a/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl
new file mode 100644
index 00000000000..e78462b6915
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl
@@ -0,0 +1,22 @@
+
+flat in int vertFlag;
+
+#define VERTEX_SELECTED (1 << 0)
+#define VERTEX_ACTIVE (1 << 1)
+
+out vec4 FragColor;
+
+void main()
+{
+ /* TODO: vertex size */
+
+ if ((vertFlag & VERTEX_SELECTED) != 0) {
+ FragColor = colorVertexSelect;
+ }
+ else if ((vertFlag & VERTEX_ACTIVE) != 0) {
+ FragColor = colorEditMeshActive;
+ }
+ else {
+ FragColor = colorVertex;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl
new file mode 100644
index 00000000000..0cbc66a2b1f
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl
@@ -0,0 +1,39 @@
+
+/* Draw Lattice Vertices */
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec3 pos;
+in int data;
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out int vertFlag;
+flat out int clipCase;
+
+/* See fragment shader */
+noperspective out vec4 eData1;
+flat out vec4 eData2;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+void main()
+{
+ clipCase = 0;
+
+ vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ /* only vertex position 0 is used */
+ eData1 = eData2 = vec4(1e10);
+ eData2.zw = proj(pPos);
+
+ vertFlag = data;
+
+ gl_PointSize = sizeVertex;
+ gl_Position = pPos;
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl
new file mode 100644
index 00000000000..07b36079884
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl
@@ -0,0 +1,19 @@
+
+flat in int isSelected;
+#ifdef VERTEX_FACING
+flat in float facing;
+#endif
+
+out vec4 FragColor;
+
+void main()
+{
+ if (isSelected != 0)
+ FragColor = colorFaceDot;
+ else
+ FragColor = colorWireEdit;
+
+#ifdef VERTEX_FACING
+ FragColor.a *= 1.0 - abs(facing) * 0.4;
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_vert.glsl
new file mode 100644
index 00000000000..fa3934c4b77
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_vert.glsl
@@ -0,0 +1,31 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec4 norAndFlag;
+
+flat out int isSelected;
+
+#ifdef VERTEX_FACING
+uniform mat4 ProjectionMatrix;
+uniform mat4 ModelViewMatrix;
+uniform mat3 NormalMatrix;
+
+flat out float facing;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ /* Bias Facedot Z position in clipspace. */
+ gl_Position.z -= 0.0002;
+ gl_PointSize = sizeFaceDot;
+ isSelected = int(norAndFlag.w);
+#ifdef VERTEX_FACING
+ vec3 view_normal = normalize(NormalMatrix * norAndFlag.xyz);
+ vec3 view_vec = (ProjectionMatrix[3][3] == 0.0)
+ ? normalize((ModelViewMatrix * vec4(pos, 1.0)).xyz)
+ : vec3(0.0, 0.0, 1.0);
+ facing = dot(view_vec, view_normal);
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl
new file mode 100644
index 00000000000..049333c8e4f
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl
@@ -0,0 +1,29 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+flat in vec4 faceColor;
+flat in int faceActive;
+
+out vec4 FragColor;
+
+const mat4 stipple_matrix = mat4(
+ vec4(1.0, 0.0, 0.0, 0.0),
+ vec4(0.0, 0.0, 0.0, 0.0),
+ vec4(0.0, 0.0, 1.0, 0.0),
+ vec4(0.0, 0.0, 0.0, 0.0)
+);
+
+void main()
+{
+ FragColor = faceColor;
+
+ if (faceActive == 1) {
+ int x = int(gl_FragCoord.x) & 0x3; /* mod 4 */
+ int y = int(gl_FragCoord.y) & 0x3; /* mod 4 */
+ FragColor *= stipple_matrix[x][y];
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl
new file mode 100644
index 00000000000..3b9aa77306f
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in ivec4 data;
+
+flat out vec4 faceColor;
+flat out int faceActive;
+
+#define FACE_ACTIVE (1 << 2)
+#define FACE_SELECTED (1 << 3)
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ if ((data.x & FACE_ACTIVE) != 0) {
+ faceColor = colorEditMeshActive;
+ faceActive = 1;
+ }
+ else if ((data.x & FACE_SELECTED) != 0) {
+ faceColor = colorFaceSelect;
+ faceActive = 0;
+ }
+ else {
+ faceColor = colorFace;
+ faceActive = 0;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl
new file mode 100644
index 00000000000..ed7421c1b1d
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl
@@ -0,0 +1,208 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+uniform float faceAlphaMod;
+
+flat in vec3 edgesCrease;
+flat in vec3 edgesBweight;
+flat in ivec3 flag;
+flat in vec4 faceColor;
+flat in int clipCase;
+#ifdef VERTEX_SELECTION
+in vec3 vertexColor;
+#endif
+#ifdef VERTEX_FACING
+in float facing;
+#endif
+
+/* We use a vec4[2] interface to pass edge data
+ * (without fragmenting memory accesses)
+ *
+ * There are 2 cases :
+ *
+ * - Simple case : geometry shader return edge distances
+ * in the first 2 components of the first vec4.
+ * This needs noperspective interpolation.
+ * The rest is filled with vertex screen positions.
+ * eData1.zw actually contain v2
+ * eData2.xy actually contain v1
+ * eData2.zw actually contain v0
+ *
+ * - Hard case : two 2d edge corner are described by each
+ * vec4 as origin and direction. This is constant over
+ * the triangle and use to detect the correct case. */
+
+noperspective in vec4 eData1;
+flat in vec4 eData2;
+
+out vec4 FragColor;
+
+#define EDGE_EXISTS (1 << 0)
+#define EDGE_ACTIVE (1 << 1)
+#define EDGE_SELECTED (1 << 2)
+#define EDGE_SEAM (1 << 3)
+#define EDGE_SHARP (1 << 4)
+/* Vertex flag is shifted and combined with the edge flag */
+#define VERTEX_ACTIVE (1 << (0 + 8))
+#define VERTEX_SELECTED (1 << (1 + 8))
+#define FACE_ACTIVE (1 << (2 + 8))
+
+/* Style Parameters in pixel */
+
+/* Array to retrieve vert/edge indices */
+const ivec3 clipEdgeIdx[6] = ivec3[6](
+ ivec3(1, 0, 2),
+ ivec3(2, 0, 1),
+ ivec3(2, 1, 0),
+ ivec3(2, 1, 0),
+ ivec3(2, 0, 1),
+ ivec3(1, 0, 2)
+);
+
+const ivec3 clipPointIdx[6] = ivec3[6](
+ ivec3(0, 1, 2),
+ ivec3(0, 2, 1),
+ ivec3(0, 2, 1),
+ ivec3(1, 2, 0),
+ ivec3(1, 2, 0),
+ ivec3(2, 1, 0)
+);
+
+const mat4 stipple_matrix = mat4(
+ vec4(1.0, 0.0, 0.0, 0.0),
+ vec4(0.0, 0.0, 0.0, 0.0),
+ vec4(0.0, 0.0, 1.0, 0.0),
+ vec4(0.0, 0.0, 0.0, 0.0)
+);
+
+void colorDist(vec4 color, float dist)
+{
+ FragColor = (dist < 0) ? color : FragColor;
+}
+
+float distToEdge(vec2 o, vec2 dir)
+{
+ vec2 af = gl_FragCoord.xy - o;
+ float daf = dot(dir, af);
+ return sqrt(abs(dot(af, af) - daf * daf));
+}
+
+#ifdef ANTI_ALIASING
+void colorDistEdge(vec4 color, float dist)
+{
+ FragColor = mix(color, FragColor, clamp(dist, 0.0, 1.0));
+}
+#else
+#define colorDistEdge colorDist
+#endif
+
+void main()
+{
+ vec3 e, p;
+
+ /* Step 1 : Computing Distances */
+
+ if (clipCase == 0) {
+ e.xy = eData1.xy;
+
+ /* computing missing distance */
+ vec2 dir = normalize(eData2.zw - eData2.xy);
+ e.z = distToEdge(eData2.zw, dir);
+
+ p.x = distance(eData2.zw, gl_FragCoord.xy);
+ p.y = distance(eData2.xy, gl_FragCoord.xy);
+ p.z = distance(eData1.zw, gl_FragCoord.xy);
+ }
+ else {
+ ivec3 eidxs = clipEdgeIdx[clipCase - 1];
+ ivec3 pidxs = clipPointIdx[clipCase - 1];
+
+ e[eidxs.x] = distToEdge(eData1.xy, eData1.zw);
+ e[eidxs.y] = distToEdge(eData2.xy, eData2.zw);
+
+ /* Three edges visible cases */
+ if (clipCase == 1 || clipCase == 2 || clipCase == 4) {
+ e[eidxs.z] = distToEdge(eData1.xy, normalize(eData2.xy - eData1.xy));
+ p[pidxs.y] = distance(eData2.xy, gl_FragCoord.xy);
+ }
+ else {
+ e[eidxs.z] = 1e10; /* off screen */
+ p[pidxs.y] = 1e10; /* off screen */
+ }
+
+ p[pidxs.x] = distance(eData1.xy, gl_FragCoord.xy);
+ p[pidxs.z] = 1e10; /* off screen */
+ }
+
+ /* Step 2 : coloring (order dependant) */
+
+ /* First */
+ FragColor = faceColor;
+
+ if ((flag[0] & FACE_ACTIVE) != 0) {
+ int x = int(gl_FragCoord.x) & 0x3; /* mod 4 */
+ int y = int(gl_FragCoord.y) & 0x3; /* mod 4 */
+ FragColor *= stipple_matrix[x][y];
+ }
+ else {
+ FragColor.a *= faceAlphaMod;
+ }
+
+ /* Edges */
+ for (int v = 0; v < 3; ++v) {
+ if ((flag[v] & EDGE_EXISTS) != 0) {
+ /* Outer large edge */
+ float largeEdge = e[v] - sizeEdge * 3.0;
+
+ vec4 large_edge_color = vec4(0.0);
+ large_edge_color = ((flag[v] & EDGE_SHARP) != 0) ? colorEdgeSharp : large_edge_color;
+ large_edge_color = (edgesCrease[v] > 0.0) ? vec4(colorEdgeCrease.rgb, edgesCrease[v]) : large_edge_color;
+ large_edge_color = (edgesBweight[v] > 0.0) ? vec4(colorEdgeBWeight.rgb, edgesBweight[v]) : large_edge_color;
+ large_edge_color = ((flag[v] & EDGE_SEAM) != 0) ? colorEdgeSeam : large_edge_color;
+
+ if (large_edge_color.a != 0.0) {
+ colorDistEdge(large_edge_color, largeEdge);
+ }
+
+ /* Inner thin edge */
+ float innerEdge = e[v] - sizeEdge;
+#ifdef ANTI_ALIASING
+ innerEdge += 0.125;
+#endif
+
+#ifdef VERTEX_SELECTION
+ colorDistEdge(vec4(vertexColor, 1.0), innerEdge);
+#else
+ vec4 inner_edge_color = colorWireEdit;
+ inner_edge_color = ((flag[v] & EDGE_SELECTED) != 0) ? colorEdgeSelect : inner_edge_color;
+ inner_edge_color = ((flag[v] & EDGE_ACTIVE) != 0) ? vec4(colorEditMeshActive.xyz, 1.0) : inner_edge_color;
+
+ colorDistEdge(inner_edge_color, innerEdge);
+#endif
+ }
+ }
+
+ /* Points */
+#ifdef VERTEX_SELECTION
+ for (int v = 0; v < 3; ++v) {
+ float size = p[v] - sizeVertex;
+
+ vec4 point_color = colorVertex;
+ point_color = ((flag[v] & VERTEX_SELECTED) != 0) ? colorVertexSelect : point_color;
+ point_color = ((flag[v] & VERTEX_ACTIVE) != 0) ? vec4(colorEditMeshActive.xyz, 1.0) : point_color;
+
+ colorDist(point_color, size);
+ }
+#endif
+
+#ifdef VERTEX_FACING
+ FragColor.a *= 1.0 - abs(facing) * 0.4;
+#endif
+
+ /* don't write depth if not opaque */
+ if (FragColor.a == 0.0) discard;
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl
new file mode 100644
index 00000000000..7d71e1540d5
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl
@@ -0,0 +1,153 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+layout(lines) in;
+layout(triangle_strip, max_vertices=6) out;
+
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec4 vPos[];
+in vec4 pPos[];
+in ivec4 vData[];
+#ifdef VERTEX_FACING
+in float vFacing[];
+#endif
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out vec3 edgesCrease;
+flat out vec3 edgesBweight;
+flat out ivec3 flag;
+flat out vec4 faceColor;
+flat out int clipCase;
+#ifdef VERTEX_SELECTION
+out vec3 vertexColor;
+#endif
+#ifdef VERTEX_FACING
+out float facing;
+#endif
+
+/* See fragment shader */
+noperspective out vec4 eData1;
+flat out vec4 eData2;
+
+#define VERTEX_ACTIVE (1 << 0)
+#define VERTEX_SELECTED (1 << 1)
+
+#define FACE_ACTIVE (1 << 2)
+#define FACE_SELECTED (1 << 3)
+
+/* Table 1. Triangle Projection Cases */
+const ivec4 clipPointsIdx[6] = ivec4[6](
+ ivec4(0, 1, 2, 2),
+ ivec4(0, 2, 1, 1),
+ ivec4(0, 0, 1, 2),
+ ivec4(1, 2, 0, 0),
+ ivec4(1, 1, 0, 2),
+ ivec4(2, 2, 0, 1)
+);
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+float dist(vec2 pos[3], vec2 vpos, int v)
+{
+ /* endpoints of opposite edge */
+ vec2 e1 = pos[(v + 1) % 3];
+ vec2 e2 = pos[(v + 2) % 3];
+ /* Edge normalized vector */
+ vec2 dir = normalize(e2 - e1);
+ /* perpendicular to dir */
+ vec2 orthogonal = vec2(-dir.y, dir.x);
+
+ return abs(dot(vpos - e1, orthogonal));
+}
+
+vec3 getVertexColor(int v)
+{
+ if ((vData[v].x & (VERTEX_ACTIVE | VERTEX_SELECTED)) != 0)
+ return colorEdgeSelect.rgb;
+ else
+ return colorWireEdit.rgb;
+}
+
+void doVertex(int v, vec4 pos)
+{
+#ifdef VERTEX_SELECTION
+ vertexColor = getVertexColor(v);
+#endif
+
+#ifdef VERTEX_FACING
+ facing = vFacing[v];
+#endif
+
+ gl_Position = pos;
+
+ EmitVertex();
+}
+
+void main()
+{
+ clipCase = 0;
+
+ /* Face */
+ faceColor = vec4(0.0);
+
+ /* Proj Vertex */
+ vec2 pos[2] = vec2[2](proj(pPos[0]), proj(pPos[1]));
+
+ /* little optimization use a vec4 to vectorize
+ * following operations */
+ vec4 dirs1, dirs2;
+
+ /* Edge normalized vector */
+ dirs1.xy = normalize(pos[1] - pos[0]);
+
+ /* perpendicular to dir */
+ dirs1.zw = vec2(-dirs1.y, dirs1.x);
+
+ /* Make it view independent */
+ dirs1 *= sizeEdgeFix / viewportSize.xyxy;
+
+ dirs2 = dirs1;
+
+ /* Perspective */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ /* vPos[i].z is negative and we don't want
+ * our fixvec to be flipped */
+ dirs1 *= -vPos[0].z;
+ dirs2 *= -vPos[1].z;
+ }
+
+ /* Edge / Vert data */
+ eData1 = vec4(1e10);
+ eData2.zw = pos[0];
+ eData2.xy = pos[1];
+ flag[0] = (vData[0].x << 8);
+ flag[1] = (vData[1].x << 8);
+ flag[2] = 0;
+
+ doVertex(0, pPos[0] + vec4(-dirs1.xy, 0.0, 0.0));
+ doVertex(0, pPos[0] + vec4( dirs1.zw, 0.0, 0.0));
+ doVertex(0, pPos[0] + vec4(-dirs1.zw, 0.0, 0.0));
+
+ flag[2] = vData[0].y | (vData[0].x << 8);
+ edgesCrease[2] = vData[0].z / 255.0;
+ edgesBweight[2] = vData[0].w / 255.0;
+
+ doVertex(1, pPos[1] + vec4( dirs2.zw, 0.0, 0.0));
+ doVertex(1, pPos[1] + vec4(-dirs2.zw, 0.0, 0.0));
+
+ flag[2] = 0;
+ doVertex(1, pPos[1] + vec4( dirs2.xy, 0.0, 0.0));
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl
new file mode 100644
index 00000000000..f83402e3869
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl
@@ -0,0 +1,293 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+layout(triangles) in;
+
+#ifdef EDGE_FIX
+/* To fix the edge artifacts, we render
+ * an outline strip around the screenspace
+ * triangle. Order is important.
+ * TODO diagram
+ */
+
+#ifdef VERTEX_SELECTION
+layout(triangle_strip, max_vertices=23) out;
+#else
+layout(triangle_strip, max_vertices=17) out;
+#endif
+#else
+layout(triangle_strip, max_vertices=3) out;
+#endif
+
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec4 vPos[];
+in vec4 pPos[];
+in ivec4 vData[];
+#ifdef VERTEX_FACING
+in float vFacing[];
+#endif
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out vec3 edgesCrease;
+flat out vec3 edgesBweight;
+flat out ivec3 flag;
+flat out vec4 faceColor;
+flat out int clipCase;
+#ifdef VERTEX_SELECTION
+out vec3 vertexColor;
+#endif
+#ifdef VERTEX_FACING
+out float facing;
+#endif
+
+/* See fragment shader */
+noperspective out vec4 eData1;
+flat out vec4 eData2;
+
+
+#define VERTEX_ACTIVE (1 << 0)
+#define VERTEX_SELECTED (1 << 1)
+
+#define FACE_ACTIVE (1 << 2)
+#define FACE_SELECTED (1 << 3)
+
+/* Table 1. Triangle Projection Cases */
+const ivec4 clipPointsIdx[6] = ivec4[6](
+ ivec4(0, 1, 2, 2),
+ ivec4(0, 2, 1, 1),
+ ivec4(0, 0, 1, 2),
+ ivec4(1, 2, 0, 0),
+ ivec4(1, 1, 0, 2),
+ ivec4(2, 2, 0, 1)
+);
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+float dist(vec2 pos[3], vec2 vpos, int v)
+{
+ /* endpoints of opposite edge */
+ vec2 e1 = pos[(v + 1) % 3];
+ vec2 e2 = pos[(v + 2) % 3];
+ /* Edge normalized vector */
+ vec2 dir = normalize(e2 - e1);
+ /* perpendicular to dir */
+ vec2 orthogonal = vec2(-dir.y, dir.x);
+
+ return abs(dot(vpos - e1, orthogonal));
+}
+
+vec3 getVertexColor(int v)
+{
+ if ((vData[v].x & (VERTEX_ACTIVE | VERTEX_SELECTED)) != 0)
+ return colorEdgeSelect.rgb;
+ else
+ return colorWireEdit.rgb;
+}
+
+vec4 getClipData(vec2 pos[3], ivec2 vidx)
+{
+ vec2 A = pos[vidx.x];
+ vec2 Adir = normalize(A - pos[vidx.y]);
+
+ return vec4(A, Adir);
+}
+
+void doVertex(int v, vec4 pos)
+{
+#ifdef VERTEX_SELECTION
+ vertexColor = getVertexColor(v);
+#endif
+
+#ifdef VERTEX_FACING
+ facing = vFacing[v];
+#endif
+
+ gl_Position = pos;
+
+ EmitVertex();
+}
+
+#ifdef ANTI_ALIASING
+#define Z_OFFSET 0.008
+#else
+#define Z_OFFSET 0.0
+#endif
+
+void main()
+{
+ /* First we detect which case we are in */
+ clipCase = 0;
+
+ /* if perspective */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ /* See Table 1. Triangle Projection Cases */
+ clipCase += int(pPos[0].z / pPos[0].w < -1 || vPos[0].z > 0.0) * 4;
+ clipCase += int(pPos[1].z / pPos[1].w < -1 || vPos[1].z > 0.0) * 2;
+ clipCase += int(pPos[2].z / pPos[2].w < -1 || vPos[2].z > 0.0) * 1;
+ }
+
+ /* If triangle is behind nearplane, early out */
+ if (clipCase == 7)
+ return;
+
+ /* Edge */
+ ivec3 eflag; vec3 ecrease, ebweight;
+ for (int v = 0; v < 3; ++v) {
+ flag[v] = eflag[v] = vData[v].y | (vData[v].x << 8);
+ edgesCrease[v] = ecrease[v] = vData[v].z / 255.0;
+ edgesBweight[v] = ebweight[v] = vData[v].w / 255.0;
+ }
+
+ /* Face */
+ if ((vData[0].x & FACE_ACTIVE) != 0)
+ faceColor = colorEditMeshActive;
+ else if ((vData[0].x & FACE_SELECTED) != 0)
+ faceColor = colorFaceSelect;
+ else
+ faceColor = colorFace;
+
+ /* Vertex */
+ vec2 pos[3] = vec2[3](proj(pPos[0]), proj(pPos[1]), proj(pPos[2]));
+
+ /* Simple case : compute edge distances in geometry shader */
+ if (clipCase == 0) {
+
+ /* Packing screen positions and 2 distances */
+ eData1 = vec4(0.0, 0.0, pos[2]);
+ eData2 = vec4(pos[1], pos[0]);
+
+ /* Only pass the first 2 distances */
+ for (int v = 0; v < 2; ++v) {
+ eData1[v] = dist(pos, pos[v], v);
+ doVertex(v, pPos[v]);
+ eData1[v] = 0.0;
+ }
+
+ /* and the last vertex */
+ doVertex(2, pPos[2]);
+
+#ifdef EDGE_FIX
+ vec2 fixvec[6];
+ vec2 fixvecaf[6];
+ vec2 cornervec[3];
+
+ /* This fix the case when 2 vertices are perfectly aligned
+ * and corner vectors have nowhere to go.
+ * ie: length(cornervec[i]) == 0 */
+ const float epsilon = 1e-2; /* in pixel so not that much */
+ const vec2 bias[3] = vec2[3](
+ vec2( epsilon, epsilon),
+ vec2(-epsilon, epsilon),
+ vec2( 0.0, -epsilon)
+ );
+
+ for (int i = 0; i < 3; ++i) {
+ int i1 = (i + 1) % 3;
+ int i2 = (i + 2) % 3;
+
+ vec2 v1 = pos[i] + bias[i];
+ vec2 v2 = pos[i1] + bias[i1];
+ vec2 v3 = pos[i2] + bias[i2];
+
+ /* Edge normalized vector */
+ vec2 dir = normalize(v2 - v1);
+ vec2 dir2 = normalize(v3 - v1);
+
+ cornervec[i] = -normalize(dir + dir2);
+
+ /* perpendicular to dir */
+ vec2 perp = vec2(-dir.y, dir.x);
+
+ /* Backface case */
+ if (dot(perp, dir2) > 0) {
+ perp = -perp;
+ }
+
+ /* Make it view independent */
+ perp *= sizeEdgeFix / viewportSize;
+ cornervec[i] *= sizeEdgeFix / viewportSize;
+ fixvec[i] = fixvecaf[i] = perp;
+
+ /* Perspective */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ /* vPos[i].z is negative and we don't want
+ * our fixvec to be flipped */
+ fixvec[i] *= -vPos[i].z;
+ fixvecaf[i] *= -vPos[i1].z;
+ cornervec[i] *= -vPos[i].z;
+ }
+ }
+
+ /* to not let face color bleed */
+ faceColor.a = 0.0;
+
+ /* we don't want other edges : make them far */
+ eData1 = vec4(1e10);
+
+ /* Start with the same last vertex to create a
+ * degenerate triangle in order to "create"
+ * a new triangle strip */
+ for (int i = 2; i < 5; ++i) {
+ int vbe = (i - 1) % 3;
+ int vaf = (i + 1) % 3;
+ int v = i % 3;
+
+ /* Position of the "hidden" third vertex */
+ eData1.zw = pos[vbe];
+
+ doVertex(v, pPos[v]);
+ doVertex(v, pPos[v] + vec4(fixvec[v], Z_OFFSET, 0.0));
+
+ /* Now one triangle only shade one edge
+ * so we use the edge distance calculated
+ * in the fragment shader, the third edge;
+ * we do this because we need flat interp to
+ * draw a continuous triangle strip */
+ eData2.xy = pos[vaf];
+ eData2.zw = pos[v];
+ flag[0] = (vData[v].x << 8);
+ flag[1] = (vData[vaf].x << 8);
+ flag[2] = eflag[vbe];
+ edgesCrease[2] = ecrease[vbe];
+ edgesBweight[2] = ebweight[vbe];
+
+ doVertex(vaf, pPos[vaf]);
+ doVertex(vaf, pPos[vaf] + vec4(fixvecaf[v], Z_OFFSET, 0.0));
+
+ /* corner vertices should not draw edges but draw point only */
+ flag[2] = (vData[vbe].x << 8);
+#ifdef VERTEX_SELECTION
+ doVertex(vaf, pPos[vaf]);
+ doVertex(vaf, pPos[vaf] + vec4(cornervec[vaf], Z_OFFSET, 0.0));
+#endif
+ }
+
+ /* finish the loop strip */
+ doVertex(2, pPos[2]);
+ doVertex(2, pPos[2] + vec4(fixvec[2], Z_OFFSET, 0.0));
+#endif
+ }
+ /* Harder case : compute visible edges vectors */
+ else {
+ ivec4 vindices = clipPointsIdx[clipCase - 1];
+
+ eData1 = getClipData(pos, vindices.xz);
+ eData2 = getClipData(pos, vindices.yw);
+
+ for (int v = 0; v < 3; ++v)
+ doVertex(v, pPos[v]);
+ }
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl
new file mode 100644
index 00000000000..0a396a5325f
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl
@@ -0,0 +1,59 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec3 pos;
+in ivec4 data;
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out vec3 edgesCrease;
+flat out vec3 edgesBweight;
+flat out ivec3 flag;
+flat out vec4 faceColor;
+flat out int clipCase;
+#ifdef VERTEX_SELECTION
+out vec3 vertexColor;
+#endif
+
+/* See fragment shader */
+noperspective out vec4 eData1;
+flat out vec4 eData2;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+void main()
+{
+ clipCase = 0;
+ edgesCrease = vec3(0.0);
+ edgesBweight = vec3(0.0);
+
+ vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ /* there is no face */
+ faceColor = vec4(0.0);
+
+#ifdef VERTEX_SELECTION
+ vertexColor = vec3(0.0);
+#endif
+
+ /* only vertex position 0 is used */
+ eData1 = eData2 = vec4(1e10);
+ eData2.zw = proj(pPos);
+
+ flag = ivec3(0);
+ flag[0] = (data.x << 8);
+
+ gl_PointSize = sizeEdgeFix;
+ gl_Position = pPos;
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl
new file mode 100644
index 00000000000..8f94a105332
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl
@@ -0,0 +1,22 @@
+
+out vec4 FragColor;
+
+uniform sampler2D wireColor;
+uniform sampler2D wireDepth;
+uniform sampler2D sceneDepth;
+uniform float alpha;
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+ float wire_depth = texelFetch(wireDepth, uv, 0).r;
+ float scene_depth = texelFetch(sceneDepth, uv, 0).r;
+ vec4 wire_color = texelFetch(wireColor, uv, 0).rgba;
+
+ FragColor = wire_color;
+
+ /* Modulate alpha if occluded */
+ if (wire_depth > scene_depth) {
+ FragColor.a *= alpha;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
new file mode 100644
index 00000000000..8ebfa4376f0
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
@@ -0,0 +1,38 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+uniform mat4 ModelViewMatrix;
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in ivec4 data;
+
+out vec4 vPos;
+out vec4 pPos;
+out ivec4 vData;
+
+#ifdef VERTEX_FACING
+uniform mat4 ProjectionMatrix;
+uniform mat3 NormalMatrix;
+
+in vec3 vnor;
+out float vFacing;
+#endif
+
+void main()
+{
+ vPos = ModelViewMatrix * vec4(pos, 1.0);
+ pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vData = data;
+#ifdef VERTEX_FACING
+ vec3 view_normal = normalize(NormalMatrix * vnor);
+ vec3 view_vec = (ProjectionMatrix[3][3] == 0.0)
+ ? normalize(vPos.xyz)
+ : vec3(0.0, 0.0, 1.0);
+ vFacing = dot(view_vec, view_normal);
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/edit_normals_geom.glsl b/source/blender/draw/modes/shaders/edit_normals_geom.glsl
new file mode 100644
index 00000000000..d17823f2f5a
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_normals_geom.glsl
@@ -0,0 +1,15 @@
+
+layout(points) in;
+layout(line_strip, max_vertices=2) out;
+
+flat in vec4 v1[1];
+flat in vec4 v2[1];
+
+void main()
+{
+ gl_Position = v1[0];
+ EmitVertex();
+ gl_Position = v2[0];
+ EmitVertex();
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/edit_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_vert.glsl
new file mode 100644
index 00000000000..3ce7e618511
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_normals_vert.glsl
@@ -0,0 +1,30 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+uniform mat4 ProjectionMatrix;
+uniform float normalSize;
+
+in vec3 pos;
+
+#ifdef LOOP_NORMALS
+in vec3 lnor;
+#define nor lnor
+
+#elif defined(FACE_NORMALS)
+in vec4 norAndFlag;
+#define nor norAndFlag.xyz
+#else
+
+in vec3 vnor;
+#define nor vnor
+#endif
+
+flat out vec4 v1;
+flat out vec4 v2;
+
+void main()
+{
+ v1 = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 n = normalize(NormalMatrix * nor); /* viewspace */
+ v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0);
+}
diff --git a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
new file mode 100644
index 00000000000..eab107354d1
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
@@ -0,0 +1,21 @@
+
+flat in vec4 finalColor;
+
+#ifndef USE_WIRE
+in vec2 texCoord_interp;
+#endif
+
+out vec4 fragColor;
+
+#ifndef USE_WIRE
+uniform sampler2D image;
+#endif
+
+void main()
+{
+#ifdef USE_WIRE
+ fragColor = finalColor;
+#else
+ fragColor = finalColor * texture(image, texCoord_interp);
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl
new file mode 100644
index 00000000000..c629fdcb7ef
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl
@@ -0,0 +1,38 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec2 aspect;
+
+/* ---- Instanciated Attribs ---- */
+in vec2 texCoord;
+in vec2 pos;
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+
+#ifdef USE_WIRE
+in vec3 color;
+#else
+in vec4 objectColor;
+#endif
+
+in float size;
+in vec2 offset;
+
+flat out vec4 finalColor;
+
+#ifndef USE_WIRE
+out vec2 texCoord_interp;
+#endif
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(
+ (pos[0] + offset[0]) * (size * aspect[0]),
+ (pos[1] + offset[1]) * (size * aspect[1]),
+ 0.0, 1.0);
+#ifdef USE_WIRE
+ finalColor = vec4(color, 1.0);
+#else
+ texCoord_interp = texCoord;
+ finalColor = objectColor;
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl
new file mode 100644
index 00000000000..eab4de72115
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl
@@ -0,0 +1,207 @@
+
+/* Infinite grid
+ * Clément Foucault */
+
+out vec4 FragColor;
+
+uniform mat4 ProjectionMatrix;
+uniform vec3 cameraPos;
+uniform vec3 planeNormal;
+uniform vec3 planeAxes;
+uniform vec3 eye;
+uniform vec4 gridSettings;
+uniform vec2 viewportSize;
+uniform vec4 screenvecs[3];
+uniform float gridOneOverLogSubdiv;
+uniform sampler2D depthBuffer;
+
+#define gridDistance gridSettings.x
+#define gridResolution gridSettings.y
+#define gridScale gridSettings.z
+#define gridSubdiv gridSettings.w
+
+uniform int gridFlag;
+
+#define AXIS_X (1 << 0)
+#define AXIS_Y (1 << 1)
+#define AXIS_Z (1 << 2)
+#define GRID (1 << 3)
+#define PLANE_XY (1 << 4)
+#define PLANE_XZ (1 << 5)
+#define PLANE_YZ (1 << 6)
+
+#define GRID_LINE_SMOOTH 1.15
+
+float get_grid(vec3 co, vec3 fwidthCos, float grid_size)
+{
+ float half_size = grid_size / 2.0;
+ /* triangular wave pattern, amplitude is [0, grid_size] */
+ vec3 grid_domain = abs(mod(co + half_size, grid_size) - half_size);
+ /* modulate by the absolute rate of change of the coordinates
+ * (make lines have the same width under perspective) */
+ grid_domain /= fwidthCos;
+
+ /* collapse waves and normalize */
+ grid_domain.x = min(grid_domain.x, min(grid_domain.y, grid_domain.z)) / grid_size;
+
+ return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH / grid_size, grid_domain.x);
+}
+
+vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size)
+{
+ vec3 axes_domain = abs(co);
+ /* modulate by the absolute rate of change of the coordinates
+ * (make line have the same width under perspective) */
+ axes_domain /= fwidthCos;
+
+ return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH, axes_domain - line_size);
+}
+
+vec3 get_floor_pos(vec2 uv, out vec3 wPos)
+{
+ vec3 camera_vec, camera_pos, corner_pos;
+ vec3 floored_pos = planeAxes * floor(screenvecs[2].xyz);
+ corner_pos = screenvecs[2].xyz - floored_pos;
+
+ vec3 pixel_pos = corner_pos + uv.x * screenvecs[0].xyz + uv.y * screenvecs[1].xyz;
+
+ /* if perspective */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ camera_pos = cameraPos - floored_pos;
+ camera_vec = normalize(pixel_pos - camera_pos);
+ }
+ else {
+ camera_pos = pixel_pos;
+ camera_vec = normalize(eye);
+ }
+
+ float plane_normal_dot_camera_vec = dot(planeNormal, camera_vec);
+ float p = -dot(planeNormal, camera_pos);
+ if (plane_normal_dot_camera_vec != 0) {
+ p /= plane_normal_dot_camera_vec;
+ }
+ vec3 plane = camera_pos + camera_vec * p;
+
+ /* fix residual imprecision */
+ plane *= planeAxes;
+
+ /* Recover non-offseted world position */
+ wPos = plane + floored_pos;
+
+ return plane;
+}
+
+void main()
+{
+ vec2 sPos = gl_FragCoord.xy / viewportSize; /* Screen [0,1] position */
+
+ /* To reduce artifacts, use a local version of the positions
+ * to compute derivatives since they are not position dependant.
+ * This gets rid of the blocky artifacts. Unfortunately we still
+ * need the world position for the grid to scale properly from the origin. */
+ vec3 gPos, wPos; /* Grid pos., World pos. */
+ gPos = get_floor_pos(sPos, wPos);
+
+ vec3 fwidthPos = fwidth(gPos);
+
+ float dist, fade;
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ vec3 viewvec = cameraPos - wPos;
+ dist = length(viewvec);
+ viewvec /= dist;
+
+ float angle;
+ if ((gridFlag & PLANE_XZ) > 0)
+ angle = viewvec.y;
+ else if ((gridFlag & PLANE_YZ) > 0)
+ angle = viewvec.x;
+ else
+ angle = viewvec.z;
+
+ angle = 1.0 - abs(angle);
+ angle *= angle;
+ fade = 1.0 - angle * angle;
+ fade *= 1.0 - smoothstep(0.0, gridDistance, dist - gridDistance);
+ }
+ else {
+ dist = abs(gl_FragCoord.z * 2.0 - 1.0);
+ fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5);
+ dist = 1.0; /* avoid branch after */
+
+ if ((gridFlag & PLANE_XY) > 0) {
+ float angle = 1.0 - abs(eye.z);
+ dist = 1.0 + angle * 2.0;
+ angle *= angle;
+ fade *= 1.0 - angle * angle;
+ }
+ }
+
+ /* Manual, non hard, depth test:
+ * Progressively fade the grid below occluders
+ * (avoids poping visuals due to depth buffer precision) */
+ float scene_depth = texture(depthBuffer, sPos).r;
+ /* Add a small bias so the grid will always
+ * be on top of a mesh with the same depth. */
+ float grid_depth = gl_FragCoord.z - 1e-8;
+ /* Harder settings tend to flicker more,
+ * but have less "see through" appearance. */
+ const float test_hardness = 1e4;
+ fade *= 1.0 - clamp((grid_depth - scene_depth) * test_hardness, 0.0, 1.0);
+
+ if ((gridFlag & GRID) > 0) {
+ float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv;
+
+ float blend = fract(-max(grid_res, 0.0));
+ float lvl = floor(grid_res);
+
+ /* from biggest to smallest */
+ float scaleA = gridScale * pow(gridSubdiv, max(lvl - 1.0, 0.0));
+ float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0));
+ float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0));
+
+ float gridA = get_grid(wPos, fwidthPos, scaleA);
+ float gridB = get_grid(wPos, fwidthPos, scaleB);
+ float gridC = get_grid(wPos, fwidthPos, scaleC);
+
+ FragColor = vec4(colorGrid.rgb, gridA * blend);
+ FragColor = mix(FragColor, vec4(mix(colorGrid.rgb, colorGridEmphasise.rgb, blend), 1.0), gridB);
+ FragColor = mix(FragColor, vec4(colorGridEmphasise.rgb, 1.0), gridC);
+ }
+ else {
+ FragColor = vec4(colorGrid.rgb, 0.0);
+ }
+
+ if ((gridFlag & (AXIS_X | AXIS_Y | AXIS_Z)) > 0) {
+ /* Setup axes 'domains' */
+ vec3 axes_dist, axes_fwidth;
+
+ if ((gridFlag & AXIS_X) > 0) {
+ axes_dist.x = dot(wPos.yz, planeAxes.yz);
+ axes_fwidth.x = dot(fwidthPos.yz, planeAxes.yz);
+ }
+ if ((gridFlag & AXIS_Y) > 0) {
+ axes_dist.y = dot(wPos.xz, planeAxes.xz);
+ axes_fwidth.y = dot(fwidthPos.xz, planeAxes.xz);
+ }
+ if ((gridFlag & AXIS_Z) > 0) {
+ axes_dist.z = dot(wPos.xy, planeAxes.xy);
+ axes_fwidth.z = dot(fwidthPos.xy, planeAxes.xy);
+ }
+
+ /* Computing all axes at once using vec3 */
+ vec3 axes = get_axes(axes_dist, axes_fwidth, 0.1);
+
+ if ((gridFlag & AXIS_X) > 0) {
+ FragColor = mix(FragColor, colorGridAxisX, axes.x);
+ }
+ if ((gridFlag & AXIS_Y) > 0) {
+ FragColor = mix(FragColor, colorGridAxisY, axes.y);
+ }
+ if ((gridFlag & AXIS_Z) > 0) {
+ FragColor = mix(FragColor, colorGridAxisZ, axes.z);
+ }
+ }
+
+ FragColor.a *= fade;
+} \ No newline at end of file
diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl
new file mode 100644
index 00000000000..3f99d8b5d0a
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl
@@ -0,0 +1,63 @@
+
+/* Infinite grid
+ * Clément Foucault */
+
+uniform mat4 ViewProjectionMatrix;
+uniform mat4 ProjectionMatrix;
+uniform vec3 cameraPos;
+uniform vec4 gridSettings;
+
+#define gridDistance gridSettings.x
+#define gridResolution gridSettings.y
+#define gridScale gridSettings.z
+#define gridSubdiv gridSettings.w
+
+uniform int gridFlag;
+
+#define PLANE_XY (1 << 4)
+#define PLANE_XZ (1 << 5)
+#define PLANE_YZ (1 << 6)
+#define CLIP_Z_POS (1 << 7)
+#define CLIP_Z_NEG (1 << 8)
+
+in vec3 pos;
+
+void main()
+{
+ vec3 vert_pos, proj_camera_pos;
+
+ /* Project camera pos to the needed plane */
+ if ((gridFlag & PLANE_XY) > 0) {
+ vert_pos = vec3(pos.x, pos.y, 0.0);
+ proj_camera_pos = vec3(cameraPos.x, cameraPos.y, 0.0);
+ }
+ else if ((gridFlag & PLANE_XZ) > 0) {
+ vert_pos = vec3(pos.x, 0.0, pos.y);
+ proj_camera_pos = vec3(cameraPos.x, 0.0, cameraPos.z);
+ }
+ else {
+ vert_pos = vec3(0.0, pos.x, pos.y);
+ proj_camera_pos = vec3(0.0, cameraPos.y, cameraPos.z);
+ }
+
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ vert_pos *= gridDistance * 2.0;
+ }
+ else {
+ float viewdist = 1.0 / min(abs(ProjectionMatrix[0][0]), abs(ProjectionMatrix[1][1]));
+ vert_pos *= viewdist * gridDistance * 2.0;
+ }
+
+ vec3 realPos = proj_camera_pos + vert_pos;
+
+ /* Used for additional Z axis */
+ if ((gridFlag & CLIP_Z_POS) > 0) {
+ realPos.z = max(realPos.z, 0.0);
+ }
+ if ((gridFlag & CLIP_Z_NEG) > 0) {
+ realPos.z = min(-realPos.z, 0.0);
+ }
+
+ gl_Position = ViewProjectionMatrix * vec4(realPos, 1.0);
+}
diff --git a/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl b/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl
new file mode 100644
index 00000000000..b47b3ee1cf4
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl
@@ -0,0 +1,28 @@
+
+in vec3 pos;
+in vec3 nor;
+
+uniform mat4 ViewProjectionMatrix;
+
+uniform float sphere_size;
+uniform ivec3 grid_resolution;
+uniform vec3 corner;
+uniform vec3 increment_x;
+uniform vec3 increment_y;
+uniform vec3 increment_z;
+
+void main()
+{
+ vec3 ls_cell_location;
+ /* Keep in sync with update_irradiance_probe */
+ ls_cell_location.z = float(gl_InstanceID % grid_resolution.z);
+ ls_cell_location.y = float((gl_InstanceID / grid_resolution.z) % grid_resolution.y);
+ ls_cell_location.x = float(gl_InstanceID / (grid_resolution.z * grid_resolution.y));
+
+ vec3 ws_cell_location = corner +
+ (increment_x * ls_cell_location.x +
+ increment_y * ls_cell_location.y +
+ increment_z * ls_cell_location.z);
+
+ gl_Position = ViewProjectionMatrix * vec4(pos * 0.02 * sphere_size + ws_cell_location, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl
new file mode 100644
index 00000000000..dc0ea938436
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl
@@ -0,0 +1,79 @@
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler2D outlineColor;
+uniform sampler2D outlineDepth;
+uniform sampler2D sceneDepth;
+
+uniform float alphaOcclu;
+uniform vec2 viewportSize;
+
+void search_outline(ivec2 uv, vec4 ref_col, inout bool ref_occlu, inout bool outline)
+{
+ if (!outline) {
+ vec4 color = texelFetch(outlineColor, uv, 0).rgba;
+ if (color != ref_col) {
+ outline = true;
+ }
+ else {
+ float depth = texelFetch(outlineDepth, uv, 0).r;
+ float scene_depth = texelFetch(sceneDepth, uv, 0).r;
+ bool occlu = (depth > scene_depth);
+
+ if (occlu != ref_occlu && !ref_occlu) {
+ outline = true;
+ }
+ }
+ }
+}
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+
+ vec4 color[4];
+ /* Idea : Use a 16bit ID to identify the color
+ * and store the colors in a UBO. And fetch all ids
+ * for discontinuity check with one textureGather \o/ */
+ vec4 ref_col = texelFetch(outlineColor, uv, 0).rgba;
+ color[0] = texelFetchOffset(outlineColor, uv, 0, ivec2( 1, 0)).rgba;
+ color[1] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, 1)).rgba;
+ color[2] = texelFetchOffset(outlineColor, uv, 0, ivec2(-1, 0)).rgba;
+ color[3] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, -1)).rgba;
+
+ /* TODO GATHER */
+ vec4 depths;
+ float depth = texelFetch(outlineDepth, uv, 0).r;
+ depths.x = texelFetchOffset(outlineDepth, uv, 0, ivec2( 1, 0)).r;
+ depths.y = texelFetchOffset(outlineDepth, uv, 0, ivec2( 0, 1)).r;
+ depths.z = texelFetchOffset(outlineDepth, uv, 0, ivec2(-1, 0)).r;
+ depths.w = texelFetchOffset(outlineDepth, uv, 0, ivec2( 0, -1)).r;
+
+ vec4 scene_depths;
+ float scene_depth = texelFetch(sceneDepth, uv, 0).r;
+ scene_depths.x = texelFetchOffset(sceneDepth, uv, 0, ivec2( 1, 0)).r;
+ scene_depths.y = texelFetchOffset(sceneDepth, uv, 0, ivec2( 0, 1)).r;
+ scene_depths.z = texelFetchOffset(sceneDepth, uv, 0, ivec2(-1, 0)).r;
+ scene_depths.w = texelFetchOffset(sceneDepth, uv, 0, ivec2( 0, -1)).r;
+
+ bool ref_occlu = (depth > scene_depth);
+ bool outline = false;
+
+#if 1
+ bvec4 occlu = (!ref_occlu) ? notEqual(greaterThan(depths, scene_depths), bvec4(ref_occlu)) : bvec4(false);
+ outline = (!outline) ? (color[0] != ref_col) || occlu.x : true;
+ outline = (!outline) ? (color[1] != ref_col) || occlu.y : true;
+ outline = (!outline) ? (color[2] != ref_col) || occlu.z : true;
+ outline = (!outline) ? (color[3] != ref_col) || occlu.w : true;
+#else
+ search_outline(uv + ivec2( 1, 0), ref_col, ref_occlu, outline);
+ search_outline(uv + ivec2( 0, 1), ref_col, ref_occlu, outline);
+ search_outline(uv + ivec2(-1, 0), ref_col, ref_occlu, outline);
+ search_outline(uv + ivec2( 0, -1), ref_col, ref_occlu, outline);
+#endif
+
+ FragColor = ref_col;
+ FragColor.a *= (outline) ? (ref_occlu) ? alphaOcclu : 1.0 : 0.0;
+}
diff --git a/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl
new file mode 100644
index 00000000000..7e288cde236
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl
@@ -0,0 +1,37 @@
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler2D outlineColor;
+
+uniform float alpha;
+uniform bool doExpand;
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+ FragColor = texelFetch(outlineColor, uv, 0).rgba;
+
+ vec4 color[4];
+ color[0] = texelFetchOffset(outlineColor, uv, 0, ivec2( 1, 0)).rgba;
+ color[1] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, 1)).rgba;
+ color[2] = texelFetchOffset(outlineColor, uv, 0, ivec2(-1, 0)).rgba;
+ color[3] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, -1)).rgba;
+
+ vec4 values = vec4(color[0].a, color[1].a, color[2].a, color[3].a);
+
+ vec4 tests = step(vec4(1e-6), values); /* (color.a != 0.0) */
+ bvec4 btests = equal(tests, vec4(1.0));
+
+ if (FragColor.a != 0.0) {
+ return;
+ }
+
+ FragColor = (btests.x) ? color[0] : FragColor;
+ FragColor = (btests.y) ? color[1] : FragColor;
+ FragColor = (btests.z) ? color[2] : FragColor;
+ FragColor = (btests.w) ? color[3] : FragColor;
+
+ FragColor.a *= (!doExpand) ? 0.0 : 1.0;
+}
diff --git a/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl
new file mode 100644
index 00000000000..964ebe72e81
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl
@@ -0,0 +1,27 @@
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler2D outlineBluredColor;
+uniform vec2 rcpDimensions;
+
+void main()
+{
+#ifdef USE_FXAA
+ float aa_alpha = FxaaPixelShader(
+ uvcoordsvar.st,
+ outlineBluredColor,
+ rcpDimensions,
+ 1.0,
+ 0.166,
+ 0.0833
+ ).r;
+#endif
+
+ FragColor = texture(outlineBluredColor, uvcoordsvar.st).rgba;
+
+#ifdef USE_FXAA
+ FragColor.a = aa_alpha;
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl b/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl
new file mode 100644
index 00000000000..e8bf7884701
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl
@@ -0,0 +1,52 @@
+
+uniform vec3 color;
+uniform vec3 outlineColor;
+uniform sampler1D ramp;
+
+in vec4 radii;
+flat in float finalVal;
+
+out vec4 fragColor;
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure outline color
+// --- 2 ---
+// smooth transition
+// --- 3 ---
+// pure point color
+// ...
+// dist = 0 at center of point
+
+ float midStroke = 0.5 * (radii[1] + radii[2]);
+
+ if (dist > midStroke) {
+ if (finalVal < 0.0) {
+ fragColor.rgb = outlineColor;
+ }
+ else {
+ fragColor.rgb = texture(ramp, finalVal).rgb;
+ }
+
+ fragColor.a = mix(1.0, 0.0, smoothstep(radii[1], radii[0], dist));
+ }
+ else {
+ if (finalVal < 0.0) {
+ fragColor.rgb = mix(color, outlineColor, smoothstep(radii[3], radii[2], dist));
+ }
+ else {
+ fragColor.rgb = texture(ramp, finalVal).rgb;
+ }
+
+ fragColor.a = 1.0;
+ }
+
+ if (fragColor.a == 0.0) {
+ discard;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl
new file mode 100644
index 00000000000..6dfc212a776
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl
@@ -0,0 +1,35 @@
+
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform float pixel_size;
+uniform float size;
+
+in vec3 pos;
+in float val;
+
+out vec4 radii;
+flat out float finalVal;
+
+void main() {
+ gl_Position = ModelViewMatrix * vec4(pos, 1.0);
+
+ float psize = (ProjectionMatrix[3][3] == 0.0) ? (size / (-gl_Position.z * pixel_size)) : (size / pixel_size);
+
+ gl_PointSize = psize;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * psize;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - 1.0;
+ radii[3] = radius - 2.0;
+
+ // convert to PointCoord units
+ radii /= psize;
+
+ gl_Position = ProjectionMatrix * gl_Position;
+
+ finalVal = val;
+}
diff --git a/source/blender/draw/modes/shaders/object_particle_prim_frag.glsl b/source/blender/draw/modes/shaders/object_particle_prim_frag.glsl
new file mode 100644
index 00000000000..aa455a85cf0
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_particle_prim_frag.glsl
@@ -0,0 +1,9 @@
+
+flat in vec4 finalColor;
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor;
+}
diff --git a/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl
new file mode 100644
index 00000000000..54ae319307a
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl
@@ -0,0 +1,56 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ViewProjectionMatrix;
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform int screen_space;
+uniform float draw_size;
+uniform vec3 color;
+uniform sampler1D ramp;
+
+in vec3 pos;
+in vec4 rot;
+in float val;
+in vec3 inst_pos;
+in int axis;
+
+flat out vec4 finalColor;
+
+vec3 rotate(vec3 vec, vec4 quat)
+{
+ /* The quaternion representation here stores the w component in the first index */
+ return vec + 2.0 * cross(quat.yzw, cross(quat.yzw, vec) + quat.x * vec);
+}
+
+void main()
+{
+ if (screen_space == 1) {
+ gl_Position = ModelViewMatrix * vec4(pos, 1.0) + vec4(inst_pos * draw_size, 0.0);
+ gl_Position = ProjectionMatrix * gl_Position;
+ }
+ else {
+ float size = draw_size;
+
+ if (axis > -1) {
+ size *= 2;
+ }
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos + rotate(inst_pos * size, rot), 1.0);
+ }
+
+#ifdef USE_AXIS
+ if (axis == 0)
+ finalColor = vec4(1.0, 0.0, 0.0, 1.0);
+ else if (axis == 1)
+ finalColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ finalColor = vec4(0.0, 0.0, 1.0, 1.0);
+#else
+ if (val < 0.0) {
+ finalColor = vec4(color, 1.0);
+ }
+ else {
+ finalColor = vec4(texture(ramp, val).rgb, 1.0);
+ }
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/paint_texture_frag.glsl b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
new file mode 100644
index 00000000000..18c58a54dca
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
@@ -0,0 +1,11 @@
+
+in vec2 uv_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+
+
+void main()
+{
+ fragColor = texture(image, uv_interp);
+}
diff --git a/source/blender/draw/modes/shaders/paint_texture_vert.glsl b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
new file mode 100644
index 00000000000..4ce12e048fa
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
@@ -0,0 +1,15 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 uv;
+in vec3 pos;
+
+out vec2 uv_interp;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ uv_interp = uv;
+
+}
diff --git a/source/blender/draw/modes/shaders/paint_vert_frag.glsl b/source/blender/draw/modes/shaders/paint_vert_frag.glsl
new file mode 100644
index 00000000000..c22e1c04b96
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_vert_frag.glsl
@@ -0,0 +1,26 @@
+
+flat in int finalFlag;
+out vec4 fragColor;
+
+#define VERTEX_SELECTED (1 << 0)
+#define VERTEX_HIDE (1 << 4)
+
+void main()
+{
+ if (bool(finalFlag & VERTEX_HIDE)) {
+ discard;
+ }
+
+ vec2 centered = gl_PointCoord - vec2(0.5);
+ float dist_squared = dot(centered, centered);
+ const float rad_squared = 0.25;
+ const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0);
+ const vec4 colUnsel = vec4(0.5, 0.5, 0.5, 1.0);
+
+ // round point with jaggy edges
+ if (dist_squared > rad_squared) {
+ discard;
+ }
+
+ fragColor = bool(finalFlag & VERTEX_SELECTED) ? colSel : colUnsel;
+}
diff --git a/source/blender/draw/modes/shaders/paint_wire_frag.glsl b/source/blender/draw/modes/shaders/paint_wire_frag.glsl
new file mode 100644
index 00000000000..e4214a4c6d1
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_wire_frag.glsl
@@ -0,0 +1,24 @@
+
+flat in int finalFlag;
+out vec4 fragColor;
+
+#define VERTEX_SELECTED (1 << 0)
+#define VERTEX_HIDE (1 << 4)
+
+void main()
+{
+ if (bool(finalFlag & VERTEX_HIDE)) {
+ discard;
+ }
+
+#ifdef VERTEX_MODE
+ vec4 colSel = colorEdgeSelect;
+ colSel.rgb = clamp(colSel.rgb - 0.2, 0.0, 1.0);
+#else
+ const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0);
+#endif
+
+ const vec4 colUnsel = vec4(0.5, 0.5, 0.5, 1.0);
+
+ fragColor = bool(finalFlag & VERTEX_SELECTED) ? colSel : colUnsel;
+}
diff --git a/source/blender/draw/modes/shaders/paint_wire_vert.glsl b/source/blender/draw/modes/shaders/paint_wire_vert.glsl
new file mode 100644
index 00000000000..253c21745e2
--- /dev/null
+++ b/source/blender/draw/modes/shaders/paint_wire_vert.glsl
@@ -0,0 +1,14 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in int data;
+
+flat out int finalFlag;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ finalFlag = data;
+}
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index 1559512d713..757fca0a1b2 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -29,13 +29,14 @@ if(WITH_BLENDER)
add_subdirectory(gpencil)
add_subdirectory(interface)
add_subdirectory(io)
+ add_subdirectory(manipulator_library)
add_subdirectory(mask)
add_subdirectory(mesh)
add_subdirectory(metaball)
add_subdirectory(object)
add_subdirectory(physics)
add_subdirectory(render)
- add_subdirectory(screen)
+ add_subdirectory(scene)
add_subdirectory(sculpt_paint)
add_subdirectory(sound)
add_subdirectory(space_action)
@@ -60,6 +61,7 @@ if(WITH_BLENDER)
add_subdirectory(transform)
add_subdirectory(util)
add_subdirectory(uvedit)
+ add_subdirectory(screen)
endif()
add_subdirectory(datafiles)
diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt
index 1bf1bb2a474..13432e38669 100644
--- a/source/blender/editors/animation/CMakeLists.txt
+++ b/source/blender/editors/animation/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../gpu
../../makesdna
../../makesrna
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index dba060bfb29..9fb30dc8066 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -68,6 +68,8 @@
#include "BKE_nla.h"
#include "BKE_context.h"
+#include "GPU_immediate.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
@@ -76,7 +78,6 @@
#include "ED_keyframing.h"
#include "BIF_gl.h"
-#include "BIF_glutil.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -119,11 +120,10 @@ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, floa
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
/* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
- UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+ UI_draw_roundbox_3fvAlpha(true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
@@ -141,13 +141,19 @@ static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale
View2D *v2d = &ac->ar->v2d;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
-
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
-
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
/* no rounded corner - just rectangular box */
- glRectf(offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+ immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+
+ immUnbindProgram();
}
/* helper method to test if group colors should be drawn */
@@ -224,13 +230,19 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, f
View2D *v2d = &ac->ar->v2d;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
/* no rounded corners - just rectangular box */
- glRectf(offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+ immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+
+ immUnbindProgram();
}
/* Indention + Offset ------------------------------------------- */
@@ -421,14 +433,13 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
/* rounded corners on LHS only
* - top and bottom
* - special hack: make the top a bit higher, since we are first...
*/
UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
- UI_draw_roundbox_gl_mode(GL_POLYGON, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+ UI_draw_roundbox_3fvAlpha(true, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
/* name for summary entries */
@@ -814,11 +825,10 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
/* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
- UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+ UI_draw_roundbox_3fvAlpha(true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
/* name for group entries */
@@ -1071,11 +1081,10 @@ static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, floa
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
- /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
+ /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
- UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5);
+ UI_draw_roundbox_3fvAlpha(true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f);
}
/* name for nla controls expander entries */
@@ -2018,7 +2027,7 @@ static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
- return PART_DS_EXPAND;
+ return 0;
case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
return ADT_NLA_EVAL_OFF;
@@ -2036,22 +2045,18 @@ static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
}
/* get pointer to the setting */
-static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+static void *acf_dspart_setting_ptr(bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting, short *type)
{
- ParticleSettings *part = (ParticleSettings *)ale->data;
-
/* clear extra return data first */
*type = 0;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(part->flag, type);
+ return NULL;
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
- if (part->adt)
- return GET_ACF_FLAG_PTR(part->adt->flag, type);
return NULL;
default: /* unsupported */
@@ -3420,24 +3425,20 @@ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float y
*/
nla_action_get_color(adt, (bAction *)ale->data, color);
- if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
- /* Yes, the color vector has 4 components, BUT we only want to be using 3 of them! */
- glColor3fv(color);
- }
- else {
- float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
- glColor4f(color[0], color[1], color[2], alpha);
- }
-
- /* only on top left corner, to show that this channel sits on top of the preceding ones
+ if (adt && (adt->flag & ADT_NLA_EDIT_ON))
+ color[3] = 1.0f;
+ else
+ color[3] = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
+
+ /* only on top left corner, to show that this channel sits on top of the preceding ones
* while still linking into the action line strip to the right
*/
UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT);
-
+
/* draw slightly shifted up vertically to look like it has more separation from other channels,
* but we then need to slightly shorten it so that it doesn't look like it overlaps
*/
- UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8);
+ UI_draw_roundbox_4fv(true, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8, color);
}
/* name for nla action entries */
@@ -3861,15 +3862,20 @@ 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;
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever
* color the curve has stored
*/
- glColor3fv(fcu->color);
+ immUniformColor3fv(fcu->color);
/* just a solid color rect
*/
- glRectf(offset, yminc, offset + ICON_WIDTH, ymaxc);
+ immRectf(pos, offset, yminc, offset + ICON_WIDTH, ymaxc);
+
+ immUnbindProgram();
}
/* icon is drawn as widget now... */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
@@ -3894,27 +3900,39 @@ 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)) {
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* FIXME: replace hardcoded color here, and check on extents! */
- glColor3f(1.0f, 0.0f, 0.0f);
- glLineWidth(2.0);
- fdrawline((float)(offset), yminc,
- (float)(v2d->cur.xmax), yminc);
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
+
+ glLineWidth(2.0f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, (float)offset, yminc);
+ immVertex2f(pos, (float)v2d->cur.xmax, yminc);
+ immEnd();
+
+ immUnbindProgram();
}
}
@@ -3928,10 +3946,13 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
short draw_sliders = 0;
float ymin_ofs = 0.0f;
float color[3];
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* get and set backdrop color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
+ immUniformColor3fv(color);
/* check if we need to show the sliders */
if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) {
@@ -3989,7 +4010,9 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
* - starts from the point where the first toggle/slider starts,
* - ends past the space that might be reserved for a scroller
*/
- glRectf(v2d->cur.xmax - (float)offset, yminc + ymin_ofs, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+ immRectf(pos, v2d->cur.xmax - (float)offset, yminc + ymin_ofs, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+
+ immUnbindProgram();
}
}
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 82f24c91df1..0db465e583b 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -50,13 +50,15 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
#include "BKE_context.h"
+#include "BKE_library.h"
#include "BKE_mask.h"
#include "BKE_global.h"
-#include "BKE_library.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph_build.h"
#include "UI_view2d.h"
@@ -1720,7 +1722,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* send notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
return OPERATOR_FINISHED;
}
@@ -2682,16 +2684,17 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
{
bDopeSheet *ads = (bDopeSheet *)ac->data;
Scene *sce = (Scene *)ads->source;
+ ViewLayer *view_layer = ac->view_layer;
Base *base = (Base *)ale->data;
Object *ob = base->object;
AnimData *adt = ob->adt;
/* set selection status */
- if ((ob->restrictflag & OB_RESTRICT_SELECT) == 0) {
+ if (base->flag & BASE_SELECTABLED) {
if (selectmode == SELECT_INVERT) {
/* swap select */
- base->flag ^= SELECT;
- ob->flag = base->flag;
+ ED_object_base_select(base, BA_INVERT);
+ BKE_scene_object_base_flag_sync_from_base(base);
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
@@ -2700,20 +2703,20 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
/* 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;
+ for (b = view_layer->object_bases.first; b; b = b->next) {
+ ED_object_base_select(b, BA_DESELECT);
+ BKE_scene_object_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;
- ob->flag |= SELECT;
+ ED_object_base_select(base, BA_SELECT);
+ BKE_scene_object_base_flag_sync_from_base(base);
if (adt) adt->flag |= ADT_UI_SELECTED;
}
/* change active object - regardless of whether it is now selected [T37883] */
- ED_base_object_activate(C, base); /* adds notifier */
+ ED_object_base_activate(C, base); /* adds notifier */
if ((adt) && (adt->flag & ADT_UI_SELECTED))
adt->flag |= ADT_UI_ACTIVE;
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index cc77a321a89..abdc6450abd 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -49,11 +49,12 @@
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_node.h"
#include "BKE_sequencer.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "ED_anim_api.h"
@@ -77,7 +78,7 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale)
adt = BKE_animdata_from_id(id);
if (adt) {
adt->recalc |= ADT_RECALC_ANIM;
- DAG_id_tag_update(id, OB_RECALC_TIME);
+ DEG_id_tag_update(id, OB_RECALC_TIME);
}
/* update data */
@@ -98,7 +99,7 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale)
else {
/* in other case we do standard depsgraph update, ideally
* we'd be calling property update functions here too ... */
- DAG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive?
+ DEG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive?
}
}
@@ -114,7 +115,7 @@ void ANIM_id_update(Scene *UNUSED(scene), ID *id)
adt->recalc |= ADT_RECALC_ANIM;
/* set recalc flags */
- DAG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive?
+ DEG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); // XXX or do we want something more restrictive?
}
}
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index a6febdb575e..08851cebf51 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -58,12 +58,13 @@
#include "RNA_access.h"
-#include "BIF_gl.h"
-
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
/* *************************************************** */
/* CURRENT FRAME DRAWING */
@@ -71,13 +72,17 @@
static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const bool time)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- float xscale, yscale, x, y;
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned char col[4];
+ float xscale, x, y;
char numstr[32] = " t"; /* t is the character to start replacing from */
int slen;
/* because the frame number text is subject to the same scaling as the contents of the view */
- UI_view2d_scale_get(v2d, &xscale, &yscale);
- glScalef(1.0f / xscale, 1.0f, 1.0f);
+ UI_view2d_scale_get(v2d, &xscale, NULL);
+ gpuPushMatrix();
+ gpuScale2f(1.0f / xscale, 1.0f);
/* get timecode string
* - padding on str-buf passed so that it doesn't sit on the frame indicator
@@ -96,17 +101,21 @@ 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;
-
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* draw green box around/behind text */
- UI_ThemeColorShade(TH_CFRAME, 0);
- glRectf(x, y, x + slen, y + 0.75f * U.widget_unit);
-
- /* 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);
-
+ immUniformThemeColorShade(TH_CFRAME, 0);
+
+ immRectf(pos, x, y, x + slen, y + 0.75f * U.widget_unit);
+ immUnbindProgram();
+
+ /* draw current frame number */
+ 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);
+ gpuPopMatrix();
}
/* General call for drawing current frame indicator in animation editor */
@@ -114,18 +123,24 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
{
Scene *scene = CTX_data_scene(C);
- /* Draw a light green line to indicate current frame */
- UI_ThemeColor(TH_CFRAME);
-
const float time = scene->r.cfra + scene->r.subframe;
const float x = (float)(time * scene->r.framelen);
glLineWidth((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0);
- glBegin(GL_LINES);
- glVertex2f(x, v2d->cur.ymin - 500.0f); /* XXX arbitrary... want it go to bottom */
- glVertex2f(x, v2d->cur.ymax);
- glEnd();
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* Draw a light green line to indicate current frame */
+ immUniformThemeColor(TH_CFRAME);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, x, v2d->cur.ymin - 500.0f); /* XXX arbitrary... want it go to bottom */
+ immVertex2f(pos, x, v2d->cur.ymax);
+ immEnd();
+ immUnbindProgram();
/* Draw current frame number in a little box */
if (flag & DRAWCFRA_SHOW_NUMBOX) {
@@ -147,17 +162,24 @@ void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
if (PRVRANGEON) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
-
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+
/* only draw two separate 'curtains' if there's no overlap between them */
if (PSFRA < PEFRA + end_frame_width) {
- glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
- glRectf((float)(PEFRA + end_frame_width), v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
+ immRectf(pos, (float)(PEFRA + end_frame_width), v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
else {
- glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
-
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
}
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 2ac305dbc30..bc901d7e13f 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -74,6 +74,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_layer_types.h"
#include "MEM_guardedalloc.h"
@@ -90,6 +91,7 @@
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_key.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
@@ -130,11 +132,11 @@ static void animedit_get_yscale_factor(bAnimContext *ac)
/* Note: there's a similar function in key.c (BKE_key_from_object) */
static Key *actedit_get_shapekeys(bAnimContext *ac)
{
- Scene *scene = ac->scene;
+ ViewLayer *view_layer = ac->view_layer;
Object *ob;
Key *key;
- ob = OBACT;
+ ob = OBACT(view_layer);
if (ob == NULL)
return NULL;
@@ -378,8 +380,9 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
ac->scene = scene;
if (scene) {
ac->markers = ED_context_get_markers(C);
- ac->obact = (scene->basact) ? scene->basact->object : NULL;
}
+ ac->view_layer = CTX_data_view_layer(C);
+ ac->obact = (ac->view_layer->basact) ? ac->view_layer->basact->object : NULL;
ac->sa = sa;
ac->ar = ar;
ac->sl = sl;
@@ -1683,15 +1686,16 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
if (ads->filterflag & ADS_FILTER_GP_3DONLY) {
Scene *scene = (Scene *)ads->source;
+ ViewLayer *view_layer = (ViewLayer *)ac->view_layer;
Base *base;
-
+
/* Active scene's GPencil block first - No parent item needed... */
if (scene->gpd) {
items += animdata_filter_gpencil_data(anim_data, ads, scene->gpd, filter_mode);
}
/* Objects in the scene */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = view_layer->object_bases.first; base; base = base->next) {
/* Only consider this object if it has got some GP data (saving on all the other tests) */
if (base->object && base->object->gpd) {
Object *ob = base->object;
@@ -1707,14 +1711,14 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
*/
if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
/* layer visibility - we check both object and base, since these may not be in sync yet */
- if ((scene->lay & (ob->lay | base->lay)) == 0) continue;
+ if ((base->flag & BASE_VISIBLED) == 0) continue;
/* outliner restrict-flag */
if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
}
/* 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 & BASE_SELECTED) /*|| (base == scene->basact)*/) ) {
/* only selected should be shown */
continue;
}
@@ -1954,25 +1958,26 @@ static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data,
static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
{
- SceneRenderLayer *srl;
+ ViewLayer *view_layer;
FreestyleLineSet *lineset;
size_t items = 0;
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
if (lineset->linestyle) {
lineset->linestyle->id.tag |= LIB_TAG_DOIT;
}
}
}
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
/* skip render layers without Freestyle enabled */
- if (!(srl->layflag & SCE_LAY_FRS))
+ if ((view_layer->flag & VIEW_LAYER_FREESTYLE) == 0) {
continue;
-
+ }
+
/* loop over linesets defined in the render layer */
- for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
FreestyleLineStyle *linestyle = lineset->linestyle;
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
@@ -2631,7 +2636,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 & BASE_SELECTED))) {
/* check if filtering by active status */
if (ANIMCHANNEL_ACTIVEOK(ob)) {
ANIMCHANNEL_NEW_CHANNEL(base, ANIMTYPE_OBJECT, ob);
@@ -2855,7 +2860,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, Base *base, int filter_mode)
{
Object *ob = base->object;
@@ -2873,7 +2878,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base
*/
if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
/* layer visibility - we check both object and base, since these may not be in sync yet */
- if ((scene->lay & (ob->lay | base->lay)) == 0)
+ if ((base->flag & BASE_VISIBLED) == 0)
return false;
/* outliner restrict-flag */
@@ -2908,7 +2913,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 & BASE_SELECTED) /*|| (base == sce->basact)*/)) {
/* only selected should be shown */
return false;
}
@@ -2936,15 +2941,15 @@ static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr)
}
/* 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 Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, ViewLayer *view_layer, 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 tot_bases = BLI_listbase_count(&view_layer->object_bases);
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) {
- if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (animdata_filter_base_is_ok(ads, base, filter_mode)) {
sorted_bases[num_bases++] = base;
}
}
@@ -2962,8 +2967,9 @@ static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int
static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode)
{
Scene *scene = (Scene *)ads->source;
+ ViewLayer *view_layer = (ViewLayer *)ac->view_layer;
size_t items = 0;
-
+
/* check that we do indeed have a scene */
if ((ads->source == NULL) || (GS(ads->source->name) != ID_SCE)) {
printf("Dope Sheet Error: No scene!\n");
@@ -3000,14 +3006,14 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
* - Don't do this if there's just a single object
*/
if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && !(ads->flag & ADS_FLAG_NO_DB_SORT) &&
- (scene->base.first != scene->base.last))
+ (view_layer->object_bases.first != view_layer->object_bases.last))
{
/* 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;
size_t num_bases;
- sorted_bases = animdata_filter_ds_sorted_bases(ads, scene, filter_mode, &num_bases);
+ sorted_bases = animdata_filter_ds_sorted_bases(ads, view_layer, filter_mode, &num_bases);
if (sorted_bases) {
/* Add the necessary channels for these bases... */
for (size_t i = 0; i < num_bases; i++) {
@@ -3024,8 +3030,8 @@ 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) {
- if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (animdata_filter_base_is_ok(ads, 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 04398e88499..107a46999f0 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -36,13 +36,14 @@
#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"
#include "BKE_context.h"
#include "BKE_fcurve.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -56,9 +57,11 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_view2d.h"
@@ -351,19 +354,30 @@ static void draw_marker(
if (flag & DRAW_MARKERS_LINES)
#endif
{
- setlinestyle(3);
-
- if (marker->flag & SELECT)
- glColor4ub(255, 255, 255, 96);
- else
- glColor4ub(0, 0, 0, 96);
-
- glBegin(GL_LINES);
- glVertex2f(xpos + 0.5f, 12.0f);
- glVertex2f(xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
- glEnd();
-
- setlinestyle(0);
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ if (marker->flag & SELECT) {
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.38f);
+ }
+ else {
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.38f);
+ }
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, xpos + 0.5f, 12.0f);
+ immVertex2f(pos, xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
+ immEnd();
+
+ immUnbindProgram();
}
/* 5 px to offset icon to align properly, space / pixels corrects for zoom */
@@ -383,19 +397,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;
@@ -409,14 +424,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);
}
}
@@ -443,21 +455,27 @@ void ED_markers_draw(const bContext *C, int flag)
v2d = UI_view2d_fromcontext(C);
if (flag & DRAW_MARKERS_MARGIN) {
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
const unsigned char shade[4] = {0, 0, 0, 16};
- glColor4ubv(shade);
+ immUniformColor4ubv(shade);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glRectf(v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y);
+ immRectf(pos, v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y);
glDisable(GL_BLEND);
+
+ immUnbindProgram();
}
/* no time correction for framelen! space is drawn with old values */
ypixels = BLI_rcti_size_y(&v2d->mask);
UI_view2d_scale_get(v2d, &xscale, &yscale);
- glScalef(1.0f / xscale, 1.0f, 1.0f);
+ gpuPushMatrix();
+ gpuScale2f(1.0f / xscale, 1.0f);
/* x-bounds with offset for text (adjust for long string, avoid checking string width) */
font_width_max = (10 * UI_DPI_FAC) / xscale;
@@ -480,7 +498,7 @@ void ED_markers_draw(const bContext *C, int flag)
}
}
- glScalef(xscale, 1.0f, 1.0f);
+ gpuPopMatrix();
}
/* ************************ Marker Wrappers API ********************* */
@@ -844,7 +862,7 @@ static void ed_marker_move_apply(bContext *C, wmOperator *op)
BKE_scene_camera_switch_update(scene);
if (camera != scene->camera) {
- BKE_screen_view3d_scene_sync(sc);
+ BKE_screen_view3d_scene_sync(sc, scene);
WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
}
#endif
@@ -1128,12 +1146,13 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool
if (camera) {
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Base *base;
TimeMarker *marker;
int sel = 0;
if (!extend)
- BKE_scene_base_deselect_all(scene);
+ BKE_view_layer_base_deselect_all(view_layer);
for (marker = markers->first; marker; marker = marker->next) {
if (marker->frame == cfra) {
@@ -1145,11 +1164,11 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool
for (marker = markers->first; marker; marker = marker->next) {
if (marker->camera) {
if (marker->frame == cfra) {
- base = BKE_scene_base_find(scene, marker->camera);
+ base = BKE_view_layer_base_find(view_layer, marker->camera);
if (base) {
- ED_base_object_select(base, sel);
+ ED_object_base_select(base, sel);
if (sel)
- ED_base_object_activate(C, base);
+ ED_object_base_activate(C, base);
}
}
}
@@ -1532,7 +1551,7 @@ static int ed_marker_camera_bind_exec(bContext *C, wmOperator *UNUSED(op))
/* camera may have changes */
BKE_scene_camera_switch_update(scene);
- BKE_screen_view3d_scene_sync(sc);
+ BKE_screen_view3d_scene_sync(sc, scene);
WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 24eb6451c5d..2d04f73c4ac 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -44,11 +44,13 @@
#include "DNA_texture_types.h"
#include "BKE_animsys.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_context.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_keyframing.h"
#include "UI_interface.h"
@@ -843,7 +845,7 @@ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_typ
if (success) {
/* send updates */
UI_context_update_anim_flag(C);
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
return OPERATOR_FINISHED;
@@ -941,7 +943,7 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op)
if (success) {
/* send updates */
UI_context_update_anim_flag(C);
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
}
@@ -1031,8 +1033,8 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
UI_context_update_anim_flag(C);
- DAG_relations_tag_update(CTX_data_main(C));
- DAG_id_tag_update(ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_relations_tag_update(CTX_data_main(C));
+ DEG_id_tag_update(ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index f25dbf2381c..12803854a42 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);
+
+ BLI_assert(draw_fill || draw_outline);
+
+ /* 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.925f;
break;
case BEZT_KEYTYPE_EXTREME: /* slightly larger */
- hsize *= 1.2f;
+ size *= 1.2f;
break;
default:
- hsize -= 0.5f * key_type;
- break;
+ size -= 0.8f * 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 icon_sz = U.widget_unit * 0.5f * yscale_fac;
+ const float half_icon_sz = 0.5f * icon_sz;
+ const float smaller_sz = 0.35f * icon_sz;
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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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 - smaller_sz, ab->end, ypos + smaller_sz);
}
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 - half_icon_sz, ab->end, ypos + half_icon_sz);
}
}
}
+ 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 */
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immBegin(GWN_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, icon_sz, (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();
}
}
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index de0d19f7b05..afbd8e5bd41 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -56,7 +56,6 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_armature.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_idcode.h"
#include "BKE_nla.h"
@@ -66,6 +65,9 @@
#include "BKE_key.h"
#include "BKE_material.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_anim_api.h"
#include "ED_keyframing.h"
#include "ED_keyframes_edit.h"
@@ -155,7 +157,7 @@ bAction *verify_adt_action(ID *id, short add)
/* tag depsgraph to be rebuilt to include time dependency */
/* XXX: we probably should have bmain passed down, but that involves altering too many API's */
- DAG_relations_tag_update(G.main);
+ DEG_relations_tag_update(G.main);
}
/* return the action */
@@ -1618,7 +1620,7 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
/* delete F-Curve completely */
if (can_delete) {
ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
changed = true;
}
}
@@ -1725,7 +1727,7 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op)
else
BKE_reportf(op->reports, RPT_ERROR, "No keyframes removed from Object '%s'", id->name + 2);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index ad08caba799..da206ac9a64 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -48,9 +48,10 @@
#include "BKE_main.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "ED_keyframing.h"
#include "ED_screen.h"
@@ -1049,7 +1050,7 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
Object *ob = (Object *)ksp->id;
// XXX: only object transforms?
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
}
default:
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index b213aca478f..5348298f57e 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../gpu
../../makesdna
../../makesrna
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 2d7a83f20c1..0d114206c6b 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -48,11 +48,12 @@
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -375,7 +376,7 @@ static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
BLI_freelistN(&bones_names);
/* since we renamed stuff... */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* copied from #rna_Bone_update_renamed */
/* redraw view */
@@ -425,7 +426,7 @@ static int armature_autoside_names_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* since we renamed stuff... */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 685f8227a47..1d63b3aee43 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -47,12 +47,15 @@
#include "BKE_animsys.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -400,12 +403,12 @@ int join_armature_exec(bContext *C, wmOperator *op)
}
/* Free the old object data */
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_object_base_free_and_unlink(bmain, scene, base->object);
}
}
CTX_DATA_END;
- DAG_relations_tag_update(bmain); /* because we removed object(s) */
+ DEG_relations_tag_update(bmain); /* because we removed object(s) */
ED_armature_from_edit(arm);
ED_armature_edit_free(arm);
@@ -579,6 +582,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
Object *oldob, *newob;
Base *oldbase, *newbase;
@@ -602,14 +606,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 = view_layer->basact;
oldob->mode &= ~OB_MODE_POSE;
//oldbase->flag &= ~OB_POSEMODE;
@@ -617,13 +625,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 */
- DAG_relations_tag_update(bmain);
+ newbase = ED_object_add_duplicate(bmain, scene, view_layer, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
+ DEG_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);
@@ -632,8 +640,8 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
/* 4) fix links before depsgraph flushes */ // err... or after?
separated_armature_fix_links(oldob, newob);
- DAG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */
- DAG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */
+ DEG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */
+ DEG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */
/* 5) restore original conditions */
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index fc295647ed5..b87942fed84 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -53,6 +53,8 @@
#include "ED_screen.h"
#include "ED_view3d.h"
+#include "DEG_depsgraph.h"
+
#include "armature_intern.h"
/* utility macros for storing a temp int in the bone (selection flag) */
@@ -98,7 +100,7 @@ void *get_bone_from_selectbuffer(
/* Determine what the current bone is */
if (obedit == NULL || base->object != obedit) {
/* no singular posemode, so check for correct object */
- if (base->selcol == (hitresult & 0xFFFF)) {
+ if (base->object->select_color == (hitresult & 0xFFFF)) {
bone = get_indexed_bone(base->object, hitresult);
if (findunsel)
@@ -166,21 +168,23 @@ void *get_bone_from_selectbuffer(
/* x and y are mouse coords (area space) */
void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel)
{
+ EvaluationContext eval_ctx;
ViewContext vc;
rcti rect;
unsigned int buffer[MAXPICKBUF];
short hits;
-
+
+ CTX_data_eval_ctx(C, &eval_ctx);
view3d_set_viewcontext(C, &vc);
// rect.xmin = ... mouseco!
rect.xmin = rect.xmax = xy[0];
rect.ymin = rect.ymax = xy[1];
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
+ hits = view3d_opengl_select(&eval_ctx, &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
if (hits > 0)
- return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel, true);
+ return get_bone_from_selectbuffer(vc.scene, vc.view_layer->basact, buffer, hits, findunsel, true);
return NULL;
}
@@ -291,7 +295,7 @@ static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits12, const
/* does bones and points */
/* note that BONE ROOT only gets drawn for root bones (or without IK) */
static EditBone *get_nearest_editbonepoint(
- ViewContext *vc, const int mval[2],
+ const EvaluationContext *eval_ctx, ViewContext *vc, const int mval[2],
ListBase *edbo, bool findunsel, bool use_cycle, int *r_selmask)
{
bArmature *arm = (bArmature *)vc->obedit->data;
@@ -344,7 +348,7 @@ static EditBone *get_nearest_editbonepoint(
view3d_opengl_select_cache_begin();
BLI_rcti_init_pt_radius(&rect, mval, 12);
- hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
+ hits12 = view3d_opengl_select(eval_ctx, vc, buffer, MAXPICKBUF, &rect, select_mode);
if (hits12 == 1) {
hits = selectbuffer_ret_hits_12(buffer, hits12);
goto cache_end;
@@ -354,7 +358,7 @@ static EditBone *get_nearest_editbonepoint(
offs = 4 * hits12;
BLI_rcti_init_pt_radius(&rect, mval, 5);
- hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
+ hits5 = view3d_opengl_select(eval_ctx, vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
if (hits5 == 1) {
hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
@@ -482,17 +486,19 @@ bool ED_armature_select_pick(bContext *C, const int mval[2], bool extend, bool d
{
Object *obedit = CTX_data_edit_object(C);
bArmature *arm = obedit->data;
+ EvaluationContext eval_ctx;
ViewContext vc;
EditBone *nearBone = NULL;
int selmask;
+ CTX_data_eval_ctx(C, &eval_ctx);
view3d_set_viewcontext(C, &vc);
-
+
if (BIF_sk_selectStroke(C, mval, extend)) {
return true;
}
- nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, true, true, &selmask);
+ nearBone = get_nearest_editbonepoint(&eval_ctx, &vc, mval, arm->edbo, true, true, &selmask);
if (nearBone) {
if (!extend && !deselect && !toggle) {
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index e8d41f722d7..72b4837c1b8 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -43,12 +43,15 @@
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_object_deform.h"
#include "BKE_report.h"
#include "BKE_subsurf.h"
#include "BKE_modifier.h"
+#include "DEG_depsgraph.h"
+
#include "ED_armature.h"
#include "ED_mesh.h"
@@ -247,8 +250,9 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
}
}
-static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, Object *par,
- int heat, const bool mirror)
+static void add_verts_to_dgroups(
+ ReportList *reports, const EvaluationContext *eval_ctx, Scene *scene, Object *ob, Object *par,
+ int heat, const bool mirror)
{
/* This functions implements the automatic computation of vertex group
* weights, either through envelopes or using a heat equilibrium.
@@ -372,7 +376,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
if (wpmode) {
/* if in weight paint mode, use final verts from derivedmesh */
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH);
if (dm->foreachMappedVert) {
mesh_get_mapped_verts_coords(dm, verts, mesh->totvert);
@@ -424,8 +428,9 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
MEM_freeN(verts);
}
-void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, Object *par,
- const int mode, const bool mirror)
+void create_vgroups_from_armature(
+ ReportList *reports, const EvaluationContext *eval_ctx, Scene *scene, Object *ob, Object *par,
+ const int mode, const bool mirror)
{
/* Lets try to create some vertex groups
* based on the bones of the parent armature.
@@ -451,6 +456,6 @@ void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob,
* that are populated with the vertices for which the
* bone is closest.
*/
- add_verts_to_dgroups(reports, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror);
+ add_verts_to_dgroups(reports, eval_ctx, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror);
}
}
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index a55264bd020..f27c4fdd96f 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -39,11 +39,12 @@
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
+#include "DEG_depsgraph.h"
+
#include "ED_armature.h"
#include "ED_util.h"
@@ -674,7 +675,7 @@ void ED_armature_from_edit(bArmature *arm)
}
}
- DAG_id_tag_update(&arm->id, 0);
+ DEG_id_tag_update(&arm->id, 0);
}
void ED_armature_edit_free(struct bArmature *arm)
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index bba486bc65c..4dd8e4bd6fa 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -33,6 +33,7 @@
#include "BKE_context.h"
#include "BKE_sketch.h"
+#include "BKE_layer.h"
#include "RNA_define.h"
#include "RNA_access.h"
@@ -49,10 +50,16 @@
#include "ED_transform.h"
#include "ED_transform_snap_object_context.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
#include "GPU_select.h"
+#include "GPU_matrix.h"
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
typedef int (*GestureDetectFct)(bContext *, SK_Gesture *, SK_Sketch *);
typedef void (*GestureApplyFct)(bContext *, SK_Gesture *, SK_Sketch *);
@@ -140,9 +147,8 @@ static RigGraph *TEMPLATE_RIGG = NULL;
void BIF_makeListTemplates(const bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
- Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
ToolSettings *ts = CTX_data_tool_settings(C);
- Base *base;
int index = 0;
if (TEMPLATES_HASH != NULL) {
@@ -152,9 +158,8 @@ void BIF_makeListTemplates(const bContext *C)
TEMPLATES_HASH = BLI_ghash_int_new("makeListTemplates gh");
TEMPLATES_CURRENT = 0;
- for (base = FIRSTBASE; base; base = base->next) {
- Object *ob = base->object;
-
+ FOREACH_OBJECT(view_layer, ob)
+ {
if (ob != obedit && ob->type == OB_ARMATURE) {
index++;
BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob);
@@ -164,6 +169,7 @@ void BIF_makeListTemplates(const bContext *C)
}
}
}
+ FOREACH_OBJECT_END
}
#if 0 /* UNUSED */
@@ -420,7 +426,6 @@ static void sk_retargetStroke(bContext *C, SK_Stroke *stk)
}
/**************************************************************/
-
static void sk_cancelStroke(SK_Sketch *sketch)
{
if (sketch->active_stroke != NULL) {
@@ -435,17 +440,33 @@ static float sk_clampPointSize(SK_Point *pt, float size)
return max_ff(size * pt->size, size / 2);
}
-static void sk_drawPoint(GLUquadric *quad, SK_Point *pt, float size)
+static void sk_drawPoint(SK_Point *pt, float size, float color[4])
{
- glTranslate3fv(pt->p);
- gluSphere(quad, sk_clampPointSize(pt, size), 8, 8);
+ Gwn_Batch *batch = NULL;
+
+ gpuTranslate3fv(pt->p);
+
+ gpuPushMatrix();
+
+ gpuScaleUniform(sk_clampPointSize(pt, size));
+
+ batch = GPU_batch_preset_sphere(0);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ GWN_batch_uniform_4fv(batch, "color", color);
+
+ GWN_batch_draw(batch);
+
+ gpuPopMatrix();
}
-static void sk_drawEdge(GLUquadric *quad, SK_Point *pt0, SK_Point *pt1, float size)
+static void sk_drawEdge(SK_Point *pt0, SK_Point *pt1, float size, float color[4])
{
- float vec1[3], vec2[3] = {0, 0, 1}, axis[3];
+ float vec1[3], vec2[3] = { 0, 0, 1 }, axis[3];
float angle, length;
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
sub_v3_v3v3(vec1, pt1->p, pt0->p);
length = normalize_v3(vec1);
cross_v3_v3v3(axis, vec2, vec1);
@@ -454,19 +475,26 @@ static void sk_drawEdge(GLUquadric *quad, SK_Point *pt0, SK_Point *pt1, float si
axis[1] = 1;
}
- angle = angle_normalized_v3v3(vec2, vec1);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
- glRotate3fv(angle * (float)(180.0 / M_PI) + 180.0f, axis);
+ angle = angle_normalized_v3v3(vec2, vec1);
+ gpuRotate3fv(angle * (float)(180.0 / M_PI) + 180.0f, axis);
+ imm_draw_cylinder_fill_3d(pos, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8);
- gluCylinder(quad, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8);
+ immUnbindProgram();
}
-static void sk_drawNormal(GLUquadric *quad, SK_Point *pt, float size, float height)
+static void sk_drawNormal(SK_Point *pt, float size, float height)
{
- float vec2[3] = {0, 0, 1}, axis[3];
+ float vec2[3] = { 0, 0, 1 }, axis[3];
float angle;
-
- glPushMatrix();
+ float color[3] = { 0.0f, 1.0f, 1.0f };
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ gpuPushMatrix();
cross_v3_v3v3(axis, vec2, pt->no);
@@ -474,41 +502,44 @@ static void sk_drawNormal(GLUquadric *quad, SK_Point *pt, float size, float heig
axis[1] = 1;
}
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+
angle = angle_normalized_v3v3(vec2, pt->no);
+ gpuRotate3fv(angle * (float)(180.0 / M_PI), axis);
- glRotate3fv(angle * (float)(180.0 / M_PI), axis);
+ imm_draw_cylinder_fill_3d(pos, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2);
- glColor3f(0, 1, 1);
- gluCylinder(quad, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2);
+ immUnbindProgram();
- glPopMatrix();
+ gpuPopMatrix();
}
static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end)
{
float rgb[3];
+ float zero_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
int i;
- GLUquadric *quad = gluNewQuadric();
- gluQuadricNormals(quad, GLU_SMOOTH);
if (id != -1) {
GPU_select_load_id(id);
for (i = 0; i < stk->nb_points; i++) {
- glPushMatrix();
+ gpuPushMatrix();
- sk_drawPoint(quad, stk->points + i, 0.1);
+ sk_drawPoint(stk->points + i, 0.1, zero_color);
if (i > 0) {
- sk_drawEdge(quad, stk->points + i - 1, stk->points + i, 0.1);
+ sk_drawEdge(stk->points + i - 1, stk->points + i, 0.1, zero_color);
}
- glPopMatrix();
+ gpuPopMatrix();
}
}
else {
- float d_rgb[3] = {1, 1, 1};
+ float d_rgb[3] = { 1, 1, 1 };
+ float tmp_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
copy_v3_v3(rgb, color);
sub_v3_v3(d_rgb, rgb);
@@ -517,48 +548,44 @@ static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int
for (i = 0; i < stk->nb_points; i++) {
SK_Point *pt = stk->points + i;
- glPushMatrix();
+ gpuPushMatrix();
if (pt->type == PT_EXACT) {
- glColor3f(0, 0, 0);
- sk_drawPoint(quad, pt, 0.15);
- sk_drawNormal(quad, pt, 0.05, 0.9);
+ sk_drawPoint(pt, 0.15, zero_color);
+ sk_drawNormal(pt, 0.05, 0.9);
}
if (i >= start && i <= end) {
- glColor3f(0.3, 0.3, 0.3);
+ copy_v4_fl4(tmp_color, 0.3f, 0.3f, 0.3f, 1.0f);
}
else {
- glColor3fv(rgb);
+ copy_v4_fl4(tmp_color, rgb[0], rgb[1], rgb[2], 1.0f);
}
if (pt->type != PT_EXACT) {
-
- sk_drawPoint(quad, pt, 0.1);
+ sk_drawPoint(pt, 0.1, tmp_color);
}
if (i > 0) {
- sk_drawEdge(quad, pt - 1, pt, 0.1);
+ sk_drawEdge(pt - 1, pt, 0.1, tmp_color);
}
- glPopMatrix();
+ gpuPopMatrix();
add_v3_v3(rgb, d_rgb);
}
}
- gluDeleteQuadric(quad);
}
static void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *iter, NextSubdivisionFunc next_subdividion)
{
SK_Stroke *stk = ((SK_StrokeIterator *)iter)->stroke;
float head[3], tail[3];
+ float color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
int bone_start = 0;
int end = iter->length;
int index;
- GLUquadric *quad = gluNewQuadric();
- gluQuadricNormals(quad, GLU_SMOOTH);
iter->head(iter);
copy_v3_v3(head, iter->p);
@@ -567,22 +594,19 @@ static void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *ite
while (index != -1) {
SK_Point *pt = stk->points + index;
- glPushMatrix();
+ gpuPushMatrix();
- glColor3f(0, 1, 0);
- sk_drawPoint(quad, pt, 0.15);
+ sk_drawPoint(pt, 0.15, color);
- sk_drawNormal(quad, pt, 0.05, 0.9);
+ sk_drawNormal(pt, 0.05, 0.9);
- glPopMatrix();
+ gpuPopMatrix();
copy_v3_v3(head, tail);
bone_start = index; // start next bone from current index
index = next_subdividion(toolsettings, iter, bone_start, end, head, tail);
}
-
- gluDeleteQuadric(quad);
}
static void sk_drawStrokeSubdivision(ToolSettings *toolsettings, SK_Stroke *stk)
@@ -974,7 +998,7 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
* 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_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
CTX_wm_region(C), CTX_wm_view3d(C));
float mvalf[2] = {UNPACK2(dd->mval)};
@@ -1900,16 +1924,18 @@ static void sk_applyGesture(bContext *C, SK_Sketch *sketch)
static bool sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], const bool extend)
{
+ EvaluationContext eval_ctx;
ViewContext vc;
rcti rect;
unsigned int buffer[MAXPICKBUF];
short hits;
+ CTX_data_eval_ctx(C, &eval_ctx);
view3d_set_viewcontext(C, &vc);
BLI_rcti_init_pt_radius(&rect, mval, 5);
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
+ hits = view3d_opengl_select(&eval_ctx, &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
if (hits > 0) {
int besthitresult = -1;
@@ -1975,9 +2001,9 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch,
GPU_select_load_id(-1);
}
else {
- float selected_rgb[3] = {1, 0, 0};
- float unselected_rgb[3] = {1, 0.5, 0};
-
+ float selected_rgb[3] = { 1, 0, 0 };
+ float unselected_rgb[3] = { 1, 0.5, 0 };
+ float tmp_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
for (stk = sketch->strokes.first; stk; stk = stk->next) {
int start = -1;
int end = -1;
@@ -2001,75 +2027,37 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch,
}
if (last != NULL) {
- GLUquadric *quad = gluNewQuadric();
- gluQuadricNormals(quad, GLU_SMOOTH);
-
- glPushMatrix();
+ gpuPushMatrix();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
switch (sketch->next_point.mode) {
case PT_SNAP:
- glColor3f(0, 1, 0);
+ copy_v4_fl4(tmp_color, 0.0f, 1.0f, 0.0f, 1.0f);
break;
case PT_PROJECT:
- glColor3f(0, 0, 0);
+ copy_v4_fl4(tmp_color, 0.0f, 0.0f, 0.0f, 1.0f);
break;
}
- sk_drawPoint(quad, &sketch->next_point, 0.1);
+ sk_drawPoint(&sketch->next_point, 0.1, tmp_color);
- glColor4f(selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3);
-
- sk_drawEdge(quad, last, &sketch->next_point, 0.1);
+ copy_v4_fl4(tmp_color, selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3);
+ sk_drawEdge(last, &sketch->next_point, 0.1f, tmp_color);
glDisable(GL_BLEND);
- glPopMatrix();
-
- gluDeleteQuadric(quad);
+ gpuPopMatrix();
}
}
}
-#if 0
- if (BLI_listbase_is_empty(&sketch->depth_peels) == false) {
- float colors[8][3] = {
- {1, 0, 0},
- {0, 1, 0},
- {0, 0, 1},
- {1, 1, 0},
- {1, 0, 1},
- {0, 1, 1},
- {1, 1, 1},
- {0, 0, 0}
- };
- DepthPeel *p;
- GLUquadric *quad = gluNewQuadric();
- gluQuadricNormals(quad, GLU_SMOOTH);
-
- for (p = sketch->depth_peels.first; p; p = p->next)
- {
- int index = GET_INT_FROM_POINTER(p->ob);
- index = (index >> 5) & 7;
-
- glColor3fv(colors[index]);
- glPushMatrix();
- glTranslate3fv(p->p);
- gluSphere(quad, 0.02, 8, 8);
- glPopMatrix();
- }
-
- gluDeleteQuadric(quad);
- }
-#endif
-
glDisable(GL_DEPTH_TEST);
/* only draw gesture in active area */
if (sketch->gesture != NULL /* && area_is_active_area(G.vd->area) */) {
- float gesture_rgb[3] = {0, 0.5, 1};
+ float gesture_rgb[3] = { 0, 0.5, 1 };
sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1);
}
}
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index acbf23ecf82..74e29b2e8da 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -43,10 +43,11 @@
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -95,7 +96,8 @@ void ED_armature_enter_posemode(bContext *C, Base *base)
case OB_ARMATURE:
ob->restore_mode = ob->mode;
ob->mode |= OB_MODE_POSE;
-
+ /* Inform all CoW versions that we changed the mode. */
+ DEG_id_tag_update_ex(CTX_data_main(C), &ob->id, DEG_TAG_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL);
break;
@@ -114,7 +116,10 @@ void ED_armature_exit_posemode(bContext *C, Base *base)
ob->restore_mode = ob->mode;
ob->mode &= ~OB_MODE_POSE;
-
+
+ /* Inform all CoW versions that we changed the mode. */
+ DEG_id_tag_update_ex(CTX_data_main(C), &ob->id, DEG_TAG_COPY_ON_WRITE);
+
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
}
}
@@ -154,8 +159,11 @@ static bool pose_has_protected_selected(Object *ob, short warn)
*
* To be called from various tools that do incremental updates
*/
-void ED_pose_recalculate_paths(Scene *scene, Object *ob)
+void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
{
+ struct Main *bmain = CTX_data_main(C);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
ListBase targets = {NULL, NULL};
/* set flag to force recalc, then grab the relevant bones to target */
@@ -163,7 +171,7 @@ void ED_pose_recalculate_paths(Scene *scene, Object *ob)
animviz_get_object_motionpaths(ob, &targets);
/* recalculate paths, then free */
- animviz_calc_motionpaths(scene, &targets);
+ animviz_calc_motionpaths(&eval_ctx, bmain, scene, &targets);
BLI_freelistN(&targets);
}
@@ -226,7 +234,7 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op)
/* calculate the bones that now have motionpaths... */
/* TODO: only make for the selected bones? */
- ED_pose_recalculate_paths(scene, ob);
+ ED_pose_recalculate_paths(C, scene, ob);
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@ -282,7 +290,7 @@ static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(op))
/* calculate the bones that now have motionpaths... */
/* TODO: only make for the selected bones? */
- ED_pose_recalculate_paths(scene, ob);
+ ED_pose_recalculate_paths(C, scene, ob);
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@ -580,7 +588,7 @@ static void pose_copy_menu(Scene *scene)
BKE_pose_tag_recalc(bmain, ob->pose);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations
BIF_undo_push("Copy Pose Attributes");
@@ -613,7 +621,7 @@ static int pose_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
BLI_freelistN(&bones_names);
/* since we renamed stuff... */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@ -660,7 +668,7 @@ static int pose_autoside_names_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* since we renamed stuff... */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@ -709,7 +717,7 @@ static int pose_bone_rotmode_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* notifiers and updates */
- DAG_id_tag_update((ID *)ob, OB_RECALC_DATA);
+ DEG_id_tag_update((ID *)ob, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
return OPERATOR_FINISHED;
@@ -1171,7 +1179,7 @@ static int pose_flip_quats_exec(bContext *C, wmOperator *UNUSED(op))
CTX_DATA_END;
/* notifiers and updates */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index ac38500c841..0dbe3ddaa0a 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -46,7 +46,6 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_armature.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
@@ -55,6 +54,8 @@
#include "BKE_context.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -1067,6 +1068,9 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData
static void poselib_preview_apply(bContext *C, wmOperator *op)
{
tPoseLib_PreviewData *pld = (tPoseLib_PreviewData *)op->customdata;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
/* only recalc pose (and its dependencies) if pose has changed */
if (pld->redraw == PL_PREVIEW_REDRAWALL) {
@@ -1089,9 +1093,9 @@ static void poselib_preview_apply(bContext *C, wmOperator *op)
*/
// FIXME: shouldn't this use the builtin stuff?
if ((pld->arm->flag & ARM_DELAYDEFORM) == 0)
- DAG_id_tag_update(&pld->ob->id, OB_RECALC_DATA); /* sets recalc flags */
+ DEG_id_tag_update(&pld->ob->id, OB_RECALC_DATA); /* sets recalc flags */
else
- BKE_pose_where_is(pld->scene, pld->ob);
+ BKE_pose_where_is(&eval_ctx, pld->scene, pld->ob);
}
/* do header print - if interactively previewing */
@@ -1582,6 +1586,9 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op)
bArmature *arm = pld->arm;
bAction *act = pld->act;
TimeMarker *marker = pld->marker;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
/* redraw the header so that it doesn't show any of our stuff anymore */
ED_area_headerprint(pld->sa, NULL);
@@ -1597,9 +1604,9 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op)
* - note: code copied from transform_generics.c -> recalcData()
*/
if ((arm->flag & ARM_DELAYDEFORM) == 0)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
else
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(&eval_ctx, scene, ob);
}
else if (pld->state == PL_PREVIEW_CONFIRM) {
/* tag poses as appropriate */
@@ -1610,14 +1617,14 @@ static void poselib_preview_cleanup(bContext *C, wmOperator *op)
action_set_activemarker(act, marker, NULL);
/* Update event for pose and deformation children */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* updates */
if (IS_AUTOKEY_MODE(scene, NORMAL)) {
//remake_action_ipos(ob->action);
}
else
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(&eval_ctx, scene, ob);
}
/* Request final redraw of the view. */
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 401f180385d..f808f09f1f4 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -43,10 +43,11 @@
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -122,7 +123,7 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
* (see rna_Bone_select_update() in rna_armature.c for details)
*/
if (arm->flag & ARM_HAS_VIZ_DEPS) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
/* send necessary notifiers */
@@ -133,7 +134,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 */
bool ED_do_pose_selectbuffer(
- Scene *scene, Base *base, const unsigned int *buffer, short hits,
+ Scene *scene, ViewLayer *view_layer, Base *base, const unsigned int *buffer, short hits,
bool extend, bool deselect, bool toggle, bool do_nearest)
{
Object *ob = base->object;
@@ -145,7 +146,7 @@ bool ED_do_pose_selectbuffer(
/* if the bone cannot be affected, don't do anything */
if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
- Object *ob_act = OBACT;
+ Object *ob_act = OBACT(view_layer);
bArmature *arm = ob->data;
/* since we do unified select, we don't shift+select a bone if the
@@ -197,7 +198,7 @@ bool ED_do_pose_selectbuffer(
if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
if (nearBone == arm->act_bone) {
ED_vgroup_select_by_name(ob_act, nearBone->name);
- DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
}
}
/* if there are some dependencies for visualizing armature state
@@ -207,7 +208,7 @@ bool ED_do_pose_selectbuffer(
/* NOTE: ob not ob_act here is intentional - it's the source of the
* bones being selected [T37247]
*/
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
}
@@ -314,7 +315,7 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve
if (arm->flag & ARM_HAS_VIZ_DEPS) {
/* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
return OPERATOR_FINISHED;
@@ -370,7 +371,7 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
/* weightpaint or mask modifiers need depsgraph updates */
if (multipaint || (arm->flag & ARM_HAS_VIZ_DEPS)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
return OPERATOR_FINISHED;
@@ -422,7 +423,7 @@ static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
if (arm->flag & ARM_HAS_VIZ_DEPS) {
/* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
return OPERATOR_FINISHED;
@@ -489,7 +490,7 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op
if (arm->flag & ARM_HAS_VIZ_DEPS) {
/* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
return OPERATOR_FINISHED;
@@ -583,7 +584,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
if (arm->flag & ARM_HAS_VIZ_DEPS) {
/* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
return OPERATOR_FINISHED;
@@ -828,7 +829,7 @@ static int pose_select_grouped_exec(bContext *C, wmOperator *op)
if (arm->flag & ARM_HAS_VIZ_DEPS) {
/* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
/* report done status */
@@ -921,7 +922,7 @@ static int pose_select_mirror_exec(bContext *C, wmOperator *op)
/* in weightpaint we select the associated vertex group too */
if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
ED_vgroup_select_by_name(ob_act, pchan_mirror_act->name);
- DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
}
}
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index 3707b914ecb..18d6408f026 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -45,13 +45,14 @@
#include "BKE_blender_copybuffer.h"
#include "BKE_context.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -70,9 +71,12 @@
/* Pose Apply */
/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
-static void applyarmature_fix_boneparents(Scene *scene, Object *armob)
+static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Object *armob)
{
Object workob, *ob;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
/* go through all objects in database */
for (ob = G.main->object.first; ob; ob = ob->id.next) {
@@ -83,7 +87,7 @@ static void applyarmature_fix_boneparents(Scene *scene, Object *armob)
*/
BKE_object_apply_mat4(ob, ob->obmat, false, false);
- BKE_object_workob_calc_parent(scene, ob, &workob);
+ BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
}
@@ -94,10 +98,13 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
+ EvaluationContext eval_ctx;
bArmature *arm = BKE_armature_from_object(ob);
bPose *pose;
bPoseChannel *pchan;
EditBone *curbone;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
/* don't check if editmode (should be done by caller) */
if (ob->type != OB_ARMATURE)
@@ -167,10 +174,10 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
ED_armature_edit_free(arm);
/* flush positions of posebones */
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(&eval_ctx, scene, ob);
/* fix parenting of objects which are bone-parented */
- applyarmature_fix_boneparents(scene, ob);
+ applyarmature_fix_boneparents(C, scene, ob);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@ -225,7 +232,7 @@ static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
}
CTX_DATA_END;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@ -543,11 +550,11 @@ static int pose_paste_exec(bContext *C, wmOperator *op)
BKE_main_free(tmp_bmain);
/* Update event for pose and deformation children. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* Recalculate paths if any of the bones have paths... */
if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
- ED_pose_recalculate_paths(scene, ob);
+ ED_pose_recalculate_paths(C, scene, ob);
}
/* Notifiers for updates, */
@@ -774,10 +781,10 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
/* now recalculate paths */
if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
- ED_pose_recalculate_paths(scene, ob);
+ ED_pose_recalculate_paths(C, scene, ob);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
@@ -924,7 +931,7 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
}
/* notifiers and updates */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index f80afdd169e..acb9363cf10 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -39,11 +39,12 @@
#include "BKE_action.h"
#include "BKE_armature.h"
-#include "BKE_depsgraph.h"
#include "BKE_idprop.h"
#include "BKE_context.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "WM_api.h"
@@ -183,15 +184,18 @@ void poseAnim_mapping_free(ListBase *pfLinks)
void poseAnim_mapping_refresh(bContext *C, Scene *scene, Object *ob)
{
bArmature *arm = (bArmature *)ob->data;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
/* old optimize trick... this enforces to bypass the depgraph
* - note: code copied from transform_generics.c -> recalcData()
*/
/* FIXME: shouldn't this use the builtin stuff? */
if ((arm->flag & ARM_DELAYDEFORM) == 0)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
else
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(&eval_ctx, scene, ob);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
@@ -266,7 +270,7 @@ void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, Object *ob, ListBa
*/
if (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) {
//ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear
- ED_pose_recalculate_paths(scene, ob);
+ ED_pose_recalculate_paths(C, scene, ob);
}
}
}
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index 2bcf3099104..0eb44085bae 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -3199,237 +3199,3 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C)
return rg;
#endif
}
-
-#if 0
-
-ReebGraph *BIF_ReebGraphFromEditMesh(void)
-{
- EditMesh *em = G.editMesh;
- EdgeIndex indexed_edges;
- VertexData *data;
- ReebGraph *rg = NULL;
-
- if (em == NULL)
- return NULL;
-
- data = allocVertexData(em);
-
- buildIndexedEdges(em, &indexed_edges);
-
- if (weightFromDistance(em, &indexed_edges) == 0)
- {
- error("No selected vertex\n");
- freeEdgeIndex(&indexed_edges);
- freeEdgeIndex(&indexed_edges);
- return NULL;
- }
-
- renormalizeWeight(em, 1.0f);
-
- if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC)
- {
- weightToHarmonic(em, &indexed_edges);
- }
-
- freeEdgeIndex(&indexed_edges);
-
-#ifdef DEBUG_REEB
-// weightToVCol(em, 1);
-#endif
-
- rg = generateReebGraph(em, G.scene->toolsettings->skgen_resolution);
-
-
- /* Remove arcs without embedding */
- filterNullReebGraph(rg);
-
- /* smart filter and loop filter on basic level */
- filterGraph(rg, SKGEN_FILTER_SMART, 0, 0);
-
- repositionNodes(rg);
-
- /* Filtering might have created degree 2 nodes, so remove them */
- removeNormalNodes(rg);
-
- joinSubgraphs(rg, 1.0);
-
- BLI_buildAdjacencyList((BGraph *)rg);
-
- /* calc length before copy, so we have same length on all levels */
- BLI_calcGraphLength((BGraph *)rg);
-
- filterGraph(rg, G.scene->toolsettings->skgen_options, G.scene->toolsettings->skgen_threshold_internal, G.scene->toolsettings->skgen_threshold_external);
-
- finalizeGraph(rg, G.scene->toolsettings->skgen_postpro_passes, G.scene->toolsettings->skgen_postpro);
-
-#ifdef DEBUG_REEB
- REEB_exportGraph(rg, -1);
-
- arcToVCol(rg, em, 0);
- //angleToVCol(em, 1);
-#endif
-
- printf("DONE\n");
- printf("%i subgraphs\n", BLI_FlagSubgraphs((BGraph *)rg));
-
- MEM_freeN(data);
-
- return rg;
-}
-
-void BIF_GlobalReebFree()
-{
- if (GLOBAL_RG != NULL)
- {
- REEB_freeGraph(GLOBAL_RG);
- GLOBAL_RG = NULL;
- }
-}
-
-void BIF_GlobalReebGraphFromEditMesh(void)
-{
- ReebGraph *rg;
-
- BIF_GlobalReebFree();
-
- rg = BIF_ReebGraphMultiFromEditMesh();
-
- GLOBAL_RG = rg;
-}
-
-void REEB_draw()
-{
- ReebGraph *rg;
- ReebArc *arc;
- int i = 0;
-
- if (GLOBAL_RG == NULL)
- {
- return;
- }
-
- if (GLOBAL_RG->link_up && G.scene->toolsettings->skgen_options & SKGEN_DISP_ORIG)
- {
- for (rg = GLOBAL_RG; rg->link_up; rg = rg->link_up) ;
- }
- else {
- i = G.scene->toolsettings->skgen_multi_level;
-
- for (rg = GLOBAL_RG; rg->multi_level != i && rg->link_up; rg = rg->link_up) ;
- }
-
- glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
-
- glDisable(GL_DEPTH_TEST);
- for (arc = rg->arcs.first; arc; arc = arc->next, i++)
- {
- ReebArcIterator arc_iter;
- BArcIterator *iter = (BArcIterator *)&arc_iter;
- float vec[3];
- char text[128];
- char *s = text;
-
- glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE) + 2);
- glColor3f(0, 0, 0);
- glBegin(GL_LINE_STRIP);
- glVertex3fv(arc->head->p);
-
- if (arc->bcount)
- {
- initArcIterator(iter, arc, arc->head);
- for (IT_next(iter); IT_stopped(iter) == 0; IT_next(iter))
- {
- glVertex3fv(iter->p);
- }
- }
-
- glVertex3fv(arc->tail->p);
- glEnd();
-
- glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE));
-
- if (arc->symmetry_level == 1)
- {
- glColor3f(1, 0, 0);
- }
- else if (arc->symmetry_flag == SYM_SIDE_POSITIVE || arc->symmetry_flag == SYM_SIDE_NEGATIVE)
- {
- glColor3f(1, 0.5f, 0);
- }
- else if (arc->symmetry_flag >= SYM_SIDE_RADIAL)
- {
- glColor3f(0.5f, 1, 0);
- }
- else {
- glColor3f(1, 1, 0);
- }
- glBegin(GL_LINE_STRIP);
- glVertex3fv(arc->head->p);
-
- if (arc->bcount)
- {
- initArcIterator(iter, arc, arc->head);
- for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter))
- {
- glVertex3fv(iter->p);
- }
- }
-
- glVertex3fv(arc->tail->p);
- glEnd();
-
-
- if (G.scene->toolsettings->skgen_options & SKGEN_DISP_EMBED)
- {
- glColor3f(1, 1, 1);
- glBegin(GL_POINTS);
- glVertex3fv(arc->head->p);
- glVertex3fv(arc->tail->p);
-
- glColor3f(0.5f, 0.5f, 1);
- if (arc->bcount)
- {
- initArcIterator(iter, arc, arc->head);
- for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter))
- {
- glVertex3fv(iter->p);
- }
- }
- glEnd();
- }
-
- if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX)
- {
- mid_v3_v3v3(vec, arc->head->p, arc->tail->p);
- s += sprintf(s, "%i (%i-%i-%i) ", i, arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group);
-
- if (G.scene->toolsettings->skgen_options & SKGEN_DISP_WEIGHT)
- {
- s += sprintf(s, "w:%0.3f ", arc->tail->weight - arc->head->weight);
- }
-
- if (G.scene->toolsettings->skgen_options & SKGEN_DISP_LENGTH)
- {
- s += sprintf(s, "l:%0.3f", arc->length);
- }
-
- glColor3f(0, 1, 0);
- glRasterPos3fv(vec);
- BMF_DrawString(G.fonts, text);
- }
-
- if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX)
- {
- sprintf(text, " %i", arc->head->index);
- glRasterPos3fv(arc->head->p);
- BMF_DrawString(G.fonts, text);
-
- sprintf(text, " %i", arc->tail->index);
- glRasterPos3fv(arc->tail->p);
- BMF_DrawString(G.fonts, text);
- }
- }
- glEnable(GL_DEPTH_TEST);
-}
-
-#endif
diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt
index 2f5b2ab6e87..ae5c0a13ced 100644
--- a/source/blender/editors/curve/CMakeLists.txt
+++ b/source/blender/editors/curve/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../gpu
../../makesdna
../../makesrna
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index fc363475608..79b63f36b76 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -45,11 +45,11 @@
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#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"
@@ -57,6 +57,9 @@
#include "BKE_action.h"
#include "BKE_modifier.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -1285,6 +1288,7 @@ static int separate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *oldob, *newob;
Base *oldbase, *newbase;
Curve *oldcu, *newcu;
@@ -1312,8 +1316,8 @@ 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 */
- DAG_relations_tag_update(bmain);
+ newbase = ED_object_add_duplicate(bmain, scene, view_layer, oldbase, 0); /* 0 = fully linked */
+ DEG_relations_tag_update(bmain);
newob = newbase->object;
newcu = newob->data = BKE_curve_copy(bmain, oldcu);
@@ -1332,8 +1336,8 @@ static int separate_exec(bContext *C, wmOperator *op)
ED_curve_editnurb_free(newob);
curve_delete_segments(oldob, true);
- DAG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */
- DAG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */
+ DEG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */
+ DEG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */
WM_event_add_notifier(C, NC_GEOM | ND_DATA, oldob->data);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
@@ -1381,7 +1385,7 @@ static int curve_split_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
}
else {
BKE_report(op->reports, RPT_ERROR, "Cannot split current selection");
@@ -2327,7 +2331,7 @@ static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
if (ED_curve_updateAnimPaths(obedit->data))
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -2375,7 +2379,7 @@ static int set_goal_weight_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -2428,7 +2432,7 @@ static int set_radius_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -2580,7 +2584,7 @@ static int smooth_exec(bContext *C, wmOperator *UNUSED(op))
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -2771,7 +2775,7 @@ static int curve_smooth_weight_exec(bContext *C, wmOperator *UNUSED(op))
curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight));
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -2799,7 +2803,7 @@ static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op))
curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius));
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -2827,7 +2831,7 @@ static int curve_smooth_tilt_exec(bContext *C, wmOperator *UNUSED(op))
curve_smooth_value(editnurb, offsetof(BezTriple, alfa), offsetof(BPoint, alfa));
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -2899,7 +2903,7 @@ static int hide_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
BKE_curve_nurb_vert_active_validate(obedit->data);
@@ -2962,7 +2966,7 @@ static int reveal_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -3383,7 +3387,7 @@ static int subdivide_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -3578,7 +3582,7 @@ static int set_spline_type_exec(bContext *C, wmOperator *op)
if (ED_curve_updateAnimPaths(obedit->data))
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
if (changed_size) {
@@ -3632,7 +3636,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op)
BKE_nurbList_handles_set(editnurb, RNA_enum_get(op->ptr, "type"));
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -3677,7 +3681,7 @@ static int curve_normals_make_consistent_exec(bContext *C, wmOperator *op)
BKE_nurbList_handles_recalculate(editnurb, calc_length, SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -4065,7 +4069,7 @@ static int merge_nurb(bContext *C, wmOperator *op)
BKE_curve_nurb_active_set(obedit->data, NULL);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -4272,7 +4276,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -4516,7 +4520,7 @@ static int spin_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -4971,7 +4975,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -5016,7 +5020,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const float mval[2] = {UNPACK2(event->mval)};
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), vc.scene, 0,
+ CTX_data_main(C), vc.scene, vc.view_layer, vc.engine_type, 0,
vc.ar, vc.v3d);
ED_transform_snap_object_project_view3d_mixed(
@@ -5126,7 +5130,7 @@ static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op))
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
}
return OPERATOR_FINISHED;
@@ -5225,7 +5229,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -5743,7 +5747,7 @@ static int curve_delete_exec(bContext *C, wmOperator *op)
if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return retval;
}
@@ -5887,7 +5891,7 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
}
return OPERATOR_FINISHED;
@@ -5963,7 +5967,7 @@ static int curve_decimate_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
}
return OPERATOR_FINISHED;
@@ -6008,7 +6012,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -6122,7 +6126,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
}
}
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_object_base_free_and_unlink(bmain, scene, base->object);
}
}
}
@@ -6134,9 +6138,9 @@ int join_curve_exec(bContext *C, wmOperator *op)
/* Account for mixed 2D/3D curves when joining */
BKE_curve_curve_dimension_update(cu);
- DAG_relations_tag_update(bmain); // because we removed object(s), call before editmode!
+ DEG_relations_tag_update(bmain); // because we removed object(s), call before editmode!
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
@@ -6176,7 +6180,7 @@ static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op))
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
@@ -6354,12 +6358,15 @@ static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Object *object = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
Curve *curve = (Curve *) object->data;
float min[3], max[3], size[3], loc[3];
int a;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (object->curve_cache == NULL) {
- BKE_displist_make_curveTypes(scene, object, false);
+ BKE_displist_make_curveTypes(&eval_ctx, scene, object, false);
}
INIT_MINMAX(min, max);
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index cc8e272d4f7..281f6c3c22e 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -42,9 +42,10 @@
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_library.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "WM_api.h"
@@ -502,7 +503,7 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
cu->flag |= CU_PATH | CU_3D;
}
else {
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
}
}
else { /* adding surface */
@@ -512,7 +513,7 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
newob = true;
}
else {
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
}
}
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 4602945d11c..5a71cc39f80 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -33,10 +33,11 @@
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -46,7 +47,11 @@
#include "ED_curve.h"
#include "BIF_gl.h"
-#include "BIF_glutil.h"
+
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#include "curve_intern.h"
@@ -128,7 +133,6 @@ struct CurveDrawData {
} prev;
ViewContext vc;
- bglMats mats;
enum {
CURVE_DRAW_IDLE = 0,
CURVE_DRAW_PAINTING = 1,
@@ -214,7 +218,7 @@ static bool stroke_elem_project(
{
const double depth = (double)ED_view3d_depth_read_cached(&cdd->vc, mval_i);
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
- if (ED_view3d_depth_unproject(ar, &cdd->mats, mval_i, depth, r_location_world)) {
+ if (ED_view3d_depth_unproject(ar, mval_i, depth, r_location_world)) {
is_location_world_set = true;
if (r_normal_world) {
zero_v3(r_normal_world);
@@ -223,7 +227,7 @@ static bool stroke_elem_project(
if (surface_offset != 0.0f) {
const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius;
float normal[3];
- if (ED_view3d_depth_read_cached_normal(&cdd->vc, &cdd->mats, mval_i, normal)) {
+ if (ED_view3d_depth_read_cached_normal(&cdd->vc, mval_i, normal)) {
madd_v3_v3fl(r_location_world, normal, offset * surface_offset);
if (r_normal_world) {
copy_v3_v3(r_normal_world, normal);
@@ -369,39 +373,43 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
Object *obedit = cdd->vc.obedit;
Curve *cu = obedit->data;
- UI_ThemeColor(TH_WIRE);
-
if (cu->ext2 > 0.0f) {
- GLUquadricObj *qobj = gluNewQuadric();
-
- gluQuadricDrawStyle(qobj, GLU_FILL);
-
BLI_mempool_iter iter;
const struct StrokeElem *selem;
const float location_zero[3] = {0};
const float *location_prev = location_zero;
+ float color[3];
+ UI_GetThemeColor3fv(TH_WIRE, color);
+
+ Gwn_Batch *sphere = GPU_batch_preset_sphere(0);
+ GWN_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
+ GWN_batch_uniform_3fv(sphere, "color", color);
+
/* scale to edit-mode space */
- glPushMatrix();
- glMultMatrixf(obedit->obmat);
+ gpuPushMatrix();
+ gpuMultMatrix(obedit->obmat);
BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
- glTranslatef(
+ gpuTranslate3f(
selem->location_local[0] - location_prev[0],
selem->location_local[1] - location_prev[1],
selem->location_local[2] - location_prev[2]);
location_prev = selem->location_local;
+
const float radius = stroke_elem_radius(cdd, selem);
- gluSphere(qobj, radius, 12, 8);
+
+ gpuPushMatrix();
+ gpuScaleUniform(radius);
+ GWN_batch_draw(sphere);
+ gpuPopMatrix();
location_prev = selem->location_local;
}
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
+ gpuPopMatrix();
}
if (stroke_len > 1) {
@@ -418,30 +426,45 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
}
{
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_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(GWN_PRIM_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(GWN_PRIM_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]);
+ }
- glDisableClientState(GL_VERTEX_ARRAY);
+ immEnd();
+
+ if (v3d->zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ }
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
+
+ immUnbindProgram();
}
MEM_freeN(coord_array);
@@ -531,7 +554,7 @@ static void curve_draw_event_add_first(wmOperator *op, const wmEvent *event)
CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW,
CURVE_PAINT_SURFACE_PLANE_NORMAL_SURFACE))
{
- if (ED_view3d_depth_read_cached_normal(&cdd->vc, &cdd->mats, event->mval, normal)) {
+ if (ED_view3d_depth_read_cached_normal(&cdd->vc, event->mval, normal)) {
if (cps->surface_plane == CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW) {
float cross_a[3], cross_b[3];
cross_v3_v3v3(cross_a, rv3d->viewinv[2], normal);
@@ -589,7 +612,9 @@ static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke)
}
}
else {
+ cdd->vc.depsgraph = CTX_data_depsgraph(C);
cdd->vc.scene = CTX_data_scene(C);
+ cdd->vc.view_layer = CTX_data_view_layer(C);
cdd->vc.obedit = CTX_data_edit_object(C);
}
@@ -1011,7 +1036,7 @@ static int curve_draw_exec(bContext *C, wmOperator *op)
cu->actvert = nu->pntsu - 1;
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
curve_draw_exit(op);
@@ -1066,12 +1091,13 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) &&
(v3d->drawtype > OB_WIRE))
{
- view3d_get_transformation(cdd->vc.ar, cdd->vc.rv3d, NULL, &cdd->mats);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
/* needed or else the draw matrix can be incorrect */
view3d_operator_needs_opengl(C);
- ED_view3d_autodist_init(cdd->vc.scene, cdd->vc.ar, cdd->vc.v3d, 0);
+ ED_view3d_autodist_init(&eval_ctx, cdd->vc.depsgraph, cdd->vc.ar, cdd->vc.v3d, 0);
if (cdd->vc.rv3d->depths) {
cdd->vc.rv3d->depths->damaged = true;
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 4c5642493fa..cbb5abf1309 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -49,13 +49,14 @@
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_font.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -254,7 +255,7 @@ static void text_update_edited(bContext *C, Object *obedit, int mode)
/* run update first since it can move the cursor */
if (mode == FO_EDIT) {
/* re-tesselllate */
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
}
else {
/* depsgraph runs above, but since we're not tagging for update, call direct */
@@ -273,6 +274,8 @@ static void text_update_edited(bContext *C, Object *obedit, int mode)
}
}
+ BKE_curve_batch_cache_dirty(cu, BKE_CURVE_BATCH_DIRTY_SELECT);
+
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
}
@@ -420,6 +423,8 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EvaluationContext eval_ctx;
Curve *cu;
Object *obedit;
Base *base;
@@ -429,13 +434,15 @@ 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;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ obedit = BKE_object_add(bmain, scene, view_layer, OB_FONT, NULL);
+ base = view_layer->basact;
/* seems to assume view align ? TODO - look into this, could be an operator option */
ED_object_base_init_transform(C, base, NULL, rot);
- BKE_object_where_is_calc(scene, obedit);
+ BKE_object_where_is_calc(&eval_ctx, scene, obedit);
add_v3_v3(obedit->loc, offset);
@@ -582,7 +589,7 @@ static int set_style(bContext *C, const int style, const bool clear)
ef->textbufinfo[i].flag |= style;
}
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 3d5317b2ebd..587c25031ab 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../imbuf
../../gpu
../../makesdna
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 100e2dc8295..1674091f138 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -60,9 +60,11 @@
#include "WM_api.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
+
#include "ED_gpencil.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -92,99 +94,194 @@ typedef enum eDrawStrokeFlags {
/* thickness above which we should use special drawing */
+#if 0
#define GP_DRAWTHICKNESS_SPECIAL 3
+#endif
+
+/* conversion utility (float --> normalized unsigned byte) */
+#define F2UB(x) (unsigned char)(255.0f * x)
/* ----- Tool Buffer Drawing ------ */
-/* helper function to set color of buffer point */
-static void gp_set_tpoint_color(tGPspoint *pt, float ink[4])
+/* helper functions to set color of buffer point */
+
+static void gp_set_tpoint_varying_color(const tGPspoint *pt, const float ink[4], unsigned attrib_id)
{
float alpha = ink[3] * pt->strength;
CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
- glColor4f(ink[0], ink[1], ink[2], alpha);
+ immAttrib4ub(attrib_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha));
}
-/* helper function to set color of point */
-static void gp_set_point_color(bGPDspoint *pt, float ink[4])
+static void gp_set_point_uniform_color(const bGPDspoint *pt, const float ink[4])
{
float alpha = ink[3] * pt->strength;
CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
- glColor4f(ink[0], ink[1], ink[2], alpha);
+ immUniformColor3fvAlpha(ink, alpha);
}
-/* helper function to set color and point */
-static void gp_set_color_and_tpoint(tGPspoint *pt, float ink[4])
+static void gp_set_point_varying_color(const bGPDspoint *pt, const float ink[4], unsigned attrib_id)
{
- gp_set_tpoint_color(pt, ink);
- glVertex2iv(&pt->x);
+ float alpha = ink[3] * pt->strength;
+ CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
+ immAttrib4ub(attrib_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha));
+}
+
+/* draw fills for buffer stroke */
+static void gp_draw_stroke_buffer_fill(const tGPspoint *points, int totpoints, float ink[4])
+{
+ if (totpoints < 3) {
+ return;
+ }
+ int tot_triangles = totpoints - 2;
+ /* allocate memory for temporary areas */
+ unsigned int(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * tot_triangles, "GP Stroke buffer temp triangulation");
+ float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, "GP Stroke buffer temp 2d points");
+
+ /* Convert points to array and triangulate
+ * Here a cache is not used because while drawing the information changes all the time, so the cache
+ * would be recalculated constantly, so it is better to do direct calculation for each function call
+ */
+ for (int i = 0; i < totpoints; i++) {
+ const tGPspoint *pt = &points[i];
+ points2d[i][0] = pt->x;
+ points2d[i][1] = pt->y;
+ }
+ BLI_polyfill_calc((const float(*)[2])points2d, (unsigned int)totpoints, 0, (unsigned int(*)[3])tmp_triangles);
+
+ /* draw triangulation data */
+ if (tot_triangles > 0) {
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ /* Draw all triangles for filling the polygon */
+ immBegin(GWN_PRIM_TRIS, tot_triangles * 3);
+ /* TODO: use batch instead of immediate mode, to share vertices */
+
+ const tGPspoint *pt;
+ for (int i = 0; i < tot_triangles; i++) {
+ /* vertex 1 */
+ pt = &points[tmp_triangles[i][0]];
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immVertex2iv(pos, &pt->x);
+ /* vertex 2 */
+ pt = &points[tmp_triangles[i][1]];
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immVertex2iv(pos, &pt->x);
+ /* vertex 3 */
+ pt = &points[tmp_triangles[i][2]];
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immVertex2iv(pos, &pt->x);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
+
+ /* clear memory */
+ if (tmp_triangles) {
+ MEM_freeN(tmp_triangles);
+ }
+ if (points2d) {
+ MEM_freeN(points2d);
+ }
}
/* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */
-static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickness,
- short dflag, short sflag, float ink[4])
+static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short thickness,
+ short dflag, short sflag, float ink[4], float fill_ink[4])
{
- tGPspoint *pt;
- int i;
-
+ int draw_points = 0;
+
/* error checking */
if ((points == NULL) || (totpoints <= 0))
return;
-
+
/* check if buffer can be drawn */
if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
return;
-
+
+ if (sflag & GP_STROKE_ERASER) {
+ /* don't draw stroke at all! */
+ return;
+ }
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ const tGPspoint *pt = points;
+
if (totpoints == 1) {
/* if drawing a single point, draw it larger */
glPointSize((float)(thickness + 2) * points->pressure);
- glBegin(GL_POINTS);
-
- gp_set_color_and_tpoint(points, ink);
- glEnd();
- }
- else if (sflag & GP_STROKE_ERASER) {
- /* don't draw stroke at all! */
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
+ immBegin(GWN_PRIM_POINTS, 1);
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immVertex2iv(pos, &pt->x);
}
else {
float oldpressure = points[0].pressure;
-
+
/* draw stroke curve */
- if (G.debug & G_DEBUG) setlinestyle(2);
-
glLineWidth(max_ff(oldpressure * thickness, 1.0));
- glBegin(GL_LINE_STRIP);
-
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints);
+
+ /* TODO: implement this with a geometry shader to draw one continuous tapered stroke */
+
+ for (int i = 0; i < totpoints; i++, pt++) {
/* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
* and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
*/
if (fabsf(pt->pressure - oldpressure) > 0.2f) {
- glEnd();
+ /* need to have 2 points to avoid immEnd assert error */
+ if (draw_points < 2) {
+ gp_set_tpoint_varying_color(pt - 1, ink, color);
+ immVertex2iv(pos, &(pt - 1)->x);
+ }
+
+ immEnd();
+ draw_points = 0;
+
glLineWidth(max_ff(pt->pressure * thickness, 1.0f));
- glBegin(GL_LINE_STRIP);
-
+ immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints - i + 1);
+
/* need to roll-back one point to ensure that there are no gaps in the stroke */
if (i != 0) {
- gp_set_color_and_tpoint((pt - 1), ink);
+ gp_set_tpoint_varying_color(pt - 1, ink, color);
+ immVertex2iv(pos, &(pt - 1)->x);
+ ++draw_points;
}
-
- /* now the point we want... */
- gp_set_color_and_tpoint(pt, ink);
-
- oldpressure = pt->pressure;
- }
- else {
- gp_set_color_and_tpoint(pt, ink);
+
+ oldpressure = pt->pressure; /* reset our threshold */
}
+
+ /* now the point we want */
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immVertex2iv(pos, &pt->x);
+ ++draw_points;
+ }
+ /* need to have 2 points to avoid immEnd assert error */
+ if (draw_points < 2) {
+ gp_set_tpoint_varying_color(pt - 1, ink, color);
+ immVertex2iv(pos, &(pt - 1)->x);
}
- glEnd();
+ }
+
+ immEnd();
+ immUnbindProgram();
- if (G.debug & G_DEBUG) setlinestyle(0);
+ // draw fill
+ if (fill_ink[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
+ gp_draw_stroke_buffer_fill(points, totpoints, fill_ink);
}
}
/* --------- 2D Stroke Drawing Helpers --------- */
/* change in parameter list */
-static void gp_calc_2d_stroke_fxy(float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
+static void gp_calc_2d_stroke_fxy(const float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
{
if (sflag & GP_STROKE_2DSPACE) {
r_co[0] = pt[0];
@@ -210,203 +307,141 @@ static void gp_calc_2d_stroke_fxy(float pt[3], short sflag, int offsx, int offsy
/* draw a 2D buffer stroke in "volumetric" style
* NOTE: the stroke buffer doesn't have any coordinate offsets/transforms
*/
-static void gp_draw_stroke_volumetric_buffer(tGPspoint *points, int totpoints, short thickness,
- short dflag, short UNUSED(sflag), float ink[4])
+static void gp_draw_stroke_volumetric_buffer(const tGPspoint *points, int totpoints, short thickness,
+ short dflag, const float ink[4])
{
- GLUquadricObj *qobj = gluNewQuadric();
- float modelview[4][4];
-
- tGPspoint *pt;
- int i;
-
/* error checking */
if ((points == NULL) || (totpoints <= 0))
return;
-
+
/* check if buffer can be drawn */
if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
return;
-
- /* get basic matrix - should be camera space (i.e "identity") */
- glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview);
-
- /* draw points */
- glPushMatrix();
-
- for (i = 0, pt = points; i < totpoints; i++, pt++) {
- /* set the transformed position */
- // TODO: scale should change based on zoom level, which requires proper translation mult too!
- modelview[3][0] = pt->x;
- modelview[3][1] = pt->y;
-
- glLoadMatrixf((float *)modelview);
-
- /* draw the disk using the current state... */
- gp_set_tpoint_color(pt, ink);
- gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1);
-
-
- modelview[3][0] = modelview[3][1] = 0.0f;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+ GPU_enable_program_point_size();
+ immBegin(GWN_PRIM_POINTS, totpoints);
+
+ const tGPspoint *pt = points;
+ for (int i = 0; i < totpoints; i++, pt++) {
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform (zoom level) */
+ immVertex2f(pos, pt->x, pt->y);
}
- glPopMatrix();
- gluDeleteQuadric(qobj);
+ immEnd();
+ immUnbindProgram();
+ GPU_disable_program_point_size();
}
/* draw a 2D strokes in "volumetric" style */
-static void gp_draw_stroke_volumetric_2d(bGPDspoint *points, int totpoints, short thickness,
- short dflag, short sflag,
+static void gp_draw_stroke_volumetric_2d(const bGPDspoint *points, int totpoints, short thickness,
+ short UNUSED(dflag), short sflag,
int offsx, int offsy, int winx, int winy,
- float diff_mat[4][4], float ink[4])
+ const float diff_mat[4][4], const float ink[4])
{
- GLUquadricObj *qobj = gluNewQuadric();
- float modelview[4][4];
- float baseloc[3];
- float scalefac = 1.0f;
-
- bGPDspoint *pt;
- int i;
- float fpt[3];
-
- /* HACK: We need a scale factor for the drawing in the image editor,
- * which seems to use 1 unit as it's maximum size, whereas everything
- * else assumes 1 unit = 1 pixel. Otherwise, we only get a massive blob.
- */
- if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
- scalefac = 0.001f;
- }
-
- /* get basic matrix */
- glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview);
- copy_v3_v3(baseloc, modelview[3]);
-
- /* draw points */
- glPushMatrix();
-
- for (i = 0, pt = points; i < totpoints; i++, pt++) {
- /* color of point */
- gp_set_point_color(pt, ink);
-
- /* set the transformed position */
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+ GPU_enable_program_point_size();
+ immBegin(GWN_PRIM_POINTS, totpoints);
+
+ const bGPDspoint *pt = points;
+ for (int i = 0; i < totpoints; i++, pt++) {
+ /* transform position to 2D */
float co[2];
-
+ float fpt[3];
+
mul_v3_m4v3(fpt, diff_mat, &pt->x);
gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
- translate_m4(modelview, co[0], co[1], 0.0f);
-
- glLoadMatrixf((float *)modelview);
-
- /* draw the disk using the current state... */
- gluDisk(qobj, 0.0, pt->pressure * thickness * scalefac, 32, 1);
-
- /* restore matrix */
- copy_v3_v3(modelview[3], baseloc);
+
+ gp_set_point_varying_color(pt, ink, color);
+ immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */
+ immVertex2f(pos, co[0], co[1]);
}
-
- glPopMatrix();
- gluDeleteQuadric(qobj);
+
+ immEnd();
+ immUnbindProgram();
+ GPU_disable_program_point_size();
}
/* draw a 3D stroke in "volumetric" style */
static void gp_draw_stroke_volumetric_3d(
- bGPDspoint *points, int totpoints, short thickness,
- short UNUSED(dflag), short UNUSED(sflag), float diff_mat[4][4], float ink[4])
+ const bGPDspoint *points, int totpoints, short thickness,
+ const float ink[4])
{
- GLUquadricObj *qobj = gluNewQuadric();
-
- float base_modelview[4][4], modelview[4][4];
- float base_loc[3];
-
- bGPDspoint *pt;
- int i;
- float fpt[3];
-
- /* Get the basic modelview matrix we use for performing calculations */
- glGetFloatv(GL_MODELVIEW_MATRIX, (float *)base_modelview);
- copy_v3_v3(base_loc, base_modelview[3]);
-
- /* Create the basic view-aligned billboard matrix we're going to actually draw qobj with:
- * - We need to knock out the rotation so that we are
- * simply left with a camera-facing billboard
- * - The scale factors here are chosen so that the thickness
- * is relatively reasonable. Otherwise, it gets far too
- * large!
- */
- scale_m4_fl(modelview, 0.1f);
-
- /* draw each point as a disk... */
- glPushMatrix();
-
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
- /* color of point */
- gp_set_point_color(pt, ink);
-
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
-
- /* apply translation to base_modelview, so that the translated point is put in the right place */
- translate_m4(base_modelview, fpt[0], fpt[1], fpt[2]);
-
- /* copy the translation component to the billboard matrix we're going to use,
- * then reset the base matrix to the original values so that we can do the same
- * for the next point without accumulation/pollution effects
- */
- copy_v3_v3(modelview[3], base_modelview[3]); /* copy offset value */
- copy_v3_v3(base_modelview[3], base_loc); /* restore */
-
- /* apply our billboard matrix for drawing... */
- glLoadMatrixf((float *)modelview);
-
- /* draw the disk using the current state... */
- gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+ GPU_enable_program_point_size();
+ immBegin(GWN_PRIM_POINTS, totpoints);
+
+ const bGPDspoint *pt = points;
+ for (int i = 0; i < totpoints && pt; i++, pt++) {
+ gp_set_point_varying_color(pt, ink, color);
+ immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */
+ immVertex3fv(pos, &pt->x); /* we can adjust size in vertex shader based on view/projection! */
}
-
- glPopMatrix();
- gluDeleteQuadric(qobj);
+
+ immEnd();
+ immUnbindProgram();
+ GPU_disable_program_point_size();
}
/* --------------- Stroke Fills ----------------- */
/* Get points of stroke always flat to view not affected by camera view or view position */
-static void gp_stroke_2d_flat(bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
+static void gp_stroke_2d_flat(const bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
{
- bGPDspoint *pt0 = &points[0];
- bGPDspoint *pt1 = &points[1];
- bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
-
+ const bGPDspoint *pt0 = &points[0];
+ const bGPDspoint *pt1 = &points[1];
+ const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
+
float locx[3];
float locy[3];
float loc3[3];
float normal[3];
-
+
/* local X axis (p0 -> p1) */
sub_v3_v3v3(locx, &pt1->x, &pt0->x);
-
+
/* point vector at 3/4 */
sub_v3_v3v3(loc3, &pt3->x, &pt0->x);
-
+
/* vector orthogonal to polygon plane */
cross_v3_v3v3(normal, locx, loc3);
-
+
/* local Y axis (cross to normal/x axis) */
cross_v3_v3v3(locy, normal, locx);
-
+
/* Normalize vectors */
normalize_v3(locx);
normalize_v3(locy);
-
+
/* Get all points in local space */
for (int i = 0; i < totpoints; i++) {
- bGPDspoint *pt = &points[i];
+ const bGPDspoint *pt = &points[i];
float loc[3];
-
+
/* Get local space using first point as origin */
sub_v3_v3v3(loc, &pt->x, &pt0->x);
-
+
points2d[i][0] = dot_v3v3(loc, locx);
points2d[i][1] = dot_v3v3(loc, locy);
}
-
+
/* Concave (-1), Convex (1), or Autodetect (0)? */
*r_direction = (int)locy[2];
}
@@ -416,14 +451,14 @@ static void gp_stroke_2d_flat(bGPDspoint *points, int totpoints, float(*points2d
static void gp_triangulate_stroke_fill(bGPDstroke *gps)
{
BLI_assert(gps->totpoints >= 3);
-
+
/* allocate memory for temporary areas */
gps->tot_triangles = gps->totpoints - 2;
unsigned int (*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation");
float (*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
-
+
int direction = 0;
-
+
/* convert to 2d and triangulate */
gp_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
BLI_polyfill_calc(points2d, (unsigned int)gps->totpoints, direction, tmp_triangles);
@@ -438,25 +473,24 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps)
else {
gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
}
-
+
for (int i = 0; i < gps->tot_triangles; i++) {
- bGPDtriangle *stroke_triangle = &gps->triangles[i];
- memcpy(stroke_triangle->verts, tmp_triangles[i], sizeof(uint[3]));
+ memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3]));
}
}
else {
/* No triangles needed - Free anything allocated previously */
if (gps->triangles)
MEM_freeN(gps->triangles);
-
+
gps->triangles = NULL;
}
-
+
/* disable recalculation flag */
if (gps->flag & GP_STROKE_RECALC_CACHES) {
gps->flag &= ~GP_STROKE_RECALC_CACHES;
}
-
+
/* clear memory */
if (tmp_triangles) MEM_freeN(tmp_triangles);
if (points2d) MEM_freeN(points2d);
@@ -466,78 +500,64 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps)
/* draw fills for shapes */
static void gp_draw_stroke_fill(
bGPdata *gpd, bGPDstroke *gps,
- int offsx, int offsy, int winx, int winy, float diff_mat[4][4])
+ int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float color[4])
{
- bGPDpalettecolor *palcolor;
- int i;
float fpt[3];
BLI_assert(gps->totpoints >= 3);
- palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
+ bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
/* Triangulation fill if high quality flag is enabled */
if (palcolor->flag & PC_COLOR_HQ_FILL) {
- bGPDtriangle *stroke_triangle;
- bGPDspoint *pt;
-
/* Calculate triangles cache for filling area (must be done only after changes) */
if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) {
gp_triangulate_stroke_fill(gps);
}
- /* Draw all triangles for filling the polygon (cache must be calculated before) */
BLI_assert(gps->tot_triangles >= 1);
- glBegin(GL_TRIANGLES);
+
+ unsigned int pos;
if (gps->flag & GP_STROKE_3DSPACE) {
- for (i = 0, stroke_triangle = gps->triangles; i < gps->tot_triangles; i++, stroke_triangle++) {
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+ else {
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ }
+
+ immUniformColor4fv(color);
+
+ /* Draw all triangles for filling the polygon (cache must be calculated before) */
+ immBegin(GWN_PRIM_TRIS, gps->tot_triangles * 3);
+ /* TODO: use batch instead of immediate mode, to share vertices */
+
+ bGPDtriangle *stroke_triangle = gps->triangles;
+ bGPDspoint *pt;
+
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
for (int j = 0; j < 3; j++) {
pt = &gps->points[stroke_triangle->verts[j]];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
+ immVertex3fv(pos, fpt);
}
}
}
else {
- for (i = 0, stroke_triangle = gps->triangles; i < gps->tot_triangles; i++, stroke_triangle++) {
+ for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
for (int j = 0; j < 3; j++) {
float co[2];
pt = &gps->points[stroke_triangle->verts[j]];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
+ immVertex3fv(pos, fpt);
}
}
}
- glEnd();
- }
- else {
- /* As an initial implementation, we use the OpenGL filled polygon drawing
- * here since it's the easiest option to implement for this case. It does
- * come with limitations (notably for concave shapes), though it shouldn't
- * be much of an issue in most cases.
- *
- * We keep this legacy implementation around despite now having the high quality
- * fills, as this is necessary for keeping everything working nicely for files
- * created using old versions of Blender which may have depended on the artifacts
- * the old fills created.
- */
- bGPDspoint *pt;
-
- glBegin(GL_POLYGON);
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (gps->flag & GP_STROKE_3DSPACE) {
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
- }
- else {
- float co[2];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
- }
- }
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
}
@@ -545,153 +565,162 @@ static void gp_draw_stroke_fill(
/* draw a given stroke - just a single dot (only one point) */
static void gp_draw_stroke_point(
- bGPDspoint *points, short thickness, short dflag, short sflag,
- int offsx, int offsy, int winx, int winy, float diff_mat[4][4], float ink[4])
+ const bGPDspoint *points, short thickness, short UNUSED(dflag), short sflag,
+ int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float ink[4])
{
- float fpt[3];
- bGPDspoint *pt = &points[0];
-
- /* color of point */
- gp_set_point_color(pt, ink);
+ const bGPDspoint *pt = points;
- /* set point thickness (since there's only one of these) */
- glPointSize((float)(thickness + 2) * points->pressure);
-
/* get final position using parent matrix */
+ float fpt[3];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
- /* draw point */
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
if (sflag & GP_STROKE_3DSPACE) {
- glBegin(GL_POINTS);
- glVertex3fv(fpt);
- glEnd();
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
}
else {
- float co[2];
-
- /* get coordinates of point */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+
+ /* get 2D coordinates of point */
+ float co[3] = { 0.0f };
gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
-
- /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok
- * - also mandatory in if Image Editor 'image-based' dot
- */
- if ((thickness < GP_DRAWTHICKNESS_SPECIAL) ||
- ((dflag & GP_DRAWDATA_IEDITHACK) && (sflag & GP_STROKE_2DSPACE)))
- {
- glBegin(GL_POINTS);
- glVertex2fv(co);
- glEnd();
- }
- else {
- /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */
- GLUquadricObj *qobj = gluNewQuadric();
-
- gluQuadricDrawStyle(qobj, GLU_FILL);
-
- /* need to translate drawing position, but must reset after too! */
- glTranslate2fv(co);
- gluDisk(qobj, 0.0, thickness, 32, 1);
- glTranslatef(-co[0], -co[1], 0.0);
-
- gluDeleteQuadric(qobj);
- }
+ copy_v3_v3(fpt, co);
}
+
+ gp_set_point_uniform_color(pt, ink);
+ /* set point thickness (since there's only one of these) */
+ immUniform1f("size", (float)(thickness + 2) * pt->pressure);
+
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3fv(pos, fpt);
+ immEnd();
+
+ immUnbindProgram();
}
/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
-static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness, bool debug,
- short UNUSED(sflag), float diff_mat[4][4], float ink[4], bool cyclic)
+static void gp_draw_stroke_3d(const bGPDspoint *points, int totpoints, short thickness, bool UNUSED(debug),
+ short UNUSED(sflag), const float diff_mat[4][4], const float ink[4], bool cyclic)
{
- bGPDspoint *pt, *pt2;
float curpressure = points[0].pressure;
- int i;
float fpt[3];
float cyclic_fpt[3];
+ int draw_points = 0;
+
+ /* if cyclic needs one vertex more */
+ int cyclic_add = 0;
+ if (cyclic) {
+ ++cyclic_add;
+ }
+
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+
+ /* TODO: implement this with a geometry shader to draw one continuous tapered stroke */
/* draw stroke curve */
glLineWidth(max_ff(curpressure * thickness, 1.0f));
- glBegin(GL_LINE_STRIP);
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
- gp_set_point_color(pt, ink);
+ immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints + cyclic_add);
+ const bGPDspoint *pt = points;
+ for (int i = 0; i < totpoints; i++, pt++) {
+ gp_set_point_varying_color(pt, ink, color);
/* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
* and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
* Note: we want more visible levels of pressures when thickness is bigger.
*/
if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
- glEnd();
+ /* if the pressure changes before get at least 2 vertices, need to repeat last point to avoid assert in immEnd() */
+ if (draw_points < 2) {
+ const bGPDspoint *pt2 = pt - 1;
+ mul_v3_m4v3(fpt, diff_mat, &pt2->x);
+ immVertex3fv(pos, fpt);
+ }
+ immEnd();
+ draw_points = 0;
+
curpressure = pt->pressure;
glLineWidth(max_ff(curpressure * thickness, 1.0f));
- glBegin(GL_LINE_STRIP);
-
+ immBeginAtMost(GWN_PRIM_LINE_STRIP, totpoints - i + 1 + cyclic_add);
+
/* need to roll-back one point to ensure that there are no gaps in the stroke */
if (i != 0) {
- pt2 = pt - 1;
+ const bGPDspoint *pt2 = pt - 1;
mul_v3_m4v3(fpt, diff_mat, &pt2->x);
- glVertex3fv(fpt);
+ gp_set_point_varying_color(pt2, ink, color);
+ immVertex3fv(pos, fpt);
+ ++draw_points;
}
-
- /* now the point we want... */
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
- }
- else {
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
}
- /* saves first point to use in cyclic */
- if (i == 0) {
+
+ /* now the point we want */
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ immVertex3fv(pos, fpt);
+ ++draw_points;
+
+ if (cyclic && i == 0) {
+ /* save first point to use in cyclic */
copy_v3_v3(cyclic_fpt, fpt);
}
}
- /* if cyclic draw line to first point */
+
if (cyclic) {
- glVertex3fv(cyclic_fpt);
+ /* draw line to first point to complete the cycle */
+ immVertex3fv(pos, cyclic_fpt);
+ ++draw_points;
}
- glEnd();
-
- /* draw debug points of curve on top? */
- /* XXX: for now, we represent "selected" strokes in the same way as debug, which isn't used anymore */
- if (debug) {
- glPointSize((float)(thickness + 2));
-
- glBegin(GL_POINTS);
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
- }
- glEnd();
+ /* if less of two points, need to repeat last point to avoid assert in immEnd() */
+ if (draw_points < 2) {
+ const bGPDspoint *pt2 = pt - 1;
+ mul_v3_m4v3(fpt, diff_mat, &pt2->x);
+ gp_set_point_varying_color(pt2, ink, color);
+ immVertex3fv(pos, fpt);
}
+
+ immEnd();
+ immUnbindProgram();
}
/* ----- Fancy 2D-Stroke Drawing ------ */
/* draw a given stroke in 2d */
-static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
- bool debug, int offsx, int offsy, int winx, int winy, float diff_mat[4][4], float ink[4])
+static void gp_draw_stroke_2d(const bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
+ bool UNUSED(debug), int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float ink[4])
{
/* otherwise thickness is twice that of the 3D view */
float thickness = (float)thickness_s * 0.5f;
-
+
/* strokes in Image Editor need a scale factor, since units there are not pixels! */
float scalefac = 1.0f;
if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
scalefac = 0.001f;
}
-
- /* tessellation code - draw stroke as series of connected quads with connection
+
+ /* TODO: fancy++ with the magic of shaders */
+
+ /* tessellation code - draw stroke as series of connected quads (triangle strips in fact) with connection
* edges rotated to minimize shrinking artifacts, and rounded endcaps
*/
{
- bGPDspoint *pt1, *pt2;
+ const bGPDspoint *pt1, *pt2;
float s0[2], s1[2]; /* segment 'center' points */
float pm[2]; /* normal from previous segment. */
int i;
float fpt[3];
-
- glShadeModel(GL_FLAT);
- glBegin(GL_QUADS);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GWN_PRIM_TRI_STRIP, totpoints * 2 + 4);
/* get x and y coordinates from first point */
mul_v3_m4v3(fpt, diff_mat, &points->x);
@@ -706,19 +735,19 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
/* get x and y coordinates from point2 (point1 has already been computed in previous iteration). */
mul_v3_m4v3(fpt, diff_mat, &pt2->x);
gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s1);
-
+
/* calculate gradient and normal - 'angle'=(ny/nx) */
m1[1] = s1[1] - s0[1];
m1[0] = s1[0] - s0[0];
normalize_v2(m1);
m2[1] = -m1[0];
m2[0] = m1[1];
-
+
/* always use pressure from first point here */
pthick = (pt1->pressure * thickness * scalefac);
-
+
/* color of point */
- gp_set_point_color(pt1, ink);
+ gp_set_point_varying_color(pt1, ink, color);
/* if the first segment, start of segment is segment's normal */
if (i == 0) {
@@ -729,40 +758,39 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
mt[1] = m2[1] * pthick * 0.5f;
sc[0] = s0[0] - (m1[0] * pthick * 0.75f);
sc[1] = s0[1] - (m1[1] * pthick * 0.75f);
-
+
t0[0] = sc[0] - mt[0];
t0[1] = sc[1] - mt[1];
t1[0] = sc[0] + mt[0];
t1[1] = sc[1] + mt[1];
-
- glVertex2fv(t0);
- glVertex2fv(t1);
-
+
+ /* First two points of cap. */
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
+
/* calculate points for start of segment */
mt[0] = m2[0] * pthick;
mt[1] = m2[1] * pthick;
-
+
t0[0] = s0[0] - mt[0];
t0[1] = s0[1] - mt[1];
t1[0] = s0[0] + mt[0];
t1[1] = s0[1] + mt[1];
-
- /* draw this line twice (first to finish off start cap, then for stroke) */
- glVertex2fv(t1);
- glVertex2fv(t0);
- glVertex2fv(t0);
- glVertex2fv(t1);
+
+ /* Last two points of start cap (and first two points of first segment). */
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
}
/* if not the first segment, use bisector of angle between segments */
else {
float mb[2]; /* bisector normal */
float athick, dfac; /* actual thickness, difference between thicknesses */
-
+
/* calculate gradient of bisector (as average of normals) */
mb[0] = (pm[0] + m2[0]) / 2;
mb[1] = (pm[1] + m2[1]) / 2;
normalize_v2(mb);
-
+
/* calculate gradient to apply
* - as basis, use just pthick * bisector gradient
* - if cross-section not as thick as it should be, add extra padding to fix it
@@ -771,49 +799,44 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
mt[1] = mb[1] * pthick;
athick = len_v2(mt);
dfac = pthick - (athick * 2);
-
+
if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) {
mt[0] += (mb[0] * dfac);
mt[1] += (mb[1] * dfac);
}
-
+
/* calculate points for start of segment */
t0[0] = s0[0] - mt[0];
t0[1] = s0[1] - mt[1];
t1[0] = s0[0] + mt[0];
t1[1] = s0[1] + mt[1];
-
- /* draw this line twice (once for end of current segment, and once for start of next) */
- glVertex2fv(t1);
- glVertex2fv(t0);
- glVertex2fv(t0);
- glVertex2fv(t1);
+
+ /* Last two points of previous segment, and first two points of current segment. */
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
}
-
+
/* if last segment, also draw end of segment (defined as segment's normal) */
if (i == totpoints - 2) {
/* for once, we use second point's pressure (otherwise it won't be drawn) */
pthick = (pt2->pressure * thickness * scalefac);
-
+
/* color of point */
- gp_set_point_color(pt2, ink);
+ gp_set_point_varying_color(pt2, ink, color);
/* calculate points for end of segment */
mt[0] = m2[0] * pthick;
mt[1] = m2[1] * pthick;
-
+
t0[0] = s1[0] - mt[0];
t0[1] = s1[1] - mt[1];
t1[0] = s1[0] + mt[0];
t1[1] = s1[1] + mt[1];
-
- /* draw this line twice (once for end of stroke, and once for endcap)*/
- glVertex2fv(t1);
- glVertex2fv(t0);
- glVertex2fv(t0);
- glVertex2fv(t1);
-
-
+
+ /* Last two points of last segment (and first two points of end cap). */
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
+
/* draw end cap as last step
* - make points slightly closer to center (about halfway across)
*/
@@ -821,42 +844,25 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
mt[1] = m2[1] * pthick * 0.5f;
sc[0] = s1[0] + (m1[0] * pthick * 0.75f);
sc[1] = s1[1] + (m1[1] * pthick * 0.75f);
-
+
t0[0] = sc[0] - mt[0];
t0[1] = sc[1] - mt[1];
t1[0] = sc[0] + mt[0];
t1[1] = sc[1] + mt[1];
-
- glVertex2fv(t1);
- glVertex2fv(t0);
+
+ /* Last two points of end cap. */
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
}
-
+
/* store computed point2 coordinates as point1 ones of next segment. */
copy_v2_v2(s0, s1);
/* store stroke's 'natural' normal for next stroke to use */
copy_v2_v2(pm, m2);
}
-
- glEnd();
- glShadeModel(GL_SMOOTH);
- }
-
- /* draw debug points of curve on top? (original stroke points) */
- if (debug) {
- bGPDspoint *pt;
- int i;
- float fpt[3];
- glPointSize((float)(thickness_s + 2));
-
- glBegin(GL_POINTS);
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
- float co[2];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
- }
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
}
@@ -871,41 +877,41 @@ static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag)
return false;
if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
return false;
-
+
/* 2) Screen Space 2D Strokes */
if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
return false;
if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
return false;
-
+
/* 3) Image Space (2D) */
if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
return false;
if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
return false;
-
-
+
/* skip stroke if it doesn't have any valid data */
if ((gps->points == NULL) || (gps->totpoints < 1))
return false;
-
+
/* stroke can be drawn */
return true;
}
/* draw a set of strokes */
static void gp_draw_strokes(
- bGPdata *gpd, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag,
+ bGPdata *gpd, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag,
bool debug, short lthick, const float opacity, const float tintcolor[4],
- const bool onion, const bool custonion, float diff_mat[4][4])
+ const bool onion, const bool custonion, const float diff_mat[4][4])
{
- bGPDstroke *gps;
float tcolor[4];
float tfill[4];
short sthickness;
float ink[4];
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ GPU_enable_program_point_size();
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
/* check if stroke can be drawn */
if (gp_can_draw_stroke(gps, dflag) == false) {
continue;
@@ -923,6 +929,10 @@ static void gp_draw_strokes(
/* calculate thickness */
sthickness = gps->thickness + lthick;
+ if (sthickness <= 0) {
+ continue;
+ }
+
/* check which stroke-drawer to use */
if (dflag & GP_DRAWDATA_ONLY3D) {
const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
@@ -936,10 +946,6 @@ static void gp_draw_strokes(
/* first arg is normally rv3d->dist, but this isn't
* available here and seems to work quite well without */
bglPolygonOffset(1.0f, 1.0f);
-#if 0
- glEnable(GL_POLYGON_OFFSET_LINE);
- glPolygonOffset(-1.0f, -1.0f);
-#endif
}
/* 3D Fill */
@@ -949,19 +955,20 @@ static void gp_draw_strokes(
interp_v3_v3v3(tfill, palcolor->fill, tintcolor, tintcolor[3]);
tfill[3] = palcolor->fill[3] * opacity;
if (tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
+ const float *color;
if (!onion) {
- glColor4fv(tfill);
+ color = tfill;
}
else {
if (custonion) {
- glColor4fv(tintcolor);
+ color = tintcolor;
}
else {
ARRAY_SET_ITEMS(tfill, UNPACK3(palcolor->fill), tintcolor[3]);
- glColor4fv(tfill);
+ color = tfill;
}
}
- gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat);
+ gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat, color);
}
}
@@ -983,7 +990,7 @@ static void gp_draw_strokes(
}
if (palcolor->flag & PC_COLOR_VOLUMETRIC) {
/* volumetric stroke drawing */
- gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, dflag, gps->flag, diff_mat, ink);
+ gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink);
}
else {
/* 3D Lines - OpenGL primitives-based */
@@ -1001,10 +1008,6 @@ static void gp_draw_strokes(
glDisable(GL_DEPTH_TEST);
bglPolygonOffset(0.0, 0.0);
-#if 0
- glDisable(GL_POLYGON_OFFSET_LINE);
- glPolygonOffset(0, 0);
-#endif
}
}
else {
@@ -1014,20 +1017,21 @@ static void gp_draw_strokes(
interp_v3_v3v3(tfill, palcolor->fill, tintcolor, tintcolor[3]);
tfill[3] = palcolor->fill[3] * opacity;
if (tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
+ const float *color;
if (!onion) {
- glColor4fv(tfill);
+ color = tfill;
}
else {
if (custonion) {
- glColor4fv(tintcolor);
+ color = tintcolor;
}
else {
ARRAY_SET_ITEMS(tfill, palcolor->fill[0], palcolor->fill[1], palcolor->fill[2],
tintcolor[3]);
- glColor4fv(tfill);
+ color = tfill;
}
}
- gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat);
+ gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat, color);
}
}
@@ -1065,15 +1069,15 @@ static void gp_draw_strokes(
}
}
}
+
+ GPU_disable_program_point_size();
}
/* Draw selected verts for strokes being edited */
static void gp_draw_strokes_edit(
- bGPdata *gpd, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, short dflag,
- short lflag, float diff_mat[4][4], float alpha)
+ bGPdata *gpd, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, short dflag,
+ short lflag, const float diff_mat[4][4], float alpha)
{
- bGPDstroke *gps;
-
/* if alpha 0 do not draw */
if (alpha == 0.0f)
return;
@@ -1087,36 +1091,28 @@ static void gp_draw_strokes_edit(
glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
glDepthMask(0);
glEnable(GL_DEPTH_TEST);
-
+
/* first arg is normally rv3d->dist, but this isn't
* available here and seems to work quite well without */
bglPolygonOffset(1.0f, 1.0f);
-#if 0
- glEnable(GL_POLYGON_OFFSET_LINE);
- glPolygonOffset(-1.0f, -1.0f);
-#endif
}
}
-
-
- /* draw stroke verts */
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- bGPDspoint *pt;
- float vsize, bsize;
- int i;
- float fpt[3];
+ GPU_enable_program_point_size();
+
+ /* draw stroke verts */
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
/* check if stroke can be drawn */
if (gp_can_draw_stroke(gps, dflag) == false)
continue;
-
+
/* Optimisation: only draw points for selected strokes
* We assume that selected points can only occur in
* strokes that are selected too.
*/
if ((gps->flag & GP_STROKE_SELECT) == 0)
continue;
-
+
/* verify palette color lock */
{
bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
@@ -1135,7 +1131,8 @@ static void gp_draw_strokes_edit(
* they stand out more.
* - We use the theme setting for size of the unselected verts
*/
- bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
+ float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
+ float vsize;
if ((int)bsize > 8) {
vsize = 10.0f;
bsize = 8.0f;
@@ -1143,89 +1140,83 @@ static void gp_draw_strokes_edit(
else {
vsize = bsize + 2;
}
-
- /* First Pass: Draw all the verts (i.e. these become the unselected state) */
+
/* for now, we assume that the base color of the points is not too close to the real color */
/* set color using palette */
bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
- glColor3fv(palcolor->color);
- glPointSize(bsize);
-
- glBegin(GL_POINTS);
- for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
+ float selectColor[4];
+ UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
+ selectColor[3] = alpha;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos; /* specified later */
+ unsigned int size = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+ }
+ else {
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR);
+ }
+
+ immBegin(GWN_PRIM_POINTS, gps->totpoints);
+
+ /* Draw start and end point differently if enabled stroke direction hint */
+ bool show_direction_hint = (gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1);
+
+ /* Draw all the stroke points (selected or not) */
+ bGPDspoint *pt = gps->points;
+ float fpt[3];
+ for (int i = 0; i < gps->totpoints; i++, pt++) {
+ /* size and color first */
+ if (show_direction_hint && i == 0) {
+ /* start point in green bigger */
+ immAttrib3f(color, 0.0f, 1.0f, 0.0f);
+ immAttrib1f(size, vsize + 4);
+ }
+ else if (show_direction_hint && (i == gps->totpoints - 1)) {
+ /* end point in red smaller */
+ immAttrib3f(color, 1.0f, 0.0f, 0.0f);
+ immAttrib1f(size, vsize + 1);
+ }
+ else if (pt->flag & GP_SPOINT_SELECT) {
+ immAttrib3fv(color, selectColor);
+ immAttrib1f(size, vsize);
+ }
+ else {
+ immAttrib3fv(color, palcolor->color);
+ immAttrib1f(size, bsize);
+ }
+
+ /* then position */
if (gps->flag & GP_STROKE_3DSPACE) {
mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
+ immVertex3fv(pos, fpt);
}
else {
float co[2];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
+ immVertex2fv(pos, co);
}
}
- glEnd();
-
-
- /* Second Pass: Draw only verts which are selected */
- float curColor[4];
- UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, curColor);
- glColor4f(curColor[0], curColor[1], curColor[2], alpha);
- glPointSize(vsize);
-
- glBegin(GL_POINTS);
- for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- if (gps->flag & GP_STROKE_3DSPACE) {
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
- }
- else {
- float co[2];
-
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
- }
- }
- }
- glEnd();
-
- /* Draw start and end point if enabled stroke direction hint */
- if ((gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1)) {
- bGPDspoint *p;
-
- glPointSize(vsize + 4);
- glBegin(GL_POINTS);
-
- /* start point in green bigger */
- glColor3f(0.0f, 1.0f, 0.0f);
- p = &gps->points[0];
- mul_v3_m4v3(fpt, diff_mat, &p->x);
- glVertex3fv(fpt);
- glEnd();
-
- /* end point in red smaller */
- glPointSize(vsize + 1);
- glBegin(GL_POINTS);
-
- glColor3f(1.0f, 0.0f, 0.0f);
- p = &gps->points[gps->totpoints - 1];
- mul_v3_m4v3(fpt, diff_mat, &p->x);
- glVertex3fv(fpt);
- glEnd();
- }
+ immEnd();
+ immUnbindProgram();
}
-
-
+
+ GPU_disable_program_point_size();
+
/* clear depth mask */
if (dflag & GP_DRAWDATA_ONLY3D) {
if (no_xray) {
glDepthMask(mask_orig);
glDisable(GL_DEPTH_TEST);
-
+
bglPolygonOffset(0.0, 0.0);
#if 0
glDisable(GL_POLYGON_OFFSET_LINE);
@@ -1239,8 +1230,8 @@ static void gp_draw_strokes_edit(
/* draw onion-skinning for a layer */
static void gp_draw_onionskins(
- bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
- int UNUSED(cfra), int dflag, bool debug, float diff_mat[4][4])
+ bGPdata *gpd, const bGPDlayer *gpl, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
+ int UNUSED(cfra), int dflag, bool debug, const float diff_mat[4][4])
{
const float default_color[3] = {UNPACK3(U.gpencil_new_layer_col)};
const float alpha = 1.0f;
@@ -1253,17 +1244,14 @@ static void gp_draw_onionskins(
else {
copy_v3_v3(color, default_color);
}
-
+
if (gpl->gstep > 0) {
- bGPDframe *gf;
- float fac;
-
/* draw previous frames first */
- for (gf = gpf->prev; gf; gf = gf->prev) {
+ for (bGPDframe *gf = gpf->prev; gf; gf = gf->prev) {
/* check if frame is drawable */
if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
/* alpha decreases with distance from curframe index */
- fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
+ float fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
color[3] = alpha * fac * 0.66f;
gp_draw_strokes(gpd, gf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color,
true, gpl->flag & GP_LAYER_GHOST_PREVCOL, diff_mat);
@@ -1283,8 +1271,7 @@ static void gp_draw_onionskins(
else {
/* don't draw - disabled */
}
-
-
+
/* 2) Now draw next frames */
if (gpl->flag & GP_LAYER_GHOST_NEXTCOL) {
copy_v3_v3(color, gpl->gcolor_next);
@@ -1292,17 +1279,14 @@ static void gp_draw_onionskins(
else {
copy_v3_v3(color, default_color);
}
-
+
if (gpl->gstep_next > 0) {
- bGPDframe *gf;
- float fac;
-
/* now draw next frames */
- for (gf = gpf->next; gf; gf = gf->next) {
+ for (bGPDframe *gf = gpf->next; gf; gf = gf->next) {
/* check if frame is drawable */
if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) {
/* alpha decreases with distance from curframe index */
- fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
+ float fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
color[3] = alpha * fac * 0.66f;
gp_draw_strokes(gpd, gf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color,
true, gpl->flag & GP_LAYER_GHOST_NEXTCOL, diff_mat);
@@ -1322,7 +1306,6 @@ static void gp_draw_onionskins(
else {
/* don't draw - disabled */
}
-
}
/* draw interpolate strokes (used only while operator is running) */
@@ -1360,29 +1343,27 @@ void ED_gp_draw_interpolation(tGPDinterpolate *tgpi, const int type)
/* loop over gpencil data layers, drawing them */
static void gp_draw_data_layers(
- bGPDbrush *brush, float alpha, bGPdata *gpd,
+ const bGPDbrush *brush, float alpha, bGPdata *gpd,
int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
- bGPDlayer *gpl;
float diff_mat[4][4];
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- bGPDframe *gpf;
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* calculate parent position */
ED_gpencil_parent_location(gpl, diff_mat);
- bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? true : false;
+ bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG);
short lthick = brush->thickness + gpl->thickness;
-
+
/* don't draw layer if hidden */
if (gpl->flag & GP_LAYER_HIDE)
continue;
-
+
/* get frame to draw */
- gpf = BKE_gpencil_layer_getframe(gpl, cfra, 0);
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra, 0);
if (gpf == NULL)
continue;
-
+
/* set basic stroke thickness */
glLineWidth(lthick);
@@ -1394,10 +1375,10 @@ static void gp_draw_data_layers(
if (condition) dflag |= (draw_flag_value); \
else dflag &= ~(draw_flag_value); \
} (void)0
-
+
/* xray... */
GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_NO_XRAY), GP_DRAWDATA_NO_XRAY);
-
+
/* volumetric strokes... */
GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_VOLUMETRIC), GP_DRAWDATA_VOLUMETRIC);
@@ -1421,11 +1402,11 @@ static void gp_draw_data_layers(
*/
gp_draw_onionskins(gpd, gpl, gpf, offsx, offsy, winx, winy, cfra, dflag, debug, diff_mat);
}
-
+
/* draw the strokes already in active frame */
gp_draw_strokes(gpd, gpf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness,
gpl->opacity, gpl->tintcolor, false, false, diff_mat);
-
+
/* Draw verts of selected strokes
* - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering
* - locked layers can't be edited, so there's no point showing these verts
@@ -1440,16 +1421,13 @@ static void gp_draw_data_layers(
{
gp_draw_strokes_edit(gpd, gpf, offsx, offsy, winx, winy, dflag, gpl->flag, diff_mat, alpha);
}
-
+
/* Check if may need to draw the active stroke cache, only if this layer is the active layer
* that is being edited. (Stroke buffer is currently stored in gp-data)
*/
if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
(gpf->flag & GP_FRAME_PAINT))
{
- /* Set color for drawing buffer stroke - since this may not be set yet */
- // glColor4fv(gpl->color);
-
/* Buffer stroke needs to be drawn with a different linestyle
* to help differentiate them from normal strokes.
*
@@ -1458,89 +1436,84 @@ static void gp_draw_data_layers(
*/
if (gpd->sflag & PC_COLOR_VOLUMETRIC) {
gp_draw_stroke_volumetric_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick,
- dflag, gpd->sbuffer_sflag, gpd->scolor);
+ dflag, gpd->scolor);
}
else {
- gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag, gpd->scolor);
+ gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag, gpd->scolor, gpd->sfill);
}
}
}
}
/* draw a short status message in the top-right corner */
-static void gp_draw_status_text(bGPdata *gpd, ARegion *ar)
+static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar)
{
rcti rect;
-
+
/* Cannot draw any status text when drawing OpenGL Renders */
if (G.f & G_RENDER_OGL)
return;
-
+
/* Get bounds of region - Necessary to avoid problems with region overlap */
ED_region_visible_rect(ar, &rect);
-
+
/* for now, this should only be used to indicate when we are in stroke editmode */
if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
const char *printable = IFACE_("GPencil Stroke Editing");
float printable_size[2];
- int xco, yco;
-
- BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
-
- xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
- yco = (rect.ymax - U.widget_unit);
+
+ int 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
BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
#endif
-
+
/* grease pencil icon... */
// XXX: is this too intrusive?
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
-
+
xco -= U.widget_unit;
yco -= (int)printable_size[1] / 2;
UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
-
+
glDisable(GL_BLEND);
}
}
/* draw grease-pencil datablock */
static void gp_draw_data(
- bGPDbrush *brush, float alpha, bGPdata *gpd,
+ const bGPDbrush *brush, float alpha, bGPdata *gpd,
int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
- /* reset line drawing style (in case previous user didn't reset) */
- setlinestyle(0);
-
/* turn on smooth lines (i.e. anti-aliasing) */
glEnable(GL_LINE_SMOOTH);
-
+
/* XXX: turn on some way of ensuring that the polygon edges get smoothed
* GL_POLYGON_SMOOTH is nasty and shouldn't be used, as it ends up
* creating internal white rays due to the ways it accumulates stuff
*/
-
+
/* turn on alpha-blending */
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
-
+
/* draw! */
gp_draw_data_layers(brush, alpha, gpd, offsx, offsy, winx, winy, cfra, dflag);
-
+
/* turn off alpha blending, then smooth lines */
glDisable(GL_BLEND); // alpha blending
glDisable(GL_LINE_SMOOTH); // smooth lines
-
- /* restore initial gl conditions */
- glColor4f(0, 0, 0, 1);
}
/* if we have strokes for scenes (3d view)/clips (movie clip editor)
@@ -1575,7 +1548,7 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i
}
}
}
-
+
/* scene/clip data has already been drawn, only object/track data is drawn here
* if gpd_source == gpd, we don't have any object/track data and we can skip */
if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) {
@@ -1601,28 +1574,27 @@ void ED_gpencil_draw_2dimage(const bContext *C)
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
- bGPdata *gpd;
+
int offsx, offsy, sizex, sizey;
int dflag = GP_DRAWDATA_NOSTATUS;
-
- gpd = ED_gpencil_data_get_active(C); // XXX
+
+ bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
if (gpd == NULL) return;
-
+
/* calculate rect */
switch (sa->spacetype) {
case SPACE_IMAGE: /* image */
case SPACE_CLIP: /* clip */
{
-
/* just draw using standard scaling (settings here are currently ignored anyways) */
/* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
offsx = 0;
offsy = 0;
sizex = ar->winx;
sizey = ar->winy;
-
+
wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax);
-
+
dflag |= GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_IEDITHACK;
break;
}
@@ -1633,7 +1605,7 @@ void ED_gpencil_draw_2dimage(const bContext *C)
offsy = 0;
sizex = ar->winx;
sizey = ar->winy;
-
+
/* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
* and everything moved to standard View2d
*/
@@ -1645,77 +1617,79 @@ void ED_gpencil_draw_2dimage(const bContext *C)
offsy = 0;
sizex = ar->winx;
sizey = ar->winy;
-
+
dflag |= GP_DRAWDATA_ONLYI2D;
break;
}
-
+
if (ED_screen_animation_playing(wm)) {
/* don't show onionskins during animation playback/scrub (i.e. it obscures the poses)
* OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes)
*/
dflag |= GP_DRAWDATA_NO_ONIONS;
}
-
-
+
/* draw it! */
gp_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, sa->spacetype);
}
/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly
- * Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes,
- * second time with onlyv2d=0 for screen-aligned strokes */
+ * Note: this gets called twice - first time with onlyv2d=true to draw 'canvas' strokes,
+ * second time with onlyv2d=false for screen-aligned strokes */
void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d)
{
wmWindowManager *wm = CTX_wm_manager(C);
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
- bGPdata *gpd;
int dflag = 0;
/* check that we have grease-pencil stuff to draw */
if (sa == NULL) return;
- gpd = ED_gpencil_data_get_active(C); // XXX
+ bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
if (gpd == NULL) return;
-
+
/* special hack for Image Editor */
/* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
if (ELEM(sa->spacetype, SPACE_IMAGE, SPACE_CLIP))
dflag |= GP_DRAWDATA_IEDITHACK;
-
+
/* draw it! */
if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS);
if (ED_screen_animation_playing(wm)) dflag |= GP_DRAWDATA_NO_ONIONS;
-
+
gp_draw_data_all(scene, gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag, sa->spacetype);
-
+
/* draw status text (if in screen/pixel-space) */
- if (onlyv2d == false) {
+ if (!onlyv2d) {
gp_draw_status_text(gpd, ar);
}
}
/* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly
- * Note: this gets called twice - first time with only3d=1 to draw 3d-strokes,
- * second time with only3d=0 for screen-aligned strokes */
-void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, ARegion *ar, bool only3d)
+ * Note: this gets called twice - first time with only3d=true to draw 3d-strokes,
+ * second time with only3d=false for screen-aligned strokes */
+void ED_gpencil_draw_view3d(wmWindowManager *wm,
+ Scene *scene,
+ ViewLayer *view_layer,
+ View3D *v3d,
+ ARegion *ar,
+ bool only3d)
{
- bGPdata *gpd;
int dflag = 0;
RegionView3D *rv3d = ar->regiondata;
int offsx, offsy, winx, winy;
-
+
/* check that we have grease-pencil stuff to draw */
- gpd = ED_gpencil_data_get_active_v3d(scene, v3d);
+ bGPdata *gpd = ED_gpencil_data_get_active_v3d(scene, view_layer);
if (gpd == NULL) return;
-
+
/* when rendering to the offscreen buffer we don't want to
* deal with the camera border, otherwise map the coords to the camera border. */
if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) {
rctf rectf;
ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &rectf, true); /* no shift */
-
+
offsx = round_fl_to_int(rectf.xmin);
offsy = round_fl_to_int(rectf.ymin);
winx = round_fl_to_int(rectf.xmax - rectf.xmin);
@@ -1727,7 +1701,7 @@ void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, AReg
winx = ar->winx;
winy = ar->winy;
}
-
+
/* set flags */
if (only3d) {
/* 3D strokes/3D space:
@@ -1736,28 +1710,27 @@ void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, AReg
*/
dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
}
-
+
if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
/* don't draw status text when "only render" flag is set */
dflag |= GP_DRAWDATA_NOSTATUS;
}
-
+
if ((wm == NULL) || ED_screen_animation_playing(wm)) {
/* don't show onionskins during animation playback/scrub (i.e. it obscures the poses)
* OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes)
*/
dflag |= GP_DRAWDATA_NO_ONIONS;
}
-
+
/* draw it! */
- gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
-
+ gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
}
void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
{
int dflag = GP_DRAWDATA_NOSTATUS | GP_DRAWDATA_ONLYV2D;
-
+
gp_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype);
}
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index bb3800941ab..38927cf91e1 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -75,8 +75,8 @@
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
#include "gpencil_intern.h"
@@ -979,28 +979,28 @@ static bool gpsculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso)
static void gp_brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata))
{
GP_EditBrush_Data *brush = gpsculpt_get_brush(CTX_data_scene(C));
-
+
if (brush) {
- glPushMatrix();
-
- glTranslatef((float)x, (float)y, 0.0f);
-
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
+
/* Inner Ring: Light color for action of the brush */
/* TODO: toggle between add and remove? */
- glColor4ub(255, 255, 255, 200);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, brush->size, 40);
-
+ immUniformColor4ub(255, 255, 255, 200);
+ imm_draw_circle_wire_2d(pos, x, y, brush->size, 40);
+
/* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */
- glColor3ub(30, 30, 30);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, brush->size + 1, 40);
-
+ immUniformColor3ub(30, 30, 30);
+ imm_draw_circle_wire_2d(pos, x, y, brush->size + 1, 40);
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
}
}
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index 7d455f214db..1a210f071e0 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -56,12 +56,13 @@
#include "DNA_view3d_types.h"
#include "DNA_gpencil_types.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -69,6 +70,8 @@
#include "BKE_screen.h"
#include "BKE_tracking.h"
+#include "DEG_depsgraph.h"
+
#include "UI_interface.h"
#include "WM_api.h"
@@ -546,7 +549,7 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
/* send updates */
- DAG_id_tag_update(&cu->id, 0);
+ DEG_id_tag_update(&cu->id, 0);
}
#undef MIN_TIME_DELTA
@@ -1121,14 +1124,15 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd)
{
struct Main *bmain = CTX_data_main(C);
- View3D *v3d = CTX_wm_view3d(C); /* may be NULL */
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SceneCollection *sc = CTX_data_scene_collection(C);
bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0);
bGPDstroke *gps, *prev_gps = NULL;
Object *ob;
Curve *cu;
Nurb *nu = NULL;
- Base *base_orig = BASACT, *base_new = NULL;
+ Base *base_new = NULL;
float minmax_weights[2] = {1.0f, 0.0f};
/* camera framing */
@@ -1152,7 +1156,8 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
*/
ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info);
cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE);
- base_new = BKE_scene_base_add(scene, ob);
+ BKE_collection_object_add(&scene->id, sc, ob);
+ base_new = BKE_view_layer_base_find(view_layer, ob);
cu->flag |= CU_3D;
@@ -1216,8 +1221,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 |= SELECT;
+ BKE_scene_object_base_flag_sync_from_base(base_new);
}
/* --- */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index bd5a42df99a..a82148788c8 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -79,6 +79,8 @@
#include "ED_view3d.h"
#include "ED_space_api.h"
+#include "DEG_depsgraph.h"
+
#include "gpencil_intern.h"
/* ************************************************ */
@@ -2106,8 +2108,12 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
/* init autodist for geometry projection */
if (mode == GP_REPROJECT_SURFACE) {
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ struct Depsgraph *graph = CTX_data_depsgraph(C);
view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar);
- ED_view3d_autodist_init(scene, gsc.ar, CTX_wm_view3d(C), 0);
+ ED_view3d_autodist_init(&eval_ctx, graph, gsc.ar, CTX_wm_view3d(C), 0);
}
// TODO: For deforming geometry workflow, create new frames?
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index f54356dfed3..09ccc4600ef 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -69,15 +69,19 @@
#include "ED_view3d.h"
#include "ED_clip.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
+#include "DEG_depsgraph.h"
+
#include "gpencil_intern.h"
/* ******************************************* */
@@ -112,7 +116,9 @@ typedef enum eGPencil_PaintFlags {
* "p" = op->customdata
*/
typedef struct tGPsdata {
+ EvaluationContext eval_ctx;
Scene *scene; /* current scene from context */
+ struct Depsgraph *graph;
wmWindow *win; /* window where painting originated */
ScrArea *sa; /* area where painting originated */
@@ -481,7 +487,8 @@ static void gp_brush_angle(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const
}
/* add current stroke-point to buffer (returns whether point was successfully added) */
-static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, double curtime)
+static short gp_stroke_addpoint(
+ tGPsdata *p, const int mval[2], float pressure, double curtime)
{
bGPdata *gpd = p->gpd;
bGPDbrush *brush = p->brush;
@@ -639,7 +646,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
View3D *v3d = p->sa->spacedata.first;
view3d_region_operator_needs_opengl(p->win, p->ar);
- ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ ED_view3d_autodist_init(
+ &p->eval_ctx, p->graph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
}
/* convert screen-coordinates to appropriate coordinates (and store them) */
@@ -735,7 +743,7 @@ static void gp_stroke_simplify(tGPsdata *p)
/* ignore return values on this... assume to be ok for now */
gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time);
-
+
j += 2;
}
}
@@ -1239,9 +1247,8 @@ static void gp_stroke_doeraser(tGPsdata *p)
if (p->sa->spacetype == SPACE_VIEW3D) {
if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) {
View3D *v3d = p->sa->spacedata.first;
-
view3d_region_operator_needs_opengl(p->win, p->ar);
- ED_view3d_autodist_init(p->scene, p->ar, v3d, 0);
+ ED_view3d_autodist_init(&p->eval_ctx, p->graph, p->ar, v3d, 0);
}
}
@@ -1394,7 +1401,9 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
}
/* pass on current scene and window */
+ CTX_data_eval_ctx(C, &p->eval_ctx);
p->scene = CTX_data_scene(C);
+ p->graph = CTX_data_depsgraph(C);
p->win = CTX_wm_window(C);
unit_m4(p->imat);
@@ -1549,6 +1558,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
bGPDpalettecolor *palcolor = p->palettecolor;
bGPdata *pdata = p->gpd;
copy_v4_v4(pdata->scolor, palcolor->color);
+ copy_v4_v4(pdata->sfill, palcolor->fill);
pdata->sflag = palcolor->flag;
/* lock axis */
p->lock_axis = ts->gp_sculpt.lock_axis;
@@ -1806,14 +1816,14 @@ static void gp_paint_strokeend(tGPsdata *p)
/* need to restore the original projection settings before packing up */
view3d_region_operator_needs_opengl(p->win, p->ar);
- ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+ ED_view3d_autodist_init(&p->eval_ctx, p->graph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
}
/* check if doing eraser or not */
if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) {
/* simplify stroke before transferring? */
gp_stroke_simplify(p);
-
+
/* transfer stroke to frame */
gp_stroke_newfrombuffer(p);
}
@@ -1844,28 +1854,41 @@ static void gp_paint_cleanup(tGPsdata *p)
static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
{
tGPsdata *p = (tGPsdata *)p_ptr;
-
+
if (p->paintmode == GP_PAINTMODE_ERASER) {
- glPushMatrix();
-
- glTranslatef((float)x, (float)y, 0.0f);
-
+ Gwn_VertFormat *format = immVertexFormat();
+ const uint shdr_pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
- glColor4ub(255, 100, 100, 20);
- glutil_draw_filled_arc(0.0, M_PI * 2.0, p->radius, 40);
-
- setlinestyle(6);
-
- glColor4ub(255, 100, 100, 200);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, p->radius, 40);
-
- setlinestyle(0);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ immUniformColor4ub(255, 100, 100, 20);
+ imm_draw_circle_fill_2d(shdr_pos, x, y, p->radius, 40);
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniform1f("dash_width", 12.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ imm_draw_circle_wire_2d(shdr_pos, x, y, p->radius,
+ /* XXX Dashed shader gives bad results with sets of small segments currently,
+ * temp hack around the issue. :( */
+ max_ii(8, p->radius / 2)); /* was fixed 40 */
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
}
}
@@ -2039,7 +2062,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p)
if (p->paintmode == GP_PAINTMODE_ERASER) {
/* do 'live' erasing now */
gp_stroke_doeraser(p);
-
+
/* store used values */
p->mvalo[0] = p->mval[0];
p->mvalo[1] = p->mval[1];
@@ -2049,7 +2072,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p)
else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) {
/* try to add point */
short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime);
-
+
/* handle errors while adding point */
if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) {
/* finish off old stroke */
@@ -2194,7 +2217,7 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event)
/* apply the current latest drawing point */
gpencil_draw_apply(op, p);
-
+
/* force refresh */
ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */
}
@@ -2370,9 +2393,9 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
static void gpencil_stroke_end(wmOperator *op)
{
tGPsdata *p = op->customdata;
-
+
gp_paint_cleanup(p);
-
+
gpencil_undo_push(p->gpd);
gp_session_cleanup(p);
@@ -2506,7 +2529,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* end stroke only, and then wait to resume painting soon */
/* printf("\t\tGP - end stroke only\n"); */
gpencil_stroke_end(op);
-
+
/* If eraser mode is on, turn it off after the stroke finishes
* NOTE: This just makes it nicer to work with drawing sessions
*/
@@ -2649,7 +2672,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* handle drawing event */
/* printf("\t\tGP - add point\n"); */
gpencil_draw_apply_event(op, event);
-
+
/* finish painting operation if anything went wrong just now */
if (p->status == GP_STATUS_ERROR) {
printf("\t\t\t\tGP - add error done!\n");
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 672c87ed6fd..e1e4f850039 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -65,6 +65,8 @@
#include "ED_clip.h"
#include "ED_view3d.h"
+#include "DEG_depsgraph.h"
+
#include "gpencil_intern.h"
/* ******************************************************** */
@@ -202,15 +204,15 @@ 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)
+bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, ViewLayer *view_layer)
{
- Base *base = scene->basact;
+ Base *base = view_layer->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.
*/
- if (base && TESTBASE(v3d, base)) {
+ if (base && TESTBASE(base)) {
gpd = base->object->gpd;
}
return gpd ? gpd : scene->gpd;
@@ -536,14 +538,18 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
if (sa->spacetype == SPACE_VIEW3D) {
wmWindow *win = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
+ struct Depsgraph *graph = CTX_data_depsgraph(C);
View3D *v3d = (View3D *)CTX_wm_space_data(C);
RegionView3D *rv3d = ar->regiondata;
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* init 3d depth buffers */
view3d_operator_needs_opengl(C);
view3d_region_operator_needs_opengl(win, ar);
- ED_view3d_autodist_init(scene, ar, v3d, 0);
+ ED_view3d_autodist_init(&eval_ctx, graph, ar, v3d, 0);
/* for camera view set the subrect */
if (rv3d->persp == RV3D_CAMOB) {
@@ -912,8 +918,8 @@ bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf)
ptc = &gps->points[after];
/* the optimal value is the corresponding to the interpolation of the pressure
- * at the distance of point b
- */
+ * at the distance of point b
+ */
float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
float optimal = (1.0f - fac) * pta->pressure + fac * ptc->pressure;
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index e264d9e16a3..f91e7d42bca 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -36,45 +36,6 @@
#include "GPU_glew.h"
#include "BLI_utildefines.h"
-/*
- * these should be phased out. cpack should be replaced in
- * code with calls to glColor3ub. - zr
- */
-/*
- *
- * This define converts a numerical value to the equivalent 24-bit
- * color, while not being endian-sensitive. On little-endians, this
- * is the same as doing a 'naive' indexing, on big-endian, it is not!
- * */
-void cpack(unsigned int x);
-
-#ifdef WITH_GL_PROFILE_COMPAT
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
-# define glMultMatrixf(x) \
- glMultMatrixf(_Generic((x), \
- float *: (float *)(x), \
- float [16]: (float *)(x), \
- float (*)[4]: (float *)(x), \
- float [4][4]: (float *)(x), \
- const float *: (float *)(x), \
- const float [16]: (float *)(x), \
- const float (*)[4]: (float *)(x), \
- const float [4][4]: (float *)(x)) \
-)
-# define glLoadMatrixf(x) \
- glLoadMatrixf(_Generic((x), \
- float *: (float *)(x), \
- float [16]: (float *)(x), \
- float (*)[4]: (float *)(x), \
- float [4][4]: (float *)(x)) \
-)
-#else
-# define glMultMatrixf(x) glMultMatrixf((float *)(x))
-# define glLoadMatrixf(x) glLoadMatrixf((float *)(x))
-#endif /* C11 */
-#endif /* WITH_GL_PROFILE_COMPAT */
-
-
/* hacking pointsize and linewidth */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
# define glPointSize(f) glPointSize(U.pixelsize * _Generic((f), double: (float)(f), default: (f)))
@@ -86,19 +47,5 @@ void cpack(unsigned int x);
#define GLA_PIXEL_OFS 0.375f
-
-BLI_INLINE void glTranslate3iv(const int vec[3]) { glTranslatef(UNPACK3_EX((const float), vec, )); }
-BLI_INLINE void glTranslate2iv(const int vec[2]) { glTranslatef(UNPACK2_EX((const float), vec, ), 0.0f); }
-BLI_INLINE void glTranslate3fv(const float vec[3]) { glTranslatef(UNPACK3(vec)); }
-BLI_INLINE void glTranslate2fv(const float vec[2]) { glTranslatef(UNPACK2(vec), 0.0f); }
-
-BLI_INLINE void glScale3iv(const int vec[3]) { glTranslatef(UNPACK3_EX((const float), vec, )); }
-BLI_INLINE void glScale2iv(const int vec[2]) { glTranslatef(UNPACK2_EX((const float), vec, ), 0.0f); }
-BLI_INLINE void glScale3fv(const float vec[3]) { glScalef(UNPACK3(vec)); }
-BLI_INLINE void glScale2fv(const float vec[2]) { glScalef(UNPACK2(vec), 0.0); }
-
-/* v2 versions don't make much sense for rotation */
-BLI_INLINE void glRotate3fv(const float angle, const float vec[3]) { glRotatef(angle, UNPACK3(vec)); }
-
#endif /* #ifdef __BIF_GL_H__ */
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index d3d2c465d46..3184ebee4d9 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -38,56 +38,14 @@ struct bContext;
struct ColorManagedViewSettings;
struct ColorManagedDisplaySettings;
-void fdrawbezier(float vec[4][3]);
-void fdrawline(float x1, float y1, float x2, float y2);
-void fdrawbox(float x1, float y1, float x2, float y2);
-void sdrawline(int x1, int y1, int x2, int y2);
-#if 0
-void sdrawtri(int x1, int y1, int x2, int y2);
-void sdrawtrifill(int x1, int y1, int x2, int y2);
-#endif
-void sdrawbox(int x1, int y1, int x2, int y2);
-
-void sdrawXORline(int x0, int y0, int x1, int y1);
-void sdrawXORline4(int nr, int x0, int y0, int x1, int y1);
-
-void fdrawXORellipse(float xofs, float yofs, float hw, float hh);
-void fdrawXORcirc(float xofs, float yofs, float rad);
-
-void fdrawcheckerboard(float x1, float y1, float x2, float y2);
-
-/* OpenGL stipple defines */
-extern const unsigned char stipple_halftone[128];
-extern const unsigned char stipple_quarttone[128];
-extern const unsigned char stipple_diag_stripes_pos[128];
-extern const unsigned char stipple_diag_stripes_neg[128];
-extern const unsigned char stipple_checker_8px[128];
-
-/**
- * Draw a lined (non-looping) arc with the given
- * \a radius, starting at angle \a start and arcing
- * through \a angle. The arc is centered at the origin
- * and drawn in the XY plane.
+/* A few functions defined here are being DEPRECATED for Blender 2.8
*
- * \param start The initial angle (in radians).
- * \param angle The length of the arc (in radians).
- * \param radius The arc radius.
- * \param nsegments The number of segments to use in drawing the arc.
- */
-void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments);
-
-/**
- * Draw a filled arc with the given \a radius,
- * starting at angle \a start and arcing through
- * \a angle. The arc is centered at the origin
- * and drawn in the XY plane.
+ * Do not use them in new code, and you are encouraged to
+ * convert existing code to draw without these.
*
- * \param start The initial angle (in radians).
- * \param angle The length of the arc (in radians).
- * \param radius The arc radius.
- * \param nsegments The number of segments to use in drawing the arc.
+ * These will be deleted before we ship 2.8!
+ * - merwin
*/
-void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments);
/**
* Returns a float value as obtained by glGetFloatv.
@@ -109,58 +67,46 @@ int glaGetOneInt(int param);
*/
void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y);
-/**
- * Functions like a limited glDrawPixels, except ensures that
- * the image is displayed onscreen even if the \a x and \a y
- * coordinates for would be clipped. The routine respects the
- * glPixelZoom values, pixel unpacking parameters are _not_
- * respected.
- *
- * \attention This routine makes many assumptions: the rect data
- * is expected to be in RGBA unsigned byte format, the coordinate
- * (GLA_PIXEL_OFS, GLA_PIXEL_OFS) is assumed to be within the view frustum,
- * and the modelview and projection matrices are assumed to define a
- * 1-to-1 mapping to screen space.
- * \attention Furthermore, in the case of zoomed or unpixel aligned
- * images extending outside the view frustum, but still within the
- * window, some portion of the image may be visible left and/or
- * below of the given \a x and \a y coordinates. It is recommended
- * to use the glScissor functionality if images are to be drawn
- * with an inset view matrix.
- */
-void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect);
+typedef struct IMMDrawPixelsTexState {
+ struct GPUShader *shader;
+ unsigned int pos;
+ unsigned int texco;
+ bool do_shader_unbind;
+} IMMDrawPixelsTexState;
+
+/* To be used before calling immDrawPixelsTex
+ * Default shader is GPU_SHADER_2D_IMAGE_COLOR
+ * Returns a shader to be able to set uniforms */
+IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin);
/**
- * glaDrawPixelsTex - Functions like a limited glDrawPixels, but actually draws the
+ * 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. The routine respects the glPixelZoom values,
- * pixel unpacking parameters are _not_ respected.
+ * clipped when offscreen. Pixel unpacking parameters and
+ * the glPixelZoom values are _not_ respected.
+ *
+ * \attention Use immDrawPixelsTexSetup before calling this function.
*
* \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 glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect);
-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);
-
-/**
- * glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef.
- * only RGBA
- * needs glaDefine2DArea to be set.
- */
-void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect);
-void glaDrawPixelsAuto_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);
-
-
-void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY);
-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 immDrawPixelsTex(IMMDrawPixelsTexState *state,
+ 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(IMMDrawPixelsTexState *state,
+ 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]);
+void immDrawPixelsTexScaled(IMMDrawPixelsTexState *state,
+ 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(IMMDrawPixelsTexState *state,
+ 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.
@@ -176,12 +122,13 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int
*/
void glaDefine2DArea(struct rcti *screen_rect);
-typedef struct gla2DDrawInfo gla2DDrawInfo;
+/* TODO(merwin): put the following 2D code to use, or build new 2D code inspired & informd by it */
+
+#if 0 /* UNUSED */
-/* UNUSED */
-#if 0
+typedef struct gla2DDrawInfo gla2DDrawInfo;
-gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect);
+gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect);
void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *r_sc_x, int *r_sc_y);
void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int r_screen[2]);
@@ -190,7 +137,8 @@ void glaEnd2DDraw(gla2DDrawInfo *di);
/** Adjust the transformation mapping of a 2d area */
void gla2DGetMap(gla2DDrawInfo *di, struct rctf *rect);
void gla2DSetMap(gla2DDrawInfo *di, struct rctf *rect);
-#endif
+
+#endif /* UNUSED */
void set_inverted_drawing(int enable);
void setlinestyle(int nr);
@@ -198,37 +146,32 @@ void setlinestyle(int nr);
/* own working polygon offset */
void bglPolygonOffset(float viewdist, float dist);
-/* For caching opengl matrices (gluProject/gluUnProject) */
-typedef struct bglMats {
- double modelview[16];
- double projection[16];
- int viewport[4];
-} bglMats;
-void bgl_get_mats(bglMats *mats);
-
/* **** Color management helper functions for GLSL display/transform ***** */
/* Draw imbuf on a screen, preferably using GLSL display transform */
void glaDrawImBuf_glsl(struct ImBuf *ibuf, float x, float y, int zoomfilter,
struct ColorManagedViewSettings *view_settings,
- struct ColorManagedDisplaySettings *display_settings);
+ struct ColorManagedDisplaySettings *display_settings,
+ float zoom_x, float zoom_y);
void glaDrawImBuf_glsl_clipping(struct ImBuf *ibuf, float x, float y, int zoomfilter,
struct ColorManagedViewSettings *view_settings,
struct ColorManagedDisplaySettings *display_settings,
float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y);
+ float clip_max_x, float clip_max_y,
+ float zoom_x, float zoom_y);
/* Draw imbuf on a screen, preferably using GLSL display transform */
-void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter);
+void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter,
+ float zoom_x, float zoom_y);
void glaDrawImBuf_glsl_ctx_clipping(const struct bContext *C,
struct ImBuf *ibuf,
float x, float y,
int zoomfilter,
float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y);
+ float clip_max_x, float clip_max_y,
+ float zoom_x, float zoom_y);
-void glaDrawBorderCorners(const struct rcti *border, float zoomx, float zoomy);
+void immDrawBorderCorners(unsigned int pos, const struct rcti *border, float zoomx, float zoomy);
#endif /* __BIF_GLUTIL_H__ */
-
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index ab02fd1ccc8..db141a2ee29 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -82,6 +82,7 @@ typedef struct bAnimContext {
struct bDopeSheet *ads; /* dopesheet data for editor (or which is being used) */
struct Scene *scene; /* active scene */
+ struct ViewLayer *view_layer; /* active scene layer */
struct Object *obact; /* active object */
ListBase *markers; /* active set of markers */
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 00081b95c51..4595bcfa86d 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -39,6 +39,7 @@ struct Base;
struct bContext;
struct Bone;
struct bPoseChannel;
+struct EvaluationContext;
struct IDProperty;
struct ListBase;
struct MeshDeformModifierData;
@@ -46,9 +47,11 @@ struct DerivedMesh;
struct Object;
struct ReportList;
struct Scene;
+struct ViewLayer;
struct ViewContext;
struct wmKeyConfig;
struct wmOperator;
+struct Main;
typedef struct EditBone {
struct EditBone *next, *prev;
@@ -85,6 +88,12 @@ typedef struct EditBone {
short segments;
+ /* Used for display */
+ float disp_mat[4][4]; /* in Armature space, rest pos matrix */
+ float disp_tail_mat[4][4]; /* in Armature space, rest pos matrix */
+ /* 32 == MAX_BBONE_SUBDIV */
+ float disp_bbone_mat[32][4][4]; /* in Armature space, rest pos matrix */
+
/* Used to store temporary data */
union {
struct EditBone *ebone;
@@ -134,7 +143,7 @@ void ED_armature_deselect_all(struct Object *obedit);
void ED_armature_deselect_all_visible(struct Object *obedit);
bool ED_do_pose_selectbuffer(
- struct Scene *scene, struct Base *base, const unsigned int *buffer, short hits,
+ struct Scene *scene, struct ViewLayer *view_layer, struct Base *base, const 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);
@@ -169,8 +178,9 @@ void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do
#define ARM_GROUPS_ENVELOPE 2
#define ARM_GROUPS_AUTO 3
-void create_vgroups_from_armature(struct ReportList *reports, struct Scene *scene, struct Object *ob,
- struct Object *par, const int mode, const bool mirror);
+void create_vgroups_from_armature(
+ struct ReportList *reports, const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, struct Object *par, const int mode, const bool mirror);
/* if bone is already in list, pass it as param to ignore it */
void unique_editbone_name(struct ListBase *ebones, char *name, EditBone *bone);
@@ -191,7 +201,7 @@ void ED_armature_exit_posemode(struct bContext *C, struct Base *base);
void ED_armature_enter_posemode(struct bContext *C, struct Base *base);
void ED_pose_de_selectall(struct Object *ob, int select_mode, const bool ignore_visibility);
void ED_pose_bone_select(struct Object *ob, struct bPoseChannel *pchan, bool select);
-void ED_pose_recalculate_paths(struct Scene *scene, struct Object *ob);
+void ED_pose_recalculate_paths(struct bContext *C, struct Scene *scene, struct Object *ob);
struct Object *ED_pose_object_from_context(struct bContext *C);
/* sketch */
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 74d9ad0886d..7e384e0056b 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -48,6 +48,8 @@ struct bGPDpalettecolor;
struct bAnimContext;
struct KeyframeEditData;
struct PointerRNA;
+struct Scene;
+struct ViewLayer;
struct wmWindowManager;
struct wmKeyConfig;
@@ -113,7 +115,7 @@ struct bGPdata *ED_gpencil_data_get_active_direct(struct ID *screen_id, struct S
struct ScrArea *sa, struct Object *ob);
/* 3D View */
-struct bGPdata *ED_gpencil_data_get_active_v3d(struct Scene *scene, struct View3D *v3d);
+struct bGPdata *ED_gpencil_data_get_active_v3d(struct Scene *scene, struct ViewLayer *view_layer);
bool ED_gpencil_has_keyframe_v3d(struct Scene *scene, struct Object *ob, int cfra);
@@ -147,7 +149,12 @@ void ED_gpencil_strokes_copybuf_free(void);
void ED_gpencil_draw_2dimage(const struct bContext *C);
void ED_gpencil_draw_view2d(const struct bContext *C, bool onlyv2d);
-void ED_gpencil_draw_view3d(struct wmWindowManager *wm, struct Scene *scene, struct View3D *v3d, struct ARegion *ar, bool only3d);
+void ED_gpencil_draw_view3d(struct wmWindowManager *wm,
+ struct Scene *scene,
+ struct ViewLayer *view_layer,
+ struct View3D *v3d,
+ struct ARegion *ar,
+ bool only3d);
void ED_gpencil_draw_ex(struct Scene *scene, struct bGPdata *gpd, int winx, int winy,
const int cfra, const char spacetype);
void ED_gp_draw_interpolation(struct tGPDinterpolate *tgpi, const int type);
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index 9de550a20ce..95ba6095517 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -39,6 +39,7 @@ struct ToolSettings;
struct wmWindowManager;
struct ARegion;
struct Scene;
+struct ViewLayer;
/* image_edit.c, exported for transform */
struct Image *ED_space_image(struct SpaceImage *sima);
@@ -74,7 +75,7 @@ bool ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit);
bool ED_space_image_paint_curve(const struct bContext *C);
-bool ED_space_image_check_show_maskedit(struct Scene *scene, struct SpaceImage *sima);
+bool ED_space_image_check_show_maskedit(struct ViewLayer *view_layer, struct SpaceImage *sima);
int ED_space_image_maskedit_poll(struct bContext *C);
int ED_space_image_maskedit_mask_poll(struct bContext *C);
diff --git a/source/blender/editors/include/ED_info.h b/source/blender/editors/include/ED_info.h
index 6970abaa633..072b1a135a3 100644
--- a/source/blender/editors/include/ED_info.h
+++ b/source/blender/editors/include/ED_info.h
@@ -28,7 +28,7 @@
#define __ED_INFO_H__
/* info_stats.c */
-void ED_info_stats_clear(struct Scene *scene);
-const char *ED_info_stats_string(struct Scene *scene);
+void ED_info_stats_clear(struct ViewLayer *view_layer);
+const char *ED_info_stats_string(struct Scene *scene, struct ViewLayer *view_layer);
#endif /* __ED_INFO_H__ */
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index c478a8b17e5..62f1a617fcb 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(GWN_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_manipulator_library.h b/source/blender/editors/include/ED_manipulator_library.h
new file mode 100644
index 00000000000..80703321490
--- /dev/null
+++ b/source/blender/editors/include/ED_manipulator_library.h
@@ -0,0 +1,202 @@
+/*
+ * ***** 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 ED_manipulator_library.h
+ * \ingroup wm
+ *
+ * \name Generic Manipulators.
+ *
+ * This is exposes pre-defined manipulators for re-use.
+ */
+
+
+#ifndef __ED_MANIPULATOR_LIBRARY_H__
+#define __ED_MANIPULATOR_LIBRARY_H__
+
+/* initialize manipulators */
+void ED_manipulatortypes_arrow_2d(void);
+void ED_manipulatortypes_arrow_3d(void);
+void ED_manipulatortypes_cage_2d(void);
+void ED_manipulatortypes_cage_3d(void);
+void ED_manipulatortypes_dial_3d(void);
+void ED_manipulatortypes_grab_3d(void);
+void ED_manipulatortypes_facemap_3d(void);
+void ED_manipulatortypes_primitive_3d(void);
+
+struct wmManipulator;
+struct wmManipulatorGroup;
+
+
+/* -------------------------------------------------------------------- */
+/* Shape Presets
+ *
+ * Intended to be called by custom draw functions.
+ */
+
+/* manipulator_library_presets.c */
+void ED_manipulator_draw_preset_box(
+ const struct wmManipulator *mpr, float mat[4][4], int select_id);
+void ED_manipulator_draw_preset_arrow(
+ const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id);
+void ED_manipulator_draw_preset_circle(
+ const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id);
+void ED_manipulator_draw_preset_facemap(
+ const struct bContext *C, const struct wmManipulator *mpr, struct Scene *scene,
+ struct Object *ob, const int facemap, int select_id);
+
+
+/* -------------------------------------------------------------------- */
+/* 3D Arrow Manipulator */
+
+enum {
+ ED_MANIPULATOR_ARROW_STYLE_NORMAL = 0,
+ ED_MANIPULATOR_ARROW_STYLE_CROSS = 1,
+ ED_MANIPULATOR_ARROW_STYLE_BOX = 2,
+ ED_MANIPULATOR_ARROW_STYLE_CONE = 3,
+};
+
+enum {
+ /* inverted offset during interaction - if set it also sets constrained below */
+ ED_MANIPULATOR_ARROW_STYLE_INVERTED = (1 << 3),
+ /* clamp arrow interaction to property width */
+ ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED = (1 << 4),
+};
+
+void ED_manipulator_arrow3d_set_ui_range(struct wmManipulator *mpr, const float min, const float max);
+void ED_manipulator_arrow3d_set_range_fac(struct wmManipulator *mpr, const float range_fac);
+
+/* -------------------------------------------------------------------- */
+/* 2D Arrow Manipulator */
+
+/* none */
+
+/* -------------------------------------------------------------------- */
+/* Cage Manipulator */
+
+enum {
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE = (1 << 0), /* Translates */
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE = (1 << 1), /* Rotates */
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE = (1 << 2), /* Scales */
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM = (1 << 3), /* Scales uniformly */
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_SIGNED = (1 << 4), /* Negative scale allowed */
+};
+
+/* draw_style */
+enum {
+ ED_MANIPULATOR_CAGE2D_STYLE_BOX = 0,
+ ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE = 1,
+};
+
+/* draw_options */
+enum {
+ /** Draw a central handle (instead of having the entire area selectable)
+ * Needed for large rectangles that we don't want to swallow all events. */
+ ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE = (1 << 0),
+};
+
+/** #wmManipulator.highlight_part */
+enum {
+ ED_MANIPULATOR_CAGE2D_PART_TRANSLATE = 0,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X = 1,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X = 2,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y = 3,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y = 4,
+ /* Corners */
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y = 5,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y = 6,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y = 7,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y = 8,
+
+ ED_MANIPULATOR_CAGE2D_PART_ROTATE = 9,
+};
+
+/** #wmManipulator.highlight_part */
+enum {
+ /* ordered min/mid/max so we can loop over values (MIN/MID/MAX) on each axis. */
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z = 0,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MID_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MAX_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MID_Y_MIN_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MID_Y_MID_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MID_Y_MAX_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MIN_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MID_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MAX_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MIN_Y_MIN_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MIN_Y_MID_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MIN_Y_MAX_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MID_Y_MIN_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MID_Y_MID_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MID_Y_MAX_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MAX_Y_MIN_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MAX_Y_MID_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MAX_Y_MAX_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MIN_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MID_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MAX_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MID_Y_MIN_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MID_Y_MID_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MID_Y_MAX_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MIN_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MID_Z,
+ ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z,
+
+ ED_MANIPULATOR_CAGE3D_PART_TRANSLATE,
+
+ ED_MANIPULATOR_CAGE3D_PART_ROTATE,
+};
+
+/* -------------------------------------------------------------------- */
+/* Dial Manipulator */
+
+/* draw_options */
+enum {
+ ED_MANIPULATOR_DIAL_DRAW_FLAG_NOP = 0,
+ ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP = (1 << 0),
+ ED_MANIPULATOR_DIAL_DRAW_FLAG_FILL = (1 << 1),
+ ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR = (1 << 2),
+ ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y = (1 << 3),
+};
+
+/* -------------------------------------------------------------------- */
+/* Grab Manipulator */
+
+/* draw_options */
+enum {
+ ED_MANIPULATOR_GRAB_DRAW_FLAG_NOP = 0,
+ /* only for solid shapes */
+ ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL = (1 << 0),
+ ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW = (1 << 1),
+};
+
+enum {
+ ED_MANIPULATOR_GRAB_STYLE_RING_2D = 0,
+ ED_MANIPULATOR_GRAB_STYLE_CROSS_2D = 1,
+};
+
+
+/* -------------------------------------------------------------------- */
+/* Primitive Manipulator */
+
+enum {
+ ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE = 0,
+};
+
+#endif /* __ED_MANIPULATOR_LIBRARY_H__ */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 84698b33e25..1fd7756df77 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -36,6 +36,7 @@ extern "C" {
#endif
struct ID;
+struct EvaluationContext;
struct View3D;
struct ARegion;
struct bContext;
@@ -112,8 +113,8 @@ struct UvElementMap *BM_uv_element_map_create(
void BM_uv_element_map_free(struct UvElementMap *vmap);
struct UvElement *BM_uv_element_get(struct UvElementMap *map, struct BMFace *efa, struct BMLoop *l);
-bool EDBM_mtexpoly_check(struct BMEditMesh *em);
-struct MTexPoly *EDBM_mtexpoly_active_get(struct BMEditMesh *em, struct BMFace **r_act_efa, const bool sloppy, const bool selected);
+bool EDBM_uv_check(struct BMEditMesh *em);
+struct BMFace *EDBM_uv_active_face_get(struct BMEditMesh *em, const bool sloppy, const bool selected);
void BM_uv_vert_map_free(struct UvVertMap *vmap);
struct UvMapVert *BM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v);
@@ -133,35 +134,36 @@ void EDBM_select_mirrored(
int *r_totmirr, int *r_totfail);
void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag);
-bool EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
+bool EDBM_backbuf_border_init(const struct EvaluationContext *eval_ctx, struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
bool EDBM_backbuf_check(unsigned int index);
void EDBM_backbuf_free(void);
-bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2], short tot,
- short xmin, short ymin, short xmax, short ymax);
-bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads);
+bool EDBM_backbuf_border_mask_init(
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc, const int mcords[][2], short tot,
+ short xmin, short ymin, short xmax, short ymax);
+bool EDBM_backbuf_circle_init(const struct EvaluationContext *eval_ctx, struct ViewContext *vc, short xs, short ys, short rads);
struct BMVert *EDBM_vert_find_nearest_ex(
- struct ViewContext *vc, float *r_dist,
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist,
const bool use_select_bias, bool use_cycle);
struct BMVert *EDBM_vert_find_nearest(
- struct ViewContext *vc, float *r_dist);
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist);
struct BMEdge *EDBM_edge_find_nearest_ex(
- struct ViewContext *vc, float *r_dist,
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist,
float *r_dist_center,
const bool use_select_bias, const bool use_cycle,
struct BMEdge **r_eed_zbuf);
struct BMEdge *EDBM_edge_find_nearest(
- struct ViewContext *vc, float *r_dist);
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist);
struct BMFace *EDBM_face_find_nearest_ex(
- struct ViewContext *vc, float *r_dist,
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist,
float *r_dist_center,
const bool use_select_bias, const bool use_cycle,
struct BMFace **r_efa_zbuf);
struct BMFace *EDBM_face_find_nearest(
- struct ViewContext *vc, float *r_dist);
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc, float *r_dist);
bool EDBM_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
@@ -198,7 +200,7 @@ void EMBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct BMEd
/* editface.c */
void paintface_flush_flags(struct Object *ob, short flag);
bool paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], bool extend, bool deselect, bool toggle);
-int do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, bool select, bool extend);
+int do_paintface_box_select(const struct EvaluationContext *eval_ctx, struct ViewContext *vc, struct rcti *rect, bool select, bool extend);
void paintface_deselect_all_visible(struct Object *ob, int action, bool flush_flags);
void paintface_select_linked(struct bContext *C, struct Object *ob, const int mval[2], const bool select);
bool paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]);
@@ -258,7 +260,6 @@ void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGrou
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum);
void ED_vgroup_vert_active_mirror(struct Object *ob, int def_nr);
-
/* mesh_data.c */
// void ED_mesh_geometry_add(struct Mesh *mesh, struct ReportList *reports, int verts, int edges, int faces);
void ED_mesh_polys_add(struct Mesh *mesh, struct ReportList *reports, int count);
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index e3c382382a9..20363c69fa0 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 cdca848f213..8d2ff327c51 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -35,6 +35,7 @@
extern "C" {
#endif
+struct bFaceMap;
struct Base;
struct EnumPropertyItem;
struct ID;
@@ -43,6 +44,7 @@ struct ModifierData;
struct Object;
struct ReportList;
struct Scene;
+struct ViewLayer;
struct bConstraint;
struct bContext;
struct bPoseChannel;
@@ -80,16 +82,21 @@ typedef enum eParentType {
PAR_VERTEX_TRI,
} eParentType;
+typedef enum eObjectSelect_Mode {
+ BA_DESELECT = 0,
+ BA_SELECT = 1,
+ BA_INVERT = 2,
+} eObjectSelect_Mode;
+
#ifdef __RNA_TYPES_H__
extern struct EnumPropertyItem prop_clear_parent_types[];
extern struct EnumPropertyItem prop_make_parent_types[];
#endif
-bool ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob,
+bool ED_object_parent_set(struct ReportList *reports, const struct bContext *C, struct Scene *scene, struct Object *ob,
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);
@@ -97,15 +104,12 @@ void ED_keymap_proportional_maskmode(struct wmKeyConfig *keyconf, struct wmKeyMa
void ED_keymap_proportional_editmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap,
const bool do_connected);
-/* send your own notifier for select! */
-void ED_base_object_select(struct Base *base, short mode);
-/* includes notifier */
-void ED_base_object_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_object_base_select(struct Base *base, eObjectSelect_Mode mode);
+void ED_object_base_activate(struct bContext *C, struct Base *base);
+void ED_object_base_free_and_unlink(struct Main *bmain, struct Scene *scene, 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 ViewLayer *view_layer, struct Base *base, int dupflag);
void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr);
@@ -191,8 +195,8 @@ void ED_object_modifier_clear(struct Main *bmain, struct Object *ob);
int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_convert(struct ReportList *reports, struct Main *bmain, struct Scene *scene,
- struct Object *ob, struct ModifierData *md);
-int ED_object_modifier_apply(struct ReportList *reports, struct Scene *scene,
+ struct ViewLayer *view_layer, struct Object *ob, struct ModifierData *md);
+int ED_object_modifier_apply(struct ReportList *reports, const struct bContext *C, 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);
@@ -214,6 +218,10 @@ const struct EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
void ED_object_check_force_modifiers(struct Main *bmain, struct Scene *scene, struct Object *object);
+/* object_facemap_ops.c */
+void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum);
+void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int facenum);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
index 6cb8c0cfb19..ffa6db18caa 100644
--- a/source/blender/editors/include/ED_particle.h
+++ b/source/blender/editors/include/ED_particle.h
@@ -38,21 +38,24 @@ struct ParticleEditSettings;
struct rcti;
struct PTCacheEdit;
struct Scene;
+struct ViewLayer;
/* particle edit mode */
void PE_free_ptcache_edit(struct PTCacheEdit *edit);
int PE_start_edit(struct PTCacheEdit *edit);
/* access */
-struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob);
-struct PTCacheEdit *PE_create_current(struct Scene *scene, struct Object *ob);
-void PE_current_changed(struct Scene *scene, struct Object *ob);
-int PE_minmax(struct Scene *scene, float min[3], float max[3]);
+struct PTCacheEdit *PE_get_current(struct Scene *scene, struct ViewLayer *view_layer, struct Object *ob);
+struct PTCacheEdit *PE_create_current(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void PE_current_changed(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+int PE_minmax(struct Scene *scene, struct ViewLayer *view_layer, float min[3], float max[3]);
struct ParticleEditSettings *PE_settings(struct Scene *scene);
/* update calls */
void PE_hide_keys_time(struct Scene *scene, struct PTCacheEdit *edit, float cfra);
-void PE_update_object(struct Scene *scene, struct Object *ob, int useflag);
+void PE_update_object(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct ViewLayer *view_layer, struct Object *ob, int useflag);
/* selection tools */
int PE_mouse_particles(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
@@ -62,13 +65,13 @@ int PE_lasso_select(struct bContext *C, const int mcords[][2], const short moves
void PE_deselect_all_visible(struct PTCacheEdit *edit);
/* undo */
-void PE_undo_push(struct Scene *scene, const char *str);
-void PE_undo_step(struct Scene *scene, int step);
-void PE_undo(struct Scene *scene);
-void PE_redo(struct Scene *scene);
-bool PE_undo_is_valid(struct Scene *scene);
-void PE_undo_number(struct Scene *scene, int nr);
-const char *PE_undo_get_name(struct Scene *scene, int nr, bool *r_active);
+void PE_undo_push(struct Scene *scene, struct ViewLayer *view_layer, const char *str);
+void PE_undo_step(struct Scene *scene, struct ViewLayer *view_layer, int step);
+void PE_undo(struct Scene *scene, struct ViewLayer *view_layer);
+void PE_redo(struct Scene *scene, struct ViewLayer *view_layer);
+bool PE_undo_is_valid(struct Scene *scene, struct ViewLayer *view_layer);
+void PE_undo_number(struct Scene *scene, struct ViewLayer *view_layer, int nr);
+const char *PE_undo_get_name(struct Scene *scene, struct ViewLayer *view_layer, int nr, bool *r_active);
#endif /* __ED_PARTICLE_H__ */
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index 707d7c6c693..b7317d75cd4 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -31,6 +31,7 @@
#include "DNA_vec_types.h"
struct bContext;
+struct DEGEditorUpdateContext;
struct ID;
struct Main;
struct MTex;
@@ -43,13 +44,15 @@ struct wmWindowManager;
void ED_operatortypes_render(void);
-/* render_shading.c */
+/* render_update.c */
-void ED_render_id_flush_update(struct Main *bmain, struct ID *id);
void ED_render_engine_changed(struct Main *bmain);
void ED_render_engine_area_exit(struct Main *bmain, struct ScrArea *sa);
-void ED_render_scene_update(struct Main *bmain, struct Scene *scene, int updated);
-void ED_render_scene_update_pre(struct Main *bmain, struct Scene *scene, bool time);
+
+/* Callbacks handling data update events coming from depsgraph. */
+
+void ED_render_id_flush_update(const struct DEGEditorUpdateContext *update_ctx, struct ID *id);
+void ED_render_scene_update(const struct DEGEditorUpdateContext *update_ctx, int updated);
void ED_viewport_render_kill_jobs(struct wmWindowManager *wm, struct Main *bmain, bool free_database);
struct Scene *ED_render_job_get_scene(const struct bContext *C);
diff --git a/source/blender/editors/include/ED_scene.h b/source/blender/editors/include/ED_scene.h
new file mode 100644
index 00000000000..647a8dda1b9
--- /dev/null
+++ b/source/blender/editors/include/ED_scene.h
@@ -0,0 +1,43 @@
+/*
+ * ***** 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 ED_scene.h
+ * \ingroup editors
+ */
+
+#ifndef __ED_SCENE_H__
+#define __ED_SCENE_H__
+
+#include "BLI_compiler_attrs.h"
+
+enum eSceneCopyMethod;
+
+struct Scene *ED_scene_add(struct Main *bmain, struct bContext *C, struct wmWindow *win, enum eSceneCopyMethod method) ATTR_NONNULL();
+bool ED_scene_delete(struct bContext *C, struct Main *bmain, struct wmWindow *win, struct Scene *scene) ATTR_NONNULL();
+void ED_scene_exit(struct bContext *C) ATTR_NONNULL();
+void ED_scene_changed_update(struct Main *bmain, struct bContext *C, struct Scene *scene_new,
+ const struct bScreen *active_screen) ATTR_NONNULL();
+bool ED_scene_view_layer_delete(
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *layer,
+ struct ReportList *reports) ATTR_NONNULL(1, 2, 3);
+
+void ED_operatortypes_scene(void);
+
+#endif /* __ED_SCENE_H__ */
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 4253e214537..89a6828a59d 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -35,21 +35,34 @@
#include "DNA_space_types.h"
#include "DNA_view2d_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_workspace_types.h"
+#include "BLI_compiler_attrs.h"
+
+struct Depsgraph;
struct wmWindowManager;
struct wmWindow;
struct wmNotifier;
struct wmEvent;
struct wmKeyConfig;
+struct WorkSpace;
+struct WorkSpaceInstanceHook;
struct bContext;
struct Scene;
+struct ViewLayer;
struct bScreen;
struct ARegion;
struct uiBlock;
struct rcti;
+struct Main;
+struct wmMsgBus;
+struct wmMsgSubscribeKey;
+struct wmMsgSubscribeValue;
/* regions */
-void ED_region_do_listen(struct bScreen *sc, struct ScrArea *sa, struct ARegion *ar, struct wmNotifier *note);
+void ED_region_do_listen(
+ struct bScreen *sc, struct ScrArea *sa, struct ARegion *ar,
+ struct wmNotifier *note, const Scene *scene);
void ED_region_do_draw(struct bContext *C, struct ARegion *ar);
void ED_region_exit(struct bContext *C, struct ARegion *ar);
void ED_region_pixelspace(struct ARegion *ar);
@@ -70,11 +83,24 @@ void ED_region_header(const struct bContext *C, struct ARegion *ar);
void ED_region_cursor_set(struct wmWindow *win, struct ScrArea *sa, struct ARegion *ar);
void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar);
void ED_region_info_draw(struct ARegion *ar, const char *text, float fill_color[4], const bool full_redraw);
+void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float fill_color[4], const bool full_redraw);
void ED_region_image_metadata_draw(int x, int y, struct ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy);
void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy);
float ED_region_blend_factor(struct ARegion *ar);
void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect);
+/* message_bus callbacks */
+void ED_region_do_msg_notify_tag_redraw(
+ struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val);
+void ED_area_do_msg_notify_tag_refresh(
+ struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val);
+
+/* message bus */
+void ED_region_message_subscribe(
+ struct bContext *C,
+ struct WorkSpace *workspace, struct Scene *scene,
+ struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus);
/* spaces */
void ED_spacetypes_keymap(struct wmKeyConfig *keyconf);
@@ -84,7 +110,8 @@ int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *bl
void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa);
void ED_area_exit(struct bContext *C, struct ScrArea *sa);
int ED_screen_area_active(const struct bContext *C);
-void ED_area_do_listen(struct bScreen *sc, ScrArea *sa, struct wmNotifier *note);
+void ED_area_do_listen(struct bScreen *sc, ScrArea *sa, struct wmNotifier *note, Scene *scene,
+ struct WorkSpace *workspace);
void ED_area_tag_redraw(ScrArea *sa);
void ED_area_tag_redraw_regiontype(ScrArea *sa, int type);
void ED_area_tag_refresh(ScrArea *sa);
@@ -101,12 +128,11 @@ void ED_screens_initialize(struct wmWindowManager *wm);
void ED_screen_draw(struct wmWindow *win);
void ED_screen_refresh(struct wmWindowManager *wm, struct wmWindow *win);
void ED_screen_do_listen(struct bContext *C, struct wmNotifier *note);
-bScreen *ED_screen_duplicate(struct wmWindow *win, struct bScreen *sc);
-bScreen *ED_screen_add(struct wmWindow *win, struct Scene *scene, const char *name);
-bool ED_screen_set(struct bContext *C, struct bScreen *sc);
-bool ED_screen_delete(struct bContext *C, struct bScreen *sc);
-void ED_screen_set_scene(struct bContext *C, struct bScreen *screen, struct Scene *scene);
-bool ED_screen_delete_scene(struct bContext *C, struct Scene *scene);
+bool ED_screen_change(struct bContext *C, struct bScreen *sc);
+void ED_screen_update_after_scene_change(
+ const struct bScreen *screen,
+ struct Scene *scene_new,
+ struct ViewLayer *view_layer);
void ED_screen_set_subwinactive(struct bContext *C, const struct wmEvent *event);
void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable);
@@ -117,10 +143,49 @@ void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa);
void ED_screen_full_restore(struct bContext *C, ScrArea *sa);
struct ScrArea *ED_screen_state_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa, const short state);
void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
-bool ED_screen_stereo3d_required(struct bScreen *screen);
+bool ED_screen_stereo3d_required(const struct bScreen *screen, const struct Scene *scene);
+Scene *ED_screen_scene_find(const struct bScreen *screen, const struct wmWindowManager *wm);
+void ED_screen_preview_render(const struct bScreen *screen, int size_x, int size_y, unsigned int *r_rect) ATTR_NONNULL();
+
+/* workspaces */
+struct WorkSpace *ED_workspace_add(
+ struct Main *bmain,
+ const char *name,
+ Scene *scene,
+ ViewLayer *act_render_layer,
+ struct ViewRender *view_render) ATTR_NONNULL();
+bool ED_workspace_change(
+ struct WorkSpace *workspace_new,
+ struct bContext *C,
+ struct wmWindowManager *wm, struct wmWindow *win) ATTR_NONNULL();
+struct WorkSpace *ED_workspace_duplicate(
+ struct WorkSpace *workspace_old,
+ struct Main *bmain, struct wmWindow *win);
+bool ED_workspace_delete(
+ struct WorkSpace *workspace,
+ struct Main *bmain, struct bContext *C,
+ struct wmWindowManager *wm) ATTR_NONNULL();
+void ED_workspace_scene_data_sync(
+ struct WorkSpaceInstanceHook *hook, Scene *scene) ATTR_NONNULL();
+void ED_workspace_view_layer_unset(
+ const struct Main *bmain, struct Scene *scene,
+ const ViewLayer *layer_unset, ViewLayer *layer_new) ATTR_NONNULL(1, 2);
+struct WorkSpaceLayout *ED_workspace_layout_add(
+ struct WorkSpace *workspace,
+ struct wmWindow *win,
+ const char *name) ATTR_NONNULL();
+struct WorkSpaceLayout *ED_workspace_layout_duplicate(
+ struct WorkSpace *workspace, const struct WorkSpaceLayout *layout_old,
+ struct wmWindow *win) ATTR_NONNULL();
+bool ED_workspace_layout_delete(
+ struct WorkSpace *workspace, struct WorkSpaceLayout *layout_old,
+ struct bContext *C) ATTR_NONNULL();
+bool ED_workspace_layout_cycle(
+ struct WorkSpace *workspace, const short direction,
+ struct bContext *C) ATTR_NONNULL();
/* anim */
-void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, int mute);
+void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct Depsgraph *depsgraph);
void ED_refresh_viewport_fps(struct bContext *C);
int ED_screen_animation_play(struct bContext *C, int sync, int mode);
@@ -130,6 +195,8 @@ bScreen *ED_screen_animation_no_scrub(const struct wmWindowManager *wm);
/* screen keymaps */
void ED_operatortypes_screen(void);
void ED_keymap_screen(struct wmKeyConfig *keyconf);
+/* workspace keymaps */
+void ED_operatortypes_workspace(void);
/* operators; context poll callbacks */
int ED_operator_screenactive(struct bContext *C);
@@ -185,6 +252,7 @@ int ED_operator_posemode_context(struct bContext *C);
int ED_operator_posemode(struct bContext *C);
int ED_operator_posemode_local(struct bContext *C);
int ED_operator_mask(struct bContext *C);
+int ED_operator_camera(struct bContext *C);
/* Cache display helpers */
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index 6daaac5bb42..a81d63d9f25 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -39,8 +39,7 @@ struct rcti;
/* sculpt.c */
void ED_operatortypes_sculpt(void);
-void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *ar,
- struct RegionView3D *rv3d, struct Object *ob);
+void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *ar, struct Object *ob);
int ED_sculpt_mask_box_select(struct bContext *C, struct ViewContext *vc, const struct rcti *rect, bool select, bool extend);
#endif /* __ED_SCULPT_H__ */
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 9a0a7f8f1bb..536f9c22dcd 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -43,6 +43,7 @@ struct wmEvent;
struct wmKeyConfig;
struct wmKeyMap;
struct wmOperatorType;
+struct WorkSpace;
struct Main;
struct SnapObjectContext;
struct SnapObjectParams;
@@ -109,9 +110,10 @@ enum TfmMode {
bool calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], float cent2d[2]);
struct TransInfo;
-struct Base;
struct Scene;
struct Object;
+struct wmManipulatorGroup;
+struct wmManipulatorGroupType;
struct wmOperator;
/* UNUSED */
@@ -128,7 +130,7 @@ void BIF_createTransformOrientation(struct bContext *C, struct ReportList *repor
const char *name, const bool use_view,
const bool activate, const bool overwrite);
void BIF_selectTransformOrientation(struct bContext *C, struct TransformOrientation *ts);
-void BIF_selectTransformOrientationValue(struct bContext *C, int orientation);
+void BIF_selectTransformOrientationValue(struct View3D *v3d, int orientation);
void ED_getTransformOrientationMatrix(const struct bContext *C, float orientation_mat[3][3], const short around);
@@ -153,10 +155,16 @@ int BIF_countTransformOrientation(const struct bContext *C);
void Transform_Properties(struct wmOperatorType *ot, int flags);
-/* view3d manipulators */
+/* transform manipulators */
+
+void TRANSFORM_WGT_manipulator(struct wmManipulatorGroupType *wgt);
+void VIEW3D_WGT_xform_cage(struct wmManipulatorGroupType *wgt);
+
+bool ED_widgetgroup_manipulator2d_poll(const struct bContext *C, struct wmManipulatorGroupType *wgt);
+void ED_widgetgroup_manipulator2d_setup(const struct bContext *C, struct wmManipulatorGroup *mgroup);
+void ED_widgetgroup_manipulator2d_refresh(const struct bContext *C, struct wmManipulatorGroup *mgroup);
+void ED_widgetgroup_manipulator2d_draw_prepare(const struct bContext *C, struct wmManipulatorGroup *mgroup);
-int BIF_do_manipulator(struct bContext *C, const struct wmEvent *event, struct wmOperator *op);
-void BIF_draw_manipulator(const struct bContext *C);
/* Snapping */
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 156b0ab36b0..8761f2c5361 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -30,11 +30,14 @@ struct BMEdge;
struct BMFace;
struct ListBase;
+struct RenderEngineType;
struct Scene;
+struct ViewLayer;
struct Main;
struct Object;
struct ARegion;
struct View3D;
+struct bContext;
/* transform_snap_object.c */
@@ -73,9 +76,9 @@ struct SnapObjectParams {
typedef struct SnapObjectContext SnapObjectContext;
SnapObjectContext *ED_transform_snap_object_context_create(
- struct Main *bmain, struct Scene *scene, int flag);
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct RenderEngineType *engine_type, int flag);
SnapObjectContext *ED_transform_snap_object_context_create_view3d(
- struct Main *bmain, struct Scene *scene, int flag,
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct RenderEngineType *engine_type, int flag,
/* extra args for view3d */
const struct ARegion *ar, const struct View3D *v3d);
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx);
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 354a9655a48..96b4004b6a6 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -35,12 +35,13 @@ struct BMesh;
struct BMEditMesh;
struct BMFace;
struct BMLoop;
+struct Depsgraph;
struct Image;
struct ImageUser;
-struct MTexPoly;
struct Main;
struct Object;
struct Scene;
+struct ViewLayer;
struct SpaceImage;
struct bNode;
struct wmKeyConfig;
@@ -51,6 +52,7 @@ void ED_keymap_uvedit(struct wmKeyConfig *keyconf);
void ED_uvedit_assign_image(struct Main *bmain, struct Scene *scene, struct Object *obedit, struct Image *ima, struct Image *previma);
bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obedit, float min[2], float max[2]);
+bool ED_uvedit_center(Scene *scene, Image *ima, struct Object *obedit, float cent[2], char mode);
void ED_uvedit_select_all(struct BMesh *bm);
bool ED_object_get_active_image(struct Object *ob, int mat_nr,
@@ -60,7 +62,7 @@ void ED_object_assign_active_image(struct Main *bmain, struct Object *ob, int ma
bool ED_uvedit_test(struct Object *obedit);
/* visibility and selection */
-bool uvedit_face_visible_test(struct Scene *scene, struct Image *ima, struct BMFace *efa, struct MTexPoly *tf);
+bool uvedit_face_visible_test(struct Scene *scene, struct Image *ima, struct BMFace *efa);
bool uvedit_face_select_test(struct Scene *scene, struct BMFace *efa,
const int cd_loop_uv_offset);
bool uvedit_edge_select_test(struct Scene *scene, struct BMLoop *l,
@@ -110,7 +112,7 @@ void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel)
/* uvedit_draw.c */
void ED_image_draw_cursor(struct ARegion *ar, const float cursor[2]);
-void ED_uvedit_draw_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit, struct Object *obact);
+void ED_uvedit_draw_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct ViewLayer *view_layer, struct Object *obedit, struct Object *obact, struct Depsgraph *depsgraph);
/* uvedit_buttons.c */
void ED_uvedit_buttons_register(struct ARegionType *art);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 2cc928117c5..69061bdcd26 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -40,7 +40,10 @@ struct BPoint;
struct Base;
struct BezTriple;
struct BoundBox;
+struct Camera;
+struct Depsgraph;
struct EditBone;
+struct EvaluationContext;
struct ImBuf;
struct MVert;
struct Main;
@@ -49,14 +52,15 @@ struct Nurb;
struct Object;
struct RV3DMatrixStore;
struct RegionView3D;
+struct RenderEngineType;
struct Scene;
+struct ViewLayer;
struct ScrArea;
struct View3D;
struct ViewContext;
struct bContext;
struct bPoseChannel;
struct bScreen;
-struct bglMats;
struct rctf;
struct rcti;
struct wmOperator;
@@ -66,11 +70,15 @@ struct wmWindowManager;
struct GPUFX;
struct GPUOffScreen;
struct GPUFXSettings;
+struct WorkSpace;
enum eGPUFXFlags;
/* for derivedmesh drawing callbacks, for view3d_select, .... */
typedef struct ViewContext {
+ struct Depsgraph *depsgraph;
struct Scene *scene;
+ struct ViewLayer *view_layer;
+ struct RenderEngineType *engine_type;
struct Object *obact;
struct Object *obedit;
struct ARegion *ar;
@@ -108,10 +116,10 @@ void ED_view3d_lastview_store(struct RegionView3D *rv3d);
void ED_view3d_depth_update(struct ARegion *ar);
float ED_view3d_depth_read_cached(const struct ViewContext *vc, const int mval[2]);
bool ED_view3d_depth_read_cached_normal(
- const ViewContext *vc, const struct bglMats *mats, const int mval[2],
+ const ViewContext *vc, const int mval[2],
float r_normal[3]);
bool ED_view3d_depth_unproject(
- const struct ARegion *ar, const struct bglMats *mats,
+ const struct ARegion *ar,
const int mval[2], const double depth,
float r_location_world[3]);
void ED_view3d_depth_tag_update(struct RegionView3D *rv3d);
@@ -148,20 +156,20 @@ typedef enum {
/* foreach iterators */
void meshobject_foreachScreenVert(
- struct ViewContext *vc,
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc,
void (*func)(void *userData, struct MVert *eve, const float screen_co[2], int index),
void *userData, const eV3DProjTest clip_flag);
void mesh_foreachScreenVert(
- struct ViewContext *vc,
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc,
void (*func)(void *userData, struct BMVert *eve, const float screen_co[2], int index),
void *userData, const eV3DProjTest clip_flag);
void mesh_foreachScreenEdge(
- struct ViewContext *vc,
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc,
void (*func)(void *userData, struct BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2],
int index),
void *userData, const eV3DProjTest clip_flag);
void mesh_foreachScreenFace(
- struct ViewContext *vc,
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc,
void (*func)(void *userData, struct BMFace *efa, const float screen_co[2], int index),
void *userData, const eV3DProjTest clip_flag);
void nurbs_foreachScreenVert(
@@ -239,7 +247,9 @@ bool ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, cons
float r_ray_start[3], float r_ray_end[3], const bool do_clip);
void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]);
void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]);
-void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z);
+
+void ED_view3d_project(const struct ARegion *ar, const float world[3], float region[3]);
+bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3]);
/* end */
@@ -264,11 +274,13 @@ void ED_view3d_calc_camera_border_size(
const struct Scene *scene, const struct ARegion *ar,
const struct View3D *v3d, const struct RegionView3D *rv3d,
float r_size[2]);
-bool ED_view3d_calc_render_border(struct Scene *scene, struct View3D *v3d,
- struct ARegion *ar, struct rcti *rect);
+bool ED_view3d_calc_render_border(
+ const struct Scene *scene, struct View3D *v3d,
+ struct ARegion *ar, struct rcti *rect);
void ED_view3d_clipping_calc_from_boundbox(float clip[6][4], const struct BoundBox *clipbb, const bool is_flip);
-void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, const struct rcti *rect);
+void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4],
+ const struct ARegion *ar, const struct Object *ob, const struct rcti *rect);
void ED_view3d_clipping_local(struct RegionView3D *rv3d, float mat[4][4]);
bool ED_view3d_clipping_test(const struct RegionView3D *rv3d, const float co[3], const bool is_local);
void ED_view3d_clipping_set(struct RegionView3D *rv3d);
@@ -284,24 +296,26 @@ float ED_view3d_radius_to_dist(
const char persp, const bool use_aspect,
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);
-struct ImBuf *ED_view3d_backbuf_read(struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax);
+void ED_view3d_backbuf_validate(const struct EvaluationContext *eval_ctx, struct ViewContext *vc);
+struct ImBuf *ED_view3d_backbuf_read(
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax);
unsigned int ED_view3d_backbuf_sample_rect(
- struct ViewContext *vc, const int mval[2], int size,
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc, const int mval[2], int size,
unsigned int min, unsigned int max, float *r_dist);
int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist);
-unsigned int ED_view3d_backbuf_sample(struct ViewContext *vc, int x, int y);
+unsigned int ED_view3d_backbuf_sample(
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc, int x, int y);
bool ED_view3d_autodist(
- struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
+ const struct EvaluationContext *eval_ctx, struct Depsgraph *graph, struct ARegion *ar, struct View3D *v3d,
const int mval[2], float mouse_worldloc[3],
const bool alphaoverride, const float fallback_depth_pt[3]);
/* only draw so ED_view3d_autodist_simple can be called many times after */
-void ED_view3d_autodist_init(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, int mode);
+void ED_view3d_autodist_init(const struct EvaluationContext *eval_ctx, struct Depsgraph *graph, struct ARegion *ar, struct View3D *v3d, int mode);
bool ED_view3d_autodist_simple(struct ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth);
bool ED_view3d_autodist_depth(struct ARegion *ar, const int mval[2], int margin, float *depth);
bool ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth);
@@ -323,7 +337,7 @@ void view3d_opengl_select_cache_begin(void);
void view3d_opengl_select_cache_end(void);
int view3d_opengl_select(
- struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input,
+ const struct EvaluationContext *eval_ctx, struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input,
eV3DSelectMode select_mode);
/* view3d_select.c */
@@ -332,7 +346,6 @@ void view3d_set_viewcontext(struct bContext *C, struct ViewContext *vc);
void view3d_operator_needs_opengl(const struct bContext *C);
void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *ar);
void view3d_opengl_read_pixels(struct ARegion *ar, int x, int y, int w, int h, int format, int type, void *data);
-void view3d_get_transformation(const struct ARegion *ar, struct RegionView3D *rv3d, struct Object *ob, struct bglMats *mats);
/* XXX should move to BLI_math */
bool edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2]);
@@ -351,20 +364,25 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d);
# define ED_view3d_clear_mats_rv3d(rv3d) (void)(rv3d)
# define ED_view3d_check_mats_rv3d(rv3d) (void)(rv3d)
#endif
-int ED_view3d_scene_layer_set(int lay, const int *values, int *active);
+int ED_view3d_view_layer_set(int lay, const int *values, int *active);
struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d);
void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat);
+void ED_draw_object_facemap(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, const float col[4], const int facemap);
+
bool ED_view3d_context_activate(struct bContext *C);
-void ED_view3d_draw_offscreen_init(struct Scene *scene, struct View3D *v3d);
+void ED_view3d_draw_offscreen_init(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct ViewLayer *view_layer, struct View3D *v3d);
void ED_view3d_draw_offscreen(
- struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4],
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct ViewLayer *view_layer, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4],
float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
struct GPUFX *fx, struct GPUFXSettings *fx_settings,
struct GPUOffScreen *ofs);
void ED_view3d_draw_setup_view(
- struct wmWindow *win, struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
+ struct wmWindow *win, const struct EvaluationContext *eval_ctx, struct Scene *scene, struct ARegion *ar, struct View3D *v3d,
float viewmat[4][4], float winmat[4][4], const struct rcti *rect);
enum {
@@ -380,12 +398,14 @@ enum {
};
struct ImBuf *ED_view3d_draw_offscreen_imbuf(
- struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey,
- unsigned int flag, unsigned int draw_flags,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct ViewLayer *view_layer, struct View3D *v3d, struct ARegion *ar,
+ int sizex, int sizey, unsigned int flag, unsigned int draw_flags,
int alpha_mode, int samples, const char *viewname,
struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
- struct Scene *scene, struct Object *camera, int width, int height,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct ViewLayer *view_layer, struct Object *camera, int width, int height,
unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode,
int samples, const char *viewname,
struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
@@ -393,7 +413,7 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
void ED_view3d_update_viewmat(
- struct Scene *scene, struct View3D *v3d, struct ARegion *ar,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct View3D *v3d, struct ARegion *ar,
float viewmat[4][4], float winmat[4][4], const struct rcti *rect);
bool ED_view3d_quat_from_axis_view(const char view, float quat[4]);
char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon);
@@ -402,7 +422,7 @@ char ED_view3d_axis_view_opposite(char view);
bool ED_view3d_lock(struct RegionView3D *rv3d);
uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d);
-uint64_t ED_view3d_screen_datamask(const struct bScreen *screen);
+uint64_t ED_view3d_screen_datamask(const struct Scene *scene, const struct bScreen *screen);
bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d);
@@ -423,10 +443,6 @@ bool ED_view3d_camera_lock_autokey(
void ED_view3D_lock_clear(struct View3D *v3d);
-struct BGpic *ED_view3D_background_image_new(struct View3D *v3d);
-void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic);
-void ED_view3D_background_image_clear(struct View3D *v3d);
-
#define VIEW3D_MARGIN 1.4f
#define VIEW3D_DIST_FALLBACK 1.0f
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 0e936fdd313..eba31a21094 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -73,6 +73,7 @@ struct bNodeSocket;
struct wmDropBox;
struct wmDrag;
struct wmEvent;
+struct wmMsgBus;
typedef struct uiBut uiBut;
typedef struct uiBlock uiBlock;
@@ -183,6 +184,8 @@ enum {
UI_BUT_UPDATE_DELAY = (1 << 28), /* don't run updates while dragging (needed in rare cases). */
UI_BUT_TEXTEDIT_UPDATE = (1 << 29), /* when widget is in textedit mode, update value on each char stroke */
UI_BUT_VALUE_CLEAR = (1 << 30), /* show 'x' icon to clear/unlink value of text or search button */
+
+ UI_BUT_OVERRIDEN = (1 << 31), /* RNA property of the button is overriden from linked reference data. */
};
#define UI_PANEL_WIDTH 340
@@ -261,6 +264,7 @@ typedef enum {
UI_BTYPE_CHECKBOX = (13 << 9), /* similar to toggle, display a 'tick' */
UI_BTYPE_CHECKBOX_N = (14 << 9),
UI_BTYPE_COLOR = (15 << 9),
+ UI_BTYPE_TAB = (16 << 9),
UI_BTYPE_SCROLL = (18 << 9),
UI_BTYPE_BLOCK = (19 << 9),
UI_BTYPE_LABEL = (20 << 9),
@@ -313,18 +317,22 @@ typedef enum {
* Functions to draw various shapes, taking theme settings into account.
* Used for code that draws its own UI style elements. */
-void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad);
void UI_draw_roundbox_corner_set(int type);
+void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4]);
+void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4]);
+void UI_draw_roundbox_3ubAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const unsigned char col[3], unsigned char alpha);
+void UI_draw_roundbox_3fvAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[3], float alpha);
+void UI_draw_roundbox_shade_x(bool filled, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown, const float col[4]);
+
+#if 0 /* unused */
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_shade_y(bool filled, float minx, float miny, float maxx, float maxy, float rad, float shadeleft, float shaderight, const float col[4]);
+#endif
+
void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy);
-void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad);
-void UI_draw_roundbox_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_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]);
-void UI_draw_safe_areas(
- float x1, float x2, float y1, float y2,
+void UI_draw_safe_areas(uint pos, float x1, float x2, float y1, float y2,
const float title_aspect[2], const float action_aspect[2]);
/* state for scrolldrawing */
@@ -800,7 +808,6 @@ void UI_popup_handlers_remove_all(struct bContext *C, struct ListBase *handlers)
void UI_init(void);
void UI_init_userdef(void);
void UI_reinit_font(void);
-void UI_reinit_gl_state(void);
void UI_exit(void);
/* Layout
@@ -865,13 +872,12 @@ enum {
UI_CNR_ALL = (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT)
};
-/* not apart of the corner flags but mixed in some functions */
-#define UI_RB_ALPHA (UI_CNR_ALL + 1)
-
uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int size, int em, int padding, struct uiStyle *style);
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout);
void UI_block_layout_resolve(uiBlock *block, int *x, int *y);
+void UI_region_message_subscribe(struct ARegion *ar, struct wmMsgBus *mbus);
+
uiBlock *uiLayoutGetBlock(uiLayout *layout);
void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv);
@@ -926,6 +932,17 @@ void uiTemplateIDPreview(uiLayout *layout, struct bContext *C, struct PointerRNA
const char *newop, const char *openop, const char *unlinkop, int rows, int cols);
void uiTemplateAnyID(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
const char *proptypename, const char *text);
+void uiTemplateSearch(
+ uiLayout *layout, struct bContext *C,
+ struct PointerRNA *ptr, const char *propname,
+ struct PointerRNA *searchptr, const char *searchpropname,
+ const char *newop, const char *unlinkop);
+void uiTemplateSearchPreview(
+ uiLayout *layout, struct bContext *C,
+ struct PointerRNA *ptr, const char *propname,
+ struct PointerRNA *searchptr, const char *searchpropname,
+ const char *newop, const char *unlinkop,
+ const int rows, const int cols);
void uiTemplatePathBuilder(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
struct PointerRNA *root_ptr, const char *text);
uiLayout *uiTemplateModifier(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
@@ -962,6 +979,11 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C);
void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C);
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
+void uiTemplateOverrideProperty(
+ uiLayout *layout, struct PointerRNA *collection_props_ptr, struct PointerRNA *scene_props_ptr,
+ const char *propname,
+ const char *name, const char *text_ctxt, int translate, int icon,
+ const char *custom_template);
void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
void uiTemplateCacheFile(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname);
@@ -1071,20 +1093,22 @@ 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 unsigned char fg[4], const unsigned char bg[4]);
+ const float col_fg[4], const float col_bg[4]);
int UI_fontstyle_string_width(const struct uiFontStyle *fs, const char *str);
int UI_fontstyle_height_max(const struct uiFontStyle *fs);
-void UI_draw_icon_tri(float x, float y, char dir);
+void UI_draw_icon_tri(float x, float y, char dir, const float[4]);
struct uiStyle *UI_style_get(void); /* use for fonts etc */
struct uiStyle *UI_style_get_dpi(void); /* DPI scaled settings for drawing */
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 945ac1b6db9..cee68ed361c 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -66,6 +66,7 @@ void UI_id_icon_render(
int UI_preview_render_size(enum eIconSizes size);
void UI_icon_draw(float x, float y, int icon_id);
+void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha);
void UI_icon_draw_preview(float x, float y, int icon_id);
void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect);
void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, float alpha, int size);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index a0efd586af5..7d2837ffe4e 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -279,6 +279,12 @@ enum {
TH_AXIS_Y,
TH_AXIS_Z,
+ TH_MANIPULATOR_HI,
+ TH_MANIPULATOR_PRIMARY,
+ TH_MANIPULATOR_SECONDARY,
+ TH_MANIPULATOR_A,
+ TH_MANIPULATOR_B,
+
TH_LOW_GRAD,
TH_HIGH_GRAD,
TH_SHOW_BACK_GRAD,
@@ -319,13 +325,13 @@ struct bThemeState {
void UI_ThemeColor(int colorid);
// sets the color plus alpha
-void UI_ThemeColor4(int colorid);
+void UI_ThemeColor4(int colorid);
// sets color plus offset for shade
-void UI_ThemeColorShade(int colorid, int offset);
+void UI_ThemeColorShade(int colorid, int offset);
// sets color plus offset for alpha
-void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset);
+void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset);
// sets color, which is blend between two theme colors
void UI_ThemeColorBlend(int colorid1, int colorid2, float fac);
@@ -343,14 +349,27 @@ int UI_GetThemeValueType(int colorid, int spacetype);
// get three color values, scaled to 0.0-1.0 range
void UI_GetThemeColor3fv(int colorid, float col[3]);
void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3]);
+void UI_GetThemeColorBlend3f(int colorid1, int colorid2, float fac, float r_col[3]);
// 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]);
// get four color values, range 0.0-1.0, complete with shading offset for the RGB components
void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4]);
+void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4]);
+
+// get four colour values ranged between 0 and 255; includes the alpha channel
+void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4]);
+
+// get four color values, range 0.0-1.0, complete with shading offset for the RGB components and blending
+void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3]);
+void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4]);
// get the 3 or 4 byte values
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3]);
@@ -368,6 +387,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/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index 7392db0c91b..03a2c1ec414 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../gpu
../../imbuf
../../makesdna
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 5f36c5e21bf..9e6d9f23442 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -41,6 +41,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
@@ -56,7 +57,8 @@
#include "BKE_screen.h"
#include "BKE_idprop.h"
-#include "BIF_gl.h"
+#include "GPU_glew.h"
+#include "GPU_matrix.h"
#include "BLF_api.h"
#include "BLT_translation.h"
@@ -68,11 +70,14 @@
#include "WM_api.h"
#include "WM_types.h"
#include "wm_subwindow.h"
+#include "WM_message.h"
#include "RNA_access.h"
#include "BPY_extern.h"
+#include "ED_screen.h"
+
#include "IMB_colormanagement.h"
#include "interface_intern.h"
@@ -509,6 +514,7 @@ static int ui_but_calc_float_precision(uiBut *but, double value)
static void ui_draw_linkline(uiLinkLine *line, int highlightActiveLines, int dashInactiveLines)
{
rcti rect;
+ float color[4] = {1.0f};
if (line->from == NULL || line->to == NULL) return;
@@ -518,15 +524,15 @@ static void ui_draw_linkline(uiLinkLine *line, int highlightActiveLines, int das
rect.ymax = BLI_rctf_cent_y(&line->to->rect);
if (dashInactiveLines)
- UI_ThemeColor(TH_GRID);
+ UI_GetThemeColor4fv(TH_GRID, color);
else if (line->flag & UI_SELECT)
- glColor3ub(100, 100, 100);
+ rgba_float_args_set_ch(color, 100, 100, 100, 255);
else if (highlightActiveLines && ((line->from->flag & UI_ACTIVE) || (line->to->flag & UI_ACTIVE)))
- UI_ThemeColor(TH_TEXT_HI);
+ UI_GetThemeColor4fv(TH_TEXT_HI, color);
else
- glColor3ub(0, 0, 0);
+ rgba_float_args_set_ch(color, 0, 0, 0, 255);
- ui_draw_link_bezier(&rect);
+ ui_draw_link_bezier(&rect, color);
}
static void ui_draw_links(uiBlock *block)
@@ -1214,6 +1220,20 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
}
}
+void ui_but_override_flag(uiBut *but)
+{
+ bool is_overridden;
+
+ RNA_property_override_status(&but->rnapoin, but->rnaprop, but->rnaindex, NULL, &is_overridden, NULL, NULL);
+
+ if (is_overridden) {
+ but->flag |= UI_BUT_OVERRIDEN;
+ }
+ else {
+ but->flag &= ~UI_BUT_OVERRIDEN;
+ }
+}
+
void UI_block_update_from_old(const bContext *C, uiBlock *block)
{
uiBut *but_old;
@@ -1278,6 +1298,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
}
ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
+ ui_but_override_flag(but);
}
@@ -1400,11 +1421,9 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ui_but_to_pixelrect(&rect, ar, block, NULL);
/* pixel space for AA widgets */
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
+ gpuPushProjectionMatrix();
+ gpuPushMatrix();
+ gpuLoadIdentity();
wmOrtho2_region_pixelspace(ar);
@@ -1429,10 +1448,8 @@ void UI_block_draw(const bContext *C, uiBlock *block)
}
/* restore matrix */
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ gpuPopProjectionMatrix();
+ gpuPopMatrix();
if (multisample_enabled)
glEnable(GL_MULTISAMPLE);
@@ -1440,6 +1457,40 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ui_draw_links(block);
}
+static void ui_block_message_subscribe(ARegion *ar, struct wmMsgBus *mbus, uiBlock *block)
+{
+ uiBut *but_prev = NULL;
+ /* possibly we should keep the region this block is contained in? */
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
+ if (but->rnapoin.type && but->rnaprop) {
+ /* quick check to avoid adding buttons representing a vector, multiple times. */
+ if ((but_prev &&
+ (but_prev->rnaprop == but->rnaprop) &&
+ (but_prev->rnapoin.type == but->rnapoin.type) &&
+ (but_prev->rnapoin.data == but->rnapoin.data) &&
+ (but_prev->rnapoin.id.data == but->rnapoin.id.data)) == false)
+ {
+ /* TODO: could make this into utility function. */
+ WM_msg_subscribe_rna(
+ mbus, &but->rnapoin, but->rnaprop,
+ &(const wmMsgSubscribeValue){
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ }, __func__);
+ but_prev = but;
+ }
+ }
+ }
+}
+
+void UI_region_message_subscribe(ARegion *ar, struct wmMsgBus *mbus)
+{
+ for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ ui_block_message_subscribe(ar, mbus, block);
+ }
+}
+
/* ************* EVENTS ************* */
/**
@@ -1486,6 +1537,7 @@ int ui_but_is_pushed_ex(uiBut *but, double *value)
break;
case UI_BTYPE_ROW:
case UI_BTYPE_LISTROW:
+ case UI_BTYPE_TAB:
UI_GET_BUT_VALUE_INIT(but, *value);
/* support for rna enum buts */
if (but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) {
@@ -2425,7 +2477,7 @@ static void ui_but_string_free_internal(uiBut *but)
bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
{
- if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
+ if (but->rnaprop && but->rnapoin.data && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) {
if (RNA_property_editable(&but->rnapoin, but->rnaprop)) {
PropertyType type;
@@ -2472,8 +2524,15 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
}
else if (but->type == UI_BTYPE_TEXT) {
/* string */
- if (ui_but_is_utf8(but)) BLI_strncpy_utf8(but->poin, str, but->hardmax);
- else BLI_strncpy(but->poin, str, but->hardmax);
+ if (!but->poin || (str[0] == '\0')) {
+ str = "";
+ }
+ else if (ui_but_is_utf8(but)) {
+ BLI_strncpy_utf8(but->poin, str, but->hardmax);
+ }
+ else {
+ BLI_strncpy(but->poin, str, but->hardmax);
+ }
return true;
}
@@ -2685,6 +2744,10 @@ static void ui_but_free(const bContext *C, uiBut *but)
MEM_freeN(but->hold_argN);
}
+ if (!but->editstr && but->free_search_arg) {
+ MEM_SAFE_FREE(but->search_arg);
+ }
+
if (but->active) {
/* XXX solve later, buttons should be free-able without context ideally,
* however they may have open tooltips or popup windows, which need to
@@ -2837,11 +2900,13 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh
block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]);
}
else {
+ const bScreen *screen = WM_window_get_active_screen(window);
+
/* no subwindow created yet, for menus for example, so we
* use the main window instead, since buttons are created
* there anyway */
- wm_subwindow_matrix_get(window, window->screen->mainwin, block->winmat);
- wm_subwindow_size_get(window, window->screen->mainwin, &getsizex, &getsizey);
+ wm_subwindow_matrix_get(window, screen->mainwin, block->winmat);
+ wm_subwindow_size_get(window, screen->mainwin, &getsizex, &getsizey);
block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]);
block->auto_open = true;
@@ -3558,7 +3623,7 @@ static uiBut *ui_def_but_rna(
}
const char *info;
- if (!RNA_property_editable_info(&but->rnapoin, prop, &info)) {
+ if (but->rnapoin.data && !RNA_property_editable_info(&but->rnapoin, prop, &info)) {
ui_def_but_rna__disable(but, info);
}
@@ -4457,7 +4522,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *but, const c
for (item = item_array; item->identifier; item++) {
/* note: need to give the index rather than the identifier because the enum can be freed */
if (BLI_strcasestr(item->name, str)) {
- if (false == UI_search_item_add(items, item->name, SET_INT_IN_POINTER(item->value), 0))
+ if (false == UI_search_item_add(items, item->name, SET_INT_IN_POINTER(item->value), item->icon))
break;
}
}
@@ -4588,7 +4653,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
tmp = BLI_strdup(RNA_property_identifier(but->rnaprop));
}
else if (type == BUT_GET_RNASTRUCT_IDENTIFIER) {
- if (but->rnaprop)
+ if (but->rnaprop && but->rnapoin.data)
tmp = BLI_strdup(RNA_struct_identifier(but->rnapoin.type));
else if (but->optype)
tmp = BLI_strdup(but->optype->idname);
@@ -4683,7 +4748,10 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
if (ptr && prop) {
if (!item) {
int i;
-
+
+ /* so the context is passed to itemf functions */
+ WM_operator_properties_sanitize(ptr, false);
+
RNA_property_enum_items_gettexted(C, ptr, prop, &items, &totitems, &free_items);
for (i = 0, item = items; i < totitems; i++, item++) {
if (item->identifier[0] && item->value == value)
diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c
index 500744c366d..9aeb685a907 100644
--- a/source/blender/editors/interface/interface_align.c
+++ b/source/blender/editors/interface/interface_align.c
@@ -110,9 +110,9 @@ enum {
bool ui_but_can_align(const uiBut *but)
{
- return (
- !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE) &&
- (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f));
+ const bool btype_can_align = !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N,
+ UI_BTYPE_TAB, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE);
+ return (btype_can_align && (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f));
}
/**
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index a04360b3395..812f4ef0747 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -39,11 +39,12 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_nla.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_keyframing.h"
#include "UI_interface.h"
@@ -211,7 +212,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
/* updates */
driver->flag |= DRIVER_FLAG_RECOMPILE;
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL);
ok = true;
}
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 9a05c12e00a..3ecb72353bc 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -50,13 +50,14 @@
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BLF_api.h"
-#include "GPU_draw.h"
-#include "GPU_basic_shader.h"
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#include "UI_interface.h"
@@ -71,336 +72,462 @@ void UI_draw_roundbox_corner_set(int type)
* if this is undone, it's not that big a deal, only makes curves edges
* square for the */
roundboxtype = type;
-
}
+#if 0 /* unused */
int UI_draw_roundbox_corner_get(void)
{
return roundboxtype;
}
+#endif
+
+void UI_draw_roundbox_3ubAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const unsigned char col[3], unsigned char alpha)
+{
+ float colv[4];
+ colv[0] = ((float)col[0]) / 255;
+ colv[1] = ((float)col[1]) / 255;
+ colv[2] = ((float)col[2]) / 255;
+ colv[3] = ((float)alpha) / 255;
+ UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
+}
+
+void UI_draw_roundbox_3fvAlpha(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[3], float alpha)
+{
+ float colv[4];
+ colv[0] = col[0];
+ colv[1] = col[1];
+ colv[2] = col[2];
+ colv[3] = alpha;
+ UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv);
+}
-void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad)
+void UI_draw_roundbox_4fv(bool filled, float minx, float miny, float maxx, float maxy, float rad, 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}};
int a;
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
/* mult */
for (a = 0; a < 7; a++) {
mul_v2_fl(vec[a], rad);
}
- glBegin(mode);
+ unsigned int vert_ct = 0;
+ vert_ct += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1;
+ vert_ct += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1;
+ vert_ct += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1;
+ vert_ct += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1;
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(col);
+ immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, vert_ct);
/* start with corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- glVertex2f(maxx - rad, miny);
+ immVertex2f(pos, maxx - rad, miny);
for (a = 0; a < 7; a++) {
- glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
}
- glVertex2f(maxx, miny + rad);
+ immVertex2f(pos, maxx, miny + rad);
}
else {
- glVertex2f(maxx, miny);
+ immVertex2f(pos, maxx, miny);
}
/* corner right-top */
if (roundboxtype & UI_CNR_TOP_RIGHT) {
- glVertex2f(maxx, maxy - rad);
+ immVertex2f(pos, maxx, maxy - rad);
for (a = 0; a < 7; a++) {
- glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
}
- glVertex2f(maxx - rad, maxy);
+ immVertex2f(pos, maxx - rad, maxy);
}
else {
- glVertex2f(maxx, maxy);
+ immVertex2f(pos, maxx, maxy);
}
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
- glVertex2f(minx + rad, maxy);
+ immVertex2f(pos, minx + rad, maxy);
for (a = 0; a < 7; a++) {
- glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
}
- glVertex2f(minx, maxy - rad);
+ immVertex2f(pos, minx, maxy - rad);
}
else {
- glVertex2f(minx, maxy);
+ immVertex2f(pos, minx, maxy);
}
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- glVertex2f(minx, miny + rad);
+ immVertex2f(pos, minx, miny + rad);
for (a = 0; a < 7; a++) {
- glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
}
- glVertex2f(minx + rad, miny);
+ immVertex2f(pos, minx + rad, miny);
}
else {
- glVertex2f(minx, miny);
+ immVertex2f(pos, minx, miny);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
-static void round_box_shade_col(const float col1[3], float const col2[3], const float fac)
+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)
+ bool filled, float minx, float miny, float maxx, float maxy,
+ 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;
-
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_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);
/* '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(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 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();
}
+#if 0 /* unused */
/* 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)
+ bool filled, float minx, float miny, float maxx, float maxy,
+ 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);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_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);
+
- 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(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 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();
}
+#endif /* unused */
-/* plain antialiased unfilled rectangle */
-void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad)
+void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4])
{
- float color[4];
-
- if (roundboxtype & UI_RB_ALPHA) {
- glGetFloatv(GL_CURRENT_COLOR, color);
- color[3] = 0.5;
- glColor4fv(color);
- glEnable(GL_BLEND);
- }
-
- /* set antialias line */
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ int ofs_y = 4 * U.pixelsize;
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
-}
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
-/* (old, used in outliner) plain antialiased filled box */
-void UI_draw_roundbox(float minx, float miny, float maxx, float maxy, float rad)
-{
- ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA);
+ immRecti(pos, pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
+ immUnbindProgram();
}
-void UI_draw_text_underline(int pos_x, int pos_y, int len, int height)
+/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
+
+/* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */
+void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3])
{
- int ofs_y = 4 * U.pixelsize;
- glRecti(pos_x, pos_y - ofs_y, pos_x + len, pos_y - ofs_y + (height * U.pixelsize));
-}
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ /* add a 1px offset, looks nicer */
+ const int minx = rect->xmin + U.pixelsize, maxx = rect->xmax - U.pixelsize;
+ const int miny = rect->ymin + U.pixelsize, maxy = rect->ymax - U.pixelsize;
+ int a;
+ float vec[4][2] = {
+ {0.195, 0.02},
+ {0.55, 0.169},
+ {0.831, 0.45},
+ {0.98, 0.805},
+ };
-/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
+
+ /* mult */
+ for (a = 0; a < 4; a++) {
+ mul_v2_fl(vec[a], rad);
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ immBeginAtMost(GWN_PRIM_LINE_STRIP, 25);
+
+ immAttrib3ubv(col, highlight);
+
+ /* start with corner left-top */
+ if (roundboxtype & UI_CNR_TOP_LEFT) {
+ immVertex2f(pos, minx, maxy - rad);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, minx + vec[a][1], maxy - rad + vec[a][0]);
+ }
+ immVertex2f(pos, minx + rad, maxy);
+ }
+ else {
+ immVertex2f(pos, minx, maxy);
+ }
+
+ /* corner right-top */
+ if (roundboxtype & UI_CNR_TOP_RIGHT) {
+ immVertex2f(pos, maxx - rad, maxy);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, maxx - rad + vec[a][0], maxy - vec[a][1]);
+ }
+ immVertex2f(pos, maxx, maxy - rad);
+ }
+ else {
+ immVertex2f(pos, maxx, maxy);
+ }
+
+ immAttrib3ubv(col, highlight_fade);
+
+ /* corner right-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
+ immVertex2f(pos, maxx, miny + rad);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, maxx - vec[a][1], miny + rad - vec[a][0]);
+ }
+ immVertex2f(pos, maxx - rad, miny);
+ }
+ else {
+ immVertex2f(pos, maxx, miny);
+ }
+
+ /* corner left-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
+ immVertex2f(pos, minx + rad, miny);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, minx + rad - vec[a][0], miny + vec[a][1]);
+ }
+ immVertex2f(pos, minx, miny + rad);
+ }
+ else {
+ immVertex2f(pos, minx, miny);
+ }
+
+ immAttrib3ubv(col, highlight);
+
+ /* back to corner left-top */
+ immVertex2f(pos, minx, roundboxtype & UI_CNR_TOP_LEFT ? maxy - rad : maxy);
+
+ immEnd();
+ immUnbindProgram();
+}
void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
{
@@ -411,15 +538,15 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
ImBuf *ibuf = (ImBuf *)but->poin;
if (!ibuf) return;
+
+ float facx = 1.0f;
+ float facy = 1.0f;
int w = BLI_rcti_size_x(rect);
int h = BLI_rcti_size_y(rect);
/* scissor doesn't seem to be doing the right thing...? */
#if 0
- //glColor4f(1.0, 0.f, 0.f, 1.f);
- //fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax)
-
/* prevent drawing outside widget area */
GLint scissor[4];
glGetIntegerv(GL_SCISSOR_BOX, scissor);
@@ -427,16 +554,15 @@ 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);
if (w != ibuf->x || h != ibuf->y) {
- float facx = (float)w / (float)ibuf->x;
- float facy = (float)h / (float)ibuf->y;
- glPixelZoom(facx, facy);
+ facx = (float)w / (float)ibuf->x;
+ facy = (float)h / (float)ibuf->y;
}
- glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect);
-
- glPixelZoom(1.0f, 1.0f);
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state, (float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect,
+ facx, facy, NULL);
glDisable(GL_BLEND);
@@ -451,43 +577,34 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
/**
* Draw title and text safe areas.
*
- * The first 4 parameters are the offsets for the view, not the zones.
+ * \Note This functionn is to be used with the 2D dashed shader enabled.
+ *
+ * \param pos is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib
+ * \param line_origin is a PRIM_FLOAT, 2, GWN_FETCH_FLOAT vertex attrib
+ *
+ * The next 4 parameters are the offsets for the view, not the zones.
*/
void UI_draw_safe_areas(
- float x1, float x2, float y1, float y2,
+ uint pos, float x1, float x2, float y1, float y2,
const float title_aspect[2], const float action_aspect[2])
{
const float size_x_half = (x2 - x1) * 0.5f;
const float size_y_half = (y2 - y1) * 0.5f;
const float *safe_areas[] = {title_aspect, action_aspect};
- int safe_len = ARRAY_SIZE(safe_areas);
- bool is_first = true;
+ const int safe_len = ARRAY_SIZE(safe_areas);
for (int i = 0; i < safe_len; i++) {
if (safe_areas[i][0] || safe_areas[i][1]) {
- float margin_x, margin_y;
- float minx, miny, maxx, maxy;
+ float margin_x = safe_areas[i][0] * size_x_half;
+ float margin_y = safe_areas[i][1] * size_y_half;
- if (is_first) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
- is_first = false;
- }
+ float minx = x1 + margin_x;
+ float miny = y1 + margin_y;
+ float maxx = x2 - margin_x;
+ float maxy = y2 - margin_y;
- margin_x = safe_areas[i][0] * size_x_half;
- margin_y = safe_areas[i][1] * size_y_half;
-
- minx = x1 + margin_x;
- miny = y1 + margin_y;
- maxx = x2 - margin_x;
- maxy = y2 - margin_y;
-
- glBegin(GL_LINE_LOOP);
- glVertex2f(maxx, miny);
- glVertex2f(maxx, maxy);
- glVertex2f(minx, maxy);
- glVertex2f(minx, miny);
- glEnd();
+ imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
}
}
}
@@ -501,52 +618,60 @@ static void draw_scope_end(const rctf *rect, GLint *scissor)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* outline */
- glColor4f(0.f, 0.f, 0.f, 0.5f);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.5f};
+ UI_draw_roundbox_4fv(false, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f, color);
}
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(GWN_PRIM_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(GWN_PRIM_TRI_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(GWN_PRIM_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);
@@ -559,7 +684,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,
@@ -573,9 +698,10 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- UI_ThemeColor4(TH_PREVIEW_BACK);
+ float color[4];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, 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];
@@ -585,34 +711,48 @@ 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);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_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);
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, rect.xmin, rect.ymin + fac * h);
+ immVertex2f(pos, rect.xmax, rect.ymin + fac * h);
+
+ immVertex2f(pos, rect.xmin + fac * w, rect.ymin);
+ immVertex2f(pos, rect.xmin + fac * w, rect.ymax);
+
+ immEnd();
}
-
+
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);
@@ -620,6 +760,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])
+{
+ Gwn_VertFormat format = {0};
+ unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, nbr);
+
+ GWN_vertbuf_attr_fill(vbo, pos_id, waveform);
+
+ /* TODO store the Gwn_Batch inside the scope */
+ Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
+ GWN_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f);
+ GWN_batch_draw(batch);
+
+ GWN_batch_discard(batch);
+}
+
void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *recti)
{
Scopes *scopes = (Scopes *)but->poin;
@@ -642,7 +801,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 */
@@ -660,9 +819,10 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- UI_ThemeColor4(TH_PREVIEW_BACK);
+ float color[4];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, 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);
@@ -671,94 +831,119 @@ 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);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
+
+ /* draw grid lines here */
+ immBegin(GWN_PRIM_LINES, 12);
+
+ for (int i = 0; i < 6; i++) {
+ immVertex2f(pos, rect.xmin + 22, yofs + (i * 0.2f) * h);
+ immVertex2f(pos, rect.xmax + 1, yofs + (i * 0.2f) * h);
}
+
+ immEnd();
+
/* 3 vertical separation */
if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
+ immBegin(GWN_PRIM_LINES, 4);
+
for (int i = 1; i < 3; i++) {
- fdrawline(rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax);
+ immVertex2f(pos, rect.xmin + i * w3, rect.ymin);
+ immVertex2f(pos, rect.xmin + i * w3, rect.ymax);
}
+
+ immEnd();
}
/* separate min max zone on the right */
- fdrawline(rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax);
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmin + w, rect.ymin);
+ immVertex2f(pos, rect.xmin + w, rect.ymax);
+ immEnd();
+
/* 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);
+ immBegin(GWN_PRIM_LINES, 8);
+
+ immVertex2f(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f);
+ immVertex2f(pos, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
+
+ immEnd();
}
/* 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);
+ if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmin, yofs + h * 0.075f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 0.075f);
+ immEnd();
+ }
if (scopes->ok && scopes->waveform_1 != NULL) {
-
- /* LUMA (1 channel) */
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();
+ gpuTranslate2f(rect.xmin, yofs);
+ gpuScale2f(w, h);
- glDisableClientState(GL_VERTEX_ARRAY);
- glPopMatrix();
+ waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col);
+
+ 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);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmax - 3, min);
+ immVertex2f(pos, rect.xmax - 3, max);
+ immEnd();
}
/* RGB (3 channel) */
else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) {
- glBlendFunc(GL_ONE, GL_ONE);
-
- glEnableClientState(GL_VERTEX_ARRAY);
-
- glPushMatrix();
+ gpuPushMatrix();
+ gpuTranslate2f(rect.xmin, yofs);
+ gpuScale2f(w, h);
- glTranslatef(rect.xmin, yofs, 0.f);
- glScalef(w, h, 0.f);
+ 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[0] );
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
-
- 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,
@@ -770,49 +955,47 @@ 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);
+ gpuPushMatrix();
+ gpuTranslate2f(rect.xmin, yofs);
+ gpuScale2f(w3, h);
- glTranslatef(rect.xmin, yofs, 0.f);
- glScalef(w3, h, 0.f);
+ waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
- glColor3fv((rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+ gpuTranslate2f(1.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[1] : colorsycc_alpha[1]);
- glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2);
- glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+ gpuTranslate2f(1.0f, 0.0f);
+ waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
- 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);
-
- 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);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, rect.xmin + w + 2 + c * 2, min);
+ immVertex2f(pos, rect.xmin + w + 2 + c * 2, max);
+ immEnd();
}
}
}
-
+
+ immUnbindProgram();
+
/* outline */
draw_scope_end(&rect, scissor);
+
+ glDisable(GL_BLEND);
}
static float polar_to_x(float center, float diam, float ampli, float angle)
@@ -825,10 +1008,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);
@@ -840,41 +1023,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(GWN_PRIM_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(GWN_PRIM_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(GWN_PRIM_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(GWN_PRIM_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(GWN_PRIM_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)
@@ -895,8 +1078,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;
@@ -904,9 +1087,10 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- UI_ThemeColor4(TH_PREVIEW_BACK);
+ float color[4];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, 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];
@@ -916,93 +1100,109 @@ 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);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_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);
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, centerx - (diam * 0.5f) - 5, centery);
+ immVertex2f(pos, centerx + (diam * 0.5f) + 5, centery);
+
+ immVertex2f(pos, centerx, centery - (diam * 0.5f) - 5);
+ immVertex2f(pos, centerx, centery + (diam * 0.5f) + 5);
+
+ immEnd();
+
/* circles */
for (int j = 0; j < 5; j++) {
- glBegin(GL_LINE_LOOP);
const int increment = 15;
+ immBegin(GWN_PRIM_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);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad));
+ immVertex2f(pos, polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad));
+ immEnd();
+
/* 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);
+ gpuPushMatrix();
+ gpuTranslate2f(centerx, centery);
+ gpuScaleUniform(diam);
- 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();
}
+ 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(GWN_PRIM_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 ? GWN_PRIM_TRIS : GWN_PRIM_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 ? GWN_PRIM_TRI_FAN : GWN_PRIM_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,
+ uint shdr_pos, const rcti *rect, float x,
const float rgb[3], struct ColorManagedDisplay *display,
bool active)
{
@@ -1021,18 +1221,26 @@ 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();
- setlinestyle(active ? 2 : 1);
- glBegin(GL_LINES);
- glColor3ub(200, 200, 200);
- glVertex2f(x, y1);
- glVertex2f(x, y2);
- glEnd();
- setlinestyle(0);
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.8f, 0.8f, 0.8f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", active ? 4.0f : 2.0f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(shdr_pos, x, y1);
+ immVertex2f(shdr_pos, x, y2);
+ immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* hide handles when zoomed out too far */
if (half_width < min_width) {
@@ -1043,45 +1251,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(shdr_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(shdr_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(shdr_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(shdr_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(shdr_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(shdr_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(shdr_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;
@@ -1092,20 +1301,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);
+ Gwn_VertFormat *format = immVertexFormat();
+ position = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_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 = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
/* layer: color ramp */
glEnable(GL_BLEND);
@@ -1118,7 +1332,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(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2);
for (int a = 0; a <= sizex; a++) {
float pos = ((float)a) / sizex;
BKE_colorband_evaluate(coba, pos, colf);
@@ -1127,17 +1341,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(GWN_PRIM_TRI_STRIP, (sizex + 1) * 2);
for (int a = 0; a <= sizex; a++) {
float pos = ((float)a) / sizex;
BKE_colorband_evaluate(coba, pos, colf);
@@ -1146,31 +1360,48 @@ 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 = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_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_box_wire_2d(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);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(position, x1, y1);
+ immVertex2f(position, x1 + sizex, y1);
+ immEnd();
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(position, x1, y1 - 1);
+ immVertex2f(position, x1 + sizex, y1 - 1);
+ immEnd();
+
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);
}
}
@@ -1178,117 +1409,100 @@ 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 */
- glColor3ubv((unsigned char *)wcol->inner);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f);
+ UI_draw_roundbox_3ubAlpha(true, 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);
/* 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);
+ 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));
+ size = 0.5f * BLI_rcti_size_y(rect);
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- 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();
- }
+ gpuTranslate2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect));
+ gpuScaleUniform(size);
- glCallList(displist);
+ Gwn_Batch *sphere = GPU_batch_preset_sphere(2);
+ GWN_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING);
+ GWN_batch_uniform_4f(sphere, "color", diffuse[0], diffuse[1], diffuse[2], 1.0f);
+ GWN_batch_uniform_3fv(sphere, "light", light);
+ GWN_batch_draw(sphere);
/* restore */
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- GPU_default_lights();
glDisable(GL_CULL_FACE);
/* AA circle */
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_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_circle_wire_2d(pos, 0.0f, 0.0f, 1.0f, 32);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
/* matrix after circle */
- glPopMatrix();
+ gpuPopMatrix();
- /* 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(GWN_PRIM_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)
@@ -1324,10 +1538,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 */
@@ -1340,96 +1552,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);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_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(GWN_PRIM_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(GWN_PRIM_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(GWN_PRIM_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(GWN_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2);
if (cuma->table == NULL)
curvemapping_changed(cumap, false);
@@ -1438,52 +1659,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 = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
cmp = cuma->curve;
glPointSize(3.0f);
- glBegin(GL_POINTS);
+ immBegin(GWN_PRIM_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 = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv((unsigned char *)wcol->outline);
+ imm_draw_box_wire_2d(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)
@@ -1513,9 +1749,9 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
(rect.ymax + 1) - (rect.ymin - 1));
if (scopes->track_disabled) {
- glColor4f(0.7f, 0.3f, 0.3f, 0.3f);
+ float color[4] = {0.7f, 0.3f, 0.3f, 0.3f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
ok = true;
}
@@ -1542,62 +1778,72 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
}
if (!ok && scopes->track_preview) {
- glPushMatrix();
+ 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 col_sel[4], col_outline[4];
if (scopes->use_track_mask) {
- glColor4f(0.0f, 0.0f, 0.0f, 0.3f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, 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);
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state, rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, drawibuf->rect, 1.0f, 1.0f, NULL);
/* draw cross for pixel position */
- glTranslatef(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1], 0.f);
+ gpuTranslate2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]);
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);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_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(GWN_PRIM_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();
ok = true;
}
if (!ok) {
- glColor4f(0.f, 0.f, 0.f, 0.3f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_4fv(true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
}
/* outline */
@@ -1643,26 +1889,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);
-
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv(but->col);
+
glEnable(GL_BLEND);
- glBegin(GL_POLYGON);
+ immBegin(GWN_PRIM_TRI_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(GWN_PRIM_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]);
@@ -1670,47 +1921,91 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol
/* ****************************************************** */
+/* TODO: high quality UI drop shadows using GLSL shader and single draw call
+ * would replace / modify the following 3 functions - merwin
+ */
-static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
+static void ui_shadowbox(unsigned pos, unsigned color, float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
{
+ /* v1-_
+ * | -_v2
+ * | |
+ * | |
+ * | |
+ * v7_______v3____v4
+ * \ | /
+ * \ | _v5
+ * v8______v6_-
+ */
+ const float v1[2] = {maxx, maxy - 0.3f * shadsize};
+ const float v2[2] = {maxx + shadsize, maxy - 0.75f * shadsize};
+ const float v3[2] = {maxx, miny};
+ const float v4[2] = {maxx + shadsize, miny};
+
+ const float v5[2] = {maxx + 0.7f * shadsize, miny - 0.7f * shadsize};
+
+ const float v6[2] = {maxx, miny - shadsize};
+ const float v7[2] = {minx + 0.3f * shadsize, miny};
+ const float v8[2] = {minx + 0.5f * shadsize, miny - shadsize};
+
/* right quad */
- glColor4ub(0, 0, 0, alpha);
- glVertex2f(maxx, miny);
- glVertex2f(maxx, maxy - 0.3f * shadsize);
- glColor4ub(0, 0, 0, 0);
- glVertex2f(maxx + shadsize, maxy - 0.75f * shadsize);
- glVertex2f(maxx + shadsize, miny);
-
+ immAttrib4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v3);
+ immVertex2fv(pos, v1);
+ immAttrib4ub(color, 0, 0, 0, 0);
+ immVertex2fv(pos, v2);
+
+ immVertex2fv(pos, v2);
+ immVertex2fv(pos, v4);
+ immAttrib4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v3);
+
/* corner shape */
- glColor4ub(0, 0, 0, alpha);
- glVertex2f(maxx, miny);
- glColor4ub(0, 0, 0, 0);
- glVertex2f(maxx + shadsize, miny);
- glVertex2f(maxx + 0.7f * shadsize, miny - 0.7f * shadsize);
- glVertex2f(maxx, miny - shadsize);
-
+ /* immAttrib4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
+ immVertex2fv(pos, v3);
+ immAttrib4ub(color, 0, 0, 0, 0);
+ immVertex2fv(pos, v4);
+ immVertex2fv(pos, v5);
+
+ immVertex2fv(pos, v5);
+ immVertex2fv(pos, v6);
+ immAttrib4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v3);
+
/* bottom quad */
- glColor4ub(0, 0, 0, alpha);
- glVertex2f(minx + 0.3f * shadsize, miny);
- glVertex2f(maxx, miny);
- glColor4ub(0, 0, 0, 0);
- glVertex2f(maxx, miny - shadsize);
- glVertex2f(minx + 0.5f * shadsize, miny - shadsize);
+ /* immAttrib4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
+ immVertex2fv(pos, v3);
+ immAttrib4ub(color, 0, 0, 0, 0);
+ immVertex2fv(pos, v6);
+ immVertex2fv(pos, v8);
+
+ immVertex2fv(pos, v8);
+ immAttrib4ub(color, 0, 0, 0, alpha);
+ immVertex2fv(pos, v7);
+ immVertex2fv(pos, v3);
}
void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
{
glEnable(GL_BLEND);
-
- glBegin(GL_QUADS);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ immBegin(GWN_PRIM_TRIS, 54);
/* accumulated outline boxes to make shade not linear, is more pleasant */
- ui_shadowbox(minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
- ui_shadowbox(minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8);
- ui_shadowbox(minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8);
-
- glEnd();
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8);
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8);
+ immEnd();
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
@@ -1719,8 +2014,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;
@@ -1741,29 +2036,16 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha
float calpha = dalpha;
for (; i--; a -= aspect) {
/* alpha ranges from 2 to 20 or so */
- glColor4f(0.0f, 0.0f, 0.0f, calpha);
+ float color[4] = {0.0f, 0.0f, 0.0f, calpha};
+ UI_draw_roundbox_4fv(true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color);
calpha += dalpha;
-
- UI_draw_roundbox_gl_mode(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a);
}
/* outline emphasis */
glEnable(GL_LINE_SMOOTH);
- glColor4ub(0, 0, 0, 100);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.4f};
+ UI_draw_roundbox_4fv(false, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f, color);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
-
-/**
- * Reset GL state (keep minimal).
- *
- * \note Blender's internal code doesn't assume these are reset,
- * but external callbacks may depend on their state.
- */
-void UI_reinit_gl_state(void)
-{
- glLineWidth(1.0f);
- glPointSize(1.0f);
-}
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 564b29d3343..e92139ada0c 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -43,10 +43,12 @@
#include "BKE_screen.h"
#include "BKE_report.h"
#include "BKE_animsys.h"
-#include "BKE_depsgraph.h"
#include "BKE_idcode.h"
#include "BKE_unit.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -139,8 +141,8 @@ static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, c
wmWindow *win = CTX_wm_window(C);
int x = win->eventstate->x;
int y = win->eventstate->y;
- const unsigned char fg[4] = {255, 255, 255, 255};
- const unsigned char bg[4] = {0, 0, 0, 50};
+ const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f};
if ((name[0] == '\0') ||
@@ -154,7 +156,7 @@ static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, c
y += U.widget_unit;
- UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, fg, bg);
+ UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg);
}
@@ -169,8 +171,8 @@ static void eyedropper_draw_cursor_text(const struct bContext *C, ARegion *ar, c
*/
static uiBut *eyedropper_get_property_button_under_mouse(bContext *C, const wmEvent *event)
{
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, event->x, event->y);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y);
ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_ANY, event->x, event->y);
uiBut *but = ui_but_find_mouse_over(ar, event);
@@ -262,10 +264,9 @@ static void eyedropper_exit(bContext *C, wmOperator *op)
*/
static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int mx, int my, float r_col[3])
{
-
/* we could use some clever */
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
const char *display_device = CTX_data_scene(C)->display_settings.display_device;
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
@@ -586,8 +587,8 @@ static void datadropper_exit(bContext *C, wmOperator *op)
static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id)
{
/* we could use some clever */
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = BKE_screen_find_area_xy(win->screen, -1, mx, my);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = BKE_screen_find_area_xy(screen, -1, mx, my);
ScrArea *area_prev = CTX_wm_area(C);
ARegion *ar_prev = CTX_wm_region(C);
@@ -887,9 +888,9 @@ static void depthdropper_exit(bContext *C, wmOperator *op)
static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth)
{
/* we could use some clever */
- wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my);
- Scene *scene = win->screen->scene;
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+ Scene *scene = CTX_data_scene(C);
UnitSettings *unit = &scene->unit;
const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
@@ -902,6 +903,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
if (sa->spacetype == SPACE_VIEW3D) {
ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
if (ar) {
+ struct Depsgraph *graph = CTX_data_depsgraph(C);
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
/* weak, we could pass in some reference point */
@@ -911,6 +913,9 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
my - ar->winrct.ymin};
float co[3];
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
CTX_wm_area_set(C, sa);
CTX_wm_region_set(C, ar);
@@ -919,7 +924,7 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx,
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(scene, ar, v3d, mval, co, true, NULL)) {
+ if (ED_view3d_autodist(&eval_ctx, graph, ar, v3d, mval, co, true, NULL)) {
const float mval_center_fl[2] = {
(float)ar->winx / 2,
(float)ar->winy / 2};
@@ -1205,8 +1210,8 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve
if (success) {
/* send updates */
UI_context_update_anim_flag(C);
- DAG_relations_tag_update(CTX_data_main(C));
- DAG_id_tag_update(ddr->ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_relations_tag_update(CTX_data_main(C));
+ DEG_id_tag_update(ddr->ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
}
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index c78fe34e849..f28a398a46a 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -186,7 +186,6 @@ typedef struct uiSelectContextStore {
uiSelectContextElem *elems;
int elems_len;
bool do_free;
- bool is_enabled;
/* When set, simply copy values (don't apply difference).
* Rules are:
* - dragging numbers uses delta.
@@ -202,7 +201,9 @@ static void ui_selectcontext_apply(
bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data,
const double value, const double value_orig);
+#if 0
#define IS_ALLSELECT_EVENT(event) ((event)->alt != 0)
+#endif
/** just show a tinted color so users know its activated */
#define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE
@@ -1182,14 +1183,11 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl
ui_but_execute_begin(C, ar, but, &active_back);
#ifdef USE_ALLSELECT
- if (data->select_others.is_enabled) {
- /* init once! */
- if (mbut_state->select_others.elems_len == 0) {
- ui_selectcontext_begin(C, but, &mbut_state->select_others);
- }
- if (mbut_state->select_others.elems_len == 0) {
- mbut_state->select_others.elems_len = -1;
- }
+ if (mbut_state->select_others.elems_len == 0) {
+ ui_selectcontext_begin(C, but, &mbut_state->select_others);
+ }
+ if (mbut_state->select_others.elems_len == 0) {
+ mbut_state->select_others.elems_len = -1;
}
/* needed so we apply the right deltas */
@@ -2072,12 +2070,7 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
else
# endif
if (data->select_others.elems_len == 0) {
- wmWindow *win = CTX_wm_window(C);
- /* may have been enabled before activating */
- if (data->select_others.is_enabled || IS_ALLSELECT_EVENT(win->eventstate)) {
- ui_selectcontext_begin(C, but, &data->select_others);
- data->select_others.is_enabled = true;
- }
+ ui_selectcontext_begin(C, but, &data->select_others);
}
if (data->select_others.elems_len == 0) {
/* dont check again */
@@ -2118,6 +2111,7 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
break;
case UI_BTYPE_ROW:
case UI_BTYPE_LISTROW:
+ case UI_BTYPE_TAB:
ui_apply_but_ROW(C, block, but, data);
break;
case UI_BTYPE_SCROLL:
@@ -3079,11 +3073,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
#ifdef USE_ALLSELECT
if (is_num_but) {
- if (IS_ALLSELECT_EVENT(win->eventstate)) {
- data->select_others.is_enabled = true;
- data->select_others.is_copy = true;
-
- }
+ data->select_others.is_copy = true;
}
#endif
@@ -3170,6 +3160,9 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data)
ui_searchbox_free(C, data->searchbox);
data->searchbox = NULL;
+ if (but->free_search_arg) {
+ MEM_SAFE_FREE(but->search_arg);
+ }
}
but->editstr = NULL;
@@ -3685,15 +3678,6 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat
data->menu->popup = but->block->handle->popup;
}
-#ifdef USE_ALLSELECT
- {
- wmWindow *win = CTX_wm_window(C);
- if (IS_ALLSELECT_EVENT(win->eventstate)) {
- data->select_others.is_enabled = true;
- }
- }
-#endif
-
/* this makes adjacent blocks auto open from now on */
//if (but->block->auto_open == 0) but->block->auto_open = 1;
}
@@ -3875,6 +3859,18 @@ static int ui_do_but_KEYEVT(
return WM_UI_HANDLER_CONTINUE;
}
+static int ui_do_but_TAB(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_CONTINUE;
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
static bool ui_but_is_mouse_over_icon_extra(const ARegion *region, uiBut *but, const int mouse_xy[2])
{
int x = mouse_xy[0], y = mouse_xy[1];
@@ -5219,7 +5215,8 @@ static int ui_do_but_COLOR(
if (!event->ctrl) {
float color[3];
Scene *scene = CTX_data_scene(C);
- Paint *paint = BKE_paint_get_active(scene);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Paint *paint = BKE_paint_get_active(scene, view_layer);
Brush *brush = BKE_paint_brush(paint);
if (brush->flag & BRUSH_USE_GRADIENT) {
@@ -6127,6 +6124,7 @@ static int ui_do_but_CURVE(
int mx, my, a;
bool changed = false;
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
mx = event->x;
my = event->y;
@@ -6255,7 +6253,7 @@ static int ui_do_but_CURVE(
}
else {
curvemapping_changed(cumap, true); /* remove doubles */
- BKE_paint_invalidate_cursor_overlay(scene, cumap);
+ BKE_paint_invalidate_cursor_overlay(scene, view_layer, cumap);
}
}
@@ -6761,6 +6759,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
MenuType *mt = WM_menutype_find("WM_MT_button_context", true);
bool is_array, is_array_component;
uiStringInfo label = {BUT_GET_LABEL, NULL};
+ wmOperatorType *ot;
+ PointerRNA op_ptr;
/* if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/
/* return 0;*/
@@ -6787,11 +6787,11 @@ static bool ui_but_menu(bContext *C, uiBut *but)
const PropertySubType subtype = RNA_property_subtype(prop);
bool is_anim = RNA_property_animateable(ptr, prop);
bool is_editable = RNA_property_editable(ptr, prop);
+ bool is_overridable;
/*bool is_idprop = RNA_property_is_idprop(prop);*/ /* XXX does not work as expected, not strictly needed */
bool is_set = RNA_property_is_set(ptr, prop);
- /* Set the (button_pointer, button_prop) and pointer data for Python access to the hovered ui element. */
- uiLayoutSetContextFromBut(layout, but);
+ RNA_property_override_status(ptr, prop, -1, &is_overridable, NULL, NULL, NULL);
/* second slower test, saved people finding keyframe items in menus when its not possible */
if (is_anim)
@@ -6920,11 +6920,57 @@ static bool ui_but_menu(bContext *C, uiBut *but)
ICON_NONE, "ANIM_OT_keyingset_button_remove");
}
}
-
+
+ if (is_overridable) {
+ /* Override Operators */
+ uiItemS(layout);
+
+ if (but->flag & UI_BUT_OVERRIDEN) {
+ if (is_array_component) {
+ ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
+ uiItemFullO_ptr(layout, ot, "Overrides Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", true);
+ uiItemFullO_ptr(layout, ot, "Single Override Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"),
+ ICON_X, "UI_OT_override_remove_button", "all", true);
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"),
+ ICON_X, "UI_OT_override_remove_button", "all", false);
+ }
+ else {
+ uiItemFullO(layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"),
+ ICON_X, "UI_OT_override_remove_button", "all", true);
+ }
+ }
+ else {
+ if (is_array_component) {
+ ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
+ uiItemFullO_ptr(layout, ot, "Define Overrides", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", true);
+ uiItemFullO_ptr(layout, ot, "Define Single Override", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+ }
+ else {
+ uiItemFullO(layout, "UI_OT_override_type_set_button", "Define Override", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+ }
+ }
+ }
+
uiItemS(layout);
-
+
/* Property Operators */
-
+
/* Copy Property Value
* Paste Property Value */
@@ -7129,6 +7175,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case UI_BTYPE_HOTKEY_EVENT:
retval = ui_do_but_HOTKEYEVT(C, but, data, event);
break;
+ case UI_BTYPE_TAB:
+ retval = ui_do_but_TAB(C, but, data, event);
+ break;
case UI_BTYPE_BUT_TOGGLE:
case UI_BTYPE_TOGGLE:
case UI_BTYPE_ICON_TOGGLE:
@@ -8200,6 +8249,7 @@ void UI_context_update_anim_flag(const bContext *C)
for (block = ar->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next) {
ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
+ ui_but_override_flag(but);
ED_region_tag_redraw(ar);
if (but->active) {
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 0357fc8ff01..d048324d35e 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -33,8 +33,8 @@
#include "MEM_guardedalloc.h"
-#include "GPU_extensions.h"
-#include "GPU_basic_shader.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -59,7 +59,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_thumbs.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "ED_datafiles.h"
@@ -224,13 +223,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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_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(GWN_PRIM_TRIS, 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)
@@ -239,7 +242,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);
@@ -248,16 +250,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;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immBegin(GWN_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.6 * 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.6f * 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);
}
@@ -290,7 +306,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 |
@@ -299,19 +315,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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_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) \
@@ -504,8 +525,12 @@ static void init_internal_icons(void)
icongltex.id = 0;
}
+#if 0 /* should be a compile-time check (if needed at all) */
/* we only use a texture for cards with non-power of two */
if (GPU_full_non_power_of_two_support()) {
+#else
+ {
+#endif
glGenTextures(1, &icongltex.id);
if (icongltex.id) {
@@ -533,11 +558,6 @@ static void init_internal_icons(void)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
-
- if (glGetError() == GL_OUT_OF_MEMORY) {
- glDeleteTextures(1, &icongltex.id);
- icongltex.id = 0;
- }
}
}
}
@@ -851,12 +871,15 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi
{
ID *id = (icon->type != 0) ? icon->obj : NULL;
PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj;
+ /* Using jobs for screen previews crashes due to offscreen rendering.
+ * XXX would be nicer if PreviewImage could store if it supports jobs */
+ const bool use_jobs = !id || (GS(id->name) != ID_SCR);
if (prv) {
const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON;
if (id || (prv->tag & PRV_TAG_DEFFERED) != 0) {
- ui_id_preview_image_render_size(C, NULL, id, prv, size, true);
+ ui_id_preview_image_render_size(C, NULL, id, prv, size, use_jobs);
}
}
break;
@@ -936,7 +959,7 @@ PreviewImage *UI_icon_to_preview(int icon_id)
}
static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh,
- unsigned int *rect, float alpha, const float rgb[3], const bool is_preview)
+ unsigned int *rect, float alpha, const float rgb[3], const bool UNUSED(is_preview))
{
ImBuf *ima = NULL;
int draw_w = w;
@@ -950,15 +973,13 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
BLI_assert(!"invalid icon size");
return;
}
-
/* modulate color */
- if (alpha != 1.0f)
- glPixelTransferf(GL_ALPHA_SCALE, alpha);
+ float col[4] = {1.0f, 1.0f, 1.0f, alpha};
if (rgb) {
- glPixelTransferf(GL_RED_SCALE, rgb[0]);
- glPixelTransferf(GL_GREEN_SCALE, rgb[1]);
- glPixelTransferf(GL_BLUE_SCALE, rgb[2]);
+ col[0] = rgb[0];
+ col[1] = rgb[1];
+ col[2] = rgb[2];
}
/* rect contains image in 'rendersize', we only scale if needed */
@@ -984,31 +1005,12 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
}
/* draw */
- if (is_preview) {
- glaDrawPixelsSafe(draw_x, draw_y, draw_w, draw_h, draw_w, GL_RGBA, GL_UNSIGNED_BYTE, rect);
- }
- else {
- int bound_options;
- GPU_BASIC_SHADER_DISABLE_AND_STORE(bound_options);
-
- glRasterPos2f(draw_x, draw_y);
- glDrawPixels(draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
-
- GPU_BASIC_SHADER_ENABLE_AND_RESTORE(bound_options);
- }
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state, draw_x, draw_y, draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect,
+ 1.0f, 1.0f, col);
if (ima)
IMB_freeImBuf(ima);
-
- /* restore color */
- if (alpha != 0.0f)
- glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
-
- if (rgb) {
- glPixelTransferf(GL_RED_SCALE, 1.0f);
- glPixelTransferf(GL_GREEN_SCALE, 1.0f);
- glPixelTransferf(GL_BLUE_SCALE, 1.0f);
- }
}
static void icon_draw_texture(
@@ -1017,38 +1019,39 @@ static void icon_draw_texture(
{
float x1, x2, y1, y2;
- if (rgb) glColor4f(rgb[0], rgb[1], rgb[2], alpha);
- else glColor4f(alpha, alpha, alpha, alpha);
-
x1 = ix * icongltex.invw;
x2 = (ix + ih) * icongltex.invw;
y1 = iy * icongltex.invh;
y2 = (iy + ih) * icongltex.invh;
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
glBindTexture(GL_TEXTURE_2D, icongltex.id);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- /* sharper downscaling, has no effect when scale matches with a mip level */
- glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -0.5f);
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+ if (rgb) immUniformColor3fvAlpha(rgb, alpha);
+ else immUniformColor4f(alpha, alpha, alpha, alpha);
- glBegin(GL_QUADS);
- glTexCoord2f(x1, y1);
- glVertex2f(x, y);
+ immUniform1i("image", 0);
- glTexCoord2f(x2, y1);
- glVertex2f(x + w, y);
+ immBegin(GWN_PRIM_TRI_STRIP, 4);
+ immAttrib2f(texCoord, x1, y2);
+ immVertex2f(pos, x, y + h);
- glTexCoord2f(x2, y2);
- glVertex2f(x + w, y + h);
+ immAttrib2f(texCoord, x1, y1);
+ immVertex2f(pos, x, y);
- glTexCoord2f(x1, y2);
- glVertex2f(x, y + h);
- glEnd();
+ immAttrib2f(texCoord, x2, y2);
+ immVertex2f(pos, x + w, y + h);
- glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f);
+ immAttrib2f(texCoord, x2, y1);
+ immVertex2f(pos, x + w, y);
+ immEnd();
+
+ immUnbindProgram();
glBindTexture(GL_TEXTURE_2D, 0);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
/* Drawing size for preview images */
@@ -1162,7 +1165,7 @@ void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big,
}
}
-static void ui_id_brush_render(const bContext *C, ID *id)
+static void ui_id_icon_render(const bContext *C, ID *id, bool use_jobs)
{
PreviewImage *pi = BKE_previewimg_id_ensure(id);
enum eIconSizes i;
@@ -1174,7 +1177,7 @@ static void ui_id_brush_render(const bContext *C, ID *id)
/* check if rect needs to be created; changed
* only set by dynamic icons */
if (((pi->flag[i] & PRV_CHANGED) || !pi->rect[i])) {
- icon_set_image(C, NULL, id, pi, i, true);
+ icon_set_image(C, NULL, id, pi, i, use_jobs);
pi->flag[i] &= ~PRV_CHANGED;
}
}
@@ -1187,7 +1190,7 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
if (br->flag & BRUSH_CUSTOM_ICON) {
BKE_icon_id_ensure(id);
- ui_id_brush_render(C, id);
+ ui_id_icon_render(C, id, true);
}
else {
Object *ob = CTX_data_active_object(C);
@@ -1234,6 +1237,15 @@ static int ui_id_brush_get_icon(const bContext *C, ID *id)
return id->icon_id;
}
+static int ui_id_screen_get_icon(const bContext *C, ID *id)
+{
+ BKE_icon_id_ensure(id);
+ /* Don't use jobs here, offscreen rendering doesn't like this and crashes. */
+ ui_id_icon_render(C, id, false);
+
+ return id->icon_id;
+}
+
int ui_id_icon_get(const bContext *C, ID *id, const bool big)
{
int iconid = 0;
@@ -1252,6 +1264,9 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big)
/* checks if not exists, or changed */
UI_id_icon_render(C, NULL, id, big, true);
break;
+ case ID_SCR:
+ iconid = ui_id_screen_get_icon(C, id);
+ break;
default:
break;
}
@@ -1344,6 +1359,8 @@ int UI_idcode_icon_get(const int idcode)
return ICON_COLOR; /* TODO! this would need its own icon! */
case ID_PC:
return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */
+ case ID_LP:
+ return ICON_RADIO;
case ID_SCE:
return ICON_SCENE_DATA;
case ID_SPK:
@@ -1388,6 +1405,11 @@ void UI_icon_draw(float x, float y, int icon_id)
UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f);
}
+void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha)
+{
+ UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, alpha);
+}
+
void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha)
{
icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, true, false);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 638ab01f8ba..df46d29c6cd 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -72,6 +72,7 @@ typedef enum {
UI_WTYPE_NUMBER,
UI_WTYPE_SLIDER,
UI_WTYPE_EXEC,
+ UI_WTYPE_TAB,
UI_WTYPE_TOOLTIP,
/* strings */
@@ -258,6 +259,7 @@ struct uiBut {
uiButSearchCreateFunc search_create_func;
uiButSearchFunc search_func;
+ bool free_search_arg;
void *search_arg;
uiButHandleRenameFunc rename_func;
@@ -281,7 +283,7 @@ struct uiBut {
BIFIconID icon;
char dt; /* drawtype: UI_EMBOSS, UI_EMBOSS_NONE ... etc, copied from the block */
signed char pie_dir; /* direction in a pie menu, used for collision detection (RadialDirection) */
- char changed; /* could be made into a single flag */
+ bool changed; /* could be made into a single flag */
unsigned char unit_type; /* so buttons can support unit systems which are not RNA */
short modifier_key;
short iconadd;
@@ -507,6 +509,7 @@ extern bool ui_but_supports_cycling(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT;
extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT;
+void ui_but_override_flag(uiBut *but);
extern void ui_block_bounds_calc(uiBlock *block);
extern void ui_block_translate(uiBlock *block, int x, int y);
@@ -654,6 +657,8 @@ extern void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, floa
void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha);
+
+void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3]);
void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
@@ -696,15 +701,16 @@ struct wmIMEData *ui_but_ime_data_get(uiBut *but);
#endif
/* interface_widgets.c */
-void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3);
-void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha);
+void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, const float color[4]);
+void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy,
+ float rad, bool use_alpha, const float color[4]);
void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
void ui_draw_pie_center(uiBlock *block);
uiWidgetColors *ui_tooltip_get_theme(void);
void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol);
-void ui_draw_link_bezier(const rcti *rect);
+void ui_draw_link_bezier(const rcti *rect, const float color[4]);
extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect);
/* theme color init */
@@ -758,4 +764,20 @@ void UI_OT_eyedropper_id(struct wmOperatorType *ot);
void UI_OT_eyedropper_depth(struct wmOperatorType *ot);
void UI_OT_eyedropper_driver(struct wmOperatorType *ot);
+/* interface_util.c */
+
+/**
+ * For use with #ui_rna_collection_search_cb.
+ */
+typedef struct uiRNACollectionSearch {
+ PointerRNA target_ptr;
+ PropertyRNA *target_prop;
+
+ PointerRNA search_ptr;
+ PropertyRNA *search_prop;
+
+ bool *but_changed; /* pointer to uiBut.changed */
+} uiRNACollectionSearch;
+void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char *str, uiSearchItems *items);
+
#endif /* __INTERFACE_INTERN_H__ */
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index fa27c6fc07b..d43b7511977 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -870,7 +870,7 @@ static uiBut *uiItemFullO_ptr_ex(
return but;
}
-static void ui_item_hold_menu(struct bContext *C, ARegion *butregion, uiBut *but)
+static void ui_item_menu_hold(struct bContext *C, ARegion *butregion, uiBut *but)
{
uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
@@ -878,6 +878,8 @@ static void ui_item_hold_menu(struct bContext *C, ARegion *butregion, uiBut *but
UI_popup_menu_but_set(pup, butregion, but);
block->flag |= UI_BLOCK_POPUP_HOLD;
+ block->flag |= UI_BLOCK_IS_FLIP;
+ UI_block_direction_set(block, UI_DIR_DOWN);
const char *menu_id = but->hold_argN;
MenuType *mt = WM_menutype_find(menu_id, true);
@@ -907,7 +909,7 @@ void uiItemFullOMenuHold_ptr(
PointerRNA *r_opptr)
{
uiBut *but = uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr);
- UI_but_func_hold_set(but, ui_item_hold_menu, BLI_strdup(menu_id));
+ UI_but_func_hold_set(but, ui_item_menu_hold, BLI_strdup(menu_id));
}
void uiItemFullO(
@@ -1639,95 +1641,6 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname
/* Pointer RNA button with search */
-typedef struct CollItemSearch {
- struct CollItemSearch *next, *prev;
- char *name;
- int index;
- int iconid;
-} CollItemSearch;
-
-static int sort_search_items_list(const void *a, const void *b)
-{
- const CollItemSearch *cis1 = a;
- const CollItemSearch *cis2 = b;
-
- if (BLI_strcasecmp(cis1->name, cis2->name) > 0)
- return 1;
- else
- return 0;
-}
-
-static void rna_search_cb(const struct bContext *C, void *arg_but, const char *str, uiSearchItems *items)
-{
- uiBut *but = arg_but;
- char *name;
- int i = 0, iconid = 0, flag = RNA_property_flag(but->rnaprop);
- ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list");
- CollItemSearch *cis;
- const bool skip_filter = !but->changed;
-
- /* build a temporary list of relevant items first */
- RNA_PROP_BEGIN (&but->rnasearchpoin, itemptr, but->rnasearchprop)
- {
- if (flag & PROP_ID_SELF_CHECK)
- if (itemptr.data == but->rnapoin.id.data)
- continue;
-
- /* use filter */
- if (RNA_property_type(but->rnaprop) == PROP_POINTER) {
- if (RNA_property_pointer_poll(&but->rnapoin, but->rnaprop, &itemptr) == 0)
- continue;
- }
-
- if (itemptr.type && RNA_struct_is_ID(itemptr.type)) {
- ID *id = itemptr.data;
- char name_ui[MAX_ID_NAME];
-
-#if 0 /* this name is used for a string comparison and can't be modified, TODO */
- /* if ever enabled, make name_ui be MAX_ID_NAME+1 */
- BKE_id_ui_prefix(name_ui, id);
-#else
- BLI_strncpy(name_ui, id->name + 2, sizeof(name_ui));
-#endif
- name = BLI_strdup(name_ui);
- iconid = ui_id_icon_get(C, id, false);
- }
- else {
- name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */
- iconid = 0;
- }
-
- if (name) {
- if (skip_filter || BLI_strcasestr(name, str)) {
- cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch");
- cis->name = MEM_dupallocN(name);
- cis->index = i;
- cis->iconid = iconid;
- BLI_addtail(items_list, cis);
- }
- MEM_freeN(name);
- }
-
- i++;
- }
- RNA_PROP_END;
-
- BLI_listbase_sort(items_list, sort_search_items_list);
-
- /* add search items from temporary list */
- for (cis = items_list->first; cis; cis = cis->next) {
- if (false == UI_search_item_add(items, cis->name, SET_INT_IN_POINTER(cis->index), cis->iconid)) {
- break;
- }
- }
-
- for (cis = items_list->first; cis; cis = cis->next) {
- MEM_freeN(cis->name);
- }
- BLI_freelistN(items_list);
- MEM_freeN(items_list);
-}
-
static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop)
{
StructRNA *srna;
@@ -1768,6 +1681,8 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN
/* turn button into search button */
if (searchprop) {
+ uiRNACollectionSearch *coll_search = MEM_mallocN(sizeof(*coll_search), __func__);
+
but->type = UI_BTYPE_SEARCH_MENU;
but->hardmax = MAX2(but->hardmax, 256.0f);
but->rnasearchpoin = *searchptr;
@@ -1777,13 +1692,22 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN
but->flag |= UI_BUT_VALUE_CLEAR;
}
+ coll_search->target_ptr = *ptr;
+ coll_search->target_prop = prop;
+ coll_search->search_ptr = *searchptr;
+ coll_search->search_prop = searchprop;
+ coll_search->but_changed = &but->changed;
+
if (RNA_property_type(prop) == PROP_ENUM) {
/* XXX, this will have a menu string,
* but in this case we just want the text */
but->str[0] = 0;
}
- UI_but_func_search_set(but, ui_searchbox_create_generic, rna_search_cb, but, NULL, NULL);
+ UI_but_func_search_set(
+ but, ui_searchbox_create_generic, ui_rna_collection_search_cb,
+ coll_search, NULL, NULL);
+ but->free_search_arg = true;
}
else if (but->type == UI_BTYPE_SEARCH_MENU) {
/* In case we fail to find proper searchprop, so other code might have already set but->type to search menu... */
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 47b7e9aa085..bbcd10270d5 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -42,14 +42,20 @@
#include "BLT_lang.h"
#include "BKE_context.h"
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
#include "BKE_screen.h"
#include "BKE_global.h"
+#include "BKE_library_override.h"
#include "BKE_node.h"
#include "BKE_text.h" /* for UI_OT_reports_to_text */
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_types.h"
#include "UI_interface.h"
@@ -328,6 +334,334 @@ static void UI_OT_unset_property_button(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
}
+/* Use/Unuse Property Button Operator ------------------------ */
+
+static int use_property_button_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PointerRNA ptr, scene_props_ptr;
+ PropertyRNA *prop;
+ IDProperty *props;
+
+ uiBut *but = UI_context_active_but_get(C);
+
+ prop = but->rnaprop;
+ ptr = but->rnapoin;
+ props = (IDProperty *)ptr.data;
+ /* XXX Using existing data struct to pass another RNAPointer */
+ scene_props_ptr = but->rnasearchpoin;
+
+ const char *identifier = RNA_property_identifier(prop);
+ if (IDP_GetPropertyFromGroup(props, identifier)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ int array_len = RNA_property_array_length(&scene_props_ptr, prop);
+ bool is_array = array_len != 0;
+
+ switch (RNA_property_type(prop)) {
+ case PROP_FLOAT:
+ {
+ if (is_array) {
+ float values[RNA_MAX_ARRAY_LENGTH];
+ RNA_property_float_get_array(&scene_props_ptr, prop, values);
+ BKE_collection_engine_property_add_float_array(props, identifier, values, array_len);
+ }
+ else {
+ float value = RNA_property_float_get(&scene_props_ptr, prop);
+ BKE_collection_engine_property_add_float(props, identifier, value);
+ }
+ break;
+ }
+ case PROP_ENUM:
+ {
+ int value = RNA_enum_get(&scene_props_ptr, identifier);
+ BKE_collection_engine_property_add_int(props, identifier, value);
+ break;
+ }
+ case PROP_INT:
+ {
+ int value = RNA_int_get(&scene_props_ptr, identifier);
+ BKE_collection_engine_property_add_int(props, identifier, value);
+ break;
+ }
+ case PROP_BOOLEAN:
+ {
+ int value = RNA_boolean_get(&scene_props_ptr, identifier);
+ BKE_collection_engine_property_add_bool(props, identifier, value);
+ break;
+ }
+ case PROP_STRING:
+ case PROP_POINTER:
+ case PROP_COLLECTION:
+ default:
+ break;
+ }
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update((ID *)CTX_data_scene(C), 0);
+
+ return OPERATOR_FINISHED;
+}
+
+static void UI_OT_use_property_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Use property";
+ ot->idname = "UI_OT_use_property_button";
+ ot->description = "Create a property";
+
+ /* callbacks */
+ ot->poll = ED_operator_regionactive;
+ ot->exec = use_property_button_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
+static int unuse_property_button_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+
+ /* try to unset the nominated property */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ const char *identifier = RNA_property_identifier(prop);
+
+ IDProperty *props = (IDProperty *)ptr.data;
+ IDProperty *prop_to_remove = IDP_GetPropertyFromGroup(props, identifier);
+ IDP_FreeFromGroup(props, prop_to_remove);
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update((ID *)CTX_data_scene(C), 0);
+
+ return OPERATOR_FINISHED;
+}
+
+static void UI_OT_unuse_property_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Unuse property";
+ ot->idname = "UI_OT_unuse_property_button";
+ ot->description = "Remove a property";
+
+ /* callbacks */
+ ot->poll = ED_operator_regionactive;
+ ot->exec = unuse_property_button_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
+
+
+
+
+/* Note that we use different values for UI/UX than 'real' override operations, user does not care
+ * whether it's added or removed for the differential operation e.g. */
+enum {
+ UIOverride_Type_NOOP = 0,
+ UIOverride_Type_Replace = 1,
+ UIOverride_Type_Difference = 2, /* Add/subtract */
+ UIOverride_Type_Factor = 3, /* Multiply */
+ /* TODO: should/can we expose insert/remove ones for collections? Doubt it... */
+};
+
+static EnumPropertyItem override_type_items[] = {
+ {UIOverride_Type_NOOP, "NOOP", 0, "NoOp",
+ "'No-Operation', place holder preventing automatic override to ever affect the property"},
+ {UIOverride_Type_Replace, "REPLACE", 0, "Replace", "Completely replace value from linked data by local one"},
+ {UIOverride_Type_Difference, "DIFFERENCE", 0, "Difference", "Store difference to linked data value"},
+ {UIOverride_Type_Factor, "FACTOR", 0, "Factor", "Store factor to linked data value (useful e.g. for scale)"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+
+static int override_type_set_button_poll(bContext *C)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ bool is_overridable;
+
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ RNA_property_override_status(&ptr, prop, index, &is_overridable, NULL, NULL, NULL);
+
+ return (ptr.data && prop && is_overridable);
+}
+
+static int override_type_set_button_exec(bContext *C, wmOperator *op)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ bool created;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+ const int op_type = RNA_enum_get(op->ptr, "type");
+
+ short operation;
+
+ switch (op_type) {
+ case UIOverride_Type_NOOP:
+ operation = IDOVERRIDESTATIC_OP_NOOP;
+ break;
+ case UIOverride_Type_Replace:
+ operation = IDOVERRIDESTATIC_OP_REPLACE;
+ break;
+ case UIOverride_Type_Difference:
+ operation = IDOVERRIDESTATIC_OP_ADD; /* override code will automatically switch to subtract if needed. */
+ break;
+ case UIOverride_Type_Factor:
+ operation = IDOVERRIDESTATIC_OP_MULTIPLY;
+ break;
+ default:
+ operation = IDOVERRIDESTATIC_OP_REPLACE;
+ BLI_assert(0);
+ break;
+ }
+
+ /* try to reset the nominated setting to its default value */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ BLI_assert(ptr.id.data != NULL);
+
+ if (all) {
+ index = -1;
+ }
+
+ IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_get(
+ &ptr, prop, operation, index, true, NULL, &created);
+ if (!created) {
+ opop->operation = operation;
+ }
+
+ return operator_button_property_finish(C, &ptr, prop);
+}
+
+static int override_type_set_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
+}
+
+static void UI_OT_override_type_set_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Define Override Type";
+ ot->idname = "UI_OT_override_type_set_button";
+ ot->description = "Create an override operation, or set the type of an existing one";
+
+ /* callbacks */
+ ot->poll = override_type_set_button_poll;
+ ot->exec = override_type_set_button_exec;
+ ot->invoke = override_type_set_button_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
+ ot->prop = RNA_def_enum(ot->srna, "type", override_type_items, UIOverride_Type_Replace,
+ "Type", "Type of override operation");
+ /* TODO: add itemf callback, not all aoptions are available for all data types... */
+}
+
+
+static int override_remove_button_poll(bContext *C)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ bool is_overridden;
+
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ RNA_property_override_status(&ptr, prop, index, NULL, &is_overridden, NULL, NULL);
+
+ return (ptr.data && ptr.id.data && prop && is_overridden);
+}
+
+static int override_remove_button_exec(bContext *C, wmOperator *op)
+{
+ PointerRNA ptr, id_refptr, src;
+ PropertyRNA *prop;
+ int index;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+
+ /* try to reset the nominated setting to its default value */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ ID *id = ptr.id.data;
+ IDOverrideStaticProperty *oprop = RNA_property_override_property_find(&ptr, prop);
+ BLI_assert(oprop != NULL);
+ BLI_assert(id != NULL && id->override_static != NULL);
+
+ const bool is_template = (id->override_static->reference == NULL);
+
+ /* We need source (i.e. linked data) to restore values of deleted overrides...
+ * If this is an override template, we obviously do not need to restore anything. */
+ if (!is_template) {
+ RNA_id_pointer_create(id->override_static->reference, &id_refptr);
+ if (!RNA_path_resolve(&id_refptr, oprop->rna_path, &src, NULL)) {
+ BLI_assert(0 && "Failed to create matching source (linked data) RNA pointer");
+ }
+ }
+
+ if (!all && index != -1) {
+ bool is_strict_find;
+ /* Remove override operation for given item, add singular operations for the other items as needed. */
+ IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find(
+ oprop, NULL, NULL, index, index, false, &is_strict_find);
+ BLI_assert(opop != NULL);
+ if (!is_strict_find) {
+ /* No specific override operation, we have to get generic one,
+ * and create item-specific override operations for all but given index, before removing generic one. */
+ for (int idx = RNA_property_array_length(&ptr, prop); idx--; ) {
+ if (idx != index) {
+ BKE_override_static_property_operation_get(oprop, opop->operation, NULL, NULL, idx, idx, true, NULL, NULL);
+ }
+ }
+ }
+ BKE_override_static_property_operation_delete(oprop, opop);
+ if (!is_template) {
+ RNA_property_copy(&ptr, &src, prop, index);
+ }
+ if (BLI_listbase_is_empty(&oprop->operations)) {
+ BKE_override_static_property_delete(id->override_static, oprop);
+ }
+ }
+ else {
+ /* Just remove whole generic override operation of this property. */
+ BKE_override_static_property_delete(id->override_static, oprop);
+ if (!is_template) {
+ RNA_property_copy(&ptr, &src, prop, -1);
+ }
+ }
+
+ return operator_button_property_finish(C, &ptr, prop);
+}
+
+static void UI_OT_override_remove_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Override";
+ ot->idname = "UI_OT_override_remove_button";
+ ot->description = "Remove an override operation";
+
+ /* callbacks */
+ ot->poll = override_remove_button_poll;
+ ot->exec = override_remove_button_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
+}
+
+
+
+
/* Copy To Selected Operator ------------------------ */
bool UI_context_copy_to_selected_list(
@@ -1117,6 +1451,10 @@ void ED_operatortypes_ui(void)
WM_operatortype_append(UI_OT_copy_python_command_button);
WM_operatortype_append(UI_OT_reset_default_button);
WM_operatortype_append(UI_OT_unset_property_button);
+ WM_operatortype_append(UI_OT_use_property_button);
+ WM_operatortype_append(UI_OT_unuse_property_button);
+ WM_operatortype_append(UI_OT_override_type_set_button);
+ WM_operatortype_append(UI_OT_override_remove_button);
WM_operatortype_append(UI_OT_copy_to_selected_button);
WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
WM_operatortype_append(UI_OT_drop_color);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index d9685d7281b..c3759e232b0 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -50,9 +50,6 @@
#include "BKE_context.h"
#include "BKE_screen.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
#include "BLF_api.h"
#include "WM_api.h"
@@ -65,6 +62,8 @@
#include "UI_interface_icons.h"
#include "UI_resources.h"
+#include "GPU_immediate.h"
+
#include "interface_intern.h"
/*********************** defines and structs ************************/
@@ -393,54 +392,42 @@ static void ui_offset_panel_block(uiBlock *block)
/**************************** drawing *******************************/
-/* extern used by previewrender */
-#if 0 /*UNUSED 2.5*/
-static void uiPanelPush(uiBlock *block)
-{
- glPushMatrix();
-
- if (block->panel)
- glTranslatef((float)block->panel->ofsx, (float)block->panel->ofsy, 0.0);
-}
-
-static void uiPanelPop(uiBlock *UNUSED(block))
-{
- glPopMatrix();
-}
-#endif
-
/* triangle 'icon' for panel header */
-void UI_draw_icon_tri(float x, float y, char dir)
+void UI_draw_icon_tri(float x, float y, char dir, const float color[4])
{
float f3 = 0.15 * U.widget_unit;
float f5 = 0.25 * U.widget_unit;
float f7 = 0.35 * U.widget_unit;
if (dir == 'h') {
- ui_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y);
+ ui_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color);
}
else if (dir == 't') {
- ui_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3);
+ ui_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3, color);
}
else { /* 'v' = vertical, down */
- ui_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7);
+ ui_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7, color);
}
}
/* triangle 'icon' inside rect */
static void ui_draw_tria_rect(const rctf *rect, char dir)
{
+ float color[4];
+ UI_GetThemeColor3fv(TH_TITLE, color);
+ color[3] = 1.0f;
+
if (dir == 'h') {
float half = 0.5f * BLI_rctf_size_y(rect);
- ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half);
+ ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half, color);
}
else {
float half = 0.5f * BLI_rctf_size_x(rect);
- ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin);
+ ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin, color);
}
}
-static void ui_draw_anti_x(float x1, float y1, float x2, float y2)
+static void ui_draw_anti_x(unsigned int pos, float x1, float y1, float x2, float y2)
{
/* set antialias line */
@@ -448,9 +435,16 @@ static void ui_draw_anti_x(float x1, float y1, float x2, float y2)
glEnable(GL_BLEND);
glLineWidth(2.0);
-
- fdrawline(x1, y1, x2, y2);
- fdrawline(x1, y2, x2, y1);
+
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y1);
+
+ immEnd();
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
@@ -458,16 +452,16 @@ static void ui_draw_anti_x(float x1, float y1, float x2, float y2)
}
/* x 'icon' for panel header */
-static void ui_draw_x_icon(float x, float y)
+static void ui_draw_x_icon(unsigned int pos, float x, float y)
{
- ui_draw_anti_x(x, y, x + 9.375f, y + 9.375f);
+ ui_draw_anti_x(pos, x, y, x + 9.375f, y + 9.375f);
}
#define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */
-static void ui_draw_panel_scalewidget(const rcti *rect)
+static void ui_draw_panel_scalewidget(unsigned int pos, const rcti *rect)
{
float xmin, xmax, dx;
float ymin, ymax, dy;
@@ -481,16 +475,33 @@ static void ui_draw_panel_scalewidget(const rcti *rect)
dy = 0.5f * (ymax - ymin);
glEnable(GL_BLEND);
- glColor4ub(255, 255, 255, 50);
- fdrawline(xmin, ymin, xmax, ymax);
- fdrawline(xmin + dx, ymin, xmax, ymax - dy);
+ immUniformColor4ub(255, 255, 255, 50);
+
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, xmin, ymin);
+ immVertex2f(pos, xmax, ymax);
+
+ immVertex2f(pos, xmin + dx, ymin);
+ immVertex2f(pos, xmax, ymax - dy);
+
+ immEnd();
- glColor4ub(0, 0, 0, 50);
- fdrawline(xmin, ymin + 1, xmax, ymax + 1);
- fdrawline(xmin + dx, ymin + 1, xmax, ymax - dy + 1);
+ immUniformColor4ub(0, 0, 0, 50);
+
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, xmin, ymin + 1);
+ immVertex2f(pos, xmax, ymax + 1);
+
+ immVertex2f(pos, xmin + dx, ymin + 1);
+ immVertex2f(pos, xmax, ymax - dy + 1);
+
+ immEnd();
+
glDisable(GL_BLEND);
}
-static void ui_draw_panel_dragwidget(const rctf *rect)
+static void ui_draw_panel_dragwidget(unsigned int pos, const rctf *rect)
{
unsigned char col_back[3], col_high[3], col_dark[3];
const int col_tint = 84;
@@ -519,10 +530,10 @@ static void ui_draw_panel_dragwidget(const rctf *rect)
const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin));
const int y_co = (y_min + y_ofs) + (i_y * (box_size + box_margin));
- glColor3ubv(col_dark);
- glRectf(x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom);
- glColor3ubv(col_high);
- glRectf(x_co - box_size, y_co, x_co, y_co + box_size);
+ immUniformColor3ubv(col_dark);
+ immRectf(pos, x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom);
+ immUniformColor3ubv(col_high);
+ immRectf(pos, x_co - box_size, y_co, x_co, y_co + box_size);
}
}
}
@@ -534,29 +545,30 @@ 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_GetThemeColor3ubv(TH_TITLE, col_title);
+ col_title[3] = 255;
+
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);
}
}
@@ -566,7 +578,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
Panel *panel = block->panel;
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;
@@ -579,6 +591,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
headrect.ymin = headrect.ymax;
headrect.ymax = headrect.ymin + floor(PNL_HEADER / block->aspect + 0.001f);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
{
float minx = rect->xmin;
float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax;
@@ -588,11 +603,18 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
if (UI_GetThemeValue(TH_PANEL_SHOW_HEADER)) {
/* draw with background color */
- UI_ThemeColor4(TH_PANEL_HEADER);
- glRectf(minx, headrect.ymin + 1, maxx, y);
+ immUniformThemeColor(TH_PANEL_HEADER);
+ immRectf(pos, minx, headrect.ymin + 1, maxx, y);
+
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, minx, y);
+ immVertex2f(pos, maxx, y);
+
+ immVertex2f(pos, minx, y);
+ immVertex2f(pos, maxx, y);
- fdrawline(minx, y, maxx, y);
- fdrawline(minx, y, maxx, y);
+ immEnd();
}
else if (!(panel->runtime_flag & PNL_FIRST)) {
/* draw embossed separator */
@@ -602,15 +624,26 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
maxx -= 5.0f / block->aspect;
}
- glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
- fdrawline(minx, y, maxx, y);
- glColor4f(1.0f, 1.0f, 1.0f, 0.25f);
- fdrawline(minx, y - 1, maxx, y - 1);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, minx, y);
+ immVertex2f(pos, maxx, y);
+ immEnd();
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, minx, y - 1);
+ immVertex2f(pos, maxx, y - 1);
+ immEnd();
}
glDisable(GL_BLEND);
}
+ immUnbindProgram();
+
/* draw optional pin icon */
#ifdef USE_PIN_HIDDEN
@@ -626,9 +659,11 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
glDisable(GL_BLEND);
}
+
/* horizontal title */
if (is_closed_x == false) {
ui_draw_aligned_panel_header(style, block, &headrect, 'h');
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
/* itemrect smaller */
itemrect.xmax = headrect.xmax - 5.0f / block->aspect;
@@ -637,7 +672,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
itemrect.ymax = headrect.ymax;
BLI_rctf_scale(&itemrect, 0.7f);
- ui_draw_panel_dragwidget(&itemrect);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ ui_draw_panel_dragwidget(pos, &itemrect);
+ immUnbindProgram();
}
/* if the panel is minimized vertically:
@@ -649,6 +686,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
else if (is_closed_x) {
/* draw vertical title */
ui_draw_aligned_panel_header(style, block, &headrect, 'v');
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
}
/* an open panel */
else {
@@ -657,33 +695,37 @@ 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_aa(false, 0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8, color);
}
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* panel backdrop */
if (UI_GetThemeValue(TH_PANEL_SHOW_BACK)) {
/* draw with background color */
glEnable(GL_BLEND);
- UI_ThemeColor4(TH_PANEL_BACK);
- glRecti(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ immUniformThemeColor(TH_PANEL_BACK);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
}
if (panel->control & UI_PNL_SCALE)
- ui_draw_panel_scalewidget(rect);
+ ui_draw_panel_scalewidget(pos, rect);
+
+ immUnbindProgram();
}
/* draw optional close icon */
- ofsx = 6;
if (panel->control & UI_PNL_CLOSE) {
- UI_ThemeColor(TH_TITLE);
- ui_draw_x_icon(rect->xmin + 2 + ofsx, rect->ymax + 2);
- ofsx = 22;
+ const int ofsx = 6;
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor3(TH_TITLE);
+ ui_draw_x_icon(pos, rect->xmin + 2 + ofsx, rect->ymax + 2);
+ immUnbindProgram();
}
/* draw collapse icon */
- UI_ThemeColor(TH_TITLE);
/* itemrect smaller */
itemrect.xmin = headrect.xmin + 5.0f / block->aspect;
@@ -699,8 +741,6 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
ui_draw_tria_rect(&itemrect, 'h');
else
ui_draw_tria_rect(&itemrect, 'v');
-
- (void)ofsx;
}
/************************** panel alignment *************************/
@@ -1513,12 +1553,13 @@ void UI_panel_category_clear_all(ARegion *ar)
BLI_freelistN(&ar->panels_category);
}
-/* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */
+/* based on UI_draw_roundbox, check on making a version which allows us to skip some sides */
static void ui_panel_category_draw_tab(
- int mode, float minx, float miny, float maxx, float maxy, float rad,
+ bool filled, float minx, float miny, float maxx, float maxy, float rad,
int roundboxtype,
- const bool use_highlight, const bool use_shadow,
- const unsigned char highlight_fade[3])
+ bool use_highlight, bool use_shadow,
+ const unsigned char highlight_fade[3],
+ const unsigned char col[3])
{
float vec[4][2] = {
{0.195, 0.02},
@@ -1527,74 +1568,96 @@ static void ui_panel_category_draw_tab(
{0.98, 0.805}};
int a;
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
/* mult */
for (a = 0; a < 4; a++) {
mul_v2_fl(vec[a], rad);
}
- glBegin(mode);
+ unsigned int vert_ct = 0;
+ if (use_highlight) {
+ vert_ct += (roundboxtype & UI_CNR_TOP_RIGHT) ? 6 : 1;
+ vert_ct += (roundboxtype & UI_CNR_TOP_LEFT) ? 6 : 1;
+ }
+ if (use_highlight && !use_shadow) {
+ vert_ct++;
+ }
+ else {
+ vert_ct += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 6 : 1;
+ vert_ct += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 6 : 1;
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_STRIP, vert_ct);
+
+ immAttrib3ubv(color, col);
/* start with corner right-top */
if (use_highlight) {
if (roundboxtype & UI_CNR_TOP_RIGHT) {
- glVertex2f(maxx, maxy - rad);
+ immVertex2f(pos, maxx, maxy - rad);
for (a = 0; a < 4; a++) {
- glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
}
- glVertex2f(maxx - rad, maxy);
+ immVertex2f(pos, maxx - rad, maxy);
}
else {
- glVertex2f(maxx, maxy);
+ immVertex2f(pos, maxx, maxy);
}
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
- glVertex2f(minx + rad, maxy);
+ immVertex2f(pos, minx + rad, maxy);
for (a = 0; a < 4; a++) {
- glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
}
- glVertex2f(minx, maxy - rad);
+ immVertex2f(pos, minx, maxy - rad);
}
else {
- glVertex2f(minx, maxy);
+ immVertex2f(pos, minx, maxy);
}
}
if (use_highlight && !use_shadow) {
if (highlight_fade) {
- glColor3ubv(highlight_fade);
+ immAttrib3ubv(color, highlight_fade);
}
- glVertex2f(minx, miny + rad);
- glEnd();
+ immVertex2f(pos, minx, miny + rad);
+ immEnd();
+ immUnbindProgram();
return;
}
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- glVertex2f(minx, miny + rad);
+ immVertex2f(pos, minx, miny + rad);
for (a = 0; a < 4; a++) {
- glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
}
- glVertex2f(minx + rad, miny);
+ immVertex2f(pos, minx + rad, miny);
}
else {
- glVertex2f(minx, miny);
+ immVertex2f(pos, minx, miny);
}
/* corner right-bottom */
-
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- glVertex2f(maxx - rad, miny);
+ immVertex2f(pos, maxx - rad, miny);
for (a = 0; a < 4; a++) {
- glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
}
- glVertex2f(maxx, miny + rad);
+ immVertex2f(pos, maxx, miny + rad);
}
else {
- glVertex2f(maxx, miny);
+ immVertex2f(pos, maxx, miny);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
@@ -1717,21 +1780,26 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* begin drawing */
glEnable(GL_LINE_SMOOTH);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* draw the background */
if (is_alpha) {
glEnable(GL_BLEND);
- glColor4ubv(theme_col_tab_bg);
+ immUniformColor4ubv(theme_col_tab_bg);
}
else {
- glColor3ubv(theme_col_tab_bg);
+ immUniformColor3ubv(theme_col_tab_bg);
}
- glRecti(v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax);
+ immRecti(pos, v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax);
if (is_alpha) {
glDisable(GL_BLEND);
}
+ immUnbindProgram();
+
for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
const rcti *rct = &pc_dyn->rect;
const char *category_id = pc_dyn->idname;
@@ -1754,28 +1822,33 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
if (is_active)
#endif
{
- glColor3ubv(is_active ? theme_col_tab_active : theme_col_tab_inactive);
- ui_panel_category_draw_tab(GL_POLYGON, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
- tab_curve_radius - px, roundboxtype, true, true, NULL);
+ ui_panel_category_draw_tab(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
+ tab_curve_radius - px, roundboxtype, true, true, NULL,
+ is_active ? theme_col_tab_active : theme_col_tab_inactive);
/* tab outline */
- glColor3ubv(theme_col_tab_outline);
- ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px,
- tab_curve_radius, roundboxtype, true, true, NULL);
+ ui_panel_category_draw_tab(false, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px,
+ tab_curve_radius, roundboxtype, true, true, NULL, theme_col_tab_outline);
+
/* tab highlight (3d look) */
- glColor3ubv(is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive);
- ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
+ ui_panel_category_draw_tab(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
tab_curve_radius, roundboxtype, true, false,
- is_active ? theme_col_back : theme_col_tab_inactive);
+ is_active ? theme_col_back : theme_col_tab_inactive,
+ is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive);
}
/* tab blackline */
if (!is_active) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + category_tabs_width - px,
- rct->ymin - tab_v_pad,
- v2d->mask.xmin + category_tabs_width,
- rct->ymax + tab_v_pad);
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + category_tabs_width - px,
+ rct->ymin - tab_v_pad,
+ v2d->mask.xmin + category_tabs_width,
+ rct->ymax + tab_v_pad);
+
+ immUnbindProgram();
}
if (do_scaletabs) {
@@ -1788,7 +1861,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);
@@ -1796,33 +1869,36 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
glDisable(GL_BLEND);
/* tab blackline remaining (last tab) */
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
if (pc_dyn->prev == NULL) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + category_tabs_width - px,
- rct->ymax + px,
- v2d->mask.xmin + category_tabs_width,
- v2d->mask.ymax);
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + category_tabs_width - px,
+ rct->ymax + px,
+ v2d->mask.xmin + category_tabs_width,
+ v2d->mask.ymax);
}
if (pc_dyn->next == NULL) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + category_tabs_width - px,
- 0,
- v2d->mask.xmin + category_tabs_width,
- rct->ymin);
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + category_tabs_width - px,
+ 0,
+ v2d->mask.xmin + category_tabs_width,
+ rct->ymin);
}
#ifdef USE_FLAT_INACTIVE
/* draw line between inactive tabs */
if (is_active == false && is_active_prev == false && pc_dyn->prev) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + (category_tabs_width / 5),
- rct->ymax + px,
- (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5),
- rct->ymax + (px * 3));
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + (category_tabs_width / 5),
+ rct->ymax + px,
+ (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5),
+ rct->ymax + (px * 3));
}
is_active_prev = is_active;
#endif
+ immUnbindProgram();
/* not essential, but allows events to be handled right up until the region edge [#38171] */
pc_dyn->rect.xmin = v2d->mask.xmin;
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index aa3e2464237..a0aecb12b84 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -603,11 +603,13 @@ void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
/* if loading new .blend while popup is open, window will be NULL */
if (block->handle) {
if (win) {
+ const bScreen *screen = WM_window_get_active_screen(win);
+
UI_popup_handlers_remove(&win->modalhandlers, block->handle);
ui_popup_block_free(C, block->handle);
/* In the case we have nested popups, closing one may need to redraw another, see: T48874 */
- for (ARegion *ar = win->screen->regionbase.first; ar; ar = ar->next) {
+ for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
ED_region_tag_refresh_ui(ar);
}
}
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index 15053f0d8ca..24990c593ac 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -324,7 +324,7 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
* Use to refresh centered popups on screen resizing (for splash).
*/
static void ui_block_region_popup_window_listener(
- bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene))
{
switch (wmn->category) {
case NC_WINDOW:
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c
index c9d313a4bab..f14f9af8785 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.c
@@ -397,7 +397,7 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
return match;
}
-static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
+static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar)
{
uiSearchboxData *data = ar->regiondata;
@@ -415,6 +415,9 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
if (data->preview) {
/* draw items */
for (a = 0; a < data->items.totitem; a++) {
+ /* ensure icon is up-to-date */
+ ui_icon_ensure_deferred(C, data->items.icons[a], data->preview);
+
ui_searchbox_butrect(&rect, data, a);
/* widget itself */
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 7d10087dcd9..f71b71fce43 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -157,6 +157,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];
@@ -225,9 +226,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, field->text);
+ UI_fontstyle_draw(&fstyle_header, &bbox, field->text, drawcol);
fstyle_header.shadow = 0;
@@ -238,8 +239,8 @@ 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]);
- UI_fontstyle_draw(&fstyle_header, &bbox, field->text_suffix);
+ rgb_float_to_uchar(drawcol, tip_colors[UI_TIP_LC_ACTIVE]);
+ UI_fontstyle_draw(&fstyle_header, &bbox, field->text_suffix, drawcol);
/* undo offset */
bbox.xmin -= xofs;
@@ -254,8 +255,8 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
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[field->format.color_id]);
- UI_fontstyle_draw(&fstyle_mono, &bbox, field->text);
+ rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]);
+ UI_fontstyle_draw(&fstyle_mono, &bbox, field->text, drawcol);
}
else {
uiFontStyle fstyle_normal = data->fstyle;
@@ -263,9 +264,9 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
fstyle_normal.word_wrap = true;
/* draw remaining data */
+ rgb_float_to_uchar(drawcol, tip_colors[field->format.color_id]);
UI_fontstyle_set(&fstyle_normal);
- glColor3fv(tip_colors[field->format.color_id]);
- UI_fontstyle_draw(&fstyle_normal, &bbox, field->text);
+ UI_fontstyle_draw(&fstyle_normal, &bbox, field->text, drawcol);
}
bbox.ymax -= data->lineh * field->geom.lines;
@@ -306,6 +307,65 @@ static void ui_tooltip_region_free_cb(ARegion *ar)
/** \name ToolTip Creation
* \{ */
+static uiTooltipData *ui_tooltip_data_from_keymap(bContext *C, wmKeyMap *keymap)
+{
+ char buf[512];
+
+ /* create tooltip data */
+ uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
+
+ BLI_assert(data->fields_len < MAX_TOOLTIP_LINES);
+
+ for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ wmOperatorType *ot = WM_operatortype_find(kmi->idname, true);
+ if (ot != NULL) {
+ /* Tip */
+ {
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_MAIN,
+ .is_pad = true,
+ });
+ field->text = BLI_strdup(ot->description[0] ? ot->description : ot->name);
+ }
+ /* Shortcut */
+ {
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_NORMAL,
+ });
+ bool found = false;
+ if (WM_keymap_item_to_string(kmi, false, buf, sizeof(buf))) {
+ found = true;
+ }
+ field->text = BLI_sprintfN(TIP_("Shortcut: %s"), found ? buf : "None");
+ }
+
+ /* Python */
+ {
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_PYTHON,
+ });
+ char *str = WM_operator_pystring_ex(C, NULL, false, false, ot, kmi->ptr);
+ WM_operator_pystring_abbreviate(str, 32);
+ field->text = BLI_sprintfN(TIP_("Python: %s"), str);
+ MEM_freeN(str);
+ }
+ }
+ }
+ if (data->fields_len == 0) {
+ MEM_freeN(data);
+ return NULL;
+ }
+ else {
+ return data;
+ }
+}
+
static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
{
uiStringInfo but_tip = {BUT_GET_TIP, NULL};
@@ -586,8 +646,27 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
if (but->drawflag & UI_BUT_NO_TOOLTIP) {
return NULL;
}
+ uiTooltipData *data = NULL;
+
+ /* custom tips for pre-defined operators */
+ if (but->optype) {
+ if (STREQ(but->optype->idname, "WM_OT_tool_set")) {
+ char keymap[64] = "";
+ RNA_string_get(but->opptr, "keymap", keymap);
+ if (keymap[0]) {
+ ScrArea *sa = CTX_wm_area(C);
+ wmKeyMap *km = WM_keymap_find_all(C, keymap, sa->spacetype, RGN_TYPE_WINDOW);
+ if (km != NULL) {
+ data = ui_tooltip_data_from_keymap(C, km);
+ }
+ }
+ }
+ }
+ /* toolsystem exception */
- uiTooltipData *data = ui_tooltip_data_from_button(C, but);
+ if (data == NULL) {
+ data = ui_tooltip_data_from_button(C, but);
+ }
if (data == NULL) {
return NULL;
}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index dd1d38bbe2e..fa25a119ada 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -61,6 +61,9 @@ ARegion *ui_region_temp_add(bScreen *sc)
void ui_region_temp_remove(bContext *C, bScreen *sc, ARegion *ar)
{
wmWindow *win = CTX_wm_window(C);
+
+ BLI_assert(ar->regiontype == RGN_TYPE_TEMPORARY);
+ BLI_assert(BLI_findindex(&sc->regionbase, ar) != -1);
if (win)
wm_draw_region_clear(win, ar);
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 8b41302b5bb..01456e2e122 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)
@@ -293,7 +296,7 @@ void UI_fontstyle_draw_simple(const uiFontStyle *fs, float x, float y, const cha
*/
void UI_fontstyle_draw_simple_backdrop(
const uiFontStyle *fs, float x, float y, const char *str,
- const unsigned char fg[4], const unsigned char bg[4])
+ const float col_fg[4], const float col_bg[4])
{
if (fs->kerning == 1)
BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
@@ -307,21 +310,19 @@ void UI_fontstyle_draw_simple_backdrop(
const float margin = height / 4.0f;
/* backdrop */
- glColor4ubv(bg);
+ float color[4] = { col_bg[0], col_bg[1], col_bg[2], 0.5f };
- UI_draw_roundbox_corner_set(UI_CNR_ALL | UI_RB_ALPHA);
- UI_draw_roundbox(
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+ UI_draw_roundbox_aa(true,
x - margin,
(y + decent) - margin,
x + width + margin,
(y + decent) + height + margin,
- margin);
-
- glColor4ubv(fg);
+ margin, color);
}
-
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_templates.c b/source/blender/editors/interface/interface_templates.c
index 63bc42f6d10..7c58ac88a23 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -56,10 +56,10 @@
#include "BKE_colorband.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_idcode.h"
#include "BKE_idprop.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_linestyle.h"
#include "BKE_main.h"
@@ -72,6 +72,9 @@
#include "BKE_sca.h"
#include "BKE_screen.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_screen.h"
#include "ED_object.h"
#include "ED_render.h"
@@ -91,11 +94,126 @@
// #define USE_OP_RESET_BUT // we may want to make this optional, disable for now.
+/* defines for templateID/TemplateSearch */
+#define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 6)
+#define TEMPLATE_SEARCH_TEXTBUT_HEIGHT UI_UNIT_Y
+
void UI_template_fix_linking(void)
{
}
+/**
+ * Add a block button for the search menu for templateID and templateSearch.
+ */
+static void template_add_button_search_menu(
+ const bContext *C, uiLayout *layout, uiBlock *block,
+ PointerRNA *ptr, PropertyRNA *prop,
+ uiBlockCreateFunc block_func, void *block_argN, const char * const tip,
+ const bool use_previews, const bool editable)
+{
+ PointerRNA active_ptr = RNA_property_pointer_get(ptr, prop);
+ ID *id = (active_ptr.data && RNA_struct_is_ID(active_ptr.type)) ? active_ptr.data : NULL;
+ const ID *idfrom = ptr->id.data;
+ const StructRNA *type = active_ptr.type ? active_ptr.type : RNA_property_pointer_type(ptr, prop);
+ uiBut *but;
+
+ if (use_previews) {
+ ARegion *region = CTX_wm_region(C);
+ const bool use_big_size = (region->regiontype != RGN_TYPE_HEADER); /* silly check, could be more generic */
+ /* Ugly exception for screens here, drawing their preview in icon size looks ugly/useless */
+ const bool use_preview_icon = use_big_size || (id && (GS(id->name) != ID_SCR));
+ const short width = UI_UNIT_X * (use_big_size ? 6 : 1.6f);
+ const short height = UI_UNIT_Y * (use_big_size ? 6 : 1);
+
+ but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, width, height, tip);
+ if (use_preview_icon) {
+ int icon = id ? ui_id_icon_get(C, id, use_big_size) : RNA_struct_ui_icon(type);
+ ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+ }
+ else {
+ ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
+ UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
+ }
+
+ if ((idfrom && idfrom->lib) || !editable)
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ if (use_big_size) {
+ uiLayoutRow(layout, true);
+ }
+ }
+ else {
+ but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, tip);
+ ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
+ if (id) {
+ /* default dragging of icon for id browse buttons */
+ UI_but_drag_set_id(but, id);
+ }
+ UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
+
+ if ((idfrom && idfrom->lib) || !editable)
+ UI_but_flag_enable(but, UI_BUT_DISABLED);
+ }
+}
+
+static uiBlock *template_common_search_menu(
+ const bContext *C, ARegion *region,
+ uiButSearchFunc search_func, void *search_arg,
+ uiButHandleFunc handle_func, void *active_item,
+ const int preview_rows, const int preview_cols)
+{
+ static char search[256];
+ wmWindow *win = CTX_wm_window(C);
+ uiBlock *block;
+ uiBut *but;
+
+ /* clear initial search string, then all items show */
+ search[0] = 0;
+
+ block = UI_block_begin(C, region, "_popup", UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU);
+
+ /* preview thumbnails */
+ if (preview_rows > 0 && preview_cols > 0) {
+ const int w = 4 * U.widget_unit * preview_cols;
+ const int h = 5 * U.widget_unit * preview_rows;
+
+ /* fake button, it holds space for search items */
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL);
+
+ but = uiDefSearchBut(
+ block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y,
+ preview_rows, preview_cols, "");
+ }
+ /* list view */
+ else {
+ const int searchbox_width = UI_searchbox_size_x();
+ const int searchbox_height = UI_searchbox_size_y();
+
+ /* fake button, it holds space for search items */
+ uiDefBut(
+ block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height,
+ NULL, 0, 0, 0, 0, NULL);
+ but = uiDefSearchBut(
+ block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0,
+ searchbox_width, UI_UNIT_Y - 1, 0, 0, "");
+ }
+ UI_but_func_search_set(
+ but, ui_searchbox_create_generic, search_func,
+ search_arg, handle_func, active_item);
+
+
+ UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
+ UI_block_direction_set(block, UI_DIR_DOWN);
+
+ /* give search-field focus */
+ UI_but_focus_on_enter_event(win, but);
+ /* this type of search menu requires undo */
+ but->flag |= UI_BUT_UNDO;
+
+ return block;
+}
+
/********************** Header Template *************************/
void uiTemplateHeader(uiLayout *layout, bContext *C)
@@ -177,61 +295,16 @@ static void id_search_cb(const bContext *C, void *arg_template, const char *str,
/* ID Search browse menu, open */
static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
{
- static char search[256];
static TemplateID template;
- PointerRNA idptr;
- wmWindow *win = CTX_wm_window(C);
- uiBlock *block;
- uiBut *but;
-
- /* clear initial search string, then all items show */
- search[0] = 0;
+ PointerRNA active_item_ptr;
+
/* arg_litem is malloced, can be freed by parent button */
template = *((TemplateID *)arg_litem);
-
- /* get active id for showing first item */
- idptr = RNA_property_pointer_get(&template.ptr, template.prop);
+ active_item_ptr = RNA_property_pointer_get(&template.ptr, template.prop);
- block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
- UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU);
-
- /* preview thumbnails */
- if (template.prv_rows > 0 && template.prv_cols > 0) {
- int w = 4 * U.widget_unit * template.prv_cols;
- int h = 5 * U.widget_unit * template.prv_rows;
-
- /* fake button, it holds space for search items */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL);
-
- but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y,
- template.prv_rows, template.prv_cols, "");
- UI_but_func_search_set(
- but, ui_searchbox_create_generic, id_search_cb,
- &template, id_search_call_cb, idptr.data);
- }
- /* list view */
- else {
- const int searchbox_width = UI_searchbox_size_x();
- const int searchbox_height = UI_searchbox_size_y();
-
- /* fake button, it holds space for search items */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, NULL, 0, 0, 0, 0, NULL);
- but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, searchbox_width, UI_UNIT_Y - 1, 0, 0, "");
- UI_but_func_search_set(
- but, ui_searchbox_create_generic, id_search_cb,
- &template, id_search_call_cb, idptr.data);
- }
-
-
- UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
- UI_block_direction_set(block, UI_DIR_DOWN);
-
- /* give search-field focus */
- UI_but_focus_on_enter_event(win, but);
- /* this type of search menu requires undo */
- but->flag |= UI_BUT_UNDO;
-
- return block;
+ return template_common_search_menu(
+ C, ar, id_search_cb, &template, id_search_call_cb, active_item_ptr.data,
+ template.prv_rows, template.prv_cols);
}
/************************ ID Template ***************************/
@@ -330,13 +403,13 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
Scene *scene = CTX_data_scene(C);
ED_object_single_user(bmain, scene, (struct Object *)id);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
else {
if (id) {
Main *bmain = CTX_data_main(C);
id_single_user(C, id, &template->ptr, template->prop);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
}
}
@@ -348,7 +421,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
}
}
-static const char *template_id_browse_tip(StructRNA *type)
+static const char *template_id_browse_tip(const StructRNA *type)
{
if (type) {
switch (RNA_type_to_ID_code(type)) {
@@ -380,6 +453,8 @@ static const char *template_id_browse_tip(StructRNA *type)
case ID_PAL: return N_("Browse Palette Data to be linked");
case ID_PC: return N_("Browse Paint Curve Data to be linked");
case ID_CF: return N_("Browse Cache Files to be linked");
+ case ID_WS: return N_("Browse Workspace to be linked");
+ case ID_LP: return N_("Browse LightProbe to be linked");
}
}
return N_("Browse ID data to be linked");
@@ -409,6 +484,7 @@ static void template_ID(
// ListBase *lb; // UNUSED
ID *id, *idfrom;
const bool editable = RNA_property_editable(&template->ptr, template->prop);
+ const bool use_previews = template->preview = (flag & UI_ID_PREVIEWS) != 0;
idptr = RNA_property_pointer_get(&template->ptr, template->prop);
id = idptr.data;
@@ -421,29 +497,11 @@ static void template_ID(
if (idptr.type)
type = idptr.type;
- if (flag & UI_ID_PREVIEWS) {
- template->preview = true;
-
- but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6,
- TIP_(template_id_browse_tip(type)));
- ui_def_but_icon(but, id ? ui_id_icon_get(C, id, true) : RNA_struct_ui_icon(type),
- UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
-
- if ((idfrom && idfrom->lib) || !editable)
- UI_but_flag_enable(but, UI_BUT_DISABLED);
-
- uiLayoutRow(layout, true);
- }
- else if (flag & UI_ID_BROWSE) {
- but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y,
- TIP_(template_id_browse_tip(type)));
- ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
- /* default dragging of icon for id browse buttons */
- UI_but_drag_set_id(but, id);
- UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
-
- if ((idfrom && idfrom->lib) || !editable)
- UI_but_flag_enable(but, UI_BUT_DISABLED);
+ if (flag & UI_ID_BROWSE) {
+ template_add_button_search_menu(
+ C, layout, block, &template->ptr, template->prop,
+ id_search_menu, MEM_dupallocN(template), TIP_(template_id_browse_tip(type)),
+ use_previews, editable);
}
/* text button with name */
@@ -453,8 +511,9 @@ static void template_ID(
//text_idbutton(id, name);
name[0] = '\0';
- but = uiDefButR(block, UI_BTYPE_TEXT, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y,
- &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type));
+ but = uiDefButR(
+ block, UI_BTYPE_TEXT, 0, name, 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT,
+ &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type));
UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT);
@@ -499,7 +558,7 @@ static void template_ID(
if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT);
- if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
+ if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
uiDefButR(block, UI_BTYPE_TOGGLE, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
}
}
@@ -533,6 +592,8 @@ static void template_ID(
BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
BLT_I18NCONTEXT_ID_GPENCIL,
BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
+ BLT_I18NCONTEXT_ID_WORKSPACE,
+ BLT_I18NCONTEXT_ID_LIGHTPROBE,
);
if (newop) {
@@ -740,6 +801,208 @@ void uiTemplateAnyID(
uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE);
}
+/********************* Search Template ********************/
+
+typedef struct TemplateSearch {
+ uiRNACollectionSearch search_data;
+
+ bool use_previews;
+ int preview_rows, preview_cols;
+} TemplateSearch;
+
+static void template_search_handle_cb(bContext *C, void *arg_template, void *item)
+{
+ TemplateSearch *template_search = arg_template;
+ uiRNACollectionSearch *coll_search = &template_search->search_data;
+ StructRNA *type = RNA_property_pointer_type(&coll_search->target_ptr, coll_search->target_prop);
+ PointerRNA item_ptr;
+
+ RNA_pointer_create(NULL, type, item, &item_ptr);
+ RNA_property_pointer_set(&coll_search->target_ptr, coll_search->target_prop, item_ptr);
+ RNA_property_update(C, &coll_search->target_ptr, coll_search->target_prop);
+}
+
+static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_template)
+{
+ static TemplateSearch template_search;
+ PointerRNA active_ptr;
+
+ /* arg_template is malloced, can be freed by parent button */
+ template_search = *((TemplateSearch *)arg_template);
+ active_ptr = RNA_property_pointer_get(&template_search.search_data.target_ptr,
+ template_search.search_data.target_prop);
+
+ return template_common_search_menu(
+ C, region, ui_rna_collection_search_cb, &template_search,
+ template_search_handle_cb, active_ptr.data,
+ template_search.preview_rows, template_search.preview_cols);
+}
+
+static void template_search_add_button_searchmenu(
+ const bContext *C, uiLayout *layout, uiBlock *block,
+ TemplateSearch *template_search, const bool editable)
+{
+ const char *ui_description = RNA_property_ui_description(template_search->search_data.target_prop);
+
+ template_add_button_search_menu(
+ C, layout, block,
+ &template_search->search_data.target_ptr, template_search->search_data.target_prop,
+ template_search_menu, MEM_dupallocN(template_search), ui_description,
+ template_search->use_previews, editable);
+}
+
+static void template_search_add_button_name(
+ uiBlock *block, PointerRNA *active_ptr, const StructRNA *type)
+{
+ uiDefAutoButR(
+ block, active_ptr, RNA_struct_name_property(type), 0, "", ICON_NONE,
+ 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT);
+}
+
+static void template_search_add_button_operator(
+ uiBlock *block, const char * const operator_name,
+ const int opcontext, const int icon, const bool editable)
+{
+ if (!operator_name) {
+ return;
+ }
+
+ uiBut *but = uiDefIconButO(
+ block, UI_BTYPE_BUT, operator_name, opcontext, icon,
+ 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+
+ if (!editable) {
+ UI_but_drawflag_enable(but, UI_BUT_DISABLED);
+ }
+}
+
+static void template_search_buttons(
+ const bContext *C, uiLayout *layout, TemplateSearch *template_search,
+ const char *newop, const char *unlinkop)
+{
+ uiBlock *block = uiLayoutGetBlock(layout);
+ uiRNACollectionSearch *search_data = &template_search->search_data;
+ StructRNA *type = RNA_property_pointer_type(&search_data->target_ptr, search_data->target_prop);
+ const bool editable = RNA_property_editable(&search_data->target_ptr, search_data->target_prop);
+ PointerRNA active_ptr = RNA_property_pointer_get(&search_data->target_ptr, search_data->target_prop);
+
+ if (active_ptr.type) {
+ /* can only get correct type when there is an active item */
+ type = active_ptr.type;
+ }
+
+ uiLayoutRow(layout, true);
+ UI_block_align_begin(block);
+
+ template_search_add_button_searchmenu(C, layout, block, template_search, editable);
+ template_search_add_button_name(block, &active_ptr, type);
+ template_search_add_button_operator(block, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, editable);
+ template_search_add_button_operator(block, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, editable);
+
+ UI_block_align_end(block);
+}
+
+static PropertyRNA *template_search_get_searchprop(
+ PointerRNA *targetptr, PropertyRNA *targetprop,
+ PointerRNA *searchptr, const char * const searchpropname)
+{
+ PropertyRNA *searchprop;
+
+ if (searchptr && !searchptr->data) {
+ searchptr = NULL;
+ }
+
+ if (!searchptr && !searchpropname) {
+ /* both NULL means we don't use a custom rna collection to search in */
+ }
+ else if (!searchptr && searchpropname) {
+ RNA_warning("searchpropname defined (%s) but searchptr is missing", searchpropname);
+ }
+ else if (searchptr && !searchpropname) {
+ RNA_warning("searchptr defined (%s) but searchpropname is missing", RNA_struct_identifier(searchptr->type));
+ }
+ else if (!(searchprop = RNA_struct_find_property(searchptr, searchpropname))) {
+ RNA_warning("search collection property not found: %s.%s",
+ RNA_struct_identifier(searchptr->type), searchpropname);
+ }
+ else if (RNA_property_type(searchprop) != PROP_COLLECTION) {
+ RNA_warning("search collection property is not a collection type: %s.%s",
+ RNA_struct_identifier(searchptr->type), searchpropname);
+ }
+ /* check if searchprop has same type as targetprop */
+ else if (RNA_property_pointer_type(searchptr, searchprop) != RNA_property_pointer_type(targetptr, targetprop)) {
+ RNA_warning("search collection items from %s.%s are not of type %s",
+ RNA_struct_identifier(searchptr->type), searchpropname,
+ RNA_struct_identifier(RNA_property_pointer_type(targetptr, targetprop)));
+ }
+ else {
+ return searchprop;
+ }
+
+ return NULL;
+}
+
+static TemplateSearch *template_search_setup(
+ PointerRNA *ptr, const char * const propname,
+ PointerRNA *searchptr, const char * const searchpropname)
+{
+ TemplateSearch *template_search;
+ PropertyRNA *prop, *searchprop;
+
+ prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop || RNA_property_type(prop) != PROP_POINTER) {
+ RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return NULL;
+ }
+ searchprop = template_search_get_searchprop(ptr, prop, searchptr, searchpropname);
+
+ template_search = MEM_callocN(sizeof(*template_search), __func__);
+ template_search->search_data.target_ptr = *ptr;
+ template_search->search_data.target_prop = prop;
+ template_search->search_data.search_ptr = *searchptr;
+ template_search->search_data.search_prop = searchprop;
+
+ return template_search;
+}
+
+/**
+ * Search menu to pick an item from a collection.
+ * A version of uiTemplateID that works for non-ID types.
+ */
+void uiTemplateSearch(
+ uiLayout *layout, bContext *C,
+ PointerRNA *ptr, const char *propname,
+ PointerRNA *searchptr, const char *searchpropname,
+ const char *newop, const char *unlinkop)
+{
+ TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname);
+ if (template_search != NULL) {
+ template_search_buttons(C, layout, template_search, newop, unlinkop);
+ MEM_freeN(template_search);
+ }
+}
+
+void uiTemplateSearchPreview(
+ uiLayout *layout, bContext *C,
+ PointerRNA *ptr, const char *propname,
+ PointerRNA *searchptr, const char *searchpropname,
+ const char *newop, const char *unlinkop,
+ const int rows, const int cols)
+{
+ TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname);
+
+ if (template_search != NULL) {
+ template_search->use_previews = true;
+ template_search->preview_rows = rows;
+ template_search->preview_cols = cols;
+
+ template_search_buttons(C, layout, template_search, newop, unlinkop);
+
+ MEM_freeN(template_search);
+ }
+}
+
/********************* RNA Path Builder Template ********************/
/* ---------- */
@@ -793,7 +1056,7 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
ob->partype = PAROBJECT;
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
ED_undo_push(C, "Modifier convert to real");
}
@@ -937,7 +1200,7 @@ static uiLayout *draw_modifier(
/* When Modifier is a simulation, show button to switch to context rather than the delete button. */
if (modifier_can_delete(md) &&
(!modifier_is_simulation(md) ||
- STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)))
+ STREQ(scene->view_render.engine_id, RE_engine_id_BLENDER_GAME)))
{
uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
}
@@ -1074,7 +1337,7 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event)
Main *bmain = CTX_data_main(C);
if (ob->pose)
BKE_pose_tag_recalc(bmain, ob->pose); /* checks & sorts pose channels */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
break;
}
#endif
@@ -1088,8 +1351,8 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event)
* object_test_constraints(ob);
* if (ob->pose) BKE_pose_update_constraint_flags(ob->pose); */
- if (ob->type == OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
- else DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ if (ob->type == OB_ARMATURE) DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
+ else DEG_id_tag_update(&ob->id, OB_RECALC_OB);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
}
@@ -3849,6 +4112,7 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
if (propptr.data) {
uiBut *but = uiLayoutGetBlock(layout)->buttons.last;
+ WM_operator_properties_sanitize(&propptr, false);
template_keymap_item_properties(layout, NULL, &propptr);
/* attach callbacks to compensate for missing properties update,
@@ -3865,6 +4129,66 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
}
}
+/********************************* Overrides *************************************/
+
+void uiTemplateOverrideProperty(
+ uiLayout *layout, PointerRNA *collection_props_ptr, PointerRNA *scene_props_ptr, const char *propname,
+ const char *name, const char *text_ctxt, int translate, int icon,
+ const char *custom_template)
+{
+ bool is_set = false;
+ uiLayout *row, *col;
+
+ PointerRNA *ptr;
+ PropertyRNA *prop;
+
+ IDProperty *collection_props = collection_props_ptr->data;
+
+ if (IDP_GetPropertyFromGroup(collection_props, propname)) {
+ prop = RNA_struct_find_property(collection_props_ptr, propname);
+ ptr = collection_props_ptr;
+ is_set = RNA_property_is_set(ptr, prop);
+ }
+ else {
+ /* property doesn't exist yet */
+ prop = RNA_struct_find_property(scene_props_ptr, propname);
+ ptr = scene_props_ptr;
+ }
+
+ /* Get translated name (label). */
+ name = RNA_translate_ui_text(name, text_ctxt, NULL, prop, translate);
+
+ row = uiLayoutRow(layout, false);
+ col = uiLayoutColumn(row, false);
+
+ uiLayoutSetEnabled(col, is_set);
+
+ if (custom_template && STREQ(custom_template, "icon_view")) {
+ uiTemplateIconView(col, ptr, propname, false, 5.0f);
+ }
+ else {
+ uiItemFullR(col, ptr, prop, -1, 0, 0, name, icon);
+ }
+
+ col = uiLayoutColumn(row, false);
+ uiBut *but;
+ uiBlock *block = uiLayoutGetBlock(col);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ if (is_set) {
+ but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_unuse_property_button", WM_OP_EXEC_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ }
+ else {
+ but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_use_property_button", WM_OP_EXEC_DEFAULT, ICON_ZOOMIN, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ /* XXX - Using existing data struct to pass another RNAPointer */
+ but->rnasearchpoin = *scene_props_ptr;
+ }
+
+ but->rnapoin = *collection_props_ptr;
+ but->rnaprop = prop;
+ UI_block_emboss_set(block, UI_EMBOSS);
+}
+
/********************************* Color management *************************************/
void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char *propname)
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 1927d7280f3..f0317087ddc 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -215,8 +215,90 @@ int uiDefAutoButsRNA(
return tot;
}
-/***************************** ID Utilities *******************************/
+/* *** RNA collection search menu *** */
+typedef struct CollItemSearch {
+ struct CollItemSearch *next, *prev;
+ void *data;
+ char *name;
+ int index;
+ int iconid;
+} CollItemSearch;
+
+static int sort_search_items_list(const void *a, const void *b)
+{
+ const CollItemSearch *cis1 = a;
+ const CollItemSearch *cis2 = b;
+
+ if (BLI_strcasecmp(cis1->name, cis2->name) > 0)
+ return 1;
+ else
+ return 0;
+}
+
+void ui_rna_collection_search_cb(const struct bContext *C, void *arg, const char *str, uiSearchItems *items)
+{
+ uiRNACollectionSearch *data = arg;
+ char *name;
+ int i = 0, iconid = 0, flag = RNA_property_flag(data->target_prop);
+ ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list");
+ CollItemSearch *cis;
+ const bool skip_filter = !(data->but_changed && *data->but_changed);
+
+ /* build a temporary list of relevant items first */
+ RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop)
+ {
+
+ if (flag & PROP_ID_SELF_CHECK)
+ if (itemptr.data == data->target_ptr.id.data)
+ continue;
+
+ /* use filter */
+ if (RNA_property_type(data->target_prop) == PROP_POINTER) {
+ if (RNA_property_pointer_poll(&data->target_ptr, data->target_prop, &itemptr) == 0)
+ continue;
+ }
+
+ name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */
+ iconid = 0;
+ if (itemptr.type && RNA_struct_is_ID(itemptr.type)) {
+ iconid = ui_id_icon_get(C, itemptr.data, false);
+ }
+
+ if (name) {
+ if (skip_filter || BLI_strcasestr(name, str)) {
+ cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch");
+ cis->data = itemptr.data;
+ cis->name = MEM_dupallocN(name);
+ cis->index = i;
+ cis->iconid = iconid;
+ BLI_addtail(items_list, cis);
+ }
+ MEM_freeN(name);
+ }
+
+ i++;
+ }
+ RNA_PROP_END;
+
+ BLI_listbase_sort(items_list, sort_search_items_list);
+
+ /* add search items from temporary list */
+ for (cis = items_list->first; cis; cis = cis->next) {
+ if (UI_search_item_add(items, cis->name, cis->data, cis->iconid) == false) {
+ break;
+ }
+ }
+
+ for (cis = items_list->first; cis; cis = cis->next) {
+ MEM_freeN(cis->name);
+ }
+ BLI_freelistN(items_list);
+ MEM_freeN(items_list);
+}
+
+
+/***************************** ID Utilities *******************************/
int UI_icon_from_id(ID *id)
{
Object *ob;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 39ee8e2885d..cc4f53cbabf 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -47,9 +47,6 @@
#include "RNA_access.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
#include "BLF_api.h"
#include "UI_interface.h"
@@ -58,6 +55,9 @@
#include "interface_intern.h"
#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#ifdef WITH_INPUT_IME
# include "WM_types.h"
@@ -208,48 +208,58 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}}
/* ************************************************* */
-void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3)
+void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3,
+ const float color[4])
{
float tri_arr[3][2] = {{x1, y1}, {x2, y2}, {x3, y3}};
- float color[4];
- int j;
-
+ float draw_color[4];
+
+ copy_v4_v4(draw_color, color);
+ draw_color[3] *= 0.125f;
+
glEnable(GL_BLEND);
- glGetFloatv(GL_CURRENT_COLOR, color);
- color[3] *= 0.125f;
- glColor4fv(color);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, tri_arr);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4fv(draw_color);
+ immBegin(GWN_PRIM_TRIS, 3 * WIDGET_AA_JITTER);
/* for each AA step */
- for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
- glDrawArrays(GL_TRIANGLES, 0, 3);
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ immVertex2f(pos, tri_arr[0][0] + jit[j][0], tri_arr[0][1] + jit[j][1]);
+ immVertex2f(pos, tri_arr[1][0] + jit[j][0], tri_arr[1][1] + jit[j][1]);
+ immVertex2f(pos, tri_arr[2][0] + jit[j][0], tri_arr[2][1] + jit[j][1]);
}
- glDisableClientState(GL_VERTEX_ARRAY);
+ immEnd();
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
-void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha)
+/* belongs in interface_draw.c, but needs WIDGET_AA_JITTER from this file */
+void UI_draw_roundbox_aa(bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4])
{
- float color[4];
- int j;
-
glEnable(GL_BLEND);
- glGetFloatv(GL_CURRENT_COLOR, color);
- if (use_alpha) {
- color[3] = 0.5f;
+
+ if (filled) {
+ /* plain antialiased filled box */
+ const float alpha = color[3] * 0.125f;
+
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ gpuPushMatrix();
+ gpuTranslate2fv(jit[j]);
+ UI_draw_roundbox_3fvAlpha(true, minx, miny, maxx, maxy, rad, color, alpha);
+ gpuPopMatrix();
+ }
}
- color[3] *= 0.125f;
- glColor4fv(color);
-
- for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
- UI_draw_roundbox_gl_mode(mode, minx, miny, maxx, maxy, rad);
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
+ else {
+ /* plain antialiased unfilled box */
+ glEnable(GL_LINE_SMOOTH);
+ UI_draw_roundbox_4fv(false, minx, miny, maxx, maxy, rad, color);
+ glDisable(GL_LINE_SMOOTH);
}
glDisable(GL_BLEND);
@@ -570,12 +580,27 @@ static void shape_preset_init_scroll_circle(uiWidgetTrias *tria, const rcti *rec
g_shape_preset_scroll_circle_face, ARRAY_SIZE(g_shape_preset_scroll_circle_face));
}
-static void shape_preset_draw_trias(uiWidgetTrias *tria)
+static void shape_preset_draw_trias(uiWidgetTrias *tria, uint pos)
{
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, tria->vec);
- glDrawElements(GL_TRIANGLES, tria->tot * 3, GL_UNSIGNED_INT, tria->index);
- glDisableClientState(GL_VERTEX_ARRAY);
+ immBegin(GWN_PRIM_TRIS, tria->tot * 3);
+ for (int i = 0; i < tria->tot; ++i)
+ for (int j = 0; j < 3; ++j)
+ immVertex2fv(pos, tria->vec[tria->index[i][j]]);
+ immEnd();
+}
+
+static void widget_draw_vertex_buffer(unsigned int pos, unsigned int col, int mode,
+ const float quads_pos[WIDGET_SIZE_MAX][2],
+ const unsigned char quads_col[WIDGET_SIZE_MAX][4],
+ unsigned int totvert)
+{
+ immBegin(mode, totvert);
+ for (int i = 0; i < totvert; ++i) {
+ if (quads_col)
+ immAttrib4ubv(col, quads_col[i]);
+ immVertex2fv(pos, quads_pos[i]);
+ }
+ immEnd();
}
static void shape_preset_trias_from_rect_menu(uiWidgetTrias *tria, const rcti *rect)
@@ -666,21 +691,18 @@ static void widget_verts_to_triangle_strip_open(uiWidgetBase *wtb, const int tot
}
}
-static void widgetbase_outline(uiWidgetBase *wtb)
+static void widgetbase_outline(uiWidgetBase *wtb, unsigned int pos)
{
float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
- glDisableClientState(GL_VERTEX_ARRAY);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2);
}
static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
{
int j, a;
-
+
glEnable(GL_BLEND);
/* backdrop non AA */
@@ -690,78 +712,76 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
float inner_v_half[WIDGET_SIZE_MAX][2];
float x_mid = 0.0f; /* used for dumb clamping of values */
- /* dark checkers */
- glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
- /* light checkers */
- 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);
+ /* checkers */
+ 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);
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immUnbindProgram();
/* alpha fill */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((unsigned char *)wcol->inner);
- glColor4ubv((unsigned char *)wcol->inner);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (a = 0; a < wtb->totvert; a++) {
x_mid += wtb->inner_v[a][0];
}
x_mid /= wtb->totvert;
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert);
/* 1/2 solid color */
- glColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255);
+ immUniformColor3ubv((unsigned char *)wcol->inner);
for (a = 0; a < wtb->totvert; a++) {
inner_v_half[a][0] = MIN2(wtb->inner_v[a][0], x_mid);
inner_v_half[a][1] = wtb->inner_v[a][1];
}
- glVertexPointer(2, GL_FLOAT, 0, inner_v_half);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, inner_v_half, NULL, wtb->totvert);
+
+ immUnbindProgram();
}
else {
/* simple fill */
- glColor4ubv((unsigned char *)wcol->inner);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((unsigned char *)wcol->inner);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert);
+
+ immUnbindProgram();
}
}
else {
char col1[4], col2[4];
- unsigned char col_array[WIDGET_SIZE_MAX * 4];
- unsigned char *col_pt = col_array;
-
+ unsigned char col_array[WIDGET_SIZE_MAX][4];
+ unsigned char *col_pt = &col_array[0][0];
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
for (a = 0; a < wtb->totvert; a++, col_pt += 4) {
round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->draw_shadedir ? 1 : 0]);
}
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, col_array);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
+ widget_draw_vertex_buffer(pos, col, GL_TRIANGLE_FAN, wtb->inner_v, col_array, wtb->totvert);
+ immUnbindProgram();
}
}
-
+
/* for each AA step */
if (wtb->draw_outline) {
float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
@@ -780,53 +800,55 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss);
}
- glEnableClientState(GL_VERTEX_ARRAY);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
+ gpuTranslate2fv(jit[j]);
/* outline */
- glColor4ubv(tcol);
+ immUniformColor4ubv(tcol);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2);
/* emboss bottom shadow */
if (wtb->draw_emboss) {
if (emboss[3]) {
- glColor4ubv(emboss);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip_emboss);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->halfwayvert * 2);
+ immUniformColor4ubv(emboss);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip_emboss, NULL, wtb->halfwayvert * 2);
}
}
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
+ gpuTranslate2f(-jit[j][0], -jit[j][1]);
}
-
- glDisableClientState(GL_VERTEX_ARRAY);
+ immUnbindProgram();
}
-
+
/* decoration */
if (wtb->tria1.tot || wtb->tria2.tot) {
const unsigned char tcol[4] = {wcol->item[0],
wcol->item[1],
wcol->item[2],
(unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER)};
- glColor4ubv(tcol);
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv(tcol);
/* for each AA step */
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
+ gpuTranslate2fv(jit[j]);
- if (wtb->tria1.tot) {
- shape_preset_draw_trias(&wtb->tria1);
- }
- if (wtb->tria2.tot) {
- shape_preset_draw_trias(&wtb->tria2);
- }
+ if (wtb->tria1.tot)
+ shape_preset_draw_trias(&wtb->tria1, pos);
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
+ if (wtb->tria2.tot)
+ shape_preset_draw_trias(&wtb->tria2, pos);
+
+ gpuTranslate2f(-jit[j][0], -jit[j][1]);
}
+
+ immUnbindProgram();
}
glDisable(GL_BLEND);
@@ -1282,6 +1304,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) {
@@ -1294,8 +1317,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) {
@@ -1312,7 +1335,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);
}
}
}
@@ -1396,11 +1419,16 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
selwidth_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selend - but->ofs);
- glColor4ubv((unsigned char *)wcol->item);
- glRecti(rect->xmin + selsta_draw,
- rect->ymin + 2,
- min_ii(rect->xmin + selwidth_draw, rect->xmax - 2),
- rect->ymax - 2);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4ubv((unsigned char *)wcol->item);
+ immRecti(pos, rect->xmin + selsta_draw,
+ rect->ymin + 2,
+ min_ii(rect->xmin + selwidth_draw, rect->xmax - 2),
+ rect->ymax - 2);
+
+ immUnbindProgram();
}
}
@@ -1423,13 +1451,18 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
t = 0;
}
- glColor3f(0.2, 0.6, 0.9);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(0.2f, 0.6f, 0.9f);
tx = rect->xmin + t + 2;
ty = rect->ymin + 2;
/* draw cursor */
- glRecti(rect->xmin + t, ty, tx, rect->ymax - 2);
+ immRecti(pos, rect->xmin + t, ty, tx, rect->ymax - 2);
+
+ immUnbindProgram();
}
#ifdef WITH_INPUT_IME
@@ -1488,43 +1521,46 @@ 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;
- UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs,
- drawstr_left_len - but->ofs, &font_xofs, &font_yofs);
+ int drawlen = (drawstr_left_len == INT_MAX) ? strlen(drawstr + but->ofs) : (drawstr_left_len - but->ofs);
- if (but->menu_key != '\0') {
- char fixedbuf[128];
- const char *str;
+ if (drawlen > 0) {
+ UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs, (unsigned char *)wcol->text,
+ drawlen, &font_xofs, &font_yofs);
- BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawstr_left_len));
+ if (but->menu_key != '\0') {
+ char fixedbuf[128];
+ const char *str;
- str = strchr(fixedbuf, but->menu_key - 32); /* upper case */
- if (str == NULL)
- str = strchr(fixedbuf, but->menu_key);
+ BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawlen));
- if (str) {
- int ul_index = -1;
- float ul_advance;
+ str = strchr(fixedbuf, but->menu_key - 32); /* upper case */
+ if (str == NULL)
+ str = strchr(fixedbuf, but->menu_key);
- ul_index = (int)(str - fixedbuf);
+ if (str) {
+ int ul_index = -1;
+ float ul_advance;
- if (fstyle->kerning == 1) {
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
+ ul_index = (int)(str - fixedbuf);
+
+ if (fstyle->kerning == 1) {
+ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
- fixedbuf[ul_index] = '\0';
- ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index);
+ fixedbuf[ul_index] = '\0';
+ ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index);
- BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f);
- BLF_draw(fstyle->uifont_id, "_", 2);
+ BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f);
+ BLF_color4ubv(fstyle->uifont_id, (unsigned char *)wcol->text);
+ BLF_draw(fstyle->uifont_id, "_", 2);
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ if (fstyle->kerning == 1) {
+ BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
}
}
}
@@ -1534,7 +1570,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);
}
}
@@ -1657,6 +1693,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
widget_draw_text(fstyle, wcol, but, rect);
ui_but_text_password_hide(password_str, but, true);
+
+ /* if a widget uses font shadow it has to be deactivated now */
+ BLF_disable(fstyle->uifont_id, BLF_SHADOW);
}
#undef UI_TEXT_CLIP_MARGIN
@@ -1671,6 +1710,8 @@ static struct uiWidgetStateColors wcol_state_colors = {
{215, 211, 75, 255},
{180, 0, 255, 255},
{153, 0, 230, 255},
+ {74, 137, 137, 255},
+ {49, 112, 112, 255},
0.5f, 0.0f
};
@@ -1915,6 +1956,19 @@ static struct uiWidgetColors wcol_list_item = {
0, 0
};
+struct uiWidgetColors wcol_tab = {
+ {255, 255, 255, 255},
+ {83, 83, 83, 255},
+ {114, 114, 114, 255},
+ {90, 90, 90, 255},
+
+ {0, 0, 0, 255},
+ {0, 0, 0, 255},
+
+ 0,
+ 0, 0
+};
+
/* free wcol struct to play with */
static struct uiWidgetColors wcol_tmp = {
{0, 0, 0, 255},
@@ -1937,6 +1991,7 @@ void ui_widget_color_init(ThemeUI *tui)
tui->wcol_tool = wcol_tool;
tui->wcol_text = wcol_text;
tui->wcol_radio = wcol_radio;
+ tui->wcol_tab = wcol_tab;
tui->wcol_option = wcol_option;
tui->wcol_toggle = wcol_toggle;
tui->wcol_num = wcol_num;
@@ -2009,6 +2064,8 @@ static void widget_state(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.inner, wcol_state->inner_anim_sel, wcol_state->blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.inner, wcol_state->inner_driven_sel, wcol_state->blend);
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden_sel, wcol_state->blend);
copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
@@ -2022,6 +2079,8 @@ static void widget_state(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.inner, wcol_state->inner_anim, wcol_state->blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.inner, wcol_state->inner_driven, wcol_state->blend);
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden, wcol_state->blend);
if (state & UI_ACTIVE) { /* mouse over? */
wt->wcol.inner[0] = wt->wcol.inner[0] >= 240 ? 255 : wt->wcol.inner[0] + 15;
@@ -2067,7 +2126,9 @@ static void widget_state_numslider(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.item, wcol_state->inner_anim_sel, blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.item, wcol_state->inner_driven_sel, blend);
-
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.item, wcol_state->inner_overridden_sel, blend);
+
if (state & UI_SELECT)
SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
}
@@ -2078,6 +2139,8 @@ static void widget_state_numslider(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.item, wcol_state->inner_anim, blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.item, wcol_state->inner_driven, blend);
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.item, wcol_state->inner_overridden, blend);
}
}
@@ -2195,23 +2258,24 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r
/* we draw a number of increasing size alpha quad strips */
alphastep = 3.0f * btheme->tui.menu_shadow_fac / radout;
-
- glEnableClientState(GL_VERTEX_ARRAY);
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
for (step = 1; step <= (int)radout; step++) {
float expfac = sqrtf(step / radout);
round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step);
- glColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
+ immUniformColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, totvert * 2); /* add + 2 for getting a complete soft rect. Now it skips top edge to allow transparent menus */
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, totvert * 2);
}
- glDisableClientState(GL_VERTEX_ARRAY);
+ immUnbindProgram();
}
static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
@@ -2248,20 +2312,21 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
static void ui_hsv_cursor(float x, float y)
{
- glPushMatrix();
- glTranslatef(x, y, 0.0f);
-
- glColor3f(1.0f, 1.0f, 1.0f);
- glutil_draw_filled_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 8);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ imm_draw_circle_fill_2d(pos, x, y, 3.0f * U.pixelsize, 8);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- glColor3f(0.0f, 0.0f, 0.0f);
- glutil_draw_lined_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 12);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ imm_draw_circle_wire_2d(pos, x, y, 3.0f * U.pixelsize, 12);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
+
+ immUnbindProgram();
}
void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect,
@@ -2301,18 +2366,17 @@ void ui_hsvcircle_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float
static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
{
+ /* TODO(merwin): reimplement as shader for pixel-perfect colors */
+
const int tot = 64;
const float radstep = 2.0f * (float)M_PI / (float)tot;
const float centx = BLI_rcti_cent_x_fl(rect);
const float centy = BLI_rcti_cent_y_fl(rect);
float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
- /* gouraud triangle fan */
ColorPicker *cpicker = but->custom_data;
const float *hsv_ptr = cpicker->color_data;
- float xpos, ypos, ang = 0.0f;
float rgb[3], hsvo[3], hsv[3], col[3], colcent[3];
- int a;
bool color_profile = ui_but_is_colorpicker_display_space(but);
/* color */
@@ -2343,11 +2407,18 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2);
- glBegin(GL_TRIANGLE_FAN);
- glColor3fv(colcent);
- glVertex2f(centx, centy);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ immBegin(GWN_PRIM_TRI_FAN, tot + 2);
+ immAttrib3fv(color, colcent);
+ immVertex2f(pos, centx, centy);
- for (a = 0; a <= tot; a++, ang += radstep) {
+ float ang = 0.0f;
+ for (int a = 0; a <= tot; a++, ang += radstep) {
float si = sinf(ang);
float co = cosf(ang);
@@ -2355,25 +2426,32 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
ui_color_picker_to_rgb_v(hsv, col);
- glColor3fv(col);
- glVertex2f(centx + co * radius, centy + si * radius);
+ immAttrib3fv(color, col);
+ immVertex2f(pos, centx + co * radius, centy + si * radius);
}
- glEnd();
-
+ immEnd();
+ immUnbindProgram();
+
/* fully rounded outline */
- glPushMatrix();
- glTranslatef(centx, centy, 0.0f);
+ format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- glColor3ubv((unsigned char *)wcol->outline);
- glutil_draw_lined_arc(0.0f, M_PI * 2.0, radius, tot + 1);
+
+ immUniformColor3ubv((unsigned char *)wcol->outline);
+ imm_draw_circle_wire_2d(pos, centx, centy, radius, tot);
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
- glPopMatrix();
/* cursor */
+ float xpos, ypos;
ui_hsvcircle_pos_from_vals(but, rect, hsvo, &xpos, &ypos);
-
ui_hsv_cursor(xpos, ypos);
}
@@ -2383,7 +2461,8 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha)
{
/* allows for 4 steps (red->yellow) */
- const float color_step = 1.0f / 48.0f;
+ const int steps = 48;
+ const float color_step = 1.0f / steps;
int a;
float h = hsv[0], s = hsv[1], v = hsv[2];
float dx, dy, sx1, sx2, sy;
@@ -2437,9 +2516,14 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
copy_v3_v3(col1[3], col1[2]);
break;
}
-
+
/* old below */
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ immBegin(GWN_PRIM_TRIS, steps * 3 * 6);
for (dx = 0.0f; dx < 0.999f; dx += color_step) { /* 0.999 = prevent float inaccuracy for steps */
const float dx_next = dx + color_step;
@@ -2497,22 +2581,29 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
sy = rect->ymin;
dy = (float)BLI_rcti_size_y(rect) / 3.0f;
- glBegin(GL_QUADS);
for (a = 0; a < 3; a++, sy += dy) {
- glColor4f(col0[a][0], col0[a][1], col0[a][2], alpha);
- glVertex2f(sx1, sy);
+ immAttrib4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
+ immVertex2f(pos, sx1, sy);
- glColor4f(col1[a][0], col1[a][1], col1[a][2], alpha);
- glVertex2f(sx2, sy);
+ immAttrib4f(col, col1[a][0], col1[a][1], col1[a][2], alpha);
+ immVertex2f(pos, sx2, sy);
+
+ immAttrib4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
+ immVertex2f(pos, sx2, sy + dy);
- glColor4f(col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
- glVertex2f(sx2, sy + dy);
+ immAttrib4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
+ immVertex2f(pos, sx1, sy);
+
+ immAttrib4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
+ immVertex2f(pos, sx2, sy + dy);
- glColor4f(col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
- glVertex2f(sx1, sy + dy);
+ immAttrib4f(col, col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
+ immVertex2f(pos, sx1, sy + dy);
}
- glEnd();
}
+ immEnd();
+
+ immUnbindProgram();
}
bool ui_but_is_colorpicker_display_space(uiBut *but)
@@ -2588,8 +2679,11 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
ui_hsv_cursor(x, y);
/* outline */
- glColor3ub(0, 0, 0);
- fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ub(0, 0, 0);
+ imm_draw_box_wire_2d(pos, (rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
+ immUnbindProgram();
}
/* vertical 'value' slider, using new widget code */
@@ -2657,12 +2751,22 @@ static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol)
wcol->text[2],
30
};
-
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
glEnable(GL_BLEND);
- glColor4ubv(col);
+ immUniformColor4ubv(col);
glLineWidth(1.0f);
- sdrawline(rect->xmin, y, rect->xmax, y);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, rect->xmin, y);
+ immVertex2f(pos, rect->xmax, y);
+ immEnd();
+
glDisable(GL_BLEND);
+
+ immUnbindProgram();
}
/* ************ button callbacks, draw ***************** */
@@ -2734,11 +2838,14 @@ bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol)
}
#define LINK_RESOL 24
-void ui_draw_link_bezier(const rcti *rect)
+void ui_draw_link_bezier(const rcti *rect, const float color[4])
{
float coord_array[LINK_RESOL + 1][2];
if (ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
#if 0 /* unused */
/* we can reuse the dist variable here to increment the GL curve eval amount*/
const float dist = 1.0f / (float)LINK_RESOL;
@@ -2746,13 +2853,17 @@ void ui_draw_link_bezier(const rcti *rect)
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, coord_array);
- glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL + 1);
- glDisableClientState(GL_VERTEX_ARRAY);
+ immUniformColor4fv(color);
+
+ immBegin(GWN_PRIM_LINE_STRIP, LINK_RESOL + 1);
+ for (int i = 0; i <= LINK_RESOL; ++i)
+ immVertex2fv(pos, coord_array[i]);
+ immEnd();
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
+
+ immUnbindProgram();
}
}
@@ -2934,15 +3045,16 @@ static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, in
if (but->flag & UI_SELECT) {
rcti rectlink;
+ float color[4];
- UI_ThemeColor(TH_TEXT_HI);
+ UI_GetThemeColor4fv(TH_TEXT_HI, color);
rectlink.xmin = BLI_rcti_cent_x(rect);
rectlink.ymin = BLI_rcti_cent_y(rect);
rectlink.xmax = but->linkto[0];
rectlink.ymax = but->linkto[1];
- ui_draw_link_bezier(&rectlink);
+ ui_draw_link_bezier(&rectlink, color);
}
}
@@ -3055,7 +3167,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
ui_but_v3_get(but, col);
- if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
+ if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_OVERRIDEN | UI_BUT_REDALERT)) {
/* draw based on state - color for keyed etc */
widgetbase_draw(&wtb, wcol);
@@ -3094,13 +3206,18 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
float bw = rgb_to_grayscale(col);
bw += (bw < 0.5f) ? 0.5f : -0.5f;
-
- glColor4f(bw, bw, bw, 1.0);
- glBegin(GL_TRIANGLES);
- glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
- glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
- glVertex2f(rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
- glEnd();
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(bw, bw, bw);
+ immBegin(GWN_PRIM_TRIS, 3);
+ immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
+ immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
+ immVertex2f(pos, rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
+ immEnd();
+
+ immUnbindProgram();
}
}
@@ -3416,12 +3533,50 @@ static void widget_roundbut_exec(uiWidgetColors *wcol, rcti *rect, int state, in
widgetbase_draw(&wtb, wcol);
}
+static void widget_tab(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
+{
+ const uiStyle *style = UI_style_get();
+ const float rad = 0.15f * U.widget_unit;
+ const int fontid = style->widget.uifont_id;
+ const bool is_active = (but->flag & UI_SELECT);
+
+ uiWidgetBase wtb;
+ unsigned char theme_col_tab_highlight[3];
+
+ /* create outline highlight colors */
+ if (is_active) {
+ interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner_sel,
+ (unsigned char *)wcol->outline, 0.2f);
+ }
+ else {
+ interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner,
+ (unsigned char *)wcol->outline, 0.12f);
+ }
+
+ widget_init(&wtb);
+
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, rad);
+
+ /* draw inner */
+ wtb.draw_outline = 0;
+ widgetbase_draw(&wtb, wcol);
+
+ /* draw outline (3d look) */
+ ui_draw_but_TAB_outline(rect, rad, theme_col_tab_highlight, (unsigned char *)wcol->inner);
+
+ /* text shadow */
+ BLF_enable(fontid, BLF_SHADOW);
+ BLF_shadow(fontid, 3, (const float[4]){1.0f, 1.0f, 1.0f, 0.25f});
+ BLF_shadow_offset(fontid, 0, -1);
+}
+
static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
{
uiWidgetBase wtb;
const float rad = 0.25f * U.widget_unit;
unsigned char col[4];
-
+
/* state copy! */
wt->wcol = *(wt->wcol_theme);
@@ -3431,12 +3586,17 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
/* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* make mask to draw over image */
UI_GetThemeColor3ubv(TH_BACK, col);
- glColor3ubv(col);
-
+ immUniformColor3ubv(col);
+
round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, rad);
- widgetbase_outline(&wtb);
+ widgetbase_outline(&wtb, pos);
+
+ immUnbindProgram();
}
/* outline */
@@ -3498,6 +3658,11 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.draw = widget_roundbut_exec;
break;
+ case UI_WTYPE_TAB:
+ wt.custom = widget_tab;
+ wt.wcol_theme = &btheme->tui.wcol_tab;
+ break;
+
case UI_WTYPE_TOOLTIP:
wt.wcol_theme = &btheme->tui.wcol_tooltip;
wt.draw = widget_menu_back;
@@ -3760,7 +3925,11 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
if (but->block->flag & UI_BLOCK_LOOP)
wt->wcol_theme = &btheme->tui.wcol_menu_back;
break;
-
+
+ case UI_BTYPE_TAB:
+ wt = widget_type(UI_WTYPE_TAB);
+ break;
+
case UI_BTYPE_BUT_TOGGLE:
case UI_BTYPE_TOGGLE:
case UI_BTYPE_TOGGLE_N:
@@ -3962,15 +4131,21 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
wt->draw(&wt->wcol, rect, 0, 0);
if (block) {
+ float draw_color[4];
+ unsigned char *color = (unsigned char *)wt->wcol.text;
+
+ draw_color[0] = ((float)color[0]) / 255.0f;
+ draw_color[1] = ((float)color[1]) / 255.0f;
+ draw_color[2] = ((float)color[2]) / 255.0f;
+ draw_color[3] = 1.0f;
+
if (block->flag & UI_BLOCK_CLIPTOP) {
/* XXX no scaling for UI here yet */
- glColor3ubv((unsigned char *)wt->wcol.text);
- UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't');
+ UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't', draw_color);
}
if (block->flag & UI_BLOCK_CLIPBOTTOM) {
/* XXX no scaling for UI here yet */
- glColor3ubv((unsigned char *)wt->wcol.text);
- UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v');
+ UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v', draw_color);
}
}
}
@@ -3988,33 +4163,21 @@ static void draw_disk_shaded(
float y1, y2;
float fac;
unsigned char r_col[4];
+ unsigned int pos, col;
- glBegin(GL_TRIANGLE_STRIP);
-
- s = sinf(start);
- c = cosf(start);
-
- y1 = s * radius_int;
- y2 = s * radius_ext;
-
+ Gwn_VertFormat *format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
if (shaded) {
- fac = (y1 + radius_ext) * radius_ext_scale;
- round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
}
-
- glVertex2f(c * radius_int, s * radius_int);
-
- if (shaded) {
- fac = (y2 + radius_ext) * radius_ext_scale;
- round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ else {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((unsigned char *)col1);
}
- glVertex2f(c * radius_ext, s * radius_ext);
- for (i = 1; i < subd; i++) {
+ immBegin(GWN_PRIM_TRI_STRIP, subd * 2);
+ for (i = 0; i < subd; i++) {
float a;
a = start + ((i) / (float)(subd - 1)) * angle;
@@ -4026,20 +4189,20 @@ static void draw_disk_shaded(
if (shaded) {
fac = (y1 + radius_ext) * radius_ext_scale;
round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ immAttrib4ubv(col, r_col);
}
- glVertex2f(c * radius_int, s * radius_int);
+ immVertex2f(pos, c * radius_int, s * radius_int);
if (shaded) {
fac = (y2 + radius_ext) * radius_ext_scale;
round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ immAttrib4ubv(col, r_col);
}
- glVertex2f(c * radius_ext, s * radius_ext);
+ immVertex2f(pos, c * radius_ext, s * radius_ext);
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
void ui_draw_pie_center(uiBlock *block)
@@ -4058,8 +4221,8 @@ void ui_draw_pie_center(uiBlock *block)
float angle = atan2f(pie_dir[1], pie_dir[0]);
float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_2 : M_PI_4;
- glPushMatrix();
- glTranslatef(cx, cy, 0.0f);
+ gpuPushMatrix();
+ gpuTranslate2f(cx, cy);
glEnable(GL_BLEND);
if (btheme->tui.wcol_pie_menu.shaded) {
@@ -4068,8 +4231,7 @@ void ui_draw_pie_center(uiBlock *block)
draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, col1, col2, true);
}
else {
- glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner);
- draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, NULL, NULL, false);
+ draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner, NULL, false);
}
if (!(block->pie_data.flags & UI_PIE_INVALID_DIR)) {
@@ -4079,25 +4241,34 @@ void ui_draw_pie_center(uiBlock *block)
draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, col1, col2, true);
}
else {
- glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner_sel);
- draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, NULL, NULL, false);
+ draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner_sel, NULL, false);
}
}
- glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.outline);
- glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_internal, subd);
- glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_external, subd);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((unsigned char *)btheme->tui.wcol_pie_menu.outline);
+
+ imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_internal, subd);
+ imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, pie_radius_external, subd);
+
+ immUnbindProgram();
if (U.pie_menu_confirm > 0 && !(block->pie_data.flags & (UI_PIE_INVALID_DIR | UI_PIE_CLICK_STYLE))) {
float pie_confirm_radius = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm);
float pie_confirm_external = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm + 7.0f);
- glColor4ub(btheme->tui.wcol_pie_menu.text_sel[0], btheme->tui.wcol_pie_menu.text_sel[1], btheme->tui.wcol_pie_menu.text_sel[2], 64);
- draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, NULL, NULL, false);
+ const char col[4] = {btheme->tui.wcol_pie_menu.text_sel[0],
+ btheme->tui.wcol_pie_menu.text_sel[1],
+ btheme->tui.wcol_pie_menu.text_sel[2],
+ 64};
+
+ draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, col, NULL, false);
}
glDisable(GL_BLEND);
- glPopMatrix();
+ gpuPopMatrix();
}
@@ -4181,8 +4352,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 */
@@ -4190,7 +4360,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;
}
}
@@ -4248,8 +4418,7 @@ 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 d12e7cc036b..2eae452debb 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -53,6 +53,8 @@
#include "BIF_gl.h"
+#include "BLF_api.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -665,6 +667,17 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_AXIS_Z:
cp = btheme->tui.zaxis; break;
+ case TH_MANIPULATOR_HI:
+ cp = btheme->tui.manipulator_hi; break;
+ case TH_MANIPULATOR_PRIMARY:
+ cp = btheme->tui.manipulator_primary; break;
+ case TH_MANIPULATOR_SECONDARY:
+ cp = btheme->tui.manipulator_secondary; break;
+ case TH_MANIPULATOR_A:
+ cp = btheme->tui.manipulator_a; break;
+ case TH_MANIPULATOR_B:
+ cp = btheme->tui.manipulator_b; break;
+
case TH_INFO_SELECTED:
cp = ts->info_selected;
break;
@@ -835,6 +848,15 @@ static void ui_theme_space_init_handles_color(ThemeSpace *theme_space)
rgba_char_args_set(theme_space->act_spline, 0xdb, 0x25, 0x12, 255);
}
+static void ui_theme_space_init_manipulator_colors(bTheme *btheme)
+{
+ rgba_char_args_set(btheme->tui.manipulator_hi, 255, 255, 255, 255);
+ rgba_char_args_set(btheme->tui.manipulator_primary, 222, 255, 13, 255);
+ rgba_char_args_set(btheme->tui.manipulator_secondary, 0, 255, 255, 255);
+ rgba_char_args_set(btheme->tui.manipulator_a, 23, 127, 23, 255);
+ rgba_char_args_set(btheme->tui.manipulator_b, 127, 23, 23, 255);
+}
+
/**
* initialize default theme
* \note: when you add new colors, created & saved themes need initialized
@@ -875,6 +897,9 @@ void ui_theme_init_default(void)
/* common (new) variables */
ui_theme_init_new(btheme);
+ /* Manipulator. */
+ ui_theme_space_init_manipulator_colors(btheme);
+
/* space view3d */
rgba_char_args_set_fl(btheme->tv3d.back, 0.225, 0.225, 0.225, 1.0);
rgba_char_args_set(btheme->tv3d.text, 0, 0, 0, 255);
@@ -1272,25 +1297,35 @@ void UI_ThemeColor4(int colorid)
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
glColor4ubv(cp);
-
}
/* set the color with offset for shades */
void UI_ThemeColorShade(int colorid, int offset)
{
- int r, g, b;
+ 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;
const unsigned char *cp;
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- r = offset + (int) cp[0];
+ r = coloffset + (int) cp[0];
CLAMP(r, 0, 255);
- g = offset + (int) cp[1];
+ g = coloffset + (int) cp[1];
CLAMP(g, 0, 255);
- b = offset + (int) cp[2];
+ b = coloffset + (int) cp[2];
CLAMP(b, 0, 255);
- glColor4ub(r, g, b, cp[3]);
+ a = alphaoffset + (int) cp[3];
+ CLAMP(a, 0, 255);
+
+ glColor4ub(r, g, b, a);
}
-void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
+
+void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4])
{
int r, g, b, a;
const unsigned char *cp;
@@ -1304,7 +1339,11 @@ void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
CLAMP(b, 0, 255);
a = alphaoffset + (int) cp[3];
CLAMP(a, 0, 255);
- glColor4ub(r, g, b, a);
+
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
+ col[3] = a;
}
void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3])
@@ -1320,6 +1359,19 @@ void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned c
col[2] = floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
}
+void UI_GetThemeColorBlend3f(int colorid1, int colorid2, float fac, float r_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);
+ r_col[0] = ((1.0f - fac) * cp1[0] + fac * cp2[0]) / 255.0f;
+ r_col[1] = ((1.0f - fac) * cp1[1] + fac * cp2[1]) / 255.0f;
+ r_col[2] = ((1.0f - fac) * cp1[2] + fac * cp2[2]) / 255.0f;
+}
+
/* blend between to theme colors, and set it */
void UI_ThemeColorBlend(int colorid1, int colorid2, float fac)
{
@@ -1372,6 +1424,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)
@@ -1470,6 +1528,111 @@ 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);
+
+ float blend[3];
+ blend[0] = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ blend[1] = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ blend[2] = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+
+ F3TOCHAR3(blend, col);
+}
+
+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;
+ const unsigned char *cp;
+
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+
+ r = coloffset + (int) cp[0];
+ CLAMP(r, 0, 255);
+ g = coloffset + (int) cp[1];
+ CLAMP(g, 0, 255);
+ b = coloffset + (int) cp[2];
+ CLAMP(b, 0, 255);
+ a = alphaoffset + (int) cp[3];
+ CLAMP(b, 0, 255);
+
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
+ col[3] = ((float)a) / 255.0f;
+}
+
+void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3])
+{
+ int r, g, b;
+ const unsigned char *cp1, *cp2;
+
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+
+ CLAMP(fac, 0.0f, 1.0f);
+
+ r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ CLAMP(r, 0, 255);
+ g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ CLAMP(g, 0, 255);
+ b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+ CLAMP(b, 0, 255);
+
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
+}
+
+void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4])
+{
+ int r, g, b, a;
+ const unsigned char *cp1, *cp2;
+
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+
+ CLAMP(fac, 0.0f, 1.0f);
+
+ r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ CLAMP(r, 0, 255);
+ g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ CLAMP(g, 0, 255);
+ b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+ CLAMP(b, 0, 255);
+ a = offset + floorf((1.0f - fac) * cp1[3] + fac * cp2[3]);
+ CLAMP(a, 0, 255);
+
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
+ col[3] = ((float)a) / 255.0f;
+}
+
/* get the color, in char pointer */
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
{
@@ -1658,11 +1821,9 @@ void init_userdef_do_versions(void)
U.savetime = 1;
// XXX error(STRINGIFY(BLENDER_STARTUP_FILE)" is buggy, please consider removing it.\n");
}
- /* transform widget settings */
- if (U.tw_hotspot == 0) {
- U.tw_hotspot = 14;
- U.tw_size = 25; /* percentage of window size */
- U.tw_handlesize = 16; /* percentage of widget radius */
+ if (U.manipulator_size == 0) {
+ U.manipulator_size = 75;
+ U.manipulator_flag |= USER_MANIPULATOR_DRAW;
}
if (U.pad_rot_angle == 0.0f)
U.pad_rot_angle = 15.0f;
@@ -2500,9 +2661,6 @@ void init_userdef_do_versions(void)
if (!USER_VERSION_ATLEAST(269, 9)) {
bTheme *btheme;
-
- U.tw_size = U.tw_size * 5.0f;
-
/* Action Editor (and NLA Editor) - Keyframe Colors */
/* Graph Editor - larger vertex size defaults */
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -2776,13 +2934,35 @@ void init_userdef_do_versions(void)
U.uiflag |= USER_LOCK_CURSOR_ADJUST;
}
+ if (!USER_VERSION_ATLEAST(280, 1)) {
+ /* interface_widgets.c */
+ struct uiWidgetColors wcol_tab = {
+ {255, 255, 255, 255},
+ {83, 83, 83, 255},
+ {114, 114, 114, 255},
+ {90, 90, 90, 255},
+
+ {0, 0, 0, 255},
+ {0, 0, 0, 255},
+
+ 0,
+ 0, 0
+ };
+
+ for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
+ btheme->tui.wcol_tab = wcol_tab;
+ }
+ }
+
/**
* Include next version bump.
*
* (keep this block even if it becomes empty).
*/
- {
-
+ if (((bTheme *)U.themes.first)->tui.manipulator_hi[3] == 0) {
+ for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
+ ui_theme_space_init_manipulator_colors(btheme);
+ }
}
if (U.pixelsize == 0.0f)
@@ -2791,11 +2971,8 @@ void init_userdef_do_versions(void)
if (U.image_draw_method == 0)
U.image_draw_method = IMAGE_DRAW_METHOD_2DTEXTURE;
- // keep the following until the new audaspace is default to be built with
-#ifdef WITH_SYSTEM_AUDASPACE
// we default to the first audio device
U.audiodevice = 0;
-#endif
/* funny name, but it is GE stuff, moves userdef stuff to engine */
// XXX space_set_commmandline_options();
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 38432395a17..a94ef0d1d5b 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -49,11 +49,11 @@
#include "BKE_screen.h"
#include "BKE_global.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
-#include "BIF_gl.h"
-
#include "BLF_api.h"
#include "ED_screen.h"
@@ -1100,9 +1100,6 @@ void UI_view2d_view_ortho(View2D *v2d)
/* set matrix on all appropriate axes */
wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax);
-
- /* XXX is this necessary? */
- glLoadIdentity();
}
/**
@@ -1130,9 +1127,6 @@ void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, const bool xaxis)
wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, ar->winy - yofs);
else
wmOrtho2(-xofs, ar->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs);
-
- /* XXX is this necessary? */
- glLoadIdentity();
}
@@ -1144,7 +1138,7 @@ void UI_view2d_view_restore(const bContext *C)
int height = BLI_rcti_size_y(&ar->winrct) + 1;
wmOrtho2(0.0f, (float)width, 0.0f, (float)height);
- glLoadIdentity();
+ gpuLoadIdentity();
// ED_region_pixelspace(CTX_wm_region(C));
}
@@ -1298,12 +1292,45 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
{
float vec1[2], vec2[2];
int a, step;
+ int vertical_minor_step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC),
+ horizontal_major_step = (BLI_rcti_size_y(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
+ unsigned char grid_line_color[3];
/* check for grid first, as it may not exist */
if (grid == NULL)
return;
- glBegin(GL_LINES);
+ /* Count the needed vertices for the gridlines */
+ unsigned vertex_count = 0;
+ if (flag & V2D_VERTICAL_LINES) {
+ /* vertical lines */
+ vertex_count += 2 * vertical_minor_step; /* minor gridlines */
+ vertex_count += 2 * (vertical_minor_step + 2); /* major gridlines */
+ }
+ if (flag & V2D_HORIZONTAL_LINES) {
+ /* horizontal lines */
+ vertex_count += 2 * (horizontal_major_step + 1); /* major gridlines */
+
+ /* fine lines */
+ if (flag & V2D_HORIZONTAL_FINELINES)
+ vertex_count += 2 * (horizontal_major_step + 1);
+ }
+ /* axes */
+ if (flag & V2D_HORIZONTAL_AXIS)
+ vertex_count += 2;
+ if (flag & V2D_VERTICAL_AXIS)
+ vertex_count += 2;
+
+ /* If there is nothing to render, exit early */
+ if (vertex_count == 0)
+ return;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINES, vertex_count);
/* vertical lines */
if (flag & V2D_VERTICAL_LINES) {
@@ -1313,24 +1340,31 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec2[1] = v2d->cur.ymax;
/* minor gridlines */
- step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
- UI_ThemeColor(TH_GRID);
-
- for (a = 0; a < step; a++) {
- glVertex2fv(vec1);
- glVertex2fv(vec2);
-
- vec2[0] = vec1[0] += grid->dx;
+ step = vertical_minor_step;
+ if (step != 0) {
+ UI_GetThemeColor3ubv(TH_GRID, grid_line_color);
+
+ for (a = 0; a < step; a++) {
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
+
+ vec2[0] = vec1[0] += grid->dx;
+ }
}
/* major gridlines */
vec2[0] = vec1[0] -= 0.5f * grid->dx;
- UI_ThemeColorShade(TH_GRID, 16);
+
+ UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color);
step++;
for (a = 0; a <= step; a++) {
- glVertex2fv(vec1);
- glVertex2fv(vec2);
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
vec2[0] = vec1[0] -= grid->dx;
}
@@ -1343,12 +1377,15 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec1[0] = grid->startx;
vec2[0] = v2d->cur.xmax;
- step = (BLI_rcti_size_y(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
-
- UI_ThemeColor(TH_GRID);
+ step = horizontal_major_step;
+
+ UI_GetThemeColor3ubv(TH_GRID, grid_line_color);
+
for (a = 0; a <= step; a++) {
- glVertex2fv(vec1);
- glVertex2fv(vec2);
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
vec2[1] = vec1[1] += grid->dy;
}
@@ -1358,10 +1395,12 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
step++;
if (flag & V2D_HORIZONTAL_FINELINES) {
- UI_ThemeColorShade(TH_GRID, 16);
+ UI_GetThemeColorShade3ubv(TH_GRID, 16, grid_line_color);
for (a = 0; a < step; a++) {
- glVertex2fv(vec1);
- glVertex2fv(vec2);
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
vec2[1] = vec1[1] -= grid->dy;
}
@@ -1369,7 +1408,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
}
/* Axes are drawn as darker lines */
- UI_ThemeColorShade(TH_GRID, -50);
+ UI_GetThemeColorShade3ubv(TH_GRID, -50, grid_line_color);
/* horizontal axis */
if (flag & V2D_HORIZONTAL_AXIS) {
@@ -1377,8 +1416,10 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec2[0] = v2d->cur.xmax;
vec1[1] = vec2[1] = 0.0f;
- glVertex2fv(vec1);
- glVertex2fv(vec2);
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
}
/* vertical axis */
@@ -1387,91 +1428,157 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec2[1] = v2d->cur.ymax;
vec1[0] = vec2[0] = 0.0f;
- glVertex2fv(vec1);
- glVertex2fv(vec2);
+ immSkipAttrib(color);
+ immVertex2fv(pos, vec1);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2fv(pos, vec2);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
/* Draw a constant grid in given 2d-region */
void UI_view2d_constant_grid_draw(View2D *v2d, float step)
{
- float start;
-
- UI_ThemeColorShade(TH_BACK, -10);
+ float start_x, start_y;
+ int count_x, count_y;
- start = v2d->cur.xmin - (float)fmod(v2d->cur.xmin, step);
+ start_x = v2d->cur.xmin;
+ if (start_x < 0.0)
+ start_x += -(float)fmod(v2d->cur.xmin, step);
+ else
+ start_x += (step - (float)fmod(v2d->cur.xmin, step));
+
+ if (start_x > v2d->cur.xmax)
+ count_x = 0;
+ else
+ count_x = (v2d->cur.xmax - start_x) / step + 1;
+
+ start_y = v2d->cur.ymin;
+ if (start_y < 0.0)
+ start_y += -(float)fmod(v2d->cur.ymin, step);
+ else
+ start_y += (step - (float)fabs(fmod(v2d->cur.ymin, step)));
+
+ if (start_y > v2d->cur.ymax)
+ count_y = 0;
+ else
+ count_y = (v2d->cur.ymax - start_y) / step + 1;
- glBegin(GL_LINES);
- for (; start < v2d->cur.xmax; start += step) {
- glVertex2f(start, v2d->cur.ymin);
- glVertex2f(start, v2d->cur.ymax);
- }
+ if (count_x > 0 || count_y > 0) {
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ float theme_color[3];
- start = v2d->cur.ymin - (float)fmod(v2d->cur.ymin, step);
- for (; start < v2d->cur.ymax; start += step) {
- glVertex2f(v2d->cur.xmin, start);
- glVertex2f(v2d->cur.xmax, start);
- }
+ UI_GetThemeColorShade3fv(TH_BACK, -10, theme_color);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINES, count_x * 2 + count_y * 2 + 4);
+
+ immAttrib3fv(color, theme_color);
+ for (int i = 0; i < count_x ; start_x += step, i++) {
+ immVertex2f(pos, start_x, v2d->cur.ymin);
+ immVertex2f(pos, start_x, v2d->cur.ymax);
+ }
+
+ for (int i = 0; i < count_y; start_y += step, i++) {
+ immVertex2f(pos, v2d->cur.xmin, start_y);
+ immVertex2f(pos, v2d->cur.xmax, start_y);
+ }
- /* X and Y axis */
- UI_ThemeColorShade(TH_BACK, -18);
- glVertex2f(0.0f, v2d->cur.ymin);
- glVertex2f(0.0f, v2d->cur.ymax);
- glVertex2f(v2d->cur.xmin, 0.0f);
- glVertex2f(v2d->cur.xmax, 0.0f);
+ /* X and Y axis */
+ UI_GetThemeColorShade3fv(TH_BACK, -18, theme_color);
+
+ immAttrib3fv(color, theme_color);
+ immVertex2f(pos, 0.0f, v2d->cur.ymin);
+ immVertex2f(pos, 0.0f, v2d->cur.ymax);
+ immVertex2f(pos, v2d->cur.xmin, 0.0f);
+ immVertex2f(pos, v2d->cur.xmax, 0.0f);
- glEnd();
+ immEnd();
+ immUnbindProgram();
+ }
}
/* Draw a multi-level grid in given 2d-region */
void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels)
{
+ /* Exit if there is nothing to draw */
+ if (totlevels == 0)
+ return;
+
int offset = -10;
float lstep = step;
- int level;
+ unsigned char grid_line_color[3];
+
+ /* Make an estimate of at least how many vertices will be needed */
+ unsigned vertex_count = 4;
+ vertex_count += 2 * ((int)((v2d->cur.xmax - v2d->cur.xmin) / lstep) + 1);
+ vertex_count += 2 * ((int)((v2d->cur.ymax - v2d->cur.ymin) / lstep) + 1);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
glLineWidth(1.0f);
- for (level = 0; level < totlevels; ++level) {
- int i;
- float start;
-
- UI_ThemeColorShade(colorid, offset);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBeginAtMost(GWN_PRIM_LINES, vertex_count);
+
+ for (int level = 0; level < totlevels; ++level) {
+ UI_GetThemeColorShade3ubv(colorid, offset, grid_line_color);
- i = (v2d->cur.xmin >= 0.0f ? -(int)(-v2d->cur.xmin / lstep) : (int)(v2d->cur.xmin / lstep));
- start = i * lstep;
+ int i = (int)(v2d->cur.xmin / lstep);
+ if (v2d->cur.xmin > 0.0f)
+ i++;
+ float start = i * lstep;
- glBegin(GL_LINES);
for (; start < v2d->cur.xmax; start += lstep, ++i) {
if (i == 0 || (level < totlevels - 1 && i % level_size == 0))
continue;
- glVertex2f(start, v2d->cur.ymin);
- glVertex2f(start, v2d->cur.ymax);
+
+ immSkipAttrib(color);
+ immVertex2f(pos, start, v2d->cur.ymin);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2f(pos, start, v2d->cur.ymax);
}
- i = (v2d->cur.ymin >= 0.0f ? -(int)(-v2d->cur.ymin / lstep) : (int)(v2d->cur.ymin / lstep));
+ i = (int)(v2d->cur.ymin / lstep);
+ if (v2d->cur.ymin > 0.0f)
+ i++;
start = i * lstep;
for (; start < v2d->cur.ymax; start += lstep, ++i) {
if (i == 0 || (level < totlevels - 1 && i % level_size == 0))
continue;
- glVertex2f(v2d->cur.xmin, start);
- glVertex2f(v2d->cur.xmax, start);
+
+ immSkipAttrib(color);
+ immVertex2f(pos, v2d->cur.xmin, start);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2f(pos, v2d->cur.xmax, start);
}
- /* X and Y axis */
- UI_ThemeColorShade(colorid, offset - 8);
- glVertex2f(0.0f, v2d->cur.ymin);
- glVertex2f(0.0f, v2d->cur.ymax);
- glVertex2f(v2d->cur.xmin, 0.0f);
- glVertex2f(v2d->cur.xmax, 0.0f);
-
- glEnd();
-
lstep *= level_size;
offset -= 6;
}
+
+ /* X and Y axis */
+ UI_GetThemeColorShade3ubv(colorid, -18 + ((totlevels - 1) * -6), grid_line_color);
+
+ immSkipAttrib(color);
+ immVertex2f(pos, 0.0f, v2d->cur.ymin);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2f(pos, 0.0f, v2d->cur.ymax);
+
+ immSkipAttrib(color);
+ immVertex2f(pos, v2d->cur.xmin, 0.0f);
+ immAttrib3ubv(color, grid_line_color);
+ immVertex2f(pos, v2d->cur.xmax, 0.0f);
+
+ immEnd();
+ immUnbindProgram();
}
/* the price we pay for not exposting structs :( */
@@ -1693,6 +1800,10 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
Scene *scene = CTX_data_scene(C);
rcti vert, hor;
int scroll = view2d_scroll_mapped(v2d->scroll);
+ unsigned char scrollers_back_color[4];
+
+ /* Color for scrollbar backs */
+ UI_GetThemeColor4ubv(TH_BACK, scrollers_back_color);
/* make copies of rects for less typing */
vert = vs->vert;
@@ -1704,7 +1815,6 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
uiWidgetColors wcol = btheme->tui.wcol_scroll;
rcti slider;
int state;
- unsigned char col[4];
slider.xmin = vs->hor_min;
slider.xmax = vs->hor_max;
@@ -1728,16 +1838,23 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
}
/* clean rect behind slider, but not with transparent background */
- UI_GetThemeColor4ubv(TH_BACK, col);
- if (col[3] == 255) {
- glColor3ub(col[0], col[1], col[2]);
- glRecti(v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax);
+ if (scrollers_back_color[3] == 255) {
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv(scrollers_back_color);
+ immRecti(pos, v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax);
+
+ immUnbindProgram();
}
UI_draw_widget_scroll(&wcol, &hor, &slider, state);
/* 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;
@@ -1752,7 +1869,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 */
@@ -1764,7 +1881,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);
@@ -1805,7 +1922,6 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
uiWidgetColors wcol = btheme->tui.wcol_scroll;
rcti slider;
int state;
- unsigned char col[4];
slider.xmin = vert.xmin;
slider.xmax = vert.xmax;
@@ -1829,10 +1945,16 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
}
/* clean rect behind slider, but not with transparent background */
- UI_GetThemeColor4ubv(TH_BACK, col);
- if (col[3] == 255) {
- glColor3ub(col[0], col[1], col[2]);
- glRecti(v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax);
+ if (scrollers_back_color[3] == 255) {
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv(scrollers_back_color);
+ immRecti(pos, v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax);
+
+ immUnbindProgram();
}
UI_draw_widget_scroll(&wcol, &vert, &slider, state);
@@ -1856,7 +1978,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 */
@@ -1865,9 +1988,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) {
@@ -1878,7 +2000,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);
}
}
}
@@ -2400,7 +2522,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);
@@ -2411,7 +2534,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;
}
@@ -2419,11 +2542,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;
@@ -2432,11 +2555,6 @@ void UI_view2d_text_cache_draw(ARegion *ar)
BLI_memarena_free(g_v2d_strings_arena);
g_v2d_strings_arena = NULL;
}
-
- // glMatrixMode(GL_PROJECTION);
- // glPopMatrix();
- // glMatrixMode(GL_MODELVIEW);
- // glPopMatrix();
}
diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt
index b3bbce939a5..4d3f106a5d6 100644
--- a/source/blender/editors/io/CMakeLists.txt
+++ b/source/blender/editors/io/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../depsgraph
../../makesdna
../../makesrna
../../windowmanager
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 39065606201..fc227a2aa75 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -56,6 +56,8 @@
#include "io_collada.h"
+#include "DEG_depsgraph.h"
+
static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
@@ -78,6 +80,7 @@ static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent *
/* function used for WM_OT_save_mainfile too */
static int wm_collada_export_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
char filepath[FILE_MAX];
int apply_modifiers;
int export_mesh_type;
@@ -87,7 +90,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int include_shapekeys;
int deform_bones_only;
- int export_texture_type;
+ int include_material_textures;
int use_texture_copies;
int active_uv_only;
@@ -103,6 +106,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int export_count;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
return OPERATOR_CANCELLED;
@@ -138,7 +143,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys");
deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only");
- export_texture_type = RNA_enum_get(op->ptr, "export_texture_type_selection");
+ include_material_textures = RNA_boolean_get(op->ptr, "include_material_textures");
use_texture_copies = RNA_boolean_get(op->ptr, "use_texture_copies");
active_uv_only = RNA_boolean_get(op->ptr, "active_uv_only");
@@ -156,7 +161,9 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
ED_object_editmode_load(CTX_data_edit_object(C));
- export_count = collada_export(CTX_data_scene(C),
+ export_count = collada_export(&eval_ctx,
+ CTX_data_scene(C),
+ CTX_data_view_layer(C),
filepath,
apply_modifiers,
export_mesh_type,
@@ -167,7 +174,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
deform_bones_only,
active_uv_only,
- export_texture_type,
+ include_material_textures,
use_texture_copies,
triangulate,
@@ -238,7 +245,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemR(row, imfptr, "active_uv_only", 0, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "export_texture_type_selection", 0, "", ICON_NONE);
+ uiItemR(row, imfptr, "include_material_textures", 0, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "use_texture_copies", 1, NULL, ICON_NONE);
@@ -315,15 +322,9 @@ void WM_OT_collada_export(wmOperatorType *ot)
};
static const EnumPropertyItem prop_bc_export_transformation_type[] = {
- { BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations" },
- { BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations" },
- { 0, NULL, 0, NULL, NULL }
- };
-
- static const EnumPropertyItem prop_bc_export_texture_type[] = {
- { BC_TEXTURE_TYPE_MAT, "mat", 0, "Materials", "Export Materials" },
- { BC_TEXTURE_TYPE_UV, "uv", 0, "UV Textures", "Export UV Textures (Face textures) as materials" },
- { 0, NULL, 0, NULL, NULL }
+ {BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations"},
+ {BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations"},
+ {0, NULL, 0, NULL, NULL}
};
ot->name = "Export COLLADA";
@@ -368,9 +369,13 @@ void WM_OT_collada_export(wmOperatorType *ot)
RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only",
"Only export deforming bones with armatures");
+
RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map",
"Export only the selected UV Map");
+ RNA_def_boolean(func, "include_material_textures", 0, "Include Material Textures",
+ "Export textures assigned to the object Materials");
+
RNA_def_boolean(func, "use_texture_copies", 1, "Copy",
"Copy textures to same folder where the .dae file is exported");
@@ -387,20 +392,11 @@ void WM_OT_collada_export(wmOperatorType *ot)
RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name",
"Sort exported data by Object name");
-
RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
- "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
+ "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
RNA_def_enum(func, "export_transformation_type_selection", prop_bc_export_transformation_type, 0,
- "Transform", "Transformation type for translation, scale and rotation");
-
-
- RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX,
- "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX);
-
- RNA_def_enum(func, "export_texture_type_selection", prop_bc_export_texture_type, 0,
- "Texture Type", "Type for exported Textures (UV or MAT)");
-
+ "Transform", "Transformation type for translation, scale and rotation");
RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim",
"Compatibility mode for SL, OpenSim and other compatible online worlds");
diff --git a/source/blender/editors/manipulator_library/CMakeLists.txt b/source/blender/editors/manipulator_library/CMakeLists.txt
new file mode 100644
index 00000000000..9f7df8c6425
--- /dev/null
+++ b/source/blender/editors/manipulator_library/CMakeLists.txt
@@ -0,0 +1,59 @@
+# ***** 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 *****
+
+set(INC
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../gpu
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/eigen
+ ../../../../intern/glew-mx
+)
+
+set(INC_SYS
+ ${GLEW_INCLUDE_PATH}
+)
+
+set(SRC
+ manipulator_draw_utils.c
+ manipulator_geometry.h
+ manipulator_library_intern.h
+ manipulator_library_presets.c
+ manipulator_library_utils.c
+ geometry/geom_arrow_manipulator.c
+ geometry/geom_cube_manipulator.c
+ geometry/geom_dial_manipulator.c
+ manipulator_types/arrow2d_manipulator.c
+ manipulator_types/arrow3d_manipulator.c
+ manipulator_types/cage2d_manipulator.c
+ manipulator_types/cage3d_manipulator.c
+ manipulator_types/dial3d_manipulator.c
+ manipulator_types/grab3d_manipulator.c
+ manipulator_types/primitive3d_manipulator.c
+)
+
+add_definitions(${GL_DEFINITIONS})
+
+blender_add_lib(bf_editor_manipulator_library "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/manipulator_library/geometry/geom_arrow_manipulator.c b/source/blender/editors/manipulator_library/geometry/geom_arrow_manipulator.c
new file mode 100644
index 00000000000..34f7d73589c
--- /dev/null
+++ b/source/blender/editors/manipulator_library/geometry/geom_arrow_manipulator.c
@@ -0,0 +1,141 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file geom_arrow_manipulator.c
+ * \ingroup wm
+ */
+
+#include "../manipulator_geometry.h"
+
+static float verts[][3] = {
+ {-0.000000, 0.012320, 0.000000},
+ {-0.000000, 0.012320, 0.974306},
+ {0.008711, 0.008711, 0.000000},
+ {0.008711, 0.008711, 0.974306},
+ {0.012320, -0.000000, 0.000000},
+ {0.012320, -0.000000, 0.974306},
+ {0.008711, -0.008711, 0.000000},
+ {0.008711, -0.008711, 0.974306},
+ {-0.000000, -0.012320, 0.000000},
+ {-0.000000, -0.012320, 0.974306},
+ {-0.008711, -0.008711, 0.000000},
+ {-0.008711, -0.008711, 0.974306},
+ {-0.012320, 0.000000, 0.000000},
+ {-0.012320, 0.000000, 0.974306},
+ {-0.008711, 0.008711, 0.000000},
+ {-0.008711, 0.008711, 0.974306},
+ {0.000000, 0.072555, 0.974306},
+ {0.051304, 0.051304, 0.974306},
+ {0.072555, -0.000000, 0.974306},
+ {0.051304, -0.051304, 0.974306},
+ {-0.000000, -0.072555, 0.974306},
+ {-0.051304, -0.051304, 0.974306},
+ {-0.072555, 0.000000, 0.974306},
+ {-0.051304, 0.051304, 0.974306},
+ {0.000000, -0.000000, 1.268098},
+};
+
+static float normals[][3] = {
+ {0.000000, 0.776360, -0.630238},
+ {0.000000, 0.594348, -0.804163},
+ {0.548967, 0.548967, -0.630238},
+ {0.420270, 0.420270, -0.804163},
+ {0.776360, 0.000000, -0.630238},
+ {0.594378, 0.000000, -0.804163},
+ {0.548967, -0.548967, -0.630238},
+ {0.420270, -0.420270, -0.804163},
+ {0.000000, -0.776360, -0.630238},
+ {0.000000, -0.594378, -0.804163},
+ {-0.548967, -0.548967, -0.630238},
+ {-0.420270, -0.420270, -0.804163},
+ {-0.776360, 0.000000, -0.630238},
+ {-0.594378, 0.000000, -0.804163},
+ {-0.548967, 0.548967, -0.630238},
+ {-0.420270, 0.420270, -0.804163},
+ {0.000000, 0.843226, -0.537492},
+ {0.596271, 0.596271, -0.537492},
+ {0.843226, 0.000000, -0.537492},
+ {0.596271, -0.596271, -0.537492},
+ {0.000000, -0.843226, -0.537492},
+ {-0.596271, -0.596271, -0.537492},
+ {-0.843226, 0.000000, -0.537492},
+ {-0.596271, 0.596271, -0.537492},
+ {0.000000, 0.000000, 1.000000},
+};
+
+static unsigned short indices[] = {
+ 1, 3, 2,
+ 3, 5, 4,
+ 5, 7, 6,
+ 7, 9, 8,
+ 9, 11, 10,
+ 11, 13, 12,
+ 5, 18, 19,
+ 15, 1, 0,
+ 13, 15, 14,
+ 6, 10, 14,
+ 11, 21, 22,
+ 7, 19, 20,
+ 13, 22, 23,
+ 3, 17, 18,
+ 9, 20, 21,
+ 15, 23, 16,
+ 1, 16, 17,
+ 23, 22, 24,
+ 21, 20, 24,
+ 19, 18, 24,
+ 17, 16, 24,
+ 16, 23, 24,
+ 22, 21, 24,
+ 20, 19, 24,
+ 18, 17, 24,
+ 0, 1, 2,
+ 2, 3, 4,
+ 4, 5, 6,
+ 6, 7, 8,
+ 8, 9, 10,
+ 10, 11, 12,
+ 7, 5, 19,
+ 14, 15, 0,
+ 12, 13, 14,
+ 14, 0, 2,
+ 2, 4, 6,
+ 6, 8, 10,
+ 10, 12, 14,
+ 14, 2, 6,
+ 13, 11, 22,
+ 9, 7, 20,
+ 15, 13, 23,
+ 5, 3, 18,
+ 11, 9, 21,
+ 1, 15, 16,
+ 3, 1, 17,
+};
+
+ManipulatorGeomInfo wm_manipulator_geom_data_arrow = {
+ .nverts = 25,
+ .ntris = 46,
+ .verts = verts,
+ .normals = normals,
+ .indices = indices,
+};
diff --git a/source/blender/editors/manipulator_library/geometry/geom_cube_manipulator.c b/source/blender/editors/manipulator_library/geometry/geom_cube_manipulator.c
new file mode 100644
index 00000000000..cee8e1e22ee
--- /dev/null
+++ b/source/blender/editors/manipulator_library/geometry/geom_cube_manipulator.c
@@ -0,0 +1,75 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file geom_cube_manipulator.c
+ * \ingroup wm
+ */
+
+#include "../manipulator_geometry.h"
+
+static const float verts[][3] = {
+ {1.000000, 1.000000, -1.000000},
+ {1.000000, -1.000000, -1.000000},
+ {-1.000000, -1.000000, -1.000000},
+ {-1.000000, 1.000000, -1.000000},
+ {1.000000, 1.000000, 1.000000},
+ {0.999999, -1.000001, 1.000000},
+ {-1.000000, -1.000000, 1.000000},
+ {-1.000000, 1.000000, 1.000000},
+};
+
+static const float normals[][3] = {
+ {0.577349, 0.577349, -0.577349},
+ {0.577349, -0.577349, -0.577349},
+ {-0.577349, -0.577349, -0.577349},
+ {-0.577349, 0.577349, -0.577349},
+ {0.577349, 0.577349, 0.577349},
+ {0.577349, -0.577349, 0.577349},
+ {-0.577349, -0.577349, 0.577349},
+ {-0.577349, 0.577349, 0.577349},
+};
+
+static const unsigned short indices[] = {
+ 1, 2, 3,
+ 7, 6, 5,
+ 4, 5, 1,
+ 5, 6, 2,
+ 2, 6, 7,
+ 0, 3, 7,
+ 0, 1, 3,
+ 4, 7, 5,
+ 0, 4, 1,
+ 1, 5, 2,
+ 3, 2, 7,
+ 4, 0, 7,
+};
+
+ManipulatorGeomInfo wm_manipulator_geom_data_cube = {
+ .nverts = 8,
+ .ntris = 12,
+ .verts = verts,
+ .normals = normals,
+ .indices = indices,
+};
diff --git a/source/blender/editors/manipulator_library/geometry/geom_dial_manipulator.c b/source/blender/editors/manipulator_library/geometry/geom_dial_manipulator.c
new file mode 100644
index 00000000000..811fc872a81
--- /dev/null
+++ b/source/blender/editors/manipulator_library/geometry/geom_dial_manipulator.c
@@ -0,0 +1,813 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file geom_dial_manipulator.c
+ * \ingroup wm
+ */
+
+#include "../manipulator_geometry.h"
+
+static const float verts[][3] = {
+ {1.034000, 0.000000, 0.000000},
+ {1.017000, 0.000000, 0.029445},
+ {0.983000, 0.000000, 0.029445},
+ {0.966000, 0.000000, 0.000000},
+ {0.983000, 0.000000, -0.029445},
+ {1.017000, 0.000000, -0.029445},
+ {1.014132, 0.201723, 0.000000},
+ {0.997459, 0.198407, 0.029445},
+ {0.964112, 0.191774, 0.029445},
+ {0.947439, 0.188457, 0.000000},
+ {0.964112, 0.191774, -0.029445},
+ {0.997459, 0.198407, -0.029445},
+ {0.955292, 0.395695, 0.000000},
+ {0.939586, 0.389189, 0.029445},
+ {0.908174, 0.376178, 0.029445},
+ {0.892468, 0.369672, 0.000000},
+ {0.908174, 0.376178, -0.029445},
+ {0.939586, 0.389189, -0.029445},
+ {0.859740, 0.574460, 0.000000},
+ {0.845605, 0.565015, 0.029445},
+ {0.817335, 0.546126, 0.029445},
+ {0.803200, 0.536681, 0.000000},
+ {0.817335, 0.546126, -0.029445},
+ {0.845605, 0.565015, -0.029445},
+ {0.731148, 0.731148, 0.000000},
+ {0.719128, 0.719128, 0.029445},
+ {0.695086, 0.695086, 0.029445},
+ {0.683065, 0.683065, 0.000000},
+ {0.695086, 0.695086, -0.029445},
+ {0.719128, 0.719128, -0.029445},
+ {0.574460, 0.859740, 0.000000},
+ {0.565015, 0.845605, 0.029445},
+ {0.546125, 0.817335, 0.029445},
+ {0.536681, 0.803200, 0.000000},
+ {0.546125, 0.817335, -0.029445},
+ {0.565015, 0.845605, -0.029445},
+ {0.395695, 0.955291, 0.000000},
+ {0.389189, 0.939585, 0.029445},
+ {0.376178, 0.908173, 0.029445},
+ {0.369672, 0.892467, 0.000000},
+ {0.376178, 0.908173, -0.029445},
+ {0.389189, 0.939585, -0.029445},
+ {0.201724, 1.014132, 0.000000},
+ {0.198407, 0.997459, 0.029445},
+ {0.191774, 0.964112, 0.029445},
+ {0.188457, 0.947439, 0.000000},
+ {0.191774, 0.964112, -0.029445},
+ {0.198407, 0.997459, -0.029445},
+ {0.000000, 1.034000, 0.000000},
+ {0.000000, 1.017000, 0.029445},
+ {0.000000, 0.983000, 0.029445},
+ {0.000000, 0.966000, 0.000000},
+ {0.000000, 0.983000, -0.029445},
+ {0.000000, 1.017000, -0.029445},
+ {-0.201723, 1.014132, 0.000000},
+ {-0.198407, 0.997459, 0.029445},
+ {-0.191774, 0.964112, 0.029445},
+ {-0.188457, 0.947439, 0.000000},
+ {-0.191774, 0.964112, -0.029445},
+ {-0.198407, 0.997459, -0.029445},
+ {-0.395695, 0.955291, 0.000000},
+ {-0.389189, 0.939585, 0.029445},
+ {-0.376178, 0.908174, 0.029445},
+ {-0.369672, 0.892468, 0.000000},
+ {-0.376178, 0.908174, -0.029445},
+ {-0.389189, 0.939585, -0.029445},
+ {-0.574459, 0.859740, 0.000000},
+ {-0.565015, 0.845605, 0.029445},
+ {-0.546125, 0.817335, 0.029445},
+ {-0.536681, 0.803200, 0.000000},
+ {-0.546125, 0.817335, -0.029445},
+ {-0.565015, 0.845605, -0.029445},
+ {-0.731149, 0.731148, 0.000000},
+ {-0.719128, 0.719127, 0.029445},
+ {-0.695086, 0.695086, 0.029445},
+ {-0.683065, 0.683065, 0.000000},
+ {-0.695086, 0.695086, -0.029445},
+ {-0.719128, 0.719127, -0.029445},
+ {-0.859740, 0.574460, 0.000000},
+ {-0.845604, 0.565015, 0.029445},
+ {-0.817335, 0.546126, 0.029445},
+ {-0.803200, 0.536681, 0.000000},
+ {-0.817335, 0.546126, -0.029445},
+ {-0.845604, 0.565015, -0.029445},
+ {-0.955291, 0.395695, 0.000000},
+ {-0.939585, 0.389189, 0.029445},
+ {-0.908173, 0.376178, 0.029445},
+ {-0.892468, 0.369672, 0.000000},
+ {-0.908173, 0.376178, -0.029445},
+ {-0.939585, 0.389189, -0.029445},
+ {-1.014132, 0.201723, 0.000000},
+ {-0.997459, 0.198407, 0.029445},
+ {-0.964112, 0.191774, 0.029445},
+ {-0.947439, 0.188457, 0.000000},
+ {-0.964112, 0.191774, -0.029445},
+ {-0.997459, 0.198407, -0.029445},
+ {-1.034000, 0.000000, 0.000000},
+ {-1.017000, 0.000000, 0.029445},
+ {-0.983000, 0.000000, 0.029445},
+ {-0.966000, 0.000000, 0.000000},
+ {-0.983000, 0.000000, -0.029445},
+ {-1.017000, 0.000000, -0.029445},
+ {-1.014132, -0.201723, 0.000000},
+ {-0.997459, -0.198407, 0.029445},
+ {-0.964112, -0.191774, 0.029445},
+ {-0.947439, -0.188457, 0.000000},
+ {-0.964112, -0.191774, -0.029445},
+ {-0.997459, -0.198407, -0.029445},
+ {-0.955292, -0.395694, 0.000000},
+ {-0.939586, -0.389189, 0.029445},
+ {-0.908174, -0.376177, 0.029445},
+ {-0.892468, -0.369672, 0.000000},
+ {-0.908174, -0.376177, -0.029445},
+ {-0.939586, -0.389189, -0.029445},
+ {-0.859740, -0.574460, 0.000000},
+ {-0.845604, -0.565015, 0.029445},
+ {-0.817335, -0.546126, 0.029445},
+ {-0.803200, -0.536681, 0.000000},
+ {-0.817335, -0.546126, -0.029445},
+ {-0.845604, -0.565015, -0.029445},
+ {-0.731149, -0.731148, 0.000000},
+ {-0.719128, -0.719127, 0.029445},
+ {-0.695086, -0.695086, 0.029445},
+ {-0.683065, -0.683065, 0.000000},
+ {-0.695086, -0.695086, -0.029445},
+ {-0.719128, -0.719127, -0.029445},
+ {-0.574460, -0.859739, 0.000000},
+ {-0.565015, -0.845604, 0.029445},
+ {-0.546126, -0.817334, 0.029445},
+ {-0.536681, -0.803199, 0.000000},
+ {-0.546126, -0.817334, -0.029445},
+ {-0.565015, -0.845604, -0.029445},
+ {-0.395695, -0.955291, 0.000000},
+ {-0.389189, -0.939585, 0.029445},
+ {-0.376178, -0.908174, 0.029445},
+ {-0.369672, -0.892468, 0.000000},
+ {-0.376178, -0.908174, -0.029445},
+ {-0.389189, -0.939585, -0.029445},
+ {-0.201724, -1.014132, 0.000000},
+ {-0.198407, -0.997459, 0.029445},
+ {-0.191774, -0.964112, 0.029445},
+ {-0.188458, -0.947438, 0.000000},
+ {-0.191774, -0.964112, -0.029445},
+ {-0.198407, -0.997459, -0.029445},
+ {0.000000, -1.034000, 0.000000},
+ {0.000000, -1.017000, 0.029445},
+ {0.000000, -0.983000, 0.029445},
+ {0.000000, -0.966000, 0.000000},
+ {0.000000, -0.983000, -0.029445},
+ {0.000000, -1.017000, -0.029445},
+ {0.201723, -1.014132, 0.000000},
+ {0.198407, -0.997459, 0.029445},
+ {0.191773, -0.964112, 0.029445},
+ {0.188457, -0.947439, 0.000000},
+ {0.191773, -0.964112, -0.029445},
+ {0.198407, -0.997459, -0.029445},
+ {0.395695, -0.955291, 0.000000},
+ {0.389189, -0.939585, 0.029445},
+ {0.376178, -0.908173, 0.029445},
+ {0.369672, -0.892467, 0.000000},
+ {0.376178, -0.908173, -0.029445},
+ {0.389189, -0.939585, -0.029445},
+ {0.574460, -0.859740, 0.000000},
+ {0.565015, -0.845605, 0.029445},
+ {0.546125, -0.817335, 0.029445},
+ {0.536681, -0.803200, 0.000000},
+ {0.546125, -0.817335, -0.029445},
+ {0.565015, -0.845605, -0.029445},
+ {0.731148, -0.731149, 0.000000},
+ {0.719127, -0.719128, 0.029445},
+ {0.695086, -0.695086, 0.029445},
+ {0.683065, -0.683066, 0.000000},
+ {0.695086, -0.695086, -0.029445},
+ {0.719127, -0.719128, -0.029445},
+ {0.859740, -0.574460, 0.000000},
+ {0.845605, -0.565015, 0.029445},
+ {0.817335, -0.546126, 0.029445},
+ {0.803200, -0.536681, 0.000000},
+ {0.817335, -0.546126, -0.029445},
+ {0.845605, -0.565015, -0.029445},
+ {0.955291, -0.395695, 0.000000},
+ {0.939585, -0.389189, 0.029445},
+ {0.908173, -0.376178, 0.029445},
+ {0.892467, -0.369673, 0.000000},
+ {0.908173, -0.376178, -0.029445},
+ {0.939585, -0.389189, -0.029445},
+ {1.014132, -0.201723, 0.000000},
+ {0.997459, -0.198407, 0.029445},
+ {0.964112, -0.191774, 0.029445},
+ {0.947439, -0.188457, 0.000000},
+ {0.964112, -0.191774, -0.029445},
+ {0.997459, -0.198407, -0.029445},
+};
+
+static const float normals[][3] = {
+ {1.000000, 0.000000, 0.000000},
+ {0.522691, 0.000000, 0.852504},
+ {-0.475845, 0.000000, 0.879513},
+ {-1.000000, 0.000000, 0.000000},
+ {-0.475845, 0.000000, -0.879513},
+ {0.522691, 0.000000, -0.852504},
+ {0.980773, 0.195074, 0.000000},
+ {0.512650, 0.101962, 0.852504},
+ {-0.466689, -0.092807, 0.879513},
+ {-0.980773, -0.195074, 0.000000},
+ {-0.466689, -0.092807, -0.879513},
+ {0.512650, 0.101962, -0.852504},
+ {0.923856, 0.382672, 0.000000},
+ {0.482894, 0.200018, 0.852504},
+ {-0.439619, -0.182073, 0.879513},
+ {-0.923856, -0.382672, 0.000000},
+ {-0.439619, -0.182073, -0.879513},
+ {0.482894, 0.200018, -0.852504},
+ {0.831446, 0.555559, 0.000000},
+ {0.434614, 0.290384, 0.852504},
+ {-0.395642, -0.264351, 0.879513},
+ {-0.831446, -0.555559, 0.000000},
+ {-0.395642, -0.264351, -0.879513},
+ {0.434614, 0.290384, -0.852504},
+ {0.707083, 0.707083, 0.000000},
+ {0.369610, 0.369610, 0.852504},
+ {-0.336467, -0.336467, 0.879513},
+ {-0.707083, -0.707083, 0.000000},
+ {-0.336467, -0.336467, -0.879513},
+ {0.369610, 0.369610, -0.852504},
+ {0.555559, 0.831446, 0.000000},
+ {0.290384, 0.434614, 0.852504},
+ {-0.264351, -0.395642, 0.879513},
+ {-0.555559, -0.831446, 0.000000},
+ {-0.264351, -0.395642, -0.879513},
+ {0.290384, 0.434614, -0.852504},
+ {0.382672, 0.923856, 0.000000},
+ {0.200018, 0.482894, 0.852504},
+ {-0.182073, -0.439619, 0.879513},
+ {-0.382672, -0.923856, 0.000000},
+ {-0.182073, -0.439619, -0.879513},
+ {0.200018, 0.482894, -0.852504},
+ {0.195074, 0.980773, 0.000000},
+ {0.101962, 0.512650, 0.852504},
+ {-0.092807, -0.466689, 0.879513},
+ {-0.195074, -0.980773, 0.000000},
+ {-0.092807, -0.466689, -0.879513},
+ {0.101962, 0.512650, -0.852504},
+ {0.000000, 1.000000, 0.000000},
+ {0.000000, 0.522691, 0.852504},
+ {0.000000, -0.475845, 0.879513},
+ {0.000000, -1.000000, 0.000000},
+ {0.000000, -0.475845, -0.879513},
+ {0.000000, 0.522691, -0.852504},
+ {-0.195074, 0.980773, 0.000000},
+ {-0.101962, 0.512650, 0.852504},
+ {0.092807, -0.466689, 0.879513},
+ {0.195074, -0.980773, 0.000000},
+ {0.092807, -0.466689, -0.879513},
+ {-0.101962, 0.512650, -0.852504},
+ {-0.382672, 0.923856, 0.000000},
+ {-0.200018, 0.482894, 0.852504},
+ {0.182073, -0.439619, 0.879513},
+ {0.382672, -0.923856, 0.000000},
+ {0.182073, -0.439619, -0.879513},
+ {-0.200018, 0.482894, -0.852504},
+ {-0.555559, 0.831446, 0.000000},
+ {-0.290384, 0.434614, 0.852504},
+ {0.264351, -0.395642, 0.879513},
+ {0.555559, -0.831446, 0.000000},
+ {0.264351, -0.395642, -0.879513},
+ {-0.290384, 0.434614, -0.852504},
+ {-0.707083, 0.707083, 0.000000},
+ {-0.369610, 0.369610, 0.852504},
+ {0.336467, -0.336467, 0.879513},
+ {0.707083, -0.707083, 0.000000},
+ {0.336467, -0.336467, -0.879513},
+ {-0.369610, 0.369610, -0.852504},
+ {-0.831446, 0.555559, 0.000000},
+ {-0.434614, 0.290384, 0.852504},
+ {0.395642, -0.264351, 0.879513},
+ {0.831446, -0.555559, 0.000000},
+ {0.395642, -0.264351, -0.879513},
+ {-0.434614, 0.290384, -0.852504},
+ {-0.923856, 0.382672, 0.000000},
+ {-0.482894, 0.200018, 0.852504},
+ {0.439619, -0.182073, 0.879513},
+ {0.923856, -0.382672, 0.000000},
+ {0.439619, -0.182073, -0.879513},
+ {-0.482894, 0.200018, -0.852504},
+ {-0.980773, 0.195074, 0.000000},
+ {-0.512650, 0.101962, 0.852504},
+ {0.466689, -0.092807, 0.879513},
+ {0.980773, -0.195074, 0.000000},
+ {0.466689, -0.092807, -0.879513},
+ {-0.512650, 0.101962, -0.852504},
+ {-1.000000, 0.000000, 0.000000},
+ {-0.522691, 0.000000, 0.852504},
+ {0.475845, 0.000000, 0.879513},
+ {1.000000, 0.000000, 0.000000},
+ {0.475845, 0.000000, -0.879513},
+ {-0.522691, 0.000000, -0.852504},
+ {-0.980773, -0.195074, 0.000000},
+ {-0.512650, -0.101962, 0.852504},
+ {0.466689, 0.092807, 0.879513},
+ {0.980773, 0.195074, 0.000000},
+ {0.466689, 0.092807, -0.879513},
+ {-0.512650, -0.101962, -0.852504},
+ {-0.923856, -0.382672, 0.000000},
+ {-0.482894, -0.200018, 0.852504},
+ {0.439619, 0.182073, 0.879513},
+ {0.923856, 0.382672, 0.000000},
+ {0.439619, 0.182073, -0.879513},
+ {-0.482894, -0.200018, -0.852504},
+ {-0.831446, -0.555559, 0.000000},
+ {-0.434614, -0.290384, 0.852504},
+ {0.395642, 0.264351, 0.879513},
+ {0.831446, 0.555559, 0.000000},
+ {0.395642, 0.264351, -0.879513},
+ {-0.434614, -0.290384, -0.852504},
+ {-0.707083, -0.707083, 0.000000},
+ {-0.369610, -0.369610, 0.852504},
+ {0.336467, 0.336467, 0.879513},
+ {0.707083, 0.707083, 0.000000},
+ {0.336467, 0.336467, -0.879513},
+ {-0.369610, -0.369610, -0.852504},
+ {-0.555559, -0.831446, 0.000000},
+ {-0.290384, -0.434614, 0.852504},
+ {0.264351, 0.395642, 0.879513},
+ {0.555559, 0.831446, 0.000000},
+ {0.264351, 0.395642, -0.879513},
+ {-0.290384, -0.434614, -0.852504},
+ {-0.382672, -0.923856, 0.000000},
+ {-0.200018, -0.482894, 0.852504},
+ {0.182073, 0.439619, 0.879513},
+ {0.382672, 0.923856, 0.000000},
+ {0.182073, 0.439619, -0.879513},
+ {-0.200018, -0.482894, -0.852504},
+ {-0.195074, -0.980773, 0.000000},
+ {-0.101962, -0.512650, 0.852504},
+ {0.092807, 0.466689, 0.879513},
+ {0.195074, 0.980773, 0.000000},
+ {0.092807, 0.466689, -0.879513},
+ {-0.101962, -0.512650, -0.852504},
+ {0.000000, -1.000000, 0.000000},
+ {0.000000, -0.522691, 0.852504},
+ {0.000000, 0.475845, 0.879513},
+ {0.000000, 1.000000, 0.000000},
+ {0.000000, 0.475845, -0.879513},
+ {0.000000, -0.522691, -0.852504},
+ {0.195074, -0.980773, 0.000000},
+ {0.101962, -0.512650, 0.852504},
+ {-0.092807, 0.466689, 0.879513},
+ {-0.195074, 0.980773, 0.000000},
+ {-0.092807, 0.466689, -0.879513},
+ {0.101962, -0.512650, -0.852504},
+ {0.382672, -0.923856, 0.000000},
+ {0.200018, -0.482894, 0.852504},
+ {-0.182073, 0.439619, 0.879513},
+ {-0.382672, 0.923856, 0.000000},
+ {-0.182073, 0.439619, -0.879513},
+ {0.200018, -0.482894, -0.852504},
+ {0.555559, -0.831446, 0.000000},
+ {0.290384, -0.434614, 0.852504},
+ {-0.264351, 0.395642, 0.879513},
+ {-0.555559, 0.831446, 0.000000},
+ {-0.264351, 0.395642, -0.879513},
+ {0.290384, -0.434614, -0.852504},
+ {0.707083, -0.707083, 0.000000},
+ {0.369610, -0.369610, 0.852504},
+ {-0.336467, 0.336467, 0.879513},
+ {-0.707083, 0.707083, 0.000000},
+ {-0.336467, 0.336467, -0.879513},
+ {0.369610, -0.369610, -0.852504},
+ {0.831446, -0.555559, 0.000000},
+ {0.434614, -0.290384, 0.852504},
+ {-0.395642, 0.264351, 0.879513},
+ {-0.831446, 0.555559, 0.000000},
+ {-0.395642, 0.264351, -0.879513},
+ {0.434614, -0.290384, -0.852504},
+ {0.923856, -0.382672, 0.000000},
+ {0.482894, -0.200018, 0.852504},
+ {-0.439619, 0.182073, 0.879513},
+ {-0.923856, 0.382672, 0.000000},
+ {-0.439619, 0.182073, -0.879513},
+ {0.482894, -0.200018, -0.852504},
+ {0.980773, -0.195074, 0.000000},
+ {0.512650, -0.101962, 0.852504},
+ {-0.466689, 0.092807, 0.879513},
+ {-0.980773, 0.195074, 0.000000},
+ {-0.466689, 0.092807, -0.879513},
+ {0.512650, -0.101962, -0.852504},
+};
+
+static const unsigned short indices[] = {
+ 6, 7, 1,
+ 7, 8, 2,
+ 8, 9, 3,
+ 9, 10, 4,
+ 10, 11, 5,
+ 5, 11, 6,
+ 12, 13, 7,
+ 13, 14, 8,
+ 14, 15, 9,
+ 15, 16, 10,
+ 16, 17, 11,
+ 11, 17, 12,
+ 18, 19, 13,
+ 13, 19, 20,
+ 20, 21, 15,
+ 15, 21, 22,
+ 22, 23, 17,
+ 17, 23, 18,
+ 24, 25, 19,
+ 19, 25, 26,
+ 26, 27, 21,
+ 21, 27, 28,
+ 28, 29, 23,
+ 23, 29, 24,
+ 30, 31, 25,
+ 25, 31, 32,
+ 26, 32, 33,
+ 27, 33, 34,
+ 34, 35, 29,
+ 29, 35, 30,
+ 36, 37, 31,
+ 31, 37, 38,
+ 38, 39, 33,
+ 39, 40, 34,
+ 40, 41, 35,
+ 35, 41, 36,
+ 36, 42, 43,
+ 43, 44, 38,
+ 44, 45, 39,
+ 45, 46, 40,
+ 46, 47, 41,
+ 47, 42, 36,
+ 48, 49, 43,
+ 49, 50, 44,
+ 50, 51, 45,
+ 51, 52, 46,
+ 52, 53, 47,
+ 47, 53, 48,
+ 54, 55, 49,
+ 49, 55, 56,
+ 50, 56, 57,
+ 57, 58, 52,
+ 58, 59, 53,
+ 53, 59, 54,
+ 60, 61, 55,
+ 55, 61, 62,
+ 56, 62, 63,
+ 63, 64, 58,
+ 64, 65, 59,
+ 59, 65, 60,
+ 66, 67, 61,
+ 61, 67, 68,
+ 68, 69, 63,
+ 69, 70, 64,
+ 70, 71, 65,
+ 71, 66, 60,
+ 72, 73, 67,
+ 73, 74, 68,
+ 68, 74, 75,
+ 75, 76, 70,
+ 76, 77, 71,
+ 71, 77, 72,
+ 78, 79, 73,
+ 79, 80, 74,
+ 74, 80, 81,
+ 81, 82, 76,
+ 82, 83, 77,
+ 83, 78, 72,
+ 78, 84, 85,
+ 85, 86, 80,
+ 80, 86, 87,
+ 87, 88, 82,
+ 82, 88, 89,
+ 89, 84, 78,
+ 90, 91, 85,
+ 91, 92, 86,
+ 86, 92, 93,
+ 93, 94, 88,
+ 88, 94, 95,
+ 95, 90, 84,
+ 96, 97, 91,
+ 97, 98, 92,
+ 98, 99, 93,
+ 99, 100, 94,
+ 100, 101, 95,
+ 101, 96, 90,
+ 102, 103, 97,
+ 103, 104, 98,
+ 104, 105, 99,
+ 99, 105, 106,
+ 106, 107, 101,
+ 101, 107, 102,
+ 108, 109, 103,
+ 103, 109, 110,
+ 110, 111, 105,
+ 105, 111, 112,
+ 112, 113, 107,
+ 107, 113, 108,
+ 114, 115, 109,
+ 115, 116, 110,
+ 116, 117, 111,
+ 111, 117, 118,
+ 112, 118, 119,
+ 113, 119, 114,
+ 114, 120, 121,
+ 121, 122, 116,
+ 122, 123, 117,
+ 117, 123, 124,
+ 124, 125, 119,
+ 125, 120, 114,
+ 126, 127, 121,
+ 121, 127, 128,
+ 128, 129, 123,
+ 123, 129, 130,
+ 130, 131, 125,
+ 125, 131, 126,
+ 132, 133, 127,
+ 133, 134, 128,
+ 128, 134, 135,
+ 135, 136, 130,
+ 136, 137, 131,
+ 131, 137, 132,
+ 132, 138, 139,
+ 133, 139, 140,
+ 134, 140, 141,
+ 141, 142, 136,
+ 142, 143, 137,
+ 143, 138, 132,
+ 138, 144, 145,
+ 139, 145, 146,
+ 146, 147, 141,
+ 141, 147, 148,
+ 148, 149, 143,
+ 149, 144, 138,
+ 144, 150, 151,
+ 151, 152, 146,
+ 146, 152, 153,
+ 153, 154, 148,
+ 154, 155, 149,
+ 155, 150, 144,
+ 156, 157, 151,
+ 151, 157, 158,
+ 158, 159, 153,
+ 159, 160, 154,
+ 160, 161, 155,
+ 155, 161, 156,
+ 156, 162, 163,
+ 163, 164, 158,
+ 158, 164, 165,
+ 165, 166, 160,
+ 160, 166, 167,
+ 167, 162, 156,
+ 162, 168, 169,
+ 169, 170, 164,
+ 164, 170, 171,
+ 165, 171, 172,
+ 166, 172, 173,
+ 173, 168, 162,
+ 174, 175, 169,
+ 175, 176, 170,
+ 170, 176, 177,
+ 177, 178, 172,
+ 172, 178, 179,
+ 173, 179, 174,
+ 174, 180, 181,
+ 181, 182, 176,
+ 176, 182, 183,
+ 183, 184, 178,
+ 178, 184, 185,
+ 179, 185, 180,
+ 186, 187, 181,
+ 187, 188, 182,
+ 188, 189, 183,
+ 183, 189, 190,
+ 190, 191, 185,
+ 191, 186, 180,
+ 0, 1, 187,
+ 1, 2, 188,
+ 2, 3, 189,
+ 3, 4, 190,
+ 190, 4, 5,
+ 191, 5, 0,
+ 0, 6, 1,
+ 1, 7, 2,
+ 2, 8, 3,
+ 3, 9, 4,
+ 4, 10, 5,
+ 0, 5, 6,
+ 6, 12, 7,
+ 7, 13, 8,
+ 8, 14, 9,
+ 9, 15, 10,
+ 10, 16, 11,
+ 6, 11, 12,
+ 12, 18, 13,
+ 14, 13, 20,
+ 14, 20, 15,
+ 16, 15, 22,
+ 16, 22, 17,
+ 12, 17, 18,
+ 18, 24, 19,
+ 20, 19, 26,
+ 20, 26, 21,
+ 22, 21, 28,
+ 22, 28, 23,
+ 18, 23, 24,
+ 24, 30, 25,
+ 26, 25, 32,
+ 27, 26, 33,
+ 28, 27, 34,
+ 28, 34, 29,
+ 24, 29, 30,
+ 30, 36, 31,
+ 32, 31, 38,
+ 32, 38, 33,
+ 33, 39, 34,
+ 34, 40, 35,
+ 30, 35, 36,
+ 37, 36, 43,
+ 37, 43, 38,
+ 38, 44, 39,
+ 39, 45, 40,
+ 40, 46, 41,
+ 41, 47, 36,
+ 42, 48, 43,
+ 43, 49, 44,
+ 44, 50, 45,
+ 45, 51, 46,
+ 46, 52, 47,
+ 42, 47, 48,
+ 48, 54, 49,
+ 50, 49, 56,
+ 51, 50, 57,
+ 51, 57, 52,
+ 52, 58, 53,
+ 48, 53, 54,
+ 54, 60, 55,
+ 56, 55, 62,
+ 57, 56, 63,
+ 57, 63, 58,
+ 58, 64, 59,
+ 54, 59, 60,
+ 60, 66, 61,
+ 62, 61, 68,
+ 62, 68, 63,
+ 63, 69, 64,
+ 64, 70, 65,
+ 65, 71, 60,
+ 66, 72, 67,
+ 67, 73, 68,
+ 69, 68, 75,
+ 69, 75, 70,
+ 70, 76, 71,
+ 66, 71, 72,
+ 72, 78, 73,
+ 73, 79, 74,
+ 75, 74, 81,
+ 75, 81, 76,
+ 76, 82, 77,
+ 77, 83, 72,
+ 79, 78, 85,
+ 79, 85, 80,
+ 81, 80, 87,
+ 81, 87, 82,
+ 83, 82, 89,
+ 83, 89, 78,
+ 84, 90, 85,
+ 85, 91, 86,
+ 87, 86, 93,
+ 87, 93, 88,
+ 89, 88, 95,
+ 89, 95, 84,
+ 90, 96, 91,
+ 91, 97, 92,
+ 92, 98, 93,
+ 93, 99, 94,
+ 94, 100, 95,
+ 95, 101, 90,
+ 96, 102, 97,
+ 97, 103, 98,
+ 98, 104, 99,
+ 100, 99, 106,
+ 100, 106, 101,
+ 96, 101, 102,
+ 102, 108, 103,
+ 104, 103, 110,
+ 104, 110, 105,
+ 106, 105, 112,
+ 106, 112, 107,
+ 102, 107, 108,
+ 108, 114, 109,
+ 109, 115, 110,
+ 110, 116, 111,
+ 112, 111, 118,
+ 113, 112, 119,
+ 108, 113, 114,
+ 115, 114, 121,
+ 115, 121, 116,
+ 116, 122, 117,
+ 118, 117, 124,
+ 118, 124, 119,
+ 119, 125, 114,
+ 120, 126, 121,
+ 122, 121, 128,
+ 122, 128, 123,
+ 124, 123, 130,
+ 124, 130, 125,
+ 120, 125, 126,
+ 126, 132, 127,
+ 127, 133, 128,
+ 129, 128, 135,
+ 129, 135, 130,
+ 130, 136, 131,
+ 126, 131, 132,
+ 133, 132, 139,
+ 134, 133, 140,
+ 135, 134, 141,
+ 135, 141, 136,
+ 136, 142, 137,
+ 137, 143, 132,
+ 139, 138, 145,
+ 140, 139, 146,
+ 140, 146, 141,
+ 142, 141, 148,
+ 142, 148, 143,
+ 143, 149, 138,
+ 145, 144, 151,
+ 145, 151, 146,
+ 147, 146, 153,
+ 147, 153, 148,
+ 148, 154, 149,
+ 149, 155, 144,
+ 150, 156, 151,
+ 152, 151, 158,
+ 152, 158, 153,
+ 153, 159, 154,
+ 154, 160, 155,
+ 150, 155, 156,
+ 157, 156, 163,
+ 157, 163, 158,
+ 159, 158, 165,
+ 159, 165, 160,
+ 161, 160, 167,
+ 161, 167, 156,
+ 163, 162, 169,
+ 163, 169, 164,
+ 165, 164, 171,
+ 166, 165, 172,
+ 167, 166, 173,
+ 167, 173, 162,
+ 168, 174, 169,
+ 169, 175, 170,
+ 171, 170, 177,
+ 171, 177, 172,
+ 173, 172, 179,
+ 168, 173, 174,
+ 175, 174, 181,
+ 175, 181, 176,
+ 177, 176, 183,
+ 177, 183, 178,
+ 179, 178, 185,
+ 174, 179, 180,
+ 180, 186, 181,
+ 181, 187, 182,
+ 182, 188, 183,
+ 184, 183, 190,
+ 184, 190, 185,
+ 185, 191, 180,
+ 186, 0, 187,
+ 187, 1, 188,
+ 188, 2, 189,
+ 189, 3, 190,
+ 191, 190, 5,
+ 186, 191, 0,
+};
+
+ManipulatorGeomInfo wm_manipulator_geom_data_dial = {
+ .nverts = 192,
+ .ntris = 384,
+ .verts = verts,
+ .normals = normals,
+ .indices = indices,
+};
diff --git a/source/blender/editors/manipulator_library/manipulator_draw_utils.c b/source/blender/editors/manipulator_library/manipulator_draw_utils.c
new file mode 100644
index 00000000000..430841311aa
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_draw_utils.c
@@ -0,0 +1,131 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file manipulator_draw_utils.c
+ * \ingroup wm
+ */
+
+#include "BLI_listbase.h"
+#include "BLI_ghash.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
+
+#include "BKE_context.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "GPU_batch.h"
+#include "GPU_glew.h"
+#include "GPU_immediate.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* only for own init/exit calls (wm_manipulatortype_init/wm_manipulatortype_free) */
+#include "wm.h"
+
+/* own includes */
+#include "manipulator_library_intern.h"
+
+/**
+ * Main draw call for ManipulatorGeomInfo data
+ */
+void wm_manipulator_geometryinfo_draw(const ManipulatorGeomInfo *info, const bool select, const float color[4])
+{
+ /* TODO store the Batches inside the ManipulatorGeomInfo and updated it when geom changes
+ * So we don't need to re-created and discard it every time */
+
+ const bool use_lighting = true || (!select && ((U.manipulator_flag & USER_MANIPULATOR_SHADED) != 0));
+ Gwn_VertBuf *vbo;
+ Gwn_IndexBuf *el;
+ Gwn_Batch *batch;
+ Gwn_IndexBufBuilder elb = {0};
+
+ Gwn_VertFormat format = {0};
+ uint pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ uint nor_id;
+
+ if (use_lighting) {
+ nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ }
+
+ /* Elements */
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, info->ntris, info->nverts);
+ for (int i = 0; i < info->ntris; ++i) {
+ const unsigned short *idx = &info->indices[i * 3];
+ GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
+ }
+ el = GWN_indexbuf_build(&elb);
+
+ vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, info->nverts);
+
+ GWN_vertbuf_attr_fill(vbo, pos_id, info->verts);
+
+ if (use_lighting) {
+ /* Normals are expected to be smooth. */
+ GWN_vertbuf_attr_fill(vbo, nor_id, info->normals);
+ }
+
+ batch = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, el, GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+
+ GWN_batch_uniform_4fv(batch, "color", color);
+
+ /* We may want to re-visit this, for now disable
+ * since it causes issues leaving the GL state modified. */
+#if 0
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+#endif
+
+ GWN_batch_draw(batch);
+
+#if 0
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+#endif
+
+
+ GWN_batch_discard(batch);
+}
+
+void wm_manipulator_vec_draw(
+ const float color[4], const float (*verts)[3], uint vert_count,
+ uint pos, uint primitive_type)
+{
+ immUniformColor4fv(color);
+ immBegin(primitive_type, vert_count);
+ for (int i = 0; i < vert_count; i++) {
+ immVertex3fv(pos, verts[i]);
+ }
+ immEnd();
+}
diff --git a/source/blender/editors/manipulator_library/manipulator_geometry.h b/source/blender/editors/manipulator_library/manipulator_geometry.h
new file mode 100644
index 00000000000..2083f9d4d31
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_geometry.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.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file manipulator_geometry.h
+ * \ingroup wm
+ *
+ * \name Manipulator Geometry
+ *
+ * \brief Prototypes for arrays defining the manipulator geometry. The actual definitions can be found in files usually
+ * called geom_xxx_manipulator.c
+ */
+
+
+#ifndef __MANIPULATOR_GEOMETRY_H__
+#define __MANIPULATOR_GEOMETRY_H__
+
+typedef struct ManipulatorGeomInfo {
+ int nverts;
+ int ntris;
+ const float (*verts)[3];
+ const float (*normals)[3];
+ const unsigned short *indices;
+} ManipulatorGeomInfo;
+
+/* arrow manipulator */
+extern ManipulatorGeomInfo wm_manipulator_geom_data_arrow;
+
+/* cube manipulator */
+extern ManipulatorGeomInfo wm_manipulator_geom_data_cube;
+
+/* dial manipulator */
+extern ManipulatorGeomInfo wm_manipulator_geom_data_dial;
+
+#endif /* __MANIPULATOR_GEOMETRY_H__ */
diff --git a/source/blender/editors/manipulator_library/manipulator_library_intern.h b/source/blender/editors/manipulator_library/manipulator_library_intern.h
new file mode 100644
index 00000000000..92ca195f21d
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_library_intern.h
@@ -0,0 +1,108 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file manipulator_library_intern.h
+ * \ingroup wm
+ */
+
+#ifndef __MANIPULATOR_LIBRARY_INTERN_H__
+#define __MANIPULATOR_LIBRARY_INTERN_H__
+
+/* distance around which manipulators respond to input (and get highlighted) */
+#define MANIPULATOR_HOTSPOT 14.0f
+
+/**
+ * Data for common interactions. Used in manipulator_library_utils.c functions.
+ */
+typedef struct ManipulatorCommonData {
+ int flag;
+
+ float range_fac; /* factor for arrow min/max distance */
+ float offset;
+
+ /* property range for constrained manipulators */
+ float range;
+ /* min/max value for constrained manipulators */
+ float min, max;
+} ManipulatorCommonData;
+
+typedef struct ManipulatorInteraction {
+ float init_value; /* initial property value */
+ float init_mval[2];
+ float init_offset;
+ float init_matrix_final[4][4];
+ float init_matrix_basis[4][4];
+
+ /* offset of last handling step */
+ float prev_offset;
+ /* Total offset added by precision tweaking.
+ * Needed to allow toggling precision on/off without causing jumps */
+ float precision_offset;
+} ManipulatorInteraction;
+
+/* ManipulatorCommonData->flag */
+enum {
+ MANIPULATOR_CUSTOM_RANGE_SET = (1 << 0),
+};
+
+
+float manipulator_offset_from_value(
+ ManipulatorCommonData *data, const float value,
+ const bool constrained, const bool inverted);
+float manipulator_value_from_offset(
+ ManipulatorCommonData *data, ManipulatorInteraction *inter, const float offset,
+ const bool constrained, const bool inverted, const bool use_precision);
+
+void manipulator_property_data_update(
+ struct wmManipulator *mpr, ManipulatorCommonData *data, wmManipulatorProperty *mpr_prop,
+ const bool constrained, const bool inverted);
+
+void manipulator_property_value_reset(
+ bContext *C, const struct wmManipulator *mpr, ManipulatorInteraction *inter, wmManipulatorProperty *mpr_prop);
+
+
+/* -------------------------------------------------------------------- */
+
+void manipulator_color_get(
+ const struct wmManipulator *mpr, const bool highlight,
+ float r_color[4]);
+
+bool manipulator_window_project_2d(
+ bContext *C, const struct wmManipulator *mpr, const float mval[2], int axis, bool use_offset,
+ float r_co[2]);
+
+/* -------------------------------------------------------------------- */
+/* Manipulator drawing */
+
+#include "manipulator_geometry.h"
+
+void wm_manipulator_geometryinfo_draw(const struct ManipulatorGeomInfo *info, const bool select, const float color[4]);
+void wm_manipulator_vec_draw(
+ const float color[4], const float (*verts)[3], uint vert_count,
+ uint pos, uint primitive_type);
+
+
+#endif /* __MANIPULATOR_LIBRARY_INTERN_H__ */
+
diff --git a/source/blender/editors/manipulator_library/manipulator_library_presets.c b/source/blender/editors/manipulator_library/manipulator_library_presets.c
new file mode 100644
index 00000000000..7b8d2104992
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_library_presets.c
@@ -0,0 +1,154 @@
+/*
+ * ***** 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/manipulator_library/manipulator_library_presets.c
+ * \ingroup wm
+ *
+ * \name Manipulator Lib Presets
+ *
+ * \brief Preset shapes that can be drawn from any manipulator type.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "DNA_view3d_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_context.h"
+
+#include "BIF_gl.h"
+
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_select.h"
+
+#include "DEG_depsgraph.h"
+
+#include "RNA_access.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "ED_view3d.h"
+#include "ED_screen.h"
+
+/* own includes */
+#include "ED_manipulator_library.h" /* own include */
+#include "manipulator_library_intern.h" /* own include */
+
+/* TODO, this is to be used by RNA. might move to ED_manipulator_library */
+
+/**
+ * Given a single axis, orient the matrix to a different direction.
+ */
+static void single_axis_convert(
+ int src_axis, float src_mat[4][4],
+ int dst_axis, float dst_mat[4][4])
+{
+ copy_m4_m4(dst_mat, src_mat);
+ if (src_axis == dst_axis) {
+ return;
+ }
+
+ float rotmat[3][3];
+ mat3_from_axis_conversion_single(src_axis, dst_axis, rotmat);
+ transpose_m3(rotmat);
+ mul_m4_m4m3(dst_mat, src_mat, rotmat);
+}
+
+/**
+ * Use for all geometry.
+ */
+static void ed_manipulator_draw_preset_geometry(
+ const struct wmManipulator *mpr, float mat[4][4], int select_id,
+ const ManipulatorGeomInfo *info)
+{
+ const bool is_select = (select_id != -1);
+ const bool is_highlight = is_select && (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
+
+ float color[4];
+ manipulator_color_get(mpr, is_highlight, color);
+
+ if (is_select) {
+ GPU_select_load_id(select_id);
+ }
+
+ gpuPushMatrix();
+ gpuMultMatrix(mat);
+ wm_manipulator_geometryinfo_draw(info, is_select, color);
+ gpuPopMatrix();
+
+ if (is_select) {
+ GPU_select_load_id(-1);
+ }
+}
+
+void ED_manipulator_draw_preset_box(
+ const struct wmManipulator *mpr, float mat[4][4], int select_id)
+{
+ ed_manipulator_draw_preset_geometry(mpr, mat, select_id, &wm_manipulator_geom_data_cube);
+}
+
+void ED_manipulator_draw_preset_arrow(
+ const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id)
+{
+ float mat_rotate[4][4];
+ single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
+ ed_manipulator_draw_preset_geometry(mpr, mat_rotate, select_id, &wm_manipulator_geom_data_arrow);
+}
+
+void ED_manipulator_draw_preset_circle(
+ const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id)
+{
+ float mat_rotate[4][4];
+ single_axis_convert(OB_POSZ, mat, axis, mat_rotate);
+ ed_manipulator_draw_preset_geometry(mpr, mat_rotate, select_id, &wm_manipulator_geom_data_dial);
+}
+
+void ED_manipulator_draw_preset_facemap(
+ const bContext *C, const struct wmManipulator *mpr, struct Scene *scene, Object *ob, const int facemap, int select_id)
+{
+ const bool is_select = (select_id != -1);
+ const bool is_highlight = is_select && (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
+
+ float color[4];
+ manipulator_color_get(mpr, is_highlight, color);
+
+ if (is_select) {
+ GPU_select_load_id(select_id);
+ }
+
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ gpuPushMatrix();
+ gpuMultMatrix(ob->obmat);
+ ED_draw_object_facemap(&eval_ctx, scene, ob, color, facemap);
+ gpuPopMatrix();
+
+ if (is_select) {
+ GPU_select_load_id(-1);
+ }
+}
+
diff --git a/source/blender/editors/manipulator_library/manipulator_library_utils.c b/source/blender/editors/manipulator_library/manipulator_library_utils.c
new file mode 100644
index 00000000000..38b518b1992
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_library_utils.c
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file manipulator_library_utils.c
+ * \ingroup wm
+ *
+ * \name Manipulator Library Utilities
+ *
+ * \brief This file contains functions for common behaviors of manipulators.
+ */
+
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+
+#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_context.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_view3d.h"
+
+/* own includes */
+#include "manipulator_library_intern.h"
+
+/* factor for precision tweaking */
+#define MANIPULATOR_PRECISION_FAC 0.05f
+
+
+BLI_INLINE float manipulator_offset_from_value_constr(
+ const float range_fac, const float min, const float range, const float value,
+ const bool inverted)
+{
+ return inverted ? (range_fac * (min + range - value) / range) : (range_fac * (value / range));
+}
+
+BLI_INLINE float manipulator_value_from_offset_constr(
+ const float range_fac, const float min, const float range, const float value,
+ const bool inverted)
+{
+ return inverted ? (min + range - (value * range / range_fac)) : (value * range / range_fac);
+}
+
+float manipulator_offset_from_value(
+ ManipulatorCommonData *data, const float value, const bool constrained, const bool inverted)
+{
+ if (constrained)
+ return manipulator_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
+
+ return value;
+}
+
+float manipulator_value_from_offset(
+ ManipulatorCommonData *data, ManipulatorInteraction *inter, const float offset,
+ const bool constrained, const bool inverted, const bool use_precision)
+{
+ const float max = data->min + data->range;
+
+ if (use_precision) {
+ /* add delta offset of this step to total precision_offset */
+ inter->precision_offset += offset - inter->prev_offset;
+ }
+ inter->prev_offset = offset;
+
+ float ofs_new = inter->init_offset + offset - inter->precision_offset * (1.0f - MANIPULATOR_PRECISION_FAC);
+ float value;
+
+ if (constrained) {
+ value = manipulator_value_from_offset_constr(data->range_fac, data->min, data->range, ofs_new, inverted);
+ }
+ else {
+ value = ofs_new;
+ }
+
+ /* clamp to custom range */
+ if (data->flag & MANIPULATOR_CUSTOM_RANGE_SET) {
+ CLAMP(value, data->min, max);
+ }
+
+ return value;
+}
+
+void manipulator_property_data_update(
+ wmManipulator *mpr, ManipulatorCommonData *data, wmManipulatorProperty *mpr_prop,
+ const bool constrained, const bool inverted)
+{
+ if (mpr_prop->custom_func.value_get_fn != NULL) {
+ /* pass */
+ }
+ else if (mpr_prop->prop != NULL) {
+ /* pass */
+ }
+ else {
+ data->offset = 0.0f;
+ return;
+ }
+
+ float value = WM_manipulator_target_property_value_get(mpr, mpr_prop);
+
+ if (constrained) {
+ if ((data->flag & MANIPULATOR_CUSTOM_RANGE_SET) == 0) {
+ float range[2];
+ if (WM_manipulator_target_property_range_get(mpr, mpr_prop, range)) {
+ data->range = range[1] - range[0];
+ data->min = range[0];
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ data->offset = manipulator_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
+ }
+ else {
+ data->offset = value;
+ }
+}
+
+void manipulator_property_value_reset(
+ bContext *C, const wmManipulator *mpr, ManipulatorInteraction *inter,
+ wmManipulatorProperty *mpr_prop)
+{
+ WM_manipulator_target_property_value_set(C, mpr, mpr_prop, inter->init_value);
+}
+
+/* -------------------------------------------------------------------- */
+
+void manipulator_color_get(
+ const wmManipulator *mpr, const bool highlight,
+ float r_col[4])
+{
+ if (highlight && !(mpr->flag & WM_MANIPULATOR_DRAW_HOVER)) {
+ copy_v4_v4(r_col, mpr->color_hi);
+ }
+ else {
+ copy_v4_v4(r_col, mpr->color);
+ }
+}
+
+/* -------------------------------------------------------------------- */
+
+/**
+ * Takes mouse coordinates and returns them in relation to the manipulator.
+ * Both 2D & 3D supported, use so we can use 2D manipulators in the 3D view.
+ */
+bool manipulator_window_project_2d(
+ bContext *C, const struct wmManipulator *mpr, const float mval[2], int axis, bool use_offset,
+ float r_co[2])
+{
+ float mat[4][4];
+ {
+ float mat_identity[4][4];
+ struct WM_ManipulatorMatrixParams params = {NULL};
+ if (use_offset == false) {
+ unit_m4(mat_identity);
+ params.matrix_offset = mat_identity;
+ }
+ WM_manipulator_calc_matrix_final_params(mpr, &params, mat);
+ }
+
+ /* rotate mouse in relation to the center and relocate it */
+ if (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) {
+ /* For 3d views, transform 2D mouse pos onto plane. */
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ float plane[4];
+
+ plane_from_point_normal_v3(plane, mat[3], mat[2]);
+
+ float ray_origin[3], ray_direction[3];
+
+ if (ED_view3d_win_to_ray(ar, v3d, mval, ray_origin, ray_direction, false)) {
+ float lambda;
+ if (isect_ray_plane_v3(ray_origin, ray_direction, plane, &lambda, true)) {
+ float co[3];
+ madd_v3_v3v3fl(co, ray_origin, ray_direction, lambda);
+ float imat[4][4];
+ invert_m4_m4(imat, mat);
+ mul_m4_v3(imat, co);
+ r_co[0] = co[(axis + 1) % 3];
+ r_co[1] = co[(axis + 2) % 3];
+ return true;
+ }
+ }
+ return false;
+ }
+ else {
+ float co[3] = {mval[0], mval[1], 0.0f};
+ float imat[4][4];
+ invert_m4_m4(imat, mat);
+ mul_m4_v3(imat, co);
+ copy_v2_v2(r_co, co);
+ return true;
+ }
+}
diff --git a/source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c
new file mode 100644
index 00000000000..749e92e25fb
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_types/arrow2d_manipulator.c
@@ -0,0 +1,224 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file arrow2d_manipulator.c
+ * \ingroup wm
+ *
+ * \name 2D Arrow Manipulator
+ *
+ * \brief Simple arrow manipulator which is dragged into a certain direction.
+ */
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_rect.h"
+
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_context.h"
+
+#include "BIF_gl.h"
+
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+/* own includes */
+#include "WM_api.h"
+
+#include "../manipulator_library_intern.h"
+
+static void arrow2d_draw_geom(wmManipulator *mpr, const float matrix[4][4], const float color[4])
+{
+ const float size = 0.11f;
+ const float size_breadth = size / 2.0f;
+ const float size_length = size * 1.7f;
+ /* Subtract the length so the arrow fits in the hotspot. */
+ const float arrow_length = RNA_float_get(mpr->ptr, "length") - size_length;
+ const float arrow_angle = RNA_float_get(mpr->ptr, "angle");
+
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ gpuPushMatrix();
+ gpuMultMatrix(matrix);
+ gpuRotate2D(RAD2DEGF(arrow_angle));
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4fv(color);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, 0.0f, 0.0f);
+ immVertex2f(pos, 0.0f, arrow_length);
+ immEnd();
+
+ immBegin(GWN_PRIM_TRIS, 3);
+ immVertex2f(pos, size_breadth, arrow_length);
+ immVertex2f(pos, -size_breadth, arrow_length);
+ immVertex2f(pos, 0.0f, arrow_length + size_length);
+ immEnd();
+
+ immUnbindProgram();
+
+ gpuPopMatrix();
+}
+
+static void manipulator_arrow2d_draw(const bContext *UNUSED(C), wmManipulator *mpr)
+{
+ float color[4];
+
+ float matrix_final[4][4];
+
+ manipulator_color_get(mpr, mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT, color);
+
+ glLineWidth(mpr->line_width);
+
+ WM_manipulator_calc_matrix_final(mpr, matrix_final);
+
+ glEnable(GL_BLEND);
+ arrow2d_draw_geom(mpr, matrix_final, color);
+ glDisable(GL_BLEND);
+
+ if (mpr->interaction_data) {
+ ManipulatorInteraction *inter = mpr->interaction_data;
+
+ glEnable(GL_BLEND);
+ arrow2d_draw_geom(mpr, inter->init_matrix_final, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
+ glDisable(GL_BLEND);
+ }
+}
+
+static void manipulator_arrow2d_setup(wmManipulator *mpr)
+{
+ mpr->flag |= WM_MANIPULATOR_DRAW_MODAL;
+}
+
+static int manipulator_arrow2d_invoke(
+ bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *UNUSED(event))
+{
+ ManipulatorInteraction *inter = MEM_callocN(sizeof(ManipulatorInteraction), __func__);
+
+ copy_m4_m4(inter->init_matrix_basis, mpr->matrix_basis);
+ WM_manipulator_calc_matrix_final(mpr, inter->init_matrix_final);
+
+ mpr->interaction_data = inter;
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int manipulator_arrow2d_test_select(
+ bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event)
+{
+ const float mval[2] = {event->mval[0], event->mval[1]};
+ const float arrow_length = RNA_float_get(mpr->ptr, "length");
+ const float arrow_angle = RNA_float_get(mpr->ptr, "angle");
+ const float line_len = arrow_length * mpr->scale_final;
+ float mval_local[2];
+
+ copy_v2_v2(mval_local, mval);
+ sub_v2_v2(mval_local, mpr->matrix_basis[3]);
+
+ float line[2][2];
+ line[0][0] = line[0][1] = line[1][0] = 0.0f;
+ line[1][1] = line_len;
+
+ /* rotate only if needed */
+ if (arrow_angle != 0.0f) {
+ float rot_point[2];
+ copy_v2_v2(rot_point, line[1]);
+ rotate_v2_v2fl(line[1], rot_point, arrow_angle);
+ }
+
+ /* arrow line intersection check */
+ float isect_1[2], isect_2[2];
+ const int isect = isect_line_sphere_v2(
+ line[0], line[1], mval_local, MANIPULATOR_HOTSPOT + mpr->line_width * 0.5f,
+ isect_1, isect_2);
+
+ if (isect > 0) {
+ float line_ext[2][2]; /* extended line for segment check including hotspot */
+ copy_v2_v2(line_ext[0], line[0]);
+ line_ext[1][0] = line[1][0] + MANIPULATOR_HOTSPOT * ((line[1][0] - line[0][0]) / line_len);
+ line_ext[1][1] = line[1][1] + MANIPULATOR_HOTSPOT * ((line[1][1] - line[0][1]) / line_len);
+
+ const float lambda_1 = line_point_factor_v2(isect_1, line_ext[0], line_ext[1]);
+ if (isect == 1) {
+ if (IN_RANGE_INCL(lambda_1, 0.0f, 1.0f)) {
+ return 0;
+ }
+ }
+ else {
+ BLI_assert(isect == 2);
+ const float lambda_2 = line_point_factor_v2(isect_2, line_ext[0], line_ext[1]);
+ if (IN_RANGE_INCL(lambda_1, 0.0f, 1.0f) && IN_RANGE_INCL(lambda_2, 0.0f, 1.0f)) {
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name 2D Arrow Manipulator API
+ *
+ * \{ */
+
+static void MANIPULATOR_WT_arrow_2d(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_arrow_2d";
+
+ /* api callbacks */
+ wt->draw = manipulator_arrow2d_draw;
+ wt->setup = manipulator_arrow2d_setup;
+ wt->invoke = manipulator_arrow2d_invoke;
+ wt->test_select = manipulator_arrow2d_test_select;
+
+ wt->struct_size = sizeof(wmManipulator);
+
+ /* rna */
+ RNA_def_float(wt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
+ RNA_def_float_rotation(
+ wt->srna, "angle", 0, NULL, DEG2RADF(-360.0f), DEG2RADF(360.0f),
+ "Roll", "", DEG2RADF(-360.0f), DEG2RADF(360.0f));
+}
+
+void ED_manipulatortypes_arrow_2d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_arrow_2d);
+}
+
+/** \} */
diff --git a/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c
new file mode 100644
index 00000000000..e9760e3e270
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c
@@ -0,0 +1,503 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file arrow3d_manipulator.c
+ * \ingroup wm
+ *
+ * \name Arrow Manipulator
+ *
+ * 3D Manipulator
+ *
+ * \brief Simple arrow manipulator which is dragged into a certain direction.
+ * The arrow head can have varying shapes, e.g. cone, box, etc.
+ *
+ * - `matrix[0]` is derived from Y and Z.
+ * - `matrix[1]` is 'up' for manipulator types that have an up.
+ * - `matrix[2]` is the arrow direction (for all arrowes).
+ */
+
+#include "BIF_gl.h"
+
+#include "BLI_math.h"
+
+#include "DNA_view3d_types.h"
+
+#include "BKE_context.h"
+
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_select.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "ED_view3d.h"
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+/* own includes */
+#include "../manipulator_geometry.h"
+#include "../manipulator_library_intern.h"
+
+/* to use custom arrows exported to geom_arrow_manipulator.c */
+//#define USE_MANIPULATOR_CUSTOM_ARROWS
+
+typedef struct ArrowManipulator3D {
+ wmManipulator manipulator;
+ ManipulatorCommonData data;
+} ArrowManipulator3D;
+
+
+/* -------------------------------------------------------------------- */
+
+static void manipulator_arrow_matrix_basis_get(const wmManipulator *mpr, float r_matrix[4][4])
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr;
+
+ copy_m4_m4(r_matrix, arrow->manipulator.matrix_basis);
+ madd_v3_v3fl(r_matrix[3], arrow->manipulator.matrix_basis[2], arrow->data.offset);
+}
+
+static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select, const float color[4])
+{
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ bool unbind_shader = true;
+ const int draw_style = RNA_enum_get(arrow->manipulator.ptr, "draw_style");
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (draw_style == ED_MANIPULATOR_ARROW_STYLE_CROSS) {
+ immUniformColor4fv(color);
+
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex3f(pos, -1.0f, 0.0f, 0.0f);
+ immVertex3f(pos, 1.0f, 0.0f, 0.0f);
+ immVertex3f(pos, 0.0f, -1.0f, 0.0f);
+ immVertex3f(pos, 0.0f, 1.0f, 0.0f);
+ immEnd();
+ }
+ else if (draw_style == ED_MANIPULATOR_ARROW_STYLE_CONE) {
+ float aspect[2];
+ RNA_float_get_array(arrow->manipulator.ptr, "aspect", aspect);
+ const float unitx = aspect[0];
+ const float unity = aspect[1];
+ const float vec[4][3] = {
+ {-unitx, -unity, 0},
+ { unitx, -unity, 0},
+ { unitx, unity, 0},
+ {-unitx, unity, 0},
+ };
+
+ glLineWidth(arrow->manipulator.line_width);
+ wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_LOOP);
+ }
+ else {
+#ifdef USE_MANIPULATOR_CUSTOM_ARROWS
+ wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_arrow, select, color);
+#else
+ const float arrow_length = RNA_float_get(arrow->manipulator.ptr, "length");
+
+ const float vec[2][3] = {
+ {0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, arrow_length},
+ };
+
+ glLineWidth(arrow->manipulator.line_width);
+ wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_STRIP);
+
+
+ /* *** draw arrow head *** */
+
+ gpuPushMatrix();
+
+ if (draw_style == ED_MANIPULATOR_ARROW_STYLE_BOX) {
+ const float size = 0.05f;
+
+ /* translate to line end with some extra offset so box starts exactly where line ends */
+ gpuTranslate3f(0.0f, 0.0f, arrow_length + size);
+ /* scale down to box size */
+ gpuScale3f(size, size, size);
+
+ /* draw cube */
+ immUnbindProgram();
+ unbind_shader = false;
+ wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_cube, select, color);
+ }
+ else {
+ BLI_assert(draw_style == ED_MANIPULATOR_ARROW_STYLE_NORMAL);
+
+ const float len = 0.25f;
+ const float width = 0.06f;
+ const bool use_lighting = (!select && ((U.manipulator_flag & USER_MANIPULATOR_SHADED) != 0));
+
+ /* translate to line end */
+ gpuTranslate3f(0.0f, 0.0f, arrow_length);
+
+ if (use_lighting) {
+ immUnbindProgram();
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+ }
+
+ imm_draw_circle_fill_3d(pos, 0.0, 0.0, width, 8);
+ imm_draw_cylinder_fill_3d(pos, width, 0.0, len, 8, 1);
+ }
+
+ gpuPopMatrix();
+#endif /* USE_MANIPULATOR_CUSTOM_ARROWS */
+ }
+
+ if (unbind_shader) {
+ immUnbindProgram();
+ }
+}
+
+static void arrow_draw_intern(ArrowManipulator3D *arrow, const bool select, const bool highlight)
+{
+ wmManipulator *mpr = &arrow->manipulator;
+ float color[4];
+ float matrix_final[4][4];
+
+ manipulator_color_get(mpr, highlight, color);
+
+ WM_manipulator_calc_matrix_final(mpr, matrix_final);
+
+ gpuPushMatrix();
+ gpuMultMatrix(matrix_final);
+ glEnable(GL_BLEND);
+ arrow_draw_geom(arrow, select, color);
+ glDisable(GL_BLEND);
+
+ gpuPopMatrix();
+
+ if (mpr->interaction_data) {
+ ManipulatorInteraction *inter = mpr->interaction_data;
+
+ gpuPushMatrix();
+ gpuMultMatrix(inter->init_matrix_final);
+
+
+ glEnable(GL_BLEND);
+ arrow_draw_geom(arrow, select, (const float [4]){0.5f, 0.5f, 0.5f, 0.5f});
+ glDisable(GL_BLEND);
+
+ gpuPopMatrix();
+ }
+}
+
+static void manipulator_arrow_draw_select(
+ const bContext *UNUSED(C), wmManipulator *mpr,
+ int select_id)
+{
+ GPU_select_load_id(select_id);
+ arrow_draw_intern((ArrowManipulator3D *)mpr, true, false);
+}
+
+static void manipulator_arrow_draw(const bContext *UNUSED(C), wmManipulator *mpr)
+{
+ arrow_draw_intern((ArrowManipulator3D *)mpr, false, (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0);
+}
+
+/**
+ * Calculate arrow offset independent from prop min value,
+ * meaning the range will not be offset by min value first.
+ */
+static int manipulator_arrow_modal(
+ bContext *C, wmManipulator *mpr, const wmEvent *event,
+ eWM_ManipulatorTweak tweak_flag)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr;
+ ManipulatorInteraction *inter = mpr->interaction_data;
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ float orig_origin[4];
+ float viewvec[3], tangent[3], plane[3];
+ float offset[4];
+ float m_diff[2];
+ float dir_2d[2], dir2d_final[2];
+ float facdir = 1.0f;
+ bool use_vertical = false;
+
+
+ copy_v3_v3(orig_origin, inter->init_matrix_basis[3]);
+ orig_origin[3] = 1.0f;
+ add_v3_v3v3(offset, orig_origin, arrow->manipulator.matrix_basis[2]);
+ offset[3] = 1.0f;
+
+ /* calculate view vector */
+ if (rv3d->is_persp) {
+ sub_v3_v3v3(viewvec, orig_origin, rv3d->viewinv[3]);
+ }
+ else {
+ copy_v3_v3(viewvec, rv3d->viewinv[2]);
+ }
+ normalize_v3(viewvec);
+
+ /* first determine if view vector is really close to the direction. If it is, we use
+ * vertical movement to determine offset, just like transform system does */
+ if (RAD2DEGF(acosf(dot_v3v3(viewvec, arrow->manipulator.matrix_basis[2]))) > 5.0f) {
+ /* multiply to projection space */
+ mul_m4_v4(rv3d->persmat, orig_origin);
+ mul_v4_fl(orig_origin, 1.0f / orig_origin[3]);
+ mul_m4_v4(rv3d->persmat, offset);
+ mul_v4_fl(offset, 1.0f / offset[3]);
+
+ sub_v2_v2v2(dir_2d, offset, orig_origin);
+ dir_2d[0] *= ar->winx;
+ dir_2d[1] *= ar->winy;
+ normalize_v2(dir_2d);
+ }
+ else {
+ dir_2d[0] = 0.0f;
+ dir_2d[1] = 1.0f;
+ use_vertical = true;
+ }
+
+ /* find mouse difference */
+ m_diff[0] = event->mval[0] - inter->init_mval[0];
+ m_diff[1] = event->mval[1] - inter->init_mval[1];
+
+ /* project the displacement on the screen space arrow direction */
+ project_v2_v2v2(dir2d_final, m_diff, dir_2d);
+
+ float zfac = ED_view3d_calc_zfac(rv3d, orig_origin, NULL);
+ ED_view3d_win_to_delta(ar, dir2d_final, offset, zfac);
+
+ add_v3_v3v3(orig_origin, offset, inter->init_matrix_basis[3]);
+
+ /* calculate view vector for the new position */
+ if (rv3d->is_persp) {
+ sub_v3_v3v3(viewvec, orig_origin, rv3d->viewinv[3]);
+ }
+ else {
+ copy_v3_v3(viewvec, rv3d->viewinv[2]);
+ }
+
+ normalize_v3(viewvec);
+ if (!use_vertical) {
+ /* now find a plane parallel to the view vector so we can intersect with the arrow direction */
+ cross_v3_v3v3(tangent, viewvec, offset);
+ cross_v3_v3v3(plane, tangent, viewvec);
+
+ const float plane_offset = dot_v3v3(plane, offset);
+ const float plane_dir = dot_v3v3(plane, arrow->manipulator.matrix_basis[2]);
+ const float fac = (plane_dir != 0.0f) ? (plane_offset / plane_dir) : 0.0f;
+ facdir = (fac < 0.0f) ? -1.0f : 1.0f;
+ if (isfinite(fac)) {
+ mul_v3_v3fl(offset, arrow->manipulator.matrix_basis[2], fac);
+ }
+ }
+ else {
+ facdir = (m_diff[1] < 0.0f) ? -1.0f : 1.0f;
+ }
+
+
+ ManipulatorCommonData *data = &arrow->data;
+ const float ofs_new = facdir * len_v3(offset);
+
+ wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset");
+
+ /* set the property for the operator and call its modal function */
+ if (WM_manipulator_target_property_is_valid(mpr_prop)) {
+ const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options");
+ const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0;
+ const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0;
+ const bool use_precision = (tweak_flag & WM_MANIPULATOR_TWEAK_PRECISE) != 0;
+ float value = manipulator_value_from_offset(data, inter, ofs_new, constrained, inverted, use_precision);
+
+ WM_manipulator_target_property_value_set(C, mpr, mpr_prop, value);
+ /* get clamped value */
+ value = WM_manipulator_target_property_value_get(mpr, mpr_prop);
+
+ data->offset = manipulator_offset_from_value(data, value, constrained, inverted);
+ }
+ else {
+ data->offset = ofs_new;
+ }
+
+ /* tag the region for redraw */
+ ED_region_tag_redraw(ar);
+ WM_event_add_mousemove(C);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void manipulator_arrow_setup(wmManipulator *mpr)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr;
+
+ arrow->manipulator.flag |= WM_MANIPULATOR_DRAW_MODAL;
+
+ arrow->data.range_fac = 1.0f;
+}
+
+static int manipulator_arrow_invoke(
+ bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr;
+ ManipulatorInteraction *inter = MEM_callocN(sizeof(ManipulatorInteraction), __func__);
+ wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset");
+
+ /* Some manipulators don't use properties. */
+ if (WM_manipulator_target_property_is_valid(mpr_prop)) {
+ inter->init_value = WM_manipulator_target_property_value_get(mpr, mpr_prop);
+ }
+
+ inter->init_offset = arrow->data.offset;
+
+ inter->init_mval[0] = event->mval[0];
+ inter->init_mval[1] = event->mval[1];
+
+ manipulator_arrow_matrix_basis_get(mpr, inter->init_matrix_basis);
+ WM_manipulator_calc_matrix_final(mpr, inter->init_matrix_final);
+
+ mpr->interaction_data = inter;
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void manipulator_arrow_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr;
+ const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options");
+ const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0;
+ const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0;
+ manipulator_property_data_update(mpr, &arrow->data, mpr_prop, constrained, inverted);
+}
+
+static void manipulator_arrow_exit(bContext *C, wmManipulator *mpr, const bool cancel)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr;
+ ManipulatorCommonData *data = &arrow->data;
+ wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset");
+ const bool is_prop_valid = WM_manipulator_target_property_is_valid(mpr_prop);
+
+ if (!cancel) {
+ /* Assign incase applying the opetration needs an updated offset
+ * editmesh bisect needs this. */
+ if (is_prop_valid) {
+ data->offset = WM_manipulator_target_property_value_get(mpr, mpr_prop);
+ }
+ return;
+ }
+
+ ManipulatorInteraction *inter = mpr->interaction_data;
+ if (is_prop_valid) {
+ manipulator_property_value_reset(C, mpr, inter, mpr_prop);
+ }
+ data->offset = inter->init_offset;
+}
+
+
+/* -------------------------------------------------------------------- */
+/** \name Arrow Manipulator API
+ *
+ * \{ */
+
+/**
+ * Define a custom property UI range
+ *
+ * \note Needs to be called before WM_manipulator_target_property_def_rna!
+ */
+void ED_manipulator_arrow3d_set_ui_range(wmManipulator *mpr, const float min, const float max)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr;
+
+ BLI_assert(min < max);
+ BLI_assert(!(WM_manipulator_target_property_is_valid(WM_manipulator_target_property_find(mpr, "offset")) &&
+ "Make sure this function is called before WM_manipulator_target_property_def_rna"));
+
+ arrow->data.range = max - min;
+ arrow->data.min = min;
+ arrow->data.flag |= MANIPULATOR_CUSTOM_RANGE_SET;
+}
+
+/**
+ * Define a custom factor for arrow min/max distance
+ *
+ * \note Needs to be called before WM_manipulator_target_property_def_rna!
+ */
+void ED_manipulator_arrow3d_set_range_fac(wmManipulator *mpr, const float range_fac)
+{
+ ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr;
+ BLI_assert(!(WM_manipulator_target_property_is_valid(WM_manipulator_target_property_find(mpr, "offset")) &&
+ "Make sure this function is called before WM_manipulator_target_property_def_rna"));
+
+ arrow->data.range_fac = range_fac;
+}
+
+static void MANIPULATOR_WT_arrow_3d(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_arrow_3d";
+
+ /* api callbacks */
+ wt->draw = manipulator_arrow_draw;
+ wt->draw_select = manipulator_arrow_draw_select;
+ wt->matrix_basis_get = manipulator_arrow_matrix_basis_get;
+ wt->modal = manipulator_arrow_modal;
+ wt->setup = manipulator_arrow_setup;
+ wt->invoke = manipulator_arrow_invoke;
+ wt->property_update = manipulator_arrow_property_update;
+ wt->exit = manipulator_arrow_exit;
+
+ wt->struct_size = sizeof(ArrowManipulator3D);
+
+ /* rna */
+ static EnumPropertyItem rna_enum_draw_style[] = {
+ {ED_MANIPULATOR_ARROW_STYLE_NORMAL, "NORMAL", 0, "Normal", ""},
+ {ED_MANIPULATOR_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""},
+ {ED_MANIPULATOR_ARROW_STYLE_BOX, "BOX", 0, "Box", ""},
+ {ED_MANIPULATOR_ARROW_STYLE_CONE, "CONE", 0, "Cone", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_MANIPULATOR_ARROW_STYLE_INVERTED, "INVERT", 0, "Inverted", ""},
+ {ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_ARROW_STYLE_NORMAL, "Draw Style", "");
+ RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+
+ RNA_def_float(wt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
+ RNA_def_float_vector(wt->srna, "aspect", 2, NULL, 0, FLT_MAX, "Aspect", "Cone/box style only", 0.0f, FLT_MAX);
+
+ WM_manipulatortype_target_property_def(wt, "offset", PROP_FLOAT, 1);
+}
+
+void ED_manipulatortypes_arrow_3d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_arrow_3d);
+}
+
+/** \} */
diff --git a/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c
new file mode 100644
index 00000000000..0299a33d0fe
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_types/cage2d_manipulator.c
@@ -0,0 +1,1109 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file cage2d_manipulator.c
+ * \ingroup wm
+ *
+ * \name Cage Manipulator
+ *
+ * 2D Manipulator
+ *
+ * \brief Rectangular manipulator acting as a 'cage' around its content.
+ * Interacting scales or translates the manipulator.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_dial.h"
+#include "BLI_rect.h"
+
+#include "BKE_context.h"
+
+#include "BIF_gl.h"
+
+#include "GPU_matrix.h"
+#include "GPU_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_select.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_manipulator_library.h"
+
+/* own includes */
+#include "../manipulator_library_intern.h"
+
+#define MANIPULATOR_RESIZER_SIZE 10.0f
+#define MANIPULATOR_MARGIN_OFFSET_SCALE 1.5f
+
+static void manipulator_calc_matrix_final_no_offset(
+ const wmManipulator *mpr, float orig_matrix_final_no_offset[4][4])
+{
+ float mat_identity[4][4];
+ struct WM_ManipulatorMatrixParams params = {NULL};
+ unit_m4(mat_identity);
+ params.matrix_offset = mat_identity;
+ WM_manipulator_calc_matrix_final_params(mpr, &params, orig_matrix_final_no_offset);
+}
+
+static void manipulator_calc_rect_view_scale(
+ const wmManipulator *mpr, const float dims[2], float scale[2])
+{
+ float matrix_final_no_offset[4][4];
+ float asp[2] = {1.0f, 1.0f};
+ if (dims[0] > dims[1]) {
+ asp[0] = dims[1] / dims[0];
+ }
+ else {
+ asp[1] = dims[0] / dims[1];
+ }
+ float x_axis[3], y_axis[3];
+ manipulator_calc_matrix_final_no_offset(mpr, matrix_final_no_offset);
+ mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, mpr->matrix_offset[0]);
+ mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, mpr->matrix_offset[1]);
+
+ mul_v2_v2(x_axis, asp);
+ mul_v2_v2(y_axis, asp);
+
+ scale[0] = 1.0f / len_v3(x_axis);
+ scale[1] = 1.0f / len_v3(y_axis);
+}
+
+static void manipulator_calc_rect_view_margin(
+ const wmManipulator *mpr, const float dims[2], float margin[2])
+{
+ float handle_size;
+ if (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) {
+ handle_size = 0.15f;
+ }
+ else {
+ handle_size = MANIPULATOR_RESIZER_SIZE;
+ }
+ handle_size *= mpr->scale_final;
+ float scale_xy[2];
+ manipulator_calc_rect_view_scale(mpr, dims, scale_xy);
+ margin[0] = ((handle_size * scale_xy[0]));
+ margin[1] = ((handle_size * scale_xy[1]));
+}
+
+/* -------------------------------------------------------------------- */
+
+static void manipulator_rect_pivot_from_scale_part(int part, float r_pt[2], bool r_constrain_axis[2])
+{
+ bool x = true, y = true;
+ switch (part) {
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X: { ARRAY_SET_ITEMS(r_pt, 0.5, 0.0); x = false; break; }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X: { ARRAY_SET_ITEMS(r_pt, -0.5, 0.0); x = false; break; }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y: { ARRAY_SET_ITEMS(r_pt, 0.0, 0.5); y = false; break; }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y: { ARRAY_SET_ITEMS(r_pt, 0.0, -0.5); y = false; break; }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y: { ARRAY_SET_ITEMS(r_pt, 0.5, 0.5); x = y = false; break; }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y: { ARRAY_SET_ITEMS(r_pt, 0.5, -0.5); x = y = false; break; }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y: { ARRAY_SET_ITEMS(r_pt, -0.5, 0.5); x = y = false; break; }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y: { ARRAY_SET_ITEMS(r_pt, -0.5, -0.5); x = y = false; break; }
+ default: BLI_assert(0);
+ }
+ r_constrain_axis[0] = x;
+ r_constrain_axis[1] = y;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Box Draw Style
+ *
+ * Useful for 3D views, see: #ED_MANIPULATOR_CAGE2D_STYLE_BOX
+ * \{ */
+
+static void cage2d_draw_box_corners(
+ const rctf *r, const float margin[2], const float color[3])
+{
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
+ immBegin(GWN_PRIM_LINES, 16);
+
+ immVertex2f(pos, r->xmin, r->ymin + margin[1]);
+ immVertex2f(pos, r->xmin, r->ymin);
+ immVertex2f(pos, r->xmin, r->ymin);
+ immVertex2f(pos, r->xmin + margin[0], r->ymin);
+
+ immVertex2f(pos, r->xmax, r->ymin + margin[1]);
+ immVertex2f(pos, r->xmax, r->ymin);
+ immVertex2f(pos, r->xmax, r->ymin);
+ immVertex2f(pos, r->xmax - margin[0], r->ymin);
+
+ immVertex2f(pos, r->xmax, r->ymax - margin[1]);
+ immVertex2f(pos, r->xmax, r->ymax);
+ immVertex2f(pos, r->xmax, r->ymax);
+ immVertex2f(pos, r->xmax - margin[0], r->ymax);
+
+ immVertex2f(pos, r->xmin, r->ymax - margin[1]);
+ immVertex2f(pos, r->xmin, r->ymax);
+ immVertex2f(pos, r->xmin, r->ymax);
+ immVertex2f(pos, r->xmin + margin[0], r->ymax);
+
+ immEnd();
+
+ immUnbindProgram();
+}
+
+static void cage2d_draw_box_interaction(
+ const float color[4], const int highlighted,
+ const float size[2], const float margin[2],
+ const float line_width, const bool is_solid, const int draw_options)
+{
+ /* 4 verts for translate, otherwise only 3 are used. */
+ float verts[4][2];
+ uint verts_len = 0;
+ Gwn_PrimType prim_type = GWN_PRIM_NONE;
+
+ switch (highlighted) {
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X:
+ {
+ rctf r = {
+ .xmin = -size[0], .xmax = -size[0] + margin[0],
+ .ymin = -size[1] + margin[1], .ymax = size[1] - margin[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
+ ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax);
+ verts_len = 2;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
+ ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
+ verts_len += 2;
+ prim_type = GWN_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GWN_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X:
+ {
+ rctf r = {
+ .xmin = size[0] - margin[0], .xmax = size[0],
+ .ymin = -size[1] + margin[1], .ymax = size[1] - margin[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin);
+ ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
+ verts_len = 2;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax);
+ ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
+ verts_len += 2;
+ prim_type = GWN_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GWN_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y:
+ {
+ rctf r = {
+ .xmin = -size[0] + margin[0], .xmax = size[0] - margin[0],
+ .ymin = -size[1], .ymax = -size[1] + margin[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
+ ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin);
+ verts_len = 2;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
+ ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
+ verts_len += 2;
+ prim_type = GWN_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GWN_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y:
+ {
+ rctf r = {
+ .xmin = -size[0] + margin[0], .xmax = size[0] - margin[0],
+ .ymin = size[1] - margin[1], .ymax = size[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax);
+ ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
+ verts_len = 2;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin);
+ ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
+ verts_len += 2;
+ prim_type = GWN_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GWN_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y:
+ {
+ rctf r = {
+ .xmin = -size[0], .xmax = -size[0] + margin[0],
+ .ymin = -size[1], .ymax = -size[1] + margin[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymin);
+ ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymax);
+ ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymax);
+ verts_len = 3;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymin);
+ verts_len += 1;
+ prim_type = GWN_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GWN_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y:
+ {
+ rctf r = {
+ .xmin = -size[0], .xmax = -size[0] + margin[0],
+ .ymin = size[1] - margin[1], .ymax = size[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmax, r.ymax);
+ ARRAY_SET_ITEMS(verts[1], r.xmax, r.ymin);
+ ARRAY_SET_ITEMS(verts[2], r.xmin, r.ymin);
+ verts_len = 3;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[3], r.xmin, r.ymax);
+ verts_len += 1;
+ prim_type = GWN_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GWN_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y:
+ {
+ rctf r = {
+ .xmin = size[0] - margin[0], .xmax = size[0],
+ .ymin = -size[1], .ymax = -size[1] + margin[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymin);
+ ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymax);
+ ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymax);
+ verts_len = 3;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymin);
+ verts_len += 1;
+ prim_type = GWN_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GWN_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y:
+ {
+ rctf r = {
+ .xmin = size[0] - margin[0], .xmax = size[0],
+ .ymin = size[1] - margin[1], .ymax = size[1],
+ };
+ ARRAY_SET_ITEMS(verts[0], r.xmin, r.ymax);
+ ARRAY_SET_ITEMS(verts[1], r.xmin, r.ymin);
+ ARRAY_SET_ITEMS(verts[2], r.xmax, r.ymin);
+ verts_len = 3;
+ if (is_solid) {
+ ARRAY_SET_ITEMS(verts[3], r.xmax, r.ymax);
+ verts_len += 1;
+ prim_type = GWN_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GWN_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+ case ED_MANIPULATOR_CAGE2D_PART_ROTATE:
+ {
+ const float rotate_pt[2] = {0.0f, size[1] + margin[1]};
+ const rctf r_rotate = {
+ .xmin = rotate_pt[0] - margin[0] / 2.0f,
+ .xmax = rotate_pt[0] + margin[0] / 2.0f,
+ .ymin = rotate_pt[1] - margin[1] / 2.0f,
+ .ymax = rotate_pt[1] + margin[1] / 2.0f,
+ };
+
+ ARRAY_SET_ITEMS(verts[0], r_rotate.xmin, r_rotate.ymin);
+ ARRAY_SET_ITEMS(verts[1], r_rotate.xmin, r_rotate.ymax);
+ ARRAY_SET_ITEMS(verts[2], r_rotate.xmax, r_rotate.ymax);
+ ARRAY_SET_ITEMS(verts[3], r_rotate.xmax, r_rotate.ymin);
+ verts_len = 4;
+ if (is_solid) {
+ prim_type = GWN_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GWN_PRIM_LINE_STRIP;
+ }
+ break;
+ }
+
+ case ED_MANIPULATOR_CAGE2D_PART_TRANSLATE:
+ if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ ARRAY_SET_ITEMS(verts[0], -margin[0] / 2, -margin[1] / 2);
+ ARRAY_SET_ITEMS(verts[1], margin[0] / 2, margin[1] / 2);
+ ARRAY_SET_ITEMS(verts[2], -margin[0] / 2, margin[1] / 2);
+ ARRAY_SET_ITEMS(verts[3], margin[0] / 2, -margin[1] / 2);
+ verts_len = 4;
+ if (is_solid) {
+ prim_type = GWN_PRIM_TRI_FAN;
+ }
+ else {
+ prim_type = GWN_PRIM_LINES;
+ }
+ }
+ else {
+ /* Only used for 3D view selection, never displayed to the user. */
+ ARRAY_SET_ITEMS(verts[0], -size[0], -size[1]);
+ ARRAY_SET_ITEMS(verts[1], -size[0], size[1]);
+ ARRAY_SET_ITEMS(verts[2], size[0], size[1]);
+ ARRAY_SET_ITEMS(verts[3], size[0], -size[1]);
+ verts_len = 4;
+ if (is_solid) {
+ prim_type = GWN_PRIM_TRI_FAN;
+ }
+ else {
+ /* unreachable */
+ BLI_assert(0);
+ prim_type = GWN_PRIM_LINE_STRIP;
+ }
+ }
+ break;
+ default:
+ return;
+ }
+
+ BLI_assert(prim_type != GWN_PRIM_NONE);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ struct {
+ uint pos, col;
+ } attr_id = {
+ .pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT),
+ .col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT),
+ };
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ {
+ if (is_solid) {
+ BLI_assert(ELEM(prim_type, GWN_PRIM_TRI_FAN));
+ immBegin(prim_type, verts_len);
+ immAttrib3f(attr_id.col, 0.0f, 0.0f, 0.0f);
+ for (uint i = 0; i < verts_len; i++) {
+ immVertex2fv(attr_id.pos, verts[i]);
+ }
+ immEnd();
+ }
+ else {
+ BLI_assert(ELEM(prim_type, GWN_PRIM_LINE_STRIP, GWN_PRIM_LINES));
+ glLineWidth(line_width + 3.0f);
+
+ immBegin(prim_type, verts_len);
+ immAttrib3f(attr_id.col, 0.0f, 0.0f, 0.0f);
+ for (uint i = 0; i < verts_len; i++) {
+ immVertex2fv(attr_id.pos, verts[i]);
+ }
+ immEnd();
+
+ glLineWidth(line_width);
+
+ immBegin(prim_type, verts_len);
+ immAttrib3fv(attr_id.col, color);
+ for (uint i = 0; i < verts_len; i++) {
+ immVertex2fv(attr_id.pos, verts[i]);
+ }
+ immEnd();
+ }
+ }
+
+ immUnbindProgram();
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Circle Draw Style
+ *
+ * Useful for 2D views, see: #ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE
+ * \{ */
+
+static void imm_draw_point_aspect_2d(
+ uint pos, float x, float y, float rad_x, float rad_y, bool solid)
+{
+ immBegin(solid ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, x - rad_x, y - rad_y);
+ immVertex2f(pos, x - rad_x, y + rad_y);
+ immVertex2f(pos, x + rad_x, y + rad_y);
+ immVertex2f(pos, x + rad_x, y - rad_y);
+ immEnd();
+}
+
+static void cage2d_draw_circle_wire(
+ const rctf *r, const float margin[2], const float color[3],
+ const int transform_flag, const int draw_options)
+{
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, r->xmin, r->ymin);
+ immVertex2f(pos, r->xmax, r->ymin);
+ immVertex2f(pos, r->xmax, r->ymax);
+ immVertex2f(pos, r->xmin, r->ymax);
+ immEnd();
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE) {
+ immBegin(GWN_PRIM_LINE_LOOP, 2);
+ immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax);
+ immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1]);
+ immEnd();
+ }
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ const float rad[2] = {margin[0] / 2, margin[1] / 2};
+ const float center[2] = {BLI_rctf_cent_x(r), BLI_rctf_cent_y(r)};
+
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex2f(pos, center[0] - rad[0], center[1] - rad[1]);
+ immVertex2f(pos, center[0] + rad[0], center[1] + rad[1]);
+ immVertex2f(pos, center[0] + rad[0], center[1] - rad[1]);
+ immVertex2f(pos, center[0] - rad[0], center[1] + rad[1]);
+ immEnd();
+ }
+ }
+
+ immUnbindProgram();
+}
+
+static void cage2d_draw_circle_handles(
+ const rctf *r, const float margin[2], const float color[3],
+ const int transform_flag,
+ bool solid)
+{
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ void (*circle_fn)(uint, float, float, float, float, int) =
+ (solid) ? imm_draw_circle_fill_aspect_2d : imm_draw_circle_wire_aspect_2d;
+ const int resolu = 12;
+ const float rad[2] = {margin[0] / 3, margin[1] / 3};
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
+ /* should really divide by two, but looks too bulky. */
+ {
+ imm_draw_point_aspect_2d(pos, r->xmin, r->ymin, rad[0], rad[1], solid);
+ imm_draw_point_aspect_2d(pos, r->xmax, r->ymin, rad[0], rad[1], solid);
+ imm_draw_point_aspect_2d(pos, r->xmax, r->ymax, rad[0], rad[1], solid);
+ imm_draw_point_aspect_2d(pos, r->xmin, r->ymax, rad[0], rad[1], solid);
+ }
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE) {
+ const float handle[2] = {BLI_rctf_cent_x(r), r->ymax + (margin[1] * MANIPULATOR_MARGIN_OFFSET_SCALE)};
+ circle_fn(pos, handle[0], handle[1], rad[0], rad[1], resolu);
+ }
+
+ immUnbindProgram();
+}
+
+/** \} */
+
+static void manipulator_cage2d_draw_intern(
+ wmManipulator *mpr, const bool select, const bool highlight, const int select_id)
+{
+ // const bool use_clamp = (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) == 0;
+ float dims[2];
+ RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ float matrix_final[4][4];
+
+ const int transform_flag = RNA_enum_get(mpr->ptr, "transform");
+ const int draw_style = RNA_enum_get(mpr->ptr, "draw_style");
+ const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+
+ const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
+
+ WM_manipulator_calc_matrix_final(mpr, matrix_final);
+
+ gpuPushMatrix();
+ gpuMultMatrix(matrix_final);
+
+ float margin[2];
+ manipulator_calc_rect_view_margin(mpr, dims, margin);
+
+ /* Handy for quick testing draw (if it's outside bounds). */
+ if (false) {
+ glEnable(GL_BLEND);
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv((const float[4]){1, 1, 1, 0.5f});
+ float s = 0.5f;
+ immRectf(pos, -s, -s, s, s);
+ immUnbindProgram();
+ glDisable(GL_BLEND);
+ }
+
+ if (select) {
+ /* expand for hotspot */
+ const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE) {
+ int scale_parts[] = {
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y,
+
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y,
+ ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y,
+ };
+ for (int i = 0; i < ARRAY_SIZE(scale_parts); i++) {
+ GPU_select_load_id(select_id | scale_parts[i]);
+ cage2d_draw_box_interaction(
+ mpr->color, scale_parts[i], size, margin, mpr->line_width, true, draw_options);
+ }
+ }
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ const int transform_part = ED_MANIPULATOR_CAGE2D_PART_TRANSLATE;
+ GPU_select_load_id(select_id | transform_part);
+ cage2d_draw_box_interaction(
+ mpr->color, transform_part, size, margin, mpr->line_width, true, draw_options);
+ }
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE) {
+ cage2d_draw_box_interaction(
+ mpr->color, ED_MANIPULATOR_CAGE2D_PART_ROTATE, size_real, margin, mpr->line_width, true, draw_options);
+ }
+ }
+ else {
+ const rctf r = {
+ .xmin = -size_real[0],
+ .ymin = -size_real[1],
+ .xmax = size_real[0],
+ .ymax = size_real[1],
+ };
+ if (draw_style == ED_MANIPULATOR_CAGE2D_STYLE_BOX) {
+ /* corner manipulators */
+ glLineWidth(mpr->line_width + 3.0f);
+ cage2d_draw_box_corners(&r, margin, (const float[3]){0, 0, 0});
+
+ /* corner manipulators */
+ float color[4];
+ manipulator_color_get(mpr, highlight, color);
+ glLineWidth(mpr->line_width);
+ cage2d_draw_box_corners(&r, margin, color);
+
+ bool show = false;
+ if (mpr->highlight_part == ED_MANIPULATOR_CAGE2D_PART_TRANSLATE) {
+ /* Only show if we're drawing the center handle
+ * otherwise the entire rectangle is the hotspot. */
+ if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ show = true;
+ }
+ }
+ else {
+ show = true;
+ }
+
+ if (show) {
+ cage2d_draw_box_interaction(
+ mpr->color, mpr->highlight_part, size_real, margin, mpr->line_width, false, draw_options);
+ }
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE) {
+ cage2d_draw_box_interaction(
+ mpr->color, ED_MANIPULATOR_CAGE2D_PART_ROTATE, size_real, margin, mpr->line_width, false, draw_options);
+ }
+ }
+ else if (draw_style == ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE) {
+ float color[4];
+ manipulator_color_get(mpr, highlight, color);
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ glLineWidth(mpr->line_width + 3.0f);
+ cage2d_draw_circle_wire(&r, margin, (const float[3]){0, 0, 0}, transform_flag, draw_options);
+ glLineWidth(mpr->line_width);
+ cage2d_draw_circle_wire(&r, margin, color, transform_flag, draw_options);
+
+
+ /* corner manipulators */
+ cage2d_draw_circle_handles(&r, margin, color, transform_flag, true);
+ cage2d_draw_circle_handles(&r, margin, (const float[3]){0, 0, 0}, transform_flag, false);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ glLineWidth(1.0);
+ gpuPopMatrix();
+}
+
+/**
+ * For when we want to draw 2d cage in 3d views.
+ */
+static void manipulator_cage2d_draw_select(const bContext *UNUSED(C), wmManipulator *mpr, int select_id)
+{
+ manipulator_cage2d_draw_intern(mpr, true, false, select_id);
+}
+
+static void manipulator_cage2d_draw(const bContext *UNUSED(C), wmManipulator *mpr)
+{
+ const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
+ manipulator_cage2d_draw_intern(mpr, false, is_highlight, -1);
+}
+
+static int manipulator_cage2d_get_cursor(wmManipulator *mpr)
+{
+ int highlight_part = mpr->highlight_part;
+
+ if (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) {
+ return BC_NSEW_SCROLLCURSOR;
+ }
+
+ switch (highlight_part) {
+ case ED_MANIPULATOR_CAGE2D_PART_TRANSLATE:
+ return BC_HANDCURSOR;
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X:
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X:
+ return CURSOR_X_MOVE;
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y:
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y:
+ return CURSOR_Y_MOVE;
+
+ /* TODO diagonal cursor */
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y:
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y:
+ return BC_NSEW_SCROLLCURSOR;
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y:
+ case ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y:
+ return BC_NSEW_SCROLLCURSOR;
+ case ED_MANIPULATOR_CAGE2D_PART_ROTATE:
+ return BC_CROSSCURSOR;
+ default:
+ return CURSOR_STD;
+ }
+}
+
+static int manipulator_cage2d_test_select(
+ bContext *C, wmManipulator *mpr, const wmEvent *event)
+{
+ float point_local[2];
+ float dims[2];
+ RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ const float size_real[2] = {dims[0] / 2.0f, dims[1] / 2.0f};
+
+ if (manipulator_window_project_2d(
+ C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, true, point_local) == false)
+ {
+ return -1;
+ }
+
+ float margin[2];
+ manipulator_calc_rect_view_margin(mpr, dims, margin);
+ /* expand for hotspot */
+ const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
+
+ const int transform_flag = RNA_enum_get(mpr->ptr, "transform");
+ const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ rctf r;
+ if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ r.xmin = -margin[0] / 2;
+ r.ymin = -margin[1] / 2;
+ r.xmax = margin[0] / 2;
+ r.ymax = margin[1] / 2;
+ }
+ else {
+ r.xmin = -size[0] + margin[0];
+ r.ymin = -size[1] + margin[1];
+ r.xmax = size[0] - margin[0];
+ r.ymax = size[1] - margin[1];
+ };
+ bool isect = BLI_rctf_isect_pt_v(&r, point_local);
+ if (isect) {
+ return ED_MANIPULATOR_CAGE2D_PART_TRANSLATE;
+ }
+ }
+
+ /* if manipulator does not have a scale intersection, don't do it */
+ if (transform_flag & (ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM)) {
+ const rctf r_xmin = {.xmin = -size[0], .ymin = -size[1], .xmax = -size[0] + margin[0], .ymax = size[1]};
+ const rctf r_xmax = {.xmin = size[0] - margin[0], .ymin = -size[1], .xmax = size[0], .ymax = size[1]};
+ const rctf r_ymin = {.xmin = -size[0], .ymin = -size[1], .xmax = size[0], .ymax = -size[1] + margin[1]};
+ const rctf r_ymax = {.xmin = -size[0], .ymin = size[1] - margin[1], .xmax = size[0], .ymax = size[1]};
+
+ if (BLI_rctf_isect_pt_v(&r_xmin, point_local)) {
+ if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
+ return ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y;
+ }
+ if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
+ return ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y;
+ }
+ return ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X;
+ }
+ if (BLI_rctf_isect_pt_v(&r_xmax, point_local)) {
+ if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
+ return ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y;
+ }
+ if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
+ return ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y;
+ }
+ return ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X;
+ }
+ if (BLI_rctf_isect_pt_v(&r_ymin, point_local)) {
+ return ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y;
+ }
+ if (BLI_rctf_isect_pt_v(&r_ymax, point_local)) {
+ return ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y;
+ }
+ }
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE) {
+ /* Rotate:
+ * (*) <-- hot spot is here!
+ * +---+
+ * | |
+ * +---+ */
+ const float r_rotate_pt[2] = {0.0f, size_real[1] + (margin[1] * MANIPULATOR_MARGIN_OFFSET_SCALE)};
+ const rctf r_rotate = {
+ .xmin = r_rotate_pt[0] - margin[0] / 2.0f,
+ .xmax = r_rotate_pt[0] + margin[0] / 2.0f,
+ .ymin = r_rotate_pt[1] - margin[1] / 2.0f,
+ .ymax = r_rotate_pt[1] + margin[1] / 2.0f,
+ };
+
+ if (BLI_rctf_isect_pt_v(&r_rotate, point_local)) {
+ return ED_MANIPULATOR_CAGE2D_PART_ROTATE;
+ }
+ }
+
+ return -1;
+}
+
+typedef struct RectTransformInteraction {
+ float orig_mouse[2];
+ float orig_matrix_offset[4][4];
+ float orig_matrix_final_no_offset[4][4];
+ Dial *dial;
+} RectTransformInteraction;
+
+static void manipulator_cage2d_setup(wmManipulator *mpr)
+{
+ mpr->flag |= WM_MANIPULATOR_DRAW_MODAL | WM_MANIPULATOR_DRAW_NO_SCALE;
+}
+
+static int manipulator_cage2d_invoke(
+ bContext *C, wmManipulator *mpr, const wmEvent *event)
+{
+ RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction");
+
+ copy_m4_m4(data->orig_matrix_offset, mpr->matrix_offset);
+ manipulator_calc_matrix_final_no_offset(mpr, data->orig_matrix_final_no_offset);
+
+ if (manipulator_window_project_2d(
+ C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, data->orig_mouse) == 0)
+ {
+ zero_v2(data->orig_mouse);
+ }
+
+ mpr->interaction_data = data;
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int manipulator_cage2d_modal(
+ bContext *C, wmManipulator *mpr, const wmEvent *event,
+ eWM_ManipulatorTweak UNUSED(tweak_flag))
+{
+ /* For transform logic to be managable we operate in -0.5..0.5 2D space,
+ * no matter the size of the rectangle, mouse coorts are scaled to unit space.
+ * The mouse coords have been projected into the matrix so we don't need to worry about axis alignment.
+ *
+ * - The cursor offset are multiplied by 'dims'.
+ * - Matrix translation is also multiplied by 'dims'.
+ */
+ RectTransformInteraction *data = mpr->interaction_data;
+ float point_local[2];
+
+ float dims[2];
+ RNA_float_get_array(mpr->ptr, "dimensions", dims);
+
+ {
+ float matrix_back[4][4];
+ copy_m4_m4(matrix_back, mpr->matrix_offset);
+ copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+
+ bool ok = manipulator_window_project_2d(
+ C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, point_local);
+ copy_m4_m4(mpr->matrix_offset, matrix_back);
+ if (!ok) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ const int transform_flag = RNA_enum_get(mpr->ptr, "transform");
+ wmManipulatorProperty *mpr_prop;
+
+ mpr_prop = WM_manipulator_target_property_find(mpr, "matrix");
+ if (mpr_prop->type != NULL) {
+ WM_manipulator_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ }
+
+ if (mpr->highlight_part == ED_MANIPULATOR_CAGE2D_PART_TRANSLATE) {
+ /* do this to prevent clamping from changing size */
+ copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+ mpr->matrix_offset[3][0] = data->orig_matrix_offset[3][0] + (point_local[0] - data->orig_mouse[0]);
+ mpr->matrix_offset[3][1] = data->orig_matrix_offset[3][1] + (point_local[1] - data->orig_mouse[1]);
+ }
+ else if (mpr->highlight_part == ED_MANIPULATOR_CAGE2D_PART_ROTATE) {
+
+#define MUL_V2_V3_M4_FINAL(test_co, mouse_co) \
+ mul_v3_m4v3(test_co, data->orig_matrix_final_no_offset, ((const float[3]){UNPACK2(mouse_co), 0.0}))
+
+ float test_co[3];
+
+ if (data->dial == NULL) {
+ MUL_V2_V3_M4_FINAL(test_co, data->orig_matrix_offset[3]);
+
+ data->dial = BLI_dial_initialize(test_co, FLT_EPSILON);
+
+ MUL_V2_V3_M4_FINAL(test_co, data->orig_mouse);
+ BLI_dial_angle(data->dial, test_co);
+ }
+
+ /* rotate */
+ MUL_V2_V3_M4_FINAL(test_co, point_local);
+ const float angle = BLI_dial_angle(data->dial, test_co);
+
+ float matrix_space_inv[4][4];
+ float matrix_rotate[4][4];
+ float pivot[3];
+
+ copy_v3_v3(pivot, data->orig_matrix_offset[3]);
+
+ invert_m4_m4(matrix_space_inv, mpr->matrix_space);
+
+ unit_m4(matrix_rotate);
+ mul_m4_m4m4(matrix_rotate, matrix_rotate, matrix_space_inv);
+ rotate_m4(matrix_rotate, 'Z', -angle);
+ mul_m4_m4m4(matrix_rotate, matrix_rotate, mpr->matrix_space);
+
+ zero_v3(matrix_rotate[3]);
+ transform_pivot_set_m4(matrix_rotate, pivot);
+
+ mul_m4_m4m4(mpr->matrix_offset, matrix_rotate, data->orig_matrix_offset);
+
+#undef MUL_V2_V3_M4_FINAL
+ }
+ else {
+ /* scale */
+ copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+ float pivot[2];
+ bool constrain_axis[2] = {false};
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ manipulator_rect_pivot_from_scale_part(mpr->highlight_part, pivot, constrain_axis);
+ }
+ else {
+ zero_v2(pivot);
+ }
+
+ /* Cursor deltas scaled to (-0.5..0.5). */
+ float delta_orig[2], delta_curr[2];
+ for (int i = 0; i < 2; i++) {
+ delta_orig[i] = ((data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i];
+ delta_curr[i] = ((point_local[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i];
+ }
+
+ float scale[2] = {1.0f, 1.0f};
+ for (int i = 0; i < 2; i++) {
+ if (constrain_axis[i] == false) {
+ if (delta_orig[i] < 0.0f) {
+ delta_orig[i] *= -1.0f;
+ delta_curr[i] *= -1.0f;
+ }
+ const int sign = signum_i(scale[i]);
+
+ scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i]));
+
+ if ((transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_SIGNED) == 0) {
+ if (sign != signum_i(scale[i])) {
+ scale[i] = 0.0f;
+ }
+ }
+ }
+ }
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM) {
+ if (constrain_axis[0] == false && constrain_axis[1] == false) {
+ scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f;
+ }
+ else if (constrain_axis[0] == false) {
+ scale[1] = scale[0];
+ }
+ else if (constrain_axis[1] == false) {
+ scale[0] = scale[1];
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ /* scale around pivot */
+ float matrix_scale[4][4];
+ unit_m4(matrix_scale);
+
+ mul_v3_fl(matrix_scale[0], scale[0]);
+ mul_v3_fl(matrix_scale[1], scale[1]);
+
+ transform_pivot_set_m4(matrix_scale, (const float [3]){pivot[0] * dims[0], pivot[1] * dims[1], 0.0f});
+ mul_m4_m4m4(mpr->matrix_offset, data->orig_matrix_offset, matrix_scale);
+ }
+
+ if (mpr_prop->type != NULL) {
+ WM_manipulator_target_property_value_set_array(C, mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ }
+
+ /* tag the region for redraw */
+ ED_region_tag_redraw(CTX_wm_region(C));
+ WM_event_add_mousemove(C);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void manipulator_cage2d_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop)
+{
+ if (STREQ(mpr_prop->type->idname, "matrix")) {
+ if (WM_manipulator_target_property_array_length(mpr, mpr_prop) == 16) {
+ WM_manipulator_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+}
+
+static void manipulator_cage2d_exit(bContext *C, wmManipulator *mpr, const bool cancel)
+{
+ RectTransformInteraction *data = mpr->interaction_data;
+
+ MEM_SAFE_FREE(data->dial);
+
+ if (!cancel)
+ return;
+
+ wmManipulatorProperty *mpr_prop;
+
+ /* reset properties */
+ mpr_prop = WM_manipulator_target_property_find(mpr, "matrix");
+ if (mpr_prop->type != NULL) {
+ WM_manipulator_target_property_value_set_array(C, mpr, mpr_prop, &data->orig_matrix_offset[0][0]);
+ }
+
+ copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+}
+
+
+/* -------------------------------------------------------------------- */
+/** \name Cage Manipulator API
+ *
+ * \{ */
+
+static void MANIPULATOR_WT_cage_2d(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_cage_2d";
+
+ /* api callbacks */
+ wt->draw = manipulator_cage2d_draw;
+ wt->draw_select = manipulator_cage2d_draw_select;
+ wt->test_select = manipulator_cage2d_test_select;
+ wt->setup = manipulator_cage2d_setup;
+ wt->invoke = manipulator_cage2d_invoke;
+ wt->property_update = manipulator_cage2d_property_update;
+ wt->modal = manipulator_cage2d_modal;
+ wt->exit = manipulator_cage2d_exit;
+ wt->cursor_get = manipulator_cage2d_get_cursor;
+
+ wt->struct_size = sizeof(wmManipulator);
+
+ /* rna */
+ static EnumPropertyItem rna_enum_draw_style[] = {
+ {ED_MANIPULATOR_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""},
+ {ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem rna_enum_transform[] = {
+ {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Translate", ""},
+ {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE, "ROTATE", 0, "Rotate", ""},
+ {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
+ {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static float unit_v2[2] = {1.0f, 1.0f};
+ RNA_def_float_vector(wt->srna, "dimensions", 2, unit_v2, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
+ RNA_def_enum_flag(wt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
+ RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE, "Draw Style", "");
+ RNA_def_enum_flag(
+ wt->srna, "draw_options", rna_enum_draw_options,
+ ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "Draw Options", "");
+
+ WM_manipulatortype_target_property_def(wt, "matrix", PROP_FLOAT, 16);
+}
+
+void ED_manipulatortypes_cage_2d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_cage_2d);
+}
+
+/** \} */
diff --git a/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c
new file mode 100644
index 00000000000..d58cdb4b187
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_types/cage3d_manipulator.c
@@ -0,0 +1,735 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file cage3d_manipulator.c
+ * \ingroup wm
+ *
+ * \name Cage Manipulator
+ *
+ * 2D Manipulator
+ *
+ * \brief Rectangular manipulator acting as a 'cage' around its content.
+ * Interacting scales or translates the manipulator.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_dial.h"
+#include "BLI_rect.h"
+
+#include "BKE_context.h"
+
+#include "BIF_gl.h"
+
+#include "GPU_matrix.h"
+#include "GPU_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_select.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_manipulator_library.h"
+
+/* own includes */
+#include "../manipulator_library_intern.h"
+
+#define MANIPULATOR_RESIZER_SIZE 10.0f
+#define MANIPULATOR_MARGIN_OFFSET_SCALE 1.5f
+
+static void manipulator_calc_matrix_final_no_offset(
+ const wmManipulator *mpr, float orig_matrix_final_no_offset[4][4], bool use_space)
+{
+ float mat_identity[4][4];
+ struct WM_ManipulatorMatrixParams params = {NULL};
+ unit_m4(mat_identity);
+ if (use_space == false) {
+ params.matrix_basis = mat_identity;
+ }
+ params.matrix_offset = mat_identity;
+ WM_manipulator_calc_matrix_final_params(mpr, &params, orig_matrix_final_no_offset);
+}
+
+static void manipulator_calc_rect_view_scale(
+ const wmManipulator *mpr, const float dims[3], float scale[3])
+{
+ UNUSED_VARS(dims);
+
+ /* Unlike cage2d, no need to correct for aspect. */
+ float matrix_final_no_offset[4][4];
+
+ float x_axis[3], y_axis[3], z_axis[3];
+ manipulator_calc_matrix_final_no_offset(mpr, matrix_final_no_offset, false);
+ mul_v3_mat3_m4v3(x_axis, matrix_final_no_offset, mpr->matrix_offset[0]);
+ mul_v3_mat3_m4v3(y_axis, matrix_final_no_offset, mpr->matrix_offset[1]);
+ mul_v3_mat3_m4v3(z_axis, matrix_final_no_offset, mpr->matrix_offset[2]);
+
+ scale[0] = 1.0f / len_v3(x_axis);
+ scale[1] = 1.0f / len_v3(y_axis);
+ scale[2] = 1.0f / len_v3(z_axis);
+}
+
+static void manipulator_calc_rect_view_margin(
+ const wmManipulator *mpr, const float dims[3], float margin[3])
+{
+ float handle_size;
+ if (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) {
+ handle_size = 0.15f;
+ }
+ else {
+ handle_size = MANIPULATOR_RESIZER_SIZE;
+ }
+ // XXX, the scale isn't taking offset into account, we need to calculate scale per handle!
+ // handle_size *= mpr->scale_final;
+
+ float scale_xyz[3];
+ manipulator_calc_rect_view_scale(mpr, dims, scale_xyz);
+ margin[0] = ((handle_size * scale_xyz[0]));
+ margin[1] = ((handle_size * scale_xyz[1]));
+ margin[2] = ((handle_size * scale_xyz[2]));
+}
+
+/* -------------------------------------------------------------------- */
+
+static void manipulator_rect_pivot_from_scale_part(int part, float r_pt[3], bool r_constrain_axis[3])
+{
+ if (part >= ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z &&
+ part <= ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z)
+ {
+ int index = (part - ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z);
+ int range[3];
+ range[2] = index % 3;
+ index = index / 3;
+ range[1] = index % 3;
+ index = index / 3;
+ range[0] = index % 3;
+
+ const float sign[3] = {-0.5f, 0.0f, 0.5f};
+ for (int i = 0; i < 3; i++) {
+ r_pt[i] = 0.5 * sign[range[i]];
+ r_constrain_axis[i] = (range[i] == 1);
+ }
+ }
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Box Draw Style
+ *
+ * Useful for 3D views, see: #ED_MANIPULATOR_CAGE2D_STYLE_BOX
+ * \{ */
+
+static void cage3d_draw_box_corners(
+ const float r[3], const float margin[3], const float color[3])
+{
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ UNUSED_VARS(margin);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
+ imm_draw_cube_wire_3d(pos, (float[3]){0}, r);
+
+ immUnbindProgram();
+}
+
+static void cage3d_draw_box_interaction(
+ const float color[4], const int highlighted,
+ const float size[3], const float margin[3])
+{
+ if (highlighted >= ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z &&
+ highlighted <= ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z)
+ {
+ int index = (highlighted - ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z);
+ int range[3];
+ range[2] = index % 3;
+ index = index / 3;
+ range[1] = index % 3;
+ index = index / 3;
+ range[0] = index % 3;
+
+ const float sign[3] = {-1.0f, 0.0f, 1.0f};
+ float co[3];
+
+ for (int i = 0; i < 3; i++) {
+ co[i] = size[i] * sign[range[i]];
+ }
+ const float rad[3] = {margin[0] / 3, margin[1] / 3, margin[2] / 3};
+
+ {
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+ imm_draw_cube_fill_3d(pos, co, rad);
+ immUnbindProgram();
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Circle Draw Style
+ *
+ * Useful for 2D views, see: #ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE
+ * \{ */
+
+static void imm_draw_point_aspect_3d(
+ uint pos, const float co[3], const float rad[3], bool solid)
+{
+ if (solid) {
+ imm_draw_cube_fill_3d(pos, co, rad);
+ }
+ else {
+ imm_draw_cube_wire_3d(pos, co, rad);
+ }
+}
+
+static void cage3d_draw_circle_wire(
+ const float r[3], const float margin[3], const float color[3],
+ const int transform_flag, const int draw_options)
+{
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
+ imm_draw_cube_wire_3d(pos, (float[3]){0}, r);
+
+#if 0
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ const float rad[2] = {margin[0] / 2, margin[1] / 2};
+ const float center[2] = {0.0f, 0.0f};
+
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex2f(pos, center[0] - rad[0], center[1] - rad[1]);
+ immVertex2f(pos, center[0] + rad[0], center[1] + rad[1]);
+ immVertex2f(pos, center[0] + rad[0], center[1] - rad[1]);
+ immVertex2f(pos, center[0] - rad[0], center[1] + rad[1]);
+ immEnd();
+ }
+ }
+#else
+ UNUSED_VARS(margin, transform_flag, draw_options);
+#endif
+
+
+ immUnbindProgram();
+}
+
+static void cage3d_draw_circle_handles(
+ const RegionView3D *rv3d, const float matrix_final[4][4],
+ const float r[3], const float margin[3], const float color[3],
+ bool solid, float scale)
+{
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ const float rad[3] = {margin[0] / 3, margin[1] / 3, margin[2] / 3};
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
+
+ float sign[3] = {-1.0f, 0.0f, 1.0f};
+ for (int x = 0; x < 3; x++) {
+ for (int y = 0; y < 3; y++) {
+ for (int z = 0; z < 3; z++) {
+ if (x == 1 && y == 1 && z == 1) {
+ continue;
+ }
+ const float co[3] = {r[0] * sign[x], r[1] * sign[y], r[2] * sign[z]};
+ float co_test[3];
+ mul_v3_m4v3(co_test, matrix_final, co);
+ float rad_scale[3];
+ mul_v3_v3fl(rad_scale, rad, ED_view3d_pixel_size(rv3d, co_test) * scale);
+ imm_draw_point_aspect_3d(pos, co, rad_scale, solid);
+ }
+ }
+ }
+
+ immUnbindProgram();
+}
+
+/** \} */
+
+static void manipulator_cage3d_draw_intern(
+ RegionView3D *rv3d,
+ wmManipulator *mpr, const bool select, const bool highlight, const int select_id)
+{
+ // const bool use_clamp = (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) == 0;
+ float dims[3];
+ RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ float matrix_final[4][4];
+
+ const int transform_flag = RNA_enum_get(mpr->ptr, "transform");
+ const int draw_style = RNA_enum_get(mpr->ptr, "draw_style");
+ const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+
+ const float size_real[3] = {dims[0] / 2.0f, dims[1] / 2.0f, dims[2] / 2.0f};
+
+ WM_manipulator_calc_matrix_final(mpr, matrix_final);
+
+ gpuPushMatrix();
+ gpuMultMatrix(matrix_final);
+
+ float margin[3];
+ manipulator_calc_rect_view_margin(mpr, dims, margin);
+
+ /* Handy for quick testing draw (if it's outside bounds). */
+ if (false) {
+ glEnable(GL_BLEND);
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv((const float[4]){1, 1, 1, 0.5f});
+ float s = 0.5f;
+ immRectf(pos, -s, -s, s, s);
+ immUnbindProgram();
+ glDisable(GL_BLEND);
+ }
+
+ if (select) {
+ /* expand for hotspot */
+#if 0
+ const float size[3] = {
+ size_real[0] + margin[0] / 2,
+ size_real[1] + margin[1] / 2,
+ size_real[2] + margin[2] / 2,
+ };
+#else
+ /* just use same value for now. */
+ const float size[3] = {UNPACK3(size_real)};
+#endif
+
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE) {
+ for (int i = ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
+ i <= ED_MANIPULATOR_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z;
+ i++)
+ {
+ if (i == ED_MANIPULATOR_CAGE3D_PART_SCALE_MID_X_MID_Y_MID_Z) {
+ continue;
+ }
+ GPU_select_load_id(select_id | i);
+ cage3d_draw_box_interaction(
+ mpr->color, i, size, margin);
+ }
+ }
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ const int transform_part = ED_MANIPULATOR_CAGE3D_PART_TRANSLATE;
+ GPU_select_load_id(select_id | transform_part);
+ cage3d_draw_box_interaction(
+ mpr->color, transform_part, size, margin);
+ }
+ }
+ else {
+#if 0
+ const rctf _r = {
+ .xmin = -size_real[0],
+ .ymin = -size_real[1],
+ .xmax = size_real[0],
+ .ymax = size_real[1],
+ };
+#endif
+ if (draw_style == ED_MANIPULATOR_CAGE2D_STYLE_BOX) {
+ /* corner manipulators */
+ glLineWidth(mpr->line_width + 3.0f);
+ cage3d_draw_box_corners(size_real, margin, (const float[3]){0, 0, 0});
+
+ /* corner manipulators */
+ float color[4];
+ manipulator_color_get(mpr, highlight, color);
+ glLineWidth(mpr->line_width);
+ cage3d_draw_box_corners(size_real, margin, color);
+
+ bool show = false;
+ if (mpr->highlight_part == ED_MANIPULATOR_CAGE3D_PART_TRANSLATE) {
+ /* Only show if we're drawing the center handle
+ * otherwise the entire rectangle is the hotspot. */
+ if (draw_options & ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
+ show = true;
+ }
+ }
+ else {
+ show = true;
+ }
+
+ if (show) {
+ cage3d_draw_box_interaction(
+ mpr->color, mpr->highlight_part, size_real, margin);
+ }
+ }
+ else if (draw_style == ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE) {
+ float color[4];
+ manipulator_color_get(mpr, highlight, color);
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_POLYGON_SMOOTH);
+ glEnable(GL_BLEND);
+
+ glLineWidth(mpr->line_width + 3.0f);
+ cage3d_draw_circle_wire(size_real, margin, (const float[3]){0, 0, 0}, transform_flag, draw_options);
+ glLineWidth(mpr->line_width);
+ cage3d_draw_circle_wire(size_real, margin, color, transform_flag, draw_options);
+
+ /* corner manipulators */
+ cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, (const float[3]){0, 0, 0}, true, 60);
+ cage3d_draw_circle_handles(rv3d, matrix_final, size_real, margin, color, true, 40);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_POLYGON_SMOOTH);
+ glDisable(GL_LINE_SMOOTH);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ glLineWidth(1.0);
+ gpuPopMatrix();
+}
+
+/**
+ * For when we want to draw 3d cage in 3d views.
+ */
+static void manipulator_cage3d_draw_select(const bContext *C, wmManipulator *mpr, int select_id)
+{
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ manipulator_cage3d_draw_intern(rv3d, mpr, true, false, select_id);
+}
+
+static void manipulator_cage3d_draw(const bContext *C, wmManipulator *mpr)
+{
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
+ manipulator_cage3d_draw_intern(rv3d, mpr, false, is_highlight, -1);
+}
+
+static int manipulator_cage3d_get_cursor(wmManipulator *mpr)
+{
+ if (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) {
+ return BC_NSEW_SCROLLCURSOR;
+ }
+
+ return CURSOR_STD;
+}
+
+typedef struct RectTransformInteraction {
+ float orig_mouse[2];
+ float orig_matrix_offset[4][4];
+ float orig_matrix_final_no_offset[4][4];
+ Dial *dial;
+} RectTransformInteraction;
+
+static void manipulator_cage3d_setup(wmManipulator *mpr)
+{
+ mpr->flag |= /* WM_MANIPULATOR_DRAW_MODAL | */ /* TODO */
+ WM_MANIPULATOR_DRAW_NO_SCALE;
+}
+
+static int manipulator_cage3d_invoke(
+ bContext *C, wmManipulator *mpr, const wmEvent *event)
+{
+ RectTransformInteraction *data = MEM_callocN(sizeof(RectTransformInteraction), "cage_interaction");
+
+ copy_m4_m4(data->orig_matrix_offset, mpr->matrix_offset);
+ manipulator_calc_matrix_final_no_offset(mpr, data->orig_matrix_final_no_offset, true);
+
+ if (manipulator_window_project_2d(
+ C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, data->orig_mouse) == 0)
+ {
+ zero_v2(data->orig_mouse);
+ }
+
+ mpr->interaction_data = data;
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* XXX. this isn't working properly, for now rely on the modal operators. */
+static int manipulator_cage3d_modal(
+ bContext *C, wmManipulator *mpr, const wmEvent *event,
+ eWM_ManipulatorTweak UNUSED(tweak_flag))
+{
+ /* For transform logic to be managable we operate in -0.5..0.5 2D space,
+ * no matter the size of the rectangle, mouse coorts are scaled to unit space.
+ * The mouse coords have been projected into the matrix so we don't need to worry about axis alignment.
+ *
+ * - The cursor offset are multiplied by 'dims'.
+ * - Matrix translation is also multiplied by 'dims'.
+ */
+ RectTransformInteraction *data = mpr->interaction_data;
+ float point_local[2];
+
+ float dims[3];
+ RNA_float_get_array(mpr->ptr, "dimensions", dims);
+
+ {
+ float matrix_back[4][4];
+ copy_m4_m4(matrix_back, mpr->matrix_offset);
+ copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+
+ bool ok = manipulator_window_project_2d(
+ C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, point_local);
+ copy_m4_m4(mpr->matrix_offset, matrix_back);
+ if (!ok) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+
+ const int transform_flag = RNA_enum_get(mpr->ptr, "transform");
+ wmManipulatorProperty *mpr_prop;
+
+ mpr_prop = WM_manipulator_target_property_find(mpr, "matrix");
+ if (mpr_prop->type != NULL) {
+ WM_manipulator_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ }
+
+ if (mpr->highlight_part == ED_MANIPULATOR_CAGE3D_PART_TRANSLATE) {
+ /* do this to prevent clamping from changing size */
+ copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+ mpr->matrix_offset[3][0] = data->orig_matrix_offset[3][0] + (point_local[0] - data->orig_mouse[0]);
+ mpr->matrix_offset[3][1] = data->orig_matrix_offset[3][1] + (point_local[1] - data->orig_mouse[1]);
+ }
+ else if (mpr->highlight_part == ED_MANIPULATOR_CAGE3D_PART_ROTATE) {
+
+#define MUL_V2_V3_M4_FINAL(test_co, mouse_co) \
+ mul_v3_m4v3(test_co, data->orig_matrix_final_no_offset, ((const float[3]){UNPACK2(mouse_co), 0.0}))
+
+ float test_co[3];
+
+ if (data->dial == NULL) {
+ MUL_V2_V3_M4_FINAL(test_co, data->orig_matrix_offset[3]);
+
+ data->dial = BLI_dial_initialize(test_co, FLT_EPSILON);
+
+ MUL_V2_V3_M4_FINAL(test_co, data->orig_mouse);
+ BLI_dial_angle(data->dial, test_co);
+ }
+
+ /* rotate */
+ MUL_V2_V3_M4_FINAL(test_co, point_local);
+ const float angle = BLI_dial_angle(data->dial, test_co);
+
+ float matrix_space_inv[4][4];
+ float matrix_rotate[4][4];
+ float pivot[3];
+
+ copy_v3_v3(pivot, data->orig_matrix_offset[3]);
+
+ invert_m4_m4(matrix_space_inv, mpr->matrix_space);
+
+ unit_m4(matrix_rotate);
+ mul_m4_m4m4(matrix_rotate, matrix_rotate, matrix_space_inv);
+ rotate_m4(matrix_rotate, 'Z', -angle);
+ mul_m4_m4m4(matrix_rotate, matrix_rotate, mpr->matrix_space);
+
+ zero_v3(matrix_rotate[3]);
+ transform_pivot_set_m4(matrix_rotate, pivot);
+
+ mul_m4_m4m4(mpr->matrix_offset, matrix_rotate, data->orig_matrix_offset);
+
+#undef MUL_V2_V3_M4_FINAL
+ }
+ else {
+ /* scale */
+ copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+ float pivot[3];
+ bool constrain_axis[3] = {false};
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE) {
+ manipulator_rect_pivot_from_scale_part(mpr->highlight_part, pivot, constrain_axis);
+ }
+ else {
+ zero_v3(pivot);
+ }
+
+ /* Cursor deltas scaled to (-0.5..0.5). */
+ float delta_orig[3], delta_curr[3];
+
+ delta_orig[2] = 0.0;
+ delta_curr[2] = 0.0;
+
+ for (int i = 0; i < 2; i++) {
+ delta_orig[i] = ((data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i];
+ delta_curr[i] = ((point_local[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i];
+ }
+
+ float scale[3] = {1.0f, 1.0f, 1.0f};
+ for (int i = 0; i < 3; i++) {
+ if (constrain_axis[i] == false) {
+ if (delta_orig[i] < 0.0f) {
+ delta_orig[i] *= -1.0f;
+ delta_curr[i] *= -1.0f;
+ }
+ const int sign = signum_i(scale[i]);
+
+ scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i]));
+
+ if ((transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_SIGNED) == 0) {
+ if (sign != signum_i(scale[i])) {
+ scale[i] = 0.0f;
+ }
+ }
+ }
+ }
+
+ if (transform_flag & ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM) {
+ if (constrain_axis[0] == false && constrain_axis[1] == false) {
+ scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f;
+ }
+ else if (constrain_axis[0] == false) {
+ scale[1] = scale[0];
+ }
+ else if (constrain_axis[1] == false) {
+ scale[0] = scale[1];
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+
+ /* scale around pivot */
+ float matrix_scale[4][4];
+ unit_m4(matrix_scale);
+
+ mul_v3_fl(matrix_scale[0], scale[0]);
+ mul_v3_fl(matrix_scale[1], scale[1]);
+ mul_v3_fl(matrix_scale[2], scale[2]);
+
+ transform_pivot_set_m4(
+ matrix_scale,
+ (const float [3]){pivot[0] * dims[0], pivot[1] * dims[1], pivot[2] * dims[2]});
+ mul_m4_m4m4(mpr->matrix_offset, data->orig_matrix_offset, matrix_scale);
+ }
+
+ if (mpr_prop->type != NULL) {
+ WM_manipulator_target_property_value_set_array(C, mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ }
+
+ /* tag the region for redraw */
+ ED_region_tag_redraw(CTX_wm_region(C));
+ WM_event_add_mousemove(C);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void manipulator_cage3d_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop)
+{
+ if (STREQ(mpr_prop->type->idname, "matrix")) {
+ if (WM_manipulator_target_property_array_length(mpr, mpr_prop) == 16) {
+ WM_manipulator_target_property_value_get_array(mpr, mpr_prop, &mpr->matrix_offset[0][0]);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+}
+
+static void manipulator_cage3d_exit(bContext *C, wmManipulator *mpr, const bool cancel)
+{
+ RectTransformInteraction *data = mpr->interaction_data;
+
+ MEM_SAFE_FREE(data->dial);
+
+ if (!cancel)
+ return;
+
+ wmManipulatorProperty *mpr_prop;
+
+ /* reset properties */
+ mpr_prop = WM_manipulator_target_property_find(mpr, "matrix");
+ if (mpr_prop->type != NULL) {
+ WM_manipulator_target_property_value_set_array(C, mpr, mpr_prop, &data->orig_matrix_offset[0][0]);
+ }
+
+ copy_m4_m4(mpr->matrix_offset, data->orig_matrix_offset);
+}
+
+
+/* -------------------------------------------------------------------- */
+/** \name Cage Manipulator API
+ *
+ * \{ */
+
+static void MANIPULATOR_WT_cage_3d(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_cage_3d";
+
+ /* api callbacks */
+ wt->draw = manipulator_cage3d_draw;
+ wt->draw_select = manipulator_cage3d_draw_select;
+ wt->setup = manipulator_cage3d_setup;
+ wt->invoke = manipulator_cage3d_invoke;
+ wt->property_update = manipulator_cage3d_property_update;
+ wt->modal = manipulator_cage3d_modal;
+ wt->exit = manipulator_cage3d_exit;
+ wt->cursor_get = manipulator_cage3d_get_cursor;
+
+ wt->struct_size = sizeof(wmManipulator);
+
+ /* rna */
+ static EnumPropertyItem rna_enum_draw_style[] = {
+ {ED_MANIPULATOR_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""},
+ {ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem rna_enum_transform[] = {
+ {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Translate", ""},
+ {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
+ {ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static float unit_v3[3] = {1.0f, 1.0f, 1.0f};
+ RNA_def_float_vector(wt->srna, "dimensions", 3, unit_v3, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
+ RNA_def_enum_flag(wt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");
+ RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_CAGE2D_STYLE_CIRCLE, "Draw Style", "");
+ RNA_def_enum_flag(
+ wt->srna, "draw_options", rna_enum_draw_options,
+ ED_MANIPULATOR_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE, "Draw Options", "");
+
+ WM_manipulatortype_target_property_def(wt, "matrix", PROP_FLOAT, 16);
+}
+
+void ED_manipulatortypes_cage_3d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_cage_3d);
+}
+
+/** \} */
diff --git a/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c
new file mode 100644
index 00000000000..f2f5851ff0c
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c
@@ -0,0 +1,478 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file dial3d_manipulator.c
+ * \ingroup wm
+ *
+ * \name Dial Manipulator
+ *
+ * 3D Manipulator
+ *
+ * \brief Circle shaped manipulator for circular interaction.
+ * Currently no own handling, use with operator only.
+ *
+ * - `matrix[0]` is derived from Y and Z.
+ * - `matrix[1]` is 'up' when DialManipulator.use_start_y_axis is set.
+ * - `matrix[2]` is the axis the dial rotates around (all dials).
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_select.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_manipulator_library.h"
+
+/* own includes */
+#include "../manipulator_geometry.h"
+#include "../manipulator_library_intern.h"
+
+/* to use custom dials exported to geom_dial_manipulator.c */
+// #define USE_MANIPULATOR_CUSTOM_DIAL
+
+static int manipulator_dial_modal(
+ bContext *C, wmManipulator *mpr, const wmEvent *event,
+ eWM_ManipulatorTweak tweak_flag);
+
+typedef struct DialInteraction {
+ float init_mval[2];
+
+ /* only for when using properties */
+ float init_prop_angle;
+
+ /* cache the last angle to detect rotations bigger than -/+ PI */
+ float last_angle;
+ /* number of full rotations */
+ int rotations;
+
+ /* final output values, used for drawing */
+ struct {
+ float angle_ofs;
+ float angle_delta;
+ } output;
+} DialInteraction;
+
+#define DIAL_WIDTH 1.0f
+#define DIAL_RESOLUTION 32
+
+/**
+ * We can't use this for the #wmManipulatorType.matrix_basis_get callback, it conflicts with depth picking.
+ */
+static void dial_calc_matrix(const wmManipulator *mpr, float mat[4][4])
+{
+ float rot[3][3];
+ const float up[3] = {0.0f, 0.0f, 1.0f};
+
+ rotation_between_vecs_to_mat3(rot, up, mpr->matrix_basis[2]);
+ copy_m4_m3(mat, rot);
+ copy_v3_v3(mat[3], mpr->matrix_basis[3]);
+}
+
+/* -------------------------------------------------------------------- */
+
+static void dial_geom_draw(
+ const wmManipulator *mpr, const float color[4], const bool select,
+ float axis_modal_mat[4][4], float clip_plane[4])
+{
+#ifdef USE_MANIPULATOR_CUSTOM_DIAL
+ UNUSED_VARS(dial, col, axis_modal_mat, clip_plane);
+ wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_dial, select);
+#else
+ const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ const bool filled = (draw_options & ED_MANIPULATOR_DIAL_DRAW_FLAG_FILL) != 0;
+
+ glLineWidth(mpr->line_width);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ if (clip_plane) {
+ immBindBuiltinProgram(GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR);
+ float clip_plane_f[4] = {clip_plane[0], clip_plane[1], clip_plane[2], clip_plane[3]};
+ immUniform4fv("ClipPlane", clip_plane_f);
+ immUniformMatrix4fv("ModelMatrix", axis_modal_mat);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+
+ immUniformColor4fv(color);
+
+ if (filled) {
+ imm_draw_circle_fill_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
+ }
+ else {
+ imm_draw_circle_wire_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
+ }
+
+ immUnbindProgram();
+
+ UNUSED_VARS(select);
+#endif
+}
+
+/**
+ * Draws a line from (0, 0, 0) to \a co_outer, at \a angle.
+ */
+static void dial_ghostarc_draw_helpline(const float angle, const float co_outer[3], const float color[4])
+{
+ glLineWidth(1.0f);
+
+ gpuPushMatrix();
+ gpuRotate3f(RAD2DEGF(angle), 0.0f, 0.0f, -1.0f);
+
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ immUniformColor4fv(color);
+
+ immBegin(GWN_PRIM_LINE_STRIP, 2);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immVertex3fv(pos, co_outer);
+ immEnd();
+
+ immUnbindProgram();
+
+ gpuPopMatrix();
+}
+
+static void dial_ghostarc_draw(
+ const wmManipulator *mpr, const float angle_ofs, const float angle_delta, const float color[4])
+{
+ const float width_inner = DIAL_WIDTH - mpr->line_width * 0.5f / U.manipulator_size;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+ imm_draw_disk_partial_fill_2d(
+ pos, 0, 0, 0.0, width_inner, DIAL_RESOLUTION, RAD2DEGF(angle_ofs), RAD2DEGF(angle_delta));
+ immUnbindProgram();
+}
+
+static void dial_ghostarc_get_angles(
+ const wmManipulator *mpr,
+ const wmEvent *event,
+ const ARegion *ar, const View3D *v3d,
+ float mat[4][4], const float co_outer[3],
+ float *r_start, float *r_delta)
+{
+ DialInteraction *inter = mpr->interaction_data;
+ const RegionView3D *rv3d = ar->regiondata;
+ const float mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
+
+ /* we might need to invert the direction of the angles */
+ float view_vec[3], axis_vec[3];
+ ED_view3d_global_to_vector(rv3d, mpr->matrix_basis[3], view_vec);
+ normalize_v3_v3(axis_vec, mpr->matrix_basis[2]);
+
+ float proj_outer_rel[3];
+ mul_v3_project_m4_v3(proj_outer_rel, mat, co_outer);
+ sub_v3_v3(proj_outer_rel, mpr->matrix_basis[3]);
+
+ float proj_mval_new_rel[3];
+ float proj_mval_init_rel[3];
+ float dial_plane[4];
+ float ray_co[3], ray_no[3];
+ float ray_lambda;
+
+ plane_from_point_normal_v3(dial_plane, mpr->matrix_basis[3], axis_vec);
+
+ if (!ED_view3d_win_to_ray(ar, v3d, inter->init_mval, ray_co, ray_no, false) ||
+ !isect_ray_plane_v3(ray_co, ray_no, dial_plane, &ray_lambda, false))
+ {
+ goto fail;
+ }
+ madd_v3_v3v3fl(proj_mval_init_rel, ray_co, ray_no, ray_lambda);
+ sub_v3_v3(proj_mval_init_rel, mpr->matrix_basis[3]);
+
+ if (!ED_view3d_win_to_ray(ar, v3d, mval, ray_co, ray_no, false) ||
+ !isect_ray_plane_v3(ray_co, ray_no, dial_plane, &ray_lambda, false))
+ {
+ goto fail;
+ }
+ madd_v3_v3v3fl(proj_mval_new_rel, ray_co, ray_no, ray_lambda);
+ sub_v3_v3(proj_mval_new_rel, mpr->matrix_basis[3]);
+
+ const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+
+ /* Start direction from mouse or set by user */
+ const float *proj_init_rel =
+ (draw_options & ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y) ?
+ mpr->matrix_basis[1] : proj_mval_init_rel;
+
+ /* return angles */
+ const float start = angle_wrap_rad(angle_signed_on_axis_v3v3_v3(proj_outer_rel, proj_init_rel, axis_vec));
+ const float delta = angle_wrap_rad(angle_signed_on_axis_v3v3_v3(proj_mval_init_rel, proj_mval_new_rel, axis_vec));
+
+ /* Change of sign, we passed the 180 degree threshold. This means we need to add a turn
+ * to distinguish between transition from 0 to -1 and -PI to +PI, use comparison with PI/2.
+ * Logic taken from BLI_dial_angle */
+ if ((delta * inter->last_angle < 0.0f) &&
+ (fabsf(inter->last_angle) > (float)M_PI_2))
+ {
+ if (inter->last_angle < 0.0f)
+ inter->rotations--;
+ else
+ inter->rotations++;
+ }
+ inter->last_angle = delta;
+
+ *r_start = start;
+ *r_delta = fmod(delta + 2.0f * (float)M_PI * inter->rotations, 2 * (float)M_PI);
+ return;
+
+ /* If we can't project (unlikely). */
+fail:
+ *r_start = 0.0;
+ *r_delta = 0.0;
+}
+
+static void dial_draw_intern(
+ const bContext *C, wmManipulator *mpr,
+ const bool select, const bool highlight, float clip_plane[4])
+{
+ float matrix_basis_adjust[4][4];
+ float matrix_final[4][4];
+ float color[4];
+
+ BLI_assert(CTX_wm_area(C)->spacetype == SPACE_VIEW3D);
+
+ manipulator_color_get(mpr, highlight, color);
+
+ dial_calc_matrix(mpr, matrix_basis_adjust);
+
+ WM_manipulator_calc_matrix_final_params(
+ mpr, &((struct WM_ManipulatorMatrixParams) {
+ .matrix_basis = (void *)matrix_basis_adjust,
+ }), matrix_final);
+
+ gpuPushMatrix();
+ gpuMultMatrix(matrix_final);
+
+ /* draw rotation indicator arc first */
+ if ((mpr->flag & WM_MANIPULATOR_DRAW_VALUE) &&
+ (mpr->state & WM_MANIPULATOR_STATE_MODAL))
+ {
+ const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f}; /* coordinate at which the arc drawing will be started */
+
+ DialInteraction *inter = mpr->interaction_data;
+
+ /* XXX, View3D rotation manipulator doesn't call modal. */
+ if (!WM_manipulator_target_property_is_valid_any(mpr)) {
+ wmWindow *win = CTX_wm_window(C);
+ manipulator_dial_modal((bContext *)C, mpr, win->eventstate, 0);
+ }
+
+ float angle_ofs = inter->output.angle_ofs;
+ float angle_delta = inter->output.angle_delta;
+
+ /* draw! */
+ for (int i = 0; i < 2; i++) {
+ dial_ghostarc_draw(mpr, angle_ofs, angle_delta, (const float [4]){0.8f, 0.8f, 0.8f, 0.4f});
+
+ dial_ghostarc_draw_helpline(angle_ofs, co_outer, color); /* starting position */
+ dial_ghostarc_draw_helpline(angle_ofs + angle_delta, co_outer, color); /* starting position + current value */
+
+ if (i == 0) {
+ const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ if ((draw_options & ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR) == 0) {
+ break;
+ }
+ }
+
+ angle_ofs += (float)M_PI;
+ }
+ }
+
+ /* draw actual dial manipulator */
+ dial_geom_draw(mpr, color, select, matrix_basis_adjust, clip_plane);
+
+ gpuPopMatrix();
+}
+
+static void manipulator_dial_draw_select(const bContext *C, wmManipulator *mpr, int select_id)
+{
+ float clip_plane_buf[4];
+ const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ float *clip_plane = (draw_options & ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP) ? clip_plane_buf : NULL;
+
+ /* enable clipping if needed */
+ if (clip_plane) {
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ copy_v3_v3(clip_plane, rv3d->viewinv[2]);
+ clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]);
+ glEnable(GL_CLIP_DISTANCE0);
+ }
+
+ GPU_select_load_id(select_id);
+ dial_draw_intern(C, mpr, true, false, clip_plane);
+
+ if (clip_plane) {
+ glDisable(GL_CLIP_DISTANCE0);
+ }
+}
+
+static void manipulator_dial_draw(const bContext *C, wmManipulator *mpr)
+{
+ const bool is_modal = mpr->state & WM_MANIPULATOR_STATE_MODAL;
+ const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
+ float clip_plane_buf[4];
+ const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ float *clip_plane = (!is_modal && (draw_options & ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP)) ? clip_plane_buf : NULL;
+
+ /* enable clipping if needed */
+ if (clip_plane) {
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ copy_v3_v3(clip_plane, rv3d->viewinv[2]);
+ clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]);
+ clip_plane[3] -= 0.02f * mpr->scale_final;
+
+ glEnable(GL_CLIP_DISTANCE0);
+ }
+
+ glEnable(GL_BLEND);
+ dial_draw_intern(C, mpr, false, is_highlight, clip_plane);
+ glDisable(GL_BLEND);
+
+ if (clip_plane) {
+ glDisable(GL_CLIP_DISTANCE0);
+ }
+}
+
+static int manipulator_dial_modal(
+ bContext *C, wmManipulator *mpr, const wmEvent *event,
+ eWM_ManipulatorTweak UNUSED(tweak_flag))
+{
+ const float co_outer[4] = {0.0f, DIAL_WIDTH, 0.0f}; /* coordinate at which the arc drawing will be started */
+ float angle_ofs, angle_delta;
+
+ float matrix[4][4];
+
+ dial_calc_matrix(mpr, matrix);
+
+ dial_ghostarc_get_angles(
+ mpr, event, CTX_wm_region(C), CTX_wm_view3d(C), matrix, co_outer, &angle_ofs, &angle_delta);
+
+ DialInteraction *inter = mpr->interaction_data;
+
+ inter->output.angle_delta = angle_delta;
+ inter->output.angle_ofs = angle_ofs;
+
+ /* set the property for the operator and call its modal function */
+ wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset");
+ if (WM_manipulator_target_property_is_valid(mpr_prop)) {
+ WM_manipulator_target_property_value_set(C, mpr, mpr_prop, inter->init_prop_angle + angle_delta);
+ }
+ return OPERATOR_RUNNING_MODAL;
+}
+
+
+static void manipulator_dial_setup(wmManipulator *mpr)
+{
+ const float dir_default[3] = {0.0f, 0.0f, 1.0f};
+
+ /* defaults */
+ copy_v3_v3(mpr->matrix_basis[2], dir_default);
+}
+
+static int manipulator_dial_invoke(
+ bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event)
+{
+ DialInteraction *inter = MEM_callocN(sizeof(DialInteraction), __func__);
+
+ inter->init_mval[0] = event->mval[0];
+ inter->init_mval[1] = event->mval[1];
+
+ wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset");
+ if (WM_manipulator_target_property_is_valid(mpr_prop)) {
+ inter->init_prop_angle = WM_manipulator_target_property_value_get(mpr, mpr_prop);
+ }
+
+ mpr->interaction_data = inter;
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Dial Manipulator API
+ *
+ * \{ */
+
+static void MANIPULATOR_WT_dial_3d(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_dial_3d";
+
+ /* api callbacks */
+ wt->draw = manipulator_dial_draw;
+ wt->draw_select = manipulator_dial_draw_select;
+ wt->setup = manipulator_dial_setup;
+ wt->invoke = manipulator_dial_invoke;
+ wt->modal = manipulator_dial_modal;
+
+ wt->struct_size = sizeof(wmManipulator);
+
+ /* rna */
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP, "CLIP", 0, "Clipped", ""},
+ {ED_MANIPULATOR_DIAL_DRAW_FLAG_FILL, "FILL", 0, "Filled", ""},
+ {ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR, "ANGLE_MIRROR", 0, "Angle Mirror", ""},
+ {ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y, "ANGLE_START_Y", 0, "Angle Start Y", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+
+ WM_manipulatortype_target_property_def(wt, "offset", PROP_FLOAT, 1);
+}
+
+void ED_manipulatortypes_dial_3d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_dial_3d);
+}
+
+/** \} */
diff --git a/source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c
new file mode 100644
index 00000000000..151e173e5e6
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_types/grab3d_manipulator.c
@@ -0,0 +1,373 @@
+/*
+ * ***** 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 grab3d_manipulator.c
+ * \ingroup wm
+ *
+ * \name Grab Manipulator
+ *
+ * 3D Manipulator, also works in 2D views.
+ *
+ * \brief Simple manipulator to grab and translate.
+ *
+ * - `matrix[0]` is derived from Y and Z.
+ * - `matrix[1]` currently not used.
+ * - `matrix[2]` is the widget direction (for all manipulators).
+ *
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_select.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_manipulator_library.h"
+
+/* own includes */
+#include "../manipulator_geometry.h"
+#include "../manipulator_library_intern.h"
+
+typedef struct GrabManipulator3D {
+ wmManipulator manipulator;
+ /* Added to 'matrix_basis' when calculating the matrix. */
+ float prop_co[3];
+} GrabManipulator3D;
+
+static void manipulator_grab_matrix_basis_get(const wmManipulator *mpr, float r_matrix[4][4])
+{
+ GrabManipulator3D *grab = (GrabManipulator3D *)mpr;
+
+ copy_m4_m4(r_matrix, grab->manipulator.matrix_basis);
+ add_v3_v3(r_matrix[3], grab->prop_co);
+}
+
+static int manipulator_grab_modal(
+ bContext *C, wmManipulator *mpr, const wmEvent *event,
+ eWM_ManipulatorTweak tweak_flag);
+
+typedef struct GrabInteraction {
+ float init_mval[2];
+
+ /* only for when using properties */
+ float init_prop_co[3];
+
+ float init_matrix_final[4][4];
+} GrabInteraction;
+
+#define DIAL_RESOLUTION 32
+
+/* -------------------------------------------------------------------- */
+
+static void grab_geom_draw(
+ const wmManipulator *mpr, const float color[4], const bool select, const int draw_options)
+{
+#ifdef USE_MANIPULATOR_CUSTOM_DIAL
+ UNUSED_VARS(grab3d, col, axis_modal_mat);
+ wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_grab3d, select);
+#else
+ const int draw_style = RNA_enum_get(mpr->ptr, "draw_style");
+ const bool filled = (draw_options & ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL) != 0;
+
+ glLineWidth(mpr->line_width);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ immUniformColor4fv(color);
+
+ if (draw_style == ED_MANIPULATOR_GRAB_STYLE_RING_2D) {
+ if (filled) {
+ imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION);
+ }
+ else {
+ imm_draw_circle_wire_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION);
+ }
+ }
+ else if (draw_style == ED_MANIPULATOR_GRAB_STYLE_CROSS_2D) {
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex2f(pos, 1.0f, 1.0f);
+ immVertex2f(pos, -1.0f, -1.0f);
+
+ immVertex2f(pos, -1.0f, 1.0f);
+ immVertex2f(pos, 1.0f, -1.0f);
+ immEnd();
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ immUnbindProgram();
+
+ UNUSED_VARS(select);
+#endif
+}
+
+static void grab3d_get_translate(
+ const wmManipulator *mpr, const wmEvent *event, const ARegion *ar,
+ float co_delta[3])
+{
+ GrabInteraction *inter = mpr->interaction_data;
+ const float mval_delta[2] = {
+ event->mval[0] - inter->init_mval[0],
+ event->mval[1] - inter->init_mval[1],
+ };
+
+ RegionView3D *rv3d = ar->regiondata;
+ float co_ref[3];
+ mul_v3_mat3_m4v3(co_ref, mpr->matrix_space, inter->init_prop_co);
+ const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL);
+
+ ED_view3d_win_to_delta(ar, mval_delta, co_delta, zfac);
+
+ float matrix_space_inv[3][3];
+ copy_m3_m4(matrix_space_inv, mpr->matrix_space);
+ invert_m3(matrix_space_inv);
+ mul_m3_v3(matrix_space_inv, co_delta);
+}
+
+static void grab3d_draw_intern(
+ const bContext *C, wmManipulator *mpr,
+ const bool select, const bool highlight)
+{
+ GrabInteraction *inter = mpr->interaction_data;
+ const int draw_options = RNA_enum_get(mpr->ptr, "draw_options");
+ const bool align_view = (draw_options & ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW) != 0;
+ float color[4];
+ float matrix_final[4][4];
+ float matrix_align[4][4];
+
+ manipulator_color_get(mpr, highlight, color);
+ WM_manipulator_calc_matrix_final(mpr, matrix_final);
+
+ gpuPushMatrix();
+ gpuMultMatrix(matrix_final);
+
+ if (align_view) {
+ float matrix_final_unit[4][4];
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ normalize_m4_m4(matrix_final_unit, matrix_final);
+ mul_m4_m4m4(matrix_align, rv3d->viewmat, matrix_final_unit);
+ zero_v3(matrix_align[3]);
+ transpose_m4(matrix_align);
+ gpuMultMatrix(matrix_align);
+ }
+
+ glEnable(GL_BLEND);
+ grab_geom_draw(mpr, color, select, draw_options);
+ glDisable(GL_BLEND);
+ gpuPopMatrix();
+
+ if (mpr->interaction_data) {
+ gpuPushMatrix();
+ gpuMultMatrix(inter->init_matrix_final);
+
+ if (align_view) {
+ gpuMultMatrix(matrix_align);
+ }
+
+ glEnable(GL_BLEND);
+ grab_geom_draw(mpr, (const float [4]){0.5f, 0.5f, 0.5f, 0.5f}, select, draw_options);
+ glDisable(GL_BLEND);
+ gpuPopMatrix();
+ }
+}
+
+static void manipulator_grab_draw_select(const bContext *C, wmManipulator *mpr, int select_id)
+{
+ GPU_select_load_id(select_id);
+ grab3d_draw_intern(C, mpr, true, false);
+}
+
+static void manipulator_grab_draw(const bContext *C, wmManipulator *mpr)
+{
+ const bool is_modal = mpr->state & WM_MANIPULATOR_STATE_MODAL;
+ const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
+
+ (void)is_modal;
+
+ glEnable(GL_BLEND);
+ grab3d_draw_intern(C, mpr, false, is_highlight);
+ glDisable(GL_BLEND);
+}
+
+static int manipulator_grab_modal(
+ bContext *C, wmManipulator *mpr, const wmEvent *event,
+ eWM_ManipulatorTweak UNUSED(tweak_flag))
+{
+ GrabManipulator3D *grab = (GrabManipulator3D *)mpr;
+ GrabInteraction *inter = mpr->interaction_data;
+ ARegion *ar = CTX_wm_region(C);
+
+ float prop_delta[3];
+ if (CTX_wm_area(C)->spacetype == SPACE_VIEW3D) {
+ grab3d_get_translate(mpr, event, ar, prop_delta);
+ }
+ else {
+ float mval_proj_init[2], mval_proj_curr[2];
+ if ((manipulator_window_project_2d(
+ C, mpr, inter->init_mval, 2, false, mval_proj_init) == false) ||
+ (manipulator_window_project_2d(
+ C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, false, mval_proj_curr) == false))
+ {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ sub_v2_v2v2(prop_delta, mval_proj_curr, mval_proj_init);
+ prop_delta[2] = 0.0f;
+ }
+ add_v3_v3v3(grab->prop_co, inter->init_prop_co, prop_delta);
+
+ /* set the property for the operator and call its modal function */
+ wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset");
+ if (WM_manipulator_target_property_is_valid(mpr_prop)) {
+ WM_manipulator_target_property_value_set_array(C, mpr, mpr_prop, grab->prop_co);
+ }
+ else {
+ zero_v3(grab->prop_co);
+ }
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int manipulator_grab_invoke(
+ bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event)
+{
+ GrabInteraction *inter = MEM_callocN(sizeof(GrabInteraction), __func__);
+
+ inter->init_mval[0] = event->mval[0];
+ inter->init_mval[1] = event->mval[1];
+
+#if 0
+ copy_v3_v3(inter->init_prop_co, grab->prop_co);
+#else
+ wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_find(mpr, "offset");
+ if (WM_manipulator_target_property_is_valid(mpr_prop)) {
+ WM_manipulator_target_property_value_get_array(mpr, mpr_prop, inter->init_prop_co);
+ }
+#endif
+
+ WM_manipulator_calc_matrix_final(mpr, inter->init_matrix_final);
+
+ mpr->interaction_data = inter;
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+
+static int manipulator_grab_test_select(
+ bContext *C, wmManipulator *mpr, const wmEvent *event)
+{
+ float point_local[2];
+
+ if (manipulator_window_project_2d(
+ C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, true, point_local) == false)
+ {
+ return -1;
+ }
+
+ if (len_squared_v2(point_local) < SQUARE(mpr->scale_final)) {
+ return 0;
+ }
+
+ return -1;
+}
+
+static void manipulator_grab_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop)
+{
+ GrabManipulator3D *grab = (GrabManipulator3D *)mpr;
+ if (WM_manipulator_target_property_is_valid(mpr_prop)) {
+ WM_manipulator_target_property_value_get_array(mpr, mpr_prop, grab->prop_co);
+ }
+ else {
+ zero_v3(grab->prop_co);
+ }
+}
+
+static int manipulator_grab_cursor_get(wmManipulator *UNUSED(mpr))
+{
+ return BC_HANDCURSOR;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Grab Manipulator API
+ *
+ * \{ */
+
+static void MANIPULATOR_WT_grab_3d(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_grab_3d";
+
+ /* api callbacks */
+ wt->draw = manipulator_grab_draw;
+ wt->draw_select = manipulator_grab_draw_select;
+ wt->test_select = manipulator_grab_test_select;
+ wt->matrix_basis_get = manipulator_grab_matrix_basis_get;
+ wt->invoke = manipulator_grab_invoke;
+ wt->property_update = manipulator_grab_property_update;
+ wt->modal = manipulator_grab_modal;
+ wt->cursor_get = manipulator_grab_cursor_get;
+
+ wt->struct_size = sizeof(GrabManipulator3D);
+
+ /* rna */
+ static EnumPropertyItem rna_enum_draw_style[] = {
+ {ED_MANIPULATOR_GRAB_STYLE_RING_2D, "RING_2D", 0, "Ring", ""},
+ {ED_MANIPULATOR_GRAB_STYLE_CROSS_2D, "CROSS_2D", 0, "Ring", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem rna_enum_draw_options[] = {
+ {ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL, "FILL", 0, "Filled", ""},
+ {ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW, "ALIGN_VIEW", 0, "Align View", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_GRAB_STYLE_RING_2D, "Draw Style", "");
+ RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+
+ WM_manipulatortype_target_property_def(wt, "offset", PROP_FLOAT, 3);
+}
+
+void ED_manipulatortypes_grab_3d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_grab_3d);
+}
+
+/** \} */ // Grab Manipulator API
diff --git a/source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c
new file mode 100644
index 00000000000..531cf742e6f
--- /dev/null
+++ b/source/blender/editors/manipulator_library/manipulator_types/primitive3d_manipulator.c
@@ -0,0 +1,190 @@
+/*
+ * ***** 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 primitive3d_manipulator.c
+ * \ingroup wm
+ *
+ * \name Primitive Manipulator
+ *
+ * 3D Manipulator
+ *
+ * \brief Manipulator with primitive drawing type (plane, cube, etc.).
+ * Currently only plane primitive supported without own handling, use with operator only.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "DNA_view3d_types.h"
+
+#include "BKE_context.h"
+
+#include "BIF_gl.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_select.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_manipulator_library.h"
+
+/* own includes */
+#include "../manipulator_library_intern.h"
+
+static float verts_plane[4][3] = {
+ {-1, -1, 0},
+ { 1, -1, 0},
+ { 1, 1, 0},
+ {-1, 1, 0},
+};
+
+
+/* -------------------------------------------------------------------- */
+
+static void manipulator_primitive_draw_geom(
+ const float col_inner[4], const float col_outer[4], const int draw_style)
+{
+ float (*verts)[3];
+ uint vert_count = 0;
+
+ if (draw_style == ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE) {
+ verts = verts_plane;
+ vert_count = ARRAY_SIZE(verts_plane);
+ }
+
+ if (vert_count > 0) {
+ uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ wm_manipulator_vec_draw(col_inner, verts, vert_count, pos, GWN_PRIM_TRI_FAN);
+ wm_manipulator_vec_draw(col_outer, verts, vert_count, pos, GWN_PRIM_LINE_LOOP);
+ immUnbindProgram();
+ }
+}
+
+static void manipulator_primitive_draw_intern(
+ wmManipulator *mpr, const bool UNUSED(select),
+ const bool highlight)
+{
+ float color_inner[4], color_outer[4];
+ float matrix_final[4][4];
+ const int draw_style = RNA_enum_get(mpr->ptr, "draw_style");
+
+ manipulator_color_get(mpr, highlight, color_outer);
+ copy_v4_v4(color_inner, color_outer);
+ color_inner[3] *= 0.5f;
+
+ WM_manipulator_calc_matrix_final(mpr, matrix_final);
+
+ gpuPushMatrix();
+ gpuMultMatrix(matrix_final);
+
+ glEnable(GL_BLEND);
+ manipulator_primitive_draw_geom(color_inner, color_outer, draw_style);
+ glDisable(GL_BLEND);
+
+ gpuPopMatrix();
+
+ if (mpr->interaction_data) {
+ ManipulatorInteraction *inter = mpr->interaction_data;
+
+ copy_v4_fl(color_inner, 0.5f);
+ copy_v3_fl(color_outer, 0.5f);
+ color_outer[3] = 0.8f;
+
+ gpuPushMatrix();
+ gpuMultMatrix(inter->init_matrix_final);
+
+ glEnable(GL_BLEND);
+ manipulator_primitive_draw_geom(color_inner, color_outer, draw_style);
+ glDisable(GL_BLEND);
+
+ gpuPopMatrix();
+ }
+}
+
+static void manipulator_primitive_draw_select(
+ const bContext *UNUSED(C), wmManipulator *mpr,
+ int select_id)
+{
+ GPU_select_load_id(select_id);
+ manipulator_primitive_draw_intern(mpr, true, false);
+}
+
+static void manipulator_primitive_draw(const bContext *UNUSED(C), wmManipulator *mpr)
+{
+ manipulator_primitive_draw_intern(
+ mpr, false,
+ (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT));
+}
+
+static void manipulator_primitive_setup(wmManipulator *mpr)
+{
+ mpr->flag |= WM_MANIPULATOR_DRAW_MODAL;
+}
+
+static int manipulator_primitive_invoke(
+ bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *UNUSED(event))
+{
+ ManipulatorInteraction *inter = MEM_callocN(sizeof(ManipulatorInteraction), __func__);
+
+ WM_manipulator_calc_matrix_final(mpr, inter->init_matrix_final);
+
+ mpr->interaction_data = inter;
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Primitive Manipulator API
+ *
+ * \{ */
+
+static void MANIPULATOR_WT_primitive_3d(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "MANIPULATOR_WT_primitive_3d";
+
+ /* api callbacks */
+ wt->draw = manipulator_primitive_draw;
+ wt->draw_select = manipulator_primitive_draw_select;
+ wt->setup = manipulator_primitive_setup;
+ wt->invoke = manipulator_primitive_invoke;
+
+ wt->struct_size = sizeof(wmManipulator);
+
+ static EnumPropertyItem rna_enum_draw_style[] = {
+ {ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE, "PLANE", 0, "Plane", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE, "Draw Style", "");
+}
+
+void ED_manipulatortypes_primitive_3d(void)
+{
+ WM_manipulatortype_append(MANIPULATOR_WT_primitive_3d);
+}
+
+/** \} */
diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt
index 033d034cf4e..d17df344dc9 100644
--- a/source/blender/editors/mask/CMakeLists.txt
+++ b/source/blender/editors/mask/CMakeLists.txt
@@ -25,6 +25,7 @@ set(INC
../include
../../blenkernel
../../blenlib
+ ../../depsgraph
../../gpu
../../makesdna
../../makesrna
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 69335195b96..ad1a567f843 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -34,9 +34,10 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_mask.h"
+#include "DEG_depsgraph.h"
+
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_mask_types.h"
@@ -692,7 +693,7 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 407c19a3860..c60b673ec69 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -36,6 +36,7 @@
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_task.h"
+#include "BLI_listbase.h"
#include "BKE_context.h"
#include "BKE_mask.h"
@@ -48,10 +49,13 @@
#include "ED_clip.h"
#include "ED_mask.h" /* own include */
#include "ED_space_api.h"
-#include "BIF_gl.h"
+
#include "BIF_glutil.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
+#include "GPU_shader.h"
+#include "GPU_matrix.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -93,40 +97,6 @@ static void mask_spline_feather_color_get(MaskLayer *UNUSED(masklay), MaskSpline
r_rgb[3] = 255;
}
-#if 0
-static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline)
-{
- int i;
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
-
- if (!spline->tot_point)
- return;
-
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(1, 0xAAAA);
-
- glColor3ub(0, 0, 0);
- glBegin(GL_LINES);
-
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &points_array[i];
- BezTriple *bezt = &point->bezt;
-
- if (point->parent.id) {
- glVertex2f(bezt->vec[1][0],
- bezt->vec[1][1]);
-
- glVertex2f(bezt->vec[1][0] - point->parent.offset[0],
- bezt->vec[1][1] - point->parent.offset[1]);
- }
- }
-
- glEnd();
-
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
-}
-#endif
-
static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2])
{
BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
@@ -134,46 +104,9 @@ static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float c
BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
}
-static void draw_circle(const float x, const float y,
- const float size, const bool fill,
- const float xscale, const float yscale)
-{
- static GLuint wire_displist = 0;
- static GLuint fill_displist = 0;
- GLuint displist = fill ? fill_displist : wire_displist;
-
- /* Initialize round circle shape. */
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, fill ? GLU_FILL : GLU_SILHOUETTE);
- gluDisk(qobj, 0, 0.7, 8, 1);
- gluDeleteQuadric(qobj);
-
- glEndList();
-
- if (fill) {
- fill_displist = displist;
- }
- else {
- wire_displist = displist;
- }
- }
-
- glPushMatrix();
- glTranslatef(x, y, 0.0f);
- glScalef(1.0f / xscale * size, 1.0f / yscale * size, 1.0f);
- glCallList(displist);
- glPopMatrix();
-}
-
static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoint *point,
const eMaskWhichHandle which_handle, const int draw_type,
- const float handle_size, const float xscale, const float yscale,
+ const float handle_size,
const float point_pos[2], const float handle_pos[2])
{
const BezTriple *bezt = &point->bezt;
@@ -190,54 +123,70 @@ static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoin
return;
}
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ubv(rgb_gray);
+
/* this could be split into its own loop */
if (draw_type == MASK_DT_OUTLINE) {
- const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
- glLineWidth(3);
- glColor4ubv(rgb_gray);
- glBegin(GL_LINES);
- glVertex2fv(point_pos);
- glVertex2fv(handle_pos);
- glEnd();
+ glLineWidth(3.0f);
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(pos, point_pos);
+ immVertex2fv(pos, handle_pos);
+ immEnd();
}
switch (handle_type) {
case HD_FREE:
- UI_ThemeColor(TH_HANDLE_FREE);
+ immUniformThemeColor(TH_HANDLE_FREE);
break;
case HD_AUTO:
- UI_ThemeColor(TH_HANDLE_AUTO);
+ immUniformThemeColor(TH_HANDLE_AUTO);
break;
case HD_ALIGN:
case HD_ALIGN_DOUBLESIDE:
- UI_ThemeColor(TH_HANDLE_ALIGN);
+ immUniformThemeColor(TH_HANDLE_ALIGN);
break;
}
- glLineWidth(1);
- glBegin(GL_LINES);
- glVertex2fv(point_pos);
- glVertex2fv(handle_pos);
- glEnd();
+ glLineWidth(1.0f);
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(pos, point_pos);
+ immVertex2fv(pos, handle_pos);
+ immEnd();
+ immUnbindProgram();
/* draw handle points */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+ immUniform1f("size", handle_size);
+ immUniform1f("outlineWidth", 1.5f);
+
+ float point_color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; /* active color by default */
if (MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
- if (point == mask_layer->act_point)
- glColor3f(1.0f, 1.0f, 1.0f);
- else
- UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
+ if (point != mask_layer->act_point) {
+ UI_GetThemeColor3fv(TH_HANDLE_VERTEX_SELECT, point_color);
+ }
}
else {
- UI_ThemeColor(TH_HANDLE_VERTEX);
+ UI_GetThemeColor3fv(TH_HANDLE_VERTEX, point_color);
}
- draw_circle(handle_pos[0], handle_pos[1], handle_size, false, xscale, yscale);
+ immUniform4fv("outlineColor", point_color);
+ immUniformColor3fvAlpha(point_color, 0.25f);
+
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex2fv(pos, handle_pos);
+ immEnd();
+
+ immUnbindProgram();
}
/* return non-zero if spline is selected */
static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline,
- const char draw_flag, const char draw_type,
- const float xscale, const float yscale)
+ const char draw_flag, const char draw_type)
{
const bool is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0;
@@ -247,7 +196,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
SpaceClip *sc = CTX_wm_space_clip(C);
bool undistort = false;
- int i, handle_size, tot_feather_point;
+ int tot_feather_point;
float (*feather_points)[2], (*fp)[2];
float min[2], max[2];
@@ -258,22 +207,24 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
/* TODO, add this to sequence editor */
- handle_size = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
-
- glPointSize(handle_size);
+ float handle_size = 2.0f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+ immUniform1f("size", 0.7f * handle_size);
+
/* feather points */
feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
- for (i = 0; i < spline->tot_point; i++) {
+ for (int i = 0; i < spline->tot_point; i++) {
/* watch it! this is intentionally not the deform array, only check for sel */
MaskSplinePoint *point = &spline->points[i];
- int j;
-
- for (j = 0; j <= point->tot_uw; j++) {
+ for (int j = 0; j <= point->tot_uw; j++) {
float feather_point[2];
bool sel = false;
@@ -291,32 +242,32 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
if (sel) {
if (point == masklay->act_point)
- glColor3f(1.0f, 1.0f, 1.0f);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
else
- UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
+ immUniformThemeColor(TH_HANDLE_VERTEX_SELECT);
}
else {
- UI_ThemeColor(TH_HANDLE_VERTEX);
+ immUniformThemeColor(TH_HANDLE_VERTEX);
}
- glBegin(GL_POINTS);
- glVertex2fv(feather_point);
- glEnd();
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex2fv(pos, feather_point);
+ immEnd();
fp++;
}
}
MEM_freeN(feather_points);
+ immUnbindProgram();
+
if (is_smooth) {
glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
/* control points */
INIT_MINMAX2(min, max);
- for (i = 0; i < spline->tot_point; i++) {
+ for (int i = 0; i < spline->tot_point; i++) {
/* watch it! this is intentionally not the deform array, only check for sel */
MaskSplinePoint *point = &spline->points[i];
@@ -339,7 +290,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
mask_point_undistort_pos(sc, handle, handle);
}
draw_single_handle(masklay, point, MASK_WHICH_HANDLE_STICK,
- draw_type, handle_size, xscale, yscale, vert, handle);
+ draw_type, handle_size, vert, handle);
}
else {
float handle_left[2], handle_right[2];
@@ -350,53 +301,62 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
mask_point_undistort_pos(sc, handle_left, handle_left);
}
draw_single_handle(masklay, point, MASK_WHICH_HANDLE_LEFT,
- draw_type, handle_size, xscale, yscale, vert, handle_left);
+ draw_type, handle_size, vert, handle_left);
draw_single_handle(masklay, point, MASK_WHICH_HANDLE_RIGHT,
- draw_type, handle_size, xscale, yscale, vert, handle_right);
+ draw_type, handle_size, vert, handle_right);
}
+ /* bind program in loop so it does not interfere with draw_single_handle */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+
/* draw CV point */
if (MASKPOINT_ISSEL_KNOT(point)) {
if (point == masklay->act_point)
- glColor3f(1.0f, 1.0f, 1.0f);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
else
- UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
+ immUniformThemeColor(TH_HANDLE_VERTEX_SELECT);
}
else
- UI_ThemeColor(TH_HANDLE_VERTEX);
+ immUniformThemeColor(TH_HANDLE_VERTEX);
+
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex2fv(pos, vert);
+ immEnd();
- glBegin(GL_POINTS);
- glVertex2fv(vert);
- glEnd();
+ immUnbindProgram();
minmax_v2v2_v2(min, max, vert);
}
+ if (is_smooth) {
+ glDisable(GL_LINE_SMOOTH);
+ }
+
if (is_spline_sel) {
- float x = (min[0] + max[0]) / 2.0f;
- float y = (min[1] + max[1]) / 2.0f;
- /* TODO(sergey): Remove hardcoded colors. */
+ float x = (min[0] + max[0]) * 0.5f;
+ float y = (min[1] + max[1]) * 0.5f;
+
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+ immUniform1f("outlineWidth", 1.5f);
+
if (masklay->act_spline == spline) {
- glColor3ub(255, 255, 255);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
}
else {
- glColor3ub(255, 255, 0);
+ immUniformColor3f(1.0f, 1.0f, 0.0f);
}
- draw_circle(x, y, 6.0f, true, xscale, yscale);
+ immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 1.0f);
+ immUniform1f("size", 12.0f);
- glColor3ub(0, 0, 0);
- draw_circle(x, y, 6.0f, false, xscale, yscale);
- }
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex2f(pos, x, y);
+ immEnd();
- if (is_smooth) {
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ immUnbindProgram();
}
}
-/* #define USE_XOR */
-
static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char rgb[4], const bool is_active)
{
if (!is_active) {
@@ -410,13 +370,21 @@ static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char r
}
}
+static void mask_draw_array(unsigned int pos, Gwn_PrimType prim_type, const float (*points)[2], unsigned int vertex_ct)
+{
+ immBegin(prim_type, vertex_ct);
+ for (unsigned int i = 0; i < vertex_ct; ++i) {
+ immVertex2fv(pos, points[i]);
+ }
+ immEnd();
+}
+
static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*orig_points)[2], int tot_point,
- const bool is_feather, const bool is_smooth, const bool is_active,
+ const bool is_feather, const bool is_active,
const unsigned char rgb_spline[4], const char draw_type)
{
- const int draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GL_LINE_LOOP : GL_LINE_STRIP;
+ const Gwn_PrimType draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GWN_PRIM_LINE_LOOP : GWN_PRIM_LINE_STRIP;
const unsigned char rgb_black[4] = {0x00, 0x00, 0x00, 0xff};
-// const unsigned char rgb_white[4] = {0xff, 0xff, 0xff, 0xff};
unsigned char rgb_tmp[4];
SpaceClip *sc = CTX_wm_space_clip(C);
float (*points)[2] = orig_points;
@@ -425,65 +393,45 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
const bool undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
if (undistort) {
- int i;
-
points = MEM_callocN(2 * tot_point * sizeof(float), "undistorthed mask curve");
- for (i = 0; i < tot_point; i++) {
+ for (int i = 0; i < tot_point; i++) {
mask_point_undistort_pos(sc, points[i], orig_points[i]);
}
}
}
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, points);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
switch (draw_type) {
case MASK_DT_OUTLINE:
- glLineWidth(3);
-
- mask_color_active_tint(rgb_tmp, rgb_black, is_active);
- glColor4ubv(rgb_tmp);
-
- glDrawArrays(draw_method, 0, tot_point);
+ /* TODO(merwin): use fancy line shader here
+ * probably better with geometry shader (after core profile switch)
+ */
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glLineWidth(1);
- mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
- glColor4ubv(rgb_tmp);
- glDrawArrays(draw_method, 0, tot_point);
+ glLineWidth(3.0f);
- break;
+ mask_color_active_tint(rgb_tmp, rgb_black, is_active);
+ immUniformColor4ubv(rgb_tmp);
+ mask_draw_array(pos, draw_method, points, tot_point);
- case MASK_DT_DASH:
- default:
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
+ glLineWidth(1.0f);
-#ifdef USE_XOR
- glEnable(GL_COLOR_LOGIC_OP);
- glLogicOp(GL_OR);
-#endif
mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
- glColor4ubv(rgb_tmp);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, points);
- glDrawArrays(draw_method, 0, tot_point);
-
-#ifdef USE_XOR
- glDisable(GL_COLOR_LOGIC_OP);
-#endif
- mask_color_active_tint(rgb_tmp, rgb_black, is_active);
- glColor4ubv(rgb_tmp);
- GPU_basic_shader_line_stipple(3, 0x5555);
- glDrawArrays(draw_method, 0, tot_point);
+ immUniformColor4ubv(rgb_tmp);
+ mask_draw_array(pos, draw_method, points, tot_point);
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ immUnbindProgram();
break;
-
case MASK_DT_BLACK:
case MASK_DT_WHITE:
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ glLineWidth(1.0f);
+
if (draw_type == MASK_DT_BLACK) { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0; }
else { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255; }
/* alpha values seem too low but gl draws many points that compensate for it */
@@ -496,26 +444,39 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
rgb_tmp[2] = (unsigned char)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2);
}
- if (is_smooth == false && is_feather) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
mask_color_active_tint(rgb_tmp, rgb_tmp, is_active);
- glColor4ubv(rgb_tmp);
+ immUniformColor4ubv(rgb_tmp);
+ mask_draw_array(pos, draw_method, points, tot_point);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, points);
- glDrawArrays(draw_method, 0, tot_point);
+ immUnbindProgram();
+ break;
- if (is_smooth == false && is_feather) {
- glDisable(GL_BLEND);
- }
+ case MASK_DT_DASH:
+ /* TODO(merwin): use dashed line shader here
+ * probably better with geometry shader (after core profile switch)
+ */
+#if 0
+ glLineWidth(1.0f);
+
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(3, 0xAAAA);
+ mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
+ immUniformColor4ubv(rgb_tmp);
+ mask_draw_array(pos, draw_method, points, tot_point);
+
+ mask_color_active_tint(rgb_tmp, rgb_black, is_active);
+ immUniformColor4ubv(rgb_tmp);
+ GPU_basic_shader_line_stipple(3, 0x5555);
+ mask_draw_array(pos, draw_method, points, tot_point);
+
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+#endif
break;
- }
- glDisableClientState(GL_VERTEX_ARRAY);
+ default:
+ BLI_assert(false);
+ }
if (points != orig_points)
MEM_freeN(points);
@@ -548,8 +509,6 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline
if (is_smooth) {
glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(spline, &tot_feather_point, resol, (is_fill != false));
@@ -557,26 +516,24 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline
/* draw feather */
mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp);
mask_draw_curve_type(C, spline, feather_points, tot_feather_point,
- true, is_smooth, is_active,
+ true, is_active,
rgb_tmp, draw_type);
if (!is_fill) {
-
const float *fp = &diff_points[0][0];
float *fp_feather = &feather_points[0][0];
- float tvec[2];
- int i;
BLI_assert(tot_diff_point == tot_feather_point);
- for (i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) {
+ for (int i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) {
+ float tvec[2];
sub_v2_v2v2(tvec, fp, fp_feather);
add_v2_v2v2(fp_feather, fp, tvec);
}
/* same as above */
mask_draw_curve_type(C, spline, feather_points, tot_feather_point,
- true, is_smooth, is_active,
+ true, is_active,
rgb_tmp, draw_type);
}
@@ -585,21 +542,22 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline
/* draw main curve */
mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp);
mask_draw_curve_type(C, spline, diff_points, tot_diff_point,
- false, is_smooth, is_active,
+ false, is_active,
rgb_tmp, draw_type);
MEM_freeN(diff_points);
- if (draw_flag & MASK_DRAWFLAG_SMOOTH) {
+ if (is_smooth) {
glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
}
-
- (void)draw_type;
}
static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, const char draw_type,
- const int width, const int height, const float xscale, const float yscale)
+ const int width, const int height)
{
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_enable_program_point_size();
+
MaskLayer *masklay;
int i;
@@ -616,11 +574,9 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c
/* draw curve itself first... */
draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
-// draw_spline_parents(masklay, spline);
-
if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) {
/* ...and then handles over the curve so they're nicely visible */
- draw_spline_points(C, masklay, spline, draw_flag, draw_type, xscale, yscale);
+ draw_spline_points(C, masklay, spline, draw_flag, draw_type);
}
/* show undeform for testing */
@@ -629,33 +585,29 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c
spline->points_deform = NULL;
draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
-// draw_spline_parents(masklay, spline);
- draw_spline_points(C, masklay, spline, draw_flag, draw_type, xscale, yscale);
+ draw_spline_points(C, masklay, spline, draw_flag, draw_type);
spline->points_deform = back;
}
}
}
+
+ GPU_disable_program_point_size();
+ glDisable(GL_BLEND);
}
void ED_mask_draw(const bContext *C,
const char draw_flag, const char draw_type)
{
ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
Mask *mask = CTX_data_edit_mask(C);
int width, height;
- float aspx, aspy;
- float xscale, yscale;
if (!mask)
return;
ED_mask_get_size(sa, &width, &height);
- ED_mask_get_aspect(sa, ar, &aspx, &aspy);
- UI_view2d_scale_get(&ar->v2d, &xscale, &yscale);
- draw_masklays(C, mask, draw_flag, draw_type, width, height, xscale * aspx, yscale * aspy);
+ draw_masklays(C, mask, draw_flag, draw_type, width, height);
}
static float *mask_rasterize(Mask *mask, const int width, const int height)
@@ -733,28 +685,26 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
}
if (draw_flag & MASK_DRAWFLAG_OVERLAY) {
+ float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
float *buffer = mask_rasterize(mask, width, height);
- int format;
- if (overlay_mode == MASK_OVERLAY_ALPHACHANNEL) {
- glColor3f(1.0f, 1.0f, 1.0f);
- format = GL_LUMINANCE;
- }
- else {
+ if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
/* More blending types could be supported in the future. */
glEnable(GL_BLEND);
- glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
- format = GL_ALPHA;
+ glBlendFunc(GL_DST_COLOR, GL_ZERO);
}
- glPushMatrix();
- glTranslatef(x, y, 0);
- glScalef(zoomx, zoomy, 0);
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+ gpuScale2f(zoomx, zoomy);
if (stabmat) {
- glMultMatrixf(stabmat);
+ gpuMultMatrix(stabmat);
}
- glaDrawPixelsTex(0.0f, 0.0f, width, height, format, GL_FLOAT, GL_NEAREST, buffer);
- glPopMatrix();
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
+ immDrawPixelsTex(&state, 0.0f, 0.0f, width, height, GL_RED, GL_FLOAT, GL_NEAREST, buffer, 1.0f, 1.0f, NULL);
+
+ gpuPopMatrix();
if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
glDisable(GL_BLEND);
@@ -764,26 +714,26 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
}
/* apply transformation so mask editing tools will assume drawing from the origin in normalized space */
- glPushMatrix();
- glTranslatef(x + xofs, y + yofs, 0);
- glScalef(zoomx, zoomy, 0);
+ gpuPushMatrix();
+ gpuTranslate2f(x + xofs, y + yofs);
+ gpuScale2f(zoomx, zoomy);
if (stabmat) {
- glMultMatrixf(stabmat);
+ gpuMultMatrix(stabmat);
}
- glScalef(maxdim, maxdim, 0);
+ gpuScale2f(maxdim, maxdim);
if (do_draw_cb) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
}
/* draw! */
- draw_masklays(C, mask, draw_flag, draw_type, width, height, maxdim * zoomx, maxdim * zoomy);
+ draw_masklays(C, mask, draw_flag, draw_type, width, height);
if (do_draw_cb) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
}
- glPopMatrix();
+ gpuPopMatrix();
}
void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra, const int efra)
@@ -792,25 +742,31 @@ void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra
MaskLayer *masklay = BKE_mask_layer_active(mask);
- glBegin(GL_LINES);
- glColor4ub(255, 175, 0, 255);
-
if (masklay) {
- MaskLayerShape *masklay_shape;
-
- for (masklay_shape = masklay->splines_shapes.first;
- masklay_shape;
- masklay_shape = masklay_shape->next)
- {
- int frame = masklay_shape->frame;
-
- /* draw_keyframe(i, CFRA, sfra, framelen, 1); */
- int height = (frame == cfra) ? 22 : 10;
- int x = (frame - sfra) * framelen;
- glVertex2i(x, 0);
- glVertex2i(x, height);
+ unsigned int num_lines = BLI_listbase_count(&masklay->splines_shapes);
+
+ if (num_lines > 0) {
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ub(255, 175, 0, 255);
+
+ immBegin(GWN_PRIM_LINES, 2 * num_lines);
+
+ for (MaskLayerShape *masklay_shape = masklay->splines_shapes.first;
+ masklay_shape;
+ masklay_shape = masklay_shape->next)
+ {
+ int frame = masklay_shape->frame;
+
+ /* draw_keyframe(i, CFRA, sfra, framelen, 1); */
+ int height = (frame == cfra) ? 22 : 10;
+ int x = (frame - sfra) * framelen;
+ immVertex2i(pos, x, 0);
+ immVertex2i(pos, x, height);
+ }
+ immEnd();
+ immUnbindProgram();
}
}
-
- glEnd();
}
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 97d5ee1eff0..b6ac23a37e8 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -35,10 +35,11 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_mask.h"
+#include "DEG_depsgraph.h"
+
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
#include "DNA_object_types.h" /* SELECT */
@@ -1062,7 +1063,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
- DAG_id_tag_update(&data->mask->id, 0);
+ DEG_id_tag_update(&data->mask->id, 0);
break;
}
@@ -1089,7 +1090,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
- DAG_id_tag_update(&data->mask->id, 0);
+ DEG_id_tag_update(&data->mask->id, 0);
free_slide_point_data(op->customdata); /* keep this last! */
return OPERATOR_FINISHED;
@@ -1105,7 +1106,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
cancel_slide_point(op->customdata);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
- DAG_id_tag_update(&data->mask->id, 0);
+ DEG_id_tag_update(&data->mask->id, 0);
free_slide_point_data(op->customdata); /* keep this last! */
return OPERATOR_CANCELLED;
@@ -1469,7 +1470,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
- DAG_id_tag_update(&slide_data->mask->id, 0);
+ DEG_id_tag_update(&slide_data->mask->id, 0);
break;
}
@@ -1483,7 +1484,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
- DAG_id_tag_update(&slide_data->mask->id, 0);
+ DEG_id_tag_update(&slide_data->mask->id, 0);
free_slide_spline_curvature_data(slide_data); /* keep this last! */
return OPERATOR_FINISHED;
@@ -1495,7 +1496,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve
cancel_slide_spline_curvature(slide_data);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
- DAG_id_tag_update(&slide_data->mask->id, 0);
+ DEG_id_tag_update(&slide_data->mask->id, 0);
free_slide_spline_curvature_data(op->customdata); /* keep this last! */
return OPERATOR_CANCELLED;
@@ -1541,7 +1542,7 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return OPERATOR_FINISHED;
@@ -1900,7 +1901,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op)
if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
@@ -1955,7 +1956,7 @@ static int mask_hide_view_clear_exec(bContext *C, wmOperator *op)
if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
@@ -2019,7 +2020,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
@@ -2079,7 +2080,7 @@ static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op))
BKE_mask_update_display(mask, CFRA);
WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c
index 4e0aa8f84ae..c500ec75aee 100644
--- a/source/blender/editors/mask/mask_relationships.c
+++ b/source/blender/editors/mask/mask_relationships.c
@@ -34,10 +34,11 @@
#include "BLI_string.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_mask.h"
#include "BKE_tracking.h"
+#include "DEG_depsgraph.h"
+
#include "DNA_mask_types.h"
#include "WM_api.h"
@@ -73,7 +74,7 @@ static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
}
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
@@ -176,7 +177,7 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
}
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c
index 99ffc9cd7d2..3fb1cc87dbd 100644
--- a/source/blender/editors/mask/mask_shapekey.c
+++ b/source/blender/editors/mask/mask_shapekey.c
@@ -36,13 +36,14 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_mask.h"
#include "DNA_object_types.h"
#include "DNA_mask_types.h"
#include "DNA_scene_types.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -75,7 +76,7 @@ static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op))
if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
@@ -124,7 +125,7 @@ static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DAG_id_tag_update(&mask->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&mask->id, OB_RECALC_DATA);
return OPERATOR_FINISHED;
}
@@ -216,7 +217,7 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op)
if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
@@ -386,7 +387,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op)
if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 8783367ef7e..80e1187609c 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../bmesh
../../gpu
../../imbuf
@@ -51,6 +52,7 @@ set(SRC
editmesh_knife_project.c
editmesh_loopcut.c
editmesh_path.c
+ editmesh_polybuild.c
editmesh_rip.c
editmesh_rip_edge.c
editmesh_select.c
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 87c8c55b0a1..992d0fada5e 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -105,6 +105,8 @@ void paintface_flush_flags(Object *ob, short flag)
/* draw-object caches hidden faces, force re-generation T46867 */
GPU_drawobject_free(dm);
}
+
+ BKE_mesh_batch_cache_dirty(me, BKE_MESH_BATCH_DIRTY_ALL);
}
void paintface_hide(Object *ob, const bool unselected)
@@ -386,14 +388,14 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b
}
/* image window redraw */
-
+
paintface_flush_flags(ob, SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
return true;
}
-int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+int do_paintface_box_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, rcti *rect, bool select, bool extend)
{
Object *ob = vc->obact;
Mesh *me;
@@ -424,7 +426,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten
}
}
- ED_view3d_backbuf_validate(vc);
+ ED_view3d_backbuf_validate(eval_ctx, vc);
ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
rt = ibuf->rect;
@@ -514,6 +516,8 @@ void paintvert_flush_flags(Object *ob)
dm_mv->flag = me->mvert[i].flag;
}
}
+
+ BKE_mesh_batch_cache_dirty(me, BKE_MESH_BATCH_DIRTY_ALL);
}
/* note: if the caller passes false to flush_flags, then they will need to run paintvert_flush_flags(ob) themselves */
void paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index 3a9e278f039..1937a9f6891 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -50,9 +50,17 @@
#include "ED_screen.h"
#include "ED_view3d.h"
+#include "UI_resources.h"
#include "mesh_intern.h" /* own include */
+#define USE_MANIPULATOR
+
+#ifdef USE_MANIPULATOR
+#include "ED_manipulator_library.h"
+#include "ED_util.h"
+#endif
+
static int mesh_bisect_exec(bContext *C, wmOperator *op);
/* -------------------------------------------------------------------- */
@@ -186,6 +194,16 @@ static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (ret & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) {
edbm_bisect_exit(C, &opdata_back);
+
+#ifdef USE_MANIPULATOR
+ /* Setup manipulators */
+ {
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d && (v3d->twtype & V3D_MANIPULATOR_DRAW)) {
+ WM_manipulator_group_type_ensure("MESH_WGT_bisect");
+ }
+ }
+#endif
}
return ret;
@@ -315,6 +333,9 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op)
}
}
+#ifdef USE_MANIPULATOR
+static void MESH_WGT_bisect(struct wmManipulatorGroupType *wgt);
+#endif
void MESH_OT_bisect(struct wmOperatorType *ot)
{
@@ -350,4 +371,331 @@ void MESH_OT_bisect(struct wmOperatorType *ot)
RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold", "", 0.00001, 0.1);
WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
+
+#ifdef USE_MANIPULATOR
+ WM_manipulatorgrouptype_append(MESH_WGT_bisect);
+#endif
+}
+
+
+#ifdef USE_MANIPULATOR
+
+/* -------------------------------------------------------------------- */
+
+/** \name Bisect Manipulator
+ * \{ */
+
+typedef struct ManipulatorGroup {
+ /* Arrow to change plane depth. */
+ struct wmManipulator *translate_z;
+ /* Translate XYZ */
+ struct wmManipulator *translate_c;
+ /* For grabbing the manipulator and moving freely. */
+ struct wmManipulator *rotate_c;
+
+ /* We could store more vars here! */
+ struct {
+ bContext *context;
+ wmOperator *op;
+ PropertyRNA *prop_plane_co;
+ PropertyRNA *prop_plane_no;
+
+ float rotate_axis[3];
+ float rotate_up[3];
+ } data;
+} ManipulatorGroup;
+
+/**
+ * XXX. calling redo from property updates is not great.
+ * This is needed because changing the RNA doesn't cause a redo
+ * and we're not using operator UI which does just this.
+ */
+static void manipulator_bisect_exec(ManipulatorGroup *man)
+{
+ wmOperator *op = man->data.op;
+ if (op == WM_operator_last_redo((bContext *)man->data.context)) {
+ ED_undo_operator_repeat((bContext *)man->data.context, op);
+ }
+}
+
+static void manipulator_mesh_bisect_update_from_op(ManipulatorGroup *man)
+{
+ wmOperator *op = man->data.op;
+
+ float plane_co[3], plane_no[3];
+
+ RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, plane_co);
+ RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no);
+
+ WM_manipulator_set_matrix_location(man->translate_z, plane_co);
+ WM_manipulator_set_matrix_location(man->rotate_c, plane_co);
+ /* translate_c location comes from the property. */
+
+ WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_z, plane_no);
+
+ WM_manipulator_set_scale(man->translate_c, 0.2);
+
+ RegionView3D *rv3d = ED_view3d_context_rv3d(man->data.context);
+ if (rv3d) {
+ normalize_v3_v3(man->data.rotate_axis, rv3d->viewinv[2]);
+ normalize_v3_v3(man->data.rotate_up, rv3d->viewinv[1]);
+
+ /* ensure its orthogonal */
+ project_plane_normalized_v3_v3v3(man->data.rotate_up, man->data.rotate_up, man->data.rotate_axis);
+ normalize_v3(man->data.rotate_up);
+
+ WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_c, plane_no);
+
+ float plane_no_cross[3];
+ cross_v3_v3v3(plane_no_cross, plane_no, man->data.rotate_axis);
+
+ WM_manipulator_set_matrix_offset_rotation_from_yz_axis(man->rotate_c, plane_no_cross, man->data.rotate_axis);
+ RNA_enum_set(man->rotate_c->ptr, "draw_options",
+ ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR |
+ ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y);
+ }
+}
+
+/* depth callbacks */
+static void manipulator_bisect_prop_depth_get(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ ManipulatorGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+ float *value = value_p;
+
+ BLI_assert(mpr_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ float plane_co[3], plane_no[3];
+ RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, plane_co);
+ RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no);
+
+ value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, mpr->matrix_basis[3]);
+}
+
+static void manipulator_bisect_prop_depth_set(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ ManipulatorGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+ const float *value = value_p;
+
+ BLI_assert(mpr_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ float plane_co[3], plane[4];
+ RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, plane_co);
+ RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane);
+ normalize_v3(plane);
+
+ plane[3] = -value[0] - dot_v3v3(plane, mpr->matrix_basis[3]);
+
+ /* Keep our location, may be offset simply to be inside the viewport. */
+ closest_to_plane_normalized_v3(plane_co, plane, plane_co);
+
+ RNA_property_float_set_array(op->ptr, man->data.prop_plane_co, plane_co);
+
+ manipulator_bisect_exec(man);
+}
+
+/* translate callbacks */
+static void manipulator_bisect_prop_translate_get(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ ManipulatorGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+
+ BLI_assert(mpr_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, value_p);
+}
+
+static void manipulator_bisect_prop_translate_set(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ ManipulatorGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+
+ BLI_assert(mpr_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ RNA_property_float_set_array(op->ptr, man->data.prop_plane_co, value_p);
+
+ manipulator_bisect_exec(man);
+}
+
+/* angle callbacks */
+static void manipulator_bisect_prop_angle_get(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ ManipulatorGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+ float *value = value_p;
+
+ BLI_assert(mpr_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ float plane_no[4];
+ RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no);
+ normalize_v3(plane_no);
+
+ float plane_no_proj[3];
+ project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis);
+
+ if (!is_zero_v3(plane_no_proj)) {
+ const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis);
+ value[0] = angle;
+ }
+ else {
+ value[0] = 0.0f;
+ }
+}
+
+static void manipulator_bisect_prop_angle_set(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ ManipulatorGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+ const float *value = value_p;
+
+ BLI_assert(mpr_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ float plane_no[4];
+ RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no);
+ normalize_v3(plane_no);
+
+ float plane_no_proj[3];
+ project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis);
+
+ if (!is_zero_v3(plane_no_proj)) {
+ const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis);
+ const float angle_delta = angle - angle_compat_rad(value[0], angle);
+ if (angle_delta != 0.0f) {
+ float mat[3][3];
+ axis_angle_normalized_to_mat3(mat, man->data.rotate_axis, angle_delta);
+ mul_m3_v3(mat, plane_no);
+
+ /* re-normalize - seems acceptable */
+ RNA_property_float_set_array(op->ptr, man->data.prop_plane_no, plane_no);
+
+ manipulator_bisect_exec(man);
+ }
+ }
+}
+
+static bool manipulator_mesh_bisect_poll(const bContext *C, wmManipulatorGroupType *wgt)
+{
+ wmOperator *op = WM_operator_last_redo(C);
+ if (op == NULL || !STREQ(op->type->idname, "MESH_OT_bisect")) {
+ WM_manipulator_group_type_unlink_delayed_ptr(wgt);
+ return false;
+ }
+ return true;
}
+
+static void manipulator_mesh_bisect_setup(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ wmOperator *op = WM_operator_last_redo(C);
+
+ if (op == NULL || !STREQ(op->type->idname, "MESH_OT_bisect")) {
+ return;
+ }
+
+ struct ManipulatorGroup *man = MEM_callocN(sizeof(ManipulatorGroup), __func__);
+ mgroup->customdata = man;
+
+ const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true);
+ const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", true);
+ const wmManipulatorType *wt_dial = WM_manipulatortype_find("MANIPULATOR_WT_dial_3d", true);
+
+ man->translate_z = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
+ man->translate_c = WM_manipulator_new_ptr(wt_grab, mgroup, NULL);
+ man->rotate_c = WM_manipulator_new_ptr(wt_dial, mgroup, NULL);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_z->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_c->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, man->rotate_c->color);
+
+ RNA_enum_set(man->translate_z->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_NORMAL);
+ RNA_enum_set(man->translate_c->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_RING_2D);
+
+ WM_manipulator_set_flag(man->translate_c, WM_MANIPULATOR_DRAW_VALUE, true);
+ WM_manipulator_set_flag(man->rotate_c, WM_MANIPULATOR_DRAW_VALUE, true);
+
+ {
+ man->data.context = (bContext *)C;
+ man->data.op = op;
+ man->data.prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co");
+ man->data.prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no");
+ }
+
+ manipulator_mesh_bisect_update_from_op(man);
+
+ /* Setup property callbacks */
+ {
+ WM_manipulator_target_property_def_func(
+ man->translate_z, "offset",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_bisect_prop_depth_get,
+ .value_set_fn = manipulator_bisect_prop_depth_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+
+ WM_manipulator_target_property_def_func(
+ man->translate_c, "offset",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_bisect_prop_translate_get,
+ .value_set_fn = manipulator_bisect_prop_translate_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+
+ WM_manipulator_target_property_def_func(
+ man->rotate_c, "offset",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_bisect_prop_angle_get,
+ .value_set_fn = manipulator_bisect_prop_angle_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+ }
+}
+
+static void manipulator_mesh_bisect_draw_prepare(
+ const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ ManipulatorGroup *man = mgroup->customdata;
+ if (man->data.op->next) {
+ man->data.op = WM_operator_last_redo((bContext *)man->data.context);
+ }
+ manipulator_mesh_bisect_update_from_op(man);
+}
+
+static void MESH_WGT_bisect(struct wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Mesh Bisect";
+ wgt->idname = "MESH_WGT_bisect";
+
+ wgt->flag = WM_MANIPULATORGROUPTYPE_3D;
+
+ wgt->mmap_params.spaceid = SPACE_VIEW3D;
+ wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
+
+ wgt->poll = manipulator_mesh_bisect_poll;
+ wgt->setup = manipulator_mesh_bisect_setup;
+ wgt->draw_prepare = manipulator_mesh_bisect_draw_prepare;
+}
+
+/** \} */
+
+#endif /* USE_MANIPULATOR */
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 5ac90ec29e6..18320ec65f5 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -45,6 +45,7 @@
#include "RNA_define.h"
#include "RNA_access.h"
+#include "WM_api.h"
#include "WM_types.h"
#include "ED_mesh.h"
@@ -52,8 +53,19 @@
#include "ED_transform.h"
#include "ED_view3d.h"
+#include "UI_resources.h"
+
+#include "MEM_guardedalloc.h"
+
#include "mesh_intern.h" /* own include */
+#define USE_MANIPULATOR
+
+#ifdef USE_MANIPULATOR
+#include "ED_manipulator_library.h"
+#include "ED_util.h"
+#endif
+
static void edbm_extrude_edge_exclude_mirror(
Object *obedit, BMEditMesh *em,
const char hflag,
@@ -747,9 +759,25 @@ static int edbm_spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e
}
}
- return edbm_spin_exec(C, op);
+ int ret = edbm_spin_exec(C, op);
+
+#ifdef USE_MANIPULATOR
+ if (ret & OPERATOR_FINISHED) {
+ /* Setup manipulators */
+ if (v3d && (v3d->twtype & V3D_MANIPULATOR_DRAW)) {
+ WM_manipulator_group_type_ensure("MESH_WGT_spin");
+ }
+ }
+#endif
+
+ return ret;
+
}
+#ifdef USE_MANIPULATOR
+static void MESH_WGT_spin(struct wmManipulatorGroupType *wgt);
+#endif
+
void MESH_OT_spin(wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -778,8 +806,385 @@ void MESH_OT_spin(wmOperatorType *ot)
"Center", "Center in global view space", -1e4f, 1e4f);
RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f);
+#ifdef USE_MANIPULATOR
+ WM_manipulatorgrouptype_append(MESH_WGT_spin);
+#endif
+}
+
+
+#ifdef USE_MANIPULATOR
+
+/* -------------------------------------------------------------------- */
+
+/** \name Spin Manipulator
+ * \{ */
+
+typedef struct ManipulatorSpinGroup {
+ /* Arrow to change plane depth. */
+ struct wmManipulator *translate_z;
+ /* Translate XYZ */
+ struct wmManipulator *translate_c;
+ /* For grabbing the manipulator and moving freely. */
+ struct wmManipulator *rotate_c;
+ /* Spin angle */
+ struct wmManipulator *angle_z;
+
+ /* We could store more vars here! */
+ struct {
+ bContext *context;
+ wmOperator *op;
+ PropertyRNA *prop_axis_co;
+ PropertyRNA *prop_axis_no;
+ PropertyRNA *prop_angle;
+
+ float rotate_axis[3];
+ float rotate_up[3];
+ } data;
+} ManipulatorSpinGroup;
+
+/**
+ * XXX. calling redo from property updates is not great.
+ * This is needed because changing the RNA doesn't cause a redo
+ * and we're not using operator UI which does just this.
+ */
+static void manipulator_spin_exec(ManipulatorSpinGroup *man)
+{
+ wmOperator *op = man->data.op;
+ if (op == WM_operator_last_redo((bContext *)man->data.context)) {
+ ED_undo_operator_repeat((bContext *)man->data.context, op);
+ }
+}
+
+static void manipulator_mesh_spin_update_from_op(ManipulatorSpinGroup *man)
+{
+ wmOperator *op = man->data.op;
+
+ float plane_co[3], plane_no[3];
+
+ RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, plane_co);
+ RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no);
+
+ WM_manipulator_set_matrix_location(man->translate_z, plane_co);
+ WM_manipulator_set_matrix_location(man->rotate_c, plane_co);
+ WM_manipulator_set_matrix_location(man->angle_z, plane_co);
+ /* translate_c location comes from the property. */
+
+ WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_z, plane_no);
+ WM_manipulator_set_matrix_rotation_from_z_axis(man->angle_z, plane_no);
+
+ WM_manipulator_set_scale(man->translate_c, 0.2);
+
+ RegionView3D *rv3d = ED_view3d_context_rv3d(man->data.context);
+ if (rv3d) {
+ normalize_v3_v3(man->data.rotate_axis, rv3d->viewinv[2]);
+ normalize_v3_v3(man->data.rotate_up, rv3d->viewinv[1]);
+
+ /* ensure its orthogonal */
+ project_plane_normalized_v3_v3v3(man->data.rotate_up, man->data.rotate_up, man->data.rotate_axis);
+ normalize_v3(man->data.rotate_up);
+
+ WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_c, plane_no);
+ WM_manipulator_set_matrix_rotation_from_yz_axis(man->rotate_c, plane_no, man->data.rotate_axis);
+
+ /* show the axis instead of mouse cursor */
+ RNA_enum_set(man->rotate_c->ptr, "draw_options",
+ ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR |
+ ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y);
+
+ }
}
+/* depth callbacks */
+static void manipulator_spin_prop_depth_get(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+ float *value = value_p;
+
+ BLI_assert(mpr_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ float plane_co[3], plane_no[3];
+ RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, plane_co);
+ RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no);
+
+ value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, mpr->matrix_basis[3]);
+}
+
+static void manipulator_spin_prop_depth_set(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+ const float *value = value_p;
+
+ BLI_assert(mpr_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ float plane_co[3], plane[4];
+ RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, plane_co);
+ RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane);
+ normalize_v3(plane);
+
+ plane[3] = -value[0] - dot_v3v3(plane, mpr->matrix_basis[3]);
+
+ /* Keep our location, may be offset simply to be inside the viewport. */
+ closest_to_plane_normalized_v3(plane_co, plane, plane_co);
+
+ RNA_property_float_set_array(op->ptr, man->data.prop_axis_co, plane_co);
+
+ manipulator_spin_exec(man);
+}
+
+/* translate callbacks */
+static void manipulator_spin_prop_translate_get(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+ float *value = value_p;
+
+ BLI_assert(mpr_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, value);
+}
+
+static void manipulator_spin_prop_translate_set(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ const void *value)
+{
+ ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+
+ BLI_assert(mpr_prop->type->array_length == 3);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ RNA_property_float_set_array(op->ptr, man->data.prop_axis_co, value);
+
+ manipulator_spin_exec(man);
+}
+
+/* angle callbacks */
+static void manipulator_spin_prop_axis_angle_get(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+ float *value = value_p;
+
+ BLI_assert(mpr_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ float plane_no[4];
+ RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no);
+ normalize_v3(plane_no);
+
+ float plane_no_proj[3];
+ project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis);
+
+ if (!is_zero_v3(plane_no_proj)) {
+ const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis);
+ value[0] = angle;
+ }
+ else {
+ value[0] = 0.0f;
+ }
+}
+
+static void manipulator_spin_prop_axis_angle_set(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+ const float *value = value_p;
+
+ BLI_assert(mpr_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+
+ float plane_no[4];
+ RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no);
+ normalize_v3(plane_no);
+
+ float plane_no_proj[3];
+ project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis);
+
+ if (!is_zero_v3(plane_no_proj)) {
+ const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis);
+ const float angle_delta = angle - angle_compat_rad(value[0], angle);
+ if (angle_delta != 0.0f) {
+ float mat[3][3];
+ axis_angle_normalized_to_mat3(mat, man->data.rotate_axis, angle_delta);
+ mul_m3_v3(mat, plane_no);
+
+ /* re-normalize - seems acceptable */
+ RNA_property_float_set_array(op->ptr, man->data.prop_axis_no, plane_no);
+
+ manipulator_spin_exec(man);
+ }
+ }
+}
+
+/* angle callbacks */
+static void manipulator_spin_prop_angle_get(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+ float *value = value_p;
+
+ BLI_assert(mpr_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+ value[0] = RNA_property_float_get(op->ptr, man->data.prop_angle);
+}
+
+static void manipulator_spin_prop_angle_set(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata;
+ wmOperator *op = man->data.op;
+ BLI_assert(mpr_prop->type->array_length == 1);
+ UNUSED_VARS_NDEBUG(mpr_prop);
+ const float *value = value_p;
+ RNA_property_float_set(op->ptr, man->data.prop_angle, value[0]);
+
+ manipulator_spin_exec(man);
+}
+
+static bool manipulator_mesh_spin_poll(const bContext *C, wmManipulatorGroupType *wgt)
+{
+ wmOperator *op = WM_operator_last_redo(C);
+ if (op == NULL || !STREQ(op->type->idname, "MESH_OT_spin")) {
+ WM_manipulator_group_type_unlink_delayed_ptr(wgt);
+ return false;
+ }
+ return true;
+}
+
+static void manipulator_mesh_spin_setup(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ wmOperator *op = WM_operator_last_redo(C);
+
+ if (op == NULL || !STREQ(op->type->idname, "MESH_OT_spin")) {
+ return;
+ }
+
+ struct ManipulatorSpinGroup *man = MEM_callocN(sizeof(ManipulatorSpinGroup), __func__);
+ mgroup->customdata = man;
+
+ const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true);
+ const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", true);
+ const wmManipulatorType *wt_dial = WM_manipulatortype_find("MANIPULATOR_WT_dial_3d", true);
+
+ man->translate_z = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
+ man->translate_c = WM_manipulator_new_ptr(wt_grab, mgroup, NULL);
+ man->rotate_c = WM_manipulator_new_ptr(wt_dial, mgroup, NULL);
+ man->angle_z = WM_manipulator_new_ptr(wt_dial, mgroup, NULL);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_z->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_c->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, man->rotate_c->color);
+ UI_GetThemeColor3fv(TH_AXIS_Z, man->angle_z->color);
+
+
+ RNA_enum_set(man->translate_z->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_NORMAL);
+ RNA_enum_set(man->translate_c->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_RING_2D);
+
+ WM_manipulator_set_flag(man->translate_c, WM_MANIPULATOR_DRAW_VALUE, true);
+ WM_manipulator_set_flag(man->rotate_c, WM_MANIPULATOR_DRAW_VALUE, true);
+ WM_manipulator_set_flag(man->angle_z, WM_MANIPULATOR_DRAW_VALUE, true);
+
+ WM_manipulator_set_scale(man->angle_z, 0.5f);
+
+ {
+ man->data.context = (bContext *)C;
+ man->data.op = op;
+ man->data.prop_axis_co = RNA_struct_find_property(op->ptr, "center");
+ man->data.prop_axis_no = RNA_struct_find_property(op->ptr, "axis");
+ man->data.prop_angle = RNA_struct_find_property(op->ptr, "angle");
+ }
+
+ manipulator_mesh_spin_update_from_op(man);
+
+ /* Setup property callbacks */
+ {
+ WM_manipulator_target_property_def_func(
+ man->translate_z, "offset",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_spin_prop_depth_get,
+ .value_set_fn = manipulator_spin_prop_depth_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+
+ WM_manipulator_target_property_def_func(
+ man->translate_c, "offset",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_spin_prop_translate_get,
+ .value_set_fn = manipulator_spin_prop_translate_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+
+ WM_manipulator_target_property_def_func(
+ man->rotate_c, "offset",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_spin_prop_axis_angle_get,
+ .value_set_fn = manipulator_spin_prop_axis_angle_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+
+ WM_manipulator_target_property_def_func(
+ man->angle_z, "offset",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_spin_prop_angle_get,
+ .value_set_fn = manipulator_spin_prop_angle_set,
+ .range_get_fn = NULL,
+ .user_data = NULL,
+ });
+
+ }
+}
+
+static void manipulator_mesh_spin_draw_prepare(
+ const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ ManipulatorSpinGroup *man = mgroup->customdata;
+ if (man->data.op->next) {
+ man->data.op = WM_operator_last_redo((bContext *)man->data.context);
+ }
+ manipulator_mesh_spin_update_from_op(man);
+}
+
+static void MESH_WGT_spin(struct wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Mesh Spin";
+ wgt->idname = "MESH_WGT_spin";
+
+ wgt->flag = WM_MANIPULATORGROUPTYPE_3D;
+
+ wgt->mmap_params.spaceid = SPACE_VIEW3D;
+ wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
+
+ wgt->poll = manipulator_mesh_spin_poll;
+ wgt->setup = manipulator_mesh_spin_setup;
+ wgt->draw_prepare = manipulator_mesh_spin_draw_prepare;
+}
+
+/** \} */
+
+#endif /* USE_MANIPULATOR */
+
+
static int edbm_screw_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 658f8b3958b..c0501078424 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -54,8 +54,10 @@
#include "BKE_editmesh_bvh.h"
#include "BKE_report.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h" /* for paint cursor */
+#include "DEG_depsgraph.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "ED_screen.h"
#include "ED_space_api.h"
@@ -159,6 +161,7 @@ typedef struct KnifePosData {
typedef struct KnifeTool_OpData {
ARegion *ar; /* region that knifetool was activated in */
void *draw_handle; /* for drawing preview loop */
+ EvaluationContext eval_ctx;
ViewContext vc; /* note: _don't_ use 'mval', instead use the one we define below */
float mval[2]; /* mouse value with snapping applied */
//bContext *C;
@@ -1004,12 +1007,18 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
copy_v3_v3(v2, ray_hit_best[1]);
}
- UI_ThemeColor(TH_TRANSFORM);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_TRANSFORM);
glLineWidth(2.0);
- glBegin(GL_LINES);
- glVertex3fv(v1);
- glVertex3fv(v2);
- glEnd();
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immEnd();
+
+ immUnbindProgram();
}
static void knife_init_colors(KnifeColors *colors)
@@ -1037,66 +1046,69 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
glPolygonOffset(1.0f, 1.0f);
- glPushMatrix();
- glMultMatrixf(kcd->ob->obmat);
+ gpuPushMatrix();
+ gpuMultMatrix(kcd->ob->obmat);
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_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(GWN_PRIM_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(GWN_PRIM_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(GWN_PRIM_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(GWN_PRIM_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(GWN_PRIM_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(GWN_PRIM_POINTS, 1);
+ immVertex3fv(pos, kcd->curr.cage);
+ immEnd();
}
if (kcd->totlinehit > 0) {
@@ -1107,26 +1119,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(GWN_PRIM_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(GWN_PRIM_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);
}
@@ -1134,44 +1155,46 @@ 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(GWN_PRIM_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(GWN_PRIM_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();
}
- glPopMatrix();
+ immUnbindProgram();
+
+ gpuPopMatrix();
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
@@ -1394,7 +1417,7 @@ static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data)
* intersecting faces matching this face (or connected when an vert/edge) will be ignored.
*/
static bool point_is_visible(
- KnifeTool_OpData *kcd, const float p[3], const float s[2], bglMats *mats,
+ KnifeTool_OpData *kcd, const float p[3], const float s[2],
BMElem *ele_test)
{
BMFace *f_hit;
@@ -1412,7 +1435,7 @@ static bool point_is_visible(
float view[3], p_ofs[3];
/* TODO: I think there's a simpler way to get the required raycast ray */
- ED_view3d_unproject(mats, view, s[0], s[1], 0.0f);
+ ED_view3d_unproject(kcd->vc.ar, s[0], s[1], 0.0f, view);
mul_m4_v3(kcd->ob->imat, view);
@@ -1485,7 +1508,6 @@ static void set_linehit_depth(KnifeTool_OpData *kcd, KnifeLineHit *lh)
/* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */
static void knife_find_line_hits(KnifeTool_OpData *kcd)
{
- bglMats mats;
SmallHash faces, kfes, kfvs;
float v1[3], v2[3], v3[3], v4[3], s1[2], s2[2];
BVHTree *planetree, *tree;
@@ -1515,8 +1537,6 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
const bool use_hit_prev = true;
const bool use_hit_curr = (kcd->is_drag_hold == false);
- bgl_get_mats(&mats);
-
if (kcd->linehits) {
MEM_freeN(kcd->linehits);
kcd->linehits = NULL;
@@ -1645,7 +1665,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
knife_project_v2(kcd, v->cageco, s);
d = dist_squared_to_line_segment_v2(s, s1, s2);
if ((d <= vert_tol_sq) &&
- (point_is_visible(kcd, v->cageco, s, &mats, bm_elem_from_knife_vert(v, &kfe_hit))))
+ (point_is_visible(kcd, v->cageco, s, bm_elem_from_knife_vert(v, &kfe_hit))))
{
memset(&hit, 0, sizeof(hit));
hit.v = v;
@@ -1708,7 +1728,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
* Need to find 3d intersection of ray through sint */
knife_input_ray_segment(kcd, sint, 1.0f, r1, r2);
isect_kind = isect_line_line_v3(kfe->v1->cageco, kfe->v2->cageco, r1, r2, p_cage, p_cage_tmp);
- if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, &mats, bm_elem_from_knife_edge(kfe))) {
+ if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, bm_elem_from_knife_edge(kfe))) {
memset(&hit, 0, sizeof(hit));
if (kcd->snap_midpoints) {
/* choose intermediate point snap too */
@@ -1737,7 +1757,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
float p[3], p_cage[3];
if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s1, &mats, (BMElem *)f)) {
+ if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
copy_v3_v3(hit.hit, p);
@@ -1749,7 +1769,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
}
if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s2, &mats, (BMElem *)f)) {
+ if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
copy_v3_v3(hit.hit, p);
@@ -1782,13 +1802,9 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs,
float r_origin[3], float r_origin_ofs[3])
{
- bglMats mats;
-
- bgl_get_mats(&mats);
-
/* unproject to find view ray */
- ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f);
- ED_view3d_unproject(&mats, r_origin_ofs, mval[0], mval[1], ofs);
+ ED_view3d_unproject(kcd->vc.ar, mval[0], mval[1], 0.0f, r_origin);
+ ED_view3d_unproject(kcd->vc.ar, mval[0], mval[1], ofs, r_origin_ofs);
/* transform into object space */
invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
@@ -1822,7 +1838,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float
if (!f) {
if (kcd->is_interactive) {
/* try to use backbuffer selection method if ray casting failed */
- f = EDBM_face_find_nearest(&kcd->vc, &dist);
+ f = EDBM_face_find_nearest(&kcd->eval_ctx, &kcd->vc, &dist);
/* cheat for now; just put in the origin instead
* of a true coordinate on the face.
@@ -2574,7 +2590,7 @@ static void knifetool_init_bmbvh(KnifeTool_OpData *kcd)
{
BM_mesh_elem_index_ensure(kcd->em->bm, BM_VERT);
- kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(kcd->em, kcd->scene, NULL);
+ kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(&kcd->eval_ctx, kcd->em, kcd->scene, NULL);
kcd->bmbvh = BKE_bmbvh_new_from_editmesh(
kcd->em,
@@ -2608,6 +2624,7 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
kcd->ob = obedit;
kcd->ar = CTX_wm_region(C);
+ CTX_data_eval_ctx(C, &kcd->eval_ctx);
em_setup_viewcontext(C, &kcd->vc);
kcd->em = BKE_editmesh_from_object(kcd->ob);
@@ -2775,6 +2792,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_FINISHED;
}
+ CTX_data_eval_ctx(C, &kcd->eval_ctx);
em_setup_viewcontext(C, &kcd->vc);
kcd->ar = kcd->vc.ar;
@@ -3008,7 +3026,6 @@ static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_through)
{
KnifeTool_OpData *kcd;
- bglMats mats;
view3d_operator_needs_opengl(C);
@@ -3027,10 +3044,6 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
if (use_tag) {
BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false);
}
-
- if (kcd->cut_through == false) {
- bgl_get_mats(&mats);
- }
}
/* execute */
@@ -3139,7 +3152,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
float cent[3], cent_ss[2];
BM_face_calc_point_in_face(f, cent);
knife_project_v2(kcd, cent, cent_ss);
- if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, &mats, (BMElem *)f)) &&
+ if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, (BMElem *)f)) &&
edbm_mesh_knife_point_isect(polys, cent_ss))
{
BM_elem_flag_enable(f, BM_ELEM_TAG);
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index 0d3cc07589b..c98d22503e1 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -42,6 +42,8 @@
#include "BKE_editmesh.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_define.h"
#include "RNA_access.h"
@@ -56,13 +58,17 @@
#include "mesh_intern.h" /* own include */
-static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object *ob, LinkNode *polys)
+static LinkNode *knifeproject_poly_from_object(const bContext *C, Scene *scene, Object *ob, LinkNode *polys)
{
+ ARegion *ar = CTX_wm_region(C);
+ EvaluationContext eval_ctx;
DerivedMesh *dm;
bool dm_needsFree;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (ob->type == OB_MESH || ob->derivedFinal) {
- dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(&eval_ctx, scene, ob, CD_MASK_BAREMESH);
dm_needsFree = false;
}
else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
@@ -116,7 +122,6 @@ static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object
static int knifeproject_exec(bContext *C, wmOperator *op)
{
- ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -127,7 +132,7 @@ static int knifeproject_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
if (ob != obedit) {
- polys = knifeproject_poly_from_object(ar, scene, ob, polys);
+ polys = knifeproject_poly_from_object(C, scene, ob, polys);
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index b9192f58a1b..3ab56f2ebcb 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"
@@ -62,6 +63,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "DEG_depsgraph.h"
+
#include "mesh_intern.h" /* own include */
#define SUBD_SMOOTH_MAX 4.0f
@@ -104,27 +107,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);
+ gpuPushMatrix();
+ gpuMultMatrix(lcd->ob->obmat);
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_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(GWN_PRIM_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(GWN_PRIM_POINTS, lcd->totpoint);
+
+ for (int i = 0; i < lcd->totpoint; i++) {
+ immVertex3fv(pos, lcd->points[i]);
+ }
+
+ immEnd();
}
- glPopMatrix();
+ immUnbindProgram();
+
+ gpuPopMatrix();
+
if (v3d && v3d->zbuf)
glEnable(GL_DEPTH_TEST);
}
@@ -538,20 +555,23 @@ static void loopcut_update_edge(RingSelOpData *lcd, BMEdge *e, const int preview
}
}
-static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines)
+static void loopcut_mouse_move(const struct EvaluationContext *eval_ctx, RingSelOpData *lcd, const int previewlines)
{
float dist = ED_view3d_select_dist_px();
- BMEdge *e = EDBM_edge_find_nearest(&lcd->vc, &dist);
+ BMEdge *e = EDBM_edge_find_nearest(eval_ctx, &lcd->vc, &dist);
loopcut_update_edge(lcd, e, previewlines);
}
/* called by both init() and exec() */
static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
{
+ EvaluationContext eval_ctx;
const bool is_interactive = (event != NULL);
Object *obedit = CTX_data_edit_object(C);
RingSelOpData *lcd;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (modifiers_isDeformedByLattice(obedit) || modifiers_isDeformedByArmature(obedit))
BKE_report(op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display");
@@ -579,7 +599,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
if (is_interactive) {
copy_v2_v2_int(lcd->vc.mval, event->mval);
- loopcut_mouse_move(lcd, is_interactive ? 1 : 0);
+ loopcut_mouse_move(&eval_ctx, lcd, is_interactive ? 1 : 0);
}
else {
const int e_index = RNA_int_get(op->ptr, "edge_index");
@@ -652,12 +672,14 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op)
static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
+ EvaluationContext eval_ctx;
RingSelOpData *lcd = op->customdata;
float cuts = lcd->cuts;
float smoothness = lcd->smoothness;
bool show_cuts = false;
const bool has_numinput = hasNumInput(&lcd->num);
+ CTX_data_eval_ctx(C, &eval_ctx);
em_setup_viewcontext(C, &lcd->vc);
lcd->ar = lcd->vc.ar;
@@ -743,7 +765,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (!has_numinput) {
lcd->vc.mval[0] = event->mval[0];
lcd->vc.mval[1] = event->mval[1];
- loopcut_mouse_move(lcd, (int)lcd->cuts);
+ loopcut_mouse_move(&eval_ctx, lcd, (int)lcd->cuts);
ED_region_tag_redraw(lcd->ar);
handled = true;
@@ -847,6 +869,8 @@ void MESH_OT_loopcut(wmOperatorType *ot)
"Smoothness", "Smoothness factor", -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ WM_operatortype_props_advanced_begin(ot);
+
prop = RNA_def_property(ot->srna, "falloff", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_proportional_falloff_curve_only_items);
RNA_def_property_enum_default(prop, PROP_INVSQUARE);
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index a85d2425b3c..b71dd029bf2 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -59,6 +59,8 @@
#include "bmesh.h"
#include "bmesh_tools.h"
+#include "DEG_depsgraph.h"
+
#include "mesh_intern.h" /* own include */
struct PathSelectParams {
@@ -570,19 +572,19 @@ static bool edbm_shortest_path_pick_ex(
static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op);
-static BMElem *edbm_elem_find_nearest(ViewContext *vc, const char htype)
+static BMElem *edbm_elem_find_nearest(const struct EvaluationContext *eval_ctx, ViewContext *vc, const char htype)
{
BMEditMesh *em = vc->em;
float dist = ED_view3d_select_dist_px();
if ((em->selectmode & SCE_SELECT_VERTEX) && (htype == BM_VERT)) {
- return (BMElem *)EDBM_vert_find_nearest(vc, &dist);
+ return (BMElem *)EDBM_vert_find_nearest(eval_ctx, vc, &dist);
}
else if ((em->selectmode & SCE_SELECT_EDGE) && (htype == BM_EDGE)) {
- return (BMElem *)EDBM_edge_find_nearest(vc, &dist);
+ return (BMElem *)EDBM_edge_find_nearest(eval_ctx, vc, &dist);
}
else if ((em->selectmode & SCE_SELECT_FACE) && (htype == BM_FACE)) {
- return (BMElem *)EDBM_face_find_nearest(vc, &dist);
+ return (BMElem *)EDBM_face_find_nearest(eval_ctx, vc, &dist);
}
return NULL;
@@ -605,10 +607,12 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
return edbm_shortest_path_pick_exec(C, op);
}
+ EvaluationContext eval_ctx;
ViewContext vc;
BMEditMesh *em;
bool track_active = true;
+ CTX_data_eval_ctx(C, &eval_ctx);
em_setup_viewcontext(C, &vc);
copy_v2_v2_int(vc.mval, event->mval);
em = vc.em;
@@ -617,14 +621,14 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
BMElem *ele_src, *ele_dst;
if (!(ele_src = edbm_elem_active_elem_or_face_get(em->bm)) ||
- !(ele_dst = edbm_elem_find_nearest(&vc, ele_src->head.htype)))
+ !(ele_dst = edbm_elem_find_nearest(&eval_ctx, &vc, ele_src->head.htype)))
{
/* special case, toggle edge tags even when we don't have a path */
if (((em->selectmode & SCE_SELECT_EDGE) &&
(vc.scene->toolsettings->edge_mode != EDGE_MODE_SELECT)) &&
/* check if we only have a destination edge */
((ele_src == NULL) &&
- (ele_dst = edbm_elem_find_nearest(&vc, BM_EDGE))))
+ (ele_dst = edbm_elem_find_nearest(&eval_ctx, &vc, BM_EDGE))))
{
ele_src = ele_dst;
track_active = false;
diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c
new file mode 100644
index 00000000000..f398f087da9
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_polybuild.c
@@ -0,0 +1,541 @@
+/*
+ * ***** 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/mesh/editmesh_polybuild.c
+ * \ingroup edmesh
+ *
+ * Tools to implement polygon building tool,
+ * an experimental tool for quickly constructing/manipulating faces.
+ */
+
+#include "DNA_object_types.h"
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_editmesh.h"
+#include "BKE_mesh.h"
+
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_transform.h"
+#include "ED_view3d.h"
+
+#include "bmesh.h"
+
+#include "mesh_intern.h" /* own include */
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Local Utilities
+ * \{ */
+
+static void edbm_selectmode_ensure(Scene *scene, BMEditMesh *em, short selectmode)
+{
+ if ((scene->toolsettings->selectmode & selectmode) == 0) {
+ scene->toolsettings->selectmode |= selectmode;
+ em->selectmode = scene->toolsettings->selectmode;
+ EDBM_selectmode_set(em);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Face At Cursor
+ * \{ */
+
+static int edbm_polybuild_face_at_cursor_invoke(
+ bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ ViewContext vc;
+ float center[3];
+ bool changed = false;
+
+ em_setup_viewcontext(C, &vc);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMElem *ele_act = BM_mesh_active_elem_get(bm);
+
+ invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
+
+ if (ele_act == NULL || ele_act->head.htype == BM_FACE) {
+ /* Just add vert */
+ copy_v3_v3(center, ED_view3d_cursor3d_get(vc.scene, vc.v3d));
+ mul_v3_m4v3(center, vc.obedit->obmat, center);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
+ mul_m4_v3(vc.obedit->imat, center);
+
+ BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BM_vert_select_set(bm, v_new, true);
+ changed = true;
+ }
+ else if (ele_act->head.htype == BM_EDGE) {
+ BMEdge *e_act = (BMEdge *)ele_act;
+ BMFace *f_reference = e_act->l ? e_act->l->f : NULL;
+
+ mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co);
+ mul_m4_v3(vc.obedit->obmat, center);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
+ mul_m4_v3(vc.obedit->imat, center);
+
+ BMVert *v_tri[3];
+ v_tri[0] = e_act->v1;
+ v_tri[1] = e_act->v2;
+ v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
+ if (e_act->l && e_act->l->v == v_tri[0]) {
+ SWAP(BMVert *, v_tri[0], v_tri[1]);
+ }
+ // BMFace *f_new =
+ BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true);
+
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BM_vert_select_set(bm, v_tri[2], true);
+ changed = true;
+ }
+ else if (ele_act->head.htype == BM_VERT) {
+ BMVert *v_act = (BMVert *)ele_act;
+ BMEdge *e_pair[2] = {NULL};
+
+ if (v_act->e != NULL) {
+ for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == NULL); allow_wire++) {
+ int i = 0;
+ BMEdge *e_iter = v_act->e;
+ do {
+ if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) &&
+ (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter)))
+ {
+ if (i == 2) {
+ e_pair[0] = e_pair[1] = NULL;
+ break;
+ }
+ e_pair[i++] = e_iter;
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e);
+ }
+ }
+
+ if (e_pair[1] != NULL) {
+ /* Quad from edge pair. */
+ if (BM_edge_calc_length_squared(e_pair[0]) <
+ BM_edge_calc_length_squared(e_pair[1]))
+ {
+ SWAP(BMEdge *, e_pair[0], e_pair[1]);
+ }
+
+ BMFace *f_reference = e_pair[0]->l ? e_pair[0]->l->f : NULL;
+
+ mul_v3_m4v3(center, vc.obedit->obmat, v_act->co);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
+ mul_m4_v3(vc.obedit->imat, center);
+
+ BMVert *v_quad[4];
+ v_quad[0] = v_act;
+ v_quad[1] = BM_edge_other_vert(e_pair[0], v_act);
+ v_quad[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
+ v_quad[3] = BM_edge_other_vert(e_pair[1], v_act);
+ if (e_pair[0]->l && e_pair[0]->l->v == v_quad[0]) {
+ SWAP(BMVert *, v_quad[1], v_quad[3]);
+ }
+ // BMFace *f_new =
+ BM_face_create_verts(bm, v_quad, 4, f_reference, BM_CREATE_NOP, true);
+
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BM_vert_select_set(bm, v_quad[2], true);
+ changed = true;
+ }
+ else {
+ /* Just add edge */
+ mul_m4_v3(vc.obedit->obmat, center);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.ar, v_act->co, event->mval, center);
+ mul_m4_v3(vc.obedit->imat, center);
+
+ BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
+
+ BM_edge_create(bm, v_act, v_new, NULL, BM_CREATE_NOP);
+
+ BM_vert_select_set(bm, v_new, true);
+ }
+ }
+
+ if (changed) {
+ BM_select_history_clear(bm);
+
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+
+ WM_event_add_mousemove(C);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void MESH_OT_polybuild_face_at_cursor(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Poly Build Face At Cursor";
+ ot->idname = "MESH_OT_polybuild_face_at_cursor";
+ ot->description = "";
+
+ /* api callbacks */
+ ot->invoke = edbm_polybuild_face_at_cursor_invoke;
+ ot->poll = EDBM_view3d_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* to give to transform */
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Split At Cursor
+ * \{ */
+
+static int edbm_polybuild_split_at_cursor_invoke(
+ bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ ViewContext vc;
+ float center[3];
+ bool changed = false;
+
+ em_setup_viewcontext(C, &vc);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
+
+ BMElem *ele_act = BM_mesh_active_elem_get(bm);
+
+ if (ele_act == NULL || ele_act->head.hflag == BM_FACE) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ else if (ele_act->head.htype == BM_EDGE) {
+ BMEdge *e_act = (BMEdge *)ele_act;
+ mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co);
+ mul_m4_v3(vc.obedit->obmat, center);
+ ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
+ mul_m4_v3(vc.obedit->imat, center);
+
+ const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co);
+ BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f));
+ copy_v3_v3(v_new->co, center);
+
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BM_vert_select_set(bm, v_new, true);
+ changed = true;
+ }
+ else if (ele_act->head.htype == BM_VERT) {
+ /* Just do nothing, allow dragging. */
+ return OPERATOR_FINISHED;
+ }
+
+ if (changed) {
+ BM_select_history_clear(bm);
+
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+
+ WM_event_add_mousemove(C);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void MESH_OT_polybuild_split_at_cursor(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Poly Build Split At Cursor";
+ ot->idname = "MESH_OT_polybuild_split_at_cursor";
+ ot->description = "";
+
+ /* api callbacks */
+ ot->invoke = edbm_polybuild_split_at_cursor_invoke;
+ ot->poll = EDBM_view3d_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* to give to transform */
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name Dissolve At Cursor
+ *
+ * \{ */
+
+static int edbm_polybuild_dissolve_at_cursor_invoke(
+ bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ ViewContext vc;
+ em_setup_viewcontext(C, &vc);
+ bool changed = false;
+
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMVert *v_act = BM_mesh_active_vert_get(bm);
+ BMEdge *e_act = BM_mesh_active_edge_get(bm);
+
+ invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
+
+
+ if (e_act) {
+ BMLoop *l_a, *l_b;
+ if (BM_edge_loop_pair(e_act, &l_a, &l_b)) {
+ BMFace *f_new = BM_faces_join_pair(bm, l_a, l_b, true);
+ if (f_new) {
+ changed = true;
+ }
+ }
+ }
+ else if (v_act) {
+ if (BM_vert_is_edge_pair(v_act)) {
+ BM_edge_collapse(
+ bm, v_act->e, v_act,
+ true, true);
+ }
+ else {
+ /* too involved to do inline */
+ if (!EDBM_op_callf(em, op,
+ "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
+ BM_ELEM_SELECT, false, true))
+ {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ changed = true;
+ }
+
+ if (changed) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ BM_select_history_clear(bm);
+
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+
+ WM_event_add_mousemove(C);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void MESH_OT_polybuild_dissolve_at_cursor(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Poly Build Dissolve At Cursor";
+ ot->idname = "MESH_OT_polybuild_dissolve_at_cursor";
+ ot->description = "";
+
+ /* api callbacks */
+ ot->invoke = edbm_polybuild_dissolve_at_cursor_invoke;
+ ot->poll = EDBM_view3d_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cursor Manipulator
+ *
+ * \note This may need its own file, for now not.
+ * \{ */
+
+static BMElem *edbm_hover_preselect(
+ bContext *C,
+ const int mval[2],
+ bool use_boundary)
+{
+ ViewContext vc;
+
+ em_setup_viewcontext(C, &vc);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+
+ invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ const float mval_fl[2] = {UNPACK2(mval)};
+ float ray_origin[3], ray_direction[3];
+
+ BMElem *ele_best = NULL;
+
+ if (ED_view3d_win_to_ray(
+ vc.ar, vc.v3d, mval_fl,
+ ray_origin, ray_direction, true))
+ {
+ BMEdge *e;
+
+ BMIter eiter;
+ float dist_sq_best = FLT_MAX;
+
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if ((BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) &&
+ (!use_boundary || BM_edge_is_boundary(e)))
+ {
+ float dist_sq_test;
+ float point[3];
+ float depth;
+#if 0
+ dist_sq_test = dist_squared_ray_to_seg_v3(
+ ray_origin, ray_direction,
+ e->v1->co, e->v2->co,
+ point, &depth);
+#else
+ mid_v3_v3v3(point, e->v1->co, e->v2->co);
+ dist_sq_test = dist_squared_to_ray_v3(
+ ray_origin, ray_direction,
+ point, &depth);
+#endif
+
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ ele_best = (BMElem *)e;
+ }
+
+ dist_sq_test = dist_squared_to_ray_v3(
+ ray_origin, ray_direction,
+ e->v1->co, &depth);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ ele_best = (BMElem *)e->v1;
+ }
+ dist_sq_test = dist_squared_to_ray_v3(
+ ray_origin, ray_direction,
+ e->v2->co, &depth);
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ ele_best = (BMElem *)e->v2;
+ }
+ }
+ }
+ }
+ return ele_best;
+}
+
+/*
+ * Developer note: this is not advocating pre-selection highlighting.
+ * This is just a quick way to test how a tool for interactively editing polygons may work. */
+static int edbm_polybuild_hover_invoke(
+ bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
+ ViewContext vc;
+
+ em_setup_viewcontext(C, &vc);
+
+ /* Vertex selection is needed */
+ if ((vc.scene->toolsettings->selectmode & SCE_SELECT_VERTEX) == 0) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ /* Don't overwrite click-drag events. */
+ if (use_boundary == false) {
+ /* pass */
+ }
+ else if (vc.win->tweak ||
+ (vc.win->eventstate->check_click &&
+ vc.win->eventstate->prevval == KM_PRESS &&
+ ISMOUSE(vc.win->eventstate->prevtype)))
+ {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMElem *ele_active = BM_mesh_active_elem_get(bm);
+ BMElem *ele_hover = edbm_hover_preselect(C, event->mval, use_boundary);
+
+ if (ele_hover && (ele_hover != ele_active)) {
+ if (event->shift == 0) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BM_select_history_clear(bm);
+ }
+ BM_elem_select_set(bm, ele_hover, true);
+ BM_select_history_store(em->bm, ele_hover);
+ BKE_mesh_batch_cache_dirty(obedit->data, BKE_MESH_BATCH_DIRTY_SELECT);
+
+ ED_region_tag_redraw(vc.ar);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void MESH_OT_polybuild_hover(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Poly Build Hover";
+ ot->idname = "MESH_OT_polybuild_hover";
+ ot->description = "";
+
+ /* api callbacks */
+ ot->invoke = edbm_polybuild_hover_invoke;
+ ot->poll = EDBM_view3d_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "use_boundary", false, "Boundary", "Select only boundary geometry");
+}
+
+/** \} */
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 1c620ad4681..3e0afd3095e 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -68,6 +68,8 @@
#include "bmesh_tools.h"
+#include "DEG_depsgraph.h"
+
#include "mesh_intern.h" /* own include */
/* use bmesh operator flags for a few operators */
@@ -194,7 +196,9 @@ static BLI_bitmap *edbm_backbuf_alloc(const int size)
/* reads rect, and builds selection array for quick lookup */
/* returns if all is OK */
-bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
+bool EDBM_backbuf_border_init(
+ const struct EvaluationContext *eval_ctx, ViewContext *vc, short xmin,
+ short ymin, short xmax, short ymax)
{
struct ImBuf *buf;
unsigned int *dr;
@@ -204,7 +208,7 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma
return false;
}
- buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
+ buf = ED_view3d_backbuf_read(eval_ctx, vc, xmin, ymin, xmax, ymax);
if ((buf == NULL) || (bm_vertoffs == 0)) {
return false;
}
@@ -267,7 +271,7 @@ static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data)
* - grab again and compare
* returns 'OK'
*/
-bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
+bool EDBM_backbuf_border_mask_init(const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
{
unsigned int *dr, *dr_mask, *dr_mask_arr;
struct ImBuf *buf;
@@ -284,7 +288,7 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short
return false;
}
- buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
+ buf = ED_view3d_backbuf_read(eval_ctx, vc, xmin, ymin, xmax, ymax);
if ((buf == NULL) || (bm_vertoffs == 0)) {
return false;
}
@@ -317,7 +321,9 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short
}
/* circle shaped sample area */
-bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
+bool EDBM_backbuf_circle_init(
+ const struct EvaluationContext *eval_ctx, ViewContext *vc,
+ short xs, short ys, short rads)
{
struct ImBuf *buf;
unsigned int *dr;
@@ -336,7 +342,7 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
xmin = xs - rads; xmax = xs + rads;
ymin = ys - rads; ymax = ys + rads;
- buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax);
+ buf = ED_view3d_backbuf_read(eval_ctx, vc, xmin, ymin, xmax, ymax);
if ((buf == NULL) || (bm_vertoffs == 0)) {
return false;
}
@@ -435,7 +441,7 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float
* \param use_cycle Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index.
*/
BMVert *EDBM_vert_find_nearest_ex(
- ViewContext *vc, float *r_dist,
+ const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist,
const bool use_select_bias, bool use_cycle)
{
BMesh *bm = vc->em->bm;
@@ -447,10 +453,10 @@ BMVert *EDBM_vert_find_nearest_ex(
BMVert *eve;
/* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
- ED_view3d_backbuf_validate(vc);
+ ED_view3d_backbuf_validate(eval_ctx, vc);
index = ED_view3d_backbuf_sample_rect(
- vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
+ eval_ctx, vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
if (eve) {
@@ -485,7 +491,7 @@ BMVert *EDBM_vert_find_nearest_ex(
data.cycle_index_prev = prev_select_index;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
+ mesh_foreachScreenVert(eval_ctx, vc, findnearestvert__doClosest, &data, clip_flag);
hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
*r_dist = hit->dist;
@@ -497,9 +503,9 @@ BMVert *EDBM_vert_find_nearest_ex(
}
}
-BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
+BMVert *EDBM_vert_find_nearest(const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist)
{
- return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
+ return EDBM_vert_find_nearest_ex(eval_ctx, vc, r_dist, false, false);
}
/* find the distance to the edge we already have */
@@ -621,7 +627,7 @@ static void find_nearest_edge__doClosest(
}
BMEdge *EDBM_edge_find_nearest_ex(
- ViewContext *vc, float *r_dist,
+ const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist,
float *r_dist_center,
const bool use_select_bias, const bool use_cycle,
BMEdge **r_eed_zbuf)
@@ -634,18 +640,18 @@ BMEdge *EDBM_edge_find_nearest_ex(
unsigned int index;
BMEdge *eed;
- /* Make sure that the edges are considered for selection.
+ /* Make sure that the edges also are considered to find nearest.
* TODO: cleanup: add `selectmode` as a parameter */
const short ts_selectmode = vc->scene->toolsettings->selectmode;
vc->scene->toolsettings->selectmode |= SCE_SELECT_EDGE;
/* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
- ED_view3d_backbuf_validate(vc);
+ ED_view3d_backbuf_validate(eval_ctx, vc);
/* restore `selectmode` */
vc->scene->toolsettings->selectmode = ts_selectmode;
- index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test);
+ index = ED_view3d_backbuf_sample_rect(eval_ctx, vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test);
eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
if (r_eed_zbuf) {
@@ -663,7 +669,7 @@ BMEdge *EDBM_edge_find_nearest_ex(
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenEdge(vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenEdge(eval_ctx, vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
*r_dist_center = data.dist;
}
@@ -703,7 +709,7 @@ BMEdge *EDBM_edge_find_nearest_ex(
data.cycle_index_prev = prev_select_index;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
+ mesh_foreachScreenEdge(eval_ctx, vc, find_nearest_edge__doClosest, &data, clip_flag);
hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
*r_dist = hit->dist;
@@ -719,9 +725,9 @@ BMEdge *EDBM_edge_find_nearest_ex(
}
BMEdge *EDBM_edge_find_nearest(
- ViewContext *vc, float *r_dist)
+ const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist)
{
- return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+ return EDBM_edge_find_nearest_ex(eval_ctx, vc, r_dist, NULL, false, false, NULL);
}
/* find the distance to the face we already have */
@@ -795,7 +801,7 @@ static void findnearestface__doClosest(void *userData, BMFace *efa, const float
BMFace *EDBM_face_find_nearest_ex(
- ViewContext *vc, float *r_dist,
+ const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist,
float *r_dist_center,
const bool use_select_bias, const bool use_cycle,
BMFace **r_efa_zbuf)
@@ -807,9 +813,9 @@ BMFace *EDBM_face_find_nearest_ex(
unsigned int index;
BMFace *efa;
- ED_view3d_backbuf_validate(vc);
+ ED_view3d_backbuf_validate(eval_ctx, vc);
- index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]);
+ index = ED_view3d_backbuf_sample(eval_ctx, vc, vc->mval[0], vc->mval[1]);
efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
if (r_efa_zbuf) {
@@ -827,7 +833,7 @@ BMFace *EDBM_face_find_nearest_ex(
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenFace(eval_ctx, vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
*r_dist_center = data.dist;
}
@@ -865,7 +871,7 @@ BMFace *EDBM_face_find_nearest_ex(
data.cycle_index_prev = prev_select_index;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
+ mesh_foreachScreenFace(eval_ctx, vc, findnearestface__doClosest, &data, clip_flag);
hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
*r_dist = hit->dist;
@@ -880,9 +886,9 @@ BMFace *EDBM_face_find_nearest_ex(
}
}
-BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
+BMFace *EDBM_face_find_nearest(const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist)
{
- return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+ return EDBM_face_find_nearest_ex(eval_ctx, vc, r_dist, NULL, false, false, NULL);
}
#undef FIND_NEAR_SELECT_BIAS
@@ -894,7 +900,9 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
* selected vertices and edges get disadvantage
* return 1 if found one
*/
-static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
+static int unified_findnearest(
+ const struct EvaluationContext *eval_ctx, ViewContext *vc,
+ BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
{
BMEditMesh *em = vc->em;
static short mval_prev[2] = {-1, -1};
@@ -913,12 +921,12 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed,
/* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
- ED_view3d_backbuf_validate(vc);
+ ED_view3d_backbuf_validate(eval_ctx, vc);
if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
float dist_center = 0.0f;
float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL;
- efa = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
+ efa = EDBM_face_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
if (efa && dist_center_p) {
dist = min_ff(dist_margin, dist_center);
}
@@ -927,14 +935,14 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed,
if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
float dist_center = 0.0f;
float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
- eed = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
+ eed = EDBM_edge_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
if (eed && dist_center_p) {
dist = min_ff(dist_margin, dist_center);
}
}
if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
- eve = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
+ eve = EDBM_vert_find_nearest_ex(eval_ctx, vc, &dist, true, use_cycle);
}
/* return only one of 3 pointers, for frontbuffer redraws */
@@ -997,13 +1005,13 @@ static const EnumPropertyItem prop_similar_types[] = {
#endif
{SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
- {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""},
{SIMFACE_AREA, "AREA", 0, "Area", ""},
{SIMFACE_SIDES, "SIDES", 0, "Polygon Sides", ""},
{SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
{SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
{SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
{SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""},
+ {SIMFACE_FACEMAP, "FACE_MAP", 0, "Face-Map", ""},
#ifdef WITH_FREESTYLE
{SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""},
#endif
@@ -1181,7 +1189,7 @@ static const EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA
#ifdef WITH_FREESTYLE
const int a_end = SIMFACE_FREESTYLE;
#else
- const int a_end = SIMFACE_SMOOTH;
+ const int a_end = SIMFACE_FACEMAP;
#endif
for (a = SIMFACE_MATERIAL; a <= a_end; a++) {
RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
@@ -1567,6 +1575,7 @@ static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool
static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring)
{
+ EvaluationContext eval_ctx;
ViewContext vc;
BMEditMesh *em;
BMEdge *eed;
@@ -1576,6 +1585,7 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de
float dist = ED_view3d_select_dist_px() * 0.6666f;
float mvalf[2];
+ CTX_data_eval_ctx(C, &eval_ctx);
em_setup_viewcontext(C, &vc);
mvalf[0] = (float)(vc.mval[0] = mval[0]);
mvalf[1] = (float)(vc.mval[1] = mval[1]);
@@ -1587,12 +1597,12 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de
vc.scene->toolsettings->selectmode |= SCE_SELECT_EDGE;
/* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */
- ED_view3d_backbuf_validate(&vc);
+ ED_view3d_backbuf_validate(&eval_ctx, &vc);
/* restore `selectmode` */
vc.scene->toolsettings->selectmode = ts_selectmode;
- eed = EDBM_edge_find_nearest_ex(&vc, &dist, NULL, true, true, NULL);
+ eed = EDBM_edge_find_nearest_ex(&eval_ctx, &vc, &dist, NULL, true, true, NULL);
if (eed == NULL) {
return false;
}
@@ -1835,17 +1845,19 @@ void MESH_OT_select_interior_faces(wmOperatorType *ot)
/* gets called via generic mouse select operator */
bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
+ EvaluationContext eval_ctx;
ViewContext vc;
BMVert *eve = NULL;
BMEdge *eed = NULL;
BMFace *efa = NULL;
/* setup view context for argument to callbacks */
+ CTX_data_eval_ctx(C, &eval_ctx);
em_setup_viewcontext(C, &vc);
vc.mval[0] = mval[0];
vc.mval[1] = mval[1];
- if (unified_findnearest(&vc, &eve, &eed, &efa)) {
+ if (unified_findnearest(&eval_ctx, &vc, &eve, &eed, &efa)) {
/* Deselect everything */
if (extend == false && deselect == false && toggle == false)
@@ -1932,12 +1944,30 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
EDBM_selectmode_flush(vc.em);
- /* change active material on object */
- if (efa && efa->mat_nr != vc.obedit->actcol - 1) {
- vc.obedit->actcol = efa->mat_nr + 1;
- vc.em->mat_nr = efa->mat_nr;
+ if (efa) {
+ /* Change active material on object. */
+ if (efa->mat_nr != vc.obedit->actcol - 1) {
+ vc.obedit->actcol = efa->mat_nr + 1;
+ vc.em->mat_nr = efa->mat_nr;
+ WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ }
- WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ /* Change active face-map on object. */
+ if (!BLI_listbase_is_empty(&vc.obedit->fmaps)) {
+ const int cd_fmap_offset = CustomData_get_offset(&vc.em->bm->pdata, CD_FACEMAP);
+ if (cd_fmap_offset != -1) {
+ int map = *((int *)BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset));
+ if ((map < -1) || (map > BLI_listbase_count_ex(&vc.obedit->fmaps, map))) {
+ map = -1;
+ }
+ map += 1;
+ if (map != vc.obedit->actfmap) {
+ /* We may want to add notifiers later,
+ * currently select update handles redraw. */
+ vc.obedit->actfmap = map;
+ }
+ }
+ }
}
@@ -2791,6 +2821,7 @@ static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, in
static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *obedit = CTX_data_edit_object(C);
+ EvaluationContext eval_ctx;
ViewContext vc;
BMEditMesh *em;
BMesh *bm;
@@ -2808,6 +2839,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
view3d_operator_needs_opengl(C);
/* setup view context for argument to callbacks */
+ CTX_data_eval_ctx(C, &eval_ctx);
em_setup_viewcontext(C, &vc);
em = vc.em;
bm = em->bm;
@@ -2820,7 +2852,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
vc.mval[1] = event->mval[1];
/* return warning! */
- if (unified_findnearest(&vc, &eve, &eed, &efa) == 0) {
+ if (unified_findnearest(&eval_ctx, &vc, &eve, &eed, &efa) == 0) {
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 4b4f1b2afea..ff1cd7224cd 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -47,15 +47,18 @@
#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"
-#include "BKE_depsgraph.h"
#include "BKE_report.h"
#include "BKE_texture.h"
#include "BKE_main.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "BLT_translation.h"
#include "RNA_define.h"
@@ -144,6 +147,8 @@ void MESH_OT_subdivide(wmOperatorType *ot)
RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, 1e3f, "Smoothness", "Smoothness factor", 0.0f, 1.0f);
+ WM_operatortype_props_advanced_begin(ot);
+
RNA_def_boolean(ot->srna, "quadtri", 0, "Quad/Tri Mode", "Tries to prevent ngons");
RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_CORNER_STRAIGHT_CUT,
"Quad Corner Type", "How to subdivide quad corners (anything other than Straight Cut will prevent ngons)");
@@ -306,7 +311,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), 0,
+ CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
ar, CTX_wm_view3d(C));
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
@@ -860,9 +865,11 @@ void MESH_OT_mark_seam(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ WM_operatortype_props_advanced_begin(ot);
}
static int edbm_mark_sharp_exec(bContext *C, wmOperator *op)
@@ -1804,6 +1811,9 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot)
RNA_def_float(ot->srna, "factor", 0.5f, -10.0f, 10.0f, "Smoothing", "Smoothing factor", 0.0f, 1.0f);
RNA_def_int(ot->srna, "repeat", 1, 1, 1000, "Repeat", "Number of times to smooth the mesh", 1, 100);
+
+ WM_operatortype_props_advanced_begin(ot);
+
RNA_def_boolean(ot->srna, "xaxis", true, "X-Axis", "Smooth along the X axis");
RNA_def_boolean(ot->srna, "yaxis", true, "Y-Axis", "Smooth along the Y axis");
RNA_def_boolean(ot->srna, "zaxis", true, "Z-Axis", "Smooth along the Z axis");
@@ -1887,6 +1897,9 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
"Lambda factor", "", 1e-7f, 1000.0f);
RNA_def_float(ot->srna, "lambda_border", 5e-5f, 1e-7f, 1000.0f,
"Lambda factor in border", "", 1e-7f, 1000.0f);
+
+ WM_operatortype_props_advanced_begin(ot);
+
RNA_def_boolean(ot->srna, "use_x", true, "Smooth X Axis", "Smooth object along X axis");
RNA_def_boolean(ot->srna, "use_y", true, "Smooth Y Axis", "Smooth object along Y axis");
RNA_def_boolean(ot->srna, "use_z", true, "Smooth Z Axis", "Smooth object along Z axis");
@@ -2342,6 +2355,9 @@ void MESH_OT_merge(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", merge_type_items, MESH_MERGE_CENTER, "Type", "Merge method to use");
RNA_def_enum_funcs(ot->prop, merge_type_itemf);
+
+ WM_operatortype_props_advanced_begin(ot);
+
RNA_def_boolean(ot->srna, "uvs", false, "UVs", "Move UVs according to merge");
}
@@ -2453,7 +2469,7 @@ static void shape_propagate(BMEditMesh *em, wmOperator *op)
//TAG Mesh Objects that share this data
for (base = scene->base.first; base; base = base->next) {
if (base->object && base->object->data == me) {
- DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
#endif
@@ -3016,7 +3032,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, ViewLayer *view_layer, Base *base_old, BMesh *bm_old)
{
Base *base_new;
Object *obedit = base_old->object;
@@ -3037,11 +3053,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, view_layer, 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);
@@ -3063,7 +3079,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, ViewLayer *view_layer, 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);
@@ -3071,7 +3087,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, view_layer, base_old, bm_old) != NULL);
}
/* flush a hflag to from verts to edges/faces */
@@ -3170,7 +3186,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, ViewLayer *view_layer, Base *base_old, BMesh *bm_old)
{
BMFace *f_cmp, *f;
BMIter iter;
@@ -3211,7 +3227,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, view_layer, base_old, bm_old);
if (base_new) {
mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr);
}
@@ -3222,7 +3238,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, ViewLayer *view_layer, Base *base_old, BMesh *bm_old)
{
int i;
BMEdge *e;
@@ -3275,7 +3291,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, view_layer, base_old, bm_old) != NULL);
}
return result;
@@ -3285,6 +3301,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
const int type = RNA_enum_get(op->ptr, "type");
int retval = 0;
@@ -3305,13 +3322,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, view_layer, base, em->bm);
break;
case MESH_SEPARATE_MATERIAL:
- retval = mesh_separate_material(bmain, scene, base, em->bm);
+ retval = mesh_separate_material(bmain, scene, view_layer, base, em->bm);
break;
case MESH_SEPARATE_LOOSE:
- retval = mesh_separate_loose(bmain, scene, base, em->bm);
+ retval = mesh_separate_loose(bmain, scene, view_layer, base, em->bm);
break;
default:
BLI_assert(0);
@@ -3346,10 +3363,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, view_layer, 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, view_layer, base_iter, bm_old);
break;
default:
BLI_assert(0);
@@ -3359,7 +3376,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
if (retval_iter) {
BM_mesh_bm_to_me(bm_old, me, (&(struct BMeshToMeshParams){0}));
- DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&me->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
}
@@ -3374,7 +3391,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
if (retval) {
/* delay depsgraph recalc until all objects are duplicated */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
return OPERATOR_FINISHED;
@@ -5065,7 +5082,7 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
}
BM_mesh_remap(em->bm, map[0], map[1], map[2]);
-/* DAG_id_tag_update(ob->data, 0);*/
+/* DEG_id_tag_update(ob->data, 0);*/
for (j = 3; j--; ) {
if (map[j])
@@ -5892,7 +5909,7 @@ static int edbm_mark_freestyle_edge_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ DEG_id_tag_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -5956,7 +5973,7 @@ static int edbm_mark_freestyle_face_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ DEG_id_tag_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 44aca23e2cc..27fe93b049a 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -44,7 +44,6 @@
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
@@ -52,6 +51,8 @@
#include "BKE_editmesh.h"
#include "BKE_editmesh_bvh.h"
+#include "DEG_depsgraph.h"
+
#include "BKE_object.h" /* XXX. only for EDBM_mesh_load(). */
#include "WM_api.h"
@@ -367,7 +368,7 @@ void EDBM_mesh_make(ToolSettings *ts, Object *ob, const bool add_key_index)
/**
* \warning This can invalidate the #DerivedMesh cache of other objects (for linked duplicates).
- * Most callers should run #DAG_id_tag_update on \a ob->data, see: T46738, T46913
+ * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913
*/
void EDBM_mesh_load(Object *ob)
{
@@ -507,7 +508,6 @@ UvVertMap *BM_uv_vert_map_create(
/* vars from original func */
UvVertMap *vmap;
UvMapVert *buf;
- /* MTexPoly *tf; */ /* UNUSED */
MLoopUV *luv;
unsigned int a;
int totverts, i, totuv, totfaces;
@@ -589,7 +589,6 @@ UvVertMap *BM_uv_vert_map_create(
newvlist = v;
efa = BM_face_at_index(bm, v->f);
- /* tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->tfindex);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -601,7 +600,6 @@ UvVertMap *BM_uv_vert_map_create(
while (iterv) {
next = iterv->next;
efa = BM_face_at_index(bm, iterv->f);
- /* tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -916,29 +914,27 @@ UvElement *BM_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l)
/* last_sel, use em->act_face otherwise get the last selected face in the editselections
* at the moment, last_sel is mainly useful for making sure the space image dosnt flicker */
-MTexPoly *EDBM_mtexpoly_active_get(BMEditMesh *em, BMFace **r_act_efa, const bool sloppy, const bool selected)
+BMFace *EDBM_uv_active_face_get(BMEditMesh *em, const bool sloppy, const bool selected)
{
BMFace *efa = NULL;
- if (!EDBM_mtexpoly_check(em))
+ if (!EDBM_uv_check(em))
return NULL;
efa = BM_mesh_active_face_get(em->bm, sloppy, selected);
if (efa) {
- if (r_act_efa) *r_act_efa = efa;
- return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ return efa;
}
- if (r_act_efa) *r_act_efa = NULL;
return NULL;
}
/* can we edit UV's for this mesh?*/
-bool EDBM_mtexpoly_check(BMEditMesh *em)
+bool EDBM_uv_check(BMEditMesh *em)
{
/* some of these checks could be a touch overkill */
- return em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY) &&
+ return em && em->bm->totface &&
CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV);
}
@@ -1267,7 +1263,7 @@ void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_d
{
Object *ob = em->ob;
/* order of calling isn't important */
- DAG_id_tag_update(ob->data, OB_RECALC_DATA);
+ DEG_id_tag_update(ob->data, OB_RECALC_DATA);
WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data);
if (do_tessface) {
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index bd7aaec075b..218b97d3ede 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -42,7 +42,6 @@
#include "BLI_math.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
@@ -50,6 +49,8 @@
#include "BKE_report.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_define.h"
#include "WM_api.h"
@@ -245,14 +246,14 @@ void ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum)
}
}
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
}
void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me)
{
/* could be ldata or pdata */
- CustomData *pdata = GET_CD_DATA(me, pdata);
- const int layernum = CustomData_get_active_layer(pdata, CD_MTEXPOLY);
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ const int layernum = CustomData_get_active_layer(ldata, CD_MLOOPUV);
ED_mesh_uv_loop_reset_ex(me, layernum);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
@@ -269,21 +270,10 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set)
if (me->edit_btmesh) {
em = me->edit_btmesh;
- layernum_dst = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
+ layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV);
if (layernum_dst >= MAX_MTFACE)
return -1;
- /* CD_MTEXPOLY */
- BM_data_layer_add_named(em->bm, &em->bm->pdata, CD_MTEXPOLY, name);
- /* copy data from active UV */
- if (layernum_dst) {
- const int layernum_src = CustomData_get_active_layer(&em->bm->pdata, CD_MTEXPOLY);
- BM_data_layer_copy(em->bm, &em->bm->pdata, CD_MTEXPOLY, layernum_src, layernum_dst);
- }
- if (active_set || layernum_dst == 0) {
- CustomData_set_layer_active(&em->bm->pdata, CD_MTEXPOLY, layernum_dst);
- }
-
/* CD_MLOOPUV */
BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_MLOOPUV, name);
/* copy data from active UV */
@@ -298,26 +288,22 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set)
}
}
else {
- layernum_dst = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
+ layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
if (layernum_dst >= MAX_MTFACE)
return -1;
- if (me->mtpoly) {
- CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DUPLICATE, me->mtpoly, me->totpoly, name);
+ if (me->mloopuv) {
CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name);
CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name);
is_init = true;
}
else {
- CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, name);
CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, name);
CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name);
}
if (active_set || layernum_dst == 0) {
- CustomData_set_layer_active(&me->pdata, CD_MTEXPOLY, layernum_dst);
CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum_dst);
-
CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum_dst);
}
@@ -329,7 +315,7 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set)
ED_mesh_uv_loop_reset_ex(me, layernum_dst);
}
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, me);
return layernum_dst;
@@ -343,12 +329,12 @@ void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name)
if (me->edit_btmesh) {
em = me->edit_btmesh;
- layernum_dst = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
+ layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV);
if (layernum_dst == 0)
ED_mesh_uv_texture_add(me, name, true);
}
else {
- layernum_dst = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
+ layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
if (layernum_dst == 0)
ED_mesh_uv_texture_add(me, name, true);
}
@@ -357,23 +343,19 @@ void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name)
bool ED_mesh_uv_texture_remove_index(Mesh *me, const int n)
{
- CustomData *pdata = GET_CD_DATA(me, pdata), *ldata = GET_CD_DATA(me, ldata);
- CustomDataLayer *cdlp, *cdlu;
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ CustomDataLayer *cdlu;
int index;
- index = CustomData_get_layer_index_n(pdata, CD_MTEXPOLY, n);
- cdlp = (index == -1) ? NULL : &pdata->layers[index];
-
index = CustomData_get_layer_index_n(ldata, CD_MLOOPUV, n);
cdlu = (index == -1) ? NULL : &ldata->layers[index];
- if (!cdlp || !cdlu)
+ if (!cdlu)
return false;
- delete_customdata_layer(me, cdlp);
delete_customdata_layer(me, cdlu);
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, me);
return true;
@@ -381,14 +363,8 @@ bool ED_mesh_uv_texture_remove_index(Mesh *me, const int n)
bool ED_mesh_uv_texture_remove_active(Mesh *me)
{
/* texpoly/uv are assumed to be in sync */
- CustomData *pdata = GET_CD_DATA(me, pdata);
- const int n = CustomData_get_active_layer(pdata, CD_MTEXPOLY);
-
- /* double check active layers align! */
-#ifdef DEBUG
CustomData *ldata = GET_CD_DATA(me, ldata);
- BLI_assert(CustomData_get_active_layer(ldata, CD_MLOOPUV) == n);
-#endif
+ const int n = CustomData_get_active_layer(ldata, CD_MLOOPUV);
if (n != -1) {
return ED_mesh_uv_texture_remove_index(me, n);
@@ -400,8 +376,8 @@ bool ED_mesh_uv_texture_remove_active(Mesh *me)
bool ED_mesh_uv_texture_remove_named(Mesh *me, const char *name)
{
/* texpoly/uv are assumed to be in sync */
- CustomData *pdata = GET_CD_DATA(me, pdata);
- const int n = CustomData_get_named_layer(pdata, CD_MTEXPOLY, name);
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ const int n = CustomData_get_named_layer(ldata, CD_MLOOPUV, name);
if (n != -1) {
return ED_mesh_uv_texture_remove_index(me, n);
}
@@ -458,7 +434,7 @@ int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set)
BKE_mesh_update_customdata_pointers(me, true);
}
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, me);
return layernum;
@@ -473,7 +449,7 @@ bool ED_mesh_color_ensure(struct Mesh *me, const char *name)
BKE_mesh_update_customdata_pointers(me, true);
}
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
return (me->mloopcol != NULL);
}
@@ -491,7 +467,7 @@ bool ED_mesh_color_remove_index(Mesh *me, const int n)
return false;
delete_customdata_layer(me, cdl);
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, me);
return true;
@@ -612,7 +588,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* load_editMesh free's pointers used by CustomData layers which might be used by DerivedMesh too,
* so signal to re-create DerivedMesh here (sergey) */
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
}
/* dummie drop support; ensure view shows a result :) */
@@ -751,7 +727,7 @@ static int mesh_customdata_clear_exec__internal(bContext *C,
CustomData_free_layers(data, type, tot);
}
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
return OPERATOR_FINISHED;
@@ -847,7 +823,7 @@ static int mesh_customdata_skin_add_exec(bContext *C, wmOperator *UNUSED(op))
BKE_mesh_ensure_skin_customdata(me);
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
return OPERATOR_FINISHED;
@@ -909,7 +885,7 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, me->totloop);
}
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
return OPERATOR_FINISHED;
@@ -986,7 +962,7 @@ void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges, int calc_tessface)
BKE_mesh_calc_normals(mesh);
- DAG_id_tag_update(&mesh->id, 0);
+ DEG_id_tag_update(&mesh->id, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mesh);
}
@@ -1306,7 +1282,6 @@ void ED_mesh_calc_tessface(Mesh *mesh, bool free_mpoly)
mesh->mloopcol = NULL;
mesh->mloopuv = NULL;
mesh->mpoly = NULL;
- mesh->mtpoly = NULL;
}
}
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 300b21a052d..99342222d52 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -109,6 +109,11 @@ void MESH_OT_dupli_extrude_cursor(struct wmOperatorType *ot);
void MESH_OT_spin(struct wmOperatorType *ot);
void MESH_OT_screw(struct wmOperatorType *ot);
+/* *** editmesh_polybuild.c *** */
+void MESH_OT_polybuild_face_at_cursor(struct wmOperatorType *ot);
+void MESH_OT_polybuild_split_at_cursor(struct wmOperatorType *ot);
+void MESH_OT_polybuild_dissolve_at_cursor(struct wmOperatorType *ot);
+void MESH_OT_polybuild_hover(struct wmOperatorType *ot);
/* *** editmesh_inset.c *** */
void MESH_OT_inset(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index b95921964eb..d7e59a05772 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -40,8 +40,8 @@
#include "BLI_math_vector.h"
#include "BLI_linklist.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
-#include "BKE_depsgraph.h"
#include "BKE_context.h"
#include "BKE_mesh.h"
#include "BKE_scene.h"
@@ -58,6 +58,8 @@
#include "recast-capi.h"
+#include "DEG_depsgraph.h"
+
#include "mesh_intern.h" /* own include */
@@ -72,18 +74,21 @@ static void createVertsTrisData(bContext *C, LinkNode *obs,
LinkNode *oblink, *dmlink;
DerivedMesh *dm;
Scene *scene = CTX_data_scene(C);
+ EvaluationContext eval_ctx;
LinkNode *dms = NULL;
int nverts, ntris, *tris;
float *verts;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
nverts = 0;
ntris = 0;
/* calculate number of verts and tris */
for (oblink = obs; oblink; oblink = oblink->next) {
ob = (Object *) oblink->link;
- dm = mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH);
+ dm = mesh_create_derived_no_virtual(&eval_ctx, scene, ob, NULL, CD_MASK_MESH);
DM_ensure_tessface(dm);
BLI_linklist_prepend(&dms, dm);
@@ -333,7 +338,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
int i, j, k;
unsigned short *v;
int face[3];
- Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit;
int createob = base == NULL;
int nverts, nmeshes, nvp;
@@ -351,8 +356,8 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
}
else {
obedit = base->object;
- BKE_scene_base_deselect_all(scene);
- BKE_scene_base_select(scene, base);
+ BKE_view_layer_base_deselect_all(view_layer);
+ BKE_view_layer_base_select(view_layer, base);
copy_v3_v3(obedit->loc, co);
copy_v3_v3(obedit->rot, rot);
}
@@ -440,7 +445,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
recast_destroyPolyMesh(pmesh);
recast_destroyPolyMeshDetail(dmesh);
- DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA);
+ DEG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@@ -461,6 +466,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
static int navmesh_create_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
LinkNode *obs = NULL;
Base *navmeshBase = NULL;
@@ -468,7 +474,7 @@ static int navmesh_create_exec(bContext *C, wmOperator *op)
{
if (base->object->type == OB_MESH) {
if (base->object->body_type == OB_BODY_TYPE_NAVMESH) {
- if (!navmeshBase || base == scene->basact) {
+ if (!navmeshBase || base == view_layer->basact) {
navmeshBase = base;
}
}
@@ -551,7 +557,7 @@ static int navmesh_face_copy_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA);
+ DEG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -632,7 +638,7 @@ static int navmesh_face_add_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA);
+ DEG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -681,7 +687,7 @@ static int navmesh_reset_exec(bContext *C, wmOperator *UNUSED(op))
BKE_mesh_ensure_navmesh(me);
- DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&me->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &me->id);
return OPERATOR_FINISHED;
@@ -709,7 +715,7 @@ static int navmesh_clear_exec(bContext *C, wmOperator *UNUSED(op))
CustomData_free_layers(&me->pdata, CD_RECAST, me->totpoly);
- DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&me->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &me->id);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 697a92f36d1..b9920f9deca 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -147,7 +147,13 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_rip_edge);
WM_operatortype_append(MESH_OT_blend_from_shape);
WM_operatortype_append(MESH_OT_shape_propagate_to_all);
-
+
+ /* editmesh_polybuild */
+ WM_operatortype_append(MESH_OT_polybuild_face_at_cursor);
+ WM_operatortype_append(MESH_OT_polybuild_split_at_cursor);
+ WM_operatortype_append(MESH_OT_polybuild_dissolve_at_cursor);
+ WM_operatortype_append(MESH_OT_polybuild_hover);
+
WM_operatortype_append(MESH_OT_uv_texture_add);
WM_operatortype_append(MESH_OT_uv_texture_remove);
WM_operatortype_append(MESH_OT_vertex_color_add);
@@ -298,6 +304,23 @@ void ED_operatormacros_mesh(void)
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+
+ ot = WM_operatortype_append_macro(
+ "MESH_OT_polybuild_face_at_cursor_move", "Face At Cursor Move", "",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MESH_OT_polybuild_face_at_cursor");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro(
+ "MESH_OT_polybuild_split_at_cursor_move", "Split At Cursor Move", "",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MESH_OT_polybuild_split_at_cursor");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", 0);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
}
/* note mesh keymap also for other space? */
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index c900373a59c..dd1fbc36d8a 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -49,7 +49,6 @@
#include "BLI_kdtree.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_deform.h"
#include "BKE_DerivedMesh.h"
#include "BKE_key.h"
@@ -62,6 +61,9 @@
#include "BKE_editmesh.h"
#include "BKE_multires.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_view3d.h"
@@ -77,7 +79,7 @@
* return 0 if no join is made (error) and 1 if the join is done */
static void join_mesh_single(
- Main *bmain, Scene *scene,
+ bContext *C, Main *bmain, Scene *scene,
Object *ob_dst, Object *ob_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,
@@ -86,6 +88,7 @@ static void join_mesh_single(
Material **matar, int *matmap, int totcol,
int *vertofs, int *edgeofs, int *loopofs, int *polyofs)
{
+ EvaluationContext eval_ctx;
int a, b;
Mesh *me = ob_src->data;
@@ -94,6 +97,8 @@ static void join_mesh_single(
MLoop *mloop = *mloop_pp;
MPoly *mpoly = *mpoly_pp;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (me->totvert) {
/* merge customdata flag */
((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag;
@@ -214,7 +219,7 @@ static void join_mesh_single(
if (ob_src != ob_dst) {
MultiresModifierData *mmd;
- multiresModifier_prepare_join(scene, ob_src, ob_dst);
+ multiresModifier_prepare_join(&eval_ctx, scene, ob_src, ob_dst);
if ((mmd = get_multires_modifier(scene, ob_src, true))) {
ED_object_iter_other(bmain, ob_src, true,
@@ -493,7 +498,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
* 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,
+ C, bmain, scene,
ob, ob, imat,
&mvert, &medge, &mloop, &mpoly,
&vdata, &edata, &ldata, &pdata,
@@ -510,7 +515,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* only join if this is a mesh */
if (base->object->type == OB_MESH) {
join_mesh_single(
- bmain, scene,
+ C, bmain, scene,
ob, base->object, imat,
&mvert, &medge, &mloop, &mpoly,
&vdata, &edata, &ldata, &pdata,
@@ -521,7 +526,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* free base, now that data is merged */
if (base->object != ob) {
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_object_base_free_and_unlink(bmain, scene, base->object);
}
}
}
@@ -594,9 +599,9 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* Due to dependnecy cycle some other object might access old derived data. */
BKE_object_free_derived_caches(ob);
- DAG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */
+ DEG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
@@ -612,6 +617,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
Mesh *me = (Mesh *)ob->data;
Mesh *selme = NULL;
DerivedMesh *dm = NULL;
@@ -619,6 +625,8 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
KeyBlock *kb;
bool ok = false, nonequal_verts = false;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
if (base->object == ob) continue;
@@ -660,7 +668,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
selme = (Mesh *)base->object->data;
if (selme->totvert == me->totvert) {
- dm = mesh_get_derived_deform(scene, base->object, CD_MASK_BAREMESH);
+ dm = mesh_get_derived_deform(&eval_ctx, scene, base->object, CD_MASK_BAREMESH);
if (!dm) continue;
@@ -1088,6 +1096,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm)
*/
bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size)
{
+ EvaluationContext eval_ctx;
ViewContext vc;
Mesh *me = ob->data;
@@ -1096,6 +1105,7 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int
if (!me || me->totpoly == 0)
return false;
+ CTX_data_eval_ctx(C, &eval_ctx);
view3d_set_viewcontext(C, &vc);
if (size) {
@@ -1103,11 +1113,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int
* on an edge in the backbuf, we can still select a face */
float dummy_dist;
- *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist);
+ *index = ED_view3d_backbuf_sample_rect(&eval_ctx, &vc, mval, size, 1, me->totpoly + 1, &dummy_dist);
}
else {
/* sample only on the exact position */
- *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]);
+ *index = ED_view3d_backbuf_sample(&eval_ctx, &vc, mval[0], mval[1]);
}
if ((*index) == 0 || (*index) > (unsigned int)me->totpoly)
@@ -1146,9 +1156,12 @@ static void ed_mesh_pick_face_vert__mpoly_find(
*/
bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size)
{
+ EvaluationContext eval_ctx;
unsigned int poly_index;
Mesh *me = ob->data;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
BLI_assert(me && GS(me->id.name) == ID_ME);
if (ED_mesh_pick_face(C, ob, mval, &poly_index, size)) {
@@ -1156,7 +1169,7 @@ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned
struct ARegion *ar = CTX_wm_region(C);
/* derived mesh to find deformed locations */
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
+ DerivedMesh *dm = mesh_get_derived_final(&eval_ctx, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
int v_idx_best = ORIGINDEX_NONE;
@@ -1253,9 +1266,12 @@ static void ed_mesh_pick_vert__mapFunc(void *userData, int index, const float co
}
bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf)
{
+ EvaluationContext eval_ctx;
ViewContext vc;
Mesh *me = ob->data;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
BLI_assert(me && GS(me->id.name) == ID_ME);
if (!me || me->totvert == 0)
@@ -1269,11 +1285,11 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int
* on an face in the backbuf, we can still select a vert */
float dummy_dist;
- *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist);
+ *index = ED_view3d_backbuf_sample_rect(&eval_ctx, &vc, mval, size, 1, me->totvert + 1, &dummy_dist);
}
else {
/* sample only on the exact position */
- *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]);
+ *index = ED_view3d_backbuf_sample(&eval_ctx, &vc, mval[0], mval[1]);
}
if ((*index) == 0 || (*index) > (unsigned int)me->totvert)
@@ -1283,7 +1299,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int
}
else {
/* derived mesh to find deformed locations */
- DerivedMesh *dm = mesh_get_derived_final(vc.scene, ob, CD_MASK_BAREMESH);
+ DerivedMesh *dm = mesh_get_derived_final(&eval_ctx, vc.scene, ob, CD_MASK_BAREMESH);
ARegion *ar = vc.ar;
RegionView3D *rv3d = ar->regiondata;
diff --git a/source/blender/editors/metaball/CMakeLists.txt b/source/blender/editors/metaball/CMakeLists.txt
index 0f9de8dbf87..89ba942ac36 100644
--- a/source/blender/editors/metaball/CMakeLists.txt
+++ b/source/blender/editors/metaball/CMakeLists.txt
@@ -22,6 +22,7 @@ set(INC
../include
../../blenkernel
../../blenlib
+ ../../depsgraph
../../makesdna
../../makesrna
../../render/extern/include
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 5b4078b98b7..935f1a5ea4a 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -48,10 +48,11 @@
#include "RNA_define.h"
#include "RNA_access.h"
-#include "BKE_depsgraph.h"
#include "BKE_context.h"
#include "BKE_mball.h"
+#include "DEG_depsgraph.h"
+
#include "ED_mball.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -433,7 +434,7 @@ static int duplicate_metaelems_exec(bContext *C, wmOperator *UNUSED(op))
ml = ml->prev;
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
}
return OPERATOR_FINISHED;
@@ -475,7 +476,7 @@ static int delete_metaelems_exec(bContext *C, wmOperator *UNUSED(op))
ml = next;
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
}
return OPERATOR_FINISHED;
@@ -515,7 +516,7 @@ static int hide_metaelems_exec(bContext *C, wmOperator *op)
ml = ml->next;
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
}
return OPERATOR_FINISHED;
@@ -558,7 +559,7 @@ static int reveal_metaelems_exec(bContext *C, wmOperator *op)
}
if (changed) {
WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
}
return OPERATOR_FINISHED;
@@ -588,6 +589,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
{
static MetaElem *startelem = NULL;
Object *obedit = CTX_data_edit_object(C);
+ EvaluationContext eval_ctx;
ViewContext vc;
MetaBall *mb = (MetaBall *)obedit->data;
MetaElem *ml, *ml_act = NULL;
@@ -595,11 +597,12 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
unsigned int buffer[MAXPICKBUF];
rcti rect;
+ CTX_data_eval_ctx(C, &eval_ctx);
view3d_set_viewcontext(C, &vc);
BLI_rcti_init_pt_radius(&rect, mval, 12);
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
+ hits = view3d_opengl_select(&eval_ctx, &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
/* does startelem exist? */
ml = mb->editelems->first;
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index b3d02d45e13..8050508983b 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../depsgraph
../../gpu
../../ikplugin
../../imbuf
@@ -46,6 +47,7 @@ set(SRC
object_bake_api.c
object_constraint.c
object_edit.c
+ object_facemap_ops.c
object_group.c
object_hook.c
object_lattice.c
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 5048b70546c..98ee42f127b 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -45,6 +45,7 @@
#include "DNA_object_fluidsim.h"
#include "DNA_object_force.h"
#include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
#include "DNA_actuator_types.h"
@@ -63,10 +64,10 @@
#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"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
@@ -74,6 +75,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"
@@ -91,6 +93,9 @@
#include "BKE_screen.h"
#include "BKE_speaker.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -112,7 +117,7 @@
#include "UI_resources.h"
-#include "GPU_material.h"
+#include "GPU_lamp.h"
#include "object_intern.h"
@@ -146,6 +151,16 @@ static const EnumPropertyItem field_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static EnumPropertyItem lightprobe_type_items[] = {
+ {LIGHTPROBE_TYPE_CUBE, "SPHERE", ICON_MESH_UVSPHERE, "Reflection Cubemap",
+ "Reflection probe with spherical or cubic attenuation"},
+ {LIGHTPROBE_TYPE_PLANAR, "PLANAR", ICON_MESH_PLANE, "Reflection Plane",
+ "Planar reflection probe"},
+ {LIGHTPROBE_TYPE_GRID, "GRID", ICON_MESH_GRID, "Irradiance Volume",
+ "Irradiance probe to capture diffuse indirect lighting"},
+ {0, NULL, 0, NULL, NULL}
+};
+
/************************** Exported *****************************/
void ED_object_location_from_view(bContext *C, float loc[3])
@@ -208,16 +223,19 @@ void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3],
{
Object *ob = base->object;
Scene *scene = CTX_data_scene(C);
+ EvaluationContext eval_ctx;
if (!scene) return;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (loc)
copy_v3_v3(ob->loc, loc);
if (rot)
copy_v3_v3(ob->rot, rot);
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc(&eval_ctx, scene, ob);
}
/* Uses context to figure out transform for primitive.
@@ -405,10 +423,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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob;
/* for as long scene has editmode... */
@@ -416,13 +435,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, view_layer, type, name);
/* editor level activate, notifiers */
- ED_base_object_activate(C, BASACT);
+ ED_object_base_activate(C, view_layer->basact);
/* more editor stuff */
- ED_object_base_init_transform(C, BASACT, loc, rot);
+ ED_object_base_init_transform(C, view_layer->basact, loc, rot);
/* Ignore collisions by default for non-mesh objects */
if (type != OB_MESH) {
@@ -430,10 +448,13 @@ Object *ED_object_add_type(
ob->gameflag &= ~(OB_SENSOR | OB_RIGID_BODY | OB_SOFT_BODY | OB_COLLISION | OB_CHARACTER | OB_OCCLUDER | OB_DYNAMIC | OB_NAVMESH); /* copied from rna_object.c */
}
- DAG_id_type_tag(bmain, ID_OB);
- DAG_relations_tag_update(bmain);
- if (ob->data) {
- ED_render_id_flush_update(bmain, ob->data);
+ /* TODO(sergey): This is weird to manually tag objects for update, better to
+ * use DEG_id_tag_update here perhaps.
+ */
+ DEG_id_type_tag(bmain, ID_OB);
+ DEG_relations_tag_update(bmain);
+ if (ob->data != NULL) {
+ DEG_id_tag_update_ex(bmain, (ID *)ob->data, DEG_TAG_EDITORS_UPDATE);
}
if (enter_editmode)
@@ -441,6 +462,9 @@ Object *ED_object_add_type(
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+
return ob;
}
@@ -492,6 +516,79 @@ void OBJECT_OT_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, true);
}
+/********************** Add Probe Operator **********************/
+
+/* for object add operator */
+static int lightprobe_add_exec(bContext *C, wmOperator *op)
+{
+ Object *ob;
+ LightProbe *probe;
+ int type;
+ bool enter_editmode;
+ unsigned int layer;
+ float loc[3], rot[3];
+ float radius;
+
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
+ return OPERATOR_CANCELLED;
+
+ type = RNA_enum_get(op->ptr, "type");
+ radius = RNA_float_get(op->ptr, "radius");
+
+ const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Light Probe");
+ ob = ED_object_add_type(C, OB_LIGHTPROBE, name, loc, rot, false, layer);
+ BKE_object_obdata_size_init(ob, radius);
+
+ probe = (LightProbe *)ob->data;
+ probe->type = type;
+
+ switch (type) {
+ case LIGHTPROBE_TYPE_GRID:
+ probe->distinf = 0.3f;
+ probe->falloff = 1.0f;
+ probe->clipsta = 0.01f;
+ break;
+ case LIGHTPROBE_TYPE_PLANAR:
+ probe->distinf = 0.1f;
+ probe->falloff = 0.5f;
+ probe->clipsta = 0.001f;
+ ob->empty_drawsize = 0.5f;
+ break;
+ case LIGHTPROBE_TYPE_CUBE:
+ probe->attenuation_type = LIGHTPROBE_SHAPE_ELIPSOID;
+ break;
+ default:
+ BLI_assert(!"Lightprobe type not configured.");
+ break;
+ }
+
+ DEG_relations_tag_update(CTX_data_main(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_lightprobe_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Light Probe";
+ ot->description = "Add a light probe object";
+ ot->idname = "OBJECT_OT_lightprobe_add";
+
+ /* api callbacks */
+ ot->exec = lightprobe_add_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", lightprobe_type_items, 0, "Type", "");
+
+ ED_object_add_unit_props(ot);
+ ED_object_add_generic_props(ot, true);
+}
+
/********************* Add Effector Operator ********************/
/* for object add operator */
@@ -535,7 +632,7 @@ static int effector_add_exec(bContext *C, wmOperator *op)
ob->pd = object_add_collision_fields(type);
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
return OPERATOR_FINISHED;
}
@@ -640,7 +737,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
newob = true;
}
else {
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
}
ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
@@ -744,7 +841,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
newob = true;
}
else {
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
}
if (obedit == NULL) {
@@ -1002,7 +1099,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
id_us_plus(&group->id);
/* works without this except if you try render right after, see: 22027 */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
@@ -1109,22 +1206,21 @@ 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_object_base_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);
- DAG_id_type_tag(bmain, ID_OB);
+ DEG_id_tag_update_ex(bmain, &ob->id, DEG_TAG_BASE_FLAGS_UPDATE);
+
+ object_delete_check_glsl_update(ob);
+ BKE_collections_object_remove(bmain, &scene->id, ob, true);
}
static int object_delete_exec(bContext *C, wmOperator *op)
@@ -1139,18 +1235,18 @@ 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;
}
@@ -1158,9 +1254,9 @@ static int object_delete_exec(bContext *C, wmOperator *op)
* custom scene/object/base handling, and use generic lib remap/query for that.
* But this is for later (aka 2.8, once layers & co are settled and working).
*/
- if (use_global && base->object->id.lib == NULL) {
+ if (use_global && ob->id.lib == NULL) {
/* We want to nuke the object, let's nuke it the easy way (not for linked data though)... */
- BKE_libblock_delete(bmain, &base->object->id);
+ BKE_libblock_delete(bmain, &ob->id);
changed = true;
continue;
}
@@ -1171,38 +1267,28 @@ static int object_delete_exec(bContext *C, wmOperator *op)
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_object_base_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(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_object_base_free_and_unlink(bmain, scene_iter, ob);
}
}
}
@@ -1216,12 +1302,12 @@ static int object_delete_exec(bContext *C, wmOperator *op)
/* delete has to handle all open scenes */
BKE_main_id_tag_listbase(&bmain->scene, LIB_TAG_DOIT, true);
for (win = wm->windows.first; win; win = win->next) {
- scene = win->screen->scene;
-
+ scene = WM_window_get_active_scene(win);
+
if (scene->id.tag & LIB_TAG_DOIT) {
scene->id.tag &= ~LIB_TAG_DOIT;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
@@ -1343,6 +1429,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
const bool use_hierarchy)
{
Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
ListBase *lb_duplis;
DupliObject *dob;
GHash *dupli_gh, *parent_gh = NULL;
@@ -1375,12 +1462,11 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
ob_dst->totcol = 0;
}
- base_dst = MEM_dupallocN(base);
- base_dst->flag &= ~(OB_FROMDUPLI | OB_FROMGROUP);
- ob_dst->flag = base_dst->flag;
- base_dst->lay = base->lay;
- BLI_addhead(&scene->base, base_dst); /* addhead: othwise eternal loop */
- base_dst->object = ob_dst;
+ BKE_collection_object_add_from(scene, base->object, ob_dst);
+ base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
+ BLI_assert(base_dst != NULL);
+
+ BKE_scene_object_base_flag_sync_from_base(base_dst);
/* make sure apply works */
BKE_animdata_free(&ob_dst->id, true);
@@ -1395,7 +1481,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
BKE_constraints_free(&ob_dst->constraints);
ob_dst->curve_cache = NULL;
ob_dst->transflag &= ~OB_DUPLI;
- ob_dst->lay = base->lay;
copy_m4_m4(ob_dst->obmat, dob->mat);
BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false);
@@ -1419,7 +1504,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
BKE_libblock_relink_to_newid(&ob_dst->id);
set_sca_new_poins_ob(ob_dst);
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
if (use_hierarchy) {
/* original parents */
@@ -1473,7 +1558,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
/* to set ob_dst->orig and in case theres any other discrepicies */
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB);
}
}
@@ -1482,7 +1567,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (ob->proxy_group == base->object) {
ob->proxy = NULL;
ob->proxy_from = NULL;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
}
@@ -1518,7 +1603,7 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE, scene);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
@@ -1552,14 +1637,14 @@ static const EnumPropertyItem convert_target_items[] = {
{0, NULL, 0, NULL, NULL}
};
-static void convert_ensure_curve_cache(Main *bmain, Scene *scene, Object *ob)
+static void convert_ensure_curve_cache(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Object *ob)
{
if (ob->curve_cache == NULL) {
/* Force creation. This is normally not needed but on operator
* redo we might end up with an object which isn't evaluated yet.
*/
if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
- BKE_displist_make_curveTypes(scene, ob, false);
+ BKE_displist_make_curveTypes(eval_ctx, scene, ob, false);
}
else if (ob->type == OB_MBALL) {
BKE_displist_make_mball(bmain->eval_ctx, scene, ob);
@@ -1567,9 +1652,9 @@ static void convert_ensure_curve_cache(Main *bmain, Scene *scene, Object *ob)
}
}
-static void curvetomesh(Main *bmain, Scene *scene, Object *ob)
+static void curvetomesh(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Object *ob)
{
- convert_ensure_curve_cache(bmain, scene, ob);
+ convert_ensure_curve_cache(eval_ctx, bmain, scene, ob);
BKE_mesh_from_nurbs(ob); /* also does users */
if (ob->type == OB_MESH) {
@@ -1583,15 +1668,16 @@ static void curvetomesh(Main *bmain, Scene *scene, Object *ob)
static int convert_poll(bContext *C)
{
- Object *obact = CTX_data_active_object(C);
Scene *scene = CTX_data_scene(C);
+ Base *base_act = CTX_data_active_base(C);
+ Object *obact = base_act ? base_act->object : NULL;
return (!ID_IS_LINKED(scene) && obact && scene->obedit != obact &&
- (obact->flag & SELECT) && !ID_IS_LINKED(obact));
+ (base_act->flag & BASE_SELECTED) && !ID_IS_LINKED(obact));
}
/* 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, ViewLayer *view_layer, Base *base, Object *ob)
{
Object *obn;
Base *basen;
@@ -1601,17 +1687,12 @@ 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);
-
- 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;
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ BKE_collection_object_add_from(scene, ob, obn);
+ basen = BKE_view_layer_base_find(view_layer, obn);
+ ED_object_base_select(basen, BA_SELECT);
+ ED_object_base_select(basen, BA_DESELECT);
return basen;
}
@@ -1619,8 +1700,10 @@ static int convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EvaluationContext eval_ctx;
Base *basen = NULL, *basact = NULL;
- Object *ob, *ob1, *newob, *obact = CTX_data_active_object(C);
+ Object *ob1, *newob, *obact = CTX_data_active_object(C);
DerivedMesh *dm;
Curve *cu;
Nurb *nu;
@@ -1630,13 +1713,13 @@ static int convert_exec(bContext *C, wmOperator *op)
bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
int a, mballConverted = 0;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* don't forget multiple users! */
{
- Base *base;
-
- for (base = scene->base.first; base; base = base->next) {
- ob = base->object;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
ob->flag &= ~OB_DONE;
/* flag data thats not been edited (only needed for !keep_original) */
@@ -1655,6 +1738,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
}
}
+ FOREACH_SCENE_OBJECT_END
}
ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases");
@@ -1665,7 +1749,7 @@ static int convert_exec(bContext *C, wmOperator *op)
{
for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
Base *base = link->ptr.data;
- ob = base->object;
+ Object *ob = base->object;
/* The way object type conversion works currently (enforcing conversion of *all* objetcs using converted
* obdata, even some un-selected/hidden/inother scene ones, sounds totally bad to me.
@@ -1678,18 +1762,19 @@ static int convert_exec(bContext *C, wmOperator *op)
"Converting some linked object/object data, enforcing 'Keep Original' option to True");
}
- DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
uint64_t customdata_mask_prev = scene->customdata_mask;
scene->customdata_mask |= CD_MASK_MESH;
- BKE_scene_update_tagged(bmain->eval_ctx, bmain, scene);
+ BKE_scene_graph_update_tagged(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
scene->customdata_mask = customdata_mask_prev;
}
for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
Base *base = link->ptr.data;
- ob = base->object;
+ Object *ob = base->object;
if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) {
if (ob->type != target) {
@@ -1710,7 +1795,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, view_layer, base, NULL);
newob = basen->object;
/* decrement original mesh's usage count */
@@ -1724,7 +1809,7 @@ static int convert_exec(bContext *C, wmOperator *op)
newob = ob;
}
- BKE_mesh_to_curve(scene, newob);
+ BKE_mesh_to_curve(&eval_ctx, scene, newob);
if (newob->type == OB_CURVE) {
BKE_object_free_modifiers(newob); /* after derivedmesh calls! */
@@ -1735,7 +1820,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, view_layer, base, NULL);
newob = basen->object;
/* decrement original mesh's usage count */
@@ -1747,14 +1832,14 @@ static int convert_exec(bContext *C, wmOperator *op)
}
else {
newob = ob;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
/* make new mesh data from the original copy */
/* note: get the mesh from the original, not from the copy in some
* cases this doesnt give correct results (when MDEF is used for eg)
*/
- dm = mesh_get_derived_final(scene, newob, CD_MASK_MESH);
+ dm = mesh_get_derived_final(&eval_ctx, scene, newob, CD_MASK_MESH);
DM_to_mesh(dm, newob->data, newob, CD_MASK_MESH, true);
@@ -1766,7 +1851,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, view_layer, base, NULL);
newob = basen->object;
/* decrement original curve's usage count */
@@ -1813,7 +1898,7 @@ static int convert_exec(bContext *C, wmOperator *op)
for (ob1 = bmain->object.first; ob1; ob1 = ob1->id.next) {
if (ob1->data == ob->data) {
ob1->type = OB_CURVE;
- DAG_id_tag_update(&ob1->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob1->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
}
}
@@ -1826,7 +1911,7 @@ static int convert_exec(bContext *C, wmOperator *op)
BKE_curve_curve_dimension_update(cu);
if (target == OB_MESH) {
- curvetomesh(bmain, scene, newob);
+ curvetomesh(&eval_ctx, bmain, scene, newob);
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
@@ -1837,7 +1922,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, view_layer, base, NULL);
newob = basen->object;
/* decrement original curve's usage count */
@@ -1850,7 +1935,7 @@ static int convert_exec(bContext *C, wmOperator *op)
newob = ob;
}
- curvetomesh(bmain, scene, newob);
+ curvetomesh(&eval_ctx, bmain, scene, newob);
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
@@ -1859,8 +1944,8 @@ static int convert_exec(bContext *C, wmOperator *op)
else if (ob->type == OB_MBALL && target == OB_MESH) {
Object *baseob;
- base->flag &= ~SELECT;
- ob->flag &= ~SELECT;
+ base->flag &= ~BASE_SELECTED;
+ ob->base_flag &= ~BASE_SELECTED;
baseob = BKE_mball_basis_find(scene, ob);
@@ -1872,7 +1957,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, view_layer, base, baseob);
newob = basen->object;
mb = newob->data;
@@ -1888,7 +1973,7 @@ static int convert_exec(bContext *C, wmOperator *op)
for (a = 0; a < newob->totcol; a++) id_us_plus((ID *)me->mat[a]);
}
- convert_ensure_curve_cache(bmain, scene, baseob);
+ convert_ensure_curve_cache(&eval_ctx, bmain, scene, baseob);
BKE_mesh_from_metaball(&baseob->curve_cache->disp, newob->data);
if (obact->type == OB_MBALL) {
@@ -1915,7 +2000,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
if (!keep_original && (ob->flag & OB_DONE)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
((ID *)ob->data)->tag &= ~LIB_TAG_DOIT; /* flag not to convert this datablock again */
}
}
@@ -1923,27 +2008,24 @@ 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;
- if (ob->type == OB_MBALL) {
- if (ob->flag & OB_DONE) {
+ FOREACH_SCENE_OBJECT(scene, ob_mball)
+ {
+ if (ob_mball->type == OB_MBALL) {
+ if (ob_mball->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_object_base_free_and_unlink(bmain, scene, ob_mball);
}
}
}
}
+ FOREACH_SCENE_OBJECT_END
}
/* delete object should renew depsgraph */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
// XXX ED_object_editmode_enter(C, 0);
@@ -1951,15 +2033,15 @@ 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(view_layer) = 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(view_layer)->object->flag & OB_DONE) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT(view_layer)->object);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT(view_layer)->object);
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -1998,39 +2080,36 @@ 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, ViewLayer *view_layer, 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? */
}
else {
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);
+ DEG_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_view_layer_base_find(view_layer, 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);
}
}
@@ -2139,7 +2218,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
}
break;
case OB_ARMATURE:
- DAG_id_tag_update(&obn->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obn->id, OB_RECALC_DATA);
if (obn->pose)
BKE_pose_tag_recalc(bmain, obn->pose);
if (dupflag & USER_DUP_ARM) {
@@ -2243,14 +2322,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, ViewLayer *view_layer, 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, view_layer, base->object, dupflag);
if (basen == NULL) {
return NULL;
}
@@ -2263,8 +2342,8 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
/* DAG_relations_tag_update(bmain); */ /* caller must do */
- if (ob->data) {
- ED_render_id_flush_update(bmain, ob->data);
+ if (ob->data != NULL) {
+ DEG_id_tag_update_ex(bmain, (ID *)ob->data, DEG_TAG_EDITORS_UPDATE);
}
BKE_main_id_clear_newpoins(bmain);
@@ -2277,6 +2356,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
const bool linked = RNA_boolean_get(op->ptr, "linked");
int dupflag = (linked) ? 0 : U.dupflag;
@@ -2284,22 +2364,23 @@ 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, view_layer, 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);
+ ED_object_base_select(basen, BA_SELECT);
if (basen == NULL) {
continue;
}
/* new object becomes active */
- if (BASACT == base)
- ED_base_object_activate(C, basen);
+ if (BASACT(view_layer) == base)
+ ED_object_base_activate(C, basen);
if (basen->object->data) {
- DAG_id_tag_update(basen->object->data, 0);
+ DEG_id_tag_update(basen->object->data, 0);
}
}
CTX_DATA_END;
@@ -2308,7 +2389,9 @@ static int duplicate_exec(bContext *C, wmOperator *op)
BKE_main_id_clear_newpoins(bmain);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&CTX_data_scene(C)->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -2344,9 +2427,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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *basen;
Object *ob;
const bool linked = RNA_boolean_get(op->ptr, "linked");
int dupflag = (linked) ? 0 : U.dupflag;
@@ -2361,22 +2444,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, view_layer, 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) {
@@ -2387,16 +2465,14 @@ 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);
BKE_main_id_clear_newpoins(bmain);
- DAG_relations_tag_update(bmain);
-
- MEM_freeN(base);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT | ND_OB_ACTIVE, scene);
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index 11d96da5786..3efb6253f6f 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -52,15 +52,17 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_multires.h"
#include "BKE_report.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_depsgraph.h"
#include "BKE_mesh.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
#include "RE_multires_bake.h"
@@ -86,6 +88,11 @@
* needed to make job totally thread-safe */
typedef struct MultiresBakerJobData {
struct MultiresBakerJobData *next, *prev;
+ /* material aligned image array (for per-face bake image) */
+ struct {
+ Image **array;
+ int len;
+ } ob_image;
DerivedMesh *lores_dm, *hires_dm;
bool simple;
int lvl, tot_lvl;
@@ -152,7 +159,7 @@ static bool multiresbake_check(bContext *C, wmOperator *op)
break;
}
- if (!me->mtpoly) {
+ if (!me->mloopuv) {
BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking");
ok = false;
@@ -160,7 +167,7 @@ static bool multiresbake_check(bContext *C, wmOperator *op)
else {
a = me->totpoly;
while (ok && a--) {
- Image *ima = me->mtpoly[a].tpage;
+ Image *ima = BKE_object_material_edit_image_get(ob, me->mpoly[a].mat_nr);
if (!ima) {
BKE_report(op->reports, RPT_ERROR, "You should have active texture to use multires baker");
@@ -283,20 +290,27 @@ static void clear_single_image(Image *image, ClearFlag flag)
}
}
-static void clear_images_poly(MTexPoly *mtpoly, int totpoly, ClearFlag flag)
+static void clear_images_poly(Image **ob_image_array, int ob_image_array_len, ClearFlag flag)
{
- int a;
-
- for (a = 0; a < totpoly; a++) {
- mtpoly[a].tpage->id.tag &= ~LIB_TAG_DOIT;
+ for (int i = 0; i < ob_image_array_len; i++) {
+ Image *image = ob_image_array[i];
+ if (image) {
+ image->id.tag &= ~LIB_TAG_DOIT;
+ }
}
- for (a = 0; a < totpoly; a++) {
- clear_single_image(mtpoly[a].tpage, flag);
+ for (int i = 0; i < ob_image_array_len; i++) {
+ Image *image = ob_image_array[i];
+ if (image) {
+ clear_single_image(image, flag);
+ }
}
- for (a = 0; a < totpoly; a++) {
- mtpoly[a].tpage->id.tag &= ~LIB_TAG_DOIT;
+ for (int i = 0; i < ob_image_array_len; i++) {
+ Image *image = ob_image_array[i];
+ if (image) {
+ image->id.tag &= ~LIB_TAG_DOIT;
+ }
}
}
@@ -312,11 +326,10 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
if (scene->r.bake_flag & R_BAKE_CLEAR) { /* clear images */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- Mesh *me;
ClearFlag clear_flag = 0;
ob = base->object;
- me = (Mesh *)ob->data;
+ // me = (Mesh *)ob->data;
if (scene->r.bake_mode == RE_BAKE_NORMALS) {
clear_flag = CLEAR_TANGENT_NORMAL;
@@ -325,7 +338,11 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
clear_flag = CLEAR_DISPLACEMENT;
}
- clear_images_poly(me->mtpoly, me->totpoly, clear_flag);
+ {
+ Image **ob_image_array = BKE_object_material_edit_image_get_array(ob);
+ clear_images_poly(ob_image_array, ob->totcol, clear_flag);
+ MEM_freeN(ob_image_array);
+ }
}
CTX_DATA_END;
}
@@ -351,11 +368,16 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
//bkr.reports= op->reports;
/* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
+ bkr.ob_image.array = BKE_object_material_edit_image_get_array(ob);
+ bkr.ob_image.len = ob->totcol;
+
bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple);
bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl);
RE_multires_bake_images(&bkr);
+ MEM_freeN(bkr.ob_image.array);
+
BLI_freelistN(&bkr.image);
bkr.lores_dm->release(bkr.lores_dm);
@@ -401,6 +423,9 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
data = MEM_callocN(sizeof(MultiresBakerJobData), "multiresBaker derivedMesh_data");
+ data->ob_image.array = BKE_object_material_edit_image_get_array(ob);
+ data->ob_image.len = ob->totcol;
+
/* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple);
data->lores_dm = multiresbake_create_loresdm(scene, ob, &lvl);
@@ -421,8 +446,6 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
if (bkj->bake_clear) { /* clear images */
for (data = bkj->data.first; data; data = data->next) {
- DerivedMesh *dm = data->lores_dm;
- MTexPoly *mtexpoly = CustomData_get_layer(&dm->polyData, CD_MTEXPOLY);
ClearFlag clear_flag = 0;
if (bkj->mode == RE_BAKE_NORMALS) {
@@ -432,7 +455,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
clear_flag = CLEAR_DISPLACEMENT;
}
- clear_images_poly(mtexpoly, dm->getNumPolys(dm), clear_flag);
+ clear_images_poly(data->ob_image.array, data->ob_image.len, clear_flag);
}
}
@@ -445,6 +468,8 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
bkr.use_lores_mesh = bkj->use_lores_mesh;
bkr.user_scale = bkj->user_scale;
//bkr.reports = bkj->reports;
+ bkr.ob_image.array = data->ob_image.array;
+ bkr.ob_image.len = data->ob_image.len;
/* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
bkr.lores_dm = data->lores_dm;
@@ -493,6 +518,8 @@ static void multiresbake_freejob(void *bkv)
GPU_free_image(ima);
}
+ MEM_freeN(data->ob_image.array);
+
BLI_freelistN(&data->images);
MEM_freeN(data);
@@ -589,6 +616,7 @@ static int test_bake_internal(bContext *C, ReportList *reports)
static void init_bake_internal(BakeRender *bkr, bContext *C)
{
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
bScreen *sc = CTX_wm_screen(C);
/* get editmode results */
@@ -597,7 +625,7 @@ static void init_bake_internal(BakeRender *bkr, bContext *C)
bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL; /* can be NULL */
bkr->main = CTX_data_main(C);
bkr->scene = scene;
- bkr->actob = (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT : NULL;
+ bkr->actob = (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT(view_layer) : NULL;
bkr->re = RE_NewRender("_Bake View_");
if (scene->r.bake_mode == RE_BAKE_AO) {
@@ -661,7 +689,7 @@ static void finish_bake_internal(BakeRender *bkr)
}
BKE_image_release_ibuf(ima, ibuf, NULL);
- DAG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
}
}
@@ -671,7 +699,7 @@ static void finish_bake_internal(BakeRender *bkr)
BLI_assert(BLI_thread_is_main());
for (me = G.main->mesh.first; me; me = me->id.next) {
if (me->id.tag & LIB_TAG_DOIT) {
- DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&me->id, OB_RECALC_DATA);
BKE_mesh_tessface_clear(me);
}
}
@@ -810,6 +838,7 @@ static int bake_image_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
int result = OPERATOR_CANCELLED;
if (is_multires_bake(scene)) {
@@ -829,7 +858,7 @@ static int bake_image_exec(bContext *C, wmOperator *op)
RE_test_break_cb(bkr.re, NULL, thread_break);
G.is_break = false; /* BKE_blender_test_break uses this global */
- RE_Database_Baking(bkr.re, bmain, scene, scene->lay, scene->r.bake_mode, (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT : NULL);
+ RE_Database_Baking(bkr.re, bmain, scene, scene->lay, scene->r.bake_mode, (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT(view_layer) : NULL);
/* baking itself is threaded, cannot use test_break in threads */
BLI_init_threads(&threads, do_bake_render, 1);
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 4825271876c..0174a307c16 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -57,7 +57,8 @@
#include "BKE_modifier.h"
#include "BKE_mesh.h"
#include "BKE_screen.h"
-#include "BKE_depsgraph.h"
+
+#include "DEG_depsgraph.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -83,6 +84,7 @@ static void bake_set_props(wmOperator *op, Scene *scene);
typedef struct BakeAPIRender {
Object *ob;
Main *main;
+ Depsgraph *depsgraph;
Scene *scene;
ReportList *reports;
ListBase selected_objects;
@@ -272,7 +274,7 @@ static void refresh_images(BakeImages *bake_images)
Image *ima = bake_images->data[i].image;
if (ima->ok == IMA_OK_LOADED) {
GPU_free_image(ima);
- DAG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
}
}
}
@@ -619,12 +621,12 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re
}
/* create new mesh with edit mode changes and modifiers applied */
-static Mesh *bake_mesh_new_from_object(Main *bmain, Scene *scene, Object *ob)
+static Mesh *bake_mesh_new_from_object(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Object *ob)
{
if (ob->mode & OB_MODE_EDIT)
ED_object_editmode_load(ob);
- Mesh *me = BKE_mesh_new_from_object(bmain, scene, ob, 1, 2, 0, 0);
+ Mesh *me = BKE_mesh_new_from_object(eval_ctx, bmain, scene, ob, 1, 2, 0, 0);
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true);
}
@@ -633,7 +635,7 @@ static Mesh *bake_mesh_new_from_object(Main *bmain, Scene *scene, Object *ob)
}
static int bake(
- Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports,
+ Render *re, Main *bmain, Depsgraph *graph, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports,
const eScenePassType pass_type, const int pass_filter, const int margin,
const eBakeSaveMode save_mode, const bool is_clear, const bool is_split_materials,
const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage,
@@ -672,7 +674,7 @@ static int bake(
size_t num_pixels;
int tot_materials;
- RE_bake_engine_set_engine_parameters(re, bmain, scene);
+ RE_bake_engine_set_engine_parameters(re, bmain, graph, scene);
if (!RE_bake_has_engine(re)) {
BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
@@ -783,7 +785,7 @@ static int bake(
}
/* get the mesh as it arrives in the renderer */
- me_low = bake_mesh_new_from_object(bmain, scene, ob_low);
+ me_low = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_low);
/* populate the pixel array with the face data */
if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
@@ -798,7 +800,7 @@ static int bake(
/* prepare cage mesh */
if (ob_cage) {
- me_cage = bake_mesh_new_from_object(bmain, scene, ob_cage);
+ me_cage = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_cage);
if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
BKE_report(reports, RPT_ERROR,
"Invalid cage object, the cage mesh must have the same number "
@@ -830,7 +832,7 @@ static int bake(
ob_low->modifiers = modifiers_tmp;
/* get the cage mesh as it arrives in the renderer */
- me_cage = bake_mesh_new_from_object(bmain, scene, ob_low);
+ me_cage = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_low);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
}
@@ -856,7 +858,7 @@ static int bake(
tmd->quad_method = MOD_TRIANGULATE_QUAD_FIXED;
tmd->ngon_method = MOD_TRIANGULATE_NGON_EARCLIP;
- highpoly[i].me = bake_mesh_new_from_object(bmain, scene, highpoly[i].ob);
+ highpoly[i].me = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, highpoly[i].ob);
highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER;
/* lowpoly to highpoly transformation matrix */
@@ -959,7 +961,7 @@ cage_cleanup:
md->mode &= ~eModifierMode_Render;
}
- me_nores = bake_mesh_new_from_object(bmain, scene, ob_low);
+ me_nores = bake_mesh_new_from_object(RE_GetEvalCtx(re), bmain, scene, ob_low);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat);
@@ -1120,6 +1122,7 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
bkr->ob = CTX_data_active_object(C);
bkr->main = CTX_data_main(C);
+ bkr->depsgraph = CTX_data_depsgraph(C);
bkr->scene = CTX_data_scene(C);
bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL;
@@ -1203,7 +1206,7 @@ static int bake_exec(bContext *C, wmOperator *op)
if (bkr.is_selected_to_active) {
result = bake(
- bkr.render, bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports,
+ bkr.render, bkr.main, bkr.depsgraph, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports,
bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage,
bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
@@ -1216,7 +1219,7 @@ static int bake_exec(bContext *C, wmOperator *op)
for (link = bkr.selected_objects.first; link; link = link->next) {
Object *ob_iter = link->ptr.data;
result = bake(
- bkr.render, bkr.main, bkr.scene, ob_iter, NULL, bkr.reports,
+ bkr.render, bkr.main, bkr.depsgraph, bkr.scene, ob_iter, NULL, bkr.reports,
bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage,
bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
@@ -1261,7 +1264,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
if (bkr->is_selected_to_active) {
bkr->result = bake(
- bkr->render, bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports,
+ bkr->render, bkr->main, bkr->depsgraph, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports,
bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage,
bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
@@ -1274,7 +1277,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
for (link = bkr->selected_objects.first; link; link = link->next) {
Object *ob_iter = link->ptr.data;
bkr->result = bake(
- bkr->render, bkr->main, bkr->scene, ob_iter, NULL, bkr->reports,
+ bkr->render, bkr->main, bkr->depsgraph, bkr->scene, ob_iter, NULL, bkr->reports,
bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage,
bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 94caaedec19..05a5f652382 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -53,7 +53,6 @@
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -62,6 +61,9 @@
#include "BKE_tracking.h"
#include "BIK_api.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -773,8 +775,12 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
/* ------------- Child-Of Constraint ------------------ */
-static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con, float invmat[4][4], const int owner)
+static void child_get_inverse_matrix(const bContext *C, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4], const int owner)
{
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* nullify inverse matrix first */
unit_m4(invmat);
@@ -800,7 +806,7 @@ static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con,
* to use as baseline ("pmat") to derive delta from. This extra calc saves users
* from having pressing "Clear Inverse" first
*/
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(&eval_ctx, scene, ob);
copy_m4_m4(pmat, pchan->pose_mat);
/* 2. knock out constraints starting from this one */
@@ -817,7 +823,7 @@ static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con,
}
/* 3. solve pose without disabled constraints */
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(&eval_ctx, scene, ob);
/* 4. determine effect of constraint by removing the newly calculated
* pchan->pose_mat from the original pchan->pose_mat, thus determining
@@ -840,7 +846,7 @@ static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con,
}
/* 6. recalculate pose with new inv-mat applied */
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(&eval_ctx, scene, ob);
}
}
if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
@@ -851,7 +857,7 @@ static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con,
BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
/* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
- BKE_object_workob_calc_parent(scene, ob, &workob);
+ BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob);
invert_m4_m4(invmat, workob.obmat);
}
}
@@ -873,7 +879,7 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- child_get_inverse_matrix(scene, ob, con, data->invmat, owner);
+ child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
@@ -1095,7 +1101,7 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- child_get_inverse_matrix(scene, ob, con, data->invmat, owner);
+ child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
@@ -1196,9 +1202,9 @@ void ED_object_constraint_update(Object *ob)
object_test_constraints(ob);
if (ob->type == OB_ARMATURE)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
else
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
static void object_pose_tag_update(Main *bmain, Object *ob)
@@ -1221,7 +1227,7 @@ void ED_object_constraint_dependency_update(Main *bmain, Object *ob)
if (ob->pose) {
object_pose_tag_update(bmain, ob);
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
void ED_object_constraint_tag_update(Object *ob, bConstraint *con)
@@ -1233,9 +1239,9 @@ void ED_object_constraint_tag_update(Object *ob, bConstraint *con)
object_test_constraint(ob, con);
if (ob->type == OB_ARMATURE)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
else
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstraint *con)
@@ -1245,7 +1251,7 @@ void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstr
if (ob->pose) {
object_pose_tag_update(bmain, ob);
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
static int constraint_poll(bContext *C)
@@ -1269,7 +1275,7 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */
/* relatiols */
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
/* notifiers */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
@@ -1411,12 +1417,12 @@ static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
CTX_DATA_END;
/* force depsgraph to get recalculated since relationships removed */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
/* note, calling BIK_clear_data() isn't needed here */
/* do updates */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
return OPERATOR_FINISHED;
@@ -1443,12 +1449,12 @@ static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
BKE_constraints_free(&ob->constraints);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
/* force depsgraph to get recalculated since relationships removed */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
/* do updates */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, NULL);
@@ -1496,13 +1502,13 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
chan->constflag |= pchan->constflag;
BKE_pose_tag_recalc(bmain, ob->pose);
- DAG_id_tag_update((ID *)ob, OB_RECALC_DATA);
+ DEG_id_tag_update((ID *)ob, OB_RECALC_DATA);
}
}
BLI_freelistN(&lb);
/* force depsgraph to get recalculated since new relationships added */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
@@ -1535,13 +1541,13 @@ static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op))
/* if we're not handling the object we're copying from, copy all constraints over */
if (obact != ob) {
BKE_constraints_copy(&ob->constraints, &obact->constraints, true);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
CTX_DATA_END;
/* force depsgraph to get recalculated since new relationships added */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, NULL);
@@ -1682,14 +1688,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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BASACT(view_layer), *newbase = NULL;
Object *obt;
/* add new target object */
- obt = BKE_object_add(bmain, scene, OB_EMPTY, NULL);
+ obt = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
/* set layers OK */
- newbase = BASACT;
+ newbase = BASACT(view_layer);
newbase->lay = base->lay;
obt->lay = newbase->lay;
@@ -1708,8 +1715,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(view_layer) = base;
+ base->flag |= BASE_SELECTED;
/* make our new target the new object */
*tar_ob = obt;
@@ -1817,7 +1824,7 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
/* force depsgraph to get recalculated since new relationships added */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
if ((ob->type == OB_ARMATURE) && (pchan)) {
BKE_pose_tag_recalc(bmain, ob->pose); /* sort pose channels */
@@ -1827,10 +1834,10 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
* XXX Temp hack until new depsgraph hopefully solves this. */
ob->adt->recalc |= ADT_RECALC_ANIM;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
}
else
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, ob);
@@ -2070,7 +2077,7 @@ static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op))
CTX_DATA_END;
/* refresh depsgraph */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index 7845cfe1022..2daa8652335 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -40,13 +40,14 @@
#include "BKE_context.h"
#include "BKE_data_transfer.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -93,15 +94,17 @@ static const EnumPropertyItem DT_layer_items[] = {
static const EnumPropertyItem *dt_layers_select_src_itemf(
bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
+ EvaluationContext eval_ctx;
EnumPropertyItem *item = NULL, tmp_item = {0};
int totitem = 0;
-
const int data_type = RNA_enum_get(ptr, "data_type");
if (!C) { /* needed for docs and i18n tools */
return rna_enum_dt_layers_select_src_items;
}
+ CTX_data_eval_ctx(C, &eval_ctx);
+
RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ACTIVE_SRC);
RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ALL_SRC);
@@ -135,19 +138,19 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(
if (ob_src) {
DerivedMesh *dm_src;
- CustomData *pdata;
+ CustomData *ldata;
int num_data, i;
/* XXX Is this OK? */
- dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MTEXPOLY);
- pdata = dm_src->getPolyDataLayout(dm_src);
- num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+ dm_src = mesh_get_derived_final(&eval_ctx, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPUV);
+ ldata = dm_src->getLoopDataLayout(dm_src);
+ num_data = CustomData_number_of_layers(ldata, CD_MLOOPUV);
RNA_enum_item_add_separator(&item, &totitem);
for (i = 0; i < num_data; i++) {
tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i);
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPUV, i);
RNA_enum_item_add(&item, &totitem, &tmp_item);
}
}
@@ -162,7 +165,7 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(
int num_data, i;
/* XXX Is this OK? */
- dm_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL);
+ dm_src = mesh_get_derived_final(&eval_ctx, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL);
ldata = dm_src->getLoopDataLayout(dm_src);
num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
@@ -344,6 +347,9 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob_src = ED_object_active_context(C);
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
ListBase ctx_objects;
CollectionPointerLink *ctx_ob_dst;
@@ -412,7 +418,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
}
if (BKE_object_data_transfer_mesh(
- scene, ob_src, ob_dst, data_type, use_create,
+ &eval_ctx, scene, ob_src, ob_dst, data_type, use_create,
map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode,
space_transform, use_auto_transform,
max_distance, ray_radius, islands_precision,
@@ -423,7 +429,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
if (reverse_transfer) {
SWAP(Object *, ob_src, ob_dst);
@@ -622,8 +628,11 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob_act = ED_object_active_context(C);
+ EvaluationContext eval_ctx;
DataTransferModifierData *dtmd;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
dtmd = (DataTransferModifierData *)edit_modifier_property_get(op, ob_act, eModifierType_DataTransfer);
/* If we have a modifier, we transfer data layout from this modifier's source object to active one.
@@ -638,10 +647,10 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_object_data_transfer_layout(scene, ob_src, ob_dst, dtmd->data_types, use_delete,
+ BKE_object_data_transfer_layout(&eval_ctx, scene, ob_src, ob_dst, dtmd->data_types, use_delete,
dtmd->layers_select_src, dtmd->layers_select_dst);
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
}
else {
Object *ob_src = ob_act;
@@ -668,11 +677,11 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op)
for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
Object *ob_dst = ctx_ob_dst->ptr.data;
if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) {
- BKE_object_data_transfer_layout(scene, ob_src, ob_dst, data_type, use_delete,
+ BKE_object_data_transfer_layout(&eval_ctx, scene, ob_src, ob_dst, data_type, use_delete,
layers_select_src, layers_select_dst);
}
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
}
BLI_freelistN(&ctx_objects);
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index d7c7976c344..5697c48d381 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -58,6 +58,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_vfont_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_workspace_types.h"
#include "IMB_imbuf_types.h"
@@ -66,7 +67,6 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_effect.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_lattice.h"
@@ -83,6 +83,10 @@
#include "BKE_modifier.h"
#include "BKE_editmesh.h"
#include "BKE_report.h"
+#include "BKE_workspace.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
#include "ED_armature.h"
#include "ED_curve.h"
@@ -132,192 +136,6 @@ Object *ED_object_active_context(bContext *C)
}
-/* ********* clear/set restrict view *********/
-static int object_hide_view_clear_exec(bContext *C, wmOperator *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;
- const bool select = RNA_boolean_get(op->ptr, "select");
-
- /* 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)) {
- SET_FLAG_FROM_TEST(base->flag, select, 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;
-
- RNA_def_boolean(ot->srna, "select", true, "Select", "");
-}
-
-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)
@@ -379,7 +197,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
* to inform dependency graph about this. But is it really the
* best place to do this?
*/
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
ED_curve_editnurb_load(obedit);
@@ -401,7 +219,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
/* Tag update so no access to freed data referenced from
* derived cache will happen.
*/
- DAG_id_tag_update((ID *)obedit->data, 0);
+ DEG_id_tag_update((ID *)obedit->data, 0);
return true;
}
@@ -417,6 +235,7 @@ void ED_object_editmode_exit(bContext *C, int flag)
/* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */
/* Note! if 'EM_FREEDATA' isn't in the flag, use ED_object_editmode_load directly */
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
const bool freedata = (flag & EM_FREEDATA) != 0;
@@ -425,8 +244,8 @@ void ED_object_editmode_exit(bContext *C, int flag)
if (ED_object_editmode_load_ex(CTX_data_main(C), obedit, freedata) == false) {
/* in rare cases (background mode) its possible active object
* is flagged for editmode, without 'obedit' being set [#35489] */
- if (UNLIKELY(scene->basact && (scene->basact->object->mode & OB_MODE_EDIT))) {
- scene->basact->object->mode &= ~OB_MODE_EDIT;
+ if (UNLIKELY(view_layer->basact && (view_layer->basact->object->mode & OB_MODE_EDIT))) {
+ view_layer->basact->object->mode &= ~OB_MODE_EDIT;
}
if (flag & EM_WAITCURSOR) waitcursor(0);
return;
@@ -451,7 +270,7 @@ void ED_object_editmode_exit(bContext *C, int flag)
BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
/* also flush ob recalc, doesn't take much overhead, but used for particles */
- DAG_id_tag_update(&obedit->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_OB | OB_RECALC_DATA);
if (flag & EM_DO_UNDO)
ED_undo_push(C, "Editmode");
@@ -462,37 +281,31 @@ void ED_object_editmode_exit(bContext *C, int flag)
}
if (flag & EM_WAITCURSOR) waitcursor(0);
+
+ /* This way we ensure scene's obedit is copied into all CoW scenes. */
+ DEG_id_tag_update(&scene->id, 0);
}
void ED_object_editmode_enter(bContext *C, int flag)
{
Scene *scene = CTX_data_scene(C);
- Base *base = NULL;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob;
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = NULL;
bool ok = false;
if (ID_IS_LINKED(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 = view_layer->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))
@@ -551,7 +364,7 @@ void ED_object_editmode_enter(bContext *C, int flag)
scene->obedit = ob;
ED_armature_to_edit(arm);
/* to ensure all goes in restposition and without striding */
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene);
}
@@ -585,7 +398,9 @@ void ED_object_editmode_enter(bContext *C, int flag)
}
if (ok) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ /* This way we ensure scene's obedit is copied into all CoW scenes. */
+ DEG_id_tag_update(&scene->id, 0);
}
else {
scene->obedit = NULL; /* XXX for context */
@@ -697,7 +512,7 @@ void OBJECT_OT_posemode_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
+static void copymenu_properties(ViewLayer *view_layer, Object *ob)
{
//XXX no longer used - to be removed - replaced by game_properties_copy_exec
bProperty *prop;
@@ -730,8 +545,8 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
nr = pupmenu(str);
if (nr == 1 || nr == 2) {
- for (base = FIRSTBASE; base; base = base->next) {
- if ((base != BASACT) && (TESTBASELIB(v3d, base))) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if ((base != BASACT(view_layer)) && (TESTBASELIB(base))) {
if (nr == 1) { /* replace */
BKE_bproperty_copy_list(&base->object->prop, &ob->prop);
}
@@ -747,8 +562,8 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
prop = BLI_findlink(&ob->prop, nr - 4); /* account for first 3 menu items & menu index starting at 1*/
if (prop) {
- for (base = FIRSTBASE; base; base = base->next) {
- if ((base != BASACT) && (TESTBASELIB(v3d, base))) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if ((base != BASACT(view_layer)) && (TESTBASELIB(base))) {
BKE_bproperty_object_set(base->object, prop);
}
}
@@ -758,14 +573,14 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
}
-static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob)
+static void copymenu_logicbricks(ViewLayer *view_layer, Object *ob)
{
//XXX no longer used - to be removed - replaced by logicbricks_copy_exec
Base *base;
- for (base = FIRSTBASE; base; base = base->next) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
if (base->object != ob) {
- if (TESTBASELIB(v3d, base)) {
+ if (TESTBASELIB(base)) {
/* first: free all logic */
free_sensors(&base->object->sensors);
@@ -844,7 +659,7 @@ static void copy_texture_space(Object *to, Object *ob)
}
/* UNUSED, keep in case we want to copy functionality for use elsewhere */
-static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
+static void copy_attr(Main *bmain, Scene *scene, ViewLayer *view_layer, short event)
{
Object *ob;
Base *base;
@@ -854,18 +669,18 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
if (ID_IS_LINKED(scene)) return;
- if (!(ob = OBACT)) return;
+ if (!(ob = OBACT(view_layer))) return;
if (scene->obedit) { // XXX get from context
/* obedit_copymenu(); */
return;
}
if (event == 9) {
- copymenu_properties(scene, v3d, ob);
+ copymenu_properties(view_layer, ob);
return;
}
else if (event == 10) {
- copymenu_logicbricks(scene, v3d, ob);
+ copymenu_logicbricks(view_layer, ob);
return;
}
else if (event == 24) {
@@ -874,10 +689,10 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
return;
}
- for (base = FIRSTBASE; base; base = base->next) {
- if (base != BASACT) {
- if (TESTBASELIB(v3d, base)) {
- DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (base != BASACT(view_layer)) {
+ if (TESTBASELIB(base)) {
+ DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
if (event == 1) { /* loc */
copy_v3_v3(base->object->loc, ob->loc);
@@ -980,7 +795,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
BLI_strncpy(cu1->family, cu->family, sizeof(cu1->family));
- DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
else if (event == 19) { /* bevel settings */
@@ -996,7 +811,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
cu1->ext1 = cu->ext1;
cu1->ext2 = cu->ext2;
- DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
else if (event == 25) { /* curve resolution */
@@ -1015,7 +830,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
nu = nu->next;
}
- DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
else if (event == 21) {
@@ -1031,7 +846,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
}
modifier_copyData(md, tmd);
- DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
}
@@ -1092,16 +907,16 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
}
if (do_depgraph_update)
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
-static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, View3D *v3d)
+static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, ViewLayer *view_layer)
{
Object *ob;
short event;
char str[512];
- if (!(ob = OBACT)) return;
+ if (!(ob = OBACT(view_layer))) return;
if (scene->obedit) { /* XXX get from context */
/* if (ob->type == OB_MESH) */
@@ -1149,7 +964,7 @@ static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, View3D *
event = pupmenu(str);
if (event <= 0) return;
- copy_attr(bmain, scene, v3d, event);
+ copy_attr(bmain, scene, view_layer, event);
}
/* ******************* force field toggle operator ***************** */
@@ -1218,6 +1033,9 @@ void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
*/
void ED_objects_recalculate_paths(bContext *C, Scene *scene)
{
+ struct Main *bmain = CTX_data_main(C);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
ListBase targets = {NULL, NULL};
/* loop over objects in scene */
@@ -1230,7 +1048,7 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene)
CTX_DATA_END;
/* recalculate paths, then free */
- animviz_calc_motionpaths(scene, &targets);
+ animviz_calc_motionpaths(&eval_ctx, bmain, scene, &targets);
BLI_freelistN(&targets);
}
@@ -1451,7 +1269,8 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
if (ob->type == OB_MESH) {
BKE_mesh_smooth_flag_set(ob, !clear);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
done = true;
@@ -1464,7 +1283,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
else nu->flag &= ~ME_SMOOTH;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
done = true;
@@ -1515,7 +1334,7 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot)
/* ********************** */
-static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
+static void UNUSED_FUNCTION(image_aspect) (Scene *scene, ViewLayer *view_layer)
{
/* all selected objects with an image map: scale in image aspect */
Base *base;
@@ -1528,8 +1347,8 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
if (scene->obedit) return; // XXX get from context
if (ID_IS_LINKED(scene)) return;
- for (base = FIRSTBASE; base; base = base->next) {
- if (TESTBASELIB(v3d, base)) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (TESTBASELIB(base)) {
ob = base->object;
done = false;
@@ -1562,7 +1381,7 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
else ob->size[1] = ob->size[0] * y / x;
done = true;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
BKE_image_release_ibuf(tex->ima, ibuf, NULL);
}
@@ -1698,7 +1517,12 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, int mode, ReportList *re
bool ok;
if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
const char *opstring = object_mode_op_string(ob->mode);
+
WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
+#ifdef USE_WORKSPACE_MODE
+ BKE_workspace_object_mode_set(CTX_wm_workspace(C), CTX_data_scene(C), ob->mode);
+#endif
+
ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
if (!ok) {
wmOperatorType *ot = WM_operatortype_find(opstring, false);
@@ -1808,13 +1632,23 @@ void OBJECT_OT_mode_set(wmOperatorType *ot)
}
-
void ED_object_toggle_modes(bContext *C, int mode)
{
if (mode != OB_MODE_OBJECT) {
const char *opstring = object_mode_op_string(mode);
+
if (opstring) {
+#ifdef USE_WORKSPACE_MODE
+ WorkSpace *workspace = CTX_wm_workspace(C);
+#endif
WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
+
+#ifdef USE_WORKSPACE_MODE
+ Object *ob = CTX_data_active_object(C);
+ if (ob) {
+ BKE_workspace_object_mode_set(workspace, CTX_data_scene(C), ob->mode);
+ }
+#endif
}
}
}
diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c
new file mode 100644
index 00000000000..857446ac6b0
--- /dev/null
+++ b/source/blender/editors/object/object_facemap_ops.c
@@ -0,0 +1,492 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_listbase.h"
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_editmesh.h"
+#include "BKE_object.h"
+#include "BKE_object_facemap.h"
+#include "BKE_object_deform.h"
+
+#include "DEG_depsgraph.h"
+
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "ED_mesh.h"
+#include "ED_object.h"
+
+#include "object_intern.h"
+
+/* called while not in editmode */
+void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum)
+{
+ int fmap_nr;
+ if (GS(((ID *)ob->data)->name) != ID_ME)
+ return;
+
+ /* get the face map number, exit if it can't be found */
+ fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+
+ if (fmap_nr != -1) {
+ int *facemap;
+ Mesh *me = ob->data;
+
+ /* if there's is no facemap layer then create one */
+ if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
+ facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly);
+
+ facemap[facenum] = fmap_nr;
+ }
+}
+
+/* called while not in editmode */
+void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum)
+{
+ int fmap_nr;
+ if (GS(((ID *)ob->data)->name) != ID_ME)
+ return;
+
+ /* get the face map number, exit if it can't be found */
+ fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+
+ if (fmap_nr != -1) {
+ int *facemap;
+ Mesh *me = ob->data;
+
+ /* if there's is no facemap layer then create one */
+ if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
+ return;
+
+ facemap[facenum] = -1;
+ }
+}
+
+static void object_fmap_swap_edit_mode(Object *ob, int num1, int num2)
+{
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_btmesh) {
+ BMEditMesh *em = me->edit_btmesh;
+ const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ if (cd_fmap_offset != -1) {
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (map) {
+ if (num1 != -1) {
+ if (*map == num1)
+ *map = num2;
+ else if (*map == num2)
+ *map = num1;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void object_fmap_swap_object_mode(Object *ob, int num1, int num2)
+{
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
+ int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+ int i;
+
+ if (map) {
+ for (i = 0; i < me->totpoly; i++) {
+ if (num1 != -1) {
+ if (map[i] == num1)
+ map[i] = num2;
+ else if (map[i] == num2)
+ map[i] = num1;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void object_facemap_swap(Object *ob, int num1, int num2)
+{
+ if (BKE_object_is_in_editmode(ob))
+ object_fmap_swap_edit_mode(ob, num1, num2);
+ else
+ object_fmap_swap_object_mode(ob, num1, num2);
+}
+
+static int face_map_supported_poll(bContext *C)
+{
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib);
+}
+
+static int face_map_supported_edit_mode_poll(bContext *C)
+{
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib && ob->mode == OB_MODE_EDIT);
+}
+
+static int face_map_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+
+ BKE_object_facemap_add(ob);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_add(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Face Map";
+ ot->idname = "OBJECT_OT_face_map_add";
+ ot->description = "Add a new face map to the active object";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_poll;
+ ot->exec = face_map_add_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int face_map_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ BKE_object_facemap_remove(ob, fmap);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_remove(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Face Map";
+ ot->idname = "OBJECT_OT_face_map_remove";
+ ot->description = "Remove a face map from the active object";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_poll;
+ ot->exec = face_map_remove_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int face_map_assign_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
+
+ cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ *map = ob->actfmap - 1;
+ }
+ }
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_assign(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Assign Face Map";
+ ot->idname = "OBJECT_OT_face_map_assign";
+ ot->description = "Assign faces to a face map";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_assign_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int face_map_remove_from_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+ int mapindex = ob->actfmap - 1;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ return OPERATOR_CANCELLED;
+
+ cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && *map == mapindex) {
+ *map = -1;
+ }
+ }
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove From Face Map";
+ ot->idname = "OBJECT_OT_face_map_remove_from";
+ ot->description = "Remove faces from a face map";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_remove_from_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static void fmap_select(Object *ob, bool select)
+{
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+ int mapindex = ob->actfmap - 1;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
+
+ cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (*map == mapindex) {
+ BM_face_select_set(em->bm, efa, select);
+ }
+ }
+}
+
+static int face_map_select_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ fmap_select(ob, true);
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_select(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Face Map Faces";
+ ot->idname = "OBJECT_OT_face_map_select";
+ ot->description = "Select faces belonging to a face map";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_select_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int face_map_deselect_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ fmap_select(ob, false);
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Deselect Face Map Faces";
+ ot->idname = "OBJECT_OT_face_map_deselect";
+ ot->description = "Deselect faces belonging to a face map";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_deselect_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+static int face_map_move_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap;
+ int dir = RNA_enum_get(op->ptr, "direction");
+ int pos1, pos2 = -1, count;
+
+ fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+ if (!fmap) {
+ return OPERATOR_CANCELLED;
+ }
+
+ count = BLI_listbase_count(&ob->fmaps);
+ pos1 = BLI_findindex(&ob->fmaps, fmap);
+
+ if (dir == 1) { /*up*/
+ void *prev = fmap->prev;
+
+ if (prev) {
+ pos2 = pos1 - 1;
+ }
+ else {
+ pos2 = count - 1;
+ }
+
+ BLI_remlink(&ob->fmaps, fmap);
+ BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
+ }
+ else { /*down*/
+ void *next = fmap->next;
+
+ if (next) {
+ pos2 = pos1 + 1;
+ }
+ else {
+ pos2 = 0;
+ }
+
+ BLI_remlink(&ob->fmaps, fmap);
+ BLI_insertlinkafter(&ob->fmaps, next, fmap);
+ }
+
+ /* iterate through mesh and substitute the indices as necessary */
+ object_facemap_swap(ob, pos2, pos1);
+
+ ob->actfmap = pos2 + 1;
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void OBJECT_OT_face_map_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem fmap_slot_move[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Move Face Map";
+ ot->idname = "OBJECT_OT_face_map_move";
+ ot->description = "Move the active face map up/down in the list";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_poll;
+ ot->exec = face_map_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "direction", fmap_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
+}
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 46c2c4e4b7d..cb0fbdda970 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -40,7 +40,6 @@
#include "DNA_scene_types.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_group.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
@@ -48,6 +47,8 @@
#include "BKE_report.h"
#include "BKE_object.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_screen.h"
#include "ED_object.h"
@@ -128,7 +129,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 +151,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 {
@@ -167,7 +167,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
if (!updated)
return OPERATOR_CANCELLED;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -200,8 +200,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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
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 +221,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;
@@ -231,7 +231,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
if (!ok)
BKE_report(op->reports, RPT_ERROR, "Active object contains no groups");
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -264,15 +264,14 @@ 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;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -297,7 +296,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 +313,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;
@@ -324,7 +322,7 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
if (!updated)
return OPERATOR_CANCELLED;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -357,7 +355,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,11 +364,11 @@ 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;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -398,7 +395,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 +403,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 +428,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 +452,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 +485,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);
@@ -559,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 42e3a4a6837..93546b1bd5d 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -48,7 +48,7 @@
#include "BKE_action.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -57,6 +57,9 @@
#include "BKE_deform.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RNA_define.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
@@ -318,7 +321,7 @@ static bool object_hook_index_array(Scene *scene, Object *obedit,
EDBM_mesh_load(obedit);
EDBM_mesh_make(scene->toolsettings, obedit, true);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
em = me->edit_btmesh;
@@ -445,34 +448,37 @@ 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, ViewLayer *view_layer, Object *obedit)
{
Base *base, *basedit;
Object *ob;
- ob = BKE_object_add(bmain, scene, OB_EMPTY, NULL);
+ ob = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
- basedit = BKE_scene_base_find(scene, obedit);
- base = scene->basact;
+ basedit = BKE_view_layer_base_find(view_layer, obedit);
+ base = view_layer->basact;
base->lay = ob->lay = obedit->lay;
- BLI_assert(scene->basact->object == ob);
+ BLI_assert(view_layer->basact->object == ob);
/* icky, BKE_object_add sets new base as active.
* so set it back to the original edit object */
- scene->basact = basedit;
+ view_layer->basact = basedit;
return ob;
}
-static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob, int mode, ReportList *reports)
+static int add_hook_object(const bContext *C, Main *bmain, Scene *scene, ViewLayer *view_layer, Object *obedit, Object *ob, int mode, ReportList *reports)
{
ModifierData *md = NULL;
HookModifierData *hmd = NULL;
+ EvaluationContext eval_ctx;
float cent[3];
float pose_mat[4][4];
int tot, ok, *indexar;
char name[MAX_NAME];
+ CTX_data_eval_ctx(C, &eval_ctx);
+
ok = object_hook_index_array(scene, obedit, &tot, &indexar, name, cent);
if (!ok) {
@@ -482,7 +488,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, view_layer, obedit);
/* transform cent to global coords for loc */
mul_v3_m4v3(ob->loc, obedit->obmat, cent);
@@ -541,13 +547,13 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
/* matrix calculus */
/* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
/* (parentinv ) */
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc(&eval_ctx, scene, ob);
invert_m4_m4(ob->imat, ob->obmat);
/* apparently this call goes from right to left... */
mul_m4_series(hmd->parentinv, pose_mat, ob->imat, obedit->obmat);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
return true;
}
@@ -556,6 +562,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_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 +587,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(C, bmain, scene, view_layer, obedit, obsel, mode, op->reports)) {
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
return OPERATOR_FINISHED;
}
@@ -611,9 +618,10 @@ static int object_add_hook_newob_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_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(C, bmain, scene, view_layer, 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;
@@ -655,7 +663,7 @@ static int object_hook_remove_exec(bContext *C, wmOperator *op)
BLI_remlink(&ob->modifiers, (ModifierData *)hmd);
modifier_free((ModifierData *)hmd);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -729,7 +737,7 @@ static int object_hook_reset_exec(bContext *C, wmOperator *op)
BKE_object_modifier_hook_reset(ob, hmd);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -779,7 +787,7 @@ static int object_hook_recenter_exec(bContext *C, wmOperator *op)
sub_v3_v3v3(hmd->cent, scene->cursor, ob->obmat[3]);
mul_m3_v3(imat, hmd->cent);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -837,7 +845,7 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op)
hmd->indexar = indexar;
hmd->totindex = tot;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index b8957bdedf9..c38a7d58904 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -55,6 +55,7 @@ void OBJECT_OT_scale_clear(struct wmOperatorType *ot);
void OBJECT_OT_origin_clear(struct wmOperatorType *ot);
void OBJECT_OT_visual_transform_apply(struct wmOperatorType *ot);
void OBJECT_OT_transform_apply(struct wmOperatorType *ot);
+void OBJECT_OT_transform_axis_target(struct wmOperatorType *ot);
void OBJECT_OT_origin_set(struct wmOperatorType *ot);
/* object_relations.c */
@@ -67,10 +68,10 @@ void OBJECT_OT_track_clear(struct wmOperatorType *ot);
void OBJECT_OT_slow_parent_set(struct wmOperatorType *ot);
void OBJECT_OT_slow_parent_clear(struct wmOperatorType *ot);
void OBJECT_OT_make_local(struct wmOperatorType *ot);
+void OBJECT_OT_make_override(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 +79,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);
@@ -117,6 +114,7 @@ void OBJECT_OT_metaball_add(struct wmOperatorType *ot);
void OBJECT_OT_text_add(struct wmOperatorType *ot);
void OBJECT_OT_armature_add(struct wmOperatorType *ot);
void OBJECT_OT_empty_add(struct wmOperatorType *ot);
+void OBJECT_OT_lightprobe_add(struct wmOperatorType *ot);
void OBJECT_OT_drop_named_image(struct wmOperatorType *ot);
void OBJECT_OT_lamp_add(struct wmOperatorType *ot);
void OBJECT_OT_effector_add(struct wmOperatorType *ot);
@@ -247,6 +245,15 @@ void OBJECT_OT_vertex_weight_set_active(struct wmOperatorType *ot);
void OBJECT_OT_vertex_weight_normalize_active_vertex(struct wmOperatorType *ot);
void OBJECT_OT_vertex_weight_copy(struct wmOperatorType *ot);
+/* object_facemap_ops.c */
+void OBJECT_OT_face_map_add(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_remove(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_assign(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_select(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_move(struct wmOperatorType *ot);
+
/* object_warp.c */
void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c
index 57053ddc020..b2f9bee27ff 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/object/object_lattice.c
@@ -52,12 +52,13 @@
#include "RNA_enum_types.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_deform.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "ED_lattice.h"
#include "ED_object.h"
#include "ED_screen.h"
@@ -590,7 +591,7 @@ static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
return OPERATOR_FINISHED;
@@ -810,7 +811,7 @@ static int lattice_flip_exec(bContext *C, wmOperator *op)
}
/* updates */
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 4e90a9bc7c4..ca58a60806c 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -54,7 +54,6 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_DerivedMesh.h"
#include "BKE_effect.h"
@@ -75,6 +74,9 @@
#include "BKE_softbody.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -171,8 +173,8 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
}
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- DAG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
return new_md;
}
@@ -253,7 +255,7 @@ bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v)
for (md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Multires) {
multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
return false;
@@ -320,7 +322,7 @@ static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
ob->mode &= ~OB_MODE_PARTICLE_EDIT;
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
BLI_remlink(&ob->modifiers, md);
modifier_free(md);
@@ -341,8 +343,8 @@ bool ED_object_modifier_remove(ReportList *reports, Main *bmain, Object *ob, Mod
return 0;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- DAG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
return 1;
}
@@ -365,8 +367,8 @@ void ED_object_modifier_clear(Main *bmain, Object *ob)
md = next_md;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- DAG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
}
int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
@@ -411,7 +413,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, ViewLayer *view_layer, Object *ob, ModifierData *md)
{
Object *obn;
ParticleSystem *psys;
@@ -463,7 +465,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, view_layer, OB_MESH, NULL);
me = obn->data;
me->totvert = totvert;
@@ -515,14 +517,17 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
}
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
return 1;
}
-static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
+static int modifier_apply_shape(ReportList *reports, const bContext *C, Scene *scene, Object *ob, ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
md->scene = scene;
@@ -553,7 +558,7 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M
return 0;
}
- dm = mesh_create_derived_for_modifier(scene, ob, md, 0);
+ dm = mesh_create_derived_for_modifier(&eval_ctx, scene, ob, md, 0);
if (!dm) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
return 0;
@@ -580,9 +585,12 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M
return 1;
}
-static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
+static int modifier_apply_obdata(ReportList *reports, const bContext *C, Scene *scene, Object *ob, ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
md->scene = scene;
@@ -606,13 +614,13 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob,
multires_force_update(ob);
if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
- if (!multiresModifier_reshapeFromDeformMod(scene, mmd, ob, md)) {
+ if (!multiresModifier_reshapeFromDeformMod(&eval_ctx, scene, mmd, ob, md)) {
BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
return 0;
}
}
else {
- dm = mesh_create_derived_for_modifier(scene, ob, md, 1);
+ dm = mesh_create_derived_for_modifier(&eval_ctx, scene, ob, md, 1);
if (!dm) {
BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
return 0;
@@ -638,12 +646,12 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob,
BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices");
vertexCos = BKE_curve_nurbs_vertexCos_get(&cu->nurb, &numVerts);
- mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0);
+ mti->deformVerts(md, &eval_ctx, ob, NULL, vertexCos, numVerts, 0);
BK_curve_nurbs_vertexCos_apply(&cu->nurb, vertexCos);
MEM_freeN(vertexCos);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else {
BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
@@ -660,14 +668,14 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob,
if (psys->part->type != PART_HAIR)
continue;
- psys_apply_hair_lattice(scene, ob, psys);
+ psys_apply_hair_lattice(&eval_ctx, scene, ob, psys);
}
}
return 1;
}
-int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode)
+int ED_object_modifier_apply(ReportList *reports, const bContext *C, Scene *scene, Object *ob, ModifierData *md, int mode)
{
int prev_mode;
@@ -695,13 +703,13 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi
md->mode |= eModifierMode_Realtime;
if (mode == MODIFIER_APPLY_SHAPE) {
- if (!modifier_apply_shape(reports, scene, ob, md)) {
+ if (!modifier_apply_shape(reports, C, scene, ob, md)) {
md->mode = prev_mode;
return 0;
}
}
else {
- if (!modifier_apply_obdata(reports, scene, ob, md)) {
+ if (!modifier_apply_obdata(reports, C, scene, ob, md)) {
md->mode = prev_mode;
return 0;
}
@@ -874,7 +882,7 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
static int modifier_remove_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(op, ob, 0);
int mode_orig = ob->mode;
@@ -887,7 +895,7 @@ static int modifier_remove_exec(bContext *C, wmOperator *op)
/* if cloth/softbody was removed, particle mode could be cleared */
if (mode_orig & OB_MODE_PARTICLE_EDIT)
if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0)
- if (scene->basact && scene->basact->object == ob)
+ if (view_layer->basact && view_layer->basact->object == ob)
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
return OPERATOR_FINISHED;
@@ -926,7 +934,7 @@ static int modifier_move_up_exec(bContext *C, wmOperator *op)
if (!md || !ED_object_modifier_move_up(op->reports, ob, md))
return OPERATOR_CANCELLED;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -965,7 +973,7 @@ static int modifier_move_down_exec(bContext *C, wmOperator *op)
if (!md || !ED_object_modifier_move_down(op->reports, ob, md))
return OPERATOR_CANCELLED;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -1003,11 +1011,11 @@ static int modifier_apply_exec(bContext *C, wmOperator *op)
ModifierData *md = edit_modifier_property_get(op, ob, 0);
int apply_as = RNA_enum_get(op->ptr, "apply_as");
- if (!md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) {
+ if (!md || !ED_object_modifier_apply(op->reports, C, scene, ob, md, apply_as)) {
return OPERATOR_CANCELLED;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -1050,13 +1058,14 @@ static int modifier_convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_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, view_layer, ob, md))
return OPERATOR_CANCELLED;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -1095,7 +1104,7 @@ static int modifier_copy_exec(bContext *C, wmOperator *op)
if (!md || !ED_object_modifier_copy(op->reports, ob, md))
return OPERATOR_CANCELLED;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -1189,7 +1198,7 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op)
ED_object_multires_update_totlevels_cb,
&mmd->totlvl);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
if (ob->mode & OB_MODE_SCULPT) {
@@ -1229,8 +1238,11 @@ static int multires_reshape_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_active_context(C), *secondob = NULL;
Scene *scene = CTX_data_scene(C);
+ EvaluationContext eval_ctx;
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (!mmd)
return OPERATOR_CANCELLED;
@@ -1253,12 +1265,12 @@ static int multires_reshape_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (!multiresModifier_reshape(scene, mmd, ob, secondob)) {
+ if (!multiresModifier_reshape(&eval_ctx, scene, mmd, ob, secondob)) {
BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices");
return OPERATOR_CANCELLED;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -1406,7 +1418,7 @@ static int multires_base_apply_exec(bContext *C, wmOperator *op)
multiresModifier_base_apply(mmd, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -1512,7 +1524,7 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op))
BLI_gset_free(visited, NULL);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -1567,7 +1579,7 @@ static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -1617,7 +1629,7 @@ static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -1686,8 +1698,10 @@ 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(const bContext *C, Scene *scene, ViewLayer *view_layer, Object *skin_ob)
{
+ Main *bmain = CTX_data_main(C);
+ EvaluationContext eval_ctx;
BLI_bitmap *edges_visited;
DerivedMesh *deform_dm;
MVert *mvert;
@@ -1699,7 +1713,9 @@ static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object *
int *emap_mem;
int v;
- deform_dm = mesh_get_derived_deform(scene, skin_ob, CD_MASK_BAREMESH);
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ deform_dm = mesh_get_derived_deform(&eval_ctx, scene, skin_ob, CD_MASK_BAREMESH);
mvert = deform_dm->getVertArray(deform_dm);
/* add vertex weights to original mesh */
@@ -1709,7 +1725,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, view_layer, OB_ARMATURE, NULL);
BKE_object_transform_copy(arm_ob, skin_ob);
arm = arm_ob->data;
arm->layer = 1;
@@ -1768,6 +1784,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = CTX_data_active_object(C), *arm_ob;
Mesh *me = ob->data;
ModifierData *skin_md;
@@ -1779,7 +1796,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(C, scene, view_layer, ob);
/* add a modifier to connect the new armature to the mesh */
arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature);
@@ -1789,8 +1806,8 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op)
arm_md->object = arm_ob;
arm_md->deformflag = ARM_DEF_VGROUP | ARM_DEF_QUATERNION;
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
@@ -1857,7 +1874,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op)
csmd->bind_coords_num = (unsigned int)-1;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -1899,8 +1916,11 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
+ EvaluationContext eval_ctx;
MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform);
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (!mmd)
return OPERATOR_CANCELLED;
@@ -1926,7 +1946,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
mmd->totcagevert = 0;
mmd->totinfluence = 0;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
}
else {
@@ -1938,17 +1958,17 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
mmd->modifier.mode |= eModifierMode_Realtime;
if (ob->type == OB_MESH) {
- dm = mesh_create_derived_view(scene, ob, 0);
+ dm = mesh_create_derived_view(&eval_ctx, scene, ob, 0);
dm->release(dm);
}
else if (ob->type == OB_LATTICE) {
- BKE_lattice_modifiers_calc(scene, ob);
+ BKE_lattice_modifiers_calc(&eval_ctx, scene, ob);
}
else if (ob->type == OB_MBALL) {
- BKE_displist_make_mball(CTX_data_main(C)->eval_ctx, scene, ob);
+ BKE_displist_make_mball(&eval_ctx, scene, ob);
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- BKE_displist_make_curveTypes(scene, ob, 0);
+ BKE_displist_make_curveTypes(&eval_ctx, scene, ob, 0);
}
mmd->bindfunc = NULL;
@@ -2000,7 +2020,7 @@ static int explode_refresh_exec(bContext *C, wmOperator *op)
emd->flag |= eExplodeFlag_CalcFaces;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
@@ -2145,7 +2165,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
if (free) {
omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
}
@@ -2173,7 +2193,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
* this part of the process before a threaded job is created */
//scene->r.cfra = f;
- //ED_update_for_newframe(CTX_data_main(C), scene, 1);
+ //ED_update_for_newframe(CTX_data_main(C), scene);
/* ok, this doesn't work with drivers, but is way faster.
* let's use this for now and hope nobody wants to drive the time value... */
@@ -2195,7 +2215,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
scene->r.cfra = cfra;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
#endif
@@ -2268,7 +2288,7 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op)
else {
lmd->flag |= MOD_LAPLACIANDEFORM_BIND;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
}
@@ -2320,7 +2340,7 @@ static int surfacedeform_bind_exec(bContext *C, wmOperator *op)
smd->flags |= MOD_SDEF_BIND;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 9b9f77a1dbb..ceea3b9c0ac 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -61,16 +61,13 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_origin_clear);
WM_operatortype_append(OBJECT_OT_visual_transform_apply);
WM_operatortype_append(OBJECT_OT_transform_apply);
+ WM_operatortype_append(OBJECT_OT_transform_axis_target);
WM_operatortype_append(OBJECT_OT_origin_set);
WM_operatortype_append(OBJECT_OT_mode_set);
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);
@@ -87,16 +84,15 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_slow_parent_set);
WM_operatortype_append(OBJECT_OT_slow_parent_clear);
WM_operatortype_append(OBJECT_OT_make_local);
+ WM_operatortype_append(OBJECT_OT_make_override);
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);
@@ -113,6 +109,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_text_add);
WM_operatortype_append(OBJECT_OT_armature_add);
WM_operatortype_append(OBJECT_OT_empty_add);
+ WM_operatortype_append(OBJECT_OT_lightprobe_add);
WM_operatortype_append(OBJECT_OT_drop_named_image);
WM_operatortype_append(OBJECT_OT_lamp_add);
WM_operatortype_append(OBJECT_OT_camera_add);
@@ -202,6 +199,14 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active_vertex);
WM_operatortype_append(OBJECT_OT_vertex_weight_copy);
+ WM_operatortype_append(OBJECT_OT_face_map_add);
+ WM_operatortype_append(OBJECT_OT_face_map_remove);
+ WM_operatortype_append(OBJECT_OT_face_map_assign);
+ WM_operatortype_append(OBJECT_OT_face_map_remove_from);
+ WM_operatortype_append(OBJECT_OT_face_map_select);
+ WM_operatortype_append(OBJECT_OT_face_map_deselect);
+ WM_operatortype_append(OBJECT_OT_face_map_move);
+
WM_operatortype_append(TRANSFORM_OT_vertex_warp);
WM_operatortype_append(OBJECT_OT_game_property_new);
@@ -376,25 +381,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 f8c80f2a933..95ccf56d409 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -63,10 +63,10 @@
#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"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_global.h"
@@ -75,9 +75,12 @@
#include "BKE_idprop.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
+#include "BKE_library_override.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
+#include "BKE_lightprobe.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mball.h"
@@ -92,6 +95,9 @@
#include "BKE_texture.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -123,7 +129,9 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
+ EvaluationContext eval_ctx;
BMVert *eve;
BMIter iter;
Curve *cu;
@@ -133,6 +141,8 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
Object *par;
int a, v1 = 0, v2 = 0, v3 = 0, v4 = 0, nr = 1;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* we need 1 to 3 selected vertices */
if (obedit->type == OB_MESH) {
@@ -142,7 +152,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
EDBM_mesh_load(obedit);
EDBM_mesh_make(scene->toolsettings, obedit, true);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
em = me->edit_btmesh;
@@ -151,7 +161,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
/* derivedMesh might be needed for solving parenting,
* so re-create it here */
- makeDerivedMesh(scene, obedit, em, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX, false);
+ makeDerivedMesh(&eval_ctx, scene, obedit, em, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX, false);
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
@@ -230,7 +240,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob != obedit) {
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
par = obedit->parent;
if (BKE_object_parent_loop_check(par, ob)) {
@@ -239,7 +249,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
else {
Object workob;
- ob->parent = BASACT->object;
+ ob->parent = BASACT(view_layer)->object;
if (v3) {
ob->partype = PARVERT3;
ob->par1 = v1 - 1;
@@ -247,7 +257,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
ob->par3 = v3 - 1;
/* inverse parent matrix */
- BKE_object_workob_calc_parent(scene, ob, &workob);
+ BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
else {
@@ -255,7 +265,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
ob->par1 = v1 - 1;
/* inverse parent matrix */
- BKE_object_workob_calc_parent(scene, ob, &workob);
+ BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
}
@@ -263,7 +273,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT, NULL);
@@ -332,44 +342,41 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob, *gob = ED_object_active_context(C);
- GroupObject *go;
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
if (gob->dup_group != NULL) {
- go = BLI_findlink(&gob->dup_group->gobject, RNA_enum_get(op->ptr, "object"));
- ob = go->ob;
+ Base *base = BLI_findlink(&gob->dup_group->view_layer->object_bases, RNA_enum_get(op->ptr, "object"));
+ ob = base->object;
}
else {
ob = gob;
- gob = NULL;
}
if (ob) {
Object *newob;
- Base *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_from(bmain, scene, view_layer, OB_EMPTY, name, gob ? gob : ob);
/* set layers OK */
- newbase = BASACT; /* BKE_object_add sets active... */
- newbase->lay = oldbase->lay;
- newob->lay = newbase->lay;
-
- /* remove base, leave user count of object, it gets linked in BKE_object_make_proxy */
- if (gob == NULL) {
- BKE_scene_base_unlink(scene, oldbase);
- MEM_freeN(oldbase);
- }
-
BKE_object_make_proxy(newob, ob, gob);
+ /* Set back pointer immediately so dependency graph knows that this is
+ * is a proxy and will act accordingly. Otherwise correctness of graph
+ * will depend on order of bases.
+ *
+ * TODO(sergey): We really need to get rid of this bi-directional links
+ * in proxies with something like static overrides.
+ */
+ newob->proxy->proxy_from = newob;
+
/* depsgraph flushes are needed for the new data */
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&newob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&newob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
}
else {
@@ -388,17 +395,18 @@ static const EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA
int totitem = 0;
int i = 0;
Object *ob = ED_object_active_context(C);
- GroupObject *go;
if (!ob || !ob->dup_group)
return DummyRNA_DEFAULT_items;
/* find the object to affect */
- for (go = ob->dup_group->gobject.first; go; go = go->next) {
- item_tmp.identifier = item_tmp.name = go->ob->id.name + 2;
+ FOREACH_GROUP_OBJECT(ob->dup_group, object)
+ {
+ item_tmp.identifier = item_tmp.name = object->id.name + 2;
item_tmp.value = i++;
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
+ FOREACH_GROUP_OBJECT_END
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -524,7 +532,7 @@ void ED_object_parent_clear(Object *ob, const int type)
/* Always clear parentinv matrix for sake of consistency, see T41950. */
unit_m4(ob->parentinv);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
/* note, poll should check for editable scene */
@@ -539,7 +547,7 @@ static int parent_clear_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
return OPERATOR_FINISHED;
@@ -607,13 +615,17 @@ EnumPropertyItem prop_make_parent_types[] = {
{0, NULL, 0, NULL, NULL}
};
-bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object *ob, Object *par,
+bool ED_object_parent_set(ReportList *reports, const bContext *C, Scene *scene, Object *ob, Object *par,
int partype, const bool xmirror, const bool keep_transform, const int vert_par[3])
{
+ Main *bmain = CTX_data_main(C);
+ EvaluationContext eval_ctx;
bPoseChannel *pchan = NULL;
const bool pararm = ELEM(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
- DAG_id_tag_update(&par->id, OB_RECALC_OB);
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ DEG_id_tag_update(&par->id, OB_RECALC_OB);
/* preconditions */
if (partype == PAR_FOLLOW || partype == PAR_PATH_CONST) {
@@ -624,7 +636,7 @@ bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
if ((cu->flag & CU_PATH) == 0) {
cu->flag |= CU_PATH | CU_FOLLOW;
- BKE_displist_make_curveTypes(scene, par, 0); /* force creation of path data */
+ BKE_displist_make_curveTypes(&eval_ctx, scene, par, 0); /* force creation of path data */
}
else {
cu->flag |= CU_FOLLOW;
@@ -710,7 +722,7 @@ bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
((CurveModifierData *)md)->object = par;
}
if (par->curve_cache && par->curve_cache->path == NULL) {
- DAG_id_tag_update(&par->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&par->id, OB_RECALC_DATA);
}
}
break;
@@ -766,34 +778,36 @@ bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
data = con->data;
data->tar = par;
- BKE_constraint_target_matrix_get(scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
+ BKE_constraint_target_matrix_get(&eval_ctx, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
sub_v3_v3v3(vec, ob->obmat[3], cmat[3]);
copy_v3_v3(ob->loc, vec);
}
else if (pararm && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) {
- if (partype == PAR_ARMATURE_NAME)
- create_vgroups_from_armature(reports, scene, ob, par, ARM_GROUPS_NAME, false);
- else if (partype == PAR_ARMATURE_ENVELOPE)
- create_vgroups_from_armature(reports, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
+ if (partype == PAR_ARMATURE_NAME) {
+ create_vgroups_from_armature(reports, &eval_ctx, scene, ob, par, ARM_GROUPS_NAME, false);
+ }
+ else if (partype == PAR_ARMATURE_ENVELOPE) {
+ create_vgroups_from_armature(reports, &eval_ctx, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
+ }
else if (partype == PAR_ARMATURE_AUTO) {
WM_cursor_wait(1);
- create_vgroups_from_armature(reports, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
+ create_vgroups_from_armature(reports, &eval_ctx, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
WM_cursor_wait(0);
}
/* get corrected inverse */
ob->partype = PAROBJECT;
- BKE_object_workob_calc_parent(scene, ob, &workob);
+ BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
else {
/* calculate inverse parent matrix */
- BKE_object_workob_calc_parent(scene, ob, &workob);
+ BKE_object_workob_calc_parent(&eval_ctx, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
}
}
@@ -864,7 +878,7 @@ static int parent_set_exec(bContext *C, wmOperator *op)
parent_set_vert_find(tree, ob, vert_par, is_tri);
}
- if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
+ if (!ED_object_parent_set(op->reports, C, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
ok = false;
break;
}
@@ -879,7 +893,7 @@ static int parent_set_exec(bContext *C, wmOperator *op)
if (!ok)
return OPERATOR_CANCELLED;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
@@ -996,7 +1010,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Object *par = ED_object_active_context(C);
- DAG_id_tag_update(&par->id, OB_RECALC_OB);
+ DEG_id_tag_update(&par->id, OB_RECALC_OB);
/* context iterator */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -1011,7 +1025,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
memset(ob->loc, 0, 3 * sizeof(float));
/* set recalc flags */
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
/* set parenting type for object - object only... */
ob->parent = par;
@@ -1021,7 +1035,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -1048,15 +1062,18 @@ void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
static int object_slow_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob->parent) {
if (ob->partype & PARSLOW) {
ob->partype -= PARSLOW;
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc(&eval_ctx, scene, ob);
ob->partype |= PARSLOW;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
}
@@ -1094,7 +1111,7 @@ static int object_slow_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
if (ob->parent)
ob->partype |= PARSLOW;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
@@ -1148,7 +1165,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
/* remove track-object for old track */
ob->track = NULL;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* also remove all tracking constraints */
for (con = ob->constraints.last; con; con = pcon) {
@@ -1162,7 +1179,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -1222,7 +1239,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
data = con->data;
data->tar = obact;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
@@ -1245,7 +1262,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
data = con->data;
data->tar = obact;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
@@ -1269,7 +1286,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
data = con->data;
data->tar = obact;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
@@ -1283,7 +1300,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
}
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -1309,119 +1326,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
@@ -1444,20 +1348,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"));
@@ -1477,9 +1367,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ SceneCollection *sc_to = BKE_collection_master(&scene_to->id);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- ED_object_scene_link(scene_to, base->object);
+ BKE_collection_object_add(&scene_to->id, sc_to, base->object);
}
CTX_DATA_END;
@@ -1535,7 +1426,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;
@@ -1572,7 +1462,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
/* if amount of material indices changed: */
test_object_materials(ob_dst, ob_dst->data);
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
break;
case MAKE_LINKS_MATERIALS:
/* new approach, using functions from kernel */
@@ -1580,7 +1470,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
Material *ma = give_current_material(ob_src, a + 1);
assign_material(ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF); /* also works with ma==NULL */
}
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
break;
case MAKE_LINKS_ANIMDATA:
BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, false);
@@ -1591,19 +1481,19 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
}
BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, false);
}
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
case MAKE_LINKS_GROUP:
{
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;
@@ -1620,7 +1510,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
break;
case MAKE_LINKS_MODIFIERS:
BKE_object_link_modifiers(ob_dst, ob_src);
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
case MAKE_LINKS_FONTS:
{
@@ -1649,7 +1539,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
cu_dst->vfontbi = cu_src->vfontbi;
id_us_plus((ID *)cu_dst->vfontbi);
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
}
}
@@ -1672,7 +1562,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_WARNING, "Skipped editing library object data");
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, CTX_wm_view3d(C));
WM_event_add_notifier(C, NC_OBJECT, NULL);
@@ -1736,69 +1626,106 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
-/* 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)
+static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups)
{
- Base *base;
- Object *ob, *obn;
- Group *group, *groupn;
- GroupObject *go;
+ if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
+ /* base gets copy of object */
+ Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
- clear_sca_new_poins(); /* BGE logic */
+ if (copy_groups) {
+ if (ob->flag & OB_FROMGROUP) {
+ obn->flag |= OB_FROMGROUP;
+ }
+ }
+ else {
+ /* copy already clears */
+ }
+ /* remap gpencil parenting */
- /* duplicate (must set newid) */
- for (base = FIRSTBASE; base; base = base->next) {
- ob = base->object;
+ if (scene->gpd) {
+ bGPdata *gpd = scene->gpd;
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->parent == ob) {
+ gpl->parent = obn;
+ }
+ }
+ }
- if ((base->flag & flag) == flag) {
- if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
- /* base gets copy of object */
- base->object = obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
+ id_us_min(&ob->id);
+ return obn;
+ }
+ return NULL;
+}
- if (copy_groups) {
- if (ob->flag & OB_FROMGROUP) {
- obn->flag |= OB_FROMGROUP;
- }
- }
- else {
- /* copy already clears */
- }
- /* remap gpencil parenting */
+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);
+ }
- if (scene->gpd) {
- bGPdata *gpd = scene->gpd;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->parent == ob) {
- gpl->parent = obn;
- }
- }
- }
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ libblock_relink_scene_collection(nsc);
+ }
+}
- base->flag = obn->flag;
+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);
+ }
+ }
- id_us_min(&ob->id);
- }
+ /* 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)
+{
+ Group *group, *groupn;
+
+ clear_sca_new_poins(); /* BGE logic */
+
+ /* duplicate all the objects of the scene */
+ SceneCollection *msc = BKE_collection_master(&scene->id);
+ single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups);
+
+ /* loop over ViewLayers and assign the pointers accordingly */
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ ID_NEW_REMAP(base->object);
}
}
/* duplicate groups that consist entirely of duplicated objects */
for (group = bmain->group.first; group; group = group->id.next) {
- if (copy_groups && group->gobject.first) {
+ if (copy_groups && group->view_layer->object_bases.first) {
bool all_duplicated = true;
- for (go = group->gobject.first; go; go = go->next) {
- if (!(go->ob && (go->ob->id.newid))) {
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ if (object->id.newid == NULL) {
all_duplicated = false;
break;
}
}
+ FOREACH_GROUP_OBJECT_END
if (all_duplicated) {
groupn = ID_NEW_SET(group, BKE_group_copy(bmain, group));
- for (go = groupn->gobject.first; go; go = go->next) {
- go->ob = (Object *)go->ob->id.newid;
+ FOREACH_GROUP_BASE(groupn, base)
+ {
+ base->object = (Object *)base->object->id.newid;
}
+ FOREACH_GROUP_BASE_END
}
}
}
@@ -1810,27 +1737,28 @@ 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;
+ 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);
}
@@ -1855,25 +1783,23 @@ static void new_id_matar(Main *bmain, Material **matar, const int totcol)
}
}
-static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
+static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag)
{
- Object *ob;
Lamp *la;
Curve *cu;
/* Camera *cam; */
- Base *base;
Mesh *me;
Lattice *lat;
ID *id;
int a;
- for (base = FIRSTBASE; base; base = base->next) {
- ob = base->object;
- if (!ID_IS_LINKED(ob) && (base->flag & flag) == flag) {
+ FOREACH_OBJECT_FLAG(scene, view_layer, flag, ob)
+ {
+ if (!ID_IS_LINKED(ob)) {
id = ob->data;
if (id && id->us > 1 && !ID_IS_LINKED(id)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
switch (ob->type) {
case OB_LAMP:
@@ -1911,16 +1837,22 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
BKE_animdata_copy_id_action((ID *)lat->key, false);
break;
case OB_ARMATURE:
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
BKE_pose_rebuild(ob, ob->data);
break;
case OB_SPEAKER:
ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
break;
+ case OB_LIGHTPROBE:
+ ob->data = ID_NEW_SET(ob->data, BKE_lightprobe_copy(bmain, ob->data));
+ break;
default:
- if (G.debug & G_DEBUG)
- printf("ERROR %s: can't copy %s\n", __func__, id->name);
+ printf("ERROR %s: can't copy %s\n", __func__, id->name);
+ BLI_assert(!"This should never happen.");
+
+ /* We need to end the FOREACH_OBJECT_FLAG iterator to prevent memory leak. */
+ BKE_scene_objects_iterator_end(&iter_macro);
return;
}
@@ -1935,6 +1867,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
}
}
}
+ FOREACH_OBJECT_FLAG_END
me = bmain->mesh.first;
while (me) {
@@ -1943,31 +1876,24 @@ 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, ViewLayer *view_layer, const int flag)
{
- Object *ob;
- Base *base;
-
- for (base = FIRSTBASE; base; base = base->next) {
- ob = base->object;
- if (!ID_IS_LINKED(ob) && (flag == 0 || (base->flag & SELECT)) ) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ FOREACH_OBJECT_FLAG(scene, view_layer, flag, ob)
+ if (!ID_IS_LINKED(ob)) {
+ DEG_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, ViewLayer *view_layer, 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(ob) && (flag == 0 || (base->flag & SELECT)) ) {
+ FOREACH_OBJECT_FLAG(scene, view_layer, flag, ob)
+ if (!ID_IS_LINKED(ob)) {
for (a = 1; a <= ob->totcol; a++) {
ma = give_current_material(ob, a);
if (ma) {
@@ -1996,7 +1922,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)
@@ -2099,8 +2025,8 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
single_object_users(bmain, scene, NULL, 0, copy_groups);
if (full) {
- single_obdata_users(bmain, scene, 0);
- single_object_action_users(scene, 0);
+ single_obdata_users(bmain, scene, NULL, 0);
+ single_object_action_users(scene, NULL, 0);
single_mat_users_expand(bmain);
single_tex_users_expand(bmain);
}
@@ -2121,12 +2047,13 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
{
IDP_RelinkProperty(scene->id.properties);
- for (Base *base = scene->base.first; base; base = base->next) {
- Object *ob = base->object;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
if (!ID_IS_LINKED(ob)) {
IDP_RelinkProperty(ob->id.properties);
}
}
+ FOREACH_SCENE_OBJECT_END
if (scene->nodetree) {
IDP_RelinkProperty(scene->nodetree->id.properties);
@@ -2148,7 +2075,7 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
}
}
BKE_main_id_clear_newpoins(bmain);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
/******************************* Make Local ***********************************/
@@ -2215,7 +2142,7 @@ static void tag_localizable_objects(bContext *C, const int mode)
* Instance indirectly referenced zero user objects,
* otherwise they're lost on reload, see T40595.
*/
-static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene)
+static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene, ViewLayer *view_layer, SceneCollection *sc)
{
Object *ob;
bool changed = false;
@@ -2226,10 +2153,11 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene)
id_us_plus(&ob->id);
- base = BKE_scene_base_add(scene, ob);
- base->flag |= SELECT;
- base->object->flag = base->flag;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ BKE_collection_object_add(&scene->id, sc, ob);
+ base = BKE_view_layer_base_find(view_layer, ob);
+ base->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(base);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
changed = true;
}
@@ -2308,12 +2236,15 @@ static int make_local_exec(bContext *C, wmOperator *op)
/* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */
if (mode == MAKE_LOCAL_ALL) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SceneCollection *scene_collection = CTX_data_scene_collection(C);
+
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
- /* de-select so the user can differentiate newly instanced from existing objects */
- BKE_scene_base_deselect_all(scene);
+ /* De-select so the user can differentiate newly instanced from existing objects. */
+ BKE_view_layer_base_deselect_all(view_layer);
- if (make_local_all__instance_indirect_unused(bmain, scene)) {
+ if (make_local_all__instance_indirect_unused(bmain, scene, view_layer, scene_collection)) {
BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss");
}
}
@@ -2404,6 +2335,44 @@ void OBJECT_OT_make_local(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
+static int make_override_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ Object *locobj, *refobj = CTX_data_active_object(C);
+
+ locobj = (Object *)BKE_override_static_create_from(bmain, &refobj->id);
+ UNUSED_VARS(locobj);
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int make_override_poll(bContext *C)
+{
+ Object *obact = CTX_data_active_object(C);
+
+ /* Object must be directly linked to be overridable. */
+ return (ED_operator_objectmode(C) && obact && obact->id.lib != NULL && obact->id.tag & LIB_TAG_EXTERN);
+}
+
+void OBJECT_OT_make_override(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Make Override";
+ ot->description = "Make local override of this library linked data-block";
+ ot->idname = "OBJECT_OT_make_override";
+
+ /* api callbacks */
+ ot->exec = make_override_exec;
+ ot->poll = make_override_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+}
+
enum {
MAKE_SINGLE_USER_ALL = 1,
MAKE_SINGLE_USER_SELECTED = 2,
@@ -2413,24 +2382,31 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_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_view_layer_selected_objects_tag(view_layer, 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;
}
if (RNA_boolean_get(op->ptr, "obdata")) {
- single_obdata_users(bmain, scene, flag);
+ single_obdata_users(bmain, scene, view_layer, flag);
}
if (RNA_boolean_get(op->ptr, "material")) {
- single_mat_users(bmain, scene, flag, RNA_boolean_get(op->ptr, "texture"));
+ single_mat_users(bmain, scene, view_layer, flag, RNA_boolean_get(op->ptr, "texture"));
}
#if 0 /* can't do this separate from materials */
@@ -2438,7 +2414,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, view_layer, flag);
}
BKE_main_id_clear_newpoins(bmain);
@@ -2446,7 +2422,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WINDOW, NULL);
if (update_deps) {
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
return OPERATOR_FINISHED;
@@ -2496,7 +2472,7 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent
assign_material(base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF);
- DAG_id_tag_update(&base->object->id, OB_RECALC_OB);
+ DEG_id_tag_update(&base->object->id, OB_RECALC_OB);
WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, base->object);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 8d5c2387fe9..552380cebdb 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -41,6 +41,7 @@
#include "DNA_scene_types.h"
#include "DNA_armature_types.h"
#include "DNA_lamp_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
@@ -52,12 +53,14 @@
#include "BKE_context.h"
#include "BKE_group.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_particle.h"
#include "BKE_property.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_workspace.h"
#include "BKE_library.h"
#include "BKE_deform.h"
@@ -86,37 +89,47 @@
/* 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_object_base_select(Base *base, eObjectSelect_Mode mode)
{
+ if (mode == BA_INVERT) {
+ mode = (base->flag & BASE_SELECTED) != 0 ? BA_DESELECT : BA_SELECT;
+ }
+
if (base) {
- if (mode == BA_SELECT) {
- if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
- base->flag |= SELECT;
- }
- else if (mode == BA_DESELECT) {
- base->flag &= ~SELECT;
+ switch (mode) {
+ case BA_SELECT:
+ if ((base->flag & BASE_SELECTABLED) != 0) {
+ base->flag |= BASE_SELECTED;
+ }
+ break;
+ case BA_DESELECT:
+ base->flag &= ~BASE_SELECTED;
+ break;
+ case BA_INVERT:
+ /* Never happens. */
+ break;
}
- base->object->flag = base->flag;
+ BKE_scene_object_base_flag_sync_from_base(base);
}
}
-/* also to set active NULL */
-void ED_base_object_activate(bContext *C, Base *base)
+/**
+ * Change active base, it includes the notifier
+ */
+void ED_object_base_activate(bContext *C, Base *base)
{
- Scene *scene = CTX_data_scene(C);
-
- /* sets scene->basact */
- BASACT = base;
-
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ view_layer->basact = base;
+
if (base) {
-
- /* XXX old signals, remember to handle notifiers now! */
- // select_actionchannel_by_name(base->object->action, "Object", 1);
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+#ifdef USE_WORKSPACE_MODE
+ BKE_workspace_object_mode_set(CTX_wm_workspace(C), CTX_data_scene(C), base->object->mode);
+#endif
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, view_layer);
}
- else
+ else {
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL);
+ }
}
/********************** Selection Operators **********************/
@@ -147,7 +160,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 +168,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 +223,15 @@ static const 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 +247,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 +257,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 +265,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 +273,6 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
}
}
}
-
- base->object->flag = base->flag;
}
}
CTX_DATA_END;
@@ -299,12 +287,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 +307,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 +335,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 +353,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 +388,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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob;
int nr = RNA_enum_get(op->ptr, "type");
bool changed = false, extend;
@@ -417,12 +398,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(view_layer);
if (ob == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active object");
return OPERATOR_CANCELLED;
@@ -517,7 +498,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 +514,6 @@ static const 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 +531,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 +547,20 @@ 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);
- View3D *v3d = CTX_wm_view3d(C);
-
- bool changed = false;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
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_view_layer_base_find(view_layer, 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);
+ if (baspar && BASE_SELECTABLE(baspar)) {
+ ED_object_base_select(baspar, BA_SELECT);
+ ED_object_base_activate(C, baspar);
changed = true;
}
return changed;
@@ -608,9 +589,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;
@@ -632,8 +615,7 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in
static bool select_grouped_object_hooks(bContext *C, Object *ob)
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
bool changed = false;
Base *base;
@@ -644,9 +626,9 @@ static bool select_grouped_object_hooks(bContext *C, Object *ob)
if (md->type == eModifierType_Hook) {
hmd = (HookModifierData *) md;
if (hmd->object && !(hmd->object->flag & SELECT)) {
- base = BKE_scene_base_find(scene, hmd->object);
- if (base && (BASE_SELECTABLE(v3d, base))) {
- ED_base_object_select(base, BA_SELECT);
+ base = BKE_view_layer_base_find(view_layer, hmd->object);
+ if (base && (BASE_SELECTABLE(base))) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -663,8 +645,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 +663,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 +678,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 +693,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 +708,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 +735,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 +774,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 +783,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 +798,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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob;
const int type = RNA_enum_get(op->ptr, "type");
bool changed = false, extend;
@@ -840,13 +808,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(view_layer);
if (ob == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active object");
return OPERATOR_CANCELLED;
@@ -868,9 +836,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 +893,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 const 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 +906,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 +918,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 +978,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 +1013,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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
bool extend;
extend = RNA_boolean_get(op->ptr, "extend");
@@ -1137,15 +1027,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_view_layer_base_find(view_layer, 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 +1070,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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
Object *ob = base->object;
ob->flag &= ~OB_DONE;
ob->id.tag &= ~LIB_TAG_DOIT;
@@ -1223,7 +1113,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 +1195,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_shapekey.c b/source/blender/editors/object/object_shapekey.c
index 27da607c696..1f80cb5f0bc 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -51,7 +51,6 @@
#include "DNA_object_types.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_key.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -59,6 +58,9 @@
#include "BKE_lattice.h"
#include "BKE_curve.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "BLI_sys_types.h" // for intptr_t support
#include "ED_object.h"
@@ -213,7 +215,7 @@ static bool object_shape_key_mirror(bContext *C, Object *ob,
*r_totmirr = totmirr;
*r_totfail = totfail;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return 1;
@@ -264,8 +266,8 @@ static int shape_key_add_exec(bContext *C, wmOperator *op)
ED_object_shape_key_add(C, ob, from_mix);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(CTX_data_main(C));
return OPERATOR_FINISHED;
}
@@ -302,8 +304,8 @@ static int shape_key_remove_exec(bContext *C, wmOperator *op)
}
if (changed) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
@@ -343,7 +345,7 @@ static int shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
for (kb = key->block.first; kb; kb = kb->next)
kb->curval = 0.0f;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
@@ -378,7 +380,7 @@ static int shape_key_retime_exec(bContext *C, wmOperator *UNUSED(op))
for (kb = key->block.first; kb; kb = kb->next)
kb->pos = (cfra += 0.1f);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
@@ -469,7 +471,7 @@ static int shape_key_move_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 9fea7bf5b89..100b9018d00 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -39,14 +39,15 @@
#include "DNA_scene_types.h"
#include "DNA_group_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_lamp_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
+#include "BLI_array.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_idcode.h"
#include "BKE_mball.h"
@@ -59,6 +60,8 @@
#include "BKE_lattice.h"
#include "BKE_tracking.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_define.h"
#include "RNA_access.h"
@@ -71,6 +74,8 @@
#include "ED_screen.h"
#include "ED_view3d.h"
+#include "MEM_guardedalloc.h"
+
#include "object_intern.h"
/*************************** Clear Transformation ****************************/
@@ -265,7 +270,7 @@ static int object_clear_transform_generic_exec(bContext *C, wmOperator *op,
ED_autokeyframe_object(C, scene, ob, ks);
/* tag for updates */
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
CTX_DATA_END;
@@ -371,7 +376,7 @@ static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
mul_m3_v3(mat, v3);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
@@ -399,16 +404,19 @@ void OBJECT_OT_origin_clear(wmOperatorType *ot)
/* use this when the loc/size/rot of the parent has changed but the children
* should stay in the same place, e.g. for apply-size-rot or object center */
-static void ignore_parent_tx(Main *bmain, Scene *scene, Object *ob)
+static void ignore_parent_tx(const bContext *C, Main *bmain, Scene *scene, Object *ob)
{
Object workob;
Object *ob_child;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
/* a change was made, adjust the children to compensate */
for (ob_child = bmain->object.first; ob_child; ob_child = ob_child->id.next) {
if (ob_child->parent == ob) {
BKE_object_apply_mat4(ob_child, ob_child->obmat, true, false);
- BKE_object_workob_calc_parent(scene, ob_child, &workob);
+ BKE_object_workob_calc_parent(&eval_ctx, scene, ob_child, &workob);
invert_m4_m4(ob_child->parentinv, workob.obmat);
}
}
@@ -421,8 +429,11 @@ static int apply_objects_internal(
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ EvaluationContext eval_ctx;
float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
bool changed = true;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
/* first check if we can execute */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -525,7 +536,7 @@ static int apply_objects_internal(
Mesh *me = ob->data;
if (apply_scale)
- multiresModifier_scale_disp(scene, ob);
+ multiresModifier_scale_disp(&eval_ctx, scene, ob);
/* adjust data */
BKE_mesh_transform(me, mat, true);
@@ -615,14 +626,14 @@ static int apply_objects_internal(
unit_axis_angle(ob->rotAxis, &ob->rotAngle);
}
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc(&eval_ctx, scene, ob);
if (ob->type == OB_ARMATURE) {
- BKE_pose_where_is(scene, ob); /* needed for bone parents */
+ BKE_pose_where_is(&eval_ctx, scene, ob); /* needed for bone parents */
}
- ignore_parent_tx(bmain, scene, ob);
+ ignore_parent_tx(C, bmain, scene, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
changed = true;
}
@@ -640,16 +651,19 @@ static int apply_objects_internal(
static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
+ EvaluationContext eval_ctx;
bool changed = false;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc(&eval_ctx, scene, ob);
BKE_object_apply_mat4(ob, ob->obmat, true, true);
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc(&eval_ctx, scene, ob);
/* update for any children that may get moved */
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
changed = true;
}
@@ -730,6 +744,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
Object *obedit = CTX_data_edit_object(C);
+ EvaluationContext eval_ctx;
Object *tob;
float cursor[3], cent[3], cent_neg[3], centn[3];
int centermode = RNA_enum_get(op->ptr, "type");
@@ -739,6 +754,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
CollectionPointerLink *ctx_ob;
CollectionPointerLink *ctx_ob_act = NULL;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* keep track of what is changed */
int tot_change = 0, tot_lib_error = 0, tot_multiuser_arm_error = 0;
@@ -793,7 +810,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
EDBM_mesh_normals_update(em);
tot_change++;
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
}
}
@@ -918,7 +935,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if (obedit) {
if (centermode == GEOMETRY_TO_ORIGIN) {
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
}
break;
}
@@ -971,10 +988,10 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
arm->id.tag |= LIB_TAG_DOIT;
/* do_inverse_offset = true; */ /* docenter_armature() handles this */
- BKE_object_where_is_calc(scene, ob);
- BKE_pose_where_is(scene, ob); /* needed for bone parents */
+ BKE_object_where_is_calc(&eval_ctx, scene, ob);
+ BKE_pose_where_is(&eval_ctx, scene, ob); /* needed for bone parents */
- ignore_parent_tx(bmain, scene, ob);
+ ignore_parent_tx(C, bmain, scene, ob);
if (obedit)
break;
@@ -996,7 +1013,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if (obedit) {
if (centermode == GEOMETRY_TO_ORIGIN) {
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
}
break;
}
@@ -1030,12 +1047,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
add_v3_v3(ob->loc, centn);
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc(&eval_ctx, scene, ob);
if (ob->type == OB_ARMATURE) {
- BKE_pose_where_is(scene, ob); /* needed for bone parents */
+ BKE_pose_where_is(&eval_ctx, scene, ob); /* needed for bone parents */
}
- ignore_parent_tx(bmain, scene, ob);
+ ignore_parent_tx(C, bmain, scene, ob);
/* other users? */
//CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects)
@@ -1054,16 +1071,16 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
(ob->transflag | ob_other->transflag) & OB_DUPLIGROUP)))
{
ob_other->flag |= OB_DONE;
- DAG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA);
mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
add_v3_v3(ob_other->loc, centn);
- BKE_object_where_is_calc(scene, ob_other);
+ BKE_object_where_is_calc(&eval_ctx, scene, ob_other);
if (ob_other->type == OB_ARMATURE) {
- BKE_pose_where_is(scene, ob_other); /* needed for bone parents */
+ BKE_pose_where_is(&eval_ctx, scene, ob_other); /* needed for bone parents */
}
- ignore_parent_tx(bmain, scene, ob_other);
+ ignore_parent_tx(C, bmain, scene, ob_other);
}
}
//CTX_DATA_END;
@@ -1072,9 +1089,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
}
BLI_freelistN(&ctx_data_list);
- for (tob = bmain->object.first; tob; tob = tob->id.next)
- if (tob->data && (((ID *)tob->data)->tag & LIB_TAG_DOIT))
- DAG_id_tag_update(&tob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ for (tob = bmain->object.first; tob; tob = tob->id.next) {
+ if (tob->data && (((ID *)tob->data)->tag & LIB_TAG_DOIT)) {
+ BKE_mesh_batch_cache_dirty(tob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ DEG_id_tag_update(&tob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ }
+ }
if (tot_change) {
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -1131,3 +1151,389 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEAN, "Center", "");
}
+
+/* -------------------------------------------------------------------- */
+
+/** \name Transform Axis Target
+ *
+ * Note this is an experemental operator to point lamps/cameras at objects.
+ * We may re-work how this behaves based on user feedback.
+ * - campbell.
+ * \{ */
+
+/* When using multiple objects, apply their relative rotational offset to the active object. */
+#define USE_RELATIVE_ROTATION
+
+struct XFormAxisItem {
+ Object *ob;
+ float rot_mat[3][3];
+ void *obtfm;
+ float xform_dist;
+
+#ifdef USE_RELATIVE_ROTATION
+ /* use when translating multiple */
+ float xform_rot_offset[3][3];
+#endif
+};
+
+struct XFormAxisData {
+ ViewContext vc;
+ struct {
+ float depth;
+ float normal[3];
+ bool is_depth_valid;
+ bool is_normal_valid;
+ } prev;
+
+ struct XFormAxisItem *object_data;
+ uint object_data_len;
+ bool is_translate;
+
+ int init_event;
+};
+
+static bool object_is_target_compat(const Object *ob)
+{
+ if (ob->type == OB_LAMP) {
+ const Lamp *la = ob->data;
+ if (ELEM(la->type, LA_SUN, LA_SPOT, LA_HEMI, LA_AREA)) {
+ return true;
+ }
+ }
+ /* We might want to enable this later, for now just lamps */
+#if 0
+ else if (ob->type == OB_CAMERA) {
+ return true;
+ }
+#endif
+ return false;
+}
+
+static void object_transform_axis_target_free_data(wmOperator *op)
+{
+ struct XFormAxisData *xfd = op->customdata;
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ MEM_freeN(item->obtfm);
+ }
+ MEM_freeN(xfd->object_data);
+ MEM_freeN(xfd);
+ op->customdata = NULL;
+}
+
+/* We may want to expose as alternative to: BKE_object_apply_rotation */
+static void object_apply_rotation(Object *ob, const float rmat[3][3])
+{
+ float size[3];
+ float loc[3];
+ float rmat4[4][4];
+ copy_m4_m3(rmat4, rmat);
+
+ copy_v3_v3(size, ob->size);
+ copy_v3_v3(loc, ob->loc);
+ BKE_object_apply_mat4(ob, rmat4, true, true);
+ copy_v3_v3(ob->size, size);
+ copy_v3_v3(ob->loc, loc);
+}
+/* We may want to extract this to: BKE_object_apply_location */
+static void object_apply_location(Object *ob, const float loc[3])
+{
+ /* quick but weak */
+ Object ob_prev = *ob;
+ float mat[4][4];
+ copy_m4_m4(mat, ob->obmat);
+ copy_v3_v3(mat[3], loc);
+ BKE_object_apply_mat4(ob, mat, true, true);
+ copy_v3_v3(mat[3], ob->loc);
+ *ob = ob_prev;
+ copy_v3_v3(ob->loc, mat[3]);
+}
+
+static void object_orient_to_location(
+ Object *ob, float rot_orig[3][3], const float axis[3], const float location[3])
+{
+ float delta[3];
+ sub_v3_v3v3(delta, ob->obmat[3], location);
+ if (normalize_v3(delta) != 0.0f) {
+ if (len_squared_v3v3(delta, axis) > FLT_EPSILON) {
+ float delta_rot[3][3];
+ float final_rot[3][3];
+ rotation_between_vecs_to_mat3(delta_rot, axis, delta);
+
+ mul_m3_m3m3(final_rot, delta_rot, rot_orig);
+
+ object_apply_rotation(ob, final_rot);
+
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
+ }
+ }
+}
+
+static void object_transform_axis_target_cancel(bContext *C, wmOperator *op)
+{
+ struct XFormAxisData *xfd = op->customdata;
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ BKE_object_tfm_restore(item->ob, item->obtfm);
+ DEG_id_tag_update(&item->ob->id, OB_RECALC_OB);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
+ }
+
+ object_transform_axis_target_free_data(op);
+}
+
+static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ViewContext vc;
+ view3d_set_viewcontext(C, &vc);
+
+ if (!object_is_target_compat(vc.obact)) {
+ /* Falls back to texture space transform. */
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ ED_view3d_autodist_init(&eval_ctx, vc.depsgraph, vc.ar, vc.v3d, 0);
+
+ if (vc.rv3d->depths != NULL) {
+ vc.rv3d->depths->damaged = true;
+ }
+ ED_view3d_depth_update(vc.ar);
+
+ if (vc.rv3d->depths == NULL) {
+ BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_region_tag_redraw(vc.ar);
+
+ struct XFormAxisData *xfd;
+ xfd = op->customdata = MEM_callocN(sizeof(struct XFormAxisData), __func__);
+
+ /* Don't change this at runtime. */
+ xfd->vc = vc;
+ xfd->vc.mval[0] = event->mval[0];
+ xfd->vc.mval[1] = event->mval[1];
+
+ xfd->prev.depth = 1.0f;
+ xfd->prev.is_depth_valid = false;
+ xfd->prev.is_normal_valid = false;
+ xfd->is_translate = false;
+
+ xfd->init_event = WM_userdef_event_type_from_keymap_type(event->type);
+
+ {
+ struct XFormAxisItem *object_data = NULL;
+ BLI_array_declare(object_data);
+
+ struct XFormAxisItem *item = BLI_array_append_ret(object_data);
+ item->ob = xfd->vc.obact;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
+ {
+ if ((ob != xfd->vc.obact) && object_is_target_compat(ob)) {
+ item = BLI_array_append_ret(object_data);
+ item->ob = ob;
+ }
+ }
+ CTX_DATA_END;
+
+ xfd->object_data = object_data;
+ xfd->object_data_len = BLI_array_count(object_data);
+
+ if (xfd->object_data_len != BLI_array_count(object_data)) {
+ xfd->object_data = MEM_reallocN(xfd->object_data, xfd->object_data_len * sizeof(*xfd->object_data));
+ }
+ }
+
+ {
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ item->obtfm = BKE_object_tfm_backup(item->ob);
+ BKE_object_rot_to_mat3(item->ob, item->rot_mat, true);
+ }
+ }
+
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ struct XFormAxisData *xfd = op->customdata;
+ ARegion *ar = xfd->vc.ar;
+
+ view3d_operator_needs_opengl(C);
+
+ const bool is_translate = (event->ctrl != 0);
+ const bool is_translate_init = is_translate && (xfd->is_translate != is_translate);
+
+ if (event->type == MOUSEMOVE || is_translate_init) {
+ const ViewDepths *depths = xfd->vc.rv3d->depths;
+ if (depths &&
+ ((unsigned int)event->mval[0] < depths->w) &&
+ ((unsigned int)event->mval[1] < depths->h))
+ {
+ double depth = (double)ED_view3d_depth_read_cached(&xfd->vc, event->mval);
+ float location_world[3];
+ if (depth == 1.0f) {
+ if (xfd->prev.is_depth_valid) {
+ depth = (double)xfd->prev.depth;
+ }
+ }
+ if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
+ xfd->prev.depth = depth;
+ xfd->prev.is_depth_valid = true;
+ if (ED_view3d_depth_unproject(ar, event->mval, depth, location_world)) {
+ if (is_translate) {
+
+ float normal[3];
+ bool normal_found = false;
+ if (ED_view3d_depth_read_cached_normal(&xfd->vc, event->mval, normal)) {
+ normal_found = true;
+
+ /* cheap attempt to smooth normals out a bit! */
+ const uint ofs = 2;
+ for (uint x = -ofs; x <= ofs; x += ofs / 2) {
+ for (uint y = -ofs; y <= ofs; y += ofs / 2) {
+ if (x != 0 && y != 0) {
+ int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y};
+ float n[3];
+ if (ED_view3d_depth_read_cached_normal(
+ &xfd->vc, mval_ofs, n))
+ {
+ add_v3_v3(normal, n);
+ }
+ }
+ }
+ }
+ normalize_v3(normal);
+ }
+ else if (xfd->prev.is_normal_valid) {
+ copy_v3_v3(normal, xfd->prev.normal);
+ normal_found = true;
+ }
+
+ if (normal_found) {
+#ifdef USE_RELATIVE_ROTATION
+ if (is_translate_init && xfd->object_data_len > 1) {
+ float xform_rot_offset_inv_first[3][3];
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ copy_m3_m4(item->xform_rot_offset, item->ob->obmat);
+ normalize_m3(item->xform_rot_offset);
+
+ if (i == 0) {
+ invert_m3_m3(xform_rot_offset_inv_first, xfd->object_data[0].xform_rot_offset);
+ }
+ else {
+ mul_m3_m3m3(item->xform_rot_offset,
+ item->xform_rot_offset,
+ xform_rot_offset_inv_first);
+ }
+ }
+ }
+
+#endif
+
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ if (is_translate_init) {
+ float ob_axis[3];
+ item->xform_dist = len_v3v3(item->ob->obmat[3], location_world);
+ normalize_v3_v3(ob_axis, item->ob->obmat[2]);
+ /* Scale to avoid adding distance when moving between surfaces. */
+ float scale = fabsf(dot_v3v3(ob_axis, normal));
+ item->xform_dist *= scale;
+ }
+
+ float target_normal[3];
+ copy_v3_v3(target_normal, normal);
+
+#ifdef USE_RELATIVE_ROTATION
+ if (i != 0) {
+ mul_m3_v3(item->xform_rot_offset, target_normal);
+ }
+#endif
+ {
+ float loc[3];
+
+ copy_v3_v3(loc, location_world);
+ madd_v3_v3fl(loc, target_normal, item->xform_dist);
+ object_apply_location(item->ob, loc);
+ copy_v3_v3(item->ob->obmat[3], loc); /* so orient behaves as expected */
+ }
+
+ object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
+ }
+ copy_v3_v3(xfd->prev.normal, normal);
+ xfd->prev.is_normal_valid = true;
+ }
+ }
+ else {
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
+ }
+ xfd->prev.is_normal_valid = false;
+ }
+ }
+ }
+ }
+ xfd->is_translate = is_translate;
+
+ ED_region_tag_redraw(xfd->vc.ar);
+ }
+
+ bool is_finished = false;
+
+ if (ISMOUSE(xfd->init_event)) {
+ if ((event->type == xfd->init_event) && (event->val == KM_RELEASE)) {
+ is_finished = true;
+ }
+ }
+ else {
+ if (ELEM(event->type, LEFTMOUSE, RETKEY, PADENTER)) {
+ is_finished = true;
+ }
+ }
+
+ if (is_finished) {
+ object_transform_axis_target_free_data(op);
+ return OPERATOR_FINISHED;
+ }
+ else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
+ object_transform_axis_target_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void OBJECT_OT_transform_axis_target(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Interactive Lamp Track to Cursor";
+ ot->description = "Interactively point cameras and lamps to a location (Ctrl translates)";
+ ot->idname = "OBJECT_OT_transform_axis_target";
+
+ /* api callbacks */
+ ot->invoke = object_transform_axis_target_invoke;
+ ot->cancel = object_transform_axis_target_cancel;
+ ot->modal = object_transform_axis_target_modal;
+ ot->poll = ED_operator_region_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+}
+
+#undef USE_RELATIVE_ROTATION
+
+/** \} */
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 9afc3772f90..bf2da284591 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -56,9 +56,9 @@
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_mesh_mapping.h"
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_modifier.h"
#include "BKE_report.h"
#include "BKE_DerivedMesh.h"
@@ -66,6 +66,8 @@
#include "BKE_object.h"
#include "BKE_lattice.h"
+#include "DEG_depsgraph.h"
+
#include "DNA_armature_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -1259,9 +1261,9 @@ static void dm_deform_clear(DerivedMesh *dm, Object *ob)
}
/* recalculate the deformation */
-static DerivedMesh *dm_deform_recalc(Scene *scene, Object *ob)
+static DerivedMesh *dm_deform_recalc(EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
- return mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+ return mesh_get_derived_deform(eval_ctx, scene, ob, CD_MASK_BAREMESH);
}
/* by changing nonzero weights, try to move a vertex in me->mverts with index 'index' to
@@ -1273,7 +1275,7 @@ static DerivedMesh *dm_deform_recalc(Scene *scene, Object *ob)
* norm and d are the plane's properties for the equation: ax + by + cz + d = 0
* coord is a point on the plane
*/
-static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, int index, float norm[3],
+static void moveCloserToDistanceFromPlane(EvaluationContext *eval_ctx, Scene *scene, Object *ob, Mesh *me, int index, float norm[3],
float coord[3], float d, float distToBe, float strength, float cp)
{
DerivedMesh *dm;
@@ -1300,7 +1302,7 @@ static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, in
float originalDistToBe = distToBe;
do {
wasChange = false;
- dm = dm_deform_recalc(scene, ob);
+ dm = dm_deform_recalc(eval_ctx, scene, ob);
dm->getVert(dm, index, &m);
copy_v3_v3(oldPos, m.co);
distToStart = dot_v3v3(norm, oldPos) + d;
@@ -1338,7 +1340,7 @@ static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, in
if (dw->weight > 1) {
dw->weight = 1;
}
- dm = dm_deform_recalc(scene, ob);
+ dm = dm_deform_recalc(eval_ctx, scene, ob);
dm->getVert(dm, index, &m);
getVerticalAndHorizontalChange(norm, d, coord, oldPos, distToStart, m.co, changes, dists, i);
dw->weight = oldw;
@@ -1448,10 +1450,13 @@ static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, in
/* this is used to try to smooth a surface by only adjusting the nonzero weights of a vertex
* but it could be used to raise or lower an existing 'bump.' */
-static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength, float cp)
+static void vgroup_fix(const bContext *C, Scene *scene, Object *ob, float distToBe, float strength, float cp)
{
+ EvaluationContext eval_ctx;
int i;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
Mesh *me = ob->data;
MVert *mvert = me->mvert;
int *verts = NULL;
@@ -1465,7 +1470,7 @@ static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength,
MVert *p = MEM_callocN(sizeof(MVert) * (count), "deformedPoints");
int k;
- DerivedMesh *dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+ DerivedMesh *dm = mesh_get_derived_deform(&eval_ctx, scene, ob, CD_MASK_BAREMESH);
k = count;
while (k--) {
dm->getVert(dm, verts[k], &m);
@@ -1483,7 +1488,7 @@ static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength,
if (mag) { /* zeros fix */
d = -dot_v3v3(norm, coord);
/* dist = (dot_v3v3(norm, m.co) + d); */ /* UNUSED */
- moveCloserToDistanceFromPlane(scene, ob, me, i, norm, coord, d, distToBe, strength, cp);
+ moveCloserToDistanceFromPlane(&eval_ctx, scene, ob, me, i, norm, coord, d, distToBe, strength, cp);
}
}
@@ -2609,7 +2614,7 @@ static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ED_object_context(C);
BKE_object_defgroup_add(ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -2642,7 +2647,7 @@ static int vertex_group_remove_exec(bContext *C, wmOperator *op)
else
vgroup_delete_active(ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -2677,7 +2682,7 @@ static int vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ED_object_context(C);
vgroup_assign_verts(ob, ts->vgroup_weight);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
return OPERATOR_FINISHED;
@@ -2750,7 +2755,7 @@ static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
return OPERATOR_FINISHED;
@@ -2839,7 +2844,7 @@ static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ED_object_context(C);
vgroup_duplicate(ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
@@ -2875,7 +2880,7 @@ static int vertex_group_levels_exec(bContext *C, wmOperator *op)
vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain);
MEM_freeN((void *)vgroup_validmap);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -2909,7 +2914,7 @@ static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op))
changed = vgroup_normalize(ob);
if (changed) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -2948,7 +2953,7 @@ static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
MEM_freeN((void *)vgroup_validmap);
if (changed) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -3001,9 +3006,9 @@ static int vertex_group_fix_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR_INVALID_CONTEXT, "This operator does not support an active mirror modifier");
return OPERATOR_CANCELLED;
}
- vgroup_fix(scene, ob, distToBe, strength, cp);
+ vgroup_fix(C, scene, ob, distToBe, strength, cp);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -3075,7 +3080,7 @@ static int vertex_group_invert_exec(bContext *C, wmOperator *op)
vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove);
MEM_freeN((void *)vgroup_validmap);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -3117,7 +3122,7 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand);
MEM_freeN((void *)vgroup_validmap);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -3159,7 +3164,7 @@ static int vertex_group_clean_exec(bContext *C, wmOperator *op)
vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single);
MEM_freeN((void *)vgroup_validmap);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -3200,7 +3205,7 @@ static int vertex_group_quantize_exec(bContext *C, wmOperator *op)
vgroup_quantize_subset(ob, vgroup_validmap, vgroup_tot, subset_count, steps);
MEM_freeN((void *)vgroup_validmap);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -3241,7 +3246,7 @@ static int vertex_group_limit_total_exec(bContext *C, wmOperator *op)
BKE_reportf(op->reports, remove_tot ? RPT_INFO : RPT_WARNING, "%d vertex weights limited", remove_tot);
if (remove_tot) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -3286,7 +3291,7 @@ static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
ED_mesh_report_mirror(op, totmirr, totfail);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -3319,25 +3324,26 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
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;
+ Object *ob_active = ED_object_context(C);
int retval = OPERATOR_CANCELLED;
- for (base = scene->base.first; base; base = base->next) {
- if (base->object->type == ob->type) {
- if (base->object != ob && base->object->data == ob->data) {
- BLI_freelistN(&base->object->defbase);
- BLI_duplicatelist(&base->object->defbase, &ob->defbase);
- base->object->actdef = ob->actdef;
+ FOREACH_SCENE_OBJECT(scene, ob_iter)
+ {
+ if (ob_iter->type == ob_active->type) {
+ if (ob_iter != ob_active && ob_iter->data == ob_active->data) {
+ BLI_freelistN(&ob_iter->defbase);
+ BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase);
+ ob_iter->actdef = ob_active->actdef;
- DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, base->object);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, base->object->data);
+ DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data);
retval = OPERATOR_FINISHED;
}
}
}
+ FOREACH_SCENE_OBJECT_END
return retval;
}
@@ -3367,7 +3373,7 @@ static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
{
if (obact != ob) {
if (ED_vgroup_array_copy(ob, obact)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
changed_tot++;
}
@@ -3410,7 +3416,7 @@ static int set_active_group_exec(bContext *C, wmOperator *op)
BLI_assert(nr + 1 >= 0);
ob->actdef = nr + 1;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
return OPERATOR_FINISHED;
@@ -3624,7 +3630,7 @@ static int vertex_group_sort_exec(bContext *C, wmOperator *op)
ret = vgroup_do_remap(ob, name_array, op);
if (ret != OPERATOR_CANCELLED) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
}
@@ -3674,7 +3680,7 @@ static int vgroup_move_exec(bContext *C, wmOperator *op)
ret = vgroup_do_remap(ob, name_array, op);
if (ret != OPERATOR_CANCELLED) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
}
}
@@ -3803,7 +3809,7 @@ static int vertex_weight_paste_exec(bContext *C, wmOperator *op)
vgroup_copy_active_to_sel_single(ob, def_nr);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
@@ -3840,7 +3846,7 @@ static int vertex_weight_delete_exec(bContext *C, wmOperator *op)
vgroup_remove_weight(ob, def_nr);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
@@ -3873,7 +3879,7 @@ static int vertex_weight_set_active_exec(bContext *C, wmOperator *op)
if (wg_index != -1) {
ob->actdef = wg_index + 1;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
@@ -3910,7 +3916,7 @@ static int vertex_weight_normalize_active_vertex_exec(bContext *C, wmOperator *U
changed = vgroup_normalize_active_vertex(ob, subset_type);
if (changed) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
@@ -3943,7 +3949,7 @@ static int vertex_weight_copy_exec(bContext *C, wmOperator *UNUSED(op))
vgroup_copy_active_to_sel(ob, subset_type);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt
index 898422dac51..3cecdccd758 100644
--- a/source/blender/editors/physics/CMakeLists.txt
+++ b/source/blender/editors/physics/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../gpu
../../makesdna
../../makesrna
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index b0c14ef3623..e068b898345 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -42,7 +42,6 @@
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_object_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_dynamicpaint.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -50,6 +49,9 @@
#include "BKE_report.h"
#include "BKE_screen.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_object.h"
@@ -135,7 +137,7 @@ static int surface_slot_remove_exec(bContext *C, wmOperator *UNUSED(op))
}
dynamicPaint_resetPreview(canvas);
- DAG_id_tag_update(&obj_ctx->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obj_ctx->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obj_ctx);
return OPERATOR_FINISHED;
@@ -181,8 +183,8 @@ static int type_toggle_exec(bContext *C, wmOperator *op)
}
/* update dependency */
- DAG_id_tag_update(&cObject->id, OB_RECALC_DATA);
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_id_tag_update(&cObject->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, cObject);
return OPERATOR_FINISHED;
@@ -286,11 +288,15 @@ typedef struct DynamicPaintBakeJob {
struct Main *bmain;
Scene *scene;
+ ViewLayer *view_layer;
+ Depsgraph *depsgraph;
Object *ob;
DynamicPaintSurface *surface;
DynamicPaintCanvasSettings *canvas;
+ EvaluationContext *eval_ctx;
+
int success;
double start;
} DynamicPaintBakeJob;
@@ -310,6 +316,8 @@ static void dpaint_bake_endjob(void *customdata)
dynamicPaint_freeSurfaceData(job->surface);
+ MEM_freeN(job->eval_ctx);
+
G.is_rendering = false;
BKE_spacedata_draw_locks(false);
@@ -357,7 +365,7 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
frame = surface->start_frame;
orig_frame = scene->r.cfra;
scene->r.cfra = (int)frame;
- ED_update_for_newframe(job->bmain, scene, 1);
+ ED_update_for_newframe(job->bmain, scene, job->view_layer, job->depsgraph);
/* Init surface */
if (!dynamicPaint_createUVSurface(scene, surface, job->progress, job->do_update)) {
@@ -383,8 +391,8 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
/* calculate a frame */
scene->r.cfra = (int)frame;
- ED_update_for_newframe(job->bmain, scene, 1);
- if (!dynamicPaint_calculateFrame(surface, scene, cObject, frame)) {
+ ED_update_for_newframe(job->bmain, scene, job->view_layer, job->depsgraph);
+ if (!dynamicPaint_calculateFrame(surface, job->eval_ctx, scene, cObject, frame)) {
job->success = 0;
return;
}
@@ -452,6 +460,10 @@ static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
DynamicPaintCanvasSettings *canvas;
Object *ob = ED_object_context(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EvaluationContext *eval_ctx = MEM_mallocN(sizeof(*eval_ctx), "EvaluationContext");
+
+ CTX_data_eval_ctx(C, eval_ctx);
DynamicPaintSurface *surface;
@@ -479,9 +491,12 @@ static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
DynamicPaintBakeJob *job = MEM_mallocN(sizeof(DynamicPaintBakeJob), "DynamicPaintBakeJob");
job->bmain = CTX_data_main(C);
job->scene = scene;
+ job->view_layer = view_layer;
+ job->depsgraph = CTX_data_depsgraph(C);
job->ob = ob;
job->canvas = canvas;
job->surface = surface;
+ job->eval_ctx = eval_ctx;
wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene,
"Dynamic Paint Bake", WM_JOB_PROGRESS,
diff --git a/source/blender/editors/physics/particle_boids.c b/source/blender/editors/physics/particle_boids.c
index 14b12497c4a..681ac75e847 100644
--- a/source/blender/editors/physics/particle_boids.c
+++ b/source/blender/editors/physics/particle_boids.c
@@ -39,10 +39,12 @@
#include "BKE_boids.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_particle.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RNA_access.h"
#include "RNA_enum_types.h"
#include "RNA_define.h"
@@ -75,7 +77,7 @@ static int rule_add_exec(bContext *C, wmOperator *op)
BLI_addtail(&state->rules, rule);
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
+ DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
return OPERATOR_FINISHED;
}
@@ -121,8 +123,8 @@ static int rule_del_exec(bContext *C, wmOperator *UNUSED(op))
if (rule)
rule->flag |= BOIDRULE_CURRENT;
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
return OPERATOR_FINISHED;
}
@@ -158,7 +160,7 @@ static int rule_move_up_exec(bContext *C, wmOperator *UNUSED(op))
BLI_remlink(&state->rules, rule);
BLI_insertlinkbefore(&state->rules, rule->prev, rule);
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
+ DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
break;
}
}
@@ -194,7 +196,7 @@ static int rule_move_down_exec(bContext *C, wmOperator *UNUSED(op))
BLI_remlink(&state->rules, rule);
BLI_insertlinkafter(&state->rules, rule->next, rule);
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
+ DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
break;
}
}
@@ -277,8 +279,8 @@ static int state_del_exec(bContext *C, wmOperator *UNUSED(op))
state->flag |= BOIDSTATE_CURRENT;
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
return OPERATOR_FINISHED;
}
@@ -349,7 +351,7 @@ static int state_move_down_exec(bContext *C, wmOperator *UNUSED(op))
if (state->flag & BOIDSTATE_CURRENT && state->next) {
BLI_remlink(&boids->states, state);
BLI_insertlinkafter(&boids->states, state->next, state);
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
+ DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
break;
}
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index da66ec44235..53bc289d378 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -53,7 +53,6 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_object.h"
@@ -64,8 +63,9 @@
#include "BKE_bvhutils.h"
#include "BKE_pointcache.h"
+#include "DEG_depsgraph.h"
+
#include "BIF_gl.h"
-#include "BIF_glutil.h"
#include "ED_object.h"
#include "ED_physics.h"
@@ -73,6 +73,9 @@
#include "ED_particle.h"
#include "ED_view3d.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+
#include "UI_resources.h"
#include "WM_api.h"
@@ -83,7 +86,9 @@
#include "physics_intern.h"
-void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
+void PE_create_particle_edit(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob,
+ PointCache *cache, ParticleSystem *psys);
void PTCacheUndo_clear(PTCacheEdit *edit);
void recalc_lengths(PTCacheEdit *edit);
void recalc_emitter_field(Object *ob, ParticleSystem *psys);
@@ -109,24 +114,26 @@ void update_world_cos(Object *ob, PTCacheEdit *edit);
int PE_poll(bContext *C)
{
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
+ if (!scene || !view_layer || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
return 0;
- return (PE_get_current(scene, ob) != NULL);
+ return (PE_get_current(scene, view_layer, ob) != NULL);
}
int PE_hair_poll(bContext *C)
{
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
PTCacheEdit *edit;
if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
return 0;
- edit= PE_get_current(scene, ob);
+ edit= PE_get_current(scene, view_layer, ob);
return (edit && edit->psys);
}
@@ -211,7 +218,8 @@ static float pe_brush_size_get(const Scene *UNUSED(scene), ParticleBrushData *br
*
* note: this function runs on poll, therefor it can runs many times a second
* keep it fast! */
-static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
+static PTCacheEdit *pe_get_current(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob, int create)
{
ParticleEditSettings *pset= PE_settings(scene);
PTCacheEdit *edit = NULL;
@@ -222,6 +230,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
return NULL;
pset->scene = scene;
+ pset->view_layer = view_layer;
pset->object = ob;
BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
@@ -250,18 +259,18 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
if (psys->part && psys->part->type == PART_HAIR) {
if (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) {
if (create && !psys->pointcache->edit)
- PE_create_particle_edit(scene, ob, pid->cache, NULL);
+ PE_create_particle_edit(eval_ctx, scene, view_layer, ob, pid->cache, NULL);
edit = pid->cache->edit;
}
else {
if (create && !psys->edit && psys->flag & PSYS_HAIR_DONE)
- PE_create_particle_edit(scene, ob, NULL, psys);
+ PE_create_particle_edit(eval_ctx, scene, view_layer, ob, NULL, psys);
edit = psys->edit;
}
}
else {
if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit)
- PE_create_particle_edit(scene, ob, pid->cache, psys);
+ PE_create_particle_edit(eval_ctx, scene, view_layer, ob, pid->cache, psys);
edit = pid->cache->edit;
}
@@ -272,7 +281,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
pset->flag |= PE_FADE_TIME;
// NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
- PE_create_particle_edit(scene, ob, pid->cache, NULL);
+ PE_create_particle_edit(eval_ctx, scene, view_layer, ob, pid->cache, NULL);
}
edit = pid->cache->edit;
break;
@@ -281,7 +290,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
pset->flag |= PE_FADE_TIME;
// NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
- PE_create_particle_edit(scene, ob, pid->cache, NULL);
+ PE_create_particle_edit(eval_ctx, scene, view_layer, ob, pid->cache, NULL);
}
edit = pid->cache->edit;
break;
@@ -296,20 +305,21 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
return edit;
}
-PTCacheEdit *PE_get_current(Scene *scene, Object *ob)
+PTCacheEdit *PE_get_current(Scene *scene, ViewLayer *view_layer, Object *ob)
{
- return pe_get_current(scene, ob, 0);
+ return pe_get_current(NULL, scene, view_layer, ob, 0);
}
-PTCacheEdit *PE_create_current(Scene *scene, Object *ob)
+PTCacheEdit *PE_create_current(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
- return pe_get_current(scene, ob, 1);
+ return pe_get_current(eval_ctx, scene, NULL, ob, 1);
}
-void PE_current_changed(Scene *scene, Object *ob)
+void PE_current_changed(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
- if (ob->mode == OB_MODE_PARTICLE_EDIT)
- PE_create_current(scene, ob);
+ if (ob->mode == OB_MODE_PARTICLE_EDIT) {
+ PE_create_current(eval_ctx, scene, ob);
+ }
}
void PE_hide_keys_time(Scene *scene, PTCacheEdit *edit, float cfra)
@@ -351,9 +361,10 @@ static int pe_x_mirror(Object *ob)
typedef struct PEData {
ViewContext vc;
- bglMats mats;
+ const bContext *context;
Scene *scene;
+ ViewLayer *view_layer;
Object *ob;
DerivedMesh *dm;
PTCacheEdit *edit;
@@ -387,9 +398,10 @@ static void PE_set_data(bContext *C, PEData *data)
{
memset(data, 0, sizeof(*data));
- data->scene= CTX_data_scene(C);
- data->ob= CTX_data_active_object(C);
- data->edit= PE_get_current(data->scene, data->ob);
+ data->scene = CTX_data_scene(C);
+ data->view_layer = CTX_data_view_layer(C);
+ data->ob = CTX_data_active_object(C);
+ data->edit = PE_get_current(data->scene, data->view_layer, data->ob);
}
static void PE_set_view3d_data(bContext *C, PEData *data)
@@ -397,15 +409,16 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
PE_set_data(C, data);
view3d_set_viewcontext(C, &data->vc);
- /* note, the object argument means the modelview matrix does not account for the objects matrix, use viewmat rather than (obmat * viewmat) */
- view3d_get_transformation(data->vc.ar, data->vc.rv3d, NULL, &data->mats);
if (V3D_IS_ZBUF(data->vc.v3d)) {
if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) {
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* needed or else the draw matrix can be incorrect */
view3d_operator_needs_opengl(C);
- ED_view3d_backbuf_validate(&data->vc);
+ ED_view3d_backbuf_validate(&eval_ctx, &data->vc);
/* we may need to force an update here by setting the rv3d as dirty
* for now it seems ok, but take care!:
* rv3d->depths->dirty = 1; */
@@ -438,7 +451,6 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[
{
View3D *v3d= data->vc.v3d;
ViewDepths *vd = data->vc.rv3d->depths;
- double ux, uy, uz;
float depth;
/* nothing to do */
@@ -454,9 +466,6 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[
}
#endif
- gluProject(co[0], co[1], co[2], data->mats.modelview, data->mats.projection,
- (GLint *)data->mats.viewport, &ux, &uy, &uz);
-
/* check if screen_co is within bounds because brush_cut uses out of screen coords */
if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) {
BLI_assert(vd && vd->depths);
@@ -466,7 +475,10 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[
else
return 0;
- if ((float)uz - 0.00001f > depth)
+ float win[3];
+ ED_view3d_project(data->vc.ar, co, win);
+
+ if (win[2] - 0.00001f > depth)
return 0;
else
return 1;
@@ -1151,12 +1163,15 @@ void recalc_emitter_field(Object *ob, ParticleSystem *psys)
BLI_kdtree_balance(edit->emitter_field);
}
-static void PE_update_selection(Scene *scene, Object *ob, int useflag)
+static void PE_update_selection(const bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, int useflag)
{
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
HairKey *hkey;
+ EvaluationContext eval_ctx;
POINT_P; KEY_K;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* flag all particles to be updated if not using flag */
if (!useflag)
LOOP_POINTS
@@ -1172,7 +1187,7 @@ static void PE_update_selection(Scene *scene, Object *ob, int useflag)
}
}
- psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering);
+ psys_cache_edit_paths(&eval_ctx, scene, ob, edit, CFRA, G.is_rendering);
/* disable update flag */
@@ -1258,12 +1273,12 @@ static void update_velocities(PTCacheEdit *edit)
}
}
-void PE_update_object(Scene *scene, Object *ob, int useflag)
+void PE_update_object(const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob, int useflag)
{
/* use this to do partial particle updates, not usable when adding or
* removing, then a full redo is necessary and calling this may crash */
ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
POINT_P;
if (!edit)
@@ -1288,7 +1303,7 @@ void PE_update_object(Scene *scene, Object *ob, int useflag)
PE_hide_keys_time(scene, edit, CFRA);
/* regenerate path caches */
- psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering);
+ psys_cache_edit_paths(eval_ctx, scene, ob, edit, CFRA, G.is_rendering);
/* disable update flag */
LOOP_POINTS {
@@ -1398,8 +1413,9 @@ static void select_action_apply(PTCacheEditPoint *point, PTCacheEditKey *key, in
static int pe_select_all_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
POINT_P; KEY_K;
int action = RNA_enum_get(op->ptr, "action");
@@ -1422,7 +1438,7 @@ static int pe_select_all_exec(bContext *C, wmOperator *op)
}
}
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(C, scene, view_layer, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1451,10 +1467,11 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec
{
PEData data;
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
POINT_P; KEY_K;
-
+
if (!PE_start_edit(edit))
return OPERATOR_CANCELLED;
@@ -1479,7 +1496,7 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec
else
for_mouse_hit_keys(&data, toggle_key_select, 1);
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(C, scene, view_layer, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1520,7 +1537,7 @@ static int select_roots_exec(bContext *C, wmOperator *op)
data.select_action = action;
foreach_point(&data, select_root);
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1585,7 +1602,7 @@ static int select_tips_exec(bContext *C, wmOperator *op)
data.select_action = action;
foreach_point(&data, select_tip);
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1624,6 +1641,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
PEData data;
int type;
Scene *scene;
+ ViewLayer *view_layer;
Object *ob;
/* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */
@@ -1643,8 +1661,9 @@ static int select_random_exec(bContext *C, wmOperator *op)
PE_set_data(C, &data);
data.select_action = SEL_SELECT;
scene = CTX_data_scene(C);
+ view_layer = CTX_data_view_layer(C);
ob = CTX_data_active_object(C);
- edit = PE_get_current(scene, ob);
+ edit = PE_get_current(scene, view_layer, ob);
rng = BLI_rng_new_srandom(seed);
@@ -1669,7 +1688,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
BLI_rng_free(rng);
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1713,7 +1732,7 @@ static int select_linked_exec(bContext *C, wmOperator *op)
data.select= !RNA_boolean_get(op->ptr, "deselect");
for_mouse_hit_keys(&data, select_keys, 1); /* nearest only */
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1761,8 +1780,9 @@ void PE_deselect_all_visible(PTCacheEdit *edit)
int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
{
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
PEData data;
if (!PE_start_edit(edit))
@@ -1777,7 +1797,7 @@ int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
for_mouse_hit_keys(&data, select_key, 0);
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(C, scene, view_layer, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1788,8 +1808,9 @@ int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
{
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
PEData data;
if (!PE_start_edit(edit))
@@ -1802,7 +1823,7 @@ int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
for_mouse_hit_keys(&data, select_key, 0);
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(C, scene, view_layer, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1813,10 +1834,11 @@ int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool extend, bool select)
{
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
ARegion *ar= CTX_wm_region(C);
ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
POINT_P; KEY_K;
@@ -1890,7 +1912,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
}
}
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(C, scene, view_layer, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1902,7 +1924,8 @@ static int hide_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_active_object(C);
Scene *scene= CTX_data_scene(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
POINT_P; KEY_K;
if (RNA_enum_get(op->ptr, "unselected")) {
@@ -1924,7 +1947,7 @@ static int hide_exec(bContext *C, wmOperator *op)
}
}
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(C, scene, view_layer, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1954,7 +1977,8 @@ static int reveal_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_active_object(C);
Scene *scene= CTX_data_scene(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
const bool select = RNA_boolean_get(op->ptr, "select");
POINT_P; KEY_K;
@@ -1969,7 +1993,7 @@ static int reveal_exec(bContext *C, wmOperator *op)
}
}
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(C, scene, view_layer, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -2031,7 +2055,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
PE_set_data(C, &data);
foreach_point(&data, select_less_keys);
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -2093,7 +2117,7 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
PE_set_data(C, &data);
foreach_point(&data, select_more_keys);
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(C, data.scene, data.view_layer, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -2126,12 +2150,15 @@ static void rekey_particle(PEData *data, int pa_index)
ParticleKey state;
HairKey *key, *new_keys, *okey;
PTCacheEditKey *ekey;
+ EvaluationContext eval_ctx;
float dval, sta, end;
int k;
- sim.scene= data->scene;
- sim.ob= data->ob;
- sim.psys= edit->psys;
+ CTX_data_eval_ctx(data->context, &eval_ctx);
+ sim.eval_ctx = &eval_ctx;
+ sim.scene = data->scene;
+ sim.ob = data->ob;
+ sim.psys = edit->psys;
pa->flag |= PARS_REKEY;
@@ -2182,6 +2209,9 @@ static int rekey_exec(bContext *C, wmOperator *op)
{
PEData data;
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
PE_set_data(C, &data);
data.dval= 1.0f / (float)(data.totrekey-1);
@@ -2190,7 +2220,7 @@ static int rekey_exec(bContext *C, wmOperator *op)
foreach_selected_point(&data, rekey_particle);
recalc_lengths(data.edit);
- PE_update_object(data.scene, data.ob, 1);
+ PE_update_object(&eval_ctx, data.scene, data.view_layer, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
return OPERATOR_FINISHED;
@@ -2215,24 +2245,28 @@ void PARTICLE_OT_rekey(wmOperatorType *ot)
RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
}
-static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time)
+static void rekey_particle_to_time(const bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, int pa_index, float path_time)
{
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
ParticleSystem *psys;
- ParticleSimulationData sim= {0};
+ ParticleSimulationData sim = {0};
ParticleData *pa;
ParticleKey state;
HairKey *new_keys, *key;
PTCacheEditKey *ekey;
+ EvaluationContext eval_ctx;
int k;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (!edit || !edit->psys) return;
psys = edit->psys;
- sim.scene= scene;
- sim.ob= ob;
- sim.psys= psys;
+ sim.eval_ctx = &eval_ctx;
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psys;
pa= psys->particles + pa_index;
@@ -2442,14 +2476,17 @@ static void subdivide_particle(PEData *data, int pa_index)
ParticleKey state;
HairKey *key, *nkey, *new_keys;
PTCacheEditKey *ekey, *nekey, *new_ekeys;
+ EvaluationContext eval_ctx;
int k;
short totnewkey=0;
float endtime;
- sim.scene= data->scene;
- sim.ob= data->ob;
- sim.psys= edit->psys;
+ CTX_data_eval_ctx(data->context, &eval_ctx);
+ sim.eval_ctx = &eval_ctx;
+ sim.scene = data->scene;
+ sim.ob = data->ob;
+ sim.psys = edit->psys;
for (k=0, ekey=point->keys; k<pa->totkey-1; k++, ekey++) {
if (ekey->flag&PEK_SELECT && (ekey+1)->flag&PEK_SELECT)
@@ -2517,11 +2554,14 @@ static int subdivide_exec(bContext *C, wmOperator *UNUSED(op))
{
PEData data;
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
PE_set_data(C, &data);
foreach_point(&data, subdivide_particle);
recalc_lengths(data.edit);
- PE_update_object(data.scene, data.ob, 1);
+ PE_update_object(&eval_ctx, data.scene, data.view_layer, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
return OPERATOR_FINISHED;
@@ -2547,8 +2587,9 @@ void PARTICLE_OT_subdivide(wmOperatorType *ot)
static int remove_doubles_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd;
KDTree *tree;
@@ -2610,7 +2651,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
BKE_reportf(op->reports, RPT_INFO, "Removed %d double particles", totremoved);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
return OPERATOR_FINISHED;
@@ -2639,9 +2680,10 @@ void PARTICLE_OT_remove_doubles(wmOperatorType *ot)
static int weight_set_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
ParticleEditSettings *pset= PE_settings(scene);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
ParticleSystem *psys = edit->psys;
POINT_P;
KEY_K;
@@ -2662,7 +2704,7 @@ static int weight_set_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
return OPERATOR_FINISHED;
@@ -2694,24 +2736,27 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)
ParticleEditSettings *pset= PE_settings(scene);
ParticleBrushData *brush;
- if (pset->brushtype < 0)
+ if (pset->brushtype < 0) {
return;
+ }
- brush= &pset->brush[pset->brushtype];
+ brush = &pset->brush[pset->brushtype];
if (brush) {
- glPushMatrix();
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glTranslatef((float)x, (float)y, 0.0f);
+ immUniformColor4ub(255, 255, 255, 128);
- glColor4ub(255, 255, 255, 128);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glutil_draw_lined_arc(0.0, M_PI*2.0, pe_brush_size_get(scene, brush), 40);
+
+ imm_draw_circle_wire_2d(pos, (float)x, (float)y, pe_brush_size_get(scene, brush), 40);
+
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
+
+ immUnbindProgram();
}
}
@@ -2768,7 +2813,7 @@ static int delete_exec(bContext *C, wmOperator *op)
recalc_lengths(data.edit);
}
- DAG_id_tag_update(&data.ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&data.ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
return OPERATOR_FINISHED;
@@ -2795,11 +2840,11 @@ void PARTICLE_OT_delete(wmOperatorType *ot)
/*************************** mirror operator **************************/
-static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
+static void PE_mirror_x(Scene *scene, ViewLayer *view_layer, Object *ob, int tagged)
{
Mesh *me= (Mesh *)(ob->data);
ParticleSystemModifierData *psmd;
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
ParticleSystem *psys = edit->psys;
ParticleData *pa, *newpa, *new_pars;
PTCacheEditPoint *newpoint, *new_points;
@@ -2946,14 +2991,15 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
static int mirror_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
- PE_mirror_x(scene, ob, 0);
+ PE_mirror_x(scene, view_layer, ob, 0);
update_world_cos(ob, edit);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
return OPERATOR_FINISHED;
}
@@ -3086,7 +3132,7 @@ static void brush_cut(PEData *data, int pa_index)
edit->points[pa_index].flag |= PEP_TAG;
}
else {
- rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
+ rekey_particle_to_time(data->context, data->scene, data->view_layer, ob, pa_index, cut_time);
edit->points[pa_index].flag |= PEP_EDIT_RECALC;
}
}
@@ -3334,25 +3380,28 @@ static void intersect_dm_quad_weights(const float v1[3], const float v2[3], cons
}
/* check intersection with a derivedmesh */
-static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm,
+static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, DerivedMesh *dm,
float *vert_cos,
const float co1[3], const float co2[3],
float *min_d, int *min_face, float *min_w,
float *face_minmax, float *pa_minmax,
float radius, float *ipoint)
{
+ EvaluationContext eval_ctx;
MFace *mface= NULL;
MVert *mvert= NULL;
int i, totface, intersect=0;
float cur_d, cur_uv[2], v1[3], v2[3], v3[3], v4[3], min[3], max[3], p_min[3], p_max[3];
float cur_ipoint[3];
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (dm == NULL) {
psys_disable_all(ob);
- dm=mesh_get_derived_final(scene, ob, 0);
+ dm = mesh_get_derived_final(&eval_ctx, scene, ob, 0);
if (dm == NULL)
- dm=mesh_get_derived_deform(scene, ob, 0);
+ dm = mesh_get_derived_deform(&eval_ctx, scene, ob, 0);
psys_enable_all(ob);
@@ -3465,8 +3514,9 @@ static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm,
return intersect;
}
-static int brush_add(PEData *data, short number)
+static int brush_add(const bContext *C, PEData *data, short number)
{
+ EvaluationContext eval_ctx;
Scene *scene= data->scene;
Object *ob= data->ob;
DerivedMesh *dm;
@@ -3494,6 +3544,9 @@ static int brush_add(PEData *data, short number)
rng = BLI_rng_new_srandom(psys->seed+data->mval[0]+data->mval[1]);
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ sim.eval_ctx = &eval_ctx;
sim.scene= scene;
sim.ob= ob;
sim.psys= psys;
@@ -3534,7 +3587,7 @@ static int brush_add(PEData *data, short number)
min_d=2.0;
/* warning, returns the derived mesh face */
- if (particle_intersect_dm(scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
+ if (particle_intersect_dm(C, scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
if (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly) {
add_pars[n].num = add_pars[n].num_dmcache;
add_pars[n].num_dmcache = DMCACHE_ISCHILD;
@@ -3715,6 +3768,7 @@ static int brush_add(PEData *data, short number)
typedef struct BrushEdit {
Scene *scene;
+ ViewLayer *view_layer;
Object *ob;
PTCacheEdit *edit;
@@ -3729,9 +3783,10 @@ typedef struct BrushEdit {
static int brush_edit_init(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= CTX_data_active_object(C);
ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
ARegion *ar= CTX_wm_region(C);
BrushEdit *bedit;
float min[3], max[3];
@@ -3741,7 +3796,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
/* set the 'distance factor' for grabbing (used in comb etc) */
INIT_MINMAX(min, max);
- PE_minmax(scene, min, max);
+ PE_minmax(scene, view_layer, min, max);
mid_v3_v3v3(min, min, max);
bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit");
@@ -3749,6 +3804,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
op->customdata= bedit;
bedit->scene= scene;
+ bedit->view_layer = view_layer;
bedit->ob= ob;
bedit->edit= edit;
@@ -3764,6 +3820,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
{
BrushEdit *bedit= op->customdata;
Scene *scene= bedit->scene;
+ ViewLayer *view_layer = bedit->view_layer;
Object *ob= bedit->ob;
PTCacheEdit *edit= bedit->edit;
ParticleEditSettings *pset= PE_settings(scene);
@@ -3779,6 +3836,9 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (!PE_start_edit(edit))
return;
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
RNA_float_get_array(itemptr, "mouse", mousef);
mouse[0] = mousef[0];
mouse[1] = mousef[1];
@@ -3904,7 +3964,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (edit->psys && edit->psys->part->from==PART_FROM_FACE) {
data.mval= mval;
- added= brush_add(&data, brush->count);
+ added= brush_add(C, &data, brush->count);
if (pset->flag & PE_KEEP_LENGTHS)
recalc_lengths(edit);
@@ -3954,21 +4014,22 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT) && (added || removed)) {
if (pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob))
- PE_mirror_x(scene, ob, 1);
+ PE_mirror_x(scene, view_layer, ob, 1);
update_world_cos(ob, edit);
psys_free_path_cache(NULL, edit);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+ else {
+ PE_update_object(&eval_ctx, scene, view_layer, ob, 1);
}
- else
- PE_update_object(scene, ob, 1);
}
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
}
else {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
}
@@ -4176,7 +4237,7 @@ static void shape_cut(PEData *data, int pa_index)
edit->points[pa_index].flag |= PEP_TAG;
}
else {
- rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
+ rekey_particle_to_time(data->context, data->scene, data->view_layer, ob, pa_index, cut_time);
edit->points[pa_index].flag |= PEP_EDIT_RECALC;
}
}
@@ -4185,9 +4246,10 @@ static void shape_cut(PEData *data, int pa_index)
static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = CTX_data_active_object(C);
ParticleEditSettings *pset = PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
Object *shapeob = pset->shape_object;
int selected = count_selected_keys(scene, edit);
int lock_root = pset->flag & PE_LOCK_FIRST;
@@ -4195,6 +4257,9 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
if (!PE_start_edit(edit))
return OPERATOR_CANCELLED;
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* disable locking temporatily for disconnected hair */
if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
pset->flag &= ~PE_LOCK_FIRST;
@@ -4220,16 +4285,17 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
if (removed) {
update_world_cos(ob, edit);
psys_free_path_cache(NULL, edit);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+ else {
+ PE_update_object(&eval_ctx, scene, view_layer, ob, 1);
}
- else
- PE_update_object(scene, ob, 1);
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
}
else {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
}
@@ -4395,9 +4461,9 @@ static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
}
}
-void PE_undo_push(Scene *scene, const char *str)
+void PE_undo_push(Scene *scene, ViewLayer *view_layer, const char *str)
{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, OBACT(view_layer));
PTCacheUndo *undo;
int nr;
@@ -4437,9 +4503,9 @@ void PE_undo_push(Scene *scene, const char *str)
make_PTCacheUndo(edit, edit->curundo);
}
-void PE_undo_step(Scene *scene, int step)
+void PE_undo_step(Scene *scene, ViewLayer *view_layer, int step)
{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, OBACT(view_layer));
if (!edit) return;
@@ -4470,12 +4536,12 @@ void PE_undo_step(Scene *scene, int step)
}
}
- DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&OBACT(view_layer)->id, OB_RECALC_DATA);
}
-bool PE_undo_is_valid(Scene *scene)
+bool PE_undo_is_valid(Scene *scene, ViewLayer *view_layer)
{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, OBACT(view_layer));
if (edit) {
return (edit->undo.last != edit->undo.first);
@@ -4498,19 +4564,19 @@ void PTCacheUndo_clear(PTCacheEdit *edit)
edit->curundo= NULL;
}
-void PE_undo(Scene *scene)
+void PE_undo(Scene *scene, ViewLayer *view_layer)
{
- PE_undo_step(scene, 1);
+ PE_undo_step(scene, view_layer, 1);
}
-void PE_redo(Scene *scene)
+void PE_redo(Scene *scene, ViewLayer *view_layer)
{
- PE_undo_step(scene, -1);
+ PE_undo_step(scene, view_layer, -1);
}
-void PE_undo_number(Scene *scene, int nr)
+void PE_undo_number(Scene *scene, ViewLayer *view_layer, int nr)
{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, OBACT(view_layer));
PTCacheUndo *undo;
int a=0;
@@ -4518,15 +4584,15 @@ void PE_undo_number(Scene *scene, int nr)
if (a==nr) break;
}
edit->curundo= undo;
- PE_undo_step(scene, 0);
+ PE_undo_step(scene, view_layer, 0);
}
/* get name of undo item, return null if no item with this index */
/* if active pointer, set it to 1 if true */
-const char *PE_undo_get_name(Scene *scene, int nr, bool *r_active)
+const char *PE_undo_get_name(Scene *scene, ViewLayer *view_layer, int nr, bool *r_active)
{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, OBACT(view_layer));
PTCacheUndo *undo;
if (r_active) *r_active = false;
@@ -4545,10 +4611,10 @@ const char *PE_undo_get_name(Scene *scene, int nr, bool *r_active)
/************************ utilities ******************************/
-int PE_minmax(Scene *scene, float min[3], float max[3])
+int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
{
- Object *ob= OBACT;
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ Object *ob= OBACT(view_layer);
+ PTCacheEdit *edit= PE_get_current(scene, view_layer, ob);
ParticleSystem *psys;
ParticleSystemModifierData *psmd = NULL;
POINT_P; KEY_K;
@@ -4585,7 +4651,8 @@ int PE_minmax(Scene *scene, float min[3], float max[3])
/************************ particle edit toggle operator ************************/
/* initialize needed data for bake edit */
-void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
+void PE_create_particle_edit(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob, PointCache *cache, ParticleSystem *psys)
{
PTCacheEdit *edit;
ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
@@ -4686,10 +4753,10 @@ void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, Partic
recalc_lengths(edit);
if (psys && !cache)
recalc_emitter_field(ob, psys);
- PE_update_object(scene, ob, 1);
+ PE_update_object(eval_ctx, scene, view_layer, ob, 1);
PTCacheUndo_clear(edit);
- PE_undo_push(scene, "Original");
+ PE_undo_push(scene, view_layer, "Original");
}
}
@@ -4716,6 +4783,9 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
const int mode_flag = OB_MODE_PARTICLE_EDIT;
const bool is_mode_set = (ob->mode & mode_flag) != 0;
+ BKE_report(op->reports, RPT_INFO, "Particles are changing, editing is not possible");
+ return OPERATOR_CANCELLED;
+
if (!is_mode_set) {
if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
return OPERATOR_CANCELLED;
@@ -4724,8 +4794,11 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
if (!is_mode_set) {
PTCacheEdit *edit;
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
ob->mode |= mode_flag;
- edit= PE_create_current(scene, ob);
+ edit= PE_create_current(&eval_ctx, scene, ob);
/* mesh may have changed since last entering editmode.
* note, this may have run before if the edit data was just created, so could avoid this and speed up a little */
@@ -4741,7 +4814,7 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
return OPERATOR_FINISHED;
}
@@ -4782,7 +4855,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
psys_reset(psys, PSYS_RESET_DEPSGRAPH);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
else { /* some operation might have protected hair from editing so let's clear the flag */
@@ -4790,7 +4863,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
psys->flag &= ~PSYS_GLOBAL_HAIR;
psys->flag &= ~PSYS_EDITED;
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
return OPERATOR_FINISHED;
@@ -4893,19 +4966,24 @@ static int unify_length_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_active_object(C);
Scene *scene = CTX_data_scene(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
float average_length = calculate_average_length(edit);
+
if (average_length == 0.0f) {
return OPERATOR_CANCELLED;
}
scale_points_to_length(edit, average_length);
- PE_update_object(scene, ob, 1);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ PE_update_object(&eval_ctx, scene, view_layer, ob, 1);
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
}
else {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
}
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index aaa9afdd8c6..4fee14dc71d 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -43,7 +43,6 @@
#include "BLI_string.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
@@ -55,6 +54,9 @@
#include "BKE_pointcache.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -69,7 +71,7 @@
#include "physics_intern.h"
-extern void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
+extern void PE_create_particle_edit(const bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, PointCache *cache, ParticleSystem *psys);
extern void PTCacheUndo_clear(PTCacheEdit *edit);
extern void recalc_lengths(PTCacheEdit *edit);
extern void recalc_emitter_field(Object *ob, ParticleSystem *psys);
@@ -133,6 +135,7 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
int mode_orig;
if (!scene || !ob)
@@ -146,7 +149,7 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
*/
if (mode_orig & OB_MODE_PARTICLE_EDIT) {
if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
- if (scene->basact && scene->basact->object == ob) {
+ if (view_layer->basact && view_layer->basact->object == ob) {
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
}
}
@@ -208,8 +211,8 @@ static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op))
psys_check_boid_data(psys);
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
@@ -256,8 +259,8 @@ static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
BLI_addtail(&psys->targets, pt);
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
@@ -304,8 +307,8 @@ static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
if (pt)
pt->flag |= PTARGET_CURRENT;
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
@@ -344,7 +347,7 @@ static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op))
BLI_remlink(&psys->targets, pt);
BLI_insertlinkbefore(&psys->targets, pt->prev, pt);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
break;
}
@@ -382,7 +385,7 @@ static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op))
BLI_remlink(&psys->targets, pt);
BLI_insertlinkafter(&psys->targets, pt->next, pt);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
break;
}
@@ -565,7 +568,9 @@ void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot)
/************************ connect/disconnect hair operators *********************/
-static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
+static void disconnect_hair(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ Object *ob, ParticleSystem *psys)
{
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
ParticleEditSettings *pset= PE_settings(scene);
@@ -611,30 +616,34 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF))
pset->brushtype = PE_BRUSH_NONE;
- PE_update_object(scene, ob, 0);
+ PE_update_object(eval_ctx, scene, view_layer, ob, 0);
}
static int disconnect_hair_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= ED_object_context(C);
ParticleSystem *psys= NULL;
const bool all = RNA_boolean_get(op->ptr, "all");
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (!ob)
return OPERATOR_CANCELLED;
if (all) {
for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- disconnect_hair(scene, ob, psys);
+ disconnect_hair(&eval_ctx, scene, view_layer, ob, psys);
}
}
else {
psys = psys_get_current(ob);
- disconnect_hair(scene, ob, psys);
+ disconnect_hair(&eval_ctx, scene, view_layer, ob, psys);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
return OPERATOR_FINISHED;
@@ -657,9 +666,10 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot)
/* from/to_world_space : whether from/to particles are in world or hair space
* from/to_mat : additional transform for from/to particles (e.g. for using object space copying)
*/
-static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
- Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit,
- float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global)
+static bool remap_hair_emitter(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob, ParticleSystem *psys,
+ Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit,
+ float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global)
{
ParticleSystemModifierData *target_psmd = psys_get_modifier(target_ob, target_psys);
ParticleData *pa, *tpa;
@@ -843,19 +853,23 @@ static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
psys_free_path_cache(target_psys, target_edit);
- PE_update_object(scene, target_ob, 0);
+ PE_update_object(eval_ctx, scene, view_layer, target_ob, 0);
return true;
}
-static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
+static bool connect_hair(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ Object *ob, ParticleSystem *psys)
{
bool ok;
if (!psys)
return false;
- ok = remap_hair_emitter(scene, ob, psys, ob, psys, psys->edit, ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false);
+ ok = remap_hair_emitter(
+ eval_ctx, scene, view_layer, ob, psys, ob, psys, psys->edit,
+ ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false);
psys->flag &= ~PSYS_GLOBAL_HAIR;
return ok;
@@ -863,7 +877,9 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
static int connect_hair_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
Scene *scene= CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob= ED_object_context(C);
ParticleSystem *psys= NULL;
const bool all = RNA_boolean_get(op->ptr, "all");
@@ -872,14 +888,16 @@ static int connect_hair_exec(bContext *C, wmOperator *op)
if (!ob)
return OPERATOR_CANCELLED;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (all) {
for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- any_connected |= connect_hair(scene, ob, psys);
+ any_connected |= connect_hair(&eval_ctx, scene, view_layer, ob, psys);
}
}
else {
psys = psys_get_current(ob);
- any_connected |= connect_hair(scene, ob, psys);
+ any_connected |= connect_hair(&eval_ctx, scene, view_layer, ob, psys);
}
if (!any_connected) {
@@ -888,7 +906,7 @@ static int connect_hair_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
return OPERATOR_FINISHED;
@@ -915,7 +933,9 @@ typedef enum eCopyParticlesSpace {
PAR_COPY_SPACE_WORLD = 1,
} eCopyParticlesSpace;
-static void copy_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystem *psys_from)
+static void copy_particle_edit(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ Object *ob, ParticleSystem *psys, ParticleSystem *psys_from)
{
PTCacheEdit *edit_from = psys_from->edit, *edit;
ParticleData *pa;
@@ -965,10 +985,10 @@ static void copy_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys, P
recalc_lengths(edit);
recalc_emitter_field(ob, psys);
- PE_update_object(scene, ob, true);
+ PE_update_object(eval_ctx, scene, view_layer, ob, true);
PTCacheUndo_clear(edit);
- PE_undo_push(scene, "Original");
+ PE_undo_push(scene, view_layer, "Original");
}
static void remove_particle_systems_from_object(Object *ob_to)
@@ -996,14 +1016,17 @@ static void remove_particle_systems_from_object(Object *ob_to)
}
/* single_psys_from is optional, if NULL all psys of ob_from are copied */
-static bool copy_particle_systems_to_object(Main *bmain,
+static bool copy_particle_systems_to_object(const bContext *C,
Scene *scene,
+ ViewLayer *view_layer,
Object *ob_from,
ParticleSystem *single_psys_from,
Object *ob_to,
int space,
bool duplicate_settings)
{
+ Main *bmain = CTX_data_main(C);
+ EvaluationContext eval_ctx;
ModifierData *md;
ParticleSystem *psys_start = NULL, *psys, *psys_from;
ParticleSystem **tmp_psys;
@@ -1011,6 +1034,8 @@ static bool copy_particle_systems_to_object(Main *bmain,
CustomDataMask cdmask;
int i, totpsys;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (ob_to->type != OB_MESH)
return false;
if (!ob_to->data || ID_IS_LINKED(ob_to->data))
@@ -1049,7 +1074,7 @@ static bool copy_particle_systems_to_object(Main *bmain,
psys_start = totpsys > 0 ? tmp_psys[0] : NULL;
/* get the DM (psys and their modifiers have not been appended yet) */
- final_dm = mesh_get_derived_final(scene, ob_to, cdmask);
+ final_dm = mesh_get_derived_final(&eval_ctx, scene, ob_to, cdmask);
/* now append psys to the object and make modifiers */
for (i = 0, psys_from = PSYS_FROM_FIRST;
@@ -1077,8 +1102,9 @@ static bool copy_particle_systems_to_object(Main *bmain,
CDDM_calc_normals(psmd->dm_final);
DM_ensure_tessface(psmd->dm_final);
- if (psys_from->edit)
- copy_particle_edit(scene, ob_to, psys, psys_from);
+ if (psys_from->edit) {
+ copy_particle_edit(&eval_ctx, scene, view_layer, ob_to, psys, psys_from);
+ }
if (duplicate_settings) {
id_us_min(&psys->part->id);
@@ -1112,7 +1138,9 @@ static bool copy_particle_systems_to_object(Main *bmain,
break;
}
if (ob_from != ob_to) {
- remap_hair_emitter(scene, ob_from, psys_from, ob_to, psys, psys->edit, from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR);
+ remap_hair_emitter(
+ &eval_ctx, scene, view_layer, ob_from, psys_from, ob_to, psys, psys->edit,
+ from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR);
}
/* tag for recalc */
@@ -1122,7 +1150,7 @@ static bool copy_particle_systems_to_object(Main *bmain,
#undef PSYS_FROM_FIRST
#undef PSYS_FROM_NEXT
- DAG_id_tag_update(&ob_to->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_to->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to);
return true;
}
@@ -1145,8 +1173,8 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op)
const int space = RNA_enum_get(op->ptr, "space");
const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles");
const bool use_active = RNA_boolean_get(op->ptr, "use_active");
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob_from = ED_object_active_context(C);
ParticleSystem *psys_from = use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data : NULL;
@@ -1161,7 +1189,7 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op)
remove_particle_systems_from_object(ob_to);
changed = true;
}
- if (copy_particle_systems_to_object(bmain, scene, ob_from, psys_from, ob_to, space, false))
+ if (copy_particle_systems_to_object(C, scene, view_layer, ob_from, psys_from, ob_to, space, false))
changed = true;
else
fail++;
@@ -1222,7 +1250,7 @@ static int duplicate_particle_systems_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
- copy_particle_systems_to_object(CTX_data_main(C), scene, ob, psys, ob,
+ copy_particle_systems_to_object(C, scene, CTX_data_view_layer(C), ob, psys, ob,
PAR_COPY_SPACE_OBJECT, duplicate_settings);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index 6460e83e2a0..12e01228e1e 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -55,6 +55,8 @@
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
#include "LBM_fluidsim.h"
#include "ED_screen.h"
@@ -244,7 +246,7 @@ static void set_channel(float *channel, float time, float *value, int i, int siz
}
}
-static void set_vertex_channel(float *channel, float time, struct Scene *scene, struct FluidObject *fobj, int i)
+static void set_vertex_channel(EvaluationContext *eval_ctx, float *channel, float time, struct Scene *scene, struct FluidObject *fobj, int i)
{
Object *ob = fobj->object;
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
@@ -257,7 +259,7 @@ static void set_vertex_channel(float *channel, float time, struct Scene *scene,
if (channel == NULL)
return;
- initElbeemMesh(scene, ob, &numVerts, &verts, &numTris, &tris, 1, modifierIndex);
+ initElbeemMesh(eval_ctx, scene, ob, &numVerts, &verts, &numTris, &tris, 1, modifierIndex);
/* don't allow mesh to change number of verts in anim sequence */
if (numVerts != fobj->numVerts) {
@@ -329,10 +331,15 @@ 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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ EvaluationContext eval_ctx;
Base *base;
int i;
int length = channels->length;
float eval_time;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
/* init time values (assuming that time moves at a constant speed; may be overridden later) */
init_time(domainSettings, channels);
@@ -343,7 +350,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
channels->DomainTime = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime");
/* allocate fluid objects */
- for (base=scene->base.first; base; base= base->next) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
Object *ob = base->object;
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
@@ -373,7 +380,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
float *verts=NULL;
int *tris=NULL, modifierIndex = BLI_findindex(&ob->modifiers, (ModifierData *)fluidmd);
- initElbeemMesh(scene, ob, &fobj->numVerts, &verts, &fobj->numTris, &tris, 0, modifierIndex);
+ initElbeemMesh(&eval_ctx, scene, ob, &fobj->numVerts, &verts, &fobj->numTris, &tris, 0, modifierIndex);
fobj->VertexCache = MEM_callocN(length *((fobj->numVerts*CHANNEL_VEC)+1) * sizeof(float), "fluidobject VertexCache");
MEM_freeN(verts);
@@ -402,7 +409,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
/* Modifying the global scene isn't nice, but we can do it in
* this part of the process before a threaded job is created */
scene->r.cfra = (int)eval_time;
- ED_update_for_newframe(CTX_data_main(C), scene, 1);
+ ED_update_for_newframe(CTX_data_main(C), scene, view_layer, depsgraph);
/* now scene data should be current according to animation system, so we fill the channels */
@@ -461,15 +468,18 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
}
if (fluid_is_animated_mesh(fluidmd->fss)) {
- set_vertex_channel(fobj->VertexCache, timeAtFrame, scene, fobj, i);
+ set_vertex_channel(&eval_ctx, fobj->VertexCache, timeAtFrame, scene, fobj, i);
}
}
}
}
-static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length)
+static void export_fluid_objects(const bContext *C, ListBase *fobjects, Scene *scene, int length)
{
FluidObject *fobj;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
for (fobj=fobjects->first; fobj; fobj=fobj->next) {
Object *ob = fobj->object;
@@ -491,7 +501,7 @@ static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length)
fsmesh.type = fluidmd->fss->type;
fsmesh.name = ob->id.name;
- initElbeemMesh(scene, ob, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
+ initElbeemMesh(&eval_ctx, scene, ob, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
fsmesh.numVertices = numVerts;
fsmesh.numTriangles = numTris;
@@ -570,14 +580,14 @@ static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length)
}
}
-static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDomain)
+static int fluid_validate_scene(ReportList *reports, ViewLayer *view_layer, Object *fsDomain)
{
Base *base;
Object *newdomain = NULL;
int channelObjCount = 0;
int fluidInputCount = 0;
- for (base=scene->base.first; base; base= base->next) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
Object *ob = base->object;
FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
@@ -835,7 +845,9 @@ static void fluidsim_delete_until_lastframe(FluidsimSettings *fss, const char *r
static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, short do_job)
{
- Scene *scene= CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
int i;
FluidsimSettings *domainSettings;
@@ -882,7 +894,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
}
/* check scene for sane object/modifier settings */
- if (!fluid_validate_scene(reports, scene, fsDomain)) {
+ if (!fluid_validate_scene(reports, view_layer, fsDomain)) {
fluidbake_free_data(channels, fobjects, fsset, fb);
return 0;
}
@@ -947,7 +959,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
/* reset to original current frame */
scene->r.cfra = origFrame;
- ED_update_for_newframe(CTX_data_main(C), scene, 1);
+ ED_update_for_newframe(CTX_data_main(C), scene, view_layer, depsgraph);
/* ******** init domain object's matrix ******** */
copy_m4_m4(domainMat, fsDomain->obmat);
@@ -1034,7 +1046,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor
elbeemAddDomain(fsset);
/* ******** export all fluid objects to elbeem ******** */
- export_fluid_objects(fobjects, scene, channels->length);
+ export_fluid_objects(C, fobjects, scene, channels->length);
/* custom data for fluid bake job */
fb->settings = fsset;
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index b1d708ebc07..758ef43590e 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -137,23 +137,6 @@ static void keymap_particle(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "unselected", true);
- /* Shift+LMB behavior first, so it has priority over KM_ANY item below. */
- kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "release_confirm", true);
- RNA_boolean_set(kmi->ptr, "use_planar_constraint", true);
- RNA_boolean_set(kmi->ptr, "use_accurate", false);
-
- kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "release_confirm", true);
- RNA_boolean_set(kmi->ptr, "use_planar_constraint", false);
- RNA_boolean_set(kmi->ptr, "use_accurate", true);
-
- /* Using KM_ANY here to allow holding modifiers before starting to transform. */
- kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_ANY, 0);
- RNA_boolean_set(kmi->ptr, "release_confirm", true);
- RNA_boolean_set(kmi->ptr, "use_planar_constraint", false);
- RNA_boolean_set(kmi->ptr, "use_accurate", false);
-
WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index f36ebb3715e..a859f664dc8 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -42,6 +42,7 @@
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
@@ -165,6 +166,8 @@ static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all)
baker->main = CTX_data_main(C);
baker->scene = CTX_data_scene(C);
+ baker->view_layer = CTX_data_view_layer(C);
+ baker->depsgraph = CTX_data_depsgraph(C);
baker->bake = RNA_boolean_get(op->ptr, "bake");
baker->render = 0;
baker->anim_init = 0;
@@ -253,22 +256,23 @@ 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;
+ Scene *scene = CTX_data_scene(C);
PTCacheID *pid;
ListBase pidlist;
- for (base=scene->base.first; base; base= base->next) {
- BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
- for (pid=pidlist.first; pid; pid=pid->next) {
+ for (pid = pidlist.first; pid; pid = pid->next) {
ptcache_free_bake(pid->cache);
}
BLI_freelistN(&pidlist);
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, base->object);
+ WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
}
+ FOREACH_SCENE_OBJECT_END
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 1bfc162a331..f77e164ba16 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -38,13 +38,15 @@
#include "DNA_scene_types.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -89,10 +91,10 @@ 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);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
return true;
}
@@ -102,10 +104,10 @@ 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);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
/* ********************************************** */
@@ -117,8 +119,9 @@ static int rigidbody_con_add_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
- Object *ob = (scene) ? OBACT : NULL;
+ Object *ob = OBACT(view_layer);
int type = RNA_enum_get(op->ptr, "type");
bool changed;
@@ -166,11 +169,8 @@ static int rigidbody_con_remove_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = (scene) ? OBACT : NULL;
-
- /* sanity checks */
- if (scene == NULL)
- return OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
/* apply to active object */
if (ELEM(NULL, ob, ob->rigidbody_constraint)) {
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index fa80fb5fbc1..3b667520550 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -43,13 +43,15 @@
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -119,10 +121,10 @@ 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);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
return true;
}
@@ -133,10 +135,10 @@ 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);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
/* ********************************************** */
@@ -345,7 +347,7 @@ static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op)
RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
RNA_enum_set(&ptr, "collision_shape", shape);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
changed = true;
}
@@ -527,7 +529,7 @@ static int rigidbody_objects_calc_mass_exec(bContext *C, wmOperator *op)
RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
RNA_float_set(&ptr, "mass", mass);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
changed = true;
}
diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt
index ec8bf3e955d..ed2e9747d1c 100644
--- a/source/blender/editors/render/CMakeLists.txt
+++ b/source/blender/editors/render/CMakeLists.txt
@@ -24,6 +24,8 @@ set(INC
../../blenlib
../../blenloader
../../blentranslation
+ ../../depsgraph
+ ../../draw
../../gpu
../../imbuf
../../bmesh
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index fb07b03c286..2bc96a7f218 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -53,8 +53,8 @@ void WORLD_OT_new(struct wmOperatorType *ot);
void MATERIAL_OT_copy(struct wmOperatorType *ot);
void MATERIAL_OT_paste(struct wmOperatorType *ot);
-void SCENE_OT_render_layer_add(struct wmOperatorType *ot);
-void SCENE_OT_render_layer_remove(struct wmOperatorType *ot);
+void SCENE_OT_view_layer_add(struct wmOperatorType *ot);
+void SCENE_OT_view_layer_remove(struct wmOperatorType *ot);
void SCENE_OT_render_view_add(struct wmOperatorType *ot);
void SCENE_OT_render_view_remove(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index d0da35aeb9d..4e75ca3e6f1 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -54,9 +54,9 @@
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_colortools.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -65,6 +65,9 @@
#include "BKE_sequencer.h"
#include "BKE_screen.h"
#include "BKE_scene.h"
+#include "BKE_workspace.h"
+
+#include "DEG_depsgraph.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -81,6 +84,7 @@
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
+#include "GPU_shader.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -97,9 +101,13 @@ static int render_break(void *rjv);
typedef struct RenderJob {
Main *main;
Scene *scene;
+ ViewLayer *view_layer;
Scene *current_scene;
+ /* TODO(sergey): Should not be needed once engine will have own
+ * depsgraph and copy-on-write will be implemented.
+ */
+ Depsgraph *depsgraph;
Render *re;
- SceneRenderLayer *srl;
struct Object *camera_override;
int lay_override;
bool v3d_override;
@@ -252,7 +260,7 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
/* set callbacks, exported to sequence render too.
* Only call in foreground (UI) renders. */
-static void screen_render_scene_layer_set(wmOperator *op, Main *mainp, Scene **scene, SceneRenderLayer **srl)
+static void screen_render_view_layer_set(wmOperator *op, Main *mainp, Scene **scene, ViewLayer **view_layer)
{
/* single layer re-render */
if (RNA_struct_property_is_set(op->ptr, "scene")) {
@@ -272,14 +280,14 @@ static void screen_render_scene_layer_set(wmOperator *op, Main *mainp, Scene **s
}
if (RNA_struct_property_is_set(op->ptr, "layer")) {
- SceneRenderLayer *rl;
+ ViewLayer *rl;
char rl_name[RE_MAXNAME];
RNA_string_get(op->ptr, "layer", rl_name);
- rl = (SceneRenderLayer *)BLI_findstring(&(*scene)->r.layers, rl_name, offsetof(SceneRenderLayer, name));
+ rl = (ViewLayer *)BLI_findstring(&(*scene)->view_layers, rl_name, offsetof(ViewLayer, name));
if (rl)
- *srl = rl;
+ *view_layer = rl;
}
}
@@ -287,7 +295,8 @@ static void screen_render_scene_layer_set(wmOperator *op, Main *mainp, Scene **s
static int screen_render_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = NULL;
+ ViewLayer *view_layer = NULL;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Render *re;
Image *ima;
View3D *v3d = CTX_wm_view3d(C);
@@ -298,7 +307,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
/* custom scene and single layer re-render */
- screen_render_scene_layer_set(op, mainp, &scene, &srl);
+ screen_render_view_layer_set(op, mainp, &scene, &view_layer);
if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
@@ -306,6 +315,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
}
re = RE_NewSceneRender(scene);
+ RE_SetDepsgraph(re, CTX_data_depsgraph(C));
lay_override = (v3d && v3d->lay != scene->lay) ? v3d->lay : 0;
G.is_break = false;
@@ -327,13 +337,13 @@ static int screen_render_exec(bContext *C, wmOperator *op)
if (is_animation)
RE_BlenderAnim(re, mainp, scene, camera_override, lay_override, scene->r.sfra, scene->r.efra, scene->r.frame_step);
else
- RE_BlenderFrame(re, mainp, scene, srl, camera_override, lay_override, scene->r.cfra, is_write_still);
+ RE_BlenderFrame(re, mainp, scene, view_layer, camera_override, lay_override, scene->r.cfra, is_write_still);
BLI_end_threaded_malloc();
RE_SetReports(re, NULL);
// no redraw needed, we leave state as we entered it
- ED_update_for_newframe(mainp, scene, 1);
+ ED_update_for_newframe(mainp, scene, view_layer, depsgraph);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
@@ -489,8 +499,9 @@ static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr,
for (wm = rj->main->wm.first; wm && matched_sa == NULL; wm = wm->id.next) { /* only 1 wm */
wmWindow *win;
for (win = wm->windows.first; win && matched_sa == NULL; win = win->next) {
- ScrArea *sa;
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ const bScreen *screen = WM_window_get_active_screen(win);
+
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->spacetype == SPACE_IMAGE) {
SpaceImage *sima = sa->spacedata.first;
// sa->spacedata might be empty when toggling fullscreen mode.
@@ -603,7 +614,7 @@ static void render_startjob(void *rjv, short *stop, short *do_update, float *pro
if (rj->anim)
RE_BlenderAnim(rj->re, rj->main, rj->scene, rj->camera_override, rj->lay_override, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step);
else
- RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->srl, rj->camera_override, rj->lay_override, rj->scene->r.cfra, rj->write_still);
+ RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->view_layer, rj->camera_override, rj->lay_override, rj->scene->r.cfra, rj->write_still);
RE_SetReports(rj->re, NULL);
}
@@ -616,8 +627,9 @@ static void render_image_restore_layer(RenderJob *rj)
for (wm = rj->main->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
wmWindow *win;
for (win = wm->windows.first; win; win = win->next) {
- ScrArea *sa;
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ const bScreen *screen = WM_window_get_active_screen(win);
+
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
if (sa == rj->sa) {
if (sa->spacetype == SPACE_IMAGE) {
SpaceImage *sima = sa->spacedata.first;
@@ -645,7 +657,7 @@ static void render_endjob(void *rjv)
if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
/* possible this fails of loading new file while rendering */
if (G.main->wm.first) {
- ED_update_for_newframe(G.main, rj->scene, 1);
+ ED_update_for_newframe(G.main, rj->scene, rj->view_layer, rj->depsgraph);
}
}
@@ -655,7 +667,7 @@ static void render_endjob(void *rjv)
/* potentially set by caller */
rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE;
- if (rj->srl) {
+ if (rj->view_layer) {
nodeUpdateID(rj->scene->nodetree, &rj->scene->id);
WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene);
}
@@ -685,7 +697,7 @@ static void render_endjob(void *rjv)
* engine API, so lets use simple and robust way for now
* - sergey -
*/
- if (rj->scene->r.layers.first != rj->scene->r.layers.last ||
+ if (rj->scene->view_layers.first != rj->scene->view_layers.last ||
rj->image_outdated)
{
void *lock;
@@ -718,7 +730,7 @@ static void render_endjob(void *rjv)
scene->lay_updated = 0;
}
- DAG_on_visible_update(G.main, false);
+ DEG_on_visible_update(G.main, false);
}
}
@@ -782,33 +794,46 @@ static void screen_render_cancel(bContext *C, wmOperator *op)
WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
}
-static void clean_viewport_memory(Main *bmain, Scene *scene, int renderlay)
+static void clean_viewport_memory_base(Base *base)
{
- Object *object;
- Scene *sce_iter;
- Base *base;
+ if ((base->flag & BASE_VISIBLED) == 0) {
+ return;
+ }
+
+ Object *object = base->object;
- for (object = bmain->object.first; object; object = object->id.next) {
- object->id.tag |= LIB_TAG_DOIT;
+ if (object->id.tag & LIB_TAG_DOIT) {
+ return;
}
- for (SETLOOPER(scene, sce_iter, base)) {
- if ((base->lay & renderlay) == 0) {
- continue;
- }
- if (RE_allow_render_generic_object(base->object)) {
- base->object->id.tag &= ~LIB_TAG_DOIT;
- }
+ object->id.tag &= ~LIB_TAG_DOIT;
+ if (RE_allow_render_generic_object(object)) {
+ BKE_object_free_derived_caches(object);
}
+}
+
+static void clean_viewport_memory(Main *bmain, Scene *scene)
+{
+ Scene *sce_iter;
+ Base *base;
- for (SETLOOPER(scene, sce_iter, base)) {
- object = base->object;
- if ((object->id.tag & LIB_TAG_DOIT) == 0) {
- continue;
+ /* Tag all the available objects. */
+ BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true);
+
+ /* Go over all the visible objects. */
+ for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ ViewLayer *view_layer = BKE_view_layer_from_workspace_get(scene, workspace);
+
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ clean_viewport_memory_base(base);
+ }
}
- object->id.tag &= ~LIB_TAG_DOIT;
+ }
- BKE_object_free_derived_caches(object);
+ for (SETLOOPER_SET_ONLY(scene, sce_iter, base)) {
+ clean_viewport_memory_base(base);
}
}
@@ -817,8 +842,8 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
{
/* new render clears all callbacks */
Main *mainp;
+ ViewLayer *view_layer = NULL;
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = NULL;
Render *re;
wmJob *wm_job;
RenderJob *rj;
@@ -885,7 +910,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
/* custom scene and single layer re-render */
- screen_render_scene_layer_set(op, mainp, &scene, &srl);
+ screen_render_view_layer_set(op, mainp, &scene, &view_layer);
if (RNA_struct_property_is_set(op->ptr, "layer"))
jobflag |= WM_JOB_SUSPEND;
@@ -895,7 +920,9 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->main = mainp;
rj->scene = scene;
rj->current_scene = rj->scene;
- rj->srl = srl;
+ rj->view_layer = view_layer;
+ /* TODO(sergey): Render engine should be using own depsgraph. */
+ rj->depsgraph = CTX_data_depsgraph(C);
rj->camera_override = camera_override;
rj->lay_override = 0;
rj->anim = is_animation;
@@ -930,8 +957,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
/* Lock the user interface depending on render settings. */
if (scene->r.use_lock_interface) {
- int renderlay = rj->lay_override ? rj->lay_override : scene->lay;
-
WM_set_locked_interface(CTX_wm_manager(C), true);
/* Set flag interface need to be unlocked.
@@ -945,7 +970,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->interface_locked = true;
/* Clean memory used by viewport? */
- clean_viewport_memory(rj->main, scene, renderlay);
+ clean_viewport_memory(rj->main, scene);
}
/* setup job */
@@ -971,6 +996,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
RE_current_scene_update_cb(re, rj, current_scene_update);
RE_stats_draw_cb(re, rj, image_renderinfo_cb);
RE_progress_cb(re, rj, render_progress_update);
+ RE_SetDepsgraph(re, CTX_data_depsgraph(C));
rj->re = re;
G.is_break = false;
@@ -1254,10 +1280,10 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
/* initalize always */
if (use_border) {
rdata.mode |= R_BORDER;
- RE_InitState(re, NULL, &rdata, NULL, rp->ar->winx, rp->ar->winy, &cliprct);
+ RE_InitState(re, NULL, &rdata, &rp->scene->view_layers, rp->scene->active_view_layer, &rp->scene->view_render, NULL, rp->ar->winx, rp->ar->winy, &cliprct);
}
else
- RE_InitState(re, NULL, &rdata, NULL, rp->ar->winx, rp->ar->winy, NULL);
+ RE_InitState(re, NULL, &rdata, &rp->scene->view_layers, rp->scene->active_view_layer, &rp->scene->view_render, NULL, rp->ar->winx, rp->ar->winy, NULL);
}
if (orth)
@@ -1545,11 +1571,10 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
if (force_fallback == false) {
if (IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, dither, true)) {
glEnable(GL_BLEND);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- glPixelZoom(scale_x, scale_y);
- glaDrawPixelsTex(xof, yof, rres.rectx, rres.recty,
- GL_RGBA, GL_FLOAT, GL_NEAREST, rres.rectf);
- glPixelZoom(1.0f, 1.0f);
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state, xof, yof, rres.rectx, rres.recty,
+ GL_RGBA, GL_FLOAT, GL_NEAREST, rres.rectf,
+ scale_x, scale_y, NULL);;
glDisable(GL_BLEND);
IMB_colormanagement_finish_glsl_draw();
@@ -1566,12 +1591,11 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
4, dither, &scene->view_settings, &scene->display_settings);
glEnable(GL_BLEND);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- glPixelZoom(scale_x, scale_y);
- glaDrawPixelsAuto(xof, yof, rres.rectx, rres.recty,
- GL_RGBA, GL_UNSIGNED_BYTE,
- GL_NEAREST, display_buffer);
- glPixelZoom(1.0f, 1.0f);
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state, xof, yof, rres.rectx, rres.recty,
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ GL_NEAREST, display_buffer,
+ scale_x, scale_y, NULL);
glDisable(GL_BLEND);
MEM_freeN(display_buffer);
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 1133b5f79d1..3c63aed9473 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -55,6 +55,8 @@
#include "BKE_sequencer.h"
#include "BKE_writeavi.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -70,9 +72,10 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "GPU_glew.h"
#include "GPU_compositing.h"
#include "GPU_framebuffer.h"
+#include "GPU_glew.h"
+#include "GPU_matrix.h"
#include "render_intern.h"
@@ -91,6 +94,9 @@ typedef struct OGLRender {
Main *bmain;
Render *re;
Scene *scene;
+ WorkSpace *workspace;
+ ViewLayer *view_layer;
+ Depsgraph *depsgraph;
View3D *v3d;
RegionView3D *rv3d;
@@ -148,17 +154,6 @@ typedef struct OGLRender {
#endif
} OGLRender;
-/* added because v3d is not always valid */
-static unsigned int screen_opengl_layers(OGLRender *oglrender)
-{
- if (oglrender->v3d) {
- return oglrender->scene->lay | oglrender->v3d->lay;
- }
- else {
- return oglrender->scene->lay;
- }
-}
-
static bool screen_opengl_is_multiview(OGLRender *oglrender)
{
View3D *v3d = oglrender->v3d;
@@ -271,9 +266,10 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
RE_ReleaseResult(oglrender->re);
}
-static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
+static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, RenderResult *rr)
{
Scene *scene = oglrender->scene;
+ ViewLayer *view_layer = oglrender->view_layer;
ARegion *ar = oglrender->ar;
View3D *v3d = oglrender->v3d;
RegionView3D *rv3d = oglrender->rv3d;
@@ -286,6 +282,9 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
unsigned char *rect = NULL;
const char *viewname = RE_GetActiveRenderView(oglrender->re);
ImBuf *ibuf_result = NULL;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
if (oglrender->is_sequencer) {
SpaceSeq *sseq = oglrender->sseq;
@@ -330,7 +329,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
wmOrtho2(0, sizex, 0, sizey);
- glTranslatef(sizex / 2, sizey / 2, 0.0f);
+ gpuTranslate2f(sizex / 2, sizey / 2);
G.f |= G_RENDER_OGL;
ED_gpencil_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ);
@@ -360,7 +359,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
draw_flags |= (draw_bgpic) ? V3D_OFSDRAW_USE_BACKGROUND : 0;
ibuf_view = ED_view3d_draw_offscreen_imbuf(
- scene, v3d, ar, sizex, sizey,
+ &eval_ctx, scene, view_layer, v3d, ar, sizex, sizey,
IB_rect, draw_flags, alpha_mode, oglrender->ofs_samples, viewname,
oglrender->fx, oglrender->ofs, err_out);
@@ -372,7 +371,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
else {
draw_flags |= (V3D_OFSDRAW_USE_GPENCIL | V3D_OFSDRAW_USE_BACKGROUND);
ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(
- scene, scene->camera, oglrender->sizex, oglrender->sizey,
+ &eval_ctx, scene, view_layer, scene->camera, oglrender->sizex, oglrender->sizey,
IB_rect, draw_flags, OB_SOLID,
alpha_mode, oglrender->ofs_samples, viewname,
oglrender->fx, oglrender->ofs, err_out);
@@ -435,7 +434,7 @@ static void addAlphaOverFloat(float dest[4], const float source[4])
}
/* add renderlayer and renderpass for each grease pencil layer for using in composition */
-static void add_gpencil_renderpass(OGLRender *oglrender, RenderResult *rr, RenderView *rv)
+static void add_gpencil_renderpass(const bContext *C, OGLRender *oglrender, RenderResult *rr, RenderView *rv)
{
bGPdata *gpd = oglrender->scene->gpd;
Scene *scene = oglrender->scene;
@@ -479,7 +478,7 @@ static void add_gpencil_renderpass(OGLRender *oglrender, RenderResult *rr, Rende
}
/* render this gp layer */
- screen_opengl_render_doit(oglrender, rr);
+ screen_opengl_render_doit(C, oglrender, rr);
/* add RendePass composite */
RenderPass *rp = RE_create_gp_pass(rr, gpl->info, rv->name);
@@ -519,7 +518,7 @@ static void add_gpencil_renderpass(OGLRender *oglrender, RenderResult *rr, Rende
scene->r.alphamode = oldalphamode;
}
-static void screen_opengl_render_apply(OGLRender *oglrender)
+static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender)
{
RenderResult *rr;
RenderView *rv;
@@ -557,10 +556,10 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
/* add grease pencil passes. For sequencer, the render does not include renderpasses
* TODO: The sequencer render of grease pencil should be rethought */
if (!oglrender->is_sequencer) {
- add_gpencil_renderpass(oglrender, rr, rv);
+ add_gpencil_renderpass(C, oglrender, rr, rv);
}
/* render composite */
- screen_opengl_render_doit(oglrender, rr);
+ screen_opengl_render_doit(C, oglrender, rr);
}
RE_ReleaseResult(oglrender->re);
@@ -576,11 +575,30 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
}
}
+static bool screen_opengl_fullsample_enabled(Scene *scene)
+{
+ if (scene->r.scemode & R_FULL_SAMPLE) {
+ return true;
+ }
+ else {
+ /* XXX TODO:
+ * Technically if the hardware supports MSAA we could keep using Blender 2.7x approach.
+ * However anti-aliasing without full_sample is not playing well even in 2.7x.
+ *
+ * For example, if you enable depth of field, there is aliasing, even if the viewport is fine.
+ * For 2.8x this is more complicated because so many things rely on shader.
+ * So until we fix the gpu_framebuffer anti-aliasing suupport we need to force full sample.
+ */
+ return true;
+ }
+}
+
static bool screen_opengl_render_init(bContext *C, wmOperator *op)
{
/* new render clears all callbacks */
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
Scene *scene = CTX_data_scene(C);
ScrArea *prevsa = CTX_wm_area(C);
@@ -589,7 +607,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
OGLRender *oglrender;
int sizex, sizey;
const int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0;
- const bool full_samples = (samples != 0) && (scene->r.scemode & R_FULL_SAMPLE);
+ const bool full_samples = (samples != 0) && screen_opengl_fullsample_enabled(scene);
bool is_view_context = RNA_boolean_get(op->ptr, "view_context");
const bool is_animation = RNA_boolean_get(op->ptr, "animation");
const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer");
@@ -652,6 +670,9 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
oglrender->sizey = sizey;
oglrender->bmain = CTX_data_main(C);
oglrender->scene = scene;
+ oglrender->workspace = workspace;
+ oglrender->view_layer = CTX_data_view_layer(C);
+ oglrender->depsgraph = CTX_data_depsgraph(C);
oglrender->cfrao = scene->r.cfra;
oglrender->write_still = is_write_still && !is_animation;
@@ -696,6 +717,8 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
/* create render */
oglrender->re = RE_NewSceneRender(scene);
+ ViewRender *view_render = BKE_viewrender_get(scene, workspace);
+ RE_SetEngineByID(oglrender->re, view_render->engine_id);
/* create image and image user */
oglrender->ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
@@ -706,7 +729,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
oglrender->iuser.ok = 1;
/* create render result */
- RE_InitState(oglrender->re, NULL, &scene->r, NULL, sizex, sizey, NULL);
+ RE_InitState(oglrender->re, NULL, &scene->r, &scene->view_layers, scene->active_view_layer, view_render, NULL, sizex, sizey, NULL);
/* create render views */
screen_opengl_views_setup(oglrender);
@@ -803,8 +826,10 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
}
if (oglrender->timer) { /* exec will not have a timer */
+ Depsgraph *depsgraph = oglrender->depsgraph;
+ ViewLayer *view_layer = oglrender->view_layer;
scene->r.cfra = oglrender->cfrao;
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, screen_opengl_layers(oglrender));
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
WM_event_remove_timer(oglrender->wm, oglrender->win, oglrender->timer);
}
@@ -1004,6 +1029,8 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
OGLRender *oglrender = op->customdata;
Scene *scene = oglrender->scene;
+ ViewLayer *view_layer = oglrender->view_layer;
+ Depsgraph *depsgraph = oglrender->depsgraph;
char name[FILE_MAX];
bool ok = false;
const bool view_context = (oglrender->v3d != NULL);
@@ -1014,12 +1041,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
if (CFRA < oglrender->nfra)
CFRA++;
while (CFRA < oglrender->nfra) {
- unsigned int lay = screen_opengl_layers(oglrender);
-
- if (lay & 0xFF000000)
- lay &= 0xFF000000;
-
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, lay);
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
CFRA++;
}
@@ -1041,11 +1063,11 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
WM_cursor_time(oglrender->win, scene->r.cfra);
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, screen_opengl_layers(oglrender));
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
if (view_context) {
if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) {
- /* since BKE_scene_update_for_newframe() is used rather
+ /* since BKE_scene_graph_update_for_newframe() is used rather
* then ED_update_for_newframe() the camera needs to be set */
if (BKE_scene_camera_switch_update(scene)) {
oglrender->v3d->camera = scene->camera;
@@ -1057,7 +1079,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
}
/* render into offscreen buffer */
- screen_opengl_render_apply(oglrender);
+ screen_opengl_render_apply(C, oglrender);
/* save to disk */
rr = RE_AcquireResultRead(oglrender->re);
@@ -1107,7 +1129,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene);
if (anim == 0) {
- screen_opengl_render_apply(op->customdata);
+ screen_opengl_render_apply(C, op->customdata);
screen_opengl_render_end(C, op->customdata);
return OPERATOR_FINISHED;
}
@@ -1158,7 +1180,7 @@ static int screen_opengl_render_exec(bContext *C, wmOperator *op)
if (!is_animation) { /* same as invoke */
/* render image */
- screen_opengl_render_apply(op->customdata);
+ screen_opengl_render_apply(C, op->customdata);
screen_opengl_render_end(C, op->customdata);
return OPERATOR_FINISHED;
@@ -1175,7 +1197,7 @@ static int screen_opengl_render_exec(bContext *C, wmOperator *op)
}
/* no redraw needed, we leave state as we entered it */
-// ED_update_for_newframe(C, 1);
+// ED_update_for_newframe(C);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, CTX_data_scene(C));
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c
index c09e8576dc2..bd75c6879e1 100644
--- a/source/blender/editors/render/render_ops.c
+++ b/source/blender/editors/render/render_ops.c
@@ -56,8 +56,8 @@ void ED_operatortypes_render(void)
WM_operatortype_append(MATERIAL_OT_copy);
WM_operatortype_append(MATERIAL_OT_paste);
- WM_operatortype_append(SCENE_OT_render_layer_add);
- WM_operatortype_append(SCENE_OT_render_layer_remove);
+ WM_operatortype_append(SCENE_OT_view_layer_add);
+ WM_operatortype_append(SCENE_OT_view_layer_remove);
WM_operatortype_append(SCENE_OT_render_view_add);
WM_operatortype_append(SCENE_OT_render_view_remove);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 35d772afae7..47794e0e357 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -69,6 +69,7 @@
#include "BKE_image.h"
#include "BKE_icons.h"
#include "BKE_lamp.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_main.h"
@@ -78,6 +79,9 @@
#include "BKE_texture.h"
#include "BKE_world.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_thumbs.h"
@@ -85,6 +89,7 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_shader.h"
#include "RE_pipeline.h"
#include "RE_engine.h"
@@ -94,6 +99,7 @@
#include "ED_datafiles.h"
#include "ED_render.h"
+#include "ED_screen.h"
#ifndef NDEBUG
/* Used for database init assert(). */
@@ -167,6 +173,7 @@ typedef struct ShaderPreview {
Main *bmain;
Main *pr_main;
+ ViewRender *view_render;
} ShaderPreview;
typedef struct IconPreviewSize {
@@ -181,6 +188,7 @@ typedef struct IconPreview {
void *owner;
ID *id;
ListBase sizes;
+ ViewRender *view_render;
} IconPreview;
/* *************************** Preview for buttons *********************** */
@@ -223,7 +231,7 @@ void ED_preview_ensure_dbase(void)
static bool check_engine_supports_textures(Scene *scene)
{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
+ RenderEngineType *type = RE_engines_find(scene->view_render.engine_id);
return type->flag & RE_USE_TEXTURE_PREVIEW;
}
@@ -269,20 +277,77 @@ static Scene *preview_get_scene(Main *pr_main)
return pr_main->scene.first;
}
+static const char *preview_layer_name(const char pr_type)
+{
+ switch (pr_type) {
+ case MA_FLAT:
+ return "Flat";
+ case MA_SPHERE:
+ return "Sphere";
+ case MA_CUBE:
+ return "Cube";
+ case MA_MONKEY:
+ return "Monkey";
+ case MA_SPHERE_A:
+ return "World Sphere";
+ case MA_TEXTURE:
+ return "Texture";
+ case MA_LAMP:
+ return "Lamp";
+ case MA_SKY:
+ return "Sky";
+ case MA_HAIR:
+ return "Hair";
+ case MA_ATMOS:
+ return "Atmosphere";
+ default:
+ BLI_assert(!"Unknown preview type");
+ return "";
+ }
+}
+
+static void set_preview_layer(ViewLayer *view_layer, char pr_type)
+{
+ LayerCollection *lc;
+ const char *collection_name = preview_layer_name(pr_type);
+
+ for (lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ if (STREQ(lc->scene_collection->name, collection_name)) {
+ lc->flag = COLLECTION_VISIBLE | COLLECTION_DISABLED;
+ BKE_collection_enable(view_layer, lc);
+ }
+ else {
+ BKE_collection_disable(view_layer, lc);
+ }
+ }
+}
+
+static World *preview_get_localized_world(ShaderPreview *sp, World *world)
+{
+ if (world == NULL) {
+ return NULL;
+ }
+ if (sp->worldcopy != NULL) {
+ return sp->worldcopy;
+ }
+ sp->worldcopy = localize_world(world);
+ BLI_addtail(&sp->pr_main->world, sp->worldcopy);
+ return sp->worldcopy;
+}
/* call this with a pointer to initialize preview scene */
/* call this with NULL to restore assigned ID pointers in preview scene */
static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp)
{
Scene *sce;
- Base *base;
Main *pr_main = sp->pr_main;
memcpy(pr_main->name, bmain->name, sizeof(pr_main->name));
sce = preview_get_scene(pr_main);
if (sce) {
-
+ ViewLayer *view_layer = BKE_view_layer_from_scene_get(sce);
+
/* this flag tells render to not execute depsgraph or ipos etc */
sce->r.scemode |= R_BUTS_PREVIEW;
/* set world always back, is used now */
@@ -320,10 +385,10 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
* seems commonly used render engines does not support
* such kind of rendering.
*/
- BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_RENDER, sizeof(sce->r.engine));
+ BLI_strncpy(sce->view_render.engine_id, RE_engine_id_BLENDER_RENDER, sizeof(sce->view_render.engine_id));
}
else {
- BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
+ BLI_strncpy(sce->view_render.engine_id, scene->view_render.engine_id, sizeof(sce->view_render.engine_id));
}
if (id_type == ID_MA) {
@@ -357,50 +422,60 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
/* this only works in a specific case where the preview.blend contains
* an object starting with 'c' which has a material linked to it (not the obdata)
* and that material has a fake shadow texture in the active texture slot */
- for (base = sce->base.first; base; base = base->next) {
- if (base->object->id.name[2] == 'c') {
- Material *shadmat = give_current_material(base->object, base->object->actcol);
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ if (ob->id.name[2] == 'c') {
+ Material *shadmat = give_current_material(ob, ob->actcol);
if (shadmat) {
- if (mat->mode2 & MA_CASTSHADOW) shadmat->septex = 0;
- else shadmat->septex |= 1;
+ if (mat->mode2 & MA_CASTSHADOW) {
+ shadmat->septex = 0;
+ }
+ else {
+ shadmat->septex |= 1;
+ }
}
}
}
/* turn off bounce lights for volume,
* doesn't make much visual difference and slows it down too */
- for (base = sce->base.first; base; base = base->next) {
- if (base->object->type == OB_LAMP) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ if (ob->type == OB_LAMP) {
/* if doesn't match 'Lamp.002' --> main key light */
- if (!STREQ(base->object->id.name + 2, "Lamp.002")) {
- if (mat->material_type == MA_TYPE_VOLUME)
- base->object->restrictflag |= OB_RESTRICT_RENDER;
- else
- base->object->restrictflag &= ~OB_RESTRICT_RENDER;
+ if (!STREQ(ob->id.name + 2, "Lamp.002")) {
+ if (mat->material_type == MA_TYPE_VOLUME) {
+ base->flag &= ~BASE_VISIBLED;
+ }
+ else {
+ base->flag |= BASE_VISIBLED;
+ }
}
}
}
}
else {
/* use current scene world to light sphere */
- if (mat->pr_type == MA_SPHERE_A)
- sce->world = scene->world;
+ if (mat->pr_type == MA_SPHERE_A) {
+ sce->world = preview_get_localized_world(sp, scene->world);
+ }
}
if (sp->pr_method == PR_ICON_RENDER) {
if (mat->material_type == MA_TYPE_HALO) {
- sce->lay = 1 << MA_FLAT;
+ set_preview_layer(view_layer, MA_FLAT);
}
else {
- sce->lay = 1 << MA_SPHERE_A;
+ set_preview_layer(view_layer, MA_SPHERE_A);
/* same as above, use current scene world to light sphere */
if (BKE_scene_use_new_shading_nodes(scene))
- sce->world = scene->world;
+ sce->world = preview_get_localized_world(sp, scene->world);
}
}
else {
- sce->lay = 1 << mat->pr_type;
+ set_preview_layer(view_layer, mat->pr_type);
+
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true);
@@ -413,7 +488,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
}
- for (base = sce->base.first; base; base = base->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
if (base->object->id.name[2] == 'p') {
/* copy over object color, in case material uses it */
copy_v4_v4(base->object->col, sp->col);
@@ -427,7 +502,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
(*matar)[actcol] = mat;
}
else if (base->object->type == OB_LAMP) {
- base->object->restrictflag &= ~OB_RESTRICT_RENDER;
+ base->flag |= BASE_VISIBLED;
}
}
}
@@ -440,9 +515,9 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
sp->texcopy = tex;
BLI_addtail(&pr_main->tex, tex);
}
- sce->lay = 1 << MA_TEXTURE;
+ set_preview_layer(view_layer, MA_TEXTURE);
- for (base = sce->base.first; base; base = base->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
if (base->object->id.name[2] == 't') {
Material *mat = give_current_material(base->object, base->object->actcol);
if (mat && mat->mtex[0]) {
@@ -481,21 +556,23 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
BLI_addtail(&pr_main->lamp, la);
}
- sce->lay = 1 << MA_LAMP;
-
if (!BKE_scene_use_new_shading_nodes(scene)) {
if (la && la->type == LA_SUN && (la->sun_effect_type & LA_SUN_EFFECT_SKY)) {
- sce->lay = 1 << MA_ATMOS;
- sce->world = scene->world;
+ set_preview_layer(view_layer, MA_ATMOS);
+ sce->world = preview_get_localized_world(sp, scene->world);
sce->camera = (Object *)BLI_findstring(&pr_main->object, "CameraAtmo", offsetof(ID, name) + 2);
}
else {
sce->world = NULL;
sce->camera = (Object *)BLI_findstring(&pr_main->object, "Camera", offsetof(ID, name) + 2);
+ set_preview_layer(view_layer, MA_LAMP);
}
}
+ else {
+ set_preview_layer(view_layer, MA_LAMP);
+ }
- for (base = sce->base.first; base; base = base->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
if (base->object->id.name[2] == 'p') {
if (base->object->type == OB_LAMP)
base->object->data = la;
@@ -517,7 +594,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
BLI_addtail(&pr_main->world, wrld);
}
- sce->lay = 1 << MA_SKY;
+ set_preview_layer(view_layer, MA_SKY);
sce->world = wrld;
if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
@@ -527,6 +604,12 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
}
}
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(sce, view_layer, true);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_graph_id_tag_update(pr_main, depsgraph, &sce->id, 0);
+ DEG_relations_tag_update(pr_main);
+ BKE_scene_graph_update_tagged(pr_main->eval_ctx, depsgraph, pr_main, sce, view_layer);
+
return sce;
}
@@ -593,7 +676,9 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
if (re)
RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0);
- glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state, fx, fy, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect_byte,
+ 1.0f, 1.0f, NULL);
MEM_freeN(rect_byte);
@@ -775,7 +860,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex;
/* entire cycle for render engine */
- RE_PreviewRender(re, pr_main, sce);
+ RE_PreviewRender(re, pr_main, sce, sp->view_render);
((Camera *)sce->camera->data)->lens = oldlens;
@@ -1022,6 +1107,12 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat
*do_update = true;
}
+ else if (idtype == ID_SCR) {
+ bScreen *screen = (bScreen *)id;
+
+ ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect);
+ *do_update = true;
+ }
else {
/* re-use shader job */
shader_preview_startjob(customdata, stop, do_update);
@@ -1096,6 +1187,7 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
/* construct shader preview from image size and previewcustomdata */
sp->scene = ip->scene;
+ sp->view_render = ip->view_render;
sp->owner = ip->owner;
sp->sizex = cur_size->sizex;
sp->sizey = cur_size->sizey;
@@ -1180,6 +1272,7 @@ void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, unsigned int *rec
ip.bmain = bmain;
ip.scene = scene;
+ ip.view_render = &scene->view_render;
ip.owner = BKE_previewimg_id_ensure(id);
ip.id = id;
@@ -1213,6 +1306,7 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r
/* customdata for preview thread */
ip->bmain = CTX_data_main(C);
ip->scene = CTX_data_scene(C);
+ ip->view_render = &ip->scene->view_render;
ip->owner = owner;
ip->id = id;
@@ -1240,8 +1334,12 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
wmJob *wm_job;
ShaderPreview *sp;
Scene *scene = CTX_data_scene(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
short id_type = GS(id->name);
- bool use_new_shading = BKE_scene_use_new_shading_nodes(scene);
+
+ /* Use workspace render only for buttons Window, since the other previews are related to the datablock. */
+ ViewRender *view_render = (method == PR_BUTS_RENDER) ? BKE_viewrender_get(scene, workspace) : &scene->view_render;
+ bool use_new_shading = BKE_viewrender_use_new_shading_nodes(view_render);
/* Only texture node preview is supported with Cycles. */
if (use_new_shading && method == PR_NODE_RENDER && id_type != ID_TE) {
@@ -1264,6 +1362,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
sp->parent = parent;
sp->slot = slot;
sp->bmain = CTX_data_main(C);
+ sp->view_render = view_render;
/* hardcoded preview .blend for cycles/internal, this should be solved
* once with custom preview .blend path for external engines */
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 0a7bca1f490..04604feab6a 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -50,10 +50,10 @@
#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#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"
@@ -65,7 +65,8 @@
#include "BKE_world.h"
#include "BKE_editmesh.h"
-
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
#ifdef WITH_FREESTYLE
# include "BKE_freestyle.h"
@@ -83,6 +84,7 @@
#include "ED_mesh.h"
#include "ED_node.h"
#include "ED_render.h"
+#include "ED_scene.h"
#include "ED_screen.h"
#include "RNA_define.h"
@@ -153,7 +155,7 @@ static int material_slot_remove_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob);
@@ -219,7 +221,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
return OPERATOR_FINISHED;
@@ -359,7 +361,7 @@ static int material_slot_copy_exec(bContext *C, wmOperator *UNUSED(op))
if (ob_iter->totcol == ob->totcol) {
ob_iter->actcol = ob->actcol;
- DAG_id_tag_update(&ob_iter->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
}
}
@@ -424,7 +426,7 @@ static int material_slot_move_exec(bContext *C, wmOperator *op)
MEM_freeN(slot_remap);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | ND_DATA, ob);
return OPERATOR_FINISHED;
@@ -622,56 +624,58 @@ void WORLD_OT_new(wmOperatorType *ot)
/********************** render layer operators *********************/
-static int render_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
+static int view_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_view_layer_add(scene, NULL);
+ scene->active_view_layer = BLI_listbase_count(&scene->view_layers) - 1;
- DAG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+ DEG_id_tag_update(&scene->id, 0);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
return OPERATOR_FINISHED;
}
-void SCENE_OT_render_layer_add(wmOperatorType *ot)
+void SCENE_OT_view_layer_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add Render Layer";
- ot->idname = "SCENE_OT_render_layer_add";
- ot->description = "Add a render layer";
+ ot->name = "Add View Layer";
+ ot->idname = "SCENE_OT_view_layer_add";
+ ot->description = "Add a view layer";
/* api callbacks */
- ot->exec = render_layer_add_exec;
+ ot->exec = view_layer_add_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
-static int render_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
+static int view_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *rl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ ViewLayer *view_layer = BKE_view_layer_from_scene_get(scene);
- if (!BKE_scene_remove_render_layer(CTX_data_main(C), scene, rl))
+ if (!ED_scene_view_layer_delete(bmain, scene, view_layer, NULL)) {
return OPERATOR_CANCELLED;
+ }
- DAG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
-
+
return OPERATOR_FINISHED;
}
-void SCENE_OT_render_layer_remove(wmOperatorType *ot)
+void SCENE_OT_view_layer_remove(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Render Layer";
- ot->idname = "SCENE_OT_render_layer_remove";
- ot->description = "Remove the selected render layer";
+ ot->name = "Remove View Layer";
+ ot->idname = "SCENE_OT_view_layer_remove";
+ ot->description = "Remove the selected view layer";
/* api callbacks */
- ot->exec = render_layer_remove_exec;
+ ot->exec = view_layer_remove_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
@@ -768,9 +772,9 @@ static int freestyle_active_module_poll(bContext *C)
static int freestyle_module_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
- BKE_freestyle_module_add(&srl->freestyleConfig);
+ BKE_freestyle_module_add(&view_layer->freestyle_config);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
@@ -794,13 +798,13 @@ void SCENE_OT_freestyle_module_add(wmOperatorType *ot)
static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
FreestyleModuleConfig *module = ptr.data;
- BKE_freestyle_module_delete(&srl->freestyleConfig, module);
+ BKE_freestyle_module_delete(&view_layer->freestyle_config, module);
- DAG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
return OPERATOR_FINISHED;
@@ -824,13 +828,13 @@ void SCENE_OT_freestyle_module_remove(wmOperatorType *ot)
static int freestyle_module_move_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
FreestyleModuleConfig *module = ptr.data;
int dir = RNA_enum_get(op->ptr, "direction");
- if (BKE_freestyle_module_move(&srl->freestyleConfig, module, dir)) {
- DAG_id_tag_update(&scene->id, 0);
+ if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) {
+ DEG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
}
@@ -866,11 +870,11 @@ static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
- BKE_freestyle_lineset_add(bmain, &srl->freestyleConfig, NULL);
+ BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, NULL);
- DAG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
return OPERATOR_FINISHED;
@@ -893,21 +897,21 @@ void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot)
static int freestyle_active_lineset_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
- if (!srl) {
+ if (!view_layer) {
return false;
}
- return BKE_freestyle_lineset_get_active(&srl->freestyleConfig) != NULL;
+ return BKE_freestyle_lineset_get_active(&view_layer->freestyle_config) != NULL;
}
static int freestyle_lineset_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
- FRS_copy_active_lineset(&srl->freestyleConfig);
+ FRS_copy_active_lineset(&view_layer->freestyle_config);
return OPERATOR_FINISHED;
}
@@ -930,11 +934,11 @@ void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot)
static int freestyle_lineset_paste_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
- FRS_paste_active_lineset(&srl->freestyleConfig);
+ FRS_paste_active_lineset(&view_layer->freestyle_config);
- DAG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
return OPERATOR_FINISHED;
@@ -958,11 +962,11 @@ void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot)
static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
- FRS_delete_active_lineset(&srl->freestyleConfig);
+ FRS_delete_active_lineset(&view_layer->freestyle_config);
- DAG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
return OPERATOR_FINISHED;
@@ -986,11 +990,11 @@ void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot)
static int freestyle_lineset_move_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
int dir = RNA_enum_get(op->ptr, "direction");
- if (FRS_move_active_lineset(&srl->freestyleConfig, dir)) {
- DAG_id_tag_update(&scene->id, 0);
+ if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) {
+ DEG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
}
@@ -1026,8 +1030,8 @@ static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
if (!lineset) {
BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
@@ -1040,7 +1044,7 @@ static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
else {
lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle");
}
- DAG_id_tag_update(&lineset->linestyle->id, 0);
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
return OPERATOR_FINISHED;
@@ -1064,8 +1068,8 @@ void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot)
static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
int type = RNA_enum_get(op->ptr, "type");
if (!freestyle_linestyle_check_report(lineset, op->reports)) {
@@ -1076,7 +1080,7 @@ static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type");
return OPERATOR_CANCELLED;
}
- DAG_id_tag_update(&lineset->linestyle->id, 0);
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
return OPERATOR_FINISHED;
@@ -1104,8 +1108,8 @@ void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot)
static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
int type = RNA_enum_get(op->ptr, "type");
if (!freestyle_linestyle_check_report(lineset, op->reports)) {
@@ -1116,7 +1120,7 @@ static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
return OPERATOR_CANCELLED;
}
- DAG_id_tag_update(&lineset->linestyle->id, 0);
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
return OPERATOR_FINISHED;
@@ -1144,8 +1148,8 @@ void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot)
static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
int type = RNA_enum_get(op->ptr, "type");
if (!freestyle_linestyle_check_report(lineset, op->reports)) {
@@ -1156,7 +1160,7 @@ static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
return OPERATOR_CANCELLED;
}
- DAG_id_tag_update(&lineset->linestyle->id, 0);
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
return OPERATOR_FINISHED;
@@ -1184,8 +1188,8 @@ void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot)
static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
int type = RNA_enum_get(op->ptr, "type");
if (!freestyle_linestyle_check_report(lineset, op->reports)) {
@@ -1196,7 +1200,7 @@ static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
return OPERATOR_CANCELLED;
}
- DAG_id_tag_update(&lineset->linestyle->id, 0);
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
return OPERATOR_FINISHED;
@@ -1237,8 +1241,8 @@ static int freestyle_get_modifier_type(PointerRNA *ptr)
static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
LineStyleModifier *modifier = ptr.data;
@@ -1263,7 +1267,7 @@ static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
return OPERATOR_CANCELLED;
}
- DAG_id_tag_update(&lineset->linestyle->id, 0);
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
return OPERATOR_FINISHED;
@@ -1287,8 +1291,8 @@ void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot)
static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
LineStyleModifier *modifier = ptr.data;
@@ -1313,7 +1317,7 @@ static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
return OPERATOR_CANCELLED;
}
- DAG_id_tag_update(&lineset->linestyle->id, 0);
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
return OPERATOR_FINISHED;
@@ -1337,8 +1341,8 @@ void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot)
static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config);
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
LineStyleModifier *modifier = ptr.data;
int dir = RNA_enum_get(op->ptr, "direction");
@@ -1367,7 +1371,7 @@ static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
}
if (changed) {
- DAG_id_tag_update(&lineset->linestyle->id, 0);
+ DEG_id_tag_update(&lineset->linestyle->id, 0);
WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle);
}
@@ -1488,7 +1492,7 @@ static int texture_slot_move_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
}
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index 4e02ff77a31..a391b13a000 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -38,9 +38,12 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_world_types.h"
#include "DNA_windowmanager_types.h"
+#include "DRW_engine.h"
+
#include "BLI_listbase.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@@ -48,12 +51,15 @@
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
#include "BKE_icons.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_paint.h"
#include "BKE_scene.h"
+#include "BKE_workspace.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
#include "GPU_buffers.h"
@@ -64,16 +70,23 @@
#include "ED_render.h"
#include "ED_view3d.h"
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+
#include "render_intern.h" // own include
extern Material defmaterial;
/***************************** Render Engines ********************************/
-void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
+void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int updated)
{
/* viewport rendering update on data changes, happens after depsgraph
* updates if there was any change. context is set to the 3d view */
+ Main *bmain = update_ctx->bmain;
+ Scene *scene = update_ctx->scene;
+ ViewLayer *view_layer = update_ctx->view_layer;
bContext *C;
wmWindowManager *wm;
wmWindow *win;
@@ -102,26 +115,24 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
wm = bmain->wm.first;
for (win = wm->windows.first; win; win = win->next) {
- bScreen *sc = win->screen;
+ bScreen *sc = WM_window_get_active_screen(win);
ScrArea *sa;
ARegion *ar;
CTX_wm_window_set(C, win);
-
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ ViewRender *view_render = BKE_viewrender_get(win->scene, workspace);
+
for (sa = sc->areabase.first; sa; sa = sa->next) {
if (sa->spacetype != SPACE_VIEW3D)
continue;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- RegionView3D *rv3d;
- RenderEngine *engine;
-
- if (ar->regiontype != RGN_TYPE_WINDOW)
+ if (ar->regiontype != RGN_TYPE_WINDOW) {
continue;
-
- rv3d = ar->regiondata;
- engine = rv3d->render_engine;
-
+ }
+ RegionView3D *rv3d = ar->regiondata;
+ RenderEngine *engine = rv3d->render_engine;
/* call update if the scene changed, or if the render engine
* tagged itself for update (e.g. because it was busy at the
* time of the last update) */
@@ -133,6 +144,23 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
engine->flag &= ~RE_ENGINE_DO_UPDATE;
engine->type->view_update(engine, C);
+
+ }
+ else {
+ RenderEngineType *engine_type = RE_engines_find(view_render->engine_id);
+ if ((engine_type->flag & RE_USE_LEGACY_PIPELINE) == 0) {
+ if (updated) {
+ DRW_notify_view_update(
+ (&(DRWUpdateContext){
+ .bmain = bmain,
+ .scene = scene,
+ .view_layer = view_layer,
+ .ar = ar,
+ .v3d = (View3D *)sa->spacedata.first,
+ .engine_type = engine_type
+ }));
+ }
+ }
}
}
}
@@ -143,23 +171,6 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
recursive_check = false;
}
-void ED_render_scene_update_pre(Main *bmain, Scene *scene, bool time)
-{
- /* Blender internal might access to the data which is gonna to be freed
- * by the scene update functions. This applies for example to simulation
- * data like smoke and fire.
- */
- if (time && !BKE_scene_use_new_shading_nodes(scene)) {
- bScreen *sc;
- ScrArea *sa;
- for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- ED_render_engine_area_exit(bmain, sa);
- }
- }
- }
-}
-
void ED_render_engine_area_exit(Main *bmain, ScrArea *sa)
{
/* clear all render engines in this area */
@@ -179,18 +190,21 @@ void ED_render_engine_area_exit(Main *bmain, ScrArea *sa)
void ED_render_engine_changed(Main *bmain)
{
/* on changing the render engine type, clear all running render engines */
- bScreen *sc;
- ScrArea *sa;
- Scene *scene;
-
- for (sc = bmain->screen.first; sc; sc = sc->id.next)
- for (sa = sc->areabase.first; sa; sa = sa->next)
+ for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
ED_render_engine_area_exit(bmain, sa);
-
+ }
+ }
RE_FreePersistentData();
-
- for (scene = bmain->scene.first; scene; scene = scene->id.next) {
- ED_render_id_flush_update(bmain, &scene->id);
+ /* Inform all render engines and draw managers. */
+ DEGEditorUpdateContext update_ctx = {NULL};
+ update_ctx.bmain = bmain;
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ update_ctx.scene = scene;
+ LINKLIST_FOREACH(ViewLayer *, view_layer, &scene->view_layers) {
+ update_ctx.view_layer = view_layer;
+ ED_render_id_flush_update(&update_ctx, &scene->id);
+ }
if (scene->nodetree) {
ntreeCompositUpdateRLayers(scene->nodetree);
}
@@ -198,7 +212,7 @@ void ED_render_engine_changed(Main *bmain)
}
/***************************** Updates ***********************************
- * ED_render_id_flush_update gets called from DAG_id_tag_update, to do *
+ * ED_render_id_flush_update gets called from DEG_id_tag_update, to do *
* editor level updates when the ID changes. when these ID blocks are in *
* the dependency graph, we can get rid of the manual dependency checks */
@@ -295,8 +309,11 @@ static void material_changed(Main *bmain, Material *ma)
BKE_icon_changed(BKE_icon_id_ensure(&ma->id));
/* glsl */
- if (ma->gpumaterial.first)
- GPU_material_free(&ma->gpumaterial);
+ if (ma->id.tag & LIB_TAG_ID_RECALC) {
+ if (!BLI_listbase_is_empty(&ma->gpumaterial)) {
+ GPU_material_free(&ma->gpumaterial);
+ }
+ }
/* find node materials using this */
for (parent = bmain->mat.first; parent; parent = parent->id.next) {
@@ -344,7 +361,6 @@ static void material_changed(Main *bmain, Material *ma)
static void lamp_changed(Main *bmain, Lamp *la)
{
Object *ob;
- Material *ma;
/* icons */
BKE_icon_changed(BKE_icon_id_ensure(&la->id));
@@ -354,10 +370,6 @@ static void lamp_changed(Main *bmain, Lamp *la)
if (ob->data == la && ob->gpulamp.first)
GPU_lamp_free(ob);
- for (ma = bmain->mat.first; ma; ma = ma->id.next)
- if (ma->gpumaterial.first)
- GPU_material_free(&ma->gpumaterial);
-
if (defmaterial.gpumaterial.first)
GPU_material_free(&defmaterial.gpumaterial);
}
@@ -378,6 +390,7 @@ static void texture_changed(Main *bmain, Tex *tex)
Lamp *la;
World *wo;
Scene *scene;
+ ViewLayer *view_layer;
Object *ob;
bNode *node;
bool texture_draw = false;
@@ -386,8 +399,11 @@ static void texture_changed(Main *bmain, Tex *tex)
BKE_icon_changed(BKE_icon_id_ensure(&tex->id));
/* paint overlays */
- for (scene = bmain->scene.first; scene; scene = scene->id.next)
- BKE_paint_invalidate_overlay_tex(scene, tex);
+ for (scene = bmain->scene.first; scene; scene = scene->id.next) {
+ for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ BKE_paint_invalidate_overlay_tex(scene, view_layer, tex);
+ }
+ }
/* find materials */
for (ma = bmain->mat.first; ma; ma = ma->id.next) {
@@ -468,23 +484,23 @@ static void texture_changed(Main *bmain, Tex *tex)
}
}
-static void world_changed(Main *bmain, World *wo)
+static void world_changed(Main *UNUSED(bmain), World *wo)
{
- Material *ma;
-
/* icons */
BKE_icon_changed(BKE_icon_id_ensure(&wo->id));
-
- /* glsl */
- for (ma = bmain->mat.first; ma; ma = ma->id.next)
- if (ma->gpumaterial.first)
- GPU_material_free(&ma->gpumaterial);
- if (defmaterial.gpumaterial.first)
- GPU_material_free(&defmaterial.gpumaterial);
-
- if (wo->gpumaterial.first)
- GPU_material_free(&wo->gpumaterial);
+ /* XXX temporary flag waiting for depsgraph proper tagging */
+ wo->update_flag = 1;
+
+ /* glsl */
+ if (wo->id.tag & LIB_TAG_ID_RECALC) {
+ if (!BLI_listbase_is_empty(&defmaterial.gpumaterial)) {
+ GPU_material_free(&defmaterial.gpumaterial);
+ }
+ if (!BLI_listbase_is_empty(&wo->gpumaterial)) {
+ GPU_material_free(&wo->gpumaterial);
+ }
+ }
}
static void image_changed(Main *bmain, Image *ima)
@@ -503,41 +519,29 @@ static void image_changed(Main *bmain, Image *ima)
static void scene_changed(Main *bmain, Scene *scene)
{
Object *ob;
- Material *ma;
- World *wo;
/* glsl */
for (ob = bmain->object.first; ob; ob = ob->id.next) {
- if (ob->gpulamp.first)
- GPU_lamp_free(ob);
-
if (ob->mode & OB_MODE_TEXTURE_PAINT) {
BKE_texpaint_slots_refresh_object(scene, ob);
BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
GPU_drawobject_free(ob->derivedFinal);
}
}
-
- for (ma = bmain->mat.first; ma; ma = ma->id.next)
- if (ma->gpumaterial.first)
- GPU_material_free(&ma->gpumaterial);
-
- for (wo = bmain->world.first; wo; wo = wo->id.next)
- if (wo->gpumaterial.first)
- GPU_material_free(&wo->gpumaterial);
-
- if (defmaterial.gpumaterial.first)
- GPU_material_free(&defmaterial.gpumaterial);
}
-void ED_render_id_flush_update(Main *bmain, ID *id)
+void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id)
{
/* this can be called from render or baking thread when a python script makes
* changes, in that case we don't want to do any editor updates, and making
* GPU changes is not possible because OpenGL only works in the main thread */
- if (!BLI_thread_is_main())
+ if (!BLI_thread_is_main()) {
return;
-
+ }
+ Main *bmain = update_ctx->bmain;
+ Scene *scene = update_ctx->scene;
+ ViewLayer *view_layer = update_ctx->view_layer;
+ /* Internal ID update handlers. */
switch (GS(id->name)) {
case ID_MA:
material_changed(bmain, (Material *)id);
@@ -563,7 +567,42 @@ void ED_render_id_flush_update(Main *bmain, ID *id)
render_engine_flag_changed(bmain, RE_ENGINE_UPDATE_OTHER);
break;
}
-
+ /* Inform all draw managers about changes.
+ *
+ * TODO(sergey): This code is run for every updated ID, via flushing
+ * mechanism. How can we avoid iterating over the whole interface for
+ * every of those IDs? One of the ideas would be to call draw manager's
+ * ID update which is not bound to any of contexts.
+ */
+ {
+ wmWindowManager *wm = bmain->wm.first;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ bScreen *sc = WM_window_get_active_screen(win);
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ ViewRender *view_render = BKE_viewrender_get(win->scene, workspace);
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype != SPACE_VIEW3D) {
+ continue;
+ }
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype != RGN_TYPE_WINDOW) {
+ continue;
+ }
+ RenderEngineType *engine_type = RE_engines_find(view_render->engine_id);
+ DRW_notify_id_update(
+ (&(DRWUpdateContext){
+ .bmain = bmain,
+ .scene = scene,
+ .view_layer = view_layer,
+ .ar = ar,
+ .v3d = (View3D *)sa->spacedata.first,
+ .engine_type = engine_type
+ }),
+ id);
+ }
+ }
+ }
+ }
}
@@ -572,6 +611,6 @@ void ED_render_internal_init(void)
RenderEngineType *ret = RE_engines_find(RE_engine_id_BLENDER_RENDER);
ret->view_update = render_view3d_update;
- ret->view_draw = render_view3d_draw;
+ ret->render_to_view = render_view3d_draw;
}
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index c4a9af79ec2..e4bae9d78ea 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -90,8 +90,10 @@ static ScrArea *find_area_showing_r_result(bContext *C, Scene *scene, wmWindow *
/* find an imagewindow showing render result */
for (*win = wm->windows.first; *win; *win = (*win)->next) {
- if ((*win)->screen->scene == scene) {
- for (sa = (*win)->screen->areabase.first; sa; sa = sa->next) {
+ if (WM_window_get_active_scene(*win) == scene) {
+ const bScreen *screen = WM_window_get_active_screen(*win);
+
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->spacetype == SPACE_IMAGE) {
sima = sa->spacedata.first;
if (sima->image && sima->image->type == IMA_TYPE_R_RESULT)
@@ -246,7 +248,7 @@ static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(op))
}
/* test if we have a temp screen in front */
- if (win->screen->temp) {
+ if (WM_window_is_temp_screen(win)) {
wm_window_lower(win);
return OPERATOR_FINISHED;
}
@@ -292,7 +294,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e
wmWindow *wincur = CTX_wm_window(C);
/* test if we have currently a temp screen active */
- if (wincur->screen->temp) {
+ if (WM_window_is_temp_screen(wincur)) {
wm_window_lower(wincur);
}
else {
@@ -301,8 +303,9 @@ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *e
/* is there another window on current scene showing result? */
for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) {
- bScreen *sc = win->screen;
- if ((sc->temp && ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) ||
+ const bScreen *sc = WM_window_get_active_screen(win);
+
+ if ((WM_window_is_temp_screen(win) && ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) ||
(win == winshow && winshow != wincur))
{
wm_window_raise(win);
diff --git a/source/blender/editors/scene/CMakeLists.txt b/source/blender/editors/scene/CMakeLists.txt
new file mode 100644
index 00000000000..9fbebbc58cc
--- /dev/null
+++ b/source/blender/editors/scene/CMakeLists.txt
@@ -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.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../depsgraph
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+)
+
+set(INC_SYS
+
+)
+
+set(SRC
+ scene_edit.c
+)
+
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
+blender_add_lib(bf_editor_scene "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c
new file mode 100644
index 00000000000..812f9a736bf
--- /dev/null
+++ b/source/blender/editors/scene/scene_edit.c
@@ -0,0 +1,278 @@
+/*
+ * ***** 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/scene/scene_edit.c
+ * \ingroup edscene
+ */
+
+#include <stdio.h>
+
+#include "BLI_compiler_attrs.h"
+#include "BLI_listbase.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_layer.h"
+#include "BKE_library_remap.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_workspace.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_workspace_types.h"
+
+#include "ED_object.h"
+#include "ED_render.h"
+#include "ED_scene.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+
+Scene *ED_scene_add(Main *bmain, bContext *C, wmWindow *win, eSceneCopyMethod method)
+{
+ Scene *scene_new;
+
+ if (method == SCE_COPY_NEW) {
+ scene_new = BKE_scene_add(bmain, DATA_("Scene"));
+ }
+ else { /* different kinds of copying */
+ Scene *scene_old = WM_window_get_active_scene(win);
+
+ scene_new = BKE_scene_copy(bmain, scene_old, method);
+
+ /* these can't be handled in blenkernel currently, so do them here */
+ if (method == SCE_COPY_LINK_DATA) {
+ ED_object_single_users(bmain, scene_new, false, true);
+ }
+ else if (method == SCE_COPY_FULL) {
+ ED_editors_flush_edits(C, false);
+ ED_object_single_users(bmain, scene_new, true, true);
+ }
+ }
+
+ WM_window_change_active_scene(bmain, C, win, scene_new);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, scene_new);
+
+ return scene_new;
+}
+
+/**
+ * \note Only call outside of area/region loops
+ * \return true if successful
+ */
+bool ED_scene_delete(bContext *C, Main *bmain, wmWindow *win, Scene *scene)
+{
+ Scene *scene_new;
+
+ if (scene->id.prev)
+ scene_new = scene->id.prev;
+ else if (scene->id.next)
+ scene_new = scene->id.next;
+ else
+ return false;
+
+ WM_window_change_active_scene(bmain, C, win, scene_new);
+
+ BKE_libblock_remap(bmain, scene, scene_new, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
+
+ id_us_clear_real(&scene->id);
+ if (scene->id.us == 0) {
+ BKE_libblock_free(bmain, scene);
+ }
+
+ return true;
+}
+
+void ED_scene_exit(bContext *C)
+{
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO);
+}
+
+static ViewLayer *scene_change_get_new_view_layer(const WorkSpace *workspace, const Scene *scene_new)
+{
+ ViewLayer *layer_new = BKE_workspace_view_layer_get(workspace, scene_new);
+ return layer_new ? layer_new : BKE_view_layer_from_scene_get(scene_new);
+}
+
+void ED_scene_changed_update(Main *bmain, bContext *C, Scene *scene_new, const bScreen *active_screen)
+{
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ ViewLayer *layer_new = scene_change_get_new_view_layer(workspace, scene_new);
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene_new, layer_new, true);
+
+ CTX_data_scene_set(C, scene_new);
+ BKE_workspace_view_layer_set(workspace, layer_new, scene_new);
+ BKE_scene_set_background(bmain, scene_new);
+ DEG_graph_relations_update(depsgraph, bmain, scene_new, layer_new);
+ DEG_on_visible_update(bmain, false);
+
+ ED_screen_update_after_scene_change(active_screen, scene_new, layer_new);
+ ED_render_engine_changed(bmain);
+ ED_update_for_newframe(bmain, scene_new, layer_new, depsgraph);
+
+ /* complete redraw */
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+}
+
+static bool view_layer_remove_poll(
+ const Scene *scene, const ViewLayer *layer)
+{
+ const int act = BLI_findindex(&scene->view_layers, layer);
+
+ if (act == -1) {
+ return false;
+ }
+ else if ((scene->view_layers.first == scene->view_layers.last) &&
+ (scene->view_layers.first == layer))
+ {
+ /* ensure 1 layer is kept */
+ return false;
+ }
+
+ return true;
+}
+
+static void view_layer_remove_unset_nodetrees(const Main *bmain, Scene *scene, ViewLayer *layer)
+{
+ int act_layer_index = BLI_findindex(&scene->view_layers, layer);
+
+ for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
+ if (sce->nodetree) {
+ BKE_nodetree_remove_layer_n(sce->nodetree, scene, act_layer_index);
+ }
+ }
+}
+
+bool ED_scene_view_layer_delete(
+ Main *bmain, Scene *scene, ViewLayer *layer,
+ ReportList *reports)
+{
+ if (view_layer_remove_poll(scene, layer) == false) {
+ if (reports) {
+ BKE_reportf(reports, RPT_ERROR, "View layer '%s' could not be removed from scene '%s'",
+ layer->name, scene->id.name + 2);
+ }
+
+ return false;
+ }
+
+ BLI_remlink(&scene->view_layers, layer);
+ BLI_assert(BLI_listbase_is_empty(&scene->view_layers) == false);
+ scene->active_view_layer = 0;
+
+ ED_workspace_view_layer_unset(bmain, scene, layer, scene->view_layers.first);
+ BKE_workspace_view_layer_remove_references(bmain, layer);
+ view_layer_remove_unset_nodetrees(bmain, scene, layer);
+
+ BKE_view_layer_free(layer);
+
+ DEG_id_tag_update(&scene->id, 0);
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER | NA_REMOVED, scene);
+
+ return true;
+}
+
+static int scene_new_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = CTX_wm_window(C);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ ED_scene_add(bmain, C, win, type);
+
+ return OPERATOR_FINISHED;
+}
+
+static void SCENE_OT_new(wmOperatorType *ot)
+{
+ static EnumPropertyItem type_items[] = {
+ {SCE_COPY_NEW, "NEW", 0, "New", "Add new scene"},
+ {SCE_COPY_EMPTY, "EMPTY", 0, "Copy Settings", "Make a copy without any objects"},
+ {SCE_COPY_LINK_OB, "LINK_OBJECTS", 0, "Link Objects", "Link to the objects from the current scene"},
+ {SCE_COPY_LINK_DATA, "LINK_OBJECT_DATA", 0, "Link Object Data", "Copy objects linked to data from the current scene"},
+ {SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "New Scene";
+ ot->description = "Add new scene by type";
+ ot->idname = "SCENE_OT_new";
+
+ /* api callbacks */
+ ot->exec = scene_new_exec;
+ ot->invoke = WM_menu_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
+}
+
+static int scene_delete_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+
+ if (ED_scene_delete(C, CTX_data_main(C), CTX_wm_window(C), scene) == false) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (G.debug & G_DEBUG)
+ printf("scene delete %p\n", scene);
+
+ WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+static void SCENE_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete Scene";
+ ot->description = "Delete active scene";
+ ot->idname = "SCENE_OT_delete";
+
+ /* api callbacks */
+ ot->exec = scene_delete_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void ED_operatortypes_scene(void)
+{
+ WM_operatortype_append(SCENE_OT_new);
+ WM_operatortype_append(SCENE_OT_delete);
+}
diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt
index ed86ffa5e16..02584a4611b 100644
--- a/source/blender/editors/screen/CMakeLists.txt
+++ b/source/blender/editors/screen/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenfont
../../blenkernel
../../blenlib
+ ../../blenloader
../../blentranslation
../../bmesh
../../gpu
@@ -42,9 +43,12 @@ set(SRC
area.c
glutil.c
screen_context.c
+ screen_draw.c
screen_edit.c
screen_ops.c
screendump.c
+ workspace_edit.c
+ workspace_layout_edit.c
screen_intern.h
)
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 9cfaf3b4c1d..08d92dfc9ff 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -51,14 +51,18 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "wm_subwindow.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
#include "ED_space_api.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_draw.h"
+
#include "BLF_api.h"
#include "IMB_imbuf.h"
@@ -71,7 +75,7 @@
#include "screen_intern.h"
-extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */
+extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, const float color[4]); /* xxx temp */
/* general area and region code */
@@ -89,21 +93,30 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINE_STRIP, 5);
+
/* right */
- glColor4ub(0, 0, 0, 30);
- sdrawline(rect.xmax, rect.ymin, rect.xmax, rect.ymax);
+ immAttrib4ub(color, 0, 0, 0, 30);
+ immVertex2f(pos, rect.xmax, rect.ymax);
+ immVertex2f(pos, rect.xmax, rect.ymin);
/* bottom */
- glColor4ub(0, 0, 0, 30);
- sdrawline(rect.xmin, rect.ymin, rect.xmax, rect.ymin);
+ immVertex2f(pos, rect.xmin, rect.ymin);
- /* top */
- glColor4ub(255, 255, 255, 30);
- sdrawline(rect.xmin, rect.ymax, rect.xmax, rect.ymax);
-
/* left */
- glColor4ub(255, 255, 255, 30);
- sdrawline(rect.xmin, rect.ymin, rect.xmin, rect.ymax);
+ immAttrib4ub(color, 255, 255, 255, 30);
+ immVertex2f(pos, rect.xmin, rect.ymax);
+
+ /* top */
+ immVertex2f(pos, rect.xmax, rect.ymax);
+
+ immEnd();
+ immUnbindProgram();
glDisable(GL_BLEND);
}
@@ -111,11 +124,11 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct)
void ED_region_pixelspace(ARegion *ar)
{
wmOrtho2_region_pixelspace(ar);
- glLoadIdentity();
+ gpuLoadIdentity();
}
/* only exported for WM */
-void ED_region_do_listen(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *note)
+void ED_region_do_listen(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *note, const Scene *scene)
{
/* generic notes first */
switch (note->category) {
@@ -129,15 +142,15 @@ void ED_region_do_listen(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *note
}
if (ar->type && ar->type->listener)
- ar->type->listener(sc, sa, ar, note);
+ ar->type->listener(sc, sa, ar, note, scene);
}
/* only exported for WM */
-void ED_area_do_listen(bScreen *sc, ScrArea *sa, wmNotifier *note)
+void ED_area_do_listen(bScreen *sc, ScrArea *sa, wmNotifier *note, Scene *scene, WorkSpace *workspace)
{
/* no generic notes? */
if (sa->type && sa->type->listener) {
- sa->type->listener(sc, sa, note);
+ sa->type->listener(sc, sa, note, scene, workspace);
}
}
@@ -206,15 +219,27 @@ static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, f
if (G.debug_value == 1) {
rcti click_rect;
float icon_size = UI_DPI_ICON_SIZE + 7 * UI_DPI_FAC;
- char alpha_debug = 255 * alpha;
+ unsigned char alpha_debug = 255 * alpha;
BLI_rcti_init(&click_rect, x, x + icon_size, y, y + icon_size);
- glColor4ub(255, 0, 0, alpha_debug);
- fdrawbox(click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax);
- glColor4ub(0, 255, 255, alpha_debug);
- fdrawline(click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax);
- fdrawline(click_rect.xmin, click_rect.ymax, click_rect.xmax, click_rect.ymin);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immAttrib4ub(color, 255, 0, 0, alpha_debug);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ imm_draw_box_wire_2d(pos, click_rect.xmin, click_rect.ymin, click_rect.xmax, click_rect.ymax);
+
+ immAttrib4ub(color, 0, 255, 255, alpha_debug);
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex2f(pos, click_rect.xmin, click_rect.ymin);
+ immVertex2f(pos, click_rect.xmax, click_rect.ymax);
+ immVertex2f(pos, click_rect.xmin, click_rect.ymax);
+ immVertex2f(pos, click_rect.xmax, click_rect.ymin);
+ immEnd();
+
+ immUnbindProgram();
}
}
@@ -229,69 +254,96 @@ static void area_draw_azone(short x1, short y1, short x2, short y2)
dx = copysign(ceilf(0.3f * abs(dx)), dx);
dy = copysign(ceilf(0.3f * abs(dy)), dy);
- glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINES, 12);
+
+ immAttrib4ub(col, 255, 255, 255, 180);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y1);
+
+ immAttrib4ub(col, 255, 255, 255, 130);
+ immVertex2f(pos, x1, y2 - dy);
+ immVertex2f(pos, x2 - dx, y1);
+
+ immAttrib4ub(col, 255, 255, 255, 80);
+ immVertex2f(pos, x1, y2 - 2 * dy);
+ immVertex2f(pos, x2 - 2 * dx, y1);
- glColor4ub(255, 255, 255, 180);
- fdrawline(x1, y2, x2, y1);
- glColor4ub(255, 255, 255, 130);
- fdrawline(x1, y2 - dy, x2 - dx, y1);
- glColor4ub(255, 255, 255, 80);
- fdrawline(x1, y2 - 2 * dy, x2 - 2 * dx, y1);
-
- glColor4ub(0, 0, 0, 210);
- fdrawline(x1, y2 + 1, x2 + 1, y1);
- glColor4ub(0, 0, 0, 180);
- fdrawline(x1, y2 - dy + 1, x2 - dx + 1, y1);
- glColor4ub(0, 0, 0, 150);
- fdrawline(x1, y2 - 2 * dy + 1, x2 - 2 * dx + 1, y1);
+ immAttrib4ub(col, 0, 0, 0, 210);
+ immVertex2f(pos, x1, y2 + 1);
+ immVertex2f(pos, x2 + 1, y1);
+
+ immAttrib4ub(col, 0, 0, 0, 180);
+ immVertex2f(pos, x1, y2 - dy + 1);
+ immVertex2f(pos, x2 - dx + 1, y1);
+
+ immAttrib4ub(col, 0, 0, 0, 150);
+ immVertex2f(pos, x1, y2 - 2 * dy + 1);
+ immVertex2f(pos, x2 - 2 * dx + 1, y1);
+
+ immEnd();
+ immUnbindProgram();
glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
}
static void region_draw_azone_icon(AZone *az)
{
- GLUquadricObj *qobj = NULL;
- short midx = az->x1 + (az->x2 - az->x1) / 2;
- short midy = az->y1 + (az->y2 - az->y1) / 2;
-
- qobj = gluNewQuadric();
-
- glPushMatrix();
- glTranslatef(midx, midy, 0.0);
-
- /* outlined circle */
- glEnable(GL_LINE_SMOOTH);
+ float midx = az->x1 + (az->x2 - az->x1) * 0.5f;
+ float midy = az->y1 + (az->y2 - az->y1) * 0.5f;
- glColor4f(1.f, 1.f, 1.f, 0.8f);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- gluQuadricDrawStyle(qobj, GLU_FILL);
- gluDisk(qobj, 0.0, 4.25f, 16, 1);
+ /* outlined circle */
+ GPU_enable_program_point_size(); /* TODO: make a fixed-size shader to avoid this */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
+ immUniform4f("outlineColor", 0.2f, 0.2f, 0.2f, 0.9f);
+ immUniform1f("outlineWidth", 1.0f);
+ immUniform1f("size", 9.5f);
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex2f(pos, midx, midy);
+ immEnd();
+ immUnbindProgram();
+ GPU_disable_program_point_size();
- glColor4f(0.2f, 0.2f, 0.2f, 0.9f);
-
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
- gluDisk(qobj, 0.0, 4.25f, 16, 1);
-
- glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
- gluDeleteQuadric(qobj);
-
/* + */
- sdrawline(midx, midy - 2, midx, midy + 3);
- sdrawline(midx - 2, midy, midx + 3, midy);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(0.2f, 0.2f, 0.2f, 0.9f);
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex2f(pos, midx, midy - 2);
+ immVertex2f(pos, midx, midy + 3);
+ immVertex2f(pos, midx - 2, midy);
+ immVertex2f(pos, midx + 3, midy);
+ immEnd();
+ immUnbindProgram();
}
static void draw_azone_plus(float x1, float y1, float x2, float y2)
{
float width = 0.1f * U.widget_unit;
float pad = 0.2f * U.widget_unit;
-
- glRectf((x1 + x2 - width) * 0.5f, y1 + pad, (x1 + x2 + width) * 0.5f, y2 - pad);
- glRectf(x1 + pad, (y1 + y2 - width) * 0.5f, (x1 + x2 - width) * 0.5f, (y1 + y2 + width) * 0.5f);
- glRectf((x1 + x2 + width) * 0.5f, (y1 + y2 - width) * 0.5f, x2 - pad, (y1 + y2 + width) * 0.5f);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ glEnable(GL_BLEND);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(0.8f, 0.8f, 0.8f, 0.4f);
+
+ immRectf(pos, (x1 + x2 - width) * 0.5f, y1 + pad, (x1 + x2 + width) * 0.5f, y2 - pad);
+ immRectf(pos, x1 + pad, (y1 + y2 - width) * 0.5f, (x1 + x2 - width) * 0.5f, (y1 + y2 + width) * 0.5f);
+ immRectf(pos, (x1 + x2 + width) * 0.5f, (y1 + y2 - width) * 0.5f, x2 - pad, (y1 + y2 + width) * 0.5f);
+
+ immUnbindProgram();
+ glDisable(GL_BLEND);
}
static void region_draw_azone_tab_plus(AZone *az)
@@ -314,54 +366,41 @@ static void region_draw_azone_tab_plus(AZone *az)
break;
}
- glColor4f(0.05f, 0.05f, 0.05f, 0.4f);
- UI_draw_roundbox((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f);
+ float color[4] = {0.05f, 0.05f, 0.05f, 0.4f};
+ UI_draw_roundbox_aa(true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, color);
- glEnable(GL_BLEND);
-
- glColor4f(0.8f, 0.8f, 0.8f, 0.4f);
draw_azone_plus((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2);
-
- glDisable(GL_BLEND);
}
static void region_draw_azone_tab(AZone *az)
{
- float col[3];
+ float col[4], black[4] = {0.0f, 0.0f, 0.0f, 0.5f};
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_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
+ UI_draw_roundbox_shade_x(true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col);
+ UI_draw_roundbox_aa(false, (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_corner_set(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
+ UI_draw_roundbox_shade_x(true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col);
+ UI_draw_roundbox_aa(false, (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_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
+ UI_draw_roundbox_shade_x(true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col);
+ UI_draw_roundbox_aa(false, (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_corner_set(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ UI_draw_roundbox_shade_x(true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, -0.3f, 0.05f, col);
+ UI_draw_roundbox_aa(false, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, black);
break;
}
@@ -372,24 +411,24 @@ static void region_draw_azone_tria(AZone *az)
{
glEnable(GL_BLEND);
//UI_GetThemeColor3fv(TH_HEADER, col);
- glColor4f(0.0f, 0.0f, 0.0f, 0.35f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.35f};
/* add code to draw region hidden as 'too small' */
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y1, (float)(az->x1 + az->x2) / 2, (float)az->y2);
+ ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y1, (float)(az->x1 + az->x2) / 2, (float)az->y2, color);
break;
case AE_BOTTOM_TO_TOPLEFT:
- ui_draw_anti_tria((float)az->x1, (float)az->y2, (float)az->x2, (float)az->y2, (float)(az->x1 + az->x2) / 2, (float)az->y1);
+ ui_draw_anti_tria((float)az->x1, (float)az->y2, (float)az->x2, (float)az->y2, (float)(az->x1 + az->x2) / 2, (float)az->y1, color);
break;
case AE_LEFT_TO_TOPRIGHT:
- ui_draw_anti_tria((float)az->x2, (float)az->y1, (float)az->x2, (float)az->y2, (float)az->x1, (float)(az->y1 + az->y2) / 2);
+ ui_draw_anti_tria((float)az->x2, (float)az->y1, (float)az->x2, (float)az->y2, (float)az->x1, (float)(az->y1 + az->y2) / 2, color);
break;
case AE_RIGHT_TO_TOPLEFT:
- ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x1, (float)az->y2, (float)az->x2, (float)(az->y1 + az->y2) / 2);
+ ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x1, (float)az->y2, (float)az->x2, (float)(az->y1 + az->y2) / 2, color);
break;
}
@@ -413,8 +452,8 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPushMatrix();
- glTranslatef(-ar->winrct.xmin, -ar->winrct.ymin, 0.0f);
+ gpuPushMatrix();
+ gpuTranslate2f(-ar->winrct.xmin, -ar->winrct.ymin);
for (az = sa->actionzones.first; az; az = az->next) {
/* test if action zone is over this region */
@@ -451,7 +490,7 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
}
}
- glPopMatrix();
+ gpuPopMatrix();
glDisable(GL_BLEND);
}
@@ -473,6 +512,33 @@ void ED_region_set(const bContext *C, ARegion *ar)
ED_region_pixelspace(ar);
}
+/* Follow wmMsgNotifyFn spec */
+void ED_region_do_msg_notify_tag_redraw(
+ bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
+{
+ ARegion *ar = msg_val->owner;
+ ED_region_tag_redraw(ar);
+
+ /* This avoids _many_ situations where header/properties control display settings.
+ * the common case is space properties in the header */
+ if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_UI)) {
+ while (ar && ar->prev) {
+ ar = ar->prev;
+ }
+ for (; ar; ar = ar->next) {
+ if (ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS)) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+}
+/* Follow wmMsgNotifyFn spec */
+void ED_area_do_msg_notify_tag_refresh(
+ bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
+{
+ ScrArea *sa = msg_val->user_data;
+ ED_area_tag_refresh(sa);
+}
/* only exported for WM */
void ED_region_do_draw(bContext *C, ARegion *ar)
@@ -511,7 +577,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) {
@@ -528,9 +594,13 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
/* for debugging unneeded area redraws and partial redraw */
#if 0
glEnable(GL_BLEND);
- glColor4f(drand48(), drand48(), drand48(), 0.1f);
- glRectf(ar->drawrct.xmin - ar->winrct.xmin, ar->drawrct.ymin - ar->winrct.ymin,
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(drand48(), drand48(), drand48(), 0.1f);
+ immRectf(pos, ar->drawrct.xmin - ar->winrct.xmin, ar->drawrct.ymin - ar->winrct.ymin,
ar->drawrct.xmax - ar->winrct.xmin, ar->drawrct.ymax - ar->winrct.ymin);
+ immUnbindProgram();
glDisable(GL_BLEND);
#endif
@@ -539,12 +609,45 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
UI_blocklist_free_inactive(C, &ar->uiblocks);
if (sa) {
+ const bScreen *screen = WM_window_get_active_screen(win);
+
/* disable emboss when the area is full,
* unless we need to see division between regions (quad-split for eg) */
- if (((win->screen->state == SCREENFULL) && (ar->alignment == RGN_ALIGN_NONE)) == 0) {
+ if (((screen->state == SCREENFULL) && (ar->alignment == RGN_ALIGN_NONE)) == 0) {
region_draw_emboss(ar, &ar->winrct);
}
}
+
+ /* We may want to detach message-subscriptions from drawing. */
+ {
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ bScreen *screen = WM_window_get_active_screen(win);
+ Scene *scene = CTX_data_scene(C);
+ struct wmMsgBus *mbus = wm->message_bus;
+ WM_msgbus_clear_by_owner(mbus, ar);
+
+ /* Cheat, always subscribe to this space type properties.
+ *
+ * This covers most cases and avoids copy-paste similar code for each space type.
+ */
+ if (ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS, RGN_TYPE_UI, RGN_TYPE_TOOLS)) {
+ SpaceLink *sl = sa->spacedata.first;
+
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_Space, sl, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+ /* All properties for this space type. */
+ WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_region_tag_redraw, __func__);
+ }
+
+ ED_region_message_subscribe(C, workspace, scene, screen, sa, ar, mbus);
+ }
}
/* **********************************
@@ -655,7 +758,7 @@ void ED_area_headerprint(ScrArea *sa, const char *str)
/* ************************************************************ */
-static void area_azone_initialize(wmWindow *win, bScreen *screen, ScrArea *sa)
+static void area_azone_initialize(wmWindow *win, const bScreen *screen, ScrArea *sa)
{
AZone *az;
@@ -1311,7 +1414,9 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
* must be minimum '4' */
}
else {
- if (ELEM(win->screen->state, SCREENNORMAL, SCREENMAXIMIZED)) {
+ const bScreen *screen = WM_window_get_active_screen(win);
+
+ if (ELEM(screen->state, SCREENNORMAL, SCREENMAXIMIZED)) {
region_azone_add(sa, ar, alignment, false);
}
else {
@@ -1435,6 +1540,7 @@ static void ed_default_handlers(wmWindowManager *wm, ScrArea *sa, ListBase *hand
/* called in screen_refresh, or screens_init, also area size changes */
void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
{
+ const bScreen *screen = WM_window_get_active_screen(win);
ARegion *ar;
rcti rect;
@@ -1453,7 +1559,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
area_calc_totrct(sa, WM_window_pixels_x(win), WM_window_pixels_y(win));
/* clear all azones, add the area triange widgets */
- area_azone_initialize(win, win->screen, sa);
+ area_azone_initialize(win, screen, sa);
/* region rect sizes */
rect = sa->totrct;
@@ -1473,8 +1579,9 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
/* default region handlers */
ed_default_handlers(wm, sa, &ar->handlers, ar->type->keymapflag);
/* own handlers */
- if (ar->type->init)
+ if (ar->type->init) {
ar->type->init(wm, ar);
+ }
}
else {
/* prevent uiblocks to run */
@@ -1968,8 +2075,12 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
/* view should be in pixelspace */
UI_view2d_view_restore(C);
glEnable(GL_BLEND);
- UI_ThemeColor4((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
- glRecti(0, 0, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct) + 1);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
+ immRecti(pos, 0, 0, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct) + 1);
+ immUnbindProgram();
glDisable(GL_BLEND);
}
else {
@@ -2073,22 +2184,37 @@ int ED_area_headersize(void)
return (int)(HEADERY * UI_DPI_FAC);
}
-void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], const bool full_redraw)
+void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float fill_color[4], const bool full_redraw)
{
const int header_height = UI_UNIT_Y;
uiStyle *style = UI_style_get_dpi();
int fontid = style->widget.uifont_id;
GLint scissor[4];
rcti rect;
+ int num_lines = 0;
/* background box */
ED_region_visible_rect(ar, &rect);
- rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height;
- /* box fill entire width or just around text */
- if (!full_redraw)
- rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, text, BLF_DRAW_STR_DUMMY_MAX) + 1.2f * U.widget_unit);
+ /* Box fill entire width or just around text. */
+ if (!full_redraw) {
+ const char **text = &text_array[0];
+ while (*text) {
+ rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, *text, BLF_DRAW_STR_DUMMY_MAX) + 1.2f * U.widget_unit);
+ text++;
+ num_lines++;
+ }
+ }
+ /* Just count the line number. */
+ else {
+ const char **text = &text_array[0];
+ while (*text) {
+ text++;
+ num_lines++;
+ }
+ }
+ rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height * num_lines;
rect.ymax = BLI_rcti_size_y(&ar->winrct);
/* setup scissor */
@@ -2098,17 +2224,28 @@ void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], con
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4fv(fill_color);
- glRecti(rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(fill_color);
+ immRecti(pos, rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1);
+ immUnbindProgram();
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);
-
- BLF_draw(fontid, text, BLF_DRAW_STR_DUMMY_MAX);
+ int offset = num_lines - 1;
+ {
+ const char **text = &text_array[0];
+ while (*text) {
+ BLF_position(fontid, rect.xmin + 0.6f * U.widget_unit, rect.ymin + 0.3f * U.widget_unit + offset * header_height, 0.0f);
+ BLF_draw(fontid, *text, BLF_DRAW_STR_DUMMY_MAX);
+ text++;
+ offset--;
+ }
+ }
BLF_disable(fontid, BLF_CLIPPING);
@@ -2116,6 +2253,11 @@ void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], con
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
+void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], const bool full_redraw)
+{
+ ED_region_info_draw_multiline(ar, (const char *[2]){text, NULL}, fill_color, full_redraw);
+}
+
#define MAX_METADATA_STR 1024
static const char *meta_data_list[] =
@@ -2284,11 +2426,11 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
return;
/* find window pixel coordinates of origin */
- glPushMatrix();
+ gpuPushMatrix();
/* offset and zoom using ogl */
- glTranslatef(x, y, 0.0f);
- glScalef(zoomx, zoomy, 1.0f);
+ gpuTranslate2f(x, y);
+ gpuScale2f(zoomx, zoomy);
BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f * U.pixelsize, U.dpi);
@@ -2298,17 +2440,20 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
box_y = metadata_box_height_get(ibuf, blf_mono_font, true);
if (box_y) {
- UI_ThemeColor(TH_METADATA_BG);
-
/* set up rect */
BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymax, frame->ymax + box_y);
/* draw top box */
- glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_METADATA_BG);
+ immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ immUnbindProgram();
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);
@@ -2320,23 +2465,26 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
box_y = metadata_box_height_get(ibuf, blf_mono_font, false);
if (box_y) {
- UI_ThemeColor(TH_METADATA_BG);
-
/* set up box rect */
BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymin - box_y, frame->ymin);
/* draw top box */
- glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_METADATA_BG);
+ immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ immUnbindProgram();
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);
}
- glPopMatrix();
+ gpuPopMatrix();
}
void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
@@ -2346,11 +2494,16 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
int x1, y1, x2, y2;
/* the image is located inside (0, 0), (1, 1) as set by view2d */
- UI_ThemeColorShade(TH_BACK, 20);
-
UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x1, &y1);
UI_view2d_view_to_region(&ar->v2d, 1.0f, 1.0f, &x2, &y2);
- glRectf(x1, y1, x2, y2);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, 20);
+ immRectf(pos, x1, y1, x2, y2);
+ immUnbindProgram();
/* gridsize adapted to zoom level */
gridsize = 0.5f * (zoomx + zoomy);
@@ -2370,33 +2523,52 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
}
}
- /* the fine resolution level */
blendfac = 0.25f * gridsize - floorf(0.25f * gridsize);
CLAMP(blendfac, 0.0f, 1.0f);
- UI_ThemeColorShade(TH_BACK, (int)(20.0f * (1.0f - blendfac)));
- fac = 0.0f;
- glBegin(GL_LINES);
- while (fac < 1.0f) {
- glVertex2f(x1, y1 * (1.0f - fac) + y2 * fac);
- glVertex2f(x2, y1 * (1.0f - fac) + y2 * fac);
- glVertex2f(x1 * (1.0f - fac) + x2 * fac, y1);
- glVertex2f(x1 * (1.0f - fac) + x2 * fac, y2);
- fac += gridstep;
- }
+ int count_fine = 1.0f / gridstep;
+ int count_large = 1.0f / (4.0f * gridstep);
+
+ if (count_fine > 0) {
+ GWN_vertformat_clear(format);
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINES, 4 * count_fine + 4 * count_large);
+
+ float theme_color[3];
+ UI_GetThemeColorShade3fv(TH_BACK, (int)(20.0f * (1.0f - blendfac)), theme_color);
+ immAttrib3fv(color, theme_color);
+ fac = 0.0f;
+
+ /* the fine resolution level */
+ for (int i = 0; i < count_fine; i++) {
+ immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac);
+ immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac);
+ immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1);
+ immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2);
+ fac += gridstep;
+ }
- /* the large resolution level */
- UI_ThemeColor(TH_BACK);
+ if (count_large > 0) {
+ UI_GetThemeColor3fv(TH_BACK, theme_color);
+ immAttrib3fv(color, theme_color);
+ fac = 0.0f;
+
+ /* the large resolution level */
+ for (int i = 0; i < count_large; i++) {
+ immVertex2f(pos, x1, y1 * (1.0f - fac) + y2 * fac);
+ immVertex2f(pos, x2, y1 * (1.0f - fac) + y2 * fac);
+ immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y1);
+ immVertex2f(pos, x1 * (1.0f - fac) + x2 * fac, y2);
+ fac += 4.0f * gridstep;
+ }
+ }
- fac = 0.0f;
- while (fac < 1.0f) {
- glVertex2f(x1, y1 * (1.0f - fac) + y2 * fac);
- glVertex2f(x2, y1 * (1.0f - fac) + y2 * fac);
- glVertex2f(x1 * (1.0f - fac) + x2 * fac, y1);
- glVertex2f(x1 * (1.0f - fac) + x2 * fac, y2);
- fac += 4.0f * gridstep;
+ immEnd();
+ immUnbindProgram();
}
- glEnd();
}
/* If the area has overlapping regions, it returns visible rect for Region *ar */
@@ -2433,8 +2605,11 @@ void ED_region_visible_rect(ARegion *ar, rcti *rect)
void ED_region_cache_draw_background(const ARegion *ar)
{
- glColor4ub(128, 128, 255, 64);
- glRecti(0, 0, ar->winx, 8 * UI_DPI_FAC);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ub(128, 128, 255, 64);
+ immRecti(pos, 0, 0, ar->winx, 8 * UI_DPI_FAC);
+ immUnbindProgram();
}
void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y)
@@ -2450,9 +2625,13 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f
BLF_width_and_height(fontid, numstr, sizeof(numstr), &font_dims[0], &font_dims[1]);
- glRecti(x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_CFRAME);
+ 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));
}
@@ -2460,17 +2639,40 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f
void ED_region_cache_draw_cached_segments(const ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra)
{
if (num_segments) {
- int a;
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ub(128, 128, 255, 128);
- glColor4ub(128, 128, 255, 128);
+ for (int a = 0; a < num_segments; a++) {
+ float x1 = (float)(points[a * 2] - sfra) / (efra - sfra + 1) * ar->winx;
+ float x2 = (float)(points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * ar->winx;
- for (a = 0; a < num_segments; a++) {
- float x1, x2;
+ immRecti(pos, x1, 0, x2, 8 * UI_DPI_FAC);
+ /* TODO(merwin): use primitive restart to draw multiple rects more efficiently */
+ }
- x1 = (float)(points[a * 2] - sfra) / (efra - sfra + 1) * ar->winx;
- x2 = (float)(points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * ar->winx;
+ immUnbindProgram();
+ }
+}
- glRecti(x1, 0, x2, 8 * UI_DPI_FAC);
- }
+/**
+ * Generate subscriptions for this region.
+ */
+void ED_region_message_subscribe(
+ bContext *C,
+ struct WorkSpace *workspace, struct Scene *scene,
+ struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ if (ar->manipulator_map != NULL) {
+ WM_manipulatormap_message_subscribe(C, ar->manipulator_map, ar, mbus);
+ }
+
+ if (BLI_listbase_is_empty(&ar->uiblocks)) {
+ UI_region_message_subscribe(ar, mbus);
+ }
+
+ if (ar->type->message_subscribe != NULL) {
+ ar->type->message_subscribe(C, workspace, scene, screen, sa, ar, mbus);
}
}
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 216cbe9d7f4..7ce16efdb97 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -49,133 +49,11 @@
#include "IMB_imbuf_types.h"
#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "UI_interface.h"
-#ifndef GL_CLAMP_TO_EDGE
-#define GL_CLAMP_TO_EDGE 0x812F
-#endif
-
-/* UNUSED */
-#if 0
-void fdrawbezier(float vec[4][3])
-{
- float dist;
- float curve_res = 24, spline_step = 0.0f;
-
- dist = 0.5f * fabsf(vec[0][0] - vec[3][0]);
-
- /* check direction later, for top sockets */
- vec[1][0] = vec[0][0] + dist;
- vec[1][1] = vec[0][1];
-
- vec[2][0] = vec[3][0] - dist;
- vec[2][1] = vec[3][1];
- /* we can reuse the dist variable here to increment the GL curve eval amount */
- dist = 1.0f / curve_res;
-
- cpack(0x0);
- glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
- glBegin(GL_LINE_STRIP);
- while (spline_step < 1.000001f) {
-#if 0
- if (do_shaded)
- UI_ThemeColorBlend(th_col1, th_col2, spline_step);
-#endif
- glEvalCoord1f(spline_step);
- spline_step += dist;
- }
- glEnd();
-}
-#endif
-
-void fdrawline(float x1, float y1, float x2, float y2)
-{
- glBegin(GL_LINES);
- glVertex2f(x1, y1);
- glVertex2f(x2, y2);
- glEnd();
-}
-
-void fdrawbox(float x1, float y1, float x2, float y2)
-{
- glBegin(GL_LINE_LOOP);
-
- glVertex2f(x1, y1);
- glVertex2f(x1, y2);
- glVertex2f(x2, y2);
- glVertex2f(x2, y1);
-
- glEnd();
-}
-
-void fdrawcheckerboard(float x1, float y1, float x2, float y2)
-{
- unsigned char col1[4] = {40, 40, 40}, col2[4] = {50, 50, 50};
-
- glColor3ubv(col1);
- glRectf(x1, y1, x2, y2);
- glColor3ubv(col2);
-
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX);
- glRectf(x1, y1, x2, y2);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-}
-
-void sdrawline(int x1, int y1, int x2, int y2)
-{
- glBegin(GL_LINES);
- glVertex2i(x1, y1);
- glVertex2i(x2, y2);
- glEnd();
-}
-
-/* UNUSED */
-#if 0
-/*
- * x1,y2
- * | \
- * | \
- * | \
- * x1,y1-- x2,y1
- */
-
-static void sdrawtripoints(int x1, int y1, int x2, int y2)
-{
- glVertex2i(x1, y1);
- glVertex2i(x1, y2);
- glVertex2i(x2, y1);
-}
-
-void sdrawtri(int x1, int y1, int x2, int y2)
-{
- glBegin(GL_LINE_STRIP);
- sdrawtripoints(x1, y1, x2, y2);
- glEnd();
-}
-
-void sdrawtrifill(int x1, int y1, int x2, int y2)
-{
- glBegin(GL_TRIANGLES);
- sdrawtripoints(x1, y1, x2, y2);
- glEnd();
-}
-#endif
-
-void sdrawbox(int x1, int y1, int x2, int y2)
-{
- glBegin(GL_LINE_LOOP);
-
- glVertex2i(x1, y1);
- glVertex2i(x1, y2);
- glVertex2i(x2, y2);
- glVertex2i(x2, y1);
-
- glEnd();
-}
-
-
/* ******************************************** */
void setlinestyle(int nr)
@@ -204,122 +82,6 @@ void set_inverted_drawing(int enable)
GL_TOGGLE(GL_DITHER, !enable);
}
-/* UNUSED */
-#if 0
-void sdrawXORline(int x0, int y0, int x1, int y1)
-{
- if (x0 == x1 && y0 == y1) return;
-
- set_inverted_drawing(1);
-
- glBegin(GL_LINES);
- glVertex2i(x0, y0);
- glVertex2i(x1, y1);
- glEnd();
-
- set_inverted_drawing(0);
-}
-
-void sdrawXORline4(int nr, int x0, int y0, int x1, int y1)
-{
- static int old[4][2][2];
- static char flags[4] = {0, 0, 0, 0};
-
- /* with builtin memory, max 4 lines */
-
- set_inverted_drawing(1);
-
- glBegin(GL_LINES);
- if (nr == -1) { /* flush */
- for (nr = 0; nr < 4; nr++) {
- if (flags[nr]) {
- glVertex2iv(old[nr][0]);
- glVertex2iv(old[nr][1]);
- flags[nr] = 0;
- }
- }
- }
- else {
- if (nr >= 0 && nr < 4) {
- if (flags[nr]) {
- glVertex2iv(old[nr][0]);
- glVertex2iv(old[nr][1]);
- }
-
- old[nr][0][0] = x0;
- old[nr][0][1] = y0;
- old[nr][1][0] = x1;
- old[nr][1][1] = y1;
-
- flags[nr] = 1;
- }
-
- glVertex2i(x0, y0);
- glVertex2i(x1, y1);
- }
- glEnd();
-
- set_inverted_drawing(0);
-}
-
-void fdrawXORellipse(float xofs, float yofs, float hw, float hh)
-{
- if (hw == 0) return;
-
- set_inverted_drawing(1);
-
- glPushMatrix();
- glTranslatef(xofs, yofs, 0.0f);
- glScalef(1.0f, hh / hw, 1.0f);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, hw, 20);
- glPopMatrix();
-
- set_inverted_drawing(0);
-}
-
-#endif
-
-void fdrawXORcirc(float xofs, float yofs, float rad)
-{
- set_inverted_drawing(1);
-
- glPushMatrix();
- glTranslatef(xofs, yofs, 0.0);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, rad, 20);
- glPopMatrix();
-
- set_inverted_drawing(0);
-}
-
-void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments)
-{
- int i;
-
- glBegin(GL_TRIANGLE_FAN);
- glVertex2f(0.0, 0.0);
- for (i = 0; i < nsegments; i++) {
- float t = (float) i / (nsegments - 1);
- float cur = start + t * angle;
-
- glVertex2f(cosf(cur) * radius, sinf(cur) * radius);
- }
- glEnd();
-}
-
-void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments)
-{
- int i;
-
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < nsegments; i++) {
- float t = (float) i / (nsegments - 1);
- float cur = start + t * angle;
-
- glVertex2f(cosf(cur) * radius, sinf(cur) * radius);
- }
- glEnd();
-}
-
float glaGetOneFloat(int param)
{
GLfloat v;
@@ -375,24 +137,66 @@ static int get_cached_work_texture(int *r_w, int *r_h)
return texid;
}
-void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
+static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state)
+{
+ Gwn_VertFormat *vert_format = immVertexFormat();
+ state->pos = GWN_vertformat_attr_add(vert_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ state->texco = GWN_vertformat_attr_add(vert_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+}
+
+/* To be used before calling immDrawPixelsTex
+ * Default shader is GPU_SHADER_2D_IMAGE_COLOR
+ * You can still set uniforms with :
+ * GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0);
+ * */
+IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
+{
+ IMMDrawPixelsTexState state;
+ immDrawPixelsTexSetupAttributes(&state);
+
+ state.shader = GPU_shader_get_builtin_shader(builtin);
+
+ /* Shader will be unbind by immUnbindProgram in immDrawPixelsTexScaled_clipping */
+ immBindBuiltinProgram(builtin);
+ immUniform1i("image", 0);
+ state.do_shader_unbind = true;
+
+ return state;
+}
+
+/* Use the currently bound shader.
+ *
+ * Use immDrawPixelsTexSetup to bind the shader you
+ * want before calling immDrawPixelsTex.
+ *
+ * If using a special shader double check it uses the same
+ * attributes "pos" "texCoord" and uniform "image".
+ *
+ * If color is NULL then use white by default
+ *
+ * Be also aware that this function unbinds the shader when
+ * it's finished.
+ * */
+void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
+ 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 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;
- float xzoom = glaGetOneFloat(GL_ZOOM_X), yzoom = glaGetOneFloat(GL_ZOOM_Y);
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));
+ float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ GLint unpack_row_length;
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpack_row_length);
- /* 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);
@@ -401,18 +205,12 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);
-#if defined(__APPLE__) && 0
- /* [merwin] disable this workaround and see if anyone is affected. If not scrap it! Also at end of this function */
- /* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */
- glPixelZoom(1.0f, 1.0f);
-#endif
-
/* setup seamless 2=on, 0=off */
seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0;
-
+
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);
@@ -420,7 +218,7 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
components = 4;
else if (format == GL_RGB)
components = 3;
- else if (ELEM(format, GL_LUMINANCE, GL_ALPHA))
+ else if (format == GL_RED)
components = 1;
else {
BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled");
@@ -436,6 +234,7 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
* 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 {
@@ -443,6 +242,16 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL);
}
+ unsigned int pos = state->pos, texco = state->texco;
+
+ /* optional */
+ /* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since
+ * it does not need color.
+ */
+ if (state->shader != NULL && GPU_shader_get_uniform(state->shader, "color") != -1) {
+ immUniformColor4fv((color) ? color : white);
+ }
+
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;
@@ -474,7 +283,7 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
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]);
@@ -485,7 +294,7 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
}
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)
@@ -494,158 +303,55 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_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]);
}
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
- glBegin(GL_QUADS);
- glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
- glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);
+ immBegin(GWN_PRIM_TRI_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);
- glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h);
- glVertex2f(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)(0 + offset_bot) / tex_h);
+ immVertex2f(pos, rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom);
- glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h);
- glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
+ 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);
- glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h);
- glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
- glEnd();
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ 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();
}
}
+ if (state->do_shader_unbind) {
+ immUnbindProgram();
+ }
+
glBindTexture(GL_TEXTURE_2D, 0);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-
-#if defined(__APPLE__) && 0
- /* workaround for os x 10.5/10.6 driver bug (above) */
- glPixelZoom(xzoom, yzoom);
-#endif
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_row_length);
}
-void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h,
+void immDrawPixelsTexScaled(IMMDrawPixelsTexState *state,
+ float x, float y, int img_w, int img_h,
int format, int type, int zoomfilter, void *rect,
- float scaleX, float scaleY)
+ float scaleX, float scaleY, float xzoom, float yzoom, float color[4])
{
- glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect,
- scaleX, scaleY, 0.0f, 0.0f, 0.0f, 0.0f);
+ immDrawPixelsTexScaled_clipping(state, x, y, img_w, img_h, format, type, zoomfilter, rect,
+ scaleX, scaleY, 0.0f, 0.0f, 0.0f, 0.0f, xzoom, yzoom, color);
}
-void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
+void immDrawPixelsTex(IMMDrawPixelsTexState *state,
+ 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])
{
- glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f,
- 0.0f, 0.0f, 0.0f, 0.0f);
+ immDrawPixelsTexScaled_clipping(state, 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 glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h,
+void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state,
+ 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)
-{
- glaDrawPixelsTexScaled_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);
-}
-
-void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect)
-{
- float xzoom = glaGetOneFloat(GL_ZOOM_X);
- float yzoom = glaGetOneFloat(GL_ZOOM_Y);
-
- /* The pixel space coordinate of the intersection of
- * the [zoomed] image with the origin.
- */
- float ix = -x / xzoom;
- float iy = -y / yzoom;
-
- /* The maximum pixel amounts the image can be cropped
- * at the lower left without exceeding the origin.
- */
- int off_x = floor(max_ff(ix, 0.0f));
- int off_y = floor(max_ff(iy, 0.0f));
-
- /* The zoomed space coordinate of the raster position
- * (starting at the lower left most unclipped pixel).
- */
- float rast_x = x + off_x * xzoom;
- float rast_y = y + off_y * yzoom;
-
- GLfloat viewport[4];
- int draw_w, draw_h;
-
- /* Determine the smallest number of pixels we need to draw
- * before the image would go off the upper right corner.
- *
- * It may seem this is just an optimization but some graphics
- * cards (ATI) freak out if there is a large zoom factor and
- * a large number of pixels off the screen (probably at some
- * level the number of image pixels to draw is getting multiplied
- * by the zoom and then clamped). Making sure we draw the
- * fewest pixels possible keeps everyone mostly happy (still
- * fails if we zoom in on one really huge pixel so that it
- * covers the entire screen).
- */
- glGetFloatv(GL_VIEWPORT, viewport);
- draw_w = min_ii(img_w - off_x, ceil((viewport[2] - rast_x) / xzoom));
- draw_h = min_ii(img_h - off_y, ceil((viewport[3] - rast_y) / yzoom));
-
- if (draw_w > 0 && draw_h > 0) {
-
- int bound_options;
- GPU_BASIC_SHADER_DISABLE_AND_STORE(bound_options);
-
- /* Don't use safe RasterPos (slower) if we can avoid it. */
- if (rast_x >= 0 && rast_y >= 0) {
- glRasterPos2f(rast_x, rast_y);
- }
- else {
- glaRasterPosSafe2f(rast_x, rast_y, 0, 0);
- }
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, row_w);
- if (format == GL_LUMINANCE || format == GL_RED) {
- if (type == GL_FLOAT) {
- const float *f_rect = (float *)rect;
- glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x));
- }
- else if (type == GL_INT || type == GL_UNSIGNED_INT) {
- const int *i_rect = (int *)rect;
- glDrawPixels(draw_w, draw_h, format, type, i_rect + (off_y * row_w + off_x));
- }
- }
- else { /* RGBA */
- if (type == GL_FLOAT) {
- const float *f_rect = (float *)rect;
- glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x) * 4);
- }
- else if (type == GL_UNSIGNED_BYTE) {
- unsigned char *uc_rect = (unsigned char *) rect;
- glDrawPixels(draw_w, draw_h, format, type, uc_rect + (off_y * row_w + off_x) * 4);
- }
- }
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-
- GPU_BASIC_SHADER_ENABLE_AND_RESTORE(bound_options);
- }
-}
-
-/* uses either DrawPixelsSafe or DrawPixelsTex, based on user defined maximum */
-void glaDrawPixelsAuto_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 clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y,
+ float xzoom, float yzoom, float color[4])
{
- if (U.image_draw_method != IMAGE_DRAW_METHOD_DRAWPIXELS) {
- glColor4f(1.0, 1.0, 1.0, 1.0);
- glaDrawPixelsTex_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y);
- }
- else {
- glaDrawPixelsSafe(x, y, img_w, img_h, img_w, format, type, rect);
- }
-}
-
-void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
-{
- glaDrawPixelsAuto_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect,
- 0.0f, 0.0f, 0.0f, 0.0f);
+ immDrawPixelsTexScaled_clipping(state, 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 */
@@ -664,15 +370,12 @@ void glaDefine2DArea(rcti *screen_rect)
* Programming Guide, Appendix H, Correctness Tips.
*/
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0.0, sc_w, 0.0, sc_h, -1, 1);
- glTranslatef(GLA_PIXEL_OFS, GLA_PIXEL_OFS, 0.0);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
+ gpuOrtho2D(GLA_PIXEL_OFS, sc_w + GLA_PIXEL_OFS, GLA_PIXEL_OFS, sc_h + GLA_PIXEL_OFS);
+ gpuLoadIdentity();
}
+/* TODO(merwin): put the following 2D code to use, or build new 2D code inspired & informd by it */
+
#if 0 /* UNUSED */
struct gla2DDrawInfo {
@@ -726,8 +429,8 @@ gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect)
glGetIntegerv(GL_VIEWPORT, (GLint *)di->orig_vp);
glGetIntegerv(GL_SCISSOR_BOX, (GLint *)di->orig_sc);
- glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)di->orig_projmat);
- glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)di->orig_viewmat);
+ gpuGetProjectionMatrix(di->orig_projmat);
+ gpuGetModelViewMatrix(di->orig_viewmat);
di->screen_rect = *screen_rect;
if (world_rect) {
@@ -778,42 +481,14 @@ void glaEnd2DDraw(gla2DDrawInfo *di)
{
glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
glScissor(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(di->orig_projmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(di->orig_viewmat);
+ gpuLoadProjectionMatrix(di->orig_projmat);
+ gpuLoadMatrix(di->orig_viewmat);
MEM_freeN(di);
}
-#endif
+#endif /* UNUSED */
-/* Uses current OpenGL state to get view matrices for gluProject/gluUnProject */
-void bgl_get_mats(bglMats *mats)
-{
- const double badvalue = 1.0e-6;
-
- glGetDoublev(GL_MODELVIEW_MATRIX, mats->modelview);
- glGetDoublev(GL_PROJECTION_MATRIX, mats->projection);
- glGetIntegerv(GL_VIEWPORT, (GLint *)mats->viewport);
-
- /* Very strange code here - it seems that certain bad values in the
- * modelview matrix can cause gluUnProject to give bad results. */
- if (mats->modelview[0] < badvalue &&
- mats->modelview[0] > -badvalue)
- {
- mats->modelview[0] = 0;
- }
- if (mats->modelview[5] < badvalue &&
- mats->modelview[5] > -badvalue)
- {
- mats->modelview[5] = 0;
- }
-
- /* Set up viewport so that gluUnProject will give correct values */
- mats->viewport[0] = 0;
- mats->viewport[1] = 0;
-}
/* *************** glPolygonOffset hack ************* */
@@ -831,8 +506,7 @@ void bglPolygonOffset(float viewdist, float dist)
// glPolygonOffset(-1.0, -1.0);
/* hack below is to mimic polygon offset */
- glMatrixMode(GL_PROJECTION);
- glGetFloatv(GL_PROJECTION_MATRIX, (float *)winmat);
+ gpuGetProjectionMatrix(winmat);
/* dist is from camera to center point */
@@ -863,17 +537,13 @@ void bglPolygonOffset(float viewdist, float dist)
winmat[14] -= offs;
offset += offs;
-
- glLoadMatrixf(winmat);
- glMatrixMode(GL_MODELVIEW);
}
else {
- glMatrixMode(GL_PROJECTION);
winmat[14] += offset;
offset = 0.0;
- glLoadMatrixf(winmat);
- glMatrixMode(GL_MODELVIEW);
}
+
+ gpuLoadProjectionMatrix(winmat);
}
/* **** Color management helper functions for GLSL display/transform ***** */
@@ -883,7 +553,8 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
ColorManagedViewSettings *view_settings,
ColorManagedDisplaySettings *display_settings,
float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y)
+ float clip_max_x, float clip_max_y,
+ float zoom_x, float zoom_y)
{
bool force_fallback = false;
bool need_fallback = true;
@@ -902,6 +573,11 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
if (force_fallback == false) {
int ok;
+ IMMDrawPixelsTexState state = {0};
+ /* We want GLSL state to be fully handled by OCIO. */
+ state.do_shader_unbind = false;
+ immDrawPixelsTexSetupAttributes(&state);
+
if (ibuf->rect_float) {
if (ibuf->float_colorspace) {
ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings,
@@ -920,8 +596,6 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
}
if (ok) {
- glColor4f(1.0, 1.0, 1.0, 1.0);
-
if (ibuf->rect_float) {
int format = 0;
@@ -933,16 +607,20 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
BLI_assert(!"Incompatible number of channels for GLSL display");
if (format != 0) {
- glaDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, format, GL_FLOAT,
+ immDrawPixelsTex_clipping(&state,
+ x, y, ibuf->x, ibuf->y, format, GL_FLOAT,
zoomfilter, ibuf->rect_float,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y);
+ clip_min_x, clip_min_y, clip_max_x, clip_max_y,
+ zoom_x, zoom_y, NULL);
}
}
else if (ibuf->rect) {
/* ibuf->rect is always RGBA */
- glaDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
+ immDrawPixelsTex_clipping(&state,
+ x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
zoomfilter, ibuf->rect,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y);
+ clip_min_x, clip_min_y, clip_max_x, clip_max_y,
+ zoom_x, zoom_y, NULL);
}
IMB_colormanagement_finish_glsl_draw();
@@ -959,9 +637,12 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
if (display_buffer) {
- glaDrawPixelsAuto_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
- zoomfilter, display_buffer,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y);
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex_clipping(&state,
+ x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
+ zoomfilter, display_buffer,
+ clip_min_x, clip_min_y, clip_max_x, clip_max_y,
+ zoom_x, zoom_y, NULL);
}
IMB_display_buffer_release(cache_handle);
@@ -970,10 +651,11 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
ColorManagedViewSettings *view_settings,
- ColorManagedDisplaySettings *display_settings)
+ ColorManagedDisplaySettings *display_settings,
+ float zoom_x, float zoom_y)
{
glaDrawImBuf_glsl_clipping(ibuf, x, y, zoomfilter, view_settings, display_settings,
- 0.0f, 0.0f, 0.0f, 0.0f);
+ 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y);
}
void glaDrawImBuf_glsl_ctx_clipping(const bContext *C,
@@ -981,7 +663,8 @@ void glaDrawImBuf_glsl_ctx_clipping(const bContext *C,
float x, float y,
int zoomfilter,
float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y)
+ float clip_max_x, float clip_max_y,
+ float zoom_x, float zoom_y)
{
ColorManagedViewSettings *view_settings;
ColorManagedDisplaySettings *display_settings;
@@ -989,22 +672,19 @@ void glaDrawImBuf_glsl_ctx_clipping(const bContext *C,
IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
glaDrawImBuf_glsl_clipping(ibuf, x, y, zoomfilter, view_settings, display_settings,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y);
-}
-
-void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter)
-{
- glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, zoomfilter, 0.0f, 0.0f, 0.0f, 0.0f);
+ clip_min_x, clip_min_y, clip_max_x, clip_max_y,
+ zoom_x, zoom_y);
}
-void cpack(unsigned int x)
+void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter,
+ float zoom_x, float zoom_y)
{
- glColor3ub(( (x) & 0xFF),
- (((x) >> 8) & 0xFF),
- (((x) >> 16) & 0xFF));
+ glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, zoomfilter, 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y);
}
-void glaDrawBorderCorners(const rcti *border, float zoomx, float zoomy)
+/* don't move to GPU_immediate_util.h because this uses user-prefs
+ * and isn't very low level */
+void immDrawBorderCorners(unsigned int pos, const rcti *border, float zoomx, float zoomy)
{
float delta_x = 4.0f * UI_DPI_FAC / zoomx;
float delta_y = 4.0f * UI_DPI_FAC / zoomy;
@@ -1013,30 +693,30 @@ void glaDrawBorderCorners(const rcti *border, float zoomx, float zoomy)
delta_y = min_ff(delta_y, border->ymax - border->ymin);
/* left bottom corner */
- glBegin(GL_LINE_STRIP);
- glVertex2f(border->xmin, border->ymin + delta_y);
- glVertex2f(border->xmin, border->ymin);
- glVertex2f(border->xmin + delta_x, border->ymin);
- glEnd();
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmin, border->ymin + delta_y);
+ immVertex2f(pos, border->xmin, border->ymin);
+ immVertex2f(pos, border->xmin + delta_x, border->ymin);
+ immEnd();
/* left top corner */
- glBegin(GL_LINE_STRIP);
- glVertex2f(border->xmin, border->ymax - delta_y);
- glVertex2f(border->xmin, border->ymax);
- glVertex2f(border->xmin + delta_x, border->ymax);
- glEnd();
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmin, border->ymax - delta_y);
+ immVertex2f(pos, border->xmin, border->ymax);
+ immVertex2f(pos, border->xmin + delta_x, border->ymax);
+ immEnd();
/* right bottom corner */
- glBegin(GL_LINE_STRIP);
- glVertex2f(border->xmax - delta_x, border->ymin);
- glVertex2f(border->xmax, border->ymin);
- glVertex2f(border->xmax, border->ymin + delta_y);
- glEnd();
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmax - delta_x, border->ymin);
+ immVertex2f(pos, border->xmax, border->ymin);
+ immVertex2f(pos, border->xmax, border->ymin + delta_y);
+ immEnd();
/* right top corner */
- glBegin(GL_LINE_STRIP);
- glVertex2f(border->xmax - delta_x, border->ymax);
- glVertex2f(border->xmax, border->ymax);
- glVertex2f(border->xmax, border->ymax - delta_y);
- glEnd();
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmax - delta_x, border->ymax);
+ immVertex2f(pos, border->xmax, border->ymax);
+ immVertex2f(pos, border->xmax, border->ymax - delta_y);
+ immEnd();
}
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 1190423e2f1..4c62253bef6 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -38,6 +38,7 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_utildefines.h"
@@ -47,8 +48,10 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_gpencil.h"
+#include "BKE_layer.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
+#include "BKE_workspace.h"
#include "RNA_access.h"
@@ -61,20 +64,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", "view_layer", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
"selected_objects", "selected_bases",
"editable_objects", "editable_bases",
"selected_editable_objects", "selected_editable_bases",
@@ -93,20 +84,14 @@ const char *screen_context_dir[] = {
int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result)
{
+ wmWindow *win = CTX_wm_window(C);
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
+ Scene *scene = WM_window_get_active_scene(win);
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ ViewLayer *view_layer = BKE_view_layer_from_workspace_get(scene, workspace);
Object *obedit = scene->obedit;
- Object *obact = OBACT;
- base = BASACT;
-#endif
+ Object *obact = (view_layer && view_layer->basact) ? view_layer->basact->object : NULL;
if (CTX_data_dir(member)) {
CTX_data_dir_set(result, screen_context_dir);
@@ -116,84 +101,100 @@ 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")) {
+ FOREACH_VISIBLE_OBJECT(view_layer, 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 = view_layer->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")) {
+ FOREACH_SELECTED_OBJECT(view_layer, 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")) {
+ FOREACH_SELECTED_OBJECT(view_layer, 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 */
+ FOREACH_VISIBLE_OBJECT(view_layer, 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")) {
+ FOREACH_VISIBLE_BASE(view_layer, 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 = view_layer->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 = view_layer->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 = view_layer->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 = view_layer->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);
}
}
}
@@ -345,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 (view_layer->basact)
+ CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact);
return 1;
}
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
new file mode 100644
index 00000000000..5690076fedb
--- /dev/null
+++ b/source/blender/editors/screen/screen_draw.c
@@ -0,0 +1,496 @@
+/*
+ * ***** 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/screen/screen_draw.c
+ * \ingroup edscr
+ */
+
+#include "ED_screen.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "screen_intern.h"
+
+
+/**
+ * Draw horizontal shape visualizing future joining (left as well right direction of future joining).
+ */
+static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos)
+{
+ vec2f points[10];
+ short i;
+ float w, h;
+ float width = sa->v3->vec.x - sa->v1->vec.x;
+ float height = sa->v3->vec.y - sa->v1->vec.y;
+
+ if (height < width) {
+ h = height / 8;
+ w = height / 4;
+ }
+ else {
+ h = width / 8;
+ w = width / 4;
+ }
+
+ points[0].x = sa->v1->vec.x;
+ points[0].y = sa->v1->vec.y + height / 2;
+
+ points[1].x = sa->v1->vec.x;
+ points[1].y = sa->v1->vec.y;
+
+ points[2].x = sa->v4->vec.x - w;
+ points[2].y = sa->v4->vec.y;
+
+ points[3].x = sa->v4->vec.x - w;
+ points[3].y = sa->v4->vec.y + height / 2 - 2 * h;
+
+ points[4].x = sa->v4->vec.x - 2 * w;
+ points[4].y = sa->v4->vec.y + height / 2;
+
+ points[5].x = sa->v4->vec.x - w;
+ points[5].y = sa->v4->vec.y + height / 2 + 2 * h;
+
+ points[6].x = sa->v3->vec.x - w;
+ points[6].y = sa->v3->vec.y;
+
+ points[7].x = sa->v2->vec.x;
+ points[7].y = sa->v2->vec.y;
+
+ points[8].x = sa->v4->vec.x;
+ points[8].y = sa->v4->vec.y + height / 2 - h;
+
+ points[9].x = sa->v4->vec.x;
+ points[9].y = sa->v4->vec.y + height / 2 + h;
+
+ if (dir == 'l') {
+ /* when direction is left, then we flip direction of arrow */
+ float cx = sa->v1->vec.x + width;
+ for (i = 0; i < 10; i++) {
+ points[i].x -= cx;
+ points[i].x = -points[i].x;
+ points[i].x += sa->v1->vec.x;
+ }
+ }
+
+ immBegin(GWN_PRIM_TRI_FAN, 5);
+
+ for (i = 0; i < 5; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
+
+ immEnd();
+
+ immBegin(GWN_PRIM_TRI_FAN, 5);
+
+ for (i = 4; i < 8; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
+
+ immVertex2f(pos, points[0].x, points[0].y);
+ immEnd();
+
+ immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
+ immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
+}
+
+/**
+ * Draw vertical shape visualizing future joining (up/down direction).
+ */
+static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos)
+{
+ vec2f points[10];
+ short i;
+ float w, h;
+ float width = sa->v3->vec.x - sa->v1->vec.x;
+ float height = sa->v3->vec.y - sa->v1->vec.y;
+
+ if (height < width) {
+ h = height / 4;
+ w = height / 8;
+ }
+ else {
+ h = width / 4;
+ w = width / 8;
+ }
+
+ points[0].x = sa->v1->vec.x + width / 2;
+ points[0].y = sa->v3->vec.y;
+
+ points[1].x = sa->v2->vec.x;
+ points[1].y = sa->v2->vec.y;
+
+ points[2].x = sa->v1->vec.x;
+ points[2].y = sa->v1->vec.y + h;
+
+ points[3].x = sa->v1->vec.x + width / 2 - 2 * w;
+ points[3].y = sa->v1->vec.y + h;
+
+ points[4].x = sa->v1->vec.x + width / 2;
+ points[4].y = sa->v1->vec.y + 2 * h;
+
+ points[5].x = sa->v1->vec.x + width / 2 + 2 * w;
+ points[5].y = sa->v1->vec.y + h;
+
+ points[6].x = sa->v4->vec.x;
+ points[6].y = sa->v4->vec.y + h;
+
+ points[7].x = sa->v3->vec.x;
+ points[7].y = sa->v3->vec.y;
+
+ points[8].x = sa->v1->vec.x + width / 2 - w;
+ points[8].y = sa->v1->vec.y;
+
+ points[9].x = sa->v1->vec.x + width / 2 + w;
+ points[9].y = sa->v1->vec.y;
+
+ if (dir == 'u') {
+ /* when direction is up, then we flip direction of arrow */
+ float cy = sa->v1->vec.y + height;
+ for (i = 0; i < 10; i++) {
+ points[i].y -= cy;
+ points[i].y = -points[i].y;
+ points[i].y += sa->v1->vec.y;
+ }
+ }
+
+ immBegin(GWN_PRIM_TRI_FAN, 5);
+
+ for (i = 0; i < 5; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
+
+ immEnd();
+
+ immBegin(GWN_PRIM_TRI_FAN, 5);
+
+ for (i = 4; i < 8; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
+
+ immVertex2f(pos, points[0].x, points[0].y);
+ immEnd();
+
+ immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
+ immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
+}
+
+/**
+ * Draw join shape due to direction of joining.
+ */
+static void draw_join_shape(ScrArea *sa, char dir, unsigned int pos)
+{
+ if (dir == 'u' || dir == 'd') {
+ draw_vertical_join_shape(sa, dir, pos);
+ }
+ else {
+ draw_horizontal_join_shape(sa, dir, pos);
+ }
+}
+
+/**
+ * Draw screen area darker with arrow (visualization of future joining).
+ */
+static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int pos)
+{
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ immUniformColor4ub(0, 0, 0, 50);
+
+ draw_join_shape(sa, dir, pos);
+}
+
+/**
+ * Draw screen area ligher with arrow shape ("eraser" of previous dark shape).
+ */
+static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir), unsigned int pos)
+{
+ glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
+ /* value 181 was hardly computed: 181~105 */
+ immUniformColor4ub(255, 255, 255, 50);
+ /* draw_join_shape(sa, dir); */
+
+ immRectf(pos, sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y);
+}
+
+static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, short x2, short y2, unsigned int pos)
+{
+ int count = 0;
+
+ if (x2 < sizex - 1) count += 2;
+ if (x1 > 0) count += 2;
+ if (y2 < sizey - 1) count += 2;
+ if (y1 > 0) count += 2;
+
+ if (count == 0) {
+ return;
+ }
+
+ immBegin(GWN_PRIM_LINES, count);
+
+ /* right border area */
+ if (x2 < sizex - 1) {
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2, y2);
+ }
+
+ /* left border area */
+ if (x1 > 0) { /* otherwise it draws the emboss of window over */
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y2);
+ }
+
+ /* top border area */
+ if (y2 < sizey - 1) {
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y2);
+ }
+
+ /* bottom border area */
+ if (y1 > 0) {
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y1);
+ }
+
+ immEnd();
+}
+
+/**
+ * \brief Screen edges drawing.
+ */
+static void drawscredge_area(ScrArea *sa, int sizex, int sizey, unsigned int pos)
+{
+ short x1 = sa->v1->vec.x;
+ short y1 = sa->v1->vec.y;
+ short x2 = sa->v3->vec.x;
+ short y2 = sa->v3->vec.y;
+
+ drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, pos);
+}
+
+/**
+ * Only for edge lines between areas, and the blended join arrows.
+ */
+void ED_screen_draw(wmWindow *win)
+{
+ bScreen *screen = WM_window_get_active_screen(win);
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
+
+ ScrArea *sa;
+ ScrArea *sa1 = NULL;
+ ScrArea *sa2 = NULL;
+ ScrArea *sa3 = NULL;
+
+ wmSubWindowSet(win, screen->mainwin);
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* Note: first loop only draws if U.pixelsize > 1, skip otherwise */
+ if (U.pixelsize > 1.0f) {
+ /* FIXME: doesn't our glLineWidth already scale by U.pixelsize? */
+ glLineWidth((2.0f * U.pixelsize) - 1);
+ immUniformColor3ub(0x50, 0x50, 0x50);
+
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ drawscredge_area(sa, winsize_x, winsize_y, pos);
+ }
+ }
+
+ glLineWidth(1);
+ immUniformColor3ub(0, 0, 0);
+
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ drawscredge_area(sa, winsize_x, winsize_y, pos);
+
+ /* gather area split/join info */
+ if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa;
+ if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa;
+ if (sa->flag & (AREA_FLAG_DRAWSPLIT_H | AREA_FLAG_DRAWSPLIT_V)) sa3 = sa;
+ }
+
+ /* blended join arrow */
+ if (sa1 && sa2) {
+ int dir = area_getorientation(sa1, sa2);
+ int dira = -1;
+ if (dir != -1) {
+ switch (dir) {
+ case 0: /* W */
+ dir = 'r';
+ dira = 'l';
+ break;
+ case 1: /* N */
+ dir = 'd';
+ dira = 'u';
+ break;
+ case 2: /* E */
+ dir = 'l';
+ dira = 'r';
+ break;
+ case 3: /* S */
+ dir = 'u';
+ dira = 'd';
+ break;
+ }
+ }
+
+ glEnable(GL_BLEND);
+
+ scrarea_draw_shape_dark(sa2, dir, pos);
+ scrarea_draw_shape_light(sa1, dira, pos);
+
+ glDisable(GL_BLEND);
+ }
+
+ /* splitpoint */
+ if (sa3) {
+ glEnable(GL_BLEND);
+ immUniformColor4ub(255, 255, 255, 100);
+
+ immBegin(GWN_PRIM_LINES, 2);
+
+ if (sa3->flag & AREA_FLAG_DRAWSPLIT_H) {
+ immVertex2f(pos, sa3->totrct.xmin, win->eventstate->y);
+ immVertex2f(pos, sa3->totrct.xmax, win->eventstate->y);
+
+ immEnd();
+
+ immUniformColor4ub(0, 0, 0, 100);
+
+ immBegin(GWN_PRIM_LINES, 2);
+
+ immVertex2f(pos, sa3->totrct.xmin, win->eventstate->y + 1);
+ immVertex2f(pos, sa3->totrct.xmax, win->eventstate->y + 1);
+ }
+ else {
+ immVertex2f(pos, win->eventstate->x, sa3->totrct.ymin);
+ immVertex2f(pos, win->eventstate->x, sa3->totrct.ymax);
+
+ immEnd();
+
+ immUniformColor4ub(0, 0, 0, 100);
+
+ immBegin(GWN_PRIM_LINES, 2);
+
+ immVertex2f(pos, win->eventstate->x + 1, sa3->totrct.ymin);
+ immVertex2f(pos, win->eventstate->x + 1, sa3->totrct.ymax);
+ }
+
+ immEnd();
+
+ glDisable(GL_BLEND);
+ }
+
+ immUnbindProgram();
+
+ screen->do_draw = false;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Screen Thumbnail Preview */
+
+/**
+ * Calculates a scale factor to squash the preview for \a screen into a rectangle of given size and aspect.
+ */
+static void screen_preview_scale_get(
+ const bScreen *screen, float size_x, float size_y,
+ const float asp[2],
+ float r_scale[2])
+{
+ float max_x = 0, max_y = 0;
+
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ max_x = MAX2(max_x, sa->totrct.xmax);
+ max_y = MAX2(max_y, sa->totrct.ymax);
+ }
+ r_scale[0] = (size_x * asp[0]) / max_x;
+ r_scale[1] = (size_y * asp[1]) / max_y;
+}
+
+static void screen_preview_draw_areas(const bScreen *screen, const float scale[2], const float col[4],
+ const float ofs_between_areas)
+{
+ const float ofs_h = ofs_between_areas * 0.5f;
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(col);
+
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ rctf rect = {
+ .xmin = sa->totrct.xmin * scale[0] + ofs_h,
+ .xmax = sa->totrct.xmax * scale[0] - ofs_h,
+ .ymin = sa->totrct.ymin * scale[1] + ofs_h,
+ .ymax = sa->totrct.ymax * scale[1] - ofs_h
+ };
+
+ immBegin(GWN_PRIM_TRI_FAN, 4);
+ immVertex2f(pos, rect.xmin, rect.ymin);
+ immVertex2f(pos, rect.xmax, rect.ymin);
+ immVertex2f(pos, rect.xmax, rect.ymax);
+ immVertex2f(pos, rect.xmin, rect.ymax);
+ immEnd();
+ }
+
+ immUnbindProgram();
+}
+
+static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
+{
+ const float asp[2] = {1.0f, 0.8f}; /* square previews look a bit ugly */
+ /* could use theme color (tui.wcol_menu_item.text), but then we'd need to regenerate all previews when changing */
+ const float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ float scale[2];
+
+ wmOrtho2(0.0f, size_x, 0.0f, size_y);
+ /* center */
+ gpuPushMatrix();
+ gpuTranslate2f(size_x * (1.0f - asp[0]) * 0.5f, size_y * (1.0f - asp[1]) * 0.5f);
+
+ screen_preview_scale_get(screen, size_x, size_y, asp, scale);
+ screen_preview_draw_areas(screen, scale, col, 1.5f);
+
+ gpuPopMatrix();
+}
+
+/**
+ * Render the preview for a screen layout in \a screen.
+ */
+void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, unsigned int *r_rect)
+{
+ char err_out[256] = "unknown";
+ GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, 0, err_out);
+
+ GPU_offscreen_bind(offscreen, true);
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ screen_preview_draw(screen, size_x, size_y);
+
+ GPU_offscreen_read_pixels(offscreen, GL_UNSIGNED_BYTE, r_rect);
+ GPU_offscreen_unbind(offscreen, true);
+
+ GPU_offscreen_free(offscreen);
+}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 8f1132dc1e5..d3f99dc8152 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -34,6 +34,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_scene_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_userdef_types.h"
#include "BLI_math.h"
@@ -41,18 +42,17 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_screen.h"
#include "BKE_scene.h"
-
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "BKE_workspace.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -66,6 +66,8 @@
#include "UI_interface.h"
+#include "WM_message.h"
+
/* XXX actually should be not here... solve later */
#include "wm_subwindow.h"
@@ -266,7 +268,7 @@ bool scredge_is_horizontal(ScrEdge *se)
}
/* need win size to make sure not to include edges along screen edge */
-ScrEdge *screen_find_active_scredge(bScreen *sc,
+ScrEdge *screen_find_active_scredge(const bScreen *sc,
const int winsize_x, const int winsize_y,
const int mx, const int my)
{
@@ -457,21 +459,17 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
return newa;
}
-/* empty screen, with 1 dummy area without spacedata */
-/* uses window size */
-bScreen *ED_screen_add(wmWindow *win, Scene *scene, const char *name)
+/**
+ * Empty screen, with 1 dummy area without spacedata. Uses window size.
+ */
+bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y)
{
- const int winsize_x = WM_window_pixels_x(win);
- const int winsize_y = WM_window_pixels_y(win);
-
bScreen *sc;
ScrVert *sv1, *sv2, *sv3, *sv4;
sc = BKE_libblock_alloc(G.main, ID_SCR, name, 0);
- sc->scene = scene;
sc->do_refresh = true;
sc->redraws_flag = TIME_ALL_3D_WIN | TIME_ALL_ANIM_WIN;
- sc->winid = win->winid;
sv1 = screen_addvert(sc, 0, 0);
sv2 = screen_addvert(sc, 0, winsize_y - 1);
@@ -489,7 +487,7 @@ bScreen *ED_screen_add(wmWindow *win, Scene *scene, const char *name)
return sc;
}
-static void screen_copy(bScreen *to, bScreen *from)
+void screen_data_copy(bScreen *to, bScreen *from)
{
ScrVert *s1, *s2;
ScrEdge *se;
@@ -532,7 +530,16 @@ static void screen_copy(bScreen *to, bScreen *from)
/* put at zero (needed?) */
for (s1 = from->vertbase.first; s1; s1 = s1->next)
s1->newv = NULL;
+}
+/**
+ * Prepare a newly created screen for initializing it as active screen.
+ */
+void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new)
+{
+ screen_new->winid = win->winid;
+ screen_new->do_refresh = true;
+ screen_new->do_draw = true;
}
@@ -615,7 +622,9 @@ int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2)
screen_delarea(C, scr, sa2);
removedouble_scrverts(scr);
sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
-
+ /* Update preview thumbnail */
+ BKE_icon_changed(scr->id.icon_id);
+
return 1;
}
@@ -838,241 +847,23 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y)
}
-/* *********************** DRAWING **************************************** */
-
-/* draw vertical shape visualizing future joining (left as well
- * right direction of future joining) */
-static void draw_horizontal_join_shape(ScrArea *sa, char dir)
-{
- vec2f points[10];
- short i;
- float w, h;
- float width = sa->v3->vec.x - sa->v1->vec.x;
- float height = sa->v3->vec.y - sa->v1->vec.y;
-
- if (height < width) {
- h = height / 8;
- w = height / 4;
- }
- else {
- h = width / 8;
- w = width / 4;
- }
-
- points[0].x = sa->v1->vec.x;
- points[0].y = sa->v1->vec.y + height / 2;
-
- points[1].x = sa->v1->vec.x;
- points[1].y = sa->v1->vec.y;
-
- points[2].x = sa->v4->vec.x - w;
- points[2].y = sa->v4->vec.y;
-
- points[3].x = sa->v4->vec.x - w;
- points[3].y = sa->v4->vec.y + height / 2 - 2 * h;
-
- points[4].x = sa->v4->vec.x - 2 * w;
- points[4].y = sa->v4->vec.y + height / 2;
-
- points[5].x = sa->v4->vec.x - w;
- points[5].y = sa->v4->vec.y + height / 2 + 2 * h;
-
- points[6].x = sa->v3->vec.x - w;
- points[6].y = sa->v3->vec.y;
-
- points[7].x = sa->v2->vec.x;
- points[7].y = sa->v2->vec.y;
-
- points[8].x = sa->v4->vec.x;
- points[8].y = sa->v4->vec.y + height / 2 - h;
-
- points[9].x = sa->v4->vec.x;
- points[9].y = sa->v4->vec.y + height / 2 + h;
-
- if (dir == 'l') {
- /* when direction is left, then we flip direction of arrow */
- float cx = sa->v1->vec.x + width;
- for (i = 0; i < 10; i++) {
- points[i].x -= cx;
- points[i].x = -points[i].x;
- points[i].x += sa->v1->vec.x;
- }
- }
-
- glBegin(GL_POLYGON);
- for (i = 0; i < 5; i++)
- glVertex2f(points[i].x, points[i].y);
- glEnd();
- glBegin(GL_POLYGON);
- for (i = 4; i < 8; i++)
- glVertex2f(points[i].x, points[i].y);
- glVertex2f(points[0].x, points[0].y);
- glEnd();
-
- glRectf(points[2].x, points[2].y, points[8].x, points[8].y);
- glRectf(points[6].x, points[6].y, points[9].x, points[9].y);
-}
-
-/* draw vertical shape visualizing future joining (up/down direction) */
-static void draw_vertical_join_shape(ScrArea *sa, char dir)
-{
- vec2f points[10];
- short i;
- float w, h;
- float width = sa->v3->vec.x - sa->v1->vec.x;
- float height = sa->v3->vec.y - sa->v1->vec.y;
-
- if (height < width) {
- h = height / 4;
- w = height / 8;
- }
- else {
- h = width / 4;
- w = width / 8;
- }
-
- points[0].x = sa->v1->vec.x + width / 2;
- points[0].y = sa->v3->vec.y;
-
- points[1].x = sa->v2->vec.x;
- points[1].y = sa->v2->vec.y;
-
- points[2].x = sa->v1->vec.x;
- points[2].y = sa->v1->vec.y + h;
-
- points[3].x = sa->v1->vec.x + width / 2 - 2 * w;
- points[3].y = sa->v1->vec.y + h;
-
- points[4].x = sa->v1->vec.x + width / 2;
- points[4].y = sa->v1->vec.y + 2 * h;
-
- points[5].x = sa->v1->vec.x + width / 2 + 2 * w;
- points[5].y = sa->v1->vec.y + h;
-
- points[6].x = sa->v4->vec.x;
- points[6].y = sa->v4->vec.y + h;
-
- points[7].x = sa->v3->vec.x;
- points[7].y = sa->v3->vec.y;
-
- points[8].x = sa->v1->vec.x + width / 2 - w;
- points[8].y = sa->v1->vec.y;
-
- points[9].x = sa->v1->vec.x + width / 2 + w;
- points[9].y = sa->v1->vec.y;
-
- if (dir == 'u') {
- /* when direction is up, then we flip direction of arrow */
- float cy = sa->v1->vec.y + height;
- for (i = 0; i < 10; i++) {
- points[i].y -= cy;
- points[i].y = -points[i].y;
- points[i].y += sa->v1->vec.y;
- }
- }
-
- glBegin(GL_POLYGON);
- for (i = 0; i < 5; i++)
- glVertex2f(points[i].x, points[i].y);
- glEnd();
- glBegin(GL_POLYGON);
- for (i = 4; i < 8; i++)
- glVertex2f(points[i].x, points[i].y);
- glVertex2f(points[0].x, points[0].y);
- glEnd();
-
- glRectf(points[2].x, points[2].y, points[8].x, points[8].y);
- glRectf(points[6].x, points[6].y, points[9].x, points[9].y);
-}
-
-/* draw join shape due to direction of joining */
-static void draw_join_shape(ScrArea *sa, char dir)
-{
- if (dir == 'u' || dir == 'd')
- draw_vertical_join_shape(sa, dir);
- else
- draw_horizontal_join_shape(sa, dir);
-}
-
-/* draw screen area darker with arrow (visualization of future joining) */
-static void scrarea_draw_shape_dark(ScrArea *sa, char dir)
-{
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4ub(0, 0, 0, 50);
- draw_join_shape(sa, dir);
-}
-
-/* draw screen area ligher with arrow shape ("eraser" of previous dark shape) */
-static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir))
-{
- glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
- /* value 181 was hardly computed: 181~105 */
- glColor4ub(255, 255, 255, 50);
- /* draw_join_shape(sa, dir); */
- glRecti(sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y);
-}
-
-static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, short x2, short y2)
-{
- /* right border area */
- if (x2 < sizex - 1) {
- glVertex2s(x2, y1);
- glVertex2s(x2, y2);
- }
-
- /* left border area */
- if (x1 > 0) { /* otherwise it draws the emboss of window over */
- glVertex2s(x1, y1);
- glVertex2s(x1, y2);
- }
-
- /* top border area */
- if (y2 < sizey - 1) {
- glVertex2s(x1, y2);
- glVertex2s(x2, y2);
- }
-
- /* bottom border area */
- if (y1 > 0) {
- glVertex2s(x1, y1);
- glVertex2s(x2, y1);
- }
-}
-
-/** screen edges drawing **/
-static void drawscredge_area(ScrArea *sa, int sizex, int sizey)
-{
- short x1 = sa->v1->vec.x;
- short y1 = sa->v1->vec.y;
- short x2 = sa->v3->vec.x;
- short y2 = sa->v3->vec.y;
-
- drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2);
-}
/* ****************** EXPORTED API TO OTHER MODULES *************************** */
-bScreen *ED_screen_duplicate(wmWindow *win, bScreen *sc)
-{
- bScreen *newsc;
-
- if (sc->state != SCREENNORMAL) return NULL; /* XXX handle this case! */
-
- /* make new empty screen: */
- newsc = ED_screen_add(win, sc->scene, sc->id.name + 2);
- /* copy all data */
- screen_copy(newsc, sc);
-
- return newsc;
-}
-
/* screen sets cursor based on swinid */
static void region_cursor_set(wmWindow *win, int swinid, int swin_changed)
{
- for (ScrArea *sa = win->screen->areabase.first; sa; sa = sa->next) {
+ bScreen *screen = WM_window_get_active_screen(win);
+
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->swinid == swinid) {
if (swin_changed || (ar->type && ar->type->event_cursor)) {
+ if (ar->manipulator_map != NULL) {
+ if (WM_manipulatormap_cursor_set(ar->manipulator_map, win)) {
+ return;
+ }
+ }
ED_region_cursor_set(win, sa, ar);
}
return;
@@ -1084,19 +875,20 @@ static void region_cursor_set(wmWindow *win, int swinid, int swin_changed)
void ED_screen_do_listen(bContext *C, wmNotifier *note)
{
wmWindow *win = CTX_wm_window(C);
-
+ bScreen *screen = CTX_wm_screen(C);
+
/* generic notes */
switch (note->category) {
case NC_WM:
if (note->data == ND_FILEREAD)
- win->screen->do_draw = true;
+ screen->do_draw = true;
break;
case NC_WINDOW:
- win->screen->do_draw = true;
+ screen->do_draw = true;
break;
case NC_SCREEN:
if (note->action == NA_EDITED)
- win->screen->do_draw = win->screen->do_refresh = true;
+ screen->do_draw = screen->do_refresh = true;
break;
case NC_SCENE:
if (note->data == ND_MODE)
@@ -1105,100 +897,6 @@ void ED_screen_do_listen(bContext *C, wmNotifier *note)
}
}
-/* only for edge lines between areas, and the blended join arrows */
-void ED_screen_draw(wmWindow *win)
-{
- const int winsize_x = WM_window_pixels_x(win);
- const int winsize_y = WM_window_pixels_y(win);
-
- ScrArea *sa;
- ScrArea *sa1 = NULL;
- ScrArea *sa2 = NULL;
- ScrArea *sa3 = NULL;
-
- wmSubWindowSet(win, win->screen->mainwin);
-
- /* Note: first loop only draws if U.pixelsize > 1, skip otherwise */
- if (U.pixelsize > 1.0f) {
- /* FIXME: doesn't our glLineWidth already scale by U.pixelsize? */
- glLineWidth((2.0f * U.pixelsize) - 1);
- glColor3ub(0x50, 0x50, 0x50);
- glBegin(GL_LINES);
- for (sa = win->screen->areabase.first; sa; sa = sa->next)
- drawscredge_area(sa, winsize_x, winsize_y);
- glEnd();
- }
-
- glLineWidth(1);
- glColor3ub(0, 0, 0);
- glBegin(GL_LINES);
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- drawscredge_area(sa, winsize_x, winsize_y);
-
- /* gather area split/join info */
- if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa;
- if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa;
- if (sa->flag & (AREA_FLAG_DRAWSPLIT_H | AREA_FLAG_DRAWSPLIT_V)) sa3 = sa;
- }
- glEnd();
-
- /* blended join arrow */
- if (sa1 && sa2) {
- int dir = area_getorientation(sa1, sa2);
- int dira = -1;
- if (dir != -1) {
- switch (dir) {
- case 0: /* W */
- dir = 'r';
- dira = 'l';
- break;
- case 1: /* N */
- dir = 'd';
- dira = 'u';
- break;
- case 2: /* E */
- dir = 'l';
- dira = 'r';
- break;
- case 3: /* S */
- dir = 'u';
- dira = 'd';
- break;
- }
- }
- glEnable(GL_BLEND);
- scrarea_draw_shape_dark(sa2, dir);
- scrarea_draw_shape_light(sa1, dira);
- glDisable(GL_BLEND);
- }
-
- /* splitpoint */
- if (sa3) {
- glEnable(GL_BLEND);
- glBegin(GL_LINES);
- glColor4ub(255, 255, 255, 100);
-
- if (sa3->flag & AREA_FLAG_DRAWSPLIT_H) {
- glVertex2s(sa3->totrct.xmin, win->eventstate->y);
- glVertex2s(sa3->totrct.xmax, win->eventstate->y);
- glColor4ub(0, 0, 0, 100);
- glVertex2s(sa3->totrct.xmin, win->eventstate->y + 1);
- glVertex2s(sa3->totrct.xmax, win->eventstate->y + 1);
- }
- else {
- glVertex2s(win->eventstate->x, sa3->totrct.ymin);
- glVertex2s(win->eventstate->x, sa3->totrct.ymax);
- glColor4ub(0, 0, 0, 100);
- glVertex2s(win->eventstate->x + 1, sa3->totrct.ymin);
- glVertex2s(win->eventstate->x + 1, sa3->totrct.ymax);
- }
- glEnd();
- glDisable(GL_BLEND);
- }
-
- win->screen->do_draw = false;
-}
-
/* helper call for below, dpi changes headers */
static void screen_refresh_headersizes(void)
{
@@ -1214,7 +912,9 @@ static void screen_refresh_headersizes(void)
/* make this screen usable */
/* for file read and first use, for scaling window, area moves */
void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
-{
+{
+ bScreen *screen = WM_window_get_active_screen(win);
+
/* exception for bg mode, we only need the screen context */
if (!G.background) {
const int winsize_x = WM_window_pixels_x(win);
@@ -1231,32 +931,34 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
WM_window_set_dpi(win);
screen_refresh_headersizes();
- screen_test_scale(win->screen, winsize_x, winsize_y);
+ screen_test_scale(screen, winsize_x, winsize_y);
- if (win->screen->mainwin == 0) {
- win->screen->mainwin = wm_subwindow_open(win, &winrct, false);
+ if (screen->mainwin == 0) {
+ screen->mainwin = wm_subwindow_open(win, &winrct, false);
}
else {
- wm_subwindow_position(win, win->screen->mainwin, &winrct, false);
+ wm_subwindow_position(win, screen->mainwin, &winrct, false);
}
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
/* set spacetype and region callbacks, calls init() */
/* sets subwindows for regions, adds handlers */
ED_area_initialize(wm, win, sa);
}
/* wake up animtimer */
- if (win->screen->animtimer)
- WM_event_timer_sleep(wm, win, win->screen->animtimer, false);
+ if (screen->animtimer)
+ WM_event_timer_sleep(wm, win, screen->animtimer, false);
}
if (G.debug & G_DEBUG_EVENTS) {
printf("%s: set screen\n", __func__);
}
- win->screen->do_refresh = false;
+ screen->do_refresh = false;
+ /* prevent multiwin errors */
+ screen->winid = win->winid;
- win->screen->context = ed_screen_context;
+ screen->context = ed_screen_context;
}
/* file read, set all screens, ... */
@@ -1265,10 +967,10 @@ void ED_screens_initialize(wmWindowManager *wm)
wmWindow *win;
for (win = wm->windows.first; win; win = win->next) {
-
- if (win->screen == NULL)
- win->screen = G.main->screen.first;
-
+ if (WM_window_get_active_workspace(win) == NULL) {
+ WM_window_set_active_workspace(win, G.main->workspaces.first);
+ }
+
ED_screen_refresh(wm, win);
}
}
@@ -1279,15 +981,18 @@ void ED_screens_initialize(wmWindowManager *wm)
void ED_region_exit(bContext *C, ARegion *ar)
{
wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
ARegion *prevar = CTX_wm_region(C);
if (ar->type && ar->type->exit)
ar->type->exit(wm, ar);
CTX_wm_region_set(C, ar);
+
WM_event_remove_handlers(C, &ar->handlers);
+ WM_event_modal_handler_region_replace(win, ar, NULL);
if (ar->swinid) {
- wm_subwindow_close(CTX_wm_window(C), ar->swinid);
+ wm_subwindow_close(win, ar->swinid);
ar->swinid = 0;
}
@@ -1297,16 +1002,19 @@ void ED_region_exit(bContext *C, ARegion *ar)
}
if (ar->regiontimer) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ar->regiontimer);
+ WM_event_remove_timer(wm, win, ar->regiontimer);
ar->regiontimer = NULL;
}
+ WM_msgbus_clear_by_owner(wm->message_bus, ar);
+
CTX_wm_region_set(C, prevar);
}
void ED_area_exit(bContext *C, ScrArea *sa)
{
wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
ScrArea *prevsa = CTX_wm_area(C);
ARegion *ar;
@@ -1314,10 +1022,13 @@ void ED_area_exit(bContext *C, ScrArea *sa)
sa->type->exit(wm, sa);
CTX_wm_area_set(C, sa);
+
for (ar = sa->regionbase.first; ar; ar = ar->next)
ED_region_exit(C, ar);
WM_event_remove_handlers(C, &sa->handlers);
+ WM_event_modal_handler_area_replace(win, sa, NULL);
+
CTX_wm_area_set(C, prevsa);
}
@@ -1349,7 +1060,7 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
/* mark it available for use for other windows */
screen->winid = 0;
- if (prevwin->screen->temp == 0) {
+ if (!WM_window_is_temp_screen(prevwin)) {
/* use previous window if possible */
CTX_wm_window_set(C, prevwin);
}
@@ -1365,13 +1076,14 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen)
/* case when on area-edge or in azones, or outside window */
static void screen_cursor_set(wmWindow *win, const wmEvent *event)
{
+ const bScreen *screen = WM_window_get_active_screen(win);
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
AZone *az = NULL;
ScrArea *sa;
- for (sa = win->screen->areabase.first; sa; sa = sa->next)
+ for (sa = screen->areabase.first; sa; sa = sa->next)
if ((az = is_in_area_actionzone(sa, &event->x)))
break;
@@ -1386,7 +1098,7 @@ static void screen_cursor_set(wmWindow *win, const wmEvent *event)
}
}
else {
- ScrEdge *actedge = screen_find_active_scredge(win->screen, winsize_x, winsize_y, event->x, event->y);
+ ScrEdge *actedge = screen_find_active_scredge(screen, winsize_x, winsize_y, event->x, event->y);
if (actedge) {
if (scredge_is_horizontal(actedge))
@@ -1405,9 +1117,9 @@ static void screen_cursor_set(wmWindow *win, const wmEvent *event)
void ED_screen_set_subwinactive(bContext *C, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
-
- if (win->screen) {
- bScreen *scr = win->screen;
+ bScreen *scr = WM_window_get_active_screen(win);
+
+ if (scr) {
ScrArea *sa;
ARegion *ar;
int oldswin = scr->subwinactive;
@@ -1460,7 +1172,7 @@ void ED_screen_set_subwinactive(bContext *C, const wmEvent *event)
/* this used to be a notifier, but needs to be done immediate
* because it can undo setting the right button as active due
* to delayed notifier handling */
- UI_screen_free_active_but(C, win->screen);
+ UI_screen_free_active_but(C, scr);
}
else
region_cursor_set(win, scr->subwinactive, false);
@@ -1488,177 +1200,120 @@ int ED_screen_area_active(const bContext *C)
return 0;
}
+
+/* -------------------------------------------------------------------- */
+/* Screen changing */
+
+static bScreen *screen_fullscreen_find_associated_normal_screen(const Main *bmain, bScreen *screen)
+{
+ for (bScreen *screen_iter = bmain->screen.first; screen_iter; screen_iter = screen_iter->id.next) {
+ ScrArea *sa = screen_iter->areabase.first;
+ if (sa->full == screen) {
+ return screen_iter;
+ }
+ }
+
+ return screen;
+}
+
/**
- * operator call, WM + Window + screen already existed before
- *
- * \warning Do NOT call in area/region queues!
- * \returns success.
+ * \return the screen to activate.
+ * \warning The returned screen may not always equal \a screen_new!
*/
-bool ED_screen_set(bContext *C, bScreen *sc)
+bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, Main *bmain, bContext *C, wmWindow *win)
{
- Main *bmain = CTX_data_main(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- bScreen *oldscreen = CTX_wm_screen(C);
-
/* validate screen, it's called with notifier reference */
- if (BLI_findindex(&bmain->screen, sc) == -1) {
- return true;
+ if (BLI_findindex(&bmain->screen, screen_new) == -1) {
+ return NULL;
}
- if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
- /* find associated full */
- bScreen *sc1;
- for (sc1 = bmain->screen.first; sc1; sc1 = sc1->id.next) {
- ScrArea *sa = sc1->areabase.first;
- if (sa->full == sc) {
- sc = sc1;
- break;
- }
- }
+ if (ELEM(screen_new->state, SCREENMAXIMIZED, SCREENFULL)) {
+ screen_new = screen_fullscreen_find_associated_normal_screen(bmain, screen_new);
}
/* check for valid winid */
- if (sc->winid != 0 && sc->winid != win->winid) {
- return false;
+ if (!(screen_new->winid == 0 || screen_new->winid == win->winid)) {
+ return NULL;
}
-
- if (oldscreen != sc) {
- wmTimer *wt = oldscreen->animtimer;
- ScrArea *sa;
- Scene *oldscene = oldscreen->scene;
+
+ if (screen_old != screen_new) {
+ wmTimer *wt = screen_old->animtimer;
/* remove handlers referencing areas in old screen */
- for (sa = oldscreen->areabase.first; sa; sa = sa->next) {
+ for (ScrArea *sa = screen_old->areabase.first; sa; sa = sa->next) {
WM_event_remove_area_handler(&win->modalhandlers, sa);
}
/* we put timer to sleep, so screen_exit has to think there's no timer */
- oldscreen->animtimer = NULL;
+ screen_old->animtimer = NULL;
if (wt) {
- WM_event_timer_sleep(wm, win, wt, true);
+ WM_event_timer_sleep(CTX_wm_manager(C), win, wt, true);
}
-
- ED_screen_exit(C, win, oldscreen);
+ ED_screen_exit(C, win, screen_old);
/* Same scene, "transfer" playback to new screen. */
if (wt) {
- if (oldscene == sc->scene) {
- sc->animtimer = wt;
- }
- /* Else, stop playback. */
- else {
- oldscreen->animtimer = wt;
- ED_screen_animation_play(C, 0, 0);
- }
+ screen_new->animtimer = wt;
}
- win->screen = sc;
- CTX_wm_window_set(C, win); // stores C->wm.screen... hrmf
-
- /* prevent multiwin errors */
- sc->winid = win->winid;
-
- ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C));
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- WM_event_add_notifier(C, NC_SCREEN | ND_SCREENSET, sc);
-
- /* makes button hilites work */
- WM_event_add_mousemove(C);
-
- /* Needed to make sure all the derivedMeshes are
- * up-to-date before viewport starts acquiring this.
- *
- * This is needed in cases when, for example, boolean
- * modifier uses operant from invisible layer.
- * Without this trick boolean wouldn't apply correct.
- *
- * Quite the same happens when setting screen's scene,
- * so perhaps this is in fact correct thing to do.
- */
- if (oldscene != sc->scene) {
- BKE_scene_set_background(bmain, sc->scene);
- }
-
- /* Always do visible update since it's possible new screen will
- * have different layers visible in 3D view-ports.
- * This is possible because of view3d.lock_camera_and_layers option.
- */
- DAG_on_visible_update(bmain, false);
+ return screen_new;
}
- return true;
+ return NULL;
}
-static bool ed_screen_used(wmWindowManager *wm, bScreen *sc)
+void screen_changed_update(bContext *C, wmWindow *win, bScreen *sc)
{
- wmWindow *win;
+ Scene *scene = WM_window_get_active_scene(win);
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc);
- for (win = wm->windows.first; win; win = win->next) {
- if (win->screen == sc) {
- return true;
- }
+ CTX_wm_window_set(C, win); /* stores C->wm.screen... hrmf */
- if (ELEM(win->screen->state, SCREENMAXIMIZED, SCREENFULL)) {
- ScrArea *sa = win->screen->areabase.first;
- if (sa->full == sc) {
- return true;
- }
- }
- }
+ ED_screen_refresh(CTX_wm_manager(C), win);
- return false;
+ BKE_screen_view3d_scene_sync(sc, scene); /* sync new screen with scene data */
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTSET, layout);
+
+ /* makes button hilites work */
+ WM_event_add_mousemove(C);
}
-/* only call outside of area/region loops */
-bool ED_screen_delete(bContext *C, bScreen *sc)
+
+/**
+ * \brief Change the active screen.
+ *
+ * Operator call, WM + Window + screen already existed before
+ *
+ * \warning Do NOT call in area/region queues!
+ * \returns if screen changing was successful.
+ */
+bool ED_screen_change(bContext *C, bScreen *sc)
{
Main *bmain = CTX_data_main(C);
- wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
- bScreen *newsc;
-
- /* don't allow deleting temp fullscreens for now */
- if (ELEM(sc->state, SCREENMAXIMIZED, SCREENFULL)) {
- return false;
- }
-
- /* screen can only be in use by one window at a time, so as
- * long as we are able to find a screen that is unused, we
- * can safely assume ours is not in use anywhere an delete it */
-
- for (newsc = sc->id.prev; newsc; newsc = newsc->id.prev)
- if (!ed_screen_used(wm, newsc) && !newsc->temp)
- break;
-
- if (!newsc) {
- for (newsc = sc->id.next; newsc; newsc = newsc->id.next)
- if (!ed_screen_used(wm, newsc) && !newsc->temp)
- break;
- }
+ bScreen *screen_old = CTX_wm_screen(C);
+ bScreen *screen_new = screen_change_prepare(screen_old, sc, bmain, C, win);
- if (!newsc) {
- return false;
- }
+ if (screen_new) {
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ WM_window_set_active_screen(win, workspace, sc);
+ screen_changed_update(C, win, screen_new);
- ED_screen_set(C, newsc);
-
- if (win->screen != sc) {
- BKE_libblock_free(bmain, sc);
return true;
}
- else {
- return false;
- }
+
+ return false;
}
-static void ed_screen_set_3dview_camera(Scene *scene, bScreen *sc, ScrArea *sa, View3D *v3d)
+static void screen_set_3dview_camera(Scene *scene, ViewLayer *view_layer, ScrArea *sa, View3D *v3d)
{
/* fix any cameras that are used in the 3d view but not in the scene */
BKE_screen_view3d_sync(v3d, scene);
- if (!v3d->camera || !BKE_scene_base_find(scene, v3d->camera)) {
- v3d->camera = BKE_scene_camera_find(sc->scene);
+ if (!v3d->camera || !BKE_view_layer_base_find(view_layer, v3d->camera)) {
+ v3d->camera = BKE_view_layer_camera_find(view_layer);
// XXX if (sc == curscreen) handle_view3d_lock();
if (!v3d->camera) {
ARegion *ar;
@@ -1682,93 +1337,16 @@ static void ed_screen_set_3dview_camera(Scene *scene, bScreen *sc, ScrArea *sa,
}
}
-/* only call outside of area/region loops */
-void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene)
+void ED_screen_update_after_scene_change(const bScreen *screen, Scene *scene_new, ViewLayer *view_layer)
{
- Main *bmain = CTX_data_main(C);
- bScreen *sc;
-
- if (screen == NULL)
- return;
-
- if (ed_screen_used(CTX_wm_manager(C), screen))
- ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO);
-
- for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- if ((U.flag & USER_SCENEGLOBAL) || sc == screen) {
-
- if (scene != sc->scene) {
- /* all areas endlocalview */
- // XXX ScrArea *sa = sc->areabase.first;
- // while (sa) {
- // endlocalview(sa);
- // sa = sa->next;
- // }
- sc->scene = scene;
- }
-
- }
- }
-
- // copy_view3d_lock(0); /* space.c */
-
- /* are there cameras in the views that are not in the scene? */
- for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- if ((U.flag & USER_SCENEGLOBAL) || sc == screen) {
- ScrArea *sa = sc->areabase.first;
- while (sa) {
- SpaceLink *sl = sa->spacedata.first;
- while (sl) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *) sl;
- ed_screen_set_3dview_camera(scene, sc, sa, v3d);
-
- }
- sl = sl->next;
- }
- sa = sa->next;
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ screen_set_3dview_camera(scene_new, view_layer, sa, v3d);
}
}
}
-
- CTX_data_scene_set(C, scene);
- BKE_scene_set_background(bmain, scene);
- DAG_on_visible_update(bmain, false);
-
- ED_render_engine_changed(bmain);
- ED_update_for_newframe(bmain, scene, 1);
-
- /* complete redraw */
- WM_event_add_notifier(C, NC_WINDOW, NULL);
-
-}
-
-/**
- * \note Only call outside of area/region loops
- * \return true if successful
- */
-bool ED_screen_delete_scene(bContext *C, Scene *scene)
-{
- Main *bmain = CTX_data_main(C);
- Scene *newscene;
-
- if (scene->id.prev)
- newscene = scene->id.prev;
- else if (scene->id.next)
- newscene = scene->id.next;
- else
- return false;
-
- ED_screen_set_scene(C, CTX_wm_screen(C), newscene);
-
- BKE_libblock_remap(bmain, scene, newscene, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
-
- id_us_clear_real(&scene->id);
- if (scene->id.us == 0) {
- BKE_libblock_free(bmain, scene);
- }
-
- return true;
}
ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
@@ -1875,6 +1453,7 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa)
ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const short state)
{
wmWindowManager *wm = CTX_wm_manager(C);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
bScreen *sc, *oldscreen;
ARegion *ar;
@@ -1896,9 +1475,10 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
}
if (sa && sa->full) {
+ WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
/* restoring back to SCREENNORMAL */
sc = sa->full; /* the old screen to restore */
- oldscreen = win->screen; /* the one disappearing */
+ oldscreen = WM_window_get_active_screen(win); /* the one disappearing */
sc->state = SCREENNORMAL;
@@ -1937,9 +1517,9 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
sc->animtimer = oldscreen->animtimer;
oldscreen->animtimer = NULL;
- ED_screen_set(C, sc);
+ ED_screen_change(C, sc);
- BKE_libblock_free(CTX_data_main(C), oldscreen);
+ BKE_workspace_layout_remove(CTX_data_main(C), workspace, layout_old);
/* After we've restored back to SCREENNORMAL, we have to wait with
* screen handling as it uses the area coords which aren't updated yet.
@@ -1949,14 +1529,18 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
}
else {
/* change from SCREENNORMAL to new state */
+ WorkSpaceLayout *layout_new;
ScrArea *newa;
char newname[MAX_ID_NAME - 2];
- oldscreen = win->screen;
+ oldscreen = WM_window_get_active_screen(win);
oldscreen->state = state;
BLI_snprintf(newname, sizeof(newname), "%s-%s", oldscreen->id.name + 2, "nonnormal");
- sc = ED_screen_add(win, oldscreen->scene, newname);
+
+ layout_new = ED_workspace_layout_add(workspace, win, newname);
+
+ sc = BKE_workspace_layout_screen_get(layout_new);
sc->state = state;
sc->redraws_flag = oldscreen->redraws_flag;
sc->temp = oldscreen->temp;
@@ -2011,7 +1595,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s
BLI_assert(false);
}
- ED_screen_set(C, sc);
+ ED_screen_change(C, sc);
}
/* XXX bad code: setscreen() ends with first area active. fullscreen render assumes this too */
@@ -2146,14 +1730,9 @@ void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh)
}
}
-/* results in fully updated anim system
- * screen can be NULL */
-void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
+/* results in fully updated anim system */
+void ED_update_for_newframe(Main *bmain, Scene *scene, ViewLayer *view_layer, struct Depsgraph *depsgraph)
{
- wmWindowManager *wm = bmain->wm.first;
- wmWindow *window;
- int layers = 0;
-
#ifdef DURIAN_CAMERA_SWITCH
void *camera = BKE_scene_camera_switch_find(scene);
if (camera && scene->camera != camera) {
@@ -2161,19 +1740,15 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
scene->camera = camera;
/* are there cameras in the views that are not in the scene? */
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- BKE_screen_view3d_scene_sync(sc);
+ BKE_screen_view3d_scene_sync(sc, scene);
}
}
#endif
ED_clip_update_frame(bmain, scene->r.cfra);
- /* get layers from all windows */
- for (window = wm->windows.first; window; window = window->next)
- layers |= BKE_screen_visible_layers(window->screen, scene);
-
/* this function applies the changes too */
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, layers);
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
/* composite */
if (scene->use_nodes && scene->nodetree)
@@ -2194,11 +1769,10 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
/*
* return true if any active area requires to see in 3D
*/
-bool ED_screen_stereo3d_required(bScreen *screen)
+bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene)
{
ScrArea *sa;
- Scene *sce = screen->scene;
- const bool is_multiview = (sce->r.scemode & R_MULTIVIEW) != 0;
+ const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
for (sa = screen->areabase.first; sa; sa = sa->next) {
switch (sa->spacetype) {
@@ -2273,3 +1847,19 @@ bool ED_screen_stereo3d_required(bScreen *screen)
return false;
}
+
+/**
+ * Find the scene displayed in \a screen.
+ * \note Assumes \a screen to be visible/active!
+ */
+Scene *ED_screen_scene_find(const bScreen *screen, const wmWindowManager *wm)
+{
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (WM_window_get_active_screen(win) == screen) {
+ return WM_window_get_active_scene(win);
+ }
+ }
+
+ BLI_assert(0);
+ return NULL;
+}
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index ccb6d5a6dca..4eb68d01df7 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -31,6 +31,9 @@
#ifndef __SCREEN_INTERN_H__
#define __SCREEN_INTERN_H__
+struct bContextDataResult;
+struct Main;
+
/* internal exports only */
#define AZONESPOT (0.6f * U.widget_unit)
@@ -40,12 +43,17 @@
/* area.c */
void ED_area_data_copy(ScrArea *sa_dst, ScrArea *sa_src, const bool do_free);
void ED_area_data_swap(ScrArea *sa1, ScrArea *sa2);
-void region_toggle_hidden(bContext *C, ARegion *ar, const bool do_fade);
+void region_toggle_hidden(struct bContext *C, ARegion *ar, const bool do_fade);
/* screen_edit.c */
+bScreen *screen_add(const char *name, const int winsize_x, const int winsize_y);
+void screen_data_copy(bScreen *to, bScreen *from);
+void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new);
+void screen_changed_update(struct bContext *C, wmWindow *win, bScreen *sc);
+bScreen *screen_change_prepare(bScreen *screen_old, bScreen *screen_new, struct Main *bmain, struct bContext *C, wmWindow *win);
ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2);
ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge);
-int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2);
+int screen_area_join(struct bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2);
int area_getorientation(ScrArea *sa, ScrArea *sb);
void select_connected_scredge(bScreen *sc, ScrEdge *edge);
@@ -54,14 +62,14 @@ void removedouble_scrverts(bScreen *sc);
void removedouble_scredges(bScreen *sc);
void removenotused_scredges(bScreen *sc);
bool scredge_is_horizontal(ScrEdge *se);
-ScrEdge *screen_find_active_scredge(bScreen *sc,
+ScrEdge *screen_find_active_scredge(const bScreen *sc,
const int winsize_x, const int winsize_y,
const int mx, const int my);
struct AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]);
/* screen_context.c */
-int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result);
+int ed_screen_context(const struct bContext *C, const char *member, struct bContextDataResult *result);
extern const char *screen_context_dir[]; /* doc access */
@@ -72,5 +80,8 @@ void SCREEN_OT_screencast(struct wmOperatorType *ot);
/* screen_ops.c */
void region_blend_start(struct bContext *C, struct ScrArea *sa, struct ARegion *ar);
+/* workspace_layout_edit.c */
+bool workspace_layout_set_poll(const struct WorkSpaceLayout *layout);
+
#endif /* __SCREEN_INTERN_H__ */
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 908d218d353..4460ac7d1a7 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -48,11 +48,13 @@
#include "DNA_meta_types.h"
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_userdef_types.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
+#include "BKE_icons.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -61,6 +63,7 @@
#include "BKE_editmesh.h"
#include "BKE_sound.h"
#include "BKE_mask.h"
+#include "BKE_workspace.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -571,8 +574,8 @@ int ED_operator_mask(bContext *C)
case SPACE_IMAGE:
{
SpaceImage *sima = sa->spacedata.first;
- Scene *scene = CTX_data_scene(C);
- return ED_space_image_check_show_maskedit(scene, sima);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ return ED_space_image_check_show_maskedit(view_layer, sima);
}
}
}
@@ -580,6 +583,12 @@ int ED_operator_mask(bContext *C)
return false;
}
+int ED_operator_camera(bContext *C)
+{
+ struct Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
+ return (cam != NULL);
+}
+
/* *************************** action zone operator ************************** */
/* operator state vars used:
@@ -977,13 +986,17 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot)
/* operator callback */
static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- wmWindow *newwin, *win;
- bScreen *newsc, *sc;
+ wmWindow *newwin, *win = CTX_wm_window(C);
+ Scene *scene;
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
+ WorkSpaceLayout *layout_new;
+ bScreen *newsc;
ScrArea *sa;
rcti rect;
win = CTX_wm_window(C);
- sc = CTX_wm_screen(C);
+ scene = CTX_data_scene(C);
sa = CTX_wm_area(C);
/* XXX hrmf! */
@@ -1009,11 +1022,15 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
*newwin->stereo3d_format = *win->stereo3d_format;
-
+
+ newwin->scene = scene;
+
+ WM_window_set_active_workspace(newwin, workspace);
/* allocs new screen and adds to newly created window, using window size */
- newsc = ED_screen_add(newwin, CTX_data_scene(C), sc->id.name + 2);
- newwin->screen = newsc;
-
+ layout_new = ED_workspace_layout_add(workspace, newwin, BKE_workspace_layout_name_get(layout_old));
+ newsc = BKE_workspace_layout_screen_get(layout_new);
+ WM_window_set_active_layout(newwin, workspace, layout_new);
+
/* copy area to new screen */
ED_area_data_copy((ScrArea *)newsc->areabase.first, sa, true);
@@ -1220,6 +1237,8 @@ static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int
}
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); /* redraw everything */
+ /* Update preview thumbnail */
+ BKE_icon_changed(sc->id.icon_id);
}
}
@@ -1508,7 +1527,9 @@ static int area_split_apply(bContext *C, wmOperator *op)
ED_area_tag_redraw(sd->narea);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
-
+ /* Update preview thumbnail */
+ BKE_icon_changed(sc->id.icon_id);
+
return 1;
}
@@ -1709,7 +1730,7 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
- CTX_wm_window(C)->screen->do_draw = true;
+ CTX_wm_screen(C)->do_draw = true;
}
@@ -2079,12 +2100,11 @@ static void areas_do_frame_follow(bContext *C, bool middle)
bScreen *scr = CTX_wm_screen(C);
Scene *scene = CTX_data_scene(C);
wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *window;
- for (window = wm->windows.first; window; window = window->next) {
- ScrArea *sa;
- for (sa = window->screen->areabase.first; sa; sa = sa->next) {
- ARegion *ar;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ for (wmWindow *window = wm->windows.first; window; window = window->next) {
+ const bScreen *screen = WM_window_get_active_screen(window);
+
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
/* do follow here if editor type supports it */
if ((scr->redraws_flag & TIME_FOLLOW)) {
if ((ar->regiontype == RGN_TYPE_WINDOW &&
@@ -2383,64 +2403,16 @@ static void SCREEN_OT_marker_jump(wmOperatorType *ot)
/* ************** switch screen operator ***************************** */
-static bool screen_set_is_ok(bScreen *screen, bScreen *screen_prev)
-{
- return ((screen->winid == 0) &&
- /* in typical usage these should have a nonzero winid
- * (all temp screens should be used, or closed & freed). */
- (screen->temp == false) &&
- (screen->state == SCREENNORMAL) &&
- (screen != screen_prev) &&
- (screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT)));
-}
-
/* function to be called outside UI context, or for redo */
static int screen_set_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- bScreen *screen = CTX_wm_screen(C);
- bScreen *screen_prev = screen;
-
- ScrArea *sa = CTX_wm_area(C);
- int tot = BLI_listbase_count(&bmain->screen);
+ WorkSpace *workspace = CTX_wm_workspace(C);
int delta = RNA_int_get(op->ptr, "delta");
-
- /* temp screens are for userpref or render display */
- if (screen->temp || (sa && sa->full && sa->full->temp)) {
- return OPERATOR_CANCELLED;
- }
-
- if (delta == 1) {
- while (tot--) {
- screen = screen->id.next;
- if (screen == NULL) screen = bmain->screen.first;
- if (screen_set_is_ok(screen, screen_prev)) {
- break;
- }
- }
- }
- else if (delta == -1) {
- while (tot--) {
- screen = screen->id.prev;
- if (screen == NULL) screen = bmain->screen.last;
- if (screen_set_is_ok(screen, screen_prev)) {
- break;
- }
- }
- }
- else {
- screen = NULL;
- }
-
- if (screen && screen_prev != screen) {
- /* return to previous state before switching screens */
- if (sa && sa->full) {
- ED_screen_full_restore(C, sa); /* may free 'screen_prev' */
- }
-
- ED_screen_set(C, screen);
+
+ if (ED_workspace_layout_cycle(workspace, delta, C)) {
return OPERATOR_FINISHED;
}
+
return OPERATOR_CANCELLED;
}
@@ -3252,7 +3224,7 @@ static int header_toggle_menus_exec(bContext *C, wmOperator *UNUSED(op))
sa->flag = sa->flag ^ HEADER_NO_PULLDOWN;
ED_area_tag_redraw(sa);
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
@@ -3436,6 +3408,8 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
if (screen->animtimer && screen->animtimer == event->customdata) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
wmTimer *wt = screen->animtimer;
ScreenAnimData *sad = wt->customdata;
wmWindowManager *wm = CTX_wm_manager(C);
@@ -3546,10 +3520,12 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
}
/* since we follow drawflags, we can't send notifier but tag regions ourselves */
- ED_update_for_newframe(bmain, scene, 1);
+ ED_update_for_newframe(bmain, scene, view_layer, depsgraph);
for (window = wm->windows.first; window; window = window->next) {
- for (sa = window->screen->areabase.first; sa; sa = sa->next) {
+ const bScreen *win_screen = WM_window_get_active_screen(window);
+
+ for (sa = win_screen->areabase.first; sa; sa = sa->next) {
ARegion *ar;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
bool redraw = false;
@@ -3623,11 +3599,11 @@ static void SCREEN_OT_animation_step(wmOperatorType *ot)
/* find window that owns the animation timer */
bScreen *ED_screen_animation_playing(const wmWindowManager *wm)
{
- wmWindow *win;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ bScreen *screen = WM_window_get_active_screen(win);
- for (win = wm->windows.first; win; win = win->next) {
- if (win->screen->animtimer || win->screen->scrubbing) {
- return win->screen;
+ if (screen->animtimer || screen->scrubbing) {
+ return screen;
}
}
@@ -3636,11 +3612,11 @@ bScreen *ED_screen_animation_playing(const wmWindowManager *wm)
bScreen *ED_screen_animation_no_scrub(const wmWindowManager *wm)
{
- wmWindow *win;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ bScreen *screen = WM_window_get_active_screen(win);
- for (win = wm->windows.first; win; win = win->next) {
- if (win->screen->animtimer) {
- return win->screen;
+ if (screen->animtimer) {
+ return screen;
}
}
@@ -3874,11 +3850,13 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot)
static int screen_new_exec(bContext *C, wmOperator *UNUSED(op))
{
wmWindow *win = CTX_wm_window(C);
- bScreen *sc = CTX_wm_screen(C);
-
- sc = ED_screen_duplicate(win, sc);
- WM_event_add_notifier(C, NC_SCREEN | ND_SCREENBROWSE, sc);
-
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ WorkSpaceLayout *layout_old = BKE_workspace_active_layout_get(win->workspace_hook);
+ WorkSpaceLayout *layout_new;
+
+ layout_new = ED_workspace_layout_duplicate(workspace, layout_old, win);
+ WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTBROWSE, layout_new);
+
return OPERATOR_FINISHED;
}
@@ -3899,9 +3877,11 @@ static void SCREEN_OT_new(wmOperatorType *ot)
static int screen_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
bScreen *sc = CTX_wm_screen(C);
-
- WM_event_add_notifier(C, NC_SCREEN | ND_SCREENDELETE, sc);
-
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ WorkSpaceLayout *layout = BKE_workspace_layout_find(workspace, sc);
+
+ WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTDELETE, layout);
+
return OPERATOR_FINISHED;
}
@@ -3916,95 +3896,6 @@ static void SCREEN_OT_delete(wmOperatorType *ot)
ot->exec = screen_delete_exec;
}
-/********************* new scene operator *********************/
-
-static int scene_new_exec(bContext *C, wmOperator *op)
-{
- Scene *newscene, *scene = CTX_data_scene(C);
- Main *bmain = CTX_data_main(C);
- int type = RNA_enum_get(op->ptr, "type");
-
- if (type == SCE_COPY_NEW) {
- newscene = BKE_scene_add(bmain, DATA_("Scene"));
- }
- else { /* different kinds of copying */
- newscene = BKE_scene_copy(bmain, scene, type);
-
- /* these can't be handled in blenkernel currently, so do them here */
- if (type == SCE_COPY_LINK_DATA) {
- ED_object_single_users(bmain, newscene, false, true);
- }
- else if (type == SCE_COPY_FULL) {
- ED_editors_flush_edits(C, false);
- ED_object_single_users(bmain, newscene, true, true);
- }
- }
-
- ED_screen_set_scene(C, CTX_wm_screen(C), newscene);
-
- WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, newscene);
-
- return OPERATOR_FINISHED;
-}
-
-static void SCENE_OT_new(wmOperatorType *ot)
-{
- static const EnumPropertyItem type_items[] = {
- {SCE_COPY_NEW, "NEW", 0, "New", "Add new scene"},
- {SCE_COPY_EMPTY, "EMPTY", 0, "Copy Settings", "Make a copy without any objects"},
- {SCE_COPY_LINK_OB, "LINK_OBJECTS", 0, "Link Objects", "Link to the objects from the current scene"},
- {SCE_COPY_LINK_DATA, "LINK_OBJECT_DATA", 0, "Link Object Data", "Copy objects linked to data from the current scene"},
- {SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene"},
- {0, NULL, 0, NULL, NULL}};
-
- /* identifiers */
- ot->name = "New Scene";
- ot->description = "Add new scene by type";
- ot->idname = "SCENE_OT_new";
-
- /* api callbacks */
- ot->exec = scene_new_exec;
- ot->invoke = WM_menu_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
-}
-
-/********************* delete scene operator *********************/
-
-static int scene_delete_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Scene *scene = CTX_data_scene(C);
-
- if (ED_screen_delete_scene(C, scene) == false) {
- return OPERATOR_CANCELLED;
- }
-
- if (G.debug & G_DEBUG)
- printf("scene delete %p\n", scene);
-
- WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
-
- return OPERATOR_FINISHED;
-}
-
-static void SCENE_OT_delete(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Delete Scene";
- ot->description = "Delete active scene";
- ot->idname = "SCENE_OT_delete";
-
- /* api callbacks */
- ot->exec = scene_delete_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
/* ***************** region alpha blending ***************** */
/* implementation note: a disappearing region needs at least 1 last draw with 100% backbuffer
@@ -4275,13 +4166,11 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(SCREEN_OT_animation_step);
WM_operatortype_append(SCREEN_OT_animation_play);
WM_operatortype_append(SCREEN_OT_animation_cancel);
-
+
/* new/delete */
WM_operatortype_append(SCREEN_OT_new);
WM_operatortype_append(SCREEN_OT_delete);
- WM_operatortype_append(SCENE_OT_new);
- WM_operatortype_append(SCENE_OT_delete);
-
+
/* tools shared by more space types */
WM_operatortype_append(ED_OT_undo);
WM_operatortype_append(ED_OT_undo_push);
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index 2dd7400bc37..69891a727d4 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -54,7 +54,9 @@
#include "BKE_writeavi.h"
#include "BIF_gl.h"
-#include "BIF_glutil.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -451,25 +453,24 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
/* Helper callback for drawing the cursor itself */
static void screencast_draw_cursor(bContext *UNUSED(C), int x, int y, void *UNUSED(p_ptr))
{
-
- glPushMatrix();
-
- glTranslatef((float)x, (float)y, 0.0f);
-
-
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
- glColor4ub(0, 0, 0, 32);
- glutil_draw_filled_arc(0.0, M_PI * 2.0, 20, 40);
-
- glColor4ub(255, 255, 255, 128);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, 20, 40);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4ub(0, 0, 0, 32);
+ imm_draw_circle_fill_2d(pos, (float)x, (float)y, 20, 40);
+
+ immUniformColor4ub(255, 255, 255, 128);
+ imm_draw_circle_wire_2d(pos, (float)x, (float)y, 20, 40);
+
+ immUnbindProgram();
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
}
/* Turn brush cursor in 3D view on/off */
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
new file mode 100644
index 00000000000..00dc1003121
--- /dev/null
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -0,0 +1,454 @@
+/*
+ * ***** 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/screen/workspace_edit.c
+ * \ingroup edscr
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_fileops.h"
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+#include "BKE_appdir.h"
+#include "BKE_blendfile.h"
+#include "BKE_context.h"
+#include "BKE_idcode.h"
+#include "BKE_main.h"
+#include "BKE_library.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_workspace.h"
+
+#include "BLO_readfile.h"
+
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "screen_intern.h"
+
+
+/** \name Workspace API
+ *
+ * \brief API for managing workspaces and their data.
+ * \{ */
+
+WorkSpace *ED_workspace_add(
+ Main *bmain, const char *name, Scene *scene,
+ ViewLayer *act_view_layer, ViewRender *view_render)
+{
+ WorkSpace *workspace = BKE_workspace_add(bmain, name);
+
+ BKE_workspace_view_layer_set(workspace, act_view_layer, scene);
+ BKE_viewrender_copy(&workspace->view_render, view_render);
+
+#ifdef USE_WORKSPACE_MODE
+ BKE_workspace_object_mode_set(workspace, scene, OB_MODE_OBJECT);
+#endif
+
+ return workspace;
+}
+
+#ifdef USE_WORKSPACE_MODE
+/**
+ * Changes the object mode (if needed) to the one set in \a workspace_new.
+ * Object mode is still stored on object level. In future it should all be workspace level instead.
+ */
+static void workspace_change_update_mode(
+ const WorkSpace *workspace_old, const WorkSpace *workspace_new,
+ bContext *C, Object *ob_act, ReportList *reports)
+{
+ const Scene *scene = CTX_data_scene(C);
+ eObjectMode mode_old = BKE_workspace_object_mode_get(workspace_old, scene);
+ eObjectMode mode_new = BKE_workspace_object_mode_get(workspace_new, scene);
+
+ if (mode_old != mode_new) {
+ ED_object_mode_compat_set(C, ob_act, mode_new, reports);
+ ED_object_toggle_modes(C, mode_new);
+ }
+}
+#endif
+
+static void workspace_change_update_view_layer(
+ WorkSpace *workspace_new, const WorkSpace *workspace_old,
+ Scene *scene)
+{
+ if (!BKE_workspace_view_layer_get(workspace_new, scene)) {
+ BKE_workspace_view_layer_set(workspace_new, BKE_workspace_view_layer_get(workspace_old, scene), scene);
+ }
+}
+
+static void workspace_change_update(
+ WorkSpace *workspace_new, const WorkSpace *workspace_old,
+ bContext *C, wmWindowManager *wm)
+{
+ /* needs to be done before changing mode! (to ensure right context) */
+ workspace_change_update_view_layer(workspace_new, workspace_old, CTX_data_scene(C));
+#ifdef USE_WORKSPACE_MODE
+ workspace_change_update_mode(workspace_old, workspace_new, C, CTX_data_active_object(C), &wm->reports);
+#else
+ UNUSED_VARS(C, wm);
+#endif
+}
+
+static bool workspace_change_find_new_layout_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
+{
+ /* return false to stop the iterator if we've found a layout that can be activated */
+ return workspace_layout_set_poll(layout) ? false : true;
+}
+
+static WorkSpaceLayout *workspace_change_get_new_layout(
+ WorkSpace *workspace_new, wmWindow *win)
+{
+ /* ED_workspace_duplicate may have stored a layout to activate once the workspace gets activated. */
+ WorkSpaceLayout *layout_new;
+ bScreen *screen_new;
+
+ if (win->workspace_hook->temp_workspace_store) {
+ layout_new = win->workspace_hook->temp_layout_store;
+ }
+ else {
+ layout_new = BKE_workspace_hook_layout_for_workspace_get(win->workspace_hook, workspace_new);
+ if (!layout_new) {
+ layout_new = BKE_workspace_layouts_get(workspace_new)->first;
+ }
+ }
+ screen_new = BKE_workspace_layout_screen_get(layout_new);
+
+ if (screen_new->winid) {
+ /* screen is already used, try to find a free one */
+ WorkSpaceLayout *layout_temp = BKE_workspace_layout_iter_circular(
+ workspace_new, layout_new, workspace_change_find_new_layout_cb,
+ NULL, false);
+ if (!layout_temp) {
+ /* fallback solution: duplicate layout */
+ layout_temp = ED_workspace_layout_duplicate(workspace_new, layout_new, win);
+ }
+ layout_new = layout_temp;
+ }
+
+ return layout_new;
+}
+
+/**
+ * \brief Change the active workspace.
+ *
+ * Operator call, WM + Window + screen already existed before
+ * Pretty similar to #ED_screen_change since changing workspace also changes screen.
+ *
+ * \warning Do NOT call in area/region queues!
+ * \returns if workspace changing was successful.
+ */
+bool ED_workspace_change(
+ WorkSpace *workspace_new, bContext *C, wmWindowManager *wm, wmWindow *win)
+{
+ Main *bmain = CTX_data_main(C);
+ WorkSpace *workspace_old = WM_window_get_active_workspace(win);
+ WorkSpaceLayout *layout_new = workspace_change_get_new_layout(workspace_new, win);
+ bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
+ bScreen *screen_old = BKE_workspace_active_screen_get(win->workspace_hook);
+
+ win->workspace_hook->temp_layout_store = NULL;
+ if (workspace_old == workspace_new) {
+ /* Could also return true, everything that needs to be done was done (nothing :P), but nothing changed */
+ return false;
+ }
+
+ screen_new = screen_change_prepare(screen_old, screen_new, bmain, C, win);
+ BLI_assert(BKE_workspace_layout_screen_get(layout_new) == screen_new);
+
+ if (screen_new) {
+ WM_window_set_active_layout(win, workspace_new, layout_new);
+ WM_window_set_active_workspace(win, workspace_new);
+
+ /* update screen *after* changing workspace - which also causes the actual screen change */
+ screen_changed_update(C, win, screen_new);
+ workspace_change_update(workspace_new, workspace_old, C, wm);
+
+ BLI_assert(BKE_workspace_view_layer_get(workspace_new, CTX_data_scene(C)) != NULL);
+ BLI_assert(CTX_wm_workspace(C) == workspace_new);
+
+ WM_toolsystem_unlink(C, workspace_old);
+ WM_toolsystem_link(C, workspace_new);
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Duplicate a workspace including its layouts. Does not activate the workspace, but
+ * it stores the screen-layout to be activated (BKE_workspace_temp_layout_store)
+ */
+WorkSpace *ED_workspace_duplicate(
+ WorkSpace *workspace_old, Main *bmain, wmWindow *win)
+{
+ WorkSpaceLayout *layout_active_old = BKE_workspace_active_layout_get(win->workspace_hook);
+ ListBase *layouts_old = BKE_workspace_layouts_get(workspace_old);
+ Scene *scene = WM_window_get_active_scene(win);
+ WorkSpace *workspace_new = ED_workspace_add(
+ bmain, workspace_old->id.name + 2, scene,
+ BKE_workspace_view_layer_get(workspace_old, scene),
+ &workspace_old->view_render);
+ ListBase *transform_orientations_old = BKE_workspace_transform_orientations_get(workspace_old);
+ ListBase *transform_orientations_new = BKE_workspace_transform_orientations_get(workspace_new);
+
+#ifdef USE_WORKSPACE_MODE
+ BKE_workspace_object_mode_set(workspace_new, scene, BKE_workspace_object_mode_get(workspace_old, scene));
+#endif
+ BLI_duplicatelist(transform_orientations_new, transform_orientations_old);
+
+ workspace_new->tool = workspace_old->tool;
+
+ for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old; layout_old = layout_old->next) {
+ WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(workspace_new, layout_old, win);
+
+ if (layout_active_old == layout_old) {
+ win->workspace_hook->temp_layout_store = layout_new;
+ }
+ }
+ return workspace_new;
+}
+
+/**
+ * \return if succeeded.
+ */
+bool ED_workspace_delete(
+ WorkSpace *workspace, Main *bmain, bContext *C, wmWindowManager *wm)
+{
+ ID *workspace_id = (ID *)workspace;
+
+ if (BLI_listbase_is_single(&bmain->workspaces)) {
+ return false;
+ }
+
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ WorkSpace *prev = workspace_id->prev;
+ WorkSpace *next = workspace_id->next;
+
+ ED_workspace_change((prev != NULL) ? prev : next, C, wm, win);
+ }
+ BKE_libblock_free(bmain, workspace_id);
+
+ return true;
+}
+
+/**
+ * Some editor data may need to be synced with scene data (3D View camera and layers).
+ * This function ensures data is synced for editors in active layout of \a workspace.
+ */
+void ED_workspace_scene_data_sync(
+ WorkSpaceInstanceHook *hook, Scene *scene)
+{
+ bScreen *screen = BKE_workspace_active_screen_get(hook);
+ BKE_screen_view3d_scene_sync(screen, scene);
+}
+
+void ED_workspace_view_layer_unset(
+ const Main *bmain, Scene *scene,
+ const ViewLayer *layer_unset, ViewLayer *layer_new)
+{
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ if (BKE_workspace_view_layer_get(workspace, scene) == layer_unset) {
+ BKE_workspace_view_layer_set(workspace, layer_new, scene);
+ }
+ }
+}
+
+/** \} Workspace API */
+
+
+/** \name Workspace Operators
+ *
+ * \{ */
+
+static int workspace_new_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = CTX_wm_window(C);
+ WorkSpace *workspace = ED_workspace_duplicate(WM_window_get_active_workspace(win), bmain, win);
+
+ WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace);
+
+ return OPERATOR_FINISHED;
+}
+
+static void WORKSPACE_OT_workspace_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Workspace";
+ ot->description = "Add a new workspace";
+ ot->idname = "WORKSPACE_OT_workspace_duplicate";
+
+ /* api callbacks */
+ ot->exec = workspace_new_exec;
+ ot->poll = WM_operator_winactive;
+}
+
+static int workspace_delete_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+
+ ED_workspace_delete(WM_window_get_active_workspace(win), bmain, C, wm);
+
+ return OPERATOR_FINISHED;
+}
+
+static void WORKSPACE_OT_workspace_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete Workspace";
+ ot->description = "Delete the active workspace";
+ ot->idname = "WORKSPACE_OT_workspace_delete";
+
+ /* api callbacks */
+ ot->exec = workspace_delete_exec;
+}
+
+static void workspace_config_file_path_from_folder_id(
+ const Main *bmain, int folder_id, char *r_path)
+{
+ const char *app_template = U.app_template[0] ? U.app_template : NULL;
+ const char * const cfgdir = BKE_appdir_folder_id(folder_id, app_template);
+
+ if (cfgdir) {
+ BLI_make_file_string(bmain->name, r_path, cfgdir, BLENDER_WORKSPACES_FILE);
+ }
+ else {
+ r_path[0] = '\0';
+ }
+}
+
+ATTR_NONNULL(1)
+static WorkspaceConfigFileData *workspace_config_file_read(
+ const Main *bmain, ReportList *reports)
+{
+ char workspace_config_path[FILE_MAX];
+ bool has_path = false;
+
+ workspace_config_file_path_from_folder_id(bmain, BLENDER_USER_CONFIG, workspace_config_path);
+ if (BLI_exists(workspace_config_path)) {
+ has_path = true;
+ }
+ else {
+ workspace_config_file_path_from_folder_id(bmain, BLENDER_DATAFILES, workspace_config_path);
+ if (BLI_exists(workspace_config_path)) {
+ has_path = true;
+ }
+ }
+
+ return has_path ? BKE_blendfile_workspace_config_read(workspace_config_path, reports) : NULL;
+}
+
+static void workspace_append_button(
+ uiLayout *layout, wmOperatorType *ot_append, const WorkSpace *workspace, const Main *from_main)
+{
+ const ID *id = (ID *)workspace;
+ PointerRNA opptr;
+ char lib_path[FILE_MAX_LIBEXTRA];
+
+ BLI_path_join(
+ lib_path, sizeof(lib_path), from_main->name, BKE_idcode_to_name(GS(id->name)), NULL);
+
+ BLI_assert(STREQ(ot_append->idname, "WM_OT_append"));
+ uiItemFullO_ptr(
+ layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL,
+ WM_OP_EXEC_DEFAULT, 0, &opptr);
+ RNA_string_set(&opptr, "directory", lib_path);
+ RNA_string_set(&opptr, "filename", id->name + 2);
+ RNA_boolean_set(&opptr, "autoselect", false);
+}
+
+ATTR_NONNULL(1, 2)
+static void workspace_config_file_append_buttons(
+ uiLayout *layout, const Main *bmain, ReportList *reports)
+{
+ WorkspaceConfigFileData *workspace_config = workspace_config_file_read(bmain, reports);
+
+ if (workspace_config) {
+ wmOperatorType *ot_append = WM_operatortype_find("WM_OT_append", true);
+
+ for (WorkSpace *workspace = workspace_config->workspaces.first; workspace; workspace = workspace->id.next) {
+ workspace_append_button(layout, ot_append, workspace, workspace_config->main);
+ }
+
+ BKE_blendfile_workspace_config_data_free(workspace_config);
+ }
+}
+
+static int workspace_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ const Main *bmain = CTX_data_main(C);
+
+ uiPopupMenu *pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ uiItemO(layout, "Duplicate Current", ICON_NONE, "WORKSPACE_OT_workspace_duplicate");
+ uiItemS(layout);
+ workspace_config_file_append_buttons(layout, bmain, op->reports);
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+}
+
+static void WORKSPACE_OT_workspace_add_menu(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Workspace";
+ ot->description = "Add a new workspace by duplicating the current one or appending one "
+ "from the user configuration";
+ ot->idname = "WORKSPACE_OT_workspace_add_menu";
+
+ /* api callbacks */
+ ot->invoke = workspace_add_invoke;
+}
+
+void ED_operatortypes_workspace(void)
+{
+ WM_operatortype_append(WORKSPACE_OT_workspace_duplicate);
+ WM_operatortype_append(WORKSPACE_OT_workspace_delete);
+ WM_operatortype_append(WORKSPACE_OT_workspace_add_menu);
+}
+
+/** \} Workspace Operators */
diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c
new file mode 100644
index 00000000000..d84df160125
--- /dev/null
+++ b/source/blender/editors/screen/workspace_layout_edit.c
@@ -0,0 +1,197 @@
+/*
+ * ***** 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/screen/workspace_layout_edit.c
+ * \ingroup edscr
+ */
+
+#include <stdlib.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_workspace_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_screen.h"
+#include "BKE_workspace.h"
+
+#include "WM_api.h"
+
+#include "ED_screen.h"
+
+#include "screen_intern.h"
+
+/**
+ * Empty screen, with 1 dummy area without spacedata. Uses window size.
+ */
+WorkSpaceLayout *ED_workspace_layout_add(
+ WorkSpace *workspace,
+ wmWindow *win,
+ const char *name)
+{
+ const int winsize_x = WM_window_pixels_x(win);
+ const int winsize_y = WM_window_pixels_y(win);
+
+ bScreen *screen = screen_add(name, winsize_x, winsize_y);
+ WorkSpaceLayout *layout = BKE_workspace_layout_add(workspace, screen, name);
+
+ return layout;
+}
+
+WorkSpaceLayout *ED_workspace_layout_duplicate(
+ WorkSpace *workspace, const WorkSpaceLayout *layout_old,
+ wmWindow *win)
+{
+ bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
+ const char *name = BKE_workspace_layout_name_get(layout_old);
+ bScreen *screen_new;
+ WorkSpaceLayout *layout_new;
+
+ if (BKE_screen_is_fullscreen_area(screen_old)) {
+ return NULL; /* XXX handle this case! */
+ }
+
+ layout_new = ED_workspace_layout_add(workspace, win, name);
+ screen_new = BKE_workspace_layout_screen_get(layout_new);
+ screen_data_copy(screen_new, screen_old);
+
+ return layout_new;
+}
+
+static bool workspace_layout_delete_doit(
+ WorkSpace *workspace, WorkSpaceLayout *layout_old, WorkSpaceLayout *layout_new,
+ bContext *C)
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
+
+ ED_screen_change(C, screen_new);
+
+ if (BKE_workspace_active_layout_get(win->workspace_hook) != layout_old) {
+ BKE_workspace_layout_remove(bmain, workspace, layout_old);
+ return true;
+ }
+
+ return false;
+}
+
+bool workspace_layout_set_poll(const WorkSpaceLayout *layout)
+{
+ const bScreen *screen = BKE_workspace_layout_screen_get(layout);
+
+ return ((BKE_screen_is_used(screen) == false) &&
+ /* in typical usage temp screens should have a nonzero winid
+ * (all temp screens should be used, or closed & freed). */
+ (screen->temp == false) &&
+ (BKE_screen_is_fullscreen_area(screen) == false) &&
+ (screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT)));
+}
+
+static WorkSpaceLayout *workspace_layout_delete_find_new(const WorkSpaceLayout *layout_old)
+{
+ for (WorkSpaceLayout *layout_new = layout_old->prev; layout_new; layout_new = layout_new->next) {
+ if (workspace_layout_set_poll(layout_new)) {
+ return layout_new;
+ }
+ }
+
+ for (WorkSpaceLayout *layout_new = layout_old->next; layout_new; layout_new = layout_new->next) {
+ if (workspace_layout_set_poll(layout_new)) {
+ return layout_new;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * \warning Only call outside of area/region loops!
+ * \return true if succeeded.
+ */
+bool ED_workspace_layout_delete(
+ WorkSpace *workspace, WorkSpaceLayout *layout_old,
+ bContext *C)
+{
+ const bScreen *screen_old = BKE_workspace_layout_screen_get(layout_old);
+ WorkSpaceLayout *layout_new;
+
+ BLI_assert(BLI_findindex(BKE_workspace_layouts_get(workspace), layout_old) != -1);
+
+ /* don't allow deleting temp fullscreens for now */
+ if (BKE_screen_is_fullscreen_area(screen_old)) {
+ return false;
+ }
+
+ /* A layout/screen can only be in use by one window at a time, so as
+ * long as we are able to find a layout/screen that is unused, we
+ * can safely assume ours is not in use anywhere an delete it. */
+
+ layout_new = workspace_layout_delete_find_new(layout_old);
+
+ if (layout_new) {
+ return workspace_layout_delete_doit(workspace, layout_old, layout_new, C);
+ }
+
+ return false;
+}
+
+static bool workspace_layout_cycle_iter_cb(const WorkSpaceLayout *layout, void *UNUSED(arg))
+{
+ /* return false to stop iterator when we have found a layout to activate */
+ return !workspace_layout_set_poll(layout);
+}
+
+bool ED_workspace_layout_cycle(
+ WorkSpace *workspace, const short direction, bContext *C)
+{
+ wmWindow *win = CTX_wm_window(C);
+ WorkSpaceLayout *old_layout = BKE_workspace_active_layout_get(win->workspace_hook);
+ WorkSpaceLayout *new_layout;
+ const bScreen *old_screen = BKE_workspace_layout_screen_get(old_layout);
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (old_screen->temp || (sa && sa->full && sa->full->temp)) {
+ return false;
+ }
+
+ BLI_assert(ELEM(direction, 1, -1));
+ new_layout = BKE_workspace_layout_iter_circular(workspace, old_layout, workspace_layout_cycle_iter_cb,
+ NULL, (direction == -1) ? true : false);
+
+ if (new_layout && (old_layout != new_layout)) {
+ bScreen *new_screen = BKE_workspace_layout_screen_get(new_layout);
+
+ if (sa && sa->full) {
+ /* return to previous state before switching screens */
+ ED_screen_full_restore(C, sa); /* may free screen of old_layout */
+ }
+
+ ED_screen_change(C, new_screen);
+
+ return true;
+ }
+
+ return false;
+}
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 69f14c950bb..b3e125baae3 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -25,6 +25,7 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../depsgraph
../../gpu
../../imbuf
../../makesdna
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index f0d9a0bbb68..e1e90506299 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -54,14 +54,14 @@
#include "WM_api.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
#include "IMB_imbuf_types.h"
#include "ED_view3d.h"
-#include "GPU_basic_shader.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#include "UI_resources.h"
@@ -336,8 +336,8 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
glBindTexture(GL_TEXTURE_2D, target->overlay_texture);
if (refresh) {
- GLenum format = col ? GL_RGBA : GL_ALPHA;
- GLenum internalformat = col ? GL_RGBA8 : GL_ALPHA8;
+ GLenum format = col ? GL_RGBA : GL_RED;
+ GLenum internalformat = col ? GL_RGBA8 : GL_R8;
if (!init || (target->old_col != col)) {
glTexImage2D(GL_TEXTURE_2D, 0, internalformat, size, size, 0, format, GL_UNSIGNED_BYTE, buffer);
@@ -352,8 +352,6 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima
target->old_col = col;
}
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -460,18 +458,16 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
if (refresh) {
if (!init) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, size, size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, size, size, 0, GL_RED, GL_UNSIGNED_BYTE, buffer);
}
else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_RED, GL_UNSIGNED_BYTE, buffer);
}
if (buffer)
MEM_freeN(buffer);
}
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -605,22 +601,20 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
glDepthMask(GL_FALSE);
glDepthFunc(GL_ALWAYS);
- glMatrixMode(GL_TEXTURE);
- glPushMatrix();
- glLoadIdentity();
-
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ gpuPushMatrix();
+
/* brush rotation */
- glTranslatef(0.5, 0.5, 0);
- glRotatef((double)RAD2DEGF((primary) ? ups->brush_rotation : ups->brush_rotation_sec),
- 0.0, 0.0, 1.0);
- glTranslatef(-0.5f, -0.5f, 0);
+ gpuTranslate2f(x, y);
+ gpuRotate2D(-RAD2DEGF(primary ? ups->brush_rotation : ups->brush_rotation_sec));
+ gpuTranslate2f(-x, -y);
/* scale based on tablet pressure */
if (primary && ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
- glTranslatef(0.5f, 0.5f, 0);
- glScalef(1.0f / ups->size_pressure_value, 1.0f / ups->size_pressure_value, 1);
- glTranslatef(-0.5f, -0.5f, 0);
+ const float scale = ups->size_pressure_value;
+ gpuTranslate2f(x, y);
+ gpuScale2f(scale, scale);
+ gpuTranslate2f(-x, -y);
}
if (ups->draw_anchored) {
@@ -658,41 +652,46 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
quad.xmax = brush->mask_stencil_dimension[0];
quad.ymax = brush->mask_stencil_dimension[1];
}
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ gpuPushMatrix();
if (primary)
- glTranslate2fv(brush->stencil_pos);
+ gpuTranslate2fv(brush->stencil_pos);
else
- glTranslate2fv(brush->mask_stencil_pos);
- glRotatef(RAD2DEGF(mtex->rot), 0, 0, 1);
- glMatrixMode(GL_TEXTURE);
+ gpuTranslate2fv(brush->mask_stencil_pos);
+ gpuRotate2D(RAD2DEGF(mtex->rot));
}
/* set quad color. Colored overlay does not get blending */
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
if (col) {
- glColor4f(1.0, 1.0, 1.0, overlay_alpha / 100.0f);
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, overlay_alpha * 0.01f);
}
else {
- glColor4f(UNPACK3(U.sculpt_paint_overlay_col), overlay_alpha / 100.0f);
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_ALPHA_COLOR);
+ immUniformColor3fvAlpha(U.sculpt_paint_overlay_col, overlay_alpha * 0.01f);
}
/* draw textured quad */
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0);
- glVertex2f(quad.xmin, quad.ymin);
- glTexCoord2f(1, 0);
- glVertex2f(quad.xmax, quad.ymin);
- glTexCoord2f(1, 1);
- glVertex2f(quad.xmax, quad.ymax);
- glTexCoord2f(0, 1);
- glVertex2f(quad.xmin, quad.ymax);
- glEnd();
-
- glPopMatrix();
-
- if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) {
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ immUniform1i("image", GL_TEXTURE0);
+
+ immBegin(GWN_PRIM_TRI_FAN, 4);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, quad.xmin, quad.ymin);
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, quad.xmax, quad.ymin);
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, quad.xmax, quad.ymax);
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, quad.xmin, quad.ymax);
+ immEnd();
+
+ immUnbindProgram();
+
+ if (ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_VIEW)) {
+ gpuPopMatrix();
}
}
}
@@ -740,32 +739,41 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
/* scale based on tablet pressure */
if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
do_pop = true;
- glPushMatrix();
- glLoadIdentity();
- glTranslate2fv(center);
- glScalef(ups->size_pressure_value, ups->size_pressure_value, 1);
- glTranslatef(-center[0], -center[1], 0);
+ gpuPushMatrix();
+ gpuLoadIdentity();
+ gpuTranslate2fv(center);
+ gpuScaleUniform(ups->size_pressure_value);
+ gpuTranslate2f(-center[0], -center[1]);
}
- glColor4f(U.sculpt_paint_overlay_col[0],
- U.sculpt_paint_overlay_col[1],
- U.sculpt_paint_overlay_col[2],
- brush->cursor_overlay_alpha / 100.0f);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+
+ immUniformColor3fvAlpha(U.sculpt_paint_overlay_col, brush->cursor_overlay_alpha * 0.01f);
+
+ /* draw textured quad */
/* draw textured quad */
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0);
- glVertex2f(quad.xmin, quad.ymin);
- glTexCoord2f(1, 0);
- glVertex2f(quad.xmax, quad.ymin);
- glTexCoord2f(1, 1);
- glVertex2f(quad.xmax, quad.ymax);
- glTexCoord2f(0, 1);
- glVertex2f(quad.xmin, quad.ymax);
- glEnd();
+ immUniform1i("image", GL_TEXTURE0);
+
+ immBegin(GWN_PRIM_TRI_FAN, 4);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, quad.xmin, quad.ymin);
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, quad.xmax, quad.ymin);
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, quad.xmax, quad.ymax);
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, quad.xmin, quad.ymax);
+ immEnd();
+
+ immUnbindProgram();
if (do_pop)
- glPopMatrix();
+ gpuPopMatrix();
}
}
@@ -775,19 +783,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
/* color means that primary brush texture is colured and secondary is used for alpha/mask control */
bool col = ELEM(mode, ePaintTextureProjective, ePaintTexture2D, ePaintVertex) ? true : false;
eOverlayControlFlags flags = BKE_paint_get_overlay_flags();
- /* save lots of GL state
- * TODO: check on whether all of these are needed? */
- glPushAttrib(GL_COLOR_BUFFER_BIT |
- GL_CURRENT_BIT |
- GL_DEPTH_BUFFER_BIT |
- GL_ENABLE_BIT |
- GL_LINE_BIT |
- GL_POLYGON_BIT |
- GL_STENCIL_BUFFER_BIT |
- GL_TRANSFORM_BIT |
- GL_VIEWPORT_BIT |
- GL_TEXTURE_BIT);
-
+ gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_BLEND_BIT);
/* coloured overlay should be drawn separately */
if (col) {
@@ -805,86 +801,98 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
}
- glPopAttrib();
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ gpuPopAttrib();
}
-BLI_INLINE void draw_tri_point(float *co, float width, bool selected)
+BLI_INLINE void draw_tri_point(
+ unsigned int pos, float sel_col[4], float pivot_col[4],
+ float *co, float width, bool selected)
{
+ immUniformColor4fv(selected ? sel_col : pivot_col);
+
+ glLineWidth(3.0f);
+
float w = width / 2.0f;
- if (selected)
- UI_ThemeColor4(TH_VERTEX_SELECT);
- else
- UI_ThemeColor4(TH_PAINT_CURVE_PIVOT);
-
- glLineWidth(3.0);
-
- glBegin(GL_LINE_LOOP);
- glVertex2f(co[0], co[1] + w);
- glVertex2f(co[0] - w, co[1] - w);
- glVertex2f(co[0] + w, co[1] - w);
- glEnd();
-
- glColor4f(1.0, 1.0, 1.0, 0.5);
- glLineWidth(1.0);
-
- glBegin(GL_LINE_LOOP);
- glVertex2f(co[0], co[1] + w);
- glVertex2f(co[0] - w, co[1] - w);
- glVertex2f(co[0] + w, co[1] - w);
- glEnd();
+ float tri[3][2] = {
+ {co[0], co[1] + w},
+ {co[0] - w, co[1] - w},
+ {co[0] + w, co[1] - w},
+ };
+
+ immBegin(GWN_PRIM_LINE_LOOP, 3);
+ immVertex2fv(pos, tri[0]);
+ immVertex2fv(pos, tri[1]);
+ immVertex2fv(pos, tri[2]);
+ immEnd();
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ glLineWidth(1.0f);
+
+ immBegin(GWN_PRIM_LINE_LOOP, 3);
+ immVertex2fv(pos, tri[0]);
+ immVertex2fv(pos, tri[1]);
+ immVertex2fv(pos, tri[2]);
+ immEnd();
}
-BLI_INLINE void draw_rect_point(float *co, float width, bool selected)
+BLI_INLINE void draw_rect_point(
+ unsigned int pos, float sel_col[4], float handle_col[4],
+ float *co, float width, bool selected)
{
+ immUniformColor4fv(selected ? sel_col : handle_col);
+
+ glLineWidth(3.0f);
+
float w = width / 2.0f;
- if (selected)
- UI_ThemeColor4(TH_VERTEX_SELECT);
- else
- UI_ThemeColor4(TH_PAINT_CURVE_HANDLE);
- glLineWidth(3.0);
-
- glBegin(GL_LINE_LOOP);
- glVertex2f(co[0] + w, co[1] + w);
- glVertex2f(co[0] - w, co[1] + w);
- glVertex2f(co[0] - w, co[1] - w);
- glVertex2f(co[0] + w, co[1] - w);
- glEnd();
-
- glColor4f(1.0, 1.0, 1.0, 0.5);
- glLineWidth(1.0);
-
- glBegin(GL_LINE_LOOP);
- glVertex2f(co[0] + w, co[1] + w);
- glVertex2f(co[0] - w, co[1] + w);
- glVertex2f(co[0] - w, co[1] - w);
- glVertex2f(co[0] + w, co[1] - w);
- glEnd();
+ float minx = co[0] - w;
+ float miny = co[1] - w;
+ float maxx = co[0] + w;
+ float maxy = co[1] + w;
+
+ imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ glLineWidth(1.0f);
+
+ imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy);
}
-BLI_INLINE void draw_bezier_handle_lines(BezTriple *bez)
+BLI_INLINE void draw_bezier_handle_lines(unsigned int pos, float sel_col[4], BezTriple *bez)
{
- short line1[] = {0, 1};
- short line2[] = {1, 2};
-
- glVertexPointer(2, GL_FLOAT, 3 * sizeof(float), bez->vec);
- glColor4f(0.0, 0.0, 0.0, 0.5);
- glLineWidth(3.0);
- glDrawArrays(GL_LINE_STRIP, 0, 3);
-
- glLineWidth(1.0);
- if (bez->f1 || bez->f2)
- UI_ThemeColor4(TH_VERTEX_SELECT);
- else
- glColor4f(1.0, 1.0, 1.0, 0.5);
- glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line1);
- if (bez->f3 || bez->f2)
- UI_ThemeColor4(TH_VERTEX_SELECT);
- else
- glColor4f(1.0, 1.0, 1.0, 0.5);
- glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line2);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+ glLineWidth(3.0f);
+
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2fv(pos, bez->vec[0]);
+ immVertex2fv(pos, bez->vec[1]);
+ immVertex2fv(pos, bez->vec[2]);
+ immEnd();
+
+ glLineWidth(1.0f);
+
+ if (bez->f1 || bez->f2) {
+ immUniformColor4fv(sel_col);
+ }
+ else {
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ }
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(pos, bez->vec[0]);
+ immVertex2fv(pos, bez->vec[1]);
+ immEnd();
+
+ if (bez->f3 || bez->f2) {
+ immUniformColor4fv(sel_col);
+ }
+ else {
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ }
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(pos, bez->vec[1]);
+ immVertex2fv(pos, bez->vec[2]);
+ immEnd();
}
static void paint_draw_curve_cursor(Brush *brush)
@@ -896,18 +904,26 @@ static void paint_draw_curve_cursor(Brush *brush)
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glEnableClientState(GL_VERTEX_ARRAY);
/* draw the bezier handles and the curve segment between the current and next point */
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ float selec_col[4], handle_col[4], pivot_col[4];
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, selec_col);
+ UI_GetThemeColor4fv(TH_PAINT_CURVE_HANDLE, handle_col);
+ UI_GetThemeColor4fv(TH_PAINT_CURVE_PIVOT, pivot_col);
+
for (i = 0; i < pc->tot_points - 1; i++, cp++) {
int j;
PaintCurvePoint *cp_next = cp + 1;
float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
/* use color coding to distinguish handles vs curve segments */
- draw_bezier_handle_lines(&cp->bez);
- draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2);
- draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2);
- draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2);
+ draw_bezier_handle_lines(pos, selec_col, &cp->bez);
+ draw_tri_point(pos, selec_col, pivot_col, &cp->bez.vec[1][0], 10.0f, cp->bez.f2);
+ draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2);
+ draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2);
for (j = 0; j < 2; j++)
BKE_curve_forward_diff_bezier(
@@ -917,25 +933,35 @@ static void paint_draw_curve_cursor(Brush *brush)
cp_next->bez.vec[1][j],
data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
- glVertexPointer(2, GL_FLOAT, 0, data);
- glLineWidth(3.0);
- glColor4f(0.0, 0.0, 0.0, 0.5);
- glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1);
+ float (*v)[2] = (float(*)[2])data;
+
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+ glLineWidth(3.0f);
+ immBegin(GWN_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
+ for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
+ immVertex2fv(pos, v[j]);
+ }
+ immEnd();
- glLineWidth(1.0);
- glColor4f(0.9, 0.9, 1.0, 0.5);
- glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1);
+ immUniformColor4f(0.9f, 0.9f, 1.0f, 0.5f);
+ glLineWidth(1.0f);
+ immBegin(GWN_PRIM_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
+ for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
+ immVertex2fv(pos, v[j]);
+ }
+ immEnd();
}
/* draw last line segment */
- draw_bezier_handle_lines(&cp->bez);
- draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2);
- draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2);
- draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2);
+ draw_bezier_handle_lines(pos, selec_col, &cp->bez);
+ draw_tri_point(pos, selec_col, pivot_col, &cp->bez.vec[1][0], 10.0f, cp->bez.f2);
+ draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2);
+ draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
- glDisableClientState(GL_VERTEX_ARRAY);
+
+ immUnbindProgram();
}
}
@@ -989,11 +1015,6 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- ViewContext vc;
- float final_radius;
- float translation[2];
- float outline_alpha, *outline_col;
- float zoomx, zoomy;
/* check that brush drawing is enabled */
if (ommit_cursor_drawing(paint, mode, brush))
@@ -1001,6 +1022,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* can't use stroke vc here because this will be called during
* mouse over too, not just during a stroke */
+ ViewContext vc;
view3d_set_viewcontext(C, &vc);
if (vc.rv3d && (vc.rv3d->rflag & RV3D_NAVIGATING)) {
@@ -1013,15 +1035,15 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
return;
}
+ float zoomx, zoomy;
get_imapaint_zoom(C, &zoomx, &zoomy);
zoomx = max_ff(zoomx, zoomy);
/* set various defaults */
- translation[0] = x;
- translation[1] = y;
- outline_alpha = 0.5;
- outline_col = brush->add_col;
- final_radius = (BKE_brush_size_get(scene, brush) * zoomx);
+ const float *outline_col = brush->add_col;
+ const float outline_alpha = 0.5f;
+ float translation[2] = { x, y };
+ float final_radius = (BKE_brush_size_get(scene, brush) * zoomx);
/* don't calculate rake angles while a stroke is active because the rake variables are global and
* we may get interference with the stroke itself. For line strokes, such interference is visible */
@@ -1037,10 +1059,9 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
if ((mode == ePaintSculpt) && vc.obact->sculpt) {
float location[3];
int pixel_radius;
- bool hit;
/* test if brush is over the mesh */
- hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location, ups);
+ bool hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location, ups);
if (BKE_brush_use_locked_size(scene, brush))
BKE_brush_size_set(scene, brush, pixel_radius);
@@ -1067,24 +1088,25 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* make lines pretty */
glLineWidth(1.0f);
- glEnable(GL_BLEND);
+ glEnable(GL_BLEND); /* TODO: also set blend mode? */
glEnable(GL_LINE_SMOOTH);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* set brush color */
- glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha);
+ immUniformColor3fvAlpha(outline_col, outline_alpha);
/* draw brush outline */
- glTranslate2fv(translation);
-
- /* draw an inner brush */
if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) {
/* inner at full alpha */
- glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius * ups->size_pressure_value, 40);
+ imm_draw_circle_wire_2d(pos, translation[0], translation[1], final_radius * ups->size_pressure_value, 40);
/* outer at half alpha */
- glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha * 0.5f);
+ immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f);
}
- glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius, 40);
- glTranslatef(-translation[0], -translation[1], 0);
+ imm_draw_circle_wire_2d(pos, translation[0], translation[1], final_radius, 40);
+
+ immUnbindProgram();
/* restore GL state */
glDisable(GL_BLEND);
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index d085c6953da..8377b22756e 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -52,7 +52,7 @@
#include "BKE_paint.h"
#include "BKE_subsurf.h"
-#include "BIF_glutil.h"
+#include "DEG_depsgraph.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -323,12 +323,10 @@ static void clip_planes_from_rect(bContext *C,
{
ViewContext vc;
BoundBox bb;
- bglMats mats = {{0}};
view3d_operator_needs_opengl(C);
view3d_set_viewcontext(C, &vc);
- view3d_get_transformation(vc.ar, vc.rv3d, vc.obact, &mats);
- ED_view3d_clipping_calc(&bb, clip_planes, &mats, rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, rect);
negate_m4(clip_planes);
}
@@ -364,6 +362,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
Mesh *me = ob->data;
PartialVisAction action;
PartialVisArea area;
@@ -375,6 +374,8 @@ static int hide_show_exec(bContext *C, wmOperator *op)
rcti rect;
int totnode, i;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* read operator properties */
action = RNA_enum_get(op->ptr, "action");
area = RNA_enum_get(op->ptr, "area");
@@ -382,7 +383,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
clip_planes_from_rect(C, clip_planes, &rect);
- dm = mesh_get_derived_final(CTX_data_scene(C), ob, CD_MASK_BAREMESH);
+ dm = mesh_get_derived_final(&eval_ctx, CTX_data_scene(C), ob, CD_MASK_BAREMESH);
pbvh = dm->getPBVH(ob, dm);
ob->sculpt->pbvh = pbvh;
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 3ecece580ee..aebd0c10e9c 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -52,7 +52,6 @@
#include "BKE_colorband.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_brush.h"
#include "BKE_image.h"
@@ -61,6 +60,8 @@
#include "BKE_node.h"
#include "BKE_paint.h"
+#include "DEG_depsgraph.h"
+
#include "UI_interface.h"
#include "UI_view2d.h"
@@ -78,9 +79,9 @@
#include "GPU_draw.h"
#include "GPU_buffers.h"
+#include "GPU_immediate.h"
#include "BIF_gl.h"
-#include "BIF_glutil.h"
#include "IMB_colormanagement.h"
@@ -372,7 +373,7 @@ void ED_image_undo_restore(bContext *C, ListBase *lb)
ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- DAG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
BKE_image_release_ibuf(ima, ibuf, NULL);
}
@@ -721,12 +722,28 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
glLineWidth(4.0);
- glColor4ub(0, 0, 0, 255);
- sdrawline(x, y, pop->startmouse[0], pop->startmouse[1]);
+ immUniformColor4ub(0, 0, 0, 255);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2i(pos, x, y);
+ immVertex2i(pos, pop->startmouse[0], pop->startmouse[1]);
+ immEnd();
+
glLineWidth(2.0);
- glColor4ub(255, 255, 255, 255);
- sdrawline(x, y, pop->startmouse[0], pop->startmouse[1]);
+ immUniformColor4ub(255, 255, 255, 255);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2i(pos, x, y);
+ immVertex2i(pos, pop->startmouse[0], pop->startmouse[1]);
+ immEnd();
+
+ immUnbindProgram();
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
@@ -748,7 +765,8 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
/* initialize from context */
if (CTX_wm_region_view3d(C)) {
- Object *ob = OBACT;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
bool uvs, mat, tex, stencil;
if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) {
BKE_paint_data_warning(op->reports, uvs, mat, tex, stencil);
@@ -1039,16 +1057,20 @@ static void toggle_paint_cursor(bContext *C, int enable)
void ED_space_image_paint_update(wmWindowManager *wm, Scene *scene)
{
ToolSettings *settings = scene->toolsettings;
- wmWindow *win;
- ScrArea *sa;
ImagePaintSettings *imapaint = &settings->imapaint;
bool enabled = false;
- for (win = wm->windows.first; win; win = win->next)
- for (sa = win->screen->areabase.first; sa; sa = sa->next)
- if (sa->spacetype == SPACE_IMAGE)
- if (((SpaceImage *)sa->spacedata.first)->mode == SI_MODE_PAINT)
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ bScreen *screen = WM_window_get_active_screen(win);
+
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype == SPACE_IMAGE) {
+ if (((SpaceImage *)sa->spacedata.first)->mode == SI_MODE_PAINT) {
enabled = true;
+ }
+ }
+ }
+ }
if (enabled) {
BKE_paint_init(scene, ePaintTexture2D, PAINT_CURSOR_TEXTURE_PAINT);
@@ -1517,7 +1539,7 @@ void ED_imapaint_bucket_fill(struct bContext *C, float color[3], wmOperator *op)
ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
- DAG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index a1aad2bdc57..603b8f9a185 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -46,12 +46,13 @@
#include "BKE_colorband.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_brush.h"
#include "BKE_image.h"
#include "BKE_paint.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "ED_paint.h"
#include "ED_screen.h"
@@ -1359,7 +1360,7 @@ void paint_2d_redraw(const bContext *C, void *ps, bool final)
/* compositor listener deals with updating */
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
- DAG_id_tag_update(&s->image->id, 0);
+ DEG_id_tag_update(&s->image->id, 0);
}
else {
if (!s->sima || !s->sima->lock)
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index c309b223a81..7148469a9d8 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -65,7 +65,6 @@
#include "BKE_colorband.h"
#include "BKE_context.h"
#include "BKE_colortools.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_idprop.h"
#include "BKE_brush.h"
@@ -81,6 +80,8 @@
#include "BKE_scene.h"
#include "BKE_texture.h"
+#include "DEG_depsgraph.h"
+
#include "UI_interface.h"
#include "ED_mesh.h"
@@ -3421,12 +3422,15 @@ static void project_paint_bleed_add_face_user(
#endif
/* Return true if DM can be painted on, false otherwise */
-static bool proj_paint_state_dm_init(ProjPaintState *ps)
+static bool proj_paint_state_dm_init(const bContext *C, ProjPaintState *ps)
{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* Workaround for subsurf selection, try the display mesh first */
if (ps->source == PROJ_SRC_IMAGE_CAM) {
/* using render mesh, assume only camera was rendered from */
- ps->dm = mesh_create_derived_render(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
+ ps->dm = mesh_create_derived_render(&eval_ctx, ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
ps->dm_release = true;
}
else if (ps->ob->derivedFinal &&
@@ -3438,7 +3442,7 @@ static bool proj_paint_state_dm_init(ProjPaintState *ps)
}
else {
ps->dm = mesh_get_derived_final(
- ps->scene, ps->ob,
+ &eval_ctx, ps->scene, ps->ob,
ps->scene->customdata_mask | CD_MASK_MTFACE | (ps->do_face_sel ? CD_ORIGINDEX : 0));
ps->dm_release = true;
}
@@ -3488,7 +3492,7 @@ static void proj_paint_layer_clone_init(
/* use clone mtface? */
if (ps->do_layer_clone) {
- const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
+ const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
ps->dm_mloopuv_clone = MEM_mallocN(ps->dm_totpoly * sizeof(MLoopUV *), "proj_paint_mtfaces");
@@ -3818,7 +3822,7 @@ static void project_paint_prepare_all_faces(
/* run once per stroke before projection painting */
static void project_paint_begin(
- ProjPaintState *ps,
+ const bContext *C, ProjPaintState *ps,
const bool is_multi_view, const char symmetry_flag)
{
ProjPaintLayerClone layer_clone;
@@ -3841,7 +3845,7 @@ static void project_paint_begin(
/* paint onto the derived mesh */
if (ps->is_shared_user == false) {
- if (!proj_paint_state_dm_init(ps)) {
+ if (!proj_paint_state_dm_init(C, ps)) {
return;
}
}
@@ -3851,7 +3855,7 @@ static void project_paint_begin(
if (ps->do_layer_stencil || ps->do_stencil_brush) {
//int layer_num = CustomData_get_stencil_layer(&ps->dm->loopData, CD_MLOOPUV);
- int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
+ int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
if (layer_num != -1)
ps->dm_mloopuv_stencil = CustomData_get_layer_n(&ps->dm->loopData, CD_MLOOPUV, layer_num);
@@ -3939,7 +3943,7 @@ static void project_paint_end(ProjPaintState *ps)
ProjPaintImage *projIma;
for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL);
- DAG_id_tag_update(&projIma->ima->id, 0);
+ DEG_id_tag_update(&projIma->ima->id, 0);
}
}
@@ -5024,7 +5028,9 @@ void paint_proj_stroke(
/* clone gets special treatment here to avoid going through image initialization */
if (ps_handle->is_clone_cursor_pick) {
+ EvaluationContext eval_ctx;
Scene *scene = ps_handle->scene;
+ struct Depsgraph *graph = CTX_data_depsgraph(C);
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
float *cursor = ED_view3d_cursor3d_get(scene, v3d);
@@ -5032,8 +5038,11 @@ void paint_proj_stroke(
view3d_operator_needs_opengl(C);
- if (!ED_view3d_autodist(scene, ar, v3d, mval_i, cursor, false, NULL))
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ if (!ED_view3d_autodist(&eval_ctx, graph, ar, v3d, mval_i, cursor, false, NULL)) {
return;
+ }
ED_region_tag_redraw(ar);
@@ -5211,7 +5220,7 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
project_state_init(C, ob, ps, mode);
- if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) {
+ if (ps->ob == NULL) {
ps_handle->ps_views_tot = i + 1;
goto fail;
}
@@ -5235,7 +5244,7 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
PROJ_PAINT_STATE_SHARED_MEMCPY(ps, ps_handle->ps_views[0]);
}
- project_paint_begin(ps, is_multi_view, symmetry_flag_views[i]);
+ project_paint_begin(C, ps, is_multi_view, symmetry_flag_views[i]);
paint_proj_begin_clone(ps, mouse);
@@ -5313,11 +5322,12 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
{
Image *image = BLI_findlink(&CTX_data_main(C)->image, RNA_enum_get(op->ptr, "image"));
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
ProjPaintState ps = {NULL};
int orig_brush_size;
IDProperty *idgroup;
IDProperty *view_data = NULL;
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
bool uvs, mat, tex;
if (ob == NULL || ob->type != OB_MESH) {
@@ -5388,7 +5398,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
ED_image_undo_restore, ED_image_undo_free, NULL);
/* allocate and initialize spatial data structures */
- project_paint_begin(&ps, false, 0);
+ project_paint_begin(C, &ps, false, 0);
if (ps.dm == NULL) {
BKE_brush_size_set(scene, ps.brush, orig_brush_size);
@@ -5446,12 +5456,16 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
char filename[FILE_MAX];
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ EvaluationContext eval_ctx;
ToolSettings *settings = scene->toolsettings;
int w = settings->imapaint.screen_grab_size[0];
int h = settings->imapaint.screen_grab_size[1];
int maxsize;
char err_out[256] = "unknown";
+ CTX_data_eval_ctx(C, &eval_ctx);
+
RNA_string_get(op->ptr, "filepath", filename);
maxsize = GPU_max_texture_size();
@@ -5460,7 +5474,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
if (h > maxsize) h = maxsize;
ibuf = ED_view3d_draw_offscreen_imbuf(
- scene, CTX_wm_view3d(C), CTX_wm_region(C),
+ &eval_ctx, scene, view_layer, CTX_wm_view3d(C), CTX_wm_region(C),
w, h, IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
NULL, NULL, err_out);
if (!ibuf) {
@@ -5594,7 +5608,7 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m
}
me = BKE_mesh_from_object(ob);
- layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
+ layernum = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
if (layernum == 0) {
hasuvs = false;
@@ -5743,7 +5757,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
BKE_texpaint_slot_refresh_cache(scene, ma);
BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
- DAG_id_tag_update(&ma->id, 0);
+ DEG_id_tag_update(&ma->id, 0);
ED_area_tag_redraw(CTX_wm_area(C));
BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
@@ -5859,7 +5873,7 @@ static int texture_paint_delete_texture_paint_slot_exec(bContext *C, wmOperator
ma->mtex[slot->index] = NULL;
BKE_texpaint_slot_refresh_cache(scene, ma);
- DAG_id_tag_update(&ma->id, 0);
+ DEG_id_tag_update(&ma->id, 0);
WM_event_add_notifier(C, NC_MATERIAL, ma);
/* we need a notifier for data change since we change the displayed modifier uvs */
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -5917,7 +5931,7 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
- DAG_id_tag_update(ob->data, 0);
+ DEG_id_tag_update(ob->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 48fcf0596e3..28d9dfe13b0 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -155,10 +155,10 @@ void PAINT_OT_weight_sample_group(struct wmOperatorType *ot);
/* paint_vertex_proj.c */
struct VertProjHandle;
struct VertProjHandle *ED_vpaint_proj_handle_create(
- struct Scene *scene, struct Object *ob,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
struct DMCoNo **r_vcosnos);
void ED_vpaint_proj_handle_update(
- struct VertProjHandle *vp_handle,
+ const struct EvaluationContext *eval_ctx, struct VertProjHandle *vp_handle,
/* runtime vars */
struct ARegion *ar, const float mval_fl[2]);
void ED_vpaint_proj_handle_free(
@@ -237,7 +237,6 @@ bool paint_convert_bb_to_rect(struct rcti *rect,
* 2D screens-space bounding box into four 3D planes) */
void paint_calc_redraw_planes(float planes[4][4],
const struct ARegion *ar,
- struct RegionView3D *rv3d,
struct Object *ob,
const struct rcti *screen_rect);
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 3b1b993a3e3..0fec4c4fc80 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -35,8 +35,6 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "BIF_glutil.h"
-
#include "BLI_bitmap_draw_2d.h"
#include "BLI_math_matrix.h"
#include "BLI_math_geom.h"
@@ -52,6 +50,8 @@
#include "BKE_paint.h"
#include "BKE_subsurf.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -131,6 +131,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
struct Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
PaintMaskFloodMode mode;
float value;
PBVH *pbvh;
@@ -139,10 +140,12 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
bool multires;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
mode = RNA_enum_get(op->ptr, "mode");
value = RNA_float_get(op->ptr, "value");
- BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true);
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, false, true);
pbvh = ob->sculpt->pbvh;
multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
@@ -249,9 +252,9 @@ static void mask_box_select_task_cb(void *userdata, const int i)
int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *rect, bool select, bool UNUSED(extend))
{
+ EvaluationContext eval_ctx;
Sculpt *sd = vc->scene->toolsettings->sculpt;
BoundBox bb;
- bglMats mats = {{0}};
float clip_planes[4][4];
float clip_planes_final[4][4];
ARegion *ar = vc->ar;
@@ -265,15 +268,16 @@ int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *r
int totnode, symmpass;
int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
mode = PAINT_MASK_FLOOD_VALUE;
value = select ? 1.0 : 0.0;
/* transform the clip planes in object space */
- view3d_get_transformation(vc->ar, vc->rv3d, vc->obact, &mats);
- ED_view3d_clipping_calc(&bb, clip_planes, &mats, rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, vc->ar, vc->obact, rect);
negate_m4(clip_planes);
- BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true);
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, false, true);
pbvh = ob->sculpt->pbvh;
multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
@@ -409,9 +413,9 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
if (mcords) {
+ EvaluationContext eval_ctx;
float clip_planes[4][4], clip_planes_final[4][4];
BoundBox bb;
- bglMats mats = {{0}};
Object *ob;
ViewContext vc;
LassoMaskData data;
@@ -425,11 +429,12 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
PaintMaskFloodMode mode = RNA_enum_get(op->ptr, "mode");
float value = RNA_float_get(op->ptr, "value");
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* Calculations of individual vertices are done in 2D screen space to diminish the amount of
* calculations done. Bounding box PBVH collision is not computed against enclosing rectangle
* of lasso */
view3d_set_viewcontext(C, &vc);
- view3d_get_transformation(vc.ar, vc.rv3d, vc.obact, &mats);
/* lasso data calculations */
data.vc = &vc;
@@ -445,10 +450,10 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
mcords, mcords_tot,
mask_lasso_px_cb, &data);
- ED_view3d_clipping_calc(&bb, clip_planes, &mats, &data.rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, &data.rect);
negate_m4(clip_planes);
- BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true);
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, false, true);
pbvh = ob->sculpt->pbvh;
multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 2c8e88e3ccb..dacaea6a96e 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -51,6 +51,7 @@
#include "BKE_curve.h"
#include "BKE_colortools.h"
#include "BKE_image.h"
+#include "BKE_mesh.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -58,7 +59,7 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -145,9 +146,18 @@ static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata
if (stroke && brush) {
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glColor4ubv(paint->paint_cursor_col);
- sdrawline(x, y, (int)stroke->last_mouse_position[0],
- (int)stroke->last_mouse_position[1]);
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv(paint->paint_cursor_col);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, x, y);
+ immVertex2f(pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]);
+ immEnd();
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}
@@ -159,36 +169,35 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
PaintStroke *stroke = customdata;
glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
- GPU_basic_shader_line_width(3.0);
+ uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- glColor4ub(0, 0, 0, paint->paint_cursor_col[3]);
- if (stroke->constrain_line) {
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- stroke->constrained_pos[0], stroke->constrained_pos[1]);
- }
- else {
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- x, y);
- }
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ const float alpha = (float)paint->paint_cursor_col[3] / 255.0f;
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.0f, 0.0f, 0.0f, alpha}, {1.0f, 1.0f, 1.0f, alpha}}, 2);
+ immUniform1f("dash_width", 6.0f);
+
+ immBegin(GWN_PRIM_LINES, 2);
- glColor4ub(255, 255, 255, paint->paint_cursor_col[3]);
- GPU_basic_shader_line_width(1.0);
if (stroke->constrain_line) {
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- stroke->constrained_pos[0], stroke->constrained_pos[1]);
+ immVertex2f(shdr_pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]);
+ immVertex2f(shdr_pos, stroke->constrained_pos[0], stroke->constrained_pos[1]);
}
else {
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- x, y);
+ immVertex2f(shdr_pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]);
+ immVertex2f(shdr_pos, x, y);
}
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ immEnd();
+
+ immUnbindProgram();
- glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 1c2ab442e95..57a3044cc2b 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -56,11 +56,13 @@
#include "BKE_paint.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "GPU_glew.h"
+#include "GPU_matrix.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
@@ -130,17 +132,12 @@ bool paint_convert_bb_to_rect(rcti *rect,
* 2D screens-space bounding box into four 3D planes) */
void paint_calc_redraw_planes(float planes[4][4],
const ARegion *ar,
- RegionView3D *rv3d,
Object *ob,
const rcti *screen_rect)
{
BoundBox bb;
- bglMats mats;
rcti rect;
- memset(&bb, 0, sizeof(BoundBox));
- view3d_get_transformation(ar, rv3d, ob, &mats);
-
/* use some extra space just in case */
rect = *screen_rect;
rect.xmin -= 2;
@@ -148,7 +145,7 @@ void paint_calc_redraw_planes(float planes[4][4],
rect.ymin -= 2;
rect.ymax += 2;
- ED_view3d_clipping_calc(&bb, planes, &mats, &rect);
+ ED_view3d_clipping_calc(&bb, planes, ar, ob, &rect);
negate_m4(planes);
}
@@ -277,9 +274,9 @@ static void imapaint_tri_weights(float matrix[4][4], GLint view[4],
}
/* compute uv coordinates of mouse in face */
-static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2])
+static void imapaint_pick_uv(EvaluationContext *eval_ctx, Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2])
{
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH);
const int tottri = dm->getNumLoopTri(dm);
int i, findex;
float p[2], w[3], absw, minabsw;
@@ -293,8 +290,8 @@ static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, c
/* get the needed opengl matrices */
glGetIntegerv(GL_VIEWPORT, view);
- glGetFloatv(GL_MODELVIEW_MATRIX, (float *)matrix);
- glGetFloatv(GL_PROJECTION_MATRIX, (float *)proj);
+ gpuGetModelViewMatrix(matrix);
+ gpuGetProjectionMatrix(proj);
view[0] = view[1] = 0;
mul_m4_m4m4(matrix, matrix, ob->obmat);
mul_m4_m4m4(matrix, proj, matrix);
@@ -355,13 +352,15 @@ static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, c
}
/* returns 0 if not found, otherwise 1 */
-static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *r_index, unsigned int totpoly)
+static int imapaint_pick_face(
+ const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mval[2],
+ unsigned int *r_index, unsigned int totpoly)
{
if (totpoly == 0)
return 0;
/* sample only on the exact position */
- *r_index = ED_view3d_backbuf_sample(vc, mval[0], mval[1]);
+ *r_index = ED_view3d_backbuf_sample(eval_ctx, vc, mval[0], mval[1]);
if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) {
return 0;
@@ -427,6 +426,7 @@ void flip_qt_qt(float out[4], const float in[4], const char symm)
void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_proj, bool use_palette)
{
Scene *scene = CTX_data_scene(C);
+ EvaluationContext eval_ctx;
Paint *paint = BKE_paint_get_active_from_context(C);
Palette *palette = BKE_paint_palette(paint);
PaletteColor *color = NULL;
@@ -434,6 +434,8 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
unsigned int col;
const unsigned char *cp;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
CLAMP(x, 0, ar->winx);
CLAMP(y, 0, ar->winy);
@@ -450,14 +452,15 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
if (CTX_wm_view3d(C) && texpaint_proj) {
/* first try getting a colour directly from the mesh faces if possible */
- Object *ob = OBACT;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
bool sample_success = false;
ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
if (ob) {
Mesh *me = (Mesh *)ob->data;
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ DerivedMesh *dm = mesh_get_derived_final(&eval_ctx, scene, ob, CD_MASK_BAREMESH);
ViewContext vc;
const int mval[2] = {x, y};
@@ -469,7 +472,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
view3d_operator_needs_opengl(C);
- if (imapaint_pick_face(&vc, mval, &faceindex, totpoly)) {
+ if (imapaint_pick_face(&eval_ctx, &vc, mval, &faceindex, totpoly)) {
Image *image;
if (use_material)
@@ -482,7 +485,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
if (ibuf && ibuf->rect) {
float uv[2];
float u, v;
- imapaint_pick_uv(scene, ob, faceindex, mval, uv);
+ imapaint_pick_uv(&eval_ctx, scene, ob, faceindex, mval, uv);
sample_success = true;
u = fmodf(uv[0], 1.0f);
@@ -564,8 +567,9 @@ static int brush_curve_preset_exec(bContext *C, wmOperator *op)
if (br) {
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
- BKE_paint_invalidate_cursor_overlay(scene, br->curve);
+ BKE_paint_invalidate_cursor_overlay(scene, view_layer, br->curve);
}
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index d61777a6d12..d9df8c78ba9 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -54,7 +54,6 @@
#include "BKE_brush.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_deform.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
@@ -63,6 +62,8 @@
#include "BKE_report.h"
#include "BKE_subsurf.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -937,11 +938,11 @@ static void do_weight_paint_vertex(
/* Toggle operator for turning vertex paint mode on or off (copied from sculpt.c) */
-static void vertex_paint_init_session(Scene *scene, Object *ob)
+static void vertex_paint_init_session(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
if (ob->sculpt == NULL) {
ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
- BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, 0, false);
+ BKE_sculpt_update_mesh_elements(eval_ctx, scene, scene->toolsettings->sculpt, ob, 0, false);
}
}
@@ -1070,6 +1071,10 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
paint_cursor_delete_textures();
}
else {
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
ob->mode |= mode_flag;
if (wp == NULL)
@@ -1087,15 +1092,17 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
if (ob->sculpt) {
BKE_sculptsession_free(ob);
}
- vertex_paint_init_session(scene, ob);
+ vertex_paint_init_session(&eval_ctx, scene, ob);
}
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+
/* Weightpaint works by overriding colors in mesh,
* so need to make sure we recalc on enter and
* exit (exit needs doing regardless because we
* should redeform).
*/
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
@@ -1278,11 +1285,14 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
bool *defbase_sel;
SculptSession *ss = ob->sculpt;
VPaint *vp = CTX_data_tool_settings(C)->wpaint;
+ EvaluationContext eval_ctx;
if (ED_wpaint_ensure_data(C, op->reports, WPAINT_ENSURE_MIRROR, &vgroup_index) == false) {
return false;
}
+ CTX_data_eval_ctx(C, &eval_ctx);
+
{
/* check if we are attempting to paint onto a locked vertex group,
* and other options disallow it from doing anything useful */
@@ -1381,7 +1391,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
}
/* If not previously created, create vertex/weight paint mode session data */
- vertex_paint_init_session(scene, ob);
+ vertex_paint_init_session(&eval_ctx, scene, ob);
vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
vertex_paint_init_session_data(ts, ob);
@@ -2021,7 +2031,9 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* also needed for "View Selected" on last stroke */
paint_last_stroke_update(scene, vc->ar, mval);
- DAG_id_tag_update(ob->data, 0);
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+
+ DEG_id_tag_update(ob->data, 0);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
swap_m4m4(wpd->vc.rv3d->persmat, mat);
@@ -2085,7 +2097,7 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
}
}
- DAG_id_tag_update(ob->data, 0);
+ DEG_id_tag_update(ob->data, 0);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -2204,6 +2216,10 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
paint_cursor_delete_textures();
}
else {
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
ob->mode |= mode_flag;
ED_mesh_color_ensure(me, NULL);
@@ -2223,11 +2239,13 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
}
BKE_sculptsession_free(ob);
}
- vertex_paint_init_session(scene, ob);
+ vertex_paint_init_session(&eval_ctx, scene, ob);
}
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+
/* update modifier stack for mapping requirements */
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
@@ -2313,6 +2331,9 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
Object *ob = CTX_data_active_object(C);
Mesh *me;
SculptSession *ss = ob->sculpt;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
/* context checks could be a poll() */
me = BKE_mesh_from_object(ob);
@@ -2360,12 +2381,12 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
/* Create projection handle */
if (vpd->is_texbrush) {
ob->sculpt->building_vp_handle = true;
- vpd->vp_handle = ED_vpaint_proj_handle_create(scene, ob, &vpd->vertexcosnos);
+ vpd->vp_handle = ED_vpaint_proj_handle_create(&eval_ctx, scene, ob, &vpd->vertexcosnos);
ob->sculpt->building_vp_handle = false;
}
/* If not previously created, create vertex/weight paint mode session data */
- vertex_paint_init_session(scene, ob);
+ vertex_paint_init_session(&eval_ctx, scene, ob);
vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
vertex_paint_init_session_data(ts, ob);
@@ -2937,6 +2958,8 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
swap_m4m4(vc->rv3d->persmat, mat);
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+
if (vp->paint.brush->vertexpaint_tool == PAINT_BLEND_SMEAR) {
memcpy(vpd->smear.color_prev, vpd->smear.color_curr, sizeof(uint) * ((Mesh *)ob->data)->totloop);
}
@@ -2950,7 +2973,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if (vpd->use_fast_update == false) {
/* recalculate modifier stack to get new colors, slow,
* avoid this if we can! */
- DAG_id_tag_update(ob->data, 0);
+ DEG_id_tag_update(ob->data, 0);
}
else {
/* If using new VBO drawing, mark mcol as dirty to force colors gpu buffer refresh! */
@@ -3049,3 +3072,4 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot)
paint_stroke_operator_properties(ot);
}
+
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
index b69ca32e5af..d7668a48139 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
@@ -33,10 +33,11 @@
#include "BLI_math_color.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_mesh.h"
#include "BKE_deform.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -97,7 +98,7 @@ static bool vertex_color_set(Object *ob, uint paintcol)
/* remove stale me->mcol, will be added later */
BKE_mesh_tessface_clear(me);
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
return true;
}
@@ -168,7 +169,7 @@ static bool vertex_paint_from_weight(Object *ob)
} while (j < mp->totloop);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
return true;
}
@@ -304,7 +305,7 @@ static bool vertex_color_smooth(Object *ob)
MEM_freeN(mlooptag);
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
return true;
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c
index 398512287c4..a8045232e05 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c
@@ -38,9 +38,10 @@
#include "IMB_colormanagement.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_mesh.h"
+#include "DEG_depsgraph.h"
+
#include "ED_mesh.h"
#include "paint_intern.h" /* own include */
@@ -87,7 +88,7 @@ bool ED_vpaint_color_transform(
/* remove stale me->mcol, will be added later */
BKE_mesh_tessface_clear(me);
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
return true;
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_proj.c b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
index c939eb6df35..999c9dc7880 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_proj.c
@@ -42,6 +42,8 @@
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
+#include "DEG_depsgraph.h"
+
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -98,13 +100,14 @@ static void vpaint_proj_dm_map_cosnos_init__map_cb(void *userData, int index, co
}
}
-static void vpaint_proj_dm_map_cosnos_init(Scene *scene, Object *ob,
- struct VertProjHandle *vp_handle)
+static void vpaint_proj_dm_map_cosnos_init(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
+ struct VertProjHandle *vp_handle)
{
Mesh *me = ob->data;
DerivedMesh *dm;
- dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
+ dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
if (dm->foreachMappedVert) {
memset(vp_handle->vcosnos, 0, sizeof(DMCoNo) * me->totvert);
@@ -169,8 +172,9 @@ static void vpaint_proj_dm_map_cosnos_update__map_cb(void *userData, int index,
}
}
-static void vpaint_proj_dm_map_cosnos_update(struct VertProjHandle *vp_handle,
- ARegion *ar, const float mval_fl[2])
+static void vpaint_proj_dm_map_cosnos_update(
+ const struct EvaluationContext *eval_ctx, struct VertProjHandle *vp_handle,
+ ARegion *ar, const float mval_fl[2])
{
struct VertProjUpdate vp_update = {vp_handle, ar, mval_fl};
@@ -182,7 +186,7 @@ static void vpaint_proj_dm_map_cosnos_update(struct VertProjHandle *vp_handle,
/* quick sanity check - we shouldn't have to run this if there are no modifiers */
BLI_assert(BLI_listbase_is_empty(&ob->modifiers) == false);
- dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
+ dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
/* highly unlikely this will become unavailable once painting starts (perhaps with animated modifiers) */
if (LIKELY(dm->foreachMappedVert)) {
@@ -198,8 +202,9 @@ static void vpaint_proj_dm_map_cosnos_update(struct VertProjHandle *vp_handle,
/* -------------------------------------------------------------------- */
/* Public Functions */
-struct VertProjHandle *ED_vpaint_proj_handle_create(Scene *scene, Object *ob,
- DMCoNo **r_vcosnos)
+struct VertProjHandle *ED_vpaint_proj_handle_create(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
+ DMCoNo **r_vcosnos)
{
struct VertProjHandle *vp_handle = MEM_mallocN(sizeof(struct VertProjHandle), __func__);
Mesh *me = ob->data;
@@ -209,7 +214,7 @@ struct VertProjHandle *ED_vpaint_proj_handle_create(Scene *scene, Object *ob,
vp_handle->use_update = false;
/* sets 'use_update' if needed */
- vpaint_proj_dm_map_cosnos_init(scene, ob, vp_handle);
+ vpaint_proj_dm_map_cosnos_init(eval_ctx, scene, ob, vp_handle);
if (vp_handle->use_update) {
vp_handle->dists_sq = MEM_mallocN(sizeof(float) * me->totvert, __func__);
@@ -228,11 +233,12 @@ struct VertProjHandle *ED_vpaint_proj_handle_create(Scene *scene, Object *ob,
return vp_handle;
}
-void ED_vpaint_proj_handle_update(struct VertProjHandle *vp_handle,
- ARegion *ar, const float mval_fl[2])
+void ED_vpaint_proj_handle_update(
+ const struct EvaluationContext *eval_ctx, struct VertProjHandle *vp_handle,
+ ARegion *ar, const float mval_fl[2])
{
if (vp_handle->use_update) {
- vpaint_proj_dm_map_cosnos_update(vp_handle, ar, mval_fl);
+ vpaint_proj_dm_map_cosnos_update(eval_ctx, vp_handle, ar, mval_fl);
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
index 2afbecbc6fb..1348847167c 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -49,7 +49,6 @@
#include "BKE_DerivedMesh.h"
#include "BKE_brush.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_deform.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
@@ -59,6 +58,8 @@
#include "BKE_report.h"
#include "BKE_colortools.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -130,9 +131,13 @@ static int weight_from_bones_exec(bContext *C, wmOperator *op)
Mesh *me = ob->data;
int type = RNA_enum_get(op->ptr, "type");
- create_vgroups_from_armature(op->reports, scene, ob, armob, type, (me->editflag & ME_EDIT_MIRROR_X));
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ create_vgroups_from_armature(op->reports, &eval_ctx, scene, ob, armob, type, (me->editflag & ME_EDIT_MIRROR_X));
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
return OPERATOR_FINISHED;
@@ -366,7 +371,7 @@ static int weight_sample_group_exec(bContext *C, wmOperator *op)
BLI_assert(type + 1 >= 0);
vc.obact->actdef = type + 1;
- DAG_id_tag_update(&vc.obact->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&vc.obact->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, vc.obact);
return OPERATOR_FINISHED;
}
@@ -482,7 +487,7 @@ static bool weight_paint_set(Object *ob, float paintweight)
wpaint_prev_destroy(&wpp);
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
return true;
}
@@ -694,7 +699,7 @@ static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEven
}
MEM_freeN(vert_cache);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
else if (ret & OPERATOR_FINISHED) {
@@ -720,7 +725,12 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
float sco_start[2] = {x_start, y_start};
float sco_end[2] = {x_end, y_end};
const bool is_interactive = (gesture != NULL);
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
+
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ DerivedMesh *dm = mesh_get_derived_final(&eval_ctx, scene, ob, scene->customdata_mask);
DMGradient_userData data = {NULL};
@@ -792,7 +802,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
dm->foreachMappedVert(dm, gradientVertUpdate__mapFunc, &data, DM_FOREACH_NOP);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
if (is_interactive == false) {
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 53d7684e331..6e08f47f60d 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -56,7 +56,6 @@
#include "BKE_brush.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_key.h"
@@ -72,6 +71,8 @@
#include "BKE_subsurf.h"
#include "BKE_colortools.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -491,8 +492,7 @@ bool sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d,
return 1;
}
-void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar,
- RegionView3D *rv3d, Object *ob)
+void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, Object *ob)
{
PBVH *pbvh = ob->sculpt->pbvh;
/* copy here, original will be used below */
@@ -500,7 +500,7 @@ void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar,
sculpt_extend_redraw_rect_previous(ob, &rect);
- paint_calc_redraw_planes(planes, ar, rv3d, ob, &rect);
+ paint_calc_redraw_planes(planes, ar, ob, &rect);
/* we will draw this rect, so now we can set it as the previous partial rect.
* Note that we don't update with the union of previous/current (rect), only with
@@ -2045,6 +2045,10 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
mul_v3_v3(offset, ss->cache->scale);
mul_v3_fl(offset, bstrength);
+ /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
+ * initialize before threads so they can do curve mapping */
+ curvemapping_initialize(brush->curve);
+
/* threaded loop over nodes */
SculptThreadedTaskData data = {
.sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
@@ -4409,10 +4413,13 @@ static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob)
SculptSession *ss = ob->sculpt;
if (ss->kb || ss->modifiers_active) {
+ EvaluationContext eval_ctx;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- BKE_sculpt_update_mesh_elements(CTX_data_scene(C), sd, ob,
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ BKE_sculpt_update_mesh_elements(&eval_ctx, CTX_data_scene(C), sd, ob,
sculpt_any_smooth_mode(brush, ss->cache, 0), false);
}
}
@@ -4618,12 +4625,15 @@ static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ EvaluationContext eval_ctx;
SculptSession *ss = CTX_data_active_object(C)->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
int mode = RNA_enum_get(op->ptr, "mode");
bool is_smooth;
bool need_mask = false;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
need_mask = true;
}
@@ -4632,7 +4642,7 @@ static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op)
sculpt_brush_init_tex(scene, sd, ss);
is_smooth = sculpt_any_smooth_mode(brush, NULL, mode);
- BKE_sculpt_update_mesh_elements(scene, sd, ob, is_smooth, need_mask);
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, is_smooth, need_mask);
return 1;
}
@@ -4676,7 +4686,7 @@ static void sculpt_flush_update(bContext *C)
GPU_drawobject_free(ob->derivedFinal);
if (ss->kb || ss->modifiers_active) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
ED_region_tag_redraw(ar);
}
else {
@@ -4706,6 +4716,9 @@ static void sculpt_flush_update(bContext *C)
ED_region_tag_redraw_partial(ar, &r);
}
}
+
+ /* 2.8x - avoid full mesh update! */
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_SCULPT_COORDS);
}
/* Returns whether the mouse/stylus is over the mesh (1)
@@ -4789,7 +4802,7 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st
* Could be optimized later, but currently don't think it's so
* much common scenario.
*
- * Same applies to the DAG_id_tag_update() invoked from
+ * Same applies to the DEG_id_tag_update() invoked from
* sculpt_flush_update().
*/
if (ss->modifiers_active) {
@@ -4863,7 +4876,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
/* try to avoid calling this, only for e.g. linked duplicates now */
if (((Mesh *)ob->data)->id.us > 1)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
@@ -5059,10 +5072,13 @@ void sculpt_update_after_dynamic_topology_toggle(bContext *C)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
Sculpt *sd = scene->toolsettings->sculpt;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* Create the PBVH */
- BKE_sculpt_update_mesh_elements(scene, sd, ob, false, false);
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, false, false);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
@@ -5396,11 +5412,15 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot)
/**** Toggle operator for turning sculpt mode on or off ****/
-static void sculpt_init_session(Scene *scene, Object *ob)
+static void sculpt_init_session(const bContext *C, Scene *scene, Object *ob)
{
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
- BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, 0, false);
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, scene->toolsettings->sculpt, ob, 0, false);
}
@@ -5436,7 +5456,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
* a consistent state.
*/
if (true || flush_recalc || (ob->sculpt && ob->sculpt->bm)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
@@ -5461,7 +5481,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
ob->mode |= mode_flag;
if (flush_recalc)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* Create persistent sculpt mode data */
if (!ts->sculpt) {
@@ -5492,7 +5512,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
if (ob->sculpt)
BKE_sculptsession_free(ob);
- sculpt_init_session(scene, ob);
+ sculpt_init_session(C, scene, ob);
/* Mask layer is required */
if (mmd) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 44bd872d107..a10c7477dc6 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -51,12 +51,12 @@
#include "BKE_ccg.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_multires.h"
#include "BKE_paint.h"
#include "BKE_key.h"
#include "BKE_mesh.h"
#include "BKE_subsurf.h"
+#include "DEG_depsgraph.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -127,9 +127,12 @@ static bool sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoN
Scene *scene = CTX_data_scene(C);
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
SculptSession *ss = ob->sculpt;
MVert *mvert;
int *index;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
if (unode->maxvert) {
/* regular mesh restore */
@@ -143,7 +146,7 @@ static bool sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoN
if (kb) {
ob->shapenr = BLI_findindex(&key->block, kb) + 1;
- BKE_sculpt_update_mesh_elements(scene, sd, ob, 0, false);
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, 0, false);
WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
}
else {
@@ -451,6 +454,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
Scene *scene = CTX_data_scene(C);
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
DerivedMesh *dm;
SculptSession *ss = ob->sculpt;
SculptUndoNode *unode;
@@ -458,6 +462,8 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
bool need_mask = false;
bool partial_update = true;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
for (unode = lb->first; unode; unode = unode->next) {
if (STREQ(unode->idname, ob->id.name)) {
if (unode->type == SCULPT_UNDO_MASK) {
@@ -469,10 +475,10 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
}
}
- BKE_sculpt_update_mesh_elements(scene, sd, ob, 0, need_mask);
+ BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, 0, need_mask);
/* call _after_ sculpt_update_mesh_elements() which may update 'ob->derivedFinal' */
- dm = mesh_get_derived_final(scene, ob, 0);
+ dm = mesh_get_derived_final(&eval_ctx, scene, ob, 0);
if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss))
return;
@@ -555,7 +561,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
}
if (tag_update) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else {
sculpt_update_object_bounding_box(ob);
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index abc4b28ee50..c9453f94e61 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -46,15 +46,19 @@
#include "BKE_paint.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_mesh_mapping.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+
#include "ED_screen.h"
#include "ED_image.h"
#include "ED_mesh.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -64,9 +68,6 @@
#include "paint_intern.h"
#include "uvedit_intern.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
#include "UI_view2d.h"
#define MARK_BOUNDARY 1
@@ -173,7 +174,7 @@ static int uv_sculpt_brush_poll_do(bContext *C, const bool check_region)
}
em = BKE_editmesh_from_object(obedit);
- ret = EDBM_mtexpoly_check(em);
+ ret = EDBM_uv_check(em);
if (ret) {
ARegion *ar = CTX_wm_region(C);
@@ -212,18 +213,17 @@ static void brush_drawcursor_uvsculpt(bContext *C, int x, int y, void *UNUSED(cu
alpha *= (size - PX_SIZE_FADE_MIN) / (PX_SIZE_FADE_MAX - PX_SIZE_FADE_MIN);
}
- glPushMatrix();
-
- glTranslatef((float)x, (float)y, 0.0f);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fvAlpha(brush->add_col, alpha);
- glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size, 40);
+ imm_draw_circle_wire_2d(pos, (float)x, (float)y, size, 40);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
- glPopMatrix();
+ immUnbindProgram();
}
#undef PX_SIZE_FADE_MAX
#undef PX_SIZE_FADE_MIN
@@ -899,7 +899,7 @@ static int uv_sculpt_stroke_modal(bContext *C, wmOperator *op, const wmEvent *ev
ED_region_tag_redraw(CTX_wm_region(C));
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/editors/sound/CMakeLists.txt b/source/blender/editors/sound/CMakeLists.txt
index 535cd579030..9efdf11e8d7 100644
--- a/source/blender/editors/sound/CMakeLists.txt
+++ b/source/blender/editors/sound/CMakeLists.txt
@@ -39,7 +39,7 @@ set(SRC
)
if(WITH_AUDASPACE)
- add_definitions(${AUDASPACE_DEFINITIONS})
+ add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 0c349e6433e..daeb7823a43 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -67,7 +67,7 @@
#include "WM_types.h"
#ifdef WITH_AUDASPACE
-# include AUD_SPECIAL_H
+# include <AUD_Special.h>
#endif
#include "ED_sound.h"
@@ -311,6 +311,8 @@ static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
int oldfra = scene->r.cfra;
int cfra;
@@ -318,11 +320,11 @@ static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) {
scene->r.cfra = cfra;
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
}
scene->r.cfra = oldfra;
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c
index bfc808f6d83..80ec9107984 100644
--- a/source/blender/editors/space_action/action_buttons.c
+++ b/source/blender/editors/space_action/action_buttons.c
@@ -48,7 +48,6 @@
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_main.h"
#include "BKE_global.h"
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 0764f586de9..11ac1d60f39 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -61,6 +61,7 @@
#include "ED_keyframes_draw.h"
#include "action_intern.h"
+#include "GPU_immediate.h"
/* ************************************************************************* */
/* Channel List */
@@ -156,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];
@@ -194,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)
*/
@@ -205,6 +203,12 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* first backdrop strips */
y = (float)(-ACHANNEL_HEIGHT(ac));
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
glEnable(GL_BLEND);
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -223,28 +227,26 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* determine if channel is selected */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
-
+
if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
switch (ale->type) {
case ANIMTYPE_SUMMARY:
{
/* reddish color from NLA */
- UI_ThemeColor4(TH_ANIM_ACTIVE);
+ immUniformThemeColor(TH_ANIM_ACTIVE);
break;
}
case ANIMTYPE_SCENE:
case ANIMTYPE_OBJECT:
{
- if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45);
- else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22);
+ immUniformColor3ubvAlpha(col1b, sel ? 0x45 : 0x22);
break;
}
case ANIMTYPE_FILLACTD:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
{
- if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45);
- else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22);
+ immUniformColor3ubvAlpha(col2b, sel ? 0x45 : 0x22);
break;
}
case ANIMTYPE_GROUP:
@@ -252,17 +254,14 @@ 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 = (unsigned char *)agrp->cs.select;
- glColor4ub(cp[0], cp[1], cp[2], 0x45);
+ immUniformColor3ubvAlpha((unsigned char *)agrp->cs.select, 0x45);
}
else {
- unsigned char *cp = (unsigned char *)agrp->cs.solid;
- glColor4ub(cp[0], cp[1], cp[2], 0x1D);
+ immUniformColor3ubvAlpha((unsigned char *)agrp->cs.solid, 0x1D);
}
}
else {
- if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
- else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
+ immUniformColor3ubvAlpha(sel ? col1a : col2a, 0x22);
}
break;
}
@@ -270,53 +269,43 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
{
FCurve *fcu = ale->data;
if (show_group_colors && fcu->grp && fcu->grp->customCol) {
- unsigned char *cp = (unsigned char *)fcu->grp->cs.active;
-
- if (sel) glColor4ub(cp[0], cp[1], cp[2], 0x65);
- else glColor4ub(cp[0], cp[1], cp[2], 0x0B);
+ immUniformColor3ubvAlpha((unsigned char *)fcu->grp->cs.active, sel ? 0x65 : 0x0B);
}
else {
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
- else glColor4ub(col2[0], col2[1], col2[2], 0x22);
+ immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22);
}
break;
}
default:
{
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
- else glColor4ub(col2[0], col2[1], col2[2], 0x22);
- break;
+ immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22);
}
}
/* draw region twice: firstly backdrop, then the current range */
- glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
if (ac->datatype == ANIMCONT_ACTION)
- glRectf(act_start, (float)y - ACHANNEL_HEIGHT_HALF(ac), act_end, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immRectf(pos, act_start, (float)y - ACHANNEL_HEIGHT_HALF(ac), act_end, (float)y + ACHANNEL_HEIGHT_HALF(ac));
}
else if (ac->datatype == ANIMCONT_GPENCIL) {
/* frames less than one get less saturated background */
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
- else glColor4ub(col2[0], col2[1], col2[2], 0x22);
- glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22);
+ immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
/* frames one and higher get a saturated background */
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
- else glColor4ub(col2[0], col2[1], col2[2], 0x44);
- glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immUniformColor3ubvAlpha(sel ? col1 : col2, 0x44);
+ immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
}
else if (ac->datatype == ANIMCONT_MASK) {
/* TODO --- this is a copy of gpencil */
/* frames less than one get less saturated background */
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
- else glColor4ub(col2[0], col2[1], col2[2], 0x22);
- glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22);
+ immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
/* frames one and higher get a saturated background */
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
- else glColor4ub(col2[0], col2[1], col2[2], 0x44);
- glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immUniformColor3ubvAlpha(sel ? col1 : col2, 0x44);
+ immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
}
}
}
@@ -325,18 +314,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(GWN_PRIM_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) )
@@ -344,7 +344,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:
@@ -374,20 +374,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) {
- glColor3f(0.0f, 0.0f, 0.0f);
-
- glBegin(GL_LINES);
- glVertex2f(saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
- glVertex2f(saction->timeslide, v2d->cur.ymax);
- glEnd();
- }
+ /* free temporary channels used for drawing */
+ ANIM_animdata_freelist(&anim_data);
}
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 5cde224b7dc..50882571dad 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -308,7 +308,9 @@ static void action_header_region_draw(const bContext *C, ARegion *ar)
ED_region_header(C, ar);
}
-static void action_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void action_channel_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -351,7 +353,9 @@ static void action_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(
}
}
-static void action_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void action_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -391,7 +395,11 @@ static void action_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
if (wmn->action == NA_RENAME)
ED_region_tag_redraw(ar);
break;
-
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
default:
if (wmn->data == ND_KEYS)
ED_region_tag_redraw(ar);
@@ -400,7 +408,9 @@ static void action_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
}
/* editor level listener */
-static void action_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
+static void action_listener(
+ bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
+ WorkSpace *UNUSED(workspace))
{
SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
@@ -507,7 +517,9 @@ static void action_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
}
}
-static void action_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void action_header_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
// SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
@@ -559,7 +571,9 @@ static void action_buttons_area_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, NULL, -1, true);
}
-static void action_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void action_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index ac6e3123e4e..32f6ac40d12 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -55,6 +55,7 @@
#include "ED_paint.h"
#include "ED_physics.h"
#include "ED_render.h"
+#include "ED_scene.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_space_api.h"
@@ -65,6 +66,7 @@
#include "ED_clip.h"
#include "ED_mask.h"
#include "ED_sequencer.h"
+#include "ED_manipulator_library.h"
#include "io_ops.h"
@@ -99,6 +101,8 @@ void ED_spacetypes_init(void)
// ...
/* register operator types for screen and all spaces */
+ ED_operatortypes_workspace();
+ ED_operatortypes_scene();
ED_operatortypes_screen();
ED_operatortypes_anim();
ED_operatortypes_animchannels();
@@ -121,12 +125,26 @@ void ED_spacetypes_init(void)
ED_operatortypes_view2d();
ED_operatortypes_ui();
-
- /* register operators */
+
+ /* manipulator types */
+ ED_manipulatortypes_dial_3d();
+ ED_manipulatortypes_grab_3d();
+ ED_manipulatortypes_arrow_2d();
+ ED_manipulatortypes_arrow_3d();
+ ED_manipulatortypes_primitive_3d();
+ ED_manipulatortypes_cage_2d();
+ ED_manipulatortypes_cage_3d();
+
+ /* register types for operators and manipulators */
spacetypes = BKE_spacetypes_list();
for (type = spacetypes->first; type; type = type->next) {
- if (type->operatortypes)
+ /* init manipulator types first, operator-types need them */
+ if (type->manipulators) {
+ type->manipulators();
+ }
+ if (type->operatortypes) {
type->operatortypes();
+ }
}
/* register internal render callbacks */
@@ -251,7 +269,6 @@ void ED_region_draw_cb_draw(const bContext *C, ARegion *ar, int type)
for (rdc = ar->type->drawcalls.first; rdc; rdc = rdc->next) {
if (rdc->type == type) {
- UI_reinit_gl_state();
rdc->draw(C, ar, rdc->customdata);
}
}
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index da3364d872d..8866c6b6c40 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -39,6 +39,7 @@
#include "BLT_translation.h"
#include "DNA_armature_types.h"
+#include "DNA_group_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@@ -49,6 +50,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"
@@ -56,6 +58,7 @@
#include "BKE_screen.h"
#include "BKE_texture.h"
#include "BKE_linestyle.h"
+#include "BKE_workspace.h"
#include "RNA_access.h"
@@ -167,27 +170,64 @@ static int buttons_context_path_linestyle(ButsContextPath *path)
return 0;
}
+static int buttons_context_path_workspace(ButsContextPath *path)
+{
+ PointerRNA *ptr = &path->ptr[path->len - 1];
+
+ /* This one just verifies. */
+ return RNA_struct_is_a(ptr->type, &RNA_WorkSpace);
+}
+
+static int buttons_context_path_collection(ButsContextPath *path, eSpaceButtons_Collection_Context collection_context)
+{
+ 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;
+ }
+
+ ViewLayer *view_layer = ptr->data;
+
+ if (collection_context == SB_COLLECTION_CTX_GROUP) {
+ Object *ob = OBACT(view_layer);
+ if (ob && ob->dup_group) {
+ view_layer = ob->dup_group->view_layer;
+
+ /* Replace the view layer by the group in the context path. */
+ RNA_pointer_create(NULL, &RNA_Group, ob->dup_group, &path->ptr[path->len - 1]);
+ }
+ }
+
+ LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
+
+ if (layer_collection) {
+ RNA_pointer_create(NULL, &RNA_LayerCollection, layer_collection, &path->ptr[path->len]);
+ path->len++;
+ return 1;
+ }
+
+ /* no path to a collection possible */
+ return 0;
+}
+
static int buttons_context_path_object(ButsContextPath *path)
{
- Scene *scene;
- Object *ob;
PointerRNA *ptr = &path->ptr[path->len - 1];
/* if we already have a (pinned) object, we're done */
if (RNA_struct_is_a(ptr->type, &RNA_Object)) {
return 1;
}
- /* 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;
- if (ob) {
- RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
- path->len++;
+ ViewLayer *view_layer = ptr->data;
+ Object *ob = (view_layer->basact) ? view_layer->basact->object : NULL;
- return 1;
- }
+ if (ob) {
+ RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
+ path->len++;
+
+ return 1;
}
/* no path to a object possible */
@@ -208,6 +248,7 @@ static int buttons_context_path_data(ButsContextPath *path, int type)
else if (RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) return 1;
else if (RNA_struct_is_a(ptr->type, &RNA_Lamp) && (type == -1 || type == OB_LAMP)) return 1;
else if (RNA_struct_is_a(ptr->type, &RNA_Speaker) && (type == -1 || type == OB_SPEAKER)) return 1;
+ else if (RNA_struct_is_a(ptr->type, &RNA_LightProbe) && (type == -1 || type == OB_LIGHTPROBE)) return 1;
/* try to get an object in the path, no pinning supported here */
else if (buttons_context_path_object(path)) {
ob = path->ptr[path->len - 1].data;
@@ -367,7 +408,7 @@ static int buttons_context_path_particle(ButsContextPath *path)
return 0;
}
-static int buttons_context_path_brush(ButsContextPath *path)
+static int buttons_context_path_brush(const bContext *C, ButsContextPath *path)
{
Scene *scene;
Brush *br = NULL;
@@ -381,8 +422,10 @@ static int buttons_context_path_brush(ButsContextPath *path)
else if (buttons_context_path_scene(path)) {
scene = path->ptr[path->len - 1].data;
- if (scene)
- br = BKE_paint_brush(BKE_paint_get_active(scene));
+ if (scene) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ br = BKE_paint_brush(BKE_paint_get_active(scene, view_layer));
+ }
if (br) {
RNA_id_pointer_create((ID *)br, &path->ptr[path->len]);
@@ -396,7 +439,7 @@ static int buttons_context_path_brush(ButsContextPath *path)
return 0;
}
-static int buttons_context_path_texture(ButsContextPath *path, ButsContextTexture *ct)
+static int buttons_context_path_texture(const bContext *C, ButsContextPath *path, ButsContextTexture *ct)
{
if (ct) {
/* new shading system */
@@ -414,7 +457,7 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur
if (id) {
if (GS(id->name) == ID_BR)
- buttons_context_path_brush(path);
+ buttons_context_path_brush(C, path);
else if (GS(id->name) == ID_MA)
buttons_context_path_material(path, false, true);
else if (GS(id->name) == ID_WO)
@@ -530,7 +573,7 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur
static bool buttons_context_linestyle_pinnable(const bContext *C)
{
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *actsrl;
+ ViewLayer *active_view_layer;
FreestyleConfig *config;
SpaceButs *sbuts;
@@ -539,8 +582,8 @@ static bool buttons_context_linestyle_pinnable(const bContext *C)
return false;
}
/* if Freestyle is not in the Parameter Editor mode */
- actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- config = &actsrl->freestyleConfig;
+ active_view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ config = &active_view_layer->freestyle_config;
if (config->mode != FREESTYLE_CONTROL_EDITOR_MODE) {
return false;
}
@@ -556,6 +599,8 @@ static bool buttons_context_linestyle_pinnable(const bContext *C)
static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag)
{
SpaceButs *sbuts = CTX_wm_space_buts(C);
+ Scene *scene = CTX_data_scene(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
ID *id;
int found;
@@ -563,18 +608,32 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
path->flag = flag;
path->tex_ctx = sbuts->texture_context;
- /* if some ID datablock is pinned, set the root pointer */
+ const bool use_scene_settings = BKE_workspace_use_scene_settings_get(workspace);
+
+ /* If some ID datablock is pinned, set the root pointer. */
if (sbuts->pinid) {
id = sbuts->pinid;
RNA_id_pointer_create(id, &path->ptr[0]);
path->len++;
}
+ /* No pinned root, use scene or workspace as initial root. */
+ else {
+ if ((mainb != BCONTEXT_WORKSPACE) && (use_scene_settings ||
+ ELEM(mainb, BCONTEXT_SCENE, BCONTEXT_RENDER, BCONTEXT_VIEW_LAYER, BCONTEXT_WORLD)))
+ {
+ RNA_id_pointer_create(&scene->id, &path->ptr[0]);
+ path->len++;
+ }
+ else {
+ RNA_id_pointer_create(&workspace->id, &path->ptr[0]);
+ path->len++;
+ }
+ }
- /* no pinned root, use scene as root */
- if (path->len == 0) {
- id = (ID *)CTX_data_scene(C);
- RNA_id_pointer_create(id, &path->ptr[0]);
+ if (!ELEM(mainb, BCONTEXT_WORKSPACE, BCONTEXT_SCENE, BCONTEXT_RENDER, BCONTEXT_VIEW_LAYER, BCONTEXT_WORLD)) {
+ ViewLayer *view_layer = BKE_view_layer_from_workspace_get(scene, workspace);
+ RNA_pointer_create(NULL, &RNA_ViewLayer, view_layer, &path->ptr[path->len]);
path->len++;
}
@@ -585,7 +644,7 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
case BCONTEXT_RENDER:
found = buttons_context_path_scene(path);
break;
- case BCONTEXT_RENDER_LAYER:
+ case BCONTEXT_VIEW_LAYER:
#ifdef WITH_FREESTYLE
if (buttons_context_linestyle_pinnable(C)) {
found = buttons_context_path_linestyle(path);
@@ -599,6 +658,12 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
case BCONTEXT_WORLD:
found = buttons_context_path_world(path);
break;
+ case BCONTEXT_WORKSPACE:
+ found = buttons_context_path_workspace(path);
+ break;
+ case BCONTEXT_COLLECTION:
+ found = buttons_context_path_collection(path, sbuts->collection_context);
+ break;
case BCONTEXT_OBJECT:
case BCONTEXT_PHYSICS:
case BCONTEXT_CONSTRAINT:
@@ -617,7 +682,7 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
found = buttons_context_path_material(path, false, (sbuts->texuser != NULL));
break;
case BCONTEXT_TEXTURE:
- found = buttons_context_path_texture(path, sbuts->texuser);
+ found = buttons_context_path_texture(C, path, sbuts->texuser);
break;
case BCONTEXT_BONE:
found = buttons_context_path_bone(path);
@@ -740,11 +805,11 @@ void buttons_context_compute(const bContext *C, SpaceButs *sbuts)
const char *buttons_context_dir[] = {
"texture_slot", "scene", "world", "object", "mesh", "armature", "lattice", "curve",
- "meta_ball", "lamp", "speaker", "camera", "material", "material_slot",
+ "meta_ball", "lamp", "speaker", "lightprobe", "camera", "material", "material_slot",
"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", "workspace", NULL
};
int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
@@ -773,6 +838,10 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
set_pointer_type(path, result, &RNA_World);
return 1;
}
+ else if (CTX_data_equals(member, "workspace")) {
+ /* Do not return one here if scene not found in path, in this case we want to get default context scene! */
+ return set_pointer_type(path, result, &RNA_WorkSpace);
+ }
else if (CTX_data_equals(member, "object")) {
set_pointer_type(path, result, &RNA_Object);
return 1;
@@ -809,6 +878,10 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
set_pointer_type(path, result, &RNA_Speaker);
return 1;
}
+ else if (CTX_data_equals(member, "lightprobe")) {
+ set_pointer_type(path, result, &RNA_LightProbe);
+ return 1;
+ }
else if (CTX_data_equals(member, "material")) {
set_pointer_type(path, result, &RNA_Material);
return 1;
@@ -1064,6 +1137,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 */
}
@@ -1121,10 +1198,14 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
if (name) {
- if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene)
+ if ((!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_VIEW_LAYER) && ptr->type == &RNA_Scene) ||
+ (!ELEM(sbuts->mainb, BCONTEXT_WORKSPACE) && ptr->type == &RNA_WorkSpace))
+ {
uiItemLDrag(row, ptr, "", icon); /* save some space */
- else
+ }
+ else {
uiItemLDrag(row, ptr, name, icon);
+ }
if (name != namebuf)
MEM_freeN(name);
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
index 7fc35a6b1e7..e6d19caad47 100644
--- a/source/blender/editors/space_buttons/buttons_intern.h
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -65,6 +65,7 @@ typedef struct ButsContextPath {
int len;
int flag;
int tex_ctx;
+ int collection_ctx;
} ButsContextPath;
typedef struct ButsTextureUser {
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index e3d72ba67d8..036db87e846 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -54,6 +54,7 @@
#include "DNA_linestyle_types.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_linestyle.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
@@ -108,14 +109,14 @@ bool ED_texture_context_check_linestyle(const bContext *C)
{
#ifdef WITH_FREESTYLE
Scene *scene = CTX_data_scene(C);
- SceneRenderLayer *actsrl;
+ ViewLayer *active_view_layer;
FreestyleConfig *config;
FreestyleLineSet *lineset;
FreestyleLineStyle *linestyle;
if (scene && (scene->r.mode & R_EDGE_FRS)) {
- actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- config = &actsrl->freestyleConfig;
+ active_view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ config = &active_view_layer->freestyle_config;
if (config->mode == FREESTYLE_CONTROL_EDITOR_MODE) {
lineset = BKE_freestyle_lineset_get_active(config);
if (lineset) {
@@ -195,7 +196,7 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
else if ((sbuts->mainb == BCONTEXT_PARTICLE) && valid_particles) {
sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_PARTICLES;
}
- else if ((sbuts->mainb == BCONTEXT_RENDER_LAYER) && valid_linestyle) {
+ else if ((sbuts->mainb == BCONTEXT_VIEW_LAYER) && valid_linestyle) {
sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_LINESTYLE;
}
else if ((ELEM(sbuts->mainb, BCONTEXT_MODIFIER, BCONTEXT_PHYSICS)) && valid_others) {
@@ -324,6 +325,7 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
Material *ma = NULL;
Lamp *la = NULL;
World *wrld = NULL;
+ WorkSpace *workspace = NULL;
FreestyleLineStyle *linestyle = NULL;
Brush *brush = NULL;
ID *pinid = sbuts->pinid;
@@ -345,17 +347,25 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
brush = (Brush *)pinid;
else if (GS(pinid->name) == ID_LS)
linestyle = (FreestyleLineStyle *)pinid;
+ else if (GS(pinid->name) == ID_WS)
+ workspace = (WorkSpace *)workspace;
}
if (!scene)
scene = CTX_data_scene(C);
if (!pinid || GS(pinid->name) == ID_SCE) {
- ob = (scene->basact) ? scene->basact->object : NULL;
wrld = scene->world;
brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
linestyle = BKE_linestyle_active_from_scene(scene);
}
+ else if (!pinid || GS(pinid->name) == ID_WS) {
+ if (!workspace) {
+ workspace = CTX_wm_workspace(C);
+ }
+ ViewLayer *view_layer = BKE_view_layer_from_workspace_get(scene, workspace);
+ ob = OBACT(view_layer);
+ }
if (ob && ob->type == OB_LAMP && !la)
la = ob->data;
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index e4c23ad74f8..d2f407bfa8c 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -44,6 +44,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "RNA_access.h"
@@ -147,10 +148,14 @@ static void buttons_main_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, "scene", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_RENDER)
ED_region_panels(C, ar, "render", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_RENDER_LAYER)
- ED_region_panels(C, ar, "render_layer", sbuts->mainb, vertical);
+ else if (sbuts->mainb == BCONTEXT_VIEW_LAYER)
+ ED_region_panels(C, ar, "view_layer", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_WORLD)
ED_region_panels(C, ar, "world", sbuts->mainb, vertical);
+ else if (sbuts->mainb == BCONTEXT_WORKSPACE)
+ ED_region_panels(C, ar, "workspace", sbuts->mainb, vertical);
+ else if (sbuts->mainb == BCONTEXT_COLLECTION)
+ ED_region_panels(C, ar, "collection", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_OBJECT)
ED_region_panels(C, ar, "object", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_DATA)
@@ -176,6 +181,20 @@ static void buttons_main_region_draw(const bContext *C, ARegion *ar)
sbuts->mainbo = sbuts->mainb;
}
+static void buttons_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn,
+ const Scene *UNUSED(scene))
+{
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
+}
+
static void buttons_operatortypes(void)
{
WM_operatortype_append(BUTTONS_OT_toolbox);
@@ -218,7 +237,9 @@ static void buttons_area_redraw(ScrArea *sa, short buttons)
}
/* reused! */
-static void buttons_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
+static void buttons_area_listener(
+ bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
+ WorkSpace *UNUSED(workspace))
{
SpaceButs *sbuts = sa->spacedata.first;
@@ -228,7 +249,7 @@ static void buttons_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *
switch (wmn->data) {
case ND_RENDER_OPTIONS:
buttons_area_redraw(sa, BCONTEXT_RENDER);
- buttons_area_redraw(sa, BCONTEXT_RENDER_LAYER);
+ buttons_area_redraw(sa, BCONTEXT_VIEW_LAYER);
break;
case ND_WORLD:
buttons_area_redraw(sa, BCONTEXT_WORLD);
@@ -468,6 +489,7 @@ void ED_spacetype_buttons(void)
art->regionid = RGN_TYPE_WINDOW;
art->init = buttons_main_region_init;
art->draw = buttons_main_region_draw;
+ art->listener = buttons_main_region_listener;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt
index 32d48c9c564..8fa4a0de53f 100644
--- a/source/blender/editors/space_clip/CMakeLists.txt
+++ b/source/blender/editors/space_clip/CMakeLists.txt
@@ -27,6 +27,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../imbuf
../../gpu
../../makesdna
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 0378c68d12c..eb9aadd2e72 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -47,11 +47,12 @@
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_screen.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
+#include "DEG_depsgraph.h"
+
#include "ED_gpencil.h"
#include "UI_interface.h"
@@ -236,7 +237,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
marker->pos[1] = cb->marker_pos[1] / height;
/* to update position of "parented" objects */
- DAG_id_tag_update(&cb->clip->id, 0);
+ DEG_id_tag_update(&cb->clip->id, 0);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
ok = true;
@@ -321,7 +322,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event)
sub_v2_v2(cb->track->markers[i].pos, delta);
/* to update position of "parented" objects */
- DAG_id_tag_update(&cb->clip->id, 0);
+ DEG_id_tag_update(&cb->clip->id, 0);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
ok = true;
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index 4bf4c1e7baa..631d891ce02 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;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_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 = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immBegin(GWN_PRIM_POINTS, keyframe_ct);
+
+ /* all same size with black outline */
+ immAttrib1f(size_id, 2.0f * STRIP_HEIGHT_HALF);
+ immAttrib4ub(outline_color_id, 0, 0, 0, 255);
+
+ 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;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_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_draw.c b/source/blender/editors/space_clip/clip_draw.c
index a71b2baa96f..09d225fc1b8 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -55,10 +55,11 @@
#include "ED_mask.h"
#include "ED_gpencil.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#include "WM_types.h"
@@ -66,26 +67,25 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-
#include "BLF_api.h"
#include "clip_intern.h" // own include
/*********************** main area drawing *************************/
-static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int width)
+static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int width, unsigned int pos)
{
int height = (frame == cfra) ? 22 : 10;
int x = (frame - sfra) * framelen;
if (width == 1) {
- glBegin(GL_LINES);
- glVertex2i(x, 0);
- glVertex2i(x, height * UI_DPI_FAC);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2i(pos, x, 0);
+ immVertex2i(pos, x, height * UI_DPI_FAC);
+ immEnd();
}
else {
- glRecti(x, 0, x + width, height * UI_DPI_FAC);
+ immRecti(pos, x, 0, x + width, height * UI_DPI_FAC);
}
}
@@ -166,6 +166,9 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
BKE_movieclip_get_cache_segments(clip, &sc->user, &totseg, &points);
ED_region_cache_draw_cached_segments(ar, totseg, points, sfra, efra);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* track */
if (act_track || act_plane_track) {
for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) {
@@ -189,14 +192,17 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) {
framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
- if (framenr != i)
- glColor4ub(128, 128, 0, 96);
- else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a))
- glColor4ub(255, 255, 0, 196);
- else
- glColor4ub(255, 255, 0, 96);
+ if (framenr != i) {
+ immUniformColor4ub(128, 128, 0, 96);
+ }
+ else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a)) {
+ immUniformColor4ub(255, 255, 0, 196);
+ }
+ else {
+ immUniformColor4ub(255, 255, 0, 96);
+ }
- glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4 * UI_DPI_FAC);
+ immRecti(pos, (i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4 * UI_DPI_FAC);
}
}
}
@@ -206,7 +212,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
int n = reconstruction->camnr;
MovieReconstructedCamera *cameras = reconstruction->cameras;
- glColor4ub(255, 0, 0, 96);
+ immUniformColor4ub(255, 0, 0, 96);
for (i = sfra, a = 0; i <= efra; i++) {
bool ok = false;
@@ -223,8 +229,9 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
a++;
}
- if (!ok)
- glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8 * UI_DPI_FAC);
+ if (!ok) {
+ immRecti(pos, (i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8 * UI_DPI_FAC);
+ }
}
}
@@ -233,15 +240,22 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
/* current frame */
x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx;
- UI_ThemeColor(TH_CFRAME);
- glRecti(x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
+ immUniformThemeColor(TH_CFRAME);
+ immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
+
+ immUnbindProgram();
ED_region_cache_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC);
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* solver keyframes */
- glColor4ub(175, 255, 0, 255);
- draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2);
- draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2);
+ immUniformColor4ub(175, 255, 0, 255);
+ draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2, pos);
+ draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2, pos);
+
+ immUnbindProgram();
/* movie clip animation */
if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask_info.mask) {
@@ -275,11 +289,16 @@ static void draw_movieclip_muted(ARegion *ar, int width, int height, float zoomx
{
int x, y;
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* find window pixel coordinates of origin */
UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
- glColor3f(0.0f, 0.0f, 0.0f);
- glRectf(x, y, x + zoomx * width, y + zoomy * height);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ immRectf(pos, x, y, x + zoomx * width, y + zoomy * height);
+
+ immUnbindProgram();
}
static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
@@ -297,7 +316,7 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
+ imm_draw_box_checker_2d(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
}
/* non-scaled proxy shouldn't use filtering */
@@ -307,13 +326,7 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
filter = GL_NEAREST;
}
- /* set zoom */
- glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
-
- glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter);
- /* reset zoom */
- glPixelZoom(1.0f, 1.0f);
-
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter, zoomx * width / ibuf->x, zoomy * height / ibuf->y);
if (sc->flag & SC_SHOW_METADATA) {
rctf frame;
@@ -335,31 +348,37 @@ static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int
/* draw boundary border for frame if stabilization is enabled */
if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
- glColor3f(0.0f, 0.0f, 0.0f);
-
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ /* Exclusive OR allows to get orig value when second operand is 0,
+ * and negative of orig value when second operand is 1. */
glEnable(GL_COLOR_LOGIC_OP);
- glLogicOp(GL_NOR);
+ glLogicOp(GL_XOR);
+
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+
+ gpuScale2f(zoomx, zoomy);
+ gpuMultMatrix(sc->stabmat);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- glPushMatrix();
- glTranslatef(x, y, 0.0f);
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.0f);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
- glScalef(zoomx, zoomy, 1.0f);
- glMultMatrixf(sc->stabmat);
+ imm_draw_box_wire_2d(shdr_pos, 0.0f, 0.0f, width, height);
- glBegin(GL_LINE_LOOP);
- glVertex2f(0.0f, 0.0f);
- glVertex2f(width, 0.0f);
- glVertex2f(width, height);
- glVertex2f(0.0f, height);
- glEnd();
+ immUnbindProgram();
- glPopMatrix();
+ gpuPopMatrix();
glDisable(GL_COLOR_LOGIC_OP);
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
}
}
@@ -432,53 +451,97 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
i++;
}
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
if (!tiny) {
- UI_ThemeColor(TH_MARKER_OUTLINE);
+ immUniformThemeColor(TH_MARKER_OUTLINE);
if (TRACK_VIEW_SELECTED(sc, track)) {
- glPointSize(5.0f);
- glBegin(GL_POINTS);
- for (i = a; i < b; i++) {
- if (i != curindex)
- glVertex2f(path[i][0], path[i][1]);
+ if ((b - a - 1) >= 1) {
+ glPointSize(5.0f);
+
+ immBegin(GWN_PRIM_POINTS, b - a - 1);
+
+ for (i = a; i < b; i++) {
+ if (i != curindex) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
+ }
+
+ immEnd();
}
- glEnd();
}
- glLineWidth(3.0f);
- glBegin(GL_LINE_STRIP);
- for (i = a; i < b; i++)
- glVertex2f(path[i][0], path[i][1]);
- glEnd();
- }
+ if ((b - a) >= 2) {
+ glLineWidth(3.0f);
+
+ immBegin(GWN_PRIM_LINE_STRIP, b - a);
+
+ for (i = a; i < b; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
- UI_ThemeColor(TH_PATH_BEFORE);
+ immEnd();
+ }
+ }
if (TRACK_VIEW_SELECTED(sc, track)) {
glPointSize(3.0f);
- glBegin(GL_POINTS);
- for (i = a; i < b; i++) {
- if (i == count + 1)
- UI_ThemeColor(TH_PATH_AFTER);
- if (i != curindex)
- glVertex2f(path[i][0], path[i][1]);
+ if ((curindex - a) >= 1) {
+ immUniformThemeColor(TH_PATH_BEFORE);
+
+ immBegin(GWN_PRIM_POINTS, curindex - a);
+
+ for (i = a; i < curindex; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
+
+ immEnd();
}
- glEnd();
- }
- UI_ThemeColor(TH_PATH_BEFORE);
+ if ((b - curindex - 1) >= 1) {
+ immUniformThemeColor(TH_PATH_AFTER);
+
+ immBegin(GWN_PRIM_POINTS, b - curindex - 1);
+
+ for (i = curindex + 1; i < b; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
+
+ immEnd();
+ }
+ }
glLineWidth(1);
- glBegin(GL_LINE_STRIP);
- for (i = a; i < b; i++) {
- if (i == count + 1)
- UI_ThemeColor(TH_PATH_AFTER);
+ if ((curindex - a + 1) >= 2) {
+ immUniformThemeColor(TH_PATH_BEFORE);
+
+ immBegin(GWN_PRIM_LINE_STRIP, curindex - a + 1);
+
+ for (i = a; i <= curindex; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
+
+ immEnd();
+ }
+
+ if ((b - curindex) >= 2) {
+ immUniformThemeColor(TH_PATH_AFTER);
+
+ immBegin(GWN_PRIM_LINE_STRIP, b - curindex);
+
+ for (i = curindex; i < b; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
- glVertex2f(path[i][0], path[i][1]);
+ immEnd();
}
- glEnd();
+
+ immUnbindProgram();
if (path != path_static) {
MEM_freeN(path);
@@ -487,19 +550,19 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
}
static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- const float marker_pos[2], int width, int height)
+ const float marker_pos[2], int width, int height, unsigned int position)
{
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
bool show_search = false;
float px[2];
- UI_ThemeColor(TH_MARKER_OUTLINE);
-
px[0] = 1.0f / width / sc->zoom;
px[1] = 1.0f / height / sc->zoom;
glLineWidth(tiny ? 1.0f : 3.0f);
+ immUniformThemeColor(TH_MARKER_OUTLINE);
+
if ((marker->flag & MARKER_DISABLED) == 0) {
float pos[2];
float p[2];
@@ -514,51 +577,54 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
marker->pattern_corners[2], marker->pattern_corners[3]))
{
glPointSize(tiny ? 3.0f : 4.0f);
- glBegin(GL_POINTS);
- glVertex2f(pos[0], pos[1]);
- glEnd();
+
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex2f(position, pos[0], pos[1]);
+ immEnd();
}
else {
- glBegin(GL_LINES);
- glVertex2f(pos[0] + px[0] * 2, pos[1]);
- glVertex2f(pos[0] + px[0] * 8, pos[1]);
+ immBegin(GWN_PRIM_LINES, 8);
+
+ immVertex2f(position, pos[0] + px[0] * 2, pos[1]);
+ immVertex2f(position, pos[0] + px[0] * 8, pos[1]);
+
+ immVertex2f(position, pos[0] - px[0] * 2, pos[1]);
+ immVertex2f(position, pos[0] - px[0] * 8, pos[1]);
- glVertex2f(pos[0] - px[0] * 2, pos[1]);
- glVertex2f(pos[0] - px[0] * 8, pos[1]);
+ immVertex2f(position, pos[0], pos[1] - px[1] * 2);
+ immVertex2f(position, pos[0], pos[1] - px[1] * 8);
- glVertex2f(pos[0], pos[1] - px[1] * 2);
- glVertex2f(pos[0], pos[1] - px[1] * 8);
+ immVertex2f(position, pos[0], pos[1] + px[1] * 2);
+ immVertex2f(position, pos[0], pos[1] + px[1] * 8);
- glVertex2f(pos[0], pos[1] + px[1] * 2);
- glVertex2f(pos[0], pos[1] + px[1] * 8);
- glEnd();
+ immEnd();
}
}
/* pattern and search outline */
- glPushMatrix();
- glTranslate2fv(marker_pos);
+ gpuPushMatrix();
+ gpuTranslate2fv(marker_pos);
if (sc->flag & SC_SHOW_MARKER_PATTERN) {
- glBegin(GL_LINE_LOOP);
- glVertex2fv(marker->pattern_corners[0]);
- glVertex2fv(marker->pattern_corners[1]);
- glVertex2fv(marker->pattern_corners[2]);
- glVertex2fv(marker->pattern_corners[3]);
- glEnd();
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex2fv(position, marker->pattern_corners[0]);
+ immVertex2fv(position, marker->pattern_corners[1]);
+ immVertex2fv(position, marker->pattern_corners[2]);
+ immVertex2fv(position, marker->pattern_corners[3]);
+ immEnd();
}
show_search = (TRACK_VIEW_SELECTED(sc, track) &&
((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
+
if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) {
- glBegin(GL_LINE_LOOP);
- glVertex2f(marker->search_min[0], marker->search_min[1]);
- glVertex2f(marker->search_max[0], marker->search_min[1]);
- glVertex2f(marker->search_max[0], marker->search_max[1]);
- glVertex2f(marker->search_min[0], marker->search_max[1]);
- glEnd();
- }
- glPopMatrix();
+ imm_draw_box_wire_2d(position, marker->search_min[0],
+ marker->search_min[1],
+ marker->search_max[0],
+ marker->search_max[1]);
+ }
+
+ gpuPopMatrix();
}
static void track_colors(MovieTrackingTrack *track, int act, float col[3], float scol[3])
@@ -582,11 +648,12 @@ static void track_colors(MovieTrackingTrack *track, int act, float col[3], float
}
static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- const float marker_pos[2], int width, int height, int act, int sel)
+ const float marker_pos[2], int width, int height, int act, int sel, const uint shdr_pos)
{
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
bool show_search = false;
- float col[3], scol[3], px[2];
+ float col[3], scol[3];
+ float px[2];
track_colors(track, act, col, scol);
@@ -595,23 +662,34 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
glLineWidth(1.0f);
+ /* Since we are switching solid and dashed lines in rather complex logic here, just always go with dashed shader. */
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 0); /* "simple" mode */
+
/* marker position and offset position */
if ((track->flag & SELECT) == sel && (marker->flag & MARKER_DISABLED) == 0) {
float pos[2], p[2];
if (track->flag & TRACK_LOCKED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else if (track->flag & SELECT)
- UI_ThemeColorShade(TH_LOCK_MARKER, 64);
- else
- UI_ThemeColor(TH_LOCK_MARKER);
+ if (act) {
+ immUniformThemeColor(TH_ACT_MARKER);
+ }
+ else if (track->flag & SELECT) {
+ immUniformThemeColorShade(TH_LOCK_MARKER, 64);
+ }
+ else {
+ immUniformThemeColor(TH_LOCK_MARKER);
+ }
}
else {
- if (track->flag & SELECT)
- glColor3fv(scol);
- else
- glColor3fv(col);
+ immUniformColor3fv((track->flag & SELECT) ? scol : col);
}
add_v2_v2v2(pos, marker->pos, track->offset);
@@ -623,123 +701,114 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
marker->pattern_corners[2], marker->pattern_corners[3]))
{
glPointSize(tiny ? 1.0f : 2.0f);
- glBegin(GL_POINTS);
- glVertex2f(pos[0], pos[1]);
- glEnd();
+
+ immUniform1f("dash_factor", 2.0f); /* Solid "line" */
+
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex2f(shdr_pos, pos[0], pos[1]);
+ immEnd();
}
else {
- glBegin(GL_LINES);
- glVertex2f(pos[0] + px[0] * 3, pos[1]);
- glVertex2f(pos[0] + px[0] * 7, pos[1]);
+ immUniform1f("dash_factor", 2.0f); /* Solid line */
+
+ immBegin(GWN_PRIM_LINES, 8);
+
+ immVertex2f(shdr_pos, pos[0] + px[0] * 3, pos[1]);
+ immVertex2f(shdr_pos, pos[0] + px[0] * 7, pos[1]);
+
+ immVertex2f(shdr_pos, pos[0] - px[0] * 3, pos[1]);
+ immVertex2f(shdr_pos, pos[0] - px[0] * 7, pos[1]);
- glVertex2f(pos[0] - px[0] * 3, pos[1]);
- glVertex2f(pos[0] - px[0] * 7, pos[1]);
+ immVertex2f(shdr_pos, pos[0], pos[1] - px[1] * 3);
+ immVertex2f(shdr_pos, pos[0], pos[1] - px[1] * 7);
- glVertex2f(pos[0], pos[1] - px[1] * 3);
- glVertex2f(pos[0], pos[1] - px[1] * 7);
+ immVertex2f(shdr_pos, pos[0], pos[1] + px[1] * 3);
+ immVertex2f(shdr_pos, pos[0], pos[1] + px[1] * 7);
- glVertex2f(pos[0], pos[1] + px[1] * 3);
- glVertex2f(pos[0], pos[1] + px[1] * 7);
- glEnd();
+ immEnd();
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.0f);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
- glColor3f(0.0f, 0.0f, 0.0f);
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
glEnable(GL_COLOR_LOGIC_OP);
- glLogicOp(GL_NOR);
+ glLogicOp(GL_XOR);
- glBegin(GL_LINES);
- glVertex2fv(pos);
- glVertex2fv(marker_pos);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(shdr_pos, pos);
+ immVertex2fv(shdr_pos, marker_pos);
+ immEnd();
glDisable(GL_COLOR_LOGIC_OP);
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
}
}
/* pattern */
- glPushMatrix();
- glTranslate2fv(marker_pos);
-
- if (tiny) {
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
- }
- else {
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE);
- }
+ gpuPushMatrix();
+ gpuTranslate2fv(marker_pos);
- if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
- if (track->flag & TRACK_LOCKED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else if (track->pat_flag & SELECT)
- UI_ThemeColorShade(TH_LOCK_MARKER, 64);
- else UI_ThemeColor(TH_LOCK_MARKER);
+ if (track->flag & TRACK_LOCKED) {
+ if (act) {
+ immUniformThemeColor(TH_ACT_MARKER);
}
- else if (marker->flag & MARKER_DISABLED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else if (track->pat_flag & SELECT)
- UI_ThemeColorShade(TH_DIS_MARKER, 128);
- else UI_ThemeColor(TH_DIS_MARKER);
+ else if (track->pat_flag & SELECT) {
+ immUniformThemeColorShade(TH_LOCK_MARKER, 64);
}
else {
- if (track->pat_flag & SELECT)
- glColor3fv(scol);
- else glColor3fv(col);
+ immUniformThemeColor(TH_LOCK_MARKER);
}
-
- glBegin(GL_LINE_LOOP);
- glVertex2fv(marker->pattern_corners[0]);
- glVertex2fv(marker->pattern_corners[1]);
- glVertex2fv(marker->pattern_corners[2]);
- glVertex2fv(marker->pattern_corners[3]);
- glEnd();
}
-
- /* search */
- show_search = (TRACK_VIEW_SELECTED(sc, track) &&
- ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
- if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
- if (track->flag & TRACK_LOCKED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else if (track->search_flag & SELECT)
- UI_ThemeColorShade(TH_LOCK_MARKER, 64);
- else UI_ThemeColor(TH_LOCK_MARKER);
+ else if (marker->flag & MARKER_DISABLED) {
+ if (act) {
+ immUniformThemeColor(TH_ACT_MARKER);
}
- else if (marker->flag & MARKER_DISABLED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else if (track->search_flag & SELECT)
- UI_ThemeColorShade(TH_DIS_MARKER, 128);
- else UI_ThemeColor(TH_DIS_MARKER);
+ else if (track->pat_flag & SELECT) {
+ immUniformThemeColorShade(TH_DIS_MARKER, 128);
}
else {
- if (track->search_flag & SELECT)
- glColor3fv(scol);
- else
- glColor3fv(col);
+ immUniformThemeColor(TH_DIS_MARKER);
}
-
- glBegin(GL_LINE_LOOP);
- glVertex2f(marker->search_min[0], marker->search_min[1]);
- glVertex2f(marker->search_max[0], marker->search_min[1]);
- glVertex2f(marker->search_max[0], marker->search_max[1]);
- glVertex2f(marker->search_min[0], marker->search_max[1]);
- glEnd();
+ }
+ else {
+ immUniformColor3fv((track->pat_flag & SELECT) ? scol : col);
}
if (tiny) {
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
}
else {
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE);
+ immUniform1f("dash_factor", 2.0f); /* Solid line */
+ }
+
+ if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex2fv(shdr_pos, marker->pattern_corners[0]);
+ immVertex2fv(shdr_pos, marker->pattern_corners[1]);
+ immVertex2fv(shdr_pos, marker->pattern_corners[2]);
+ immVertex2fv(shdr_pos, marker->pattern_corners[3]);
+ immEnd();
+ }
+
+ /* search */
+ show_search = (TRACK_VIEW_SELECTED(sc, track) &&
+ ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
+
+ if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
+ imm_draw_box_wire_2d(shdr_pos, marker->search_min[0], marker->search_min[1],
+ marker->search_max[0], marker->search_max[1]);
}
- glPopMatrix();
+ gpuPopMatrix();
+
+ /* Restore default shader */
+ immUnbindProgram();
+
+ const uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ BLI_assert(pos == shdr_pos);
+ UNUSED_VARS_NDEBUG(pos);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
}
static float get_shortest_pattern_side(MovieTrackingMarker *marker)
@@ -760,7 +829,7 @@ static float get_shortest_pattern_side(MovieTrackingMarker *marker)
return sqrtf(len_sq);
}
-static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2])
+static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2], unsigned int pos)
{
float tdx, tdy;
@@ -772,15 +841,10 @@ static void draw_marker_slide_square(float x, float y, float dx, float dy, int o
tdy += px[1];
}
- glBegin(GL_QUADS);
- glVertex3f(x - tdx, y + tdy, 0.0f);
- glVertex3f(x + tdx, y + tdy, 0.0f);
- glVertex3f(x + tdx, y - tdy, 0.0f);
- glVertex3f(x - tdx, y - tdy, 0.0f);
- glEnd();
+ immRectf(pos, x - tdx, y - tdy, x + tdx, y + tdy);
}
-static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2])
+static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2], unsigned int pos)
{
float tdx, tdy;
@@ -792,15 +856,16 @@ static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int
tdy += px[1];
}
- glBegin(GL_TRIANGLES);
- glVertex3f(x, y, 0.0f);
- glVertex3f(x - tdx, y, 0.0f);
- glVertex3f(x, y + tdy, 0.0f);
- glEnd();
+ immBegin(GWN_PRIM_TRIS, 3);
+ immVertex2f(pos, x, y);
+ immVertex2f(pos, x - tdx, y);
+ immVertex2f(pos, x, y + tdy);
+ immEnd();
}
static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- const float marker_pos[2], int outline, int sel, int act, int width, int height)
+ const float marker_pos[2], int outline, int sel, int act,
+ int width, int height, unsigned int pos)
{
float dx, dy, patdx, patdy, searchdx, searchdy;
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
@@ -815,11 +880,11 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
track_colors(track, act, col, scol);
if (outline) {
- UI_ThemeColor(TH_MARKER_OUTLINE);
+ immUniformThemeColor(TH_MARKER_OUTLINE);
}
- glPushMatrix();
- glTranslate2fv(marker_pos);
+ gpuPushMatrix();
+ gpuTranslate2fv(marker_pos);
dx = 6.0f / width / sc->zoom;
dy = 6.0f / height / sc->zoom;
@@ -836,17 +901,14 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
if ((sc->flag & SC_SHOW_MARKER_SEARCH) && ((track->search_flag & SELECT) == sel || outline)) {
if (!outline) {
- if (track->search_flag & SELECT)
- glColor3fv(scol);
- else
- glColor3fv(col);
+ immUniformColor3fv((track->search_flag & SELECT) ? scol : col);
}
/* search offset square */
- draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px);
+ draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px, pos);
/* search re-sizing triangle */
- draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px);
+ draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px, pos);
}
if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) {
@@ -856,16 +918,13 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
float tilt_ctrl[2];
if (!outline) {
- if (track->pat_flag & SELECT)
- glColor3fv(scol);
- else
- glColor3fv(col);
+ immUniformColor3fv((track->pat_flag & SELECT) ? scol : col);
}
/* pattern's corners sliding squares */
for (i = 0; i < 4; i++) {
draw_marker_slide_square(marker->pattern_corners[i][0], marker->pattern_corners[i][1],
- patdx / 1.5f, patdy / 1.5f, outline, px);
+ patdx / 1.5f, patdy / 1.5f, outline, px, pos);
}
/* ** sliders to control overall pattern ** */
@@ -875,18 +934,16 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
glLineWidth(outline ? 3.0f : 1.0f);
- glBegin(GL_LINES);
- glVertex2f(0.0f, 0.0f);
- glVertex2fv(tilt_ctrl);
- glEnd();
-
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, 0.0f, 0.0f);
+ immVertex2fv(pos, tilt_ctrl);
+ immEnd();
/* slider to control pattern tilt */
- draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px);
+ draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px, pos);
}
- glPopMatrix();
+ gpuPopMatrix();
}
static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
@@ -904,16 +961,17 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
fontsize = BLF_height_max(fontid);
if (marker->flag & MARKER_DISABLED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else
- UI_ThemeColorShade(TH_DIS_MARKER, 128);
+ if (act) {
+ UI_FontThemeColor(fontid, TH_ACT_MARKER);
+ }
+ else {
+ unsigned char color[4];
+ UI_GetThemeColorShade4ubv(TH_DIS_MARKER, 128, color);
+ BLF_color4ubv(fontid, color);
+ }
}
else {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else
- UI_ThemeColor(TH_SEL_MARKER);
+ UI_FontThemeColor(fontid, act ? TH_ACT_MARKER : TH_SEL_MARKER);
}
if ((sc->flag & SC_SHOW_MARKER_SEARCH) &&
@@ -974,10 +1032,7 @@ static void plane_track_colors(bool is_active, float color[3], float selected_co
{
UI_GetThemeColor3fv(TH_MARKER, color);
- if (is_active)
- UI_GetThemeColor3fv(TH_ACT_MARKER, selected_color);
- else
- UI_GetThemeColor3fv(TH_SEL_MARKER, selected_color);
+ UI_GetThemeColor3fv(is_active ? TH_ACT_MARKER : TH_SEL_MARKER, selected_color);
}
static void getArrowEndPoint(const int width, const int height, const float zoom,
@@ -1074,9 +1129,6 @@ static void draw_plane_marker_image(Scene *scene,
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- glColor4f(1.0, 1.0, 1.0, plane_track->image_opacity);
-
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
glGenTextures(1, (GLuint *)&texid);
glBindTexture(GL_TEXTURE_2D, texid);
@@ -1087,20 +1139,38 @@ static void draw_plane_marker_image(Scene *scene,
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA,
GL_UNSIGNED_BYTE, display_buffer);
- glPushMatrix();
- glMultMatrixf(gl_matrix);
+ gpuPushMatrix();
+ gpuMultMatrix(gl_matrix);
+
+ Gwn_VertFormat *imm_format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(imm_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int texCoord = GWN_vertformat_attr_add(imm_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, plane_track->image_opacity);
+ immUniform1i("image", GL_TEXTURE0);
+
+ immBegin(GWN_PRIM_TRI_FAN, 4);
+
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, 0.0f, 0.0f);
+
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, 1.0f, 0.0f);
+
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, 1.0f, 1.0f);
+
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, 0.0f, 1.0f);
+
+ immEnd();
- glBegin(GL_QUADS);
- glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
- glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
- glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f);
- glEnd();
+ immUnbindProgram();
- glPopMatrix();
+ gpuPopMatrix();
glBindTexture(GL_TEXTURE_2D, 0);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
if (transparent) {
glDisable(GL_BLEND);
@@ -1123,20 +1193,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
BKE_image_has_ibuf(plane_track->image, NULL);
const bool draw_plane_quad = !has_image || plane_track->image_opacity == 0.0f;
float px[2];
-
- if (draw_outline) {
- UI_ThemeColor(TH_MARKER_OUTLINE);
- }
- else {
- float color[3], selected_color[3];
- plane_track_colors(is_active_track, color, selected_color);
- if (is_selected_track) {
- glColor3fv(selected_color);
- }
- else {
- glColor3fv(color);
- }
- }
+ float color[3], selected_color[3];
px[0] = 1.0f / width / sc->zoom;
px[1] = 1.0f / height / sc->zoom;
@@ -1146,66 +1203,92 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
draw_plane_marker_image(scene, plane_track, plane_marker);
}
- if (draw_plane_quad) {
+ if (draw_plane_quad || is_selected_track) {
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- const bool stipple = !draw_outline && tiny;
- const bool thick = draw_outline && !tiny;
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- if (stipple) {
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
- }
- else {
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE);
- }
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- GPU_basic_shader_line_width(thick ? 3.0f : 1.0f);
+ immUniform1i("num_colors", 0); /* "simple" mode */
- /* Draw rectangle itself. */
- glBegin(GL_LINE_LOOP);
- glVertex2fv(plane_marker->corners[0]);
- glVertex2fv(plane_marker->corners[1]);
- glVertex2fv(plane_marker->corners[2]);
- glVertex2fv(plane_marker->corners[3]);
- glEnd();
+ if (draw_plane_quad) {
+ const bool stipple = !draw_outline && tiny;
+ const bool thick = draw_outline && !tiny;
- /* Draw axis. */
- if (!draw_outline) {
- float end_point[2];
- glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
+ glLineWidth(thick ? 3.0f : 1.0f);
- glBegin(GL_LINES);
+ if (stipple) {
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+ }
+ else {
+ immUniform1f("dash_factor", 2.0f); /* Solid line */
+ }
- getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
- glColor3f(1.0, 0.0, 0.0f);
- glVertex2fv(plane_marker->corners[0]);
- glVertex2fv(end_point);
+ if (draw_outline) {
+ immUniformThemeColor(TH_MARKER_OUTLINE);
+ }
+ else {
+ plane_track_colors(is_active_track, color, selected_color);
+ immUniformColor3fv(is_selected_track ? selected_color : color);
+ }
- getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
- glColor3f(0.0, 1.0, 0.0f);
- glVertex2fv(plane_marker->corners[0]);
- glVertex2fv(end_point);
+ /* Draw rectangle itself. */
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex2fv(shdr_pos, plane_marker->corners[0]);
+ immVertex2fv(shdr_pos, plane_marker->corners[1]);
+ immVertex2fv(shdr_pos, plane_marker->corners[2]);
+ immVertex2fv(shdr_pos, plane_marker->corners[3]);
+ immEnd();
- glEnd();
+ /* Draw axis. */
+ if (!draw_outline) {
+ float end_point[2];
- glPopAttrib();
- }
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
- if (stipple) {
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- }
- else {
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE);
+ immBegin(GWN_PRIM_LINES, 2);
+
+ getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
+ immVertex2fv(shdr_pos, plane_marker->corners[0]);
+ immVertex2fv(shdr_pos, end_point);
+
+ immEnd();
+
+ immUniformColor3f(0.0f, 1.0f, 0.0f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+
+ getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
+ immVertex2fv(shdr_pos, plane_marker->corners[0]);
+ immVertex2fv(shdr_pos, end_point);
+
+ immEnd();
+ }
}
- }
- /* Draw sliders. */
- if (is_selected_track) {
- int i;
- for (i = 0; i < 4; i++) {
- draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1],
- 3.0f * px[0], 3.0f * px[1], draw_outline, px);
+ /* Draw sliders. */
+ if (is_selected_track) {
+ immUniform1f("dash_factor", 2.0f); /* Solid line */
+
+ if (draw_outline) {
+ immUniformThemeColor(TH_MARKER_OUTLINE);
+ }
+ else {
+ immUniformColor3fv(selected_color);
+ }
+
+ int i;
+ for (i = 0; i < 4; i++) {
+ draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1],
+ 3.0f * px[0], 3.0f * px[1], draw_outline, px, shdr_pos);
+ }
}
+
+ immUnbindProgram();
}
}
@@ -1257,13 +1340,13 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
- glPushMatrix();
- glTranslatef(x, y, 0);
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
- glPushMatrix();
- glScalef(zoomx, zoomy, 0);
- glMultMatrixf(sc->stabmat);
- glScalef(width, height, 0);
+ gpuPushMatrix();
+ gpuScale2f(zoomx, zoomy);
+ gpuMultMatrix(sc->stabmat);
+ gpuScale2f(width, height);
act_track = BKE_tracking_track_get_active(tracking);
@@ -1329,6 +1412,10 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
}
}
+ unsigned int position = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* markers outline and non-selected areas */
track = tracksbase->first;
fp = marker_pos;
@@ -1339,10 +1426,10 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
if (MARKER_VISIBLE(sc, track, marker)) {
copy_v2_v2(cur_pos, fp ? fp : marker->pos);
- draw_marker_outline(sc, track, marker, cur_pos, width, height);
- draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0);
- draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height);
- draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height);
+ draw_marker_outline(sc, track, marker, cur_pos, width, height, position);
+ draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0, position);
+ draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height, position);
+ draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height, position);
if (fp)
fp += 2;
@@ -1365,8 +1452,8 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
if (!act) {
copy_v2_v2(cur_pos, fp ? fp : marker->pos);
- draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1);
- draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height);
+ draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1, position);
+ draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height, position);
}
if (fp)
@@ -1385,8 +1472,8 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
if (MARKER_VISIBLE(sc, act_track, marker)) {
copy_v2_v2(cur_pos, active_pos ? active_pos : marker->pos);
- draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1);
- draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height);
+ draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1, position);
+ draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height, position);
}
}
}
@@ -1395,7 +1482,6 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
float pos[4], vec[4], mat[4][4], aspy;
- glEnable(GL_POINT_SMOOTH);
glPointSize(3.0f);
aspy = 1.0f / clip->tracking.camera.pixel_aspect;
@@ -1424,28 +1510,34 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
sub_v2_v2(vec, npos);
- if (len_squared_v2(vec) < (3.0f * 3.0f))
- glColor3f(0.0f, 1.0f, 0.0f);
- else
- glColor3f(1.0f, 0.0f, 0.0f);
+ if (len_squared_v2(vec) < (3.0f * 3.0f)) {
+ immUniformColor3f(0.0f, 1.0f, 0.0f);
+ }
+ else {
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
+ }
- glBegin(GL_POINTS);
- if (undistort)
- glVertex3f(pos[0] / width, pos[1] / (height * aspy), 0);
- else
- glVertex3f(npos[0] / width, npos[1] / (height * aspy), 0);
- glEnd();
+ immBegin(GWN_PRIM_POINTS, 1);
+
+ if (undistort) {
+ immVertex2f(position, pos[0] / width, pos[1] / (height * aspy));
+ }
+ else {
+ immVertex2f(position, npos[0] / width, npos[1] / (height * aspy));
+ }
+
+ immEnd();
}
}
}
track = track->next;
}
-
- glDisable(GL_POINT_SMOOTH);
}
- glPopMatrix();
+ immUnbindProgram();
+
+ gpuPopMatrix();
if (sc->flag & SC_SHOW_NAMES) {
/* scaling should be cleared before drawing texts, otherwise font would also be scaled */
@@ -1471,7 +1563,7 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
}
}
- glPopMatrix();
+ gpuPopMatrix();
if (marker_pos)
MEM_freeN(marker_pos);
@@ -1498,11 +1590,15 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
- glPushMatrix();
- glTranslatef(x, y, 0);
- glScalef(zoomx, zoomy, 0);
- glMultMatrixf(sc->stabmat);
- glScalef(width, height, 0);
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+ gpuScale2f(zoomx, zoomy);
+ gpuMultMatrix(sc->stabmat);
+ gpuScale2f(width, height);
+
+ unsigned int position = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* grid */
if (sc->flag & SC_SHOW_GRID) {
@@ -1574,22 +1670,26 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
pos[1] += dy;
}
- glColor3f(1.0f, 0.0f, 0.0f);
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
for (i = 0; i <= n; i++) {
- glBegin(GL_LINE_STRIP);
+ immBegin(GWN_PRIM_LINE_STRIP, n + 1);
+
for (j = 0; j <= n; j++) {
- glVertex2fv(grid[i][j]);
+ immVertex2fv(position, grid[i][j]);
}
- glEnd();
+
+ immEnd();
}
for (j = 0; j <= n; j++) {
- glBegin(GL_LINE_STRIP);
+ immBegin(GWN_PRIM_LINE_STRIP, n + 1);
+
for (i = 0; i <= n; i++) {
- glVertex2fv(grid[i][j]);
+ immVertex2fv(position, grid[i][j]);
}
- glEnd();
+
+ immEnd();
}
}
@@ -1608,7 +1708,8 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
continue;
}
- glColor4fv(layer->color);
+ immUniformColor4fv(layer->color);
+
glLineWidth(layer->thickness);
glPointSize((float)(layer->thickness + 2));
@@ -1618,7 +1719,6 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
while (stroke) {
if (stroke->flag & GP_STROKE_2DSPACE) {
if (stroke->totpoints > 1) {
- glBegin(GL_LINE_STRIP);
for (i = 0; i < stroke->totpoints - 1; i++) {
float npos[2], dpos[2], len;
int steps;
@@ -1641,19 +1741,22 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
sub_v2_v2v2(dpos, npos, pos);
mul_v2_fl(dpos, 1.0f / steps);
+ immBegin(GWN_PRIM_LINE_STRIP, steps + 1);
+
for (j = 0; j <= steps; j++) {
BKE_tracking_distort_v2(tracking, pos, tpos);
- glVertex2f(tpos[0] / width, tpos[1] / (height * aspy));
+ immVertex2f(position, tpos[0] / width, tpos[1] / (height * aspy));
add_v2_v2(pos, dpos);
}
+
+ immEnd();
}
- glEnd();
}
else if (stroke->totpoints == 1) {
- glBegin(GL_POINTS);
- glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy);
- glEnd();
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex2f(position, stroke->points[0].x + offsx, stroke->points[0].y + offsy);
+ immEnd();
}
}
@@ -1667,7 +1770,9 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
}
}
- glPopMatrix();
+ immUnbindProgram();
+
+ gpuPopMatrix();
}
void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
@@ -1764,8 +1869,8 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d)
* associated with the clip is already drawn in draw_distortion
*/
if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || is_track_source) {
- glPushMatrix();
- glMultMatrixf(sc->unistabmat);
+ gpuPushMatrix();
+ gpuMultMatrix(sc->unistabmat);
if (is_track_source) {
MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);
@@ -1774,13 +1879,13 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d)
int framenr = ED_space_clip_get_clip_frame_number(sc);
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- glTranslate2fv(marker->pos);
+ gpuTranslate2fv(marker->pos);
}
}
ED_gpencil_draw_2dimage(C);
- glPopMatrix();
+ gpuPopMatrix();
}
}
else {
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 59dd755173f..942bc2661c3 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -305,15 +305,12 @@ bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r
void ED_clip_update_frame(const Main *mainp, int cfra)
{
- wmWindowManager *wm;
- wmWindow *win;
-
/* image window, compo node users */
- for (wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
- for (win = wm->windows.first; win; win = win->next) {
- ScrArea *sa;
+ for (wmWindowManager *wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ bScreen *screen = WM_window_get_active_screen(win);
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->spacetype == SPACE_CLIP) {
SpaceClip *sc = sa->spacedata.first;
diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c
index 424d25defdd..1bd1ad69d64 100644
--- a/source/blender/editors/space_clip/clip_graph_draw.c
+++ b/source/blender/editors/space_clip/clip_graph_draw.c
@@ -42,7 +42,9 @@
#include "ED_screen.h"
#include "ED_clip.h"
-#include "BIF_gl.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#include "WM_types.h"
@@ -53,52 +55,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)
+static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord, bool is_point)
{
- 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 +87,22 @@ static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track,
glLineWidth(1.0f);
}
- glColor4fv(col);
+ immUniformColor4fv(col);
- glBegin(GL_LINE_STRIP);
+ if (is_point) {
+ immBeginAtMost(GWN_PRIM_POINTS, 1);
+ }
+ else {
+ /* Graph can be composed of smaller segments, if any marker is disabled */
+ immBeginAtMost(GWN_PRIM_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 +116,19 @@ 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);
+
+ gpuPushMatrix();
+ gpuTranslate2f(scene_framenr, val);
+ gpuScale2f(1.0f / data->xscale * data->hsize, 1.0f / data->yscale * data->hsize);
- draw_curve_knot(scene_framenr, val, data->xscale, data->yscale, data->hsize);
+ imm_draw_circle_wire_2d(data->pos, 0, 0, 0.7, 8);
+
+ gpuPopMatrix();
}
}
-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 +145,18 @@ 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);
-
/* 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);
@@ -195,6 +178,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,11 +214,11 @@ 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);
}
}
-static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord)
+static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord, bool is_point)
{
if (coord == 1) {
TrackErrorCurveUserData *data = (TrackErrorCurveUserData *) userdata;
@@ -249,20 +233,26 @@ static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *
glLineWidth(1.0f);
}
- glColor4fv(col);
+ immUniformColor4fv(col);
- glBegin(GL_LINE_STRIP);
+ if (is_point) { /* This probably never happens here, but just in case... */
+ immBeginAtMost(GWN_PRIM_POINTS, 1);
+ }
+ else {
+ /* Graph can be composed of smaller segments, if any marker is disabled */
+ immBeginAtMost(GWN_PRIM_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 +263,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 +280,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(GWN_PRIM_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)
@@ -335,14 +327,24 @@ void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene)
UI_view2d_grid_free(grid);
if (clip) {
- if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION)
- draw_tracks_motion_curves(v2d, sc);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ glPointSize(3.0f);
- if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR)
- draw_tracks_error_curves(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, pos);
+ }
+
+ if (sc->flag & SC_SHOW_GRAPH_FRAMES) {
+ draw_frame_curves(sc, pos);
+ }
- if (sc->flag & SC_SHOW_GRAPH_FRAMES)
- draw_frame_curves(sc);
+ immUnbindProgram();
}
/* frame range */
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index 9ad4fd4642a..e5a3cb6b57b 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -37,7 +37,8 @@
#include "BKE_context.h"
#include "BKE_tracking.h"
-#include "BKE_depsgraph.h"
+
+#include "DEG_depsgraph.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -691,7 +692,7 @@ static int graph_disable_markers_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index 14393c6968b..ffc7a41f0aa 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -125,12 +125,12 @@ void ED_clip_tool_props_register(struct ARegionType *art);
/* clip_utils.c */
void clip_graph_tracking_values_iterate_track(struct SpaceClip *sc, struct MovieTrackingTrack *track, void *userdata,
void (*func)(void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val),
- void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord),
+ void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord, bool is_point),
void (*segment_end)(void *userdata, int coord));
void clip_graph_tracking_values_iterate(struct SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
void (*func)(void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val),
- void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord),
+ void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord, bool is_point),
void (*segment_end)(void *userdata, int coord));
void clip_graph_tracking_iterate(struct SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 7d8dd629562..4afec844f6d 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -56,7 +56,6 @@
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_depsgraph.h"
#include "BKE_report.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -83,6 +82,8 @@
#include "PIL_time.h"
+#include "DEG_depsgraph_build.h"
+
#include "clip_intern.h" // own include
/******************** view navigation utilities *********************/
@@ -248,7 +249,7 @@ static int open_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_MOVIECLIP | NA_ADDED, clip);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
MEM_freeN(op->customdata);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index e901b9f8026..40661937bae 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -41,10 +41,11 @@
#include "BKE_context.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
-#include "BKE_depsgraph.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "DEG_depsgraph.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -52,7 +53,6 @@
#include "ED_screen.h"
#include "ED_clip.h"
-
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -63,7 +63,7 @@ void clip_graph_tracking_values_iterate_track(
SpaceClip *sc, MovieTrackingTrack *track, void *userdata,
void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord,
int scene_framenr, float val),
- void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord),
+ void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point),
void (*segment_end)(void *userdata, int coord))
{
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -92,8 +92,14 @@ void clip_graph_tracking_values_iterate_track(
}
if (!open) {
- if (segment_start)
- segment_start(userdata, track, coord);
+ if (segment_start) {
+ if ((i + 1) == track->markersnr) {
+ segment_start(userdata, track, coord, true);
+ }
+ else {
+ segment_start(userdata, track, coord, (track->markers[i + 1].flag & MARKER_DISABLED));
+ }
+ }
open = true;
prevval = marker->pos[coord];
@@ -124,7 +130,7 @@ void clip_graph_tracking_values_iterate(
SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker,
int coord, int scene_framenr, float val),
- void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord),
+ void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point),
void (*segment_end)(void *userdata, int coord))
{
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -205,7 +211,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
}
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
if (has_bundle)
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
@@ -238,31 +244,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 int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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(GWN_PRIM_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 */
- UI_view2d_scale_get(v2d, &xscale, &yscale);
- glScalef(1.0f / xscale, 1.0f, 1.0f);
+ float xscale;
+ UI_view2d_scale_get(v2d, &xscale, NULL);
+ gpuPushMatrix();
+ gpuScale2f(1.0f / xscale, 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);
+ gpuPopMatrix();
}
void clip_draw_sfra_efra(View2D *v2d, Scene *scene)
@@ -272,15 +282,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 int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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(GWN_PRIM_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/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 58930fa2cf2..478254fb165 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -60,7 +60,8 @@
#include "IMB_imbuf.h"
-#include "BIF_gl.h"
+#include "GPU_glew.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -329,7 +330,8 @@ static SpaceLink *clip_duplicate(SpaceLink *sl)
return (SpaceLink *)scn;
}
-static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
+static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
+ WorkSpace *UNUSED(workspace))
{
/* context changes */
switch (wmn->category) {
@@ -1214,13 +1216,13 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
show_cursor |= sc->around == V3D_AROUND_CURSOR;
if (show_cursor) {
- glPushMatrix();
- glTranslatef(x, y, 0);
- glScalef(zoomx, zoomy, 0);
- glMultMatrixf(sc->stabmat);
- glScalef(width, height, 0);
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+ gpuScale2f(zoomx, zoomy);
+ gpuMultMatrix(sc->stabmat);
+ gpuScale2f(width, height);
ED_image_draw_cursor(ar, sc->cursor);
- glPopMatrix();
+ gpuPopMatrix();
}
clip_draw_cache_and_notes(C, sc, ar);
@@ -1239,7 +1241,9 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
}
}
-static void clip_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void clip_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -1350,7 +1354,9 @@ static void clip_preview_region_draw(const bContext *C, ARegion *ar)
dopesheet_region_draw(C, ar);
}
-static void clip_preview_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void clip_preview_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
{
}
@@ -1391,7 +1397,9 @@ static void clip_channels_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
}
-static void clip_channels_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void clip_channels_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
{
}
@@ -1408,7 +1416,9 @@ static void clip_header_region_draw(const bContext *C, ARegion *ar)
ED_region_header(C, ar);
}
-static void clip_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void clip_header_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -1448,7 +1458,9 @@ static void clip_tools_region_draw(const bContext *C, ARegion *ar)
/****************** tool properties region ******************/
-static void clip_props_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void clip_props_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -1493,7 +1505,9 @@ static void clip_properties_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, NULL, -1, true);
}
-static void clip_properties_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void clip_properties_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index f32071b81dc..2439ac06d9c 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -42,10 +42,11 @@
#include "BKE_context.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
-#include "BKE_depsgraph.h"
#include "BKE_report.h"
#include "BKE_sound.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -905,7 +906,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- DAG_id_tag_update(&sc->clip->id, 0);
+ DEG_id_tag_update(&sc->clip->id, 0);
}
else if (data->area == TRACK_AREA_PAT) {
if (data->action == SLIDE_ACTION_SIZE) {
@@ -1200,7 +1201,7 @@ static int disable_markers_exec(bContext *C, wmOperator *op)
}
}
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c
index 71a5a825b0e..8e3871836e4 100644
--- a/source/blender/editors/space_clip/tracking_ops_orient.c
+++ b/source/blender/editors/space_clip/tracking_ops_orient.c
@@ -43,10 +43,12 @@
#include "BKE_constraint.h"
#include "BKE_tracking.h"
#include "BKE_global.h"
-#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -69,17 +71,16 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip)
return camera;
}
- for (Base *base = scene->base.first;
- base != NULL;
- base = base->next)
+ 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);
+ ViewLayer *view_layer = CTX_data_view_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(view_layer);
}
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);
+ ViewLayer *view_layer = CTX_data_view_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(view_layer) != NULL;
}
}
}
@@ -247,8 +249,8 @@ static int set_origin_exec(bContext *C, wmOperator *op)
copy_v3_v3(object->loc, vec);
}
- DAG_id_tag_update(&clip->id, 0);
- DAG_id_tag_update(&object->id, OB_RECALC_OB);
+ DEG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&object->id, OB_RECALC_OB);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -404,6 +406,7 @@ static int set_plane_exec(bContext *C, wmOperator *op)
ListBase *tracksbase;
Object *object;
Object *camera = get_camera_with_movieclip(scene, clip);
+ EvaluationContext eval_ctx;
int tot = 0;
float vec[3][3], mat[4][4], obmat[4][4], newmat[4][4], orig[3] = {0.0f, 0.0f, 0.0f};
int plane = RNA_enum_get(op->ptr, "plane");
@@ -428,6 +431,8 @@ static int set_plane_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ CTX_data_eval_ctx(C, &eval_ctx);
+
BKE_tracking_get_camera_object_matrix(scene, camera, mat);
/* Get 3 bundles to use as reference. */
@@ -490,11 +495,11 @@ static int set_plane_exec(bContext *C, wmOperator *op)
BKE_object_apply_mat4(object, mat, 0, 0);
}
- BKE_object_where_is_calc(scene, object);
+ BKE_object_where_is_calc(&eval_ctx, scene, object);
set_axis(scene, object, clip, tracking_object, axis_track, 'X');
- DAG_id_tag_update(&clip->id, 0);
- DAG_id_tag_update(&object->id, OB_RECALC_OB);
+ DEG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&object->id, OB_RECALC_OB);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -567,8 +572,8 @@ static int set_axis_exec(bContext *C, wmOperator *op)
set_axis(scene, object, clip, tracking_object, track, axis == 0 ? 'X' : 'Y');
- DAG_id_tag_update(&clip->id, 0);
- DAG_id_tag_update(&object->id, OB_RECALC_OB);
+ DEG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&object->id, OB_RECALC_OB);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -694,10 +699,10 @@ static int do_set_scale(bContext *C,
tracking_object->scale = scale;
}
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
if (object)
- DAG_id_tag_update(&object->id, OB_RECALC_OB);
+ DEG_id_tag_update(&object->id, OB_RECALC_OB);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
diff --git a/source/blender/editors/space_clip/tracking_ops_plane.c b/source/blender/editors/space_clip/tracking_ops_plane.c
index aa8518befaa..6c85bdfc4ec 100644
--- a/source/blender/editors/space_clip/tracking_ops_plane.c
+++ b/source/blender/editors/space_clip/tracking_ops_plane.c
@@ -39,9 +39,10 @@
#include "BKE_context.h"
#include "BKE_tracking.h"
-#include "BKE_depsgraph.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -372,7 +373,7 @@ static int slide_plane_marker_modal(bContext *C,
data->previous_mval[1] = event->mval[1];
copy_v2_v2(data->previous_corner, data->corner);
- DAG_id_tag_update(&sc->clip->id, 0);
+ DEG_id_tag_update(&sc->clip->id, 0);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
@@ -390,7 +391,7 @@ static int slide_plane_marker_modal(bContext *C,
clip_tracking_show_cursor(C);
- DAG_id_tag_update(&sc->clip->id, 0);
+ DEG_id_tag_update(&sc->clip->id, 0);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_clip/tracking_ops_solve.c b/source/blender/editors/space_clip/tracking_ops_solve.c
index 5c74c1947e3..89dfadc8974 100644
--- a/source/blender/editors/space_clip/tracking_ops_solve.c
+++ b/source/blender/editors/space_clip/tracking_ops_solve.c
@@ -43,10 +43,11 @@
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
#include "BKE_global.h"
-#include "BKE_depsgraph.h"
#include "BKE_report.h"
#include "BKE_library.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -180,7 +181,7 @@ static void solve_camera_freejob(void *scv)
MEM_freeN(tracking->stats);
tracking->stats = NULL;
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
WM_main_add_notifier(NC_MOVIECLIP | NA_EVALUATED, clip);
WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, NULL);
@@ -327,7 +328,7 @@ static int clear_solution_exec(bContext *C, wmOperator *UNUSED(op))
reconstruction->camnr = 0;
reconstruction->flag &= ~TRACKING_RECONSTRUCTED;
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
diff --git a/source/blender/editors/space_clip/tracking_ops_stabilize.c b/source/blender/editors/space_clip/tracking_ops_stabilize.c
index 35b1aead343..4eb6a4fbb24 100644
--- a/source/blender/editors/space_clip/tracking_ops_stabilize.c
+++ b/source/blender/editors/space_clip/tracking_ops_stabilize.c
@@ -38,7 +38,8 @@
#include "BKE_context.h"
#include "BKE_tracking.h"
-#include "BKE_depsgraph.h"
+
+#include "DEG_depsgraph.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -84,7 +85,7 @@ static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op))
}
if (update) {
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
}
@@ -138,7 +139,7 @@ static int stabilize_2d_remove_exec(bContext *C, wmOperator *UNUSED(op))
}
if (update) {
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
}
@@ -227,7 +228,7 @@ static int stabilize_2d_rotation_add_exec(bContext *C, wmOperator *UNUSED(op))
}
if (update) {
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
}
@@ -281,7 +282,7 @@ static int stabilize_2d_rotation_remove_exec(bContext *C, wmOperator *UNUSED(op)
}
if (update) {
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
}
diff --git a/source/blender/editors/space_clip/tracking_ops_track.c b/source/blender/editors/space_clip/tracking_ops_track.c
index 0dd0ee8c7d4..cd8e92c9b9c 100644
--- a/source/blender/editors/space_clip/tracking_ops_track.c
+++ b/source/blender/editors/space_clip/tracking_ops_track.c
@@ -297,7 +297,8 @@ static void track_markers_endjob(void *tmv)
tmj->scene->r.cfra = BKE_movieclip_remap_clip_to_scene_frame(tmj->clip,
tmj->lastfra);
if (wm != NULL) {
- ED_update_for_newframe(tmj->main, tmj->scene, 0);
+ // XXX: ...
+ // ED_update_for_newframe(tmj->main, tmj->scene);
}
BKE_autotrack_context_sync(tmj->context);
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
index 6396b390ca0..c8a06545e0f 100644
--- a/source/blender/editors/space_console/console_draw.c
+++ b/source/blender/editors/space_console/console_draw.c
@@ -40,6 +40,7 @@
#include "MEM_guardedalloc.h"
#include "BIF_gl.h"
+#include "GPU_immediate.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -157,6 +158,8 @@ static int console_textview_line_color(struct TextViewContext *tvc, unsigned cha
int offl = 0, offc = 0;
int xy[2] = {CONSOLE_DRAW_MARGIN, CONSOLE_DRAW_MARGIN};
int pen[2];
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
xy[1] += tvc->lheight / 6;
console_cursor_wrap_offset(sc->prompt, tvc->console_width, &offl, &offc, NULL);
@@ -168,14 +171,17 @@ static int console_textview_line_color(struct TextViewContext *tvc, unsigned cha
pen[1] += tvc->lheight * offl;
/* cursor */
- UI_GetThemeColor3ubv(TH_CONSOLE_CURSOR, fg);
- glColor3ubv(fg);
-
- glRecti((xy[0] + pen[0]) - 1,
- (xy[1] + pen[1]),
- (xy[0] + pen[0]) + 1,
- (xy[1] + pen[1] + tvc->lheight)
- );
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_CONSOLE_CURSOR);
+
+ immRectf(pos,
+ (xy[0] + pen[0]) - 1,
+ (xy[1] + pen[1]),
+ (xy[0] + pen[0]) + 1,
+ (xy[1] + pen[1] + tvc->lheight)
+ );
+
+ immUnbindProgram();
}
console_line_color(fg, cl_iter->type);
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index 97a85bce006..9a2f4b5d431 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -368,7 +368,9 @@ static void console_header_region_draw(const bContext *C, ARegion *ar)
ED_region_header(C, ar);
}
-static void console_main_region_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar, wmNotifier *wmn)
+static void console_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
// SpaceInfo *sinfo = sa->spacedata.first;
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 52d01063175..c1e298c426f 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -42,7 +42,6 @@
# include "BLI_winstuff.h"
#endif
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BKE_context.h"
@@ -71,6 +70,9 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+
#include "filelist.h"
#include "file_intern.h" // own include
@@ -258,9 +260,10 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
static void draw_tile(int sx, int sy, int width, int height, int colorid, int shade)
{
- UI_ThemeColorShade(colorid, shade);
+ float color[4];
+ UI_GetThemeColorShade4fv(colorid, shade, color);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox((float)sx, (float)(sy - height), (float)(sx + width), (float)sy, 5.0f);
+ UI_draw_roundbox_aa(true, (float)sx, (float)(sy - height), (float)(sx + width), (float)sy, 5.0f, color);
}
@@ -285,7 +288,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;
@@ -310,7 +314,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)
@@ -335,6 +339,7 @@ static void file_draw_preview(
float scale;
int ex, ey;
bool use_dropshadow = !is_icon && (typeflags & FILE_TYPE_IMAGE);
+ float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
BLI_assert(imb != NULL);
@@ -381,12 +386,12 @@ static void file_draw_preview(
/* the image */
if (!is_icon && typeflags & FILE_TYPE_FTFONT) {
- UI_ThemeColor(TH_TEXT);
- }
- else {
- glColor4f(1.0, 1.0, 1.0, 1.0);
+ UI_GetThemeColor4fv(TH_TEXT, col);
}
- glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale);
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTexScaled(&state, (float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect,
+ scale, scale, 1.0f, 1.0f, col);
if (icon) {
UI_icon_draw_aspect((float)xco, (float)yco, icon, icon_aspect, 1.0f);
@@ -394,8 +399,13 @@ static void file_draw_preview(
/* border */
if (use_dropshadow) {
- glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
- fdrawbox((float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+ imm_draw_box_wire_2d(pos, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
+ immUnbindProgram();
}
but = uiDefBut(block, UI_BTYPE_LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, NULL);
@@ -451,49 +461,70 @@ static void draw_background(FileLayout *layout, View2D *v2d)
int i;
int sy;
- UI_ThemeColorShade(TH_BACK, -7);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, -7);
/* alternating flat shade background */
for (i = 0; (i <= layout->rows); i += 2) {
sy = (int)v2d->cur.ymax - i * (layout->tile_h + 2 * layout->tile_border_y) - layout->tile_border_y;
- glRectf(v2d->cur.xmin, (float)sy, v2d->cur.xmax, (float)(sy + layout->tile_h + 2 * layout->tile_border_y));
-
+ immRectf(pos, v2d->cur.xmin, (float)sy, v2d->cur.xmax, (float)(sy + layout->tile_h + 2 * layout->tile_border_y));
}
+
+ immUnbindProgram();
}
static void draw_dividers(FileLayout *layout, View2D *v2d)
{
+ /* vertical column dividers */
+
const int step = (layout->tile_w + 2 * layout->tile_border_x);
- int v1[2], v2[2];
- int sx;
- unsigned char col_hi[3], col_lo[3];
- UI_GetThemeColorShade3ubv(TH_BACK, 30, col_hi);
- UI_GetThemeColorShade3ubv(TH_BACK, -30, col_lo);
+ unsigned int vertex_ct = 0;
+ int sx = (int)v2d->tot.xmin;
+ while (sx < v2d->cur.xmax) {
+ sx += step;
+ vertex_ct += 4; /* vertex_count = 2 points per line * 2 lines per divider */
+ }
- v1[1] = v2d->cur.ymax - layout->tile_border_y;
- v2[1] = v2d->cur.ymin;
+ if (vertex_ct > 0) {
+ int v1[2], v2[2];
+ unsigned char col_hi[3], col_lo[3];
- glBegin(GL_LINES);
+ UI_GetThemeColorShade3ubv(TH_BACK, 30, col_hi);
+ UI_GetThemeColorShade3ubv(TH_BACK, -30, col_lo);
- /* vertical column dividers */
- sx = (int)v2d->tot.xmin;
- while (sx < v2d->cur.xmax) {
- sx += step;
+ v1[1] = v2d->cur.ymax - layout->tile_border_y;
+ v2[1] = v2d->cur.ymin;
- glColor3ubv(col_lo);
- v1[0] = v2[0] = sx;
- glVertex2iv(v1);
- glVertex2iv(v2);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- glColor3ubv(col_hi);
- v1[0] = v2[0] = sx + 1;
- glVertex2iv(v1);
- glVertex2iv(v2);
- }
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINES, vertex_ct);
+
+ sx = (int)v2d->tot.xmin;
+ while (sx < v2d->cur.xmax) {
+ sx += step;
+
+ v1[0] = v2[0] = sx;
+ immSkipAttrib(color);
+ immVertex2iv(pos, v1);
+ immAttrib3ubv(color, col_lo);
+ immVertex2iv(pos, v2);
- glEnd();
+ v1[0] = v2[0] = sx + 1;
+ immSkipAttrib(color);
+ immVertex2iv(pos, v1);
+ immAttrib3ubv(color, col_hi);
+ immVertex2iv(pos, v2);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
}
void file_draw_list(const bContext *C, ARegion *ar)
@@ -517,6 +548,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));
@@ -587,9 +619,6 @@ void file_draw_list(const bContext *C, ARegion *ar)
BLI_join_dirfile(path, sizeof(path), root, file->relpath);
- UI_ThemeColor4(TH_TEXT);
-
-
if (!(file_selflag & FILE_SEL_EDITING)) {
if ((params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ||
(file_selflag & FILE_SEL_SELECTED))
@@ -625,7 +654,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;
@@ -656,7 +685,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;
@@ -668,7 +697,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;
}
@@ -679,10 +709,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 {
@@ -697,7 +729,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_file/file_utils.c b/source/blender/editors/space_file/file_utils.c
index c1caf5ae8ac..fc870399696 100644
--- a/source/blender/editors/space_file/file_utils.c
+++ b/source/blender/editors/space_file/file_utils.c
@@ -26,6 +26,7 @@
#include "BLI_rect.h"
#include "BLI_fileops.h"
+#include "BLI_listbase.h"
#include "BLO_readfile.h"
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 7abe5ff5070..3dfeb5eb5b3 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -215,7 +215,8 @@ short ED_fileselect_set_params(SpaceFile *sfile)
FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA |
FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB |
FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO |
- FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF;
+ FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS |
+ FILTER_ID_LP;
if (U.uiflag & USER_HIDE_DOT) {
params->flag |= FILE_HIDE_DOT;
@@ -228,7 +229,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
if (params->type == FILE_LOADLIB) {
params->flag |= RNA_boolean_get(op->ptr, "link") ? FILE_LINK : 0;
params->flag |= RNA_boolean_get(op->ptr, "autoselect") ? FILE_AUTOSELECT : 0;
- params->flag |= RNA_boolean_get(op->ptr, "active_layer") ? FILE_ACTIVELAY : 0;
+ params->flag |= RNA_boolean_get(op->ptr, "active_collection") ? FILE_ACTIVE_COLLECTION : 0;
}
if ((prop = RNA_struct_find_property(op->ptr, "display_type"))) {
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 287b98fa589..3f26604c23a 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -49,6 +49,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "ED_space_api.h"
#include "ED_screen.h"
@@ -292,7 +293,8 @@ static void file_refresh(const bContext *C, ScrArea *sa)
}
}
-static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
+static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
+ WorkSpace *UNUSED(workspace))
{
SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
@@ -334,7 +336,9 @@ static void file_main_region_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
-static void file_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void file_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -351,6 +355,33 @@ static void file_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa),
}
}
+static void file_main_region_message_subscribe(
+ const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
+ struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ SpaceFile *sfile = sa->spacedata.first;
+ FileSelectParams *params = ED_fileselect_get_params(sfile);
+ /* This is a bit odd that a region owns the subscriber for an area,
+ * keep for now since all subscribers for WM are regions.
+ * May be worth re-visiting later. */
+ wmMsgSubscribeValue msg_sub_value_area_tag_refresh = {
+ .owner = ar,
+ .user_data = sa,
+ .notify = ED_area_do_msg_notify_tag_refresh,
+ };
+
+ /* FileSelectParams */
+ {
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_FileSelectParams, params, &ptr);
+
+ /* All properties for this space type. */
+ WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__);
+ }
+}
+
static void file_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
@@ -598,7 +629,9 @@ static void file_tools_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, NULL, -1, true);
}
-static void file_tools_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void file_tools_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
{
#if 0
/* context changes */
@@ -660,7 +693,9 @@ static void file_ui_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
}
-static void file_ui_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void file_ui_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -724,6 +759,7 @@ void ED_spacetype_file(void)
art->init = file_main_region_init;
art->draw = file_main_region_draw;
art->listener = file_main_region_listener;
+ art->message_subscribe = file_main_region_message_subscribe;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_graph/CMakeLists.txt b/source/blender/editors/space_graph/CMakeLists.txt
index 40a196fa95b..2840324e65e 100644
--- a/source/blender/editors/space_graph/CMakeLists.txt
+++ b/source/blender/editors/space_graph/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../gpu
../../makesdna
../../makesrna
@@ -48,7 +49,7 @@ set(SRC
)
if(WITH_AUDASPACE)
- add_definitions(${AUDASPACE_DEFINITIONS})
+ add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index df6bd01144d..49f498b3419 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -48,13 +48,13 @@
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_main.h"
#include "BKE_global.h"
#include "BKE_screen.h"
#include "BKE_unit.h"
+#include "DEG_depsgraph_build.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -481,7 +481,7 @@ static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int e
case B_IPO_DEPCHANGE:
{
/* rebuild depsgraph for the new deps */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
break;
}
}
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 96a078b2817..d917e3b85a2 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -46,10 +46,12 @@
#include "BKE_curve.h"
#include "BKE_fcurve.h"
-
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
#include "ED_anim_api.h"
#include "graph_intern.h"
@@ -82,38 +84,59 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
FCM_EnvelopeData *fed;
const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
int i;
-
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ glLineWidth(1.0f);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 0); /* Simple dashes. */
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ immUniform1f("dash_width", 10.0f);
+ immUniform1f("dash_factor", 0.5f);
+
/* draw two black lines showing the standard reference levels */
- glColor3f(0.0f, 0.0f, 0.0f);
- glLineWidth(1);
- setlinestyle(5);
-
- glBegin(GL_LINES);
- glVertex2f(v2d->cur.xmin, env->midval + env->min);
- glVertex2f(v2d->cur.xmax, env->midval + env->min);
-
- glVertex2f(v2d->cur.xmin, env->midval + env->max);
- glVertex2f(v2d->cur.xmax, env->midval + env->max);
- glEnd();
- setlinestyle(0);
-
- /* set size of vertices (non-adjustable for now) */
- glPointSize(2.0f);
-
- /* for now, point color is fixed, and is white */
- glColor3f(1.0f, 1.0f, 1.0f);
-
- glBegin(GL_POINTS);
- for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
- /* only draw if visible
- * - min/max here are fixed, not relative
- */
- if (IN_RANGE(fed->time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
- glVertex2f(fed->time, fed->min);
- glVertex2f(fed->time, fed->max);
+
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->min);
+ immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->min);
+
+ immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->max);
+ immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->max);
+ immEnd();
+
+ immUnbindProgram();
+
+ if (env->totvert > 0) {
+ /* set size of vertices (non-adjustable for now) */
+ glPointSize(2.0f);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* for now, point color is fixed, and is white */
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+
+ immBeginAtMost(GWN_PRIM_POINTS, env->totvert * 2);
+
+ for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
+ /* only draw if visible
+ * - min/max here are fixed, not relative
+ */
+ if (IN_RANGE(fed->time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
+ immVertex2f(shdr_pos, fed->time, fed->min);
+ immVertex2f(shdr_pos, fed->time, fed->max);
+ }
}
+
+ immEnd();
+
+ immUnbindProgram();
}
- glEnd();
}
/* *************************** */
@@ -121,16 +144,37 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
/* Points ---------------- */
-/* helper func - draw keyframe vertices only for an F-Curve */
-static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo), View2D *v2d, short edit, short sel)
+/* helper func - set color to draw F-Curve data with */
+static void set_fcurve_vertex_color(FCurve *fcu, bool sel)
+{
+ /* Fade the 'intensity' of the vertices based on the selection of the curves too */
+ int alphaOffset = (int)((fcurve_display_alpha(fcu) - 1.0f) * 255);
+
+ float color[4];
+
+ /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */
+ if ((fcu->flag & FCURVE_PROTECTED) == 0) {
+ /* Curve's points ARE BEING edited */
+ UI_GetThemeColorShadeAlpha4fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, 0, alphaOffset, color);
+ }
+ else {
+ /* Curve's points CANNOT BE edited */
+ UI_GetThemeColorShadeAlpha4fv(sel ? TH_TEXT_HI : TH_TEXT, 0, alphaOffset, color);
+ }
+
+ immUniformColor4fv(color);
+}
+
+static void draw_fcurve_selected_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, bool sel, unsigned pos)
{
- BezTriple *bezt = fcu->bezt;
const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
- int i;
-
- glBegin(GL_POINTS);
-
- for (i = 0; i < fcu->totvert; i++, bezt++) {
+
+ set_fcurve_vertex_color(fcu, sel);
+
+ immBeginAtMost(GWN_PRIM_POINTS, fcu->totvert);
+
+ BezTriple *bezt = fcu->bezt;
+ for (int i = 0; i < fcu->totvert; i++, bezt++) {
/* as an optimization step, only draw those in view
* - we apply a correction factor to ensure that points don't pop in/out due to slight twitches of view size
*/
@@ -141,80 +185,50 @@ static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo),
* -
*/
if ((bezt->f2 & SELECT) == sel)
- glVertex3fv(bezt->vec[1]);
+ immVertex2fv(pos, bezt->vec[1]);
}
else {
/* no check for selection here, as curve is not editable... */
/* XXX perhaps we don't want to even draw points? maybe add an option for that later */
- glVertex3fv(bezt->vec[1]);
+ immVertex2fv(pos, bezt->vec[1]);
}
}
}
-
- glEnd();
-}
+ immEnd();
+}
-/* helper func - draw handle vertex for an F-Curve as a round unfilled circle
- * NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't
- * have a consistent appearance (due to off-pixel alignments)...
- */
-static void draw_fcurve_handle_control(float x, float y, float xscale, float yscale, float hsize)
+/* helper func - draw keyframe vertices only for an F-Curve */
+static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, unsigned pos)
{
- static GLuint displist = 0;
-
- /* initialize round circle shape */
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
- gluDisk(qobj, 0, 0.7, 8, 1);
- gluDeleteQuadric(qobj);
-
- glEndList();
- }
-
- /* adjust view transform before starting */
- glTranslatef(x, y, 0.0f);
- glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f);
-
- /* draw! */
- glCallList(displist);
-
- /* restore view transform */
- glScalef(xscale / hsize, yscale / hsize, 1.0);
- glTranslatef(-x, -y, 0.0f);
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+
+ immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize);
+
+ draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos);
+ draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos);
+
+ immUnbindProgram();
}
+
/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
-static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2d, short sel, short sel_handle_only, float units_scale)
+static void draw_fcurve_selected_handle_vertices(FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, unsigned pos)
{
- BezTriple *bezt = fcu->bezt;
- BezTriple *prevbezt = NULL;
- float hsize, xscale, yscale;
- int i;
-
- /* get view settings */
- hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
- UI_view2d_scale_get(v2d, &xscale, &yscale);
+ (void) v2d; /* TODO: use this to draw only points in view */
- /* Compensate OGL scale sued for unit mapping, so circle will be circle, not ellipse */
- yscale *= units_scale;
-
/* set handle color */
- if (sel) UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
- else UI_ThemeColor(TH_HANDLE_VERTEX);
-
- /* anti-aliased lines for more consistent appearance */
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
-
- for (i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) {
- /* Draw the editmode handles for a bezier curve (others don't have handles)
+ float hcolor[3];
+ UI_GetThemeColor3fv(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX, hcolor);
+ immUniform4f("outlineColor", hcolor[0], hcolor[1], hcolor[2], 1.0f);
+ immUniformColor3fvAlpha(hcolor, 0.01f); /* almost invisible - only keep for smoothness */
+
+ immBeginAtMost(GWN_PRIM_POINTS, fcu->totvert * 2);
+
+ BezTriple *bezt = fcu->bezt;
+ BezTriple *prevbezt = NULL;
+ for (int i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) {
+ /* Draw the editmode handles for a bezier curve (others don't have handles)
* if their selection status matches the selection status we're drawing for
* - first handle only if previous beztriple was bezier-mode
* - second handle only if current beztriple is bezier-mode
@@ -225,68 +239,61 @@ static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2
if (!sel_handle_only || BEZT_ISSEL_ANY(bezt)) {
if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
if ((bezt->f1 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/
- draw_fcurve_handle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize);
+ immVertex2fv(pos, bezt->vec[0]);
}
-
+
if (bezt->ipo == BEZT_IPO_BEZ) {
if ((bezt->f3 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax)*/
- draw_fcurve_handle_control(bezt->vec[2][0], bezt->vec[2][1], xscale, yscale, hsize);
+ immVertex2fv(pos, bezt->vec[2]);
}
}
}
-
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+
+ immEnd();
}
-/* helper func - set color to draw F-Curve data with */
-static void set_fcurve_vertex_color(FCurve *fcu, short sel)
+/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
+static void draw_fcurve_handle_vertices(FCurve *fcu, View2D *v2d, bool sel_handle_only, unsigned pos)
{
- /* Fade the 'intensity' of the vertices based on the selection of the curves too */
- int alphaOffset = (int)((fcurve_display_alpha(fcu) - 1.0f) * 255);
-
- /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */
- if ((fcu->flag & FCURVE_PROTECTED) == 0) {
- /* Curve's points ARE BEING edited */
- if (sel) UI_ThemeColorShadeAlpha(TH_VERTEX_SELECT, 0, alphaOffset);
- else UI_ThemeColorShadeAlpha(TH_VERTEX, 0, alphaOffset);
- }
- else {
- /* Curve's points CANNOT BE edited */
- if (sel) UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, alphaOffset);
- else UI_ThemeColorShadeAlpha(TH_TEXT, 0, alphaOffset);
- }
+ /* smooth outlines for more consistent appearance */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+
+ /* set handle size */
+ immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.pixelsize);
+ immUniform1f("outlineWidth", 1.5f * U.pixelsize);
+
+ draw_fcurve_selected_handle_vertices(fcu, v2d, false, sel_handle_only, pos);
+ draw_fcurve_selected_handle_vertices(fcu, v2d, true, sel_handle_only, pos);
+
+ immUnbindProgram();
}
-static void draw_fcurve_vertices(SpaceIpo *sipo, ARegion *ar, FCurve *fcu, short do_handles, short sel_handle_only, float units_scale)
+static void draw_fcurve_vertices(ARegion *ar, FCurve *fcu, bool do_handles, bool sel_handle_only)
{
View2D *v2d = &ar->v2d;
-
+
/* only draw points if curve is visible
- * - draw unselected points before selected points as separate passes to minimize color-changing overhead
- * (XXX dunno if this is faster than drawing all in one pass though)
- * and also to make sure in the case of overlapping points that the selected is always visible
+ * - draw unselected points before selected points as separate passes
+ * to make sure in the case of overlapping points that the selected is always visible
* - draw handles before keyframes, so that keyframes will overlap handles (keyframes are more important for users)
*/
-
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ glEnable(GL_BLEND);
+ GPU_enable_program_point_size();
+
/* draw the two handles first (if they're shown, the curve doesn't have just a single keyframe, and the curve is being edited) */
if (do_handles) {
- set_fcurve_vertex_color(fcu, 0);
- draw_fcurve_vertices_handles(fcu, sipo, v2d, 0, sel_handle_only, units_scale);
-
- set_fcurve_vertex_color(fcu, 1);
- draw_fcurve_vertices_handles(fcu, sipo, v2d, 1, sel_handle_only, units_scale);
+ draw_fcurve_handle_vertices(fcu, v2d, sel_handle_only, pos);
}
-
+
/* draw keyframes over the handles */
- set_fcurve_vertex_color(fcu, 0);
- draw_fcurve_vertices_keyframes(fcu, sipo, v2d, !(fcu->flag & FCURVE_PROTECTED), 0);
-
- set_fcurve_vertex_color(fcu, 1);
- draw_fcurve_vertices_keyframes(fcu, sipo, v2d, !(fcu->flag & FCURVE_PROTECTED), 1);
+ draw_fcurve_keyframe_vertices(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), pos);
+
+ GPU_disable_program_point_size();
+ glDisable(GL_BLEND);
}
/* Handles ---------------- */
@@ -303,10 +310,10 @@ static bool draw_fcurve_handles_check(SpaceIpo *sipo, FCurve *fcu)
(fcu->totvert <= 1) /* do not show handles if there is only 1 keyframe, otherwise they all clump together in an ugly ball */
)
{
- return 0;
+ return false;
}
else {
- return 1;
+ return true;
}
}
@@ -315,13 +322,10 @@ static bool draw_fcurve_handles_check(SpaceIpo *sipo, FCurve *fcu)
static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
{
int sel, b;
-
- /* a single call to GL_LINES here around these calls should be sufficient to still
- * get separate line segments, but which aren't wrapped with GL_LINE_STRIP every time we
- * want a single line
- */
- glBegin(GL_LINES);
-
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* slightly hacky, but we want to draw unselected points before selected ones
* so that selected points are clearly visible
*/
@@ -348,18 +352,24 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
UI_GetThemeColor3ubv(basecol + bezt->h1, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- glColor4ubv((GLubyte *)col);
-
- glVertex2fv(fp); glVertex2fv(fp + 3);
+ immUniformColor4ubv(col);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(pos, fp);
+ immVertex2fv(pos, fp + 3);
+ immEnd();
}
/* only draw second handle if this segment is bezier */
if (bezt->ipo == BEZT_IPO_BEZ) {
UI_GetThemeColor3ubv(basecol + bezt->h2, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- glColor4ubv((GLubyte *)col);
-
- glVertex2fv(fp + 3); glVertex2fv(fp + 6);
+ immUniformColor4ubv(col);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(pos, fp + 3);
+ immVertex2fv(pos, fp + 6);
+ immEnd();
}
}
else {
@@ -370,9 +380,12 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
fp = bezt->vec[0];
UI_GetThemeColor3ubv(basecol + bezt->h1, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- glColor4ubv((GLubyte *)col);
-
- glVertex2fv(fp); glVertex2fv(fp + 3);
+ immUniformColor4ubv(col);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(pos, fp);
+ immVertex2fv(pos, fp + 3);
+ immEnd();
}
/* only draw second handle if this segment is bezier, and selection is ok */
@@ -382,15 +395,18 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
fp = bezt->vec[1];
UI_GetThemeColor3ubv(basecol + bezt->h2, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- glColor4ubv((GLubyte *)col);
-
- glVertex2fv(fp); glVertex2fv(fp + 3);
+ immUniformColor4ubv(col);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(pos, fp);
+ immVertex2fv(pos, fp + 3);
+ immEnd();
}
}
}
}
-
- glEnd(); /* GL_LINES */
+
+ immUnbindProgram();
}
/* Samples ---------------- */
@@ -399,36 +415,24 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
* NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't
* have a consistent appearance (due to off-pixel alignments)...
*/
-static void draw_fcurve_sample_control(float x, float y, float xscale, float yscale, float hsize)
+static void draw_fcurve_sample_control(float x, float y, float xscale, float yscale, float hsize, unsigned int pos)
{
- static GLuint displist = 0;
-
- /* initialize X shape */
- if (displist == 0) {
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- glBegin(GL_LINES);
- glVertex2f(-0.7f, -0.7f);
- glVertex2f(+0.7f, +0.7f);
-
- glVertex2f(-0.7f, +0.7f);
- glVertex2f(+0.7f, -0.7f);
- glEnd(); /* GL_LINES */
-
- glEndList();
- }
-
/* adjust view transform before starting */
- glTranslatef(x, y, 0.0f);
- glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f);
-
- /* draw! */
- glCallList(displist);
-
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+ gpuScale2f(1.0f / xscale * hsize, 1.0f / yscale * hsize);
+
+ /* draw X shape */
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex2f(pos, -0.7f, -0.7f);
+ immVertex2f(pos, +0.7f, +0.7f);
+
+ immVertex2f(pos, -0.7f, +0.7f);
+ immVertex2f(pos, +0.7f, -0.7f);
+ immEnd();
+
/* restore view transform */
- glScalef(xscale / hsize, yscale / hsize, 1.0);
- glTranslatef(-x, -y, 0.0f);
+ gpuPopMatrix();
}
/* helper func - draw keyframe vertices only for an F-Curve */
@@ -441,10 +445,6 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
hsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
UI_view2d_scale_get(&ar->v2d, &xscale, &yscale);
- /* set vertex color */
- if (fcu->flag & (FCURVE_ACTIVE | FCURVE_SELECTED)) UI_ThemeColor(TH_TEXT_HI);
- else UI_ThemeColor(TH_TEXT);
-
/* get verts */
first = fcu->fpt;
last = (first) ? (first + (fcu->totvert - 1)) : (NULL);
@@ -454,10 +454,17 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
/* anti-aliased lines for more consistent appearance */
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
- draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize);
- draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize);
-
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor((fcu->flag & FCURVE_SELECTED) ? TH_TEXT_HI : TH_TEXT);
+
+ draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize, pos);
+ draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize, pos);
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
}
@@ -466,7 +473,7 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
/* Curve ---------------- */
/* helper func - just draw the F-Curve by sampling the visible region (for drawing curves with modifiers) */
-static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid)
+static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid, unsigned int pos)
{
SpaceIpo *sipo = (SpaceIpo *)ac->sl;
ChannelDriver *driver;
@@ -536,37 +543,50 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
* - apply the unit correction factor to the calculated values so that
* the displayed values appear correctly in the viewport
*/
- glBegin(GL_LINE_STRIP);
-
+
n = (etime - stime) / samplefreq + 0.5f;
- for (i = 0; i <= n; i++) {
- float ctime = stime + i * samplefreq;
- glVertex2f(ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac);
+
+ if (n > 0) {
+ immBegin(GWN_PRIM_LINE_STRIP, (n + 1));
+
+ for (i = 0; i <= n; i++) {
+ float ctime = stime + i * samplefreq;
+ immVertex2f(pos, ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac);
+ }
+
+ immEnd();
}
-
- glEnd();
-
+
/* restore driver */
fcu->driver = driver;
}
/* helper func - draw a samples-based F-Curve */
-static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d)
+static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, const uint shdr_pos)
{
FPoint *prevfpt = fcu->fpt;
FPoint *fpt = prevfpt + 1;
float fac, v[2];
- int b = fcu->totvert - 1;
+ int b = fcu->totvert;
float unit_scale, offset;
short mapping_flag = ANIM_get_normalization_flags(ac);
+ int count = fcu->totvert;
+
+ if (prevfpt->vec[0] > v2d->cur.xmin) {
+ count++;
+ }
+
+ if ((prevfpt + b - 1)->vec[0] < v2d->cur.xmax) {
+ count++;
+ }
/* apply unit mapping */
- glPushMatrix();
+ gpuPushMatrix();
unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
- glScalef(1.0f, unit_scale, 1.0f);
- glTranslatef(0.0f, offset, 0.0f);
+ gpuScale2f(1.0f, unit_scale);
+ gpuTranslate2f(0.0f, offset);
- glBegin(GL_LINE_STRIP);
+ immBegin(GWN_PRIM_LINE_STRIP, count);
/* extrapolate to left? - left-side of view comes before first keyframe? */
if (prevfpt->vec[0] > v2d->cur.xmin) {
@@ -584,26 +604,19 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
}
- glVertex2fv(v);
+ immVertex2fv(shdr_pos, v);
}
- /* if only one sample, add it now */
- if (fcu->totvert == 1)
- glVertex2fv(prevfpt->vec);
-
/* loop over samples, drawing segments */
/* draw curve between first and last keyframe (if there are enough to do so) */
while (b--) {
/* Linear interpolation: just add one point (which should add a new line segment) */
- glVertex2fv(prevfpt->vec);
+ immVertex2fv(shdr_pos, prevfpt->vec);
/* get next pointers */
- prevfpt = fpt;
- fpt++;
-
- /* last point? */
- if (b == 0)
- glVertex2fv(prevfpt->vec);
+ if (b > 0) {
+ prevfpt++;
+ }
}
/* extrapolate to right? (see code for left-extrapolation above too) */
@@ -623,11 +636,12 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
}
- glVertex2fv(v);
+ immVertex2fv(shdr_pos, v);
}
- glEnd();
- glPopMatrix();
+ immEnd();
+
+ gpuPopMatrix();
}
/* helper func - check if the F-Curve only contains easily drawable segments
@@ -648,7 +662,7 @@ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
}
/* helper func - draw one repeat of an F-Curve (using Bezier curve approximations) */
-static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d)
+static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, unsigned int pos)
{
BezTriple *prevbezt = fcu->bezt;
BezTriple *bezt = prevbezt + 1;
@@ -661,12 +675,15 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
short mapping_flag = ANIM_get_normalization_flags(ac);
/* apply unit mapping */
- glPushMatrix();
+ gpuPushMatrix();
unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
- glScalef(1.0f, unit_scale, 1.0f);
- glTranslatef(0.0f, offset, 0.0f);
+ gpuScale2f(1.0f, unit_scale);
+ gpuTranslate2f(0.0f, offset);
- glBegin(GL_LINE_STRIP);
+ /* For now, this assumes the worst case scenario, where all the keyframes have
+ * bezier interpolation, and are drawn at full res.
+ * This is tricky to optimize, but maybe can be improved at some point... */
+ immBeginAtMost(GWN_PRIM_LINE_STRIP, (b * 32 + 3));
/* extrapolate to left? */
if (prevbezt->vec[1][0] > v2d->cur.xmin) {
@@ -691,14 +708,14 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]);
}
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
/* if only one keyframe, add it now */
if (fcu->totvert == 1) {
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
/* draw curve between first and last keyframe (if there are enough to do so) */
@@ -708,17 +725,17 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
/* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
v1[0] = bezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
else if (prevbezt->ipo == BEZT_IPO_LIN) {
/* Linear interpolation: just add one point (which should add a new line segment) */
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
else if (prevbezt->ipo == BEZT_IPO_BEZ) {
/* Bezier-Interpolation: draw curve as series of segments between keyframes
@@ -738,7 +755,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
/* only draw one */
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
else {
/* clamp resolution to max of 32 */
@@ -760,8 +777,9 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3);
BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3);
- for (fp = data; resol; resol--, fp += 3)
- glVertex2fv(fp);
+ for (fp = data; resol; resol--, fp += 3) {
+ immVertex2fv(pos, fp);
+ }
}
}
@@ -773,7 +791,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
if (b == 0) {
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
}
@@ -800,11 +818,12 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]);
}
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
- glEnd();
- glPopMatrix();
+ immEnd();
+
+ gpuPopMatrix();
}
/* Debugging -------------------------------- */
@@ -825,7 +844,16 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
/* for now, only show when debugging driver... */
//if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0)
// return;
-
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 0); /* Simple dashes. */
+
/* No curve to modify/visualize the result?
* => We still want to show the 1-1 default...
*/
@@ -833,26 +861,24 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
float t;
/* draw with thin dotted lines in style of what curve would have been */
- glColor3fv(fcu->color);
+ immUniformColor3fv(fcu->color);
- setlinestyle(20);
+ immUniform1f("dash_width", 40.0f);
+ immUniform1f("dash_factor", 0.5f);
glLineWidth(2.0f);
/* draw 1-1 line, stretching just past the screen limits
* NOTE: we need to scale the y-values to be valid for the units
*/
- glBegin(GL_LINES);
- {
- t = v2d->cur.xmin;
- glVertex2f(t, (t + offset) * unitfac);
-
- t = v2d->cur.xmax;
- glVertex2f(t, (t + offset) * unitfac);
- }
- glEnd();
-
- /* cleanup line drawing */
- setlinestyle(0);
+ immBegin(GWN_PRIM_LINES, 2);
+
+ t = v2d->cur.xmin;
+ immVertex2f(shdr_pos, t, (t + offset) * unitfac);
+
+ t = v2d->cur.xmax;
+ immVertex2f(shdr_pos, t, (t + offset) * unitfac);
+
+ immEnd();
}
/* draw driver only if actually functional */
@@ -866,53 +892,59 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
float co[2];
/* draw dotted lines leading towards this point from both axes ....... */
- glColor3f(0.9f, 0.9f, 0.9f);
- setlinestyle(5);
-
- glBegin(GL_LINES);
- {
- /* x-axis lookup */
- co[0] = x;
-
- if (y >= v2d->cur.ymin) {
- co[1] = v2d->cur.ymin - 1.0f;
- glVertex2fv(co);
-
- co[1] = y;
- glVertex2fv(co);
- }
-
- /* y-axis lookup */
+ immUniformColor3f(0.9f, 0.9f, 0.9f);
+ immUniform1f("dash_width", 10.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GWN_PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2);
+
+ /* x-axis lookup */
+ co[0] = x;
+
+ if (y >= v2d->cur.ymin) {
+ co[1] = v2d->cur.ymin - 1.0f;
+ immVertex2fv(shdr_pos, co);
+
co[1] = y;
-
- co[0] = v2d->cur.xmin - 1.0f;
- glVertex2fv(co);
-
- co[0] = x;
- glVertex2fv(co);
+ immVertex2fv(shdr_pos, co);
}
- glEnd();
-
- setlinestyle(0);
+
+ /* y-axis lookup */
+ co[1] = y;
+
+ co[0] = v2d->cur.xmin - 1.0f;
+ immVertex2fv(shdr_pos, co);
+
+ co[0] = x;
+ immVertex2fv(shdr_pos, co);
+
+ immEnd();
+ immUnbindProgram();
+
+ /* GWN_PRIM_POINTS do not survive dashed line geometry shader... */
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* x marks the spot .................................................... */
/* -> outer frame */
- glColor3f(0.9f, 0.9f, 0.9f);
+ immUniformColor3f(0.9f, 0.9f, 0.9f);
glPointSize(7.0);
- glBegin(GL_POINTS);
- glVertex2f(x, y);
- glEnd();
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex2f(shdr_pos, x, y);
+ immEnd();
/* inner frame */
- glColor3f(0.9f, 0.0f, 0.0f);
+ immUniformColor3f(0.9f, 0.0f, 0.0f);
glPointSize(3.0);
- glBegin(GL_POINTS);
- glVertex2f(x, y);
- glEnd();
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex2f(shdr_pos, x, y);
+ immEnd();
}
}
+
+ immUnbindProgram();
}
/* Public Curve-Drawing API ---------------- */
@@ -925,29 +957,43 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
FCurve *fcu;
/* draw with thick dotted lines */
- setlinestyle(10);
glLineWidth(3.0f);
/* anti-aliased lines for less jagged appearance */
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
+ glEnable(GL_LINE_SMOOTH);
+ }
glEnable(GL_BLEND);
-
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 0); /* Simple dashes. */
+ immUniform1f("dash_width", 20.0f);
+ immUniform1f("dash_factor", 0.5f);
+
/* the ghost curves are simply sampled F-Curves stored in sipo->ghostCurves */
for (fcu = sipo->ghostCurves.first; fcu; fcu = fcu->next) {
/* set whatever color the curve has set
* - this is set by the function which creates these
* - draw with a fixed opacity of 2
*/
- glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], 0.5f);
+ immUniformColor3fvAlpha(fcu->color, 0.5f);
/* simply draw the stored samples */
- draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d);
+ draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d, shdr_pos);
+ }
+
+ immUnbindProgram();
+
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
+ glDisable(GL_LINE_SMOOTH);
}
-
- /* restore settings */
- setlinestyle(0);
-
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
@@ -975,9 +1021,10 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
/* map keyframes for drawing if scaled F-Curve */
- if (adt)
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
-
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ }
+
/* draw curve:
* - curve line may be result of one or more destructive modifiers or just the raw data,
* so we need to check which method should be used
@@ -986,60 +1033,82 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
*/
/* 1) draw curve line */
+ if (((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) ||
+ (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)))
{
/* set color/drawing style for curve itself */
+ /* draw active F-Curve thicker than the rest to make it stand out */
+ if (fcu->flag & FCURVE_ACTIVE) {
+ glLineWidth(2.5);
+ }
+ else {
+ glLineWidth(1.0);
+ }
+
+ /* anti-aliased lines for less jagged appearance */
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
+ glEnable(GL_LINE_SMOOTH);
+ }
+ glEnable(GL_BLEND);
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 0); /* Simple dashes. */
+
if (BKE_fcurve_is_protected(fcu)) {
/* protected curves (non editable) are drawn with dotted lines */
- setlinestyle(2);
+ immUniform1f("dash_width", 4.0f);
+ immUniform1f("dash_factor", 0.5f);
+ }
+ else {
+ immUniform1f("dash_factor", 2.0f); /* solid line */
}
+
if (((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED)) {
/* muted curves are drawn in a grayish hue */
/* XXX should we have some variations? */
- UI_ThemeColorShade(TH_HEADER, 50);
+ immUniformThemeColorShade(TH_HEADER, 50);
}
else {
- /* set whatever color the curve has set
+ /* set whatever color the curve has set
* - unselected curves draw less opaque to help distinguish the selected ones
*/
- glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], fcurve_display_alpha(fcu));
- }
-
- /* draw active F-Curve thicker than the rest to make it stand out */
- if (fcu->flag & FCURVE_ACTIVE) {
- glLineWidth(2.0);
- }
- else {
- glLineWidth(1.0);
+ immUniformColor3fvAlpha(fcu->color, fcurve_display_alpha(fcu));
}
-
- /* anti-aliased lines for less jagged appearance */
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
-
+
/* draw F-Curve */
if ((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) {
/* draw a curve affected by modifiers or only allowed to have integer values
* by sampling it at various small-intervals over the visible region
*/
- draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid);
+ draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid, shdr_pos);
}
else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
/* just draw curve based on defined data (i.e. no modifiers) */
if (fcu->bezt) {
- if (fcurve_can_use_simple_bezt_drawing(fcu))
- draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d);
- else
- draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid);
+ if (fcurve_can_use_simple_bezt_drawing(fcu)) {
+ draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d, shdr_pos);
+ }
+ else {
+ draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid, shdr_pos);
+ }
}
else if (fcu->fpt) {
- draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d);
+ draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d, shdr_pos);
}
}
-
- /* restore settings */
- setlinestyle(0);
-
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
+
+ immUnbindProgram();
+
+ if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
+ glDisable(GL_LINE_SMOOTH);
+ }
glDisable(GL_BLEND);
}
@@ -1047,7 +1116,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
* - if the option to only show controls if the F-Curve is selected is enabled, we must obey this
*/
if (!(sipo->flag & SIPO_SELCUVERTSONLY) || (fcu->flag & FCURVE_SELECTED)) {
- if (fcurve_are_keyframes_usable(fcu) == 0) {
+ if (!fcurve_are_keyframes_usable(fcu) && !(fcu->fpt && fcu->totvert)) {
/* only draw controls if this is the active modifier */
if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) {
switch (fcm->type) {
@@ -1063,9 +1132,9 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
/* apply unit-scaling to all values via OpenGL */
- glPushMatrix();
- glScalef(1.0f, unit_scale, 1.0f);
- glTranslatef(0.0f, offset, 0.0f);
+ gpuPushMatrix();
+ gpuScale2f(1.0f, unit_scale);
+ gpuTranslate2f(0.0f, offset);
/* set this once and for all - all handles and handle-verts should use the same thickness */
glLineWidth(1.0);
@@ -1080,14 +1149,14 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
glDisable(GL_BLEND);
}
- draw_fcurve_vertices(sipo, ar, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY), unit_scale);
+ draw_fcurve_vertices(ar, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY));
}
else {
/* samples: only draw two indicators at either end as indicators */
draw_fcurve_samples(sipo, ar, fcu);
}
- glPopMatrix();
+ gpuPopMatrix();
}
}
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 839fce48b1c..2876fccaa51 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -36,7 +36,7 @@
#include <float.h>
#ifdef WITH_AUDASPACE
-# include AUD_SPECIAL_H
+# include <AUD_Special.h>
#endif
#include "MEM_guardedalloc.h"
@@ -54,13 +54,14 @@
#include "BLT_translation.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_nla.h"
#include "BKE_context.h"
#include "BKE_report.h"
+#include "DEG_depsgraph_build.h"
+
#include "UI_view2d.h"
#include "ED_anim_api.h"
@@ -2714,7 +2715,7 @@ static int graph_driver_vars_paste_exec(bContext *C, wmOperator *op)
/* successful or not? */
if (ok) {
/* rebuild depsgraph, now that there are extra deps here */
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, CTX_data_scene(C));
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index f12db310856..4b89c8db9e6 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 int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, v2d->cur.xmin, y);
+ immVertex2f(pos, v2d->cur.xmax, y);
+ immEnd();
+
+ 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(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, x, v2d->cur.ymin);
+ immVertex2f(pos, x, v2d->cur.ymax);
+ immEnd();
+
+ glDisable(GL_BLEND);
+ }
- 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;
@@ -404,7 +413,9 @@ static void graph_buttons_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, NULL, -1, true);
}
-static void graph_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void graph_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -450,6 +461,11 @@ static void graph_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AReg
if (wmn->action == NA_RENAME)
ED_region_tag_redraw(ar);
break;
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
default:
if (wmn->data == ND_KEYS)
ED_region_tag_redraw(ar);
@@ -459,7 +475,8 @@ static void graph_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), AReg
}
/* editor level listener */
-static void graph_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
+static void graph_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
+ WorkSpace *UNUSED(workspace))
{
SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first;
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt
index c60d194b620..0bc09981ba5 100644
--- a/source/blender/editors/space_image/CMakeLists.txt
+++ b/source/blender/editors/space_image/CMakeLists.txt
@@ -25,6 +25,7 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../depsgraph
../../imbuf
../../gpu
../../makesdna
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 8cb23c9e021..23c4fbbe45e 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -60,9 +60,12 @@
#include "BKE_image.h"
#include "BKE_paint.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+
#include "BLF_api.h"
#include "ED_gpencil.h"
@@ -87,7 +90,6 @@ static void draw_render_info(const bContext *C,
float zoomx,
float zoomy)
{
- RenderResult *rr;
Render *re = RE_GetSceneRender(scene);
RenderData *rd = RE_engine_get_render_data(re);
Scene *stats_scene = ED_render_job_get_scene(C);
@@ -95,7 +97,7 @@ static void draw_render_info(const bContext *C,
stats_scene = CTX_data_scene(C);
}
- rr = BKE_image_acquire_renderresult(stats_scene, ima);
+ RenderResult *rr = BKE_image_acquire_renderresult(stats_scene, ima);
if (rr && rr->text) {
float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
@@ -107,39 +109,41 @@ static void draw_render_info(const bContext *C,
if (re) {
int total_tiles;
bool need_free_tiles;
- rcti *tiles;
-
- tiles = RE_engine_get_current_tiles(re, &total_tiles, &need_free_tiles);
+ rcti *tiles = RE_engine_get_current_tiles(re, &total_tiles, &need_free_tiles);
if (total_tiles) {
- int i, x, y;
- rcti *tile;
-
/* find window pixel coordinates of origin */
+ int x, y;
UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
- glPushMatrix();
- glTranslatef(x, y, 0.0f);
- glScalef(zoomx, zoomy, 1.0f);
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+ gpuScale2f(zoomx, zoomy);
if (rd->mode & R_BORDER) {
- glTranslatef((int)(-rd->border.xmin * rd->xsch * rd->size / 100.0f),
- (int)(-rd->border.ymin * rd->ysch * rd->size / 100.0f),
- 0.0f);
+ /* TODO: round or floor instead of casting to int */
+ gpuTranslate2f((int)(-rd->border.xmin * rd->xsch * rd->size * 0.01f),
+ (int)(-rd->border.ymin * rd->ysch * rd->size * 0.01f));
}
- UI_ThemeColor(TH_FACE_SELECT);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_FACE_SELECT);
glLineWidth(1.0f);
- for (i = 0, tile = tiles; i < total_tiles; i++, tile++) {
- glaDrawBorderCorners(tile, zoomx, zoomy);
+
+ rcti *tile = tiles;
+ for (int i = 0; i < total_tiles; i++, tile++) {
+ immDrawBorderCorners(pos, tile, zoomx, zoomy);
}
+ immUnbindProgram();
+
if (need_free_tiles) {
MEM_freeN(tiles);
}
- glPopMatrix();
+ gpuPopMatrix();
}
}
}
@@ -169,28 +173,34 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* noisy, high contrast make impossible to read if lower alpha is used. */
- glColor4ub(0, 0, 0, 190);
- glRecti(0.0, 0.0, BLI_rcti_size_x(&ar->winrct) + 1, UI_UNIT_Y);
+ immUniformColor4ub(0, 0, 0, 190);
+ immRecti(pos, 0, 0, BLI_rcti_size_x(&ar->winrct) + 1, UI_UNIT_Y);
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
BLF_size(blf_mono_font, 11 * U.pixelsize, U.dpi);
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
BLI_snprintf(str, sizeof(str), "X:%-4d Y:%-4d |", x, y);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str, sizeof(str));
if (zp) {
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
BLI_snprintf(str, sizeof(str), " Z:%-.4f |", 0.5f + 0.5f * (((float)*zp) / (float)0x7fffffff));
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str, sizeof(str));
}
if (zpf) {
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
BLI_snprintf(str, sizeof(str), " Z:%-.3f |", *zpf);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
@@ -204,14 +214,14 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
else if (cp != NULL) {
BLI_snprintf(str, sizeof(str), " Val:%-.3f |", cp[0] / 255.0f);
}
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str, sizeof(str));
}
if (channels >= 3) {
- glColor3ubv(red);
+ BLF_color3ubv(blf_mono_font, red);
if (fp)
BLI_snprintf(str, sizeof(str), " R:%-.5f", fp[0]);
else if (cp)
@@ -222,7 +232,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str, sizeof(str));
- glColor3ubv(green);
+ BLF_color3ubv(blf_mono_font, green);
if (fp)
BLI_snprintf(str, sizeof(str), " G:%-.5f", fp[1]);
else if (cp)
@@ -233,7 +243,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str, sizeof(str));
- glColor3ubv(blue);
+ BLF_color3ubv(blf_mono_font, blue);
if (fp)
BLI_snprintf(str, sizeof(str), " B:%-.5f", fp[2]);
else if (cp)
@@ -245,7 +255,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
dx += BLF_width(blf_mono_font, str, sizeof(str));
if (channels == 4) {
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
if (fp)
BLI_snprintf(str, sizeof(str), " A:%-.4f", fp[3]);
else if (cp)
@@ -267,9 +277,9 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
rgba[3] = linearcol[3];
if (use_default_view)
- IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings);
else
- IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, &scene->view_settings, &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, &scene->view_settings, &scene->display_settings);
BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", rgba[0], rgba[1], rgba[2]);
BLF_position(blf_mono_font, dx, dy, 0);
@@ -305,9 +315,9 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
if (color_manage) {
if (use_default_view)
- IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings);
else
- IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings);
}
else {
copy_v4_v4(finalcol, col);
@@ -318,13 +328,18 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
BLI_rcti_init(&color_rect, dx, dx + (1.5f * UI_UNIT_X), 0.15f * UI_UNIT_Y, 0.85f * UI_UNIT_Y);
+ /* BLF uses immediate mode too, so we must reset our vertex format */
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
if (channels == 4) {
rcti color_rect_half;
int color_quater_x, color_quater_y;
color_rect_half = color_rect;
color_rect_half.xmax = BLI_rcti_cent_x(&color_rect);
- glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ /* what color ??? */
+ immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
color_rect_half = color_rect;
color_rect_half.xmin = BLI_rcti_cent_x(&color_rect);
@@ -332,31 +347,34 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
color_quater_x = BLI_rcti_cent_x(&color_rect_half);
color_quater_y = BLI_rcti_cent_y(&color_rect_half);
- glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255);
- glRecti(color_rect_half.xmin, color_rect_half.ymin, color_rect_half.xmax, color_rect_half.ymax);
+ immUniformColor3ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK);
+ immRecti(pos, color_rect_half.xmin, color_rect_half.ymin, color_rect_half.xmax, color_rect_half.ymax);
- glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255);
- glRecti(color_quater_x, color_quater_y, color_rect_half.xmax, color_rect_half.ymax);
- glRecti(color_rect_half.xmin, color_rect_half.ymin, color_quater_x, color_quater_y);
+ immUniformColor3ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT);
+ immRecti(pos, color_quater_x, color_quater_y, color_rect_half.xmax, color_rect_half.ymax);
+ immRecti(pos, color_rect_half.xmin, color_rect_half.ymin, color_quater_x, color_quater_y);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(UNPACK3(finalcol), fp ? fp[3] : (cp[3] / 255.0f));
- glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ immUniformColor3fvAlpha(finalcol, fp ? fp[3] : (cp[3] / 255.0f));
+ immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
glDisable(GL_BLEND);
}
else {
- glColor3fv(finalcol);
- glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ immUniformColor3fv(finalcol);
+ immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
}
+ immUnbindProgram();
/* draw outline */
- glColor3ub(128, 128, 128);
- sdrawbox(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ub(128, 128, 128);
+ imm_draw_box_wire_2d(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ immUnbindProgram();
dx += 1.75f * UI_UNIT_X;
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
if (channels == 1) {
if (fp) {
rgb_to_hsv(fp[0], fp[0], fp[0], &hue, &sat, &val);
@@ -375,7 +393,6 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
BLI_snprintf(str, sizeof(str), " L:%-.4f", lum);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
}
else if (channels >= 3) {
rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val);
@@ -399,70 +416,37 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
BLI_snprintf(str, sizeof(str), " L:%-.4f", lum);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
}
-
- (void)dx;
}
/* image drawing */
-
-static void sima_draw_alpha_pixels(float x1, float y1, int rectx, int recty, unsigned int *recti)
+static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *rect,
+ float zoomx, float zoomy)
{
-
- /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
- if (ENDIAN_ORDER == B_ENDIAN)
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+ float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
- glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_UNSIGNED_INT, recti);
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
-}
+ /* Slowwww */
+ int *recti = MEM_mallocN(rectx * recty * sizeof(int), "temp");
+ for (int a = rectx * recty - 1; a >= 0; a--) {
+ /* zbuffer values are signed, so we need to shift color range */
+ recti[a] = rect[a] * 0.5f + 0.5f;
+ }
-static void sima_draw_alpha_pixelsf(float x1, float y1, int rectx, int recty, float *rectf)
-{
- float *trectf = MEM_mallocN(rectx * recty * 4, "temp");
- int a, b;
-
- for (a = rectx * recty - 1, b = 4 * a + 3; a >= 0; a--, b -= 4)
- trectf[a] = rectf[b];
-
- glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, trectf);
- MEM_freeN(trectf);
- /* ogl trick below is slower... (on ATI 9600) */
-// glColorMask(1, 0, 0, 0);
-// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 3);
-// glColorMask(0, 1, 0, 0);
-// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 2);
-// glColorMask(0, 0, 1, 0);
-// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 1);
-// glColorMask(1, 1, 1, 1);
-}
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
-static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *recti)
-{
- /* zbuffer values are signed, so we need to shift color range */
- glPixelTransferf(GL_RED_SCALE, 0.5f);
- glPixelTransferf(GL_GREEN_SCALE, 0.5f);
- glPixelTransferf(GL_BLUE_SCALE, 0.5f);
- glPixelTransferf(GL_RED_BIAS, 0.5f);
- glPixelTransferf(GL_GREEN_BIAS, 0.5f);
- glPixelTransferf(GL_BLUE_BIAS, 0.5f);
-
- glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_INT, recti);
-
- glPixelTransferf(GL_RED_SCALE, 1.0f);
- glPixelTransferf(GL_GREEN_SCALE, 1.0f);
- glPixelTransferf(GL_BLUE_SCALE, 1.0f);
- glPixelTransferf(GL_RED_BIAS, 0.0f);
- glPixelTransferf(GL_GREEN_BIAS, 0.0f);
- glPixelTransferf(GL_BLUE_BIAS, 0.0f);
+ immDrawPixelsTex(&state, x1, y1, rectx, recty, GL_RED, GL_INT, GL_NEAREST, recti, zoomx, zoomy, NULL);
+
+ MEM_freeN(recti);
}
-static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty, float *rect_float)
+static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty,
+ float *rect_float, float zoomx, float zoomy)
{
float bias, scale, *rectf, clipend;
int a;
-
+ float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
+
if (scene->camera && scene->camera->type == OB_CAMERA) {
bias = ((Camera *)scene->camera->data)->clipsta;
clipend = ((Camera *)scene->camera->data)->clipend;
@@ -473,8 +457,8 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec
scale = 0.01f;
clipend = 100.0f;
}
-
- rectf = MEM_mallocN(rectx * recty * 4, "temp");
+
+ rectf = MEM_mallocN(rectx * recty * sizeof(float), "temp");
for (a = rectx * recty - 1; a >= 0; a--) {
if (rect_float[a] > clipend)
rectf[a] = 0.0f;
@@ -485,92 +469,85 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec
rectf[a] *= rectf[a];
}
}
- glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, rectf);
-
- MEM_freeN(rectf);
-}
-static int draw_image_channel_offset(SpaceImage *sima)
-{
-#ifdef __BIG_ENDIAN__
- if (sima->flag & SI_SHOW_R) return 0;
- else if (sima->flag & SI_SHOW_G) return 1;
- else return 2;
-#else
- if (sima->flag & SI_SHOW_R) return 1;
- else if (sima->flag & SI_SHOW_G) return 2;
- else return 3;
-#endif
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
+
+ immDrawPixelsTex(&state, x1, y1, rectx, recty, GL_RED, GL_FLOAT, GL_NEAREST, rectf, zoomx, zoomy, NULL);
+
+ MEM_freeN(rectf);
}
static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
{
int x, y;
- /* set zoom */
- glPixelZoom(zoomx, zoomy);
-
glaDefine2DArea(&ar->winrct);
/* find window pixel coordinates of origin */
UI_view2d_view_to_region(&ar->v2d, fx, fy, &x, &y);
/* this part is generic image display */
- if (sima->flag & SI_SHOW_ALPHA) {
- if (ibuf->rect)
- sima_draw_alpha_pixels(x, y, ibuf->x, ibuf->y, ibuf->rect);
- else if (ibuf->rect_float && ibuf->channels == 4)
- sima_draw_alpha_pixelsf(x, y, ibuf->x, ibuf->y, ibuf->rect_float);
- }
- else if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
+ if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
if (ibuf->zbuf)
- sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf);
+ sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf, zoomx, zoomy);
else if (ibuf->zbuf_float)
- sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float);
+ sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float, zoomx, zoomy);
else if (ibuf->channels == 1)
- sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float);
+ sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float, zoomx, zoomy);
}
else {
+ int clip_max_x, clip_max_y;
+ UI_view2d_view_to_region(&ar->v2d,
+ ar->v2d.cur.xmax, ar->v2d.cur.ymax,
+ &clip_max_x, &clip_max_y);
+
if (sima->flag & SI_USE_ALPHA) {
+ imm_draw_box_checker_2d(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
+
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
}
- if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B)) == 0) {
- int clip_max_x, clip_max_y;
- UI_view2d_view_to_region(&ar->v2d,
- ar->v2d.cur.xmax, ar->v2d.cur.ymax,
- &clip_max_x, &clip_max_y);
+ /* If RGBA display with color management */
+ if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) {
+
glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, GL_NEAREST,
- 0, 0, clip_max_x, clip_max_y);
+ 0, 0, clip_max_x, clip_max_y, zoomx, zoomy);
}
else {
+ float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
unsigned char *display_buffer;
void *cache_handle;
-
- /* TODO(sergey): Ideally GLSL shading should be capable of either
- * disabling some channels or displaying buffer with custom offset.
- */
- display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
-
- if (display_buffer != NULL) {
- int channel_offset = draw_image_channel_offset(sima);
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT,
- display_buffer - (4 - channel_offset));
- }
- if (cache_handle != NULL) {
- IMB_display_buffer_release(cache_handle);
+ ColorManagedViewSettings *view_settings;
+ ColorManagedDisplaySettings *display_settings;
+
+ if (sima->flag & SI_SHOW_R)
+ shuffle[0] = 1.0f;
+ else if (sima->flag & SI_SHOW_G)
+ shuffle[1] = 1.0f;
+ else if (sima->flag & SI_SHOW_B)
+ shuffle[2] = 1.0f;
+ else if (sima->flag & SI_SHOW_ALPHA)
+ shuffle[3] = 1.0f;
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle);
+
+ IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
+ display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
+
+ if (display_buffer) {
+ immDrawPixelsTex_clipping(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer,
+ 0, 0, clip_max_x, clip_max_y, zoomx, zoomy, NULL);
}
+
+ IMB_display_buffer_release(cache_handle);
}
if (sima->flag & SI_USE_ALPHA)
glDisable(GL_BLEND);
}
-
- /* reset zoom */
- glPixelZoom(1.0f, 1.0f);
}
static unsigned int *get_part_from_buffer(unsigned int *buffer, int width, short startx, short starty, short endx, short endy)
@@ -601,7 +578,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
unsigned int *rect;
int dx, dy, sx, sy, x, y;
void *cache_handle;
- int channel_offset = -1;
+ float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
/* verify valid values, just leave this a while */
if (ima->xrep < 1) return;
@@ -615,8 +592,6 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
if (!display_buffer)
return;
- glPixelZoom(zoomx, zoomy);
-
if (sima->curtile >= ima->xrep * ima->yrep)
sima->curtile = ima->xrep * ima->yrep - 1;
@@ -628,24 +603,34 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
rect = get_part_from_buffer((unsigned int *)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy);
/* draw repeated */
- if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B)) != 0) {
- channel_offset = draw_image_channel_offset(sima);
+ if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) != 0) {
+ if (sima->flag & SI_SHOW_R)
+ shuffle[0] = 1.0f;
+ else if (sima->flag & SI_SHOW_G)
+ shuffle[1] = 1.0f;
+ else if (sima->flag & SI_SHOW_B)
+ shuffle[2] = 1.0f;
+ else if (sima->flag & SI_SHOW_ALPHA)
+ shuffle[3] = 1.0f;
}
+
for (sy = 0; sy + dy <= ibuf->y; sy += dy) {
for (sx = 0; sx + dx <= ibuf->x; sx += dx) {
UI_view2d_view_to_region(&ar->v2d, fx + (float)sx / (float)ibuf->x, fy + (float)sy / (float)ibuf->y, &x, &y);
- if (channel_offset == -1) {
- glaDrawPixelsSafe(x, y, dx, dy, dx, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+
+ if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) {
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state, x, y, dx, dy, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, zoomx, zoomy, NULL);
}
else {
- glaDrawPixelsSafe(x, y, dx, dy, dx, GL_LUMINANCE, GL_UNSIGNED_INT,
- (unsigned char *)rect - (4 - channel_offset));
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle);
+
+ immDrawPixelsTex(&state, x, y, dx, dy, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, zoomx, zoomy, NULL);
}
}
}
- glPixelZoom(1.0f, 1.0f);
-
IMB_display_buffer_release(cache_handle);
MEM_freeN(rect);
@@ -701,134 +686,62 @@ void draw_image_sample_line(SpaceImage *sima)
if (sima->sample_line_hist.flag & HISTO_FLAG_SAMPLELINE) {
Histogram *hist = &sima->sample_line_hist;
- glBegin(GL_LINES);
- glColor3ub(0, 0, 0);
- glVertex2fv(hist->co[0]);
- glVertex2fv(hist->co[1]);
- glEnd();
-
- setlinestyle(1);
- glBegin(GL_LINES);
- glColor3ub(255, 255, 255);
- glVertex2fv(hist->co[0]);
- glVertex2fv(hist->co[1]);
- glEnd();
- setlinestyle(0);
-
- }
-}
-
-/* XXX becomes WM paint cursor */
-#if 0
-static void draw_image_view_tool(Scene *scene)
-{
- ToolSettings *settings = scene->toolsettings;
- Brush *brush = settings->imapaint.brush;
- int mval[2];
- float radius;
- int draw = 0;
-
- if (brush) {
- if (settings->imapaint.flag & IMAGEPAINT_DRAWING) {
- if (settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL_DRAWING)
- draw = 1;
- }
- else if (settings->imapaint.flag & IMAGEPAINT_DRAW_TOOL)
- draw = 1;
-
- if (draw) {
- getmouseco_areawin(mval);
-
- radius = BKE_brush_size_get(brush) * G.sima->zoom;
- fdrawXORcirc(mval[0], mval[1], radius);
-
- if (brush->innerradius != 1.0) {
- radius *= brush->innerradius;
- fdrawXORcirc(mval[0], mval[1], radius);
- }
- }
- }
-}
-#endif
-
-static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int *width, int *height)
-{
- Brush *brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
- ImBuf *ibuf;
- unsigned int size, alpha;
- unsigned char *display_buffer;
- unsigned char *rect, *cp;
- void *cache_handle;
-
- if (!brush || !brush->clone.image)
- return NULL;
-
- ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL);
-
- if (!ibuf)
- return NULL;
-
- display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int shdr_dashed_pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- if (!display_buffer) {
- BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
- IMB_display_buffer_release(cache_handle);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- return NULL;
- }
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- rect = MEM_dupallocN(display_buffer);
+ immUniform1i("num_colors", 2); /* Advanced dashes. */
+ immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", 2.0f);
- IMB_display_buffer_release(cache_handle);
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(shdr_dashed_pos, hist->co[0]);
+ immVertex2fv(shdr_dashed_pos, hist->co[1]);
+ immEnd();
- if (!rect) {
- BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
- return NULL;
+ immUnbindProgram();
}
-
- *width = ibuf->x;
- *height = ibuf->y;
-
- size = (*width) * (*height);
- alpha = (unsigned char)255 * brush->clone.alpha;
- cp = rect;
-
- while (size-- > 0) {
- cp[3] = alpha;
- cp += 4;
- }
-
- BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
-
- return rect;
}
static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy)
{
Brush *brush;
- int x, y, w, h;
- unsigned char *clonerect;
+ int x, y;
+ ImBuf *ibuf;
brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
- if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE)) {
- /* this is not very efficient, but glDrawPixels doesn't allow
- * drawing with alpha */
- clonerect = get_alpha_clone_image(C, scene, &w, &h);
+ if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE) && brush->clone.image) {
+ ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL);
- if (clonerect) {
+ if (ibuf) {
+ void *cache_handle = NULL;
+ float col[4] = {1.0f, 1.0f, 1.0f, brush->clone.alpha};
UI_view2d_view_to_region(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y);
- glPixelZoom(zoomx, zoomy);
+ unsigned char *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+
+ if (!display_buffer) {
+ BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
+ IMB_display_buffer_release(cache_handle);
+ return;
+ }
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, clonerect);
- glDisable(GL_BLEND);
- glPixelZoom(1.0, 1.0);
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer, zoomx, zoomy, col);
- MEM_freeN(clonerect);
+ glDisable(GL_BLEND);
+
+ BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
+ IMB_display_buffer_release(cache_handle);
}
}
}
@@ -924,23 +837,6 @@ void draw_image_main(const bContext *C, ARegion *ar)
if (show_paint)
draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
- /* XXX integrate this code */
-#if 0
- if (ibuf) {
- float xoffs = 0.0f, yoffs = 0.0f;
-
- if (image_preview_active(sa, &xim, &yim)) {
- xoffs = scene->r.disprect.xmin;
- yoffs = scene->r.disprect.ymin;
- glColor3ub(0, 0, 0);
- calc_image_view(sima, 'f');
- myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
- glRectf(0.0f, 0.0f, 1.0f, 1.0f);
- glLoadIdentity();
- }
- }
-#endif
-
if (show_viewer) {
BLI_unlock_thread(LOCK_DRAW_IMAGE);
}
@@ -1002,8 +898,12 @@ void draw_image_cache(const bContext *C, ARegion *ar)
/* Draw current frame. */
x = (cfra - sfra) / (efra - sfra + 1) * ar->winx;
- UI_ThemeColor(TH_CFRAME);
- glRecti(x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_CFRAME);
+ immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
+ immUnbindProgram();
+
ED_region_cache_draw_curfra_label(cfra, x, 8.0f * UI_DPI_FAC);
if (mask != NULL) {
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index 8f2f6595408..587689eda78 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -365,7 +365,7 @@ bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
bool ret;
- ret = EDBM_mtexpoly_check(em);
+ ret = EDBM_uv_check(em);
return ret;
}
@@ -374,10 +374,10 @@ bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
}
/* matches clip function */
-bool ED_space_image_check_show_maskedit(Scene *scene, SpaceImage *sima)
+bool ED_space_image_check_show_maskedit(ViewLayer *view_layer, SpaceImage *sima)
{
/* check editmode - this is reserved for UV editing */
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
if (ob && ob->mode & OB_MODE_EDIT && ED_space_image_show_uvedit(sima, ob)) {
return false;
}
@@ -390,8 +390,8 @@ int ED_space_image_maskedit_poll(bContext *C)
SpaceImage *sima = CTX_wm_space_image(C);
if (sima) {
- Scene *scene = CTX_data_scene(C);
- return ED_space_image_check_show_maskedit(scene, sima);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ return ED_space_image_check_show_maskedit(view_layer, sima);
}
return false;
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 52d04ad4956..47d6257366c 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -90,7 +90,7 @@ void IMAGE_OT_curves_point_set(struct wmOperatorType *ot);
void IMAGE_OT_change_frame(struct wmOperatorType *ot);
-void IMAGE_OT_read_renderlayers(struct wmOperatorType *ot);
+void IMAGE_OT_read_viewlayers(struct wmOperatorType *ot);
void IMAGE_OT_render_border(struct wmOperatorType *ot);
void IMAGE_OT_clear_render_border(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 24db8ba40fd..5a69deb82a7 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -48,6 +48,7 @@
#include "BLT_translation.h"
+#include "DNA_camera_types.h"
#include "DNA_object_types.h"
#include "DNA_node_types.h"
#include "DNA_packedFile_types.h"
@@ -56,7 +57,6 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_icons.h"
#include "BKE_image.h"
@@ -70,6 +70,8 @@
#include "BKE_sound.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
#include "GPU_draw.h"
#include "GPU_buffers.h"
@@ -792,6 +794,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
SpaceImage *sima;
ARegion *ar;
Scene *scene;
+ ViewLayer *view_layer;
Object *obedit;
Image *ima;
@@ -799,6 +802,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
sima = CTX_wm_space_image(C);
ar = CTX_wm_region(C);
scene = CTX_data_scene(C);
+ view_layer = CTX_data_view_layer(C);
obedit = CTX_data_edit_object(C);
ima = ED_space_image(sima);
@@ -810,7 +814,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
}
- else if (ED_space_image_check_show_maskedit(scene, sima)) {
+ else if (ED_space_image_check_show_maskedit(view_layer, sima)) {
if (!ED_mask_selected_minmax(C, min, max)) {
return OPERATOR_CANCELLED;
}
@@ -1306,21 +1310,23 @@ static int image_open_exec(bContext *C, wmOperator *op)
ED_space_image_set(sima, scene, obedit, ima);
iuser = &sima->iuser;
}
- else if (sa && sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
-
- for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- if (bgpic->ima == ima) {
- iuser = &bgpic->iuser;
- break;
- }
- }
- }
else {
Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
if (tex && tex->type == TEX_IMAGE) {
iuser = &tex->iuser;
}
+
+ if (iuser == NULL) {
+ Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
+ if (cam) {
+ for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
+ if (bgpic->ima == ima) {
+ iuser = &bgpic->iuser;
+ break;
+ }
+ }
+ }
+ }
}
/* initialize because of new image */
@@ -2340,7 +2346,7 @@ static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
// XXX other users?
BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_RELOAD);
- DAG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
@@ -3593,7 +3599,7 @@ void IMAGE_OT_change_frame(wmOperatorType *ot)
/* Reload cached render results... */
/* goes over all scenes, reads render layers */
-static int image_read_renderlayers_exec(bContext *C, wmOperator *UNUSED(op))
+static int image_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
SpaceImage *sima = CTX_wm_space_image(C);
@@ -3610,14 +3616,14 @@ static int image_read_renderlayers_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void IMAGE_OT_read_renderlayers(wmOperatorType *ot)
+void IMAGE_OT_read_viewlayers(wmOperatorType *ot)
{
- ot->name = "Read Render Layers";
- ot->idname = "IMAGE_OT_read_renderlayers";
- ot->description = "Read all the current scene's render layers from cache, as needed";
+ ot->name = "Read View Layers";
+ ot->idname = "IMAGE_OT_read_viewlayers";
+ ot->description = "Read all the current scene's view layers from cache, as needed";
ot->poll = space_image_main_region_poll;
- ot->exec = image_read_renderlayers_exec;
+ ot->exec = image_read_viewlayers_exec;
/* flags */
ot->flag = 0;
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 6ddf78290aa..4f595ad98c6 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -44,10 +44,15 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
+#include "BKE_editmesh.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_material.h"
+
+#include "DEG_depsgraph.h"
#include "IMB_imbuf_types.h"
@@ -59,6 +64,7 @@
#include "ED_space_api.h"
#include "ED_screen.h"
#include "ED_uvedit.h"
+#include "ED_transform.h"
#include "BIF_gl.h"
@@ -263,7 +269,7 @@ static void image_operatortypes(void)
WM_operatortype_append(IMAGE_OT_change_frame);
- WM_operatortype_append(IMAGE_OT_read_renderlayers);
+ WM_operatortype_append(IMAGE_OT_read_viewlayers);
WM_operatortype_append(IMAGE_OT_render_border);
WM_operatortype_append(IMAGE_OT_clear_render_border);
}
@@ -277,7 +283,7 @@ static void image_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "IMAGE_OT_new", NKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_open", OKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_reload", RKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_add_item(keymap, "IMAGE_OT_read_renderlayers", RKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_read_viewlayers", RKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_save", SKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_save_as", F3KEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_properties", NKEY, KM_PRESS, 0, 0);
@@ -422,27 +428,23 @@ static void image_refresh(const bContext *C, ScrArea *sa)
}
else {
/* old shading system, we set texface */
- MTexPoly *tf;
-
- if (em && EDBM_mtexpoly_check(em)) {
- tf = EDBM_mtexpoly_active_get(em, NULL, sloppy, selected);
+ if (em && EDBM_uv_check(em)) {
+ BMFace *efa = BM_mesh_active_face_get(em->bm, sloppy, selected);
- if (tf) {
+ if (efa) {
/* don't need to check for pin here, see above */
- sima->image = tf->tpage;
-
- if ((sima->flag & SI_EDITTILE) == 0) {
- sima->curtile = tf->tile;
- }
+ Image *image = BKE_object_material_edit_image_get(obedit, efa->mat_nr);
+
+ sima->image = image;
}
}
}
}
}
-static void image_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn)
+static void image_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *scene,
+ WorkSpace *workspace)
{
- Scene *scene = sc->scene;
SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
/* context changes */
@@ -535,7 +537,8 @@ static void image_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn)
case ND_TRANSFORM:
case ND_MODIFIER:
{
- Object *ob = OBACT;
+ ViewLayer *view_layer = BKE_view_layer_from_workspace_get(scene, workspace);
+ Object *ob = OBACT(view_layer);
if (ob && (ob == wmn->reference) && (ob->mode & OB_MODE_EDIT)) {
if (sima->lock && (sima->flag & SI_DRAWSHADOW)) {
ED_area_tag_refresh(sa);
@@ -587,6 +590,27 @@ static int image_context(const bContext *C, const char *member, bContextDataResu
return 0;
}
+static void IMAGE_WGT_manipulator2d(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "UV Transform Manipulator";
+ wgt->idname = "IMAGE_WGT_manipulator2d";
+
+ wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT;
+
+ wgt->poll = ED_widgetgroup_manipulator2d_poll;
+ wgt->setup = ED_widgetgroup_manipulator2d_setup;
+ wgt->refresh = ED_widgetgroup_manipulator2d_refresh;
+ wgt->draw_prepare = ED_widgetgroup_manipulator2d_draw_prepare;
+}
+
+static void image_widgets(void)
+{
+ wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(
+ &(const struct wmManipulatorMapType_Params){SPACE_IMAGE, RGN_TYPE_WINDOW});
+
+ WM_manipulatorgrouptype_append_and_link(mmap_type, IMAGE_WGT_manipulator2d);
+}
+
/************************** main region ***************************/
/* sets up the fields of the View2D from zoom and offset */
@@ -650,6 +674,16 @@ static void image_main_region_init(wmWindowManager *wm, ARegion *ar)
// image space manages own v2d
// UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+ /* manipulators */
+ if (ar->manipulator_map == NULL) {
+ const struct wmManipulatorMapType_Params wmap_params = {
+ .spaceid = SPACE_IMAGE,
+ .regionid = RGN_TYPE_WINDOW,
+ };
+ ar->manipulator_map = WM_manipulatormap_new_from_type(&wmap_params);
+ }
+ WM_manipulatormap_add_handlers(ar, ar->manipulator_map);
+
/* mask polls mode */
keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -675,7 +709,6 @@ static void image_main_region_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
keymap = WM_keymap_find(wm->defaultconf, "Image", SPACE_IMAGE, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
-
}
static void image_main_region_draw(const bContext *C, ARegion *ar)
@@ -684,9 +717,11 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
SpaceImage *sima = CTX_wm_space_image(C);
Object *obact = CTX_data_active_object(C);
Object *obedit = CTX_data_edit_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Mask *mask = NULL;
bool curve = false;
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
View2D *v2d = &ar->v2d;
//View2DScrollers *scrollers;
float col[3];
@@ -722,7 +757,7 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
- ED_uvedit_draw_main(sima, ar, scene, obedit, obact);
+ ED_uvedit_draw_main(sima, ar, scene, view_layer, obedit, obact, depsgraph);
/* check for mask (delay draw) */
if (ED_space_image_show_uvedit(sima, obedit)) {
@@ -791,6 +826,8 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
}
+ WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D);
+
draw_image_cache(C, ar);
/* scrollers? */
@@ -801,10 +838,16 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
#endif
}
-static void image_main_region_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar, wmNotifier *wmn)
+static void image_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
+ case NC_GEOM:
+ if (ELEM(wmn->data, ND_DATA, ND_SELECT))
+ WM_manipulatormap_tag_refresh(ar->manipulator_map);
+ break;
case NC_GPENCIL:
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
ED_region_tag_redraw(ar);
@@ -814,6 +857,7 @@ static void image_main_region_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion
case NC_IMAGE:
if (wmn->action == NA_PAINTING)
ED_region_tag_redraw(ar);
+ WM_manipulatormap_tag_refresh(ar->manipulator_map);
break;
case NC_MATERIAL:
if (wmn->data == ND_SHADING_LINKS) {
@@ -823,6 +867,11 @@ static void image_main_region_listener(bScreen *UNUSED(sc), ScrArea *sa, ARegion
ED_region_tag_redraw(ar);
}
break;
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
}
}
@@ -845,7 +894,9 @@ static void image_buttons_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, NULL, -1, true);
}
-static void image_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void image_buttons_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -918,7 +969,9 @@ static void image_tools_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, NULL, -1, true);
}
-static void image_tools_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void image_tools_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -964,7 +1017,9 @@ static void image_header_region_draw(const bContext *C, ARegion *ar)
ED_region_header(C, ar);
}
-static void image_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void image_header_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -1033,6 +1088,7 @@ void ED_spacetype_image(void)
st->refresh = image_refresh;
st->listener = image_listener;
st->context = image_context;
+ st->manipulators = image_widgets;
st->id_remap = image_id_remap;
/* regions: main window */
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 8dc6c4229b2..3cf833756ef 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -49,6 +49,7 @@
#include "BKE_displist.h"
#include "BKE_DerivedMesh.h"
#include "BKE_key.h"
+#include "BKE_layer.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_editmesh.h"
@@ -269,9 +270,42 @@ static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats)
stats->tottri = ob->sculpt->bm->totface;
}
+static void stats_dupli_object_group_count(SceneCollection *scene_collection, int *count)
+{
+ for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
+ (*count)++;
+ }
+
+ SceneCollection *scene_collection_nested;
+ for (scene_collection_nested = scene_collection->scene_collections.first;
+ scene_collection_nested;
+ scene_collection_nested = scene_collection_nested->next)
+ {
+ stats_dupli_object_group_count(scene_collection_nested, count);
+ }
+}
+
+static void stats_dupli_object_group_doit(SceneCollection *scene_collection, SceneStats *stats, ParticleSystem *psys,
+ const int totgroup, int *cur)
+{
+ for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
+ int tot = count_particles_mod(psys, totgroup, *cur);
+ stats_object(link->data, 0, tot, stats);
+ (*cur)++;
+ }
+
+ SceneCollection *scene_collection_nested;
+ for (scene_collection_nested = scene_collection->scene_collections.first;
+ scene_collection_nested;
+ scene_collection_nested = scene_collection_nested->next)
+ {
+ stats_dupli_object_group_doit(scene_collection_nested, stats, psys, totgroup, cur);
+ }
+}
+
static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
{
- if (base->flag & SELECT) stats->totobjsel++;
+ if (base->flag & BASE_SELECTED) stats->totobjsel++;
if (ob->transflag & OB_DUPLIPARTS) {
/* Dupli Particles */
@@ -286,21 +320,15 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
stats_object(part->dup_ob, 0, tot, stats);
}
else if (part->draw_as == PART_DRAW_GR && part->dup_group) {
- GroupObject *go;
- int tot, totgroup = 0, cur = 0;
-
- for (go = part->dup_group->gobject.first; go; go = go->next)
- totgroup++;
-
- for (go = part->dup_group->gobject.first; go; go = go->next) {
- tot = count_particles_mod(psys, totgroup, cur);
- stats_object(go->ob, 0, tot, stats);
- cur++;
- }
+ int totgroup = 0, cur = 0;
+
+ SceneCollection *scene_collection = part->dup_group->collection;
+ stats_dupli_object_group_count(scene_collection, &totgroup);
+ stats_dupli_object_group_doit(scene_collection, stats, psys, totgroup, &cur);
}
}
- stats_object(ob, base->flag & SELECT, 1, stats);
+ stats_object(ob, base->flag & BASE_SELECTED, 1, stats);
stats->totobj++;
}
else if (ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES))) {
@@ -316,23 +344,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 & BASE_SELECTED, 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 & BASE_SELECTED, 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 & BASE_SELECTED, tot, stats);
}
else {
/* No Dupli */
- stats_object(ob, base->flag & SELECT, 1, stats);
+ stats_object(ob, base->flag & BASE_SELECTED, 1, stats);
stats->totobj++;
}
}
@@ -344,10 +372,10 @@ static bool stats_is_object_dynamic_topology_sculpt(Object *ob)
}
/* Statistics displayed in info header. Called regularly on scene changes. */
-static void stats_update(Scene *scene)
+static void stats_update(Scene *scene, ViewLayer *view_layer)
{
SceneStats stats = {0};
- Object *ob = (scene->basact) ? scene->basact->object : NULL;
+ Object *ob = (view_layer->basact) ? view_layer->basact->object : NULL;
Base *base;
if (scene->obedit) {
@@ -364,23 +392,25 @@ static void stats_update(Scene *scene)
}
else {
/* Objects */
- for (base = scene->base.first; base; base = base->next)
- if (scene->lay & base->lay)
+ for (base = view_layer->object_bases.first; base; base = base->next)
+ if (base->flag & BASE_VISIBLED) {
stats_dupli_object(base, base->object, &stats);
+ }
}
- if (!scene->stats)
- scene->stats = MEM_callocN(sizeof(SceneStats), "SceneStats");
+ if (!view_layer->stats) {
+ view_layer->stats = MEM_callocN(sizeof(SceneStats), "SceneStats");
+ }
- *(scene->stats) = stats;
+ *(view_layer->stats) = stats;
}
-static void stats_string(Scene *scene)
+static void stats_string(Scene *scene, ViewLayer *view_layer)
{
#define MAX_INFO_MEM_LEN 64
- SceneStats *stats = scene->stats;
+ SceneStats *stats = view_layer->stats;
SceneStatsFmt stats_fmt;
- Object *ob = (scene->basact) ? scene->basact->object : NULL;
+ Object *ob = (view_layer->basact) ? view_layer->basact->object : NULL;
uintptr_t mem_in_use, mmap_in_use;
char memstr[MAX_INFO_MEM_LEN];
char gpumemstr[MAX_INFO_MEM_LEN] = "";
@@ -487,19 +517,20 @@ static void stats_string(Scene *scene)
#undef MAX_INFO_LEN
-void ED_info_stats_clear(Scene *scene)
+void ED_info_stats_clear(ViewLayer *view_layer)
{
- if (scene->stats) {
- MEM_freeN(scene->stats);
- scene->stats = NULL;
+ if (view_layer->stats) {
+ MEM_freeN(view_layer->stats);
+ view_layer->stats = NULL;
}
}
-const char *ED_info_stats_string(Scene *scene)
+const char *ED_info_stats_string(Scene *scene, ViewLayer *view_layer)
{
- if (!scene->stats)
- stats_update(scene);
- stats_string(scene);
+ if (!view_layer->stats) {
+ stats_update(scene, view_layer);
+ }
+ stats_string(scene, view_layer);
- return scene->stats->infostr;
+ return view_layer->stats->infostr;
}
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index 21777fd8afa..4f042364c63 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -236,7 +236,9 @@ static void info_header_region_draw(const bContext *C, ARegion *ar)
ED_region_header(C, ar);
}
-static void info_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void info_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
// SpaceInfo *sinfo = sa->spacedata.first;
@@ -251,13 +253,16 @@ static void info_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa),
}
}
-static void info_header_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void info_header_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
case NC_SCREEN:
- if (ELEM(wmn->data, ND_SCREENCAST, ND_ANIMPLAY))
+ if (ELEM(wmn->data, ND_LAYER, ND_SCREENCAST, ND_ANIMPLAY)) {
ED_region_tag_redraw(ar);
+ }
break;
case NC_WM:
if (wmn->data == ND_JOB)
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index c801a736e31..3eb0158e7b5 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -39,6 +39,8 @@
#include "BLI_utildefines.h"
#include "BLI_string_utf8.h"
+#include "GPU_immediate.h"
+
#include "BIF_gl.h"
#include "BKE_text.h"
@@ -81,9 +83,15 @@ static void console_draw_sel(const char *str, const int sel[2], const int xy[2],
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4ubv(bg_sel);
- glRecti(xy[0] + (cwidth * sta), xy[1] - 2 + lheight, xy[0] + (cwidth * end), xy[1] - 2);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4ubv(bg_sel);
+ immRecti(pos, xy[0] + (cwidth * sta), xy[1] - 2 + lheight, xy[0] + (cwidth * end), xy[1] - 2);
+
+ immUnbindProgram();
glDisable(GL_BLEND);
}
@@ -182,21 +190,25 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
cdc->sel[1] = str_len - sel_orig[0];
if (bg) {
- glColor3ubv(bg);
- glRecti(0, cdc->xy[1], cdc->winx, (cdc->xy[1] + (cdc->lheight * tot_lines)));
- }
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glColor3ubv(fg);
+ immUniformColor3ubv(bg);
+ immRecti(pos, 0, cdc->xy[1], cdc->winx, (cdc->xy[1] + (cdc->lheight * tot_lines)));
+
+ immUnbindProgram();
+ }
/* 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
+ /* BLF_color3ub(cdc->font_id, 255, 0, 0); // debug */
console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
- glColor3ubv(fg);
}
cdc->xy[1] += cdc->lheight;
@@ -210,9 +222,8 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
if (cdc->sel[0] != cdc->sel[1]) {
console_step_sel(cdc, len);
- // glColor4ub(0, 255, 0, 96); // debug
+ /* BLF_color3ub(cdc->font_id, 0, 255, 0); // debug */
console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
- glColor3ubv(fg);
}
cdc->xy[1] += cdc->lheight;
@@ -230,12 +241,17 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
else { /* simple, no wrap */
if (bg) {
- glColor3ubv(bg);
- glRecti(0, cdc->xy[1], cdc->winx, cdc->xy[1] + cdc->lheight);
- }
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glColor3ubv(fg);
+ immUniformColor3ubv(bg);
+ immRecti(pos, 0, cdc->xy[1], cdc->winx, cdc->xy[1] + cdc->lheight);
+
+ immUnbindProgram();
+ }
+ BLF_color3ubv(cdc->font_id, 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);
@@ -245,7 +261,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
isel[0] = str_len - cdc->sel[1];
isel[1] = str_len - cdc->sel[0];
- // glColor4ub(255, 255, 0, 96); // debug
+ /* BLF_color3ub(cdc->font_id, 255, 255, 0); // debug */
console_draw_sel(str, isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight, bg_sel);
console_step_sel(cdc, -(str_len + 1));
}
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 3de44174d6a..69bf51ade3a 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -461,13 +461,13 @@ static void set_sca_ob(Object *ob)
static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisflag)
{
Base *base;
- Main *bmain= CTX_data_main(C);
- Scene *scene= CTX_data_scene(C);
- Object *ob, *obt, *obact= CTX_data_active_object(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob, *obt, *obact = CTX_data_active_object(C);
ID **idar;
bSensor *sens;
bController *cont;
- unsigned int lay;
int a, nr, do_it;
/* we need a sorted object list */
@@ -485,19 +485,12 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf
ob= ob->id.next;
}
- /* XXX here it checked 3d lay */
- lay= scene->lay;
-
- base= FIRSTBASE;
- while (base) {
- if (base->lay & lay) {
- if (base->flag & 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;
- }
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) && (base->flag & 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;
}
- base= base->next;
}
if (obact) {
diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c
index 12ca141128b..af90ef487e0 100644
--- a/source/blender/editors/space_logic/space_logic.c
+++ b/source/blender/editors/space_logic/space_logic.c
@@ -198,7 +198,9 @@ static void logic_refresh(const bContext *UNUSED(C), ScrArea *UNUSED(sa))
}
-static void logic_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void logic_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index c261821db16..89bf57fdb6c 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"
@@ -123,40 +124,37 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
}
case ANIMTYPE_OBJECT:
{
- bDopeSheet *ads = (bDopeSheet *)ac->data;
- Scene *sce = (Scene *)ads->source;
+ ViewLayer *view_layer = ac->view_layer;
Base *base = (Base *)ale->data;
Object *ob = base->object;
AnimData *adt = ob->adt;
- if (nlaedit_is_tweakmode_on(ac) == 0 && (ob->restrictflag & OB_RESTRICT_SELECT) == 0) {
+ if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLED)) {
/* set selection status */
if (selectmode == SELECT_INVERT) {
/* swap select */
- base->flag ^= SELECT;
- ob->flag = base->flag;
+ ED_object_base_select(base, BA_INVERT);
+ BKE_scene_object_base_flag_sync_from_base(base);
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
else {
- Base *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;
+ for (Base *b = view_layer->object_bases.first; b; b = b->next) {
+ ED_object_base_select(b, BA_DESELECT);
+ BKE_scene_object_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;
- ob->flag |= SELECT;
+ ED_object_base_select(base, BA_SELECT);
+ BKE_scene_object_base_flag_sync_from_base(base);
if (adt) adt->flag |= ADT_UI_SELECTED;
}
/* change active object - regardless of whether it is now selected [T37883] */
- ED_base_object_activate(C, base); /* adds notifier */
+ ED_object_base_activate(C, base); /* adds notifier */
if ((adt) && (adt->flag & ADT_UI_SELECTED))
adt->flag |= ADT_UI_ACTIVE;
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 255fc0d6f8f..cb20b76a3ee 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -53,9 +53,12 @@
#include "ED_anim_api.h"
#include "ED_keyframes_draw.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_draw.h"
+
#include "WM_types.h"
#include "UI_interface.h"
@@ -97,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))
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);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ 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 */
+ /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */
+ unsigned int key_ct = BLI_listbase_count((ListBase *)&keys);
+
+ if (key_ct > 0) {
+ format = immVertexFormat();
+ pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immBegin(GWN_PRIM_POINTS, key_ct);
+
+ /* - disregard the selection status of keyframes so they draw a certain way
+ * - size is 6.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, 6.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);
}
@@ -148,57 +169,70 @@ 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, const bool dashed)
{
- bAction *act = strip->act;
- TimeMarker *marker;
-
- if (ELEM(NULL, strip->act, strip->act->markers.first))
+ const bAction *act = strip->act;
+
+ if (ELEM(NULL, act, act->markers.first))
return;
-
- for (marker = act->markers.first; marker; marker = marker->next) {
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ if (dashed) {
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ }
+ immUniformThemeColorShade(TH_STRIP_SELECT, shade);
+
+ immBeginAtMost(GWN_PRIM_LINES, BLI_listbase_count(&act->markers) * 2);
+ 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(shdr_pos, frame, yminc + 1);
+ immVertex2f(shdr_pos, frame, ymaxc - 1);
}
}
+ immEnd();
+
+ immUnbindProgram();
}
/* Markers inside a NLA-Strip */
static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc)
{
- 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);
-
- setlinestyle(3);
-
+ int shade = (strip->flag & NLASTRIP_FLAG_SELECT) ? -60 : -40;
+
/* just draw the markers in this clip */
- nla_actionclip_draw_markers(strip, yminc, ymaxc);
-
- setlinestyle(0);
+ nla_actionclip_draw_markers(strip, yminc, ymaxc, shade, true);
}
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, false);
}
}
}
- glLineWidth(1.0);
+ glLineWidth(1.0f);
}
/* Strips (Proper) ---------------------- */
@@ -266,15 +300,12 @@ 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)
{
const float yheight = ymaxc - yminc;
- /* drawing color is simply a light-gray */
- // TODO: is this color suitable?
- // XXX nasty hacked color for now... which looks quite bad too...
- glColor3f(0.7f, 0.7f, 0.7f);
-
+ immUniformColor3f(0.7f, 0.7f, 0.7f);
+
/* draw with AA'd line */
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
@@ -285,57 +316,93 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc)
float cfra;
/* plot the curve (over the strip's main region) */
- glBegin(GL_LINE_STRIP);
+ immBegin(GWN_PRIM_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);
+ float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */
CLAMP(y, 0.0f, 1.0f);
- glVertex2f(cfra, ((y * yheight) + yminc));
+ immVertex2f(pos, cfra, ((y * yheight) + yminc));
}
- glEnd(); // GL_LINE_STRIP
+
+ immEnd();
}
else {
/* use blend in/out values only if both aren't zero */
if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) {
- glBegin(GL_LINE_STRIP);
+ immBeginAtMost(GWN_PRIM_LINE_STRIP, 4);
+
/* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */
if (IS_EQF(strip->blendin, 0.0f) == 0) {
- glVertex2f(strip->start, yminc);
- glVertex2f(strip->start + strip->blendin, ymaxc);
+ immVertex2f(pos, strip->start, yminc);
+ immVertex2f(pos, strip->start + strip->blendin, ymaxc);
}
else
- glVertex2f(strip->start, ymaxc);
+ immVertex2f(pos, strip->start, ymaxc);
/* end of strip */
if (IS_EQF(strip->blendout, 0.0f) == 0) {
- glVertex2f(strip->end - strip->blendout, ymaxc);
- glVertex2f(strip->end, yminc);
+ immVertex2f(pos, strip->end - strip->blendout, ymaxc);
+ immVertex2f(pos, strip->end, yminc);
}
else
- glVertex2f(strip->end, ymaxc);
- glEnd(); // GL_LINE_STRIP
+ immVertex2f(pos, strip->end, ymaxc);
+
+ immEnd();
}
}
-
- /* time -------------------------- */
- // XXX do we want to draw this curve? in a different color too?
-
+
/* turn off AA'd lines */
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
+/* helper call to setup dashed-lines for strip outlines */
+static uint nla_draw_use_dashed_outlines(float color[4], bool muted)
+{
+ /* Note that we use dashed shader here, and make it draw solid lines if not muted... */
+ uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 0); /* Simple dashes. */
+ immUniformColor3fv(color);
+
+ /* line style: dotted for muted */
+ if (muted) {
+ /* dotted - and slightly thicker for readability of the dashes */
+ immUniform1f("dash_width", 5.0f);
+ immUniform1f("dash_factor", 0.4f);
+ glLineWidth(1.5f);
+ }
+ else {
+ /* solid line */
+ immUniform1f("dash_factor", 2.0f);
+ glLineWidth(1.0f);
+ }
+
+ return shdr_pos;
+}
+
/* 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];
+ const bool muted = ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED));
+ float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ uint shdr_pos;
/* get color of strip */
nla_strip_get_color_inside(adt, strip, color);
+ shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* draw extrapolation info first (as backdrop)
* - but this should only be drawn if track has some contribution
*/
@@ -343,7 +410,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:
@@ -352,15 +419,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(shdr_pos, v2d->cur.xmin, yminc, strip->start, ymaxc);
}
ATTR_FALLTHROUGH;
@@ -369,118 +431,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(shdr_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(true, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color);
+
+ /* restore current vertex format & program (roundbox trashes it) */
+ shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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(shdr_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, shdr_pos);
+
+ immUnbindProgram();
+
/* 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
+
+ /* 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
+ * - dashed-line shader is loaded after this block
+ */
+ if (muted) {
+ /* muted - draw dotted, squarish outline (for simplicity) */
+ shdr_pos = nla_draw_use_dashed_outlines(color, muted);
+ imm_draw_box_wire_2d(shdr_pos, strip->start, yminc, strip->end, ymaxc);
+ }
+ else {
+ /* non-muted - draw solid, rounded outline */
+ UI_draw_roundbox_shade_x(false, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1, color);
- /* draw outline */
- UI_draw_roundbox_shade_x(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1);
-
+ /* restore current vertex format & program (roundbox trashes it) */
+ shdr_pos = nla_draw_use_dashed_outlines(color, muted);
+ }
+
/* 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(GWN_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(shdr_pos, repeatPos, yminc + 4);
+ immVertex2f(shdr_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;
-
+ const float y = (ymaxc - yminc) * 0.5f + yminc;
+
+ immBeginAtMost(GWN_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(shdr_pos, cs->start, y);
+ immVertex2f(shdr_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(shdr_pos, cs->end, yminc);
+ immVertex2f(shdr_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(
@@ -491,7 +567,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) {
@@ -518,12 +593,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);
}
@@ -537,8 +614,7 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
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.
@@ -548,7 +624,7 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
/* start frame */
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);
@@ -558,20 +634,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
@@ -579,16 +649,17 @@ 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));
@@ -631,45 +702,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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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.3f);
+ immBegin(GWN_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(GWN_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);
}
@@ -691,7 +777,6 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
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);
@@ -703,7 +788,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_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 3b5604087b9..f6068087f02 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -353,7 +353,9 @@ static void nla_buttons_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, NULL, -1, true);
}
-static void nla_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void nla_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -386,7 +388,9 @@ static void nla_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegio
}
-static void nla_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void nla_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -424,6 +428,11 @@ static void nla_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), A
if (wmn->action == NA_RENAME)
ED_region_tag_redraw(ar);
break;
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
default:
if (wmn->data == ND_KEYS)
ED_region_tag_redraw(ar);
@@ -431,7 +440,9 @@ static void nla_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), A
}
}
-static void nla_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void nla_channel_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -466,7 +477,8 @@ static void nla_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
}
/* editor level listener */
-static void nla_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
+static void nla_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
+ WorkSpace *UNUSED(workspace))
{
/* context changes */
switch (wmn->category) {
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index cde818333e4..77b1351435b 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../imbuf
../../gpu
../../makesdna
@@ -47,6 +48,7 @@ set(SRC
node_draw.c
node_edit.c
node_group.c
+ node_manipulators.c
node_ops.c
node_relationships.c
node_select.c
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 8b103200862..c591433f7b1 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -50,9 +50,12 @@
#include "BLF_api.h"
#include "BLT_translation.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -62,6 +65,7 @@
#include "WM_types.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
@@ -80,49 +84,6 @@ static void node_socket_button_label(bContext *UNUSED(C), uiLayout *layout, Poin
uiItemL(layout, text, 0);
}
-
-/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
-
-#if 0 /* UNUSED */
-static void node_draw_socket_new(bNodeSocket *sock, float size)
-{
- float x = sock->locx, y = sock->locy;
-
- /* 16 values of sin function */
- static float si[16] = {
- 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
- 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
- -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
- -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
- };
- /* 16 values of cos function */
- static float co[16] = {
- 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
- -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
- -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
- 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
- };
- int a;
-
- glColor3ub(180, 180, 180);
-
- glBegin(GL_POLYGON);
- for (a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
- glEnd();
-
- glColor4ub(0, 0, 0, 150);
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
- glBegin(GL_LINE_LOOP);
- for (a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
- glEnd();
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
-}
-#endif
-
/* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */
static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -392,6 +353,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
const int font_size = data->label_size / aspect;
const float margin = (float)(NODE_DY / 4);
int label_height;
+ unsigned char color[3];
nodeLabel(ntree, node, label, sizeof(label));
@@ -400,7 +362,8 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
BLF_size(fontid, MIN2(24, font_size), U.dpi); /* clamp otherwise it can suck up a LOT of memory */
/* title color */
- UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
+ UI_GetThemeColorBlendShade3ubv(TH_TEXT, color_id, 0.4f, 10, color);
+ BLF_color3ubv(fontid, color);
width = BLF_width(fontid, label, sizeof(label));
ascender = BLF_ascender(fontid);
@@ -465,7 +428,7 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
{
rctf *rct = &node->totr;
int color_id = node_get_colorid(node);
- unsigned char color[4];
+ float color[4];
float alpha;
/* skip if out of view */
@@ -475,40 +438,32 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
return;
}
- UI_GetThemeColor4ubv(TH_NODE_FRAME, color);
- alpha = (float)(color[3]) / 255.0f;
+ UI_GetThemeColor4fv(TH_NODE_FRAME, color);
+ alpha = color[3];
/* shadow */
node_draw_shadow(snode, node, BASIS_RAD, alpha);
/* body */
- if (node->flag & NODE_CUSTOM_COLOR)
- glColor4f(node->color[0], node->color[1], node->color[2], alpha);
+ if (node->flag & NODE_CUSTOM_COLOR) {
+ rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], alpha);
+ }
else
- UI_ThemeColor4(TH_NODE_FRAME);
- glEnable(GL_BLEND);
+ UI_GetThemeColor4fv(TH_NODE_FRAME, color);
+
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
- glDisable(GL_BLEND);
+ UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
/* outline active and selected emphasis */
if (node->flag & SELECT) {
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
-
if (node->flag & NODE_ACTIVE)
- UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
+ UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -40, color);
else
- UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP,
- rct->xmin, rct->ymin,
- rct->xmax, rct->ymax, BASIS_RAD);
-
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -40, color);
+
+ UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
}
-
+
/* label */
node_draw_frame_label(ntree, node, snode->aspect);
@@ -580,15 +535,9 @@ static void node_draw_reroute_prepare(const bContext *UNUSED(C), bNodeTree *UNUS
static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode),
bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
{
- bNodeSocket *sock;
char showname[128]; /* 128 used below */
rctf *rct = &node->totr;
-#if 0 /* UNUSED */
- float size = NODE_REROUTE_SIZE;
-#endif
- float socket_size = NODE_SOCKSIZE;
-
/* skip if out of view */
if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax ||
node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax)
@@ -602,23 +551,26 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
* selection state is indicated by socket outline below!
*/
#if 0
+ float size = NODE_REROUTE_SIZE;
+
/* body */
+ float debug_color[4];
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_ThemeColor4(TH_NODE);
- glEnable(GL_BLEND);
- UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
- glDisable(GL_BLEND);
+ UI_GetThemeColor4fv(TH_NODE, debug_color);
+ UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color);
/* outline active and selected emphasis */
if (node->flag & SELECT) {
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
/* using different shades of TH_TEXT_HI for the empasis, like triangle */
- if (node->flag & NODE_ACTIVE)
- UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40);
- else
- UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
+ if (node->flag & NODE_ACTIVE) {
+ UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, 0, -40, debug_color);
+ }
+ else {
+ UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, -20, -120, debug_color);
+ }
+ UI_draw_roundbox_4fv(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
@@ -637,9 +589,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
/* only draw input socket. as they all are placed on the same position.
* highlight also if node itself is selected, since we don't display the node body separately!
*/
- for (sock = node->inputs.first; sock; sock = sock->next) {
- node_socket_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
- }
+ node_draw_sockets(&ar->v2d, C, ntree, node, false, node->flag & SELECT);
UI_block_end(C, node->block);
UI_block_draw(C, node->block);
@@ -798,7 +748,7 @@ static void node_shader_buts_geometry(uiLayout *layout, bContext *C, PointerRNA
if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
- uiItemPointerR(col, ptr, "uv_layer", &dataptr, "uv_textures", "", ICON_NONE);
+ uiItemPointerR(col, ptr, "uv_layer", &dataptr, "uv_layers", "", ICON_NONE);
uiItemPointerR(col, ptr, "color_layer", &dataptr, "vertex_colors", "", ICON_NONE);
}
else {
@@ -1016,7 +966,7 @@ static void node_shader_buts_uvmap(uiLayout *layout, bContext *C, PointerRNA *pt
if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
- uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE);
+ uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
}
}
}
@@ -1035,7 +985,7 @@ static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRN
if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
- uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE);
+ uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
}
else
uiItemR(layout, ptr, "uv_map", 0, "", 0);
@@ -1057,7 +1007,7 @@ static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *
if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
- uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE);
+ uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE);
}
else
uiItemR(row, ptr, "uv_map", 0, "", 0);
@@ -1320,7 +1270,7 @@ static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRN
uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 1);
}
-static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr)
+static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
bNode *node = ptr->data;
uiLayout *col, *row;
@@ -2218,14 +2168,21 @@ static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNo
const float cy = y + snode->zoom * backdropHeight * node->custom4;
const float cross_size = 12 * U.pixelsize;
- glColor3f(1.0, 1.0, 1.0);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- glBegin(GL_LINES);
- glVertex2f(cx - cross_size, cy - cross_size);
- glVertex2f(cx + cross_size, cy + cross_size);
- glVertex2f(cx + cross_size, cy - cross_size);
- glVertex2f(cx - cross_size, cy + cross_size);
- glEnd();
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex2f(pos, cx - cross_size, cy - cross_size);
+ immVertex2f(pos, cx + cross_size, cy + cross_size);
+ immVertex2f(pos, cx + cross_size, cy - cross_size);
+ immVertex2f(pos, cx - cross_size, cy + cross_size);
+ immEnd();
+
+ immUnbindProgram();
}
}
@@ -2244,9 +2201,6 @@ static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bN
float cx, cy, x1, x2, x3, x4;
float y1, y2, y3, y4;
-
- glColor3f(1.0, 1.0, 1.0);
-
cx = x + snode->zoom * backdropWidth * boxmask->x;
cy = y + snode->zoom * backdropHeight * boxmask->y;
@@ -2259,12 +2213,21 @@ static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bN
y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
- glBegin(GL_LINE_LOOP);
- glVertex2f(x1, y1);
- glVertex2f(x2, y2);
- glVertex2f(x3, y3);
- glVertex2f(x4, y4);
- glEnd();
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x3, y3);
+ immVertex2f(pos, x4, y4);
+ immEnd();
+
+ immUnbindProgram();
}
static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
@@ -2282,9 +2245,6 @@ static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop
float cx, cy, x1, x2, x3, x4;
float y1, y2, y3, y4;
-
- glColor3f(1.0, 1.0, 1.0);
-
cx = x + snode->zoom * backdropWidth * ellipsemask->x;
cy = y + snode->zoom * backdropHeight * ellipsemask->y;
@@ -2297,13 +2257,21 @@ static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop
y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
- glBegin(GL_LINE_LOOP);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
- glVertex2f(x1, y1);
- glVertex2f(x2, y2);
- glVertex2f(x3, y3);
- glVertex2f(x4, y4);
- glEnd();
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x3, y3);
+ immVertex2f(pos, x4, y4);
+ immEnd();
+
+ immUnbindProgram();
}
static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -2503,7 +2471,7 @@ static void node_composit_set_butfunc(bNodeType *ntype)
ntype->draw_buttons_ex = node_composit_buts_image_ex;
break;
case CMP_NODE_R_LAYERS:
- ntype->draw_buttons = node_composit_buts_renderlayers;
+ ntype->draw_buttons = node_composit_buts_viewlayers;
break;
case CMP_NODE_NORMAL:
ntype->draw_buttons = node_buts_normal;
@@ -3209,6 +3177,7 @@ void ED_init_node_socket_type_virtual(bNodeSocketType *stype)
void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeInstanceKey parent_key)
{
bNodeInstanceKey active_viewer_key = (snode->nodetree ? snode->nodetree->active_viewer_key : NODE_INSTANCE_KEY_NONE);
+ float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
Image *ima;
void *lock;
ImBuf *ibuf;
@@ -3223,12 +3192,10 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
float x, y;
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
-
+
+ gpuPushProjectionMatrix();
+ gpuPushMatrix();
+
/* somehow the offset has to be calculated inverse */
glaDefine2DArea(&ar->winrct);
@@ -3241,60 +3208,37 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
unsigned char *display_buffer = NULL;
void *cache_handle = NULL;
- if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B)) {
- int ofs;
-
- display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
-
-#ifdef __BIG_ENDIAN__
- if (snode->flag & SNODE_SHOW_R) ofs = 0;
- else if (snode->flag & SNODE_SHOW_G) ofs = 1;
- else ofs = 2;
-#else
- if (snode->flag & SNODE_SHOW_R) ofs = 1;
- else if (snode->flag & SNODE_SHOW_G) ofs = 2;
- else ofs = 3;
-#endif
+ if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) {
- glPixelZoom(snode->zoom, snode->zoom);
- /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
-
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT,
- display_buffer - (4 - ofs));
-
- glPixelZoom(1.0f, 1.0f);
- }
- else if (snode->flag & SNODE_SHOW_ALPHA) {
display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
-
- glPixelZoom(snode->zoom, snode->zoom);
- /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
-#ifdef __BIG_ENDIAN__
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
-#endif
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, display_buffer);
-
-#ifdef __BIG_ENDIAN__
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
-#endif
- glPixelZoom(1.0f, 1.0f);
+
+ if (snode->flag & SNODE_SHOW_R)
+ shuffle[0] = 1.0f;
+ else if (snode->flag & SNODE_SHOW_G)
+ shuffle[1] = 1.0f;
+ else if (snode->flag & SNODE_SHOW_B)
+ shuffle[2] = 1.0f;
+ else
+ shuffle[3] = 1.0f;
+
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle);
+
+ immDrawPixelsTex(&state, x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST,
+ display_buffer, snode->zoom, snode->zoom, NULL);
+
+ GPU_shader_unbind();
}
else if (snode->flag & SNODE_USE_ALPHA) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPixelZoom(snode->zoom, snode->zoom);
-
- glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST);
-
- glPixelZoom(1.0f, 1.0f);
+
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
+
glDisable(GL_BLEND);
}
else {
- glPixelZoom(snode->zoom, snode->zoom);
-
- glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST);
-
- glPixelZoom(1.0f, 1.0f);
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
}
if (cache_handle)
@@ -3319,20 +3263,24 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
viewer_border->ymin < viewer_border->ymax)
{
rcti pixel_border;
- UI_ThemeColor(TH_ACTIVE);
BLI_rcti_init(&pixel_border,
x + snode->zoom * viewer_border->xmin * ibuf->x,
x + snode->zoom * viewer_border->xmax * ibuf->x,
y + snode->zoom * viewer_border->ymin * ibuf->y,
y + snode->zoom * viewer_border->ymax * ibuf->y);
- glaDrawBorderCorners(&pixel_border, 1.0f, 1.0f);
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_ACTIVE);
+
+ immDrawBorderCorners(pos, &pixel_border, 1.0f, 1.0f);
+
+ immUnbindProgram();
}
}
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+
+ gpuPopProjectionMatrix();
+ gpuPopMatrix();
}
BKE_image_release_ibuf(ima, ibuf, lock);
@@ -3444,6 +3392,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
float linew;
float arrow[2], arrow1[2], arrow2[2];
glGetFloatv(GL_LINE_WIDTH, &linew);
+ unsigned int pos;
/* we can reuse the dist variable here to increment the GL curve eval amount*/
dist = 1.0f / (float)LINK_RESOL;
@@ -3467,141 +3416,89 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
arrow[0] = coord_array[LINK_ARROW][0];
arrow[1] = coord_array[LINK_ARROW][1];
}
+
+ if (do_triple || drawarrow || (!do_shaded)) {
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ }
+
if (do_triple) {
- UI_ThemeColorShadeAlpha(th_col3, -80, -120);
+ immUniformThemeColorShadeAlpha(th_col3, -80, -120);
glLineWidth(4.0f);
-
- glBegin(GL_LINE_STRIP);
+
+ immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1));
+
for (i = 0; i <= LINK_RESOL; i++) {
- glVertex2fv(coord_array[i]);
+ immVertex2fv(pos, coord_array[i]);
}
- glEnd();
+
+ immEnd();
+
if (drawarrow) {
- glBegin(GL_LINE_STRIP);
- glVertex2fv(arrow1);
- glVertex2fv(arrow);
- glVertex2fv(arrow2);
- glEnd();
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2fv(pos, arrow1);
+ immVertex2fv(pos, arrow);
+ immVertex2fv(pos, arrow2);
+ immEnd();
}
}
-
- /* XXX using GL_LINES for shaded node lines is a workaround
- * for Intel hardware, this breaks with GL_LINE_STRIP and
- * changing color in begin/end blocks.
- */
+
glLineWidth(1.5f);
- if (do_shaded) {
- glBegin(GL_LINES);
- for (i = 0; i < LINK_RESOL; i++) {
- UI_ThemeColorBlend(th_col1, th_col2, spline_step);
- glVertex2fv(coord_array[i]);
-
- UI_ThemeColorBlend(th_col1, th_col2, spline_step + dist);
- glVertex2fv(coord_array[i + 1]);
-
- spline_step += dist;
- }
- glEnd();
+
+ if (drawarrow) {
+ immUniformThemeColorBlend(th_col1, th_col2, 0.5f);
+
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex2fv(pos, arrow1);
+ immVertex2fv(pos, arrow);
+ immVertex2fv(pos, arrow2);
+ immEnd();
}
- else {
- UI_ThemeColor(th_col1);
- glBegin(GL_LINE_STRIP);
+
+ if (!do_shaded) {
+ immUniformThemeColor(th_col1);
+
+ immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1));
+
for (i = 0; i <= LINK_RESOL; i++) {
- glVertex2fv(coord_array[i]);
+ immVertex2fv(pos, coord_array[i]);
}
- glEnd();
+
+ immEnd();
}
-
- if (drawarrow) {
- glBegin(GL_LINE_STRIP);
- glVertex2fv(arrow1);
- glVertex2fv(arrow);
- glVertex2fv(arrow2);
- glEnd();
+
+ if (do_triple || drawarrow || (!do_shaded)) {
+ immUnbindProgram();
}
-
- glDisable(GL_LINE_SMOOTH);
- }
-}
-#if 0 /* not used in 2.5x yet */
-static void node_link_straight_points(View2D *UNUSED(v2d), SpaceNode *snode, bNodeLink *link, float coord_array[][2])
-{
- if (link->fromsock) {
- coord_array[0][0] = link->fromsock->locx;
- coord_array[0][1] = link->fromsock->locy;
- }
- else {
- if (snode == NULL) return;
- coord_array[0][0] = snode->mx;
- coord_array[0][1] = snode->my;
- }
- if (link->tosock) {
- coord_array[1][0] = link->tosock->locx;
- coord_array[1][1] = link->tosock->locy;
- }
- else {
- if (snode == NULL) return;
- coord_array[1][0] = snode->mx;
- coord_array[1][1] = snode->my;
- }
-}
+ if (do_shaded) {
+ unsigned char col[3];
-void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link,
- int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3)
-{
- float coord_array[2][2];
- int i;
-
- node_link_straight_points(v2d, snode, link, coord_array);
-
- glEnable(GL_LINE_SMOOTH);
-
- if (do_triple) {
- UI_ThemeColorShadeAlpha(th_col3, -80, -120);
- glLineWidth(4.0f);
-
- glBegin(GL_LINES);
- glVertex2fv(coord_array[0]);
- glVertex2fv(coord_array[1]);
- glEnd();
- }
-
- UI_ThemeColor(th_col1);
- glLineWidth(1.5f);
-
- /* XXX using GL_LINES for shaded node lines is a workaround
- * for Intel hardware, this breaks with GL_LINE_STRIP and
- * changing color in begin/end blocks.
- */
- if (do_shaded) {
- glBegin(GL_LINES);
- for (i = 0; i < LINK_RESOL - 1; ++i) {
- float t = (float)i / (float)(LINK_RESOL - 1);
- UI_ThemeColorBlend(th_col1, th_col2, t);
- glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0],
- (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]);
-
- t = (float)(i + 1) / (float)(LINK_RESOL - 1);
- UI_ThemeColorBlend(th_col1, th_col2, t);
- glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0],
- (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]);
- }
- glEnd();
- }
- else {
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < LINK_RESOL; ++i) {
- float t = (float)i / (float)(LINK_RESOL - 1);
- glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0],
- (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]);
+ Gwn_VertFormat *format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1));
+
+ for (i = 0; i <= LINK_RESOL; i++) {
+ UI_GetThemeColorBlend3ubv(th_col1, th_col2, spline_step, col);
+ immAttrib3ubv(color, col);
+
+ immVertex2fv(pos, coord_array[i]);
+
+ spline_step += dist;
+ }
+
+ immEnd();
+
+ immUnbindProgram();
}
- glEnd();
+
+ glDisable(GL_LINE_SMOOTH);
}
-
- glDisable(GL_LINE_SMOOTH);
}
-#endif
/* note; this is used for fake links in groups too */
void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
@@ -3649,27 +3546,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(GWN_PRIM_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 d7119302611..231039b2e22 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -44,16 +44,21 @@
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "DEG_depsgraph.h"
+
#include "BLF_api.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -128,10 +133,10 @@ void ED_node_tag_update_id(ID *id)
* all the users of this tree will have update
* flushed from the tree,
*/
- DAG_id_tag_update(&ntree->id, 0);
+ DEG_id_tag_update(&ntree->id, 0);
if (ntree->type == NTREE_SHADER) {
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
if (GS(id->name) == ID_MA)
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
@@ -144,12 +149,12 @@ void ED_node_tag_update_id(ID *id)
WM_main_add_notifier(NC_SCENE | ND_NODES, id);
}
else if (ntree->type == NTREE_TEXTURE) {
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
WM_main_add_notifier(NC_TEXTURE | ND_NODES, id);
}
else if (id == &ntree->id) {
/* node groups */
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
}
}
@@ -617,103 +622,16 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
glDisable(GL_LINE_SMOOTH);
}
-static void node_socket_shape_draw(
- float x, float y, float size, const float col[4], bool highlight,
- const float coords[][2], int coords_len)
-{
- int a;
-
- glColor4fv(col);
-
- glEnable(GL_BLEND);
- glBegin(GL_POLYGON);
- for (a = 0; a < coords_len; a++) {
- glVertex2f(x + size * coords[a][0], y + size * coords[a][1]);
- }
- glEnd();
- glDisable(GL_BLEND);
-
- if (highlight) {
- UI_ThemeColor(TH_TEXT_HI);
- glLineWidth(1.5f);
- }
- else {
- glColor4ub(0, 0, 0, 150);
- }
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
- glBegin(GL_LINE_LOOP);
- for (a = 0; a < coords_len; a++) {
- glVertex2f(x + size * coords[a][0], y + size * coords[a][1]);
- }
- glEnd();
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
-}
-
-
-void node_socket_draw(const bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock, float size, bool highlight)
+static void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, PointerRNA node_ptr, bNodeSocket *sock, unsigned pos, unsigned col)
{
- PointerRNA ptr, node_ptr;
+ PointerRNA ptr;
float color[4];
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
- RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
-
- /* 16 values of {sin, cos} function */
- const float shape_circle[16][2] = {
- {0.00000000f, 1.00000000f},
- {0.39435585f, 0.91895781f},
- {0.72479278f, 0.68896691f},
- {0.93775213f, 0.34730525f},
- {0.99871650f, -0.05064916f},
- {0.89780453f, -0.44039415f},
- {0.65137248f, -0.75875812f},
- {0.29936312f, -0.95413925f},
- {-0.10116832f, -0.99486932f},
- {-0.48530196f, -0.87434661f},
- {-0.79077573f, -0.61210598f},
- {-0.96807711f, -0.25065253f},
- {-0.98846832f, 0.15142777f},
- {-0.84864425f, 0.52896401f},
- {-0.57126821f, 0.82076344f},
- {-0.20129852f, 0.97952994f }
- };
-
- const float shape_diamond[4][2] = {
- {0.0f, 1.2f},
- {1.2f, 0.0f},
- {0.0f, -1.2f},
- {-1.2f, 0.0f},
- };
-
- const float shape_square[4][2] = {
- {-0.9f, 0.9f},
- {0.9f, 0.9f},
- {0.9f, -0.9f},
- {-0.9f, -0.9f},
- };
-
- const float (*shape)[2];
- int shape_len;
- switch (sock->draw_shape) {
- default:
- case SOCK_DRAW_SHAPE_CIRCLE:
- shape = shape_circle;
- shape_len = ARRAY_SIZE(shape_circle);
- break;
- case SOCK_DRAW_SHAPE_DIAMOND:
- shape = shape_diamond;
- shape_len = ARRAY_SIZE(shape_diamond);
- break;
- case SOCK_DRAW_SHAPE_SQUARE:
- shape = shape_square;
- shape_len = ARRAY_SIZE(shape_square);
- break;
- }
-
- node_socket_shape_draw(sock->locx, sock->locy, size, color, highlight, shape, shape_len);
+
+ immAttrib4fv(col, color);
+ immVertex2f(pos, sock->locx, sock->locy);
}
/* ************** Socket callbacks *********** */
@@ -722,10 +640,15 @@ static void node_draw_preview_background(float tile, rctf *rect)
{
float x, y;
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* draw checkerboard backdrop to show alpha */
- glColor3ub(120, 120, 120);
- glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- glColor3ub(160, 160, 160);
+ immUniformColor3ub(120, 120, 120);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ immUniformColor3ub(160, 160, 160);
for (y = rect->ymin; y < rect->ymax; y += tile * 2) {
for (x = rect->xmin; x < rect->xmax; x += tile * 2) {
@@ -736,7 +659,7 @@ static void node_draw_preview_background(float tile, rctf *rect)
if (y + tile > rect->ymax)
tiley = rect->ymax - y;
- glRectf(x, y, x + tilex, y + tiley);
+ immRectf(pos, x, y, x + tilex, y + tiley);
}
}
for (y = rect->ymin + tile; y < rect->ymax; y += tile * 2) {
@@ -748,9 +671,10 @@ static void node_draw_preview_background(float tile, rctf *rect)
if (y + tile > rect->ymax)
tiley = rect->ymax - y;
- glRectf(x, y, x + tilex, y + tiley);
+ immRectf(pos, x, y, x + tilex, y + tiley);
}
}
+ immUnbindProgram();
}
/* not a callback */
@@ -783,15 +707,17 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */
- glColor4f(1.0, 1.0, 1.0, 1.0);
- glPixelZoom(scale, scale);
- glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect);
- glPixelZoom(1.0f, 1.0f);
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state, draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect,
+ scale, scale, NULL);
glDisable(GL_BLEND);
- UI_ThemeColorShadeAlpha(TH_BACK, -15, +100);
- fdrawbox(draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_BACK, -15, +100);
+ imm_draw_box_wire_2d(pos, draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
+ immUnbindProgram();
}
/* common handle function for operator buttons that need to select the node first */
@@ -816,23 +742,134 @@ void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha)
else {
const float margin = 3.0f;
- glColor4f(0.0f, 0.0f, 0.0f, 0.33f);
- glEnable(GL_BLEND);
- UI_draw_roundbox(rct->xmin - margin, rct->ymin - margin,
- rct->xmax + margin, rct->ymax + margin, radius + margin);
- glDisable(GL_BLEND);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.33f};
+ UI_draw_roundbox_aa(true, rct->xmin - margin, rct->ymin - margin,
+ rct->xmax + margin, rct->ymax + margin, radius + margin, color);
+ }
+}
+
+void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *node, bool draw_outputs, bool select_all)
+{
+ const unsigned int total_input_ct = BLI_listbase_count(&node->inputs);
+ const unsigned int total_output_ct = BLI_listbase_count(&node->outputs);
+
+ if (total_input_ct + total_output_ct == 0) {
+ return;
+ }
+
+ PointerRNA node_ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+
+ float scale;
+ UI_view2d_scale_get(v2d, &scale, NULL);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+
+ glEnable(GL_BLEND);
+ GPU_enable_program_point_size();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA);
+
+ /* set handle size */
+ immUniform1f("size", 2.0f * NODE_SOCKSIZE * scale); /* 2 * size to have diameter */
+
+ if (!select_all) {
+ /* outline for unselected sockets */
+ immUniform1f("outlineWidth", 1.0f);
+ immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 0.6f);
+
+ immBeginAtMost(GWN_PRIM_POINTS, total_input_ct + total_output_ct);
+ }
+
+ /* socket inputs */
+ short selected_input_ct = 0;
+ bNodeSocket *sock;
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock))
+ continue;
+ if (select_all || (sock->flag & SELECT)) {
+ ++selected_input_ct;
+ continue;
+ }
+
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ }
+
+ /* socket outputs */
+ short selected_output_ct = 0;
+ if (draw_outputs) {
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock))
+ continue;
+ if (select_all || (sock->flag & SELECT)) {
+ ++selected_output_ct;
+ continue;
+ }
+
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ }
+ }
+
+ if (!select_all) {
+ immEnd();
+ }
+
+ /* go back and draw selected sockets */
+ if (selected_input_ct + selected_output_ct > 0) {
+ /* outline for selected sockets */
+ float c[3];
+ UI_GetThemeColor3fv(TH_TEXT_HI, c);
+ immUniform4f("outlineColor", c[0], c[1], c[2], 1.0f);
+ immUniform1f("outlineWidth", 1.5f);
+
+ immBegin(GWN_PRIM_POINTS, selected_input_ct + selected_output_ct);
+
+ if (selected_input_ct) {
+ /* socket inputs */
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock))
+ continue;
+ if (select_all || (sock->flag & SELECT)) {
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ if (--selected_input_ct == 0)
+ break; /* stop as soon as last one is drawn */
+ }
+ }
+ }
+
+ if (selected_output_ct) {
+ /* socket outputs */
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock))
+ continue;
+ if (select_all || (sock->flag & SELECT)) {
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ if (--selected_output_ct == 0)
+ break; /* stop as soon as last one is drawn */
+ }
+ }
+ }
+
+ immEnd();
}
+
+ immUnbindProgram();
+
+ GPU_disable_program_point_size();
+ glDisable(GL_BLEND);
}
static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data;
- bNodeSocket *sock;
rctf *rct = &node->totr;
float iconofs;
/* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */
float iconbutw = 0.8f * UI_UNIT_X;
int color_id = node_get_colorid(node);
+ float color[4];
char showname[128]; /* 128 used below */
View2D *v2d = &ar->v2d;
@@ -841,7 +878,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
nodeSynchronizeID(node, false);
/* skip if out of view */
- if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == false) {
+ if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) {
UI_block_end(C, node->block);
node->block = NULL;
return;
@@ -850,23 +887,24 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
/* shadow */
node_draw_shadow(snode, node, BASIS_RAD, 1.0f);
- /* header uses color from backdrop, but we make it opaqie */
- if (color_id == TH_NODE) {
- float col[3];
- UI_GetThemeColorShade3fv(color_id, -20, col);
- glColor4f(col[0], col[1], col[2], 1.0f);
+ if (node->flag & NODE_MUTED) {
+ UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color);
+ }
+ else {
+ /* header uses color from backdrop, but we make it opaque */
+ if (color_id == TH_NODE) {
+ UI_GetThemeColorShade3fv(color_id, -20, color);
+ color[3] = 1.0f;
+ }
+ else {
+ UI_GetThemeColor4fv(color_id, color);
+ }
}
- else
- UI_ThemeColor(color_id);
-
- if (node->flag & NODE_MUTED)
- UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f);
-
glLineWidth(1.0f);
UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
- UI_draw_roundbox(rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD);
+ UI_draw_roundbox_aa(true, rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD, color);
/* show/hide icons */
iconofs = rct->xmax - 0.35f * U.widget_unit;
@@ -899,10 +937,12 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
}
/* title */
- if (node->flag & SELECT)
- UI_ThemeColor(TH_SELECT);
- else
- UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
+ if (node->flag & SELECT) {
+ UI_GetThemeColor4fv(TH_SELECT, color);
+ }
+ else {
+ UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
+ }
/* open/close entirely? */
{
@@ -917,17 +957,9 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
UI_block_emboss_set(node->block, UI_EMBOSS);
/* custom draw function for this button */
- UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v');
+ UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v', color);
}
- /* this isn't doing anything for the label, so commenting out */
-#if 0
- if (node->flag & SELECT)
- UI_ThemeColor(TH_TEXT_HI);
- else
- UI_ThemeColor(TH_TEXT);
-#endif
-
nodeLabel(ntree, node, showname, sizeof(showname));
//if (node->flag & NODE_MUTED)
@@ -940,55 +972,30 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
/* body */
if (!nodeIsRegistered(node))
- UI_ThemeColor4(TH_REDALERT); /* use warning color to indicate undefined types */
- else if (node->flag & NODE_CUSTOM_COLOR)
- glColor3fv(node->color);
+ UI_GetThemeColor4fv(TH_REDALERT, color); /* use warning color to indicate undefined types */
+ else if (node->flag & NODE_CUSTOM_COLOR) {
+ rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], 1.0f);
+ }
else
- UI_ThemeColor4(TH_NODE);
- glEnable(GL_BLEND);
+ UI_GetThemeColor4fv(TH_NODE, color);
+
UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT);
- UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD);
- glDisable(GL_BLEND);
+ UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD, color);
/* outline active and selected emphasis */
if (node->flag & SELECT) {
-
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
-
- if (node->flag & NODE_ACTIVE)
- UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
- else
- UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
-
+ UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
+
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
-
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
}
/* disable lines */
if (node->flag & NODE_MUTED)
node_draw_mute_line(v2d, snode, node);
-
- /* socket inputs, buttons */
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (nodeSocketIsHidden(sock))
- continue;
-
- node_socket_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
- }
-
- /* socket outputs */
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (nodeSocketIsHidden(sock))
- continue;
-
- node_socket_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
- }
-
+ node_draw_sockets(v2d, C, ntree, node, true, false);
+
/* preview */
if (node->flag & NODE_PREVIEW && previews) {
bNodePreview *preview = BKE_node_instance_hash_lookup(previews, key);
@@ -1008,37 +1015,33 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
{
- bNodeSocket *sock;
rctf *rct = &node->totr;
float dx, centy = BLI_rctf_cent_y(rct);
float hiddenrad = BLI_rctf_size_y(rct) / 2.0f;
- float socket_size = NODE_SOCKSIZE;
int color_id = node_get_colorid(node);
+ float color[4];
char showname[128]; /* 128 is used below */
+ View2D *v2d = &ar->v2d;
+ float scale;
+
+ UI_view2d_scale_get(v2d, &scale, NULL);
/* shadow */
node_draw_shadow(snode, node, hiddenrad, 1.0f);
/* body */
- UI_ThemeColor(color_id);
if (node->flag & NODE_MUTED)
- UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f);
-
- UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
+ UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color);
+ else
+ UI_GetThemeColor4fv(color_id, color);
+
+ UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color);
/* outline active and selected emphasis */
if (node->flag & SELECT) {
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
-
- if (node->flag & NODE_ACTIVE)
- UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
- else
- UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
-
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
+
+ UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color);
}
/* custom color inline */
@@ -1046,18 +1049,19 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- glColor3fv(node->color);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad);
+ UI_draw_roundbox_3fvAlpha(false, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad, node->color, 1.0f);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
/* title */
- if (node->flag & SELECT)
- UI_ThemeColor(TH_SELECT);
- else
- UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
+ if (node->flag & SELECT) {
+ UI_GetThemeColor4fv(TH_SELECT, color);
+ }
+ else {
+ UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
+ }
/* open entirely icon */
{
@@ -1072,18 +1076,13 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
UI_block_emboss_set(node->block, UI_EMBOSS);
/* custom draw function for this button */
- UI_draw_icon_tri(rct->xmin + 10.0f, centy, 'h');
+ UI_draw_icon_tri(rct->xmin + 10.0f, centy, 'h', color);
}
/* disable lines */
if (node->flag & NODE_MUTED)
node_draw_mute_line(&ar->v2d, snode, node);
-
- if (node->flag & SELECT)
- UI_ThemeColor(TH_SELECT);
- else
- UI_ThemeColor(TH_TEXT);
-
+
if (node->miniwidth > 0.0f) {
nodeLabel(ntree, node, showname, sizeof(showname));
@@ -1097,29 +1096,35 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
}
/* scale widget thing */
- UI_ThemeColorShade(color_id, -10);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColorShade(color_id, -10);
dx = 10.0f;
- fdrawline(rct->xmax - dx, centy - 4.0f, rct->xmax - dx, centy + 4.0f);
- fdrawline(rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
-
- UI_ThemeColorShade(color_id, +30);
+
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
+
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
+ immEnd();
+
+ immUniformThemeColorShade(color_id, 30);
dx -= snode->aspect;
- fdrawline(rct->xmax - dx, centy - 4.0f, rct->xmax - dx, centy + 4.0f);
- fdrawline(rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
- /* sockets */
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- node_socket_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
- }
- }
-
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- node_socket_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
- }
- }
-
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
+
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
+ immEnd();
+
+ immUnbindProgram();
+
+ node_draw_sockets(v2d, C, ntree, node, true, false);
+
UI_block_end(C, node->block);
UI_block_draw(C, node->block);
node->block = NULL;
@@ -1260,7 +1265,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));
}
@@ -1293,12 +1298,14 @@ static void draw_group_overlay(const bContext *C, ARegion *ar)
View2D *v2d = &ar->v2d;
rctf rect = v2d->cur;
uiBlock *block;
-
+ float color[4];
+
/* shade node groups to separate them visually */
- UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
glEnable(GL_BLEND);
+
+ UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, -70, color);
UI_draw_roundbox_corner_set(UI_CNR_NONE);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0);
+ UI_draw_roundbox_4fv(true, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color);
glDisable(GL_BLEND);
/* set the block bounds to clip mouse events from underlying nodes */
@@ -1330,7 +1337,6 @@ void drawnodespace(const bContext *C, ARegion *ar)
/* only set once */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_MAP1_VERTEX_3);
/* nodes */
snode_set_context(C);
@@ -1390,7 +1396,23 @@ void drawnodespace(const bContext *C, ARegion *ar)
/* backdrop */
draw_nodespace_back_pix(C, ar, snode, path->parent_key);
-
+
+ {
+ float original_proj[4][4];
+ gpuGetProjectionMatrix(original_proj);
+
+ gpuPushMatrix();
+ gpuLoadIdentity();
+
+ glaDefine2DArea(&ar->winrct);
+ wmOrtho2_pixelspace(ar->winx, ar->winy);
+
+ WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D);
+
+ gpuPopMatrix();
+ gpuLoadProjectionMatrix(original_proj);
+ }
+
draw_nodetree(C, ar, ntree, path->parent_key);
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index e38b48d4bb8..94c31a7ddb7 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -41,7 +41,6 @@
#include "BLI_blenlib.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_library.h"
@@ -50,6 +49,8 @@
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -123,7 +124,7 @@ static int compo_get_recalc_flags(const bContext *C)
int recalc_flags = 0;
for (win = wm->windows.first; win; win = win->next) {
- bScreen *sc = win->screen;
+ const bScreen *sc = WM_window_get_active_screen(win);
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
@@ -328,11 +329,11 @@ void snode_dag_update(bContext *C, SpaceNode *snode)
if (snode->edittree != snode->nodetree) {
FOREACH_NODETREE(bmain, tntree, id) {
if (ntreeHasTree(tntree, snode->edittree))
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
} FOREACH_NODETREE_END
}
- DAG_id_tag_update(snode->id, 0);
+ DEG_id_tag_update(snode->id, 0);
}
void snode_notify(bContext *C, SpaceNode *snode)
@@ -382,7 +383,7 @@ bool ED_node_is_texture(struct SpaceNode *snode)
/* called from shading buttons or header */
void ED_node_shader_default(const bContext *C, ID *id)
{
- Scene *scene = CTX_data_scene(C);
+ ViewRender *view_render = CTX_data_view_render(C);
bNode *in, *out;
bNodeSocket *fromsock, *tosock, *sock;
bNodeTree *ntree;
@@ -397,7 +398,11 @@ void ED_node_shader_default(const bContext *C, ID *id)
Material *ma = (Material *)id;
ma->nodetree = ntree;
- if (BKE_scene_use_new_shading_nodes(scene)) {
+ if (BKE_viewrender_uses_blender_eevee(view_render)) {
+ output_type = SH_NODE_OUTPUT_MATERIAL;
+ shader_type = SH_NODE_BSDF_PRINCIPLED;
+ }
+ else if (BKE_viewrender_use_new_shading_nodes(view_render)) {
output_type = SH_NODE_OUTPUT_MATERIAL;
shader_type = SH_NODE_BSDF_DIFFUSE;
}
@@ -455,7 +460,7 @@ void ED_node_shader_default(const bContext *C, ID *id)
nodeAddLink(ntree, in, fromsock, out, tosock);
/* default values */
- if (BKE_scene_use_new_shading_nodes(scene)) {
+ if (BKE_viewrender_use_new_shading_nodes(view_render)) {
PointerRNA sockptr;
sock = in->inputs.first;
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
@@ -695,12 +700,12 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
for (scene = bmain->scene.first; scene; scene = scene->id.next) {
if (scene->nodetree && scene->use_nodes && ntreeHasTree(scene->nodetree, ntree)) {
if (node->id == NULL || node->id == (ID *)scene) {
- int num_layers = BLI_listbase_count(&scene->r.layers);
- scene->r.actlay = node->custom1;
+ int num_layers = BLI_listbase_count(&scene->view_layers);
+ scene->active_view_layer = node->custom1;
/* Clamp the value, because it might have come from a different
* scene which could have more render layers than new one.
*/
- scene->r.actlay = min_ff(scene->r.actlay, num_layers - 1);
+ scene->active_view_layer = min_ff(scene->active_view_layer, num_layers - 1);
}
}
}
@@ -1271,7 +1276,7 @@ bool ED_node_select_check(ListBase *lb)
/* goes over all scenes, reads render layers */
-static int node_read_renderlayers_exec(bContext *C, wmOperator *UNUSED(op))
+static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
@@ -1301,14 +1306,14 @@ static int node_read_renderlayers_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void NODE_OT_read_renderlayers(wmOperatorType *ot)
+void NODE_OT_read_viewlayers(wmOperatorType *ot)
{
- ot->name = "Read Render Layers";
- ot->idname = "NODE_OT_read_renderlayers";
+ ot->name = "Read View Layers";
+ ot->idname = "NODE_OT_read_viewlayers";
ot->description = "Read all render layers of all used scenes";
- ot->exec = node_read_renderlayers_exec;
+ ot->exec = node_read_viewlayers_exec;
ot->poll = composite_node_active;
@@ -1361,13 +1366,13 @@ int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op))
}
}
if (node) {
- SceneRenderLayer *srl = BLI_findlink(&sce->r.layers, node->custom1);
+ ViewLayer *view_layer = BLI_findlink(&sce->view_layers, node->custom1);
- if (srl) {
+ if (view_layer) {
PointerRNA op_ptr;
WM_operator_properties_create(&op_ptr, "RENDER_OT_render");
- RNA_string_set(&op_ptr, "layer", srl->name);
+ RNA_string_set(&op_ptr, "layer", view_layer->name);
RNA_string_set(&op_ptr, "scene", sce->id.name + 2);
/* to keep keypositions */
@@ -2348,7 +2353,7 @@ void NODE_OT_tree_socket_move(wmOperatorType *ot)
static int node_shader_script_update_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- RenderEngineType *type = RE_engines_find(scene->r.engine);
+ RenderEngineType *type = RE_engines_find(scene->view_render.engine_id);
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
Text *text;
@@ -2418,7 +2423,7 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op)
bool found = false;
/* setup render engine */
- type = RE_engines_find(scene->r.engine);
+ type = RE_engines_find(scene->view_render.engine_id);
engine = RE_engine_create(type);
engine->reports = op->reports;
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 352f9e51012..7138b63364a 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -67,13 +67,11 @@ void snode_group_offset(struct SpaceNode *snode, float *x, float *y); /* transfo
/* node_draw.c */
int node_get_colorid(struct bNode *node);
-void node_socket_draw(
- const struct bContext *C, struct bNodeTree *ntree, struct bNode *node,
- struct bNodeSocket *sock, float size, bool highlight);
int node_get_resize_cursor(int directions);
void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha);
void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
+void node_draw_sockets(struct View2D *v2d, const struct bContext *C, struct bNodeTree *ntree, struct bNode *node, bool draw_outputs, bool select_all);
void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
int node_select_area_default(struct bNode *node, int x, int y);
int node_tweak_area_default(struct bNode *node, int x, int y);
@@ -199,7 +197,7 @@ void NODE_OT_options_toggle(struct wmOperatorType *ot);
void NODE_OT_node_copy_color(struct wmOperatorType *ot);
void NODE_OT_read_fullsamplelayers(struct wmOperatorType *ot);
-void NODE_OT_read_renderlayers(struct wmOperatorType *ot);
+void NODE_OT_read_viewlayers(struct wmOperatorType *ot);
void NODE_OT_render_changed(struct wmOperatorType *ot);
void NODE_OT_output_file_add_socket(struct wmOperatorType *ot);
@@ -221,6 +219,13 @@ void NODE_OT_shader_script_update(struct wmOperatorType *ot);
void NODE_OT_viewer_border(struct wmOperatorType *ot);
void NODE_OT_clear_viewer_border(struct wmOperatorType *ot);
+/* node_widgets.c */
+void NODE_WGT_backdrop_transform(struct wmManipulatorGroupType *wgt);
+void NODE_WGT_backdrop_crop(struct wmManipulatorGroupType *wgt);
+void NODE_WGT_backdrop_sun_beams(struct wmManipulatorGroupType *wgt);
+void NODE_WGT_backdrop_corner_pin(struct wmManipulatorGroupType *wgt);
+
+
extern const char *node_context_dir[];
// XXXXXX
diff --git a/source/blender/editors/space_node/node_manipulators.c b/source/blender/editors/space_node/node_manipulators.c
new file mode 100644
index 00000000000..73b0f44b043
--- /dev/null
+++ b/source/blender/editors/space_node/node_manipulators.c
@@ -0,0 +1,616 @@
+/*
+ * ***** 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_node/node_manipulators.c
+ * \ingroup spnode
+ */
+
+#include <math.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_math_matrix.h"
+#include "BLI_math_vector.h"
+#include "BLI_rect.h"
+
+#include "BKE_context.h"
+#include "BKE_image.h"
+
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "node_intern.h"
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Local Utilities
+ * \{ */
+
+static void node_manipulator_calc_matrix_space(
+ const SpaceNode *snode, const ARegion *ar, float matrix_space[4][4])
+{
+ unit_m4(matrix_space);
+ mul_v3_fl(matrix_space[0], snode->zoom);
+ mul_v3_fl(matrix_space[1], snode->zoom);
+ matrix_space[3][0] = (ar->winx / 2) + snode->xof;
+ matrix_space[3][1] = (ar->winy / 2) + snode->yof;
+}
+
+static void node_manipulator_calc_matrix_space_with_image_dims(
+ const SpaceNode *snode, const ARegion *ar, const float image_dims[2], float matrix_space[4][4])
+{
+ unit_m4(matrix_space);
+ mul_v3_fl(matrix_space[0], snode->zoom * image_dims[0]);
+ mul_v3_fl(matrix_space[1], snode->zoom * image_dims[1]);
+ matrix_space[3][0] = ((ar->winx / 2) + snode->xof) - ((image_dims[0] / 2.0f) * snode->zoom);
+ matrix_space[3][1] = ((ar->winy / 2) + snode->yof) - ((image_dims[1] / 2.0f) * snode->zoom);
+}
+
+/** \} */
+
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Backdrop Manipulator
+ * \{ */
+
+static void manipulator_node_backdrop_prop_matrix_get(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ float (*matrix)[4] = value_p;
+ BLI_assert(mpr_prop->type->array_length == 16);
+ const SpaceNode *snode = mpr_prop->custom_func.user_data;
+ matrix[0][0] = snode->zoom;
+ matrix[1][1] = snode->zoom;
+ matrix[3][0] = snode->xof;
+ matrix[3][1] = snode->yof;
+}
+
+static void manipulator_node_backdrop_prop_matrix_set(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ const float (*matrix)[4] = value_p;
+ BLI_assert(mpr_prop->type->array_length == 16);
+ SpaceNode *snode = mpr_prop->custom_func.user_data;
+ snode->zoom = matrix[0][0];
+ snode->zoom = matrix[1][1];
+ snode->xof = matrix[3][0];
+ snode->yof = matrix[3][1];
+}
+
+static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ if ((snode->flag & SNODE_BACKDRAW) == 0) {
+ return false;
+ }
+
+ if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
+ bNode *node = nodeGetActive(snode->edittree);
+
+ if (node && ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
+
+ wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL);
+
+ RNA_enum_set(wwrapper->manipulator->ptr, "transform",
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM);
+
+ mgroup->customdata = wwrapper;
+}
+
+static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ wmManipulator *cage = ((wmManipulatorWrapper *)mgroup->customdata)->manipulator;
+ const ARegion *ar = CTX_wm_region(C);
+ /* center is always at the origin */
+ const float origin[3] = {ar->winx / 2, ar->winy / 2};
+
+ void *lock;
+ Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ const float dims[2] = {
+ (ibuf->x > 0) ? ibuf->x : 64.0f,
+ (ibuf->y > 0) ? ibuf->y : 64.0f,
+ };
+
+ RNA_float_set_array(cage->ptr, "dimensions", dims);
+ WM_manipulator_set_matrix_location(cage, origin);
+ WM_manipulator_set_flag(cage, WM_MANIPULATOR_HIDDEN, false);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ SpaceNode *snode = CTX_wm_space_node(C);
+#if 0
+ PointerRNA nodeptr;
+ RNA_pointer_create(snode->id, &RNA_SpaceNodeEditor, snode, &nodeptr);
+ WM_manipulator_target_property_def_rna(cage, "offset", &nodeptr, "backdrop_offset", -1);
+ WM_manipulator_target_property_def_rna(cage, "scale", &nodeptr, "backdrop_zoom", -1);
+#endif
+
+ WM_manipulator_target_property_def_func(
+ cage, "matrix",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_node_backdrop_prop_matrix_get,
+ .value_set_fn = manipulator_node_backdrop_prop_matrix_set,
+ .range_get_fn = NULL,
+ .user_data = snode,
+ });
+ }
+ else {
+ WM_manipulator_set_flag(cage, WM_MANIPULATOR_HIDDEN, true);
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+}
+
+void NODE_WGT_backdrop_transform(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Backdrop Transform Widget";
+ wgt->idname = "NODE_WGT_backdrop_transform";
+
+ wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT;
+
+ wgt->poll = WIDGETGROUP_node_transform_poll;
+ wgt->setup = WIDGETGROUP_node_transform_setup;
+ wgt->refresh = WIDGETGROUP_node_transform_refresh;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Crop Manipulator
+ * \{ */
+
+struct NodeCropWidgetGroup {
+ wmManipulator *border;
+
+ struct {
+ float dims[2];
+ } state;
+
+ struct {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ bContext *context;
+ } update_data;
+};
+
+static void manipulator_node_crop_update(struct NodeCropWidgetGroup *crop_group)
+{
+ RNA_property_update(crop_group->update_data.context, &crop_group->update_data.ptr, crop_group->update_data.prop);
+}
+
+static void two_xy_to_rect(const NodeTwoXYs *nxy, rctf *rect, const float dims[2], bool is_relative)
+{
+ if (is_relative) {
+ rect->xmin = nxy->fac_x1;
+ rect->xmax = nxy->fac_x2;
+ rect->ymin = nxy->fac_y1;
+ rect->ymax = nxy->fac_y2;
+ }
+ else {
+ rect->xmin = nxy->x1 / dims[0];
+ rect->xmax = nxy->x2 / dims[0];
+ rect->ymin = nxy->y1 / dims[1];
+ rect->ymax = nxy->y2 / dims[1];
+ }
+}
+
+static void two_xy_from_rect(NodeTwoXYs *nxy, const rctf *rect, const float dims[2], bool is_relative)
+{
+ if (is_relative) {
+ nxy->fac_x1 = rect->xmin;
+ nxy->fac_x2 = rect->xmax;
+ nxy->fac_y1 = rect->ymin;
+ nxy->fac_y2 = rect->ymax;
+ }
+ else {
+ nxy->x1 = rect->xmin * dims[0];
+ nxy->x2 = rect->xmax * dims[0];
+ nxy->y1 = rect->ymin * dims[1];
+ nxy->y2 = rect->ymax * dims[1];
+ }
+}
+
+/* scale callbacks */
+static void manipulator_node_crop_prop_matrix_get(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ float (*matrix)[4] = value_p;
+ BLI_assert(mpr_prop->type->array_length == 16);
+ struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata;
+ const float *dims = crop_group->state.dims;
+ const bNode *node = mpr_prop->custom_func.user_data;
+ const NodeTwoXYs *nxy = node->storage;
+ bool is_relative = (bool)node->custom2;
+ rctf rct;
+ two_xy_to_rect(nxy, &rct, dims, is_relative);
+ matrix[0][0] = BLI_rctf_size_x(&rct);
+ matrix[1][1] = BLI_rctf_size_y(&rct);
+ matrix[3][0] = (BLI_rctf_cent_x(&rct) - 0.5f) * dims[0];
+ matrix[3][1] = (BLI_rctf_cent_y(&rct) - 0.5f) * dims[1];
+}
+
+static void manipulator_node_crop_prop_matrix_set(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ const float (*matrix)[4] = value_p;
+ BLI_assert(mpr_prop->type->array_length == 16);
+ struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata;
+ const float *dims = crop_group->state.dims;
+ bNode *node = mpr_prop->custom_func.user_data;
+ NodeTwoXYs *nxy = node->storage;
+ bool is_relative = (bool)node->custom2;
+ rctf rct;
+ two_xy_to_rect(nxy, &rct, dims, is_relative);
+ BLI_rctf_resize(&rct, matrix[0][0], matrix[1][1]);
+ BLI_rctf_recenter(&rct, (matrix[3][0] / dims[0]) + 0.5f, (matrix[3][1] / dims[1]) + 0.5f);
+ BLI_rctf_isect(&(rctf){.xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1}, &rct, &rct);
+ two_xy_from_rect(nxy, &rct, dims, is_relative);
+ manipulator_node_crop_update(crop_group);
+}
+
+static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ if ((snode->flag & SNODE_BACKDRAW) == 0) {
+ return false;
+ }
+
+ if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
+ bNode *node = nodeGetActive(snode->edittree);
+
+ if (node && ELEM(node->type, CMP_NODE_CROP)) {
+ /* ignore 'use_crop_size', we can't usefully edit the crop in this case. */
+ if ((node->custom1 & (0 << 1)) == 0) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ struct NodeCropWidgetGroup *crop_group = MEM_mallocN(sizeof(struct NodeCropWidgetGroup), __func__);
+
+ crop_group->border = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL);
+
+ RNA_enum_set(crop_group->border->ptr, "transform",
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE);
+
+ mgroup->customdata = crop_group;
+}
+
+static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ ARegion *ar = CTX_wm_region(C);
+ wmManipulator *mpr = mgroup->manipulators.first;
+
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ node_manipulator_calc_matrix_space(snode, ar, mpr->matrix_space);
+}
+
+static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ struct NodeCropWidgetGroup *crop_group = mgroup->customdata;
+ wmManipulator *mpr = crop_group->border;
+
+ void *lock;
+ Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ crop_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
+ crop_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
+
+ RNA_float_set_array(mpr->ptr, "dimensions", crop_group->state.dims);
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node = nodeGetActive(snode->edittree);
+
+ crop_group->update_data.context = (bContext *)C;
+ RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeCrop, node, &crop_group->update_data.ptr);
+ crop_group->update_data.prop = RNA_struct_find_property(&crop_group->update_data.ptr, "relative");
+
+ WM_manipulator_target_property_def_func(
+ mpr, "matrix",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_node_crop_prop_matrix_get,
+ .value_set_fn = manipulator_node_crop_prop_matrix_set,
+ .range_get_fn = NULL,
+ .user_data = node,
+ });
+ }
+ else {
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+}
+
+void NODE_WGT_backdrop_crop(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Backdrop Crop Widget";
+ wgt->idname = "NODE_WGT_backdrop_crop";
+
+ wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT;
+
+ wgt->poll = WIDGETGROUP_node_crop_poll;
+ wgt->setup = WIDGETGROUP_node_crop_setup;
+ wgt->draw_prepare = WIDGETGROUP_node_crop_draw_prepare;
+ wgt->refresh = WIDGETGROUP_node_crop_refresh;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Sun Beams
+ * \{ */
+
+struct NodeSunBeamsWidgetGroup {
+ wmManipulator *manipulator;
+
+ struct {
+ float dims[2];
+ } state;
+};
+
+static bool WIDGETGROUP_node_sbeam_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ if ((snode->flag & SNODE_BACKDRAW) == 0) {
+ return false;
+ }
+
+ if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
+ bNode *node = nodeGetActive(snode->edittree);
+
+ if (node && ELEM(node->type, CMP_NODE_SUNBEAMS)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ struct NodeSunBeamsWidgetGroup *sbeam_group = MEM_mallocN(sizeof(struct NodeSunBeamsWidgetGroup), __func__);
+
+ sbeam_group->manipulator = WM_manipulator_new("MANIPULATOR_WT_grab_3d", mgroup, NULL);
+ wmManipulator *mpr = sbeam_group->manipulator;
+
+ RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_CROSS_2D);
+
+ mpr->scale_basis = 0.05f;
+
+ mgroup->customdata = sbeam_group;
+}
+
+static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ struct NodeSunBeamsWidgetGroup *sbeam_group = mgroup->customdata;
+ ARegion *ar = CTX_wm_region(C);
+ wmManipulator *mpr = mgroup->manipulators.first;
+
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ node_manipulator_calc_matrix_space_with_image_dims(snode, ar, sbeam_group->state.dims, mpr->matrix_space);
+}
+
+static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ struct NodeSunBeamsWidgetGroup *sbeam_group = mgroup->customdata;
+ wmManipulator *mpr = sbeam_group->manipulator;
+
+ void *lock;
+ Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ sbeam_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
+ sbeam_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
+
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node = nodeGetActive(snode->edittree);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ PointerRNA nodeptr;
+ RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr);
+ WM_manipulator_target_property_def_rna(mpr, "offset", &nodeptr, "source", -1);
+
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_MODAL, true);
+ }
+ else {
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+}
+
+void NODE_WGT_backdrop_sun_beams(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Sun Beams Widget";
+ wgt->idname = "NODE_WGT_sbeam";
+
+ wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT;
+
+ wgt->poll = WIDGETGROUP_node_sbeam_poll;
+ wgt->setup = WIDGETGROUP_node_sbeam_setup;
+ wgt->draw_prepare = WIDGETGROUP_node_sbeam_draw_prepare;
+ wgt->refresh = WIDGETGROUP_node_sbeam_refresh;
+}
+
+/** \} */
+
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Corner Pin
+ * \{ */
+
+struct NodeCornerPinWidgetGroup {
+ wmManipulator *manipulators[4];
+
+ struct {
+ float dims[2];
+ } state;
+};
+
+static bool WIDGETGROUP_node_corner_pin_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ if ((snode->flag & SNODE_BACKDRAW) == 0) {
+ return false;
+ }
+
+ if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
+ bNode *node = nodeGetActive(snode->edittree);
+
+ if (node && ELEM(node->type, CMP_NODE_CORNERPIN)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ struct NodeCornerPinWidgetGroup *cpin_group = MEM_mallocN(sizeof(struct NodeCornerPinWidgetGroup), __func__);
+ const wmManipulatorType *wt_grab_3d = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", false);
+
+ for (int i = 0; i < 4; i++) {
+ cpin_group->manipulators[i] = WM_manipulator_new_ptr(wt_grab_3d, mgroup, NULL);
+ wmManipulator *mpr = cpin_group->manipulators[i];
+
+ RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_CROSS_2D);
+
+ mpr->scale_basis = 0.01f;
+ }
+
+ mgroup->customdata = cpin_group;
+}
+
+static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ struct NodeCornerPinWidgetGroup *cpin_group = mgroup->customdata;
+ ARegion *ar = CTX_wm_region(C);
+
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ float matrix_space[4][4];
+ node_manipulator_calc_matrix_space_with_image_dims(snode, ar, cpin_group->state.dims, matrix_space);
+
+ for (int i = 0; i < 4; i++) {
+ wmManipulator *mpr = cpin_group->manipulators[i];
+ copy_m4_m4(mpr->matrix_space, matrix_space);
+ }
+}
+
+static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ struct NodeCornerPinWidgetGroup *cpin_group = mgroup->customdata;
+
+ void *lock;
+ Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ cpin_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
+ cpin_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
+
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node = nodeGetActive(snode->edittree);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ int i = 0;
+ for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) {
+ if (sock->type == SOCK_VECTOR) {
+ wmManipulator *mpr = cpin_group->manipulators[i++];
+
+ PointerRNA sockptr;
+ RNA_pointer_create((ID *)snode->edittree, &RNA_NodeSocket, sock, &sockptr);
+ WM_manipulator_target_property_def_rna(mpr, "offset", &sockptr, "default_value", -1);
+
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_MODAL, true);
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < 4; i++) {
+ wmManipulator *mpr = cpin_group->manipulators[i];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
+ }
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+}
+
+void NODE_WGT_backdrop_corner_pin(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Corner Pin Widget";
+ wgt->idname = "NODE_WGT_backdrop_corner_pin";
+
+ wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT;
+
+ wgt->poll = WIDGETGROUP_node_corner_pin_poll;
+ wgt->setup = WIDGETGROUP_node_corner_pin_setup;
+ wgt->draw_prepare = WIDGETGROUP_node_corner_pin_draw_prepare;
+ wgt->refresh = WIDGETGROUP_node_corner_pin_refresh;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 5118d52efc4..1859785173c 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -94,7 +94,7 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_insert_offset);
- WM_operatortype_append(NODE_OT_read_renderlayers);
+ WM_operatortype_append(NODE_OT_read_viewlayers);
WM_operatortype_append(NODE_OT_read_fullsamplelayers);
WM_operatortype_append(NODE_OT_render_changed);
@@ -335,7 +335,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "exit", true);
- WM_keymap_add_item(keymap, "NODE_OT_read_renderlayers", RKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "NODE_OT_read_viewlayers", RKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_read_fullsamplelayers", RKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_render_changed", ZKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index 5d0877a1eff..c791b9f6eae 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -559,6 +559,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewRender *view_render = CTX_data_view_render(C);
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *but = (uiBut *)but_p;
uiLayout *split, *column;
@@ -575,7 +576,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
arg->layout = split;
if (ntreetype && ntreetype->foreach_nodeclass)
- ntreetype->foreach_nodeclass(scene, arg, node_menu_column_foreach_cb);
+ ntreetype->foreach_nodeclass(view_render, arg, node_menu_column_foreach_cb);
column = uiLayoutColumn(split, false);
UI_block_layout_set_current(block, column);
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 2267316d257..e1765e39f7a 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -49,14 +49,15 @@
#include "ED_node.h"
#include "ED_render.h"
#include "ED_screen.h"
-#include "WM_api.h"
-#include "WM_types.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "RNA_access.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
#include "node_intern.h" /* own include */
@@ -381,12 +382,14 @@ static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
}
-static void node_area_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn)
+static void node_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *scene,
+ WorkSpace *workspace)
{
/* note, ED_area_tag_refresh will re-execute compositor */
SpaceNode *snode = sa->spacedata.first;
+ ViewRender *view_render = BKE_viewrender_get(scene, workspace);
/* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */
- short shader_type = BKE_scene_use_new_shading_nodes(sc->scene) ? snode->shaderfrom : SNODE_SHADER_OBJECT;
+ short shader_type = BKE_viewrender_use_new_shading_nodes(view_render) ? snode->shaderfrom : SNODE_SHADER_OBJECT;
/* preview renders */
switch (wmn->category) {
@@ -643,6 +646,14 @@ static void node_main_region_init(wmWindowManager *wm, ARegion *ar)
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+ /* manipulators stay in the background for now - quick patchjob to make sure nodes themselves work */
+ if (ar->manipulator_map == NULL) {
+ ar->manipulator_map = WM_manipulatormap_new_from_type(
+ &(const struct wmManipulatorMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW});
+ }
+
+ WM_manipulatormap_add_handlers(ar, ar->manipulator_map);
+
/* own keymaps */
keymap = WM_keymap_find(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
@@ -737,18 +748,32 @@ static void node_header_region_draw(const bContext *C, ARegion *ar)
}
/* used for header + main region */
-static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void node_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
+ wmManipulatorMap *mmap = ar->manipulator_map;
+
/* context changes */
switch (wmn->category) {
case NC_SPACE:
- if (wmn->data == ND_SPACE_NODE)
- ED_region_tag_redraw(ar);
+ switch (wmn->data) {
+ case ND_SPACE_NODE:
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_SPACE_NODE_VIEW:
+ WM_manipulatormap_tag_refresh(mmap);
+ break;
+ }
break;
case NC_SCREEN:
+ if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) {
+ WM_manipulatormap_tag_refresh(mmap);
+ }
switch (wmn->data) {
case ND_SCREENCAST:
case ND_ANIMPLAY:
+ case ND_LAYER:
ED_region_tag_redraw(ar);
break;
}
@@ -758,10 +783,20 @@ static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegi
ED_region_tag_redraw(ar);
break;
case NC_SCENE:
+ ED_region_tag_redraw(ar);
+ if (wmn->data == ND_RENDER_RESULT) {
+ WM_manipulatormap_tag_refresh(mmap);
+ }
+ break;
+ case NC_NODE:
+ ED_region_tag_redraw(ar);
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
+ WM_manipulatormap_tag_refresh(mmap);
+ }
+ break;
case NC_MATERIAL:
case NC_TEXTURE:
case NC_WORLD:
- case NC_NODE:
case NC_LINESTYLE:
ED_region_tag_redraw(ar);
break;
@@ -826,6 +861,17 @@ static int node_context(const bContext *C, const char *member, bContextDataResul
return 0;
}
+static void node_widgets(void)
+{
+ /* create the widgetmap for the area here */
+ wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(
+ &(const struct wmManipulatorMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW});
+ WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_transform);
+ WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_crop);
+ WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_sun_beams);
+ WM_manipulatorgrouptype_append_and_link(mmap_type, NODE_WGT_backdrop_corner_pin);
+}
+
static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
{
SpaceNode *snode = (SpaceNode *)slink;
@@ -916,6 +962,7 @@ void ED_spacetype_node(void)
st->refresh = node_area_refresh;
st->context = node_context;
st->dropboxes = node_dropboxes;
+ st->manipulators = node_widgets;
st->id_remap = node_id_remap;
/* regions: main window */
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index 289d6e715e1..96d27c6fd89 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../imbuf
../../gpu
../../makesdna
@@ -37,12 +38,14 @@ set(INC_SYS
)
set(SRC
+ outliner_collections.c
outliner_draw.c
outliner_edit.c
outliner_ops.c
outliner_select.c
outliner_tools.c
outliner_tree.c
+ outliner_utils.c
space_outliner.c
outliner_intern.h
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
new file mode 100644
index 00000000000..d5c833a7b5f
--- /dev/null
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -0,0 +1,572 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation, Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_outliner/outliner_collections.c
+ * \ingroup spoutliner
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+
+#include "BKE_context.h"
+#include "BKE_collection.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+#include "DNA_group_types.h"
+
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "UI_resources.h"
+
+#include "outliner_intern.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+
+static LayerCollection *outliner_collection_active(bContext *C)
+{
+ TODO_LAYER_OPERATORS;
+ /* consider that we may have overrides or objects active
+ * leading to no active collections */
+ return CTX_data_layer_collection(C);
+}
+
+SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te)
+{
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (tselem->type == TSE_SCENE_COLLECTION) {
+ return te->directdata;
+ }
+ else if (tselem->type == TSE_LAYER_COLLECTION) {
+ LayerCollection *lc = te->directdata;
+ return lc->scene_collection;
+ }
+
+ return NULL;
+}
+
+#if 0
+static CollectionOverride *outliner_override_active(bContext *UNUSED(C))
+{
+ TODO_LAYER_OPERATORS;
+ TODO_LAYER_OVERRIDE;
+ return NULL;
+}
+#endif
+
+/* -------------------------------------------------------------------- */
+/* collection manager operators */
+
+/**
+ * Recursively get the collection for a given index
+ */
+static SceneCollection *scene_collection_from_index(ListBase *lb, const int number, int *i)
+{
+ for (SceneCollection *sc = lb->first; sc; sc = sc->next) {
+ if (*i == number) {
+ return sc;
+ }
+
+ (*i)++;
+
+ SceneCollection *sc_nested = scene_collection_from_index(&sc->scene_collections, number, i);
+ if (sc_nested) {
+ return sc_nested;
+ }
+ }
+ return NULL;
+}
+
+static int collection_link_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SceneCollection *sc_master = BKE_collection_master(&scene->id);
+ SceneCollection *sc;
+
+ int scene_collection_index = RNA_enum_get(op->ptr, "scene_collection");
+ if (scene_collection_index == 0) {
+ sc = sc_master;
+ }
+ else {
+ int index = 1;
+ sc = scene_collection_from_index(&sc_master->scene_collections, scene_collection_index, &index);
+ BLI_assert(sc);
+ }
+
+ BKE_collection_link(view_layer, sc);
+
+ DEG_relations_tag_update(CTX_data_main(C));
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
+}
+
+static int collection_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneCollection *master_collection = BKE_collection_master(&scene->id);
+ if (master_collection->scene_collections.first == NULL) {
+ RNA_enum_set(op->ptr, "scene_collection", 0);
+ return collection_link_exec(C, op);
+ }
+ else {
+ return WM_enum_search_invoke(C, op, event);
+ }
+}
+
+static void collection_scene_collection_itemf_recursive(
+ EnumPropertyItem *tmp, EnumPropertyItem **item, int *totitem, int *value, SceneCollection *sc)
+{
+ tmp->value = *value;
+ tmp->icon = ICON_COLLAPSEMENU;
+ tmp->identifier = sc->name;
+ tmp->name = sc->name;
+ RNA_enum_item_add(item, totitem, tmp);
+
+ (*value)++;
+
+ for (SceneCollection *ncs = sc->scene_collections.first; ncs; ncs = ncs->next) {
+ collection_scene_collection_itemf_recursive(tmp, item, totitem, value, ncs);
+ }
+}
+
+static const EnumPropertyItem *collection_scene_collection_itemf(
+ bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem *item = NULL;
+ int value = 0, totitem = 0;
+
+ Scene *scene = CTX_data_scene(C);
+ SceneCollection *sc = BKE_collection_master(&scene->id);
+
+ collection_scene_collection_itemf_recursive(&tmp, &item, &totitem, &value, sc);
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+void OUTLINER_OT_collection_link(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Add Collection";
+ ot->idname = "OUTLINER_OT_collection_link";
+ ot->description = "Link a new collection to the active layer";
+
+ /* api callbacks */
+ ot->exec = collection_link_exec;
+ ot->invoke = collection_link_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_enum(ot->srna, "scene_collection", DummyRNA_NULL_items, 0, "Scene Collection", "");
+ RNA_def_enum_funcs(prop, collection_scene_collection_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
+}
+
+/**
+ * Returns true if selected element is a collection directly
+ * linked to the active ViewLayer (not a nested collection)
+ */
+static int collection_unlink_poll(bContext *C)
+{
+ LayerCollection *lc = outliner_collection_active(C);
+
+ if (lc == NULL) {
+ return 0;
+ }
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ return BLI_findindex(&view_layer->layer_collections, lc) != -1 ? 1 : 0;
+}
+
+static int collection_unlink_exec(bContext *C, wmOperator *op)
+{
+ LayerCollection *lc = outliner_collection_active(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+
+ if (lc == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Active element is not a collection");
+ return OPERATOR_CANCELLED;
+ }
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_collection_unlink(view_layer, lc);
+
+ if (soops) {
+ outliner_cleanup_tree(soops);
+ }
+
+ DEG_relations_tag_update(CTX_data_main(C));
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&CTX_data_scene(C)->id, 0);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_unlink(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Collection";
+ ot->idname = "OUTLINER_OT_collection_unlink";
+ ot->description = "Unlink collection from the active layer";
+
+ /* api callbacks */
+ ot->exec = collection_unlink_exec;
+ ot->poll = collection_unlink_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/**********************************************************************************/
+/* Add new collection. */
+
+static int collection_new_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SceneCollection *scene_collection = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL);
+ BKE_collection_link(view_layer, scene_collection);
+
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Collection";
+ ot->idname = "OUTLINER_OT_collection_new";
+ ot->description = "Add a new collection to the scene";
+
+ /* api callbacks */
+ ot->exec = collection_new_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/**********************************************************************************/
+
+/**
+ * Returns true is selected element is a collection
+ */
+static int collection_override_new_poll(bContext *(C))
+{
+#ifdef TODO_LAYER_OVERRIDE
+ /* disable for now, since it's not implemented */
+ (void) C;
+ return 0;
+#else
+ return outliner_collection_active(C) ? 1 : 0;
+#endif
+}
+
+static int collection_override_new_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
+{
+ TODO_LAYER_OPERATORS;
+ TODO_LAYER_OVERRIDE;
+ BKE_report(op->reports, RPT_ERROR, "OUTLINER_OT_collections_override_new not implemented yet");
+ return OPERATOR_CANCELLED;
+}
+
+/* in the middle of renames remove s */
+void OUTLINER_OT_collection_override_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Override";
+ ot->idname = "OUTLINER_OT_collection_override_new";
+ ot->description = "Add a new override to the active collection";
+
+ /* api callbacks */
+ ot->invoke = collection_override_new_invoke;
+ ot->poll = collection_override_new_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+struct CollectionDeleteData {
+ Scene *scene;
+ SpaceOops *soops;
+ GSet *collections_to_delete;
+};
+
+static TreeTraversalAction collection_find_data_to_delete(TreeElement *te, void *customdata)
+{
+ struct CollectionDeleteData *data = customdata;
+ SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
+
+ if (!scene_collection) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
+
+ if (scene_collection == BKE_collection_master(&data->scene->id)) {
+ /* skip - showing warning/error message might be missleading
+ * when deleting multiple collections, so just do nothing */
+ }
+ else {
+ BLI_gset_add(data->collections_to_delete, scene_collection);
+ }
+
+ return TRAVERSE_CONTINUE;
+}
+
+static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionDeleteData data = {.scene = scene, .soops = soops};
+
+ data.collections_to_delete = BLI_gset_ptr_new(__func__);
+
+ TODO_LAYER_OVERRIDE; /* handle overrides */
+
+ /* We first walk over and find the SceneCollections we actually want to delete (ignoring duplicates). */
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_delete, &data);
+
+ /* Effectively delete the collections. */
+ GSetIterator collections_to_delete_iter;
+ GSET_ITER(collections_to_delete_iter, data.collections_to_delete) {
+
+ SceneCollection *sc = BLI_gsetIterator_getKey(&collections_to_delete_iter);
+ BKE_collection_remove(&data.scene->id, sc);
+ }
+
+ BLI_gset_free(data.collections_to_delete, NULL);
+
+ DEG_relations_tag_update(CTX_data_main(C));
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collections_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete";
+ ot->idname = "OUTLINER_OT_collections_delete";
+ ot->description = "Delete selected overrides or collections";
+
+ /* api callbacks */
+ ot->exec = collection_delete_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int collection_select_exec(bContext *C, wmOperator *op)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const int collection_index = RNA_int_get(op->ptr, "collection_index");
+ view_layer->active_collection = collection_index;
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select";
+ ot->idname = "OUTLINER_OT_collection_select";
+ ot->description = "Change active collection or override";
+
+ /* api callbacks */
+ ot->exec = collection_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);
+}
+
+#define ACTION_DISABLE 0
+#define ACTION_ENABLE 1
+#define ACTION_TOGGLE 2
+
+static int collection_toggle_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ int action = RNA_enum_get(op->ptr, "action");
+ LayerCollection *layer_collection = CTX_data_layer_collection(C);
+
+ if (layer_collection->flag & COLLECTION_DISABLED) {
+ if (ELEM(action, ACTION_TOGGLE, ACTION_ENABLE)) {
+ BKE_collection_enable(view_layer, layer_collection);
+ }
+ else { /* ACTION_DISABLE */
+ BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already disabled",
+ layer_collection->scene_collection->name);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ if (ELEM(action, ACTION_TOGGLE, ACTION_DISABLE)) {
+ BKE_collection_disable(view_layer, layer_collection);
+ }
+ else { /* ACTION_ENABLE */
+ BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already enabled",
+ layer_collection->scene_collection->name);
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_toggle(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ static EnumPropertyItem actions_items[] = {
+ {ACTION_DISABLE, "DISABLE", 0, "Disable", "Disable selected markers"},
+ {ACTION_ENABLE, "ENABLE", 0, "Enable", "Enable selected markers"},
+ {ACTION_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Toggle Collection";
+ ot->idname = "OUTLINER_OT_collection_toggle";
+ ot->description = "Deselect collection objects";
+
+ /* api callbacks */
+ ot->exec = collection_toggle_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna, "collection_index", -1, -1, INT_MAX, "Collection Index", "Index of collection to toggle", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_enum(ot->srna, "action", actions_items, ACTION_TOGGLE, "Action", "Selection action to execute");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+#undef ACTION_TOGGLE
+#undef ACTION_ENABLE
+#undef ACTION_DISABLE
+
+/* -------------------------------------------------------------------- */
+
+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;
+}
+
+void OUTLINER_OT_collection_objects_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_add";
+ ot->description = "Add selected objects to collection";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_objects_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Object";
+ ot->idname = "OUTLINER_OT_collection_objects_remove";
+ ot->description = "Remove objects from collection";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_select";
+ ot->description = "Select collection objects";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Deselect Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_deselect";
+ ot->description = "Deselect collection objects";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index d8d6b09ac6b..670fc4e6627 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -48,9 +48,9 @@
#include "BKE_context.h"
#include "BKE_deform.h"
-#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"
@@ -58,6 +58,9 @@
#include "BKE_scene.h"
#include "BKE_object.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_armature.h"
#include "ED_keyframing.h"
#include "ED_object.h"
@@ -66,8 +69,7 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "GPU_immediate.h"
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -172,116 +174,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);
@@ -291,7 +183,7 @@ static void restrictbutton_modifier_cb(bContext *C, void *UNUSED(poin), void *po
{
Object *ob = (Object *)poin2;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
}
@@ -355,96 +247,50 @@ 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 enablebutton_collection_flag_cb(bContext *C, void *poin, void *poin2)
{
- GroupObject *gob;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ID *id = poin;
+ LayerCollection *layer_collection = poin2;
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(id, layer_collection);
+
+ /* TODO: This breaks when you see the collections of a group. (dfelinto) */
+ if (view_layer == NULL) {
+ WM_reportf(RPT_INFO, "Enable/disable of group collections disabled for now");
+ return;
+ }
-#ifdef USE_GROUP_SELECT
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if ((gob->ob->restrictflag & flag) == 0)
- return 0;
+ /* We need to toggle the flag since this is called after the flag is already set. */
+ layer_collection->flag ^= COLLECTION_DISABLED;
+
+ if (layer_collection->flag & COLLECTION_DISABLED) {
+ BKE_collection_enable(view_layer, layer_collection);
+ }
+ else {
+ BKE_collection_disable(view_layer, layer_collection);
}
- 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
+ DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+ 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_flag_cb(bContext *C, void *poin, void *UNUSED(poin2))
{
- Scene *scene = (Scene *)poin;
- GroupObject *gob;
- Group *gr = (Group *)poin2;
-
- if (group_restrict_flag(gr, flag)) {
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if (ID_IS_LINKED(gob->ob))
- continue;
-
- 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);
- }
- }
- else {
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if (ID_IS_LINKED(gob->ob))
- continue;
+ ID *id = (ID *)poin;
- /* not in editmode */
- if (scene->obedit != gob->ob) {
- gob->ob->restrictflag |= flag;
+ /* hide and deselect bases that are directly influenced by this LayerCollection */
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(id, 0);
- 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);
- }
- }
- }
- }
+ if (GS(id->name) == ID_SCE) {
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, id);
}
-}
-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))
@@ -466,6 +312,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
BLI_mempool *ts = soops->treestore;
TreeStoreElem *tselem = tsep;
@@ -527,7 +374,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(view_layer));
}
break;
}
@@ -539,8 +386,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, view_layer, soops, te, OL_SETSEL_NORMAL, true);
+ ob = OBACT(view_layer);
/* restore bone name */
BLI_strncpy(newname, bone->name, sizeof(bone->name));
@@ -556,8 +403,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, view_layer, soops, te, OL_SETSEL_NORMAL, true);
+ ob = OBACT(view_layer);
BLI_assert(ob->type == OB_ARMATURE);
@@ -591,6 +438,13 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
}
case TSE_R_LAYER:
break;
+ case TSE_SCENE_COLLECTION:
+ case TSE_LAYER_COLLECTION:
+ {
+ SceneCollection *sc = outliner_scene_collection_from_tree_element(te);
+ BKE_collection_rename(scene, sc, te->name);
+ break;
+ }
}
}
tselem->flag &= ~TSE_TEXTBUT;
@@ -603,8 +457,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
TreeElement *te;
TreeStoreElem *tselem;
Object *ob = NULL;
- Group *gr = NULL;
+#if 0
PropertyRNA *object_prop_hide, *object_prop_hide_select, *object_prop_hide_render;
/* get RNA properties (once) */
@@ -612,81 +466,17 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
object_prop_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select");
object_prop_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render");
BLI_assert(object_prop_hide && object_prop_hide_select && object_prop_hide_render);
+#endif
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(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,
+ bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, VIEW_LAYER_RENDER, 0, ICON_CHECKBOX_HLT - 1,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
UI_UNIT_Y, te->directdata, 0, 0, 0, 0, TIP_("Render this RenderLayer"));
UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
@@ -805,6 +595,39 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
UI_block_emboss_set(block, UI_EMBOSS);
}
+ else if (tselem->type == TSE_LAYER_COLLECTION) {
+ LayerCollection *collection = te->directdata;
+
+ const bool is_enabled = (collection->flag & COLLECTION_DISABLED) == 0;
+
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ bt = uiDefIconButBitS(block, UI_BTYPE_BUT_TOGGLE, COLLECTION_DISABLED, 0,
+ is_enabled ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_ENABLEX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
+ TIP_("Enable/Disable collection from depsgraph"));
+ UI_but_func_set(bt, enablebutton_collection_flag_cb, tselem->id, collection);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ 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_flag_cb, tselem->id, collection);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ if (collection->scene_collection->type == COLLECTION_TYPE_NONE) {
+ 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_flag_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);
@@ -878,18 +701,23 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex)
float miny = v2d->cur.ymin;
if (miny < v2d->tot.ymin) miny = v2d->tot.ymin;
- UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
+ glLineWidth(1.0f);
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
+
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, sizex, v2d->cur.ymax);
+ immVertex2f(pos, sizex, miny);
- /* draw column separator lines */
- fdrawline((float)sizex,
- v2d->cur.ymax,
- (float)sizex,
- miny);
+ immVertex2f(pos, sizex + OL_RNA_COL_SIZEX, v2d->cur.ymax);
+ immVertex2f(pos, sizex + OL_RNA_COL_SIZEX, miny);
- fdrawline((float)sizex + OL_RNA_COL_SIZEX,
- v2d->cur.ymax,
- (float)sizex + OL_RNA_COL_SIZEX,
- miny);
+ immEnd();
+
+ immUnbindProgram();
}
static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb)
@@ -987,7 +815,7 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
/* restrict column clip... it has been coded by simply overdrawing, doesnt work for buttons */
if (arg->x >= arg->xmax) {
glEnable(GL_BLEND);
- UI_icon_draw_aspect(arg->x, arg->y, icon, 1.0f / UI_DPI_FAC, arg->alpha);
+ UI_icon_draw_alpha(arg->x, arg->y, icon, arg->alpha);
glDisable(GL_BLEND);
}
else {
@@ -1047,7 +875,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
arg.xb = x; /* for ui buttons */
arg.yb = y;
arg.alpha = alpha;
-
+
/* placement of icons, copied from interface_widgets.c */
aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
x += 2.0f * aspect;
@@ -1055,184 +883,253 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
arg.x = x;
arg.y = y;
+#define ICON_DRAW(_icon) UI_icon_draw_alpha(x, y, _icon, alpha)
+
if (tselem->type) {
switch (tselem->type) {
case TSE_ANIM_DATA:
- UI_icon_draw(x, y, ICON_ANIM_DATA); break; // xxx
+ ICON_DRAW(ICON_ANIM_DATA); /* XXX */
+ break;
case TSE_NLA:
- UI_icon_draw(x, y, ICON_NLA); break;
+ ICON_DRAW(ICON_NLA);
+ break;
case TSE_NLA_TRACK:
- UI_icon_draw(x, y, ICON_NLA); break; // XXX
+ ICON_DRAW(ICON_NLA); /* XXX */
+ break;
case TSE_NLA_ACTION:
- UI_icon_draw(x, y, ICON_ACTION); break;
+ ICON_DRAW(ICON_ACTION);
+ break;
case TSE_DRIVER_BASE:
- UI_icon_draw(x, y, ICON_DRIVER); break;
+ ICON_DRAW(ICON_DRIVER);
+ break;
case TSE_DEFGROUP_BASE:
- UI_icon_draw(x, y, ICON_GROUP_VERTEX); break;
+ ICON_DRAW(ICON_GROUP_VERTEX);
+ break;
case TSE_BONE:
case TSE_EBONE:
- UI_icon_draw(x, y, ICON_BONE_DATA); break;
+ ICON_DRAW(ICON_BONE_DATA);
+ break;
case TSE_CONSTRAINT_BASE:
- UI_icon_draw(x, y, ICON_CONSTRAINT); break;
+ ICON_DRAW(ICON_CONSTRAINT);
+ break;
case TSE_MODIFIER_BASE:
- UI_icon_draw(x, y, ICON_MODIFIER); break;
+ ICON_DRAW(ICON_MODIFIER);
+ break;
case TSE_LINKED_OB:
- UI_icon_draw(x, y, ICON_OBJECT_DATA); break;
+ ICON_DRAW(ICON_OBJECT_DATA);
+ break;
case TSE_LINKED_PSYS:
- UI_icon_draw(x, y, ICON_PARTICLES); break;
+ ICON_DRAW(ICON_PARTICLES);
+ break;
case TSE_MODIFIER:
{
Object *ob = (Object *)tselem->id;
ModifierData *md = BLI_findlink(&ob->modifiers, tselem->nr);
switch ((ModifierType)md->type) {
- case eModifierType_Subsurf:
- UI_icon_draw(x, y, ICON_MOD_SUBSURF); break;
- case eModifierType_Armature:
- UI_icon_draw(x, y, ICON_MOD_ARMATURE); break;
- case eModifierType_Lattice:
- UI_icon_draw(x, y, ICON_MOD_LATTICE); break;
- case eModifierType_Curve:
- UI_icon_draw(x, y, ICON_MOD_CURVE); break;
- case eModifierType_Build:
- UI_icon_draw(x, y, ICON_MOD_BUILD); break;
- case eModifierType_Mirror:
- UI_icon_draw(x, y, ICON_MOD_MIRROR); break;
- case eModifierType_Decimate:
- UI_icon_draw(x, y, ICON_MOD_DECIM); break;
- case eModifierType_Wave:
- UI_icon_draw(x, y, ICON_MOD_WAVE); break;
- case eModifierType_Hook:
- UI_icon_draw(x, y, ICON_HOOK); break;
- case eModifierType_Softbody:
- UI_icon_draw(x, y, ICON_MOD_SOFT); break;
- case eModifierType_Boolean:
- UI_icon_draw(x, y, ICON_MOD_BOOLEAN); break;
- case eModifierType_ParticleSystem:
- UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
+ case eModifierType_Subsurf:
+ ICON_DRAW(ICON_MOD_SUBSURF);
+ break;
+ case eModifierType_Armature:
+ ICON_DRAW(ICON_MOD_ARMATURE);
+ break;
+ case eModifierType_Lattice:
+ ICON_DRAW(ICON_MOD_LATTICE);
+ break;
+ case eModifierType_Curve:
+ ICON_DRAW(ICON_MOD_CURVE);
+ break;
+ case eModifierType_Build:
+ ICON_DRAW(ICON_MOD_BUILD);
+ break;
+ case eModifierType_Mirror:
+ ICON_DRAW(ICON_MOD_MIRROR);
+ break;
+ case eModifierType_Decimate:
+ ICON_DRAW(ICON_MOD_DECIM);
+ break;
+ case eModifierType_Wave:
+ ICON_DRAW(ICON_MOD_WAVE);
+ break;
+ case eModifierType_Hook:
+ ICON_DRAW(ICON_HOOK);
+ break;
+ case eModifierType_Softbody:
+ ICON_DRAW(ICON_MOD_SOFT);
+ break;
+ case eModifierType_Boolean:
+ ICON_DRAW(ICON_MOD_BOOLEAN);
+ break;
+ case eModifierType_ParticleSystem:
+ ICON_DRAW(ICON_MOD_PARTICLES);
+ break;
case eModifierType_ParticleInstance:
- UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
+ ICON_DRAW(ICON_MOD_PARTICLES);
+ break;
case eModifierType_EdgeSplit:
- UI_icon_draw(x, y, ICON_MOD_EDGESPLIT); break;
+ ICON_DRAW(ICON_MOD_EDGESPLIT);
+ break;
case eModifierType_Array:
- UI_icon_draw(x, y, ICON_MOD_ARRAY); break;
+ ICON_DRAW(ICON_MOD_ARRAY);
+ break;
case eModifierType_UVProject:
case eModifierType_UVWarp: /* TODO, get own icon */
- UI_icon_draw(x, y, ICON_MOD_UVPROJECT); break;
+ ICON_DRAW(ICON_MOD_UVPROJECT);
+ break;
case eModifierType_Displace:
- UI_icon_draw(x, y, ICON_MOD_DISPLACE); break;
+ ICON_DRAW(ICON_MOD_DISPLACE);
+ break;
case eModifierType_Shrinkwrap:
- UI_icon_draw(x, y, ICON_MOD_SHRINKWRAP); break;
+ ICON_DRAW(ICON_MOD_SHRINKWRAP);
+ break;
case eModifierType_Cast:
- UI_icon_draw(x, y, ICON_MOD_CAST); break;
+ ICON_DRAW(ICON_MOD_CAST);
+ break;
case eModifierType_MeshDeform:
case eModifierType_SurfaceDeform:
- UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break;
+ ICON_DRAW(ICON_MOD_MESHDEFORM);
+ break;
case eModifierType_Bevel:
- UI_icon_draw(x, y, ICON_MOD_BEVEL); break;
+ ICON_DRAW(ICON_MOD_BEVEL);
+ break;
case eModifierType_Smooth:
case eModifierType_LaplacianSmooth:
case eModifierType_CorrectiveSmooth:
- UI_icon_draw(x, y, ICON_MOD_SMOOTH); break;
+ ICON_DRAW(ICON_MOD_SMOOTH);
+ break;
case eModifierType_SimpleDeform:
- UI_icon_draw(x, y, ICON_MOD_SIMPLEDEFORM); break;
+ ICON_DRAW(ICON_MOD_SIMPLEDEFORM);
+ break;
case eModifierType_Mask:
- UI_icon_draw(x, y, ICON_MOD_MASK); break;
+ ICON_DRAW(ICON_MOD_MASK);
+ break;
case eModifierType_Cloth:
- UI_icon_draw(x, y, ICON_MOD_CLOTH); break;
+ ICON_DRAW(ICON_MOD_CLOTH);
+ break;
case eModifierType_Explode:
- UI_icon_draw(x, y, ICON_MOD_EXPLODE); break;
+ ICON_DRAW(ICON_MOD_EXPLODE);
+ break;
case eModifierType_Collision:
case eModifierType_Surface:
- UI_icon_draw(x, y, ICON_MOD_PHYSICS); break;
+ ICON_DRAW(ICON_MOD_PHYSICS);
+ break;
case eModifierType_Fluidsim:
- UI_icon_draw(x, y, ICON_MOD_FLUIDSIM); break;
+ ICON_DRAW(ICON_MOD_FLUIDSIM);
+ break;
case eModifierType_Multires:
- UI_icon_draw(x, y, ICON_MOD_MULTIRES); break;
+ ICON_DRAW(ICON_MOD_MULTIRES);
+ break;
case eModifierType_Smoke:
- UI_icon_draw(x, y, ICON_MOD_SMOKE); break;
+ ICON_DRAW(ICON_MOD_SMOKE);
+ break;
case eModifierType_Solidify:
- UI_icon_draw(x, y, ICON_MOD_SOLIDIFY); break;
+ ICON_DRAW(ICON_MOD_SOLIDIFY);
+ break;
case eModifierType_Screw:
- UI_icon_draw(x, y, ICON_MOD_SCREW); break;
+ ICON_DRAW(ICON_MOD_SCREW);
+ break;
case eModifierType_Remesh:
- UI_icon_draw(x, y, ICON_MOD_REMESH); break;
+ ICON_DRAW(ICON_MOD_REMESH);
+ break;
case eModifierType_WeightVGEdit:
case eModifierType_WeightVGMix:
case eModifierType_WeightVGProximity:
- UI_icon_draw(x, y, ICON_MOD_VERTEX_WEIGHT); break;
+ ICON_DRAW(ICON_MOD_VERTEX_WEIGHT);
+ break;
case eModifierType_DynamicPaint:
- UI_icon_draw(x, y, ICON_MOD_DYNAMICPAINT); break;
+ ICON_DRAW(ICON_MOD_DYNAMICPAINT);
+ break;
case eModifierType_Ocean:
- UI_icon_draw(x, y, ICON_MOD_OCEAN); break;
+ ICON_DRAW(ICON_MOD_OCEAN);
+ break;
case eModifierType_Warp:
- UI_icon_draw(x, y, ICON_MOD_WARP); break;
+ ICON_DRAW(ICON_MOD_WARP);
+ break;
case eModifierType_Skin:
- UI_icon_draw(x, y, ICON_MOD_SKIN); break;
+ ICON_DRAW(ICON_MOD_SKIN);
+ break;
case eModifierType_Triangulate:
- UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break;
+ ICON_DRAW(ICON_MOD_TRIANGULATE);
+ break;
case eModifierType_MeshCache:
- UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
+ ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
+ break;
case eModifierType_MeshSequenceCache:
- UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
+ ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
+ break;
case eModifierType_Wireframe:
- UI_icon_draw(x, y, ICON_MOD_WIREFRAME); break;
+ ICON_DRAW(ICON_MOD_WIREFRAME);
+ break;
case eModifierType_LaplacianDeform:
- UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
+ ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
+ break;
case eModifierType_DataTransfer:
- UI_icon_draw(x, y, ICON_MOD_DATA_TRANSFER); break;
+ ICON_DRAW(ICON_MOD_DATA_TRANSFER);
+ break;
case eModifierType_NormalEdit:
- UI_icon_draw(x, y, ICON_MOD_NORMALEDIT); break;
+ ICON_DRAW(ICON_MOD_NORMALEDIT);
+ break;
/* Default */
case eModifierType_None:
case eModifierType_ShapeKey:
case NUM_MODIFIER_TYPES:
- UI_icon_draw(x, y, ICON_DOT); break;
+ ICON_DRAW(ICON_DOT);
+ break;
}
break;
}
case TSE_POSE_BASE:
- UI_icon_draw(x, y, ICON_ARMATURE_DATA); break;
+ ICON_DRAW(ICON_ARMATURE_DATA);
+ break;
case TSE_POSE_CHANNEL:
- UI_icon_draw(x, y, ICON_BONE_DATA); break;
+ ICON_DRAW(ICON_BONE_DATA);
+ break;
case TSE_PROXY:
- UI_icon_draw(x, y, ICON_GHOST); break;
+ ICON_DRAW(ICON_GHOST);
+ break;
case TSE_R_LAYER_BASE:
- UI_icon_draw(x, y, ICON_RENDERLAYERS); break;
+ ICON_DRAW(ICON_RENDERLAYERS);
+ break;
case TSE_R_LAYER:
- UI_icon_draw(x, y, ICON_RENDERLAYERS); break;
+ ICON_DRAW(ICON_RENDERLAYERS);
+ break;
case TSE_LINKED_LAMP:
- UI_icon_draw(x, y, ICON_LAMP_DATA); break;
+ ICON_DRAW(ICON_LAMP_DATA);
+ break;
case TSE_LINKED_MAT:
- UI_icon_draw(x, y, ICON_MATERIAL_DATA); break;
+ ICON_DRAW(ICON_MATERIAL_DATA);
+ break;
case TSE_POSEGRP_BASE:
- UI_icon_draw(x, y, ICON_GROUP_BONE); break;
+ ICON_DRAW(ICON_GROUP_BONE);
+ break;
case TSE_SEQUENCE:
if (te->idcode == SEQ_TYPE_MOVIE)
- UI_icon_draw(x, y, ICON_SEQUENCE);
+ ICON_DRAW(ICON_SEQUENCE);
else if (te->idcode == SEQ_TYPE_META)
- UI_icon_draw(x, y, ICON_DOT);
+ ICON_DRAW(ICON_DOT);
else if (te->idcode == SEQ_TYPE_SCENE)
- UI_icon_draw(x, y, ICON_SCENE);
+ ICON_DRAW(ICON_SCENE);
else if (te->idcode == SEQ_TYPE_SOUND_RAM)
- UI_icon_draw(x, y, ICON_SOUND);
+ ICON_DRAW(ICON_SOUND);
else if (te->idcode == SEQ_TYPE_IMAGE)
- UI_icon_draw(x, y, ICON_IMAGE_COL);
+ ICON_DRAW(ICON_IMAGE_COL);
else
- UI_icon_draw(x, y, ICON_PARTICLES);
+ ICON_DRAW(ICON_PARTICLES);
break;
case TSE_SEQ_STRIP:
- UI_icon_draw(x, y, ICON_LIBRARY_DATA_DIRECT);
+ ICON_DRAW(ICON_LIBRARY_DATA_DIRECT);
break;
case TSE_SEQUENCE_DUP:
- UI_icon_draw(x, y, ICON_OBJECT_DATA);
+ ICON_DRAW(ICON_OBJECT_DATA);
break;
case TSE_RNA_STRUCT:
if (RNA_struct_is_ID(te->rnaptr.type)) {
arg.id = (ID *)te->rnaptr.data;
tselem_draw_icon_uibut(&arg, RNA_struct_ui_icon(te->rnaptr.type));
}
- else
- UI_icon_draw(x, y, RNA_struct_ui_icon(te->rnaptr.type));
+ else {
+ int icon = RNA_struct_ui_icon(te->rnaptr.type);
+ ICON_DRAW(icon);
+ }
break;
/* Removed the icons from outliner. Need a better structure with Layers, Palettes and Colors */
#if 0
@@ -1241,7 +1138,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
break;
#endif
default:
- UI_icon_draw(x, y, ICON_DOT); break;
+ ICON_DRAW(ICON_DOT);
+ break;
}
}
else if (tselem->id) {
@@ -1351,17 +1249,18 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
}
}
}
+
+#undef ICON_DRAW
}
-static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level,
- int xmax, int *offsx, int ys)
+static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
+ ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac)
{
TreeElement *te;
TreeStoreElem *tselem;
eOLDrawState active;
for (te = lb->first; te; te = te->next) {
-
/* exit drawing early */
if ((*offsx) - UI_UNIT_X > xmax)
break;
@@ -1374,34 +1273,38 @@ 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(view_layer) == (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, view_layer, 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(C, scene, view_layer, soops, te, tselem, OL_SETSEL_NONE, false);
}
if (active != OL_DRAWSEL_NONE) {
float ufac = UI_UNIT_X / 20.0f;
+ float color[4] = {1.0f, 1.0f, 1.0f, 0.4f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- glColor4ub(255, 255, 255, 100);
- UI_draw_roundbox(
+ color[3] *= alpha_fac;
+
+ UI_draw_roundbox_aa(
+ true,
(float) *offsx + 1.0f * ufac,
(float)ys + 1.0f * ufac,
(float)*offsx + UI_UNIT_X - 1.0f * ufac,
(float)ys + UI_UNIT_Y - ufac,
- (float)UI_UNIT_Y / 2.0f - ufac);
+ (float)UI_UNIT_Y / 2.0f - ufac,
+ color);
glEnable(GL_BLEND); /* roundbox disables */
}
- tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f);
+ tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac);
te->xs = *offsx;
te->ys = ys;
te->xend = (short)*offsx + UI_UNIT_X;
@@ -1412,7 +1315,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, view_layer, soops, &te->subtree, level + 1, xmax, offsx, ys, alpha_fac);
}
}
@@ -1421,11 +1324,14 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa
static void outliner_set_coord_tree_element(TreeElement *te, int startx, int starty)
{
TreeElement *ten;
-
- /* store coord and continue, we need coordinates for elements outside view too */
- te->xs = startx;
- te->ys = starty;
-
+
+ /* closed items may be displayed in row of parent, don't change their coordinate! */
+ if ((te->flag & TE_ICONROW) == 0) {
+ /* store coord and continue, we need coordinates for elements outside view too */
+ te->xs = startx;
+ te->ys = starty;
+ }
+
for (ten = te->subtree.first; ten; ten = ten->next) {
outliner_set_coord_tree_element(ten, startx + UI_UNIT_X, starty);
}
@@ -1433,24 +1339,28 @@ 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,
- TreeElement *te, int startx, int *starty, TreeElement **te_edit)
+ bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, ViewLayer *view_layer,
+ ARegion *ar, SpaceOops *soops, TreeElement *te, bool draw_grayed_out,
+ int startx, int *starty, TreeElement **te_edit, TreeElement **te_floating)
{
- TreeElement *ten;
TreeStoreElem *tselem;
float ufac = UI_UNIT_X / 20.0f;
int offsx = 0;
eOLDrawState active = OL_DRAWSEL_NONE;
-
+ float color[4];
tselem = TREESTORE(te);
if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
+ const float alpha_fac = draw_grayed_out ? 0.5f : 1.0f;
+ const float alpha = 0.5f * alpha_fac;
int xmax = ar->v2d.cur.xmax;
- unsigned char alpha = 128;
-
+
if ((tselem->flag & TSE_TEXTBUT) && (*te_edit == NULL)) {
*te_edit = te;
}
+ if ((te->drag_data != NULL) && (*te_floating == NULL)) {
+ *te_floating = te;
+ }
/* icons can be ui buts, we don't want it to overlap with restrict */
if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0)
@@ -1458,50 +1368,24 @@ static void outliner_draw_tree_element(
glEnable(GL_BLEND);
- /* start by highlighting search matches
- * we don't expand items when searching in the datablocks but we
- * still want to highlight any filter matches.
- */
- if ((SEARCHING_OUTLINER(soops) || (soops->outlinevis == SO_DATABLOCKS && soops->search_string[0] != 0)) &&
- (tselem->flag & TSE_SEARCHMATCH))
- {
- char col[4];
- UI_GetThemeColorType4ubv(TH_MATCH, SPACE_OUTLINER, col);
- col[3] = alpha;
- glColor4ubv((GLubyte *)col);
- glRecti(startx, *starty + 1, ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
- }
-
/* colors for active/selected data */
if (tselem->type == 0) {
-
if (te->idcode == ID_SCE) {
if (tselem->id == (ID *)scene) {
- glColor4ub(255, 255, 255, alpha);
- 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);
- col[3] = alpha;
- glColor4ubv((GLubyte *)col);
-
+ rgba_float_args_set(color, 1.0f, 1.0f, 1.0f, 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(view_layer) || (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(view_layer)) {
if (ob->flag & SELECT) {
UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col);
col[3] = alpha;
@@ -1513,38 +1397,36 @@ static void outliner_draw_tree_element(
UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
col[3] = alpha;
}
-
- glColor4ubv((GLubyte *)col);
+ rgba_float_args_set(color, (float)col[0] / 255, (float)col[1] / 255, (float)col[2] / 255, alpha);
}
}
else if (scene->obedit && scene->obedit->data == tselem->id) {
- glColor4ub(255, 255, 255, alpha);
+ rgba_float_args_set(color, 1.0f, 1.0f, 1.0f, alpha);
active = OL_DRAWSEL_ACTIVE;
}
else {
- if (tree_element_active(C, scene, soops, te, OL_SETSEL_NONE, false)) {
- glColor4ub(220, 220, 255, alpha);
+ if (tree_element_active(C, scene, view_layer, 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) {
- active = OL_DRAWSEL_ACTIVE;
- }
- glColor4ub(220, 220, 255, alpha);
+ active = tree_element_type_active(C, scene, view_layer, soops, te, tselem, OL_SETSEL_NONE, false);
+ rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha);
}
/* active circle */
if (active != OL_DRAWSEL_NONE) {
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox(
+ UI_draw_roundbox_aa(
+ true,
(float)startx + UI_UNIT_X + 1.0f * ufac,
(float)*starty + 1.0f * ufac,
(float)startx + 2.0f * UI_UNIT_X - 1.0f * ufac,
(float)*starty + UI_UNIT_Y - 1.0f * ufac,
- UI_UNIT_Y / 2.0f - 1.0f * ufac);
+ UI_UNIT_Y / 2.0f - 1.0f * ufac, color);
glEnable(GL_BLEND); /* roundbox disables it */
te->flag |= TE_ACTIVE; // for lookup in display hierarchies
@@ -1553,56 +1435,64 @@ static void outliner_draw_tree_element(
/* open/close icon, only when sublevels, except for scene */
if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
int icon_x;
- icon_x = startx;
-
+ if (tselem->type == 0 && ELEM(te->idcode, ID_OB, ID_SCE))
+ icon_x = startx;
+ else
+ icon_x = startx + 5 * ufac;
+
// icons a bit higher
if (TSELEM_OPEN(tselem, soops))
- UI_icon_draw((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN);
+ UI_icon_draw_alpha((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN,
+ alpha_fac);
else
- UI_icon_draw((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT);
+ UI_icon_draw_alpha((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT,
+ alpha_fac);
}
offsx += UI_UNIT_X;
/* datatype icon */
if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) {
-
- tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, 1.0f);
-
+ tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac);
offsx += UI_UNIT_X + 2 * ufac;
}
else
offsx += 2 * ufac;
if (tselem->type == 0 && ID_IS_LINKED(tselem->id)) {
- glPixelTransferf(GL_ALPHA_SCALE, 0.5f);
if (tselem->id->tag & LIB_TAG_MISSING) {
- UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN);
+ UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN,
+ alpha_fac);
}
else if (tselem->id->tag & LIB_TAG_INDIRECT) {
- UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT);
+ UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT,
+ alpha_fac);
}
else {
- UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT);
+ UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT,
+ alpha_fac);
}
- glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
offsx += UI_UNIT_X + 2 * ufac;
}
glDisable(GL_BLEND);
/* 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);
}
+ text_col[3] *= alpha_fac;
- 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));
@@ -1613,24 +1503,33 @@ static void outliner_draw_tree_element(
if (tselem->type == 0 && te->idcode == ID_SCE) {
/* pass */
}
+ /* this tree element always has same amount of branches, so don't draw */
else if (tselem->type != TSE_R_LAYER) {
- /* this tree element always has same amount of branches, so don't draw */
-
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);
-
+
glEnable(GL_BLEND);
- glPixelTransferf(GL_ALPHA_SCALE, 0.5);
-
- outliner_draw_iconrow(C, block, scene, soops, &te->subtree, 0, xmax, &tempx, *starty);
-
- glPixelTransferf(GL_ALPHA_SCALE, 1.0);
+
+ /* divider */
+ {
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ unsigned char col[4];
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ UI_GetThemeColorShade4ubv(TH_BACK, -40, col);
+ col[3] *= alpha_fac;
+
+ immUniformColor4ubv(col);
+ immRecti(pos, tempx - 10.0f * ufac,
+ *starty + 4.0f * ufac,
+ tempx - 8.0f * ufac,
+ *starty + UI_UNIT_Y - 4.0f * ufac);
+ immUnbindProgram();
+ }
+
+ outliner_draw_iconrow(C, block, scene, view_layer, soops, &te->subtree, 0, xmax, &tempx,
+ *starty, alpha_fac);
+
glDisable(GL_BLEND);
}
}
@@ -1640,16 +1539,20 @@ static void outliner_draw_tree_element(
te->xs = startx;
te->ys = *starty;
te->xend = startx + offsx;
-
+
if (TSELEM_OPEN(tselem, soops)) {
*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);
+ for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
+ /* check if element needs to be drawn grayed out, but also gray out
+ * childs of a grayed out parent (pass on draw_grayed_out to childs) */
+ bool draw_childs_grayed_out = draw_grayed_out || (ten->drag_data != NULL);
+ outliner_draw_tree_element(C, block, fstyle, scene, view_layer, ar, soops, ten, draw_childs_grayed_out,
+ startx + UI_UNIT_X, starty, te_edit, te_floating);
}
}
else {
- for (ten = te->subtree.first; ten; ten = ten->next) {
+ for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
outliner_set_coord_tree_element(ten, startx, *starty);
}
@@ -1657,115 +1560,277 @@ static void outliner_draw_tree_element(
}
}
-static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx, int *starty)
+static void outliner_draw_tree_element_floating(
+ const ARegion *ar, const TreeElement *te_floating)
+{
+ const TreeElement *te_insert = te_floating->drag_data->insert_handle;
+ const int line_width = 2;
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ int coord_y = te_insert->ys;
+ int coord_x = te_insert->xs;
+ float col[4];
+
+ if (te_insert == te_floating) {
+ /* don't draw anything */
+ return;
+ }
+
+ UI_GetThemeColorShade4fv(TH_BACK, -40, col);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ glEnable(GL_BLEND);
+
+ if (ELEM(te_floating->drag_data->insert_type, TE_INSERT_BEFORE, TE_INSERT_AFTER)) {
+ if (te_floating->drag_data->insert_type == TE_INSERT_BEFORE) {
+ coord_y += UI_UNIT_Y;
+ }
+ immUniformColor4fv(col);
+ glLineWidth(line_width);
+
+ immBegin(GWN_PRIM_LINE_STRIP, 2);
+ immVertex2f(pos, coord_x, coord_y);
+ immVertex2f(pos, ar->v2d.cur.xmax, coord_y);
+ immEnd();
+ }
+ else {
+ BLI_assert(te_floating->drag_data->insert_type == TE_INSERT_INTO);
+ immUniformColor3fvAlpha(col, col[3] * 0.5f);
+
+ immBegin(GWN_PRIM_TRI_STRIP, 4);
+ immVertex2f(pos, coord_x, coord_y + UI_UNIT_Y);
+ immVertex2f(pos, coord_x, coord_y);
+ immVertex2f(pos, ar->v2d.cur.xmax, coord_y + UI_UNIT_Y);
+ immVertex2f(pos, ar->v2d.cur.xmax, coord_y);
+ immEnd();
+ }
+
+ glDisable(GL_BLEND);
+ immUnbindProgram();
+}
+
+static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soops, ListBase *lb, int startx,
+ const unsigned char col[4], bool draw_grayed_out,
+ int *starty)
{
TreeElement *te;
TreeStoreElem *tselem;
int y1, y2;
-
- if (BLI_listbase_is_empty(lb)) return;
-
+
+ if (BLI_listbase_is_empty(lb)) {
+ return;
+ }
+
+ const unsigned char grayed_alpha = col[3] / 2;
+
y1 = y2 = *starty; /* for vertical lines between objects */
for (te = lb->first; te; te = te->next) {
+ bool draw_childs_grayed_out = draw_grayed_out || (te->drag_data != NULL);
y2 = *starty;
tselem = TREESTORE(te);
-
+
+ if (draw_childs_grayed_out) {
+ immUniformColor3ubvAlpha(col, grayed_alpha);
+ }
+ else {
+ immUniformColor4ubv(col);
+ }
+
/* 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(soops, &te->subtree, startx + UI_UNIT_X, starty);
+ outliner_draw_hierarchy_lines_recursive(pos, soops, &te->subtree, startx + UI_UNIT_X,
+ col, draw_childs_grayed_out, starty);
}
-
+
+ if (draw_grayed_out) {
+ immUniformColor3ubvAlpha(col, grayed_alpha);
+ }
+ else {
+ immUniformColor4ubv(col);
+ }
+
/* 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)
+{
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ unsigned char col[4];
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col);
+ col[3] = 255;
+
+ glEnable(GL_BLEND);
+ outliner_draw_hierarchy_lines_recursive(pos, soops, lb, startx, col, false, starty);
+ glDisable(GL_BLEND);
+
+ immUnbindProgram();
+}
+
static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty)
{
TreeElement *te;
TreeStoreElem *tselem;
-
+
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
/* selection status */
if (TSELEM_OPEN(tselem, soops))
- if (tselem->type == TSE_RNA_STRUCT)
- glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
+ if (tselem->type == TSE_RNA_STRUCT) {
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immThemeColorShadeAlpha(TH_BACK, -15, -200);
+ immRecti(pos, 0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
+ immUnbindProgram();
+ }
*starty -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops)) {
outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
- if (tselem->type == TSE_RNA_STRUCT)
- fdrawline(0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
+ if (tselem->type == TSE_RNA_STRUCT) {
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immThemeColorShadeAlpha(TH_BACK, -15, -200);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, 0, (float)*starty + UI_UNIT_Y);
+ immVertex2f(pos, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
+ immEnd();
+
+ immUnbindProgram();
+ }
}
}
}
-static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty)
+static void outliner_draw_highlights_recursive(
+ 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)
{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
-
+ const bool is_searching = SEARCHING_OUTLINER(soops) ||
+ (soops->outlinevis == SO_DATABLOCKS && soops->search_string[0] != 0);
+
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ const TreeStoreElem *tselem = TREESTORE(te);
+ const int start_y = *io_start_y;
+
/* selection status */
if (tselem->flag & TSE_SELECTED) {
- glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
+ 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)) {
+ 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) || (te->drag_data != NULL)) {
+ 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(
+ pos, ar, soops, &te->subtree, col_selection, col_highlight, col_searchmatch,
+ start_x + UI_UNIT_X, io_start_y);
}
- *starty -= UI_UNIT_Y;
- if (TSELEM_OPEN(tselem, soops)) outliner_draw_selection(ar, soops, &te->subtree, starty);
}
}
+static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx, int *starty)
+{
+ const float col_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f};
+ float col_selection[4], col_searchmatch[4];
+
+ UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col_selection);
+ col_selection[3] = 1.0f; /* no alpha */
+ UI_GetThemeColor4fv(TH_MATCH, col_searchmatch);
+ col_searchmatch[3] = 0.5f;
+
+ glEnable(GL_BLEND);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_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,
- SpaceOops *soops, TreeElement **te_edit)
+static void outliner_draw_tree(
+ bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, ARegion *ar,
+ SpaceOops *soops, const bool has_restrict_icons,
+ TreeElement **te_edit)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- TreeElement *te;
+ TreeElement *te_floating = NULL;
int starty, startx;
- float col[3];
-
+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // only once
-
+
if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
/* struct marks */
- UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
- //UI_ThemeColorShade(TH_BACK, -20);
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
outliner_draw_struct_marks(ar, soops, &soops->tree, &starty);
}
-
- /* always draw selection fill before hierarchy */
- UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col);
- glColor3fv(col);
+
+ /* draw highlights before hierarchy */
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
- outliner_draw_selection(ar, soops, &soops->tree, &starty);
-
+ startx = 0;
+ outliner_draw_highlights(ar, soops, startx, &starty);
+
+ /* set scissor so tree elements or lines can't overlap restriction icons */
+ GLfloat scissor[4] = {0};
+ if (has_restrict_icons) {
+ int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)OL_TOGW + 1;
+ CLAMP_MIN(mask_x, 0);
+
+ glGetFloatv(GL_SCISSOR_BOX, scissor);
+ glScissor(ar->winrct.xmin, ar->winrct.ymin, mask_x, ar->winy);
+ }
+
// gray hierarchy lines
- UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.4f);
- starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET;
- startx = UI_UNIT_X / 2 - 1.0f;
- outliner_draw_hierarchy(soops, &soops->tree, startx, &starty);
+ starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET;
+ startx = 6;
+ outliner_draw_hierarchy_lines(soops, &soops->tree, startx, &starty);
+
// items themselves
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
startx = 0;
- for (te = soops->tree.first; te; te = te->next) {
- outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, te, startx, &starty, te_edit);
+ for (TreeElement *te = soops->tree.first; te; te = te->next) {
+ outliner_draw_tree_element(C, block, fstyle, scene, view_layer, ar, soops, te, te->drag_data != NULL,
+ startx, &starty, te_edit, &te_floating);
+ }
+ if (te_floating && te_floating->drag_data->insert_handle) {
+ outliner_draw_tree_element_floating(ar, te_floating);
+ }
+
+ if (has_restrict_icons) {
+ /* reset scissor */
+ glScissor(UNPACK4(scissor));
}
}
@@ -1774,53 +1839,60 @@ static void outliner_back(ARegion *ar)
{
int ystart;
- UI_ThemeColorShade(TH_BACK, 6);
ystart = (int)ar->v2d.tot.ymax;
ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
-
- while (ystart + 2 * UI_UNIT_Y > ar->v2d.cur.ymin) {
- glRecti(0, ystart, (int)ar->v2d.cur.xmax, ystart + UI_UNIT_Y);
- ystart -= 2 * UI_UNIT_Y;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, 6);
+
+ const float x1 = 0.0f, x2 = ar->v2d.cur.xmax;
+ float y1 = ystart, y2;
+ int tot = (int)floor(ystart - ar->v2d.cur.ymin + 2 * UI_UNIT_Y) / (2 * UI_UNIT_Y);
+
+ if (tot > 0) {
+ immBegin(GWN_PRIM_TRIS, 6 * tot);
+ while (tot--) {
+ y1 -= 2 * UI_UNIT_Y;
+ y2 = y1 + UI_UNIT_Y;
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2, y2);
+
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x1, y2);
+ }
+ immEnd();
}
+ immUnbindProgram();
}
static void outliner_draw_restrictcols(ARegion *ar)
{
- int ystart;
-
- /* background underneath */
- UI_ThemeColor(TH_BACK);
- glRecti((int)(ar->v2d.cur.xmax - OL_TOGW),
- (int)(ar->v2d.cur.ymin - 1), (int)ar->v2d.cur.xmax, (int)ar->v2d.cur.ymax);
-
- UI_ThemeColorShade(TH_BACK, 6);
- ystart = (int)ar->v2d.tot.ymax;
- ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
-
- while (ystart + 2 * UI_UNIT_Y > ar->v2d.cur.ymin) {
- glRecti((int)ar->v2d.cur.xmax - OL_TOGW, ystart, (int)ar->v2d.cur.xmax, ystart + UI_UNIT_Y);
- ystart -= 2 * UI_UNIT_Y;
- }
-
- UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
+ glLineWidth(1.0f);
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
+ immBegin(GWN_PRIM_LINES, 6);
/* view */
- sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
- (int)ar->v2d.cur.ymax,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
- (int)ar->v2d.cur.ymin);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymax);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymin);
/* render */
- sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
- (int)ar->v2d.cur.ymax,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
- (int)ar->v2d.cur.ymin);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)ar->v2d.cur.ymax);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)ar->v2d.cur.ymin);
/* render */
- sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
- (int)ar->v2d.cur.ymax,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
- (int)ar->v2d.cur.ymin);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)ar->v2d.cur.ymax);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)ar->v2d.cur.ymin);
+
+ immEnd();
+ immUnbindProgram();
}
/* ****************************************************** */
@@ -1830,14 +1902,16 @@ void draw_outliner(const bContext *C)
{
Main *mainvar = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
SpaceOops *soops = CTX_wm_space_outliner(C);
uiBlock *block;
int sizey = 0, sizex = 0, sizex_rna = 0;
TreeElement *te_edit = NULL;
+ bool has_restrict_icons;
- outliner_build_tree(mainvar, scene, soops); // always
+ outliner_build_tree(mainvar, scene, view_layer, soops); // always
/* get extents of data */
outliner_height(soops, &soops->tree, &sizey);
@@ -1857,6 +1931,7 @@ void draw_outliner(const bContext *C)
/* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */
sizex = sizex_rna + OL_RNA_COL_SIZEX + 50;
+ has_restrict_icons = false;
}
else {
/* width must take into account restriction columns (if visible) so that entries will still be visible */
@@ -1868,7 +1943,8 @@ void draw_outliner(const bContext *C)
// XXX this isn't that great yet...
if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0)
sizex += OL_TOGW * 3;
-
+
+ has_restrict_icons = !(soops->flag & SO_HIDE_RESTRICTCOLS);
}
/* adds vertical offset */
@@ -1885,19 +1961,19 @@ void draw_outliner(const bContext *C)
/* draw outliner stuff (background, hierarchy lines and names) */
outliner_back(ar);
block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
- outliner_draw_tree((bContext *)C, block, scene, ar, soops, &te_edit);
+ outliner_draw_tree((bContext *)C, block, scene, view_layer, ar, soops, has_restrict_icons, &te_edit);
if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
/* draw rna buttons */
outliner_draw_rnacols(ar, sizex_rna);
outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree);
}
- else if ((soops->outlinevis == SO_ID_ORPHANS) && !(soops->flag & SO_HIDE_RESTRICTCOLS)) {
+ else if ((soops->outlinevis == SO_ID_ORPHANS) && has_restrict_icons) {
/* draw user toggle columns */
outliner_draw_restrictcols(ar);
outliner_draw_userbuts(block, ar, soops, &soops->tree);
}
- else if (!(soops->flag & SO_HIDE_RESTRICTCOLS)) {
+ else if (has_restrict_icons) {
/* draw restriction columns */
outliner_draw_restrictcols(ar);
outliner_draw_restrictbuts(block, scene, ar, soops, &soops->tree);
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 0b001ca9578..8cd76179f23 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -51,9 +51,9 @@
#include "BKE_animsys.h"
#include "BKE_context.h"
-#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"
@@ -64,6 +64,8 @@
#include "BKE_material.h"
#include "BKE_group.h"
+#include "DEG_depsgraph_build.h"
+
#include "../blenloader/BLO_readfile.h"
#include "ED_object.h"
@@ -148,8 +150,46 @@ TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2]
return NULL;
}
+
/* ************************************************************** */
-/* Click Activated */
+
+/* Highlight --------------------------------------------------- */
+
+static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
+
+ TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, my);
+ bool changed = false;
+
+ if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) {
+ changed = outliner_set_flag(&soops->tree, TSE_HIGHLIGHTED, false);
+ if (hovered_te) {
+ hovered_te->store_elem->flag |= TSE_HIGHLIGHTED;
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
+ ED_region_tag_redraw(ar);
+ }
+
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+}
+
+void OUTLINER_OT_highlight_update(wmOperatorType *ot)
+{
+ ot->name = "Update Highlight";
+ ot->idname = "OUTLINER_OT_highlight_update";
+ ot->description = "Update the item highlight based on the current mouse position";
+
+ ot->invoke = outliner_highlight_update;
+
+ ot->poll = ED_operator_outliner_active;
+}
/* Toggle Open/Closed ------------------------------------------- */
@@ -216,8 +256,11 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
/* Rename --------------------------------------------------- */
-static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, ReportList *reports)
+static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
+ ReportList *reports)
{
+ bool add_textbut = false;
+
/* can't rename rna datablocks entries or listbases */
if (ELEM(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE)) {
/* do nothing */;
@@ -230,6 +273,18 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
}
+ else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ SceneCollection *master = BKE_collection_master(&scene->id);
+
+ if ((tselem->type == TSE_SCENE_COLLECTION && te->directdata == master) ||
+ (((LayerCollection *)te->directdata)->scene_collection == master))
+ {
+ BKE_report(reports, RPT_WARNING, "Cannot edit name of master collection");
+ }
+ else {
+ add_textbut = true;
+ }
+ }
else if (ID_IS_LINKED(tselem->id)) {
BKE_report(reports, RPT_WARNING, "Cannot edit external libdata");
}
@@ -237,34 +292,39 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library");
}
else {
+ add_textbut = true;
+ }
+
+ if (add_textbut) {
tselem->flag |= TSE_TEXTBUT;
ED_region_tag_redraw(ar);
}
}
void item_rename_cb(
- bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *te,
+ bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
ARegion *ar = CTX_wm_region(C);
- do_item_rename(ar, te, tselem, reports);
+ do_item_rename(scene, ar, te, tselem, reports);
}
-static int do_outliner_item_rename(ReportList *reports, ARegion *ar, TreeElement *te, const float mval[2])
+static int do_outliner_item_rename(const Scene *scene, ReportList *reports, ARegion *ar, TreeElement *te,
+ const float mval[2])
{
if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
TreeStoreElem *tselem = TREESTORE(te);
/* click on name */
if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) {
- do_item_rename(ar, te, tselem, reports);
+ do_item_rename(scene, ar, te, tselem, reports);
return 1;
}
return 0;
}
for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_rename(reports, ar, te, mval)) return 1;
+ if (do_outliner_item_rename(scene, reports, ar, te, mval)) return 1;
}
return 0;
}
@@ -280,7 +340,7 @@ static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *even
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_rename(op->reports, ar, te, fmval)) {
+ if (do_outliner_item_rename(CTX_data_scene(C), op->reports, ar, te, fmval)) {
changed = true;
break;
}
@@ -403,7 +463,6 @@ void OUTLINER_OT_id_delete(wmOperatorType *ot)
static int outliner_id_remap_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
const short id_type = (short)RNA_enum_get(op->ptr, "id_type");
@@ -433,7 +492,7 @@ static int outliner_id_remap_exec(bContext *C, wmOperator *op)
BKE_main_lib_objects_recalc_all(bmain);
/* recreate dependency graph to include new objects */
- DAG_scene_relations_rebuild(bmain, scene);
+ DEG_relations_tag_update(bmain);
/* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */
GPU_materials_free();
@@ -744,17 +803,34 @@ int outliner_has_one_flag(ListBase *lb, short flag, const int curlevel)
return 0;
}
-void outliner_set_flag(ListBase *lb, short flag, short set)
+/**
+ * Set or unset \a flag for all outliner elements in \a lb and sub-trees.
+ * \return if any flag was modified.
+ */
+bool outliner_set_flag(ListBase *lb, short flag, short set)
{
TreeElement *te;
TreeStoreElem *tselem;
-
+ bool changed = false;
+ bool has_flag;
+
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
- if (set == 0) tselem->flag &= ~flag;
- else tselem->flag |= flag;
- outliner_set_flag(&te->subtree, flag, set);
+ has_flag = (tselem->flag & flag);
+ if (set == 0) {
+ if (has_flag) {
+ tselem->flag &= ~flag;
+ changed = true;
+ }
+ }
+ else if (!has_flag) {
+ tselem->flag |= flag;
+ changed = true;
+ }
+ changed |= outliner_set_flag(&te->subtree, flag, set);
}
+
+ return changed;
}
/* Restriction Columns ------------------------------- */
@@ -782,181 +858,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(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(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(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) ---------------------------------------- */
@@ -1077,14 +978,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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
TreeElement *te;
int xdelta, ytop;
- Object *obact = OBACT;
+ Object *obact = OBACT(view_layer);
if (!obact)
return OPERATOR_CANCELLED;
@@ -2002,9 +1903,9 @@ static int parent_drop_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL);
+ ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
@@ -2020,6 +1921,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Main *bmain = CTX_data_main(C);
Scene *scene = NULL;
TreeElement *te = NULL;
+ TreeStoreElem *tselem;
char childname[MAX_ID_NAME];
char parname[MAX_ID_NAME];
int partype = 0;
@@ -2029,8 +1931,21 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* Find object hovered over */
te = outliner_dropzone_find(soops, fmval, true);
+ tselem = te ? TREESTORE(te) : NULL;
- if (te) {
+ if (tselem && ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ SceneCollection *sc = outliner_scene_collection_from_tree_element(te);
+
+ scene = BKE_scene_find_from_collection(bmain, sc);
+ BLI_assert(scene);
+ RNA_string_get(op->ptr, "child", childname);
+ ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
+ BKE_collection_object_add(&scene->id, sc, ob);
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ else if (te) {
RNA_string_set(op->ptr, "parent", te->name);
/* Identify parent and child */
RNA_string_get(op->ptr, "child", childname);
@@ -2062,8 +1977,8 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) {
- if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL)) {
- DAG_relations_tag_update(bmain);
+ if (ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL)) {
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
}
@@ -2191,7 +2106,7 @@ static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
ED_object_parent_clear(ob, RNA_enum_get(op->ptr, "type"));
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
return OPERATOR_FINISHED;
@@ -2234,8 +2149,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);
@@ -2246,19 +2159,29 @@ 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->id);
+ }
+ else {
+ sc = CTX_data_scene_collection(C);
+ }
+
+ BKE_collection_object_add(&scene->id, sc, ob);
+
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ if (base) {
+ ED_object_base_select(base, BA_SELECT);
+ }
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
@@ -2350,7 +2273,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;
@@ -2380,7 +2302,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 ca7dbe4f73c..f69eb9af1bf 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -37,13 +37,49 @@
/* internal exports only */
struct wmOperatorType;
+struct TreeElement;
struct TreeStoreElem;
+struct Main;
struct bContext;
struct Scene;
+struct ViewLayer;
struct ID;
struct Object;
struct bPoseChannel;
struct EditBone;
+struct wmKeyConfig;
+
+
+typedef enum TreeElementInsertType {
+ TE_INSERT_BEFORE,
+ TE_INSERT_AFTER,
+ TE_INSERT_INTO,
+} TreeElementInsertType;
+
+typedef enum TreeTraversalAction {
+ /* Continue traversal regularly, don't skip children. */
+ TRAVERSE_CONTINUE = 0,
+ /* Stop traversal */
+ TRAVERSE_BREAK,
+ /* Continue traversal, but skip childs of traversed element */
+ TRAVERSE_SKIP_CHILDS,
+} TreeTraversalAction;
+
+/**
+ * Callback type for reinserting elements at a different position, used to allow user customizable element order.
+ */
+typedef void (*TreeElementReinsertFunc)(struct Main *bmain,
+ struct TreeElement *insert_element,
+ struct TreeElement *insert_handle, TreeElementInsertType action);
+/**
+ * Executed on (almost) each mouse move while dragging. It's supposed to give info
+ * if reinserting insert_element before/after/into insert_handle would be allowed.
+ * It's allowed to change the reinsert info here for non const pointers.
+ */
+typedef bool (*TreeElementReinsertPollFunc)(const struct TreeElement *insert_element,
+ struct TreeElement **io_insert_handle, TreeElementInsertType *io_action);
+typedef TreeTraversalAction (*TreeTraversalFunc)(struct TreeElement *te, void *customdata);
+
typedef struct TreeElement {
struct TreeElement *next, *prev, *parent;
@@ -57,18 +93,32 @@ typedef struct TreeElement {
const char *name;
void *directdata; // Armature Bones, Base, Sequence, Strip...
PointerRNA rnaptr; // RNA Pointer
-} TreeElement;
+
+ /* callbacks - TODO should be moved into a type (like TreeElementType) */
+ TreeElementReinsertFunc reinsert;
+ TreeElementReinsertPollFunc reinsert_poll;
+
+ struct {
+ TreeElementInsertType insert_type;
+ /* the element before/after/into which we may insert the dragged one (NULL to insert at top) */
+ struct TreeElement *insert_handle;
+ } *drag_data;
+} TreeElement;
#define TREESTORE_ID_TYPE(_id) \
(ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
- ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS) || \
- ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF, ID_PAL)) /* Only in 'blendfile' mode ... :/ */
+ ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS, ID_LP) || \
+ ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF, ID_PAL, ID_WS)) /* Only in 'blendfile' mode ... :/ */
/* TreeElement->flag */
-#define TE_ACTIVE 1
-#define TE_ICONROW 2
-#define TE_LAZY_CLOSED 4
-#define TE_FREE_NAME 8
+enum {
+ TE_ACTIVE = (1 << 0),
+ /* Closed items display their children as icon within the row. TE_ICONROW is for
+ * these child-items that are visible but only within the row of the closed parent. */
+ TE_ICONROW = (1 << 1),
+ TE_LAZY_CLOSED = (1 << 2),
+ TE_FREE_NAME = (1 << 3),
+};
/* button events */
#define OL_NAMEBUTTON 1
@@ -93,11 +143,12 @@ typedef enum {
/* size constants */
#define OL_Y_OFFSET 2
-#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 3.0f)
-#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 2.0f)
+#define OL_TOG_RESTRICT_ENABLEX (UI_UNIT_X * 3.0f)
+#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f)
+#define OL_TOG_RESTRICT_SELECTX UI_UNIT_X
#define OL_TOG_RESTRICT_RENDERX UI_UNIT_X
-#define OL_TOGW OL_TOG_RESTRICT_VIEWX
+#define OL_TOGW OL_TOG_RESTRICT_ENABLEX
#define OL_RNA_COLX (UI_UNIT_X * 15)
#define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f)
@@ -129,15 +180,9 @@ typedef enum {
void outliner_free_tree(ListBase *lb);
void outliner_cleanup_tree(struct SpaceOops *soops);
+void outliner_remove_treestore_element(struct SpaceOops *soops, TreeStoreElem *tselem);
-TreeElement *outliner_find_tse(struct SpaceOops *soops, const TreeStoreElem *tse);
-TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem);
-TreeElement *outliner_find_id(struct SpaceOops *soops, ListBase *lb, const struct ID *id);
-TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *pchan);
-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 ViewLayer *view_layer, struct SpaceOops *soops);
/* outliner_draw.c ---------------------------------------------- */
@@ -146,9 +191,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 ViewLayer *view_layer, 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 ViewLayer *view_layer, SpaceOops *soops,
TreeElement *te, const eOLSetState set, const bool handle_all_types);
void outliner_item_do_activate_from_tree_element(
@@ -164,16 +209,16 @@ typedef void (*outliner_operation_cb)(
struct TreeElement *, struct TreeStoreElem *, TreeStoreElem *, void *);
void outliner_do_object_operation_ex(
- struct bContext *C, ReportList *reports, struct Scene *scene, struct SpaceOops *soops, struct ListBase *lb,
- outliner_operation_cb operation_cb, bool recurse_selected);
+ struct bContext *C, struct ReportList *reports, struct Scene *scene, struct SpaceOops *soops,
+ struct ListBase *lb, outliner_operation_cb operation_cb, bool recurse_selected);
void outliner_do_object_operation(
- struct bContext *C, ReportList *reports, struct Scene *scene, struct SpaceOops *soops, struct ListBase *lb,
- outliner_operation_cb operation_cb);
+ struct bContext *C, struct ReportList *reports, struct Scene *scene, struct SpaceOops *soops,
+ struct ListBase *lb, outliner_operation_cb operation_cb);
int common_restrict_check(struct bContext *C, struct Object *ob);
int outliner_has_one_flag(ListBase *lb, short flag, const int curlevel);
-void outliner_set_flag(ListBase *lb, short flag, short set);
+bool outliner_set_flag(ListBase *lb, short flag, short set);
void object_toggle_visibility_cb(
struct bContext *C, struct ReportList *reports, struct Scene *scene,
@@ -214,8 +259,11 @@ void id_remap_cb(
struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children);
+
/* ...................................................... */
+void OUTLINER_OT_highlight_update(struct wmOperatorType *ot);
+
void OUTLINER_OT_item_activate(struct wmOperatorType *ot);
void OUTLINER_OT_item_openclose(struct wmOperatorType *ot);
void OUTLINER_OT_item_rename(struct wmOperatorType *ot);
@@ -235,10 +283,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);
@@ -267,10 +311,41 @@ void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot);
void OUTLINER_OT_action_set(struct wmOperatorType *ot);
void OUTLINER_OT_constraint_operation(struct wmOperatorType *ot);
void OUTLINER_OT_modifier_operation(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_operation(struct wmOperatorType *ot);
/* ---------------------------------------------------------------- */
/* outliner_ops.c */
void outliner_operatortypes(void);
void outliner_keymap(struct wmKeyConfig *keyconf);
+/* outliner_collections.c */
+
+struct SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te);
+
+void OUTLINER_OT_collections_delete(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_select(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_toggle(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_unlink(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_new(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_override_new(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_add(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot);
+
+/* outliner_utils.c ---------------------------------------------- */
+
+TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y);
+TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x);
+TreeElement *outliner_find_tse(struct SpaceOops *soops, const TreeStoreElem *tse);
+TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem);
+TreeElement *outliner_find_id(struct SpaceOops *soops, ListBase *lb, const struct ID *id);
+TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *pchan);
+TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone);
+struct ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode);
+bool outliner_tree_traverse(const SpaceOops *soops, ListBase *tree, int filter_te_flag, int filter_tselem_flag,
+ TreeTraversalFunc func, void *customdata);
+
+
#endif /* __OUTLINER_INTERN_H__ */
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 776717c8443..856dd022c14 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -28,25 +28,263 @@
* \ingroup spoutliner
*/
-#include "DNA_space_types.h"
+#include "MEM_guardedalloc.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_main.h"
#include "RNA_access.h"
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_screen.h"
+
#include "outliner_intern.h"
+enum {
+ OUTLINER_ITEM_DRAG_CANCEL,
+ OUTLINER_ITEM_DRAG_CONFIRM,
+};
+
+static int outliner_item_drag_drop_poll(bContext *C)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ return ED_operator_outliner_active(C) &&
+ /* Only collection display modes supported for now. Others need more design work */
+ ELEM(soops->outlinevis, SO_ACT_LAYER, SO_COLLECTIONS, SO_GROUPS);
+}
+
+static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event)
+{
+ /* note: using EVT_TWEAK_ events to trigger dragging is fine,
+ * it sends coordinates from where dragging was started */
+ const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
+ return outliner_find_item_at_y(soops, &soops->tree, my);
+}
+
+static void outliner_item_drag_end(TreeElement *dragged_te)
+{
+ MEM_SAFE_FREE(dragged_te->drag_data);
+}
+
+static void outliner_item_drag_get_insert_data(
+ const SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged,
+ TreeElement **r_te_insert_handle, TreeElementInsertType *r_insert_type)
+{
+ TreeElement *te_hovered;
+ float view_mval[2];
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ te_hovered = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
+
+ if (te_hovered) {
+ /* mouse hovers an element (ignoring x-axis), now find out how to insert the dragged item exactly */
+
+ if (te_hovered == te_dragged) {
+ *r_te_insert_handle = te_dragged;
+ }
+ else if (te_hovered != te_dragged) {
+ const float margin = UI_UNIT_Y * (1.0f / 4);
+
+ *r_te_insert_handle = te_hovered;
+ if (view_mval[1] < (te_hovered->ys + margin)) {
+ if (TSELEM_OPEN(TREESTORE(te_hovered), soops)) {
+ /* inserting after a open item means we insert into it, but as first child */
+ if (BLI_listbase_is_empty(&te_hovered->subtree)) {
+ *r_insert_type = TE_INSERT_INTO;
+ }
+ else {
+ *r_insert_type = TE_INSERT_BEFORE;
+ *r_te_insert_handle = te_hovered->subtree.first;
+ }
+ }
+ else {
+ *r_insert_type = TE_INSERT_AFTER;
+ }
+ }
+ else if (view_mval[1] > (te_hovered->ys + (3 * margin))) {
+ *r_insert_type = TE_INSERT_BEFORE;
+ }
+ else {
+ *r_insert_type = TE_INSERT_INTO;
+ }
+ }
+ }
+ else {
+ /* mouse doesn't hover any item (ignoring x-axis), so it's either above list bounds or below. */
+
+ TreeElement *first = soops->tree.first;
+ TreeElement *last = soops->tree.last;
+
+ if (view_mval[1] < last->ys) {
+ *r_te_insert_handle = last;
+ *r_insert_type = TE_INSERT_AFTER;
+ }
+ else if (view_mval[1] > (first->ys + UI_UNIT_Y)) {
+ *r_te_insert_handle = first;
+ *r_insert_type = TE_INSERT_BEFORE;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+}
+
+static void outliner_item_drag_handle(
+ SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged)
+{
+ TreeElement *te_insert_handle;
+ TreeElementInsertType insert_type;
+
+ outliner_item_drag_get_insert_data(soops, ar, event, te_dragged, &te_insert_handle, &insert_type);
+
+ if (!te_dragged->reinsert_poll &&
+ /* there is no reinsert_poll, so we do some generic checks (same types and reinsert callback is available) */
+ (TREESTORE(te_dragged)->type == TREESTORE(te_insert_handle)->type) &&
+ te_dragged->reinsert)
+ {
+ /* pass */
+ }
+ else if (te_dragged == te_insert_handle) {
+ /* nothing will happen anyway, no need to do poll check */
+ }
+ else if (!te_dragged->reinsert_poll ||
+ !te_dragged->reinsert_poll(te_dragged, &te_insert_handle, &insert_type))
+ {
+ te_insert_handle = NULL;
+ }
+ te_dragged->drag_data->insert_type = insert_type;
+ te_dragged->drag_data->insert_handle = te_insert_handle;
+}
+
+static bool outliner_item_drag_drop_apply(Main *bmain, TreeElement *dragged_te)
+{
+ TreeElement *insert_handle = dragged_te->drag_data->insert_handle;
+ TreeElementInsertType insert_type = dragged_te->drag_data->insert_type;
+
+ if ((insert_handle == dragged_te) || !insert_handle) {
+ /* No need to do anything */
+ }
+ else if (dragged_te->reinsert) {
+ BLI_assert(!dragged_te->reinsert_poll || dragged_te->reinsert_poll(dragged_te, &insert_handle,
+ &insert_type));
+ /* call of assert above should not have changed insert_handle and insert_type at this point */
+ BLI_assert(dragged_te->drag_data->insert_handle == insert_handle &&
+ dragged_te->drag_data->insert_type == insert_type);
+ dragged_te->reinsert(bmain, dragged_te, insert_handle, insert_type);
+ return true;
+ }
+
+ return false;
+}
+
+static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Main *bmain = CTX_data_main(C);
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te_dragged = op->customdata;
+ int retval = OPERATOR_RUNNING_MODAL;
+ bool redraw = false;
+ bool skip_rebuild = true;
+
+ switch (event->type) {
+ case EVT_MODAL_MAP:
+ if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) {
+ if (outliner_item_drag_drop_apply(bmain, te_dragged)) {
+ skip_rebuild = false;
+ }
+ retval = OPERATOR_FINISHED;
+ }
+ else if (event->val == OUTLINER_ITEM_DRAG_CANCEL) {
+ retval = OPERATOR_CANCELLED;
+ }
+ else {
+ BLI_assert(0);
+ }
+ WM_event_add_mousemove(C); /* update highlight */
+ outliner_item_drag_end(te_dragged);
+ redraw = true;
+ break;
+ case MOUSEMOVE:
+ outliner_item_drag_handle(soops, ar, event, te_dragged);
+ redraw = true;
+ break;
+ }
+
+ if (skip_rebuild) {
+ soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
+ }
+ if (redraw) {
+ ED_region_tag_redraw(ar);
+ }
+
+ return retval;
+}
+
+static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te_dragged = outliner_item_drag_element_find(soops, ar, event);
+
+ if (!te_dragged) {
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ }
+
+ op->customdata = te_dragged;
+ te_dragged->drag_data = MEM_callocN(sizeof(*te_dragged->drag_data), __func__);
+ /* by default we don't change the item position */
+ te_dragged->drag_data->insert_handle = te_dragged;
+ /* unset highlighted tree element, dragged one will be highlighted instead */
+ outliner_set_flag(&soops->tree, TSE_HIGHLIGHTED, false);
+
+ soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
+ ED_region_tag_redraw(ar);
+
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/**
+ * Notes about Outliner Item Drag 'n Drop:
+ * Right now only collections display mode is supported. But ideally all/most modes would support this. There are
+ * just some open design questions that have to be answered: do we want to allow mixing order of different data types
+ * (like render-layers and objects)? Would that be a purely visual change or would that have any other effect? ...
+ */
+static void OUTLINER_OT_item_drag_drop(wmOperatorType *ot)
+{
+ ot->name = "Drag and Drop Item";
+ ot->idname = "OUTLINER_OT_item_drag_drop";
+ ot->description = "Change the hierarchical position of an item by repositioning it using drag and drop";
+
+ ot->invoke = outliner_item_drag_drop_invoke;
+ ot->modal = outliner_item_drag_drop_modal;
+
+ ot->poll = outliner_item_drag_drop_poll;
+
+ ot->flag = OPTYPE_UNDO;
+}
+
/* ************************** registration **********************************/
void outliner_operatortypes(void)
{
+ WM_operatortype_append(OUTLINER_OT_highlight_update);
WM_operatortype_append(OUTLINER_OT_item_activate);
WM_operatortype_append(OUTLINER_OT_select_border);
WM_operatortype_append(OUTLINER_OT_item_openclose);
WM_operatortype_append(OUTLINER_OT_item_rename);
+ WM_operatortype_append(OUTLINER_OT_item_drag_drop);
WM_operatortype_append(OUTLINER_OT_operation);
WM_operatortype_append(OUTLINER_OT_scene_operation);
WM_operatortype_append(OUTLINER_OT_object_operation);
@@ -61,6 +299,7 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_action_set);
WM_operatortype_append(OUTLINER_OT_constraint_operation);
WM_operatortype_append(OUTLINER_OT_modifier_operation);
+ WM_operatortype_append(OUTLINER_OT_collection_operation);
WM_operatortype_append(OUTLINER_OT_show_one_level);
WM_operatortype_append(OUTLINER_OT_show_active);
@@ -70,10 +309,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);
@@ -87,13 +322,58 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_scene_drop);
WM_operatortype_append(OUTLINER_OT_material_drop);
WM_operatortype_append(OUTLINER_OT_group_link);
+
+ /* collections */
+ WM_operatortype_append(OUTLINER_OT_collections_delete);
+ WM_operatortype_append(OUTLINER_OT_collection_select);
+ WM_operatortype_append(OUTLINER_OT_collection_toggle);
+ WM_operatortype_append(OUTLINER_OT_collection_link);
+ WM_operatortype_append(OUTLINER_OT_collection_unlink);
+ WM_operatortype_append(OUTLINER_OT_collection_new);
+ WM_operatortype_append(OUTLINER_OT_collection_override_new);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_add);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_remove);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_select);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_deselect);
+}
+
+static wmKeyMap *outliner_item_drag_drop_modal_keymap(wmKeyConfig *keyconf)
+{
+ static EnumPropertyItem modal_items[] = {
+ {OUTLINER_ITEM_DRAG_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {OUTLINER_ITEM_DRAG_CONFIRM, "CONFIRM", 0, "Confirm/Drop", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ const char *map_name = "Outliner Item Drap 'n Drop Modal Map";
+
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, map_name);
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if (keymap && keymap->modal_items)
+ return NULL;
+
+ keymap = WM_modalkeymap_add(keyconf, map_name, modal_items);
+
+ /* items for modal map */
+ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, OUTLINER_ITEM_DRAG_CANCEL);
+ WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, OUTLINER_ITEM_DRAG_CANCEL);
+
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, OUTLINER_ITEM_DRAG_CONFIRM);
+ WM_modalkeymap_add_item(keymap, RETKEY, KM_RELEASE, KM_ANY, 0, OUTLINER_ITEM_DRAG_CONFIRM);
+ WM_modalkeymap_add_item(keymap, PADENTER, KM_RELEASE, KM_ANY, 0, OUTLINER_ITEM_DRAG_CONFIRM);
+
+ WM_modalkeymap_assign(keymap, "OUTLINER_OT_item_drag_drop");
+
+ return keymap;
}
void outliner_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Outliner", SPACE_OUTLINER, 0);
wmKeyMapItem *kmi;
-
+
+ WM_keymap_add_item(keymap, "OUTLINER_OT_highlight_update", MOUSEMOVE, KM_ANY, KM_ANY, 0);
+
WM_keymap_add_item(keymap, "OUTLINER_OT_item_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, 0, 0);
@@ -123,6 +403,8 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "OUTLINER_OT_item_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "OUTLINER_OT_operation", RIGHTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "OUTLINER_OT_item_drag_drop", EVT_TWEAK_L, KM_ANY, 0, 0);
+
WM_keymap_add_item(keymap, "OUTLINER_OT_show_hierarchy", HOMEKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "OUTLINER_OT_show_active", PERIODKEY, KM_PRESS, 0, 0);
@@ -140,11 +422,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);
@@ -154,5 +431,7 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_add_selected", DKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_delete_selected", DKEY, KM_PRESS, KM_ALT, 0);
+
+ outliner_item_drag_drop_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 9f79b575966..08b5f337936 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -44,12 +44,15 @@
#include "BLI_listbase.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "BKE_group.h"
#include "BKE_object.h"
+#include "BKE_layer.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_armature.h"
+#include "DEG_depsgraph.h"
+
#include "ED_armature.h"
#include "ED_object.h"
#include "ED_screen.h"
@@ -68,61 +71,12 @@
#include "outliner_intern.h"
-/* ****************************************************** */
-/* Outliner Selection (gray-blue highlight for rows) */
-
-static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *selecting)
-{
- TreeElement *te;
- TreeStoreElem *tselem;
- bool changed = false;
-
- for (te = lb->first; te && *index >= 0; te = te->next, (*index)--) {
- tselem = TREESTORE(te);
-
- /* if we've encountered the right item, set its 'Outliner' selection status */
- if (*index == 0) {
- /* this should be the last one, so no need to do anything with index */
- if ((te->flag & TE_ICONROW) == 0) {
- /* -1 value means toggle testing for now... */
- if (*selecting == -1) {
- if (tselem->flag & TSE_SELECTED)
- *selecting = 0;
- else
- *selecting = 1;
- }
-
- /* set selection */
- if (*selecting)
- tselem->flag |= TSE_SELECTED;
- else
- tselem->flag &= ~TSE_SELECTED;
-
- changed |= true;
- }
- }
- else if (TSELEM_OPEN(tselem, soops)) {
- /* Only try selecting sub-elements if we haven't hit the right element yet
- *
- * Hack warning:
- * Index must be reduced before supplying it to the sub-tree to try to do
- * selection, however, we need to increment it again for the next loop to
- * function correctly
- */
- (*index)--;
- changed |= outliner_select(soops, &te->subtree, index, selecting);
- (*index)++;
- }
- }
-
- return changed;
-}
/* ****************************************************** */
/* Outliner Element Selection/Activation on Click */
static eOLDrawState tree_element_active_renderlayer(
- bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
Scene *sce;
@@ -132,11 +86,11 @@ static eOLDrawState tree_element_active_renderlayer(
sce = (Scene *)tselem->id;
if (set != OL_SETSEL_NONE) {
- sce->r.actlay = tselem->nr;
+ sce->active_view_layer = tselem->nr;
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, sce);
}
else {
- return sce->r.actlay == tselem->nr;
+ return sce->active_view_layer == tselem->nr;
}
return OL_DRAWSEL_NONE;
}
@@ -146,14 +100,14 @@ static eOLDrawState tree_element_active_renderlayer(
* CTRL+LMB: Select/Deselect object and all cildren
* CTRL+SHIFT+LMB: Add/Remove object and all children
*/
-static void do_outliner_object_select_recursive(Scene *scene, Object *ob_parent, bool select)
+static void do_outliner_object_select_recursive(ViewLayer *view_layer, Object *ob_parent, bool select)
{
Base *base;
- for (base = FIRSTBASE; base; base = base->next) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
Object *ob = base->object;
- if ((((ob->restrictflag & OB_RESTRICT_VIEW) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
- ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
+ if ((((base->flag & BASE_VISIBLED) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
+ ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
}
}
}
@@ -184,7 +138,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, ViewLayer *view_layer, SpaceOops *soops,
TreeElement *te, const eOLSetState set, bool recursive)
{
TreeStoreElem *tselem = TREESTORE(te);
@@ -198,7 +152,7 @@ static eOLDrawState tree_element_set_active_object(
}
else {
ob = (Object *)outliner_search_back(soops, te, ID_OB);
- if (ob == OBACT) {
+ if (ob == OBACT(view_layer)) {
return OL_DRAWSEL_NONE;
}
}
@@ -208,34 +162,34 @@ static eOLDrawState tree_element_set_active_object(
sce = (Scene *)outliner_search_back(soops, te, ID_SCE);
if (sce && scene != sce) {
- ED_screen_set_scene(C, CTX_wm_screen(C), sce);
+ WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
scene = sce;
}
/* find associated base in current scene */
- base = BKE_scene_base_find(scene, ob);
+ base = BKE_view_layer_base_find(view_layer, ob);
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_view_layer_base_deselect_all(view_layer);
+ ED_object_base_select(base, BA_SELECT);
}
if (recursive) {
/* Recursive select/deselect for Object hierarchies */
- do_outliner_object_select_recursive(scene, ob, (ob->flag & SELECT) != 0);
+ do_outliner_object_select_recursive(view_layer, ob, (ob->flag & SELECT) != 0);
}
- if (C) {
- ED_base_object_activate(C, base); /* adds notifier */
+ if (set != OL_SETSEL_NONE) {
+ ED_object_base_activate(C, base); /* adds notifier */
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
}
@@ -247,7 +201,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), ViewLayer *view_layer, SpaceOops *soops,
TreeElement *te, const eOLSetState set)
{
TreeElement *tes;
@@ -256,7 +210,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(view_layer) || ob->matbits == NULL) {
return OL_DRAWSEL_NONE; /* just paranoia */
}
@@ -293,19 +247,19 @@ static eOLDrawState tree_element_active_material(
/* Tagging object for update seems a bit stupid here, but looks like we have to do it
* for render views to update. See T42973.
* Note that RNA material update does it too, see e.g. rna_MaterialSlot_update(). */
- DAG_id_tag_update((ID *)ob, OB_RECALC_OB);
+ DEG_id_tag_update((ID *)ob, OB_RECALC_OB);
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
}
return OL_DRAWSEL_NONE;
}
static eOLDrawState tree_element_active_texture(
- bContext *C, Scene *scene, SpaceOops *UNUSED(soops),
+ bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOops *UNUSED(soops),
TreeElement *te, const eOLSetState set)
{
TreeElement *tep;
TreeStoreElem /* *tselem,*/ *tselemp;
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
SpaceButs *sbuts = NULL;
if (ob == NULL) {
@@ -387,14 +341,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), ViewLayer *view_layer, 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(view_layer)) {
/* just paranoia */
return OL_DRAWSEL_NONE;
}
@@ -410,7 +364,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, ViewLayer *UNUSED(sl), SpaceOops *soops,
TreeElement *te, const eOLSetState set)
{
Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
@@ -423,7 +377,7 @@ static eOLDrawState tree_element_active_camera(
}
static eOLDrawState tree_element_active_world(
- bContext *C, Scene *scene, SpaceOops *UNUSED(soops),
+ bContext *C, Scene *scene, ViewLayer *UNUSED(sl), SpaceOops *UNUSED(soops),
TreeElement *te, const eOLSetState set)
{
TreeElement *tep;
@@ -440,7 +394,7 @@ static eOLDrawState tree_element_active_world(
if (set != OL_SETSEL_NONE) {
/* make new scene active */
if (sce && scene != sce) {
- ED_screen_set_scene(C, CTX_wm_screen(C), sce);
+ WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
}
}
@@ -456,7 +410,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, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
Object *ob;
@@ -466,21 +420,20 @@ static eOLDrawState tree_element_active_defgroup(
BLI_assert(te->index + 1 >= 0);
ob->actdef = te->index + 1;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
}
else {
- if (ob == OBACT) {
+ if (ob == OBACT(view_layer))
if (ob->actdef == te->index + 1) {
return OL_DRAWSEL_NORMAL;
}
- }
}
return OL_DRAWSEL_NONE;
}
static eOLDrawState tree_element_active_posegroup(
- bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *UNUSED(scene), ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
Object *ob = (Object *)tselem->id;
@@ -491,7 +444,7 @@ static eOLDrawState tree_element_active_posegroup(
}
}
else {
- if (ob == OBACT && ob->pose) {
+ if (ob == OBACT(view_layer) && ob->pose) {
if (ob->pose->active_group == te->index + 1) {
return OL_DRAWSEL_NORMAL;
}
@@ -501,7 +454,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), ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
{
Object *ob = (Object *)tselem->id;
bArmature *arm = ob->data;
@@ -535,7 +488,7 @@ static eOLDrawState tree_element_active_posechannel(
}
}
else {
- if (ob == OBACT && ob->pose) {
+ if (ob == OBACT(view_layer) && ob->pose) {
if (pchan->bone->flag & BONE_SELECTED) {
return OL_DRAWSEL_NORMAL;
}
@@ -545,14 +498,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, ViewLayer *view_layer, 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(view_layer);
if (ob) {
if (set != OL_SETSEL_EXTEND) {
/* single select forces all other bones to get unselected */
@@ -581,7 +534,7 @@ static eOLDrawState tree_element_active_bone(
}
}
else {
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
if (ob && ob->data == arm) {
if (bone->flag & BONE_SELECTED) {
@@ -654,7 +607,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), ViewLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
{
if (set != OL_SETSEL_NONE) {
Object *ob = (Object *)tselem->id;
@@ -682,7 +635,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), ViewLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
{
if (set != OL_SETSEL_NONE) {
Object *ob = (Object *)tselem->id;
@@ -695,7 +648,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), ViewLayer *UNUSED(sl), SpaceOops *UNUSED(soops),
TreeElement *UNUSED(te), int UNUSED(set))
{
// XXX removed
@@ -703,10 +656,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, ViewLayer *view_layer, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
{
Object *ob = (Object *)tselem->id;
- Base *base = BKE_scene_base_find(scene, ob);
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
if (base == NULL) {
/* Armature not instantiated in current scene (e.g. inside an appended group...). */
@@ -792,7 +745,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), ViewLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
{
wmKeyMapItem *kmi = te->directdata;
@@ -808,84 +761,127 @@ static eOLDrawState tree_element_active_keymap_item(
return OL_DRAWSEL_NONE;
}
+static eOLDrawState tree_element_active_collection(
+ bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+{
+ if (set == OL_SETSEL_NONE) {
+ LayerCollection *active = CTX_data_layer_collection(C);
+
+ /* sometimes the renderlayer has no LayerCollection at all */
+ if (active == NULL) {
+ return OL_DRAWSEL_NONE;
+ }
+
+ if ((tselem->type == TSE_SCENE_COLLECTION && active->scene_collection == te->directdata) ||
+ (tselem->type == TSE_LAYER_COLLECTION && active == te->directdata))
+ {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ /* don't allow selecting a scene collection, it can have multiple layer collection
+ * instances (which one would the user want to be selected then?) */
+ else if (tselem->type == TSE_LAYER_COLLECTION) {
+ LayerCollection *layer_collection = te->directdata;
+
+ switch (layer_collection->scene_collection->type) {
+ case COLLECTION_TYPE_NONE:
+ case COLLECTION_TYPE_GROUP_INTERNAL:
+ {
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(tselem->id, layer_collection);
+ const int collection_index = BKE_layer_collection_findindex(view_layer, layer_collection);
+
+ if (collection_index > -1) {
+ view_layer->active_collection = collection_index;
+ }
+ break;
+ }
+ default:
+ BLI_assert(!"Collection type not fully implemented");
+ }
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ }
+
+ 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, ViewLayer *view_layer, SpaceOops *soops, TreeElement *te,
const eOLSetState set, const bool handle_all_types)
{
switch (te->idcode) {
/* Note: ID_OB only if handle_all_type is true, else objects are handled specially to allow multiple
- * selection. See do_outliner_item_activate_from_cursor. */
+ * 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, view_layer, 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, view_layer, soops, te, set);
case ID_WO:
- return tree_element_active_world(C, scene, soops, te, set);
+ return tree_element_active_world(C, scene, view_layer, soops, te, set);
case ID_LA:
- return tree_element_active_lamp(C, scene, soops, te, set);
+ return tree_element_active_lamp(C, scene, view_layer, soops, te, set);
case ID_TE:
- return tree_element_active_texture(C, scene, soops, te, set);
+ return tree_element_active_texture(C, scene, view_layer, soops, te, set);
case ID_TXT:
- return tree_element_active_text(C, scene, soops, te, set);
+ return tree_element_active_text(C, scene, view_layer, soops, te, set);
case ID_CA:
- return tree_element_active_camera(C, scene, soops, te, set);
+ return tree_element_active_camera(C, scene, view_layer, soops, te, set);
}
return OL_DRAWSEL_NONE;
}
/**
* Generic call for non-id data to make/check active in UI
- *
- * \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, ViewLayer *view_layer, 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, view_layer, te, tselem, set);
case TSE_BONE:
- return tree_element_active_bone(C, scene, te, tselem, set, recursive);
+ return tree_element_active_bone(C, view_layer, 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, view_layer, 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, view_layer, soops, te, set, false);
}
- else if (tselem->id == (ID *)OBACT) {
+ else if (tselem->id == (ID *)OBACT(view_layer)) {
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, view_layer, 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, view_layer, te, tselem, set, recursive);
case TSE_CONSTRAINT:
- return tree_element_active_constraint(C, te, tselem, set);
+ return tree_element_active_constraint(C, scene, view_layer, te, tselem, set);
case TSE_R_LAYER:
- return tree_element_active_renderlayer(C, te, tselem, set);
+ return tree_element_active_renderlayer(C, scene, view_layer, te, tselem, set);
case TSE_POSEGRP:
- return tree_element_active_posegroup(C, scene, te, tselem, set);
+ return tree_element_active_posegroup(C, scene, view_layer, 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, view_layer, 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_SCENE_COLLECTION:
+ case TSE_LAYER_COLLECTION:
+ return tree_element_active_collection(C, te, tselem, set);
}
return OL_DRAWSEL_NONE;
}
@@ -899,16 +895,16 @@ eOLDrawState tree_element_type_active(
* Needed to run from operators accessed from a menu.
*/
static void do_outliner_item_activate_tree_element(
- bContext *C, Scene *scene, SpaceOops *soops,
+ bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
TreeElement *te, TreeStoreElem *tselem,
- bool extend, bool recursive)
+ const bool extend, const bool recursive)
{
/* 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)) {
+ if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE, TSE_LAYER_COLLECTION)) {
tree_element_set_active_object(
- C, scene, soops, te,
+ C, scene, view_layer, soops, te,
(extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
recursive && tselem->type == 0);
}
@@ -917,100 +913,101 @@ static void do_outliner_item_activate_tree_element(
/* editmode? */
if (te->idcode == ID_SCE) {
if (scene != (Scene *)tselem->id) {
- ED_screen_set_scene(C, CTX_wm_screen(C), (Scene *)tselem->id);
+ WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id);
}
}
else if (te->idcode == ID_GR) {
Group *gr = (Group *)tselem->id;
- GroupObject *gob;
if (extend) {
int sel = BA_SELECT;
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if (gob->ob->flag & SELECT) {
+ FOREACH_GROUP_BASE(gr, base)
+ {
+ if (base->flag & BASE_SELECTED) {
sel = BA_DESELECT;
break;
}
}
+ FOREACH_GROUP_BASE_END
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel);
+ FOREACH_GROUP_OBJECT(gr, object)
+ {
+ ED_object_base_select(BKE_view_layer_base_find(view_layer, object), sel);
}
+ FOREACH_GROUP_OBJECT_END
}
else {
- BKE_scene_base_deselect_all(scene);
-
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if ((gob->ob->flag & SELECT) == 0)
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT);
+ BKE_view_layer_base_deselect_all(view_layer);
+
+ FOREACH_GROUP_OBJECT(gr, object)
+ {
+ Base *base = BKE_view_layer_base_find(view_layer, object);
+ /* Object may not be in this scene */
+ if (base != NULL) {
+ if ((base->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
}
+ FOREACH_GROUP_OBJECT_END
}
-
+
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
}
else { // rest of types
- tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, false);
+ tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, false);
}
}
else {
- tree_element_type_active(
- C, scene, soops, te, tselem,
- extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
- recursive);
+ tree_element_type_active(C, scene, view_layer, soops, te, tselem,
+ extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
+ recursive);
}
}
/**
- * Activates tree items, also handles clicking on arrows.
+ * \param extend: Don't deselect other items, only modify \a te.
+ * \param toggle: Select \a te when not selected, deselect when selected.
*/
-static bool do_outliner_item_activate_from_cursor(
- bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops,
- TreeElement *te, bool extend, bool recursive, const float mval[2])
+static void outliner_item_select(SpaceOops *soops, const TreeElement *te, const bool extend, const bool toggle)
{
- if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
- TreeStoreElem *tselem = TREESTORE(te);
- bool openclose = false;
-
- /* open close icon */
- if ((te->flag & TE_ICONROW) == 0) { // hidden icon, no open/close
- if (mval[0] > te->xs && mval[0] < te->xs + UI_UNIT_X)
- openclose = true;
- }
-
- if (openclose) {
- /* all below close/open? */
- if (extend) {
- tselem->flag &= ~TSE_CLOSED;
- outliner_set_flag(&te->subtree, TSE_CLOSED, !outliner_has_one_flag(&te->subtree, TSE_CLOSED, 1));
- }
- else {
- if (tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED;
- else tselem->flag |= TSE_CLOSED;
-
- }
-
- return true;
- }
- /* name and first icon */
- else if (mval[0] > te->xs + UI_UNIT_X && mval[0] < te->xend) {
- do_outliner_item_activate_tree_element(
- C, scene, soops,
- te, tselem,
- extend, recursive);
- return true;
- }
+ TreeStoreElem *tselem = TREESTORE(te);
+ const short new_flag = toggle ? (tselem->flag ^ TSE_SELECTED) : (tselem->flag | TSE_SELECTED);
+
+ if (extend == false) {
+ outliner_set_flag(&soops->tree, TSE_SELECTED, false);
}
-
- for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, mval)) {
- return true;
- }
+ tselem->flag = new_flag;
+}
+
+static void outliner_item_toggle_closed(TreeElement *te, const bool toggle_children)
+{
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (toggle_children) {
+ tselem->flag &= ~TSE_CLOSED;
+
+ const bool all_opened = !outliner_has_one_flag(&te->subtree, TSE_CLOSED, 1);
+ outliner_set_flag(&te->subtree, TSE_CLOSED, all_opened);
+ }
+ else {
+ tselem->flag ^= TSE_CLOSED;
}
- return false;
+}
+
+static bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x)
+{
+ return ((te->flag & TE_ICONROW) == 0) && (view_co_x > te->xs) && (view_co_x < te->xs + UI_UNIT_X);
+}
+
+static bool outliner_is_co_within_restrict_columns(const SpaceOops *soops, const ARegion *ar, float view_co_x)
+{
+ return (!ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF) &&
+ !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
+ (view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX));
}
/**
@@ -1024,10 +1021,11 @@ void outliner_item_do_activate_from_tree_element(
bool extend, bool recursive)
{
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
do_outliner_item_activate_tree_element(
- C, scene, soops,
+ C, scene, view_layer, soops,
te, tselem,
extend, recursive);
}
@@ -1041,56 +1039,52 @@ int outliner_item_do_activate_from_cursor(
bContext *C, const int mval[2],
bool extend, bool recursive)
{
- Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
TreeElement *te;
- float fmval[2];
+ float view_mval[2];
+ bool changed = false, rebuild_tree = false;
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
- if (!ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF) &&
- !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
- (fmval[0] > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX))
- {
+ if (outliner_is_co_within_restrict_columns(soops, ar, view_mval[0])) {
return OPERATOR_CANCELLED;
}
- for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, fmval)) {
- break;
- }
+ if (!(te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]))) {
+ /* skip */
}
-
- if (te) {
- ED_undo_push(C, "Outliner click event");
+ else if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
+ outliner_item_toggle_closed(te, extend);
+ changed = true;
+ rebuild_tree = true;
}
else {
- short selecting = -1;
- int row;
-
- /* get row number - 100 here is just a dummy value since we don't need the column */
- UI_view2d_listview_view_to_cell(&ar->v2d, 1000, UI_UNIT_Y, 0.0f, OL_Y_OFFSET,
- fmval[0], fmval[1], NULL, &row);
-
- /* select relevant row */
- if (outliner_select(soops, &soops->tree, &row, &selecting)) {
-
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ /* the row may also contain children, if one is hovered we want this instead of current te */
+ TreeElement *activate_te = outliner_find_item_at_x_in_row(soops, te, view_mval[0]);
+ TreeStoreElem *activate_tselem = TREESTORE(activate_te);
+
+ outliner_item_select(soops, activate_te, extend, extend);
+ do_outliner_item_activate_tree_element(C, scene, view_layer, soops, activate_te, activate_tselem, extend, recursive);
+ changed = true;
+ }
+
+ if (changed) {
+ if (!rebuild_tree) {
+ /* only needs to redraw, no rebuild */
soops->storeflag |= SO_TREESTORE_REDRAW;
-
- /* no need for undo push here, only changing outliner data which is
- * scene level - campbell */
- /* ED_undo_push(C, "Outliner selection event"); */
}
+ ED_undo_push(C, "Outliner selection change");
+ ED_region_tag_redraw(ar);
}
-
- ED_region_tag_redraw(ar);
return OPERATOR_FINISHED;
}
/* event can enterkey, then it opens/closes */
-static int outliner_item_activate(bContext *C, wmOperator *op, const wmEvent *event)
+static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bool extend = RNA_boolean_get(op->ptr, "extend");
bool recursive = RNA_boolean_get(op->ptr, "recursive");
@@ -1103,7 +1097,7 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot)
ot->idname = "OUTLINER_OT_item_activate";
ot->description = "Handle mouse clicks to activate/select items";
- ot->invoke = outliner_item_activate;
+ ot->invoke = outliner_item_activate_invoke;
ot->poll = ED_operator_outliner_active;
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index cf9deeaedf8..99fd539293f 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -53,9 +53,9 @@
#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_constraint.h"
-#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"
@@ -64,8 +64,12 @@
#include "BKE_scene.h"
#include "BKE_sequencer.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_armature.h"
#include "ED_object.h"
+#include "ED_scene.h"
#include "ED_screen.h"
#include "ED_sequencer.h"
#include "ED_util.h"
@@ -308,7 +312,7 @@ static bool scene_cb(bContext *C, eOutliner_PropSceneOps event, TreeElement *UNU
Scene *scene = (Scene *)tselem->id;
if (event == OL_SCENE_OP_DELETE) {
- if (ED_screen_delete_scene(C, scene)) {
+ if (ED_scene_delete(C, CTX_data_main(C), CTX_wm_window(C), scene)) {
WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene);
}
else {
@@ -359,15 +363,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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (base && ((base->flag & BASE_VISIBLED) != 0)) {
+ base->flag |= BASE_SELECTED;
}
}
@@ -381,15 +385,15 @@ 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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
if (base) {
- base->flag &= ~SELECT;
- base->object->flag &= ~SELECT;
+ base->flag &= ~BASE_SELECTED;
}
}
@@ -397,30 +401,27 @@ static void object_delete_cb(
bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
TreeStoreElem *tsep, TreeStoreElem *tselem, void *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_object_base_free_and_unlink(CTX_data_main(C), scene, ob);
/* leave for ED_outliner_id_unref to handle */
#if 0
te->directdata = NULL;
@@ -518,23 +519,27 @@ static void singleuser_world_cb(
}
static void group_linkobs2scene_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
+ bContext *C, ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SceneCollection *sc = CTX_data_scene_collection(C);
Group *group = (Group *)tselem->id;
- GroupObject *gob;
Base *base;
- for (gob = group->gobject.first; gob; gob = gob->next) {
- base = BKE_scene_base_find(scene, gob->ob);
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ base = BKE_view_layer_base_find(view_layer, object);
if (!base) {
/* link to scene */
- base = BKE_scene_base_add(scene, gob->ob);
- id_us_plus(&gob->ob->id);
+ BKE_collection_object_add(&scene->id, sc, object);
+ base = BKE_view_layer_base_find(view_layer, object);
+ id_us_plus(&object->id);
}
- base->object->flag |= SELECT;
- base->flag |= SELECT;
+
+ base->flag |= BASE_SELECTED;
}
+ FOREACH_GROUP_OBJECT_END
}
static void group_instance_cb(
@@ -566,7 +571,7 @@ void outliner_do_object_operation_ex(
// when objects selected in other scenes... dunno if that should be allowed
Scene *scene_owner = (Scene *)outliner_search_back(soops, te, ID_SCE);
if (scene_owner && scene_act != scene_owner) {
- ED_screen_set_scene(C, CTX_wm_screen(C), scene_owner);
+ WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), scene_owner);
}
/* important to use 'scene_owner' not scene_act else deleting objects can crash.
* only use 'scene_act' when 'scene_owner' is NULL, which can happen when the
@@ -653,6 +658,15 @@ typedef enum eOutliner_PropModifierOps {
OL_MODIFIER_OP_DELETE
} eOutliner_PropModifierOps;
+typedef enum eOutliner_PropCollectionOps {
+ OL_COLLECTION_OP_OBJECTS_ADD = 1,
+ OL_COLLECTION_OP_OBJECTS_REMOVE,
+ OL_COLLECTION_OP_COLLECTION_NEW,
+ OL_COLLECTION_OP_COLLECTION_DEL,
+ OL_COLLECTION_OP_COLLECTION_UNLINK,
+ OL_COLLECTION_OP_GROUP_CREATE,
+} eOutliner_PropCollectionOps;
+
static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
bPoseChannel *pchan = (bPoseChannel *)te->directdata;
@@ -788,12 +802,12 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem
if (event == OL_MODIFIER_OP_TOGVIS) {
md->mode ^= eModifierMode_Realtime;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
}
else if (event == OL_MODIFIER_OP_TOGREN) {
md->mode ^= eModifierMode_Render;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
}
else if (event == OL_MODIFIER_OP_DELETE) {
@@ -803,6 +817,81 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem
}
}
+static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *Carg)
+{
+ bContext *C = (bContext *)Carg;
+ Scene *scene = CTX_data_scene(C);
+ LayerCollection *lc = te->directdata;
+ ID *id = te->store_elem->id;
+ SceneCollection *sc = lc->scene_collection;
+
+ if (event == OL_COLLECTION_OP_OBJECTS_ADD) {
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+ {
+ BKE_collection_object_add(id, sc, ob);
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ else if (event == OL_COLLECTION_OP_OBJECTS_REMOVE) {
+ Main *bmain = CTX_data_main(C);
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+ {
+ BKE_collection_object_remove(bmain, id, sc, ob, true);
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ te->store_elem->flag &= ~TSE_SELECTED;
+ }
+ else if (event == OL_COLLECTION_OP_COLLECTION_NEW) {
+ if (GS(id->name) == ID_GR) {
+ BKE_collection_add(id, sc, COLLECTION_TYPE_GROUP_INTERNAL, NULL);
+ }
+ else {
+ BLI_assert(GS(id->name) == ID_SCE);
+ BKE_collection_add(id, sc, COLLECTION_TYPE_NONE, NULL);
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ else if (event == OL_COLLECTION_OP_COLLECTION_UNLINK) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ if (BLI_findindex(&view_layer->layer_collections, lc) == -1) {
+ /* we can't unlink if the layer collection wasn't directly linked */
+ TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */
+ }
+ else {
+ BKE_collection_unlink(view_layer, lc);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ }
+ else if (event == OL_COLLECTION_OP_COLLECTION_DEL) {
+ if (BKE_collection_remove(id, sc)) {
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ else {
+ /* we can't remove the master collection */
+ TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */
+ }
+ }
+ else if (event == OL_COLLECTION_OP_GROUP_CREATE) {
+ Main *bmain = CTX_data_main(C);
+ BKE_collection_group_create(bmain, scene, lc);
+ DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ else {
+ BLI_assert(!"Collection operation not fully implemented!");
+ }
+}
+
static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb,
void (*operation_cb)(int, TreeElement *, TreeStoreElem *, void *),
void *arg)
@@ -827,12 +916,13 @@ static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *s
{
Base *child_base, *base_next;
Object *parent;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
if (!base) {
return NULL;
}
- for (child_base = scene->base.first; child_base; child_base = base_next) {
+ for (child_base = view_layer->object_bases.first; child_base; child_base = base_next) {
base_next = child_base->next;
for (parent = child_base->object->parent; parent && (parent != base->object); parent = parent->parent);
if (parent) {
@@ -855,7 +945,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_object_base_free_and_unlink(CTX_data_main(C), scene, base->object);
return base_next;
}
@@ -863,11 +953,12 @@ static void object_delete_hierarchy_cb(
bContext *C, ReportList *reports, Scene *scene,
TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Base *base = (Base *)te->directdata;
Object *obedit = scene->obedit;
if (!base) {
- base = BKE_scene_base_find(scene, (Object *)tselem->id);
+ base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id);
}
if (base) {
/* Check also library later. */
@@ -922,6 +1013,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ wmWindow *win = CTX_wm_window(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
int event;
const char *str = NULL;
@@ -936,7 +1028,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
Scene *sce = scene; // to be able to delete, scenes are set...
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_select_cb);
if (scene != sce) {
- ED_screen_set_scene(C, CTX_wm_screen(C), sce);
+ WM_window_change_active_scene(bmain, C, win, sce);
}
str = "Select Objects";
@@ -946,8 +1038,8 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
Scene *sce = scene; // to be able to delete, scenes are set...
outliner_do_object_operation_ex(C, op->reports, scene, soops, &soops->tree, object_select_hierarchy_cb, false);
if (scene != sce) {
- ED_screen_set_scene(C, CTX_wm_screen(C), sce);
- }
+ WM_window_change_active_scene(bmain, C, win, sce);
+ }
str = "Select Object Hierarchy";
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
@@ -966,7 +1058,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
* cleanup tree here to prevent such cases. */
outliner_cleanup_tree(soops);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
str = "Delete Objects";
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
@@ -976,7 +1068,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
/* XXX: See OL_OP_DELETE comment above. */
outliner_cleanup_tree(soops);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
str = "Delete Object Hierarchy";
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
@@ -988,21 +1080,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";
@@ -1090,7 +1167,7 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op)
case OL_GROUPOP_INSTANCE:
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_instance_cb, NULL);
/* works without this except if you try render right after, see: 22027 */
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
break;
case OL_GROUPOP_DELETE:
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
@@ -1098,15 +1175,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;
@@ -1628,7 +1696,7 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
/* update dependencies */
if (updateDeps) {
/* rebuild depsgraph for the new deps */
- DAG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(CTX_data_main(C));
}
return OPERATOR_FINISHED;
@@ -1746,6 +1814,81 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot)
/* ******************** */
+static EnumPropertyItem prop_collection_op_none_types[] = {
+ {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"},
+ {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"},
+ {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"},
+ {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"},
+ {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"},
+ {OL_COLLECTION_OP_GROUP_CREATE, "GROUP_CREATE", ICON_GROUP, "Create Group", "Turn the collection into a group collection"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static EnumPropertyItem prop_collection_op_group_internal_types[] = {
+ {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"},
+ {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"},
+ {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"},
+ {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static const EnumPropertyItem *outliner_collection_operation_type_itemf(
+ bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ *r_free = false;
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+
+ switch (soops->outlinevis) {
+ case SO_GROUPS:
+ return prop_collection_op_group_internal_types;
+ case SO_ACT_LAYER:
+ return prop_collection_op_none_types;
+ }
+ return NULL;
+}
+
+static int outliner_collection_operation_exec(bContext *C, wmOperator *op)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ eOutliner_PropCollectionOps event;
+
+ event = RNA_enum_get(op->ptr, "type");
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, collection_cb, C);
+
+ outliner_cleanup_tree(soops);
+
+ ED_undo_push(C, "Collection operation");
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_operation(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Outliner Collection Operation";
+ ot->idname = "OUTLINER_OT_collection_operation";
+ ot->description = "";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_collection_operation_exec;
+ ot->poll = ED_operator_outliner_active;
+
+ ot->flag = 0;
+
+ prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Collection Operation", "");
+ RNA_def_enum_funcs(prop, outliner_collection_operation_type_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
+}
+
+/* ******************** */
+
// XXX: select linked is for RNA structs only
static const EnumPropertyItem prop_data_op_types[] = {
{OL_DOP_SELECT, "SELECT", 0, "Select", ""},
@@ -1920,6 +2063,9 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else if (datalevel == TSE_MODIFIER) {
WM_operator_name_call(C, "OUTLINER_OT_modifier_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
+ else if (datalevel == TSE_LAYER_COLLECTION) {
+ WM_operator_name_call(C, "OUTLINER_OT_collection_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
else {
WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index cf77afa32c4..a9c9ab74970 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -46,6 +46,7 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_world_types.h"
@@ -63,12 +64,15 @@
#include "BKE_fcurve.h"
#include "BKE_main.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
#include "BKE_sequencer.h"
#include "BKE_idcode.h"
#include "BKE_outliner_treehash.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_armature.h"
#include "ED_screen.h"
@@ -83,6 +87,11 @@
# include "BLI_math_base.h" /* M_PI */
#endif
+/* prototypes */
+static void outliner_add_layer_collections_recursive(
+ SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten);
+static void outliner_make_hierarchy(ListBase *lb);
+
/* ********************************************************* */
/* Persistent Data */
@@ -199,105 +208,6 @@ void outliner_cleanup_tree(SpaceOops *soops)
outliner_storage_cleanup(soops);
}
-/* Find specific item from the treestore */
-TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem)
-{
- TreeElement *te, *tes;
- for (te = lb->first; te; te = te->next) {
- if (te->store_elem == store_elem) return te;
- tes = outliner_find_tree_element(&te->subtree, store_elem);
- if (tes) return tes;
- }
- return NULL;
-}
-
-/* tse is not in the treestore, we use its contents to find a match */
-TreeElement *outliner_find_tse(SpaceOops *soops, const TreeStoreElem *tse)
-{
- TreeStoreElem *tselem;
-
- if (tse->id == NULL) return NULL;
-
- /* check if 'tse' is in treestore */
- tselem = BKE_outliner_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
- if (tselem)
- return outliner_find_tree_element(&soops->tree, tselem);
-
- return NULL;
-}
-
-/* Find treestore that refers to given ID */
-TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id)
-{
- for (TreeElement *te = lb->first; te; te = te->next) {
- TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0) {
- if (tselem->id == id) {
- return te;
- }
- /* only deeper on scene or object */
- if (ELEM(te->idcode, ID_OB, ID_SCE) ||
- ((soops->outlinevis == SO_GROUPS) && (te->idcode == ID_GR)))
- {
- TreeElement *tes = outliner_find_id(soops, &te->subtree, id);
- if (tes) {
- return tes;
- }
- }
- }
- }
- return NULL;
-}
-
-TreeElement *outliner_find_posechannel(ListBase *lb, const bPoseChannel *pchan)
-{
- for (TreeElement *te = lb->first; te; te = te->next) {
- if (te->directdata == pchan) {
- return te;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, TSE_POSE_BASE, TSE_POSE_CHANNEL)) {
- TreeElement *tes = outliner_find_posechannel(&te->subtree, pchan);
- if (tes) {
- return tes;
- }
- }
- }
- return NULL;
-}
-
-TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone)
-{
- for (TreeElement *te = lb->first; te; te = te->next) {
- if (te->directdata == ebone) {
- return te;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, 0, TSE_EBONE)) {
- TreeElement *tes = outliner_find_editbone(&te->subtree, ebone);
- if (tes) {
- return tes;
- }
- }
- }
- return NULL;
-}
-
-ID *outliner_search_back(SpaceOops *UNUSED(soops), TreeElement *te, short idcode)
-{
- TreeStoreElem *tselem;
- te = te->parent;
-
- while (te) {
- tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == idcode) return tselem->id;
- te = te->parent;
- }
- return NULL;
-}
-
/* ********************************************************* */
@@ -326,7 +236,7 @@ static void outliner_add_bone(SpaceOops *soops, ListBase *lb, ID *id, Bone *curB
#define LOG2I(x) (int)(log(x) / M_LN2)
-static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, SceneRenderLayer *srl)
+static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, ViewLayer *view_layer)
{
TreeStoreElem *tselem = NULL;
TreeElement *te = NULL;
@@ -336,7 +246,7 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_COMBINED));
te->name = IFACE_("Combined");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
/* save cpu cycles, but we add the first to invoke an open/close triangle */
tselem = TREESTORE(tenla);
@@ -345,71 +255,71 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_Z));
te->name = IFACE_("Z");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_VECTOR));
te->name = IFACE_("Vector");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_NORMAL));
te->name = IFACE_("Normal");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_UV));
te->name = IFACE_("UV");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_MIST));
te->name = IFACE_("Mist");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXOB));
te->name = IFACE_("Index Object");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXMA));
te->name = IFACE_("Index Material");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_RGBA));
te->name = IFACE_("Color");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_DIFFUSE));
te->name = IFACE_("Diffuse");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SPEC));
te->name = IFACE_("Specular");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SHADOW));
te->name = IFACE_("Shadow");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_AO));
te->name = IFACE_("AO");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFLECT));
te->name = IFACE_("Reflection");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFRACT));
te->name = IFACE_("Refraction");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDIRECT));
te->name = IFACE_("Indirect");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_ENVIRONMENT));
te->name = IFACE_("Environment");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_EMIT));
te->name = IFACE_("Emit");
- te->directdata = &srl->passflag;
+ te->directdata = &view_layer->passflag;
}
#undef LOG2I
@@ -424,19 +334,19 @@ static bool outliner_animdata_test(AnimData *adt)
#ifdef WITH_FREESTYLE
static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
{
- SceneRenderLayer *srl;
+ ViewLayer *view_layer;
FreestyleLineSet *lineset;
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
FreestyleLineStyle *linestyle = lineset->linestyle;
if (linestyle) {
linestyle->id.tag |= LIB_TAG_DOIT;
}
}
}
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
FreestyleLineStyle *linestyle = lineset->linestyle;
if (linestyle) {
if (!(linestyle->id.tag & LIB_TAG_DOIT))
@@ -451,22 +361,16 @@ static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce,
static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
{
- SceneRenderLayer *srl;
+ ViewLayer *view_layer;
TreeElement *tenla = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
int a;
tenla->name = IFACE_("RenderLayers");
- for (a = 0, srl = sce->r.layers.first; srl; srl = srl->next, a++) {
+ for (a = 0, view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next, a++) {
TreeElement *tenlay = outliner_add_element(soops, &tenla->subtree, sce, te, TSE_R_LAYER, a);
- tenlay->name = srl->name;
- tenlay->directdata = &srl->layflag;
-
- if (srl->light_override)
- outliner_add_element(soops, &tenlay->subtree, srl->light_override, tenlay, TSE_LINKED_LAMP, 0);
- if (srl->mat_override)
- outliner_add_element(soops, &tenlay->subtree, srl->mat_override, tenlay, TSE_LINKED_MAT, 0);
-
- outliner_add_passes(soops, tenlay, &sce->id, srl);
+ tenlay->name = view_layer->name;
+ tenlay->directdata = &view_layer->flag;
+ outliner_add_passes(soops, tenlay, &sce->id, view_layer);
}
// TODO: move this to the front?
@@ -478,17 +382,63 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
outliner_add_element(soops, lb, sce->world, te, 0, 0);
#ifdef WITH_FREESTYLE
- if (STREQ(sce->r.engine, RE_engine_id_BLENDER_RENDER) && (sce->r.mode & R_EDGE_FRS))
+ if (STREQ(sce->view_render->engine_id, RE_engine_id_BLENDER_RENDER) && (sce->r.mode & R_EDGE_FRS))
outliner_add_line_styles(soops, lb, sce, te);
#endif
}
+static void outliner_object_reorder(
+ Main *UNUSED(bmain),
+ TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+{
+ TreeStoreElem *tselem_insert = TREESTORE(insert_element);
+ Object *ob = (Object *)tselem_insert->id;
+ SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle);
+ SceneCollection *sc_ob_parent = NULL;
+ ID *id = insert_handle->store_elem->id;
+
+ BLI_assert(action == TE_INSERT_INTO);
+ UNUSED_VARS_NDEBUG(action);
+
+ /* find parent scene-collection of object */
+ if (insert_element->parent) {
+ for (TreeElement *te_ob_parent = insert_element->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) {
+ if (ELEM(TREESTORE(te_ob_parent)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
+ sc_ob_parent = outliner_scene_collection_from_tree_element(te_ob_parent);
+ break;
+ }
+ }
+ }
+ else {
+ sc_ob_parent = BKE_collection_master(id);
+ }
+ BKE_collection_object_move(id, sc, sc_ob_parent, ob);
+}
+
+static bool outliner_object_reorder_poll(
+ const TreeElement *insert_element,
+ TreeElement **io_insert_handle, TreeElementInsertType *io_action)
+{
+ TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+ if (ELEM(tselem_handle->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION) &&
+ (insert_element->parent != *io_insert_handle))
+ {
+ *io_action = TE_INSERT_INTO;
+ return true;
+ }
+
+ return false;
+}
+
// can be inlined if necessary
static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, Object *ob)
{
+ te->reinsert = outliner_object_reorder;
+ te->reinsert_poll = outliner_object_reorder_poll;
+
if (outliner_animdata_test(ob->adt))
outliner_add_element(soops, &te->subtree, ob, te, TSE_ANIM_DATA, 0);
-
+
outliner_add_element(soops, &te->subtree, ob->poselib, te, 0, 0); // XXX FIXME.. add a special type for this
if (ob->proxy && !ID_IS_LINKED(ob))
@@ -778,6 +728,14 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
outliner_add_element(soops, &te->subtree, spk, te, TSE_ANIM_DATA, 0);
break;
}
+ case ID_LP:
+ {
+ LightProbe *prb = (LightProbe *)id;
+
+ if (outliner_animdata_test(prb->adt))
+ outliner_add_element(soops, &te->subtree, prb, te, TSE_ANIM_DATA, 0);
+ break;
+ }
case ID_WO:
{
World *wrld = (World *)id;
@@ -905,7 +863,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
id = TREESTORE(parent)->id;
}
- /* One exception */
+ /* exceptions */
if (type == TSE_ID_BASE) {
/* pass */
}
@@ -943,6 +901,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_GP_LAYER) {
/* pass */
}
+ else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ /* pass */
+ }
else if (type == TSE_ID_BASE) {
/* pass */
}
@@ -1241,9 +1202,23 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
te->flag |= TE_LAZY_CLOSED;
}
+ if ((type != TSE_LAYER_COLLECTION) && GS(id->name) == ID_GR) {
+ Group *group = (Group *)id;
+ outliner_add_layer_collections_recursive(soops, &te->subtree, id, &group->view_layer->layer_collections, NULL);
+ }
+
return te;
}
+/**
+ * \note Really only removes \a tselem, not it's TreeElement instance or any children.
+ */
+void outliner_remove_treestore_element(SpaceOops *soops, TreeStoreElem *tselem)
+{
+ BKE_outliner_treehash_remove_element(soops->treehash, tselem);
+ BLI_mempool_free(soops->treestore, tselem);
+}
+
/* ======================================================= */
/* Sequencer mode tree building */
@@ -1381,6 +1356,155 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
}
}
+static void outliner_layer_collections_reorder(
+ Main *bmain,
+ TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+{
+ LayerCollection *lc_insert = insert_element->directdata;
+ LayerCollection *lc_handle = insert_handle->directdata;
+ ID *id = insert_element->store_elem->id;
+
+ if (action == TE_INSERT_BEFORE) {
+ BKE_layer_collection_move_above(id, lc_handle, lc_insert);
+ }
+ else if (action == TE_INSERT_AFTER) {
+ BKE_layer_collection_move_below(id, lc_handle, lc_insert);
+ }
+ else if (action == TE_INSERT_INTO) {
+ BKE_layer_collection_move_into(id, lc_handle, lc_insert);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ DEG_relations_tag_update(bmain);
+}
+static bool outliner_layer_collections_reorder_poll(
+ const TreeElement *insert_element,
+ TreeElement **io_insert_handle, TreeElementInsertType *UNUSED(io_action))
+{
+ const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+
+ if (tselem_handle->id != insert_element->store_elem->id) {
+ return false;
+ }
+
+ return ELEM(tselem_handle->type, TSE_LAYER_COLLECTION);
+}
+
+static void outliner_add_layer_collections_recursive(
+ SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten)
+{
+ for (LayerCollection *collection = layer_collections->first; collection; collection = collection->next) {
+ TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0);
+
+ ten->name = collection->scene_collection->name;
+ ten->directdata = collection;
+ ten->reinsert = outliner_layer_collections_reorder;
+ ten->reinsert_poll = outliner_layer_collections_reorder_poll;
+
+ outliner_add_layer_collections_recursive(soops, &ten->subtree, id, &collection->layer_collections, ten);
+ for (LinkData *link = collection->object_bases.first; link; link = link->next) {
+ Base *base = (Base *)link->data;
+ TreeElement *te_object = outliner_add_element(soops, &ten->subtree, base->object, ten, 0, 0);
+ te_object->directdata = base;
+ }
+ outliner_make_hierarchy(&ten->subtree);
+ }
+}
+static void outliner_add_collections_act_layer(SpaceOops *soops, Scene *scene, ViewLayer *layer)
+{
+ outliner_add_layer_collections_recursive(soops, &soops->tree, &scene->id, &layer->layer_collections, NULL);
+}
+
+static void outliner_scene_collections_reorder(
+ Main *bmain,
+ TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+{
+ SceneCollection *sc_insert = insert_element->directdata;
+ SceneCollection *sc_handle = insert_handle->directdata;
+ ID *id = insert_handle->store_elem->id;
+ BLI_assert(id == insert_element->store_elem->id);
+
+ BLI_assert((action == TE_INSERT_INTO) || (sc_handle != BKE_collection_master(id)));
+ if (action == TE_INSERT_BEFORE) {
+ BKE_collection_move_above(id, sc_handle, sc_insert);
+ }
+ else if (action == TE_INSERT_AFTER) {
+ BKE_collection_move_below(id, sc_handle, sc_insert);
+ }
+ else if (action == TE_INSERT_INTO) {
+ BKE_collection_move_into(id, sc_handle, sc_insert);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ DEG_relations_tag_update(bmain);
+}
+static bool outliner_scene_collections_reorder_poll(
+ const TreeElement *insert_element,
+ TreeElement **io_insert_handle, TreeElementInsertType *io_action)
+{
+ const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+ ID *id = tselem_handle->id;
+
+ if (id != insert_element->store_elem->id) {
+ return false;
+ }
+
+ if (!ELEM(tselem_handle->type, TSE_SCENE_COLLECTION)) {
+ return false;
+ }
+
+ SceneCollection *sc_master = BKE_collection_master(id);
+ SceneCollection *sc_handle = (*io_insert_handle)->directdata;
+
+ if (sc_handle == sc_master) {
+ /* exception: Can't insert before/after master selection, has to be one of its childs */
+ TreeElement *te_master = *io_insert_handle;
+ if (*io_action == TE_INSERT_BEFORE) {
+ /* can't go higher than master collection, insert into it */
+ *io_action = TE_INSERT_INTO;
+ }
+ else if (*io_action == TE_INSERT_AFTER) {
+ *io_insert_handle = te_master->subtree.last;
+ }
+ }
+ return true;
+}
+
+static void outliner_add_scene_collection_objects(
+ SpaceOops *soops, ListBase *tree, SceneCollection *collection, TreeElement *parent)
+{
+ for (LinkData *link = collection->objects.first; link; link = link->next) {
+ outliner_add_element(soops, tree, link->data, parent, 0, 0);
+ }
+ outliner_make_hierarchy(tree);
+}
+
+static void outliner_add_scene_collections_recursive(
+ SpaceOops *soops, ListBase *tree, ListBase *scene_collections, TreeElement *parent_ten)
+{
+ for (SceneCollection *collection = scene_collections->first; collection; collection = collection->next) {
+ TreeElement *ten = outliner_add_element(soops, tree, collection, parent_ten, TSE_SCENE_COLLECTION, 0);
+
+ ten->name = collection->name;
+ ten->directdata = collection;
+ ten->reinsert = outliner_scene_collections_reorder;
+ ten->reinsert_poll = outliner_scene_collections_reorder_poll;
+
+ outliner_add_scene_collections_recursive(soops, &ten->subtree, &collection->scene_collections, ten);
+ outliner_add_scene_collection_objects(soops, &ten->subtree, collection, ten);
+ }
+}
+static void outliner_add_collections_master(SpaceOops *soops, Scene *scene)
+{
+ SceneCollection *master = BKE_collection_master(&scene->id);
+ outliner_add_scene_collections_recursive(soops, &soops->tree, &master->scene_collections, NULL);
+ outliner_add_scene_collection_objects(soops, &soops->tree, master, NULL);
+}
+
/* ======================================================= */
/* Generic Tree Building helpers - order these are called is top to bottom */
@@ -1494,18 +1618,15 @@ static void outliner_sort(ListBase *lb)
{
TreeElement *te;
TreeStoreElem *tselem;
- int totelem = 0;
te = lb->last;
if (te == NULL) return;
tselem = TREESTORE(te);
-
+
/* sorting rules; only object lists, ID lists, or deformgroups */
- if ( ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || (tselem->type == 0 && te->idcode == ID_OB)) {
-
- /* count first */
- for (te = lb->first; te; te = te->next) totelem++;
-
+ if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || (tselem->type == 0 && te->idcode == ID_OB)) {
+ int totelem = BLI_listbase_count(lb);
+
if (totelem > 1) {
tTreeSort *tear = MEM_mallocN(totelem * sizeof(tTreeSort), "tree sort array");
tTreeSort *tp = tear;
@@ -1630,9 +1751,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, ViewLayer *view_layer, 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 */
@@ -1713,72 +1833,71 @@ 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;
+
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ 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;
+
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ 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);
+ FOREACH_VISIBLE_BASE(view_layer, base)
+ {
+ ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten->directdata = base;
+
}
+ FOREACH_VISIBLE_BASE_END
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_GROUPS) {
Group *group;
- GroupObject *go;
-
for (group = mainvar->group.first; group; group = group->id.next) {
- if (group->gobject.first) {
- te = outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
-
- 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) */
- for (go = group->gobject.first; go; go = go->next) go->ob->id.newid = NULL;
- }
+ te = outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
+ outliner_make_hierarchy(&te->subtree);
}
}
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(view_layer);
+ if (ob_active) {
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ if (ob->type == ob_active->type) {
+ 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;
- }
- }
+ FOREACH_SELECTED_BASE(view_layer, base)
+ {
+ ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten->directdata = base;
}
+ FOREACH_SELECTED_BASE_END
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_SEQUENCE) {
@@ -1832,9 +1951,15 @@ 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_ACT_LAYER) {
+ outliner_add_collections_act_layer(soops, scene, view_layer);
+ }
+ else if (soops->outlinevis == SO_COLLECTIONS) {
+ outliner_add_collections_master(soops, scene);
+ }
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(view_layer), NULL, 0, 0);
+ ten->directdata = BASACT(view_layer);
}
if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) {
diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c
new file mode 100644
index 00000000000..d3f7fd7055e
--- /dev/null
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -0,0 +1,233 @@
+/*
+ * ***** 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) 2017 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_outliner/outliner_utils.c
+ * \ingroup spoutliner
+ */
+
+#include "BLI_utildefines.h"
+
+#include "DNA_action_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_outliner_treehash.h"
+
+#include "ED_armature.h"
+
+#include "UI_interface.h"
+
+#include "outliner_intern.h"
+
+/**
+ * Try to find an item under y-coordinate \a view_co_y (view-space).
+ * \note Recursive
+ */
+TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y)
+{
+ for (TreeElement *te_iter = tree->first; te_iter; te_iter = te_iter->next) {
+ if (view_co_y < (te_iter->ys + UI_UNIT_Y)) {
+ if (view_co_y >= te_iter->ys) {
+ /* co_y is inside this element */
+ return te_iter;
+ }
+ else if (TSELEM_OPEN(te_iter->store_elem, soops)) {
+ /* co_y is lower than current element, possibly inside children */
+ TreeElement *te_sub = outliner_find_item_at_y(soops, &te_iter->subtree, view_co_y);
+ if (te_sub) {
+ return te_sub;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Collapsed items can show their children as click-able icons. This function tries to find
+ * such an icon that represents the child item at x-coordinate \a view_co_x (view-space).
+ *
+ * \return a hovered child item or \a parent_te (if no hovered child found).
+ */
+TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x)
+{
+ if (!TSELEM_OPEN(TREESTORE(parent_te), soops)) { /* if parent_te is opened, it doesn't show childs in row */
+ /* no recursion, items can only display their direct children in the row */
+ for (TreeElement *child_te = parent_te->subtree.first;
+ child_te && view_co_x >= child_te->xs; /* don't look further if co_x is smaller than child position*/
+ child_te = child_te->next)
+ {
+ if ((child_te->flag & TE_ICONROW) && (view_co_x > child_te->xs) && (view_co_x < child_te->xend)) {
+ return child_te;
+ }
+ }
+ }
+
+ /* return parent if no child is hovered */
+ return (TreeElement *)parent_te;
+}
+
+/* Find specific item from the treestore */
+TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem)
+{
+ TreeElement *te, *tes;
+ for (te = lb->first; te; te = te->next) {
+ if (te->store_elem == store_elem) return te;
+ tes = outliner_find_tree_element(&te->subtree, store_elem);
+ if (tes) return tes;
+ }
+ return NULL;
+}
+
+/* tse is not in the treestore, we use its contents to find a match */
+TreeElement *outliner_find_tse(SpaceOops *soops, const TreeStoreElem *tse)
+{
+ TreeStoreElem *tselem;
+
+ if (tse->id == NULL) return NULL;
+
+ /* check if 'tse' is in treestore */
+ tselem = BKE_outliner_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
+ if (tselem)
+ return outliner_find_tree_element(&soops->tree, tselem);
+
+ return NULL;
+}
+
+/* Find treestore that refers to given ID */
+TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id)
+{
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (tselem->type == 0) {
+ if (tselem->id == id) {
+ return te;
+ }
+ /* only deeper on scene or object */
+ if (ELEM(te->idcode, ID_OB, ID_SCE) ||
+ ((soops->outlinevis == SO_GROUPS) && (te->idcode == ID_GR)))
+ {
+ TreeElement *tes = outliner_find_id(soops, &te->subtree, id);
+ if (tes) {
+ return tes;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+TreeElement *outliner_find_posechannel(ListBase *lb, const bPoseChannel *pchan)
+{
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ if (te->directdata == pchan) {
+ return te;
+ }
+
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (ELEM(tselem->type, TSE_POSE_BASE, TSE_POSE_CHANNEL)) {
+ TreeElement *tes = outliner_find_posechannel(&te->subtree, pchan);
+ if (tes) {
+ return tes;
+ }
+ }
+ }
+ return NULL;
+}
+
+TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone)
+{
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ if (te->directdata == ebone) {
+ return te;
+ }
+
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (ELEM(tselem->type, 0, TSE_EBONE)) {
+ TreeElement *tes = outliner_find_editbone(&te->subtree, ebone);
+ if (tes) {
+ return tes;
+ }
+ }
+ }
+ return NULL;
+}
+
+ID *outliner_search_back(SpaceOops *UNUSED(soops), TreeElement *te, short idcode)
+{
+ TreeStoreElem *tselem;
+ te = te->parent;
+
+ while (te) {
+ tselem = TREESTORE(te);
+ if (tselem->type == 0 && te->idcode == idcode) return tselem->id;
+ te = te->parent;
+ }
+ return NULL;
+}
+
+/**
+ * Iterate over all tree elements (pre-order traversal), executing \a func callback for
+ * each tree element matching the optional filters.
+ *
+ * \param filter_te_flag: If not 0, only TreeElements with this flag will be visited.
+ * \param filter_tselem_flag: Same as \a filter_te_flag, but for the TreeStoreElem.
+ * \param func: Custom callback to execute for each visited item.
+ */
+bool outliner_tree_traverse(const SpaceOops *soops, ListBase *tree, int filter_te_flag, int filter_tselem_flag,
+ TreeTraversalFunc func, void *customdata)
+{
+ for (TreeElement *te = tree->first, *te_next; te; te = te_next) {
+ TreeTraversalAction func_retval = TRAVERSE_CONTINUE;
+ /* in case te is freed in callback */
+ TreeStoreElem *tselem = TREESTORE(te);
+ ListBase subtree = te->subtree;
+ te_next = te->next;
+
+ if (filter_te_flag && (te->flag & filter_te_flag) == 0) {
+ /* skip */
+ }
+ else if (filter_tselem_flag && (tselem->flag & filter_tselem_flag) == 0) {
+ /* skip */
+ }
+ else {
+ func_retval = func(te, customdata);
+ }
+ /* Don't access te or tselem from now on! Might've been freed... */
+
+ if (func_retval == TRAVERSE_BREAK) {
+ return false;
+ }
+
+ if (func_retval == TRAVERSE_SKIP_CHILDS) {
+ /* skip */
+ }
+ else if (!outliner_tree_traverse(soops, &subtree, filter_te_flag, filter_tselem_flag, func, customdata)) {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 759ef4e78e4..1bc1a227a03 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -39,6 +39,7 @@
#include "BLI_mempool.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_screen.h"
#include "BKE_scene.h"
#include "BKE_outliner_treehash.h"
@@ -102,10 +103,14 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
if (GS(id->name) == ID_OB) {
/* Ensure item under cursor is valid drop target */
TreeElement *te = outliner_dropzone_find(soops, fmval, true);
+ TreeStoreElem *tselem = te ? TREESTORE(te) : NULL;
- if (te && te->idcode == ID_OB && TREESTORE(te)->type == 0) {
+ if (!te) {
+ /* pass */
+ }
+ else if (te->idcode == ID_OB && tselem->type == 0) {
Scene *scene;
- ID *te_id = TREESTORE(te)->id;
+ ID *te_id = tselem->id;
/* check if dropping self or parent */
if (te_id == id || (Object *)te_id == ((Object *)id)->parent)
@@ -118,9 +123,23 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
* element for object it means that all displayed objects belong to
* active scene and parenting them is allowed (sergey)
*/
- if (!scene || BKE_scene_base_find(scene, (Object *)id)) {
+ if (!scene) {
return 1;
}
+ else {
+ for (ViewLayer *view_layer = scene->view_layers.first;
+ view_layer;
+ view_layer = view_layer->next)
+ {
+ if (BKE_view_layer_base_find(view_layer, (Object *)id)) {
+ return 1;
+ }
+ }
+ }
+ }
+ else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ /* support adding object from different scene to collection */
+ return 1;
}
}
}
@@ -292,7 +311,9 @@ static void outliner_main_region_free(ARegion *UNUSED(ar))
}
-static void outliner_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void outliner_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -308,6 +329,7 @@ static void outliner_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(s
case ND_RENDER_OPTIONS:
case ND_SEQUENCER:
case ND_LAYER:
+ case ND_LAYER_CONTENT:
case ND_WORLD:
ED_region_tag_redraw(ar);
break;
@@ -392,6 +414,11 @@ static void outliner_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(s
if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
ED_region_tag_redraw(ar);
break;
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
}
}
@@ -414,7 +441,9 @@ static void outliner_header_region_free(ARegion *UNUSED(ar))
{
}
-static void outliner_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void outliner_header_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c
index 4228635ccd6..fb8de02d3bd 100644
--- a/source/blender/editors/space_script/space_script.c
+++ b/source/blender/editors/space_script/space_script.c
@@ -176,7 +176,9 @@ static void script_header_region_draw(const bContext *C, ARegion *ar)
ED_region_header(C, ar);
}
-static void script_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void script_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
{
/* context changes */
// XXX - Todo, need the ScriptSpace accessible to get the python script to run.
diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt
index 6dce962ee02..6b8108a1265 100644
--- a/source/blender/editors/space_sequencer/CMakeLists.txt
+++ b/source/blender/editors/space_sequencer/CMakeLists.txt
@@ -54,7 +54,7 @@ set(SRC
)
if(WITH_AUDASPACE)
- add_definitions(${AUDASPACE_DEFINITIONS})
+ add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 258cbdfaffd..0b6bacfbe68 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -69,7 +69,7 @@
#include "BKE_sound.h"
#ifdef WITH_AUDASPACE
-# include AUD_SEQUENCE_H
+# include <AUD_Sequence.h>
#endif
/* own include */
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 14661e2f44f..04dbab0b853 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -56,11 +56,12 @@
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "GPU_basic_shader.h"
#include "GPU_compositing.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#include "ED_anim_api.h"
#include "ED_gpencil.h"
@@ -194,25 +195,35 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
}
}
-static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize)
+static void drawseqwave(View2D *v2d, const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq,
+ float x1, float y1, float x2, float y2, float stepsize, unsigned int pos)
{
/*
* x1 is the starting x value to draw the wave,
* x2 the end x value, same for y1 and y2
* stepsize is width of a pixel.
*/
+
+ /* offset x1 and x2 values, to match view min/max, if strip is out of bounds */
+ int x1_offset = max_ff(v2d->cur.xmin, x1);
+ int x2_offset = min_ff(v2d->cur.xmax + 1.0f, x2);
+
if (seq->sound && ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM))) {
- int i, j, pos;
- int length = floor((x2 - x1) / stepsize) + 1;
- float ymid = (y1 + y2) / 2;
- float yscale = (y2 - y1) / 2;
+ int i, j, p;
+ int length = floor((x2_offset - x1_offset) / stepsize) + 1;
+ float ymid = (y1 + y2) / 2.0f;
+ float yscale = (y2 - y1) / 2.0f;
float samplestep;
float startsample, endsample;
float value1, value2;
bSound *sound = seq->sound;
SoundWaveform *waveform;
-
+
+ if (length < 2) {
+ return;
+ }
+
if (!sound->spinlock) {
sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
BLI_spin_init(sound->spinlock);
@@ -245,21 +256,27 @@ static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequenc
endsample = ceil((seq->startofs + seq->anim_startofs + seq->enddisp - seq->startdisp) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
samplestep = (endsample - startsample) * stepsize / (x2 - x1);
- if (length > floor((waveform->length - startsample) / samplestep))
- length = floor((waveform->length - startsample) / samplestep);
+ length = min_ii(floor((waveform->length - startsample) / samplestep), length);
+
+ if (length < 2) {
+ return;
+ }
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
- glColor4f(1.0f, 1.0f, 1.0f, 0.5);
glEnable(GL_BLEND);
- glBegin(GL_TRIANGLE_STRIP);
+
+ immBegin(GWN_PRIM_TRI_STRIP, length * 2);
+
for (i = 0; i < length; i++) {
- float sampleoffset = startsample + i * samplestep;
- pos = sampleoffset;
+ float sampleoffset = startsample + ((x1_offset - x1) / stepsize + i) * samplestep;
+ p = sampleoffset;
- value1 = waveform->data[pos * 3];
- value2 = waveform->data[pos * 3 + 1];
+ value1 = waveform->data[p * 3];
+ value2 = waveform->data[p * 3 + 1];
if (samplestep > 1.0f) {
- for (j = pos + 1; (j < waveform->length) && (j < pos + samplestep); j++) {
+ for (j = p + 1; (j < waveform->length) && (j < p + samplestep); j++) {
if (value1 > waveform->data[j * 3])
value1 = waveform->data[j * 3];
@@ -269,34 +286,20 @@ static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequenc
}
else {
/* use simple linear interpolation */
- float f = sampleoffset - pos;
- value1 = (1.0f - f) * value1 + f * waveform->data[pos * 3 + 3];
- value2 = (1.0f - f) * value2 + f * waveform->data[pos * 3 + 4];
+ float f = sampleoffset - p;
+ value1 = (1.0f - f) * value1 + f * waveform->data[p * 3 + 3];
+ value2 = (1.0f - f) * value2 + f * waveform->data[p * 3 + 4];
}
- glVertex2f(x1 + i * stepsize, ymid + value1 * yscale);
- glVertex2f(x1 + i * stepsize, ymid + value2 * yscale);
+ immVertex2f(pos, x1_offset + i * stepsize, ymid + value1 * yscale);
+ immVertex2f(pos, x1_offset + i * stepsize, ymid + value2 * yscale);
}
- glEnd();
- glDisable(GL_BLEND);
- }
-}
-static void drawmeta_stipple(int value)
-{
- if (value) {
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_HALFTONE);
-
- glEnable(GL_LINE_STIPPLE);
- glLineStipple(1, 0x8888);
- }
- else {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- glDisable(GL_LINE_STIPPLE);
+ immEnd();
+
+ glDisable(GL_BLEND);
}
}
-
static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, float x2, float y2)
{
/* note: this used to use SEQ_BEGIN/SEQ_END, but it messes up the
@@ -329,9 +332,6 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- if (seqm->flag & SEQ_MUTE)
- drawmeta_stipple(1);
-
for (seq = seqbase->first; seq; seq = seq->next) {
chan_min = min_ii(chan_min, seq->machine);
chan_max = max_ii(chan_max, seq->machine);
@@ -342,6 +342,10 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
col[3] = 196; /* alpha, used for all meta children */
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
for (seq = seqbase->first; seq; seq = seq->next) {
const int startdisp = seq->startdisp + offset;
const int enddisp = seq->enddisp + offset;
@@ -352,12 +356,16 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
float x2_chan = enddisp;
float y1_chan, y2_chan;
- if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE))
- drawmeta_stipple(1);
-
color3ubv_from_seq(scene, seq, col);
- glColor4ubv(col);
+ if ((seqm->flag & SEQ_MUTE) || (seq->flag & SEQ_MUTE)) {
+ col[3] = 64;
+ }
+ else {
+ col[3] = 196;
+ }
+
+ immUniformColor4ubv(col);
/* clamp within parent sequence strip bounds */
if (x1_chan < x1) x1_chan = x1;
@@ -366,20 +374,12 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
y1_chan = y1 + y_chan + (draw_height * SEQ_STRIP_OFSBOTTOM);
y2_chan = y1 + y_chan + (draw_height * SEQ_STRIP_OFSTOP);
- glRectf(x1_chan, y1_chan, x2_chan, y2_chan);
-
- UI_GetColorPtrShade3ubv(col, col, -30);
- glColor4ubv(col);
- fdrawbox(x1_chan, y1_chan, x2_chan, y2_chan);
-
- if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE))
- drawmeta_stipple(0);
+ immRectf(pos, x1_chan, y1_chan, x2_chan, y2_chan);
}
}
- if (seqm->flag & SEQ_MUTE)
- drawmeta_stipple(0);
-
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
@@ -395,7 +395,7 @@ static float draw_seq_handle_size_get_clamped(Sequence *seq, const float pixelx)
}
/* draw a handle, for each end of a sequence strip */
-static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_clamped, const short direction)
+static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_clamped, const short direction, unsigned int pos)
{
float v1[2], v2[2], v3[2], rx1 = 0, rx2 = 0; //for triangles and rect
float x1, x2, y1, y2;
@@ -437,21 +437,31 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- if (seq->flag & whichsel) glColor4ub(0, 0, 0, 80);
- else if (seq->flag & SELECT) glColor4ub(255, 255, 255, 30);
- else glColor4ub(0, 0, 0, 22);
-
- glRectf(rx1, y1, rx2, y2);
-
- if (seq->flag & whichsel) glColor4ub(255, 255, 255, 200);
- else glColor4ub(0, 0, 0, 50);
+ if (seq->flag & whichsel) {
+ immUniformColor4ub(0, 0, 0, 80);
+ }
+ else if (seq->flag & SELECT) {
+ immUniformColor4ub(255, 255, 255, 30);
+ }
+ else {
+ immUniformColor4ub(0, 0, 0, 22);
+ }
- glEnable(GL_POLYGON_SMOOTH);
- glBegin(GL_TRIANGLES);
- glVertex2fv(v1); glVertex2fv(v2); glVertex2fv(v3);
- glEnd();
+ immRectf(pos, rx1, y1, rx2, y2);
- glDisable(GL_POLYGON_SMOOTH);
+ if (seq->flag & whichsel) {
+ immUniformColor4ub(255, 255, 255, 200);
+ }
+ else {
+ immUniformColor4ub(0, 0, 0, 50);
+ }
+
+ immBegin(GWN_PRIM_TRIS, 3);
+ immVertex2fv(pos, v1);
+ immVertex2fv(pos, v2);
+ immVertex2fv(pos, v3);
+ immEnd();
+
glDisable(GL_BLEND);
}
@@ -590,67 +600,10 @@ static void draw_seq_text(View2D *v2d, SpaceSeq *sseq, Sequence *seq, float x1,
UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col);
}
-/* draws a shaded strip, made from gradient + flat color + gradient */
-void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2)
+static void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq, unsigned int pos)
{
- float ymid1, ymid2;
-
- if (seq->flag & SEQ_MUTE) {
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_HALFTONE);
- }
-
- ymid1 = (y2 - y1) * 0.25f + y1;
- ymid2 = (y2 - y1) * 0.65f + y1;
-
- glBegin(GL_QUADS);
-
- if (seq->flag & SEQ_INVALID_EFFECT) { col[0] = 255; col[1] = 0; col[2] = 255; }
- else if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, -50);
- /* else UI_GetColorPtrShade3ubv(col, col, 0); */ /* DO NOTHING */
-
- glColor3ubv(col);
-
- glVertex2f(x1, y1);
- glVertex2f(x2, y1);
-
- if (seq->flag & SEQ_INVALID_EFFECT) { col[0] = 255; col[1] = 0; col[2] = 255; }
- else if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 5);
- else UI_GetColorPtrShade3ubv(col, col, -5);
-
- glColor3ubv((GLubyte *)col);
-
- glVertex2f(x2, ymid1);
- glVertex2f(x1, ymid1);
-
- glEnd();
-
- glRectf(x1, ymid1, x2, ymid2);
-
- glBegin(GL_QUADS);
-
- glVertex2f(x1, ymid2);
- glVertex2f(x2, ymid2);
-
- if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, -15);
- else UI_GetColorPtrShade3ubv(col, col, 25);
-
- glColor3ubv((GLubyte *)col);
-
- glVertex2f(x2, y2);
- glVertex2f(x1, y2);
-
- glEnd();
-
- if (seq->flag & SEQ_MUTE) {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- }
-}
-
-void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq)
-{
- float x1, x2, y1, y2, pixely, a;
- unsigned char col[3], blendcol[3];
+ float x1, x2, y1, y2, pixely;
+ unsigned char col[4], blendcol[3];
View2D *v2d = &ar->v2d;
x1 = seq->startdisp;
@@ -664,90 +617,82 @@ void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq)
if (pixely <= 0) return; /* can happen when the view is split/resized */
blendcol[0] = blendcol[1] = blendcol[2] = 120;
-
- if (seq->startofs) {
+
+ if (seq->startofs || seq->endofs) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
color3ubv_from_seq(scene, seq, col);
-
+
if (seq->flag & SELECT) {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
- glColor4ub(col[0], col[1], col[2], 170);
+ UI_GetColorPtrShade3ubv(col, col, -50);
+ }
+
+ if (seq->flag & SEQ_MUTE) {
+ col[3] = 64;
}
else {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
- glColor4ub(col[0], col[1], col[2], 110);
+ if (seq->flag & SELECT) {
+ col[3] = 170;
+ }
+ else {
+ col[3] = 80;
+ }
}
-
- glRectf((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
-
- if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
- else glColor4ub(col[0], col[1], col[2], 160);
-
- fdrawbox((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); //outline
-
- glDisable(GL_BLEND);
+ }
+
+ if (seq->startofs) {
+ immUniformColor4ubv(col);
+ immRectf(pos, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
+
+ immUniformColor3ubvAlpha(col, col[3] + 50);
+
+ imm_draw_box_wire_2d(pos, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); /* outline */
}
if (seq->endofs) {
+ immUniformColor4ubv(col);
+ immRectf(pos, x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
+
+ immUniformColor3ubvAlpha(col, col[3] + 50);
+
+ imm_draw_box_wire_2d(pos, x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); /* outline */
+ }
+
+ if (seq->startofs || seq->endofs) {
+ glDisable(GL_BLEND);
+ }
+
+ if (seq->startstill || seq->endstill) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
+
color3ubv_from_seq(scene, seq, col);
-
- if (seq->flag & SELECT) {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
- glColor4ub(col[0], col[1], col[2], 170);
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5f, 60);
+
+ if (seq->flag & SEQ_MUTE) {
+ col[3] = 96;
}
else {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
- glColor4ub(col[0], col[1], col[2], 110);
+ if (seq->flag & SELECT) {
+ col[3] = 255;
+ }
+ else {
+ col[3] = 170;
+ }
}
-
- glRectf(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
-
- if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
- else glColor4ub(col[0], col[1], col[2], 160);
-
- fdrawbox(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); //outline
-
- glDisable(GL_BLEND);
+
+ immUniformColor4ubv(col);
}
+
if (seq->startstill) {
- color3ubv_from_seq(scene, seq, col);
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
- glColor3ubv((GLubyte *)col);
-
- draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
-
- /* feint pinstripes, helps see exactly which is extended and which isn't,
- * especially when the extension is very small */
- if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
- else UI_GetColorPtrShade3ubv(col, col, -16);
-
- glColor3ubv((GLubyte *)col);
-
- for (a = y1; a < y2; a += pixely * 2.0f) {
- fdrawline(x1, a, (float)(seq->start), a);
- }
+ immRectf(pos, x1, y1, (float)(seq->start), y2);
}
if (seq->endstill) {
- color3ubv_from_seq(scene, seq, col);
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
- glColor3ubv((GLubyte *)col);
-
- draw_shadedstrip(seq, col, (float)(seq->start + seq->len), y1, x2, y2);
-
- /* feint pinstripes, helps see exactly which is extended and which isn't,
- * especially when the extension is very small */
- if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, 24);
- else UI_GetColorPtrShade3ubv(col, col, -16);
-
- glColor3ubv((GLubyte *)col);
-
- for (a = y1; a < y2; a += pixely * 2.0f) {
- fdrawline((float)(seq->start + seq->len), a, x2, a);
- }
+ immRectf(pos, (float)(seq->start + seq->len), y1, x2, y2);
+ }
+
+ if (seq->startstill || seq->endstill) {
+ glDisable(GL_BLEND);
}
}
@@ -761,7 +706,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;
+ unsigned char col[4], background_col[4], is_single_image;
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 */
@@ -773,72 +718,105 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
x2 = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
y2 = seq->machine + SEQ_STRIP_OFSTOP;
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* get the correct color per strip type*/
//color3ubv_from_seq(scene, seq, col);
color3ubv_from_seq(scene, seq, background_col);
-
+
+ if (seq->flag & SEQ_MUTE) {
+ background_col[3] = 128;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ background_col[3] = 255;
+ }
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrShade3ubv(background_col, background_col, -50);
+ }
+
+ immUniformColor4ubv(background_col);
+
/* draw the main strip body */
if (is_single_image) { /* single image */
- draw_shadedstrip(seq, background_col,
- BKE_sequence_tx_get_final_left(seq, false), y1,
- BKE_sequence_tx_get_final_right(seq, false), y2);
+ immRectf(pos, BKE_sequence_tx_get_final_left(seq, false), y1,
+ BKE_sequence_tx_get_final_right(seq, false), y2);
}
else { /* normal operation */
- draw_shadedstrip(seq, background_col, x1, y1, x2, y2);
+ immRectf(pos, x1, y1, x2, y2);
+ }
+
+ if (seq->flag & SEQ_MUTE) {
+ glDisable(GL_BLEND);
}
if (!is_single_image) {
if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) {
- draw_sequence_extensions(scene, ar, seq);
+ draw_sequence_extensions(scene, ar, seq, pos);
}
}
- draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE);
- draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE);
-
- /* draw the strip outline */
+ draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE, pos);
+ draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE, pos);
+
x1 = seq->startdisp;
x2 = seq->enddisp;
/* draw sound wave */
if (seq->type == SEQ_TYPE_SOUND_RAM) {
if (!(sseq->flag & SEQ_NO_WAVEFORMS)) {
- drawseqwave(C, sseq, scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
+ drawseqwave(v2d, C, sseq, scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx, pos);
}
}
+ immUnbindProgram();
+
/* draw lock */
if (seq->flag & SEQ_LOCK) {
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
glEnable(GL_BLEND);
- /* light stripes */
- glColor4ub(255, 255, 255, 32);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_DIAG_STRIPES);
- glRectf(x1, y1, x2, y2);
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
+
+ immUniform4f("color1", 1.0f, 1.0f, 1.0f, 0.125f);
+ immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.125f);
+ immUniform1i("size1", 8);
+ immUniform1i("size2", 8);
+
+ immRectf(pos, x1, y1, x2, y2);
- /* dark stripes */
- glColor4ub(0, 0, 0, 32);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP);
- glRectf(x1, y1, x2, y2);
+ immUnbindProgram();
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
glDisable(GL_BLEND);
}
if (!BKE_sequence_is_valid_check(seq)) {
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
+ glEnable(GL_BLEND);
+
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
+
+ immUniform4f("color1", 1.0f, 0.0f, 0.0f, 1.0f);
+ immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.0f);
+ immUniform1i("size1", 8);
+ immUniform1i("size2", 8);
- /* panic! */
- glColor4ub(255, 0, 0, 255);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_DIAG_STRIPES);
- glRectf(x1, y1, x2, y2);
+ immRectf(pos, x1, y1, x2, y2);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immUnbindProgram();
+
+ glDisable(GL_BLEND);
}
color3ubv_from_seq(scene, seq, col);
+
+ /* draw the strip outline */
+ color3ubv_from_seq(scene, seq, col);
if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT)) {
if (seq->flag & SEQ_OVERLAP) {
col[0] = 255; col[1] = col[2] = 40;
@@ -855,19 +833,27 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
drawmeta_contents(scene, seq, x1, y1, x2, y2);
}
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ /* TODO: add back stippled line for muted strips? */
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
if (seq->flag & SEQ_MUTE) {
- glEnable(GL_LINE_STIPPLE);
- glLineStipple(1, 0x8888);
+ col[3] = 96;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ immUniformColor4ubv(col);
}
-
- glColor3ubv((GLubyte *)col);
-
- UI_draw_roundbox_shade_x(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0);
-
- if (seq->flag & SEQ_MUTE) {
- glDisable(GL_LINE_STIPPLE);
+ else {
+ immUniformColor3ubv(col);
}
-
+
+ imm_draw_box_wire_2d(pos, x1, y1, x2, y2); /* outline */
+
+ immUnbindProgram();
+
/* calculate if seq is long enough to print a name */
x1 = seq->startdisp + handsize_clamped;
x2 = seq->enddisp - handsize_clamped;
@@ -1057,33 +1043,39 @@ static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, cons
glLineWidth(1.0f);
/* border */
- setlinestyle(3);
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- glBegin(GL_LINE_LOOP);
- glVertex2f(x1 - 0.5f, y1 - 0.5f);
- glVertex2f(x1 - 0.5f, y2 + 0.5f);
- glVertex2f(x2 + 0.5f, y2 + 0.5f);
- glVertex2f(x2 + 0.5f, y1 - 0.5f);
- glEnd();
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniformThemeColor(TH_BACK);
+ immUniform1i("num_colors", 0); /* Simple dashes. */
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ imm_draw_box_wire_2d(shdr_pos, x1 - 0.5f, y1 - 0.5f, x2 + 0.5f, y2 + 0.5f);
/* safety border */
if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) {
+ immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f);
+
UI_draw_safe_areas(
- x1, x2, y1, y2,
+ shdr_pos, x1, x2, y1, y2,
scene->safe_areas.title,
scene->safe_areas.action);
if (sseq->flag & SEQ_SHOW_SAFE_CENTER) {
UI_draw_safe_areas(
- x1, x2, y1, y2,
+ shdr_pos, x1, x2, y1, y2,
scene->safe_areas.title_center,
scene->safe_areas.action_center);
}
}
- setlinestyle(0);
+ immUnbindProgram();
}
/* draws checkerboard background for transparent content */
@@ -1098,11 +1090,7 @@ static void sequencer_draw_background(
/* only draw alpha for main buffer */
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
if ((sseq->flag & SEQ_USE_ALPHA) && !draw_overlay) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
- glColor4f(1.0, 1.0, 1.0, 1.0);
+ imm_draw_box_checker_2d(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
}
}
}
@@ -1144,9 +1132,6 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glClear(GL_COLOR_BUFFER_BIT);
}
- /* without this colors can flicker from previous opengl state */
- glColor4ub(255, 255, 255, 255);
-
/* only initialize the preview if a render is in progress */
if (G.is_rendering)
return;
@@ -1161,15 +1146,16 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if ((ibuf == NULL) ||
(ibuf->rect == NULL && ibuf->rect_float == NULL))
{
- /* gpencil can also be drawn without a valid imbuf */
- if ((draw_gpencil && is_imbuf) && !draw_overlay) {
- sequencer_display_size(scene, sseq, viewrect);
+ sequencer_display_size(scene, sseq, viewrect);
- sequencer_draw_background(sseq, v2d, viewrect, false);
- sequencer_draw_borders(sseq, v2d, scene);
+ sequencer_draw_background(sseq, v2d, viewrect, false);
+ sequencer_draw_borders(sseq, v2d, scene);
+ /* gpencil can also be drawn without a valid imbuf */
+ if ((draw_gpencil && is_imbuf) && !draw_overlay) {
sequencer_draw_gpencil(C);
}
+
return;
}
@@ -1238,6 +1224,18 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
sequencer_draw_background(sseq, v2d, viewrect, draw_overlay);
}
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ /* Format needs to be created prior to any immBindProgram call.
+ * Do it here because OCIO binds it's own shader.
+ */
+ Gwn_VertFormat *imm_format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(imm_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int texCoord = GWN_vertformat_attr_add(imm_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
if (scope) {
IMB_freeImBuf(ibuf);
ibuf = scope;
@@ -1310,9 +1308,12 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
}
- glColor4f(1.0, 1.0, 1.0, 1.0);
+ if (draw_backdrop) {
+ /* XXX: need to load identity projection too? */
+ gpuPushMatrix();
+ gpuLoadIdentity();
+ }
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
glGenTextures(1, (GLuint *)&texid);
glBindTexture(GL_TEXTURE_2D, texid);
@@ -1325,15 +1326,13 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);
- if (draw_backdrop) {
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
+ if (!glsl_used) {
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ immUniform1i("image", GL_TEXTURE0);
}
- glBegin(GL_QUADS);
+
+ immBegin(GWN_PRIM_TRI_FAN, 4);
if (draw_overlay) {
if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
@@ -1343,16 +1342,30 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
tot_clip.xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax);
tot_clip.ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax);
- glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin);
- glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax);
- glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmax, tot_clip.ymax);
- glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmax, tot_clip.ymin);
+ immAttrib2f(texCoord, scene->ed->over_border.xmin, scene->ed->over_border.ymin);
+ immVertex2f(pos, tot_clip.xmin, tot_clip.ymin);
+
+ immAttrib2f(texCoord, scene->ed->over_border.xmin, scene->ed->over_border.ymax);
+ immVertex2f(pos, tot_clip.xmin, tot_clip.ymax);
+
+ immAttrib2f(texCoord, scene->ed->over_border.xmax, scene->ed->over_border.ymax);
+ immVertex2f(pos, tot_clip.xmax, tot_clip.ymax);
+
+ immAttrib2f(texCoord, scene->ed->over_border.xmax, scene->ed->over_border.ymin);
+ immVertex2f(pos, tot_clip.xmax, tot_clip.ymin);
}
else if (sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
- glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
- glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
- glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymin);
+
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymax);
+
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymax);
+
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymin);
}
}
else if (draw_backdrop) {
@@ -1371,25 +1384,46 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
imagey = aspect / image_aspect;
}
- glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey);
- glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey);
- glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, -imagex, -imagey);
+
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, -imagex, imagey);
+
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, imagex, imagey);
+
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, imagex, -imagey);
}
else {
draw_metadata = ((sseq->flag & SEQ_SHOW_METADATA) != 0);
- glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
- glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
- glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymin);
+
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymax);
+
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymax);
+
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymin);
}
- glEnd();
+
+ immEnd();
glBindTexture(GL_TEXTURE_2D, 0);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
+
+ if (!glsl_used) {
+ immUnbindProgram();
+ }
+
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
glDisable(GL_BLEND);
+ }
+
glDeleteTextures(1, &texid);
if (glsl_used)
@@ -1406,10 +1440,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
if (draw_backdrop) {
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
+ gpuPopMatrix();
return;
}
@@ -1483,42 +1514,42 @@ void drawprefetchseqspace(Scene *scene, ARegion *UNUSED(ar), SpaceSeq *sseq)
static void draw_seq_backdrop(View2D *v2d)
{
int i;
-
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* darker gray overlay over the view backdrop */
- UI_ThemeColorShade(TH_BACK, -20);
- glRectf(v2d->cur.xmin, -1.0, v2d->cur.xmax, 1.0);
+ immUniformThemeColorShade(TH_BACK, -20);
+ immRectf(pos, v2d->cur.xmin, -1.0, v2d->cur.xmax, 1.0);
/* Alternating horizontal stripes */
i = max_ii(1, ((int)v2d->cur.ymin) - 1);
- glBegin(GL_QUADS);
while (i < v2d->cur.ymax) {
- if (((int)i) & 1)
- UI_ThemeColorShade(TH_BACK, -15);
- else
- UI_ThemeColorShade(TH_BACK, -25);
-
- glVertex2f(v2d->cur.xmax, i);
- glVertex2f(v2d->cur.xmin, i);
- glVertex2f(v2d->cur.xmin, i + 1);
- glVertex2f(v2d->cur.xmax, i + 1);
+ if (i & 1) {
+ immUniformThemeColorShade(TH_BACK, -15);
+ }
+ else {
+ immUniformThemeColorShade(TH_BACK, -25);
+ }
+
+ immRectf(pos, v2d->cur.xmin, i, v2d->cur.xmax, i + 1);
- i += 1.0;
+ i++;
}
- glEnd();
-
+
/* Darker lines separating the horizontal bands */
i = max_ii(1, ((int)v2d->cur.ymin) - 1);
- UI_ThemeColor(TH_GRID);
-
- glBegin(GL_LINES);
- while (i < v2d->cur.ymax) {
- glVertex2f(v2d->cur.xmax, i);
- glVertex2f(v2d->cur.xmin, i);
-
- i += 1.0;
+ int line_ct = (int)v2d->cur.ymax - i + 1;
+ immUniformThemeColor(TH_GRID);
+ immBegin(GWN_PRIM_LINES, line_ct * 2);
+ while (line_ct--) {
+ immVertex2f(pos, v2d->cur.xmax, i);
+ immVertex2f(pos, v2d->cur.xmin, i);
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
/* draw the contents of the sequencer strips view */
@@ -1534,7 +1565,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
/* loop through twice, first unselected, then selected */
for (j = 0; j < 2; j++) {
Sequence *seq;
- int outline_tint = (j) ? -60 : -150; /* highlighting around strip edges indicating selection */
+ int outline_tint = (j) ? 40 : -40; /* highlighting around strip edges indicating selection */
/* loop through strips, checking for those that are visible */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
@@ -1562,8 +1593,15 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
if (special_seq_update) {
const Sequence *seq = special_seq_update;
glEnable(GL_BLEND);
- glColor4ub(255, 255, 255, 48);
- glRectf(seq->startdisp, seq->machine + SEQ_STRIP_OFSBOTTOM, seq->enddisp, seq->machine + SEQ_STRIP_OFSTOP);
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4ub(255, 255, 255, 48);
+ immRectf(pos, seq->startdisp, seq->machine + SEQ_STRIP_OFSBOTTOM, seq->enddisp, seq->machine + SEQ_STRIP_OFSTOP);
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
}
@@ -1575,36 +1613,56 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
const int frame_end = PEFRA + 1;
glEnable(GL_BLEND);
-
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* draw darkened area outside of active timeline
* frame range used is preview range or scene range */
- UI_ThemeColorShadeAlpha(TH_BACK, -25, -100);
+ immUniformThemeColorShadeAlpha(TH_BACK, -25, -100);
if (frame_sta < frame_end) {
- glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)frame_sta, v2d->cur.ymax);
- glRectf((float)frame_end, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)frame_sta, v2d->cur.ymax);
+ immRectf(pos, (float)frame_end, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
else {
- glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
- UI_ThemeColorShade(TH_BACK, -60);
+ immUniformThemeColorShade(TH_BACK, -60);
+
/* thin lines where the actual frames are */
- fdrawline(frame_sta, v2d->cur.ymin, frame_sta, v2d->cur.ymax);
- fdrawline(frame_end, v2d->cur.ymin, frame_end, v2d->cur.ymax);
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, frame_sta, v2d->cur.ymin);
+ immVertex2f(pos, frame_sta, v2d->cur.ymax);
+
+ immVertex2f(pos, frame_end, v2d->cur.ymin);
+ immVertex2f(pos, frame_end, v2d->cur.ymax);
+
+ immEnd();
if (ed && !BLI_listbase_is_empty(&ed->metastack)) {
MetaStack *ms = ed->metastack.last;
- glColor4ub(255, 255, 255, 8);
- glRectf(ms->disp_range[0], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax);
+ immUniformColor4ub(255, 255, 255, 8);
+ immRectf(pos, ms->disp_range[0], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax);
+
+ immUniformThemeColorShade(TH_BACK, -40);
- UI_ThemeColorShade(TH_BACK, -40);
+ immBegin(GWN_PRIM_LINES, 4);
- fdrawline(ms->disp_range[0], v2d->cur.ymin, ms->disp_range[0], v2d->cur.ymax);
- fdrawline(ms->disp_range[1], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax);
+ immVertex2f(pos, ms->disp_range[0], v2d->cur.ymin);
+ immVertex2f(pos, ms->disp_range[0], v2d->cur.ymax);
+
+ immVertex2f(pos, ms->disp_range[1], v2d->cur.ymin);
+ immVertex2f(pos, ms->disp_range[1], v2d->cur.ymax);
+
+ immEnd();
}
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
@@ -1678,16 +1736,20 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
/* overlap playhead */
if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) {
int cfra_over = (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) ? scene->ed->over_cfra : scene->r.cfra + scene->ed->over_ofs;
- glColor3f(0.2, 0.2, 0.2);
- // glRectf(cfra_over, v2d->cur.ymin, scene->ed->over_ofs + scene->r.cfra + 1, v2d->cur.ymax);
- glBegin(GL_LINES);
- glVertex2f(cfra_over, v2d->cur.ymin);
- glVertex2f(cfra_over, v2d->cur.ymax);
- glEnd();
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(0.2f, 0.2f, 0.2f);
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, cfra_over, v2d->cur.ymin);
+ immVertex2f(pos, cfra_over, v2d->cur.ymax);
+ immEnd();
+
+ immUnbindProgram();
}
-
+
/* callback */
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index f0d14825bb2..8f6eb064b0d 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -1265,7 +1265,6 @@ typedef struct SlipData {
int num_seq;
bool slow;
int slow_offset; /* offset at the point where offset was turned on */
- void *draw_handle;
NumInput num_input;
} SlipData;
@@ -1300,21 +1299,6 @@ static void transseq_restore(TransSeq *ts, Sequence *seq)
seq->len = ts->len;
}
-static void draw_slip_extensions(const bContext *C, ARegion *ar, void *data)
-{
- Scene *scene = CTX_data_scene(C);
- SlipData *td = data;
- int i;
-
- for (i = 0; i < td->num_seq; i++) {
- Sequence *seq = td->seq_array[i];
-
- if ((seq->type != SEQ_TYPE_META) && td->trim[i]) {
- draw_sequence_extensions(scene, ar, seq);
- }
- }
-}
-
static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
{
Sequence *seq;
@@ -1363,7 +1347,6 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
SlipData *data;
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
- ARegion *ar = CTX_wm_region(C);
float mouseloc[2];
int num_seq, i;
View2D *v2d = UI_view2d_fromcontext(C);
@@ -1393,8 +1376,6 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
transseq_backup(data->ts + i, data->seq_array[i]);
}
- data->draw_handle = ED_region_draw_cb_activate(ar->type, draw_slip_extensions, data, REGION_DRAW_POST_VIEW);
-
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
copy_v2_v2_int(data->init_mouse, event->mval);
@@ -1536,7 +1517,6 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
Scene *scene = CTX_data_scene(C);
SlipData *data = (SlipData *)op->customdata;
ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
const bool has_numInput = hasNumInput(&data->num_input);
bool handled = true;
@@ -1594,7 +1574,6 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
case RETKEY:
case SPACEKEY:
{
- ED_region_draw_cb_exit(ar->type, data->draw_handle);
MEM_freeN(data->seq_array);
MEM_freeN(data->trim);
MEM_freeN(data->ts);
@@ -1623,8 +1602,6 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
BKE_sequence_calc(scene, seq);
}
- ED_region_draw_cb_exit(ar->type, data->draw_handle);
-
MEM_freeN(data->seq_array);
MEM_freeN(data->ts);
MEM_freeN(data->trim);
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 730cc117287..7ce2f73cbef 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -56,8 +56,6 @@ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
void draw_timeline_seq(const struct bContext *C, struct ARegion *ar);
void draw_image_seq(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay, bool draw_backdrop);
void color3ubv_from_seq(struct Scene *curscene, struct Sequence *seq, unsigned char col[3]);
-void draw_shadedstrip(struct Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2);
-void draw_sequence_extensions(struct Scene *scene, struct ARegion *ar, struct Sequence *seq);
void sequencer_special_update_set(Sequence *seq);
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 6b50d3fecdf..23387f291e6 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -344,7 +344,9 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl)
return (SpaceLink *)sseqn;
}
-static void sequencer_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
+static void sequencer_listener(
+ bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
+ WorkSpace *UNUSED(workspace))
{
/* context changes */
switch (wmn->category) {
@@ -498,7 +500,9 @@ static void sequencer_main_region_draw(const bContext *C, ARegion *ar)
draw_timeline_seq(C, ar);
}
-static void sequencer_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void sequencer_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -604,7 +608,9 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *ar)
}
}
-static void sequencer_preview_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void sequencer_preview_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -670,7 +676,9 @@ static void sequencer_buttons_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, NULL, -1, true);
}
-static void sequencer_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void sequencer_buttons_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index fcb46ced750..539fe1c53bd 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -125,7 +125,8 @@ static SpaceLink *text_duplicate(SpaceLink *sl)
return (SpaceLink *)stextn;
}
-static void text_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
+static void text_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
+ WorkSpace *UNUSED(workspace))
{
SpaceText *st = sa->spacedata.first;
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 70b5feac280..fcb675abcf2 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -49,6 +49,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -123,38 +125,38 @@ static void txt_format_text(SpaceText *st)
#endif
/* Sets the current drawing color based on the format character specified */
-static void format_draw_color(char formatchar)
+static void format_draw_color(const TextDrawContext *tdc, char formatchar)
{
switch (formatchar) {
case FMT_TYPE_WHITESPACE:
break;
case FMT_TYPE_SYMBOL:
- UI_ThemeColor(TH_SYNTAX_S);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_S);
break;
case FMT_TYPE_COMMENT:
- UI_ThemeColor(TH_SYNTAX_C);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_C);
break;
case FMT_TYPE_NUMERAL:
- UI_ThemeColor(TH_SYNTAX_N);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_N);
break;
case FMT_TYPE_STRING:
- UI_ThemeColor(TH_SYNTAX_L);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_L);
break;
case FMT_TYPE_DIRECTIVE:
- UI_ThemeColor(TH_SYNTAX_D);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_D);
break;
case FMT_TYPE_SPECIAL:
- UI_ThemeColor(TH_SYNTAX_V);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_V);
break;
case FMT_TYPE_RESERVED:
- UI_ThemeColor(TH_SYNTAX_R);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_R);
break;
case FMT_TYPE_KEYWORD:
- UI_ThemeColor(TH_SYNTAX_B);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_B);
break;
case FMT_TYPE_DEFAULT:
default:
- UI_ThemeColor(TH_TEXT);
+ UI_FontThemeColor(tdc->font_id, TH_TEXT);
break;
}
}
@@ -429,7 +431,7 @@ static int text_draw_wrapped(
/* Draw the visible portion of text on the overshot line */
for (a = fstart, ma = mstart; ma < mend; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
if (use_syntax) {
- if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
+ if (fmt_prev != format[a]) format_draw_color(tdc, fmt_prev = format[a]);
}
x += text_font_draw_character_utf8(tdc, x, y, str + ma);
fpos++;
@@ -452,7 +454,7 @@ static int text_draw_wrapped(
/* Draw the remaining text */
for (a = fstart, ma = mstart; str[ma] && y > clip_min_y; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
if (use_syntax) {
- if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
+ if (fmt_prev != format[a]) format_draw_color(tdc, fmt_prev = format[a]);
}
x += text_font_draw_character_utf8(tdc, x, y, str + ma);
@@ -505,7 +507,7 @@ static void text_draw(
char fmt_prev = 0xff;
for (a = 0; a < amount; a++) {
- if (format[a] != fmt_prev) format_draw_color(fmt_prev = format[a]);
+ if (format[a] != fmt_prev) format_draw_color(tdc, fmt_prev = format[a]);
x += text_font_draw_character_utf8(tdc, x, y, in + str_shift);
str_shift += BLI_str_utf8_size_safe(in + str_shift);
}
@@ -906,22 +908,23 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
{
bTheme *btheme = UI_GetTheme();
uiWidgetColors wcol = btheme->tui.wcol_scroll;
- unsigned char col[4];
+ float col[4];
float rad;
-
- UI_ThemeColor(TH_BACK);
- glRecti(back->xmin, back->ymin, back->xmax, back->ymax);
+
+ /* background so highlights don't go behind the scrollbar */
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_BACK);
+ immRecti(pos, back->xmin, back->ymin, back->xmax, back->ymax);
+ immUnbindProgram();
UI_draw_widget_scroll(&wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT) ? UI_SCROLL_PRESSED : 0);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
rad = 0.4f * min_ii(BLI_rcti_size_x(&st->txtscroll), BLI_rcti_size_y(&st->txtscroll));
- UI_GetThemeColor3ubv(TH_HILITE, col);
- col[3] = 48;
- glColor4ubv(col);
- glEnable(GL_BLEND);
- UI_draw_roundbox(st->txtscroll.xmin + 1, st->txtscroll.ymin, st->txtscroll.xmax - 1, st->txtscroll.ymax, rad);
- glDisable(GL_BLEND);
+ UI_GetThemeColor3fv(TH_HILITE, col);
+ col[3] = 0.18f;
+ UI_draw_roundbox_aa(true, st->txtscroll.xmin + 1, st->txtscroll.ymin, st->txtscroll.xmax - 1, st->txtscroll.ymax, rad, col);
}
/*********************** draw documentation *******************************/
@@ -963,26 +966,32 @@ static void draw_documentation(const SpaceText *st, ARegion *ar)
boxh = (DOC_HEIGHT + 1) * (st->lheight_dpi + TXT_LINE_SPACING);
/* Draw panel */
- UI_ThemeColor(TH_BACK);
- glRecti(x, y, x + boxw, y - boxh);
- UI_ThemeColor(TH_SHADE1);
- glBegin(GL_LINE_LOOP);
- glVertex2i(x, y);
- glVertex2i(x + boxw, y);
- glVertex2i(x + boxw, y - boxh);
- glVertex2i(x, y - boxh);
- glEnd();
- glBegin(GL_LINE_LOOP);
- glVertex2i(x + boxw - 10, y - 7);
- glVertex2i(x + boxw - 4, y - 7);
- glVertex2i(x + boxw - 7, y - 2);
- glEnd();
- glBegin(GL_LINE_LOOP);
- glVertex2i(x + boxw - 10, y - boxh + 7);
- glVertex2i(x + boxw - 4, y - boxh + 7);
- glVertex2i(x + boxw - 7, y - boxh + 2);
- glEnd();
- UI_ThemeColor(TH_TEXT);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_BACK);
+ immRecti(pos, x, y, x + boxw, y - boxh);
+ immUniformThemeColor(TH_SHADE1);
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex2i(pos, x, y);
+ immVertex2i(pos, x + boxw, y);
+ immVertex2i(pos, x + boxw, y - boxh);
+ immVertex2i(pos, x, y - boxh);
+ immEnd();
+ immBegin(GWN_PRIM_LINE_LOOP, 3);
+ immVertex2i(pos, x + boxw - 10, y - 7);
+ immVertex2i(pos, x + boxw - 4, y - 7);
+ immVertex2i(pos, x + boxw - 7, y - 2);
+ immEnd();
+ immBegin(GWN_PRIM_LINE_LOOP, 3);
+ immVertex2i(pos, x + boxw - 10, y - boxh + 7);
+ immVertex2i(pos, x + boxw - 4, y - boxh + 7);
+ immVertex2i(pos, x + boxw - 7, y - boxh + 2);
+ immEnd();
+
+ immUnbindProgram();
+
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
i = 0; br = DOC_WIDTH; lines = 0; // XXX -doc_scroll;
for (p = docs; *p; p++) {
@@ -1009,11 +1018,6 @@ static void draw_documentation(const SpaceText *st, ARegion *ar)
}
if (lines >= DOC_HEIGHT) break;
}
-
- if (0 /* XXX doc_scroll*/ /* > 0 && lines < DOC_HEIGHT */) {
- // XXX doc_scroll--;
- draw_documentation(st, ar);
- }
}
#endif
@@ -1061,10 +1065,15 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
/* not needed but stands out nicer */
UI_draw_box_shadow(220, x, y - boxh, x + boxw, y);
- UI_ThemeColor(TH_SHADE1);
- glRecti(x - 1, y + 1, x + boxw + 1, y - boxh - 1);
- UI_ThemeColorShade(TH_BACK, 16);
- glRecti(x, y, x + boxw, y - boxh);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_SHADE1);
+ immRecti(pos, x - 1, y + 1, x + boxw + 1, y - boxh - 1);
+ immUniformThemeColorShade(TH_BACK, 16);
+ immRecti(pos, x, y, x + boxw, y - boxh);
+
+ immUnbindProgram();
/* Set the top 'item' of the visible list */
for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
@@ -1079,11 +1088,16 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
w = st->cwidth * text_get_char_pos(st, str, len);
if (item == sel) {
- UI_ThemeColor(TH_SHADE2);
- glRecti(x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
+ unsigned int posi = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_SHADE2);
+ immRecti(posi, x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
+
+ immUnbindProgram();
}
- format_draw_color(item->type);
+ format_draw_color(tdc, item->type);
text_draw(st, tdc, str, 0, 0, x + margin_x, y - 1, NULL);
if (item == last) break;
@@ -1092,42 +1106,57 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
/*********************** draw cursor ************************/
-static void draw_cursor(SpaceText *st, ARegion *ar)
+static void draw_text_decoration(SpaceText *st, ARegion *ar)
{
Text *text = st->text;
int vcurl, vcurc, vsell, vselc, hidden = 0;
int x, y, w, i;
+ int offl, offc;
const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
+ /* Convert to view space character coordinates to determine if cursor is hidden */
+ wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
+ vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl;
+ vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc;
+
+ if (vselc < 0) {
+ vselc = 0;
+ hidden = 1;
+ }
+
+ if (text->curl == text->sell && text->curc == text->selc && !st->line_hlight && hidden) {
+ /* Nothing to draw here */
+ return;
+ }
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* Draw the selection */
if (text->curl != text->sell || text->curc != text->selc) {
- int offl, offc;
/* Convert all to view space character coordinates */
wrap_offset(st, ar, text->curl, text->curc, &offl, &offc);
vcurl = txt_get_span(text->lines.first, text->curl) - st->top + offl;
vcurc = text_get_char_pos(st, text->curl->line, text->curc) - st->left + offc;
- wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
- vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl;
- vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc;
if (vcurc < 0) {
vcurc = 0;
}
- if (vselc < 0) {
- vselc = 0;
- hidden = 1;
- }
-
- UI_ThemeColor(TH_SHADE2);
+
+ immUniformThemeColor(TH_SHADE2);
+
x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
y = ar->winy;
if (vcurl == vsell) {
y -= vcurl * lheight;
- if (vcurc < vselc)
- glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight);
- else
- glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight);
+
+ if (vcurc < vselc) {
+ immRecti(pos, x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight);
+ }
+ else {
+ immRecti(pos, x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight);
+ }
}
else {
int froml, fromc, tol, toc;
@@ -1143,35 +1172,24 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
y -= froml * lheight;
- glRecti(x + fromc * st->cwidth - 1, y, ar->winx, y - lheight);
+ immRecti(pos, x + fromc * st->cwidth - 1, y, ar->winx, y - lheight);
y -= lheight;
+
for (i = froml + 1; i < tol; i++) {
- glRecti(x - 4, y, ar->winx, y - lheight);
+ immRecti(pos, x - 4, y, ar->winx, y - lheight);
y -= lheight;
}
- glRecti(x - 4, y, x + toc * st->cwidth, y - lheight);
+ immRecti(pos, x - 4, y, x + toc * st->cwidth, y - lheight);
y -= lheight;
}
}
- else {
- int offl, offc;
- wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
- vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl;
- vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc;
-
- if (vselc < 0) {
- vselc = 0;
- hidden = 1;
- }
- }
if (st->line_hlight) {
int x1, x2, y1, y2;
if (st->wordwrap) {
int visible_lines = text_get_visible_lines(st, ar, text->sell->line);
- int offl, offc;
wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc);
@@ -1187,36 +1205,38 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
x1 = 0; // st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
x2 = x1 + ar->winx;
- glColor4ub(255, 255, 255, 32);
-
+ immUniformColor4ub(255, 255, 255, 32);
+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- glRecti(x1 - 4, y1, x2, y2);
+ immRecti(pos, x1 - 4, y1, x2, y2);
glDisable(GL_BLEND);
}
}
-
+
if (!hidden) {
/* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */
x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
x += vselc * st->cwidth;
y = ar->winy - vsell * lheight;
-
+
+ immUniformThemeColor(TH_HILITE);
+
if (st->overwrite) {
char ch = text->sell->line[text->selc];
-
+
y += TXT_LINE_SPACING;
w = st->cwidth;
if (ch == '\t') w *= st->tabnumber - (vselc + st->left) % st->tabnumber;
-
- UI_ThemeColor(TH_HILITE);
- glRecti(x, y - lheight - 1, x + w, y - lheight + 1);
+
+ immRecti(pos, x, y - lheight - 1, x + w, y - lheight + 1);
}
else {
- UI_ThemeColor(TH_HILITE);
- glRecti(x - 1, y, x + 1, y - lheight);
+ immRecti(pos, x - 1, y, x + 1, y - lheight);
}
}
+
+ immUnbindProgram();
}
/******************* draw matching brackets *********************/
@@ -1317,7 +1337,7 @@ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegi
if (!endl || endc == -1)
return;
- UI_ThemeColor(TH_HILITE);
+ UI_FontThemeColor(tdc->font_id, TH_HILITE);
x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
y = ar->winy - st->lheight_dpi;
@@ -1422,8 +1442,11 @@ void draw_text_main(SpaceText *st, ARegion *ar)
if (st->showlinenrs) {
x = TXT_OFFSET + TEXTXLOC;
- UI_ThemeColor(TH_GRID);
- glRecti((TXT_OFFSET - 12), 0, (TXT_OFFSET - 5) + TEXTXLOC, ar->winy - 2);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_GRID);
+ immRecti(pos, (TXT_OFFSET - 12), 0, (TXT_OFFSET - 5) + TEXTXLOC, ar->winy - 2);
+ immUnbindProgram();
}
else {
st->linenrs_tot = 0; /* not used */
@@ -1432,11 +1455,11 @@ void draw_text_main(SpaceText *st, ARegion *ar)
y = ar->winy - st->lheight_dpi;
winx = ar->winx - TXT_SCROLL_WIDTH;
- /* draw cursor */
- draw_cursor(st, ar);
+ /* draw cursor, margin, selection and highlight */
+ draw_text_decoration(st, ar);
/* draw the text */
- UI_ThemeColor(TH_TEXT);
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
for (i = 0; y > clip_min_y && i < st->viewlines && tmp; i++, tmp = tmp->next) {
if (st->showsyntax && !tmp->format)
@@ -1444,16 +1467,20 @@ void draw_text_main(SpaceText *st, ARegion *ar)
if (st->showlinenrs && !wrap_skip) {
/* draw line number */
- if (tmp == text->curl)
- UI_ThemeColor(TH_HILITE);
- else
- UI_ThemeColor(TH_TEXT);
+ if (tmp == text->curl) {
+ UI_FontThemeColor(tdc.font_id, TH_HILITE);
+ }
+ else {
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
+ }
BLI_snprintf(linenr, sizeof(linenr), "%*d", st->linenrs_tot, i + linecount + 1);
/* itoa(i + linecount + 1, linenr, 10); */ /* not ansi-c :/ */
text_font_draw(&tdc, TXT_OFFSET - 7, y, linenr);
- UI_ThemeColor(TH_TEXT);
+ if (tmp == text->curl) {
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
+ }
}
if (st->wordwrap) {
@@ -1474,15 +1501,24 @@ void draw_text_main(SpaceText *st, ARegion *ar)
margin_column_x = x + st->cwidth * (st->margin_column - st->left);
if (margin_column_x >= x) {
- /* same color as line number background */
- UI_ThemeColor(TH_GRID);
-
- setlinestyle(1);
- glBegin(GL_LINES);
- glVertex2i(margin_column_x, 0);
- glVertex2i(margin_column_x, ar->winy - 2);
- glEnd();
- setlinestyle(0);
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniformThemeColor(TH_GRID); /* same color as line number background */
+ immUniform1f("dash_width", 2.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2i(shdr_pos, margin_column_x, 0);
+ immVertex2i(shdr_pos, margin_column_x, ar->winy - 2);
+ immEnd();
+ immUnbindProgram();
}
}
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 4f0d2c93970..772cd6bd419 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -694,7 +694,7 @@ static int text_refresh_pyconstraints_exec(bContext *UNUSED(C), wmOperator *UNUS
}
if (update) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
#endif
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index f29d2b30ffe..283dbf3b4e2 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -58,9 +58,11 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
+
+#include "RNA_access.h"
#include "BIF_gl.h"
-#include "BIF_glutil.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -69,6 +71,9 @@
#include "ED_space_api.h"
#include "ED_markers.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
#include "time_intern.h"
/* ************************ main time area region *********************** */
@@ -80,28 +85,42 @@ static void time_draw_sfra_efra(Scene *scene, View2D *v2d)
*/
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
-
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+
if (PSFRA < PEFRA) {
- glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
- glRectf((float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
+ immRectf(pos, (float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
else {
- glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
+
glDisable(GL_BLEND);
- UI_ThemeColorShade(TH_BACK, -60);
/* thin lines where the actual frames are */
- fdrawline((float)PSFRA, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
- fdrawline((float)PEFRA, v2d->cur.ymin, (float)PEFRA, v2d->cur.ymax);
+ immUniformThemeColorShade(TH_BACK, -60);
+
+ immBegin(GWN_PRIM_LINES, 4);
+
+ immVertex2f(pos, (float)PSFRA, v2d->cur.ymin);
+ immVertex2f(pos, (float)PSFRA, v2d->cur.ymax);
+
+ immVertex2f(pos, (float)PEFRA, v2d->cur.ymin);
+ immVertex2f(pos, (float)PEFRA, v2d->cur.ymax);
+
+ immEnd();
+ immUnbindProgram();
}
static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
{
PTCacheID *pid;
ListBase pidlist;
- SpaceTimeCache *stc = stime->caches.first;
const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize);
float yoffs = 0.f;
@@ -110,12 +129,13 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* iterate over pointcaches on the active object,
* add spacetimecache and vertex array for each */
for (pid = pidlist.first; pid; pid = pid->next) {
- float col[4], *fp;
- int i, sta = pid->cache->startframe, end = pid->cache->endframe;
- int len = (end - sta + 1) * 4;
+ float col[4];
switch (pid->type) {
case PTCACHE_TYPE_SOFTBODY:
@@ -142,43 +162,9 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
if (pid->cache->cached_frames == NULL)
continue;
- /* make sure we have stc with correct array length */
- if (stc == NULL || MEM_allocN_len(stc->array) != len * 2 * sizeof(float)) {
- if (stc) {
- MEM_freeN(stc->array);
- }
- else {
- stc = MEM_callocN(sizeof(SpaceTimeCache), "spacetimecache");
- BLI_addtail(&stime->caches, stc);
- }
-
- stc->array = MEM_callocN(len * 2 * sizeof(float), "SpaceTimeCache array");
- }
-
- /* fill the vertex array with a quad for each cached frame */
- for (i = sta, fp = stc->array; i <= end; i++) {
- if (pid->cache->cached_frames[i - sta]) {
- fp[0] = (float)i - 0.5f;
- fp[1] = 0.0;
- fp += 2;
-
- fp[0] = (float)i - 0.5f;
- fp[1] = 1.0;
- fp += 2;
-
- fp[0] = (float)i + 0.5f;
- fp[1] = 1.0;
- fp += 2;
-
- fp[0] = (float)i + 0.5f;
- fp[1] = 0.0;
- fp += 2;
- }
- }
-
- glPushMatrix();
- glTranslatef(0.0, (float)V2D_SCROLL_HEIGHT + yoffs, 0.0);
- glScalef(1.0, cache_draw_height, 0.0);
+ gpuPushMatrix();
+ gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT + yoffs);
+ gpuScale2f(1.0, cache_draw_height);
switch (pid->type) {
case PTCACHE_TYPE_SOFTBODY:
@@ -212,12 +198,15 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
BLI_assert(0);
break;
}
- glColor4fv(col);
-
+
+ const int sta = pid->cache->startframe, end = pid->cache->endframe;
+ const int len = (end - sta + 1) * 6;
+
glEnable(GL_BLEND);
-
- glRectf((float)sta, 0.0, (float)end, 1.0);
-
+
+ immUniformColor4fv(col);
+ immRectf(pos, (float)sta, 0.0, (float)end, 1.0);
+
col[3] = 0.4f;
if (pid->cache->flag & PTCACHE_BAKED) {
col[0] -= 0.4f; col[1] -= 0.4f; col[2] -= 0.4f;
@@ -225,52 +214,38 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
else if (pid->cache->flag & PTCACHE_OUTDATED) {
col[0] += 0.4f; col[1] += 0.4f; col[2] += 0.4f;
}
- glColor4fv(col);
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, stc->array);
- glDrawArrays(GL_QUADS, 0, (fp - stc->array) / 2);
- glDisableClientState(GL_VERTEX_ARRAY);
-
- glDisable(GL_BLEND);
-
- glPopMatrix();
-
- yoffs += cache_draw_height;
- stc = stc->next;
- }
+ immUniformColor4fv(col);
- BLI_freelistN(&pidlist);
+ if (len > 0) {
+ immBeginAtMost(GWN_PRIM_TRIS, len);
- /* free excessive caches */
- while (stc) {
- SpaceTimeCache *tmp = stc->next;
- BLI_remlink(&stime->caches, stc);
- MEM_freeN(stc->array);
- MEM_freeN(stc);
- stc = tmp;
- }
-}
+ /* draw a quad for each cached frame */
+ for (int i = sta; i <= end; i++) {
+ if (pid->cache->cached_frames[i - sta]) {
+ immVertex2f(pos, (float)i - 0.5f, 0.0f);
+ immVertex2f(pos, (float)i - 0.5f, 1.0f);
+ immVertex2f(pos, (float)i + 0.5f, 1.0f);
-static void time_cache_free(SpaceTime *stime)
-{
- SpaceTimeCache *stc;
-
- for (stc = stime->caches.first; stc; stc = stc->next) {
- if (stc->array) {
- MEM_freeN(stc->array);
- stc->array = NULL;
+ immVertex2f(pos, (float)i - 0.5f, 0.0f);
+ immVertex2f(pos, (float)i + 0.5f, 1.0f);
+ immVertex2f(pos, (float)i + 0.5f, 0.0f);
+ }
+ }
+
+ immEnd();
}
+
+ glDisable(GL_BLEND);
+
+ gpuPopMatrix();
+
+ yoffs += cache_draw_height;
}
-
- BLI_freelistN(&stime->caches);
-}
-static void time_cache_refresh(SpaceTime *stime)
-{
- /* Free previous caches to indicate full refresh */
- time_cache_free(stime);
+ immUnbindProgram();
+
+ BLI_freelistN(&pidlist);
}
/* helper function - find actkeycolumn that occurs on cframe, or the nearest one if not found */
@@ -296,7 +271,7 @@ static ActKeyColumn *time_cfra_find_ak(ActKeyColumn *ak, float cframe)
}
/* helper for time_draw_keyframes() */
-static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
+static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel, const unsigned char color[3])
{
bDopeSheet ads = {NULL};
DLRBT_Tree keys;
@@ -341,21 +316,40 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
* the first visible keyframe (last one can then be easily checked)
* - draw within a single GL block to be faster
*/
- glBegin(GL_LINES);
- for (ak = time_cfra_find_ak(keys.root, v2d->cur.xmin);
- (ak) && (ak->cfra <= v2d->cur.xmax);
- ak = ak->next)
- {
- glVertex2f(ak->cfra, ymin);
- glVertex2f(ak->cfra, ymax);
+
+ ActKeyColumn *link;
+ int max_len = 0;
+
+ ak = time_cfra_find_ak(keys.root, v2d->cur.xmin);
+
+ for (link = ak; link; link = link->next) {
+ max_len++;
}
- glEnd(); // GL_LINES
-
+
+ if (max_len > 0) {
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ubv(color);
+
+ immBeginAtMost(GWN_PRIM_LINES, max_len * 2);
+
+ for (; (ak) && (ak->cfra <= v2d->cur.xmax); ak = ak->next) {
+ immVertex2f(pos, ak->cfra, ymin);
+ immVertex2f(pos, ak->cfra, ymax);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
+
/* free temp stuff */
BLI_dlrbTree_free(&keys);
}
-static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, bool onlysel)
+static void time_draw_caches_keyframes(Main *bmain, ViewLayer *view_layer, View2D *v2d, bool onlysel, const unsigned char color[3])
{
CacheFile *cache_file;
@@ -366,7 +360,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 (Base *base = view_layer->object_bases.first; base; base = base->next) {
Object *ob = base->object;
ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
@@ -382,7 +376,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b
cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN;
- time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel);
+ time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel, color);
}
for (bConstraint *con = ob->constraints.first; con; con = con->next) {
@@ -400,7 +394,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b
cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN;
- time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel);
+ time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel, color);
}
}
}
@@ -409,24 +403,27 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b
static void time_draw_keyframes(const bContext *C, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = CTX_data_active_object(C);
View2D *v2d = &ar->v2d;
bool onlysel = ((scene->flag & SCE_KEYS_NO_SELONLY) == 0);
+ unsigned char color[3];
/* set this for all keyframe lines once and for all */
glLineWidth(1.0);
/* draw cache files keyframes (if available) */
- UI_ThemeColor(TH_TIME_KEYFRAME);
- time_draw_caches_keyframes(CTX_data_main(C), scene, v2d, onlysel);
+ UI_GetThemeColor3ubv(TH_TIME_KEYFRAME, color);
+ time_draw_caches_keyframes(CTX_data_main(C), view_layer, v2d, onlysel, color);
/* draw grease pencil keyframes (if available) */
- UI_ThemeColor(TH_TIME_GP_KEYFRAME);
+ UI_GetThemeColor3ubv(TH_TIME_GP_KEYFRAME, color);
+
if (scene->gpd) {
- time_draw_idblock_keyframes(v2d, (ID *)scene->gpd, onlysel);
+ time_draw_idblock_keyframes(v2d, (ID *)scene->gpd, onlysel, color);
}
if (ob && ob->gpd) {
- time_draw_idblock_keyframes(v2d, (ID *)ob->gpd, onlysel);
+ time_draw_idblock_keyframes(v2d, (ID *)ob->gpd, onlysel, color);
}
/* draw scene keyframes first
@@ -435,8 +432,8 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
*/
if (onlysel == 0) {
/* set draw color */
- UI_ThemeColorShade(TH_TIME_KEYFRAME, -50);
- time_draw_idblock_keyframes(v2d, (ID *)scene, onlysel);
+ UI_GetThemeColorShade3ubv(TH_TIME_KEYFRAME, -50, color);
+ time_draw_idblock_keyframes(v2d, (ID *)scene, onlysel, color);
}
/* draw keyframes from selected objects
@@ -444,11 +441,11 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
* OR the onlysel flag was set, which means that only active object's keyframes should
* be considered
*/
- UI_ThemeColor(TH_TIME_KEYFRAME);
-
+ UI_GetThemeColor3ubv(TH_TIME_KEYFRAME, color);
+
if (ob && ((ob->mode == OB_MODE_POSE) || onlysel)) {
/* draw keyframes for active object only */
- time_draw_idblock_keyframes(v2d, (ID *)ob, onlysel);
+ time_draw_idblock_keyframes(v2d, (ID *)ob, onlysel, color);
}
else {
bool active_done = false;
@@ -457,7 +454,7 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
CTX_DATA_BEGIN (C, Object *, obsel, selected_objects)
{
/* last arg is 0, since onlysel doesn't apply here... */
- time_draw_idblock_keyframes(v2d, (ID *)obsel, 0);
+ time_draw_idblock_keyframes(v2d, (ID *)obsel, 0, color);
/* if this object is the active one, set flag so that we don't draw again */
if (obsel == ob)
@@ -467,24 +464,15 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
/* if active object hasn't been done yet, draw it... */
if (ob && (active_done == 0))
- time_draw_idblock_keyframes(v2d, (ID *)ob, 0);
+ time_draw_idblock_keyframes(v2d, (ID *)ob, 0, color);
}
}
/* ---------------- */
-static void time_refresh(const bContext *UNUSED(C), ScrArea *sa)
-{
- /* find the main timeline region and refresh cache display*/
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar) {
- SpaceTime *stime = (SpaceTime *)sa->spacedata.first;
- time_cache_refresh(stime);
- }
-}
-
/* editor level listener */
-static void time_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
+static void time_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene),
+ WorkSpace *UNUSED(workspace))
{
/* mainly for updating cache display */
@@ -625,7 +613,9 @@ static void time_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_scrollers_free(scrollers);
}
-static void time_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void time_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -654,9 +644,55 @@ static void time_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa),
if (wmn->data == ND_DATA)
ED_region_tag_redraw(ar);
break;
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
+ }
+}
+
+static void time_main_region_message_subscribe(
+ const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace), struct Scene *scene,
+ struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceTimeline, sa->spacedata.first, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ /* Timeline depends on scene properties. */
+ {
+ bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
+ extern PropertyRNA rna_Scene_frame_start;
+ extern PropertyRNA rna_Scene_frame_end;
+ extern PropertyRNA rna_Scene_frame_preview_start;
+ extern PropertyRNA rna_Scene_frame_preview_end;
+ extern PropertyRNA rna_Scene_use_preview_range;
+ extern PropertyRNA rna_Scene_frame_current;
+ const PropertyRNA *props[] = {
+ use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
+ use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
+ &rna_Scene_use_preview_range,
+ &rna_Scene_frame_current,
+ };
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&scene->id, &idptr);
+
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
+ }
}
}
+
/* ************************ header time area region *********************** */
/* add handlers, stuff you only do once or on area/region changes */
@@ -670,7 +706,9 @@ static void time_header_region_draw(const bContext *C, ARegion *ar)
ED_region_header(C, ar);
}
-static void time_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void time_header_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -754,13 +792,6 @@ static SpaceLink *time_new(const bContext *C)
return (SpaceLink *)stime;
}
-/* not spacelink itself */
-static void time_free(SpaceLink *sl)
-{
- SpaceTime *stime = (SpaceTime *)sl;
-
- time_cache_free(stime);
-}
/* spacetype; init callback in ED_area_initialize() */
/* init is called to (re)initialize an existing editor (file read, screen changes) */
/* validate spacedata, add own area level handlers */
@@ -768,8 +799,6 @@ static void time_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
{
SpaceTime *stime = (SpaceTime *)sa->spacedata.first;
- time_cache_free(stime);
-
/* enable all cache display */
stime->cache_display |= TIME_CACHE_DISPLAY;
stime->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES);
@@ -798,13 +827,11 @@ void ED_spacetype_time(void)
strncpy(st->name, "Timeline", BKE_ST_MAXNAME);
st->new = time_new;
- st->free = time_free;
st->init = time_init;
st->duplicate = time_duplicate;
st->operatortypes = time_operatortypes;
st->keymap = NULL;
st->listener = time_listener;
- st->refresh = time_refresh;
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype time region");
@@ -814,6 +841,7 @@ void ED_spacetype_time(void)
art->init = time_main_region_init;
art->draw = time_main_region_draw;
art->listener = time_main_region_listener;
+ art->message_subscribe = time_main_region_message_subscribe;
art->keymap = time_keymap;
art->lock = 1; /* Due to pointcache, see T4960. */
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index aeba4a86f3e..f640fe63f93 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -136,12 +136,16 @@ static void userpref_header_region_draw(const bContext *C, ARegion *ar)
ED_region_header(C, ar);
}
-static void userpref_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void userpref_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
{
/* context changes */
}
-static void userpref_header_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
+static void userpref_header_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar),
+ wmNotifier *UNUSED(wmn), const Scene *UNUSED(scene))
{
/* context changes */
#if 0
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index a5c60248bf1..de8380aa8bb 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -25,6 +25,7 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../draw
../../gpu
../../imbuf
../../makesdna
@@ -52,11 +53,18 @@ set(SRC
view3d_buttons.c
view3d_camera_control.c
view3d_draw.c
+ view3d_draw_legacy.c
view3d_edit.c
view3d_fly.c
view3d_walk.c
view3d_header.c
view3d_iterators.c
+ view3d_manipulator_armature.c
+ view3d_manipulator_camera.c
+ view3d_manipulator_empty.c
+ view3d_manipulator_forcefield.c
+ view3d_manipulator_lamp.c
+ view3d_manipulator_ruler.c
view3d_ops.c
view3d_project.c
view3d_ruler.c
@@ -94,8 +102,4 @@ if(WITH_MOD_SMOKE)
add_definitions(-DWITH_SMOKE)
endif()
-if(WITH_LEGACY_DEPSGRAPH)
- add_definitions(-DWITH_LEGACY_DEPSGRAPH)
-endif()
-
blender_add_lib(bf_editor_space_view3d "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c
index f0e65f84205..66355a50478 100644
--- a/source/blender/editors/space_view3d/drawanimviz.c
+++ b/source/blender/editors/space_view3d/drawanimviz.c
@@ -49,7 +49,8 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
-#include "BIF_gl.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "ED_keyframes_draw.h"
@@ -71,8 +72,8 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar)
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
+ gpuPushMatrix();
+ gpuLoadMatrix(rv3d->viewmat);
}
/* set color
@@ -86,10 +87,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 +99,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 +111,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 +130,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 +147,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 +238,65 @@ void draw_motion_path_instance(Scene *scene,
/* set line thickness */
glLineWidth(mpath->line_thickness);
- glBegin(GL_LINE_STRIP);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+
+ immBegin(GWN_PRIM_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 int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_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(GWN_PRIM_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(GWN_PRIM_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 +304,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(GWN_PRIM_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 +385,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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(col);
- glBegin(GL_POINTS);
+ immBeginAtMost(GWN_PRIM_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) {
@@ -398,5 +434,5 @@ void draw_motion_path_instance(Scene *scene,
void draw_motion_paths_cleanup(View3D *v3d)
{
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- glPopMatrix();
+ gpuPopMatrix();
}
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 5208013b6fe..77cd64be7c1 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -54,15 +54,20 @@
#include "BKE_modifier.h"
#include "BKE_nla.h"
#include "BKE_curve.h"
+#include "BKE_context.h"
+#include "DEG_depsgraph.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "ED_armature.h"
#include "ED_keyframes_draw.h"
#include "GPU_basic_shader.h"
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#include "UI_resources.h"
@@ -74,8 +79,10 @@
/* global here is reset before drawing each bone */
static ThemeWireColor *bcolor = NULL;
+static float fcolor[4] = {0.0f};
+static bool flat_color;
-/* values of colCode for set_pchan_glcolor */
+/* values of colCode for set_pchan_color */
enum {
PCHAN_COLOR_NORMAL = 0, /* normal drawing */
PCHAN_COLOR_SOLID, /* specific case where "solid" color is needed */
@@ -128,7 +135,7 @@ static void set_pchan_colorset(Object *ob, bPoseChannel *pchan)
}
}
-/* This function is for brightening/darkening a given color (like UI_ThemeColorShade()) */
+/* This function is for brightening/darkening a given color (like UI_GetThemeColorShade3ubv()) */
static void cp_shade_color3ub(unsigned char cp[3], const int offset)
{
int r, g, b;
@@ -146,13 +153,13 @@ 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)
+static bool set_pchan_color(short colCode, int boneflag, short constflag)
{
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);
@@ -169,20 +176,20 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
cp_shade_color3ub(cp, -50);
}
- 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);
}
}
@@ -191,21 +198,25 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
case PCHAN_COLOR_SOLID:
{
if (bcolor) {
- glColor3ubv((unsigned char *)bcolor->solid);
+ rgb_uchar_to_float(fcolor, (unsigned char *)bcolor->solid);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
}
- else
- UI_ThemeColor(TH_BONE_SOLID);
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);
+
+ rgba_uchar_to_float(fcolor, cp);
+
return true;
}
return false;
@@ -213,7 +224,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);
@@ -225,12 +236,18 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
copy_v3_v3_char((char *)cp, bcolor->solid);
}
- 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_GetThemeColorShade4fv(TH_BONE_POSE, 40, fcolor);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ }
}
return true;
@@ -238,7 +255,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);
@@ -253,12 +270,18 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
cp_shade_color3ub(cp, -30);
}
- 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_GetThemeColorShade4fv(TH_BONE_POSE, 10, fcolor);
+ }
+ else if (boneflag & BONE_SELECTED) {
+ UI_GetThemeColorShade4fv(TH_BONE_POSE, -30, fcolor);
+ }
+ else {
+ UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
+ }
}
break;
}
@@ -266,19 +289,24 @@ 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 */
+
+ 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 {
+ UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor);
}
- else
- UI_ThemeColorShade(TH_BACK, -30);
}
return true;
@@ -288,26 +316,37 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
return false;
}
-static void set_ebone_glColor(const unsigned int boneflag)
+static void set_ebone_color(const unsigned int boneflag)
{
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 ******************* */
+static void add_solid_flat_triangle(Gwn_VertBuf *vbo, unsigned int *vertex, unsigned int pos, unsigned int nor,
+ const float p1[3], const float p2[3], const float p3[3], const float n[3])
+{
+ GWN_vertbuf_attr_set(vbo, nor, *vertex, n);
+ GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p1);
+ GWN_vertbuf_attr_set(vbo, nor, *vertex, n);
+ GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p2);
+ GWN_vertbuf_attr_set(vbo, nor, *vertex, n);
+ GWN_vertbuf_attr_set(vbo, pos, (*vertex)++, p3);
+}
+
/* 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,128 +357,184 @@ 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;
- float n[3] = {0.0f};
-
- glScalef(xsize, ysize, zsize);
-
- if (displist == 0) {
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
+ static Gwn_VertFormat format = {0};
+ static Gwn_VertBuf vbo = {{0}};
+ static Gwn_Batch batch = {{0}};
+ const float light_vec[3] = {0.0f, 0.0f, 1.0f};
+
+ if (format.attrib_ct == 0) {
+ unsigned int i = 0;
+ float n[3] = {0.0f};
+ /* Vertex format */
+ unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ /* Vertices */
+ GWN_vertbuf_init_with_format(&vbo, &format);
+ GWN_vertbuf_data_alloc(&vbo, 36);
- glBegin(GL_QUADS);
n[0] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[1], cube_vert[2], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[2], cube_vert[3], cube_vert[0], n);
n[0] = 0;
n[1] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[4], cube_vert[5], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[5], cube_vert[1], cube_vert[0], n);
n[1] = 0;
n[0] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[4], cube_vert[7], cube_vert[6], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[6], cube_vert[5], cube_vert[4], n);
n[0] = 0;
n[1] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[7], cube_vert[3], cube_vert[2], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[2], cube_vert[6], cube_vert[7], n);
n[1] = 0;
n[2] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[1], cube_vert[5], cube_vert[6], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[6], cube_vert[2], cube_vert[1], n);
n[2] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
- glEnd();
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[7], cube_vert[4], cube_vert[0], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[3], cube_vert[7], n);
- glEndList();
+ GWN_batch_init(&batch, GWN_PRIM_TRIS, &vbo, NULL);
}
- glCallList(displist);
+ gpuPushMatrix();
+ gpuScale3f(xsize, ysize, zsize);
+
+ if (flat_color) {
+ GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+ else {
+ /* TODO replace with good default lighting shader ? */
+ GWN_batch_program_set_builtin(&batch, GPU_SHADER_SIMPLE_LIGHTING);
+ GWN_batch_uniform_3fv(&batch, "light", light_vec);
+ }
+ GWN_batch_uniform_4fv(&batch, "color", fcolor);
+ GWN_batch_draw(&batch);
+
+ gpuPopMatrix();
}
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 Gwn_VertFormat format = {0};
+ static Gwn_VertBuf vbo = {{0}};
+ static Gwn_IndexBufBuilder elb = {0};
+ static Gwn_IndexBuf el = {0};
+ static Gwn_Batch batch = {{0}};
+
+ if (format.attrib_ct == 0) {
+ /* Vertex format */
+ unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ /* Elements */
+ GWN_indexbuf_init(&elb, GWN_PRIM_LINES, 12, 8);
+ for (int i = 0; i < 12; ++i) {
+ GWN_indexbuf_add_line_verts(&elb, cube_wire[i * 2], cube_wire[i * 2 + 1]);
+ }
+ GWN_indexbuf_build_in_place(&elb, &el);
+
+ /* Vertices */
+ GWN_vertbuf_init_with_format(&vbo, &format);
+ GWN_vertbuf_data_alloc(&vbo, 8);
+ for (int i = 0; i < 8; ++i) {
+ GWN_vertbuf_attr_set(&vbo, pos, i, cube_vert[i]);
+ }
+
+ GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, &el);
+ GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
}
- glScalef(xsize, ysize, zsize);
- glCallList(displist);
-
+ gpuPushMatrix();
+ gpuScale3f(xsize, ysize, zsize);
+
+ GWN_batch_program_use_begin(&batch);
+ GWN_batch_uniform_4fv(&batch, "color", fcolor);
+ GWN_batch_draw(&batch);
+
+ gpuPopMatrix();
}
static void draw_bonevert(void)
{
- static GLuint displist = 0;
-
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- glPushMatrix();
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
- gluDisk(qobj, 0.0, 0.05, 16, 1);
-
- glRotatef(90, 0, 1, 0);
- gluDisk(qobj, 0.0, 0.05, 16, 1);
-
- glRotatef(90, 1, 0, 0);
- gluDisk(qobj, 0.0, 0.05, 16, 1);
-
- gluDeleteQuadric(qobj);
-
- glPopMatrix();
- glEndList();
+ static Gwn_VertFormat format = {0};
+ static Gwn_VertBuf vbo = {{0}};
+ static Gwn_Batch batch = {{0}};
+
+ if (format.attrib_ct == 0) {
+ /* Vertex format */
+ unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ /* Vertices */
+ GWN_vertbuf_init_with_format(&vbo, &format);
+ GWN_vertbuf_data_alloc(&vbo, 96);
+ for (int i = 0; i < 16; ++i) {
+ float vert[3] = {0.f, 0.f, 0.f};
+ const float r = 0.05f;
+
+ vert[0] = r * cosf(2 * M_PI * i / 16.f);
+ vert[1] = r * sinf(2 * M_PI * i / 16.f);
+ GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 0, vert);
+ vert[0] = r * cosf(2 * M_PI * (i + 1) / 16.f);
+ vert[1] = r * sinf(2 * M_PI * (i + 1) / 16.f);
+ GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 1, vert);
+
+ vert[0] = 0.f;
+ vert[1] = r * cosf(2 * M_PI * i / 16.f);
+ vert[2] = r * sinf(2 * M_PI * i / 16.f);
+ GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 2, vert);
+ vert[1] = r * cosf(2 * M_PI * (i + 1) / 16.f);
+ vert[2] = r * sinf(2 * M_PI * (i + 1) / 16.f);
+ GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 3, vert);
+
+ vert[1] = 0.f;
+ vert[0] = r * cosf(2 * M_PI * i / 16.f);
+ vert[2] = r * sinf(2 * M_PI * i / 16.f);
+ GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 4, vert);
+ vert[0] = r * cosf(2 * M_PI * (i + 1) / 16.f);
+ vert[2] = r * sinf(2 * M_PI * (i + 1) / 16.f);
+ GWN_vertbuf_attr_set(&vbo, pos, i * 6 + 5, vert);
+ }
+
+ GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, NULL);
+ GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
}
- glCallList(displist);
+ GWN_batch_program_use_begin(&batch);
+ GWN_batch_uniform_4fv(&batch, "color", fcolor);
+ GWN_batch_draw(&batch);
}
static void draw_bonevert_solid(void)
{
- static GLuint displist = 0;
-
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
- /* Draw tips of a bone */
- gluSphere(qobj, 0.05, 8, 5);
- gluDeleteQuadric(qobj);
-
- glEndList();
+ Gwn_Batch *batch = GPU_batch_preset_sphere(0);
+ const float light_vec[3] = {0.0f, 0.0f, 1.0f};
+
+ gpuPushMatrix();
+ gpuScaleUniform(0.05);
+
+ if (flat_color) {
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
}
+ else {
+ /* TODO replace with good default lighting shader ? */
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING);
+ GWN_batch_uniform_3fv(batch, "light", light_vec);
+ }
+ GWN_batch_uniform_4fv(batch, "color", fcolor);
+ GWN_batch_draw(batch);
- glCallList(displist);
+ gpuPopMatrix();
}
static const float bone_octahedral_verts[6][3] = {
@@ -451,8 +546,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,70 +578,78 @@ 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);
-
- /* 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();
+ static Gwn_VertFormat format = {0};
+ static Gwn_VertBuf vbo = {{0}};
+ static Gwn_IndexBufBuilder elb = {0};
+ static Gwn_IndexBuf el = {0};
+ static Gwn_Batch batch = {{0}};
+
+ if (format.attrib_ct == 0) {
+ /* Vertex format */
+ unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ /* Elements */
+ GWN_indexbuf_init(&elb, GWN_PRIM_LINES, 12, 6);
+ for (int i = 0; i < 12; ++i) {
+ GWN_indexbuf_add_line_verts(&elb, bone_octahedral_wire[i * 2], bone_octahedral_wire[i * 2 + 1]);
+ }
+ GWN_indexbuf_build_in_place(&elb, &el);
+
+ /* Vertices */
+ GWN_vertbuf_init_with_format(&vbo, &format);
+ GWN_vertbuf_data_alloc(&vbo, 6);
+ for (int i = 0; i < 6; ++i) {
+ GWN_vertbuf_attr_set(&vbo, pos, i, bone_octahedral_verts[i]);
+ }
+
+ GWN_batch_init(&batch, GWN_PRIM_LINES, &vbo, &el);
+ GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
}
- glCallList(displist);
-}
+ GWN_batch_program_use_begin(&batch);
+ GWN_batch_uniform_4fv(&batch, "color", fcolor);
+ GWN_batch_draw(&batch);
+}
static void draw_bone_solid_octahedral(void)
{
- static GLuint displist = 0;
-
- if (displist == 0) {
- int i;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
-#if 1
- glBegin(GL_TRIANGLES);
- for (i = 0; i < 8; i++) {
- glNormal3fv(bone_octahedral_solid_normals[i]);
- glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]);
- glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]);
- glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]);
- }
-
- glEnd();
-
-#else /* not working because each vert needs a different normal */
- glEnableClientState(GL_NORMAL_ARRAY);
- glEnableClientState(GL_VERTEX_ARRAY);
- glNormalPointer(GL_FLOAT, 0, bone_octahedral_solid_normals);
- glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts);
- glDrawElements(GL_TRIANGLES, sizeof(bone_octahedral_solid_tris) / sizeof(unsigned int),
- GL_UNSIGNED_INT, bone_octahedral_solid_tris);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
-#endif
+ static Gwn_VertFormat format = {0};
+ static Gwn_VertBuf vbo = {{0}};
+ static Gwn_Batch batch = {{0}};
+ const float light_vec[3] = {0.0f, 0.0f, 1.0f};
+
+ if (format.attrib_ct == 0) {
+ unsigned int v_idx = 0;
+ /* Vertex format */
+ unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ /* Vertices */
+ GWN_vertbuf_init_with_format(&vbo, &format);
+ GWN_vertbuf_data_alloc(&vbo, 24);
+
+ for (int i = 0; i < 8; i++) {
+ add_solid_flat_triangle(&vbo, &v_idx, pos, nor,
+ bone_octahedral_verts[bone_octahedral_solid_tris[i][0]],
+ bone_octahedral_verts[bone_octahedral_solid_tris[i][1]],
+ bone_octahedral_verts[bone_octahedral_solid_tris[i][2]],
+ bone_octahedral_solid_normals[i]);
+ }
- glEndList();
+ GWN_batch_init(&batch, GWN_PRIM_TRIS, &vbo, NULL);
}
- glCallList(displist);
-}
+ if (flat_color) {
+ GWN_batch_program_set_builtin(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+ else {
+ /* TODO replace with good default lighting shader ? */
+ GWN_batch_program_set_builtin(&batch, GPU_SHADER_SIMPLE_LIGHTING);
+ GWN_batch_uniform_3fv(&batch, "light", light_vec);
+ }
+ GWN_batch_uniform_4fv(&batch, "color", fcolor);
+ GWN_batch_draw(&batch);
+}
/* *************** Armature drawing, bones ******************* */
@@ -557,15 +663,20 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag,
if (dt <= OB_WIRE) {
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
+ if (boneflag & BONE_ROOTSEL) {
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_VERTEX, fcolor);
+ }
}
}
else {
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
- else
- UI_ThemeColor(TH_BONE_SOLID);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, 0);
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ }
}
if (dt > OB_WIRE)
@@ -580,24 +691,29 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag,
if (dt <= OB_WIRE) {
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
+ if (boneflag & BONE_TIPSEL) {
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_VERTEX, fcolor);
+ }
}
}
else {
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
- else
- UI_ThemeColor(TH_BONE_SOLID);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, 0);
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ }
}
- glTranslatef(0.0f, 1.0f, 0.0f);
+ gpuPushMatrix();
+ gpuTranslate2f(0.0f, 1.0f);
if (dt > OB_WIRE)
draw_bonevert_solid();
else
draw_bonevert();
- glTranslatef(0.0f, -1.0f, 0.0f);
-
+ gpuPopMatrix();
}
/* 16 values of sin function (still same result!) */
@@ -696,8 +812,13 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann
//mul_v3_fl(dirvec, head);
cross_v3_v3v3(norvec, dirvec, imat[2]);
-
- glBegin(GL_QUAD_STRIP);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBegin(GWN_PRIM_TRI_STRIP, 66);
+ immUniformColor4ub(255, 255, 255, 50);
for (a = 0; a < 16; a++) {
vec[0] = -si[a] * dirvec[0] + co[a] * norvec[0];
@@ -707,10 +828,8 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann
madd_v3_v3v3fl(vec1, headvec, vec, head);
madd_v3_v3v3fl(vec2, headvec, vec, head + dist);
- glColor4ub(255, 255, 255, 50);
- glVertex3fv(vec1);
- //glColor4ub(255, 255, 255, 0);
- glVertex3fv(vec2);
+ immVertex3fv(pos, vec1);
+ immVertex3fv(pos, vec2);
}
for (a = 15; a >= 0; a--) {
@@ -721,10 +840,8 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann
madd_v3_v3v3fl(vec1, tailvec, vec, tail);
madd_v3_v3v3fl(vec2, tailvec, vec, tail + dist);
- //glColor4ub(255, 255, 255, 50);
- glVertex3fv(vec1);
- //glColor4ub(255, 255, 255, 0);
- glVertex3fv(vec2);
+ immVertex3fv(pos, vec1);
+ immVertex3fv(pos, vec2);
}
/* make it cyclic... */
@@ -735,12 +852,11 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann
madd_v3_v3v3fl(vec1, headvec, vec, head);
madd_v3_v3v3fl(vec2, headvec, vec, head + dist);
- //glColor4ub(255, 255, 255, 50);
- glVertex3fv(vec1);
- //glColor4ub(255, 255, 255, 0);
- glVertex3fv(vec2);
+ immVertex3fv(pos, vec1);
+ immVertex3fv(pos, vec2);
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
}
@@ -752,6 +868,11 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
{
float head, tail /*, length*/;
float *headvec, *tailvec, dirvec[3];
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
/* figure out the sizes of spheres */
if (ebone) {
@@ -780,35 +901,49 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
/* sphere root color */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
+ if (boneflag & BONE_ROOTSEL) {
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_VERTEX, fcolor);
+ }
}
else if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
-
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
+
+ immUniformColor4fv(fcolor);
+
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (id != -1)
GPU_select_load_id(id | BONESEL_ROOT);
- drawcircball(GL_LINE_LOOP, headvec, head, imat);
+ imm_drawcircball(headvec, head, imat, pos);
}
/* Draw tip point */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
+ if (boneflag & BONE_TIPSEL) {
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_VERTEX, fcolor);
+ }
}
if (id != -1)
GPU_select_load_id(id | BONESEL_TIP);
- drawcircball(GL_LINE_LOOP, tailvec, tail, imat);
+ imm_drawcircball(tailvec, tail, imat, pos);
/* base */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
- else UI_ThemeColor(TH_WIRE_EDIT);
+ if (boneflag & BONE_SELECTED) {
+ UI_GetThemeColor4fv(TH_SELECT, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor);
+ }
}
sub_v3_v3v3(dirvec, tailvec, headvec);
@@ -834,34 +969,40 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
if (id != -1)
GPU_select_load_id(id | BONESEL_BONE);
- glBegin(GL_LINES);
+ immBegin(GWN_PRIM_LINES, 4);
add_v3_v3v3(vec, headvec, norvech);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
add_v3_v3v3(vec, tailvec, norvect);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
sub_v3_v3v3(vec, headvec, norvech);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
sub_v3_v3v3(vec, tailvec, norvect);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
- glEnd();
+ immEnd();
}
+
+ immUnbindProgram();
}
/* does wire only for outline selecting */
static void draw_sphere_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
bPoseChannel *pchan, EditBone *ebone)
{
- GLUquadricObj *qobj;
+ Gwn_Batch *sphere = GPU_batch_preset_sphere(1);
float head, tail, length;
- float fac1, fac2;
-
- glPushMatrix();
- qobj = gluNewQuadric();
+ float fac1, fac2, size1, size2;
+ const float light_vec[3] = {0.0f, 0.0f, 1.0f};
+
+ /* dt is always OB_SOlID */
+ GWN_batch_program_set_builtin(sphere, GPU_SHADER_SIMPLE_LIGHTING);
+ GWN_batch_uniform_3fv(sphere, "light", light_vec);
+
+ gpuPushMatrix();
/* figure out the sizes of spheres */
if (ebone) {
@@ -882,110 +1023,124 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
}
/* move to z-axis space */
- glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
+ gpuRotateAxis(-90.0f, 'X');
- if (dt == OB_SOLID) {
- /* set up solid drawing */
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
-
- gluQuadricDrawStyle(qobj, GLU_FILL);
- }
- else {
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
- }
-
/* sphere root color */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColorShade(TH_BONE_SOLID, -30);
+ if (boneflag & BONE_ROOTSEL)
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ else
+ UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
}
else if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag);
else if (dt == OB_SOLID)
- UI_ThemeColorShade(TH_BONE_SOLID, -30);
+ UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (id != -1)
GPU_select_load_id(id | BONESEL_ROOT);
- gluSphere(qobj, head, 16, 10);
+ gpuPushMatrix();
+ gpuScaleUniform(head);
+ GWN_batch_uniform_4fv(sphere, "color", fcolor);
+ GWN_batch_draw(sphere);
+ gpuPopMatrix();
}
/* Draw tip point */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColorShade(TH_BONE_SOLID, -30);
+ if (boneflag & BONE_TIPSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ else UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
}
if (id != -1)
GPU_select_load_id(id | BONESEL_TIP);
- glTranslatef(0.0f, 0.0f, length);
- gluSphere(qobj, tail, 16, 10);
- glTranslatef(0.0f, 0.0f, -length);
+ gpuTranslate3f(0.0f, 0.0f, length);
+
+ gpuPushMatrix();
+ gpuScaleUniform(tail);
+ GWN_batch_program_use_begin(sphere); /* hack to make the following uniforms stick */
+ GWN_batch_uniform_4fv(sphere, "color", fcolor);
+ GWN_batch_draw(sphere);
+ gpuPopMatrix();
+
+ gpuTranslate3f(0.0f, 0.0f, -length);
/* base */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
- else UI_ThemeColor(TH_BONE_SOLID);
+ if (boneflag & BONE_SELECTED) UI_GetThemeColor4fv(TH_SELECT, fcolor);
+ else UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
}
else if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag);
else if (dt == OB_SOLID)
- UI_ThemeColor(TH_BONE_SOLID);
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+
+ GWN_batch_program_use_begin(sphere); /* hack to make the following uniforms stick */
+ GWN_batch_uniform_4fv(sphere, "color", fcolor);
fac1 = (length - head) / length;
fac2 = (length - tail) / length;
if (length > (head + tail)) {
+ size1 = fac2 * tail + (1.0f - fac2) * head;
+ size2 = fac1 * head + (1.0f - fac1) * tail;
+
if (id != -1)
GPU_select_load_id(id | BONESEL_BONE);
+ /* draw sphere on extrema */
+ gpuPushMatrix();
+ gpuTranslate3f(0.0f, 0.0f, length - tail);
+ gpuScaleUniform(size1);
+
+ GWN_batch_draw(sphere);
+ gpuPopMatrix();
+
+ gpuPushMatrix();
+ gpuTranslate3f(0.0f, 0.0f, head);
+ gpuScaleUniform(size2);
+
+ GWN_batch_draw(sphere);
+ gpuPopMatrix();
+
+ /* draw cynlinder between spheres */
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -1.0f);
-
- glTranslatef(0.0f, 0.0f, head);
- gluCylinder(qobj, fac1 * head + (1.0f - fac1) * tail, fac2 * tail + (1.0f - fac2) * head, length - head - tail, 16, 1);
- glTranslatef(0.0f, 0.0f, -head);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_SIMPLE_LIGHTING);
+ immUniformColor4fv(fcolor);
+ immUniform3fv("light", light_vec);
+
+ gpuTranslate3f(0.0f, 0.0f, head);
+ imm_draw_cylinder_fill_normal_3d(pos, nor, size2, size1, length - head - tail, 16, 1);
+
+ immUnbindProgram();
glDisable(GL_POLYGON_OFFSET_FILL);
-
- /* draw sphere on extrema */
- glTranslatef(0.0f, 0.0f, length - tail);
- gluSphere(qobj, fac2 * tail + (1.0f - fac2) * head, 16, 10);
- glTranslatef(0.0f, 0.0f, -length + tail);
-
- glTranslatef(0.0f, 0.0f, head);
- gluSphere(qobj, fac1 * head + (1.0f - fac1) * tail, 16, 10);
}
else {
+ size1 = fac1 * head + (1.0f - fac1) * tail;
+
/* 1 sphere in center */
- glTranslatef(0.0f, 0.0f, (head + length - tail) / 2.0f);
- gluSphere(qobj, fac1 * head + (1.0f - fac1) * tail, 16, 10);
- }
-
- /* restore */
- if (dt == OB_SOLID) {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ gpuTranslate3f(0.0f, 0.0f, (head + length - tail) / 2.0f);
+
+ gpuScaleUniform(size1);
+ GWN_batch_draw(sphere);
}
- glPopMatrix();
- gluDeleteQuadric(qobj);
+ gpuPopMatrix();
}
-static GLubyte bm_dot6[] = {0x0, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x0};
-static GLubyte bm_dot8[] = {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C};
-
-static GLubyte bm_dot5[] = {0x0, 0x0, 0x10, 0x38, 0x7c, 0x38, 0x10, 0x0};
-static GLubyte bm_dot7[] = {0x0, 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38};
-
-
static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned int id,
bPoseChannel *pchan, EditBone *ebone)
{
- /* call this once, avoid constant changing */
- BLI_assert(glaGetOneInt(GL_UNPACK_ALIGNMENT) == 1);
-
float length;
if (pchan)
@@ -993,103 +1148,119 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
else
length = ebone->length;
- glPushMatrix();
- glScalef(length, length, length);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ gpuPushMatrix();
+ gpuScaleUniform(length);
/* this chunk not in object mode */
if (armflag & (ARM_EDITMODE | ARM_POSEMODE)) {
glLineWidth(4.0f);
- if (G.f & G_PICKSEL) {
- /* no bitmap in selection mode, crashes 3d cards...
- * instead draw a solid point the same size */
- glPointSize(8.0f);
- }
+ glPointSize(8.0f);
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
else if (armflag & ARM_EDITMODE) {
- UI_ThemeColor(TH_WIRE_EDIT);
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor);
}
-
+
+ /* line */
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(fcolor);
+
+ if (id != -1)
+ GPU_select_load_id(id | BONESEL_BONE);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3f(pos, 0.0f, 1.0f, 0.0f);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+ immUniformColor4fv(fcolor);
+
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
- if (G.f & G_PICKSEL) {
+ if (G.f & G_PICKSEL)
GPU_select_load_id(id | BONESEL_ROOT);
- glBegin(GL_POINTS);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glEnd();
- }
- else {
- glRasterPos3f(0.0f, 0.0f, 0.0f);
- glBitmap(8, 8, 4, 4, 0, 0, bm_dot8);
- }
+
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immEnd();
}
-
- if (id != -1)
- GPU_select_load_id((GLuint) id | BONESEL_BONE);
-
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3f(0.0f, 1.0f, 0.0f);
- glEnd();
-
+
/* tip */
- if (G.f & G_PICKSEL) {
- /* no bitmap in selection mode, crashes 3d cards... */
+ if (G.f & G_PICKSEL)
GPU_select_load_id(id | BONESEL_TIP);
- glBegin(GL_POINTS);
- glVertex3f(0.0f, 1.0f, 0.0f);
- glEnd();
- }
- else {
- glRasterPos3f(0.0f, 1.0f, 0.0f);
- glBitmap(8, 8, 4, 4, 0, 0, bm_dot7);
- }
-
+
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3f(pos, 0.0f, 1.0f, 0.0f);
+ immEnd();
+
+ immUnbindProgram();
+
+
/* further we send no names */
if (id != -1)
GPU_select_load_id(id & 0xFFFF); /* object tag, for bordersel optim */
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_LINEBONE, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_LINEBONE, boneflag, constflag);
}
-
- glLineWidth(2.0);
-
+
+ /* Now draw the inner color */
+ glLineWidth(2.0f);
+ glPointSize(5.0f);
+
+ /* line */
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_SELECTED) UI_GetThemeColor4fv(TH_EDGE_SELECT, fcolor);
+ else UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor);
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(fcolor);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3f(pos, 0.0f, 1.0f, 0.0f);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+
/*Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
- if ((G.f & G_PICKSEL) == 0) {
- /* no bitmap in selection mode, crashes 3d cards... */
- if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
- }
- glRasterPos3f(0.0f, 0.0f, 0.0f);
- glBitmap(8, 8, 4, 4, 0, 0, bm_dot6);
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_ROOTSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ else UI_GetThemeColor4fv(TH_VERTEX, fcolor);
}
+ immUniformColor4fv(fcolor);
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immEnd();
}
-
- if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT);
- else UI_ThemeColorShade(TH_BACK, -30);
- }
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3f(0.0f, 1.0f, 0.0f);
- glEnd();
-
+
/* tip */
if ((G.f & G_PICKSEL) == 0) {
/* no bitmap in selection mode, crashes 3d cards... */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
+ if (boneflag & BONE_TIPSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ else UI_GetThemeColor4fv(TH_VERTEX, fcolor);
}
- glRasterPos3f(0.0f, 1.0f, 0.0f);
- glBitmap(8, 8, 4, 4, 0, 0, bm_dot5);
+ immUniformColor4fv(fcolor);
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3f(pos, 0.0f, 1.0f, 0.0f);
+ immEnd();
}
-
- glPopMatrix();
+
+ immUnbindProgram();
+
+ gpuPopMatrix();
}
/* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings
@@ -1188,18 +1359,16 @@ static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, EditBone *ebo
}
for (a = 0; a < segments; a++) {
- glPushMatrix();
- glMultMatrixf(bbone[a].mat);
+ gpuPushMatrix();
+ gpuMultMatrix(bbone[a].mat);
if (dt == OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
else drawcube_size(xwidth, dlen, zwidth);
- glPopMatrix();
+ gpuPopMatrix();
}
}
else {
- glPushMatrix();
if (dt == OB_SOLID) drawsolidcube_size(xwidth, length, zwidth);
else drawcube_size(xwidth, length, zwidth);
- glPopMatrix();
}
}
@@ -1222,26 +1391,27 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
/* draw points only if... */
if (armflag & ARM_EDITMODE) {
/* move to unitspace */
- glPushMatrix();
- glScalef(length, length, length);
+ gpuPushMatrix();
+ gpuScaleUniform(length);
draw_bone_points(dt, armflag, boneflag, id);
- glPopMatrix();
+ gpuPopMatrix();
length *= 0.95f; /* make vertices visible */
}
/* colors for modes */
if (armflag & ARM_POSEMODE) {
if (dt <= OB_WIRE)
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
else
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
}
else if (armflag & ARM_EDITMODE) {
if (dt == OB_WIRE) {
- set_ebone_glColor(boneflag);
+ set_ebone_color(boneflag);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
}
- else
- UI_ThemeColor(TH_BONE_SOLID);
}
if (id != -1) {
@@ -1250,33 +1420,31 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
/* set up solid drawing */
if (dt > OB_WIRE) {
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
-
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
- else
- UI_ThemeColor(TH_BONE_SOLID);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ }
+ flat_color = false;
draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth);
-
- /* disable solid drawing */
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
else {
/* wire */
if (armflag & ARM_POSEMODE) {
if (constflag && ((G.f & G_PICKSEL) == 0)) {
/* set constraint colors */
- if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
+ if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
glEnable(GL_BLEND);
+ flat_color = true;
draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth);
glDisable(GL_BLEND);
}
/* restore colors */
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
}
}
@@ -1286,33 +1454,41 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float length, int segments)
{
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(fcolor);
+
if ((segments > 1) && (pchan)) {
float dlen = length / (float)segments;
Mat4 *bbone = bbones;
int a;
-
+
for (a = 0; a < segments; a++, bbone++) {
- glPushMatrix();
- glMultMatrixf(bbone->mat);
-
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3f(0.0f, dlen, 0.0f);
- glEnd(); /* GL_LINES */
-
- glPopMatrix();
+ gpuPushMatrix();
+ gpuMultMatrix(bbone->mat);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immVertex3f(pos, 0.0f, dlen, 0.0f);
+ immEnd();
+
+ gpuPopMatrix();
}
}
else {
- glPushMatrix();
-
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3f(0.0f, length, 0.0f);
- glEnd();
-
- glPopMatrix();
+ gpuPushMatrix();
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immVertex3f(pos, 0.0f, length, 0.0f);
+ immEnd();
+
+ gpuPopMatrix();
}
+
+ immUnbindProgram();
}
static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
@@ -1338,10 +1514,11 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
/* draw points only if... */
if (armflag & ARM_EDITMODE) {
/* move to unitspace */
- glPushMatrix();
- glScalef(length, length, length);
+ gpuPushMatrix();
+ gpuScaleUniform(length);
+ flat_color = true;
draw_bone_points(dt, armflag, boneflag, id);
- glPopMatrix();
+ gpuPopMatrix();
length *= 0.95f; /* make vertices visible */
}
@@ -1359,10 +1536,10 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
/* colors for modes */
if (armflag & ARM_POSEMODE) {
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
}
else if (armflag & ARM_EDITMODE) {
- set_ebone_glColor(boneflag);
+ set_ebone_color(boneflag);
}
/* draw normal */
@@ -1372,23 +1549,23 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
static void draw_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, float length)
{
- /* Draw a 3d octahedral bone, we use normalized space based on length,
- * for display-lists */
-
- glScalef(length, length, length);
+ /* Draw a 3d octahedral bone, we use normalized space based on length */
+ gpuScaleUniform(length);
/* set up solid drawing */
if (dt > OB_WIRE) {
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
- UI_ThemeColor(TH_BONE_SOLID);
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ flat_color = false;
}
+ else
+ flat_color = true;
/* colors for posemode */
if (armflag & ARM_POSEMODE) {
if (dt <= OB_WIRE)
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
else
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
}
@@ -1403,12 +1580,12 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag
if (dt <= OB_WIRE) {
/* colors */
if (armflag & ARM_EDITMODE) {
- set_ebone_glColor(boneflag);
+ set_ebone_color(boneflag);
}
else if (armflag & ARM_POSEMODE) {
if (constflag && ((G.f & G_PICKSEL) == 0)) {
/* draw constraint colors */
- if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
+ if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
glEnable(GL_BLEND);
draw_bone_solid_octahedral();
@@ -1417,7 +1594,7 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag
}
/* restore colors */
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
}
}
draw_bone_octahedral();
@@ -1425,35 +1602,33 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag
else {
/* solid */
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
else
- UI_ThemeColor(TH_BONE_SOLID);
- draw_bone_solid_octahedral();
- }
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
- /* disable solid drawing */
- if (dt > OB_WIRE) {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ draw_bone_solid_octahedral();
}
}
-static void draw_custom_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob,
- const short dt, int armflag, int boneflag, unsigned int id, float length)
+static void draw_custom_bone(
+ const struct EvaluationContext *eval_ctx,
+ Scene *scene, ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, Object *ob,
+ const short dt, int armflag, int boneflag, unsigned int id, float length)
{
if (ob == NULL) return;
- glScalef(length, length, length);
+ gpuScaleUniform(length);
/* colors for posemode */
if (armflag & ARM_POSEMODE) {
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, 0);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, 0);
}
if (id != -1) {
GPU_select_load_id((GLuint) id | BONESEL_BONE);
}
-
- draw_object_instance(scene, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE);
+
+ draw_object_instance(eval_ctx, scene, view_layer, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE, fcolor);
}
@@ -1461,7 +1636,20 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
{
bConstraint *con;
bPoseChannel *parchan;
-
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniformColor4fv(fcolor);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
for (con = pchan->constraints.first; con; con = con->next) {
if (con->enforce == 0.0f)
continue;
@@ -1471,47 +1659,45 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
{
bKinematicConstraint *data = (bKinematicConstraint *)con->data;
int segcount = 0;
+ float ik_tip[3];
/* if only_temp, only draw if it is a temporary ik-chain */
if ((only_temp) && !(data->flag & CONSTRAINT_IK_TEMP))
continue;
-
- setlinestyle(3);
- glBegin(GL_LINES);
-
+
/* exclude tip from chain? */
if ((data->flag & CONSTRAINT_IK_TIP) == 0)
parchan = pchan->parent;
else
parchan = pchan;
- glVertex3fv(parchan->pose_tail);
+ copy_v3_v3(ik_tip, parchan->pose_tail);
/* Find the chain's root */
while (parchan->parent) {
segcount++;
- if (segcount == data->rootbone || segcount > 255) {
- break; /* 255 is weak */
- }
+ /* FIXME: revise the breaking conditions */
+ if (segcount == data->rootbone || segcount > 255) break; /* 255 is weak */
parchan = parchan->parent;
}
- if (parchan)
- glVertex3fv(parchan->pose_head);
+
+ if (parchan) {
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(shdr_pos, ik_tip);
+ immVertex3fv(shdr_pos, parchan->pose_head);
+ immEnd();
+ }
- glEnd();
- setlinestyle(0);
break;
}
case CONSTRAINT_TYPE_SPLINEIK:
{
bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
int segcount = 0;
-
- setlinestyle(3);
- glBegin(GL_LINES);
+ float ik_tip[3];
parchan = pchan;
- glVertex3fv(parchan->pose_tail);
+ copy_v3_v3(ik_tip, parchan->pose_tail);
/* Find the chain's root */
while (parchan->parent) {
@@ -1521,18 +1707,21 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
parchan = parchan->parent;
}
/* Only draw line in case our chain is more than one bone long! */
- if (parchan != pchan) /* XXX revise the breaking conditions to only stop at the tail? */
- glVertex3fv(parchan->pose_head);
-
- glEnd();
- setlinestyle(0);
+ if (parchan != pchan) { /* XXX revise the breaking conditions to only stop at the tail? */
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(shdr_pos, ik_tip);
+ immVertex3fv(shdr_pos, parchan->pose_head);
+ immEnd();
+ }
break;
}
}
}
+
+ immUnbindProgram();
}
-static void bgl_sphere_project(float ax, float az)
+static void imm_sphere_project(unsigned int pos, float ax, float az)
{
float dir[3], sine, q3;
@@ -1543,11 +1732,13 @@ static void bgl_sphere_project(float ax, float az)
dir[1] = 1.0f - 2.0f * sine;
dir[2] = ax * q3;
- glVertex3fv(dir);
+ immVertex3fv(pos, dir);
}
-static void draw_dof_ellipse(float ax, float az)
+static void draw_dof_ellipse(unsigned int pos, float ax, float az)
{
+ const int n = 16;
+ const int tri = n * n - 2 * n + 1; /* Yay fancy math ! */
const float staticSine[16] = {
0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f,
0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f,
@@ -1556,15 +1747,15 @@ static void draw_dof_ellipse(float ax, float az)
0.994521895368f, 1.0f
};
- int i, j, n = 16;
+ int i, j;
float x, z, px, pz;
glEnable(GL_BLEND);
glDepthMask(0);
- glColor4ub(70, 70, 70, 50);
+ immUniformColor4ub(70, 70, 70, 50);
- glBegin(GL_QUADS);
+ immBegin(GWN_PRIM_TRIS, tri * 3);
pz = 0.0f;
for (i = 1; i < n; i++) {
z = staticSine[i];
@@ -1574,36 +1765,35 @@ static void draw_dof_ellipse(float ax, float az)
x = staticSine[j];
if (j == n - i) {
- glEnd();
- glBegin(GL_TRIANGLES);
- bgl_sphere_project(ax * px, az * z);
- bgl_sphere_project(ax * px, az * pz);
- bgl_sphere_project(ax * x, az * pz);
- glEnd();
- glBegin(GL_QUADS);
+ imm_sphere_project(pos, ax * px, az * z);
+ imm_sphere_project(pos, ax * px, az * pz);
+ imm_sphere_project(pos, ax * x, az * pz);
}
else {
- bgl_sphere_project(ax * x, az * z);
- bgl_sphere_project(ax * x, az * pz);
- bgl_sphere_project(ax * px, az * pz);
- bgl_sphere_project(ax * px, az * z);
+ imm_sphere_project(pos, ax * x, az * z);
+ imm_sphere_project(pos, ax * x, az * pz);
+ imm_sphere_project(pos, ax * px, az * pz);
+
+ imm_sphere_project(pos, ax * px, az * pz);
+ imm_sphere_project(pos, ax * px, az * z);
+ imm_sphere_project(pos, ax * x, az * z);
}
px = x;
}
pz = z;
}
- glEnd();
+ immEnd();
glDisable(GL_BLEND);
glDepthMask(1);
- glColor3ub(0, 0, 0);
+ immUniformColor3ub(0, 0, 0);
- glBegin(GL_LINE_STRIP);
+ immBegin(GWN_PRIM_LINE_STRIP, n);
for (i = 0; i < n; i++)
- bgl_sphere_project(staticSine[n - i - 1] * ax, staticSine[i] * az);
- glEnd();
+ imm_sphere_project(pos, staticSine[n - i - 1] * ax, staticSine[i] * az);
+ immEnd();
}
static void draw_pose_dofs(Object *ob)
@@ -1611,7 +1801,12 @@ static void draw_pose_dofs(Object *ob)
bArmature *arm = ob->data;
bPoseChannel *pchan;
Bone *bone;
-
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
bone = pchan->bone;
@@ -1625,54 +1820,55 @@ static void draw_pose_dofs(Object *ob)
int a, i;
/* in parent-bone pose, but own restspace */
- glPushMatrix();
+ gpuPushMatrix();
copy_v3_v3(posetrans, pchan->pose_mat[3]);
- glTranslate3fv(posetrans);
+ gpuTranslate3fv(posetrans);
if (pchan->parent) {
copy_m4_m4(mat, pchan->parent->pose_mat);
mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
- glMultMatrixf(mat);
+ gpuMultMatrix(mat);
}
copy_m4_m3(mat, pchan->bone->bone_mat);
- glMultMatrixf(mat);
+ gpuMultMatrix(mat);
scale = bone->length * pchan->size[1];
- glScalef(scale, scale, scale);
+ gpuScaleUniform(scale);
- if (pchan->ikflag & BONE_IK_XLIMIT) {
- if (pchan->ikflag & BONE_IK_ZLIMIT) {
- float amin[3], amax[3];
-
- for (i = 0; i < 3; i++) {
- /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
- amin[i] = sinf(pchan->limitmin[i] * 0.5f);
- amax[i] = sinf(pchan->limitmax[i] * 0.5f);
- }
-
- glScalef(1.0f, -1.0f, 1.0f);
- if ((amin[0] != 0.0f) && (amin[2] != 0.0f))
- draw_dof_ellipse(amin[0], amin[2]);
- if ((amin[0] != 0.0f) && (amax[2] != 0.0f))
- draw_dof_ellipse(amin[0], amax[2]);
- if ((amax[0] != 0.0f) && (amin[2] != 0.0f))
- draw_dof_ellipse(amax[0], amin[2]);
- if ((amax[0] != 0.0f) && (amax[2] != 0.0f))
- draw_dof_ellipse(amax[0], amax[2]);
- glScalef(1.0f, -1.0f, 1.0f);
+ if (((pchan->ikflag & BONE_IK_XLIMIT) != 0) &&
+ ((pchan->ikflag & BONE_IK_ZLIMIT) != 0))
+ {
+ float amin[3], amax[3];
+
+ for (i = 0; i < 3; i++) {
+ /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
+ amin[i] = sinf(pchan->limitmin[i] * 0.5f);
+ amax[i] = sinf(pchan->limitmax[i] * 0.5f);
}
+
+ gpuScale3f(1.0f, -1.0f, 1.0f);
+ if ((amin[0] != 0.0f) && (amin[2] != 0.0f))
+ draw_dof_ellipse(pos, amin[0], amin[2]);
+ if ((amin[0] != 0.0f) && (amax[2] != 0.0f))
+ draw_dof_ellipse(pos, amin[0], amax[2]);
+ if ((amax[0] != 0.0f) && (amin[2] != 0.0f))
+ draw_dof_ellipse(pos, amax[0], amin[2]);
+ if ((amax[0] != 0.0f) && (amax[2] != 0.0f))
+ draw_dof_ellipse(pos, amax[0], amax[2]);
+ gpuScale3f(1.0f, -1.0f, 1.0f); /* XXX same as above, is this intentional? */
}
/* arcs */
if (pchan->ikflag & BONE_IK_ZLIMIT) {
/* OpenGL requires rotations in degrees; so we're taking the average angle here */
theta = RAD2DEGF(0.5f * (pchan->limitmin[2] + pchan->limitmax[2]));
- glRotatef(theta, 0.0f, 0.0f, 1.0f);
+ gpuPushMatrix();
+ gpuRotateAxis(theta, 'Z');
- glColor3ub(50, 50, 255); /* blue, Z axis limit */
- glBegin(GL_LINE_STRIP);
+ immUniformColor3ub(50, 50, 255); /* blue, Z axis limit */
+ immBegin(GWN_PRIM_LINE_STRIP, 33);
for (a = -16; a <= 16; a++) {
/* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
float fac = ((float)a) / 16.0f * 0.5f;
@@ -1683,20 +1879,21 @@ static void draw_pose_dofs(Object *ob)
corner[i][0] = sinf(phi);
corner[i][1] = cosf(phi);
corner[i][2] = 0.0f;
- glVertex3fv(corner[i]);
+ immVertex3fv(pos, corner[i]);
}
- glEnd();
+ immEnd();
- glRotatef(-theta, 0.0f, 0.0f, 1.0f);
+ gpuPopMatrix();
}
if (pchan->ikflag & BONE_IK_XLIMIT) {
/* OpenGL requires rotations in degrees; so we're taking the average angle here */
theta = RAD2DEGF(0.5f * (pchan->limitmin[0] + pchan->limitmax[0]));
- glRotatef(theta, 1.0f, 0.0f, 0.0f);
+ gpuPushMatrix();
+ gpuRotateAxis(theta, 'X');
- glColor3ub(255, 50, 50); /* Red, X axis limit */
- glBegin(GL_LINE_STRIP);
+ immUniformColor3ub(255, 50, 50); /* Red, X axis limit */
+ immBegin(GWN_PRIM_LINE_STRIP, 33);
for (a = -16; a <= 16; a++) {
/* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
float fac = ((float)a) / 16.0f * 0.5f;
@@ -1706,21 +1903,23 @@ static void draw_pose_dofs(Object *ob)
corner[i][0] = 0.0f;
corner[i][1] = sinf(phi);
corner[i][2] = cosf(phi);
- glVertex3fv(corner[i]);
+ immVertex3fv(pos, corner[i]);
}
- glEnd();
+ immEnd();
- glRotatef(-theta, 1.0f, 0.0f, 0.0f);
+ gpuPopMatrix();
}
/* out of cone, out of bone */
- glPopMatrix();
+ gpuPopMatrix();
}
}
}
}
}
}
+
+ immUnbindProgram();
}
static void bone_matrix_translate_y(float mat[4][4], float y)
@@ -1733,9 +1932,10 @@ 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,
- const short dt, const unsigned char ob_wire_col[4],
- const bool do_const_color, const bool is_outline)
+static void draw_pose_bones(
+ const struct EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d, ARegion *ar, Base *base,
+ const short dt, const unsigned char ob_wire_col[4],
+ const bool do_const_color, const bool is_outline)
{
RegionView3D *rv3d = ar->regiondata;
Object *ob = base->object;
@@ -1756,7 +1956,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* being set below */
arm->layer_used = 0;
-
+
+ rgba_uchar_to_float(fcolor, ob_wire_col);
+
/* precalc inverse matrix for drawing screen aligned */
if (arm->drawtype == ARM_ENVELOPE) {
/* precalc inverse matrix for drawing screen aligned */
@@ -1805,7 +2007,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* if solid we draw that first, with selection codes, but without names, axes etc */
if (dt > OB_WIRE) {
if (arm->flag & ARM_POSEMODE)
- index = base->selcol;
+ index = base->object->select_color;
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
bone = pchan->bone;
@@ -1817,13 +2019,13 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
{
if (bone->layer & arm->layer) {
const bool use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM);
- glPushMatrix();
+ gpuPushMatrix();
if (use_custom && pchan->custom_tx) {
- glMultMatrixf(pchan->custom_tx->pose_mat);
+ gpuMultMatrix(pchan->custom_tx->pose_mat);
}
else {
- glMultMatrixf(pchan->pose_mat);
+ gpuMultMatrix(pchan->pose_mat);
}
/* catch exception for bone with hidden parent */
@@ -1858,7 +2060,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
glDisable(GL_CULL_FACE);
}
- draw_custom_bone(scene, v3d, rv3d, pchan->custom,
+ draw_custom_bone(eval_ctx, scene, view_layer, v3d, rv3d, pchan->custom,
OB_SOLID, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
}
}
@@ -1885,7 +2087,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
}
- glPopMatrix();
+ gpuPopMatrix();
}
}
@@ -1913,7 +2115,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
(draw_wire || (dt <= OB_WIRE)) )
{
if (arm->flag & ARM_POSEMODE)
- index = base->selcol;
+ index = base->object->select_color;
/* only draw custom bone shapes that need to be drawn as wires */
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
@@ -1926,13 +2128,13 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (bone->layer & arm->layer) {
if (pchan->custom) {
if ((dt < OB_SOLID) || (bone->flag & BONE_DRAWWIRE)) {
- glPushMatrix();
+ gpuPushMatrix();
if (pchan->custom_tx) {
- glMultMatrixf(pchan->custom_tx->pose_mat);
+ gpuMultMatrix(pchan->custom_tx->pose_mat);
}
else {
- glMultMatrixf(pchan->pose_mat);
+ gpuMultMatrix(pchan->pose_mat);
}
/* prepare colors */
@@ -1942,7 +2144,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
else if (arm->flag & ARM_POSEMODE)
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 */
@@ -1954,10 +2156,10 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (bone == arm->act_bone)
flag |= BONE_DRAW_ACTIVE;
- draw_custom_bone(scene, v3d, rv3d, pchan->custom,
+ draw_custom_bone(eval_ctx, scene, view_layer, v3d, rv3d, pchan->custom,
OB_WIRE, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
- glPopMatrix();
+ gpuPopMatrix();
}
}
}
@@ -1979,7 +2181,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* draw line check first. we do selection indices */
if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
if (arm->flag & ARM_POSEMODE)
- index = base->selcol;
+ index = base->object->select_color;
}
/* if solid && posemode, we draw again with polygonoffset */
else if ((dt > OB_WIRE) && (arm->flag & ARM_POSEMODE)) {
@@ -1988,7 +2190,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
else {
/* and we use selection indices if not done yet */
if (arm->flag & ARM_POSEMODE)
- index = base->selcol;
+ index = base->object->select_color;
}
if (is_cull_enabled == false) {
@@ -2011,16 +2213,30 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
* - only if V3D_HIDE_HELPLINES is enabled...
*/
if ((do_dashed & DASH_HELP_LINES) && ((bone->flag & BONE_CONNECTED) == 0)) {
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniformColor4fv(fcolor);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
if (arm->flag & ARM_POSEMODE) {
GPU_select_load_id(index & 0xFFFF); /* object tag, for bordersel optim */
- UI_ThemeColor(TH_WIRE);
+ immUniformThemeColor(TH_WIRE);
}
- setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(pchan->pose_head);
- glVertex3fv(pchan->parent->pose_tail);
- glEnd();
- setlinestyle(0);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(shdr_pos, pchan->parent->pose_tail);
+ immVertex3fv(shdr_pos, pchan->pose_head);
+ immEnd();
+
+ immUnbindProgram();
}
/* Draw a line to IK root bone
@@ -2029,8 +2245,11 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (arm->flag & ARM_POSEMODE) {
if (constflag & PCHAN_HAS_IK) {
if (bone->flag & BONE_SELECTED) {
- if (constflag & PCHAN_HAS_TARGET) glColor3ub(200, 120, 0);
- else glColor3ub(200, 200, 50); /* add theme! */
+ if (constflag & PCHAN_HAS_TARGET) {
+ rgba_float_args_set(fcolor, 200.f / 255.f, 120.f / 255.f, 0.f / 255.f, 1.0f);
+ }
+ /* add theme! */
+ else rgba_float_args_set(fcolor, 200.f / 255.f, 200.f / 255.f, 50.f / 255.f, 1.0f);
GPU_select_load_id(index & 0xFFFF);
pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES));
@@ -2038,8 +2257,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
else if (constflag & PCHAN_HAS_SPLINEIK) {
if (bone->flag & BONE_SELECTED) {
- glColor3ub(150, 200, 50); /* add theme! */
-
+ /* add theme! */
+ rgba_float_args_set(fcolor, 150.f / 255.f, 200.f / 255.f, 50.f / 255.f, 1.0f);
+
GPU_select_load_id(index & 0xFFFF);
pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES));
}
@@ -2047,9 +2267,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
}
- glPushMatrix();
+ gpuPushMatrix();
if (arm->drawtype != ARM_ENVELOPE)
- glMultMatrixf(pchan->pose_mat);
+ gpuMultMatrix(pchan->pose_mat);
/* catch exception for bone with hidden parent */
flag = bone->flag;
@@ -2086,7 +2306,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
else
draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length);
- glPopMatrix();
+ gpuPopMatrix();
}
}
@@ -2106,7 +2326,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,26 +2334,17 @@ 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) {
float vec[3];
unsigned char col[4];
- if (do_const_color) {
- /* so we can draw bone names in current const color */
- float tcol[4];
- glGetFloatv(GL_CURRENT_COLOR, tcol);
- rgb_float_to_uchar(col, tcol);
- col[3] = 255;
- }
- else {
- col[0] = ob_wire_col[0];
- col[1] = ob_wire_col[1];
- col[2] = ob_wire_col[2];
- col[3] = 255;
- }
+ col[0] = ob_wire_col[0];
+ col[1] = ob_wire_col[1];
+ col[2] = ob_wire_col[2];
+ col[3] = 255;
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
@@ -2156,18 +2367,16 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* Draw additional axes on the bone tail */
if ((arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE)) {
- glPushMatrix();
+ gpuPushMatrix();
copy_m4_m4(bmat, pchan->pose_mat);
bone_matrix_translate_y(bmat, pchan->bone->length);
- glMultMatrixf(bmat);
+ gpuMultMatrix(bmat);
- glColor3ubv(col);
-
float viewmat_pchan[4][4];
mul_m4_m4m4(viewmat_pchan, rv3d->viewmatob, bmat);
- drawaxes(viewmat_pchan, pchan->bone->length * 0.25f, OB_ARROWS);
+ drawaxes(viewmat_pchan, pchan->bone->length * 0.25f, OB_ARROWS, col);
- glPopMatrix();
+ gpuPopMatrix();
}
}
}
@@ -2233,9 +2442,9 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
for (eBone = arm->edbo->first, index = 0; eBone; eBone = eBone->next, index++) {
if (eBone->layer & arm->layer) {
if ((eBone->flag & BONE_HIDDEN_A) == 0) {
- glPushMatrix();
+ gpuPushMatrix();
get_matrix_editbone(eBone, bmat);
- glMultMatrixf(bmat);
+ gpuMultMatrix(bmat);
/* catch exception for bone with hidden parent */
flag = eBone->flag;
@@ -2257,7 +2466,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
}
- glPopMatrix();
+ gpuPopMatrix();
}
}
}
@@ -2295,9 +2504,9 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone);
}
else {
- glPushMatrix();
+ gpuPushMatrix();
get_matrix_editbone(eBone, bmat);
- glMultMatrixf(bmat);
+ gpuMultMatrix(bmat);
if (arm->drawtype == ARM_LINE)
draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
@@ -2308,21 +2517,32 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
else
draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length);
- glPopMatrix();
+ gpuPopMatrix();
}
/* offset to parent */
if (eBone->parent) {
- UI_ThemeColor(TH_WIRE_EDIT);
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
GPU_select_load_id(-1); /* -1 here is OK! */
- setlinestyle(3);
-
- glBegin(GL_LINES);
- glVertex3fv(eBone->parent->tail);
- glVertex3fv(eBone->head);
- glEnd();
-
- setlinestyle(0);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniformThemeColor(TH_WIRE_EDIT);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(shdr_pos, eBone->parent->tail);
+ immVertex3fv(shdr_pos, eBone->head);
+ immEnd();
+
+ immUnbindProgram();
}
}
}
@@ -2364,18 +2584,16 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
}
/* Draw additional axes */
if (arm->flag & ARM_DRAWAXES) {
- glPushMatrix();
+ gpuPushMatrix();
get_matrix_editbone(eBone, bmat);
bone_matrix_translate_y(bmat, eBone->length);
- glMultMatrixf(bmat);
-
- glColor3ubv(col);
+ gpuMultMatrix(bmat);
float viewmat_ebone[4][4];
mul_m4_m4m4(viewmat_ebone, rv3d->viewmatob, bmat);
- drawaxes(viewmat_ebone, eBone->length * 0.25f, OB_ARROWS);
+ drawaxes(viewmat_ebone, eBone->length * 0.25f, OB_ARROWS, col);
- glPopMatrix();
+ gpuPopMatrix();
}
}
@@ -2448,7 +2666,8 @@ 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(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d, ARegion *ar, Base *base)
{
Object *ob = base->object;
AnimData *adt = BKE_animdata_from_id(&ob->id);
@@ -2456,6 +2675,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base
bPose *posen, *poseo;
float start, end, stepsize, range, colfac;
int cfrao, flago;
+ unsigned char col[4];
start = (float)arm->ghostsf;
end = (float)arm->ghostef;
@@ -2488,11 +2708,11 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base
/* draw from first frame of range to last */
for (CFRA = (int)start; CFRA <= end; CFRA += (int)stepsize) {
colfac = (end - (float)CFRA) / range;
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)));
+ UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col);
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
- BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
+ BKE_pose_where_is(eval_ctx, scene, ob);
+ draw_pose_bones(eval_ctx, scene, view_layer, v3d, ar, base, OB_WIRE, col, true, false);
}
glDisable(GL_BLEND);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@ -2514,7 +2734,9 @@ 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(
+ const struct EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ View3D *v3d, ARegion *ar, Base *base)
{
Object *ob = base->object;
AnimData *adt = BKE_animdata_from_id(&ob->id);
@@ -2525,6 +2747,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *
ActKeyColumn *ak, *akn;
float start, end, range, colfac, i;
int cfrao, flago;
+ unsigned char col[4];
start = (float)arm->ghostsf;
end = (float)arm->ghostef;
@@ -2566,13 +2789,13 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *
/* draw from first frame of range to last */
for (ak = keys.first, i = 0; ak; ak = ak->next, i++) {
colfac = i / range;
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)));
+ UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col);
CFRA = (int)ak->cfra;
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
- BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
+ BKE_pose_where_is(eval_ctx, scene, ob);
+ draw_pose_bones(eval_ctx, scene, view_layer, v3d, ar, base, OB_WIRE, col, true, false);
}
glDisable(GL_BLEND);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@ -2595,7 +2818,9 @@ 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(
+ const struct EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ View3D *v3d, ARegion *ar, Base *base)
{
Object *ob = base->object;
AnimData *adt = BKE_animdata_from_id(&ob->id);
@@ -2603,7 +2828,8 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
bPose *posen, *poseo;
float cur, start, end, stepsize, range, colfac, actframe, ctime;
int cfrao, flago;
-
+ unsigned char col[4];
+
/* pre conditions, get an action with sufficient frames */
if (ELEM(NULL, adt, adt->action))
return;
@@ -2640,7 +2866,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
for (cur = stepsize; cur < range; cur += stepsize) {
ctime = cur - (float)fmod(cfrao, stepsize); /* ensures consistent stepping */
colfac = ctime / range;
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)));
+ UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col);
/* only within action range */
if (actframe + ctime >= start && actframe + ctime <= end) {
@@ -2648,14 +2874,14 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
if (CFRA != cfrao) {
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
- BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
+ BKE_pose_where_is(eval_ctx, scene, ob);
+ draw_pose_bones(eval_ctx, scene, view_layer, v3d, ar, base, OB_WIRE, col, true, false);
}
}
ctime = cur + (float)fmod((float)cfrao, stepsize) - stepsize + 1.0f; /* ensures consistent stepping */
colfac = ctime / range;
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)));
+ UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col);
/* only within action range */
if ((actframe - ctime >= start) && (actframe - ctime <= end)) {
@@ -2663,8 +2889,8 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
if (CFRA != cfrao) {
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
- BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
+ BKE_pose_where_is(eval_ctx, scene, ob);
+ draw_pose_bones(eval_ctx, scene, view_layer, v3d, ar, base, OB_WIRE, col, true, false);
}
}
}
@@ -2689,9 +2915,10 @@ 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,
- const short dt, const short dflag, const unsigned char ob_wire_col[4],
- const bool is_outline)
+bool draw_armature(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d, ARegion *ar, Base *base,
+ const short dt, const short dflag, const unsigned char ob_wire_col[4],
+ const bool is_outline)
{
Object *ob = base->object;
bArmature *arm = ob->data;
@@ -2700,11 +2927,7 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (v3d->flag2 & V3D_RENDER_OVERRIDE)
return true;
- /* needed for 'draw_line_bone' which draws pixel. */
- if (arm->drawtype == ARM_LINE) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- }
-
+#if 0 /* Not used until lighting is properly reimplemented */
if (dt > OB_WIRE) {
/* we use color for solid lighting */
if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
@@ -2719,7 +2942,8 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); /* only for lighting... */
}
}
-
+#endif
+
/* arm->flag is being used to detect mode... */
/* editmode? */
if (arm->edbo) {
@@ -2736,7 +2960,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 */
@@ -2752,31 +2976,28 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
else if (ob->mode & OB_MODE_POSE) {
if (arm->ghosttype == ARM_GHOST_RANGE) {
- draw_ghost_poses_range(scene, v3d, ar, base);
+ draw_ghost_poses_range(eval_ctx, scene, view_layer, v3d, ar, base);
}
else if (arm->ghosttype == ARM_GHOST_KEYS) {
- draw_ghost_poses_keys(scene, v3d, ar, base);
+ draw_ghost_poses_keys(eval_ctx, scene, view_layer, v3d, ar, base);
}
else if (arm->ghosttype == ARM_GHOST_CUR) {
if (arm->ghostep)
- draw_ghost_poses(scene, v3d, ar, base);
+ draw_ghost_poses(eval_ctx, scene, view_layer, v3d, ar, base);
}
if ((dflag & DRAW_SCENESET) == 0) {
- if (ob == OBACT)
+ if (ob == OBACT(view_layer))
arm->flag |= ARM_POSEMODE;
- else if (OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) {
- if (ob == modifiers_isDeformedByArmature(OBACT))
+ else if (OBACT(view_layer) && (OBACT(view_layer)->mode & OB_MODE_WEIGHT_PAINT)) {
+ if (ob == modifiers_isDeformedByArmature(OBACT(view_layer)))
arm->flag |= ARM_POSEMODE;
}
draw_pose_paths(scene, v3d, ar, ob);
}
}
}
- draw_pose_bones(scene, v3d, ar, base, dt, ob_wire_col, (dflag & DRAW_CONSTCOLOR), is_outline);
+ draw_pose_bones(eval_ctx, scene, view_layer, v3d, ar, base, dt, ob_wire_col, (dflag & DRAW_CONSTCOLOR), is_outline);
arm->flag &= ~ARM_POSEMODE;
-
- if (ob->mode & OB_MODE_POSE)
- UI_ThemeColor(TH_WIRE); /* restore, for extra draw stuff */
}
else {
retval = true;
@@ -2785,9 +3006,5 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* restore */
glFrontFace(GL_CCW);
- if (arm->drawtype == ARM_LINE) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- }
-
return retval;
}
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index bbbf8c633bd..f8f2d5598de 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -55,7 +55,6 @@
#include "BKE_editmesh.h"
#include "BKE_scene.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "UI_resources.h"
@@ -64,6 +63,7 @@
#include "GPU_material.h"
#include "GPU_basic_shader.h"
#include "GPU_shader.h"
+#include "GPU_matrix.h"
#include "RE_engine.h"
@@ -77,20 +77,6 @@ typedef struct drawMeshFaceSelect_userData {
BLI_bitmap *edge_flags; /* pairs of edge options (visible, select) */
} drawMeshFaceSelect_userData;
-typedef struct drawEMTFMapped_userData {
- BMEditMesh *em;
- bool has_mcol;
- int cd_poly_tex_offset;
- const MPoly *mpoly;
- const MTexPoly *mtexpoly;
-} drawEMTFMapped_userData;
-
-typedef struct drawTFace_userData {
- const Mesh *me;
- const MPoly *mpoly;
- const MTexPoly *mtexpoly;
-} drawTFace_userData;
-
/**************************** Face Select Mode *******************************/
/* mainly to be less confusing */
@@ -213,562 +199,6 @@ void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm, bool d
/***************************** Texture Drawing ******************************/
-static Material *give_current_material_or_def(Object *ob, int matnr)
-{
- extern Material defmaterial; /* render module abuse... */
- Material *ma = give_current_material(ob, matnr);
-
- return ma ? ma : &defmaterial;
-}
-
-/* Icky globals, fix with userdata parameter */
-
-static struct TextureDrawState {
- Object *ob;
- Image *stencil; /* texture painting stencil */
- Image *canvas; /* texture painting canvas, for image mode */
- bool use_game_mat;
- int is_lit, is_tex;
- int color_profile;
- bool use_backface_culling;
- bool two_sided_lighting;
- unsigned char obcol[4];
- bool is_texpaint;
- bool texpaint_material; /* use material slots for texture painting */
-} Gtexdraw = {NULL, NULL, NULL, false, 0, 0, 0, false, false, {0, 0, 0, 0}, false, false};
-
-static bool set_draw_settings_cached(
- int clearcache, MTexPoly *texface, Material *ma,
- const struct TextureDrawState *gtexdraw)
-{
- static Material *c_ma;
- static int c_textured;
- static MTexPoly c_texface;
- static int c_backculled;
- static bool c_badtex;
- static int c_lit;
- static int c_has_texface;
-
- int backculled = 1;
- int alphablend = GPU_BLEND_SOLID;
- int textured = 0;
- int lit = 0;
- int has_texface = texface != NULL;
- bool need_set_tpage = false;
- bool texpaint = ((gtexdraw->ob->mode & OB_MODE_TEXTURE_PAINT) != 0);
-
- Image *ima = NULL;
-
- if (ma != NULL) {
- if (ma->mode & MA_TRANSP) {
- alphablend = GPU_BLEND_ALPHA;
- }
- }
-
- if (clearcache) {
- c_textured = c_lit = c_backculled = -1;
- memset(&c_texface, 0, sizeof(c_texface));
- c_badtex = false;
- c_has_texface = -1;
- c_ma = NULL;
- }
- else {
- textured = gtexdraw->is_tex;
- }
-
- /* convert number of lights into boolean */
- if (gtexdraw->is_lit) {
- lit = 1;
- }
-
- backculled = gtexdraw->use_backface_culling;
- if (ma) {
- if (ma->mode & MA_SHLESS) lit = 0;
- if (gtexdraw->use_game_mat) {
- backculled = backculled || (ma->game.flag & GEMAT_BACKCULL);
- alphablend = ma->game.alpha_blend;
- }
- }
-
- if (texface && !texpaint) {
- textured = textured && (texface->tpage);
-
- /* no material, render alpha if texture has depth=32 */
- if (!ma && BKE_image_has_alpha(texface->tpage))
- alphablend = GPU_BLEND_ALPHA;
- }
- else if (texpaint) {
- if (gtexdraw->texpaint_material)
- ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
- else
- ima = gtexdraw->canvas;
- }
- else
- textured = 0;
-
- if (backculled != c_backculled) {
- if (backculled) glEnable(GL_CULL_FACE);
- else glDisable(GL_CULL_FACE);
-
- c_backculled = backculled;
- }
-
- /* need to re-set tpage if textured flag changed or existsment of texface changed.. */
- need_set_tpage = textured != c_textured || has_texface != c_has_texface;
- /* ..or if settings inside texface were changed (if texface was used) */
- need_set_tpage |= (texpaint && c_ma != ma) || (texface && memcmp(&c_texface, texface, sizeof(c_texface)));
-
- if (need_set_tpage) {
- if (textured) {
- if (texpaint) {
- c_badtex = false;
- if (GPU_verify_image(ima, NULL, GL_TEXTURE_2D, 0, 1, 0, false)) {
- glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
-
- glActiveTexture(GL_TEXTURE1);
- glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS);
- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
- glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]);
- glActiveTexture(GL_TEXTURE0);
- }
- else {
- glActiveTexture(GL_TEXTURE1);
- glDisable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, 0);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glActiveTexture(GL_TEXTURE0);
-
- c_badtex = true;
- GPU_clear_tpage(true);
- glDisable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, 0);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- }
- }
- else {
- c_badtex = !GPU_set_tpage(texface, !texpaint, alphablend);
- }
- }
- else {
- GPU_set_tpage(NULL, 0, 0);
- c_badtex = false;
- }
- c_textured = textured;
- c_has_texface = has_texface;
- if (texface)
- memcpy(&c_texface, texface, sizeof(c_texface));
- }
-
- if (c_badtex) lit = 0;
- if (lit != c_lit || ma != c_ma || textured != c_textured) {
- int options = GPU_SHADER_USE_COLOR;
-
- if (c_textured && !c_badtex) {
- options |= GPU_SHADER_TEXTURE_2D;
- }
- if (gtexdraw->two_sided_lighting) {
- options |= GPU_SHADER_TWO_SIDED;
- }
-
- if (lit) {
- options |= GPU_SHADER_LIGHTING;
- if (!ma)
- ma = give_current_material_or_def(NULL, 0); /* default material */
-
- float specular[3];
- mul_v3_v3fl(specular, &ma->specr, ma->spec);
-
- GPU_basic_shader_colors(NULL, specular, ma->har, 1.0f);
- }
-
- GPU_basic_shader_bind(options);
-
- c_lit = lit;
- c_ma = ma;
- }
-
- return c_badtex;
-}
-
-static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
-{
- unsigned char obcol[4];
- bool is_tex, solidtex;
- Mesh *me = ob->data;
- ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
-
- /* XXX scene->obedit warning */
-
- /* texture draw is abused for mask selection mode, do this so wire draw
- * with face selection in weight paint is not lit. */
- if ((v3d->drawtype <= OB_WIRE) && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT))) {
- solidtex = false;
- Gtexdraw.is_lit = 0;
- }
- else if ((ob->mode & OB_MODE_TEXTURE_PAINT) && BKE_scene_use_new_shading_nodes(scene)) {
- solidtex = true;
- if (v3d->flag2 & V3D_SHADELESS_TEX)
- Gtexdraw.is_lit = 0;
- else
- Gtexdraw.is_lit = -1;
- }
- else if ((v3d->drawtype == OB_SOLID) ||
- ((ob->mode & OB_MODE_EDIT) && (v3d->drawtype != OB_TEXTURE)))
- {
- /* draw with default lights in solid draw mode and edit mode */
- solidtex = true;
- Gtexdraw.is_lit = -1;
- }
- else {
- /* draw with lights in the scene otherwise */
- solidtex = false;
- if (v3d->flag2 & V3D_SHADELESS_TEX) {
- Gtexdraw.is_lit = 0;
- }
- else {
- Gtexdraw.is_lit = GPU_scene_object_lights(
- scene, ob, v3d->localvd ? v3d->localvd->lay : v3d->lay,
- rv3d->viewmat, !rv3d->is_persp);
- }
- }
-
- rgba_float_to_uchar(obcol, ob->col);
-
- if (solidtex || v3d->drawtype == OB_TEXTURE) is_tex = true;
- else is_tex = false;
-
- Gtexdraw.ob = ob;
- Gtexdraw.stencil = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? imapaint->stencil : NULL;
- Gtexdraw.is_texpaint = (ob->mode == OB_MODE_TEXTURE_PAINT);
- Gtexdraw.texpaint_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
- Gtexdraw.canvas = (Gtexdraw.texpaint_material) ? NULL : imapaint->canvas;
- Gtexdraw.is_tex = is_tex;
-
- /* naughty multitexturing hacks to quickly support stencil + shading + alpha blending
- * in new texpaint code. The better solution here would be to support GLSL */
- if (Gtexdraw.is_texpaint) {
- glActiveTexture(GL_TEXTURE1);
- glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS);
- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
-
- /* load the stencil texture here */
- if (Gtexdraw.stencil != NULL) {
- glActiveTexture(GL_TEXTURE2);
- if (GPU_verify_image(Gtexdraw.stencil, NULL, GL_TEXTURE_2D, false, false, false, false)) {
- float col[4] = {imapaint->stencil_col[0], imapaint->stencil_col[1], imapaint->stencil_col[2], 1.0f};
- glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE);
- glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
- glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
- glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, col);
- if ((imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) == 0) {
- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_ONE_MINUS_SRC_COLOR);
- }
- else {
- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
- }
- }
- }
- glActiveTexture(GL_TEXTURE0);
- }
-
- Gtexdraw.color_profile = BKE_scene_check_color_management_enabled(scene);
- Gtexdraw.use_game_mat = (RE_engines_find(scene->r.engine)->flag & RE_GAME) != 0;
- Gtexdraw.use_backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0;
- Gtexdraw.two_sided_lighting = (me->flag & ME_TWOSIDED);
-
- memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
- set_draw_settings_cached(1, NULL, NULL, &Gtexdraw);
- glCullFace(GL_BACK);
-}
-
-static void draw_textured_end(void)
-{
- if (Gtexdraw.ob->mode & OB_MODE_TEXTURE_PAINT) {
- glActiveTexture(GL_TEXTURE1);
- glDisable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- if (Gtexdraw.stencil != NULL) {
- glActiveTexture(GL_TEXTURE2);
- glDisable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glBindTexture(GL_TEXTURE_2D, 0);
- }
- glActiveTexture(GL_TEXTURE0);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- /* manual reset, since we don't use tpage */
- glBindTexture(GL_TEXTURE_2D, 0);
- /* force switch off textures */
- GPU_clear_tpage(true);
- }
- else {
- /* switch off textures */
- GPU_set_tpage(NULL, 0, 0);
- }
-
- glDisable(GL_CULL_FACE);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-
- /* XXX, bad patch - GPU_default_lights() calls
- * glLightfv(GL_POSITION, ...) which
- * is transformed by the current matrix... we
- * need to make sure that matrix is identity.
- *
- * It would be better if drawmesh.c kept track
- * of and restored the light settings it changed.
- * - zr
- */
- glPushMatrix();
- glLoadIdentity();
- GPU_default_lights();
- glPopMatrix();
-}
-
-static DMDrawOption draw_tface__set_draw_legacy(MTexPoly *mtexpoly, const bool has_mcol, int matnr)
-{
- Material *ma = give_current_material(Gtexdraw.ob, matnr + 1);
- bool invalidtexture = false;
-
- if (ma && (ma->game.flag & GEMAT_INVISIBLE))
- return DM_DRAW_OPTION_SKIP;
-
- invalidtexture = set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw);
-
- if (mtexpoly && invalidtexture) {
- glColor3ub(0xFF, 0x00, 0xFF);
- return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
- }
- else if (!has_mcol) {
- if (mtexpoly) {
- glColor3f(1.0, 1.0, 1.0);
- }
- else {
- if (ma) {
- if (ma->shade_flag & MA_OBCOLOR) {
- glColor3ubv(Gtexdraw.obcol);
- }
- else {
- float col[3];
- if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
- else copy_v3_v3(col, &ma->r);
-
- glColor3fv(col);
- }
- }
- else {
- glColor3f(1.0, 1.0, 1.0);
- }
- }
- return DM_DRAW_OPTION_NORMAL; /* normal drawing (no mcols anyway, no need to turn off) */
- }
- else {
- return DM_DRAW_OPTION_NORMAL; /* Set color from mcol */
- }
-}
-
-static DMDrawOption draw_tface__set_draw(MTexPoly *mtexpoly, const bool UNUSED(has_mcol), int matnr)
-{
- Material *ma = give_current_material(Gtexdraw.ob, matnr + 1);
-
- if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return DM_DRAW_OPTION_SKIP;
-
- if (mtexpoly || Gtexdraw.is_texpaint)
- set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw);
-
- /* always use color from mcol, as set in update_tface_color_layer */
- return DM_DRAW_OPTION_NORMAL;
-}
-
-static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol)
-{
- const MPoly *mp = dm->getPolyArray(dm);
- const int mpoly_num = dm->getNumPolys(dm);
- MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
- MLoopCol *finalCol;
- int i, j;
- MLoopCol *mloopcol = NULL;
-
- /* cache material values to avoid a lot of lookups */
- Material *ma = NULL;
- short mat_nr_prev = -1;
- enum {
- COPY_CALC,
- COPY_ORIG,
- COPY_PREV,
- } copy_mode = COPY_CALC;
-
- if (use_mcol) {
- mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL);
- if (!mloopcol)
- mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL);
- }
-
- if (CustomData_has_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL)) {
- finalCol = CustomData_get_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL);
- }
- else {
- finalCol = MEM_mallocN(sizeof(MLoopCol) * dm->numLoopData, "add_tface_color_layer");
- CustomData_add_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL, CD_ASSIGN, finalCol, dm->numLoopData);
- }
-
- for (i = mpoly_num; i--; mp++) {
- const short mat_nr = mp->mat_nr;
-
- if (UNLIKELY(mat_nr_prev != mat_nr)) {
- ma = give_current_material(Gtexdraw.ob, mat_nr + 1);
- copy_mode = COPY_CALC;
- mat_nr_prev = mat_nr;
- }
-
- /* avoid lookups */
- if (copy_mode == COPY_ORIG) {
- memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
- }
- else if (copy_mode == COPY_PREV) {
- int loop_index = mp->loopstart;
- const MLoopCol *lcol_prev = &finalCol[(mp - 1)->loopstart];
- for (j = 0; j < mp->totloop; j++, loop_index++) {
- finalCol[loop_index] = *lcol_prev;
- }
- }
-
- /* (copy_mode == COPY_CALC) */
- else if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
- if (mloopcol) {
- memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
- copy_mode = COPY_ORIG;
- }
- else {
- memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
- copy_mode = COPY_PREV;
- }
- }
- else if (mtexpoly && set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw)) {
- int loop_index = mp->loopstart;
- for (j = 0; j < mp->totloop; j++, loop_index++) {
- finalCol[loop_index].r = 255;
- finalCol[loop_index].g = 0;
- finalCol[loop_index].b = 255;
- finalCol[loop_index].a = 255;
- }
- copy_mode = COPY_PREV;
- }
- else if (ma && (ma->shade_flag & MA_OBCOLOR)) {
- int loop_index = mp->loopstart;
- for (j = 0; j < mp->totloop; j++, loop_index++) {
- copy_v3_v3_uchar(&finalCol[loop_index].r, Gtexdraw.obcol);
- finalCol[loop_index].a = 255;
- }
- copy_mode = COPY_PREV;
- }
- else {
- if (mloopcol) {
- memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
- copy_mode = COPY_ORIG;
- }
- else if (mtexpoly) {
- memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
- copy_mode = COPY_PREV;
- }
- else {
- float col[3];
-
- if (ma) {
- int loop_index = mp->loopstart;
- MLoopCol lcol;
-
- if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
- else copy_v3_v3(col, &ma->r);
- rgb_float_to_uchar((unsigned char *)&lcol.r, col);
- lcol.a = 255;
-
- for (j = 0; j < mp->totloop; j++, loop_index++) {
- finalCol[loop_index] = lcol;
- }
- }
- else {
- memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
- }
- copy_mode = COPY_PREV;
- }
- }
- }
-
- dm->dirty |= DM_DIRTY_MCOL_UPDATE_DRAW;
-}
-
-static DMDrawOption draw_tface_mapped__set_draw(void *userData, int origindex, int UNUSED(mat_nr))
-{
- const Mesh *me = ((drawTFace_userData *)userData)->me;
-
- /* array checked for NULL before calling */
- MPoly *mpoly = &me->mpoly[origindex];
-
- BLI_assert(origindex >= 0 && origindex < me->totpoly);
-
- if (mpoly->flag & ME_HIDE) {
- return DM_DRAW_OPTION_SKIP;
- }
- else {
- MTexPoly *tpoly = (me->mtpoly) ? &me->mtpoly[origindex] : NULL;
- int matnr = mpoly->mat_nr;
-
- return draw_tface__set_draw(tpoly, (me->mloopcol != NULL), matnr);
- }
-}
-
-static DMDrawOption draw_em_tf_mapped__set_draw(void *userData, int origindex, int mat_nr)
-{
- drawEMTFMapped_userData *data = userData;
- BMEditMesh *em = data->em;
- BMFace *efa;
-
- if (UNLIKELY(origindex >= em->bm->totface))
- return DM_DRAW_OPTION_NORMAL;
-
- efa = BM_face_at_index(em->bm, origindex);
-
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- return DM_DRAW_OPTION_SKIP;
- }
- else {
- MTexPoly *mtexpoly = (data->cd_poly_tex_offset != -1) ?
- BM_ELEM_CD_GET_VOID_P(efa, data->cd_poly_tex_offset) : NULL;
- int matnr = (mat_nr != -1) ? mat_nr : efa->mat_nr;
-
- return draw_tface__set_draw_legacy(mtexpoly, data->has_mcol, matnr);
- }
-}
-
/* when face select is on, use face hidden flag */
static DMDrawOption wpaint__setSolidDrawOptions_facemask(void *userData, int index)
{
@@ -779,288 +209,6 @@ static DMDrawOption wpaint__setSolidDrawOptions_facemask(void *userData, int ind
return DM_DRAW_OPTION_NORMAL;
}
-static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
-{
- Mesh *me = ob->data;
- DerivedMesh *ddm;
- MPoly *mp, *mface = me->mpoly;
- MTexPoly *mtpoly = me->mtpoly;
- MLoopUV *mloopuv = me->mloopuv;
- MLoopUV *luv;
- MLoopCol *mloopcol = me->mloopcol; /* why does mcol exist? */
- MLoopCol *lcol;
-
- bProperty *prop = BKE_bproperty_object_get(ob, "Text");
- GPUVertexAttribs gattribs;
- int a, totpoly = me->totpoly;
-
- /* fake values to pass to GPU_render_text() */
- MCol tmp_mcol[4] = {{0}};
- MCol *tmp_mcol_pt = mloopcol ? tmp_mcol : NULL;
-
- /* don't draw without tfaces */
- if (!mtpoly || !mloopuv)
- return;
-
- /* don't draw when editing */
- if (ob->mode & OB_MODE_EDIT)
- return;
- else if (ob == OBACT)
- if (BKE_paint_select_elem_test(ob))
- return;
-
- ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
-
- for (a = 0, mp = mface; a < totpoly; a++, mtpoly++, mp++) {
- short matnr = mp->mat_nr;
- const bool mf_smooth = (mp->flag & ME_SMOOTH) != 0;
- Material *mat = (me->mat) ? me->mat[matnr] : NULL;
- int mode = mat ? mat->game.flag : GEMAT_INVISIBLE;
-
-
- if (!(mode & GEMAT_INVISIBLE) && (mode & GEMAT_TEXT) && mp->totloop >= 3) {
- /* get the polygon as a tri/quad */
- int mp_vi[4];
- float v_quad_data[4][3];
- const float *v_quad[4];
- const float *uv_quad[4];
- char string[MAX_PROPSTRING];
- int characters, i, glattrib = -1, badtex = 0;
-
-
- /* TEXFACE */
- if (glsl) {
- GPU_object_material_bind(matnr + 1, &gattribs);
-
- for (i = 0; i < gattribs.totlayer; i++) {
- if (gattribs.layer[i].type == CD_MTFACE) {
- glattrib = gattribs.layer[i].glindex;
- break;
- }
- }
- }
- else {
- badtex = set_draw_settings_cached(0, mtpoly, mat, &Gtexdraw);
- if (badtex) {
- continue;
- }
- }
-
- mp_vi[0] = me->mloop[mp->loopstart + 0].v;
- mp_vi[1] = me->mloop[mp->loopstart + 1].v;
- mp_vi[2] = me->mloop[mp->loopstart + 2].v;
- mp_vi[3] = (mp->totloop >= 4) ? me->mloop[mp->loopstart + 3].v : 0;
-
- /* UV */
- luv = &mloopuv[mp->loopstart];
- uv_quad[0] = luv->uv; luv++;
- uv_quad[1] = luv->uv; luv++;
- uv_quad[2] = luv->uv; luv++;
- if (mp->totloop >= 4) {
- uv_quad[3] = luv->uv;
- }
- else {
- uv_quad[3] = NULL;
- }
-
-
- /* COLOR */
- if (mloopcol) {
- unsigned int totloop_clamp = min_ii(4, mp->totloop);
- unsigned int j;
- lcol = &mloopcol[mp->loopstart];
-
- for (j = 0; j < totloop_clamp; j++, lcol++) {
- MESH_MLOOPCOL_TO_MCOL(lcol, &tmp_mcol[j]);
- }
- }
-
- /* LOCATION */
- ddm->getVertCo(ddm, mp_vi[0], v_quad_data[0]);
- ddm->getVertCo(ddm, mp_vi[1], v_quad_data[1]);
- ddm->getVertCo(ddm, mp_vi[2], v_quad_data[2]);
- if (mp->totloop >= 4) {
- ddm->getVertCo(ddm, mp_vi[3], v_quad_data[3]);
- }
-
- v_quad[0] = v_quad_data[0];
- v_quad[1] = v_quad_data[1];
- v_quad[2] = v_quad_data[2];
- if (mp->totloop >= 4) {
- v_quad[3] = v_quad_data[2];
- }
- else {
- v_quad[3] = NULL;
- }
-
-
- /* The BM_FONT handling is in the gpu module, shared with the
- * game engine, was duplicated previously */
-
- BKE_bproperty_set_valstr(prop, string);
- characters = strlen(string);
-
- if (!BKE_image_has_ibuf(mtpoly->tpage, NULL))
- characters = 0;
-
- if (!mf_smooth) {
- float nor[3];
-
- normal_tri_v3(nor, v_quad[0], v_quad[1], v_quad[2]);
-
- glNormal3fv(nor);
- }
-
- GPU_render_text(
- mtpoly, mode, string, characters,
- (unsigned int *)tmp_mcol_pt,
- v_quad, uv_quad,
- glattrib);
- }
- }
-
- ddm->release(ddm);
-}
-
-static int compareDrawOptions(void *userData, int cur_index, int next_index)
-{
- drawTFace_userData *data = userData;
-
- if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr)
- return 0;
-
- if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage)
- return 0;
-
- return 1;
-}
-
-
-static int compareDrawOptionsEm(void *userData, int cur_index, int next_index)
-{
- drawEMTFMapped_userData *data = userData;
-
- if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr)
- return 0;
-
- if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage)
- return 0;
-
- return 1;
-}
-
-static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d,
- Object *ob, DerivedMesh *dm, const int draw_flags)
-{
- Mesh *me = ob->data;
-
- /* correct for negative scale */
- if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
- else glFrontFace(GL_CCW);
-
- /* draw the textured mesh */
- draw_textured_begin(scene, v3d, rv3d, ob);
-
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
-
- if (ob->mode & OB_MODE_EDIT) {
- drawEMTFMapped_userData data;
-
- data.em = me->edit_btmesh;
- data.has_mcol = CustomData_has_layer(&me->edit_btmesh->bm->ldata, CD_MLOOPCOL);
- data.cd_poly_tex_offset = CustomData_get_offset(&me->edit_btmesh->bm->pdata, CD_MTEXPOLY);
-
- data.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY);
- data.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
-
- dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data, 0);
- }
- else {
- DMDrawFlag dm_draw_flag;
- drawTFace_userData userData;
-
- if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- dm_draw_flag = DM_DRAW_USE_TEXPAINT_UV;
- }
- else {
- dm_draw_flag = DM_DRAW_USE_ACTIVE_UV;
- }
-
- if (ob == OBACT) {
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- dm_draw_flag |= DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH | DM_DRAW_SKIP_HIDDEN;
- }
- else if (ob->mode & OB_MODE_SCULPT) {
- dm_draw_flag |= DM_DRAW_SKIP_HIDDEN | DM_DRAW_USE_COLORS;
- }
- else if ((ob->mode & OB_MODE_TEXTURE_PAINT) == 0) {
- dm_draw_flag |= DM_DRAW_USE_COLORS;
- }
- }
- else {
- if ((ob->mode & OB_MODE_TEXTURE_PAINT) == 0) {
- dm_draw_flag |= DM_DRAW_USE_COLORS;
- }
- }
-
-
- userData.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY);
- userData.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
-
- if (draw_flags & DRAW_FACE_SELECT) {
- userData.me = me;
-
- dm->drawMappedFacesTex(
- dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions,
- &userData, dm_draw_flag);
- }
- else {
- userData.me = NULL;
-
- /* if ((ob->mode & OB_MODE_ALL_PAINT) == 0) */ {
-
- /* Note: this isn't efficient and runs on every redraw,
- * its needed so material colors are used for vertex colors.
- * In the future we will likely remove 'texface' so, just avoid running this where possible,
- * (when vertex paint or weight paint are used).
- *
- * Note 2: We disable optimization for now since it causes T48788
- * and it is now too close to release to do something smarter.
- *
- * TODO(sergey): Find some real solution here.
- */
-
- update_tface_color_layer(dm, !(ob->mode & OB_MODE_TEXTURE_PAINT));
- }
-
- dm->drawFacesTex(
- dm, draw_tface__set_draw, compareDrawOptions,
- &userData, dm_draw_flag);
- }
- }
-
- /* draw game engine text hack */
- if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
- if (BKE_bproperty_object_get(ob, "Text")) {
- draw_mesh_text(scene, ob, 0);
- }
- }
-
- draw_textured_end();
-
- /* draw edges and selected faces over textured mesh */
- if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT)) {
- bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0;
- draw_mesh_face_select(rv3d, me, dm, draw_select_edges);
- }
-
- /* reset from negative scale correction */
- glFrontFace(GL_CCW);
-
- /* in editmode, the blend mode needs to be set in case it was ADD */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-}
-
/************************** NEW SHADING NODES ********************************/
typedef struct TexMatCallback {
@@ -1072,187 +220,11 @@ typedef struct TexMatCallback {
bool two_sided_lighting;
} TexMatCallback;
-static void tex_mat_set_material_cb(void *UNUSED(userData), int mat_nr, void *attribs)
-{
- /* all we have to do here is simply enable the GLSL material, but note
- * that the GLSL code will give different result depending on the drawtype,
- * in texture draw mode it will output the active texture node, in material
- * draw mode it will show the full material. */
- GPU_object_material_bind(mat_nr, attribs);
-}
-
-static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
-{
- /* texture draw mode without GLSL */
- TexMatCallback *data = (TexMatCallback *)userData;
- GPUVertexAttribs *gattribs = attribs;
- Image *ima;
- ImageUser *iuser;
- bNode *node;
-
- /* draw image texture if we find one */
- if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node, NULL)) {
- /* get openl texture */
- int mipmap = 1;
- int bindcode = (ima) ? GPU_verify_image(ima, iuser, GL_TEXTURE_2D, 0, 0, mipmap, false) : 0;
-
- if (bindcode) {
- NodeTexBase *texbase = node->storage;
-
- /* disable existing material */
- GPU_object_material_unbind();
-
- /* bind texture */
- glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]);
-
- glMatrixMode(GL_TEXTURE);
- glLoadMatrixf(texbase->tex_mapping.mat);
- glMatrixMode(GL_MODELVIEW);
-
- /* use active UV texture layer */
- memset(gattribs, 0, sizeof(*gattribs));
-
- gattribs->layer[0].type = CD_MTFACE;
- gattribs->layer[0].name[0] = '\0';
- gattribs->layer[0].gltexco = 1;
- gattribs->totlayer = 1;
-
- /* bind material */
- float diffuse[3] = {1.0f, 1.0f, 1.0f};
-
- int options = GPU_SHADER_TEXTURE_2D;
- if (!data->shadeless)
- options |= GPU_SHADER_LIGHTING;
- if (data->two_sided_lighting)
- options |= GPU_SHADER_TWO_SIDED;
-
- GPU_basic_shader_colors(diffuse, NULL, 0, 1.0f);
- GPU_basic_shader_bind(options);
-
- return;
- }
- }
-
- /* disable texture material */
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-
- if (data->shadeless) {
- glColor3f(1.0f, 1.0f, 1.0f);
- memset(gattribs, 0, sizeof(*gattribs));
- }
- else {
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
-
- /* enable solid material */
- GPU_object_material_bind(mat_nr, attribs);
- }
-}
-
-static bool tex_mat_set_face_mesh_cb(void *userData, int index)
-{
- /* faceselect mode face hiding */
- TexMatCallback *data = (TexMatCallback *)userData;
- Mesh *me = (Mesh *)data->me;
- MPoly *mp = &me->mpoly[index];
-
- return !(mp->flag & ME_HIDE);
-}
-
-static bool tex_mat_set_face_editmesh_cb(void *userData, int index)
-{
- /* editmode face hiding */
- TexMatCallback *data = (TexMatCallback *)userData;
- Mesh *me = (Mesh *)data->me;
- BMEditMesh *em = me->edit_btmesh;
- BMFace *efa;
-
- if (UNLIKELY(index >= em->bm->totface))
- return DM_DRAW_OPTION_NORMAL;
-
- efa = BM_face_at_index(em->bm, index);
-
- return !BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
-}
-
-void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
+void draw_mesh_textured(Scene *scene, ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d,
Object *ob, DerivedMesh *dm, const int draw_flags)
{
- /* if not cycles, or preview-modifiers, or drawing matcaps */
- if ((draw_flags & DRAW_MODIFIERS_PREVIEW) ||
- (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) ||
- (BKE_scene_use_new_shading_nodes(scene) == false) ||
- ((ob->mode & OB_MODE_TEXTURE_PAINT) && ELEM(v3d->drawtype, OB_TEXTURE, OB_SOLID)))
- {
- draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags);
- return;
- }
- else if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
- draw_mesh_paint(v3d, rv3d, ob, dm, draw_flags);
- return;
- }
-
- /* set opengl state for negative scale & color */
- if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
- else glFrontFace(GL_CCW);
-
- Mesh *me = ob->data;
-
- bool shadeless = ((v3d->flag2 & V3D_SHADELESS_TEX) &&
- ((v3d->drawtype == OB_TEXTURE) || (ob->mode & OB_MODE_TEXTURE_PAINT)));
- bool two_sided_lighting = (me->flag & ME_TWOSIDED) != 0;
-
- TexMatCallback data = {scene, ob, me, dm, shadeless, two_sided_lighting};
- bool (*set_face_cb)(void *, int);
- bool picking = (G.f & G_PICKSEL) != 0;
-
- /* face hiding callback depending on mode */
- if (ob == scene->obedit)
- set_face_cb = tex_mat_set_face_editmesh_cb;
- else if (draw_flags & DRAW_FACE_SELECT)
- set_face_cb = tex_mat_set_face_mesh_cb;
- else
- set_face_cb = NULL;
-
- /* test if we can use glsl */
- const int drawtype = view3d_effective_drawtype(v3d);
- bool glsl = (drawtype == OB_MATERIAL) && !picking;
-
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
-
- if (glsl || picking) {
- /* draw glsl or solid */
- dm->drawMappedFacesMat(dm,
- tex_mat_set_material_cb,
- set_face_cb, &data);
- }
- else {
- /* draw textured */
- dm->drawMappedFacesMat(dm,
- tex_mat_set_texture_cb,
- set_face_cb, &data);
- }
-
- GPU_end_object_materials();
-
- /* reset opengl state */
- GPU_end_object_materials();
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glFrontFace(GL_CCW);
-
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
-
- /* faceselect mode drawing over textured mesh */
- if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT)) {
- bool draw_select_edges = (ob->mode & OB_MODE_TEXTURE_PAINT) == 0;
- draw_mesh_face_select(rv3d, ob->data, dm, draw_select_edges);
- }
+ UNUSED_VARS(scene, view_layer, v3d, rv3d, ob, dm, draw_flags);
+ return;
}
/* Vertex Paint and Weight Paint */
@@ -1299,13 +271,6 @@ void draw_mesh_paint_vcolor_faces(DerivedMesh *dm, const bool use_light,
flags |= DM_DRAW_NEED_NORMALS;
}
- /* Don't show alpha in wire mode. */
- const bool show_alpha = use_light;
- if (show_alpha) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
if (me->mloopcol) {
dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data,
DM_DRAW_USE_COLORS | flags);
@@ -1315,10 +280,6 @@ void draw_mesh_paint_vcolor_faces(DerivedMesh *dm, const bool use_light,
dm->drawMappedFaces(dm, facemask_cb, setMaterial, NULL, user_data, flags);
}
- if (show_alpha) {
- glDisable(GL_BLEND);
- }
-
if (use_light) {
draw_mesh_paint_light_end();
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index a1075f7efcf..08ef9cc21cb 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -54,6 +54,7 @@
#include "BKE_camera.h"
#include "BKE_colortools.h"
#include "BKE_constraint.h" /* for the get_constraint_target function */
+#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_DerivedMesh.h"
#include "BKE_deform.h"
@@ -62,6 +63,7 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_key.h"
+#include "BKE_layer.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
@@ -80,6 +82,8 @@
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -90,6 +94,10 @@
#include "GPU_select.h"
#include "GPU_basic_shader.h"
#include "GPU_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_batch.h"
+#include "GPU_matrix.h"
#include "ED_mesh.h"
#include "ED_particle.h"
@@ -105,6 +113,13 @@
#include "view3d_intern.h" /* bad level include */
+#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */
+
+/* prototypes */
+static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos);
+
+// #define USE_MESH_DM_SELECT
+
/* Workaround for sequencer scene render mode.
*
* Strips doesn't use DAG to update objects or so, which
@@ -129,6 +144,7 @@ typedef struct drawDMVerts_userData {
BMVert *eve_act;
char sel;
+ unsigned int pos, color;
/* cached theme values */
unsigned char th_editmesh_active[4];
@@ -181,6 +197,7 @@ typedef struct drawDMFacesSel_userData {
} drawDMFacesSel_userData;
typedef struct drawDMNormal_userData {
+ unsigned int pos;
BMesh *bm;
int uniform_scale;
float normalsize;
@@ -189,6 +206,7 @@ typedef struct drawDMNormal_userData {
} drawDMNormal_userData;
typedef struct drawMVertOffset_userData {
+ unsigned int pos, col;
MVert *mvert;
int offset;
} drawMVertOffset_userData;
@@ -196,9 +214,11 @@ typedef struct drawMVertOffset_userData {
typedef struct drawDMLayer_userData {
BMesh *bm;
int cd_layer_offset;
+ unsigned int pos, col;
} drawDMLayer_userData;
typedef struct drawBMOffset_userData {
+ unsigned int pos, col;
BMesh *bm;
int offset;
} drawBMOffset_userData;
@@ -206,25 +226,23 @@ typedef struct drawBMOffset_userData {
typedef struct drawBMSelect_userData {
BMesh *bm;
bool select;
+ unsigned int pos;
} drawBMSelect_userData;
-static void draw_bounding_volume(Object *ob, char type);
-static void drawcube_size(float size);
-static void drawcircle_size(float size);
-static void draw_empty_sphere(float size);
-static void draw_empty_cone(float size);
-static void draw_box(const float vec[8][3], bool solid);
+static void drawcube_size(float size, unsigned pos);
+static void drawcircle_size(float size, unsigned pos);
+static void draw_empty_sphere(float size, unsigned pos);
+static void draw_empty_cone(float size, unsigned pos);
-static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac)
+static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac, float r_col[3])
{
- float col_wire[3], col_bg[3], col[3];
+ float col_wire[3], col_bg[3];
rgb_uchar_to_float(col_wire, ob_wire_col);
UI_GetThemeColor3fv(theme_id, col_bg);
- interp_v3_v3v3(col, col_bg, col_wire, fac);
- glColor3fv(col);
+ interp_v3_v3v3(r_col, col_bg, col_wire, fac);
}
int view3d_effective_drawtype(const struct View3D *v3d)
@@ -296,13 +314,13 @@ static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
/* check for glsl drawing */
-bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
+bool draw_glsl_material(Scene *scene, ViewLayer *view_layer, Object *ob, View3D *v3d, const char dt)
{
if (G.f & G_PICKSEL)
return false;
if (!check_object_draw_texture(scene, v3d, dt))
return false;
- if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
+ if (ob == OBACT(view_layer) && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
return false;
if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP)
@@ -318,7 +336,7 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
static bool check_alpha_pass(Base *base)
{
- if (base->flag & OB_FROMDUPLI)
+ if (base->flag_legacy & OB_FROMDUPLI)
return false;
if (G.f & G_PICKSEL)
@@ -414,9 +432,9 @@ static const float cosval[CIRCLE_RESOL] = {
* \param viewmat_local_unit is typically the 'rv3d->viewmatob'
* copied into a 3x3 matrix and normalized.
*/
-static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3], float size, int axis)
+static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3], float size, int axis, unsigned pos)
{
- int line_type;
+ Gwn_PrimType line_type = GWN_PRIM_LINES;
float buffer[4][3];
int n = 0;
@@ -429,8 +447,6 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3]
switch (axis) {
case 0: /* x axis */
- line_type = GL_LINES;
-
/* bottom left to top right */
negate_v3_v3(v1, dx);
sub_v3_v3(v1, dy);
@@ -450,8 +466,6 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3]
break;
case 1: /* y axis */
- line_type = GL_LINES;
-
/* bottom left to top right */
mul_v3_fl(dx, 0.75f);
negate_v3_v3(v1, dx);
@@ -472,7 +486,7 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3]
break;
case 2: /* z axis */
- line_type = GL_LINE_STRIP;
+ line_type = GWN_PRIM_LINE_STRIP;
/* start at top left */
negate_v3_v3(v1, dx);
@@ -501,54 +515,60 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3]
return;
}
+ immBegin(line_type, n);
for (int i = 0; i < n; i++) {
mul_transposed_m3_v3((float (*)[3])viewmat_local_unit, buffer[i]);
add_v3_v3(buffer[i], c);
+ immVertex3fv(pos, buffer[i]);
}
+ immEnd();
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, buffer);
- glDrawArrays(line_type, 0, n);
- glDisableClientState(GL_VERTEX_ARRAY);
+ /* TODO: recode this function for clarity once we're not in a hurry to modernize GL usage */
}
-void drawaxes(const float viewmat_local[4][4], float size, char drawtype)
+void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4])
{
int axis;
float v1[3] = {0.0, 0.0, 0.0};
float v2[3] = {0.0, 0.0, 0.0};
float v3[3] = {0.0, 0.0, 0.0};
- glLineWidth(1);
+ glLineWidth(1.0f);
- switch (drawtype) {
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ if (color) {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4ubv(color);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY);
+ }
+ switch (drawtype) {
case OB_PLAINAXES:
+ immBegin(GWN_PRIM_LINES, 6);
for (axis = 0; axis < 3; axis++) {
- glBegin(GL_LINES);
-
v1[axis] = size;
v2[axis] = -size;
- glVertex3fv(v1);
- glVertex3fv(v2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
/* reset v1 & v2 to zero */
v1[axis] = v2[axis] = 0.0f;
-
- glEnd();
}
+ immEnd();
break;
- case OB_SINGLE_ARROW:
- glBegin(GL_LINES);
+ case OB_SINGLE_ARROW:
+ immBegin(GWN_PRIM_LINES, 2);
/* in positive z direction only */
v1[2] = size;
- glVertex3fv(v1);
- glVertex3fv(v2);
- glEnd();
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immEnd();
/* square pyramid */
- glBegin(GL_TRIANGLES);
+ immBegin(GWN_PRIM_TRIS, 12);
v2[0] = size * 0.035f; v2[1] = size * 0.035f;
v3[0] = size * -0.035f; v3[1] = size * 0.035f;
@@ -564,28 +584,27 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype)
v3[0] = -v3[0];
}
- glVertex3fv(v1);
- glVertex3fv(v2);
- glVertex3fv(v3);
-
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immVertex3fv(pos, v3);
}
- glEnd();
-
+ immEnd();
break;
+
case OB_CUBE:
- drawcube_size(size);
+ drawcube_size(size, pos);
break;
case OB_CIRCLE:
- drawcircle_size(size);
+ drawcircle_size(size, pos);
break;
case OB_EMPTY_SPHERE:
- draw_empty_sphere(size);
+ draw_empty_sphere(size, pos);
break;
case OB_EMPTY_CONE:
- draw_empty_cone(size);
+ draw_empty_cone(size, pos);
break;
case OB_ARROWS:
@@ -599,34 +618,34 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype)
for (axis = 0; axis < 3; axis++) {
const int arrow_axis = (axis == 0) ? 1 : 0;
- glBegin(GL_LINES);
+ immBegin(GWN_PRIM_LINES, 6);
v2[axis] = size;
- glVertex3fv(v1);
- glVertex3fv(v2);
-
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+
v1[axis] = size * 0.85f;
v1[arrow_axis] = -size * 0.08f;
- glVertex3fv(v1);
- glVertex3fv(v2);
-
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+
v1[arrow_axis] = size * 0.08f;
- glVertex3fv(v1);
- glVertex3fv(v2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
- glEnd();
-
- v2[axis] += size * 0.125f;
+ immEnd();
- draw_xyz_wire(viewmat_local_unit, v2, size, axis);
+ v2[axis] += size * 0.125f;
+ draw_xyz_wire(viewmat_local_unit, v2, size, axis, pos);
/* reset v1 & v2 to zero */
v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
}
- break;
}
}
+
+ immUnbindProgram();
}
@@ -634,38 +653,39 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype)
static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4], eStereoViews sview)
{
Image *ima = ob->data;
- ImBuf *ibuf;
- ImageUser iuser = *ob->iuser;
- /* Support multi-view */
- if (ima && (sview == STEREO_RIGHT_ID)) {
- iuser.multiview_eye = sview;
- iuser.flag |= IMA_SHOW_STEREO;
- BKE_image_multiview_index(ima, &iuser);
- }
+ const float ob_alpha = ob->col[3];
+ float ima_x, ima_y;
- ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+ int bindcode = 0;
- if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
- IMB_rect_from_float(ibuf);
- }
+ if (ima) {
+ ImageUser iuser = *ob->iuser;
+
+ /* Support multi-view */
+ if (ima && (sview == STEREO_RIGHT_ID)) {
+ iuser.multiview_eye = sview;
+ iuser.flag |= IMA_SHOW_STEREO;
+ BKE_image_multiview_index(ima, &iuser);
+ }
- int ima_x, ima_y;
+ if (ob_alpha > 0.0f) {
+ bindcode = GPU_verify_image(ima, &iuser, GL_TEXTURE_2D, 0, false, false, false);
+ /* don't bother drawing the image if alpha = 0 */
+ }
- /* Get the buffer dimensions so we can fallback to fake ones */
- if (ibuf && ibuf->rect) {
- ima_x = ibuf->x;
- ima_y = ibuf->y;
+ int w, h;
+ BKE_image_get_size(ima, &iuser, &w, &h);
+ ima_x = w;
+ ima_y = h;
}
else {
- ima_x = 1;
- ima_y = 1;
+ /* if no image, make it a 1x1 empty square, honor scale & offset */
+ ima_x = ima_y = 1.0f;
}
- float sca_x = 1.0f;
- float sca_y = 1.0f;
-
/* Get the image aspect even if the buffer is invalid */
+ float sca_x = 1.0f, sca_y = 1.0f;
if (ima) {
if (ima->aspx > ima->aspy) {
sca_y = ima->aspy / ima->aspx;
@@ -675,61 +695,98 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
}
}
- /* Calculate the scale center based on object's origin */
- float ofs_x = ob->ima_ofs[0] * ima_x;
- float ofs_y = ob->ima_ofs[1] * ima_y;
+ float scale_x;
+ float scale_y;
+ {
+ const float scale_x_inv = ima_x * sca_x;
+ const float scale_y_inv = ima_y * sca_y;
+ if (scale_x_inv > scale_y_inv) {
+ scale_x = ob->empty_drawsize;
+ scale_y = ob->empty_drawsize * (scale_y_inv / scale_x_inv);
+ }
+ else {
+ scale_x = ob->empty_drawsize * (scale_x_inv / scale_y_inv);
+ scale_y = ob->empty_drawsize;
+ }
+ }
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ const float ofs_x = ob->ima_ofs[0] * scale_x;
+ const float ofs_y = ob->ima_ofs[1] * scale_y;
- /* Calculate Image scale */
- float scale = ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y);
+ const rctf rect = {
+ .xmin = ofs_x,
+ .xmax = ofs_x + scale_x,
+ .ymin = ofs_y,
+ .ymax = ofs_y + scale_y,
+ };
- /* Set the object scale */
- glScalef(scale * sca_x, scale * sca_y, 1.0f);
+ bool use_blend = false;
- if (ibuf && ibuf->rect) {
- const bool use_clip = (U.glalphaclip != 1.0f);
- int zoomfilter = (U.gameflags & USER_DISABLE_MIPMAP) ? GL_NEAREST : GL_LINEAR;
- /* Setup GL params */
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ if (bindcode) {
+ use_blend = ob_alpha < 1.0f || BKE_image_has_alpha(ima);
- if (use_clip) {
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GREATER, U.glalphaclip);
+ if (use_blend) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- /* Use the object color and alpha */
- glColor4fv(ob->col);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
+ immUniform1f("alpha", ob_alpha);
+ immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
- /* Draw the Image on the screen */
- glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, zoomfilter, ibuf->rect);
+ immBegin(GWN_PRIM_TRI_FAN, 4);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, rect.xmin, rect.ymin);
- glDisable(GL_BLEND);
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, rect.xmax, rect.ymin);
- if (use_clip) {
- glDisable(GL_ALPHA_TEST);
- glAlphaFunc(GL_ALWAYS, 0.0f);
- }
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, rect.xmax, rect.ymax);
+
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, rect.xmin, rect.ymax);
+ immEnd();
+
+ immUnbindProgram();
+
+ glBindTexture(GL_TEXTURE_2D, 0); /* necessary? */
}
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
+ /* Draw the image outline */
+ glLineWidth(1.5f);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ const bool picking = dflag & DRAW_CONSTCOLOR;
+ if (picking) {
+ /* TODO: deal with picking separately, use this function just to draw */
+ immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY);
+ if (use_blend) {
+ glDisable(GL_BLEND);
+ }
+
+ imm_draw_box_wire_2d(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
}
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(ob_wire_col);
+ glEnable(GL_LINE_SMOOTH);
- /* Calculate the outline vertex positions */
- glBegin(GL_LINE_LOOP);
- glVertex2f(ofs_x, ofs_y);
- glVertex2f(ofs_x + ima_x, ofs_y);
- glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
- glVertex2f(ofs_x, ofs_y + ima_y);
- glEnd();
+ if (!use_blend) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
- /* Reset GL settings */
- glPopMatrix();
+ imm_draw_box_wire_2d(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ }
+
+ immUnbindProgram();
}
static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, const float tmat[4][4])
@@ -747,62 +804,65 @@ static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3
}
}
-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)
{
float verts[CIRCLE_RESOL][3];
circball_array_fill(verts, cent, rad, tmat);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, verts);
- glDrawArrays(mode, 0, CIRCLE_RESOL);
- glDisableClientState(GL_VERTEX_ARRAY);
+ immBegin(GWN_PRIM_LINE_LOOP, CIRCLE_RESOL);
+ for (int i = 0; i < CIRCLE_RESOL; ++i) {
+ immVertex3fv(pos, verts[i]);
+ }
+ immEnd();
}
/* circle for object centers, special_color is for library or ob users */
-static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, bool special_color)
+static void drawcentercircle(View3D *v3d, RegionView3D *UNUSED(rv3d), const float co[3], int selstate, bool special_color)
{
- const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
- float verts[CIRCLE_RESOL][3];
+ const float outlineWidth = 1.0f * U.pixelsize;
+ const float size = U.obcenter_dia * U.pixelsize + outlineWidth;
+
+ if (v3d->zbuf) {
+ glDisable(GL_DEPTH_TEST);
+ /* TODO(merwin): fit things like this into plates/buffers design */
+ }
- /* using glDepthFunc guarantees that it does write z values,
- * but not checks for it, so centers remain visible independent of draw order */
- if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
- /* write to near buffer always */
- glDepthRange(0.0, 0.0);
glEnable(GL_BLEND);
-
+ GPU_enable_program_point_size();
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+ immUniform1f("size", size);
+
if (special_color) {
- if (selstate == ACTIVE || selstate == SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
- else glColor4ub(0x55, 0xCC, 0xCC, 155);
+ if (selstate == ACTIVE || selstate == SELECT) immUniformColor4ub(0x88, 0xFF, 0xFF, 155);
+ else immUniformColor4ub(0x55, 0xCC, 0xCC, 155);
}
else {
- if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
- else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
- else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
+ if (selstate == ACTIVE) immUniformThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
+ else if (selstate == SELECT) immUniformThemeColorShadeAlpha(TH_SELECT, 0, -80);
+ else if (selstate == DESELECT) immUniformThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
}
- circball_array_fill(verts, co, size, rv3d->viewinv);
-
- /* enable vertex array */
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, verts);
-
- /* 1. draw filled, blended polygon */
- glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL);
+ /* set up outline */
+ float outlineColor[4];
+ UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, outlineColor);
+ immUniform4fv("outlineColor", outlineColor);
+ immUniform1f("outlineWidth", outlineWidth);
- /* 2. draw outline */
- glLineWidth(1);
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
- glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3fv(pos, co);
+ immEnd();
- /* finish up */
- glDisableClientState(GL_VERTEX_ARRAY);
+ immUnbindProgram();
- glDepthRange(0.0, 1.0);
+ GPU_disable_program_point_size();
glDisable(GL_BLEND);
- if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
+ if (v3d->zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ }
}
/* *********** text drawing for object/particles/armature ************* */
@@ -893,36 +953,30 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write)
if (tot) {
int col_pack_prev = 0;
-#if 0
- bglMats mats; /* ZBuffer depth vars */
- double ux, uy, uz;
- float depth;
-
- if (v3d->zbuf)
- bgl_get_mats(&mats);
-#endif
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_disable();
}
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ float original_proj[4][4];
+ gpuGetProjectionMatrix(original_proj);
wmOrtho2_region_pixelspace(ar);
- glLoadIdentity();
+
+ gpuPushMatrix();
+ gpuLoadIdentity();
if (depth_write) {
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
}
else {
- glDepthMask(0);
+ glDepthMask(GL_FALSE);
}
+ const int font_id = BLF_default();
+
for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) {
if (vos->sco[0] != IS_CLIPPED) {
if (col_pack_prev != vos->col.pack) {
- glColor3ubv(vos->col.ub);
+ BLF_color3ubv(font_id, vos->col.ub);
col_pack_prev = vos->col.pack;
}
@@ -941,13 +995,11 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write)
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
else {
- glDepthMask(1);
+ glDepthMask(GL_TRUE);
}
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ gpuPopMatrix();
+ gpuLoadProjectionMatrix(original_proj);
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_enable();
@@ -971,9 +1023,9 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write)
/* draws a cube given the scaling of the cube, assuming that
* all required matrices have been set (used for drawing empties)
*/
-static void drawcube_size(float size)
+static void drawcube_size(float size, unsigned pos)
{
- const GLfloat pos[8][3] = {
+ const float verts[8][3] = {
{-size, -size, -size},
{-size, -size, size},
{-size, size, -size},
@@ -986,13 +1038,21 @@ static void drawcube_size(float size)
const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6};
+#if 0
glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, pos);
+ glVertexPointer(3, GL_FLOAT, 0, verts);
glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices);
glDisableClientState(GL_VERTEX_ARRAY);
+#else
+ immBegin(GWN_PRIM_LINES, 24);
+ for (int i = 0; i < 24; ++i) {
+ immVertex3fv(pos, verts[indices[i]]);
+ }
+ immEnd();
+#endif
}
-static void drawshadbuflimits(Lamp *la, float mat[4][4])
+static void drawshadbuflimits(const Lamp *la, const float mat[4][4], unsigned pos)
{
float sta[3], end[3], lavec[3];
@@ -1002,16 +1062,16 @@ static void drawshadbuflimits(Lamp *la, float mat[4][4])
madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta);
madd_v3_v3v3fl(end, mat[3], lavec, la->clipend);
- glBegin(GL_LINES);
- glVertex3fv(sta);
- glVertex3fv(end);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(pos, sta);
+ immVertex3fv(pos, end);
+ immEnd();
- glPointSize(3.0);
- glBegin(GL_POINTS);
- glVertex3fv(sta);
- glVertex3fv(end);
- glEnd();
+ glPointSize(3.0f);
+ immBegin(GWN_PRIM_POINTS, 2);
+ immVertex3fv(pos, sta);
+ immVertex3fv(pos, end);
+ immEnd();
}
static void spotvolume(float lvec[3], float vvec[3], const float inp)
@@ -1077,62 +1137,63 @@ static void spotvolume(float lvec[3], float vvec[3], const float inp)
mul_m3_v3(mat2, vvec);
}
-static void draw_spot_cone(Lamp *la, float x, float z)
+static void draw_spot_cone(Lamp *la, float x, float z, unsigned pos)
{
z = fabsf(z);
- glBegin(GL_TRIANGLE_FAN);
- glVertex3f(0.0f, 0.0f, -x);
+ const bool square = (la->mode & LA_SQUARE);
+
+ immBegin(GWN_PRIM_TRI_FAN, square ? 6 : 34);
+ immVertex3f(pos, 0.0f, 0.0f, -x);
- if (la->mode & LA_SQUARE) {
- glVertex3f(z, z, 0);
- glVertex3f(-z, z, 0);
- glVertex3f(-z, -z, 0);
- glVertex3f(z, -z, 0);
- glVertex3f(z, z, 0);
+ if (square) {
+ immVertex3f(pos, z, z, 0);
+ immVertex3f(pos, -z, z, 0);
+ immVertex3f(pos, -z, -z, 0);
+ immVertex3f(pos, z, -z, 0);
+ immVertex3f(pos, z, z, 0);
}
else {
for (int a = 0; a < 33; a++) {
float angle = a * M_PI * 2 / (33 - 1);
- glVertex3f(z * cosf(angle), z * sinf(angle), 0);
+ immVertex3f(pos, z * cosf(angle), z * sinf(angle), 0.0f);
}
}
- glEnd();
+ immEnd();
}
-static void draw_transp_spot_volume(Lamp *la, float x, float z)
+static void draw_transp_spot_volume(Lamp *la, float x, float z, unsigned pos)
{
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
- glDepthMask(0);
+ glDepthMask(GL_FALSE);
/* draw backside darkening */
glCullFace(GL_FRONT);
glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
- glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
- draw_spot_cone(la, x, z);
+ draw_spot_cone(la, x, z, pos);
/* draw front side lighting */
glCullFace(GL_BACK);
glBlendFunc(GL_ONE, GL_ONE);
- glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
+ immUniformColor3f(0.2f, 0.2f, 0.2f);
- draw_spot_cone(la, x, z);
+ draw_spot_cone(la, x, z, pos);
/* restore state */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND);
- glDepthMask(1);
+ glDepthMask(GL_TRUE);
glDisable(GL_CULL_FACE);
- glCullFace(GL_BACK);
}
#ifdef WITH_GAMEENGINE
-static void draw_transp_sun_volume(Lamp *la)
+static void draw_transp_sun_volume(Lamp *la, unsigned pos)
{
float box[8][3];
@@ -1145,50 +1206,46 @@ static void draw_transp_sun_volume(Lamp *la)
box[1][2] = box[2][2] = box[5][2] = box[6][2] = -la->clipsta;
/* draw edges */
- draw_box(box, false);
+ imm_draw_box(box, false, pos);
/* draw faces */
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
- glDepthMask(0);
+ glDepthMask(GL_FALSE);
/* draw backside darkening */
glCullFace(GL_FRONT);
glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
- glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
- draw_box(box, true);
+ imm_draw_box(box, true, pos);
/* draw front side lighting */
glCullFace(GL_BACK);
glBlendFunc(GL_ONE, GL_ONE);
- glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
+ immUniformColor3f(0.2f, 0.2f, 0.2f);
- draw_box(box, true);
+ imm_draw_box(box, true, pos);
/* restore state */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND);
- glDepthMask(1);
+ glDepthMask(GL_TRUE);
glDisable(GL_CULL_FACE);
- glCullFace(GL_BACK);
}
#endif
-static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
- const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact)
+void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact)
{
Object *ob = base->object;
const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
Lamp *la = ob->data;
float vec[3], lvec[3], vvec[3], circrad;
- float lampsize;
float imat[4][4];
- unsigned char curcol[4];
- unsigned char col[4];
/* cone can't be drawn for duplicated lamps, because duplilist would be freed */
/* the moment of view3d_draw_transp() call */
const bool is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object);
@@ -1196,7 +1253,7 @@ static 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
@@ -1208,7 +1265,7 @@ static 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;
@@ -1216,118 +1273,159 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
if ((drawcone || drawshadowbox) && !v3d->transp) {
/* in this case we need to draw delayed */
- ED_view3d_after_add(v3d->xray ? &v3d->afterdraw_xraytransp : &v3d->afterdraw_transp, base, dflag);
+ ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
return;
}
-
+
/* we first draw only the screen aligned & fixed scale stuff */
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
+ gpuPushMatrix();
+ gpuLoadMatrix(rv3d->viewmat);
/* lets calculate the scale: */
- lampsize = pixsize * ((float)U.obcenter_dia * 0.5f);
+ const float lampsize_px = U.obcenter_dia;
+ const float lampsize = pixsize * lampsize_px * 0.5f;
/* and view aligned matrix: */
copy_m4_m4(imat, rv3d->viewinv);
normalize_v3(imat[0]);
normalize_v3(imat[1]);
+ const unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
/* lamp center */
copy_v3_v3(vec, ob->obmat[3]);
+ float curcol[4];
if ((dflag & DRAW_CONSTCOLOR) == 0) {
/* for AA effects */
- curcol[0] = ob_wire_col[0];
- curcol[1] = ob_wire_col[1];
- curcol[2] = ob_wire_col[2];
- curcol[3] = 154;
- glColor4ubv(curcol);
+ rgb_uchar_to_float(curcol, ob_wire_col);
+ curcol[3] = 0.6f;
+ /* TODO: pay attention to GL_BLEND */
}
- glLineWidth(1);
+ glLineWidth(1.0f);
+ setlinestyle(3);
if (lampsize > 0.0f) {
+ const float outlineWidth = 1.5f * U.pixelsize;
+ const float lampdot_size = lampsize_px * U.pixelsize + outlineWidth;
+ /* Inner Circle */
if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ const float *color = curcol;
if (ob->id.us > 1) {
- if (is_obact || (ob->flag & SELECT)) {
- glColor4ub(0x88, 0xFF, 0xFF, 155);
+ 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;
}
else {
- glColor4ub(0x77, 0xCC, 0xCC, 155);
+ static const float inactive_color[4] = {0.467f, 0.8f, 0.8f, 1.0f};
+ color = inactive_color;
}
}
+
+ GPU_enable_program_point_size();
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+ immUniform1f("size", lampdot_size);
+ immUniform1f("outlineWidth", outlineWidth);
+ immUniformColor3fvAlpha(color, 0.3f);
+ immUniform4fv("outlineColor", color);
+
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3fv(pos, vec);
+ immEnd();
+
+ immUnbindProgram();
+
+ glDisable(GL_BLEND);
+ GPU_disable_program_point_size();
}
-
- /* Inner Circle */
- glEnable(GL_BLEND);
- drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
- glDisable(GL_BLEND);
- drawcircball(GL_POLYGON, vec, lampsize, imat);
-
+ else {
+ /* CONSTCOLOR in effect */
+ /* TODO: separate picking from drawing */
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+ /* color doesn't matter, so don't set */
+ glPointSize(lampdot_size);
+
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3fv(pos, vec);
+ immEnd();
+
+ immUnbindProgram();
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ /* TODO(merwin): short term, use DEPTH_ONLY for picking
+ * long term, separate picking from drawing
+ */
+
/* restore */
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (ob->id.us > 1)
- glColor4ubv(curcol);
+ immUniformColor4fv(curcol);
}
/* Outer circle */
circrad = 3.0f * lampsize;
- setlinestyle(3);
- drawcircball(GL_LINE_LOOP, vec, circrad, imat);
+ imm_drawcircball(vec, circrad, imat, pos);
/* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
if (la->type != LA_HEMI) {
if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
- drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f * pixsize, imat);
+ imm_drawcircball(vec, circrad + 3.0f * pixsize, imat, pos);
}
}
}
else {
- setlinestyle(3);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ immUniformColor4fv(curcol);
+ }
circrad = 0.0f;
}
-
+
/* draw the pretty sun rays */
if (la->type == LA_SUN) {
float v1[3], v2[3], mat[3][3];
short axis;
-
+
/* setup a 45 degree rotation matrix */
axis_angle_normalized_to_mat3_ex(mat, imat[2], M_SQRT1_2, M_SQRT1_2);
/* vectors */
mul_v3_v3fl(v1, imat[0], circrad * 1.2f);
mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
-
+
/* center */
- glTranslate3fv(vec);
-
+ gpuPushMatrix();
+ gpuTranslate3fv(vec);
+
setlinestyle(3);
-
- glBegin(GL_LINES);
+
+ immBegin(GWN_PRIM_LINES, 16);
for (axis = 0; axis < 8; axis++) {
- glVertex3fv(v1);
- glVertex3fv(v2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
mul_m3_v3(mat, v1);
mul_m3_v3(mat, v2);
}
- glEnd();
-
- glTranslatef(-vec[0], -vec[1], -vec[2]);
+ immEnd();
+ gpuPopMatrix();
}
-
+
if (la->type == LA_LOCAL) {
if (la->mode & LA_SPHERE) {
- drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
+ imm_drawcircball(vec, la->dist, imat, pos);
}
}
-
- glPopMatrix(); /* back in object space */
+
+ gpuPopMatrix(); /* back in object space */
zero_v3(vec);
-
+
if (is_view) {
/* skip drawing extra info */
}
@@ -1359,24 +1457,18 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
{z_abs, -z_abs, x},
{-z_abs, z_abs, x},
};
- const unsigned char indices[] = {
- 0, 1, 3,
- 0, 3, 2,
- 0, 2, 4,
- 0, 1, 4,
- };
-
- /* Draw call:
- * activate and specify pointer to vertex array */
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, vertices);
- /* draw the pyramid */
- glDrawElements(GL_LINE_STRIP, 12, GL_UNSIGNED_BYTE, indices);
- /* deactivate vertex arrays after drawing */
- glDisableClientState(GL_VERTEX_ARRAY);
+ immBegin(GWN_PRIM_LINES, 16);
+ for (int i = 1; i <= 4; ++i) {
+ immVertex3fv(pos, vertices[0]); /* apex to corner */
+ immVertex3fv(pos, vertices[i]);
+ int next_i = (i == 4) ? 1 : (i + 1);
+ immVertex3fv(pos, vertices[i]); /* corner to next corner */
+ immVertex3fv(pos, vertices[next_i]);
+ }
+ immEnd();
- glTranslatef(0.0f, 0.0f, x);
+ gpuTranslate3f(0.0f, 0.0f, x);
/* draw the square representing spotbl */
if (la->type == LA_SPOT) {
@@ -1386,22 +1478,21 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
* previously it adjusted to always to show it but that seems
* confusing because it doesn't show the actual blend size */
if (blend != 0.0f && blend != z_abs) {
- fdrawbox(blend, -blend, -blend, blend);
+ imm_draw_box_wire_3d(pos, blend, -blend, -blend, blend);
}
}
}
else {
-
/* draw the angled sides of the cone */
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vvec);
- glVertex3fv(vec);
- glVertex3fv(lvec);
- glEnd();
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ immVertex3fv(pos, vvec);
+ immVertex3fv(pos, vec);
+ immVertex3fv(pos, lvec);
+ immEnd();
/* draw the circle at the end of the cone */
- glTranslatef(0.0f, 0.0f, x);
- circ(0.0f, 0.0f, z_abs);
+ gpuTranslate3f(0.0f, 0.0f, x);
+ imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, z_abs, 32);
/* draw the circle representing spotbl */
if (la->type == LA_SPOT) {
@@ -1411,17 +1502,17 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
* previously it adjusted to always to show it but that seems
* confusing because it doesn't show the actual blend size */
if (blend != 0.0f && blend != z_abs) {
- circ(0.0f, 0.0f, blend);
+ imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, blend, 32);
}
}
}
if (drawcone)
- draw_transp_spot_volume(la, x, z);
+ draw_transp_spot_volume(la, x, z, pos);
/* draw clip start, useful for wide cones where its not obvious where the start is */
- glTranslatef(0.0, 0.0, -x); /* reverse translation above */
- glBegin(GL_LINES);
+ gpuTranslate3f(0.0f, 0.0f, -x); /* reverse translation above */
+ immBegin(GWN_PRIM_LINES, 2);
if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF)) {
float lvec_clip[3];
float vvec_clip[3];
@@ -1430,41 +1521,40 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac);
interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac);
- glVertex3fv(lvec_clip);
- glVertex3fv(vvec_clip);
+ immVertex3fv(pos, lvec_clip);
+ immVertex3fv(pos, vvec_clip);
}
/* Else, draw spot direction (using distance as end limit, same as for Area lamp). */
else {
- glVertex3f(0.0, 0.0, -circrad);
- glVertex3f(0.0, 0.0, -la->dist);
+ immVertex3f(pos, 0.0f, 0.0f, -circrad);
+ immVertex3f(pos, 0.0f, 0.0f, -la->dist);
}
- glEnd();
+ immEnd();
}
else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
-
/* draw the line from the circle along the dist */
- glBegin(GL_LINES);
+ immBegin(GWN_PRIM_LINES, 2);
vec[2] = -circrad;
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
vec[2] = -la->dist;
- glVertex3fv(vec);
- glEnd();
-
+ immVertex3fv(pos, vec);
+ immEnd();
+
if (la->type == LA_HEMI) {
/* draw the hemisphere curves */
short axis, steps, dir;
float outdist, zdist, mul;
zero_v3(vec);
- outdist = 0.14; mul = 1.4; dir = 1;
-
+ outdist = 0.14f; mul = 1.4f; dir = 1;
+
setlinestyle(4);
/* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
for (axis = 0; axis < 4; axis++) {
- float v[3] = {0.0, 0.0, 0.0};
- zdist = 0.02;
-
- glBegin(GL_LINE_STRIP);
-
+ float v[3] = {0.0f, 0.0f, 0.0f};
+ zdist = 0.02f;
+
+ immBegin(GWN_PRIM_LINE_STRIP, 6);
+
for (steps = 0; steps < 6; steps++) {
if (axis == 0 || axis == 1) { /* x axis up, x axis down */
/* make the arcs start at the edge of the energy circle */
@@ -1477,13 +1567,13 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
}
v[2] = v[2] - steps * zdist;
-
- glVertex3fv(v);
-
+
+ immVertex3fv(pos, v);
+
zdist = zdist * mul;
}
-
- glEnd();
+
+ immEnd();
/* flip the direction */
dir = -dir;
}
@@ -1491,96 +1581,92 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
#ifdef WITH_GAMEENGINE
if (drawshadowbox) {
- draw_transp_sun_volume(la);
+ draw_transp_sun_volume(la, pos);
}
#endif
-
}
else if (la->type == LA_AREA) {
setlinestyle(3);
if (la->area_shape == LA_AREA_SQUARE)
- fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f);
+ imm_draw_box_wire_3d(pos, -la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f);
else if (la->area_shape == LA_AREA_RECT)
- fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f);
+ imm_draw_box_wire_3d(pos, -la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f);
- glBegin(GL_LINES);
- glVertex3f(0.0, 0.0, -circrad);
- glVertex3f(0.0, 0.0, -la->dist);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3f(pos, 0.0f, 0.0f, -circrad);
+ immVertex3f(pos, 0.0f, 0.0f, -la->dist);
+ immEnd();
}
-
+
/* and back to viewspace */
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
+ gpuPushMatrix();
+ gpuLoadMatrix(rv3d->viewmat);
copy_v3_v3(vec, ob->obmat[3]);
setlinestyle(0);
-
+
if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == false)) {
- drawshadbuflimits(la, ob->obmat);
+ drawshadbuflimits(la, ob->obmat, pos);
}
-
+
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- UI_GetThemeColor4ubv(TH_LAMP, col);
- glColor4ubv(col);
+ immUniformThemeColor(TH_LAMP);
}
glEnable(GL_BLEND);
-
+
if (vec[2] > 0) vec[2] -= circrad;
else vec[2] += circrad;
-
- glBegin(GL_LINES);
- glVertex3fv(vec);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(pos, vec);
vec[2] = 0;
- glVertex3fv(vec);
- glEnd();
-
- glPointSize(2.0);
- glBegin(GL_POINTS);
- glVertex3fv(vec);
- glEnd();
-
+ immVertex3fv(pos, vec);
+ immEnd();
+
+ glPointSize(2.0f);
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3fv(pos, vec);
+ immEnd();
+
glDisable(GL_BLEND);
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- /* restore for drawing extra stuff */
- glColor3ubv(ob_wire_col);
- }
- /* and finally back to org object space! */
- glPopMatrix();
+
+ immUnbindProgram();
+ gpuPopMatrix();
}
-static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3])
+static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3], unsigned pos)
{
- glBegin(GL_LINES);
- glVertex3f(0.0, 0.0, -sta);
- glVertex3f(0.0, 0.0, -end);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3f(pos, 0.0f, 0.0f, -sta);
+ immVertex3f(pos, 0.0f, 0.0f, -end);
+ immEnd();
if (!(dflag & DRAW_PICKING)) {
- glPointSize(3.0);
- glBegin(GL_POINTS);
+ glPointSize(3.0f);
+ /* would like smooth round points here, but that means binding another shader...
+ * if it's really desired, pull these points into their own function to be called after */
+ immBegin(GWN_PRIM_POINTS, 2);
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(col);
+ immUniformColor3ubv(col);
}
- glVertex3f(0.0, 0.0, -sta);
- glVertex3f(0.0, 0.0, -end);
- glEnd();
+ immVertex3f(pos, 0.0f, 0.0f, -sta);
+ immVertex3f(pos, 0.0f, 0.0f, -end);
+ immEnd();
}
}
/* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
/* qdn: now also enabled for Blender to set focus point for defocus composite node */
-static void draw_focus_cross(float dist, float size)
+static void draw_focus_cross(float dist, float size, unsigned pos)
{
- glBegin(GL_LINES);
- glVertex3f(-size, 0.0f, -dist);
- glVertex3f(size, 0.0f, -dist);
- glVertex3f(0.0f, -size, -dist);
- glVertex3f(0.0f, size, -dist);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 4);
+ immVertex3f(pos, -size, 0.0f, -dist);
+ immVertex3f(pos, size, 0.0f, -dist);
+ immVertex3f(pos, 0.0f, -size, -dist);
+ immVertex3f(pos, 0.0f, size, -dist);
+ immEnd();
}
#ifdef VIEW3D_CAMERA_BORDER_HACK
@@ -1590,26 +1676,6 @@ bool view3d_camera_border_hack_test = false;
/* ****************** draw clip data *************** */
-static void draw_bundle_sphere(void)
-{
- static GLuint displist = 0;
-
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
- gluSphere(qobj, 0.05, 8, 8);
- gluDeleteQuadric(qobj);
-
- glEndList();
- }
-
- glCallList(displist);
-}
-
static void draw_viewport_object_reconstruction(
Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d,
MovieClip *clip, MovieTrackingObject *tracking_object,
@@ -1635,7 +1701,7 @@ static void draw_viewport_object_reconstruction(
if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0)
mul_v3_fl(camera_size, tracking_object->scale);
- glPushMatrix();
+ gpuPushMatrix();
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
/* current ogl matrix is translated in camera space, bundles should
@@ -1643,8 +1709,8 @@ static void draw_viewport_object_reconstruction(
* from current ogl matrix */
invert_m4_m4(imat, base->object->obmat);
- glMultMatrixf(imat);
- glMultMatrixf(mat);
+ gpuMultMatrix(imat);
+ gpuMultMatrix(mat);
}
else {
float obmat[4][4];
@@ -1653,7 +1719,7 @@ static void draw_viewport_object_reconstruction(
BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, obmat);
invert_m4_m4(imat, obmat);
- glMultMatrixf(imat);
+ gpuMultMatrix(imat);
}
for (track = tracksbase->first; track; track = track->next) {
@@ -1666,66 +1732,93 @@ static void draw_viewport_object_reconstruction(
continue;
if (dflag & DRAW_PICKING)
- GPU_select_load_id(base->selcol + (tracknr << 16));
+ GPU_select_load_id(base->object->select_color + (tracknr << 16));
- glPushMatrix();
- glTranslate3fv(track->bundle_pos);
- glScalef(v3d->bundle_size / 0.05f / camera_size[0],
- v3d->bundle_size / 0.05f / camera_size[1],
- v3d->bundle_size / 0.05f / camera_size[2]);
+ gpuPushMatrix();
+ gpuTranslate3fv(track->bundle_pos);
+ gpuScale3f(v3d->bundle_size / 0.05f / camera_size[0],
+ v3d->bundle_size / 0.05f / camera_size[1],
+ v3d->bundle_size / 0.05f / camera_size[2]);
const int v3d_drawtype = view3d_effective_drawtype(v3d);
if (v3d_drawtype == OB_WIRE) {
+ unsigned char color[4];
+ const unsigned char *color_ptr = NULL;
if ((dflag & DRAW_CONSTCOLOR) == 0) {
if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
+ color_ptr = ob_wire_col;
}
else {
- glColor3fv(track->color);
+ rgba_float_to_uchar(color, track->color);
+ color_ptr = color;
}
}
- drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype);
+ drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype, color_ptr);
}
else if (v3d_drawtype > OB_WIRE) {
if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
+ Gwn_Batch *batch;
+
+ gpuScaleUniform(0.05f);
+
/* selection outline */
if (selected) {
+ batch = GPU_batch_preset_sphere_wire(1);
+
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ GWN_batch_uniform_4f(batch, "color",
+ ob_wire_col[0] / 255.f,
+ ob_wire_col[1] / 255.f,
+ ob_wire_col[2] / 255.f, 1.0f);
+ }
+ else {
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_DEPTH_ONLY);
}
-
glLineWidth(2.0f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- draw_bundle_sphere();
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ GWN_batch_draw(batch);
}
+ batch = GPU_batch_preset_sphere(0);
+
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
- else UI_ThemeColor(TH_BUNDLE_SOLID);
+ const float light[3] = {0.0f, 0.0f, 1.0f};
+ float col[3];
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING);
+ GWN_batch_uniform_3fv(batch, "light", light);
+
+ if (track->flag & TRACK_CUSTOMCOLOR) copy_v3_v3(col, track->color);
+ else UI_GetThemeColor3fv(TH_BUNDLE_SOLID, col);
+ GWN_batch_uniform_4f(batch, "color", col[0], col[1], col[2], 1.0f);
+ }
+ else {
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_DEPTH_ONLY);
}
- draw_bundle_sphere();
+ GWN_batch_draw(batch);
}
else {
+ unsigned char color[4];
+ const unsigned char *color_ptr = NULL;
if ((dflag & DRAW_CONSTCOLOR) == 0) {
if (selected) {
- glColor3ubv(ob_wire_col);
+ color_ptr = ob_wire_col;
}
else {
- if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
- else UI_ThemeColor(TH_WIRE);
+ if (track->flag & TRACK_CUSTOMCOLOR) rgba_float_to_uchar(color, track->color);
+ else UI_GetThemeColor4ubv(TH_WIRE, color);
+
+ color_ptr = color;
}
}
- drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype);
+ drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype, color_ptr);
}
}
- glPopMatrix();
+ gpuPopMatrix();
if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) {
float pos[3];
@@ -1745,22 +1838,27 @@ static void draw_viewport_object_reconstruction(
MovieTrackingReconstruction *reconstruction;
reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object);
- if (reconstruction->camnr) {
+ if (reconstruction->camnr >= 2) {
MovieReconstructedCamera *camera = reconstruction->cameras;
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_CAMERA_PATH);
- UI_ThemeColor(TH_CAMERA_PATH);
glLineWidth(2.0f);
- glBegin(GL_LINE_STRIP);
+ immBegin(GWN_PRIM_LINE_STRIP, reconstruction->camnr);
for (int a = 0; a < reconstruction->camnr; a++, camera++) {
- glVertex3fv(camera->mat[3]);
+ immVertex3fv(pos, camera->mat[3]);
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
}
}
- glPopMatrix();
+ gpuPopMatrix();
*global_track_index = tracknr;
}
@@ -1795,67 +1893,65 @@ static void draw_viewport_reconstruction(
/* restore */
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
- }
-
if (dflag & DRAW_PICKING)
- GPU_select_load_id(base->selcol);
+ GPU_select_load_id(base->object->select_color);
}
-static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], const GLenum mode)
+/* camera frame */
+static void drawcamera_frame(float vec[4][3], bool filled, unsigned pos)
{
- glBegin(mode);
- glVertex3fv(near_plane[0]);
- glVertex3fv(far_plane[0]);
- glVertex3fv(far_plane[1]);
- glVertex3fv(near_plane[1]);
- glEnd();
-
- glBegin(mode);
- glVertex3fv(near_plane[1]);
- glVertex3fv(far_plane[1]);
- glVertex3fv(far_plane[2]);
- glVertex3fv(near_plane[2]);
- glEnd();
-
- glBegin(mode);
- glVertex3fv(near_plane[2]);
- glVertex3fv(far_plane[2]);
- glVertex3fv(far_plane[3]);
- glVertex3fv(near_plane[3]);
- glEnd();
-
- glBegin(mode);
- glVertex3fv(far_plane[3]);
- glVertex3fv(near_plane[3]);
- glVertex3fv(near_plane[0]);
- glVertex3fv(far_plane[0]);
- glEnd();
+ immBegin(filled ? GWN_PRIM_TRI_FAN : GWN_PRIM_LINE_LOOP, 4);
+ immVertex3fv(pos, vec[0]);
+ immVertex3fv(pos, vec[1]);
+ immVertex3fv(pos, vec[2]);
+ immVertex3fv(pos, vec[3]);
+ immEnd();
}
-/* camera frame */
-static void drawcamera_frame(float vec[4][3], const GLenum mode)
+/* center point to camera frame */
+static void drawcamera_framelines(float vec[4][3], float origin[3], unsigned pos)
{
- glBegin(mode);
- glVertex3fv(vec[0]);
- glVertex3fv(vec[1]);
- glVertex3fv(vec[2]);
- glVertex3fv(vec[3]);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 8);
+ immVertex3fv(pos, origin);
+ immVertex3fv(pos, vec[0]);
+ immVertex3fv(pos, origin);
+ immVertex3fv(pos, vec[1]);
+ immVertex3fv(pos, origin);
+ immVertex3fv(pos, vec[2]);
+ immVertex3fv(pos, origin);
+ immVertex3fv(pos, vec[3]);
+ immEnd();
}
-/* center point to camera frame */
-static void drawcamera_framelines(float vec[4][3], float origin[3])
+static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], bool filled, unsigned pos)
{
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vec[1]);
- glVertex3fv(origin);
- glVertex3fv(vec[0]);
- glVertex3fv(vec[3]);
- glVertex3fv(origin);
- glVertex3fv(vec[2]);
- glEnd();
+ drawcamera_frame(near_plane, filled, pos);
+ drawcamera_frame(far_plane, filled, pos);
+
+ if (filled) {
+ immBegin(GWN_PRIM_TRI_STRIP, 10);
+
+ immVertex3fv(pos, near_plane[0]);
+ immVertex3fv(pos, far_plane[0]);
+ immVertex3fv(pos, near_plane[1]);
+ immVertex3fv(pos, far_plane[1]);
+ immVertex3fv(pos, near_plane[2]);
+ immVertex3fv(pos, far_plane[2]);
+ immVertex3fv(pos, near_plane[3]);
+ immVertex3fv(pos, far_plane[3]);
+ immVertex3fv(pos, near_plane[0]);
+ immVertex3fv(pos, far_plane[0]);
+
+ immEnd();
+ }
+ else {
+ immBegin(GWN_PRIM_LINES, 8);
+ for (int i = 0; i < 4; ++i) {
+ immVertex3fv(pos, near_plane[i]);
+ immVertex3fv(pos, far_plane[i]);
+ }
+ immEnd();
+ }
}
static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob)
@@ -1867,7 +1963,7 @@ static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob)
static void drawcamera_stereo3d(
Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const Camera *cam,
- float vec[4][3], float drawsize, const float scale[3])
+ float vec[4][3], float drawsize, const float scale[3], unsigned pos)
{
float obmat[4][4];
float vec_lr[2][4][3];
@@ -1883,15 +1979,15 @@ static void drawcamera_stereo3d(
zero_v3(tvec);
- glPushMatrix();
+ /* caller bound GPU_SHADER_3D_UNIFORM_COLOR, passed in pos attribute ID */
for (int i = 0; i < 2; i++) {
ob = BKE_camera_multiview_render(scene, ob, names[i]);
cam_lr[i] = ob->data;
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix(rv3d->viewmat);
BKE_camera_multiview_model_matrix(&scene->r, ob, names[i], obmat);
- glMultMatrixf(obmat);
+ gpuMultMatrix(obmat);
copy_m3_m3(vec_lr[i], vec);
copy_v3_v3(vec_lr[i][3], vec[3]);
@@ -1908,10 +2004,10 @@ static void drawcamera_stereo3d(
if (is_stereo3d_cameras) {
/* camera frame */
- drawcamera_frame(vec_lr[i], GL_LINE_LOOP);
+ drawcamera_frame(vec_lr[i], false, pos);
/* center point to camera frame */
- drawcamera_framelines(vec_lr[i], tvec);
+ drawcamera_framelines(vec_lr[i], tvec, pos);
}
/* connecting line */
@@ -1925,21 +2021,20 @@ static void drawcamera_stereo3d(
}
}
-
/* the remaining drawing takes place in the view space */
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix(rv3d->viewmat);
if (is_stereo3d_cameras) {
/* draw connecting lines */
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(2, 0xAAAA);
+ glLineStipple(2, 0xAAAA);
+ glEnable(GL_LINE_STIPPLE);
- glBegin(GL_LINES);
- glVertex3fv(origin[0]);
- glVertex3fv(origin[1]);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(pos, origin[0]);
+ immVertex3fv(pos, origin[1]);
+ immEnd();
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ glDisable(GL_LINE_STIPPLE);
}
/* draw convergence plane */
@@ -1964,21 +2059,21 @@ static void drawcamera_stereo3d(
add_v3_v3(local_plane[i], axis_center);
}
- glColor3f(0.0f, 0.0f, 0.0f);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
/* camera frame */
- drawcamera_frame(local_plane, GL_LINE_LOOP);
+ drawcamera_frame(local_plane, false, pos);
if (v3d->stereo3d_convergence_alpha > 0.0f) {
glEnable(GL_BLEND);
- glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
+ glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */
- glColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha);
- drawcamera_frame(local_plane, GL_QUADS);
+ drawcamera_frame(local_plane, true, pos);
glDisable(GL_BLEND);
- glDepthMask(1); /* restore write in zbuffer */
+ glDepthMask(GL_TRUE); /* restore write in zbuffer */
}
}
@@ -2003,37 +2098,31 @@ static void drawcamera_stereo3d(
}
/* camera frame */
- glColor3f(0.0f, 0.0f, 0.0f);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
- drawcamera_frame(near_plane, GL_LINE_LOOP);
- drawcamera_frame(far_plane, GL_LINE_LOOP);
- drawcamera_volume(near_plane, far_plane, GL_LINE_LOOP);
+ drawcamera_volume(near_plane, far_plane, false, pos);
if (v3d->stereo3d_volume_alpha > 0.0f) {
glEnable(GL_BLEND);
- glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
+ glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */
if (i == 0)
- glColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha);
+ immUniformColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha);
else
- glColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha);
+ immUniformColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha);
- drawcamera_frame(near_plane, GL_QUADS);
- drawcamera_frame(far_plane, GL_QUADS);
- drawcamera_volume(near_plane, far_plane, GL_QUADS);
+ drawcamera_volume(near_plane, far_plane, true, pos);
glDisable(GL_BLEND);
- glDepthMask(1); /* restore write in zbuffer */
+ glDepthMask(GL_TRUE); /* restore write in zbuffer */
}
}
}
-
- glPopMatrix();
}
/* flag similar to draw_object() */
-static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
- const short dflag, const unsigned char ob_wire_col[4])
+void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const short dflag, const unsigned char ob_wire_col[4])
{
/* a standing up pyramid with (0,0,0) as top */
Camera *cam;
@@ -2096,8 +2185,12 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
asp, shift, &drawsize, vec);
- glDisable(GL_CULL_FACE);
- glLineWidth(1);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) {
+ immUniformColor3ubv(ob_wire_col);
+ }
+ glLineWidth(1.0f);
/* camera frame */
if (!is_stereo3d_cameras) {
@@ -2106,27 +2199,29 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
float obmat[4][4];
bool is_left = v3d->multiview_eye == STEREO_LEFT_ID;
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
+ gpuPushMatrix();
+ gpuLoadMatrix(rv3d->viewmat);
BKE_camera_multiview_model_matrix(&scene->r, ob, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, obmat);
- glMultMatrixf(obmat);
+ gpuMultMatrix(obmat);
- drawcamera_frame(vec, GL_LINE_LOOP);
- glPopMatrix();
+ drawcamera_frame(vec, false, pos);
+ gpuPopMatrix();
}
else {
- drawcamera_frame(vec, GL_LINE_LOOP);
+ drawcamera_frame(vec, false, pos);
}
}
- if (is_view)
+ if (is_view) {
+ immUnbindProgram();
return;
+ }
zero_v3(tvec);
/* center point to camera frame */
if (!is_stereo3d_cameras)
- drawcamera_framelines(vec, tvec);
+ drawcamera_framelines(vec, tvec, pos);
/* arrow on top */
tvec[2] = vec[1][2]; /* copy the depth */
@@ -2135,22 +2230,25 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
* for active cameras. We actually draw both outline+filled
* for active cameras so the wire can be seen side-on */
for (int i = 0; i < 2; i++) {
- if (i == 0) glBegin(GL_LINE_LOOP);
- else if (i == 1 && is_active) glBegin(GL_TRIANGLES);
+ if (i == 0) immBegin(GWN_PRIM_LINE_LOOP, 3);
+ else if (i == 1 && is_active) {
+ glDisable(GL_CULL_FACE); /* TODO: declarative state tracking */
+ immBegin(GWN_PRIM_TRIS, 3);
+ }
else break;
tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]);
tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
- glVertex3fv(tvec); /* left */
+ immVertex3fv(pos, tvec); /* left */
tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]);
- glVertex3fv(tvec); /* right */
+ immVertex3fv(pos, tvec); /* right */
tvec[0] = shift[0];
tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
- glVertex3fv(tvec); /* top */
+ immVertex3fv(pos, tvec); /* top */
- glEnd();
+ immEnd();
}
if ((dflag & DRAW_SCENESET) == 0) {
@@ -2161,16 +2259,15 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
copy_m4_m4(nobmat, ob->obmat);
normalize_m4(nobmat);
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
- glMultMatrixf(nobmat);
+ gpuLoadMatrix(rv3d->viewmat);
+ gpuMultMatrix(nobmat);
if (cam->flag & CAM_SHOWLIMITS) {
const unsigned char col[3] = {128, 128, 60}, col_hi[3] = {255, 255, 120};
- draw_limit_line(cam->clipsta, cam->clipend, dflag, (is_active ? col_hi : col));
+ draw_limit_line(cam->clipsta, cam->clipend, dflag, (is_active ? col_hi : col), pos);
/* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
- draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize);
+ draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize, pos);
}
if (cam->flag & CAM_SHOWMIST) {
@@ -2179,69 +2276,79 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
if (world) {
draw_limit_line(world->miststa, world->miststa + world->mistdist,
- dflag, (is_active ? col_hi : col));
+ dflag, (is_active ? col_hi : col), pos);
}
}
- glPopMatrix();
}
}
/* stereo cameras drawing */
if (is_stereo3d) {
- drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale);
+ drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale, pos);
}
+
+ immUnbindProgram();
}
/* flag similar to draw_object() */
-static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
- Object *UNUSED(ob), int UNUSED(flag))
+void drawspeaker(const unsigned char ob_wire_col[3])
{
- float vec[3];
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- glEnable(GL_BLEND);
- glLineWidth(1);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (ob_wire_col) {
+ immUniformColor3ubv(ob_wire_col);
+ }
+
+ glLineWidth(1.0f);
+
+ const int segments = 16;
for (int j = 0; j < 3; j++) {
- vec[2] = 0.25f * j - 0.125f;
+ float z = 0.25f * j - 0.125f;
- glBegin(GL_LINE_LOOP);
- for (int i = 0; i < 16; i++) {
- vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
- vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
- glVertex3fv(vec);
+ immBegin(GWN_PRIM_LINE_LOOP, segments);
+ for (int i = 0; i < segments; i++) {
+ float x = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
+ float y = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
+ immVertex3f(pos, x, y, z);
}
- glEnd();
+ immEnd();
}
for (int j = 0; j < 4; j++) {
- vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
- vec[1] = ((j % 2) * (j - 2)) * 0.5f;
- glBegin(GL_LINE_STRIP);
+ float x = (((j + 1) % 2) * (j - 1)) * 0.5f;
+ float y = ((j % 2) * (j - 2)) * 0.5f;
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
for (int i = 0; i < 3; i++) {
if (i == 1) {
- vec[0] *= 0.5f;
- vec[1] *= 0.5f;
+ x *= 0.5f;
+ y *= 0.5f;
}
- vec[2] = 0.25f * i - 0.125f;
- glVertex3fv(vec);
+ float z = 0.25f * i - 0.125f;
+ immVertex3f(pos, x, y, z);
}
- glEnd();
+ immEnd();
}
- glDisable(GL_BLEND);
+ immUnbindProgram();
}
-static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel)
+static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel,
+ unsigned int pos, unsigned int color)
{
BPoint *bp = lt->def;
const float *co = dl ? dl->verts : NULL;
+ float active_color[4], draw_color[4];
- const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX;
- UI_ThemeColor(color);
+ UI_GetThemeColor4fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, draw_color);
+ UI_GetThemeColor4fv(TH_ACTIVE_VERT, active_color);
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
+ immBeginAtMost(GWN_PRIM_POINTS, lt->pntsw * lt->pntsv * lt->pntsu);
for (int w = 0; w < lt->pntsw; w++) {
int wxt = (w == 0 || w == lt->pntsw - 1);
@@ -2253,12 +2360,12 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s
if (bp->hide == 0) {
/* check for active BPoint and ensure selected */
if ((bp == actbp) && (bp->f1 & SELECT)) {
- UI_ThemeColor(TH_ACTIVE_VERT);
- glVertex3fv(dl ? co : bp->vec);
- UI_ThemeColor(color);
+ immAttrib4fv(color, active_color);
+ immVertex3fv(pos, dl ? co : bp->vec);
}
else if ((bp->f1 & SELECT) == sel) {
- glVertex3fv(dl ? co : bp->vec);
+ immAttrib4fv(color, draw_color);
+ immVertex3fv(pos, dl ? co : bp->vec);
}
}
}
@@ -2266,32 +2373,32 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s
}
}
- glEnd();
+ immEnd();
}
-static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol)
+static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol,
+ unsigned int pos, unsigned int color)
{
int index = ((w * lt->pntsv + v) * lt->pntsu) + u;
if (actdef_wcol) {
float col[3];
MDeformWeight *mdw = defvert_find_index(lt->dvert + index, actdef_wcol - 1);
-
weight_to_rgb(col, mdw ? mdw->weight : 0.0f);
- glColor3fv(col);
-
+ immAttrib3fv(color, col);
}
if (dl) {
- glVertex3fv(&dl->verts[index * 3]);
+ immVertex3fv(pos, &dl->verts[index * 3]);
}
else {
- glVertex3fv(lt->def[index].vec);
+ immVertex3fv(pos, lt->def[index].vec);
}
}
#ifdef SEQUENCER_DAG_WORKAROUND
-static void ensure_curve_cache(Scene *scene, Object *object)
+static void ensure_curve_cache(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *object)
{
bool need_recalc = object->curve_cache == NULL;
/* Render thread might have freed the curve cache if the
@@ -2320,13 +2427,13 @@ static void ensure_curve_cache(Scene *scene, Object *object)
case OB_CURVE:
case OB_SURF:
case OB_FONT:
- BKE_displist_make_curveTypes(scene, object, false);
+ BKE_displist_make_curveTypes(eval_ctx, scene, object, false);
break;
case OB_MBALL:
- BKE_displist_make_mball(G.main->eval_ctx, scene, object);
+ BKE_displist_make_mball(eval_ctx, scene, object);
break;
case OB_LATTICE:
- BKE_lattice_modifiers_calc(scene, object);
+ BKE_lattice_modifiers_calc(eval_ctx, scene, object);
break;
}
}
@@ -2334,7 +2441,7 @@ static void ensure_curve_cache(Scene *scene, Object *object)
#endif
/* lattice color is hardcoded, now also shows weightgroup values in edit mode */
-static void drawlattice(View3D *v3d, Object *ob)
+static void drawlattice(View3D *v3d, Object *ob, const short dflag, const unsigned char ob_wire_col[4])
{
Lattice *lt = ob->data;
DispList *dl;
@@ -2347,15 +2454,37 @@ static void drawlattice(View3D *v3d, Object *ob)
if (is_edit) {
lt = lt->editlatt->latt;
- UI_ThemeColor(TH_WIRE_EDIT);
-
if (ob->defbase.first && lt->dvert) {
actdef_wcol = ob->actdef;
}
}
- glLineWidth(1);
- glBegin(GL_LINES);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int color, pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ if (actdef_wcol) {
+ color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (is_edit) {
+ immUniformThemeColor(TH_WIRE_EDIT);
+ }
+ else {
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ immUniformColor3ubv(ob_wire_col);
+ }
+ else {
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ glLineWidth(1.0f);
+ immBeginAtMost(GWN_PRIM_LINES, lt->pntsw * lt->pntsv * lt->pntsu * 6);
+
for (w = 0; w < lt->pntsw; w++) {
int wxt = (w == 0 || w == lt->pntsw - 1);
for (v = 0; v < lt->pntsv; v++) {
@@ -2364,30 +2493,40 @@ static void drawlattice(View3D *v3d, Object *ob)
int uxt = (u == 0 || u == lt->pntsu - 1);
if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
- drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol);
- drawlattice__point(lt, dl, u, v, w, actdef_wcol);
+ drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol, pos, color);
+ drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color);
}
if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
- drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol);
- drawlattice__point(lt, dl, u, v, w, actdef_wcol);
+ drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol, pos, color);
+ drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color);
}
if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
- drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol);
- drawlattice__point(lt, dl, u, v, w, actdef_wcol);
+ drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol, pos, color);
+ drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color);
}
}
}
}
- glEnd();
+
+ immEnd();
+ immUnbindProgram();
if (is_edit) {
BPoint *actbp = BKE_lattice_active_point_get(lt);
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- lattice_draw_verts(lt, dl, actbp, 0);
- lattice_draw_verts(lt, dl, actbp, 1);
-
+
+ Gwn_VertFormat *v_format = immVertexFormat();
+ unsigned int v_pos = GWN_vertformat_attr_add(v_format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int v_color = GWN_vertformat_attr_add(v_format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
+
+ lattice_draw_verts(lt, dl, actbp, 0, v_pos, v_color);
+ lattice_draw_verts(lt, dl, actbp, 1, v_pos, v_color);
+
+ immUnbindProgram();
+
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
}
@@ -2401,6 +2540,7 @@ typedef struct drawDMVertSel_userData {
int active;
unsigned char *col[3]; /* (base, sel, act) */
char sel_prev;
+ unsigned int pos, color;
} drawDMVertSel_userData;
static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3],
@@ -2412,17 +2552,18 @@ static void drawSelectedVertices__mapFunc(void *userData, int index, const float
if (!(mv->flag & ME_HIDE)) {
const char sel = (index == data->active) ? 2 : (mv->flag & SELECT);
if (sel != data->sel_prev) {
- glColor3ubv(data->col[sel]);
+ immAttrib3ubv(data->color, data->col[sel]);
data->sel_prev = sel;
}
- glVertex3fv(co);
+ immVertex3fv(data->pos, co);
}
}
static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
{
drawDMVertSel_userData data;
+ Gwn_VertFormat *format = immVertexFormat();
/* TODO define selected color */
unsigned char base_col[3] = {0x0, 0x0, 0x0};
@@ -2437,9 +2578,18 @@ static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
data.col[1] = sel_col;
data.col[2] = act_col;
- glBegin(GL_POINTS);
+ data.color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ if (dm->getNumVerts(dm) == 0) return;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ immBeginAtMost(GWN_PRIM_POINTS, dm->getNumVerts(dm));
dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
/* ************** DRAW MESH ****************** */
@@ -2486,25 +2636,34 @@ static void draw_dm_face_normals__mapFunc(void *userData, int index, const float
copy_v3_v3(n, no);
}
- glVertex3fv(cent);
- glVertex3f(cent[0] + n[0] * data->normalsize,
- cent[1] + n[1] * data->normalsize,
- cent[2] + n[2] * data->normalsize);
+ immVertex3fv(data->pos, cent);
+ immVertex3f(data->pos, cent[0] + n[0] * data->normalsize,
+ cent[1] + n[1] * data->normalsize,
+ cent[2] + n[2] * data->normalsize);
}
}
-static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
+static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id)
{
+ Gwn_VertFormat *format = immVertexFormat();
drawDMNormal_userData data;
data.bm = em->bm;
data.normalsize = scene->toolsettings->normalsize;
+ data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
calcDrawDMNormalScale(ob, &data);
- glBegin(GL_LINES);
+ if (dm->getNumPolys(dm) == 0) return;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(theme_id);
+
+ immBeginAtMost(GWN_PRIM_LINES, dm->getNumPolys(dm) * 2);
dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
@@ -2515,16 +2674,28 @@ static void draw_dm_face_centers__mapFunc(void *userData, int index, const float
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) &&
(BM_elem_flag_test(efa, BM_ELEM_SELECT) == data->select))
{
- glVertex3fv(cent);
+ immVertex3fv(data->pos, cent);
}
}
-static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select)
+static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select, const unsigned char fcol[3])
{
- drawBMSelect_userData data = {em->bm, select};
+ Gwn_VertFormat *format = immVertexFormat();
- glBegin(GL_POINTS);
+ drawBMSelect_userData data;
+ data.bm = em->bm;
+ data.select = select;
+ data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ if (dm->getNumPolys(dm) == 0) return;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(fcol);
+
+ immBeginAtMost(GWN_PRIM_POINTS, dm->getNumPolys(dm));
dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3])
@@ -2551,71 +2722,83 @@ static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float
copy_v3_v3(n, no);
}
- glVertex3fv(co);
- glVertex3f(co[0] + n[0] * data->normalsize,
- co[1] + n[1] * data->normalsize,
- co[2] + n[2] * data->normalsize);
+ immVertex3fv(data->pos, co);
+ immVertex3f(data->pos, co[0] + n[0] * data->normalsize,
+ co[1] + n[1] * data->normalsize,
+ co[2] + n[2] * data->normalsize);
}
}
-static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
+static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id)
{
drawDMNormal_userData data;
+ Gwn_VertFormat *format = immVertexFormat();
data.bm = em->bm;
data.normalsize = scene->toolsettings->normalsize;
+ data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
calcDrawDMNormalScale(ob, &data);
- glBegin(GL_LINES);
+ if (dm->getNumVerts(dm) == 0) return;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(theme_id);
+
+ immBeginAtMost(GWN_PRIM_LINES, dm->getNumVerts(dm) * 2);
dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
-/* Draw verts with color set based on selection */
-static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+static void draw_dm_verts_skin_root__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
drawDMVerts_userData *data = userData;
BMVert *eve = BM_vert_at_index(data->bm, index);
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
/* skin nodes: draw a red circle around the root node(s) */
- if (data->cd_vskin_offset != -1) {
- const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset);
- if (vs->flag & MVERT_SKIN_ROOT) {
- float radius = (vs->radius[0] + vs->radius[1]) * 0.5f;
- glEnd();
-
- glColor4ubv(data->th_skin_root);
- drawcircball(GL_LINES, co, radius, data->imat);
-
- glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
- glBegin(GL_POINTS);
- }
+ const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset);
+ if (vs->flag & MVERT_SKIN_ROOT) {
+ float radius = (vs->radius[0] + vs->radius[1]) * 0.5f;
+ imm_drawcircball(co, radius, data->imat, data->pos);
}
+ }
+}
+
+/* Draw verts with color set based on selection */
+static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ drawDMVerts_userData *data = userData;
+ BMVert *eve = BM_vert_at_index(data->bm, index);
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
/* draw active in a different color - no need to stop/start point drawing for this :D */
if (eve == data->eve_act) {
- glColor4ubv(data->th_editmesh_active);
- glVertex3fv(co);
-
- /* back to regular vertex color */
- glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
+ immAttrib4ubv(data->color, data->th_editmesh_active);
+ immVertex3fv(data->pos, co);
}
else {
- glVertex3fv(co);
+ immAttrib4ubv(data->color, data->sel ? data->th_vertex_select : data->th_vertex);
+ immVertex3fv(data->pos, co);
}
}
}
static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVert *eve_act,
- RegionView3D *rv3d)
+ RegionView3D *rv3d, const unsigned char col[4])
{
+ Gwn_VertFormat *format = immVertexFormat();
+
drawDMVerts_userData data;
data.sel = sel;
data.eve_act = eve_act;
data.bm = em->bm;
+ data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ data.color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
/* Cache theme values */
UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active);
@@ -2623,16 +2806,37 @@ static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVer
UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex);
UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root);
- /* For skin root drawing */
- data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN);
+ /* Set correct alpha */
+ data.th_editmesh_active[3] = data.th_vertex_select[3] = data.th_vertex[3] = data.th_skin_root[3] = col[3];
+
/* view-aligned matrix */
mul_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat);
invert_m4(data.imat);
+ if (dm->getNumVerts(dm) == 0) return;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
+
+ immBeginAtMost(GWN_PRIM_POINTS, dm->getNumVerts(dm));
dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
+
+ /* For skin root drawing */
+ data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN);
+
+ if (data.cd_vskin_offset != -1) {
+ data.pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4ubv(data.th_skin_root);
+
+ dm->foreachMappedVert(dm, draw_dm_verts_skin_root__mapFunc, &data, DM_FOREACH_NOP);
+
+ immUnbindProgram();
+ }
}
/* Draw edges with color set based on selection */
@@ -2938,24 +3142,32 @@ static void draw_dm_loop_normals__mapFunc(void *userData, int vertex_index, int
}
mul_v3_fl(vec, data->normalsize);
add_v3_v3(vec, co);
- glVertex3fv(co);
- glVertex3fv(vec);
+ immVertex3fv(data->pos, co);
+ immVertex3fv(data->pos, vec);
}
}
}
-static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
+static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id)
{
drawDMNormal_userData data;
data.bm = em->bm;
data.normalsize = scene->toolsettings->normalsize;
+ data.pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ if (dm->getNumLoops(dm) == 0) return;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(theme_id);
calcDrawDMNormalScale(ob, &data);
- glBegin(GL_LINES);
+ immBeginAtMost(GWN_PRIM_LINES, dm->getNumLoops(dm) * 2);
dm->foreachMappedLoop(dm, draw_dm_loop_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
/* Draw faces with color set based on selection
@@ -3072,7 +3284,7 @@ static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm)
data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
if (data.cd_layer_offset != -1) {
- glLineWidth(3.0);
+ glLineWidth(3.0f);
dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, &data);
}
}
@@ -3102,8 +3314,10 @@ static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
const float bweight = BM_ELEM_CD_GET_FLOAT(eve, data->cd_layer_offset);
if (bweight != 0.0f) {
- UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_BEVEL, bweight);
- glVertex3fv(co);
+ unsigned char col[3];
+ UI_GetThemeColorBlend3ubv(TH_VERTEX, TH_VERTEX_BEVEL, bweight, col);
+ immAttrib3ubv(data->col, col);
+ immVertex3fv(data->pos, co);
}
}
}
@@ -3117,11 +3331,21 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
data.bm = em->bm;
data.cd_layer_offset = CustomData_get_offset(&em->bm->vdata, CD_BWEIGHT);
+ /* is that ever true? */
if (data.cd_layer_offset != -1) {
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
- glBegin(GL_POINTS);
+ Gwn_VertFormat *format = immVertexFormat();
+ data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2.0f);
+
+ immBeginAtMost(GWN_PRIM_POINTS, dm->getNumVerts(dm));
dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
}
else {
@@ -3131,7 +3355,7 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
if (data.cd_layer_offset != -1) {
- glLineWidth(3.0);
+ glLineWidth(3.0f);
dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, &data);
}
}
@@ -3152,7 +3376,7 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
{
ToolSettings *ts = scene->toolsettings;
- if (v3d->zbuf) glDepthMask(0); /* disable write in zbuffer, zbuf select */
+ if (v3d->zbuf) glDepthMask(GL_FALSE); /* disable write in zbuffer, zbuf select */
for (int sel = 0; sel < 2; sel++) {
unsigned char col[4], fcol[4];
@@ -3182,15 +3406,12 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
}
if (ts->selectmode & SCE_SELECT_VERTEX) {
- glPointSize(size);
- glColor4ubv(col);
- draw_dm_verts(em, cageDM, sel, eve_act, rv3d);
+ draw_dm_verts(em, cageDM, sel, eve_act, rv3d, col);
}
if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
glPointSize(fsize);
- glColor4ubv(fcol);
- draw_dm_face_centers(em, cageDM, sel);
+ draw_dm_face_centers(em, cageDM, sel, fcol);
}
if (pass == 0) {
@@ -3200,7 +3421,7 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
}
}
- if (v3d->zbuf) glDepthMask(1);
+ if (v3d->zbuf) glDepthMask(GL_TRUE);
}
static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
@@ -3307,11 +3528,9 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
if (me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_EDGEANG)) {
BoundBox bb;
- bglMats mats = {{0}};
const rcti rect = {0, ar->winx, 0, ar->winy};
- view3d_get_transformation(ar, ar->regiondata, em->ob, &mats);
- ED_view3d_clipping_calc(&bb, clip_planes, &mats, &rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, ar, em->ob, &rect);
}
if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
@@ -3675,7 +3894,7 @@ static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
}
}
-static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
+static void draw_em_fancy(Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d,
Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const char dt)
{
@@ -3684,7 +3903,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
const bool use_occlude_wire = (dt > OB_WIRE) && (v3d->flag2 & V3D_OCCLUDE_WIRE);
bool use_depth_offset = false;
- glLineWidth(1);
+ glLineWidth(1.0f);
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
@@ -3693,7 +3912,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
draw_mesh_paint_weight_faces(finalDM, true, draw_em_fancy__setFaceOpts, me->edit_btmesh);
ED_view3d_polygon_offset(rv3d, 1.0);
- glDepthMask(0);
+ glDepthMask(GL_FALSE);
use_depth_offset = true;
}
else {
@@ -3713,7 +3932,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
else if (check_object_draw_texture(scene, v3d, dt)) {
- if (draw_glsl_material(scene, ob, v3d, dt)) {
+ if (draw_glsl_material(scene, view_layer, ob, v3d, dt)) {
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
finalDM->drawMappedFacesGLSL(finalDM, GPU_object_material_bind,
@@ -3723,7 +3942,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
glFrontFace(GL_CCW);
}
else {
- draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
+ draw_mesh_textured(scene, view_layer, v3d, rv3d, ob, finalDM, 0);
}
}
else {
@@ -3740,7 +3959,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
UI_ThemeColor(TH_WIRE_EDIT);
ED_view3d_polygon_offset(rv3d, 1.0);
- glDepthMask(0);
+ glDepthMask(GL_FALSE);
use_depth_offset = true;
}
else {
@@ -3790,7 +4009,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
#endif
glEnable(GL_BLEND);
- glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
+ glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */
/* don't draw unselected faces, only selected, this is MUCH nicer when texturing */
if (check_object_draw_texture(scene, v3d, dt))
@@ -3806,7 +4025,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
#endif
glDisable(GL_BLEND);
- glDepthMask(1); /* restore write in zbuffer */
+ glDepthMask(GL_TRUE); /* restore write in zbuffer */
}
else if (efa_act) {
/* even if draw faces is off it would be nice to draw the stipple face
@@ -3821,7 +4040,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
glEnable(GL_BLEND);
- glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
+ glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */
#ifdef WITH_FREESTYLE
draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act);
@@ -3830,7 +4049,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
#endif
glDisable(GL_BLEND);
- glDepthMask(1); /* restore write in zbuffer */
+ glDepthMask(GL_TRUE); /* restore write in zbuffer */
}
/* here starts all fancy draw-extra over */
@@ -3844,7 +4063,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
else {
if (me->drawflag & ME_DRAWSEAMS) {
UI_ThemeColor(TH_EDGE_SEAM);
- glLineWidth(2);
+ glLineWidth(2.0f);
draw_dm_edges_seams(em, cageDM);
@@ -3853,7 +4072,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
if (me->drawflag & ME_DRAWSHARP) {
UI_ThemeColor(TH_EDGE_SHARP);
- glLineWidth(2);
+ glLineWidth(2.0f);
draw_dm_edges_sharp(em, cageDM);
@@ -3863,7 +4082,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
#ifdef WITH_FREESTYLE
if (me->drawflag & ME_DRAW_FREESTYLE_EDGE && CustomData_has_layer(&em->bm->edata, CD_FREESTYLE_EDGE)) {
UI_ThemeColor(TH_FREESTYLE_EDGE_MARK);
- glLineWidth(2);
+ glLineWidth(2.0f);
draw_dm_edges_freestyle(em, cageDM);
@@ -3878,7 +4097,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
draw_dm_bweights(em, scene, cageDM);
}
- glLineWidth(1);
+ glLineWidth(1.0f);
draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act);
}
@@ -3886,16 +4105,13 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act, rv3d);
if (me->drawflag & ME_DRAWNORMALS) {
- UI_ThemeColor(TH_NORMAL);
- draw_dm_face_normals(em, scene, ob, cageDM);
+ draw_dm_face_normals(em, scene, ob, cageDM, TH_NORMAL);
}
if (me->drawflag & ME_DRAW_VNORMALS) {
- UI_ThemeColor(TH_VNORMAL);
- draw_dm_vert_normals(em, scene, ob, cageDM);
+ draw_dm_vert_normals(em, scene, ob, cageDM, TH_VNORMAL);
}
if (me->drawflag & ME_DRAW_LNORMALS) {
- UI_ThemeColor(TH_LNORMAL);
- draw_dm_loop_normals(em, scene, ob, cageDM);
+ draw_dm_loop_normals(em, scene, ob, cageDM, TH_LNORMAL);
}
if ((me->drawflag & (ME_DRAWEXTRA_EDGELEN |
@@ -3916,7 +4132,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
}
if (use_depth_offset) {
- glDepthMask(1);
+ glDepthMask(GL_TRUE);
ED_view3d_polygon_offset(rv3d, 0.0);
GPU_object_material_unbind();
}
@@ -3927,15 +4143,97 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
#endif
}
+static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *UNUSED(ar), View3D *UNUSED(v3d),
+ Object *UNUSED(ob), Mesh *me, BMEditMesh *UNUSED(em), DerivedMesh *UNUSED(cageDM), DerivedMesh *UNUSED(finalDM), const char UNUSED(dt))
+{
+ /* for now... something simple! */
+ Gwn_Batch *surface = DRW_mesh_batch_cache_get_all_triangles(me);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+
+ glEnable(GL_BLEND);
+
+ /* disable depth writes for transparent surface, so it doesn't interfere with itself */
+ glDepthMask(GL_FALSE);
+
+ GWN_batch_program_set_builtin(surface, GPU_SHADER_3D_UNIFORM_COLOR);
+ GWN_batch_uniform_4f(surface, "color", 1.0f, 0.5f, 0.0f, 0.5f);
+ GWN_batch_draw(surface);
+
+#if 0 /* until I understand finalDM better */
+ if (finalDM != cageDM) {
+ puts("finalDM != cageDM");
+ Gwn_Batch *finalSurface = MBC_get_all_triangles(finalDM);
+ GWN_batch_program_set_builtin(finalSurface, GPU_SHADER_3D_UNIFORM_COLOR);
+ GWN_batch_uniform_4f(finalSurface, "color", 0.0f, 0.0f, 0.0f, 0.05f);
+ GWN_batch_draw(finalSurface);
+ }
+#endif
+
+ glDepthMask(GL_TRUE);
+
+ /* now write surface depth so other objects won't poke through
+ * NOTE: does not help as much as desired
+ * TODO: draw edit object last to avoid this mess
+ */
+ GWN_batch_program_set_builtin(surface, GPU_SHADER_3D_DEPTH_ONLY);
+ GWN_batch_draw(surface);
+
+ if (GLEW_VERSION_3_2) {
+#if 0
+ Gwn_Batch *overlay = DRW_mesh_batch_cache_get_overlay_edges(me);
+ GWN_batch_program_set_builtin(overlay, GPU_SHADER_EDGES_OVERLAY);
+ GWN_batch_uniform_2f(overlay, "viewportSize", ar->winx, ar->winy);
+ GWN_batch_draw(overlay);
+#endif
+
+#if 0 /* TODO: use this SIMPLE variant for pure triangle meshes */
+ GWN_batch_program_set_builtin(surface, GPU_SHADER_EDGES_OVERLAY_SIMPLE);
+ /* use these defaults:
+ * const float edgeColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
+ * GWN_batch_uniform_4f(surface, "fillColor", edgeColor[0], edgeColor[1], edgeColor[2], 0.0f);
+ * GWN_batch_uniform_4fv(surface, "outlineColor", edgeColor);
+ * GWN_batch_uniform_1f(surface, "outlineWidth", 1.0f);
+ */
+ GWN_batch_uniform_2f(surface, "viewportSize", ar->winx, ar->winy);
+ GWN_batch_draw(surface);
+#endif
+ }
+ else {
+ Gwn_Batch *edges = DRW_mesh_batch_cache_get_all_edges(me);
+ GWN_batch_program_set_builtin(edges, GPU_SHADER_3D_UNIFORM_COLOR);
+ GWN_batch_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
+ glEnable(GL_LINE_SMOOTH);
+ glLineWidth(1.5f);
+ GWN_batch_draw(edges);
+ glDisable(GL_LINE_SMOOTH);
+ }
+
+#if 0 /* looks good even without points */
+ Gwn_Batch *verts = MBC_get_all_verts(me);
+ glEnable(GL_BLEND);
+
+ GWN_batch_program_set_builtin(verts, GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+ GWN_batch_uniform_4f(verts, "color", 0.0f, 0.0f, 0.0f, 1.0f);
+ GWN_batch_uniform_1f(verts, "size", UI_GetThemeValuef(TH_VERTEX_SIZE) * 1.5f);
+ GWN_batch_draw(verts);
+
+ glDisable(GL_BLEND);
+#endif
+}
+
/* Mesh drawing routines */
-static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
+void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm, const unsigned char ob_wire_col[4]) /* LEGACY */
{
if ((v3d->transp == false) && /* not when we draw the transparent pass */
(ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */
{
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- glDepthMask(0);
+ glDepthMask(GL_FALSE);
+
+ if (ob_wire_col) glColor4ubv(ob_wire_col);
/* if transparent, we cannot draw the edges for solid select... edges
* have no material info. GPU_object_material_visible will skip the
@@ -3949,7 +4247,49 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
dm->drawEdges(dm, 0, 1);
}
- glDepthMask(1);
+ glDepthMask(GL_TRUE);
+ }
+}
+
+static void draw_mesh_object_outline_new(View3D *v3d, RegionView3D *rv3d, Object *ob, Mesh *me, const bool is_active)
+{
+ if ((v3d->transp == false) && /* not when we draw the transparent pass */
+ (ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */
+ {
+ glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+ glDepthMask(GL_FALSE);
+
+ float outline_color[4];
+ UI_GetThemeColor4fv((is_active ? TH_ACTIVE : TH_SELECT), outline_color);
+
+#if 1 /* new version that draws only silhouette edges */
+ Gwn_Batch *fancy_edges = DRW_mesh_batch_cache_get_fancy_edges(me);
+
+ if (rv3d->persp == RV3D_ORTHO) {
+ GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
+ /* set eye vector, transformed to object coords */
+ float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */
+ mul_m3_v3(gpuGetNormalMatrixInverse(NULL), eye);
+ GWN_batch_uniform_3fv(fancy_edges, "eye", eye);
+ }
+ else {
+ GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_PERSP);
+ }
+
+ GWN_batch_uniform_1b(fancy_edges, "drawFront", false);
+ GWN_batch_uniform_1b(fancy_edges, "drawBack", false);
+ GWN_batch_uniform_1b(fancy_edges, "drawSilhouette", true);
+ GWN_batch_uniform_4fv(fancy_edges, "silhouetteColor", outline_color);
+
+ GWN_batch_draw(fancy_edges);
+#else /* alternate version that matches look of old viewport (but more efficient) */
+ Gwn_Batch *batch = MBC_get_all_edges(dm);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ GWN_batch_uniform_4fv(batch, "color", outline_color);
+ GWN_batch_draw(batch);
+#endif
+
+ glDepthMask(GL_TRUE);
}
}
@@ -3959,19 +4299,20 @@ 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,
- const char dt, const unsigned char ob_wire_col[4], const short dflag)
+static void draw_mesh_fancy(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
#ifdef WITH_GAMEENGINE
- Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, scene) : base->object;
+ Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, view_layer) : base->object;
#else
Object *ob = base->object;
#endif
Mesh *me = ob->data;
eWireDrawMode draw_wire = OBDRAW_WIRE_OFF;
bool /* no_verts,*/ no_edges, no_faces;
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
- const bool is_obact = (ob == OBACT);
+ DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, scene->customdata_mask);
+ const bool is_obact = (ob == OBACT(view_layer));
int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0;
if (!dm)
@@ -4007,12 +4348,12 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if (dt == OB_BOUNDBOX) {
if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0)
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
else if ((no_faces && no_edges) ||
((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob)))
{
- glPointSize(1.5);
+ glPointSize(1.5f);
dm->drawVerts(dm);
}
else if ((dt == OB_WIRE) || no_faces) {
@@ -4025,19 +4366,19 @@ 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))
{
- draw_mesh_object_outline(v3d, ob, dm);
+ draw_mesh_object_outline(v3d, ob, dm, ob_wire_col);
}
- if (draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
+ if (draw_glsl_material(scene, view_layer, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
Paint *p;
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene))) {
+ if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene, view_layer))) {
GPUVertexAttribs gattribs;
float planes[4][4];
float (*fpl)[4] = NULL;
@@ -4045,7 +4386,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if (ob->sculpt->partial_redraw) {
if (ar->do_draw & RGN_DRAW_PARTIAL) {
- ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob);
+ ED_sculpt_redraw_planes_get(planes, ar, ob);
fpl = planes;
ob->sculpt->partial_redraw = 0;
}
@@ -4070,7 +4411,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
draw_mesh_face_select(rv3d, me, dm, false);
}
else {
- draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
+ draw_mesh_textured(scene, view_layer, v3d, rv3d, ob, dm, draw_flags);
}
if (draw_loose && !(draw_flags & DRAW_FACE_SELECT)) {
@@ -4096,11 +4437,11 @@ 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))
{
- draw_mesh_object_outline(v3d, ob, dm);
+ draw_mesh_object_outline(v3d, ob, dm, ob_wire_col);
}
/* materials arent compatible with vertex colors */
@@ -4120,23 +4461,23 @@ 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))
{
- draw_mesh_object_outline(v3d, ob, dm);
+ draw_mesh_object_outline(v3d, ob, dm, ob_wire_col);
}
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- if (ob->sculpt && (p = BKE_paint_get_active(scene))) {
+ if (ob->sculpt && (p = BKE_paint_get_active(scene, view_layer))) {
float planes[4][4];
float (*fpl)[4] = NULL;
const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
if (ob->sculpt->partial_redraw) {
if (ar->do_draw & RGN_DRAW_PARTIAL) {
- ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob);
+ ED_sculpt_redraw_planes_get(planes, ar, ob);
fpl = planes;
ob->sculpt->partial_redraw = 0;
}
@@ -4177,7 +4518,9 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if ((dflag & DRAW_CONSTCOLOR) == 0) {
if (is_obact && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f);
+ float color[3];
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f, color);
+ glColor3fv(color);
}
else {
glColor3ubv(ob_wire_col);
@@ -4195,14 +4538,14 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
*/
if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) {
ED_view3d_polygon_offset(rv3d, 1.0);
- glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
+ glDepthMask(GL_FALSE); /* disable write in zbuffer, selected edge wires show better */
}
glLineWidth(1.0f);
dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0);
if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) {
- glDepthMask(1);
+ glDepthMask(GL_TRUE);
ED_view3d_polygon_offset(rv3d, 0.0);
}
}
@@ -4221,8 +4564,9 @@ 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,
- const char dt, const unsigned char ob_wire_col[4], const short dflag)
+static bool draw_mesh_object(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
Object *ob = base->object;
Object *obedit = scene->obedit;
@@ -4233,7 +4577,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3
/* If we are drawing shadows and any of the materials don't cast a shadow,
* then don't draw the object */
if (v3d->flag2 & V3D_RENDER_SHADOW) {
- for (int i = 1; i <= ob->totcol; ++i) {
+ for (int i = 0; i < ob->totcol; ++i) {
Material *ma = give_current_material(ob, i);
if (ma && !(ma->mode2 & MA_CASTSHADOW)) {
return true;
@@ -4262,7 +4606,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3
}
else {
cageDM = editbmesh_get_derived_cage_and_final(
- scene, ob, em, scene->customdata_mask,
+ eval_ctx, scene, ob, em, scene->customdata_mask,
&finalDM);
}
@@ -4275,13 +4619,13 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3
if (use_material) {
if (dt > OB_WIRE) {
- const bool glsl = draw_glsl_material(scene, ob, v3d, dt);
+ const bool glsl = draw_glsl_material(scene, view_layer, ob, v3d, dt);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, glsl, NULL);
}
}
- draw_em_fancy(scene, ar, v3d, ob, em, cageDM, finalDM, dt);
+ draw_em_fancy(scene, view_layer, ar, v3d, ob, em, cageDM, finalDM, dt);
if (use_material) {
GPU_end_object_materials();
@@ -4294,16 +4638,16 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3
/* ob->bb was set by derived mesh system, do NULL check just to be sure */
if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) {
if (dt > OB_WIRE) {
- const bool glsl = draw_glsl_material(scene, ob, v3d, dt);
+ const bool glsl = draw_glsl_material(scene, view_layer, ob, v3d, dt);
if (dt == OB_SOLID || glsl) {
const bool check_alpha = check_alpha_pass(base);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, glsl,
(check_alpha) ? &do_alpha_after : NULL);
}
}
- draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
+ draw_mesh_fancy(eval_ctx, scene, view_layer, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
GPU_end_object_materials();
@@ -4311,7 +4655,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) {
@@ -4335,18 +4679,551 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3
return retval;
}
+static void make_color_variations(const unsigned char base_ubyte[4], float low[4], float med[4], float high[4], const bool other_obedit)
+{
+ /* original idea: nice variations (lighter & darker shades) of base color
+ * current implementation uses input color as high; med & low get closer to background color
+ */
+
+ float bg[3];
+ UI_GetThemeColor3fv(TH_BACK, bg);
+
+ float base[4];
+ rgba_uchar_to_float(base, base_ubyte);
+
+ if (other_obedit) {
+ /* this object should fade away so user can focus on the object being edited */
+ interp_v3_v3v3(low, bg, base, 0.1f);
+ interp_v3_v3v3(med, bg, base, 0.2f);
+ interp_v3_v3v3(high, bg, base, 0.25f);
+ }
+ else {
+ interp_v3_v3v3(low, bg, base, 0.333f);
+ interp_v3_v3v3(med, bg, base, 0.667f);
+ copy_v3_v3(high, base);
+ }
+
+ /* use original alpha */
+ low[3] = base[3];
+ med[3] = base[3];
+ high[3] = base[3];
+}
+
+static void draw_mesh_fancy_new(EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const unsigned char ob_wire_col[4], const short dflag, const bool other_obedit)
+{
+ if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) {
+ /* too complicated! use existing methods */
+ /* TODO: move this into a separate depth pre-pass */
+ draw_mesh_fancy(eval_ctx, scene, view_layer, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
+ return;
+ }
+
+#ifdef WITH_GAMEENGINE
+ Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, view_layer) : base->object;
+#else
+ Object *ob = base->object;
+#endif
+ Mesh *me = ob->data;
+ eWireDrawMode draw_wire = OBDRAW_WIRE_OFF; /* could be bool draw_wire_overlay */
+ bool no_edges, no_faces;
+ DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, scene->customdata_mask);
+ const bool is_obact = (ob == OBACT(view_layer));
+ int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0;
+
+ if (!dm)
+ return;
+
+ const bool solid = dt >= OB_SOLID;
+ if (solid) {
+ DM_update_materials(dm, ob);
+ }
+
+ /* Check to draw dynamic paint colors (or weights from WeightVG modifiers).
+ * Note: Last "preview-active" modifier in stack will win! */
+ if (DM_get_loop_data_layer(dm, CD_PREVIEW_MLOOPCOL) && modifiers_isPreview(ob))
+ draw_flags |= DRAW_MODIFIERS_PREVIEW;
+
+ /* Unwanted combination */
+ if (draw_flags & DRAW_FACE_SELECT) {
+ draw_wire = OBDRAW_WIRE_OFF;
+ }
+ else if (ob->dtx & OB_DRAWWIRE) {
+ draw_wire = OBDRAW_WIRE_ON;
+ }
+
+ /* check polys instead of tessfaces because of dyntopo where tessfaces don't exist */
+ if (dm->type == DM_TYPE_CCGDM) {
+ no_edges = !subsurf_has_edges(dm);
+ no_faces = !subsurf_has_faces(dm);
+ }
+ else {
+ no_edges = (dm->getNumEdges(dm) == 0);
+ no_faces = (dm->getNumPolys(dm) == 0);
+ }
+
+ if (solid) {
+ /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
+ glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
+ }
+
+ if (dt == OB_BOUNDBOX) {
+ if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0)
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
+ }
+ else if ((no_faces && no_edges) ||
+ ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob)))
+ {
+ glPointSize(1.5f);
+ // dm->drawVerts(dm);
+ // TODO: draw smooth round points as a batch
+ }
+ else if ((dt == OB_WIRE) || no_faces) {
+ draw_wire = OBDRAW_WIRE_ON;
+
+ /* enable depth for wireframes */
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ glLineWidth(1.0f);
+
+#if 1 /* fancy wireframes */
+
+ Gwn_Batch *fancy_edges = DRW_mesh_batch_cache_get_fancy_edges(me);
+
+ if (rv3d->persp == RV3D_ORTHO) {
+ GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
+ /* set eye vector, transformed to object coords */
+ float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */
+ mul_m3_v3(gpuGetNormalMatrixInverse(NULL), eye);
+ GWN_batch_uniform_3fv(fancy_edges, "eye", eye);
+ }
+ else {
+ GWN_batch_program_set_builtin(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_PERSP);
+ }
+
+ float frontColor[4];
+ float backColor[4];
+ float outlineColor[4];
+ make_color_variations(ob_wire_col, backColor, frontColor, outlineColor, other_obedit);
+
+ GWN_batch_uniform_4fv(fancy_edges, "frontColor", frontColor);
+ GWN_batch_uniform_4fv(fancy_edges, "backColor", backColor);
+ GWN_batch_uniform_1b(fancy_edges, "drawFront", true);
+ GWN_batch_uniform_1b(fancy_edges, "drawBack", true); /* false here = backface cull */
+ GWN_batch_uniform_1b(fancy_edges, "drawSilhouette", false);
+
+ GWN_batch_draw(fancy_edges);
+
+ /* extra oomph for the silhouette contours */
+ glLineWidth(2.0f);
+ GWN_batch_program_use_begin(fancy_edges); /* hack to make the following uniforms stick */
+ GWN_batch_uniform_1b(fancy_edges, "drawFront", false);
+ GWN_batch_uniform_1b(fancy_edges, "drawBack", false);
+ GWN_batch_uniform_1b(fancy_edges, "drawSilhouette", true);
+ GWN_batch_uniform_4fv(fancy_edges, "silhouetteColor", outlineColor);
+
+ GWN_batch_draw(fancy_edges);
+
+#else /* simple wireframes */
+
+ Gwn_Batch *batch = MBC_get_all_edges(dm);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+
+ float color[4];
+ rgba_uchar_to_float(color, ob_wire_col);
+
+ GWN_batch_uniform_4fv(batch, "color", color);
+
+ GWN_batch_draw(batch);
+#endif
+ }
+ else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) ||
+ check_object_draw_texture(scene, v3d, dt))
+ {
+ bool draw_loose = true;
+
+ if ((v3d->flag & V3D_SELECT_OUTLINE) &&
+ ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ (base->flag & BASE_SELECTED) &&
+ !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
+ (draw_wire == OBDRAW_WIRE_OFF))
+ {
+ draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT(view_layer)));
+ }
+
+ if (draw_glsl_material(scene, view_layer, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
+ Paint *p;
+
+ glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
+
+ if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene, view_layer))) {
+ GPUVertexAttribs gattribs;
+ float planes[4][4];
+ float (*fpl)[4] = NULL;
+ const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
+
+ if (ob->sculpt->partial_redraw) {
+ if (ar->do_draw & RGN_DRAW_PARTIAL) {
+ ED_sculpt_redraw_planes_get(planes, ar, ob);
+ fpl = planes;
+ ob->sculpt->partial_redraw = 0;
+ }
+ }
+
+ GPU_object_material_bind(1, &gattribs);
+ dm->drawFacesSolid(dm, fpl, fast, NULL);
+ draw_loose = false;
+ }
+ else
+ dm->drawFacesGLSL(dm, GPU_object_material_bind);
+
+ GPU_object_material_unbind();
+
+ glFrontFace(GL_CCW);
+
+ if (draw_flags & DRAW_FACE_SELECT)
+ draw_mesh_face_select(rv3d, me, dm, false);
+ }
+ else {
+ draw_mesh_textured(scene, view_layer, v3d, rv3d, ob, dm, draw_flags);
+ }
+
+ if (draw_loose && !(draw_flags & DRAW_FACE_SELECT)) {
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ glColor3ubv(ob_wire_col);
+ }
+ glLineWidth(1.0f);
+ dm->drawLooseEdges(dm);
+ }
+ }
+ }
+ else if (dt == OB_SOLID) {
+ if (draw_flags & DRAW_MODIFIERS_PREVIEW) {
+ /* for object selection draws no shade */
+ if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) {
+ /* TODO: draw basic faces with GPU_SHADER_3D_DEPTH_ONLY */
+ }
+ else {
+ const float specular[3] = {0.47f, 0.47f, 0.47f};
+
+ /* draw outline */
+ /* TODO: move this into a separate pass */
+ if ((v3d->flag & V3D_SELECT_OUTLINE) &&
+ ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ (base->flag & BASE_SELECTED) &&
+ (draw_wire == OBDRAW_WIRE_OFF) &&
+ (ob->sculpt == NULL))
+ {
+ draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT(view_layer)));
+ }
+
+ /* materials arent compatible with vertex colors */
+ GPU_end_object_materials();
+
+ /* set default specular */
+ GPU_basic_shader_colors(NULL, specular, 35, 1.0f);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
+
+ dm->drawMappedFaces(dm, NULL, NULL, NULL, NULL, DM_DRAW_USE_COLORS | DM_DRAW_NEED_NORMALS);
+
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ }
+ }
+ else {
+ Paint *p;
+
+ if ((v3d->flag & V3D_SELECT_OUTLINE) &&
+ ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
+ (base->flag & BASE_SELECTED) &&
+ (draw_wire == OBDRAW_WIRE_OFF) &&
+ (ob->sculpt == NULL))
+ {
+ /* TODO: move this into a separate pass */
+ draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT(view_layer)));
+ }
+
+ glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
+
+ if (ob->sculpt && (p = BKE_paint_get_active(scene, view_layer))) {
+ float planes[4][4];
+ float (*fpl)[4] = NULL;
+ const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
+
+ if (ob->sculpt->partial_redraw) {
+ if (ar->do_draw & RGN_DRAW_PARTIAL) {
+ ED_sculpt_redraw_planes_get(planes, ar, ob);
+ fpl = planes;
+ ob->sculpt->partial_redraw = 0;
+ }
+ }
+
+ dm->drawFacesSolid(dm, fpl, fast, GPU_object_material_bind);
+ }
+ else
+ dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
+
+ glFrontFace(GL_CCW);
+
+ GPU_object_material_unbind();
+
+ if (!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ glColor3ubv(ob_wire_col);
+ }
+ glLineWidth(1.0f);
+ dm->drawLooseEdges(dm);
+ }
+ }
+ }
+ else if (dt == OB_PAINT) {
+ draw_mesh_paint(v3d, rv3d, ob, dm, draw_flags);
+
+ /* since we already draw wire as wp guide, don't draw over the top */
+ draw_wire = OBDRAW_WIRE_OFF;
+ }
+
+ if ((draw_wire != OBDRAW_WIRE_OFF) && /* draw extra wire */
+ /* when overriding with render only, don't bother */
+ (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_SOLID) == 0)) // <-- is this "== 0" in the right spot???
+ {
+ /* When using wireframe object draw in particle edit mode
+ * the mesh gets in the way of seeing the particles, fade the wire color
+ * with the background. */
+
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ /* TODO:
+ * Batch_UniformColor4ubv(ob_wire_col);
+ */
+ }
+
+ /* If drawing wire and drawtype is not OB_WIRE then we are
+ * overlaying the wires.
+ *
+ * No need for polygon offset because new technique is AWESOME.
+ */
+#if 0
+ glLineWidth(1.0f);
+ dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0);
+#else
+ /* something */
+#endif
+ }
+
+#if 0 // (merwin) what is this for?
+ if (is_obact && BKE_paint_select_vert_test(ob)) {
+ const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0;
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+
+ if (!use_depth) glDisable(GL_DEPTH_TEST);
+ else ED_view3d_polygon_offset(rv3d, 1.0);
+ drawSelectedVertices(dm, ob->data);
+ if (!use_depth) glEnable(GL_DEPTH_TEST);
+ else ED_view3d_polygon_offset(rv3d, 0.0);
+ }
+#endif
+
+ dm->release(dm);
+}
+
+static bool UNUSED_FUNCTION(draw_mesh_object_new)(const bContext *C, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const unsigned char ob_wire_col[4], const short dflag)
+{
+ EvaluationContext eval_ctx;
+ Object *ob = base->object;
+ Object *obedit = scene->obedit;
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ bool do_alpha_after = false, drawlinked = false, retval = false;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ if (v3d->flag2 & V3D_RENDER_SHADOW) {
+ /* TODO: handle shadow pass separately */
+ return true;
+ }
+
+ if (obedit && ob != obedit && ob->data == obedit->data) {
+ if (BKE_key_from_object(ob) || BKE_key_from_object(obedit)) {}
+ else if (ob->modifiers.first || obedit->modifiers.first) {}
+ else drawlinked = true;
+ }
+
+ /* backface culling */
+ const bool solid = dt > OB_WIRE;
+ const bool cullBackface = solid && (v3d->flag2 & V3D_BACKFACE_CULLING);
+ if (cullBackface) {
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ }
+
+ if (ob == obedit || drawlinked) {
+ DerivedMesh *finalDM, *cageDM;
+
+ if (obedit != ob) {
+ /* linked to the edit object */
+ finalDM = cageDM = editbmesh_get_derived_base(
+ ob, em, scene->customdata_mask);
+ }
+ else {
+ cageDM = editbmesh_get_derived_cage_and_final(
+ &eval_ctx, scene, ob, em, scene->customdata_mask,
+ &finalDM);
+ }
+
+ const bool use_material = solid && ((me->drawflag & ME_DRAWEIGHT) == 0);
+
+#if 0 // why update if not being used?
+ DM_update_materials(finalDM, ob);
+ if (cageDM != finalDM) {
+ DM_update_materials(cageDM, ob);
+ }
+#endif // moved to below
+
+ if (use_material) {
+ DM_update_materials(finalDM, ob);
+ if (cageDM != finalDM) {
+ DM_update_materials(cageDM, ob);
+ }
+
+ const bool glsl = draw_glsl_material(scene, view_layer, ob, v3d, dt);
+
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, glsl, NULL);
+ }
+
+ draw_em_fancy_new(scene, ar, v3d, ob, me, em, cageDM, finalDM, dt);
+
+ if (use_material) {
+ GPU_end_object_materials();
+ }
+
+ if (obedit != ob)
+ finalDM->release(finalDM);
+ }
+ else {
+ /* ob->bb was set by derived mesh system, do NULL check just to be sure */
+ if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) {
+ if (solid) {
+ const bool glsl = draw_glsl_material(scene, view_layer, ob, v3d, dt);
+
+ if (dt == OB_SOLID || glsl) {
+ const bool check_alpha = check_alpha_pass(base);
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, glsl,
+ (check_alpha) ? &do_alpha_after : NULL);
+ }
+ }
+
+ const bool other_obedit = obedit && (obedit != ob);
+
+ draw_mesh_fancy_new(&eval_ctx, scene, view_layer, ar, v3d, rv3d, base, dt, ob_wire_col, dflag, other_obedit);
+
+ GPU_end_object_materials();
+
+ if (me->totvert == 0) retval = true;
+ }
+ }
+
+ if (cullBackface)
+ glDisable(GL_CULL_FACE);
+
+ return retval;
+}
+
/* ************** DRAW DISPLIST ****************** */
+static void drawDispListVerts(Gwn_PrimType prim_type, const void *data, unsigned int vert_ct, const unsigned char wire_col[3])
+{
+ Gwn_VertFormat format = {0};
+ unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vert_ct);
+
+ GWN_vertbuf_attr_fill(vbo, pos_id, data);
+
+ Gwn_Batch *batch = GWN_batch_create_ex(prim_type, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ if (wire_col) {
+ GWN_batch_uniform_4f(batch, "color", wire_col[0] / 255.0f, wire_col[1] / 255.0f, wire_col[2] / 255.0f, 1.0f);
+ }
+ GWN_batch_draw(batch);
+ GWN_batch_discard(batch);
+}
+
+/* convert dispList with elem indices to batch, only support triangles and quads
+ * XXX : This is a huge perf issue. We should cache the resulting batches inside the object instead.
+ * But new viewport will do it anyway
+ * TODO implement flat drawing */
+static void drawDispListElem(
+ bool quads, bool UNUSED(smooth), bool ndata_is_single,
+ const float *data, const float *ndata, unsigned int data_len,
+ const int *elem, unsigned int elem_len, const unsigned char wire_col[3])
+{
+ Gwn_VertFormat format = {0};
+ int i;
+ const int *idx = elem;
+ unsigned int pos_id, nor_id;
+
+ pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ if (ndata) {
+ if (ndata_is_single) {
+ /* pass */
+ }
+ else {
+ nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+ }
+
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, (quads) ? elem_len * 2 : elem_len, 0xffffffff);
+
+ if (quads) {
+ for (i = elem_len; i; --i, idx += 4) {
+ GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
+ GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[2], idx[3]);
+ }
+ }
+ else {
+ for (i = elem_len; i; --i, idx += 3) {
+ GWN_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
+ }
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, data_len);
+
+ GWN_vertbuf_attr_fill(vbo, pos_id, data);
+
+ if (ndata) {
+ if (ndata_is_single) {
+ /* TODO: something like glNormal for a single value */
+ }
+ else {
+ GWN_vertbuf_attr_fill(vbo, nor_id, ndata);
+ }
+ }
+
+ Gwn_Batch *batch = GWN_batch_create_ex(
+ GWN_PRIM_TRIS, vbo, GWN_indexbuf_build(&elb), GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING);
+ if (wire_col) {
+ GWN_batch_uniform_4f(batch, "color", wire_col[0] / 255.0f, wire_col[1] / 255.0f, wire_col[2] / 255.0f, 1.0f);
+ }
+ GWN_batch_uniform_4f(batch, "color", 0.8f, 0.8f, 0.8f, 1.0f);
+ GWN_batch_uniform_3f(batch, "light", 0.0f, 0.0f, 1.0f);
+ GWN_batch_draw(batch);
+ GWN_batch_discard(batch);
+}
/**
* \param dl_type_mask Only draw types matching this mask.
* \return true when nothing was drawn
*/
-static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask)
+static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask, const unsigned char wire_col[3])
{
if (dlbase == NULL) return true;
- glEnableClientState(GL_VERTEX_ARRAY);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
for (DispList *dl = dlbase->first; dl; dl = dl->next) {
@@ -4357,83 +5234,76 @@ static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask)
if ((dl_type_mask & (1 << dl->type)) == 0) {
continue;
}
-
+
const float *data = dl->verts;
int parts;
switch (dl->type) {
case DL_SEGM:
-
- glVertexPointer(3, GL_FLOAT, 0, data);
-
for (parts = 0; parts < dl->parts; parts++)
- glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr);
-
+ drawDispListVerts(GWN_PRIM_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col);
break;
- case DL_POLY:
-
- glVertexPointer(3, GL_FLOAT, 0, data);
+ case DL_POLY:
for (parts = 0; parts < dl->parts; parts++)
- glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr);
-
+ drawDispListVerts(GWN_PRIM_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col);
break;
- case DL_SURF:
-
- glVertexPointer(3, GL_FLOAT, 0, data);
+ case DL_SURF:
for (parts = 0; parts < dl->parts; parts++) {
if (dl->flag & DL_CYCL_U)
- glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr);
+ drawDispListVerts(GWN_PRIM_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col);
else
- glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr);
+ drawDispListVerts(GWN_PRIM_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col);
}
+ float *data_aligned = MEM_mallocN(sizeof(float) * 3 * dl->parts, "aligned data");
for (int nr = 0; nr < dl->nr; nr++) {
int ofs = 3 * dl->nr;
+ int idx = 0;
data = (dl->verts) + 3 * nr;
parts = dl->parts;
- if (dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
- else glBegin(GL_LINE_STRIP);
-
while (parts--) {
- glVertex3fv(data);
+ copy_v3_v3(data_aligned + idx, data);
data += ofs;
+ idx += 3;
}
- glEnd();
-#if 0
- /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
- glVertexPointer(3, GL_FLOAT, sizeof(float) * 3 * dl->nr, data + 3 * nr);
- if (dl->flag & DL_CYCL_V)
- glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
- else
- glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
-#endif
+ if (dl->flag & DL_CYCL_V)
+ drawDispListVerts(GWN_PRIM_LINE_LOOP, data_aligned, dl->parts, wire_col);
+ else
+ drawDispListVerts(GWN_PRIM_LINE_STRIP, data_aligned, dl->parts, wire_col);
}
+
+ if (data_aligned)
+ MEM_freeN(data_aligned);
+
break;
case DL_INDEX3:
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index);
+ drawDispListElem(
+ false, true, false,
+ dl->verts, NULL, dl->nr,
+ dl->index, dl->parts, wire_col);
break;
case DL_INDEX4:
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index);
+ drawDispListElem(
+ true, true, false,
+ dl->verts, NULL, dl->nr,
+ dl->index, dl->parts, wire_col);
break;
}
}
- glDisableClientState(GL_VERTEX_ARRAY);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
return false;
}
-static bool drawDispListwire(ListBase *dlbase, const short ob_type)
+static bool drawDispListwire(ListBase *dlbase, const short ob_type, const unsigned char wire_col[3])
{
unsigned int dl_mask = 0xffffffff;
@@ -4442,27 +5312,25 @@ static bool drawDispListwire(ListBase *dlbase, const short ob_type)
dl_mask &= ~((1 << DL_INDEX3) | (1 << DL_INDEX4));
}
- return drawDispListwire_ex(dlbase, dl_mask);
+ return drawDispListwire_ex(dlbase, dl_mask, wire_col);
}
static bool index3_nors_incr = true;
-static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
+static void drawDispListsolid(ListBase *lb, Object *ob, const short UNUSED(dflag),
const unsigned char ob_wire_col[4], const bool use_glsl)
{
GPUVertexAttribs gattribs;
if (lb == NULL) return;
- glEnableClientState(GL_VERTEX_ARRAY);
-
/* track current material, -1 for none (needed for lines) */
short col = -1;
DispList *dl = lb->first;
while (dl) {
const float *data = dl->verts;
- const float *ndata = dl->nors;
+ //const float *ndata = dl->nors;
switch (dl->type) {
case DL_SEGM:
@@ -4472,15 +5340,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
col = -1;
}
- if ((dflag & DRAW_CONSTCOLOR) == 0)
- glColor3ubv(ob_wire_col);
-
- // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
- glBegin(GL_LINE_STRIP);
- for (int nr = dl->nr; nr; nr--, data += 3)
- glVertex3fv(data);
- glEnd();
+ drawDispListVerts(GWN_PRIM_LINE_STRIP, data, dl->nr, ob_wire_col);
}
break;
case DL_POLY:
@@ -4490,14 +5350,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
col = -1;
}
- /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
- //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
-
- glBegin(GL_LINE_LOOP);
- for (int nr = dl->nr; nr; nr--, data += 3)
- glVertex3fv(data);
- glEnd();
+ drawDispListVerts(GWN_PRIM_LINE_LOOP, data, dl->nr, ob_wire_col);
}
break;
case DL_SURF:
@@ -4507,15 +5360,12 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
GPU_object_material_bind(dl->col + 1, use_glsl ? &gattribs : NULL);
col = dl->col;
}
- /* FLAT/SMOOTH shading for surfaces */
- glShadeModel((dl->rt & CU_SMOOTH) ? GL_SMOOTH : GL_FLAT);
+ const unsigned int verts_len = dl->nr * dl->parts;
- glEnableClientState(GL_NORMAL_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- glNormalPointer(GL_FLOAT, 0, dl->nors);
- glDrawElements(GL_QUADS, 4 * dl->totindex, GL_UNSIGNED_INT, dl->index);
- glDisableClientState(GL_NORMAL_ARRAY);
- glShadeModel(GL_SMOOTH);
+ drawDispListElem(
+ true, (dl->rt & CU_SMOOTH) != 0, false,
+ dl->verts, dl->nors, verts_len,
+ dl->index, dl->totindex, ob_wire_col);
}
break;
@@ -4525,8 +5375,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
col = dl->col;
}
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
-
+#if 0
/* for polys only one normal needed */
if (index3_nors_incr) {
glEnableClientState(GL_NORMAL_ARRAY);
@@ -4534,11 +5383,17 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
}
else
glNormal3fv(ndata);
+#endif
+ /* special case, 'nors' is a single value */
+ drawDispListElem(
+ false, (dl->rt & CU_SMOOTH) != 0, true,
+ dl->verts, dl->nors, dl->nr,
+ dl->index, dl->parts, ob_wire_col);
- glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index);
-
+#if 0
if (index3_nors_incr)
glDisableClientState(GL_NORMAL_ARRAY);
+#endif
break;
@@ -4548,18 +5403,16 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
col = dl->col;
}
- glEnableClientState(GL_NORMAL_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- glNormalPointer(GL_FLOAT, 0, dl->nors);
- glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index);
- glDisableClientState(GL_NORMAL_ARRAY);
+ drawDispListElem(
+ true, true, false,
+ dl->verts, dl->nors, dl->nr,
+ dl->index, dl->parts, ob_wire_col);
break;
}
dl = dl->next;
}
- glDisableClientState(GL_VERTEX_ARRAY);
glFrontFace(GL_CCW);
if (col != -1) {
@@ -4574,7 +5427,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, ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt)
{
Object *ob = base->object;
DerivedMesh *dm = ob->derivedFinal;
@@ -4588,8 +5441,8 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d,
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
if (dt > OB_WIRE && dm->getNumPolys(dm)) {
- bool glsl = draw_glsl_material(scene, ob, v3d, dt);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
+ bool glsl = draw_glsl_material(scene, view_layer, ob, v3d, dt);
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, glsl, NULL);
if (!glsl)
dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
@@ -4610,7 +5463,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, ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
Object *ob = base->object;
@@ -4640,10 +5493,10 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
if (!render_only) {
/* when we have faces, only draw loose-wire */
if (has_faces) {
- drawDispListwire_ex(lb, (1 << DL_SEGM));
+ drawDispListwire_ex(lb, (1 << DL_SEGM), ob_wire_col);
}
else {
- drawDispListwire(lb, ob->type);
+ drawDispListwire(lb, ob->type, ob_wire_col);
}
}
@@ -4651,26 +5504,26 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
/* pass */
}
else {
- if (draw_glsl_material(scene, ob, v3d, dt)) {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
+ if (draw_glsl_material(scene, view_layer, ob, v3d, dt)) {
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, 1, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, true);
GPU_end_object_materials();
}
else {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, 0, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, false);
GPU_end_object_materials();
}
if (cu->editnurb && cu->bevobj == NULL && cu->taperobj == NULL && cu->ext1 == 0.0f && cu->ext2 == 0.0f) {
- cpack(0);
- drawDispListwire(lb, ob->type);
+ unsigned char col[4] = {0, 0, 0, 0};
+ drawDispListwire(lb, ob->type, col);
}
}
index3_nors_incr = true;
}
else {
if (!render_only || BKE_displist_has_faces(lb)) {
- return drawDispListwire(lb, ob->type);
+ return drawDispListwire(lb, ob->type, ob_wire_col);
}
}
break;
@@ -4686,19 +5539,19 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
if (dl->nors == NULL) BKE_displist_normals_add(lb);
- if (draw_glsl_material(scene, ob, v3d, dt)) {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
+ if (draw_glsl_material(scene, view_layer, ob, v3d, dt)) {
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, 1, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, true);
GPU_end_object_materials();
}
else {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, 0, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, false);
GPU_end_object_materials();
}
}
else {
- return drawDispListwire(lb, ob->type);
+ return drawDispListwire(lb, ob->type, ob_wire_col);
}
break;
case OB_MBALL:
@@ -4711,19 +5564,19 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
if (solid) {
- if (draw_glsl_material(scene, ob, v3d, dt)) {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
+ if (draw_glsl_material(scene, view_layer, ob, v3d, dt)) {
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, 1, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, true);
GPU_end_object_materials();
}
else {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, 0, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, false);
GPU_end_object_materials();
}
}
else {
- return drawDispListwire(lb, ob->type);
+ return drawDispListwire(lb, ob->type, ob_wire_col);
}
}
break;
@@ -4731,8 +5584,9 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
return false;
}
-static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
- const char dt, const short dflag, const unsigned char ob_wire_col[4])
+static bool drawDispList(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
bool retval;
@@ -4744,10 +5598,10 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba
}
#ifdef SEQUENCER_DAG_WORKAROUND
- ensure_curve_cache(scene, base->object);
+ ensure_curve_cache(eval_ctx, scene, base->object);
#endif
- if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == false) {
+ if (drawCurveDerivedMesh(scene, view_layer, v3d, rv3d, base, dt) == false) {
retval = false;
}
else {
@@ -4763,7 +5617,7 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba
glFrontFace(mode);
- retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ retval = drawDispList_nobackface(scene, view_layer, v3d, rv3d, base, dt, dflag, ob_wire_col);
if (mode != GL_CCW) {
glFrontFace(GL_CCW);
@@ -4778,16 +5632,63 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba
}
/* *********** drawing for particles ************* */
-static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select)
+/* stride : offset size in bytes
+ * col[4] : the color to use when *color is NULL, can be also NULL */
+static void draw_vertex_array(Gwn_PrimType prim_type, const float *vert, const float *nor, const float *color, int stride, int vert_ct, float col[4])
+{
+ Gwn_VertFormat format = {0};
+ unsigned int pos_id, nor_id, col_id;
+ pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ if (nor) nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ if (color) col_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, vert_ct);
+
+ if (stride == 0) {
+ GWN_vertbuf_attr_fill(vbo, pos_id, vert);
+ if (nor) GWN_vertbuf_attr_fill(vbo, nor_id, nor);
+ if (color) GWN_vertbuf_attr_fill(vbo, col_id, color);
+ }
+ else {
+ GWN_vertbuf_attr_fill_stride(vbo, pos_id, stride, vert);
+ if (nor) GWN_vertbuf_attr_fill_stride(vbo, nor_id, stride, nor);
+ if (color) GWN_vertbuf_attr_fill_stride(vbo, col_id, stride, color);
+ }
+
+ Gwn_Batch *batch = GWN_batch_create_ex(prim_type, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ if (nor && color) {
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR);
+ GWN_batch_uniform_3f(batch, "light", 0.0f, 0.0f, 1.0f);
+ }
+ else if (nor) {
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_SIMPLE_LIGHTING);
+ GWN_batch_uniform_3f(batch, "light", 0.0f, 0.0f, 1.0f);
+ if (col) GWN_batch_uniform_4fv(batch, "color", col);
+ }
+ else if (color) {
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_SMOOTH_COLOR);
+ }
+ else {
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ if (col) GWN_batch_uniform_4fv(batch, "color", col);
+ }
+ GWN_batch_draw(batch);
+ GWN_batch_discard(batch);
+}
+
+static void draw_particle_arrays_new(int draw_as, int ob_dt, int select,
+ const float *vert, const float *nor, const float *color,
+ int totpoint, float col[4])
{
/* draw created data arrays */
switch (draw_as) {
case PART_DRAW_AXIS:
case PART_DRAW_CROSS:
- glDrawArrays(GL_LINES, 0, 6 * totpoint);
+ draw_vertex_array(GWN_PRIM_LINES, vert, nor, color, 0, 6 * totpoint, col);
break;
case PART_DRAW_LINE:
- glDrawArrays(GL_LINES, 0, 2 * totpoint);
+ draw_vertex_array(GWN_PRIM_LINES, vert, nor, color, 0, 2 * totpoint, col);
break;
case PART_DRAW_BB:
if (ob_dt <= OB_WIRE || select)
@@ -4795,15 +5696,16 @@ static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int selec
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glDrawArrays(GL_QUADS, 0, 4 * totpoint);
+ draw_vertex_array(GWN_PRIM_TRIS, vert, nor, color, 0, 6 * totpoint, col);
break;
default:
- glDrawArrays(GL_POINTS, 0, totpoint);
+ draw_vertex_array(GWN_PRIM_POINTS, vert, nor, color, 0, totpoint, col);
break;
}
}
static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize,
- float imat[4][4], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd)
+ float imat[4][4], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd,
+ unsigned int pos)
{
float vec[3], vec2[3];
float *vd = NULL;
@@ -4913,24 +5815,19 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
}
case PART_DRAW_CIRC:
{
- drawcircball(GL_LINE_LOOP, state->co, pixsize, imat);
+ imm_drawcircball(state->co, pixsize, imat, pos);
break;
}
case PART_DRAW_BB:
{
float xvec[3], yvec[3], zvec[3], bb_center[3];
- if (cd) {
- cd[0] = cd[3] = cd[6] = cd[9] = ma_col[0];
- cd[1] = cd[4] = cd[7] = cd[10] = ma_col[1];
- cd[2] = cd[5] = cd[8] = cd[11] = ma_col[2];
- pdd->cd += 12;
- }
copy_v3_v3(bb->vec, state->co);
copy_v3_v3(bb->vel, state->vel);
psys_make_billboard(bb, xvec, yvec, zvec, bb_center);
-
+
+ /* First tri */
add_v3_v3v3(pdd->vd, bb_center, xvec);
add_v3_v3(pdd->vd, yvec); pdd->vd += 3;
@@ -4940,13 +5837,24 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
sub_v3_v3v3(pdd->vd, bb_center, xvec);
sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3;
+ /* Second tri */
+ add_v3_v3v3(pdd->vd, bb_center, xvec);
+ add_v3_v3(pdd->vd, yvec); pdd->vd += 3;
+
+ sub_v3_v3v3(pdd->vd, bb_center, xvec);
+ sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3;
+
add_v3_v3v3(pdd->vd, bb_center, xvec);
sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3;
- copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
- copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
- copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
- copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
+ if (cd) {
+ for (int i = 0; i < 6; i++, cd += 3, pdd->cd += 3) {
+ copy_v3_v3(cd, ma_col);
+ }
+ }
+ for (int i = 0; i < 6; i++, pdd->nd += 3) {
+ copy_v3_v3(pdd->nd, zvec);
+ }
break;
}
}
@@ -4954,7 +5862,8 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d,
ParticleKey *state, int draw_as,
float imat[4][4], ParticleBillboardData *bb, ParticleDrawData *pdd,
- const float ct, const float pa_size, const float r_tilt, const float pixsize_scale)
+ const float ct, const float pa_size, const float r_tilt, const float pixsize_scale,
+ unsigned int pos)
{
ParticleSettings *part = psys->part;
float pixsize;
@@ -4985,7 +5894,7 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d,
pixsize = ED_view3d_pixel_size(rv3d, state->co) * pixsize_scale;
- draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd);
+ draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd, pos);
}
/* unified drawing of all new particle systems draw types except dupli ob & group
* mostly tries to use vertex arrays for speed
@@ -4998,9 +5907,10 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d,
* 6. draw the arrays
* 7. clean up
*/
-static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d,
- Base *base, ParticleSystem *psys,
- const char ob_dt, const short dflag)
+static void draw_new_particle_system(
+ const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ Base *base, ParticleSystem *psys,
+ const char ob_dt, const short dflag)
{
Object *ob = base->object;
ParticleEditSettings *pset = PE_settings(scene);
@@ -5018,10 +5928,11 @@ 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};
+ unsigned int pos;
/* 1. */
if (part == NULL || !psys_check_enabled(ob, psys, G.is_rendering))
@@ -5030,7 +5941,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if (pars == NULL) return;
/* don't draw normal paths in edit mode */
- if (psys_in_edit_mode(scene, psys) && (pset->flag & PE_DRAW_PART) == 0)
+ if (psys_in_edit_mode(eval_ctx->view_layer, psys) && (pset->flag & PE_DRAW_PART) == 0)
return;
if (part->draw_as == PART_DRAW_REND)
@@ -5048,6 +5959,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
curvemapping_changed_all(psys->part->roughcurve);
/* 2. */
+ sim.eval_ctx = eval_ctx;
sim.scene = scene;
sim.ob = ob;
sim.psys = psys;
@@ -5083,16 +5995,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
copy_v3_v3(ma_col, &ma->r);
}
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(tcol);
- }
-
timestep = psys_get_timestep(&sim);
- if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) {
+ if ((ob->flag & OB_FROMGROUP) != 0) {
float mat[4][4];
mul_m4_m4m4(mat, ob->obmat, psys->imat);
- glMultMatrixf(mat);
+ gpuMultMatrix(mat);
}
/* needed for text display */
@@ -5212,7 +6120,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
tot_vec_size *= 2;
break;
case PART_DRAW_BB:
- tot_vec_size *= 4;
+ tot_vec_size *= 6; /* New OGL only understands tris, no choice here. */
create_ndata = 1;
break;
}
@@ -5266,6 +6174,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
totpoint = pdd->totpoint; /* draw data is up to date */
}
else {
+ if ((draw_as == PART_DRAW_CIRC) || (part->draw & PART_DRAW_SIZE)) {
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ imm_cpack(0xFFFFFF);
+ }
for (a = 0, pa = pars; a < totpart + totchild; a++, pa++) {
/* setup per particle individual stuff */
if (a < totpart) {
@@ -5336,7 +6249,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
draw_particle_data(psys, rv3d,
&state, draw_as, imat, &bb, psys->pdd,
- ct, pa_size, r_tilt, pixsize_scale);
+ ct, pa_size, r_tilt, pixsize_scale, pos);
totpoint++;
drawn = 1;
@@ -5348,7 +6261,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
draw_particle_data(psys, rv3d,
&state, draw_as, imat, &bb, psys->pdd,
- pa_time, pa_size, r_tilt, pixsize_scale);
+ pa_time, pa_size, r_tilt, pixsize_scale, pos);
totpoint++;
drawn = 1;
@@ -5370,7 +6283,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if (part->draw & PART_DRAW_SIZE) {
setlinestyle(3);
- drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
+ imm_drawcircball(state.co, pa_size, imat, pos);
setlinestyle(0);
}
@@ -5407,31 +6320,19 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
}
}
}
+ if ((draw_as == PART_DRAW_CIRC) || (part->draw & PART_DRAW_SIZE)) {
+ immUnbindProgram();
+ }
}
}
/* 6. */
glGetIntegerv(GL_POLYGON_MODE, polygonmode);
- glEnableClientState(GL_VERTEX_ARRAY);
if (draw_as == PART_DRAW_PATH) {
ParticleCacheKey **cache, *path;
float *cdata2 = NULL;
- /* setup gl flags */
- if (1) { //ob_dt > OB_WIRE) {
- glEnableClientState(GL_NORMAL_ARRAY);
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (part->draw_col == PART_DRAW_COL_MAT)
- glEnableClientState(GL_COLOR_ARRAY);
- }
-
- // XXX test
- GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
- }
-
if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
totpart = 0;
else if (psys->pathcache == NULL)
@@ -5442,41 +6343,28 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
path = cache[a];
if (path->segments > 0) {
- glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
-
- if (1) { //ob_dt > OB_WIRE) {
- glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (part->draw_col == PART_DRAW_COL_MAT) {
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
- }
- }
+ if (((dflag & DRAW_CONSTCOLOR) == 0) && (part->draw_col == PART_DRAW_COL_MAT)) {
+ draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, path->col, sizeof(ParticleCacheKey), path->segments + 1, NULL);
+ }
+ else {
+ float color[4];
+ rgba_uchar_to_float(color, tcol);
+ draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, NULL, sizeof(ParticleCacheKey), path->segments + 1, color);
}
-
- glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
}
}
if (part->type == PART_HAIR) {
if (part->draw & PART_DRAW_GUIDE_HAIRS) {
DerivedMesh *hair_dm = psys->hair_out_dm;
-
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
-
+
for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
if (pa->totkey > 1) {
HairKey *hkey = pa->hair;
- glVertexPointer(3, GL_FLOAT, sizeof(HairKey), hkey->world_co);
-
-#if 0 /* XXX use proper theme color here */
- UI_ThemeColor(TH_NORMAL);
-#else
- glColor3f(0.58f, 0.67f, 1.0f);
-#endif
-
- glDrawArrays(GL_LINE_STRIP, 0, pa->totkey);
+ /* XXX use proper theme color here */
+ float color[4] = {0.58f, 0.67f, 1.0f, 1.0f};
+ draw_vertex_array(GWN_PRIM_LINE_STRIP, hkey->world_co, NULL, NULL, sizeof(HairKey), pa->totkey, color);
}
}
@@ -5484,30 +6372,36 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
MVert *mvert = hair_dm->getVertArray(hair_dm);
int i;
- glColor3f(0.9f, 0.4f, 0.4f);
-
- glBegin(GL_LINES);
+ unsigned int pos_id = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3f(0.9f, 0.4f, 0.4f);
+
+ unsigned int count = 0;
for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
- for (i = 1; i < pa->totkey; ++i) {
- float v1[3], v2[3];
-
- copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co);
- copy_v3_v3(v2, mvert[pa->hair_index + i].co);
-
- mul_m4_v3(ob->obmat, v1);
- mul_m4_v3(ob->obmat, v2);
-
- glVertex3fv(v1);
- glVertex3fv(v2);
+ count += MAX2(pa->totkey - 1, 0);
+ }
+
+ if (count > 0) {
+ immBegin(GWN_PRIM_LINES, count * 2);
+ for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
+ for (i = 1; i < pa->totkey; ++i) {
+ float v1[3], v2[3];
+
+ copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co);
+ copy_v3_v3(v2, mvert[pa->hair_index + i].co);
+
+ mul_m4_v3(ob->obmat, v1);
+ mul_m4_v3(ob->obmat, v2);
+
+ immVertex3fv(pos_id, v1);
+ immVertex3fv(pos_id, v2);
+ }
}
+ immEnd();
}
- glEnd();
+
+ immUnbindProgram();
}
-
- glEnableClientState(GL_NORMAL_ARRAY);
- if ((dflag & DRAW_CONSTCOLOR) == 0)
- if (part->draw_col == PART_DRAW_COL_MAT)
- glEnableClientState(GL_COLOR_ARRAY);
}
if (part->draw & PART_DRAW_HAIR_GRID) {
@@ -5518,64 +6412,69 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
int *res = clmd->hair_grid_res;
int i;
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
-
+ unsigned int pos_id = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
if (select)
- UI_ThemeColor(TH_ACTIVE);
+ immUniformThemeColor(TH_ACTIVE);
else
- UI_ThemeColor(TH_WIRE);
- glBegin(GL_LINES);
- glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmin[2]);
- glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmin[2]);
- glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmin[2]);
- glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmin[2]);
+ immUniformThemeColor(TH_WIRE);
+
+ immBegin(GWN_PRIM_LINES, 24);
+ immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]);
+ immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]);
+ immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]);
+ immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]);
- glVertex3f(gmin[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmin[1], gmax[2]);
- glVertex3f(gmax[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmax[1], gmax[2]);
- glVertex3f(gmax[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmax[1], gmax[2]);
- glVertex3f(gmin[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmin[1], gmax[2]);
+ immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]);
+ immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]);
+ immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]);
+ immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]);
- glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmax[2]);
- glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmax[2]);
- glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmax[2]);
- glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmax[2]);
- glEnd();
+ immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]);
+ immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]);
+ immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]);
+ immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]);
+ immEnd();
if (select)
- UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -100);
+ immUniformThemeColorShadeAlpha(TH_ACTIVE, 0, -100);
else
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -100);
- glEnable(GL_BLEND);
- glBegin(GL_LINES);
- for (i = 1; i < res[0] - 1; ++i) {
- float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1));
- glVertex3f(f, gmin[1], gmin[2]); glVertex3f(f, gmax[1], gmin[2]);
- glVertex3f(f, gmax[1], gmin[2]); glVertex3f(f, gmax[1], gmax[2]);
- glVertex3f(f, gmax[1], gmax[2]); glVertex3f(f, gmin[1], gmax[2]);
- glVertex3f(f, gmin[1], gmax[2]); glVertex3f(f, gmin[1], gmin[2]);
- }
- for (i = 1; i < res[1] - 1; ++i) {
- float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1));
- glVertex3f(gmin[0], f, gmin[2]); glVertex3f(gmax[0], f, gmin[2]);
- glVertex3f(gmax[0], f, gmin[2]); glVertex3f(gmax[0], f, gmax[2]);
- glVertex3f(gmax[0], f, gmax[2]); glVertex3f(gmin[0], f, gmax[2]);
- glVertex3f(gmin[0], f, gmax[2]); glVertex3f(gmin[0], f, gmin[2]);
- }
- for (i = 1; i < res[2] - 1; ++i) {
- float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1));
- glVertex3f(gmin[0], gmin[1], f); glVertex3f(gmax[0], gmin[1], f);
- glVertex3f(gmax[0], gmin[1], f); glVertex3f(gmax[0], gmax[1], f);
- glVertex3f(gmax[0], gmax[1], f); glVertex3f(gmin[0], gmax[1], f);
- glVertex3f(gmin[0], gmax[1], f); glVertex3f(gmin[0], gmin[1], f);
+ immUniformThemeColorShadeAlpha(TH_WIRE, 0, -100);
+
+ int count = 0;
+ count += MAX2(0, res[0] - 2) * 8;
+ count += MAX2(0, res[1] - 2) * 8;
+ count += MAX2(0, res[2] - 2) * 8;
+
+ if (count >= 2) {
+ glEnable(GL_BLEND);
+ immBegin(GWN_PRIM_LINES, count);
+ for (i = 1; i < res[0] - 1; ++i) {
+ float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1));
+ immVertex3f(pos_id, f, gmin[1], gmin[2]); immVertex3f(pos_id, f, gmax[1], gmin[2]);
+ immVertex3f(pos_id, f, gmax[1], gmin[2]); immVertex3f(pos_id, f, gmax[1], gmax[2]);
+ immVertex3f(pos_id, f, gmax[1], gmax[2]); immVertex3f(pos_id, f, gmin[1], gmax[2]);
+ immVertex3f(pos_id, f, gmin[1], gmax[2]); immVertex3f(pos_id, f, gmin[1], gmin[2]);
+ }
+ for (i = 1; i < res[1] - 1; ++i) {
+ float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1));
+ immVertex3f(pos_id, gmin[0], f, gmin[2]); immVertex3f(pos_id, gmax[0], f, gmin[2]);
+ immVertex3f(pos_id, gmax[0], f, gmin[2]); immVertex3f(pos_id, gmax[0], f, gmax[2]);
+ immVertex3f(pos_id, gmax[0], f, gmax[2]); immVertex3f(pos_id, gmin[0], f, gmax[2]);
+ immVertex3f(pos_id, gmin[0], f, gmax[2]); immVertex3f(pos_id, gmin[0], f, gmin[2]);
+ }
+ for (i = 1; i < res[2] - 1; ++i) {
+ float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1));
+ immVertex3f(pos_id, gmin[0], gmin[1], f); immVertex3f(pos_id, gmax[0], gmin[1], f);
+ immVertex3f(pos_id, gmax[0], gmin[1], f); immVertex3f(pos_id, gmax[0], gmax[1], f);
+ immVertex3f(pos_id, gmax[0], gmax[1], f); immVertex3f(pos_id, gmin[0], gmax[1], f);
+ immVertex3f(pos_id, gmin[0], gmax[1], f); immVertex3f(pos_id, gmin[0], gmin[1], f);
+ }
+ immEnd();
+ glDisable(GL_BLEND);
}
- glEnd();
- glDisable(GL_BLEND);
-
- glEnableClientState(GL_NORMAL_ARRAY);
- if ((dflag & DRAW_CONSTCOLOR) == 0)
- if (part->draw_col == PART_DRAW_COL_MAT)
- glEnableClientState(GL_COLOR_ARRAY);
+
+ immUnbindProgram();
}
}
}
@@ -5584,27 +6483,17 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
cache = psys->childcache;
for (a = 0; a < totchild; a++) {
path = cache[a];
- glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
- if (1) { //ob_dt > OB_WIRE) {
- glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (part->draw_col == PART_DRAW_COL_MAT) {
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
- }
- }
+ if (((dflag & DRAW_CONSTCOLOR) == 0) && (part->draw_col == PART_DRAW_COL_MAT)) {
+ draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, path->col, sizeof(ParticleCacheKey), path->segments + 1, NULL);
+ }
+ else {
+ float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ draw_vertex_array(GWN_PRIM_LINE_STRIP, path->co, path->vel, NULL, sizeof(ParticleCacheKey), path->segments + 1, color);
}
-
- glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
}
/* restore & clean up */
- if (1) { //ob_dt > OB_WIRE) {
- if (part->draw_col == PART_DRAW_COL_MAT)
- glDisableClientState(GL_COLOR_ARRAY);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- }
-
if (cdata2) {
MEM_freeN(cdata2);
cdata2 = NULL;
@@ -5624,19 +6513,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
}
}
else if (pdd && ELEM(draw_as, 0, PART_DRAW_CIRC) == 0) {
- glDisableClientState(GL_COLOR_ARRAY);
- /* enable point data array */
if (pdd->vdata) {
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, pdd->vdata);
- }
- else
- glDisableClientState(GL_VERTEX_ARRAY);
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
if (select) {
- UI_ThemeColor(TH_ACTIVE);
+ float color[4];
+ UI_GetThemeColor4fv(TH_ACTIVE, color);
if (part->draw_size)
glPointSize(part->draw_size + 2);
@@ -5645,48 +6526,39 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
glLineWidth(3.0);
- draw_particle_arrays(draw_as, totpoint, ob_dt, 1);
+ draw_particle_arrays_new(draw_as, ob_dt, 1, pdd->vdata, NULL, NULL, totpoint, color);
}
- /* restore from select */
- glColor3fv(ma_col);
- }
-
- glPointSize(part->draw_size ? part->draw_size : 2.0);
- glLineWidth(1.0);
-
- /* enable other data arrays */
+ glPointSize(part->draw_size ? part->draw_size : 2.0);
+ glLineWidth(1.0);
- /* billboards are drawn this way */
- if (pdd->ndata && ob_dt > OB_WIRE) {
- glEnableClientState(GL_NORMAL_ARRAY);
- glNormalPointer(GL_FLOAT, 0, pdd->ndata);
- GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
- }
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (pdd->cdata) {
- glEnableClientState(GL_COLOR_ARRAY);
- glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
+#if 0
+ /* enable other data arrays */
+ /* billboards are drawn this way */
+ if (pdd->ndata && ob_dt > OB_WIRE) {
+ GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
}
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ if (pdd->cdata) {
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
+ }
+ }
+#endif
+
+ draw_particle_arrays_new(draw_as, ob_dt, 0, pdd->vdata, pdd->ndata, pdd->cdata, totpoint, NULL);
}
- draw_particle_arrays(draw_as, totpoint, ob_dt, 0);
pdd->flag |= PARTICLE_DRAW_DATA_UPDATED;
pdd->totpoint = totpoint;
}
if (pdd && pdd->vedata) {
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glDisableClientState(GL_COLOR_ARRAY);
- cpack(0xC0C0C0);
- }
-
- glVertexPointer(3, GL_FLOAT, 0, pdd->vedata);
-
- glDrawArrays(GL_LINES, 0, 2 * totve);
+ float color[4] = {0.75f, 0.75f, 0.75f, 1.0f};
+ draw_vertex_array(GWN_PRIM_LINES, pdd->vedata, NULL, NULL, 0, 2 * totve, color);
}
glPolygonMode(GL_FRONT, polygonmode[0]);
@@ -5695,9 +6567,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
/* 7. */
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
if (states)
MEM_freeN(states);
@@ -5720,32 +6589,28 @@ 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)) {
- glLoadMatrixf(rv3d->viewmat);
+ if ((ob->flag & OB_FROMGROUP) != 0) {
+ gpuLoadMatrix(rv3d->viewmat);
}
}
-static void draw_update_ptcache_edit(Scene *scene, Object *ob, PTCacheEdit *edit)
+static void draw_update_ptcache_edit(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, Object *ob, PTCacheEdit *edit)
{
if (edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED)
- PE_update_object(scene, ob, 0);
+ PE_update_object(eval_ctx, scene, view_layer, ob, 0);
/* create path and child path cache if it doesn't exist already */
- if (edit->pathcache == NULL)
- psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering);
+ if (edit->pathcache == NULL) {
+ psys_cache_edit_paths(eval_ctx, scene, ob, edit, CFRA, G.is_rendering);
+ }
}
static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
{
- ParticleCacheKey **cache, *path, *pkey;
- PTCacheEditPoint *point;
- PTCacheEditKey *key;
ParticleEditSettings *pset = PE_settings(scene);
- int i, k, totpoint = edit->totpoint, timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : 0;
- int totkeys = 1;
- float sel_col[3];
- float nosel_col[3];
- float *pathcol = NULL, *pcol;
+ const int totpoint = edit->totpoint;
+ const bool timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : false;
if (edit->pathcache == NULL)
return;
@@ -5757,50 +6622,71 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glDisable(GL_DEPTH_TEST);
/* get selection theme colors */
+ float sel_col[3], nosel_col[3];
UI_GetThemeColor3fv(TH_VERTEX_SELECT, sel_col);
UI_GetThemeColor3fv(TH_VERTEX, nosel_col);
/* draw paths */
- totkeys = (*edit->pathcache)->segments + 1;
+ const int totkeys = (*edit->pathcache)->segments + 1;
glEnable(GL_BLEND);
- pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data");
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
+ float *pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data");
if (pset->brushtype == PE_BRUSH_WEIGHT)
glLineWidth(2.0f);
- cache = edit->pathcache;
+ ParticleCacheKey **cache = edit->pathcache;
+ PTCacheEditPoint *point;
+ int i;
+
for (i = 0, point = edit->points; i < totpoint; i++, point++) {
- path = cache[i];
- glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+ ParticleCacheKey *path = cache[i];
+
+ Gwn_VertFormat format = {0};
+ unsigned int pos_id, col_id, col_comp;
+
+ col_comp = ((point->flag & PEP_HIDE) || timed) ? 4 : 3;
+
+ pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ col_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, col_comp, GWN_FETCH_FLOAT);
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, path->segments + 1);
+
+ GWN_vertbuf_attr_fill_stride(vbo, pos_id, sizeof(ParticleCacheKey), path->co);
+
+ float *pcol = pathcol;
if (point->flag & PEP_HIDE) {
- for (k = 0, pcol = pathcol; k < totkeys; k++, pcol += 4) {
+ for (int k = 0; k < totkeys; k++, pcol += 4) {
copy_v3_v3(pcol, path->col);
pcol[3] = 0.25f;
}
- glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
+ GWN_vertbuf_attr_fill(vbo, col_id, pathcol);
}
else if (timed) {
- for (k = 0, pcol = pathcol, pkey = path; k < totkeys; k++, pkey++, pcol += 4) {
+ ParticleCacheKey *pkey = path;
+ for (int k = 0; k < totkeys; k++, pkey++, pcol += 4) {
copy_v3_v3(pcol, pkey->col);
pcol[3] = 1.0f - fabsf((float)(CFRA) -pkey->time) / (float)pset->fade_frames;
}
- glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
+ GWN_vertbuf_attr_fill(vbo, col_id, pathcol);
+ }
+ else {
+ /* FIXME: shader wants 4 color components but the cache only contains ParticleCacheKey
+ * So alpha is random */
+ GWN_vertbuf_attr_fill_stride(vbo, col_id, sizeof(ParticleCacheKey), path->col);
}
- else
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
- glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
+ Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_SMOOTH_COLOR);
+ GWN_batch_draw(batch);
+ GWN_batch_discard(batch);
}
- if (pathcol) { MEM_freeN(pathcol); pathcol = pcol = NULL; }
-
+ if (pathcol) { MEM_freeN(pathcol); pathcol = NULL; }
/* draw edit vertices */
if (pset->selectmode != SCE_SELECT_PATH) {
@@ -5811,6 +6697,10 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
float *cd = NULL, *cdata = NULL;
int totkeys_visible = 0;
+ Gwn_VertFormat format = {0};
+ unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int col_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, (timed ? 4 : 3), GWN_FETCH_FLOAT);
+
for (i = 0, point = edit->points; i < totpoint; i++, point++)
if (!(point->flag & PEP_HIDE))
totkeys_visible += point->totkey;
@@ -5825,7 +6715,8 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
if (point->flag & PEP_HIDE)
continue;
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
+ PTCacheEditKey *key = point->keys;
+ for (int k = 0; k < point->totkey; k++, key++) {
if (pd) {
copy_v3_v3(pd, key->co);
pd += 3;
@@ -5850,14 +6741,20 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
if (point->flag & PEP_HIDE || point->totkey == 0)
continue;
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, point->totkey);
+
if (point->keys->flag & PEK_USE_WCO)
- glVertexPointer(3, GL_FLOAT, sizeof(PTCacheEditKey), point->keys->world_co);
+ GWN_vertbuf_attr_fill_stride(vbo, pos_id, sizeof(PTCacheEditKey), point->keys->world_co);
else
- glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), pd);
+ GWN_vertbuf_attr_fill(vbo, pos_id, pd);
- glColorPointer((timed ? 4 : 3), GL_FLOAT, (timed ? 4 : 3) * sizeof(float), cd);
+ GWN_vertbuf_attr_fill(vbo, col_id, cd);
- glDrawArrays(GL_POINTS, 0, point->totkey);
+ Gwn_Batch *batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_SMOOTH_COLOR);
+ GWN_batch_draw(batch);
+ GWN_batch_discard(batch);
pd += pd ? 3 * point->totkey : 0;
cd += (timed ? 4 : 3) * point->totkey;
@@ -5866,23 +6763,30 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
if (cdata) { MEM_freeN(cdata); cd = cdata = NULL; }
}
else if (pset->selectmode == SCE_SELECT_END) {
- glBegin(GL_POINTS);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int col_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+ immBeginAtMost(GWN_PRIM_POINTS, totpoint);
for (i = 0, point = edit->points; i < totpoint; i++, point++) {
if ((point->flag & PEP_HIDE) == 0 && point->totkey) {
- key = point->keys + point->totkey - 1;
- glColor3fv((key->flag & PEK_SELECT) ? sel_col : nosel_col);
+ PTCacheEditKey *key = point->keys + point->totkey - 1;
+ if ((key->flag & PEK_SELECT) != 0) {
+ immAttrib3fv(col_id, sel_col);
+ }
+ else {
+ immAttrib3fv(col_id, nosel_col);
+ }
/* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/
- glVertex3fv((key->flag & PEK_USE_WCO) ? key->world_co : key->co);
+ immVertex3fv(pos_id, (key->flag & PEK_USE_WCO) ? key->world_co : key->co);
}
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
}
glDisable(GL_BLEND);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
@@ -5895,130 +6799,137 @@ static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, flo
float tw = itw * drw_size;
float th = ith * drw_size;
- glBegin(GL_LINES);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
- glColor4ub(0x7F, 0x00, 0x00, 155);
+ immBegin(GWN_PRIM_LINES, 30);
+
+ immAttrib4ub(col, 0x7F, 0x00, 0x00, 155);
root[1] = root[2] = 0.0f;
root[0] = -drw_size;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
+ immVertex3fv(pos, root);
tip[1] = tip[2] = 0.0f;
tip[0] = drw_size;
mul_m3_v3(tr, tip);
add_v3_v3(tip, com);
- glVertex3fv(tip);
+ immVertex3fv(pos, tip);
root[1] = 0.0f; root[2] = tw;
root[0] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[1] = 0.0f; root[2] = -tw;
root[0] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[1] = tw; root[2] = 0.0f;
root[0] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[1] = -tw; root[2] = 0.0f;
root[0] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
- glColor4ub(0x00, 0x7F, 0x00, 155);
+ immAttrib4ub(col, 0x00, 0x7F, 0x00, 155);
root[0] = root[2] = 0.0f;
root[1] = -drw_size;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
+ immVertex3fv(pos, root);
tip[0] = tip[2] = 0.0f;
tip[1] = drw_size;
mul_m3_v3(tr, tip);
add_v3_v3(tip, com);
- glVertex3fv(tip);
+ immVertex3fv(pos, tip);
root[0] = 0.0f; root[2] = tw;
root[1] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = 0.0f; root[2] = -tw;
root[1] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = tw; root[2] = 0.0f;
root[1] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = -tw; root[2] = 0.0f;
root[1] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
- glColor4ub(0x00, 0x00, 0x7F, 155);
+ immAttrib4ub(col, 0x00, 0x00, 0x7F, 155);
root[0] = root[1] = 0.0f;
root[2] = -drw_size;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
+ immVertex3fv(pos, root);
tip[0] = tip[1] = 0.0f;
tip[2] = drw_size;
mul_m3_v3(tr, tip);
add_v3_v3(tip, com);
- glVertex3fv(tip);
+ immVertex3fv(pos, tip);
root[0] = 0.0f; root[1] = tw;
root[2] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = 0.0f; root[1] = -tw;
root[2] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = tw; root[1] = 0.0f;
root[2] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = -tw; root[1] = 0.0f;
root[2] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
+
+ immEnd();
- glEnd();
+ immUnbindProgram();
}
/* place to add drawers */
@@ -6027,7 +6938,7 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles)
{
if (nu->hide || hide_handles) return;
- if (nu->type == CU_BEZIER) {
+ if (nu->type == CU_BEZIER && nu->pntsu > 0) {
const float *fp;
@@ -6040,9 +6951,14 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles)
UI_GetThemeColor3ubv(basecol + a, handle_cols[a]);
}
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
glLineWidth(1.0f);
- glBegin(GL_LINES);
+ immBeginAtMost(GWN_PRIM_LINES, nu->pntsu * 4);
BezTriple *bezt = nu->bezt;
int a = nu->pntsu;
@@ -6051,33 +6967,35 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles)
if ((bezt->f2 & SELECT) == sel) {
fp = bezt->vec[0];
- glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]);
- glVertex3fv(fp);
- glVertex3fv(fp + 3);
+ immAttrib3ubv(col, handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]);
+ immVertex3fv(pos, fp);
+ immVertex3fv(pos, fp + 3);
- glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]);
- glVertex3fv(fp + 3);
- glVertex3fv(fp + 6);
+ immAttrib3ubv(col, handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]);
+ immVertex3fv(pos, fp + 3);
+ immVertex3fv(pos, fp + 6);
}
else if ((bezt->f1 & SELECT) == sel) {
fp = bezt->vec[0];
- glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]);
- glVertex3fv(fp);
- glVertex3fv(fp + 3);
+ immAttrib3ubv(col, handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]);
+ immVertex3fv(pos, fp);
+ immVertex3fv(pos, fp + 3);
}
else if ((bezt->f3 & SELECT) == sel) {
fp = bezt->vec[1];
- glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]);
- glVertex3fv(fp);
- glVertex3fv(fp + 3);
+ immAttrib3ubv(col, handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]);
+ immVertex3fv(pos, fp);
+ immVertex3fv(pos, fp + 3);
}
}
bezt++;
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
#undef TH_HANDLE_COL_TOT
@@ -6088,153 +7006,196 @@ static void drawhandlesN_active(Nurb *nu)
{
if (nu->hide) return;
- UI_ThemeColor(TH_ACTIVE_SPLINE);
- glLineWidth(2);
-
- glBegin(GL_LINES);
+ if (nu->type == CU_BEZIER && nu->pntsu > 0) {
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_ACTIVE_SPLINE);
+ glLineWidth(2.0f);
- if (nu->type == CU_BEZIER) {
+ immBeginAtMost(GWN_PRIM_LINES, nu->pntsu * 4);
BezTriple *bezt = nu->bezt;
int a = nu->pntsu;
while (a--) {
if (bezt->hide == 0) {
const float *fp = bezt->vec[0];
- glVertex3fv(fp);
- glVertex3fv(fp + 3);
+ immVertex3fv(pos, fp);
+ immVertex3fv(pos, fp + 3);
- glVertex3fv(fp + 3);
- glVertex3fv(fp + 6);
+ immVertex3fv(pos, fp + 3);
+ immVertex3fv(pos, fp + 6);
}
bezt++;
}
+ immEnd();
+ immUnbindProgram();
}
- glEnd();
-
- glColor3ub(0, 0, 0);
}
-static void drawvertsN(Nurb *nu, const char sel, const bool hide_handles, const void *vert)
+static void drawvertsN(const Nurb *nurb, const bool hide_handles, const void *vert)
{
- if (nu->hide) return;
+ const Nurb *nu;
- const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX;
+ // just quick guesstimate of how many verts to draw
+ int count = 0;
+ for (nu = nurb; nu; nu = nu->next) {
+ if (!nu->hide) {
+ if (nu->type == CU_BEZIER) {
+ count += nu->pntsu * 3;
+ }
+ else {
+ count += nu->pntsu * nu->pntsv;
+ }
+ }
+ }
+ if (count == 0) return;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
- UI_ThemeColor(color);
+ unsigned char vert_color[3];
+ unsigned char vert_color_select[3];
+ unsigned char vert_color_active[3];
+ UI_GetThemeColor3ubv(TH_VERTEX, vert_color);
+ UI_GetThemeColor3ubv(TH_VERTEX_SELECT, vert_color_select);
+ UI_GetThemeColor3ubv(TH_ACTIVE_VERT, vert_color_active);
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+
+ immBeginAtMost(GWN_PRIM_POINTS, count);
- glBegin(GL_POINTS);
-
- if (nu->type == CU_BEZIER) {
+ for (nu = nurb; nu; nu = nu->next) {
- BezTriple *bezt = nu->bezt;
- int a = nu->pntsu;
- while (a--) {
- if (bezt->hide == 0) {
- if (sel == 1 && bezt == vert) {
- UI_ThemeColor(TH_ACTIVE_VERT);
+ if (nu->hide) continue;
- if (bezt->f2 & SELECT) glVertex3fv(bezt->vec[1]);
- if (!hide_handles) {
- if (bezt->f1 & SELECT) glVertex3fv(bezt->vec[0]);
- if (bezt->f3 & SELECT) glVertex3fv(bezt->vec[2]);
- }
+ if (nu->type == CU_BEZIER) {
- UI_ThemeColor(color);
- }
- else if (hide_handles) {
- if ((bezt->f2 & SELECT) == sel) glVertex3fv(bezt->vec[1]);
- }
- else {
- if ((bezt->f1 & SELECT) == sel) glVertex3fv(bezt->vec[0]);
- if ((bezt->f2 & SELECT) == sel) glVertex3fv(bezt->vec[1]);
- if ((bezt->f3 & SELECT) == sel) glVertex3fv(bezt->vec[2]);
+ const BezTriple *bezt = nu->bezt;
+ int a = nu->pntsu;
+ while (a--) {
+ if (bezt->hide == 0) {
+ if (bezt == vert) {
+ immAttrib3ubv(color, bezt->f2 & SELECT ? vert_color_active : vert_color);
+ immVertex3fv(pos, bezt->vec[1]);
+ if (!hide_handles) {
+ immAttrib3ubv(color, bezt->f1 & SELECT ? vert_color_active : vert_color);
+ immVertex3fv(pos, bezt->vec[0]);
+ immAttrib3ubv(color, bezt->f3 & SELECT ? vert_color_active : vert_color);
+ immVertex3fv(pos, bezt->vec[2]);
+ }
+ }
+ else {
+ immAttrib3ubv(color, bezt->f2 & SELECT ? vert_color_select : vert_color);
+ immVertex3fv(pos, bezt->vec[1]);
+ if (!hide_handles) {
+ immAttrib3ubv(color, bezt->f1 & SELECT ? vert_color_select : vert_color);
+ immVertex3fv(pos, bezt->vec[0]);
+ immAttrib3ubv(color, bezt->f3 & SELECT ? vert_color_select : vert_color);
+ immVertex3fv(pos, bezt->vec[2]);
+ }
+ }
}
+ bezt++;
}
- bezt++;
}
- }
- else {
- BPoint *bp = nu->bp;
- int a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->hide == 0) {
- if (bp == vert) {
- UI_ThemeColor(TH_ACTIVE_VERT);
- glVertex3fv(bp->vec);
- UI_ThemeColor(color);
- }
- else {
- if ((bp->f1 & SELECT) == sel) glVertex3fv(bp->vec);
+ else {
+ const BPoint *bp = nu->bp;
+ int a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->hide == 0) {
+ if (bp == vert) {
+ immAttrib3ubv(color, vert_color_active);
+ }
+ else {
+ immAttrib3ubv(color, bp->f1 & SELECT ? vert_color_select : vert_color);
+ }
+ immVertex3fv(pos, bp->vec);
}
+ bp++;
}
- bp++;
}
}
-
- glEnd();
+
+ immEnd();
+ immUnbindProgram();
}
static void editnurb_draw_active_poly(Nurb *nu)
{
- UI_ThemeColor(TH_ACTIVE_SPLINE);
- glLineWidth(2);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_ACTIVE_SPLINE);
+
+ glLineWidth(2.0f);
BPoint *bp = nu->bp;
for (int b = 0; b < nu->pntsv; b++) {
- if (nu->flagu & 1) glBegin(GL_LINE_LOOP);
- else glBegin(GL_LINE_STRIP);
+ if (nu->pntsu >= 2) {
+ if (nu->flagu & 1) immBegin(GWN_PRIM_LINE_LOOP, nu->pntsu);
+ else immBegin(GWN_PRIM_LINE_STRIP, nu->pntsu);
- for (int a = 0; a < nu->pntsu; a++, bp++) {
- glVertex3fv(bp->vec);
- }
+ for (int a = 0; a < nu->pntsu; a++, bp++) {
+ immVertex3fv(pos, bp->vec);
+ }
- glEnd();
+ immEnd();
+ }
}
- glColor3ub(0, 0, 0);
+ immUnbindProgram();
}
static void editnurb_draw_active_nurbs(Nurb *nu)
{
- UI_ThemeColor(TH_ACTIVE_SPLINE);
- glLineWidth(2);
-
- glBegin(GL_LINES);
- BPoint *bp = nu->bp;
- for (int b = 0; b < nu->pntsv; b++) {
- BPoint *bp1 = bp;
- bp++;
+ if (nu->pntsv > 0) {
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_ACTIVE_SPLINE);
- for (int a = nu->pntsu - 1; a > 0; a--, bp++) {
- if (bp->hide == 0 && bp1->hide == 0) {
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
- }
- bp1 = bp;
- }
- }
+ glLineWidth(2.0f);
+ // just quick guesstimate of how many verts to draw
+ int count = (nu->pntsu - 1) * nu->pntsv * 2;
+ if (nu->pntsv > 1) count += (nu->pntsv - 1) * nu->pntsu * 2;
+ if (count < 2) return;
- if (nu->pntsv > 1) { /* surface */
+ immBeginAtMost(GWN_PRIM_LINES, count);
+ BPoint *bp = nu->bp;
+ for (int b = 0; b < nu->pntsv; b++) {
+ BPoint *bp1 = bp;
+ bp++;
- int ofs = nu->pntsu;
- for (int b = 0; b < nu->pntsu; b++) {
- BPoint *bp1 = nu->bp + b;
- bp = bp1 + ofs;
- for (int a = nu->pntsv - 1; a > 0; a--, bp += ofs) {
+ for (int a = nu->pntsu - 1; a > 0; a--, bp++) {
if (bp->hide == 0 && bp1->hide == 0) {
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
}
bp1 = bp;
}
}
- }
- glEnd();
+ if (nu->pntsv > 1) { /* surface */
+ int ofs = nu->pntsu;
+ for (int b = 0; b < nu->pntsu; b++) {
+ BPoint *bp1 = nu->bp + b;
+ bp = bp1 + ofs;
+ for (int a = nu->pntsv - 1; a > 0; a--, bp += ofs) {
+ if (bp->hide == 0 && bp1->hide == 0) {
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
+ }
+ bp1 = bp;
+ }
+ }
+ }
+
+ immEnd();
- glColor3ub(0, 0, 0);
+ immUnbindProgram();
+ }
}
static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
@@ -6242,6 +7203,9 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
BPoint *bp, *bp1;
int a, b;
Curve *cu = ob->data;
+ Gwn_VertFormat *format;
+ unsigned int pos, col;
+ unsigned char color[3];
int index = 0;
Nurb *nu = nurb;
@@ -6249,35 +7213,55 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
if (nu->hide == 0) {
switch (nu->type) {
case CU_POLY:
+ {
if (!sel && index == cu->actnu) {
/* we should draw active spline highlight below everything */
editnurb_draw_active_poly(nu);
}
- glLineWidth(1);
+ format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ glLineWidth(1.0f);
- UI_ThemeColor(TH_NURB_ULINE);
+ immUniformThemeColor(TH_NURB_ULINE);
bp = nu->bp;
for (b = 0; b < nu->pntsv; b++) {
- if (nu->flagu & 1) glBegin(GL_LINE_LOOP);
- else glBegin(GL_LINE_STRIP);
+ if (nu->pntsu >= 2) {
+ if (nu->flagu & 1) immBegin(GWN_PRIM_LINE_LOOP, nu->pntsu);
+ else immBegin(GWN_PRIM_LINE_STRIP, nu->pntsu);
- for (a = 0; a < nu->pntsu; a++, bp++) {
- glVertex3fv(bp->vec);
- }
+ for (a = 0; a < nu->pntsu; a++, bp++) {
+ immVertex3fv(pos, bp->vec);
+ }
- glEnd();
+ immEnd();
+ }
}
+ immUnbindProgram();
break;
+ }
case CU_NURBS:
+ {
if (!sel && index == cu->actnu) {
/* we should draw active spline highlight below everything */
editnurb_draw_active_nurbs(nu);
}
- glLineWidth(1);
+ format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
- glBegin(GL_LINES);
+ // just quick guesstimate of how many verts to draw
+ int count = (nu->pntsu - 1) * nu->pntsv * 2;
+ if (nu->pntsv > 1) count += (nu->pntsv - 1) * nu->pntsu * 2;
+ if (count < 2) return;
+
+ glLineWidth(1.0f);
+
+ immBeginAtMost(GWN_PRIM_LINES, count);
bp = nu->bp;
for (b = 0; b < nu->pntsv; b++) {
@@ -6287,10 +7271,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
if (bp->hide == 0 && bp1->hide == 0) {
if (sel) {
if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) {
- UI_ThemeColor(TH_NURB_SEL_ULINE);
-
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
+ UI_GetThemeColor3ubv(TH_NURB_SEL_ULINE, color);
+ immAttrib3ubv(col, color);
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
}
}
else {
@@ -6298,10 +7282,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
/* pass */
}
else {
- UI_ThemeColor(TH_NURB_ULINE);
-
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
+ UI_GetThemeColor3ubv(TH_NURB_ULINE, color);
+ immAttrib3ubv(col, color);
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
}
}
}
@@ -6318,10 +7302,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
if (bp->hide == 0 && bp1->hide == 0) {
if (sel) {
if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) {
- UI_ThemeColor(TH_NURB_SEL_VLINE);
-
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
+ UI_GetThemeColor3ubv(TH_NURB_SEL_VLINE, color);
+ immAttrib3ubv(col, color);
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
}
}
else {
@@ -6329,10 +7313,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
/* pass */
}
else {
- UI_ThemeColor(TH_NURB_VLINE);
-
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
+ UI_GetThemeColor3ubv(TH_NURB_VLINE, color);
+ immAttrib3ubv(col, color);
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
}
}
}
@@ -6340,9 +7324,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
}
}
}
-
- glEnd();
+ immEnd();
+ immUnbindProgram();
break;
+ }
}
}
@@ -6352,8 +7337,9 @@ 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,
- const char dt, const short dflag, const unsigned char ob_wire_col[4])
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb,
+ const char dt, const short dflag, const unsigned char UNUSED(ob_wire_col[4]))
{
ToolSettings *ts = scene->toolsettings;
Object *ob = base->object;
@@ -6365,9 +7351,8 @@ static void draw_editnurb(
/* DispList */
UI_GetThemeColor3ubv(TH_WIRE_EDIT, wire_col);
- glColor3ubv(wire_col);
- drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ drawDispList(eval_ctx, scene, view_layer, v3d, rv3d, base, dt, dflag, wire_col);
/* for shadows only show solid faces */
if (v3d->flag2 & V3D_RENDER_SHADOW)
@@ -6391,79 +7376,110 @@ static void draw_editnurb(
for (nu = nurb; nu; nu = nu->next) {
if (nu->type == CU_BEZIER && (cu->drawflag & CU_HIDE_HANDLES) == 0)
drawhandlesN(nu, 1, hide_handles);
- drawvertsN(nu, 0, hide_handles, NULL);
}
if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
- glColor3ubv(wire_col);
-
/* direction vectors for 3d curve paths
* when at its lowest, don't render normals */
if ((cu->flag & CU_3D) && (ts->normalsize > 0.0015f) && (cu->drawflag & CU_HIDE_NORMALS) == 0) {
BevList *bl;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_WIRE_EDIT);
+
glLineWidth(1.0f);
+
+ int count = 0;
+ int count_used = 0;
for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
- BevPoint *bevp = bl->bevpoints;
int nr = bl->nr;
int skip = nu->resolu / 16;
-
+
+#if 0
while (nr-- > 0) { /* accounts for empty bevel lists */
- const float fac = bevp->radius * ts->normalsize;
- float vec_a[3]; /* Offset perpendicular to the curve */
- float vec_b[3]; /* Delta along the curve */
+ count += 4;
+ nr -= skip;
+ }
+#else
+ /* Same as loop above */
+ count += 4 * max_ii((nr + max_ii(skip - 1, 0)) / (skip + 1), 0);
+#endif
+ }
- vec_a[0] = fac;
- vec_a[1] = 0.0f;
- vec_a[2] = 0.0f;
-
- mul_qt_v3(bevp->quat, vec_a);
- madd_v3_v3fl(vec_a, bevp->dir, -fac);
+ if (count > 2) {
+ immBegin(GWN_PRIM_LINES, count);
+ for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
+ BevPoint *bevp = bl->bevpoints;
+ int nr = bl->nr;
+ int skip = nu->resolu / 16;
- reflect_v3_v3v3(vec_b, vec_a, bevp->dir);
- negate_v3(vec_b);
+ while (nr-- > 0) { /* accounts for empty bevel lists */
+ const float fac = bevp->radius * ts->normalsize;
+ float vec_a[3]; /* Offset perpendicular to the curve */
+ float vec_b[3]; /* Delta along the curve */
- add_v3_v3(vec_a, bevp->vec);
- add_v3_v3(vec_b, bevp->vec);
+ vec_a[0] = fac;
+ vec_a[1] = 0.0f;
+ vec_a[2] = 0.0f;
+
+ mul_qt_v3(bevp->quat, vec_a);
+ madd_v3_v3fl(vec_a, bevp->dir, -fac);
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vec_a);
- glVertex3fv(bevp->vec);
- glVertex3fv(vec_b);
- glEnd();
-
- bevp += skip + 1;
- nr -= skip;
+ reflect_v3_v3v3(vec_b, vec_a, bevp->dir);
+ negate_v3(vec_b);
+
+ add_v3_v3(vec_a, bevp->vec);
+ add_v3_v3(vec_b, bevp->vec);
+
+ immVertex3fv(pos, vec_a);
+ immVertex3fv(pos, bevp->vec);
+ immVertex3fv(pos, bevp->vec);
+ immVertex3fv(pos, vec_b);
+
+ bevp += skip + 1;
+ nr -= skip;
+ count_used += 4;
+ }
}
+ BLI_assert(count == count_used);
+ UNUSED_VARS_NDEBUG(count_used);
+
+ immEnd();
}
+ immUnbindProgram();
}
- if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
-
- for (nu = nurb; nu; nu = nu->next) {
- drawvertsN(nu, 1, hide_handles, vert);
- }
-
- if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ drawvertsN(nurb, hide_handles, vert);
+
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
static void draw_editfont_textcurs(RegionView3D *rv3d, float textcurs[4][2])
{
- cpack(0);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
ED_view3d_polygon_offset(rv3d, -1.0);
set_inverted_drawing(1);
- glBegin(GL_QUADS);
- glVertex2fv(textcurs[0]);
- glVertex2fv(textcurs[1]);
- glVertex2fv(textcurs[2]);
- glVertex2fv(textcurs[3]);
- glEnd();
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ imm_cpack(0);
+ immBegin(GWN_PRIM_TRI_FAN, 4);
+ immVertex2fv(pos, textcurs[0]);
+ immVertex2fv(pos, textcurs[1]);
+ immVertex2fv(pos, textcurs[2]);
+ immVertex2fv(pos, textcurs[3]);
+ immEnd();
set_inverted_drawing(0);
ED_view3d_polygon_offset(rv3d, 0.0);
+ immUnbindProgram();
}
-static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
- const char dt, const short dflag, const unsigned char ob_wire_col[4])
+static void draw_editfont(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
Object *ob = base->object;
Curve *cu = ob->data;
@@ -6473,17 +7489,19 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b
draw_editfont_textcurs(rv3d, ef->textcurs);
if (cu->flag & CU_FAST) {
- cpack(0xFFFFFF);
+ imm_cpack(0xFFFFFF);
set_inverted_drawing(1);
- drawDispList(scene, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col);
+ drawDispList(eval_ctx, scene, view_layer, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col);
set_inverted_drawing(0);
}
else {
- drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ drawDispList(eval_ctx, scene, view_layer, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
if (cu->linewidth != 0.0f) {
- UI_ThemeColor(TH_WIRE_EDIT);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_WIRE_EDIT);
copy_v3_v3(vec1, ob->orig);
copy_v3_v3(vec2, ob->orig);
vec1[0] += cu->linewidth;
@@ -6491,31 +7509,35 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b
vec1[1] += cu->linedist * cu->fsize;
vec2[1] -= cu->lines * cu->linedist * cu->fsize;
setlinestyle(3);
- glBegin(GL_LINES);
- glVertex2fv(vec1);
- glVertex2fv(vec2);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(pos, vec1);
+ immVertex2fv(pos, vec2);
+ immEnd();
setlinestyle(0);
+ immUnbindProgram();
}
setlinestyle(3);
for (int i = 0; i < cu->totbox; i++) {
if (cu->tb[i].w != 0.0f) {
- UI_ThemeColor(i == (cu->actbox - 1) ? TH_ACTIVE : TH_WIRE);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(i == (cu->actbox - 1) ? TH_ACTIVE : TH_WIRE);
vec1[0] = cu->xof + cu->tb[i].x;
vec1[1] = cu->yof + cu->tb[i].y + cu->fsize;
vec1[2] = 0.001;
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vec1);
+ immBegin(GWN_PRIM_LINE_STRIP, 5);
+ immVertex3fv(pos, vec1);
vec1[0] += cu->tb[i].w;
- glVertex3fv(vec1);
+ immVertex3fv(pos, vec1);
vec1[1] -= cu->tb[i].h;
- glVertex3fv(vec1);
+ immVertex3fv(pos, vec1);
vec1[0] -= cu->tb[i].w;
- glVertex3fv(vec1);
+ immVertex3fv(pos, vec1);
vec1[1] += cu->tb[i].h;
- glVertex3fv(vec1);
- glEnd();
+ immVertex3fv(pos, vec1);
+ immEnd();
+ immUnbindProgram();
}
}
setlinestyle(0);
@@ -6524,7 +7546,9 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b
if (ef->selboxes && ef->selboxes_len) {
float selboxw;
- cpack(0xffffff);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ imm_cpack(0xffffff);
set_inverted_drawing(1);
for (int i = 0; i < ef->selboxes_len; i++) {
EditFontSelBox *sb = &ef->selboxes[i];
@@ -6543,20 +7567,20 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b
/* fill in xy below */
tvec[2] = 0.001;
- glBegin(GL_QUADS);
+ immBegin(GWN_PRIM_TRI_FAN, 4);
if (sb->rot == 0.0f) {
copy_v2_fl2(tvec, sb->x, sb->y);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, sb->x + selboxw, sb->y);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, sb->x + selboxw, sb->y + sb->h);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, sb->x, sb->y + sb->h);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
}
else {
float mat[2][2];
@@ -6564,84 +7588,87 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b
angle_to_mat2(mat, sb->rot);
copy_v2_fl2(tvec, sb->x, sb->y);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, selboxw, 0.0f);
mul_m2v2(mat, tvec);
add_v2_v2(tvec, &sb->x);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, selboxw, sb->h);
mul_m2v2(mat, tvec);
add_v2_v2(tvec, &sb->x);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, 0.0f, sb->h);
mul_m2v2(mat, tvec);
add_v2_v2(tvec, &sb->x);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
}
- glEnd();
+ immEnd();
}
set_inverted_drawing(0);
+ immUnbindProgram();
}
}
/* draw a sphere for use as an empty drawtype */
-static void draw_empty_sphere(float size)
-{
- static GLuint displist = 0;
-
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- glPushMatrix();
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
- gluDisk(qobj, 0.0, 1, 16, 1);
-
- glRotatef(90, 0, 1, 0);
- gluDisk(qobj, 0.0, 1, 16, 1);
-
- glRotatef(90, 1, 0, 0);
- gluDisk(qobj, 0.0, 1, 16, 1);
-
- gluDeleteQuadric(qobj);
-
- glPopMatrix();
- glEndList();
- }
-
- glScalef(size, size, size);
- glCallList(displist);
- glScalef(1.0f / size, 1.0f / size, 1.0f / size);
+static void draw_empty_sphere(float size, unsigned pos)
+{
+#define NSEGMENTS 16
+ /* a single ring of vertices */
+ float p[NSEGMENTS][2];
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
+ p[i][0] = size * cosf(angle);
+ p[i][1] = size * sinf(angle);
+ }
+
+ immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS);
+ for (int i = 0; i < NSEGMENTS; ++i)
+ immVertex3f(pos, p[i][0], p[i][1], 0.0f);
+ immEnd();
+ immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS);
+ for (int i = 0; i < NSEGMENTS; ++i)
+ immVertex3f(pos, p[i][0], 0.0f, p[i][1]);
+ immEnd();
+ immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS);
+ for (int i = 0; i < NSEGMENTS; ++i)
+ immVertex3f(pos, 0.0f, p[i][0], p[i][1]);
+ immEnd();
+#undef NSEGMENTS
}
/* draw a cone for use as an empty drawtype */
-static void draw_empty_cone(float size)
+static void draw_empty_cone(float size, unsigned pos)
{
- const float radius = size;
+#define NSEGMENTS 8
+ /* a single ring of vertices */
+ float p[NSEGMENTS][2];
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
+ p[i][0] = size * cosf(angle);
+ p[i][1] = size * sinf(angle);
+ }
- GLUquadricObj *qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
-
- glPushMatrix();
-
- glScalef(radius, size * 2.0f, radius);
- glRotatef(-90.0, 1.0, 0.0, 0.0);
- gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
+ /* cone sides */
+ immBegin(GWN_PRIM_LINES, NSEGMENTS * 2);
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ immVertex3f(pos, 0.0f, 2.0f * size, 0.0f);
+ immVertex3f(pos, p[i][0], 0.0f, p[i][1]);
+ }
+ immEnd();
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
+ /* end ring */
+ immBegin(GWN_PRIM_LINE_LOOP, NSEGMENTS);
+ for (int i = 0; i < NSEGMENTS; ++i)
+ immVertex3f(pos, p[i][0], 0.0f, p[i][1]);
+ immEnd();
+#undef NSEGMENTS
}
-static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start)
+static void drawspiral(unsigned int pos, const float cent[3], float rad, float tmat[4][4], int start)
{
float vec[3], vx[3], vy[3];
const float tot_inv = 1.0f / (float)CIRCLE_RESOL;
@@ -6657,11 +7684,11 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta
mul_v3_v3fl(vx, tmat[0], rad);
mul_v3_v3fl(vy, tmat[1], rad);
- glBegin(GL_LINE_STRIP);
+ immBegin(GWN_PRIM_LINE_STRIP, CIRCLE_RESOL + 1);
if (inverse == 0) {
copy_v3_v3(vec, cent);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
for (a = 0; a < CIRCLE_RESOL; a++) {
if (a + start >= CIRCLE_RESOL)
@@ -6675,7 +7702,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta
vec[1] = cent[1] + (x * vx[1] + y * vy[1]);
vec[2] = cent[2] + (x * vx[2] + y * vy[2]);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
}
}
else {
@@ -6687,7 +7714,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta
vec[1] = cent[1] + (x * vx[1] + y * vy[1]);
vec[2] = cent[2] + (x * vx[2] + y * vy[2]);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
for (a = 0; a < CIRCLE_RESOL; a++) {
if (a + start >= CIRCLE_RESOL)
@@ -6700,79 +7727,79 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta
vec[0] = cent[0] + (x * vx[0] + y * vy[0]);
vec[1] = cent[1] + (x * vx[1] + y * vy[1]);
vec[2] = cent[2] + (x * vx[2] + y * vy[2]);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
}
}
- glEnd();
+ immEnd();
}
/* draws a circle on x-z plane given the scaling of the circle, assuming that
* all required matrices have been set (used for drawing empties) */
-static void drawcircle_size(float size)
+static void drawcircle_size(float size, unsigned pos)
{
- glBegin(GL_LINE_LOOP);
+ immBegin(GWN_PRIM_LINE_LOOP, CIRCLE_RESOL);
/* coordinates are: cos(degrees * 11.25) = x, sin(degrees * 11.25) = y, 0.0f = z */
for (short degrees = 0; degrees < CIRCLE_RESOL; degrees++) {
float x = cosval[degrees];
float y = sinval[degrees];
-
- glVertex3f(x * size, 0.0f, y * size);
+
+ immVertex3f(pos, x * size, 0.0f, y * size);
}
-
- glEnd();
+ immEnd();
}
/* needs fixing if non-identity matrix used */
-static void drawtube(const float vec[3], float radius, float height, float tmat[4][4])
+static void imm_drawtube(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos)
{
float cur[3];
- drawcircball(GL_LINE_LOOP, vec, radius, tmat);
+ imm_drawcircball(vec, radius, tmat, pos);
copy_v3_v3(cur, vec);
cur[2] += height;
- drawcircball(GL_LINE_LOOP, cur, radius, tmat);
+ imm_drawcircball(cur, radius, tmat, pos);
- glBegin(GL_LINES);
- glVertex3f(vec[0] + radius, vec[1], vec[2]);
- glVertex3f(cur[0] + radius, cur[1], cur[2]);
- glVertex3f(vec[0] - radius, vec[1], vec[2]);
- glVertex3f(cur[0] - radius, cur[1], cur[2]);
- glVertex3f(vec[0], vec[1] + radius, vec[2]);
- glVertex3f(cur[0], cur[1] + radius, cur[2]);
- glVertex3f(vec[0], vec[1] - radius, vec[2]);
- glVertex3f(cur[0], cur[1] - radius, cur[2]);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 8);
+ immVertex3f(pos, vec[0] + radius, vec[1], vec[2]);
+ immVertex3f(pos, cur[0] + radius, cur[1], cur[2]);
+ immVertex3f(pos, vec[0] - radius, vec[1], vec[2]);
+ immVertex3f(pos, cur[0] - radius, cur[1], cur[2]);
+ immVertex3f(pos, vec[0], vec[1] + radius, vec[2]);
+ immVertex3f(pos, cur[0], cur[1] + radius, cur[2]);
+ immVertex3f(pos, vec[0], vec[1] - radius, vec[2]);
+ immVertex3f(pos, cur[0], cur[1] - radius, cur[2]);
+ immEnd();
}
/* needs fixing if non-identity matrix used */
-static void drawcone(const float vec[3], float radius, float height, float tmat[4][4])
+static void imm_drawcone(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos)
{
float cur[3];
copy_v3_v3(cur, vec);
cur[2] += height;
- drawcircball(GL_LINE_LOOP, cur, radius, tmat);
+ imm_drawcircball(cur, radius, tmat, pos);
- glBegin(GL_LINES);
- glVertex3f(vec[0], vec[1], vec[2]);
- glVertex3f(cur[0] + radius, cur[1], cur[2]);
- glVertex3f(vec[0], vec[1], vec[2]);
- glVertex3f(cur[0] - radius, cur[1], cur[2]);
- glVertex3f(vec[0], vec[1], vec[2]);
- glVertex3f(cur[0], cur[1] + radius, cur[2]);
- glVertex3f(vec[0], vec[1], vec[2]);
- glVertex3f(cur[0], cur[1] - radius, cur[2]);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 8);
+ immVertex3f(pos, vec[0], vec[1], vec[2]);
+ immVertex3f(pos, cur[0] + radius, cur[1], cur[2]);
+ immVertex3f(pos, vec[0], vec[1], vec[2]);
+ immVertex3f(pos, cur[0] - radius, cur[1], cur[2]);
+ immVertex3f(pos, vec[0], vec[1], vec[2]);
+ immVertex3f(pos, cur[0], cur[1] + radius, cur[2]);
+ immVertex3f(pos, vec[0], vec[1], vec[2]);
+ immVertex3f(pos, cur[0], cur[1] - radius, cur[2]);
+ immEnd();
}
/* return true if nothing was drawn */
-static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
- const char dt, const short dflag, const unsigned char ob_wire_col[4])
+static bool drawmball(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
Object *ob = base->object;
MetaElem *ml;
@@ -6785,15 +7812,13 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
if ((G.f & G_PICKSEL) == 0) {
unsigned char wire_col[4];
UI_GetThemeColor4ubv(TH_WIRE_EDIT, wire_col);
- glColor3ubv(wire_col);
-
- drawDispList(scene, v3d, rv3d, base, dt, dflag, wire_col);
+ drawDispList(eval_ctx, scene, view_layer, v3d, rv3d, base, dt, dflag, wire_col);
}
ml = mb->editelems->first;
}
else {
- if ((base->flag & OB_FROMDUPLI) == 0) {
- drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ if ((base->flag_legacy & OB_FROMDUPLI) == 0) {
+ drawDispList(eval_ctx, scene, view_layer, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
ml = mb->elems.first;
}
@@ -6810,20 +7835,25 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
normalize_v3(imat[0]);
normalize_v3(imat[1]);
+#if 0 /* no purpose? */
if (mb->editelems == NULL) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
glColor3ubv(ob_wire_col);
}
}
-
+#endif
+
glLineWidth(1.0f);
+ const unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
while (ml) {
/* draw radius */
if (mb->editelems) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) cpack(0xA0A0F0);
- else cpack(0x3030A0);
+ if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) imm_cpack(0xA0A0F0);
+ else imm_cpack(0x3030A0);
}
if (G.f & G_PICKSEL) {
@@ -6831,24 +7861,26 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
GPU_select_load_id(code++);
}
}
- drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat);
+ imm_drawcircball(&(ml->x), ml->rad, imat, pos);
/* draw stiffness */
if (mb->editelems) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) cpack(0xA0F0A0);
- else cpack(0x30A030);
+ if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) imm_cpack(0xA0F0A0);
+ else imm_cpack(0x30A030);
}
if (G.f & G_PICKSEL) {
ml->selcol2 = code;
GPU_select_load_id(code++);
}
- drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat);
+ imm_drawcircball(&(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat, pos);
}
ml = ml->next;
}
+
+ immUnbindProgram();
return false;
}
@@ -6858,6 +7890,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
PartDeflect *pd = ob->pd;
float imat[4][4], tmat[4][4];
float vec[3] = {0.0, 0.0, 0.0};
+ float draw_color[3] = {0.0f, 0.0f, 0.0f};
/* scale size of circle etc with the empty drawsize */
const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f;
@@ -6867,35 +7900,53 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */
normalize_v3(imat[1]);
#endif
+
+ const unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fv(draw_color);
if (pd->forcefield == PFIELD_WIND) {
float force_val = pd->f_strength;
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color);
+ immUniformColor3fv(draw_color);
}
unit_m4(tmat);
force_val *= 0.1f;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ imm_drawcircball(vec, size, tmat, pos);
vec[2] = 0.5f * force_val;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ imm_drawcircball(vec, size, tmat, pos);
vec[2] = 1.0f * force_val;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ imm_drawcircball(vec, size, tmat, pos);
vec[2] = 1.5f * force_val;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ imm_drawcircball(vec, size, tmat, pos);
vec[2] = 0.0f; /* reset vec for max dist circle */
-
}
else if (pd->forcefield == PFIELD_FORCE) {
float ffall_val = pd->f_power;
- if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
- drawcircball(GL_LINE_LOOP, vec, size, imat);
- if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(1.5f, ffall_val));
- drawcircball(GL_LINE_LOOP, vec, size * 1.5f, imat);
- if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(2.0f, ffall_val));
- drawcircball(GL_LINE_LOOP, vec, size * 2.0f, imat);
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color);
+ immUniformColor3fv(draw_color);
+ }
+
+ imm_drawcircball(vec, size, imat, pos);
+
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(1.5f, ffall_val), draw_color);
+ immUniformColor3fv(draw_color);
+ }
+
+ imm_drawcircball(vec, size * 1.5f, imat, pos);
+
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(2.0f, ffall_val), draw_color);
+ immUniformColor3fv(draw_color);
+ }
+
+ imm_drawcircball(vec, size * 2.0f, imat, pos);
}
else if (pd->forcefield == PFIELD_VORTEX) {
float force_val = pd->f_strength;
@@ -6903,16 +7954,17 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
unit_m4(tmat);
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f);
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f, draw_color);
+ immUniformColor3fv(draw_color);
}
if (force_val < 0) {
- drawspiral(vec, size, tmat, 1);
- drawspiral(vec, size, tmat, 16);
+ drawspiral(pos, vec, size, tmat, 1);
+ drawspiral(pos, vec, size, tmat, 16);
}
else {
- drawspiral(vec, size, tmat, -1);
- drawspiral(vec, size, tmat, -16);
+ drawspiral(pos, vec, size, tmat, -1);
+ drawspiral(pos, vec, size, tmat, -16);
}
}
else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) {
@@ -6922,18 +7974,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
float mindist = pd->f_strength;
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color);
+ immUniformColor3fv(draw_color);
}
/* path end */
setlinestyle(3);
where_on_path(ob, 1.0f, guidevec1, guidevec2, NULL, NULL, NULL);
- drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
+ imm_drawcircball(guidevec1, mindist, imat, pos);
/* path beginning */
setlinestyle(0);
where_on_path(ob, 0.0f, guidevec1, guidevec2, NULL, NULL, NULL);
- drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
+ imm_drawcircball(guidevec1, mindist, imat, pos);
copy_v3_v3(vec, guidevec1); /* max center */
}
@@ -6942,16 +7995,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
setlinestyle(3);
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color);
+ immUniformColor3fv(draw_color);
}
if (pd->falloff == PFIELD_FALL_SPHERE) {
/* as last, guide curve alters it */
- if (pd->flag & PFIELD_USEMAX)
- drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);
+ if ((pd->flag & PFIELD_USEMAX) != 0) {
+ imm_drawcircball(vec, pd->maxdist, imat, pos);
+ }
- if (pd->flag & PFIELD_USEMIN)
- drawcircball(GL_LINE_LOOP, vec, pd->mindist, imat);
+ if ((pd->flag & PFIELD_USEMIN) != 0) {
+ imm_drawcircball(vec, pd->mindist, imat, pos);
+ }
}
else if (pd->falloff == PFIELD_FALL_TUBE) {
float radius, distance;
@@ -6964,16 +8020,18 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
vec[2] = distance;
distance = (pd->flag & PFIELD_POSZ) ? -distance : -2.0f * distance;
- if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR))
- drawtube(vec, radius, distance, tmat);
+ if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
+ imm_drawtube(vec, radius, distance, tmat, pos);
+ }
radius = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f;
distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
vec[2] = distance;
distance = (pd->flag & PFIELD_POSZ) ? -distance : -2.0f * distance;
- if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR))
- drawtube(vec, radius, distance, tmat);
+ if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
+ imm_drawtube(vec, radius, distance, tmat, pos);
+ }
}
else if (pd->falloff == PFIELD_FALL_CONE) {
float radius, distance;
@@ -6984,46 +8042,54 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
- drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat);
+ imm_drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat, pos);
if ((pd->flag & PFIELD_POSZ) == 0)
- drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat);
+ imm_drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat, pos);
}
radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f);
distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
- drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat);
+ imm_drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat, pos);
if ((pd->flag & PFIELD_POSZ) == 0)
- drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat);
+ imm_drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat, pos);
}
}
setlinestyle(0);
+
+ immUnbindProgram();
}
-static void draw_box(const float vec[8][3], bool solid)
+static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos)
{
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, vec);
-
if (solid) {
- const GLubyte indices[24] = {0,1,2,3,7,6,5,4,4,5,1,0,3,2,6,7,3,7,4,0,1,5,6,2};
- glDrawRangeElements(GL_QUADS, 0, 7, 24, GL_UNSIGNED_BYTE, indices);
+ /* Adpated from "Optimizing Triangle Strips for Fast Rendering" by F. Evans, S. Skiena and A. Varshney
+ * (http://www.cs.umd.edu/gvil/papers/av_ts.pdf). */
+ static const GLubyte tris_strip_indices[14] = {0,1,3,2,6,1,5,0,4,3,7,6,4,5};
+ immBegin(GWN_PRIM_TRI_STRIP, 14);
+ for (int i = 0; i < 14; ++i) {
+ immVertex3fv(pos, vec[tris_strip_indices[i]]);
+ }
+ immEnd();
}
else {
- const GLubyte indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7};
- glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices);
+ static const GLubyte line_indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7};
+ immBegin(GWN_PRIM_LINES, 24);
+ for (int i = 0; i < 24; ++i) {
+ immVertex3fv(pos, vec[line_indices[i]]);
+ }
+ immEnd();
}
- glDisableClientState(GL_VERTEX_ARRAY);
}
-static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
+static void imm_draw_bb(BoundBox *bb, char type, bool around_origin, const unsigned char ob_wire_col[4])
{
float size[3], cent[3];
- GLUquadricObj *qobj = gluNewQuadric();
-
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+ Gwn_Batch *sphere = GPU_batch_preset_sphere_wire(0);
+ GWN_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) GWN_batch_uniform_4f(sphere, "color", ob_wire_col[0] / 255.0f, ob_wire_col[1] / 255.0f, ob_wire_col[2] / 255.0f, 1.0f);
BKE_boundbox_calc_size_aabb(bb, size);
@@ -7034,40 +8100,51 @@ static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
BKE_boundbox_calc_center_aabb(bb, cent);
}
- glPushMatrix();
+ gpuPushMatrix();
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
+
if (type == OB_BOUND_SPHERE) {
float scale = MAX3(size[0], size[1], size[2]);
- glTranslate3fv(cent);
- glScalef(scale, scale, scale);
- gluSphere(qobj, 1.0, 8, 5);
+ gpuTranslate3fv(cent);
+ gpuRotateAxis(90, 'X');
+ gpuScaleUniform(scale);
+ GWN_batch_draw(sphere);
}
else if (type == OB_BOUND_CYLINDER) {
float radius = size[0] > size[1] ? size[0] : size[1];
- glTranslatef(cent[0], cent[1], cent[2] - size[2]);
- glScalef(radius, radius, 2.0f * size[2]);
- gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1);
+ gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]);
+ gpuScale3f(radius, radius, 2.0f * size[2]);
+ imm_draw_cylinder_wire_3d(pos, 1.0f, 1.0f, 1.0f, 8, 1);
}
else if (type == OB_BOUND_CONE) {
float radius = size[0] > size[1] ? size[0] : size[1];
- glTranslatef(cent[0], cent[1], cent[2] - size[2]);
- glScalef(radius, radius, 2.0f * size[2]);
- gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
+ gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]);
+ gpuScale3f(radius, radius, 2.0f * size[2]);
+ imm_draw_cylinder_wire_3d(pos, 1.0f, 0.0f, 1.0f, 8, 1);
+
}
else if (type == OB_BOUND_CAPSULE) {
float radius = size[0] > size[1] ? size[0] : size[1];
float length = size[2] > radius ? 2.0f * (size[2] - radius) : 0.0f;
- glTranslatef(cent[0], cent[1], cent[2] - length * 0.5f);
- gluCylinder(qobj, radius, radius, length, 8, 1);
- gluSphere(qobj, radius, 8, 4);
- glTranslatef(0.0, 0.0, length);
- gluSphere(qobj, radius, 8, 4);
+ gpuTranslate3f(cent[0], cent[1], cent[2] - length * 0.5f);
+ imm_draw_cylinder_wire_3d(pos, radius, radius, length, 8, 1);
+
+ gpuRotateAxis(90, 'X');
+ gpuScaleUniform(radius);
+ GWN_batch_draw(sphere);
+
+ gpuTranslate3f(0.0f, length / radius, 0.0f);
+ GWN_batch_draw(sphere);
}
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
+
+ gpuPopMatrix();
+ immUnbindProgram();
}
-static void draw_bounding_volume(Object *ob, char type)
+void draw_bounding_volume(Object *ob, char type, const unsigned char ob_wire_col[4])
{
BoundBox bb_local;
BoundBox *bb = NULL;
@@ -7097,12 +8174,16 @@ static void draw_bounding_volume(Object *ob, char type)
if (bb == NULL)
return;
-
+
if (ob->gameflag & OB_BOUNDS) { /* bounds need to be drawn around origin for game engine */
if (type == OB_BOUND_BOX) {
float vec[8][3], size[3];
-
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
+
BKE_boundbox_calc_size_aabb(bb, size);
vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0];
@@ -7112,21 +8193,31 @@ static void draw_bounding_volume(Object *ob, char type)
vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2];
vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2];
- draw_box(vec, false);
+ imm_draw_box(vec, false, pos);
+
+ immUnbindProgram();
}
else {
- draw_bb_quadric(bb, type, true);
+ imm_draw_bb(bb, type, true, ob_wire_col);
}
}
else {
- if (type == OB_BOUND_BOX)
- draw_box(bb->vec, false);
+ if (type == OB_BOUND_BOX) {
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
+
+ imm_draw_box(bb->vec, false, pos);
+
+ immUnbindProgram();
+ }
else
- draw_bb_quadric(bb, type, false);
+ imm_draw_bb(bb, type, false, ob_wire_col);
}
+
}
-static void drawtexspace(Object *ob)
+static void drawtexspace(Object *ob, const unsigned char ob_wire_col[3])
{
float vec[8][3], loc[3], size[3];
@@ -7156,26 +8247,38 @@ static void drawtexspace(Object *ob)
setlinestyle(2);
- draw_box(vec, false);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ if (ob_wire_col) {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(ob_wire_col);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY);
+ }
+
+ imm_draw_box(vec, false, pos);
+
+ immUnbindProgram();
setlinestyle(0);
}
/* draws wire outline */
static void draw_object_selected_outline(
- Scene *scene, View3D *v3d, ARegion *ar, Base *base,
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d, ARegion *ar, Base *base,
const unsigned char ob_wire_col[4])
{
RegionView3D *rv3d = ar->regiondata;
Object *ob = base->object;
- glDepthMask(0);
+ glDepthMask(GL_FALSE);
if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
bool has_faces = false;
#ifdef SEQUENCER_DAG_WORKAROUND
- ensure_curve_cache(scene, ob);
+ ensure_curve_cache(eval_ctx, scene, ob);
#endif
DerivedMesh *dm = ob->derivedFinal;
@@ -7193,46 +8296,41 @@ static void draw_object_selected_outline(
if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->bb)) {
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
if (dm) {
- draw_mesh_object_outline(v3d, ob, dm);
+ draw_mesh_object_outline(v3d, ob, dm, ob_wire_col);
}
else {
/* only draw 'solid' parts of the display list as wire. */
- drawDispListwire_ex(&ob->curve_cache->disp, (DL_INDEX3 | DL_INDEX4 | DL_SURF));
+ drawDispListwire_ex(&ob->curve_cache->disp, (DL_INDEX3 | DL_INDEX4 | DL_SURF), ob_wire_col);
}
}
}
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);
+ drawDispListwire(&ob->curve_cache->disp, ob->type, ob_wire_col);
}
}
}
else if (ob->type == OB_ARMATURE) {
- if (!(ob->mode & OB_MODE_POSE && base == scene->basact)) {
+ if (!(ob->mode & OB_MODE_POSE && base == view_layer->basact)) {
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- draw_armature(scene, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true);
+ draw_armature(eval_ctx, scene, view_layer, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true);
}
}
- glDepthMask(1);
+ glDepthMask(GL_TRUE);
}
static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const unsigned char ob_wire_col[4])
{
if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL)) {
-
- if (scene->obedit == ob) {
- UI_ThemeColor(TH_WIRE_EDIT);
- }
- else {
- glColor3ubv(ob_wire_col);
- }
+ unsigned char wire_edit_col[4];
+ UI_GetThemeColor4ubv(TH_WIRE_EDIT, wire_edit_col);
ED_view3d_polygon_offset(rv3d, 1.0);
- glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
- glLineWidth(1);
+ glDepthMask(GL_FALSE); /* disable write in zbuffer, selected edge wires show better */
+ glLineWidth(1.0f);
if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
@@ -7241,23 +8339,23 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const
drawCurveDMWired(ob);
}
else {
- drawDispListwire(&ob->curve_cache->disp, ob->type);
+ drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col);
}
}
}
else if (ob->type == OB_MBALL) {
if (BKE_mball_is_basis(ob)) {
- drawDispListwire(&ob->curve_cache->disp, ob->type);
+ drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col);
}
}
- glDepthMask(1);
+ glDepthMask(GL_TRUE);
ED_view3d_polygon_offset(rv3d, 0.0);
}
}
/* should be called in view space */
-static void draw_hooks(Object *ob)
+static void draw_hooks(Object *ob, unsigned int pos)
{
for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Hook) {
@@ -7268,17 +8366,17 @@ static void draw_hooks(Object *ob)
if (hmd->object) {
setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(hmd->object->obmat[3]);
- glVertex3fv(vec);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(pos, hmd->object->obmat[3]);
+ immVertex3fv(pos, vec);
+ immEnd();
setlinestyle(0);
}
- glPointSize(3.0);
- glBegin(GL_POINTS);
- glVertex3fv(vec);
- glEnd();
+ glPointSize(3.0f);
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3fv(pos, vec);
+ immEnd();
}
}
}
@@ -7289,9 +8387,16 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data,
const char *axis_str[3] = {"px", "py", "pz"};
float mat[4][4];
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
+
eul_to_mat4(mat, &data->axX);
glLineWidth(4.0f);
setlinestyle(2);
+
+ immBegin(GWN_PRIM_LINES, 6);
for (int axis = 0; axis < 3; axis++) {
float dir[3] = {0, 0, 0};
float v[3];
@@ -7299,12 +8404,10 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data,
copy_v3_v3(v, &data->pivX);
dir[axis] = 1.0f;
- glBegin(GL_LINES);
mul_m4_v3(mat, dir);
add_v3_v3(v, dir);
- glVertex3fv(&data->pivX);
- glVertex3fv(v);
- glEnd();
+ immVertex3fv(pos, &data->pivX);
+ immVertex3fv(pos, v);
/* when const color is set wirecolor is NULL - we could get the current color but
* with selection and group instancing its not needed to draw the text */
@@ -7312,11 +8415,15 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data,
view3d_cached_text_draw_add(v, axis_str[axis], 2, 0, V3D_CACHE_TEXT_ASCII, ob_wire_col);
}
}
+ immEnd();
setlinestyle(0);
+ glLineWidth(1.0f);
+
+ immUnbindProgram();
}
-static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4])
+void draw_object_wire_color(Scene *scene, ViewLayer *view_layer, Base *base, unsigned char r_ob_wire_col[4])
{
Object *ob = base->object;
int colindex = 0;
@@ -7330,23 +8437,23 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_
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(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;
- if (scene->basact != base) {
+ if (view_layer->basact != base) {
theme_shade = -32;
}
}
@@ -7355,8 +8462,8 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_
}
}
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 = view_layer->basact == base ? TH_ACTIVE : TH_SELECT;
}
else {
if (ob->type == OB_LAMP) theme_id = TH_LAMP;
@@ -7410,10 +8517,11 @@ static void draw_object_matcap_check(View3D *v3d, Object *ob)
v3d->flag2 |= V3D_SHOW_SOLID_MATCAP;
}
-static void draw_rigidbody_shape(Object *ob)
+void draw_rigidbody_shape(Object *ob, const unsigned char ob_wire_col[4])
{
BoundBox *bb = NULL;
float size[3], vec[8][3];
+ unsigned int pos;
if (ob->type == OB_MESH) {
bb = BKE_mesh_boundbox_get(ob);
@@ -7426,6 +8534,10 @@ static void draw_rigidbody_shape(Object *ob)
case RB_SHAPE_BOX:
BKE_boundbox_calc_size_aabb(bb, size);
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
+
vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0];
vec[4][0] = vec[5][0] = vec[6][0] = vec[7][0] = +size[0];
vec[0][1] = vec[1][1] = vec[4][1] = vec[5][1] = -size[1];
@@ -7433,19 +8545,20 @@ static void draw_rigidbody_shape(Object *ob)
vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2];
vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2];
- draw_box(vec, false);
+ imm_draw_box(vec, false, pos);
+ immUnbindProgram();
break;
case RB_SHAPE_SPHERE:
- draw_bb_quadric(bb, OB_BOUND_SPHERE, true);
+ imm_draw_bb(bb, OB_BOUND_SPHERE, true, ob_wire_col);
break;
case RB_SHAPE_CONE:
- draw_bb_quadric(bb, OB_BOUND_CONE, true);
+ imm_draw_bb(bb, OB_BOUND_CONE, true, ob_wire_col);
break;
case RB_SHAPE_CYLINDER:
- draw_bb_quadric(bb, OB_BOUND_CYLINDER, true);
+ imm_draw_bb(bb, OB_BOUND_CYLINDER, true, ob_wire_col);
break;
case RB_SHAPE_CAPSULE:
- draw_bb_quadric(bb, OB_BOUND_CAPSULE, true);
+ imm_draw_bb(bb, OB_BOUND_CAPSULE, true, ob_wire_col);
break;
}
}
@@ -7454,17 +8567,18 @@ static 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(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d,
+ Base *base, const short dflag)
{
ModifierData *md = NULL;
Object *ob = base->object;
Curve *cu;
RegionView3D *rv3d = ar->regiondata;
- unsigned int col = 0;
unsigned char _ob_wire_col[4]; /* dont initialize this */
const unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */
bool zbufoff = false, is_paint = false, empty_object = false;
- const bool is_obact = (ob == OBACT);
+ const bool is_obact = (ob == OBACT(view_layer));
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);
@@ -7504,7 +8618,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)))
{
@@ -7528,7 +8642,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 */
@@ -7581,10 +8695,10 @@ 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, view_layer, base, _ob_wire_col);
ob_wire_col = _ob_wire_col;
- glColor3ubv(ob_wire_col);
+ //glColor3ubv(ob_wire_col);
}
/* maximum drawtype */
@@ -7636,15 +8750,22 @@ 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))) {
- draw_object_selected_outline(scene, v3d, ar, base, ob_wire_col);
+ if (!(ob->dtx & OB_DRAWWIRE) && (base->flag & BASE_SELECTED) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) {
+ draw_object_selected_outline(eval_ctx, scene, view_layer, v3d, ar, base, ob_wire_col);
}
}
}
+ /* TODO Viewport: draw only for selection */
+ if ((dflag & DRAW_PICKING) == 0) {
+ if ((dt == OB_BOUNDBOX) || ELEM(ob->type, OB_EMPTY, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ goto afterdraw;
+ }
+ }
+
switch (ob->type) {
case OB_MESH:
- empty_object = draw_mesh_object(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
+ empty_object = draw_mesh_object(eval_ctx, scene, view_layer, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
if ((dflag & DRAW_CONSTCOLOR) == 0) {
/* mesh draws wire itself */
dtx &= ~OB_DRAWWIRE;
@@ -7654,18 +8775,18 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
case OB_FONT:
cu = ob->data;
if (cu->editfont) {
- draw_editfont(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ draw_editfont(eval_ctx, scene, view_layer, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
else if (dt == OB_BOUNDBOX) {
if ((render_override && v3d->drawtype >= OB_WIRE) == 0) {
#ifdef SEQUENCER_DAG_WORKAROUND
- ensure_curve_cache(scene, base->object);
+ ensure_curve_cache(eval_ctx, scene, base->object);
#endif
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
}
else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
- empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ empty_object = drawDispList(eval_ctx, scene, view_layer, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
break;
@@ -7675,18 +8796,18 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (cu->editnurb) {
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- draw_editnurb(scene, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col);
+ draw_editnurb(eval_ctx, scene, view_layer, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col);
}
else if (dt == OB_BOUNDBOX) {
if ((render_override && (v3d->drawtype >= OB_WIRE)) == 0) {
#ifdef SEQUENCER_DAG_WORKAROUND
- ensure_curve_cache(scene, base->object);
+ ensure_curve_cache(eval_ctx, scene, base->object);
#endif
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
}
else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
- empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ empty_object = drawDispList(eval_ctx, scene, view_layer, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
break;
case OB_MBALL:
@@ -7694,17 +8815,17 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
MetaBall *mb = ob->data;
if (mb->editelems)
- drawmball(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ drawmball(eval_ctx, scene, view_layer, v3d, rv3d, base, dt, dflag, ob_wire_col);
else if (dt == OB_BOUNDBOX) {
if ((render_override && (v3d->drawtype >= OB_WIRE)) == 0) {
#ifdef SEQUENCER_DAG_WORKAROUND
- ensure_curve_cache(scene, base->object);
+ ensure_curve_cache(eval_ctx, scene, base->object);
#endif
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
}
else
- empty_object = drawmball(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ empty_object = drawmball(eval_ctx, scene, view_layer, v3d, rv3d, base, dt, dflag, ob_wire_col);
break;
}
case OB_EMPTY:
@@ -7713,7 +8834,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
draw_empty_image(ob, dflag, ob_wire_col, v3d->multiview_eye);
}
else {
- drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype);
+ drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, ob_wire_col);
}
}
break;
@@ -7731,7 +8852,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
break;
case OB_SPEAKER:
if (!render_override)
- drawspeaker(scene, v3d, rv3d, ob, dflag);
+ drawspeaker(ob_wire_col);
break;
case OB_LATTICE:
if (!render_override) {
@@ -7739,13 +8860,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if ((dt == OB_BOUNDBOX) && (ob->mode & OB_MODE_EDIT))
dt = OB_WIRE;
if (dt == OB_BOUNDBOX) {
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
else {
#ifdef SEQUENCER_DAG_WORKAROUND
- ensure_curve_cache(scene, ob);
+ ensure_curve_cache(eval_ctx, scene, ob);
#endif
- drawlattice(v3d, ob);
+ drawlattice(v3d, ob, dflag, ob_wire_col);
}
}
break;
@@ -7755,21 +8876,33 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if ((dt == OB_BOUNDBOX) && (ob->mode & (OB_MODE_EDIT | OB_MODE_POSE)))
dt = OB_WIRE;
if (dt == OB_BOUNDBOX) {
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
else {
+ unsigned char arm_col[4];
glLineWidth(1.0f);
- empty_object = draw_armature(scene, v3d, ar, base, dt, dflag, ob_wire_col, false);
+
+ if (ob_wire_col == NULL) {
+ float fcol[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ rgba_float_to_uchar(arm_col, fcol);
+ }
+ else
+ copy_v4_v4_uchar(arm_col, ob_wire_col);
+
+ empty_object = draw_armature(eval_ctx, scene, view_layer, v3d, ar, base, dt, dflag, arm_col, false);
}
}
break;
default:
if (!render_override) {
- drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS);
+ drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS, ob_wire_col);
}
break;
}
+ /* TODO Viewport: some elements are being drawn for object selection only */
+afterdraw:
+
if (!render_override) {
if (ob->soft /*&& dflag & OB_SBMOTION*/) {
float mrt[3][3], msc[3][3], mtr[3][3];
@@ -7778,12 +8911,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if ((sb = ob->soft)) {
if (sb->solverflags & SBSO_ESTIMATEIPO) {
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix(rv3d->viewmat);
copy_m3_m3(msc, sb->lscale);
copy_m3_m3(mrt, sb->lrot);
mul_m3_m3m3(mtr, mrt, msc);
ob_draw_RE_motion(sb->lcom, mtr, tipw, tiph, drawsize);
- glMultMatrixf(ob->obmat);
+ gpuMultMatrix(ob->obmat);
}
}
}
@@ -7800,35 +8933,28 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
{
ParticleSystem *psys;
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- /* for visibility, also while wpaint */
- if (col || (ob->flag & SELECT)) {
- cpack(0xFFFFFF);
- }
- }
//glDepthMask(GL_FALSE);
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix(rv3d->viewmat);
view3d_cached_text_draw_begin();
for (psys = ob->particlesystem.first; psys; psys = psys->next) {
/* run this so that possible child particles get cached */
if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) {
- PTCacheEdit *edit = PE_create_current(scene, ob);
+ PTCacheEdit *edit = PE_create_current(eval_ctx, scene, ob);
if (edit && edit->psys == psys)
- draw_update_ptcache_edit(scene, ob, edit);
+ draw_update_ptcache_edit(eval_ctx, scene, view_layer, ob, edit);
}
- draw_new_particle_system(scene, v3d, rv3d, base, psys, dt, dflag);
+ draw_new_particle_system(eval_ctx, scene, v3d, rv3d, base, psys, dt, dflag);
}
invert_m4_m4(ob->imat, ob->obmat);
view3d_cached_text_draw_end(v3d, ar, 0);
- glMultMatrixf(ob->obmat);
+ gpuMultMatrix(ob->obmat);
//glDepthMask(GL_TRUE);
- if (col) cpack(col);
}
/* draw edit particles last so that they can draw over child particles */
@@ -7837,12 +8963,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
{
if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) {
- PTCacheEdit *edit = PE_create_current(scene, ob);
+ PTCacheEdit *edit = PE_create_current(eval_ctx, scene, ob);
if (edit) {
- glLoadMatrixf(rv3d->viewmat);
- draw_update_ptcache_edit(scene, ob, edit);
+ gpuLoadMatrix(rv3d->viewmat);
+ draw_update_ptcache_edit(eval_ctx, scene, view_layer, ob, edit);
draw_ptcache_edit(scene, v3d, edit);
- glMultMatrixf(ob->obmat);
+ gpuMultMatrix(ob->obmat);
}
}
}
@@ -7850,21 +8976,25 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* draw code for smoke, only draw domains */
if (smd && smd->domain) {
SmokeDomainSettings *sds = smd->domain;
+ const bool show_smoke = (CFRA >= sds->point_cache[0]->startframe);
float viewnormal[3];
- glLoadMatrixf(rv3d->viewmat);
- glMultMatrixf(ob->obmat);
+ gpuLoadMatrix(rv3d->viewmat);
+ gpuMultMatrix(ob->obmat);
if (!render_override) {
BoundBox bb;
float p0[3], p1[3];
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
/* draw max domain bounds */
if ((sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN)) {
VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res);
VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res);
BKE_boundbox_init_from_minmax(&bb, p0, p1);
- draw_box(bb.vec, false);
+ imm_draw_box(bb.vec, false, pos);
}
/* draw a single voxel to hint the user about the resolution of the fluid */
@@ -7878,11 +9008,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
BKE_boundbox_init_from_minmax(&bb, p0, p1);
- draw_box(bb.vec, false);
+ imm_draw_box(bb.vec, false, pos);
+
+ immUnbindProgram();
}
/* don't show smoke before simulation starts, this could be made an option in the future */
- if (sds->fluid && CFRA >= sds->point_cache[0]->startframe) {
+ if (sds->fluid && show_smoke) {
float p0[3], p1[3];
/* get view vector */
@@ -7934,29 +9066,37 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if ((ob->gameflag & OB_BOUNDS) && (ob->mode == OB_MODE_OBJECT)) {
if (ob->boundtype != ob->collision_boundtype || (dtx & OB_DRAWBOUNDOX) == 0) {
setlinestyle(2);
- draw_bounding_volume(ob, ob->collision_boundtype);
+ draw_bounding_volume(ob, ob->collision_boundtype, ob_wire_col);
setlinestyle(0);
}
}
if (ob->rigidbody_object) {
- draw_rigidbody_shape(ob);
+ draw_rigidbody_shape(ob, ob_wire_col);
}
/* draw extra: after normal draw because of makeDispList */
if (dtx && (G.f & G_RENDER_OGL) == 0) {
if (dtx & OB_AXIS) {
- drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS);
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ /* prevent random colors being used */
+ drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, ob_wire_col);
+ }
+ else {
+ drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, NULL);
+ }
}
if (dtx & OB_DRAWBOUNDOX) {
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
if (dtx & OB_TEXSPACE) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
/* prevent random colors being used */
- glColor3ubv(ob_wire_col);
+ drawtexspace(ob, ob_wire_col);
+ }
+ else {
+ drawtexspace(ob, NULL);
}
- drawtexspace(ob);
}
if (dtx & OB_DRAWNAME) {
/* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */
@@ -7983,16 +9123,21 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
{
float imat[4][4], vec[3] = {0.0f, 0.0f, 0.0f};
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
invert_m4_m4(imat, rv3d->viewmatob);
if ((dflag & DRAW_CONSTCOLOR) == 0) {
/* prevent random colors being used */
- glColor3ubv(ob_wire_col);
+ immUniformColor3ubv(ob_wire_col);
}
setlinestyle(2);
- drawcircball(GL_LINE_LOOP, vec, ob->inertia, imat);
+ imm_drawcircball(vec, ob->inertia, imat, pos);
setlinestyle(0);
+
+ immUnbindProgram();
}
}
@@ -8002,13 +9147,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* return warning, clear temp flag */
v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP;
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix(rv3d->viewmat);
if (zbufoff) {
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;
}
@@ -8022,7 +9167,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
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;
@@ -8033,10 +9178,15 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if ((base->sx != IS_CLIPPED) &&
(U.obcenter_dia != 0.0))
{
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+ /* TODO: short term, use DEPTH_ONLY shader or set appropriate color */
+ /* TODO: long term, solve picking & selection problem better */
glPointSize(U.obcenter_dia);
- glBegin(GL_POINTS);
- glVertex3fv(ob->obmat[3]);
- glEnd();
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3fv(pos, ob->obmat[3]);
+ immEnd();
+ immUnbindProgram();
}
}
else if ((dflag & DRAW_CONSTCOLOR) == 0) {
@@ -8057,18 +9207,24 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
ListBase *list;
RigidBodyCon *rbc = ob->rigidbody_constraint;
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(ob_wire_col);
+
/* draw hook center and offset line */
if (ob != scene->obedit)
- draw_hooks(ob);
+ draw_hooks(ob, pos);
/* help lines and so */
- if (ob != scene->obedit && ob->parent && (ob->parent->lay & v3d->lay)) {
- setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(ob->obmat[3]);
- glVertex3fv(ob->orig);
- glEnd();
- setlinestyle(0);
+ if (ob != scene->obedit && ob->parent) {
+ if (BKE_object_is_visible(ob->parent)) {
+ setlinestyle(3);
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(pos, ob->obmat[3]);
+ immVertex3fv(pos, ob->orig);
+ immEnd();
+ setlinestyle(0);
+ }
}
/* Drawing the constraint lines */
@@ -8081,7 +9237,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
UI_GetThemeColor3ubv(TH_GRID, col1);
UI_make_axis_color(col1, col2, 'Z');
- glColor3ubv(col2);
+ immUniformColor3ubv(col2);
cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
@@ -8106,10 +9262,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (camob) {
setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(camob->obmat[3]);
- glVertex3fv(ob->obmat[3]);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(pos, camob->obmat[3]);
+ immVertex3fv(pos, ob->obmat[3]);
+ immEnd();
setlinestyle(0);
}
}
@@ -8125,15 +9281,15 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
for (ct = targets.first; ct; ct = ct->next) {
/* calculate target's matrix */
if (cti->get_target_matrix)
- cti->get_target_matrix(curcon, cob, ct, BKE_scene_frame_get(scene));
+ cti->get_target_matrix(eval_ctx, curcon, cob, ct, BKE_scene_frame_get(scene));
else
unit_m4(ct->matrix);
setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(ct->matrix[3]);
- glVertex3fv(ob->obmat[3]);
- glEnd();
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(pos, ct->matrix[3]);
+ immVertex3fv(pos, ob->obmat[3]);
+ immEnd();
setlinestyle(0);
}
@@ -8146,21 +9302,24 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
BKE_constraints_clear_evalob(cob);
}
/* draw rigid body constraint lines */
- if (rbc) {
- UI_ThemeColor(TH_WIRE);
+ if (rbc && (rbc->ob1 || rbc->ob2)) {
+ immUniformThemeColor(TH_WIRE);
+
setlinestyle(3);
- glBegin(GL_LINES);
+ immBegin(GWN_PRIM_LINES, ((int)((bool)rbc->ob1) + (int)((bool)rbc->ob2)) * 2);
if (rbc->ob1) {
- glVertex3fv(ob->obmat[3]);
- glVertex3fv(rbc->ob1->obmat[3]);
+ immVertex3fv(pos, ob->obmat[3]);
+ immVertex3fv(pos, rbc->ob1->obmat[3]);
}
if (rbc->ob2) {
- glVertex3fv(ob->obmat[3]);
- glVertex3fv(rbc->ob2->obmat[3]);
+ immVertex3fv(pos, ob->obmat[3]);
+ immVertex3fv(pos, rbc->ob2->obmat[3]);
}
- glEnd();
+ immEnd();
setlinestyle(0);
}
+
+ immUnbindProgram();
}
ED_view3d_clear_mats_rv3d(rv3d);
@@ -8171,10 +9330,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
* Drawing for selection picking,
* caller must have called 'GPU_select_load_id(base->selcode)' first.
*/
-void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag)
+void draw_object_select(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d,
+ Base *base, const short dflag)
{
BLI_assert(dflag & DRAW_PICKING && dflag & DRAW_CONSTCOLOR);
- draw_object(scene, ar, v3d, base, dflag);
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, base, dflag);
/* we draw duplicators for selection too */
if ((base->object->transflag & OB_DUPLI)) {
@@ -8182,13 +9343,11 @@ void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, cons
DupliObject *dob;
Base tbase;
- tbase.flag = OB_FROMDUPLI;
- lb = object_duplilist(G.main->eval_ctx, scene, base->object);
+ tbase.flag_legacy = OB_FROMDUPLI;
+ lb = object_duplilist(eval_ctx, scene, base->object);
for (dob = lb->first; dob; dob = dob->next) {
float omat[4][4];
- char dt;
- short dtx;
tbase.object = dob->ob;
copy_m4_m4(omat, dob->ob->obmat);
@@ -8196,10 +9355,10 @@ void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, cons
/* extra service: draw the duplicator in drawtype of parent */
/* MIN2 for the drawtype to allow bounding box objects in groups for lods */
- dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
- dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
+ char dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
+ short dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
- draw_object(scene, ar, v3d, &tbase, dflag);
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, &tbase, dflag);
tbase.object->dt = dt;
tbase.object->dtx = dtx;
@@ -8212,6 +9371,7 @@ void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, cons
/* ***************** BACKBUF SEL (BBS) ********* */
+#ifdef USE_MESH_DM_SELECT
static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, const float co[3],
const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
@@ -8219,8 +9379,10 @@ static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, const floa
MVert *mv = &data->mvert[index];
if (!(mv->flag & ME_HIDE)) {
- GPU_select_index_set(data->offset + index);
- glVertex3fv(co);
+ int selcol;
+ GPU_select_index_get(data->offset + index, &selcol);
+ immAttrib1u(data->col, selcol);
+ immVertex3fv(data->pos, co);
}
}
@@ -8231,12 +9393,36 @@ static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset)
MVert *mvert = me->mvert;
data.mvert = mvert;
data.offset = offset;
+
+ const int imm_len = dm->getNumVerts(dm);
+
+ if (imm_len == 0) return;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
+
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
+
+ immBeginAtMost(GWN_PRIM_POINTS, imm_len);
dm->foreachMappedVert(dm, bbs_obmode_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
+}
+#else
+static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *UNUSED(dm), int offset)
+{
+ Mesh *me = ob->data;
+ Gwn_Batch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GWN_batch_draw(batch);
}
+#endif
+#ifdef USE_MESH_DM_SELECT
static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3],
const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
@@ -8244,98 +9430,225 @@ static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3]
BMVert *eve = BM_vert_at_index(data->bm, index);
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- GPU_select_index_set(data->offset + index);
- glVertex3fv(co);
+ int selcol;
+ GPU_select_index_get(data->offset + index, &selcol);
+ immAttrib1u(data->col, selcol);
+ immVertex3fv(data->pos, co);
}
}
static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
{
- drawBMOffset_userData data = {em->bm, offset};
+ drawBMOffset_userData data;
+ data.bm = em->bm;
+ data.offset = offset;
+ Gwn_VertFormat *format = immVertexFormat();
+ data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
+
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
+
+ immBeginAtMost(GWN_PRIM_POINTS, em->bm->totvert);
dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
+#else
+static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset)
+{
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-static DMDrawOption bbs_mesh_wire__setDrawOptions(void *userData, int index)
+ Mesh *me = em->ob->data;
+ Gwn_Batch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GWN_batch_draw(batch);
+}
+#endif
+
+#ifdef USE_MESH_DM_SELECT
+static void bbs_mesh_wire__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3])
{
drawBMOffset_userData *data = userData;
BMEdge *eed = BM_edge_at_index(data->bm, index);
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- GPU_select_index_set(data->offset + index);
- return DM_DRAW_OPTION_NORMAL;
- }
- else {
- return DM_DRAW_OPTION_SKIP;
+ int selcol;
+ GPU_select_index_get(data->offset + index, &selcol);
+ immAttrib1u(data->col, selcol);
+ immVertex3fv(data->pos, v0co);
+ immVertex3fv(data->pos, v1co);
}
}
+
static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
{
- drawBMOffset_userData data = {em->bm, offset};
- glLineWidth(1);
- dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, &data);
+ drawBMOffset_userData data;
+ data.bm = em->bm;
+ data.offset = offset;
+
+ Gwn_VertFormat *format = immVertexFormat();
+
+ const int imm_len = dm->getNumEdges(dm) * 2;
+
+ if (imm_len == 0) return;
+
+ data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
+
+ glLineWidth(1.0f);
+
+ immBeginAtMost(GWN_PRIM_LINES, imm_len);
+ dm->foreachMappedEdge(dm, bbs_mesh_wire__mapFunc, &data);
+ immEnd();
+
+ immUnbindProgram();
}
+#else
+static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset)
+{
+ glLineWidth(1.0f);
-/**
- * dont set #GPU_framebuffer_index_set. just use to mask other
- */
-static DMDrawOption bbs_mesh_mask__setSolidDrawOptions(void *userData, int index)
+ Mesh *me = em->ob->data;
+ Gwn_Batch *batch = DRW_mesh_batch_cache_get_edges_with_select_id(me, offset);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GWN_batch_draw(batch);
+}
+#endif
+
+#ifdef USE_MESH_DM_SELECT
+static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *dm, const bool use_select)
{
- BMFace *efa = BM_face_at_index(userData, index);
-
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- return DM_DRAW_OPTION_NORMAL;
+ UNUSED_VARS(dm);
+
+ drawBMOffset_userData data;
+ data.bm = em->bm;
+
+ const int tri_len = em->tottri;
+ const int imm_len = tri_len * 3;
+ const char hflag_skip = use_select ? BM_ELEM_HIDDEN : (BM_ELEM_HIDDEN | BM_ELEM_SELECT);
+
+ if (imm_len == 0) return;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
+
+ immBeginAtMost(GWN_PRIM_TRIS, imm_len);
+
+ if (use_select == false) {
+ int selcol;
+ GPU_select_index_get(0, &selcol);
+ immAttrib1u(data.col, selcol);
}
- else {
- return DM_DRAW_OPTION_SKIP;
+
+ int index = 0;
+ while (index < tri_len) {
+ const BMFace *f = em->looptris[index][0]->f;
+ const int ntris = f->len - 2;
+ if (!BM_elem_flag_test(f, hflag_skip)) {
+ if (use_select) {
+ int selcol;
+ GPU_select_index_get(BM_elem_index_get(f) + 1, &selcol);
+ immAttrib1u(data.col, selcol);
+ }
+ for (int t = 0; t < ntris; t++) {
+ immVertex3fv(data.pos, em->looptris[index][0]->v->co);
+ immVertex3fv(data.pos, em->looptris[index][1]->v->co);
+ immVertex3fv(data.pos, em->looptris[index][2]->v->co);
+ index++;
+ }
+ }
+ else {
+ index += ntris;
+ }
}
-}
+ immEnd();
-static DMDrawOption bbs_mesh_solid__setSolidDrawOptions(void *userData, int index)
+ immUnbindProgram();
+}
+#else
+static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *UNUSED(dm), const bool use_select)
{
- BMFace *efa = BM_face_at_index(userData, index);
+ Mesh *me = em->ob->data;
+ Gwn_Batch *batch;
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- GPU_select_index_set(index + 1);
- return DM_DRAW_OPTION_NORMAL;
+ if (use_select) {
+ batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GWN_batch_draw(batch);
}
else {
- return DM_DRAW_OPTION_SKIP;
+ int selcol;
+ GPU_select_index_get(0, &selcol);
+ batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32);
+ GWN_batch_uniform_1i(batch, "color", selcol);
+ GWN_batch_draw(batch);
}
}
+#endif
+#ifdef USE_MESH_DM_SELECT
static void bbs_mesh_solid__drawCenter(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
{
+ drawBMOffset_userData *data = (drawBMOffset_userData *)userData;
BMFace *efa = BM_face_at_index(userData, index);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- GPU_select_index_set(index + 1);
-
- glVertex3fv(cent);
+ int selcol;
+ GPU_select_index_get(index + 1, &selcol);
+ immAttrib1u(data->col, selcol);
+ immVertex3fv(data->pos, cent);
}
}
+static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *dm)
+{
+ drawBMOffset_userData data; /* don't use offset */
+ data.bm = em->bm;
+ Gwn_VertFormat *format = immVertexFormat();
+ data.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ data.col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U32, 1, GWN_FETCH_INT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
+
+ glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
+
+ immBeginAtMost(GWN_PRIM_POINTS, em->bm->totface);
+ dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, &data, DM_FOREACH_NOP);
+ immEnd();
+
+ immUnbindProgram();
+}
+#else
+static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *UNUSED(dm))
+{
+ Mesh *me = em->ob->data;
+ Gwn_Batch *batch = DRW_mesh_batch_cache_get_facedots_with_select_id(me, 1);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GWN_batch_draw(batch);
+}
+#endif
+
/* two options, facecolors or black */
static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d,
Object *ob, DerivedMesh *dm, bool use_faceselect)
{
- cpack(0);
-
if (use_faceselect) {
- dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, NULL, NULL, em->bm, DM_DRAW_SKIP_HIDDEN | DM_DRAW_SELECT_USE_EDITMODE);
+ bbs_mesh_face(em, dm, true);
if (check_ob_drawface_dot(scene, v3d, ob->dt)) {
- glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
-
- glBegin(GL_POINTS);
- dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, em->bm, DM_FOREACH_NOP);
- glEnd();
+ bbs_mesh_face_dot(em, dm);
}
-
}
else {
- dm->drawMappedFaces(dm, bbs_mesh_mask__setSolidDrawOptions, NULL, NULL, em->bm, DM_DRAW_SKIP_SELECT | DM_DRAW_SKIP_HIDDEN | DM_DRAW_SELECT_USE_EDITMODE);
+ bbs_mesh_face(em, dm, false);
}
}
@@ -8350,7 +9663,6 @@ static DMDrawOption bbs_mesh_solid_hide__setDrawOpts(void *userData, int index)
Mesh *me = userData;
if (!(me->mpoly[index].flag & ME_HIDE)) {
- GPU_select_index_set(index + 1);
return DM_DRAW_OPTION_NORMAL;
}
else {
@@ -8358,6 +9670,7 @@ static DMDrawOption bbs_mesh_solid_hide__setDrawOpts(void *userData, int index)
}
}
+#ifdef USE_MESH_DM_SELECT
/* must have called GPU_framebuffer_index_set beforehand */
static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index)
{
@@ -8371,11 +9684,10 @@ static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index)
}
}
-static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
+static void bbs_mesh_solid_verts(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
Mesh *me = ob->data;
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
- glColor3ub(0, 0, 0);
+ DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, scene->customdata_mask);
DM_update_materials(dm, ob);
@@ -8391,29 +9703,53 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
bm_vertoffs = me->totvert + 1;
dm->release(dm);
}
-
-static void bbs_mesh_solid_faces(Scene *scene, Object *ob)
+#else
+static void bbs_mesh_solid_verts(const EvaluationContext *UNUSED(eval_ctx), Scene *UNUSED(scene), Object *ob)
{
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
Mesh *me = ob->data;
-
- glColor3ub(0, 0, 0);
- DM_update_materials(dm, ob);
+ /* Only draw faces to mask out verts, we don't want their selection ID's. */
+ const int G_f_orig = G.f;
+ G.f &= ~G_BACKBUFSEL;
- if ((me->editflag & ME_EDIT_PAINT_FACE_SEL))
- dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, NULL, NULL, me, DM_DRAW_SKIP_HIDDEN);
- else
- dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, NULL, NULL, me, 0);
+ {
+ int selcol;
+ Gwn_Batch *batch;
+ GPU_select_index_get(0, &selcol);
+ batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32);
+ GWN_batch_uniform_1i(batch, "color", selcol);
+ GWN_batch_draw(batch);
+ }
- dm->release(dm);
+ G.f |= (G_f_orig & G_BACKBUFSEL);
+
+ bbs_obmode_mesh_verts(ob, NULL, 1);
+ bm_vertoffs = me->totvert + 1;
}
+#endif
-void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
+static void bbs_mesh_solid_faces(Scene *scene, Object *ob)
+{
+ Mesh *me = ob->data;
+ UNUSED_VARS(scene, bbs_mesh_solid_hide__setDrawOpts, bbs_mesh_solid__setDrawOpts);
+ Gwn_Batch *batch;
+ if ((me->editflag & ME_EDIT_PAINT_FACE_SEL)) {
+ batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1);
+ }
+ else {
+ batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, false, 1);
+ }
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
+ GWN_batch_draw(batch);
+}
+
+void draw_object_backbufsel(
+ const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
{
ToolSettings *ts = scene->toolsettings;
- glMultMatrixf(ob->obmat);
+ gpuMultMatrix(ob->obmat);
glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
@@ -8424,7 +9760,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
Mesh *me = ob->data;
BMEditMesh *em = me->edit_btmesh;
- DerivedMesh *dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
+ DerivedMesh *dm = editbmesh_get_derived_cage(eval_ctx, scene, ob, em, CD_MASK_BAREMESH);
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
@@ -8463,7 +9799,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
/* currently vertex select supports weight paint and vertex paint*/
((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT)))
{
- bbs_mesh_solid_verts(scene, ob);
+ bbs_mesh_solid_verts(eval_ctx, scene, ob);
}
else {
bbs_mesh_solid_faces(scene, ob);
@@ -8475,7 +9811,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
break;
}
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix(rv3d->viewmat);
}
@@ -8483,8 +9819,9 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
/* assumes all matrices/etc set OK */
/* helper function for drawing object instances - meshes */
-static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d,
- Object *ob, const short dt, int outline)
+static void draw_object_mesh_instance(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d,
+ Object *ob, const short dt, int outline, const unsigned char ob_wire_col[4])
{
Mesh *me = ob->data;
DerivedMesh *dm = NULL, *edm = NULL;
@@ -8494,11 +9831,12 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
DM_update_materials(edm, ob);
}
else {
- dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH);
DM_update_materials(dm, ob);
}
if (dt <= OB_WIRE) {
+ glColor4ubv(ob_wire_col);
if (dm)
dm->drawEdges(dm, 1, 0);
else if (edm)
@@ -8506,11 +9844,11 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
}
else {
if (outline)
- draw_mesh_object_outline(v3d, ob, dm ? dm : edm);
+ draw_mesh_object_outline(v3d, ob, dm ? dm : edm, ob_wire_col);
if (dm) {
- bool glsl = draw_glsl_material(scene, ob, v3d, dt);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
+ bool glsl = draw_glsl_material(scene, view_layer, ob, v3d, dt);
+ GPU_begin_object_materials(v3d, rv3d, scene, view_layer, ob, glsl, NULL);
}
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
@@ -8529,23 +9867,153 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
if (dm) dm->release(dm);
}
-void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline)
+void draw_object_instance(const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline, const float wire_col[4])
{
if (ob == NULL)
return;
+ unsigned char bcol[4];
+ rgba_float_to_uchar(bcol, wire_col);
+
switch (ob->type) {
case OB_MESH:
- draw_object_mesh_instance(scene, v3d, rv3d, ob, dt, outline);
+ draw_object_mesh_instance(eval_ctx, scene, view_layer, v3d, rv3d, ob, dt, outline, bcol);
break;
case OB_EMPTY:
if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
- /* CONSTCOLOR == no wire outline */
- draw_empty_image(ob, DRAW_CONSTCOLOR, NULL, v3d->multiview_eye);
+ draw_empty_image(ob, 0, bcol, v3d->multiview_eye);
}
else {
- drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype);
+ drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, bcol);
}
break;
}
}
+
+void ED_draw_object_facemap(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, const float col[4], const int facemap)
+{
+ DerivedMesh *dm = NULL;
+
+ /* happens on undo */
+ if (ob->type != OB_MESH || !ob->data)
+ return;
+
+ /* Temporary, happens on undo, would resolve but will eventually move away from DM. */
+ if (ob->derivedFinal == NULL) {
+ return;
+ }
+
+ dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH);
+ if (!dm || !CustomData_has_layer(&dm->polyData, CD_FACEMAP))
+ return;
+
+
+ glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
+
+#if 0
+ DM_update_materials(dm, ob);
+
+ /* add polygon offset so we draw above the original surface */
+ glPolygonOffset(1.0, 1.0);
+
+ GPU_facemap_setup(dm);
+
+ glColor4fv(col);
+
+ gpuPushAttrib(GL_ENABLE_BIT);
+ glEnable(GL_BLEND);
+ glDisable(GL_LIGHTING);
+
+ /* always draw using backface culling */
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+
+ if (dm->drawObject->facemapindices) {
+ glDrawElements(GL_TRIANGLES, dm->drawObject->facemap_count[facemap] * 3, GL_UNSIGNED_INT,
+ (int *)NULL + dm->drawObject->facemap_start[facemap] * 3);
+ }
+ gpuPopAttrib();
+
+ GPU_buffers_unbind();
+
+ glPolygonOffset(0.0, 0.0);
+
+#else
+
+ /* Just to create the data to pass to immediate mode, grr! */
+ Mesh *me = ob->data;
+ const int *facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+ if (facemap_data) {
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(col);
+
+ /* XXX, alpha isn't working yet, not sure why. */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ MVert *mvert;
+
+ MPoly *mpoly;
+ int mpoly_len;
+
+ MLoop *mloop;
+ int mloop_len;
+
+ if (dm && CustomData_has_layer(&dm->polyData, CD_FACEMAP)) {
+ mvert = dm->getVertArray(dm);
+ mpoly = dm->getPolyArray(dm);
+ mloop = dm->getLoopArray(dm);
+
+ mpoly_len = dm->getNumPolys(dm);
+ mloop_len = dm->getNumLoops(dm);
+
+ facemap_data = CustomData_get_layer(&dm->polyData, CD_FACEMAP);
+ }
+ else {
+ mvert = me->mvert;
+ mpoly = me->mpoly;
+ mloop = me->mloop;
+
+ mpoly_len = me->totpoly;
+ mloop_len = me->totloop;
+
+ facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+ }
+
+ /* use gawain immediate mode fore now */
+ const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len);
+ immBeginAtMost(GWN_PRIM_TRIS, looptris_len * 3);
+
+ MPoly *mp;
+ int i;
+ for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) {
+ if (facemap_data[i] == facemap) {
+ /* Weak, fan-fill, use until we have derived-mesh replaced. */
+ const MLoop *ml_start = &mloop[mp->loopstart];
+ const MLoop *ml_a = ml_start + 1;
+ const MLoop *ml_b = ml_start + 2;
+ for (int j = 2; j < mp->totloop; j++) {
+ immVertex3fv(pos, mvert[ml_start->v].co);
+ immVertex3fv(pos, mvert[ml_a->v].co);
+ immVertex3fv(pos, mvert[ml_b->v].co);
+
+ ml_a++;
+ ml_b++;
+ }
+ }
+ }
+ immEnd();
+
+ immUnbindProgram();
+
+ glDisable(GL_BLEND);
+ }
+#endif
+
+ dm->release(dm);
+}
+
diff --git a/source/blender/editors/space_view3d/drawsimdebug.c b/source/blender/editors/space_view3d/drawsimdebug.c
index 3f23d4aa09a..14708ca67bc 100644
--- a/source/blender/editors/space_view3d/drawsimdebug.c
+++ b/source/blender/editors/space_view3d/drawsimdebug.c
@@ -40,102 +40,137 @@
#include "BKE_effect.h"
-#include "view3d_intern.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
-#include "BIF_gl.h"
+#include "view3d_intern.h"
static void draw_sim_debug_elements(SimDebugData *debug_data, float imat[4][4])
{
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ /* count element types */
GHashIterator iter;
+ int num_dots = 0;
+ int num_circles = 0;
+ int num_lines = 0;
+ int num_vectors = 0;
+ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
+ SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
+ switch (elem->type) {
+ case SIM_DEBUG_ELEM_DOT: ++num_dots; break;
+ case SIM_DEBUG_ELEM_CIRCLE: ++num_circles; break;
+ case SIM_DEBUG_ELEM_LINE: ++num_lines; break;
+ case SIM_DEBUG_ELEM_VECTOR: ++num_vectors; break;
+ }
+ }
/**** dots ****/
glPointSize(3.0f);
- glBegin(GL_POINTS);
+ immBegin(GWN_PRIM_POINTS, num_dots);
for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
if (elem->type != SIM_DEBUG_ELEM_DOT)
continue;
- glColor3f(elem->color[0], elem->color[1], elem->color[2]);
- glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
+ immAttrib3fv(color, elem->color);
+ immVertex3fv(pos, elem->v1);
}
- glEnd();
+ immEnd();
/**** circles ****/
{
- float circle[16][2] = {
+#define CIRCLERES 16
+ float circle[CIRCLERES][2] = {
{0.000000, 1.000000}, {0.382683, 0.923880}, {0.707107, 0.707107}, {0.923880, 0.382683},
{1.000000, -0.000000}, {0.923880, -0.382683}, {0.707107, -0.707107}, {0.382683, -0.923880},
{-0.000000, -1.000000}, {-0.382683, -0.923880}, {-0.707107, -0.707107}, {-0.923879, -0.382684},
{-1.000000, 0.000000}, {-0.923879, 0.382684}, {-0.707107, 0.707107}, {-0.382683, 0.923880} };
+
+ immBegin(GWN_PRIM_LINES, num_circles * CIRCLERES * 2);
+
for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
float radius = elem->v2[0];
- float co[3];
+ float co[3], nco[3];
int i;
if (elem->type != SIM_DEBUG_ELEM_CIRCLE)
continue;
- glColor3f(elem->color[0], elem->color[1], elem->color[2]);
- glBegin(GL_LINE_LOOP);
- for (i = 0; i < 16; ++i) {
- co[0] = radius * circle[i][0];
- co[1] = radius * circle[i][1];
- co[2] = 0.0f;
- mul_mat3_m4_v3(imat, co);
- add_v3_v3(co, elem->v1);
+ immAttrib3fv(color, elem->color);
+ zero_v3(co);
+ for (i = 0; i <= CIRCLERES; ++i) {
+ int ni = i % CIRCLERES;
+ nco[0] = radius * circle[ni][0];
+ nco[1] = radius * circle[ni][1];
+ nco[2] = 0.0f;
+ mul_mat3_m4_v3(imat, nco);
+ add_v3_v3(nco, elem->v1);
- glVertex3f(co[0], co[1], co[2]);
+ if (i > 0) {
+ immVertex3fv(pos, co);
+ immVertex3fv(pos, nco);
+ }
+
+ copy_v3_v3(co, nco);
}
- glEnd();
}
+
+ immEnd();
+#undef CIRCLERES
}
/**** lines ****/
- glBegin(GL_LINES);
+ immBegin(GWN_PRIM_LINES, num_lines * 2);
for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
if (elem->type != SIM_DEBUG_ELEM_LINE)
continue;
- glColor3f(elem->color[0], elem->color[1], elem->color[2]);
- glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
- glVertex3f(elem->v2[0], elem->v2[1], elem->v2[2]);
+ immAttrib3fv(color, elem->color);
+ immVertex3fv(pos, elem->v1);
+ immVertex3fv(pos, elem->v2);
}
- glEnd();
+ immEnd();
/**** vectors ****/
glPointSize(2.0f);
- glBegin(GL_POINTS);
+ immBegin(GWN_PRIM_POINTS, num_vectors);
for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
if (elem->type != SIM_DEBUG_ELEM_VECTOR)
continue;
- glColor3f(elem->color[0], elem->color[1], elem->color[2]);
- glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
+ immAttrib3fv(color, elem->color);
+ immVertex3fv(pos, elem->v1);
}
- glEnd();
+ immEnd();
- glBegin(GL_LINES);
+ immBegin(GWN_PRIM_LINES, num_vectors * 2);
for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
SimDebugElement *elem = BLI_ghashIterator_getValue(&iter);
float t[3];
if (elem->type != SIM_DEBUG_ELEM_VECTOR)
continue;
- glColor3f(elem->color[0], elem->color[1], elem->color[2]);
- glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]);
+ immAttrib3fv(color, elem->color);
+ immVertex3fv(pos, elem->v1);
add_v3_v3v3(t, elem->v1, elem->v2);
- glVertex3f(t[0], t[1], t[2]);
+ immVertex3fv(pos, t);
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
/**** strings ****/
@@ -163,18 +198,12 @@ void draw_sim_debug_data(Scene *UNUSED(scene), View3D *v3d, ARegion *ar)
invert_m4_m4(imat, rv3d->viewmatob);
-// glDepthMask(GL_FALSE);
-// glEnable(GL_BLEND);
-
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
+ gpuPushMatrix();
+ gpuLoadMatrix(rv3d->viewmat);
view3d_cached_text_draw_begin();
draw_sim_debug_elements(_sim_debug_data, imat);
view3d_cached_text_draw_end(v3d, ar, false);
- glPopMatrix();
-
-// glDepthMask(GL_TRUE);
-// glDisable(GL_BLEND);
+ gpuPopMatrix();
}
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index cf118404183..d39f3937a9d 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -48,7 +48,6 @@
#include "BIF_gl.h"
-#include "GPU_debug.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -160,7 +159,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 996506a9cf7..728547e7a40 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -43,25 +43,31 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "BKE_curve.h"
#include "BKE_icons.h"
+#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_mball.h"
+#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_transform.h"
#include "GPU_compositing.h"
#include "GPU_framebuffer.h"
#include "GPU_material.h"
-
-#include "BIF_gl.h"
+#include "GPU_viewport.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -250,7 +256,7 @@ void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d)
/* we have to multiply instead of loading viewmatob to make
* it work with duplis using displists, otherwise it will
* override the dupli-matrix */
- glMultMatrixf(ob->obmat);
+ gpuMultMatrix(ob->obmat);
}
#ifdef DEBUG
@@ -304,7 +310,7 @@ void ED_view3d_shade_update(Main *bmain, Scene *scene, View3D *v3d, ScrArea *sa)
}
else if (scene->obedit != NULL && scene->obedit->type == OB_MESH) {
/* Tag mesh to load edit data. */
- DAG_id_tag_update(scene->obedit->data, 0);
+ DEG_id_tag_update(scene->obedit->data, 0);
}
}
@@ -340,9 +346,10 @@ static SpaceLink *view3d_new(const bContext *C)
v3d->near = 0.01f;
v3d->far = 1000.0f;
- v3d->twflag |= U.tw_flag & V3D_USE_MANIPULATOR;
+ v3d->twflag |= U.manipulator_flag & V3D_MANIPULATOR_DRAW;
v3d->twtype = V3D_MANIP_TRANSLATE;
v3d->around = V3D_AROUND_CENTER_MEAN;
+ v3d->custom_orientation_index = -1;
v3d->bundle_size = 0.2f;
v3d->bundle_drawtype = OB_PLAINAXES;
@@ -404,17 +411,6 @@ static SpaceLink *view3d_new(const bContext *C)
static void view3d_free(SpaceLink *sl)
{
View3D *vd = (View3D *) sl;
- BGpic *bgpic;
-
- for (bgpic = vd->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- if (bgpic->source == V3D_BGPIC_IMAGE) {
- id_us_min((ID *)bgpic->ima);
- }
- else if (bgpic->source == V3D_BGPIC_MOVIE) {
- id_us_min((ID *)bgpic->clip);
- }
- }
- BLI_freelistN(&vd->bgpicbase);
if (vd->localvd) MEM_freeN(vd->localvd);
@@ -445,7 +441,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
{
View3D *v3do = (View3D *)sl;
View3D *v3dn = MEM_dupallocN(sl);
- BGpic *bgpic;
/* clear or remove stuff from old */
@@ -462,16 +457,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
v3dn->defmaterial = NULL;
- BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase);
- for (bgpic = v3dn->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- if (bgpic->source == V3D_BGPIC_IMAGE) {
- id_us_plus((ID *)bgpic->ima);
- }
- else if (bgpic->source == V3D_BGPIC_MOVIE) {
- id_us_plus((ID *)bgpic->clip);
- }
- }
-
v3dn->properties_storage = NULL;
if (v3dn->fx_settings.dof)
v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof);
@@ -487,6 +472,13 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
ListBase *lb;
wmKeyMap *keymap;
+ if (ar->manipulator_map == NULL) {
+ ar->manipulator_map = WM_manipulatormap_new_from_type(
+ &(const struct wmManipulatorMapType_Params) {SPACE_VIEW3D, RGN_TYPE_WINDOW});
+ }
+
+ WM_manipulatormap_add_handlers(ar, ar->manipulator_map);
+
/* object ops. */
/* important to be before Pose keymap since they can both be enabled at once */
@@ -582,6 +574,12 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
GPU_fx_compositor_destroy(rv3d->compositor);
rv3d->compositor = NULL;
}
+
+ if (rv3d->viewport) {
+ GPU_viewport_free(rv3d->viewport);
+ MEM_freeN(rv3d->viewport);
+ rv3d->viewport = NULL;
+ }
}
static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
@@ -712,6 +710,26 @@ static void view3d_dropboxes(void)
WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
}
+static void view3d_widgets(void)
+{
+ wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(
+ &(const struct wmManipulatorMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW});
+
+ WM_manipulatorgrouptype_append_and_link(mmap_type, TRANSFORM_WGT_manipulator);
+ WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_spot);
+ WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_area);
+ WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_target);
+ WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_force_field);
+ WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera);
+ WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera_view);
+ WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_empty_image);
+ WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_armature_spline);
+
+ WM_manipulatorgrouptype_append(VIEW3D_WGT_xform_cage);
+
+ WM_manipulatorgrouptype_append(VIEW3D_WGT_ruler);
+ WM_manipulatortype_append(VIEW3D_WT_ruler_item);
+}
/* type callback, not region itself */
@@ -739,6 +757,10 @@ static void view3d_main_region_free(ARegion *ar)
if (rv3d->compositor) {
GPU_fx_compositor_destroy(rv3d->compositor);
}
+ if (rv3d->viewport) {
+ GPU_viewport_free(rv3d->viewport);
+ MEM_freeN(rv3d->viewport);
+ }
MEM_freeN(rv3d);
ar->regiondata = NULL;
@@ -763,32 +785,22 @@ static void *view3d_main_region_duplicate(void *poin)
new->sms = NULL;
new->smooth_timer = NULL;
new->compositor = NULL;
+ new->viewport = NULL;
return new;
}
return NULL;
}
-static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene)
+static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene))
{
wmWindow *win = wmn->wm->winactive;
- ScrArea *sa;
unsigned int lay_used = 0;
- Base *base;
if (!win) return;
- base = scene->base.first;
- while (base) {
- lay_used |= base->lay & ((1 << 20) - 1); /* ignore localview */
-
- if (lay_used == (1 << 20) - 1)
- break;
-
- base = base->next;
- }
-
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ const bScreen *screen = WM_window_get_active_screen(win);
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->spacetype == SPACE_VIEW3D) {
if (BLI_findindex(&sa->regionbase, ar) != -1) {
View3D *v3d = sa->spacedata.first;
@@ -799,13 +811,21 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene
}
}
-static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *wmn)
+static void view3d_main_region_listener(
+ bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar,
+ wmNotifier *wmn, const Scene *scene)
{
- Scene *scene = sc->scene;
View3D *v3d = sa->spacedata.first;
-
+ RegionView3D *rv3d = ar->regiondata;
+ wmManipulatorMap *mmap = ar->manipulator_map;
+
/* context changes */
switch (wmn->category) {
+ case NC_WM:
+ if (ELEM(wmn->data, ND_UNDO)) {
+ WM_manipulatormap_tag_refresh(mmap);
+ }
+ break;
case NC_ANIMATION:
switch (wmn->data) {
case ND_KEYFRAME_PROP:
@@ -825,21 +845,32 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
break;
case NC_SCENE:
switch (wmn->data) {
+ case ND_SCENEBROWSE:
case ND_LAYER_CONTENT:
if (wmn->reference)
view3d_recalc_used_layers(ar, wmn, wmn->reference);
ED_region_tag_redraw(ar);
+ WM_manipulatormap_tag_refresh(mmap);
+ break;
+ case ND_LAYER:
+ if (wmn->reference) {
+ BKE_screen_view3d_sync(v3d, wmn->reference);
+ }
+ ED_region_tag_redraw(ar);
+ WM_manipulatormap_tag_refresh(mmap);
break;
- case ND_FRAME:
- case ND_TRANSFORM:
case ND_OB_ACTIVE:
case ND_OB_SELECT:
+ DEG_id_tag_update((ID *)&scene->id, DEG_TAG_SELECT_UPDATE);
+ ATTR_FALLTHROUGH;
+ case ND_FRAME:
+ case ND_TRANSFORM:
case ND_OB_VISIBLE:
- case ND_LAYER:
case ND_RENDER_OPTIONS:
case ND_MARKERS:
case ND_MODE:
ED_region_tag_redraw(ar);
+ WM_manipulatormap_tag_refresh(mmap);
break;
case ND_WORLD:
/* handled by space_view3d_listener() for v3d access */
@@ -847,7 +878,6 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
case ND_DRAW_RENDER_VIEWPORT:
{
if (v3d->camera && (scene == wmn->reference)) {
- RegionView3D *rv3d = ar->regiondata;
if (rv3d->persp == RV3D_CAMOB) {
ED_region_tag_redraw(ar);
}
@@ -872,6 +902,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
case ND_POINTCACHE:
case ND_LOD:
ED_region_tag_redraw(ar);
+ WM_manipulatormap_tag_refresh(mmap);
break;
}
switch (wmn->action) {
@@ -882,9 +913,18 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
break;
case NC_GEOM:
switch (wmn->data) {
+ case ND_SELECT:
+ {
+ WM_manipulatormap_tag_refresh(mmap);
+ if (scene->obedit) {
+ Object *ob = scene->obedit;
+ /* TODO(sergey): Notifiers shouldn't really be doing DEG tags. */
+ DEG_id_tag_update((ID *)ob->data, DEG_TAG_SELECT_UPDATE);
+ }
+ ATTR_FALLTHROUGH;
+ }
case ND_DATA:
case ND_VERTEX_GROUP:
- case ND_SELECT:
ED_region_tag_redraw(ar);
break;
}
@@ -899,7 +939,6 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
case ND_DRAW_RENDER_VIEWPORT:
{
if (v3d->camera && (v3d->camera->data == wmn->reference)) {
- RegionView3D *rv3d = ar->regiondata;
if (rv3d->persp == RV3D_CAMOB) {
ED_region_tag_redraw(ar);
}
@@ -928,21 +967,13 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
switch (wmn->data) {
case ND_SHADING:
case ND_NODES:
- {
-#ifdef WITH_LEGACY_DEPSGRAPH
- Object *ob = OBACT;
- if ((v3d->drawtype == OB_MATERIAL) ||
- (ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) ||
- (v3d->drawtype == OB_TEXTURE &&
- (scene->gm.matmode == GAME_MAT_GLSL ||
- BKE_scene_use_new_shading_nodes(scene))) ||
- !DEG_depsgraph_use_legacy())
-#endif
- {
- ED_region_tag_redraw(ar);
- }
+ /* TODO(sergey) This is a bit too much updates, but needed to
+ * have proper material drivers update in the viewport.
+ *
+ * How to solve?
+ */
+ ED_region_tag_redraw(ar);
break;
- }
case ND_SHADING_DRAW:
case ND_SHADING_LINKS:
ED_region_tag_redraw(ar);
@@ -954,20 +985,23 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
case ND_WORLD_DRAW:
/* handled by space_view3d_listener() for v3d access */
break;
+ case ND_WORLD:
+ /* Needed for updating world materials */
+ ED_region_tag_redraw(ar);
+ break;
}
break;
case NC_LAMP:
switch (wmn->data) {
case ND_LIGHTING:
- if ((v3d->drawtype == OB_MATERIAL) ||
- (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL)) ||
- !DEG_depsgraph_use_legacy())
- {
- ED_region_tag_redraw(ar);
- }
+ /* TODO(sergey): This is a bit too much, but needed to
+ * handle updates from new depsgraph.
+ */
+ ED_region_tag_redraw(ar);
break;
case ND_LIGHTING_DRAW:
ED_region_tag_redraw(ar);
+ WM_manipulatormap_tag_refresh(mmap);
break;
}
break;
@@ -987,10 +1021,10 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
case NC_SPACE:
if (wmn->data == ND_SPACE_VIEW3D) {
if (wmn->subtype == NS_VIEW3D_GPU) {
- RegionView3D *rv3d = ar->regiondata;
rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
}
ED_region_tag_redraw(ar);
+ WM_manipulatormap_tag_refresh(mmap);
}
break;
case NC_ID:
@@ -1003,15 +1037,13 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
case ND_SKETCH:
ED_region_tag_redraw(ar);
break;
- case ND_SCREENBROWSE:
- case ND_SCREENDELETE:
- case ND_SCREENSET:
- /* screen was changed, need to update used layers due to NC_SCENE|ND_LAYER_CONTENT */
- /* updates used layers only for View3D in active screen */
- if (wmn->reference) {
- bScreen *sc_ref = wmn->reference;
- view3d_recalc_used_layers(ar, wmn, sc_ref->scene);
- }
+ case ND_LAYOUTBROWSE:
+ case ND_LAYOUTDELETE:
+ case ND_LAYOUTSET:
+ WM_manipulatormap_tag_refresh(mmap);
+ ED_region_tag_redraw(ar);
+ break;
+ case ND_LAYER:
ED_region_tag_redraw(ar);
break;
}
@@ -1025,10 +1057,79 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
}
}
+static void view3d_main_region_message_subscribe(
+ const struct bContext *UNUSED(C),
+ struct WorkSpace *workspace, struct Scene *scene,
+ struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ /* Developer note: there are many properties that impact 3D view drawing,
+ * so instead of subscribing to individual properties, just subscribe to types
+ * accepting some redundant redraws.
+ *
+ * For other space types we might try avoid this, keep the 3D view as an exceptional case! */
+ ViewRender *view_render = BKE_viewrender_get(scene, workspace);
+ wmMsgParams_RNA msg_key_params = {0};
+
+ /* Only subscribe to types. */
+ StructRNA *type_array[] = {
+ /* These object have properties that impact drawing. */
+ &RNA_AreaLamp,
+ &RNA_Camera,
+ &RNA_Lamp,
+ &RNA_Speaker,
+ &RNA_SunLamp,
+
+ /* General types the 3D view depends on. */
+ &RNA_Object,
+ &RNA_UnitSettings, /* grid-floor */
+
+ &RNA_ViewRenderSettings,
+ &RNA_World,
+ };
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+ msg_key_params.ptr.type = type_array[i];
+ WM_msg_subscribe_rna_params(
+ mbus,
+ &msg_key_params,
+ &msg_sub_value_region_tag_redraw,
+ __func__);
+ }
+
+ /* Subscribe to a handful of other properties. */
+ RegionView3D *rv3d = ar->regiondata;
+
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_region_tag_redraw);
+ if (rv3d->persp == RV3D_CAMOB) {
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw);
+ }
+
+ /* Each engine could be responsible for its own engine data types.
+ * For now this is simplest. */
+ if (STREQ(view_render->engine_id, RE_engine_id_BLENDER_EEVEE)) {
+ extern StructRNA RNA_ViewLayerEngineSettingsEevee;
+ WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsEevee, &msg_sub_value_region_tag_redraw);
+ }
+ else if (STREQ(view_render->engine_id, RE_engine_id_BLENDER_CLAY)) {
+ extern StructRNA RNA_ViewLayerEngineSettingsClay;
+ WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsClay, &msg_sub_value_region_tag_redraw);
+ }
+}
+
/* concept is to retrieve cursor type context-less */
static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
{
- Scene *scene = win->screen->scene;
+ const Scene *scene = WM_window_get_active_scene(win);
if (scene->obedit) {
WM_cursor_set(win, CURSOR_EDIT);
@@ -1053,7 +1154,9 @@ static void view3d_header_region_draw(const bContext *C, ARegion *ar)
ED_region_header(C, ar);
}
-static void view3d_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void view3d_header_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -1099,7 +1202,9 @@ static void view3d_buttons_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, NULL, -1, true);
}
-static void view3d_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void view3d_buttons_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -1205,7 +1310,9 @@ static void view3d_tools_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, CTX_data_mode_string(C), -1, true);
}
-static void view3d_props_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void view3d_props_region_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -1225,7 +1332,9 @@ static void view3d_props_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
}
/* area (not region) level listener */
-static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn)
+static void space_view3d_listener(
+ bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn, Scene *UNUSED(scene),
+ WorkSpace *UNUSED(workspace))
{
View3D *v3d = sa->spacedata.first;
@@ -1260,8 +1369,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
};
@@ -1272,109 +1379,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;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (view_layer->basact) {
+ Object *ob = view_layer->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 ((view_layer->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) {
+ CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (view_layer->basact) {
+ Object *ob = view_layer->basact->object;
+ /* if hidden but in edit mode, we still display, can happen with animation */
+ if ((view_layer->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
+ CTX_data_id_pointer_set(result, &ob->id);
+ }
}
return 1;
@@ -1424,21 +1449,6 @@ static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_i
v3d->ob_centre_bone[0] = '\0';
}
}
-
- if (ELEM(GS(old_id->name), ID_IM, ID_MC)) {
- for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- if ((ID *)bgpic->ima == old_id) {
- bgpic->ima = (Image *)new_id;
- id_us_min(old_id);
- id_us_plus(new_id);
- }
- if ((ID *)bgpic->clip == old_id) {
- bgpic->clip = (MovieClip *)new_id;
- id_us_min(old_id);
- id_us_plus(new_id);
- }
- }
- }
}
if (is_local) {
@@ -1464,6 +1474,7 @@ void ED_spacetype_view3d(void)
st->operatortypes = view3d_operatortypes;
st->keymap = view3d_keymap;
st->dropboxes = view3d_dropboxes;
+ st->manipulators = view3d_widgets;
st->context = view3d_context;
st->id_remap = view3d_id_remap;
@@ -1477,6 +1488,7 @@ void ED_spacetype_view3d(void)
art->free = view3d_main_region_free;
art->duplicate = view3d_main_region_duplicate;
art->listener = view3d_main_region_listener;
+ art->message_subscribe = view3d_main_region_message_subscribe;
art->cursor = view3d_main_region_cursor;
art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 0c67776693d..644a6956e54 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -55,13 +55,14 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_customdata.h"
-#include "BKE_depsgraph.h"
#include "BKE_screen.h"
#include "BKE_editmesh.h"
#include "BKE_deform.h"
#include "BKE_object.h"
#include "BKE_object_deform.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -776,18 +777,18 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event)
return;
}
else {
- Scene *scene = CTX_data_scene(C);
- Object *ob = scene->basact->object;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = view_layer->basact->object;
ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
}
}
static int view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt))
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = OBACT;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
if (ob && (BKE_object_is_in_editmode_vgroup(ob) ||
BKE_object_is_in_wpaint_select_vert(ob)))
{
@@ -805,7 +806,8 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
{
uiBlock *block = uiLayoutAbsoluteBlock(pa->layout);
Scene *scene = CTX_data_scene(C);
- Object *ob = scene->basact->object;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = view_layer->basact->object;
MDeformVert *dv;
@@ -1095,9 +1097,9 @@ static void v3d_editmetaball_buts(uiLayout *layout, Object *ob)
static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event)
{
- Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C);
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
switch (event) {
@@ -1108,7 +1110,7 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event
case B_OBJECTPANELMEDIAN:
if (ob) {
v3d_editvertex_buts(NULL, v3d, ob, 1.0);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
break;
}
@@ -1119,16 +1121,17 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event
static int view3d_panel_transform_poll(const bContext *C, PanelType *UNUSED(pt))
{
- Scene *scene = CTX_data_scene(C);
- return (scene->basact != NULL);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ return (view_layer->basact != NULL);
}
static void view3d_panel_transform(const bContext *C, Panel *pa)
{
uiBlock *block;
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
- Object *ob = scene->basact->object;
+ Object *ob = view_layer->basact->object;
uiLayout *col;
block = uiLayoutGetBlock(pa->layout);
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index f717f1c0a43..9b07593e576 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -54,8 +54,9 @@
#include "BLI_utildefines.h"
#include "BKE_object.h"
+#include "BKE_context.h"
-#include "BKE_depsgraph.h" /* for object updating */
+#include "DEG_depsgraph.h"
#include "ED_screen.h"
@@ -137,10 +138,13 @@ Object *ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl)
* the view for first-person style navigation.
*/
struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
- Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d,
const bool use_parent_root)
{
View3DCameraControl *vctrl;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__);
@@ -177,7 +181,7 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
/* store the original camera loc and rot */
vctrl->obtfm = BKE_object_tfm_backup(ob_back);
- BKE_object_where_is_calc(scene, v3d->camera);
+ BKE_object_where_is_calc(&eval_ctx, scene, v3d->camera);
negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]);
rv3d->dist = 0.0;
@@ -242,7 +246,7 @@ void ED_view3d_cameracontrol_update(
ob_update = v3d->camera->parent;
while (ob_update) {
- DAG_id_tag_update(&ob_update->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob_update->id, OB_RECALC_OB);
ob_update = ob_update->parent;
}
@@ -264,7 +268,7 @@ void ED_view3d_cameracontrol_update(
BKE_object_apply_mat4(v3d->camera, view_mat, true, true);
- DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
+ DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
copy_v3_v3(v3d->camera->size, size_back);
@@ -299,7 +303,7 @@ void ED_view3d_cameracontrol_release(
/* store the original camera loc and rot */
BKE_object_tfm_restore(ob_back, vctrl->obtfm);
- DAG_id_tag_update(&ob_back->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob_back->id, OB_RECALC_OB);
}
else {
/* Non Camera we need to reset the view back to the original location bacause the user canceled*/
@@ -311,7 +315,7 @@ void ED_view3d_cameracontrol_release(
rv3d->dist = vctrl->dist_backup;
}
else if (vctrl->persp_backup == RV3D_CAMOB) { /* camera */
- DAG_id_tag_update((ID *)view3d_cameracontrol_object(vctrl), OB_RECALC_OB);
+ DEG_id_tag_update((ID *)view3d_cameracontrol_object(vctrl), OB_RECALC_OB);
/* always, is set to zero otherwise */
copy_v3_v3(rv3d->ofs, vctrl->ofs_backup);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 9e220f4b141..6ea2ff10af2 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -28,948 +28,284 @@
* \ingroup spview3d
*/
-#include <string.h>
-#include <stdio.h>
#include <math.h>
-#include "DNA_armature_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_customdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_group_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_key_types.h"
-#include "DNA_lamp_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_world_types.h"
-#include "DNA_brush_types.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_jitter.h"
-#include "BLI_utildefines.h"
-#include "BLI_endian_switch.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
#include "BLI_threads.h"
+#include "BLI_jitter.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
-#include "BKE_anim.h"
#include "BKE_camera.h"
#include "BKE_context.h"
-#include "BKE_customdata.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_image.h"
+#include "BKE_global.h"
#include "BKE_key.h"
-#include "BKE_main.h"
+#include "BKE_scene.h"
#include "BKE_object.h"
-#include "BKE_global.h"
#include "BKE_paint.h"
-#include "BKE_scene.h"
-#include "BKE_screen.h"
#include "BKE_unit.h"
-#include "BKE_movieclip.h"
-
-#include "RE_engine.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-#include "IMB_colormanagement.h"
+#include "BLF_api.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "BLT_translation.h"
-#include "WM_api.h"
+#include "DNA_armature_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
-#include "BLF_api.h"
-#include "BLT_translation.h"
+#include "DRW_engine.h"
#include "ED_armature.h"
#include "ED_keyframing.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
-#include "ED_space_api.h"
-#include "ED_screen_types.h"
#include "ED_transform.h"
-#include "UI_interface.h"
-#include "UI_interface_icons.h"
-#include "UI_resources.h"
+#include "DEG_depsgraph_query.h"
#include "GPU_draw.h"
-#include "GPU_framebuffer.h"
+#include "GPU_matrix.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
#include "GPU_material.h"
+#include "GPU_viewport.h"
#include "GPU_compositing.h"
-#include "GPU_extensions.h"
-#include "GPU_select.h"
-
-#include "view3d_intern.h" /* own include */
-
-/* prototypes */
-static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d);
-static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect);
-static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
- float winmat[4][4], const char *viewname);
-
-/* handy utility for drawing shapes in the viewport for arbitrary code.
- * could add lines and points too */
-// #define DEBUG_DRAW
-#ifdef DEBUG_DRAW
-static void bl_debug_draw(void);
-/* add these locally when using these functions for testing */
-extern void bl_debug_draw_quad_clear(void);
-extern void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]);
-extern void bl_debug_draw_edge_add(const float v0[3], const float v1[3]);
-extern void bl_debug_color_set(const unsigned int col);
-#endif
-
-void circf(float x, float y, float rad)
-{
- GLUquadricObj *qobj = gluNewQuadric();
-
- gluQuadricDrawStyle(qobj, GLU_FILL);
-
- glPushMatrix();
-
- glTranslatef(x, y, 0.0);
-
- gluDisk(qobj, 0.0, rad, 32, 1);
-
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
-}
-
-void circ(float x, float y, float rad)
-{
- GLUquadricObj *qobj = gluNewQuadric();
-
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
-
- glPushMatrix();
-
- glTranslatef(x, y, 0.0);
-
- gluDisk(qobj, 0.0, rad, 32, 1);
-
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
-}
-
-/* ********* custom clipping *********** */
+#include "MEM_guardedalloc.h"
-static void view3d_draw_clipping(RegionView3D *rv3d)
-{
- BoundBox *bb = rv3d->clipbb;
-
- if (bb) {
- const unsigned int clipping_index[6][4] = {
- {0, 1, 2, 3},
- {0, 4, 5, 1},
- {4, 7, 6, 5},
- {7, 3, 2, 6},
- {1, 5, 6, 2},
- {7, 4, 0, 3}
- };
-
- /* fill in zero alpha for rendering & re-projection [#31530] */
- unsigned char col[4];
- UI_GetThemeColor4ubv(TH_V3D_CLIPPING_BORDER, col);
- glColor4ubv(col);
-
- glEnable(GL_BLEND);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, bb->vec);
- glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisable(GL_BLEND);
- }
-}
+#include "UI_interface.h"
+#include "UI_resources.h"
-void ED_view3d_clipping_set(RegionView3D *rv3d)
-{
- double plane[4];
- const unsigned int tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
- unsigned int a;
-
- for (a = 0; a < tot; a++) {
- copy_v4db_v4fl(plane, rv3d->clip[a]);
- glClipPlane(GL_CLIP_PLANE0 + a, plane);
- glEnable(GL_CLIP_PLANE0 + a);
- }
-}
+#include "RE_engine.h"
-/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */
-void ED_view3d_clipping_disable(void)
-{
- unsigned int a;
+#include "WM_api.h"
+#include "WM_types.h"
- for (a = 0; a < 6; a++) {
- glDisable(GL_CLIP_PLANE0 + a);
- }
-}
-void ED_view3d_clipping_enable(void)
-{
- unsigned int a;
+#include "RNA_access.h"
- for (a = 0; a < 6; a++) {
- glEnable(GL_CLIP_PLANE0 + a);
- }
-}
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
-static bool view3d_clipping_test(const float co[3], const float clip[6][4])
-{
- if (plane_point_side_v3(clip[0], co) > 0.0f)
- if (plane_point_side_v3(clip[1], co) > 0.0f)
- if (plane_point_side_v3(clip[2], co) > 0.0f)
- if (plane_point_side_v3(clip[3], co) > 0.0f)
- return false;
+#include "view3d_intern.h" /* own include */
- return true;
-}
+/* ******************** general functions ***************** */
-/* for 'local' ED_view3d_clipping_local must run first
- * then all comparisons can be done in localspace */
-bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local)
+static bool use_depth_doit(Scene *scene, View3D *v3d)
{
- return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
-}
-
-/* ********* end custom clipping *********** */
-
-
-static void drawgrid_draw(ARegion *ar, double wx, double wy, double x, double y, double dx)
-{
- double verts[2][2];
-
- x += (wx);
- y += (wy);
-
- /* set fixed 'Y' */
- verts[0][1] = 0.0f;
- verts[1][1] = (double)ar->winy;
-
- /* iter over 'X' */
- verts[0][0] = verts[1][0] = x - dx * floor(x / dx);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_DOUBLE, 0, verts);
+ if (v3d->drawtype > OB_WIRE)
+ return true;
- while (verts[0][0] < ar->winx) {
- glDrawArrays(GL_LINES, 0, 2);
- verts[0][0] = verts[1][0] = verts[0][0] + dx;
- }
-
- /* set fixed 'X' */
- verts[0][0] = 0.0f;
- verts[1][0] = (double)ar->winx;
-
- /* iter over 'Y' */
- verts[0][1] = verts[1][1] = y - dx * floor(y / dx);
- while (verts[0][1] < ar->winy) {
- glDrawArrays(GL_LINES, 0, 2);
- verts[0][1] = verts[1][1] = verts[0][1] + dx;
+ /* special case (depth for wire color) */
+ if (v3d->drawtype <= OB_WIRE) {
+ if (scene->obedit && scene->obedit->type == OB_MESH) {
+ Mesh *me = scene->obedit->data;
+ if (me->drawflag & ME_DRAWEIGHT) {
+ return true;
+ }
+ }
}
-
- glDisableClientState(GL_VERTEX_ARRAY);
+ return false;
}
-#define GRID_MIN_PX_D 6.0
-#define GRID_MIN_PX_F 6.0f
-
-static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
+/**
+ * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
+ */
+void ED_view3d_update_viewmat(
+ const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar,
+ float viewmat[4][4], float winmat[4][4], const rcti *rect)
{
- /* extern short bgpicmode; */
RegionView3D *rv3d = ar->regiondata;
- double wx, wy, x, y, fw, fx, fy, dx;
- double vec4[4];
- unsigned char col[3], col2[3];
-
- fx = rv3d->persmat[3][0];
- fy = rv3d->persmat[3][1];
- fw = rv3d->persmat[3][3];
-
- wx = (ar->winx / 2.0); /* because of rounding errors, grid at wrong location */
- wy = (ar->winy / 2.0);
- x = (wx) * fx / fw;
- y = (wy) * fy / fw;
- vec4[0] = vec4[1] = v3d->grid;
-
- vec4[2] = 0.0;
- vec4[3] = 1.0;
- mul_m4_v4d(rv3d->persmat, vec4);
- fx = vec4[0];
- fy = vec4[1];
- fw = vec4[3];
-
- dx = fabs(x - (wx) * fx / fw);
- if (dx == 0) dx = fabs(y - (wy) * fy / fw);
-
- glLineWidth(1.0f);
-
- glDepthMask(GL_FALSE); /* disable write in zbuffer */
-
- /* check zoom out */
- UI_ThemeColor(TH_GRID);
-
- if (unit->system) {
- /* Use GRID_MIN_PX * 2 for units because very very small grid
- * items are less useful when dealing with units */
- const void *usys;
- int len, i;
- double dx_scalar;
- float blend_fac;
-
- bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len);
-
- if (usys) {
- i = len;
- while (i--) {
- double scalar = bUnit_GetScaler(usys, i);
-
- dx_scalar = dx * scalar / (double)unit->scale_length;
- if (dx_scalar < (GRID_MIN_PX_D * 2.0))
- continue;
+ /* setup window matrices */
+ if (winmat)
+ copy_m4_m4(rv3d->winmat, winmat);
+ else
+ view3d_winmatrix_set(ar, v3d, rect);
- /* Store the smallest drawn grid size units name so users know how big each grid cell is */
- if (*grid_unit == NULL) {
- *grid_unit = bUnit_GetNameDisplay(usys, i);
- rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length);
- }
- blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar);
+ /* setup view matrix */
+ if (viewmat)
+ copy_m4_m4(rv3d->viewmat, viewmat);
+ else
+ view3d_viewmatrix_set(eval_ctx, scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
- /* tweak to have the fade a bit nicer */
- blend_fac = (blend_fac * blend_fac) * 2.0f;
- CLAMP(blend_fac, 0.3f, 1.0f);
+ /* update utility matrices */
+ mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
+ invert_m4_m4(rv3d->persinv, rv3d->persmat);
+ invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
+ /* calculate GLSL view dependent values */
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, blend_fac);
+ /* store window coordinates scaling/offset */
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ rctf cameraborder;
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false);
+ rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
+ rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
- drawgrid_draw(ar, wx, wy, x, y, dx_scalar);
- }
- }
+ rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx;
+ rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy;
}
else {
- const double sublines = v3d->gridsubdiv;
- const float sublines_fl = v3d->gridsubdiv;
-
- if (dx < GRID_MIN_PX_D) {
- rv3d->gridview *= sublines_fl;
- dx *= sublines;
-
- if (dx < GRID_MIN_PX_D) {
- rv3d->gridview *= sublines_fl;
- dx *= sublines;
-
- if (dx < GRID_MIN_PX_D) {
- rv3d->gridview *= sublines_fl;
- dx *= sublines;
- if (dx < GRID_MIN_PX_D) {
- /* pass */
- }
- else {
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, dx);
- }
- }
- else { /* start blending out */
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
- drawgrid_draw(ar, wx, wy, x, y, dx);
-
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, sublines * dx);
- }
- }
- else { /* start blending out (GRID_MIN_PX < dx < (GRID_MIN_PX * 10)) */
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
- drawgrid_draw(ar, wx, wy, x, y, dx);
-
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, sublines * dx);
- }
- }
- else {
- if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
- rv3d->gridview /= sublines_fl;
- dx /= sublines;
- if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
- rv3d->gridview /= sublines_fl;
- dx /= sublines;
- if (dx > (GRID_MIN_PX_D * 10.0)) {
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, dx);
- }
- else {
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
- drawgrid_draw(ar, wx, wy, x, y, dx);
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
- }
- }
- else {
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
- drawgrid_draw(ar, wx, wy, x, y, dx);
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
- }
- }
- else {
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
- drawgrid_draw(ar, wx, wy, x, y, dx);
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
- }
- }
+ rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f;
+ rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f;
}
+ /* calculate pixelsize factor once, is used for lamps and obcenters */
+ {
+ /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])'
+ * because of float point precision problems at large values [#23908] */
+ float v1[3], v2[3];
+ float len_px, len_sc;
- x += (wx);
- y += (wy);
- UI_GetThemeColor3ubv(TH_GRID, col);
-
- setlinestyle(0);
-
- /* center cross */
- /* horizontal line */
- if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT))
- UI_make_axis_color(col, col2, 'Y');
- else UI_make_axis_color(col, col2, 'X');
- glColor3ubv(col2);
-
- fdrawline(0.0, y, (float)ar->winx, y);
-
- /* vertical line */
- if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM))
- UI_make_axis_color(col, col2, 'Y');
- else UI_make_axis_color(col, col2, 'Z');
- glColor3ubv(col2);
-
- fdrawline(x, 0.0, x, (float)ar->winy);
-
- glDepthMask(GL_TRUE); /* enable write in zbuffer */
-}
-#undef GRID_MIN_PX
+ v1[0] = rv3d->persmat[0][0];
+ v1[1] = rv3d->persmat[1][0];
+ v1[2] = rv3d->persmat[2][0];
-/** could move this elsewhere, but tied into #ED_view3d_grid_scale */
-float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
-{
- /* apply units */
- if (scene->unit.system) {
- const void *usys;
- int len;
+ v2[0] = rv3d->persmat[0][1];
+ v2[1] = rv3d->persmat[1][1];
+ v2[2] = rv3d->persmat[2][1];
- bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
+ len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
+ len_sc = (float)MAX2(ar->winx, ar->winy);
- if (usys) {
- int i = bUnit_GetBaseUnit(usys);
- if (grid_unit)
- *grid_unit = bUnit_GetNameDisplay(usys, i);
- return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length;
- }
+ rv3d->pixsize = len_px / len_sc;
}
-
- return 1.0f;
-}
-
-float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
-{
- return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
}
-static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
+static void view3d_main_region_setup_view(
+ const EvaluationContext *eval_ctx, Scene *scene,
+ View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect)
{
- float grid, grid_scale;
- unsigned char col_grid[3];
- const int gridlines = v3d->gridlines / 2;
-
- if (v3d->gridlines < 3) return;
-
- /* use 'grid_scale' instead of 'v3d->grid' from now on */
- grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
- grid = gridlines * grid_scale;
-
- if (!write_depth)
- glDepthMask(GL_FALSE);
-
- UI_GetThemeColor3ubv(TH_GRID, col_grid);
-
- glLineWidth(1);
-
- /* draw the Y axis and/or grid lines */
- if (v3d->gridflag & V3D_SHOW_FLOOR) {
- const int sublines = v3d->gridsubdiv;
- float vert[4][3] = {{0.0f}};
- unsigned char col_bg[3];
- unsigned char col_grid_emphasise[3], col_grid_light[3];
- int a;
- int prev_emphasise = -1;
-
- UI_GetThemeColor3ubv(TH_BACK, col_bg);
-
- /* emphasise division lines lighter instead of darker, if background is darker than grid */
- UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
- UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
- (((col_grid[0] + col_grid[1] + col_grid[2]) + 30) >
- (col_bg[0] + col_bg[1] + col_bg[2])) ? 20 : -10);
-
- /* set fixed axis */
- vert[0][0] = vert[2][1] = grid;
- vert[1][0] = vert[3][1] = -grid;
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, vert);
-
- for (a = -gridlines; a <= gridlines; a++) {
- const float line = a * grid_scale;
- const int is_emphasise = (a % sublines) == 0;
-
- if (is_emphasise != prev_emphasise) {
- glColor3ubv(is_emphasise ? col_grid_emphasise : col_grid_light);
- prev_emphasise = is_emphasise;
- }
-
- /* set variable axis */
- vert[0][1] = vert[1][1] = vert[2][0] = vert[3][0] = line;
+ RegionView3D *rv3d = ar->regiondata;
- glDrawArrays(GL_LINES, 0, 4);
- }
+ ED_view3d_update_viewmat(eval_ctx, scene, v3d, ar, viewmat, winmat, rect);
- glDisableClientState(GL_VERTEX_ARRAY);
- }
-
- /* draw the Z axis line */
- /* check for the 'show Z axis' preference */
- if (v3d->gridflag & (V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
- glBegin(GL_LINES);
- int axis;
- for (axis = 0; axis < 3; axis++) {
- if (v3d->gridflag & (V3D_SHOW_X << axis)) {
- float vert[3];
- unsigned char tcol[3];
-
- UI_make_axis_color(col_grid, tcol, 'X' + axis);
- glColor3ubv(tcol);
-
- zero_v3(vert);
- vert[axis] = grid;
- glVertex3fv(vert);
- vert[axis] = -grid;
- glVertex3fv(vert);
- }
- }
- glEnd();
- }
-
- glDepthMask(GL_TRUE);
+ /* set for opengl */
+ gpuLoadProjectionMatrix(rv3d->winmat);
+ gpuLoadMatrix(rv3d->viewmat);
}
-
-static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
+static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d)
{
- int co[2];
-
- /* we don't want the clipping for cursor */
- if (ED_view3d_project_int_global(ar, ED_view3d_cursor3d_get(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- const float f5 = 0.25f * U.widget_unit;
- const float f10 = 0.5f * U.widget_unit;
- const float f20 = U.widget_unit;
-
- glLineWidth(1);
- setlinestyle(0);
- cpack(0xFF);
- circ((float)co[0], (float)co[1], f10);
- setlinestyle(4);
- cpack(0xFFFFFF);
- circ((float)co[0], (float)co[1], f10);
- setlinestyle(0);
-
- UI_ThemeColor(TH_VIEW_OVERLAY);
- sdrawline(co[0] - f20, co[1], co[0] - f5, co[1]);
- sdrawline(co[0] + f5, co[1], co[0] + f20, co[1]);
- sdrawline(co[0], co[1] - f20, co[0], co[1] - f5);
- sdrawline(co[0], co[1] + f5, co[0], co[1] + f20);
+ if ((scene->r.scemode & R_MULTIVIEW) == 0) {
+ return false;
}
-}
-
-/* Draw a live substitute of the view icon, which is always shown
- * colors copied from transform_manipulator.c, we should keep these matching. */
-static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
-{
- const float k = U.rvisize * U.pixelsize; /* axis size */
- const float toll = 0.5; /* used to see when view is quasi-orthogonal */
- float startx = k + 1.0f; /* axis center in screen coordinates, x=y */
- float starty = k + 1.0f;
- float ydisp = 0.0; /* vertical displacement to allow obj info text */
- int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */
- float vec[3];
- float dx, dy;
-
- int axis_order[3] = {0, 1, 2};
- int axis_i;
- startx += rect->xmin;
- starty += rect->ymin;
-
- axis_sort_v3(rv3d->viewinv[2], axis_order);
-
- /* thickness of lines is proportional to k */
- glLineWidth(2);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- for (axis_i = 0; axis_i < 3; axis_i++) {
- int i = axis_order[axis_i];
- const char axis_text[2] = {'x' + i, '\0'};
-
- zero_v3(vec);
- vec[i] = 1.0f;
- mul_qt_v3(rv3d->viewquat, vec);
- dx = vec[0] * k;
- dy = vec[1] * k;
-
- UI_ThemeColorShadeAlpha(TH_AXIS_X + i, 0, bright);
- glBegin(GL_LINES);
- glVertex2f(startx, starty + ydisp);
- glVertex2f(startx + dx, starty + dy + ydisp);
- glEnd();
-
- if (fabsf(dx) > toll || fabsf(dy) > toll) {
- BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, axis_text, 1);
-
- /* BLF_draw_default disables blending */
- glEnable(GL_BLEND);
- }
+ if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) {
+ return false;
}
- glDisable(GL_BLEND);
-}
-
-#ifdef WITH_INPUT_NDOF
-/* draw center and axis of rotation for ongoing 3D mouse navigation */
-static void draw_rotation_guide(RegionView3D *rv3d)
-{
- float o[3]; /* center of rotation */
- float end[3]; /* endpoints for drawing */
-
- float color[4] = {0.0f, 0.4235f, 1.0f, 1.0f}; /* bright blue so it matches device LEDs */
-
- negate_v3_v3(o, rv3d->ofs);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPointSize(5);
- glEnable(GL_POINT_SMOOTH);
- glDepthMask(0); /* don't overwrite zbuf */
-
- if (rv3d->rot_angle != 0.0f) {
- /* -- draw rotation axis -- */
- float scaled_axis[3];
- const float scale = rv3d->dist;
- mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale);
-
-
- glBegin(GL_LINE_STRIP);
- color[3] = 0.0f; /* more transparent toward the ends */
- glColor4fv(color);
- add_v3_v3v3(end, o, scaled_axis);
- glVertex3fv(end);
-
-#if 0
- color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */
- /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */
-#endif
-
- color[3] = 0.5f; /* more opaque toward the center */
- glColor4fv(color);
- glVertex3fv(o);
-
- color[3] = 0.0f;
- glColor4fv(color);
- sub_v3_v3v3(end, o, scaled_axis);
- glVertex3fv(end);
- glEnd();
-
- /* -- draw ring around rotation center -- */
- {
-#define ROT_AXIS_DETAIL 13
-
- const float s = 0.05f * scale;
- const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL);
- float angle;
- int i;
-
- float q[4]; /* rotate ring so it's perpendicular to axis */
- const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f;
- if (!upright) {
- const float up[3] = {0.0f, 0.0f, 1.0f};
- float vis_angle, vis_axis[3];
-
- cross_v3_v3v3(vis_axis, up, rv3d->rot_axis);
- vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis));
- axis_angle_to_quat(q, vis_axis, vis_angle);
+ switch (v3d->stereo3d_camera) {
+ case STEREO_MONO_ID:
+ return false;
+ break;
+ case STEREO_3D_ID:
+ /* win will be NULL when calling this from the selection or draw loop. */
+ if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) {
+ return false;
}
-
- color[3] = 0.25f; /* somewhat faint */
- glColor4fv(color);
- glBegin(GL_LINE_LOOP);
- for (i = 0, angle = 0.0f; i < ROT_AXIS_DETAIL; ++i, angle += step) {
- float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f};
-
- if (!upright) {
- mul_qt_v3(q, p);
- }
-
- add_v3_v3(p, o);
- glVertex3fv(p);
+ if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) &&
+ !BKE_scene_multiview_is_stereo3d(&scene->r))
+ {
+ return false;
}
- glEnd();
-
-#undef ROT_AXIS_DETAIL
- }
-
- color[3] = 1.0f; /* solid dot */
- }
- else
- color[3] = 0.5f; /* see-through dot */
-
- /* -- draw rotation center -- */
- glColor4fv(color);
- glBegin(GL_POINTS);
- glVertex3fv(o);
- glEnd();
-
-#if 0
- /* find screen coordinates for rotation center, then draw pretty icon */
- mul_m4_v3(rv3d->persinv, rot_center);
- UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN);
- /* ^^ just playing around, does not work */
-#endif
-
- glDisable(GL_BLEND);
- glDisable(GL_POINT_SMOOTH);
- glDepthMask(1);
-}
-#endif /* WITH_INPUT_NDOF */
-
-static void draw_view_icon(RegionView3D *rv3d, rcti *rect)
-{
- BIFIconID icon;
-
- if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM))
- icon = ICON_AXIS_TOP;
- else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK))
- icon = ICON_AXIS_FRONT;
- else if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT))
- icon = ICON_AXIS_SIDE;
- else return;
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- UI_icon_draw(5.0 + rect->xmin, 5.0 + rect->ymin, icon);
-
- glDisable(GL_BLEND);
-}
-
-static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
-{
- const char *name = NULL;
-
- switch (rv3d->view) {
- case RV3D_VIEW_FRONT:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho");
- else name = IFACE_("Front Persp");
- break;
- case RV3D_VIEW_BACK:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho");
- else name = IFACE_("Back Persp");
- break;
- case RV3D_VIEW_TOP:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho");
- else name = IFACE_("Top Persp");
- break;
- case RV3D_VIEW_BOTTOM:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho");
- else name = IFACE_("Bottom Persp");
- break;
- case RV3D_VIEW_RIGHT:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho");
- else name = IFACE_("Right Persp");
break;
- case RV3D_VIEW_LEFT:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho");
- else name = IFACE_("Left Persp");
- break;
-
+ /* We always need the stereo calculation for left and right cameras. */
+ case STEREO_LEFT_ID:
+ case STEREO_RIGHT_ID:
default:
- if (rv3d->persp == RV3D_CAMOB) {
- if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
- Camera *cam;
- cam = v3d->camera->data;
- if (cam->type == CAM_PERSP) {
- name = IFACE_("Camera Persp");
- }
- else if (cam->type == CAM_ORTHO) {
- name = IFACE_("Camera Ortho");
- }
- else {
- BLI_assert(cam->type == CAM_PANO);
- name = IFACE_("Camera Pano");
- }
- }
- else {
- name = IFACE_("Object as Camera");
- }
- }
- else {
- name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp");
- }
break;
}
-
- return name;
+ return true;
}
-static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
-{
- RegionView3D *rv3d = ar->regiondata;
- const char *name = view3d_get_name(v3d, rv3d);
- /* increase size for unicode languages (Chinese in utf-8...) */
-#ifdef WITH_INTERNATIONAL
- char tmpstr[96];
-#else
- char tmpstr[32];
-#endif
- if (v3d->localvd) {
- BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
- name = tmpstr;
- }
+/* setup the view and win matrices for the multiview cameras
+ *
+ * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called
+ * we have no winmatrix (i.e., projection matrix) defined at that time.
+ * Since the camera and the camera shift are needed for the winmat calculation
+ * we do a small hack to replace it temporarily so we don't need to change the
+ * view3d)main_region_setup_view() code to account for that.
+ */
+static void view3d_stereo3d_setup(
+ const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect)
+{
+ bool is_left;
+ const char *names[2] = { STEREO_LEFT_NAME, STEREO_RIGHT_NAME };
+ const char *viewname;
- UI_ThemeColor(TH_TEXT_HI);
-#ifdef WITH_INTERNATIONAL
- BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
-#else
- BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
-#endif
-}
+ /* show only left or right camera */
+ if (v3d->stereo3d_camera != STEREO_3D_ID)
+ v3d->multiview_eye = v3d->stereo3d_camera;
-/* draw info beside axes in bottom left-corner:
- * framenum, object name, bone name (if available), marker name (if available)
- */
+ is_left = v3d->multiview_eye == STEREO_LEFT_ID;
+ viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID];
-static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
-{
- const int cfra = CFRA;
- const char *msg_pin = " (Pinned)";
- const char *msg_sep = " : ";
+ /* update the viewport matrices with the new camera */
+ if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
+ Camera *data;
+ float viewmat[4][4];
+ float shiftx;
- char info[300];
- const char *markern;
- char *s = info;
- short offset = 1.5f * UI_UNIT_X + rect->xmin;
+ data = (Camera *)v3d->camera->data;
+ shiftx = data->shiftx;
- s += sprintf(s, "(%d)", cfra);
+ BLI_lock_thread(LOCK_VIEW3D);
+ data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
- /*
- * info can contain:
- * - a frame (7 + 2)
- * - 3 object names (MAX_NAME)
- * - 2 BREAD_CRUMB_SEPARATORs (6)
- * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room!
- * - a marker name (MAX_NAME + 3)
- */
+ BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
+ view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, NULL, rect);
- /* get name of marker on current frame (if available) */
- markern = BKE_scene_find_marker_name(scene, cfra);
-
- /* check if there is an object */
- if (ob) {
- *s++ = ' ';
- s += BLI_strcpy_rlen(s, ob->id.name + 2);
+ data->shiftx = shiftx;
+ BLI_unlock_thread(LOCK_VIEW3D);
+ }
+ else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
+ float viewmat[4][4];
+ Object *view_ob = v3d->camera;
+ Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
- /* name(s) to display depends on type of object */
- if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
-
- /* show name of active bone too (if possible) */
- if (arm->edbo) {
- if (arm->act_edbone) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_edbone->name);
- }
- }
- else if (ob->mode & OB_MODE_POSE) {
- if (arm->act_bone) {
+ BLI_lock_thread(LOCK_VIEW3D);
+ v3d->camera = camera;
- if (arm->act_bone->layer & arm->layer) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_bone->name);
- }
- }
- }
- }
- else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
- Key *key = NULL;
- KeyBlock *kb = NULL;
+ BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
+ view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, NULL, rect);
- /* try to display active bone and active shapekey too (if they exist) */
+ v3d->camera = view_ob;
+ BLI_unlock_thread(LOCK_VIEW3D);
+ }
+}
- if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) {
- Object *armobj = BKE_object_pose_armature_get(ob);
- if (armobj && armobj->mode & OB_MODE_POSE) {
- bArmature *arm = armobj->data;
- if (arm->act_bone) {
- if (arm->act_bone->layer & arm->layer) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_bone->name);
- }
- }
- }
- }
+/**
+ * Set the correct matrices
+ */
+void ED_view3d_draw_setup_view(
+ wmWindow *win, const EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d,
+ float viewmat[4][4], float winmat[4][4], const rcti *rect)
+{
+ RegionView3D *rv3d = ar->regiondata;
- key = BKE_key_from_object(ob);
- if (key) {
- kb = BLI_findlink(&key->block, ob->shapenr - 1);
- if (kb) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, kb->name);
- if (ob->shapeflag & OB_SHAPE_LOCK) {
- s += BLI_strcpy_rlen(s, IFACE_(msg_pin));
- }
- }
- }
- }
-
- /* color depends on whether there is a keyframe */
- if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL))
- UI_ThemeColor(TH_TIME_KEYFRAME);
- else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra))
- UI_ThemeColor(TH_TIME_GP_KEYFRAME);
- else
- UI_ThemeColor(TH_TEXT_HI);
+ /* Setup the view matrix. */
+ if (view3d_stereo3d_active(win, scene, v3d, rv3d)) {
+ view3d_stereo3d_setup(eval_ctx, scene, v3d, ar, rect);
}
else {
- /* no object */
- if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra))
- UI_ThemeColor(TH_TIME_GP_KEYFRAME);
- else
- UI_ThemeColor(TH_TEXT_HI);
+ view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, rect);
}
-
- if (markern) {
- s += sprintf(s, " <%s>", markern);
- }
-
- if (U.uiflag & USER_SHOW_ROTVIEWICON)
- offset = U.widget_unit + (U.rvisize * 2) + rect->xmin;
-
- BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info));
}
+/* ******************** view border ***************** */
+
static void view3d_camera_border(
const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
rctf *r_viewborder, const bool no_shift, const bool no_zoom)
@@ -1023,7 +359,7 @@ void ED_view3d_calc_camera_border(
view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false);
}
-static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float fac)
+static void drawviewborder_grid3(uint shdr_pos, float x1, float x2, float y1, float y2, float fac)
{
float x3, y3, x4, y4;
@@ -1032,29 +368,33 @@ static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float f
x4 = x1 + (1.0f - fac) * (x2 - x1);
y4 = y1 + (1.0f - fac) * (y2 - y1);
- glBegin(GL_LINES);
- glVertex2f(x1, y3);
- glVertex2f(x2, y3);
+ immBegin(GWN_PRIM_LINES, 8);
+
+ immVertex2f(shdr_pos, x1, y3);
+ immVertex2f(shdr_pos, x2, y3);
- glVertex2f(x1, y4);
- glVertex2f(x2, y4);
+ immVertex2f(shdr_pos, x1, y4);
+ immVertex2f(shdr_pos, x2, y4);
- glVertex2f(x3, y1);
- glVertex2f(x3, y2);
+ immVertex2f(shdr_pos, x3, y1);
+ immVertex2f(shdr_pos, x3, y2);
- glVertex2f(x4, y1);
- glVertex2f(x4, y2);
- glEnd();
+ immVertex2f(shdr_pos, x4, y1);
+ immVertex2f(shdr_pos, x4, y2);
+
+ immEnd();
}
/* harmonious triangle */
-static void drawviewborder_triangle(float x1, float x2, float y1, float y2, const char golden, const char dir)
+static void drawviewborder_triangle(
+ uint shdr_pos, float x1, float x2, float y1, float y2, const char golden, const char dir)
{
float ofs;
float w = x2 - x1;
float h = y2 - y1;
- glBegin(GL_LINES);
+ immBegin(GWN_PRIM_LINES, 6);
+
if (w > h) {
if (golden) {
ofs = w * (1.0f - (1.0f / 1.61803399f));
@@ -1064,14 +404,14 @@ static void drawviewborder_triangle(float x1, float x2, float y1, float y2, cons
}
if (dir == 'B') SWAP(float, y1, y2);
- glVertex2f(x1, y1);
- glVertex2f(x2, y2);
+ immVertex2f(shdr_pos, x1, y1);
+ immVertex2f(shdr_pos, x2, y2);
- glVertex2f(x2, y1);
- glVertex2f(x1 + (w - ofs), y2);
+ immVertex2f(shdr_pos, x2, y1);
+ immVertex2f(shdr_pos, x1 + (w - ofs), y2);
- glVertex2f(x1, y2);
- glVertex2f(x1 + ofs, y1);
+ immVertex2f(shdr_pos, x1, y2);
+ immVertex2f(shdr_pos, x1 + ofs, y1);
}
else {
if (golden) {
@@ -1082,16 +422,17 @@ static void drawviewborder_triangle(float x1, float x2, float y1, float y2, cons
}
if (dir == 'B') SWAP(float, x1, x2);
- glVertex2f(x1, y1);
- glVertex2f(x2, y2);
+ immVertex2f(shdr_pos, x1, y1);
+ immVertex2f(shdr_pos, x2, y2);
- glVertex2f(x2, y1);
- glVertex2f(x1, y1 + ofs);
+ immVertex2f(shdr_pos, x2, y1);
+ immVertex2f(shdr_pos, x1, y1 + ofs);
- glVertex2f(x1, y2);
- glVertex2f(x2, y1 + (h - ofs));
+ immVertex2f(shdr_pos, x1, y2);
+ immVertex2f(shdr_pos, x2, y1 + (h - ofs));
}
- glEnd();
+
+ immEnd();
}
static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
@@ -1128,58 +469,76 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
y1i = (int)(y1 - 1.0001f);
x2i = (int)(x2 + (1.0f - 0.0001f));
y2i = (int)(y2 + (1.0f - 0.0001f));
-
- /* passepartout, specified in camera edit buttons */
- if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) {
- const float winx = (ar->winx + 1);
- const float winy = (ar->winy + 1);
- if (ca->passepartalpha == 1.0f) {
- glColor3f(0, 0, 0);
+ uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ /* First, solid lines. */
+ {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* passepartout, specified in camera edit buttons */
+ if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) {
+ const float winx = (ar->winx + 1);
+ const float winy = (ar->winy + 1);
+
+ float alpha = 1.0f;
+
+ if (ca->passepartalpha != 1.0f) {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ alpha = ca->passepartalpha;
+ }
+
+ immUniformColor4f(0.0f, 0.0f, 0.0f, alpha);
+
+ if (x1i > 0.0f)
+ immRectf(shdr_pos, 0.0f, winy, x1i, 0.0f);
+ if (x2i < winx)
+ immRectf(shdr_pos, x2i, winy, winx, 0.0f);
+ if (y2i < winy)
+ immRectf(shdr_pos, x1i, winy, x2i, y2i);
+ if (y2i > 0.0f)
+ immRectf(shdr_pos, x1i, y1i, x2i, 0.0f);
+
+ glDisable(GL_BLEND);
}
- else {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- glColor4f(0, 0, 0, ca->passepartalpha);
+
+ immUniformThemeColor(TH_BACK);
+ imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i);
+
+#ifdef VIEW3D_CAMERA_BORDER_HACK
+ if (view3d_camera_border_hack_test == true) {
+ immUniformColor3ubv(view3d_camera_border_hack_col);
+ imm_draw_box_wire_2d(shdr_pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1);
+ view3d_camera_border_hack_test = false;
}
+#endif
- if (x1i > 0.0f)
- glRectf(0.0, winy, x1i, 0.0);
- if (x2i < winx)
- glRectf(x2i, winy, winx, 0.0);
- if (y2i < winy)
- glRectf(x1i, winy, x2i, y2i);
- if (y2i > 0.0f)
- glRectf(x1i, y1i, x2i, 0.0);
-
- glDisable(GL_BLEND);
+ immUnbindProgram();
}
- setlinestyle(0);
+ /* And now, the dashed lines! */
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
- UI_ThemeColor(TH_BACK);
-
- fdrawbox(x1i, y1i, x2i, y2i);
+ {
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
-#ifdef VIEW3D_CAMERA_BORDER_HACK
- if (view3d_camera_border_hack_test == true) {
- glColor3ubv(view3d_camera_border_hack_col);
- fdrawbox(x1i + 1, y1i + 1, x2i - 1, y2i - 1);
- view3d_camera_border_hack_test = false;
- }
-#endif
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
- setlinestyle(3);
+ /* outer line not to confuse with object selection */
+ if (v3d->flag2 & V3D_LOCK_CAMERA) {
+ immUniformThemeColor(TH_REDALERT);
+ imm_draw_box_wire_2d(shdr_pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1);
+ }
- /* outer line not to confuse with object selecton */
- if (v3d->flag2 & V3D_LOCK_CAMERA) {
- UI_ThemeColor(TH_REDALERT);
- fdrawbox(x1i - 1, y1i - 1, x2i + 1, y2i + 1);
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i);
}
- UI_ThemeColor(TH_VIEW_OVERLAY);
- fdrawbox(x1i, y1i, x2i, y2i);
-
/* border */
if (scene->r.mode & R_BORDER) {
float x3, y3, x4, y4;
@@ -1189,82 +548,76 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1);
y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1);
- cpack(0x4040FF);
- sdrawbox(x3, y3, x4, y4);
+ immUniformColor3f(1.0f, 0.25f, 0.25f);
+ imm_draw_box_wire_2d(shdr_pos, x3, y3, x4, y4);
}
/* safety border */
if (ca) {
+ immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f);
+
if (ca->dtx & CAM_DTX_CENTER) {
float x3, y3;
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
-
x3 = x1 + 0.5f * (x2 - x1);
y3 = y1 + 0.5f * (y2 - y1);
- glBegin(GL_LINES);
- glVertex2f(x1, y3);
- glVertex2f(x2, y3);
+ immBegin(GWN_PRIM_LINES, 4);
- glVertex2f(x3, y1);
- glVertex2f(x3, y2);
- glEnd();
+ immVertex2f(shdr_pos, x1, y3);
+ immVertex2f(shdr_pos, x2, y3);
+
+ immVertex2f(shdr_pos, x3, y1);
+ immVertex2f(shdr_pos, x3, y2);
+
+ immEnd();
}
if (ca->dtx & CAM_DTX_CENTER_DIAG) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
+ immBegin(GWN_PRIM_LINES, 4);
- glBegin(GL_LINES);
- glVertex2f(x1, y1);
- glVertex2f(x2, y2);
+ immVertex2f(shdr_pos, x1, y1);
+ immVertex2f(shdr_pos, x2, y2);
- glVertex2f(x1, y2);
- glVertex2f(x2, y1);
- glEnd();
+ immVertex2f(shdr_pos, x1, y2);
+ immVertex2f(shdr_pos, x2, y1);
+
+ immEnd();
}
if (ca->dtx & CAM_DTX_THIRDS) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_grid3(x1, x2, y1, y2, 1.0f / 3.0f);
+ drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f / 3.0f);
}
if (ca->dtx & CAM_DTX_GOLDEN) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_grid3(x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f));
+ drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f));
}
if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_triangle(x1, x2, y1, y2, 0, 'A');
+ drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'A');
}
if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_triangle(x1, x2, y1, y2, 0, 'B');
+ drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'B');
}
if (ca->dtx & CAM_DTX_HARMONY_TRI_A) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_triangle(x1, x2, y1, y2, 1, 'A');
+ drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'A');
}
if (ca->dtx & CAM_DTX_HARMONY_TRI_B) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_triangle(x1, x2, y1, y2, 1, 'B');
+ drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'B');
}
if (ca->flag & CAM_SHOW_SAFE_MARGINS) {
UI_draw_safe_areas(
- x1, x2, y1, y2,
- scene->safe_areas.title,
- scene->safe_areas.action);
+ shdr_pos, x1, x2, y1, y2,
+ scene->safe_areas.title, scene->safe_areas.action);
if (ca->flag & CAM_SHOW_SAFE_CENTER) {
UI_draw_safe_areas(
- x1, x2, y1, y2,
- scene->safe_areas.title_center,
- scene->safe_areas.action_center);
+ shdr_pos, x1, x2, y1, y2,
+ scene->safe_areas.title_center, scene->safe_areas.action_center);
}
}
@@ -1300,1776 +653,1293 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
}
/* draw */
- UI_ThemeColorShade(TH_VIEW_OVERLAY, 100);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f);
+ immUniformThemeColorShade(TH_VIEW_OVERLAY, 100);
+
+ /* TODO Was using UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color).
+ * We'll probably need a new imm_draw_line_roundbox_dashed dor that - though in practice the
+ * 2.0f round corner effect was nearly not visible anyway... */
+ imm_draw_box_wire_2d(shdr_pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
}
}
- setlinestyle(0);
+ immUnbindProgram();
+ /* end dashed lines */
/* 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);
}
}
-/* *********************** backdraw for selection *************** */
+static void drawrenderborder(ARegion *ar, View3D *v3d)
+{
+ /* use the same program for everything */
+ uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ glLineWidth(1.0f);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniform4f("color", 1.0f, 0.25f, 0.25f, 1.0f);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ imm_draw_box_wire_2d(shdr_pos,
+ v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy,
+ v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy);
-static void backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d)
+ immUnbindProgram();
+}
+
+void ED_view3d_draw_depth(
+ const EvaluationContext *eval_ctx, struct Depsgraph *graph,
+ ARegion *ar, View3D *v3d, bool alphaoverride)
{
+ struct bThemeState theme_state;
+ Scene *scene = DEG_get_evaluated_scene(graph);
RegionView3D *rv3d = ar->regiondata;
- struct Base *base = scene->basact;
- int multisample_enabled;
- BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
+ short zbuf = v3d->zbuf;
+ short flag = v3d->flag;
+ float glalphaclip = U.glalphaclip;
+ int obcenter_dia = U.obcenter_dia;
+ /* temp set drawtype to solid */
+ /* Setting these temporarily is not nice */
+ v3d->flag &= ~V3D_SELECT_OUTLINE;
+ U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */
+ U.obcenter_dia = 0;
- if (base && (base->object->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
- BKE_paint_select_face_test(base->object)))
- {
- /* do nothing */
- }
- /* texture paint mode sampling */
- else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) &&
- (v3d->drawtype > OB_WIRE))
- {
- /* do nothing */
- }
- else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
- V3D_IS_ZBUF(v3d))
- {
- /* do nothing */
- }
- else if (scene->obedit &&
- V3D_IS_ZBUF(v3d))
- {
- /* do nothing */
- }
- else {
- v3d->flag &= ~V3D_INVALID_BACKBUF;
- return;
- }
+ /* Tools may request depth outside of regular drawing code. */
+ UI_Theme_Store(&theme_state);
+ UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
- if (!(v3d->flag & V3D_INVALID_BACKBUF))
- return;
+ ED_view3d_draw_setup_view(NULL, eval_ctx, scene, ar, v3d, NULL, NULL, NULL);
-#if 0
- if (test) {
- if (qtest()) {
- addafterqueue(ar->win, BACKBUFDRAW, 1);
- return;
- }
- }
-#endif
+ glClear(GL_DEPTH_BUFFER_BIT);
- if (v3d->drawtype > OB_WIRE) v3d->zbuf = true;
-
- /* dithering and AA break color coding, so disable */
- glDisable(GL_DITHER);
-
- multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
- if (multisample_enabled)
- glDisable(GL_MULTISAMPLE);
-
- if (win->multisamples != USER_MULTISAMPLE_NONE) {
- /* for multisample we use an offscreen FBO. multisample drawing can fail
- * with color coded selection drawing, and reading back depths from such
- * a buffer can also cause a few seconds freeze on OS X / NVidia. */
- int w = BLI_rcti_size_x(&ar->winrct);
- int h = BLI_rcti_size_y(&ar->winrct);
- char error[256];
-
- if (rv3d->gpuoffscreen) {
- if (GPU_offscreen_width(rv3d->gpuoffscreen) != w ||
- GPU_offscreen_height(rv3d->gpuoffscreen) != h)
- {
- GPU_offscreen_free(rv3d->gpuoffscreen);
- rv3d->gpuoffscreen = NULL;
- }
- }
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_set(rv3d);
+ }
+ /* get surface depth without bias */
+ rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
- if (!rv3d->gpuoffscreen) {
- rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error);
+ v3d->zbuf = true;
+ glEnable(GL_DEPTH_TEST);
- if (!rv3d->gpuoffscreen)
- fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
- }
+#ifdef WITH_OPENGL_LEGACY
+ if (IS_VIEWPORT_LEGACY(vc->v3d)) {
+ /* temp, calls into view3d_draw_legacy.c */
+ ED_view3d_draw_depth_loop(scene, ar, v3d);
}
-
- if (rv3d->gpuoffscreen)
- GPU_offscreen_bind(rv3d->gpuoffscreen, true);
else
- glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
-
- glClearColor(0.0, 0.0, 0.0, 0.0);
- if (v3d->zbuf) {
- glEnable(GL_DEPTH_TEST);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#endif /* WITH_OPENGL_LEGACY */
+ {
+ DRW_draw_depth_loop(graph, ar, v3d);
}
- else {
- glClear(GL_COLOR_BUFFER_BIT);
- glDisable(GL_DEPTH_TEST);
+
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_disable();
}
-
- if (rv3d->rflag & RV3D_CLIPPING)
- ED_view3d_clipping_set(rv3d);
-
- G.f |= G_BACKBUFSEL;
-
- if (base && (base->lay & v3d->lay))
- draw_object_backbufsel(scene, v3d, rv3d, base->object);
-
- if (rv3d->gpuoffscreen)
- GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
- else
- ar->swap = 0; /* mark invalid backbuf for wm draw */
+ rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
- v3d->flag &= ~V3D_INVALID_BACKBUF;
+ v3d->zbuf = zbuf;
+ if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
- G.f &= ~G_BACKBUFSEL;
- v3d->zbuf = false;
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_DITHER);
- if (multisample_enabled)
- glEnable(GL_MULTISAMPLE);
+ U.glalphaclip = glalphaclip;
+ v3d->flag = flag;
+ U.obcenter_dia = obcenter_dia;
- if (rv3d->rflag & RV3D_CLIPPING)
- ED_view3d_clipping_disable();
+ UI_Theme_Restore(&theme_state);
}
-void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
+/* ******************** background plates ***************** */
+
+static void view3d_draw_background_gradient(void)
{
- RegionView3D *rv3d = ar->regiondata;
+ /* TODO: finish 2D API & draw background with that */
- if (rv3d->gpuoffscreen) {
- GPU_offscreen_bind(rv3d->gpuoffscreen, true);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
- glReadPixels(x, y, w, h, format, type, data);
- GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
- }
- else {
- glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
- }
-}
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ unsigned char col_hi[3], col_lo[3];
-/* XXX depth reading exception, for code not using gpu offscreen */
-static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
-{
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
- glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
-}
+ UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
+ UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
-void ED_view3d_backbuf_validate(ViewContext *vc)
-{
- if (vc->v3d->flag & V3D_INVALID_BACKBUF)
- backdrawview3d(vc->scene, vc->win, vc->ar, vc->v3d);
+ immBegin(GWN_PRIM_TRI_FAN, 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();
}
-/**
- * allow for small values [0.5 - 2.5],
- * and large values, FLT_MAX by clamping by the area size
- */
-int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
+static void view3d_draw_background_none(void)
{
- return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
+ UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
}
-/* samples a single pixel (copied from vpaint) */
-unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y)
+static void view3d_draw_background_world(Scene *scene, RegionView3D *rv3d)
{
- unsigned int col;
-
- if (x >= vc->ar->winx || y >= vc->ar->winy) {
- return 0;
- }
+ if (scene->world) {
+ GPUMaterial *gpumat = GPU_material_world(scene, scene->world);
- ED_view3d_backbuf_validate(vc);
+ /* calculate full shader for background */
+ GPU_material_bind(gpumat, 1, 1, 1.0f, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac);
+
+ if (GPU_material_bound(gpumat)) {
+ /* TODO viewport (dfelinto): GPU_material_bind relies on immediate mode,
+ * we can't get rid of the following code without a bigger refactor
+ * or we dropping this functionality. */
+
+ glBegin(GL_TRIANGLE_STRIP);
+ glVertex2f(-1.0f, -1.0f);
+ glVertex2f(1.0f, -1.0f);
+ glVertex2f(-1.0f, 1.0f);
+ glVertex2f(1.0f, 1.0f);
+ glEnd();
- view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
- glReadBuffer(GL_BACK);
-
- if (ENDIAN_ORDER == B_ENDIAN) {
- BLI_endian_switch_uint32(&col);
+ GPU_material_unbind(gpumat);
+ return;
+ }
}
-
- return GPU_select_to_index(col);
+
+ /* if any of the above fails */
+ view3d_draw_background_none();
}
-/* reads full rect, converts indices */
-ImBuf *ED_view3d_backbuf_read(ViewContext *vc, int xmin, int ymin, int xmax, int ymax)
-{
- struct ImBuf *ibuf_clip;
- /* clip */
- const rcti clip = {
- max_ii(xmin, 0), min_ii(xmax, vc->ar->winx - 1),
- max_ii(ymin, 0), min_ii(ymax, vc->ar->winy - 1)};
- const int size_clip[2] = {
- BLI_rcti_size_x(&clip) + 1,
- BLI_rcti_size_y(&clip) + 1};
-
- if (UNLIKELY((clip.xmin > clip.xmax) ||
- (clip.ymin > clip.ymax)))
- {
- return NULL;
- }
+/* ******************** other elements ***************** */
- ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect);
- ED_view3d_backbuf_validate(vc);
+#define DEBUG_GRID 0
- view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect);
+static void gridline_range(double x0, double dx, double max, int *r_first, int *r_count)
+{
+ /* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y
+ * x0 is gridline 0, the axis in screen space
+ * Area covers [0 .. max) pixels */
- glReadBuffer(GL_BACK);
+ int first = (int)ceil(-x0 / dx);
+ int last = (int)floor((max - x0) / dx);
- if (ENDIAN_ORDER == B_ENDIAN) {
- IMB_convert_rgba_to_abgr(ibuf_clip);
- }
-
- GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]);
-
- if ((clip.xmin == xmin) &&
- (clip.xmax == xmax) &&
- (clip.ymin == ymin) &&
- (clip.ymax == ymax))
- {
- return ibuf_clip;
+ if (first <= last) {
+ *r_first = first;
+ *r_count = last - first + 1;
}
else {
- /* put clipped result into a non-clipped buffer */
- struct ImBuf *ibuf_full;
- const int size[2] = {
- (xmax - xmin + 1),
- (ymax - ymin + 1)};
-
- ibuf_full = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
-
- IMB_rectcpy(
- ibuf_full, ibuf_clip,
- clip.xmin - xmin, clip.ymin - ymin,
- 0, 0,
- size_clip[0], size_clip[1]);
- IMB_freeImBuf(ibuf_clip);
- return ibuf_full;
+ *r_first = 0;
+ *r_count = 0;
}
+
+#if DEBUG_GRID
+ printf(" first %d * dx = %f\n", first, x0 + first * dx);
+ printf(" last %d * dx = %f\n", last, x0 + last * dx);
+ printf(" count = %d\n", *count_out);
+#endif
}
-/* smart function to sample a rect spiralling outside, nice for backbuf selection */
-unsigned int ED_view3d_backbuf_sample_rect(
- ViewContext *vc, const int mval[2], int size,
- unsigned int min, unsigned int max, float *r_dist)
+static int gridline_count(ARegion *ar, double x0, double y0, double dx)
{
- struct ImBuf *buf;
- const unsigned int *bufmin, *bufmax, *tbuf;
- int minx, miny;
- int a, b, rc, nr, amount, dirvec[4][2];
- unsigned int index = 0;
+ /* x0 & y0 establish the "phase" of the grid within this 2D region
+ * dx is the frequency, shared by x & y directions
+ * pass in dx of smallest (highest precision) grid we want to draw */
- amount = (size - 1) / 2;
+#if DEBUG_GRID
+ printf(" %s(%f, %f, dx:%f)\n", __FUNCTION__, x0, y0, dx);
+#endif
- minx = mval[0] - (amount + 1);
- miny = mval[1] - (amount + 1);
- buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1);
- if (!buf) return 0;
+ int first, x_ct, y_ct;
- rc = 0;
-
- dirvec[0][0] = 1; dirvec[0][1] = 0;
- dirvec[1][0] = 0; dirvec[1][1] = -size;
- dirvec[2][0] = -1; dirvec[2][1] = 0;
- dirvec[3][0] = 0; dirvec[3][1] = size;
-
- bufmin = buf->rect;
- tbuf = buf->rect;
- bufmax = buf->rect + size * size;
- tbuf += amount * size + amount;
-
- for (nr = 1; nr <= size; nr++) {
-
- for (a = 0; a < 2; a++) {
- for (b = 0; b < nr; b++) {
- if (*tbuf && *tbuf >= min && *tbuf < max) {
- /* we got a hit */
-
- /* get x,y pixel coords from the offset
- * (manhatten distance in keeping with other screen-based selection) */
- *r_dist = (float)(
- abs(((int)(tbuf - buf->rect) % size) - (size / 2)) +
- abs(((int)(tbuf - buf->rect) / size) - (size / 2)));
-
- /* indices start at 1 here */
- index = (*tbuf - min) + 1;
- goto exit;
- }
-
- tbuf += (dirvec[rc][0] + dirvec[rc][1]);
-
- if (tbuf < bufmin || tbuf >= bufmax) {
- goto exit;
- }
- }
- rc++;
- rc &= 3;
- }
- }
+ gridline_range(x0, dx, ar->winx, &first, &x_ct);
+ gridline_range(y0, dx, ar->winy, &first, &y_ct);
-exit:
- IMB_freeImBuf(buf);
- return index;
-}
+ int total_ct = x_ct + y_ct;
+#if DEBUG_GRID
+ printf(" %d + %d = %d gridlines\n", x_ct, y_ct, total_ct);
+#endif
-/* ************************************************************* */
+ return total_ct;
+}
-static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
+static bool drawgrid_draw(ARegion *ar, double x0, double y0, double dx, int skip_mod, unsigned pos, unsigned col, GLubyte col_value[3])
{
- if (BKE_image_is_stereo(ima)) {
- iuser->flag |= IMA_SHOW_STEREO;
+ /* skip every skip_mod lines relative to each axis; they will be overlaid by another drawgrid_draw
+ * always skip exact x0 & y0 axes; they will be drawn later in color
+ *
+ * set grid color once, just before the first line is drawn
+ * it's harmless to set same color for every line, or every vertex
+ * but if no lines are drawn, color must not be set! */
- if ((scene->r.scemode & R_MULTIVIEW) == 0) {
- iuser->multiview_eye = STEREO_LEFT_ID;
- }
- else if (v3d->stereo3d_camera != STEREO_3D_ID) {
- /* show only left or right camera */
- iuser->multiview_eye = v3d->stereo3d_camera;
- }
+#if DEBUG_GRID
+ printf(" %s(%f, %f, dx:%f, skip_mod:%d)\n", __FUNCTION__, x0, y0, dx, skip_mod);
+#endif
- BKE_image_multiview_index(ima, iuser);
- }
- else {
- iuser->flag &= ~IMA_SHOW_STEREO;
- }
-}
+ const float x_max = (float)ar->winx;
+ const float y_max = (float)ar->winy;
-static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
- const bool do_foreground, const bool do_camera_frame)
-{
- RegionView3D *rv3d = ar->regiondata;
- BGpic *bgpic;
- int fg_flag = do_foreground ? V3D_BGPIC_FOREGROUND : 0;
+ int first, ct;
+ int x_ct = 0, y_ct = 0; /* count of lines actually drawn */
+ int lines_skipped_for_next_unit = 0;
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- bgpic->iuser.scene = scene; /* Needed for render results. */
+ /* draw vertical lines */
+ gridline_range(x0, dx, x_max, &first, &ct);
- if ((bgpic->flag & V3D_BGPIC_FOREGROUND) != fg_flag)
+ for (int i = first; i < first + ct; ++i) {
+ if (i == 0)
continue;
+ else if (skip_mod && (i % skip_mod) == 0) {
+ ++lines_skipped_for_next_unit;
+ continue;
+ }
- if ((bgpic->view == 0) || /* zero for any */
- (bgpic->view & (1 << rv3d->view)) || /* check agaist flags */
- (rv3d->persp == RV3D_CAMOB && bgpic->view == (1 << RV3D_VIEW_CAMERA)))
- {
- float image_aspect[2];
- float fac, asp, zoomx, zoomy;
- float x1, y1, x2, y2, centx, centy;
-
- ImBuf *ibuf = NULL, *freeibuf, *releaseibuf;
- void *lock;
- rctf clip_rect;
-
- Image *ima = NULL;
- MovieClip *clip = NULL;
-
- /* disable individual images */
- if ((bgpic->flag & V3D_BGPIC_DISABLED))
- continue;
-
- freeibuf = NULL;
- releaseibuf = NULL;
- if (bgpic->source == V3D_BGPIC_IMAGE) {
- ima = bgpic->ima;
- if (ima == NULL)
- continue;
- BKE_image_user_frame_calc(&bgpic->iuser, CFRA, 0);
- if (ima->source == IMA_SRC_SEQUENCE && !(bgpic->iuser.flag & IMA_USER_FRAME_IN_RANGE)) {
- ibuf = NULL; /* frame is out of range, dont show */
- }
- else {
- view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser);
- ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock);
- releaseibuf = ibuf;
- }
+ if (x_ct == 0)
+ immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
- image_aspect[0] = ima->aspx;
- image_aspect[1] = ima->aspy;
- }
- else if (bgpic->source == V3D_BGPIC_MOVIE) {
- /* TODO: skip drawing when out of frame range (as image sequences do above) */
+ float x = (float)(x0 + i * dx);
+ immVertex2f(pos, x, 0.0f);
+ immVertex2f(pos, x, y_max);
+ ++x_ct;
+ }
- if (bgpic->flag & V3D_BGPIC_CAMERACLIP) {
- if (scene->camera)
- clip = BKE_object_movieclip_get(scene, scene->camera, true);
- }
- else {
- clip = bgpic->clip;
- }
+ /* draw horizontal lines */
+ gridline_range(y0, dx, y_max, &first, &ct);
- if (clip == NULL)
- continue;
+ for (int i = first; i < first + ct; ++i) {
+ if (i == 0)
+ continue;
+ else if (skip_mod && (i % skip_mod) == 0) {
+ ++lines_skipped_for_next_unit;
+ continue;
+ }
- BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA);
- ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser);
+ if (x_ct + y_ct == 0)
+ immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
- image_aspect[0] = clip->aspx;
- image_aspect[1] = clip->aspy;
+ float y = (float)(y0 + i * dx);
+ immVertex2f(pos, 0.0f, y);
+ immVertex2f(pos, x_max, y);
+ ++y_ct;
+ }
- /* working with ibuf from image and clip has got different workflow now.
- * ibuf acquired from clip is referenced by cache system and should
- * be dereferenced after usage. */
- freeibuf = ibuf;
- }
- else {
- /* perhaps when loading future files... */
- BLI_assert(0);
- copy_v2_fl(image_aspect, 1.0f);
- }
+#if DEBUG_GRID
+ int total_ct = x_ct + y_ct;
+ printf(" %d + %d = %d gridlines drawn, %d skipped for next unit\n", x_ct, y_ct, total_ct, lines_skipped_for_next_unit);
+#endif
- if (ibuf == NULL)
- continue;
+ return lines_skipped_for_next_unit > 0;
+}
- if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */
- if (freeibuf)
- IMB_freeImBuf(freeibuf);
- if (releaseibuf)
- BKE_image_release_ibuf(ima, releaseibuf, lock);
+#define GRID_MIN_PX_D 6.0
+#define GRID_MIN_PX_F 6.0f
- continue;
- }
+static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
+{
+ RegionView3D *rv3d = ar->regiondata;
- if (ibuf->rect == NULL)
- IMB_rect_from_float(ibuf);
+#if DEBUG_GRID
+ printf("%s width %d, height %d\n", __FUNCTION__, ar->winx, ar->winy);
+#endif
- if (rv3d->persp == RV3D_CAMOB) {
+ double fx = rv3d->persmat[3][0];
+ double fy = rv3d->persmat[3][1];
+ double fw = rv3d->persmat[3][3];
- if (do_camera_frame) {
- rctf vb;
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
- x1 = vb.xmin;
- y1 = vb.ymin;
- x2 = vb.xmax;
- y2 = vb.ymax;
- }
- else {
- x1 = ar->winrct.xmin;
- y1 = ar->winrct.ymin;
- x2 = ar->winrct.xmax;
- y2 = ar->winrct.ymax;
- }
+ const double wx = 0.5 * ar->winx; /* use double precision to avoid rounding errors */
+ const double wy = 0.5 * ar->winy;
- /* apply offset last - camera offset is different to offset in blender units */
- /* so this has some sane way of working - this matches camera's shift _exactly_ */
- {
- const float max_dim = max_ff(x2 - x1, y2 - y1);
- const float xof_scale = bgpic->xof * max_dim;
- const float yof_scale = bgpic->yof * max_dim;
-
- x1 += xof_scale;
- y1 += yof_scale;
- x2 += xof_scale;
- y2 += yof_scale;
- }
+ double x = wx * fx / fw;
+ double y = wy * fy / fw;
- centx = (x1 + x2) / 2.0f;
- centy = (y1 + y2) / 2.0f;
+ double vec4[4] = { v3d->grid, v3d->grid, 0.0, 1.0 };
+ mul_m4_v4d(rv3d->persmat, vec4);
+ fx = vec4[0];
+ fy = vec4[1];
+ fw = vec4[3];
- /* aspect correction */
- if (bgpic->flag & V3D_BGPIC_CAMERA_ASPECT) {
- /* apply aspect from clip */
- const float w_src = ibuf->x * image_aspect[0];
- const float h_src = ibuf->y * image_aspect[1];
+ double dx = fabs(x - wx * fx / fw);
+ if (dx == 0) dx = fabs(y - wy * fy / fw);
- /* destination aspect is already applied from the camera frame */
- const float w_dst = x1 - x2;
- const float h_dst = y1 - y2;
+ x += wx;
+ y += wy;
- const float asp_src = w_src / h_src;
- const float asp_dst = w_dst / h_dst;
+ /* now x, y, and dx have their final values
+ * (x,y) is the world origin (0,0,0) mapped to Area-relative screen space
+ * dx is the distance in pixels between grid lines -- same for horiz or vert grid lines */
- if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) {
- if ((asp_src > asp_dst) == ((bgpic->flag & V3D_BGPIC_CAMERA_CROP) != 0)) {
- /* fit X */
- const float div = asp_src / asp_dst;
- x1 = ((x1 - centx) * div) + centx;
- x2 = ((x2 - centx) * div) + centx;
- }
- else {
- /* fit Y */
- const float div = asp_dst / asp_src;
- y1 = ((y1 - centy) * div) + centy;
- y2 = ((y2 - centy) * div) + centy;
- }
- }
- }
- }
- else {
- float tvec[3];
- float sco[2];
- const float mval_f[2] = {1.0f, 0.0f};
- const float co_zero[3] = {0};
- float zfac;
-
- /* calc window coord */
- zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL);
- ED_view3d_win_to_delta(ar, mval_f, tvec, zfac);
- fac = max_ff(fabsf(tvec[0]), max_ff(fabsf(tvec[1]), fabsf(tvec[2]))); /* largest abs axis */
- fac = 1.0f / fac;
-
- asp = (float)ibuf->y / (float)ibuf->x;
-
- zero_v3(tvec);
- ED_view3d_project_float_v2_m4(ar, tvec, sco, rv3d->persmat);
-
- x1 = sco[0] + fac * (bgpic->xof - bgpic->size);
- y1 = sco[1] + asp * fac * (bgpic->yof - bgpic->size);
- x2 = sco[0] + fac * (bgpic->xof + bgpic->size);
- y2 = sco[1] + asp * fac * (bgpic->yof + bgpic->size);
-
- centx = (x1 + x2) / 2.0f;
- centy = (y1 + y2) / 2.0f;
- }
+ glLineWidth(1.0f);
- /* complete clip? */
- BLI_rctf_init(&clip_rect, x1, x2, y1, y2);
- if (bgpic->rotation) {
- BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation);
- }
+#if 0 /* TODO: write to UI/widget depth buffer, not scene depth */
+ glDepthMask(GL_FALSE); /* disable write in zbuffer */
+#endif
- if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) {
- if (freeibuf)
- IMB_freeImBuf(freeibuf);
- if (releaseibuf)
- BKE_image_release_ibuf(ima, releaseibuf, lock);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- continue;
- }
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- zoomx = (x2 - x1) / ibuf->x;
- zoomy = (y2 - y1) / ibuf->y;
-
- /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
- if (zoomx < 1.0f || zoomy < 1.0f) {
- float tzoom = min_ff(zoomx, zoomy);
- int mip = 0;
+ unsigned char col[3], col2[3];
+ UI_GetThemeColor3ubv(TH_GRID, col);
- if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) {
- IMB_remakemipmap(ibuf, 0);
- ibuf->userflags &= ~IB_MIPMAP_INVALID;
- }
- else if (ibuf->mipmap[0] == NULL)
- IMB_makemipmap(ibuf, 0);
-
- while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) {
- tzoom *= 2.0f;
- zoomx *= 2.0f;
- zoomy *= 2.0f;
- mip++;
- }
- if (mip > 0)
- ibuf = ibuf->mipmap[mip - 1];
- }
+ if (unit->system) {
+ const void *usys;
+ int len;
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- glDepthMask(0);
+ bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ bool first = true;
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- ED_region_pixelspace(ar);
+ if (usys) {
+ int i = len;
+ while (i--) {
+ double scalar = bUnit_GetScaler(usys, i);
- glTranslatef(centx, centy, 0.0);
- glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f);
+ double dx_scalar = dx * scalar / (double)unit->scale_length;
+ if (dx_scalar < (GRID_MIN_PX_D * 2.0)) {
+ /* very very small grid items are less useful when dealing with units */
+ continue;
+ }
- if (bgpic->flag & V3D_BGPIC_FLIP_X) {
- zoomx *= -1.0f;
- x1 = x2;
- }
- if (bgpic->flag & V3D_BGPIC_FLIP_Y) {
- zoomy *= -1.0f;
- y1 = y2;
- }
- glPixelZoom(zoomx, zoomy);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend);
+ if (first) {
+ first = false;
- /* could not use glaDrawPixelsAuto because it could fallback to
- * glaDrawPixelsSafe in some cases, which will end up in missing
- * alpha transparency for the background image (sergey)
- */
- glaDrawPixelsTex(x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
+ /* Store the smallest drawn grid size units name so users know how big each grid cell is */
+ *grid_unit = bUnit_GetNameDisplay(usys, i);
+ rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length);
- glPixelZoom(1.0, 1.0);
- glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
+ int gridline_ct = gridline_count(ar, x, y, dx_scalar);
+ if (gridline_ct == 0)
+ goto drawgrid_cleanup; /* nothing to draw */
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ immBegin(GWN_PRIM_LINES, gridline_ct * 2);
+ }
- glDisable(GL_BLEND);
+ float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar);
+ /* tweak to have the fade a bit nicer */
+ blend_fac = (blend_fac * blend_fac) * 2.0f;
+ CLAMP(blend_fac, 0.3f, 1.0f);
- glDepthMask(1);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, blend_fac, col2);
- if (freeibuf)
- IMB_freeImBuf(freeibuf);
- if (releaseibuf)
- BKE_image_release_ibuf(ima, releaseibuf, lock);
+ const int skip_mod = (i == 0) ? 0 : (int)round(bUnit_GetScaler(usys, i - 1) / scalar);
+#if DEBUG_GRID
+ printf("%s %f, ", bUnit_GetNameDisplay(usys, i), scalar);
+ if (i > 0)
+ printf("next unit is %d times larger\n", skip_mod);
+ else
+ printf("largest unit\n");
+#endif
+ if (!drawgrid_draw(ar, x, y, dx_scalar, skip_mod, pos, color, col2))
+ break;
+ }
}
}
-}
+ else {
+ const double sublines = v3d->gridsubdiv;
+ const float sublines_fl = v3d->gridsubdiv;
-static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
- const bool do_foreground, const bool do_camera_frame)
-{
- RegionView3D *rv3d = ar->regiondata;
+ int grids_to_draw = 2; /* first the faint fine grid, then the bold coarse grid */
- if ((v3d->flag & V3D_DISPBGPICS) == 0)
- return;
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ grids_to_draw = (dx < GRID_MIN_PX_D) ? 0 : 1;
+ }
+ }
+ }
+ else {
+ if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
+ rv3d->gridview /= sublines_fl;
+ dx /= sublines;
+ if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
+ rv3d->gridview /= sublines_fl;
+ dx /= sublines;
+ if (dx > (GRID_MIN_PX_D * 10.0)) {
+ grids_to_draw = 1;
+ }
+ }
+ }
+ }
- /* disabled - mango request, since footage /w only render is quite useful
- * and this option is easy to disable all background images at once */
-#if 0
- if (v3d->flag2 & V3D_RENDER_OVERRIDE)
- return;
-#endif
+ int gridline_ct = gridline_count(ar, x, y, dx);
+ if (gridline_ct == 0)
+ goto drawgrid_cleanup; /* nothing to draw */
+
+ immBegin(GWN_PRIM_LINES, gridline_ct * 2);
- if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
- if (rv3d->persp == RV3D_CAMOB) {
- view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
+ if (grids_to_draw == 2) {
+ UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2);
+ if (drawgrid_draw(ar, x, y, dx, v3d->gridsubdiv, pos, color, col2))
+ drawgrid_draw(ar, x, y, dx * sublines, 0, pos, color, col);
+ }
+ else if (grids_to_draw == 1) {
+ drawgrid_draw(ar, x, y, dx, 0, pos, color, col);
}
}
- else {
- view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
+
+ /* draw visible axes */
+ /* horizontal line */
+ if (0 <= y && y < ar->winy) {
+ UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ? 'Y' : 'X');
+ immAttrib3ub(color, col2[0], col2[1], col2[2]);
+ immVertex2f(pos, 0.0f, y);
+ immVertex2f(pos, (float)ar->winx, y);
}
-}
-/* ****************** View3d afterdraw *************** */
+ /* vertical line */
+ if (0 <= x && x < ar->winx) {
+ UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ? 'Y' : 'Z');
+ immAttrib3ub(color, col2[0], col2[1], col2[2]);
+ immVertex2f(pos, x, 0.0f);
+ immVertex2f(pos, x, (float)ar->winy);
+ }
-typedef struct View3DAfter {
- struct View3DAfter *next, *prev;
- struct Base *base;
- short dflag;
-} View3DAfter;
+ immEnd();
-/* temp storage of Objects that need to be drawn as last */
-void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag)
-{
- View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after");
- BLI_assert((base->flag & OB_FROMDUPLI) == 0);
- BLI_addtail(lb, v3da);
- v3da->base = base;
- v3da->dflag = dflag;
-}
+drawgrid_cleanup:
+ immUnbindProgram();
-/* disables write in zbuffer and draws it over */
-static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
-{
- View3DAfter *v3da;
-
- glDepthMask(GL_FALSE);
- v3d->transp = true;
-
- while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
- draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
- MEM_freeN(v3da);
- }
- v3d->transp = false;
-
- glDepthMask(GL_TRUE);
-
+#if 0 /* depth write is left enabled above */
+ glDepthMask(GL_TRUE); /* enable write in zbuffer */
+#endif
}
-/* clears zbuffer and draws it over */
-static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear)
+#undef DEBUG_GRID
+#undef GRID_MIN_PX_D
+#undef GRID_MIN_PX_F
+
+static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
{
- View3DAfter *v3da;
+ /* draw only if there is something to draw */
+ if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
+ /* draw how many lines?
+ * trunc(v3d->gridlines / 2) * 4
+ * + 2 for xy axes (possibly with special colors)
+ * + 1 for z axis (the only line not in xy plane)
+ * even v3d->gridlines are honored, odd rounded down */
+ const int gridlines = v3d->gridlines / 2;
+ const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
+ const float grid = gridlines * grid_scale;
- if (*clear && v3d->zbuf) {
- glClear(GL_DEPTH_BUFFER_BIT);
- *clear = false;
- }
+ const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1;
- v3d->xray = true;
- while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
- draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
- MEM_freeN(v3da);
- }
- v3d->xray = false;
-}
+ bool show_axis_x = v3d->gridflag & V3D_SHOW_X;
+ bool show_axis_y = v3d->gridflag & V3D_SHOW_Y;
+ bool show_axis_z = v3d->gridflag & V3D_SHOW_Z;
+ unsigned char col_grid[3], col_axis[3];
-/* clears zbuffer and draws it over */
-static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const bool clear)
-{
- View3DAfter *v3da;
+ glLineWidth(1.0f);
- if (clear && v3d->zbuf)
- glClear(GL_DEPTH_BUFFER_BIT);
+ UI_GetThemeColor3ubv(TH_GRID, col_grid);
- v3d->xray = true;
- v3d->transp = true;
-
- glDepthMask(GL_FALSE);
+ if (!write_depth)
+ glDepthMask(GL_FALSE);
- while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
- draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
- MEM_freeN(v3da);
- }
+ if (show_floor) {
+ const unsigned vertex_ct = 2 * (gridlines * 4 + 2);
+ const int sublines = v3d->gridsubdiv;
- v3d->transp = false;
- v3d->xray = false;
+ unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3];
- glDepthMask(GL_TRUE);
-}
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
-/* clears zbuffer and draws it over,
- * note that in the select version we don't care about transparent flag as with regular drawing */
-static void view3d_draw_xray_select(Scene *scene, ARegion *ar, View3D *v3d, bool *clear)
-{
- /* Not ideal, but we need to read from the previous depths before clearing
- * otherwise we could have a function to load the depths after drawing.
- *
- * Clearing the depth buffer isn't all that common between drawing objects so accept this for now.
- */
- if (U.gpu_select_pick_deph) {
- GPU_select_load_id(-1);
- }
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
- View3DAfter *v3da;
- if (*clear && v3d->zbuf) {
- glClear(GL_DEPTH_BUFFER_BIT);
- *clear = false;
- }
+ immBegin(GWN_PRIM_LINES, vertex_ct);
- v3d->xray = true;
- while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
- if (GPU_select_load_id(v3da->base->selcol)) {
- draw_object_select(scene, ar, v3d, v3da->base, v3da->dflag);
- }
- MEM_freeN(v3da);
- }
- v3d->xray = false;
-}
+ /* draw normal grid lines */
+ UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
-/* *********************** */
+ for (int a = 1; a <= gridlines; a++) {
+ /* skip emphasised divider lines */
+ if (a % sublines != 0) {
+ const float line = a * grid_scale;
-/*
- * In most cases call draw_dupli_objects,
- * draw_dupli_objects_color was added because when drawing set dupli's
- * we need to force the color
- */
+ immAttrib3ubv(color, col_grid_light);
-#if 0
-int dupli_ob_sort(void *arg1, void *arg2)
-{
- void *p1 = ((DupliObject *)arg1)->ob;
- void *p2 = ((DupliObject *)arg2)->ob;
- int val = 0;
- if (p1 < p2) val = -1;
- else if (p1 > p2) val = 1;
- return val;
-}
-#endif
+ immVertex2f(pos, -grid, -line);
+ immVertex2f(pos, +grid, -line);
+ immVertex2f(pos, -grid, +line);
+ immVertex2f(pos, +grid, +line);
+ immVertex2f(pos, -line, -grid);
+ immVertex2f(pos, -line, +grid);
+ immVertex2f(pos, +line, -grid);
+ immVertex2f(pos, +line, +grid);
+ }
+ }
-static DupliObject *dupli_step(DupliObject *dob)
-{
- while (dob && dob->no_draw)
- dob = dob->next;
- return dob;
-}
+ /* draw emphasised grid lines */
+ UI_GetThemeColor3ubv(TH_BACK, col_bg);
+ /* emphasise division lines lighter instead of darker, if background is darker than grid */
+ UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
+ (col_grid[0] + col_grid[1] + col_grid[2] + 30 >
+ col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10);
-static void draw_dupli_objects_color(
- Scene *scene, ARegion *ar, View3D *v3d, Base *base,
- const short dflag, const int color)
-{
- RegionView3D *rv3d = ar->regiondata;
- ListBase *lb;
- LodLevel *savedlod;
- DupliObject *dob_prev = NULL, *dob, *dob_next = NULL;
- Base tbase = {NULL};
- BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */
- GLuint displist = 0;
- unsigned char color_rgb[3];
- const short dflag_dupli = dflag | DRAW_CONSTCOLOR;
- short transflag;
- bool use_displist = false; /* -1 is initialize */
- char dt;
- short dtx;
- DupliApplyData *apply_data;
-
- if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
- if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return;
-
- if (dflag & DRAW_CONSTCOLOR) {
- BLI_assert(color == TH_UNDEFINED);
- }
- else {
- UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb);
- }
+ if (sublines <= gridlines) {
+ immAttrib3ubv(color, col_grid_emphasise);
+
+ for (int a = sublines; a <= gridlines; a += sublines) {
+ const float line = a * grid_scale;
- tbase.flag = OB_FROMDUPLI | base->flag;
- lb = object_duplilist(G.main->eval_ctx, scene, base->object);
- // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */
+ immVertex2f(pos, -grid, -line);
+ immVertex2f(pos, +grid, -line);
+ immVertex2f(pos, -grid, +line);
+ immVertex2f(pos, +grid, +line);
- apply_data = duplilist_apply(base->object, scene, lb);
+ immVertex2f(pos, -line, -grid);
+ immVertex2f(pos, -line, +grid);
+ immVertex2f(pos, +line, -grid);
+ immVertex2f(pos, +line, +grid);
+ }
+ }
- dob = dupli_step(lb->first);
- if (dob) dob_next = dupli_step(dob->next);
+ /* draw X axis */
+ if (show_axis_x) {
+ show_axis_x = false; /* drawing now, won't need to draw later */
+ UI_make_axis_color(col_grid, col_axis, 'X');
+ immAttrib3ubv(color, col_axis);
+ }
+ else
+ immAttrib3ubv(color, col_grid_emphasise);
- for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) {
- bool testbb = false;
+ immVertex2f(pos, -grid, 0.0f);
+ immVertex2f(pos, +grid, 0.0f);
- tbase.object = dob->ob;
+ /* draw Y axis */
+ if (show_axis_y) {
+ show_axis_y = false; /* drawing now, won't need to draw later */
+ UI_make_axis_color(col_grid, col_axis, 'Y');
+ immAttrib3ubv(color, col_axis);
+ }
+ else
+ immAttrib3ubv(color, col_grid_emphasise);
- /* Make sure lod is updated from dupli's position */
- savedlod = dob->ob->currentlod;
+ immVertex2f(pos, 0.0f, -grid);
+ immVertex2f(pos, 0.0f, +grid);
-#ifdef WITH_GAMEENGINE
- if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
- BKE_object_lod_update(dob->ob, rv3d->viewinv[3]);
+ immEnd();
+ immUnbindProgram();
+
+ /* done with XY plane */
}
-#endif
- /* extra service: draw the duplicator in drawtype of parent, minimum taken
- * to allow e.g. boundbox box objects in groups for LOD */
- dt = tbase.object->dt;
- tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
+ if (show_axis_x || show_axis_y || show_axis_z) {
+ /* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */
- /* inherit draw extra, but not if a boundbox under the assumption that this
- * is intended to speed up drawing, and drawing extra (especially wire) can
- * slow it down too much */
- dtx = tbase.object->dtx;
- if (tbase.object->dt != OB_BOUNDBOX)
- tbase.object->dtx = base->object->dtx;
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- /* negative scale flag has to propagate */
- transflag = tbase.object->transflag;
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2);
- if (is_negative_m4(dob->mat))
- tbase.object->transflag |= OB_NEG_SCALE;
- else
- tbase.object->transflag &= ~OB_NEG_SCALE;
-
- /* should move outside the loop but possible color is set in draw_object still */
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(color_rgb);
- }
-
- /* generate displist, test for new object */
- if (dob_prev && dob_prev->ob != dob->ob) {
- if (use_displist == true)
- glDeleteLists(displist, 1);
-
- use_displist = false;
- }
-
- if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) {
- bb = *bb_tmp; /* must make a copy */
- testbb = true;
- }
+ if (show_axis_x) {
+ UI_make_axis_color(col_grid, col_axis, 'X');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, -grid, 0.0f, 0.0f);
+ immVertex3f(pos, +grid, 0.0f, 0.0f);
+ }
- if (!testbb || ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) {
- /* generate displist */
- if (use_displist == false) {
-
- /* note, since this was added, its checked (dob->type == OB_DUPLIGROUP)
- * however this is very slow, it was probably needed for the NLA
- * offset feature (used in group-duplicate.blend but no longer works in 2.5)
- * so for now it should be ok to - campbell */
-
- if ( /* if this is the last no need to make a displist */
- (dob_next == NULL || dob_next->ob != dob->ob) ||
- /* lamp drawing messes with matrices, could be handled smarter... but this works */
- (dob->ob->type == OB_LAMP) ||
- (dob->type == OB_DUPLIGROUP && dob->animated) ||
- !bb_tmp ||
- draw_glsl_material(scene, dob->ob, v3d, dt) ||
- check_object_draw_texture(scene, v3d, dt) ||
- (v3d->flag2 & V3D_SOLID_MATCAP) != 0)
- {
- // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2);
- use_displist = false;
- }
- else {
- // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2);
-
- /* disable boundbox check for list creation */
- BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1);
- /* need this for next part of code */
- unit_m4(dob->ob->obmat); /* obmat gets restored */
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
- draw_object(scene, ar, v3d, &tbase, dflag_dupli);
- glEndList();
-
- use_displist = true;
- BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0);
- }
+ if (show_axis_y) {
+ UI_make_axis_color(col_grid, col_axis, 'Y');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, 0.0f, -grid, 0.0f);
+ immVertex3f(pos, 0.0f, +grid, 0.0f);
}
-
- if (use_displist) {
- glPushMatrix();
- glMultMatrixf(dob->mat);
- glCallList(displist);
- glPopMatrix();
- }
- else {
- copy_m4_m4(dob->ob->obmat, dob->mat);
- GPU_begin_dupli_object(dob);
- draw_object(scene, ar, v3d, &tbase, dflag_dupli);
- GPU_end_dupli_object();
+
+ if (show_axis_z) {
+ UI_make_axis_color(col_grid, col_axis, 'Z');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, 0.0f, 0.0f, -grid);
+ immVertex3f(pos, 0.0f, 0.0f, +grid);
}
+
+ immEnd();
+ immUnbindProgram();
}
-
- tbase.object->dt = dt;
- tbase.object->dtx = dtx;
- tbase.object->transflag = transflag;
- tbase.object->currentlod = savedlod;
+
+ if (!write_depth)
+ glDepthMask(GL_TRUE);
}
+}
+
+/** could move this elsewhere, but tied into #ED_view3d_grid_scale */
+float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
+{
+ /* apply units */
+ if (scene->unit.system) {
+ const void *usys;
+ int len;
+
+ bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
- if (apply_data) {
- duplilist_restore(lb, apply_data);
- duplilist_free_apply_data(apply_data);
+ if (usys) {
+ int i = bUnit_GetBaseUnit(usys);
+ if (grid_unit)
+ *grid_unit = bUnit_GetNameDisplay(usys, i);
+ return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length;
+ }
}
- free_object_duplilist(lb);
-
- if (use_displist)
- glDeleteLists(displist, 1);
+ return 1.0f;
}
-static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base)
+float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
{
- /* define the color here so draw_dupli_objects_color can be called
- * from the set loop */
-
- int color = (base->flag & SELECT) ? TH_SELECT : TH_WIRE;
- /* debug */
- if (base->object->dup_group && base->object->dup_group->id.us < 1)
- color = TH_REDALERT;
-
- draw_dupli_objects_color(scene, ar, v3d, base, 0, color);
+ return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
}
-/* XXX warning, not using gpu offscreen here */
-void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
+static bool is_cursor_visible(Scene *scene, ViewLayer *view_layer)
{
- int x, y, w, h;
- rcti r;
- /* clamp rect by region */
+ Object *ob = OBACT(view_layer);
- r.xmin = 0;
- r.xmax = ar->winx - 1;
- r.ymin = 0;
- r.ymax = ar->winy - 1;
+ /* don't draw cursor in paint modes, but with a few exceptions */
+ if (ob && ob->mode & OB_MODE_ALL_PAINT) {
+ /* exception: object is in weight paint and has deforming armature in pose mode */
+ if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (BKE_object_pose_armature_get(ob) != NULL) {
+ return true;
+ }
+ }
+ /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
+ else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ const Paint *p = BKE_paint_get_active(scene, view_layer);
- /* Constrain rect to depth bounds */
- BLI_rcti_isect(&r, rect, rect);
+ if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
+ if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
+ return true;
+ }
+ }
+ }
- /* assign values to compare with the ViewDepths */
- x = rect->xmin;
- y = rect->ymin;
+ /* no exception met? then don't draw cursor! */
+ return false;
+ }
- w = BLI_rcti_size_x(rect);
- h = BLI_rcti_size_y(rect);
+ return true;
+}
- if (w <= 0 || h <= 0) {
- if (d->depths)
- MEM_freeN(d->depths);
- d->depths = NULL;
+static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
+{
+ int co[2];
- d->damaged = false;
- }
- else if (d->w != w ||
- d->h != h ||
- d->x != x ||
- d->y != y ||
- d->depths == NULL
- )
- {
- d->x = x;
- d->y = y;
- d->w = w;
- d->h = h;
+ /* we don't want the clipping for cursor */
+ if (ED_view3d_project_int_global(ar, ED_view3d_cursor3d_get(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ const float f5 = 0.25f * U.widget_unit;
+ const float f10 = 0.5f * U.widget_unit;
+ const float f20 = U.widget_unit;
+
+ glLineWidth(1.0f);
- if (d->depths)
- MEM_freeN(d->depths);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
- d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
-
- d->damaged = true;
- }
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- if (d->damaged) {
- /* XXX using special function here, it doesn't use the gpu offscreen system */
- view3d_opengl_read_Z_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
- glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
- d->damaged = false;
- }
-}
+ const int segments = 16;
-/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */
-void ED_view3d_depth_update(ARegion *ar)
-{
- RegionView3D *rv3d = ar->regiondata;
-
- /* Create storage for, and, if necessary, copy depth buffer */
- if (!rv3d->depths) rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
- if (rv3d->depths) {
- ViewDepths *d = rv3d->depths;
- if (d->w != ar->winx ||
- d->h != ar->winy ||
- !d->depths)
- {
- d->w = ar->winx;
- d->h = ar->winy;
- if (d->depths)
- MEM_freeN(d->depths);
- d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
- d->damaged = true;
- }
-
- if (d->damaged) {
- view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
- glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
-
- d->damaged = false;
- }
- }
-}
+ immBegin(GWN_PRIM_LINE_LOOP, segments);
-/* utility function to find the closest Z value, use for autodepth */
-float view3d_depth_near(ViewDepths *d)
-{
- /* convert to float for comparisons */
- const float near = (float)d->depth_range[0];
- const float far_real = (float)d->depth_range[1];
- float far = far_real;
-
- const float *depths = d->depths;
- float depth = FLT_MAX;
- int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */
-
- /* far is both the starting 'far' value
- * and the closest value found. */
- while (i--) {
- depth = *depths++;
- if ((depth < far) && (depth > near)) {
- far = depth;
+ for (int i = 0; i < segments; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)segments);
+ float x = co[0] + f10 * cosf(angle);
+ float y = co[1] + f10 * sinf(angle);
+
+ if (i % 2 == 0)
+ immAttrib3ub(color, 255, 0, 0);
+ else
+ immAttrib3ub(color, 255, 255, 255);
+
+ immVertex2f(pos, x, y);
}
- }
+ immEnd();
- return far == far_real ? FLT_MAX : far;
-}
+ immUnbindProgram();
-void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
-{
- short zbuf = v3d->zbuf;
- RegionView3D *rv3d = ar->regiondata;
+ GWN_vertformat_clear(format);
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- /* Setup view matrix. */
- ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glClear(GL_DEPTH_BUFFER_BIT);
+ unsigned char crosshair_color[3];
+ UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color);
+ immUniformColor3ubv(crosshair_color);
- v3d->zbuf = true;
- glEnable(GL_DEPTH_TEST);
+ immBegin(GWN_PRIM_LINES, 8);
+ immVertex2f(pos, co[0] - f20, co[1]);
+ immVertex2f(pos, co[0] - f5, co[1]);
+ immVertex2f(pos, co[0] + f5, co[1]);
+ immVertex2f(pos, co[0] + f20, co[1]);
+ immVertex2f(pos, co[0], co[1] - f20);
+ immVertex2f(pos, co[0], co[1] - f5);
+ immVertex2f(pos, co[0], co[1] + f5);
+ immVertex2f(pos, co[0], co[1] + f20);
+ immEnd();
- if (v3d->flag2 & V3D_SHOW_GPENCIL) {
- ED_gpencil_draw_view3d(NULL, scene, v3d, ar, true);
+ immUnbindProgram();
}
-
- v3d->zbuf = zbuf;
}
-static void view3d_draw_depth_loop(Scene *scene, ARegion *ar, View3D *v3d)
+static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
{
- Base *base;
-
- /* no need for color when drawing depth buffer */
- const short dflag_depth = DRAW_CONSTCOLOR;
-
- /* draw set first */
- if (scene->set) {
- Scene *sce_iter;
- for (SETLOOPER(scene->set, sce_iter, base)) {
- if (v3d->lay & base->lay) {
- draw_object(scene, ar, v3d, base, 0);
- if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED);
- }
- }
- }
- }
-
- for (base = scene->base.first; base; base = base->next) {
- if (v3d->lay & base->lay) {
- /* dupli drawing */
- if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED);
- }
- draw_object(scene, ar, v3d, base, dflag_depth);
- }
+ const float k = U.rvisize * U.pixelsize; /* axis size */
+ const int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */
+
+ const float startx = rect->xmin + k + 1.0f; /* axis center in screen coordinates, x=y */
+ const float starty = rect->ymin + k + 1.0f;
+
+ float axis_pos[3][2];
+ unsigned char axis_col[3][4];
+
+ int axis_order[3] = {0, 1, 2};
+ axis_sort_v3(rv3d->viewinv[2], axis_order);
+
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
+
+ /* get position of each axis tip on screen */
+ float vec[3] = { 0.0f };
+ vec[i] = 1.0f;
+ mul_qt_v3(rv3d->viewquat, vec);
+ axis_pos[i][0] = startx + vec[0] * k;
+ axis_pos[i][1] = starty + vec[1] * k;
+
+ /* get color of each axis */
+ UI_GetThemeColorShade3ubv(TH_AXIS_X + i, bright, axis_col[i]); /* rgb */
+ axis_col[i][3] = 255 * hypotf(vec[0], vec[1]); /* alpha */
}
-
- /* this isn't that nice, draw xray objects as if they are normal */
- if (v3d->afterdraw_transp.first ||
- v3d->afterdraw_xray.first ||
- v3d->afterdraw_xraytransp.first)
- {
- View3DAfter *v3da;
- int mask_orig;
- v3d->xray = true;
-
- /* transp materials can change the depth mask, see #21388 */
- glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
+ /* draw axis lines */
+ glLineWidth(2.0f);
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
- if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) {
- glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
- for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) {
- draw_object(scene, ar, v3d, v3da->base, dflag_depth);
- }
- glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
- }
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GWN_PRIM_LINES, 6);
- /* draw 3 passes, transp/xray/xraytransp */
- v3d->xray = false;
- v3d->transp = true;
- while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
- draw_object(scene, ar, v3d, v3da->base, dflag_depth);
- MEM_freeN(v3da);
- }
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
- v3d->xray = true;
- v3d->transp = false;
- while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
- draw_object(scene, ar, v3d, v3da->base, dflag_depth);
- MEM_freeN(v3da);
- }
+ immAttrib4ubv(col, axis_col[i]);
+ immVertex2f(pos, startx, starty);
+ immVertex2fv(pos, axis_pos[i]);
+ }
- v3d->xray = true;
- v3d->transp = true;
- while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
- draw_object(scene, ar, v3d, v3da->base, dflag_depth);
- MEM_freeN(v3da);
- }
+ immEnd();
+ immUnbindProgram();
+ glDisable(GL_LINE_SMOOTH);
-
- v3d->xray = false;
- v3d->transp = false;
+ /* draw axis names */
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
- glDepthMask(mask_orig);
+ const char axis_text[2] = {'x' + i, '\0'};
+ 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);
}
}
-void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride)
+#ifdef WITH_INPUT_NDOF
+/* draw center and axis of rotation for ongoing 3D mouse navigation */
+static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
{
- struct bThemeState theme_state;
- RegionView3D *rv3d = ar->regiondata;
- short zbuf = v3d->zbuf;
- short flag = v3d->flag;
- float glalphaclip = U.glalphaclip;
- int obcenter_dia = U.obcenter_dia;
- /* temp set drawtype to solid */
-
- /* Setting these temporarily is not nice */
- v3d->flag &= ~V3D_SELECT_OUTLINE;
- U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */
- U.obcenter_dia = 0;
-
- /* Tools may request depth outside of regular drawing code. */
- UI_Theme_Store(&theme_state);
- UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
+ float o[3]; /* center of rotation */
+ float end[3]; /* endpoints for drawing */
- /* Setup view matrix. */
- ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL);
-
- glClear(GL_DEPTH_BUFFER_BIT);
-
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_set(rv3d);
- }
- /* get surface depth without bias */
- rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
+ GLubyte color[4] = {0, 108, 255, 255}; /* bright blue so it matches device LEDs */
- v3d->zbuf = true;
- glEnable(GL_DEPTH_TEST);
+ negate_v3_v3(o, rv3d->ofs);
- view3d_draw_depth_loop(scene, ar, v3d);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDepthMask(GL_FALSE); /* don't overwrite zbuf */
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_disable();
- }
- rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
-
- v3d->zbuf = zbuf;
- if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
- U.glalphaclip = glalphaclip;
- v3d->flag = flag;
- U.obcenter_dia = obcenter_dia;
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
- UI_Theme_Restore(&theme_state);
-}
+ if (rv3d->rot_angle != 0.0f) {
+ /* -- draw rotation axis -- */
+ float scaled_axis[3];
+ const float scale = rv3d->dist;
+ mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale);
-void ED_view3d_draw_select_loop(
- ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar,
- bool use_obedit_skip, bool use_nearest)
-{
- short code = 1;
- const short dflag = DRAW_PICKING | DRAW_CONSTCOLOR;
- if (vc->obedit && vc->obedit->type == OB_MBALL) {
- draw_object(scene, ar, v3d, BASACT, dflag);
- }
- 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, dflag);
- }
- }
- else {
- Base *base;
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+ color[3] = 0; /* more transparent toward the ends */
+ immAttrib4ubv(col, color);
+ add_v3_v3v3(end, o, scaled_axis);
+ immVertex3fv(pos, end);
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & v3d->lay) {
+#if 0
+ color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */
+ /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */
+#endif
- if ((base->object->restrictflag & OB_RESTRICT_SELECT) ||
- (use_obedit_skip && (scene->obedit->data == base->object->data)))
- {
- base->selcol = 0;
- }
- else {
- base->selcol = code;
+ color[3] = 127; /* more opaque toward the center */
+ immAttrib4ubv(col, color);
+ immVertex3fv(pos, o);
- if (use_nearest && (base->object->dtx & OB_DRAWXRAY)) {
- ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag);
- }
- else {
- if (GPU_select_load_id(code)) {
- draw_object_select(scene, ar, v3d, base, dflag);
- }
- }
- code++;
- }
+ color[3] = 0;
+ immAttrib4ubv(col, color);
+ sub_v3_v3v3(end, o, scaled_axis);
+ immVertex3fv(pos, end);
+ immEnd();
+
+ /* -- draw ring around rotation center -- */
+ {
+#define ROT_AXIS_DETAIL 13
+
+ const float s = 0.05f * scale;
+ const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL);
+
+ float q[4]; /* rotate ring so it's perpendicular to axis */
+ const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f;
+ if (!upright) {
+ const float up[3] = {0.0f, 0.0f, 1.0f};
+ float vis_angle, vis_axis[3];
+
+ cross_v3_v3v3(vis_axis, up, rv3d->rot_axis);
+ vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis));
+ axis_angle_to_quat(q, vis_axis, vis_angle);
}
- }
- if (use_nearest) {
- bool xrayclear = true;
- if (v3d->afterdraw_xray.first) {
- view3d_draw_xray_select(scene, ar, v3d, &xrayclear);
+ immBegin(GWN_PRIM_LINE_LOOP, ROT_AXIS_DETAIL);
+ color[3] = 63; /* somewhat faint */
+ immAttrib4ubv(col, color);
+ float angle = 0.0f;
+ for (int i = 0; i < ROT_AXIS_DETAIL; ++i, angle += step) {
+ float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f};
+
+ if (!upright) {
+ mul_qt_v3(q, p);
+ }
+
+ add_v3_v3(p, o);
+ immVertex3fv(pos, p);
}
+ immEnd();
+
+#undef ROT_AXIS_DETAIL
}
+
+ color[3] = 255; /* solid dot */
}
-}
+ else
+ color[3] = 127; /* see-through dot */
-typedef struct View3DShadow {
- struct View3DShadow *next, *prev;
- GPULamp *lamp;
-} View3DShadow;
+ immUnbindProgram();
-static void gpu_render_lamp_update(Scene *scene, View3D *v3d,
- Object *ob, Object *par,
- float obmat[4][4], unsigned int lay,
- ListBase *shadows, SceneRenderLayer *srl)
-{
- GPULamp *lamp;
- Lamp *la = (Lamp *)ob->data;
- View3DShadow *shadow;
- unsigned int layers;
-
- lamp = GPU_lamp_from_blender(scene, ob, par);
-
- if (lamp) {
- GPU_lamp_update(lamp, lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat);
- GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy);
-
- layers = lay & v3d->lay;
- if (srl)
- layers &= srl->lay;
-
- if (layers &&
- GPU_lamp_has_shadow_buffer(lamp) &&
- /* keep last, may do string lookup */
- GPU_lamp_visible(lamp, srl, NULL))
- {
- shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow");
- shadow->lamp = lamp;
- BLI_addtail(shadows, shadow);
- }
- }
+ /* -- draw rotation center -- */
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
+ glPointSize(5.0f);
+ immBegin(GWN_PRIM_POINTS, 1);
+ immAttrib4ubv(col, color);
+ immVertex3fv(pos, o);
+ immEnd();
+ immUnbindProgram();
+
+#if 0
+ /* find screen coordinates for rotation center, then draw pretty icon */
+ mul_m4_v3(rv3d->persinv, rot_center);
+ UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN);
+ /* ^^ just playing around, does not work */
+#endif
+
+ glDisable(GL_BLEND);
+ glDepthMask(GL_TRUE);
}
+#endif /* WITH_INPUT_NDOF */
+
+/* ******************** info ***************** */
-static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d)
+/**
+* Render and camera border
+*/
+static void view3d_draw_border(const bContext *C, ARegion *ar)
{
- ListBase shadows;
- View3DShadow *shadow;
- Scene *sce_iter;
- Base *base;
- Object *ob;
- World *world = scene->world;
- SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL;
-
- BLI_listbase_clear(&shadows);
-
- /* update lamp transform and gather shadow lamps */
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
-
- if (ob->type == OB_LAMP)
- gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, ob->lay, &shadows, srl);
-
- if (ob->transflag & OB_DUPLI) {
- DupliObject *dob;
- ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
-
- for (dob = lb->first; dob; dob = dob->next)
- if (dob->ob->type == OB_LAMP)
- gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, ob->lay, &shadows, srl);
-
- free_object_duplilist(lb);
- }
- }
-
- /* render shadows after updating all lamps, nested object_duplilist
- * don't work correct since it's replacing object matrices */
- for (shadow = shadows.first; shadow; shadow = shadow->next) {
- /* this needs to be done better .. */
- float viewmat[4][4], winmat[4][4];
- int drawtype, lay, winsize, flag2 = v3d->flag2;
- ARegion ar = {NULL};
- RegionView3D rv3d = {{{0}}};
-
- drawtype = v3d->drawtype;
- lay = v3d->lay;
-
- v3d->drawtype = OB_SOLID;
- v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
- v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
- v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW;
-
- GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
-
- ar.regiondata = &rv3d;
- ar.regiontype = RGN_TYPE_WINDOW;
- rv3d.persp = RV3D_CAMOB;
- copy_m4_m4(rv3d.winmat, winmat);
- copy_m4_m4(rv3d.viewmat, viewmat);
- invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
- mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
- invert_m4_m4(rv3d.persinv, rv3d.viewinv);
-
- /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */
- ED_view3d_draw_offscreen(
- scene, v3d, &ar, winsize, winsize, viewmat, winmat,
- false, false, true,
- NULL, NULL, NULL, NULL);
- GPU_lamp_shadow_buffer_unbind(shadow->lamp);
-
- v3d->drawtype = drawtype;
- v3d->lay = lay;
- v3d->flag2 = flag2;
+ Scene *scene = CTX_data_scene(C);
+ RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = CTX_wm_view3d(C);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ drawviewborder(scene, ar, v3d);
}
-
- BLI_freelistN(&shadows);
-
- /* update world values */
- if (world) {
- GPU_mist_update_enable(world->mode & WO_MIST);
- GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr);
- GPU_horizon_update_color(&world->horr);
- GPU_ambient_update_color(&world->ambr);
- GPU_zenith_update_color(&world->zenr);
+ else if (v3d->flag2 & V3D_RENDER_BORDER) {
+ drawrenderborder(ar, v3d);
}
}
-/* *********************** customdata **************** */
+/**
+* Grease Pencil
+*/
+static void view3d_draw_grease_pencil(const bContext *UNUSED(C))
+{
+ /* TODO viewport */
+}
-CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d)
+/**
+* Viewport Name
+*/
+static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
{
- CustomDataMask mask = 0;
- const int drawtype = view3d_effective_drawtype(v3d);
+ const char *name = NULL;
- if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL) ||
- ((drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX)))
- {
- mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
+ switch (rv3d->view) {
+ case RV3D_VIEW_FRONT:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho");
+ else name = IFACE_("Front Persp");
+ break;
+ case RV3D_VIEW_BACK:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho");
+ else name = IFACE_("Back Persp");
+ break;
+ case RV3D_VIEW_TOP:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho");
+ else name = IFACE_("Top Persp");
+ break;
+ case RV3D_VIEW_BOTTOM:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho");
+ else name = IFACE_("Bottom Persp");
+ break;
+ case RV3D_VIEW_RIGHT:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho");
+ else name = IFACE_("Right Persp");
+ break;
+ case RV3D_VIEW_LEFT:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho");
+ else name = IFACE_("Left Persp");
+ break;
- if (BKE_scene_use_new_shading_nodes(scene)) {
- if (drawtype == OB_MATERIAL)
- mask |= CD_MASK_ORCO;
- }
- else {
- if ((scene->gm.matmode == GAME_MAT_GLSL && drawtype == OB_TEXTURE) ||
- (drawtype == OB_MATERIAL))
- {
- mask |= CD_MASK_ORCO;
+ default:
+ if (rv3d->persp == RV3D_CAMOB) {
+ if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
+ Camera *cam;
+ cam = v3d->camera->data;
+ if (cam->type == CAM_PERSP) {
+ name = IFACE_("Camera Persp");
+ }
+ else if (cam->type == CAM_ORTHO) {
+ name = IFACE_("Camera Ortho");
+ }
+ else {
+ BLI_assert(cam->type == CAM_PANO);
+ name = IFACE_("Camera Pano");
+ }
+ }
+ else {
+ name = IFACE_("Object as Camera");
+ }
+ }
+ else {
+ name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp");
}
- }
}
- return mask;
+ return name;
}
-/* goes over all modes and view3d settings */
-CustomDataMask ED_view3d_screen_datamask(const bScreen *screen)
+static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
{
- const Scene *scene = screen->scene;
- CustomDataMask mask = CD_MASK_BAREMESH;
- const ScrArea *sa;
-
- /* check if we need tfaces & mcols due to view mode */
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_VIEW3D) {
- mask |= ED_view3d_datamask(scene, sa->spacedata.first);
- }
+ RegionView3D *rv3d = ar->regiondata;
+ const char *name = view3d_get_name(v3d, rv3d);
+ /* increase size for unicode languages (Chinese in utf-8...) */
+#ifdef WITH_INTERNATIONAL
+ char tmpstr[96];
+#else
+ char tmpstr[32];
+#endif
+
+ if (v3d->localvd) {
+ BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
+ name = tmpstr;
}
- return mask;
+ 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
+ BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
+#endif
}
/**
- * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
+ * draw info beside axes in bottom left-corner:
+ * framenum, object name, bone name (if available), marker name (if available)
*/
-void ED_view3d_update_viewmat(
- Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect)
-{
- RegionView3D *rv3d = ar->regiondata;
- /* setup window matrices */
- if (winmat)
- copy_m4_m4(rv3d->winmat, winmat);
- else
- view3d_winmatrix_set(ar, v3d, rect);
+static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
+{
+ const int cfra = CFRA;
+ const char *msg_pin = " (Pinned)";
+ const char *msg_sep = " : ";
- /* setup view matrix */
- if (viewmat)
- copy_m4_m4(rv3d->viewmat, viewmat);
- else
- view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
+ const int font_id = BLF_default();
- /* update utility matrices */
- mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
- invert_m4_m4(rv3d->persinv, rv3d->persmat);
- invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
-
- /* calculate GLSL view dependent values */
+ char info[300];
+ char *s = info;
+ short offset = 1.5f * UI_UNIT_X + rect->xmin;
- /* store window coordinates scaling/offset */
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
- rctf cameraborder;
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false);
- rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
- rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
-
- rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx;
- rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy;
- }
- else {
- rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f;
- rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f;
- }
+ s += sprintf(s, "(%d)", cfra);
- /**
- * Calculate pixel-size factor once, is used for lamps and object centers.
- * Used by #ED_view3d_pixel_size and typically not accessed directly.
- *
- * \note #BKE_camera_params_compute_viewplane' also calculates a pixel-size value,
- * passed to #RE_SetPixelSize, in ortho mode this is compatible with this value,
- * but in perspective mode its offset by the near-clip.
- *
- * 'RegionView3D.pixsize' is used for viewport drawing, not rendering.
+ /*
+ * info can contain:
+ * - a frame (7 + 2)
+ * - 3 object names (MAX_NAME)
+ * - 2 BREAD_CRUMB_SEPARATORs (6)
+ * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room!
+ * - a marker name (MAX_NAME + 3)
*/
- {
- /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])'
- * because of float point precision problems at large values [#23908] */
- float v1[3], v2[3];
- float len_px, len_sc;
-
- v1[0] = rv3d->persmat[0][0];
- v1[1] = rv3d->persmat[1][0];
- v1[2] = rv3d->persmat[2][0];
-
- v2[0] = rv3d->persmat[0][1];
- v2[1] = rv3d->persmat[1][1];
- v2[2] = rv3d->persmat[2][1];
-
- len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
- len_sc = (float)MAX2(ar->winx, ar->winy);
- rv3d->pixsize = len_px / len_sc;
- }
-}
+ /* get name of marker on current frame (if available) */
+ const char *markern = BKE_scene_find_marker_name(scene, cfra);
-/**
- * Shared by #ED_view3d_draw_offscreen and #view3d_main_region_draw_objects
- *
- * \note \a C and \a grid_unit will be NULL when \a draw_offscreen is set.
- * \note Drawing lamps and opengl render uses this, so dont do grease pencil or view widgets here.
- */
-static void view3d_draw_objects(
- const bContext *C,
- Scene *scene, View3D *v3d, ARegion *ar,
- const char **grid_unit,
- const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
-{
- RegionView3D *rv3d = ar->regiondata;
- Base *base;
- const bool do_camera_frame = !draw_offscreen;
- const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0;
- const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
- /* only draw grids after in solid modes, else it hovers over mesh wires */
- const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx;
- bool do_composite_xray = false;
- bool xrayclear = true;
-
- if (!draw_offscreen) {
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
- }
+ /* check if there is an object */
+ if (ob) {
+ *s++ = ' ';
+ s += BLI_strcpy_rlen(s, ob->id.name + 2);
- if (rv3d->rflag & RV3D_CLIPPING)
- view3d_draw_clipping(rv3d);
+ /* name(s) to display depends on type of object */
+ if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
- /* set zbuffer after we draw clipping region */
- if (v3d->drawtype > OB_WIRE) {
- v3d->zbuf = true;
- }
- else {
- v3d->zbuf = false;
- }
+ /* show name of active bone too (if possible) */
+ if (arm->edbo) {
+ if (arm->act_edbone) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_edbone->name);
+ }
+ }
+ else if (ob->mode & OB_MODE_POSE) {
+ if (arm->act_bone) {
- /* special case (depth for wire color) */
- if (v3d->drawtype <= OB_WIRE) {
- if (scene->obedit && scene->obedit->type == OB_MESH) {
- Mesh *me = scene->obedit->data;
- if (me->drawflag & ME_DRAWEIGHT) {
- v3d->zbuf = true;
+ if (arm->act_bone->layer & arm->layer) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_bone->name);
+ }
+ }
}
}
- }
-
- if (v3d->zbuf) {
- glEnable(GL_DEPTH_TEST);
- }
+ else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
+ /* try to display active bone and active shapekey too (if they exist) */
- /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
- * objects if done last */
- if (draw_grids) {
- /* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */
- rv3d->gridview = ED_view3d_grid_scale(scene, v3d, grid_unit);
+ if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) {
+ Object *armobj = BKE_object_pose_armature_get(ob);
+ if (armobj && armobj->mode & OB_MODE_POSE) {
+ bArmature *arm = armobj->data;
+ if (arm->act_bone) {
+ if (arm->act_bone->layer & arm->layer) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_bone->name);
+ }
+ }
+ }
+ }
- if (!draw_floor) {
- ED_region_pixelspace(ar);
- *grid_unit = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
- drawgrid(&scene->unit, ar, v3d, grid_unit);
- /* XXX make function? replaces persp(1) */
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
- }
- else if (!draw_grids_after) {
- drawfloor(scene, v3d, grid_unit, true);
+ Key *key = BKE_key_from_object(ob);
+ if (key) {
+ KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1);
+ if (kb) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, kb->name);
+ if (ob->shapeflag & OB_SHAPE_LOCK) {
+ s += BLI_strcpy_rlen(s, IFACE_(msg_pin));
+ }
+ }
+ }
}
- }
- /* important to do before clipping */
- if (do_bgpic) {
- view3d_draw_bgpic_test(scene, ar, v3d, false, do_camera_frame);
+ /* 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_FontThemeColor(font_id, TH_TIME_KEYFRAME);
+ else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra))
+ UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
+ else
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
}
-
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_set(rv3d);
+ else {
+ /* no object */
+ if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra))
+ UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
+ else
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
}
- /* draw set first */
- if (scene->set) {
- const short dflag = DRAW_CONSTCOLOR | DRAW_SCENESET;
- Scene *sce_iter;
- for (SETLOOPER(scene->set, sce_iter, base)) {
- if (v3d->lay & base->lay) {
- UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
- draw_object(scene, ar, v3d, base, dflag);
-
- if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects_color(scene, ar, v3d, base, dflag, TH_UNDEFINED);
- }
- }
- }
-
- /* Transp and X-ray afterdraw stuff for sets is done later */
+ if (markern) {
+ s += sprintf(s, " <%s>", markern);
}
+ if (U.uiflag & USER_SHOW_ROTVIEWICON)
+ offset = U.widget_unit + (U.rvisize * 2) + rect->xmin;
- if (draw_offscreen) {
- for (base = scene->base.first; base; base = base->next) {
- if (v3d->lay & base->lay) {
- /* dupli drawing */
- if (base->object->transflag & OB_DUPLI)
- draw_dupli_objects(scene, ar, v3d, base);
+ BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info));
+}
- draw_object(scene, ar, v3d, base, 0);
- }
- }
- }
- else {
- unsigned int lay_used = 0;
+/* ******************** view loop ***************** */
- /* then draw not selected and the duplis, but skip editmode object */
- for (base = scene->base.first; base; base = base->next) {
- lay_used |= base->lay;
+/**
+* Information drawn on top of the solid plates and composed data
+*/
+void view3d_draw_region_info(const bContext *C, ARegion *ar, const int offset)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
- if (v3d->lay & base->lay) {
+ /* correct projection matrix */
+ ED_region_pixelspace(ar);
- /* dupli drawing */
- if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects(scene, ar, v3d, base);
- }
- if ((base->flag & SELECT) == 0) {
- if (base->object != scene->obedit)
- draw_object(scene, ar, v3d, base, 0);
- }
- }
- }
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ rcti rect;
+ ED_region_visible_rect(ar, &rect);
- /* mask out localview */
- v3d->lay_used = lay_used & ((1 << 20) - 1);
+ /* Leave room for previously drawn info. */
+ rect.ymax -= offset;
- /* 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);
- }
- }
- }
+ view3d_draw_border(C, ar);
+ view3d_draw_grease_pencil(C);
+
+ if (U.uiflag & USER_SHOW_ROTVIEWICON) {
+ draw_view_axis(rv3d, &rect);
}
- /* perspective floor goes last to use scene depth and avoid writing to depth buffer */
- if (draw_grids_after) {
- drawfloor(scene, v3d, grid_unit, false);
+ if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
+ ED_scene_draw_fps(scene, &rect);
+ }
+ else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
+ draw_viewport_name(ar, v3d, &rect);
}
- /* must be before xray draw which clears the depth buffer */
- if (v3d->flag2 & V3D_SHOW_GPENCIL) {
- wmWindowManager *wm = (C != NULL) ? CTX_wm_manager(C) : NULL;
-
- /* must be before xray draw which clears the depth buffer */
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- ED_gpencil_draw_view3d(wm, scene, v3d, ar, true);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ if (U.uiflag & USER_DRAWVIEWINFO) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ draw_selected_name(scene, ob, &rect);
}
+#if 0 /* TODO */
+ if (grid_unit) { /* draw below the viewport name */
+ char numstr[32] = "";
- /* transp and X-ray afterdraw stuff */
- if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d);
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+ if (v3d->grid != 1.0f) {
+ BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
+ }
- /* always do that here to cleanup depth buffers if none needed */
- if (fx) {
- do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first);
- GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray);
+ BLF_draw_default_ascii(rect.xmin + U.widget_unit,
+ rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
+ numstr[0] ? numstr : grid_unit, sizeof(numstr));
}
+#endif
+}
- if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, &xrayclear);
- if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, xrayclear);
+static void view3d_draw_view(const bContext *C, ARegion *ar)
+{
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
- if (fx && do_composite_xray) {
- GPU_fx_compositor_XRay_resolve(fx);
- }
+ ED_view3d_draw_setup_view(CTX_wm_window(C), &eval_ctx, CTX_data_scene(C), ar, CTX_wm_view3d(C), NULL, NULL, NULL);
- if (!draw_offscreen) {
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
- }
+ /* Only 100% compliant on new spec goes bellow */
+ DRW_draw_view(C);
+}
- if (rv3d->rflag & RV3D_CLIPPING)
- ED_view3d_clipping_disable();
+void view3d_main_region_draw(const bContext *C, ARegion *ar)
+{
+ Scene *scene = CTX_data_scene(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = ar->regiondata;
+ ViewRender *view_render = BKE_viewrender_get(scene, workspace);
+ RenderEngineType *type = RE_engines_find(view_render->engine_id);
- /* important to do after clipping */
- if (do_bgpic) {
- view3d_draw_bgpic_test(scene, ar, v3d, true, do_camera_frame);
+ /* Provisory Blender Internal drawing */
+ if (type->flag & RE_USE_LEGACY_PIPELINE) {
+ view3d_main_region_draw_legacy(C, ar);
+ return;
}
- if (!draw_offscreen) {
- BIF_draw_manipulator(C);
+ if (!rv3d->viewport) {
+ rv3d->viewport = GPU_viewport_create();
}
- /* cleanup */
- if (v3d->zbuf) {
- v3d->zbuf = false;
- glDisable(GL_DEPTH_TEST);
- }
+ GPU_viewport_bind(rv3d->viewport, &ar->winrct);
+ view3d_draw_view(C, ar);
+ GPU_viewport_unbind(rv3d->viewport);
- if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
- GPU_free_images_old();
- }
+ v3d->flag |= V3D_INVALID_BACKBUF;
}
-static void view3d_main_region_setup_view(
- Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect)
-{
- RegionView3D *rv3d = ar->regiondata;
- ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat, rect);
+/* -------------------------------------------------------------------- */
- /* set for opengl */
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
-}
+/** \name Offscreen Drawing
+ * \{ */
-/**
- * Store values from #RegionView3D, set when drawing.
- * This is needed when we draw with to a viewport using a different matrix (offscreen drawing for example).
- *
- * Values set by #ED_view3d_update_viewmat should be handled here.
- */
-struct RV3DMatrixStore {
- float winmat[4][4];
- float viewmat[4][4];
- float viewinv[4][4];
- float persmat[4][4];
- float persinv[4][4];
- float viewcamtexcofac[4];
- float pixsize;
-};
-
-struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
+static void view3d_stereo3d_setup_offscreen(
+ const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar,
+ float winmat[4][4], const char *viewname)
{
- struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__);
- copy_m4_m4(rv3dmat->winmat, rv3d->winmat);
- copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat);
- copy_m4_m4(rv3dmat->persmat, rv3d->persmat);
- copy_m4_m4(rv3dmat->persinv, rv3d->persinv);
- copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv);
- copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac);
- rv3dmat->pixsize = rv3d->pixsize;
- return (void *)rv3dmat;
-}
+ /* update the viewport matrices with the new camera */
+ if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
+ float viewmat[4][4];
+ const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
-void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat)
-{
- copy_m4_m4(rv3d->winmat, rv3dmat->winmat);
- copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat);
- copy_m4_m4(rv3d->persmat, rv3dmat->persmat);
- copy_m4_m4(rv3d->persinv, rv3dmat->persinv);
- copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv);
- copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac);
- rv3d->pixsize = rv3dmat->pixsize;
+ BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
+ view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL);
+ }
+ else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
+ float viewmat[4][4];
+ Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
+
+ BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
+ view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL);
+ }
}
-void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d)
+void ED_view3d_draw_offscreen_init(const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d)
{
- /* shadow buffers, before we setup matrices */
- if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
- gpu_update_lamps_shadows_world(scene, v3d);
+ RenderEngineType *engine_type = eval_ctx->engine_type;
+ if (engine_type->flag & RE_USE_LEGACY_PIPELINE) {
+ /* shadow buffers, before we setup matrices */
+ if (draw_glsl_material(scene, view_layer, NULL, v3d, v3d->drawtype)) {
+ VP_deprecated_gpu_update_lamps_shadows_world(eval_ctx, scene, v3d);
+ }
+ }
}
/*
@@ -3077,79 +1947,13 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d)
*/
static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
{
- if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) {
- RegionView3D *rv3d = ar->regiondata;
- GPUMaterial *gpumat = GPU_material_world(scene, scene->world);
-
- /* calculate full shader for background */
- GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
-
- bool material_not_bound = !GPU_material_bound(gpumat);
-
- if (material_not_bound) {
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
- }
-
- /* Draw world */
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_ALWAYS);
- glBegin(GL_TRIANGLE_STRIP);
- glVertex3f(-1.0, -1.0, 1.0);
- glVertex3f(1.0, -1.0, 1.0);
- glVertex3f(-1.0, 1.0, 1.0);
- glVertex3f(1.0, 1.0, 1.0);
- glEnd();
-
- if (material_not_bound) {
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
+ glClear(GL_DEPTH_BUFFER_BIT);
- GPU_material_unbind(gpumat);
-
- glDepthFunc(GL_LEQUAL);
- glDisable(GL_DEPTH_TEST);
+ if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) {
+ VP_view3d_draw_background_world(scene, ar->regiondata);
}
else {
- if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_ALWAYS);
- glBegin(GL_QUADS);
- UI_ThemeColor(TH_LOW_GRAD);
- glVertex3f(-1.0, -1.0, 1.0);
- glVertex3f(1.0, -1.0, 1.0);
- UI_ThemeColor(TH_HIGH_GRAD);
- glVertex3f(1.0, 1.0, 1.0);
- glVertex3f(-1.0, 1.0, 1.0);
- glEnd();
- glDepthFunc(GL_LEQUAL);
- glDisable(GL_DEPTH_TEST);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
-
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
- else {
- UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
+ VP_view3d_draw_background_none();
}
}
@@ -3157,24 +1961,20 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
* stuff like shadow buffers
*/
void ED_view3d_draw_offscreen(
- Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ View3D *v3d, ARegion *ar, int winx, int winy,
float viewmat[4][4], float winmat[4][4],
bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
GPUFX *fx, GPUFXSettings *fx_settings,
GPUOffScreen *ofs)
{
- struct bThemeState theme_state;
- int bwinx, bwiny;
- rcti brect;
bool do_compositing = false;
RegionView3D *rv3d = ar->regiondata;
- glPushMatrix();
-
/* set temporary new size */
- bwinx = ar->winx;
- bwiny = ar->winy;
- brect = ar->winrct;
+ int bwinx = ar->winx;
+ int bwiny = ar->winy;
+ rcti brect = ar->winrct;
ar->winx = winx;
ar->winy = winy;
@@ -3183,6 +1983,7 @@ void ED_view3d_draw_offscreen(
ar->winrct.xmax = winx;
ar->winrct.ymax = winy;
+ struct bThemeState theme_state;
UI_Theme_Store(&theme_state);
UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
@@ -3195,26 +1996,10 @@ void ED_view3d_draw_offscreen(
GPU_free_images_anim();
}
- /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */
- if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
- view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname);
- else
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL);
-
- /* framebuffer fx needed, we need to draw offscreen first */
- if (v3d->fx_settings.fx_flag && fx) {
- GPUSSAOSettings *ssao = NULL;
-
- if (v3d->drawtype < OB_SOLID) {
- ssao = v3d->fx_settings.ssao;
- v3d->fx_settings.ssao = NULL;
- }
-
- do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings);
-
- if (ssao)
- v3d->fx_settings.ssao = ssao;
- }
+ gpuPushProjectionMatrix();
+ gpuLoadIdentity();
+ gpuPushMatrix();
+ gpuLoadIdentity();
/* clear opengl buffers */
if (do_sky) {
@@ -3225,28 +2010,57 @@ void ED_view3d_draw_offscreen(
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
+ if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
+ view3d_stereo3d_setup_offscreen(eval_ctx, scene, v3d, ar, winmat, viewname);
+ else
+ view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL);
+
/* main drawing call */
- view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL);
+ RenderEngineType *engine_type = eval_ctx->engine_type;
+ if (engine_type->flag & RE_USE_LEGACY_PIPELINE) {
- /* post process */
- if (do_compositing) {
- if (!winmat)
- is_persp = rv3d->is_persp;
- GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
- }
+ /* framebuffer fx needed, we need to draw offscreen first */
+ if (v3d->fx_settings.fx_flag && fx) {
+ GPUSSAOSettings *ssao = NULL;
- if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
- /* draw grease-pencil stuff */
- ED_region_pixelspace(ar);
+ if (v3d->drawtype < OB_SOLID) {
+ ssao = v3d->fx_settings.ssao;
+ v3d->fx_settings.ssao = NULL;
+ }
+ do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings);
- if (v3d->flag2 & V3D_SHOW_GPENCIL) {
- /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
- ED_gpencil_draw_view3d(NULL, scene, v3d, ar, false);
+ if (ssao)
+ v3d->fx_settings.ssao = ssao;
}
- /* freeing the images again here could be done after the operator runs, leaving for now */
- GPU_free_images_anim();
+ VP_deprecated_view3d_draw_objects(NULL, eval_ctx, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL);
+
+ /* post process */
+ if (do_compositing) {
+ if (!winmat)
+ is_persp = rv3d->is_persp;
+ GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
+ }
+
+ if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
+ /* draw grease-pencil stuff */
+ ED_region_pixelspace(ar);
+
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
+ ED_gpencil_draw_view3d(NULL, scene, view_layer, v3d, ar, false);
+ }
+
+ /* freeing the images again here could be done after the operator runs, leaving for now */
+ GPU_free_images_anim();
+ }
+ }
+ else {
+ /* XXX, should take depsgraph as arg */
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
+ BLI_assert(depsgraph != NULL);
+ DRW_draw_render_loop_offscreen(depsgraph, eval_ctx->engine_type, ar, v3d, ofs);
}
/* restore size */
@@ -3254,7 +2068,8 @@ void ED_view3d_draw_offscreen(
ar->winy = bwiny;
ar->winrct = brect;
- glPopMatrix();
+ gpuPopProjectionMatrix();
+ gpuPopMatrix();
UI_Theme_Restore(&theme_state);
@@ -3262,37 +2077,20 @@ void ED_view3d_draw_offscreen(
}
/**
- * Set the correct matrices
- */
-void ED_view3d_draw_setup_view(
- wmWindow *win, Scene *scene, ARegion *ar, View3D *v3d, float viewmat[4][4], float winmat[4][4], const rcti *rect)
-{
- RegionView3D *rv3d = ar->regiondata;
-
- /* Setup the view matrix. */
- if (view3d_stereo3d_active(win, scene, v3d, rv3d)) {
- view3d_stereo3d_setup(scene, v3d, ar, rect);
- }
- else {
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, rect);
- }
-}
-
-/**
* Utility func for ED_view3d_draw_offscreen
*
* \param ofs: Optional off-screen buffer, can be NULL.
* (avoids re-creating when doing multiple GL renders).
*/
ImBuf *ED_view3d_draw_offscreen_imbuf(
- Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey,
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ View3D *v3d, ARegion *ar, int sizex, int sizey,
unsigned int flag, unsigned int draw_flags,
int alpha_mode, int samples, const char *viewname,
/* output vars */
GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
{
RegionView3D *rv3d = ar->regiondata;
- ImBuf *ibuf;
const bool draw_sky = (alpha_mode == R_ADDSKY);
const bool draw_background = (draw_flags & V3D_OFSDRAW_USE_BACKGROUND);
const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE);
@@ -3317,12 +2115,12 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
}
}
- ED_view3d_draw_offscreen_init(scene, v3d);
+ ED_view3d_draw_offscreen_init(eval_ctx, scene, view_layer, v3d);
GPU_offscreen_bind(ofs, true);
/* read in pixels & stamp */
- ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
+ ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
/* render 3d view */
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
@@ -3359,7 +2157,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
if ((samples && use_full_sample) == 0) {
/* Single-pass render, common case */
ED_view3d_draw_offscreen(
- scene, v3d, ar, sizex, sizey, NULL, winmat,
+ eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat,
draw_background, draw_sky, !is_ortho, viewname,
fx, &fx_settings, ofs);
@@ -3378,25 +2176,23 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
/* use imbuf as temp storage, before writing into it from accumulation buffer */
unsigned char *rect_temp = ibuf->rect ? (void *)ibuf->rect : (void *)ibuf->rect_float;
unsigned int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int[4]), "accum1");
- unsigned int i;
- int j;
BLI_jitter_init(jit_ofs, samples);
/* first sample buffer, also initializes 'rv3d->persmat' */
ED_view3d_draw_offscreen(
- scene, v3d, ar, sizex, sizey, NULL, winmat,
+ eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat,
draw_background, draw_sky, !is_ortho, viewname,
fx, &fx_settings, ofs);
GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
- i = sizex * sizey * 4;
+ unsigned i = sizex * sizey * 4;
while (i--) {
accum_buffer[i] = rect_temp[i];
}
/* skip the first sample */
- for (j = 1; j < samples; j++) {
+ for (int j = 1; j < samples; j++) {
copy_m4_m4(winmat_jitter, winmat);
window_translate_m4(
winmat_jitter, rv3d->persmat,
@@ -3404,7 +2200,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
(jit_ofs[j][1] * 2.0f) / sizey);
ED_view3d_draw_offscreen(
- scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
+ eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat_jitter,
draw_background, draw_sky, !is_ortho, viewname,
fx, &fx_settings, ofs);
GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
@@ -3455,7 +2251,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
* \note used by the sequencer
*/
ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
- Scene *scene, Object *camera, int width, int height,
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer,
+ Object *camera, int width, int height,
unsigned int flag, unsigned int draw_flags, int drawtype,
int alpha_mode, int samples, const char *viewname,
GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
@@ -3516,664 +2313,104 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
return ED_view3d_draw_offscreen_imbuf(
- scene, &v3d, &ar, width, height, flag, draw_flags,
- alpha_mode, samples, viewname, fx, ofs, err_out);
+ eval_ctx, scene, view_layer, &v3d, &ar, width, height, flag,
+ draw_flags, alpha_mode, samples, viewname, fx, ofs, err_out);
}
+/** \} */
-/**
- * \note The info that this uses is updated in #ED_refresh_viewport_fps,
- * which currently gets called during #SCREEN_OT_animation_step.
- */
-void ED_scene_draw_fps(Scene *scene, const rcti *rect)
-{
- ScreenFrameRateInfo *fpsi = scene->fps_info;
- float fps;
- char printable[16];
- int i, tot;
-
- if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime)
- return;
-
- printable[0] = '\0';
-
-#if 0
- /* this is too simple, better do an average */
- fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime))
-#else
- fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime));
-
- for (i = 0, tot = 0, fps = 0.0f; i < REDRAW_FRAME_AVERAGE; i++) {
- if (fpsi->redrawtimes_fps[i]) {
- fps += fpsi->redrawtimes_fps[i];
- tot++;
- }
- }
- if (tot) {
- fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
-
- //fpsi->redrawtime_index++;
- //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE)
- // fpsi->redrawtime = 0;
-
- fps = fps / tot;
- }
-#endif
-
- /* is this more than half a frame behind? */
- if (fps + 0.5f < (float)(FPS)) {
- UI_ThemeColor(TH_REDALERT);
- BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
- }
- else {
- UI_ThemeColor(TH_TEXT_HI);
- BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
- }
-
-#ifdef WITH_INTERNATIONAL
- BLF_draw_default(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
-#else
- BLF_draw_default_ascii(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
-#endif
-}
-static bool view3d_main_region_do_render_draw(Scene *scene)
-{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
+/* -------------------------------------------------------------------- */
- return (type && type->view_update && type->view_draw);
-}
+/** \name Legacy Interface
+ *
+ * This will be removed once the viewport gets replaced
+ * meanwhile it should keep the old viewport working.
+ *
+ * \{ */
-bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti *rect)
+void VP_legacy_drawcursor(Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d)
{
- RegionView3D *rv3d = ar->regiondata;
- rctf viewborder;
- bool use_border;
-
- /* test if there is a 3d view rendering */
- if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene))
- return false;
-
- /* test if there is a border render */
- if (rv3d->persp == RV3D_CAMOB)
- use_border = (scene->r.mode & R_BORDER) != 0;
- else
- use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
-
- if (!use_border)
- return false;
-
- /* compute border */
- if (rv3d->persp == RV3D_CAMOB) {
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
-
- rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
- rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
- rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
- rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
+ if (is_cursor_visible(scene, view_layer)) {
+ drawcursor(scene, ar, v3d);
}
- else {
- rect->xmin = v3d->render_border.xmin * ar->winx;
- rect->xmax = v3d->render_border.xmax * ar->winx;
- rect->ymin = v3d->render_border.ymin * ar->winy;
- rect->ymax = v3d->render_border.ymax * ar->winy;
- }
-
- BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin);
- BLI_rcti_isect(&ar->winrct, rect, rect);
-
- return true;
}
-static bool view3d_main_region_draw_engine(const bContext *C, Scene *scene,
- ARegion *ar, View3D *v3d,
- bool clip_border, const rcti *border_rect)
+void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect)
{
- RegionView3D *rv3d = ar->regiondata;
- RenderEngineType *type;
- GLint scissor[4];
-
- /* create render engine */
- if (!rv3d->render_engine) {
- RenderEngine *engine;
-
- type = RE_engines_find(scene->r.engine);
-
- if (!(type->view_update && type->view_draw))
- return false;
-
- engine = RE_engine_create_ex(type, true);
-
- engine->tile_x = scene->r.tilex;
- engine->tile_y = scene->r.tiley;
-
- type->view_update(engine, C);
-
- rv3d->render_engine = engine;
- }
-
- /* setup view matrices */
- view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL, NULL);
-
- /* background draw */
- ED_region_pixelspace(ar);
-
- if (clip_border) {
- /* for border draw, we only need to clear a subset of the 3d view */
- if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) {
- glGetIntegerv(GL_SCISSOR_BOX, scissor);
- glScissor(border_rect->xmin, border_rect->ymin,
- BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect));
- }
- else {
- return false;
- }
- }
-
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- if (v3d->flag & V3D_DISPBGPICS)
- view3d_draw_bgpic_test(scene, ar, v3d, false, true);
- else
- fdrawcheckerboard(0, 0, ar->winx, ar->winy);
-
- /* render result draw */
- type = rv3d->render_engine->type;
- type->view_draw(rv3d->render_engine, C);
-
- if (v3d->flag & V3D_DISPBGPICS)
- view3d_draw_bgpic_test(scene, ar, v3d, true, true);
-
- if (clip_border) {
- /* restore scissor as it was before */
- glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
- }
-
- return true;
+ draw_view_axis(rv3d, rect);
}
-static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border)
+void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
{
- float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
-
- if (!rv3d->render_engine || !rv3d->render_engine->text[0])
- return;
-
- if (render_border) {
- /* draw darkened background color. no alpha because border render does
- * partial redraw and will not redraw the region behind this info bar */
- float alpha = 1.0f - fill_color[3];
- Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
-
- if (camera) {
- if (camera->flag & CAM_SHOWPASSEPARTOUT) {
- alpha *= (1.0f - camera->passepartalpha);
- }
- }
-
- UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color);
- mul_v3_fl(fill_color, alpha);
- fill_color[3] = 1.0f;
- }
-
- ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true);
+ draw_viewport_name(ar, v3d, rect);
}
-static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d)
+void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect)
{
- if ((scene->r.scemode & R_MULTIVIEW) == 0) {
- return false;
- }
-
- if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) {
- return false;
- }
-
- switch (v3d->stereo3d_camera) {
- case STEREO_MONO_ID:
- return false;
- break;
- case STEREO_3D_ID:
- /* win will be NULL when calling this from the selection or draw loop. */
- if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) {
- return false;
- }
- if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) &&
- !BKE_scene_multiview_is_stereo3d(&scene->r))
- {
- return false;
- }
- break;
- /* We always need the stereo calculation for left and right cameras. */
- case STEREO_LEFT_ID:
- case STEREO_RIGHT_ID:
- default:
- break;
- }
- return true;
+ draw_selected_name(scene, ob, rect);
}
-/* setup the view and win matrices for the multiview cameras
- *
- * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called
- * we have no winmatrix (i.e., projection matrix) defined at that time.
- * Since the camera and the camera shift are needed for the winmat calculation
- * we do a small hack to replace it temporarily so we don't need to change the
- * view3d)main_region_setup_view() code to account for that.
- */
-static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect)
+void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
{
- bool is_left;
- const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
- const char *viewname;
-
- /* show only left or right camera */
- if (v3d->stereo3d_camera != STEREO_3D_ID)
- v3d->multiview_eye = v3d->stereo3d_camera;
-
- is_left = v3d->multiview_eye == STEREO_LEFT_ID;
- viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID];
-
- /* update the viewport matrices with the new camera */
- if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
- Camera *data;
- float viewmat[4][4];
- float shiftx;
-
- data = (Camera *)v3d->camera->data;
- shiftx = data->shiftx;
-
- BLI_lock_thread(LOCK_VIEW3D);
- data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
-
- BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect);
-
- data->shiftx = shiftx;
- BLI_unlock_thread(LOCK_VIEW3D);
- }
- else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
- float viewmat[4][4];
- Object *view_ob = v3d->camera;
- Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
-
- BLI_lock_thread(LOCK_VIEW3D);
- v3d->camera = camera;
-
- BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect);
-
- v3d->camera = view_ob;
- BLI_unlock_thread(LOCK_VIEW3D);
- }
+ drawgrid(unit, ar, v3d, grid_unit);
}
-static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
- float winmat[4][4], const char *viewname)
+void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
{
- /* update the viewport matrices with the new camera */
- if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
- float viewmat[4][4];
- const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
-
- BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL);
- }
- else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
- float viewmat[4][4];
- Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
-
- BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL);
- }
+ drawfloor(scene, v3d, grid_unit, write_depth);
}
-#ifdef WITH_GAMEENGINE
-static void update_lods(Scene *scene, float camera_pos[3])
+void VP_legacy_view3d_main_region_setup_view(
+ const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d,
+ ARegion *ar, float viewmat[4][4], float winmat[4][4])
{
- Scene *sce_iter;
- Base *base;
- Object *ob;
-
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
- BKE_object_lod_update(ob, camera_pos);
- }
+ view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL);
}
-#endif
-static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
- ARegion *ar, const char **grid_unit)
+bool VP_legacy_view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d)
{
- wmWindow *win = CTX_wm_window(C);
- RegionView3D *rv3d = ar->regiondata;
- unsigned int lay_used = v3d->lay_used;
-
- /* post processing */
- bool do_compositing = false;
-
- /* shadow buffers, before we setup matrices */
- if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
- gpu_update_lamps_shadows_world(scene, v3d);
-
- /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */
- if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) {
- rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE;
- GPU_default_lights();
- }
-
- /* Setup the view matrix. */
- ED_view3d_draw_setup_view(CTX_wm_window(C), scene, ar, v3d, NULL, NULL, NULL);
-
- rv3d->rflag &= ~RV3D_IS_GAME_ENGINE;
-#ifdef WITH_GAMEENGINE
- if (STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)) {
- rv3d->rflag |= RV3D_IS_GAME_ENGINE;
-
- /* Make sure LoDs are up to date */
- update_lods(scene, rv3d->viewinv[3]);
- }
-#endif
-
- /* framebuffer fx needed, we need to draw offscreen first */
- if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) {
- GPUFXSettings fx_settings;
- BKE_screen_gpu_fx_validate(&v3d->fx_settings);
- fx_settings = v3d->fx_settings;
- if (!rv3d->compositor)
- rv3d->compositor = GPU_fx_compositor_create();
-
- if (rv3d->persp == RV3D_CAMOB && v3d->camera)
- BKE_camera_to_gpu_dof(v3d->camera, &fx_settings);
- else {
- fx_settings.dof = NULL;
- }
-
- do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings);
- }
-
- /* clear the background */
- view3d_main_region_clear(scene, v3d, ar);
-
- /* enables anti-aliasing for 3D view drawing */
- if (win->multisamples != USER_MULTISAMPLE_NONE) {
- glEnable(GL_MULTISAMPLE);
- }
-
- /* main drawing call */
- view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL);
-
- /* post process */
- if (do_compositing) {
- GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
- }
-
- /* Disable back anti-aliasing */
- if (win->multisamples != USER_MULTISAMPLE_NONE) {
- glDisable(GL_MULTISAMPLE);
- }
-
- if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */
- /* find header and force tag redraw */
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- ED_region_tag_redraw(ar_header); /* can be NULL */
- }
-
- if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
- BDR_drawSketch(C);
- }
-
-#ifdef WITH_INPUT_NDOF
- if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) && (rv3d->persp != RV3D_CAMOB))
- /* TODO: draw something else (but not this) during fly mode */
- draw_rotation_guide(rv3d);
-#endif
+ return view3d_stereo3d_active(win, scene, v3d, rv3d);
}
-static bool is_cursor_visible(Scene *scene)
+void VP_legacy_view3d_stereo3d_setup(const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar)
{
- Object *ob = OBACT;
-
- /* don't draw cursor in paint modes, but with a few exceptions */
- if (ob && ob->mode & OB_MODE_ALL_PAINT) {
- /* exception: object is in weight paint and has deforming armature in pose mode */
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- if (BKE_object_pose_armature_get(ob) != NULL) {
- return true;
- }
- }
- /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
- else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- const Paint *p = BKE_paint_get_active(scene);
-
- if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
- if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
- return true;
- }
- }
- }
-
- /* no exception met? then don't draw cursor! */
- return false;
- }
-
- return true;
+ view3d_stereo3d_setup(eval_ctx, scene, v3d, ar, NULL);
}
-static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
- ARegion *ar, View3D *v3d,
- const char *grid_unit, bool render_border)
+bool VP_legacy_use_depth(Scene *scene, View3D *v3d)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- RegionView3D *rv3d = ar->regiondata;
- rcti rect;
-
- /* local coordinate visible rect inside region, to accomodate overlapping ui */
- ED_region_visible_rect(ar, &rect);
-
- if (rv3d->persp == RV3D_CAMOB) {
- drawviewborder(scene, ar, v3d);
- }
- else if (v3d->flag2 & V3D_RENDER_BORDER) {
- glLineWidth(1.0f);
- setlinestyle(3);
- cpack(0x4040FF);
-
- sdrawbox(v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy,
- v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy);
-
- setlinestyle(0);
- }
-
- if (v3d->flag2 & V3D_SHOW_GPENCIL) {
- /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
- ED_gpencil_draw_view3d(wm, scene, v3d, ar, false);
- }
-
- if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
- Object *ob;
-
- /* 3d cursor */
- if (is_cursor_visible(scene)) {
- drawcursor(scene, ar, v3d);
- }
-
- if (U.uiflag & USER_SHOW_ROTVIEWICON)
- draw_view_axis(rv3d, &rect);
- else
- draw_view_icon(rv3d, &rect);
-
- ob = OBACT;
- if (U.uiflag & USER_DRAWVIEWINFO)
- draw_selected_name(scene, ob, &rect);
- }
-
- if (rv3d->render_engine) {
- view3d_main_region_draw_engine_info(v3d, rv3d, ar, render_border);
- return;
- }
-
- if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
- if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
- ED_scene_draw_fps(scene, &rect);
- }
- else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
- draw_viewport_name(ar, v3d, &rect);
- }
-
- if (grid_unit) { /* draw below the viewport name */
- char numstr[32] = "";
-
- UI_ThemeColor(TH_TEXT_HI);
- if (v3d->grid != 1.0f) {
- BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
- }
-
- BLF_draw_default_ascii(rect.xmin + U.widget_unit,
- rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
- numstr[0] ? numstr : grid_unit, sizeof(numstr));
- }
- }
+ return use_depth_doit(scene, v3d);
}
-void view3d_main_region_draw(const bContext *C, ARegion *ar)
+void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- const char *grid_unit = NULL;
- rcti border_rect;
- bool render_border, clip_border;
-
- /* if we only redraw render border area, skip opengl draw and also
- * don't do scissor because it's already set */
- render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect);
- clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect));
-
- /* draw viewport using opengl */
- if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene) || clip_border) {
- view3d_main_region_draw_objects(C, scene, v3d, ar, &grid_unit);
-
-#ifdef DEBUG_DRAW
- bl_debug_draw();
-#endif
- if (G.debug & G_DEBUG_SIMDATA)
- draw_sim_debug_data(scene, v3d, ar);
-
- ED_region_pixelspace(ar);
- }
-
- /* draw viewport using external renderer */
- if (v3d->drawtype == OB_RENDER)
- view3d_main_region_draw_engine(C, scene, ar, v3d, clip_border, &border_rect);
-
- view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border);
-
- v3d->flag |= V3D_INVALID_BACKBUF;
-
- BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_transp));
- BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xray));
- BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xraytransp));
+ drawviewborder(scene, ar, v3d);
}
-#ifdef DEBUG_DRAW
-/* debug drawing */
-#define _DEBUG_DRAW_QUAD_TOT 1024
-#define _DEBUG_DRAW_EDGE_TOT 1024
-static float _bl_debug_draw_quads[_DEBUG_DRAW_QUAD_TOT][4][3];
-static int _bl_debug_draw_quads_tot = 0;
-static float _bl_debug_draw_edges[_DEBUG_DRAW_QUAD_TOT][2][3];
-static int _bl_debug_draw_edges_tot = 0;
-static unsigned int _bl_debug_draw_quads_color[_DEBUG_DRAW_QUAD_TOT];
-static unsigned int _bl_debug_draw_edges_color[_DEBUG_DRAW_EDGE_TOT];
-static unsigned int _bl_debug_draw_color;
-
-void bl_debug_draw_quad_clear(void)
-{
- _bl_debug_draw_quads_tot = 0;
- _bl_debug_draw_edges_tot = 0;
- _bl_debug_draw_color = 0x00FF0000;
-}
-void bl_debug_color_set(const unsigned int color)
+void VP_drawrenderborder(ARegion *ar, View3D *v3d)
{
- _bl_debug_draw_color = color;
+ drawrenderborder(ar, v3d);
}
-void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3])
+
+void VP_view3d_draw_background_none(void)
{
- if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_QUAD_TOT) {
- printf("%s: max quad count hit %d!", __func__, _bl_debug_draw_quads_tot);
+ if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+ view3d_draw_background_gradient();
}
else {
- float *pt = &_bl_debug_draw_quads[_bl_debug_draw_quads_tot][0][0];
- copy_v3_v3(pt, v0); pt += 3;
- copy_v3_v3(pt, v1); pt += 3;
- copy_v3_v3(pt, v2); pt += 3;
- copy_v3_v3(pt, v3); pt += 3;
- _bl_debug_draw_quads_color[_bl_debug_draw_quads_tot] = _bl_debug_draw_color;
- _bl_debug_draw_quads_tot++;
+ view3d_draw_background_none();
}
}
-void bl_debug_draw_edge_add(const float v0[3], const float v1[3])
+
+void VP_view3d_draw_background_world(Scene *scene, RegionView3D *rv3d)
{
- if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_EDGE_TOT) {
- printf("%s: max edge count hit %d!", __func__, _bl_debug_draw_edges_tot);
- }
- else {
- float *pt = &_bl_debug_draw_edges[_bl_debug_draw_edges_tot][0][0];
- copy_v3_v3(pt, v0); pt += 3;
- copy_v3_v3(pt, v1); pt += 3;
- _bl_debug_draw_edges_color[_bl_debug_draw_edges_tot] = _bl_debug_draw_color;
- _bl_debug_draw_edges_tot++;
- }
+ view3d_draw_background_world(scene, rv3d);
}
-static void bl_debug_draw(void)
+
+void VP_view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
{
- unsigned int color;
- if (_bl_debug_draw_quads_tot) {
- int i;
- color = _bl_debug_draw_quads_color[0];
- cpack(color);
- for (i = 0; i < _bl_debug_draw_quads_tot; i ++) {
- if (_bl_debug_draw_quads_color[i] != color) {
- color = _bl_debug_draw_quads_color[i];
- cpack(color);
- }
- glBegin(GL_LINE_LOOP);
- glVertex3fv(_bl_debug_draw_quads[i][0]);
- glVertex3fv(_bl_debug_draw_quads[i][1]);
- glVertex3fv(_bl_debug_draw_quads[i][2]);
- glVertex3fv(_bl_debug_draw_quads[i][3]);
- glEnd();
- }
- }
- if (_bl_debug_draw_edges_tot) {
- int i;
- color = _bl_debug_draw_edges_color[0];
- cpack(color);
- glBegin(GL_LINES);
- for (i = 0; i < _bl_debug_draw_edges_tot; i ++) {
- if (_bl_debug_draw_edges_color[i] != color) {
- color = _bl_debug_draw_edges_color[i];
- cpack(color);
- }
- glVertex3fv(_bl_debug_draw_edges[i][0]);
- glVertex3fv(_bl_debug_draw_edges[i][1]);
- }
- glEnd();
- color = _bl_debug_draw_edges_color[0];
- cpack(color);
- glPointSize(4.0);
- glBegin(GL_POINTS);
- for (i = 0; i < _bl_debug_draw_edges_tot; i ++) {
- if (_bl_debug_draw_edges_color[i] != color) {
- color = _bl_debug_draw_edges_color[i];
- cpack(color);
- }
- glVertex3fv(_bl_debug_draw_edges[i][0]);
- glVertex3fv(_bl_debug_draw_edges[i][1]);
- }
- glEnd();
- }
+ view3d_main_region_clear(scene, v3d, ar);
}
-#endif
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
new file mode 100644
index 00000000000..84f0f96fe0b
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -0,0 +1,2186 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/view3d_draw_legacy.c
+ * \ingroup spview3d
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_group_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_world_types.h"
+#include "DNA_brush_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_jitter.h"
+#include "BLI_utildefines.h"
+#include "BLI_endian_switch.h"
+#include "BLI_threads.h"
+
+#include "BKE_anim.h"
+#include "BKE_camera.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_image.h"
+#include "BKE_key.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_paint.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_unit.h"
+#include "BKE_movieclip.h"
+
+#include "DEG_depsgraph.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
+
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BLF_api.h"
+#include "BLT_translation.h"
+
+#include "ED_armature.h"
+#include "ED_keyframing.h"
+#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_screen_types.h"
+#include "ED_transform.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+
+#include "GPU_draw.h"
+#include "GPU_framebuffer.h"
+#include "GPU_lamp.h"
+#include "GPU_material.h"
+#include "GPU_compositing.h"
+#include "GPU_extensions.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_select.h"
+#include "GPU_matrix.h"
+
+#include "RE_engine.h"
+
+#include "DRW_engine.h"
+
+#include "view3d_intern.h" /* own include */
+
+/* ********* custom clipping *********** */
+
+static void view3d_draw_clipping(RegionView3D *rv3d)
+{
+ BoundBox *bb = rv3d->clipbb;
+
+ if (bb) {
+ const unsigned int clipping_index[6][4] = {
+ {0, 1, 2, 3},
+ {0, 4, 5, 1},
+ {4, 7, 6, 5},
+ {7, 3, 2, 6},
+ {1, 5, 6, 2},
+ {7, 4, 0, 3}
+ };
+
+ /* fill in zero alpha for rendering & re-projection [#31530] */
+ unsigned char col[4];
+ UI_GetThemeColor4ubv(TH_V3D_CLIPPING_BORDER, col);
+ glColor4ubv(col);
+
+ glEnable(GL_BLEND);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, bb->vec);
+ glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisable(GL_BLEND);
+ }
+}
+
+void ED_view3d_clipping_set(RegionView3D *rv3d)
+{
+ double plane[4];
+ const unsigned int tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
+
+ for (unsigned a = 0; a < tot; a++) {
+ copy_v4db_v4fl(plane, rv3d->clip[a]);
+ glClipPlane(GL_CLIP_PLANE0 + a, plane);
+ glEnable(GL_CLIP_PLANE0 + a);
+ }
+}
+
+/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */
+void ED_view3d_clipping_disable(void)
+{
+ for (unsigned a = 0; a < 6; a++) {
+ glDisable(GL_CLIP_PLANE0 + a);
+ }
+}
+void ED_view3d_clipping_enable(void)
+{
+ for (unsigned a = 0; a < 6; a++) {
+ glEnable(GL_CLIP_PLANE0 + a);
+ }
+}
+
+static bool view3d_clipping_test(const float co[3], const float clip[6][4])
+{
+ if (plane_point_side_v3(clip[0], co) > 0.0f)
+ if (plane_point_side_v3(clip[1], co) > 0.0f)
+ if (plane_point_side_v3(clip[2], co) > 0.0f)
+ if (plane_point_side_v3(clip[3], co) > 0.0f)
+ return false;
+
+ return true;
+}
+
+/* for 'local' ED_view3d_clipping_local must run first
+ * then all comparisons can be done in localspace */
+bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local)
+{
+ return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
+}
+
+/* ********* end custom clipping *********** */
+
+static void draw_view_icon(RegionView3D *rv3d, rcti *rect)
+{
+ BIFIconID icon;
+
+ if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM))
+ icon = ICON_AXIS_TOP;
+ else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK))
+ icon = ICON_AXIS_FRONT;
+ else if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT))
+ icon = ICON_AXIS_SIDE;
+ else return;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ UI_icon_draw(5.0 + rect->xmin, 5.0 + rect->ymin, icon);
+
+ glDisable(GL_BLEND);
+}
+
+/* *********************** backdraw for selection *************** */
+
+static void backdrawview3d(const struct EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, wmWindow *win, ARegion *ar, View3D *v3d)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ struct Base *base = view_layer->basact;
+ int multisample_enabled;
+
+ BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
+
+ if (base && (base->object->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
+ BKE_paint_select_face_test(base->object)))
+ {
+ /* do nothing */
+ }
+ /* texture paint mode sampling */
+ else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) &&
+ (v3d->drawtype > OB_WIRE))
+ {
+ /* do nothing */
+ }
+ else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
+ V3D_IS_ZBUF(v3d))
+ {
+ /* do nothing */
+ }
+ else if (scene->obedit &&
+ V3D_IS_ZBUF(v3d))
+ {
+ /* do nothing */
+ }
+ else {
+ v3d->flag &= ~V3D_INVALID_BACKBUF;
+ return;
+ }
+
+ if (!(v3d->flag & V3D_INVALID_BACKBUF))
+ return;
+
+#if 0
+ if (test) {
+ if (qtest()) {
+ addafterqueue(ar->win, BACKBUFDRAW, 1);
+ return;
+ }
+ }
+#endif
+
+ if (v3d->drawtype > OB_WIRE) v3d->zbuf = true;
+
+ /* dithering and AA break color coding, so disable */
+ glDisable(GL_DITHER);
+
+ multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
+ if (multisample_enabled)
+ glDisable(GL_MULTISAMPLE);
+
+ if (win->multisamples != USER_MULTISAMPLE_NONE) {
+ /* for multisample we use an offscreen FBO. multisample drawing can fail
+ * with color coded selection drawing, and reading back depths from such
+ * a buffer can also cause a few seconds freeze on OS X / NVidia. */
+ int w = BLI_rcti_size_x(&ar->winrct);
+ int h = BLI_rcti_size_y(&ar->winrct);
+ char error[256];
+
+ if (rv3d->gpuoffscreen) {
+ if (GPU_offscreen_width(rv3d->gpuoffscreen) != w ||
+ GPU_offscreen_height(rv3d->gpuoffscreen) != h)
+ {
+ GPU_offscreen_free(rv3d->gpuoffscreen);
+ rv3d->gpuoffscreen = NULL;
+ }
+ }
+
+ if (!rv3d->gpuoffscreen) {
+ rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error);
+
+ if (!rv3d->gpuoffscreen)
+ fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
+ }
+ }
+
+ if (rv3d->gpuoffscreen)
+ GPU_offscreen_bind(rv3d->gpuoffscreen, true);
+ else
+ glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ if (v3d->zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ else {
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ if (rv3d->rflag & RV3D_CLIPPING)
+ ED_view3d_clipping_set(rv3d);
+
+ G.f |= G_BACKBUFSEL;
+
+ if (base && ((base->flag & BASE_VISIBLED) != 0))
+ draw_object_backbufsel(eval_ctx, scene, v3d, rv3d, base->object);
+
+ if (rv3d->gpuoffscreen)
+ GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
+ else
+ ar->swap = 0; /* mark invalid backbuf for wm draw */
+
+ v3d->flag &= ~V3D_INVALID_BACKBUF;
+
+ G.f &= ~G_BACKBUFSEL;
+ v3d->zbuf = false;
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_DITHER);
+ if (multisample_enabled)
+ glEnable(GL_MULTISAMPLE);
+
+ if (rv3d->rflag & RV3D_CLIPPING)
+ ED_view3d_clipping_disable();
+}
+
+void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->gpuoffscreen) {
+ GPU_offscreen_bind(rv3d->gpuoffscreen, true);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glReadPixels(x, y, w, h, format, type, data);
+ GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
+ }
+ else {
+ glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
+ }
+}
+
+/* XXX depth reading exception, for code not using gpu offscreen */
+static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
+{
+ glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
+}
+
+void ED_view3d_backbuf_validate(const struct EvaluationContext *eval_ctx, ViewContext *vc)
+{
+ if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
+ backdrawview3d(eval_ctx, vc->scene, vc->view_layer, vc->win, vc->ar, vc->v3d);
+ }
+}
+
+/**
+ * allow for small values [0.5 - 2.5],
+ * and large values, FLT_MAX by clamping by the area size
+ */
+int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
+{
+ return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
+}
+
+/* samples a single pixel (copied from vpaint) */
+unsigned int ED_view3d_backbuf_sample(
+ const EvaluationContext *eval_ctx, ViewContext *vc, int x, int y)
+{
+ if (x >= vc->ar->winx || y >= vc->ar->winy) {
+ return 0;
+ }
+
+ ED_view3d_backbuf_validate(eval_ctx, vc);
+
+ unsigned int col;
+ view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadBuffer(GL_BACK);
+
+ if (ENDIAN_ORDER == B_ENDIAN) {
+ BLI_endian_switch_uint32(&col);
+ }
+
+ return GPU_select_to_index(col);
+}
+
+/* reads full rect, converts indices */
+ImBuf *ED_view3d_backbuf_read(
+ const EvaluationContext *eval_ctx, ViewContext *vc, int xmin, int ymin, int xmax, int ymax)
+{
+ /* clip */
+ const rcti clip = {
+ max_ii(xmin, 0), min_ii(xmax, vc->ar->winx - 1),
+ max_ii(ymin, 0), min_ii(ymax, vc->ar->winy - 1)};
+ const int size_clip[2] = {
+ BLI_rcti_size_x(&clip) + 1,
+ BLI_rcti_size_y(&clip) + 1};
+
+ if (UNLIKELY((clip.xmin > clip.xmax) ||
+ (clip.ymin > clip.ymax)))
+ {
+ return NULL;
+ }
+
+ ImBuf *ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect);
+
+ ED_view3d_backbuf_validate(eval_ctx, vc);
+
+ view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect);
+
+ glReadBuffer(GL_BACK);
+
+ if (ENDIAN_ORDER == B_ENDIAN) {
+ IMB_convert_rgba_to_abgr(ibuf_clip);
+ }
+
+ GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]);
+
+ if ((clip.xmin == xmin) &&
+ (clip.xmax == xmax) &&
+ (clip.ymin == ymin) &&
+ (clip.ymax == ymax))
+ {
+ return ibuf_clip;
+ }
+ else {
+ /* put clipped result into a non-clipped buffer */
+ const int size[2] = {
+ (xmax - xmin + 1),
+ (ymax - ymin + 1)};
+
+ ImBuf *ibuf_full = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
+
+ IMB_rectcpy(
+ ibuf_full, ibuf_clip,
+ clip.xmin - xmin, clip.ymin - ymin,
+ 0, 0,
+ size_clip[0], size_clip[1]);
+ IMB_freeImBuf(ibuf_clip);
+ return ibuf_full;
+ }
+}
+
+/* smart function to sample a rect spiralling outside, nice for backbuf selection */
+unsigned int ED_view3d_backbuf_sample_rect(
+ const EvaluationContext *eval_ctx, ViewContext *vc, const int mval[2], int size,
+ unsigned int min, unsigned int max, float *r_dist)
+{
+ int dirvec[4][2];
+
+ const int amount = (size - 1) / 2;
+
+ const int minx = mval[0] - (amount + 1);
+ const int miny = mval[1] - (amount + 1);
+ ImBuf *buf = ED_view3d_backbuf_read(eval_ctx, vc, minx, miny, minx + size - 1, miny + size - 1);
+ if (!buf) return 0;
+
+ unsigned index = 0;
+ int rc = 0;
+
+ dirvec[0][0] = 1; dirvec[0][1] = 0;
+ dirvec[1][0] = 0; dirvec[1][1] = -size;
+ dirvec[2][0] = -1; dirvec[2][1] = 0;
+ dirvec[3][0] = 0; dirvec[3][1] = size;
+
+ const unsigned *bufmin = buf->rect;
+ const unsigned *tbuf = buf->rect;
+ const unsigned *bufmax = buf->rect + size * size;
+ tbuf += amount * size + amount;
+
+ for (int nr = 1; nr <= size; nr++) {
+ for (int a = 0; a < 2; a++) {
+ for (int b = 0; b < nr; b++) {
+ if (*tbuf && *tbuf >= min && *tbuf < max) {
+ /* we got a hit */
+
+ /* get x,y pixel coords from the offset
+ * (manhatten distance in keeping with other screen-based selection) */
+ *r_dist = (float)(
+ abs(((int)(tbuf - buf->rect) % size) - (size / 2)) +
+ abs(((int)(tbuf - buf->rect) / size) - (size / 2)));
+
+ /* indices start at 1 here */
+ index = (*tbuf - min) + 1;
+ goto exit;
+ }
+
+ tbuf += (dirvec[rc][0] + dirvec[rc][1]);
+
+ if (tbuf < bufmin || tbuf >= bufmax) {
+ goto exit;
+ }
+ }
+ rc++;
+ rc &= 3;
+ }
+ }
+
+exit:
+ IMB_freeImBuf(buf);
+ return index;
+}
+
+
+/* ************************************************************* */
+
+static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
+{
+ if (BKE_image_is_stereo(ima)) {
+ iuser->flag |= IMA_SHOW_STEREO;
+
+ if ((scene->r.scemode & R_MULTIVIEW) == 0) {
+ iuser->multiview_eye = STEREO_LEFT_ID;
+ }
+ else if (v3d->stereo3d_camera != STEREO_3D_ID) {
+ /* show only left or right camera */
+ iuser->multiview_eye = v3d->stereo3d_camera;
+ }
+
+ BKE_image_multiview_index(ima, iuser);
+ }
+ else {
+ iuser->flag &= ~IMA_SHOW_STEREO;
+ }
+}
+
+static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
+ const bool do_foreground, const bool do_camera_frame)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ int fg_flag = do_foreground ? CAM_BGIMG_FLAG_FOREGROUND : 0;
+ if (v3d->camera == NULL || v3d->camera->type != OB_CAMERA) {
+ return;
+ }
+ Camera *cam = v3d->camera->data;
+
+ for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
+ bgpic->iuser.scene = scene; /* Needed for render results. */
+
+ if ((bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != fg_flag)
+ continue;
+
+ {
+ float image_aspect[2];
+ float x1, y1, x2, y2, centx, centy;
+
+ void *lock;
+
+ Image *ima = NULL;
+
+ /* disable individual images */
+ if ((bgpic->flag & CAM_BGIMG_FLAG_DISABLED))
+ continue;
+
+ ImBuf *ibuf = NULL;
+ ImBuf *freeibuf = NULL;
+ ImBuf *releaseibuf = NULL;
+ if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
+ ima = bgpic->ima;
+ if (ima == NULL)
+ continue;
+ BKE_image_user_frame_calc(&bgpic->iuser, CFRA, 0);
+ if (ima->source == IMA_SRC_SEQUENCE && !(bgpic->iuser.flag & IMA_USER_FRAME_IN_RANGE)) {
+ ibuf = NULL; /* frame is out of range, dont show */
+ }
+ else {
+ view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser);
+ ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock);
+ releaseibuf = ibuf;
+ }
+
+ image_aspect[0] = ima->aspx;
+ image_aspect[1] = ima->aspy;
+ }
+ else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
+ /* TODO: skip drawing when out of frame range (as image sequences do above) */
+ MovieClip *clip = NULL;
+
+ if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) {
+ if (scene->camera)
+ clip = BKE_object_movieclip_get(scene, scene->camera, true);
+ }
+ else {
+ clip = bgpic->clip;
+ }
+
+ if (clip == NULL)
+ continue;
+
+ BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA);
+ ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser);
+
+ image_aspect[0] = clip->aspx;
+ image_aspect[1] = clip->aspy;
+
+ /* working with ibuf from image and clip has got different workflow now.
+ * ibuf acquired from clip is referenced by cache system and should
+ * be dereferenced after usage. */
+ freeibuf = ibuf;
+ }
+ else {
+ /* perhaps when loading future files... */
+ BLI_assert(0);
+ copy_v2_fl(image_aspect, 1.0f);
+ }
+
+ if (ibuf == NULL)
+ continue;
+
+ if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */
+ if (freeibuf)
+ IMB_freeImBuf(freeibuf);
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
+
+ continue;
+ }
+
+ if (ibuf->rect == NULL)
+ IMB_rect_from_float(ibuf);
+
+ BLI_assert(rv3d->persp == RV3D_CAMOB);
+ {
+ if (do_camera_frame) {
+ rctf vb;
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
+ x1 = vb.xmin;
+ y1 = vb.ymin;
+ x2 = vb.xmax;
+ y2 = vb.ymax;
+ }
+ else {
+ x1 = ar->winrct.xmin;
+ y1 = ar->winrct.ymin;
+ x2 = ar->winrct.xmax;
+ y2 = ar->winrct.ymax;
+ }
+
+ /* apply offset last - camera offset is different to offset in blender units */
+ /* so this has some sane way of working - this matches camera's shift _exactly_ */
+ {
+ const float max_dim = max_ff(x2 - x1, y2 - y1);
+ const float xof_scale = bgpic->offset[0] * max_dim;
+ const float yof_scale = bgpic->offset[1] * max_dim;
+
+ x1 += xof_scale;
+ y1 += yof_scale;
+ x2 += xof_scale;
+ y2 += yof_scale;
+ }
+
+ centx = (x1 + x2) * 0.5f;
+ centy = (y1 + y2) * 0.5f;
+
+ /* aspect correction */
+ if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) {
+ /* apply aspect from clip */
+ const float w_src = ibuf->x * image_aspect[0];
+ const float h_src = ibuf->y * image_aspect[1];
+
+ /* destination aspect is already applied from the camera frame */
+ const float w_dst = x1 - x2;
+ const float h_dst = y1 - y2;
+
+ const float asp_src = w_src / h_src;
+ const float asp_dst = w_dst / h_dst;
+
+ if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) {
+ if ((asp_src > asp_dst) == ((bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) != 0)) {
+ /* fit X */
+ const float div = asp_src / asp_dst;
+ x1 = ((x1 - centx) * div) + centx;
+ x2 = ((x2 - centx) * div) + centx;
+ }
+ else {
+ /* fit Y */
+ const float div = asp_dst / asp_src;
+ y1 = ((y1 - centy) * div) + centy;
+ y2 = ((y2 - centy) * div) + centy;
+ }
+ }
+ }
+ }
+
+ /* complete clip? */
+ rctf clip_rect;
+ BLI_rctf_init(&clip_rect, x1, x2, y1, y2);
+ if (bgpic->rotation) {
+ BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation);
+ }
+
+ if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) {
+ if (freeibuf)
+ IMB_freeImBuf(freeibuf);
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
+
+ continue;
+ }
+
+ float zoomx = (x2 - x1) / ibuf->x;
+ float zoomy = (y2 - y1) / ibuf->y;
+
+ /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
+ if (zoomx < 1.0f || zoomy < 1.0f) {
+ float tzoom = min_ff(zoomx, zoomy);
+ int mip = 0;
+
+ if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) {
+ IMB_remakemipmap(ibuf, 0);
+ ibuf->userflags &= ~IB_MIPMAP_INVALID;
+ }
+ else if (ibuf->mipmap[0] == NULL)
+ IMB_makemipmap(ibuf, 0);
+
+ while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) {
+ tzoom *= 2.0f;
+ zoomx *= 2.0f;
+ zoomy *= 2.0f;
+ mip++;
+ }
+ if (mip > 0)
+ ibuf = ibuf->mipmap[mip - 1];
+ }
+
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ gpuPushProjectionMatrix();
+ gpuPushMatrix();
+ ED_region_pixelspace(ar);
+
+ gpuTranslate2f(centx, centy);
+ gpuScaleUniform(bgpic->scale);
+ gpuRotate2D(RAD2DEGF(-bgpic->rotation));
+
+ if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) {
+ zoomx *= -1.0f;
+ x1 = x2;
+ }
+ if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) {
+ zoomy *= -1.0f;
+ y1 = y2;
+ }
+
+ float col[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha};
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(&state, x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect,
+ zoomx, zoomy, col);
+
+ gpuPopProjectionMatrix();
+ gpuPopMatrix();
+
+ glDisable(GL_BLEND);
+
+ glDepthMask(GL_TRUE);
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+
+ if (freeibuf)
+ IMB_freeImBuf(freeibuf);
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
+ }
+ }
+}
+
+void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
+ const bool do_foreground, const bool do_camera_frame)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) {
+ Camera *cam = v3d->camera->data;
+ if ((cam->flag & CAM_SHOW_BG_IMAGE) == 0) {
+ return;
+ }
+ }
+ else {
+ return;
+ }
+
+ /* disabled - mango request, since footage /w only render is quite useful
+ * and this option is easy to disable all background images at once */
+#if 0
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE)
+ return;
+#endif
+
+ if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
+ }
+ }
+ else {
+ view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
+ }
+}
+
+/* ****************** View3d afterdraw *************** */
+
+typedef struct View3DAfter {
+ struct View3DAfter *next, *prev;
+ struct Base *base;
+ short dflag;
+} View3DAfter;
+
+/* temp storage of Objects that need to be drawn as last */
+void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag)
+{
+ View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after");
+ BLI_assert((base->flag_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(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d)
+{
+ View3DAfter *v3da;
+
+ glDepthMask(GL_FALSE);
+ v3d->transp = true;
+
+ while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, v3da->base, v3da->dflag);
+ MEM_freeN(v3da);
+ }
+ v3d->transp = false;
+
+ glDepthMask(GL_TRUE);
+
+}
+
+/* clears zbuffer and draws it over */
+static void view3d_draw_xray(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, bool *clear)
+{
+ if (*clear && v3d->zbuf) {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ *clear = false;
+ }
+
+ v3d->xray = true;
+ View3DAfter *v3da;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, v3da->base, v3da->dflag);
+ MEM_freeN(v3da);
+ }
+ v3d->xray = false;
+}
+
+
+/* clears zbuffer and draws it over */
+static void view3d_draw_xraytransp(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, const bool clear)
+{
+ if (clear && v3d->zbuf)
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ v3d->xray = true;
+ v3d->transp = true;
+
+ glDepthMask(GL_FALSE);
+
+ View3DAfter *v3da;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, v3da->base, v3da->dflag);
+ MEM_freeN(v3da);
+ }
+
+ v3d->transp = false;
+ v3d->xray = false;
+
+ glDepthMask(GL_TRUE);
+}
+
+/* clears zbuffer and draws it over,
+ * note that in the select version we don't care about transparent flag as with regular drawing */
+static void view3d_draw_xray_select(
+ const struct EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, bool *clear)
+{
+ /* Not ideal, but we need to read from the previous depths before clearing
+ * otherwise we could have a function to load the depths after drawing.
+ *
+ * Clearing the depth buffer isn't all that common between drawing objects so accept this for now.
+ */
+ if (U.gpu_select_pick_deph) {
+ GPU_select_load_id(-1);
+ }
+
+ View3DAfter *v3da;
+ if (*clear && v3d->zbuf) {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ *clear = false;
+ }
+
+ v3d->xray = true;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
+ if (GPU_select_load_id(v3da->base->object->select_color)) {
+ draw_object_select(eval_ctx, scene, view_layer, ar, v3d, v3da->base, v3da->dflag);
+ }
+ MEM_freeN(v3da);
+ }
+ v3d->xray = false;
+}
+
+/* *********************** */
+
+/*
+ * In most cases call draw_dupli_objects,
+ * draw_dupli_objects_color was added because when drawing set dupli's
+ * we need to force the color
+ */
+
+#if 0
+int dupli_ob_sort(void *arg1, void *arg2)
+{
+ void *p1 = ((DupliObject *)arg1)->ob;
+ void *p2 = ((DupliObject *)arg2)->ob;
+ int val = 0;
+ if (p1 < p2) val = -1;
+ else if (p1 > p2) val = 1;
+ return val;
+}
+#endif
+
+
+static DupliObject *dupli_step(DupliObject *dob)
+{
+ while (dob && dob->no_draw)
+ dob = dob->next;
+ return dob;
+}
+
+static void draw_dupli_objects_color(
+ const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Base *base,
+ const short dflag, const int color)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ ListBase *lb;
+ LodLevel *savedlod;
+ Base tbase = {NULL};
+ BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */
+ unsigned char color_rgb[3];
+ const short dflag_dupli = dflag | DRAW_CONSTCOLOR;
+ short transflag;
+ char dt;
+ short dtx;
+ DupliApplyData *apply_data;
+
+ if ((base->flag & BASE_VISIBLED) == 0) return;
+ if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return;
+
+ if (dflag & DRAW_CONSTCOLOR) {
+ BLI_assert(color == TH_UNDEFINED);
+ }
+ else {
+ UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb);
+ }
+
+ tbase.flag_legacy = OB_FROMDUPLI | base->flag_legacy;
+ tbase.flag = base->flag;
+ lb = object_duplilist(eval_ctx, scene, base->object);
+ // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */
+
+ apply_data = duplilist_apply(eval_ctx, base->object, scene, lb);
+
+ DupliObject *dob_next = NULL;
+ DupliObject *dob = dupli_step(lb->first);
+ if (dob) dob_next = dupli_step(dob->next);
+
+ for (; dob; dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) {
+ bool testbb = false;
+
+ tbase.object = dob->ob;
+
+ /* Make sure lod is updated from dupli's position */
+ savedlod = dob->ob->currentlod;
+
+#ifdef WITH_GAMEENGINE
+ if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
+ BKE_object_lod_update(dob->ob, rv3d->viewinv[3]);
+ }
+#endif
+
+ /* extra service: draw the duplicator in drawtype of parent, minimum taken
+ * to allow e.g. boundbox box objects in groups for LOD */
+ dt = tbase.object->dt;
+ tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
+
+ /* inherit draw extra, but not if a boundbox under the assumption that this
+ * is intended to speed up drawing, and drawing extra (especially wire) can
+ * slow it down too much */
+ dtx = tbase.object->dtx;
+ if (tbase.object->dt != OB_BOUNDBOX)
+ tbase.object->dtx = base->object->dtx;
+
+ /* negative scale flag has to propagate */
+ transflag = tbase.object->transflag;
+
+ if (is_negative_m4(dob->mat))
+ tbase.object->transflag |= OB_NEG_SCALE;
+ else
+ tbase.object->transflag &= ~OB_NEG_SCALE;
+
+ /* should move outside the loop but possible color is set in draw_object still */
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ glColor3ubv(color_rgb);
+ }
+
+ if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) {
+ bb = *bb_tmp; /* must make a copy */
+ testbb = true;
+ }
+
+ if (!testbb || ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) {
+ copy_m4_m4(dob->ob->obmat, dob->mat);
+ GPU_begin_dupli_object(dob);
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, &tbase, dflag_dupli);
+ GPU_end_dupli_object();
+ }
+
+ tbase.object->dt = dt;
+ tbase.object->dtx = dtx;
+ tbase.object->transflag = transflag;
+ tbase.object->currentlod = savedlod;
+ }
+
+ if (apply_data) {
+ duplilist_restore(lb, apply_data);
+ duplilist_free_apply_data(apply_data);
+ }
+
+ free_object_duplilist(lb);
+}
+
+void draw_dupli_objects(const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Base *base)
+{
+ /* define the color here so draw_dupli_objects_color can be called
+ * from the set loop */
+
+ int color = (base->flag & 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(eval_ctx, scene, view_layer, ar, v3d, base, 0, color);
+}
+
+/* XXX warning, not using gpu offscreen here */
+void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
+{
+ /* clamp rect by region */
+ rcti r = {
+ .xmin = 0,
+ .xmax = ar->winx - 1,
+ .ymin = 0,
+ .ymax = ar->winy - 1
+ };
+
+ /* Constrain rect to depth bounds */
+ BLI_rcti_isect(&r, rect, rect);
+
+ /* assign values to compare with the ViewDepths */
+ int x = rect->xmin;
+ int y = rect->ymin;
+
+ int w = BLI_rcti_size_x(rect);
+ int h = BLI_rcti_size_y(rect);
+
+ if (w <= 0 || h <= 0) {
+ if (d->depths)
+ MEM_freeN(d->depths);
+ d->depths = NULL;
+
+ d->damaged = false;
+ }
+ else if (d->w != w ||
+ d->h != h ||
+ d->x != x ||
+ d->y != y ||
+ d->depths == NULL
+ )
+ {
+ d->x = x;
+ d->y = y;
+ d->w = w;
+ d->h = h;
+
+ if (d->depths)
+ MEM_freeN(d->depths);
+
+ d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
+
+ d->damaged = true;
+ }
+
+ if (d->damaged) {
+ /* XXX using special function here, it doesn't use the gpu offscreen system */
+ view3d_opengl_read_Z_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
+ glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
+ d->damaged = false;
+ }
+}
+
+/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */
+void ED_view3d_depth_update(ARegion *ar)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* Create storage for, and, if necessary, copy depth buffer */
+ if (!rv3d->depths) rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
+ if (rv3d->depths) {
+ ViewDepths *d = rv3d->depths;
+ if (d->w != ar->winx ||
+ d->h != ar->winy ||
+ !d->depths)
+ {
+ d->w = ar->winx;
+ d->h = ar->winy;
+ if (d->depths)
+ MEM_freeN(d->depths);
+ d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
+ d->damaged = true;
+ }
+
+ if (d->damaged) {
+ view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
+ glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
+
+ d->damaged = false;
+ }
+ }
+}
+
+/* utility function to find the closest Z value, use for autodepth */
+float view3d_depth_near(ViewDepths *d)
+{
+ /* convert to float for comparisons */
+ const float near = (float)d->depth_range[0];
+ const float far_real = (float)d->depth_range[1];
+ float far = far_real;
+
+ const float *depths = d->depths;
+ float depth = FLT_MAX;
+ int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */
+
+ /* far is both the starting 'far' value
+ * and the closest value found. */
+ while (i--) {
+ depth = *depths++;
+ if ((depth < far) && (depth > near)) {
+ far = depth;
+ }
+ }
+
+ return far == far_real ? FLT_MAX : far;
+}
+
+void ED_view3d_draw_depth_gpencil(
+ const EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d)
+{
+ bool zbuf = v3d->zbuf;
+
+ /* Setup view matrix. */
+ ED_view3d_draw_setup_view(NULL, eval_ctx, scene, ar, v3d, NULL, NULL, NULL);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ v3d->zbuf = true;
+ glEnable(GL_DEPTH_TEST);
+
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ ED_gpencil_draw_view3d(NULL, scene, eval_ctx->view_layer, v3d, ar, true);
+ }
+
+ v3d->zbuf = zbuf;
+ if (!zbuf) glDisable(GL_DEPTH_TEST);
+}
+
+void ED_view3d_draw_depth_loop(const EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d)
+{
+ Base *base;
+ ViewLayer *view_layer = eval_ctx->view_layer;
+ /* no need for color when drawing depth buffer */
+ const short dflag_depth = DRAW_CONSTCOLOR;
+
+ /* draw set first */
+ if (scene->set) {
+ Scene *sce_iter;
+ for (SETLOOPER(scene->set, sce_iter, base)) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, base, 0);
+ if (base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects_color(eval_ctx, scene, view_layer, ar, v3d, base, dflag_depth, TH_UNDEFINED);
+ }
+ }
+ }
+ }
+
+ for (base = view_layer->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(eval_ctx, scene, view_layer, ar, v3d, base, dflag_depth, TH_UNDEFINED);
+ }
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, base, dflag_depth);
+ }
+ }
+
+ /* this isn't that nice, draw xray objects as if they are normal */
+ if (v3d->afterdraw_transp.first ||
+ v3d->afterdraw_xray.first ||
+ v3d->afterdraw_xraytransp.first)
+ {
+ View3DAfter *v3da;
+ int mask_orig;
+
+ v3d->xray = true;
+
+ /* transp materials can change the depth mask, see #21388 */
+ glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
+
+
+ if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) {
+ glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
+ for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, v3da->base, dflag_depth);
+ }
+ glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
+ }
+
+ /* draw 3 passes, transp/xray/xraytransp */
+ v3d->xray = false;
+ v3d->transp = true;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, v3da->base, dflag_depth);
+ MEM_freeN(v3da);
+ }
+
+ v3d->xray = true;
+ v3d->transp = false;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, v3da->base, dflag_depth);
+ MEM_freeN(v3da);
+ }
+
+ v3d->xray = true;
+ v3d->transp = true;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, v3da->base, dflag_depth);
+ MEM_freeN(v3da);
+ }
+
+
+ v3d->xray = false;
+ v3d->transp = false;
+
+ glDepthMask(mask_orig);
+ }
+}
+
+void ED_view3d_draw_select_loop(
+ const struct EvaluationContext *eval_ctx, ViewContext *vc, Scene *scene, ViewLayer *view_layer,
+ View3D *v3d, ARegion *ar, bool use_obedit_skip, bool use_nearest)
+{
+ struct bThemeState theme_state;
+
+ short code = 1;
+ const short dflag = DRAW_PICKING | DRAW_CONSTCOLOR;
+
+ /* Tools may request depth outside of regular drawing code. */
+ UI_Theme_Store(&theme_state);
+ UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
+
+ if (vc->obedit && vc->obedit->type == OB_MBALL) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, BASACT(view_layer), dflag);
+ }
+ else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) {
+ /* if not drawing sketch, draw bones */
+ if (!BDR_drawSketchNames(vc)) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, BASACT(view_layer), dflag);
+ }
+ }
+ else {
+ Base *base;
+
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
+ if (((base->flag & BASE_SELECTABLED) == 0) ||
+ (use_obedit_skip && (scene->obedit->data == base->object->data)))
+ {
+ base->object->select_color = 0;
+ }
+ else {
+ base->object->select_color = code;
+
+ if (use_nearest && (base->object->dtx & OB_DRAWXRAY)) {
+ ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag);
+ }
+ else {
+ if (GPU_select_load_id(code)) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, base, dflag);
+ }
+ }
+ code++;
+ }
+ }
+ }
+
+ if (use_nearest) {
+ bool xrayclear = true;
+ if (v3d->afterdraw_xray.first) {
+ view3d_draw_xray_select(eval_ctx, scene, view_layer, ar, v3d, &xrayclear);
+ }
+ }
+ }
+
+ UI_Theme_Restore(&theme_state);
+}
+
+typedef struct View3DShadow {
+ struct View3DShadow *next, *prev;
+ GPULamp *lamp;
+} View3DShadow;
+
+static void gpu_render_lamp_update(Scene *scene, View3D *v3d,
+ Object *ob, Object *par,
+ float obmat[4][4], unsigned int lay,
+ ListBase *shadows)
+{
+ GPULamp *lamp = GPU_lamp_from_blender(scene, ob, par);
+
+ if (lamp) {
+ Lamp *la = (Lamp *)ob->data;
+
+ GPU_lamp_update(lamp, lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat);
+ GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy);
+
+ unsigned int layers = lay & v3d->lay;
+
+ if (layers &&
+ GPU_lamp_has_shadow_buffer(lamp) &&
+ /* keep last, may do string lookup */
+ GPU_lamp_visible(lamp, NULL))
+ {
+ View3DShadow *shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow");
+ shadow->lamp = lamp;
+ BLI_addtail(shadows, shadow);
+ }
+ }
+}
+
+static void gpu_update_lamps_shadows_world(const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d)
+{
+ ListBase shadows;
+ Scene *sce_iter;
+ Base *base;
+ World *world = scene->world;
+
+ BLI_listbase_clear(&shadows);
+
+ /* update lamp transform and gather shadow lamps */
+ for (SETLOOPER(scene, sce_iter, base)) {
+ Object *ob = base->object;
+
+ if (ob->type == OB_LAMP)
+ gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, ob->lay, &shadows);
+
+ if (ob->transflag & OB_DUPLI) {
+ DupliObject *dob;
+ ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
+
+ for (dob = lb->first; dob; dob = dob->next)
+ if (dob->ob->type == OB_LAMP)
+ gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, ob->lay, &shadows);
+
+ free_object_duplilist(lb);
+ }
+ }
+
+ /* render shadows after updating all lamps, nested object_duplilist
+ * don't work correct since it's replacing object matrices */
+ for (View3DShadow *shadow = shadows.first; shadow; shadow = shadow->next) {
+ /* this needs to be done better .. */
+ float viewmat[4][4], winmat[4][4];
+ ARegion ar = {NULL};
+ RegionView3D rv3d = {{{0}}};
+
+ int drawtype = v3d->drawtype;
+ int lay = v3d->lay;
+ int flag2 = v3d->flag2;
+
+ v3d->drawtype = OB_SOLID;
+ v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
+ v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
+ v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW;
+
+ int winsize;
+ GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
+
+ ar.regiondata = &rv3d;
+ ar.regiontype = RGN_TYPE_WINDOW;
+ rv3d.persp = RV3D_CAMOB;
+ copy_m4_m4(rv3d.winmat, winmat);
+ copy_m4_m4(rv3d.viewmat, viewmat);
+ invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
+ mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
+ invert_m4_m4(rv3d.persinv, rv3d.viewinv);
+
+ /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */
+ ED_view3d_draw_offscreen(
+ eval_ctx, scene, eval_ctx->view_layer, v3d, &ar, winsize, winsize, viewmat, winmat,
+ false, false, true,
+ NULL, NULL, NULL, NULL);
+ GPU_lamp_shadow_buffer_unbind(shadow->lamp);
+
+ v3d->drawtype = drawtype;
+ v3d->lay = lay;
+ v3d->flag2 = flag2;
+ }
+
+ BLI_freelistN(&shadows);
+
+ /* update world values */
+ if (world) {
+ GPU_mist_update_enable(world->mode & WO_MIST);
+ GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr);
+ GPU_horizon_update_color(&world->horr);
+ GPU_ambient_update_color(&world->ambr);
+ GPU_zenith_update_color(&world->zenr);
+ }
+}
+
+/* *********************** customdata **************** */
+
+CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d)
+{
+ CustomDataMask mask = 0;
+ const int drawtype = view3d_effective_drawtype(v3d);
+
+ if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL) ||
+ ((drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX)))
+ {
+ mask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
+
+ if (BKE_scene_use_new_shading_nodes(scene)) {
+ if (drawtype == OB_MATERIAL)
+ mask |= CD_MASK_ORCO;
+ }
+ else {
+ if ((scene->gm.matmode == GAME_MAT_GLSL && drawtype == OB_TEXTURE) ||
+ (drawtype == OB_MATERIAL))
+ {
+ mask |= CD_MASK_ORCO;
+ }
+ }
+ }
+
+ return mask;
+}
+
+/* goes over all modes and view3d settings */
+CustomDataMask ED_view3d_screen_datamask(const Scene *scene, const bScreen *screen)
+{
+ CustomDataMask mask = CD_MASK_BAREMESH;
+
+ /* check if we need tfaces & mcols due to view mode */
+ for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ mask |= ED_view3d_datamask(scene, sa->spacedata.first);
+ }
+ }
+
+ return mask;
+}
+
+/**
+ * Shared by #ED_view3d_draw_offscreen and #view3d_main_region_draw_objects
+ *
+ * \note \a C and \a grid_unit will be NULL when \a draw_offscreen is set.
+ * \note Drawing lamps and opengl render uses this, so dont do grease pencil or view widgets here.
+ */
+static void view3d_draw_objects(
+ const bContext *C,
+ const EvaluationContext *eval_ctx,
+ Scene *scene, View3D *v3d, ARegion *ar,
+ const char **grid_unit,
+ const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
+{
+ ViewLayer *view_layer = C ? CTX_data_view_layer(C) : BKE_view_layer_from_scene_get(scene);
+ RegionView3D *rv3d = ar->regiondata;
+ Base *base;
+ const bool do_camera_frame = !draw_offscreen;
+ const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0;
+ const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
+ /* only draw grids after in solid modes, else it hovers over mesh wires */
+ const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx;
+ bool do_composite_xray = false;
+ bool xrayclear = true;
+
+ if (!draw_offscreen) {
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+ }
+
+ if (rv3d->rflag & RV3D_CLIPPING)
+ view3d_draw_clipping(rv3d);
+
+ /* set zbuffer after we draw clipping region */
+ v3d->zbuf = VP_legacy_use_depth(scene, v3d);
+
+ if (v3d->zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ }
+
+ /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
+ * objects if done last */
+ if (draw_grids) {
+ /* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */
+ rv3d->gridview = ED_view3d_grid_scale(scene, v3d, grid_unit);
+
+ if (!draw_floor) {
+ ED_region_pixelspace(ar);
+ *grid_unit = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
+ VP_legacy_drawgrid(&scene->unit, ar, v3d, grid_unit);
+ gpuLoadProjectionMatrix(rv3d->winmat);
+ gpuLoadMatrix(rv3d->viewmat);
+ }
+ else if (!draw_grids_after) {
+ VP_legacy_drawfloor(scene, v3d, grid_unit, true);
+ }
+ }
+
+ /* important to do before clipping */
+ if (do_bgpic) {
+ view3d_draw_bgpic_test(scene, ar, v3d, false, do_camera_frame);
+ }
+
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_set(rv3d);
+ }
+
+ /* draw set first */
+ if (scene->set) {
+ const short dflag = DRAW_CONSTCOLOR | DRAW_SCENESET;
+ Scene *sce_iter;
+ for (SETLOOPER(scene->set, sce_iter, base)) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
+ UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, base, dflag);
+
+ if (base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects_color(eval_ctx, scene, view_layer, ar, v3d, base, dflag, TH_UNDEFINED);
+ }
+ }
+ }
+
+ /* Transp and X-ray afterdraw stuff for sets is done later */
+ }
+
+ if (draw_offscreen) {
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
+ /* dupli drawing */
+ if (base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects(eval_ctx, scene, view_layer, ar, v3d, base);
+ }
+
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, base, 0);
+ }
+ }
+ }
+ else {
+ unsigned int lay_used = 0;
+
+ /* then draw not selected and the duplis, but skip editmode object */
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ lay_used |= base->lay;
+
+ if ((base->flag & BASE_VISIBLED) != 0) {
+
+ /* dupli drawing */
+ if (base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects(eval_ctx, scene, view_layer, ar, v3d, base);
+ }
+ if ((base->flag & BASE_SELECTED) == 0) {
+ if (base->object != scene->obedit)
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, base, 0);
+ }
+ }
+ }
+
+ /* mask out localview */
+ v3d->lay_used = lay_used & ((1 << 20) - 1);
+
+ /* draw selected and editmode */
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
+ if (base->object == scene->obedit || (base->flag & BASE_SELECTED)) {
+ draw_object(eval_ctx, scene, view_layer, ar, v3d, base, 0);
+ }
+ }
+ }
+ }
+
+ /* perspective floor goes last to use scene depth and avoid writing to depth buffer */
+ if (draw_grids_after) {
+ VP_legacy_drawfloor(scene, v3d, grid_unit, false);
+ }
+
+ /* must be before xray draw which clears the depth buffer */
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ wmWindowManager *wm = (C != NULL) ? CTX_wm_manager(C) : NULL;
+
+ /* must be before xray draw which clears the depth buffer */
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ ED_gpencil_draw_view3d(wm, scene, view_layer, v3d, ar, true);
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ }
+
+ /* transp and X-ray afterdraw stuff */
+ if (v3d->afterdraw_transp.first) view3d_draw_transp(eval_ctx, scene, view_layer, ar, v3d);
+
+ /* always do that here to cleanup depth buffers if none needed */
+ if (fx) {
+ do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first);
+ GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray);
+ }
+
+ if (v3d->afterdraw_xray.first) view3d_draw_xray(eval_ctx, scene, view_layer, ar, v3d, &xrayclear);
+ if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(eval_ctx, scene, view_layer, ar, v3d, xrayclear);
+
+ if (fx && do_composite_xray) {
+ GPU_fx_compositor_XRay_resolve(fx);
+ }
+
+ if (!draw_offscreen) {
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+ }
+
+ if (rv3d->rflag & RV3D_CLIPPING)
+ ED_view3d_clipping_disable();
+
+ /* important to do after clipping */
+ if (do_bgpic) {
+ view3d_draw_bgpic_test(scene, ar, v3d, true, do_camera_frame);
+ }
+
+ /* cleanup */
+ if (v3d->zbuf) {
+ v3d->zbuf = false;
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
+ GPU_free_images_old();
+ }
+}
+
+/**
+ * Store values from #RegionView3D, set when drawing.
+ * This is needed when we draw with to a viewport using a different matrix (offscreen drawing for example).
+ *
+ * Values set by #ED_view3d_update_viewmat should be handled here.
+ */
+struct RV3DMatrixStore {
+ float winmat[4][4];
+ float viewmat[4][4];
+ float viewinv[4][4];
+ float persmat[4][4];
+ float persinv[4][4];
+ float viewcamtexcofac[4];
+ float pixsize;
+};
+
+struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
+{
+ struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__);
+ copy_m4_m4(rv3dmat->winmat, rv3d->winmat);
+ copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat);
+ copy_m4_m4(rv3dmat->persmat, rv3d->persmat);
+ copy_m4_m4(rv3dmat->persinv, rv3d->persinv);
+ copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv);
+ copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac);
+ rv3dmat->pixsize = rv3d->pixsize;
+ return (void *)rv3dmat;
+}
+
+void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt)
+{
+ struct RV3DMatrixStore *rv3dmat = rv3dmat_pt;
+ copy_m4_m4(rv3d->winmat, rv3dmat->winmat);
+ copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat);
+ copy_m4_m4(rv3d->persmat, rv3dmat->persmat);
+ copy_m4_m4(rv3d->persinv, rv3dmat->persinv);
+ copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv);
+ copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac);
+ rv3d->pixsize = rv3dmat->pixsize;
+}
+
+/**
+ * \note The info that this uses is updated in #ED_refresh_viewport_fps,
+ * which currently gets called during #SCREEN_OT_animation_step.
+ */
+void ED_scene_draw_fps(Scene *scene, const rcti *rect)
+{
+ ScreenFrameRateInfo *fpsi = scene->fps_info;
+ char printable[16];
+
+ if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime)
+ return;
+
+ printable[0] = '\0';
+
+#if 0
+ /* this is too simple, better do an average */
+ fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime))
+#else
+ fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime));
+
+ float fps = 0.0f;
+ int tot = 0;
+ for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) {
+ if (fpsi->redrawtimes_fps[i]) {
+ fps += fpsi->redrawtimes_fps[i];
+ tot++;
+ }
+ }
+ if (tot) {
+ fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
+
+ //fpsi->redrawtime_index++;
+ //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE)
+ // fpsi->redrawtime = 0;
+
+ fps = fps / tot;
+ }
+#endif
+
+ const int font_id = BLF_default();
+
+ /* is this more than half a frame behind? */
+ if (fps + 0.5f < (float)(FPS)) {
+ UI_FontThemeColor(font_id, TH_REDALERT);
+ BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
+ }
+ else {
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
+ BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
+ }
+
+#ifdef WITH_INTERNATIONAL
+ BLF_draw_default(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
+#else
+ BLF_draw_default_ascii(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
+#endif
+}
+
+static bool view3d_main_region_do_render_draw(const Scene *scene)
+{
+ RenderEngineType *type = RE_engines_find(scene->view_render.engine_id);
+ return (type && type->view_update && type->render_to_view);
+}
+
+bool ED_view3d_calc_render_border(const Scene *scene, View3D *v3d, ARegion *ar, rcti *rect)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ bool use_border;
+
+ /* test if there is a 3d view rendering */
+ if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene))
+ return false;
+
+ /* test if there is a border render */
+ if (rv3d->persp == RV3D_CAMOB)
+ use_border = (scene->r.mode & R_BORDER) != 0;
+ else
+ use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
+
+ if (!use_border)
+ return false;
+
+ /* compute border */
+ if (rv3d->persp == RV3D_CAMOB) {
+ rctf viewborder;
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
+
+ rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
+ rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
+ rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
+ rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
+ }
+ else {
+ rect->xmin = v3d->render_border.xmin * ar->winx;
+ rect->xmax = v3d->render_border.xmax * ar->winx;
+ rect->ymin = v3d->render_border.ymin * ar->winy;
+ rect->ymax = v3d->render_border.ymax * ar->winy;
+ }
+
+ BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin);
+ BLI_rcti_isect(&ar->winrct, rect, rect);
+
+ return true;
+}
+
+/**
+ * IMPORTANT: this is deprecated, any changes made in this function should
+ * be mirrored in view3d_draw_render_draw() in view3d_draw.c
+ */
+static bool view3d_main_region_draw_engine(
+ const bContext *C, const EvaluationContext *eval_ctx, Scene *scene,
+ ARegion *ar, View3D *v3d,
+ bool clip_border, const rcti *border_rect)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ RenderEngineType *type;
+ GLint scissor[4];
+
+
+ /* create render engine */
+ if (!rv3d->render_engine) {
+ RenderEngine *engine;
+ type = RE_engines_find(scene->view_render.engine_id);
+
+ if (!(type->view_update && type->render_to_view))
+ return false;
+
+ engine = RE_engine_create_ex(type, true);
+
+ engine->tile_x = scene->r.tilex;
+ engine->tile_y = scene->r.tiley;
+
+ type->view_update(engine, C);
+
+ rv3d->render_engine = engine;
+ }
+
+ /* setup view matrices */
+ VP_legacy_view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, NULL, NULL);
+
+ /* background draw */
+ ED_region_pixelspace(ar);
+
+ if (clip_border) {
+ /* for border draw, we only need to clear a subset of the 3d view */
+ if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) {
+ glGetIntegerv(GL_SCISSOR_BOX, scissor);
+ glScissor(border_rect->xmin, border_rect->ymin,
+ BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect));
+ }
+ else {
+ return false;
+ }
+ }
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ bool show_image = false;
+ {
+ Camera *cam = ED_view3d_camera_data_get(v3d, rv3d);
+ if (cam->flag & CAM_SHOW_BG_IMAGE) {
+ show_image = true;
+ view3d_draw_bgpic_test(scene, ar, v3d, false, true);
+ }
+ else {
+ imm_draw_box_checker_2d(0, 0, ar->winx, ar->winy);
+ }
+ }
+
+ if (show_image) {
+ view3d_draw_bgpic_test(scene, ar, v3d, false, true);
+ }
+ else {
+ imm_draw_box_checker_2d(0, 0, ar->winx, ar->winy);
+ }
+
+ /* render result draw */
+ type = rv3d->render_engine->type;
+ type->render_to_view(rv3d->render_engine, C);
+
+ if (show_image) {
+ view3d_draw_bgpic_test(scene, ar, v3d, true, true);
+ }
+
+ if (clip_border) {
+ /* restore scissor as it was before */
+ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ }
+
+ return true;
+}
+
+static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border)
+{
+ float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
+
+ if (!rv3d->render_engine || !rv3d->render_engine->text[0])
+ return;
+
+ if (render_border) {
+ /* draw darkened background color. no alpha because border render does
+ * partial redraw and will not redraw the region behind this info bar */
+ float alpha = 1.0f - fill_color[3];
+ Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
+
+ if (camera) {
+ if (camera->flag & CAM_SHOWPASSEPARTOUT) {
+ alpha *= (1.0f - camera->passepartalpha);
+ }
+ }
+
+ UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color);
+ mul_v3_fl(fill_color, alpha);
+ fill_color[3] = 1.0f;
+ }
+
+ ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true);
+}
+
+#ifdef WITH_GAMEENGINE
+static void update_lods(Scene *scene, float camera_pos[3])
+{
+ Scene *sce_iter;
+ Base *base;
+
+ for (SETLOOPER(scene, sce_iter, base)) {
+ Object *ob = base->object;
+ BKE_object_lod_update(ob, camera_pos);
+ }
+}
+#endif
+
+static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, ViewLayer *view_layer, View3D *v3d,
+ ARegion *ar, const char **grid_unit)
+{
+ wmWindow *win = CTX_wm_window(C);
+ EvaluationContext eval_ctx;
+ RegionView3D *rv3d = ar->regiondata;
+ unsigned int lay_used = v3d->lay_used;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ /* post processing */
+ bool do_compositing = false;
+
+ /* shadow buffers, before we setup matrices */
+ if (draw_glsl_material(scene, view_layer, NULL, v3d, v3d->drawtype))
+ gpu_update_lamps_shadows_world(&eval_ctx, scene, v3d);
+
+ /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */
+ if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) {
+ rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE;
+ GPU_default_lights();
+ }
+
+ /* setup the view matrix */
+ if (VP_legacy_view3d_stereo3d_active(win, scene, v3d, rv3d)) {
+ VP_legacy_view3d_stereo3d_setup(&eval_ctx, scene, v3d, ar);
+ }
+ else {
+ VP_legacy_view3d_main_region_setup_view(&eval_ctx, scene, v3d, ar, NULL, NULL);
+ }
+
+ rv3d->rflag &= ~RV3D_IS_GAME_ENGINE;
+#ifdef WITH_GAMEENGINE
+ if (STREQ(scene->view_render.engine_id, RE_engine_id_BLENDER_GAME)) {
+ rv3d->rflag |= RV3D_IS_GAME_ENGINE;
+
+ /* Make sure LoDs are up to date */
+ update_lods(scene, rv3d->viewinv[3]);
+ }
+#endif
+
+ /* framebuffer fx needed, we need to draw offscreen first */
+ if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) {
+ BKE_screen_gpu_fx_validate(&v3d->fx_settings);
+ GPUFXSettings fx_settings = v3d->fx_settings;
+ if (!rv3d->compositor)
+ rv3d->compositor = GPU_fx_compositor_create();
+
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera)
+ BKE_camera_to_gpu_dof(v3d->camera, &fx_settings);
+ else {
+ fx_settings.dof = NULL;
+ }
+
+ do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings);
+ }
+
+ /* enables anti-aliasing for 3D view drawing */
+ if (win->multisamples != USER_MULTISAMPLE_NONE) {
+ glEnable(GL_MULTISAMPLE);
+ }
+
+ /* main drawing call */
+ view3d_draw_objects(C, &eval_ctx, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL);
+
+ /* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */
+ /* TODO depth culling manipulators is not yet supported, just drawing _3D here, should
+ * later become _IN_SCENE (and draw _3D separate) */
+ WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_3D);
+
+ /* post process */
+ if (do_compositing) {
+ GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
+ }
+
+ /* Disable back anti-aliasing */
+ if (win->multisamples != USER_MULTISAMPLE_NONE) {
+ glDisable(GL_MULTISAMPLE);
+ }
+
+ if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */
+ /* find header and force tag redraw */
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ ED_region_tag_redraw(ar_header); /* can be NULL */
+ }
+
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ BDR_drawSketch(C);
+ }
+}
+
+static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
+ ARegion *ar, View3D *v3d,
+ const char *grid_unit, bool render_border)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ RegionView3D *rv3d = ar->regiondata;
+ rcti rect;
+
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ ED_region_visible_rect(ar, &rect);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ VP_drawviewborder(scene, ar, v3d);
+ }
+ else if (v3d->flag2 & V3D_RENDER_BORDER) {
+ VP_drawrenderborder(ar, v3d);
+ }
+
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
+ ED_gpencil_draw_view3d(wm, scene, view_layer, v3d, ar, false);
+ }
+
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ VP_legacy_drawcursor(scene, view_layer, ar, v3d); /* 3D cursor */
+
+ if (U.uiflag & USER_SHOW_ROTVIEWICON)
+ VP_legacy_draw_view_axis(rv3d, &rect);
+ else
+ draw_view_icon(rv3d, &rect);
+
+ if (U.uiflag & USER_DRAWVIEWINFO) {
+ Object *ob = OBACT(view_layer);
+ VP_legacy_draw_selected_name(scene, ob, &rect);
+ }
+ }
+
+ if (rv3d->render_engine) {
+ view3d_main_region_draw_engine_info(v3d, rv3d, ar, render_border);
+ return;
+ }
+
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
+ ED_scene_draw_fps(scene, &rect);
+ }
+ else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
+ VP_legacy_draw_viewport_name(ar, v3d, &rect);
+ }
+
+ if (grid_unit) { /* draw below the viewport name */
+ char numstr[32] = "";
+
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+ if (v3d->grid != 1.0f) {
+ BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
+ }
+
+ BLF_draw_default_ascii(rect.xmin + U.widget_unit,
+ rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
+ numstr[0] ? numstr : grid_unit, sizeof(numstr));
+ }
+ }
+}
+
+void view3d_main_region_draw_legacy(const bContext *C, ARegion *ar)
+{
+ EvaluationContext eval_ctx;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ const char *grid_unit = NULL;
+ rcti border_rect;
+
+ /* if we only redraw render border area, skip opengl draw and also
+ * don't do scissor because it's already set */
+ bool render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect);
+ bool clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect));
+
+ gpuPushProjectionMatrix();
+ gpuLoadIdentityProjectionMatrix();
+ gpuPushMatrix();
+ gpuLoadIdentity();
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ /* draw viewport using opengl */
+ if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene) || clip_border) {
+ VP_view3d_main_region_clear(scene, v3d, ar); /* background */
+ view3d_main_region_draw_objects(C, scene, view_layer, v3d, ar, &grid_unit);
+
+ if (G.debug & G_DEBUG_SIMDATA)
+ draw_sim_debug_data(scene, v3d, ar);
+
+ glDisable(GL_DEPTH_TEST);
+ ED_region_pixelspace(ar);
+ }
+
+ /* draw viewport using external renderer */
+ if (v3d->drawtype == OB_RENDER) {
+ view3d_main_region_draw_engine(C, &eval_ctx, scene, ar, v3d, clip_border, &border_rect);
+ }
+
+ VP_legacy_view3d_main_region_setup_view(&eval_ctx, scene, v3d, ar, NULL, NULL);
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ ED_region_pixelspace(ar);
+
+ WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D);
+
+ view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border);
+
+ gpuPopProjectionMatrix();
+ gpuPopMatrix();
+
+ v3d->flag |= V3D_INVALID_BACKBUF;
+
+ BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_transp));
+ BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xray));
+ BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xraytransp));
+}
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Deprecated Interface
+ *
+ * New viewport sometimes has a check for new/old viewport code.
+ * Use these functions so new viewport can *optionally* call.
+ *
+ * \{ */
+
+
+void VP_deprecated_view3d_draw_objects(
+ const bContext *C,
+ const EvaluationContext *eval_ctx,
+ Scene *scene, View3D *v3d, ARegion *ar,
+ const char **grid_unit,
+ const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
+{
+ view3d_draw_objects(C, eval_ctx, scene, v3d, ar, grid_unit, do_bgpic, draw_offscreen, fx);
+}
+
+void VP_deprecated_gpu_update_lamps_shadows_world(const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d)
+{
+ gpu_update_lamps_shadows_world(eval_ctx, scene, v3d);
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 5203e0617ee..0dba87bef25 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -34,6 +34,7 @@
#include <float.h>
#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -51,6 +52,7 @@
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_font.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -58,11 +60,10 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_action.h"
-#include "BKE_depsgraph.h" /* for ED_view3d_camera_lock_sync */
+#include "DEG_depsgraph.h"
#include "BIF_gl.h"
-#include "BIF_glutil.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -79,6 +80,8 @@
#include "ED_gpencil.h"
#include "ED_view3d.h"
+#include "DEG_depsgraph_query.h"
+
#include "UI_resources.h"
#include "PIL_time.h" /* smoothview */
@@ -163,7 +166,7 @@ bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
ob_update = v3d->camera;
while (ob_update) {
- DAG_id_tag_update(&ob_update->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob_update->id, OB_RECALC_OB);
WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update);
ob_update = ob_update->parent;
}
@@ -175,7 +178,7 @@ bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all);
- DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
+ DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera);
}
@@ -621,7 +624,8 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
bool is_set = false;
Scene *scene = CTX_data_scene(C);
- Object *ob_act = OBACT;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_act = OBACT(view_layer);
if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) &&
/* with weight-paint + pose-mode, fall through to using calculateTransformCenter */
@@ -658,14 +662,13 @@ 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;
unsigned int tot = 0;
float select_center[3];
zero_v3(select_center);
- for (base = FIRSTBASE; base; base = base->next) {
- if (TESTBASE(v3d, base)) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (TESTBASE(base)) {
/* use the boundbox if we can */
Object *ob = base->object;
@@ -741,14 +744,18 @@ static void viewops_data_create_ex(
/* we need the depth info before changing any viewport options */
if (orbit_mode & VIEWOPS_ORBIT_DEPTH) {
+ EvaluationContext eval_ctx;
+ struct Depsgraph *graph = CTX_data_depsgraph(C);
float fallback_depth_pt[3];
+ CTX_data_eval_ctx(C, &eval_ctx);
+
view3d_operator_needs_opengl(C); /* needed for zbuf drawing */
negate_v3_v3(fallback_depth_pt, rv3d->ofs);
vod->use_dyn_ofs = ED_view3d_autodist(
- vod->scene, vod->ar, vod->v3d,
+ &eval_ctx, graph, vod->ar, vod->v3d,
event->mval, vod->dyn_ofs, true, fallback_depth_pt);
}
else {
@@ -866,8 +873,9 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even
static void viewops_data_free(bContext *C, wmOperator *op)
{
ARegion *ar;
+#if 0
Paint *p = BKE_paint_get_active_from_context(C);
-
+#endif
if (op->customdata) {
ViewOpsData *vod = op->customdata;
ar = vod->ar;
@@ -883,7 +891,9 @@ static void viewops_data_free(bContext *C, wmOperator *op)
ar = CTX_wm_region(C);
}
+#if 0
if (p && (p->flags & PAINT_FAST_NAVIGATE))
+#endif
ED_region_tag_redraw(ar);
}
/** \} */
@@ -2980,6 +2990,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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Base *base;
float *curs;
const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
@@ -3003,8 +3014,8 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
INIT_MINMAX(min, max);
}
- for (base = scene->base.first; base; base = base->next) {
- if (BASE_VISIBLE(v3d, base)) {
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_VISIBLE(base)) {
changed = true;
if (skip_camera && base->object == v3d->camera) {
@@ -3064,9 +3075,12 @@ static int viewselected_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
bGPdata *gpd = CTX_data_gpencil_data(C);
const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE));
- Object *ob = OBACT;
+ const bool is_face_map = ((is_gp_edit == false) && ar->manipulator_map &&
+ WM_manipulatormap_is_any_selected(ar->manipulator_map));
+ Object *ob = OBACT(view_layer);
Object *obedit = CTX_data_edit_object(C);
float min[3], max[3];
bool ok = false, ok_dist = true;
@@ -3077,8 +3091,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
INIT_MINMAX(min, max);
-
- if (is_gp_edit) {
+ if (is_gp_edit || is_face_map) {
ob = NULL;
}
@@ -3086,8 +3099,8 @@ static int viewselected_exec(bContext *C, wmOperator *op)
/* 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;
- for (base = scene->base.first; base; base = base->next) {
- if (TESTBASELIB(v3d, base)) {
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if (TESTBASELIB(base)) {
if (base->object->type == OB_ARMATURE)
if (base->object->mode & OB_MODE_POSE)
break;
@@ -3110,6 +3123,9 @@ static int viewselected_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
}
+ else if (is_face_map) {
+ ok = WM_manipulatormap_minmax(ar->manipulator_map, true, true, min, max);
+ }
else if (obedit) {
ok = ED_view3d_minmax_verts(obedit, min, max); /* only selected */
}
@@ -3120,7 +3136,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
ok = paintface_minmax(ob, min, max);
}
else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
- ok = PE_minmax(scene, min, max);
+ ok = PE_minmax(scene, view_layer, min, max);
}
else if (ob &&
(ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
@@ -3132,8 +3148,8 @@ static int viewselected_exec(bContext *C, wmOperator *op)
}
else {
Base *base;
- for (base = FIRSTBASE; base; base = base->next) {
- if (TESTBASE(v3d, base)) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (TESTBASE(base)) {
if (skip_camera && base->object == v3d->camera) {
continue;
@@ -3310,18 +3326,21 @@ static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *ev
{
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
if (rv3d) {
+ EvaluationContext eval_ctx;
+ struct Depsgraph *graph = CTX_data_depsgraph(C);
float new_ofs[3];
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
+ CTX_data_eval_ctx(C, &eval_ctx);
+
ED_view3d_smooth_view_force_finish(C, v3d, ar);
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(scene, ar, v3d, event->mval, new_ofs, false, NULL)) {
+ if (ED_view3d_autodist(&eval_ctx, graph, ar, v3d, event->mval, new_ofs, false, NULL)) {
/* pass */
}
else {
@@ -3576,10 +3595,10 @@ void VIEW3D_OT_clear_render_border(wmOperatorType *ot)
static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Scene *scene = CTX_data_scene(C);
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
/* Zooms in on a border drawn by the user */
@@ -3592,13 +3611,14 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
float new_ofs[3];
/* ZBuffer depth vars */
- bglMats mats;
float depth_close = FLT_MAX;
- double cent[2], p[3];
+ float p[3];
/* note; otherwise opengl won't work */
view3d_operator_needs_opengl(C);
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* get border select values using rna */
WM_operator_properties_border_to_rcti(op, &rect);
@@ -3608,8 +3628,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
ED_view3d_dist_range_get(v3d, dist_range);
/* Get Z Depths, needed for perspective, nice for ortho */
- bgl_get_mats(&mats);
- ED_view3d_draw_depth(scene, ar, v3d, true);
+ ED_view3d_draw_depth(&eval_ctx, CTX_data_depsgraph(C), ar, v3d, true);
{
/* avoid allocating the whole depth buffer */
@@ -3624,11 +3643,11 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
MEM_SAFE_FREE(depth_temp.depths);
}
- cent[0] = (((double)rect.xmin) + ((double)rect.xmax)) / 2;
- cent[1] = (((double)rect.ymin) + ((double)rect.ymax)) / 2;
+ float centx = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
+ float centy = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
if (rv3d->is_persp) {
- double p_corner[3];
+ float p_corner[3];
/* no depths to use, we cant do anything! */
if (depth_close == FLT_MAX) {
@@ -3636,23 +3655,14 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* convert border to 3d coordinates */
- if ((!gluUnProject(cent[0], cent[1], depth_close,
- mats.modelview, mats.projection, (GLint *)mats.viewport,
- &p[0], &p[1], &p[2])) ||
- (!gluUnProject((double)rect.xmin, (double)rect.ymin, depth_close,
- mats.modelview, mats.projection, (GLint *)mats.viewport,
- &p_corner[0], &p_corner[1], &p_corner[2])))
+ if ((!ED_view3d_unproject(ar, centx, centy, depth_close, p)) ||
+ (!ED_view3d_unproject(ar, rect.xmin, rect.ymin, depth_close, p_corner)))
{
return OPERATOR_CANCELLED;
}
- dvec[0] = p[0] - p_corner[0];
- dvec[1] = p[1] - p_corner[1];
- dvec[2] = p[2] - p_corner[2];
-
- new_ofs[0] = -p[0];
- new_ofs[1] = -p[1];
- new_ofs[2] = -p[2];
+ sub_v3_v3v3(dvec, p, p_corner);
+ negate_v3_v3(new_ofs, p);
new_dist = len_v3(dvec);
@@ -3667,13 +3677,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
new_dist = rv3d->dist;
/* convert the drawn rectangle into 3d space */
- if (depth_close != FLT_MAX && gluUnProject(cent[0], cent[1], depth_close,
- mats.modelview, mats.projection, (GLint *)mats.viewport,
- &p[0], &p[1], &p[2]))
- {
- new_ofs[0] = -p[0];
- new_ofs[1] = -p[1];
- new_ofs[2] = -p[2];
+ if (depth_close != FLT_MAX && ED_view3d_unproject(ar, centx, centy, depth_close, p)) {
+ negate_v3_v3(new_ofs, p);
}
else {
float mval_f[2];
@@ -3910,6 +3915,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
ARegion *ar;
RegionView3D *rv3d;
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
static int perspo = RV3D_PERSP;
int viewnum, nextperspo;
bool align_active;
@@ -3944,7 +3950,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
/* lastview - */
if (rv3d->persp != RV3D_CAMOB) {
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
if (!rv3d->smooth_timer) {
/* store settings of current view before allowing overwriting with camera view
@@ -3979,7 +3985,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
v3d->camera = ob;
if (v3d->camera == NULL)
- v3d->camera = BKE_scene_camera_find(scene);
+ v3d->camera = BKE_view_layer_camera_find(view_layer);
/* couldnt find any useful camera, bail out */
if (v3d->camera == NULL)
@@ -4511,11 +4517,11 @@ void VIEW3D_OT_navigate(wmOperatorType *ot)
/* ******************** add background image operator **************** */
-static BGpic *background_image_add(bContext *C)
+static CameraBGImage *background_image_add(bContext *C)
{
- View3D *v3d = CTX_wm_view3d(C);
+ Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
- return ED_view3D_background_image_new(v3d);
+ return BKE_camera_background_image_new(cam);
}
static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op))
@@ -4527,9 +4533,9 @@ static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op))
static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- View3D *v3d = CTX_wm_view3d(C);
+ Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
Image *ima;
- BGpic *bgpic;
+ CameraBGImage *bgpic;
ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
/* may be NULL, continue anyway */
@@ -4537,10 +4543,10 @@ static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEven
bgpic = background_image_add(C);
bgpic->ima = ima;
- v3d->flag |= V3D_DISPBGPICS;
-
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
-
+ cam->flag |= CAM_SHOW_BG_IMAGE;
+
+ WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
+
return OPERATOR_FINISHED;
}
@@ -4556,7 +4562,7 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot)
/* api callbacks */
ot->invoke = background_image_add_invoke;
ot->exec = background_image_add_exec;
- ot->poll = ED_operator_view3d_active;
+ ot->poll = ED_operator_camera;
/* flags */
ot->flag = OPTYPE_UNDO;
@@ -4572,21 +4578,22 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot)
/* ***** remove image operator ******* */
static int background_image_remove_exec(bContext *C, wmOperator *op)
{
- View3D *v3d = CTX_wm_view3d(C);
+ Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
const int index = RNA_int_get(op->ptr, "index");
- BGpic *bgpic_rem = BLI_findlink(&v3d->bgpicbase, index);
+ CameraBGImage *bgpic_rem = BLI_findlink(&cam->bg_images, index);
if (bgpic_rem) {
- if (bgpic_rem->source == V3D_BGPIC_IMAGE) {
+ if (bgpic_rem->source == CAM_BGIMG_SOURCE_IMAGE) {
id_us_min((ID *)bgpic_rem->ima);
}
- else if (bgpic_rem->source == V3D_BGPIC_MOVIE) {
+ else if (bgpic_rem->source == CAM_BGIMG_SOURCE_MOVIE) {
id_us_min((ID *)bgpic_rem->clip);
}
- ED_view3D_background_image_remove(v3d, bgpic_rem);
+ BKE_camera_background_image_remove(cam, bgpic_rem);
+
+ WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
return OPERATOR_FINISHED;
}
else {
@@ -4604,7 +4611,7 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot)
/* api callbacks */
ot->exec = background_image_remove_exec;
- ot->poll = ED_operator_view3d_active;
+ ot->poll = ED_operator_camera;
/* flags */
ot->flag = 0;
@@ -4638,9 +4645,8 @@ void ED_view3d_clipping_local(RegionView3D *rv3d, float mat[4][4])
static int view3d_clipping_exec(bContext *C, wmOperator *op)
{
+ ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- ViewContext vc;
- bglMats mats;
rcti rect;
WM_operator_properties_border_to_rcti(op, &rect);
@@ -4648,12 +4654,8 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op)
rv3d->rflag |= RV3D_CLIPPING;
rv3d->clipbb = MEM_callocN(sizeof(BoundBox), "clipbb");
- /* note; otherwise opengl won't work */
- view3d_operator_needs_opengl(C);
-
- view3d_set_viewcontext(C, &vc);
- view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */
- ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, &mats, &rect);
+ /* NULL object because we don't want it in object space */
+ ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, ar, NULL, &rect);
return OPERATOR_FINISHED;
}
@@ -4705,7 +4707,6 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
/* note: cannot use event->mval here (called by object_add() */
void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
{
- Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
@@ -4727,9 +4728,15 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
}
if (U.uiflag & USER_ZBUF_CURSOR) { /* maybe this should be accessed some other way */
+ EvaluationContext eval_ctx;
+ struct Depsgraph *graph = CTX_data_depsgraph(C);
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(scene, ar, v3d, mval, fp, true, NULL))
+ if (ED_view3d_autodist(&eval_ctx, graph, ar, v3d, mval, fp, true, NULL)) {
depth_used = true;
+ }
}
if (depth_used == false) {
@@ -4808,45 +4815,6 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
/* ***************** manipulator op ******************* */
-
-static int manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- View3D *v3d = CTX_wm_view3d(C);
-
- if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return OPERATOR_PASS_THROUGH;
- if (!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return OPERATOR_PASS_THROUGH;
-
- /* note; otherwise opengl won't work */
- view3d_operator_needs_opengl(C);
-
- if (BIF_do_manipulator(C, event, op) == 0)
- return OPERATOR_PASS_THROUGH;
-
- return OPERATOR_FINISHED;
-}
-
-void VIEW3D_OT_manipulator(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "3D Manipulator";
- ot->description = "Manipulate selected item by axis";
- ot->idname = "VIEW3D_OT_manipulator";
-
- /* api callbacks */
- ot->invoke = manipulator_invoke;
-
- ot->poll = ED_operator_view3d_active;
-
- /* properties to pass to transform */
- Transform_Properties(ot, P_CONSTRAINT);
-
- prop = RNA_def_boolean(ot->srna, "use_planar_constraint", false, "Planar Constraint", "Limit the transformation to the "
- "two axes that have not been clicked (translate/scale only)");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
-}
-
static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
View3D *v3d = CTX_wm_view3d(C);
@@ -4950,22 +4918,17 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg
* \param fallback_depth_pt: Use this points depth when no depth can be found.
*/
bool ED_view3d_autodist(
- Scene *scene, ARegion *ar, View3D *v3d,
+ const EvaluationContext *eval_ctx, struct Depsgraph *graph, ARegion *ar, View3D *v3d,
const int mval[2], float mouse_worldloc[3],
const bool alphaoverride, const float fallback_depth_pt[3])
{
- bglMats mats; /* ZBuffer depth vars */
float depth_close;
- double cent[2], p[3];
int margin_arr[] = {0, 2, 4};
int i;
bool depth_ok = false;
/* Get Z Depths, needed for perspective, nice for ortho */
- ED_view3d_draw_depth(scene, ar, v3d, alphaoverride);
-
- /* call after in case settings have been modified since last drawing, see: T47089 */
- bgl_get_mats(&mats);
+ ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, alphaoverride);
/* Attempt with low margin's first */
i = 0;
@@ -4975,15 +4938,10 @@ bool ED_view3d_autodist(
} while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
if (depth_ok) {
- cent[0] = (double)mval[0] + 0.5;
- cent[1] = (double)mval[1] + 0.5;
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
- if (gluUnProject(cent[0], cent[1], depth_close,
- mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
- {
- mouse_worldloc[0] = (float)p[0];
- mouse_worldloc[1] = (float)p[1];
- mouse_worldloc[2] = (float)p[2];
+ if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc)) {
return true;
}
}
@@ -4997,16 +4955,21 @@ bool ED_view3d_autodist(
}
}
-void ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode)
+void ED_view3d_autodist_init(
+ const EvaluationContext *eval_ctx, struct Depsgraph *graph,
+ ARegion *ar, View3D *v3d, int mode)
{
/* Get Z Depths, needed for perspective, nice for ortho */
switch (mode) {
case 0:
- ED_view3d_draw_depth(scene, ar, v3d, true);
+ ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, true);
break;
case 1:
- ED_view3d_draw_depth_gpencil(scene, ar, v3d);
+ {
+ Scene *scene = DEG_get_evaluated_scene(graph);
+ ED_view3d_draw_depth_gpencil(eval_ctx, scene, ar, v3d);
break;
+ }
}
}
@@ -5014,9 +4977,7 @@ void ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode)
bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3],
int margin, float *force_depth)
{
- bglMats mats; /* ZBuffer depth vars, could cache? */
float depth;
- double cent[2], p[3];
/* Get Z Depths, needed for perspective, nice for ortho */
if (force_depth)
@@ -5027,21 +4988,9 @@ bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_world
if (depth == FLT_MAX)
return false;
- cent[0] = (double)mval[0] + 0.5;
- cent[1] = (double)mval[1] + 0.5;
-
- bgl_get_mats(&mats);
-
- if (!gluUnProject(cent[0], cent[1], depth,
- mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
- {
- return false;
- }
-
- mouse_worldloc[0] = (float)p[0];
- mouse_worldloc[1] = (float)p[1];
- mouse_worldloc[2] = (float)p[2];
- return true;
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
+ return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc);
}
bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth)
@@ -5223,6 +5172,7 @@ void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist,
void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist)
{
float mat[4][4];
+
ED_view3d_to_m4(mat, ofs, quat, dist);
BKE_object_apply_mat4(ob, mat, true, true);
}
@@ -5239,43 +5189,6 @@ void ED_view3d_lastview_store(RegionView3D *rv3d)
}
}
-BGpic *ED_view3D_background_image_new(View3D *v3d)
-{
- BGpic *bgpic = MEM_callocN(sizeof(BGpic), "Background Image");
-
- bgpic->rotation = 0.0f;
- bgpic->size = 5.0f;
- bgpic->blend = 0.5f;
- bgpic->iuser.fie_ima = 2;
- bgpic->iuser.ok = 1;
- bgpic->view = 0; /* 0 for all */
- bgpic->flag |= V3D_BGPIC_EXPANDED;
-
- BLI_addtail(&v3d->bgpicbase, bgpic);
-
- return bgpic;
-}
-
-void ED_view3D_background_image_remove(View3D *v3d, BGpic *bgpic)
-{
- BLI_remlink(&v3d->bgpicbase, bgpic);
-
- MEM_freeN(bgpic);
-}
-
-void ED_view3D_background_image_clear(View3D *v3d)
-{
- BGpic *bgpic = v3d->bgpicbase.first;
-
- while (bgpic) {
- BGpic *next_bgpic = bgpic->next;
-
- ED_view3D_background_image_remove(v3d, bgpic);
-
- bgpic = next_bgpic;
- }
-}
-
void ED_view3D_lock_clear(View3D *v3d)
{
v3d->ob_centre = NULL;
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index eda780d01a7..5e7eddb1c22 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -56,6 +56,8 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_immediate.h"
+
#include "view3d_intern.h" /* own include */
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
@@ -257,36 +259,45 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
x2 = xoff + 0.55f * fly->width;
y2 = yoff + 0.55f * fly->height;
- UI_ThemeColor(TH_VIEW_OVERLAY);
- glBegin(GL_LINES);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+
+ immBegin(GWN_PRIM_LINES, 16);
+
/* bottom left */
- glVertex2f(x1, y1);
- glVertex2f(x1, y1 + 5);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y1 + 5);
- glVertex2f(x1, y1);
- glVertex2f(x1 + 5, y1);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1 + 5, y1);
/* top right */
- glVertex2f(x2, y2);
- glVertex2f(x2, y2 - 5);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2, y2 - 5);
- glVertex2f(x2, y2);
- glVertex2f(x2 - 5, y2);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2 - 5, y2);
/* top left */
- glVertex2f(x1, y2);
- glVertex2f(x1, y2 - 5);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x1, y2 - 5);
- glVertex2f(x1, y2);
- glVertex2f(x1 + 5, y2);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x1 + 5, y2);
/* bottom right */
- glVertex2f(x2, y1);
- glVertex2f(x2, y1 + 5);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2, y1 + 5);
+
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2 - 5, y1);
- glVertex2f(x2, y1);
- glVertex2f(x2 - 5, y1);
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
static void fly_update_header(bContext *C, wmOperator *op, FlyInfo *fly)
@@ -406,7 +417,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
}
fly->v3d_camera_control = ED_view3d_cameracontrol_acquire(
- fly->scene, fly->v3d, fly->rv3d,
+ C, fly->scene, fly->v3d, fly->rv3d,
(U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
/* calculate center */
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 11dc4d10f2a..a1dc2a21477 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -41,11 +41,12 @@
#include "BLT_translation.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -71,11 +72,10 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event);
/* XXX quickly ported across */
static void handle_view3d_lock(bContext *C)
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = CTX_wm_view3d(C);
-
+
if (v3d != NULL && sa != NULL) {
if (v3d->localvd == NULL && v3d->scenelock && sa->spacetype == SPACE_VIEW3D) {
/* copy to scene */
@@ -83,10 +83,6 @@ static void handle_view3d_lock(bContext *C)
scene->layact = v3d->layact;
scene->camera = v3d->camera;
- /* not through notifier, listener don't have context
- * and non-open screens or spaces need to be updated too */
- BKE_screen_view3d_main_sync(&bmain->screen, scene);
-
/* notifiers for scene update */
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
}
@@ -97,7 +93,7 @@ static void handle_view3d_lock(bContext *C)
* layer code is on three levels actually:
* - here for operator
* - uiTemplateLayers in interface/ code for buttons
- * - ED_view3d_scene_layer_set for RNA
+ * - ED_view3d_view_layer_set for RNA
*/
static void view3d_layers_editmode_ensure(Scene *scene, View3D *v3d)
{
@@ -172,7 +168,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
if (v3d->scenelock) handle_view3d_lock(C);
- DAG_on_visible_update(CTX_data_main(C), false);
+ DEG_on_visible_update(CTX_data_main(C), false);
ED_area_tag_redraw(sa);
@@ -284,15 +280,16 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
ToolSettings *ts = CTX_data_tool_settings(C);
PointerRNA v3dptr, toolsptr, sceneptr;
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
Object *obedit = CTX_data_edit_object(C);
bGPdata *gpd = CTX_data_gpencil_data(C);
uiBlock *block;
uiLayout *row;
- bool is_paint = false;
- int modeselect;
+ bool is_paint = ob && !(gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) &&
+ ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT);
RNA_pointer_create(&screen->id, &RNA_SpaceView3D, v3d, &v3dptr);
RNA_pointer_create(&scene->id, &RNA_ToolSettings, ts, &toolsptr);
@@ -303,39 +300,6 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
/* other buttons: */
UI_block_emboss_set(block, UI_EMBOSS);
-
- /* mode */
- if ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
- modeselect = OB_MODE_GPENCIL;
- }
- else if (ob) {
- modeselect = ob->mode;
- is_paint = ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT);
- }
- else {
- modeselect = OB_MODE_OBJECT;
- }
-
- row = uiLayoutRow(layout, false);
- {
- const EnumPropertyItem *item = rna_enum_object_mode_items;
- const char *name = "";
- int icon = ICON_OBJECT_DATAMODE;
-
- while (item->identifier) {
- if (item->value == modeselect && item->identifier[0]) {
- name = IFACE_(item->name);
- icon = item->icon;
- break;
- }
- item++;
- }
-
- uiItemMenuEnumO(row, C, "OBJECT_OT_mode_set", "mode", name, icon);
- }
-
- /* Draw type */
- uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
row = uiLayoutRow(layout, true);
uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
@@ -364,18 +328,13 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
/* Transform widget / manipulators */
row = uiLayoutRow(layout, true);
uiItemR(row, &v3dptr, "show_manipulator", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
- if (v3d->twflag & V3D_USE_MANIPULATOR) {
+ if (v3d->twflag & V3D_MANIPULATOR_DRAW) {
uiItemR(row, &v3dptr, "transform_manipulators", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
}
uiItemR(row, &v3dptr, "transform_orientation", 0, "", ICON_NONE);
}
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 7a106a27833..a7368a84eb6 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -37,7 +37,9 @@
struct ARegion;
struct ARegionType;
+struct Base;
struct BoundBox;
+struct Gwn_Batch;
struct DerivedMesh;
struct Object;
struct SmokeDomainSettings;
@@ -46,9 +48,12 @@ struct bContext;
struct bMotionPath;
struct bPoseChannel;
struct Mesh;
+struct ViewLayer;
struct wmOperatorType;
-struct wmWindowManager;
struct wmKeyConfig;
+struct wmManipulatorGroupType;
+struct wmManipulatorType;
+struct wmWindowManager;
/* drawing flags: */
enum {
@@ -99,7 +104,6 @@ void VIEW3D_OT_view_orbit(struct wmOperatorType *ot);
void VIEW3D_OT_view_roll(struct wmOperatorType *ot);
void VIEW3D_OT_clip_border(struct wmOperatorType *ot);
void VIEW3D_OT_cursor3d(struct wmOperatorType *ot);
-void VIEW3D_OT_manipulator(struct wmOperatorType *ot);
void VIEW3D_OT_enable_manipulator(struct wmOperatorType *ot);
void VIEW3D_OT_render_border(struct wmOperatorType *ot);
void VIEW3D_OT_clear_render_border(struct wmOperatorType *ot);
@@ -142,13 +146,29 @@ 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_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag);
-
-bool draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char dt);
-void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline);
-void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob);
-void drawaxes(const float viewmat_local[4][4], float size, char drawtype);
+void draw_object(
+ const struct EvaluationContext *eval_ctx, Scene *scene, struct ViewLayer *view_layer, struct ARegion *ar, View3D *v3d,
+ struct Base *base, const short dflag);
+void draw_object_select(
+ const struct EvaluationContext *eval_ctx, Scene *scene, struct ViewLayer *view_layer, struct ARegion *ar, View3D *v3d,
+ Base *base, const short dflag);
+
+void draw_mesh_object_outline(View3D *v3d, Object *ob, struct DerivedMesh *dm, const unsigned char ob_wire_col[4]);
+
+bool draw_glsl_material(Scene *scene, struct ViewLayer *view_layer, struct Object *ob, View3D *v3d, const char dt);
+void draw_object_instance(const struct EvaluationContext *eval_ctx, Scene *scene, struct ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline, const float wire_col[4]);
+void draw_object_backbufsel(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob);
+
+void draw_object_wire_color(Scene *scene, struct ViewLayer *, 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],
+ const bool is_obact);
+void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const short dflag, const unsigned char ob_wire_col[4]);
+void drawspeaker(const unsigned char ob_wire_col[3]);
+void draw_bounding_volume(struct Object *ob, char type, const unsigned char ob_wire_col[4]);
+void draw_rigidbody_shape(struct Object *ob, const unsigned char ob_wire_col[4]);
void view3d_cached_text_draw_begin(void);
void view3d_cached_text_draw_add(const float co[3],
@@ -169,12 +189,13 @@ enum {
int view3d_effective_drawtype(const struct View3D *v3d);
/* drawarmature.c */
-bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
- const short dt, const short dflag, const unsigned char ob_wire_col[4],
- const bool is_outline);
+bool draw_armature(
+ const struct EvaluationContext *eval_ctx, Scene *scene, struct ViewLayer *view_layer, View3D *v3d, ARegion *ar, Base *base,
+ const short dt, const short dflag, const unsigned char ob_wire_col[4],
+ const bool is_outline);
/* drawmesh.c */
-void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
+void draw_mesh_textured(Scene *scene, struct ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d,
struct Object *ob, struct DerivedMesh *dm, const int draw_flags);
void draw_mesh_face_select(
struct RegionView3D *rv3d, struct Mesh *me, struct DerivedMesh *dm,
@@ -195,16 +216,28 @@ void draw_sim_debug_data(Scene *scene, View3D *v3d, ARegion *ar);
/* view3d_draw.c */
void view3d_main_region_draw(const struct bContext *C, struct ARegion *ar);
-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 view3d_draw_region_info(const struct bContext *C, struct ARegion *ar, const int offset);
+
+void ED_view3d_draw_depth(
+ const struct EvaluationContext *eval_ctx, struct Depsgraph *graph,
+ struct ARegion *ar, View3D *v3d, bool alphaoverride);
+
+/* view3d_draw_legacy.c */
+void view3d_main_region_draw_legacy(const struct bContext *C, struct ARegion *ar);
+void ED_view3d_draw_depth_gpencil(const struct EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d);
+
void ED_view3d_draw_select_loop(
- ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar,
+ const struct EvaluationContext *eval_ctx, ViewContext *vc, Scene *scene, struct ViewLayer *view_layer, View3D *v3d, ARegion *ar,
bool use_obedit_skip, bool use_nearest);
-void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag);\
+void ED_view3d_draw_depth_loop(
+ const struct EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d);
+
+void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
+ const bool do_foreground, const bool do_camera_frame);
+
+void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag);
-void circf(float x, float y, float rad);
-void circ(float x, float y, float rad);
void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect);
float view3d_depth_near(struct ViewDepths *d);
@@ -219,7 +252,6 @@ void VIEW3D_OT_smoothview(struct wmOperatorType *ot);
void VIEW3D_OT_camera_to_view(struct wmOperatorType *ot);
void VIEW3D_OT_camera_to_view_selected(struct wmOperatorType *ot);
void VIEW3D_OT_object_as_camera(struct wmOperatorType *ot);
-void VIEW3D_OT_localview(struct wmOperatorType *ot);
void VIEW3D_OT_game_start(struct wmOperatorType *ot);
@@ -248,7 +280,7 @@ void ED_view3d_smooth_view_force_finish(
struct View3D *v3d, struct ARegion *ar);
void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect);
-void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d);
+void view3d_viewmatrix_set(const struct EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d);
void fly_modal_keymap(struct wmKeyConfig *keyconf);
void walk_modal_keymap(struct wmKeyConfig *keyconf);
@@ -263,7 +295,7 @@ void view3d_buttons_register(struct ARegionType *art);
/* view3d_camera_control.c */
struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
- Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ const struct bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d,
const bool use_parent_root);
void ED_view3d_cameracontrol_update(
struct View3DCameraControl *vctrl,
@@ -297,6 +329,20 @@ ARegion *view3d_has_tools_region(ScrArea *sa);
extern const char *view3d_context_dir[]; /* doc access */
+/* view3d_widgets.c */
+void VIEW3D_WGT_lamp_spot(struct wmManipulatorGroupType *wgt);
+void VIEW3D_WGT_lamp_area(struct wmManipulatorGroupType *wgt);
+void VIEW3D_WGT_lamp_target(struct wmManipulatorGroupType *wgt);
+void VIEW3D_WGT_camera(struct wmManipulatorGroupType *wgt);
+void VIEW3D_WGT_camera_view(struct wmManipulatorGroupType *wgt);
+void VIEW3D_WGT_force_field(struct wmManipulatorGroupType *wgt);
+void VIEW3D_WGT_empty_image(struct wmManipulatorGroupType *wgt);
+void VIEW3D_WGT_armature_spline(struct wmManipulatorGroupType *wgt);
+
+void VIEW3D_WGT_ruler(struct wmManipulatorGroupType *wgt);
+void VIEW3D_WT_ruler_item(struct wmManipulatorType *wt);
+void VIEW3D_OT_ruler_add(struct wmOperatorType *ot);
+
/* draw_volume.c */
void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob,
const float min[3], const float max[3],
@@ -315,5 +361,31 @@ extern unsigned char view3d_camera_border_hack_col[3];
extern bool view3d_camera_border_hack_test;
#endif
-#endif /* __VIEW3D_INTERN_H__ */
+/* temporary for legacy viewport to work */
+void VP_legacy_drawcursor(Scene *scene, struct ViewLayer *view_layer, ARegion *ar, View3D *v3d);
+void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect);
+void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect);
+void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect);
+void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit);
+void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth);
+void VP_legacy_view3d_main_region_setup_view(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]);
+bool VP_legacy_view3d_stereo3d_active(struct wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d);
+void VP_legacy_view3d_stereo3d_setup(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar);
+void draw_dupli_objects(const struct EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Base *base);
+bool VP_legacy_use_depth(Scene *scene, View3D *v3d);
+void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d);
+void VP_drawrenderborder(ARegion *ar, View3D *v3d);
+void VP_view3d_draw_background_none(void);
+void VP_view3d_draw_background_world(Scene *scene, RegionView3D *rv3d);
+void VP_view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar);
+
+/* temporary legacy calls, only when there is a switch between new/old draw calls */
+void VP_deprecated_gpu_update_lamps_shadows_world(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d);
+void VP_deprecated_view3d_draw_objects(
+ const struct bContext *C,
+ const struct EvaluationContext *eval_ctx,
+ Scene *scene, View3D *v3d, ARegion *ar,
+ const char **grid_unit,
+ const bool do_bgpic, const bool draw_offscreen, struct GPUFX *fx);
+#endif /* __VIEW3D_INTERN_H__ */
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index ef7b01f7a21..4f80270e1e7 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -40,6 +40,9 @@
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
+#include "BKE_context.h"
+
+#include "DEG_depsgraph.h"
#include "bmesh.h"
@@ -104,12 +107,14 @@ static void meshobject_foreachScreenVert__mapFunc(void *userData, int index, con
}
void meshobject_foreachScreenVert(
- ViewContext *vc,
+ const EvaluationContext *eval_ctx, ViewContext *vc,
void (*func)(void *userData, MVert *eve, const float screen_co[2], int index),
void *userData, eV3DProjTest clip_flag)
{
foreachScreenObjectVert_userData data;
- DerivedMesh *dm = mesh_get_derived_deform(vc->scene, vc->obact, CD_MASK_BAREMESH);
+ DerivedMesh *dm;
+
+ dm = mesh_get_derived_deform(eval_ctx, vc->scene, vc->obact, CD_MASK_BAREMESH);
ED_view3d_check_mats_rv3d(vc->rv3d);
@@ -145,12 +150,14 @@ static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const flo
}
void mesh_foreachScreenVert(
- ViewContext *vc,
+ const EvaluationContext *eval_ctx, ViewContext *vc,
void (*func)(void *userData, BMVert *eve, const float screen_co[2], int index),
void *userData, eV3DProjTest clip_flag)
{
foreachScreenVert_userData data;
- DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+ DerivedMesh *dm;
+
+ dm = editbmesh_get_derived_cage(eval_ctx, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
ED_view3d_check_mats_rv3d(vc->rv3d);
@@ -199,12 +206,14 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const flo
}
void mesh_foreachScreenEdge(
- ViewContext *vc,
+ const EvaluationContext *eval_ctx, ViewContext *vc,
void (*func)(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index),
void *userData, eV3DProjTest clip_flag)
{
foreachScreenEdge_userData data;
- DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+ DerivedMesh *dm;
+
+ dm = editbmesh_get_derived_cage(eval_ctx, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
ED_view3d_check_mats_rv3d(vc->rv3d);
@@ -245,12 +254,14 @@ static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const flo
}
void mesh_foreachScreenFace(
- ViewContext *vc,
+ const EvaluationContext *eval_ctx, ViewContext *vc,
void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index),
void *userData, const eV3DProjTest clip_flag)
{
foreachScreenFace_userData data;
- DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
+ DerivedMesh *dm;
+
+ dm = editbmesh_get_derived_cage(eval_ctx, vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH);
ED_view3d_check_mats_rv3d(vc->rv3d);
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_armature.c b/source/blender/editors/space_view3d/view3d_manipulator_armature.c
new file mode 100644
index 00000000000..5d3d88ff2a2
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_armature.c
@@ -0,0 +1,220 @@
+/*
+ * ***** 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_view3d/view3d_manipulator_armature.c
+ * \ingroup spview3d
+ */
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_armature.h"
+#include "BKE_action.h"
+#include "BKE_context.h"
+#include "BKE_object.h"
+
+#include "DNA_object_types.h"
+#include "DNA_armature_types.h"
+
+#include "ED_armature.h"
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "UI_resources.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "view3d_intern.h" /* own include */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Armature Spline Manipulator
+ *
+ * \{ */
+
+/*
+ * TODO(campbell): Current conversion is a approximation (usable not correct),
+ * we'll need to take the next/previous bones into account to get the tangent directions.
+ * First last matrices from 'b_bone_spline_setup' are close but also not quite accurate
+ * since they're not at either end-points on the curve.
+ *
+ * Likely we'll need a function especially to get the first/last orientations.
+ */
+
+#define BBONE_SCALE_Y 3.0f
+
+struct BoneSplineHandle {
+ wmManipulator *manipulator;
+ bPoseChannel *pchan;
+ /* We could remove, keep since at the moment for checking the conversion. */
+ float co[3];
+ int index;
+};
+
+struct BoneSplineWidgetGroup {
+ struct BoneSplineHandle handles[2];
+};
+
+static void manipulator_bbone_offset_get(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ struct BoneSplineHandle *bh = mpr_prop->custom_func.user_data;
+ bPoseChannel *pchan = bh->pchan;
+
+ float *value = value_p;
+ BLI_assert(mpr_prop->type->array_length == 3);
+
+ if (bh->index == 0) {
+ bh->co[1] = pchan->bone->ease1 / BBONE_SCALE_Y;
+ bh->co[0] = pchan->curveInX;
+ bh->co[2] = pchan->curveInY;
+ }
+ else {
+ bh->co[1] = -pchan->bone->ease2 / BBONE_SCALE_Y;
+ bh->co[0] = pchan->curveOutX;
+ bh->co[2] = pchan->curveOutY;
+ }
+ copy_v3_v3(value, bh->co);
+}
+
+static void manipulator_bbone_offset_set(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ struct BoneSplineHandle *bh = mpr_prop->custom_func.user_data;
+ bPoseChannel *pchan = bh->pchan;
+
+ const float *value = value_p;
+
+ BLI_assert(mpr_prop->type->array_length == 3);
+ copy_v3_v3(bh->co, value);
+
+ if (bh->index == 0) {
+ pchan->bone->ease1 = max_ff(0.0f, bh->co[1] * BBONE_SCALE_Y);
+ pchan->curveInX = bh->co[0];
+ pchan->curveInY = bh->co[2];
+ }
+ else {
+ pchan->bone->ease2 = max_ff(0.0f, -bh->co[1] * BBONE_SCALE_Y);
+ pchan->curveOutX = bh->co[0];
+ pchan->curveOutY = bh->co[2];
+ }
+
+}
+
+static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ if (ob != NULL) {
+ const bArmature *arm = ob->data;
+ if (arm->drawtype == ARM_B_BONE) {
+ if (arm->act_bone && arm->act_bone->segments > 1) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+static void WIDGETGROUP_armature_spline_setup(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+
+ const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", true);
+
+ struct BoneSplineWidgetGroup *bspline_group = MEM_callocN(sizeof(struct BoneSplineWidgetGroup), __func__);
+ mgroup->customdata = bspline_group;
+
+ /* Handles */
+ for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) {
+ wmManipulator *mpr;
+ mpr = bspline_group->handles[i].manipulator = WM_manipulator_new_ptr(wt_grab, mgroup, NULL);
+ RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_RING_2D);
+ RNA_enum_set(mpr->ptr, "draw_options",
+ ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL | ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW);
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_VALUE, true);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
+
+ mpr->scale_basis = 0.06f;
+
+ if (i == 0) {
+ copy_v3_v3(mpr->matrix_basis[3], pchan->loc);
+ }
+ }
+}
+
+static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+
+ if (!mgroup->customdata)
+ return;
+
+ struct BoneSplineWidgetGroup *bspline_group = mgroup->customdata;
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+
+ /* Handles */
+ for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) {
+ wmManipulator *mpr = bspline_group->handles[i].manipulator;
+ bspline_group->handles[i].pchan = pchan;
+ bspline_group->handles[i].index = i;
+
+ float mat[4][4];
+ mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat);
+ copy_m4_m4(mpr->matrix_space, mat);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ WM_manipulator_target_property_def_func(
+ mpr, "offset",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_bbone_offset_get,
+ .value_set_fn = manipulator_bbone_offset_set,
+ .range_get_fn = NULL,
+ .user_data = &bspline_group->handles[i],
+ });
+ }
+}
+
+void VIEW3D_WGT_armature_spline(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Armature Spline Widgets";
+ wgt->idname = "VIEW3D_WGT_armature_spline";
+
+ wgt->flag = (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+ WM_MANIPULATORGROUPTYPE_3D);
+
+ wgt->poll = WIDGETGROUP_armature_spline_poll;
+ wgt->setup = WIDGETGROUP_armature_spline_setup;
+ wgt->refresh = WIDGETGROUP_armature_spline_refresh;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
new file mode 100644
index 00000000000..d020571930a
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
@@ -0,0 +1,448 @@
+/*
+ * ***** 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_view3d/view3d_manipulator_camera.c
+ * \ingroup spview3d
+ */
+
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_camera.h"
+#include "BKE_context.h"
+
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
+
+#include "ED_armature.h"
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "UI_resources.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "WM_message.h"
+
+#include "view3d_intern.h" /* own include */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Camera Manipulators
+ * \{ */
+
+struct CameraWidgetGroup {
+ wmManipulator *dop_dist;
+ wmManipulator *focal_len;
+ wmManipulator *ortho_scale;
+};
+
+static bool WIDGETGROUP_camera_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ Object *ob = CTX_data_active_object(C);
+
+ return (ob && ob->type == OB_CAMERA);
+}
+
+static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ Object *ob = CTX_data_active_object(C);
+ float dir[3];
+
+ const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true);
+
+ struct CameraWidgetGroup *camgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__);
+ mgroup->customdata = camgroup;
+
+ negate_v3_v3(dir, ob->obmat[2]);
+
+ /* dof distance */
+ {
+ wmManipulator *mpr;
+ mpr = camgroup->dop_dist = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
+ RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CROSS);
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_HOVER, true);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_A, mpr->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
+ }
+
+ /* focal length
+ * - logic/calculations are similar to BKE_camera_view_frame_ex, better keep in sync */
+ {
+ wmManipulator *mpr;
+ mpr = camgroup->focal_len = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
+ mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE;
+ RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE);
+ RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
+
+ mpr = camgroup->ortho_scale = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
+ mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE;
+ RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE);
+ RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
+ }
+}
+
+static void WIDGETGROUP_camera_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ if (!mgroup->customdata)
+ return;
+
+ struct CameraWidgetGroup *camgroup = mgroup->customdata;
+ Object *ob = CTX_data_active_object(C);
+ Camera *ca = ob->data;
+ PointerRNA camera_ptr;
+ float dir[3];
+
+ const float ob_scale_inv[3] = {
+ 1.0f / len_v3(ob->obmat[0]),
+ 1.0f / len_v3(ob->obmat[1]),
+ 1.0f / len_v3(ob->obmat[2]),
+ };
+ const float ob_scale_uniform_inv = (ob_scale_inv[0] + ob_scale_inv[1] + ob_scale_inv[2]) / 3.0f;
+
+ RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr);
+
+ negate_v3_v3(dir, ob->obmat[2]);
+
+ if (ca->flag & CAM_SHOWLIMITS) {
+ WM_manipulator_set_matrix_location(camgroup->dop_dist, ob->obmat[3]);
+ WM_manipulator_set_matrix_rotation_from_yz_axis(camgroup->dop_dist, ob->obmat[1], dir);
+ WM_manipulator_set_scale(camgroup->dop_dist, ca->drawsize);
+ WM_manipulator_set_flag(camgroup->dop_dist, WM_MANIPULATOR_HIDDEN, false);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ WM_manipulator_target_property_def_rna(camgroup->dop_dist, "offset", &camera_ptr, "dof_distance", -1);
+ }
+ else {
+ WM_manipulator_set_flag(camgroup->dop_dist, WM_MANIPULATOR_HIDDEN, true);
+ }
+
+ /* TODO - make focal length/ortho ob_scale_inv widget optional */
+ const Scene *scene = CTX_data_scene(C);
+ const float aspx = (float)scene->r.xsch * scene->r.xasp;
+ const float aspy = (float)scene->r.ysch * scene->r.yasp;
+ const bool is_ortho = (ca->type == CAM_ORTHO);
+ const int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, aspx, aspy);
+ wmManipulator *widget = is_ortho ? camgroup->ortho_scale : camgroup->focal_len;
+ float scale_matrix;
+ if (true) {
+ float offset[3];
+ float aspect[2];
+
+ WM_manipulator_set_flag(widget, WM_MANIPULATOR_HIDDEN, false);
+ WM_manipulator_set_flag(is_ortho ? camgroup->focal_len : camgroup->ortho_scale, WM_MANIPULATOR_HIDDEN, true);
+
+
+ /* account for lens shifting */
+ offset[0] = ((ob->size[0] > 0.0f) ? -2.0f : 2.0f) * ca->shiftx;
+ offset[1] = 2.0f * ca->shifty;
+ offset[2] = 0.0f;
+
+ /* get aspect */
+ aspect[0] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? 1.0f : aspx / aspy;
+ aspect[1] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? aspy / aspx : 1.0f;
+
+ unit_m4(widget->matrix_basis);
+ WM_manipulator_set_matrix_location(widget, ob->obmat[3]);
+ WM_manipulator_set_matrix_rotation_from_yz_axis(widget, ob->obmat[1], dir);
+
+ if (is_ortho) {
+ scale_matrix = ca->ortho_scale * 0.5f;
+ }
+ else {
+ scale_matrix = ca->drawsize / ob_scale_uniform_inv;
+ }
+ mul_v3_fl(widget->matrix_basis[0], scale_matrix);
+ mul_v3_fl(widget->matrix_basis[1], scale_matrix);
+
+ RNA_float_set_array(widget->ptr, "aspect", aspect);
+
+ WM_manipulator_set_matrix_offset_location(widget, offset);
+ }
+
+ /* define & update properties */
+ {
+ const char *propname = is_ortho ? "ortho_scale" : "lens";
+ PropertyRNA *prop = RNA_struct_find_property(&camera_ptr, propname);
+ const wmManipulatorPropertyType *mpr_prop_type = WM_manipulatortype_target_property_find(widget->type, "offset");
+
+ WM_manipulator_target_property_clear_rna_ptr(widget, mpr_prop_type);
+
+ float min, max, range;
+ float step, precision;
+
+ /* get property range */
+ RNA_property_float_ui_range(&camera_ptr, prop, &min, &max, &step, &precision);
+ range = max - min;
+
+ ED_manipulator_arrow3d_set_range_fac(
+ widget, is_ortho ?
+ (ca->drawsize * range) :
+ (scale_matrix * range /
+ /* Half sensor, intentionally use sensor from camera and not calculated above. */
+ (0.5f * ((ca->sensor_fit == CAMERA_SENSOR_FIT_HOR) ? ca->sensor_x : ca->sensor_x))));
+
+ WM_manipulator_target_property_def_rna_ptr(widget, mpr_prop_type, &camera_ptr, prop, -1);
+ }
+
+}
+
+static void WIDGETGROUP_camera_message_subscribe(
+ const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus)
+{
+ ARegion *ar = CTX_wm_region(C);
+ Object *ob = CTX_data_active_object(C);
+ Camera *ca = ob->data;
+
+ wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = {
+ .owner = ar,
+ .user_data = mgroup->parent_mmap,
+ .notify = WM_manipulator_do_msg_notify_tag_refresh,
+ };
+
+ {
+ extern PropertyRNA rna_Camera_dof_distance;
+ extern PropertyRNA rna_Camera_draw_size;
+ extern PropertyRNA rna_Camera_ortho_scale;
+ extern PropertyRNA rna_Camera_sensor_fit;
+ extern PropertyRNA rna_Camera_sensor_width;
+ extern PropertyRNA rna_Camera_shift_x;
+ extern PropertyRNA rna_Camera_shift_y;
+ extern PropertyRNA rna_Camera_type;
+ const PropertyRNA *props[] = {
+ &rna_Camera_dof_distance,
+ &rna_Camera_draw_size,
+ &rna_Camera_ortho_scale,
+ &rna_Camera_sensor_fit,
+ &rna_Camera_sensor_width,
+ &rna_Camera_shift_x,
+ &rna_Camera_shift_y,
+ &rna_Camera_type,
+ };
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&ca->id, &idptr);
+
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
+ }
+ }
+
+ /* Subscribe to render settings */
+ {
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_mpr_tag_refresh);
+ }
+}
+
+void VIEW3D_WGT_camera(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Camera Widgets";
+ wgt->idname = "VIEW3D_WGT_camera";
+
+ wgt->flag = (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+ WM_MANIPULATORGROUPTYPE_3D |
+ WM_MANIPULATORGROUPTYPE_DEPTH_3D);
+
+ wgt->poll = WIDGETGROUP_camera_poll;
+ wgt->setup = WIDGETGROUP_camera_setup;
+ wgt->refresh = WIDGETGROUP_camera_refresh;
+ wgt->message_subscribe = WIDGETGROUP_camera_message_subscribe;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name CameraView Manipulators
+ * \{ */
+
+struct CameraViewWidgetGroup {
+ wmManipulator *border;
+
+ struct {
+ rctf *edit_border;
+ rctf view_border;
+ } state;
+};
+
+/* scale callbacks */
+static void manipulator_render_border_prop_matrix_get(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ float (*matrix)[4] = value_p;
+ BLI_assert(mpr_prop->type->array_length == 16);
+ struct CameraViewWidgetGroup *viewgroup = mpr_prop->custom_func.user_data;
+ const rctf *border = viewgroup->state.edit_border;
+
+ unit_m4(matrix);
+ matrix[0][0] = BLI_rctf_size_x(border);
+ matrix[1][1] = BLI_rctf_size_y(border);
+ matrix[3][0] = BLI_rctf_cent_x(border);
+ matrix[3][1] = BLI_rctf_cent_y(border);
+}
+
+static void manipulator_render_border_prop_matrix_set(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ const float (*matrix)[4] = value_p;
+ struct CameraViewWidgetGroup *viewgroup = mpr_prop->custom_func.user_data;
+ rctf *border = viewgroup->state.edit_border;
+ BLI_assert(mpr_prop->type->array_length == 16);
+
+ BLI_rctf_resize(border, len_v3(matrix[0]), len_v3(matrix[1]));
+ BLI_rctf_recenter(border, matrix[3][0], matrix[3][1]);
+ BLI_rctf_isect(&(rctf){.xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1}, border, border);
+}
+
+static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ /* This is just so the border isn't always in the way,
+ * stealing mouse clicks from regular usage.
+ * We could change the rules for when to show. */
+ {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (scene->camera != OBACT(view_layer)) {
+ return false;
+ }
+ }
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ if (scene->r.mode & R_BORDER) {
+ return true;
+ }
+ }
+ else if (v3d->flag2 & V3D_RENDER_BORDER) {
+ return true;
+ }
+ return false;
+}
+
+static void WIDGETGROUP_camera_view_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ struct CameraViewWidgetGroup *viewgroup = MEM_mallocN(sizeof(struct CameraViewWidgetGroup), __func__);
+
+ viewgroup->border = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL);
+
+ RNA_enum_set(viewgroup->border->ptr, "transform",
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE);
+ /* Box style is more subtle in this case. */
+ RNA_enum_set(viewgroup->border->ptr, "draw_style", ED_MANIPULATOR_CAGE2D_STYLE_BOX);
+
+
+ mgroup->customdata = viewgroup;
+}
+
+static void WIDGETGROUP_camera_view_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ struct CameraViewWidgetGroup *viewgroup = mgroup->customdata;
+
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->persp == RV3D_CAMOB) {
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewgroup->state.view_border, false);
+ }
+ else {
+ viewgroup->state.view_border = (rctf){.xmin = 0, .ymin = 0, .xmax = ar->winx, .ymax = ar->winy};
+ }
+
+ wmManipulator *mpr = viewgroup->border;
+ unit_m4(mpr->matrix_space);
+ mul_v3_fl(mpr->matrix_space[0], BLI_rctf_size_x(&viewgroup->state.view_border));
+ mul_v3_fl(mpr->matrix_space[1], BLI_rctf_size_y(&viewgroup->state.view_border));
+ mpr->matrix_space[3][0] = viewgroup->state.view_border.xmin;
+ mpr->matrix_space[3][1] = viewgroup->state.view_border.ymin;
+}
+
+static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ struct CameraViewWidgetGroup *viewgroup = mgroup->customdata;
+
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+ Scene *scene = CTX_data_scene(C);
+
+ {
+ wmManipulator *mpr = viewgroup->border;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ RNA_enum_set(viewgroup->border->ptr, "transform",
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE | ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ viewgroup->state.edit_border = &scene->r.border;
+ }
+ else {
+ viewgroup->state.edit_border = &v3d->render_border;
+ }
+
+ WM_manipulator_target_property_def_func(
+ mpr, "matrix",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_render_border_prop_matrix_get,
+ .value_set_fn = manipulator_render_border_prop_matrix_set,
+ .range_get_fn = NULL,
+ .user_data = viewgroup,
+ });
+ }
+
+}
+
+void VIEW3D_WGT_camera_view(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Camera View Widgets";
+ wgt->idname = "VIEW3D_WGT_camera_view";
+
+ wgt->flag = (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+ WM_MANIPULATORGROUPTYPE_SCALE);
+
+ wgt->poll = WIDGETGROUP_camera_view_poll;
+ wgt->setup = WIDGETGROUP_camera_view_setup;
+ wgt->draw_prepare = WIDGETGROUP_camera_view_draw_prepare;
+ wgt->refresh = WIDGETGROUP_camera_view_refresh;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_empty.c b/source/blender/editors/space_view3d/view3d_manipulator_empty.c
new file mode 100644
index 00000000000..1d56c5ee7f4
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_empty.c
@@ -0,0 +1,196 @@
+/*
+ * ***** 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_view3d/view3d_manipulator_empty.c
+ * \ingroup spview3d
+ */
+
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_object.h"
+#include "BKE_image.h"
+
+#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
+
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "UI_resources.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "view3d_intern.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Empty Image Manipulators
+ * \{ */
+
+struct EmptyImageWidgetGroup {
+ wmManipulator *manipulator;
+ struct {
+ Object *ob;
+ float dims[2];
+ } state;
+};
+
+/* translate callbacks */
+static void manipulator_empty_image_prop_matrix_get(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ float (*matrix)[4] = value_p;
+ BLI_assert(mpr_prop->type->array_length == 16);
+ struct EmptyImageWidgetGroup *imgroup = mpr_prop->custom_func.user_data;
+ const Object *ob = imgroup->state.ob;
+
+ unit_m4(matrix);
+ matrix[0][0] = ob->empty_drawsize;
+ matrix[1][1] = ob->empty_drawsize;
+
+ float dims[2] = {0.0f, 0.0f};
+ RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ dims[0] *= ob->empty_drawsize;
+ dims[1] *= ob->empty_drawsize;
+
+ matrix[3][0] = (ob->ima_ofs[0] * dims[0]) + (0.5f * dims[0]);
+ matrix[3][1] = (ob->ima_ofs[1] * dims[1]) + (0.5f * dims[1]);
+}
+
+static void manipulator_empty_image_prop_matrix_set(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ const float (*matrix)[4] = value_p;
+ BLI_assert(mpr_prop->type->array_length == 16);
+ struct EmptyImageWidgetGroup *imgroup = mpr_prop->custom_func.user_data;
+ Object *ob = imgroup->state.ob;
+
+ ob->empty_drawsize = matrix[0][0];
+
+ float dims[2];
+ RNA_float_get_array(mpr->ptr, "dimensions", dims);
+ dims[0] *= ob->empty_drawsize;
+ dims[1] *= ob->empty_drawsize;
+
+ ob->ima_ofs[0] = (matrix[3][0] - (0.5f * dims[0])) / dims[0];
+ ob->ima_ofs[1] = (matrix[3][1] - (0.5f * dims[1])) / dims[1];
+}
+
+static bool WIDGETGROUP_empty_image_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ Object *ob = CTX_data_active_object(C);
+
+ if (ob && ob->type == OB_EMPTY) {
+ return (ob->empty_drawtype == OB_EMPTY_IMAGE);
+ }
+ return false;
+}
+
+static void WIDGETGROUP_empty_image_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ struct EmptyImageWidgetGroup *imgroup = MEM_mallocN(sizeof(struct EmptyImageWidgetGroup), __func__);
+ imgroup->manipulator = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL);
+ wmManipulator *mpr = imgroup->manipulator;
+ RNA_enum_set(mpr->ptr, "transform",
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE);
+
+ mgroup->customdata = imgroup;
+
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_HOVER, true);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
+}
+
+static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ struct EmptyImageWidgetGroup *imgroup = mgroup->customdata;
+ Object *ob = CTX_data_active_object(C);
+ wmManipulator *mpr = imgroup->manipulator;
+
+ copy_m4_m4(mpr->matrix_basis, ob->obmat);
+
+ RNA_enum_set(mpr->ptr, "transform",
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE |
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE |
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM);
+
+ imgroup->state.ob = ob;
+
+ /* Use dimensions for aspect. */
+ if (ob->data != NULL) {
+ const Image *image = ob->data;
+ ImageUser iuser = *ob->iuser;
+ float size[2];
+ BKE_image_get_size_fl(ob->data, &iuser, size);
+
+ /* Get the image aspect even if the buffer is invalid */
+ if (image->aspx > image->aspy) {
+ size[1] *= image->aspy / image->aspx;
+ }
+ else if (image->aspx < image->aspy) {
+ size[0] *= image->aspx / image->aspy;
+ }
+
+ const float dims_max = max_ff(size[0], size[1]);
+ imgroup->state.dims[0] = size[0] / dims_max;
+ imgroup->state.dims[1] = size[1] / dims_max;
+ }
+ else {
+ copy_v2_fl(imgroup->state.dims, 1.0f);
+ }
+ RNA_float_set_array(mpr->ptr, "dimensions", imgroup->state.dims);
+
+ WM_manipulator_target_property_def_func(
+ mpr, "matrix",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_empty_image_prop_matrix_get,
+ .value_set_fn = manipulator_empty_image_prop_matrix_set,
+ .range_get_fn = NULL,
+ .user_data = imgroup,
+ });
+}
+
+void VIEW3D_WGT_empty_image(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Area Lamp Widgets";
+ wgt->idname = "VIEW3D_WGT_empty_image";
+
+ wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+ WM_MANIPULATORGROUPTYPE_3D |
+ WM_MANIPULATORGROUPTYPE_DEPTH_3D);
+
+ wgt->poll = WIDGETGROUP_empty_image_poll;
+ wgt->setup = WIDGETGROUP_empty_image_setup;
+ wgt->refresh = WIDGETGROUP_empty_image_refresh;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
new file mode 100644
index 00000000000..6a34f493caf
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
@@ -0,0 +1,118 @@
+/*
+ * ***** 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_view3d/view3d_manipulator_forcefield.c
+ * \ingroup spview3d
+ */
+
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_object.h"
+
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "UI_resources.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "view3d_intern.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Force Field Manipulators
+ * \{ */
+
+static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ Object *ob = CTX_data_active_object(C);
+
+ return (ob && ob->pd && ob->pd->forcefield);
+}
+
+static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ /* only wind effector for now */
+ wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
+ mgroup->customdata = wwrapper;
+
+ wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL);
+ wmManipulator *mpr = wwrapper->manipulator;
+ RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED);
+ ED_manipulator_arrow3d_set_ui_range(mpr, -200.0f, 200.0f);
+ ED_manipulator_arrow3d_set_range_fac(mpr, 6.0f);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
+}
+
+static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ wmManipulatorWrapper *wwrapper = mgroup->customdata;
+ wmManipulator *mpr = wwrapper->manipulator;
+ Object *ob = CTX_data_active_object(C);
+ PartDeflect *pd = ob->pd;
+
+ if (pd->forcefield == PFIELD_WIND) {
+ const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f;
+ const float ofs[3] = {0.0f, -size, 0.0f};
+ PointerRNA field_ptr;
+
+ RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr);
+ WM_manipulator_set_matrix_location(mpr, ob->obmat[3]);
+ WM_manipulator_set_matrix_rotation_from_z_axis(mpr, ob->obmat[2]);
+ WM_manipulator_set_matrix_offset_location(mpr, ofs);
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ WM_manipulator_target_property_def_rna(mpr, "offset", &field_ptr, "strength", -1);
+ }
+ else {
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
+ }
+}
+
+void VIEW3D_WGT_force_field(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Force Field Widgets";
+ wgt->idname = "VIEW3D_WGT_force_field";
+
+ wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+ WM_MANIPULATORGROUPTYPE_3D |
+ WM_MANIPULATORGROUPTYPE_SCALE |
+ WM_MANIPULATORGROUPTYPE_DEPTH_3D);
+
+ wgt->poll = WIDGETGROUP_forcefield_poll;
+ wgt->setup = WIDGETGROUP_forcefield_setup;
+ wgt->refresh = WIDGETGROUP_forcefield_refresh;
+}
+
+/** \} */
+
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c
new file mode 100644
index 00000000000..93b6b69a105
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c
@@ -0,0 +1,289 @@
+/*
+ * ***** 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_view3d/view3d_manipulator_lamp.c
+ * \ingroup spview3d
+ */
+
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_object.h"
+
+#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
+
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "UI_resources.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "view3d_intern.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Spot Lamp Manipulators
+ * \{ */
+
+static bool WIDGETGROUP_lamp_spot_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ Object *ob = CTX_data_active_object(C);
+
+ if (ob && ob->type == OB_LAMP) {
+ Lamp *la = ob->data;
+ return (la->type == LA_SPOT);
+ }
+ return false;
+}
+
+static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
+
+ wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL);
+ wmManipulator *mpr = wwrapper->manipulator;
+ RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_INVERTED);
+
+ mgroup->customdata = wwrapper;
+
+ ED_manipulator_arrow3d_set_range_fac(mpr, 4.0f);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, mpr->color);
+}
+
+static void WIDGETGROUP_lamp_spot_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ wmManipulatorWrapper *wwrapper = mgroup->customdata;
+ wmManipulator *mpr = wwrapper->manipulator;
+ Object *ob = CTX_data_active_object(C);
+ Lamp *la = ob->data;
+ float dir[3];
+
+ negate_v3_v3(dir, ob->obmat[2]);
+
+ WM_manipulator_set_matrix_rotation_from_z_axis(mpr, dir);
+ WM_manipulator_set_matrix_location(mpr, ob->obmat[3]);
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ PointerRNA lamp_ptr;
+ const char *propname = "spot_size";
+ RNA_pointer_create(&la->id, &RNA_Lamp, la, &lamp_ptr);
+ WM_manipulator_target_property_def_rna(mpr, "offset", &lamp_ptr, propname, -1);
+}
+
+void VIEW3D_WGT_lamp_spot(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Spot Lamp Widgets";
+ wgt->idname = "VIEW3D_WGT_lamp_spot";
+
+ wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+ WM_MANIPULATORGROUPTYPE_3D |
+ WM_MANIPULATORGROUPTYPE_DEPTH_3D);
+
+ wgt->poll = WIDGETGROUP_lamp_spot_poll;
+ wgt->setup = WIDGETGROUP_lamp_spot_setup;
+ wgt->refresh = WIDGETGROUP_lamp_spot_refresh;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Area Lamp Manipulators
+ * \{ */
+
+/* scale callbacks */
+static void manipulator_area_lamp_prop_matrix_get(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ BLI_assert(mpr_prop->type->array_length == 16);
+ float (*matrix)[4] = value_p;
+ const Lamp *la = mpr_prop->custom_func.user_data;
+
+ matrix[0][0] = la->area_size;
+ matrix[1][1] = (la->area_shape == LA_AREA_RECT) ? la->area_sizey : la->area_size;
+}
+
+static void manipulator_area_lamp_prop_matrix_set(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ const float (*matrix)[4] = value_p;
+ BLI_assert(mpr_prop->type->array_length == 16);
+ Lamp *la = mpr_prop->custom_func.user_data;
+
+ if (la->area_shape == LA_AREA_RECT) {
+ la->area_size = len_v3(matrix[0]);
+ la->area_sizey = len_v3(matrix[1]);
+ }
+ else {
+ la->area_size = len_v3(matrix[0]);
+ }
+}
+
+static bool WIDGETGROUP_lamp_area_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ Object *ob = CTX_data_active_object(C);
+
+ if (ob && ob->type == OB_LAMP) {
+ Lamp *la = ob->data;
+ return (la->type == LA_AREA);
+ }
+ return false;
+}
+
+static void WIDGETGROUP_lamp_area_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
+ wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL);
+ wmManipulator *mpr = wwrapper->manipulator;
+ RNA_enum_set(mpr->ptr, "transform",
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE);
+
+ mgroup->customdata = wwrapper;
+
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_HOVER, true);
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
+}
+
+static void WIDGETGROUP_lamp_area_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ wmManipulatorWrapper *wwrapper = mgroup->customdata;
+ Object *ob = CTX_data_active_object(C);
+ Lamp *la = ob->data;
+ wmManipulator *mpr = wwrapper->manipulator;
+
+ copy_m4_m4(mpr->matrix_basis, ob->obmat);
+
+ RNA_enum_set(mpr->ptr, "transform",
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE |
+ ((la->area_shape == LA_AREA_SQUARE) ? ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM : 0));
+
+ /* need to set property here for undo. TODO would prefer to do this in _init */
+ WM_manipulator_target_property_def_func(
+ mpr, "matrix",
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = manipulator_area_lamp_prop_matrix_get,
+ .value_set_fn = manipulator_area_lamp_prop_matrix_set,
+ .range_get_fn = NULL,
+ .user_data = la,
+ });
+}
+
+void VIEW3D_WGT_lamp_area(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Area Lamp Widgets";
+ wgt->idname = "VIEW3D_WGT_lamp_area";
+
+ wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+ WM_MANIPULATORGROUPTYPE_3D |
+ WM_MANIPULATORGROUPTYPE_DEPTH_3D);
+
+ wgt->poll = WIDGETGROUP_lamp_area_poll;
+ wgt->setup = WIDGETGROUP_lamp_area_setup;
+ wgt->refresh = WIDGETGROUP_lamp_area_refresh;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Lamp Target Manipulator
+ * \{ */
+
+static bool WIDGETGROUP_lamp_target_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ Object *ob = CTX_data_active_object(C);
+
+ if (ob != NULL) {
+ if (ob->type == OB_LAMP) {
+ Lamp *la = ob->data;
+ return (ELEM(la->type, LA_SUN, LA_SPOT, LA_HEMI, LA_AREA));
+ }
+#if 0
+ else if (ob->type == OB_CAMERA) {
+ return true;
+ }
+#endif
+ }
+ return false;
+}
+
+static void WIDGETGROUP_lamp_target_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
+ wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_grab_3d", mgroup, NULL);
+ wmManipulator *mpr = wwrapper->manipulator;
+
+ mgroup->customdata = wwrapper;
+
+ UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
+ UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
+
+ mpr->scale_basis = 0.06f;
+
+ wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_transform_axis_target", true);
+
+ RNA_enum_set(mpr->ptr, "draw_options",
+ ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL | ED_MANIPULATOR_GRAB_DRAW_FLAG_ALIGN_VIEW);
+
+ WM_manipulator_operator_set(mpr, 0, ot, NULL);
+}
+
+static void WIDGETGROUP_lamp_target_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ wmManipulatorWrapper *wwrapper = mgroup->customdata;
+ Object *ob = CTX_data_active_object(C);
+ wmManipulator *mpr = wwrapper->manipulator;
+
+ copy_m4_m4(mpr->matrix_basis, ob->obmat);
+ unit_m4(mpr->matrix_offset);
+ mpr->matrix_offset[3][2] = -2.4f / mpr->scale_basis;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true);
+}
+
+void VIEW3D_WGT_lamp_target(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Target Lamp Widgets";
+ wgt->idname = "VIEW3D_WGT_lamp_target";
+
+ wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+ WM_MANIPULATORGROUPTYPE_3D);
+
+ wgt->poll = WIDGETGROUP_lamp_target_poll;
+ wgt->setup = WIDGETGROUP_lamp_target_setup;
+ wgt->draw_prepare = WIDGETGROUP_lamp_target_draw_prepare;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
new file mode 100644
index 00000000000..230b4f44c16
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
@@ -0,0 +1,1079 @@
+/*
+ * ***** 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_view3d/view3d_manipulator_ruler.c
+ * \ingroup spview3d
+ */
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_rect.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "BKE_context.h"
+#include "BKE_object.h"
+#include "BKE_gpencil.h"
+#include "BKE_unit.h"
+
+#include "DNA_object_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BIF_gl.h"
+
+#include "ED_screen.h"
+#include "ED_transform_snap_object_context.h"
+#include "ED_view3d.h"
+
+#include "UI_resources.h"
+#include "UI_interface.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "view3d_intern.h" /* own include */
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_select.h"
+
+#include "BLF_api.h"
+
+
+static const char *view3d_wgt_ruler_id = "VIEW3D_WGT_ruler";
+
+
+#define MVAL_MAX_PX_DIST 12.0f
+
+/* -------------------------------------------------------------------- */
+/* Ruler Item (we can have many) */
+enum {
+ RULERITEM_USE_ANGLE = (1 << 0), /* use protractor */
+ RULERITEM_USE_RAYCAST = (1 << 1)
+};
+
+enum {
+ RULERITEM_DIRECTION_IN = 0,
+ RULERITEM_DIRECTION_OUT
+};
+
+/* keep smaller then selection, since we may want click elsewhere without selecting a ruler */
+#define RULER_PICK_DIST 12.0f
+#define RULER_PICK_DIST_SQ (RULER_PICK_DIST * RULER_PICK_DIST)
+
+/* not clicking on a point */
+#define PART_LINE 0xff
+
+/* -------------------------------------------------------------------- */
+/* Ruler Info (wmManipulatorGroup customdata) */
+
+enum {
+ RULER_STATE_NORMAL = 0,
+ RULER_STATE_DRAG
+};
+
+enum {
+ RULER_SNAP_OK = (1 << 0),
+};
+
+typedef struct RulerInfo {
+ // ListBase items;
+ int item_active;
+ int flag;
+ int snap_flag;
+ int state;
+
+ struct SnapObjectContext *snap_context;
+
+ /* wm state */
+ wmWindow *win;
+ ScrArea *sa;
+ ARegion *ar; /* re-assigned every modal update */
+} RulerInfo;
+
+/* -------------------------------------------------------------------- */
+/* Ruler Item (two or three points) */
+
+typedef struct RulerItem {
+ wmManipulator mpr;
+
+ /* worldspace coords, middle being optional */
+ float co[3][3];
+
+ int flag;
+ int raycast_dir; /* RULER_DIRECTION_* */
+} RulerItem;
+
+typedef struct RulerInteraction {
+ /* selected coord */
+ char co_index; /* 0 -> 2 */
+ float drag_start_co[3];
+ uint inside_region : 1;
+} RulerInteraction;
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Ruler Utilities
+ * \{ */
+
+static RulerItem *ruler_item_add(wmManipulatorGroup *mgroup)
+{
+ /* could pass this as an arg */
+ const wmManipulatorType *wt_ruler = WM_manipulatortype_find("VIEW3D_WT_ruler_item", true);
+ RulerItem *ruler_item = (RulerItem *)WM_manipulator_new_ptr(wt_ruler, mgroup, NULL);
+ WM_manipulator_set_flag(&ruler_item->mpr, WM_MANIPULATOR_DRAW_MODAL, true);
+ return ruler_item;
+}
+
+static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
+ char *numstr, size_t numstr_size, int prec)
+{
+ const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0;
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ const float ruler_angle = angle_v3v3v3(ruler_item->co[0],
+ ruler_item->co[1],
+ ruler_item->co[2]);
+
+ if (unit->system == USER_UNIT_NONE) {
+ BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle));
+ }
+ else {
+ bUnit_AsString(numstr, numstr_size,
+ (double)ruler_angle,
+ prec, unit->system, B_UNIT_ROTATION, do_split, false);
+ }
+ }
+ else {
+ const float ruler_len = len_v3v3(ruler_item->co[0],
+ ruler_item->co[2]);
+
+ if (unit->system == USER_UNIT_NONE) {
+ BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len);
+ }
+ else {
+ bUnit_AsString(numstr, numstr_size,
+ (double)(ruler_len * unit->scale_length),
+ prec, unit->system, B_UNIT_LENGTH, do_split, false);
+ }
+ }
+}
+
+static bool view3d_ruler_pick(
+ wmManipulatorGroup *mgroup, RulerItem *ruler_item, const float mval[2],
+ int *r_co_index)
+{
+ RulerInfo *ruler_info = mgroup->customdata;
+ ARegion *ar = ruler_info->ar;
+ bool found = false;
+
+ float dist_best = RULER_PICK_DIST_SQ;
+ int co_index_best = -1;
+
+ {
+ float co_ss[3][2];
+ float dist;
+ int j;
+
+ /* should these be checked? - ok for now not to */
+ for (j = 0; j < 3; j++) {
+ ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
+ }
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]),
+ dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2]));
+ if (dist < dist_best) {
+ dist_best = dist;
+ found = true;
+
+ {
+ const float dist_points[3] = {
+ len_squared_v2v2(co_ss[0], mval),
+ len_squared_v2v2(co_ss[1], mval),
+ len_squared_v2v2(co_ss[2], mval),
+ };
+ if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) {
+ co_index_best = min_axis_v3(dist_points);
+ }
+ else {
+ co_index_best = -1;
+ }
+ }
+ }
+ }
+ else {
+ dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]);
+ if (dist < dist_best) {
+ dist_best = dist;
+ found = true;
+
+ {
+ const float dist_points[2] = {
+ len_squared_v2v2(co_ss[0], mval),
+ len_squared_v2v2(co_ss[2], mval),
+ };
+ if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) {
+ co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2;
+ }
+ else {
+ co_index_best = -1;
+ }
+ }
+ }
+ }
+ }
+
+ *r_co_index = co_index_best;
+ return found;
+}
+
+/**
+ * Ensure the 'snap_context' is only cached while dragging,
+ * needed since the user may toggle modes between tool use.
+ */
+static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
+{
+ if (state == ruler_info->state) {
+ return;
+ }
+
+ /* always remove */
+ if (ruler_info->snap_context) {
+ ED_transform_snap_object_context_destroy(ruler_info->snap_context);
+ ruler_info->snap_context = NULL;
+ }
+
+ if (state == RULER_STATE_NORMAL) {
+ /* pass */
+ }
+ 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), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
+ ruler_info->ar, CTX_wm_view3d(C));
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ ruler_info->state = state;
+}
+
+static void view3d_ruler_item_project(
+ RulerInfo *ruler_info, float r_co[3],
+ const int xy[2])
+{
+ ED_view3d_win_to_3d_int(ruler_info->sa->spacedata.first, ruler_info->ar, r_co, xy, r_co);
+}
+
+/* use for mousemove events */
+static bool view3d_ruler_item_mousemove(
+ RulerInfo *ruler_info, RulerItem *ruler_item, const int mval[2],
+ const bool do_thickness, const bool do_snap)
+{
+ RulerInteraction *inter = ruler_item->mpr.interaction_data;
+ const float eps_bias = 0.0002f;
+ float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */
+
+ ruler_info->snap_flag &= ~RULER_SNAP_OK;
+
+ if (ruler_item) {
+ float *co = ruler_item->co[inter->co_index];
+ /* restore the initial depth */
+ copy_v3_v3(co, inter->drag_start_co);
+ view3d_ruler_item_project(ruler_info, co, mval);
+ if (do_thickness && inter->co_index != 1) {
+ // Scene *scene = CTX_data_scene(C);
+ // View3D *v3d = ruler_info->sa->spacedata.first;
+ const float mval_fl[2] = {UNPACK2(mval)};
+ float ray_normal[3];
+ float ray_start[3];
+ float *co_other;
+
+ co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0];
+
+ if (ED_transform_snap_object_project_view3d_mixed(
+ ruler_info->snap_context,
+ SCE_SELECT_FACE,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ },
+ mval_fl, &dist_px, true,
+ co, ray_normal))
+ {
+ negate_v3(ray_normal);
+ /* add some bias */
+ madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias);
+ ED_transform_snap_object_project_ray(
+ ruler_info->snap_context,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ },
+ ray_start, ray_normal, NULL,
+ co_other, NULL);
+ }
+ }
+ else if (do_snap) {
+ // Scene *scene = CTX_data_scene(C);
+ View3D *v3d = ruler_info->sa->spacedata.first;
+ const float mval_fl[2] = {UNPACK2(mval)};
+ bool use_depth = (v3d->drawtype >= OB_SOLID);
+
+ if (ED_transform_snap_object_project_view3d_mixed(
+ ruler_info->snap_context,
+ (SCE_SELECT_VERTEX | SCE_SELECT_EDGE) | (use_depth ? SCE_SELECT_FACE : 0),
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ },
+ mval_fl, &dist_px, use_depth,
+ co, NULL))
+ {
+ ruler_info->snap_flag |= RULER_SNAP_OK;
+ }
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Ruler/Grease Pencil Conversion
+ * \{ */
+
+#define RULER_ID "RulerData3D"
+static bool view3d_ruler_to_gpencil(bContext *C, wmManipulatorGroup *mgroup)
+{
+ // RulerInfo *ruler_info = mgroup->customdata;
+ Scene *scene = CTX_data_scene(C);
+ bGPDlayer *gpl;
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+ bGPDpalette *palette;
+ bGPDpalettecolor *palcolor;
+ RulerItem *ruler_item;
+ const char *ruler_name = RULER_ID;
+ bool changed = false;
+
+ if (scene->gpd == NULL) {
+ scene->gpd = BKE_gpencil_data_addnew("GPencil");
+ }
+
+ gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ if (gpl == NULL) {
+ gpl = BKE_gpencil_layer_addnew(scene->gpd, ruler_name, false);
+ gpl->thickness = 1;
+ gpl->flag |= GP_LAYER_HIDE;
+ }
+
+ /* try to get active palette or create a new one */
+ palette = BKE_gpencil_palette_getactive(scene->gpd);
+ if (palette == NULL) {
+ palette = BKE_gpencil_palette_addnew(scene->gpd, DATA_("GP_Palette"), true);
+ }
+ /* try to get color with the ruler name or create a new one */
+ palcolor = BKE_gpencil_palettecolor_getbyname(palette, (char *)ruler_name);
+ if (palcolor == NULL) {
+ palcolor = BKE_gpencil_palettecolor_addnew(palette, (char *)ruler_name, true);
+ }
+
+ gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true);
+ BKE_gpencil_free_strokes(gpf);
+
+ for (ruler_item = mgroup->manipulators.first; ruler_item; ruler_item = (RulerItem *)ruler_item->mpr.next) {
+ bGPDspoint *pt;
+ int j;
+
+ /* allocate memory for a new stroke */
+ gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ gps->totpoints = 3;
+ pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ for (j = 0; j < 3; j++) {
+ copy_v3_v3(&pt->x, ruler_item->co[j]);
+ pt->pressure = 1.0f;
+ pt->strength = 1.0f;
+ pt++;
+ }
+ }
+ else {
+ gps->totpoints = 2;
+ pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ for (j = 0; j < 3; j += 2) {
+ copy_v3_v3(&pt->x, ruler_item->co[j]);
+ pt->pressure = 1.0f;
+ pt->strength = 1.0f;
+ pt++;
+ }
+ }
+ gps->flag = GP_STROKE_3DSPACE;
+ gps->thickness = 3;
+ /* assign color to stroke */
+ BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname));
+ gps->palcolor = palcolor;
+ BLI_addtail(&gpf->strokes, gps);
+ changed = true;
+ }
+
+ return changed;
+}
+
+static bool view3d_ruler_from_gpencil(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ Scene *scene = CTX_data_scene(C);
+ bool changed = false;
+
+ if (scene->gpd) {
+ bGPDlayer *gpl;
+ const char *ruler_name = RULER_ID;
+ gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ if (gpl) {
+ bGPDframe *gpf;
+ gpf = BKE_gpencil_layer_getframe(gpl, CFRA, false);
+ if (gpf) {
+ bGPDstroke *gps;
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt = gps->points;
+ int j;
+ RulerItem *ruler_item = NULL;
+ if (gps->totpoints == 3) {
+ ruler_item = ruler_item_add(mgroup);
+ for (j = 0; j < 3; j++) {
+ copy_v3_v3(ruler_item->co[j], &pt->x);
+ pt++;
+ }
+ ruler_item->flag |= RULERITEM_USE_ANGLE;
+ changed = true;
+ }
+ else if (gps->totpoints == 2) {
+ ruler_item = ruler_item_add(mgroup);
+ for (j = 0; j < 3; j += 2) {
+ copy_v3_v3(ruler_item->co[j], &pt->x);
+ pt++;
+ }
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+
+ return changed;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Ruler Item Manipulator Type
+ * \{ */
+
+static void manipulator_ruler_draw(const bContext *C, wmManipulator *mpr)
+{
+ Scene *scene = CTX_data_scene(C);
+ UnitSettings *unit = &scene->unit;
+ RulerInfo *ruler_info = mpr->parent_mgroup->customdata;
+ RulerItem *ruler_item = (RulerItem *)mpr;
+ ARegion *ar = ruler_info->ar;
+ RegionView3D *rv3d = ar->regiondata;
+ const float cap_size = 4.0f;
+ const float bg_margin = 4.0f * U.pixelsize;
+ const float bg_radius = 4.0f * U.pixelsize;
+ const float arc_size = 64.0f * U.pixelsize;
+#define ARC_STEPS 24
+ const int arc_steps = ARC_STEPS;
+ const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ const float color_base[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ unsigned char color_text[3];
+ unsigned char color_wire[3];
+ float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f};
+
+ /* anti-aliased lines for more consistent appearance */
+ glEnable(GL_LINE_SMOOTH);
+
+ BLF_enable(blf_mono_font, BLF_ROTATION);
+ BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi);
+ BLF_rotation(blf_mono_font, 0.0f);
+
+ UI_GetThemeColor3ubv(TH_TEXT, color_text);
+ UI_GetThemeColor3ubv(TH_WIRE, color_wire);
+
+ const bool is_act = (mpr->flag & WM_MANIPULATOR_DRAW_HOVER);
+ float dir_ruler[2];
+ float co_ss[3][2];
+ int j;
+
+ /* should these be checked? - ok for now not to */
+ for (j = 0; j < 3; j++) {
+ ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
+ }
+
+ glEnable(GL_BLEND);
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ const float *col = is_act ? color_act : color_base;
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2);
+ immUniform1f("dash_width", 6.0f);
+
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+
+ immVertex2fv(shdr_pos, co_ss[0]);
+ immVertex2fv(shdr_pos, co_ss[1]);
+ immVertex2fv(shdr_pos, co_ss[2]);
+
+ immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* arc */
+ {
+ float dir_tmp[3];
+ float co_tmp[3];
+ float arc_ss_coord[2];
+
+ float dir_a[3];
+ float dir_b[3];
+ float quat[4];
+ float axis[3];
+ float angle;
+ const float px_scale = (ED_view3d_pixel_size(rv3d, ruler_item->co[1]) *
+ min_fff(arc_size,
+ len_v2v2(co_ss[0], co_ss[1]) / 2.0f,
+ len_v2v2(co_ss[2], co_ss[1]) / 2.0f));
+
+ sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]);
+ sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]);
+ normalize_v3(dir_a);
+ normalize_v3(dir_b);
+
+ cross_v3_v3v3(axis, dir_a, dir_b);
+ angle = angle_normalized_v3v3(dir_a, dir_b);
+
+ axis_angle_to_quat(quat, axis, angle / arc_steps);
+
+ copy_v3_v3(dir_tmp, dir_a);
+
+ immUniformColor3ubv(color_wire);
+
+ immBegin(GWN_PRIM_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_coord, V3D_PROJ_TEST_NOP);
+ mul_qt_v3(quat, dir_tmp);
+
+ immVertex2fv(shdr_pos, arc_ss_coord);
+ }
+
+ immEnd();
+ }
+
+ /* capping */
+ {
+ float rot_90_vec_a[2];
+ float rot_90_vec_b[2];
+ float cap[2];
+
+ sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]);
+ rot_90_vec_a[0] = -dir_ruler[1];
+ rot_90_vec_a[1] = dir_ruler[0];
+ normalize_v2(rot_90_vec_a);
+
+ sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]);
+ rot_90_vec_b[0] = -dir_ruler[1];
+ rot_90_vec_b[1] = dir_ruler[0];
+ normalize_v2(rot_90_vec_b);
+
+ glEnable(GL_BLEND);
+
+ immUniformColor3ubv(color_wire);
+
+ immBegin(GWN_PRIM_LINES, 8);
+
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
+ immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
+ immVertex2fv(shdr_pos, cap);
+
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
+ immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
+ immVertex2fv(shdr_pos, cap);
+
+ /* angle vertex */
+ immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
+ immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+
+ immEnd();
+
+ glDisable(GL_BLEND);
+ }
+
+ immUnbindProgram();
+
+ /* text */
+ {
+ char numstr[256];
+ float numstr_size[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]);
+
+ 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_aa(
+ true,
+ 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_rotation(blf_mono_font, 0.0f);
+ BLF_draw(blf_mono_font, numstr, sizeof(numstr));
+ }
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ const float *col = is_act ? color_act : color_base;
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2);
+ immUniform1f("dash_width", 6.0f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+
+ immVertex2fv(shdr_pos, co_ss[0]);
+ immVertex2fv(shdr_pos, co_ss[2]);
+
+ immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);
+
+ /* capping */
+ {
+ float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]};
+ float cap[2];
+
+ normalize_v2(rot_90_vec);
+
+ glEnable(GL_BLEND);
+
+ immUniformColor3ubv(color_wire);
+
+ immBegin(GWN_PRIM_LINES, 4);
+
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
+ immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
+ immVertex2fv(shdr_pos, cap);
+
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
+ immVertex2fv(shdr_pos, cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
+ immVertex2fv(shdr_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_aa(
+ true,
+ 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));
+ }
+ }
+
+ glDisable(GL_LINE_SMOOTH);
+
+ BLF_disable(blf_mono_font, BLF_ROTATION);
+
+#undef ARC_STEPS
+
+ /* draw snap */
+ if ((ruler_info->snap_flag & RULER_SNAP_OK) &&
+ (ruler_info->state == RULER_STATE_DRAG) &&
+ (ruler_item->mpr.interaction_data != NULL))
+ {
+ RulerInteraction *inter = ruler_item->mpr.interaction_data;
+ /* size from drawSnapping */
+ const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+ float co_ss_snap[3];
+ ED_view3d_project_float_global(ar, ruler_item->co[inter->co_index], co_ss_snap, V3D_PROJ_TEST_NOP);
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(color_act);
+
+ imm_draw_circle_wire_2d(pos, co_ss_snap[0], co_ss_snap[1], size * U.pixelsize, 32);
+
+ immUnbindProgram();
+ }
+}
+
+static int manipulator_ruler_test_select(
+ bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event)
+{
+ RulerItem *ruler_item_pick = (RulerItem *)mpr;
+ float mval_fl[2] = {UNPACK2(event->mval)};
+ int co_index;
+
+ /* select and drag */
+ if (view3d_ruler_pick(mpr->parent_mgroup, ruler_item_pick, mval_fl, &co_index)) {
+ if (co_index == -1) {
+ if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
+ return PART_LINE;
+ }
+ }
+ else {
+ return co_index;
+ }
+ }
+ return -1;
+}
+
+static int manipulator_ruler_modal(
+ bContext *C, wmManipulator *mpr, const wmEvent *event,
+ eWM_ManipulatorTweak UNUSED(tweak_flag))
+{
+ bool do_draw = false;
+ int exit_code = OPERATOR_RUNNING_MODAL;
+ RulerInfo *ruler_info = mpr->parent_mgroup->customdata;
+ RulerItem *ruler_item = (RulerItem *)mpr;
+ RulerInteraction *inter = ruler_item->mpr.interaction_data;
+ ARegion *ar = CTX_wm_region(C);
+
+ ruler_info->ar = ar;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ {
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ if (view3d_ruler_item_mousemove(
+ ruler_info, ruler_item, event->mval,
+ event->shift != 0, event->ctrl != 0))
+ {
+ do_draw = true;
+ }
+ inter->inside_region = BLI_rcti_isect_pt_v(&ar->winrct, &event->x);
+ }
+ break;
+ }
+ }
+ if (do_draw) {
+ ED_region_tag_redraw(ar);
+ }
+ return exit_code;
+}
+
+static int manipulator_ruler_invoke(
+ bContext *C, wmManipulator *mpr, const wmEvent *event)
+{
+ wmManipulatorGroup *mgroup = mpr->parent_mgroup;
+ RulerInfo *ruler_info = mgroup->customdata;
+ RulerItem *ruler_item_pick = (RulerItem *)mpr;
+ RulerInteraction *inter = MEM_callocN(sizeof(RulerInteraction), __func__);
+ mpr->interaction_data = inter;
+
+ ARegion *ar = ruler_info->ar;
+
+ const float mval_fl[2] = {UNPACK2(event->mval)};
+
+ /* select and drag */
+ if (mpr->highlight_part == PART_LINE) {
+ if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
+ /* Add Center Point */
+ ruler_item_pick->flag |= RULERITEM_USE_ANGLE;
+ inter->co_index = 1;
+ ruler_state_set(C, ruler_info, RULER_STATE_DRAG);
+
+ /* find the factor */
+ {
+ float co_ss[2][2];
+ float fac;
+
+ ED_view3d_project_float_global(ar, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP);
+ ED_view3d_project_float_global(ar, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP);
+
+ fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]);
+ CLAMP(fac, 0.0f, 1.0f);
+
+ interp_v3_v3v3(ruler_item_pick->co[1],
+ ruler_item_pick->co[0],
+ ruler_item_pick->co[2], fac);
+ }
+
+ /* update the new location */
+ view3d_ruler_item_mousemove(
+ ruler_info, ruler_item_pick, event->mval,
+ event->shift != 0, event->ctrl != 0);
+ }
+ }
+ else {
+ inter->co_index = mpr->highlight_part;
+ ruler_state_set(C, ruler_info, RULER_STATE_DRAG);
+
+ /* store the initial depth */
+ copy_v3_v3(inter->drag_start_co, ruler_item_pick->co[inter->co_index]);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void manipulator_ruler_exit(bContext *C, wmManipulator *mpr, const bool cancel)
+{
+ wmManipulatorGroup *mgroup = mpr->parent_mgroup;
+ RulerInfo *ruler_info = mgroup->customdata;
+ RulerItem *ruler_item = (RulerItem *)mpr;
+ RulerInteraction *inter = mpr->interaction_data;
+
+ if (!cancel) {
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ /* rubber-band angle removal */
+ if (ruler_item && (inter->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) {
+ if (!inter->inside_region) {
+ ruler_item->flag &= ~RULERITEM_USE_ANGLE;
+ }
+ }
+ if (ruler_info->snap_flag & RULER_SNAP_OK) {
+ ruler_info->snap_flag &= ~RULER_SNAP_OK;
+ }
+ ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
+ }
+ /* We could convert only the current manipulator, for now just re-generate. */
+ view3d_ruler_to_gpencil(C, mgroup);
+ }
+
+ MEM_SAFE_FREE(mpr->interaction_data);
+
+ ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
+}
+
+static int manipulator_ruler_cursor_get(wmManipulator *mpr)
+{
+ if (mpr->highlight_part == PART_LINE) {
+ return BC_CROSSCURSOR;
+ }
+ return BC_NSEW_SCROLLCURSOR;
+}
+
+void VIEW3D_WT_ruler_item(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "VIEW3D_WT_ruler_item";
+
+ /* api callbacks */
+ wt->draw = manipulator_ruler_draw;
+ wt->test_select = manipulator_ruler_test_select;
+ wt->modal = manipulator_ruler_modal;
+ wt->invoke = manipulator_ruler_invoke;
+ wt->exit = manipulator_ruler_exit;
+ wt->cursor_get = manipulator_ruler_cursor_get;
+
+ wt->struct_size = sizeof(RulerItem);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Ruler Manipulator Group
+ * \{ */
+
+static bool WIDGETGROUP_ruler_poll(const bContext *C, wmManipulatorGroupType *wgt)
+{
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ if (!STREQ(wgt->idname, workspace->tool.manipulator_group)) {
+ WM_manipulator_group_type_unlink_delayed_ptr(wgt);
+ return false;
+ }
+ return true;
+}
+
+static void WIDGETGROUP_ruler_setup(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ RulerInfo *ruler_info = MEM_callocN(sizeof(RulerInfo), __func__);
+
+ if (view3d_ruler_from_gpencil(C, mgroup)) {
+ /* nop */
+ }
+
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ ruler_info->win = win;
+ ruler_info->sa = sa;
+ ruler_info->ar = ar;
+
+ mgroup->customdata = ruler_info;
+}
+
+void VIEW3D_WGT_ruler(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Ruler Widgets";
+ wgt->idname = view3d_wgt_ruler_id;
+
+ wgt->flag |= WM_MANIPULATORGROUPTYPE_SCALE;
+
+ wgt->mmap_params.spaceid = SPACE_VIEW3D;
+ wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
+
+ wgt->poll = WIDGETGROUP_ruler_poll;
+ wgt->setup = WIDGETGROUP_ruler_setup;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Ruler Operator
+ * \{ */
+
+static int view3d_ruler_poll(bContext *C)
+{
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ if (!STREQ(view3d_wgt_ruler_id, workspace->tool.manipulator_group) ||
+ CTX_wm_region_view3d(C) == NULL)
+ {
+ return false;
+ }
+ return true;
+}
+
+static int view3d_ruler_add_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ wmManipulatorGroup *mgroup = WM_manipulatormap_group_find(mmap, view3d_wgt_ruler_id);
+ const bool use_depth = (v3d->drawtype >= OB_SOLID);
+
+ /* Create new line */
+ RulerItem *ruler_item;
+ ruler_item = ruler_item_add(mgroup);
+
+ /* This is a little weak, but there is no real good way to tweak directly. */
+ WM_manipulator_highlight_set(mmap, &ruler_item->mpr);
+ if (WM_operator_name_call(
+ C, "MANIPULATORGROUP_OT_manipulator_tweak",
+ WM_OP_INVOKE_REGION_WIN, NULL) == OPERATOR_RUNNING_MODAL)
+ {
+ RulerInfo *ruler_info = mgroup->customdata;
+ RulerInteraction *inter = ruler_item->mpr.interaction_data;
+ if (use_depth) {
+ /* snap the first point added, not essential but handy */
+ inter->co_index = 0;
+ view3d_ruler_item_mousemove(ruler_info, ruler_item, event->mval, false, true);
+ copy_v3_v3(inter->drag_start_co, ruler_item->co[inter->co_index]);
+ }
+ else {
+ negate_v3_v3(inter->drag_start_co, rv3d->ofs);
+ copy_v3_v3(ruler_item->co[0], inter->drag_start_co);
+ view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval);
+ }
+
+ copy_v3_v3(ruler_item->co[2], ruler_item->co[0]);
+ ruler_item->mpr.highlight_part = inter->co_index = 2;
+ }
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_ruler_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Ruler Add";
+ ot->idname = "VIEW3D_OT_ruler_add";
+ ot->description = "";
+
+ ot->invoke = view3d_ruler_add_invoke;
+ ot->poll = view3d_ruler_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index d71639c35d2..79fa9e14dc1 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -46,6 +46,7 @@
#include "BKE_appdir.h"
#include "BKE_blender_copybuffer.h"
#include "BKE_context.h"
+#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -81,14 +82,16 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
for (Group *group = bmain->group.first; group; group = group->id.next) {
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- if (go->ob && (go->ob->id.tag & LIB_TAG_DOIT)) {
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ if (object && (object->id.tag & LIB_TAG_DOIT)) {
BKE_copybuffer_tag_ID(&group->id);
/* don't expand out to all other objects */
group->id.tag &= ~LIB_TAG_NEED_EXPAND;
break;
}
}
+ FOREACH_GROUP_OBJECT_END
}
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
@@ -119,8 +122,8 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
if (RNA_boolean_get(op->ptr, "autoselect"))
flag |= FILE_AUTOSELECT;
- if (RNA_boolean_get(op->ptr, "active_layer"))
- flag |= FILE_ACTIVELAY;
+ if (RNA_boolean_get(op->ptr, "active_collection"))
+ flag |= FILE_ACTIVE_COLLECTION;
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
if (BKE_copybuffer_paste(C, str, flag, op->reports)) {
@@ -152,7 +155,7 @@ static void VIEW3D_OT_pastebuffer(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select pasted objects");
- RNA_def_boolean(ot->srna, "active_layer", true, "Active Layer", "Put pasted objects on the active layer");
+ RNA_def_boolean(ot->srna, "active_collection", true, "Active Collection", "Put pasted objects on the active collection");
}
/* ************************** registration **********************************/
@@ -193,7 +196,6 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_render_border);
WM_operatortype_append(VIEW3D_OT_clear_render_border);
WM_operatortype_append(VIEW3D_OT_zoom_border);
- WM_operatortype_append(VIEW3D_OT_manipulator);
WM_operatortype_append(VIEW3D_OT_enable_manipulator);
WM_operatortype_append(VIEW3D_OT_cursor3d);
WM_operatortype_append(VIEW3D_OT_select_lasso);
@@ -201,7 +203,6 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_camera_to_view);
WM_operatortype_append(VIEW3D_OT_camera_to_view_selected);
WM_operatortype_append(VIEW3D_OT_object_as_camera);
- WM_operatortype_append(VIEW3D_OT_localview);
WM_operatortype_append(VIEW3D_OT_game_start);
WM_operatortype_append(VIEW3D_OT_fly);
WM_operatortype_append(VIEW3D_OT_walk);
@@ -224,6 +225,8 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_toggle_render);
+ WM_operatortype_append(VIEW3D_OT_ruler_add);
+
transform_operatortypes();
}
@@ -240,24 +243,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
/* only for region 3D window */
keymap = WM_keymap_find(keyconf, "3D View", SPACE_VIEW3D, 0);
- /* Shift+LMB behavior first, so it has priority over KM_ANY item below. */
- kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "release_confirm", true);
- RNA_boolean_set(kmi->ptr, "use_planar_constraint", true);
- RNA_boolean_set(kmi->ptr, "use_accurate", false);
-
- kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "release_confirm", true);
- RNA_boolean_set(kmi->ptr, "use_planar_constraint", false);
- RNA_boolean_set(kmi->ptr, "use_accurate", true);
-
- /* Using KM_ANY here to allow holding modifiers before starting to transform. */
- kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_ANY, 0);
- RNA_boolean_set(kmi->ptr, "release_confirm", true);
- RNA_boolean_set(kmi->ptr, "use_planar_constraint", false);
- RNA_boolean_set(kmi->ptr, "use_accurate", false);
-
- WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_CLICK, 0, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_rotate", MIDDLEMOUSE, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_move", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0);
@@ -372,8 +358,6 @@ void view3d_keymap(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD7, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_BOTTOM);
RNA_boolean_set(kmi->ptr, "align_active", true);
-
- WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0);
#ifdef WITH_INPUT_NDOF
/* note: positioned here so keymaps show keyboard keys if assigned */
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 65a6dee2f6c..f8b02f0b405 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -36,14 +36,13 @@
#include "BLI_sys_types.h" /* int64_t */
-#include "BIF_gl.h" /* bglMats */
-#include "BIF_glutil.h" /* bglMats */
-
#include "BLI_math_vector.h"
#include "BKE_camera.h"
#include "BKE_screen.h"
+#include "GPU_matrix.h"
+
#include "ED_view3d.h" /* own include */
#define BL_NEAR_CLIP 0.001
@@ -656,16 +655,22 @@ void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obm
}
/**
- * Uses window coordinates (x,y) and depth component z to find a point in
- * modelspace */
-void ED_view3d_unproject(bglMats *mats, float out[3], const float x, const float y, const float z)
+ * Convert between region relative coordinates (x,y) and depth component z and
+ * a point in world space. */
+void ED_view3d_project(const struct ARegion *ar, const float world[3], float region[3])
{
- double ux, uy, uz;
+ // viewport is set up to make coordinates relative to the region, not window
+ RegionView3D *rv3d = ar->regiondata;
+ int viewport[4] = {0, 0, ar->winx, ar->winy};
- gluUnProject(x, y, z, mats->modelview, mats->projection,
- (GLint *)mats->viewport, &ux, &uy, &uz);
+ gpuProject(world, rv3d->viewmat, rv3d->winmat, viewport, region);
+}
+
+bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3])
+{
+ RegionView3D *rv3d = ar->regiondata;
+ int viewport[4] = {0, 0, ar->winx, ar->winy};
+ float region[3] = {regionx, regiony, regionz};
- out[0] = ux;
- out[1] = uy;
- out[2] = uz;
+ return gpuUnProject(region, rv3d->viewmat, rv3d->winmat, viewport, world);
}
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index f2c87953302..093425fc3bc 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -43,6 +43,9 @@
#include "BIF_gl.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -279,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), 0,
+ CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
ruler_info->ar, CTX_wm_view3d(C));
}
else {
@@ -425,12 +428,11 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
#define ARC_STEPS 24
const int arc_steps = ARC_STEPS;
int i;
- //unsigned int color_act = 0x666600;
- unsigned int color_act = 0xffffff;
- unsigned int color_base = 0x0;
- unsigned char color_back[4] = {0xff, 0xff, 0xff, 0x80};
+ const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ const float color_base[4] = {0.0f, 0.0f, 0.0f, 1.0f};
unsigned char color_text[3];
unsigned char color_wire[3];
+ float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f};
/* anti-aliased lines for more consistent appearance */
glEnable(GL_LINE_SMOOTH);
@@ -455,28 +457,37 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a
glEnable(GL_BLEND);
- cpack(is_act ? color_act : color_base);
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
if (ruler_item->flag & RULERITEM_USE_ANGLE) {
- glBegin(GL_LINE_STRIP);
- for (j = 0; j < 3; j++) {
- glVertex2fv(co_ss[j]);
- }
- glEnd();
- cpack(0xaaaaaa);
- setlinestyle(3);
- glBegin(GL_LINE_STRIP);
- for (j = 0; j < 3; j++) {
- glVertex2fv(co_ss[j]);
- }
- glEnd();
- setlinestyle(0);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ const float *col = is_act ? color_act : color_base;
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2);
+ immUniform1f("dash_width", 6.0f);
+
+ immBegin(GWN_PRIM_LINE_STRIP, 3);
+
+ immVertex2fv(shdr_pos, co_ss[0]);
+ immVertex2fv(shdr_pos, co_ss[1]);
+ immVertex2fv(shdr_pos, co_ss[2]);
+
+ immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* 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];
@@ -500,46 +511,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(GWN_PRIM_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(shdr_pos, arc_ss_coord);
+ }
- /* draw text (bg) */
- glColor4ubv(color_back);
- 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);
- /* 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,75 +544,84 @@ 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(GWN_PRIM_LINES, 8);
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
- glVertex2fv(cap);
+ immVertex2fv(shdr_pos, cap);
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
- glVertex2fv(cap);
+ immVertex2fv(shdr_pos, cap);
madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
- glVertex2fv(cap);
+ immVertex2fv(shdr_pos, cap);
madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
- glVertex2fv(cap);
+ immVertex2fv(shdr_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(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
+ immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_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) */
- glColor4ubv(color_back);
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);
+ UI_draw_roundbox_aa(true,
+ 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 {
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ const float *col = is_act ? color_act : color_base;
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2);
+ immUniform1f("dash_width", 6.0f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+
+ immVertex2fv(shdr_pos, co_ss[0]);
+ immVertex2fv(shdr_pos, co_ss[2]);
+
+ immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);
/* capping */
{
@@ -638,22 +631,56 @@ 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(GWN_PRIM_LINES, 4);
+
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
- glVertex2fv(cap);
+ immVertex2fv(shdr_pos, cap);
madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
- glVertex2fv(cap);
+ immVertex2fv(shdr_pos, cap);
madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
- glVertex2fv(cap);
+ immVertex2fv(shdr_pos, cap);
madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
- glVertex2fv(cap);
- glEnd();
+ immVertex2fv(shdr_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_aa(true,
+ 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));
+ }
}
}
@@ -672,8 +699,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 int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(color_act);
+
+ imm_draw_circle_wire_2d(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 05cf552e5cc..28e15b3bfee 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -63,16 +63,16 @@
#include "BKE_armature.h"
#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 "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "DEG_depsgraph.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -93,6 +93,8 @@
#include "UI_interface.h"
#include "GPU_draw.h"
+#include "GPU_glew.h"
+#include "GPU_matrix.h"
#include "view3d_intern.h" /* own include */
@@ -108,7 +110,10 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc)
{
memset(vc, 0, sizeof(ViewContext));
vc->ar = CTX_wm_region(C);
+ vc->depsgraph = CTX_data_depsgraph(C);
vc->scene = CTX_data_scene(C);
+ vc->view_layer = CTX_data_view_layer(C);
+ vc->engine_type = CTX_data_engine_type(C);
vc->v3d = CTX_wm_view3d(C);
vc->win = CTX_wm_window(C);
vc->rv3d = CTX_wm_region_view3d(C);
@@ -116,34 +121,6 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc)
vc->obedit = CTX_data_edit_object(C);
}
-/*
- * ob == NULL if you want global matrices
- * */
-void view3d_get_transformation(const ARegion *ar, RegionView3D *rv3d, Object *ob, bglMats *mats)
-{
- float cpy[4][4];
- int i, j;
-
- if (ob) {
- mul_m4_m4m4(cpy, rv3d->viewmat, ob->obmat);
- }
- else {
- copy_m4_m4(cpy, rv3d->viewmat);
- }
-
- for (i = 0; i < 4; ++i) {
- for (j = 0; j < 4; ++j) {
- mats->projection[i * 4 + j] = rv3d->winmat[i][j];
- mats->modelview[i * 4 + j] = cpy[i][j];
- }
- }
-
- mats->viewport[0] = ar->winrct.xmin;
- mats->viewport[1] = ar->winrct.ymin;
- mats->viewport[2] = ar->winx;
- mats->viewport[3] = ar->winy;
-}
-
/* ********************** view3d_select: selection manipulations ********************* */
/* local prototypes */
@@ -394,18 +371,18 @@ static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[]
bArmature *arm = ob->data;
if (arm->flag & ARM_HAS_VIZ_DEPS) {
/* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
}
-static void object_deselect_all_visible(Scene *scene, View3D *v3d)
+static void object_deselect_all_visible(ViewLayer *view_layer)
{
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 = view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE(base)) {
+ ED_object_base_select(base, BA_DESELECT);
}
}
}
@@ -416,15 +393,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->view_layer);
- 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->view_layer->object_bases.first; base; base = base->next) {
+ if (BASE_SELECTABLE(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)) {
@@ -481,7 +457,9 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, cons
}
}
-static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
+static void do_lasso_select_mesh(
+ const struct EvaluationContext *eval_ctx, ViewContext *vc,
+ const int mcords[][2], short moves, bool extend, bool select)
{
LassoSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
@@ -501,25 +479,25 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m
/* for non zbuf projections, don't change the GL state */
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- glLoadMatrixf(vc->rv3d->viewmat);
- bbsel = EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ gpuLoadMatrix(vc->rv3d->viewmat);
+ bbsel = EDBM_backbuf_border_mask_init(eval_ctx, vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
if (ts->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
edbm_backbuf_check_and_select_verts(vc->em, select);
}
else {
- mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenVert(eval_ctx, vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
}
if (ts->selectmode & SCE_SELECT_EDGE) {
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
data.pass = 0;
- mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ mesh_foreachScreenEdge(eval_ctx, vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
if (data.is_done == false) {
data.pass = 1;
- mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ mesh_foreachScreenEdge(eval_ctx, vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
@@ -528,7 +506,7 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m
edbm_backbuf_check_and_select_faces(vc->em, select);
}
else {
- mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenFace(eval_ctx, vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
}
@@ -727,7 +705,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv,
SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
}
}
-static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
+static void do_lasso_select_paintvert(const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
{
const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
Object *ob = vc->obact;
@@ -745,7 +723,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh
if (use_zbuf) {
bm_vertoffs = me->totvert + 1; /* max index array */
- EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ EDBM_backbuf_border_mask_init(eval_ctx, vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
edbm_backbuf_check_and_select_verts_obmode(me, select);
@@ -758,7 +736,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
- meshobject_foreachScreenVert(vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ meshobject_foreachScreenVert(eval_ctx, vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
@@ -767,7 +745,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh
}
paintvert_flush_flags(ob);
}
-static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
+static void do_lasso_select_paintface(const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
{
Object *ob = vc->obact;
Mesh *me = ob->data;
@@ -782,7 +760,7 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh
bm_vertoffs = me->totpoly + 1; /* max index array */
BLI_lasso_boundbox(&rect, mcords, moves);
- EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ EDBM_backbuf_border_mask_init(eval_ctx, vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
edbm_backbuf_check_and_select_tfaces(me, select);
@@ -828,16 +806,22 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc,
{
Object *ob = CTX_data_active_object(C);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (vc->obedit == NULL) { /* Object Mode */
- if (BKE_paint_select_face_test(ob))
- do_lasso_select_paintface(vc, mcords, moves, extend, select);
- else if (BKE_paint_select_vert_test(ob))
- do_lasso_select_paintvert(vc, mcords, moves, extend, select);
+ if (BKE_paint_select_face_test(ob)) {
+ do_lasso_select_paintface(&eval_ctx, vc, mcords, moves, extend, select);
+ }
+ else if (BKE_paint_select_vert_test(ob)) {
+ do_lasso_select_paintvert(&eval_ctx, vc, mcords, moves, extend, select);
+ }
else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
/* pass */
}
- else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT))
+ else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
PE_lasso_select(C, mcords, moves, extend, select);
+ }
else {
do_lasso_select_objects(vc, mcords, moves, extend, select);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
@@ -846,7 +830,7 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc,
else { /* Edit Mode */
switch (vc->obedit->type) {
case OB_MESH:
- do_lasso_select_mesh(vc, mcords, moves, extend, select);
+ do_lasso_select_mesh(&eval_ctx, vc, mcords, moves, extend, select);
break;
case OB_CURVE:
case OB_SURF:
@@ -930,7 +914,7 @@ static unsigned int samplerect(unsigned int *buf, int size, unsigned int dontdo)
base = LASTBASE;
if (base == 0) return 0;
- maxob = base->selcol;
+ maxob = base->object->select_color;
len = (size - 1) / 2;
rc = 0;
@@ -1016,8 +1000,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;
}
}
@@ -1028,8 +1012,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;
}
}
@@ -1073,14 +1057,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(ViewLayer *view_layer, Base *b) /* deselect all except b */
{
- Base *base;
-
- for (base = FIRSTBASE; base; base = base->next) {
- if (base->flag & SELECT) {
+ for (Base *base = view_layer->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);
}
}
}
@@ -1093,7 +1075,8 @@ static Base *object_mouse_select_menu(
short baseCount = 0;
bool ok;
LinkNode *linklist = NULL;
-
+
+ /* handle base->object->select_color */
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
ok = false;
@@ -1102,7 +1085,7 @@ static Base *object_mouse_select_menu(
if (buffer) {
for (int a = 0; a < hits; a++) {
/* index was converted */
- if (base->selcol == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
+ if (base->object->select_color == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
ok = true;
break;
}
@@ -1201,7 +1184,7 @@ static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const
/* we want a select buffer with bones, if there are... */
/* so check three selection levels and compare */
static int mixed_bones_object_selectbuffer(
- ViewContext *vc, unsigned int *buffer, const int mval[2],
+ const EvaluationContext *eval_ctx, ViewContext *vc, unsigned int *buffer, const int mval[2],
bool use_cycle, bool enumerate,
bool *r_do_nearest)
{
@@ -1241,7 +1224,7 @@ static int mixed_bones_object_selectbuffer(
view3d_opengl_select_cache_begin();
BLI_rcti_init_pt_radius(&rect, mval, 14);
- hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
+ hits15 = view3d_opengl_select(eval_ctx, vc, buffer, MAXPICKBUF, &rect, select_mode);
if (hits15 == 1) {
hits = selectbuffer_ret_hits_15(buffer, hits15);
goto finally;
@@ -1252,7 +1235,7 @@ static int mixed_bones_object_selectbuffer(
offs = 4 * hits15;
BLI_rcti_init_pt_radius(&rect, mval, 9);
- hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
+ hits9 = view3d_opengl_select(eval_ctx, vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
if (hits9 == 1) {
hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
goto finally;
@@ -1262,7 +1245,7 @@ static int mixed_bones_object_selectbuffer(
offs += 4 * hits9;
BLI_rcti_init_pt_radius(&rect, mval, 5);
- hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
+ hits5 = view3d_opengl_select(eval_ctx, vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
if (hits5 == 1) {
hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
goto finally;
@@ -1291,8 +1274,7 @@ finally:
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;
+ ViewLayer *view_layer = vc->view_layer;
Base *base, *basact = NULL;
int a;
@@ -1312,7 +1294,9 @@ 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(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) {
+ notcol = BASACT(view_layer)->object->select_color;
+ }
for (a = 0; a < hits; a++) {
if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
@@ -1322,10 +1306,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int
}
}
- base = FIRSTBASE;
+ base = FIRSTBASE(view_layer);
while (base) {
- if (BASE_SELECTABLE(v3d, base)) {
- if (base->selcol == selcol) break;
+ if (BASE_SELECTABLE(base)) {
+ if (base->object->select_color == selcol) break;
}
base = base->next;
}
@@ -1337,23 +1321,23 @@ 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(view_layer);
if (base == startbase) break;
}
- if (BASE_SELECTABLE(v3d, base)) {
+ if (BASE_SELECTABLE(base)) {
for (a = 0; a < hits; a++) {
if (has_bones) {
/* skip non-bone objects */
if ((buffer[4 * a + 3] & 0xFFFF0000)) {
- if (base->selcol == (buffer[(4 * a) + 3] & 0xFFFF))
+ if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF))
basact = base;
}
}
else {
- if (base->selcol == (buffer[(4 * a) + 3] & 0xFFFF))
+ if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF))
basact = base;
}
}
@@ -1362,7 +1346,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(view_layer);
if (base == startbase) break;
}
}
@@ -1373,6 +1357,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int
/* mval comes from event->mval, only use within region handlers */
Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
{
+ EvaluationContext eval_ctx;
ViewContext vc;
Base *basact = NULL;
unsigned int buffer[MAXPICKBUF];
@@ -1381,13 +1366,15 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
/* setup view context for argument to callbacks */
view3d_operator_needs_opengl(C);
+
+ CTX_data_eval_ctx(C, &eval_ctx);
view3d_set_viewcontext(C, &vc);
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, false, false, &do_nearest);
+ hits = mixed_bones_object_selectbuffer(&eval_ctx, &vc, buffer, mval, false, false, &do_nearest);
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.view_layer->object_bases.first, has_bones, do_nearest);
}
return basact;
@@ -1417,10 +1404,11 @@ static bool ed_object_select_pick(
bContext *C, const int mval[2],
bool extend, bool deselect, bool toggle, bool obcenter, bool enumerate, bool object)
{
+ EvaluationContext eval_ctx;
ViewContext vc;
ARegion *ar = CTX_wm_region(C);
- View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL;
bool is_obedit;
float dist = ED_view3d_select_dist_px() * 1.3333f;
@@ -1430,6 +1418,7 @@ static bool ed_object_select_pick(
/* setup view context for argument to callbacks */
+ CTX_data_eval_ctx(C, &eval_ctx);
view3d_set_viewcontext(C, &vc);
is_obedit = (vc.obedit != NULL);
@@ -1439,8 +1428,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(view_layer);
+ if (BASACT(view_layer) && BASACT(view_layer)->next) startbase = BASACT(view_layer)->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 */
@@ -1453,13 +1442,13 @@ static bool ed_object_select_pick(
else {
base = startbase;
while (base) {
- if (BASE_SELECTABLE(v3d, base)) {
+ if (BASE_SELECTABLE(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(view_layer)) dist_temp += 10.0f;
if (dist_temp < dist) {
dist = dist_temp;
basact = base;
@@ -1468,7 +1457,7 @@ static bool ed_object_select_pick(
}
base = base->next;
- if (base == NULL) base = FIRSTBASE;
+ if (base == NULL) base = FIRSTBASE(view_layer);
if (base == startbase) break;
}
}
@@ -1480,7 +1469,7 @@ static bool ed_object_select_pick(
// TIMEIT_START(select_time);
/* if objects have posemode set, the bones are in the same selection buffer */
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest);
+ hits = mixed_bones_object_selectbuffer(&eval_ctx, &vc, buffer, mval, true, enumerate, &do_nearest);
// TIMEIT_END(select_time);
@@ -1498,7 +1487,7 @@ static bool ed_object_select_pick(
if (has_bones && basact) {
if (basact->object->type == OB_CAMERA) {
- if (BASACT == basact) {
+ if (BASACT(view_layer) == basact) {
int i, hitresult;
bool changed = false;
@@ -1507,7 +1496,7 @@ static bool ed_object_select_pick(
/* if there's bundles in buffer select bundles first,
* so non-camera elements should be ignored in buffer */
- if (basact->selcol != (hitresult & 0xFFFF)) {
+ if (basact->object->select_color != (hitresult & 0xFFFF)) {
continue;
}
@@ -1536,8 +1525,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;
@@ -1555,27 +1544,27 @@ static bool ed_object_select_pick(
}
}
}
- else if (ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend, deselect, toggle, do_nearest)) {
+ else if (ED_do_pose_selectbuffer(scene, view_layer, basact, buffer, hits, extend, deselect, toggle, do_nearest)) {
/* then bone is found */
/* 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_object_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(view_layer) && (BASACT(view_layer)->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(view_layer))
basact = NULL;
}
}
@@ -1587,37 +1576,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(view_layer, 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(basact)) {
- oldbasact = BASACT;
+ oldbasact = BASACT(view_layer);
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(view_layer, 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 */
}
}
@@ -1673,7 +1662,8 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con
SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
}
}
-static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+static int do_paintvert_box_select(
+ const EvaluationContext *eval_ctx, ViewContext *vc, rcti *rect, bool select, bool extend)
{
const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
Mesh *me;
@@ -1697,7 +1687,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo
if (use_zbuf) {
selar = MEM_callocN(me->totvert + 1, "selar");
- ED_view3d_backbuf_validate(vc);
+ ED_view3d_backbuf_validate(eval_ctx, vc);
ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
rt = ibuf->rect;
@@ -1745,7 +1735,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
- meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ meshobject_foreachScreenVert(eval_ctx, vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
if (select == false) {
@@ -1860,7 +1850,8 @@ static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const
BM_face_select_set(data->vc->em->bm, efa, data->select);
}
}
-static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+static int do_mesh_box_select(
+ const struct EvaluationContext *eval_ctx, ViewContext *vc, rcti *rect, bool select, bool extend)
{
BoxSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
@@ -1874,26 +1865,26 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
/* for non zbuf projections, don't change the GL state */
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- glLoadMatrixf(vc->rv3d->viewmat);
- bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ gpuLoadMatrix(vc->rv3d->viewmat);
+ bbsel = EDBM_backbuf_border_init(eval_ctx, vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
if (ts->selectmode & SCE_SELECT_VERTEX) {
if (bbsel) {
edbm_backbuf_check_and_select_verts(vc->em, select);
}
else {
- mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenVert(eval_ctx, vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
}
if (ts->selectmode & SCE_SELECT_EDGE) {
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
data.pass = 0;
- mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ mesh_foreachScreenEdge(eval_ctx, vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
if (data.is_done == 0) {
data.pass = 1;
- mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ mesh_foreachScreenEdge(eval_ctx, vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
@@ -1902,7 +1893,7 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
edbm_backbuf_check_and_select_faces(vc->em, select);
}
else {
- mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenFace(eval_ctx, vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
}
@@ -1913,7 +1904,9 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
return OPERATOR_FINISHED;
}
-static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+static int do_meta_box_select(
+ const struct EvaluationContext *eval_ctx, ViewContext *vc,
+ const rcti *rect, bool select, bool extend)
{
MetaBall *mb = (MetaBall *)vc->obedit->data;
MetaElem *ml;
@@ -1922,7 +1915,7 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
unsigned int buffer[MAXPICKBUF];
int hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
+ hits = view3d_opengl_select(eval_ctx, vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
if (extend == false && select)
BKE_mball_deselect_all(mb);
@@ -1947,7 +1940,9 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
return OPERATOR_FINISHED;
}
-static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+static int do_armature_box_select(
+ const struct EvaluationContext *eval_ctx, ViewContext *vc,
+ const rcti *rect, bool select, bool extend)
{
bArmature *arm = vc->obedit->data;
EditBone *ebone;
@@ -1956,7 +1951,7 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
unsigned int buffer[MAXPICKBUF];
int hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
+ hits = view3d_opengl_select(eval_ctx, vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
/* clear flag we use to detect point was affected */
for (ebone = arm->edbo->first; ebone; ebone = ebone->next)
@@ -2020,8 +2015,30 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
+/**
+ * Compare result of 'GPU_select': 'uint[4]',
+ * needed for when we need to align with object draw-order.
+ */
+static int opengl_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
+{
+ /* 4th element is select id */
+ const uint sel_a = ((uint *)sel_a_p)[3];
+ const uint sel_b = ((uint *)sel_b_p)[3];
+
+ if (sel_a < sel_b) {
+ return -1;
+ }
+ else if (sel_a > sel_b) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, bool select, bool extend)
{
+ EvaluationContext eval_ctx;
Bone *bone;
Object *ob = vc->obact;
unsigned int *vbuffer = NULL; /* selection buffer */
@@ -2031,6 +2048,8 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
int totobj = MAXPICKBUF; /* XXX solve later */
int hits;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if ((ob) && (ob->mode & OB_MODE_POSE))
bone_only = 1;
else
@@ -2047,13 +2066,13 @@ 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->view_layer);
}
}
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer");
- hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL);
+ hits = view3d_opengl_select(&eval_ctx, vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL);
/*
* LOGIC NOTES (theeth):
* The buffer and ListBase have the same relative order, which makes the selection
@@ -2061,18 +2080,22 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
* is the same as the object, we have a hit and can move to the next color
* and object pair, if not, just move to the next object,
* keeping the same color until we have a hit.
- *
- * The buffer order is defined by OGL standard, hopefully no stupid GFX card
- * does it incorrectly.
*/
if (hits > 0) { /* no need to loop if there's no hit */
Base *base;
col = vbuffer + 3;
-
- for (base = vc->scene->base.first; base && hits; base = base->next) {
- if (BASE_SELECTABLE(vc->v3d, base)) {
- while (base->selcol == (*col & 0xFFFF)) { /* we got an object */
+
+ /* The draw order doesn't always match the order we populate the engine, see: T51695. */
+ qsort(vbuffer, hits, sizeof(uint[4]), opengl_select_buffer_cmp);
+
+ /*
+ * Even though 'DRW_draw_select_loop' uses 'DEG_OBJECT_ITER',
+ * we can be sure the order remains the same between both.
+ */
+ for (base = vc->view_layer->object_bases.first; base && hits; base = base->next) {
+ if (BASE_SELECTABLE(base)) {
+ while (base->object->select_color == (*col & 0xFFFF)) { /* we got an object */
if (*col & 0xFFFF0000) { /* we got a bone */
bone = get_indexed_bone(base->object, *col & ~(BONESEL_ANY));
if (bone) {
@@ -2091,7 +2114,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
}
}
else if (!bone_only) {
- ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
+ ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
}
col += 4; /* next color */
@@ -2108,7 +2131,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
if (arm && (arm->flag & ARM_HAS_VIZ_DEPS)) {
/* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
}
@@ -2123,6 +2146,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
static int view3d_borderselect_exec(bContext *C, wmOperator *op)
{
+ EvaluationContext eval_ctx;
ViewContext vc;
rcti rect;
bool extend;
@@ -2133,6 +2157,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
view3d_operator_needs_opengl(C);
/* setup view context for argument to callbacks */
+ CTX_data_eval_ctx(C, &eval_ctx);
view3d_set_viewcontext(C, &vc);
select = !RNA_boolean_get(op->ptr, "deselect");
@@ -2143,7 +2168,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
switch (vc.obedit->type) {
case OB_MESH:
vc.em = BKE_editmesh_from_object(vc.obedit);
- ret = do_mesh_box_select(&vc, &rect, select, extend);
+ ret = do_mesh_box_select(&eval_ctx, &vc, &rect, select, extend);
// if (EM_texFaceCheck())
if (ret & OPERATOR_FINISHED) {
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
@@ -2157,13 +2182,13 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
}
break;
case OB_MBALL:
- ret = do_meta_box_select(&vc, &rect, select, extend);
+ ret = do_meta_box_select(&eval_ctx, &vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
}
break;
case OB_ARMATURE:
- ret = do_armature_box_select(&vc, &rect, select, extend);
+ ret = do_armature_box_select(&eval_ctx, &vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
}
@@ -2184,10 +2209,10 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
ret = ED_sculpt_mask_box_select(C, &vc, &rect, select, extend);
}
else if (vc.obact && BKE_paint_select_face_test(vc.obact)) {
- ret = do_paintface_box_select(&vc, &rect, select, extend);
+ ret = do_paintface_box_select(&eval_ctx, &vc, &rect, select, extend);
}
else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) {
- ret = do_paintvert_box_select(&vc, &rect, select, extend);
+ ret = do_paintvert_box_select(&eval_ctx, &vc, &rect, select, extend);
}
else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
ret = PE_border_select(C, &rect, select, extend);
@@ -2431,13 +2456,13 @@ static void mesh_circle_doSelectFace(void *userData, BMFace *efa, const float sc
}
}
-static void mesh_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
+static void mesh_circle_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad)
{
ToolSettings *ts = vc->scene->toolsettings;
int bbsel;
CircleSelectUserData data;
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ bbsel = EDBM_backbuf_circle_init(eval_ctx, vc, mval[0], mval[1], (short)(rad + 1.0f));
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
vc->em = BKE_editmesh_from_object(vc->obedit);
@@ -2449,7 +2474,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva
edbm_backbuf_check_and_select_verts(vc->em, select);
}
else {
- mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenVert(eval_ctx, vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
}
@@ -2458,7 +2483,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva
edbm_backbuf_check_and_select_edges(vc->em, select);
}
else {
- mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ mesh_foreachScreenEdge(eval_ctx, vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
@@ -2467,7 +2492,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva
edbm_backbuf_check_and_select_faces(vc->em, select);
}
else {
- mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ mesh_foreachScreenFace(eval_ctx, vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
}
@@ -2475,7 +2500,7 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva
EDBM_selectmode_flush(vc->em);
}
-static void paint_facesel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
+static void paint_facesel_circle_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad)
{
Object *ob = vc->obact;
Mesh *me = ob->data;
@@ -2483,7 +2508,7 @@ static void paint_facesel_circle_select(ViewContext *vc, const bool select, cons
bm_vertoffs = me->totpoly + 1; /* max index array */
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ bbsel = EDBM_backbuf_circle_init(eval_ctx, vc, mval[0], mval[1], (short)(rad + 1.0f));
if (bbsel) {
edbm_backbuf_check_and_select_tfaces(me, select);
EDBM_backbuf_free();
@@ -2499,7 +2524,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv,
SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
}
}
-static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
+static void paint_vertsel_circle_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad)
{
const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0;
Object *ob = vc->obact;
@@ -2510,7 +2535,7 @@ static void paint_vertsel_circle_select(ViewContext *vc, const bool select, cons
if (use_zbuf) {
bm_vertoffs = me->totvert + 1; /* max index array */
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
+ bbsel = EDBM_backbuf_circle_init(eval_ctx, vc, mval[0], mval[1], (short)(rad + 1.0f));
if (bbsel) {
edbm_backbuf_check_and_select_verts_obmode(me, select);
EDBM_backbuf_free();
@@ -2522,7 +2547,7 @@ static void paint_vertsel_circle_select(ViewContext *vc, const bool select, cons
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
- meshobject_foreachScreenVert(vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ meshobject_foreachScreenVert(eval_ctx, vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
if (select != LEFTMOUSE) {
@@ -2666,7 +2691,7 @@ static void pose_circle_select(ViewContext *vc, const bool select, const int mva
if (arm->flag & ARM_HAS_VIZ_DEPS) {
/* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&vc->obact->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&vc->obact->id, OB_RECALC_DATA);
}
}
}
@@ -2776,11 +2801,12 @@ static void mball_circle_select(ViewContext *vc, const bool select, const int mv
/** Callbacks for circle selection in Editmode */
-static void obedit_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
+static void obedit_circle_select(
+ const struct EvaluationContext *eval_ctx, ViewContext *vc, const bool select, const int mval[2], float rad)
{
switch (vc->obedit->type) {
case OB_MESH:
- mesh_circle_select(vc, select, mval, rad);
+ mesh_circle_select(eval_ctx, vc, select, mval, rad);
break;
case OB_CURVE:
case OB_SURF:
@@ -2802,22 +2828,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;
+ ViewLayer *view_layer = vc->view_layer;
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(view_layer); base; base = base->next) {
+ if (BASE_SELECTABLE(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;
}
}
@@ -2840,22 +2866,24 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
if (CTX_data_edit_object(C) || BKE_paint_select_elem_test(obact) ||
(obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) )
{
+ EvaluationContext eval_ctx;
ViewContext vc;
view3d_operator_needs_opengl(C);
+ CTX_data_eval_ctx(C, &eval_ctx);
view3d_set_viewcontext(C, &vc);
if (CTX_data_edit_object(C)) {
- obedit_circle_select(&vc, select, mval, (float)radius);
+ obedit_circle_select(&eval_ctx, &vc, select, mval, (float)radius);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
}
else if (BKE_paint_select_face_test(obact)) {
- paint_facesel_circle_select(&vc, select, mval, (float)radius);
+ paint_facesel_circle_select(&eval_ctx, &vc, select, mval, (float)radius);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
}
else if (BKE_paint_select_vert_test(obact)) {
- paint_vertsel_circle_select(&vc, select, mval, (float)radius);
+ paint_vertsel_circle_select(&eval_ctx, &vc, select, mval, (float)radius);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
}
else if (obact->mode & OB_MODE_POSE)
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 5dd69cc66eb..1df29201bf6 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -40,13 +40,14 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_mball.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_tracking.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -73,9 +74,12 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
RegionView3D *rv3d = CTX_wm_region_data(C);
TransVertStore tvs = {NULL};
TransVert *tv;
+ EvaluationContext eval_ctx;
float gridf, imat[3][3], bmat[3][3], vec[3];
int a;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
gridf = rv3d->gridview;
if (obedit) {
@@ -153,7 +157,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
}
ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else {
vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf);
@@ -162,7 +166,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
if (ob->parent) {
float originmat[3][3];
- BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);
+ BKE_object_where_is_calc_ex(&eval_ctx, scene, NULL, ob, originmat);
invert_m3_m3(imat, originmat);
mul_m3_v3(imat, vec);
@@ -177,7 +181,7 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
/* auto-keyframing */
ED_autokeyframe_object(C, scene, ob, ks);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
CTX_DATA_END;
@@ -213,11 +217,14 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global
View3D *v3d = CTX_wm_view3d(C);
TransVertStore tvs = {NULL};
TransVert *tv;
+ EvaluationContext eval_ctx;
float imat[3][3], bmat[3][3];
float center_global[3];
float offset_global[3];
int a;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
if (use_offset) {
if ((v3d && v3d->around == V3D_AROUND_ACTIVE) &&
snap_calc_active_center(C, true, center_global))
@@ -329,7 +336,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global
obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
- DAG_id_tag_update(&obact->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obact->id, OB_RECALC_DATA);
}
else {
struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
@@ -370,7 +377,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global
if (ob->parent) {
float originmat[3][3];
- BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);
+ BKE_object_where_is_calc_ex(&eval_ctx, scene, NULL, ob, originmat);
invert_m3_m3(imat, originmat);
mul_m3_v3(imat, cursor_parent);
@@ -385,7 +392,7 @@ static int snap_selected_to_location(bContext *C, const float snap_target_global
/* auto-keyframing */
ED_autokeyframe_object(C, scene, ob, ks);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 0bccab626e6..882f0ec0bc0 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -43,7 +43,6 @@
#include "BKE_action.h"
#include "BKE_camera.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_object.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -51,12 +50,15 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
-#include "BIF_gl.h"
+#include "DEG_depsgraph.h"
+
#include "BIF_glutil.h"
#include "UI_resources.h"
+#include "GPU_glew.h"
#include "GPU_select.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -64,6 +66,8 @@
#include "ED_screen.h"
#include "ED_armature.h"
+#include "DRW_engine.h"
+
#ifdef WITH_GAMEENGINE
# include "BLI_listbase.h"
@@ -98,10 +102,8 @@ void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
RegionView3D *rv3d = ar->regiondata;
wmSubWindowSet(win, ar->swinid);
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadProjectionMatrix(rv3d->winmat);
+ gpuLoadMatrix(rv3d->viewmat);
}
}
@@ -443,6 +445,9 @@ void ED_view3d_smooth_view_force_finish(
View3D *v3d, ARegion *ar)
{
RegionView3D *rv3d = ar->regiondata;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
if (rv3d && rv3d->sms) {
rv3d->sms->time_allowed = 0.0; /* force finishing */
@@ -451,7 +456,7 @@ void ED_view3d_smooth_view_force_finish(
/* force update of view matrix so tools that run immediately after
* can use them without redrawing first */
Scene *scene = CTX_data_scene(C);
- ED_view3d_update_viewmat(scene, v3d, ar, NULL, NULL, NULL);
+ ED_view3d_update_viewmat(&eval_ctx, scene, v3d, ar, NULL, NULL, NULL);
}
}
@@ -493,7 +498,7 @@ static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op))
BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag);
- DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
+ DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
rv3d->persp = RV3D_CAMOB;
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, v3d->camera);
@@ -541,6 +546,7 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
Object *camera_ob = v3d ? v3d->camera : scene->camera;
@@ -553,7 +559,7 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
}
/* this function does all the important stuff */
- if (BKE_camera_view_frame_fit_to_scene(scene, v3d, camera_ob, r_co, &r_scale)) {
+ if (BKE_camera_view_frame_fit_to_scene(scene, view_layer, camera_ob, r_co, &r_scale)) {
ObjectTfmProtectedChannels obtfm;
float obmat_new[4][4];
@@ -570,7 +576,7 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D);
/* notifiers */
- DAG_id_tag_update(&camera_ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&camera_ob->id, OB_RECALC_OB);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, camera_ob);
return OPERATOR_FINISHED;
}
@@ -727,40 +733,35 @@ void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb,
}
}
-void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect)
+void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect)
{
- float modelview[4][4];
- double xs, ys, p[3];
- int val, flip_sign, a;
-
- /* near zero floating point values can give issues with gluUnProject
- * in side view on some implementations */
- if (fabs(mats->modelview[0]) < 1e-6) mats->modelview[0] = 0.0;
- if (fabs(mats->modelview[5]) < 1e-6) mats->modelview[5] = 0.0;
-
- /* Set up viewport so that gluUnProject will give correct values */
- mats->viewport[0] = 0;
- mats->viewport[1] = 0;
+ /* init in case unproject fails */
+ memset(bb->vec, 0, sizeof(bb->vec));
/* four clipping planes and bounding volume */
/* first do the bounding volume */
- for (val = 0; val < 4; val++) {
- xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax;
- ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax;
+ for (int val = 0; val < 4; val++) {
+ float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax;
+ float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax;
- gluUnProject(xs, ys, 0.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]);
- copy_v3fl_v3db(bb->vec[val], p);
+ ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]);
+ ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]);
+ }
- gluUnProject(xs, ys, 1.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]);
- copy_v3fl_v3db(bb->vec[4 + val], p);
+ /* optionally transform to object space */
+ if (ob) {
+ float imat[4][4];
+ invert_m4_m4(imat, ob->obmat);
+
+ for (int val = 0; val < 8; val++) {
+ mul_m4_v3(imat, bb->vec[val]);
+ }
}
/* verify if we have negative scale. doing the transform before cross
* product flips the sign of the vector compared to doing cross product
* before transform then, so we correct for that. */
- for (a = 0; a < 16; a++)
- ((float *)modelview)[a] = mats->modelview[a];
- flip_sign = is_negative_m4(modelview);
+ int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false;
ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign);
}
@@ -836,7 +837,7 @@ float ED_view3d_depth_read_cached(const ViewContext *vc, const int mval[2])
}
bool ED_view3d_depth_read_cached_normal(
- const ViewContext *vc, const bglMats *mats, const int mval[2],
+ const ViewContext *vc, const int mval[2],
float r_normal[3])
{
/* Note: we could support passing in a radius.
@@ -855,7 +856,7 @@ bool ED_view3d_depth_read_cached_normal(
const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs);
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
- if (ED_view3d_depth_unproject(ar, mats, mval_ofs, depth, coords[i])) {
+ if (ED_view3d_depth_unproject(ar, mval_ofs, depth, coords[i])) {
depths_valid[i] = true;
}
}
@@ -897,21 +898,13 @@ bool ED_view3d_depth_read_cached_normal(
}
bool ED_view3d_depth_unproject(
- const ARegion *ar, const bglMats *mats,
+ const ARegion *ar,
const int mval[2], const double depth,
float r_location_world[3])
{
- double p[3];
- if (gluUnProject(
- (double)ar->winrct.xmin + mval[0] + 0.5,
- (double)ar->winrct.ymin + mval[1] + 0.5,
- depth, mats->modelview, mats->projection, (const GLint *)mats->viewport,
- &p[0], &p[1], &p[2]))
- {
- copy_v3fl_v3db(r_location_world, p);
- return true;
- }
- return false;
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
+ return ED_view3d_unproject(ar, centx, centy, depth, r_location_world);
}
/** \} */
@@ -1025,14 +1018,14 @@ void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect)
}
if (is_ortho) {
- wmOrtho(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+ gpuOrtho(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
}
else {
- wmFrustum(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+ gpuFrustum(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
}
/* update matrix in 3d view region */
- glGetFloatv(GL_PROJECTION_MATRIX, (float *)rv3d->winmat);
+ gpuGetProjectionMatrix(rv3d->winmat);
}
static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
@@ -1116,11 +1109,11 @@ bool ED_view3d_lock(RegionView3D *rv3d)
}
/* don't set windows active in here, is used by renderwin too */
-void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d)
+void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d)
{
if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */
if (v3d->camera) {
- BKE_object_where_is_calc(scene, v3d->camera);
+ BKE_object_where_is_calc(eval_ctx, scene, v3d->camera);
obmat_to_viewmat(rv3d, v3d->camera);
}
else {
@@ -1205,10 +1198,11 @@ void view3d_opengl_select_cache_end(void)
* \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection.
*/
int view3d_opengl_select(
- ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input,
+ const EvaluationContext *eval_ctx, ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input,
eV3DSelectMode select_mode)
{
struct bThemeState theme_state;
+ Depsgraph *graph = vc->depsgraph;
Scene *scene = vc->scene;
View3D *v3d = vc->v3d;
ARegion *ar = vc->ar;
@@ -1270,7 +1264,7 @@ int view3d_opengl_select(
/* Important we use the 'viewmat' and don't re-calculate since
* the object & bone view locking takes 'rect' into account, see: T51629. */
- ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect);
+ ED_view3d_draw_setup_view(vc->win, eval_ctx, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect);
if (v3d->drawtype > OB_WIRE) {
v3d->zbuf = true;
@@ -1282,7 +1276,16 @@ int view3d_opengl_select(
GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
- ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest);
+#ifdef WITH_OPENGL_LEGACY
+ if (IS_VIEWPORT_LEGACY(vc->v3d)) {
+ ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
+ }
+ else
+#else
+ {
+ DRW_draw_select_loop(graph, ar, v3d, use_obedit_skip, use_nearest, &rect);
+ }
+#endif /* WITH_OPENGL_LEGACY */
hits = GPU_select_end();
@@ -1290,13 +1293,22 @@ int view3d_opengl_select(
if (do_passes && (hits > 0)) {
GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
- ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest);
+#ifdef WITH_OPENGL_LEGACY
+ if (IS_VIEWPORT_LEGACY(vc->v3d)) {
+ ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
+ }
+ else
+#else
+ {
+ DRW_draw_select_loop(graph, ar, v3d, use_obedit_skip, use_nearest, &rect);
+ }
+#endif /* WITH_OPENGL_LEGACY */
GPU_select_end();
}
G.f &= ~G_PICKSEL;
- ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
+ ED_view3d_draw_setup_view(vc->win, eval_ctx, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL);
if (v3d->drawtype > OB_WIRE) {
v3d->zbuf = 0;
@@ -1314,43 +1326,7 @@ finally:
return hits;
}
-/* ********************** local view operator ******************** */
-
-static unsigned int free_localbit(Main *bmain)
-{
- unsigned int lay;
- ScrArea *sa;
- bScreen *sc;
-
- lay = 0;
-
- /* sometimes we loose a localview: when an area is closed */
- /* check all areas: which localviews are in use? */
- for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl = sa->spacedata.first;
- for (; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *) sl;
- lay |= v3d->lay;
- }
- }
- }
- }
-
- if ((lay & 0x01000000) == 0) return 0x01000000;
- if ((lay & 0x02000000) == 0) return 0x02000000;
- if ((lay & 0x04000000) == 0) return 0x04000000;
- if ((lay & 0x08000000) == 0) return 0x08000000;
- if ((lay & 0x10000000) == 0) return 0x10000000;
- if ((lay & 0x20000000) == 0) return 0x20000000;
- if ((lay & 0x40000000) == 0) return 0x40000000;
- if ((lay & 0x80000000) == 0) return 0x80000000;
-
- return 0;
-}
-
-int ED_view3d_scene_layer_set(int lay, const int *values, int *active)
+int ED_view3d_view_layer_set(int lay, const int *values, int *active)
{
int i, tot = 0;
@@ -1388,267 +1364,6 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active)
return lay;
}
-static bool view3d_localview_init(
- wmWindowManager *wm, wmWindow *win,
- Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx,
- ReportList *reports)
-{
- View3D *v3d = sa->spacedata.first;
- Base *base;
- float min[3], max[3], box[3], mid[3];
- float size = 0.0f;
- unsigned int locallay;
- bool ok = false;
-
- if (v3d->localvd) {
- return ok;
- }
-
- INIT_MINMAX(min, max);
-
- locallay = free_localbit(bmain);
-
- if (locallay == 0) {
- BKE_report(reports, RPT_ERROR, "No more than 8 local views");
- ok = false;
- }
- else {
- if (scene->obedit) {
- BKE_object_minmax(scene->obedit, min, max, false);
-
- ok = true;
-
- BASACT->lay |= locallay;
- scene->obedit->lay = BASACT->lay;
- }
- else {
- for (base = FIRSTBASE; base; base = base->next) {
- if (TESTBASE(v3d, base)) {
- BKE_object_minmax(base->object, min, max, false);
- base->lay |= locallay;
- base->object->lay = base->lay;
- ok = true;
- }
- }
- }
-
- sub_v3_v3v3(box, max, min);
- size = max_fff(box[0], box[1], box[2]);
- }
-
- if (ok == true) {
- ARegion *ar;
-
- v3d->localvd = MEM_mallocN(sizeof(View3D), "localview");
-
- memcpy(v3d->localvd, v3d, sizeof(View3D));
-
- mid_v3_v3v3(mid, min, max);
-
- copy_v3_v3(v3d->cursor, mid);
-
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
- bool ok_dist = true;
-
- /* new view values */
- Object *camera_old = NULL;
- float dist_new, ofs_new[3];
-
- rv3d->localvd = MEM_mallocN(sizeof(RegionView3D), "localview region");
- memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D));
-
- negate_v3_v3(ofs_new, mid);
-
- if (rv3d->persp == RV3D_CAMOB) {
- rv3d->persp = RV3D_PERSP;
- camera_old = v3d->camera;
- }
-
- if (rv3d->persp == RV3D_ORTHO) {
- if (size < 0.0001f) {
- ok_dist = false;
- }
- }
-
- if (ok_dist) {
- dist_new = ED_view3d_radius_to_dist(v3d, ar, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN);
- if (rv3d->persp == RV3D_PERSP) {
- /* don't zoom closer than the near clipping plane */
- dist_new = max_ff(dist_new, v3d->near * 1.5f);
- }
- }
-
- ED_view3d_smooth_view_ex(
- wm, win, sa, v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) {
- .camera_old = camera_old,
- .ofs = ofs_new, .quat = rv3d->viewquat,
- .dist = ok_dist ? &dist_new : NULL, .lens = &v3d->lens});
- }
- }
-
- v3d->lay = locallay;
- }
- else {
- /* clear flags */
- for (base = FIRSTBASE; base; base = base->next) {
- if (base->lay & locallay) {
- base->lay -= locallay;
- if (base->lay == 0) base->lay = v3d->layact;
- if (base->object != scene->obedit) base->flag |= SELECT;
- base->object->lay = base->lay;
- }
- }
- }
-
- DAG_on_visible_update(bmain, false);
-
- return ok;
-}
-
-static void restore_localviewdata(wmWindowManager *wm, wmWindow *win, Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx)
-{
- const bool free = true;
- ARegion *ar;
- View3D *v3d = sa->spacedata.first;
- Object *camera_old, *camera_new;
-
- if (v3d->localvd == NULL) return;
-
- camera_old = v3d->camera;
- camera_new = v3d->localvd->camera;
-
- v3d->lay = v3d->localvd->lay;
- v3d->layact = v3d->localvd->layact;
- v3d->drawtype = v3d->localvd->drawtype;
- v3d->camera = v3d->localvd->camera;
-
- if (free) {
- MEM_freeN(v3d->localvd);
- v3d->localvd = NULL;
- }
-
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d->localvd) {
- Object *camera_old_rv3d, *camera_new_rv3d;
-
- camera_old_rv3d = (rv3d->persp == RV3D_CAMOB) ? camera_old : NULL;
- camera_new_rv3d = (rv3d->localvd->persp == RV3D_CAMOB) ? camera_new : NULL;
-
- rv3d->view = rv3d->localvd->view;
- rv3d->persp = rv3d->localvd->persp;
- rv3d->camzoom = rv3d->localvd->camzoom;
-
- ED_view3d_smooth_view_ex(
- wm, win, sa,
- v3d, ar, smooth_viewtx,
- &(const V3D_SmoothParams) {
- .camera_old = camera_old_rv3d, .camera = camera_new_rv3d,
- .ofs = rv3d->localvd->ofs, .quat = rv3d->localvd->viewquat,
- .dist = &rv3d->localvd->dist});
-
- if (free) {
- MEM_freeN(rv3d->localvd);
- rv3d->localvd = NULL;
- }
- }
-
- ED_view3d_shade_update(bmain, scene, v3d, sa);
- }
- }
-}
-
-static bool view3d_localview_exit(
- wmWindowManager *wm, wmWindow *win,
- Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx)
-{
- View3D *v3d = sa->spacedata.first;
- struct Base *base;
- unsigned int locallay;
-
- if (v3d->localvd) {
-
- locallay = v3d->lay & 0xFF000000;
-
- restore_localviewdata(wm, win, bmain, scene, sa, smooth_viewtx);
-
- /* for when in other window the layers have changed */
- if (v3d->scenelock) v3d->lay = scene->lay;
-
- for (base = FIRSTBASE; base; base = base->next) {
- if (base->lay & locallay) {
- base->lay -= locallay;
- if (base->lay == 0) base->lay = v3d->layact;
- if (base->object != scene->obedit) {
- base->flag |= SELECT;
- base->object->flag |= SELECT;
- }
- base->object->lay = base->lay;
- }
- }
-
- DAG_on_visible_update(bmain, false);
-
- return true;
- }
- else {
- return false;
- }
-}
-
-static int localview_exec(bContext *C, wmOperator *op)
-{
- const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win = CTX_wm_window(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = CTX_wm_view3d(C);
- bool changed;
-
- if (v3d->localvd) {
- changed = view3d_localview_exit(wm, win, bmain, scene, sa, smooth_viewtx);
- }
- else {
- changed = view3d_localview_init(wm, win, bmain, scene, sa, smooth_viewtx, op->reports);
- }
-
- if (changed) {
- DAG_id_type_tag(bmain, ID_OB);
- ED_area_tag_redraw(sa);
-
- /* unselected objects become selected when exiting */
- if (v3d->localvd == NULL) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
-}
-
-void VIEW3D_OT_localview(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Local View";
- ot->description = "Toggle display of selected object(s) separately and centered in view";
- ot->idname = "VIEW3D_OT_localview";
-
- /* api callbacks */
- ot->exec = localview_exec;
- ot->flag = OPTYPE_UNDO; /* localview changes object layer bitflags */
-
- ot->poll = ED_operator_view3d_active;
-}
-
#ifdef WITH_GAMEENGINE
static ListBase queue_back;
@@ -1687,7 +1402,6 @@ static void RestoreState(bContext *C, wmWindow *win)
win->queue = queue_back;
GPU_state_init();
- GPU_set_tpage(NULL, 0, 0);
glPopAttrib();
}
@@ -1730,10 +1444,6 @@ static void game_set_commmandline_options(GameData *gm)
SYS_WriteCommandLineInt(syshandle, "blender_material", test);
test = (gm->matmode == GAME_MAT_GLSL);
SYS_WriteCommandLineInt(syshandle, "blender_glsl_material", test);
- test = (gm->flag & GAME_DISPLAY_LISTS);
- SYS_WriteCommandLineInt(syshandle, "displaylists", test);
-
-
}
}
@@ -1741,19 +1451,21 @@ static void game_set_commmandline_options(GameData *gm)
static int game_engine_poll(bContext *C)
{
- bScreen *screen;
+ const wmWindow *win = CTX_wm_window(C);
+ const Scene *scene = WM_window_get_active_scene(win);
+
/* we need a context and area to launch BGE
* it's a temporary solution to avoid crash at load time
* if we try to auto run the BGE. Ideally we want the
* context to be set as soon as we load the file. */
- if (CTX_wm_window(C) == NULL) return 0;
- if ((screen = CTX_wm_screen(C)) == NULL) return 0;
+ if (win == NULL) return 0;
+ if (CTX_wm_screen(C) == NULL) return 0;
if (CTX_data_mode_enum(C) != CTX_MODE_OBJECT)
return 0;
- if (!BKE_scene_uses_blender_game(screen->scene))
+ if (!BKE_scene_uses_blender_game(scene))
return 0;
return 1;
@@ -1862,7 +1574,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
//XXX restore_all_scene_cfra(scene_cfra_store);
BKE_scene_set_background(CTX_data_main(C), startscene);
- //XXX BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
+ //XXX BKE_scene_graph_update_for_newframe(bmain->eval_ctx, bmain, scene, depsgraph);
BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_POST);
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 9464f332d39..76da1faf530 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -56,6 +56,10 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_immediate.h"
+
+#include "RE_engine.h"
+
#include "view3d_intern.h" /* own include */
#ifdef WITH_INPUT_NDOF
@@ -246,6 +250,8 @@ typedef struct WalkInfo {
View3D *v3d;
ARegion *ar;
Scene *scene;
+ ViewLayer *view_layer;
+ RenderEngineType *engine_type;
wmTimer *timer; /* needed for redraws */
@@ -337,24 +343,33 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a
yoff = walk->ar->winy / 2;
}
- UI_ThemeColor(TH_VIEW_OVERLAY);
- glBegin(GL_LINES);
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+
+ immBegin(GWN_PRIM_LINES, 8);
+
/* North */
- glVertex2i(xoff, yoff + inner_length);
- glVertex2i(xoff, yoff + outter_length);
+ immVertex2i(pos, xoff, yoff + inner_length);
+ immVertex2i(pos, xoff, yoff + outter_length);
/* East */
- glVertex2i(xoff + inner_length, yoff);
- glVertex2i(xoff + outter_length, yoff);
+ immVertex2i(pos, xoff + inner_length, yoff);
+ immVertex2i(pos, xoff + outter_length, yoff);
/* South */
- glVertex2i(xoff, yoff - inner_length);
- glVertex2i(xoff, yoff - outter_length);
+ immVertex2i(pos, xoff, yoff - inner_length);
+ immVertex2i(pos, xoff, yoff - outter_length);
/* West */
- glVertex2i(xoff - inner_length, yoff);
- glVertex2i(xoff - outter_length, yoff);
- glEnd();
+ immVertex2i(pos, xoff - inner_length, yoff);
+ immVertex2i(pos, xoff - outter_length, yoff);
+
+ immEnd();
+ immUnbindProgram();
}
static void walk_update_header(bContext *C, wmOperator *op, WalkInfo *walk)
@@ -499,6 +514,8 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->v3d = CTX_wm_view3d(C);
walk->ar = CTX_wm_region(C);
walk->scene = CTX_data_scene(C);
+ walk->view_layer = CTX_data_view_layer(C);
+ walk->engine_type = CTX_data_engine_type(C);
#ifdef NDOF_WALK_DEBUG
puts("\n-- walk begin --");
@@ -587,11 +604,11 @@ 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, 0,
+ CTX_data_main(C), walk->scene, walk->view_layer, walk->engine_type, 0,
walk->ar, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
- walk->scene, walk->v3d, walk->rv3d,
+ C, walk->scene, walk->v3d, walk->rv3d,
(U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
/* center the mouse */
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index b7de49d8158..f38f6c064b8 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -29,6 +29,7 @@ set(INC
../../ikplugin
../../makesdna
../../makesrna
+ ../../render/extern/include
../../windowmanager
../../depsgraph
../../../../intern/guardedalloc
@@ -46,6 +47,7 @@ set(SRC
transform_generics.c
transform_input.c
transform_manipulator.c
+ transform_manipulator2d.c
transform_ops.c
transform_orientations.c
transform_snap.c
@@ -58,10 +60,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
-if(WITH_LEGACY_DEPSGRAPH)
- add_definitions(-DWITH_LEGACY_DEPSGRAPH)
-endif()
-
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_editor_transform "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index b25ab1c6a89..5a63532b0f5 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -43,6 +43,7 @@
#include "DNA_mask_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h" /* PET modes */
+#include "DNA_workspace_types.h"
#include "BLI_alloca.h"
#include "BLI_utildefines.h"
@@ -63,10 +64,16 @@
#include "BKE_unit.h"
#include "BKE_mask.h"
#include "BKE_report.h"
+#include "BKE_workspace.h"
+
+#include "DEG_depsgraph.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+
#include "ED_image.h"
#include "ED_keyframing.h"
#include "ED_screen.h"
@@ -1598,8 +1605,16 @@ typedef enum {
LEFT,
RIGHT
} ArrowDirection;
+
+#define POS_INDEX 0
+/* NOTE: this --^ is a bit hackish, but simplifies Gwn_VertFormat usage among functions
+ * private to this file - merwin
+ */
+
static void drawArrow(ArrowDirection d, short offset, short length, short size)
{
+ immBegin(GWN_PRIM_LINES, 6);
+
switch (d) {
case LEFT:
offset = -offset;
@@ -1607,14 +1622,12 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size)
size = -size;
ATTR_FALLTHROUGH;
case RIGHT:
- glBegin(GL_LINES);
- glVertex2s(offset, 0);
- glVertex2s(offset + length, 0);
- glVertex2s(offset + length, 0);
- glVertex2s(offset + length - size, -size);
- glVertex2s(offset + length, 0);
- glVertex2s(offset + length - size, size);
- glEnd();
+ immVertex2f(POS_INDEX, offset, 0);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length - size, -size);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length - size, size);
break;
case DOWN:
@@ -1623,45 +1636,45 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size)
size = -size;
ATTR_FALLTHROUGH;
case UP:
- glBegin(GL_LINES);
- glVertex2s(0, offset);
- glVertex2s(0, offset + length);
- glVertex2s(0, offset + length);
- glVertex2s(-size, offset + length - size);
- glVertex2s(0, offset + length);
- glVertex2s(size, offset + length - size);
- glEnd();
+ immVertex2f(POS_INDEX, 0, offset);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, -size, offset + length - size);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, size, offset + length - size);
break;
}
+
+ immEnd();
}
static void drawArrowHead(ArrowDirection d, short size)
{
+ immBegin(GWN_PRIM_LINES, 4);
+
switch (d) {
case LEFT:
size = -size;
ATTR_FALLTHROUGH;
case RIGHT:
- glBegin(GL_LINES);
- glVertex2s(0, 0);
- glVertex2s(-size, -size);
- glVertex2s(0, 0);
- glVertex2s(-size, size);
- glEnd();
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, -size);
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, size);
break;
case DOWN:
size = -size;
ATTR_FALLTHROUGH;
case UP:
- glBegin(GL_LINES);
- glVertex2s(0, 0);
- glVertex2s(-size, -size);
- glVertex2s(0, 0);
- glVertex2s(size, -size);
- glEnd();
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, -size);
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, size, -size);
break;
}
+
+ immEnd();
}
static void drawArc(float size, float angle_start, float angle_end, int segments)
@@ -1670,14 +1683,14 @@ static void drawArc(float size, float angle_start, float angle_end, int segments
float angle;
int a;
- glBegin(GL_LINE_STRIP);
+ immBegin(GWN_PRIM_LINE_STRIP, segments + 1);
for (angle = angle_start, a = 0; a < segments; angle += delta, a++) {
- glVertex2f(cosf(angle) * size, sinf(angle) * size);
+ immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size);
}
- glVertex2f(cosf(angle_end) * size, sinf(angle_end) * size);
+ immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size);
- glEnd();
+ immEnd();
}
static int helpline_poll(bContext *C)
@@ -1693,12 +1706,9 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
{
TransInfo *t = (TransInfo *)customdata;
- if (t->helpline != HLP_NONE && !(t->flag & T_USES_MANIPULATOR)) {
+ if (t->helpline != HLP_NONE) {
float vecrot[3], cent[2];
- int mval[2];
-
- mval[0] = x;
- mval[1] = y;
+ float mval[3] = { x, y, 0.0f };
copy_v3_v3(vecrot, t->center);
if (t->flag & T_EDIT) {
@@ -1712,42 +1722,67 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO);
- glPushMatrix();
+ gpuPushMatrix();
+
+ /* Dashed lines first. */
+ if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) {
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */
+ BLI_assert(shdr_pos == POS_INDEX);
+
+ glLineWidth(1.0f);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(POS_INDEX, cent);
+ immVertex2f(POS_INDEX, (float)t->mval[0], (float)t->mval[1]);
+ immEnd();
+
+ immUnbindProgram();
+ }
+
+ /* And now, solid lines. */
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ UNUSED_VARS_NDEBUG(pos); /* silence warning */
+ BLI_assert(pos == POS_INDEX);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
switch (t->helpline) {
case HLP_SPRING:
- UI_ThemeColor(TH_VIEW_OVERLAY);
-
- setlinestyle(3);
- glLineWidth(1);
- glBegin(GL_LINES);
- glVertex2iv(t->mval);
- glVertex2fv(cent);
- glEnd();
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- glTranslate2iv(mval);
- glRotatef(-RAD2DEGF(atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1])), 0, 0, 1);
+ gpuTranslate3fv(mval);
+ gpuRotateAxis(-RAD2DEGF(atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1])), 'Z');
- setlinestyle(0);
- glLineWidth(3.0);
+ glLineWidth(3.0f);
drawArrow(UP, 5, 10, 5);
drawArrow(DOWN, 5, 10, 5);
break;
case HLP_HARROW:
- UI_ThemeColor(TH_VIEW_OVERLAY);
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ gpuTranslate3fv(mval);
- glTranslate2iv(mval);
-
- glLineWidth(3.0);
+ glLineWidth(3.0f);
drawArrow(RIGHT, 5, 10, 5);
drawArrow(LEFT, 5, 10, 5);
break;
case HLP_VARROW:
- UI_ThemeColor(TH_VIEW_OVERLAY);
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- glTranslate2iv(mval);
+ gpuTranslate3fv(mval);
- glLineWidth(3.0);
+ glLineWidth(3.0f);
drawArrow(UP, 5, 10, 5);
drawArrow(DOWN, 5, 10, 5);
break;
@@ -1758,33 +1793,26 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
float dist = hypotf(dx, dy);
float delta_angle = min_ff(15.0f / dist, (float)M_PI / 4.0f);
float spacing_angle = min_ff(5.0f / dist, (float)M_PI / 12.0f);
- UI_ThemeColor(TH_VIEW_OVERLAY);
- setlinestyle(3);
- glLineWidth(1);
- glBegin(GL_LINES);
- glVertex2iv(t->mval);
- glVertex2fv(cent);
- glEnd();
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- glTranslatef(cent[0] - t->mval[0] + mval[0], cent[1] - t->mval[1] + mval[1], 0);
+ gpuTranslate3f(cent[0] - t->mval[0] + mval[0], cent[1] - t->mval[1] + mval[1], 0);
- setlinestyle(0);
- glLineWidth(3.0);
+ glLineWidth(3.0f);
drawArc(dist, angle - delta_angle, angle - spacing_angle, 10);
drawArc(dist, angle + spacing_angle, angle + delta_angle, 10);
- glPushMatrix();
+ gpuPushMatrix();
- glTranslatef(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
- glRotatef(RAD2DEGF(angle - delta_angle), 0, 0, 1);
+ gpuTranslate3f(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
+ gpuRotateAxis(RAD2DEGF(angle - delta_angle), 'Z');
drawArrowHead(DOWN, 5);
- glPopMatrix();
+ gpuPopMatrix();
- glTranslatef(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0);
- glRotatef(RAD2DEGF(angle + delta_angle), 0, 0, 1);
+ gpuTranslate3f(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0);
+ gpuRotateAxis(RAD2DEGF(angle + delta_angle), 'Z');
drawArrowHead(UP, 5);
break;
@@ -1794,18 +1822,18 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
unsigned char col[3], col2[3];
UI_GetThemeColor3ubv(TH_GRID, col);
- glTranslate2iv(mval);
+ gpuTranslate3fv(mval);
- glLineWidth(3.0);
+ glLineWidth(3.0f);
UI_make_axis_color(col, col2, 'X');
- glColor3ubv((GLubyte *)col2);
+ immUniformColor3ubv((GLubyte *)col2);
drawArrow(RIGHT, 5, 10, 5);
drawArrow(LEFT, 5, 10, 5);
UI_make_axis_color(col, col2, 'Y');
- glColor3ubv((GLubyte *)col2);
+ immUniformColor3ubv((GLubyte *)col2);
drawArrow(UP, 5, 10, 5);
drawArrow(DOWN, 5, 10, 5);
@@ -1813,7 +1841,8 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
}
}
- glPopMatrix();
+ immUnbindProgram();
+ gpuPopMatrix();
}
}
@@ -1821,7 +1850,7 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi
{
TransInfo *t = arg;
- glLineWidth(1.0);
+ glLineWidth(1.0f);
drawConstraint(t);
drawPropCircle(C, t);
@@ -1841,8 +1870,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);
@@ -1850,7 +1880,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
@@ -1873,7 +1905,8 @@ static void drawTransformPixel(const struct bContext *UNUSED(C), ARegion *ar, vo
{
TransInfo *t = arg;
Scene *scene = t->scene;
- Object *ob = OBACT;
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
/* draw autokeyframing hint in the corner
* - only draw if enabled (advanced users may be distracted/annoyed),
@@ -1984,6 +2017,10 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
View3D *v3d = t->view;
v3d->twmode = t->current_orientation;
+
+ BLI_assert(((v3d->custom_orientation_index == -1) && (t->custom_orientation == NULL)) ||
+ (BKE_workspace_transform_orientation_get_index(
+ CTX_wm_workspace(C), t->custom_orientation) == v3d->custom_orientation_index));
}
}
}
@@ -2003,15 +2040,20 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) {
- /* constraint orientation can be global, event if user selects something else
- * so use the orientation in the constraint if set
- * */
- if (t->con.mode & CON_APPLY) {
- RNA_enum_set(op->ptr, "constraint_orientation", t->con.orientation);
- }
- else {
- RNA_enum_set(op->ptr, "constraint_orientation", t->current_orientation);
+ /* constraint orientation can be global, even if user selects something else
+ * so use the orientation in the constraint if set */
+ short orientation = (t->con.mode & CON_APPLY) ? t->con.orientation : t->current_orientation;
+
+ if (orientation == V3D_MANIP_CUSTOM) {
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ const int custom_orientation_index = BKE_workspace_transform_orientation_get_index(
+ workspace, t->custom_orientation);
+
+ /* Maybe we need a t->con.custom_orientation? Seems like it would always match t->custom_orientation. */
+ orientation = V3D_MANIP_CUSTOM + custom_orientation_index;
+ BLI_assert(orientation >= V3D_MANIP_CUSTOM);
}
+ RNA_enum_set(op->ptr, "constraint_orientation", orientation);
if (t->con.mode & CON_APPLY) {
if (t->con.mode & CON_AXIS0) {
@@ -2583,6 +2625,9 @@ static void constraintTransLim(TransInfo *t, TransData *td)
if (td->con) {
const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_LOCLIMIT);
const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_DISTLIMIT);
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(t->context, &eval_ctx);
bConstraintOb cob = {NULL};
bConstraint *con;
@@ -2632,7 +2677,7 @@ static void constraintTransLim(TransInfo *t, TransData *td)
}
/* get constraint targets if needed */
- BKE_constraint_targets_for_solving_get(con, &cob, &targets, ctime);
+ BKE_constraint_targets_for_solving_get(&eval_ctx, con, &cob, &targets, ctime);
/* do constraint */
cti->evaluate_constraint(con, &cob, &targets);
@@ -3402,7 +3447,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3])
constraintTransLim(t, td);
}
-static void applyResize(TransInfo *t, const int mval[2])
+static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
{
TransData *td;
float mat[3][3];
@@ -3413,15 +3458,7 @@ static void applyResize(TransInfo *t, const int mval[2])
copy_v3_v3(t->values, t->auto_values);
}
else {
- float ratio;
-
- /* for manipulator, center handle, the scaling can't be done relative to center */
- if ((t->flag & T_USES_MANIPULATOR) && t->con.mode == 0) {
- ratio = 1.0f - ((t->mouse.imval[0] - mval[0]) + (t->mouse.imval[1] - mval[1])) / 100.0f;
- }
- else {
- ratio = t->values[0];
- }
+ float ratio = t->values[0];
copy_v3_fl(t->values, ratio);
@@ -5248,23 +5285,14 @@ static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3])
td->loc[1] = oldy;
}
-static void applyBoneSize(TransInfo *t, const int mval[2])
+static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2]))
{
TransData *td = t->data;
float size[3], mat[3][3];
- float ratio;
+ float ratio = t->values[0];
int i;
char str[UI_MAX_DRAW_STR];
-
- // TRANSFORM_FIX_ME MOVE TO MOUSE INPUT
- /* for manipulator, center handle, the scaling can't be done relative to center */
- if ((t->flag & T_USES_MANIPULATOR) && t->con.mode == 0) {
- ratio = 1.0f - ((t->mouse.imval[0] - mval[0]) + (t->mouse.imval[1] - mval[1])) / 100.0f;
- }
- else {
- ratio = t->values[0];
- }
-
+
copy_v3_fl(size, ratio);
snapGridIncrement(t, size);
@@ -6856,10 +6884,12 @@ static void drawEdgeSlide(TransInfo *t)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT);
- glPushMatrix();
+ gpuPushMatrix();
+ gpuMultMatrix(t->obedit->obmat);
- glMultMatrixf(t->obedit->obmat);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
if (sld->use_even == true) {
float co_a[3], co_b[3], co_mark[3];
@@ -6873,39 +6903,35 @@ static void drawEdgeSlide(TransInfo *t)
add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]);
glLineWidth(line_size);
- UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- glBegin(GL_LINES);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ immBeginAtMost(GWN_PRIM_LINES, 4);
if (curr_sv->v_side[0]) {
- glVertex3fv(curr_sv->v_side[0]->co);
- glVertex3fv(curr_sv->v_co_orig);
+ immVertex3fv(pos, curr_sv->v_side[0]->co);
+ immVertex3fv(pos, curr_sv->v_co_orig);
}
if (curr_sv->v_side[1]) {
- glVertex3fv(curr_sv->v_side[1]->co);
- glVertex3fv(curr_sv->v_co_orig);
+ immVertex3fv(pos, curr_sv->v_side[1]->co);
+ immVertex3fv(pos, curr_sv->v_co_orig);
}
- glEnd();
+ immEnd();
- UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
+ immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
glPointSize(ctrl_size);
- glBegin(GL_POINTS);
+ immBegin(GWN_PRIM_POINTS, 1);
if (sld->flipped) {
- if (curr_sv->v_side[1]) glVertex3fv(curr_sv->v_side[1]->co);
+ if (curr_sv->v_side[1]) immVertex3fv(pos, curr_sv->v_side[1]->co);
}
else {
- if (curr_sv->v_side[0]) glVertex3fv(curr_sv->v_side[0]->co);
+ if (curr_sv->v_side[0]) immVertex3fv(pos, curr_sv->v_side[0]->co);
}
- glEnd();
+ immEnd();
- UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
+ immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
glPointSize(guide_size);
- glBegin(GL_POINTS);
-#if 0
- interp_v3_v3v3(co_mark, co_b, co_a, fac);
- glVertex3fv(co_mark);
-#endif
+ immBegin(GWN_PRIM_POINTS, 1);
interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
- glVertex3fv(co_mark);
- glEnd();
+ immVertex3fv(pos, co_mark);
+ immEnd();
}
else {
if (is_clamp == false) {
@@ -6915,8 +6941,8 @@ static void drawEdgeSlide(TransInfo *t)
const int alpha_shade = -160;
glLineWidth(line_size);
- UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- glBegin(GL_LINES);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ immBegin(GWN_PRIM_LINES, sld->totsv * 2);
sv = sld->sv;
for (i = 0; i < sld->totsv; i++, sv++) {
@@ -6934,18 +6960,19 @@ static void drawEdgeSlide(TransInfo *t)
add_v3_v3(a, sv->v_co_orig);
add_v3_v3(b, sv->v_co_orig);
- glVertex3fv(a);
- glVertex3fv(b);
+ immVertex3fv(pos, a);
+ immVertex3fv(pos, b);
}
- glEnd();
+ immEnd();
}
else {
BLI_assert(0);
}
}
- glPopMatrix();
- glPopAttrib();
+ immUnbindProgram();
+
+ gpuPopMatrix();
glDisable(GL_BLEND);
@@ -7469,19 +7496,22 @@ static void drawVertSlide(TransInfo *t)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT);
- glPushMatrix();
-
- glMultMatrixf(t->obedit->obmat);
+ gpuPushMatrix();
+ gpuMultMatrix(t->obedit->obmat);
glLineWidth(line_size);
- UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- glBegin(GL_LINES);
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+
+ immBegin(GWN_PRIM_LINES, sld->totsv * 2);
if (is_clamp) {
sv = sld->sv;
for (i = 0; i < sld->totsv; i++, sv++) {
- glVertex3fv(sv->co_orig_3d);
- glVertex3fv(sv->co_link_orig_3d[sv->co_link_curr]);
+ immVertex3fv(shdr_pos, sv->co_orig_3d);
+ immVertex3fv(shdr_pos, sv->co_link_orig_3d[sv->co_link_curr]);
}
}
else {
@@ -7494,21 +7524,21 @@ static void drawVertSlide(TransInfo *t)
add_v3_v3(a, sv->co_orig_3d);
add_v3_v3(b, sv->co_orig_3d);
- glVertex3fv(a);
- glVertex3fv(b);
+ immVertex3fv(shdr_pos, a);
+ immVertex3fv(shdr_pos, b);
}
}
- glEnd();
+ immEnd();
glPointSize(ctrl_size);
- glBegin(GL_POINTS);
- glVertex3fv((sld->flipped && sld->use_even) ?
+ immBegin(GWN_PRIM_POINTS, 1);
+ immVertex3fv(shdr_pos, (sld->flipped && sld->use_even) ?
curr_sv->co_link_orig_3d[curr_sv->co_link_curr] :
curr_sv->co_orig_3d);
- glEnd();
+ immEnd();
- glDisable(GL_BLEND);
+ immUnbindProgram();
/* direction from active vertex! */
if ((t->mval[0] != t->mouse.imval[0]) ||
@@ -7532,19 +7562,28 @@ static void drawVertSlide(TransInfo *t)
add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
- glLineWidth(1);
- setlinestyle(1);
+ glLineWidth(1.0f);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
- cpack(0xffffff);
- glBegin(GL_LINES);
- glVertex3fv(curr_sv->co_orig_3d);
- glVertex3fv(co_dest_3d);
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(shdr_pos, curr_sv->co_orig_3d);
+ immVertex3fv(shdr_pos, co_dest_3d);
+ immEnd();
- glEnd();
+ immUnbindProgram();
}
- glPopMatrix();
- glPopAttrib();
+ gpuPopMatrix();
if (v3d && v3d->zbuf)
glEnable(GL_DEPTH_TEST);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 06a60456cdb..d9bfcd0c289 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -37,6 +37,8 @@
#include "ED_numinput.h"
#include "ED_view3d.h"
+#include "RE_engine.h"
+
#include "DNA_listBase.h"
/* ************************** Types ***************************** */
@@ -50,6 +52,7 @@ struct Object;
struct View3D;
struct ScrArea;
struct Scene;
+struct ViewLayer;
struct bConstraint;
struct wmKeyMap;
struct wmKeyConfig;
@@ -59,6 +62,7 @@ struct wmTimer;
struct ARegion;
struct ReportList;
struct EditBone;
+struct RenderEngineType;
struct SnapObjectContext;
/* transinfo->redraw */
@@ -446,6 +450,7 @@ typedef struct TransInfo {
short launch_event; /* event type used to launch transform */
short current_orientation;
+ TransformOrientation *custom_orientation; /* this gets used when current_orientation is V3D_MANIP_CUSTOM */
short twtype; /* backup from view3d, to restore on end */
short prop_mode;
@@ -464,6 +469,8 @@ typedef struct TransInfo {
struct ScrArea *sa;
struct ARegion *ar;
struct Scene *scene;
+ struct ViewLayer *view_layer;
+ struct RenderEngineType *engine_type;
struct ToolSettings *settings;
struct wmTimer *animtimer;
struct wmKeyMap *keymap; /* so we can do lookups for header text */
@@ -496,8 +503,7 @@ typedef struct TransInfo {
#define T_CAMERA (1 << 4)
// trans on points, having no rotation/scale
#define T_POINTS (1 << 6)
- // for manipulator exceptions, like scaling using center point, drawing help lines
-#define T_USES_MANIPULATOR (1 << 7)
+/* empty slot - (1 << 7) */
/* restrictions flags */
#define T_ALL_RESTRICTIONS ((1 << 8)|(1 << 9)|(1 << 10))
@@ -637,7 +643,10 @@ void flushTransMasking(TransInfo *t);
void flushTransPaintCurve(TransInfo *t);
void restoreBones(TransInfo *t);
-/*********************** exported from transform_manipulator.c ********** */
+/*********************** transform_manipulator.c ********** */
+
+#define MANIPULATOR_AXIS_LINE_WIDTH 2.0f
+
bool gimbal_axis(struct Object *ob, float gmat[3][3]); /* return 0 when no gimbal for selection */
/*********************** TransData Creation and General Handling *********** */
@@ -652,7 +661,7 @@ bool transdata_check_local_islands(TransInfo *t, short around);
int count_set_pose_transflags(int *out_mode, short around, struct Object *ob);
/* auto-keying stuff used by special_aftertrans_update */
-void autokeyframe_ob_cb_func(struct bContext *C, struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode);
+void autokeyframe_ob_cb_func(struct bContext *C, struct Scene *scene, struct ViewLayer *view_layer, struct View3D *v3d, struct Object *ob, int tmode);
void autokeyframe_pose_cb_func(struct bContext *C, struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode, short targetless_ik);
/*********************** Constraints *****************************/
@@ -787,7 +796,7 @@ bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const floa
struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3],
const char *name, const bool overwrite);
-bool applyTransformOrientation(const struct bContext *C, float mat[3][3], char r_name[64], int index);
+bool applyTransformOrientation(const struct TransformOrientation *ts, float r_mat[3][3], char r_name[64]);
#define ORIENTATION_NONE 0
#define ORIENTATION_NORMAL 1
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 5621eede543..4e409e7f77f 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -40,9 +40,11 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
@@ -651,7 +653,7 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[])
*/
void setUserConstraint(TransInfo *t, short orientation, int mode, const char ftext[])
{
- char text[40];
+ char text[256];
switch (orientation) {
case V3D_MANIP_GLOBAL:
@@ -683,10 +685,15 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte
BLI_snprintf(text, sizeof(text), ftext, IFACE_("gimbal"));
setConstraint(t, t->spacemtx, mode, text);
break;
- default: /* V3D_MANIP_CUSTOM */
- BLI_snprintf(text, sizeof(text), ftext, t->spacename);
+ case V3D_MANIP_CUSTOM:
+ {
+ char orientation_str[128];
+ BLI_snprintf(orientation_str, sizeof(orientation_str), "%s \"%s\"",
+ IFACE_("custom orientation"), t->custom_orientation->name);
+ BLI_snprintf(text, sizeof(text), ftext, orientation_str);
setConstraint(t, t->spacemtx, mode, text);
break;
+ }
}
t->con.orientation = orientation;
@@ -704,8 +711,6 @@ void drawConstraint(TransInfo *t)
return;
if (!(tc->mode & CON_APPLY))
return;
- if (t->flag & T_USES_MANIPULATOR)
- return;
if (t->flag & T_NO_CONSTRAINT)
return;
@@ -715,7 +720,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,18 +729,29 @@ 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);
- setlinestyle(1);
- glBegin(GL_LINES);
- glVertex3fv(t->center_global);
- glVertex3fv(vec);
- glEnd();
- setlinestyle(0);
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ immUniform1f("dash_width", 2.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(shdr_pos, t->center_global);
+ immVertex3fv(shdr_pos, vec);
+ immEnd();
+
+ immUnbindProgram();
if (depth_test_enabled)
glEnable(GL_DEPTH_TEST);
@@ -762,8 +777,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);
@@ -773,13 +786,13 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
unit_m4(imat);
}
- glPushMatrix();
+ gpuPushMatrix();
if (t->spacetype == SPACE_VIEW3D) {
/* pass */
}
else if (t->spacetype == SPACE_IMAGE) {
- glScalef(1.0f / t->aspect[0], 1.0f / t->aspect[1], 1.0f);
+ gpuScale2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]);
}
else if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) {
/* only scale y */
@@ -789,21 +802,28 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
float ysize = BLI_rctf_size_y(datamask);
float xmask = BLI_rcti_size_x(mask);
float ymask = BLI_rcti_size_y(mask);
- glScalef(1.0f, (ysize / xsize) * (xmask / ymask), 1.0f);
+ gpuScale2f(1.0f, (ysize / xsize) * (xmask / ymask));
}
depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
if (depth_test_enabled)
glDisable(GL_DEPTH_TEST);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_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);
- glPopMatrix();
+ gpuPopMatrix();
}
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 34cc143f3a9..730ca70547b 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -68,10 +68,10 @@
#include "BKE_context.h"
#include "BKE_crazyspace.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#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"
@@ -118,6 +118,8 @@
#include "RNA_access.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "transform.h"
#include "bmesh.h"
@@ -285,13 +287,13 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
static void createTransTexspace(TransInfo *t)
{
- Scene *scene = t->scene;
+ ViewLayer *view_layer = t->view_layer;
TransData *td;
Object *ob;
ID *id;
short *texflag;
- ob = OBACT;
+ ob = OBACT(view_layer);
if (ob == NULL) { // Shouldn't logically happen, but still...
t->total = 0;
@@ -836,14 +838,9 @@ void transform_autoik_update(TransInfo *t, short mode)
changed |= pchan_autoik_adjust(pchan, *chainlen);
}
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!DEG_depsgraph_use_legacy())
-#endif
- {
- if (changed) {
- /* TODO(sergey): Consider doing partial update only. */
- DAG_relations_tag_update(G.main);
- }
+ if (changed) {
+ /* TODO(sergey): Consider doing partial update only. */
+ DEG_relations_tag_update(G.main);
}
}
@@ -853,9 +850,7 @@ static void pose_grab_with_ik_clear(Object *ob)
bKinematicConstraint *data;
bPoseChannel *pchan;
bConstraint *con, *next;
-#ifdef WITH_LEGACY_DEPSGRAPH
- bool need_dependency_update = false;
-#endif
+ bool relations_changed = false;
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
/* clear all temporary lock flags */
@@ -869,10 +864,9 @@ static void pose_grab_with_ik_clear(Object *ob)
if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
data = con->data;
if (data->flag & CONSTRAINT_IK_TEMP) {
+ relations_changed = true;
+
/* iTaSC needs clear for removed constraints */
-#ifdef WITH_LEGACY_DEPSGRAPH
- need_dependency_update = true;
-#endif
BIK_clear_data(ob->pose);
BLI_remlink(&pchan->constraints, con);
@@ -887,12 +881,9 @@ static void pose_grab_with_ik_clear(Object *ob)
}
}
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!DEG_depsgraph_use_legacy() && need_dependency_update)
-#endif
- {
+ if (relations_changed) {
/* TODO(sergey): Consider doing partial update only. */
- DAG_relations_tag_update(G.main);
+ DEG_relations_tag_update(G.main);
}
}
@@ -1046,13 +1037,8 @@ static short pose_grab_with_ik(Object *ob)
/* iTaSC needs clear for new IK constraints */
if (tot_ik) {
BIK_clear_data(ob->pose);
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!DEG_depsgraph_use_legacy())
-#endif
- {
- /* TODO(sergey): Consuder doing partial update only. */
- DAG_relations_tag_update(G.main);
- }
+ /* TODO(sergey): Consuder doing partial update only. */
+ DEG_relations_tag_update(G.main);
}
return (tot_ik) ? 1 : 0;
@@ -1907,7 +1893,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
TransDataExtension *tx;
Object *ob = CTX_data_active_object(C);
ParticleEditSettings *pset = PE_settings(t->scene);
- PTCacheEdit *edit = PE_get_current(t->scene, ob);
+ PTCacheEdit *edit = PE_get_current(t->scene, t->view_layer, ob);
ParticleSystem *psys = NULL;
ParticleSystemModifierData *psmd = NULL;
PTCacheEditPoint *point;
@@ -2022,8 +2008,9 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
void flushTransParticles(TransInfo *t)
{
Scene *scene = t->scene;
- Object *ob = OBACT;
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+ PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd = NULL;
PTCacheEditPoint *point;
@@ -2062,7 +2049,9 @@ void flushTransParticles(TransInfo *t)
point->flag |= PEP_EDIT_RECALC;
}
- PE_update_object(scene, OBACT, 1);
+ EvaluationContext eval_ctx;
+ CTX_data_eval_ctx(t->context, &eval_ctx);
+ PE_update_object(&eval_ctx, scene, view_layer, OBACT(view_layer), 1);
}
/* ********************* mesh ****************** */
@@ -2474,6 +2463,7 @@ static void createTransEditVerts(TransInfo *t)
{
TransData *tob = NULL;
TransDataExtension *tx = NULL;
+ EvaluationContext eval_ctx;
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
Mesh *me = t->obedit->data;
BMesh *bm = em->bm;
@@ -2492,6 +2482,10 @@ static void createTransEditVerts(TransInfo *t)
int island_info_tot;
int *island_vert_map = NULL;
+ DEG_evaluation_context_init_from_scene(&eval_ctx,
+ t->scene, t->view_layer, t->engine_type,
+ DAG_EVAL_VIEWPORT);
+
/* Even for translation this is needed because of island-orientation, see: T51651. */
const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
/* Original index of our connected vertex when connected distances are calculated.
@@ -2575,7 +2569,7 @@ static void createTransEditVerts(TransInfo *t)
if (modifiers_isCorrectableDeformed(t->scene, t->obedit)) {
/* check if we can use deform matrices for modifier from the
* start up to stack, they are more accurate than quats */
- totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(t->scene, t->obedit, em, &defmats, &defcos);
+ totleft = BKE_crazyspace_get_first_deform_matrices_editbmesh(&eval_ctx, t->scene, t->obedit, em, &defmats, &defcos);
}
/* if we still have more modifiers, also do crazyspace
@@ -2588,7 +2582,7 @@ static void createTransEditVerts(TransInfo *t)
if (totleft > 0)
#endif
{
- mappedcos = BKE_crazyspace_get_mapped_editverts(t->scene, t->obedit);
+ mappedcos = BKE_crazyspace_get_mapped_editverts(&eval_ctx, t->scene, t->obedit);
quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats");
BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode);
if (mappedcos)
@@ -2957,7 +2951,6 @@ static void createTransUVs(bContext *C, TransInfo *t)
const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0;
const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
if (!ED_space_image_show_uvedit(sima, t->obedit))
return;
@@ -2981,10 +2974,9 @@ static void createTransUVs(bContext *C, TransInfo *t)
}
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
BMLoop *l;
- if (!uvedit_face_visible_test(scene, ima, efa, tf)) {
+ if (!uvedit_face_visible_test(scene, ima, efa)) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
continue;
}
@@ -5416,6 +5408,9 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
Scene *scene = t->scene;
bool constinv;
bool skip_invert = false;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(t->context, &eval_ctx);
if (t->mode != TFM_DUMMY && ob->rigidbody_object) {
float rot[3][3], scale[3];
@@ -5463,11 +5458,11 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
if (skip_invert == false && constinv == false) {
ob->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc_time checks this */
- BKE_object_where_is_calc(t->scene, ob);
+ BKE_object_where_is_calc(&eval_ctx, t->scene, ob);
ob->transflag &= ~OB_NO_CONSTRAINTS;
}
else
- BKE_object_where_is_calc(t->scene, ob);
+ BKE_object_where_is_calc(&eval_ctx, t->scene, ob);
td->ob = ob;
@@ -5534,84 +5529,97 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
}
}
+static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer)
+{
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ base->object->id.tag &= ~LIB_TAG_DOIT;
+ }
+}
+
+static void set_trans_object_base_deps_flag_cb(ID *id, void *UNUSED(user_data))
+{
+ /* Here we only handle object IDs. */
+ if (GS(id->name) != ID_OB) {
+ return;
+ }
+ id->tag |= LIB_TAG_DOIT;
+}
+
+static void flush_trans_object_base_deps_flag(Depsgraph *depsgraph, Object *object)
+{
+ object->id.tag |= LIB_TAG_DOIT;
+ DEG_foreach_dependent_ID(depsgraph, &object->id,
+ set_trans_object_base_deps_flag_cb, NULL);
+}
+
+static void trans_object_base_deps_flag_finish(ViewLayer *view_layer)
+{
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object->id.tag & LIB_TAG_DOIT) {
+ base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
+ }
+ }
+}
/* sets flags in Bases to define whether they take part in transform */
/* it deselects Bases, so we have to call the clear function always after */
static void set_trans_object_base_flags(TransInfo *t)
{
+ /* TODO(sergey): Get rid of global, use explicit main. */
+ Main *bmain = G.main;
+ ViewLayer *view_layer = t->view_layer;
Scene *scene = t->scene;
- View3D *v3d = t->view;
-
- /*
- * if Base selected and has parent selected:
- * base->flag = BA_WAS_SEL
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ /* NOTE: if Base selected and has parent selected:
+ * base->flag_legacy = BA_WAS_SEL
*/
- Base *base;
-
- /* don't do it if we're not actually going to recalculate anything */
- if (t->mode == TFM_DUMMY)
+ /* Don't do it if we're not actually going to recalculate anything. */
+ if (t->mode == TFM_DUMMY) {
return;
-
- /* makes sure base flags and object flags are identical */
- BKE_scene_base_flag_to_objects(t->scene);
-
- /* 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) {
- 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;
-
- if (TESTBASELIB_BGMODE(v3d, scene, base)) {
+ /* Makes sure base flags and object flags are identical. */
+ BKE_scene_base_flag_to_objects(t->view_layer);
+ /* Make sure depsgraph is here. */
+ DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
+ /* Clear all flags we need. It will be used to detect dependencies. */
+ trans_object_base_deps_flag_prepare(view_layer);
+ /* Traverse all bases and set all possible flags. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ base->flag_legacy &= ~BA_WAS_SEL;
+ if (TESTBASELIB_BGMODE(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);
- if (parbase) { /* in rare cases this can fail */
- if (TESTBASELIB_BGMODE(v3d, scene, parbase)) {
+ /* If parent selected, deselect. */
+ while (parsel != NULL) {
+ if (parsel->base_flag & BASE_SELECTED) {
+ Base *parbase = BKE_view_layer_base_find(view_layer, parsel);
+ if (parbase != NULL) { /* in rare cases this can fail */
+ if (TESTBASELIB_BGMODE(parbase)) {
break;
}
}
}
parsel = parsel->parent;
}
-
- if (parsel) {
- /* rotation around local centers are allowed to propagate */
+ if (parsel != NULL) {
+ /* Rotation around local centers are allowed to propagate. */
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);
- }
- }
-
- /* all recalc flags get flushed to all layers, so a layer flip later on works fine */
- DAG_scene_flush_update(G.main, t->scene, -1, 0);
-
- /* 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) {
- if (base->object->recalc & (OB_RECALC_OB | OB_RECALC_DATA)) {
- base->flag |= BA_SNAP_FIX_DEPS_FIASCO;
+ flush_trans_object_base_deps_flag(depsgraph, ob);
}
}
+ /* Store temporary bits in base indicating that base is being modified
+ * (directly or indirectly) by transforming objects.
+ */
+ trans_object_base_deps_flag_finish(view_layer);
}
static bool mark_children(Object *ob)
@@ -5632,78 +5640,69 @@ static bool mark_children(Object *ob)
static int count_proportional_objects(TransInfo *t)
{
int total = 0;
+ ViewLayer *view_layer = t->view_layer;
Scene *scene = t->scene;
- View3D *v3d = t->view;
- Base *base;
-
- /* rotations around local centers are allowed to propagate, so we take all objects */
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ /* Clear all flags we need. It will be used to detect dependencies. */
+ trans_object_base_deps_flag_prepare(view_layer);
+ /* Rotations around local centers are allowed to propagate, so we take all objects. */
if (!((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
(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)) {
+ /* Mark all parents. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (TESTBASELIB_BGMODE(base)) {
Object *parent = base->object->parent;
-
/* flag all parents */
- while (parent) {
+ while (parent != NULL) {
parent->flag |= BA_TRANSFORM_PARENT;
parent = parent->parent;
}
}
}
-
- /* mark all children */
- for (base = scene->base.first; base; base = base->next) {
+ /* Mark all children. */
+ for (Base *base = view_layer->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(base)))
{
mark_children(base->object);
}
}
}
-
- for (base = scene->base.first; base; base = base->next) {
+ /* Flush changed flags to all dependencies. */
+ for (Base *base = view_layer->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 base is not selected, not a parent of selection or not a child of
+ * selection and it is editable.
+ */
+ if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
+ (base->flag & BASE_SELECTED) == 0 &&
+ (BASE_EDITABLE_BGMODE(base)))
{
-
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
-
+ flush_trans_object_base_deps_flag(depsgraph, ob);
total += 1;
}
}
-
-
- /* all recalc flags get flushed to all layers, so a layer flip later on works fine */
- DAG_scene_relations_update(G.main, t->scene);
- DAG_scene_flush_update(G.main, t->scene, -1, 0);
-
- /* 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) {
- if (base->object->recalc & (OB_RECALC_OB | OB_RECALC_DATA)) {
- base->flag |= BA_SNAP_FIX_DEPS_FIASCO;
- }
- }
-
+ /* Store temporary bits in base indicating that base is being modified
+ * (directly or indirectly) by transforming objects.
+ */
+ trans_object_base_deps_flag_finish(view_layer);
return total;
}
static void clear_trans_object_base_flags(TransInfo *t)
{
- Scene *sce = t->scene;
+ ViewLayer *view_layer = t->view_layer;
Base *base;
- for (base = sce->base.first; base; base = base->next) {
- if (base->flag & BA_WAS_SEL)
- base->flag |= SELECT;
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->flag_legacy & BA_WAS_SEL) {
+ base->flag |= BASE_SELECTED;
+ }
- base->flag &= ~(BA_WAS_SEL | BA_SNAP_FIX_DEPS_FIASCO | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT);
+ base->flag_legacy &= ~(BA_WAS_SEL | BA_SNAP_FIX_DEPS_FIASCO | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT);
}
}
@@ -5711,7 +5710,7 @@ static void clear_trans_object_base_flags(TransInfo *t)
* tmode: should be a transform mode
*/
// NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases
-void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, int tmode)
+void autokeyframe_ob_cb_func(bContext *C, Scene *scene, ViewLayer *view_layer, View3D *v3d, Object *ob, int tmode)
{
ID *id = &ob->id;
FCurve *fcu;
@@ -5760,7 +5759,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
}
else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
if (v3d->around == V3D_AROUND_ACTIVE) {
- if (ob != OBACT)
+ if (ob != OBACT(view_layer))
do_loc = true;
}
else if (v3d->around == V3D_AROUND_CURSOR)
@@ -5771,7 +5770,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
}
else if (tmode == TFM_RESIZE) {
if (v3d->around == V3D_AROUND_ACTIVE) {
- if (ob != OBACT)
+ if (ob != OBACT(view_layer))
do_loc = true;
}
else if (v3d->around == V3D_AROUND_CURSOR)
@@ -5949,7 +5948,7 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o
*/
if (C && (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) {
//ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear
- ED_pose_recalculate_paths(scene, ob);
+ ED_pose_recalculate_paths(C, scene, ob);
}
}
else {
@@ -6104,10 +6103,13 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
* */
void special_aftertrans_update(bContext *C, TransInfo *t)
{
+ EvaluationContext eval_ctx;
Object *ob;
// short redrawipo=0, resetslowpar=1;
const bool canceled = (t->state == TRANS_CANCEL);
const bool duplicate = (t->mode == TFM_TIME_DUPLICATE);
+
+ CTX_data_eval_ctx(C, &eval_ctx);
/* early out when nothing happened */
if (t->total == 0 || t->mode == TFM_DUMMY)
@@ -6259,9 +6261,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
// fixme... some of this stuff is not good
if (ob) {
if (ob->pose || BKE_key_from_object(ob))
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
else
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
/* 3 cases here for curve cleanups:
@@ -6447,7 +6449,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
* we need to update the pose otherwise no updates get called during
* transform and the auto-ik is not applied. see [#26164] */
struct Object *pose_ob = t->poseobj;
- BKE_pose_where_is(t->scene, pose_ob);
+ BKE_pose_where_is(&eval_ctx, t->scene, pose_ob);
}
/* set BONE_TRANSFORM flags for autokey, manipulator draw might have changed them */
@@ -6471,24 +6473,28 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
/* automatic inserting of keys and unkeyed tagging - only if transform wasn't canceled (or TFM_DUMMY) */
if (!canceled && (t->mode != TFM_DUMMY)) {
autokeyframe_pose_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode, targetless_ik);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else if (arm->flag & ARM_DELAYDEFORM) {
- /* old optimize trick... this enforces to bypass the depgraph */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- ob->recalc = 0; // is set on OK position already by recalcData()
+ /* TODO(sergey): Armature is already updated by recalcData(), so we
+ * might save some time by skipping re-evaluating it. But this isn't
+ * possible yet within new dependency graph, and also other contexts
+ * might need to update their CoW copies.
+ */
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+ else {
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
- else
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else if (t->options & CTX_PAINT_CURVE) {
/* pass */
}
- else if ((t->scene->basact) &&
- (ob = t->scene->basact->object) &&
+ else if ((t->view_layer->basact) &&
+ (ob = t->view_layer->basact->object) &&
(ob->mode & OB_MODE_PARTICLE_EDIT) &&
- PE_get_current(t->scene, ob))
+ PE_get_current(t->scene, t->view_layer, ob))
{
/* do nothing */
}
@@ -6519,17 +6525,17 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
/* pointcache refresh */
if (BKE_ptcache_object_reset(t->scene, ob, PTCACHE_RESET_OUTDATED))
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
/* Needed for proper updating of "quick cached" dynamics. */
/* Creates troubles for moving animated objects without */
/* autokey though, probably needed is an anim sys override? */
/* Please remove if some other solution is found. -jahka */
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
/* Set autokey if necessary */
if (!canceled) {
- autokeyframe_ob_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode);
+ autokeyframe_ob_cb_func(C, t->scene, t->view_layer, (View3D *)t->view, ob, t->mode);
}
/* restore rigid body transform */
@@ -6564,8 +6570,6 @@ int special_transform_moving(TransInfo *t)
static void createTransObject(bContext *C, TransInfo *t)
{
- Scene *scene = t->scene;
-
TransData *td = NULL;
TransDataExtension *tx;
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
@@ -6615,15 +6619,16 @@ static void createTransObject(bContext *C, TransInfo *t)
CTX_DATA_END;
if (is_prop_edit) {
- View3D *v3d = t->view;
+ ViewLayer *view_layer = t->view_layer;
Base *base;
- for (base = scene->base.first; base; base = base->next) {
+ for (base = view_layer->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(base))
{
td->protectflag = ob->protectflag;
td->ext = tx;
@@ -8070,7 +8075,8 @@ static void createTransGPencil(bContext *C, TransInfo *t)
void createTransData(bContext *C, TransInfo *t)
{
Scene *scene = t->scene;
- Object *ob = OBACT;
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
/* if tests must match recalcData for correct updates */
if (t->options & CTX_TEXTURE) {
@@ -8235,17 +8241,16 @@ 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_view_layer_base_find(t->view_layer, ob_armature);
if (base_arm) {
- View3D *v3d = t->view;
- if (BASE_VISIBLE(v3d, base_arm)) {
+ if (BASE_VISIBLE(base_arm)) {
createTransPose(t, ob_armature);
}
}
}
}
- else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) {
+ else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, view_layer, ob))) {
createTransParticleVerts(C, t);
t->flag |= T_POINTS;
@@ -8277,7 +8282,7 @@ void createTransData(bContext *C, TransInfo *t)
RegionView3D *rv3d = t->ar->regiondata;
if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) {
/* we could have a flag to easily check an object is being transformed */
- if (v3d->camera->recalc) {
+ if (v3d->camera->id.tag & LIB_TAG_DOIT) {
t->flag |= T_CAMERA;
}
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 277e01d1e2b..10a7677f42b 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -62,8 +62,8 @@
#include "RNA_access.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "BIK_api.h"
@@ -71,7 +71,6 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
@@ -82,6 +81,9 @@
#include "BKE_editmesh.h"
#include "BKE_tracking.h"
#include "BKE_mask.h"
+#include "BKE_workspace.h"
+
+#include "DEG_depsgraph.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -102,6 +104,8 @@
#include "WM_types.h"
#include "WM_api.h"
+#include "RE_engine.h"
+
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -314,7 +318,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;
+ ViewLayer *view_layer = t->view_layer;
SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
bAnimContext ac = {NULL};
@@ -325,7 +329,8 @@ 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.view_layer = t->view_layer;
+ ac.obact = OBACT(view_layer);
ac.sa = t->sa;
ac.ar = t->ar;
ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
@@ -362,7 +367,7 @@ static void recalcData_actedit(TransInfo *t)
static void recalcData_graphedit(TransInfo *t)
{
SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
- Scene *scene;
+ ViewLayer *view_layer = t->view_layer;
ListBase anim_data = {NULL, NULL};
bAnimContext ac = {NULL};
@@ -373,8 +378,9 @@ 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.view_layer = t->view_layer;
+ ac.obact = OBACT(view_layer);
ac.sa = t->sa;
ac.ar = t->ar;
ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
@@ -636,7 +642,7 @@ static void recalcData_mask_common(TransInfo *t)
flushTransMasking(t);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
}
/* helper for recalcData() - for Image Editor transforms */
@@ -655,7 +661,7 @@ static void recalcData_image(TransInfo *t)
if (sima->flag & SI_LIVE_UNWRAP)
ED_uvedit_live_unwrap_re_solve();
- DAG_id_tag_update(t->obedit->data, 0);
+ DEG_id_tag_update(t->obedit->data, 0);
}
}
@@ -698,7 +704,7 @@ static void recalcData_spaceclip(TransInfo *t)
track = track->next;
}
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
}
else if (t->options & CTX_MASK) {
recalcData_mask_common(t);
@@ -708,7 +714,10 @@ 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;
+ Base *base = t->view_layer->basact;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(t->context, &eval_ctx);
if (t->obedit) {
if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) {
@@ -721,7 +730,7 @@ static void recalcData_objects(TransInfo *t)
applyProject(t);
}
- DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
+ DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
if (t->state == TRANS_CANCEL) {
while (nu) {
@@ -745,7 +754,7 @@ static void recalcData_objects(TransInfo *t)
applyProject(t);
}
- DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
+ DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
if (la->editlatt->latt->flag & LT_OUTSIDE) outside_lattice(la->editlatt->latt);
}
@@ -767,7 +776,7 @@ static void recalcData_objects(TransInfo *t)
projectVertSlideData(t, false);
}
- DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
+ DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
EDBM_mesh_normals_update(em);
BKE_editmesh_tessface_calc(em);
@@ -865,7 +874,7 @@ static void recalcData_objects(TransInfo *t)
if (t->state != TRANS_CANCEL) {
applyProject(t);
}
- DAG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
+ DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
}
}
else if ((t->flag & T_POSE) && t->poseobj) {
@@ -888,14 +897,14 @@ static void recalcData_objects(TransInfo *t)
/* old optimize trick... this enforces to bypass the depgraph */
if (!(arm->flag & ARM_DELAYDEFORM)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
/* transformation of pose may affect IK tree, make sure it is rebuilt */
BIK_clear_data(ob->pose);
}
else
- BKE_pose_where_is(t->scene, ob);
+ BKE_pose_where_is(&eval_ctx, t->scene, ob);
}
- else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, base->object)) {
+ else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, t->view_layer, base->object)) {
if (t->state != TRANS_CANCEL) {
applyProject(t);
}
@@ -925,16 +934,16 @@ static void recalcData_objects(TransInfo *t)
// TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
animrecord_check_state(t->scene, &ob->id, t->animtimer);
- autokeyframe_ob_cb_func(t->context, t->scene, (View3D *)t->view, ob, t->mode);
+ autokeyframe_ob_cb_func(t->context, t->scene, t->view_layer, (View3D *)t->view, ob, t->mode);
}
/* sets recalc flags fully, instead of flushing existing ones
* otherwise proxies don't function correctly
*/
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
if (t->flag & T_TEXTURE)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
}
@@ -1031,11 +1040,10 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis
if (t->spacetype == SPACE_VIEW3D) {
View3D *v3d = t->view;
- glPushMatrix();
-
- //if (t->obedit) glLoadMatrixf(t->obedit->obmat); // sets opengl viewing
-
-
+ gpuPushMatrix();
+
+ // if (t->obedit) gpuLoadMatrix(t->obedit->obmat); // sets opengl viewing
+
copy_v3_v3(v3, dir);
mul_v3_fl(v3, v3d->far);
@@ -1049,15 +1057,20 @@ 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();
-
- glPopMatrix();
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(col2);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immEnd();
+
+ immUnbindProgram();
+
+ gpuPopMatrix();
}
}
@@ -1103,15 +1116,19 @@ 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);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
ToolSettings *ts = CTX_data_tool_settings(C);
ARegion *ar = CTX_wm_region(C);
ScrArea *sa = CTX_wm_area(C);
Object *obedit = CTX_data_edit_object(C);
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = CTX_data_gpencil_data(C);
+ RenderEngineType *engine_type = CTX_data_engine_type(C);
PropertyRNA *prop;
t->scene = sce;
+ t->view_layer = view_layer;
+ t->engine_type = engine_type;
t->sa = sa;
t->ar = ar;
t->obedit = obedit;
@@ -1219,7 +1236,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->animtimer = (animscreen) ? animscreen->animtimer : NULL;
/* turn manipulator off during transform */
- // FIXME: but don't do this when USING the manipulator...
if (t->flag & T_MODAL) {
t->twtype = v3d->twtype;
v3d->twtype = 0;
@@ -1234,6 +1250,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
t->current_orientation = v3d->twmode;
+ t->custom_orientation = BKE_workspace_transform_orientation_find(
+ CTX_wm_workspace(C), v3d->custom_orientation_index);
/* exceptional case */
if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
@@ -1324,11 +1342,22 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) &&
RNA_property_is_set(op->ptr, prop)))
{
- t->current_orientation = RNA_property_enum_get(op->ptr, prop);
+ short orientation = RNA_property_enum_get(op->ptr, prop);
+ TransformOrientation *custom_orientation = NULL;
- if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) {
- t->current_orientation = V3D_MANIP_GLOBAL;
+ if (orientation >= V3D_MANIP_CUSTOM) {
+ if (orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) {
+ orientation = V3D_MANIP_GLOBAL;
+ }
+ else {
+ custom_orientation = BKE_workspace_transform_orientation_find(
+ CTX_wm_workspace(C), orientation - V3D_MANIP_CUSTOM);
+ orientation = V3D_MANIP_CUSTOM;
+ }
}
+
+ t->current_orientation = orientation;
+ t->custom_orientation = custom_orientation;
}
if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
@@ -1773,8 +1802,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;
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
if (ob) {
bPoseChannel *pchan = BKE_pose_channel_active(ob);
if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) {
@@ -1784,7 +1813,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
}
}
else if (t->options & CTX_PAINT_CURVE) {
- Paint *p = BKE_paint_get_active(t->scene);
+ Paint *p = BKE_paint_get_active(t->scene, t->view_layer);
Brush *br = p->brush;
PaintCurve *pc = br->paint_curve;
copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
@@ -1793,9 +1822,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))) {
+ ViewLayer *view_layer = t->view_layer;
+ Object *ob = OBACT(view_layer);
+ Base *base = BASACT(view_layer);
+ 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_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 9a362ee609f..0e0c2f3ae25 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -59,24 +59,35 @@
#include "BKE_editmesh.h"
#include "BKE_lattice.h"
#include "BKE_gpencil.h"
+#include "BKE_workspace.h"
#include "BIF_gl.h"
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "ED_armature.h"
#include "ED_curve.h"
+#include "ED_object.h"
#include "ED_particle.h"
#include "ED_view3d.h"
#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
#include "UI_resources.h"
/* local module include */
#include "transform.h"
+#include "MEM_guardedalloc.h"
+
#include "GPU_select.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
+#define USE_AXIS_BOUNDS
/* return codes for select, and drawing flags */
@@ -88,35 +99,348 @@
#define MAN_ROT_X (1 << 3)
#define MAN_ROT_Y (1 << 4)
#define MAN_ROT_Z (1 << 5)
-#define MAN_ROT_V (1 << 6)
-#define MAN_ROT_T (1 << 7)
-#define MAN_ROT_C (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z | MAN_ROT_V | MAN_ROT_T)
+#define MAN_ROT_C (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z)
#define MAN_SCALE_X (1 << 8)
#define MAN_SCALE_Y (1 << 9)
#define MAN_SCALE_Z (1 << 10)
#define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z)
-/* color codes */
-
-#define MAN_RGB 0
-#define MAN_GHOST 1
-#define MAN_MOVECOL 2
-
/* threshold for testing view aligned manipulator axis */
#define TW_AXIS_DOT_MIN 0.02f
#define TW_AXIS_DOT_MAX 0.1f
+/* axes as index */
+enum {
+ MAN_AXIS_TRANS_X = 0,
+ MAN_AXIS_TRANS_Y,
+ MAN_AXIS_TRANS_Z,
+ MAN_AXIS_TRANS_C,
+
+ MAN_AXIS_TRANS_XY,
+ MAN_AXIS_TRANS_YZ,
+ MAN_AXIS_TRANS_ZX,
+#define MAN_AXIS_RANGE_TRANS_START MAN_AXIS_TRANS_X
+#define MAN_AXIS_RANGE_TRANS_END (MAN_AXIS_TRANS_ZX + 1)
+
+ MAN_AXIS_ROT_X,
+ MAN_AXIS_ROT_Y,
+ MAN_AXIS_ROT_Z,
+ MAN_AXIS_ROT_C,
+ MAN_AXIS_ROT_T, /* trackball rotation */
+#define MAN_AXIS_RANGE_ROT_START MAN_AXIS_ROT_X
+#define MAN_AXIS_RANGE_ROT_END (MAN_AXIS_ROT_T + 1)
+
+ MAN_AXIS_SCALE_X,
+ MAN_AXIS_SCALE_Y,
+ MAN_AXIS_SCALE_Z,
+ MAN_AXIS_SCALE_C,
+ MAN_AXIS_SCALE_XY,
+ MAN_AXIS_SCALE_YZ,
+ MAN_AXIS_SCALE_ZX,
+#define MAN_AXIS_RANGE_SCALE_START MAN_AXIS_SCALE_X
+#define MAN_AXIS_RANGE_SCALE_END (MAN_AXIS_SCALE_ZX + 1)
+
+ MAN_AXIS_LAST = MAN_AXIS_RANGE_SCALE_END,
+};
+
+/* axis types */
+enum {
+ MAN_AXES_ALL = 0,
+ MAN_AXES_TRANSLATE,
+ MAN_AXES_ROTATE,
+ MAN_AXES_SCALE,
+};
+
+typedef struct ManipulatorGroup {
+ bool all_hidden;
+
+ struct wmManipulator *manipulators[MAN_AXIS_LAST];
+} ManipulatorGroup;
+
struct TransformBounds {
float center[3]; /* Center for transform widget. */
float min[3], max[3]; /* Boundbox of selection for transform widget. */
+
+#ifdef USE_AXIS_BOUNDS
+ /* Normalized axis */
+ float axis[3][3];
+ float axis_min[3], axis_max[3];
+#endif
};
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+/* loop over axes */
+#define MAN_ITER_AXES_BEGIN(axis, axis_idx) \
+ { \
+ wmManipulator *axis; \
+ int axis_idx; \
+ for (axis_idx = 0; axis_idx < MAN_AXIS_LAST; axis_idx++) { \
+ axis = manipulator_get_axis_from_index(man, axis_idx);
+
+#define MAN_ITER_AXES_END \
+ } \
+ } ((void)0)
+
+static wmManipulator *manipulator_get_axis_from_index(const ManipulatorGroup *man, const short axis_idx)
+{
+ BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN_AXIS_TRANS_X, (float)MAN_AXIS_LAST));
+ return man->manipulators[axis_idx];
+}
+
+static short manipulator_get_axis_type(const int axis_idx)
+{
+ if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
+ return MAN_AXES_TRANSLATE;
+ }
+ if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) {
+ return MAN_AXES_ROTATE;
+ }
+ if (axis_idx >= MAN_AXIS_RANGE_SCALE_START && axis_idx < MAN_AXIS_RANGE_SCALE_END) {
+ return MAN_AXES_SCALE;
+ }
+ BLI_assert(0);
+ return -1;
+}
+
+static uint manipulator_orientation_axis(const int axis_idx, bool *r_is_plane)
+{
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_SCALE_YZ:
+ if (r_is_plane) {
+ *r_is_plane = true;
+ }
+ ATTR_FALLTHROUGH;
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_SCALE_X:
+ return 0;
+
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_ZX:
+ if (r_is_plane) {
+ *r_is_plane = true;
+ }
+ ATTR_FALLTHROUGH;
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_SCALE_Y:
+ return 1;
+
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_SCALE_XY:
+ if (r_is_plane) {
+ *r_is_plane = true;
+ }
+ ATTR_FALLTHROUGH;
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_ROT_Z:
+ case MAN_AXIS_SCALE_Z:
+ return 2;
+ }
+ return 3;
+}
+
+static bool manipulator_is_axis_visible(
+ const View3D *v3d, const RegionView3D *rv3d,
+ const float idot[3], const int axis_type, const int axis_idx)
+{
+ bool is_plane = false;
+ const uint aidx_norm = manipulator_orientation_axis(axis_idx, &is_plane);
+ /* don't draw axis perpendicular to the view */
+ if (aidx_norm < 3) {
+ float idot_axis = idot[aidx_norm];
+ if (is_plane) {
+ idot_axis = 1.0f - idot_axis;
+ }
+ if (idot_axis < TW_AXIS_DOT_MIN) {
+ return false;
+ }
+ }
+
+ if ((axis_type == MAN_AXES_TRANSLATE && !(v3d->twtype & V3D_MANIP_TRANSLATE)) ||
+ (axis_type == MAN_AXES_ROTATE && !(v3d->twtype & V3D_MANIP_ROTATE)) ||
+ (axis_type == MAN_AXES_SCALE && !(v3d->twtype & V3D_MANIP_SCALE)))
+ {
+ return false;
+ }
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ return (rv3d->twdrawflag & MAN_TRANS_X);
+ case MAN_AXIS_TRANS_Y:
+ return (rv3d->twdrawflag & MAN_TRANS_Y);
+ case MAN_AXIS_TRANS_Z:
+ return (rv3d->twdrawflag & MAN_TRANS_Z);
+ case MAN_AXIS_TRANS_C:
+ return (rv3d->twdrawflag & MAN_TRANS_C);
+ case MAN_AXIS_ROT_X:
+ return (rv3d->twdrawflag & MAN_ROT_X);
+ case MAN_AXIS_ROT_Y:
+ return (rv3d->twdrawflag & MAN_ROT_Y);
+ case MAN_AXIS_ROT_Z:
+ return (rv3d->twdrawflag & MAN_ROT_Z);
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_ROT_T:
+ return (rv3d->twdrawflag & MAN_ROT_C);
+ case MAN_AXIS_SCALE_X:
+ return (rv3d->twdrawflag & MAN_SCALE_X);
+ case MAN_AXIS_SCALE_Y:
+ return (rv3d->twdrawflag & MAN_SCALE_Y);
+ case MAN_AXIS_SCALE_Z:
+ return (rv3d->twdrawflag & MAN_SCALE_Z);
+ case MAN_AXIS_SCALE_C:
+ return (rv3d->twdrawflag & MAN_SCALE_C && (v3d->twtype & V3D_MANIP_TRANSLATE) == 0);
+ case MAN_AXIS_TRANS_XY:
+ return (rv3d->twdrawflag & MAN_TRANS_X &&
+ rv3d->twdrawflag & MAN_TRANS_Y &&
+ (v3d->twtype & V3D_MANIP_ROTATE) == 0);
+ case MAN_AXIS_TRANS_YZ:
+ return (rv3d->twdrawflag & MAN_TRANS_Y &&
+ rv3d->twdrawflag & MAN_TRANS_Z &&
+ (v3d->twtype & V3D_MANIP_ROTATE) == 0);
+ case MAN_AXIS_TRANS_ZX:
+ return (rv3d->twdrawflag & MAN_TRANS_Z &&
+ rv3d->twdrawflag & MAN_TRANS_X &&
+ (v3d->twtype & V3D_MANIP_ROTATE) == 0);
+ case MAN_AXIS_SCALE_XY:
+ return (rv3d->twdrawflag & MAN_SCALE_X &&
+ rv3d->twdrawflag & MAN_SCALE_Y &&
+ (v3d->twtype & V3D_MANIP_TRANSLATE) == 0 &&
+ (v3d->twtype & V3D_MANIP_ROTATE) == 0);
+ case MAN_AXIS_SCALE_YZ:
+ return (rv3d->twdrawflag & MAN_SCALE_Y &&
+ rv3d->twdrawflag & MAN_SCALE_Z &&
+ (v3d->twtype & V3D_MANIP_TRANSLATE) == 0 &&
+ (v3d->twtype & V3D_MANIP_ROTATE) == 0);
+ case MAN_AXIS_SCALE_ZX:
+ return (rv3d->twdrawflag & MAN_SCALE_Z &&
+ rv3d->twdrawflag & MAN_SCALE_X &&
+ (v3d->twtype & V3D_MANIP_TRANSLATE) == 0 &&
+ (v3d->twtype & V3D_MANIP_ROTATE) == 0);
+ }
+ return false;
+}
+
+static void manipulator_get_axis_color(
+ const int axis_idx, const float idot[3],
+ float r_col[4], float r_col_hi[4])
+{
+ /* alpha values for normal/highlighted states */
+ const float alpha = 0.6f;
+ const float alpha_hi = 1.0f;
+ float alpha_fac;
+
+ bool is_plane = false;
+ const int axis_idx_norm = manipulator_orientation_axis(axis_idx, &is_plane);
+ /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */
+ if (axis_idx_norm < 3) {
+ float idot_axis = idot[axis_idx_norm];
+ if (is_plane) {
+ idot_axis = 1.0f - idot_axis;
+ }
+ alpha_fac = (idot_axis > TW_AXIS_DOT_MAX) ?
+ 1.0f : (idot_axis < TW_AXIS_DOT_MIN) ?
+ 0.0f : ((idot_axis - TW_AXIS_DOT_MIN) / (TW_AXIS_DOT_MAX - TW_AXIS_DOT_MIN));
+ }
+ else {
+ /* trackball rotation axis is a special case, we only draw a slight overlay */
+ alpha_fac = (axis_idx == MAN_AXIS_ROT_T) ? 0.1f : 1.0f;
+ }
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_SCALE_X:
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_SCALE_YZ:
+ UI_GetThemeColor4fv(TH_AXIS_X, r_col);
+ break;
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_SCALE_Y:
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_ZX:
+ UI_GetThemeColor4fv(TH_AXIS_Y, r_col);
+ break;
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_ROT_Z:
+ case MAN_AXIS_SCALE_Z:
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_SCALE_XY:
+ UI_GetThemeColor4fv(TH_AXIS_Z, r_col);
+ break;
+ case MAN_AXIS_TRANS_C:
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_SCALE_C:
+ case MAN_AXIS_ROT_T:
+ copy_v4_fl(r_col, 1.0f);
+ break;
+ }
+
+ copy_v4_v4(r_col_hi, r_col);
+
+ r_col[3] = alpha * alpha_fac;
+ r_col_hi[3] = alpha_hi * alpha_fac;
+}
+
+static void manipulator_get_axis_constraint(const int axis_idx, int r_axis[3])
+{
+ zero_v3_int(r_axis);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_SCALE_X:
+ r_axis[0] = 1;
+ break;
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_SCALE_Y:
+ r_axis[1] = 1;
+ break;
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_ROT_Z:
+ case MAN_AXIS_SCALE_Z:
+ r_axis[2] = 1;
+ break;
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_SCALE_XY:
+ r_axis[0] = r_axis[1] = 1;
+ break;
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_SCALE_YZ:
+ r_axis[1] = r_axis[2] = 1;
+ break;
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_ZX:
+ r_axis[2] = r_axis[0] = 1;
+ break;
+ default:
+ break;
+ }
+}
+
+
+/* **************** Preparation Stuff **************** */
+
/* transform widget center calc helper for below */
static void calc_tw_center(struct TransformBounds *tbounds, const float co[3])
{
minmax_v3v3_v3(tbounds->min, tbounds->max, co);
add_v3_v3(tbounds->center, co);
+
+#ifdef USE_AXIS_BOUNDS
+ for (int i = 0; i < 3; i++) {
+ const float d = dot_v3v3(tbounds->axis[i], co);
+ tbounds->axis_min[i] = min_ff(d, tbounds->axis_min[i]);
+ tbounds->axis_max[i] = max_ff(d, tbounds->axis_max[i]);
+ }
+#endif
}
static void protectflag_to_drawflags(short protectflag, short *drawflags)
@@ -261,16 +585,19 @@ bool gimbal_axis(Object *ob, float gmat[3][3])
/* centroid, boundbox, of selection */
/* returns total items selected */
-static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbounds)
+static int calc_manipulator_stats(
+ const bContext *C, bool use_only_center,
+ struct TransformBounds *tbounds)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
Base *base;
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
bGPdata *gpd = CTX_data_gpencil_data(C);
const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE));
int a, totsel = 0;
@@ -278,12 +605,104 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo
/* transform widget matrix */
unit_m4(rv3d->twmat);
+#ifdef USE_AXIS_BOUNDS
+ unit_m3(rv3d->tw_axis_matrix);
+ zero_v3(rv3d->tw_axis_min);
+ zero_v3(rv3d->tw_axis_max);
+#endif
+
rv3d->twdrawflag = 0xFFFF;
+ /* global, local or normal orientation?
+ * if we could check 'totsel' now, this should be skipped with no selection. */
+ if (ob && !is_gp_edit) {
+
+ switch (v3d->twmode) {
+
+ case V3D_MANIP_GLOBAL:
+ {
+ break; /* nothing to do */
+ }
+ case V3D_MANIP_GIMBAL:
+ {
+ float mat[3][3];
+ if (gimbal_axis(ob, mat)) {
+ copy_m4_m3(rv3d->twmat, mat);
+ break;
+ }
+ /* if not gimbal, fall through to normal */
+ ATTR_FALLTHROUGH;
+ }
+ case V3D_MANIP_NORMAL:
+ {
+ if (obedit || ob->mode & OB_MODE_POSE) {
+ float mat[3][3];
+ ED_getTransformOrientationMatrix(C, mat, v3d->around);
+ copy_m4_m3(rv3d->twmat, mat);
+ break;
+ }
+ /* no break we define 'normal' as 'local' in Object mode */
+ ATTR_FALLTHROUGH;
+ }
+ case V3D_MANIP_LOCAL:
+ {
+ if (ob->mode & OB_MODE_POSE) {
+ /* each bone moves on its own local axis, but to avoid confusion,
+ * use the active pones axis for display [#33575], this works as expected on a single bone
+ * and users who select many bones will understand whats going on and what local means
+ * when they start transforming */
+ float mat[3][3];
+ ED_getTransformOrientationMatrix(C, mat, v3d->around);
+ copy_m4_m3(rv3d->twmat, mat);
+ break;
+ }
+ copy_m4_m4(rv3d->twmat, ob->obmat);
+ normalize_m4(rv3d->twmat);
+ break;
+ }
+ case V3D_MANIP_VIEW:
+ {
+ float mat[3][3];
+ copy_m3_m4(mat, rv3d->viewinv);
+ normalize_m3(mat);
+ copy_m4_m3(rv3d->twmat, mat);
+ break;
+ }
+ case V3D_MANIP_CUSTOM:
+ {
+ TransformOrientation *custom_orientation = BKE_workspace_transform_orientation_find(
+ CTX_wm_workspace(C), v3d->custom_orientation_index);
+ float mat[3][3];
+
+ if (applyTransformOrientation(custom_orientation, mat, NULL)) {
+ copy_m4_m3(rv3d->twmat, mat);
+ }
+ break;
+ }
+ }
+ }
+
/* transform widget centroid/center */
INIT_MINMAX(tbounds->min, tbounds->max);
zero_v3(tbounds->center);
+#ifdef USE_AXIS_BOUNDS
+ copy_m3_m4(tbounds->axis, rv3d->twmat);
+ if (ob && ob->mode & OB_MODE_EDIT) {
+ float diff_mat[3][3];
+ copy_m3_m4(diff_mat, ob->obmat);
+ normalize_m3(diff_mat);
+ invert_m3(diff_mat);
+ mul_m3_m3m3(tbounds->axis, tbounds->axis, diff_mat);
+ normalize_m3(tbounds->axis);
+ }
+
+ for (int i = 0; i < 3; i++) {
+ tbounds->axis_min[i] = +FLT_MAX;
+ tbounds->axis_max[i] = -FLT_MAX;
+ }
+#endif
+
if (is_gp_edit) {
float diff_mat[4][4];
float fpt[3];
@@ -330,13 +749,11 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo
/* selection center */
if (totsel) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel);
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); /* centroid! */
}
}
else if (obedit) {
ob = obedit;
- if ((ob->lay & v3d->lay) == 0) return 0;
-
if (obedit->type == OB_MESH) {
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMEditSelection ese;
@@ -442,15 +859,11 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo
}
else {
if (bezt->f1 & SELECT) {
- calc_tw_center(
- tbounds,
- bezt->vec[(v3d->around == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0]);
+ calc_tw_center(tbounds, bezt->vec[(v3d->around == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0]);
totsel++;
}
if (bezt->f3 & SELECT) {
- calc_tw_center(
- tbounds,
- bezt->vec[(v3d->around == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2]);
+ calc_tw_center(tbounds, bezt->vec[(v3d->around == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2]);
totsel++;
}
}
@@ -512,7 +925,7 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo
/* selection center */
if (totsel) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel);
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
mul_m4_v3(obedit->obmat, tbounds->center);
mul_m4_v3(obedit->obmat, tbounds->min);
mul_m4_v3(obedit->obmat, tbounds->max);
@@ -523,8 +936,6 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo
int mode = TFM_ROTATION; // mislead counting bones... bah. We don't know the manipulator mode, could be mixed
bool ok = false;
- if ((ob->lay & v3d->lay) == 0) return 0;
-
if ((v3d->around == V3D_AROUND_ACTIVE) && (pchan = BKE_pose_channel_active(ob))) {
/* doesn't check selection or visibility intentionally */
Bone *bone = pchan->bone;
@@ -552,7 +963,7 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo
}
if (ok) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel);
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
mul_m4_v3(ob->obmat, tbounds->center);
mul_m4_v3(ob->obmat, tbounds->min);
mul_m4_v3(ob->obmat, tbounds->max);
@@ -562,7 +973,7 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo
/* pass */
}
else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
PTCacheEditPoint *point;
PTCacheEditKey *ek;
int k;
@@ -582,20 +993,30 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo
/* selection center */
if (totsel)
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel);
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
}
}
else {
/* we need the one selected object, if its not active */
- ob = OBACT;
- if (ob && !(ob->flag & SELECT)) ob = NULL;
+ base = BASACT(view_layer);
+ ob = OBACT(view_layer);
+ if (base && ((base->flag & BASE_SELECTED) == 0)) ob = NULL;
- for (base = scene->base.first; base; base = base->next) {
- if (TESTBASELIB(v3d, base)) {
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ if (TESTBASELIB(base)) {
if (ob == NULL)
ob = base->object;
- calc_tw_center(tbounds, base->object->obmat[3]);
+ if (use_only_center || base->object->bb == NULL) {
+ calc_tw_center(tbounds, base->object->obmat[3]);
+ }
+ else {
+ for (uint j = 0; j < 8; j++) {
+ float co[3];
+ mul_v3_m4v3(co, base->object->obmat, base->object->bb->vec[j]);
+ calc_tw_center(tbounds, co);
+ }
+ }
protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
totsel++;
}
@@ -603,1378 +1024,658 @@ static int calc_manipulator_stats(const bContext *C, struct TransformBounds *tbo
/* selection center */
if (totsel) {
- mul_v3_fl(tbounds->center, 1.0f / (float)totsel);
+ mul_v3_fl(tbounds->center, 1.0f / (float)totsel); // centroid!
}
}
- /* global, local or normal orientation? */
- if (ob && totsel && !is_gp_edit) {
-
- switch (v3d->twmode) {
-
- case V3D_MANIP_GLOBAL:
- {
- break; /* nothing to do */
- }
- case V3D_MANIP_GIMBAL:
- {
- float mat[3][3];
- if (gimbal_axis(ob, mat)) {
- copy_m4_m3(rv3d->twmat, mat);
- break;
- }
- /* if not gimbal, fall through to normal */
- ATTR_FALLTHROUGH;
- }
- case V3D_MANIP_NORMAL:
- {
- if (obedit || ob->mode & OB_MODE_POSE) {
- float mat[3][3];
- ED_getTransformOrientationMatrix(C, mat, v3d->around);
- copy_m4_m3(rv3d->twmat, mat);
- break;
- }
- /* no break we define 'normal' as 'local' in Object mode */
- ATTR_FALLTHROUGH;
- }
- case V3D_MANIP_LOCAL:
- {
- if (ob->mode & OB_MODE_POSE) {
- /* each bone moves on its own local axis, but to avoid confusion,
- * use the active pones axis for display [#33575], this works as expected on a single bone
- * and users who select many bones will understand whats going on and what local means
- * when they start transforming */
- float mat[3][3];
- ED_getTransformOrientationMatrix(C, mat, v3d->around);
- copy_m4_m3(rv3d->twmat, mat);
- break;
- }
- copy_m4_m4(rv3d->twmat, ob->obmat);
- normalize_m4(rv3d->twmat);
- break;
- }
- case V3D_MANIP_VIEW:
- {
- float mat[3][3];
- copy_m3_m4(mat, rv3d->viewinv);
- normalize_m3(mat);
- copy_m4_m3(rv3d->twmat, mat);
- break;
- }
- default: /* V3D_MANIP_CUSTOM */
- {
- float mat[3][3];
- if (applyTransformOrientation(C, mat, NULL, v3d->twmode - V3D_MANIP_CUSTOM)) {
- copy_m4_m3(rv3d->twmat, mat);
- }
- break;
- }
- }
-
+ if (totsel == 0) {
+ unit_m4(rv3d->twmat);
+ }
+ else {
+#ifdef USE_AXIS_BOUNDS
+ copy_v3_v3(rv3d->tw_axis_min, tbounds->axis_min);
+ copy_v3_v3(rv3d->tw_axis_max, tbounds->axis_max);
+ copy_m3_m3(rv3d->tw_axis_matrix, tbounds->axis);
+#endif
}
return totsel;
}
-/* don't draw axis perpendicular to the view */
-static void test_manipulator_axis(const bContext *C)
+static void manipulator_get_idot(RegionView3D *rv3d, float r_idot[3])
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
float view_vec[3], axis_vec[3];
- float idot;
- int i;
-
- const int twdrawflag_axis[3] = {
- (MAN_TRANS_X | MAN_SCALE_X),
- (MAN_TRANS_Y | MAN_SCALE_Y),
- (MAN_TRANS_Z | MAN_SCALE_Z)};
-
ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], view_vec);
-
- for (i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++) {
normalize_v3_v3(axis_vec, rv3d->twmat[i]);
- rv3d->tw_idot[i] = idot = 1.0f - fabsf(dot_v3v3(view_vec, axis_vec));
- if (idot < TW_AXIS_DOT_MIN) {
- rv3d->twdrawflag &= ~twdrawflag_axis[i];
- }
+ r_idot[i] = 1.0f - fabsf(dot_v3v3(view_vec, axis_vec));
}
}
-
-/* ******************** DRAWING STUFFIES *********** */
-
-static float screen_aligned(RegionView3D *rv3d, float mat[4][4])
-{
- glTranslate3fv(mat[3]);
-
- /* sets view screen aligned */
- glRotatef(-360.0f * saacos(rv3d->viewquat[0]) / (float)M_PI, rv3d->viewquat[1], rv3d->viewquat[2], rv3d->viewquat[3]);
-
- return len_v3(mat[0]); /* draw scale */
-}
-
-
-/* radring = radius of doughnut rings
- * radhole = radius hole
- * start = starting segment (based on nrings)
- * end = end segment
- * nsides = amount of points in ring
- * nrigns = amount of rings
- */
-static void partial_doughnut(float radring, float radhole, int start, int end, int nsides, int nrings)
+static void manipulator_prepare_mat(
+ const bContext *C, View3D *v3d, RegionView3D *rv3d, const struct TransformBounds *tbounds)
{
- float theta, phi, theta1;
- float cos_theta, sin_theta;
- float cos_theta1, sin_theta1;
- float ring_delta, side_delta;
- int i, j, do_caps = true;
-
- if (start == 0 && end == nrings) do_caps = false;
-
- ring_delta = 2.0f * (float)M_PI / (float)nrings;
- side_delta = 2.0f * (float)M_PI / (float)nsides;
-
- theta = (float)M_PI + 0.5f * ring_delta;
- cos_theta = cosf(theta);
- sin_theta = sinf(theta);
-
- for (i = nrings - 1; i >= 0; i--) {
- theta1 = theta + ring_delta;
- cos_theta1 = cosf(theta1);
- sin_theta1 = sinf(theta1);
-
- if (do_caps && i == start) { // cap
- glBegin(GL_POLYGON);
- phi = 0.0;
- for (j = nsides; j >= 0; j--) {
- float cos_phi, sin_phi, dist;
-
- phi += side_delta;
- cos_phi = cosf(phi);
- sin_phi = sinf(phi);
- dist = radhole + radring * cos_phi;
-
- glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi);
- }
- glEnd();
- }
- if (i >= start && i <= end) {
- glBegin(GL_QUAD_STRIP);
- phi = 0.0;
- for (j = nsides; j >= 0; j--) {
- float cos_phi, sin_phi, dist;
-
- phi += side_delta;
- cos_phi = cosf(phi);
- sin_phi = sinf(phi);
- dist = radhole + radring * cos_phi;
-
- glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi);
- glVertex3f(cos_theta * dist, -sin_theta * dist, radring * sin_phi);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ switch (v3d->around) {
+ case V3D_AROUND_CENTER_BOUNDS:
+ case V3D_AROUND_ACTIVE:
+ {
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ Object *ob = OBACT(view_layer);
+
+ if (((v3d->around == V3D_AROUND_ACTIVE) && (scene->obedit == NULL)) &&
+ ((gpd == NULL) || !(gpd->flag & GP_DATA_STROKE_EDITMODE)) &&
+ (!(ob->mode & OB_MODE_POSE)))
+ {
+ copy_v3_v3(rv3d->twmat[3], ob->obmat[3]);
}
- glEnd();
- }
-
- if (do_caps && i == end) { // cap
- glBegin(GL_POLYGON);
- phi = 0.0;
- for (j = nsides; j >= 0; j--) {
- float cos_phi, sin_phi, dist;
-
- phi -= side_delta;
- cos_phi = cosf(phi);
- sin_phi = sinf(phi);
- dist = radhole + radring * cos_phi;
-
- glVertex3f(cos_theta * dist, -sin_theta * dist, radring * sin_phi);
+ else {
+ mid_v3_v3v3(rv3d->twmat[3], tbounds->min, tbounds->max);
}
- glEnd();
+ break;
}
-
-
- theta = theta1;
- cos_theta = cos_theta1;
- sin_theta = sin_theta1;
- }
-}
-
-static char axisBlendAngle(float idot)
-{
- if (idot > TW_AXIS_DOT_MAX) {
- return 255;
- }
- else if (idot < TW_AXIS_DOT_MIN) {
- return 0;
- }
- else {
- return (char)(255.0f * (idot - TW_AXIS_DOT_MIN) / (TW_AXIS_DOT_MAX - TW_AXIS_DOT_MIN));
+ case V3D_AROUND_LOCAL_ORIGINS:
+ case V3D_AROUND_CENTER_MEAN:
+ copy_v3_v3(rv3d->twmat[3], tbounds->center);
+ break;
+ case V3D_AROUND_CURSOR:
+ copy_v3_v3(rv3d->twmat[3], ED_view3d_cursor3d_get(scene, v3d));
+ break;
}
}
-/* three colors can be set:
- * gray for ghosting
- * moving: in transform theme color
- * else the red/green/blue
+/**
+ * Sets up \a r_start and \a r_len to define arrow line range.
+ * Needed to adjust line drawing for combined manipulator axis types.
*/
-static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned char alpha)
+static void manipulator_line_range(const View3D *v3d, const short axis_type, float *r_start, float *r_len)
{
- unsigned char col[4] = {0};
- col[3] = alpha;
-
- if (colcode == MAN_GHOST) {
- col[3] = 70;
- }
- else if (colcode == MAN_MOVECOL) {
- UI_GetThemeColor3ubv(TH_TRANSFORM, col);
- }
- else {
- switch (axis) {
- case 'C':
- UI_GetThemeColor3ubv(TH_TRANSFORM, col);
- if (v3d->twmode == V3D_MANIP_LOCAL) {
- col[0] = col[0] > 200 ? 255 : col[0] + 55;
- col[1] = col[1] > 200 ? 255 : col[1] + 55;
- col[2] = col[2] > 200 ? 255 : col[2] + 55;
- }
- else if (v3d->twmode == V3D_MANIP_NORMAL) {
- col[0] = col[0] < 55 ? 0 : col[0] - 55;
- col[1] = col[1] < 55 ? 0 : col[1] - 55;
- col[2] = col[2] < 55 ? 0 : col[2] - 55;
- }
- break;
- case 'X':
- UI_GetThemeColor3ubv(TH_AXIS_X, col);
- break;
- case 'Y':
- UI_GetThemeColor3ubv(TH_AXIS_Y, col);
- break;
- case 'Z':
- UI_GetThemeColor3ubv(TH_AXIS_Z, col);
- break;
- default:
- BLI_assert(0);
- break;
- }
- }
+ const float ofs = 0.2f;
- glColor4ubv(col);
-}
+ *r_start = 0.2f;
+ *r_len = 1.0f;
-static void manipulator_axis_order(RegionView3D *rv3d, int r_axis_order[3])
-{
- float axis_values[3];
- float vec[3];
-
- ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], vec);
-
- axis_values[0] = -dot_v3v3(rv3d->twmat[0], vec);
- axis_values[1] = -dot_v3v3(rv3d->twmat[1], vec);
- axis_values[2] = -dot_v3v3(rv3d->twmat[2], vec);
-
- axis_sort_v3(axis_values, r_axis_order);
-}
-
-/* viewmatrix should have been set OK, also no shademode! */
-static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int colcode,
- int flagx, int flagy, int flagz, int axis,
- const bool is_picksel)
-{
- switch (axis) {
- case 0:
- /* axes */
- if (flagx) {
- if (is_picksel) {
- if (flagx & MAN_SCALE_X) GPU_select_load_id(MAN_SCALE_X);
- else if (flagx & MAN_TRANS_X) GPU_select_load_id(MAN_TRANS_X);
- }
- else {
- manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0]));
- }
- glBegin(GL_LINES);
- glVertex3f(0.2f, 0.0f, 0.0f);
- glVertex3f(1.0f, 0.0f, 0.0f);
- glEnd();
+ switch (axis_type) {
+ case MAN_AXES_TRANSLATE:
+ if (v3d->twtype & V3D_MANIP_SCALE) {
+ *r_start = *r_len - ofs + 0.075f;
}
- break;
- case 1:
- if (flagy) {
- if (is_picksel) {
- if (flagy & MAN_SCALE_Y) GPU_select_load_id(MAN_SCALE_Y);
- else if (flagy & MAN_TRANS_Y) GPU_select_load_id(MAN_TRANS_Y);
- }
- else {
- manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1]));
- }
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.2f, 0.0f);
- glVertex3f(0.0f, 1.0f, 0.0f);
- glEnd();
+ if (v3d->twtype & V3D_MANIP_ROTATE) {
+ *r_len += ofs;
}
break;
- case 2:
- if (flagz) {
- if (is_picksel) {
- if (flagz & MAN_SCALE_Z) GPU_select_load_id(MAN_SCALE_Z);
- else if (flagz & MAN_TRANS_Z) GPU_select_load_id(MAN_TRANS_Z);
- }
- else {
- manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2]));
- }
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.2f);
- glVertex3f(0.0f, 0.0f, 1.0f);
- glEnd();
+ case MAN_AXES_SCALE:
+ if (v3d->twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE)) {
+ *r_len -= ofs + 0.025f;
}
break;
}
-}
-static void draw_manipulator_axes(View3D *v3d, RegionView3D *rv3d, int colcode,
- int flagx, int flagy, int flagz,
- const int axis_order[3], const bool is_picksel)
-{
- int i;
- for (i = 0; i < 3; i++) {
- draw_manipulator_axes_single(v3d, rv3d, colcode, flagx, flagy, flagz, axis_order[i], is_picksel);
- }
-}
-static void preOrthoFront(const bool ortho, float twmat[4][4], int axis)
-{
- if (ortho == false) {
- float omat[4][4];
- copy_m4_m4(omat, twmat);
- orthogonalize_m4(omat, axis);
- glPushMatrix();
- glMultMatrixf(omat);
- glFrontFace(is_negative_m4(omat) ? GL_CW : GL_CCW);
- }
+ *r_len -= *r_start;
}
-static void postOrtho(const bool ortho)
+static void manipulator_xform_message_subscribe(
+ wmManipulatorGroup *mgroup, struct wmMsgBus *mbus,
+ bScreen *screen, ScrArea *sa, ARegion *ar, const void *type_fn)
{
- if (ortho == false) {
- glPopMatrix();
- }
-}
+ /* Subscribe to view properties */
+ wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = {
+ .owner = ar,
+ .user_data = mgroup->parent_mmap,
+ .notify = WM_manipulator_do_msg_notify_tag_refresh,
+ };
-BLI_INLINE bool manipulator_rotate_is_visible(const int drawflags)
-{
- return (drawflags & (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z));
-}
+ PointerRNA space_ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceView3D, sa->spacedata.first, &space_ptr);
-static void draw_manipulator_rotate(
- View3D *v3d, RegionView3D *rv3d, const int drawflags, const int combo,
- const bool is_moving, const bool is_picksel)
-{
- double plane[4];
- float matt[4][4];
- float size, unitmat[4][4];
- float cywid = 0.33f * 0.01f * (float)U.tw_handlesize;
- float cusize = cywid * 0.65f;
- int arcs = (G.debug_value != 2);
- const int colcode = (is_moving) ? MAN_MOVECOL : MAN_RGB;
- bool ortho;
-
- /* skip drawing if all axes are locked */
- if (manipulator_rotate_is_visible(drawflags) == false) return;
-
- /* Init stuff */
- glDisable(GL_DEPTH_TEST);
- unit_m4(unitmat);
-
- /* prepare for screen aligned draw */
- size = len_v3(rv3d->twmat[0]);
- glPushMatrix();
- glTranslate3fv(rv3d->twmat[3]);
-
- if (arcs) {
- /* clipplane makes nice handles, calc here because of multmatrix but with translate! */
- copy_v3db_v3fl(plane, rv3d->viewinv[2]);
- plane[3] = -0.02f * size; // clip just a bit more
- glClipPlane(GL_CLIP_PLANE0, plane);
- }
- /* sets view screen aligned */
- glRotatef(-360.0f * saacos(rv3d->viewquat[0]) / (float)M_PI, rv3d->viewquat[1], rv3d->viewquat[2], rv3d->viewquat[3]);
-
- /* Screen aligned help circle */
- if (arcs) {
- if (is_picksel == false) {
- UI_ThemeColorShade(TH_BACK, -30);
- drawcircball(GL_LINE_LOOP, unitmat[3], size, unitmat);
+ {
+ extern PropertyRNA rna_SpaceView3D_transform_orientation;
+ const PropertyRNA *props[] = {
+ &rna_SpaceView3D_transform_orientation,
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &space_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
}
}
- /* Screen aligned trackball rot circle */
- if (drawflags & MAN_ROT_T) {
- if (is_picksel) GPU_select_load_id(MAN_ROT_T);
- else UI_ThemeColor(TH_TRANSFORM);
-
- drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f * size, unitmat);
- }
-
- /* Screen aligned view rot circle */
- if (drawflags & MAN_ROT_V) {
- if (is_picksel) GPU_select_load_id(MAN_ROT_V);
- else UI_ThemeColor(TH_TRANSFORM);
- drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f * size, unitmat);
-
- if (is_moving) {
- float vec[3];
- vec[0] = 0; // XXX (float)(t->mouse.imval[0] - t->center2d[0]);
- vec[1] = 0; // XXX (float)(t->mouse.imval[1] - t->center2d[1]);
- vec[2] = 0.0f;
- normalize_v3_length(vec, 1.2f * size);
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3fv(vec);
- glEnd();
+ if (type_fn == TRANSFORM_WGT_manipulator) {
+ extern PropertyRNA rna_SpaceView3D_pivot_point;
+ const PropertyRNA *props[] = {
+ &rna_SpaceView3D_pivot_point
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &space_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
}
}
- glPopMatrix();
-
-
- ortho = is_orthogonal_m4(rv3d->twmat);
-
- /* apply the transform delta */
- if (is_moving) {
- copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
- // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat);
- if (ortho) {
- glMultMatrixf(matt);
- glFrontFace(is_negative_m4(matt) ? GL_CW : GL_CCW);
- }
+ else if (type_fn == VIEW3D_WGT_xform_cage) {
+ /* pass */
}
else {
- if (ortho) {
- glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW : GL_CCW);
- glMultMatrixf(rv3d->twmat);
- }
+ BLI_assert(0);
}
+}
- /* axes */
- if (arcs == 0) {
- if (!is_picksel) {
- if ((combo & V3D_MANIP_SCALE) == 0) {
- /* axis */
- if ((drawflags & MAN_ROT_X) || (is_moving && (drawflags & MAN_ROT_Z))) {
- preOrthoFront(ortho, rv3d->twmat, 2);
- manipulator_setcolor(v3d, 'X', colcode, 255);
- glBegin(GL_LINES);
- glVertex3f(0.2f, 0.0f, 0.0f);
- glVertex3f(1.0f, 0.0f, 0.0f);
- glEnd();
- postOrtho(ortho);
- }
- if ((drawflags & MAN_ROT_Y) || (is_moving && (drawflags & MAN_ROT_X))) {
- preOrthoFront(ortho, rv3d->twmat, 0);
- manipulator_setcolor(v3d, 'Y', colcode, 255);
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.2f, 0.0f);
- glVertex3f(0.0f, 1.0f, 0.0f);
- glEnd();
- postOrtho(ortho);
- }
- if ((drawflags & MAN_ROT_Z) || (is_moving && (drawflags & MAN_ROT_Y))) {
- preOrthoFront(ortho, rv3d->twmat, 1);
- manipulator_setcolor(v3d, 'Z', colcode, 255);
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.2f);
- glVertex3f(0.0f, 0.0f, 1.0f);
- glEnd();
- postOrtho(ortho);
- }
- }
- }
- }
+/** \} */
- if (arcs == 0 && is_moving) {
- /* Z circle */
- if (drawflags & MAN_ROT_Z) {
- preOrthoFront(ortho, matt, 2);
- if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
- else manipulator_setcolor(v3d, 'Z', colcode, 255);
- drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
- postOrtho(ortho);
- }
- /* X circle */
- if (drawflags & MAN_ROT_X) {
- preOrthoFront(ortho, matt, 0);
- if (is_picksel) GPU_select_load_id(MAN_ROT_X);
- else manipulator_setcolor(v3d, 'X', colcode, 255);
- glRotatef(90.0, 0.0, 1.0, 0.0);
- drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
- glRotatef(-90.0, 0.0, 1.0, 0.0);
- postOrtho(ortho);
- }
- /* Y circle */
- if (drawflags & MAN_ROT_Y) {
- preOrthoFront(ortho, matt, 1);
- if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
- else manipulator_setcolor(v3d, 'Y', colcode, 255);
- glRotatef(-90.0, 1.0, 0.0, 0.0);
- drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
- glRotatef(90.0, 1.0, 0.0, 0.0);
- postOrtho(ortho);
- }
- }
- // donut arcs
- if (arcs) {
- glEnable(GL_CLIP_PLANE0);
-
- /* Z circle */
- if (drawflags & MAN_ROT_Z) {
- preOrthoFront(ortho, rv3d->twmat, 2);
- if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
- else manipulator_setcolor(v3d, 'Z', colcode, 255);
- partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48);
- postOrtho(ortho);
- }
- /* X circle */
- if (drawflags & MAN_ROT_X) {
- preOrthoFront(ortho, rv3d->twmat, 0);
- if (is_picksel) GPU_select_load_id(MAN_ROT_X);
- else manipulator_setcolor(v3d, 'X', colcode, 255);
- glRotatef(90.0, 0.0, 1.0, 0.0);
- partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48);
- glRotatef(-90.0, 0.0, 1.0, 0.0);
- postOrtho(ortho);
- }
- /* Y circle */
- if (drawflags & MAN_ROT_Y) {
- preOrthoFront(ortho, rv3d->twmat, 1);
- if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
- else manipulator_setcolor(v3d, 'Y', colcode, 255);
- glRotatef(-90.0, 1.0, 0.0, 0.0);
- partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48);
- glRotatef(90.0, 1.0, 0.0, 0.0);
- postOrtho(ortho);
- }
+/* -------------------------------------------------------------------- */
+/** \name Transform Manipulator
+ * \{ */
- glDisable(GL_CLIP_PLANE0);
- }
-
- if (arcs == 0) {
+static ManipulatorGroup *manipulatorgroup_init(wmManipulatorGroup *mgroup)
+{
+ ManipulatorGroup *man;
- /* Z handle on X axis */
- if (drawflags & MAN_ROT_Z) {
- preOrthoFront(ortho, rv3d->twmat, 2);
- glPushMatrix();
- if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
- else manipulator_setcolor(v3d, 'Z', colcode, 255);
+ man = MEM_callocN(sizeof(ManipulatorGroup), "manipulator_data");
- partial_doughnut(0.7f * cusize, 1.0f, 31, 33, 8, 64);
+ const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true);
+ const wmManipulatorType *wt_dial = WM_manipulatortype_find("MANIPULATOR_WT_dial_3d", true);
+ const wmManipulatorType *wt_prim = WM_manipulatortype_find("MANIPULATOR_WT_primitive_3d", true);
- glPopMatrix();
- postOrtho(ortho);
- }
+#define MANIPULATOR_NEW_ARROW(v, draw_style) { \
+ man->manipulators[v] = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); \
+ RNA_enum_set(man->manipulators[v]->ptr, "draw_style", draw_style); \
+} ((void)0)
+#define MANIPULATOR_NEW_DIAL(v, draw_options) { \
+ man->manipulators[v] = WM_manipulator_new_ptr(wt_dial, mgroup, NULL); \
+ RNA_enum_set(man->manipulators[v]->ptr, "draw_options", draw_options); \
+} ((void)0)
+#define MANIPULATOR_NEW_PRIM(v, draw_style) { \
+ man->manipulators[v] = WM_manipulator_new_ptr(wt_prim, mgroup, NULL); \
+ RNA_enum_set(man->manipulators[v]->ptr, "draw_style", draw_style); \
+} ((void)0)
- /* Y handle on X axis */
- if (drawflags & MAN_ROT_Y) {
- preOrthoFront(ortho, rv3d->twmat, 1);
- glPushMatrix();
- if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
- else manipulator_setcolor(v3d, 'Y', colcode, 255);
+ /* add/init widgets - order matters! */
+ MANIPULATOR_NEW_DIAL(MAN_AXIS_ROT_T, ED_MANIPULATOR_DIAL_DRAW_FLAG_FILL);
- glRotatef(90.0, 1.0, 0.0, 0.0);
- glRotatef(90.0, 0.0, 0.0, 1.0);
- partial_doughnut(0.7f * cusize, 1.0f, 31, 33, 8, 64);
+ MANIPULATOR_NEW_DIAL(MAN_AXIS_SCALE_C, ED_MANIPULATOR_DIAL_DRAW_FLAG_NOP);
- glPopMatrix();
- postOrtho(ortho);
- }
+ MANIPULATOR_NEW_ARROW(MAN_AXIS_SCALE_X, ED_MANIPULATOR_ARROW_STYLE_BOX);
+ MANIPULATOR_NEW_ARROW(MAN_AXIS_SCALE_Y, ED_MANIPULATOR_ARROW_STYLE_BOX);
+ MANIPULATOR_NEW_ARROW(MAN_AXIS_SCALE_Z, ED_MANIPULATOR_ARROW_STYLE_BOX);
- /* X handle on Z axis */
- if (drawflags & MAN_ROT_X) {
- preOrthoFront(ortho, rv3d->twmat, 0);
- glPushMatrix();
- if (is_picksel) GPU_select_load_id(MAN_ROT_X);
- else manipulator_setcolor(v3d, 'X', colcode, 255);
+ MANIPULATOR_NEW_PRIM(MAN_AXIS_SCALE_XY, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
+ MANIPULATOR_NEW_PRIM(MAN_AXIS_SCALE_YZ, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
+ MANIPULATOR_NEW_PRIM(MAN_AXIS_SCALE_ZX, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
- glRotatef(-90.0, 0.0, 1.0, 0.0);
- glRotatef(90.0, 0.0, 0.0, 1.0);
- partial_doughnut(0.7f * cusize, 1.0f, 31, 33, 8, 64);
+ MANIPULATOR_NEW_DIAL(MAN_AXIS_ROT_X, ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP);
+ MANIPULATOR_NEW_DIAL(MAN_AXIS_ROT_Y, ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP);
+ MANIPULATOR_NEW_DIAL(MAN_AXIS_ROT_Z, ED_MANIPULATOR_DIAL_DRAW_FLAG_CLIP);
- glPopMatrix();
- postOrtho(ortho);
- }
+ /* init screen aligned widget last here, looks better, behaves better */
+ MANIPULATOR_NEW_DIAL(MAN_AXIS_ROT_C, ED_MANIPULATOR_DIAL_DRAW_FLAG_NOP);
- }
+ MANIPULATOR_NEW_DIAL(MAN_AXIS_TRANS_C, ED_MANIPULATOR_DIAL_DRAW_FLAG_NOP);
- /* restore */
- glLoadMatrixf(rv3d->viewmat);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ MANIPULATOR_NEW_ARROW(MAN_AXIS_TRANS_X, ED_MANIPULATOR_ARROW_STYLE_NORMAL);
+ MANIPULATOR_NEW_ARROW(MAN_AXIS_TRANS_Y, ED_MANIPULATOR_ARROW_STYLE_NORMAL);
+ MANIPULATOR_NEW_ARROW(MAN_AXIS_TRANS_Z, ED_MANIPULATOR_ARROW_STYLE_NORMAL);
-}
+ MANIPULATOR_NEW_PRIM(MAN_AXIS_TRANS_XY, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
+ MANIPULATOR_NEW_PRIM(MAN_AXIS_TRANS_YZ, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
+ MANIPULATOR_NEW_PRIM(MAN_AXIS_TRANS_ZX, ED_MANIPULATOR_PRIMITIVE_STYLE_PLANE);
-static void drawsolidcube(float size)
-{
- const float cube[8][3] = {
- {-1.0, -1.0, -1.0},
- {-1.0, -1.0, 1.0},
- {-1.0, 1.0, 1.0},
- {-1.0, 1.0, -1.0},
- { 1.0, -1.0, -1.0},
- { 1.0, -1.0, 1.0},
- { 1.0, 1.0, 1.0},
- { 1.0, 1.0, -1.0},
- };
- float n[3] = {0.0f};
-
- glPushMatrix();
- glScalef(size, size, size);
-
- glBegin(GL_QUADS);
- n[0] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
- n[0] = 0;
- glEnd();
-
- glBegin(GL_QUADS);
- n[1] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
- n[1] = 0;
- glEnd();
-
- glBegin(GL_QUADS);
- n[0] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
- n[0] = 0;
- glEnd();
-
- glBegin(GL_QUADS);
- n[1] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
- n[1] = 0;
- glEnd();
-
- glBegin(GL_QUADS);
- n[2] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
- n[2] = 0;
- glEnd();
-
- glBegin(GL_QUADS);
- n[2] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
- glEnd();
-
- glPopMatrix();
+ return man;
}
-
-static void draw_manipulator_scale(
- View3D *v3d, RegionView3D *rv3d, const int drawflags, const int combo, const int colcode,
- const bool is_moving, const bool is_picksel)
+/**
+ * Custom handler for manipulator widgets
+ */
+static int manipulator_modal(
+ bContext *C, wmManipulator *widget, const wmEvent *UNUSED(event),
+ eWM_ManipulatorTweak UNUSED(tweak_flag))
{
- float cywid = 0.25f * 0.01f * (float)U.tw_handlesize;
- float cusize = cywid * 0.75f, dz;
- int axis_order[3] = {2, 0, 1};
- int i;
-
- /* when called while moving in mixed mode, do not draw when... */
- if ((drawflags & MAN_SCALE_C) == 0) return;
-
- manipulator_axis_order(rv3d, axis_order);
-
- glDisable(GL_DEPTH_TEST);
-
- /* not in combo mode */
- if ((combo & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE)) == 0) {
- float size, unitmat[4][4];
- int shift = 0; // XXX
-
- /* center circle, do not add to selection when shift is pressed (planar constraint) */
- if (is_picksel && shift == 0) GPU_select_load_id(MAN_SCALE_C);
- else manipulator_setcolor(v3d, 'C', colcode, 255);
+ const ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = sa->spacedata.first;
+ RegionView3D *rv3d = ar->regiondata;
+ struct TransformBounds tbounds;
- glPushMatrix();
- size = screen_aligned(rv3d, rv3d->twmat);
- unit_m4(unitmat);
- drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f * size, unitmat);
- glPopMatrix();
- dz = 1.0;
- }
- else {
- dz = 1.0f - 4.0f * cusize;
+ if (calc_manipulator_stats(C, true, &tbounds)) {
+ manipulator_prepare_mat(C, v3d, rv3d, &tbounds);
+ WM_manipulator_set_matrix_location(widget, rv3d->twmat[3]);
}
- if (is_moving) {
- float matt[4][4];
+ ED_region_tag_redraw(ar);
- copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
- // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat);
- glMultMatrixf(matt);
- glFrontFace(is_negative_m4(matt) ? GL_CW : GL_CCW);
- }
- else {
- glMultMatrixf(rv3d->twmat);
- glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW : GL_CCW);
- }
+ return OPERATOR_RUNNING_MODAL;
+}
- /* axis */
+static void WIDGETGROUP_manipulator_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ ManipulatorGroup *man = manipulatorgroup_init(mgroup);
+ struct {
+ wmOperatorType *translate, *rotate, *trackball, *resize;
+ } ot_store = {NULL};
- /* in combo mode, this is always drawn as first type */
- draw_manipulator_axes(v3d, rv3d, colcode,
- drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z,
- axis_order, is_picksel);
+ mgroup->customdata = man;
+ /* *** set properties for axes *** */
- for (i = 0; i < 3; i++) {
- switch (axis_order[i]) {
- case 0: /* X cube */
- if (drawflags & MAN_SCALE_X) {
- glTranslatef(dz, 0.0, 0.0);
- if (is_picksel) GPU_select_load_id(MAN_SCALE_X);
- else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0]));
- drawsolidcube(cusize);
- glTranslatef(-dz, 0.0, 0.0);
- }
+ MAN_ITER_AXES_BEGIN(axis, axis_idx)
+ {
+ const short axis_type = manipulator_get_axis_type(axis_idx);
+ int constraint_axis[3] = {1, 0, 0};
+ PointerRNA *ptr;
+
+ manipulator_get_axis_constraint(axis_idx, constraint_axis);
+
+ /* custom handler! */
+ WM_manipulator_set_fn_custom_modal(axis, manipulator_modal);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_SCALE_X:
+ case MAN_AXIS_SCALE_Y:
+ case MAN_AXIS_SCALE_Z:
+ WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH);
break;
- case 1: /* Y cube */
- if (drawflags & MAN_SCALE_Y) {
- glTranslatef(0.0, dz, 0.0);
- if (is_picksel) GPU_select_load_id(MAN_SCALE_Y);
- else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1]));
- drawsolidcube(cusize);
- glTranslatef(0.0, -dz, 0.0);
- }
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_ROT_Z:
+ /* increased line width for better display */
+ WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH + 1.0f);
+ WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_VALUE, true);
break;
- case 2: /* Z cube */
- if (drawflags & MAN_SCALE_Z) {
- glTranslatef(0.0, 0.0, dz);
- if (is_picksel) GPU_select_load_id(MAN_SCALE_Z);
- else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2]));
- drawsolidcube(cusize);
- glTranslatef(0.0, 0.0, -dz);
- }
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_XY:
+ case MAN_AXIS_SCALE_YZ:
+ case MAN_AXIS_SCALE_ZX:
+ {
+ const float ofs_ax = 11.0f;
+ const float ofs[3] = {ofs_ax, ofs_ax, 0.0f};
+ WM_manipulator_set_scale(axis, 0.07f);
+ WM_manipulator_set_matrix_offset_location(axis, ofs);
+ WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true);
break;
- }
- }
-
-#if 0 // XXX
- /* if shiftkey, center point as last, for selectbuffer order */
- if (is_picksel) {
- int shift = 0; // XXX
-
- if (shift) {
- glTranslatef(0.0, -dz, 0.0);
- GPU_select_load_id(MAN_SCALE_C);
- /* TODO: set glPointSize before drawing center point */
- glBegin(GL_POINTS);
- glVertex3f(0.0, 0.0, 0.0);
- glEnd();
- }
- }
-#endif
-
- /* restore */
- glLoadMatrixf(rv3d->viewmat);
-
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- glFrontFace(GL_CCW);
-}
-
-
-static void draw_cone(GLUquadricObj *qobj, float len, float width)
-{
- glTranslatef(0.0, 0.0, -0.5f * len);
- gluCylinder(qobj, width, 0.0, len, 8, 1);
- gluQuadricOrientation(qobj, GLU_INSIDE);
- gluDisk(qobj, 0.0, width, 8, 1);
- gluQuadricOrientation(qobj, GLU_OUTSIDE);
- glTranslatef(0.0, 0.0, 0.5f * len);
-}
-
-static void draw_cylinder(GLUquadricObj *qobj, float len, float width)
-{
-
- width *= 0.8f; // just for beauty
-
- glTranslatef(0.0, 0.0, -0.5f * len);
- gluCylinder(qobj, width, width, len, 8, 1);
- gluQuadricOrientation(qobj, GLU_INSIDE);
- gluDisk(qobj, 0.0, width, 8, 1);
- gluQuadricOrientation(qobj, GLU_OUTSIDE);
- glTranslatef(0.0, 0.0, len);
- gluDisk(qobj, 0.0, width, 8, 1);
- glTranslatef(0.0, 0.0, -0.5f * len);
-}
-
-
-static void draw_manipulator_translate(
- View3D *v3d, RegionView3D *rv3d, int drawflags, int combo, int colcode,
- const bool UNUSED(is_moving), const bool is_picksel)
-{
- GLUquadricObj *qobj;
- float cylen = 0.01f * (float)U.tw_handlesize;
- float cywid = 0.25f * cylen, dz, size;
- float unitmat[4][4];
- int shift = 0; // XXX
- int axis_order[3] = {0, 1, 2};
- int i;
-
- /* when called while moving in mixed mode, do not draw when... */
- if ((drawflags & MAN_TRANS_C) == 0) return;
-
- manipulator_axis_order(rv3d, axis_order);
-
- // XXX if (moving) glTranslate3fv(t->vec);
- glDisable(GL_DEPTH_TEST);
-
- /* center circle, do not add to selection when shift is pressed (planar constraint) */
- if (is_picksel && shift == 0) GPU_select_load_id(MAN_TRANS_C);
- else manipulator_setcolor(v3d, 'C', colcode, 255);
-
- glPushMatrix();
- size = screen_aligned(rv3d, rv3d->twmat);
- unit_m4(unitmat);
- drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f * size, unitmat);
- glPopMatrix();
-
- /* and now apply matrix, we move to local matrix drawing */
- glMultMatrixf(rv3d->twmat);
-
- /* axis */
- GPU_select_load_id(-1);
-
- // translate drawn as last, only axis when no combo with scale, or for ghosting
- if ((combo & V3D_MANIP_SCALE) == 0 || colcode == MAN_GHOST) {
- draw_manipulator_axes(v3d, rv3d, colcode,
- drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z,
- axis_order, is_picksel);
- }
-
-
- /* offset in combo mode, for rotate a bit more */
- if (combo & (V3D_MANIP_ROTATE)) dz = 1.0f + 2.0f * cylen;
- else if (combo & (V3D_MANIP_SCALE)) dz = 1.0f + 0.5f * cylen;
- else dz = 1.0f;
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
-
- for (i = 0; i < 3; i++) {
- switch (axis_order[i]) {
- case 0: /* Z Cone */
- if (drawflags & MAN_TRANS_Z) {
- glTranslatef(0.0, 0.0, dz);
- if (is_picksel) GPU_select_load_id(MAN_TRANS_Z);
- else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2]));
- draw_cone(qobj, cylen, cywid);
- glTranslatef(0.0, 0.0, -dz);
+ }
+ case MAN_AXIS_TRANS_C:
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_SCALE_C:
+ case MAN_AXIS_ROT_T:
+ WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH);
+ if (axis_idx == MAN_AXIS_ROT_T) {
+ WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_HOVER, true);
}
- break;
- case 1: /* X Cone */
- if (drawflags & MAN_TRANS_X) {
- glTranslatef(dz, 0.0, 0.0);
- if (is_picksel) GPU_select_load_id(MAN_TRANS_X);
- else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0]));
- glRotatef(90.0, 0.0, 1.0, 0.0);
- draw_cone(qobj, cylen, cywid);
- glRotatef(-90.0, 0.0, 1.0, 0.0);
- glTranslatef(-dz, 0.0, 0.0);
+ else if (axis_idx == MAN_AXIS_ROT_C) {
+ WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_VALUE, true);
}
- break;
- case 2: /* Y Cone */
- if (drawflags & MAN_TRANS_Y) {
- glTranslatef(0.0, dz, 0.0);
- if (is_picksel) GPU_select_load_id(MAN_TRANS_Y);
- else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1]));
- glRotatef(-90.0, 1.0, 0.0, 0.0);
- draw_cone(qobj, cylen, cywid);
- glRotatef(90.0, 1.0, 0.0, 0.0);
- glTranslatef(0.0, -dz, 0.0);
+ else {
+ WM_manipulator_set_scale(axis, 0.2f);
}
break;
}
- }
-
- gluDeleteQuadric(qobj);
- glLoadMatrixf(rv3d->viewmat);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
-
-}
-
-static void draw_manipulator_rotate_cyl(
- View3D *v3d, RegionView3D *rv3d, int drawflags, const int combo, const int colcode,
- const bool is_moving, const bool is_picksel)
-{
- GLUquadricObj *qobj;
- float size;
- float cylen = 0.01f * (float)U.tw_handlesize;
- float cywid = 0.25f * cylen;
- int axis_order[3] = {2, 0, 1};
- int i;
-
- /* skip drawing if all axes are locked */
- if (manipulator_rotate_is_visible(drawflags) == false) return;
-
- manipulator_axis_order(rv3d, axis_order);
-
- /* prepare for screen aligned draw */
- glPushMatrix();
- size = screen_aligned(rv3d, rv3d->twmat);
-
- glDisable(GL_DEPTH_TEST);
-
- qobj = gluNewQuadric();
-
- /* Screen aligned view rot circle */
- if (drawflags & MAN_ROT_V) {
- float unitmat[4][4];
-
- unit_m4(unitmat);
-
- if (is_picksel) GPU_select_load_id(MAN_ROT_V);
- UI_ThemeColor(TH_TRANSFORM);
- drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f * size, unitmat);
-
- if (is_moving) {
- float vec[3];
- vec[0] = 0; // XXX (float)(t->mouse.imval[0] - t->center2d[0]);
- vec[1] = 0; // XXX (float)(t->mouse.imval[1] - t->center2d[1]);
- vec[2] = 0.0f;
- normalize_v3_length(vec, 1.2f * size);
- glBegin(GL_LINES);
- glVertex3f(0.0, 0.0, 0.0);
- glVertex3fv(vec);
- glEnd();
- }
- }
- glPopMatrix();
-
- /* apply the transform delta */
- if (is_moving) {
- float matt[4][4];
- copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3]
- // XXX if (t->flag & T_USES_MANIPULATOR) {
- // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat);
- // XXX }
- glMultMatrixf(matt);
- }
- else {
- glMultMatrixf(rv3d->twmat);
- }
-
- glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW : GL_CCW);
-
- /* axis */
- if (is_picksel == false) {
-
- // only draw axis when combo didn't draw scale axes
- if ((combo & V3D_MANIP_SCALE) == 0) {
- draw_manipulator_axes(v3d, rv3d, colcode,
- drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z,
- axis_order, is_picksel);
- }
-
- /* only has to be set when not in picking */
- gluQuadricDrawStyle(qobj, GLU_FILL);
- }
-
- for (i = 0; i < 3; i++) {
- switch (axis_order[i]) {
- case 0: /* X cylinder */
- if (drawflags & MAN_ROT_X) {
- glTranslatef(1.0, 0.0, 0.0);
- if (is_picksel) GPU_select_load_id(MAN_ROT_X);
- glRotatef(90.0, 0.0, 1.0, 0.0);
- manipulator_setcolor(v3d, 'X', colcode, 255);
- draw_cylinder(qobj, cylen, cywid);
- glRotatef(-90.0, 0.0, 1.0, 0.0);
- glTranslatef(-1.0, 0.0, 0.0);
+ switch (axis_type) {
+ case MAN_AXES_TRANSLATE:
+ if (ot_store.translate == NULL) {
+ ot_store.translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
}
+ ptr = WM_manipulator_operator_set(axis, 0, ot_store.translate, NULL);
break;
- case 1: /* Y cylinder */
- if (drawflags & MAN_ROT_Y) {
- glTranslatef(0.0, 1.0, 0.0);
- if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
- glRotatef(-90.0, 1.0, 0.0, 0.0);
- manipulator_setcolor(v3d, 'Y', colcode, 255);
- draw_cylinder(qobj, cylen, cywid);
- glRotatef(90.0, 1.0, 0.0, 0.0);
- glTranslatef(0.0, -1.0, 0.0);
+ case MAN_AXES_ROTATE:
+ {
+ wmOperatorType *ot_rotate;
+ if (axis_idx == MAN_AXIS_ROT_T) {
+ if (ot_store.trackball == NULL) {
+ ot_store.trackball = WM_operatortype_find("TRANSFORM_OT_trackball", true);
+ }
+ ot_rotate = ot_store.trackball;
}
+ else {
+ if (ot_store.rotate == NULL) {
+ ot_store.rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true);
+ }
+ ot_rotate = ot_store.rotate;
+ }
+ ptr = WM_manipulator_operator_set(axis, 0, ot_rotate, NULL);
break;
- case 2: /* Z cylinder */
- if (drawflags & MAN_ROT_Z) {
- glTranslatef(0.0, 0.0, 1.0);
- if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
- manipulator_setcolor(v3d, 'Z', colcode, 255);
- draw_cylinder(qobj, cylen, cywid);
- glTranslatef(0.0, 0.0, -1.0);
+ }
+ case MAN_AXES_SCALE:
+ {
+ if (ot_store.resize == NULL) {
+ ot_store.resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
}
+ ptr = WM_manipulator_operator_set(axis, 0, ot_store.resize, NULL);
break;
+ }
}
- }
-
- /* restore */
-
- gluDeleteQuadric(qobj);
- glLoadMatrixf(rv3d->viewmat);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ {
+ PropertyRNA *prop;
+ if ((prop = RNA_struct_find_property(ptr, "constraint_axis"))) {
+ RNA_property_boolean_set_array(ptr, prop, constraint_axis);
+ }
+ }
+ RNA_boolean_set(ptr, "release_confirm", 1);
+ }
+ MAN_ITER_AXES_END;
}
-
-/* ********************************************* */
-
-/* main call, does calc centers & orientation too */
-static int drawflags = 0xFFFF; // only for the calls below, belongs in scene...?
-
-void BIF_draw_manipulator(const bContext *C)
+static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGroup *mgroup)
{
+ ManipulatorGroup *man = mgroup->customdata;
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
- int totsel;
+ struct TransformBounds tbounds;
- const bool is_picksel = false;
+ /* skip, we don't draw anything anyway */
+ if ((man->all_hidden = (calc_manipulator_stats(C, true, &tbounds) == 0)))
+ return;
- if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return;
+ manipulator_prepare_mat(C, v3d, rv3d, &tbounds);
- if ((v3d->twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE | V3D_MANIP_SCALE)) == 0) return;
+ /* *** set properties for axes *** */
+ MAN_ITER_AXES_BEGIN(axis, axis_idx)
{
- struct TransformBounds tbounds;
- v3d->twflag &= ~V3D_DRAW_MANIPULATOR;
-
- totsel = calc_manipulator_stats(C, &tbounds);
- if (totsel == 0) return;
-
- v3d->twflag |= V3D_DRAW_MANIPULATOR;
-
- /* now we can define center */
- switch (v3d->around) {
- case V3D_AROUND_CENTER_BOUNDS:
- case V3D_AROUND_ACTIVE:
+ const short axis_type = manipulator_get_axis_type(axis_idx);
+ const int aidx_norm = manipulator_orientation_axis(axis_idx, NULL);
+
+ WM_manipulator_set_matrix_location(axis, rv3d->twmat[3]);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_X:
+ case MAN_AXIS_TRANS_Y:
+ case MAN_AXIS_TRANS_Z:
+ case MAN_AXIS_SCALE_X:
+ case MAN_AXIS_SCALE_Y:
+ case MAN_AXIS_SCALE_Z:
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- Object *ob = OBACT;
+ float start_co[3] = {0.0f, 0.0f, 0.0f};
+ float len;
- if (((v3d->around == V3D_AROUND_ACTIVE) && (scene->obedit == NULL)) &&
- ((gpd == NULL) || !(gpd->flag & GP_DATA_STROKE_EDITMODE)) &&
- (ob && !(ob->mode & OB_MODE_POSE)))
- {
- copy_v3_v3(rv3d->twmat[3], ob->obmat[3]);
- }
- else {
- mid_v3_v3v3(rv3d->twmat[3], tbounds.min, tbounds.max);
- }
+ manipulator_line_range(v3d, axis_type, &start_co[2], &len);
+
+ WM_manipulator_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]);
+ RNA_float_set(axis->ptr, "length", len);
+ WM_manipulator_set_matrix_offset_location(axis, start_co);
+ WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true);
break;
}
- case V3D_AROUND_LOCAL_ORIGINS:
- case V3D_AROUND_CENTER_MEAN:
- copy_v3_v3(rv3d->twmat[3], tbounds.center);
+ case MAN_AXIS_ROT_X:
+ case MAN_AXIS_ROT_Y:
+ case MAN_AXIS_ROT_Z:
+ WM_manipulator_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]);
break;
- case V3D_AROUND_CURSOR:
- copy_v3_v3(rv3d->twmat[3], ED_view3d_cursor3d_get(scene, v3d));
+ case MAN_AXIS_TRANS_XY:
+ case MAN_AXIS_TRANS_YZ:
+ case MAN_AXIS_TRANS_ZX:
+ case MAN_AXIS_SCALE_XY:
+ case MAN_AXIS_SCALE_YZ:
+ case MAN_AXIS_SCALE_ZX:
+ {
+ const float *y_axis = rv3d->twmat[aidx_norm - 1 < 0 ? 2 : aidx_norm - 1];
+ const float *z_axis = rv3d->twmat[aidx_norm];
+ WM_manipulator_set_matrix_rotation_from_yz_axis(axis, y_axis, z_axis);
break;
+ }
}
-
- mul_mat3_m4_fl(rv3d->twmat, ED_view3d_pixel_size(rv3d, rv3d->twmat[3]) * U.tw_size);
}
+ MAN_ITER_AXES_END;
+}
+
+static void WIDGETGROUP_manipulator_message_subscribe(
+ const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ manipulator_xform_message_subscribe(mgroup, mbus, screen, sa, ar, TRANSFORM_WGT_manipulator);
+}
+
+static void WIDGETGROUP_manipulator_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ ManipulatorGroup *man = mgroup->customdata;
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = sa->spacedata.first;
+ RegionView3D *rv3d = ar->regiondata;
+ float idot[3];
/* when looking through a selected camera, the manipulator can be at the
* exact same position as the view, skip so we don't break selection */
- if (fabsf(mat4_to_scale(rv3d->twmat)) < 1e-7f)
+ if (man->all_hidden || fabsf(ED_view3d_pixel_size(rv3d, rv3d->twmat[3])) < 1e-6f) {
+ MAN_ITER_AXES_BEGIN(axis, axis_idx)
+ {
+ WM_manipulator_set_flag(axis, WM_MANIPULATOR_HIDDEN, true);
+ }
+ MAN_ITER_AXES_END;
return;
+ }
+ manipulator_get_idot(rv3d, idot);
- test_manipulator_axis(C);
- drawflags = rv3d->twdrawflag; /* set in calc_manipulator_stats */
-
- if (v3d->twflag & V3D_DRAW_MANIPULATOR) {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- glLineWidth(1.0f);
+ /* *** set properties for axes *** */
- if (v3d->twtype & V3D_MANIP_ROTATE) {
- if (G.debug_value == 3) {
- if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT))
- draw_manipulator_rotate_cyl(v3d, rv3d, drawflags, v3d->twtype, MAN_MOVECOL, true, is_picksel);
- else
- draw_manipulator_rotate_cyl(v3d, rv3d, drawflags, v3d->twtype, MAN_RGB, false, is_picksel);
- }
- else {
- draw_manipulator_rotate(v3d, rv3d, drawflags, v3d->twtype, false, is_picksel);
- }
- }
- if (v3d->twtype & V3D_MANIP_SCALE) {
- draw_manipulator_scale(v3d, rv3d, drawflags, v3d->twtype, MAN_RGB, false, is_picksel);
+ MAN_ITER_AXES_BEGIN(axis, axis_idx)
+ {
+ const short axis_type = manipulator_get_axis_type(axis_idx);
+ /* XXX maybe unset _HIDDEN flag on redraw? */
+ if (manipulator_is_axis_visible(v3d, rv3d, idot, axis_type, axis_idx)) {
+ WM_manipulator_set_flag(axis, WM_MANIPULATOR_HIDDEN, false);
}
- if (v3d->twtype & V3D_MANIP_TRANSLATE) {
- draw_manipulator_translate(v3d, rv3d, drawflags, v3d->twtype, MAN_RGB, false, is_picksel);
+ else {
+ WM_manipulator_set_flag(axis, WM_MANIPULATOR_HIDDEN, true);
+ continue;
}
- glDisable(GL_BLEND);
+ float color[4], color_hi[4];
+ manipulator_get_axis_color(axis_idx, idot, color, color_hi);
+ WM_manipulator_set_color(axis, color);
+ WM_manipulator_set_color_highlight(axis, color_hi);
+
+ switch (axis_idx) {
+ case MAN_AXIS_TRANS_C:
+ case MAN_AXIS_ROT_C:
+ case MAN_AXIS_SCALE_C:
+ case MAN_AXIS_ROT_T:
+ WM_manipulator_set_matrix_rotation_from_z_axis(axis, rv3d->viewinv[2]);
+ break;
+ }
}
+ MAN_ITER_AXES_END;
}
-static int manipulator_selectbuf(Scene *scene, ScrArea *sa, ARegion *ar, const int mval[2], float hotspot)
+static bool WIDGETGROUP_manipulator_poll(const struct bContext *C, struct wmManipulatorGroupType *UNUSED(wgt))
{
- View3D *v3d = sa->spacedata.first;
- RegionView3D *rv3d = ar->regiondata;
- rcti rect;
- GLuint buffer[64]; // max 4 items per select, so large enuf
- short hits;
- const bool is_picksel = true;
- const bool do_passes = GPU_select_query_check_active();
+ /* it's a given we only use this in 3D view */
+ const ScrArea *sa = CTX_wm_area(C);
+ const View3D *v3d = sa->spacedata.first;
- /* when looking through a selected camera, the manipulator can be at the
- * exact same position as the view, skip so we don't break selection */
- if (fabsf(mat4_to_scale(rv3d->twmat)) < 1e-7f)
- return 0;
+ if (((v3d->twflag & V3D_MANIPULATOR_DRAW) != 0) &&
+ ((v3d->twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE | V3D_MANIP_SCALE)) != 0))
+ {
+ /* Don't show when tools have a manipulator. */
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ if (workspace->tool.manipulator_group[0] == '\0') {
+ return true;
+ }
+ }
+ return false;
+}
- rect.xmin = mval[0] - hotspot;
- rect.xmax = mval[0] + hotspot;
- rect.ymin = mval[1] - hotspot;
- rect.ymax = mval[1] + hotspot;
+void TRANSFORM_WGT_manipulator(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Transform Manipulator";
+ wgt->idname = "TRANSFORM_WGT_manipulator";
- ED_view3d_draw_setup_view(NULL, scene, ar, v3d, NULL, NULL, &rect);
+ wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+ WM_MANIPULATORGROUPTYPE_3D);
- if (do_passes)
- GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
- else
- GPU_select_begin(buffer, 64, &rect, GPU_SELECT_ALL, 0);
+ wgt->poll = WIDGETGROUP_manipulator_poll;
+ wgt->setup = WIDGETGROUP_manipulator_setup;
+ wgt->refresh = WIDGETGROUP_manipulator_refresh;
+ wgt->message_subscribe = WIDGETGROUP_manipulator_message_subscribe;
+ wgt->draw_prepare = WIDGETGROUP_manipulator_draw_prepare;
+}
- /* do the drawing */
- if (v3d->twtype & V3D_MANIP_ROTATE) {
- if (G.debug_value == 3) draw_manipulator_rotate_cyl(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
- else draw_manipulator_rotate(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, false, is_picksel);
- }
- if (v3d->twtype & V3D_MANIP_SCALE)
- draw_manipulator_scale(v3d, rv3d, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
- if (v3d->twtype & V3D_MANIP_TRANSLATE)
- draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
+/** \} */
- hits = GPU_select_end();
- if (do_passes && (hits > 0)) {
- GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+/* -------------------------------------------------------------------- */
+/** \name Scale Cage Manipulator
+ * \{ */
- /* do the drawing */
- if (v3d->twtype & V3D_MANIP_ROTATE) {
- if (G.debug_value == 3) draw_manipulator_rotate_cyl(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
- else draw_manipulator_rotate(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, false, is_picksel);
- }
- if (v3d->twtype & V3D_MANIP_SCALE)
- draw_manipulator_scale(v3d, rv3d, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
- if (v3d->twtype & V3D_MANIP_TRANSLATE)
- draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
+struct XFormCageWidgetGroup {
+ wmManipulator *manipulator;
+};
- GPU_select_end();
+static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmManipulatorGroupType *wgt)
+{
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ if (!STREQ(wgt->idname, workspace->tool.manipulator_group)) {
+ WM_manipulator_group_type_unlink_delayed_ptr(wgt);
+ return false;
}
+ return true;
+}
- ED_view3d_draw_setup_view(NULL, scene, ar, v3d, NULL, NULL, NULL);
+static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ struct XFormCageWidgetGroup *xmgroup = MEM_mallocN(sizeof(struct XFormCageWidgetGroup), __func__);
+ const wmManipulatorType *wt_cage = WM_manipulatortype_find("MANIPULATOR_WT_cage_3d", true);
+ xmgroup->manipulator = WM_manipulator_new_ptr(wt_cage, mgroup, NULL);
+ wmManipulator *mpr = xmgroup->manipulator;
- if (hits == 1) return buffer[3];
- else if (hits > 1) {
- GLuint val, dep, mindep = 0, mindeprot = 0, minval = 0, minvalrot = 0;
- int a;
+ RNA_enum_set(mpr->ptr, "transform",
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE |
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE);
- /* we compare the hits in buffer, but value centers highest */
- /* we also store the rotation hits separate (because of arcs) and return hits on other widgets if there are */
+ mpr->color[0] = 1;
+ mpr->color_hi[0] =1;
- for (a = 0; a < hits; a++) {
- dep = buffer[4 * a + 1];
- val = buffer[4 * a + 3];
+ mgroup->customdata = xmgroup;
- if (val == MAN_TRANS_C) {
- return MAN_TRANS_C;
- }
- else if (val == MAN_SCALE_C) {
- return MAN_SCALE_C;
- }
- else {
- if (val & MAN_ROT_C) {
- if (minvalrot == 0 || dep < mindeprot) {
- mindeprot = dep;
- minvalrot = val;
- }
- }
- else {
- if (minval == 0 || dep < mindep) {
- mindep = dep;
- minval = val;
+ {
+ wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
+ PointerRNA *ptr;
+
+ /* assign operator */
+ PropertyRNA *prop_release_confirm = NULL;
+ PropertyRNA *prop_constraint_axis = NULL;
+
+ int i = ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
+ for (int x = 0; x < 3; x++) {
+ for (int y = 0; y < 3; y++) {
+ for (int z = 0; z < 3; z++) {
+ int constraint[3] = {x != 1, y != 1, z != 1};
+ ptr = WM_manipulator_operator_set(mpr, i, ot_resize, NULL);
+ if (prop_release_confirm == NULL) {
+ prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
+ prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
}
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint);
+ i++;
}
}
}
-
- if (minval)
- return minval;
- else
- return minvalrot;
}
- return 0;
}
-static const char *manipulator_get_operator_name(int man_val)
+static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmManipulatorGroup *mgroup)
{
- if (man_val & MAN_TRANS_C) {
- return "TRANSFORM_OT_translate";
- }
- else if (man_val == MAN_ROT_T) {
- return "TRANSFORM_OT_trackball";
- }
- else if (man_val & MAN_ROT_C) {
- return "TRANSFORM_OT_rotate";
- }
- else if (man_val & MAN_SCALE_C) {
- return "TRANSFORM_OT_resize";
- }
-
- return NULL;
-}
-
-/* return 0; nothing happened */
-int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
ARegion *ar = CTX_wm_region(C);
- int constraint_axis[3] = {0, 0, 0};
- int val;
- const bool use_planar = RNA_boolean_get(op->ptr, "use_planar_constraint");
-
- if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return 0;
- if (!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return 0;
-
- /* Force orientation */
- RNA_enum_set(op->ptr, "constraint_orientation", v3d->twmode);
-
- // find the hotspots first test narrow hotspot
- val = manipulator_selectbuf(scene, sa, ar, event->mval, 0.5f * (float)U.tw_hotspot);
- if (val) {
- wmOperatorType *ot;
- PointerRNA props_ptr;
- PropertyRNA *prop;
- const char *opname;
-
- // drawflags still global, for drawing call above
- drawflags = manipulator_selectbuf(scene, sa, ar, event->mval, 0.2f * (float)U.tw_hotspot);
- if (drawflags == 0) drawflags = val;
-
- /* Planar constraint doesn't make sense for rotation, give other keymaps a chance */
- if ((drawflags & MAN_ROT_C) && use_planar) {
- return 0;
- }
+ RegionView3D *rv3d = ar->regiondata;
- opname = manipulator_get_operator_name(drawflags);
- ot = WM_operatortype_find(opname, true);
- WM_operator_properties_create_ptr(&props_ptr, ot);
+ struct XFormCageWidgetGroup *xmgroup = mgroup->customdata;
+ wmManipulator *mpr = xmgroup->manipulator;
- if (drawflags & MAN_TRANS_C) {
- switch (drawflags) {
- case MAN_TRANS_C:
- break;
- case MAN_TRANS_X:
- if (use_planar) {
- constraint_axis[1] = 1;
- constraint_axis[2] = 1;
- }
- else
- constraint_axis[0] = 1;
- break;
- case MAN_TRANS_Y:
- if (use_planar) {
- constraint_axis[0] = 1;
- constraint_axis[2] = 1;
- }
- else
- constraint_axis[1] = 1;
- break;
- case MAN_TRANS_Z:
- if (use_planar) {
- constraint_axis[0] = 1;
- constraint_axis[1] = 1;
- }
- else
- constraint_axis[2] = 1;
- break;
- }
- RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis);
- }
- else if (drawflags & MAN_SCALE_C) {
- switch (drawflags) {
- case MAN_SCALE_X:
- if (use_planar) {
- constraint_axis[1] = 1;
- constraint_axis[2] = 1;
- }
- else
- constraint_axis[0] = 1;
- break;
- case MAN_SCALE_Y:
- if (use_planar) {
- constraint_axis[0] = 1;
- constraint_axis[2] = 1;
- }
- else
- constraint_axis[1] = 1;
- break;
- case MAN_SCALE_Z:
- if (use_planar) {
- constraint_axis[0] = 1;
- constraint_axis[1] = 1;
+ struct TransformBounds tbounds;
+
+ if ((calc_manipulator_stats(C, false, &tbounds) == 0) ||
+ equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max))
+ {
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
+ }
+ else {
+ manipulator_prepare_mat(C, v3d, rv3d, &tbounds);
+
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ float dims[3];
+ sub_v3_v3v3(dims, rv3d->tw_axis_max, rv3d->tw_axis_min);
+ RNA_float_set_array(mpr->ptr, "dimensions", dims);
+ mul_v3_fl(dims, 0.5f);
+
+ copy_m4_m3(mpr->matrix_offset, rv3d->tw_axis_matrix);
+ mid_v3_v3v3(mpr->matrix_offset[3], rv3d->tw_axis_max, rv3d->tw_axis_min);
+ mul_m3_v3(rv3d->tw_axis_matrix, mpr->matrix_offset[3]);
+
+ PropertyRNA *prop_center_override = NULL;
+ float center[3];
+ float center_global[3];
+ int i = ED_MANIPULATOR_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
+ for (int x = 0; x < 3; x++) {
+ center[0] = (float)(1 - x) * dims[0];
+ for (int y = 0; y < 3; y++) {
+ center[1] = (float)(1 - y) * dims[1];
+ for (int z = 0; z < 3; z++) {
+ center[2] = (float)(1 - z) * dims[2];
+ struct wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, i);
+ if (prop_center_override == NULL) {
+ prop_center_override = RNA_struct_find_property(&mpop->ptr, "center_override");
}
- else
- constraint_axis[2] = 1;
- break;
- }
- RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis);
- }
- else if (drawflags == MAN_ROT_T) {
- /* pass */
- }
- else if (drawflags & MAN_ROT_C) {
- switch (drawflags) {
- case MAN_ROT_X:
- constraint_axis[0] = 1;
- break;
- case MAN_ROT_Y:
- constraint_axis[1] = 1;
- break;
- case MAN_ROT_Z:
- constraint_axis[2] = 1;
- break;
+ mul_v3_m4v3(center_global, mpr->matrix_offset, center);
+ RNA_property_float_set_array(&mpop->ptr, prop_center_override, center_global);
+ i++;
+ }
}
- RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis);
}
+ }
+}
- /* pass operator properties on to transform operators */
- prop = RNA_struct_find_property(op->ptr, "use_accurate");
- if (RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(&props_ptr, prop, RNA_property_boolean_get(op->ptr, prop));
- }
- prop = RNA_struct_find_property(op->ptr, "release_confirm");
- if (RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(&props_ptr, prop, RNA_property_boolean_get(op->ptr, prop));
- }
- prop = RNA_struct_find_property(op->ptr, "constraint_orientation");
- if (RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(&props_ptr, prop, RNA_property_enum_get(op->ptr, prop));
- }
+static void WIDGETGROUP_xform_cage_message_subscribe(
+ const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ manipulator_xform_message_subscribe(mgroup, mbus, screen, sa, ar, VIEW3D_WGT_xform_cage);
+}
+
+static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ struct XFormCageWidgetGroup *xmgroup = mgroup->customdata;
+ wmManipulator *mpr = xmgroup->manipulator;
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
- WM_operator_properties_free(&props_ptr);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ if (ob && ob->mode & OB_MODE_EDIT) {
+ copy_m4_m4(mpr->matrix_space, ob->obmat);
+ }
+ else {
+ unit_m4(mpr->matrix_space);
}
- /* after transform, restore drawflags */
- drawflags = 0xFFFF;
+}
+
+void VIEW3D_WGT_xform_cage(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "Transform Cage";
+ wgt->idname = "VIEW3D_WGT_xform_cage";
+
+ wgt->flag |= WM_MANIPULATORGROUPTYPE_3D;
+
+ wgt->mmap_params.spaceid = SPACE_VIEW3D;
+ wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
- return val;
+ wgt->poll = WIDGETGROUP_xform_cage_poll;
+ wgt->setup = WIDGETGROUP_xform_cage_setup;
+ wgt->refresh = WIDGETGROUP_xform_cage_refresh;
+ wgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe;
+ wgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare;
}
+/** \} */
diff --git a/source/blender/editors/transform/transform_manipulator2d.c b/source/blender/editors/transform/transform_manipulator2d.c
new file mode 100644
index 00000000000..6e2d0d8c5c0
--- /dev/null
+++ b/source/blender/editors/transform/transform_manipulator2d.c
@@ -0,0 +1,383 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/transform/transform_manipulator2d.c
+ * \ingroup edtransform
+ *
+ * \name 2D Transform Manipulator
+ *
+ * Used for UV/Image Editor
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_context.h"
+#include "BKE_editmesh.h"
+
+#include "RNA_access.h"
+
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm.h" /* XXX */
+
+#include "ED_image.h"
+#include "ED_screen.h"
+#include "ED_uvedit.h"
+#include "ED_manipulator_library.h"
+
+#include "transform.h" /* own include */
+
+/* axes as index */
+enum {
+ MAN2D_AXIS_TRANS_X = 0,
+ MAN2D_AXIS_TRANS_Y,
+
+ MAN2D_AXIS_LAST,
+};
+
+typedef struct ManipulatorGroup2D {
+ wmManipulator *translate_x,
+ *translate_y;
+
+ wmManipulator *cage;
+
+ /* Current origin in view space, used to update widget origin for possible view changes */
+ float origin[2];
+ float min[2];
+ float max[2];
+
+} ManipulatorGroup2D;
+
+
+/* **************** Utilities **************** */
+
+/* loop over axes */
+#define MAN2D_ITER_AXES_BEGIN(axis, axis_idx) \
+ { \
+ wmManipulator *axis; \
+ int axis_idx; \
+ for (axis_idx = 0; axis_idx < MAN2D_AXIS_LAST; axis_idx++) { \
+ axis = manipulator2d_get_axis_from_index(man, axis_idx);
+
+#define MAN2D_ITER_AXES_END \
+ } \
+ } ((void)0)
+
+static wmManipulator *manipulator2d_get_axis_from_index(const ManipulatorGroup2D *man, const short axis_idx)
+{
+ BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN2D_AXIS_TRANS_X, (float)MAN2D_AXIS_TRANS_Y));
+
+ switch (axis_idx) {
+ case MAN2D_AXIS_TRANS_X:
+ return man->translate_x;
+ case MAN2D_AXIS_TRANS_Y:
+ return man->translate_y;
+ }
+
+ return NULL;
+}
+
+static void manipulator2d_get_axis_color(const int axis_idx, float *r_col, float *r_col_hi)
+{
+ const float alpha = 0.6f;
+ const float alpha_hi = 1.0f;
+ int col_id;
+
+ switch (axis_idx) {
+ case MAN2D_AXIS_TRANS_X:
+ col_id = TH_AXIS_X;
+ break;
+ case MAN2D_AXIS_TRANS_Y:
+ col_id = TH_AXIS_Y;
+ break;
+ }
+
+ UI_GetThemeColor4fv(col_id, r_col);
+
+ copy_v4_v4(r_col_hi, r_col);
+ r_col[3] *= alpha;
+ r_col_hi[3] *= alpha_hi;
+}
+
+static ManipulatorGroup2D *manipulatorgroup2d_init(wmManipulatorGroup *mgroup)
+{
+ const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_2d", true);
+ const wmManipulatorType *wt_cage = WM_manipulatortype_find("MANIPULATOR_WT_cage_2d", true);
+
+ ManipulatorGroup2D *man = MEM_callocN(sizeof(ManipulatorGroup2D), __func__);
+
+ man->translate_x = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
+ man->translate_y = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
+ man->cage = WM_manipulator_new_ptr(wt_cage, mgroup, NULL);
+
+ RNA_enum_set(man->cage->ptr, "transform",
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE |
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE |
+ ED_MANIPULATOR_CAGE2D_XFORM_FLAG_ROTATE);
+
+ return man;
+}
+
+/**
+ * Calculates origin in view space, use with #manipulator2d_origin_to_region.
+ */
+static void manipulator2d_calc_bounds(const bContext *C, float *r_center, float *r_min, float *r_max)
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = ED_space_image(sima);
+
+ float min_buf[2], max_buf[2];
+ if (r_min == NULL) {
+ r_min = min_buf;
+ }
+ if (r_max == NULL) {
+ r_max = max_buf;
+ }
+
+ if (!ED_uvedit_minmax(CTX_data_scene(C), ima, CTX_data_edit_object(C), r_min, r_max)) {
+ zero_v2(r_min);
+ zero_v2(r_max);
+ }
+ mid_v2_v2v2(r_center, r_min, r_max);
+}
+
+/**
+ * Convert origin (or any other point) from view to region space.
+ */
+BLI_INLINE void manipulator2d_origin_to_region(ARegion *ar, float *r_origin)
+{
+ UI_view2d_view_to_region_fl(&ar->v2d, r_origin[0], r_origin[1], &r_origin[0], &r_origin[1]);
+}
+
+/**
+ * Custom handler for manipulator widgets
+ */
+static int manipulator2d_modal(
+ bContext *C, wmManipulator *widget, const wmEvent *UNUSED(event),
+ eWM_ManipulatorTweak UNUSED(tweak_flag))
+{
+ ARegion *ar = CTX_wm_region(C);
+ float origin[3];
+
+ manipulator2d_calc_bounds(C, origin, NULL, NULL);
+ manipulator2d_origin_to_region(ar, origin);
+ WM_manipulator_set_matrix_location(widget, origin);
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void ED_widgetgroup_manipulator2d_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ wmOperatorType *ot_translate = WM_operatortype_find("TRANSFORM_OT_translate", true);
+ ManipulatorGroup2D *man = manipulatorgroup2d_init(mgroup);
+ mgroup->customdata = man;
+
+ MAN2D_ITER_AXES_BEGIN(axis, axis_idx)
+ {
+ const float offset[3] = {0.0f, 0.2f};
+
+ float color[4], color_hi[4];
+ manipulator2d_get_axis_color(axis_idx, color, color_hi);
+
+ /* custom handler! */
+ WM_manipulator_set_fn_custom_modal(axis, manipulator2d_modal);
+ /* set up widget data */
+ RNA_float_set(axis->ptr, "angle", -M_PI_2 * axis_idx);
+ RNA_float_set(axis->ptr, "length", 0.8f);
+ WM_manipulator_set_matrix_offset_location(axis, offset);
+ WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH);
+ WM_manipulator_set_scale(axis, U.manipulator_size);
+ WM_manipulator_set_color(axis, color);
+ WM_manipulator_set_color_highlight(axis, color_hi);
+
+ /* assign operator */
+ PointerRNA *ptr = WM_manipulator_operator_set(axis, 0, ot_translate, NULL);
+ int constraint[3] = {0};
+ constraint[(axis_idx + 1) % 2] = 1;
+ if (RNA_struct_find_property(ptr, "constraint_axis"))
+ RNA_boolean_set_array(ptr, "constraint_axis", constraint);
+ RNA_boolean_set(ptr, "release_confirm", 1);
+ }
+ MAN2D_ITER_AXES_END;
+
+ {
+ wmOperatorType *ot_resize = WM_operatortype_find("TRANSFORM_OT_resize", true);
+ wmOperatorType *ot_rotate = WM_operatortype_find("TRANSFORM_OT_rotate", true);
+ PointerRNA *ptr;
+
+ /* assign operator */
+ ptr = WM_manipulator_operator_set(man->cage, 0, ot_translate, NULL);
+ RNA_boolean_set(ptr, "release_confirm", 1);
+
+ int constraint_x[3] = {1, 0, 0};
+ int constraint_y[3] = {0, 1, 0};
+
+ ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X, ot_resize, NULL);
+ PropertyRNA *prop_release_confirm = RNA_struct_find_property(ptr, "release_confirm");
+ PropertyRNA *prop_constraint_axis = RNA_struct_find_property(ptr, "constraint_axis");
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X, ot_resize, NULL);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_x);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y, ot_resize, NULL);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y, ot_resize, NULL);
+ RNA_property_boolean_set_array(ptr, prop_constraint_axis, constraint_y);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+
+ ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y, ot_resize, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ ptr = WM_manipulator_operator_set(man->cage, ED_MANIPULATOR_CAGE2D_PART_ROTATE, ot_rotate, NULL);
+ RNA_property_boolean_set(ptr, prop_release_confirm, true);
+ }
+}
+
+void ED_widgetgroup_manipulator2d_refresh(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ ManipulatorGroup2D *man = mgroup->customdata;
+ float origin[3];
+ manipulator2d_calc_bounds(C, origin, man->min, man->max);
+ copy_v2_v2(man->origin, origin);
+ bool show_cage = !equals_v2v2(man->min, man->max);
+
+ if (show_cage) {
+ man->cage->flag &= ~WM_MANIPULATOR_HIDDEN;
+ man->translate_x->flag |= WM_MANIPULATOR_HIDDEN;
+ man->translate_y->flag |= WM_MANIPULATOR_HIDDEN;
+ }
+ else {
+ man->cage->flag |= WM_MANIPULATOR_HIDDEN;
+ man->translate_x->flag &= ~WM_MANIPULATOR_HIDDEN;
+ man->translate_y->flag &= ~WM_MANIPULATOR_HIDDEN;
+ }
+
+ if (show_cage) {
+ wmManipulatorOpElem *mpop;
+ float mid[2];
+ const float *min = man->min;
+ const float *max = man->max;
+ mid_v2_v2v2(mid, min, max);
+
+ mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X);
+ PropertyRNA *prop_center_override = RNA_struct_find_property(&mpop->ptr, "center_override");
+ RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){max[0], mid[1], 0.0f});
+ mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X);
+ RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){min[0], mid[1], 0.0f});
+ mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_Y);
+ RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){mid[0], max[1], 0.0f});
+ mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_Y);
+ RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){mid[0], min[1], 0.0f});
+
+ mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MIN_Y);
+ RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){max[0], max[1], 0.0f});
+ mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MIN_X_MAX_Y);
+ RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){max[0], min[1], 0.0f});
+ mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MIN_Y);
+ RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){min[0], max[1], 0.0f});
+ mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_SCALE_MAX_X_MAX_Y);
+ RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){min[0], min[1], 0.0f});
+
+ mpop = WM_manipulator_operator_get(man->cage, ED_MANIPULATOR_CAGE2D_PART_ROTATE);
+ RNA_property_float_set_array(&mpop->ptr, prop_center_override, (float[3]){mid[0], mid[1], 0.0f});
+ }
+}
+
+void ED_widgetgroup_manipulator2d_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ ARegion *ar = CTX_wm_region(C);
+ ManipulatorGroup2D *man = mgroup->customdata;
+ float origin[3] = {UNPACK2(man->origin), 0.0f};
+ float origin_aa[3] = {UNPACK2(man->origin), 0.0f};
+
+ manipulator2d_origin_to_region(ar, origin);
+
+ MAN2D_ITER_AXES_BEGIN(axis, axis_idx)
+ {
+ WM_manipulator_set_matrix_location(axis, origin);
+ }
+ MAN2D_ITER_AXES_END;
+
+ UI_view2d_view_to_region_m4(&ar->v2d, man->cage->matrix_space);
+ WM_manipulator_set_matrix_offset_location(man->cage, origin_aa);
+ man->cage->matrix_offset[0][0] = (man->max[0] - man->min[0]);
+ man->cage->matrix_offset[1][1] = (man->max[1] - man->min[1]);
+}
+
+/* TODO (Julian)
+ * - Called on every redraw, better to do a more simple poll and check for selection in _refresh
+ * - UV editing only, could be expanded for other things.
+ */
+bool ED_widgetgroup_manipulator2d_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Object *obedit = CTX_data_edit_object(C);
+
+ if (ED_space_image_show_uvedit(sima, obedit)) {
+ Image *ima = ED_space_image(sima);
+ Scene *scene = CTX_data_scene(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ /* check if there's a selected poly */
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, ima, efa))
+ continue;
+
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 46bd83b5d35..ab0e24671eb 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -160,11 +160,12 @@ const EnumPropertyItem rna_enum_transform_mode_types[] =
static int select_orientation_exec(bContext *C, wmOperator *op)
{
+ View3D *v3d = CTX_wm_view3d(C);
int orientation = RNA_enum_get(op->ptr, "orientation");
- BIF_selectTransformOrientationValue(C, orientation);
+ BIF_selectTransformOrientationValue(v3d, orientation);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
return OPERATOR_FINISHED;
}
@@ -206,10 +207,9 @@ static void TRANSFORM_OT_select_orientation(struct wmOperatorType *ot)
static int delete_orientation_exec(bContext *C, wmOperator *UNUSED(op))
{
View3D *v3d = CTX_wm_view3d(C);
- int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
- BIF_removeTransformOrientationIndex(C, selected_index);
-
+ BIF_removeTransformOrientationIndex(C, v3d->custom_orientation_index);
+
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
WM_event_add_notifier(C, NC_SCENE | NA_EDITED, CTX_data_scene(C));
@@ -223,18 +223,12 @@ static int delete_orientation_invoke(bContext *C, wmOperator *op, const wmEvent
static int delete_orientation_poll(bContext *C)
{
- int selected_index = -1;
View3D *v3d = CTX_wm_view3d(C);
-
+
if (ED_operator_areaactive(C) == 0)
return 0;
-
-
- if (v3d) {
- selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
- }
-
- return selected_index >= 0;
+
+ return (v3d->twmode >= V3D_MANIP_CUSTOM) && (v3d->custom_orientation_index != -1);
}
static void TRANSFORM_OT_delete_orientation(struct wmOperatorType *ot)
@@ -289,6 +283,9 @@ static void TRANSFORM_OT_create_orientation(struct wmOperatorType *ot)
RNA_def_string(ot->srna, "name", NULL, MAX_NAME, "Name", "Name of the new custom orientation");
RNA_def_boolean(ot->srna, "use_view", false, "Use View",
"Use the current view instead of the active object to create the new orientation");
+
+ WM_operatortype_props_advanced_begin(ot);
+
RNA_def_boolean(ot->srna, "use", false, "Use after creation", "Select orientation after its creation");
RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite previous",
"Overwrite previously created orientation with same name");
@@ -599,6 +596,8 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
RNA_def_float_vector_xyz(ot->srna, "value", 3, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS | P_GPENCIL_EDIT);
}
@@ -619,6 +618,8 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(
ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_GPENCIL_EDIT | P_CENTER);
}
@@ -650,6 +651,8 @@ static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "value", 3, VecOne, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_OPTIONS | P_NO_TEXSPACE);
}
@@ -671,6 +674,8 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
/* Maybe we could use float_vector_xyz here too? */
RNA_def_float_rotation(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
@@ -691,6 +696,8 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(
ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
@@ -715,6 +722,8 @@ static void TRANSFORM_OT_tilt(struct wmOperatorType *ot)
RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
}
@@ -735,6 +744,8 @@ static void TRANSFORM_OT_bend(struct wmOperatorType *ot)
RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
@@ -755,6 +766,8 @@ static void TRANSFORM_OT_shear(struct wmOperatorType *ot)
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Offset", "", -FLT_MAX, FLT_MAX);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
// XXX Shear axis?
}
@@ -776,6 +789,8 @@ static void TRANSFORM_OT_push_pull(struct wmOperatorType *ot)
RNA_def_float(ot->srna, "value", 0, -FLT_MAX, FLT_MAX, "Distance", "", -FLT_MAX, FLT_MAX);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_CENTER);
}
@@ -798,6 +813,8 @@ static void TRANSFORM_OT_shrink_fatten(struct wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_even_offset", true, "Offset Even", "Scale the offset to give more even thickness");
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
}
@@ -819,6 +836,8 @@ static void TRANSFORM_OT_tosphere(struct wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
@@ -863,6 +882,9 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
RNA_def_boolean(ot->srna, "use_even", false, "Even",
"Make the edge loop match the shape of the adjacent edge loop");
+
+ WM_operatortype_props_advanced_begin(ot);
+
RNA_def_boolean(ot->srna, "flipped", false, "Flipped",
"When Even mode is active, flips between the two adjacent edge loops");
RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp",
@@ -889,6 +911,9 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
RNA_def_boolean(ot->srna, "use_even", false, "Even",
"Make the edge loop match the shape of the adjacent edge loop");
+
+ WM_operatortype_props_advanced_begin(ot);
+
RNA_def_boolean(ot->srna, "flipped", false, "Flipped",
"When Even mode is active, flips between the two adjacent edge loops");
RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp",
@@ -914,6 +939,8 @@ static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_SNAP);
}
@@ -955,6 +982,8 @@ static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_SNAP);
}
@@ -975,6 +1004,8 @@ static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot)
RNA_def_float_vector_xyz(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(ot, P_SNAP);
}
@@ -1000,6 +1031,8 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "value", 4, NULL, -FLT_MAX, FLT_MAX, "Values", "", -FLT_MAX, FLT_MAX);
+ WM_operatortype_props_advanced_begin(ot);
+
Transform_Properties(
ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
@@ -1066,6 +1099,8 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_element");
+ /* Will fall-through to texture-space transform. */
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_transform_axis_target", TKEY, KM_PRESS, KM_SHIFT, 0);
kmi = WM_keymap_add_item(keymap, OP_TRANSLATION, TKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "texture_space", true);
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 54959304d72..63cd5291193 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -38,6 +38,7 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
@@ -52,6 +53,7 @@
#include "BKE_report.h"
#include "BKE_main.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
#include "BLT_translation.h"
@@ -63,14 +65,16 @@
void BIF_clearTransformOrientation(bContext *C)
{
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ ListBase *transform_orientations = BKE_workspace_transform_orientations_get(workspace);
View3D *v3d = CTX_wm_view3d(C);
- ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
- BLI_freelistN(transform_spaces);
+ BLI_freelistN(transform_orientations);
// Need to loop over all view3d
- if (v3d && v3d->twmode >= V3D_MANIP_CUSTOM) {
- v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
+ if (v3d && v3d->twmode == V3D_MANIP_CUSTOM) {
+ v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
+ v3d->custom_orientation_index = -1;
}
}
@@ -318,23 +322,24 @@ void BIF_createTransformOrientation(bContext *C, ReportList *reports,
TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3],
const char *name, const bool overwrite)
{
- ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
TransformOrientation *ts = NULL;
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ ListBase *transform_orientations = BKE_workspace_transform_orientations_get(workspace);
char name_unique[sizeof(ts->name)];
if (overwrite) {
- ts = findOrientationName(transform_spaces, name);
+ ts = findOrientationName(transform_orientations, name);
}
else {
BLI_strncpy(name_unique, name, sizeof(name_unique));
- uniqueOrientationName(transform_spaces, name_unique);
+ uniqueOrientationName(transform_orientations, name_unique);
name = name_unique;
}
/* if not, create a new one */
if (ts == NULL) {
ts = MEM_callocN(sizeof(TransformOrientation), "UserTransSpace from matrix");
- BLI_addtail(transform_spaces, ts);
+ BLI_addtail(transform_orientations, ts);
BLI_strncpy(ts->name, name, sizeof(ts->name));
}
@@ -346,70 +351,55 @@ TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3],
void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target)
{
- Scene *scene = CTX_data_scene(C);
- ListBase *transform_spaces = &scene->transform_spaces;
- const int i = BLI_findindex(transform_spaces, target);
-
- if (i != -1) {
- Main *bmain = CTX_data_main(C);
- BKE_screen_view3d_main_twmode_remove(&bmain->screen, scene, i);
- BLI_freelinkN(transform_spaces, target);
- }
+ BKE_workspace_transform_orientation_remove(CTX_wm_workspace(C), target);
}
void BIF_removeTransformOrientationIndex(bContext *C, int index)
{
- ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
- TransformOrientation *ts = BLI_findlink(transform_spaces, index);
-
- if (ts) {
- BIF_removeTransformOrientation(C, ts);
- }
+ TransformOrientation *target = BKE_workspace_transform_orientation_find(CTX_wm_workspace(C), index);
+ BIF_removeTransformOrientation(C, target);
}
void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target)
{
- ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
- const int i = BLI_findindex(transform_spaces, target);
+ int index = BKE_workspace_transform_orientation_get_index(CTX_wm_workspace(C), target);
+ View3D *v3d = CTX_wm_view3d(C);
- if (i != -1) {
- View3D *v3d = CTX_wm_view3d(C);
- v3d->twmode = V3D_MANIP_CUSTOM + i;
- }
+ BLI_assert(index != -1);
+
+ v3d->twmode = V3D_MANIP_CUSTOM;
+ v3d->custom_orientation_index = index;
}
-void BIF_selectTransformOrientationValue(bContext *C, int orientation)
+/**
+ * Activate a transform orientation in a 3D view based on an enum value.
+ *
+ * \param orientation: If this is #V3D_MANIP_CUSTOM or greater, the custom transform orientation
+ * with index \a orientation - #V3D_MANIP_CUSTOM gets activated.
+ */
+void BIF_selectTransformOrientationValue(View3D *v3d, int orientation)
{
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d) /* currently using generic poll */
- v3d->twmode = orientation;
+ const bool is_custom = orientation >= V3D_MANIP_CUSTOM;
+
+ v3d->twmode = is_custom ? V3D_MANIP_CUSTOM : orientation;
+ v3d->custom_orientation_index = is_custom ? (orientation - V3D_MANIP_CUSTOM) : -1;
}
int BIF_countTransformOrientation(const bContext *C)
{
- ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
- return BLI_listbase_count(transform_spaces);
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ ListBase *transform_orientations = BKE_workspace_transform_orientations_get(workspace);
+ return BLI_listbase_count(transform_orientations);
}
-bool applyTransformOrientation(const bContext *C, float mat[3][3], char *r_name, int index)
+bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name)
{
- ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
- TransformOrientation *ts = BLI_findlink(transform_spaces, index);
-
- BLI_assert(index >= 0);
-
- if (ts) {
- if (r_name) {
- BLI_strncpy(r_name, ts->name, MAX_NAME);
- }
-
- copy_m3_m3(mat, ts->mat);
- return true;
- }
- else {
- /* invalid index, can happen sometimes */
- return false;
+ if (r_name) {
+ BLI_strncpy(r_name, ts->name, MAX_NAME);
}
+ copy_m3_m3(r_mat, ts->mat);
+
+ return true;
}
static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it)
@@ -492,8 +482,10 @@ void initTransformOrientation(bContext *C, TransInfo *t)
unit_m3(t->spacemtx);
}
break;
- default: /* V3D_MANIP_CUSTOM */
- if (applyTransformOrientation(C, t->spacemtx, t->spacename, t->current_orientation - V3D_MANIP_CUSTOM)) {
+ case V3D_MANIP_CUSTOM:
+ BLI_strncpy(t->spacename, t->custom_orientation->name, sizeof(t->spacename));
+
+ if (applyTransformOrientation(t->custom_orientation, t->spacemtx, t->spacename)) {
/* pass */
}
else {
@@ -586,10 +578,10 @@ static unsigned int bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const
int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3], const short around)
{
- Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
Base *base;
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
int result = ORIENTATION_NONE;
const bool activeOnly = (around == V3D_AROUND_ACTIVE);
@@ -1052,16 +1044,16 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
}
else {
/* we need the one selected object, if its not active */
- View3D *v3d = CTX_wm_view3d(C);
- ob = OBACT;
- if (ob && (ob->flag & SELECT)) {
+ base = BASACT(view_layer);
+ ob = OBACT(view_layer);
+ 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 = view_layer->object_bases.first; base; base = base->next) {
+ if (TESTBASELIB(base)) {
ob = base->object;
break;
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 5750224de3d..30aad46843d 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 int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_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(GWN_PRIM_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);
}
@@ -200,35 +206,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
else if (t->spacetype == SPACE_IMAGE) {
if (validSnap(t)) {
/* This will not draw, and Im nor sure why - campbell */
-#if 0
- float xuser_asp, yuser_asp;
- int wi, hi;
- float w, h;
-
- calc_image_view(G.sima, 'f'); // float
- myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
- glLoadIdentity();
-
- ED_space_image_get_aspect(t->sa->spacedata.first, &xuser_aspx, &yuser_asp);
- ED_space_image_width(t->sa->spacedata.first, &wi, &hi);
- w = (((float)wi) / IMG_SIZE_FALLBACK) * G.sima->zoom * xuser_asp;
- h = (((float)hi) / IMG_SIZE_FALLBACK) * G.sima->zoom * yuser_asp;
-
- cpack(0xFFFFFF);
- glTranslate2fv(t->tsnap.snapPoint);
-
- //glRectf(0, 0, 1, 1);
-
- setlinestyle(0);
- cpack(0x0);
- fdrawline(-0.020 / w, 0, -0.1 / w, 0);
- fdrawline(0.1 / w, 0, 0.020 / w, 0);
- fdrawline(0, -0.020 / h, 0, -0.1 / h);
- fdrawline(0, 0.1 / h, 0, 0.020 / h);
-
- glTranslatef(-t->tsnap.snapPoint[0], -t->tsnap.snapPoint[1], 0.0f);
- setlinestyle(0);
-#endif
+ /* TODO: see 2.7x for non-working code */
}
}
else if (t->spacetype == SPACE_NODE) {
@@ -241,23 +219,29 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
glEnable(GL_BLEND);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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);
}
}
@@ -516,8 +500,8 @@ static void initSnappingMode(TransInfo *t)
{
ToolSettings *ts = t->settings;
Object *obedit = t->obedit;
- Scene *scene = t->scene;
- Base *base_act = scene->basact;
+ ViewLayer *view_layer = t->view_layer;
+ Base *base_act = view_layer->basact;
if (t->spacetype == SPACE_NODE) {
/* force project off when not supported */
@@ -598,7 +582,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, 0,
+ G.main, t->scene, t->view_layer, t->engine_type, 0,
t->ar, t->view);
ED_transform_snap_object_context_set_editmesh_callbacks(
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 63bdf3ac010..ce8de2ef4d3 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -51,6 +51,9 @@
#include "BKE_editmesh.h"
#include "BKE_main.h"
#include "BKE_tracking.h"
+#include "BKE_context.h"
+
+#include "DEG_depsgraph.h"
#include "ED_transform.h"
#include "ED_transform_snap_object_context.h"
@@ -101,6 +104,8 @@ typedef struct SnapObjectData_EditMesh {
struct SnapObjectContext {
Main *bmain;
Scene *scene;
+ EvaluationContext eval_ctx;
+
int flag;
/* Optional: when performing screen-space projection.
@@ -155,18 +160,17 @@ static void iter_snap_objects(
IterSnapObjsCallback sob_callback,
void *data)
{
- Base *base_act = sctx->scene->basact;
- for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) {
- if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) &&
- (base->flag & BA_SNAP_FIX_DEPS_FIASCO) == 0 &&
- !((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL))) ||
+ Base *base_act = sctx->eval_ctx.view_layer->basact;
+ for (Base *base = sctx->eval_ctx.view_layer->object_bases.first; base != NULL; base = base->next) {
+ if ((BASE_VISIBLE(base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 &&
+ !((snap_select == SNAP_NOT_SELECTED && ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) ||
(snap_select == SNAP_NOT_ACTIVE && base == base_act)))
{
bool use_obedit;
Object *obj = base->object;
if (obj->transflag & OB_DUPLI) {
DupliObject *dupli_ob;
- ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, obj);
+ ListBase *lb = object_duplilist(&sctx->eval_ctx, sctx->scene, obj);
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
use_obedit = obedit && dupli_ob->ob->data == obedit->data;
sob_callback(sctx, use_obedit, use_obedit ? obedit : dupli_ob->ob, dupli_ob->mat, data);
@@ -725,10 +729,10 @@ static bool raycastObj(
DerivedMesh *dm;
em = BKE_editmesh_from_object(ob);
if (em) {
- editbmesh_get_derived_cage_and_final(sctx->scene, ob, em, CD_MASK_BAREMESH, &dm);
+ editbmesh_get_derived_cage_and_final(&sctx->eval_ctx, sctx->scene, ob, em, CD_MASK_BAREMESH, &dm);
}
else {
- dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH);
+ dm = mesh_get_derived_final(&sctx->eval_ctx, sctx->scene, ob, CD_MASK_BAREMESH);
}
retval = raycastDerivedMesh(
sctx,
@@ -1938,10 +1942,10 @@ static bool snapObject(
DerivedMesh *dm;
em = BKE_editmesh_from_object(ob);
if (em) {
- editbmesh_get_derived_cage_and_final(sctx->scene, ob, em, CD_MASK_BAREMESH, &dm);
+ editbmesh_get_derived_cage_and_final(&sctx->eval_ctx, sctx->scene, ob, em, CD_MASK_BAREMESH, &dm);
}
else {
- dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH);
+ dm = mesh_get_derived_final(&sctx->eval_ctx, sctx->scene, ob, CD_MASK_BAREMESH);
}
retval = snapDerivedMesh(
sctx, snapdata, ob, dm, obmat,
@@ -2083,7 +2087,7 @@ static bool snapObjectsRay(
* \{ */
SnapObjectContext *ED_transform_snap_object_context_create(
- Main *bmain, Scene *scene, int flag)
+ Main *bmain, Scene *scene, ViewLayer *view_layer, RenderEngineType *engine_type, int flag)
{
SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
@@ -2092,6 +2096,8 @@ SnapObjectContext *ED_transform_snap_object_context_create(
sctx->bmain = bmain;
sctx->scene = scene;
+ DEG_evaluation_context_init_from_scene(&sctx->eval_ctx, scene, view_layer, engine_type, DAG_EVAL_VIEWPORT);
+
sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
@@ -2099,11 +2105,11 @@ SnapObjectContext *ED_transform_snap_object_context_create(
}
SnapObjectContext *ED_transform_snap_object_context_create_view3d(
- Main *bmain, Scene *scene, int flag,
+ Main *bmain, Scene *scene, ViewLayer *view_layer, RenderEngineType *engine_type, int flag,
/* extra args for view3d */
const ARegion *ar, const View3D *v3d)
{
- SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, flag);
+ SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, view_layer, engine_type, flag);
sctx->use_v3d = true;
sctx->v3d_data.ar = ar;
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index c0b30f93939..71a3322cb50 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../depsgraph
../../imbuf
../../gpu
../../makesdna
@@ -64,6 +65,7 @@ set(SRC
../include/ED_lattice.h
../include/ED_logic.h
../include/ED_markers.h
+ ../include/ED_manipulator_library.h
../include/ED_mask.h
../include/ED_mball.h
../include/ED_mesh.h
@@ -75,6 +77,7 @@ set(SRC
../include/ED_particle.h
../include/ED_physics.h
../include/ED_render.h
+ ../include/ED_scene.h
../include/ED_screen.h
../include/ED_screen_types.h
../include/ED_sculpt.h
diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c
index b0970cdfd48..872810c5cf2 100644
--- a/source/blender/editors/util/ed_transverts.c
+++ b/source/blender/editors/util/ed_transverts.c
@@ -39,12 +39,13 @@
#include "BLI_math.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_lattice.h"
#include "BKE_editmesh.h"
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
+#include "DEG_depsgraph.h"
+
#include "ED_armature.h"
#include "ED_transverts.h" /* own include */
@@ -56,7 +57,7 @@ void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit)
const int mode = tvs->mode;
BLI_assert(ED_transverts_check_obedit(obedit) == true);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
if (obedit->type == OB_MESH) {
BMEditMesh *em = BKE_editmesh_from_object(obedit);
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 278b8e34311..b52cc20f71f 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -70,6 +70,8 @@
#include "ED_space_api.h"
#include "ED_util.h"
+#include "GPU_immediate.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
@@ -86,7 +88,8 @@ void ED_editors_init(bContext *C)
wmWindowManager *wm = CTX_wm_manager(C);
Main *bmain = CTX_data_main(C);
Scene *sce = CTX_data_scene(C);
- Object *ob, *obact = (sce && sce->basact) ? sce->basact->object : NULL;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob, *obact = (view_layer && view_layer->basact) ? view_layer->basact->object : NULL;
ID *data;
/* This is called during initialization, so we don't want to store any reports */
@@ -101,12 +104,15 @@ void ED_editors_init(bContext *C)
for (ob = bmain->object.first; ob; ob = ob->id.next) {
int mode = ob->mode;
- if (!ELEM(mode, OB_MODE_OBJECT, OB_MODE_POSE)) {
- ob->mode = OB_MODE_OBJECT;
+ if (mode == OB_MODE_OBJECT) {
+ /* pass */
+ }
+ else {
data = ob->data;
-
- if (ob == obact && !ID_IS_LINKED(ob) && !(data && ID_IS_LINKED(data)))
+ ob->mode = OB_MODE_OBJECT;
+ if ((ob == obact) && !ID_IS_LINKED(ob) && !(data && ID_IS_LINKED(data))) {
ED_object_toggle_modes(C, mode);
+ }
}
}
@@ -313,16 +319,28 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
{
wmWindow *win = CTX_wm_window(C);
const float *mval_src = (float *)arg_info;
- const int mval_dst[2] = {win->eventstate->x - ar->winrct.xmin,
- win->eventstate->y - ar->winrct.ymin};
-
- UI_ThemeColor(TH_VIEW_OVERLAY);
- setlinestyle(3);
- glBegin(GL_LINES);
- glVertex2iv(mval_dst);
- glVertex2fv(mval_src);
- glEnd();
- setlinestyle(0);
+ const float mval_dst[2] = {win->eventstate->x - ar->winrct.xmin,
+ win->eventstate->y - ar->winrct.ymin};
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 0); /* "simple" mode */
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2fv(shdr_pos, mval_src);
+ immVertex2fv(shdr_pos, mval_dst);
+ immEnd();
+
+ immUnbindProgram();
}
/**
diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c
index 441fd446cd6..d9f777771a8 100644
--- a/source/blender/editors/util/editmode_undo.c
+++ b/source/blender/editors/util/editmode_undo.c
@@ -42,9 +42,10 @@
#include "BKE_blender_undo.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
+#include "DEG_depsgraph.h"
+
#include "ED_util.h"
#include "ED_mesh.h"
@@ -269,7 +270,7 @@ void undo_editmode_step(bContext *C, int step)
EDBM_selectmode_to_scene(C);
}
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
/* XXX notifiers */
}
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index 95b5c2c1e48..9e28a5f84ec 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -45,6 +45,7 @@
#include "BKE_blender_undo.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_library_override.h"
#include "BKE_main.h"
#include "BKE_screen.h"
@@ -82,6 +83,9 @@ void ED_undo_push(bContext *C, const char *str)
if (G.debug & G_DEBUG)
printf("%s: %s\n", __func__, str);
+ /* Always do it for now, this might need to be refined... */
+ BKE_main_override_static_operations_create(CTX_data_main(C));
+
if (obedit) {
if (U.undosteps == 0) return;
@@ -101,7 +105,7 @@ void ED_undo_push(bContext *C, const char *str)
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
if (U.undosteps == 0) return;
- PE_undo_push(CTX_data_scene(C), str);
+ PE_undo_push(CTX_data_scene(C), CTX_data_view_layer(C), str);
}
else if (obact && obact->mode & OB_MODE_SCULPT) {
/* do nothing for now */
@@ -120,6 +124,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
wmWindow *win = CTX_wm_window(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
Object *obact = CTX_data_active_object(C);
ScrArea *sa = CTX_wm_area(C);
@@ -180,9 +185,9 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
}
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
if (step == 1)
- PE_undo(scene);
+ PE_undo(scene, view_layer);
else
- PE_redo(scene);
+ PE_redo(scene, view_layer);
}
else if (U.uiflag & USER_GLOBALUNDO) {
// note python defines not valid here anymore.
@@ -297,7 +302,7 @@ bool ED_undo_is_valid(const bContext *C, const char *undoname)
return 1;
}
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
- return PE_undo_is_valid(CTX_data_scene(C));
+ return PE_undo_is_valid(CTX_data_scene(C), CTX_data_view_layer(C));
}
if (U.uiflag & USER_GLOBALUNDO) {
@@ -542,7 +547,7 @@ static const EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *tot
const char *name = NULL;
if (undosys == UNDOSYSTEM_PARTICLE) {
- name = PE_undo_get_name(CTX_data_scene(C), i, &active);
+ name = PE_undo_get_name(CTX_data_scene(C), CTX_data_view_layer(C), i, &active);
}
else if (undosys == UNDOSYSTEM_EDITMODE) {
name = undo_editmode_get_name(C, i, &active);
@@ -625,7 +630,7 @@ static int undo_history_exec(bContext *C, wmOperator *op)
int item = RNA_int_get(op->ptr, "item");
if (undosys == UNDOSYSTEM_PARTICLE) {
- PE_undo_number(CTX_data_scene(C), item);
+ PE_undo_number(CTX_data_scene(C), CTX_data_view_layer(C), item);
}
else if (undosys == UNDOSYSTEM_EDITMODE) {
undo_editmode_number(C, item + 1);
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index 543ef0e0663..a933717fe98 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../depsgraph
../../gpu
../../makesdna
../../makesrna
diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c
index ab415c0cb83..6b4dd0f0210 100644
--- a/source/blender/editors/uvedit/uvedit_buttons.c
+++ b/source/blender/editors/uvedit/uvedit_buttons.c
@@ -66,17 +66,14 @@ static int uvedit_center(Scene *scene, BMEditMesh *em, Image *ima, float center[
BMFace *f;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
int tot = 0;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
zero_v2(center);
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(f, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, f, tf))
+ if (!uvedit_face_visible_test(scene, ima, f))
continue;
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
@@ -102,14 +99,11 @@ static void uvedit_translate(Scene *scene, BMEditMesh *em, Image *ima, float del
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
- MTexPoly *tf;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(f, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, f, tf))
+ if (!uvedit_face_visible_test(scene, ima, f))
continue;
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index fecacd07997..db6f2c27623 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -33,6 +33,8 @@
#include <stdlib.h>
#include <string.h>
+#include "MEM_guardedalloc.h"
+
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -52,9 +54,15 @@
#include "BKE_scene.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+
#include "ED_image.h"
#include "ED_mesh.h"
#include "ED_uvedit.h"
@@ -65,12 +73,7 @@
#include "uvedit_intern.h"
-#include "GPU_basic_shader.h"
-
-/* 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, const uint shdr_pos);
void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
{
@@ -81,38 +84,59 @@ 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);
-
-
- 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);
-
- 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);
-
- glTranslatef(-cursor[0], -cursor[1], 0.0);
- setlinestyle(0);
+
+ gpuTranslate2fv(cursor);
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", 8.0f);
+
+ immBegin(GWN_PRIM_LINES, 8);
+
+ immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac);
+
+ immVertex2f(shdr_pos, 0.0f, 0.05f * y_fac);
+ immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f);
+
+ immVertex2f(shdr_pos, 0.05f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac);
+
+ immVertex2f(shdr_pos, 0.0f, -0.05f * y_fac);
+ immVertex2f(shdr_pos, -0.05f * x_fac, 0.0f);
+
+ immEnd();
+
+ immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", 2.0f);
+
+ immBegin(GWN_PRIM_LINES, 8);
+
+ immVertex2f(shdr_pos, -0.020f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, -0.1f * x_fac, 0.0f);
+
+ immVertex2f(shdr_pos, 0.1f * x_fac, 0.0f);
+ immVertex2f(shdr_pos, 0.020f * x_fac, 0.0f);
+
+ immVertex2f(shdr_pos, 0.0f, -0.020f * y_fac);
+ immVertex2f(shdr_pos, 0.0f, -0.1f * y_fac);
+
+ immVertex2f(shdr_pos, 0.0f, 0.1f * y_fac);
+ immVertex2f(shdr_pos, 0.0f, 0.020f * y_fac);
+
+ immEnd();
+
+ immUnbindProgram();
+
+ gpuTranslate2f(-cursor[0], -cursor[1]);
}
static int draw_uvs_face_check(Scene *scene)
@@ -141,41 +165,32 @@ static void draw_uvs_shadow(Object *obedit)
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- /* draws the mesh when painting */
- UI_ThemeColor(TH_UV_SHADOW);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
- }
-}
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-static int draw_uvs_dm_shadow(DerivedMesh *dm)
-{
- /* draw shadow mesh - this is the mesh with the modifier applied */
+ /* draws the mesh when painting */
+ immUniformThemeColor(TH_UV_SHADOW);
- if (dm && dm->drawUVEdges && CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
- UI_ThemeColor(TH_UV_SHADOW);
- dm->drawUVEdges(dm);
- return 1;
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, pos);
}
- return 0;
+ immUnbindProgram();
}
-static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTexPoly *activetf)
+static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, const BMFace *efa_act)
{
BMesh *bm = em->bm;
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
Image *ima = sima->image;
float aspx, aspy, col[4];
int i;
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);
BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
BLI_buffer_declare_static(vec2f, tf_uvorig_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
@@ -191,7 +206,6 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
const int efa_len = efa->len;
float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len);
float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len);
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -203,28 +217,37 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
totarea += BM_face_calc_area(efa);
totuvarea += area_poly_v2(tf_uv, efa->len);
- if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+ if (uvedit_face_visible_test(scene, ima, efa)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
else {
- if (tf == activetf)
- activetf = NULL;
+ if (efa == efa_act) {
+ efa_act = NULL;
+ }
BM_elem_flag_disable(efa, BM_ELEM_TAG);
}
}
-
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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(GWN_PRIM_TRI_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 +277,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);
+ /* TODO: use editmesh tessface */
+ immBegin(GWN_PRIM_TRI_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,11 +306,15 @@ 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 */
-
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_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);
-
- if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+ if (uvedit_face_visible_test(scene, ima, efa)) {
const int efa_len = efa->len;
float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len);
float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len);
@@ -319,24 +351,26 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
ang[i] = angle_normalized_v3v3(av[i], av[(i + 1) % efa_len]);
}
- /* TODO: USE_EDBM_LOOPTRIS */
- glBegin(GL_POLYGON);
+ /* TODO: use editmesh tessface */
+ immBegin(GWN_PRIM_TRI_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)
- activetf = NULL;
+ if (efa == efa_act)
+ efa_act = NULL;
BM_elem_flag_disable(efa, BM_ELEM_TAG);
}
}
+ immUnbindProgram();
+
BLI_buffer_free(&uvang_buf);
BLI_buffer_free(&ang_buf);
BLI_buffer_free(&av_buf);
@@ -350,58 +384,74 @@ 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, const uint shdr_pos)
{
BMIter liter;
BMLoop *l;
MLoopUV *luv;
- glBegin(GL_LINE_LOOP);
+ immBegin(GWN_PRIM_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(shdr_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(GWN_PRIM_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;
- MTexPoly *mtpoly = me->mtpoly;
int a;
if (me->mloopuv == NULL) {
return;
}
- for (a = me->totpoly; a != 0; a--, mpoly++, mtpoly++) {
+ Image **image_array = NULL;
+
+ if (other_uv_filter == SI_FILTER_SAME_IMAGE) {
+ image_array = BKE_object_material_edit_image_get_array(ob);
+ }
+
+ for (a = me->totpoly; a != 0; a--, mpoly++) {
if (other_uv_filter == SI_FILTER_ALL) {
/* Nothing to compare, all UV faces are visible. */
}
else if (other_uv_filter == SI_FILTER_SAME_IMAGE) {
- if (mtpoly->tpage != curimage) {
+ if (mpoly[a].mat_nr >= ob->totcol) {
+ continue;
+ }
+ if (image_array[mpoly[a].mat_nr] != curimage) {
continue;
}
}
- draw_uvs_lineloop_mpoly(me, mpoly);
+ draw_uvs_lineloop_mpoly(me, mpoly, pos);
+ }
+
+ if (image_array) {
+ MEM_freeN(image_array);
}
}
-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,41 +503,43 @@ 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,
+static void draw_uvs_other(ViewLayer *view_layer, Object *obedit, const Image *curimage, const bool new_shading_nodes,
const int other_uv_filter)
{
- Base *base;
-
- UI_ThemeColor(TH_UV_OTHERS);
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- for (base = scene->base.first; base; base = base->next) {
- Object *ob = base->object;
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- if (!(base->flag & SELECT)) continue;
- if (!(base->lay & scene->lay)) continue;
- if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
+ immUniformThemeColor(TH_UV_OTHERS);
- if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) {
- draw_uvs_other_mesh(ob, curimage, new_shading_nodes, other_uv_filter);
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (((base->flag & BASE_SELECTED) != 0) &&
+ ((base->flag & BASE_VISIBLED) != 0))
+ {
+ Object *ob = base->object;
+ if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) {
+ 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)
+static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Object *ob)
{
const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
Image *curimage = ED_space_image(sima);
@@ -495,11 +547,9 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
Material *ma;
if (sima->flag & SI_DRAW_OTHER) {
- draw_uvs_other(scene, ob, curimage, new_shading_nodes, sima->other_uv_filter);
+ draw_uvs_other(view_layer, ob, curimage, new_shading_nodes, sima->other_uv_filter);
}
- UI_ThemeColor(TH_UV_SHADOW);
-
ma = give_current_material(ob, ob->actcol);
if (me->mloopuv) {
@@ -512,24 +562,33 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
mloopuv = me->mloopuv;
}
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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(GWN_PRIM_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,16 +596,15 @@ 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));
*r_loop_index = i - 1;
}
-#endif
/* draws uv's in the image space */
-static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
+static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Object *obedit, Depsgraph *depsgraph)
{
const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
ToolSettings *ts;
@@ -554,26 +612,19 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
BMEditMesh *em = me->edit_btmesh;
BMesh *bm = em->bm;
BMFace *efa, *efa_act;
-#ifndef USE_EDBM_LOOPTRIS
- BMFace *activef;
-#endif
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf, *activetf = NULL;
MLoopUV *luv;
- DerivedMesh *finaldm, *cagedm;
unsigned char col1[4], col2[4];
float pointsize;
int drawfaces, interpedges;
Image *ima = sima->image;
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);
- 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);
-#endif
+ unsigned int pos;
+
+ efa_act = EDBM_uv_active_face_get(em, false, false); /* will be set to NULL if hidden */
ts = scene->toolsettings;
drawfaces = draw_uvs_face_check(scene);
@@ -595,38 +646,30 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
}
}
else {
- curimage = (activetf) ? activetf->tpage : ima;
+ curimage = (efa_act) ? BKE_object_material_edit_image_get(obedit, efa_act->mat_nr) : ima;
}
- draw_uvs_other(scene, obedit, curimage, new_shading_nodes, sima->other_uv_filter);
+ draw_uvs_other(view_layer, obedit, curimage, new_shading_nodes, sima->other_uv_filter);
}
/* 1. draw shadow mesh */
if (sima->flag & SI_DRAWSHADOW) {
- DM_update_materials(em->derivedFinal, obedit);
- /* first try existing derivedmesh */
- if (!draw_uvs_dm_shadow(em->derivedFinal)) {
- /* create one if it does not exist */
- cagedm = editbmesh_get_derived_cage_and_final(
- scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH | CD_MASK_MTFACE,
- &finaldm);
-
- /* when sync selection is enabled, all faces are drawn (except for hidden)
- * so if cage is the same as the final, theres no point in drawing this */
- if (!((ts->uv_flag & UV_SYNC_SELECTION) && (cagedm == finaldm)))
- draw_uvs_dm_shadow(finaldm);
-
- /* release derivedmesh again */
- if (cagedm != finaldm) cagedm->release(cagedm);
- finaldm->release(finaldm);
+ Object *ob_cage = DEG_get_evaluated_object(depsgraph, obedit);
+ /* XXX TODO: Need to check if shadow mesh is different than original mesh. */
+ bool is_cage_like_final_meshes = (ob_cage == obedit);
+
+ /* When sync selection is enabled, all faces are drawn (except for hidden)
+ * so if cage is the same as the final, there is no point in drawing this. */
+ if (((ts->uv_flag & UV_SYNC_SELECTION) == 0) || is_cage_like_final_meshes) {
+ draw_uvs_shadow(ob_cage);
}
}
-
+
/* 2. draw colored faces */
if (sima->flag & SI_DRAW_STRETCH) {
- draw_uvs_stretch(sima, scene, em, activetf);
+ draw_uvs_stretch(sima, scene, em, efa_act);
}
else if (!(sima->flag & SI_NO_DRAWFACES)) {
/* draw transparent faces */
@@ -635,79 +678,47 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
-#ifdef USE_EDBM_LOOPTRIS
- {
- unsigned int i;
- 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);
- if (uvedit_face_visible_test(scene, ima, efa, tf)) {
- const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset);
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- 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);
- }
- else {
- glColor4ubv((GLubyte *)(is_select ? col2 : col1));
- }
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glBegin(GL_TRIANGLES);
- draw_uvs_looptri(em, &i, cd_loop_uv_offset);
- glEnd();
+ for (unsigned int i = 0; i < em->tottri; i++) {
+ efa = em->looptris[i][0]->f;
+ if (uvedit_face_visible_test(scene, ima, efa)) {
+ const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset);
+ BM_elem_flag_enable(efa, BM_ELEM_TAG);
- if (tf == activetf) {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- }
+ if (efa == efa_act) {
+ /* only once */
+ immUniformThemeColor(TH_EDITMESH_ACTIVE);
}
else {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
+ immUniformColor4ubv(is_select ? col2 : col1);
}
- }
- }
-#else
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (uvedit_face_visible_test(scene, ima, efa, tf)) {
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
- if (tf == activetf) continue; /* important the temp boolean is set above */
- if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset))
- glColor4ubv((GLubyte *)col2);
- else
- glColor4ubv((GLubyte *)col1);
-
- glBegin(GL_POLYGON);
- 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);
- }
- glEnd();
+ immBegin(GWN_PRIM_TRIS, (em->looptris[i][0]->f->len - 2) * 3);
+ draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos);
+ immEnd();
}
else {
- if (tf == activetf)
- activetf = NULL;
BM_elem_flag_disable(efa, BM_ELEM_TAG);
}
}
-#endif
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
else {
/* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+ if (uvedit_face_visible_test(scene, ima, efa)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
else {
- if (tf == activetf)
- activetf = NULL;
+ if (efa == efa_act)
+ efa_act = NULL;
BM_elem_flag_disable(efa, BM_ELEM_TAG);
}
}
@@ -715,30 +726,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
}
/* 3. draw active face stippled */
-#ifndef USE_EDBM_LOOPTRIS
- if (activef) {
- tf = BM_ELEM_CD_GET_VOID_P(activef, cd_poly_tex_offset);
- if (uvedit_face_visible_test(scene, ima, activef, tf)) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- UI_ThemeColor4(TH_EDITMESH_ACTIVE);
-
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE);
-
- glBegin(GL_POLYGON);
- BM_ITER_ELEM (l, &liter, activef, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- glVertex2fv(luv->uv);
- }
- glEnd();
+ /* (removed during OpenGL upgrade, reimplement if needed) */
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- glDisable(GL_BLEND);
- }
- }
-#endif
-
/* 4. draw edges */
if (sima->flag & SI_SMOOTH_UV) {
@@ -751,104 +740,150 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
switch (sima->dt_uv) {
case SI_UVDT_DASH:
+ {
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}}, 2);
+ immUniform1f("dash_width", 4.0f);
+
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);
+ draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset, shdr_pos);
+ }
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+ immUnbindProgram();
- setlinestyle(2);
- cpack(0x909090);
+ break;
+ }
+ case SI_UVDT_BLACK: /* black/white */
+ case SI_UVDT_WHITE:
+ pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- draw_uvs_lineloop_bmface(efa, cd_loop_uv_offset);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- setlinestyle(0);
- }
+ if (sima->dt_uv == SI_UVDT_WHITE) {
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ }
+ else {
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
}
- 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);
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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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);
+ Gwn_VertFormat *format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
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(GWN_PRIM_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(GWN_PRIM_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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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 +896,80 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
if (drawfaces) {
float cent[2];
-
+ bool col_set = false;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
pointsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
glPointSize(pointsize);
- glBegin(GL_POINTS);
+ immBeginAtMost(GWN_PRIM_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 = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_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(GWN_PRIM_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 +977,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(GWN_PRIM_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 +998,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(GWN_PRIM_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 +1018,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();
}
}
@@ -967,13 +1039,13 @@ static void draw_uv_shadows_get(SpaceImage *sima, Object *ob, Object *obedit, bo
if ((sima->mode == SI_MODE_PAINT) && obedit && obedit->type == OB_MESH) {
struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
- *show_shadow = EDBM_mtexpoly_check(em);
+ *show_shadow = EDBM_uv_check(em);
}
*show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT);
}
-void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit, Object *obact)
+void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, ViewLayer *view_layer, Object *obedit, Object *obact, Depsgraph *depsgraph)
{
ToolSettings *toolsettings = scene->toolsettings;
bool show_uvedit, show_uvshadow, show_texpaint_uvshadow;
@@ -985,9 +1057,9 @@ void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *ob
if (show_uvshadow)
draw_uvs_shadow(obedit);
else if (show_uvedit)
- draw_uvs(sima, scene, obedit);
+ draw_uvs(sima, scene, view_layer, obedit, depsgraph);
else
- draw_uvs_texpaint(sima, scene, obact);
+ draw_uvs_texpaint(sima, scene, view_layer, obact);
if (show_uvedit && !(toolsettings->use_uv_sculpt))
ED_image_draw_cursor(ar, sima->cursor);
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index e028c08091c..6ca46941404 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -32,7 +32,6 @@
#ifndef __UVEDIT_INTERN_H__
#define __UVEDIT_INTERN_H__
-struct MTexPoly;
struct Image;
struct Object;
struct Scene;
@@ -53,7 +52,6 @@ void uv_poly_center(struct BMFace *f, float r_cent[2], const int cd_loop_uv_off
typedef struct NearestHit {
struct BMFace *efa;
- struct MTexPoly *tf;
struct BMLoop *l;
struct MLoopUV *luv, *luv_next;
int lindex; /* index of loop within face */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index d69588e91c6..03a5f4dddc8 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -57,7 +57,6 @@
#include "BKE_context.h"
#include "BKE_customdata.h"
-#include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -68,6 +67,8 @@
#include "BKE_scene.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+
#include "ED_image.h"
#include "ED_mesh.h"
#include "ED_node.h"
@@ -106,7 +107,7 @@ bool ED_uvedit_test(Object *obedit)
return 0;
em = BKE_editmesh_from_object(obedit);
- ret = EDBM_mtexpoly_check(em);
+ ret = EDBM_uv_check(em);
return ret;
}
@@ -182,7 +183,6 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I
{
BMEditMesh *em;
BMIter iter;
- MTexPoly *tf;
bool update = false;
const bool selected = !(scene->toolsettings->uv_flag & UV_SYNC_SELECTION);
@@ -206,8 +206,6 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I
BMFace *efa;
int cd_loop_uv_offset;
- int cd_poly_tex_offset;
-
/* old shading system, assign image to selected faces */
#ifdef USE_SWITCH_ASPECT
float prev_aspect[2], fprev_aspect;
@@ -221,31 +219,22 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I
#endif
/* ensure we have a uv map */
- if (!CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) {
- BM_data_layer_add(em->bm, &em->bm->pdata, CD_MTEXPOLY);
+ if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
BM_data_layer_add(em->bm, &em->bm->ldata, CD_MLOOPUV);
/* make UVs all nice 0-1 */
- ED_mesh_uv_loop_reset_ex(obedit->data, CustomData_get_active_layer(&em->bm->pdata, CD_MTEXPOLY));
+ ED_mesh_uv_loop_reset_ex(obedit->data, CustomData_get_active_layer(&em->bm->ldata, CD_MLOOPUV));
update = true;
}
cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
/* now assign to all visible faces */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- if (uvedit_face_visible_test(scene, previma, efa, tf) &&
+ if (uvedit_face_visible_test(scene, previma, efa) &&
(selected == true || uvedit_face_select_test(scene, efa, cd_loop_uv_offset)))
{
- if (ima) {
- tf->tpage = ima;
-
- if (ima->id.us == 0) id_us_plus(&ima->id);
- else id_lib_extern(&ima->id);
-
#ifdef USE_SWITCH_ASPECT
+ if (ima) {
/* we also need to correct the aspect of uvs */
if (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) {
/* do nothing */
@@ -261,11 +250,9 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I
luv->uv[0] /= faspect;
}
}
-#endif
- }
- else {
- tf->tpage = NULL;
}
+#endif
+ BKE_object_material_edit_image_set(obedit, efa->mat_nr, ima);
update = true;
}
@@ -273,49 +260,12 @@ void ED_uvedit_assign_image(Main *UNUSED(bmain), Scene *scene, Object *obedit, I
/* and update depdency graph */
if (update) {
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
}
}
}
-/* dotile - 1, set the tile flag (from the space image)
- * 2, set the tile index for the faces. */
-static bool uvedit_set_tile(Object *obedit, Image *ima, int curtile)
-{
- BMEditMesh *em;
- BMFace *efa;
- BMIter iter;
- MTexPoly *tf;
- int cd_poly_tex_offset;
-
- /* verify if we have something to do */
- if (!ima || !ED_uvedit_test(obedit))
- return false;
-
- if ((ima->tpageflag & IMA_TILES) == 0)
- return false;
-
- /* skip assigning these procedural images... */
- if (ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE)
- return false;
-
- em = BKE_editmesh_from_object(obedit);
-
- cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT))
- tf->tile = curtile; /* set tile index */
- }
-
- DAG_id_tag_update(obedit->data, 0);
-
- return true;
-}
-
/*********************** space conversion *********************/
static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist)
@@ -346,14 +296,17 @@ bool uvedit_face_visible_nolocal(Scene *scene, BMFace *efa)
return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT));
}
-bool uvedit_face_visible_test(Scene *scene, Image *ima, BMFace *efa, MTexPoly *tf)
+bool uvedit_face_visible_test(Scene *scene, Image *ima, BMFace *efa)
{
ToolSettings *ts = scene->toolsettings;
- if (ts->uv_flag & UV_SHOW_SAME_IMAGE)
- return (tf->tpage == ima) ? uvedit_face_visible_nolocal(scene, efa) : false;
- else
+ if (ts->uv_flag & UV_SHOW_SAME_IMAGE) {
+ const Image *face_image = BKE_object_material_edit_image_get(scene->obedit, efa->mat_nr);
+ return (face_image == ima) ? uvedit_face_visible_nolocal(scene, efa) : false;
+ }
+ else {
return uvedit_face_visible_nolocal(scene, efa);
+ }
}
bool uvedit_face_select_test(Scene *scene, BMFace *efa,
@@ -646,18 +599,15 @@ bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2],
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
INIT_MINMAX2(r_min, r_max);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -696,17 +646,14 @@ static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
unsigned int sel = 0;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
zero_v2(co);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -723,7 +670,7 @@ static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[
return (sel != 0);
}
-static bool uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode)
+bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode)
{
bool changed = false;
@@ -747,7 +694,6 @@ static bool uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2
void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float co[2], NearestHit *hit)
{
- MTexPoly *tf;
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
@@ -756,7 +702,6 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float
int i;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
mindist_squared = 1e10f;
memset(hit, 0, sizeof(*hit));
@@ -764,8 +709,7 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
@@ -775,7 +719,6 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float
dist_squared = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv);
if (dist_squared < mindist_squared) {
- hit->tf = tf;
hit->efa = efa;
hit->l = l;
@@ -791,13 +734,11 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float
static void uv_find_nearest_face(Scene *scene, Image *ima, BMEditMesh *em, const float co[2], NearestHit *hit)
{
- MTexPoly *tf;
BMFace *efa;
BMIter iter;
float mindist, dist, cent[2];
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
mindist = 1e10f;
memset(hit, 0, sizeof(*hit));
@@ -808,8 +749,7 @@ static void uv_find_nearest_face(Scene *scene, Image *ima, BMEditMesh *em, const
hit->luv = hit->luv_next = NULL;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
uv_poly_center(efa, cent, cd_loop_uv_offset);
@@ -817,7 +757,6 @@ static void uv_find_nearest_face(Scene *scene, Image *ima, BMEditMesh *em, const
dist = len_manhattan_v2v2(co, cent);
if (dist < mindist) {
- hit->tf = tf;
hit->efa = efa;
mindist = dist;
}
@@ -841,13 +780,11 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em,
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
float mindist, dist;
int i;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
/*this will fill in hit.vert1 and hit.vert2*/
uv_find_nearest_edge(scene, ima, em, co, hit);
@@ -860,8 +797,7 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em,
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
@@ -883,7 +819,6 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em,
hit->l = l;
hit->luv = luv;
hit->luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
- hit->tf = tf;
hit->efa = efa;
hit->lindex = i;
}
@@ -897,20 +832,17 @@ bool ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
float mindist, dist;
bool found = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
mindist = 1e10f;
copy_v2_v2(r_uv, co);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1020,7 +952,6 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH
BMFace *efa;
BMIter iter, liter;
BMLoop *l;
- MTexPoly *tf;
UvVertMap *vmap;
UvMapVert *iterv_curr;
UvMapVert *iterv_next;
@@ -1028,7 +959,6 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH
bool looking, select;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
/* setup */
BM_mesh_elem_table_ensure(em->bm, BM_FACE);
@@ -1061,9 +991,7 @@ static int uv_select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestH
/* find correct valence edges which are not tagged yet, but connect to tagged one */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, ima, efa, tf)) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, ima, efa)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
/* check face not hidden and not tagged */
if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l)))
@@ -1123,7 +1051,6 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
UvVertMap *vmap;
UvMapVert *vlist, *iterv, *startv;
@@ -1132,7 +1059,6 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
char *flag;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
@@ -1152,9 +1078,7 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo
if (!hit) {
BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+ if (uvedit_face_visible_test(scene, ima, efa)) {
if (select_faces) {
if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
stack[stacksize] = a;
@@ -1318,12 +1242,9 @@ static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVer
BMLoop *l;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
- MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset);
-
- if (!uvedit_face_visible_test(scene, ima, l->f, tf))
+ if (!uvedit_face_visible_test(scene, ima, l->f))
continue;
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
@@ -1349,7 +1270,6 @@ static int uv_select_more_less(bContext *C, const bool select)
ToolSettings *ts = scene->toolsettings;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
if (ts->uv_flag & UV_SYNC_SELECTION) {
if (select) {
@@ -1372,9 +1292,7 @@ static int uv_select_more_less(bContext *C, const bool select)
/* mark loops to be selected */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+ if (uvedit_face_visible_test(scene, ima, efa)) {
#define IS_SEL 1
#define IS_UNSEL 2
@@ -1417,9 +1335,7 @@ static int uv_select_more_less(bContext *C, const bool select)
/* mark loops to be selected */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+ if (uvedit_face_visible_test(scene, ima, efa)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -1486,11 +1402,9 @@ static void uv_weld_align(bContext *C, int tool)
SpaceImage *sima;
Scene *scene;
Image *ima;
- MTexPoly *tf;
float cent[2], min[2], max[2];
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
scene = CTX_data_scene(C);
ima = CTX_data_edit_image(C);
@@ -1504,9 +1418,7 @@ static void uv_weld_align(bContext *C, int tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1520,7 +1432,7 @@ static void uv_weld_align(bContext *C, int tool)
tool = (max[0] - min[0] >= max[1] - min[1]) ? 'y' : 'x';
}
- uvedit_center(scene, ima, obedit, cent, 0);
+ ED_uvedit_center(scene, ima, obedit, cent, 0);
if (tool == 'x' || tool == 'w') {
BMIter iter, liter;
@@ -1528,8 +1440,7 @@ static void uv_weld_align(bContext *C, int tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1548,8 +1459,7 @@ static void uv_weld_align(bContext *C, int tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1577,9 +1487,7 @@ static void uv_weld_align(bContext *C, int tool)
/* tag verts with a selected UV */
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
- tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset);
-
- if (!uvedit_face_visible_test(scene, ima, l->f, tf))
+ if (!uvedit_face_visible_test(scene, ima, l->f))
continue;
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
@@ -1667,9 +1575,7 @@ static void uv_weld_align(bContext *C, int tool)
/* go over all verts except for endpoints */
for (i = 0; i < BLI_array_count(eve_line); i++) {
BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) {
- tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset);
-
- if (!uvedit_face_visible_test(scene, ima, l->f, tf))
+ if (!uvedit_face_visible_test(scene, ima, l->f))
continue;
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
@@ -1703,7 +1609,7 @@ static void uv_weld_align(bContext *C, int tool)
uvedit_live_unwrap_update(sima, scene, obedit);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
}
@@ -1755,7 +1661,6 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
Image *ima;
- MTexPoly *tf;
int uv_a_index;
int uv_b_index;
float *uv_a;
@@ -1766,7 +1671,6 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
BMLoop *l;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
sima = CTX_wm_space_image(C);
scene = CTX_data_scene(C);
@@ -1780,8 +1684,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
/* TODO, use qsort as with MESH_OT_remove_doubles, this isn't optimal */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1843,8 +1746,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
BLI_array_declare(loop_arr_unselected);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1881,7 +1783,7 @@ static int uv_remove_doubles_exec(bContext *C, wmOperator *op)
}
uvedit_live_unwrap_update(sima, scene, obedit);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -1934,11 +1836,9 @@ static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
if (ts->uv_flag & UV_SYNC_SELECTION) {
@@ -1962,9 +1862,7 @@ static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -1980,9 +1878,7 @@ static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -2071,7 +1967,6 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
NearestHit hit;
int i, selectmode, sticky, sync, *hitv = NULL;
@@ -2081,7 +1976,6 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
float penalty[2];
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
/* notice 'limit' is the same no matter the zoom level, since this is like
* remove doubles and could annoying if it joined points when zoomed out.
@@ -2233,8 +2127,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -2269,8 +2162,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
/* select sticky uvs */
if (sticky != SI_STICKY_DISABLE) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -2313,7 +2205,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
#endif
}
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
@@ -2452,7 +2344,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
uv_select_linked(scene, ima, em, limit, hit_p, extend, select_faces);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -2526,12 +2418,10 @@ static int uv_select_split_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
bool changed = false;
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);
if (ts->uv_flag & UV_SYNC_SELECTION) {
BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled");
@@ -2543,9 +2433,8 @@ static int uv_select_split_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
bool is_sel = false;
bool is_unsel = false;
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
/* are we all selected? */
@@ -2686,7 +2575,6 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- /* MTexPoly *tf; */
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) {
@@ -2775,7 +2663,6 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- /* MTexPoly *tf; */
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
@@ -2859,7 +2746,6 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
rctf rectf;
bool changed, pinned, select, extend;
@@ -2868,7 +2754,6 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
(ts->uv_selectmode == UV_SELECT_FACE);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
/* get rectangle from operator */
WM_operator_properties_border_to_rctf(op, &rectf);
@@ -2893,8 +2778,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
/* assume not touched */
BM_elem_flag_disable(efa, BM_ELEM_TAG);
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+ if (uvedit_face_visible_test(scene, ima, efa)) {
uv_poly_center(efa, cent, cd_loop_uv_offset);
if (BLI_rctf_isect_pt_v(&rectf, cent)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -2913,8 +2797,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
changed = true;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tf))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -3111,13 +2994,11 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
(ts->uv_selectmode == UV_SELECT_FACE));
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
BMIter iter, liter;
BMFace *efa;
BMLoop *l;
- MTexPoly *tf;
int screen_uv[2];
bool changed = false;
rcti rect;
@@ -3153,8 +3034,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
}
else { /* Vert Sel */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+ if (uvedit_face_visible_test(scene, ima, efa)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -3244,7 +3124,7 @@ static void uv_snap_cursor_to_pixels(SpaceImage *sima)
static bool uv_snap_cursor_to_selection(Scene *scene, Image *ima, Object *obedit, SpaceImage *sima)
{
- return uvedit_center(scene, ima, obedit, sima->cursor, sima->around);
+ return ED_uvedit_center(scene, ima, obedit, sima->cursor, sima->around);
}
static int uv_snap_cursor_exec(bContext *C, wmOperator *op)
@@ -3302,16 +3182,13 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, cons
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tface;
MLoopUV *luv;
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tface))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -3332,16 +3209,13 @@ static bool uv_snap_uvs_offset(Scene *scene, Image *ima, Object *obedit, const f
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *mtexpoly;
MLoopUV *luv;
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- mtexpoly = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, mtexpoly))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -3363,17 +3237,14 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object
BMFace *f;
BMLoop *l, *lsub;
BMIter iter, liter, lsubiter;
- MTexPoly *tface;
MLoopUV *luv;
bool changed = false;
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);
/* index every vert that has a selected UV using it, but only once so as to
* get unique indices and to count how much to malloc */
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- tface = BM_ELEM_CD_GET_VOID_P(f, cd_poly_tex_offset);
- if (uvedit_face_visible_test(scene, ima, f, tface)) {
+ if (uvedit_face_visible_test(scene, ima, f)) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
BM_elem_flag_set(l, BM_ELEM_TAG, uvedit_uv_select_test(scene, l, cd_loop_uv_offset));
@@ -3421,22 +3292,19 @@ static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tface;
MLoopUV *luv;
int width = 0, height = 0;
float w, h;
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
ED_space_image_get_size(sima, &width, &height);
w = (float)width;
h = (float)height;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tface))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -3470,7 +3338,7 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op)
case 2:
{
float center[2];
- if (uvedit_center(scene, ima, obedit, center, sima->around)) {
+ if (ED_uvedit_center(scene, ima, obedit, center, sima->around)) {
float offset[2];
sub_v2_v2v2(offset, sima->cursor, center);
changed = uv_snap_uvs_offset(scene, ima, obedit, offset);
@@ -3486,7 +3354,7 @@ static int uv_snap_selection_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
uvedit_live_unwrap_update(sima, scene, obedit);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -3526,16 +3394,13 @@ static int uv_pin_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tface;
MLoopUV *luv;
const bool clear = RNA_boolean_get(op->ptr, "clear");
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tface))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -3584,15 +3449,12 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tface;
MLoopUV *luv;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!uvedit_face_visible_test(scene, ima, efa, tface))
+ if (!uvedit_face_visible_test(scene, ima, efa))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -3656,13 +3518,11 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
- MTexPoly *tf;
const bool swap = RNA_boolean_get(op->ptr, "unselected");
Image *ima = sima ? sima->image : NULL;
const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
if (ts->uv_flag & UV_SYNC_SELECTION) {
EDBM_mesh_hide(em, swap);
@@ -3674,9 +3534,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
int hide = 0;
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- if (!uvedit_face_visible_test(scene, ima, efa, tf)) {
+ if (!uvedit_face_visible_test(scene, ima, efa)) {
continue;
}
@@ -3957,73 +3815,6 @@ static void UV_OT_cursor_set(wmOperatorType *ot)
"Cursor location in normalized (0.0-1.0) coordinates", -10.0f, 10.0f);
}
-/********************** set tile operator **********************/
-
-static int set_tile_exec(bContext *C, wmOperator *op)
-{
- Image *ima = CTX_data_edit_image(C);
- int tile[2];
- Object *obedit = CTX_data_edit_object(C);
-
- RNA_int_get_array(op->ptr, "tile", tile);
-
- if (uvedit_set_tile(obedit, ima, tile[0] + ima->xrep * tile[1])) {
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
-}
-
-static int set_tile_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
- ARegion *ar = CTX_wm_region(C);
- float fx, fy;
- int tile[2];
-
- if (!ima || !(ima->tpageflag & IMA_TILES))
- return OPERATOR_CANCELLED;
-
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy);
-
- if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
- fx = fx * ima->xrep;
- fy = fy * ima->yrep;
-
- tile[0] = fx;
- tile[1] = fy;
-
- sima->curtile = tile[1] * ima->xrep + tile[0];
- RNA_int_set_array(op->ptr, "tile", tile);
- }
-
- return set_tile_exec(C, op);
-}
-
-static void UV_OT_tile_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Set Tile";
- ot->description = "Set UV image tile coordinates";
- ot->idname = "UV_OT_tile_set";
-
- /* api callbacks */
- ot->exec = set_tile_exec;
- ot->invoke = set_tile_invoke;
- ot->poll = ED_operator_image_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int_vector(ot->srna, "tile", 2, NULL, 0, INT_MAX, "Tile", "Tile coordinate", 0, 10);
-}
-
-
static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
{
UvVertMap *vmap;
@@ -4041,7 +3832,7 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
em = me->edit_btmesh;
bm = em->bm;
- if (!EDBM_mtexpoly_check(em)) {
+ if (!EDBM_uv_check(em)) {
return OPERATOR_CANCELLED;
}
@@ -4133,7 +3924,7 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
BM_uv_vert_map_free(vmap);
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
return OPERATOR_FINISHED;
@@ -4188,7 +3979,7 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op)
if (scene->toolsettings->edge_mode_live_unwrap)
ED_unwrap_lscm(scene, ob, false);
- DAG_id_tag_update(&me->id, 0);
+ DEG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
return OPERATOR_FINISHED;
@@ -4278,7 +4069,6 @@ void ED_operatortypes_uvedit(void)
WM_operatortype_append(UV_OT_hide);
WM_operatortype_append(UV_OT_cursor_set);
- WM_operatortype_append(UV_OT_tile_set);
}
void ED_keymap_uvedit(wmKeyConfig *keyconf)
@@ -4358,7 +4148,6 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf)
/* cursor */
WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "UV_OT_tile_set", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
/* menus */
WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index c2a38a90621..fa936e998fa 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -52,10 +52,11 @@
#include "BKE_context.h"
#include "BKE_customdata.h"
-#include "BKE_depsgraph.h"
#include "BKE_mesh_mapping.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+
#include "UI_interface.h"
#include "ED_mesh.h"
@@ -63,6 +64,8 @@
#include "ED_screen.h"
#include "ED_space_api.h"
+#include "GPU_batch.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -1538,63 +1541,126 @@ static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *no
normalize_v2(normal);
}
+/**
+ */
+static void stitch_draw_vbo(Gwn_VertBuf *vbo, Gwn_PrimType prim_type, const float col[4])
+{
+ Gwn_Batch *batch = GWN_batch_create_ex(prim_type, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR);
+ GWN_batch_uniform_4fv(batch, "color", col);
+ GWN_batch_draw(batch);
+ GWN_batch_discard(batch);
+}
+
+/* TODO make things pretier : store batches inside StitchPreviewer instead of the bare verts pos */
static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
{
- int i, index = 0;
+ int j, index = 0;
+ unsigned int num_line = 0, num_tri, tri_idx = 0, line_idx = 0;
StitchState *state = (StitchState *)arg;
StitchPreviewer *stitch_preview = state->stitch_preview;
+ Gwn_VertBuf *vbo, *vbo_line;
+ float col[4];
- glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
- glEnableClientState(GL_VERTEX_ARRAY);
+ static Gwn_VertFormat format = { 0 };
+ static unsigned int pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
glEnable(GL_BLEND);
- UI_ThemeColor4(TH_STITCH_PREVIEW_ACTIVE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->static_tris);
- glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_static_tris * 3);
-
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_polys);
- for (i = 0; i < stitch_preview->num_polys; i++) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- UI_ThemeColor4(TH_STITCH_PREVIEW_FACE);
- glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE);
- glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
-#if 0
- glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
- UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
- glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
-#endif
-
- index += stitch_preview->uvs_per_polygon[i];
+ /* Static Tris */
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_ACTIVE, col);
+ vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, stitch_preview->num_static_tris * 3);
+ for (int i = 0; i < stitch_preview->num_static_tris * 3; i++) {
+ GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->static_tris[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GWN_PRIM_TRIS, col);
+
+
+ /* Preview Polys */
+ for (int i = 0; i < stitch_preview->num_polys; i++)
+ num_line += stitch_preview->uvs_per_polygon[i];
+
+ num_tri = num_line - 2 * stitch_preview->num_polys;
+
+ /* we need to convert the polys into triangles / lines */
+ vbo = GWN_vertbuf_create_with_format(&format);
+ vbo_line = GWN_vertbuf_create_with_format(&format);
+
+ GWN_vertbuf_data_alloc(vbo, num_tri * 3);
+ GWN_vertbuf_data_alloc(vbo_line, num_line * 2);
+
+ for (int i = 0; i < stitch_preview->num_polys; i++) {
+ BLI_assert(stitch_preview->uvs_per_polygon[i] >= 3);
+
+ /* Start line */
+ GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
+ GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + 2]);
+
+ for (j = 1; j < stitch_preview->uvs_per_polygon[i] - 1; ++j) {
+ GWN_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index]);
+ GWN_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
+ GWN_vertbuf_attr_set(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
+
+ GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 0) * 2]);
+ GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j + 1) * 2]);
+ }
+
+ /* Closing line */
+ GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
+ /* j = uvs_per_polygon[i] - 1*/
+ GWN_vertbuf_attr_set(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + j * 2]);
+
+ index += stitch_preview->uvs_per_polygon[i] * 2;
}
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_FACE, col);
+ stitch_draw_vbo(vbo, GWN_PRIM_TRIS, col);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_EDGE, col);
+ stitch_draw_vbo(vbo_line, GWN_PRIM_LINES, col);
+
glDisable(GL_BLEND);
- /* draw vert preview */
+
+ /* draw stitch vert/lines preview */
if (state->mode == STITCH_VERT) {
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2.0f);
- UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
- glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
+ vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable);
+ for (int i = 0; i < stitch_preview->num_stitchable; i++) {
+ GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GWN_PRIM_POINTS, col);
- UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
- glDrawArrays(GL_POINTS, 0, stitch_preview->num_unstitchable);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
+ vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable);
+ for (int i = 0; i < stitch_preview->num_unstitchable; i++) {
+ GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GWN_PRIM_POINTS, col);
}
else {
- UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
- glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_stitchable);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
+ vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, stitch_preview->num_stitchable * 2);
+ for (int i = 0; i < stitch_preview->num_stitchable * 2; i++) {
+ GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_stitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GWN_PRIM_LINES, col);
- UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
- glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_unstitchable);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
+ vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, stitch_preview->num_unstitchable * 2);
+ for (int i = 0; i < stitch_preview->num_unstitchable * 2; i++) {
+ GWN_vertbuf_attr_set(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i * 2]);
+ }
+ stitch_draw_vbo(vbo, GWN_PRIM_LINES, col);
}
-
- glPopClientAttrib();
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
static UvEdge *uv_edge_get(BMLoop *l, StitchState *state)
@@ -2024,7 +2090,7 @@ static void stitch_exit(bContext *C, wmOperator *op, int finished)
ED_region_draw_cb_exit(CTX_wm_region(C)->type, state->draw_handle);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
state_delete(state);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index bc38a1cd3bb..4f28d1f9eea 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -55,13 +55,15 @@
#include "BKE_subsurf.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
-#include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+
#include "PIL_time.h"
#include "UI_interface.h"
@@ -116,7 +118,7 @@ static bool ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
if (ED_uvedit_test(obedit))
return 1;
- if (em && em->bm->totface && !CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY))
+ if (em && em->bm->totface && !CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV))
ED_mesh_uv_texture_add(obedit->data, NULL, true);
if (!ED_uvedit_test(obedit))
@@ -214,8 +216,7 @@ void ED_uvedit_get_aspect(Scene *scene, Object *ob, BMesh *bm, float *aspx, floa
ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL, NULL);
}
else {
- MTexPoly *tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
- ima = tf->tpage;
+ ima = BKE_object_material_edit_image_get(ob, efa->mat_nr);
}
ED_image_get_uv_aspect(ima, NULL, aspx, aspy);
@@ -570,7 +571,7 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interac
ms->lasttime = PIL_check_seconds_timer();
- DAG_id_tag_update(ms->obedit->data, 0);
+ DEG_id_tag_update(ms->obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ms->obedit->data);
}
}
@@ -593,7 +594,7 @@ static void minimize_stretch_exit(bContext *C, wmOperator *op, bool cancel)
param_stretch_end(ms->handle);
param_delete(ms->handle);
- DAG_id_tag_update(ms->obedit->data, 0);
+ DEG_id_tag_update(ms->obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ms->obedit->data);
MEM_freeN(ms);
@@ -741,7 +742,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
ED_uvedit_pack_islands(scene, obedit, em->bm, true, true, do_rotate);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -784,7 +785,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
param_flush(handle);
param_delete(handle);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -1265,7 +1266,7 @@ static int unwrap_exec(bContext *C, wmOperator *op)
/* execute unwrap */
ED_unwrap_lscm(scene, obedit, true);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -1392,7 +1393,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
uv_map_clip_correct(scene, obedit, em, op);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -1445,7 +1446,7 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op))
ED_mesh_uv_loop_reset(C, me);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -1481,7 +1482,7 @@ static void uv_sphere_project(float target[2], float source[3], float center[3],
target[0] -= 1.0f;
}
-static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf))
+static void uv_map_mirror(BMEditMesh *em, BMFace *efa)
{
BMLoop *l;
BMIter liter;
@@ -1519,7 +1520,6 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
float center[3], rotmat[4][4];
@@ -1545,13 +1545,12 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
uv_sphere_project(luv->uv, l->v->co, center, rotmat);
}
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- uv_map_mirror(em, efa, tf);
+ uv_map_mirror(em, efa);
}
uv_map_clip_correct(scene, obedit, em, op);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -1600,7 +1599,6 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MTexPoly *tf;
MLoopUV *luv;
float center[3], rotmat[4][4];
@@ -1626,13 +1624,12 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
}
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
- uv_map_mirror(em, efa, tf);
+ uv_map_mirror(em, efa);
}
uv_map_clip_correct(scene, obedit, em, op);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
@@ -1663,7 +1660,6 @@ void ED_uvedit_unwrap_cube_project(BMesh *bm, float cube_size, bool use_select,
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- /* MTexPoly *tf; */ /* UNUSED */
MLoopUV *luv;
float loc[3];
int cox, coy;
@@ -1733,7 +1729,7 @@ static int cube_project_exec(bContext *C, wmOperator *op)
uv_map_clip_correct(scene, obedit, em, op);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
diff --git a/source/blender/freestyle/CMakeLists.txt b/source/blender/freestyle/CMakeLists.txt
index f6b7efe978c..183eaf595ed 100644
--- a/source/blender/freestyle/CMakeLists.txt
+++ b/source/blender/freestyle/CMakeLists.txt
@@ -392,8 +392,8 @@ set(SRC
intern/scene_graph/NodeGroup.h
intern/scene_graph/NodeLight.cpp
intern/scene_graph/NodeLight.h
- intern/scene_graph/NodeSceneRenderLayer.cpp
- intern/scene_graph/NodeSceneRenderLayer.h
+ intern/scene_graph/NodeViewLayer.cpp
+ intern/scene_graph/NodeViewLayer.h
intern/scene_graph/NodeShape.cpp
intern/scene_graph/NodeShape.h
intern/scene_graph/NodeTransform.cpp
@@ -557,6 +557,7 @@ set(INC
../blenkernel
../blenlib
../blentranslation
+ ../depsgraph
../imbuf
../makesdna
../makesrna
diff --git a/source/blender/freestyle/FRS_freestyle.h b/source/blender/freestyle/FRS_freestyle.h
index a6382010ca7..58f1c343235 100644
--- a/source/blender/freestyle/FRS_freestyle.h
+++ b/source/blender/freestyle/FRS_freestyle.h
@@ -30,6 +30,7 @@ extern "C" {
#endif
struct Render;
+struct RenderLayer;
struct Material;
struct FreestyleConfig;
struct FreestyleLineStyle;
@@ -50,13 +51,13 @@ extern struct FreestyleGlobals g_freestyle;
void FRS_initialize(void);
void FRS_set_context(struct bContext *C);
void FRS_read_file(struct bContext *C);
-int FRS_is_freestyle_enabled(struct SceneRenderLayer *srl);
+int FRS_is_freestyle_enabled(struct ViewLayer *view_layer);
void FRS_init_stroke_renderer(struct Render *re);
void FRS_begin_stroke_rendering(struct Render *re);
-struct Render *FRS_do_stroke_rendering(struct Render *re, struct SceneRenderLayer *srl, int render);
+struct Render *FRS_do_stroke_rendering(struct Render *re, struct ViewLayer *view_layer, int render);
void FRS_end_stroke_rendering(struct Render *re);
void FRS_free_view_map_cache(void);
-void FRS_composite_result(struct Render *re, struct SceneRenderLayer *srl, struct Render *freestyle_render);
+void FRS_composite_result(struct Render *re, struct ViewLayer *view_layer, struct Render *freestyle_render);
void FRS_exit(void);
/* FreestyleConfig.linesets */
diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp
index beb85798223..759f6456759 100644
--- a/source/blender/freestyle/intern/application/Controller.cpp
+++ b/source/blender/freestyle/intern/application/Controller.cpp
@@ -40,7 +40,7 @@ extern "C" {
#include "../scene_graph/NodeDrawingStyle.h"
#include "../scene_graph/NodeShape.h"
#include "../scene_graph/NodeTransform.h"
-#include "../scene_graph/NodeSceneRenderLayer.h"
+#include "../scene_graph/NodeViewLayer.h"
#include "../scene_graph/ScenePrettyPrinter.h"
#include "../scene_graph/VertexRep.h"
@@ -232,9 +232,9 @@ bool Controller::hitViewMapCache()
return false;
}
-int Controller::LoadMesh(Render *re, SceneRenderLayer *srl)
+int Controller::LoadMesh(Render *re, ViewLayer *view_layer)
{
- BlenderFileLoader loader(re, srl);
+ BlenderFileLoader loader(re, view_layer);
loader.setRenderMonitor(_pRenderMonitor);
@@ -301,7 +301,7 @@ int Controller::LoadMesh(Render *re, SceneRenderLayer *srl)
}
cam->setProjectionMatrix(proj);
_RootNode->AddChild(cam);
- _RootNode->AddChild(new NodeSceneRenderLayer(*re->scene, *srl));
+ _RootNode->AddChild(new NodeViewLayer(*re->scene, *view_layer));
sceneHashFunc.reset();
//blenderScene->accept(sceneHashFunc);
diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h
index 154edaf1e53..0304c18b8a6 100644
--- a/source/blender/freestyle/intern/application/Controller.h
+++ b/source/blender/freestyle/intern/application/Controller.h
@@ -68,7 +68,7 @@ public:
//soc
void init_options();
- int LoadMesh(Render *re, SceneRenderLayer *srl);
+ int LoadMesh(Render *re, ViewLayer *view_layer);
int Load3DSFile(const char *iFileName);
void CloseFile();
void ComputeViewMap();
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
index 1f5e2b63bfa..a0da68849f7 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -32,16 +32,16 @@
namespace Freestyle {
-BlenderFileLoader::BlenderFileLoader(Render *re, SceneRenderLayer *srl)
+BlenderFileLoader::BlenderFileLoader(Render *re, ViewLayer *view_layer)
{
_re = re;
- _srl = srl;
+ _view_layer = view_layer;
_Scene = NULL;
_numFacesRead = 0;
#if 0
_minEdgeSize = DBL_MAX;
#endif
- _smooth = (srl->freestyleConfig.flags & FREESTYLE_FACE_SMOOTHNESS_FLAG) != 0;
+ _smooth = (view_layer->freestyle_config.flags & FREESTYLE_FACE_SMOOTHNESS_FLAG) != 0;
_pRenderMonitor = NULL;
}
@@ -105,8 +105,6 @@ NodeGroup *BlenderFileLoader::Load()
cnt++;
}
- if (!(obi->lay & _srl->lay))
- continue;
char *name = obi->ob->id.name;
//printf("%c%c:%s\n", name[0], name[1], name+2);
//print_m4("obi->mat", obi->mat);
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
index 894f8eeeb4e..ad92416801d 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
@@ -78,7 +78,7 @@ class BlenderFileLoader
{
public:
/*! Builds a MaxFileLoader */
- BlenderFileLoader(Render *re, SceneRenderLayer *srl);
+ BlenderFileLoader(Render *re, ViewLayer *view_layer);
virtual ~BlenderFileLoader();
/*! Loads the 3D scene and returns a pointer to the scene root node */
@@ -114,7 +114,7 @@ protected:
unsigned n;
};
Render *_re;
- SceneRenderLayer *_srl;
+ ViewLayer *_view_layer;
NodeGroup *_Scene;
unsigned _numFacesRead;
#if 0
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index 9c478c203e7..79f17756ca6 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -43,8 +43,8 @@ extern "C" {
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
+#include "BKE_collection.h"
#include "BKE_customdata.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_library.h" /* free_libblock */
#include "BKE_material.h"
@@ -59,6 +59,9 @@ extern "C" {
#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RE_pipeline.h"
#include "render_types.h"
@@ -73,6 +76,7 @@ const char *BlenderStrokeRenderer::uvNames[] = {"along_stroke", "along_stroke_ti
BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : StrokeRenderer()
{
freestyle_bmain = re->freestyle_bmain;
+ freestyle_depsgraph = DEG_graph_new();
// for stroke mesh generation
_width = re->winx;
@@ -112,23 +116,24 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
freestyle_scene->r.filtertype = old_scene->r.filtertype;
freestyle_scene->r.gauss = old_scene->r.gauss;
freestyle_scene->r.dither_intensity = old_scene->r.dither_intensity;
- BLI_strncpy(freestyle_scene->r.engine, old_scene->r.engine, sizeof(freestyle_scene->r.engine));
- freestyle_scene->r.im_format.planes = R_IMF_PLANES_RGBA;
+ BKE_viewrender_copy(&freestyle_scene->view_render, &old_scene->view_render);
+ freestyle_scene->r.im_format.planes = R_IMF_PLANES_RGBA;
freestyle_scene->r.im_format.imtype = R_IMF_IMTYPE_PNG;
if (G.debug & G_DEBUG_FREESTYLE) {
printf("%s: %d thread(s)\n", __func__, BKE_render_num_threads(&freestyle_scene->r));
}
- // Render layer
- SceneRenderLayer *srl = (SceneRenderLayer *)freestyle_scene->r.layers.first;
- srl->layflag = SCE_LAY_SOLID | SCE_LAY_ZTRA;
-
BKE_scene_set_background(freestyle_bmain, freestyle_scene);
+ DEG_graph_id_tag_update(freestyle_bmain, freestyle_depsgraph, &freestyle_scene->id, 0);
+
+ // Scene layer.
+ ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first;
+ view_layer->layflag = SCE_LAY_SOLID | SCE_LAY_ZTRA;
// Camera
- Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA, NULL);
- DAG_relations_tag_update(freestyle_bmain);
+ Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, view_layer, OB_CAMERA, NULL);
+ DEG_graph_id_tag_update(freestyle_bmain, freestyle_depsgraph, &object_camera->id, 0);
Camera *camera = (Camera *)object_camera->data;
camera->type = CAM_ORTHO;
@@ -156,6 +161,9 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
_nodetree_hash = BLI_ghash_ptr_new("BlenderStrokeRenderer::_nodetree_hash");
else
_nodetree_hash = NULL;
+
+ // New IDs were added, tag relations for update.
+ DEG_graph_tag_relations_update(freestyle_depsgraph);
}
BlenderStrokeRenderer::~BlenderStrokeRenderer()
@@ -166,7 +174,8 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer()
// compositor has finished.
// release objects and data blocks
- for (Base *b = (Base *)freestyle_scene->base.first; b; b = b->next) {
+ ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first;
+ for (Base *b = (Base *)view_layer->object_bases.first; b; b = b->next) {
Object *ob = b->object;
void *data = ob->data;
char *name = ob->id.name;
@@ -189,7 +198,14 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer()
cerr << "Warning: unexpected object in the scene: " << name[0] << name[1] << ":" << (name + 2) << endl;
}
}
- BLI_freelistN(&freestyle_scene->base);
+
+ // Make sure we don't have any bases which might reference freed objects.
+ FOREACH_SCENE_COLLECTION(freestyle_scene, sc)
+ {
+ BLI_freelistN(&sc->objects);
+ }
+ FOREACH_SCENE_COLLECTION_END
+ BLI_freelistN(&view_layer->object_bases);
// release materials
Link *lnk = (Link *)freestyle_bmain->mat.first;
@@ -213,6 +229,8 @@ BlenderStrokeRenderer::~BlenderStrokeRenderer()
if (_use_shading_nodes)
BLI_ghash_free(_nodetree_hash, NULL, NULL);
+ DEG_graph_free(freestyle_depsgraph);
+
FreeStrokeGroups();
}
@@ -461,7 +479,7 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
BLI_ghash_insert(_nodetree_hash, nt, ma);
}
- if (STREQ(freestyle_scene->r.engine, RE_engine_id_CYCLES)) {
+ if (STREQ(freestyle_scene->view_render.engine_id, RE_engine_id_CYCLES)) {
PointerRNA scene_ptr, freestyle_scene_ptr;
RNA_pointer_create(NULL, &RNA_Scene, old_scene, &scene_ptr);
RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &freestyle_scene_ptr);
@@ -510,7 +528,7 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
// If still no material, create one
if (!has_mat) {
Material *ma = BKE_material_add(freestyle_bmain, "stroke_material");
- DAG_relations_tag_update(freestyle_bmain);
+ DEG_relations_tag_update(freestyle_bmain);
ma->mode |= MA_VERTEXCOLP;
ma->mode |= MA_TRANSP;
ma->mode |= MA_SHLESS;
@@ -674,8 +692,8 @@ 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);
- DAG_relations_tag_update(freestyle_bmain);
+ Object *object_mesh = BKE_object_add(freestyle_bmain, freestyle_scene, (ViewLayer *)freestyle_scene->view_layers.first, OB_MESH);
+ DEG_relations_tag_update(freestyle_bmain);
#else
Object *object_mesh = NewMesh();
#endif
@@ -700,17 +718,13 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
if (hasTex) {
// First UV layer
- CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, uvNames[0]);
CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[0]);
- CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 0);
CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 0);
BKE_mesh_update_customdata_pointers(mesh, true);
loopsuv[0] = mesh->mloopuv;
// Second UV layer
- CustomData_add_layer_named(&mesh->pdata, CD_MTEXPOLY, CD_CALLOC, NULL, mesh->totpoly, uvNames[1]);
CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_CALLOC, NULL, mesh->totloop, uvNames[1]);
- CustomData_set_layer_active(&mesh->pdata, CD_MTEXPOLY, 1);
CustomData_set_layer_active(&mesh->ldata, CD_MLOOPUV, 1);
BKE_mesh_update_customdata_pointers(mesh, true);
loopsuv[1] = mesh->mloopuv;
@@ -922,7 +936,6 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
Object *BlenderStrokeRenderer::NewMesh() const
{
Object *ob;
- Base *base;
char name[MAX_ID_NAME];
unsigned int mesh_id = get_stroke_mesh_id();
@@ -932,16 +945,14 @@ Object *BlenderStrokeRenderer::NewMesh() const
ob->data = BKE_mesh_add(freestyle_bmain, name);
ob->lay = 1;
- base = BKE_scene_base_add(freestyle_scene, ob);
- DAG_relations_tag_update(freestyle_bmain);
-#if 0
- BKE_scene_base_deselect_all(scene);
- BKE_scene_base_select(scene, base);
-#else
- (void)base;
-#endif
+ SceneCollection *sc_master = BKE_collection_master(&freestyle_scene->id);
+ BKE_collection_object_add(&freestyle_scene->id, sc_master, ob);
+ DEG_graph_tag_relations_update(freestyle_depsgraph);
- DAG_id_tag_update_ex(freestyle_bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_graph_id_tag_update(freestyle_bmain,
+ freestyle_depsgraph,
+ &ob->id,
+ OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
return ob;
}
@@ -958,6 +969,9 @@ Render *BlenderStrokeRenderer::RenderScene(Render * /*re*/, bool render)
#endif
Render *freestyle_render = RE_NewSceneRender(freestyle_scene);
+ ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first;
+ DEG_graph_relations_update(freestyle_depsgraph, freestyle_bmain, freestyle_scene, view_layer);
+ freestyle_render->depsgraph = freestyle_depsgraph;
RE_RenderFreestyleStrokes(freestyle_render, freestyle_bmain, freestyle_scene,
render && get_stroke_count() > 0);
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
index ec53efa14cd..c7204293839 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
@@ -29,6 +29,7 @@
#include "../system/FreestyleConfig.h"
extern "C" {
+struct Depsgraph;
struct GHash;
struct Main;
struct Material;
@@ -76,6 +77,7 @@ protected:
Main *freestyle_bmain;
Scene *old_scene;
Scene *freestyle_scene;
+ Depsgraph *freestyle_depsgraph;
bContext *_context;
float _width, _height;
float _z, _z_delta;
diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
index ea22633c50e..e2560a33443 100644
--- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
+++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
@@ -283,19 +283,19 @@ static bool test_edge_type_conditions(struct edge_type_condition *conditions,
return true;
}
-static void prepare(Render *re, SceneRenderLayer *srl)
+static void prepare(Render *re, ViewLayer *view_layer)
{
// load mesh
re->i.infostr = IFACE_("Freestyle: Mesh loading");
re->stats_draw(re->sdh, &re->i);
re->i.infostr = NULL;
- if (controller->LoadMesh(re, srl)) // returns if scene cannot be loaded or if empty
+ if (controller->LoadMesh(re, view_layer)) // returns if scene cannot be loaded or if empty
return;
if (re->test_break(re->tbh))
return;
// add style modules
- FreestyleConfig *config = &srl->freestyleConfig;
+ FreestyleConfig *config = &view_layer->freestyle_config;
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "\n=== Rendering options ===" << endl;
@@ -359,7 +359,7 @@ static void prepare(Render *re, SceneRenderLayer *srl)
cout << " " << layer_count+1 << ": " << lineset->name << " - " <<
(lineset->linestyle ? (lineset->linestyle->id.name + 2) : "<NULL>") << endl;
}
- char *buffer = create_lineset_handler(srl->name, lineset->name);
+ char *buffer = create_lineset_handler(view_layer->name, lineset->name);
controller->InsertStyleModule(layer_count, lineset->name, buffer);
controller->toggleLayer(layer_count, true);
MEM_freeN(buffer);
@@ -445,7 +445,7 @@ static void prepare(Render *re, SceneRenderLayer *srl)
}
// set diffuse and z depth passes
- RenderLayer *rl = RE_GetRenderLayer(re->result, srl->name);
+ RenderLayer *rl = RE_GetRenderLayer(re->result, view_layer->name);
bool diffuse = false, z = false;
for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) {
if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) {
@@ -473,7 +473,7 @@ static void prepare(Render *re, SceneRenderLayer *srl)
controller->ComputeViewMap();
}
-void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_render)
+void FRS_composite_result(Render *re, ViewLayer *view_layer, Render *freestyle_render)
{
RenderLayer *rl;
float *src, *dest, *pixSrc, *pixDest;
@@ -503,7 +503,7 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r
}
#endif
- rl = RE_GetRenderLayer(re->result, srl->name);
+ rl = RE_GetRenderLayer(re->result, view_layer->name);
if (!rl) {
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "No destination render layer to composite to" << endl;
@@ -536,13 +536,13 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r
}
}
-static int displayed_layer_count(SceneRenderLayer *srl)
+static int displayed_layer_count(ViewLayer *view_layer)
{
int count = 0;
- switch (srl->freestyleConfig.mode) {
+ switch (view_layer->freestyle_config.mode) {
case FREESTYLE_CONTROL_SCRIPT_MODE:
- for (FreestyleModuleConfig *module = (FreestyleModuleConfig *)srl->freestyleConfig.modules.first;
+ for (FreestyleModuleConfig *module = (FreestyleModuleConfig *)view_layer->freestyle_config.modules.first;
module;
module = module->next)
{
@@ -551,7 +551,7 @@ static int displayed_layer_count(SceneRenderLayer *srl)
}
break;
case FREESTYLE_CONTROL_EDITOR_MODE:
- for (FreestyleLineSet *lineset = (FreestyleLineSet *)srl->freestyleConfig.linesets.first;
+ for (FreestyleLineSet *lineset = (FreestyleLineSet *)view_layer->freestyle_config.linesets.first;
lineset;
lineset = lineset->next)
{
@@ -563,9 +563,11 @@ static int displayed_layer_count(SceneRenderLayer *srl)
return count;
}
-int FRS_is_freestyle_enabled(SceneRenderLayer *srl)
+int FRS_is_freestyle_enabled(ViewLayer *view_layer)
{
- return (!(srl->layflag & SCE_LAY_DISABLE) && srl->layflag & SCE_LAY_FRS && displayed_layer_count(srl) > 0);
+ return ((view_layer->flag & VIEW_LAYER_RENDER) &&
+ (view_layer->flag & VIEW_LAYER_FREESTYLE) &&
+ displayed_layer_count(view_layer) > 0);
}
void FRS_init_stroke_renderer(Render *re)
@@ -587,7 +589,7 @@ void FRS_begin_stroke_rendering(Render *re)
init_camera(re);
}
-Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render)
+Render *FRS_do_stroke_rendering(Render *re, ViewLayer *view_layer, int render)
{
Render *freestyle_render = NULL;
@@ -596,12 +598,12 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render)
RenderMonitor monitor(re);
controller->setRenderMonitor(&monitor);
- controller->setViewMapCache((srl->freestyleConfig.flags & FREESTYLE_VIEW_MAP_CACHE) ? true : false);
+ controller->setViewMapCache((view_layer->freestyle_config.flags & FREESTYLE_VIEW_MAP_CACHE) ? true : false);
if (G.debug & G_DEBUG_FREESTYLE) {
cout << endl;
cout << "----------------------------------------------------------" << endl;
- cout << "| " << (re->scene->id.name + 2) << "|" << srl->name << endl;
+ cout << "| " << (re->scene->id.name + 2) << "|" << view_layer->name << endl;
cout << "----------------------------------------------------------" << endl;
}
@@ -610,7 +612,7 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render)
// - add style modules
// - set parameters
// - compute view map
- prepare(re, srl);
+ prepare(re, view_layer);
if (re->test_break(re->tbh)) {
controller->CloseFile();
@@ -635,7 +637,7 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render)
// composite result
if (freestyle_render) {
- FRS_composite_result(re, srl, freestyle_render);
+ FRS_composite_result(re, view_layer, freestyle_render);
RE_FreeRenderResult(freestyle_render->result);
freestyle_render->result = NULL;
}
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
index 9c462bb6b2b..6f5491fc8ef 100644
--- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
@@ -51,7 +51,6 @@ IndexedFaceSet::IndexedFaceSet() : Rep()
_MISize = 0;
_TIndices = NULL;
_TISize = 0;
- _displayList = 0;
}
IndexedFaceSet::IndexedFaceSet(float *iVertices, unsigned iVSize, float *iNormals, unsigned iNSize,
@@ -150,8 +149,6 @@ IndexedFaceSet::IndexedFaceSet(float *iVertices, unsigned iVSize, float *iNormal
_TISize = iTISize;
_TIndices = iTIndices;
}
-
- _displayList = 0;
}
IndexedFaceSet::IndexedFaceSet(const IndexedFaceSet& iBrother) : Rep(iBrother)
@@ -215,8 +212,6 @@ IndexedFaceSet::IndexedFaceSet(const IndexedFaceSet& iBrother) : Rep(iBrother)
_TIndices = new unsigned[_TISize];
memcpy(_TIndices, iBrother.tindices(), _TISize * sizeof(unsigned));
}
-
- _displayList = 0;
}
IndexedFaceSet::~IndexedFaceSet()
@@ -276,10 +271,6 @@ IndexedFaceSet::~IndexedFaceSet()
delete[] _TIndices;
_TIndices = NULL;
}
-
- // should find a way to deallocates the displayList
- // glDeleteLists(GLuint list, GLSizei range)
- _displayList = 0;
}
void IndexedFaceSet::accept(SceneVisitor& v)
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
index 8d7bf986bde..16dea6f907e 100644
--- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
@@ -150,8 +150,6 @@ public:
std::swap(_MISize, ioOther._MISize);
std::swap(_TISize, ioOther._TISize);
- std::swap(_displayList, ioOther._displayList);
-
Rep::swap(ioOther);
}
@@ -173,12 +171,6 @@ public:
/*! Compute the Bounding Box */
virtual void ComputeBBox();
- /*! modifiers */
- inline void setDisplayList(unsigned int index)
- {
- _displayList = index;
- }
-
/*! Accessors */
virtual const float *vertices() const
{
@@ -280,11 +272,6 @@ public:
return _TISize;
}
- inline unsigned int displayList() const
- {
- return _displayList;
- }
-
protected:
float *_Vertices;
float *_Normals;
@@ -311,8 +298,6 @@ protected:
unsigned _MISize;
unsigned _TISize;
- unsigned int _displayList;
-
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:IndexedFaceSet")
#endif
diff --git a/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp b/source/blender/freestyle/intern/scene_graph/NodeViewLayer.cpp
index 24c56ff4e28..701c5caa91d 100644
--- a/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp
+++ b/source/blender/freestyle/intern/scene_graph/NodeViewLayer.cpp
@@ -18,18 +18,18 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.cpp
+/** \file blender/freestyle/intern/scene_graph/NodeViewLayer.cpp
* \ingroup freestyle
* \brief Class to represent a scene render layer in Blender.
*/
-#include "NodeSceneRenderLayer.h"
+#include "NodeViewLayer.h"
namespace Freestyle {
-void NodeSceneRenderLayer::accept(SceneVisitor& v)
+void NodeViewLayer::accept(SceneVisitor& v)
{
- v.visitNodeSceneRenderLayer(*this);
+ v.visitNodeViewLayer(*this);
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h b/source/blender/freestyle/intern/scene_graph/NodeViewLayer.h
index 8dc93d84201..cc64fda60b6 100644
--- a/source/blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h
+++ b/source/blender/freestyle/intern/scene_graph/NodeViewLayer.h
@@ -18,38 +18,38 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __FREESTYLE_NODE_SCENE_RENDER_LAYER_H__
-#define __FREESTYLE_NODE_SCENE_RENDER_LAYER_H__
+#ifndef __FREESTYLE_NODE_VIEW_LAYER_H__
+#define __FREESTYLE_NODE_VIEW_LAYER_H__
-/** \file blender/freestyle/intern/scene_graph/NodeSceneRenderLayer.h
+/** \file blender/freestyle/intern/scene_graph/NodeViewLayer.h
* \ingroup freestyle
- * \brief Class to represent a scene render layer in Blender.
+ * \brief Class to represent a view layer in Blender.
*/
#include "Node.h"
extern "C" {
-#include "DNA_scene_types.h" /* for Scene and SceneRenderLayer */
+#include "DNA_scene_types.h" /* for Scene and ViewLayer */
}
using namespace std;
namespace Freestyle {
-class NodeSceneRenderLayer : public Node
+class NodeViewLayer : public Node
{
public:
- inline NodeSceneRenderLayer(Scene& scene, SceneRenderLayer& srl) : Node(), _Scene(scene), _SceneRenderLayer(srl) {}
- virtual ~NodeSceneRenderLayer() {}
+ inline NodeViewLayer(Scene& scene, ViewLayer& view_layer) : Node(), _Scene(scene), _ViewLayer(view_layer) {}
+ virtual ~NodeViewLayer() {}
inline struct Scene& scene() const
{
return _Scene;
}
- inline struct SceneRenderLayer& sceneRenderLayer() const
+ inline struct ViewLayer& sceneLayer() const
{
- return _SceneRenderLayer;
+ return _ViewLayer;
}
/*! Accept the corresponding visitor */
@@ -58,9 +58,9 @@ public:
protected:
Scene& _Scene;
- SceneRenderLayer& _SceneRenderLayer;
+ ViewLayer& _ViewLayer;
};
} /* namespace Freestyle */
-#endif // __FREESTYLE_NODE_SCENE_RENDER_LAYER_H__
+#endif // __FREESTYLE_NODE_VIEW_LAYER_H__
diff --git a/source/blender/freestyle/intern/scene_graph/SceneHash.cpp b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp
index 2af02ab5764..16c353678c1 100644
--- a/source/blender/freestyle/intern/scene_graph/SceneHash.cpp
+++ b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp
@@ -35,14 +35,14 @@ string SceneHash::toString()
return ss.str();
}
-void SceneHash::visitNodeSceneRenderLayer(NodeSceneRenderLayer& node)
+void SceneHash::visitNodeViewLayer(NodeViewLayer& node)
{
struct RenderData *r = &node.scene().r;
adler32((unsigned char *)&r->xsch, sizeof(r->xsch)); // resolution_x
adler32((unsigned char *)&r->ysch, sizeof(r->ysch)); // resolution_y
adler32((unsigned char *)&r->size, sizeof(r->size)); // resolution_percentage
- struct FreestyleConfig *config = &node.sceneRenderLayer().freestyleConfig;
+ struct FreestyleConfig *config = &node.sceneLayer().freestyle_config;
adler32((unsigned char *)&config->flags, sizeof(config->flags));
adler32((unsigned char *)&config->crease_angle, sizeof(config->crease_angle));
adler32((unsigned char *)&config->sphere_radius, sizeof(config->sphere_radius));
diff --git a/source/blender/freestyle/intern/scene_graph/SceneHash.h b/source/blender/freestyle/intern/scene_graph/SceneHash.h
index 9da711673f0..662b4bba8f1 100644
--- a/source/blender/freestyle/intern/scene_graph/SceneHash.h
+++ b/source/blender/freestyle/intern/scene_graph/SceneHash.h
@@ -26,7 +26,7 @@
*/
#include "IndexedFaceSet.h"
-#include "NodeSceneRenderLayer.h"
+#include "NodeViewLayer.h"
#include "NodeCamera.h"
#include "SceneVisitor.h"
@@ -49,7 +49,7 @@ public:
virtual ~SceneHash() {}
VISIT_DECL(NodeCamera)
- VISIT_DECL(NodeSceneRenderLayer)
+ VISIT_DECL(NodeViewLayer)
VISIT_DECL(IndexedFaceSet)
string toString();
diff --git a/source/blender/freestyle/intern/scene_graph/SceneVisitor.h b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
index 712585c4064..d76e48980bf 100644
--- a/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
+++ b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
@@ -56,7 +56,7 @@ class NodeLight;
class NodeCamera;
class NodeDrawingStyle;
class NodeTransform;
-class NodeSceneRenderLayer;
+class NodeViewLayer;
class Rep;
class LineRep;
@@ -88,7 +88,7 @@ public:
VISIT_COMPLETE_DEF(NodeCamera)
VISIT_COMPLETE_DEF(NodeDrawingStyle)
VISIT_COMPLETE_DEF(NodeTransform)
- VISIT_COMPLETE_DEF(NodeSceneRenderLayer)
+ VISIT_COMPLETE_DEF(NodeViewLayer)
VISIT_COMPLETE_DEF(Rep)
VISIT_COMPLETE_DEF(LineRep)
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 885ff2ff159..18a1ef36bdc 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -31,6 +31,9 @@ set(INC
../imbuf
../makesdna
../makesrna
+ ../draw
+
+ ../editors/include
# For node muting stuff...
../nodes
@@ -39,6 +42,7 @@ set(INC
../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/smoke/extern
+ ../../../intern/gawain
)
set(INC_SYS
@@ -47,6 +51,7 @@ set(INC_SYS
set(SRC
intern/gpu_basic_shader.c
+ intern/gpu_batch.c
intern/gpu_buffers.c
intern/gpu_codegen.c
intern/gpu_compositing.c
@@ -54,13 +59,19 @@ set(SRC
intern/gpu_draw.c
intern/gpu_extensions.c
intern/gpu_framebuffer.c
+ intern/gpu_immediate.c
+ intern/gpu_immediate_util.c
intern/gpu_init_exit.c
+ intern/gpu_lamp.c
intern/gpu_material.c
+ intern/gpu_matrix.c
intern/gpu_select.c
intern/gpu_select_pick.c
intern/gpu_select_sample_query.c
intern/gpu_shader.c
intern/gpu_texture.c
+ intern/gpu_uniformbuffer.c
+ intern/gpu_viewport.c
shaders/gpu_shader_fx_lib.glsl
shaders/gpu_shader_fx_ssao_frag.glsl
@@ -69,7 +80,7 @@ set(SRC
shaders/gpu_shader_fx_dof_hq_frag.glsl
shaders/gpu_shader_fx_dof_hq_vert.glsl
shaders/gpu_shader_fx_dof_hq_geo.glsl
- shaders/gpu_shader_fx_vert.glsl
+ shaders/gpu_shader_fullscreen_vert.glsl
shaders/gpu_shader_material.glsl
shaders/gpu_shader_sep_gaussian_blur_frag.glsl
shaders/gpu_shader_sep_gaussian_blur_vert.glsl
@@ -85,6 +96,7 @@ set(SRC
shaders/gpu_shader_smoke_vert.glsl
GPU_basic_shader.h
+ GPU_batch.h
GPU_buffers.h
GPU_compositing.h
GPU_debug.h
@@ -92,16 +104,108 @@ set(SRC
GPU_extensions.h
GPU_framebuffer.h
GPU_glew.h
+ GPU_immediate.h
+ GPU_immediate_util.h
GPU_init_exit.h
+ GPU_lamp.h
+ GPU_legacy_stubs.h
GPU_material.h
+ GPU_matrix.h
GPU_select.h
GPU_shader.h
GPU_texture.h
+ GPU_uniformbuffer.h
+ GPU_viewport.h
+
intern/gpu_codegen.h
intern/gpu_private.h
+ intern/gpu_lamp_private.h
intern/gpu_select_private.h
+ intern/gpu_shader_private.h
)
+data_to_c_simple(shaders/gpu_shader_depth_only_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_uniform_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_checker_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_diag_stripes_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_simple_lighting_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_alpha_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)
+data_to_c_simple(shaders/gpu_shader_2D_flat_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_line_dashed_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_line_dashed_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_smooth_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_smooth_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_image_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_linear_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_shuffle_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_mask_uniform_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_alpha_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_interlace_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_normal_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_line_dashed_uniform_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_normal_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_objectspace_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_instance_screen_aligned_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_camera_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_distance_line_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_bone_envelope_wire_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_mball_helpers_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_aa_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_varying_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_varying_size_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl SRC)
+
+data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_front_back_ortho_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_overlay_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_overlay_geom.glsl SRC)
+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)
data_to_c_simple(shaders/gpu_shader_smoke_frag.glsl SRC)
@@ -116,7 +220,7 @@ data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fullscreen_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_fx_ssao_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_fx_dof_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_fx_dof_vert.glsl SRC)
diff --git a/source/blender/gpu/GPU_basic_shader.h b/source/blender/gpu/GPU_basic_shader.h
index d9bf3d1ced3..dc378927e79 100644
--- a/source/blender/gpu/GPU_basic_shader.h
+++ b/source/blender/gpu/GPU_basic_shader.h
@@ -64,12 +64,6 @@ typedef enum GPUBasicShaderStipple {
GPU_SHADER_STIPPLE_HEXAGON = 3,
GPU_SHADER_STIPPLE_DIAG_STRIPES = 4,
GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP = 5,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW = 6,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW_SWAP = 7,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN = 8,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN_SWAP = 9,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER = 10,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER_SWAP = 11
} GPUBasicShaderStipple;
void GPU_basic_shaders_init(void);
@@ -132,9 +126,6 @@ void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id);
void GPU_basic_shader_line_stipple(GLint stipple_factor, GLushort stipple_pattern);
void GPU_basic_shader_line_width(float line_width);
-bool GPU_basic_shader_use_glsl_get(void);
-void GPU_basic_shader_use_glsl_set(bool enabled);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
new file mode 100644
index 00000000000..6d16092996e
--- /dev/null
+++ b/source/blender/gpu/GPU_batch.h
@@ -0,0 +1,51 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* Batched geometry rendering is powered by the Gawain library.
+ * This file contains any additions or modifications specific to Blender.
+ */
+
+#ifndef __GPU_BATCH_H__
+#define __GPU_BATCH_H__
+
+#include "../../../intern/gawain/gawain/gwn_batch.h"
+
+// TODO: CMake magic to do this:
+// #include "gawain/batch.h"
+
+#include "GPU_shader.h"
+
+/* Extend GWN_batch_program_set to use Blender’s library of built-in shader programs. */
+void GWN_batch_program_set_builtin(Gwn_Batch *, GPUBuiltinShader);
+
+/* Replacement for gluSphere */
+Gwn_Batch *GPU_batch_preset_sphere(int lod);
+Gwn_Batch *GPU_batch_preset_sphere_wire(int lod);
+
+void gpu_batch_init(void);
+void gpu_batch_exit(void);
+
+#endif /* __GPU_BATCH_H__ */
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index e4a837d0a5f..30fd4bd30b8 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -51,6 +51,7 @@ struct GPUVertPointLink;
struct GPUDrawObject;
struct GridCommonGPUBuffer;
struct PBVH;
+struct Gwn_Batch;
struct MVert;
typedef struct GPUBuffer {
@@ -260,11 +261,10 @@ void GPU_pbvh_grid_buffers_update(
void GPU_pbvh_buffers_draw(
GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
bool wireframe, bool fast);
+struct Gwn_Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast);
-/* debug PBVH draw*/
-void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf);
-void GPU_pbvh_BB_draw_init(void);
-void GPU_pbvh_BB_draw_end(void);
+/* debug PBVH draw */
+void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos);
bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, struct GSet *bm_faces, bool show_diffuse_color);
diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/gpu/GPU_debug.h
index 61b2bc591ce..c7a99d33654 100644
--- a/source/blender/gpu/GPU_debug.h
+++ b/source/blender/gpu/GPU_debug.h
@@ -41,24 +41,6 @@ extern "C" {
/* prints something if debug mode is active only */
void GPU_print_error_debug(const char *str);
-/* replacement for gluErrorString */
-const char *gpuErrorString(GLenum err);
-
-/* prints current OpenGL state */
-void GPU_state_print(void);
-
-void GPU_assert_no_gl_errors(const char *file, int line, const char *str);
-
-# define GPU_ASSERT_NO_GL_ERRORS(str) GPU_assert_no_gl_errors(__FILE__, __LINE__, (str))
-
-# define GPU_CHECK_ERRORS_AROUND(glProcCall) \
- ( \
- GPU_ASSERT_NO_GL_ERRORS("Pre: " #glProcCall), \
- (glProcCall), \
- GPU_ASSERT_NO_GL_ERRORS("Post: " #glProcCall) \
- )
-
-
/* inserts a debug marker message for the debug context messaging system */
void GPU_string_marker(const char *str);
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 90b65af87c8..8d29632fc71 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -39,9 +39,9 @@ extern "C" {
struct ImBuf;
struct Image;
struct ImageUser;
-struct MTexPoly;
struct Object;
struct Scene;
+struct ViewLayer;
struct View3D;
struct RegionView3D;
struct SmokeModifierData;
@@ -59,6 +59,13 @@ struct DupliObject;
void GPU_state_init(void);
+/* Programmable point size
+ * - shaders set their own point size when enabled
+ * - use glPointSize when disabled */
+
+void GPU_enable_program_point_size(void);
+void GPU_disable_program_point_size(void);
+
/* Material drawing
* - first the state is initialized by a particular object and
* it's materials
@@ -66,8 +73,9 @@ void GPU_state_init(void);
* GPU_object_material_bind returns 0 if drawing should be skipped
* - after drawing, the material must be disabled again */
-void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
- struct Scene *scene, struct Object *ob, bool glsl, bool *do_alpha_after);
+void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
+ struct Scene *scene, struct ViewLayer *view_layer,
+ struct Object *ob, bool glsl, bool *do_alpha_after);
void GPU_end_object_materials(void);
bool GPU_object_materials_check(void);
@@ -84,29 +92,19 @@ bool GPU_material_use_matcaps_get(void);
void GPU_set_material_alpha_blend(int alphablend);
int GPU_get_material_alpha_blend(void);
-/* TexFace drawing
- * - this is mutually exclusive with material drawing, a mesh should
- * be drawn using one or the other
- * - passing NULL clears the state again */
-
-int GPU_set_tpage(struct MTexPoly *mtexpoly, int mipmap, int transp);
-void GPU_clear_tpage(bool force);
-
/* Lights
* - returns how many lights were enabled
* - this affects fixed functions materials and texface, not glsl */
int GPU_default_lights(void);
int GPU_scene_object_lights(
- struct Scene *scene, struct Object *ob,
- int lay, float viewmat[4][4], int ortho);
+ struct ViewLayer *view_layer, float viewmat[4][4], int ortho);
/* Text render
* - based on moving uv coordinates */
void GPU_render_text(
- struct MTexPoly *mtexpoly, int mode,
- const char *textstr, int textlen, unsigned int *col,
+ int mode, const char *textstr, int textlen, unsigned int *col,
const float *v_quad[4], const float *uv_quad[4],
int glattrib);
@@ -166,6 +164,17 @@ void GPU_select_index_get(int index, int *r_col);
int GPU_select_to_index(unsigned int col);
void GPU_select_to_index_array(unsigned int *col, const unsigned int size);
+typedef enum eGPUAttribMask {
+ GPU_DEPTH_BUFFER_BIT = (1 << 0),
+ GPU_ENABLE_BIT = (1 << 1),
+ GPU_SCISSOR_BIT = (1 << 2),
+ GPU_VIEWPORT_BIT = (1 << 3),
+ GPU_BLEND_BIT = (1 << 4),
+} eGPUAttribMask;
+
+void gpuPushAttrib(eGPUAttribMask mask);
+void gpuPopAttrib(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 31ad8243c4b..d860431b04f 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -38,21 +38,16 @@ extern "C" {
/* GPU extensions support */
-void GPU_extensions_disable(void);
-
-bool GPU_legacy_support(void);
bool GPU_full_non_power_of_two_support(void);
-bool GPU_display_list_support(void);
bool GPU_bicubic_bump_support(void);
-bool GPU_geometry_shader_support(void);
-bool GPU_geometry_shader_support_via_extension(void);
-bool GPU_instanced_drawing_support(void);
int GPU_max_texture_size(void);
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]);
@@ -69,6 +64,7 @@ typedef enum GPUDeviceType {
GPU_DEVICE_INTEL = (1 << 2),
GPU_DEVICE_SOFTWARE = (1 << 3),
GPU_DEVICE_UNKNOWN = (1 << 4),
+ GPU_DEVICE_AMD_VEGA = (1 << 5),
GPU_DEVICE_ANY = (0xff)
} GPUDeviceType;
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index 2719b8fa6a8..705ef1997c1 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -50,8 +50,13 @@ struct GPUTexture;
void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex);
GPUFrameBuffer *GPU_framebuffer_create(void);
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, char err_out[256]);
+bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
+bool GPU_framebuffer_texture_layer_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
+bool GPU_framebuffer_texture_cubeface_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
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);
@@ -66,6 +71,14 @@ void GPU_framebuffer_blur(
GPUFrameBuffer *fb, struct GPUTexture *tex,
GPUFrameBuffer *blurfb, struct GPUTexture *blurtex);
+void GPU_framebuffer_blit(
+ GPUFrameBuffer *fb_read, int read_slot,
+ GPUFrameBuffer *fb_write, int write_slot, bool use_depth, bool use_stencil);
+
+void GPU_framebuffer_recursive_downsample(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int num_iter,
+ void (*callback)(void *userData, int level), void *userData);
+
/* GPU OffScreen
* - wrapper around framebuffer and texture for simple offscreen drawing
* - changes size if graphics card can't support it */
@@ -79,6 +92,10 @@ int GPU_offscreen_width(const GPUOffScreen *ofs);
int GPU_offscreen_height(const GPUOffScreen *ofs);
int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
+void GPU_offscreen_viewport_data_get(
+ GPUOffScreen *ofs,
+ GPUFrameBuffer **r_fb, struct GPUTexture **r_color, struct GPUTexture **r_depth);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_glew.h b/source/blender/gpu/GPU_glew.h
index 94217863fd6..afe1c9763ad 100644
--- a/source/blender/gpu/GPU_glew.h
+++ b/source/blender/gpu/GPU_glew.h
@@ -34,4 +34,8 @@
#include "glew-mx.h"
+#ifndef WITH_LEGACY_OPENGL
+#include "GPU_legacy_stubs.h"
+#endif
+
#endif /* __GPU_GLEW_H__ */
diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h
new file mode 100644
index 00000000000..6206e973908
--- /dev/null
+++ b/source/blender/gpu/GPU_immediate.h
@@ -0,0 +1,58 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* Immediate mode rendering is powered by the Gawain library.
+ * This file contains any additions or modifications specific to Blender.
+ */
+
+#ifndef __GPU_IMMEDIATE_H__
+#define __GPU_IMMEDIATE_H__
+
+#include "../../../intern/gawain/gawain/gwn_immediate.h"
+#include "../../../intern/gawain/gawain/gwn_imm_util.h"
+
+// TODO: CMake magic to do this:
+// #include "gawain/gwn_immediate.h"
+// #include "gawain/gwn_imm_util.h"
+
+#include "GPU_shader.h"
+
+/* Extend immBindProgram to use Blender’s library of built-in shader programs.
+ * Use immUnbindProgram() when done. */
+void immBindBuiltinProgram(GPUBuiltinShader shader_id);
+
+/*
+ * Extend immUniformColor to take Blender's themes
+ */
+void immUniformThemeColor(int color_id);
+void immUniformThemeColor3(int color_id);
+void immUniformThemeColorShade(int color_id, int offset);
+void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset);
+void immUniformThemeColorBlendShade(int color_id1, int color_id2, float fac, int offset);
+void immUniformThemeColorBlend(int color_id1, int color_id2, float fac);
+void immThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset);
+
+#endif /* __GPU_IMMEDIATE_H__ */
diff --git a/source/blender/gpu/GPU_immediate_util.h b/source/blender/gpu/GPU_immediate_util.h
new file mode 100644
index 00000000000..c31d477ff5b
--- /dev/null
+++ b/source/blender/gpu/GPU_immediate_util.h
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_immediate_util.h
+ * \ingroup gpu
+ *
+ * Utility drawing functions (rough equivalent to OpenGL's GLU)
+ */
+
+#ifndef __GPU_IMMEDIATE_UTIL_H__
+#define __GPU_IMMEDIATE_UTIL_H__
+
+void imm_cpack(uint x);
+
+void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float radius, int nsegments);
+void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float radius, int nsegments);
+
+void imm_draw_circle_wire_aspect_2d(uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments);
+void imm_draw_circle_fill_aspect_2d(uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments);
+
+/* use this version when Gwn_VertFormat has a vec3 position */
+void imm_draw_circle_wire_3d(uint pos, float x, float y, float radius, int nsegments);
+void imm_draw_circle_fill_3d(uint pos, float x, float y, float radius, int nsegments);
+
+void imm_draw_disk_partial_fill_2d(
+ uint pos, float x, float y,
+ float radius_inner, float radius_outer, int nsegments, float start, float sweep);
+
+void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2);
+void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2);
+
+void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2);
+
+void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3]);
+void imm_draw_cube_wire_3d(uint pos, const float co[3], const float aspect[3]);
+
+void imm_draw_cylinder_fill_normal_3d(
+ uint pos, uint nor, float base, float top, float height,
+ int slices, int stacks);
+void imm_draw_cylinder_wire_3d(
+ uint pos, float base, float top, float height,
+ int slices, int stacks);
+void imm_draw_cylinder_fill_3d(
+ uint pos, float base, float top, float height,
+ int slices, int stacks);
+
+#endif /* __GPU_IMMEDIATE_UTIL_H__ */
diff --git a/source/blender/gpu/GPU_lamp.h b/source/blender/gpu/GPU_lamp.h
new file mode 100644
index 00000000000..87350f1ceb4
--- /dev/null
+++ b/source/blender/gpu/GPU_lamp.h
@@ -0,0 +1,77 @@
+/*
+ * ***** 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): Brecht Van Lommel, Clément Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_lamp.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_LAMP_H__
+#define __GPU_LAMP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Scene;
+struct Object;
+struct RenderEngineType;
+
+typedef struct GPULamp GPULamp;
+
+#define MAX_LAMP_DATA 2
+
+typedef struct LampEngineData {
+ void *storage[MAX_LAMP_DATA];
+} LampEngineData;
+
+LampEngineData *GPU_lamp_engine_data_get(struct Scene *scene, struct Object *ob, struct Object *par, struct RenderEngineType *re);
+
+GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
+void GPU_lamp_free(struct Object *ob);
+void GPU_lamp_engine_data_free(LampEngineData *led);
+
+bool GPU_lamp_visible(GPULamp *lamp, struct Material *ma);
+bool GPU_lamp_has_shadow_buffer(GPULamp *lamp);
+void GPU_lamp_update_buffer_mats(GPULamp *lamp);
+void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]);
+void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp);
+int GPU_lamp_shadow_buffer_type(GPULamp *lamp);
+int GPU_lamp_shadow_bind_code(GPULamp *lamp);
+float *GPU_lamp_dynpersmat(GPULamp *lamp);
+
+void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]);
+void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy);
+void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
+ float coeff_const, float coeff_lin, float coeff_quad);
+void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend);
+int GPU_lamp_shadow_layer(GPULamp *lamp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_LAMP_H__ */
diff --git a/source/blender/gpu/GPU_legacy_stubs.h b/source/blender/gpu/GPU_legacy_stubs.h
new file mode 100644
index 00000000000..a195eac9eec
--- /dev/null
+++ b/source/blender/gpu/GPU_legacy_stubs.h
@@ -0,0 +1,457 @@
+/*
+ * ***** 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) 2017 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Blender Foundation, Dalai Felinto.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_legacy_stubs.h
+ * \ingroup gpu
+ *
+ * This is to mark the transition to OpenGL core profile
+ * The idea is to allow Blender 2.8 to be built with OpenGL 3.3 even if it means breaking things
+ *
+ * This file should be removed in the future
+ */
+
+#ifndef __GPU_LEGACY_STUBS_H__
+#define __GPU_LEGACY_STUBS_H__
+
+#if defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+# pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#include <stdlib.h> /* for abort(). */
+
+#include "BLI_utildefines.h"
+
+/**
+ * Empty function, use for breakpoint when a depreacated
+ * OpenGL function is called.
+ */
+static void gl_deprecated(void)
+{
+ BLI_assert(true);
+}
+
+#define _GL_BOOL BLI_INLINE GLboolean
+#define _GL_BOOL_RET { \
+ gl_deprecated(); \
+ return false; \
+}
+
+#define _GL_ENUM BLI_INLINE GLenum
+#define _GL_ENUM_RET { \
+ gl_deprecated(); \
+ return 0; \
+}
+
+#define _GL_INT BLI_INLINE GLint
+#define _GL_INT_RET { \
+ gl_deprecated(); \
+ return 0; \
+}
+
+
+#define _GL_UINT BLI_INLINE GLuint
+#define _GL_UINT_RET { \
+ gl_deprecated(); \
+ return 0; \
+}
+
+#define _GL_VOID BLI_INLINE void
+#define _GL_VOID_RET { \
+ gl_deprecated(); \
+}
+
+static bool disable_enable_check(GLenum cap)
+{
+ const bool is_deprecated = \
+ ELEM(
+ cap,
+ GL_ALPHA_TEST,
+ GL_LINE_STIPPLE,
+ GL_POINT_SPRITE,
+ GL_TEXTURE_1D,
+ GL_TEXTURE_2D,
+ GL_TEXTURE_GEN_S,
+ GL_TEXTURE_GEN_T,
+ -1
+ );
+
+ if (is_deprecated) {
+ gl_deprecated();
+ }
+
+ return is_deprecated;
+}
+
+_GL_VOID USE_CAREFULLY_glDisable (GLenum cap)
+{
+ if (!disable_enable_check(cap)) {
+ glDisable(cap);
+ }
+}
+#define glDisable USE_CAREFULLY_glDisable
+
+_GL_VOID USE_CAREFULLY_glEnable (GLenum cap)
+{
+ if (!disable_enable_check(cap)) {
+ glEnable(cap);
+ }
+}
+#define glEnable USE_CAREFULLY_glEnable
+
+/**
+ * Hand written cases
+ */
+
+_GL_VOID DO_NOT_USE_glClientActiveTexture (GLenum texture) _GL_VOID_RET
+
+
+/**
+ * List automatically generated from `gl-deprecated.h` and `glew.h`
+ */
+
+/**
+ * ENUM values
+ */
+#define DO_NOT_USE_GL_CURRENT_FOG_COORDINATE 0
+#define DO_NOT_USE_GL_FOG_COORDINATE 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_ARRAY 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_POINTER 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_STRIDE 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_TYPE 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_SOURCE 0
+#define DO_NOT_USE_GL_POINT_SIZE_GRANULARITY 0
+#define DO_NOT_USE_GL_POINT_SIZE_RANGE 0
+#define DO_NOT_USE_GL_SOURCE0_ALPHA 0
+#define DO_NOT_USE_GL_SOURCE0_RGB 0
+#define DO_NOT_USE_GL_SOURCE1_ALPHA 0
+#define DO_NOT_USE_GL_SOURCE1_RGB 0
+#define DO_NOT_USE_GL_SOURCE2_ALPHA 0
+#define DO_NOT_USE_GL_SOURCE2_RGB 0
+
+/**
+ * Functions
+ */
+_GL_VOID DO_NOT_USE_glAccum (GLenum op, GLfloat value) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glAlphaFunc (GLenum func, GLclampf ref) _GL_VOID_RET
+_GL_BOOL DO_NOT_USE_glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences) _GL_BOOL_RET
+_GL_VOID DO_NOT_USE_glArrayElement (GLint i) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glBegin (GLenum mode) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glCallList (GLuint list) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glCallLists (GLsizei n, GLenum type, const void *lists) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glClearIndex (GLfloat c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glClipPlane (GLenum plane, const GLdouble *equation) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3b (GLbyte red, GLbyte green, GLbyte blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3bv (const GLbyte *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3d (GLdouble red, GLdouble green, GLdouble blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3f (GLfloat red, GLfloat green, GLfloat blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3i (GLint red, GLint green, GLint blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3s (GLshort red, GLshort green, GLshort blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3ub (GLubyte red, GLubyte green, GLubyte blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3ubv (const GLubyte *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3ui (GLuint red, GLuint green, GLuint blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3uiv (const GLuint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3us (GLushort red, GLushort green, GLushort blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3usv (const GLushort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4bv (const GLbyte *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4i (GLint red, GLint green, GLint blue, GLint alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4ubv (const GLubyte *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4uiv (const GLuint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4usv (const GLushort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColorMaterial (GLenum face, GLenum mode) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glDeleteLists (GLuint list, GLsizei range) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glDisableClientState (GLenum array) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEdgeFlag (GLboolean flag) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEdgeFlagPointer (GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEdgeFlagv (const GLboolean *flag) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEnableClientState (GLenum array) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEnd (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEndList (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord1d (GLdouble u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord1dv (const GLdouble *u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord1f (GLfloat u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord1fv (const GLfloat *u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord2d (GLdouble u, GLdouble v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord2dv (const GLdouble *u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord2f (GLfloat u, GLfloat v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord2fv (const GLfloat *u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalMesh1 (GLenum mode, GLint i1, GLint i2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalPoint1 (GLint i) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalPoint2 (GLint i, GLint j) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFogf (GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFogfv (GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFogi (GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFogiv (GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) _GL_VOID_RET
+_GL_UINT DO_NOT_USE_glGenLists (GLsizei range) _GL_UINT_RET
+_GL_VOID DO_NOT_USE_glGetClipPlane (GLenum plane, GLdouble *equation) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetLightfv (GLenum light, GLenum pname, GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetLightiv (GLenum light, GLenum pname, GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetMapdv (GLenum target, GLenum query, GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetMapfv (GLenum target, GLenum query, GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetMapiv (GLenum target, GLenum query, GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetMaterialiv (GLenum face, GLenum pname, GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetPixelMapfv (GLenum map, GLfloat *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetPixelMapuiv (GLenum map, GLuint *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetPixelMapusv (GLenum map, GLushort *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetPolygonStipple (GLubyte *mask) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetTexEnviv (GLenum target, GLenum pname, GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetTexGeniv (GLenum coord, GLenum pname, GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexMask (GLuint mask) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexPointer (GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexd (GLdouble c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexdv (const GLdouble *c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexf (GLfloat c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexfv (const GLfloat *c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexi (GLint c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexiv (const GLint *c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexs (GLshort c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexsv (const GLshort *c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexub (GLubyte c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexubv (const GLubyte *c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glInitNames (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glInterleavedArrays (GLenum format, GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_BOOL DO_NOT_USE_glIsList (GLuint list) _GL_BOOL_RET
+_GL_VOID DO_NOT_USE_glLightModelf (GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightModelfv (GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightModeli (GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightModeliv (GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightf (GLenum light, GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightfv (GLenum light, GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLighti (GLenum light, GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightiv (GLenum light, GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLineStipple (GLint factor, GLushort pattern) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glListBase (GLuint base) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLoadIdentity (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLoadMatrixd (const GLdouble *m) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLoadMatrixf (const GLfloat *m) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLoadName (GLuint name) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMapGrid1d (GLint un, GLdouble u1, GLdouble u2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMapGrid1f (GLint un, GLfloat u1, GLfloat u2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMaterialf (GLenum face, GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMaterialfv (GLenum face, GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMateriali (GLenum face, GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMaterialiv (GLenum face, GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMatrixMode (GLenum mode) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMultMatrixd (const GLdouble *m) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMultMatrixf (const GLfloat *m) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNewList (GLuint list, GLenum mode) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3bv (const GLbyte *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3i (GLint nx, GLint ny, GLint nz) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3s (GLshort nx, GLshort ny, GLshort nz) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormalPointer (GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPassThrough (GLfloat token) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelTransferf (GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelTransferi (GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelZoom (GLfloat xfactor, GLfloat yfactor) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPolygonStipple (const GLubyte *mask) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPopAttrib (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPopClientAttrib (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPopMatrix (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPopName (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPushAttrib (GLbitfield mask) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPushClientAttrib (GLbitfield mask) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPushMatrix (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPushName (GLuint name) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2d (GLdouble x, GLdouble y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2f (GLfloat x, GLfloat y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2i (GLint x, GLint y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2s (GLshort x, GLshort y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3d (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3f (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3i (GLint x, GLint y, GLint z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3s (GLshort x, GLshort y, GLshort z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4i (GLint x, GLint y, GLint z, GLint w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectdv (const GLdouble *v1, const GLdouble *v2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectfv (const GLfloat *v1, const GLfloat *v2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRecti (GLint x1, GLint y1, GLint x2, GLint y2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectiv (const GLint *v1, const GLint *v2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectsv (const GLshort *v1, const GLshort *v2) _GL_VOID_RET
+_GL_INT DO_NOT_USE_glRenderMode (GLenum mode) _GL_INT_RET
+_GL_VOID DO_NOT_USE_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glScaled (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glScalef (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glSelectBuffer (GLsizei size, GLuint *buffer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glShadeModel (GLenum mode) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1d (GLdouble s) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1f (GLfloat s) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1i (GLint s) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1s (GLshort s) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2d (GLdouble s, GLdouble t) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2f (GLfloat s, GLfloat t) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2i (GLint s, GLint t) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2s (GLshort s, GLshort t) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3d (GLdouble s, GLdouble t, GLdouble r) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3i (GLint s, GLint t, GLint r) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3s (GLshort s, GLshort t, GLshort r) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4i (GLint s, GLint t, GLint r, GLint q) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexEnvf (GLenum target, GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexEnvi (GLenum target, GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexEnviv (GLenum target, GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGend (GLenum coord, GLenum pname, GLdouble param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGendv (GLenum coord, GLenum pname, const GLdouble *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGenf (GLenum coord, GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGeni (GLenum coord, GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGeniv (GLenum coord, GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTranslated (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTranslatef (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2d (GLdouble x, GLdouble y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2f (GLfloat x, GLfloat y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2i (GLint x, GLint y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2s (GLshort x, GLshort y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3d (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3f (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3i (GLint x, GLint y, GLint z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3s (GLshort x, GLshort y, GLshort z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4i (GLint x, GLint y, GLint z, GLint w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertexPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET
+
+/**
+ * End of automatically generated list
+ */
+
+
+
+#undef _GL_BOOL
+#undef _GL_BOOL_RET
+#undef _GL_ENUM
+#undef _GL_ENUM_RET
+#undef _GL_INT
+#undef _GL_INT_RET
+#undef _GL_UINT
+#undef _GL_UINT_RET
+#undef _GL_VOID
+#undef _GL_VOID_RET
+
+#if defined(__GNUC__)
+# pragma GCC diagnostic pop
+#endif
+
+#endif /* __GPU_LEGACY_STUBS_H__ */
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index dbfcd4d1ea4..698f3ada2a3 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -43,30 +43,33 @@ extern "C" {
struct Image;
struct ImageUser;
+struct ListBase;
struct Material;
struct Object;
-struct Image;
struct Scene;
-struct SceneRenderLayer;
struct GPUVertexAttribs;
struct GPUNode;
struct GPUNodeLink;
struct GPUNodeStack;
struct GPUMaterial;
struct GPUTexture;
+struct GPUUniformBuffer;
struct GPULamp;
struct PreviewImage;
struct World;
+struct bNode;
+struct bNodeTree;
typedef struct GPUNode GPUNode;
typedef struct GPUNodeLink GPUNodeLink;
typedef struct GPUMaterial GPUMaterial;
-typedef struct GPULamp GPULamp;
+
typedef struct GPUParticleInfo GPUParticleInfo;
/* Functions to create GPU Materials nodes */
typedef enum GPUType {
+ /* Keep in sync with GPU_DATATYPE_STR */
/* The value indicates the number of elements in each type */
GPU_NONE = 0,
GPU_FLOAT = 1,
@@ -76,9 +79,16 @@ typedef enum GPUType {
GPU_MAT3 = 9,
GPU_MAT4 = 16,
+ /* Values not in GPU_DATATYPE_STR */
GPU_TEX2D = 1002,
- GPU_SHADOW2D = 1003,
- GPU_TEXCUBE = 1004,
+ GPU_TEX3D = 1003,
+ GPU_SHADOW2D = 1004,
+ GPU_TEXCUBE = 1005,
+
+ /* GLSL Struct types */
+ GPU_CLOSURE = 1006,
+
+ /* Opengl Attributes */
GPU_ATTRIB = 3001
} GPUType;
@@ -98,7 +108,9 @@ typedef enum GPUBuiltin {
GPU_PARTICLE_ANG_VELOCITY = (1 << 12),
GPU_LOC_TO_VIEW_MATRIX = (1 << 13),
GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14),
- GPU_OBJECT_INFO = (1 << 15)
+ GPU_OBJECT_INFO = (1 << 15),
+ GPU_VOLUME_DENSITY = (1 << 16),
+ GPU_VOLUME_FLAME = (1 << 17)
} GPUBuiltin;
typedef enum GPUOpenGLBuiltin {
@@ -141,6 +153,7 @@ typedef struct GPUNodeStack {
#define GPU_DYNAMIC_GROUP_MIST 0x00050000
#define GPU_DYNAMIC_GROUP_WORLD 0x00060000
#define GPU_DYNAMIC_GROUP_MAT 0x00070000
+#define GPU_DYNAMIC_UBO 0x00080000
typedef enum GPUDynamicType {
@@ -200,6 +213,7 @@ typedef enum GPUDynamicType {
GPUNodeLink *GPU_attribute(CustomDataType type, const char *name);
GPUNodeLink *GPU_uniform(float *num);
GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data);
+GPUNodeLink *GPU_uniform_buffer(float *num, GPUType gputype);
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data);
GPUNodeLink *GPU_cube_map(struct Image *ima, struct ImageUser *iuser, bool is_data);
GPUNodeLink *GPU_image_preview(struct PreviewImage *prv);
@@ -210,26 +224,36 @@ GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin);
void GPU_node_link_set_type(GPUNodeLink *link, GPUType type);
bool GPU_link(GPUMaterial *mat, const char *name, ...);
-bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...);
+bool GPU_stack_link(GPUMaterial *mat, struct bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...);
+GPUNodeLink *GPU_uniformbuffer_link_out(
+ struct GPUMaterial *mat, struct bNode *node,
+ struct GPUNodeStack *stack, const int index);
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link);
void GPU_material_enable_alpha(GPUMaterial *material);
GPUBuiltin GPU_get_material_builtins(GPUMaterial *material);
GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]);
+void GPU_material_sss_profile_create(GPUMaterial *material, float *radii, short *falloff_type, float *sharpness);
+struct GPUUniformBuffer *GPU_material_sss_profile_get(
+ GPUMaterial *material, int sample_ct, struct GPUTexture **tex_profile);
+
/* High level functions to create and use GPU materials */
GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo);
-
+GPUMaterial *GPU_material_from_nodetree_find(
+ struct ListBase *gpumaterials, const void *engine_type, int options);
+GPUMaterial *GPU_material_from_nodetree(
+ struct Scene *scene, struct bNodeTree *ntree, struct ListBase *gpumaterials, const void *engine_type, int options,
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines);
GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(void);
-bool GPU_lamp_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma);
void GPU_material_bind(
GPUMaterial *material, int oblay, int viewlay, double time, int mipmap,
- float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock);
+ float viewmat[4][4], float viewinv[4][4], float cameraborder[4]);
void GPU_material_bind_uniforms(
GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
float autobumpscale, GPUParticleInfo *pi, float object_info[3]);
@@ -237,6 +261,11 @@ void GPU_material_unbind(GPUMaterial *material);
bool GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
GPUMatType GPU_Material_get_type(GPUMaterial *material);
+struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
+
+struct GPUUniformBuffer *GPU_material_get_uniform_buffer(GPUMaterial *material);
+void GPU_material_create_uniform_buffer(GPUMaterial *material, struct ListBase *inputs);
+void GPU_material_uniform_buffer_tag_dirty(struct ListBase *gpumaterials);
void GPU_material_vertex_attributes(GPUMaterial *material,
struct GPUVertexAttribs *attrib);
@@ -244,6 +273,8 @@ void GPU_material_vertex_attributes(GPUMaterial *material,
bool GPU_material_do_color_management(GPUMaterial *mat);
bool GPU_material_use_new_shading_nodes(GPUMaterial *mat);
bool GPU_material_use_world_space_shading(GPUMaterial *mat);
+bool GPU_material_use_domain_surface(GPUMaterial *mat);
+bool GPU_material_use_domain_volume(GPUMaterial *mat);
/* Exported shading */
@@ -312,26 +343,8 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma);
void GPU_free_shader_export(GPUShaderExport *shader);
/* Lamps */
-
-GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
-void GPU_lamp_free(struct Object *ob);
-
-bool GPU_lamp_has_shadow_buffer(GPULamp *lamp);
-void GPU_lamp_update_buffer_mats(GPULamp *lamp);
-void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]);
-void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp);
-int GPU_lamp_shadow_buffer_type(GPULamp *lamp);
-int GPU_lamp_shadow_bind_code(GPULamp *lamp);
-float *GPU_lamp_dynpersmat(GPULamp *lamp);
-
-void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]);
-void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy);
-void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
- float coeff_const, float coeff_lin, float coeff_quad);
-void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend);
-int GPU_lamp_shadow_layer(GPULamp *lamp);
GPUNodeLink *GPU_lamp_get_data(
- GPUMaterial *mat, GPULamp *lamp,
+ GPUMaterial *mat, struct GPULamp *lamp,
GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy);
/* World */
diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h
new file mode 100644
index 00000000000..f22c0cd5c4d
--- /dev/null
+++ b/source/blender/gpu/GPU_matrix.h
@@ -0,0 +1,190 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Alexandr Kuznetsov, Jason Wilkins, Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/GPU_matrix.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_MATRIX_H__
+#define __GPU_MATRIX_H__
+
+#include "BLI_sys_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Gwn_ShaderInterface;
+
+void gpuMatrixReset(void); /* to Identity transform & empty stack */
+
+/* ModelView Matrix (2D or 3D) */
+
+void gpuPushMatrix(void); /* TODO: PushCopy vs PushIdentity? */
+void gpuPopMatrix(void);
+
+void gpuLoadIdentity(void);
+
+void gpuScaleUniform(float factor);
+
+
+/* 3D ModelView Matrix */
+
+void gpuLoadMatrix(const float m[4][4]);
+void gpuMultMatrix(const float m[4][4]);
+
+void gpuTranslate3f(float x, float y, float z);
+void gpuTranslate3fv(const float vec[3]);
+void gpuScale3f(float x, float y, float z);
+void gpuScale3fv(const float vec[3]);
+void gpuRotate3f(float deg, float x, float y, float z); /* axis of rotation should be a unit vector */
+void gpuRotate3fv(float deg, const float axis[3]); /* axis of rotation should be a unit vector */
+void gpuRotateAxis(float deg, char axis); /* TODO: enum for axis? */
+
+void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ);
+/* TODO: variant that takes eye[3], center[3], up[3] */
+
+
+/* 2D ModelView Matrix */
+
+void gpuTranslate2f(float x, float y);
+void gpuTranslate2fv(const float vec[2]);
+void gpuScale2f(float x, float y);
+void gpuScale2fv(const float vec[2]);
+void gpuRotate2D(float deg);
+
+/* Projection Matrix (2D or 3D) */
+
+void gpuPushProjectionMatrix(void);
+void gpuPopProjectionMatrix(void);
+
+/* 3D Projection Matrix */
+
+void gpuLoadIdentityProjectionMatrix(void);
+void gpuLoadProjectionMatrix(const float m[4][4]);
+
+void gpuOrtho(float left, float right, float bottom, float top, float near, float far);
+void gpuFrustum(float left, float right, float bottom, float top, float near, float far);
+void gpuPerspective(float fovy, float aspect, float near, float far);
+
+/* 3D Projection between Window and World Space */
+
+void gpuProject(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3]);
+bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3]);
+
+/* 2D Projection Matrix */
+
+void gpuOrtho2D(float left, float right, float bottom, float top);
+
+
+/* functions to get matrix values */
+const float (*gpuGetModelViewMatrix(float m[4][4]))[4];
+const float (*gpuGetProjectionMatrix(float m[4][4]))[4];
+const float (*gpuGetModelViewProjectionMatrix(float m[4][4]))[4];
+
+const float (*gpuGetNormalMatrix(float m[3][3]))[3];
+const float (*gpuGetNormalMatrixInverse(float m[3][3]))[3];
+
+
+/* set uniform values for currently bound shader */
+void gpuBindMatrices(const struct Gwn_ShaderInterface *);
+bool gpuMatricesDirty(void); /* since last bind */
+
+
+/* Python API needs to be able to inspect the stack so errors raise exceptions instead of crashing. */
+#ifdef USE_GPU_PY_MATRIX_API
+int GPU_matrix_stack_level_get_model_view(void);
+int GPU_matrix_stack_level_get_projection(void);
+/* static assert ensures this doesn't change! */
+#define GPU_PY_MATRIX_STACK_LEN 31
+#endif /* USE_GPU_PY_MATRIX_API */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifndef SUPPRESS_GENERIC_MATRIX_API
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+#define _GPU_MAT3_CONST_CAST(x) (_Generic((x), \
+ void *: (const float (*)[3])(x), \
+ float *: (const float (*)[3])(x), \
+ float [9]: (const float (*)[3])(x), \
+ float (*)[4]: (const float (*)[3])(x), \
+ float [4][4]: (const float (*)[3])(x), \
+ const void *: (const float (*)[3])(x), \
+ const float *: (const float (*)[3])(x), \
+ const float [9]: (const float (*)[3])(x), \
+ const float (*)[3]: (const float (*)[3])(x), \
+ const float [3][3]: (const float (*)[3])(x)) \
+)
+#define _GPU_MAT3_CAST(x) (_Generic((x), \
+ void *: (float (*)[3])(x), \
+ float *: (float (*)[3])(x), \
+ float [9]: (float (*)[3])(x), \
+ float (*)[3]: (float (*)[3])(x), \
+ float [3][3]: (float (*)[3])(x)) \
+)
+#define _GPU_MAT4_CONST_CAST(x) (_Generic((x), \
+ void *: (const float (*)[4])(x), \
+ float *: (const float (*)[4])(x), \
+ float [16]: (const float (*)[4])(x), \
+ float (*)[4]: (const float (*)[4])(x), \
+ float [4][4]: (const float (*)[4])(x), \
+ const void *: (const float (*)[4])(x), \
+ const float *: (const float (*)[4])(x), \
+ const float [16]: (const float (*)[4])(x), \
+ const float (*)[4]: (const float (*)[4])(x), \
+ const float [4][4]: (const float (*)[4])(x)) \
+)
+#define _GPU_MAT4_CAST(x) (_Generic((x), \
+ void *: (float (*)[4])(x), \
+ float *: (float (*)[4])(x), \
+ float [16]: (float (*)[4])(x), \
+ float (*)[4]: (float (*)[4])(x), \
+ float [4][4]: (float (*)[4])(x)) \
+)
+#else
+# define _GPU_MAT3_CONST_CAST(x) (const float (*)[3])(x)
+# define _GPU_MAT3_CAST(x) (float (*)[3])(x)
+# define _GPU_MAT4_CONST_CAST(x) (const float (*)[4])(x)
+# define _GPU_MAT4_CAST(x) (float (*)[4])(x)
+#endif /* C11 */
+
+/* make matrix inputs generic, to avoid warnings */
+# define gpuMultMatrix(x) gpuMultMatrix(_GPU_MAT4_CONST_CAST(x))
+# define gpuLoadMatrix(x) gpuLoadMatrix(_GPU_MAT4_CONST_CAST(x))
+# define gpuLoadProjectionMatrix(x) gpuLoadProjectionMatrix(_GPU_MAT4_CONST_CAST(x))
+# define gpuGetModelViewMatrix(x) gpuGetModelViewMatrix(_GPU_MAT4_CAST(x))
+# define gpuGetProjectionMatrix(x) gpuGetProjectionMatrix(_GPU_MAT4_CAST(x))
+# define gpuGetModelViewProjectionMatrix(x) gpuGetModelViewProjectionMatrix(_GPU_MAT4_CAST(x))
+# define gpuGetNormalMatrix(x) gpuGetNormalMatrix(_GPU_MAT3_CAST(x))
+# define gpuGetNormalMatrixInverse(x) gpuGetNormalMatrixInverse(_GPU_MAT3_CAST(x))
+#endif /* SUPPRESS_GENERIC_MATRIX_API */
+
+#endif /* __GPU_MATRIX_H__ */
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
index cf5b8bf7d8f..0617d58f3b6 100644
--- a/source/blender/gpu/GPU_select.h
+++ b/source/blender/gpu/GPU_select.h
@@ -56,4 +56,7 @@ void GPU_select_cache_begin(void);
void GPU_select_cache_load_id(void);
void GPU_select_cache_end(void);
+/* utilities */
+const uint *GPU_select_buffer_near(const uint *buffer, int hits);
+
#endif
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 5b94db6e120..f2119a117e5 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
@@ -54,29 +55,35 @@ GPUShader *GPU_shader_create(
const char *fragcode,
const char *geocode,
const char *libcode,
- const char *defines,
- int input, int output, int number);
+ const char *defines);
GPUShader *GPU_shader_create_ex(
const char *vertexcode,
const char *fragcode,
const char *geocode,
const char *libcode,
const char *defines,
- int input, int output, int number,
const int flags);
void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
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);
+
+void *GPU_fx_shader_get_interface(GPUShader *shader);
+void GPU_fx_shader_set_interface(GPUShader *shader, void *interface);
+
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
+int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin);
+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);
@@ -85,13 +92,102 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name);
/* Builtin/Non-generated shaders */
typedef enum GPUBuiltinShader {
- GPU_SHADER_VSM_STORE = 0,
- GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
- GPU_SHADER_SMOKE = 2,
- GPU_SHADER_SMOKE_FIRE = 3,
- GPU_SHADER_SMOKE_COBA = 4,
+ GPU_SHADER_VSM_STORE,
+ GPU_SHADER_SEP_GAUSSIAN_BLUR,
+ GPU_SHADER_SMOKE,
+ GPU_SHADER_SMOKE_FIRE,
+ GPU_SHADER_SMOKE_COBA,
+
+ /* specialized drawing */
+ GPU_SHADER_TEXT,
+ GPU_SHADER_EDGES_FRONT_BACK_PERSP,
+ GPU_SHADER_EDGES_FRONT_BACK_ORTHO,
+ GPU_SHADER_EDGES_OVERLAY_SIMPLE,
+ GPU_SHADER_EDGES_OVERLAY,
+ GPU_SHADER_KEYFRAME_DIAMOND,
+ GPU_SHADER_SIMPLE_LIGHTING,
+ GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR,
+ GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR,
+ GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA,
+ /* 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_IMAGE_ALPHA_COLOR,
+ GPU_SHADER_2D_CHECKER,
+ GPU_SHADER_2D_DIAG_STRIPES,
+ /* for simple 3D drawing */
+ GPU_SHADER_3D_UNIFORM_COLOR,
+ GPU_SHADER_3D_UNIFORM_COLOR_U32,
+ GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE,
+ GPU_SHADER_3D_FLAT_COLOR,
+ GPU_SHADER_3D_FLAT_COLOR_U32, /* use for select-id's */
+ GPU_SHADER_3D_SMOOTH_COLOR,
+ GPU_SHADER_3D_DEPTH_ONLY,
+ GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR,
+ /* basic image drawing */
+ GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB,
+ GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR,
+ GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR,
+ GPU_SHADER_3D_IMAGE_MODULATE_ALPHA,
+ GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA,
+ GPU_SHADER_3D_IMAGE_DEPTH,
+ /* stereo 3d */
+ GPU_SHADER_2D_IMAGE_INTERLACE,
+ /* points */
+ GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR,
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA,
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA,
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA,
+ GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR,
+ GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR,
+ GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR,
+ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA,
+ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA,
+ GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR,
+ GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR,
+ /* lines */
+ GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR,
+ GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR,
+ /* lamp drawing */
+ GPU_SHADER_3D_GROUNDPOINT,
+ GPU_SHADER_3D_GROUNDLINE,
+ GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR,
+ /* bone drawing */
+ GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR,
+ GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR,
+ /* camera drawing */
+ GPU_SHADER_CAMERA,
+ /* distance in front of objects */
+ GPU_SHADER_DISTANCE_LINES,
+ /* axis name */
+ GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS,
+ GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED,
+ /* instance */
+ GPU_SHADER_INSTANCE_UNIFORM_COLOR,
+ GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, /* Uniformly scaled */
+ GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE,
+ GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR,
+
+ GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID,
+ GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE,
+
+ GPU_SHADER_3D_INSTANCE_MBALL_HELPERS,
+
+ GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
} GPUBuiltinShader;
+/* Keep these in sync with:
+ * gpu_shader_image_interlace_frag.glsl
+ * gpu_shader_image_rect_interlace_frag.glsl
+ **/
+typedef enum GPUInterlaceShader {
+ GPU_SHADER_INTERLACE_ROW = 0,
+ GPU_SHADER_INTERLACE_COLUMN = 1,
+ GPU_SHADER_INTERLACE_CHECKER = 2,
+} GPUInterlaceShader;
+
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 756fe79151b..82e215f6fae 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -55,25 +55,121 @@ 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_RGBA32F,
+ GPU_RGBA16F,
+ GPU_RGBA8,
+ GPU_RG32F,
+ GPU_RG16F,
+ GPU_R32F,
+ GPU_R16F,
+ GPU_RG8,
+ GPU_R8,
+#if 0
+ 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_RG8I,
+ GPU_RG8UI,
+ GPU_R32I,
+ GPU_R32UI,
+ GPU_R16I,
+ GPU_R16UI,
+ GPU_R16,
+ GPU_R8I,
+ GPU_R8UI,
+#endif
+
+ /* Special formats texture & renderbuffer */
+#if 0
+ GPU_RGB10_A2,
+ GPU_RGB10_A2UI,
+ GPU_DEPTH32F_STENCIL8,
+#endif
+ GPU_R11F_G11F_B10F,
+ GPU_DEPTH24_STENCIL8,
+
+ /* Texture only format */
+ GPU_RGB16F,
+#if 0
+ GPU_RGBA16_SNORM,
+ GPU_RGBA8_SNORM,
+ GPU_RGB32F,
+ GPU_RGB32I,
+ GPU_RGB32UI,
+ GPU_RGB16_SNORM,
+ 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;
+
+unsigned int GPU_texture_memory_usage_get(void);
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_custom(
+ int w, int h, int d, int channels, GPUTextureFormat data_type, 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_cube_custom(
+ int w, 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_with_stencil(int w, int h, char err_out[256]);
GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]);
+GPUTexture *GPU_texture_create_depth_with_stencil_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_texture_update(GPUTexture *tex, const float *pixels);
+
void GPU_invalid_tex_init(void);
void GPU_invalid_tex_bind(int mode);
void GPU_invalid_tex_free(void);
@@ -81,12 +177,15 @@ 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_generate_mipmap(GPUTexture *tex);
+void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare);
+void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter);
+void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, 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);
@@ -95,7 +194,9 @@ void GPU_texture_framebuffer_set(GPUTexture *tex, struct GPUFrameBuffer *fb, int
int GPU_texture_target(const GPUTexture *tex);
int GPU_texture_width(const GPUTexture *tex);
int GPU_texture_height(const GPUTexture *tex);
-int GPU_texture_depth(const GPUTexture *tex);
+int GPU_texture_format(const GPUTexture *tex);
+bool GPU_texture_depth(const GPUTexture *tex);
+bool GPU_texture_stencil(const GPUTexture *tex);
int GPU_texture_opengl_bindcode(const GPUTexture *tex);
#ifdef __cplusplus
diff --git a/source/blender/gpu/GPU_uniformbuffer.h b/source/blender/gpu/GPU_uniformbuffer.h
new file mode 100644
index 00000000000..c2480f8ba03
--- /dev/null
+++ b/source/blender/gpu/GPU_uniformbuffer.h
@@ -0,0 +1,59 @@
+/*
+ * ***** 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
+ */
+
+#ifndef __GPU_UNIFORMBUFFER_H__
+#define __GPU_UNIFORMBUFFER_H__
+
+struct ListBase;
+
+typedef struct GPUUniformBuffer GPUUniformBuffer;
+typedef struct GPUUniformBufferDynamicItem GPUUniformBufferDynamicItem;
+
+GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256]);
+GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(struct ListBase *inputs, char err_out[256]);
+
+void GPU_uniformbuffer_free(GPUUniformBuffer *ubo);
+
+void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data);
+void GPU_uniformbuffer_dynamic_update(GPUUniformBuffer *ubo_);
+
+void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number);
+void GPU_uniformbuffer_unbind(GPUUniformBuffer *ubo);
+
+int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo);
+
+bool GPU_uniformbuffer_is_empty(GPUUniformBuffer *ubo);
+bool GPU_uniformbuffer_is_dirty(GPUUniformBuffer *ubo);
+void GPU_uniformbuffer_tag_dirty(GPUUniformBuffer *ubo);
+
+#define GPU_UBO_BLOCK_NAME "nodeTree"
+
+#endif /* __GPU_UNIFORMBUFFER_H__ */
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
new file mode 100644
index 00000000000..f2bb05a6d1e
--- /dev/null
+++ b/source/blender/gpu/GPU_viewport.h
@@ -0,0 +1,135 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_viewport.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_VIEWPORT_H__
+#define __GPU_VIEWPORT_H__
+
+#include <stdbool.h>
+
+#include "DNA_vec_types.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_texture.h"
+
+#define GPU_INFO_SIZE 512 /* IMA_MAX_RENDER_TEXT */
+
+typedef struct GPUViewport GPUViewport;
+
+/* Contains memory pools informations */
+typedef struct ViewportMemoryPool {
+ struct BLI_mempool *calls;
+ struct BLI_mempool *calls_generate;
+ struct BLI_mempool *calls_dynamic;
+ struct BLI_mempool *shgroups;
+ struct BLI_mempool *uniforms;
+ struct BLI_mempool *attribs;
+ struct BLI_mempool *passes;
+} ViewportMemoryPool;
+
+/* All FramebufferLists are just the same pointers with different names */
+typedef struct FramebufferList {
+ struct GPUFrameBuffer *framebuffers[0];
+} FramebufferList;
+
+typedef struct TextureList {
+ struct GPUTexture *textures[0];
+} TextureList;
+
+typedef struct PassList {
+ struct DRWPass *passes[0];
+} PassList;
+
+typedef struct StorageList {
+ void *storage[0]; /* custom structs from the engine */
+} StorageList;
+
+typedef struct ViewportEngineData {
+ void *engine_type;
+
+ FramebufferList *fbl;
+ TextureList *txl;
+ PassList *psl;
+ StorageList *stl;
+ char info[GPU_INFO_SIZE];
+
+ /* we may want to put this elsewhere */
+ struct DRWTextStore *text_draw_cache;
+
+ /* Profiling data */
+ double init_time;
+ double cache_time;
+ double render_time;
+ double background_time;
+} ViewportEngineData;
+
+typedef struct ViewportEngineData_Info {
+ int fbl_len;
+ int txl_len;
+ int psl_len;
+ int stl_len;
+} ViewportEngineData_Info;
+
+GPUViewport *GPU_viewport_create(void);
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect);
+void GPU_viewport_unbind(GPUViewport *viewport);
+void GPU_viewport_free(GPUViewport *viewport);
+
+GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs);
+void GPU_viewport_clear_from_offscreen(GPUViewport *viewport);
+
+ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport);
+
+void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type);
+void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type);
+void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport);
+void *GPU_viewport_texture_list_get(GPUViewport *viewport);
+void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]);
+void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]);
+
+void GPU_viewport_tag_update(GPUViewport *viewport);
+bool GPU_viewport_do_update(GPUViewport *viewport);
+
+/* Texture pool */
+GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine, int width, int height, int channels, int format);
+
+bool GPU_viewport_engines_data_validate(GPUViewport *viewport, unsigned int hash);
+void GPU_viewport_cache_release(GPUViewport *viewport);
+
+/* 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);
+void GPU_viewport_debug_depth_store(GPUViewport *viewport, const int x, const int y);
+void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, const float zfar);
+bool GPU_viewport_debug_depth_is_valid(GPUViewport *viewport);
+int GPU_viewport_debug_depth_width(const GPUViewport *viewport);
+int GPU_viewport_debug_depth_height(const GPUViewport *viewport);
+
+#endif // __GPU_VIEWPORT_H__
diff --git a/source/blender/gpu/intern/gpu_basic_shader.c b/source/blender/gpu/intern/gpu_basic_shader.c
index 8505bd847a0..620a06ae606 100644
--- a/source/blender/gpu/intern/gpu_basic_shader.c
+++ b/source/blender/gpu/intern/gpu_basic_shader.c
@@ -140,114 +140,6 @@ const GLubyte stipple_checker_8px[128] = {
0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
-const GLubyte stipple_interlace_row[128] = {
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};
-
-const GLubyte stipple_interlace_row_swap[128] = {
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};
-
-const GLubyte stipple_interlace_column[128] = {
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
-
-const GLubyte stipple_interlace_column_swap[128] = {
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
-
-const GLubyte stipple_interlace_checker[128] = {
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa};
-
-const GLubyte stipple_interlace_checker_swap[128] = {
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55};
-
const GLubyte stipple_hexagon[128] = {
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
@@ -267,24 +159,6 @@ const GLubyte stipple_hexagon[128] = {
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22};
/* ********************************************* */
-/* GLSL State */
-
-static bool USE_GLSL = false;
-
-/**
- * \note this isn't part of the basic shader API,
- * only set from the command line once on startup.
- */
-void GPU_basic_shader_use_glsl_set(bool enabled)
-{
- USE_GLSL = enabled;
-}
-
-bool GPU_basic_shader_use_glsl_get(void)
-{
- return USE_GLSL;
-}
-
/* Init / exit */
void GPU_basic_shaders_init(void)
@@ -316,31 +190,6 @@ static bool solid_compatible_lighting(void)
return ((directional & enabled) == enabled);
}
-#if 0
-static int detect_options()
-{
- GLint two_sided;
- int options = 0;
-
- if (glIsEnabled(GL_TEXTURE_2D))
- options |= GPU_SHADER_TEXTURE_2D;
- if (glIsEnabled(GL_TEXTURE_RECTANGLE))
- options |= GPU_SHADER_TEXTURE_RECT;
- GPU_SHADER_TEXTURE_RECT
- if (glIsEnabled(GL_COLOR_MATERIAL))
- options |= GPU_SHADER_USE_COLOR;
-
- if (glIsEnabled(GL_LIGHTING))
- options |= GPU_SHADER_LIGHTING;
-
- glGetIntegerv(GL_LIGHT_MODEL_TWO_SIDE, &two_sided);
- if (two_sided == GL_TRUE)
- options |= GPU_SHADER_TWO_SIDED;
-
- return options;
-}
-#endif
-
static GPUShader *gpu_basic_shader(int options)
{
/* glsl code */
@@ -388,7 +237,7 @@ static GPUShader *gpu_basic_shader(int options)
datatoc_gpu_shader_basic_frag_glsl,
geom_glsl,
NULL,
- defines, 0, 0, 0);
+ defines);
if (shader) {
/* set texture map to first texture unit */
@@ -420,102 +269,16 @@ static void gpu_basic_shader_uniform_autoset(GPUShader *shader, int options)
void GPU_basic_shader_bind(int options)
{
- if (USE_GLSL) {
- if (options) {
- const int bound_options = GPU_MATERIAL_STATE.bound_options;
-
- /* texture options need to be set for basic shader too */
- if (options & GPU_SHADER_TEXTURE_2D) {
- glEnable(GL_TEXTURE_2D);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_2D) {
- glDisable(GL_TEXTURE_2D);
- }
-
- if (options & GPU_SHADER_TEXTURE_RECT) {
- glEnable(GL_TEXTURE_RECTANGLE);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_RECT) {
- glDisable(GL_TEXTURE_RECTANGLE);
- }
-
- GPUShader *shader = gpu_basic_shader(options);
+ if (options) {
+ GPUShader *shader = gpu_basic_shader(options);
- if (shader) {
- GPU_shader_bind(shader);
- gpu_basic_shader_uniform_autoset(shader, options);
- }
- }
- else {
- GPU_shader_unbind();
+ if (shader) {
+ GPU_shader_bind(shader);
+ gpu_basic_shader_uniform_autoset(shader, options);
}
}
else {
- const int bound_options = GPU_MATERIAL_STATE.bound_options;
-
- if (options & GPU_SHADER_LIGHTING) {
- glEnable(GL_LIGHTING);
-
- if (options & GPU_SHADER_USE_COLOR)
- glEnable(GL_COLOR_MATERIAL);
- else
- glDisable(GL_COLOR_MATERIAL);
-
- if (options & GPU_SHADER_TWO_SIDED)
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
- else
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
- }
- else if (bound_options & GPU_SHADER_LIGHTING) {
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
- }
-
- if (options & GPU_SHADER_TEXTURE_2D) {
- GLint env_mode = (options & (GPU_SHADER_USE_COLOR | GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE;
- glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_2D) {
- if ((options & GPU_SHADER_TEXTURE_RECT) == 0) {
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- }
- glDisable(GL_TEXTURE_2D);
- }
-
- if (options & GPU_SHADER_TEXTURE_RECT) {
- GLint env_mode = (options & (GPU_SHADER_USE_COLOR | GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE;
- glEnable(GL_TEXTURE_RECTANGLE);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_RECT) {
- if ((options & GPU_SHADER_TEXTURE_2D) == 0) {
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- }
- glDisable(GL_TEXTURE_RECTANGLE);
- }
-
- if ((options & GPU_SHADER_LINE) && (options & GPU_SHADER_STIPPLE)) {
- glEnable(GL_LINE_STIPPLE);
- }
- else if ((bound_options & GPU_SHADER_LINE) && (bound_options & GPU_SHADER_STIPPLE)) {
- glDisable(GL_LINE_STIPPLE);
- }
-
- if (((options & GPU_SHADER_LINE) == 0) && (options & GPU_SHADER_STIPPLE)) {
- glEnable(GL_POLYGON_STIPPLE);
- }
- else if (((bound_options & GPU_SHADER_LINE) == 0) && (bound_options & GPU_SHADER_STIPPLE)) {
- glDisable(GL_POLYGON_STIPPLE);
- }
-
- if (options & GPU_SHADER_FLAT_NORMAL) {
- glShadeModel(GL_FLAT);
- }
- else if (bound_options & GPU_SHADER_FLAT_NORMAL) {
- glShadeModel(GL_SMOOTH);
- }
+ GPU_shader_unbind();
}
GPU_MATERIAL_STATE.bound_options = options;
@@ -544,175 +307,37 @@ void GPU_basic_shader_colors(
const float diffuse[3], const float specular[3],
int shininess, float alpha)
{
- float gl_diffuse[4], gl_specular[4];
-
- if (diffuse)
- copy_v3_v3(gl_diffuse, diffuse);
- else
- zero_v3(gl_diffuse);
- gl_diffuse[3] = alpha;
-
- if (specular)
- copy_v3_v3(gl_specular, specular);
- else
- zero_v3(gl_specular);
- gl_specular[3] = 1.0f;
-
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gl_diffuse);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, gl_specular);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128));
+ UNUSED_VARS(diffuse, specular, shininess, alpha);
+ return;
}
void GPU_basic_shader_light_set(int light_num, GPULightData *light)
{
- int light_bit = (1 << light_num);
-
- /* note that light position is affected by the current modelview matrix! */
-
- GPU_MATERIAL_STATE.lights_enabled &= ~light_bit;
- GPU_MATERIAL_STATE.lights_directional &= ~light_bit;
-
- if (light) {
- float position[4], diffuse[4], specular[4];
-
- glEnable(GL_LIGHT0 + light_num);
-
- /* position */
- if (light->type == GPU_LIGHT_SUN) {
- copy_v3_v3(position, light->direction);
- position[3] = 0.0f;
- }
- else {
- copy_v3_v3(position, light->position);
- position[3] = 1.0f;
- }
- glLightfv(GL_LIGHT0 + light_num, GL_POSITION, position);
-
- /* energy */
- copy_v3_v3(diffuse, light->diffuse);
- copy_v3_v3(specular, light->specular);
- diffuse[3] = 1.0f;
- specular[3] = 1.0f;
- glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, diffuse);
- glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, specular);
-
- /* attenuation */
- if (light->type == GPU_LIGHT_SUN) {
- glLightf(GL_LIGHT0 + light_num, GL_CONSTANT_ATTENUATION, 1.0f);
- glLightf(GL_LIGHT0 + light_num, GL_LINEAR_ATTENUATION, 0.0f);
- glLightf(GL_LIGHT0 + light_num, GL_QUADRATIC_ATTENUATION, 0.0f);
- }
- else {
- glLightf(GL_LIGHT0 + light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation);
- glLightf(GL_LIGHT0 + light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation);
- glLightf(GL_LIGHT0 + light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation);
- }
-
- /* spot */
- glLightfv(GL_LIGHT0 + light_num, GL_SPOT_DIRECTION, light->direction);
- if (light->type == GPU_LIGHT_SPOT) {
- glLightf(GL_LIGHT0 + light_num, GL_SPOT_CUTOFF, light->spot_cutoff);
- glLightf(GL_LIGHT0 + light_num, GL_SPOT_EXPONENT, light->spot_exponent);
- }
- else {
- glLightf(GL_LIGHT0 + light_num, GL_SPOT_CUTOFF, 180.0f);
- glLightf(GL_LIGHT0 + light_num, GL_SPOT_EXPONENT, 0.0f);
- }
-
- GPU_MATERIAL_STATE.lights_enabled |= light_bit;
- if (position[3] == 0.0f)
- GPU_MATERIAL_STATE.lights_directional |= light_bit;
- }
- else {
- /* TODO(sergey): Needs revisit. */
- if (USE_GLSL || true) {
- /* glsl shader needs these zero to skip them */
- const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
-
- glLightfv(GL_LIGHT0 + light_num, GL_POSITION, zero);
- glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, zero);
- glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, zero);
- }
-
- glDisable(GL_LIGHT0 + light_num);
- }
+ UNUSED_VARS(light_num, light);
+ return;
}
void GPU_basic_shader_light_set_viewer(bool local)
{
- glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (local) ? GL_TRUE: GL_FALSE);
+ UNUSED_VARS(local);
+ return;
}
void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id)
{
- if (USE_GLSL) {
- glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id);
- }
- else {
- switch (stipple_id) {
- case GPU_SHADER_STIPPLE_HALFTONE:
- glPolygonStipple(stipple_halftone);
- return;
- case GPU_SHADER_STIPPLE_QUARTTONE:
- glPolygonStipple(stipple_quarttone);
- return;
- case GPU_SHADER_STIPPLE_CHECKER_8PX:
- glPolygonStipple(stipple_checker_8px);
- return;
- case GPU_SHADER_STIPPLE_HEXAGON:
- glPolygonStipple(stipple_hexagon);
- return;
- case GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP:
- glPolygonStipple(stipple_diag_stripes_neg);
- return;
- case GPU_SHADER_STIPPLE_DIAG_STRIPES:
- glPolygonStipple(stipple_diag_stripes_pos);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW:
- glPolygonStipple(stipple_interlace_row);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW_SWAP:
- glPolygonStipple(stipple_interlace_row_swap);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN:
- glPolygonStipple(stipple_interlace_column);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN_SWAP:
- glPolygonStipple(stipple_interlace_column_swap);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER:
- glPolygonStipple(stipple_interlace_checker);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER_SWAP:
- glPolygonStipple(stipple_interlace_checker_swap);
- return;
- default:
- glPolygonStipple(stipple_hexagon);
- return;
- }
- }
+ glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id);
}
void GPU_basic_shader_line_width(float line_width)
{
- if (USE_GLSL) {
- GPU_MATERIAL_STATE.line_width = line_width;
- if (GPU_MATERIAL_STATE.bound_options & GPU_SHADER_LINE) {
- glUniform1f(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "line_width"), line_width);
- }
- }
- else {
- glLineWidth(line_width);
+ GPU_MATERIAL_STATE.line_width = line_width;
+ if (GPU_MATERIAL_STATE.bound_options & GPU_SHADER_LINE) {
+ glUniform1f(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "line_width"), line_width);
}
}
void GPU_basic_shader_line_stipple(GLint stipple_factor, GLushort stipple_pattern)
{
- if (USE_GLSL) {
- glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_factor"), stipple_factor);
- glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_pattern"), stipple_pattern);
- }
- else {
- glLineStipple(stipple_factor, stipple_pattern);
- }
+ glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_factor"), stipple_factor);
+ glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_pattern"), stipple_pattern);
}
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
new file mode 100644
index 00000000000..5d347fc80e8
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -0,0 +1,171 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "GPU_batch.h"
+#include "gpu_shader_private.h"
+
+void GWN_batch_program_set_builtin(Gwn_Batch *batch, GPUBuiltinShader shader_id)
+{
+ GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
+ GWN_batch_program_set(batch, shader->program, shader->interface);
+}
+
+static Gwn_Batch *sphere_high = NULL;
+static Gwn_Batch *sphere_med = NULL;
+static Gwn_Batch *sphere_low = NULL;
+static Gwn_Batch *sphere_wire_low = NULL;
+static Gwn_Batch *sphere_wire_med = NULL;
+
+static Gwn_VertBuf *vbo;
+static Gwn_VertFormat 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);
+
+ GWN_vertbuf_attr_set(vbo, nor_id, vert, pos);
+ GWN_vertbuf_attr_set(vbo, pos_id, vert++, pos);
+}
+
+/* Replacement for gluSphere */
+static Gwn_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 = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(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 + lat_inc, lon + lon_inc);
+ batch_sphere_lat_lon_vert(lat + lat_inc, lon);
+ batch_sphere_lat_lon_vert(lat, lon);
+ }
+
+ if (j != 0) { /* Pole */
+ batch_sphere_lat_lon_vert(lat, lon + lon_inc);
+ batch_sphere_lat_lon_vert(lat + lat_inc, lon + lon_inc);
+ batch_sphere_lat_lon_vert(lat, lon);
+ }
+ }
+ }
+
+ return GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+}
+
+static Gwn_Batch *batch_sphere_wire(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 = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, (lat_res * lon_res * 2) + ((lat_res - 1) * lon_res * 2));
+ 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) {
+ batch_sphere_lat_lon_vert(lat + lat_inc, lon);
+ batch_sphere_lat_lon_vert(lat, lon);
+
+ if (j != lat_res - 1) { /* Pole */
+ batch_sphere_lat_lon_vert(lat + lat_inc, lon + lon_inc);
+ batch_sphere_lat_lon_vert(lat + lat_inc, lon);
+ }
+ }
+ }
+
+ return GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+}
+
+Gwn_Batch *GPU_batch_preset_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;
+}
+
+Gwn_Batch *GPU_batch_preset_sphere_wire(int lod)
+{
+ BLI_assert(lod >= 0 && lod <= 1);
+
+ if (lod == 0)
+ return sphere_wire_low;
+ else
+ return sphere_wire_med;
+}
+
+void gpu_batch_init(void)
+{
+ /* Hard coded resolution */
+ sphere_low = batch_sphere(8, 16);
+ sphere_med = batch_sphere(16, 10);
+ sphere_high = batch_sphere(32, 24);
+
+ sphere_wire_low = batch_sphere_wire(6, 8);
+ sphere_wire_med = batch_sphere_wire(8, 16);
+}
+
+void gpu_batch_exit(void)
+{
+ GWN_batch_discard(sphere_low);
+ GWN_batch_discard(sphere_med);
+ GWN_batch_discard(sphere_high);
+ GWN_batch_discard(sphere_wire_low);
+ GWN_batch_discard(sphere_wire_med);
+}
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index e288c74fee6..3a6b0a2a72d 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -35,8 +35,6 @@
#include <stddef.h>
#include <string.h>
-#include "GPU_glew.h"
-
#include "MEM_guardedalloc.h"
#include "BLI_bitmap.h"
@@ -55,10 +53,14 @@
#include "GPU_buffers.h"
#include "GPU_draw.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_batch.h"
#include "bmesh.h"
+/* TODO: gawain support for baseelemarray */
+// #define USE_BASE_ELEM
+
typedef enum {
GPU_BUFFER_VERTEX_STATE = (1 << 0),
GPU_BUFFER_NORMAL_STATE = (1 << 1),
@@ -106,9 +108,8 @@ static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
/* multires global buffer, can be used for many grids having the same grid size */
typedef struct GridCommonGPUBuffer {
- GPUBuffer *mres_buffer;
+ Gwn_IndexBuf *mres_buffer;
int mres_prev_gridsize;
- GLenum mres_prev_index_type;
unsigned mres_prev_totquad;
} GridCommonGPUBuffer;
@@ -943,26 +944,12 @@ void GPU_buffer_draw_elements(GPUBuffer *UNUSED(elements), unsigned int mode, in
/* XXX: the rest of the code in this file is used for optimized PBVH
* drawing and doesn't interact at all with the buffer code above */
-/* Convenience struct for building the VBO. */
-typedef struct {
- float co[3];
- short no[3];
-
- /* inserting this to align the 'color' field to a four-byte
- * boundary; drastically increases viewport performance on my
- * drivers (Gallium/Radeon) --nicholasbishop */
- char pad[2];
-
- unsigned char color[3];
-} VertexBufferFormat;
-
struct GPU_PBVH_Buffers {
- /* opengl buffer handles */
- GPUBuffer *vert_buf, *index_buf, *index_buf_fast;
- GLenum index_type;
+ Gwn_IndexBuf *index_buf, *index_buf_fast;
+ Gwn_VertBuf *vert_buf;
- int *baseelemarray;
- void **baseindex;
+ Gwn_Batch *triangles;
+ Gwn_Batch *triangles_fast;
/* mesh pointers in case buffer allocation fails */
const MPoly *mpoly;
@@ -997,6 +984,39 @@ struct GPU_PBVH_Buffers {
float diffuse_color[4];
};
+typedef struct {
+ uint pos, nor, col;
+} VertexBufferAttrID;
+
+static void gpu_pbvh_vert_format_init__gwn(Gwn_VertFormat *format, VertexBufferAttrID *vbo_id)
+{
+ vbo_id->pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ vbo_id->nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ vbo_id->col = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+}
+
+static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers)
+{
+ /* force flushing to the GPU */
+ if (buffers->vert_buf->data) {
+ GWN_vertbuf_use(buffers->vert_buf);
+ }
+
+ GWN_BATCH_DISCARD_SAFE(buffers->triangles);
+ buffers->triangles = GWN_batch_create(
+ GWN_PRIM_TRIS, buffers->vert_buf,
+ /* can be NULL */
+ buffers->index_buf);
+
+ GWN_BATCH_DISCARD_SAFE(buffers->triangles_fast);
+ if (buffers->index_buf_fast) {
+ buffers->triangles_fast = GWN_batch_create(
+ GWN_PRIM_TRIS, buffers->vert_buf,
+ /* can be NULL */
+ buffers->index_buf_fast);
+ }
+}
+
static float gpu_color_from_mask(float mask)
{
return 1.0f - mask * 0.75f;
@@ -1035,9 +1055,6 @@ void GPU_pbvh_mesh_buffers_update(
const int *vert_indices, int totvert, const float *vmask,
const int (*face_vert_indices)[3], bool show_diffuse_color)
{
- VertexBufferFormat *vert_data;
- int i;
-
buffers->vmask = vmask;
buffers->show_diffuse_color = show_diffuse_color;
buffers->use_matcaps = GPU_material_use_matcaps_get();
@@ -1061,35 +1078,39 @@ void GPU_pbvh_mesh_buffers_update(
rgba_float_to_uchar(diffuse_color_ub, diffuse_color);
/* Build VBO */
- if (buffers->vert_buf)
- GPU_buffer_free(buffers->vert_buf);
- buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totelem);
- vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY);
+ GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
+
+ /* match 'VertexBufferFormat' */
+ Gwn_VertFormat format = {0};
+ VertexBufferAttrID vbo_id;
+ gpu_pbvh_vert_format_init__gwn(&format, &vbo_id);
- if (vert_data) {
+ buffers->vert_buf = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(buffers->vert_buf, totelem);
+
+ if (buffers->vert_buf->data) {
/* Vertex data is shared if smooth-shaded, but separate
* copies are made for flat shading because normals
* shouldn't be shared. */
if (buffers->smooth) {
- for (i = 0; i < totvert; ++i) {
+ for (uint i = 0; i < totvert; ++i) {
const MVert *v = &mvert[vert_indices[i]];
- VertexBufferFormat *out = vert_data + i;
-
- copy_v3_v3(out->co, v->co);
- memcpy(out->no, v->no, sizeof(short) * 3);
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.pos, i, v->co);
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, i, v->no);
}
- for (i = 0; i < buffers->face_indices_len; i++) {
+ for (uint i = 0; i < buffers->face_indices_len; i++) {
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
for (uint j = 0; j < 3; j++) {
- VertexBufferFormat *out = vert_data + face_vert_indices[i][j];
-
+ int vidx = face_vert_indices[i][j];
if (vmask) {
- uint v_index = buffers->mloop[lt->tri[j]].v;
- gpu_color_from_mask_copy(vmask[v_index], diffuse_color, out->color);
+ int v_index = buffers->mloop[lt->tri[j]].v;
+ uchar color_ub[3];
+ gpu_color_from_mask_copy(vmask[v_index], diffuse_color, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vidx, color_ub);
}
else {
- copy_v3_v3_uchar(out->color, diffuse_color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vidx, diffuse_color_ub);
}
}
}
@@ -1098,8 +1119,9 @@ void GPU_pbvh_mesh_buffers_update(
/* calculate normal for each polygon only once */
unsigned int mpoly_prev = UINT_MAX;
short no[3];
+ int vbo_index = 0;
- for (i = 0; i < buffers->face_indices_len; ++i) {
+ for (uint i = 0; i < buffers->face_indices_len; i++) {
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
const unsigned int vtri[3] = {
buffers->mloop[lt->tri[0]].v,
@@ -1130,22 +1152,20 @@ void GPU_pbvh_mesh_buffers_update(
for (uint j = 0; j < 3; j++) {
const MVert *v = &mvert[vtri[j]];
- VertexBufferFormat *out = vert_data;
- copy_v3_v3(out->co, v->co);
- copy_v3_v3_short(out->no, no);
- copy_v3_v3_uchar(out->color, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.pos, vbo_index, v->co);
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, vbo_index, no);
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vbo_index, color_ub);
- vert_data++;
+ vbo_index++;
}
}
}
- GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
+ gpu_pbvh_batch_init(buffers);
}
else {
- GPU_buffer_free(buffers->vert_buf);
- buffers->vert_buf = NULL;
+ GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
}
}
@@ -1160,12 +1180,17 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(
const int face_indices_len)
{
GPU_PBVH_Buffers *buffers;
- unsigned short *tri_data;
- int i, j, tottri;
+ int i, tottri;
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
- buffers->index_type = GL_UNSIGNED_SHORT;
+
+ /* smooth or flat for all */
+#if 0
buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH;
+#else
+ /* for DrawManager we dont support mixed smooth/flat */
+ buffers->smooth = (mpoly[0].flag & ME_SMOOTH) != 0;
+#endif
buffers->show_diffuse_color = false;
buffers->use_matcaps = false;
@@ -1193,35 +1218,28 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(
* shading requires separate vertex normals so an index buffer is
* can't be used there. */
if (buffers->smooth) {
- buffers->index_buf = GPU_buffer_alloc(sizeof(unsigned short) * tottri * 3);
- buffers->is_index_buf_global = false;
- }
-
- if (buffers->index_buf) {
/* Fill the triangle buffer */
- tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX);
- if (tri_data) {
- for (i = 0; i < face_indices_len; ++i) {
- const MLoopTri *lt = &looptri[face_indices[i]];
-
- /* Skip hidden faces */
- if (paint_is_face_hidden(lt, mvert, mloop))
- continue;
-
- for (j = 0; j < 3; ++j) {
- *tri_data = face_vert_indices[i][j];
- tri_data++;
- }
- }
- GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX);
+ buffers->index_buf = NULL;
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, INT_MAX);
+
+ for (i = 0; i < face_indices_len; ++i) {
+ const MLoopTri *lt = &looptri[face_indices[i]];
+
+ /* Skip hidden faces */
+ if (paint_is_face_hidden(lt, mvert, mloop))
+ continue;
+
+ GWN_indexbuf_add_tri_verts(&elb, UNPACK3(face_vert_indices[i]));
}
- else {
- if (!buffers->is_index_buf_global) {
- GPU_buffer_free(buffers->index_buf);
- }
- buffers->index_buf = NULL;
- buffers->is_index_buf_global = false;
+ buffers->index_buf = GWN_indexbuf_build(&elb);
+ }
+ else {
+ if (!buffers->is_index_buf_global) {
+ GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
}
+ buffers->index_buf = NULL;
+ buffers->is_index_buf_global = false;
}
buffers->tot_tri = tottri;
@@ -1241,7 +1259,6 @@ void GPU_pbvh_grid_buffers_update(
const DMFlagMat *grid_flag_mats, int *grid_indices,
int totgrid, const CCGKey *key, bool show_diffuse_color)
{
- VertexBufferFormat *vert_data;
int i, j, k, x, y;
buffers->show_diffuse_color = show_diffuse_color;
@@ -1249,12 +1266,13 @@ void GPU_pbvh_grid_buffers_update(
buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
/* Build VBO */
- if (buffers->vert_buf) {
+ if (buffers->index_buf) {
const int has_mask = key->has_mask;
float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
- if (buffers->use_matcaps)
+ if (buffers->use_matcaps) {
diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
+ }
else if (show_diffuse_color) {
const DMFlagMat *flags = &grid_flag_mats[grid_indices[0]];
@@ -1263,33 +1281,43 @@ void GPU_pbvh_grid_buffers_update(
copy_v4_v4(buffers->diffuse_color, diffuse_color);
- vert_data = GPU_buffer_lock_stream(buffers->vert_buf, GPU_BINDING_ARRAY);
- if (vert_data) {
+ Gwn_VertFormat format = {0};
+ VertexBufferAttrID vbo_id;
+ gpu_pbvh_vert_format_init__gwn(&format, &vbo_id);
+
+ /* Build coord/normal VBO */
+ GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
+ buffers->vert_buf = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(buffers->vert_buf, totgrid * key->grid_area);
+
+ uint vbo_index_offset = 0;
+ if (buffers->vert_buf->data) {
for (i = 0; i < totgrid; ++i) {
- VertexBufferFormat *vd = vert_data;
CCGElem *grid = grids[grid_indices[i]];
+ int vbo_index = vbo_index_offset;
for (y = 0; y < key->grid_size; y++) {
for (x = 0; x < key->grid_size; x++) {
CCGElem *elem = CCG_grid_elem(key, grid, x, y);
-
- copy_v3_v3(vd->co, CCG_elem_co(key, elem));
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.pos, vbo_index, CCG_elem_co(key, elem));
+
if (buffers->smooth) {
- normal_float_to_short_v3(vd->no, CCG_elem_no(key, elem));
+ short no_short[3];
+ normal_float_to_short_v3(no_short, CCG_elem_no(key, elem));
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, vbo_index, no_short);
if (has_mask) {
+ uchar color_ub[3];
gpu_color_from_mask_copy(*CCG_elem_mask(key, elem),
- diffuse_color, vd->color);
+ diffuse_color, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vbo_index, color_ub);
}
}
- vd++;
+ vbo_index += 1;
}
}
if (!buffers->smooth) {
- /* for flat shading, recalc normals and set the last vertex of
- * each triangle in the index buffer to have the flat normal as
- * that is what opengl will use */
for (j = 0; j < key->grid_size - 1; j++) {
for (k = 0; k < key->grid_size - 1; k++) {
CCGElem *elems[4] = {
@@ -1306,30 +1334,33 @@ void GPU_pbvh_grid_buffers_update(
CCG_elem_co(key, elems[2]),
CCG_elem_co(key, elems[3]));
- vd = vert_data + (j + 1) * key->grid_size + k;
- normal_float_to_short_v3(vd->no, fno);
+ vbo_index = vbo_index_offset + ((j + 1) * key->grid_size + k);
+ short no_short[3];
+ normal_float_to_short_v3(no_short, fno);
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.nor, vbo_index, no_short);
if (has_mask) {
+ uchar color_ub[3];
gpu_color_from_mask_quad_copy(key,
elems[0],
elems[1],
elems[2],
elems[3],
diffuse_color,
- vd->color);
+ color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, vbo_id.col, vbo_index, color_ub);
}
}
}
}
- vert_data += key->grid_area;
+ vbo_index_offset += key->grid_area;
}
- GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
+ gpu_pbvh_batch_init(buffers);
}
else {
- GPU_buffer_free(buffers->vert_buf);
- buffers->vert_buf = NULL;
+ GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
}
}
@@ -1344,57 +1375,54 @@ void GPU_pbvh_grid_buffers_update(
/* Build the element array buffer of grid indices using either
* unsigned shorts or unsigned ints. */
-#define FILL_QUAD_BUFFER(type_, tot_quad_, buffer_) \
+#define FILL_QUAD_BUFFER(max_vert_, tot_quad_, buffer_) \
{ \
- type_ *tri_data; \
int offset = 0; \
int i, j, k; \
- buffer_ = GPU_buffer_alloc(sizeof(type_) * (tot_quad_) * 6); \
+ \
+ Gwn_IndexBufBuilder elb; \
+ GWN_indexbuf_init( \
+ &elb, GWN_PRIM_TRIS, tot_quad_ * 2, max_vert_); \
\
/* Fill the buffer */ \
- tri_data = GPU_buffer_lock(buffer_, GPU_BINDING_INDEX); \
- if (tri_data) { \
- for (i = 0; i < totgrid; ++i) { \
- BLI_bitmap *gh = NULL; \
- if (grid_hidden) \
- gh = grid_hidden[(grid_indices)[i]]; \
+ for (i = 0; i < totgrid; ++i) { \
+ BLI_bitmap *gh = NULL; \
+ if (grid_hidden) \
+ gh = grid_hidden[(grid_indices)[i]]; \
\
- for (j = 0; j < gridsize - 1; ++j) { \
- for (k = 0; k < gridsize - 1; ++k) { \
- /* Skip hidden grid face */ \
- if (gh && \
- paint_is_grid_face_hidden(gh, \
- gridsize, k, j)) \
- continue; \
- \
- *(tri_data++) = offset + j * gridsize + k + 1; \
- *(tri_data++) = offset + j * gridsize + k; \
- *(tri_data++) = offset + (j + 1) * gridsize + k; \
- \
- *(tri_data++) = offset + (j + 1) * gridsize + k + 1; \
- *(tri_data++) = offset + j * gridsize + k + 1; \
- *(tri_data++) = offset + (j + 1) * gridsize + k; \
- } \
- } \
- \
- offset += gridsize * gridsize; \
+ for (j = 0; j < gridsize - 1; ++j) { \
+ for (k = 0; k < gridsize - 1; ++k) { \
+ /* Skip hidden grid face */ \
+ if (gh && paint_is_grid_face_hidden( \
+ gh, gridsize, k, j)) \
+ { \
+ continue; \
+ } \
+ GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \
+ GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k); \
+ GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \
+ \
+ GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k + 1); \
+ GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \
+ GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \
+ } \
} \
- GPU_buffer_unlock(buffer_, GPU_BINDING_INDEX); \
- } \
- else { \
- GPU_buffer_free(buffer_); \
- (buffer_) = NULL; \
+ \
+ offset += gridsize * gridsize; \
} \
+ buffer_ = GWN_indexbuf_build(&elb); \
} (void)0
/* end FILL_QUAD_BUFFER */
-static GPUBuffer *gpu_get_grid_buffer(
- int gridsize, GLenum *index_type, unsigned *totquad, GridCommonGPUBuffer **grid_common_gpu_buffer)
+static Gwn_IndexBuf *gpu_get_grid_buffer(
+ int gridsize, unsigned *totquad, GridCommonGPUBuffer **grid_common_gpu_buffer,
+ /* remove this arg when gawain gets base-vertex support! */
+ int totgrid)
{
/* used in the FILL_QUAD_BUFFER macro */
BLI_bitmap * const *grid_hidden = NULL;
const int *grid_indices = NULL;
- int totgrid = 1;
+ // int totgrid = 1;
GridCommonGPUBuffer *gridbuff = *grid_common_gpu_buffer;
@@ -1402,65 +1430,48 @@ static GPUBuffer *gpu_get_grid_buffer(
*grid_common_gpu_buffer = gridbuff = MEM_mallocN(sizeof(GridCommonGPUBuffer), __func__);
gridbuff->mres_buffer = NULL;
gridbuff->mres_prev_gridsize = -1;
- gridbuff->mres_prev_index_type = 0;
gridbuff->mres_prev_totquad = 0;
}
/* VBO is already built */
if (gridbuff->mres_buffer && gridbuff->mres_prev_gridsize == gridsize) {
- *index_type = gridbuff->mres_prev_index_type;
*totquad = gridbuff->mres_prev_totquad;
return gridbuff->mres_buffer;
}
/* we can't reuse old, delete the existing buffer */
else if (gridbuff->mres_buffer) {
- GPU_buffer_free(gridbuff->mres_buffer);
+ GWN_indexbuf_discard(gridbuff->mres_buffer);
+ gridbuff->mres_buffer = NULL;
}
/* Build new VBO */
- *totquad = (gridsize - 1) * (gridsize - 1);
+ *totquad = (gridsize - 1) * (gridsize - 1) * totgrid;
+ int max_vert = gridsize * gridsize * totgrid;
- if (gridsize * gridsize < USHRT_MAX) {
- *index_type = GL_UNSIGNED_SHORT;
- FILL_QUAD_BUFFER(unsigned short, *totquad, gridbuff->mres_buffer);
- }
- else {
- *index_type = GL_UNSIGNED_INT;
- FILL_QUAD_BUFFER(unsigned int, *totquad, gridbuff->mres_buffer);
- }
+ FILL_QUAD_BUFFER(max_vert, *totquad, gridbuff->mres_buffer);
gridbuff->mres_prev_gridsize = gridsize;
- gridbuff->mres_prev_index_type = *index_type;
gridbuff->mres_prev_totquad = *totquad;
return gridbuff->mres_buffer;
}
-#define FILL_FAST_BUFFER(type_) \
+#define FILL_FAST_BUFFER() \
{ \
- type_ *buffer; \
- buffers->index_buf_fast = GPU_buffer_alloc(sizeof(type_) * 6 * totgrid); \
- buffer = GPU_buffer_lock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
- if (buffer) { \
- int i; \
- for (i = 0; i < totgrid; i++) { \
- int currentquad = i * 6; \
- buffer[currentquad] = i * gridsize * gridsize + gridsize - 1; \
- buffer[currentquad + 1] = i * gridsize * gridsize; \
- buffer[currentquad + 2] = (i + 1) * gridsize * gridsize - gridsize; \
- buffer[currentquad + 3] = (i + 1) * gridsize * gridsize - 1; \
- buffer[currentquad + 4] = i * gridsize * gridsize + gridsize - 1; \
- buffer[currentquad + 5] = (i + 1) * gridsize * gridsize - gridsize; \
- } \
- GPU_buffer_unlock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
- } \
- else { \
- GPU_buffer_free(buffers->index_buf_fast); \
- buffers->index_buf_fast = NULL; \
+ Gwn_IndexBufBuilder elb; \
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, 6 * totgrid, INT_MAX); \
+ for (int i = 0; i < totgrid; i++) { \
+ GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \
+ GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize); \
+ GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \
+ GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - 1); \
+ GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \
+ GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \
} \
+ buffers->index_buf_fast = GWN_indexbuf_build(&elb); \
} (void)0
GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
- int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key,
+ int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *UNUSED(key),
GridCommonGPUBuffer **grid_common_gpu_buffer)
{
GPU_PBVH_Buffers *buffers;
@@ -1482,39 +1493,26 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
return buffers;
/* create and fill indices of the fast buffer too */
- if (totgrid * gridsize * gridsize < USHRT_MAX) {
- FILL_FAST_BUFFER(unsigned short);
- }
- else {
- FILL_FAST_BUFFER(unsigned int);
- }
+ FILL_FAST_BUFFER();
if (totquad == fully_visible_totquad) {
buffers->index_buf = gpu_get_grid_buffer(
- gridsize, &buffers->index_type, &buffers->tot_quad, grid_common_gpu_buffer);
+ gridsize, &buffers->tot_quad, grid_common_gpu_buffer, totgrid);
buffers->has_hidden = false;
buffers->is_index_buf_global = true;
}
else {
+ uint max_vert = totgrid * gridsize * gridsize;
buffers->tot_quad = totquad;
- if (totgrid * gridsize * gridsize < USHRT_MAX) {
- buffers->index_type = GL_UNSIGNED_SHORT;
- FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf);
- }
- else {
- buffers->index_type = GL_UNSIGNED_INT;
- FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf);
- }
+ FILL_QUAD_BUFFER(max_vert, totquad, buffers->index_buf);
- buffers->has_hidden = true;
+ buffers->has_hidden = false;
buffers->is_index_buf_global = false;
}
+#ifdef USE_BASE_ELEM
/* Build coord/normal VBO */
- if (buffers->index_buf)
- buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totgrid * key->grid_area);
-
if (GLEW_ARB_draw_elements_base_vertex /* 3.2 */) {
int i;
buffers->baseelemarray = MEM_mallocN(sizeof(int) * totgrid * 2, "GPU_PBVH_Buffers.baseelemarray");
@@ -1525,6 +1523,7 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
buffers->baseindex[i] = NULL;
}
}
+#endif
return buffers;
}
@@ -1537,26 +1536,36 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
* index '*v_index' in the 'vert_data' array and '*v_index' is
* incremented.
*/
-static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
- VertexBufferFormat *vert_data,
- int *v_index,
- const float fno[3],
- const float *fmask,
- const int cd_vert_mask_offset,
- const float diffuse_color[4])
+static void gpu_bmesh_vert_to_buffer_copy__gwn(
+ BMVert *v,
+ Gwn_VertBuf *vert_buf,
+ const VertexBufferAttrID *vbo_id,
+ int *v_index,
+ const float fno[3],
+ const float *fmask,
+ const int cd_vert_mask_offset,
+ const float diffuse_color[4])
{
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- VertexBufferFormat *vd = &vert_data[*v_index];
/* Set coord, normal, and mask */
- copy_v3_v3(vd->co, v->co);
- normal_float_to_short_v3(vd->no, fno ? fno : v->no);
+ GWN_vertbuf_attr_set(vert_buf, vbo_id->pos, *v_index, v->co);
- gpu_color_from_mask_copy(
- fmask ? *fmask :
- BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset),
- diffuse_color,
- vd->color);
+ {
+ short no_short[3];
+ normal_float_to_short_v3(no_short, fno ? fno : v->no);
+ GWN_vertbuf_attr_set(vert_buf, vbo_id->nor, *v_index, no_short);
+ }
+
+ {
+ uchar color_ub[3];
+ gpu_color_from_mask_copy(
+ fmask ? *fmask :
+ BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset),
+ diffuse_color,
+ color_ub);
+ GWN_vertbuf_attr_set(vert_buf, vbo_id->col, *v_index, color_ub);
+ }
/* Assign index for use in the triangle index buffer */
/* note: caller must set: bm->elem_index_dirty |= BM_VERT; */
@@ -1613,8 +1622,6 @@ void GPU_pbvh_bmesh_buffers_update(
GSet *bm_other_verts,
bool show_diffuse_color)
{
- VertexBufferFormat *vert_data;
- void *tri_data;
int tottri, totvert, maxvert = 0;
float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
@@ -1653,13 +1660,17 @@ void GPU_pbvh_bmesh_buffers_update(
copy_v4_v4(buffers->diffuse_color, diffuse_color);
/* Initialize vertex buffer */
- if (buffers->vert_buf)
- GPU_buffer_free(buffers->vert_buf);
- buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totvert);
+ GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
+ /* match 'VertexBufferFormat' */
+ Gwn_VertFormat format = {0};
+ VertexBufferAttrID vbo_id;
+ gpu_pbvh_vert_format_init__gwn(&format, &vbo_id);
+
+ buffers->vert_buf = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(buffers->vert_buf, totvert);
/* Fill vertex buffer */
- vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY);
- if (vert_data) {
+ if (buffers->vert_buf->data) {
int v_index = 0;
if (buffers->smooth) {
@@ -1670,15 +1681,17 @@ void GPU_pbvh_bmesh_buffers_update(
bm->elem_index_dirty |= BM_VERT;
GSET_ITER (gs_iter, bm_unique_verts) {
- gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter),
- vert_data, &v_index, NULL, NULL,
- cd_vert_mask_offset, diffuse_color);
+ gpu_bmesh_vert_to_buffer_copy__gwn(
+ BLI_gsetIterator_getKey(&gs_iter),
+ buffers->vert_buf, &vbo_id, &v_index, NULL, NULL,
+ cd_vert_mask_offset, diffuse_color);
}
GSET_ITER (gs_iter, bm_other_verts) {
- gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter),
- vert_data, &v_index, NULL, NULL,
- cd_vert_mask_offset, diffuse_color);
+ gpu_bmesh_vert_to_buffer_copy__gwn(
+ BLI_gsetIterator_getKey(&gs_iter),
+ buffers->vert_buf, &vbo_id, &v_index, NULL, NULL,
+ cd_vert_mask_offset, diffuse_color);
}
maxvert = v_index;
@@ -1708,9 +1721,10 @@ void GPU_pbvh_bmesh_buffers_update(
fmask /= 3.0f;
for (i = 0; i < 3; i++) {
- gpu_bmesh_vert_to_buffer_copy(v[i], vert_data,
- &v_index, f->no, &fmask,
- cd_vert_mask_offset, diffuse_color);
+ gpu_bmesh_vert_to_buffer_copy__gwn(
+ v[i], buffers->vert_buf, &vbo_id,
+ &v_index, f->no, &fmask,
+ cd_vert_mask_offset, diffuse_color);
}
}
}
@@ -1718,32 +1732,30 @@ void GPU_pbvh_bmesh_buffers_update(
buffers->tot_tri = tottri;
}
- GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
-
/* gpu_bmesh_vert_to_buffer_copy sets dirty index values */
bm->elem_index_dirty |= BM_VERT;
}
else {
+ GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
/* Memory map failed */
- GPU_buffer_free(buffers->vert_buf);
- buffers->vert_buf = NULL;
return;
}
if (buffers->smooth) {
- const int use_short = (maxvert < USHRT_MAX);
+ /* Fill the triangle buffer */
+ buffers->index_buf = NULL;
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, maxvert);
/* Initialize triangle index buffer */
- if (buffers->index_buf && !buffers->is_index_buf_global)
- GPU_buffer_free(buffers->index_buf);
+ if (buffers->triangles && !buffers->is_index_buf_global) {
+ GWN_BATCH_DISCARD_SAFE(buffers->triangles);
+ }
buffers->is_index_buf_global = false;
- buffers->index_buf = GPU_buffer_alloc((use_short ?
- sizeof(unsigned short) :
- sizeof(unsigned int)) * 3 * tottri);
/* Fill triangle index buffer */
- tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX);
- if (tri_data) {
+
+ {
GSetIterator gs_iter;
GSET_ITER (gs_iter, bm_faces) {
@@ -1755,46 +1767,25 @@ void GPU_pbvh_bmesh_buffers_update(
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
- BMVert *v = l_iter->v;
- if (use_short) {
- unsigned short *elem = tri_data;
- (*elem) = BM_elem_index_get(v);
- elem++;
- tri_data = elem;
- }
- else {
- unsigned int *elem = tri_data;
- (*elem) = BM_elem_index_get(v);
- elem++;
- tri_data = elem;
- }
+ GWN_indexbuf_add_generic_vert(&elb, BM_elem_index_get(l_iter->v));
} while ((l_iter = l_iter->next) != l_first);
}
}
- GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX);
-
buffers->tot_tri = tottri;
- buffers->index_type = (use_short ?
- GL_UNSIGNED_SHORT :
- GL_UNSIGNED_INT);
- }
- else {
- /* Memory map failed */
- if (!buffers->is_index_buf_global) {
- GPU_buffer_free(buffers->index_buf);
- }
- buffers->index_buf = NULL;
- buffers->is_index_buf_global = false;
+
+ buffers->index_buf = GWN_indexbuf_build(&elb);
}
}
else if (buffers->index_buf) {
if (!buffers->is_index_buf_global) {
- GPU_buffer_free(buffers->index_buf);
+ GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
}
buffers->index_buf = NULL;
buffers->is_index_buf_global = false;
}
+
+ gpu_pbvh_batch_init(buffers);
}
GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading)
@@ -1814,145 +1805,42 @@ void GPU_pbvh_buffers_draw(
GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
bool wireframe, bool fast)
{
- bool do_fast = fast && buffers->index_buf_fast;
- /* sets material from the first face, to solve properly face would need to
- * be sorted in buckets by materials */
- if (setMaterial) {
- if (buffers->face_indices_len) {
- const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
- const MPoly *mp = &buffers->mpoly[lt->poly];
- if (!setMaterial(mp->mat_nr + 1, NULL))
- return;
- }
- else if (buffers->totgrid) {
- const DMFlagMat *f = &buffers->grid_flag_mats[buffers->grid_indices[0]];
- if (!setMaterial(f->mat_nr + 1, NULL))
- return;
- }
- else {
- if (!setMaterial(1, NULL))
- return;
- }
- }
-
- if (buffers->vert_buf) {
- char *base = NULL;
- char *index_base = NULL;
- /* weak inspection of bound options, should not be necessary ideally */
- const int bound_options_old = GPU_basic_shader_bound_options();
- int bound_options_new = 0;
- glEnableClientState(GL_VERTEX_ARRAY);
- if (!wireframe) {
- glEnableClientState(GL_NORMAL_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
-
- bound_options_new |= GPU_SHADER_USE_COLOR;
- }
-
- GPU_buffer_bind(buffers->vert_buf, GPU_BINDING_ARRAY);
-
- if (do_fast) {
- GPU_buffer_bind(buffers->index_buf_fast, GPU_BINDING_INDEX);
- }
- else if (buffers->index_buf) {
- GPU_buffer_bind(buffers->index_buf, GPU_BINDING_INDEX);
- }
-
- if (wireframe) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- }
- else {
- if ((buffers->smooth == false) && (buffers->face_indices_len == 0)) {
- bound_options_new |= GPU_SHADER_FLAT_NORMAL;
- }
- }
-
- if (bound_options_new & ~bound_options_old) {
- GPU_basic_shader_bind(bound_options_old | bound_options_new);
- }
-
- if (buffers->tot_quad) {
- const char *offset = base;
- const bool drawall = !(buffers->has_hidden || do_fast);
-
- if (GLEW_ARB_draw_elements_base_vertex && drawall) {
-
- glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, co));
- if (!wireframe) {
- glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, no));
- glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, color));
- }
-
- glMultiDrawElementsBaseVertex(GL_TRIANGLES, buffers->baseelemarray, buffers->index_type,
- (const void * const *)buffers->baseindex,
- buffers->totgrid, &buffers->baseelemarray[buffers->totgrid]);
- }
- else {
- int i, last = drawall ? buffers->totgrid : 1;
-
- /* we could optimize this to one draw call, but it would need more memory */
- for (i = 0; i < last; i++) {
- glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, co));
- if (!wireframe) {
- glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, no));
- glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, color));
- }
-
- if (do_fast)
- glDrawElements(GL_TRIANGLES, buffers->totgrid * 6, buffers->index_type, index_base);
- else
- glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, index_base);
+ UNUSED_VARS(wireframe, fast, setMaterial);
+ bool do_fast = fast && buffers->triangles_fast;
+ Gwn_Batch *triangles = do_fast ? buffers->triangles_fast : buffers->triangles;
- offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat);
- }
- }
- }
- else if (buffers->tot_tri) {
- int totelem = buffers->tot_tri * 3;
-
- glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
- (void *)(base + offsetof(VertexBufferFormat, co)));
-
- if (!wireframe) {
- glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
- (void *)(base + offsetof(VertexBufferFormat, no)));
- glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
- (void *)(base + offsetof(VertexBufferFormat, color)));
- }
+ if (triangles) {
- if (buffers->index_buf)
- glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, index_base);
- else
- glDrawArrays(GL_TRIANGLES, 0, totelem);
- }
+ /* Simple Shader: use when drawing without the draw-manager (old 2.7x viewport) */
+ if (triangles->interface == NULL) {
+ GPUBuiltinShader shader_id =
+ buffers->smooth ? GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR : GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR;
+ GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
- if (wireframe)
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ GWN_batch_program_set(
+ triangles,
+ GPU_shader_get_program(shader), GPU_shader_get_interface(shader));
- GPU_buffer_unbind(buffers->vert_buf, GPU_BINDING_ARRAY);
- if (buffers->index_buf || do_fast)
- GPU_buffer_unbind(do_fast ? buffers->index_buf_fast : buffers->index_buf, GPU_BINDING_INDEX);
+ static float light[3] = {-0.3f, 0.5f, 1.0f};
+ static float alpha = 1.0f;
+ static float world_light = 1.0f;
- glDisableClientState(GL_VERTEX_ARRAY);
- if (!wireframe) {
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- }
+ GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "light"), 3, 1, light);
+ GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "alpha"), 1, 1, &alpha);
+ GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "global"), 1, 1, &world_light);
- if (bound_options_new & ~bound_options_old) {
- GPU_basic_shader_bind(bound_options_old);
}
+ GWN_batch_draw(triangles);
}
}
-bool GPU_pbvh_buffers_diffuse_changed(
- GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
+Gwn_Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast)
+{
+ return (fast && buffers->triangles_fast) ?
+ buffers->triangles_fast : buffers->triangles;
+}
+
+bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
{
float diffuse_color[4];
bool use_matcaps = GPU_material_use_matcaps_get();
@@ -1998,16 +1886,20 @@ bool GPU_pbvh_buffers_diffuse_changed(
void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers)
{
if (buffers) {
- if (buffers->vert_buf)
- GPU_buffer_free(buffers->vert_buf);
- if (buffers->index_buf && !buffers->is_index_buf_global)
- GPU_buffer_free(buffers->index_buf);
- if (buffers->index_buf_fast)
- GPU_buffer_free(buffers->index_buf_fast);
+ GWN_BATCH_DISCARD_SAFE(buffers->triangles);
+ GWN_BATCH_DISCARD_SAFE(buffers->triangles_fast);
+ if (!buffers->is_index_buf_global) {
+ GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
+ }
+ GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast);
+ GWN_vertbuf_discard(buffers->vert_buf);
+
+#ifdef USE_BASE_ELEM
if (buffers->baseelemarray)
MEM_freeN(buffers->baseelemarray);
if (buffers->baseindex)
MEM_freeN(buffers->baseindex);
+#endif
MEM_freeN(buffers);
}
@@ -2020,7 +1912,7 @@ void GPU_pbvh_multires_buffers_free(GridCommonGPUBuffer **grid_common_gpu_buffer
if (gridbuff) {
if (gridbuff->mres_buffer) {
BLI_mutex_lock(&buffer_mutex);
- gpu_buffer_free_intern(gridbuff->mres_buffer);
+ GWN_INDEXBUF_DISCARD_SAFE(gridbuff->mres_buffer);
BLI_mutex_unlock(&buffer_mutex);
}
MEM_freeN(gridbuff);
@@ -2029,59 +1921,57 @@ void GPU_pbvh_multires_buffers_free(GridCommonGPUBuffer **grid_common_gpu_buffer
}
/* debug function, draws the pbvh BB */
-void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf)
+void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos)
{
- const float quads[4][4][3] = {
- {
- {min[0], min[1], min[2]},
- {max[0], min[1], min[2]},
- {max[0], min[1], max[2]},
- {min[0], min[1], max[2]}
- },
+ if (leaf)
+ immUniformColor4f(0.0, 1.0, 0.0, 0.5);
+ else
+ immUniformColor4f(1.0, 0.0, 0.0, 0.5);
- {
- {min[0], min[1], min[2]},
- {min[0], max[1], min[2]},
- {min[0], max[1], max[2]},
- {min[0], min[1], max[2]}
- },
+ /* TODO(merwin): revisit this after we have mutable VertexBuffers
+ * could keep a static batch & index buffer, change the VBO contents per draw
+ */
- {
- {max[0], max[1], min[2]},
- {max[0], min[1], min[2]},
- {max[0], min[1], max[2]},
- {max[0], max[1], max[2]}
- },
+ immBegin(GWN_PRIM_LINES, 24);
- {
- {max[0], max[1], min[2]},
- {min[0], max[1], min[2]},
- {min[0], max[1], max[2]},
- {max[0], max[1], max[2]}
- },
- };
+ /* top */
+ immVertex3f(pos, min[0], min[1], max[2]);
+ immVertex3f(pos, min[0], max[1], max[2]);
- if (leaf)
- glColor4f(0.0, 1.0, 0.0, 0.5);
- else
- glColor4f(1.0, 0.0, 0.0, 0.5);
+ immVertex3f(pos, min[0], max[1], max[2]);
+ immVertex3f(pos, max[0], max[1], max[2]);
- glVertexPointer(3, GL_FLOAT, 0, &quads[0][0][0]);
- glDrawArrays(GL_QUADS, 0, 16);
-}
+ immVertex3f(pos, max[0], max[1], max[2]);
+ immVertex3f(pos, max[0], min[1], max[2]);
-void GPU_pbvh_BB_draw_init(void)
-{
- glPushAttrib(GL_ENABLE_BIT);
- glDisable(GL_CULL_FACE);
- glEnableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- glEnable(GL_BLEND);
-}
+ immVertex3f(pos, max[0], min[1], max[2]);
+ immVertex3f(pos, min[0], min[1], max[2]);
-void GPU_pbvh_BB_draw_end(void)
-{
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glPopAttrib();
+ /* bottom */
+ immVertex3f(pos, min[0], min[1], min[2]);
+ immVertex3f(pos, min[0], max[1], min[2]);
+
+ immVertex3f(pos, min[0], max[1], min[2]);
+ immVertex3f(pos, max[0], max[1], min[2]);
+
+ immVertex3f(pos, max[0], max[1], min[2]);
+ immVertex3f(pos, max[0], min[1], min[2]);
+
+ immVertex3f(pos, max[0], min[1], min[2]);
+ immVertex3f(pos, min[0], min[1], min[2]);
+
+ /* sides */
+ immVertex3f(pos, min[0], min[1], min[2]);
+ immVertex3f(pos, min[0], min[1], max[2]);
+
+ immVertex3f(pos, min[0], max[1], min[2]);
+ immVertex3f(pos, min[0], max[1], max[2]);
+
+ immVertex3f(pos, max[0], max[1], min[2]);
+ immVertex3f(pos, max[0], max[1], max[2]);
+
+ immVertex3f(pos, max[0], min[1], min[2]);
+ immVertex3f(pos, max[0], min[1], max[2]);
+
+ immEnd();
}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index b5512aa108d..9e4daa2a036 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -36,6 +36,7 @@
#include "DNA_customdata_types.h"
#include "DNA_image_types.h"
#include "DNA_material_types.h"
+#include "DNA_node_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -47,6 +48,7 @@
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_uniformbuffer.h"
#include "BLI_sys_types.h" /* for intptr_t support */
@@ -88,7 +90,7 @@ typedef struct GPUFunction {
/* Indices match the GPUType enum */
static const char *GPU_DATATYPE_STR[17] = {
"", "float", "vec2", "vec3", "vec4",
- NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4",
+ NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"
};
/* GLSL code parsing for finding function definitions.
@@ -172,7 +174,7 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
/* test for type */
type = GPU_NONE;
- for (i = 1; i <= 16; i++) {
+ for (i = 1; i < ARRAY_SIZE(GPU_DATATYPE_STR); i++) {
if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
type = i;
break;
@@ -188,6 +190,13 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
if (!type && gpu_str_prefix(code, "sampler2D")) {
type = GPU_TEX2D;
}
+ if (!type && gpu_str_prefix(code, "sampler3D")) {
+ type = GPU_TEX3D;
+ }
+
+ if (!type && gpu_str_prefix(code, "Closure")) {
+ type = GPU_CLOSURE;
+ }
if (type) {
/* add parameter */
@@ -350,6 +359,8 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t
BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
else if (from == GPU_FLOAT)
BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
+ else /* can happen with closure */
+ BLI_dynstr_append(ds, name);
}
}
@@ -412,6 +423,10 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
return "unfparticleangvel";
else if (builtin == GPU_OBJECT_INFO)
return "unfobjectinfo";
+ else if (builtin == GPU_VOLUME_DENSITY)
+ return "sampdensity";
+ else if (builtin == GPU_VOLUME_FLAME)
+ return "sampflame";
else
return "";
}
@@ -500,12 +515,16 @@ static void codegen_set_unique_ids(ListBase *nodes)
BLI_ghash_free(definehash, NULL, NULL);
}
-static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
+/**
+ * It will create an UBO for GPUMaterial if there is any GPU_DYNAMIC_UBO.
+ */
+static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds, ListBase *nodes)
{
GPUNode *node;
GPUInput *input;
const char *name;
int builtins = 0;
+ ListBase ubo_inputs = {NULL, NULL};
/* print uniforms */
for (node = nodes->first; node; node = node->next) {
@@ -525,7 +544,14 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
builtins |= input->builtin;
name = GPU_builtin_name(input->builtin);
- if (gpu_str_prefix(name, "unf")) {
+ if (gpu_str_prefix(name, "samp")) {
+ if ((input->builtin == GPU_VOLUME_DENSITY) ||
+ (input->builtin == GPU_VOLUME_FLAME))
+ {
+ BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", name);
+ }
+ }
+ else if (gpu_str_prefix(name, "unf")) {
BLI_dynstr_appendf(ds, "uniform %s %s;\n",
GPU_DATATYPE_STR[input->type], name);
}
@@ -536,14 +562,23 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
}
}
}
+ else if (input->source == GPU_SOURCE_STRUCT) {
+ /* Add other struct here if needed. */
+ BLI_dynstr_appendf(ds, "Closure strct%d = CLOSURE_DEFAULT;\n", input->id);
+ }
else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
- if (input->dynamicvec) {
+ if (input->dynamictype == GPU_DYNAMIC_UBO) {
+ if (!input->link) {
+ /* We handle the UBOuniforms separately. */
+ BLI_addtail(&ubo_inputs, BLI_genericNodeN(input));
+ }
+ }
+ else if (input->dynamicvec) {
/* only create uniforms for dynamic vectors */
BLI_dynstr_appendf(ds, "uniform %s unf%d;\n",
GPU_DATATYPE_STR[input->type], input->id);
}
else {
- /* for others use const so the compiler can do folding */
BLI_dynstr_appendf(ds, "const %s cons%d = ",
GPU_DATATYPE_STR[input->type], input->id);
codegen_print_datatype(ds, input->type, input->vec);
@@ -569,6 +604,22 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
}
}
+ /* Handle the UBO block separately. */
+ if ((material != NULL) && !BLI_listbase_is_empty(&ubo_inputs)) {
+ GPU_material_create_uniform_buffer(material, &ubo_inputs);
+
+ /* Inputs are sorted */
+ BLI_dynstr_appendf(ds, "\nlayout (std140) uniform %s {\n", GPU_UBO_BLOCK_NAME);
+
+ for (LinkData *link = ubo_inputs.first; link; link = link->next) {
+ input = link->data;
+ BLI_dynstr_appendf(ds, "\t%s unf%d;\n",
+ GPU_DATATYPE_STR[input->type], input->id);
+ }
+ BLI_dynstr_append(ds, "};\n");
+ BLI_freelistN(&ubo_inputs);
+ }
+
BLI_dynstr_append(ds, "\n");
return builtins;
@@ -594,8 +645,13 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
/* declare temporary variables for node output storage */
for (output = node->outputs.first; output; output = output->next) {
- BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
- GPU_DATATYPE_STR[output->type], output->id);
+ if (output->type == GPU_CLOSURE) {
+ BLI_dynstr_appendf(ds, "\tClosure tmp%d;\n", output->id);
+ }
+ else {
+ BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
+ GPU_DATATYPE_STR[output->type], output->id);
+ }
}
}
@@ -622,11 +678,26 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
"tmp", input->link->output->id);
}
else if (input->source == GPU_SOURCE_BUILTIN) {
- if (input->builtin == GPU_VIEW_NORMAL)
+ if (input->builtin == GPU_INVERSE_VIEW_MATRIX)
+ BLI_dynstr_append(ds, "viewinv");
+ else if (input->builtin == GPU_VIEW_MATRIX)
+ BLI_dynstr_append(ds, "viewmat");
+ else if (input->builtin == GPU_CAMERA_TEXCO_FACTORS)
+ BLI_dynstr_append(ds, "camtexfac");
+ else if (input->builtin == GPU_OBJECT_MATRIX)
+ BLI_dynstr_append(ds, "objmat");
+ else if (input->builtin == GPU_INVERSE_OBJECT_MATRIX)
+ BLI_dynstr_append(ds, "objinv");
+ else if (input->builtin == GPU_VIEW_POSITION)
+ BLI_dynstr_append(ds, "viewposition");
+ else if (input->builtin == GPU_VIEW_NORMAL)
BLI_dynstr_append(ds, "facingnormal");
else
BLI_dynstr_append(ds, GPU_builtin_name(input->builtin));
}
+ else if (input->source == GPU_SOURCE_STRUCT) {
+ BLI_dynstr_appendf(ds, "strct%d", input->id);
+ }
else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
if (input->dynamicvec)
BLI_dynstr_appendf(ds, "unf%d", input->id);
@@ -655,12 +726,11 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_append(ds, ");\n");
}
- BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
- codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
+ BLI_dynstr_appendf(ds, "\n\treturn tmp%d", finaloutput->id);
BLI_dynstr_append(ds, ";\n");
}
-static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
+static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUOutput *output, bool use_new_shading)
{
DynStr *ds = BLI_dynstr_new();
char *code;
@@ -677,17 +747,47 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
#endif
codegen_set_unique_ids(nodes);
- builtins = codegen_print_uniforms_functions(ds, nodes);
+ builtins = codegen_process_uniforms_functions(material, ds, nodes);
#if 0
if (G.debug & G_DEBUG)
BLI_dynstr_appendf(ds, "/* %s */\n", name);
#endif
- BLI_dynstr_append(ds, "void main()\n{\n");
+ BLI_dynstr_append(ds, "Closure nodetree_exec(void)\n{\n");
- if (builtins & GPU_VIEW_NORMAL)
- BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? varnormal: -varnormal;\n");
+ if (use_new_shading) {
+ if (builtins & GPU_VIEW_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 viewmat = ViewMatrix;\n");
+ if (builtins & GPU_CAMERA_TEXCO_FACTORS)
+ BLI_dynstr_append(ds, "\tvec4 camtexfac = CameraTexCoFactors;\n");
+ if (builtins & GPU_OBJECT_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 objmat = ModelMatrix;\n");
+ if (builtins & GPU_INVERSE_OBJECT_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 objinv = ModelMatrixInverse;\n");
+ if (builtins & GPU_INVERSE_VIEW_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 viewinv = ViewMatrixInverse;\n");
+ if (builtins & GPU_VIEW_NORMAL)
+ BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? viewNormal: -viewNormal;\n");
+ if (builtins & GPU_VIEW_POSITION)
+ BLI_dynstr_append(ds, "\tvec3 viewposition = viewPosition;\n");
+ }
+ else {
+ if (builtins & GPU_VIEW_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 viewmat = unfviewmat;\n");
+ if (builtins & GPU_CAMERA_TEXCO_FACTORS)
+ BLI_dynstr_append(ds, "\tvec4 camtexfac = unfcameratexfactors;\n");
+ if (builtins & GPU_OBJECT_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 objmat = unfobmat;\n");
+ if (builtins & GPU_INVERSE_OBJECT_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 objinv = unfinvobmat;\n");
+ if (builtins & GPU_INVERSE_VIEW_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 viewinv = unfinvviewmat;\n");
+ if (builtins & GPU_VIEW_NORMAL)
+ BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? varnormal: -varnormal;\n");
+ if (builtins & GPU_VIEW_POSITION)
+ BLI_dynstr_append(ds, "\tvec3 viewposition = varposition;\n");
+ }
/* Calculate tangent space. */
#ifdef WITH_OPENSUBDIV
@@ -722,6 +822,17 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
BLI_dynstr_append(ds, "}\n");
+ /* XXX This cannot go into gpu_shader_material.glsl because main() would be parsed and generate error */
+ /* Old glsl mode compat. */
+ BLI_dynstr_append(ds, "#ifndef NODETREE_EXEC\n");
+ BLI_dynstr_append(ds, "out vec4 fragColor;\n");
+ BLI_dynstr_append(ds, "void main()\n");
+ BLI_dynstr_append(ds, "{\n");
+ BLI_dynstr_append(ds, "\tClosure cl = nodetree_exec();\n");
+ BLI_dynstr_append(ds, "\tfragColor = vec4(cl.radiance, cl.opacity);\n");
+ BLI_dynstr_append(ds, "}\n");
+ BLI_dynstr_append(ds, "#endif\n\n");
+
/* create shader */
code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
@@ -733,6 +844,95 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
return code;
}
+static const char *attrib_prefix_get(CustomDataType type)
+{
+ switch (type) {
+ case CD_ORCO: return "orco";
+ case CD_MTFACE: return "u";
+ case CD_TANGENT: return "t";
+ case CD_MCOL: return "c";
+ case CD_AUTO_FROM_NAME: return "a";
+ default: BLI_assert(false && "Gwn_VertAttr Prefix type not found : This should not happen!"); return "";
+ }
+}
+
+static char *code_generate_vertex_new(ListBase *nodes, const char *vert_code, bool use_geom)
+{
+ DynStr *ds = BLI_dynstr_new();
+ GPUNode *node;
+ GPUInput *input;
+ char *code;
+
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+ /* XXX FIXME : see notes in mesh_render_data_create() */
+ /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
+ if (input->attribtype == CD_ORCO) {
+ /* orco is computed from local positions, see bellow */
+ BLI_dynstr_appendf(ds, "uniform vec3 OrcoTexCoFactors[2];\n");
+ }
+ else if (input->attribname[0] == '\0') {
+ BLI_dynstr_appendf(ds, "in %s %s;\n", GPU_DATATYPE_STR[input->type], attrib_prefix_get(input->attribtype));
+ BLI_dynstr_appendf(ds, "#define att%d %s\n", input->attribid, attrib_prefix_get(input->attribtype));
+ }
+ else {
+ unsigned int hash = BLI_ghashutil_strhash_p(input->attribname);
+ BLI_dynstr_appendf(ds, "in %s %s%u;\n",
+ GPU_DATATYPE_STR[input->type], attrib_prefix_get(input->attribtype), hash);
+ BLI_dynstr_appendf(ds, "#define att%d %s%u\n",
+ input->attribid, attrib_prefix_get(input->attribtype), hash);
+ }
+ BLI_dynstr_appendf(ds, "out %s var%d%s;\n",
+ GPU_DATATYPE_STR[input->type], input->attribid, use_geom ? "g" : "");
+ }
+ }
+ }
+
+ BLI_dynstr_append(ds, "\n");
+
+ BLI_dynstr_append(ds, "#define ATTRIB\n");
+ BLI_dynstr_append(ds, "uniform mat3 NormalMatrix;\n");
+ BLI_dynstr_append(ds, "void pass_attrib(in vec3 position) {\n");
+
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+ if (input->attribtype == CD_TANGENT) { /* silly exception */
+ BLI_dynstr_appendf(
+ ds, "\tvar%d%s.xyz = normalize(NormalMatrix * att%d.xyz);\n",
+ input->attribid, use_geom ? "g" : "", input->attribid);
+ BLI_dynstr_appendf(
+ ds, "\tvar%d%s.w = att%d.w;\n",
+ input->attribid, use_geom ? "g" : "", input->attribid);
+ }
+ else if (input->attribtype == CD_ORCO) {
+ BLI_dynstr_appendf(ds, "\tvar%d%s = OrcoTexCoFactors[0] + position * OrcoTexCoFactors[1];\n",
+ input->attribid, use_geom ? "g" : "");
+ }
+ else {
+ BLI_dynstr_appendf(ds, "\tvar%d%s = att%d;\n",
+ input->attribid, use_geom ? "g" : "", input->attribid);
+ }
+ }
+ }
+ }
+
+ BLI_dynstr_append(ds, "}\n");
+
+ BLI_dynstr_append(ds, vert_code);
+
+ code = BLI_dynstr_get_cstring(ds);
+
+ BLI_dynstr_free(ds);
+
+#if 0
+ if (G.debug & G_DEBUG) printf("%s\n", code);
+#endif
+
+ return code;
+}
+
static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
{
DynStr *ds = BLI_dynstr_new();
@@ -790,7 +990,7 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
#endif
BLI_dynstr_appendf(
- ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n",
+ ds, "\tvar%d.xyz = normalize(NormalMatrix * att%d.xyz);\n",
input->attribid, input->attribid);
BLI_dynstr_appendf(
ds, "\tvar%d.w = att%d.w;\n",
@@ -841,6 +1041,51 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
return code;
}
+static char *code_generate_geometry_new(ListBase *nodes, const char *geom_code)
+{
+ DynStr *ds = BLI_dynstr_new();
+ GPUNode *node;
+ GPUInput *input;
+ char *code;
+
+ /* Create prototype because attributes cannot be declared before layout. */
+ BLI_dynstr_appendf(ds, "void pass_attrib(in int vert);\n");
+ BLI_dynstr_append(ds, "#define ATTRIB\n");
+
+ BLI_dynstr_append(ds, geom_code);
+
+ /* Generate varying declarations. */
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+ BLI_dynstr_appendf(ds, "in %s var%dg[];\n",
+ GPU_DATATYPE_STR[input->type],
+ input->attribid);
+ BLI_dynstr_appendf(ds, "out %s var%d;\n",
+ GPU_DATATYPE_STR[input->type],
+ input->attribid);
+ }
+ }
+ }
+
+ /* Generate varying assignments. */
+ BLI_dynstr_appendf(ds, "void pass_attrib(in int vert) {\n");
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+ /* TODO let shader choose what to do depending on what the attrib is. */
+ BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", input->attribid, input->attribid);
+ }
+ }
+ }
+ BLI_dynstr_append(ds, "}\n");
+
+ code = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return code;
+}
+
static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
{
#ifdef WITH_OPENSUBDIV
@@ -928,6 +1173,67 @@ GPUShader *GPU_pass_shader(GPUPass *pass)
return pass->shader;
}
+static void gpu_nodes_extract_dynamic_inputs_new(GPUPass *pass, ListBase *nodes)
+{
+ GPUShader *shader = pass->shader;
+ GPUNode *node;
+ GPUInput *next, *input;
+ ListBase *inputs = &pass->inputs;
+ int extract, z;
+
+ memset(inputs, 0, sizeof(*inputs));
+
+ if (!shader)
+ return;
+
+ GPU_shader_bind(shader);
+
+ for (node = nodes->first; node; node = node->next) {
+ z = 0;
+ for (input = node->inputs.first; input; input = next, z++) {
+ next = input->next;
+
+ /* attributes don't need to be bound, they already have
+ * an id that the drawing functions will use */
+ if (input->source == GPU_SOURCE_ATTRIB) {
+ continue;
+ }
+
+ if (input->source == GPU_SOURCE_BUILTIN ||
+ input->source == GPU_SOURCE_OPENGL_BUILTIN)
+ {
+ continue;
+ }
+
+ if (input->ima || input->tex || input->prv)
+ BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
+ else
+ BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
+
+ /* pass non-dynamic uniforms to opengl */
+ extract = 0;
+
+ if (input->ima || input->tex || input->prv) {
+ if (input->bindtex)
+ extract = 1;
+ }
+ else if (input->dynamicvec)
+ extract = 1;
+
+ if (extract)
+ input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
+
+ /* extract nodes */
+ if (extract) {
+ BLI_remlink(&node->inputs, input);
+ BLI_addtail(inputs, input);
+ }
+ }
+ }
+
+ GPU_shader_unbind();
+}
+
static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
{
GPUShader *shader = pass->shader;
@@ -1135,7 +1441,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
name = outnode->name;
input = outnode->inputs.first;
- if ((STREQ(name, "set_value") || STREQ(name, "set_rgb")) &&
+ if ((STREQ(name, "set_value") || STREQ(name, "set_rgb") || STREQ(name, "set_rgba")) &&
(input->type == type))
{
input = MEM_dupallocN(outnode->inputs.first);
@@ -1194,7 +1500,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);
@@ -1235,6 +1541,12 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
MEM_freeN(link);
}
+ else if (type == GPU_CLOSURE) {
+ input->type = type;
+ input->source = GPU_SOURCE_STRUCT;
+
+ MEM_freeN(link);
+ }
else {
/* uniform vector */
input->type = type;
@@ -1246,21 +1558,100 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
input->dynamictype = link->dynamictype;
input->dynamicdata = link->ptr2;
}
+
MEM_freeN(link);
}
BLI_addtail(&node->inputs, input);
}
-static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
+
+static const char *gpu_uniform_set_function_from_type(eNodeSocketDatatype type)
+{
+ switch (type) {
+ case SOCK_FLOAT:
+ return "set_value";
+ case SOCK_VECTOR:
+ return "set_rgb";
+ case SOCK_RGBA:
+ return "set_rgba";
+ default:
+ BLI_assert(!"No gpu function for non-supported eNodeSocketDatatype");
+ return NULL;
+ }
+}
+
+/**
+ * Link stack uniform buffer.
+ * This is called for the input/output sockets that are note connected.
+ */
+static GPUNodeLink *gpu_uniformbuffer_link(
+ GPUMaterial *mat, bNode *node, GPUNodeStack *stack, const int index, const eNodeSocketInOut in_out)
{
- GPUNodeLink *link;
+ bNodeSocket *socket;
+
+ /* Some nodes can have been create on the fly and does
+ * not have an original to point to. (i.e. the bump from
+ * ntree_shader_relink_displacement). In this case just
+ * revert to static constant folding. */
+ if (node->original == NULL) {
+ return NULL;
+ }
+
+ if (in_out == SOCK_IN) {
+ socket = BLI_findlink(&node->original->inputs, index);
+ }
+ else {
+ socket = BLI_findlink(&node->original->outputs, index);
+ }
+
+ BLI_assert(socket != NULL);
+ BLI_assert(socket->in_out == in_out);
+
+ if ((socket->flag & SOCK_HIDE_VALUE) == 0) {
+ GPUNodeLink *link;
+ switch (socket->type) {
+ case SOCK_FLOAT:
+ {
+ bNodeSocketValueFloat *socket_data = socket->default_value;
+ link = GPU_uniform_buffer(&socket_data->value, GPU_FLOAT);
+ break;
+ }
+ case SOCK_VECTOR:
+ {
+ bNodeSocketValueRGBA *socket_data = socket->default_value;
+ link = GPU_uniform_buffer(socket_data->value, GPU_VEC3);
+ break;
+ }
+ case SOCK_RGBA:
+ {
+ bNodeSocketValueRGBA *socket_data = socket->default_value;
+ link = GPU_uniform_buffer(socket_data->value, GPU_VEC4);
+ break;
+ }
+ default:
+ return NULL;
+ break;
+ }
+
+ if (in_out == SOCK_IN) {
+ GPU_link(mat, gpu_uniform_set_function_from_type(socket->type), link, &stack->link);
+ }
+ return link;
+ }
+ return NULL;
+}
+static void gpu_node_input_socket(GPUMaterial *material, bNode *bnode, GPUNode *node, GPUNodeStack *sock, const int index)
+{
if (sock->link) {
gpu_node_input_link(node, sock->link, sock->type);
}
+ else if ((material != NULL) && (gpu_uniformbuffer_link(material, bnode, sock, index, SOCK_IN) != NULL)) {
+ gpu_node_input_link(node, sock->link, sock->type);
+ }
else {
- link = GPU_node_link_create();
+ GPUNodeLink *link = GPU_node_link_create();
link->ptr1 = sock->vec;
gpu_node_input_link(node, link, sock->type);
}
@@ -1387,7 +1778,14 @@ GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
{
GPUNodeLink *link = GPU_node_link_create();
- link->attribtype = type;
+ /* Fall back to the UV layer, which matches old behavior. */
+ if (type == CD_AUTO_FROM_NAME && name[0] == '\0') {
+ link->attribtype = CD_MTFACE;
+ }
+ else {
+ link->attribtype = type;
+ }
+
link->attribname = name;
return link;
@@ -1416,6 +1814,21 @@ GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *d
return link;
}
+/**
+ * Add uniform to UBO struct of GPUMaterial.
+ */
+GPUNodeLink *GPU_uniform_buffer(float *num, GPUType gputype)
+{
+ GPUNodeLink *link = GPU_node_link_create();
+ link->ptr1 = num;
+ link->ptr2 = NULL;
+ link->dynamic = true;
+ link->dynamictype = GPU_DYNAMIC_UBO;
+ link->type = gputype;
+
+ return link;
+}
+
GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
{
GPUNodeLink *link = GPU_node_link_create();
@@ -1526,7 +1939,7 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
return true;
}
-bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
+bool GPU_stack_link(GPUMaterial *material, bNode *bnode, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
{
GPUNode *node;
GPUFunction *function;
@@ -1546,11 +1959,11 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
if (in) {
for (i = 0; in[i].type != GPU_NONE; i++) {
- gpu_node_input_socket(node, &in[i]);
+ gpu_node_input_socket(material, bnode, node, &in[i], i);
totin++;
}
}
-
+
if (out) {
for (i = 0; out[i].type != GPU_NONE; i++) {
gpu_node_output(node, out[i].type, &out[i].link);
@@ -1572,7 +1985,7 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
if (totin == 0) {
link = va_arg(params, GPUNodeLink *);
if (link->socket)
- gpu_node_input_socket(node, link->socket);
+ gpu_node_input_socket(NULL, NULL, node, link->socket, -1);
else
gpu_node_input_link(node, link, function->paramtype[i]);
}
@@ -1582,8 +1995,8 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
}
va_end(params);
- gpu_material_add_node(mat, node);
-
+ gpu_material_add_node(material, node);
+
return true;
}
@@ -1608,6 +2021,11 @@ int GPU_link_changed(GPUNodeLink *link)
return 0;
}
+GPUNodeLink *GPU_uniformbuffer_link_out(GPUMaterial *mat, bNode *node, GPUNodeStack *stack, const int index)
+{
+ return gpu_uniformbuffer_link(mat, node, stack, index, SOCK_OUT);
+}
+
/* Pass create/free */
static void gpu_nodes_tag(GPUNodeLink *link)
@@ -1647,6 +2065,78 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
}
}
+GPUPass *GPU_generate_pass_new(
+ struct GPUMaterial *material,
+ ListBase *nodes, struct GPUNodeLink *frag_outlink,
+ GPUVertexAttribs *attribs,
+ const char *vert_code, const char *geom_code,
+ const char *frag_lib, const char *defines)
+{
+ GPUShader *shader;
+ GPUPass *pass;
+ char *vertexgen, *fragmentgen, *tmp;
+ char *vertexcode, *geometrycode, *fragmentcode;
+
+ /* prune unused nodes */
+ gpu_nodes_prune(nodes, frag_outlink);
+
+ gpu_nodes_get_vertex_attributes(nodes, attribs);
+
+ /* generate code and compile with opengl */
+ fragmentgen = code_generate_fragment(material, nodes, frag_outlink->output, true);
+ vertexgen = code_generate_vertex_new(nodes, vert_code, (geom_code != NULL));
+
+ tmp = BLI_strdupcat(frag_lib, glsl_material_library);
+ fragmentcode = BLI_strdupcat(tmp, fragmentgen);
+ vertexcode = BLI_strdup(vertexgen);
+
+ if (geom_code) {
+ geometrycode = code_generate_geometry_new(nodes, geom_code);
+ }
+ else {
+ geometrycode = NULL;
+ }
+
+ shader = GPU_shader_create(vertexcode,
+ fragmentcode,
+ geometrycode,
+ NULL,
+ defines);
+
+ MEM_freeN(tmp);
+
+ /* failed? */
+ if (!shader) {
+ if (fragmentcode)
+ MEM_freeN(fragmentcode);
+ if (vertexcode)
+ MEM_freeN(vertexcode);
+ if (geometrycode)
+ MEM_freeN(geometrycode);
+ MEM_freeN(fragmentgen);
+ MEM_freeN(vertexgen);
+ gpu_nodes_free(nodes);
+ return NULL;
+ }
+
+ /* create pass */
+ pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
+ pass->shader = shader;
+ pass->fragmentcode = fragmentcode;
+ pass->geometrycode = geometrycode;
+ pass->vertexcode = vertexcode;
+ pass->libcode = glsl_material_library;
+
+ /* extract dynamic inputs and throw away nodes */
+ gpu_nodes_extract_dynamic_inputs_new(pass, nodes);
+ gpu_nodes_free(nodes);
+
+ MEM_freeN(fragmentgen);
+ MEM_freeN(vertexgen);
+
+ return pass;
+}
+
GPUPass *GPU_generate_pass(
ListBase *nodes, GPUNodeLink *outlink,
GPUVertexAttribs *attribs, int *builtins,
@@ -1672,7 +2162,7 @@ GPUPass *GPU_generate_pass(
gpu_nodes_get_builtin_flag(nodes, builtins);
/* generate code and compile with opengl */
- fragmentcode = code_generate_fragment(nodes, outlink->output);
+ fragmentcode = code_generate_fragment(NULL, nodes, outlink->output, false);
vertexcode = code_generate_vertex(nodes, type);
geometrycode = code_generate_geometry(nodes, use_opensubdiv);
@@ -1688,9 +2178,6 @@ GPUPass *GPU_generate_pass(
geometrycode,
glsl_material_library,
NULL,
- 0,
- 0,
- 0,
flags);
/* failed? */
@@ -1708,7 +2195,6 @@ GPUPass *GPU_generate_pass(
/* create pass */
pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
- pass->output = outlink->output;
pass->shader = shader;
pass->fragmentcode = fragmentcode;
pass->geometrycode = geometrycode;
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 7af17f9122d..14e07a6e012 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -57,7 +57,8 @@ typedef enum GPUDataSource {
GPU_SOURCE_OPENGL_BUILTIN,
GPU_SOURCE_TEX_PIXEL,
GPU_SOURCE_TEX,
- GPU_SOURCE_ATTRIB
+ GPU_SOURCE_ATTRIB,
+ GPU_SOURCE_STRUCT
} GPUDataSource;
typedef enum {
@@ -156,10 +157,7 @@ typedef struct GPUInput {
} GPUInput;
struct GPUPass {
- struct GPUPass *next, *prev;
-
ListBase inputs;
- struct GPUOutput *output;
struct GPUShader *shader;
char *fragmentcode;
char *geometrycode;
@@ -170,11 +168,18 @@ struct GPUPass {
typedef struct GPUPass GPUPass;
-GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
- struct GPUVertexAttribs *attribs, int *builtin,
- const GPUMatType type, const char *name,
- const bool use_opensubdiv,
- const bool use_new_shading);
+GPUPass *GPU_generate_pass_new(
+ struct GPUMaterial *material,
+ ListBase *nodes, struct GPUNodeLink *frag_outlink,
+ struct GPUVertexAttribs *attribs,
+ const char *vert_code, const char *geom_code,
+ const char *frag_lib, const char *defines);
+GPUPass *GPU_generate_pass(
+ ListBase *nodes, struct GPUNodeLink *outlink,
+ struct GPUVertexAttribs *attribs, int *builtin,
+ const GPUMatType type, const char *name,
+ const bool use_opensubdiv,
+ const bool use_new_shading);
struct GPUShader *GPU_pass_shader(GPUPass *pass);
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
index 2f2a16f9e1d..12ed67cdf4e 100644
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -42,11 +42,13 @@
#include "DNA_gpu_types.h"
#include "GPU_compositing.h"
+#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
#include "GPU_glew.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_batch.h"
#include "MEM_guardedalloc.h"
@@ -193,7 +195,8 @@ struct GPUFX {
/* we have a stencil, restore the previous state */
bool restore_stencil;
- unsigned int vbuffer;
+ Gwn_Batch *quad_batch;
+ Gwn_Batch *point_batch;
};
#if 0
@@ -225,7 +228,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 +256,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;
}
@@ -257,12 +272,32 @@ GPUFX *GPU_fx_compositor_create(void)
{
GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor");
- glGenBuffers(1, &fx->vbuffer);
- glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer);
- glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STATIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * sizeof(float), fullscreencos);
- glBufferSubData(GL_ARRAY_BUFFER, 8 * sizeof(float), 8 * sizeof(float), fullscreenuvs);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+ /* Quad buffer */
+ static Gwn_VertFormat format = {0};
+ static unsigned int pos, uvs;
+ if (format.attrib_ct == 0) {
+ pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, 4);
+ for (int i = 0; i < 4; ++i) {
+ GWN_vertbuf_attr_set(vbo, pos, i, fullscreencos[i]);
+ GWN_vertbuf_attr_set(vbo, uvs, i, fullscreenuvs[i]);
+ }
+ fx->quad_batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+
+ /* Point Buffer */
+ static Gwn_VertFormat format_point = {0};
+ static unsigned int dummy_attrib;
+ if (format_point.attrib_ct == 0) {
+ dummy_attrib = GWN_vertformat_attr_add(&format_point, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+ float dummy[2] = {0.0f, 0.0f};
+ Gwn_VertBuf *vbo_point = GWN_vertbuf_create_with_format(&format_point);
+ GWN_vertbuf_data_alloc(vbo_point, 1);
+ GWN_vertbuf_attr_set(vbo_point, dummy_attrib, 0, &dummy);
+ fx->point_batch = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo_point, NULL, GWN_BATCH_OWNS_VBO);
return fx;
}
@@ -352,12 +387,14 @@ static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo)
void GPU_fx_compositor_destroy(GPUFX *fx)
{
cleanup_fx_gl_data(fx, true);
- glDeleteBuffers(1, &fx->vbuffer);
+ GWN_batch_discard(fx->quad_batch);
+ GWN_batch_discard(fx->point_batch);
MEM_freeN(fx);
}
static GPUTexture * create_jitter_texture(void)
{
+ GPUTexture *tex;
float jitter[64 * 64][2];
int i;
@@ -367,7 +404,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;
}
@@ -382,9 +427,6 @@ bool GPU_fx_compositor_initialize_passes(
fx->effects = 0;
- if (!GLEW_EXT_framebuffer_object)
- return false;
-
if (!fx_settings) {
cleanup_fx_gl_data(fx, true);
return false;
@@ -436,7 +478,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;
@@ -472,8 +514,7 @@ bool GPU_fx_compositor_initialize_passes(
/* create textures for dof effect */
if (fx_flag & GPU_FX_FLAG_DOF) {
- bool dof_high_quality = (fx_settings->dof->high_quality != 0) &&
- GPU_geometry_shader_support() && GPU_instanced_drawing_support();
+ bool dof_high_quality = (fx_settings->dof->high_quality != 0);
/* cleanup buffers if quality setting has changed (no need to keep more buffers around than necessary ) */
if (dof_high_quality != fx->dof_high_quality)
@@ -488,38 +529,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, 4, 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, 4, GPU_RGBA16F, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
@@ -534,21 +579,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);
@@ -567,7 +612,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;
@@ -585,11 +630,8 @@ bool GPU_fx_compositor_initialize_passes(
/* bind the buffers */
/* first depth buffer, because system assumes read/write buffers */
- if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out))
- printf("%.256s\n", err_out);
-
- if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out))
- printf("%.256s\n", err_out);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, 0);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, 0);
if (!GPU_framebuffer_check_valid(fx->gbuffer, err_out))
printf("%.256s\n", err_out);
@@ -600,7 +642,7 @@ bool GPU_fx_compositor_initialize_passes(
if (scissor_rect) {
int w_sc = BLI_rcti_size_x(scissor_rect) + 1;
int h_sc = BLI_rcti_size_y(scissor_rect) + 1;
- glPushAttrib(GL_SCISSOR_BIT);
+ gpuPushAttrib(GPU_SCISSOR_BIT);
glEnable(GL_SCISSOR_TEST);
glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin,
w_sc, h_sc);
@@ -634,7 +676,7 @@ static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOff
}
else {
/* bind the ping buffer to the color buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, 0);
}
}
@@ -663,8 +705,7 @@ void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray)
GPU_framebuffer_texture_detach(fx->depth_buffer);
/* first depth buffer, because system assumes read/write buffers */
- if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, err_out))
- printf("%.256s\n", err_out);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, 0);
}
@@ -674,39 +715,35 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
/* attach regular framebuffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, 0);
/* full screen quad where we will always write to depth buffer */
- glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT);
+ gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_SCISSOR_BIT);
glDepthFunc(GL_ALWAYS);
/* disable scissor from sculpt if any */
glDisable(GL_SCISSOR_TEST);
/* disable writing to color buffer, it's depth only pass */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- /* set up quad buffer */
- glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer);
- glVertexPointer(2, GL_FLOAT, 0, NULL);
- glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float)));
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false);
if (depth_resolve_shader) {
- GPUDepthResolveInterface *interface = GPU_shader_get_interface(depth_resolve_shader);
+ GPUDepthResolveInterface *interface = GPU_fx_shader_get_interface(depth_resolve_shader);
- GPU_shader_bind(depth_resolve_shader);
+ /* set up quad buffer */
+ GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(depth_resolve_shader), GPU_shader_get_interface(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);
+ GWN_batch_draw(fx->quad_batch);
/* 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();
@@ -714,11 +751,7 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glPopAttrib();
+ gpuPopAttrib();
}
@@ -748,19 +781,13 @@ bool GPU_fx_do_composite_pass(
GPU_framebuffer_texture_detach(fx->color_buffer);
GPU_framebuffer_texture_detach(fx->depth_buffer);
- if (fx->restore_stencil)
- glPopAttrib();
+ if (fx->restore_stencil) {
+ gpuPopAttrib();
+ }
src = fx->color_buffer;
target = fx->color_buffer_sec;
- /* set up quad buffer */
- glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer);
- glVertexPointer(2, GL_FLOAT, 0, NULL);
- glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float)));
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
/* full screen FX pass */
/* invert the view matrix */
@@ -788,8 +815,6 @@ bool GPU_fx_do_composite_pass(
viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
}
- /* set invalid color in case shader fails */
- glColor3f(1.0, 0.0, 1.0);
glDisable(GL_DEPTH_TEST);
/* ssao pass */
@@ -810,9 +835,9 @@ bool GPU_fx_do_composite_pass(
ssao_params[3] = (passes_left == 1 && !ofs) ? dfdyfac[0] : dfdyfac[1];
- GPUSSAOShaderInterface *interface = GPU_shader_get_interface(ssao_shader);
+ GPUSSAOShaderInterface *interface = GPU_fx_shader_get_interface(ssao_shader);
- GPU_shader_bind(ssao_shader);
+ GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(ssao_shader), GPU_shader_get_interface(ssao_shader));
GPU_shader_uniform_vector(ssao_shader, interface->ssao_uniform, 4, 1, ssao_params);
GPU_shader_uniform_vector(ssao_shader, interface->ssao_color_uniform, 4, 1, fx_ssao->color);
@@ -823,7 +848,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++);
@@ -835,11 +861,12 @@ bool GPU_fx_do_composite_pass(
/* draw */
gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ GWN_batch_draw(fx->quad_batch);
/* 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);
@@ -892,11 +919,8 @@ bool GPU_fx_do_composite_pass(
if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3)) {
GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
GPU_framebuffer_restore();
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
GPU_shader_unbind();
- glBindBuffer(GL_ARRAY_BUFFER, 0);
return false;
}
@@ -904,9 +928,9 @@ bool GPU_fx_do_composite_pass(
{
float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
- GPUDOFHQPassOneInterface *interface = GPU_shader_get_interface(dof_shader_pass1);
+ GPUDOFHQPassOneInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass1);
- GPU_shader_bind(dof_shader_pass1);
+ GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass1), GPU_shader_get_interface(dof_shader_pass1));
GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
@@ -915,28 +939,31 @@ 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 */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, NULL);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1, NULL);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, 0);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1, 0);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2, 0);
/* binding takes care of setting the viewport to the downsampled size */
GPU_framebuffer_slots_bind(fx->gbuffer, 0);
GPU_framebuffer_check_valid(fx->gbuffer, NULL);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ GWN_batch_draw(fx->quad_batch);
+
/* 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);
@@ -953,24 +980,23 @@ bool GPU_fx_do_composite_pass(
int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h};
float selection[2] = {0.0f, 1.0f};
- GPUDOFHQPassTwoInterface *interface = GPU_shader_get_interface(dof_shader_pass2);
+ GPUDOFHQPassTwoInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass2);
- GPU_shader_bind(dof_shader_pass2);
+ GWN_batch_program_set(fx->point_batch, GPU_shader_get_program(dof_shader_pass2), GPU_shader_get_interface(dof_shader_pass2));
+
+ GPU_texture_bind(fx->dof_nearfar_coc, numslots++);
+ GPU_texture_bind(fx->dof_half_downsampled_far, numslots++);
+ GPU_texture_bind(fx->dof_half_downsampled_near, numslots++);
GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
GPU_shader_uniform_vector_int(dof_shader_pass2, interface->rendertargetdim_uniform, 2, 1, rendertargetdim);
GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
-
- GPU_texture_bind(fx->dof_nearfar_coc, numslots++);
GPU_shader_uniform_texture(dof_shader_pass2, interface->coc_uniform, fx->dof_nearfar_coc);
-
- 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, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0, 0);
GPU_texture_bind_as_framebuffer(fx->dof_far_blur);
glDisable(GL_DEPTH_TEST);
@@ -981,24 +1007,24 @@ bool GPU_fx_do_composite_pass(
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
/* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
- glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h);
+ GWN_batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, NULL, NULL);
GPU_texture_unbind(fx->dof_half_downsampled_far);
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);
-
selection[0] = 1.0f;
selection[1] = 0.0f;
GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
+ 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);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, 0);
/* have to clear the buffer unfortunately */
glClear(GL_COLOR_BUFFER_BIT);
/* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
- glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h);
+ GWN_batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, NULL, NULL);
+ GWN_batch_program_use_end(fx->point_batch);
/* disable bindings */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -1010,15 +1036,16 @@ bool GPU_fx_do_composite_pass(
GPU_texture_unbind(fx->dof_nearfar_coc);
GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_far_blur);
+ numslots = 0;
}
/* third pass, accumulate the near/far blur fields */
{
float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
- GPUDOFHQPassThreeInterface *interface = GPU_shader_get_interface(dof_shader_pass3);
+ GPUDOFHQPassThreeInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass3);
- GPU_shader_bind(dof_shader_pass3);
+ GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass3), GPU_shader_get_interface(dof_shader_pass3));
GPU_shader_uniform_vector(dof_shader_pass3, interface->dof_uniform, 4, 1, dof_params);
@@ -1027,14 +1054,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++);
@@ -1043,13 +1071,13 @@ bool GPU_fx_do_composite_pass(
/* if this is the last pass, prepare for rendering on the frambuffer */
gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ GWN_batch_draw(fx->quad_batch);
/* disable bindings */
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 */
@@ -1085,11 +1113,8 @@ bool GPU_fx_do_composite_pass(
if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) {
GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
GPU_framebuffer_restore();
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
GPU_shader_unbind();
- glBindBuffer(GL_ARRAY_BUFFER, 0);
return false;
}
@@ -1097,9 +1122,9 @@ bool GPU_fx_do_composite_pass(
{
float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
- GPUDOFPassOneInterface *interface = GPU_shader_get_interface(dof_shader_pass1);
+ GPUDOFPassOneInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass1);
- GPU_shader_bind(dof_shader_pass1);
+ GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass1), GPU_shader_get_interface(dof_shader_pass1));
GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
@@ -1109,18 +1134,20 @@ 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 */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, 0);
/* binding takes care of setting the viewport to the downsampled size */
GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ GWN_batch_draw(fx->quad_batch);
/* 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);
@@ -1134,32 +1161,37 @@ bool GPU_fx_do_composite_pass(
float tmp = invrendertargetdim[0];
invrendertargetdim[0] = 0.0f;
- GPUDOFPassTwoInterface *interface = GPU_shader_get_interface(dof_shader_pass2);
+ GPUDOFPassTwoInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass2);
dof_params[2] = GPU_texture_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
/* Blurring vertically */
- GPU_shader_bind(dof_shader_pass2);
+ GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass2), GPU_shader_get_interface(dof_shader_pass2));
GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
GPU_shader_uniform_vector(dof_shader_pass2, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
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++);
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_buffer);
/* use final buffer as a temp here */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, 0);
/* Drawing quad */
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ GWN_batch_draw(fx->quad_batch);
+
+ /* Rebind Shader */
+ GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass2), GPU_shader_get_interface(dof_shader_pass2));
/* *unbind/detach */
GPU_texture_unbind(fx->dof_near_coc_buffer);
+
GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
/* Blurring horizontally */
@@ -1170,11 +1202,13 @@ bool GPU_fx_do_composite_pass(
GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_final_buffer);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, 0);
+
+ GWN_batch_draw(fx->quad_batch);
/* *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);
@@ -1187,9 +1221,9 @@ bool GPU_fx_do_composite_pass(
/* third pass, calculate near coc */
{
- GPUDOFPassThreeInterface *interface = GPU_shader_get_interface(dof_shader_pass3);
+ GPUDOFPassThreeInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass3);
- GPU_shader_bind(dof_shader_pass3);
+ GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass3), GPU_shader_get_interface(dof_shader_pass3));
GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_downsampled, fx->dof_near_coc_buffer);
@@ -1197,9 +1231,9 @@ bool GPU_fx_do_composite_pass(
GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_blurred, fx->dof_near_coc_blurred_buffer);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, 0);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ GWN_batch_draw(fx->quad_batch);
/* disable bindings */
GPU_texture_unbind(fx->dof_near_coc_buffer);
GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
@@ -1215,17 +1249,17 @@ bool GPU_fx_do_composite_pass(
float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
- GPUDOFPassFourInterface *interface = GPU_shader_get_interface(dof_shader_pass4);
+ GPUDOFPassFourInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass4);
- GPU_shader_bind(dof_shader_pass4);
+ GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass4), GPU_shader_get_interface(dof_shader_pass4));
GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
GPU_shader_uniform_texture(dof_shader_pass4, interface->near_coc_downsampled, fx->dof_near_coc_final_buffer);
GPU_shader_uniform_vector(dof_shader_pass4, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, 0);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ GWN_batch_draw(fx->quad_batch);
/* disable bindings */
GPU_texture_unbind(fx->dof_near_coc_final_buffer);
@@ -1240,9 +1274,9 @@ bool GPU_fx_do_composite_pass(
{
float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
- GPUDOFPassFiveInterface *interface = GPU_shader_get_interface(dof_shader_pass5);
+ GPUDOFPassFiveInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass5);
- GPU_shader_bind(dof_shader_pass5);
+ GWN_batch_program_set(fx->quad_batch, GPU_shader_get_program(dof_shader_pass5), GPU_shader_get_interface(dof_shader_pass5));
GPU_shader_uniform_vector(dof_shader_pass5, interface->dof_uniform, 4, 1, dof_params);
GPU_shader_uniform_vector(dof_shader_pass5, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
@@ -1258,18 +1292,20 @@ 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 */
gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ GWN_batch_draw(fx->quad_batch);
/* disable bindings */
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 */
@@ -1289,10 +1325,6 @@ bool GPU_fx_do_composite_pass(
}
}
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
GPU_shader_unbind();
return true;
@@ -1305,6 +1337,7 @@ void GPU_fx_compositor_init_dof_settings(GPUDOFSettings *fx_dof)
fx_dof->focus_distance = 1.0f;
fx_dof->sensor = 1.0f;
fx_dof->num_blades = 6;
+ fx_dof->ratio = 1.0f;
}
void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
@@ -1315,7 +1348,7 @@ void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
fx_ssao->samples = 20;
}
-void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect effect)
+void GPU_fx_shader_init_interface(GPUShader *shader, GPUFXShaderEffect effect)
{
if (!shader)
return;
@@ -1334,7 +1367,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->ssao_concentric_tex = GPU_shader_get_uniform(shader, "ssao_concentric_tex");
interface->ssao_jitter_uniform = GPU_shader_get_uniform(shader, "jitter_tex");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
@@ -1348,7 +1381,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
@@ -1362,7 +1395,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->select_uniform = GPU_shader_get_uniform(shader, "layerselection");
interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
@@ -1378,7 +1411,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
@@ -1392,7 +1425,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
@@ -1405,7 +1438,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
@@ -1415,7 +1448,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
interface->near_coc_blurred = GPU_shader_get_uniform(shader, "blurredcolorbuffer");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
@@ -1425,7 +1458,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
@@ -1440,7 +1473,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
@@ -1450,7 +1483,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c
index 859aab9565f..8aea87ef659 100644
--- a/source/blender/gpu/intern/gpu_debug.c
+++ b/source/blender/gpu/intern/gpu_debug.c
@@ -20,7 +20,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): Brecht Van Lommel, Jason Wilkins.
+ * Contributor(s): Brecht Van Lommel, Jason Wilkins, Mike Erwin.
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -44,122 +44,18 @@
#include <stdlib.h>
#include <string.h>
-#define CASE_CODE_RETURN_STR(code) case code: return #code;
+#ifndef __APPLE__ /* only non-Apple systems implement OpenGL debug callbacks */
-static const char *gpu_gl_error_symbol(GLenum err)
-{
- switch (err) {
- CASE_CODE_RETURN_STR(GL_NO_ERROR)
- CASE_CODE_RETURN_STR(GL_INVALID_ENUM)
- CASE_CODE_RETURN_STR(GL_INVALID_VALUE)
- CASE_CODE_RETURN_STR(GL_INVALID_OPERATION)
- CASE_CODE_RETURN_STR(GL_STACK_OVERFLOW)
- CASE_CODE_RETURN_STR(GL_STACK_UNDERFLOW)
- CASE_CODE_RETURN_STR(GL_OUT_OF_MEMORY)
-
-#if GL_ARB_imaging
- CASE_CODE_RETURN_STR(GL_TABLE_TOO_LARGE)
-#endif
-
-#if defined(WITH_GLU)
- CASE_CODE_RETURN_STR(GLU_INVALID_ENUM)
- CASE_CODE_RETURN_STR(GLU_INVALID_VALUE)
- CASE_CODE_RETURN_STR(GLU_OUT_OF_MEMORY)
-#endif
+/* control whether we use older AMD_debug_output extension
+ * some supported GPU + OS combos do not have the newer extensions */
+# define LEGACY_DEBUG 1
- default:
- return "<unknown error>";
- }
-}
-
-#undef CASE_CODE_RETURN_STR
-
-
-static bool gpu_report_gl_errors(const char *file, int line, const char *str)
-{
- GLenum gl_error = glGetError();
-
- if (gl_error == GL_NO_ERROR) {
- return true;
- }
- else {
- /* glGetError should have cleared the error flag, so if we get the
- * same flag twice that means glGetError itself probably triggered
- * the error. This happens on Windows if the GL context is invalid.
- */
- {
- GLenum new_error = glGetError();
- if (gl_error == new_error) {
- fprintf(stderr, "GL: Possible context invalidation issue\n");
- return false;
- }
- }
-
- fprintf(stderr,
- "%s:%d: ``%s'' -> GL Error (0x%04X - %s): %s\n",
- file, line, str, gl_error,
- gpu_gl_error_symbol(gl_error),
- gpuErrorString(gl_error));
-
- return false;
- }
-}
-
-
-const char *gpuErrorString(GLenum err)
-{
- switch (err) {
- case GL_NO_ERROR:
- return "No Error";
-
- case GL_INVALID_ENUM:
- return "Invalid Enumeration";
-
- case GL_INVALID_VALUE:
- return "Invalid Value";
-
- case GL_INVALID_OPERATION:
- return "Invalid Operation";
-
- case GL_STACK_OVERFLOW:
- return "Stack Overflow";
-
- case GL_STACK_UNDERFLOW:
- return "Stack Underflow";
-
- case GL_OUT_OF_MEMORY:
- return "Out of Memory";
-
-#if GL_ARB_imaging
- case GL_TABLE_TOO_LARGE:
- return "Table Too Large";
-#endif
-
-#if defined(WITH_GLU)
- case GLU_INVALID_ENUM:
- return "Invalid Enum (GLU)";
-
- case GLU_INVALID_VALUE:
- return "Invalid Value (GLU)";
-
- case GLU_OUT_OF_MEMORY:
- return "Out of Memory (GLU)";
-#endif
-
- default:
- return "<unknown error>";
- }
-}
-
-
-/* Debug callbacks need the same calling convention as OpenGL functions.
- */
-#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
- /* Win32 but not WinCE */
-# define APIENTRY __stdcall
-#else
-# define APIENTRY
-#endif
+/* Debug callbacks need the same calling convention as OpenGL functions. */
+# if defined(_WIN32)
+# define APIENTRY __stdcall
+# else
+# define APIENTRY
+# endif
static const char *source_name(GLenum source)
@@ -189,32 +85,11 @@ static const char *message_type_name(GLenum message)
}
}
-static const char *category_name_amd(GLenum category)
-{
- switch (category) {
- case GL_DEBUG_CATEGORY_API_ERROR_AMD: return "API error";
- case GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD: return "window system";
- case GL_DEBUG_CATEGORY_DEPRECATION_AMD: return "deprecated behavior";
- case GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD: return "undefined behavior";
- case GL_DEBUG_CATEGORY_PERFORMANCE_AMD: return "performance";
- case GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD: return "shader compiler";
- case GL_DEBUG_CATEGORY_APPLICATION_AMD: return "application";
- case GL_DEBUG_CATEGORY_OTHER_AMD: return "other";
- default: return "???";
- }
-}
-
-
static void APIENTRY gpu_debug_proc(
GLenum source, GLenum type, GLuint UNUSED(id),
GLenum severity, GLsizei UNUSED(length),
const GLchar *message, const GLvoid *UNUSED(userParm))
{
- if (type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR) {
- /* Blender 2.7x uses OpenGL 2.1, we don't care if features are deprecated */
- return;
- }
-
bool backtrace = false;
switch (severity) {
@@ -233,18 +108,28 @@ static void APIENTRY gpu_debug_proc(
}
}
+# if LEGACY_DEBUG
+
+static const char *category_name_amd(GLenum category)
+{
+ switch (category) {
+ case GL_DEBUG_CATEGORY_API_ERROR_AMD: return "API error";
+ case GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD: return "window system";
+ case GL_DEBUG_CATEGORY_DEPRECATION_AMD: return "deprecated behavior";
+ case GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD: return "undefined behavior";
+ case GL_DEBUG_CATEGORY_PERFORMANCE_AMD: return "performance";
+ case GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD: return "shader compiler";
+ case GL_DEBUG_CATEGORY_APPLICATION_AMD: return "application";
+ case GL_DEBUG_CATEGORY_OTHER_AMD: return "other";
+ default: return "???";
+ }
+}
-#ifndef GLEW_ES_ONLY
static void APIENTRY gpu_debug_proc_amd(
GLuint UNUSED(id), GLenum category,
GLenum severity, GLsizei UNUSED(length),
const GLchar *message, GLvoid *UNUSED(userParm))
{
- if (category == GL_DEBUG_CATEGORY_DEPRECATION_AMD) {
- /* Blender 2.7x uses OpenGL 2.1, we don't care if features are deprecated */
- return;
- }
-
bool backtrace = false;
switch (severity) {
@@ -261,148 +146,88 @@ static void APIENTRY gpu_debug_proc_amd(
fflush(stderr);
}
}
-#endif
+# endif /* LEGACY_DEBUG */
-
-#undef APIENTRY
+# undef APIENTRY
+#endif /* not Apple */
void gpu_debug_init(void)
{
+#ifdef __APPLE__
+ fprintf(stderr, "OpenGL debug callback is not available on Apple.\n");
+#else /* not Apple */
const char success[] = "Successfully hooked OpenGL debug callback.";
-#if !defined(WITH_GLEW_ES) && !defined(GLEW_ES_ONLY)
- if (GLEW_VERSION_4_3) {
- fprintf(stderr, "Using OpenGL 4.3 debug facilities\n");
- glEnable(GL_DEBUG_OUTPUT);
- glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
- glDebugMessageCallback((GLDEBUGPROC)gpu_debug_proc, mxGetCurrentContext());
- glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
- GPU_string_marker(success);
- return;
- }
-#endif
-
- if (GLEW_KHR_debug) {
-#ifndef GLEW_ES_ONLY
- fprintf(stderr, "Using KHR_debug extension\n");
+ if (GLEW_VERSION_4_3 || GLEW_KHR_debug) {
+ fprintf(stderr, "Using %s\n", GLEW_VERSION_4_3 ? "OpenGL 4.3 debug facilities" : "KHR_debug extension");
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
- glDebugMessageCallback((GLDEBUGPROC)gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageCallback((GLDEBUGPROC)gpu_debug_proc, NULL);
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
GPU_string_marker(success);
-#endif
- return;
}
-
-#ifndef GLEW_ES_ONLY
- if (GLEW_ARB_debug_output) {
+ else if (GLEW_ARB_debug_output) {
fprintf(stderr, "Using ARB_debug_output extension\n");
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
- glDebugMessageCallbackARB((GLDEBUGPROCARB)gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageCallbackARB((GLDEBUGPROCARB)gpu_debug_proc, NULL);
glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
GPU_string_marker(success);
-
- return;
}
-
- if (GLEW_AMD_debug_output) {
+# if LEGACY_DEBUG
+ else if (GLEW_AMD_debug_output) {
fprintf(stderr, "Using AMD_debug_output extension\n");
- glDebugMessageCallbackAMD(gpu_debug_proc_amd, mxGetCurrentContext());
+ glDebugMessageCallbackAMD(gpu_debug_proc_amd, NULL);
glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
GPU_string_marker(success);
-
- return;
}
-#endif
-
- fprintf(stderr, "Failed to hook OpenGL debug callback.\n");
-
- return;
+# endif
+ else {
+ fprintf(stderr, "Failed to hook OpenGL debug callback.\n");
+ }
+#endif /* not Apple */
}
void gpu_debug_exit(void)
{
-#ifndef WITH_GLEW_ES
-#ifndef GLEW_ES_ONLY
- if (GLEW_VERSION_4_3) {
- glDebugMessageCallback(NULL, NULL);
-
- return;
- }
-#endif
-#endif
-
- if (GLEW_KHR_debug) {
-#ifndef GLEW_ES_ONLY
+#ifndef __APPLE__
+ if (GLEW_VERSION_4_3 || GLEW_KHR_debug) {
glDebugMessageCallback(NULL, NULL);
-#endif
- return;
}
-
-#ifndef GLEW_ES_ONLY
- if (GLEW_ARB_debug_output) {
+ else if (GLEW_ARB_debug_output) {
glDebugMessageCallbackARB(NULL, NULL);
-
- return;
}
-
- if (GLEW_AMD_debug_output) {
+# if LEGACY_DEBUG
+ else if (GLEW_AMD_debug_output) {
glDebugMessageCallbackAMD(NULL, NULL);
-
- return;
}
+# endif
#endif
-
- return;
}
void GPU_string_marker(const char *buf)
{
-#ifndef WITH_GLEW_ES
-#ifndef GLEW_ES_ONLY
- if (GLEW_VERSION_4_3) {
- glDebugMessageInsert(
- GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0,
- GL_DEBUG_SEVERITY_NOTIFICATION, -1, buf);
-
- return;
- }
-#endif
-#endif
-
- if (GLEW_KHR_debug) {
-#ifndef GLEW_ES_ONLY
+#ifdef __APPLE__
+ UNUSED_VARS(buf);
+#else /* not Apple */
+ if (GLEW_VERSION_4_3 || GLEW_KHR_debug) {
glDebugMessageInsert(
GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0,
GL_DEBUG_SEVERITY_NOTIFICATION, -1, buf);
-#endif
- return;
}
-
-#ifndef GLEW_ES_ONLY
- if (GLEW_ARB_debug_output) {
+ else if (GLEW_ARB_debug_output) {
glDebugMessageInsertARB(
GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_OTHER_ARB, 0,
GL_DEBUG_SEVERITY_LOW_ARB, -1, buf);
-
- return;
}
-
- if (GLEW_AMD_debug_output) {
+# if LEGACY_DEBUG
+ else if (GLEW_AMD_debug_output) {
glDebugMessageInsertAMD(
GL_DEBUG_CATEGORY_APPLICATION_AMD, GL_DEBUG_SEVERITY_LOW_AMD, 0,
0, buf);
-
- return;
}
-
- if (GLEW_GREMEDY_string_marker) {
- glStringMarkerGREMEDY(0, buf);
-
- return;
- }
-#endif
+# endif
+#endif /* not Apple */
}
void GPU_print_error_debug(const char *str)
@@ -410,406 +235,3 @@ void GPU_print_error_debug(const char *str)
if (G.debug & G_DEBUG)
fprintf(stderr, "GPU: %s\n", str);
}
-
-
-void GPU_assert_no_gl_errors(const char *file, int line, const char *str)
-{
- if (G.debug) {
- GLboolean gl_ok = gpu_report_gl_errors(file, line, str);
-
- BLI_assert(gl_ok);
- (void) gl_ok;
- }
-}
-
-
-static void gpu_state_print_fl_ex(const char *name, GLenum type)
-{
-#define MAX_ARRAY_SIZE 64
-
- const unsigned char err_mark[4] = {0xff, 0xff, 0xff, 0xff};
-
- float value[MAX_ARRAY_SIZE];
- int a;
-
- memset(value, 0xff, sizeof(value));
- glGetFloatv(type, value);
-
- if (glGetError() == GL_NO_ERROR) {
- printf("%s: ", name);
- for (a = 0; a < MAX_ARRAY_SIZE; a++) {
- if (memcmp(&value[a], err_mark, sizeof(value[a])) == 0) {
- break;
- }
- printf("%.2f ", value[a]);
- }
- printf("\n");
- }
-
-#undef MAX_ARRAY_SIZE
-}
-
-#define gpu_state_print_fl(val) gpu_state_print_fl_ex(#val, val)
-
-void GPU_state_print(void)
-{
- GPU_ASSERT_NO_GL_ERRORS("GPU_state_print"); /* clear any errors */
-
- gpu_state_print_fl(GL_ACCUM_ALPHA_BITS);
- gpu_state_print_fl(GL_ACCUM_BLUE_BITS);
- gpu_state_print_fl(GL_ACCUM_CLEAR_VALUE);
- gpu_state_print_fl(GL_ACCUM_GREEN_BITS);
- gpu_state_print_fl(GL_ACCUM_RED_BITS);
- gpu_state_print_fl(GL_ACTIVE_TEXTURE);
- gpu_state_print_fl(GL_ALIASED_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_ALIASED_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_ALPHA_BIAS);
- gpu_state_print_fl(GL_ALPHA_BITS);
- gpu_state_print_fl(GL_ALPHA_SCALE);
- gpu_state_print_fl(GL_ALPHA_TEST);
- gpu_state_print_fl(GL_ALPHA_TEST_FUNC);
- gpu_state_print_fl(GL_ALPHA_TEST_REF);
- gpu_state_print_fl(GL_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_AUTO_NORMAL);
- gpu_state_print_fl(GL_AUX_BUFFERS);
- gpu_state_print_fl(GL_BLEND);
- gpu_state_print_fl(GL_BLEND_COLOR);
- gpu_state_print_fl(GL_BLEND_DST_ALPHA);
- gpu_state_print_fl(GL_BLEND_DST_RGB);
- gpu_state_print_fl(GL_BLEND_EQUATION_ALPHA);
- gpu_state_print_fl(GL_BLEND_EQUATION_RGB);
- gpu_state_print_fl(GL_BLEND_SRC_ALPHA);
- gpu_state_print_fl(GL_BLEND_SRC_RGB);
- gpu_state_print_fl(GL_BLUE_BIAS);
- gpu_state_print_fl(GL_BLUE_BITS);
- gpu_state_print_fl(GL_BLUE_SCALE);
- gpu_state_print_fl(GL_CLIENT_ACTIVE_TEXTURE);
- gpu_state_print_fl(GL_CLIENT_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_CLIP_PLANE0);
- gpu_state_print_fl(GL_COLOR_ARRAY);
- gpu_state_print_fl(GL_COLOR_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_COLOR_ARRAY_SIZE);
- gpu_state_print_fl(GL_COLOR_ARRAY_STRIDE);
- gpu_state_print_fl(GL_COLOR_ARRAY_TYPE);
- gpu_state_print_fl(GL_COLOR_CLEAR_VALUE);
- gpu_state_print_fl(GL_COLOR_LOGIC_OP);
- gpu_state_print_fl(GL_COLOR_MATERIAL);
- gpu_state_print_fl(GL_COLOR_MATERIAL_FACE);
- gpu_state_print_fl(GL_COLOR_MATERIAL_PARAMETER);
- gpu_state_print_fl(GL_COLOR_MATRIX);
- gpu_state_print_fl(GL_COLOR_MATRIX_STACK_DEPTH);
- gpu_state_print_fl(GL_COLOR_SUM);
- gpu_state_print_fl(GL_COLOR_TABLE);
- gpu_state_print_fl(GL_COLOR_WRITEMASK);
- gpu_state_print_fl(GL_NUM_COMPRESSED_TEXTURE_FORMATS);
- gpu_state_print_fl(GL_COMPRESSED_TEXTURE_FORMATS);
- gpu_state_print_fl(GL_CONVOLUTION_1D);
- gpu_state_print_fl(GL_CONVOLUTION_2D);
- gpu_state_print_fl(GL_CULL_FACE);
- gpu_state_print_fl(GL_CULL_FACE_MODE);
- gpu_state_print_fl(GL_CURRENT_COLOR);
- gpu_state_print_fl(GL_CURRENT_FOG_COORD);
- gpu_state_print_fl(GL_CURRENT_INDEX);
- gpu_state_print_fl(GL_CURRENT_NORMAL);
- gpu_state_print_fl(GL_CURRENT_PROGRAM);
- gpu_state_print_fl(GL_CURRENT_RASTER_COLOR);
- gpu_state_print_fl(GL_CURRENT_RASTER_DISTANCE);
- gpu_state_print_fl(GL_CURRENT_RASTER_INDEX);
- gpu_state_print_fl(GL_CURRENT_RASTER_POSITION);
- gpu_state_print_fl(GL_CURRENT_RASTER_POSITION_VALID);
- gpu_state_print_fl(GL_CURRENT_RASTER_SECONDARY_COLOR);
- gpu_state_print_fl(GL_CURRENT_RASTER_TEXTURE_COORDS);
- gpu_state_print_fl(GL_CURRENT_SECONDARY_COLOR);
- gpu_state_print_fl(GL_CURRENT_TEXTURE_COORDS);
- gpu_state_print_fl(GL_DEPTH_BIAS);
- gpu_state_print_fl(GL_DEPTH_BITS);
- gpu_state_print_fl(GL_DEPTH_CLEAR_VALUE);
- gpu_state_print_fl(GL_DEPTH_FUNC);
- gpu_state_print_fl(GL_DEPTH_RANGE);
- gpu_state_print_fl(GL_DEPTH_SCALE);
- gpu_state_print_fl(GL_DEPTH_TEST);
- gpu_state_print_fl(GL_DEPTH_WRITEMASK);
- gpu_state_print_fl(GL_DITHER);
- gpu_state_print_fl(GL_DOUBLEBUFFER);
- gpu_state_print_fl(GL_DRAW_BUFFER);
- gpu_state_print_fl(GL_DRAW_BUFFER0);
- gpu_state_print_fl(GL_EDGE_FLAG);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_STRIDE);
- gpu_state_print_fl(GL_ELEMENT_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_FEEDBACK_BUFFER_SIZE);
- gpu_state_print_fl(GL_FEEDBACK_BUFFER_TYPE);
- gpu_state_print_fl(GL_FOG);
- gpu_state_print_fl(GL_FOG_COLOR);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_STRIDE);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_TYPE);
- gpu_state_print_fl(GL_FOG_COORD_SRC);
- gpu_state_print_fl(GL_FOG_DENSITY);
- gpu_state_print_fl(GL_FOG_END);
- gpu_state_print_fl(GL_FOG_HINT);
- gpu_state_print_fl(GL_FOG_INDEX);
- gpu_state_print_fl(GL_FOG_MODE);
- gpu_state_print_fl(GL_FOG_START);
- gpu_state_print_fl(GL_FRAGMENT_PROGRAM_ARB); /* TODO: remove ARB program support */
- gpu_state_print_fl(GL_FRAGMENT_SHADER_DERIVATIVE_HINT);
- gpu_state_print_fl(GL_FRONT_FACE);
- gpu_state_print_fl(GL_GENERATE_MIPMAP_HINT);
- gpu_state_print_fl(GL_GREEN_BIAS);
- gpu_state_print_fl(GL_GREEN_BITS);
- gpu_state_print_fl(GL_GREEN_SCALE);
- gpu_state_print_fl(GL_HISTOGRAM);
- gpu_state_print_fl(GL_INDEX_ARRAY);
- gpu_state_print_fl(GL_INDEX_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_INDEX_ARRAY_STRIDE);
- gpu_state_print_fl(GL_INDEX_ARRAY_TYPE);
- gpu_state_print_fl(GL_INDEX_BITS);
- gpu_state_print_fl(GL_INDEX_CLEAR_VALUE);
- gpu_state_print_fl(GL_INDEX_LOGIC_OP);
- gpu_state_print_fl(GL_INDEX_MODE);
- gpu_state_print_fl(GL_INDEX_OFFSET);
- gpu_state_print_fl(GL_INDEX_SHIFT);
- gpu_state_print_fl(GL_INDEX_WRITEMASK);
- gpu_state_print_fl(GL_LIGHT0);
- gpu_state_print_fl(GL_LIGHT1);
- gpu_state_print_fl(GL_LIGHT2);
- gpu_state_print_fl(GL_LIGHT3);
- gpu_state_print_fl(GL_LIGHT4);
- gpu_state_print_fl(GL_LIGHT5);
- gpu_state_print_fl(GL_LIGHT6);
- gpu_state_print_fl(GL_LIGHT7);
- gpu_state_print_fl(GL_LIGHTING);
- gpu_state_print_fl(GL_LIGHT_MODEL_AMBIENT);
- gpu_state_print_fl(GL_LIGHT_MODEL_COLOR_CONTROL);
- gpu_state_print_fl(GL_LIGHT_MODEL_LOCAL_VIEWER);
- gpu_state_print_fl(GL_LIGHT_MODEL_TWO_SIDE);
- gpu_state_print_fl(GL_LINE_SMOOTH);
- gpu_state_print_fl(GL_LINE_SMOOTH_HINT);
- gpu_state_print_fl(GL_LINE_STIPPLE);
- gpu_state_print_fl(GL_LINE_STIPPLE_PATTERN);
- gpu_state_print_fl(GL_LINE_STIPPLE_REPEAT);
- gpu_state_print_fl(GL_LINE_WIDTH);
- gpu_state_print_fl(GL_LINE_WIDTH_GRANULARITY);
- gpu_state_print_fl(GL_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_LIST_BASE);
- gpu_state_print_fl(GL_LIST_INDEX);
- gpu_state_print_fl(GL_LIST_MODE);
- gpu_state_print_fl(GL_LOGIC_OP);
- gpu_state_print_fl(GL_LOGIC_OP_MODE);
- gpu_state_print_fl(GL_MAP1_COLOR_4);
- gpu_state_print_fl(GL_MAP1_GRID_DOMAIN);
- gpu_state_print_fl(GL_MAP1_GRID_SEGMENTS);
- gpu_state_print_fl(GL_MAP1_INDEX);
- gpu_state_print_fl(GL_MAP1_NORMAL);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_1);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_2);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_3);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_4);
- gpu_state_print_fl(GL_MAP1_VERTEX_3);
- gpu_state_print_fl(GL_MAP1_VERTEX_4);
- gpu_state_print_fl(GL_MAP2_COLOR_4);
- gpu_state_print_fl(GL_MAP2_GRID_DOMAIN);
- gpu_state_print_fl(GL_MAP2_GRID_SEGMENTS);
- gpu_state_print_fl(GL_MAP2_INDEX);
- gpu_state_print_fl(GL_MAP2_NORMAL);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_1);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_2);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_3);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_4);
- gpu_state_print_fl(GL_MAP2_VERTEX_3);
- gpu_state_print_fl(GL_MAP2_VERTEX_4);
- gpu_state_print_fl(GL_MAP_COLOR);
- gpu_state_print_fl(GL_MAP_STENCIL);
- gpu_state_print_fl(GL_MATRIX_MODE);
- gpu_state_print_fl(GL_MAX_3D_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_CLIP_PLANES);
- gpu_state_print_fl(GL_MAX_COLOR_MATRIX_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_CUBE_MAP_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_DRAW_BUFFERS);
- gpu_state_print_fl(GL_MAX_ELEMENTS_INDICES);
- gpu_state_print_fl(GL_MAX_ELEMENTS_VERTICES);
- gpu_state_print_fl(GL_MAX_EVAL_ORDER);
- gpu_state_print_fl(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
- gpu_state_print_fl(GL_MAX_LIGHTS);
- gpu_state_print_fl(GL_MAX_LIST_NESTING);
- gpu_state_print_fl(GL_MAX_MODELVIEW_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_NAME_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_PIXEL_MAP_TABLE);
- gpu_state_print_fl(GL_MAX_PROJECTION_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_TEXTURE_COORDS);
- gpu_state_print_fl(GL_MAX_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_TEXTURE_LOD_BIAS);
- gpu_state_print_fl(GL_MAX_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_TEXTURE_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_TEXTURE_UNITS);
- gpu_state_print_fl(GL_MAX_VARYING_FLOATS);
- gpu_state_print_fl(GL_MAX_VERTEX_ATTRIBS);
- gpu_state_print_fl(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_VERTEX_UNIFORM_COMPONENTS);
- gpu_state_print_fl(GL_MAX_VIEWPORT_DIMS);
- gpu_state_print_fl(GL_MINMAX);
- gpu_state_print_fl(GL_MODELVIEW_MATRIX);
- gpu_state_print_fl(GL_MODELVIEW_STACK_DEPTH);
- gpu_state_print_fl(GL_MULTISAMPLE);
- gpu_state_print_fl(GL_NAME_STACK_DEPTH);
- gpu_state_print_fl(GL_NORMALIZE);
- gpu_state_print_fl(GL_NORMAL_ARRAY);
- gpu_state_print_fl(GL_NORMAL_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_NORMAL_ARRAY_STRIDE);
- gpu_state_print_fl(GL_NORMAL_ARRAY_TYPE);
- gpu_state_print_fl(GL_NUM_COMPRESSED_TEXTURE_FORMATS);
- gpu_state_print_fl(GL_PACK_ALIGNMENT);
- gpu_state_print_fl(GL_PACK_IMAGE_HEIGHT);
- gpu_state_print_fl(GL_PACK_LSB_FIRST);
- gpu_state_print_fl(GL_PACK_ROW_LENGTH);
- gpu_state_print_fl(GL_PACK_SKIP_IMAGES);
- gpu_state_print_fl(GL_PACK_SKIP_PIXELS);
- gpu_state_print_fl(GL_PACK_SKIP_ROWS);
- gpu_state_print_fl(GL_PACK_SWAP_BYTES);
- gpu_state_print_fl(GL_PERSPECTIVE_CORRECTION_HINT);
- gpu_state_print_fl(GL_PIXEL_MAP_A_TO_A_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_B_TO_B_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_G_TO_G_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_A_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_B_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_G_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_I_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_R_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_R_TO_R_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_S_TO_S_SIZE);
- gpu_state_print_fl(GL_PIXEL_PACK_BUFFER_BINDING);
- gpu_state_print_fl(GL_PIXEL_UNPACK_BUFFER_BINDING);
- gpu_state_print_fl(GL_POINT_DISTANCE_ATTENUATION);
- gpu_state_print_fl(GL_POINT_FADE_THRESHOLD_SIZE);
- gpu_state_print_fl(GL_POINT_SIZE);
- gpu_state_print_fl(GL_POINT_SIZE_GRANULARITY);
- gpu_state_print_fl(GL_POINT_SIZE_MAX);
- gpu_state_print_fl(GL_POINT_SIZE_MIN);
- gpu_state_print_fl(GL_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_POINT_SMOOTH);
- gpu_state_print_fl(GL_POINT_SMOOTH_HINT);
- gpu_state_print_fl(GL_POINT_SPRITE);
- gpu_state_print_fl(GL_POLYGON_MODE);
- gpu_state_print_fl(GL_POLYGON_OFFSET_FACTOR);
- gpu_state_print_fl(GL_POLYGON_OFFSET_FILL);
- gpu_state_print_fl(GL_POLYGON_OFFSET_LINE);
- gpu_state_print_fl(GL_POLYGON_OFFSET_POINT);
- gpu_state_print_fl(GL_POLYGON_OFFSET_UNITS);
- gpu_state_print_fl(GL_POLYGON_SMOOTH);
- gpu_state_print_fl(GL_POLYGON_SMOOTH_HINT);
- gpu_state_print_fl(GL_POLYGON_STIPPLE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_COLOR_TABLE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_COLOR_TABLE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_RED_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_RED_SCALE);
- gpu_state_print_fl(GL_PROJECTION_MATRIX);
- gpu_state_print_fl(GL_PROJECTION_STACK_DEPTH);
- gpu_state_print_fl(GL_READ_BUFFER);
- gpu_state_print_fl(GL_RED_BIAS);
- gpu_state_print_fl(GL_RED_BITS);
- gpu_state_print_fl(GL_RED_SCALE);
- gpu_state_print_fl(GL_RENDER_MODE);
- gpu_state_print_fl(GL_RESCALE_NORMAL);
- gpu_state_print_fl(GL_RGBA_MODE);
- gpu_state_print_fl(GL_SAMPLES);
- gpu_state_print_fl(GL_SAMPLE_BUFFERS);
- gpu_state_print_fl(GL_SAMPLE_COVERAGE_INVERT);
- gpu_state_print_fl(GL_SAMPLE_COVERAGE_VALUE);
- gpu_state_print_fl(GL_SCISSOR_BOX);
- gpu_state_print_fl(GL_SCISSOR_TEST);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_SIZE);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_STRIDE);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_TYPE);
- gpu_state_print_fl(GL_SELECTION_BUFFER_SIZE);
- gpu_state_print_fl(GL_SEPARABLE_2D);
- gpu_state_print_fl(GL_SHADE_MODEL);
- gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_GRANULARITY);
- gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_GRANULARITY);
- gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_STENCIL_BACK_FAIL);
- gpu_state_print_fl(GL_STENCIL_BACK_FUNC);
- gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_FAIL);
- gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_PASS);
- gpu_state_print_fl(GL_STENCIL_BACK_REF);
- gpu_state_print_fl(GL_STENCIL_BACK_VALUE_MASK);
- gpu_state_print_fl(GL_STENCIL_BACK_WRITEMASK);
- gpu_state_print_fl(GL_STENCIL_BITS);
- gpu_state_print_fl(GL_STENCIL_CLEAR_VALUE);
- gpu_state_print_fl(GL_STENCIL_FAIL);
- gpu_state_print_fl(GL_STENCIL_FUNC);
- gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_FAIL);
- gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_PASS);
- gpu_state_print_fl(GL_STENCIL_REF);
- gpu_state_print_fl(GL_STENCIL_TEST);
- gpu_state_print_fl(GL_STENCIL_VALUE_MASK);
- gpu_state_print_fl(GL_STENCIL_WRITEMASK);
- gpu_state_print_fl(GL_STEREO);
- gpu_state_print_fl(GL_SUBPIXEL_BITS);
- gpu_state_print_fl(GL_TEXTURE_1D);
- gpu_state_print_fl(GL_TEXTURE_2D);
- gpu_state_print_fl(GL_TEXTURE_3D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_1D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_2D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_3D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_CUBE_MAP);
- gpu_state_print_fl(GL_TEXTURE_COMPRESSION_HINT);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_SIZE);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_STRIDE);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_TYPE);
- gpu_state_print_fl(GL_TEXTURE_CUBE_MAP);
- gpu_state_print_fl(GL_TEXTURE_GEN_Q);
- gpu_state_print_fl(GL_TEXTURE_GEN_R);
- gpu_state_print_fl(GL_TEXTURE_GEN_S);
- gpu_state_print_fl(GL_TEXTURE_GEN_T);
- gpu_state_print_fl(GL_TEXTURE_MATRIX);
- gpu_state_print_fl(GL_TEXTURE_STACK_DEPTH);
- gpu_state_print_fl(GL_TRANSPOSE_COLOR_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_MODELVIEW_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_PROJECTION_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_TEXTURE_MATRIX);
- gpu_state_print_fl(GL_UNPACK_ALIGNMENT);
- gpu_state_print_fl(GL_UNPACK_IMAGE_HEIGHT);
- gpu_state_print_fl(GL_UNPACK_LSB_FIRST);
- gpu_state_print_fl(GL_UNPACK_ROW_LENGTH);
- gpu_state_print_fl(GL_UNPACK_SKIP_IMAGES);
- gpu_state_print_fl(GL_UNPACK_SKIP_PIXELS);
- gpu_state_print_fl(GL_UNPACK_SKIP_ROWS);
- gpu_state_print_fl(GL_UNPACK_SWAP_BYTES);
- gpu_state_print_fl(GL_VERTEX_ARRAY);
- gpu_state_print_fl(GL_VERTEX_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_VERTEX_ARRAY_SIZE);
- gpu_state_print_fl(GL_VERTEX_ARRAY_STRIDE);
- gpu_state_print_fl(GL_VERTEX_ARRAY_TYPE);
- gpu_state_print_fl(GL_VERTEX_PROGRAM_POINT_SIZE);
- gpu_state_print_fl(GL_VERTEX_PROGRAM_TWO_SIDE);
- gpu_state_print_fl(GL_VIEWPORT);
- gpu_state_print_fl(GL_ZOOM_X);
- gpu_state_print_fl(GL_ZOOM_Y);
-}
-
-#undef gpu_state_print_fl
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 427e179f29a..f9cf3235ac1 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"
@@ -81,6 +79,7 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_material.h"
+#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -109,23 +108,27 @@ static void gpu_mcol(unsigned int ucol)
}
void GPU_render_text(
- MTexPoly *mtexpoly, int mode,
- const char *textstr, int textlen, unsigned int *col,
+ int mode, const char *textstr, int textlen, unsigned int *col,
const float *v_quad[4], const float *uv_quad[4],
int glattrib)
{
- if ((mode & GEMAT_TEXT) && (textlen > 0) && mtexpoly->tpage) {
+ /* XXX, 2.8 removes texface */
+#if 0
+ Image *ima = mtexpoly->tpage;
+#else
+ Image *ima = NULL;
+#endif
+ if ((mode & GEMAT_TEXT) && (textlen > 0) && ima) {
const float *v1 = v_quad[0];
const float *v2 = v_quad[1];
const float *v3 = v_quad[2];
const float *v4 = v_quad[3];
- Image *ima = (Image *)mtexpoly->tpage;
const size_t textlen_st = textlen;
float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
-
+
/* multiline */
float line_start = 0.0f, line_height;
-
+
if (v4)
line_height = max_ffff(v1[1], v2[1], v3[1], v4[2]) - min_ffff(v1[1], v2[1], v3[1], v4[2]);
else
@@ -133,50 +136,48 @@ void GPU_render_text(
line_height *= 1.2f; /* could be an option? */
/* end multiline */
-
+
/* color has been set */
- if (mtexpoly->mode & TF_OBCOL)
- col = NULL;
- else if (!col)
+ if (!col)
glColor3f(1.0f, 1.0f, 1.0f);
- glPushMatrix();
-
+ gpuPushMatrix();
+
/* get the tab width */
ImBuf *first_ibuf = BKE_image_get_first_ibuf(ima);
matrixGlyph(first_ibuf, ' ', &centerx, &centery,
- &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
-
+ &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
+
float advance_tab = advance * 4; /* tab width could also be an option */
-
-
+
+
for (size_t index = 0; index < textlen_st; ) {
unsigned int character;
float uv[4][2];
/* lets calculate offset stuff */
character = BLI_str_utf8_as_unicode_and_size_safe(textstr + index, &index);
-
+
if (character == '\n') {
- glTranslatef(line_start, -line_height, 0.0f);
+ gpuTranslate2f(line_start, -line_height);
line_start = 0.0f;
continue;
}
else if (character == '\t') {
- glTranslatef(advance_tab, 0.0f, 0.0f);
+ gpuTranslate2f(advance_tab, 0.0f);
line_start -= advance_tab; /* so we can go back to the start of the line */
continue;
-
+
}
else if (character > USHRT_MAX) {
/* not much we can do here bmfonts take ushort */
character = '?';
}
-
+
/* space starts at offset 1 */
/* character = character - ' ' + 1; */
matrixGlyph(first_ibuf, character, & centerx, &centery,
- &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
+ &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
uv[0][0] = (uv_quad[0][0] - centerx) * sizex + transx;
uv[0][1] = (uv_quad[0][1] - centery) * sizey + transy;
@@ -184,13 +185,13 @@ void GPU_render_text(
uv[1][1] = (uv_quad[1][1] - centery) * sizey + transy;
uv[2][0] = (uv_quad[2][0] - centerx) * sizex + transx;
uv[2][1] = (uv_quad[2][1] - centery) * sizey + transy;
-
+
glBegin(GL_POLYGON);
if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[0]);
else glTexCoord2fv(uv[0]);
if (col) gpu_mcol(col[0]);
glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
-
+
if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[1]);
else glTexCoord2fv(uv[1]);
if (col) gpu_mcol(col[1]);
@@ -212,28 +213,29 @@ void GPU_render_text(
}
glEnd();
- glTranslatef(advance, 0.0f, 0.0f);
+ gpuTranslate2f(advance, 0.0f);
line_start -= advance; /* so we can go back to the start of the line */
}
- glPopMatrix();
+ gpuPopMatrix();
BKE_image_release_ibuf(ima, first_ibuf, NULL);
}
}
/* Checking powers of two for images since OpenGL ES requires it */
-
+#ifdef WITH_DDS
static bool is_power_of_2_resolution(int w, int h)
{
return is_power_of_2_i(w) && is_power_of_2_i(h);
}
+#endif
static bool is_over_resolution_limit(GLenum textarget, int w, int h)
{
int size = (textarget == GL_TEXTURE_2D) ?
GPU_max_texture_size() : GPU_max_cube_map_size();
int reslimit = (U.glreslimit != 0) ?
- min_ii(U.glreslimit, size) : size;
+ min_ii(U.glreslimit, size) : size;
return (w > reslimit || h > reslimit);
}
@@ -269,8 +271,7 @@ static struct GPUTextureState {
int alphablend;
float anisotropic;
int gpu_mipmap;
- MTexPoly *lasttface;
-} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.0f, 0, NULL};
+} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.0f, 0};
/* Mipmap settings */
@@ -279,36 +280,13 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap)
int old_value = GTS.gpu_mipmap;
/* only actually enable if it's supported */
- GTS.gpu_mipmap = gpu_mipmap && GLEW_EXT_framebuffer_object;
+ GTS.gpu_mipmap = gpu_mipmap;
if (old_value != GTS.gpu_mipmap) {
GPU_free_images();
}
}
-static void gpu_generate_mipmap(GLenum target)
-{
- const bool is_ati = GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY);
- int target_enabled = 0;
-
- /* work around bug in ATI driver, need to have GL_TEXTURE_2D enabled
- * http://www.opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation */
- if (is_ati) {
- target_enabled = glIsEnabled(target);
- if (!target_enabled)
- glEnable(target);
- }
-
- /* TODO: simplify when we transition to GL >= 3 */
- if (GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object)
- glGenerateMipmap(target);
- else if (GLEW_EXT_framebuffer_object)
- glGenerateMipmapEXT(target);
-
- if (is_ati && !target_enabled)
- glDisable(target);
-}
-
void GPU_set_mipmap(bool mipmap)
{
if (GTS.domipmap != mipmap) {
@@ -415,43 +393,16 @@ static unsigned int *gpu_get_image_bindcode(Image *ima, GLenum textarget)
return bind;
}
-void GPU_clear_tpage(bool force)
-{
- if (GTS.lasttface == NULL && !force)
- return;
-
- GTS.lasttface = NULL;
- GTS.curtile = 0;
- GTS.curima = NULL;
- if (GTS.curtilemode != 0) {
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- }
- GTS.curtilemode = 0;
- GTS.curtileXRep = 0;
- GTS.curtileYRep = 0;
- GTS.alphablend = -1;
-
- glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_TEXTURE_GEN_S);
- glDisable(GL_TEXTURE_GEN_T);
- glDisable(GL_ALPHA_TEST);
-}
-
static void gpu_set_alpha_blend(GPUBlendMode alphablend)
{
if (alphablend == GPU_BLEND_SOLID) {
glDisable(GL_BLEND);
- glDisable(GL_ALPHA_TEST);
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else if (alphablend == GPU_BLEND_ADD) {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
- glDisable(GL_ALPHA_TEST);
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
else if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ALPHA_SORT)) {
@@ -460,59 +411,20 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend)
/* for OpenGL render we use the alpha channel, this makes alpha blend correct */
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-
+
/* if U.glalphaclip == 1.0, some cards go bonkers...
* turn off alpha test in this case */
- /* added after 2.45 to clip alpha */
- if (U.glalphaclip == 1.0f) {
- glDisable(GL_ALPHA_TEST);
- }
- else {
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GREATER, U.glalphaclip);
- }
}
else if (alphablend == GPU_BLEND_CLIP) {
glDisable(GL_BLEND);
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GREATER, 0.5f);
}
else if (alphablend == GPU_BLEND_ALPHA_TO_COVERAGE) {
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GREATER, U.glalphaclip);
glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
}
-static void gpu_verify_alpha_blend(int alphablend)
-{
- /* verify alpha blending modes */
- if (GTS.alphablend == alphablend)
- return;
-
- gpu_set_alpha_blend(alphablend);
- GTS.alphablend = alphablend;
-}
-
-static void gpu_verify_reflection(Image *ima)
-{
- if (ima && (ima->flag & IMA_REFLECT)) {
- /* enable reflection mapping */
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
-
- glEnable(GL_TEXTURE_GEN_S);
- glEnable(GL_TEXTURE_GEN_T);
- }
- else {
- /* disable reflection mapping */
- glDisable(GL_TEXTURE_GEN_S);
- glDisable(GL_TEXTURE_GEN_T);
- }
-}
-
typedef struct VerifyThreadData {
ImBuf *ibuf;
float *srgb_frect;
@@ -534,8 +446,6 @@ static void gpu_verify_high_bit_srgb_buffer_slice(float *srgb_frect,
ibuf->x, height,
ibuf->x, ibuf->x);
IMB_buffer_float_unpremultiply(current_srgb_frect, ibuf->x, height);
- /* Clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images. */
- IMB_buffer_float_clamp(current_srgb_frect, ibuf->x, height);
}
static void verify_thread_do(void *data_v,
@@ -604,19 +514,6 @@ int GPU_verify_image(
return (ima != NULL);
}
- /* if tiling mode or repeat changed, change texture matrix to fit */
- if (GTS.tilemode != GTS.curtilemode || GTS.curtileXRep != GTS.tileXRep ||
- GTS.curtileYRep != GTS.tileYRep)
- {
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
-
- if (ima && (ima->tpageflag & IMA_TILES))
- glScalef(ima->xrep, ima->yrep, 1.0f);
-
- glMatrixMode(GL_MODELVIEW);
- }
-
/* check if we have a valid image */
if (ima == NULL || ima->ok == 0)
return 0;
@@ -652,29 +549,29 @@ int GPU_verify_image(
GPU_free_image(ima);
ima->tpageflag &= ~IMA_TPAGE_REFRESH;
}
-
+
if (GTS.tilemode) {
/* tiled mode */
if (ima->repbind == NULL) gpu_make_repbind(ima);
if (GTS.tile >= ima->totbind) GTS.tile = 0;
-
+
/* this happens when you change repeat buttons */
if (ima->repbind && textarget == GL_TEXTURE_2D) bind = &ima->repbind[GTS.tile];
else bind = gpu_get_image_bindcode(ima, textarget);
-
+
if (*bind == 0) {
short texwindx = ibuf->x / ima->xrep;
short texwindy = ibuf->y / ima->yrep;
-
+
if (GTS.tile >= ima->xrep * ima->yrep)
GTS.tile = ima->xrep * ima->yrep - 1;
-
+
short texwinsy = GTS.tile / ima->xrep;
short texwinsx = GTS.tile - texwinsy * ima->xrep;
-
+
texwinsx *= texwindx;
texwinsy *= texwindy;
-
+
tpx = texwindx;
tpy = texwindy;
@@ -748,7 +645,7 @@ int GPU_verify_image(
memcpy(tilerectrow, rectrow, tpx * sizeof(*rectrow));
}
-
+
rect = tilerect;
}
}
@@ -759,13 +656,13 @@ int GPU_verify_image(
else
#endif
GPU_create_gl_tex(bind, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima);
-
+
/* mark as non-color data texture */
if (*bind) {
if (is_data)
- ima->tpageflag |= IMA_GLBIND_IS_DATA;
+ ima->tpageflag |= IMA_GLBIND_IS_DATA;
else
- ima->tpageflag &= ~IMA_GLBIND_IS_DATA;
+ ima->tpageflag &= ~IMA_GLBIND_IS_DATA;
}
/* clean up */
@@ -858,30 +755,6 @@ void GPU_create_gl_tex(
int tpx = rectw;
int tpy = recth;
- /* 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;
- }
- }
-
/* create image */
glGenTextures(1, (GLuint *)bind);
glBindTexture(textarget, *bind);
@@ -900,7 +773,7 @@ void GPU_create_gl_tex(
if (GPU_get_mipmap() && mipmap) {
if (GTS.gpu_mipmap) {
- gpu_generate_mipmap(GL_TEXTURE_2D);
+ glGenerateMipmap(GL_TEXTURE_2D);
}
else {
int i;
@@ -951,7 +824,7 @@ void GPU_create_gl_tex(
if (GPU_get_mipmap() && mipmap) {
if (GTS.gpu_mipmap) {
- gpu_generate_mipmap(GL_TEXTURE_CUBE_MAP);
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
}
else {
if (!ibuf) {
@@ -975,7 +848,7 @@ void GPU_create_gl_tex(
if (mip_cube_map) {
for (int j = 0; j < 6; j++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i,
- informat, mipw, miph, 0, GL_RGBA, type, mip_cube_map[j]);
+ informat, mipw, miph, 0, GL_RGBA, type, mip_cube_map[j]);
}
}
gpu_del_cube_map(mip_cube_map);
@@ -1056,7 +929,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
size = ((width + 3) / 4) * ((height + 3) / 4) * blocksize;
glCompressedTexImage2D(GL_TEXTURE_2D, i, format, width, height,
- 0, size, ibuf->dds_data.data + offset);
+ 0, size, ibuf->dds_data.data + offset);
offset += size;
width >>= 1;
@@ -1091,62 +964,6 @@ void GPU_create_gl_tex_compressed(
}
#endif
}
-static void gpu_verify_repeat(Image *ima)
-{
- /* set either clamp or repeat in X/Y */
- if (ima->tpageflag & IMA_CLAMP_U)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- else
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-
- if (ima->tpageflag & IMA_CLAMP_V)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- else
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-}
-
-int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend)
-{
- /* check if we need to clear the state */
- if (mtexpoly == NULL) {
- GPU_clear_tpage(false);
- return 0;
- }
-
- Image *ima = mtexpoly->tpage;
- GTS.lasttface = mtexpoly;
-
- gpu_verify_alpha_blend(alphablend);
- gpu_verify_reflection(ima);
-
- if (GPU_verify_image(ima, NULL, GL_TEXTURE_2D, mtexpoly->tile, 1, mipmap, false)) {
- GTS.curtile = GTS.tile;
- GTS.curima = GTS.ima;
- GTS.curtilemode = GTS.tilemode;
- GTS.curtileXRep = GTS.tileXRep;
- GTS.curtileYRep = GTS.tileYRep;
-
- glEnable(GL_TEXTURE_2D);
- }
- else {
- glDisable(GL_TEXTURE_2D);
-
- GTS.curtile = 0;
- GTS.curima = NULL;
- GTS.curtilemode = 0;
- GTS.curtileXRep = 0;
- GTS.curtileYRep = 0;
-
- return 0;
- }
-
- gpu_verify_repeat(ima);
-
- /* Did this get lost in the image recode? */
- /* BKE_image_tag_time(ima);*/
-
- return 1;
-}
/* these two functions are called on entering and exiting texture paint mode,
* temporary disabling/enabling mipmapping on all images for quick texture
@@ -1206,9 +1023,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 ((!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))
- {
+ 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);
@@ -1261,7 +1076,7 @@ static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x,
}
if (GPU_get_mipmap()) {
- gpu_generate_mipmap(GL_TEXTURE_2D);
+ glGenerateMipmap(GL_TEXTURE_2D);
}
else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
@@ -1296,7 +1111,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf");
bool is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA) != 0;
IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data);
-
+
if (gpu_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
MEM_freeN(buffer);
BKE_image_release_ibuf(ima, ibuf, NULL);
@@ -1311,7 +1126,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
/* we have already accounted for the case where GTS.gpu_mipmap is false
* so we will be using GPU mipmap generation here */
if (GPU_get_mipmap()) {
- gpu_generate_mipmap(GL_TEXTURE_2D);
+ glGenerateMipmap(GL_TEXTURE_2D);
}
else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
@@ -1337,7 +1152,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
- GL_UNSIGNED_BYTE, ibuf->rect);
+ GL_UNSIGNED_BYTE, ibuf->rect);
glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
@@ -1345,7 +1160,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
/* see comment above as to why we are using gpu mipmap generation here */
if (GPU_get_mipmap()) {
- gpu_generate_mipmap(GL_TEXTURE_2D);
+ glGenerateMipmap(GL_TEXTURE_2D);
}
else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
@@ -1361,9 +1176,9 @@ void GPU_update_images_framechange(void)
if (ima->tpageflag & IMA_TWINANIM) {
if (ima->twend >= ima->xrep * ima->yrep)
ima->twend = ima->xrep * ima->yrep - 1;
-
+
/* check: is bindcode not in the array? free. (to do) */
-
+
ima->lastframe++;
if (ima->lastframe > ima->twend)
ima->lastframe = ima->twsta;
@@ -1386,9 +1201,9 @@ int GPU_update_image_time(Image *ima, double time)
if (ima->tpageflag & IMA_TWINANIM) {
if (ima->twend >= ima->xrep * ima->yrep) ima->twend = ima->xrep * ima->yrep - 1;
-
+
/* check: is the bindcode not in the array? Then free. (still to do) */
-
+
float diff = (float)((float)time - ima->lastupdate);
inc = (int)(diff * (float)ima->animspeed);
@@ -1437,31 +1252,60 @@ 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);
+
+ /* Swizzle the RGBA components to read the Red channel so
+ * that the shader stay the same for colored and non color
+ * density textures. */
+ GPU_texture_bind(sds->tex, 0);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_G, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED);
+ GPU_texture_unbind(sds->tex);
}
- 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);
+
+ /* Swizzle the RGBA components to read the Red channel so
+ * that the shader stay the same for colored and non color
+ * density textures. */
+ GPU_texture_bind(sds->tex, 0);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_G, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED);
+ GPU_texture_unbind(sds->tex);
}
- 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;
@@ -1528,7 +1372,7 @@ void GPU_free_image(Image *ima)
/* free repeated image binding */
if (ima->repbind) {
glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
-
+
MEM_freeN(ima->repbind);
ima->repbind = NULL;
}
@@ -1601,7 +1445,7 @@ typedef struct GPUMaterialFixed {
float spec[3];
int hard;
float alpha;
-} GPUMaterialFixed;
+} GPUMaterialFixed;
static struct GPUMaterialState {
GPUMaterialFixed (*matbuf);
@@ -1619,7 +1463,6 @@ static struct GPUMaterialState {
DupliObject *dob;
Scene *gscene;
int glay;
- bool gscenelock;
float (*gviewmat)[4];
float (*gviewinv)[4];
float (*gviewcamtexcofac);
@@ -1657,12 +1500,12 @@ static void gpu_material_to_fixed(
copy_v3_v3(smat->spec, &bmat->specr);
smat->alpha = 1.0f;
smat->hard = CLAMPIS(bmat->har, 0, 128);
-
+
if (dimdown) {
mul_v3_fl(smat->diff, 0.8f);
mul_v3_fl(smat->spec, 0.5f);
}
-
+
if (gamma) {
linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
linearrgb_to_srgb_v3_v3(smat->spec, smat->spec);
@@ -1673,7 +1516,7 @@ static void gpu_material_to_fixed(
if (bmat->shade_flag & MA_OBCOLOR)
mul_v3_v3(smat->diff, ob->col);
-
+
mul_v3_v3fl(smat->spec, &bmat->specr, bmat->spec);
smat->hard = CLAMPIS(bmat->har, 1, 128);
smat->alpha = 1.0f;
@@ -1710,7 +1553,7 @@ void GPU_end_dupli_object(void)
}
void GPU_begin_object_materials(
- View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob,
+ View3D *v3d, RegionView3D *rv3d, Scene *scene, ViewLayer *view_layer, Object *ob,
bool glsl, bool *do_alpha_after)
{
Material *ma;
@@ -1749,8 +1592,10 @@ void GPU_begin_object_materials(
#ifdef WITH_GAMEENGINE
if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
- ob = BKE_object_lod_matob_get(ob, scene);
+ ob = BKE_object_lod_matob_get(ob, view_layer);
}
+#else
+ UNUSED_VARS(view_layer);
#endif
/* initialize state */
@@ -1775,7 +1620,6 @@ void GPU_begin_object_materials(
GMS.is_opensubdiv = use_opensubdiv;
GMS.totmat = use_matcap ? 1 : ob->totcol + 1; /* materials start from 1, default material is 0 */
GMS.glay = (v3d->localvd) ? v3d->localvd->lay : v3d->lay; /* keep lamps visible in local view */
- GMS.gscenelock = (v3d->scenelock != 0);
GMS.gviewmat = rv3d->viewmat;
GMS.gviewinv = rv3d->viewinv;
GMS.gviewcamtexcofac = rv3d->viewcamtexcofac;
@@ -1789,7 +1633,7 @@ void GPU_begin_object_materials(
GMS.is_alpha_pass = (v3d->transp != false);
if (GMS.use_alpha_pass)
*do_alpha_after = false;
-
+
if (GMS.totmat > FIXEDMAT) {
GMS.matbuf = MEM_callocN(sizeof(GPUMaterialFixed) * GMS.totmat, "GMS.matbuf");
GMS.gmatbuf = MEM_callocN(sizeof(*GMS.gmatbuf) * GMS.totmat, "GMS.matbuf");
@@ -1808,11 +1652,11 @@ void GPU_begin_object_materials(
/* do material 1 too, for displists! */
memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
-
+
GMS.alphablend[0] = GPU_BLEND_SOLID;
}
else {
-
+
/* no materials assigned? */
if (ob->totcol == 0) {
gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes, true);
@@ -1827,7 +1671,7 @@ void GPU_begin_object_materials(
GMS.alphablend[0] = GPU_BLEND_SOLID;
}
-
+
/* setup materials */
for (a = 1; a <= ob->totcol; a++) {
/* find a suitable material */
@@ -1985,13 +1829,13 @@ int GPU_object_material_bind(int nr, void *attribs)
gpu_get_particle_info(&partile_info);
}
- if (GPU_get_material_builtins(gpumat) & GPU_OBJECT_INFO) {
+ if ((GPU_get_material_builtins(gpumat) & GPU_OBJECT_INFO) != 0) {
GPU_get_object_info(object_info, mat);
}
GPU_material_bind(
gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT),
- GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock);
+ GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac);
auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f;
GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info, object_info);
@@ -2062,7 +1906,7 @@ void GPU_set_material_alpha_blend(int alphablend)
{
if (GMS.lastalphablend == alphablend)
return;
-
+
gpu_set_alpha_blend(alphablend);
GMS.lastalphablend = alphablend;
}
@@ -2133,13 +1977,6 @@ void GPU_end_object_materials(void)
GMS.gmatbuf = NULL;
GMS.alphablend = NULL;
GMS.two_sided_lighting = false;
-
- /* resetting the texture matrix after the scaling needed for tiled textures */
- if (GTS.tilemode) {
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- }
}
/* Lights */
@@ -2153,13 +1990,13 @@ int GPU_default_lights(void)
U.light[0].col[0] = 0.8; U.light[0].col[1] = 0.8; U.light[0].col[2] = 0.8;
U.light[0].spec[0] = 0.5; U.light[0].spec[1] = 0.5; U.light[0].spec[2] = 0.5;
U.light[0].spec[3] = 1.0;
-
+
U.light[1].flag = 0;
U.light[1].vec[0] = 0.5; U.light[1].vec[1] = 0.5; U.light[1].vec[2] = 0.1;
U.light[1].col[0] = 0.4; U.light[1].col[1] = 0.4; U.light[1].col[2] = 0.8;
U.light[1].spec[0] = 0.3; U.light[1].spec[1] = 0.3; U.light[1].spec[2] = 0.5;
U.light[1].spec[3] = 1.0;
-
+
U.light[2].flag = 0;
U.light[2].vec[0] = 0.3; U.light[2].vec[1] = -0.3; U.light[2].vec[2] = -0.2;
U.light[2].col[0] = 0.8; U.light[2].col[1] = 0.5; U.light[2].col[2] = 0.4;
@@ -2192,31 +2029,28 @@ int GPU_default_lights(void)
return count;
}
-int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][4], int ortho)
+int GPU_scene_object_lights(ViewLayer *view_layer, float viewmat[4][4], int ortho)
{
/* disable all lights */
for (int count = 0; count < 8; count++)
GPU_basic_shader_light_set(count, NULL);
-
+
/* view direction for specular is not computed correct by default in
* opengl, so we set the settings ourselves */
GPU_basic_shader_light_set_viewer(!ortho);
int count = 0;
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
if (base->object->type != OB_LAMP)
continue;
- if (!(base->lay & lay) || !(base->lay & ob->lay))
- continue;
-
Lamp *la = base->object->data;
-
+
/* setup lamp transform */
- glPushMatrix();
- glLoadMatrixf((float *)viewmat);
-
+ gpuPushMatrix();
+ gpuLoadMatrix(viewmat);
+
/* setup light */
GPULightData light = {0};
@@ -2235,7 +2069,7 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][
light.constant_attenuation = 1.0f;
light.linear_attenuation = la->att1 / la->dist;
light.quadratic_attenuation = la->att2 / (la->dist * la->dist);
-
+
if (la->type == LA_SPOT) {
light.type = GPU_LIGHT_SPOT;
negate_v3_v3(light.direction, base->object->obmat[2]);
@@ -2246,11 +2080,11 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][
else
light.type = GPU_LIGHT_POINT;
}
-
+
GPU_basic_shader_light_set(count, &light);
-
- glPopMatrix();
-
+
+ gpuPopMatrix();
+
count++;
if (count == 8)
break;
@@ -2297,64 +2131,36 @@ static void gpu_multisample(bool enable)
void GPU_state_init(void)
{
- float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
- float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
-
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 35);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
-
GPU_default_lights();
-
+
+ GPU_disable_program_point_size();
+
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+
glDepthFunc(GL_LEQUAL);
- /* scaling matrices */
- glEnable(GL_NORMALIZE);
- glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
- glDisable(GL_FOG);
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_LOGIC_OP);
+ glDisable(GL_COLOR_LOGIC_OP);
glDisable(GL_STENCIL_TEST);
- glDisable(GL_TEXTURE_1D);
- glDisable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- /* default disabled, enable should be local per function */
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
- glPixelTransferi(GL_RED_SCALE, 1);
- glPixelTransferi(GL_RED_BIAS, 0);
- glPixelTransferi(GL_GREEN_SCALE, 1);
- glPixelTransferi(GL_GREEN_BIAS, 0);
- glPixelTransferi(GL_BLUE_SCALE, 1);
- glPixelTransferi(GL_BLUE_BIAS, 0);
- glPixelTransferi(GL_ALPHA_SCALE, 1);
- glPixelTransferi(GL_ALPHA_BIAS, 0);
-
- glPixelTransferi(GL_DEPTH_BIAS, 0);
- glPixelTransferi(GL_DEPTH_SCALE, 1);
- glDepthRange(0.0, 1.0);
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
+ glDepthRange(0.0, 1.0);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
glDisable(GL_CULL_FACE);
gpu_multisample(false);
+}
+
+void GPU_enable_program_point_size(void)
+{
+ glEnable(GL_PROGRAM_POINT_SIZE);
+}
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+void GPU_disable_program_point_size(void)
+{
+ glDisable(GL_PROGRAM_POINT_SIZE);
}
#ifdef WITH_OPENSUBDIV
@@ -2500,10 +2306,10 @@ void GPU_select_to_index_array(unsigned int *col, const unsigned int size)
{
#define INDEX_BUF_ARRAY(INDEX_FROM_BUF_BITS) \
for (i = size; i--; col++) { \
- if ((c = *col)) { \
- *col = INDEX_FROM_BUF_BITS(c); \
- } \
- } ((void)0)
+ if ((c = *col)) { \
+ *col = INDEX_FROM_BUF_BITS(c); \
+ } \
+ } ((void)0)
if (size > 0) {
unsigned int i, c;
@@ -2531,4 +2337,173 @@ void GPU_select_to_index_array(unsigned int *col, const unsigned int size)
#undef INDEX_BUF_ARRAY
}
+#define STATE_STACK_DEPTH 16
+
+typedef struct {
+ eGPUAttribMask mask;
+
+ /* GL_ENABLE_BIT */
+ unsigned int is_blend : 1;
+ unsigned int is_cull_face : 1;
+ unsigned int is_depth_test : 1;
+ unsigned int is_dither : 1;
+ unsigned int is_lighting : 1;
+ unsigned int is_line_smooth : 1;
+ unsigned int is_color_logic_op : 1;
+ unsigned int is_multisample : 1;
+ unsigned int is_polygon_offset_line : 1;
+ unsigned int is_polygon_offset_fill : 1;
+ unsigned int is_polygon_smooth : 1;
+ unsigned int is_sample_alpha_to_coverage : 1;
+ unsigned int is_scissor_test : 1;
+ unsigned int is_stencil_test : 1;
+
+ bool is_clip_plane[6];
+
+ /* GL_DEPTH_BUFFER_BIT */
+ /* unsigned int is_depth_test : 1; */
+ int depth_func;
+ double depth_clear_value;
+ bool depth_write_mask;
+
+ /* GL_SCISSOR_BIT */
+ int scissor_box[4];
+ /* unsigned int is_scissor_test : 1; */
+
+ /* GL_VIEWPORT_BIT */
+ int viewport[4];
+ double near_far[2];
+} GPUAttribValues;
+
+typedef struct {
+ GPUAttribValues attrib_stack[STATE_STACK_DEPTH];
+ unsigned int top;
+} GPUAttribStack;
+
+static GPUAttribStack state = {
+ .top = 0
+};
+
+#define AttribStack state
+#define Gwn_VertAttr state.attrib_stack[state.top]
+
+/**
+ * Replacement for glPush/PopAttributes
+ *
+ * We don't need to cover all the options of legacy OpenGL
+ * but simply the ones used by Blender.
+ */
+void gpuPushAttrib(eGPUAttribMask mask)
+{
+ Gwn_VertAttr.mask = mask;
+
+ if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
+ Gwn_VertAttr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ glGetIntegerv(GL_DEPTH_FUNC, &Gwn_VertAttr.depth_func);
+ glGetDoublev(GL_DEPTH_CLEAR_VALUE, &Gwn_VertAttr.depth_clear_value);
+ glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&Gwn_VertAttr.depth_write_mask);
+ }
+
+ if ((mask & GPU_ENABLE_BIT) != 0) {
+ Gwn_VertAttr.is_blend = glIsEnabled(GL_BLEND);
+
+ for (int i = 0; i < 6; i++) {
+ Gwn_VertAttr.is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i);
+ }
+
+ Gwn_VertAttr.is_cull_face = glIsEnabled(GL_CULL_FACE);
+ Gwn_VertAttr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ Gwn_VertAttr.is_dither = glIsEnabled(GL_DITHER);
+ Gwn_VertAttr.is_line_smooth = glIsEnabled(GL_LINE_SMOOTH);
+ Gwn_VertAttr.is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP);
+ Gwn_VertAttr.is_multisample = glIsEnabled(GL_MULTISAMPLE);
+ Gwn_VertAttr.is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE);
+ Gwn_VertAttr.is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL);
+ Gwn_VertAttr.is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH);
+ Gwn_VertAttr.is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
+ Gwn_VertAttr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ Gwn_VertAttr.is_stencil_test = glIsEnabled(GL_STENCIL_TEST);
+ }
+
+ if ((mask & GPU_SCISSOR_BIT) != 0) {
+ Gwn_VertAttr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&Gwn_VertAttr.scissor_box);
+ }
+
+ if ((mask & GPU_VIEWPORT_BIT) != 0) {
+ glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Gwn_VertAttr.near_far);
+ glGetIntegerv(GL_VIEWPORT, (GLint *)&Gwn_VertAttr.viewport);
+ }
+
+ if ((mask & GPU_BLEND_BIT) != 0) {
+ Gwn_VertAttr.is_blend = glIsEnabled(GL_BLEND);
+ }
+
+ BLI_assert(AttribStack.top < STATE_STACK_DEPTH);
+ AttribStack.top++;
+}
+
+static void restore_mask(GLenum cap, const bool value)
+{
+ if (value) {
+ glEnable(cap);
+ }
+ else {
+ glDisable(cap);
+ }
+}
+
+void gpuPopAttrib(void)
+{
+ BLI_assert(AttribStack.top > 0);
+ AttribStack.top--;
+
+ GLint mask = Gwn_VertAttr.mask;
+
+ if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
+ restore_mask(GL_DEPTH_TEST, Gwn_VertAttr.is_depth_test);
+ glDepthFunc(Gwn_VertAttr.depth_func);
+ glClearDepth(Gwn_VertAttr.depth_clear_value);
+ glDepthMask(Gwn_VertAttr.depth_write_mask);
+ }
+
+ if ((mask & GPU_ENABLE_BIT) != 0) {
+ restore_mask(GL_BLEND, Gwn_VertAttr.is_blend);
+
+ for (int i = 0; i < 6; i++) {
+ restore_mask(GL_CLIP_PLANE0 + i, Gwn_VertAttr.is_clip_plane[i]);
+ }
+
+ restore_mask(GL_CULL_FACE, Gwn_VertAttr.is_cull_face);
+ restore_mask(GL_DEPTH_TEST, Gwn_VertAttr.is_depth_test);
+ restore_mask(GL_DITHER, Gwn_VertAttr.is_dither);
+ restore_mask(GL_LINE_SMOOTH, Gwn_VertAttr.is_line_smooth);
+ restore_mask(GL_COLOR_LOGIC_OP, Gwn_VertAttr.is_color_logic_op);
+ restore_mask(GL_MULTISAMPLE, Gwn_VertAttr.is_multisample);
+ restore_mask(GL_POLYGON_OFFSET_LINE, Gwn_VertAttr.is_polygon_offset_line);
+ restore_mask(GL_POLYGON_OFFSET_FILL, Gwn_VertAttr.is_polygon_offset_fill);
+ restore_mask(GL_POLYGON_SMOOTH, Gwn_VertAttr.is_polygon_smooth);
+ restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, Gwn_VertAttr.is_sample_alpha_to_coverage);
+ restore_mask(GL_SCISSOR_TEST, Gwn_VertAttr.is_scissor_test);
+ restore_mask(GL_STENCIL_TEST, Gwn_VertAttr.is_stencil_test);
+ }
+
+ if ((mask & GPU_VIEWPORT_BIT) != 0) {
+ glViewport(Gwn_VertAttr.viewport[0], Gwn_VertAttr.viewport[1], Gwn_VertAttr.viewport[2], Gwn_VertAttr.viewport[3]);
+ glDepthRange(Gwn_VertAttr.near_far[0], Gwn_VertAttr.near_far[1]);
+ }
+
+ if ((mask & GPU_SCISSOR_BIT) != 0) {
+ restore_mask(GL_SCISSOR_TEST, Gwn_VertAttr.is_scissor_test);
+ glScissor(Gwn_VertAttr.scissor_box[0], Gwn_VertAttr.scissor_box[1], Gwn_VertAttr.scissor_box[2], Gwn_VertAttr.scissor_box[3]);
+ }
+
+ if ((mask & GPU_BLEND_BIT) != 0) {
+ restore_mask(GL_BLEND, Gwn_VertAttr.is_blend);
+ }
+}
+
+#undef Gwn_VertAttr
+#undef AttribStack
+
/** \} */
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index e0ce87d0e68..57df877bf18 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -56,14 +56,11 @@
/* Extensions support */
/* -- extension: version of GL that absorbs it
+ * EXT_gpu_shader4: 3.0
* ARB_framebuffer object: 3.0
- * EXT_framebuffer_object: 3.0
- * EXT_framebuffer_blit: 3.0
- * EXT_framebuffer_multisample: 3.0
* EXT_framebuffer_multisample_blit_scaled: ???
* ARB_draw_instanced: 3.1
* ARB_texture_multisample: 3.2
- * EXT_geometry_shader4: 3.2
* ARB_texture_query_lod: 4.0
*/
@@ -71,7 +68,8 @@ static struct GPUGlobal {
GLint maxtexsize;
GLint maxcubemapsize;
GLint maxtextures;
- bool extdisabled;
+ GLint maxubosize;
+ GLint maxubobinds;
int colordepth;
int samples_color_texture_max;
GPUDeviceType device;
@@ -93,11 +91,6 @@ bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
/* GPU Extensions */
-void GPU_extensions_disable(void)
-{
- GG.extdisabled = true;
-}
-
int GPU_max_texture_size(void)
{
return GG.maxtexsize;
@@ -123,6 +116,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);
@@ -130,8 +133,11 @@ void GPU_get_dfdy_factors(float fac[2])
void gpu_extensions_init(void)
{
- /* BLI_assert(GLEW_VERSION_2_1); */
- /* ^-- maybe a bit extreme? */
+ /* during 2.8 development each platform has its own OpenGL minimum requirements
+ * final 2.8 release will be unified on OpenGL 3.3 core profile, no required extensions
+ * see developer.blender.org/T49012 for details
+ */
+ BLI_assert(GLEW_VERSION_3_3);
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
@@ -143,11 +149,22 @@ 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);
+
+#ifndef NDEBUG
+ GLint ret;
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &ret);
+ /* We expect FRONT_LEFT to be the default buffer. */
+ BLI_assert(ret == GL_FRAMEBUFFER_DEFAULT);
+#endif
+
GLint r, g, b;
- glGetIntegerv(GL_RED_BITS, &r);
- glGetIntegerv(GL_GREEN_BITS, &g);
- glGetIntegerv(GL_BLUE_BITS, &b);
- GG.colordepth = r + g + b; /* assumes same depth for RGB */
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &r);
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, &g);
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, &b);
+ GG.colordepth = r + g + b; /* Assumes same depth for RGB. */
if (GLEW_VERSION_3_2 || GLEW_ARB_texture_multisample) {
glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max);
@@ -161,6 +178,14 @@ void gpu_extensions_init(void)
GG.device = GPU_DEVICE_ATI;
GG.driver = GPU_DRIVER_OFFICIAL;
}
+ /* XXX : TODO : Remove this once this sampling mipmap problem is gone.
+ * https://github.com/dfelinto/opengl-sandbox/blob/downsample/README.md */
+ else if (strstr(renderer, "AMD VEGA") &&
+ strstr(vendor, "X.Org"))
+ {
+ GG.device = GPU_DEVICE_AMD_VEGA;
+ GG.driver = GPU_DRIVER_OPENSOURCE;
+ }
else if (strstr(vendor, "NVIDIA")) {
GG.device = GPU_DEVICE_NVIDIA;
GG.driver = GPU_DRIVER_OFFICIAL;
@@ -201,10 +226,6 @@ void gpu_extensions_init(void)
GG.driver = GPU_DRIVER_ANY;
}
- /* make sure double side isn't used by default and only getting enabled in places where it's
- * really needed to prevent different unexpected behaviors like with intel gme965 card (sergey) */
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
-
#ifdef _WIN32
GG.os = GPU_OS_WIN;
#elif defined(__APPLE__)
@@ -246,43 +267,6 @@ void gpu_extensions_exit(void)
GPU_invalid_tex_free();
}
-bool GPU_legacy_support(void)
-{
- /* return whether or not current GL context is compatible with legacy OpenGL */
- static bool checked = false;
- static bool support = true;
-
- if (!checked) {
- if (GLEW_VERSION_3_2) {
- GLint profile;
- glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
-
- if (G.debug & G_DEBUG_GPU) {
- printf("GL_CONTEXT_PROFILE_MASK = %#x (%s profile)\n", (unsigned int)profile,
- (profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) ? "compatibility" :
- (profile & GL_CONTEXT_CORE_PROFILE_BIT) ? "core" : "unknown");
- }
-
- if (profile == 0) {
- /* workaround for nVidia's Linux driver */
- support = GLEW_ARB_compatibility;
- }
- else {
- support = profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
- }
- }
- else if (GLEW_VERSION_3_1) {
- support = GLEW_ARB_compatibility;
- }
-
- /* any OpenGL version <= 3.0 is legacy, so support remains true */
-
- checked = true;
- }
-
- return support;
-}
-
bool GPU_full_non_power_of_two_support(void)
{
/* always supported on full GL but still relevant for OpenGL ES 2.0 where
@@ -290,39 +274,11 @@ bool GPU_full_non_power_of_two_support(void)
return true;
}
-bool GPU_display_list_support(void)
-{
- /* deprecated in GL 3
- * supported on older GL and compatibility profile
- * still queried by game engine
- */
- return true;
-}
-
bool GPU_bicubic_bump_support(void)
{
return GLEW_VERSION_4_0 || (GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0);
}
-bool GPU_geometry_shader_support(void)
-{
- /* in GL 3.2 geometry shaders are fully supported
- * core profile clashes with our other shaders so accept compatibility only
- * other GL versions can use EXT_geometry_shader4 if available
- */
- return (GLEW_VERSION_3_2 && GPU_legacy_support()) || GLEW_EXT_geometry_shader4;
-}
-
-bool GPU_geometry_shader_support_via_extension(void)
-{
- return GLEW_EXT_geometry_shader4 && !(GLEW_VERSION_3_2 && GPU_legacy_support());
-}
-
-bool GPU_instanced_drawing_support(void)
-{
- return GLEW_VERSION_3_1 || GLEW_ARB_draw_instanced;
-}
-
int GPU_color_depth(void)
{
return GG.colordepth;
@@ -330,12 +286,14 @@ int GPU_color_depth(void)
bool GPU_mem_stats_supported(void)
{
- return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM);
+ return (GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo) && (G.debug & G_DEBUG_GPU_MEM);
}
void GPU_mem_stats_get(int *totalmem, int *freemem)
{
+ /* TODO(merwin): use Apple's platform API to get this info */
+
if (GLEW_NVX_gpu_memory_info) {
/* returned value in Kb */
glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index e7a8beae5cc..6830e73cb03 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -32,9 +32,11 @@
#include "BKE_global.h"
-#include "GPU_debug.h"
-#include "GPU_glew.h"
+#include "GPU_batch.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
+#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -43,8 +45,8 @@ static struct GPUFrameBufferGlobal {
} GG = {0};
/* Number of maximum output slots.
- * We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
-#define GPU_FB_MAX_SLOTS 4
+ * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate) */
+#define GPU_FB_MAX_SLOTS 5
struct GPUFrameBuffer {
GLuint object;
@@ -54,44 +56,37 @@ struct GPUFrameBuffer {
static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
{
+ const char *format = "GPUFrameBuffer: framebuffer status %s\n";
const char *err = "unknown";
+#define format_status(X) \
+ case GL_FRAMEBUFFER_##X: err = "GL_FRAMEBUFFER_"#X; \
+ break;
+
switch (status) {
- case GL_FRAMEBUFFER_COMPLETE_EXT:
- break;
- case GL_INVALID_OPERATION:
- err = "Invalid operation";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- err = "Incomplete attachment";
- break;
- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- err = "Unsupported framebuffer format";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- err = "Missing attachment";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- err = "Attached images must have same dimensions";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- err = "Attached images must have same format";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- err = "Missing draw buffer";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- err = "Missing read buffer";
- break;
+ /* success */
+ format_status(COMPLETE)
+ /* errors shared by OpenGL desktop & ES */
+ format_status(INCOMPLETE_ATTACHMENT)
+ format_status(INCOMPLETE_MISSING_ATTACHMENT)
+ format_status(UNSUPPORTED)
+#if 0 /* for OpenGL ES only */
+ format_status(INCOMPLETE_DIMENSIONS)
+#else /* for desktop GL only */
+ format_status(INCOMPLETE_DRAW_BUFFER)
+ format_status(INCOMPLETE_READ_BUFFER)
+ format_status(INCOMPLETE_MULTISAMPLE)
+ format_status(UNDEFINED)
+#endif
}
+#undef format_status
+
if (err_out) {
- BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
- (int)status, err);
+ BLI_snprintf(err_out, 256, format, err);
}
else {
- fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
- (int)status, err);
+ fprintf(stderr, format, err);
}
}
@@ -101,41 +96,33 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
{
GPUFrameBuffer *fb;
- if (!(GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object ||
- (GLEW_EXT_framebuffer_object && GLEW_EXT_framebuffer_blit)))
- {
- return NULL;
- }
-
fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
- glGenFramebuffersEXT(1, &fb->object);
+ glGenFramebuffers(1, &fb->object);
if (!fb->object) {
- fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
- (int)glGetError());
+ fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed.\n");
GPU_framebuffer_free(fb);
return NULL;
}
/* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
glReadBuffer(GL_NONE);
glDrawBuffer(GL_NONE);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
return fb;
}
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
+bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
{
GLenum attachment;
- GLenum error;
if (slot >= GPU_FB_MAX_SLOTS) {
fprintf(stderr,
"Attaching to index %d framebuffer slot unsupported. "
"Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
- return 0;
+ return false;
}
if ((G.debug & G_DEBUG)) {
@@ -146,26 +133,64 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot
}
}
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ GG.currentfb = fb->object;
+
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ else if (GPU_texture_depth(tex))
+ attachment = GL_DEPTH_ATTACHMENT;
+ else
+ attachment = GL_COLOR_ATTACHMENT0 + slot;
+
+ glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip);
+
if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT_EXT;
+ fb->depthtex = tex;
else
- attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
+ fb->colortex[slot] = tex;
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- GG.currentfb = fb->object;
+ GPU_texture_framebuffer_set(tex, fb, slot);
- /* Clean glError buffer. */
- while (glGetError() != GL_NO_ERROR) {}
+ return true;
+}
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
- GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), 0);
+static bool gpu_framebuffer_texture_layer_attach_ex(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip, bool cubemap)
+{
+ GLenum attachment;
+ GLenum facetarget;
- error = glGetError();
+ if (slot >= GPU_FB_MAX_SLOTS) {
+ fprintf(stderr,
+ "Attaching to index %d framebuffer slot unsupported. "
+ "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
+ return false;
+ }
- if (error == GL_INVALID_OPERATION) {
- GPU_framebuffer_restore();
- gpu_print_framebuffer_error(error, err_out);
- return 0;
+ if ((G.debug & G_DEBUG)) {
+ if (GPU_texture_bound_number(tex) != -1) {
+ fprintf(stderr,
+ "Feedback loop warning!: "
+ "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
+ }
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ GG.currentfb = fb->object;
+
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ else if (GPU_texture_depth(tex))
+ attachment = GL_DEPTH_ATTACHMENT;
+ else
+ attachment = GL_COLOR_ATTACHMENT0 + slot;
+
+ if (cubemap) {
+ facetarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
+ glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, facetarget, GPU_texture_opengl_bindcode(tex), mip);
+ }
+ else {
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), mip, layer);
}
if (GPU_texture_depth(tex))
@@ -175,7 +200,18 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot
GPU_texture_framebuffer_set(tex, fb, slot);
- return 1;
+ return true;
+}
+
+bool GPU_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
+{
+ return gpu_framebuffer_texture_layer_attach_ex(fb, tex, slot, layer, mip, false);
+}
+
+bool GPU_framebuffer_texture_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
+{
+ BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_CUBE_MAP);
+ return gpu_framebuffer_texture_layer_attach_ex(fb, tex, slot, face, mip, true);
}
void GPU_framebuffer_texture_detach(GPUTexture *tex)
@@ -188,21 +224,25 @@ void GPU_framebuffer_texture_detach(GPUTexture *tex)
return;
if (GG.currentfb != fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
GG.currentfb = fb->object;
}
- if (GPU_texture_depth(tex)) {
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) {
fb->depthtex = NULL;
- attachment = GL_DEPTH_ATTACHMENT_EXT;
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ }
+ else if (GPU_texture_depth(tex)) {
+ fb->depthtex = NULL;
+ attachment = GL_DEPTH_ATTACHMENT;
}
else {
BLI_assert(fb->colortex[fb_attachment] == tex);
fb->colortex[fb_attachment] = NULL;
- attachment = GL_COLOR_ATTACHMENT0_EXT + fb_attachment;
+ attachment = GL_COLOR_ATTACHMENT0 + fb_attachment;
}
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, GPU_texture_target(tex), 0, 0);
+ glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
GPU_texture_framebuffer_set(tex, NULL, -1);
}
@@ -218,11 +258,11 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
}
/* push attributes */
- glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
+ gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
glDisable(GL_SCISSOR_TEST);
/* bind framebuffer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
if (GPU_texture_depth(tex)) {
glDrawBuffer(GL_NONE);
@@ -230,86 +270,109 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
}
else {
/* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
}
if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
glEnable(GL_MULTISAMPLE);
}
- /* push matrices and set default viewport and matrix */
+ /* set default viewport */
glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
GG.currentfb = fb->object;
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
}
void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
{
int numslots = 0, i;
- GLenum attachments[4];
+ GLenum attachments[GPU_FB_MAX_SLOTS];
if (!fb->colortex[slot]) {
fprintf(stderr, "Error, framebuffer slot empty!\n");
return;
}
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
if (fb->colortex[i]) {
- attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
+ attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
numslots++;
}
}
/* push attributes */
- glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
+ gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
glDisable(GL_SCISSOR_TEST);
/* bind framebuffer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
/* last bound prevails here, better allow explicit control here too */
glDrawBuffers(numslots, attachments);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
- /* push matrices and set default viewport and matrix */
+ /* set default viewport */
glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
GG.currentfb = fb->object;
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
}
+void GPU_framebuffer_bind(GPUFrameBuffer *fb)
+{
+ int numslots = 0, i;
+ GLenum attachments[GPU_FB_MAX_SLOTS];
+ GLenum readattachement = 0;
+ GPUTexture *tex;
+
+ for (i = 0; i < GPU_FB_MAX_SLOTS; 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);
+ }
+
+ if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
+ glEnable(GL_MULTISAMPLE);
+ }
+
+ 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))
{
- /* restore matrix */
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- /* restore attributes */
- glPopAttrib();
+ /* Restore attributes. */
+ gpuPopAttrib();
}
void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
/* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
/* push matrices and set default viewport and matrix */
glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
GG.currentfb = fb->object;
- GG.currentfb = fb->object;
}
bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
@@ -319,22 +382,17 @@ bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
{
- GLenum status;
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
GG.currentfb = fb->object;
-
- /* Clean glError buffer. */
- while (glGetError() != GL_NO_ERROR) {}
-
- status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
GPU_framebuffer_restore();
gpu_print_framebuffer_error(status, err_out);
return false;
}
-
+
return true;
}
@@ -351,10 +409,10 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb)
}
if (fb->object) {
- glDeleteFramebuffersEXT(1, &fb->object);
+ glDeleteFramebuffers(1, &fb->object);
if (GG.currentfb == fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
GG.currentfb = 0;
}
}
@@ -365,7 +423,7 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb)
void GPU_framebuffer_restore(void)
{
if (GG.currentfb != 0) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
GG.currentfb = 0;
}
}
@@ -374,73 +432,214 @@ void GPU_framebuffer_blur(
GPUFrameBuffer *fb, GPUTexture *tex,
GPUFrameBuffer *blurfb, GPUTexture *blurtex)
{
+ const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
+ const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
+
+ static Gwn_VertFormat format = {0};
+ static Gwn_VertBuf vbo = {{0}};
+ static Gwn_Batch batch = {{0}};
+
const float scaleh[2] = {1.0f / GPU_texture_width(blurtex), 0.0f};
const float scalev[2] = {0.0f, 1.0f / GPU_texture_height(tex)};
GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
- int scale_uniform, texture_source_uniform;
if (!blur_shader)
return;
- scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU");
- texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource");
+ /* Preparing to draw quad */
+ if (format.attrib_ct == 0) {
+ unsigned int i = 0;
+ /* Vertex format */
+ unsigned int pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ /* Vertices */
+ GWN_vertbuf_init_with_format(&vbo, &format);
+ GWN_vertbuf_data_alloc(&vbo, 36);
+
+ for (int j = 0; j < 3; ++j) {
+ GWN_vertbuf_attr_set(&vbo, uvs, i, fullscreenuvs[j]);
+ GWN_vertbuf_attr_set(&vbo, pos, i++, fullscreencos[j]);
+ }
+ for (int j = 1; j < 4; ++j) {
+ GWN_vertbuf_attr_set(&vbo, uvs, i, fullscreenuvs[j]);
+ GWN_vertbuf_attr_set(&vbo, pos, i++, fullscreencos[j]);
+ }
+
+ GWN_batch_init(&batch, GL_TRIANGLES, &vbo, NULL);
+ }
+ glDisable(GL_DEPTH_TEST);
+
/* Blurring horizontally */
-
/* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
* pushing unnecessary matrices onto the OpenGL stack. */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glBindFramebuffer(GL_FRAMEBUFFER, blurfb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
/* avoid warnings from texture binding */
GG.currentfb = blurfb->object;
- GPU_shader_bind(blur_shader);
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
- GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
glViewport(0, 0, GPU_texture_width(blurtex), GPU_texture_height(blurtex));
- /* Preparing to draw quad */
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glDisable(GL_DEPTH_TEST);
-
GPU_texture_bind(tex, 0);
- /* Drawing quad */
- glBegin(GL_QUADS);
- glTexCoord2d(0, 0); glVertex2f(1, 1);
- glTexCoord2d(1, 0); glVertex2f(-1, 1);
- glTexCoord2d(1, 1); glVertex2f(-1, -1);
- glTexCoord2d(0, 1); glVertex2f(1, -1);
- glEnd();
+ GWN_batch_program_set_builtin(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR);
+ GWN_batch_uniform_2f(&batch, "ScaleU", scaleh[0], scaleh[1]);
+ GWN_batch_uniform_1i(&batch, "textureSource", GL_TEXTURE0);
+ GWN_batch_draw(&batch);
/* Blurring vertically */
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
GG.currentfb = fb->object;
glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
- GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
+
GPU_texture_bind(blurtex, 0);
- glBegin(GL_QUADS);
- glTexCoord2d(0, 0); glVertex2f(1, 1);
- glTexCoord2d(1, 0); glVertex2f(-1, 1);
- glTexCoord2d(1, 1); glVertex2f(-1, -1);
- glTexCoord2d(0, 1); glVertex2f(1, -1);
- glEnd();
+ /* Hack to make the following uniform stick */
+ GWN_batch_program_set_builtin(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR);
+ GWN_batch_uniform_2f(&batch, "ScaleU", scalev[0], scalev[1]);
+ GWN_batch_uniform_1i(&batch, "textureSource", GL_TEXTURE0);
+ GWN_batch_draw(&batch);
+}
- GPU_shader_unbind();
+void GPU_framebuffer_blit(
+ GPUFrameBuffer *fb_read, int read_slot, GPUFrameBuffer *fb_write,
+ int write_slot, bool use_depth, bool use_stencil)
+{
+ GPUTexture *read_tex = (use_depth || use_stencil) ? fb_read->depthtex : fb_read->colortex[read_slot];
+ GPUTexture *write_tex = (use_depth || use_stencil) ? fb_write->depthtex : fb_write->colortex[write_slot];
+ int read_attach = (use_depth) ? GL_DEPTH_ATTACHMENT :
+ (use_stencil) ? GL_DEPTH_STENCIL_ATTACHMENT :
+ GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(read_tex);
+ int write_attach = (use_depth) ? GL_DEPTH_ATTACHMENT :
+ (use_stencil) ? GL_DEPTH_STENCIL_ATTACHMENT :
+ GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(write_tex);
+ int read_bind = GPU_texture_opengl_bindcode(read_tex);
+ int write_bind = GPU_texture_opengl_bindcode(write_tex);
+ const int read_w = GPU_texture_width(read_tex);
+ const int read_h = GPU_texture_height(read_tex);
+ const int write_w = GPU_texture_width(write_tex);
+ const int write_h = GPU_texture_height(write_tex);
+
+
+ /* Never both! */
+ BLI_assert(!(use_depth && use_stencil));
+
+ if (use_depth) {
+ BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex));
+ BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
+ }
+ else if (use_stencil) {
+ BLI_assert(GPU_texture_stencil(read_tex) && GPU_texture_stencil(write_tex));
+ BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
+ }
+
+ /* read from multi-sample buffer */
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object);
+ glFramebufferTexture2D(
+ GL_READ_FRAMEBUFFER, read_attach,
+ GPU_texture_target(read_tex), read_bind, 0);
+ BLI_assert(glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+ /* write into new single-sample buffer */
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object);
+ glFramebufferTexture2D(
+ GL_DRAW_FRAMEBUFFER, write_attach,
+ GPU_texture_target(write_tex), write_bind, 0);
+ BLI_assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+ glDrawBuffer((use_depth || use_stencil) ? GL_COLOR_ATTACHMENT0 : read_attach);
+ glBlitFramebuffer(0, 0, read_w, read_h, 0, 0, write_w, write_h,
+ (use_depth) ? GL_DEPTH_BUFFER_BIT :
+ (use_stencil) ? GL_STENCIL_BUFFER_BIT :
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ /* Restore previous framebuffer */
+ glBindFramebuffer(GL_FRAMEBUFFER, GG.currentfb);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+}
+
+/**
+ * Use this if you need to custom downsample your texture and use the previous mip level as input.
+ * This function only takes care of the correct texture handling. It execute the callback for each texture level.
+ **/
+void GPU_framebuffer_recursive_downsample(
+ GPUFrameBuffer *fb, GPUTexture *tex, int num_iter, void (*callback)(void *userData, int level), void *userData)
+{
+ int i;
+ int current_dim[2] = {GPU_texture_width(tex), GPU_texture_height(tex)};
+ GLenum attachment;
+
+ /* Manually setup framebuffer to not use GPU_texture_framebuffer_set() */
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ GG.currentfb = fb->object;
+
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ else if (GPU_texture_depth(tex))
+ attachment = GL_DEPTH_ATTACHMENT;
+ else
+ attachment = GL_COLOR_ATTACHMENT0;
+
+ /* last bound prevails here, better allow explicit control here too */
+ if (GPU_texture_depth(tex)) {
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+ }
+ else {
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ }
+
+ for (i = 1; i < num_iter + 1; i++) {
+
+ /* calculate next viewport size */
+ current_dim[0] /= 2;
+ current_dim[1] /= 2;
+
+ if (GPU_type_matches(GPU_DEVICE_AMD_VEGA, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) {
+ /* NOTE : here 16 is because of a bug on AMD Vega GPU + non-pro drivers, that prevents us
+ * from sampling mipmaps that are smaller or equal to 16px. (9) */
+ if (current_dim[0] <= 16 && current_dim[1] <= 16) {
+ break;
+ }
+ }
+ else {
+ if (current_dim[0] <= 2 && current_dim[1] <= 2) {
+ /* Cannot reduce further. */
+ break;
+ }
+ }
+
+ /* ensure that the viewport size is always at least 1x1 */
+ CLAMP_MIN(current_dim[0], 1);
+ CLAMP_MIN(current_dim[1], 1);
+
+ glViewport(0, 0, current_dim[0], current_dim[1]);
+
+ /* bind next level for rendering but first restrict fetches only to previous level */
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
+ GPU_texture_unbind(tex);
+
+ glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), i);
+
+ callback(userData, i);
+ }
+
+ glFramebufferTexture(GL_FRAMEBUFFER, attachment, 0, 0);
+
+ /* reset mipmap level range for the depth image */
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
+ GPU_texture_unbind(tex);
}
/* GPUOffScreen */
@@ -464,12 +663,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_
}
if (samples) {
- if (!GLEW_EXT_framebuffer_multisample ||
- !GLEW_ARB_texture_multisample ||
- /* Only needed for GPU_offscreen_read_pixels.
- * We could add an arg if we intend to use multi-sample
- * offscreen buffers w/o reading their pixels */
- !GLEW_EXT_framebuffer_blit ||
+ if (!GLEW_ARB_texture_multisample ||
/* This is required when blitting from a multi-sampled buffers,
* even though we're not scaling. */
!GLEW_EXT_framebuffer_multisample_blit_scaled)
@@ -478,24 +672,24 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_
}
}
- ofs->depth = GPU_texture_create_depth_multisample(width, height, samples, err_out);
+ ofs->depth = GPU_texture_create_depth_with_stencil_multisample(width, height, samples, err_out);
if (!ofs->depth) {
GPU_offscreen_free(ofs);
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, 0)) {
GPU_offscreen_free(ofs);
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;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, 0)) {
GPU_offscreen_free(ofs);
return NULL;
}
@@ -569,37 +763,37 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
#ifdef USE_FBO_CTX_SWITCH
/* read from multi-sample buffer */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, ofs->color->fb->object);
- glFramebufferTexture2DEXT(
- GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + ofs->color->fb_attachment,
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->color->fb->object);
+ glFramebufferTexture2D(
+ GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + ofs->color->fb_attachment,
GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
- status = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
goto finally;
}
#endif
/* write into new single-sample buffer */
- glGenFramebuffersEXT(1, &fbo_blit);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo_blit);
- glFramebufferTexture2DEXT(
- GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ glGenFramebuffers(1, &fbo_blit);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
+ glFramebufferTexture2D(
+ GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, tex_blit, 0);
- status = glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
goto finally;
}
/* perform the copy */
- glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
/* read the results */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo_blit);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit);
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
#ifdef USE_FBO_CTX_SWITCH
/* restore the original frame-bufer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ofs->color->fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, ofs->color->fb->object);
#undef USE_FBO_CTX_SWITCH
#endif
@@ -610,10 +804,8 @@ finally:
glDeleteTextures(1, &tex_blit);
}
if (fbo_blit) {
- glDeleteFramebuffersEXT(1, &fbo_blit);
+ glDeleteFramebuffers(1, &fbo_blit);
}
-
- GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels");
}
else {
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
@@ -635,3 +827,12 @@ int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
return GPU_texture_opengl_bindcode(ofs->color);
}
+/* only to be used by viewport code! */
+void GPU_offscreen_viewport_data_get(
+ GPUOffScreen *ofs,
+ GPUFrameBuffer **r_fb, GPUTexture **r_color, GPUTexture **r_depth)
+{
+ *r_fb = ofs->fb;
+ *r_color = ofs->color;
+ *r_depth = ofs->depth;
+}
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
new file mode 100644
index 00000000000..5f22b7f9279
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -0,0 +1,88 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "UI_resources.h"
+#include "BLI_utildefines.h"
+
+#include "gpu_shader_private.h"
+
+void immBindBuiltinProgram(GPUBuiltinShader shader_id)
+{
+ GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
+ immBindProgram(shader->program, shader->interface);
+}
+
+void immUniformThemeColor(int color_id)
+{
+ float color[4];
+ UI_GetThemeColor4fv(color_id, color);
+ immUniformColor4fv(color);
+}
+
+void immUniformThemeColor3(int color_id)
+{
+ float color[3];
+ UI_GetThemeColor3fv(color_id, color);
+ immUniformColor3fv(color);
+}
+
+void immUniformThemeColorShade(int color_id, int offset)
+{
+ float color[4];
+ UI_GetThemeColorShade4fv(color_id, offset, color);
+ immUniformColor4fv(color);
+}
+
+void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset)
+{
+ float color[4];
+ UI_GetThemeColorShadeAlpha4fv(color_id, color_offset, alpha_offset, color);
+ immUniformColor4fv(color);
+}
+
+void immUniformThemeColorBlendShade(int color_id1, int color_id2, float fac, int offset)
+{
+ float color[4];
+ UI_GetThemeColorBlendShade4fv(color_id1, color_id2, fac, offset, color);
+ immUniformColor4fv(color);
+}
+
+void immUniformThemeColorBlend(int color_id1, int color_id2, float fac)
+{
+ uint8_t color[3];
+ UI_GetThemeColorBlend3ubv(color_id1, color_id2, fac, color);
+ immUniformColor3ubv(color);
+}
+
+void immThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
+{
+ unsigned char col[4];
+ UI_GetThemeColorShadeAlpha4ubv(colorid, coloffset, alphaoffset, col);
+ immUniformColor4ub(col[0], col[1], col[2], col[3]);
+}
diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c
new file mode 100644
index 00000000000..bad878ef4bf
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_immediate_util.c
@@ -0,0 +1,424 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/intern/gpu_immediate_util.c
+ * \ingroup gpu
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+
+static const float cube_coords[8][3] = {
+ {-1, -1, -1},
+ {-1, -1, +1},
+ {-1, +1, -1},
+ {-1, +1, +1},
+ {+1, -1, -1},
+ {+1, -1, +1},
+ {+1, +1, -1},
+ {+1, +1, +1},
+};
+static const int cube_quad_index[6][4] = {
+ {0, 1, 3, 2},
+ {0, 2, 6, 4},
+ {0, 4, 5, 1},
+ {1, 5, 7, 3},
+ {2, 3, 7, 6},
+ {4, 6, 7, 5},
+};
+static const int cube_line_index[12][2] = {
+ {0, 1},
+ {0, 2},
+ {0, 4},
+ {1, 3},
+ {1, 5},
+ {2, 3},
+ {2, 6},
+ {3, 7},
+ {4, 5},
+ {4, 6},
+ {5, 7},
+ {6, 7},
+};
+
+/**
+ * Pack color into 3 bytes
+ *
+ * This define converts a numerical value to the equivalent 24-bit
+ * color, while not being endian-sensitive. On little-endians, this
+ * is the same as doing a 'naive' indexing, on big-endian, it is not!
+ *
+ * \note BGR format (i.e. 0xBBGGRR)...
+ *
+ * \param x color.
+ */
+void imm_cpack(unsigned int x)
+{
+ immUniformColor3ub(((x) & 0xFF),
+ (((x) >> 8) & 0xFF),
+ (((x) >> 16) & 0xFF));
+}
+
+static void imm_draw_circle(
+ Gwn_PrimType prim_type, const uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
+{
+ immBegin(prim_type, nsegments);
+ for (int i = 0; i < nsegments; ++i) {
+ const float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments);
+ immVertex2f(shdr_pos, x + (rad_x * cosf(angle)), y + (rad_y * sinf(angle)));
+ }
+ immEnd();
+}
+
+/**
+ * Draw a circle outline with the given \a radius.
+ * The circle is centered at \a x, \a y and drawn in the XY plane.
+ *
+ * \param shdr_pos The vertex attribute number for position.
+ * \param x Horizontal center.
+ * \param y Vertical center.
+ * \param radius The circle's radius.
+ * \param nsegments The number of segments to use in drawing (more = smoother).
+ */
+void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float rad, int nsegments)
+{
+ imm_draw_circle(GWN_PRIM_LINE_LOOP, shdr_pos, x, y, rad, rad, nsegments);
+}
+
+/**
+ * Draw a filled circle with the given \a radius.
+ * The circle is centered at \a x, \a y and drawn in the XY plane.
+ *
+ * \param shdr_pos The vertex attribute number for position.
+ * \param x Horizontal center.
+ * \param y Vertical center.
+ * \param radius The circle's radius.
+ * \param nsegments The number of segments to use in drawing (more = smoother).
+ */
+void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float rad, int nsegments)
+{
+ imm_draw_circle(GWN_PRIM_TRI_FAN, shdr_pos, x, y, rad, rad, nsegments);
+}
+
+void imm_draw_circle_wire_aspect_2d(uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
+{
+ imm_draw_circle(GWN_PRIM_LINE_LOOP, shdr_pos, x, y, rad_x, rad_y, nsegments);
+}
+void imm_draw_circle_fill_aspect_2d(uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
+{
+ imm_draw_circle(GWN_PRIM_TRI_FAN, shdr_pos, x, y, rad_x, rad_y, nsegments);
+}
+
+/**
+ * \note We could have `imm_draw_lined_disk_partial` but currently there is no need.
+ */
+static void imm_draw_disk_partial(
+ Gwn_PrimType prim_type, unsigned pos, float x, float y,
+ float rad_inner, float rad_outer, int nsegments, float start, float sweep)
+{
+ /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */
+ const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2);
+ const float angle_end = -(DEG2RADF(sweep) - angle_start);
+ nsegments += 1;
+ immBegin(prim_type, nsegments * 2);
+ for (int i = 0; i < nsegments; ++i) {
+ const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1)));
+ const float angle_sin = sinf(angle);
+ const float angle_cos = cosf(angle);
+ immVertex2f(pos, x + rad_inner * angle_cos, y + rad_inner * angle_sin);
+ immVertex2f(pos, x + rad_outer * angle_cos, y + rad_outer * angle_sin);
+ }
+ immEnd();
+}
+
+/**
+ * Draw a filled arc with the given inner and outer radius.
+ * The circle is centered at \a x, \a y and drawn in the XY plane.
+ *
+ * \note Arguments are `gluPartialDisk` compatible.
+ *
+ * \param pos: The vertex attribute number for position.
+ * \param x: Horizontal center.
+ * \param y: Vertical center.
+ * \param radius_inner: The inner circle's radius.
+ * \param radius_outer: The outer circle's radius (can be zero).
+ * \param nsegments: The number of segments to use in drawing (more = smoother).
+ * \param start: Specifies the starting angle, in degrees, of the disk portion.
+ * \param sweep: Specifies the sweep angle, in degrees, of the disk portion.
+ */
+void imm_draw_disk_partial_fill_2d(
+ unsigned pos, float x, float y,
+ float rad_inner, float rad_outer, int nsegments, float start, float sweep)
+{
+ imm_draw_disk_partial(GWN_PRIM_TRI_STRIP, pos, x, y, rad_inner, rad_outer, nsegments, start, sweep);
+}
+
+static void imm_draw_circle_3D(
+ Gwn_PrimType prim_type, unsigned pos, float x, float y,
+ float rad, int nsegments)
+{
+ immBegin(prim_type, nsegments);
+ for (int i = 0; i < nsegments; ++i) {
+ float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments);
+ immVertex3f(pos, x + rad * cosf(angle), y + rad * sinf(angle), 0.0f);
+ }
+ immEnd();
+}
+
+void imm_draw_circle_wire_3d(unsigned pos, float x, float y, float rad, int nsegments)
+{
+ imm_draw_circle_3D(GWN_PRIM_LINE_LOOP, pos, x, y, rad, nsegments);
+}
+
+void imm_draw_circle_fill_3d(unsigned pos, float x, float y, float rad, int nsegments)
+{
+ imm_draw_circle_3D(GWN_PRIM_TRI_FAN, pos, x, y, rad, nsegments);
+}
+
+/**
+* Draw a lined box.
+*
+* \param pos The vertex attribute number for position.
+* \param x1 left.
+* \param y1 bottom.
+* \param x2 right.
+* \param y2 top.
+*/
+void imm_draw_box_wire_2d(unsigned pos, float x1, float y1, float x2, float y2)
+{
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2, y1);
+ immEnd();
+}
+
+void imm_draw_box_wire_3d(unsigned pos, float x1, float y1, float x2, float y2)
+{
+ /* use this version when Gwn_VertFormat has a vec3 position */
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex3f(pos, x1, y1, 0.0f);
+ immVertex3f(pos, x1, y2, 0.0f);
+ immVertex3f(pos, x2, y2, 0.0f);
+ immVertex3f(pos, x2, y1, 0.0f);
+ immEnd();
+}
+
+/**
+ * Draw a standard checkerboard to indicate transparent backgrounds.
+ */
+void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2)
+{
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
+
+ immUniform4f("color1", 0.15f, 0.15f, 0.15f, 1.0f);
+ immUniform4f("color2", 0.2f, 0.2f, 0.2f, 1.0f);
+ immUniform1i("size", 8);
+
+ immRectf(pos, x1, y1, x2, y2);
+
+ immUnbindProgram();
+}
+
+void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3])
+{
+ float coords[ARRAY_SIZE(cube_coords)][3];
+
+ for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) {
+ madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect);
+ }
+
+ immBegin(GWN_PRIM_TRIS, ARRAY_SIZE(cube_quad_index) * 3 * 2);
+ for (int i = 0; i < ARRAY_SIZE(cube_quad_index); i++) {
+ immVertex3fv(pos, coords[cube_quad_index[i][0]]);
+ immVertex3fv(pos, coords[cube_quad_index[i][1]]);
+ immVertex3fv(pos, coords[cube_quad_index[i][2]]);
+
+ immVertex3fv(pos, coords[cube_quad_index[i][0]]);
+ immVertex3fv(pos, coords[cube_quad_index[i][2]]);
+ immVertex3fv(pos, coords[cube_quad_index[i][3]]);
+ }
+ immEnd();
+}
+
+void imm_draw_cube_wire_3d(uint pos, const float co[3], const float aspect[3])
+{
+ float coords[ARRAY_SIZE(cube_coords)][3];
+
+ for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) {
+ madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect);
+ }
+
+ immBegin(GWN_PRIM_LINES, ARRAY_SIZE(cube_line_index) * 2);
+ for (int i = 0; i < ARRAY_SIZE(cube_line_index); i++) {
+ immVertex3fv(pos, coords[cube_line_index[i][0]]);
+ immVertex3fv(pos, coords[cube_line_index[i][1]]);
+ }
+ immEnd();
+}
+
+/**
+* Draw a cylinder. Replacement for gluCylinder.
+* _warning_ : Slow, better use it only if you no other choices.
+*
+* \param pos The vertex attribute number for position.
+* \param nor The vertex attribute number for normal.
+* \param base Specifies the radius of the cylinder at z = 0.
+* \param top Specifies the radius of the cylinder at z = height.
+* \param height Specifies the height of the cylinder.
+* \param slices Specifies the number of subdivisions around the z axis.
+* \param stacks Specifies the number of subdivisions along the z axis.
+*/
+void imm_draw_cylinder_fill_normal_3d(
+ unsigned int pos, unsigned int nor, float base, float top, float height, int slices, int stacks)
+{
+ immBegin(GWN_PRIM_TRIS, 6 * slices * stacks);
+ for (int i = 0; i < slices; ++i) {
+ const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
+ const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
+ const float cos1 = cosf(angle1);
+ const float sin1 = sinf(angle1);
+ const float cos2 = cosf(angle2);
+ const float sin2 = sinf(angle2);
+
+ for (int j = 0; j < stacks; ++j) {
+ float fac1 = (float)j / (float)stacks;
+ float fac2 = (float)(j + 1) / (float)stacks;
+ float r1 = base * (1.f - fac1) + top * fac1;
+ float r2 = base * (1.f - fac2) + top * fac2;
+ float h1 = height * ((float)j / (float)stacks);
+ float h2 = height * ((float)(j + 1) / (float)stacks);
+
+ float v1[3] = {r1 *cos2, r1 * sin2, h1};
+ float v2[3] = {r2 *cos2, r2 * sin2, h2};
+ float v3[3] = {r2 *cos1, r2 * sin1, h2};
+ float v4[3] = {r1 *cos1, r1 * sin1, h1};
+ float n1[3], n2[3];
+
+ /* calc normals */
+ sub_v3_v3v3(n1, v2, v1);
+ normalize_v3(n1);
+ n1[0] = cos1; n1[1] = sin1; n1[2] = 1 - n1[2];
+
+ sub_v3_v3v3(n2, v3, v4);
+ normalize_v3(n2);
+ n2[0] = cos2; n2[1] = sin2; n2[2] = 1 - n2[2];
+
+ /* first tri */
+ immAttrib3fv(nor, n2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immAttrib3fv(nor, n1);
+ immVertex3fv(pos, v3);
+
+ /* second tri */
+ immVertex3fv(pos, v3);
+ immVertex3fv(pos, v4);
+ immAttrib3fv(nor, n2);
+ immVertex3fv(pos, v1);
+ }
+ }
+ immEnd();
+}
+
+void imm_draw_cylinder_wire_3d(unsigned int pos, float base, float top, float height, int slices, int stacks)
+{
+ immBegin(GWN_PRIM_LINES, 6 * slices * stacks);
+ for (int i = 0; i < slices; ++i) {
+ const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
+ const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
+ const float cos1 = cosf(angle1);
+ const float sin1 = sinf(angle1);
+ const float cos2 = cosf(angle2);
+ const float sin2 = sinf(angle2);
+
+ for (int j = 0; j < stacks; ++j) {
+ float fac1 = (float)j / (float)stacks;
+ float fac2 = (float)(j + 1) / (float)stacks;
+ float r1 = base * (1.f - fac1) + top * fac1;
+ float r2 = base * (1.f - fac2) + top * fac2;
+ float h1 = height * ((float)j / (float)stacks);
+ float h2 = height * ((float)(j + 1) / (float)stacks);
+
+ float v1[3] = {r1 * cos2, r1 * sin2, h1};
+ float v2[3] = {r2 * cos2, r2 * sin2, h2};
+ float v3[3] = {r2 * cos1, r2 * sin1, h2};
+ float v4[3] = {r1 * cos1, r1 * sin1, h1};
+
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+
+ immVertex3fv(pos, v2);
+ immVertex3fv(pos, v3);
+
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v4);
+ }
+ }
+ immEnd();
+}
+
+void imm_draw_cylinder_fill_3d(unsigned int pos, float base, float top, float height, int slices, int stacks)
+{
+ immBegin(GWN_PRIM_TRIS, 6 * slices * stacks);
+ for (int i = 0; i < slices; ++i) {
+ const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
+ const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
+ const float cos1 = cosf(angle1);
+ const float sin1 = sinf(angle1);
+ const float cos2 = cosf(angle2);
+ const float sin2 = sinf(angle2);
+
+ for (int j = 0; j < stacks; ++j) {
+ float fac1 = (float)j / (float)stacks;
+ float fac2 = (float)(j + 1) / (float)stacks;
+ float r1 = base * (1.f - fac1) + top * fac1;
+ float r2 = base * (1.f - fac2) + top * fac2;
+ float h1 = height * ((float)j / (float)stacks);
+ float h2 = height * ((float)(j + 1) / (float)stacks);
+
+ float v1[3] = {r1 * cos2, r1 * sin2, h1};
+ float v2[3] = {r2 * cos2, r2 * sin2, h2};
+ float v3[3] = {r2 * cos1, r2 * sin1, h2};
+ float v4[3] = {r1 * cos1, r1 * sin1, h1};
+
+ /* first tri */
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immVertex3fv(pos, v3);
+
+ /* second tri */
+ immVertex3fv(pos, v3);
+ immVertex3fv(pos, v4);
+ immVertex3fv(pos, v1);
+ }
+ }
+ immEnd();
+}
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index c72c83b6b07..7a6b1ff6c70 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -31,7 +31,8 @@
#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,14 +60,22 @@ void GPU_init(void)
if (G.debug & G_DEBUG_GPU)
gpu_debug_init();
+ gpu_batch_init();
+
+ immInit();
}
void GPU_exit(void)
{
+ immDestroy();
+
+ gpu_batch_exit();
+
if (G.debug & G_DEBUG_GPU)
gpu_debug_exit();
+
gpu_codegen_exit();
gpu_extensions_exit(); /* must come last */
diff --git a/source/blender/gpu/intern/gpu_lamp.c b/source/blender/gpu/intern/gpu_lamp.c
new file mode 100644
index 00000000000..3c49c057b49
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_lamp.c
@@ -0,0 +1,483 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel, Clément Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_lamp.c
+ * \ingroup gpu
+ *
+ * Manages Opengl lights.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_lamp_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_group.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_glew.h"
+#include "GPU_lamp.h"
+#include "GPU_material.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+#include "gpu_lamp_private.h"
+
+bool GPU_lamp_visible(GPULamp *lamp, Material *ma)
+{
+ if (lamp->hide)
+ return false;
+ else if (ma && ma->group)
+ return BKE_group_object_exists(ma->group, lamp->ob);
+ else
+ return true;
+}
+
+static void gpu_lamp_calc_winmat(GPULamp *lamp)
+{
+ float temp, angle, pixsize, wsize;
+
+ if (lamp->type == LA_SUN) {
+ wsize = lamp->la->shadow_frustum_size;
+ orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
+ }
+ else if (lamp->type == LA_SPOT) {
+ angle = saacos(lamp->spotsi);
+ temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
+ pixsize = lamp->d / temp;
+ wsize = pixsize * 0.5f * lamp->size;
+ /* compute shadows according to X and Y scaling factors */
+ perspective_m4(
+ lamp->winmat,
+ -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0],
+ -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1],
+ lamp->d, lamp->clipend);
+ }
+}
+
+void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
+{
+ float mat[4][4];
+ float obmat_scale[3];
+
+ lamp->lay = lay;
+ lamp->hide = hide;
+
+ normalize_m4_m4_ex(mat, obmat, obmat_scale);
+
+ copy_v3_v3(lamp->vec, mat[2]);
+ copy_v3_v3(lamp->co, mat[3]);
+ copy_m4_m4(lamp->obmat, mat);
+ invert_m4_m4(lamp->imat, mat);
+
+ if (lamp->type == LA_SPOT) {
+ /* update spotlamp scale on X and Y axis */
+ lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2];
+ lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2];
+ }
+
+ if (GPU_lamp_has_shadow_buffer(lamp)) {
+ /* makeshadowbuf */
+ gpu_lamp_calc_winmat(lamp);
+ }
+}
+
+void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
+{
+ lamp->energy = energy;
+ if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
+
+ lamp->col[0] = r;
+ lamp->col[1] = g;
+ lamp->col[2] = b;
+}
+
+void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
+ float coeff_const, float coeff_lin, float coeff_quad)
+{
+ lamp->dist = distance;
+ lamp->att1 = att1;
+ lamp->att2 = att2;
+ lamp->coeff_const = coeff_const;
+ lamp->coeff_lin = coeff_lin;
+ lamp->coeff_quad = coeff_quad;
+}
+
+void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
+{
+ lamp->spotsi = cosf(spotsize * 0.5f);
+ lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
+}
+
+static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
+{
+ lamp->scene = scene;
+ lamp->ob = ob;
+ lamp->par = par;
+ lamp->la = la;
+
+ /* add_render_lamp */
+ lamp->mode = la->mode;
+ lamp->type = la->type;
+
+ lamp->energy = la->energy;
+ if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
+
+ lamp->col[0] = la->r;
+ lamp->col[1] = la->g;
+ lamp->col[2] = la->b;
+
+ GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
+
+ lamp->spotsi = la->spotsize;
+ if (lamp->mode & LA_HALO)
+ if (lamp->spotsi > DEG2RADF(170.0f))
+ lamp->spotsi = DEG2RADF(170.0f);
+ lamp->spotsi = cosf(lamp->spotsi * 0.5f);
+ lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend;
+ lamp->k = la->k;
+
+ lamp->dist = la->dist;
+ lamp->falloff_type = la->falloff_type;
+ lamp->att1 = la->att1;
+ lamp->att2 = la->att2;
+ lamp->coeff_const = la->coeff_const;
+ lamp->coeff_lin = la->coeff_lin;
+ lamp->coeff_quad = la->coeff_quad;
+ lamp->curfalloff = la->curfalloff;
+
+ /* initshadowbuf */
+ lamp->bias = 0.02f * la->bias;
+ lamp->size = la->bufsize;
+ lamp->d = la->clipsta;
+ lamp->clipend = la->clipend;
+
+ /* arbitrary correction for the fact we do no soft transition */
+ lamp->bias *= 0.25f;
+}
+
+static void gpu_lamp_shadow_free(GPULamp *lamp)
+{
+ if (lamp->tex) {
+ GPU_texture_free(lamp->tex);
+ lamp->tex = NULL;
+ }
+ if (lamp->depthtex) {
+ GPU_texture_free(lamp->depthtex);
+ lamp->depthtex = NULL;
+ }
+ if (lamp->fb) {
+ GPU_framebuffer_free(lamp->fb);
+ lamp->fb = NULL;
+ }
+ if (lamp->blurtex) {
+ GPU_texture_free(lamp->blurtex);
+ lamp->blurtex = NULL;
+ }
+ if (lamp->blurfb) {
+ GPU_framebuffer_free(lamp->blurfb);
+ lamp->blurfb = NULL;
+ }
+}
+
+static GPUTexture *gpu_lamp_create_vsm_shadow_map(int size)
+{
+ return GPU_texture_create_2D_custom(size, size, 2, GPU_RG32F, NULL, NULL);
+}
+
+LampEngineData *GPU_lamp_engine_data_get(Scene *scene, Object *ob, Object *par, struct RenderEngineType *re)
+{
+ GPULamp *lamp;
+ LinkData *link;
+
+ for (link = ob->gpulamp.first; link; link = link->next) {
+ lamp = (GPULamp *)link->data;
+
+ if ((lamp->par == par) && (lamp->scene == scene) && (lamp->re == re))
+ return &lamp->data;
+ }
+
+ lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
+
+ link = MEM_callocN(sizeof(LinkData), "GPULampLink");
+ link->data = lamp;
+ BLI_addtail(&ob->gpulamp, link);
+
+ lamp->scene = scene;
+ lamp->ob = ob;
+ lamp->par = par;
+ lamp->la = ob->data;
+ lamp->re = re;
+
+ return &lamp->data;
+}
+
+GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
+{
+ Lamp *la;
+ GPULamp *lamp;
+ LinkData *link;
+
+ for (link = ob->gpulamp.first; link; link = link->next) {
+ lamp = (GPULamp *)link->data;
+
+ if (lamp->par == par && lamp->scene == scene)
+ return link->data;
+ }
+
+ lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
+
+ link = MEM_callocN(sizeof(LinkData), "GPULampLink");
+ link->data = lamp;
+ BLI_addtail(&ob->gpulamp, link);
+
+ la = ob->data;
+ gpu_lamp_from_blender(scene, ob, par, la, lamp);
+
+ if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
+ (la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
+ {
+ /* opengl */
+ lamp->fb = GPU_framebuffer_create();
+ if (!lamp->fb) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
+ /* Shadow depth map */
+ lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
+ if (!lamp->depthtex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ GPU_texture_bind(lamp->depthtex, 0);
+ GPU_texture_compare_mode(lamp->depthtex, true);
+ GPU_texture_unbind(lamp->depthtex);
+
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ /* Shadow color map */
+ lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size);
+ if (!lamp->tex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ /* FBO and texture for blurring */
+ lamp->blurfb = GPU_framebuffer_create();
+ if (!lamp->blurfb) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5);
+ if (!lamp->blurtex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ /* we need to properly bind to test for completeness */
+ GPU_texture_bind_as_framebuffer(lamp->blurtex);
+
+ if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
+ }
+ else {
+ lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
+ if (!lamp->tex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ GPU_texture_bind(lamp->tex, 0);
+ GPU_texture_compare_mode(lamp->tex, true);
+ GPU_texture_unbind(lamp->tex);
+
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+ }
+
+ GPU_framebuffer_restore();
+
+ lamp->shadow_color[0] = la->shdwr;
+ lamp->shadow_color[1] = la->shdwg;
+ lamp->shadow_color[2] = la->shdwb;
+ }
+ else {
+ lamp->shadow_color[0] = 1.0;
+ lamp->shadow_color[1] = 1.0;
+ lamp->shadow_color[2] = 1.0;
+ }
+
+ return lamp;
+}
+
+void GPU_lamp_engine_data_free(LampEngineData *led)
+{
+ for (int i = 0; i < MAX_LAMP_DATA; ++i) {
+ if (led->storage[i]) {
+ MEM_freeN(led->storage[i]);
+ led->storage[i] = NULL;
+ }
+ }
+}
+
+void GPU_lamp_free(Object *ob)
+{
+ GPULamp *lamp;
+ LinkData *link;
+
+ for (link = ob->gpulamp.first; link; link = link->next) {
+ lamp = link->data;
+
+ gpu_lamp_shadow_free(lamp);
+ GPU_lamp_engine_data_free(&lamp->data);
+
+ MEM_freeN(lamp);
+ }
+
+ BLI_freelistN(&ob->gpulamp);
+}
+
+bool GPU_lamp_has_shadow_buffer(GPULamp *lamp)
+{
+ return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) &&
+ !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) &&
+ lamp->tex && lamp->fb);
+}
+
+void GPU_lamp_update_buffer_mats(GPULamp *lamp)
+{
+ float rangemat[4][4], persmat[4][4];
+
+ /* initshadowbuf */
+ invert_m4_m4(lamp->viewmat, lamp->obmat);
+ normalize_v3(lamp->viewmat[0]);
+ normalize_v3(lamp->viewmat[1]);
+ normalize_v3(lamp->viewmat[2]);
+
+ /* makeshadowbuf */
+ mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat);
+
+ /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */
+ unit_m4(rangemat);
+ rangemat[0][0] = 0.5f;
+ rangemat[1][1] = 0.5f;
+ rangemat[2][2] = 0.5f;
+ rangemat[3][0] = 0.5f;
+ rangemat[3][1] = 0.5f;
+ rangemat[3][2] = 0.5f;
+
+ mul_m4_m4m4(lamp->persmat, rangemat, persmat);
+}
+
+void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4])
+{
+ GPU_lamp_update_buffer_mats(lamp);
+
+ /* opengl */
+ glDisable(GL_SCISSOR_TEST);
+ GPU_texture_bind_as_framebuffer(lamp->tex);
+ if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
+ GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
+
+ /* set matrices */
+ copy_m4_m4(viewmat, lamp->viewmat);
+ copy_m4_m4(winmat, lamp->winmat);
+ *winsize = lamp->size;
+}
+
+void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
+{
+ if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
+ GPU_shader_unbind();
+ GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
+ }
+
+ GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
+ GPU_framebuffer_restore();
+ glEnable(GL_SCISSOR_TEST);
+}
+
+int GPU_lamp_shadow_buffer_type(GPULamp *lamp)
+{
+ return lamp->la->shadowmap_type;
+}
+
+int GPU_lamp_shadow_bind_code(GPULamp *lamp)
+{
+ return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1;
+}
+
+float *GPU_lamp_dynpersmat(GPULamp *lamp)
+{
+ return &lamp->dynpersmat[0][0];
+}
+
+int GPU_lamp_shadow_layer(GPULamp *lamp)
+{
+ if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW)))
+ return lamp->lay;
+ else
+ return -1;
+}
diff --git a/source/blender/gpu/intern/gpu_lamp_private.h b/source/blender/gpu/intern/gpu_lamp_private.h
new file mode 100644
index 00000000000..f227ce74e7e
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_lamp_private.h
@@ -0,0 +1,84 @@
+/*
+ * ***** 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): Brecht Van Lommel, Clément Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpu_lamp_private.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_LAMP_PRIVATE_H__
+#define __GPU_LAMP_PRIVATE_H__
+
+#include "BLI_sys_types.h" /* for bool */
+
+struct GPULamp {
+ Scene *scene;
+ Object *ob;
+ Object *par;
+ Lamp *la;
+ struct RenderEngineType *re;
+
+ /* Old Viewport (pre-2.8) */
+ int type, mode, lay, hide;
+
+ float dynenergy, dyncol[3];
+ float energy, col[3];
+
+ float co[3], vec[3];
+ float dynco[3], dynvec[3];
+ float obmat[4][4];
+ float imat[4][4];
+ float dynimat[4][4];
+
+ float spotsi, spotbl, k;
+ float spotvec[2];
+ float dyndist, dynatt1, dynatt2;
+ float dist, att1, att2;
+ float coeff_const, coeff_lin, coeff_quad;
+ float shadow_color[3];
+
+ float bias, d, clipend;
+ int size;
+
+ int falloff_type;
+ struct CurveMapping *curfalloff;
+
+ float winmat[4][4];
+ float viewmat[4][4];
+ float persmat[4][4];
+ float dynpersmat[4][4];
+
+ GPUFrameBuffer *fb;
+ GPUFrameBuffer *blurfb;
+ GPUTexture *tex;
+ GPUTexture *depthtex;
+ GPUTexture *blurtex;
+
+ /* New viewport */
+ struct LampEngineData data;
+};
+
+#endif /* __GPU_LAMP_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 33eac16dadf..2e6c1cbf9df 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -45,12 +45,14 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_rand.h"
#include "BKE_anim.h"
#include "BKE_colorband.h"
#include "BKE_colortools.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_scene.h"
@@ -60,11 +62,14 @@
#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_uniformbuffer.h"
#include "gpu_codegen.h"
+#include "gpu_lamp_private.h"
#ifdef WITH_OPENSUBDIV
# include "BKE_DerivedMesh.h"
@@ -92,12 +97,15 @@ static struct GPUWorld {
} GPUWorld;
struct GPUMaterial {
- Scene *scene;
+ Scene *scene; /* DEPRECATED was only usefull for lamps */
Material *ma;
/* material for mesh surface, worlds or something else.
* some code generation is done differently depending on the use case */
- int type;
+ int type; /* DEPRECATED */
+
+ const void *engine_type; /* attached engine type */
+ int options; /* to identify shader variations (shadow, probe, world background...) */
/* for creating the material */
ListBase nodes;
@@ -128,50 +136,26 @@ struct GPUMaterial {
bool bound;
bool is_opensubdiv;
-};
-
-struct GPULamp {
- Scene *scene;
- Object *ob;
- Object *par;
- Lamp *la;
-
- int type, mode, lay, hide;
-
- float dynenergy, dyncol[3];
- float energy, col[3];
-
- float co[3], vec[3];
- float dynco[3], dynvec[3];
- float obmat[4][4];
- float imat[4][4];
- float dynimat[4][4];
-
- float spotsi, spotbl, k;
- float spotvec[2];
- float dyndist, dynatt1, dynatt2;
- float dist, att1, att2;
- float coeff_const, coeff_lin, coeff_quad;
- float shadow_color[3];
-
- float bias, d, clipend;
- int size;
-
- int falloff_type;
- struct CurveMapping *curfalloff;
- float winmat[4][4];
- float viewmat[4][4];
- float persmat[4][4];
- float dynpersmat[4][4];
-
- GPUFrameBuffer *fb;
- GPUFrameBuffer *blurfb;
- GPUTexture *tex;
- GPUTexture *depthtex;
- GPUTexture *blurtex;
+ /* XXX: Should be in Material. But it depends on the output node
+ * used and since the output selection is difference for GPUMaterial...
+ */
+ int domain;
+
+ GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */
+ GPUUniformBuffer *sss_profile; /* UBO containing SSS profile. */
+ GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */
+ float *sss_radii; /* UBO containing SSS profile. */
+ int sss_samples;
+ short int *sss_falloff;
+ float *sss_sharpness;
+ bool sss_dirty;
+};
- ListBase materials;
+enum {
+ GPU_DOMAIN_SURFACE = (1 << 0),
+ GPU_DOMAIN_VOLUME = (1 << 1),
+ GPU_DOMAIN_SSS = (1 << 2)
};
/* Forward declaration so shade_light_textures() can use this, while still keeping the code somewhat organized */
@@ -289,21 +273,18 @@ void GPU_material_free(ListBase *gpumaterial)
if (material->pass)
GPU_pass_free(material->pass);
- for (LinkData *nlink = material->lamps.first; nlink; nlink = nlink->next) {
- GPULamp *lamp = nlink->data;
+ if (material->ubo != NULL) {
+ GPU_uniformbuffer_free(material->ubo);
+ }
- if (material->ma) {
- Material *ma = material->ma;
-
- LinkData *next = NULL;
- for (LinkData *mlink = lamp->materials.first; mlink; mlink = next) {
- next = mlink->next;
- if (mlink->data == ma)
- BLI_freelinkN(&lamp->materials, mlink);
- }
- }
+ if (material->sss_tex_profile != NULL) {
+ GPU_texture_free(material->sss_tex_profile);
}
-
+
+ if (material->sss_profile != NULL) {
+ GPU_uniformbuffer_free(material->sss_profile);
+ }
+
BLI_freelistN(&material->lamps);
MEM_freeN(material);
@@ -312,28 +293,12 @@ void GPU_material_free(ListBase *gpumaterial)
BLI_freelistN(gpumaterial);
}
-bool GPU_lamp_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
-{
- if (lamp->hide)
- return false;
- else if (srl && srl->light_override)
- return BKE_group_object_exists(srl->light_override, lamp->ob);
- else if (ma && ma->group)
- return BKE_group_object_exists(ma->group, lamp->ob);
- else
- return true;
-}
-
void GPU_material_bind(
GPUMaterial *material, int oblay, int viewlay, double time, int mipmap,
- float viewmat[4][4], float viewinv[4][4], float camerafactors[4], bool scenelock)
+ float viewmat[4][4], float viewinv[4][4], float camerafactors[4])
{
if (material->pass) {
GPUShader *shader = GPU_pass_shader(material->pass);
- SceneRenderLayer *srl = scenelock ? BLI_findlink(&material->scene->r.layers, material->scene->r.actlay) : NULL;
-
- if (srl)
- viewlay &= srl->lay;
/* handle layer lamps */
if (material->type == GPU_MATERIAL_TYPE_MESH) {
@@ -341,7 +306,7 @@ void GPU_material_bind(
GPULamp *lamp = nlink->data;
if ((lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay)) &&
- GPU_lamp_visible(lamp, srl, material->ma))
+ GPU_lamp_visible(lamp, material->ma))
{
lamp->dynenergy = lamp->energy;
copy_v3_v3(lamp->dyncol, lamp->col);
@@ -490,6 +455,346 @@ GPUMatType GPU_Material_get_type(GPUMaterial *material)
return material->type;
}
+GPUPass *GPU_material_get_pass(GPUMaterial *material)
+{
+ return material->pass;
+}
+
+GPUUniformBuffer *GPU_material_get_uniform_buffer(GPUMaterial *material)
+{
+ return material->ubo;
+}
+
+/**
+ * Create dynamic UBO from parameters
+ * \param ListBase of BLI_genericNodeN(GPUInput)
+ */
+void GPU_material_create_uniform_buffer(GPUMaterial *material, ListBase *inputs)
+{
+ material->ubo = GPU_uniformbuffer_dynamic_create(inputs, NULL);
+}
+
+void GPU_material_uniform_buffer_tag_dirty(ListBase *gpumaterials)
+{
+ for (LinkData *link = gpumaterials->first; link; link = link->next) {
+ GPUMaterial *material = link->data;
+ if (material->ubo != NULL) {
+ GPU_uniformbuffer_tag_dirty(material->ubo);
+ }
+ if (material->sss_profile != NULL) {
+ material->sss_dirty = true;
+ }
+ }
+}
+
+/* Eevee Subsurface scattering. */
+/* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */
+
+#define SSS_SAMPLES 65
+#define SSS_EXPONENT 2.0f /* Importance sampling exponent */
+
+typedef struct GPUSssKernelData {
+ float kernel[SSS_SAMPLES][4];
+ float param[3], max_radius;
+ int samples;
+} GPUSssKernelData;
+
+static void sss_calculate_offsets(GPUSssKernelData *kd, int count, float exponent)
+{
+ float step = 2.0f / (float)(count - 1);
+ for (int i = 0; i < count; i++) {
+ float o = ((float)i) * step - 1.0f;
+ float sign = (o < 0.0f) ? -1.0f : 1.0f;
+ float ofs = sign * fabsf(powf(o, exponent));
+ kd->kernel[i][3] = ofs;
+ }
+}
+
+#define GAUSS_TRUNCATE 12.46f
+static float gaussian_profile(float r, float radius)
+{
+ const float v = radius * radius * (0.25f * 0.25f);
+ const float Rm = sqrtf(v * GAUSS_TRUNCATE);
+
+ if (r >= Rm) {
+ return 0.0f;
+ }
+ return expf(-r * r / (2.0f * v)) / (2.0f * M_PI * v);
+}
+
+#define BURLEY_TRUNCATE 16.0f
+#define BURLEY_TRUNCATE_CDF 0.9963790093708328f // cdf(BURLEY_TRUNCATE)
+static float burley_profile(float r, float d)
+{
+ float exp_r_3_d = expf(-r / (3.0f * d));
+ float exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d;
+ return (exp_r_d + exp_r_3_d) / (4.0f * d);
+}
+
+static float cubic_profile(float r, float radius, float sharpness)
+{
+ float Rm = radius * (1.0f + sharpness);
+
+ if (r >= Rm) {
+ return 0.0f;
+ }
+ /* custom variation with extra sharpness, to match the previous code */
+ const float y = 1.0f / (1.0f + sharpness);
+ float Rmy, ry, ryinv;
+
+ Rmy = powf(Rm, y);
+ ry = powf(r, y);
+ ryinv = (r > 0.0f) ? powf(r, y - 1.0f) : 0.0f;
+
+ const float Rmy5 = (Rmy * Rmy) * (Rmy * Rmy) * Rmy;
+ const float f = Rmy - ry;
+ const float num = f * (f * f) * (y * ryinv);
+
+ return (10.0f * num) / (Rmy5 * M_PI);
+}
+
+static float eval_profile(float r, short falloff_type, float sharpness, float param)
+{
+ r = fabsf(r);
+
+ if (falloff_type == SHD_SUBSURFACE_BURLEY) {
+ return burley_profile(r, param) / BURLEY_TRUNCATE_CDF;
+ }
+ else if (falloff_type == SHD_SUBSURFACE_CUBIC) {
+ return cubic_profile(r, param, sharpness);
+ }
+ else {
+ return gaussian_profile(r, param);
+ }
+}
+
+/* Resolution for each sample of the precomputed kernel profile */
+#define INTEGRAL_RESOLUTION 32
+static float eval_integral(float x0, float x1, short falloff_type, float sharpness, float param)
+{
+ const float range = x1 - x0;
+ const float step = range / INTEGRAL_RESOLUTION;
+ float integral = 0.0f;
+
+ for (int i = 0; i < INTEGRAL_RESOLUTION; ++i) {
+ float x = x0 + range * ((float)i + 0.5f) / (float)INTEGRAL_RESOLUTION;
+ float y = eval_profile(x, falloff_type, sharpness, param);
+ integral += y * step;
+ }
+
+ return integral;
+}
+#undef INTEGRAL_RESOLUTION
+
+static void compute_sss_kernel(
+ GPUSssKernelData *kd, float *radii, int sample_ct, int falloff_type, float sharpness)
+{
+ float rad[3];
+ /* Minimum radius */
+ rad[0] = MAX2(radii[0], 1e-15f);
+ rad[1] = MAX2(radii[1], 1e-15f);
+ rad[2] = MAX2(radii[2], 1e-15f);
+
+ /* Christensen-Burley fitting */
+ float l[3], d[3];
+
+ if (falloff_type == SHD_SUBSURFACE_BURLEY) {
+ mul_v3_v3fl(l, rad, 0.25f * M_1_PI);
+ const float A = 1.0f;
+ const float s = 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f);
+ /* XXX 0.6f Out of nowhere to match cycles! Empirical! Can be tweak better. */
+ mul_v3_v3fl(d, l, 0.6f / s);
+ mul_v3_v3fl(rad, d, BURLEY_TRUNCATE);
+ kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
+
+ copy_v3_v3(kd->param, d);
+ }
+ else if (falloff_type == SHD_SUBSURFACE_CUBIC) {
+ copy_v3_v3(kd->param, rad);
+ mul_v3_fl(rad, 1.0f + sharpness);
+ kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
+ }
+ else {
+ kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
+
+ copy_v3_v3(kd->param, rad);
+ }
+
+ /* Compute samples locations on the 1d kernel [-1..1] */
+ sss_calculate_offsets(kd, sample_ct, SSS_EXPONENT);
+
+ /* Weights sum for normalization */
+ float sum[3] = {0.0f, 0.0f, 0.0f};
+
+ /* Compute integral of each sample footprint */
+ for (int i = 0; i < sample_ct; i++) {
+ float x0, x1;
+
+ if (i == 0) {
+ x0 = kd->kernel[0][3] - fabsf(kd->kernel[0][3] - kd->kernel[1][3]) / 2.0f;
+ }
+ else {
+ x0 = (kd->kernel[i - 1][3] + kd->kernel[i][3]) / 2.0f;
+ }
+
+ if (i == sample_ct - 1) {
+ x1 = kd->kernel[sample_ct - 1][3] + fabsf(kd->kernel[sample_ct - 2][3] - kd->kernel[sample_ct - 1][3]) / 2.0f;
+ }
+ else {
+ x1 = (kd->kernel[i][3] + kd->kernel[i + 1][3]) / 2.0f;
+ }
+
+ x0 *= kd->max_radius;
+ x1 *= kd->max_radius;
+
+ kd->kernel[i][0] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[0]);
+ kd->kernel[i][1] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[1]);
+ kd->kernel[i][2] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[2]);
+
+ sum[0] += kd->kernel[i][0];
+ sum[1] += kd->kernel[i][1];
+ sum[2] += kd->kernel[i][2];
+ }
+
+ for (int i = 0; i < 3; ++i) {
+ if (sum[i] > 0.0f) {
+ /* Normalize */
+ for (int j = 0; j < sample_ct; j++) {
+ kd->kernel[j][i] /= sum[i];
+ }
+ }
+ else {
+ /* Avoid 0 kernel sum. */
+ kd->kernel[sample_ct / 2][i] = 1.0f;
+ }
+ }
+
+ /* Put center sample at the start of the array (to sample first) */
+ float tmpv[4];
+ copy_v4_v4(tmpv, kd->kernel[sample_ct / 2]);
+ for (int i = sample_ct / 2; i > 0; i--) {
+ copy_v4_v4(kd->kernel[i], kd->kernel[i - 1]);
+ }
+ copy_v4_v4(kd->kernel[0], tmpv);
+
+ kd->samples = sample_ct;
+}
+
+#define INTEGRAL_RESOLUTION 512
+static void compute_sss_translucence_kernel(
+ const GPUSssKernelData *kd, int resolution, short falloff_type, float sharpness, float **output)
+{
+ float (*texels)[4];
+ texels = MEM_callocN(sizeof(float) * 4 * resolution, "compute_sss_translucence_kernel");
+ *output = (float *)texels;
+
+ /* Last texel should be black, hence the - 1. */
+ for (int i = 0; i < resolution - 1; ++i) {
+ /* Distance from surface. */
+ float d = kd->max_radius * ((float)i + 0.00001f) / ((float)resolution);
+
+ /* For each distance d we compute the radiance incomming from an hypothetic parallel plane. */
+ /* Compute radius of the footprint on the hypothetic plane */
+ float r_fp = sqrtf(kd->max_radius * kd->max_radius - d * d);
+ float r_step = r_fp / INTEGRAL_RESOLUTION;
+ float area_accum = 0.0f;
+ for (float r = 0.0f; r < r_fp; r += r_step) {
+ /* Compute distance to the "shading" point through the medium. */
+ /* r_step * 0.5f to put sample between the area borders */
+ float dist = hypotf(r + r_step * 0.5f, d);
+
+ float profile[3];
+ profile[0] = eval_profile(dist, falloff_type, sharpness, kd->param[0]);
+ profile[1] = eval_profile(dist, falloff_type, sharpness, kd->param[1]);
+ profile[2] = eval_profile(dist, falloff_type, sharpness, kd->param[2]);
+
+ /* Since the profile and configuration are radially symetrical we
+ * can just evaluate it once and weight it accordingly */
+ float r_next = r + r_step;
+ float disk_area = (M_PI * r_next * r_next) - (M_PI * r * r);
+
+ mul_v3_fl(profile, disk_area);
+ add_v3_v3(texels[i], profile);
+ area_accum += disk_area;
+ }
+ /* Normalize over the disk. */
+ mul_v3_fl(texels[i], 1.0f / (area_accum));
+ }
+
+ /* Normalize */
+ for (int j = resolution - 2; j > 0; j--) {
+ texels[j][0] /= (texels[0][0] > 0.0f) ? texels[0][0] : 1.0f;
+ texels[j][1] /= (texels[0][1] > 0.0f) ? texels[0][1] : 1.0f;
+ texels[j][2] /= (texels[0][2] > 0.0f) ? texels[0][2] : 1.0f;
+ }
+
+ /* First texel should be white */
+ texels[0][0] = (texels[0][0] > 0.0f) ? 1.0f : 0.0f;
+ texels[0][1] = (texels[0][1] > 0.0f) ? 1.0f : 0.0f;
+ texels[0][2] = (texels[0][2] > 0.0f) ? 1.0f : 0.0f;
+
+ /* dim the last few texels for smoother transition */
+ mul_v3_fl(texels[resolution - 2], 0.25f);
+ mul_v3_fl(texels[resolution - 3], 0.5f);
+ mul_v3_fl(texels[resolution - 4], 0.75f);
+}
+#undef INTEGRAL_RESOLUTION
+
+void GPU_material_sss_profile_create(GPUMaterial *material, float *radii, short *falloff_type, float *sharpness)
+{
+ material->sss_radii = radii;
+ material->sss_falloff = falloff_type;
+ material->sss_sharpness = sharpness;
+ material->sss_dirty = true;
+
+ /* Update / Create UBO */
+ if (material->sss_profile == NULL) {
+ material->sss_profile = GPU_uniformbuffer_create(sizeof(GPUSssKernelData), NULL, NULL);
+ }
+}
+
+struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material, int sample_ct, GPUTexture **tex_profile)
+{
+ if (material->sss_radii == NULL)
+ return NULL;
+
+ if (material->sss_dirty || (material->sss_samples != sample_ct)) {
+ GPUSssKernelData kd;
+
+ float sharpness = (material->sss_sharpness != NULL) ? *material->sss_sharpness : 0.0f;
+
+ /* XXX Black magic but it seems to fit. Maybe because we integrate -1..1 */
+ sharpness *= 0.5f;
+
+ compute_sss_kernel(&kd, material->sss_radii, sample_ct, *material->sss_falloff, sharpness);
+
+ /* Update / Create UBO */
+ GPU_uniformbuffer_update(material->sss_profile, &kd);
+
+ /* Update / Create Tex */
+ float *translucence_profile;
+ compute_sss_translucence_kernel(&kd, 64, *material->sss_falloff, sharpness, &translucence_profile);
+
+ if (material->sss_tex_profile != NULL) {
+ GPU_texture_free(material->sss_tex_profile);
+ }
+
+ material->sss_tex_profile = GPU_texture_create_1D_custom(64, 4, GPU_RGBA16F, translucence_profile, NULL);
+
+ MEM_freeN(translucence_profile);
+
+ material->sss_samples = sample_ct;
+ material->sss_dirty = false;
+ }
+
+ if (tex_profile != NULL) {
+ *tex_profile = material->sss_tex_profile;
+ }
+ return material->sss_profile;
+}
+
+#undef SSS_EXPONENT
+#undef SSS_SAMPLES
void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
{
@@ -540,6 +845,16 @@ bool GPU_material_use_world_space_shading(GPUMaterial *mat)
return BKE_scene_use_world_space_shading(mat->scene);
}
+bool GPU_material_use_domain_surface(GPUMaterial *mat)
+{
+ return (mat->domain & GPU_DOMAIN_SURFACE);
+}
+
+bool GPU_material_use_domain_volume(GPUMaterial *mat)
+{
+ return (mat->domain & GPU_DOMAIN_VOLUME);
+}
+
static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist)
{
GPUNodeLink *visifac;
@@ -951,14 +1266,12 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
}
add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, shi->gpumat->ma);
return;
}
}
}
else if ((mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS) && (lamp->mode & LA_ONLYSHADOW)) {
add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, shi->gpumat->ma);
return;
}
else
@@ -1025,7 +1338,6 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
}
add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, shi->gpumat->ma);
}
static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
@@ -2150,6 +2462,73 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo)
return mat;
}
+GPUMaterial *GPU_material_from_nodetree_find(
+ ListBase *gpumaterials, const void *engine_type, int options)
+{
+ for (LinkData *link = gpumaterials->first; link; link = link->next) {
+ GPUMaterial *current_material = (GPUMaterial *)link->data;
+ if (current_material->engine_type == engine_type &&
+ current_material->options == options)
+ {
+ return current_material;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * TODO: This is supposed to replace GPU_material_from_blender/_world in the future
+ *
+ * \note Caller must use #GPU_material_from_nodetree_find to re-use existing materials,
+ * This is enforced since constructing other arguments to this function may be expensive
+ * so only do this when they are needed.
+ */
+GPUMaterial *GPU_material_from_nodetree(
+ Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, int options,
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
+{
+ GPUMaterial *mat;
+ GPUNodeLink *outlink;
+ LinkData *link;
+ bool has_volume_output, has_surface_output;
+
+ /* Caller must re-use materials. */
+ BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
+
+ /* allocate material */
+ mat = GPU_material_construct_begin(NULL); /* TODO remove GPU_material_construct_begin */
+ mat->scene = scene;
+ mat->engine_type = engine_type;
+ mat->options = options;
+
+ ntreeGPUMaterialNodes(ntree, mat, NODE_NEW_SHADING | NODE_NEWER_SHADING);
+ ntreeGPUMaterialDomain(ntree, &has_surface_output, &has_volume_output);
+
+ if (has_surface_output) {
+ mat->domain |= GPU_DOMAIN_SURFACE;
+ }
+ if (has_volume_output) {
+ mat->domain |= GPU_DOMAIN_VOLUME;
+ }
+
+ /* Let Draw manager finish the construction. */
+ if (mat->outlink) {
+ outlink = mat->outlink;
+ mat->pass = GPU_generate_pass_new(
+ mat, &mat->nodes, outlink, &mat->attribs, vert_code, geom_code, frag_lib, defines);
+ }
+
+ /* note that even if building the shader fails in some way, we still keep
+ * it to avoid trying to compile again and again, and simple do not use
+ * the actual shader on drawing */
+
+ link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
+ link->data = mat;
+ BLI_addtail(gpumaterials, link);
+
+ return mat;
+}
GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv)
{
@@ -2237,386 +2616,6 @@ void GPU_materials_free(void)
/* Lamps and shadow buffers */
-static void gpu_lamp_calc_winmat(GPULamp *lamp)
-{
- float temp, angle, pixsize, wsize;
-
- if (lamp->type == LA_SUN) {
- wsize = lamp->la->shadow_frustum_size;
- orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
- }
- else if (lamp->type == LA_SPOT) {
- angle = saacos(lamp->spotsi);
- temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
- pixsize = lamp->d / temp;
- wsize = pixsize * 0.5f * lamp->size;
- /* compute shadows according to X and Y scaling factors */
- perspective_m4(
- lamp->winmat,
- -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0],
- -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1],
- lamp->d, lamp->clipend);
- }
-}
-
-void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
-{
- float mat[4][4];
- float obmat_scale[3];
-
- lamp->lay = lay;
- lamp->hide = hide;
-
- normalize_m4_m4_ex(mat, obmat, obmat_scale);
-
- copy_v3_v3(lamp->vec, mat[2]);
- copy_v3_v3(lamp->co, mat[3]);
- copy_m4_m4(lamp->obmat, mat);
- invert_m4_m4(lamp->imat, mat);
-
- if (lamp->type == LA_SPOT) {
- /* update spotlamp scale on X and Y axis */
- lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2];
- lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2];
- }
-
- if (GPU_lamp_has_shadow_buffer(lamp)) {
- /* makeshadowbuf */
- gpu_lamp_calc_winmat(lamp);
- }
-}
-
-void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
-{
- lamp->energy = energy;
- if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
-
- lamp->col[0] = r;
- lamp->col[1] = g;
- lamp->col[2] = b;
-}
-
-void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
- float coeff_const, float coeff_lin, float coeff_quad)
-{
- lamp->dist = distance;
- lamp->att1 = att1;
- lamp->att2 = att2;
- lamp->coeff_const = coeff_const;
- lamp->coeff_lin = coeff_lin;
- lamp->coeff_quad = coeff_quad;
-}
-
-void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
-{
- lamp->spotsi = cosf(spotsize * 0.5f);
- lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
-}
-
-static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
-{
- lamp->scene = scene;
- lamp->ob = ob;
- lamp->par = par;
- lamp->la = la;
-
- /* add_render_lamp */
- lamp->mode = la->mode;
- lamp->type = la->type;
-
- lamp->energy = la->energy;
- if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
-
- lamp->col[0] = la->r;
- lamp->col[1] = la->g;
- lamp->col[2] = la->b;
-
- GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
-
- lamp->spotsi = la->spotsize;
- if (lamp->mode & LA_HALO)
- if (lamp->spotsi > DEG2RADF(170.0f))
- lamp->spotsi = DEG2RADF(170.0f);
- lamp->spotsi = cosf(lamp->spotsi * 0.5f);
- lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend;
- lamp->k = la->k;
-
- lamp->dist = la->dist;
- lamp->falloff_type = la->falloff_type;
- lamp->att1 = la->att1;
- lamp->att2 = la->att2;
- lamp->coeff_const = la->coeff_const;
- lamp->coeff_lin = la->coeff_lin;
- lamp->coeff_quad = la->coeff_quad;
- lamp->curfalloff = la->curfalloff;
-
- /* initshadowbuf */
- lamp->bias = 0.02f * la->bias;
- lamp->size = la->bufsize;
- lamp->d = la->clipsta;
- lamp->clipend = la->clipend;
-
- /* arbitrary correction for the fact we do no soft transition */
- lamp->bias *= 0.25f;
-}
-
-static void gpu_lamp_shadow_free(GPULamp *lamp)
-{
- if (lamp->tex) {
- GPU_texture_free(lamp->tex);
- lamp->tex = NULL;
- }
- if (lamp->depthtex) {
- GPU_texture_free(lamp->depthtex);
- lamp->depthtex = NULL;
- }
- if (lamp->fb) {
- GPU_framebuffer_free(lamp->fb);
- lamp->fb = NULL;
- }
- if (lamp->blurtex) {
- GPU_texture_free(lamp->blurtex);
- lamp->blurtex = NULL;
- }
- if (lamp->blurfb) {
- GPU_framebuffer_free(lamp->blurfb);
- lamp->blurfb = NULL;
- }
-}
-
-GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
-{
- Lamp *la;
- GPULamp *lamp;
- LinkData *link;
-
- for (link = ob->gpulamp.first; link; link = link->next) {
- lamp = (GPULamp *)link->data;
-
- if (lamp->par == par && lamp->scene == scene)
- return link->data;
- }
-
- lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
-
- link = MEM_callocN(sizeof(LinkData), "GPULampLink");
- link->data = lamp;
- BLI_addtail(&ob->gpulamp, link);
-
- la = ob->data;
- gpu_lamp_from_blender(scene, ob, par, la, lamp);
-
- if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
- (la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
- {
- /* opengl */
- lamp->fb = GPU_framebuffer_create();
- if (!lamp->fb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- /* Shadow depth map */
- lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->depthtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* Shadow color map */
- lamp->tex = GPU_texture_create_vsm_shadow_map(lamp->size, NULL);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* FBO and texture for blurring */
- lamp->blurfb = GPU_framebuffer_create();
- if (!lamp->blurfb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size * 0.5, NULL);
- if (!lamp->blurtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* we need to properly bind to test for completeness */
- GPU_texture_bind_as_framebuffer(lamp->blurtex);
-
- if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
- }
- else {
- lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
- }
-
- GPU_framebuffer_restore();
-
- lamp->shadow_color[0] = la->shdwr;
- lamp->shadow_color[1] = la->shdwg;
- lamp->shadow_color[2] = la->shdwb;
- }
- else {
- lamp->shadow_color[0] = 1.0;
- lamp->shadow_color[1] = 1.0;
- lamp->shadow_color[2] = 1.0;
- }
-
- return lamp;
-}
-
-void GPU_lamp_free(Object *ob)
-{
- GPULamp *lamp;
- LinkData *link;
- LinkData *nlink;
- Material *ma;
-
- for (link = ob->gpulamp.first; link; link = link->next) {
- lamp = link->data;
-
- while (lamp->materials.first) {
- nlink = lamp->materials.first;
- ma = nlink->data;
- BLI_freelinkN(&lamp->materials, nlink);
-
- if (ma->gpumaterial.first)
- GPU_material_free(&ma->gpumaterial);
- }
-
- gpu_lamp_shadow_free(lamp);
-
- MEM_freeN(lamp);
- }
-
- BLI_freelistN(&ob->gpulamp);
-}
-
-bool GPU_lamp_has_shadow_buffer(GPULamp *lamp)
-{
- return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) &&
- !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) &&
- lamp->tex && lamp->fb);
-}
-
-void GPU_lamp_update_buffer_mats(GPULamp *lamp)
-{
- float rangemat[4][4], persmat[4][4];
-
- /* initshadowbuf */
- invert_m4_m4(lamp->viewmat, lamp->obmat);
- normalize_v3(lamp->viewmat[0]);
- normalize_v3(lamp->viewmat[1]);
- normalize_v3(lamp->viewmat[2]);
-
- /* makeshadowbuf */
- mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat);
-
- /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */
- unit_m4(rangemat);
- rangemat[0][0] = 0.5f;
- rangemat[1][1] = 0.5f;
- rangemat[2][2] = 0.5f;
- rangemat[3][0] = 0.5f;
- rangemat[3][1] = 0.5f;
- rangemat[3][2] = 0.5f;
-
- mul_m4_m4m4(lamp->persmat, rangemat, persmat);
-}
-
-void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4])
-{
- GPU_lamp_update_buffer_mats(lamp);
-
- /* opengl */
- glDisable(GL_SCISSOR_TEST);
- GPU_texture_bind_as_framebuffer(lamp->tex);
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
- GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
-
- /* set matrices */
- copy_m4_m4(viewmat, lamp->viewmat);
- copy_m4_m4(winmat, lamp->winmat);
- *winsize = lamp->size;
-}
-
-void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
-{
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- GPU_shader_unbind();
- GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
- }
-
- GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
- GPU_framebuffer_restore();
- glEnable(GL_SCISSOR_TEST);
-}
-
-int GPU_lamp_shadow_buffer_type(GPULamp *lamp)
-{
- return lamp->la->shadowmap_type;
-}
-
-int GPU_lamp_shadow_bind_code(GPULamp *lamp)
-{
- return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1;
-}
-
-float *GPU_lamp_dynpersmat(GPULamp *lamp)
-{
- return &lamp->dynpersmat[0][0];
-}
-
-int GPU_lamp_shadow_layer(GPULamp *lamp)
-{
- if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW)))
- return lamp->lay;
- else
- return -1;
-}
-
GPUNodeLink *GPU_lamp_get_data(
GPUMaterial *mat, GPULamp *lamp,
GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy)
@@ -2658,7 +2657,6 @@ GPUNodeLink *GPU_lamp_get_data(
/* ensure shadow buffer and lamp textures will be updated */
add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, mat->ma);
return visifac;
}
@@ -2728,6 +2726,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
break;
case GPU_NONE:
+ case GPU_TEX3D:
case GPU_TEXCUBE:
case GPU_FLOAT:
case GPU_VEC2:
@@ -2735,6 +2734,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
case GPU_VEC4:
case GPU_MAT3:
case GPU_MAT4:
+ case GPU_CLOSURE:
case GPU_ATTRIB:
break;
}
@@ -2763,7 +2763,9 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
break;
case GPU_NONE:
+ case GPU_CLOSURE:
case GPU_TEX2D:
+ case GPU_TEX3D:
case GPU_TEXCUBE:
case GPU_SHADOW2D:
case GPU_ATTRIB:
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
new file mode 100644
index 00000000000..b6214f2778b
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -0,0 +1,649 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the ipmlied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Alexandr Kuznetsov, Jason Wilkins, Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/intern/gpu_matrix.c
+ * \ingroup gpu
+ */
+
+#include "../../../intern/gawain/gawain/gwn_shader_interface.h"
+
+#define SUPPRESS_GENERIC_MATRIX_API
+#define USE_GPU_PY_MATRIX_API /* only so values are declared */
+#include "GPU_matrix.h"
+#undef USE_GPU_PY_MATRIX_API
+
+#include "BLI_math_matrix.h"
+#include "BLI_math_rotation.h"
+#include "BLI_math_vector.h"
+
+
+#define DEBUG_MATRIX_BIND 0
+
+#define MATRIX_STACK_DEPTH 32
+
+typedef float Mat4[4][4];
+typedef float Mat3[3][3];
+
+typedef struct MatrixStack {
+ Mat4 stack[MATRIX_STACK_DEPTH];
+ unsigned int top;
+} MatrixStack;
+
+typedef struct {
+ MatrixStack model_view_stack;
+ MatrixStack projection_stack;
+
+ bool dirty;
+
+ /* TODO: cache of derived matrices (Normal, MVP, inverse MVP, etc)
+ * generate as needed for shaders, invalidate when original matrices change
+ *
+ * TODO: separate Model from View transform? Batches/objects have model,
+ * camera/eye has view & projection
+ */
+} MatrixState;
+
+#define MATRIX_4X4_IDENTITY {{1.0f, 0.0f, 0.0f, 0.0f}, \
+ {0.0f, 1.0f, 0.0f, 0.0f}, \
+ {0.0f, 0.0f, 1.0f, 0.0f}, \
+ {0.0f, 0.0f, 0.0f, 1.0f}}
+
+static MatrixState state = {
+ .model_view_stack = {{MATRIX_4X4_IDENTITY}, 0},
+ .projection_stack = {{MATRIX_4X4_IDENTITY}, 0},
+ .dirty = true
+};
+
+#undef MATRIX_4X4_IDENTITY
+
+#define ModelViewStack state.model_view_stack
+#define ModelView ModelViewStack.stack[ModelViewStack.top]
+
+#define ProjectionStack state.projection_stack
+#define Projection ProjectionStack.stack[ProjectionStack.top]
+
+void gpuMatrixReset(void)
+{
+ state.model_view_stack.top = 0;
+ state.projection_stack.top = 0;
+ unit_m4(ModelView);
+ unit_m4(Projection);
+ state.dirty = true;
+}
+
+#ifdef WITH_GPU_SAFETY
+
+/* Check if matrix is numerically good */
+static void checkmat(cosnt float *m)
+{
+ const int n = 16;
+ for (int i = 0; i < n; i++) {
+#if _MSC_VER
+ BLI_assert(_finite(m[i]));
+#else
+ BLI_assert(!isinf(m[i]));
+#endif
+ }
+}
+
+#define CHECKMAT(m) checkmat((const float*)m)
+
+#else
+
+#define CHECKMAT(m)
+
+#endif
+
+
+void gpuPushMatrix(void)
+{
+ BLI_assert(ModelViewStack.top + 1 < MATRIX_STACK_DEPTH);
+ ModelViewStack.top++;
+ copy_m4_m4(ModelView, ModelViewStack.stack[ModelViewStack.top - 1]);
+}
+
+void gpuPopMatrix(void)
+{
+ BLI_assert(ModelViewStack.top > 0);
+ ModelViewStack.top--;
+ state.dirty = true;
+}
+
+void gpuPushProjectionMatrix(void)
+{
+ BLI_assert(ProjectionStack.top + 1 < MATRIX_STACK_DEPTH);
+ ProjectionStack.top++;
+ copy_m4_m4(Projection, ProjectionStack.stack[ProjectionStack.top - 1]);
+}
+
+void gpuPopProjectionMatrix(void)
+{
+ BLI_assert(ProjectionStack.top > 0);
+ ProjectionStack.top--;
+ state.dirty = true;
+}
+
+void gpuLoadMatrix(const float m[4][4])
+{
+ copy_m4_m4(ModelView, m);
+ CHECKMAT(ModelView3D);
+ state.dirty = true;
+}
+
+void gpuLoadIdentityProjectionMatrix(void)
+{
+ unit_m4(Projection);
+ CHECKMAT(Projection3D);
+ state.dirty = true;
+}
+
+void gpuLoadProjectionMatrix(const float m[4][4])
+{
+ copy_m4_m4(Projection, m);
+ CHECKMAT(Projection3D);
+ state.dirty = true;
+}
+
+void gpuLoadIdentity(void)
+{
+ unit_m4(ModelView);
+ state.dirty = true;
+}
+
+void gpuTranslate2f(float x, float y)
+{
+ Mat4 m;
+ unit_m4(m);
+ m[3][0] = x;
+ m[3][1] = y;
+ gpuMultMatrix(m);
+}
+
+void gpuTranslate2fv(const float vec[2])
+{
+ gpuTranslate2f(vec[0], vec[1]);
+}
+
+void gpuTranslate3f(float x, float y, float z)
+{
+#if 1
+ translate_m4(ModelView, x, y, z);
+ CHECKMAT(ModelView);
+#else /* above works well in early testing, below is generic version */
+ Mat4 m;
+ unit_m4(m);
+ m[3][0] = x;
+ m[3][1] = y;
+ m[3][2] = z;
+ gpuMultMatrix(m);
+#endif
+ state.dirty = true;
+}
+
+void gpuTranslate3fv(const float vec[3])
+{
+ gpuTranslate3f(vec[0], vec[1], vec[2]);
+}
+
+void gpuScaleUniform(float factor)
+{
+ Mat4 m;
+ scale_m4_fl(m, factor);
+ gpuMultMatrix(m);
+}
+
+void gpuScale2f(float x, float y)
+{
+ Mat4 m = {{0.0f}};
+ m[0][0] = x;
+ m[1][1] = y;
+ m[2][2] = 1.0f;
+ m[3][3] = 1.0f;
+ gpuMultMatrix(m);
+}
+
+void gpuScale2fv(const float vec[2])
+{
+ gpuScale2f(vec[0], vec[1]);
+}
+
+void gpuScale3f(float x, float y, float z)
+{
+ Mat4 m = {{0.0f}};
+ m[0][0] = x;
+ m[1][1] = y;
+ m[2][2] = z;
+ m[3][3] = 1.0f;
+ gpuMultMatrix(m);
+}
+
+void gpuScale3fv(const float vec[3])
+{
+ gpuScale3f(vec[0], vec[1], vec[2]);
+}
+
+void gpuMultMatrix(const float m[4][4])
+{
+ mul_m4_m4_post(ModelView, m);
+ CHECKMAT(ModelView);
+ state.dirty = true;
+}
+
+void gpuRotate2D(float deg)
+{
+ /* essentially RotateAxis('Z')
+ * TODO: simpler math for 2D case
+ */
+ rotate_m4(ModelView, 'Z', DEG2RADF(deg));
+}
+
+void gpuRotate3f(float deg, float x, float y, float z)
+{
+ const float axis[3] = {x, y, z};
+ gpuRotate3fv(deg, axis);
+}
+
+void gpuRotate3fv(float deg, const float axis[3])
+{
+ Mat4 m;
+ axis_angle_to_mat4(m, axis, DEG2RADF(deg));
+ gpuMultMatrix(m);
+}
+
+void gpuRotateAxis(float deg, char axis)
+{
+ /* rotate_m4 works in place */
+ rotate_m4(ModelView, axis, DEG2RADF(deg));
+ CHECKMAT(ModelView);
+ state.dirty = true;
+}
+
+static void mat4_ortho_set(float m[4][4], float left, float right, float bottom, float top, float near, float far)
+{
+ m[0][0] = 2.0f / (right - left);
+ m[1][0] = 0.0f;
+ m[2][0] = 0.0f;
+ m[3][0] = -(right + left) / (right - left);
+
+ m[0][1] = 0.0f;
+ m[1][1] = 2.0f / (top - bottom);
+ m[2][1] = 0.0f;
+ m[3][1] = -(top + bottom) / (top - bottom);
+
+ m[0][2] = 0.0f;
+ m[1][2] = 0.0f;
+ m[2][2] = -2.0f / (far - near);
+ m[3][2] = -(far + near) / (far - near);
+
+ m[0][3] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][3] = 0.0f;
+ m[3][3] = 1.0f;
+
+ state.dirty = true;
+}
+
+static void mat4_frustum_set(float m[4][4], float left, float right, float bottom, float top, float near, float far)
+{
+ m[0][0] = 2.0f * near / (right - left);
+ m[1][0] = 0.0f;
+ m[2][0] = (right + left) / (right - left);
+ m[3][0] = 0.0f;
+
+ m[0][1] = 0.0f;
+ m[1][1] = 2.0f * near / (top - bottom);
+ m[2][1] = (top + bottom) / (top - bottom);
+ m[3][1] = 0.0f;
+
+ m[0][2] = 0.0f;
+ m[1][2] = 0.0f;
+ m[2][2] = -(far + near) / (far - near);
+ m[3][2] = -2.0f * far * near / (far - near);
+
+ m[0][3] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][3] = -1.0f;
+ m[3][3] = 0.0f;
+
+ state.dirty = true;
+}
+
+static void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3])
+{
+/* This function is loosely based on Mesa implementation.
+ *
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+ float side[3];
+
+ normalize_v3(lookdir);
+
+ cross_v3_v3v3(side, lookdir, camup);
+
+ normalize_v3(side);
+
+ cross_v3_v3v3(camup, side, lookdir);
+
+ m[0][0] = side[0];
+ m[1][0] = side[1];
+ m[2][0] = side[2];
+ m[3][0] = 0.0f;
+
+ m[0][1] = camup[0];
+ m[1][1] = camup[1];
+ m[2][1] = camup[2];
+ m[3][1] = 0.0f;
+
+ m[0][2] = -lookdir[0];
+ m[1][2] = -lookdir[1];
+ m[2][2] = -lookdir[2];
+ m[3][2] = 0.0f;
+
+ m[0][3] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][3] = 0.0f;
+ m[3][3] = 1.0f;
+
+ state.dirty = true;
+}
+
+void gpuOrtho(float left, float right, float bottom, float top, float near, float far)
+{
+ mat4_ortho_set(Projection, left, right, bottom, top, near, far);
+ CHECKMAT(Projection);
+ state.dirty = true;
+}
+
+void gpuOrtho2D(float left, float right, float bottom, float top)
+{
+ Mat4 m;
+ mat4_ortho_set(m, left, right, bottom, top, -1.0f, 1.0f);
+ CHECKMAT(Projection2D);
+ state.dirty = true;
+}
+
+void gpuFrustum(float left, float right, float bottom, float top, float near, float far)
+{
+ mat4_frustum_set(Projection, left, right, bottom, top, near, far);
+ CHECKMAT(Projection);
+ state.dirty = true;
+}
+
+void gpuPerspective(float fovy, float aspect, float near, float far)
+{
+ float half_height = tanf(fovy * (float)(M_PI / 360.0)) * near;
+ float half_width = half_height * aspect;
+ gpuFrustum(-half_width, +half_width, -half_height, +half_height, near, far);
+}
+
+void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
+{
+ Mat4 cm;
+ float lookdir[3];
+ float camup[3] = {upX, upY, upZ};
+
+ lookdir[0] = centerX - eyeX;
+ lookdir[1] = centerY - eyeY;
+ lookdir[2] = centerZ - eyeZ;
+
+ mat4_look_from_origin(cm, lookdir, camup);
+
+ gpuMultMatrix(cm);
+ gpuTranslate3f(-eyeX, -eyeY, -eyeZ);
+}
+
+void gpuProject(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3])
+{
+ float v[4];
+
+ mul_v4_m4v3(v, model, world);
+ mul_m4_v4(proj, v);
+
+ if (v[3] != 0.0f) {
+ mul_v3_fl(v, 1.0f / v[3]);
+ }
+
+ win[0] = view[0] + (view[2] * (v[0] + 1)) * 0.5f;
+ win[1] = view[1] + (view[3] * (v[1] + 1)) * 0.5f;
+ win[2] = (v[2] + 1) * 0.5f;
+}
+
+bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3])
+{
+ float pm[4][4];
+ float in[4];
+ float out[4];
+
+ mul_m4_m4m4(pm, proj, model);
+
+ if (!invert_m4(pm)) {
+ zero_v3(world);
+ return false;
+ }
+
+ in[0] = win[0];
+ in[1] = win[1];
+ in[2] = win[2];
+ in[3] = 1;
+
+ /* Map x and y from window coordinates */
+ in[0] = (in[0] - view[0]) / view[2];
+ in[1] = (in[1] - view[1]) / view[3];
+
+ /* Map to range -1 to +1 */
+ in[0] = 2 * in[0] - 1;
+ in[1] = 2 * in[1] - 1;
+ in[2] = 2 * in[2] - 1;
+
+ mul_v4_m4v3(out, pm, in);
+
+ if (out[3] == 0.0f) {
+ copy_v3_v3(world, out);
+ return false;
+ }
+
+ mul_v3_v3fl(world, out, 1.0f / out[3]);
+ return true;
+}
+
+const float (*gpuGetModelViewMatrix(float m[4][4]))[4]
+{
+ if (m) {
+ copy_m4_m4(m, ModelView);
+ return m;
+ }
+ else {
+ return ModelView;
+ }
+}
+
+const float (*gpuGetProjectionMatrix(float m[4][4]))[4]
+{
+ if (m) {
+ copy_m4_m4(m, Projection);
+ return m;
+ }
+ else {
+ return Projection;
+ }
+}
+
+const float (*gpuGetModelViewProjectionMatrix(float m[4][4]))[4]
+{
+ if (m == NULL) {
+ static Mat4 temp;
+ m = temp;
+ }
+
+ mul_m4_m4m4(m, Projection, ModelView);
+ return m;
+}
+
+const float (*gpuGetNormalMatrix(float m[3][3]))[3]
+{
+ if (m == NULL) {
+ static Mat3 temp3;
+ m = temp3;
+ }
+
+ copy_m3_m4(m, (const float (*)[4])gpuGetModelViewMatrix(NULL));
+
+ invert_m3(m);
+ transpose_m3(m);
+
+ return m;
+}
+
+const float (*gpuGetNormalMatrixInverse(float m[3][3]))[3]
+{
+ if (m == NULL) {
+ static Mat3 temp3;
+ m = temp3;
+ }
+
+ gpuGetNormalMatrix(m);
+ invert_m3(m);
+
+ return m;
+}
+
+void gpuBindMatrices(const Gwn_ShaderInterface *shaderface)
+{
+ /* set uniform values to matrix stack values
+ * call this before a draw call if desired matrices are dirty
+ * call glUseProgram before this, as glUniform expects program to be bound
+ */
+
+ const Gwn_ShaderInput *MV = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_MODELVIEW);
+ const Gwn_ShaderInput *P = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_PROJECTION);
+ const Gwn_ShaderInput *MVP = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_MVP);
+
+ const Gwn_ShaderInput *N = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_NORMAL);
+ const Gwn_ShaderInput *MV_inv = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_MODELVIEW_INV);
+ const Gwn_ShaderInput *P_inv = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_PROJECTION_INV);
+
+ if (MV) {
+#if DEBUG_MATRIX_BIND
+ puts("setting MV matrix");
+#endif
+
+ glUniformMatrix4fv(MV->location, 1, GL_FALSE, (const float *)gpuGetModelViewMatrix(NULL));
+ }
+
+ if (P) {
+#if DEBUG_MATRIX_BIND
+ puts("setting P matrix");
+#endif
+
+ glUniformMatrix4fv(P->location, 1, GL_FALSE, (const float *)gpuGetProjectionMatrix(NULL));
+ }
+
+ if (MVP) {
+#if DEBUG_MATRIX_BIND
+ puts("setting MVP matrix");
+#endif
+
+ glUniformMatrix4fv(MVP->location, 1, GL_FALSE, (const float *)gpuGetModelViewProjectionMatrix(NULL));
+ }
+
+ if (N) {
+#if DEBUG_MATRIX_BIND
+ puts("setting normal matrix");
+#endif
+
+ glUniformMatrix3fv(N->location, 1, GL_FALSE, (const float *)gpuGetNormalMatrix(NULL));
+ }
+
+ if (MV_inv) {
+ Mat4 m;
+ gpuGetModelViewMatrix(m);
+ invert_m4(m);
+ glUniformMatrix4fv(MV_inv->location, 1, GL_FALSE, (const float *)m);
+ }
+
+ if (P_inv) {
+ Mat4 m;
+ gpuGetProjectionMatrix(m);
+ invert_m4(m);
+ glUniformMatrix4fv(P_inv->location, 1, GL_FALSE, (const float *)m);
+ }
+
+ state.dirty = false;
+}
+
+bool gpuMatricesDirty(void)
+{
+ return state.dirty;
+}
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Python API Helpers
+ * \{ */
+BLI_STATIC_ASSERT(GPU_PY_MATRIX_STACK_LEN + 1 == MATRIX_STACK_DEPTH, "define mismatch");
+
+/* Return int since caller is may subtract. */
+
+int GPU_matrix_stack_level_get_model_view(void)
+{
+ return (int)state.model_view_stack.top;
+}
+
+int GPU_matrix_stack_level_get_projection(void)
+{
+ return (int)state.projection_stack.top;
+}
+
+/** \} */
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 632b0cfee1b..153cf5f1e97 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -187,12 +187,7 @@ unsigned int GPU_select_end(void)
*/
bool GPU_select_query_check_active(void)
{
- return ((U.gpu_select_method == USER_SELECT_USE_OCCLUSION_QUERY) ||
- ((U.gpu_select_method == USER_SELECT_AUTO) &&
- (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY) ||
- /* unsupported by nouveau, gallium 0.4, see: T47940 */
- GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE))));
-
+ return ELEM(U.gpu_select_method, USER_SELECT_USE_OCCLUSION_QUERY, USER_SELECT_AUTO);
}
/* ----------------------------------------------------------------------------
@@ -232,3 +227,29 @@ bool GPU_select_is_cached(void)
{
return g_select_state.use_cache && gpu_select_pick_is_cached();
}
+
+
+/* ----------------------------------------------------------------------------
+ * Utilities
+ */
+
+/**
+ * Helper function, nothing special but avoids doing inline since hit's aren't sorted by depth
+ * and purpose of 4x buffer indices isn't so clear.
+ *
+ * Note that comparing depth as uint is fine.
+ */
+const uint *GPU_select_buffer_near(const uint *buffer, int hits)
+{
+ const uint *buffer_near = NULL;
+ uint depth_min = (uint)-1;
+ for (int i = 0; i < hits; i++) {
+ if (buffer[1] < depth_min) {
+ BLI_assert(buffer[3] != -1);
+ depth_min = buffer[1];
+ buffer_near = buffer;
+ }
+ buffer += 4;
+ }
+ return buffer_near;
+}
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
index 0a77420fa25..f1d311890e6 100644
--- a/source/blender/gpu/intern/gpu_select_pick.c
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -31,6 +31,8 @@
#include <stdlib.h>
#include <float.h>
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
#include "GPU_select.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
@@ -316,8 +318,8 @@ void gpu_select_pick_begin(
/* Restrict OpenGL operations for when we don't have cache */
if (ps->is_cached == false) {
+ gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT);
- glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
/* disable writing to the framebuffer */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
@@ -331,10 +333,6 @@ void gpu_select_pick_begin(
glDepthFunc(GL_LEQUAL);
}
- /* set just in case */
- glPixelTransferf(GL_DEPTH_BIAS, 0.0);
- glPixelTransferf(GL_DEPTH_SCALE, 1.0);
-
float viewport[4];
glGetFloatv(GL_SCISSOR_BOX, viewport);
@@ -540,7 +538,7 @@ unsigned int gpu_select_pick_end(void)
gpu_select_pick_load_id(ps->gl.prev_id);
}
- glPopAttrib();
+ gpuPopAttrib();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c
index 3d589986281..e3bd20f3776 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.c
+++ b/source/blender/gpu/intern/gpu_select_sample_query.c
@@ -32,6 +32,8 @@
#include <stdlib.h>
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
#include "GPU_select.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
@@ -94,7 +96,7 @@ void gpu_select_query_begin(
g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id), "gpu selection ids");
glGenQueries(g_query_state.num_of_queries, g_query_state.queries);
- glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
+ gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT);
/* disable writing to the framebuffer */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
@@ -206,7 +208,7 @@ unsigned int gpu_select_query_end(void)
glDeleteQueries(g_query_state.num_of_queries, g_query_state.queries);
MEM_freeN(g_query_state.queries);
MEM_freeN(g_query_state.id);
- glPopAttrib();
+ gpuPopAttrib();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
return hits;
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index b579f87698c..598722d372b 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -30,22 +30,113 @@
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
#include "BLI_math_vector.h"
+#include "BLI_path_util.h"
+#include "BKE_appdir.h"
#include "BKE_global.h"
+#include "DNA_space_types.h"
+
#include "GPU_compositing.h"
-#include "GPU_debug.h"
#include "GPU_extensions.h"
-#include "GPU_glew.h"
+#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
-#include "GPU_material.h"
+#include "GPU_uniformbuffer.h"
+
+#include "gpu_shader_private.h"
-/* TODO(sergey): Find better default values for this constants. */
-#define MAX_DEFINE_LENGTH 1024
-#define MAX_EXT_DEFINE_LENGTH 1024
+/* Adjust these constants as needed. */
+#define MAX_DEFINE_LENGTH 256
+#define MAX_EXT_DEFINE_LENGTH 256
/* 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_diag_stripes_frag_glsl[];
+extern char datatoc_gpu_shader_simple_lighting_frag_glsl[];
+extern char datatoc_gpu_shader_simple_lighting_flat_color_frag_glsl[];
+extern char datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl[];
+extern char datatoc_gpu_shader_simple_lighting_smooth_color_alpha_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[];
+extern char datatoc_gpu_shader_2D_flat_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[];
+extern char datatoc_gpu_shader_2D_image_vert_glsl[];
+
+extern char datatoc_gpu_shader_3D_image_vert_glsl[];
+extern char datatoc_gpu_shader_image_linear_frag_glsl[];
+extern char datatoc_gpu_shader_image_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_alpha_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_interlace_frag_glsl[];
+extern char datatoc_gpu_shader_image_mask_uniform_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
+extern char datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl[];
+extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[];
+extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_3D_normal_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_normal_flat_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_normal_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_objectspace_variying_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_screen_aligned_vert_glsl[];
+extern char datatoc_gpu_shader_instance_camera_vert_glsl[];
+extern char datatoc_gpu_shader_instance_distance_line_vert_glsl[];
+extern char datatoc_gpu_shader_instance_edges_variying_color_geom_glsl[];
+extern char datatoc_gpu_shader_instance_edges_variying_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_bone_envelope_solid_vert_glsl[];
+extern char datatoc_gpu_shader_instance_bone_envelope_wire_vert_glsl[];
+extern char datatoc_gpu_shader_instance_mball_helpers_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_aa_frag_glsl[];
+extern char datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl[];
+extern char datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl[];
+extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
+extern char datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_varying_size_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl[];
+
+extern char datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[];
+extern char datatoc_gpu_shader_2D_line_dashed_geom_glsl[];
+extern char datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl[];
+extern char datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl[];
+
+extern char datatoc_gpu_shader_edges_front_back_persp_vert_glsl[];
+extern char datatoc_gpu_shader_edges_front_back_persp_geom_glsl[];
+extern char datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl[];
+extern char datatoc_gpu_shader_edges_front_back_ortho_vert_glsl[];
+extern char datatoc_gpu_shader_edges_overlay_vert_glsl[];
+extern char datatoc_gpu_shader_edges_overlay_geom_glsl[];
+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[];
extern char datatoc_gpu_shader_smoke_frag_glsl[];
@@ -53,7 +144,7 @@ extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
-extern char datatoc_gpu_shader_fx_vert_glsl[];
+extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
@@ -63,41 +154,25 @@ extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[];
extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
extern char datatoc_gpu_shader_fx_lib_glsl[];
-static struct GPUShadersGlobal {
- struct {
- GPUShader *vsm_store;
- GPUShader *sep_gaussian_blur;
- GPUShader *smoke;
- GPUShader *smoke_fire;
- GPUShader *smoke_coba;
- /* cache for shader fx. Those can exist in combinations so store them here */
- GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
- } shaders;
-} GG = {{NULL}};
-
-/* GPUShader */
+/* cache of built-in shaders (each is created on first use) */
+static GPUShader *builtin_shaders[GPU_NUM_BUILTIN_SHADERS] = { NULL };
-struct GPUShader {
- GLuint program; /* handle for full program (links shader stages below) */
+/* cache for shader fx. Those can exist in combinations so store them here */
+static GPUShader *fx_shaders[MAX_FX_SHADERS * 2] = { NULL };
- GLuint vertex; /* handle for vertex shader */
- GLuint geometry; /* handle for geometry shader */
- GLuint fragment; /* handle for fragment shader */
-
- int totattrib; /* total number of attributes */
- int uniforms; /* required uniforms */
-
- void *uniform_interface; /* cached uniform interface for shader. Data depends on shader */
-};
+typedef struct {
+ const char *vert;
+ const char *frag;
+ const char *geom; /* geometry stage runs between vert & frag, but is less common, so it goes last */
+} GPUShaderStages;
static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
{
- int i;
int line = 1;
fprintf(stderr, "GPUShader: %s error:\n", task);
- for (i = 0; i < totcode; i++) {
+ for (int i = 0; i < totcode; i++) {
const char *c, *pos, *end = code[i] + strlen(code[i]);
if (G.debug & G_DEBUG) {
@@ -120,71 +195,19 @@ static void shader_print_errors(const char *task, const char *log, const char **
static const char *gpu_shader_version(void)
{
- if (GLEW_VERSION_3_2) {
- if (GLEW_ARB_compatibility) {
- return "#version 150 compatibility\n";
- /* highest version that is widely supported
- * gives us native geometry shaders!
- * use compatibility profile so we can continue using builtin shader input/output names
- */
- }
- else {
- return "#version 130\n";
- /* latest version that is compatible with existing shaders */
- }
- }
- else if (GLEW_VERSION_3_1) {
- if (GLEW_ARB_compatibility) {
- return "#version 140\n";
- /* also need the ARB_compatibility extension, handled below */
- }
- else {
- return "#version 130\n";
- /* latest version that is compatible with existing shaders */
- }
- }
- else if (GLEW_VERSION_3_0) {
- return "#version 130\n";
- /* GLSL 1.3 has modern syntax/keywords/datatypes so use if available
- * older features are deprecated but still available without compatibility extension or profile
- */
- }
- else {
- return "#version 120\n";
- /* minimum supported */
- }
+ return "#version 330\n";
}
-
-static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_geometry_shader)
+static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH])
{
/* enable extensions for features that are not part of our base GLSL version
* don't use an extension for something already available!
*/
if (GLEW_ARB_texture_query_lod) {
- /* a #version 400 feature, but we use #version 150 maximum so use extension */
+ /* a #version 400 feature, but we use #version 330 maximum so use extension */
strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
}
-
- if (use_geometry_shader && GPU_geometry_shader_support_via_extension()) {
- strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n");
- }
-
- if (GLEW_VERSION_3_1 && !GLEW_VERSION_3_2 && GLEW_ARB_compatibility) {
- strcat(defines, "#extension GL_ARB_compatibility: enable\n");
- }
-
- if (!GLEW_VERSION_3_1) {
- if (GLEW_ARB_draw_instanced) {
- strcat(defines, "#extension GL_ARB_draw_instanced: enable\n");
- }
-
- if (!GLEW_VERSION_3_0 && GLEW_EXT_gpu_shader4) {
- strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n");
- /* TODO: maybe require this? shaders become so much nicer */
- }
- }
}
static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH],
@@ -207,10 +230,6 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH],
if (GPU_bicubic_bump_support())
strcat(defines, "#define BUMP_BICUBIC\n");
- if (GLEW_VERSION_3_0) {
- strcat(defines, "#define BIT_OPERATIONS\n");
- }
-
#ifdef WITH_OPENSUBDIV
/* TODO(sergey): Check whether we actually compiling shader for
* the OpenSubdiv mesh.
@@ -243,37 +262,71 @@ GPUShader *GPU_shader_create(const char *vertexcode,
const char *fragcode,
const char *geocode,
const char *libcode,
- const char *defines,
- int input,
- int output,
- int number)
+ const char *defines)
{
return GPU_shader_create_ex(vertexcode,
fragcode,
geocode,
libcode,
defines,
- input,
- output,
- number,
GPU_SHADER_FLAGS_NONE);
}
+#define DEBUG_SHADER_NONE ""
+#define DEBUG_SHADER_VERTEX "vert"
+#define DEBUG_SHADER_FRAGMENT "frag"
+#define DEBUG_SHADER_GEOMETRY "geom"
+
+/**
+ * Dump GLSL shaders to disk
+ *
+ * This is used for profiling shader performance externally and debug if shader code is correct.
+ * If called with no code, it simply bumps the shader index, so different shaders for the same
+ * program share the same index.
+ */
+static void gpu_dump_shaders(const char **code, const int num_shaders, const char *extension)
+{
+ if ((G.debug & G_DEBUG_GPU_SHADERS) == 0) {
+ return;
+ }
+
+ /* We use the same shader index for shaders in the same program.
+ * So we call this function once before calling for the invidual shaders. */
+ static int shader_index = 0;
+ if (code == NULL) {
+ shader_index++;
+ BLI_assert(STREQ(DEBUG_SHADER_NONE, extension));
+ return;
+ }
+
+ /* Determine the full path of the new shader. */
+ char shader_path[FILE_MAX];
+
+ char file_name[512] = {'\0'};
+ sprintf(file_name, "%04d.%s", shader_index, extension);
+
+ BLI_join_dirfile(shader_path, sizeof(shader_path), BKE_tempdir_session(), file_name);
+
+ /* Write shader to disk. */
+ FILE *f = fopen(shader_path, "w");
+ if (f == NULL) {
+ printf("Error writing to file: %s\n", shader_path);
+ }
+ for (int j = 0; j < num_shaders; j++) {
+ fprintf(f, "%s", code[j]);
+ }
+ fclose(f);
+ printf("Shader file written to disk: %s\n", shader_path);
+}
+
GPUShader *GPU_shader_create_ex(const char *vertexcode,
const char *fragcode,
const char *geocode,
const char *libcode,
const char *defines,
- int input,
- int output,
- int number,
const int flags)
{
#ifdef WITH_OPENSUBDIV
- /* TODO(sergey): used to add #version 150 to the geometry shader.
- * Could safely be renamed to "use_geometry_code" since it's very
- * likely any of geometry code will want to use GLSL 1.5.
- */
bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
#else
UNUSED_VARS(flags);
@@ -286,10 +339,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
char standard_defines[MAX_DEFINE_LENGTH] = "";
char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
- if (geocode && !GPU_geometry_shader_support())
- return NULL;
-
shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
+ gpu_dump_shaders(NULL, 0, DEBUG_SHADER_NONE);
if (vertexcode)
shader->vertex = glCreateShader(GL_VERTEX_SHADER);
@@ -313,7 +364,7 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
gpu_shader_standard_defines(standard_defines,
use_opensubdiv,
(flags & GPU_SHADER_FLAGS_NEW_SHADING) != 0);
- gpu_shader_standard_extensions(standard_extensions, geocode != NULL);
+ gpu_shader_standard_extensions(standard_extensions);
if (vertexcode) {
const char *source[5];
@@ -327,6 +378,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
if (defines) source[num_source++] = defines;
source[num_source++] = vertexcode;
+ gpu_dump_shaders(source, num_source, DEBUG_SHADER_VERTEX);
+
glAttachShader(shader->program, shader->vertex);
glShaderSource(shader->vertex, num_source, source, NULL);
@@ -366,6 +419,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
if (libcode) source[num_source++] = libcode;
source[num_source++] = fragcode;
+ gpu_dump_shaders(source, num_source, DEBUG_SHADER_FRAGMENT);
+
glAttachShader(shader->program, shader->fragment);
glShaderSource(shader->fragment, num_source, source, NULL);
@@ -392,6 +447,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
if (defines) source[num_source++] = defines;
source[num_source++] = geocode;
+ gpu_dump_shaders(source, num_source, DEBUG_SHADER_GEOMETRY);
+
glAttachShader(shader->program, shader->geometry);
glShaderSource(shader->geometry, num_source, source, NULL);
@@ -405,20 +462,12 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
GPU_shader_free(shader);
return NULL;
}
-
- if (!use_opensubdiv) {
- GPU_shader_geometry_stage_primitive_io(shader, input, output, number);
- }
}
#ifdef WITH_OPENSUBDIV
if (use_opensubdiv) {
glBindAttribLocation(shader->program, 0, "position");
glBindAttribLocation(shader->program, 1, "normal");
- GPU_shader_geometry_stage_primitive_io(shader,
- GL_LINES_ADJACENCY_EXT,
- GL_TRIANGLE_STRIP,
- 4);
}
#endif
@@ -436,38 +485,54 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
return NULL;
}
+ shader->interface = GWN_shaderinterface_create(shader->program);
+
#ifdef WITH_OPENSUBDIV
/* TODO(sergey): Find a better place for this. */
- if (use_opensubdiv && GLEW_VERSION_4_1) {
- glProgramUniform1i(shader->program,
- glGetUniformLocation(shader->program, "FVarDataOffsetBuffer"),
- 30); /* GL_TEXTURE30 */
-
- glProgramUniform1i(shader->program,
- glGetUniformLocation(shader->program, "FVarDataBuffer"),
- 31); /* GL_TEXTURE31 */
+ if (use_opensubdiv) {
+ if (GLEW_VERSION_4_1) {
+ glProgramUniform1i(shader->program,
+ GWN_shaderinterface_uniform(shader->interface, "FVarDataOffsetBuffer")->location,
+ 30); /* GL_TEXTURE30 */
+
+ glProgramUniform1i(shader->program,
+ GWN_shaderinterface_uniform(shader->interface, "FVarDataBuffer")->location,
+ 31); /* GL_TEXTURE31 */
+ }
+ else {
+ glUseProgram(shader->program);
+ glUniform1i(GWN_shaderinterface_uniform(shader->interface, "FVarDataOffsetBuffer")->location, 30);
+ glUniform1i(GWN_shaderinterface_uniform(shader->interface, "FVarDataBuffer")->location, 31);
+ glUseProgram(0);
+ }
}
#endif
return shader;
}
+#undef DEBUG_SHADER_GEOMETRY
+#undef DEBUG_SHADER_FRAGMENT
+#undef DEBUG_SHADER_VERTEX
+#undef DEBUG_SHADER_NONE
+
void GPU_shader_bind(GPUShader *shader)
{
- GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
+ BLI_assert(shader && shader->program);
+
glUseProgram(shader->program);
- GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind");
+ gpuBindMatrices(shader->interface);
}
void GPU_shader_unbind(void)
{
- GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind");
glUseProgram(0);
- GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind");
}
void GPU_shader_free(GPUShader *shader)
{
+ BLI_assert(shader);
+
if (shader->vertex)
glDeleteShader(shader->vertex);
if (shader->geometry)
@@ -480,20 +545,51 @@ void GPU_shader_free(GPUShader *shader)
if (shader->uniform_interface)
MEM_freeN(shader->uniform_interface);
+ if (shader->interface)
+ GWN_shaderinterface_discard(shader->interface);
+
MEM_freeN(shader);
}
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
{
- return glGetUniformLocation(shader->program, name);
+ BLI_assert(shader && shader->program);
+ const Gwn_ShaderInput *uniform = GWN_shaderinterface_uniform(shader->interface, name);
+ return uniform ? uniform->location : -1;
}
-void *GPU_shader_get_interface(GPUShader *shader)
+int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin)
+{
+ BLI_assert(shader && shader->program);
+ const Gwn_ShaderInput *uniform = GWN_shaderinterface_uniform_builtin(shader->interface, builtin);
+ return uniform ? uniform->location : -1;
+}
+
+int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
+{
+ BLI_assert(shader && shader->program);
+
+ const Gwn_ShaderInput *ubo = GWN_shaderinterface_ubo(shader->interface, name);
+ return ubo ? ubo->location : -1;
+}
+
+void *GPU_fx_shader_get_interface(GPUShader *shader)
{
return shader->uniform_interface;
}
-void GPU_shader_set_interface(GPUShader *shader, void *interface)
+void *GPU_shader_get_interface(GPUShader *shader)
+{
+ return shader->interface;
+}
+
+/* Clement : Temp */
+int GPU_shader_get_program(GPUShader *shader)
+{
+ return (int)shader->program;
+}
+
+void GPU_fx_shader_set_interface(GPUShader *shader, void *interface)
{
shader->uniform_interface = interface;
}
@@ -503,16 +599,12 @@ void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int leng
if (location == -1 || value == NULL)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
-
if (length == 1) glUniform1fv(location, arraysize, value);
else if (length == 2) glUniform2fv(location, arraysize, value);
else if (length == 3) glUniform3fv(location, arraysize, value);
else if (length == 4) glUniform4fv(location, arraysize, value);
else if (length == 9) glUniformMatrix3fv(location, arraysize, 0, value);
else if (length == 16) glUniformMatrix4fv(location, arraysize, 0, value);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
}
void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
@@ -520,14 +612,10 @@ void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int
if (location == -1)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
-
if (length == 1) glUniform1iv(location, arraysize, value);
else if (length == 2) glUniform2iv(location, arraysize, value);
else if (length == 3) glUniform3iv(location, arraysize, value);
else if (length == 4) glUniform4iv(location, arraysize, value);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
}
void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
@@ -535,22 +623,22 @@ void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
if (location == -1)
return;
- GPU_CHECK_ERRORS_AROUND(glUniform1i(location, value));
+ glUniform1i(location, value);
}
-void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number)
+void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo)
{
- if (GPU_geometry_shader_support_via_extension()) {
- /* geometry shaders must provide this info themselves for #version 150 and up */
- glProgramParameteriEXT(shader->program, GL_GEOMETRY_INPUT_TYPE_EXT, input);
- glProgramParameteriEXT(shader->program, GL_GEOMETRY_OUTPUT_TYPE_EXT, output);
- glProgramParameteriEXT(shader->program, GL_GEOMETRY_VERTICES_OUT_EXT, number);
+ 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)
{
- GLenum arbnumber;
int number = GPU_texture_bound_number(tex);
int bindcode = GPU_texture_opengl_bindcode(tex);
int target = GPU_texture_target(tex);
@@ -566,78 +654,228 @@ void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUText
if (location == -1)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture");
-
- arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
+ if (number != 0)
+ glActiveTexture(GL_TEXTURE0 + number);
- if (number != 0) glActiveTexture(arbnumber);
if (bindcode != 0)
glBindTexture(target, bindcode);
else
GPU_invalid_tex_bind(target);
+
glUniform1i(location, number);
- glEnable(target);
- if (number != 0) glActiveTexture(GL_TEXTURE0);
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture");
+ if (number != 0)
+ glActiveTexture(GL_TEXTURE0);
}
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
{
- int index;
-
- GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocation(shader->program, name));
-
- return index;
+ BLI_assert(shader && shader->program);
+ const Gwn_ShaderInput *attrib = GWN_shaderinterface_attr(shader->interface, name);
+ return attrib ? attrib->location : -1;
}
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
{
- GPUShader *retval = NULL;
-
- switch (shader) {
- case GPU_SHADER_VSM_STORE:
- if (!GG.shaders.vsm_store)
- GG.shaders.vsm_store = GPU_shader_create(
- datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.vsm_store;
- break;
- case GPU_SHADER_SEP_GAUSSIAN_BLUR:
- if (!GG.shaders.sep_gaussian_blur)
- GG.shaders.sep_gaussian_blur = GPU_shader_create(
- datatoc_gpu_shader_sep_gaussian_blur_vert_glsl,
- datatoc_gpu_shader_sep_gaussian_blur_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.sep_gaussian_blur;
- break;
- case GPU_SHADER_SMOKE:
- if (!GG.shaders.smoke)
- GG.shaders.smoke = GPU_shader_create(
- datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.smoke;
- break;
- case GPU_SHADER_SMOKE_FIRE:
- if (!GG.shaders.smoke_fire)
- GG.shaders.smoke_fire = GPU_shader_create(
- datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_fire_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.smoke_fire;
- break;
- case GPU_SHADER_SMOKE_COBA:
- if (!GG.shaders.smoke_coba)
- GG.shaders.smoke_coba = GPU_shader_create(
- datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl,
- NULL, NULL, "#define USE_COBA;\n", 0, 0, 0);
- retval = GG.shaders.smoke_coba;
- break;
- }
+ BLI_assert(shader != GPU_NUM_BUILTIN_SHADERS); /* don't be a troll */
+
+ static const GPUShaderStages builtin_shader_stages[GPU_NUM_BUILTIN_SHADERS] = {
+ [GPU_SHADER_VSM_STORE] = { datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl },
+ [GPU_SHADER_SEP_GAUSSIAN_BLUR] = { datatoc_gpu_shader_sep_gaussian_blur_vert_glsl,
+ datatoc_gpu_shader_sep_gaussian_blur_frag_glsl },
+ [GPU_SHADER_SMOKE] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
+ [GPU_SHADER_SMOKE_FIRE] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
+ [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 },
+ [GPU_SHADER_EDGES_FRONT_BACK_ORTHO] = { datatoc_gpu_shader_edges_front_back_ortho_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_EDGES_OVERLAY_SIMPLE] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_edges_overlay_frag_glsl,
+ datatoc_gpu_shader_edges_overlay_simple_geom_glsl },
+ [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_normal_vert_glsl, datatoc_gpu_shader_simple_lighting_frag_glsl },
+ /* Use 'USE_FLAT_NORMAL' to make flat shader from smooth */
+ [GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR] = { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl },
+ [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl },
+ [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA] = { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, datatoc_gpu_shader_simple_lighting_smooth_color_alpha_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 },
+ [GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] = { datatoc_gpu_shader_3D_image_vert_glsl,
+ datatoc_gpu_shader_image_modulate_alpha_frag_glsl },
+ [GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA] = { datatoc_gpu_shader_3D_image_vert_glsl,
+ datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl },
+ [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_CHECKER] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_checker_frag_glsl },
+
+ [GPU_SHADER_2D_DIAG_STRIPES] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_diag_stripes_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,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_2D_SMOOTH_COLOR] = { datatoc_gpu_shader_2D_smooth_color_vert_glsl,
+ datatoc_gpu_shader_2D_smooth_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_linear_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_ALPHA_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_alpha_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_shuffle_color_frag_glsl },
+ [GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_UNIFORM_COLOR_U32] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_3D_FLAT_COLOR_U32] = { datatoc_gpu_shader_3D_flat_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [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_CLIPPED_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl,
+ datatoc_gpu_shader_uniform_color_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_2D_LINE_DASHED_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl,
+ datatoc_gpu_shader_2D_line_dashed_frag_glsl,
+ datatoc_gpu_shader_2D_line_dashed_geom_glsl },
+ [GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl,
+ datatoc_gpu_shader_2D_line_dashed_frag_glsl,
+ datatoc_gpu_shader_2D_line_dashed_geom_glsl },
+
+ [GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR] =
+ { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl,
+ datatoc_gpu_shader_simple_lighting_frag_glsl},
+ [GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR] = { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_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_3D_INSTANCE_SCREEN_ALIGNED_AXIS] = { datatoc_gpu_shader_instance_screen_aligned_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+ [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED] = { datatoc_gpu_shader_instance_screen_aligned_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+
+ [GPU_SHADER_CAMERA] = { datatoc_gpu_shader_instance_camera_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+ [GPU_SHADER_DISTANCE_LINES] = { datatoc_gpu_shader_instance_distance_line_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] =
+ { datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_frag_glsl },
+ [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] =
+ { datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_aa_frag_glsl },
+ [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] =
+ { datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl },
+ [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA] =
+ { datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl },
+ [GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] = { datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_frag_glsl },
+ [GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_point_varying_size_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] =
+ { datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_frag_glsl },
+ [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] =
+ { datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_aa_frag_glsl },
+ [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] =
+ { datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_outline_aa_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 },
+ [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE] =
+ { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR] = { datatoc_gpu_shader_instance_edges_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ datatoc_gpu_shader_instance_edges_variying_color_geom_glsl},
+
+ [GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID] = { datatoc_gpu_shader_instance_bone_envelope_solid_vert_glsl,
+ datatoc_gpu_shader_simple_lighting_frag_glsl },
+ [GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE] = { datatoc_gpu_shader_instance_bone_envelope_wire_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+
+ [GPU_SHADER_3D_INSTANCE_MBALL_HELPERS] = { datatoc_gpu_shader_instance_mball_helpers_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ };
+
+ if (builtin_shaders[shader] == NULL) {
+ /* just a few special cases */
+ const char *defines = NULL;
+ switch (shader) {
+ case GPU_SHADER_SMOKE_COBA:
+ defines = "#define USE_COBA;\n";
+ break;
+ case GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE:
+ defines = "#define UNIFORM_SCALE;\n";
+ break;
+ case GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS:
+ defines = "#define AXIS_NAME;\n";
+ break;
+ case GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR:
+ case GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID:
+ defines = "#define USE_INSTANCE_COLOR;\n";
+ break;
+ case GPU_SHADER_3D_FLAT_COLOR_U32:
+ case GPU_SHADER_3D_UNIFORM_COLOR_U32:
+ defines = "#define USE_COLOR_U32;\n";
+ break;
+ case GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR:
+ defines = "#define USE_FLAT_NORMAL;\n";
+ break;
+ default:
+ break;
+ }
+
+ const GPUShaderStages *stages = builtin_shader_stages + shader;
- if (retval == NULL)
- printf("Unable to create a GPUShader for builtin shader: %u\n", shader);
+ 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;
+ }
+
+ if (shader == GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR && !GLEW_VERSION_3_2) {
+ /* Dashed need geometry shader, which are not supported by legacy OpenGL, fallback to solid lines. */
+ /* TODO: remove after switch to core profile (maybe) */
+ static const GPUShaderStages legacy_dashed_lines = { datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl,
+ datatoc_gpu_shader_2D_line_dashed_frag_glsl };
+ stages = &legacy_dashed_lines;
+ }
- return retval;
+ /* common case */
+ builtin_shaders[shader] = GPU_shader_create(stages->vert, stages->frag, stages->geom, NULL, defines);
+ }
+
+ return builtin_shaders[shader];
}
#define MAX_DEFINES 100
@@ -657,103 +895,80 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp)
strcat(defines, "#define PERSP_MATRIX\n");
}
- if (!GG.shaders.fx_shaders[offset]) {
+ if (!fx_shaders[offset]) {
GPUShader *shader = NULL;
switch (effect) {
case GPU_SHADER_FX_SSAO:
- shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ shader = GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
break;
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
strcat(defines, "#define FIRST_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
break;
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
strcat(defines, "#define SECOND_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
break;
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
strcat(defines, "#define THIRD_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
break;
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
strcat(defines, "#define FOURTH_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
break;
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
strcat(defines, "#define FIFTH_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
break;
case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
strcat(defines, "#define FIRST_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
break;
case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
strcat(defines, "#define SECOND_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl,
- defines, GL_POINTS, GL_TRIANGLE_STRIP, 4);
+ shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl, defines);
break;
case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
strcat(defines, "#define THIRD_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines);
break;
case GPU_SHADER_FX_DEPTH_RESOLVE:
- shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
+ shader = GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines);
break;
}
- GG.shaders.fx_shaders[offset] = shader;
+ fx_shaders[offset] = shader;
GPU_fx_shader_init_interface(shader, effect);
}
- return GG.shaders.fx_shaders[offset];
+ return fx_shaders[offset];
}
void GPU_shader_free_builtin_shaders(void)
{
- int i;
-
- if (GG.shaders.vsm_store) {
- GPU_shader_free(GG.shaders.vsm_store);
- GG.shaders.vsm_store = NULL;
- }
-
- if (GG.shaders.sep_gaussian_blur) {
- GPU_shader_free(GG.shaders.sep_gaussian_blur);
- GG.shaders.sep_gaussian_blur = NULL;
- }
-
- if (GG.shaders.smoke) {
- GPU_shader_free(GG.shaders.smoke);
- GG.shaders.smoke = NULL;
- }
-
- if (GG.shaders.smoke_fire) {
- GPU_shader_free(GG.shaders.smoke_fire);
- GG.shaders.smoke_fire = NULL;
- }
-
- if (GG.shaders.smoke_coba) {
- GPU_shader_free(GG.shaders.smoke_coba);
- GG.shaders.smoke_coba = NULL;
+ for (int i = 0; i < GPU_NUM_BUILTIN_SHADERS; ++i) {
+ if (builtin_shaders[i]) {
+ GPU_shader_free(builtin_shaders[i]);
+ builtin_shaders[i] = NULL;
+ }
}
- for (i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
- if (GG.shaders.fx_shaders[i]) {
- GPU_shader_free(GG.shaders.fx_shaders[i]);
- GG.shaders.fx_shaders[i] = NULL;
+ for (int i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
+ if (fx_shaders[i]) {
+ GPU_shader_free(fx_shaders[i]);
+ fx_shaders[i] = NULL;
}
}
}
-
-
diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h
new file mode 100644
index 00000000000..f883773df17
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_private.h
@@ -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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpu_shader_private.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_SHADER_PRIVATE_H__
+#define __GPU_SHADER_PRIVATE_H__
+
+#include "GPU_glew.h"
+#include "gawain/gwn_shader_interface.h"
+
+struct GPUShader {
+ GLuint program; /* handle for full program (links shader stages below) */
+
+ GLuint vertex; /* handle for vertex shader */
+ GLuint geometry; /* handle for geometry shader */
+ GLuint fragment; /* handle for fragment shader */
+
+ void *uniform_interface; /* cached uniform interface for shader. Data depends on shader */
+ /* NOTE: ^-- only FX compositing shaders use this */
+
+ Gwn_ShaderInterface *interface; /* cached uniform & attrib interface for shader */
+};
+
+#endif /* __GPU_SHADER_PRIVATE_H__ */
+
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 1c97c2ce811..252eede8758 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,43 +61,260 @@ 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? */
+ bool stencil; /* is a stencil texture? */
+
+ unsigned int bytesize; /* number of byte for one pixel */
+ int format; /* GPUTextureFormat */
+ int components; /* number of color/alpha channels */
};
-static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
+/* ------ Memory Management ------- */
+/* Records every texture allocation / free
+ * to estimate the Texture Pool Memory consumption */
+static unsigned int memory_usage;
+
+static unsigned int gpu_texture_memory_footprint_compute(GPUTexture *tex)
{
- unsigned char *pixels, *p;
- const float *fp = fpixels;
- const int len = 4 * length;
+ switch (tex->target) {
+ case GL_TEXTURE_1D:
+ return tex->bytesize * tex->w;
+ case GL_TEXTURE_1D_ARRAY:
+ case GL_TEXTURE_2D:
+ return tex->bytesize * tex->w * tex->h;
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_3D:
+ return tex->bytesize * tex->w * tex->h * tex->d;
+ case GL_TEXTURE_CUBE_MAP:
+ return tex->bytesize * 6 * tex->w * tex->h;
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ return tex->bytesize * 6 * tex->w * tex->h * tex->d;
+ default:
+ return 0;
+ }
+}
- p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
+static void gpu_texture_memory_footprint_add(GPUTexture *tex)
+{
+ memory_usage += gpu_texture_memory_footprint_compute(tex);
+}
- for (int a = 0; a < len; a++, p++, fp++)
- *p = FTOCHAR((*fp));
+static void gpu_texture_memory_footprint_remove(GPUTexture *tex)
+{
+ memory_usage -= gpu_texture_memory_footprint_compute(tex);
+}
- return pixels;
+unsigned int GPU_texture_memory_usage_get(void)
+{
+ return memory_usage;
}
-static void gpu_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
+/* -------------------------------- */
+
+static GLenum gpu_texture_get_format(
+ int components, GPUTextureFormat data_type,
+ GLenum *format, GLenum *data_format, bool *is_depth, bool *is_stencil, unsigned int *bytesize)
{
- void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
+ if (data_type == GPU_DEPTH_COMPONENT24 ||
+ data_type == GPU_DEPTH_COMPONENT16 ||
+ data_type == GPU_DEPTH_COMPONENT32F)
+ {
+ *is_depth = true;
+ *is_stencil = false;
+ *data_format = GL_FLOAT;
+ *format = GL_DEPTH_COMPONENT;
+ }
+ else if (data_type == GPU_DEPTH24_STENCIL8) {
+ *is_depth = true;
+ *is_stencil = true;
+ *data_format = GL_UNSIGNED_INT_24_8;
+ *format = GL_DEPTH_STENCIL;
+ }
+ else {
+ *is_depth = false;
+ *is_stencil = false;
+ *data_format = GL_FLOAT;
+
+ 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;
+ }
+ }
- 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 (data_type) {
+ case GPU_RGBA32F:
+ *bytesize = 32;
+ break;
+ case GPU_RG32F:
+ case GPU_RGBA16F:
+ *bytesize = 16;
+ break;
+ case GPU_RGB16F:
+ *bytesize = 12;
+ break;
+ case GPU_RG16F:
+ case GPU_DEPTH24_STENCIL8:
+ case GPU_DEPTH_COMPONENT32F:
+ case GPU_RGBA8:
+ case GPU_R11F_G11F_B10F:
+ case GPU_R32F:
+ *bytesize = 4;
+ break;
+ case GPU_DEPTH_COMPONENT24:
+ *bytesize = 3;
+ break;
+ case GPU_DEPTH_COMPONENT16:
+ case GPU_R16F:
+ case GPU_RG8:
+ *bytesize = 2;
+ break;
+ case GPU_R8:
+ *bytesize = 1;
+ break;
+ default:
+ *bytesize = 0;
+ break;
+ }
+
+ /* 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_RGBA32F: return GL_RGBA32F;
+ case GPU_RGBA16F: return GL_RGBA16F;
+ case GPU_RG32F: return GL_RG32F;
+ case GPU_RGB16F: return GL_RGB16F;
+ case GPU_RG16F: return GL_RG16F;
+ case GPU_RGBA8: return GL_RGBA8;
+ case GPU_R32F: return GL_R32F;
+ case GPU_R16F: return GL_R16F;
+ case GPU_RG8: return GL_RG8;
+ case GPU_R8: return GL_R8;
+ /* Special formats texture & renderbuffer */
+ case GPU_R11F_G11F_B10F: return GL_R11F_G11F_B10F;
+ case GPU_DEPTH24_STENCIL8: return GL_DEPTH24_STENCIL8;
+ /* 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;
+ }
}
-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])
+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");
+
+ 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;
+}
+
+/* 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, GLenum data_format,
+ int channels, bool try_rescale, const float *fpixels, float **rescaled_fpixels)
{
- GLenum type, format, internalformat;
- void *pixels = NULL;
+ int r_width;
+ switch (proxy) {
+ case GL_PROXY_TEXTURE_1D:
+ glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, data_format, NULL);
+ break;
+ case GL_PROXY_TEXTURE_1D_ARRAY:
+ case GL_PROXY_TEXTURE_2D:
+ glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, data_format, NULL);
+ break;
+ case GL_PROXY_TEXTURE_2D_ARRAY:
+ case GL_PROXY_TEXTURE_3D:
+ glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, 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, data_format, NULL);
+ else if (proxy == GL_PROXY_TEXTURE_2D)
+ glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, data_format, NULL);
+ else if (proxy == GL_PROXY_TEXTURE_3D)
+ glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, 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 d, int n, const float *fpixels,
+ GPUTextureFormat data_type, int components, int samples,
+ const bool can_rescale, char err_out[256])
+{
if (samples) {
CLAMP_MAX(samples, GPU_max_color_texture_samples());
}
@@ -106,264 +322,206 @@ 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;
tex->fb_attachment = -1;
+ tex->format = data_type;
+ tex->components = components;
+
+ 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 == 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 == 3) {
+ tex->target_base = tex->target = GL_TEXTURE_3D;
+ }
+ else {
+ /* should never happen */
+ MEM_freeN(tex);
+ return NULL;
+ }
+
+ if (samples && n == 2 && d == 0)
+ tex->target = GL_TEXTURE_2D_MULTISAMPLE;
+
+ GLenum format, internalformat, data_format;
+ internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil, &tex->bytesize);
+ gpu_texture_memory_footprint_add(tex);
+
+ /* Generate Texture object */
glGenTextures(1, &tex->bindcode);
if (!tex->bindcode) {
- if (err_out) {
- BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
- (int)glGetError());
- }
- else {
- fprintf(stderr, "GPUTexture: texture create failed: %d\n",
- (int)glGetError());
- }
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUTexture: texture create failed");
+ else
+ fprintf(stderr, "GPUTexture: texture create failed");
GPU_texture_free(tex);
return NULL;
}
- 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);
- }
-
tex->number = 0;
glBindTexture(tex->target, tex->bindcode);
- if (depth) {
- type = GL_UNSIGNED_BYTE;
- format = GL_DEPTH_COMPONENT;
- internalformat = GL_DEPTH_COMPONENT;
- }
- 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;
- }
- }
+ /* Check if texture fit in VRAM */
+ GLenum proxy = GL_PROXY_TEXTURE_2D;
- if (fpixels && hdr_type == GPU_HDR_NONE) {
- type = GL_UNSIGNED_BYTE;
- pixels = GPU_texture_convert_pixels(w * h, fpixels);
- }
+ if (n == 2) {
+ if (d > 0)
+ proxy = GL_PROXY_TEXTURE_2D_ARRAY;
+ }
+ else if (n == 1) {
+ if (h == 0)
+ proxy = GL_PROXY_TEXTURE_1D;
+ else
+ proxy = GL_PROXY_TEXTURE_1D_ARRAY;
+ }
+ else if (n == 3) {
+ proxy = GL_PROXY_TEXTURE_3D;
}
- if (tex->target == GL_TEXTURE_1D) {
- glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
+ float *rescaled_fpixels = NULL;
+ bool valid = gpu_texture_try_alloc(tex, proxy, internalformat, format, data_format, components, can_rescale,
+ fpixels, &rescaled_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 (fpixels) {
- glTexSubImage1D(tex->target, 0, 0, w, format, type,
- pixels ? pixels : fpixels);
+ /* Upload Texture */
+ const float *pix = (rescaled_fpixels) ? rescaled_fpixels : fpixels;
- if (tex->w > w) {
- gpu_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1);
- }
- }
- }
- else {
+ if (tex->target == GL_TEXTURE_2D ||
+ tex->target == GL_TEXTURE_2D_MULTISAMPLE ||
+ tex->target == GL_TEXTURE_1D_ARRAY)
+ {
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, data_format, 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, data_format, pix);
}
}
+ else if (tex->target == GL_TEXTURE_1D) {
+ glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, data_format, pix);
+ }
+ else {
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, 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);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
}
else {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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);
+ if (n > 2) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ }
+
+ GPU_texture_unbind(tex);
return tex;
}
-
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
+static GPUTexture *GPU_texture_cube_create(
+ int w, int d,
+ const float *fpixels_px, const float *fpixels_py, const float *fpixels_pz,
+ const float *fpixels_nx, const float *fpixels_ny, const float *fpixels_nz,
+ GPUTextureFormat data_type, int components,
+ char err_out[256])
{
- GLenum type, format, internalformat;
- void *pixels = NULL;
+ GLenum format, internalformat, data_format;
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
tex->w = w;
- tex->h = h;
- tex->depth = depth;
+ tex->h = w;
+ tex->d = d;
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: %d\n",
- (int)glGetError());
- GPU_texture_free(tex);
- return NULL;
- }
-
- tex->number = 0;
- glBindTexture(tex->target, tex->bindcode);
-
- GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
+ tex->fb_attachment = -1;
+ tex->format = data_type;
+ tex->components = components;
- type = GL_FLOAT;
- if (channels == 4) {
- format = GL_RGBA;
- internalformat = GL_RGBA8;
+ if (d == 0) {
+ tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP;
}
else {
- format = GL_RED;
- internalformat = GL_INTENSITY8;
+ BLI_assert(false && "Cubemap array Not implemented yet");
+ // tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY;
}
- /* 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);
+ internalformat = gpu_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil, &tex->bytesize);
- bool rescale = false;
- int r_width;
+ gpu_texture_memory_footprint_add(tex);
- glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+ /* Generate Texture object */
+ glGenTextures(1, &tex->bindcode);
- 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);
+ if (!tex->bindcode) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUTexture: texture create failed");
+ else
+ fprintf(stderr, "GPUTexture: texture create failed");
+ GPU_texture_free(tex);
+ return NULL;
}
- /* 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
-
- GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
-
- /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
- * for gooseberry */
- if (rescale && fpixels) {
- /* 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];
- }
- }
- }
+ tex->number = 0;
+ glBindTexture(tex->target, tex->bindcode);
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
+ /* Upload Texture */
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_px);
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_py);
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_pz);
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_nx);
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_ny);
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_nz);
- MEM_freeN(tex3d);
+ /* 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_NONE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
}
else {
- if (fpixels) {
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
- GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
- }
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
-
- 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);
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
GPU_texture_unbind(tex);
@@ -380,6 +538,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
/* see GPUInput::textarget: it can take two values - GL_TEXTURE_2D and GL_TEXTURE_CUBE_MAP
* these values are correct for glDisable, so textarget can be safely used in
* GPU_texture_bind/GPU_texture_unbind through tex->target_base */
+ /* (is any of this obsolete now that we don't glEnable/Disable textures?) */
if (textarget == GL_TEXTURE_2D)
gputt = TEXTARGET_TEXTURE_2D;
else
@@ -398,14 +557,16 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
tex->target = textarget;
tex->target_base = textarget;
tex->fromblender = 1;
+ tex->format = -1;
+ tex->components = -1;
ima->gputexture[gputt] = tex;
if (!glIsTexture(tex->bindcode)) {
- GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
+ GPU_print_error_debug("Blender Texture Not Loaded");
}
else {
- GLint w, h, border;
+ GLint w, h;
GLenum gettarget;
@@ -417,10 +578,8 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
glBindTexture(textarget, tex->bindcode);
glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_HEIGHT, &h);
- glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_BORDER, &border);
-
- tex->w = w - border;
- tex->h = h - border;
+ tex->w = w;
+ tex->h = h;
}
glBindTexture(textarget, 0);
@@ -452,11 +611,13 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
tex->refcount = 1;
tex->target = GL_TEXTURE_2D;
tex->target_base = GL_TEXTURE_2D;
+ tex->format = -1;
+ tex->components = -1;
prv->gputexture[0] = tex;
if (!glIsTexture(tex->bindcode)) {
- GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
+ GPU_print_error_debug("Blender Texture Not Loaded");
}
else {
GLint w, h;
@@ -475,114 +636,123 @@ 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_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(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
+ return GPU_texture_create_nD(w, h, d, 2, pixels, data_type, channels, 0, false, 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);
+GPUTexture *GPU_texture_create_3D(int w, int h, int d, const float *pixels, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, d, 3, pixels, GPU_RGBA8, 4, 0, true, err_out);
+}
- GPU_texture_unbind(tex);
+GPUTexture *GPU_texture_create_3D_custom(int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, d, 3, pixels, data_type, channels, 0, true, err_out);
+}
+GPUTexture *GPU_texture_create_cube_custom(int w, int channels, GPUTextureFormat data_type, const float *fpixels, char err_out[256])
+{
+ const float *fpixels_px, *fpixels_py, *fpixels_pz, *fpixels_nx, *fpixels_ny, *fpixels_nz;
+
+ if (fpixels) {
+ fpixels_px = fpixels + 0 * w * w * channels;
+ fpixels_nx = fpixels + 1 * w * w * channels;
+ fpixels_py = fpixels + 2 * w * w * channels;
+ fpixels_ny = fpixels + 3 * w * w * channels;
+ fpixels_pz = fpixels + 4 * w * w * channels;
+ fpixels_nz = fpixels + 5 * w * w * channels;
+ }
+ else {
+ fpixels_px = fpixels_py = fpixels_pz = fpixels_nx = fpixels_ny = fpixels_nz = NULL;
}
- return tex;
+ return GPU_texture_cube_create(w, 0, fpixels_px, fpixels_py, fpixels_pz, fpixels_nx, fpixels_ny, fpixels_nz, data_type, channels, 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_depth(int w, int h, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
+ return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH_COMPONENT24, 1, 0, false, 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);
+GPUTexture *GPU_texture_create_depth_with_stencil(int w, int h, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH24_STENCIL8, 1, 0, false, err_out);
+}
- GPU_texture_unbind(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);
+}
- return tex;
+GPUTexture *GPU_texture_create_depth_with_stencil_multisample(int w, int h, int samples, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH24_STENCIL8, 1, samples, false, err_out);
}
-GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
+void GPU_texture_update(GPUTexture *tex, const float *pixels)
{
- GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
+ BLI_assert(tex->format > -1);
+ BLI_assert(tex->components > -1);
- 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);
+ GLenum format, data_format;
+ gpu_texture_get_format(tex->components, tex->format, &format, &data_format, &tex->depth, &tex->stencil, &tex->bytesize);
+
+ glBindTexture(tex->target, tex->bindcode);
- GPU_texture_unbind(tex);
+ switch (tex->target) {
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_1D_ARRAY:
+ glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, data_format, pixels);
+ break;
+ case GL_TEXTURE_1D:
+ glTexSubImage1D(tex->target, 0, 0, tex->w, format, data_format, pixels);
+ break;
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->d, format, data_format, pixels);
+ break;
+ default:
+ BLI_assert(!"tex->target mode not supported");
}
- return tex;
+ glBindTexture(tex->target, 0);
}
void GPU_invalid_tex_init(void)
{
+ memory_usage = 0;
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)
@@ -627,21 +797,18 @@ void GPU_texture_bind(GPUTexture *tex, int number)
if (number < 0)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
+ if (number != 0)
+ glActiveTexture(GL_TEXTURE0 + number);
- GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
- if (number != 0) glActiveTexture(arbnumber);
- if (tex->bindcode != 0) {
- glBindTexture(tex->target_base, tex->bindcode);
- }
+ if (tex->bindcode != 0)
+ glBindTexture(tex->target, tex->bindcode);
else
GPU_invalid_tex_bind(tex->target_base);
- glEnable(tex->target_base);
- if (number != 0) glActiveTexture(GL_TEXTURE0);
- tex->number = number;
+ if (number != 0)
+ glActiveTexture(GL_TEXTURE0);
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
+ tex->number = number;
}
void GPU_texture_unbind(GPUTexture *tex)
@@ -653,18 +820,16 @@ void GPU_texture_unbind(GPUTexture *tex)
if (tex->number == -1)
return;
-
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
- GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
- if (tex->number != 0) glActiveTexture(arbnumber);
- glBindTexture(tex->target_base, 0);
- glDisable(tex->target_base);
- if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0 + tex->number);
- tex->number = -1;
+ glBindTexture(tex->target, 0);
+
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0);
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
+ tex->number = -1;
}
int GPU_texture_bound_number(GPUTexture *tex)
@@ -672,7 +837,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_generate_mipmap(GPUTexture *tex)
{
if (tex->number >= GPU_max_textures()) {
fprintf(stderr, "Not enough texture slots.\n");
@@ -682,29 +847,104 @@ void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
if (tex->number == -1)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0 + tex->number);
- GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
- if (tex->number != 0) glActiveTexture(arbnumber);
+ glGenerateMipmap(tex->target_base);
- if (tex->depth) {
- if (compare)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
- else
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0);
+}
+
+void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
+{
+ if (tex->number >= GPU_max_textures()) {
+ fprintf(stderr, "Not enough texture slots.\n");
+ return;
}
- if (use_filter) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ if (tex->number == -1)
+ return;
+
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+
+ /* 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;
}
- else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ if (tex->number == -1)
+ return;
+
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+
+ GLenum filter = use_filter ? GL_LINEAR : GL_NEAREST;
+ 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_mipmap_mode(GPUTexture *tex, bool use_mipmap, 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 mipmap = (use_filter)
+ ? use_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR
+ : use_mipmap ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST;
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap);
+
+ GLenum filter = use_filter ? GL_LINEAR : GL_NEAREST;
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_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 != 0) glActiveTexture(GL_TEXTURE0);
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
+ 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);
}
void GPU_texture_free(GPUTexture *tex)
@@ -720,6 +960,8 @@ void GPU_texture_free(GPUTexture *tex)
if (tex->bindcode && !tex->fromblender)
glDeleteTextures(1, &tex->bindcode);
+ gpu_texture_memory_footprint_remove(tex);
+
MEM_freeN(tex);
}
}
@@ -744,11 +986,21 @@ int GPU_texture_height(const GPUTexture *tex)
return tex->h;
}
-int GPU_texture_depth(const GPUTexture *tex)
+int GPU_texture_format(const GPUTexture *tex)
+{
+ return tex->format;
+}
+
+bool GPU_texture_depth(const GPUTexture *tex)
{
return tex->depth;
}
+bool GPU_texture_stencil(const GPUTexture *tex)
+{
+ return tex->stencil;
+}
+
int GPU_texture_opengl_bindcode(const GPUTexture *tex)
{
return tex->bindcode;
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c
new file mode 100644
index 00000000000..6d52dab5a1f
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_uniformbuffer.c
@@ -0,0 +1,378 @@
+/*
+ * ***** 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 <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "gpu_codegen.h"
+
+#include "GPU_extensions.h"
+#include "GPU_glew.h"
+#include "GPU_material.h"
+#include "GPU_uniformbuffer.h"
+
+typedef enum GPUUniformBufferFlag {
+ GPU_UBO_FLAG_INITIALIZED = (1 << 0),
+ GPU_UBO_FLAG_DIRTY = (1 << 1),
+} GPUUniformBufferFlag;
+
+typedef enum GPUUniformBufferType {
+ GPU_UBO_STATIC = 0,
+ GPU_UBO_DYNAMIC = 1,
+} GPUUniformBufferType;
+
+struct GPUUniformBuffer {
+ int size; /* in bytes */
+ GLuint bindcode; /* opengl identifier for UBO */
+ int bindpoint; /* current binding point */
+ GPUUniformBufferType type;
+};
+
+#define GPUUniformBufferStatic GPUUniformBuffer
+
+typedef struct GPUUniformBufferDynamic {
+ GPUUniformBuffer buffer;
+ ListBase items; /* GPUUniformBufferDynamicItem */
+ void *data;
+ char flag;
+} GPUUniformBufferDynamic;
+
+struct GPUUniformBufferDynamicItem {
+ struct GPUUniformBufferDynamicItem *next, *prev;
+ GPUType gputype;
+ float *data;
+ int size;
+};
+
+
+/* Prototypes */
+static GPUType get_padded_gpu_type(struct LinkData *link);
+static void gpu_uniformbuffer_inputs_sort(struct ListBase *inputs);
+
+static GPUUniformBufferDynamicItem *gpu_uniformbuffer_populate(
+ GPUUniformBufferDynamic *ubo, const GPUType gputype, float *num);
+
+/* Only support up to this type, if you want to extend it, make sure the
+ * padding logic is correct for the new types. */
+#define MAX_UBO_GPU_TYPE GPU_VEC4
+
+static void gpu_uniformbuffer_initialize(GPUUniformBuffer *ubo, const void *data)
+{
+ glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode);
+ glBufferData(GL_UNIFORM_BUFFER, ubo->size, data, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+}
+
+GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256])
+{
+ GPUUniformBuffer *ubo = MEM_callocN(sizeof(GPUUniformBufferStatic), "GPUUniformBufferStatic");
+ ubo->size = size;
+ ubo->bindpoint = -1;
+
+ /* 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;
+ }
+
+ gpu_uniformbuffer_initialize(ubo, data);
+ return ubo;
+}
+
+/**
+ * Create dynamic UBO from parameters
+ * Return NULL if failed to create or if \param inputs is empty.
+ *
+ * \param inputs ListBase of BLI_genericNodeN(GPUInput)
+ */
+GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_out[256])
+{
+ /* There is no point on creating an UBO if there is no arguments. */
+ if (BLI_listbase_is_empty(inputs)) {
+ return NULL;
+ }
+
+ GPUUniformBufferDynamic *ubo = MEM_callocN(sizeof(GPUUniformBufferDynamic), "GPUUniformBufferDynamic");
+ ubo->buffer.type = GPU_UBO_DYNAMIC;
+ ubo->buffer.bindpoint = -1;
+ ubo->flag = GPU_UBO_FLAG_DIRTY;
+
+ /* Generate Buffer object. */
+ glGenBuffers(1, &ubo->buffer.bindcode);
+
+ if (!ubo->buffer.bindcode) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO create failed");
+ GPU_uniformbuffer_free(&ubo->buffer);
+ return NULL;
+ }
+
+ if (ubo->buffer.size > GPU_max_ubo_size()) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO too big");
+ GPU_uniformbuffer_free(&ubo->buffer);
+ return NULL;
+ }
+
+ /* Make sure we comply to the ubo alignment requirements. */
+ gpu_uniformbuffer_inputs_sort(inputs);
+
+ for (LinkData *link = inputs->first; link; link = link->next) {
+ GPUInput *input = link->data;
+ GPUType gputype = get_padded_gpu_type(link);
+ gpu_uniformbuffer_populate(ubo, gputype, input->dynamicvec);
+ }
+
+ ubo->data = MEM_mallocN(ubo->buffer.size, __func__);
+
+ /* Initialize buffer data. */
+ GPU_uniformbuffer_dynamic_update(&ubo->buffer);
+ return &ubo->buffer;
+}
+
+/**
+ * Free the data, and clean the items list.
+ */
+static void gpu_uniformbuffer_dynamic_reset(GPUUniformBufferDynamic *ubo)
+{
+ ubo->buffer.size = 0;
+ if (ubo->data) {
+ MEM_freeN(ubo->data);
+ }
+ BLI_freelistN(&ubo->items);
+}
+
+void GPU_uniformbuffer_free(GPUUniformBuffer *ubo)
+{
+ if (ubo->type == GPU_UBO_DYNAMIC) {
+ gpu_uniformbuffer_dynamic_reset((GPUUniformBufferDynamic *)ubo);
+ }
+
+ glDeleteBuffers(1, &ubo->bindcode);
+ MEM_freeN(ubo);
+}
+
+static 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_update(GPUUniformBuffer *ubo, const void *data)
+{
+ BLI_assert(ubo->type == GPU_UBO_STATIC);
+ gpu_uniformbuffer_update(ubo, data);
+}
+
+/**
+ * We need to recalculate the internal data, and re-generate it
+ * from its populated items.
+ */
+void GPU_uniformbuffer_dynamic_update(GPUUniformBuffer *ubo_)
+{
+ BLI_assert(ubo_->type == GPU_UBO_DYNAMIC);
+ GPUUniformBufferDynamic *ubo = (GPUUniformBufferDynamic *)ubo_;
+
+ float *offset = ubo->data;
+ for (GPUUniformBufferDynamicItem *item = ubo->items.first; item; item = item->next) {
+ memcpy(offset, item->data, item->size);
+ offset += item->gputype;
+ }
+
+ if (ubo->flag & GPU_UBO_FLAG_INITIALIZED) {
+ gpu_uniformbuffer_update(ubo_, ubo->data);
+ }
+ else {
+ ubo->flag |= GPU_UBO_FLAG_INITIALIZED;
+ gpu_uniformbuffer_initialize(ubo_, ubo->data);
+ }
+
+ ubo->flag &= ~GPU_UBO_FLAG_DIRTY;
+}
+
+/**
+ * We need to pad some data types (vec3) on the C side
+ * To match the GPU expected memory block alignment.
+ */
+static GPUType get_padded_gpu_type(LinkData *link)
+{
+ GPUInput *input = link->data;
+ GPUType gputype = input->type;
+
+ /* Unless the vec3 is followed by a float we need to treat it as a vec4. */
+ if (gputype == GPU_VEC3 &&
+ (link->next != NULL) &&
+ (((GPUInput *)link->next->data)->type != GPU_FLOAT))
+ {
+ gputype = GPU_VEC4;
+ }
+
+ return gputype;
+}
+
+/**
+ * Returns 1 if the first item shold be after second item.
+ * We make sure the vec4 uniforms come first.
+ */
+static int inputs_cmp(const void *a, const void *b)
+{
+ const LinkData *link_a = a, *link_b = b;
+ const GPUInput *input_a = link_a->data, *input_b = link_b->data;
+ return input_a->type < input_b->type ? 1 : 0;
+}
+
+/**
+ * Make sure we respect the expected alignment of UBOs.
+ * vec4, pad vec3 as vec4, then vec2, then floats.
+ */
+static void gpu_uniformbuffer_inputs_sort(ListBase *inputs)
+{
+ /* Order them as vec4, vec3, vec2, float. */
+ BLI_listbase_sort(inputs, inputs_cmp);
+
+ /* Creates a lookup table for the different types; */
+ LinkData *inputs_lookup[MAX_UBO_GPU_TYPE + 1] = {NULL};
+ GPUType cur_type = MAX_UBO_GPU_TYPE + 1;
+
+ for (LinkData *link = inputs->first; link; link = link->next) {
+ GPUInput *input = link->data;
+ if (input->type == cur_type) {
+ continue;
+ }
+ else {
+ inputs_lookup[input->type] = link;
+ cur_type = input->type;
+ }
+ }
+
+ /* If there is no GPU_VEC3 there is no need for alignment. */
+ if (inputs_lookup[GPU_VEC3] == NULL) {
+ return;
+ }
+
+ LinkData *link = inputs_lookup[GPU_VEC3];
+ while (link != NULL && ((GPUInput *)link->data)->type == GPU_VEC3) {
+ LinkData *link_next = link->next;
+
+ /* If GPU_VEC3 is followed by nothing or a GPU_FLOAT, no need for aligment. */
+ if ((link_next == NULL) ||
+ ((GPUInput *)link_next->data)->type == GPU_FLOAT)
+ {
+ break;
+ }
+
+ /* If there is a float, move it next to current vec3. */
+ if (inputs_lookup[GPU_FLOAT] != NULL) {
+ LinkData *float_input = inputs_lookup[GPU_FLOAT];
+ inputs_lookup[GPU_FLOAT] = float_input->next;
+
+ BLI_remlink(inputs, float_input);
+ BLI_insertlinkafter(inputs, link, float_input);
+ }
+
+ link = link_next;
+ }
+}
+
+/**
+ * This may now happen from the main thread, so we can't update the UBO
+ * We simply flag it as dirty
+ */
+static GPUUniformBufferDynamicItem *gpu_uniformbuffer_populate(
+ GPUUniformBufferDynamic *ubo, const GPUType gputype, float *num)
+{
+ BLI_assert(gputype <= MAX_UBO_GPU_TYPE);
+ GPUUniformBufferDynamicItem *item = MEM_callocN(sizeof(GPUUniformBufferDynamicItem), __func__);
+
+ item->gputype = gputype;
+ item->data = num;
+ item->size = gputype * sizeof(float);
+ ubo->buffer.size += item->size;
+
+ ubo->flag |= GPU_UBO_FLAG_DIRTY;
+ BLI_addtail(&ubo->items, item);
+
+ return item;
+}
+
+void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number)
+{
+ if (number >= GPU_max_ubo_binds()) {
+ fprintf(stderr, "Not enough UBO slots.\n");
+ return;
+ }
+
+ if (ubo->type == GPU_UBO_DYNAMIC) {
+ GPUUniformBufferDynamic *ubo_dynamic = (GPUUniformBufferDynamic *)ubo;
+ if (ubo_dynamic->flag & GPU_UBO_FLAG_DIRTY) {
+ GPU_uniformbuffer_dynamic_update(ubo);
+ }
+ }
+
+ if (ubo->bindcode != 0) {
+ glBindBufferBase(GL_UNIFORM_BUFFER, number, ubo->bindcode);
+ }
+
+ ubo->bindpoint = number;
+}
+
+void GPU_uniformbuffer_unbind(GPUUniformBuffer *ubo)
+{
+ ubo->bindpoint = -1;
+}
+
+int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo)
+{
+ return ubo->bindpoint;
+}
+
+void GPU_uniformbuffer_tag_dirty(GPUUniformBuffer *ubo_)
+{
+ BLI_assert(ubo_->type == GPU_UBO_DYNAMIC);
+ GPUUniformBufferDynamic *ubo = (GPUUniformBufferDynamic *)ubo_;
+ ubo->flag |= GPU_UBO_FLAG_DIRTY;
+}
+
+#undef MAX_UBO_GPU_TYPE
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
new file mode 100644
index 00000000000..bd563a36f57
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -0,0 +1,682 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_viewport.c
+ * \ingroup gpu
+ *
+ * System that manages viewport drawing.
+ */
+
+#include <string.h>
+
+#include "BLI_listbase.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
+#include "BLI_mempool.h"
+
+#include "DNA_vec_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_global.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_glew.h"
+#include "GPU_immediate.h"
+#include "GPU_texture.h"
+#include "GPU_viewport.h"
+
+#include "DRW_engine.h"
+
+#include "MEM_guardedalloc.h"
+
+static const int default_fbl_len = (sizeof(DefaultFramebufferList)) / sizeof(void *);
+static const int default_txl_len = (sizeof(DefaultTextureList)) / sizeof(void *);
+
+/* Maximum number of simultaneous engine enabled at the same time.
+ * Setting it lower than the real number will do lead to
+ * higher VRAM usage due to sub-efficient buffer reuse. */
+#define MAX_ENGINE_BUFFER_SHARING 5
+
+typedef struct ViewportTempTexture {
+ struct ViewportTempTexture *next, *prev;
+ void *user[MAX_ENGINE_BUFFER_SHARING];
+ GPUTexture *texture;
+} ViewportTempTexture;
+
+struct GPUViewport {
+ float pad[4];
+
+ /* debug */
+ GPUTexture *debug_depth;
+ int size[2];
+
+ int samples;
+ int flag;
+
+ ListBase data; /* ViewportEngineData wrapped in LinkData */
+ unsigned int data_hash; /* If hash mismatch we free all ViewportEngineData in this viewport */
+
+ DefaultFramebufferList *fbl;
+ DefaultTextureList *txl;
+
+ ViewportMemoryPool vmempool; /* Used for rendering data structure. */
+
+ ListBase tex_pool; /* ViewportTempTexture list : Temporary textures shared across draw engines */
+};
+
+enum {
+ DO_UPDATE = (1 << 0),
+};
+
+static void gpu_viewport_buffers_free(FramebufferList *fbl, int fbl_len, TextureList *txl, int txl_len);
+static void gpu_viewport_storage_free(StorageList *stl, int stl_len);
+static void gpu_viewport_passes_free(PassList *psl, int psl_len);
+static void gpu_viewport_texture_pool_free(GPUViewport *viewport);
+
+void GPU_viewport_tag_update(GPUViewport *viewport)
+{
+ viewport->flag |= DO_UPDATE;
+}
+
+bool GPU_viewport_do_update(GPUViewport *viewport)
+{
+ bool ret = (viewport->flag & DO_UPDATE);
+ viewport->flag &= ~DO_UPDATE;
+ return ret;
+}
+
+GPUViewport *GPU_viewport_create(void)
+{
+ GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport");
+ viewport->fbl = MEM_callocN(sizeof(DefaultFramebufferList), "FramebufferList");
+ viewport->txl = MEM_callocN(sizeof(DefaultTextureList), "TextureList");
+
+ viewport->size[0] = viewport->size[1] = -1;
+
+ return viewport;
+}
+
+GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs)
+{
+ GPUViewport *viewport = GPU_viewport_create();
+ GPU_offscreen_viewport_data_get(ofs, &viewport->fbl->default_fb, &viewport->txl->color, &viewport->txl->depth);
+ viewport->size[0] = GPU_offscreen_width(ofs);
+ viewport->size[1] = GPU_offscreen_height(ofs);
+ return viewport;
+}
+/**
+ * Clear vars assigned from offscreen, so we don't free data owned by `GPUOffScreen`.
+ */
+void GPU_viewport_clear_from_offscreen(GPUViewport *viewport)
+{
+ viewport->fbl->default_fb = NULL;
+ viewport->txl->color = NULL;
+ viewport->txl->depth = NULL;
+}
+
+void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type)
+{
+ LinkData *ld = MEM_callocN(sizeof(LinkData), "LinkData");
+ ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData");
+ int fbl_len, txl_len, psl_len, stl_len;
+
+ DRW_engine_viewport_data_size_get(engine_type, &fbl_len, &txl_len, &psl_len, &stl_len);
+
+ data->engine_type = engine_type;
+
+ data->fbl = MEM_callocN((sizeof(void *) * fbl_len) + sizeof(FramebufferList), "FramebufferList");
+ data->txl = MEM_callocN((sizeof(void *) * txl_len) + sizeof(TextureList), "TextureList");
+ data->psl = MEM_callocN((sizeof(void *) * psl_len) + sizeof(PassList), "PassList");
+ data->stl = MEM_callocN((sizeof(void *) * stl_len) + sizeof(StorageList), "StorageList");
+
+ ld->data = data;
+ BLI_addtail(&viewport->data, ld);
+
+ return data;
+}
+
+static void gpu_viewport_engines_data_free(GPUViewport *viewport)
+{
+ int fbl_len, txl_len, psl_len, stl_len;
+
+ LinkData *next;
+ for (LinkData *link = viewport->data.first; link; link = next) {
+ next = link->next;
+ ViewportEngineData *data = link->data;
+ DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, &psl_len, &stl_len);
+
+ gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
+ gpu_viewport_passes_free(data->psl, psl_len);
+ gpu_viewport_storage_free(data->stl, stl_len);
+
+ MEM_freeN(data->fbl);
+ MEM_freeN(data->txl);
+ MEM_freeN(data->psl);
+ MEM_freeN(data->stl);
+
+ /* We could handle this in the DRW module */
+ if (data->text_draw_cache) {
+ extern void DRW_text_cache_destroy(struct DRWTextStore *dt);
+ DRW_text_cache_destroy(data->text_draw_cache);
+ data->text_draw_cache = NULL;
+ }
+
+ MEM_freeN(data);
+
+ BLI_remlink(&viewport->data, link);
+ MEM_freeN(link);
+ }
+
+ gpu_viewport_texture_pool_free(viewport);
+}
+
+void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type)
+{
+ for (LinkData *link = viewport->data.first; link; link = link->next) {
+ ViewportEngineData *vdata = link->data;
+ if (vdata->engine_type == engine_type) {
+ return vdata;
+ }
+ }
+ return NULL;
+}
+
+ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport)
+{
+ return &viewport->vmempool;
+}
+
+void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport)
+{
+ return viewport->fbl;
+}
+
+void *GPU_viewport_texture_list_get(GPUViewport *viewport)
+{
+ return viewport->txl;
+}
+
+void GPU_viewport_size_get(const GPUViewport *viewport, int size[2])
+{
+ size[0] = viewport->size[0];
+ size[1] = viewport->size[1];
+}
+
+/**
+ * Special case, this is needed for when we have a viewport without a frame-buffer output
+ * (occlusion queries for eg) but still need to set the size since it may be used for other calculations.
+ */
+void GPU_viewport_size_set(GPUViewport *viewport, const int size[2])
+{
+ viewport->size[0] = size[0];
+ viewport->size[1] = size[1];
+}
+
+/**
+ * Try to find a texture coresponding to params into the texture pool.
+ * If no texture was found, create one and add it to the pool.
+ */
+GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine, int width, int height, int channels, int format)
+{
+ GPUTexture *tex;
+
+ for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) {
+ if ((GPU_texture_width(tmp_tex->texture) == width) &&
+ (GPU_texture_height(tmp_tex->texture) == height) &&
+ (GPU_texture_format(tmp_tex->texture) == format))
+ {
+ /* Search if the engine is not already using this texture */
+ for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; ++i) {
+ if (tmp_tex->user[i] == engine) {
+ break;
+ }
+
+ if (tmp_tex->user[i] == NULL) {
+ tmp_tex->user[i] = engine;
+ return tmp_tex->texture;
+ }
+ }
+ }
+ }
+
+ tex = GPU_texture_create_2D_custom(width, height, channels, format, NULL, NULL);
+
+ ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture");
+ tmp_tex->texture = tex;
+ tmp_tex->user[0] = engine;
+
+ BLI_addtail(&viewport->tex_pool, tmp_tex);
+
+ return tex;
+}
+
+static void gpu_viewport_texture_pool_clear_users(GPUViewport *viewport)
+{
+ ViewportTempTexture *tmp_tex_next;
+
+ for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex_next) {
+ tmp_tex_next = tmp_tex->next;
+ bool no_user = true;
+ for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; ++i) {
+ if (tmp_tex->user[i] != NULL) {
+ tmp_tex->user[i] = NULL;
+ no_user = false;
+ }
+ }
+
+ if (no_user) {
+ GPU_texture_free(tmp_tex->texture);
+ BLI_freelinkN(&viewport->tex_pool, tmp_tex);
+ }
+ }
+}
+
+static void gpu_viewport_texture_pool_free(GPUViewport *viewport)
+{
+ for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) {
+ GPU_texture_free(tmp_tex->texture);
+ }
+
+ BLI_freelistN(&viewport->tex_pool);
+}
+
+bool GPU_viewport_engines_data_validate(GPUViewport *viewport, unsigned int hash)
+{
+ bool dirty = false;
+
+ if (viewport->data_hash != hash) {
+ gpu_viewport_engines_data_free(viewport);
+ dirty = true;
+ }
+
+ viewport->data_hash = hash;
+
+ return dirty;
+}
+
+void GPU_viewport_cache_release(GPUViewport *viewport)
+{
+ for (LinkData *link = viewport->data.first; link; link = link->next) {
+ ViewportEngineData *data = link->data;
+ int psl_len;
+ DRW_engine_viewport_data_size_get(data->engine_type, NULL, NULL, &psl_len, NULL);
+ gpu_viewport_passes_free(data->psl, psl_len);
+ }
+}
+
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+ DefaultTextureList *dtxl = viewport->txl;
+ int fbl_len, txl_len;
+
+ /* add one pixel because of scissor test */
+ int rect_w = BLI_rcti_size_x(rect) + 1;
+ int rect_h = BLI_rcti_size_y(rect) + 1;
+
+ if (dfbl->default_fb) {
+ if (rect_w != viewport->size[0] || rect_h != viewport->size[1] || U.ogl_multisamples != viewport->samples) {
+ gpu_viewport_buffers_free(
+ (FramebufferList *)viewport->fbl, default_fbl_len,
+ (TextureList *)viewport->txl, default_txl_len);
+
+ for (LinkData *link = viewport->data.first; link; link = link->next) {
+ ViewportEngineData *data = link->data;
+ DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, NULL, NULL);
+ gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
+ }
+
+ gpu_viewport_texture_pool_free(viewport);
+ }
+ }
+
+ gpu_viewport_texture_pool_clear_users(viewport);
+
+ /* Multisample Buffer */
+ if (U.ogl_multisamples > 0) {
+ if (!dfbl->default_fb) {
+ bool ok = true;
+ viewport->samples = U.ogl_multisamples;
+
+ dfbl->multisample_fb = GPU_framebuffer_create();
+ if (!dfbl->multisample_fb) {
+ ok = false;
+ goto cleanup_multisample;
+ }
+
+ /* Color */
+ dtxl->multisample_color = GPU_texture_create_2D_multisample(rect_w, rect_h, NULL, U.ogl_multisamples, NULL);
+ if (!dtxl->multisample_color) {
+ ok = false;
+ goto cleanup_multisample;
+ }
+
+ if (!GPU_framebuffer_texture_attach(dfbl->multisample_fb, dtxl->multisample_color, 0, 0)) {
+ ok = false;
+ goto cleanup_multisample;
+ }
+
+ /* Depth */
+ dtxl->multisample_depth = GPU_texture_create_depth_with_stencil_multisample(rect_w, rect_h,
+ U.ogl_multisamples, NULL);
+
+ if (!dtxl->multisample_depth) {
+ ok = false;
+ goto cleanup_multisample;
+ }
+
+ if (!GPU_framebuffer_texture_attach(dfbl->multisample_fb, dtxl->multisample_depth, 0, 0)) {
+ ok = false;
+ goto cleanup_multisample;
+ }
+ else if (!GPU_framebuffer_check_valid(dfbl->multisample_fb, NULL)) {
+ ok = false;
+ goto cleanup_multisample;
+ }
+
+cleanup_multisample:
+ if (!ok) {
+ GPU_viewport_free(viewport);
+ MEM_freeN(viewport);
+ return;
+ }
+ }
+ }
+
+ if (!dfbl->default_fb) {
+ bool ok = true;
+ viewport->size[0] = rect_w;
+ viewport->size[1] = rect_h;
+
+ dfbl->default_fb = GPU_framebuffer_create();
+ if (!dfbl->default_fb) {
+ ok = false;
+ goto cleanup;
+ }
+
+ /* Color */
+ dtxl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL);
+ if (!dtxl->color) {
+ ok = false;
+ goto cleanup;
+ }
+
+ if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->color, 0, 0)) {
+ ok = false;
+ goto cleanup;
+ }
+
+ /* Depth */
+ dtxl->depth = GPU_texture_create_depth_with_stencil(rect_w, rect_h, NULL);
+
+ if (dtxl->depth) {
+ /* Define texture parameters */
+ GPU_texture_bind(dtxl->depth, 0);
+ GPU_texture_compare_mode(dtxl->depth, false);
+ GPU_texture_filter_mode(dtxl->depth, true);
+ GPU_texture_unbind(dtxl->depth);
+ }
+ else {
+ ok = false;
+ goto cleanup;
+ }
+
+ if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0)) {
+ ok = false;
+ goto cleanup;
+ }
+ else if (!GPU_framebuffer_check_valid(dfbl->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(dfbl->default_fb, 0);
+}
+
+static void draw_ofs_to_screen(GPUViewport *viewport)
+{
+ DefaultTextureList *dtxl = viewport->txl;
+
+ GPUTexture *color = dtxl->color;
+
+ const float w = (float)GPU_texture_width(color);
+ const float h = (float)GPU_texture_height(color);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
+ GPU_texture_bind(color, 0);
+
+ immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
+
+ immBegin(GWN_PRIM_TRI_STRIP, 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, 0.0f, 1.0f);
+ immVertex2f(pos, 0.0f, h);
+
+ immAttrib2f(texcoord, 1.0f, 1.0f);
+ immVertex2f(pos, w, h);
+
+ immEnd();
+
+ GPU_texture_unbind(color);
+
+ immUnbindProgram();
+}
+
+void GPU_viewport_unbind(GPUViewport *viewport)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+
+ if (dfbl->default_fb) {
+ GPU_framebuffer_texture_unbind(NULL, NULL);
+ GPU_framebuffer_restore();
+
+ glEnable(GL_SCISSOR_TEST);
+ glDisable(GL_DEPTH_TEST);
+
+ /* This might be bandwidth limiting */
+ draw_ofs_to_screen(viewport);
+ }
+}
+
+static void gpu_viewport_buffers_free(
+ FramebufferList *fbl, int fbl_len,
+ TextureList *txl, int txl_len)
+{
+ for (int i = 0; i < fbl_len; i++) {
+ GPUFrameBuffer *fb = fbl->framebuffers[i];
+ if (fb) {
+ GPU_framebuffer_free(fb);
+ fbl->framebuffers[i] = NULL;
+ }
+ }
+ for (int i = 0; i < txl_len; i++) {
+ GPUTexture *tex = txl->textures[i];
+ if (tex) {
+ GPU_texture_free(tex);
+ txl->textures[i] = NULL;
+ }
+ }
+}
+
+static void gpu_viewport_storage_free(StorageList *stl, int stl_len)
+{
+ for (int i = 0; i < stl_len; i++) {
+ void *storage = stl->storage[i];
+ if (storage) {
+ MEM_freeN(storage);
+ stl->storage[i] = NULL;
+ }
+ }
+}
+
+static void gpu_viewport_passes_free(PassList *psl, int psl_len)
+{
+ for (int i = 0; i < psl_len; i++) {
+ struct DRWPass *pass = psl->passes[i];
+ if (pass) {
+ DRW_pass_free(pass);
+ psl->passes[i] = NULL;
+ }
+ }
+}
+
+void GPU_viewport_free(GPUViewport *viewport)
+{
+ gpu_viewport_engines_data_free(viewport);
+
+ gpu_viewport_buffers_free(
+ (FramebufferList *)viewport->fbl, default_fbl_len,
+ (TextureList *)viewport->txl, default_txl_len);
+
+ gpu_viewport_texture_pool_free(viewport);
+
+ MEM_freeN(viewport->fbl);
+ MEM_freeN(viewport->txl);
+
+ if (viewport->vmempool.calls != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.calls);
+ }
+ if (viewport->vmempool.calls_generate != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.calls_generate);
+ }
+ if (viewport->vmempool.calls_dynamic != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.calls_dynamic);
+ }
+ if (viewport->vmempool.shgroups != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.shgroups);
+ }
+ if (viewport->vmempool.uniforms != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.uniforms);
+ }
+ if (viewport->vmempool.attribs != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.attribs);
+ }
+ if (viewport->vmempool.passes != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.passes);
+ }
+
+ GPU_viewport_debug_depth_free(viewport);
+}
+
+/****************** debug ********************/
+
+bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256])
+{
+ viewport->debug_depth = GPU_texture_create_2D_custom(width, height, 4, GPU_RGBA16F, NULL, err_out);
+ return (viewport->debug_depth != NULL);
+}
+
+void GPU_viewport_debug_depth_free(GPUViewport *viewport)
+{
+ if (viewport->debug_depth != NULL) {
+ MEM_freeN(viewport->debug_depth);
+ viewport->debug_depth = NULL;
+ }
+}
+
+void GPU_viewport_debug_depth_store(GPUViewport *viewport, const int x, const int y)
+{
+ const int w = GPU_texture_width(viewport->debug_depth);
+ const int h = GPU_texture_height(viewport->debug_depth);
+
+ GPU_texture_bind(viewport->debug_depth, 0);
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, x, y, w, h, 0);
+ GPU_texture_unbind(viewport->debug_depth);
+}
+
+void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, const float zfar)
+{
+ const float w = (float)GPU_texture_width(viewport->debug_depth);
+ const float h = (float)GPU_texture_height(viewport->debug_depth);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_DEPTH);
+
+ GPU_texture_bind(viewport->debug_depth, 0);
+
+ immUniform1f("znear", znear);
+ immUniform1f("zfar", zfar);
+ immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
+
+ immBegin(GWN_PRIM_TRI_STRIP, 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, 0.0f, 1.0f);
+ immVertex2f(pos, 0.0f, h);
+
+ immAttrib2f(texcoord, 1.0f, 1.0f);
+ immVertex2f(pos, w, h);
+
+ immEnd();
+
+ GPU_texture_unbind(viewport->debug_depth);
+
+ immUnbindProgram();
+}
+
+int GPU_viewport_debug_depth_width(const GPUViewport *viewport)
+{
+ return GPU_texture_width(viewport->debug_depth);
+}
+
+int GPU_viewport_debug_depth_height(const GPUViewport *viewport)
+{
+ return GPU_texture_height(viewport->debug_depth);
+}
+
+bool GPU_viewport_debug_depth_is_valid(GPUViewport *viewport)
+{
+ return viewport->debug_depth != NULL;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl
new file mode 100644
index 00000000000..769e2b0e37c
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 pos;
+in vec4 color;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl
new file mode 100644
index 00000000000..228f3f1da19
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+/* Keep in sync with intern/opencolorio/gpu_shader_display_transform_vertex.glsl */
+in vec2 texCoord;
+in vec2 pos;
+out vec2 texCoord_interp;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos.xy, 0.0f, 1.0f);
+ texCoord_interp = texCoord;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl
new file mode 100644
index 00000000000..7caf00f58fd
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl
@@ -0,0 +1,54 @@
+
+/*
+ * Fragment Shader for dashed lines, with uniform multi-color(s), or any single-color, and any thickness.
+ *
+ * Dashed is performed in screen space.
+ */
+
+uniform float dash_width;
+
+/* Simple mode, discarding non-dash parts (so no need for blending at all). */
+uniform float dash_factor; /* if > 1.0, solid line. */
+
+/* More advanced mode, allowing for complex, multi-colored patterns. Enabled when num_colors > 0. */
+/* Note: max number of steps/colors in pattern is 32! */
+uniform int num_colors; /* Enabled if > 0, 1 for solid line. */
+uniform vec4 colors[32];
+
+noperspective in float distance_along_line;
+noperspective in vec4 color_geom;
+
+out vec4 fragColor;
+
+void main()
+{
+ /* Multi-color option. */
+ if (num_colors > 0) {
+ /* Solid line case, simple. */
+ if (num_colors == 1) {
+ fragColor = colors[0];
+ }
+ /* Actually dashed line... */
+ else {
+ float normalized_distance = fract(distance_along_line / dash_width);
+ fragColor = colors[int(normalized_distance * num_colors)];
+ }
+ }
+ /* Single color option. */
+ else {
+ /* Solid line case, simple. */
+ if (dash_factor >= 1.0f) {
+ fragColor = color_geom;
+ }
+ /* Actually dashed line... */
+ else {
+ float normalized_distance = fract(distance_along_line / dash_width);
+ if (normalized_distance <= dash_factor) {
+ fragColor = color_geom;
+ }
+ else {
+ discard;
+ }
+ }
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl
new file mode 100644
index 00000000000..db4bdf0a9f0
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl
@@ -0,0 +1,56 @@
+
+/*
+ * Geometry Shader for dashed lines, with uniform multi-color(s), or any single-color, and unary thickness.
+ *
+ * Dashed is performed in screen space.
+ */
+
+
+/* Make to be used with dynamic batching so no Model Matrix needed */
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewport_size;
+
+/* Uniforms from fragment shader, used here to optimize out useless computation in case of solid line. */
+uniform float dash_factor; /* if > 1.0, solid line. */
+uniform int num_colors; /* Enabled if > 0, 1 for solid line. */
+
+layout(lines) in;
+
+in vec4 color_vert[];
+
+layout(line_strip, max_vertices = 2) out;
+noperspective out float distance_along_line;
+noperspective out vec4 color_geom;
+
+void main()
+{
+ vec4 v1 = gl_in[0].gl_Position;
+ vec4 v2 = gl_in[1].gl_Position;
+
+ gl_Position = v1;
+ color_geom = color_vert[0];
+ distance_along_line = 0.0f;
+ EmitVertex();
+
+ gl_Position = v2;
+ color_geom = color_vert[1];
+ if ((num_colors == 1) || (dash_factor >= 1.0f)) {
+ /* Solid line, optimize out distance computation! */
+ distance_along_line = 0.0f;
+ }
+ else {
+ vec2 p1 = (v1.xy / v1.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range.
+ p1 = p1 * viewport_size; // <- 'virtual' screen coordinates.
+
+ vec2 p2 = (v2.xy / v2.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range.
+ p2 = p2 * viewport_size; // <- 'virtual' screen coordinates.
+
+ distance_along_line = distance(p1, p2);
+ }
+ EmitVertex();
+
+ EndPrimitive();
+
+ /* Note: we could also use similar approach as diag_stripes_frag, but this would give us dashed 'anchored'
+ * to the screen, and not to one end of the line... */
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl
new file mode 100644
index 00000000000..f5c611586aa
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl
@@ -0,0 +1,21 @@
+
+/*
+ * Vertex Shader for dashed lines with 2D coordinates, with uniform multi-colors or uniform single-color,
+ * and unary thickness.
+ *
+ * Dashed is performed in screen space.
+ */
+
+uniform mat4 ModelViewProjectionMatrix;
+
+uniform vec4 color;
+
+in vec2 pos;
+
+out vec4 color_vert;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ color_vert = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl
new file mode 100644
index 00000000000..20c72f4407d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl
@@ -0,0 +1,59 @@
+
+// Draw dashed lines, perforated in screen space, with non-unary width.
+
+/* Make to be used with dynamic batching so no Model Matrix needed */
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewport_size;
+
+/* Width of the generated 'line'. */
+uniform float width; /* in pixels, screen space. */
+
+/* Uniforms from fragment shader, used here to optimize out useless computation in case of solid line. */
+uniform float dash_factor; /* if > 1.0, solid line. */
+uniform int num_colors; /* Enabled if > 0, 1 for solid line. */
+
+layout(lines) in;
+
+layout(triangle_strip, max_vertices = 4) out;
+noperspective out float distance_along_line;
+
+void main()
+{
+ vec4 v1 = gl_in[0].gl_Position;
+ vec4 v2 = gl_in[1].gl_Position;
+
+ /* Width, from 2D screen space in pixels, to ModelViewProjection space of each input vertices. */
+ float w1 = (width / viewport_size) * v1.w * 2.0;
+ float w2 = (width / viewport_size) * v2.w * 2.0;
+
+ /* Normalized vector parallel to screen and orthogonal to line. */
+ vec4 wdir = normalize(vec4(v1.y - v2.y, v2.x - v1.x, 0.0, 0.0))
+
+ distance_along_line = 0.0f;
+ gl_Position = v1 + (wdir * w1);
+ EmitVertex();
+
+ gl_Position = v1 - (wdir * w1);
+ EmitVertex();
+
+ if ((num_colors == 1) || (dash_factor >= 1.0f)) {
+ /* Solid line, optimize out distance computation! */
+ distance_along_line = 0.0f;
+ }
+ else {
+ vec2 p1 = (v1.xy / v1.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range.
+ p1 = p1 * viewport_size; // <- 'virtual' screen coordinates.
+
+ vec2 p2 = (v2.xy / v2.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range.
+ p2 = p2 * viewport_size; // <- 'virtual' screen coordinates.
+
+ distance_along_line = distance(p1, p2);
+ }
+ gl_Position = v2 + (wdir * w2);
+ EmitVertex();
+
+ gl_Position = v2 - (wdir * w2);
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl
new file mode 100644
index 00000000000..1f833cfb7be
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl
@@ -0,0 +1,21 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+
+in vec2 pos;
+out vec2 radii;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl
new file mode 100644
index 00000000000..99bdeb22904
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl
@@ -0,0 +1,24 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+uniform float outlineWidth;
+
+in vec2 pos;
+out vec4 radii;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - outlineWidth;
+ radii[3] = radius - outlineWidth - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl
new file mode 100644
index 00000000000..5fad95236df
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl
@@ -0,0 +1,27 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+uniform float outlineWidth;
+
+in vec2 pos;
+in vec4 color;
+out vec4 radii;
+out vec4 fillColor;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+ fillColor = color;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - outlineWidth;
+ radii[3] = radius - outlineWidth - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl
new file mode 100644
index 00000000000..d6aacf0cdc5
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl
@@ -0,0 +1,14 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 pos;
+in float size;
+in vec4 color;
+out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl
new file mode 100644
index 00000000000..4a4bfb6a616
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl
@@ -0,0 +1,8 @@
+
+noperspective in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl
new file mode 100644
index 00000000000..fe91f4d0902
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 pos;
+in vec4 color;
+
+noperspective out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl
new file mode 100644
index 00000000000..89e3c52f9f8
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl
@@ -0,0 +1,9 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 pos;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl
new file mode 100644
index 00000000000..84e44837264
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl
@@ -0,0 +1,12 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ModelMatrix;
+uniform vec4 ClipPlane;
+
+in vec3 pos;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_ClipDistance[0] = dot(ModelMatrix * vec4(pos, 1.0), ClipPlane);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl
new file mode 100644
index 00000000000..7db7e28d8e6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl
@@ -0,0 +1,26 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+#if defined(USE_COLOR_U32)
+in uint color;
+#else
+in vec4 color;
+#endif
+
+flat out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+#if defined(USE_COLOR_U32)
+ finalColor = vec4(
+ ((color ) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 8) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 16) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 24) ) * (1.0f / 255.0f));
+#else
+ finalColor = color;
+#endif
+}
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_image_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl
new file mode 100644
index 00000000000..eb877ab20b6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl
@@ -0,0 +1,12 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 texCoord;
+in vec3 pos;
+out vec2 texCoord_interp;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos.xyz, 1.0f);
+ texCoord_interp = texCoord;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl
new file mode 100644
index 00000000000..84fbf977846
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl
@@ -0,0 +1,26 @@
+
+/*
+ * Vertex Shader for dashed lines with 3D coordinates, with uniform multi-colors or uniform single-color,
+ * and unary thickness.
+ *
+ * Legacy version, without geometry shader support, always produce solid lines!
+ */
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewport_size;
+
+uniform vec4 color;
+
+in vec3 pos;
+noperspective out float distance_along_line;
+noperspective out vec4 color_geom;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ /* Hack - prevent stupid GLSL compiler to optimize out unused viewport_size uniform, which gives crash! */
+ distance_along_line = viewport_size.x * 0.000001f - viewport_size.x * 0.0000009f;
+
+ color_geom = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl
new file mode 100644
index 00000000000..2fe08896585
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl
@@ -0,0 +1,21 @@
+
+/*
+ * Vertex Shader for dashed lines with 3D coordinates, with uniform multi-colors or uniform single-color,
+ * and unary thickness.
+ *
+ * Dashed is performed in screen space.
+ */
+
+uniform mat4 ModelViewProjectionMatrix;
+
+uniform vec4 color;
+
+in vec3 pos;
+
+out vec4 color_vert;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ color_vert = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl
new file mode 100644
index 00000000000..e6b8fed7265
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl
@@ -0,0 +1,22 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+
+in vec3 pos;
+in vec3 nor;
+in vec4 color;
+
+#ifdef USE_FLAT_NORMAL
+flat out vec3 normal;
+flat out vec4 finalColor;
+#else
+out vec3 normal;
+out vec4 finalColor;
+#endif
+
+void main()
+{
+ normal = normalize(NormalMatrix * nor);
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl
new file mode 100644
index 00000000000..a3f447a85f9
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+
+in vec3 pos;
+in vec3 nor;
+out vec3 normal;
+
+void main()
+{
+ normal = normalize(NormalMatrix * nor);
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.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_point_fixed_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl
new file mode 100644
index 00000000000..2fe9c0623fa
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl
@@ -0,0 +1,12 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec4 color;
+out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl
new file mode 100644
index 00000000000..ebc945fcf35
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl
@@ -0,0 +1,21 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+
+in vec3 pos;
+out vec2 radii;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl
new file mode 100644
index 00000000000..0d6b90cfba4
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl
@@ -0,0 +1,24 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+uniform float outlineWidth;
+
+in vec3 pos;
+out vec4 radii;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - outlineWidth;
+ radii[3] = radius - outlineWidth - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl
new file mode 100644
index 00000000000..e14b9535c89
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl
@@ -0,0 +1,14 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in float size;
+in vec4 color;
+out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl
new file mode 100644
index 00000000000..e4f173ab617
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl
@@ -0,0 +1,11 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in float size;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl
new file mode 100644
index 00000000000..41fdefd22e8
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl
@@ -0,0 +1,8 @@
+
+in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl
new file mode 100644
index 00000000000..a1feb2f75b7
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec4 color;
+
+out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl
new file mode 100644
index 00000000000..059473ebb74
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl
@@ -0,0 +1,9 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
index 01a335af048..5f7455582cd 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
@@ -20,12 +20,10 @@
#define STIPPLE_HEXAGON 3
#define STIPPLE_DIAG_STRIPES 4
#define STIPPLE_DIAG_STRIPES_SWAP 5
-#define STIPPLE_S3D_INTERLACE_ROW 6
-#define STIPPLE_S3D_INTERLACE_ROW_SWAP 7
-#define STIPPLE_S3D_INTERLACE_COLUMN 8
-#define STIPPLE_S3D_INTERLACE_COLUMN_SWAP 9
-#define STIPPLE_S3D_INTERLACE_CHECKERBOARD 10
-#define STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP 11
+
+#ifndef NO_SPECULAR
+uniform mat4 ProjectionMatrix;
+#endif
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
#if defined(USE_FLAT_NORMAL)
@@ -58,7 +56,7 @@ uniform sampler2D_default texture_map;
#ifdef USE_STIPPLE
uniform int stipple_id;
#if defined(DRAW_LINE)
-varying in float t;
+varying float t;
uniform int stipple_pattern;
#endif
#endif
@@ -74,14 +72,9 @@ void main()
/* We have to use mod function and integer casting.
* This can be optimized further with the bitwise operations
* when GLSL 1.3 is supported. */
- if (stipple_id == STIPPLE_HALFTONE ||
- stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD ||
- stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP)
- {
+ if (stipple_id == STIPPLE_HALFTONE) {
int result = int(mod(gl_FragCoord.x + gl_FragCoord.y, 2));
bool dis = result == 0;
- if (stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP)
- dis = !dis;
if (dis)
discard;
}
@@ -116,22 +109,6 @@ void main()
if (!((16 - modx > mody && mody > 8 - modx) || mody > 24 - modx))
discard;
}
- else if (stipple_id == STIPPLE_S3D_INTERLACE_ROW || stipple_id == STIPPLE_S3D_INTERLACE_ROW_SWAP) {
- int result = int(mod(gl_FragCoord.y, 2));
- bool dis = result == 0;
- if (stipple_id == STIPPLE_S3D_INTERLACE_ROW_SWAP)
- dis = !dis;
- if (dis)
- discard;
- }
- else if (stipple_id == STIPPLE_S3D_INTERLACE_COLUMN || stipple_id == STIPPLE_S3D_INTERLACE_COLUMN_SWAP) {
- int result = int(mod(gl_FragCoord.x, 2));
- bool dis = result != 0;
- if (stipple_id == STIPPLE_S3D_INTERLACE_COLUMN_SWAP)
- dis = !dis;
- if (dis)
- discard;
- }
else if (stipple_id == STIPPLE_HEXAGON) {
int mody = int(mod(gl_FragCoord.y, 2));
int modx = int(mod(gl_FragCoord.x, 4));
@@ -190,7 +167,7 @@ void main()
#ifndef NO_SPECULAR
/* view vector computation, depends on orthographics or perspective */
- vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position) : vec3(0.0, 0.0, -1.0);
+ vec3 V = (ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position) : vec3(0.0, 0.0, -1.0);
#endif
for (int i = 0; i < NUM_SCENE_LIGHTS; i++) {
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl b/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
index a88681a5fd3..13f05b340bf 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
@@ -14,9 +14,9 @@ layout(line_strip, max_vertices = 10) out;
layout(triangle_strip, max_vertices = 6) out;
#endif
-varying out float t;
-varying in vec4 varying_vertex_color_line[];
-varying out vec4 varying_vertex_color;
+out float t;
+in vec4 varying_vertex_color_line[];
+out vec4 varying_vertex_color;
uniform ivec4 viewport;
uniform float line_width;
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
index 42fbdadf1d1..dbf6c267f14 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
@@ -1,4 +1,8 @@
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat3 NormalMatrix;
+
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
#if defined(USE_FLAT_NORMAL)
varying vec3 eyespace_vert_pos;
@@ -29,15 +33,15 @@ varying float gl_ClipDistance[6];
void main()
{
- vec4 co = gl_ModelViewMatrix * gl_Vertex;
+ vec4 co = ModelViewMatrix * gl_Vertex;
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
#if !defined(USE_FLAT_NORMAL)
- varying_normal = normalize(gl_NormalMatrix * gl_Normal);
+ varying_normal = normalize(NormalMatrix * gl_Normal);
#endif
#if defined(USE_FLAT_NORMAL)
/* transform vertex into eyespace */
- eyespace_vert_pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
+ eyespace_vert_pos = (ModelViewMatrix * gl_Vertex).xyz;
#endif
#ifndef USE_SOLID_LIGHTING
@@ -45,7 +49,7 @@ void main()
#endif
#endif
- gl_Position = gl_ProjectionMatrix * co;
+ gl_Position = ProjectionMatrix * co;
#ifdef CLIP_WORKAROUND
int i;
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..545f6d19e21
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl
@@ -0,0 +1,20 @@
+
+uniform vec4 color1;
+uniform vec4 color2;
+uniform int size;
+
+out vec4 fragColor;
+
+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_depth_only_frag.glsl b/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl
new file mode 100644
index 00000000000..60e71e19004
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl
@@ -0,0 +1,6 @@
+
+void main()
+{
+ // no color output, only depth (line below is implicit)
+ // gl_FragDepth = gl_FragCoord.z;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl b/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl
new file mode 100644
index 00000000000..beb71c58100
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl
@@ -0,0 +1,20 @@
+
+uniform vec4 color1;
+uniform vec4 color2;
+uniform int size1;
+uniform int size2;
+
+out vec4 fragColor;
+
+void main()
+{
+ float phase = mod((gl_FragCoord.x + gl_FragCoord.y), (size1 + size2));
+
+ if (phase < size1)
+ {
+ fragColor = color1;
+ }
+ else {
+ fragColor = color2;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl
new file mode 100644
index 00000000000..4ed7ed56c11
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl
@@ -0,0 +1,54 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+uniform bool drawFront = true;
+uniform bool drawBack = true;
+uniform bool drawSilhouette = true;
+
+uniform vec4 frontColor;
+uniform vec4 backColor;
+uniform vec4 silhouetteColor;
+
+uniform vec3 eye; // direction we are looking
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+
+// normals of faces this edge joins (object coords)
+in vec3 N1;
+in vec3 N2;
+
+flat out vec4 finalColor;
+
+// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
+
+// to discard an entire line, set both endpoints to nowhere
+// and it won't produce any fragments
+const vec4 nowhere = vec4(vec3(0.0), 1.0);
+
+void main()
+{
+ bool face_1_front = dot(N1, eye) > 0.0;
+ bool face_2_front = dot(N2, eye) > 0.0;
+
+ vec4 position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ if (face_1_front && face_2_front) {
+ // front-facing edge
+ gl_Position = drawFront ? position : nowhere;
+ finalColor = frontColor;
+ }
+ else if (face_1_front || face_2_front) {
+ // exactly one face is front-facing, silhouette edge
+ gl_Position = drawSilhouette ? position : nowhere;
+ finalColor = silhouetteColor;
+ }
+ else {
+ // back-facing edge
+ gl_Position = drawBack ? position : nowhere;
+ finalColor = backColor;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl
new file mode 100644
index 00000000000..10b5fad7972
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl
@@ -0,0 +1,60 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. This geometry shader
+// decides which edge type to use if endpoints disagree.
+
+uniform mat4 ProjectionMatrix;
+
+uniform bool drawFront = true;
+uniform bool drawBack = true;
+uniform bool drawSilhouette = true;
+
+uniform vec4 frontColor;
+uniform vec4 backColor;
+uniform vec4 silhouetteColor;
+
+layout(lines) in;
+layout(line_strip, max_vertices = 2) out;
+
+in vec4 MV_pos[];
+in float edgeClass[];
+
+flat out vec4 finalColor;
+
+void emitLine(vec4 color)
+{
+ gl_Position = ProjectionMatrix * MV_pos[0];
+ EmitVertex();
+ gl_Position = ProjectionMatrix * MV_pos[1];
+ finalColor = color;
+ EmitVertex();
+ EndPrimitive();
+}
+
+void main()
+{
+ float finalEdgeClass = max(edgeClass[0], edgeClass[1]);
+
+ if (finalEdgeClass > 0.0f) {
+ // front-facing edge
+ if (drawFront)
+ emitLine(frontColor);
+ }
+ else if (finalEdgeClass < 0.0f) {
+ // back-facing edge
+ if (drawBack)
+ emitLine(backColor);
+ }
+ else {
+ // exactly one face is front-facing, silhouette edge
+ if (drawSilhouette)
+ emitLine(silhouetteColor);
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl
new file mode 100644
index 00000000000..30b3bdb890d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl
@@ -0,0 +1,68 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// This shader is an imperfect stepping stone until all platforms are
+// ready for geometry shaders.
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. Need to use a geometry
+// shader or pass in an extra position attribute (the other endpoint)
+// to do this properly.
+
+uniform bool drawFront = true;
+uniform bool drawBack = true;
+uniform bool drawSilhouette = true;
+
+uniform vec4 frontColor;
+uniform vec4 backColor;
+uniform vec4 silhouetteColor;
+
+uniform mat4 ModelViewMatrix;
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+
+in vec3 pos;
+
+// normals of faces this edge joins (object coords)
+in vec3 N1;
+in vec3 N2;
+
+flat out vec4 finalColor;
+
+// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
+
+// to discard an entire line, set its color to invisible
+// (must have GL_BLEND enabled, or discard in fragment shader)
+const vec4 invisible = vec4(0.0);
+
+bool front(vec3 N)
+{
+ vec4 xformed = ModelViewMatrix * vec4(pos, 1.0);
+ return dot(NormalMatrix * N, normalize(-xformed.xyz)) > 0.0;
+}
+
+void main()
+{
+ bool face_1_front = front(N1);
+ bool face_2_front = front(N2);
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ if (face_1_front && face_2_front) {
+ // front-facing edge
+ finalColor = drawFront ? frontColor : invisible;
+ }
+ else if (face_1_front || face_2_front) {
+ // exactly one face is front-facing, silhouette edge
+ finalColor = drawSilhouette ? silhouetteColor : invisible;
+ }
+ else {
+ // back-facing edge
+ finalColor = drawBack ? backColor : invisible;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl
new file mode 100644
index 00000000000..e1fb78dd1a9
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl
@@ -0,0 +1,44 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. We use a geometry
+// shader to resolve this properly.
+
+uniform mat4 ModelViewMatrix;
+uniform mat3 NormalMatrix;
+
+in vec3 pos;
+in vec3 N1, N2; // normals of faces this edge joins (object coords)
+
+out vec4 MV_pos;
+out float edgeClass;
+
+// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
+
+bool front(vec3 N, vec3 eye)
+{
+ return dot(NormalMatrix * N, eye) > 0.0;
+}
+
+void main()
+{
+ MV_pos = ModelViewMatrix * vec4(pos, 1.0);
+
+ vec3 eye = normalize(-MV_pos.xyz);
+
+ bool face_1_front = front(N1, eye);
+ bool face_2_front = front(N2, eye);
+
+ if (face_1_front && face_2_front)
+ edgeClass = 1.0; // front-facing edge
+ else if (face_1_front || face_2_front)
+ edgeClass = 0.0; // exactly one face is front-facing, silhouette edge
+ else
+ edgeClass = -1.0; // back-facing edge
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl
new file mode 100644
index 00000000000..0538c037dcf
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl
@@ -0,0 +1,20 @@
+
+#define SMOOTH 1
+
+const float transitionWidth = 1.0;
+
+uniform vec4 fillColor = vec4(0);
+uniform vec4 outlineColor = vec4(0,0,0,1);
+
+noperspective in vec3 distanceToOutline;
+
+out vec4 FragColor;
+
+void main() {
+ float edgeness = min(min(distanceToOutline.x, distanceToOutline.y), distanceToOutline.z);
+#if SMOOTH
+ FragColor = mix(outlineColor, fillColor, smoothstep(0, transitionWidth, edgeness));
+#else
+ FragColor = (edgeness <= 0) ? outlineColor : fillColor;
+#endif
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl
new file mode 100644
index 00000000000..ad0dccb6c81
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl
@@ -0,0 +1,67 @@
+layout(triangles) in;
+layout(triangle_strip, max_vertices=3) out;
+
+uniform float outlineWidth = 1.0;
+uniform vec2 viewportSize;
+
+in vec4 pos_xformed[];
+in float widthModulator[];
+
+noperspective out vec3 distanceToOutline;
+
+// project to screen space
+vec2 proj(int axis) {
+ vec4 pos = pos_xformed[axis];
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+float dist(vec2 pos[3], int v) {
+ // current vertex position
+ vec2 vpos = pos[v];
+ // endpoints of opposite edge
+ vec2 e1 = pos[(v + 1) % 3];
+ vec2 e2 = pos[(v + 2) % 3];
+
+ float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify
+ return abs_det / distance(e2, e1);
+}
+
+vec3 distance[3];
+
+void clearEdge(int v) {
+ float distant = 10 * outlineWidth;
+ for (int i = 0; i < 3; ++i)
+ distance[i][v] += distant;
+}
+
+void modulateEdge(int v) {
+ float offset = min(widthModulator[v],1) * outlineWidth;
+ for (int i = 0; i < 3; ++i)
+ distance[i][v] -= offset;
+}
+
+void main() {
+ vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2));
+
+ for (int v = 0; v < 3; ++v)
+ distance[v] = vec3(0);
+
+ for (int v = 0; v < 3; ++v) {
+ if (widthModulator[v] > 0) {
+ distance[v][v] = dist(pos, v);
+ modulateEdge(v);
+ }
+ }
+
+ for (int v = 0; v < 3; ++v)
+ if (widthModulator[v] <= 0)
+ clearEdge(v);
+
+ for (int v = 0; v < 3; ++v) {
+ gl_Position = pos_xformed[v];
+ distanceToOutline = distance[v];
+ EmitVertex();
+ }
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl
new file mode 100644
index 00000000000..ec692e210c2
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl
@@ -0,0 +1,52 @@
+layout(triangles) in;
+layout(triangle_strip, max_vertices=3) out;
+
+uniform float outlineWidth = 1.0;
+uniform vec2 viewportSize;
+
+noperspective out vec3 distanceToOutline;
+
+// project to screen space
+vec2 proj(int axis) {
+ vec4 pos = gl_in[axis].gl_Position;
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+float dist(vec2 pos[3], int v) {
+ // current vertex position
+ vec2 vpos = pos[v];
+ // endpoints of opposite edge
+ vec2 e1 = pos[(v + 1) % 3];
+ vec2 e2 = pos[(v + 2) % 3];
+
+ float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify
+ return abs_det / distance(e2, e1);
+}
+
+vec3 distance[3];
+
+void modulateEdge(int v) {
+ float offset = 0.5 * outlineWidth;
+ for (int i = 0; i < 3; ++i)
+ distance[i][v] -= offset;
+}
+
+void main() {
+ vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2));
+
+ for (int v = 0; v < 3; ++v)
+ distance[v] = vec3(0);
+
+ for (int v = 0; v < 3; ++v) {
+ distance[v][v] = dist(pos, v);
+ modulateEdge(v);
+ }
+
+ for (int v = 0; v < 3; ++v) {
+ gl_Position = gl_in[v].gl_Position;
+ distanceToOutline = distance[v];
+ EmitVertex();
+ }
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl
new file mode 100644
index 00000000000..fb1d0aafe05
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in float edgeWidthModulator;
+
+out vec4 pos_xformed;
+out float widthModulator;
+
+void main() {
+ pos_xformed = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ widthModulator = edgeWidthModulator;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl
index 3819203bcd9..fc9cafb6b02 100644
--- a/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl
@@ -1,17 +1,15 @@
-varying vec3 coords;
+in vec3 coords;
+out vec4 fragColor;
uniform sampler3D flame_texture;
uniform sampler1D spectrum_texture;
void main()
{
- float flame = texture3D(flame_texture, coords).r;
- vec4 emission = texture1D(spectrum_texture, flame);
+ float flame = texture(flame_texture, coords).r;
+ vec4 emission = texture(spectrum_texture, flame);
- vec4 color;
- color.rgb = emission.a * emission.rgb;
- color.a = emission.a;
-
- gl_FragColor = color;
+ fragColor.rgb = emission.a * emission.rgb;
+ fragColor.a = emission.a;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl b/source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl
new file mode 100644
index 00000000000..cefae1021d2
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl
@@ -0,0 +1,11 @@
+
+flat in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ if (finalColor.a > 0.0)
+ fragColor = finalColor;
+ else
+ discard;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl
new file mode 100644
index 00000000000..d738ed5ddb2
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl
@@ -0,0 +1,8 @@
+
+flat in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl
new file mode 100644
index 00000000000..fc5cc1cdcc3
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl
@@ -0,0 +1,10 @@
+
+in vec2 pos;
+in vec2 uvs;
+out vec4 uvcoordsvar;
+
+void main()
+{
+ uvcoordsvar = vec4(uvs, 0.0, 0.0);
+ gl_Position = vec4(pos, 0.0, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
index e04cd7d3306..c4e7cff2b0b 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
@@ -1,9 +1,10 @@
uniform sampler2D depthbuffer;
-varying vec4 uvcoordsvar;
+
+in vec4 uvcoordsvar;
void main(void)
{
- float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
+ float depth = texture(depthbuffer, uvcoordsvar.xy).r;
/* XRay background, discard */
if (depth >= 1.0) {
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
index 338ef6d51a7..15d30e75969 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
@@ -17,17 +17,18 @@ uniform vec4 dof_params;
uniform vec4 viewvecs[3];
// coordinates on framebuffer in normalized (0.0-1.0) uv space
-varying vec4 uvcoordsvar;
+in vec4 uvcoordsvar;
/* color texture coordinates, offset by a small amount */
-varying vec2 color_uv1;
-varying vec2 color_uv2;
+in vec2 color_uv1;
+in vec2 color_uv2;
-varying vec2 depth_uv1;
-varying vec2 depth_uv2;
-varying vec2 depth_uv3;
-varying vec2 depth_uv4;
+in vec2 depth_uv1;
+in vec2 depth_uv2;
+in vec2 depth_uv3;
+in vec2 depth_uv4;
+out vec4 FragColor;
float calculate_far_coc(in float zdepth)
{
@@ -63,85 +64,85 @@ void first_pass()
offset_row[2] = 3.0 * offset_row[0];
/* heavily blur the image */
- vec4 color = texture2D(colorbuffer, color_uv1);
- color += texture2D(colorbuffer, color_uv1 + offset_row[1]);
- color += texture2D(colorbuffer, color_uv2);
- color += texture2D(colorbuffer, color_uv2 + offset_row[1]);
+ vec4 color = texture(colorbuffer, color_uv1);
+ color += texture(colorbuffer, color_uv1 + offset_row[1]);
+ color += texture(colorbuffer, color_uv2);
+ color += texture(colorbuffer, color_uv2 + offset_row[1]);
color /= 4.0;
- depth.r = texture2D(depthbuffer, depth_uv1).r;
- depth.g = texture2D(depthbuffer, depth_uv2).r;
- depth.b = texture2D(depthbuffer, depth_uv3).r;
- depth.a = texture2D(depthbuffer, depth_uv4).r;
+ depth.r = texture(depthbuffer, depth_uv1).r;
+ depth.g = texture(depthbuffer, depth_uv2).r;
+ depth.b = texture(depthbuffer, depth_uv3).r;
+ depth.a = texture(depthbuffer, depth_uv4).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = calculate_near_coc(zdepth);
- depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[0]).r;
- depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[0]).r;
- depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[0]).r;
- depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[0]).r;
+ depth.r = texture(depthbuffer, depth_uv1 + offset_row[0]).r;
+ depth.g = texture(depthbuffer, depth_uv2 + offset_row[0]).r;
+ depth.b = texture(depthbuffer, depth_uv3 + offset_row[0]).r;
+ depth.a = texture(depthbuffer, depth_uv4 + offset_row[0]).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = max(calculate_near_coc(zdepth), coc);
- depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[1]).r;
- depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[1]).r;
- depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[1]).r;
- depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[1]).r;
+ depth.r = texture(depthbuffer, depth_uv1 + offset_row[1]).r;
+ depth.g = texture(depthbuffer, depth_uv2 + offset_row[1]).r;
+ depth.b = texture(depthbuffer, depth_uv3 + offset_row[1]).r;
+ depth.a = texture(depthbuffer, depth_uv4 + offset_row[1]).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = max(calculate_near_coc(zdepth), coc);
- depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[2]).r;
- depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[2]).r;
- depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[2]).r;
- depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[2]).r;
+ depth.r = texture(depthbuffer, depth_uv1 + offset_row[2]).r;
+ depth.g = texture(depthbuffer, depth_uv2 + offset_row[2]).r;
+ depth.b = texture(depthbuffer, depth_uv3 + offset_row[2]).r;
+ depth.a = texture(depthbuffer, depth_uv4 + offset_row[2]).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = max(calculate_near_coc(zdepth), coc);
final_coc = max(max(coc.x, coc.y), max(coc.z, coc.w));
- gl_FragColor = vec4(color.rgb, final_coc);
+ FragColor = vec4(color.rgb, final_coc);
}
/* second pass, gaussian blur the downsampled image */
void second_pass()
{
- vec4 depth = vec4(texture2D(depthbuffer, uvcoordsvar.xy).r);
+ vec4 depth = vec4(texture(depthbuffer, uvcoordsvar.xy).r);
/* clever sampling to sample 2 pixels at once. Of course it's not real gaussian sampling this way */
- vec4 color = texture2D(colorbuffer, uvcoordsvar.xy) * 0.3125;
- color += texture2D(colorbuffer, uvcoordsvar.xy + invrendertargetdim) * 0.234375;
- color += texture2D(colorbuffer, uvcoordsvar.xy + 2.5 * invrendertargetdim) * 0.09375;
- color += texture2D(colorbuffer, uvcoordsvar.xy + 4.5 * invrendertargetdim) * 0.015625;
- color += texture2D(colorbuffer, uvcoordsvar.xy - invrendertargetdim) * 0.234375;
- color += texture2D(colorbuffer, uvcoordsvar.xy - 2.5 * invrendertargetdim) * 0.09375;
- color += texture2D(colorbuffer, uvcoordsvar.xy - 4.5 * invrendertargetdim) * 0.015625;
-
- gl_FragColor = color;
+ vec4 color = texture(colorbuffer, uvcoordsvar.xy) * 0.3125;
+ color += texture(colorbuffer, uvcoordsvar.xy + invrendertargetdim) * 0.234375;
+ color += texture(colorbuffer, uvcoordsvar.xy + 2.5 * invrendertargetdim) * 0.09375;
+ color += texture(colorbuffer, uvcoordsvar.xy + 4.5 * invrendertargetdim) * 0.015625;
+ color += texture(colorbuffer, uvcoordsvar.xy - invrendertargetdim) * 0.234375;
+ color += texture(colorbuffer, uvcoordsvar.xy - 2.5 * invrendertargetdim) * 0.09375;
+ color += texture(colorbuffer, uvcoordsvar.xy - 4.5 * invrendertargetdim) * 0.015625;
+
+ FragColor = color;
}
/* third pass, calculate the final coc from blurred and unblurred images */
void third_pass()
{
- vec4 color = texture2D(colorbuffer, uvcoordsvar.xy);
- vec4 color_blurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
+ vec4 color = texture(colorbuffer, uvcoordsvar.xy);
+ vec4 color_blurred = texture(blurredcolorbuffer, uvcoordsvar.xy);
float coc = 2.0 * max(color_blurred.a, color.a); -color.a;
- gl_FragColor = vec4(color.rgb, coc);
+ FragColor = vec4(color.rgb, coc);
}
/* fourth pass, blur the final coc once to get rid of discontinuities */
void fourth_pass()
{
- vec4 color = texture2D(colorbuffer, uvcoordsvar.xz);
- color += texture2D(colorbuffer, uvcoordsvar.yz);
- color += texture2D(colorbuffer, uvcoordsvar.xw);
- color += texture2D(colorbuffer, uvcoordsvar.yw);
+ vec4 color = texture(colorbuffer, uvcoordsvar.xz);
+ color += texture(colorbuffer, uvcoordsvar.yz);
+ color += texture(colorbuffer, uvcoordsvar.xw);
+ color += texture(colorbuffer, uvcoordsvar.yw);
- gl_FragColor = color / 4.0;
+ FragColor = color / 4.0;
}
vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
@@ -150,10 +151,10 @@ vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
vec4 result = weight * color;
weight *= 4.0;
- result += weight * texture2D(colorbuffer, uv + color_uv1.xy);
- result += weight * texture2D(colorbuffer, uv - color_uv1.xy);
- result += weight * texture2D(colorbuffer, uv + color_uv1.yx);
- result += weight * texture2D(colorbuffer, uv - color_uv1.yx);
+ result += weight * texture(colorbuffer, uv + color_uv1.xy);
+ result += weight * texture(colorbuffer, uv - color_uv1.xy);
+ result += weight * texture(colorbuffer, uv + color_uv1.yx);
+ result += weight * texture(colorbuffer, uv - color_uv1.yx);
return result;
}
@@ -163,11 +164,11 @@ vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
void fifth_pass()
{
vec4 factors;
- vec4 color_orig = texture2D(colorbuffer, uvcoordsvar.xy);
- vec4 highblurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
- vec4 mediumblurred = texture2D(mblurredcolorbuffer, uvcoordsvar.xy);
+ vec4 color_orig = texture(colorbuffer, uvcoordsvar.xy);
+ vec4 highblurred = texture(blurredcolorbuffer, uvcoordsvar.xy);
+ vec4 mediumblurred = texture(mblurredcolorbuffer, uvcoordsvar.xy);
vec4 smallblurred = small_sample_blur(colorbuffer, uvcoordsvar.xy, color_orig);
- float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
+ float depth = texture(depthbuffer, uvcoordsvar.xy).r;
float zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth)).r;
float coc_far = clamp(calculate_far_coc(zdepth), 0.0, 1.0);
@@ -188,7 +189,7 @@ void fifth_pass()
color /= dot(factors, vec4(1.0));
/* using original color is not correct, but use that for now because alpha of
* blurred buffers uses CoC instead */
- gl_FragColor = vec4(color.rgb, color_orig.a);
+ FragColor = vec4(color.rgb, color_orig.a);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
index 182113367d3..c41c1d0820b 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
@@ -14,24 +14,28 @@ uniform sampler2D depthbuffer;
uniform sampler2D cocbuffer;
-/* this includes focal distance in x and aperture size in y */
+/* this includes aperture size in x and focal distance in y */
uniform vec4 dof_params;
/* viewvectors for reconstruction of world space */
uniform vec4 viewvecs[3];
/* initial uv coordinate */
-varying vec2 uvcoord;
+in vec2 uvcoord;
/* coordinate used for calculating radius et al set in geometry shader */
-varying vec2 particlecoord;
-varying vec4 color;
+in vec2 particlecoord;
+flat in vec4 color;
/* downsampling coordinates */
-varying vec2 downsample1;
-varying vec2 downsample2;
-varying vec2 downsample3;
-varying vec2 downsample4;
+in vec2 downsample1;
+in vec2 downsample2;
+in vec2 downsample3;
+in vec2 downsample4;
+
+layout(location = 0) out vec4 fragData0;
+layout(location = 1) out vec4 fragData1;
+layout(location = 2) out vec4 fragData2;
#define M_PI 3.1415926535897932384626433832795
@@ -55,15 +59,15 @@ void downsample_pass()
float far_coc, near_coc;
/* custom downsampling. We need to be careful to sample nearest here to avoid leaks */
- vec4 color1 = texture2D(colorbuffer, downsample1);
- vec4 color2 = texture2D(colorbuffer, downsample2);
- vec4 color3 = texture2D(colorbuffer, downsample3);
- vec4 color4 = texture2D(colorbuffer, downsample4);
+ vec4 color1 = texture(colorbuffer, downsample1);
+ vec4 color2 = texture(colorbuffer, downsample2);
+ vec4 color3 = texture(colorbuffer, downsample3);
+ vec4 color4 = texture(colorbuffer, downsample4);
- depth.r = texture2D(depthbuffer, downsample1).r;
- depth.g = texture2D(depthbuffer, downsample2).r;
- depth.b = texture2D(depthbuffer, downsample3).r;
- depth.a = texture2D(depthbuffer, downsample4).r;
+ depth.r = texture(depthbuffer, downsample1).r;
+ depth.g = texture(depthbuffer, downsample2).r;
+ depth.b = texture(depthbuffer, downsample3).r;
+ depth.a = texture(depthbuffer, downsample4).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = calculate_coc(zdepth);
@@ -82,16 +86,16 @@ void downsample_pass()
float norm_far = dot(far_weights, vec4(1.0));
/* now write output to weighted buffers. */
- gl_FragData[0] = color1 * near_weights.x + color2 * near_weights.y + color3 * near_weights.z +
+ fragData0 = color1 * near_weights.x + color2 * near_weights.y + color3 * near_weights.z +
color4 * near_weights.w;
- gl_FragData[1] = color1 * far_weights.x + color2 * far_weights.y + color3 * far_weights.z +
+ fragData1 = color1 * far_weights.x + color2 * far_weights.y + color3 * far_weights.z +
color4 * far_weights.w;
if (norm_near > 0.0)
- gl_FragData[0] /= norm_near;
+ fragData0 /= norm_near;
if (norm_far > 0.0)
- gl_FragData[1] /= norm_far;
- gl_FragData[2] = vec4(near_coc, far_coc, 0.0, 1.0);
+ fragData1 /= norm_far;
+ fragData2 = vec4(near_coc, far_coc, 0.0, 1.0);
}
/* accumulate color in the near/far blur buffers */
@@ -102,36 +106,36 @@ void accumulate_pass(void) {
if (dof_params.w == 0.0)
r = 1.0;
else
- r = cos(M_PI / dof_params.w) /
- (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI))));
+ r = cos(M_PI / dof_params.w) /
+ (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI))));
if (dot(particlecoord, particlecoord) > r * r)
discard;
- gl_FragData[0] = color;
+ fragData0 = color;
}
-#define MERGE_THRESHOLD 4.0
+#define MERGE_THRESHOLD 4.0
/* combine the passes, */
void final_pass(void) {
vec4 finalcolor;
float totalweight;
- float depth = texture2D(depthbuffer, uvcoord).r;
+ float depth = texture(depthbuffer, uvcoord).r;
vec4 zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth));
float coc_near = calculate_coc(zdepth).r;
float coc_far = max(-coc_near, 0.0);
coc_near = max(coc_near, 0.0);
- vec4 farcolor = texture2D(farbuffer, uvcoord);
+ vec4 farcolor = texture(farbuffer, uvcoord);
float farweight = farcolor.a;
if (farweight > 0.0)
farcolor /= farweight;
- vec4 nearcolor = texture2D(nearbuffer, uvcoord);
+ vec4 nearcolor = texture(nearbuffer, uvcoord);
- vec4 srccolor = texture2D(colorbuffer, uvcoord);
+ vec4 srccolor = texture(colorbuffer, uvcoord);
- vec4 coc = texture2D(cocbuffer, uvcoord);
+ vec4 coc = texture(cocbuffer, uvcoord);
float mixfac = smoothstep(1.0, MERGE_THRESHOLD, coc_far);
finalcolor = mix(srccolor, farcolor, mixfac);
@@ -152,7 +156,9 @@ void final_pass(void) {
finalcolor = mix(finalcolor, nearcolor, nearweight / totalweight);
}
- gl_FragData[0] = finalcolor;
+ fragData0 = finalcolor;
+ // fragData0 = vec4(nearweight, farweight, 0.0, 1.0);
+ // fragData0 = vec4(nearcolor.rgb, 1.0);
}
void main()
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
index 4c650e7695f..52d0a9be499 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
@@ -5,27 +5,14 @@ uniform vec2 layerselection;
uniform sampler2D cocbuffer;
-#if __VERSION__ >= 150
- layout(points) in;
- layout(triangle_strip, max_vertices = 4) out;
-
- #define POS gl_in[0].gl_Position
-#else
- /* use the EXT_geometry_shader4 way */
- #define POS gl_PositionIn[0]
-#endif
-
-/* initial uv coordinate */
-#if __VERSION__ < 130
- varying in vec2 uvcoord[];
- varying out vec2 particlecoord;
- varying out vec4 color;
- #define textureLod texture2DLod
-#else
- in vec2 uvcoord[];
- out vec2 particlecoord;
- out vec4 color;
-#endif
+layout(points) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+#define POS gl_in[0].gl_Position
+
+in vec2 uvcoord[];
+out vec2 particlecoord;
+flat out vec4 color;
#define M_PI 3.1415926535897932384626433832795
@@ -46,21 +33,23 @@ void main()
vec2 offset_far = vec2(offset_val * 0.5) / vec2(rendertargetdim.x, rendertargetdim.y);
- gl_Position = POS + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0);
color = colortex;
+
+ gl_Position = POS + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0);
particlecoord = vec2(-1.0, -1.0);
EmitVertex();
+
gl_Position = POS + vec4(-offset_far.x, offset_far.y, 0.0, 0.0);
particlecoord = vec2(-1.0, 1.0);
- color = colortex;
EmitVertex();
+
gl_Position = POS + vec4(offset_far.x, -offset_far.y, 0.0, 0.0);
particlecoord = vec2(1.0, -1.0);
- color = colortex;
EmitVertex();
+
gl_Position = POS + vec4(offset_far.x, offset_far.y, 0.0, 0.0);
particlecoord = vec2(1.0, 1.0);
- color = colortex;
EmitVertex();
+
EndPrimitive();
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
index 09a0c75facc..1dd5bf42b25 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
@@ -1,27 +1,31 @@
-uniform vec2 invrendertargetdim;
-uniform ivec2 rendertargetdim;
+
+in vec2 pos;
+in vec2 uvs;
/* initial uv coordinate */
-varying vec2 uvcoord;
+out vec2 uvcoord;
/* coordinate used for calculating radius et al set in geometry shader */
-varying vec2 particlecoord;
+out vec2 particlecoord;
/* downsampling coordinates */
-varying vec2 downsample1;
-varying vec2 downsample2;
-varying vec2 downsample3;
-varying vec2 downsample4;
+out vec2 downsample1;
+out vec2 downsample2;
+out vec2 downsample3;
+out vec2 downsample4;
+
+uniform vec2 invrendertargetdim;
+uniform ivec2 rendertargetdim;
void vert_dof_downsample()
{
/* gather pixels from neighbors. half dimensions means we offset half a pixel to
* get this right though it's possible we may lose a pixel at some point */
- downsample1 = gl_MultiTexCoord0.xy + vec2(-0.5, -0.5) * invrendertargetdim;
- downsample2 = gl_MultiTexCoord0.xy + vec2(-0.5, 0.5) * invrendertargetdim;
- downsample3 = gl_MultiTexCoord0.xy + vec2(0.5, 0.5) * invrendertargetdim;
- downsample4 = gl_MultiTexCoord0.xy + vec2(0.5, -0.5) * invrendertargetdim;
+ downsample1 = uvs.xy + vec2(-0.5, -0.5) * invrendertargetdim;
+ downsample2 = uvs.xy + vec2(-0.5, 0.5) * invrendertargetdim;
+ downsample3 = uvs.xy + vec2(0.5, 0.5) * invrendertargetdim;
+ downsample4 = uvs.xy + vec2(0.5, -0.5) * invrendertargetdim;
- gl_Position = gl_Vertex;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
/* geometry shading pass, calculate a texture coordinate based on the indexed id */
@@ -42,8 +46,8 @@ void vert_dof_coc_scatter_pass()
void vert_dof_final()
{
- uvcoord = gl_MultiTexCoord0.xy;
- gl_Position = gl_Vertex;
+ uvcoord = uvs;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void main()
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
index 63b57d5775c..0fcab6302e4 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
@@ -1,51 +1,54 @@
uniform vec2 invrendertargetdim;
-//texture coordinates for framebuffer read
-varying vec4 uvcoordsvar;
+in vec2 pos;
+in vec2 uvs;
+
+/* texture coordinates for framebuffer read */
+out vec4 uvcoordsvar;
/* color texture coordinates, offset by a small amount */
-varying vec2 color_uv1;
-varying vec2 color_uv2;
+out vec2 color_uv1;
+out vec2 color_uv2;
-varying vec2 depth_uv1;
-varying vec2 depth_uv2;
-varying vec2 depth_uv3;
-varying vec2 depth_uv4;
+out vec2 depth_uv1;
+out vec2 depth_uv2;
+out vec2 depth_uv3;
+out vec2 depth_uv4;
//very simple shader for gull screen FX, just pass values on
void vert_generic()
{
- uvcoordsvar = gl_MultiTexCoord0;
- gl_Position = gl_Vertex;
+ uvcoordsvar = vec4(uvs, 0.0, 0.0);
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void vert_dof_first_pass()
{
/* we offset the texture coordinates by 1.5 pixel,
* then we reuse that to sample the surrounding pixels */
- color_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
- color_uv2 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
+ color_uv1 = uvs.xy + vec2(-1.5, -1.5) * invrendertargetdim;
+ color_uv2 = uvs.xy + vec2(0.5, -1.5) * invrendertargetdim;
- depth_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
- depth_uv2 = gl_MultiTexCoord0.xy + vec2(-0.5, -1.5) * invrendertargetdim;
- depth_uv3 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
- depth_uv4 = gl_MultiTexCoord0.xy + vec2(1.5, -1.5) * invrendertargetdim;
+ depth_uv1 = uvs.xy + vec2(-1.5, -1.5) * invrendertargetdim;
+ depth_uv2 = uvs.xy + vec2(-0.5, -1.5) * invrendertargetdim;
+ depth_uv3 = uvs.xy + vec2(0.5, -1.5) * invrendertargetdim;
+ depth_uv4 = uvs.xy + vec2(1.5, -1.5) * invrendertargetdim;
- gl_Position = gl_Vertex;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void vert_dof_fourth_pass()
{
vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
- uvcoordsvar = gl_MultiTexCoord0.xxyy +
+ uvcoordsvar = uvs.xxyy +
halfpixel *
vec4(invrendertargetdim.x,
invrendertargetdim.x,
invrendertargetdim.y,
invrendertargetdim.y);
- gl_Position = gl_Vertex;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void vert_dof_fifth_pass()
@@ -53,8 +56,8 @@ void vert_dof_fifth_pass()
vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
color_uv1 = vec2(0.5, 1.5) * invrendertargetdim;
- uvcoordsvar = gl_MultiTexCoord0;
- gl_Position = gl_Vertex;
+ uvcoordsvar = vec4(uvs, 0.0, 0.0);
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void main()
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
index 1dc49b52be1..7aa6786d292 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
@@ -1,14 +1,17 @@
+uniform mat4 ProjectionMatrix;
+
/* 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. */
#ifdef PERSP_MATRIX
+
/* perspective camera code */
vec3 get_view_space_from_depth(in vec2 uvcoords, in vec3 viewvec_origin, in vec3 viewvec_diff, in float depth)
{
float d = 2.0 * depth - 1.0;
- float zview = -gl_ProjectionMatrix[3][2] / (d + gl_ProjectionMatrix[2][2]);
+ float zview = -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
return zview * (viewvec_origin + vec3(uvcoords, 0.0) * viewvec_diff);
}
@@ -18,7 +21,7 @@ vec4 get_view_space_z_from_depth(in vec4 near, in vec4 range, in vec4 depth)
vec4 d = 2.0 * depth - vec4(1.0);
/* return positive value, so sign differs! */
- return vec4(gl_ProjectionMatrix[3][2]) / (d + vec4(gl_ProjectionMatrix[2][2]));
+ return vec4(ProjectionMatrix[3][2]) / (d + vec4(ProjectionMatrix[2][2]));
}
#else
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
index f19ff4ec65a..4904010c841 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
@@ -1,3 +1,4 @@
+
// color buffer
uniform sampler2D colorbuffer;
@@ -9,8 +10,10 @@ uniform sampler1D ssao_concentric_tex;
// depth buffer
uniform sampler2D depthbuffer;
+
// coordinates on framebuffer in normalized (0.0-1.0) uv space
-varying vec4 uvcoordsvar;
+in vec4 uvcoordsvar;
+out vec4 FragColor;
/* ssao_params.x : pixel scale for the ssao radious */
/* ssao_params.y : factor for the ssao darkening */
@@ -33,7 +36,7 @@ vec3 calculate_view_space_normal(in vec3 viewposition)
float calculate_ssao_factor(float depth)
{
/* take the normalized ray direction here */
- vec2 rotX = texture2D(jitter_tex, uvcoordsvar.xy * ssao_sample_params.yz).rg;
+ vec2 rotX = texture(jitter_tex, uvcoordsvar.xy * ssao_sample_params.yz).rg;
vec2 rotY = vec2(-rotX.y, rotX.x);
/* occlusion is zero in full depth */
@@ -46,9 +49,9 @@ float calculate_ssao_factor(float depth)
/* 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 = gl_ProjectionMatrix[2][3] * position.z + gl_ProjectionMatrix[3][3];
- offset.x = gl_ProjectionMatrix[0][0] * ssao_params.x / homcoord;
- offset.y = gl_ProjectionMatrix[1][1] * ssao_params.x / homcoord;
+ float homcoord = ProjectionMatrix[2][3] * position.z + ProjectionMatrix[3][3];
+ offset.x = ProjectionMatrix[0][0] * ssao_params.x / homcoord;
+ offset.y = ProjectionMatrix[1][1] * ssao_params.x / homcoord;
/* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
offset *= 0.5;
@@ -57,7 +60,7 @@ float calculate_ssao_factor(float depth)
int num_samples = int(ssao_sample_params.x);
for (x = 0; x < num_samples; x++) {
- vec2 dir_sample = texture1D(ssao_concentric_tex, (float(x) + 0.5) / ssao_sample_params.x).rg;
+ vec2 dir_sample = texture(ssao_concentric_tex, (float(x) + 0.5) / ssao_sample_params.x).rg;
/* rotate with random direction to get jittered result */
vec2 dir_jittered = vec2(dot(dir_sample, rotX), dot(dir_sample, rotY));
@@ -67,7 +70,7 @@ float calculate_ssao_factor(float depth)
if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0)
continue;
- float depth_new = texture2D(depthbuffer, uvcoords).r;
+ float depth_new = texture(depthbuffer, uvcoords).r;
if (depth_new != 1.0) {
vec3 pos_new = get_view_space_from_depth(uvcoords, viewvecs[0].xyz, viewvecs[1].xyz, depth_new);
vec3 dir = pos_new - position;
@@ -87,8 +90,8 @@ float calculate_ssao_factor(float depth)
void main()
{
- float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
- vec4 scene_col = texture2D(colorbuffer, uvcoordsvar.xy);
+ float depth = texture(depthbuffer, uvcoordsvar.xy).r;
+ vec4 scene_col = texture(colorbuffer, uvcoordsvar.xy);
vec3 final_color = mix(scene_col.rgb, ssao_color.rgb, calculate_ssao_factor(depth));
- gl_FragColor = vec4(final_color.rgb, scene_col.a);
+ FragColor = vec4(final_color.rgb, scene_col.a);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
deleted file mode 100644
index 5194e414520..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
+++ /dev/null
@@ -1,9 +0,0 @@
-varying vec4 uvcoordsvar;
-
-//very simple shader for full screen FX, just pass values on
-
-void main()
-{
- uvcoordsvar = gl_MultiTexCoord0;
- gl_Position = gl_Vertex;
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_geometry.glsl b/source/blender/gpu/shaders/gpu_shader_geometry.glsl
index fe630dbeddb..7586050b258 100644
--- a/source/blender/gpu/shaders/gpu_shader_geometry.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_geometry.glsl
@@ -1,10 +1,11 @@
+
+uniform mat4 ProjectionMatrix;
+
uniform int PrimitiveIdBase;
uniform int osd_active_uv_offset;
-#if __VERSION__ >= 150
- layout(lines_adjacency) in;
- layout(triangle_strip, max_vertices = 4) out;
-#endif
+layout(lines_adjacency) in;
+layout(triangle_strip, max_vertices = 4) out;
in block {
VertexData v;
@@ -69,7 +70,7 @@ void emit_flat(int index, vec3 normal)
set_mtface_vertex_attrs(st);
- gl_Position = gl_ProjectionMatrix * inpt[index].v.position;
+ gl_Position = ProjectionMatrix * inpt[index].v.position;
EmitVertex();
}
@@ -90,7 +91,7 @@ void emit_smooth(int index)
set_mtface_vertex_attrs(st);
- gl_Position = gl_ProjectionMatrix * inpt[index].v.position;
+ gl_Position = ProjectionMatrix * inpt[index].v.position;
EmitVertex();
}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl
new file mode 100644
index 00000000000..727c3c0a832
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl
@@ -0,0 +1,11 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform vec4 color;
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp).r * color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl
new file mode 100644
index 00000000000..ef8935cc7ba
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl
@@ -0,0 +1,11 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform vec4 color;
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp) * color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl
new file mode 100644
index 00000000000..bcbe1f577fd
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl
@@ -0,0 +1,16 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform float znear;
+uniform float zfar;
+uniform sampler2D image;
+
+void main()
+{
+ float depth = texture(image, texCoord_interp).r;
+
+ /* normalize */
+ fragColor.rgb = vec3((2.0f * znear) / (zfar + znear - (depth * (zfar - znear))));
+ fragColor.a = 1.0f;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
new file mode 100644
index 00000000000..7f3e7df40ac
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
@@ -0,0 +1,34 @@
+
+/* Keep these in sync with GPU_shader.h */
+#define INTERLACE_ROW 0
+#define INTERLACE_COLUMN 1
+#define INTERLACE_CHECKERBOARD 2
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform int interlace_id;
+uniform sampler2DRect image_a;
+uniform sampler2DRect image_b;
+
+bool interlace()
+{
+ if (interlace_id == INTERLACE_CHECKERBOARD) {
+ return (int(gl_FragCoord.x + gl_FragCoord.y) & 1) != 0;
+ }
+ else if (interlace_id == INTERLACE_ROW) {
+ return (int(gl_FragCoord.y) & 1) != 0;
+ }
+ else if (interlace_id == INTERLACE_COLUMN) {
+ return (int(gl_FragCoord.x) & 1) != 0;
+ }
+}
+
+void main()
+{
+ if (interlace()) {
+ fragColor = texture(image_a, texCoord_interp);
+ } else {
+ fragColor = texture(image_b, texCoord_interp);
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl
new file mode 100644
index 00000000000..c2b25cc8011
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl
@@ -0,0 +1,30 @@
+
+/* Display a linear image texture into sRGB space */
+
+uniform sampler2D image;
+
+in vec2 texCoord_interp;
+
+out vec4 fragColor;
+
+float linearrgb_to_srgb(float c)
+{
+ if (c < 0.0031308)
+ return (c < 0.0) ? 0.0 : c * 12.92;
+ else
+ return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
+}
+
+void linearrgb_to_srgb(vec4 col_from, out vec4 col_to)
+{
+ col_to.r = linearrgb_to_srgb(col_from.r);
+ col_to.g = linearrgb_to_srgb(col_from.g);
+ col_to.b = linearrgb_to_srgb(col_from.b);
+ col_to.a = col_from.a;
+}
+
+void main() {
+ fragColor = texture(image, texCoord_interp.st);
+
+ linearrgb_to_srgb(fragColor, fragColor);
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl
new file mode 100644
index 00000000000..4a45d03175e
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl
@@ -0,0 +1,12 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+uniform vec4 color;
+
+void main()
+{
+ fragColor.a = texture(image, texCoord_interp).a * color.a;
+ fragColor.rgb = color.rgb;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl
new file mode 100644
index 00000000000..51092d56e5e
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl
@@ -0,0 +1,12 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform float alpha;
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp);
+ fragColor.a *= alpha;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl
new file mode 100644
index 00000000000..7d9ce9d2003
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl
@@ -0,0 +1,12 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform float alpha;
+uniform sampler2DRect image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp);
+ fragColor.a *= alpha;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl
new file mode 100644
index 00000000000..64662247d69
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl
@@ -0,0 +1,16 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+uniform vec4 color;
+uniform vec4 shuffle;
+
+void main()
+{
+ vec4 sample = texture(image, texCoord_interp);
+ fragColor = vec4(sample.r * shuffle.r +
+ sample.g * shuffle.g +
+ sample.b * shuffle.b +
+ sample.a * shuffle.a) * color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl
new file mode 100644
index 00000000000..74c8f6f3103
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl
@@ -0,0 +1,122 @@
+
+
+/* This shader essentially operates in Object space, where it aligns given geometry with bone, scales it accordingly
+ * to given radii, and then does usual basic solid operations.
+ * Note that if one of head/tail radius is negative, it assumes it only works on the other end of the bone
+ * (used to draw head/tail spheres). */
+
+
+uniform mat4 ViewMatrix;
+uniform mat4 ObjectModelMatrix;
+uniform mat4 ViewProjectionMatrix;
+
+
+/* ---- Instanciated Attribs ---- */
+in vec4 pos; /* w encodes head (== 0.0f), tail (== 1.0f) or in-between. */
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec4 color;
+
+in float radius_head;
+in float radius_tail;
+
+
+out vec3 normal;
+flat out vec4 finalColor;
+
+
+void main()
+{
+ /* We get head/tail in object space. */
+ vec4 head = InstanceModelMatrix * vec4(0.0f, 0.0f, 0.0f, 1.0f);
+ vec4 tail = InstanceModelMatrix * vec4(0.0f, 1.0f, 0.0f, 1.0f);
+
+ /* We need rotation from bone mat, but not scaling. */
+ mat3 bone_mat = mat3(InstanceModelMatrix);
+ bone_mat[0] = normalize(bone_mat[0]);
+ bone_mat[1] = normalize(bone_mat[1]);
+ bone_mat[2] = normalize(bone_mat[2]);
+
+ mat3 nor_mat = transpose(inverse(mat3(ViewMatrix * ObjectModelMatrix) * bone_mat));
+
+ /* Where does this comes from???? Don't know why, but is mandatory anyway... :/ */
+ const float size = 2.0f;
+
+ head.xyz *= size;
+ tail.xyz *= size;
+
+ bool head_only = (radius_tail < 0.0f);
+ bool tail_only = (radius_head < 0.0f);
+ /* == 0: head; == 1: tail; in-between: along bone. */
+ float head_fac = head_only ? 0.0f : (tail_only ? 1.0f : pos.w);
+
+ vec4 ob_pos;
+ vec4 ob_bone_origin;
+ float radius;
+
+ /* head */
+ if (head_fac <= 0.0f) {
+ if (!head_only) {
+ /* We are drawing the body itself, need to adjust start/end positions and radius! */
+ vec3 bone_vec = tail.xyz - head.xyz;
+ float len = length(bone_vec);
+
+ if (len > (radius_head + radius_tail)) {
+ float fac = (len - radius_head) / len;
+ radius = fac * radius_head + (1.0f - fac) * radius_tail;
+ bone_vec /= len;
+ ob_bone_origin = vec4(head.xyz + bone_vec * radius_head * size, 1.0f);
+ }
+ else {
+ radius = (radius_head + radius_tail) / 2.0f;
+ ob_bone_origin = (head + tail) / 2.0f;
+ }
+ }
+ else {
+ radius = radius_head;
+ ob_bone_origin = head;
+ }
+ }
+ /* tail */
+ else if (head_fac >= 1.0f) {
+ if (!tail_only) {
+ /* We are drawing the body itself, need to adjust start/end positions and radius! */
+ vec3 bone_vec = tail.xyz - head.xyz;
+ float len = length(bone_vec);
+
+ if (len > (radius_head + radius_tail)) {
+ float fac = (len - radius_tail) / len;
+ radius = fac * radius_tail + (1.0f - fac) * radius_head;
+ bone_vec /= len;
+ ob_bone_origin = vec4(tail.xyz - bone_vec * radius_tail * size, 1.0f);
+ }
+ else {
+ radius = (radius_head + radius_tail) / 2.0f;
+ ob_bone_origin = (head + tail) / 2.0f;
+ }
+ }
+ else {
+ radius = radius_tail;
+ ob_bone_origin = tail;
+ }
+ }
+ /* Body of the bone */
+#if 0 /* Note: not used currently! */
+ else {
+ float tail_fac = 1.0f - head_fac;
+ radius = radius_head * head_fac + radius_tail * tail_fac;
+ ob_bone_origin = head * head_fac + tail * tail_fac;
+ }
+#endif
+
+ /* Yep, since input pos is unit sphere coordinates, it's also our normal. */
+ vec3 nor = pos.xyz;
+ ob_pos = pos * radius * size;
+ ob_pos.xyz = bone_mat * ob_pos.xyz;
+ ob_pos.w = 1.0f;
+
+ gl_Position = ViewProjectionMatrix * ObjectModelMatrix * (ob_pos + ob_bone_origin);
+ normal = normalize(nor_mat * nor);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_wire_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_wire_vert.glsl
new file mode 100644
index 00000000000..a36eb1dec77
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_wire_vert.glsl
@@ -0,0 +1,103 @@
+
+
+/* This shader takes a 2D shape, puts it in 3D Object space such that is stays aligned with view and bone,
+ * and scales head/tail/distance according to per-instance attributes
+ * (and 'role' of current vertex, encoded in zw input, head or tail, and inner or outer for distance outline).
+ * It is used for both the distance outline drawing, and the wire version of envelope bone.
+ * Note that if one of head/tail radius is negative, it assumes it only works on the other end of the bone
+ * (used to draw head/tail spheres). */
+
+
+uniform mat4 ViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat4 ObjectModelMatrix;
+
+
+/* ---- Instanciated Attribs ---- */
+in vec4 pos; /* z encodes head (== 0.0f), tail (== 1.0f) or in-between; w encodes inner (0.0f) or outer border. */
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec4 color;
+
+in float radius_head;
+in float radius_tail;
+in float distance;
+
+
+flat out vec4 finalColor;
+
+
+void main()
+{
+ /* We get head/tail in object space. */
+ mat4 bone_mat = InstanceModelMatrix;
+ vec4 head = bone_mat * vec4(0.0f, 0.0f, 0.0f, 1.0f);
+ vec4 tail = bone_mat * vec4(0.0f, 1.0f, 0.0f, 1.0f);
+
+ /* We generate our XY axes in object space, Y axis being aligned with bone in view space. */
+ mat4 obview_mat = ViewMatrix * ObjectModelMatrix;
+ mat4 iobview_mat = inverse(obview_mat);
+
+ vec4 view_bone_vec = obview_mat * normalize(tail - head);
+ view_bone_vec.z = 0.0f;
+ if (length(view_bone_vec.xy) <= 1e-5f) {
+ /* A bit weak, but will do the job for now.
+ * Ideally we could compute head/tail radius in view space, and take larger one... */
+ if (view_bone_vec.x > view_bone_vec.y) {
+ view_bone_vec.x = 1e-5f;
+ }
+ else {
+ view_bone_vec.y = 1e-5f;
+ }
+ }
+ vec3 bone_axis_y = normalize((iobview_mat * view_bone_vec).xyz);
+ vec3 bone_axis_x = normalize(cross(bone_axis_y, iobview_mat[2].xyz));
+
+ /* Where does this comes from???? Don't know why, but is mandatory anyway... :/ */
+ float size = 2.0f;
+
+ head.xyz *= size;
+ tail.xyz *= size;
+
+ bool head_only = (radius_tail < 0.0f);
+ bool tail_only = (radius_head < 0.0f);
+ /* == 0: head; == 1: tail; in-between: along bone. */
+ float head_fac = head_only ? 0.0f : (tail_only ? 1.0f : pos.z);
+ bool do_distance_offset = (pos.w != 0.0f) && (distance >= 0.0f);
+
+ vec2 xy_pos = pos.xy;
+ vec4 ob_pos;
+
+ vec4 ob_bone_origin;
+ float radius;
+
+ /* head */
+ if (head_fac <= 0.0f) {
+ radius = radius_head;
+ ob_bone_origin = head;
+ }
+ /* tail */
+ else if (head_fac >= 1.0f) {
+ radius = radius_tail;
+ ob_bone_origin = tail;
+ }
+ /* Body of the bone */
+#if 0 /* Note: not used currently! */
+ else {
+ float tail_fac = 1.0f - head_fac;
+ radius = radius_head * head_fac + radius_tail * tail_fac;
+ ob_bone_origin = head * head_fac + tail * tail_fac;
+ }
+#endif
+
+ if (do_distance_offset) {
+ radius += distance;
+ }
+
+ xy_pos = xy_pos * radius * size;
+
+ ob_pos = ob_bone_origin + vec4(bone_axis_x * xy_pos.x + bone_axis_y * xy_pos.y, 1.0f);
+ gl_Position = ProjectionMatrix * obview_mat * ob_pos;
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl
new file mode 100644
index 00000000000..aec8fd9b0a1
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl
@@ -0,0 +1,50 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in float pos;
+
+/* ---- Per instance Attribs ---- */
+in vec3 color;
+in vec4 corners[2]; /* trouble fetching vec2 */
+in float depth;
+in vec4 tria;
+in mat4 InstanceModelMatrix;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ vec3 pPos;
+
+ if (pos == 1.0) {
+ pPos = vec3(corners[0].xy, depth);
+ }
+ else if (pos == 2.0) {
+ pPos = vec3(corners[0].zw, depth);
+ }
+ else if (pos == 3.0) {
+ pPos = vec3(corners[1].xy, depth);
+ }
+ else if (pos == 4.0) {
+ pPos = vec3(corners[1].zw, depth);
+ }
+ else if (pos == 5.0) {
+ pPos = vec3(tria.xy, depth);
+ }
+ else if (pos == 6.0) {
+ vec2 ofs = tria.xy - corners[0].xy;
+ ofs.x = -ofs.x;
+ pPos = vec3(corners[1].zw + ofs, depth);
+ }
+ else if (pos == 7.0) {
+ pPos = vec3(tria.zw, depth);
+ }
+ else {
+ pPos = vec3(0.0);
+ }
+
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pPos, 1.0);
+
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl
new file mode 100644
index 00000000000..142df70e68a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl
@@ -0,0 +1,25 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+
+/* ---- Per instance Attribs ---- */
+in vec3 color;
+in float start;
+in float end;
+in mat4 InstanceModelMatrix;
+
+uniform float size;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ float len = end - start;
+ vec3 sta = vec3(0.0, 0.0, -start);
+
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos * -len + sta, 1.0);
+ gl_PointSize = size;
+ finalColor = vec4(color, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl
new file mode 100644
index 00000000000..6f580ef3ff6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl
@@ -0,0 +1,57 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. This geometry shader
+// decides which edge type to use if endpoints disagree.
+
+uniform mat4 ProjectionMatrix;
+
+uniform bool drawFront = true;
+uniform bool drawBack = true;
+uniform bool drawSilhouette = true;
+
+layout(lines) in;
+layout(line_strip, max_vertices = 2) out;
+
+in vec4 MV_pos[];
+in float edgeClass[];
+in vec3 fCol[];
+
+flat out vec4 finalColor;
+
+void emitLine(vec4 color)
+{
+ gl_Position = ProjectionMatrix * MV_pos[0];
+ EmitVertex();
+ gl_Position = ProjectionMatrix * MV_pos[1];
+ finalColor = color;
+ EmitVertex();
+ EndPrimitive();
+}
+
+void main()
+{
+ float finalEdgeClass = max(edgeClass[0], edgeClass[1]);
+
+ if (finalEdgeClass > 0.0f) {
+ // front-facing edge
+ if (drawFront)
+ emitLine(vec4(fCol[0], 0.75));
+ }
+ else if (finalEdgeClass < 0.0f) {
+ // back-facing edge
+ if (drawBack)
+ emitLine(vec4(fCol[0], 0.5));
+ }
+ else {
+ // exactly one face is front-facing, silhouette edge
+ if (drawSilhouette)
+ emitLine(vec4(fCol[0], 1.0));
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl
new file mode 100644
index 00000000000..fa30c9fb1ed
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl
@@ -0,0 +1,63 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. We use a geometry
+// shader to resolve this properly.
+
+uniform mat4 ViewMatrix;
+uniform mat4 ProjectionMatrix;
+
+in vec3 pos;
+in vec3 N1, N2; // normals of faces this edge joins (object coords)
+
+/* instance attrib */
+in vec3 color;
+in mat4 InstanceModelMatrix;
+
+out vec4 MV_pos;
+out float edgeClass;
+out vec3 fCol;
+
+// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
+
+bool front(mat3 NormalMatrix, vec3 N, vec3 eye)
+{
+ return dot(NormalMatrix * N, eye) > 0.0;
+}
+
+void main()
+{
+ vec3 eye;
+
+ mat4 ModelViewMatrix = ViewMatrix * InstanceModelMatrix;
+
+ MV_pos = ModelViewMatrix * vec4(pos, 1.0);
+
+ mat3 NormalMatrix = transpose(inverse(mat3(ModelViewMatrix)));
+
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ eye = normalize(-MV_pos.xyz);
+ }
+ else {
+ eye = vec3(0.0, 0.0, 1.0);
+ }
+
+ bool face_1_front = front(NormalMatrix, N1, eye);
+ bool face_2_front = front(NormalMatrix, N2, eye);
+
+ if (face_1_front && face_2_front)
+ edgeClass = 1.0; // front-facing edge
+ else if (face_1_front || face_2_front)
+ edgeClass = 0.0; // exactly one face is front-facing, silhouette edge
+ else
+ edgeClass = -1.0; // back-facing edge
+
+ fCol = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl
new file mode 100644
index 00000000000..819199c26c7
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl
@@ -0,0 +1,36 @@
+
+/* This shader takes a 2D shape, puts it in 3D Object space such that is stays aligned with view,
+ * and scales the shape according to per-instance attributes
+ * Note that if the stiffness is zero, it assumes the scale is directly multiplied by the radius */
+
+
+ #define M_PI_2 1.570796f // pi/2
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screen_vecs[2];
+
+/* ---- Instanciated Attribs ---- */
+in vec2 pos;
+
+/* ---- Per instance Attribs ---- */
+in mat3x4 ScaleTranslationMatrix;
+in float radius;
+in vec3 color;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ mat3 Scamat = mat3(ScaleTranslationMatrix);
+ vec4 world_pos = vec4(
+ ScaleTranslationMatrix[0][3],
+ ScaleTranslationMatrix[1][3],
+ ScaleTranslationMatrix[2][3],
+ 1.0);
+
+ vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y;
+ world_pos.xyz += Scamat * (screen_pos * radius);
+
+ gl_Position = ViewProjectionMatrix * world_pos;
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl
new file mode 100644
index 00000000000..195d4849d99
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ViewMatrix;
+uniform mat4 ViewProjectionMatrix;
+uniform mat4 ObjectModelMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+in vec3 nor;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec4 color;
+
+out vec3 normal;
+flat out vec4 finalColor;
+
+void main()
+{
+ mat4 FinalModelMatrix = ObjectModelMatrix * InstanceModelMatrix;
+ mat4 ModelViewProjectionMatrix = ViewProjectionMatrix * FinalModelMatrix;
+ /* This is slow and run per vertex, but it's still faster than
+ * doing it per instance on CPU and sending it on via instance attrib */
+ mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * FinalModelMatrix)));
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ normal = NormalMatrix * nor;
+
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl
new file mode 100644
index 00000000000..2ee74b3eae0
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl
@@ -0,0 +1,32 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screen_vecs[2];
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos; /* using Z as axis id */
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec3 color;
+in float size;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ vec3 offset = vec3(0.0);
+
+#ifdef AXIS_NAME
+ if (pos.z == 0.0)
+ offset = vec3(1.125, 0.0, 0.0);
+ else if (pos.z == 1.0)
+ offset = vec3(0.0, 1.125, 0.0);
+ else
+ offset = vec3(0.0, 0.0, 1.125);
+ offset *= size;
+#endif
+
+ vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y;
+ gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(offset, 1.0) + vec4(screen_pos * size, 0.0));
+ finalColor = vec4(color, 1.0);
+}
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..10a2ba61a2c
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl
@@ -0,0 +1,22 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec3 color;
+#ifdef UNIFORM_SCALE
+in float size;
+#else
+in vec3 size;
+#endif
+
+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..7f445369833
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl
@@ -0,0 +1,31 @@
+
+in vec4 radii;
+in vec4 finalColor;
+in vec4 finalOutlineColor;
+out vec4 fragColor;
+
+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(finalOutlineColor.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..c49832bf9b4
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl
@@ -0,0 +1,34 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+const float pixel_fudge = sqrt(2.0);
+const float outline_width = 1.15 * pixel_fudge;
+
+in vec2 pos;
+in float size;
+in vec4 color;
+in vec4 outlineColor;
+out vec4 finalColor;
+out vec4 finalOutlineColor;
+out vec4 radii;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+
+ // pass through unchanged
+ gl_PointSize = size + pixel_fudge; // 0.5 pixel_fudge on either side
+ 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 0a63fc216a0..9d22fbba65e 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1,11 +1,57 @@
+
+uniform mat4 ModelViewMatrix;
+#ifndef EEVEE_ENGINE
+uniform mat4 ProjectionMatrix;
+uniform mat4 ViewMatrixInverse;
+uniform mat4 ViewMatrix;
+#endif
+uniform mat4 ModelMatrix;
+uniform mat4 ModelMatrixInverse;
+uniform mat4 ModelViewMatrixInverse;
+uniform mat4 ProjectionMatrixInverse;
+uniform mat3 NormalMatrix;
+uniform vec4 CameraTexCoFactors;
+
+/* Old glsl mode compat. */
+
+#ifndef CLOSURE_DEFAULT
+
+struct Closure {
+ vec3 radiance;
+ float opacity;
+};
+
+#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0)
+
+Closure closure_mix(Closure cl1, Closure cl2, float fac)
+{
+ Closure cl;
+ cl.radiance = mix(cl1.radiance, cl2.radiance, fac);
+ cl.opacity = mix(cl1.opacity, cl2.opacity, fac);
+ return cl;
+}
+
+Closure closure_add(Closure cl1, Closure cl2)
+{
+ Closure cl;
+ cl.radiance = cl1.radiance + cl2.radiance;
+ cl.opacity = cl1.opacity + cl2.opacity;
+ return cl;
+}
+
+Closure nodetree_exec(void); /* Prototype */
+
+#endif /* CLOSURE_DEFAULT */
+
+
/* Converters */
float convert_rgba_to_float(vec4 color)
{
#ifdef USE_NEW_SHADING
- return color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722;
+ return dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
#else
- return (color.r + color.g + color.b) / 3.0;
+ return (color.r + color.g + color.b) * 0.333333;
#endif
}
@@ -53,7 +99,7 @@ void rgb_to_hsv(vec4 rgb, out vec4 outcol)
h = 0.0;
}
else {
- c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta;
+ c = (vec3(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];
@@ -155,15 +201,18 @@ void color_to_blender_normal_new_shading(vec3 color, out vec3 normal)
normal.y = -2.0 * ((color.g) - 0.5);
normal.z = -2.0 * ((color.b) - 0.5);
}
-
+#ifndef M_PI
#define M_PI 3.14159265358979323846
-#define M_1_PI 0.31830988618379069
+#endif
+#ifndef M_1_PI
+#define M_1_PI 0.318309886183790671538
+#endif
/*********** SHADER NODES ***************/
void vcol_attribute(vec4 attvcol, out vec4 vcol)
{
- vcol = vec4(attvcol.x, attvcol.y, attvcol.z, 1.0);
+ vcol = vec4(attvcol.xyz, 1.0);
}
void uv_attribute(vec2 attuv, out vec3 uv)
@@ -177,7 +226,7 @@ void geom(
out vec3 normal, out vec4 vcol, out float vcol_alpha, out float frontback)
{
local = co;
- view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(local) : vec3(0.0, 0.0, -1.0);
+ view = (ProjectionMatrix[3][3] == 0.0) ? normalize(local) : vec3(0.0, 0.0, -1.0);
global = (viewinvmat * vec4(local, 1.0)).xyz;
orco = attorco;
uv_attribute(attuv, uv);
@@ -419,13 +468,13 @@ void squeeze(float val, float width, float center, out float outval)
void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
{
outvec = v1 + v2;
- outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) / 3.0;
+ outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333;
}
void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
{
outvec = v1 - v2;
- outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) / 3.0;
+ outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333;
}
void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
@@ -441,7 +490,7 @@ void vec_math_mix(float strength, vec3 v1, vec3 v2, out vec3 outvec)
void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
{
- outvec = vec3(0, 0, 0);
+ outvec = vec3(0);
outval = dot(v1, v2);
}
@@ -483,9 +532,9 @@ void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
{
- outvec.x = texture2D(curvemap, vec2((vec.x + 1.0) * 0.5, 0.0)).x;
- outvec.y = texture2D(curvemap, vec2((vec.y + 1.0) * 0.5, 0.0)).y;
- outvec.z = texture2D(curvemap, vec2((vec.z + 1.0) * 0.5, 0.0)).z;
+ outvec.x = texture(curvemap, vec2((vec.x + 1.0) * 0.5, 0.0)).x;
+ outvec.y = texture(curvemap, vec2((vec.y + 1.0) * 0.5, 0.0)).y;
+ outvec.z = texture(curvemap, vec2((vec.z + 1.0) * 0.5, 0.0)).z;
if (fac != 1.0)
outvec = (outvec * fac) + (vec * (1.0 - fac));
@@ -494,9 +543,9 @@ void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
void curves_rgb(float fac, vec4 col, sampler2D curvemap, out vec4 outcol)
{
- outcol.r = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.r, 0.0)).a, 0.0)).r;
- outcol.g = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.g, 0.0)).a, 0.0)).g;
- outcol.b = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.b, 0.0)).a, 0.0)).b;
+ outcol.r = texture(curvemap, vec2(texture(curvemap, vec2(col.r, 0.0)).a, 0.0)).r;
+ outcol.g = texture(curvemap, vec2(texture(curvemap, vec2(col.g, 0.0)).a, 0.0)).g;
+ outcol.b = texture(curvemap, vec2(texture(curvemap, vec2(col.b, 0.0)).a, 0.0)).b;
if (fac != 1.0)
outcol = (outcol * fac) + (col * (1.0 - fac));
@@ -816,22 +865,23 @@ void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha)
{
- outcol = texture2D(colormap, vec2(fac, 0.0));
+ outcol = texture(colormap, vec2(fac, 0.0));
outalpha = outcol.a;
}
void rgbtobw(vec4 color, out float outval)
{
#ifdef USE_NEW_SHADING
- outval = color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722;
+ vec3 factors = vec3(0.2126, 0.7152, 0.0722);
#else
- outval = color.r * 0.35 + color.g * 0.45 + color.b * 0.2; /* keep these factors in sync with texture.h:RGBTOBW */
+ vec3 factors = vec3(0.35, 0.45, 0.2); /* keep these factors in sync with texture.h:RGBTOBW */
#endif
+ outval = dot(color.rgb, factors);
}
void invert(float fac, vec4 col, out vec4 outcol)
{
- outcol.xyz = mix(col.xyz, vec3(1.0, 1.0, 1.0) - col.xyz, fac);
+ outcol.xyz = mix(col.xyz, vec3(1.0) - col.xyz, fac);
outcol.w = col.w;
}
@@ -916,12 +966,12 @@ void texture_flip_blend(vec3 vec, out vec3 outvec)
void texture_blend_lin(vec3 vec, out float outval)
{
- outval = (1.0 + vec.x) / 2.0;
+ outval = (1.0 + vec.x) * 0.5;
}
void texture_blend_quad(vec3 vec, out float outval)
{
- outval = max((1.0 + vec.x) / 2.0, 0.0);
+ outval = max((1.0 + vec.x) * 0.5, 0.0);
outval *= outval;
}
@@ -932,12 +982,12 @@ void texture_wood_sin(vec3 vec, out float value, out vec4 color, out vec3 normal
value = wi;
color = vec4(wi, wi, wi, 1.0);
- normal = vec3(0.0, 0.0, 0.0);
+ normal = vec3(0.0);
}
void texture_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal)
{
- color = texture2D(ima, (vec.xy + vec2(1.0, 1.0)) * 0.5);
+ color = texture(ima, (vec.xy + vec2(1.0)) * 0.5);
value = color.a;
normal.x = 2.0 * (color.r - 0.5);
@@ -955,7 +1005,7 @@ void texco_orco(vec3 attorco, out vec3 orco)
void texco_uv(vec2 attuv, out vec3 uv)
{
/* disabled for now, works together with leaving out mtex_2d_mapping
- uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0); */
+ uv = vec3(attuv * 2.0 - vec2(1.0), 0.0); */
uv = vec3(attuv, 0.0);
}
@@ -1277,11 +1327,7 @@ void mtex_har_divide(float har, out float outhar)
void mtex_har_multiply_clamp(float har, out float outhar)
{
- har *= 128.0;
-
- if (har < 1.0) outhar = 1.0;
- else if (har > 511.0) outhar = 511.0;
- else outhar = har;
+ outhar = clamp(har * 128.0, 1.0, 511.0);
}
void mtex_alpha_from_col(vec4 col, out float alpha)
@@ -1350,14 +1396,14 @@ vec3 mtex_2d_mapping(vec3 vec)
void mtex_cube_map(vec3 co, samplerCube ima, out float value, out vec4 color)
{
- color = textureCube(ima, co);
+ color = texture(ima, co);
value = 1.0;
}
void mtex_cube_map_refl_from_refldir(
samplerCube ima, vec3 reflecteddirection, out float value, out vec4 color)
{
- color = textureCube(ima, reflecteddirection);
+ color = texture(ima, reflecteddirection);
value = color.a;
}
@@ -1368,13 +1414,13 @@ void mtex_cube_map_refl(
vec3 viewdirection = vec3(viewmatrixinverse * vec4(vp, 0.0));
vec3 normaldirection = normalize(vec3(vec4(vn, 0.0) * viewmatrix));
vec3 reflecteddirection = reflect(viewdirection, normaldirection);
- color = textureCube(ima, reflecteddirection);
+ color = texture(ima, reflecteddirection);
value = 1.0;
}
void mtex_image(vec3 texco, sampler2D ima, out float value, out vec4 color)
{
- color = texture2D(ima, texco.xy);
+ color = texture(ima, texco.xy);
value = 1.0;
}
@@ -1385,7 +1431,7 @@ void mtex_normal(vec3 texco, sampler2D ima, out vec3 normal)
// It needs to be done because in Blender
// the normal used points inward.
// Should this ever change this negate must be removed.
- vec4 color = texture2D(ima, texco.xy);
+ vec4 color = texture(ima, texco.xy);
normal = 2.0 * (vec3(-color.r, color.g, color.b) - vec3(-0.5, 0.5, 0.5));
}
@@ -1413,8 +1459,8 @@ void mtex_bump_init_objspace(
out float fPrevMagnitude_out, out vec3 vNacc_out,
out vec3 vR1, out vec3 vR2, out float fDet)
{
- mat3 obj2view = to_mat3(gl_ModelViewMatrix);
- mat3 view2obj = to_mat3(gl_ModelViewMatrixInverse);
+ mat3 obj2view = to_mat3(ModelViewMatrix);
+ mat3 view2obj = to_mat3(ModelViewMatrixInverse);
vec3 vSigmaS = view2obj * dFdx(surf_pos);
vec3 vSigmaT = view2obj * dFdy(surf_pos);
@@ -1481,9 +1527,9 @@ void mtex_bump_tap3(
vec2 STul = texco.xy + dFdy(texco.xy);
float Hll, Hlr, Hul;
- rgbtobw(texture2D(ima, STll), Hll);
- rgbtobw(texture2D(ima, STlr), Hlr);
- rgbtobw(texture2D(ima, STul), Hul);
+ rgbtobw(texture(ima, STll), Hll);
+ rgbtobw(texture(ima, STlr), Hlr);
+ rgbtobw(texture(ima, STul), Hul);
dBs = hScale * (Hlr - Hll);
dBt = hScale * (Hul - Hll);
@@ -1508,10 +1554,10 @@ void mtex_bump_bicubic(
vec2 STd = texco.xy - 0.5 * TexDy;
vec2 STu = texco.xy + 0.5 * TexDy;
- rgbtobw(texture2D(ima, STl), Hl);
- rgbtobw(texture2D(ima, STr), Hr);
- rgbtobw(texture2D(ima, STd), Hd);
- rgbtobw(texture2D(ima, STu), Hu);
+ rgbtobw(texture(ima, STl), Hl);
+ rgbtobw(texture(ima, STr), Hr);
+ rgbtobw(texture(ima, STd), Hd);
+ rgbtobw(texture(ima, STu), Hu);
vec2 dHdxy = vec2(Hr - Hl, Hu - Hd);
float fBlend = clamp(1.0 - textureQueryLOD(ima, texco.xy).x, 0.0, 1.0);
@@ -1597,11 +1643,11 @@ void mtex_bump_tap5(
vec2 STu = texco.xy + 0.5 * TexDy;
float Hc, Hl, Hr, Hd, Hu;
- rgbtobw(texture2D(ima, STc), Hc);
- rgbtobw(texture2D(ima, STl), Hl);
- rgbtobw(texture2D(ima, STr), Hr);
- rgbtobw(texture2D(ima, STd), Hd);
- rgbtobw(texture2D(ima, STu), Hu);
+ rgbtobw(texture(ima, STc), Hc);
+ rgbtobw(texture(ima, STl), Hl);
+ rgbtobw(texture(ima, STr), Hr);
+ rgbtobw(texture(ima, STd), Hd);
+ rgbtobw(texture(ima, STu), Hu);
dBs = hScale * (Hr - Hl);
dBt = hScale * (Hu - Hd);
@@ -1618,7 +1664,7 @@ void mtex_bump_deriv(
// this variant using a derivative map is described here
// http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html
vec2 dim = vec2(ima_x, ima_y);
- vec2 dBduv = hScale * dim * (2.0 * texture2D(ima, texco.xy).xy - 1.0);
+ vec2 dBduv = hScale * dim * (2.0 * texture(ima, texco.xy).xy - 1.0);
dBs = dBduv.x * TexDx.x + s * dBduv.y * TexDx.y;
dBt = dBduv.x * TexDy.x + s * dBduv.y * TexDy.y;
@@ -1670,7 +1716,7 @@ void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal)
void mtex_nspace_object(vec3 texnormal, out vec3 outnormal)
{
- outnormal = normalize(gl_NormalMatrix * texnormal);
+ outnormal = normalize(NormalMatrix * texnormal);
}
void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal)
@@ -1727,7 +1773,7 @@ void lamp_falloff_invcoefficients(float coeff_const, float coeff_lin, float coef
void lamp_falloff_curve(float lampdist, sampler2D curvemap, float dist, out float visifac)
{
- visifac = texture2D(curvemap, vec2(dist / lampdist, 0.0)).x;
+ visifac = texture(curvemap, vec2(dist / lampdist, 0.0)).x;
}
void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac)
@@ -1794,7 +1840,7 @@ void lamp_visibility_clamp(float visifac, out float outvisifac)
void world_paper_view(vec3 vec, out vec3 outvec)
{
vec3 nvec = normalize(vec);
- outvec = (gl_ProjectionMatrix[3][3] == 0.0) ? vec3(nvec.x, 0.0, nvec.y) : vec3(0.0, 0.0, -1.0);
+ outvec = (ProjectionMatrix[3][3] == 0.0) ? vec3(nvec.x, 0.0, nvec.y) : vec3(0.0, 0.0, -1.0);
}
void world_zen_mapping(vec3 view, float zenup, float zendown, out float zenfac)
@@ -1828,7 +1874,7 @@ void world_blend(vec3 vec, out float blend)
void shade_view(vec3 co, out vec3 view)
{
/* handle perspective/orthographic */
- view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(co) : vec3(0.0, 0.0, -1.0);
+ view = (ProjectionMatrix[3][3] == 0.0) ? normalize(co) : vec3(0.0, 0.0, -1.0);
}
void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn)
@@ -2020,7 +2066,7 @@ void shade_add_to_diffuse(float i, vec3 lampcol, vec3 col, out vec3 outcol)
if (i > 0.0)
outcol = i * lampcol * col;
else
- outcol = vec3(0.0, 0.0, 0.0);
+ outcol = vec3(0.0);
}
void shade_hemi_spec(vec3 vn, vec3 lv, vec3 view, float spec, float hard, float visifac, out float t)
@@ -2177,12 +2223,12 @@ void shade_madd(vec4 col, vec4 col1, vec4 col2, out vec4 outcol)
void shade_add_clamped(vec4 col1, vec4 col2, out vec4 outcol)
{
- outcol = col1 + max(col2, vec4(0.0, 0.0, 0.0, 0.0));
+ outcol = col1 + max(col2, vec4(0.0));
}
void shade_madd_clamped(vec4 col, vec4 col1, vec4 col2, out vec4 outcol)
{
- outcol = col + max(col1 * col2, vec4(0.0, 0.0, 0.0, 0.0));
+ outcol = col + max(col1 * col2, vec4(0.0));
}
void env_apply(vec4 col, vec3 hor, vec3 zen, vec4 f, mat4 vm, vec3 vn, out vec4 outcol)
@@ -2219,7 +2265,7 @@ void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
void ramp_rgbtobw(vec3 color, out float outval)
{
- outval = color.r * 0.3 + color.g * 0.58 + color.b * 0.12;
+ outval = dot(color, vec3(0.3, 0.58, 0.12));
}
void shade_only_shadow(float i, float shadfac, float energy, vec3 shadcol, out vec3 outshadrgb)
@@ -2255,10 +2301,12 @@ void test_shadowbuf(
//float bias = (1.5 - inp*inp)*shadowbias;
co.z -= shadowbias * co.w;
- if (co.w > 0.0 && co.x > 0.0 && co.x / co.w < 1.0 && co.y > 0.0 && co.y / co.w < 1.0)
- result = shadow2DProj(shadowmap, co).x;
- else
+ if (co.w > 0.0 && co.x > 0.0 && co.x / co.w < 1.0 && co.y > 0.0 && co.y / co.w < 1.0) {
+ result = textureProj(shadowmap, co);
+ }
+ else {
result = 1.0;
+ }
}
}
@@ -2272,7 +2320,7 @@ void test_shadowbuf_vsm(
else {
vec4 co = shadowpersmat * vec4(rco, 1.0);
if (co.w > 0.0 && co.x > 0.0 && co.x / co.w < 1.0 && co.y > 0.0 && co.y / co.w < 1.0) {
- vec2 moments = texture2DProj(shadowmap, co).rg;
+ vec2 moments = textureProj(shadowmap, co).rg;
float dist = co.z / co.w;
float p = 0.0;
@@ -2331,7 +2379,7 @@ void shade_light_texture(vec3 rco, sampler2D cookie, mat4 shadowpersmat, out vec
vec4 co = shadowpersmat * vec4(rco, 1.0);
- result = texture2DProj(cookie, co);
+ result = textureProj(cookie, co);
}
void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outcol)
@@ -2346,7 +2394,7 @@ void shade_mist_factor(
if (enable == 1.0) {
float fac, zcor;
- zcor = (gl_ProjectionMatrix[3][3] == 0.0) ? length(co) : -co[2];
+ zcor = (ProjectionMatrix[3][3] == 0.0) ? length(co) : -co[2];
fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0);
if (misttype == 0.0) fac *= fac;
@@ -2421,7 +2469,15 @@ float hypot(float x, float y)
void generated_from_orco(vec3 orco, out vec3 generated)
{
- generated = orco * 0.5 + vec3(0.5);
+#ifdef VOLUMETRICS
+#ifdef MESH_SHADER
+ generated = volumeObjectLocalCoord;
+#else
+ generated = worldPosition;
+#endif
+#else
+ generated = orco;
+#endif
}
int floor_to_int(float x)
@@ -2434,7 +2490,6 @@ int quick_floor(float x)
return int(x) - ((x < 0) ? 1 : 0);
}
-#ifdef BIT_OPERATIONS
float integer_noise(int n)
{
int nn;
@@ -2499,7 +2554,6 @@ vec3 cellnoise_color(vec3 p)
return vec3(r, g, b);
}
-#endif // BIT_OPERATIONS
float floorfrac(float x, out int i)
{
@@ -2561,41 +2615,107 @@ vec3 rotate_vector(vec3 p, vec3 n, float theta) {
);
}
+void prepare_tangent(
+ float anisotropic, float anisotropic_rotation, float roughness, vec3 N, vec3 T,
+ out vec3 X, out vec3 Y, out float ax, out float ay)
+{
+ /* rotate tangent */
+ if (anisotropic_rotation != 0.0) {
+ T = rotate_vector(T, N, anisotropic_rotation * 2.0 * M_PI);
+ }
+
+ Y = normalize(cross(T, N));
+
+ float aspect = sqrt(1.0 - anisotropic * 0.9);
+ float a = sqr(roughness);
+ ax = max(0.001, a / aspect);
+ ay = max(0.001, a * aspect);
+}
+
+void convert_metallic_to_specular(vec3 basecol, float metallic, float specular_fac, out vec3 diffuse, out vec3 f0)
+{
+ vec3 dielectric = vec3(0.034) * specular_fac * 2.0;
+ diffuse = mix(basecol, vec3(0.0), metallic);
+ f0 = mix(dielectric, basecol, metallic);
+}
+
+void convert_metallic_to_specular_tinted(
+ vec3 basecol, float metallic, float specular_fac, float specular_tint,
+ out vec3 diffuse, out vec3 f0)
+{
+ vec3 dielectric = vec3(0.034) * specular_fac * 2.0;
+ float lum = dot(basecol, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
+ vec3 tint = lum > 0 ? basecol / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
+ f0 = mix(dielectric * mix(vec3(1.0), tint, specular_tint), basecol, metallic);
+ diffuse = mix(basecol, vec3(0.0), metallic);
+}
/*********** NEW SHADER NODES ***************/
#define NUM_LIGHTS 3
-/* bsdfs */
+struct glLight {
+ vec4 position;
+ vec4 diffuse;
+ vec4 specular;
+ vec4 halfVector;
+};
-void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out vec4 result)
-{
+layout(std140) uniform lightSource {
+ glLight glLightSource[NUM_LIGHTS];
+};
+
+#ifndef VOLUMETRICS
+/* bsdfs */
+void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
+{
+#ifdef EEVEE_ENGINE
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance);
+ result.radiance *= color.rgb;
+#else
/* ambient light */
vec3 L = vec3(0.2);
/* directional lights */
for (int i = 0; i < NUM_LIGHTS; i++) {
- vec3 light_position = gl_LightSource[i].position.xyz;
- vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
+ vec3 light_position = glLightSource[i].position.xyz;
+ vec3 light_diffuse = glLightSource[i].diffuse.rgb;
float bsdf = max(dot(N, light_position), 0.0);
L += light_diffuse * bsdf;
}
- result = vec4(L * color.rgb, 1.0);
+ result = Closure(L * color.rgb, 1.0);
+#endif
}
-void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result)
+void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result)
{
+#ifdef EEVEE_ENGINE
+ vec3 out_spec, ssr_spec;
+ roughness = sqrt(roughness);
+ eevee_closure_glossy(N, vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec * color.rgb;
+ result.ssr_data = vec4(ssr_spec * color.rgb, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
+#else
/* ambient light */
vec3 L = vec3(0.2);
+ direction_transform_m4v3(N, ViewMatrix, N);
+
/* directional lights */
for (int i = 0; i < NUM_LIGHTS; i++) {
- vec3 light_position = gl_LightSource[i].position.xyz;
- vec3 H = gl_LightSource[i].halfVector.xyz;
- vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
- vec3 light_specular = gl_LightSource[i].specular.rgb;
+ vec3 light_position = glLightSource[i].position.xyz;
+ vec3 H = glLightSource[i].halfVector.xyz;
+ vec3 light_diffuse = glLightSource[i].diffuse.rgb;
+ vec3 light_specular = glLightSource[i].specular.rgb;
/* we mix in some diffuse so low roughness still shows up */
float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / roughness);
@@ -2603,30 +2723,52 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result)
L += light_specular * bsdf;
}
- result = vec4(L * color.rgb, 1.0);
+ result = Closure(L * color.rgb, 1.0);
+#endif
}
void node_bsdf_anisotropic(
vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T,
- out vec4 result)
+ out Closure result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
-void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, out vec4 result)
-{
+void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result)
+{
+#ifdef EEVEE_ENGINE
+ vec3 out_spec, out_refr, ssr_spec;
+ roughness = sqrt(roughness);
+ vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : color.rgb; /* Simulate 2 transmission event */
+ eevee_closure_glass(N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
+ out_refr *= refr_color;
+ out_spec *= color.rgb;
+ float fresnel = F_eta(ior, dot(N, cameraVec));
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.radiance = mix(out_refr, out_spec, fresnel);
+ result.ssr_data = vec4(ssr_spec * color.rgb * fresnel, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
+#else
node_bsdf_diffuse(color, 0.0, N, result);
+#endif
}
-void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 result)
+void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
+#ifndef EEVEE_ENGINE
void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
- float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result)
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out Closure result)
{
+ vec3 X, Y;
+ float ax, ay;
+ prepare_tangent(anisotropic, anisotropic_rotation, roughness, N, T, X, Y, ax, ay);
+
/* ambient light */
// TODO: set ambient light to an appropriate value
vec3 L = mix(0.1, 0.03, metallic) * mix(base_color.rgb, subsurface_color.rgb, subsurface * (1.0 - metallic));
@@ -2634,28 +2776,7 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad
float eta = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0;
/* set the viewing vector */
- vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? -normalize(I) : vec3(0.0, 0.0, 1.0);
-
- /* get the tangent */
- vec3 Tangent = T;
- if (T == vec3(0.0)) {
- // if no tangent is set, use a default tangent
- if(N.x != N.y || N.x != N.z) {
- Tangent = vec3(N.z-N.y, N.x-N.z, N.y-N.x); // (1,1,1) x N
- }
- else {
- Tangent = vec3(N.z-N.y, N.x+N.z, -N.y-N.x); // (-1,1,1) x N
- }
- }
-
- /* rotate tangent */
- if (anisotropic_rotation != 0.0) {
- Tangent = rotate_vector(Tangent, N, anisotropic_rotation * 2.0 * M_PI);
- }
-
- /* calculate the tangent and bitangent */
- vec3 Y = normalize(cross(N, Tangent));
- vec3 X = cross(Y, N);
+ vec3 V = (ProjectionMatrix[3][3] == 0.0) ? -normalize(I) : vec3(0.0, 0.0, 1.0);
/* fresnel normalization parameters */
float F0 = fresnel_dielectric_0(eta);
@@ -2663,13 +2784,13 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad
/* directional lights */
for (int i = 0; i < NUM_LIGHTS; i++) {
- vec3 light_position_world = gl_LightSource[i].position.xyz;
+ vec3 light_position_world = glLightSource[i].position.xyz;
vec3 light_position = normalize(light_position_world);
vec3 H = normalize(light_position + V);
- vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
- vec3 light_specular = gl_LightSource[i].specular.rgb;
+ vec3 light_diffuse = glLightSource[i].diffuse.rgb;
+ vec3 light_specular = glLightSource[i].specular.rgb;
float NdotL = dot(N, light_position);
float NdotV = dot(N, V);
@@ -2679,7 +2800,7 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad
if (NdotL >= 0.0 && NdotV >= 0.0) {
float NdotH = dot(N, H);
- float Cdlum = 0.3 * base_color.r + 0.6 * base_color.g + 0.1 * base_color.b; // luminance approx.
+ float Cdlum = dot(base_color.rgb, vec3(0.3, 0.6, 0.1)); // luminance approx.
vec3 Ctint = Cdlum > 0 ? base_color.rgb / Cdlum : vec3(1.0); // normalize lum. to isolate hue+sat
vec3 Cspec0 = mix(specular * 0.08 * mix(vec3(1.0), Ctint, specular_tint), base_color.rgb, metallic);
@@ -2700,10 +2821,6 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad
float ss = 1.25 * (Fss * (1.0 / (NdotL + NdotV) - 0.5) + 0.5);
// specular
- float aspect = sqrt(1.0 - anisotropic * 0.9);
- float a = sqr(roughness);
- float ax = max(0.001, a / aspect);
- float ay = max(0.001, a * aspect);
float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay); //GTR2(NdotH, a);
float FH = (fresnel_dielectric_cos(LdotH, eta) - F0) * F0_norm;
vec3 Fs = mix(Cspec0, vec3(1.0), FH);
@@ -2739,83 +2856,232 @@ void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_rad
L += diffuse_and_specular_bsdf + clearcoat_bsdf;
}
- result = vec4(L, 1.0);
+ result = Closure(L, 1.0);
}
+#endif
-void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result)
+void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
+ float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id,
+ float sss_id, vec3 sss_scale, out Closure result)
{
- node_bsdf_diffuse(color, 0.0, N, result);
+#ifdef EEVEE_ENGINE
+ metallic = saturate(metallic);
+ transmission = saturate(transmission);
+
+ vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec;
+ convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0);
+
+ transmission *= 1.0 - metallic;
+ subsurface *= 1.0 - metallic;
+
+ clearcoat *= 0.25;
+ clearcoat *= 1.0 - transmission;
+
+#ifdef USE_SSS
+ diffuse = mix(diffuse, vec3(0.0), subsurface);
+#else
+ diffuse = mix(diffuse, subsurface_color.rgb, subsurface);
+#endif
+ f0 = mix(f0, vec3(1.0), transmission);
+
+ float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0));
+ eevee_closure_principled(N, diffuse, f0, int(ssr_id), roughness,
+ CN, clearcoat, clearcoat_roughness, 1.0, sss_scalef, ior,
+ out_diff, out_trans, out_spec, out_refr, ssr_spec);
+
+ vec3 refr_color = base_color.rgb;
+ refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission event */
+
+ float fresnel = F_eta(ior, dot(N, cameraVec));
+ vec3 refr_spec_color = base_color.rgb * fresnel;
+ /* This bit maybe innacurate. */
+ out_refr = out_refr * refr_color * (1.0 - fresnel) + out_spec * refr_spec_color;
+
+ ssr_spec = mix(ssr_spec, refr_spec_color, transmission);
+
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec + out_diff * diffuse;
+ result.radiance = mix(result.radiance, out_refr, transmission);
+ result.ssr_data = vec4(ssr_spec, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
+#ifdef USE_SSS
+ result.sss_data.a = sss_scalef;
+ result.sss_data.rgb = out_diff + out_trans;
+#ifdef USE_SSS_ALBEDO
+ result.sss_albedo.rgb = mix(vec3(0.0), subsurface_color.rgb, subsurface);
+#else
+ result.sss_data.rgb *= mix(vec3(0.0), subsurface_color.rgb, subsurface);
+#endif
+ result.sss_data.rgb *= (1.0 - transmission);
+#endif
+
+#else
+ node_bsdf_principled(base_color, subsurface, subsurface_radius, subsurface_color, metallic, specular,
+ specular_tint, roughness, anisotropic, anisotropic_rotation, sheen, sheen_tint, clearcoat,
+ clearcoat_roughness, ior, transmission, transmission_roughness, N, CN, T, I, result);
+#endif
+}
+
+void node_bsdf_translucent(vec4 color, vec3 N, out Closure result)
+{
+ node_bsdf_diffuse(color, 0.0, -N, result);
}
-void node_bsdf_transparent(vec4 color, out vec4 result)
+void node_bsdf_transparent(vec4 color, out Closure result)
{
/* this isn't right */
- result.r = color.r;
- result.g = color.g;
- result.b = color.b;
- result.a = 0.0;
+ result = CLOSURE_DEFAULT;
+ result.radiance = vec3(0.0);
+ result.opacity = 0.0;
+#ifdef EEVEE_ENGINE
+ result.ssr_id = TRANSPARENT_CLOSURE_FLAG;
+#endif
}
-void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out vec4 result)
+void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
void node_subsurface_scattering(
- vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N,
- out vec4 result)
-{
+ vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, float sss_id,
+ out Closure result)
+{
+#if defined(EEVEE_ENGINE) && defined(USE_SSS)
+ vec3 out_diff, out_trans;
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.ssr_data = vec4(0.0);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = -1;
+ result.sss_data.a = scale;
+ eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans);
+ result.sss_data.rgb = out_diff + out_trans;
+#ifdef USE_SSS_ALBEDO
+ /* Not perfect for texture_blur not exaclty equal to 0.0 or 1.0. */
+ result.sss_albedo.rgb = mix(color.rgb, vec3(1.0), texture_blur);
+ result.sss_data.rgb *= mix(vec3(1.0), color.rgb, texture_blur);
+#else
+ result.sss_data.rgb *= color.rgb;
+#endif
+#else
node_bsdf_diffuse(color, 0.0, N, result);
+#endif
}
-void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, vec3 tangent, out vec4 result)
+void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result)
{
- result = color;
+#ifdef EEVEE_ENGINE
+ vec3 out_refr;
+ color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */
+ roughness = sqrt(roughness);
+ eevee_closure_refraction(N, roughness, ior, out_refr);
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_refr * color.rgb;
+ result.ssr_id = REFRACT_CLOSURE_FLAG;
+#else
+ node_bsdf_diffuse(color, 0.0, N, result);
+#endif /* EEVEE_ENGINE */
}
-void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out vec4 result)
+/* Unsupported for now */
+#ifndef EEVEE_ENGINE
+void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, vec3 tangent, out Closure result)
{
- node_bsdf_diffuse(color, 0.0, N, result);
+ result = Closure(color.rgb, color.a);
}
-void node_ambient_occlusion(vec4 color, out vec4 result)
+void node_ambient_occlusion(vec4 color, out Closure result)
{
- result = color;
+ result = Closure(color.rgb, color.a);
}
+#endif /* EEVEE_ENGINE */
+
+#endif /* VOLUMETRICS */
/* emission */
-void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
+void node_emission(vec4 color, float strength, vec3 N, out Closure result)
{
- result = color * strength;
+#ifndef VOLUMETRICS
+ color *= strength;
+#ifdef EEVEE_ENGINE
+ result = CLOSURE_DEFAULT;
+ result.radiance = color.rgb;
+ result.opacity = color.a;
+ result.ssr_normal = normal_encode(N, viewCameraVec);
+#else
+ result = Closure(color.rgb, color.a);
+#endif
+#else
+ result = Closure(vec3(0.0), vec3(0.0), color.rgb * strength, 0.0);
+#endif
}
/* background */
void background_transform_to_world(vec3 viewvec, out vec3 worldvec)
{
- vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
+ vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (ProjectionMatrixInverse * v);
vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
- worldvec = (gl_ModelViewMatrixInverse * co).xyz;
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ worldvec = (ViewMatrixInverse * co).xyz;
+#else
+ worldvec = (ModelViewMatrixInverse * co).xyz;
+#endif
+}
+
+void node_background(vec4 color, float strength, out Closure result)
+{
+#ifndef VOLUMETRICS
+ color *= strength;
+#ifdef EEVEE_ENGINE
+ result = CLOSURE_DEFAULT;
+ result.radiance = color.rgb;
+ result.opacity = color.a;
+#else
+ result = Closure(color.rgb, color.a);
+#endif
+#else
+ result = CLOSURE_DEFAULT;
+#endif
+}
+
+/* volumes */
+
+void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result)
+{
+#ifdef VOLUMETRICS
+ result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy);
+#else
+ result = CLOSURE_DEFAULT;
+#endif
}
-void node_background(vec4 color, float strength, vec3 N, out vec4 result)
+void node_volume_absorption(vec4 color, float density, out Closure result)
{
- result = color * strength;
+#ifdef VOLUMETRICS
+ result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0);
+#else
+ result = CLOSURE_DEFAULT;
+#endif
}
/* closures */
-void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader)
+void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader)
{
- shader = mix(shader1, shader2, fac);
+ shader = closure_mix(shader1, shader2, fac);
}
-void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader)
+void node_add_shader(Closure shader1, Closure shader2, out Closure shader)
{
- shader = shader1 + shader2;
+ shader = closure_add(shader1, shader2);
}
/* fresnel */
@@ -2823,7 +3089,7 @@ void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader)
void node_fresnel(float ior, vec3 N, vec3 I, out float result)
{
/* handle perspective/orthographic */
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
float eta = max(ior, 0.00001);
result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta);
@@ -2835,7 +3101,7 @@ void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float
{
/* fresnel */
float eta = max(1.0 - blend, 0.00001);
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta);
@@ -2865,11 +3131,47 @@ void node_gamma(vec4 col, float gamma, out vec4 outcol)
/* geometry */
+void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(EEVEE_ENGINE) && defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+ outvec = texture(tex, cos).aaa;
+ outcol = vec4(outvec, 1.0);
+ outf = dot(vec3(1.0 / 3.0), outvec);
+}
+
+void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(EEVEE_ENGINE) && defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+ outvec = texture(tex, cos).rgb;
+ outcol = vec4(outvec, 1.0);
+ outf = dot(vec3(1.0 / 3.0), outvec);
+}
+
+void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(EEVEE_ENGINE) && defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+ outvec = texture(tex, cos).rrr;
+ outcol = vec4(outvec, 1.0);
+ outf = dot(vec3(1.0 / 3.0), outvec);
+}
+
void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf)
{
outcol = vec4(attr, 1.0);
outvec = attr;
- outf = (attr.x + attr.y + attr.z) / 3.0;
+ outf = dot(vec3(1.0 / 3.0), attr);
}
void node_uvmap(vec3 attr_uv, out vec3 outvec)
@@ -2877,19 +3179,51 @@ void node_uvmap(vec3 attr_uv, out vec3 outvec)
outvec = attr_uv;
}
+void tangent_orco_x(vec3 orco_in, out vec3 orco_out)
+{
+ orco_out = vec3(0.0, (orco_in.z - 0.5) * -0.5, (orco_in.y - 0.5) * 0.5);
+}
+
+void tangent_orco_y(vec3 orco_in, out vec3 orco_out)
+{
+ orco_out = vec3((orco_in.z - 0.5) * -0.5, 0.0, (orco_in.x - 0.5) * 0.5);
+}
+
+void tangent_orco_z(vec3 orco_in, out vec3 orco_out)
+{
+ orco_out = vec3((orco_in.y - 0.5) * -0.5, (orco_in.x - 0.5) * 0.5, 0.0);
+}
+
+void node_tangentmap(vec4 attr_tangent, mat4 toworld, out vec3 tangent)
+{
+ tangent = (toworld * vec4(attr_tangent.xyz, 0.0)).xyz;
+}
+
+void node_tangent(vec3 N, vec3 orco, mat4 objmat, mat4 toworld, out vec3 T)
+{
+ N = (toworld * vec4(N, 0.0)).xyz;
+ T = (objmat * vec4(orco, 0.0)).xyz;
+ T = cross(N, normalize(cross(T, N)));
+}
+
void node_geometry(
- vec3 I, vec3 N, mat4 toworld,
+ vec3 I, vec3 N, vec3 orco, mat4 objmat, mat4 toworld,
out vec3 position, out vec3 normal, out vec3 tangent,
out vec3 true_normal, out vec3 incoming, out vec3 parametric,
out float backfacing, out float pointiness)
{
+#ifdef EEVEE_ENGINE
+ position = worldPosition;
+#else
position = (toworld * vec4(I, 1.0)).xyz;
+#endif
normal = (toworld * vec4(N, 0.0)).xyz;
- tangent = vec3(0.0);
+ tangent_orco_z(orco, orco);
+ node_tangent(N, orco, objmat, toworld, tangent);
true_normal = normal;
/* handle perspective/orthographic */
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
incoming = -(toworld * vec4(I_view, 0.0)).xyz;
parametric = vec3(0.0);
@@ -2903,12 +3237,12 @@ void node_tex_coord(
out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
out vec3 camera, out vec3 window, out vec3 reflection)
{
- generated = attr_orco * 0.5 + vec3(0.5);
+ generated = attr_orco;
normal = normalize((obinvmat * (viewinvmat * vec4(N, 0.0))).xyz);
uv = attr_uv;
object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz;
camera = vec3(I.xy, -I.z);
- vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0);
+ vec4 projvec = ProjectionMatrix * vec4(I, 1.0);
window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);
vec3 shade_I;
@@ -2923,13 +3257,18 @@ void node_tex_coord_background(
out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
out vec3 camera, out vec3 window, out vec3 reflection)
{
- vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
+ vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (ProjectionMatrixInverse * v);
vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
co = normalize(co);
- vec3 coords = (gl_ModelViewMatrixInverse * co).xyz;
+
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ vec3 coords = (ViewMatrixInverse * co).xyz;
+#else
+ vec3 coords = (ModelViewMatrixInverse * co).xyz;
+#endif
generated = coords;
normal = -coords;
@@ -2937,13 +3276,17 @@ void node_tex_coord_background(
object = coords;
camera = vec3(co.xy, -co.z);
- window = (gl_ProjectionMatrix[3][3] == 0.0) ?
+ window = (ProjectionMatrix[3][3] == 0.0) ?
vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) :
vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0);
reflection = -coords;
}
+#if defined(WORLD_BACKGROUND) || (defined(PROBE_CAPTURE) && !defined(MESH_SHADER))
+#define node_tex_coord node_tex_coord_background
+#endif
+
/* textures */
float calc_gradient(vec3 p, int gradient_type)
@@ -3013,7 +3356,6 @@ void node_tex_checker(vec3 co, vec4 color1, vec4 color2, float scale, out vec4 c
fac = check ? 1.0 : 0.0;
}
-#ifdef BIT_OPERATIONS
vec2 calc_brick_texture(vec3 p, float mortar_size, float mortar_smooth, float bias,
float brick_width, float row_height,
float offset_amount, int offset_frequency,
@@ -3049,7 +3391,6 @@ vec2 calc_brick_texture(vec3 p, float mortar_size, float mortar_smooth, float bi
return vec2(tint, smoothstep(0.0, mortar_smooth, min_dist));
}
}
-#endif
void node_tex_brick(vec3 co,
vec4 color1, vec4 color2,
@@ -3060,7 +3401,6 @@ void node_tex_brick(vec3 co,
float squash_amount, float squash_frequency,
out vec4 color, out float fac)
{
-#ifdef BIT_OPERATIONS
vec2 f2 = calc_brick_texture(co * scale,
mortar_size, mortar_smooth, bias,
brick_width, row_height,
@@ -3074,10 +3414,6 @@ void node_tex_brick(vec3 co,
}
color = mix(color1, mortar, f);
fac = f;
-#else
- color = vec4(1.0);
- fac = 1.0;
-#endif
}
void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac)
@@ -3092,7 +3428,15 @@ void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color
float u = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5;
float v = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5;
- color = texture2D(ima, vec2(u, v));
+ /* Fix pole bleeding */
+ float half_width = 0.5 / float(textureSize(ima, 0).x);
+ v = clamp(v, half_width, 1.0 - half_width);
+
+ /* Fix u = 0 seam */
+ /* This is caused by texture filtering, since uv don't have smooth derivatives
+ * at u = 0 or 2PI, hardware filtering is using the smallest mipmap for certain
+ * texels. So we force the highest mipmap and don't do anisotropic filtering. */
+ color = textureLod(ima, vec2(u, v), 0.0);
}
void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color)
@@ -3108,7 +3452,7 @@ void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color)
float u = 0.5 * (nco.x + 1.0);
float v = 0.5 * (nco.z + 1.0);
- color = texture2D(ima, vec2(u, v));
+ color = texture(ima, vec2(u, v));
}
void node_tex_environment_empty(vec3 co, out vec4 color)
@@ -3118,7 +3462,7 @@ void node_tex_environment_empty(vec3 co, out vec4 color)
void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha)
{
- color = texture2D(ima, co.xy);
+ color = texture(ima, co.xy);
alpha = color.a;
}
@@ -3192,21 +3536,21 @@ void node_tex_image_box(vec3 texco,
if(signed_N.x < 0.0) {
uv.x = 1.0 - uv.x;
}
- color += weight.x * texture2D(ima, uv);
+ color += weight.x * texture(ima, uv);
}
if (weight.y > 0.0) {
vec2 uv = texco.xz;
if(signed_N.y > 0.0) {
uv.x = 1.0 - uv.x;
}
- color += weight.y * texture2D(ima, uv);
+ color += weight.y * texture(ima, uv);
}
if (weight.z > 0.0) {
vec2 uv = texco.yx;
if(signed_N.z > 0.0) {
uv.x = 1.0 - uv.x;
}
- color += weight.z * texture2D(ima, uv);
+ color += weight.z * texture(ima, uv);
}
alpha = color.a;
@@ -3279,7 +3623,6 @@ void node_tex_magic(vec3 co, float scale, float distortion, float depth, out vec
fac = (color.x + color.y + color.z) / 3.0;
}
-#ifdef BIT_OPERATIONS
float noise_fade(float t)
{
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
@@ -3342,10 +3685,9 @@ float noise_turbulence(vec3 p, float octaves, int hard)
float fscale = 1.0;
float amp = 1.0;
float sum = 0.0;
- int i, n;
octaves = clamp(octaves, 0.0, 16.0);
- n = int(octaves);
- for (i = 0; i <= n; i++) {
+ int n = int(octaves);
+ for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
if (hard != 0) {
t = abs(2.0 * t - 1.0);
@@ -3355,7 +3697,7 @@ float noise_turbulence(vec3 p, float octaves, int hard)
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
- if (rmd != 0.0) {
+ if (rmd != 0.0) {
float t = noise(fscale * p);
if (hard != 0) {
t = abs(2.0 * t - 1.0);
@@ -3370,11 +3712,9 @@ float noise_turbulence(vec3 p, float octaves, int hard)
return sum;
}
}
-#endif // BIT_OPERATIONS
void node_tex_noise(vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac)
{
-#ifdef BIT_OPERATIONS
vec3 p = co * scale;
int hard = 0;
if (distortion != 0.0) {
@@ -3390,15 +3730,8 @@ void node_tex_noise(vec3 co, float scale, float detail, float distortion, out ve
noise_turbulence(vec3(p.y, p.x, p.z), detail, hard),
noise_turbulence(vec3(p.y, p.z, p.x), detail, hard),
1);
-#else // BIT_OPERATIONS
- color = vec4(1.0);
- fac = 1.0;
-#endif // BIT_OPERATIONS
}
-
-#ifdef BIT_OPERATIONS
-
/* Musgrave fBm
*
* H: fractal increment parameter
@@ -3414,9 +3747,8 @@ float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves)
float value = 0.0;
float pwr = 1.0;
float pwHL = pow(lacunarity, -H);
- int i;
- for (i = 0; i < int(octaves); i++) {
+ for (int i = 0; i < int(octaves); i++) {
value += snoise(p) * pwr;
pwr *= pwHL;
p *= lacunarity;
@@ -3442,9 +3774,8 @@ float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octa
float value = 1.0;
float pwr = 1.0;
float pwHL = pow(lacunarity, -H);
- int i;
- for (i = 0; i < int(octaves); i++) {
+ for (int i = 0; i < int(octaves); i++) {
value *= (pwr * snoise(p) + 1.0);
pwr *= pwHL;
p *= lacunarity;
@@ -3470,13 +3801,12 @@ float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float oct
float value, increment, rmd;
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
- int i;
/* first unscaled octave of function; later octaves are scaled */
value = offset + snoise(p);
p *= lacunarity;
- for (i = 1; i < int(octaves); i++) {
+ for (int i = 1; i < int(octaves); i++) {
increment = (snoise(p) + offset) * pwr * value;
value += increment;
pwr *= pwHL;
@@ -3505,13 +3835,12 @@ float noise_musgrave_hybrid_multi_fractal(vec3 p, float H, float lacunarity, flo
float result, signal, weight, rmd;
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
- int i;
result = snoise(p) + offset;
weight = gain * result;
p *= lacunarity;
- for (i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
+ for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
if (weight > 1.0)
weight = 1.0;
@@ -3542,14 +3871,13 @@ float noise_musgrave_ridged_multi_fractal(vec3 p, float H, float lacunarity, flo
float result, signal, weight;
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
- int i;
signal = offset - abs(snoise(p));
signal *= signal;
result = signal;
weight = 1.0;
- for (i = 1; i < int(octaves); i++) {
+ for (int i = 1; i < int(octaves); i++) {
p *= lacunarity;
weight = clamp(signal * gain, 0.0, 1.0);
signal = offset - abs(snoise(p));
@@ -3571,19 +3899,18 @@ float svm_musgrave(int type,
float gain,
vec3 p)
{
- if (type == 0 /*NODE_MUSGRAVE_MULTIFRACTAL*/)
+ if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */)
return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
- else if (type == 1 /*NODE_MUSGRAVE_FBM*/)
+ else if (type == 1 /* NODE_MUSGRAVE_FBM */)
return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
- else if (type == 2 /*NODE_MUSGRAVE_HYBRID_MULTIFRACTAL*/)
+ else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */)
return intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
- else if (type == 3 /*NODE_MUSGRAVE_RIDGED_MULTIFRACTAL*/)
+ else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */)
return intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
- else if (type == 4 /*NODE_MUSGRAVE_HETERO_TERRAIN*/)
+ else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */)
return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
return 0.0;
}
-#endif // #ifdef BIT_OPERATIONS
void node_tex_musgrave(vec3 co,
float scale,
@@ -3596,7 +3923,6 @@ void node_tex_musgrave(vec3 co,
out vec4 color,
out float fac)
{
-#ifdef BIT_OPERATIONS
fac = svm_musgrave(int(type),
dimension,
lacunarity,
@@ -3605,9 +3931,6 @@ void node_tex_musgrave(vec3 co,
1.0,
gain,
co * scale);
-#else
- fac = 1.0;
-#endif
color = vec4(fac, fac, fac, 1.0);
}
@@ -3619,7 +3942,6 @@ void node_tex_sky(vec3 co, out vec4 color)
void node_tex_voronoi(vec3 co, float scale, float coloring, out vec4 color, out float fac)
{
-#ifdef BIT_OPERATIONS
vec3 p = co * scale;
int xx, yy, zz, xi, yi, zi;
float da[4];
@@ -3684,13 +4006,8 @@ void node_tex_voronoi(vec3 co, float scale, float coloring, out vec4 color, out
color = vec4(cellnoise_color(pa[0]), 1);
fac = (color.x + color.y + color.z) * (1.0 / 3.0);
}
-#else // BIT_OPERATIONS
- color = vec4(1.0);
- fac = 1.0;
-#endif // BIT_OPERATIONS
}
-#ifdef BIT_OPERATIONS
float calc_wave(vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile)
{
float n;
@@ -3712,22 +4029,16 @@ float calc_wave(vec3 p, float distortion, float detail, float detail_scale, int
return (n < 0.0) ? n + 1.0 : n;
}
}
-#endif // BIT_OPERATIONS
void node_tex_wave(
vec3 co, float scale, float distortion, float detail, float detail_scale, float wave_type, float wave_profile,
out vec4 color, out float fac)
{
-#ifdef BIT_OPERATIONS
float f;
f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile));
color = vec4(f, f, f, 1.0);
fac = f;
-#else // BIT_OPERATIONS
- color = vec4(1.0);
- fac = 1;
-#endif // BIT_OPERATIONS
}
/* light path */
@@ -3747,13 +4058,21 @@ void node_light_path(
out float transparent_depth,
out float transmission_depth)
{
+#ifndef PROBE_CAPTURE
is_camera_ray = 1.0;
- is_shadow_ray = 0.0;
- is_diffuse_ray = 0.0;
is_glossy_ray = 0.0;
- is_singular_ray = 0.0;
+ is_diffuse_ray = 0.0;
is_reflection_ray = 0.0;
is_transmission_ray = 0.0;
+#else
+ is_camera_ray = 0.0;
+ is_glossy_ray = 1.0;
+ is_diffuse_ray = 1.0;
+ is_reflection_ray = 1.0;
+ is_transmission_ray = 1.0;
+#endif
+ is_shadow_ray = 0.0;
+ is_singular_ray = 0.0;
ray_length = 1.0;
ray_depth = 1.0;
diffuse_depth = 1.0;
@@ -3818,37 +4137,79 @@ void node_bevel(float radius, vec3 N, out vec3 result)
/* output */
-void node_output_material(vec4 surface, vec4 volume, float displacement, out vec4 result)
+void node_output_material(Closure surface, Closure volume, float displacement, out Closure result)
{
+#ifdef VOLUMETRICS
+ result = volume;
+#else
result = surface;
+#endif
}
-void node_output_world(vec4 surface, vec4 volume, out vec4 result)
+uniform float backgroundAlpha;
+
+void node_output_world(Closure surface, Closure volume, out Closure result)
{
- result = surface;
+#ifndef VOLUMETRICS
+#ifdef EEVEE_ENGINE
+ result.radiance = surface.radiance;
+ result.opacity = backgroundAlpha;
+#else
+ result = Closure(surface.radiance, backgroundAlpha);
+#endif
+#else
+ result = volume;
+#endif /* VOLUMETRICS */
+}
+
+#ifndef VOLUMETRICS
+/* TODO : clean this ifdef mess */
+/* EEVEE output */
+#ifdef EEVEE_ENGINE
+void world_normals_get(out vec3 N)
+{
+ N = gl_FrontFacing ? worldNormal : -worldNormal;
+}
+
+void node_eevee_specular(
+ vec4 diffuse, vec4 specular, float roughness, vec4 emissive, float transp, vec3 normal,
+ float clearcoat, float clearcoat_roughness, vec3 clearcoat_normal,
+ float occlusion, float ssr_id, out Closure result)
+{
+ vec3 out_diff, out_spec, ssr_spec;
+ eevee_closure_default(normal, diffuse.rgb, specular.rgb, int(ssr_id), roughness, occlusion,
+ out_diff, out_spec, ssr_spec);
+
+ vec3 vN = normalize(mat3(ViewMatrix) * normal);
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb;
+ result.opacity = 1.0 - transp;
+ result.ssr_data = vec4(ssr_spec, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
}
+#endif /* EEVEE_ENGINE */
+#endif /* VOLUMETRICS */
+
/* ********************** matcap style render ******************** */
void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result)
{
vec3 normal;
- vec2 tex;
#ifndef USE_OPENSUBDIV
/* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
* between shader stages and we want the full range of the normal */
- normal = vec3(2.0, 2.0, 2.0) * vec3(N.x, N.y, N.z) - vec3(1.0, 1.0, 1.0);
- if (normal.z < 0.0) {
- normal.z = 0.0;
- }
+ normal = 2.0 * N.xyz - vec3(1.0);
+ normal.z = max(normal.z, 0.0);
normal = normalize(normal);
#else
normal = inpt.v.normal;
- mask = vec4(1.0, 1.0, 1.0, 1.0);
+ mask = vec4(1.0);
#endif
- tex.x = 0.5 + 0.49 * normal.x;
- tex.y = 0.5 + 0.49 * normal.y;
- result = texture2D(ima, tex) * mask;
+ vec2 tex = 0.49 * normal.xy + vec2(0.5);
+
+ result = texture(ima, tex) * mask;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl
new file mode 100644
index 00000000000..fef81cf58fe
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl
@@ -0,0 +1,24 @@
+
+uniform vec4 color;
+
+in vec2 radii;
+out vec4 fragColor;
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure point color
+// ...
+// dist = 0 at center of point
+
+ fragColor.rgb = color.rgb;
+ fragColor.a = mix(color.a, 0.0, smoothstep(radii[1], radii[0], dist));
+
+ if (fragColor.a == 0.0) {
+ discard;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl
new file mode 100644
index 00000000000..852c76fcb26
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl
@@ -0,0 +1,17 @@
+
+uniform vec4 color;
+
+out vec4 fragColor;
+
+void main()
+{
+ vec2 centered = gl_PointCoord - vec2(0.5);
+ float dist_squared = dot(centered, centered);
+ const float rad_squared = 0.25;
+
+ // round point with jaggy edges
+ if (dist_squared > rad_squared)
+ discard;
+
+ fragColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl
new file mode 100644
index 00000000000..eae5ee633ae
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl
@@ -0,0 +1,36 @@
+
+uniform vec4 color;
+uniform vec4 outlineColor;
+
+in vec4 radii;
+out vec4 fragColor;
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure outline color
+// --- 2 ---
+// smooth transition
+// --- 3 ---
+// pure point color
+// ...
+// dist = 0 at center of point
+
+ float midStroke = 0.5 * (radii[1] + radii[2]);
+
+ if (dist > midStroke) {
+ fragColor.rgb = outlineColor.rgb;
+ fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist));
+ }
+ else {
+ fragColor = mix(color, outlineColor, smoothstep(radii[3], radii[2], dist));
+ }
+
+ if (fragColor.a == 0.0) {
+ discard;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl
new file mode 100644
index 00000000000..2d2724bb686
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl
@@ -0,0 +1,16 @@
+
+in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ vec2 centered = gl_PointCoord - vec2(0.5);
+ float dist_squared = dot(centered, centered);
+ const float rad_squared = 0.25;
+
+ // round point with jaggy edges
+ if (dist_squared > rad_squared)
+ discard;
+
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl
new file mode 100644
index 00000000000..9b7d4bfc6d6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl
@@ -0,0 +1,31 @@
+
+uniform vec4 outlineColor;
+
+in vec4 radii;
+in vec4 fillColor;
+out vec4 fragColor;
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure outline color
+// --- 2 ---
+// smooth transition
+// --- 3 ---
+// pure fill color
+// ...
+// dist = 0 at center of point
+
+ float midStroke = 0.5 * (radii[1] + radii[2]);
+
+ if (dist > midStroke) {
+ fragColor.rgb = outlineColor.rgb;
+ fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist));
+ }
+ else
+ fragColor = mix(fillColor, outlineColor, smoothstep(radii[3], radii[2], dist));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
index b485d2cce86..78241a798a2 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
@@ -1,16 +1,19 @@
uniform vec2 ScaleU;
uniform sampler2D textureSource;
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
void main()
{
vec4 color = vec4(0.0);
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-3.0 * ScaleU.x, -3.0 * ScaleU.y)) * 0.015625;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-2.0 * ScaleU.x, -2.0 * ScaleU.y)) * 0.09375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-1.0 * ScaleU.x, -1.0 * ScaleU.y)) * 0.234375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(0.0, 0.0)) * 0.3125;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y)) * 0.234375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y)) * 0.09375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y)) * 0.015625;
+ color += texture(textureSource, texCoord_interp.st + vec2(-3.0 * ScaleU.x, -3.0 * ScaleU.y)) * 0.015625;
+ color += texture(textureSource, texCoord_interp.st + vec2(-2.0 * ScaleU.x, -2.0 * ScaleU.y)) * 0.09375;
+ color += texture(textureSource, texCoord_interp.st + vec2(-1.0 * ScaleU.x, -1.0 * ScaleU.y)) * 0.234375;
+ color += texture(textureSource, texCoord_interp.st + vec2(0.0, 0.0)) * 0.3125;
+ color += texture(textureSource, texCoord_interp.st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y)) * 0.234375;
+ color += texture(textureSource, texCoord_interp.st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y)) * 0.09375;
+ color += texture(textureSource, texCoord_interp.st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y)) * 0.015625;
- gl_FragColor = color;
+ fragColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
index 5d00108b052..1319e386c65 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
@@ -1,6 +1,12 @@
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 pos;
+in vec2 uvs;
+out vec2 texCoord_interp;
+
void main()
{
- gl_Position = ftransform();
- gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ texCoord_interp = uvs;
}
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..4d7131c4eb1
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl
@@ -0,0 +1,17 @@
+
+#ifndef USE_INSTANCE_COLOR
+uniform vec4 color;
+#endif
+uniform vec3 light;
+
+in vec3 normal;
+#ifdef USE_INSTANCE_COLOR
+flat in vec4 finalColor;
+# define color finalColor
+#endif
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = color * max(0.0, dot(normalize(normal), light));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl
new file mode 100644
index 00000000000..6b13f408c84
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl
@@ -0,0 +1,14 @@
+
+uniform vec3 light;
+uniform float alpha;
+uniform float global;
+
+in vec3 normal;
+in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor * (global + (1.0 - global) * max(0.0, dot(normalize(normal), light)));
+ fragColor.a = alpha;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl
new file mode 100644
index 00000000000..58c5f292647
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl
@@ -0,0 +1,16 @@
+
+uniform vec3 light;
+
+#ifdef USE_FLAT_NORMAL
+flat in vec3 normal;
+flat in vec4 finalColor;
+#else
+in vec3 normal;
+in vec4 finalColor;
+#endif
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor * max(0.0, dot(normalize(normal), light));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
index 6ded453225e..b57bd5b6a37 100644
--- a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
@@ -1,5 +1,6 @@
-varying vec3 coords;
+in vec3 coords;
+out vec4 fragColor;
uniform vec3 active_color;
uniform float step_size;
@@ -16,7 +17,7 @@ uniform sampler3D color_band_texture;
void main()
{
/* compute color and density from volume texture */
- vec4 soot = texture3D(soot_texture, coords);
+ vec4 soot = texture(soot_texture, coords);
#ifndef USE_COBA
vec3 soot_color;
@@ -24,7 +25,7 @@ void main()
soot_color = active_color * soot.rgb / soot.a;
}
else {
- soot_color = vec3(0, 0, 0);
+ soot_color = vec3(0);
}
float soot_density = density_scale * soot.a;
@@ -33,16 +34,14 @@ void main()
float soot_alpha = 1.0 - soot_transmittance;
/* shade */
- float shadow = texture3D(shadow_texture, coords).r;
+ float shadow = texture(shadow_texture, coords).r;
soot_color *= soot_transmittance * shadow;
/* premultiply alpha */
- vec4 color = vec4(soot_alpha * soot_color, soot_alpha);
+ fragColor = vec4(soot_alpha * soot_color, soot_alpha);
#else
- float color_band = texture3D(color_band_texture, coords).r;
- vec4 transfer_function = texture1D(transfer_texture, color_band);
- vec4 color = transfer_function * density_scale;
+ float color_band = texture(color_band_texture, coords).r;
+ vec4 transfer_function = texture(transfer_texture, color_band);
+ fragColor = transfer_function * density_scale;
#endif
-
- gl_FragColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl b/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl
index 297486ae26a..8c30e9baf9e 100644
--- a/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl
@@ -1,5 +1,7 @@
-varying vec3 coords;
+uniform mat4 ModelViewProjectionMatrix;
+
+out vec3 coords;
uniform vec3 min_location;
uniform vec3 invsize;
@@ -7,6 +9,7 @@ uniform vec3 ob_sizei;
void main()
{
- gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz * ob_sizei, 1.0);
+ // TODO: swap gl_Vertex for vec3 pos, update smoke setup code
+ gl_Position = ModelViewProjectionMatrix * vec4(gl_Vertex.xyz * ob_sizei, 1.0);
coords = (gl_Vertex.xyz - min_location) * invsize;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
new file mode 100644
index 00000000000..7ff90ad4f21
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
@@ -0,0 +1,15 @@
+
+flat in vec4 color_flat;
+noperspective in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D glyph;
+
+void main()
+{
+ // input color replaces texture color
+ fragColor.rgb = color_flat.rgb;
+
+ // modulate input alpha & texture alpha
+ fragColor.a = color_flat.a * texture(glyph, texCoord_interp).r;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
new file mode 100644
index 00000000000..6129f49ce22
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
@@ -0,0 +1,16 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 pos;
+in vec2 texCoord;
+in vec4 color;
+flat out vec4 color_flat;
+noperspective out vec2 texCoord_interp;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+
+ color_flat = color;
+ texCoord_interp = texCoord;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl
new file mode 100644
index 00000000000..118a661863d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl
@@ -0,0 +1,21 @@
+
+#if defined(USE_COLOR_U32)
+uniform uint color;
+#else
+uniform vec4 color;
+#endif
+
+out vec4 fragColor;
+
+void main()
+{
+#if defined(USE_COLOR_U32)
+ fragColor = vec4(
+ ((color ) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 8) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 16) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 24) ) * (1.0f / 255.0f));
+#else
+ fragColor = color;
+#endif
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
index db0068d2f3d..4ebd10d514f 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
@@ -1,3 +1,8 @@
+
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat3 NormalMatrix;
+
#ifdef USE_OPENSUBDIV
in vec3 normal;
in vec4 position;
@@ -7,8 +12,8 @@ out block {
} outpt;
#endif
-varying vec3 varposition;
-varying vec3 varnormal;
+out vec3 varposition;
+out vec3 varnormal;
#ifdef CLIP_WORKAROUND
varying float gl_ClipDistance[6];
@@ -89,11 +94,11 @@ void main()
vec3 normal = gl_Normal;
#endif
- vec4 co = gl_ModelViewMatrix * position;
+ vec4 co = ModelViewMatrix * position;
varposition = co.xyz;
- varnormal = normalize(gl_NormalMatrix * normal);
- gl_Position = gl_ProjectionMatrix * co;
+ varnormal = normalize(NormalMatrix * normal);
+ gl_Position = ProjectionMatrix * co;
#ifdef CLIP_WORKAROUND
int i;
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
index d45a4b316a8..89a2f391a12 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
@@ -1,7 +1,6 @@
-varying vec3 varposition;
-varying vec3 varnormal;
-
+out vec3 varposition;
+out vec3 varnormal;
/* Color, keep in sync with: gpu_shader_vertex.glsl */
diff --git a/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl b/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
index 3761bf350eb..6aad94bbf59 100644
--- a/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
@@ -2,7 +2,8 @@
* This fragment shader was initially found at http://fabiensanglard.net/shadowmappingVSM/index.php
*/
-varying vec4 v_position;
+in vec4 v_position;
+out vec4 fragColor;
void main()
{
@@ -17,5 +18,6 @@ void main()
float dy = dFdy(depth);
moment2 += 0.25 * (dx * dx + dy * dy);
- gl_FragColor = vec4(moment1, moment2, 0.0, 0.0);
+ fragColor = vec4(moment1, moment2, 0.0, 0.0);
+ // TODO: write to a 2-component target --^
}
diff --git a/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl b/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl
index 224c3e78adc..def835156f7 100644
--- a/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl
@@ -1,7 +1,10 @@
-varying vec4 v_position;
+
+uniform mat4 ModelViewProjectionMatrix;
+
+out vec4 v_position;
void main()
{
- gl_Position = ftransform();
+ gl_Position = ModelViewProjectionMatrix * gl_Vertex;
v_position = gl_Position;
}
diff --git a/source/blender/ikplugin/BIK_api.h b/source/blender/ikplugin/BIK_api.h
index 177be074897..ad842029941 100644
--- a/source/blender/ikplugin/BIK_api.h
+++ b/source/blender/ikplugin/BIK_api.h
@@ -43,6 +43,7 @@ struct bPoseChannel;
struct bPose;
struct Scene;
struct bConstraint;
+struct EvaluationContext;
enum BIK_ParamType {
BIK_PARAM_TYPE_FLOAT = 0,
@@ -61,8 +62,8 @@ struct BIK_ParamValue {
};
typedef struct BIK_ParamValue BIK_ParamValue;
-void BIK_initialize_tree(struct Scene *scene, struct Object *ob, float ctime);
-void BIK_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime);
+void BIK_initialize_tree(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime);
+void BIK_execute_tree(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime);
void BIK_release_tree(struct Scene *scene, struct Object *ob, float ctime);
void BIK_clear_data(struct bPose *pose);
void BIK_clear_cache(struct bPose *pose);
diff --git a/source/blender/ikplugin/intern/ikplugin_api.c b/source/blender/ikplugin/intern/ikplugin_api.c
index 0f81fb34a63..0ee26ff45f1 100644
--- a/source/blender/ikplugin/intern/ikplugin_api.c
+++ b/source/blender/ikplugin/intern/ikplugin_api.c
@@ -89,20 +89,20 @@ static IKPlugin *get_plugin(bPose *pose)
/*----------------------------------------*/
/* Plugin API */
-void BIK_initialize_tree(Scene *scene, Object *ob, float ctime)
+void BIK_initialize_tree(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float ctime)
{
IKPlugin *plugin = get_plugin(ob->pose);
if (plugin && plugin->initialize_tree_func)
- plugin->initialize_tree_func(scene, ob, ctime);
+ plugin->initialize_tree_func(eval_ctx, scene, ob, ctime);
}
-void BIK_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan, float ctime)
+void BIK_execute_tree(const struct EvaluationContext *eval_ctx, struct Scene *scene, Object *ob, bPoseChannel *pchan, float ctime)
{
IKPlugin *plugin = get_plugin(ob->pose);
if (plugin && plugin->execute_tree_func)
- plugin->execute_tree_func(scene, ob, pchan, ctime);
+ plugin->execute_tree_func(eval_ctx, scene, ob, pchan, ctime);
}
void BIK_release_tree(struct Scene *scene, Object *ob, float ctime)
diff --git a/source/blender/ikplugin/intern/ikplugin_api.h b/source/blender/ikplugin/intern/ikplugin_api.h
index cd32bf26242..9a71463ede4 100644
--- a/source/blender/ikplugin/intern/ikplugin_api.h
+++ b/source/blender/ikplugin/intern/ikplugin_api.h
@@ -41,11 +41,12 @@ extern "C" {
struct Object;
struct bPoseChannel;
struct Scene;
+struct EvaluationContext;
struct IKPlugin {
- void (*initialize_tree_func)(struct Scene *scene, struct Object *ob, float ctime);
- void (*execute_tree_func)(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime);
+ void (*initialize_tree_func)(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime);
+ void (*execute_tree_func)(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime);
void (*release_tree_func)(struct Scene *scene, struct Object *ob, float ctime);
void (*remove_armature_func)(struct bPose *pose);
void (*clear_cache)(struct bPose *pose);
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c
index f837789914e..5169b72590c 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.c
+++ b/source/blender/ikplugin/intern/iksolver_plugin.c
@@ -252,7 +252,7 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[3][3]) // nr =
/* called from within the core BKE_pose_where_is loop, all animsystems and constraints
* were executed & assigned. Now as last we do an IK pass */
-static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
+static void execute_posetree(const struct EvaluationContext *eval_ctx, struct Scene *scene, Object *ob, PoseTree *tree)
{
float R_parmat[3][3], identity[3][3];
float iR_parmat[3][3];
@@ -394,7 +394,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
/* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though
* strictly speaking, it is a posechannel)
*/
- BKE_constraint_target_matrix_get(scene, target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+ BKE_constraint_target_matrix_get(eval_ctx, scene, target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
/* and set and transform goal */
mul_m4_m4m4(goal, goalinv, rootmat);
@@ -405,7 +405,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
/* same for pole vector target */
if (data->poletar) {
- BKE_constraint_target_matrix_get(scene, target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+ BKE_constraint_target_matrix_get(eval_ctx, scene, target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
if (data->flag & CONSTRAINT_IK_SETANGLE) {
/* don't solve IK when we are setting the pole angle */
@@ -534,7 +534,7 @@ static void free_posetree(PoseTree *tree)
///----------------------------------------
/// Plugin API for legacy iksolver
-void iksolver_initialize_tree(struct Scene *UNUSED(scene), struct Object *ob, float UNUSED(ctime))
+void iksolver_initialize_tree(const struct EvaluationContext *UNUSED(eval_ctx), struct Scene *UNUSED(scene), struct Object *ob, float UNUSED(ctime))
{
bPoseChannel *pchan;
@@ -545,7 +545,7 @@ void iksolver_initialize_tree(struct Scene *UNUSED(scene), struct Object *ob, fl
ob->pose->flag &= ~POSE_WAS_REBUILT;
}
-void iksolver_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
+void iksolver_execute_tree(const struct EvaluationContext *eval_ctx, struct Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
{
while (pchan_root->iktree.first) {
PoseTree *tree = pchan_root->iktree.first;
@@ -558,13 +558,13 @@ void iksolver_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan
/* 4. walk over the tree for regular solving */
for (a = 0; a < tree->totchannel; a++) {
if (!(tree->pchan[a]->flag & POSE_DONE)) // successive trees can set the flag
- BKE_pose_where_is_bone(scene, ob, tree->pchan[a], ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, scene, ob, tree->pchan[a], ctime, 1);
/* tell blender that this channel was controlled by IK, it's cleared on each BKE_pose_where_is() */
tree->pchan[a]->flag |= POSE_CHAIN;
}
/* 5. execute the IK solver */
- execute_posetree(scene, ob, tree);
+ execute_posetree(eval_ctx, scene, ob, tree);
/* 6. apply the differences to the channels,
* we need to calculate the original differences first */
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.h b/source/blender/ikplugin/intern/iksolver_plugin.h
index 07264280a25..f1ca91ebb49 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.h
+++ b/source/blender/ikplugin/intern/iksolver_plugin.h
@@ -40,8 +40,11 @@
extern "C" {
#endif
-void iksolver_initialize_tree(struct Scene *scene, struct Object *ob, float ctime);
-void iksolver_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan_root, float ctime);
+void iksolver_initialize_tree(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime);
+void iksolver_execute_tree(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
+ struct bPoseChannel *pchan_root, float ctime);
#ifdef __cplusplus
}
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index d58340965a7..93460559067 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -542,7 +542,7 @@ static void GetJointRotation(KDL::Rotation& boneRot, int type, double *rot)
}
}
-static bool target_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param)
+static bool target_callback(const struct EvaluationContext *eval_ctx, const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param)
{
IK_Target *target = (IK_Target *)param;
// compute next target position
@@ -550,7 +550,7 @@ static bool target_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Fram
bConstraint *constraint = (bConstraint *)target->blenderConstraint;
float tarmat[4][4];
- BKE_constraint_target_matrix_get(target->blscene, constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0);
+ BKE_constraint_target_matrix_get(eval_ctx, target->blscene, constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0);
// rootmat contains the target pose in world coordinate
// if enforce is != 1.0, blend the target position with the end effector position
@@ -577,7 +577,7 @@ static bool target_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Fram
return true;
}
-static bool base_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param)
+static bool base_callback(const struct EvaluationContext *eval_ctx, const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param)
{
IK_Scene *ikscene = (IK_Scene *)param;
// compute next armature base pose
@@ -619,7 +619,7 @@ static bool base_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Frame&
IK_Channel &rootchan = ikscene->channels[0];
// get polar target matrix in world space
- BKE_constraint_target_matrix_get(ikscene->blscene, ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0);
+ BKE_constraint_target_matrix_get(eval_ctx, ikscene->blscene, ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0);
// convert to armature space
mul_m4_m4m4(polemat, imat, mat);
// get the target in world space (was computed before as target object are defined before base object)
@@ -863,7 +863,7 @@ static bool joint_callback(const iTaSC::Timestamp& timestamp, iTaSC::ConstraintV
}
// build array of joint corresponding to IK chain
-static int convert_channels(IK_Scene *ikscene, PoseTree *tree, float ctime)
+static int convert_channels(const struct EvaluationContext *eval_ctx, IK_Scene *ikscene, PoseTree *tree, float ctime)
{
IK_Channel *ikchan;
bPoseChannel *pchan;
@@ -880,7 +880,7 @@ static int convert_channels(IK_Scene *ikscene, PoseTree *tree, float ctime)
// this is because some of the pose data (e.g. pose head) don't have corresponding
// joint angles and can't be applied to the iTaSC armature dynamically
if (!(pchan->flag & POSE_DONE))
- BKE_pose_where_is_bone(ikscene->blscene, ikscene->blArmature, pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, ikscene->blscene, ikscene->blArmature, pchan, ctime, 1);
// tell blender that this channel was controlled by IK, it's cleared on each BKE_pose_where_is()
pchan->flag |= (POSE_DONE | POSE_CHAIN);
@@ -1056,7 +1056,7 @@ static void BKE_pose_rest(IK_Scene *ikscene)
}
}
-static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan, float ctime)
+static IK_Scene *convert_tree(const struct EvaluationContext *eval_ctx, Scene *blscene, Object *ob, bPoseChannel *pchan, float ctime)
{
PoseTree *tree = (PoseTree *)pchan->iktree.first;
PoseTarget *target;
@@ -1134,7 +1134,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan, f
std::vector<double> weights;
double weight[3];
// build the array of joints corresponding to the IK chain
- convert_channels(ikscene, tree, ctime);
+ convert_channels(eval_ctx, ikscene, tree, ctime);
if (ingame) {
// in the GE, set the initial joint angle to match the current pose
// this will update the jointArray in ikscene
@@ -1397,7 +1397,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan, f
// we can now add the armature
// the armature is based on a moving frame.
// initialize with the correct position in case there is no cache
- base_callback(iTaSC::Timestamp(), iTaSC::F_identity, initPose, ikscene);
+ base_callback(eval_ctx, iTaSC::Timestamp(), iTaSC::F_identity, initPose, ikscene);
ikscene->base = new iTaSC::MovingFrame(initPose);
ikscene->base->setCallback(base_callback, ikscene);
std::string armname;
@@ -1458,7 +1458,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan, f
mul_m4_m4m4(iktarget->eeRest, invBaseFrame, mat);
iktarget->eeBlend = (!ikscene->polarConstraint && condata->type == CONSTRAINT_IK_COPYPOSE) ? true : false;
// use target_callback to make sure the initPose includes enforce coefficient
- target_callback(iTaSC::Timestamp(), iTaSC::F_identity, initPose, iktarget);
+ target_callback(eval_ctx, iTaSC::Timestamp(), iTaSC::F_identity, initPose, iktarget);
iktarget->target = new iTaSC::MovingFrame(initPose);
iktarget->target->setCallback(target_callback, iktarget);
ret = scene->addObject(iktarget->targetName, iktarget->target);
@@ -1526,7 +1526,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan, f
return ikscene;
}
-static void create_scene(Scene *scene, Object *ob, float ctime)
+static void create_scene(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float ctime)
{
bPoseChannel *pchan;
@@ -1537,7 +1537,7 @@ static void create_scene(Scene *scene, Object *ob, float ctime)
if (tree) {
IK_Data *ikdata = get_ikdata(ob->pose);
// convert tree in iTaSC::Scene
- IK_Scene *ikscene = convert_tree(scene, ob, pchan, ctime);
+ IK_Scene *ikscene = convert_tree(eval_ctx, scene, ob, pchan, ctime);
if (ikscene) {
ikscene->next = ikdata->first;
ikdata->first = ikscene;
@@ -1576,7 +1576,7 @@ static int init_scene(Object *ob)
return 0;
}
-static void execute_scene(Scene *blscene, IK_Scene *ikscene, bItasc *ikparam, float ctime, float frtime)
+static void execute_scene(const struct EvaluationContext *eval_ctx, Scene *blscene, IK_Scene *ikscene, bItasc *ikparam, float ctime, float frtime)
{
int i;
IK_Channel *ikchan;
@@ -1592,7 +1592,7 @@ static void execute_scene(Scene *blscene, IK_Scene *ikscene, bItasc *ikparam, fl
// in animation mode, we must get the bone position from action and constraints
for (i = 0, ikchan = ikscene->channels; i < ikscene->numchan; i++, ++ikchan) {
if (!(ikchan->pchan->flag & POSE_DONE))
- BKE_pose_where_is_bone(blscene, ikscene->blArmature, ikchan->pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, blscene, ikscene->blArmature, ikchan->pchan, ctime, 1);
// tell blender that this channel was controlled by IK, it's cleared on each BKE_pose_where_is()
ikchan->pchan->flag |= (POSE_DONE | POSE_CHAIN);
ikchan->jointValid = 0;
@@ -1647,7 +1647,7 @@ static void execute_scene(Scene *blscene, IK_Scene *ikscene, bItasc *ikparam, fl
}
}
// don't cache if we are reiterating because we don't want to destroy the cache unnecessarily
- ikscene->scene->update(timestamp, timestep, numstep, false, !reiterate, simulation);
+ ikscene->scene->update(eval_ctx, timestamp, timestep, numstep, false, !reiterate, simulation);
if (reiterate) {
// how many times do we reiterate?
for (i = 0; i < ikparam->numiter; i++) {
@@ -1656,11 +1656,11 @@ static void execute_scene(Scene *blscene, IK_Scene *ikscene, bItasc *ikparam, fl
{
break;
}
- ikscene->scene->update(timestamp, timestep, numstep, true, false, simulation);
+ ikscene->scene->update(eval_ctx, timestamp, timestep, numstep, true, false, simulation);
}
if (simulation) {
// one more fake iteration to cache
- ikscene->scene->update(timestamp, 0.0, 1, true, true, true);
+ ikscene->scene->update(eval_ctx, timestamp, 0.0, 1, true, true, true);
}
}
// compute constraint error
@@ -1744,7 +1744,7 @@ static void execute_scene(Scene *blscene, IK_Scene *ikscene, bItasc *ikparam, fl
//---------------------------------------------------
// plugin interface
//
-void itasc_initialize_tree(struct Scene *scene, Object *ob, float ctime)
+void itasc_initialize_tree(const struct EvaluationContext *eval_ctx, struct Scene *scene, Object *ob, float ctime)
{
bPoseChannel *pchan;
int count = 0;
@@ -1764,13 +1764,13 @@ void itasc_initialize_tree(struct Scene *scene, Object *ob, float ctime)
// if at least one tree, create the scenes from the PoseTree stored in the channels
// postpone until execute_tree: this way the pose constraint are included
if (count)
- create_scene(scene, ob, ctime);
+ create_scene(eval_ctx, scene, ob, ctime);
itasc_update_param(ob->pose);
// make sure we don't rebuilt until the user changes something important
ob->pose->flag &= ~POSE_WAS_REBUILT;
}
-void itasc_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
+void itasc_execute_tree(const struct EvaluationContext *eval_ctx, struct Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
{
if (ob->pose->ikdata) {
IK_Data *ikdata = (IK_Data *)ob->pose->ikdata;
@@ -1787,7 +1787,7 @@ void itasc_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan_ro
if (timestep > 0.2f)
timestep = 0.2f;
}
- execute_scene(scene, ikscene, ikparam, ctime, timestep);
+ execute_scene(eval_ctx, scene, ikscene, ikparam, ctime, timestep);
break;
}
}
diff --git a/source/blender/ikplugin/intern/itasc_plugin.h b/source/blender/ikplugin/intern/itasc_plugin.h
index bcd95bc31ca..2f4e4036d76 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.h
+++ b/source/blender/ikplugin/intern/itasc_plugin.h
@@ -40,8 +40,8 @@
extern "C" {
#endif
-void itasc_initialize_tree(struct Scene *scene, struct Object *ob, float ctime);
-void itasc_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan_root, float ctime);
+void itasc_initialize_tree(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime);
+void itasc_execute_tree(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan_root, float ctime);
void itasc_release_tree(struct Scene *scene, struct Object *ob, float ctime);
void itasc_clear_data(struct bPose *pose);
void itasc_clear_cache(struct bPose *pose);
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c
index 3629332a4ac..8c427dff4a3 100644
--- a/source/blender/imbuf/intern/thumbs.c
+++ b/source/blender/imbuf/intern/thumbs.c
@@ -44,10 +44,10 @@
#include "BLI_threads.h"
#include BLI_SYSTEM_PID_H
-#include "BLO_readfile.h"
-
#include "DNA_space_types.h" /* For FILE_MAX_LIBEXTRA */
+#include "BLO_readfile.h"
+
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_thumbs.h"
diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c
index b5c6deb6b01..00fb1a44dff 100644
--- a/source/blender/imbuf/intern/thumbs_blend.c
+++ b/source/blender/imbuf/intern/thumbs_blend.c
@@ -32,6 +32,7 @@
#include "BLI_endian_switch.h"
#include "BLI_fileops.h"
#include "BLI_linklist.h"
+#include "BLI_listbase.h" /* Needed due to import of BLO_readfile.h */
#include "BLO_blend_defs.h"
#include "BLO_readfile.h"
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 923df70dd4d..4e1161148ea 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -96,6 +96,17 @@ enum {
IDP_STRING_SUB_BYTE = 1, /* arbitrary byte array, _not_ null terminated */
};
+/* IDP_GROUP */
+enum {
+ IDP_GROUP_SUB_NONE = 0, /* default */
+ IDP_GROUP_SUB_MODE_OBJECT = 1, /* object mode settings */
+ IDP_GROUP_SUB_MODE_EDIT = 2, /* mesh edit mode settings */
+ IDP_GROUP_SUB_ENGINE_RENDER = 3, /* render engine settings */
+ IDP_GROUP_SUB_OVERRIDE = 4, /* data override */
+ IDP_GROUP_SUB_MODE_PAINT_WEIGHT = 5, /* weight paint mode settings */
+ IDP_GROUP_SUB_MODE_PAINT_VERTEX = 6, /* vertex paint mode settings */
+};
+
/*->flag*/
enum {
IDP_FLAG_GHOST = 1 << 7, /* this means the property is set but RNA will return false when checking
@@ -104,6 +115,76 @@ enum {
/* add any future new id property types here.*/
+
+/* Static ID override structs. */
+
+typedef struct IDOverrideStaticPropertyOperation {
+ struct IDOverrideStaticPropertyOperation *next, *prev;
+
+ /* Type of override. */
+ short operation;
+ short flag;
+ short pad_s1[2];
+
+ /* Sub-item references, if needed (for arrays or collections only).
+ * We need both reference and local values to allow e.g. insertion into collections (constraints, modifiers...).
+ * In collection case, if names are defined, they are used in priority.
+ * Names are pointers (instead of char[64]) to save some space, NULL when unset.
+ * Indices are -1 when unset. */
+ char *subitem_reference_name;
+ char *subitem_local_name;
+ int subitem_reference_index;
+ int subitem_local_index;
+} IDOverrideStaticPropertyOperation;
+
+/* IDOverridePropertyOperation->operation. */
+enum {
+ /* Basic operations. */
+ IDOVERRIDESTATIC_OP_NOOP = 0, /* Special value, forbids any overriding. */
+
+ IDOVERRIDESTATIC_OP_REPLACE = 1, /* Fully replace local value by reference one. */
+
+ /* Numeric-only operations. */
+ IDOVERRIDESTATIC_OP_ADD = 101, /* Add local value to reference one. */
+ /* Subtract local value from reference one (needed due to unsigned values etc.). */
+ IDOVERRIDESTATIC_OP_SUBTRACT = 102,
+ /* Multiply reference value by local one (more useful than diff for scales and the like). */
+ IDOVERRIDESTATIC_OP_MULTIPLY = 103,
+
+ /* Collection-only operations. */
+ IDOVERRIDESTATIC_OP_INSERT_AFTER = 201, /* Insert after given reference's subitem. */
+ IDOVERRIDESTATIC_OP_INSERT_BEFORE = 202, /* Insert before given reference's subitem. */
+ /* We can add more if needed (move, delete, ...). */
+};
+
+/* IDOverridePropertyOperation->flag. */
+enum {
+ IDOVERRIDESTATIC_FLAG_MANDATORY = 1 << 0, /* User cannot remove that override operation. */
+ IDOVERRIDESTATIC_FLAG_LOCKED = 1 << 1, /* User cannot change that override operation. */
+};
+
+/* A single overriden property, contain all operations on this one. */
+typedef struct IDOverrideStaticProperty {
+ struct IDOverrideStaticProperty *next, *prev;
+
+ /* Path from ID to overridden property. *Does not* include indices/names for final arrays/collections items. */
+ char *rna_path;
+
+ ListBase operations; /* List of overriding operations (IDOverridePropertyOperation) applied to this property. */
+} IDOverrideStaticProperty;
+
+/* Main container for all overriding data info of a data-block. */
+typedef struct IDOverrideStatic {
+ struct ID *reference; /* Reference linked ID which this one overrides. */
+ ListBase properties; /* List of IDOverrideProperty structs. */
+
+ /* Read/write data. */
+ /* Temp ID storing extra override data (used for differential operations only currently).
+ * Always NULL outside of read/write context. */
+ struct ID *storage;
+} IDOverrideStatic;
+
+
/* watch it: Sequence has identical beginning. */
/**
* ID is the first thing included in all serializable types. It
@@ -131,6 +212,12 @@ typedef struct ID {
int us;
int icon_id;
IDProperty *properties;
+
+ IDOverrideStatic *override_static; /* Reference linked ID which this one overrides. */
+
+ void *py_instance;
+
+ void *pad1;
} ID;
/**
@@ -253,6 +340,8 @@ typedef enum ID_Type {
ID_PAL = MAKE_ID2('P', 'L'), /* Palette */
ID_PC = MAKE_ID2('P', 'C'), /* PaintCurve */
ID_CF = MAKE_ID2('C', 'F'), /* CacheFile */
+ ID_WS = MAKE_ID2('W', 'S'), /* WorkSpace */
+ ID_LP = MAKE_ID2('L', 'P'), /* LightProbe */
} ID_Type;
/* Only used as 'placeholder' in .blend files for directly linked datablocks. */
@@ -276,7 +365,7 @@ typedef enum ID_Type {
#define ID_REAL_USERS(id) (((ID *)id)->us - ID_FAKE_USERS(id))
#define ID_EXTRA_USERS(id) (((ID *)id)->tag & LIB_TAG_EXTRAUSER ? 1 : 0)
-#define ID_CHECK_UNDO(id) ((GS((id)->name) != ID_SCR) && (GS((id)->name) != ID_WM))
+#define ID_CHECK_UNDO(id) ((GS((id)->name) != ID_SCR) && (GS((id)->name) != ID_WM) && (GS((id)->name) != ID_WS))
#define ID_BLEND_PATH(_bmain, _id) ((_id)->lib ? (_id)->lib->filepath : (_bmain)->name)
@@ -295,7 +384,8 @@ typedef enum ID_Type {
/* id->flag (persitent). */
enum {
- LIB_FAKEUSER = 1 << 9,
+ LIB_OVERRIDE_STATIC_AUTO = 1 << 0, /* Allow automatic generation of overriding rules. */
+ LIB_FAKEUSER = 1 << 9,
};
/**
@@ -330,6 +420,9 @@ enum {
/* RESET_NEVER tag datablock as a place-holder (because the real one could not be linked from its library e.g.). */
LIB_TAG_MISSING = 1 << 6,
+ /* RESET_NEVER tag datablock as being up-to-date regarding its reference. */
+ LIB_TAG_OVERRIDESTATIC_OK = 1 << 9,
+
/* tag datablock has having an extra user. */
LIB_TAG_EXTRAUSER = 1 << 2,
/* tag datablock has having actually increased usercount for the extra virtual user. */
@@ -350,12 +443,16 @@ enum {
LIB_TAG_ANIM_NO_RECALC = 1 << 14,
LIB_TAG_ID_RECALC_ALL = (LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA),
+ /* The datablock is a copy-on-write version. */
+ LIB_TAG_COPY_ON_WRITE = 1 << 15,
+ LIB_TAG_COPY_ON_WRITE_EVAL = 1 << 16,
+
/* RESET_NEVER tag datablock for freeing etc. behavior (usually set when copying real one into temp/runtime one). */
- LIB_TAG_NO_MAIN = 1 << 16, /* Datablock is not listed in Main database. */
- LIB_TAG_NO_USER_REFCOUNT = 1 << 17, /* Datablock does not refcount usages of other IDs. */
+ LIB_TAG_NO_MAIN = 1 << 17, /* Datablock is not listed in Main database. */
+ LIB_TAG_NO_USER_REFCOUNT = 1 << 18, /* Datablock does not refcount usages of other IDs. */
/* Datablock was not allocated by standard system (BKE_libblock_alloc), do not free its memory
* (usual type-specific freeing is called though). */
- LIB_TAG_NOT_ALLOCATED = 1 << 18,
+ LIB_TAG_NOT_ALLOCATED = 1 << 19,
};
/* To filter ID types (filter_id) */
@@ -393,9 +490,11 @@ enum {
FILTER_ID_WO = (1 << 26),
FILTER_ID_PA = (1 << 27),
FILTER_ID_CF = (1 << 28),
+ FILTER_ID_WS = (1 << 29),
+ FILTER_ID_LP = (1u << 31),
};
-/* IMPORTANT: this enum matches the order currently use in set_lisbasepointers,
+/* IMPORTANT: this enum matches the order currently use in set_listbasepointers,
* keep them in sync! */
enum {
INDEX_ID_LI = 0,
@@ -424,12 +523,14 @@ enum {
INDEX_ID_BR,
INDEX_ID_PA,
INDEX_ID_SPK,
+ INDEX_ID_LP,
INDEX_ID_WO,
INDEX_ID_MC,
INDEX_ID_SCR,
INDEX_ID_OB,
INDEX_ID_LS,
INDEX_ID_SCE,
+ INDEX_ID_WS,
INDEX_ID_WM,
INDEX_ID_MSK,
INDEX_ID_NULL,
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index a7f3d27e9d2..c8780c6b4b8 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -180,6 +180,18 @@ typedef enum eMotionPaths_BakeFlag {
MOTIONPATH_BAKE_HAS_PATHS = (1 << 2)
} eMotionPath_BakeFlag;
+/* runtime */
+#
+#
+typedef struct bPoseChannelDrawData {
+ float solid_color[4];
+ float wire_color[4];
+
+ int bbone_matrix_len;
+ /* keep last */
+ float bbone_matrix[0][4][4];
+} bPoseChannelDrawData;
+
/* ************************************************ */
/* Poses */
@@ -238,6 +250,8 @@ typedef struct bPoseChannel {
float chan_mat[4][4]; /* matrix result of loc/quat/size, and where we put deform in, see next line */
float pose_mat[4][4]; /* constraints accumulate here. in the end, pose_mat = bone->arm_mat * chan_mat
* this matrix is object space */
+ float disp_mat[4][4]; /* for display, pose_mat with bone length applied */
+ float disp_tail_mat[4][4]; /* for display, pose_mat with bone length applied and translated to tail*/
float constinv[4][4]; /* inverse result of constraints.
* doesn't include effect of restposition, parent, and local transform*/
@@ -259,8 +273,10 @@ typedef struct bPoseChannel {
struct bPoseChannel *bbone_prev; /* next/prev bones to use as handle references when calculating bbones (optional) */
struct bPoseChannel *bbone_next;
-
+
void *temp; /* use for outliner */
+ /* Runtime data for color and bbone segment matrix. */
+ bPoseChannelDrawData *draw_data;
} bPoseChannel;
diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h
index 52e40cbc098..c90599bb5cc 100644
--- a/source/blender/makesdna/DNA_camera_types.h
+++ b/source/blender/makesdna/DNA_camera_types.h
@@ -34,6 +34,8 @@
#include "DNA_defs.h"
#include "DNA_gpu_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_image_types.h"
#include "DNA_ID.h"
#ifdef __cplusplus
@@ -59,6 +61,20 @@ typedef struct CameraStereoSettings {
float pole_merge_angle_to;
} CameraStereoSettings;
+/* Background Picture */
+typedef struct CameraBGImage {
+ struct CameraBGImage *next, *prev;
+
+ struct Image *ima;
+ struct ImageUser iuser;
+ struct MovieClip *clip;
+ struct MovieClipUser cuser;
+ float offset[2], scale, rotation;
+ float alpha;
+ short flag;
+ short source;
+} CameraBGImage;
+
typedef struct Camera {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
@@ -82,9 +98,19 @@ typedef struct Camera {
struct Object *dof_ob;
struct GPUDOFSettings gpu_dof;
+ /* CameraBGImage reference images */
+ struct ListBase bg_images;
+
char sensor_fit;
char pad[7];
+ /* runtime only, used for drawing */
+ float drwcorners[4][2];
+ float drwtria[2][2];
+ float drwdepth, pad1;
+ float drwfocusmat[4][4];
+ float drwnormalmat[4][4];
+
/* Stereo settings */
struct CameraStereoSettings stereo;
} Camera;
@@ -124,6 +150,7 @@ enum {
#endif
CAM_SHOWSENSOR = (1 << 8),
CAM_SHOW_SAFE_CENTER = (1 << 9),
+ CAM_SHOW_BG_IMAGE = (1 << 10),
};
/* yafray: dof sampling switch */
@@ -159,6 +186,32 @@ enum {
CAM_S3D_POLE_MERGE = (1 << 1),
};
+/* CameraBGImage->flag */
+/* may want to use 1 for select ? */
+enum {
+ CAM_BGIMG_FLAG_EXPANDED = (1 << 1),
+ CAM_BGIMG_FLAG_CAMERACLIP = (1 << 2),
+ CAM_BGIMG_FLAG_DISABLED = (1 << 3),
+ CAM_BGIMG_FLAG_FOREGROUND = (1 << 4),
+
+ /* Camera framing options */
+ CAM_BGIMG_FLAG_CAMERA_ASPECT = (1 << 5), /* don't stretch to fit the camera view */
+ CAM_BGIMG_FLAG_CAMERA_CROP = (1 << 6), /* crop out the image */
+
+ /* Axis flip options */
+ CAM_BGIMG_FLAG_FLIP_X = (1 << 7),
+ CAM_BGIMG_FLAG_FLIP_Y = (1 << 8),
+};
+
+#define CAM_BGIMG_FLAG_EXPANDED (CAM_BGIMG_FLAG_EXPANDED | CAM_BGIMG_FLAG_CAMERACLIP)
+
+/* CameraBGImage->source */
+/* may want to use 1 for select ?*/
+enum {
+ CAM_BGIMG_SOURCE_IMAGE = 0,
+ CAM_BGIMG_SOURCE_MOVIE = 1,
+};
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 2207b0ec0b1..261e0a5410f 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -267,6 +267,7 @@ typedef struct Curve {
char pad2[2];
+ void *batch_cache;
} Curve;
#define CURVE_VFONT_ANY(cu) \
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index 2d1ffaa53eb..0e0b1d669d9 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -92,13 +92,13 @@ typedef enum CustomDataType {
CD_MCOL = 6,
CD_ORIGINDEX = 7,
CD_NORMAL = 8,
-/* CD_POLYINDEX = 9, */
+ CD_FACEMAP = 9, /* exclusive face group, each face can only be part of one */
CD_PROP_FLT = 10,
CD_PROP_INT = 11,
CD_PROP_STR = 12,
CD_ORIGSPACE = 13, /* for modifier stack face location mapping */
CD_ORCO = 14,
- CD_MTEXPOLY = 15,
+/* CD_MTEXPOLY = 15, */ /* deprecated */
CD_MLOOPUV = 16,
CD_MLOOPCOL = 17,
CD_TANGENT = 18,
@@ -143,13 +143,13 @@ typedef enum CustomDataType {
#define CD_MASK_MCOL (1 << CD_MCOL)
#define CD_MASK_ORIGINDEX (1 << CD_ORIGINDEX)
#define CD_MASK_NORMAL (1 << CD_NORMAL)
-// #define CD_MASK_POLYINDEX (1 << CD_POLYINDEX)
+#define CD_MASK_FACEMAP (1 << CD_FACEMAP)
#define CD_MASK_PROP_FLT (1 << CD_PROP_FLT)
#define CD_MASK_PROP_INT (1 << CD_PROP_INT)
#define CD_MASK_PROP_STR (1 << CD_PROP_STR)
#define CD_MASK_ORIGSPACE (1 << CD_ORIGSPACE)
#define CD_MASK_ORCO (1 << CD_ORCO)
-#define CD_MASK_MTEXPOLY (1 << CD_MTEXPOLY)
+// #define CD_MASK_MTEXPOLY (1 << CD_MTEXPOLY) /* DEPRECATED */
#define CD_MASK_MLOOPUV (1 << CD_MLOOPUV)
#define CD_MASK_MLOOPCOL (1 << CD_MLOOPCOL)
#define CD_MASK_TANGENT (1 << CD_TANGENT)
diff --git a/source/blender/makesdna/DNA_defs.h b/source/blender/makesdna/DNA_defs.h
index fc9dd8f06a9..bfa8da02707 100644
--- a/source/blender/makesdna/DNA_defs.h
+++ b/source/blender/makesdna/DNA_defs.h
@@ -44,6 +44,12 @@
# endif
#endif
+#ifdef __GNUC__
+# define DNA_PRIVATE_ATTR __attribute__ ((deprecated))
+#else
+# define DNA_PRIVATE_ATTR
+#endif
+
/* poison pragma */
#ifdef DNA_DEPRECATED_ALLOW
diff --git a/source/blender/makesdna/DNA_fileglobal_types.h b/source/blender/makesdna/DNA_fileglobal_types.h
index b2ab0d2a08d..ed9640c365f 100644
--- a/source/blender/makesdna/DNA_fileglobal_types.h
+++ b/source/blender/makesdna/DNA_fileglobal_types.h
@@ -32,9 +32,6 @@
#ifndef __DNA_FILEGLOBAL_TYPES_H__
#define __DNA_FILEGLOBAL_TYPES_H__
-struct bScreen;
-struct Scene;
-
/**
* FileGlobal stores a part of the current user-interface settings at
* the moment of saving, and the file-specific settings.
@@ -46,6 +43,9 @@ typedef struct FileGlobal {
char pad[6];
struct bScreen *curscreen;
struct Scene *curscene;
+ struct ViewLayer *cur_view_layer;
+ void *pad1;
+
int fileflags;
int globalf;
uint64_t build_commit_timestamp; /* commit timestamp from buildinfo */
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index a62538d1032..d5a5a1d5d4a 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -128,7 +128,7 @@ typedef enum eGPDpalettecolor_Flag {
PC_COLOR_LOCKED = (1 << 2),
/* do onion skinning */
PC_COLOR_ONIONSKIN = (1 << 3),
- /* "volumetric" strokes (i.e. GLU Quadric discs in 3D) */
+ /* "volumetric" strokes */
PC_COLOR_VOLUMETRIC = (1 << 4),
/* Use High quality fill */
PC_COLOR_HQ_FILL = (1 << 5)
@@ -273,7 +273,7 @@ typedef enum eGPDlayer_Flag {
GP_LAYER_GHOST_PREVCOL = (1 << 8),
/* use custom color for ghosts after current frame */
GP_LAYER_GHOST_NEXTCOL = (1 << 9),
- /* "volumetric" strokes (i.e. GLU Quadric discs in 3D) */
+ /* "volumetric" strokes */
GP_LAYER_VOLUMETRIC = (1 << 10),
/* Use high quality fill (instead of buggy legacy OpenGL Fill) */
GP_LAYER_HQ_FILL = (1 << 11),
@@ -300,6 +300,7 @@ typedef struct bGPdata {
short sbuffer_sflag; /* flags for stroke that cache represents */
void *sbuffer; /* stroke buffer (can hold GP_STROKE_BUFFER_MAX) */
float scolor[4]; /* buffer color using palettes */
+ float sfill[4]; /* buffer fill color */
char pad[6]; /* padding for compiler alignment error */
short sflag; /* settings for palette color */
diff --git a/source/blender/makesdna/DNA_gpu_types.h b/source/blender/makesdna/DNA_gpu_types.h
index 967cb7284dc..be34309572f 100644
--- a/source/blender/makesdna/DNA_gpu_types.h
+++ b/source/blender/makesdna/DNA_gpu_types.h
@@ -38,6 +38,8 @@ typedef struct GPUDOFSettings {
float fstop;
float focal_length;
float sensor;
+ float rotation;
+ float ratio;
int num_blades;
int high_quality;
} GPUDOFSettings;
diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h
index 45dd0cb9ff2..8f15aa85e97 100644
--- a/source/blender/makesdna/DNA_group_types.h
+++ b/source/blender/makesdna/DNA_group_types.h
@@ -60,6 +60,13 @@ typedef struct Group {
* on the last used scene */
unsigned int layer;
float dupli_ofs[3];
+
+ struct SceneCollection *collection;
+ struct ViewLayer *view_layer;
} Group;
+
+#define GROUP_MASTER_COLLECTION(_group) \
+ (((LayerCollection *)(_group)->view_layer->layer_collections.first)->scene_collection)
+
#endif /* __DNA_GROUP_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h
index a2e39f93875..92703fa2d3b 100644
--- a/source/blender/makesdna/DNA_lamp_types.h
+++ b/source/blender/makesdna/DNA_lamp_types.h
@@ -67,7 +67,7 @@ typedef struct Lamp {
short pad2;
float clipsta, clipend;
- float bias, soft, compressthresh, bleedbias, pad5;
+ float bias, soft, compressthresh, bleedbias, bleedexp;
short bufsize, samp, buffers, filtertype;
char bufflag, buftype;
@@ -106,6 +106,14 @@ typedef struct Lamp {
short pr_texture, use_nodes;
char pad6[4];
+ /* Eevee */
+ float cascade_max_dist;
+ float cascade_exponent;
+ float cascade_fade;
+ int cascade_count;
+
+ float contact_dist, contact_bias, contact_spread, contact_thickness;
+
/* preview */
struct PreviewImage *preview;
@@ -151,6 +159,7 @@ typedef struct Lamp {
#define LA_SHAD_TEX (1 << 16)
#define LA_SHOW_CONE (1 << 17)
#define LA_SHOW_SHADOW_BOX (1 << 18)
+#define LA_SHAD_CONTACT (1 << 19)
/* layer_shadow */
#define LA_LAYER_SHADOW_BOTH 0
diff --git a/source/blender/makesdna/DNA_lattice_types.h b/source/blender/makesdna/DNA_lattice_types.h
index 242d6f0feeb..28a401676fc 100644
--- a/source/blender/makesdna/DNA_lattice_types.h
+++ b/source/blender/makesdna/DNA_lattice_types.h
@@ -69,6 +69,7 @@ typedef struct Lattice {
char vgroup[64]; /* multiply the influence, MAX_VGROUP_NAME */
struct EditLatt *editlatt;
+ void *batch_cache;
} Lattice;
/* ***************** LATTICE ********************* */
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
new file mode 100644
index 00000000000..c677383cb6e
--- /dev/null
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -0,0 +1,164 @@
+/*
+ * ***** 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_freestyle_types.h"
+#include "DNA_listBase.h"
+
+typedef struct Base {
+ struct Base *next, *prev;
+ short flag;
+ short refcount;
+ short sx, sy;
+ struct Object *object;
+ unsigned int lay;
+ int flag_legacy;
+ struct IDProperty *collection_properties; /* used by depsgraph, flushed from collection-tree */
+} Base;
+
+typedef struct CollectionOverride {
+ struct CollectionOverride *next, *prev;
+ char name[64]; /* MAX_NAME */
+ /* TODO proper data */
+} CollectionOverride;
+
+typedef struct ViewLayerEngineData {
+ struct ViewLayerEngineData *next, *prev;
+ struct DrawEngineType *engine_type;
+ void *storage;
+ void (*free)(void *storage);
+} ViewLayerEngineData;
+
+typedef struct LayerCollection {
+ struct LayerCollection *next, *prev;
+ struct SceneCollection *scene_collection;
+ short flag;
+ /* TODO(sergey): Get rid of this once we've got CoW in DEG, */
+ short flag_evaluated;
+ short pad[2];
+ ListBase object_bases; /* (ObjectBase *)LinkData->data - synced with collection->objects and collection->filter_objects */
+ ListBase overrides;
+ ListBase layer_collections; /* synced with collection->collections */
+ struct IDProperty *properties; /* overrides */
+ struct IDProperty *properties_evaluated;
+} LayerCollection;
+
+typedef struct ViewLayer {
+ struct ViewLayer *next, *prev;
+ char name[64]; /* MAX_NAME */
+ short active_collection;
+ short flag;
+ short pad[2];
+ ListBase object_bases; /* ObjectBase */
+ struct SceneStats *stats; /* default allocated now */
+ struct Base *basact;
+ ListBase layer_collections; /* LayerCollection */
+ struct IDProperty *properties; /* overrides */
+ struct IDProperty *properties_evaluated;
+
+ /* Old SceneRenderLayer data. */
+ int layflag;
+ int passflag; /* pass_xor has to be after passflag */
+ int pass_xor;
+ float pass_alpha_threshold;
+
+ struct IDProperty *id_properties; /* Equivalent to datablocks ID properties. */
+
+ struct FreestyleConfig freestyle_config;
+
+ /* Runtime data */
+ ListBase drawdata; /* ViewLayerEngineData */
+} ViewLayer;
+
+typedef struct SceneCollection {
+ struct SceneCollection *next, *prev;
+ char name[64]; /* MAX_NAME */
+ char filter[64]; /* MAX_NAME */
+ int active_object_index; /* for UI */
+ char type;
+ char pad[3];
+ 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),
+ BASE_FROM_SET = (1 << 5), /* To be set only by the depsgraph */
+};
+
+/* LayerCollection->flag */
+enum {
+ COLLECTION_VISIBLE = (1 << 0),
+ COLLECTION_SELECTABLE = (1 << 1),
+ COLLECTION_DISABLED = (1 << 2),
+};
+
+/* ViewLayer->flag */
+enum {
+ VIEW_LAYER_RENDER = (1 << 0),
+ VIEW_LAYER_ENGINE_DIRTY = (1 << 1),
+ VIEW_LAYER_FREESTYLE = (1 << 2),
+};
+
+/* SceneCollection->type */
+enum {
+ COLLECTION_TYPE_NONE = 0,
+ COLLECTION_TYPE_GROUP_INTERNAL = 1,
+};
+
+/* *************************************************************** */
+/* Engine Settings */
+
+/* CollectionEngineSettings->type */
+typedef enum CollectionEngineSettingsType {
+ COLLECTION_MODE_NONE = 0,
+ COLLECTION_MODE_OBJECT = 1,
+ COLLECTION_MODE_EDIT = 2,
+ COLLECTION_MODE_PAINT_WEIGHT = 5,
+ COLLECTION_MODE_PAINT_VERTEX = 6,
+} CollectionModeSettingsType;
+
+/* *************************************************************** */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DNA_LAYER_TYPES_H__ */
+
diff --git a/source/blender/makesdna/DNA_lightprobe_types.h b/source/blender/makesdna/DNA_lightprobe_types.h
new file mode 100644
index 00000000000..75705f7dd37
--- /dev/null
+++ b/source/blender/makesdna/DNA_lightprobe_types.h
@@ -0,0 +1,109 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file DNA_lightprobe_types.h
+ * \ingroup DNA
+ */
+
+#ifndef __DNA_LIGHTPROBE_TYPES_H__
+#define __DNA_LIGHTPROBE_TYPES_H__
+
+#include "DNA_defs.h"
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Object;
+struct AnimData;
+
+typedef struct LightProbe {
+ ID id;
+ struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
+
+ char type; /* For realtime probe objects */
+ char flag; /* General purpose flags for probes */
+ char attenuation_type; /* Attenuation type */
+ char parallax_type; /* Parallax type */
+
+ float distinf; /* Influence Radius */
+ float distpar; /* Parallax Radius */
+ float falloff; /* Influence falloff */
+
+ float clipsta, clipend;
+
+ float vis_bias, vis_bleedbias; /* VSM visibility biases */
+ float vis_blur, pad2;
+
+ int grid_resolution_x; /* Irradiance grid resolution */
+ int grid_resolution_y;
+ int grid_resolution_z;
+ int pad1;
+
+ struct Object *parallax_ob; /* Object to use as a parallax origin */
+ struct Image *image; /* Image to use on as lighting data */
+
+ float data_draw_size;
+
+ /* Runtime display data */
+ float distfalloff, distgridinf;
+ float pad;
+} LightProbe;
+
+/* Probe->type */
+enum {
+ LIGHTPROBE_TYPE_CUBE = 0,
+ LIGHTPROBE_TYPE_PLANAR = 1,
+ LIGHTPROBE_TYPE_GRID = 2,
+};
+
+/* Probe->flag */
+enum {
+ LIGHTPROBE_FLAG_CUSTOM_PARALLAX = (1 << 0),
+ LIGHTPROBE_FLAG_SHOW_INFLUENCE = (1 << 1),
+ LIGHTPROBE_FLAG_SHOW_PARALLAX = (1 << 2),
+ LIGHTPROBE_FLAG_SHOW_CLIP_DIST = (1 << 3),
+ LIGHTPROBE_FLAG_SHOW_DATA = (1 << 4),
+};
+
+/* Probe->display */
+enum {
+ LIGHTPROBE_DISP_WIRE = 0,
+ LIGHTPROBE_DISP_SHADED = 1,
+ LIGHTPROBE_DISP_DIFFUSE = 2,
+ LIGHTPROBE_DISP_REFLECTIVE = 3,
+};
+
+/* Probe->parallax && Probe->attenuation_type*/
+enum {
+ LIGHTPROBE_SHAPE_ELIPSOID = 0,
+ LIGHTPROBE_SHAPE_BOX = 1,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DNA_LIGHTPROBE_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 0c500e366a7..bc33b7ba6e2 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -90,6 +90,16 @@ typedef struct TexPaintSlot {
int pad;
} TexPaintSlot;
+/* Clay engine */
+
+/* MaterialRuntimeClay.flag */
+#define CLAY_OUTDATED 1
+
+/* 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) */
@@ -201,6 +211,18 @@ typedef struct Material {
char nmap_tangent_names[9][64]; /* [MAX_MTFACE+1][MAX_NAME]; +1 for empty name */
int nmap_tangent_names_count, pad5;
+ /* Transparency */
+ float alpha_threshold;
+ float refract_depth;
+ char blend_method;
+ char blend_shadow;
+ char blend_flag;
+ char pad6[5];
+
+ /* image to use for image/uv space, also bake target
+ * (not to be used shading/rendering pipeline, this is editor featyure only!). */
+ struct Image *edit_image;
+
struct TexPaintSlot *texpaintslot; /* cached slot for painting. Make sure to recalculate before use
* with refresh_texpaint_image_cache */
ListBase gpumaterial; /* runtime */
@@ -275,7 +297,7 @@ typedef struct Material {
#define MA_ONLYSHADOW 1024
#define MA_HALO_XALPHA 1024
#define MA_STAR 0x800
-#define MA_FACETEXTURE 0x800
+// #define MA_FACETEXTURE 0x800 /* deprecated */
#define MA_HALOTEX 0x1000
#define MA_HALOPUNO 0x2000
#define MA_ONLYCAST 0x2000
@@ -297,7 +319,7 @@ typedef struct Material {
/* qdn: a bit clumsy this, tangents needed for normal maps separated from shading */
#define MA_NORMAP_TANG 0x8000000
#define MA_GROUP_NOLAY 0x10000000
-#define MA_FACETEXTURE_ALPHA 0x20000000
+// #define MA_FACETEXTURE_ALPHA 0x20000000 /* deprecated */
#define MA_STR_B_UNITS 0x40000000
#define MA_STR_SURFDIFF 0x80000000
@@ -477,5 +499,31 @@ typedef struct Material {
#define MA_VOL_SHADE_MULTIPLE 3
#define MA_VOL_SHADE_SHADEDPLUSMULTIPLE 4
+/* blend_method */
+enum {
+ MA_BM_SOLID,
+ MA_BM_ADD,
+ MA_BM_MULTIPLY,
+ MA_BM_CLIP,
+ MA_BM_HASHED,
+ MA_BM_BLEND,
+};
+
+/* blend_flag */
+enum {
+ MA_BL_HIDE_BACKSIDE = (1 << 0),
+ MA_BL_SS_REFRACTION = (1 << 1),
+ MA_BL_SS_SUBSURFACE = (1 << 2),
+ MA_BL_TRANSLUCENCY = (1 << 3),
+};
+
+/* blend_shadow */
+enum {
+ MA_BS_NONE = 0,
+ MA_BS_SOLID,
+ MA_BS_CLIP,
+ MA_BS_HASHED,
+};
+
#endif
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 39e56925903..505b1f7157b 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -66,7 +66,6 @@ typedef struct Mesh {
/* BMESH ONLY */
/*new face structures*/
struct MPoly *mpoly;
- struct MTexPoly *mtpoly;
struct MLoop *mloop;
struct MLoopUV *mloopuv;
struct MLoopCol *mloopcol;
@@ -127,6 +126,7 @@ typedef struct Mesh {
short totcol;
struct Multires *mr DNA_DEPRECATED; /* deprecated multiresolution modeling data, only keep for loading old files */
+ void *batch_cache;
} Mesh;
/* deprecated by MTFace, only here for file reading */
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 8bb711339f7..6d38fe22ea1 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -186,22 +186,9 @@ typedef struct MVertTri {
unsigned int tri[3];
} MVertTri;
-
-typedef struct MTexPoly {
- struct Image *tpage;
- char flag, transp;
- short mode, tile, pad;
-} MTexPoly;
-
-/* can copy from/to MTexPoly/MTFace */
-#define ME_MTEXFACE_CPY(dst, src) \
-{ \
- (dst)->tpage = (src)->tpage; \
- (dst)->flag = (src)->flag; \
- (dst)->transp = (src)->transp; \
- (dst)->mode = (src)->mode; \
- (dst)->tile = (src)->tile; \
-} (void)0
+//typedef struct MTexPoly {
+// void *pad;
+//} MTexPoly;
typedef struct MLoopUV {
float uv[2];
@@ -256,9 +243,6 @@ typedef struct MSelect {
/*tessellation uv face data*/
typedef struct MTFace {
float uv[4][2];
- struct Image *tpage;
- char flag, transp;
- short mode, tile, unwrap;
} MTFace;
/*Custom Data Properties*/
@@ -463,58 +447,4 @@ enum {
ME_FSEL = 2,
};
-/* mtface->flag */
-enum {
- // TF_SELECT = (1 << 0), /* use MFace hide flag (after 2.43), should be able to reuse after 2.44 */
- // TF_ACTIVE = (1 << 1), /* deprecated! */
- TF_SEL1 = (1 << 2),
- TF_SEL2 = (1 << 3),
- TF_SEL3 = (1 << 4),
- TF_SEL4 = (1 << 5),
-};
-
-/* mtface->mode */
-enum {
- TF_DYNAMIC = (1 << 0),
- TF_ALPHASORT = (1 << 1),
- TF_TEX = (1 << 2),
- TF_SHAREDVERT = (1 << 3),
- TF_LIGHT = (1 << 4),
-
- TF_CONVERTED = (1 << 5), /* tface converted to material */
-
- TF_SHAREDCOL = (1 << 6),
- // TF_TILES = (1 << 7), /* deprecated */
- TF_BILLBOARD = (1 << 8),
- TF_TWOSIDE = (1 << 9),
- TF_INVISIBLE = (1 << 10),
-
- TF_OBCOL = (1 << 11),
- TF_BILLBOARD2 = (1 << 12), /* with Z axis constraint */
- TF_SHADOW = (1 << 13),
- TF_BMFONT = (1 << 14),
-};
-
-/* mtface->transp, values 1-4 are used as flags in the GL, WARNING, TF_SUB cant work with this */
-enum {
- TF_SOLID = 0,
- TF_ADD = (1 << 0),
- TF_ALPHA = (1 << 1),
- TF_CLIP = (1 << 2), /* clipmap alpha/binary alpha all or nothing! */
-
- TF_SUB = 3, /* sub is not available in the user interface anymore */
-};
-
-/* mtface->unwrap */
-enum {
- TF_DEPRECATED1 = (1 << 0),
- TF_DEPRECATED2 = (1 << 1),
- TF_DEPRECATED3 = (1 << 2),
- TF_DEPRECATED4 = (1 << 3),
- TF_PIN1 = (1 << 4),
- TF_PIN2 = (1 << 5),
- TF_PIN3 = (1 << 6),
- TF_PIN4 = (1 << 7),
-};
-
#endif /* __DNA_MESHDATA_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h
index 68d16700a73..f9ba45efef8 100644
--- a/source/blender/makesdna/DNA_meta_types.h
+++ b/source/blender/makesdna/DNA_meta_types.h
@@ -59,7 +59,11 @@ typedef struct MetaElem {
float len; /* old, only used for backwards compat. use dimensions now */
float *mat, *imat; /* matrix and inverted matrix */
-
+
+ /* Draw_Data: stores pointers used for shader attributes */
+ float draw_scale_xform[3][4]; /* Matrix of Scale and Translation */
+ float draw_stiffness_radius; /* stiffness circle radius (only in edit mode) */
+ float pad;
} MetaElem;
typedef struct MetaBall {
@@ -93,6 +97,8 @@ typedef struct MetaBall {
/* used in editmode */
/*ListBase edit_elems;*/
MetaElem *lastelem;
+
+ void *batch_cache;
} MetaBall;
/* **************** METABALL ********************* */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index fc0bf59518c..5dbfbaadf75 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -420,7 +420,7 @@ typedef struct UVProjectModifierData {
/* the objects which do the projecting */
struct Object *projectors[10]; /* MOD_UVPROJECT_MAXPROJECTORS */
struct Image *image; /* the image to project */
- int flags;
+ int pad2;
int num_projectors;
float aspectx, aspecty;
float scalex, scaley;
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index e6bc315b728..0bd36244ffb 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -221,8 +221,11 @@ typedef struct bNode {
* and replacing all uses with per-instance data.
*/
short preview_xsize, preview_ysize; /* reserved size of the preview rect */
- int pad2;
+ short pad2[2];
struct uiBlock *block; /* runtime during drawing */
+
+ float ssr_id; /* XXX: eevee only, id of screen space reflection layer, needs to be a float to feed GPU_uniform. */
+ float sss_id; /* XXX: eevee only, id of screen subsurface scatter layer, needs to be a float to feed GPU_uniform. */
} bNode;
/* node->flag */
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h
index 6e8d4a0480c..63e1da4f90e 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force.h
@@ -112,6 +112,12 @@ typedef struct PartDeflect {
float f_noise; /* noise of force */
int seed; /* noise random seed */
+ /* Display Size */
+ float drawvec1[4]; /* Runtime only : start of the curve or draw scale */
+ float drawvec2[4]; /* Runtime only : end of the curve */
+ float drawvec_falloff_min[3], pad1; /* Runtime only */
+ float drawvec_falloff_max[3], pad2; /* Runtime only */
+
struct Object *f_source; /* force source object */
} PartDeflect;
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 80fa29a9c43..78c623f6408 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -65,6 +65,23 @@ typedef struct bDeformGroup {
/* need this flag for locking weights */
char flag, pad[7];
} bDeformGroup;
+
+/* Face Maps*/
+typedef struct bFaceMap {
+ struct bFaceMap *next, *prev;
+ char name[64]; /* MAX_VGROUP_NAME */
+ char flag;
+ char pad[7];
+} bFaceMap;
+
+/* Object Runtime display data */
+typedef struct ObjectEngineData {
+ struct ObjectEngineData *next, *prev;
+ struct DrawEngineType *engine_type;
+ void *storage;
+ void (*free)(void *storage);
+} ObjectEngineData;
+
#define MAX_VGROUP_NAME 64
/* bDeformGroup->flag */
@@ -142,7 +159,8 @@ typedef struct Object {
ListBase effect DNA_DEPRECATED; // XXX deprecated... keep for readfile
ListBase defbase; /* list of bDeformGroup (vertex groups) names and flag only */
ListBase modifiers; /* list of ModifierData structures */
-
+ ListBase fmaps; /* list of facemaps */
+
int mode; /* Local object mode */
int restore_mode; /* Keep track of what mode to return to after toggling a mode */
@@ -223,7 +241,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;
@@ -248,6 +269,8 @@ typedef struct Object {
short index; /* custom index, for renderpasses */
unsigned short actdef; /* current deformation group, note: index starts at 1 */
+ unsigned short actfmap; /* current face map, note: index starts at 1 */
+ unsigned char pad5[6];
float col[4]; /* object color */
int gameflag;
@@ -256,7 +279,7 @@ typedef struct Object {
struct BulletSoftBody *bsoft; /* settings for game engine bullet soft body */
char restrictflag; /* for restricting view, select, render etc. accessible in outliner */
- char recalc; /* dependency flag */
+ char pad3;
short softflag; /* softbody settings */
float anisotropicFriction[3];
@@ -276,15 +299,15 @@ typedef struct Object {
struct FluidsimSettings *fluidsimSettings; /* if fluidsim enabled, store additional settings */
- /* Runtime valuated curve-specific data, not stored in the file */
- struct CurveCache *curve_cache;
-
struct DerivedMesh *derivedDeform, *derivedFinal;
uint64_t lastDataMask; /* the custom data layer mask that was last used to calculate derivedDeform and derivedFinal */
uint64_t customdata_mask; /* (extra) custom data layer mask to use for creating derivedmesh, set by depsgraph */
unsigned int state; /* bit masks of game controllers that are active */
unsigned int init_state; /* bit masks of initial state as recorded by the users */
+ /* Runtime valuated curve-specific data, not stored in the file */
+ struct CurveCache *curve_cache;
+
ListBase gpulamp; /* runtime, for glsl lamp display only */
ListBase pc_ids;
ListBase *duplilist; /* for temporary dupli list storage, only for use by RNA API */
@@ -299,6 +322,17 @@ typedef struct Object {
LodLevel *currentlod;
struct PreviewImage *preview;
+
+ struct IDProperty *base_collection_properties; /* used by depsgraph, flushed from base */
+
+ ListBase drawdata; /* runtime, ObjectEngineData */
+ int pad1;
+ int select_color;
+
+ /* Mesh structure createrd during object evaluaiton.
+ * It has all modifiers applied.
+ */
+ struct Mesh *mesh_evaluated;
} Object;
/* Warning, this is not used anymore because hooks are now modifiers */
@@ -337,6 +371,7 @@ typedef struct DupliObject {
struct ParticleSystem *particle_system;
unsigned int random_id;
unsigned int pad;
+ struct IDProperty *collection_properties;
} DupliObject;
/* **************** OBJECT ********************* */
@@ -357,6 +392,7 @@ enum {
OB_CAMERA = 11,
OB_SPEAKER = 12,
+ OB_LIGHTPROBE = 13,
/* OB_WAVE = 21, */
OB_LATTICE = 22,
@@ -377,10 +413,10 @@ enum {
/* is this ID type used as object data */
#define OB_DATA_SUPPORT_ID(_id_type) \
- (ELEM(_id_type, ID_ME, ID_CU, ID_MB, ID_LA, ID_SPK, ID_CA, ID_LT, ID_AR))
+ (ELEM(_id_type, ID_ME, ID_CU, ID_MB, ID_LA, ID_SPK, ID_LP, ID_CA, ID_LT, ID_AR))
#define OB_DATA_SUPPORT_ID_CASE \
- ID_ME: case ID_CU: case ID_MB: case ID_LA: case ID_SPK: case ID_CA: case ID_LT: case ID_AR
+ ID_ME: case ID_CU: case ID_MB: case ID_LA: case ID_SPK: case ID_LP: case ID_CA: case ID_LT: case ID_AR
/* partype: first 4 bits: type */
enum {
@@ -512,12 +548,6 @@ enum {
#define BA_TRANSFORM_CHILD (1 << 8) /* child of a transformed object */
#define BA_TRANSFORM_PARENT (1 << 13) /* parent of a transformed object */
-
-/* an initial attempt as making selection more specific! */
-#define BA_DESELECT 0
-#define BA_SELECT 1
-
-
#define OB_FROMDUPLI (1 << 9)
#define OB_DONE (1 << 10) /* unknown state, clear before use */
/* #define OB_RADIO (1 << 11) */ /* deprecated */
@@ -603,6 +633,11 @@ enum {
OB_DEPS_EXTRA_DATA_RECALC = 1 << 1,
};
+/* ob->deg_update_flag */
+enum {
+ DEG_RUNTIME_DATA_UPDATE = 1 << 0,
+};
+
/* ob->scavisflag */
enum {
OB_VIS_SENS = 1 << 0,
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index 984e3334414..81575beaac8 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -38,6 +38,9 @@ struct ID;
typedef struct TreeStoreElem {
short type, nr, flag, used;
+
+ /* XXX We actually also store non-ID data in this pointer for identifying
+ * the TreeStoreElem for a TreeElement when rebuilding the tree. Ugly! */
struct ID *id;
} TreeStoreElem;
@@ -50,11 +53,14 @@ typedef struct TreeStore {
} TreeStore;
/* TreeStoreElem->flag */
-#define TSE_CLOSED 1
-#define TSE_SELECTED 2
-#define TSE_TEXTBUT 4
-#define TSE_CHILDSEARCH 8
-#define TSE_SEARCHMATCH 16
+enum {
+ TSE_CLOSED = (1 << 0),
+ TSE_SELECTED = (1 << 1),
+ TSE_TEXTBUT = (1 << 2),
+ TSE_CHILDSEARCH = (1 << 3),
+ TSE_SEARCHMATCH = (1 << 4),
+ TSE_HIGHLIGHTED = (1 << 5),
+};
/* TreeStoreElem->types */
#define TSE_NLA 1 /* NO ID */
@@ -96,6 +102,8 @@ typedef struct TreeStore {
#define TSE_KEYMAP_ITEM 35 /* NO ID */
#define TSE_ID_BASE 36 /* NO ID */
#define TSE_GP_LAYER 37 /* NO ID */
+#define TSE_LAYER_COLLECTION 38 /* NO ID */
+#define TSE_SCENE_COLLECTION 39 /* NO ID */
/* Check whether given TreeStoreElem should have a real ID in its ->id member. */
@@ -103,7 +111,8 @@ typedef struct TreeStore {
(!ELEM((_tse)->type, TSE_NLA, TSE_NLA_TRACK, TSE_DRIVER_BASE, \
TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, \
TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, \
- TSE_KEYMAP, TSE_KEYMAP_ITEM, TSE_ID_BASE, TSE_GP_LAYER))
+ TSE_KEYMAP, TSE_KEYMAP_ITEM, TSE_ID_BASE, TSE_GP_LAYER, \
+ TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION))
#endif
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index f6bed37dfa2..ea7905eb2ad 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -166,8 +166,9 @@ typedef struct ParticleSettings {
short type, from, distr, texact;
/* physics modes */
short phystype, rotmode, avemode, reactevent;
- int draw, pad1;
- short draw_as, draw_size, childtype, pad2;
+ int draw;
+ float draw_size;
+ short draw_as, pad1, childtype, pad2;
short ren_as, subframes, draw_col;
/* number of path segments, power of 2 except */
short draw_step, ren_step;
@@ -259,8 +260,9 @@ typedef struct ParticleSettings {
/* modified dm support */
short use_modifier_stack;
- short pad5[3];
+ short pad5;
+ int recalc;
} ParticleSettings;
typedef struct ParticleSystem {
@@ -324,6 +326,8 @@ typedef struct ParticleSystem {
float dt_frac; /* current time step, as a fraction of a frame */
float lattice_strength; /* influence of the lattice modifier */
+
+ void *batch_cache;
} ParticleSystem;
typedef enum eParticleDrawFlag {
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 90815b95d24..d25391ca95d 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,19 +67,11 @@ 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;
-
/* ************************************************************* */
/* Output Format Data */
@@ -178,25 +172,24 @@ typedef struct AudioData {
typedef struct SceneRenderLayer {
struct SceneRenderLayer *next, *prev;
- char name[64]; /* MAX_NAME */
+ char name[64] DNA_DEPRECATED; /* MAX_NAME */
- struct Material *mat_override;
- struct Group *light_override;
+ struct Material *mat_override DNA_DEPRECATED; /* Converted to ViewLayer override. */
- unsigned int lay; /* scene->lay itself has priority over this */
- unsigned int lay_zmask; /* has to be after lay, this is for Z-masking */
- unsigned int lay_exclude; /* not used by internal, exclude */
- int layflag;
+ unsigned int lay DNA_DEPRECATED; /* Converted to LayerCollection cycles camera visibility override. */
+ unsigned int lay_zmask DNA_DEPRECATED; /* Converted to LayerCollection cycles holdout override. */
+ unsigned int lay_exclude DNA_DEPRECATED;
+ int layflag DNA_DEPRECATED; /* Converted to ViewLayer layflag and flag. */
- int passflag; /* pass_xor has to be after passflag */
- int pass_xor;
+ int passflag DNA_DEPRECATED; /* pass_xor has to be after passflag */
+ int pass_xor DNA_DEPRECATED; /* Converted to ViewLayer passflag and flag. */
- int samples;
- float pass_alpha_threshold;
+ int samples DNA_DEPRECATED; /* Converted to ViewLayer override. */
+ float pass_alpha_threshold DNA_DEPRECATED; /* Converted to ViewLayer pass_alpha_threshold. */
- IDProperty *prop;
+ IDProperty *prop DNA_DEPRECATED; /* Converted to ViewLayer id_properties. */
- struct FreestyleConfig freestyleConfig;
+ struct FreestyleConfig freestyleConfig DNA_DEPRECATED; /* Converted to ViewLayer freestyleConfig. */
} SceneRenderLayer;
/* srl->layflag */
@@ -542,6 +535,12 @@ typedef enum eBakePassFilter {
#define R_BAKE_PASS_FILTER_ALL (~0)
+/* RenderEngineSettingsClay.options */
+typedef enum ClayFlagSettings {
+ CLAY_USE_AO = (1 << 0),
+ CLAY_USE_HSV = (1 << 1),
+} ClayFlagSettings;
+
/* *************************************************************** */
/* Render Data */
@@ -663,8 +662,8 @@ typedef struct RenderData {
rcti disprect;
/* information on different layers to be rendered */
- ListBase layers;
- short actlay;
+ ListBase layers DNA_DEPRECATED; /* Converted to Scene->view_layers. */
+ short actlay DNA_DEPRECATED; /* Converted to Scene->active_layer. */
/* number of mblur samples */
short mblur_samples;
@@ -746,7 +745,7 @@ typedef struct RenderData {
float unit_line_thickness; /* in pixels */
/* render engine */
- char engine[32];
+ char engine[32] DNA_DEPRECATED; // XXX deprecated since 2.8
/* Cycles baking */
struct BakeData bake;
@@ -770,6 +769,12 @@ typedef struct RenderData {
} RenderData;
/* *************************************************************** */
+/* Settings related to viewport drawing/render, only settings used by WorkSpace and Scene. */
+typedef struct ViewRender {
+ char engine_id[32];
+} ViewRender;
+
+/* *************************************************************** */
/* Render Conversion/Simplfication Settings */
/* control render convert and shading engine */
@@ -880,7 +885,6 @@ typedef struct GameData {
/* Scene LoD */
short lodflag, pad2;
int scehysteresis, pad5;
-
} GameData;
#define STEREO_NOSTEREO 1
@@ -923,7 +927,7 @@ typedef struct GameData {
#define GAME_SHOW_DEBUG_PROPS (1 << 2)
#define GAME_SHOW_FRAMERATE (1 << 3)
#define GAME_SHOW_PHYSICS (1 << 4)
-#define GAME_DISPLAY_LISTS (1 << 5)
+// #define GAME_DISPLAY_LISTS (1 << 5) /* deprecated */
#define GAME_GLSL_NO_LIGHTS (1 << 6)
#define GAME_GLSL_NO_SHADERS (1 << 7)
#define GAME_GLSL_NO_SHADOWS (1 << 8)
@@ -1071,6 +1075,7 @@ typedef struct ParticleEditSettings {
int draw_step, fade_frames;
struct Scene *scene;
+ struct ViewLayer *view_layer;
struct Object *object;
struct Object *shape_object;
} ParticleEditSettings;
@@ -1246,17 +1251,6 @@ typedef enum eGP_Interpolate_Type {
GP_IPO_SINE = 12,
} eGP_Interpolate_Type;
-
-/* *************************************************************** */
-/* Transform Orientations */
-
-typedef struct TransformOrientation {
- struct TransformOrientation *next, *prev;
- char name[64]; /* MAX_NAME */
- float mat[3][3];
- int pad;
-} TransformOrientation;
-
/* *************************************************************** */
/* Unified Paint Settings
*/
@@ -1616,8 +1610,8 @@ typedef struct Scene {
struct Scene *set;
- ListBase base;
- struct Base *basact; /* active base */
+ ListBase base DNA_DEPRECATED;
+ struct Base *basact DNA_DEPRECATED; /* active base */
struct Object *obedit; /* name replaces old G.obedit */
float cursor[3]; /* 3d cursor location */
@@ -1637,17 +1631,17 @@ typedef struct Scene {
struct Editing *ed; /* sequence editor data is allocated here */
struct ToolSettings *toolsettings; /* default allocated now */
- struct SceneStats *stats; /* default allocated now */
+ void *pad2;
struct DisplaySafeAreas safe_areas;
/* migrate or replace? depends on some internal things... */
/* no, is on the right place (ton) */
struct RenderData r;
struct AudioData audio;
-
+
ListBase markers;
- ListBase transform_spaces;
-
+ ListBase transform_spaces DNA_DEPRECATED;
+
void *sound_scene;
void *playback_handle;
void *sound_scrub_handle;
@@ -1656,11 +1650,8 @@ typedef struct Scene {
void *fps_info; /* (runtime) info/cache used for presenting playback framerate info to the user */
/* none of the dependency graph vars is mean to be saved */
- struct Depsgraph *depsgraph;
- void *pad1;
- struct DagForest *theDag;
- short dagflags;
- short pad3;
+ struct GHash *depsgraph_hash;
+ int pad7;
/* User-Defined KeyingSets */
int active_keyingset; /* index of the active KeyingSet. first KeyingSet has index 1, 'none' active is 0, 'add new' is -1 */
@@ -1679,14 +1670,14 @@ typedef struct Scene {
/* Physics simulation settings */
struct PhysicsSettings physics_settings;
- /* Movie Tracking */
- struct MovieClip *clip; /* active movie clip */
-
- void *pad4;
+ void *pad6;
uint64_t customdata_mask; /* XXX. runtime flag for drawing, actually belongs in the window, only used by BKE_object_handle_update() */
uint64_t customdata_mask_modal; /* XXX. same as above but for temp operator use (gl renders) */
+ /* Movie Tracking */
+ struct MovieClip *clip; /* active movie clip */
+
/* Color Management */
ColorManagedViewSettings view_settings;
ColorManagedDisplaySettings display_settings;
@@ -1696,6 +1687,18 @@ typedef struct Scene {
struct RigidBodyWorld *rigidbody_world;
struct PreviewImage *preview;
+
+ ListBase view_layers;
+ struct SceneCollection *collection;
+ int active_view_layer;
+ int pad4;
+
+ IDProperty *collection_properties; /* settings to be overriden by layer collections */
+ IDProperty *layer_properties; /* settings to be override by workspaces */
+
+ int pad5[2];
+
+ ViewRender view_render;
} Scene;
/* **************** RENDERDATA ********************* */
@@ -1887,6 +1890,8 @@ 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_BLENDER_EEVEE;
extern const char *RE_engine_id_CYCLES;
/* **************** SCENE ********************* */
@@ -1905,39 +1910,30 @@ extern const char *RE_engine_id_CYCLES;
#define MINAFRAME -1048574
#define MINAFRAMEF -1048574.0f
-/* depricate this! */
-#define TESTBASE(v3d, base) ( \
- ((base)->flag & SELECT) && \
- ((base)->lay & v3d->lay) && \
- (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0))
-#define TESTBASELIB(v3d, base) ( \
- ((base)->flag & SELECT) && \
- ((base)->lay & v3d->lay) && \
+/* deprecate this! */
+#define TESTBASE(base) ( \
+ (((base)->flag & BASE_SELECTED) != 0) && \
+ (((base)->flag & BASE_VISIBLED) != 0))
+#define TESTBASELIB(base) ( \
+ (((base)->flag & BASE_SELECTED) != 0) && \
((base)->object->id.lib == NULL) && \
- (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0))
-#define TESTBASELIB_BGMODE(v3d, scene, base) ( \
- ((base)->flag & SELECT) && \
- ((base)->lay & (v3d ? v3d->lay : scene->lay)) && \
+ (((base)->flag & BASE_VISIBLED) != 0))
+#define TESTBASELIB_BGMODE(base) ( \
+ (((base)->flag & BASE_SELECTED) != 0) && \
((base)->object->id.lib == NULL) && \
- (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0))
-#define BASE_EDITABLE_BGMODE(v3d, scene, base) ( \
- ((base)->lay & (v3d ? v3d->lay : scene->lay)) && \
+ (((base)->flag & BASE_VISIBLED) != 0))
+#define BASE_EDITABLE_BGMODE(base) ( \
((base)->object->id.lib == NULL) && \
- (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0))
-#define BASE_SELECTABLE(v3d, base) ( \
- (base->lay & v3d->lay) && \
- (base->object->restrictflag & (OB_RESTRICT_SELECT | OB_RESTRICT_VIEW)) == 0)
-#define BASE_VISIBLE(v3d, base) ( \
- (base->lay & v3d->lay) && \
- (base->object->restrictflag & OB_RESTRICT_VIEW) == 0)
-#define BASE_VISIBLE_BGMODE(v3d, scene, base) ( \
- (base->lay & (v3d ? v3d->lay : scene->lay)) && \
- (base->object->restrictflag & OB_RESTRICT_VIEW) == 0)
-
-#define FIRSTBASE scene->base.first
-#define LASTBASE scene->base.last
-#define BASACT (scene->basact)
-#define OBACT (BASACT ? BASACT->object: NULL)
+ (((base)->flag & BASE_VISIBLED) != 0))
+#define BASE_SELECTABLE(base) \
+ (((base)->flag & BASE_SELECTABLED) != 0)
+#define BASE_VISIBLE(base) ( \
+ ((base)->flag & BASE_VISIBLED) != 0)
+
+#define FIRSTBASE(_view_layer) ((_view_layer)->object_bases.first)
+#define LASTBASE(_view_layer) ((_view_layer)->object_bases.last)
+#define BASACT(_view_layer) ((_view_layer)->basact)
+#define OBACT(_view_layer) (BASACT(_view_layer) ? BASACT(_view_layer)->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)
@@ -1953,7 +1949,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_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index fd63d7c471c..e3e5aaf8ca4 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -30,6 +30,7 @@
#ifndef __DNA_SCREEN_TYPES_H__
#define __DNA_SCREEN_TYPES_H__
+#include "DNA_defs.h"
#include "DNA_listBase.h"
#include "DNA_view2d_types.h"
#include "DNA_vec_types.h"
@@ -52,10 +53,9 @@ typedef struct bScreen {
ListBase edgebase;
ListBase areabase;
ListBase regionbase; /* screen level regions (menus), runtime only */
-
- struct Scene *scene;
- struct Scene *newscene; /* temporary when switching */
-
+
+ struct Scene *scene DNA_DEPRECATED;
+
short winid; /* winid from WM, starts with 1 */
short redraws_flag; /* user-setting for which editors get redrawn during anim playback (used to be time->redraws) */
@@ -76,6 +76,8 @@ typedef struct bScreen {
struct wmTimer *animtimer; /* if set, screen has timer handler added in window */
void *context; /* context callback */
+
+ PreviewImage *preview;
} bScreen;
typedef struct ScrVert {
@@ -191,6 +193,13 @@ typedef struct uiList { /* some list UI data need to be saved in file
uiListDyn *dyn_data;
} uiList;
+typedef struct TransformOrientation {
+ struct TransformOrientation *next, *prev;
+ char name[64]; /* MAX_NAME */
+ float mat[3][3];
+ int pad;
+} TransformOrientation;
+
typedef struct uiPreview { /* some preview UI data need to be saved in file */
struct uiPreview *next, *prev;
@@ -265,9 +274,10 @@ typedef struct ARegion {
ListBase ui_previews; /* uiPreview */
ListBase handlers; /* wmEventHandler */
ListBase panels_category; /* Panel categories runtime */
-
+
+ struct wmManipulatorMap *manipulator_map; /* manipulator-map of this region */
struct wmTimer *regiontimer; /* blend in/out */
-
+
char *headerstr; /* use this string to draw info */
void *regiondata; /* XXX 2.50, need spacedata equivalent? */
} ARegion;
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 693917939ef..39ac3f72b94 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -126,7 +126,9 @@ typedef struct SpaceButs {
short preview; /* preview is signal to refresh */
/* texture context selector (material, lamp, particles, world, other) */
short texture_context, texture_context_prev;
- char flag, pad[7];
+ char flag;
+ char collection_context;
+ char pad[6];
void *path; /* runtime */
int pathflag, dataicon; /* runtime */
@@ -180,8 +182,10 @@ typedef enum eSpaceButtons_Context {
BCONTEXT_MODIFIER = 10,
BCONTEXT_CONSTRAINT = 11,
BCONTEXT_BONE_CONSTRAINT = 12,
- BCONTEXT_RENDER_LAYER = 13,
-
+ BCONTEXT_VIEW_LAYER = 13,
+ BCONTEXT_COLLECTION = 14,
+ BCONTEXT_WORKSPACE = 15,
+
/* always as last... */
BCONTEXT_TOT
} eSpaceButtons_Context;
@@ -206,6 +210,12 @@ typedef enum eSpaceButtons_Texture_Context {
SB_TEXC_LINESTYLE = 5,
} eSpaceButtons_Texture_Context;
+/* sbuts->collection_context */
+typedef enum eSpaceButtons_Collection_Context {
+ SB_COLLECTION_CTX_VIEW_LAYER = 0,
+ SB_COLLECTION_CTX_GROUP = 1,
+} eSpaceButtons_Collection_Context;
+
/* sbuts->align */
typedef enum eSpaceButtons_Align {
BUT_FREE = 0,
@@ -273,21 +283,23 @@ 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_ACT_LAYER = 15,
+ SO_COLLECTIONS = 16,
} eSpaceOutliner_Mode;
/* SpaceOops->storeflag */
@@ -715,7 +727,7 @@ typedef enum eFileSel_Params_Flag {
FILE_LINK = (1 << 2),
FILE_HIDE_DOT = (1 << 3),
FILE_AUTOSELECT = (1 << 4),
- FILE_ACTIVELAY = (1 << 5),
+ FILE_ACTIVE_COLLECTION = (1 << 5),
/* FILE_ATCURSOR = (1 << 6), */ /* deprecated */
FILE_DIRSEL_ONLY = (1 << 7),
FILE_FILTER = (1 << 8),
@@ -944,7 +956,7 @@ typedef enum eSpaceImage_Sticky {
/* SpaceImage->flag */
typedef enum eSpaceImage_Flag {
/* SI_BE_SQUARE = (1 << 0), */ /* deprecated */
- SI_EDITTILE = (1 << 1), /* XXX - not used but should be? */
+/* SI_EDITTILE = (1 << 1), */ /* deprecated */
SI_CLIP_UV = (1 << 2),
/* SI_DRAWTOOL = (1 << 3), */ /* deprecated */
SI_NO_DRAWFACES = (1 << 4),
diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h
index 8d1bba6ca4f..c7969cd30e7 100644
--- a/source/blender/makesdna/DNA_text_types.h
+++ b/source/blender/makesdna/DNA_text_types.h
@@ -61,8 +61,8 @@ typedef struct Text {
char *undo_buf;
int undo_pos, undo_len;
- void *compiled;
double mtime;
+ void *compiled;
} Text;
#define TXT_TABSIZE 4
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index cddb1e06b8c..92ec93d8f20 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -140,6 +140,8 @@ typedef struct uiWidgetStateColors {
char inner_key_sel[4];
char inner_driven[4];
char inner_driven_sel[4];
+ char inner_overridden[4];
+ char inner_overridden_sel[4];
float blend, pad;
} uiWidgetStateColors;
@@ -162,7 +164,7 @@ typedef struct ThemeUI {
/* Interface Elements (buttons, menus, icons) */
uiWidgetColors wcol_regular, wcol_tool, wcol_text;
uiWidgetColors wcol_radio, wcol_option, wcol_toggle;
- uiWidgetColors wcol_num, wcol_numslider;
+ uiWidgetColors wcol_num, wcol_numslider, wcol_tab;
uiWidgetColors wcol_menu, wcol_pulldown, wcol_menu_back, wcol_menu_item, wcol_tooltip;
uiWidgetColors wcol_box, wcol_scroll, wcol_progress, wcol_list_item, wcol_pie_menu;
@@ -183,6 +185,14 @@ typedef struct ThemeUI {
/* Axis Colors */
char xaxis[4], yaxis[4], zaxis[4];
+
+ /* Manipulator Colors. */
+ char manipulator_hi[4];
+ char manipulator_primary[4];
+ char manipulator_secondary[4];
+ char manipulator_a[4];
+ char manipulator_b[4];
+ char pad2[4];
} ThemeUI;
/* try to put them all in one, if needed a special struct can be created as well
@@ -497,7 +507,8 @@ typedef struct UserDef {
short gp_settings; /* eGP_UserdefSettings */
short tb_leftmouse, tb_rightmouse;
struct SolidLight light[3];
- short tw_hotspot, tw_flag, tw_handlesize, tw_size;
+ short manipulator_flag, manipulator_size;
+ int pad3;
short textimeout, texcollectrate;
short wmdrawmethod; /* eWM_DrawMethod */
short dragthreshold;
@@ -603,7 +614,7 @@ typedef enum eUserPref_Flag {
USER_FLAG_DEPRECATED_1 = (1 << 1), /* cleared */
USER_FLAG_DEPRECATED_2 = (1 << 2), /* cleared */
USER_FLAG_DEPRECATED_3 = (1 << 3), /* cleared */
- USER_SCENEGLOBAL = (1 << 4),
+/* USER_SCENEGLOBAL = (1 << 4), deprecated */
USER_TRACKBALL = (1 << 5),
USER_FLAG_DEPRECATED_6 = (1 << 6), /* cleared */
USER_FLAG_DEPRECATED_7 = (1 << 7), /* cleared */
@@ -805,6 +816,11 @@ typedef enum eGP_UserdefSettings {
GP_PAINT_DOSIMPLIFY = (1 << 1),
} eGP_UserdefSettings;
+enum {
+ USER_MANIPULATOR_DRAW = (1 << 0),
+ USER_MANIPULATOR_SHADED = (1 << 1),
+};
+
/* Color Picker Types.
* UserDef.color_picker_type */
typedef enum eColorPicker_Types {
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index b9894d46b5b..619f9fd4f6e 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -45,6 +45,7 @@ struct SmoothView3DStore;
struct wmTimer;
struct Material;
struct GPUFX;
+struct GPUViewport;
/* This is needed to not let VC choke on near and far... old
* proprietary MS extensions... */
@@ -65,21 +66,12 @@ struct GPUFX;
/* The near/far thing is a Win EXCEPTION. Thus, leave near/far in the
* code, and patch for windows. */
-
-/* Background Picture in 3D-View */
-typedef struct BGpic {
- struct BGpic *next, *prev;
-
- struct Image *ima;
- struct ImageUser iuser;
- struct MovieClip *clip;
- struct MovieClipUser cuser;
- float xof, yof, size, blend, rotation;
- short view;
- short flag;
- short source;
- char pad[6];
-} BGpic;
+
+typedef struct View3DDebug {
+ float znear, zfar;
+ char background;
+ char pad[7];
+} View3DDebug;
/* ********************************* */
@@ -111,8 +103,12 @@ typedef struct RegionView3D {
struct wmTimer *smooth_timer;
- /* transform widget matrix */
+ /* transform manipulator matrix */
float twmat[4][4];
+ /* min/max dot product on twmat xyz axis. */
+ float tw_axis_min[3], tw_axis_max[3];
+ float tw_axis_matrix[3][3];
+ char _pad[4];
float viewquat[4]; /* view rotation, must be kept normalized */
float dist; /* distance from 'ofs' along -viewinv[2] vector, where result is negative as is 'ofs' */
@@ -130,7 +126,7 @@ typedef struct RegionView3D {
char pad[3];
float ofs_lock[2]; /* normalized offset for locked view: (-1, -1) bottom left, (1, 1) upper right */
- short twdrawflag;
+ short twdrawflag; /* XXX can easily get rid of this (Julian) */
short rflag;
@@ -147,6 +143,7 @@ typedef struct RegionView3D {
float rot_axis[3];
struct GPUFX *compositor;
+ struct GPUViewport *viewport;
} RegionView3D;
/* 3D ViewPort Struct */
@@ -173,9 +170,6 @@ typedef struct View3D {
struct Object *camera, *ob_centre;
rctf render_border;
- struct ListBase bgpicbase;
- struct BGpic *bgpic DNA_DEPRECATED; /* deprecated, use bgpicbase, only kept for do_versions(...) */
-
struct View3D *localvd; /* allocated backup of its self while in localview */
char ob_centre_bone[64]; /* optional string for armature bone to define center, MAXBONENAME */
@@ -202,7 +196,7 @@ typedef struct View3D {
short gridsubdiv; /* Number of subdivisions in the grid between each highlighted grid line */
char gridflag;
- /* transform widget info */
+ /* transform manipulator info */
char twtype, twmode, twflag;
short flag3;
@@ -217,8 +211,9 @@ typedef struct View3D {
char multiview_eye; /* multiview current eye - for internal use */
- /* built-in shader effects (eGPUFXFlags) */
- char pad3[4];
+ /* The active custom transform orientation of this 3D view. */
+ short custom_orientation_index;
+ char pad3[2];
/* note, 'fx_settings.dof' is currently _not_ allocated,
* instead set (temporarily) from camera */
@@ -245,6 +240,7 @@ typedef struct View3D {
short prev_drawtype;
short pad1;
float pad2;
+ View3DDebug debug;
} View3D;
@@ -255,7 +251,7 @@ typedef struct View3D {
/* View3D->flag (short) */
/*#define V3D_DISPIMAGE 1*/ /*UNUSED*/
-#define V3D_DISPBGPICS 2
+/*#define V3D_DISPBGPICS 2*/ /* UNUSED */
#define V3D_HIDE_HELPLINES 4
#define V3D_INVALID_BACKBUF 8
@@ -315,12 +311,19 @@ typedef struct View3D {
#define V3D_SOLID_MATCAP (1 << 12) /* user flag */
#define V3D_SHOW_SOLID_MATCAP (1 << 13) /* runtime flag */
#define V3D_OCCLUDE_WIRE (1 << 14)
-#define V3D_SHADELESS_TEX (1 << 15)
+#define V3D_SHOW_MODE_SHADE_OVERRIDE (1 << 15)
/* View3d->flag3 (short) */
#define V3D_SHOW_WORLD (1 << 0)
+/* View3d->debug.background */
+enum {
+ V3D_DEBUG_BACKGROUND_NONE = (1 << 0),
+ V3D_DEBUG_BACKGROUND_GRADIENT = (1 << 1),
+ V3D_DEBUG_BACKGROUND_WORLD = (1 << 2),
+};
+
/* View3D->around */
enum {
/* center of the bounding box */
@@ -362,38 +365,13 @@ enum {
#define V3D_MANIP_NORMAL 2
#define V3D_MANIP_VIEW 3
#define V3D_MANIP_GIMBAL 4
-#define V3D_MANIP_CUSTOM 5 /* anything of value 5 or higher is custom */
-
-/* View3d->twflag */
- /* USE = user setting, DRAW = based on selection */
-#define V3D_USE_MANIPULATOR 1
-#define V3D_DRAW_MANIPULATOR 2
-/* #define V3D_CALC_MANIPULATOR 4 */ /*UNUSED*/
+#define V3D_MANIP_CUSTOM 5
-/* BGPic->flag */
-/* may want to use 1 for select ? */
+/* View3d->twflag (also) */
enum {
- V3D_BGPIC_EXPANDED = (1 << 1),
- V3D_BGPIC_CAMERACLIP = (1 << 2),
- V3D_BGPIC_DISABLED = (1 << 3),
- V3D_BGPIC_FOREGROUND = (1 << 4),
-
- /* Camera framing options */
- V3D_BGPIC_CAMERA_ASPECT = (1 << 5), /* don't stretch to fit the camera view */
- V3D_BGPIC_CAMERA_CROP = (1 << 6), /* crop out the image */
-
- /* Axis flip options */
- V3D_BGPIC_FLIP_X = (1 << 7),
- V3D_BGPIC_FLIP_Y = (1 << 8),
+ V3D_MANIPULATOR_DRAW = (1 << 0),
};
-#define V3D_BGPIC_EXPANDED (V3D_BGPIC_EXPANDED | V3D_BGPIC_CAMERACLIP)
-
-/* BGPic->source */
-/* may want to use 1 for select ?*/
-#define V3D_BGPIC_IMAGE 0
-#define V3D_BGPIC_MOVIE 1
-
#define RV3D_CAMZOOM_MIN -30
#define RV3D_CAMZOOM_MAX 600
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 16116036e86..fd2a422b4c8 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -41,6 +41,7 @@
struct wmWindowManager;
struct wmWindow;
+struct wmMsgBus;
struct wmEvent;
struct wmGesture;
struct wmOperatorType;
@@ -156,12 +157,15 @@ typedef struct wmWindowManager {
char is_interface_locked; /* indicates whether interface is locked for user interaction */
char par[7];
+
+ struct wmMsgBus *message_bus;
+
} wmWindowManager;
/* wmWindowManager.initialized */
enum {
- WM_INIT_WINDOW = (1<<0),
- WM_INIT_KEYMAP = (1<<1),
+ WM_WINDOW_IS_INITIALIZED = (1<<0),
+ WM_KEYMAP_IS_INITIALIZED = (1<<1),
};
/* IME is win32 only! */
@@ -177,9 +181,12 @@ typedef struct wmWindow {
void *ghostwin; /* don't want to include ghost.h stuff */
- struct bScreen *screen; /* active screen */
- struct bScreen *newscreen; /* temporary when switching */
- char screenname[64]; /* MAX_ID_NAME for matching window with active screen after file read */
+ struct Scene *scene; /* The scene displayed in this window. */
+ struct Scene *new_scene; /* temporary when switching */
+
+ struct WorkSpaceInstanceHook *workspace_hook;
+
+ struct bScreen *screen DNA_DEPRECATED;
short posx, posy, sizex, sizey; /* window coords */
short windowstate; /* borderless, full */
diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h
new file mode 100644
index 00000000000..adc3c1fef2b
--- /dev/null
+++ b/source/blender/makesdna/DNA_workspace_types.h
@@ -0,0 +1,156 @@
+/*
+ * ***** 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 DNA_workspace_types.h
+ * \ingroup DNA
+ *
+ * Use API in BKE_workspace.h!
+ * Struct members marked with DNA_PRIVATE_WORKSPACE will throw a
+ * warning saying it's deprecated when used outside of workspace.c.
+ */
+
+#ifndef __DNA_WORKSPACE_TYPES_H__
+#define __DNA_WORKSPACE_TYPES_H__
+
+#include "DNA_scene_types.h"
+
+/* Same logic as DNA_DEPRECATED_ALLOW, but throws 'deprecated'
+ * warnings if DNA_PRIVATE_WORKSPACE_ALLOW is not defined */
+#ifdef DNA_PRIVATE_WORKSPACE_ALLOW
+ /* allow use of private items */
+# define DNA_PRIVATE_WORKSPACE
+#else
+# ifndef DNA_PRIVATE_WORKSPACE
+# define DNA_PRIVATE_WORKSPACE DNA_PRIVATE_ATTR
+# endif
+#endif
+
+#ifdef DNA_PRIVATE_READ_WRITE_ALLOW
+# define DNA_PRIVATE_WORKSPACE_READ_WRITE
+#else
+# ifndef DNA_PRIVATE_WORKSPACE_READ_WRITE
+# define DNA_PRIVATE_WORKSPACE_READ_WRITE DNA_PRIVATE_WORKSPACE
+# endif
+#endif
+
+/* Currently testing, allow to disable. */
+#define USE_WORKSPACE_TOOL
+
+typedef struct bToolDef {
+ /* either the keymap AND/OR manipulator_group must be defined. */
+ char keymap[64];
+ char manipulator_group[64];
+ int spacetype;
+ /* index when a tool is a member of a group */
+ int index;
+} bToolDef;
+
+/**
+ * \brief Wrapper for bScreen.
+ *
+ * bScreens are IDs and thus stored in a main list-base. We also want to store a list-base of them within the
+ * workspace (so each workspace can have its own set of screen-layouts) which would mess with the next/prev pointers.
+ * So we use this struct to wrap a bScreen pointer with another pair of next/prev pointers.
+ */
+typedef struct WorkSpaceLayout {
+ struct WorkSpaceLayout *next, *prev;
+
+ struct bScreen *screen DNA_PRIVATE_WORKSPACE;
+ /* The name of this layout, we override the RNA name of the screen with this (but not ID name itself) */
+ char name[64] DNA_PRIVATE_WORKSPACE; /* MAX_NAME */
+} WorkSpaceLayout;
+
+typedef struct WorkSpace {
+ ID id;
+
+ ListBase layouts DNA_PRIVATE_WORKSPACE; /* WorkSpaceLayout */
+ /* Store for each hook (so for each window) which layout has
+ * been activated the last time this workspace was visible. */
+ ListBase hook_layout_relations DNA_PRIVATE_WORKSPACE_READ_WRITE; /* WorkSpaceDataRelation */
+ ListBase scene_viewlayer_relations DNA_PRIVATE_WORKSPACE_READ_WRITE; /* WorkSpaceDataRelation */
+
+ /* Custom transform orientations */
+ ListBase transform_orientations DNA_PRIVATE_WORKSPACE;
+
+ int pad;
+ int flags DNA_PRIVATE_WORKSPACE; /* enum eWorkSpaceFlags */
+
+ /* should be: '#ifdef USE_WORKSPACE_TOOL'. */
+ bToolDef tool;
+
+ struct ViewLayer *view_layer DNA_DEPRECATED;
+ struct ViewRender view_render;
+} WorkSpace;
+
+/* internal struct, but exported for read/write */
+#if defined(DNA_PRIVATE_READ_WRITE_ALLOW) || defined(DNA_PRIVATE_WORKSPACE_ALLOW)
+
+/**
+ * Generic (and simple/primitive) struct for storing a history of assignments/relations
+ * of workspace data to non-workspace data in a listbase inside the workspace.
+ *
+ * Using this we can restore the old state of a workspace if the user switches back to it.
+ *
+ * Usage
+ * =====
+ * When activating a workspace, it should activate the screen-layout that was active in that
+ * workspace before *in this window*.
+ * More concretely:
+ * * There are two windows, win1 and win2.
+ * * Both show workspace ws1, but both also had workspace ws2 activated at some point before.
+ * * Last time ws2 was active in win1, screen-layout sl1 was activated.
+ * * Last time ws2 was active in win2, screen-layout sl2 was activated.
+ * * When changing from ws1 to ws2 in win1, screen-layout sl1 should be activated again.
+ * * When changing from ws1 to ws2 in win2, screen-layout sl2 should be activated again.
+ * So that means we have to store the active screen-layout in a per workspace, per window
+ * relation. This struct is used to store an active screen-layout for each window within the
+ * workspace.
+ * To find the screen-layout to activate for this window-workspace combination, simply lookup
+ * the WorkSpaceDataRelation with the workspace-hook of the window set as parent.
+ */
+typedef struct WorkSpaceDataRelation {
+ struct WorkSpaceDataRelation *next, *prev;
+
+ /* the data used to identify the relation (e.g. to find screen-layout (= value) from/for a hook) */
+ void *parent;
+ /* The value for this parent-data/workspace relation */
+ void *value;
+} WorkSpaceDataRelation;
+
+#endif /* DNA_PRIVATE_WORKSPACE_READ_WRITE */
+
+/**
+ * Little wrapper to store data that is going to be per window, but comming from the workspace.
+ * It allows us to keep workspace and window data completely separate.
+ */
+typedef struct WorkSpaceInstanceHook {
+ WorkSpace *active DNA_PRIVATE_WORKSPACE;
+ struct WorkSpaceLayout *act_layout DNA_PRIVATE_WORKSPACE;
+
+ /* Needed because we can't change workspaces/layouts in running handler loop, it would break context. */
+ WorkSpace *temp_workspace_store;
+ struct WorkSpaceLayout *temp_layout_store;
+} WorkSpaceInstanceHook;
+
+typedef enum eWorkSpaceFlags {
+ WORKSPACE_USE_SCENE_SETTINGS = (1 << 0),
+} eWorkSpaceFlags;
+
+#endif /* __DNA_WORKSPACE_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
index 5fd4c9fd407..2ab99617ee8 100644
--- a/source/blender/makesdna/DNA_world_types.h
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -120,7 +120,8 @@ typedef struct World {
struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */
struct MTex *mtex[18]; /* MAX_MTEX */
- short pr_texture, use_nodes, pad[2];
+ short pr_texture, use_nodes, pad;
+ short update_flag; /* XXX temporary flag waiting for depsgraph proper tagging */
/* previews */
struct PreviewImage *preview;
@@ -128,6 +129,7 @@ typedef struct World {
/* nodes */
struct bNodeTree *nodetree;
+ float mistend, pad1; /* runtime : miststa + mistdist, used for drawing camera */
ListBase gpumaterial; /* runtime */
} World;
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 181d01e04fc..ac932a8daaf 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -311,10 +311,52 @@ BLI_INLINE const char *pad_up_4(const char *ptr)
}
/**
+ * Temporary DNA doversion for files that were created with Blender 2.80
+ * between October 2016, and November 2017 (>=280.0 and < 280.2).
+ *
+ * /note This would be way more efficient if we can get the version from SDNA
+ * So we could return true if version == 280 && subversion < 2.
+ *
+ * Returns true if we need to do the DNA renaming.
+ */
+static bool need_doversion_280(SDNA *sdna, int *data, const bool data_alloc)
+{
+ if (data_alloc == false) {
+ return false;
+ }
+
+ bool active_layer = false, render_layers = false;
+
+ const char *cp = (char *)data;
+ for (int nr = 0; nr < sdna->nr_names; nr++) {
+ if (strcmp(cp, "active_layer") == 0) {
+ active_layer = true;
+ if (active_layer && render_layers) {
+ return true;
+ }
+ }
+ else if (strcmp(cp, "render_layers") == 0) {
+ render_layers = true;
+ if (active_layer && render_layers) {
+ return true;
+ }
+ }
+
+ while (*cp) cp++;
+ cp++;
+ }
+
+ /* If someone adds only one of them to the DNA, don't! */
+ BLI_assert(!(active_layer || render_layers));
+ return false;
+}
+
+/**
* In sdna->data the data, now we convert that to something understandable
*/
static bool init_structDNA(
SDNA *sdna, bool do_endian_swap,
+ bool data_alloc,
const char **r_error_message)
{
int *data, *verg, gravity_fix = -1;
@@ -359,6 +401,10 @@ static bool init_structDNA(
*r_error_message = "NAME error in SDNA file";
return false;
}
+
+ /* Temporary DNA doversion for files that were created with Blender 2.80
+ * between 280.0 and 280.2. */
+ const bool doversion_280 = need_doversion_280(sdna, data, data_alloc);
cp = (char *)data;
for (int nr = 0; nr < sdna->nr_names; nr++) {
@@ -373,6 +419,28 @@ static bool init_structDNA(
gravity_fix = nr;
}
}
+ else if (doversion_280) {
+ if (strcmp(cp, "*render_layer") == 0) {
+ /* WorkSpace. */
+ sdna->names[nr] = "*view_layer";
+ }
+ else if (strcmp(cp, "*scene_layer") == 0) {
+ /* ParticleEditSettings. */
+ sdna->names[nr] = "*view_layer";
+ }
+ else if (strcmp(cp, "render_layers") == 0) {
+ /* Scene. */
+ sdna->names[nr] = "view_layers";
+ }
+ else if (strcmp(cp, "active_layer") == 0) {
+ /* Scene. */
+ sdna->names[nr] = "active_view_layer";
+ }
+ else if (strcmp(cp, "*cur_render_layer") == 0) {
+ /* FileGlobal. */
+ sdna->names[nr] = "*cur_view_layer";
+ }
+ }
while (*cp) cp++;
cp++;
@@ -410,6 +478,14 @@ static bool init_structDNA(
/* struct Screen was already used by X, 'bScreen' replaces the old IrisGL 'Screen' struct */
if (strcmp("bScreen", cp) == 0) sdna->types[nr] = cp + 1;
}
+ else if (doversion_280) {
+ if (strcmp(cp, "SceneLayer") == 0) {
+ sdna->types[nr] = "ViewLayer";
+ }
+ else if (strcmp(cp, "SceneLayerEngineData") == 0) {
+ sdna->types[nr] = "ViewLayerEngineData";
+ }
+ }
while (*cp) cp++;
cp++;
@@ -552,7 +628,7 @@ SDNA *DNA_sdna_from_data(
sdna->data_alloc = data_alloc;
- if (init_structDNA(sdna, do_endian_swap, &error_message)) {
+ if (init_structDNA(sdna, do_endian_swap, data_alloc, &error_message)) {
return sdna;
}
else {
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 17e30de4509..593d93b5615 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -130,6 +130,10 @@ static const char *includefiles[] = {
"DNA_freestyle_types.h",
"DNA_linestyle_types.h",
"DNA_cachefile_types.h",
+ "DNA_layer_types.h",
+ "DNA_workspace_types.h",
+ "DNA_lightprobe_types.h",
+
/* see comment above before editing! */
/* empty string to indicate end of includefiles */
@@ -504,6 +508,17 @@ static int preprocess_include(char *maindata, int len)
a -= 13;
cp += 13;
}
+ else if (strncmp("DNA_PRIVATE_WORKSPACE", cp, 21) == 0) {
+ /* Check for DNA_PRIVATE_WORKSPACE_READ_WRITE */
+ if (strncmp("_READ_WRITE", cp + 21, 11) == 0) {
+ a -= 31;
+ cp += 31;
+ }
+ else {
+ a -= 20;
+ cp += 20;
+ }
+ }
else {
md[0] = cp[0];
md++;
@@ -1342,4 +1357,8 @@ 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"
+#include "DNA_workspace_types.h"
+#include "DNA_lightprobe_types.h"
+
/* end of list */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index a975cbbfd7d..a99541385d0 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -39,6 +39,9 @@ extern "C" {
struct bContext;
struct ID;
+struct IDOverrideStatic;
+struct IDOverrideStaticProperty;
+struct IDOverrideStaticPropertyOperation;
struct ListBase;
struct Main;
struct ReportList;
@@ -106,6 +109,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;
@@ -204,6 +208,8 @@ extern StructRNA RNA_CurveMapPoint;
extern StructRNA RNA_CurveMapping;
extern StructRNA RNA_CurveModifier;
extern StructRNA RNA_CurvePoint;
+extern StructRNA RNA_Depsgraph;
+extern StructRNA RNA_DepsgraphIter;
extern StructRNA RNA_DampedTrackConstraint;
extern StructRNA RNA_DataTransferModifier;
extern StructRNA RNA_DecimateModifier;
@@ -233,6 +239,7 @@ extern StructRNA RNA_EnvironmentMapTexture;
extern StructRNA RNA_Event;
extern StructRNA RNA_ExplodeModifier;
extern StructRNA RNA_ExpressionController;
+extern StructRNA RNA_FaceMap;
extern StructRNA RNA_FCurve;
extern StructRNA RNA_FCurveSample;
extern StructRNA RNA_FFmpegSettings;
@@ -320,6 +327,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;
@@ -373,6 +382,8 @@ extern StructRNA RNA_LineStyleThicknessModifier_Tangent;
extern StructRNA RNA_LockedTrackConstraint;
extern StructRNA RNA_Macro;
extern StructRNA RNA_MagicTexture;
+extern StructRNA RNA_Manipulator;
+extern StructRNA RNA_ManipulatorProperties;
extern StructRNA RNA_MarbleTexture;
extern StructRNA RNA_MaskModifier;
extern StructRNA RNA_MaskSequence;
@@ -485,6 +496,7 @@ extern StructRNA RNA_PointLamp;
extern StructRNA RNA_PointerProperty;
extern StructRNA RNA_Pose;
extern StructRNA RNA_PoseBone;
+extern StructRNA RNA_LightProbe;
extern StructRNA RNA_Property;
extern StructRNA RNA_PropertyGroup;
extern StructRNA RNA_PropertyGroupItem;
@@ -500,6 +512,8 @@ 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;
@@ -697,11 +711,14 @@ extern StructRNA RNA_WaveModifier;
extern StructRNA RNA_VertexWeightEditModifier;
extern StructRNA RNA_VertexWeightMixModifier;
extern StructRNA RNA_VertexWeightProximityModifier;
+extern StructRNA RNA_ViewLayer;
+extern StructRNA RNA_ViewRenderSettings;
extern StructRNA RNA_Window;
extern StructRNA RNA_WindowManager;
extern StructRNA RNA_WipeSequence;
extern StructRNA RNA_WireframeModifier;
extern StructRNA RNA_WoodTexture;
+extern StructRNA RNA_WorkSpace;
extern StructRNA RNA_World;
extern StructRNA RNA_WorldAmbientOcclusion;
extern StructRNA RNA_WorldLighting;
@@ -1030,7 +1047,7 @@ char *RNA_path_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int
* call RNA_struct_find_property. The names have to exist as RNA properties
* for the type in the pointer, if they do not exist an error will be printed.
*
- * There is no support for pointers and collections here yet, these can be
+ * There is no support for pointers and collections here yet, these can be
* added when ID properties support them. */
int RNA_boolean_get(PointerRNA *ptr, const char *name);
@@ -1222,17 +1239,51 @@ StructRNA *ID_code_to_RNA_type(short idcode);
void _RNA_warning(const char *format, ...) ATTR_PRINTF_FORMAT(1, 2);
-/* Equals test (skips pointers and collections)
- * is_strict false assumes uninitialized properties are equal */
+/* Equals test. */
-typedef enum eRNAEqualsMode {
- RNA_EQ_STRICT, /* set/unset ignored */
- RNA_EQ_UNSET_MATCH_ANY, /* unset property matches anything */
- RNA_EQ_UNSET_MATCH_NONE /* unset property never matches set property */
-} eRNAEqualsMode;
+/* Note: In practice, EQ_STRICT and EQ_COMPARE have same behavior currently, and will yield same result. */
+typedef enum eRNACompareMode {
+ /* Only care about equality, not full comparison. */
+ RNA_EQ_STRICT, /* set/unset ignored */
+ RNA_EQ_UNSET_MATCH_ANY, /* unset property matches anything */
+ RNA_EQ_UNSET_MATCH_NONE, /* unset property never matches set property */
+ /* Full comparison. */
+ RNA_EQ_COMPARE,
+} eRNACompareMode;
-bool RNA_property_equals(struct PointerRNA *a, struct PointerRNA *b, struct PropertyRNA *prop, eRNAEqualsMode mode);
-bool RNA_struct_equals(struct PointerRNA *a, struct PointerRNA *b, eRNAEqualsMode mode);
+bool RNA_property_equals(struct PointerRNA *a, struct PointerRNA *b, struct PropertyRNA *prop, eRNACompareMode mode);
+bool RNA_struct_equals(struct PointerRNA *a, struct PointerRNA *b, eRNACompareMode mode);
+
+/* Override. */
+
+bool RNA_struct_override_matches(struct PointerRNA *local, struct PointerRNA *reference,
+ struct IDOverrideStatic *override, const bool ignore_non_overridable, const bool ignore_overridden);
+
+bool RNA_struct_override_store(
+ struct PointerRNA *local, struct PointerRNA *reference, PointerRNA *storage, struct IDOverrideStatic *override);
+
+void RNA_property_override_apply(
+ struct PointerRNA *dst, struct PointerRNA *src, struct PointerRNA *storage, struct PropertyRNA *prop,
+ struct IDOverrideStaticProperty *op);
+void RNA_struct_override_apply(
+ struct PointerRNA *dst, struct PointerRNA *src, struct PointerRNA *storage,
+ struct IDOverrideStatic *override);
+
+bool RNA_struct_auto_override(
+ struct PointerRNA *local, struct PointerRNA *reference, struct IDOverrideStatic *override, const char *root_path);
+
+struct IDOverrideStaticProperty *RNA_property_override_property_find(PointerRNA *ptr, PropertyRNA *prop);
+struct IDOverrideStaticProperty *RNA_property_override_property_get(PointerRNA *ptr, PropertyRNA *prop, bool *r_created);
+
+struct IDOverrideStaticPropertyOperation *RNA_property_override_property_operation_find(
+ PointerRNA *ptr, PropertyRNA *prop, const int index, const bool strict, bool *r_strict);
+struct IDOverrideStaticPropertyOperation *RNA_property_override_property_operation_get(
+ PointerRNA *ptr, PropertyRNA *prop, const short operation, const int index,
+ const bool strict, bool *r_strict, bool *r_created);
+
+void RNA_property_override_status(
+ PointerRNA *ptr, PropertyRNA *prop, const int index,
+ bool *r_overridable, bool *r_overridden, bool *r_mandatory, bool *r_locked);
#ifdef __cplusplus
}
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 5f71f2ccdcf..4e32651d356 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -37,6 +37,14 @@
extern "C" {
#endif
+#ifdef UNIT_TEST
+#define RNA_MAX_ARRAY_LENGTH 64
+#else
+#define RNA_MAX_ARRAY_LENGTH 32
+#endif
+
+#define RNA_MAX_ARRAY_DIMENSION 3
+
/* Blender RNA */
BlenderRNA *RNA_create(void);
@@ -169,6 +177,8 @@ void RNA_def_property_update(PropertyRNA *prop, int noteflag, const char *update
void RNA_def_property_editable_func(PropertyRNA *prop, const char *editable);
void RNA_def_property_editable_array_func(PropertyRNA *prop, const char *editable);
+void RNA_def_property_override_funcs(PropertyRNA *prop, const char *diff, const char *store, const char *apply);
+
void RNA_def_property_update_runtime(PropertyRNA *prop, const void *func);
void RNA_def_property_poll_runtime(PropertyRNA *prop, const void *func);
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 0f4e20a02ab..345c47ae1bf 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -62,6 +62,9 @@ extern const EnumPropertyItem rna_enum_constraint_type_items[];
extern const EnumPropertyItem rna_enum_boidrule_type_items[];
extern const EnumPropertyItem rna_enum_sequence_modifier_type_items[];
+extern const EnumPropertyItem rna_enum_collection_type_items[];
+extern const EnumPropertyItem rna_enum_layer_collection_mode_settings_type_items[];
+
extern const EnumPropertyItem rna_enum_modifier_triangulate_quad_method_items[];
extern const EnumPropertyItem rna_enum_modifier_triangulate_ngon_method_items[];
@@ -107,6 +110,7 @@ extern const EnumPropertyItem rna_enum_motionpath_bake_location_items[];
extern const EnumPropertyItem rna_enum_event_value_items[];
extern const EnumPropertyItem rna_enum_event_type_items[];
extern const EnumPropertyItem rna_enum_operator_return_items[];
+extern const EnumPropertyItem rna_enum_operator_property_tags[];
extern const EnumPropertyItem rna_enum_brush_sculpt_tool_items[];
extern const EnumPropertyItem rna_enum_brush_vertex_tool_items[];
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index ce2ca01ccfe..47aebbc13e7 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -108,6 +108,8 @@ typedef enum PropertyUnit {
#define RNA_TRANSLATION_PREC_DEFAULT 5
+#define RNA_STACK_ARRAY 32
+
/* also update enums in bpy_props.c when adding items here
* watch it: these values are written to files as part of
* node socket button subtypes!
@@ -156,7 +158,7 @@ typedef enum PropertySubType {
/* Make sure enums are updated with these */
/* HIGHEST FLAG IN USE: 1 << 31
- * FREE FLAGS: 2, 3, 7, 9, 11, 13, 14, 15, 30 */
+ * FREE FLAGS: 3, 7, 9, 11, 13, 14, 15, 30 */
typedef enum PropertyFlag {
/* editable means the property is editable in the user
* interface, properties are editable by default except
@@ -174,6 +176,9 @@ typedef enum PropertyFlag {
* and collections */
PROP_ANIMATABLE = (1 << 1),
+ /* Means the property can be overriden by a local 'proxy' of some linked datablock. */
+ PROP_OVERRIDABLE_STATIC = (1 << 2),
+
/* This flag means when the property's widget is in 'textedit' mode, it will be updated
* after every typed char, instead of waiting final validation. Used e.g. for text searchbox.
* It will also cause UI_BUT_VALUE_CLEAR to be set for text buttons. We could add an own flag
@@ -232,7 +237,7 @@ typedef enum PropertyFlag {
PROP_IDPROPERTY = (1 << 10), /* This is an IDProperty, not a DNA one. */
PROP_DYNAMIC = (1 << 17), /* for dynamic arrays, and retvals of type string */
PROP_ENUM_NO_CONTEXT = (1 << 24), /* for enum that shouldn't be contextual */
- PROP_ENUM_NO_TRANSLATE = (1 << 29), /* for enums not to be translated (e.g. renderlayers' names in nodes) */
+ PROP_ENUM_NO_TRANSLATE = (1 << 29), /* for enums not to be translated (e.g. viewlayers' names in nodes) */
} PropertyFlag;
/* Function parameters flags.
@@ -282,6 +287,7 @@ typedef struct CollectionPropertyIterator {
union {
ArrayIterator array;
ListBaseIterator listbase;
+ void *custom;
} internal;
int idprop;
int level;
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 743d192f0c5..74c36c456b0 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -56,6 +56,7 @@ set(DEFSRC
rna_key.c
rna_lamp.c
rna_lattice.c
+ rna_layer.c
rna_linestyle.c
rna_main.c
rna_mask.c
@@ -72,6 +73,7 @@ set(DEFSRC
rna_palette.c
rna_particle.c
rna_pose.c
+ rna_lightprobe.c
rna_property.c
rna_render.c
rna_rigidbody.c
@@ -94,6 +96,8 @@ set(DEFSRC
rna_userdef.c
rna_vfont.c
rna_wm.c
+ rna_wm_manipulator.c
+ rna_workspace.c
rna_world.c
)
@@ -124,6 +128,7 @@ set(APISRC
rna_ui_api.c
rna_vfont_api.c
rna_wm_api.c
+ rna_wm_manipulator_api.c
)
string(REGEX REPLACE "rna_([a-zA-Z0-9_-]*).c" "${CMAKE_CURRENT_BINARY_DIR}/rna_\\1_gen.c" GENSRC "${DEFSRC}")
@@ -192,6 +197,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()
@@ -225,7 +234,7 @@ if(WITH_IMAGE_FRAMESERVER)
endif()
if(WITH_AUDASPACE)
- add_definitions(${AUDASPACE_DEFINITIONS})
+ add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
@@ -334,6 +343,7 @@ blender_include_dirs(
../../bmesh
../../blentranslation
../../depsgraph
+ ../../draw
../../gpu
../../imbuf
../../ikplugin
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index e1d4e8fb8ad..19f66109665 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -3025,12 +3025,15 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
prop->arraylength[1],
prop->arraylength[2],
prop->totarraylength);
- fprintf(f, "\t%s%s, %d, %s, %s,\n",
+ fprintf(f, "\t%s%s, %d, %s, %s, %s, %s, %s,\n",
(prop->flag & PROP_CONTEXT_UPDATE) ? "(UpdateFunc)" : "",
rna_function_string(prop->update),
prop->noteflag,
rna_function_string(prop->editable),
- rna_function_string(prop->itemeditable));
+ rna_function_string(prop->itemeditable),
+ rna_function_string(prop->override_diff),
+ rna_function_string(prop->override_store),
+ rna_function_string(prop->override_apply));
if (prop->flag_internal & PROP_INTERN_RAW_ACCESS) rna_set_raw_offset(f, srna, prop);
else fprintf(f, "\t0, -1");
@@ -3337,7 +3340,6 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_context.c", NULL, RNA_def_context},
{"rna_controller.c", "rna_controller_api.c", RNA_def_controller},
{"rna_curve.c", "rna_curve_api.c", RNA_def_curve},
- {"rna_depsgraph.c", NULL, RNA_def_depsgraph},
{"rna_dynamicpaint.c", NULL, RNA_def_dynamic_paint},
{"rna_fcurve.c", "rna_fcurve_api.c", RNA_def_fcurve},
{"rna_fluidsim.c", NULL, RNA_def_fluidsim},
@@ -3347,6 +3349,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_key.c", NULL, RNA_def_key},
{"rna_lamp.c", NULL, RNA_def_lamp},
{"rna_lattice.c", "rna_lattice_api.c", RNA_def_lattice},
+ {"rna_layer.c", NULL, RNA_def_view_layer},
{"rna_linestyle.c", NULL, RNA_def_linestyle},
{"rna_main.c", "rna_main_api.c", RNA_def_main},
{"rna_material.c", "rna_material_api.c", RNA_def_material},
@@ -3357,10 +3360,12 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_nodetree.c", NULL, RNA_def_nodetree},
{"rna_object.c", "rna_object_api.c", RNA_def_object},
{"rna_object_force.c", NULL, RNA_def_object_force},
+ {"rna_depsgraph.c", NULL, RNA_def_depsgraph},
{"rna_packedfile.c", NULL, RNA_def_packedfile},
{"rna_palette.c", NULL, RNA_def_palette},
{"rna_particle.c", NULL, RNA_def_particle},
{"rna_pose.c", "rna_pose_api.c", RNA_def_pose},
+ {"rna_lightprobe.c", NULL, RNA_def_lightprobe},
{"rna_property.c", NULL, RNA_def_gameproperty},
{"rna_render.c", NULL, RNA_def_render},
{"rna_rigidbody.c", NULL, RNA_def_rigidbody},
@@ -3380,6 +3385,8 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_userdef.c", NULL, RNA_def_userdef},
{"rna_vfont.c", "rna_vfont_api.c", RNA_def_vfont},
{"rna_wm.c", "rna_wm_api.c", RNA_def_wm},
+ {"rna_wm_manipulator.c", "rna_wm_manipulator_api.c", RNA_def_wm_manipulator},
+ {"rna_workspace.c", NULL, RNA_def_workspace},
{"rna_world.c", NULL, RNA_def_world},
{"rna_movieclip.c", NULL, RNA_def_movieclip},
{"rna_tracking.c", NULL, RNA_def_tracking},
@@ -3710,6 +3717,9 @@ static const char *cpp_classes = ""
" operator void*() { return ptr.data; }\n"
" operator bool() { return ptr.data != NULL; }\n"
"\n"
+" bool operator==(const Pointer &other) { return ptr.data == other.ptr.data; }\n"
+" bool operator!=(const Pointer &other) { return ptr.data != other.ptr.data; }\n"
+"\n"
" PointerRNA ptr;\n"
"};\n"
"\n"
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 9d42ba55ecc..44df8916796 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -74,6 +74,7 @@ const EnumPropertyItem rna_enum_id_type_items[] = {
{ID_PC, "PAINTCURVE", ICON_CURVE_BEZCURVE, "Paint Curve", ""},
{ID_PAL, "PALETTE", ICON_COLOR, "Palette", ""},
{ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""},
+ {ID_LT, "LIGHT_PROBE", ICON_RADIO, "Light Probe", ""},
{ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""},
{ID_SCR, "SCREEN", ICON_SPLITSCREEN, "Screen", ""},
{ID_SO, "SOUND", ICON_PLAY_AUDIO, "Sound", ""},
@@ -82,6 +83,7 @@ const EnumPropertyItem rna_enum_id_type_items[] = {
{ID_TE, "TEXTURE", ICON_TEXTURE_DATA, "Texture", ""},
{ID_WM, "WINDOWMANAGER", ICON_FULLSCREEN, "Window Manager", ""},
{ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""},
+ {ID_WS, "WORKSPACE", ICON_NONE, "Workspace", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -95,12 +97,15 @@ const EnumPropertyItem rna_enum_id_type_items[] = {
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
+#include "BKE_library_override.h"
#include "BKE_library_remap.h"
#include "BKE_animsys.h"
#include "BKE_material.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h" /* XXX, remove me */
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "WM_api.h"
/* name functions that ignore the first two ID characters */
@@ -166,6 +171,7 @@ short RNA_type_to_ID_code(const StructRNA *type)
if (base_type == &RNA_ParticleSettings) return ID_PA;
if (base_type == &RNA_Palette) return ID_PAL;
if (base_type == &RNA_PaintCurve) return ID_PC;
+ if (base_type == &RNA_LightProbe) return ID_LP;
if (base_type == &RNA_Scene) return ID_SCE;
if (base_type == &RNA_Screen) return ID_SCR;
if (base_type == &RNA_Sound) return ID_SO;
@@ -173,6 +179,7 @@ short RNA_type_to_ID_code(const StructRNA *type)
if (base_type == &RNA_Texture) return ID_TE;
if (base_type == &RNA_Text) return ID_TXT;
if (base_type == &RNA_VectorFont) return ID_VF;
+ if (base_type == &RNA_WorkSpace) return ID_WS;
if (base_type == &RNA_World) return ID_WO;
if (base_type == &RNA_WindowManager) return ID_WM;
@@ -208,6 +215,7 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_PA: return &RNA_ParticleSettings;
case ID_PAL: return &RNA_Palette;
case ID_PC: return &RNA_PaintCurve;
+ case ID_LP: return &RNA_LightProbe;
case ID_SCE: return &RNA_Scene;
case ID_SCR: return &RNA_Screen;
case ID_SO: return &RNA_Sound;
@@ -217,6 +225,7 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_VF: return &RNA_VectorFont;
case ID_WM: return &RNA_WindowManager;
case ID_WO: return &RNA_World;
+ case ID_WS: return &RNA_WorkSpace;
/* deprecated */
case ID_IP: break;
@@ -303,6 +312,15 @@ static ID *rna_ID_copy(ID *id, Main *bmain)
return NULL;
}
+static ID *rna_ID_override_create(ID *id, Main *bmain)
+{
+ if (id->lib == NULL) {
+ return NULL;
+ }
+
+ return BKE_override_static_create_from(bmain, id);
+}
+
static void rna_ID_update_tag(ID *id, ReportList *reports, int flag)
{
/* XXX, new function for this! */
@@ -341,7 +359,7 @@ static void rna_ID_update_tag(ID *id, ReportList *reports, int flag)
}
}
- DAG_id_tag_update(id, flag);
+ DEG_id_tag_update(id, flag);
}
static void rna_ID_user_clear(ID *id)
@@ -377,15 +395,23 @@ static struct ID *rna_ID_make_local(struct ID *self, Main *bmain, int clear_prox
static AnimData * rna_ID_animation_data_create(ID *id, Main *bmain)
{
AnimData *adt = BKE_animdata_add_id(id);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
return adt;
}
static void rna_ID_animation_data_free(ID *id, Main *bmain)
{
BKE_animdata_free(id, true);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
+}
+
+#ifdef WITH_PYTHON
+void **rna_ID_instance(PointerRNA *ptr)
+{
+ ID *id = (ID *)ptr->data;
+ return &id->py_instance;
}
+#endif
static void rna_IDPArray_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
@@ -442,7 +468,7 @@ static Material *rna_IDMaterials_pop_id(ID *id, Main *bmain, ReportList *reports
return NULL;
}
- DAG_id_tag_update(id, OB_RECALC_DATA);
+ DEG_id_tag_update(id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, id);
WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id);
@@ -453,7 +479,7 @@ static void rna_IDMaterials_clear_id(ID *id, int remove_material_slot)
{
BKE_material_clear_id(G.main, id, remove_material_slot);
- DAG_id_tag_update(id, OB_RECALC_DATA);
+ DEG_id_tag_update(id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, id);
WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id);
}
@@ -746,6 +772,14 @@ static PointerRNA rna_IDPreview_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_ImagePreview, prv_img);
}
+static PointerRNA rna_ID_override_reference_get(PointerRNA *ptr)
+{
+ ID *id = (ID *)ptr->data;
+ ID *reference = (id && id->override_static) ? id->override_static->reference : NULL;
+
+ return reference ? rna_pointer_inherit_refine(ptr, ID_code_to_RNA_type(GS(reference->name)), reference) : PointerRNA_NULL;
+}
+
#else
static void rna_def_ID_properties(BlenderRNA *brna)
@@ -1008,6 +1042,12 @@ static void rna_def_ID(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Library", "Library file the data-block is linked from");
+ prop = RNA_def_pointer(srna, "override_static_reference", "ID",
+ "Override Reference", "Reference linked data-block overridden by this one");
+ RNA_def_property_pointer_sdna(prop, NULL, "override_static->reference");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_pointer_funcs(prop, "rna_ID_override_reference_get", NULL, NULL, NULL);
+
prop = RNA_def_pointer(srna, "preview", "ImagePreview", "Preview",
"Preview image and icon of this data-block (None if not supported for this type of data)");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -1020,6 +1060,12 @@ static void rna_def_ID(BlenderRNA *brna)
parm = RNA_def_pointer(func, "id", "ID", "", "New copy of the ID");
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "override_create", "rna_ID_override_create");
+ RNA_def_function_ui_description(func, "Create an overridden local copy of this linked data-block (not supported for all data-blocks)");
+ RNA_def_function_flag(func, FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "id", "ID", "", "New overridden local copy of the ID");
+ RNA_def_function_return(func, parm);
+
func = RNA_def_function(srna, "user_clear", "rna_ID_user_clear");
RNA_def_function_ui_description(func, "Clear the user count of a data-block so its not saved, "
"on reload the data will be removed");
@@ -1064,6 +1110,10 @@ static void rna_def_ID(BlenderRNA *brna)
"Tag the ID to update its display data, "
"e.g. when calling :class:`bpy.types.Scene.update`");
RNA_def_enum_flag(func, "refresh", update_flag_items, 0, "", "Type of updates to perform");
+
+#ifdef WITH_PYTHON
+ RNA_def_struct_register_funcs(srna, NULL, NULL, "rna_ID_instance");
+#endif
}
static void rna_def_library(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 1f974f3a440..345c3d23dbe 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -51,18 +51,21 @@
#include "BKE_idprop.h"
#include "BKE_fcurve.h"
#include "BKE_library.h"
+#include "BKE_library_override.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "WM_api.h"
+#include "WM_message.h"
/* flush updates */
#include "DNA_object_types.h"
-#include "BKE_depsgraph.h"
#include "WM_types.h"
#include "rna_internal.h"
@@ -1821,7 +1824,8 @@ bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
return ((flag & PROP_EDITABLE) &&
(flag & PROP_REGISTER) == 0 &&
- (!id || !ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION)));
+ (!id || ((!ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION)) &&
+ (!id->override_static || (prop->flag & PROP_OVERRIDABLE_STATIC)))));
}
/**
@@ -1847,11 +1851,19 @@ bool RNA_property_editable_info(PointerRNA *ptr, PropertyRNA *prop, const char *
}
/* property from linked data-block */
- if (id && ID_IS_LINKED(id) && (prop->flag & PROP_LIB_EXCEPTION) == 0) {
- if (!(*r_info)[0]) {
- *r_info = "Can't edit this property from a linked data-block.";
+ if (id) {
+ if (ID_IS_LINKED(id) && (prop->flag & PROP_LIB_EXCEPTION) == 0) {
+ if (!(*r_info)[0]) {
+ *r_info = "Can't edit this property from a linked data-block.";
+ }
+ return false;
+ }
+ if (id->override_static != NULL && (prop->flag & PROP_OVERRIDABLE_STATIC) == 0) {
+ if (!(*r_info)[0]) {
+ *r_info = "Can't edit this property from an override data-block.";
+ }
+ return false;
}
- return false;
}
return ((flag & PROP_EDITABLE) && (flag & PROP_REGISTER) == 0);
@@ -1959,7 +1971,7 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR
* parts of the code that need it still, so we have this exception */
if (prop->flag & PROP_CONTEXT_UPDATE) {
if (C) {
- if (prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) {
+ if ((prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) == PROP_CONTEXT_PROPERTY_UPDATE) {
((ContextPropUpdateFunc)prop->update)(C, ptr, prop);
}
else {
@@ -1970,14 +1982,24 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR
else
prop->update(bmain, scene, ptr);
}
+#if 0
if (prop->noteflag)
WM_main_add_notifier(prop->noteflag, ptr->id.data);
+#else
+ /* if C is NULL, we're updating from animation.
+ * avoid slow-down from f-curves by not publishing (for now). */
+ if (C != NULL) {
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ /* we could add NULL check, for now don't */
+ WM_msg_publish_rna(mbus, ptr, prop);
+ }
+#endif
}
if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
/* WARNING! This is so property drivers update the display!
* not especially nice */
- DAG_id_tag_update(ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
WM_main_add_notifier(NC_WINDOW, NULL);
/* Not nice as well, but the only way to make sure material preview
* is updated with custom nodes.
@@ -6963,120 +6985,22 @@ bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
}
}
+static bool rna_property_override_operation_apply(
+ PointerRNA *ptr_local, PointerRNA *ptr_reference, PointerRNA *ptr_storage, PropertyRNA *prop_local,
+ IDOverrideStaticPropertyOperation *opop);
+
bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index)
{
- int len, fromlen;
- PropertyRNA *fromprop = prop;
-
- if (prop->magic != RNA_MAGIC) {
- /* In case of IDProperty, we have to find the *real* idprop of ptr,
- * since prop in this case is just a fake wrapper around actual IDProp data, and not a 'real' PropertyRNA. */
- prop = (PropertyRNA *)rna_idproperty_find(ptr, ((IDProperty *)fromprop)->name);
-
- /* its possible the custom-prop doesn't exist on this data-block */
- if (prop == NULL) {
- return false;
- }
-
- /* Even though currently we now prop will always be the 'fromprop', this might not be the case in the future. */
- if (prop == fromprop) {
- fromprop = (PropertyRNA *)rna_idproperty_find(fromptr, ((IDProperty *)prop)->name);
- }
- }
-
- /* get the length of the array to work with */
- len = RNA_property_array_length(ptr, prop);
- fromlen = RNA_property_array_length(fromptr, fromprop);
-
- if (len != fromlen)
+ if (!RNA_property_editable(ptr, prop)) {
return false;
-
- /* get and set the default values as appropriate for the various types */
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- if (len) {
- if (index == -1) {
- int *tmparray = MEM_callocN(sizeof(int) * len, "copy - boolean");
-
- RNA_property_boolean_get_array(fromptr, fromprop, tmparray);
- RNA_property_boolean_set_array(ptr, prop, tmparray);
-
- MEM_freeN(tmparray);
- }
- else {
- int value = RNA_property_boolean_get_index(fromptr, fromprop, index);
- RNA_property_boolean_set_index(ptr, prop, index, value);
- }
- }
- else {
- int value = RNA_property_boolean_get(fromptr, fromprop);
- RNA_property_boolean_set(ptr, prop, value);
- }
- return true;
- case PROP_INT:
- if (len) {
- if (index == -1) {
- int *tmparray = MEM_callocN(sizeof(int) * len, "copy - int");
-
- RNA_property_int_get_array(fromptr, fromprop, tmparray);
- RNA_property_int_set_array(ptr, prop, tmparray);
-
- MEM_freeN(tmparray);
- }
- else {
- int value = RNA_property_int_get_index(fromptr, fromprop, index);
- RNA_property_int_set_index(ptr, prop, index, value);
- }
- }
- else {
- int value = RNA_property_int_get(fromptr, fromprop);
- RNA_property_int_set(ptr, prop, value);
- }
- return true;
- case PROP_FLOAT:
- if (len) {
- if (index == -1) {
- float *tmparray = MEM_callocN(sizeof(float) * len, "copy - float");
-
- RNA_property_float_get_array(fromptr, fromprop, tmparray);
- RNA_property_float_set_array(ptr, prop, tmparray);
-
- MEM_freeN(tmparray);
- }
- else {
- float value = RNA_property_float_get_index(fromptr, fromprop, index);
- RNA_property_float_set_index(ptr, prop, index, value);
- }
- }
- else {
- float value = RNA_property_float_get(fromptr, fromprop);
- RNA_property_float_set(ptr, prop, value);
- }
- return true;
- case PROP_ENUM:
- {
- int value = RNA_property_enum_get(fromptr, fromprop);
- RNA_property_enum_set(ptr, prop, value);
- return true;
- }
- case PROP_POINTER:
- {
- PointerRNA value = RNA_property_pointer_get(fromptr, fromprop);
- RNA_property_pointer_set(ptr, prop, value);
- return true;
- }
- case PROP_STRING:
- {
- char *value = RNA_property_string_get_alloc(fromptr, fromprop, NULL, 0, NULL);
- RNA_property_string_set(ptr, prop, value);
- MEM_freeN(value);
- return true;
- }
- default:
- return false;
}
- return false;
+ IDOverrideStaticPropertyOperation opop = {
+ .operation = IDOVERRIDESTATIC_OP_REPLACE,
+ .subitem_reference_index = index,
+ .subitem_local_index = index
+ };
+ return rna_property_override_operation_apply(ptr, fromptr, NULL, prop, &opop);
}
/* use RNA_warning macro which includes __func__ suffix */
@@ -7101,176 +7025,513 @@ void _RNA_warning(const char *format, ...)
#endif
}
-bool RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop, eRNAEqualsMode mode)
+static int rna_property_override_diff(
+ PointerRNA *a, PointerRNA *b, PropertyRNA *prop, eRNACompareMode mode,
+ IDOverrideStatic *override, const char *rna_path, bool *r_override_changed, const int flags);
+
+bool RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop, eRNACompareMode mode)
+{
+ BLI_assert(ELEM(mode, RNA_EQ_STRICT, RNA_EQ_UNSET_MATCH_ANY, RNA_EQ_UNSET_MATCH_NONE));
+
+ return (rna_property_override_diff(a, b, prop, mode, NULL, NULL, NULL, 0) != 0);
+}
+
+bool RNA_struct_equals(PointerRNA *a, PointerRNA *b, eRNACompareMode mode)
{
- int len, fromlen;
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop;
+ bool equals = true;
+
+ if (a == NULL && b == NULL)
+ return true;
+ else if (a == NULL || b == NULL)
+ return false;
+ else if (a->type != b->type)
+ return false;
+
+ iterprop = RNA_struct_iterator_property(a->type);
+
+ RNA_property_collection_begin(a, iterprop, &iter);
+ for (; iter.valid; RNA_property_collection_next(&iter)) {
+ PropertyRNA *prop = iter.ptr.data;
+
+ if (!RNA_property_equals(a, b, prop, mode)) {
+ equals = false;
+ break;
+ }
+ }
+ RNA_property_collection_end(&iter);
+
+ return equals;
+}
+
+/* Low-level functions, also used by non-override RNA API like copy or equality check. */
+#include "PIL_time_utildefines.h"
+static int rna_property_override_diff(
+ PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop_a, eRNACompareMode mode,
+ IDOverrideStatic *override, const char *rna_path, bool *r_override_changed, const int flags)
+{
+ int len_a, len_b;
+
+ PropertyRNA *prop_b = prop_a;
+
+ if (prop_a->magic != RNA_MAGIC) {
+ /* In case of IDProperty, we have to find the *real* idprop of ptr,
+ * since prop in this case is just a fake wrapper around actual IDProp data, and not a 'real' PropertyRNA. */
+ /* XXX TODO this is ugly, we already get correct prop in upcalling code, whould just pass them to this func! */
+ prop_a = (PropertyRNA *)rna_idproperty_find(ptr_a, ((IDProperty *)prop_a)->name);
+ prop_b = (PropertyRNA *)rna_idproperty_find(ptr_b, ((IDProperty *)prop_b)->name);
+
+ if (ELEM(NULL, prop_a, prop_b)) {
+ return 1;
+ }
+ }
+
+ BLI_assert(prop_a->override_diff == prop_b->override_diff && prop_a->override_diff != NULL);
if (mode == RNA_EQ_UNSET_MATCH_ANY) {
/* uninitialized properties are assumed to match anything */
- if (!RNA_property_is_set(a, prop) || !RNA_property_is_set(b, prop))
- return true;
+ if (!RNA_property_is_set(ptr_a, prop_a) || !RNA_property_is_set(ptr_b, prop_b))
+ return 0;
}
else if (mode == RNA_EQ_UNSET_MATCH_NONE) {
/* unset properties never match set properties */
- if (RNA_property_is_set(a, prop) != RNA_property_is_set(b, prop))
- return false;
+ if (RNA_property_is_set(ptr_a, prop_a) != RNA_property_is_set(ptr_b, prop_b))
+ return 1;
}
/* get the length of the array to work with */
- len = RNA_property_array_length(a, prop);
- fromlen = RNA_property_array_length(b, prop);
+ len_a = RNA_property_array_length(ptr_a, prop_a);
+ len_b = RNA_property_array_length(ptr_b, prop_b);
- if (len != fromlen)
- return false;
+ if (len_a != len_b) {
+ /* Do not handle override in that case, we do not support insertion/deletion from arrays for now. */
+ return len_a > len_b ? 1 : -1;
+ }
- /* get and set the default values as appropriate for the various types */
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- {
- if (len) {
- int fixed_a[16], fixed_b[16];
- int *array_a, *array_b;
- bool equals;
+ return prop_a->override_diff(
+ ptr_a, ptr_b, prop_a, prop_b, len_a, len_b, mode, override, rna_path, flags, r_override_changed);
+}
- array_a = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_a;
- array_b = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_b;
+/* Modify local data-block to make it ready for override application (only needed for diff operations, where we use
+ * the local data-block's data as second operand). */
+static bool rna_property_override_operation_store(
+ PointerRNA *ptr_local, PointerRNA *ptr_reference, PointerRNA *ptr_storage, PropertyRNA *prop_local,
+ IDOverrideStaticProperty *op)
+{
+ int len_local, len_reference, len_storage = 0;
+ PropertyRNA *prop_reference = prop_local;
+ PropertyRNA *prop_storage = prop_local;
+ bool changed = false;
- RNA_property_boolean_get_array(a, prop, array_a);
- RNA_property_boolean_get_array(b, prop, array_b);
+ if (!ptr_storage) {
+ return changed;
+ }
- equals = memcmp(array_a, array_b, sizeof(int) * len) == 0;
+ if (prop_local->magic != RNA_MAGIC) {
+ /* In case of IDProperty, we have to find the *real* idprop of ptr,
+ * since prop in this case is just a fake wrapper around actual IDProp data, and not a 'real' PropertyRNA. */
+ /* XXX TODO this is ugly, we already get correct prop in upcalling code, should just pass them to this func! */
+ prop_local = (PropertyRNA *)rna_idproperty_find(ptr_local, ((IDProperty *)prop_local)->name);
+ prop_reference = (PropertyRNA *)rna_idproperty_find(ptr_reference, ((IDProperty *)prop_reference)->name);
+ if (ptr_storage) {
+ prop_storage = (PropertyRNA *)rna_idproperty_find(ptr_storage, ((IDProperty *)prop_storage)->name);
+ }
- if (array_a != fixed_a) MEM_freeN(array_a);
- if (array_b != fixed_b) MEM_freeN(array_b);
+ /* its possible the custom-prop doesn't exist on this data-block */
+ if (prop_local == NULL) {
+ return changed;
+ }
+ }
- return equals;
- }
- else {
- int value = RNA_property_boolean_get(a, prop);
- return value == RNA_property_boolean_get(b, prop);
- }
+ /* get the length of the array to work with */
+ len_local = RNA_property_array_length(ptr_local, prop_local);
+ len_reference = RNA_property_array_length(ptr_reference, prop_reference);
+ if (prop_storage) {
+ len_storage = RNA_property_array_length(ptr_storage, prop_storage);
+ }
+
+ if (len_local != len_reference || len_local != len_storage) {
+ /* Do not handle override in that case, we do not support insertion/deletion from arrays for now. */
+ return changed;
+ }
+
+ BLI_assert(prop_local->override_store == prop_reference->override_store &&
+ (!ptr_storage || prop_local->override_store == prop_storage->override_store) &&
+ prop_local->override_store != NULL);
+
+ for (IDOverrideStaticPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
+ /* Only needed for diff operations. */
+ if (!ELEM(opop->operation, IDOVERRIDESTATIC_OP_ADD, IDOVERRIDESTATIC_OP_SUBTRACT, IDOVERRIDESTATIC_OP_MULTIPLY)) {
+ continue;
}
- case PROP_INT:
+ if (prop_local->override_store(
+ ptr_local, ptr_reference, ptr_storage, prop_local, prop_reference, prop_storage,
+ len_local, len_reference, len_storage, opop))
{
- if (len) {
- int fixed_a[16], fixed_b[16];
- int *array_a, *array_b;
- bool equals;
+ changed = true;
+ }
+ }
- array_a = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_a;
- array_b = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_b;
+ return changed;
+}
- RNA_property_int_get_array(a, prop, array_a);
- RNA_property_int_get_array(b, prop, array_b);
+static bool rna_property_override_operation_apply(
+ PointerRNA *ptr_local, PointerRNA *ptr_reference, PointerRNA *ptr_storage, PropertyRNA *prop_local,
+ IDOverrideStaticPropertyOperation *opop)
+{
+ int len_local, len_reference, len_storage = 0;
+ PropertyRNA *prop_reference = prop_local;
+ PropertyRNA *prop_storage = prop_local;
- equals = memcmp(array_a, array_b, sizeof(int) * len) == 0;
+ const short override_op = opop->operation;
- if (array_a != fixed_a) MEM_freeN(array_a);
- if (array_b != fixed_b) MEM_freeN(array_b);
+ if (override_op == IDOVERRIDESTATIC_OP_NOOP) {
+ return true;
+ }
- return equals;
- }
- else {
- int value = RNA_property_int_get(a, prop);
- return value == RNA_property_int_get(b, prop);
- }
+ if (ELEM(override_op, IDOVERRIDESTATIC_OP_ADD, IDOVERRIDESTATIC_OP_SUBTRACT, IDOVERRIDESTATIC_OP_MULTIPLY) && !ptr_storage) {
+ /* We cannot apply 'diff' override operations without some refference storage.
+ * This should typically only happen at read time of .blend file... */
+ return false;
+ }
+
+ if (prop_local->magic != RNA_MAGIC) {
+ /* In case of IDProperty, we have to find the *real* idprop of ptr,
+ * since prop in this case is just a fake wrapper around actual IDProp data, and not a 'real' PropertyRNA. */
+ /* XXX TODO this is ugly, we already get correct prop in upcalling code, whould just pass them to this func! */
+ prop_local = (PropertyRNA *)rna_idproperty_find(ptr_local, ((IDProperty *)prop_local)->name);
+ prop_reference = (PropertyRNA *)rna_idproperty_find(ptr_reference, ((IDProperty *)prop_reference)->name);
+ if (ptr_storage) {
+ prop_storage = (PropertyRNA *)rna_idproperty_find(ptr_storage, ((IDProperty *)prop_storage)->name);
}
- case PROP_FLOAT:
- {
- if (len) {
- float fixed_a[16], fixed_b[16];
- float *array_a, *array_b;
- bool equals;
+ /* its possible the custom-prop doesn't exist on this data-block */
+ if (prop_local == NULL) {
+ return false;
+ }
+ }
- array_a = (len > 16) ? MEM_mallocN(sizeof(float) * len, "RNA equals") : fixed_a;
- array_b = (len > 16) ? MEM_mallocN(sizeof(float) * len, "RNA equals") : fixed_b;
+ if (ELEM(override_op, IDOVERRIDESTATIC_OP_ADD, IDOVERRIDESTATIC_OP_SUBTRACT, IDOVERRIDESTATIC_OP_MULTIPLY) && !prop_storage) {
+ /* We cannot apply 'diff' override operations without some refference storage.
+ * This should typically only happen at read time of .blend file... */
+ return false;
+ }
- RNA_property_float_get_array(a, prop, array_a);
- RNA_property_float_get_array(b, prop, array_b);
+ /* get the length of the array to work with */
+ len_local = RNA_property_array_length(ptr_local, prop_local);
+ len_reference = RNA_property_array_length(ptr_reference, prop_reference);
+ if (ptr_storage) {
+ len_storage = RNA_property_array_length(ptr_storage, prop_storage);
+ }
- equals = memcmp(array_a, array_b, sizeof(float) * len) == 0;
+ if (len_local != len_reference || (ptr_storage && len_local != len_storage)) {
+ /* Do not handle override in that case, we do not support insertion/deletion from arrays for now. */
+ return false;
+ }
- if (array_a != fixed_a) MEM_freeN(array_a);
- if (array_b != fixed_b) MEM_freeN(array_b);
+ BLI_assert(prop_local->override_apply == prop_reference->override_apply &&
+ (!ptr_storage || prop_local->override_apply == prop_storage->override_apply) &&
+ prop_local->override_apply != NULL);
- return equals;
- }
- else {
- float value = RNA_property_float_get(a, prop);
- return value == RNA_property_float_get(b, prop);
+ /* get and set the default values as appropriate for the various types */
+ return prop_local->override_apply(
+ ptr_local, ptr_reference, ptr_storage,
+ prop_local, prop_reference, prop_storage,
+ len_local, len_reference, len_storage,
+ opop);
+}
+
+
+/**
+ * Check whether reference and local overriden data match (are the same),
+ * with respect to given restrictive sets of properties. */
+bool RNA_struct_override_matches(
+ PointerRNA *local, PointerRNA *reference,
+ IDOverrideStatic *override, const bool ignore_non_overridable, const bool ignore_overridden)
+{
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop;
+ bool equals = true;
+
+ BLI_assert(local->type == reference->type);
+
+ iterprop = RNA_struct_iterator_property(local->type);
+
+ RNA_property_collection_begin(local, iterprop, &iter);
+ for (; iter.valid; RNA_property_collection_next(&iter)) {
+ PropertyRNA *prop = iter.ptr.data;
+
+ if (ignore_non_overridable && !(prop->flag & PROP_OVERRIDABLE_STATIC)) {
+ continue;
+ }
+
+ if (ignore_overridden) {
+ /* XXX TODO this will have to be refined to handle collections insertions, and array items */
+ char *rna_path = RNA_path_from_ID_to_property(local, prop);
+ if (BKE_override_static_property_find(override, rna_path) != NULL) {
+ MEM_SAFE_FREE(rna_path);
+ continue;
}
+ MEM_SAFE_FREE(rna_path);
}
- case PROP_ENUM:
- {
- int value = RNA_property_enum_get(a, prop);
- return value == RNA_property_enum_get(b, prop);
+ int flag = 0;
+ if (ignore_non_overridable) {
+ flag |= RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE;
+ }
+ if (ignore_overridden) {
+ flag |= RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN;
+ }
+ if (rna_property_override_diff(local, reference, prop, RNA_EQ_STRICT, override, NULL, NULL, flag) != 0) {
+ equals = false;
+ break;
}
+ }
+ RNA_property_collection_end(&iter);
- case PROP_STRING:
- {
- char fixed_a[128], fixed_b[128];
- int len_a, len_b;
- char *value_a = RNA_property_string_get_alloc(a, prop, fixed_a, sizeof(fixed_a), &len_a);
- char *value_b = RNA_property_string_get_alloc(b, prop, fixed_b, sizeof(fixed_b), &len_b);
- bool equals = STREQ(value_a, value_b);
+ return equals;
+}
- if (value_a != fixed_a) MEM_freeN(value_a);
- if (value_b != fixed_b) MEM_freeN(value_b);
+/** Store needed second operands into \a storage data-block for differential override operations. */
+bool RNA_struct_override_store(PointerRNA *local, PointerRNA *reference, PointerRNA *storage, IDOverrideStatic *override)
+{
+ bool changed = false;
- return equals;
- }
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_START_AVERAGED(RNA_struct_override_store);
+#endif
+ for (IDOverrideStaticProperty *op = override->properties.first; op; op = op->next) {
+ /* Simplified for now! */
+ PointerRNA src_data, dst_data;
+ PropertyRNA *src_prop, *dst_prop;
- case PROP_POINTER:
+ if (RNA_path_resolve_property(reference, op->rna_path, &src_data, &src_prop) &&
+ RNA_path_resolve_property(local, op->rna_path, &dst_data, &dst_prop))
{
- if (!STREQ(RNA_property_identifier(prop), "rna_type")) {
- PointerRNA propptr_a = RNA_property_pointer_get(a, prop);
- PointerRNA propptr_b = RNA_property_pointer_get(b, prop);
- return RNA_struct_equals(&propptr_a, &propptr_b, mode);
+ PointerRNA storage_data;
+ PropertyRNA *storage_prop = NULL;
+
+ /* It is totally OK if this does not success, only a subset of override operations actually need storage. */
+ if (storage && (storage->id.data != NULL)) {
+ RNA_path_resolve_property(storage, op->rna_path, &storage_data, &storage_prop);
+ }
+
+ if (rna_property_override_operation_store(&dst_data, &src_data, &storage_data, src_prop, op)) {
+ changed = true;
}
- break;
}
+ }
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_END_AVERAGED(RNA_struct_override_store);
+#endif
- default:
- break;
+ return changed;
+}
+
+/** Apply given \a op override property operations on \a dst, using \a src as source. */
+void RNA_property_override_apply(
+ PointerRNA *dst, PointerRNA *src, PointerRNA *storage, PropertyRNA *prop, IDOverrideStaticProperty *op)
+{
+ for (IDOverrideStaticPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
+ if (!rna_property_override_operation_apply(dst, src, storage, prop, opop)) {
+ BLI_assert(0);
+ }
}
+}
- return true;
+/** Apply given \a override operations on \a dst, using \a src as source. */
+void RNA_struct_override_apply(PointerRNA *dst, PointerRNA *src, PointerRNA *storage, IDOverrideStatic *override)
+{
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_START_AVERAGED(RNA_struct_override_apply);
+#endif
+ for (IDOverrideStaticProperty *op = override->properties.first; op; op = op->next) {
+ /* Simplified for now! */
+ PointerRNA src_data, dst_data;
+ PropertyRNA *src_prop, *dst_prop;
+
+ if (RNA_path_resolve_property(src, op->rna_path, &src_data, &src_prop) &&
+ RNA_path_resolve_property(dst, op->rna_path, &dst_data, &dst_prop))
+ {
+ PointerRNA storage_data;
+ PropertyRNA *storage_prop = NULL;
+
+ /* It is totally OK if this does not success, only a subset of override operations actually need storage. */
+ if (storage && (storage->id.data != NULL)) {
+ RNA_path_resolve_property(storage, op->rna_path, &storage_data, &storage_prop);
+ }
+
+ /* Note that src and dst props are the same, unless they are IDProperties... */
+ RNA_property_override_apply(&dst_data, &src_data, storage_prop ? &storage_data : NULL, src_prop, op);
+ }
+#ifndef NDEBUG
+ else {
+ printf("Failed to apply static override operation to '%s.%s' (could not resolve some properties)\n",
+ ((ID *)src->id.data)->name, op->rna_path);
+ }
+#endif
+ }
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_END_AVERAGED(RNA_struct_override_apply);
+#endif
}
-bool RNA_struct_equals(PointerRNA *a, PointerRNA *b, eRNAEqualsMode mode)
+/** Automatically define override rules by comparing \a local and \a reference RNA structs. */
+bool RNA_struct_auto_override(PointerRNA *local, PointerRNA *reference, IDOverrideStatic *override, const char *root_path)
{
CollectionPropertyIterator iter;
-// CollectionPropertyRNA *citerprop; /* UNUSED */
PropertyRNA *iterprop;
- bool equals = true;
+ bool changed = false;
- if (a == NULL && b == NULL)
- return true;
- else if (a == NULL || b == NULL)
- return false;
- else if (a->type != b->type)
- return false;
+ BLI_assert(local->type == reference->type);
+ BLI_assert(local->id.data && reference->id.data);
- iterprop = RNA_struct_iterator_property(a->type);
-// citerprop = (CollectionPropertyRNA *)rna_ensure_property(iterprop); /* UNUSED */
+ if ((((ID *)local->id.data)->flag & LIB_OVERRIDE_STATIC_AUTO) == 0) {
+ return changed;
+ }
- RNA_property_collection_begin(a, iterprop, &iter);
- for (; iter.valid; RNA_property_collection_next(&iter)) {
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ static float _sum_time = 0.0f;
+ static float _num_time = 0.0f;
+ double _timeit_time;
+ if (!root_path) {
+ _timeit_time = PIL_check_seconds_timer();
+ }
+#endif
+
+ iterprop = RNA_struct_iterator_property(local->type);
+
+ for (RNA_property_collection_begin(local, iterprop, &iter); iter.valid; RNA_property_collection_next(&iter)) {
PropertyRNA *prop = iter.ptr.data;
- if (!RNA_property_equals(a, b, prop, mode)) {
- equals = false;
- break;
+ if (!(prop->flag & PROP_OVERRIDABLE_STATIC)) {
+ continue;
+ }
+ if (RNA_property_animated(local, prop)) {
+ continue;
}
+
+ /* XXX TODO this will have to be refined to handle collections insertions, and array items */
+ char *rna_path;
+ if (root_path) {
+ /* Inlined building, much much more efficient. */
+ rna_path = BLI_sprintfN("%s.%s", root_path, RNA_property_identifier(prop));
+ }
+ else {
+ rna_path = RNA_path_from_ID_to_property(local, prop);
+ }
+ if (rna_path == NULL) {
+ continue;
+ }
+
+ rna_property_override_diff(local, reference, prop, RNA_EQ_STRICT, override, rna_path, &changed,
+ RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE | RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN);
+
+ MEM_SAFE_FREE(rna_path);
}
RNA_property_collection_end(&iter);
- return equals;
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ if (!root_path) {
+ const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time);
+ _sum_time += _delta_time;
+ _num_time++;
+ printf("ID: %s\n", ((ID *)local->id.data)->name);
+ printf("time end (%s): %.6f\n", __func__, _delta_time);
+ printf("time averaged (%s): %.6f (total: %.6f, in %d runs)\n", __func__, (_sum_time / _num_time), _sum_time, (int)_num_time);
+ }
+#endif
+
+ return changed;
}
+IDOverrideStaticProperty *RNA_property_override_property_find(PointerRNA *ptr, PropertyRNA *prop)
+{
+ ID *id = ptr->id.data;
+
+ if (!id || !id->override_static) {
+ return NULL;
+ }
+
+ char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
+ if (rna_path) {
+ IDOverrideStaticProperty *op = BKE_override_static_property_find(id->override_static, rna_path);
+ MEM_freeN(rna_path);
+ return op;
+ }
+ return NULL;
+}
+
+IDOverrideStaticProperty *RNA_property_override_property_get(PointerRNA *ptr, PropertyRNA *prop, bool *r_created)
+{
+ ID *id = ptr->id.data;
+
+ if (!id || !id->override_static) {
+ return NULL;
+ }
+
+ char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
+ if (rna_path) {
+ IDOverrideStaticProperty *op = BKE_override_static_property_get(id->override_static, rna_path, r_created);
+ MEM_freeN(rna_path);
+ return op;
+ }
+ return NULL;
+}
+
+IDOverrideStaticPropertyOperation *RNA_property_override_property_operation_find(
+ PointerRNA *ptr, PropertyRNA *prop, const int index, const bool strict, bool *r_strict)
+{
+ IDOverrideStaticProperty *op = RNA_property_override_property_find(ptr, prop);
+
+ if (!op) {
+ return NULL;
+ }
+
+ return BKE_override_static_property_operation_find(op, NULL, NULL, index, index, strict, r_strict);
+}
+
+IDOverrideStaticPropertyOperation *RNA_property_override_property_operation_get(
+ PointerRNA *ptr, PropertyRNA *prop, const short operation, const int index,
+ const bool strict, bool *r_strict, bool *r_created)
+{
+ IDOverrideStaticProperty *op = RNA_property_override_property_get(ptr, prop, NULL);
+
+ if (!op) {
+ return NULL;
+ }
+
+ return BKE_override_static_property_operation_get(op, operation, NULL, NULL, index, index, strict, r_strict, r_created);
+}
+
+void RNA_property_override_status(
+ PointerRNA *ptr, PropertyRNA *prop, const int index,
+ bool *r_overridable, bool *r_overridden, bool *r_mandatory, bool *r_locked)
+{
+#define SET_RET(_name, _val) if (_name != NULL) *_name = (_val)
+
+ SET_RET(r_overridable, false);
+ SET_RET(r_overridden, false);
+ SET_RET(r_mandatory, false);
+ SET_RET(r_locked, false);
+
+ if (!ptr || !prop || !ptr->id.data || !((ID *)ptr->id.data)->override_static) {
+ return;
+ }
+
+ SET_RET(r_overridable, (prop->flag & PROP_OVERRIDABLE_STATIC) && (prop->flag & PROP_EDITABLE));
+
+ if (r_overridden || r_mandatory || r_locked) {
+ IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_find(ptr, prop, index, false, NULL);
+ SET_RET(r_overridden, opop != NULL);
+ SET_RET(r_mandatory, (opop->flag & IDOVERRIDESTATIC_FLAG_MANDATORY) != 0);
+ SET_RET(r_locked, (opop->flag & IDOVERRIDESTATIC_FLAG_LOCKED) != 0);
+ }
+}
+
+
bool RNA_path_resolved_create(
PointerRNA *ptr, struct PropertyRNA *prop,
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index c9c8a791545..3d11e7bb723 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -73,10 +73,11 @@ const EnumPropertyItem rna_enum_keying_flag_items[] = {
#include "BLI_math_base.h"
#include "BKE_animsys.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_nla.h"
+#include "DEG_depsgraph.h"
+
#include "DNA_object_types.h"
#include "WM_api.h"
@@ -88,7 +89,7 @@ static void rna_AnimData_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point
/* tag for refresh so that scheduled updates (e.g. action changed) will
* get computed and reflected in the scene [#34869]
*/
- DAG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA);
}
static int rna_AnimData_action_editable(PointerRNA *ptr, const char **UNUSED(r_info))
@@ -114,7 +115,7 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value)
adt = BKE_animdata_from_id(ownerId);
if (adt) {
adt->recalc |= ADT_RECALC_ANIM;
- DAG_id_tag_update(ownerId, OB_RECALC_TIME);
+ DEG_id_tag_update(ownerId, OB_RECALC_TIME);
}
}
@@ -584,6 +585,34 @@ static FCurve *rna_Driver_find(AnimData *adt, ReportList *reports, const char *d
return list_find_fcurve(&adt->drivers, data_path, index);
}
+bool rna_AnimaData_override_apply(
+ PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage,
+ PropertyRNA *prop_dst, PropertyRNA *prop_src, PropertyRNA *UNUSED(prop_storage),
+ const int len_dst, const int len_src, const int len_storage,
+ IDOverrideStaticPropertyOperation *opop)
+{
+ BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage) && len_dst == 0);
+ BLI_assert(opop->operation == IDOVERRIDESTATIC_OP_REPLACE && "Unsupported RNA override operation on animdata pointer");
+ UNUSED_VARS_NDEBUG(ptr_storage, len_dst, len_src, len_storage, opop);
+
+ /* AnimData is a special case, since you cannot edit/replace it, it's either existent or not. */
+ AnimData *adt_dst = RNA_property_pointer_get(ptr_dst, prop_dst).data;
+ AnimData *adt_src = RNA_property_pointer_get(ptr_src, prop_src).data;
+
+ if (adt_dst == NULL && adt_src != NULL) {
+ /* Copy anim data from reference into final local ID. */
+ BKE_animdata_copy_id(NULL, ptr_dst->id.data, ptr_src->id.data, false);
+ return true;
+ }
+ else if (adt_dst != NULL && adt_src == NULL) {
+ /* Override has cleared/removed anim data from its reference. */
+ BKE_animdata_free(ptr_dst->id.data, true);
+ return true;
+ }
+
+ return false;
+}
+
#else
/* helper function for Keying Set -> keying settings */
@@ -998,6 +1027,8 @@ void rna_def_animdata_common(StructRNA *srna)
prop = RNA_def_property(srna, "animation_data", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "adt");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
+ RNA_def_property_override_funcs(prop, NULL, NULL, "rna_AnimaData_override_apply");
RNA_def_property_ui_text(prop, "Animation Data", "Animation data for this data-block");
}
@@ -1021,7 +1052,7 @@ static void rna_def_animdata(BlenderRNA *brna)
/* Active Action */
prop = RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
/* this flag as well as the dynamic test must be defined for this to be editable... */
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_OVERRIDABLE_STATIC);
RNA_def_property_pointer_funcs(prop, NULL, "rna_AnimData_action_set", NULL, "rna_Action_id_poll");
RNA_def_property_editable_func(prop, "rna_AnimData_action_editable");
RNA_def_property_ui_text(prop, "Action", "Active Action for this data-block");
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index a707bef8845..1ec0fd92a67 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -44,18 +44,19 @@
#ifdef RNA_RUNTIME
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
#include "ED_armature.h"
#include "BKE_armature.h"
+#include "DEG_depsgraph.h"
+
static void rna_Armature_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
ID *id = ptr->id.data;
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
/*WM_main_add_notifier(NC_OBJECT|ND_POSE, NULL); */
}
@@ -173,7 +174,7 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
bArmature *arm = (bArmature *)id;
if (arm->flag & ARM_HAS_VIZ_DEPS) {
- DAG_id_tag_update(id, OB_RECALC_DATA);
+ DEG_id_tag_update(id, OB_RECALC_DATA);
}
}
else if (GS(id->name) == ID_OB) {
@@ -181,7 +182,7 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
bArmature *arm = (bArmature *)ob->data;
if (arm->flag & ARM_HAS_VIZ_DEPS) {
- DAG_id_tag_update(id, OB_RECALC_DATA);
+ DEG_id_tag_update(id, OB_RECALC_DATA);
}
}
}
diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c
index fd3694e7c45..98ca58e0edd 100644
--- a/source/blender/makesrna/intern/rna_boid.c
+++ b/source/blender/makesrna/intern/rna_boid.c
@@ -87,9 +87,11 @@ static const EnumPropertyItem boidruleset_type_items[] = {
#include "BLI_math_base.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_particle.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
static void rna_Boids_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
if (ptr->type == &RNA_ParticleSystem) {
@@ -97,10 +99,10 @@ static void rna_Boids_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN
psys->recalc = PSYS_RECALC_RESET;
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
}
else
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
}
@@ -111,12 +113,12 @@ static void rna_Boids_reset_deps(Main *bmain, Scene *UNUSED(scene), PointerRNA *
psys->recalc = PSYS_RECALC_RESET;
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
}
else
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
}
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 6a67e036c5d..5336a63fb76 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -371,17 +371,23 @@ static void rna_Brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
/*WM_main_add_notifier(NC_SPACE|ND_SPACE_VIEW3D, NULL); */
}
-static void rna_Brush_main_tex_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Brush_main_tex_update(bContext *C, PointerRNA *ptr)
{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Brush *br = (Brush *)ptr->data;
- BKE_paint_invalidate_overlay_tex(scene, br->mtex.tex);
+ BKE_paint_invalidate_overlay_tex(scene, view_layer, br->mtex.tex);
rna_Brush_update(bmain, scene, ptr);
}
-static void rna_Brush_secondary_tex_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Brush_secondary_tex_update(bContext *C, PointerRNA *ptr)
{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Brush *br = (Brush *)ptr->data;
- BKE_paint_invalidate_overlay_tex(scene, br->mask_mtex.tex);
+ BKE_paint_invalidate_overlay_tex(scene, view_layer, br->mask_mtex.tex);
rna_Brush_update(bmain, scene, ptr);
}
@@ -437,14 +443,17 @@ static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
-static void rna_TextureSlot_brush_angle_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_TextureSlot_brush_angle_update(bContext *C, PointerRNA *ptr)
{
+ Scene *scene = CTX_data_scene(C);
MTex *mtex = ptr->data;
/* skip invalidation of overlay for stencil mode */
- if (mtex->mapping != MTEX_MAP_MODE_STENCIL)
- BKE_paint_invalidate_overlay_tex(scene, mtex->tex);
+ if (mtex->mapping != MTEX_MAP_MODE_STENCIL) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_paint_invalidate_overlay_tex(scene, view_layer, mtex->tex);
+ }
- rna_TextureSlot_update(bmain, scene, ptr);
+ rna_TextureSlot_update(C, ptr);
}
static void rna_Brush_set_size(PointerRNA *ptr, int value)
@@ -658,39 +667,46 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "rot");
RNA_def_property_range(prop, 0, M_PI * 2);
RNA_def_property_ui_text(prop, "Angle", "Brush texture rotation");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_brush_angle_update");
prop = RNA_def_property(srna, "map_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "brush_map_mode");
RNA_def_property_enum_items(prop, prop_map_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "tex_paint_map_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "brush_map_mode");
RNA_def_property_enum_items(prop, prop_tex_paint_map_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "mask_map_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "brush_map_mode");
RNA_def_property_enum_items(prop, prop_mask_paint_map_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "use_rake", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "brush_angle_mode", MTEX_ANGLE_RAKE);
RNA_def_property_ui_text(prop, "Rake", "");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "use_random", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "brush_angle_mode", MTEX_ANGLE_RANDOM);
RNA_def_property_ui_text(prop, "Random", "");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "random_angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_range(prop, 0, M_PI * 2);
RNA_def_property_ui_text(prop, "Random Angle", "Brush texture random angle");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
TEXTURE_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source");
@@ -1367,7 +1383,7 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "mtex.tex");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Texture", "");
RNA_def_property_update(prop, NC_TEXTURE, "rna_Brush_main_tex_update");
@@ -1379,7 +1395,7 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "mask_texture", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "mask_mtex.tex");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Mask Texture", "");
RNA_def_property_update(prop, NC_TEXTURE, "rna_Brush_secondary_tex_update");
diff --git a/source/blender/makesrna/intern/rna_cachefile.c b/source/blender/makesrna/intern/rna_cachefile.c
index 73928d377f1..c0aa1f2a9f4 100644
--- a/source/blender/makesrna/intern/rna_cachefile.c
+++ b/source/blender/makesrna/intern/rna_cachefile.c
@@ -37,7 +37,6 @@
#include "BLI_string.h"
#include "BKE_cachefile.h"
-#include "BKE_depsgraph.h"
#include "DEG_depsgraph.h"
@@ -52,7 +51,7 @@ static void rna_CacheFile_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
CacheFile *cache_file = (CacheFile *)ptr->data;
- DAG_id_tag_update(&cache_file->id, 0);
+ DEG_id_tag_update(&cache_file->id, 0);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
UNUSED_VARS(bmain, scene);
@@ -63,7 +62,7 @@ static void rna_CacheFile_update_handle(Main *bmain, Scene *scene, PointerRNA *p
CacheFile *cache_file = ptr->data;
if ((cache_file->flag & CACHEFILE_DIRTY) != 0) {
- BKE_cachefile_clean(scene, cache_file);
+ BKE_cachefile_clean(bmain, cache_file);
BLI_freelistN(&cache_file->object_paths);
cache_file->flag &= ~CACHEFILE_DIRTY;
}
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 981ae75e7c5..146a8e2738d 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -30,20 +30,22 @@
#include "BLI_math.h"
+#include "RNA_access.h"
#include "RNA_define.h"
#include "rna_internal.h"
+#include "WM_api.h"
#include "WM_types.h"
#ifdef RNA_RUNTIME
#include "BKE_camera.h"
-#include "BKE_depsgraph.h"
#include "BKE_object.h"
#include "BKE_sequencer.h"
-#include "WM_api.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
static float rna_Camera_angle_get(PointerRNA *ptr)
{
@@ -87,14 +89,43 @@ static void rna_Camera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointer
{
Camera *camera = (Camera *)ptr->id.data;
- DAG_id_tag_update(&camera->id, 0);
+ DEG_id_tag_update(&camera->id, 0);
}
static void rna_Camera_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
Camera *camera = (Camera *)ptr->id.data;
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&camera->id, 0);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&camera->id, 0);
+}
+
+static CameraBGImage *rna_Camera_background_images_new(Camera *cam)
+{
+ CameraBGImage *bgpic = BKE_camera_background_image_new(cam);
+
+ WM_main_add_notifier(NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
+
+ return bgpic;
+}
+
+static void rna_Camera_background_images_remove(Camera *cam, ReportList *reports, PointerRNA *bgpic_ptr)
+{
+ CameraBGImage *bgpic = bgpic_ptr->data;
+ if (BLI_findindex(&cam->bg_images, bgpic) == -1) {
+ BKE_report(reports, RPT_ERROR, "Background image cannot be removed");
+ }
+
+ BKE_camera_background_image_remove(cam, bgpic);
+ RNA_POINTER_INVALIDATE(bgpic_ptr);
+
+ WM_main_add_notifier(NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
+}
+
+static void rna_Camera_background_images_clear(Camera *cam)
+{
+ BKE_camera_background_image_clear(cam);
+
+ WM_main_add_notifier(NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
}
static void rna_Camera_dof_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
@@ -107,6 +138,161 @@ static void rna_Camera_dof_update(Main *UNUSED(bmain), Scene *scene, PointerRNA
#else
+static void rna_def_camera_background_image(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static const EnumPropertyItem bgpic_source_items[] = {
+ {CAM_BGIMG_SOURCE_IMAGE, "IMAGE", 0, "Image", ""},
+ {CAM_BGIMG_SOURCE_MOVIE, "MOVIE_CLIP", 0, "Movie Clip", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static const EnumPropertyItem bgpic_camera_frame_items[] = {
+ {0, "STRETCH", 0, "Stretch", ""},
+ {CAM_BGIMG_FLAG_CAMERA_ASPECT, "FIT", 0, "Fit", ""},
+ {CAM_BGIMG_FLAG_CAMERA_ASPECT | CAM_BGIMG_FLAG_CAMERA_CROP, "CROP", 0, "Crop", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static const EnumPropertyItem bgpic_draw_depth_items[] = {
+ {0, "BACK", 0, "Back", ""},
+ {CAM_BGIMG_FLAG_FOREGROUND, "FRONT", 0, "Front", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "CameraBackgroundImage", NULL);
+ RNA_def_struct_sdna(srna, "CameraBGImage");
+ RNA_def_struct_ui_text(srna, "Background Image", "Image and settings for display in the 3D View background");
+
+ prop = RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "source");
+ RNA_def_property_enum_items(prop, bgpic_source_items);
+ RNA_def_property_ui_text(prop, "Background Source", "Data source used for background");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "ima");
+ RNA_def_property_ui_text(prop, "Image", "Image displayed and edited in this space");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "clip");
+ RNA_def_property_ui_text(prop, "MovieClip", "Movie clip displayed and edited in this space");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "iuser");
+ RNA_def_property_ui_text(prop, "Image User",
+ "Parameters defining which layer, pass and frame of the image is displayed");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "clip_user", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "MovieClipUser");
+ RNA_def_property_pointer_sdna(prop, NULL, "cuser");
+ RNA_def_property_ui_text(prop, "Clip User", "Parameters defining which frame of the movie clip is displayed");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "offset");
+ RNA_def_property_ui_text(prop, "Offset", "");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "scale");
+ RNA_def_property_ui_text(prop, "Scale", "Scale the background image");
+ RNA_def_property_range(prop, 0.0, FLT_MAX);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "rotation");
+ RNA_def_property_ui_text(prop, "Rotation", "Rotation for the background image (ortho view only)");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_FLIP_X);
+ RNA_def_property_ui_text(prop, "Flip Horizontally", "Flip the background image horizontally");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "use_flip_y", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_FLIP_Y);
+ RNA_def_property_ui_text(prop, "Flip Vertically", "Flip the background image vertically");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "alpha");
+ RNA_def_property_ui_text(prop, "Alpha", "Image opacity to blend the image against the background color");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_EXPANDED);
+ RNA_def_property_ui_text(prop, "Show Expanded", "Show the expanded in the user interface");
+ RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1);
+
+ prop = RNA_def_property(srna, "use_camera_clip", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_CAMERACLIP);
+ RNA_def_property_ui_text(prop, "Camera Clip", "Use movie clip from active scene camera");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "show_background_image", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_DISABLED);
+ RNA_def_property_ui_text(prop, "Show Background Image", "Show this image as background");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "show_on_foreground", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_BGIMG_FLAG_FOREGROUND);
+ RNA_def_property_ui_text(prop, "Show On Foreground", "Show this image in front of objects in viewport");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ /* expose 1 flag as a enum of 2 items */
+ prop = RNA_def_property(srna, "draw_depth", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
+ RNA_def_property_enum_items(prop, bgpic_draw_depth_items);
+ RNA_def_property_ui_text(prop, "Depth", "Draw under or over everything");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ /* expose 2 flags as a enum of 3 items */
+ prop = RNA_def_property(srna, "frame_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
+ RNA_def_property_enum_items(prop, bgpic_camera_frame_items);
+ RNA_def_property_ui_text(prop, "Frame Method", "How the image fits in the camera frame");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+}
+
+
+static void rna_def_camera_background_images(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "CameraBackgroundImages");
+ srna = RNA_def_struct(brna, "CameraBackgroundImages", NULL);
+ RNA_def_struct_sdna(srna, "Camera");
+ RNA_def_struct_ui_text(srna, "Background Images", "Collection of background images");
+
+ func = RNA_def_function(srna, "new", "rna_Camera_background_images_new");
+ RNA_def_function_ui_description(func, "Add new background image");
+ parm = RNA_def_pointer(func, "image", "CameraBackgroundImage", "", "Image displayed as viewport background");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Camera_background_images_remove");
+ RNA_def_function_ui_description(func, "Remove background image");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "image", "CameraBackgroundImage", "", "Image displayed as viewport background");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+
+ func = RNA_def_function(srna, "clear", "rna_Camera_background_images_clear");
+ RNA_def_function_ui_description(func, "Remove all background images");
+}
+
static void rna_def_camera_stereo_data(BlenderRNA *brna)
{
StructRNA *srna;
@@ -381,6 +567,12 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Sensor Size", "Show sensor size (film gate) in Camera view");
RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
+ prop = RNA_def_property(srna, "show_background_images", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOW_BG_IMAGE);
+ RNA_def_property_ui_text(prop, "Display Background Images",
+ "Display reference images behind objects in the 3D View");
+ RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
+
prop = RNA_def_property(srna, "lens_unit", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_lens_unit_items);
@@ -399,8 +591,17 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "GPU Depth Of Field", "");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ prop = RNA_def_property(srna, "background_images", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "bg_images", NULL);
+ RNA_def_property_struct_type(prop, "CameraBackgroundImage");
+ RNA_def_property_ui_text(prop, "Background Images", "List of background images");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
rna_def_animdata_common(srna);
+ rna_def_camera_background_image(brna);
+ rna_def_camera_background_images(brna, prop);
+
/* Nested Data */
RNA_define_animate_sdna(true);
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index 0ac5bf899a3..3d1a1458102 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -46,19 +46,20 @@
#ifdef RNA_RUNTIME
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
static void rna_cloth_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Object *ob = (Object *)ptr->id.data;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
}
static void rna_cloth_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
rna_cloth_update(bmain, scene, ptr);
}
@@ -70,7 +71,7 @@ static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene),
cloth_free_modifier(clmd);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
}
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index d51436df563..d9b7a58de04 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -54,13 +54,14 @@
#include "BKE_colorband.h"
#include "BKE_colortools.h"
-#include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BKE_movieclip.h"
#include "BKE_node.h"
#include "BKE_sequencer.h"
#include "BKE_linestyle.h"
+#include "DEG_depsgraph.h"
+
#include "ED_node.h"
#include "IMB_colormanagement.h"
@@ -315,7 +316,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
{
Material *ma = ptr->id.data;
- DAG_id_tag_update(&ma->id, 0);
+ DEG_id_tag_update(&ma->id, 0);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma);
break;
}
@@ -335,7 +336,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
{
Tex *tex = ptr->id.data;
- DAG_id_tag_update(&tex->id, 0);
+ DEG_id_tag_update(&tex->id, 0);
WM_main_add_notifier(NC_TEXTURE, tex);
break;
}
@@ -350,7 +351,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
{
ParticleSettings *part = ptr->id.data;
- DAG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
+ DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, part);
}
default:
@@ -446,7 +447,7 @@ static void rna_ColorManagedDisplaySettings_display_device_update(Main *UNUSED(b
IMB_colormanagement_validate_settings(&scene->display_settings, &scene->view_settings);
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
}
}
@@ -581,7 +582,7 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain)
if (GS(id->name) == ID_IM) {
Image *ima = (Image *) id;
- DAG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
@@ -664,7 +665,7 @@ static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
return;
if (GS(id->name) == ID_SCE) {
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
}
}
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index bef121cd535..8eb6bc1261e 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -154,7 +154,6 @@ static const EnumPropertyItem space_object_items[] = {
#include "BKE_action.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#ifdef WITH_ALEMBIC
# include "ABC_alembic.h"
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index 4bbf31d6500..3df114282fd 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -39,6 +39,8 @@
#ifdef RNA_RUNTIME
+#include "RE_engine.h"
+
static PointerRNA rna_Context_manager_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
@@ -51,6 +53,12 @@ static PointerRNA rna_Context_window_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Window, CTX_wm_window(C));
}
+static PointerRNA rna_Context_workspace_get(PointerRNA *ptr)
+{
+ bContext *C = (bContext *)ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_WorkSpace, CTX_wm_workspace(C));
+}
+
static PointerRNA rna_Context_screen_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
@@ -95,18 +103,72 @@ static PointerRNA rna_Context_region_data_get(PointerRNA *ptr)
return PointerRNA_NULL;
}
+static PointerRNA rna_Context_manipulator_group_get(PointerRNA *ptr)
+{
+ bContext *C = (bContext *)ptr->data;
+ PointerRNA newptr;
+ RNA_pointer_create(NULL, &RNA_ManipulatorGroup, CTX_wm_manipulator_group(C), &newptr);
+ return newptr;
+}
+
static PointerRNA rna_Context_main_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
return rna_pointer_inherit_refine(ptr, &RNA_BlendData, CTX_data_main(C));
}
+static PointerRNA rna_Context_depsgraph_get(PointerRNA *ptr)
+{
+ bContext *C = (bContext *)ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_Depsgraph, CTX_data_depsgraph(C));
+}
+
static PointerRNA rna_Context_scene_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
return rna_pointer_inherit_refine(ptr, &RNA_Scene, CTX_data_scene(C));
}
+static PointerRNA rna_Context_view_layer_get(PointerRNA *ptr)
+{
+ bContext *C = (bContext *)ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, CTX_data_view_layer(C));
+}
+
+static PointerRNA rna_Context_view_render_get(PointerRNA *ptr)
+{
+ bContext *C = (bContext *)ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_ViewRenderSettings, CTX_data_view_render(C));
+}
+
+static void rna_Context_engine_get(PointerRNA *ptr, char *value)
+ {
+ bContext *C = (bContext *)ptr->data;
+ RenderEngineType *engine_type = CTX_data_engine_type(C);
+ strcpy(value, engine_type->idname);
+}
+
+static int rna_Context_engine_length(PointerRNA *ptr)
+{
+ bContext *C = (bContext *)ptr->data;
+ RenderEngineType *engine_type = CTX_data_engine_type(C);
+ return strlen(engine_type->idname);
+}
+
+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;
@@ -167,6 +229,11 @@ void RNA_def_context(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Window");
RNA_def_property_pointer_funcs(prop, "rna_Context_window_get", NULL, NULL, NULL);
+ prop = RNA_def_property(srna, "workspace", PROP_POINTER, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "WorkSpace");
+ RNA_def_property_pointer_funcs(prop, "rna_Context_workspace_get", NULL, NULL, NULL);
+
prop = RNA_def_property(srna, "screen", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "Screen");
@@ -192,17 +259,51 @@ void RNA_def_context(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "RegionView3D");
RNA_def_property_pointer_funcs(prop, "rna_Context_region_data_get", NULL, NULL, NULL);
+ prop = RNA_def_property(srna, "manipulator_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "ManipulatorGroup");
+ RNA_def_property_pointer_funcs(prop, "rna_Context_manipulator_group_get", NULL, NULL, NULL);
+
/* Data */
prop = RNA_def_property(srna, "blend_data", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "BlendData");
RNA_def_property_pointer_funcs(prop, "rna_Context_main_get", NULL, NULL, NULL);
+ prop = RNA_def_property(srna, "depsgraph", PROP_POINTER, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "Depsgraph");
+ RNA_def_property_pointer_funcs(prop, "rna_Context_depsgraph_get", NULL, NULL, NULL);
+
prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
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, "view_layer", PROP_POINTER, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "ViewLayer");
+ RNA_def_property_pointer_funcs(prop, "rna_Context_view_layer_get", NULL, NULL, NULL);
+
+ prop = RNA_def_property(srna, "view_render", PROP_POINTER, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "ViewRenderSettings");
+ RNA_def_property_pointer_funcs(prop, "rna_Context_view_render_get", NULL, NULL, NULL);
+
+ prop = RNA_def_property(srna, "engine", PROP_STRING, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_string_funcs(prop, "rna_Context_engine_get", "rna_Context_engine_length", 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_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 45b312a742d..894af338c12 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -124,9 +124,11 @@ static const EnumPropertyItem curve2d_fill_mode_items[] = {
#include "DNA_object_types.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "WM_api.h"
#include "MEM_guardedalloc.h"
@@ -338,7 +340,7 @@ static void rna_BPoint_array_begin(CollectionPropertyIterator *iter, PointerRNA
static void rna_Curve_update_data_id(Main *UNUSED(bmain), Scene *UNUSED(scene), ID *id)
{
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
}
@@ -349,7 +351,7 @@ static void rna_Curve_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Curve_update_deps(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
rna_Curve_update_data(bmain, scene, ptr);
}
@@ -638,7 +640,7 @@ static void rna_Curve_spline_remove(Curve *cu, ReportList *reports, PointerRNA *
BKE_nurb_free(nu);
RNA_POINTER_INVALIDATE(nu_ptr);
- DAG_id_tag_update(&cu->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&cu->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_GEOM | ND_DATA, NULL);
}
@@ -648,7 +650,7 @@ static void rna_Curve_spline_clear(Curve *cu)
BKE_nurbList_free(nurbs);
- DAG_id_tag_update(&cu->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&cu->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_GEOM | ND_DATA, NULL);
}
diff --git a/source/blender/makesrna/intern/rna_curve_api.c b/source/blender/makesrna/intern/rna_curve_api.c
index be6808567bb..b518b0cb5b0 100644
--- a/source/blender/makesrna/intern/rna_curve_api.c
+++ b/source/blender/makesrna/intern/rna_curve_api.c
@@ -47,8 +47,14 @@ static void rna_Curve_transform(Curve *cu, float *mat, int shape_keys)
{
BKE_curve_transform(cu, (float (*)[4])mat, shape_keys, true);
- DAG_id_tag_update(&cu->id, 0);
+ DEG_id_tag_update(&cu->id, 0);
}
+
+static void rna_Curve_update_gpu_tag(Curve *cu)
+{
+ BKE_curve_batch_cache_dirty(cu, BKE_CURVE_BATCH_DIRTY_ALL);
+}
+
#else
void RNA_api_curve(StructRNA *srna)
@@ -67,6 +73,8 @@ void RNA_api_curve(StructRNA *srna)
"has had invalid indices corrected (to default 0)");
parm = RNA_def_boolean(func, "result", 0, "Result", "");
RNA_def_function_return(func, parm);
+
+ RNA_def_function(srna, "update_gpu_tag", "rna_Curve_update_gpu_tag");
}
#endif
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index c8a6a503fd9..03e58f8f78e 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -1270,6 +1270,14 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier
#endif
}
+ /* Override handling. */
+ if (DefRNA.preprocess) {
+ prop->override_diff = (RNAPropOverrideDiff)"rna_property_override_diff_default";
+ prop->override_store = (RNAPropOverrideStore)"rna_property_override_store_default";
+ prop->override_apply = (RNAPropOverrideApply)"rna_property_override_apply_default";
+ }
+ /* TODO: do we want that for runtime-defined stuff too? I’d say no, but... maybe yes :/ */
+
rna_addtail(&cont->properties, prop);
return prop;
@@ -2222,6 +2230,29 @@ void RNA_def_property_editable_array_func(PropertyRNA *prop, const char *editabl
if (editable) prop->itemeditable = (ItemEditableFunc)editable;
}
+/**
+ * Set custom callbacks for override operations handling.
+ *
+ * \note \a diff callback will also be used by RNA comparison/equality functions.
+ */
+void RNA_def_property_override_funcs(PropertyRNA *prop, const char *diff, const char *store, const char *apply)
+{
+ if (!DefRNA.preprocess) {
+ fprintf(stderr, "%s: only during preprocessing.\n", __func__);
+ return;
+ }
+
+ if (diff) {
+ prop->override_diff = (RNAPropOverrideDiff)diff;
+ }
+ if (store) {
+ prop->override_store = (RNAPropOverrideStore)store;
+ }
+ if (apply) {
+ prop->override_apply = (RNAPropOverrideApply)apply;
+ }
+}
+
void RNA_def_property_update(PropertyRNA *prop, int noteflag, const char *func)
{
if (!DefRNA.preprocess) {
diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c
index adb99acef1f..7d520ec6abd 100644
--- a/source/blender/makesrna/intern/rna_depsgraph.c
+++ b/source/blender/makesrna/intern/rna_depsgraph.c
@@ -36,14 +36,89 @@
#include "DEG_depsgraph.h"
-#include "BKE_depsgraph.h"
+#include "DNA_object_types.h"
#define STATS_MAX_SIZE 16384
#ifdef RNA_RUNTIME
+#include "BLI_iterator.h"
+
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_debug.h"
+#include "DEG_depsgraph_query.h"
+
+#include "MEM_guardedalloc.h"
+
+/* **************** Depsgraph **************** */
+
+static PointerRNA rna_DepsgraphIter_object_get(PointerRNA *ptr)
+{
+ BLI_Iterator *iterator = ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_Object, iterator->current);
+}
+
+static PointerRNA rna_DepsgraphIter_instance_object_get(PointerRNA *ptr)
+{
+ BLI_Iterator *iterator = ptr->data;
+ DEGOIterObjectData *deg_iter = (DEGOIterObjectData *)iterator->data;
+ Object *instance_object = NULL;
+ if (deg_iter->dupli_object_current != NULL) {
+ instance_object = deg_iter->dupli_object_current->ob;
+ }
+ return rna_pointer_inherit_refine(ptr, &RNA_Object, instance_object);
+}
+
+static PointerRNA rna_DepsgraphIter_parent_get(PointerRNA *ptr)
+{
+ BLI_Iterator *iterator = ptr->data;
+ DEGOIterObjectData *deg_iter = (DEGOIterObjectData *)iterator->data;
+ Object *dupli_parent = NULL;
+ if (deg_iter->dupli_object_current != NULL) {
+ dupli_parent = deg_iter->dupli_parent;
+ }
+ return rna_pointer_inherit_refine(ptr, &RNA_Object, dupli_parent);
+}
+
+static void rna_DepsgraphIter_persistent_id_get(PointerRNA *ptr, int *persistent_id)
+{
+ BLI_Iterator *iterator = ptr->data;
+ DEGOIterObjectData *deg_iter = (DEGOIterObjectData *)iterator->data;
+ memcpy(persistent_id, deg_iter->dupli_object_current->persistent_id,
+ sizeof(deg_iter->dupli_object_current->persistent_id));
+}
+
+static void rna_DepsgraphIter_orco_get(PointerRNA *ptr, float *orco)
+{
+ BLI_Iterator *iterator = ptr->data;
+ DEGOIterObjectData *deg_iter = (DEGOIterObjectData *)iterator->data;
+ memcpy(orco, deg_iter->dupli_object_current->orco,
+ sizeof(deg_iter->dupli_object_current->orco));
+}
+
+static unsigned int rna_DepsgraphIter_random_id_get(PointerRNA *ptr)
+{
+ BLI_Iterator *iterator = ptr->data;
+ DEGOIterObjectData *deg_iter = (DEGOIterObjectData *)iterator->data;
+ return deg_iter->dupli_object_current->random_id;
+}
+
+static void rna_DepsgraphIter_uv_get(PointerRNA *ptr, float *uv)
+{
+ BLI_Iterator *iterator = ptr->data;
+ DEGOIterObjectData *deg_iter = (DEGOIterObjectData *)iterator->data;
+ memcpy(uv, deg_iter->dupli_object_current->uv,
+ sizeof(deg_iter->dupli_object_current->uv));
+}
+
+static int rna_DepsgraphIter_is_instance_get(PointerRNA *ptr)
+{
+ BLI_Iterator *iterator = ptr->data;
+ DEGOIterObjectData *deg_iter = (DEGOIterObjectData *)iterator->data;
+ return (deg_iter->dupli_object_current != NULL);
+}
+
+/* **************** Depsgraph **************** */
static void rna_Depsgraph_debug_graphviz(Depsgraph *graph, const char *filename)
{
@@ -66,16 +141,153 @@ static void rna_Depsgraph_debug_stats(Depsgraph *graph, char *result)
DEG_stats_simple(graph, &outer, &ops, &rels);
BLI_snprintf(result, STATS_MAX_SIZE,
"Approx %lu Operations, %lu Relations, %lu Outer Nodes",
- ops, rels, outer);
+ ops, rels, outer);
+}
+
+/* Iteration over objects, simple version */
+
+static void rna_Depsgraph_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ iter->internal.custom = MEM_callocN(sizeof(BLI_Iterator), __func__);
+ DEGOIterObjectData *data = MEM_callocN(sizeof(DEGOIterObjectData), __func__);
+
+ data->graph = (Depsgraph *)ptr->data;
+ data->flag = DEG_ITER_OBJECT_FLAG_SET;
+
+ ((BLI_Iterator *)iter->internal.custom)->valid = true;
+ DEG_iterator_objects_begin(iter->internal.custom, data);
+ iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
+}
+
+static void rna_Depsgraph_objects_next(CollectionPropertyIterator *iter)
+{
+ DEG_iterator_objects_next(iter->internal.custom);
+ iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
+}
+
+static void rna_Depsgraph_objects_end(CollectionPropertyIterator *iter)
+{
+ DEG_iterator_objects_end(iter->internal.custom);
+ MEM_freeN(((BLI_Iterator *)iter->internal.custom)->data);
+ MEM_freeN(iter->internal.custom);
+}
+
+static PointerRNA rna_Depsgraph_objects_get(CollectionPropertyIterator *iter)
+{
+ Object *ob = ((BLI_Iterator *)iter->internal.custom)->current;
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ob);
+}
+
+/* Iteration over objects, extended version
+ *
+ * Contains extra information about duplicator and persistent ID.
+ */
+
+static void rna_Depsgraph_duplis_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ iter->internal.custom = MEM_callocN(sizeof(BLI_Iterator), __func__);
+ DEGOIterObjectData *data = MEM_callocN(sizeof(DEGOIterObjectData), __func__);
+
+ data->graph = (Depsgraph *)ptr->data;
+ data->flag = DEG_ITER_OBJECT_FLAG_ALL;
+
+ ((BLI_Iterator *)iter->internal.custom)->valid = true;
+ DEG_iterator_objects_begin(iter->internal.custom, data);
+ iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
+}
+
+static void rna_Depsgraph_duplis_next(CollectionPropertyIterator *iter)
+{
+ DEG_iterator_objects_next(iter->internal.custom);
+ iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
+}
+
+static void rna_Depsgraph_duplis_end(CollectionPropertyIterator *iter)
+{
+ DEG_iterator_objects_end(iter->internal.custom);
+ MEM_freeN(((BLI_Iterator *)iter->internal.custom)->data);
+ MEM_freeN(iter->internal.custom);
+}
+
+static PointerRNA rna_Depsgraph_duplis_get(CollectionPropertyIterator *iter)
+{
+ BLI_Iterator *iterator = (BLI_Iterator *)iter->internal.custom;
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_DepsgraphIter, iterator);
+}
+
+static ID *rna_Depsgraph_evaluated_id_get(Depsgraph *depsgraph, ID *id_orig)
+{
+ return DEG_get_evaluated_id(depsgraph, id_orig);
}
#else
+static void rna_def_depsgraph_iter(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "DepsgraphIter", NULL);
+ RNA_def_struct_ui_text(srna, "Dependency Graph Iterator",
+ "Extended information about dependency graph object iterator");
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_ui_text(prop, "Object", "Object the iterator points to");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_def_property_pointer_funcs(prop, "rna_DepsgraphIter_object_get", NULL, NULL, NULL);
+
+ prop = RNA_def_property(srna, "instance_object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_ui_text(prop, "Instance Object", "Object which is being instanced by this iterator");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_def_property_pointer_funcs(prop, "rna_DepsgraphIter_instance_object_get", NULL, NULL, NULL);
+
+ prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_ui_text(prop, "Parent", "Parent of the duplication list");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_def_property_pointer_funcs(prop, "rna_DepsgraphIter_parent_get", NULL, NULL, NULL);
+
+ prop = RNA_def_property(srna, "persistent_id", PROP_INT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Persistent ID",
+ "Persistent identifier for inter-frame matching of objects with motion blur");
+ RNA_def_property_array(prop, 2 * MAX_DUPLI_RECUR);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_def_property_int_funcs(prop, "rna_DepsgraphIter_persistent_id_get", NULL, NULL);
+
+ prop = RNA_def_property(srna, "orco", PROP_FLOAT, PROP_TRANSLATION);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ /* Seems system is not smart enough to figure that getter function should return
+ * array for PROP_TRANSLATION.
+ */
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Generated Coordinates", "Generated coordinates in parent object space");
+ RNA_def_property_float_funcs(prop, "rna_DepsgraphIter_orco_get", NULL, NULL);
+
+ prop = RNA_def_property(srna, "random_id", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Dupli random id", "Random id for this dupli object");
+ RNA_def_property_int_funcs(prop, "rna_DepsgraphIter_random_id_get", NULL, NULL);
+
+ prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "UV Coordinates", "UV coordinates in parent object space");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_def_property_float_funcs(prop, "rna_DepsgraphIter_uv_get", NULL, NULL);
+
+ prop = RNA_def_property(srna, "is_instance", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Instance", "Denotes whether the object is ocming from dupli-list");
+ RNA_def_property_boolean_funcs(prop, "rna_DepsgraphIter_is_instance_get", NULL);
+}
+
static void rna_def_depsgraph(BlenderRNA *brna)
{
StructRNA *srna;
FunctionRNA *func;
PropertyRNA *parm;
+ PropertyRNA *prop;
srna = RNA_def_struct(brna, "Depsgraph", NULL);
RNA_def_struct_ui_text(srna, "Dependency Graph", "");
@@ -93,10 +305,36 @@ static void rna_def_depsgraph(BlenderRNA *brna)
parm = RNA_def_string(func, "result", NULL, STATS_MAX_SIZE, "result", "");
RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0); /* needed for string return value */
RNA_def_function_output(func, parm);
+
+ prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_collection_funcs(prop,
+ "rna_Depsgraph_objects_begin",
+ "rna_Depsgraph_objects_next",
+ "rna_Depsgraph_objects_end",
+ "rna_Depsgraph_objects_get",
+ NULL, NULL, NULL, NULL);
+
+ func = RNA_def_function(srna, "evaluated_id_get", "rna_Depsgraph_evaluated_id_get");
+ parm = RNA_def_pointer(func, "id", "ID", "", "Original ID to get evaluated complementary part for");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "evaluated_id", "ID", "", "Evaluated ID for the given original one");
+ RNA_def_function_return(func, parm);
+
+ /* TODO(sergey): Find a better name. */
+ prop = RNA_def_property(srna, "duplis", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "DepsgraphIter");
+ RNA_def_property_collection_funcs(prop,
+ "rna_Depsgraph_duplis_begin",
+ "rna_Depsgraph_duplis_next",
+ "rna_Depsgraph_duplis_end",
+ "rna_Depsgraph_duplis_get",
+ NULL, NULL, NULL, NULL);
}
void RNA_def_depsgraph(BlenderRNA *brna)
{
+ rna_def_depsgraph_iter(brna);
rna_def_depsgraph(brna);
}
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index fb8389fc2e9..596aff6de8f 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -55,9 +55,10 @@ const EnumPropertyItem rna_enum_prop_dynamicpaint_type_items[] = {
#ifdef RNA_RUNTIME
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_particle.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
static char *rna_DynamicPaintCanvasSettings_path(PointerRNA *ptr)
{
@@ -98,7 +99,7 @@ static char *rna_DynamicPaintSurface_path(PointerRNA *ptr)
static void rna_DynamicPaint_redoModifier(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
}
static void rna_DynamicPaintSurfaces_updateFrames(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -160,7 +161,7 @@ static void rna_DynamicPaintSurfaces_changeFormat(Main *bmain, Scene *scene, Poi
static void rna_DynamicPaint_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_DynamicPaintSurface_reset(bmain, scene, ptr);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
static PointerRNA rna_PaintSurface_active_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index c8ee6e15689..969424cd989 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -127,9 +127,11 @@ static StructRNA *rna_FModifierType_refine(struct PointerRNA *ptr)
/* ****************************** */
#include "BKE_fcurve.h"
-#include "BKE_depsgraph.h"
#include "BKE_animsys.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
static void rna_ChannelDriver_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
{
ID *id = ptr->id.data;
@@ -138,8 +140,8 @@ static void rna_ChannelDriver_update_data(Main *bmain, Scene *scene, PointerRNA
driver->flag &= ~DRIVER_FLAG_INVALID;
/* TODO: this really needs an update guard... */
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA);
WM_main_add_notifier(NC_SCENE | ND_FRAME, scene);
}
@@ -588,7 +590,7 @@ static void rna_FModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin
ID *id = ptr->id.data;
FModifier *fcm = (FModifier *)ptr->data;
AnimData *adt = BKE_animdata_from_id(id);
- DAG_id_tag_update(id, (GS(id->name) == ID_OB) ? OB_RECALC_OB : OB_RECALC_DATA);
+ DEG_id_tag_update(id, (GS(id->name) == ID_OB) ? OB_RECALC_OB : OB_RECALC_DATA);
if (adt != NULL) {
adt->recalc |= ADT_RECALC_ANIM;
}
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index 437095ffb31..074db855c17 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -46,7 +46,6 @@
#include "DNA_scene_types.h"
#include "DNA_particle_types.h"
-#include "BKE_depsgraph.h"
#include "BKE_fluidsim.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -54,6 +53,8 @@
#include "BKE_particle.h"
#include "BKE_pointcache.h"
+#include "DEG_depsgraph.h"
+
static StructRNA *rna_FluidSettings_refine(struct PointerRNA *ptr)
{
FluidsimSettings *fss = (FluidsimSettings *)ptr->data;
@@ -82,7 +83,7 @@ static void rna_fluid_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
{
Object *ob = ptr->id.data;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
}
diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c
index aa02a3c159d..bf64bb1181f 100644
--- a/source/blender/makesrna/intern/rna_group.c
+++ b/source/blender/makesrna/intern/rna_group.c
@@ -49,13 +49,14 @@ static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter)
{
ListBaseIterator *internal = &iter->internal.listbase;
- /* we are actually iterating a GroupObject list, so override get */
- return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((GroupObject *)internal->link)->ob);
+ /* 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 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 +64,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 +92,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 +101,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);
@@ -124,20 +125,18 @@ void RNA_def_group(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
- prop = RNA_def_property(srna, "layers", PROP_BOOLEAN, PROP_LAYER);
- RNA_def_property_boolean_sdna(prop, NULL, "layer", 1);
- RNA_def_property_array(prop, 20);
- RNA_def_property_ui_text(prop, "Dupli Layers", "Layers visible when this group is instanced as a dupli");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "gobject", NULL);
+ RNA_def_property_collection_sdna(prop, NULL, "view_layer->object_bases", NULL);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_ui_text(prop, "Objects", "A collection of this groups objects");
RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_Group_objects_get", NULL, NULL, NULL, NULL);
-
rna_def_group_objects(brna, prop);
+ prop = RNA_def_property(srna, "view_layer", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ViewLayer");
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "View Layer", "Group internal view layer");
}
#endif
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index cb71cf756ec..212a8bb8e20 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -32,9 +32,10 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_image.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -104,7 +105,7 @@ static void rna_Image_source_set(PointerRNA *ptr, int value)
if (value != ima->source) {
ima->source = value;
BKE_image_signal(ima, NULL, IMA_SIGNAL_SRC_CHANGE);
- DAG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
}
}
@@ -134,7 +135,7 @@ static void rna_Image_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P
Image *ima = ptr->id.data;
BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
- DAG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
}
static void rna_Image_generated_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -147,7 +148,7 @@ static void rna_Image_colormanage_update(Main *UNUSED(bmain), Scene *UNUSED(scen
{
Image *ima = ptr->id.data;
BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
- DAG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id);
WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
}
@@ -177,7 +178,7 @@ static void rna_ImageUser_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *
if (ptr->id.data) {
/* Update material or texture for render preview. */
- DAG_id_tag_update(ptr->id.data, 0);
+ DEG_id_tag_update(ptr->id.data, 0);
}
}
@@ -668,6 +669,7 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_IMAGE_DATA);
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_ui_text(prop, "File Name", "Image/Movie file name");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_reload_update");
@@ -707,6 +709,7 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Packed Files", "Collection of packed images");
prop = RNA_def_property(srna, "field_order", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_field_order_items);
RNA_def_property_ui_text(prop, "Field Order", "Order of video fields (select which lines are displayed first)");
@@ -714,6 +717,7 @@ static void rna_def_image(BlenderRNA *brna)
/* booleans */
prop = RNA_def_property(srna, "use_fields", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_FIELDS);
RNA_def_property_ui_text(prop, "Fields", "Use fields of the image");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_fields_update");
@@ -721,36 +725,43 @@ static void rna_def_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_view_as_render", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_VIEW_AS_RENDER);
RNA_def_property_ui_text(prop, "View as Render", "Apply render part of display transformation when displaying this image on the screen");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_IGNORE_ALPHA);
RNA_def_property_ui_text(prop, "Use Alpha", "Use the alpha channel information from the image or make image fully opaque");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update");
prop = RNA_def_property(srna, "use_deinterlace", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_DEINTERLACE);
RNA_def_property_ui_text(prop, "Deinterlace", "Deinterlace movie file on load");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_reload_update");
prop = RNA_def_property(srna, "use_multiview", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_USE_VIEWS);
RNA_def_property_ui_text(prop, "Use Multi-View", "Use Multiple Views (when available)");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_views_format_update");
prop = RNA_def_property(srna, "is_stereo_3d", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_funcs(prop, "rna_Image_is_stereo_3d_get", NULL);
RNA_def_property_ui_text(prop, "Stereo 3D", "Image has left and right views");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "is_multiview", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_funcs(prop, "rna_Image_is_multiview_get", NULL);
RNA_def_property_ui_text(prop, "Multiple Views", "Image has more than one view");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_funcs(prop, "rna_Image_dirty_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Dirty", "Image has changed and is not saved");
@@ -794,12 +805,14 @@ static void rna_def_image(BlenderRNA *brna)
/* realtime properties */
prop = RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_mapping_items);
RNA_def_property_ui_text(prop, "Mapping", "Mapping type to use for this image in the game engine");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "display_aspect", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_float_sdna(prop, NULL, "aspx");
RNA_def_property_array(prop, 2);
RNA_def_property_range(prop, 0.1f, FLT_MAX);
@@ -808,52 +821,61 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "use_animation", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_TWINANIM);
RNA_def_property_ui_text(prop, "Animated", "Use as animated texture in the game engine");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_animated_update");
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_int_sdna(prop, NULL, "twsta");
RNA_def_property_range(prop, 0, 255);
RNA_def_property_ui_text(prop, "Animation Start", "Start frame of an animated texture");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_animated_update");
prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_int_sdna(prop, NULL, "twend");
RNA_def_property_range(prop, 0, 255);
RNA_def_property_ui_text(prop, "Animation End", "End frame of an animated texture");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_animated_update");
prop = RNA_def_property(srna, "fps", PROP_INT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_int_sdna(prop, NULL, "animspeed");
RNA_def_property_range(prop, 1, 100);
RNA_def_property_ui_text(prop, "Animation Speed", "Speed of the animation in frames per second");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "use_tiles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_TILES);
RNA_def_property_ui_text(prop, "Tiles",
"Use of tilemode for faces (default shift-LMB to pick the tile for selected faces)");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "tiles_x", PROP_INT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_int_sdna(prop, NULL, "xrep");
RNA_def_property_range(prop, 1, 16);
RNA_def_property_ui_text(prop, "Tiles X", "Degree of repetition in the X direction");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "tiles_y", PROP_INT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_int_sdna(prop, NULL, "yrep");
RNA_def_property_range(prop, 1, 16);
RNA_def_property_ui_text(prop, "Tiles Y", "Degree of repetition in the Y direction");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "use_clamp_x", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_CLAMP_U);
RNA_def_property_ui_text(prop, "Clamp X", "Disable texture repeating horizontally");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "use_clamp_y", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_CLAMP_V);
RNA_def_property_ui_text(prop, "Clamp Y", "Disable texture repeating vertically");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
@@ -892,6 +914,7 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_float_vector(srna, "resolution", 2, NULL, 0, 0, "Resolution", "X/Y pixels per meter", 0, 0);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_float_funcs(prop, "rna_Image_resolution_get", "rna_Image_resolution_set", NULL);
prop = RNA_def_property(srna, "frame_duration", PROP_INT, PROP_UNSIGNED);
@@ -926,12 +949,14 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_enum_items(prop, alpha_mode_items);
RNA_def_property_ui_text(prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update");
/* multiview */
prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_enum_sdna(prop, NULL, "views_format");
RNA_def_property_enum_items(prop, rna_enum_views_format_items);
RNA_def_property_ui_text(prop, "Views Format", "Mode to load image views");
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index 61f1edc0af5..7f0ddf04724 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -56,9 +56,6 @@
#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
-#include "GPU_draw.h"
-#include "GPU_debug.h"
-
#include "DNA_image_types.h"
#include "DNA_scene_types.h"
@@ -251,6 +248,8 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag);
+ /* TODO(merwin): validate input (dimensions, filter, mag) before calling OpenGL
+ * instead of trusting input & testing for error after */
error = glGetError();
if (error) {
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 01c3c8033cf..7dffab4eefb 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -35,13 +35,18 @@
#define RNA_MAGIC ((int)~0)
+struct FreestyleSettings;
struct ID;
+struct IDOverrideStatic;
+struct IDOverrideStaticProperty;
+struct IDOverrideStaticPropertyOperation;
struct IDProperty;
struct Main;
struct Mesh;
struct Object;
struct ReportList;
struct SDNA;
+struct ViewLayer;
/* Data structures used during define */
@@ -166,10 +171,12 @@ void RNA_def_packedfile(struct BlenderRNA *brna);
void RNA_def_palette(struct BlenderRNA *brna);
void RNA_def_particle(struct BlenderRNA *brna);
void RNA_def_pose(struct BlenderRNA *brna);
+void RNA_def_lightprobe(struct BlenderRNA *brna);
void RNA_def_render(struct BlenderRNA *brna);
void RNA_def_rigidbody(struct BlenderRNA *brna);
void RNA_def_rna(struct BlenderRNA *brna);
void RNA_def_scene(struct BlenderRNA *brna);
+void RNA_def_view_layer(struct BlenderRNA *brna);
void RNA_def_screen(struct BlenderRNA *brna);
void RNA_def_sculpt_paint(struct BlenderRNA *brna);
void RNA_def_sensor(struct BlenderRNA *brna);
@@ -186,6 +193,8 @@ void RNA_def_ui(struct BlenderRNA *brna);
void RNA_def_userdef(struct BlenderRNA *brna);
void RNA_def_vfont(struct BlenderRNA *brna);
void RNA_def_wm(struct BlenderRNA *brna);
+void RNA_def_wm_manipulator(struct BlenderRNA *brna);
+void RNA_def_workspace(struct BlenderRNA *brna);
void RNA_def_world(struct BlenderRNA *brna);
void RNA_def_movieclip(struct BlenderRNA *brna);
void RNA_def_tracking(struct BlenderRNA *brna);
@@ -195,6 +204,12 @@ void RNA_def_mask(struct BlenderRNA *brna);
void rna_def_animdata_common(struct StructRNA *srna);
+bool rna_AnimaData_override_apply(
+ struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, struct PointerRNA *ptr_storage,
+ struct PropertyRNA *prop_local, struct PropertyRNA *prop_reference, struct PropertyRNA *prop_storage,
+ const int len_local, const int len_reference, const int len_storage,
+ struct IDOverrideStaticPropertyOperation *opop);
+
void rna_def_animviz_common(struct StructRNA *srna);
void rna_def_motionpath_common(struct StructRNA *srna);
@@ -205,7 +220,7 @@ void rna_def_mtex_common(struct BlenderRNA *brna, struct StructRNA *srna, const
const char *activeset, const char *activeeditable, const char *structname,
const char *structname_slots, const char *update, const char *update_index);
void rna_def_texpaint_slots(struct BlenderRNA *brna, struct StructRNA *srna);
-void rna_def_render_layer_common(struct StructRNA *srna, int scene);
+void rna_def_view_layer_common(struct StructRNA *srna, int scene);
void rna_def_actionbone_group_common(struct StructRNA *srna, int update_flag, const char *update_cb);
void rna_ActionGroup_colorset_set(struct PointerRNA *ptr, int value);
@@ -217,6 +232,7 @@ void rna_ID_name_set(struct PointerRNA *ptr, const char *value);
struct StructRNA *rna_ID_refine(struct PointerRNA *ptr);
struct IDProperty *rna_ID_idprops(struct PointerRNA *ptr, bool create);
void rna_ID_fake_user_set(struct PointerRNA *ptr, int value);
+void **rna_ID_instance(PointerRNA *ptr);
struct IDProperty *rna_PropertyGroup_idprops(struct PointerRNA *ptr, bool create);
void rna_PropertyGroup_unregister(struct Main *bmain, struct StructRNA *type);
struct StructRNA *rna_PropertyGroup_register(struct Main *bmain, struct ReportList *reports, void *data,
@@ -233,10 +249,33 @@ void rna_object_vcollayer_name_set(struct PointerRNA *ptr, const char *value, ch
PointerRNA rna_object_shapekey_index_get(struct ID *id, int value);
int rna_object_shapekey_index_set(struct ID *id, PointerRNA value, int current);
+/* ViewLayer related functions defined in rna_scene.c but required in rna_layer.c */
+void rna_def_freestyle_settings(struct BlenderRNA *brna);
+struct PointerRNA rna_FreestyleLineSet_linestyle_get(struct PointerRNA *ptr);
+void rna_FreestyleLineSet_linestyle_set(struct PointerRNA *ptr, struct PointerRNA value);
+struct FreestyleLineSet *rna_FreestyleSettings_lineset_add(
+ struct ID *id, struct FreestyleSettings *config, struct Main *bmain, const char *name);
+void rna_FreestyleSettings_lineset_remove(
+ struct ID *id, struct FreestyleSettings *config, struct ReportList *reports, struct PointerRNA *lineset_ptr);
+struct PointerRNA rna_FreestyleSettings_active_lineset_get(struct PointerRNA *ptr);
+void rna_FreestyleSettings_active_lineset_index_range(
+ struct PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax);
+int rna_FreestyleSettings_active_lineset_index_get(struct PointerRNA *ptr);
+void rna_FreestyleSettings_active_lineset_index_set(struct PointerRNA *ptr, int value);
+struct FreestyleModuleConfig *rna_FreestyleSettings_module_add(struct ID *id, struct FreestyleSettings *config);
+void rna_FreestyleSettings_module_remove(
+ struct ID *id, struct FreestyleSettings *config, struct ReportList *reports, struct PointerRNA *module_ptr);
+
+void rna_Scene_use_view_map_cache_update(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
+void rna_Scene_glsl_update(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
+void rna_Scene_freestyle_update(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
+void rna_ViewLayer_name_set(struct PointerRNA *ptr, const char *value);
+void rna_ViewLayer_pass_update(struct Main *bmain, struct Scene *activescene, struct PointerRNA *ptr);
+
/* named internal so as not to conflict with obj.update() rna func */
void rna_Object_internal_update_data(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
void rna_Mesh_update_draw(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
-void rna_TextureSlot_update(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
+void rna_TextureSlot_update(struct bContext *C, struct PointerRNA *ptr);
/* basic poll functions for object types */
int rna_Armature_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
@@ -267,6 +306,8 @@ void RNA_api_image(struct StructRNA *srna);
void RNA_api_lattice(struct StructRNA *srna);
void RNA_api_operator(struct StructRNA *srna);
void RNA_api_macro(struct StructRNA *srna);
+void RNA_api_manipulator(struct StructRNA *srna);
+void RNA_api_manipulatorgroup(struct StructRNA *srna);
void RNA_api_keyconfig(struct StructRNA *srna);
void RNA_api_keyconfigs(struct StructRNA *srna);
void RNA_api_keyingset(struct StructRNA *srna);
@@ -279,7 +320,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);
@@ -335,6 +376,8 @@ void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_cachefiles(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_paintcurves(BlenderRNA *brna, PropertyRNA *cprop);
+void RNA_def_main_workspaces(BlenderRNA *brna, PropertyRNA *cprop);
+void RNA_def_main_lightprobes(BlenderRNA *brna, PropertyRNA *cprop);
/* ID Properties */
@@ -357,6 +400,33 @@ extern StructRNA RNA_PropertyGroup;
struct IDProperty *rna_idproperty_check(struct PropertyRNA **prop, struct PointerRNA *ptr);
+/* Override default callbacks. */
+/* Default override callbacks for all types. */
+/* TODO: Maybe at some point we'll want to write that in direct RNA-generated code instead
+ * (like we do for default get/set/etc.)?
+ * Not obvious though, those are fairly more complicated than basic SDNA access.
+ */
+int rna_property_override_diff_default(
+ struct PointerRNA *ptr_a, struct PointerRNA *ptr_b,
+ struct PropertyRNA *prop_a, struct PropertyRNA *prop_b,
+ const int len_a, const int len_b,
+ const int mode,
+ struct IDOverrideStatic *override, const char *rna_path,
+ const int flags, bool *r_override_changed);
+
+bool rna_property_override_store_default(
+ struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, struct PointerRNA *ptr_storage,
+ struct PropertyRNA *prop_local, struct PropertyRNA *prop_reference, struct PropertyRNA *prop_storage,
+ const int len_local, const int len_reference, const int len_storage,
+ struct IDOverrideStaticPropertyOperation *opop);
+
+bool rna_property_override_apply_default(
+ struct PointerRNA *ptr_dst, struct PointerRNA *ptr_src, struct PointerRNA *ptr_storage,
+ struct PropertyRNA *prop_dst, struct PropertyRNA *prop_src, struct PropertyRNA *prop_storage,
+ const int len_dst, const int len_src, const int len_storage,
+ struct IDOverrideStaticPropertyOperation *opop);
+
+
/* Builtin Property Callbacks */
void rna_builtin_properties_begin(struct CollectionPropertyIterator *iter, struct PointerRNA *ptr);
@@ -402,7 +472,7 @@ PointerRNA rna_pointer_inherit_refine(struct PointerRNA *ptr, struct StructRNA *
int rna_parameter_size(struct PropertyRNA *parm);
struct Mesh *rna_Main_meshes_new_from_object(
- struct Main *bmain, struct ReportList *reports, struct Scene *sce,
+ struct Main *bmain, struct ReportList *reports, struct Scene *sce, struct ViewLayer *view_layer,
struct Object *ob, int apply_modifiers, int settings, int calc_tessface, int calc_undeformed);
/* XXX, these should not need to be defined here~! */
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index d93f3308b2a..fd0b655e41e 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -40,20 +40,14 @@ struct PointerRNA;
struct FunctionRNA;
struct CollectionPropertyIterator;
struct bContext;
+struct IDOverrideStatic;
+struct IDOverrideStaticProperty;
+struct IDOverrideStaticPropertyOperation;
struct IDProperty;
struct GHash;
struct Main;
struct Scene;
-#ifdef UNIT_TEST
-#define RNA_MAX_ARRAY_LENGTH 64
-#else
-#define RNA_MAX_ARRAY_LENGTH 32
-#endif
-
-#define RNA_MAX_ARRAY_DIMENSION 3
-
-
/* store local properties here */
#define RNA_IDP_UI "_RNA_UI"
@@ -126,6 +120,60 @@ typedef void (*PropStringSetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *
typedef int (*PropEnumGetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop);
typedef void (*PropEnumSetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, int value);
+/* Handling override operations, and also comparison. */
+enum {
+ /* Do not compare properties that are not overridable. */
+ RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE = 1 << 0,
+ /* Do not compare properties that are already overridden. */
+ RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN = 1 << 1,
+};
+
+/**
+ * If \a override is NULL, merely do comparison between prop_a from ptr_a and prop_b from ptr_b,
+ * following comparison mode given.
+ * If \a override and \a rna_path are not NULL, it will add a new override operation for overridable properties
+ * that differ and have not yet been overridden (and set accordingly \a r_override_changed if given).
+ *
+ * \note Given PropertyRNA are final (in case of IDProps...).
+ * \note In non-array cases, \a len values are 0.
+ * \note \a override, \a rna_path and \a r_override_changed may be NULL pointers.
+ */
+typedef int (*RNAPropOverrideDiff)(
+ struct PointerRNA *ptr_a, struct PointerRNA *ptr_b,
+ struct PropertyRNA *prop_a, struct PropertyRNA *prop_b,
+ const int len_a, const int len_b,
+ const int mode,
+ struct IDOverrideStatic *override, const char *rna_path,
+ const int flags, bool *r_override_changed);
+
+/**
+ * Only used for differential override (add, sub, etc.).
+ * Store into storage the value needed to transform reference's value into local's value.
+ *
+ * \note Given PropertyRNA are final (in case of IDProps...).
+ * \note In non-array cases, \a len values are 0.
+ * \note Might change given override operation (e.g. change 'add' one into 'sub'), in case computed storage value
+ * is out of range (or even change it to basic 'set' operation if nothing else works).
+ */
+typedef bool (*RNAPropOverrideStore)(
+ struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, struct PointerRNA *ptr_storage,
+ struct PropertyRNA *prop_local, struct PropertyRNA *prop_reference, struct PropertyRNA *prop_storage,
+ const int len_local, const int len_reference, const int len_storage,
+ struct IDOverrideStaticPropertyOperation *opop);
+
+/**
+ * Apply given override operation from src to dst (using value from storage as second operand
+ * for differential operations).
+ *
+ * \note Given PropertyRNA are final (in case of IDProps...).
+ * \note In non-array cases, \a len values are 0.
+ */
+typedef bool (*RNAPropOverrideApply)(
+ struct PointerRNA *ptr_dst, struct PointerRNA *ptr_src, struct PointerRNA *ptr_storage,
+ struct PropertyRNA *prop_dst, struct PropertyRNA *prop_src, struct PropertyRNA *prop_storage,
+ const int len_dst, const int len_src, const int len_storage,
+ struct IDOverrideStaticPropertyOperation *opop);
+
/* Container - generic abstracted container of RNA properties */
typedef struct ContainerRNA {
void *next, *prev;
@@ -203,6 +251,11 @@ struct PropertyRNA {
/* callback for testing if array-item editable (if applicable) */
ItemEditableFunc itemeditable;
+ /* Override handling callbacks (diff is also used for comparison). */
+ RNAPropOverrideDiff override_diff;
+ RNAPropOverrideStore override_store;
+ RNAPropOverrideApply override_apply;
+
/* raw access */
int rawoffset;
RawPropertyType rawtype;
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index e65011d34d7..a47a5c604b4 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -51,10 +51,11 @@
#include "DNA_object_types.h"
#include "BKE_animsys.h"
-#include "BKE_depsgraph.h"
#include "BKE_key.h"
#include "BKE_main.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -486,7 +487,7 @@ static void rna_Key_update_data(Main *bmain, Scene *UNUSED(scene), PointerRNA *p
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (BKE_key_from_object(ob) == key) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
}
}
diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c
index f29fa44d306..9e28e31057d 100644
--- a/source/blender/makesrna/intern/rna_lamp.c
+++ b/source/blender/makesrna/intern/rna_lamp.c
@@ -45,10 +45,11 @@
#include "MEM_guardedalloc.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_texture.h"
+#include "DEG_depsgraph.h"
+
#include "ED_node.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -134,7 +135,7 @@ static void rna_Lamp_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN
{
Lamp *la = ptr->id.data;
- DAG_id_tag_update(&la->id, 0);
+ DEG_id_tag_update(&la->id, 0);
WM_main_add_notifier(NC_LAMP | ND_LIGHTING, la);
}
@@ -142,7 +143,7 @@ static void rna_Lamp_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin
{
Lamp *la = ptr->id.data;
- DAG_id_tag_update(&la->id, 0);
+ DEG_id_tag_update(&la->id, 0);
WM_main_add_notifier(NC_LAMP | ND_LIGHTING_DRAW, la);
}
@@ -150,7 +151,7 @@ static void rna_Lamp_sky_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point
{
Lamp *la = ptr->id.data;
- DAG_id_tag_update(&la->id, 0);
+ DEG_id_tag_update(&la->id, 0);
WM_main_add_notifier(NC_LAMP | ND_SKY, la);
}
@@ -475,7 +476,7 @@ static void rna_def_lamp_falloff(StructRNA *srna)
RNA_def_property_update(prop, 0, "rna_Lamp_draw_update");
}
-static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
+static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area, int sun)
{
PropertyRNA *prop;
@@ -586,8 +587,9 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
prop = RNA_def_property(srna, "shadow_buffer_bias", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "bias");
- RNA_def_property_range(prop, 0.001f, 5.0f);
- RNA_def_property_ui_text(prop, "Shadow Buffer Bias", "Shadow buffer sampling bias");
+ RNA_def_property_range(prop, 0.001f, 9999.0f);
+ RNA_def_property_ui_range(prop, 0.001f, 5.0f, 1.0, 3);
+ RNA_def_property_ui_text(prop, "Shadow Buffer Bias", "Bias for reducing self shadowing");
RNA_def_property_update(prop, 0, "rna_Lamp_update");
prop = RNA_def_property(srna, "shadow_buffer_bleed_bias", PROP_FLOAT, PROP_NONE);
@@ -596,6 +598,12 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
RNA_def_property_ui_text(prop, "Shadow Buffer Bleed Bias", "Bias for reducing light-bleed on variance shadow maps");
RNA_def_property_update(prop, 0, "rna_Lamp_update");
+ prop = RNA_def_property(srna, "shadow_buffer_exp", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "bleedexp");
+ RNA_def_property_range(prop, 1.0f, 9999.0f);
+ RNA_def_property_ui_text(prop, "Shadow Buffer Exponent", "Bias for reducing light-bleed on exponential shadow maps");
+ RNA_def_property_update(prop, 0, "rna_Lamp_update");
+
prop = RNA_def_property(srna, "shadow_buffer_soft", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "soft");
RNA_def_property_range(prop, 0.0f, 100.0f);
@@ -690,6 +698,67 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_LAYER_SHADOW);
RNA_def_property_ui_text(prop, "Shadow Layer", "Objects on the same layers only cast shadows");
RNA_def_property_update(prop, 0, "rna_Lamp_update");
+
+ /* Eevee */
+ prop = RNA_def_property(srna, "use_contact_shadow", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_SHAD_CONTACT);
+ RNA_def_property_ui_text(prop, "Contact Shadow", "Use screen space raytracing to have correct shadowing "
+ "near occluder, or for small features that does not appear "
+ "in shadow maps");
+ RNA_def_property_update(prop, 0, "rna_Lamp_update");
+
+ prop = RNA_def_property(srna, "contact_shadow_distance", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "contact_dist");
+ RNA_def_property_range(prop, 0.0f, 9999.0f);
+ RNA_def_property_ui_text(prop, "Contact Shadow Distance", "World space distance in which to search for "
+ "screen space occluder");
+ RNA_def_property_update(prop, 0, "rna_Lamp_update");
+
+ prop = RNA_def_property(srna, "contact_shadow_bias", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "contact_bias");
+ RNA_def_property_range(prop, 0.001f, 9999.0f);
+ RNA_def_property_ui_range(prop, 0.001f, 5.0f, 1.0, 3);
+ RNA_def_property_ui_text(prop, "Contact Shadow Bias", "Bias to avoid self shadowing");
+ RNA_def_property_update(prop, 0, "rna_Lamp_update");
+
+ prop = RNA_def_property(srna, "contact_shadow_soft_size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "contact_spread");
+ RNA_def_property_range(prop, 0.0f, 9999.0f);
+ RNA_def_property_ui_text(prop, "Contact Shadow Soft", "Control how soft the contact shadows will be");
+ RNA_def_property_update(prop, 0, "rna_Lamp_update");
+
+ prop = RNA_def_property(srna, "contact_shadow_thickness", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "contact_thickness");
+ RNA_def_property_range(prop, 0.0f, 9999.0f);
+ RNA_def_property_ui_range(prop, 0, 100, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Contact Shadow Thickness", "Pixel thickness used to detect occlusion");
+ RNA_def_property_update(prop, 0, "rna_Lamp_update");
+
+ if (sun) {
+ prop = RNA_def_property(srna, "shadow_cascade_max_distance", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "cascade_max_dist");
+ RNA_def_property_range(prop, 0.0f, 9999.0f);
+ RNA_def_property_ui_text(prop, "Cascade Max Distance", "End distance of the cascaded shadow map (only in perspective view)");
+ RNA_def_property_update(prop, 0, "rna_Lamp_update");
+
+ prop = RNA_def_property(srna, "shadow_cascade_count", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "cascade_count");
+ RNA_def_property_range(prop, 1, 4);
+ RNA_def_property_ui_text(prop, "Cascade Count", "Number of texture used by the cascaded shadow map");
+ RNA_def_property_update(prop, 0, "rna_Lamp_update");
+
+ prop = RNA_def_property(srna, "shadow_cascade_exponent", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "cascade_exponent");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Exponential Distribution", "Higher value increase resolution towards the viewpoint");
+ RNA_def_property_update(prop, 0, "rna_Lamp_update");
+
+ prop = RNA_def_property(srna, "shadow_cascade_fade", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "cascade_fade");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Cascade Fade", "How smooth is the transition between each cascade");
+ RNA_def_property_update(prop, 0, "rna_Lamp_update");
+ }
}
static void rna_def_point_lamp(BlenderRNA *brna)
@@ -702,7 +771,7 @@ static void rna_def_point_lamp(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_LAMP_POINT);
rna_def_lamp_falloff(srna);
- rna_def_lamp_shadow(srna, 0, 0);
+ rna_def_lamp_shadow(srna, 0, 0, 0);
}
static void rna_def_area_lamp(BlenderRNA *brna)
@@ -721,7 +790,8 @@ static void rna_def_area_lamp(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Area Lamp", "Directional area lamp");
RNA_def_struct_ui_icon(srna, ICON_LAMP_AREA);
- rna_def_lamp_shadow(srna, 0, 1);
+ rna_def_lamp_shadow(srna, 0, 1, 0);
+ rna_def_lamp_falloff(srna);
prop = RNA_def_property(srna, "use_umbra", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "ray_samp_type", LA_SAMP_UMBRA);
@@ -777,7 +847,7 @@ static void rna_def_spot_lamp(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_LAMP_SPOT);
rna_def_lamp_falloff(srna);
- rna_def_lamp_shadow(srna, 1, 0);
+ rna_def_lamp_shadow(srna, 1, 0, 0);
prop = RNA_def_property(srna, "use_square", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_SQUARE);
@@ -830,7 +900,7 @@ static void rna_def_sun_lamp(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Sun Lamp", "Constant direction parallel ray lamp");
RNA_def_struct_ui_icon(srna, ICON_LAMP_SUN);
- rna_def_lamp_shadow(srna, 0, 0);
+ rna_def_lamp_shadow(srna, 0, 0, 1);
/* sky */
prop = RNA_def_property(srna, "sky", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c
index 9424ddf7d0e..904a6289fc1 100644
--- a/source/blender/makesrna/intern/rna_lattice.c
+++ b/source/blender/makesrna/intern/rna_lattice.c
@@ -43,11 +43,12 @@
#include "DNA_scene_types.h"
#include "BLI_string.h"
-#include "BKE_depsgraph.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_deform.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
#include "ED_lattice.h"
@@ -97,7 +98,7 @@ static void rna_Lattice_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), P
{
ID *id = ptr->id.data;
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
}
@@ -119,7 +120,7 @@ static void rna_Lattice_update_data_editlatt(Main *UNUSED(bmain), Scene *UNUSED(
BLI_strncpy(lt_em->vgroup, lt->vgroup, sizeof(lt_em->vgroup));
}
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
}
diff --git a/source/blender/makesrna/intern/rna_lattice_api.c b/source/blender/makesrna/intern/rna_lattice_api.c
index 2ea59d31262..5637f8d9248 100644
--- a/source/blender/makesrna/intern/rna_lattice_api.c
+++ b/source/blender/makesrna/intern/rna_lattice_api.c
@@ -45,8 +45,14 @@ static void rna_Lattice_transform(Lattice *lt, float *mat, int shape_keys)
{
BKE_lattice_transform(lt, (float (*)[4])mat, shape_keys);
- DAG_id_tag_update(&lt->id, 0);
+ DEG_id_tag_update(&lt->id, 0);
}
+
+static void rna_Lattice_update_gpu_tag(Lattice *lt)
+{
+ BKE_lattice_batch_cache_dirty(lt, BKE_LATTICE_BATCH_DIRTY_ALL);
+}
+
#else
void RNA_api_lattice(StructRNA *srna)
@@ -59,6 +65,8 @@ void RNA_api_lattice(StructRNA *srna)
parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_boolean(func, "shape_keys", 0, "", "Transform Shape Keys");
+
+ RNA_def_function(srna, "update_gpu_tag", "rna_Lattice_update_gpu_tag");
}
#endif
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
new file mode 100644
index 00000000000..877d6b250c0
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -0,0 +1,2320 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/makesrna/intern/rna_layer.c
+ * \ingroup RNA
+ */
+
+#include "DNA_scene_types.h"
+#include "DNA_layer_types.h"
+
+#include "BLI_math.h"
+#include "BLI_string_utils.h"
+
+#include "BLT_translation.h"
+
+#include "ED_object.h"
+#include "ED_render.h"
+
+#include "RE_engine.h"
+
+#include "DRW_engine.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
+const EnumPropertyItem rna_enum_layer_collection_mode_settings_type_items[] = {
+ {COLLECTION_MODE_OBJECT, "OBJECT", 0, "Object", ""},
+ {COLLECTION_MODE_EDIT, "EDIT", 0, "Edit", ""},
+ {COLLECTION_MODE_PAINT_WEIGHT, "PAINT_WEIGHT", 0, "Weight Paint", ""},
+ {COLLECTION_MODE_PAINT_WEIGHT, "PAINT_VERTEX", 0, "Vertex Paint", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+const EnumPropertyItem rna_enum_collection_type_items[] = {
+ {COLLECTION_TYPE_NONE, "NONE", 0, "Normal", ""},
+ {COLLECTION_TYPE_GROUP_INTERNAL, "GROUP_INTERNAL", 0, "Group Internal", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+#ifdef RNA_RUNTIME
+
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+
+#include "RNA_access.h"
+
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
+#include "BKE_node.h"
+#include "BKE_scene.h"
+#include "BKE_mesh.h"
+
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+static StructRNA *rna_SceneCollection_refine(PointerRNA *ptr)
+{
+ SceneCollection *scene_collection = (SceneCollection *)ptr->data;
+ switch (scene_collection->type) {
+ case COLLECTION_TYPE_GROUP_INTERNAL:
+ case COLLECTION_TYPE_NONE:
+ return &RNA_SceneCollection;
+ default:
+ BLI_assert(!"Collection type not fully implemented");
+ break;
+ }
+ return &RNA_SceneCollection;
+}
+
+static void rna_SceneCollection_name_set(PointerRNA *ptr, const char *value)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ SceneCollection *sc = (SceneCollection *)ptr->data;
+ BKE_collection_rename(scene, sc, value);
+}
+
+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 int rna_SceneCollection_move_above(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst)
+{
+ if (!BKE_collection_move_above(id, sc_dst, sc_src)) {
+ return 0;
+ }
+
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
+}
+
+static int rna_SceneCollection_move_below(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst)
+{
+ if (!BKE_collection_move_below(id, sc_dst, sc_src)) {
+ return 0;
+ }
+
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
+}
+
+static int rna_SceneCollection_move_into(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst)
+{
+ if (!BKE_collection_move_into(id, sc_dst, sc_src)) {
+ return 0;
+ }
+
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
+}
+
+static SceneCollection *rna_SceneCollection_new(
+ ID *id, SceneCollection *sc_parent, Main *bmain, const char *name)
+{
+ SceneCollection *sc = BKE_collection_add(id, sc_parent, COLLECTION_TYPE_NONE, name);
+
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return sc;
+}
+
+static void rna_SceneCollection_remove(
+ ID *id, SceneCollection *sc_parent, Main *bmain, ReportList *reports, PointerRNA *sc_ptr)
+{
+ 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(id, 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);
+
+ DEG_relations_tag_update(bmain);
+ 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->id, sc, ob);
+
+ /* TODO(sergey): Only update relations for the current scene. */
+ DEG_relations_tag_update(bmain);
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+
+ DEG_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->id, sc, ob, false);
+
+ /* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */
+ DEG_relations_tag_update(bmain);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
+}
+
+/****** layer collection engine settings *******/
+
+#define RNA_LAYER_ENGINE_GET_SET(_TYPE_, _ENGINE_, _MODE_, _NAME_) \
+static _TYPE_ rna_LayerEngineSettings_##_ENGINE_##_##_NAME_##_get(PointerRNA *ptr) \
+{ \
+ IDProperty *props = (IDProperty *)ptr->data; \
+ return BKE_collection_engine_property_value_get_##_TYPE_(props, #_NAME_); \
+} \
+ \
+static void rna_LayerEngineSettings_##_ENGINE_##_##_NAME_##_set(PointerRNA *ptr, _TYPE_ value) \
+{ \
+ IDProperty *props = (IDProperty *)ptr->data; \
+ BKE_collection_engine_property_value_set_##_TYPE_(props, #_NAME_, value); \
+}
+
+#define RNA_LAYER_ENGINE_GET_SET_ARRAY(_TYPE_, _ENGINE_, _MODE_, _NAME_, _LEN_) \
+static void rna_LayerEngineSettings_##_ENGINE_##_##_NAME_##_get(PointerRNA *ptr, _TYPE_ *values) \
+{ \
+ IDProperty *props = (IDProperty *)ptr->data; \
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, #_NAME_); \
+ if (idprop != NULL) { \
+ memcpy(values, IDP_Array(idprop), sizeof(_TYPE_) * idprop->len); \
+ } \
+} \
+ \
+static void rna_LayerEngineSettings_##_ENGINE_##_##_NAME_##_set(PointerRNA *ptr, const _TYPE_ *values) \
+{ \
+ IDProperty *props = (IDProperty *)ptr->data; \
+ BKE_collection_engine_property_value_set_##_TYPE_##_array(props, #_NAME_, values); \
+}
+
+#define RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(float, Clay, COLLECTION_MODE_NONE, _NAME_)
+
+#define RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT_ARRAY(_NAME_, _LEN_) \
+ RNA_LAYER_ENGINE_GET_SET_ARRAY(float, Clay, COLLECTION_MODE_NONE, _NAME_, _LEN_)
+
+#define RNA_LAYER_ENGINE_CLAY_GET_SET_INT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(int, Clay, COLLECTION_MODE_NONE, _NAME_)
+
+#define RNA_LAYER_ENGINE_CLAY_GET_SET_BOOL(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(bool, Clay, COLLECTION_MODE_NONE, _NAME_)
+
+#define RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(float, Eevee, COLLECTION_MODE_NONE, _NAME_)
+
+#define RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT_ARRAY(_NAME_, _LEN_) \
+ RNA_LAYER_ENGINE_GET_SET_ARRAY(float, Eevee, COLLECTION_MODE_NONE, _NAME_, _LEN_)
+
+#define RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(int, Eevee, COLLECTION_MODE_NONE, _NAME_)
+
+#define RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(bool, Eevee, COLLECTION_MODE_NONE, _NAME_)
+
+/* mode engines */
+
+#define RNA_LAYER_MODE_OBJECT_GET_SET_FLOAT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(float, ObjectMode, COLLECTION_MODE_OBJECT, _NAME_)
+
+#define RNA_LAYER_MODE_OBJECT_GET_SET_INT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(int, ObjectMode, COLLECTION_MODE_OBJECT, _NAME_)
+
+#define RNA_LAYER_MODE_OBJECT_GET_SET_BOOL(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(bool, ObjectMode, COLLECTION_MODE_OBJECT, _NAME_)
+
+#define RNA_LAYER_MODE_EDIT_GET_SET_FLOAT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(float, EditMode, COLLECTION_MODE_EDIT, _NAME_)
+
+#define RNA_LAYER_MODE_EDIT_GET_SET_INT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(int, EditMode, COLLECTION_MODE_EDIT, _NAME_)
+
+#define RNA_LAYER_MODE_EDIT_GET_SET_BOOL(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(bool, EditMode, COLLECTION_MODE_EDIT, _NAME_)
+
+#define RNA_LAYER_MODE_PAINT_WEIGHT_GET_SET_BOOL(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(bool, PaintWeightMode, COLLECTION_MODE_PAINT_WEIGHT, _NAME_)
+
+#define RNA_LAYER_MODE_PAINT_VERTEX_GET_SET_BOOL(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(bool, PaintVertexMode, COLLECTION_MODE_PAINT_VERTEX, _NAME_)
+
+/* clay engine */
+#ifdef WITH_CLAY_ENGINE
+/* ViewLayer settings. */
+RNA_LAYER_ENGINE_CLAY_GET_SET_INT(ssao_samples)
+
+/* LayerCollection settings. */
+RNA_LAYER_ENGINE_CLAY_GET_SET_INT(matcap_icon)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(matcap_rotation)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(matcap_hue)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(matcap_saturation)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(matcap_value)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_factor_cavity)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_factor_edge)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_distance)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_attenuation)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(hair_brightness_randomness)
+#endif /* WITH_CLAY_ENGINE */
+
+/* eevee engine */
+/* ViewLayer settings. */
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(gtao_enable)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(gtao_use_bent_normals)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(gtao_denoise)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(gtao_bounce)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(gtao_factor)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(gtao_quality)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(gtao_distance)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(gtao_samples)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(dof_enable)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(bokeh_max_size)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(bokeh_threshold)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(bloom_enable)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(bloom_threshold)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT_ARRAY(bloom_color, 3)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(bloom_knee)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(bloom_radius)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(bloom_clamp)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(bloom_intensity)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(motion_blur_enable)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(motion_blur_samples)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(motion_blur_shutter)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_enable)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(volumetric_start)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(volumetric_end)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(volumetric_tile_size)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(volumetric_samples)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(volumetric_sample_distribution)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_lights)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(volumetric_light_clamp)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_shadows)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(volumetric_shadow_samples)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_colored_transmittance)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(sss_enable)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(sss_samples)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(sss_jitter_threshold)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(sss_separate_albedo)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_refraction)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_enable)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_halfres)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(ssr_ray_count)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(ssr_quality)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(ssr_max_roughness)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(ssr_thickness)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(ssr_border_fade)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(ssr_firefly_fac)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(shadow_method)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(shadow_size)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(shadow_high_bitdepth)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(taa_samples)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(gi_diffuse_bounces)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(gi_cubemap_resolution)
+RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(gi_visibility_resolution)
+
+/* object engine */
+RNA_LAYER_MODE_OBJECT_GET_SET_BOOL(show_wire)
+RNA_LAYER_MODE_OBJECT_GET_SET_BOOL(show_backface_culling)
+
+/* mesh engine */
+RNA_LAYER_MODE_EDIT_GET_SET_BOOL(show_occlude_wire)
+RNA_LAYER_MODE_EDIT_GET_SET_BOOL(show_weight)
+RNA_LAYER_MODE_EDIT_GET_SET_BOOL(face_normals_show)
+RNA_LAYER_MODE_EDIT_GET_SET_BOOL(vert_normals_show)
+RNA_LAYER_MODE_EDIT_GET_SET_BOOL(loop_normals_show)
+RNA_LAYER_MODE_EDIT_GET_SET_FLOAT(normals_length)
+RNA_LAYER_MODE_EDIT_GET_SET_FLOAT(backwire_opacity)
+
+/* weight paint engine */
+RNA_LAYER_MODE_PAINT_WEIGHT_GET_SET_BOOL(use_shading)
+RNA_LAYER_MODE_PAINT_WEIGHT_GET_SET_BOOL(use_wire)
+
+/* vertex paint engine */
+RNA_LAYER_MODE_PAINT_VERTEX_GET_SET_BOOL(use_shading)
+RNA_LAYER_MODE_PAINT_VERTEX_GET_SET_BOOL(use_wire)
+
+#undef RNA_LAYER_ENGINE_GET_SET
+
+static void rna_ViewLayerEngineSettings_update(bContext *C, PointerRNA *UNUSED(ptr))
+{
+ Scene *scene = CTX_data_scene(C);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+}
+
+static void rna_LayerCollectionEngineSettings_update(bContext *UNUSED(C), PointerRNA *ptr)
+{
+ ID *id = ptr->id.data;
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(id, 0);
+
+ /* Instead of passing 'noteflag' to the rna update function, we handle the notifier ourselves.
+ * We need to do this because the LayerCollection may be coming from different ID types (Scene or Group)
+ * and when using NC_SCENE the id most match the active scene for the listener to receive the notification.*/
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+}
+
+static void rna_LayerCollectionEngineSettings_wire_update(bContext *C, PointerRNA *UNUSED(ptr))
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+
+ if (ob != NULL && ob->type == OB_MESH) {
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ }
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+}
+
+/***********************************/
+
+static void engine_settings_use(IDProperty *root, IDProperty *props, PointerRNA *props_ptr, const char *identifier)
+{
+ PropertyRNA *prop = RNA_struct_find_property(props_ptr, identifier);
+
+ switch (RNA_property_type(prop)) {
+ case PROP_FLOAT:
+ {
+ float value = BKE_collection_engine_property_value_get_float(props, identifier);
+ BKE_collection_engine_property_add_float(root, identifier, value);
+ break;
+ }
+ case PROP_ENUM:
+ {
+ int value = BKE_collection_engine_property_value_get_int(props, identifier);
+ BKE_collection_engine_property_add_int(root, identifier, value);
+ break;
+ }
+ case PROP_INT:
+ {
+ int value = BKE_collection_engine_property_value_get_int(props, identifier);
+ BKE_collection_engine_property_add_int(root, identifier, value);
+ break;
+ }
+ case PROP_BOOLEAN:
+ {
+ int value = BKE_collection_engine_property_value_get_int(props, identifier);
+ BKE_collection_engine_property_add_bool(root, identifier, value);
+ break;
+ }
+ case PROP_STRING:
+ case PROP_POINTER:
+ case PROP_COLLECTION:
+ default:
+ break;
+ }
+}
+
+static StructRNA *rna_ViewLayerSettings_refine(PointerRNA *ptr)
+{
+ IDProperty *props = (IDProperty *)ptr->data;
+ BLI_assert(props && props->type == IDP_GROUP);
+
+ switch (props->subtype) {
+ case IDP_GROUP_SUB_ENGINE_RENDER:
+#ifdef WITH_CLAY_ENGINE
+ if (STREQ(props->name, RE_engine_id_BLENDER_CLAY)) {
+ return &RNA_ViewLayerEngineSettingsClay;
+ }
+#endif
+ if (STREQ(props->name, RE_engine_id_BLENDER_EEVEE)) {
+ return &RNA_ViewLayerEngineSettingsEevee;
+ }
+ break;
+ case IDP_GROUP_SUB_MODE_OBJECT:
+ case IDP_GROUP_SUB_MODE_EDIT:
+ case IDP_GROUP_SUB_MODE_PAINT_WEIGHT:
+ case IDP_GROUP_SUB_MODE_PAINT_VERTEX:
+ default:
+ BLI_assert(!"Mode not fully implemented");
+ break;
+ }
+
+ return &RNA_ViewLayerSettings;
+}
+
+static void rna_ViewLayerSettings_name_get(PointerRNA *ptr, char *value)
+{
+ IDProperty *props = (IDProperty *)ptr->data;
+ strcpy(value, props->name);
+}
+
+static int rna_ViewLayerSettings_name_length(PointerRNA *ptr)
+{
+ IDProperty *props = (IDProperty *)ptr->data;
+ return strnlen(props->name, sizeof(props->name));
+}
+
+static void rna_ViewLayerSettings_use(ID *id, IDProperty *props, const char *identifier)
+{
+ Scene *scene = (Scene *)id;
+ PointerRNA scene_props_ptr;
+ IDProperty *scene_props;
+
+ scene_props = BKE_view_layer_engine_scene_get(scene, COLLECTION_MODE_NONE, props->name);
+ RNA_pointer_create(id, &RNA_ViewLayerSettings, scene_props, &scene_props_ptr);
+
+ engine_settings_use(props, scene_props, &scene_props_ptr, identifier);
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(id, 0);
+}
+
+static void rna_ViewLayerSettings_unuse(ID *id, IDProperty *props, const char *identifier)
+{
+ IDProperty *prop_to_remove = IDP_GetPropertyFromGroup(props, identifier);
+ IDP_FreeFromGroup(props, prop_to_remove);
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(id, 0);
+}
+
+static StructRNA *rna_LayerCollectionSettings_refine(PointerRNA *ptr)
+{
+ IDProperty *props = (IDProperty *)ptr->data;
+ BLI_assert(props && props->type == IDP_GROUP);
+
+ switch (props->subtype) {
+ case IDP_GROUP_SUB_ENGINE_RENDER:
+#ifdef WITH_CLAY_ENGINE
+ if (STREQ(props->name, RE_engine_id_BLENDER_CLAY)) {
+ return &RNA_LayerCollectionEngineSettingsClay;
+ }
+#endif
+ if (STREQ(props->name, RE_engine_id_BLENDER_EEVEE)) {
+ /* printf("Mode not fully implemented\n"); */
+ return &RNA_LayerCollectionSettings;
+ }
+ break;
+ case IDP_GROUP_SUB_MODE_OBJECT:
+ return &RNA_LayerCollectionModeSettingsObject;
+ break;
+ case IDP_GROUP_SUB_MODE_EDIT:
+ return &RNA_LayerCollectionModeSettingsEdit;
+ break;
+ case IDP_GROUP_SUB_MODE_PAINT_WEIGHT:
+ return &RNA_LayerCollectionModeSettingsPaintWeight;
+ break;
+ case IDP_GROUP_SUB_MODE_PAINT_VERTEX:
+ return &RNA_LayerCollectionModeSettingsPaintVertex;
+ break;
+ default:
+ BLI_assert(!"Mode not fully implemented");
+ break;
+ }
+
+ return &RNA_LayerCollectionSettings;
+}
+
+static void rna_LayerCollectionSettings_name_get(PointerRNA *ptr, char *value)
+{
+ IDProperty *props = (IDProperty *)ptr->data;
+ strcpy(value, props->name);
+}
+
+static int rna_LayerCollectionSettings_name_length(PointerRNA *ptr)
+{
+ IDProperty *props = (IDProperty *)ptr->data;
+ return strnlen(props->name, sizeof(props->name));
+}
+
+static void rna_LayerCollectionSettings_use(ID *id, IDProperty *props, const char *identifier)
+{
+ Scene *scene = (Scene *)id;
+ PointerRNA scene_props_ptr;
+ IDProperty *scene_props;
+
+ scene_props = BKE_layer_collection_engine_scene_get(scene, COLLECTION_MODE_NONE, props->name);
+ RNA_pointer_create(id, &RNA_LayerCollectionSettings, scene_props, &scene_props_ptr);
+ engine_settings_use(props, scene_props, &scene_props_ptr, identifier);
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(id, 0);
+}
+
+static void rna_LayerCollectionSettings_unuse(ID *id, IDProperty *props, const char *identifier)
+{
+ IDProperty *prop_to_remove = IDP_GetPropertyFromGroup(props, identifier);
+ IDP_FreeFromGroup(props, prop_to_remove);
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(id, 0);
+}
+
+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;
+ BKE_collection_rename(scene, sc, value);
+}
+
+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 int rna_LayerCollection_move_above(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst)
+{
+ if (!BKE_layer_collection_move_above(id, lc_dst, lc_src)) {
+ return 0;
+ }
+
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
+}
+
+static int rna_LayerCollection_move_below(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst)
+{
+ if (!BKE_layer_collection_move_below(id, lc_dst, lc_src)) {
+ return 0;
+ }
+
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
+}
+
+static int rna_LayerCollection_move_into(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst)
+{
+ if (!BKE_layer_collection_move_into(id, lc_dst, lc_src)) {
+ return 0;
+ }
+
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
+}
+
+static void rna_LayerCollection_flag_update(bContext *C, PointerRNA *ptr)
+{
+ ID *id = ptr->id.data;
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(id, 0);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+}
+
+static void rna_LayerCollection_enable_set(
+ ID *id, LayerCollection *layer_collection, Main *bmain, bContext *C, ReportList *reports, int value)
+{
+ ViewLayer *view_layer;
+ if (GS(id->name) == ID_SCE) {
+ Scene *scene = (Scene *)id;
+ view_layer = BKE_view_layer_find_from_collection(&scene->id, layer_collection);
+ }
+ else {
+ BLI_assert(GS(id->name) == ID_GR);
+ Group *group = (Group *)id;
+ view_layer = group->view_layer;
+ }
+
+ if (layer_collection->flag & COLLECTION_DISABLED) {
+ if (value == 1) {
+ BKE_collection_enable(view_layer, layer_collection);
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "Layer collection '%s' is already disabled",
+ layer_collection->scene_collection->name);
+ return;
+ }
+ }
+ else {
+ if (value == 0) {
+ BKE_collection_disable(view_layer, layer_collection);
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "Layer collection '%s' is already enabled",
+ layer_collection->scene_collection->name);
+ }
+ }
+
+ Scene *scene = CTX_data_scene(C);
+ DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+}
+
+static Group *rna_LayerCollection_create_group(
+ ID *id, LayerCollection *layer_collection, Main *bmain, bContext *C, ReportList *reports)
+{
+ Group *group;
+ Scene *scene = (Scene *)id;
+ SceneCollection *scene_collection = layer_collection->scene_collection;
+
+ /* The master collection can't be converted. */
+ if (scene_collection == BKE_collection_master(&scene->id)) {
+ BKE_report(reports, RPT_ERROR, "The master collection can't be converted to group");
+ return NULL;
+ }
+
+ group = BKE_collection_group_create(bmain, scene, layer_collection);
+ if (group == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Failed to convert collection %s", scene_collection->name);
+ return NULL;
+ }
+
+ DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ return group;
+}
+
+static int rna_LayerCollections_active_collection_index_get(PointerRNA *ptr)
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ return view_layer->active_collection;
+}
+
+static void rna_LayerCollections_active_collection_index_set(PointerRNA *ptr, int value)
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ int num_collections = BKE_layer_collection_count(view_layer);
+ view_layer->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))
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ *min = 0;
+ *max = max_ii(0, BKE_layer_collection_count(view_layer) - 1);
+}
+
+static PointerRNA rna_LayerCollections_active_collection_get(PointerRNA *ptr)
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
+ return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, lc);
+}
+
+static void rna_LayerCollections_active_collection_set(PointerRNA *ptr, PointerRNA value)
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ LayerCollection *lc = (LayerCollection *)value.data;
+ const int index = BKE_layer_collection_findindex(view_layer, lc);
+ if (index != -1) view_layer->active_collection = index;
+}
+
+LayerCollection * rna_ViewLayer_collection_link(
+ ID *id, ViewLayer *view_layer, Main *bmain, SceneCollection *sc)
+{
+ Scene *scene = (Scene *)id;
+ LayerCollection *lc = BKE_collection_link(view_layer, sc);
+
+ DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(id, 0);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, scene);
+
+ return lc;
+}
+
+static void rna_ViewLayer_collection_unlink(
+ ID *id, ViewLayer *view_layer, Main *bmain, ReportList *reports, LayerCollection *lc)
+{
+ Scene *scene = (Scene *)id;
+
+ if (BLI_findindex(&view_layer->layer_collections, lc) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Layer collection '%s' is not in '%s'",
+ lc->scene_collection->name, view_layer->name);
+ return;
+ }
+
+ BKE_collection_unlink(view_layer, lc);
+
+ DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(id, 0);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
+}
+
+static PointerRNA rna_LayerObjects_active_object_get(PointerRNA *ptr)
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_Object, view_layer->basact ? view_layer->basact->object : NULL);
+}
+
+static void rna_LayerObjects_active_object_set(PointerRNA *ptr, PointerRNA value)
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ if (value.data)
+ view_layer->basact = BKE_view_layer_base_find(view_layer, (Object *)value.data);
+ else
+ view_layer->basact = NULL;
+}
+
+static IDProperty *rna_ViewLayer_idprops(PointerRNA *ptr, bool create)
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+
+ if (create && !view_layer->id_properties) {
+ IDPropertyTemplate val = {0};
+ view_layer->id_properties = IDP_New(IDP_GROUP, &val, "ViewLayer ID properties");
+ }
+
+ return view_layer->id_properties;
+}
+
+static void rna_ViewLayer_update_render_passes(ID *id)
+{
+ Scene *scene = (Scene *)id;
+ if (scene->nodetree)
+ ntreeCompositUpdateRLayers(scene->nodetree);
+}
+
+static PointerRNA rna_ViewLayer_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_ViewLayer_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 PointerRNA rna_ViewLayer_depsgraph_get(PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
+ return rna_pointer_inherit_refine(ptr, &RNA_Depsgraph, depsgraph);
+}
+
+static void rna_LayerObjects_selected_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ rna_iterator_listbase_begin(iter, &view_layer->object_bases, rna_ViewLayer_objects_selected_skip);
+}
+
+static void rna_ViewLayer_update_tagged(ViewLayer *UNUSED(view_layer), bContext *C)
+{
+ Depsgraph *graph = CTX_data_depsgraph(C);
+ DEG_OBJECT_ITER(graph, ob, DEG_ITER_OBJECT_FLAG_ALL)
+ {
+ /* Don't do anything, we just need to run the iterator to flush
+ * the base info to the objects. */
+ UNUSED_VARS(ob);
+ }
+ DEG_OBJECT_ITER_END
+}
+
+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);
+}
+
+static char *rna_ViewRenderSettings_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_sprintfN("viewport_render");
+}
+
+static void rna_ViewRenderSettings_engine_set(PointerRNA *ptr, int value)
+{
+ ViewRender *view_render = (ViewRender *)ptr->data;
+ RenderEngineType *type = BLI_findlink(&R_engines, value);
+
+ if (type) {
+ BLI_strncpy_utf8(view_render->engine_id, type->idname, sizeof(view_render->engine_id));
+ DEG_id_tag_update(ptr->id.data, DEG_TAG_COPY_ON_WRITE);
+ }
+}
+
+static const EnumPropertyItem *rna_ViewRenderSettings_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_ViewRenderSettings_engine_get(PointerRNA *ptr)
+{
+ ViewRender *view_render = (ViewRender *)ptr->data;
+ RenderEngineType *type;
+ int a = 0;
+
+ for (type = R_engines.first; type; type = type->next, a++)
+ if (STREQ(type->idname, view_render->engine_id))
+ return a;
+
+ return 0;
+}
+
+static void rna_ViewRenderSettings_engine_update(Main *bmain, Scene *UNUSED(unused), PointerRNA *UNUSED(ptr))
+{
+ ED_render_engine_changed(bmain);
+}
+
+static int rna_ViewRenderSettings_multiple_engines_get(PointerRNA *UNUSED(ptr))
+{
+ return (BLI_listbase_count(&R_engines) > 1);
+}
+
+static int rna_ViewRenderSettings_use_shading_nodes_get(PointerRNA *ptr)
+{
+ ViewRender *view_render = (ViewRender *)ptr->data;
+ return BKE_viewrender_use_new_shading_nodes(view_render);
+}
+
+static int rna_ViewRenderSettings_use_spherical_stereo_get(PointerRNA *ptr)
+{
+ ViewRender *view_render = (ViewRender *)ptr->data;
+ return BKE_viewrender_use_spherical_stereo(view_render);
+}
+
+static int rna_ViewRenderSettings_use_game_engine_get(PointerRNA *ptr)
+{
+ ViewRender *view_render = (ViewRender *)ptr->data;
+ RenderEngineType *type;
+
+ for (type = R_engines.first; type; type = type->next)
+ if (STREQ(type->idname, view_render->engine_id))
+ return (type->flag & RE_GAME) != 0;
+
+ return 0;
+}
+
+#else
+
+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 | FUNC_USE_MAIN);
+ 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_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
+ 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;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ srna = RNA_def_struct(brna, "SceneCollection", NULL);
+ RNA_def_struct_ui_text(srna, "Scene Collection", "Collection");
+ RNA_def_struct_refine_func(srna, "rna_SceneCollection_refine");
+
+ 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, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_collection_type_items);
+ RNA_def_property_ui_text(prop, "Type", "Type of collection");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ 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");
+
+ /* Functions */
+ func = RNA_def_function(srna, "move_above", "rna_SceneCollection_move_above");
+ RNA_def_function_ui_description(func, "Move collection after another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "sc_dst", "SceneCollection", "Collection", "Reference collection above which the collection will move");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "move_below", "rna_SceneCollection_move_below");
+ RNA_def_function_ui_description(func, "Move collection before another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "sc_dst", "SceneCollection", "Collection", "Reference collection below which the collection will move");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "move_into", "rna_SceneCollection_move_into");
+ RNA_def_function_ui_description(func, "Move collection into another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "sc_dst", "SceneCollection", "Collection", "Collection to insert into");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
+ RNA_def_function_return(func, parm);
+}
+
+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);
+}
+
+
+#ifdef WITH_CLAY_ENGINE
+static void rna_def_view_layer_engine_settings_clay(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ViewLayerEngineSettingsClay", "ViewLayerSettings");
+ RNA_def_struct_ui_text(srna, "Clay Scene Layer Settings", "Clay Engine settings");
+
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ /* see RNA_LAYER_ENGINE_GET_SET macro */
+ prop = RNA_def_property(srna, "ssao_samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Clay_ssao_samples_get",
+ "rna_LayerEngineSettings_Clay_ssao_samples_set", NULL);
+ RNA_def_property_ui_text(prop, "Samples", "Number of samples");
+ RNA_def_property_range(prop, 1, 500);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+}
+#endif /* WITH_CLAY_ENGINE */
+
+static void rna_def_view_layer_engine_settings_eevee(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ /* Keep in sync with eevee_private.h */
+ static const EnumPropertyItem eevee_shadow_method_items[] = {
+ {1, "ESM", 0, "ESM", "Exponential Shadow Mapping"},
+ {2, "VSM", 0, "VSM", "Variance Shadow Mapping"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static const EnumPropertyItem eevee_shadow_size_items[] = {
+ {64, "64", 0, "64px", ""},
+ {128, "128", 0, "128px", ""},
+ {256, "256", 0, "256px", ""},
+ {512, "512", 0, "512px", ""},
+ {1024, "1024", 0, "1024px", ""},
+ {2048, "2048", 0, "2048px", ""},
+ {4096, "4096", 0, "4096px", ""},
+ {8192, "8192", 0, "8192px", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static const EnumPropertyItem eevee_gi_visibility_size_items[] = {
+ {8, "8", 0, "8px", ""},
+ {16, "16", 0, "16px", ""},
+ {32, "32", 0, "32px", ""},
+ {64, "64", 0, "64px", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static const EnumPropertyItem eevee_volumetric_tile_size_items[] = {
+ {2, "2", 0, "2px", ""},
+ {4, "4", 0, "4px", ""},
+ {8, "8", 0, "8px", ""},
+ {16, "16", 0, "16px", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "ViewLayerEngineSettingsEevee", "ViewLayerSettings");
+ RNA_def_struct_ui_text(srna, "Eevee Scene Layer Settings", "Eevee Engine settings");
+
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ /* see RNA_LAYER_ENGINE_GET_SET macro */
+
+ /* Indirect Lighting */
+ prop = RNA_def_property(srna, "gi_diffuse_bounces", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_gi_diffuse_bounces_get",
+ "rna_LayerEngineSettings_Eevee_gi_diffuse_bounces_set", NULL);
+ RNA_def_property_ui_text(prop, "Diffuse Bounces", "Number of time the light is reinjected inside light grids, "
+ "0 disable indirect diffuse light");
+ RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "gi_cubemap_resolution", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_Eevee_gi_cubemap_resolution_get",
+ "rna_LayerEngineSettings_Eevee_gi_cubemap_resolution_set", NULL);
+ RNA_def_property_enum_items(prop, eevee_shadow_size_items);
+ RNA_def_property_ui_text(prop, "Cubemap Size", "Size of every cubemaps");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "gi_visibility_resolution", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_Eevee_gi_visibility_resolution_get",
+ "rna_LayerEngineSettings_Eevee_gi_visibility_resolution_set", NULL);
+ RNA_def_property_enum_items(prop, eevee_gi_visibility_size_items);
+ RNA_def_property_ui_text(prop, "Irradiance Visibility Size",
+ "Size of the shadow map applied to each irradiance sample");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ /* Temporal Anti-Aliasing (super sampling) */
+ prop = RNA_def_property(srna, "taa_samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_taa_samples_get",
+ "rna_LayerEngineSettings_Eevee_taa_samples_set", NULL);
+ RNA_def_property_ui_text(prop, "Viewport Samples", "Number of temporal samples, unlimited if 0, "
+ "disabled if 1");
+ RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ /* Screen Space Subsurface Scattering */
+ prop = RNA_def_property(srna, "sss_enable", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_sss_enable_get",
+ "rna_LayerEngineSettings_Eevee_sss_enable_set");
+ RNA_def_property_ui_text(prop, "Subsurface Scattering", "Enable screen space subsurface scattering");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "sss_samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_sss_samples_get",
+ "rna_LayerEngineSettings_Eevee_sss_samples_set", NULL);
+ RNA_def_property_ui_text(prop, "Samples", "Number of samples to compute the scattering effect");
+ RNA_def_property_range(prop, 1, 32);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "sss_jitter_threshold", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_sss_jitter_threshold_get",
+ "rna_LayerEngineSettings_Eevee_sss_jitter_threshold_set", NULL);
+ RNA_def_property_ui_text(prop, "Jitter Threshold", "Rotate samples that are below this threshold");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "sss_separate_albedo", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_sss_separate_albedo_get",
+ "rna_LayerEngineSettings_Eevee_sss_separate_albedo_set");
+ RNA_def_property_ui_text(prop, "Separate Albedo", "Avoid albedo being blured by the subsurface scattering "
+ "but uses more video memory");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ /* Screen Space Reflection */
+ prop = RNA_def_property(srna, "ssr_enable", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_enable_get",
+ "rna_LayerEngineSettings_Eevee_ssr_enable_set");
+ RNA_def_property_ui_text(prop, "Screen Space Reflections", "Enable screen space reflection");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssr_refraction", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_refraction_get",
+ "rna_LayerEngineSettings_Eevee_ssr_refraction_set");
+ RNA_def_property_ui_text(prop, "Screen Space Refractions", "Enable screen space Refractions");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssr_halfres", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_halfres_get",
+ "rna_LayerEngineSettings_Eevee_ssr_halfres_set");
+ RNA_def_property_ui_text(prop, "Half Res Trace", "Raytrace at a lower resolution");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssr_quality", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_quality_get",
+ "rna_LayerEngineSettings_Eevee_ssr_quality_set", NULL);
+ RNA_def_property_ui_text(prop, "Trace Quality", "Quality of the screen space raytracing");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssr_max_roughness", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_max_roughness_get",
+ "rna_LayerEngineSettings_Eevee_ssr_max_roughness_set", NULL);
+ RNA_def_property_ui_text(prop, "Max Roughness", "Do not raytrace reflections for roughness above this value");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssr_ray_count", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_ray_count_get",
+ "rna_LayerEngineSettings_Eevee_ssr_ray_count_set", NULL);
+ RNA_def_property_ui_text(prop, "Samples", "Number of rays to trace per pixels");
+ RNA_def_property_range(prop, 1, 4);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssr_thickness", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_thickness_get",
+ "rna_LayerEngineSettings_Eevee_ssr_thickness_set", NULL);
+ RNA_def_property_ui_text(prop, "Thickness", "Pixel thickness used to detect intersection");
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 5, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssr_border_fade", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_border_fade_get",
+ "rna_LayerEngineSettings_Eevee_ssr_border_fade_set", NULL);
+ RNA_def_property_ui_text(prop, "Edge Fading", "Screen percentage used to fade the SSR");
+ RNA_def_property_range(prop, 0.0f, 0.5f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssr_firefly_fac", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_firefly_fac_get",
+ "rna_LayerEngineSettings_Eevee_ssr_firefly_fac_set", NULL);
+ RNA_def_property_ui_text(prop, "Clamp", "Clamp pixel intensity to remove noise (0 to disabled)");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ /* Volumetrics */
+ prop = RNA_def_property(srna, "volumetric_enable", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_enable_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_enable_set");
+ RNA_def_property_ui_text(prop, "Volumetrics", "Enable scattering and absorbance of volumetric material");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_start", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_start_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_start_set", NULL);
+ RNA_def_property_ui_text(prop, "Start", "Start distance of the volumetric effect");
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_end", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_end_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_end_set", NULL);
+ RNA_def_property_ui_text(prop, "End", "End distance of the volumetric effect");
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_tile_size", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_tile_size_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_tile_size_set", NULL);
+ RNA_def_property_enum_items(prop, eevee_volumetric_tile_size_items);
+ RNA_def_property_ui_text(prop, "Tile Size", "Control the quality of the volumetric effects "
+ "(lower size increase vram usage and quality)");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_samples_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_samples_set", NULL);
+ RNA_def_property_ui_text(prop, "Samples", "Number of samples to compute volumetric effects");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_range(prop, 1, 256);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_sample_distribution", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_sample_distribution_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_sample_distribution_set", NULL);
+ RNA_def_property_ui_text(prop, "Exponential Sampling", "Distribute more samples closer to the camera");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_lights", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_lights_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_lights_set");
+ RNA_def_property_ui_text(prop, "Volumetric Lighting", "Enable scene lamps interactions with volumetrics");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_light_clamp", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_light_clamp_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_light_clamp_set", NULL);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Clamp", "Maximum light contribution, reducing noise");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_shadows", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_shadows_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_shadows_set");
+ RNA_def_property_ui_text(prop, "Volumetric Shadows", "Generate shadows from volumetric material (Very expensive)");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_shadow_samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_shadow_samples_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_shadow_samples_set", NULL);
+ RNA_def_property_range(prop, 1, 128);
+ RNA_def_property_ui_text(prop, "Volumetric Shadow Samples", "Number of samples to compute volumetric shadowing");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "volumetric_colored_transmittance", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_colored_transmittance_get",
+ "rna_LayerEngineSettings_Eevee_volumetric_colored_transmittance_set");
+ RNA_def_property_ui_text(prop, "Colored Transmittance", "Enable wavelength dependent volumetric transmittance");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ /* Ambient Occlusion */
+ prop = RNA_def_property(srna, "gtao_enable", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_gtao_enable_get",
+ "rna_LayerEngineSettings_Eevee_gtao_enable_set");
+ RNA_def_property_ui_text(prop, "Ambient Occlusion", "Enable ambient occlusion to simulate medium scale indirect shadowing");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "gtao_use_bent_normals", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_gtao_use_bent_normals_get",
+ "rna_LayerEngineSettings_Eevee_gtao_use_bent_normals_set");
+ RNA_def_property_ui_text(prop, "Bent Normals", "Compute main non occluded direction to sample the environment");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "gtao_denoise", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_gtao_denoise_get",
+ "rna_LayerEngineSettings_Eevee_gtao_denoise_set");
+ RNA_def_property_ui_text(prop, "Denoise", "Use denoising to filter the resulting occlusion and bent normal but exhibit 2x2 pixel blocks");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "gtao_bounce", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_gtao_bounce_get",
+ "rna_LayerEngineSettings_Eevee_gtao_bounce_set");
+ RNA_def_property_ui_text(prop, "Bounces Approximation", "An approximation to simulate light bounces "
+ "giving less occlusion on brighter objects");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "gtao_factor", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_gtao_factor_get", "rna_LayerEngineSettings_Eevee_gtao_factor_set", NULL);
+ RNA_def_property_ui_text(prop, "Factor", "Factor for ambient occlusion blending");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1f, 2);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "gtao_quality", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_gtao_quality_get", "rna_LayerEngineSettings_Eevee_gtao_quality_set", NULL);
+ RNA_def_property_ui_text(prop, "Trace Quality", "Quality of the horizon search");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "gtao_distance", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_gtao_distance_get", "rna_LayerEngineSettings_Eevee_gtao_distance_set", NULL);
+ RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the ambient occlusion 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, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "gtao_samples", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_gtao_samples_get",
+ "rna_LayerEngineSettings_Eevee_gtao_samples_set", NULL);
+ RNA_def_property_ui_text(prop, "Samples", "Number of samples to take to compute occlusion");
+ RNA_def_property_range(prop, 2, 32);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ /* Depth of Field */
+ prop = RNA_def_property(srna, "dof_enable", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_dof_enable_get",
+ "rna_LayerEngineSettings_Eevee_dof_enable_set");
+ RNA_def_property_ui_text(prop, "Depth of Field", "Enable depth of field using the values from the active camera");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "bokeh_max_size", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_bokeh_max_size_get",
+ "rna_LayerEngineSettings_Eevee_bokeh_max_size_set", NULL);
+ RNA_def_property_ui_text(prop, "Max Size", "Max size of the bokeh shape for the depth of field (lower is faster)");
+ RNA_def_property_range(prop, 0.0f, 2000.0f);
+ RNA_def_property_ui_range(prop, 2.0f, 200.0f, 1, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "bokeh_threshold", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_bokeh_threshold_get",
+ "rna_LayerEngineSettings_Eevee_bokeh_threshold_set", NULL);
+ RNA_def_property_ui_text(prop, "Sprite Threshold", "Brightness threshold for using sprite base depth of field");
+ RNA_def_property_range(prop, 0.0f, 100000.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ /* Bloom */
+ prop = RNA_def_property(srna, "bloom_enable", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_bloom_enable_get",
+ "rna_LayerEngineSettings_Eevee_bloom_enable_set");
+ RNA_def_property_ui_text(prop, "Bloom", "High brighness pixels generate a glowing effect");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "bloom_threshold", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_bloom_threshold_get",
+ "rna_LayerEngineSettings_Eevee_bloom_threshold_set", NULL);
+ RNA_def_property_ui_text(prop, "Threshold", "Filters out pixels under this level of brightness");
+ RNA_def_property_range(prop, 0.0f, 100000.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "bloom_color", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_bloom_color_get",
+ "rna_LayerEngineSettings_Eevee_bloom_color_set", NULL);
+ RNA_def_property_ui_text(prop, "Color", "Color applied to the bloom effect");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "bloom_knee", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_bloom_knee_get",
+ "rna_LayerEngineSettings_Eevee_bloom_knee_set", NULL);
+ RNA_def_property_ui_text(prop, "Knee", "Makes transition between under/over-threshold gradual");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "bloom_radius", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_bloom_radius_get",
+ "rna_LayerEngineSettings_Eevee_bloom_radius_set", NULL);
+ RNA_def_property_ui_text(prop, "Radius", "Bloom spread distance");
+ RNA_def_property_range(prop, 0.0f, 100.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "bloom_clamp", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_bloom_clamp_get",
+ "rna_LayerEngineSettings_Eevee_bloom_clamp_set", NULL);
+ RNA_def_property_ui_text(prop, "Clamp", "Maximum intensity a bloom pixel can have");
+ RNA_def_property_range(prop, 0.0f, 1000.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "bloom_intensity", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_bloom_intensity_get",
+ "rna_LayerEngineSettings_Eevee_bloom_intensity_set", NULL);
+ RNA_def_property_ui_text(prop, "Intensity", "Blend factor");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ /* Motion blur */
+ prop = RNA_def_property(srna, "motion_blur_enable", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_motion_blur_enable_get",
+ "rna_LayerEngineSettings_Eevee_motion_blur_enable_set");
+ RNA_def_property_ui_text(prop, "Motion Blur", "Enable motion blur effect (only in camera view)");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "motion_blur_samples", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_motion_blur_samples_get",
+ "rna_LayerEngineSettings_Eevee_motion_blur_samples_set", NULL);
+ RNA_def_property_ui_text(prop, "Samples", "Number of samples to take with motion blur");
+ RNA_def_property_range(prop, 1, 64);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_motion_blur_shutter_get",
+ "rna_LayerEngineSettings_Eevee_motion_blur_shutter_set", NULL);
+ RNA_def_property_ui_text(prop, "Shutter", "Time taken in frames between shutter open and close");
+ RNA_def_property_ui_range(prop, 0.01f, 2.0f, 1, 2);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ /* Shadows */
+ prop = RNA_def_property(srna, "shadow_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_Eevee_shadow_method_get", "rna_LayerEngineSettings_Eevee_shadow_method_set", NULL);
+ RNA_def_property_enum_items(prop, eevee_shadow_method_items);
+ RNA_def_property_ui_text(prop, "Method", "Technique use to compute the shadows");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "shadow_size", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_Eevee_shadow_size_get", "rna_LayerEngineSettings_Eevee_shadow_size_set", NULL);
+ RNA_def_property_enum_items(prop, eevee_shadow_size_items);
+ RNA_def_property_ui_text(prop, "Size", "Size of every shadow maps");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ prop = RNA_def_property(srna, "shadow_high_bitdepth", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_shadow_high_bitdepth_get", "rna_LayerEngineSettings_Eevee_shadow_high_bitdepth_set");
+ RNA_def_property_ui_text(prop, "High Bitdepth", "Use 32bit shadows");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update");
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+}
+
+#ifdef WITH_CLAY_ENGINE
+static void rna_def_layer_collection_engine_settings_clay(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static const 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, "LayerCollectionEngineSettingsClay", "LayerCollectionSettings");
+ RNA_def_struct_ui_text(srna, "Collections Clay Engine Settings", "Engine specific settings for this collection");
+
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ /* see RNA_LAYER_ENGINE_GET_SET macro */
+ prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_Clay_matcap_icon_get", "rna_LayerEngineSettings_Clay_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, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_matcap_rotation_get", "rna_LayerEngineSettings_Clay_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, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_matcap_hue_get", "rna_LayerEngineSettings_Clay_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, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_matcap_saturation_get", "rna_LayerEngineSettings_Clay_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, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_matcap_value_get", "rna_LayerEngineSettings_Clay_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, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_ssao_factor_cavity_get", "rna_LayerEngineSettings_Clay_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, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_ssao_factor_edge_get", "rna_LayerEngineSettings_Clay_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, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_ssao_distance_get", "rna_LayerEngineSettings_Clay_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, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_ssao_attenuation_get", "rna_LayerEngineSettings_Clay_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, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "hair_brightness_randomness", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_hair_brightness_randomness_get", "rna_LayerEngineSettings_Clay_hair_brightness_randomness_set", NULL);
+ RNA_def_property_ui_text(prop, "Hair Brightness Randomness", "Brightness randomness for hair");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+}
+#endif /* WITH_CLAY_ENGINE */
+
+static void rna_def_layer_collection_mode_settings_object(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "LayerCollectionModeSettingsObject", "LayerCollectionSettings");
+ RNA_def_struct_ui_text(srna, "Collections Object Mode Settings", "Object Mode specific settings for this collection");
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ /* see RNA_LAYER_ENGINE_GET_SET macro */
+
+ prop = RNA_def_property(srna, "show_wire", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Wire", "Add the object's wireframe over solid drawing");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_ObjectMode_show_wire_get", "rna_LayerEngineSettings_ObjectMode_show_wire_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "show_backface_culling", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Backface Culling", "");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_ObjectMode_show_backface_culling_get", "rna_LayerEngineSettings_ObjectMode_show_backface_culling_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+}
+
+static void rna_def_layer_collection_mode_settings_edit(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "LayerCollectionModeSettingsEdit", "LayerCollectionSettings");
+ RNA_def_struct_ui_text(srna, "Collections Edit Mode Settings", "Edit Mode specific settings to be overridden per collection");
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ /* see RNA_LAYER_ENGINE_GET_SET macro */
+
+ prop = RNA_def_property(srna, "show_occlude_wire", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Hidden Wire", "Use hidden wireframe display");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_show_occlude_wire_get", "rna_LayerEngineSettings_EditMode_show_occlude_wire_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "show_weight", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Show Weights", "Draw weights in editmode");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_show_weight_get", "rna_LayerEngineSettings_EditMode_show_weight_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "face_normals_show", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Draw Normals", "Display face normals as lines");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_face_normals_show_get", "rna_LayerEngineSettings_EditMode_face_normals_show_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "vert_normals_show", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Draw Vertex Normals", "Display vertex normals as lines");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_vert_normals_show_get", "rna_LayerEngineSettings_EditMode_vert_normals_show_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "loop_normals_show", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Draw Split Normals", "Display vertex-per-face normals as lines");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_loop_normals_show_get", "rna_LayerEngineSettings_EditMode_loop_normals_show_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "normals_length", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_ui_text(prop, "Normal Size", "Display size for normals in the 3D view");
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_EditMode_normals_length_get", "rna_LayerEngineSettings_EditMode_normals_length_set", NULL);
+ RNA_def_property_range(prop, 0.00001, 1000.0);
+ RNA_def_property_ui_range(prop, 0.01, 10.0, 10.0, 2);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "backwire_opacity", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_ui_text(prop, "Backwire Opacity", "Opacity when rendering transparent wires");
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_EditMode_backwire_opacity_get", "rna_LayerEngineSettings_EditMode_backwire_opacity_set", NULL);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+}
+
+static void rna_def_layer_collection_mode_settings_paint_weight(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "LayerCollectionModeSettingsPaintWeight", "LayerCollectionSettings");
+ RNA_def_struct_ui_text(srna, "Collections Weight Paint Mode Settings", "Weight Paint Mode specific settings to be overridden per collection");
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ /* see RNA_LAYER_ENGINE_GET_SET macro */
+
+ prop = RNA_def_property(srna, "use_shading", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Use Shading", "Whether to use shaded or shadeless drawing");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_PaintWeightMode_use_shading_get", "rna_LayerEngineSettings_PaintWeightMode_use_shading_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "use_wire", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Show Wire", "Whether to overlay wireframe onto the mesh");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_PaintWeightMode_use_wire_get", "rna_LayerEngineSettings_PaintWeightMode_use_wire_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_wire_update");
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+}
+
+static void rna_def_layer_collection_mode_settings_paint_vertex(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "LayerCollectionModeSettingsPaintVertex", "LayerCollectionSettings");
+ RNA_def_struct_ui_text(srna, "Collections Vertex Paint Mode Settings", "Vertex Paint Mode specific settings to be overridden per collection");
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ /* see RNA_LAYER_ENGINE_GET_SET macro */
+
+ prop = RNA_def_property(srna, "use_shading", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Use Shading", "Whether to use shaded or shadeless drawing");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_PaintVertexMode_use_shading_get", "rna_LayerEngineSettings_PaintVertexMode_use_shading_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "use_wire", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Show Wire", "Whether to overlay wireframe onto the mesh");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_PaintVertexMode_use_wire_get", "rna_LayerEngineSettings_PaintVertexMode_use_wire_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_wire_update");
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+}
+
+static void rna_def_view_layer_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ srna = RNA_def_struct(brna, "ViewLayerSettings", NULL);
+ RNA_def_struct_sdna(srna, "IDProperty");
+ RNA_def_struct_ui_text(srna, "Scene Layer Settings",
+ "Engine specific settings that can be overriden by ViewLayer");
+ RNA_def_struct_refine_func(srna, "rna_ViewLayerSettings_refine");
+
+ RNA_define_verify_sdna(0);
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, "rna_ViewLayerSettings_name_get", "rna_ViewLayerSettings_name_length", NULL);
+ RNA_def_property_ui_text(prop, "Name", "Engine Name");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_struct_name_property(srna, prop);
+
+ func = RNA_def_function(srna, "use", "rna_ViewLayerSettings_use");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Initialize this property to use");
+ parm = RNA_def_string(func, "identifier", NULL, 0, "Property Name", "Name of the property to set");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "unuse", "rna_ViewLayerSettings_unuse");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Remove the property");
+ parm = RNA_def_string(func, "identifier", NULL, 0, "Property Name", "Name of the property to unset");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+#ifdef WITH_CLAY_ENGINE
+ rna_def_view_layer_engine_settings_clay(brna);
+#endif
+ rna_def_view_layer_engine_settings_eevee(brna);
+
+#if 0
+ rna_def_view_layer_mode_settings_object(brna);
+ rna_def_view_layer_mode_settings_edit(brna);
+ rna_def_view_layer_mode_settings_paint_weight(brna);
+ rna_def_view_layer_mode_settings_paint_vertex(brna);
+#endif
+
+ RNA_define_verify_sdna(1);
+}
+
+static void rna_def_layer_collection_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ srna = RNA_def_struct(brna, "LayerCollectionSettings", NULL);
+ RNA_def_struct_sdna(srna, "IDProperty");
+ RNA_def_struct_ui_text(srna, "Layer Collection Settings",
+ "Engine specific settings that can be overriden by LayerCollection");
+ RNA_def_struct_refine_func(srna, "rna_LayerCollectionSettings_refine");
+
+ RNA_define_verify_sdna(0);
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, "rna_LayerCollectionSettings_name_get", "rna_LayerCollectionSettings_name_length", NULL);
+ RNA_def_property_ui_text(prop, "Name", "Engine Name");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_struct_name_property(srna, prop);
+
+ func = RNA_def_function(srna, "use", "rna_LayerCollectionSettings_use");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Initialize this property to use");
+ parm = RNA_def_string(func, "identifier", NULL, 0, "Property Name", "Name of the property to set");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "unuse", "rna_LayerCollectionSettings_unuse");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Remove the property");
+ parm = RNA_def_string(func, "identifier", NULL, 0, "Property Name", "Name of the property to unset");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+#ifdef WITH_CLAY_ENGINE
+ rna_def_layer_collection_engine_settings_clay(brna);
+#endif
+
+ rna_def_layer_collection_mode_settings_object(brna);
+ rna_def_layer_collection_mode_settings_edit(brna);
+ rna_def_layer_collection_mode_settings_paint_weight(brna);
+ rna_def_layer_collection_mode_settings_paint_vertex(brna);
+
+ RNA_define_verify_sdna(1);
+}
+
+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", "");
+
+ /* Override settings */
+ prop = RNA_def_property(srna, "engine_overrides", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "properties->data.group", NULL);
+ RNA_def_property_struct_type(prop, "LayerCollectionSettings");
+ RNA_def_property_ui_text(prop, "Collection Settings", "Override of engine specific render settings");
+
+ /* Functions */
+ func = RNA_def_function(srna, "move_above", "rna_LayerCollection_move_above");
+ RNA_def_function_ui_description(func, "Move collection after another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "lc_dst", "LayerCollection", "Collection", "Reference collection above which the collection will move");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "move_below", "rna_LayerCollection_move_below");
+ RNA_def_function_ui_description(func, "Move collection before another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "lc_dst", "LayerCollection", "Collection", "Reference collection below which the collection will move");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "move_into", "rna_LayerCollection_move_into");
+ RNA_def_function_ui_description(func, "Move collection into another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "lc_dst", "LayerCollection", "Collection", "Collection to insert into");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "enable_set", "rna_LayerCollection_enable_set");
+ RNA_def_function_ui_description(func, "Enable or disable a collection");
+ parm = RNA_def_boolean(func, "value", 1, "Enable", "");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+
+ func = RNA_def_function(srna, "create_group", "rna_LayerCollection_create_group");
+ RNA_def_function_ui_description(func, "Enable or disable a collection");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "result", "Group", "", "Newly created Group");
+ RNA_def_function_return(func, parm);
+
+ /* Flags */
+ prop = RNA_def_property(srna, "is_enabled", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_DISABLED);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Enabled", "Enable or disable collection from depsgraph");
+
+ 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_flag_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_flag_update");
+
+ /* 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, "ViewLayer");
+ 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_ViewLayer_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_ViewLayer_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, "ViewLayer");
+ 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_object_base_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_ViewLayer_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_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");
+}
+
+static void rna_def_scene_view_render(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static const 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, "ViewRenderSettings", NULL);
+ RNA_def_struct_sdna(srna, "ViewRender");
+ RNA_def_struct_path_func(srna, "rna_ViewRenderSettings_path");
+ RNA_def_struct_ui_text(srna, "View Render", "Rendering settings related to viewport drawing/rendering");
+
+ /* 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_ViewRenderSettings_engine_get", "rna_ViewRenderSettings_engine_set",
+ "rna_ViewRenderSettings_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_ViewRenderSettings_engine_update");
+
+ prop = RNA_def_property(srna, "has_multiple_engines", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_ViewRenderSettings_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");
+
+ prop = RNA_def_property(srna, "use_shading_nodes", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_ViewRenderSettings_use_shading_nodes_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Use Shading Nodes", "Active render engine uses new shading nodes system");
+
+ prop = RNA_def_property(srna, "use_spherical_stereo", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_ViewRenderSettings_use_spherical_stereo_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Use Spherical Stereo", "Active render engine supports spherical stereo rendering");
+
+ prop = RNA_def_property(srna, "use_game_engine", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_ViewRenderSettings_use_game_engine_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Use Game Engine", "Current rendering engine is a game engine");
+}
+
+void RNA_def_view_layer(BlenderRNA *brna)
+{
+ FunctionRNA *func;
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ViewLayer", NULL);
+ RNA_def_struct_ui_text(srna, "Render Layer", "Render layer");
+ RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
+ RNA_def_struct_idprops_func(srna, "rna_ViewLayer_idprops");
+
+ rna_def_view_layer_common(srna, 1);
+
+ func = RNA_def_function(srna, "update_render_passes", "rna_ViewLayer_update_render_passes");
+ RNA_def_function_ui_description(func, "Requery the enabled render passes from the render engine");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF);
+
+ 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_ViewLayer_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", VIEW_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);
+
+ prop = RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", VIEW_LAYER_FREESTYLE);
+ RNA_def_property_ui_text(prop, "Freestyle", "Render stylized strokes in this Layer");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL);
+
+ /* Freestyle */
+ rna_def_freestyle_settings(brna);
+
+ prop = RNA_def_property(srna, "freestyle_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "freestyle_config");
+ RNA_def_property_struct_type(prop, "FreestyleSettings");
+ RNA_def_property_ui_text(prop, "Freestyle Settings", "");
+
+ /* Override settings */
+ prop = RNA_def_property(srna, "engine_overrides", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "properties->data.group", NULL);
+ RNA_def_property_struct_type(prop, "ViewLayerSettings");
+ RNA_def_property_ui_text(prop, "Layer Settings", "Override of engine specific render settings");
+
+ /* debug update routine */
+ func = RNA_def_function(srna, "update", "rna_ViewLayer_update_tagged");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(func,
+ "Update data tagged to be updated from previous access to data or operators");
+
+ /* Dependency Graph */
+ prop = RNA_def_property(srna, "depsgraph", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Depsgraph");
+ RNA_def_property_ui_text(prop, "Dependency Graph", "Dependencies in the scene data");
+ RNA_def_property_pointer_funcs(prop, "rna_ViewLayer_depsgraph_get", NULL, NULL, NULL);
+
+ /* Nested Data */
+ /* *** Non-Animated *** */
+ RNA_define_animate_sdna(false);
+ rna_def_scene_collection(brna);
+ rna_def_layer_collection(brna);
+ rna_def_layer_collection_override(brna);
+ rna_def_object_base(brna);
+ RNA_define_animate_sdna(true);
+ /* *** Animated *** */
+ rna_def_view_layer_settings(brna);
+ rna_def_layer_collection_settings(brna);
+ rna_def_scene_view_render(brna);
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_lightprobe.c b/source/blender/makesrna/intern/rna_lightprobe.c
new file mode 100644
index 00000000000..61dc835022b
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_lightprobe.c
@@ -0,0 +1,204 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/makesrna/intern/rna_lightprobe.c
+ * \ingroup RNA
+ */
+
+#include <stdlib.h>
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#include "DNA_lightprobe_types.h"
+
+#include "WM_types.h"
+
+#ifdef RNA_RUNTIME
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_main.h"
+#include "DEG_depsgraph.h"
+
+#include "DNA_object_types.h"
+
+#include "WM_api.h"
+
+static void rna_LightProbe_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+}
+
+#else
+
+static EnumPropertyItem parallax_type_items[] = {
+ {LIGHTPROBE_SHAPE_ELIPSOID, "ELIPSOID", ICON_NONE, "Sphere", ""},
+ {LIGHTPROBE_SHAPE_BOX, "BOX", ICON_NONE, "Box", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static EnumPropertyItem lightprobe_type_items[] = {
+ {LIGHTPROBE_TYPE_CUBE, "CUBEMAP", ICON_NONE, "Reflection Cubemap", "Capture reflections"},
+ {LIGHTPROBE_TYPE_PLANAR, "PLANAR", ICON_NONE, "Reflection Plane", ""},
+ {LIGHTPROBE_TYPE_GRID, "GRID", ICON_NONE, "Irradiance Volume", "Volume used for precomputing indirect lighting"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static void rna_def_lightprobe(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "LightProbe", "ID");
+ RNA_def_struct_ui_text(srna, "LightProbe", "Light Probe data-block for lighting capture objects");
+ RNA_def_struct_ui_icon(srna, ICON_RADIO);
+
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, lightprobe_type_items);
+ RNA_def_property_ui_text(prop, "Type", "Type of light probe");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "clipsta");
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
+ RNA_def_property_ui_text(prop, "Clip Start",
+ "Probe clip start, below which objects will not appear in reflections");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
+
+ prop = RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "clipend");
+ RNA_def_property_range(prop, 1e-6f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
+ RNA_def_property_ui_text(prop, "Clip End",
+ "Probe clip end, beyond which objects will not appear in reflections");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
+
+ prop = RNA_def_property(srna, "show_clip", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_SHOW_CLIP_DIST);
+ RNA_def_property_ui_text(prop, "Clipping", "Show the clipping distances in the 3D view");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ prop = RNA_def_property(srna, "influence_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "attenuation_type");
+ RNA_def_property_enum_items(prop, parallax_type_items);
+ RNA_def_property_ui_text(prop, "Type", "Type of parallax volume");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ prop = RNA_def_property(srna, "show_influence", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_SHOW_INFLUENCE);
+ RNA_def_property_ui_text(prop, "Influence", "Show the influence volume in the 3D view");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ prop = RNA_def_property(srna, "influence_distance", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "distinf");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Influence Distance", "Influence distance of the probe");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Falloff", "Control how fast the probe influence decreases");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ prop = RNA_def_property(srna, "use_custom_parallax", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_CUSTOM_PARALLAX);
+ RNA_def_property_ui_text(prop, "Use Custom Parallax", "Enable custom settings for the parallax correction volume");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ prop = RNA_def_property(srna, "show_parallax", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_SHOW_PARALLAX);
+ RNA_def_property_ui_text(prop, "Parallax", "Show the parallax correction volume in the 3D view");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ prop = RNA_def_property(srna, "parallax_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, parallax_type_items);
+ RNA_def_property_ui_text(prop, "Type", "Type of parallax volume");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ prop = RNA_def_property(srna, "parallax_distance", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "distpar");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Parallax Radius", "Lowest corner of the parallax bounding box");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ /* irradiance grid */
+ prop = RNA_def_property(srna, "grid_resolution_x", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, 256);
+ RNA_def_property_ui_text(prop, "Resolution X", "Number of sample along the x axis of the volume");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
+
+ prop = RNA_def_property(srna, "grid_resolution_y", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, 256);
+ RNA_def_property_ui_text(prop, "Resolution Y", "Number of sample along the y axis of the volume");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
+
+ prop = RNA_def_property(srna, "grid_resolution_z", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, 256);
+ RNA_def_property_ui_text(prop, "Resolution Z", "Number of sample along the z axis of the volume");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
+
+ prop = RNA_def_property(srna, "visibility_buffer_bias", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "vis_bias");
+ RNA_def_property_range(prop, 0.001f, 9999.0f);
+ RNA_def_property_ui_range(prop, 0.001f, 5.0f, 1.0, 3);
+ RNA_def_property_ui_text(prop, "Visibility Bias", "Bias for reducing self shadowing");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ prop = RNA_def_property(srna, "visibility_bleed_bias", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "vis_bleedbias");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Visibility Bleed Bias", "Bias for reducing light-bleed on variance shadow maps");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ prop = RNA_def_property(srna, "visibility_blur", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "vis_blur");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Visibility Blur", "Filter size of the visibilty blur");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
+
+ /* Data preview */
+ prop = RNA_def_property(srna, "show_data", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_SHOW_DATA);
+ RNA_def_property_ui_text(prop, "Show Data", "Show captured lighting data into the 3D view for debuging purpose");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ prop = RNA_def_property(srna, "data_draw_size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.05f, 10.0f);
+ RNA_def_property_ui_text(prop, "Data Draw Size", "Size of the spheres to debug captured light");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL);
+
+ /* common */
+ rna_def_animdata_common(srna);
+}
+
+
+void RNA_def_lightprobe(BlenderRNA *brna)
+{
+ rna_def_lightprobe(brna);
+}
+
+#endif
+
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index bcd8ab054ae..e138d0d98d8 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -101,7 +101,8 @@ const EnumPropertyItem rna_enum_linestyle_geometry_modifier_type_items[] = {
#include "BKE_linestyle.h"
#include "BKE_texture.h"
-#include "BKE_depsgraph.h"
+
+#include "DEG_depsgraph.h"
#include "ED_node.h"
@@ -323,7 +324,7 @@ static void rna_LineStyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin
{
FreestyleLineStyle *linestyle = ptr->id.data;
- DAG_id_tag_update(&linestyle->id, 0);
+ DEG_id_tag_update(&linestyle->id, 0);
WM_main_add_notifier(NC_LINESTYLE, linestyle);
}
@@ -347,7 +348,7 @@ static LineStyleModifier *rna_LineStyle_color_modifier_add(FreestyleLineStyle *l
return NULL;
}
- DAG_id_tag_update(&linestyle->id, 0);
+ DEG_id_tag_update(&linestyle->id, 0);
WM_main_add_notifier(NC_LINESTYLE, linestyle);
return modifier;
@@ -365,7 +366,7 @@ static void rna_LineStyle_color_modifier_remove(FreestyleLineStyle *linestyle, R
RNA_POINTER_INVALIDATE(modifier_ptr);
- DAG_id_tag_update(&linestyle->id, 0);
+ DEG_id_tag_update(&linestyle->id, 0);
WM_main_add_notifier(NC_LINESTYLE, linestyle);
}
@@ -379,7 +380,7 @@ static LineStyleModifier *rna_LineStyle_alpha_modifier_add(FreestyleLineStyle *l
return NULL;
}
- DAG_id_tag_update(&linestyle->id, 0);
+ DEG_id_tag_update(&linestyle->id, 0);
WM_main_add_notifier(NC_LINESTYLE, linestyle);
return modifier;
@@ -397,7 +398,7 @@ static void rna_LineStyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, R
RNA_POINTER_INVALIDATE(modifier_ptr);
- DAG_id_tag_update(&linestyle->id, 0);
+ DEG_id_tag_update(&linestyle->id, 0);
WM_main_add_notifier(NC_LINESTYLE, linestyle);
}
@@ -411,7 +412,7 @@ static LineStyleModifier *rna_LineStyle_thickness_modifier_add(FreestyleLineStyl
return NULL;
}
- DAG_id_tag_update(&linestyle->id, 0);
+ DEG_id_tag_update(&linestyle->id, 0);
WM_main_add_notifier(NC_LINESTYLE, linestyle);
return modifier;
@@ -429,7 +430,7 @@ static void rna_LineStyle_thickness_modifier_remove(FreestyleLineStyle *linestyl
RNA_POINTER_INVALIDATE(modifier_ptr);
- DAG_id_tag_update(&linestyle->id, 0);
+ DEG_id_tag_update(&linestyle->id, 0);
WM_main_add_notifier(NC_LINESTYLE, linestyle);
}
@@ -443,7 +444,7 @@ static LineStyleModifier *rna_LineStyle_geometry_modifier_add(FreestyleLineStyle
return NULL;
}
- DAG_id_tag_update(&linestyle->id, 0);
+ DEG_id_tag_update(&linestyle->id, 0);
WM_main_add_notifier(NC_LINESTYLE, linestyle);
return modifier;
@@ -461,7 +462,7 @@ static void rna_LineStyle_geometry_modifier_remove(FreestyleLineStyle *linestyle
RNA_POINTER_INVALIDATE(modifier_ptr);
- DAG_id_tag_update(&linestyle->id, 0);
+ DEG_id_tag_update(&linestyle->id, 0);
WM_main_add_notifier(NC_LINESTYLE, linestyle);
}
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index 94687b6fd46..6479826b7b3 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -293,6 +293,18 @@ static void rna_Main_paintcurves_begin(CollectionPropertyIterator *iter, Pointer
rna_iterator_listbase_begin(iter, &bmain->paintcurves, NULL);
}
+static void rna_Main_workspaces_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Main *bmain = (Main *)ptr->data;
+ rna_iterator_listbase_begin(iter, &bmain->workspaces, NULL);
+}
+
+static void rna_Main_lightprobes_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Main *bmain = (Main *)ptr->data;
+ rna_iterator_listbase_begin(iter, &bmain->lightprobe, NULL);
+}
+
static void rna_Main_version_get(PointerRNA *ptr, int *value)
{
Main *bmain = (Main *)ptr->data;
@@ -368,6 +380,8 @@ void RNA_def_main(BlenderRNA *brna)
{"linestyles", "FreestyleLineStyle", "rna_Main_linestyle_begin", "Line Styles", "Line Style data-blocks", RNA_def_main_linestyles},
{"cache_files", "CacheFile", "rna_Main_cachefiles_begin", "Cache Files", "Cache Files data-blocks", RNA_def_main_cachefiles},
{"paint_curves", "PaintCurve", "rna_Main_paintcurves_begin", "Paint Curves", "Paint Curves data-blocks", RNA_def_main_paintcurves},
+ {"workspaces", "WorkSpace", "rna_Main_workspaces_begin", "Workspaces", "Workspace data-blocks", RNA_def_main_workspaces},
+ {"lightprobes", "LightProbe", "rna_Main_lightprobes_begin", "LightProbes", "LightProbe data-blocks", RNA_def_main_lightprobes},
{NULL, NULL, NULL, NULL, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 7e2ced81a6d..f15006fa0ed 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -78,12 +78,16 @@
#include "BKE_paint.h"
#include "BKE_font.h"
#include "BKE_node.h"
-#include "BKE_depsgraph.h"
#include "BKE_speaker.h"
+#include "BKE_lightprobe.h"
#include "BKE_movieclip.h"
#include "BKE_mask.h"
#include "BKE_gpencil.h"
#include "BKE_linestyle.h"
+#include "BKE_workspace.h"
+
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
@@ -93,6 +97,7 @@
#include "DNA_mesh_types.h"
#include "DNA_speaker_types.h"
#include "DNA_sound_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_text_types.h"
#include "DNA_texture_types.h"
#include "DNA_group_types.h"
@@ -115,6 +120,8 @@
# include "BPY_extern.h"
#endif
+#include "WM_api.h"
+
static void rna_idname_validate(const char *name, char *r_name)
{
@@ -170,14 +177,15 @@ static void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports
(scene_new = scene->id.next))
{
if (do_unlink) {
- bScreen *sc = CTX_wm_screen(C);
- if (sc->scene == scene) {
+ wmWindow *win = CTX_wm_window(C);
+
+ if (WM_window_get_active_scene(win) == scene) {
#ifdef WITH_PYTHON
BPy_BEGIN_ALLOW_THREADS;
#endif
- ED_screen_set_scene(C, sc, scene_new);
+ WM_window_change_active_scene(bmain, C, win, scene_new);
#ifdef WITH_PYTHON
BPy_END_ALLOW_THREADS;
@@ -241,7 +249,6 @@ static Object *rna_Main_objects_new(Main *bmain, ReportList *reports, const char
}
ob = BKE_object_add_only_object(bmain, type, safe_name);
- id_us_min(&ob->id);
ob->data = data;
test_object_materials(ob, ob->data);
@@ -293,9 +300,26 @@ static Mesh *rna_Main_meshes_new(Main *bmain, const char *name)
/* copied from Mesh_getFromObject and adapted to RNA interface */
/* settings: 1 - preview, 2 - render */
Mesh *rna_Main_meshes_new_from_object(
- Main *bmain, ReportList *reports, Scene *sce,
+ Main *bmain, ReportList *reports, Scene *sce, ViewLayer *view_layer,
Object *ob, int apply_modifiers, int settings, int calc_tessface, int calc_undeformed)
{
+ EvaluationContext eval_ctx;
+
+ /* XXX: This should never happen, but render pipeline is not ready to give
+ * proper view_layer, and will always pass NULL here. For until we port
+ * pipeline form SceneRenderLayer to ViewLayer we have this stub to prevent
+ * some obvious crashes.
+ * - sergey -
+ */
+ if (view_layer == NULL) {
+ view_layer = sce->view_layers.first;
+ }
+
+ DEG_evaluation_context_init(&eval_ctx, settings);
+ eval_ctx.ctime = (float)sce->r.cfra + sce->r.subframe;
+ eval_ctx.view_layer = view_layer;
+ eval_ctx.depsgraph = BKE_scene_get_depsgraph(sce, view_layer, false);
+
switch (ob->type) {
case OB_FONT:
case OB_CURVE:
@@ -308,7 +332,7 @@ Mesh *rna_Main_meshes_new_from_object(
return NULL;
}
- return BKE_mesh_new_from_object(bmain, sce, ob, apply_modifiers, settings, calc_tessface, calc_undeformed);
+ return BKE_mesh_new_from_object(&eval_ctx, bmain, sce, ob, apply_modifiers, settings, calc_tessface, calc_undeformed);
}
static Lamp *rna_Main_lamps_new(Main *bmain, const char *name, int type)
@@ -544,7 +568,7 @@ static MovieClip *rna_Main_movieclip_load(Main *bmain, ReportList *reports, cons
}
if (clip != NULL) {
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
else {
BKE_reportf(reports, RPT_ERROR, "Cannot read '%s': %s", filepath,
@@ -573,13 +597,23 @@ static FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char *name
return linestyle;
}
+static LightProbe *rna_Main_lightprobe_new(Main *bmain, const char *name)
+{
+ char safe_name[MAX_ID_NAME - 2];
+ rna_idname_validate(name, safe_name);
+
+ LightProbe *probe = BKE_lightprobe_add(bmain, safe_name);
+ id_us_min(&probe->id);
+ return probe;
+}
+
/* tag and is_updated functions, all the same */
#define RNA_MAIN_ID_TAG_FUNCS_DEF(_func_name, _listbase_name, _id_type) \
static void rna_Main_##_func_name##_tag(Main *bmain, int value) { \
BKE_main_id_tag_listbase(&bmain->_listbase_name, LIB_TAG_DOIT, value); \
} \
static int rna_Main_##_func_name##_is_updated_get(PointerRNA *ptr) { \
- return DAG_id_type_tagged(ptr->data, _id_type) != 0; \
+ return DEG_id_type_tagged(ptr->data, _id_type) != 0; \
}
RNA_MAIN_ID_TAG_FUNCS_DEF(cameras, camera, ID_CA)
@@ -615,6 +649,8 @@ RNA_MAIN_ID_TAG_FUNCS_DEF(masks, mask, ID_MSK)
RNA_MAIN_ID_TAG_FUNCS_DEF(linestyle, linestyle, ID_LS)
RNA_MAIN_ID_TAG_FUNCS_DEF(cachefiles, cachefiles, ID_CF)
RNA_MAIN_ID_TAG_FUNCS_DEF(paintcurves, paintcurves, ID_PC)
+RNA_MAIN_ID_TAG_FUNCS_DEF(workspaces, workspaces, ID_WS)
+RNA_MAIN_ID_TAG_FUNCS_DEF(lightprobes, lightprobe, ID_LP)
#undef RNA_MAIN_ID_TAG_FUNCS_DEF
@@ -881,6 +917,8 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate modifiers");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "", "Scene layer within which to evaluate modifiers");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_pointer(func, "object", "Object", "", "Object to create mesh from");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
@@ -1676,6 +1714,7 @@ void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_Main_particles_is_updated_get", NULL);
}
+
void RNA_def_main_palettes(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
@@ -1927,4 +1966,68 @@ void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_boolean_funcs(prop, "rna_Main_linestyle_is_updated_get", NULL);
}
+void RNA_def_main_workspaces(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+ PropertyRNA *prop;
+
+ RNA_def_property_srna(cprop, "BlendDataWorkSpaces");
+ srna = RNA_def_struct(brna, "BlendDataWorkSpaces", NULL);
+ RNA_def_struct_sdna(srna, "Main");
+ RNA_def_struct_ui_text(srna, "Main Workspaces", "Collection of workspaces");
+
+ func = RNA_def_function(srna, "tag", "rna_Main_workspaces_tag");
+ parm = RNA_def_boolean(func, "value", 0, "Value", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_boolean_funcs(prop, "rna_Main_workspaces_is_updated_get", NULL);
+}
+
+void RNA_def_main_lightprobes(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+ PropertyRNA *prop;
+
+ RNA_def_property_srna(cprop, "BlendDataProbes");
+ srna = RNA_def_struct(brna, "BlendDataProbes", NULL);
+ RNA_def_struct_sdna(srna, "Main");
+ RNA_def_struct_ui_text(srna, "Main Light Probes", "Collection of light probes");
+
+ func = RNA_def_function(srna, "new", "rna_Main_lightprobe_new");
+ RNA_def_function_ui_description(func, "Add a new probe to the main database");
+ parm = RNA_def_string(func, "name", "Probe", 0, "", "New name for the data-block");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* return type */
+ parm = RNA_def_pointer(func, "lightprobe", "LightProbe", "", "New light probe data-block");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Remove a probe from the current blendfile");
+ parm = RNA_def_pointer(func, "lightprobe", "LightProbe", "", "Probe to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+ RNA_def_boolean(func, "do_unlink", true, "",
+ "Unlink all usages of this probe before deleting it "
+ "(WARNING: will also delete objects instancing that light probe data)");
+ RNA_def_boolean(func, "do_id_user", true, "",
+ "Decrement user counter of all datablocks used by this light probe");
+ RNA_def_boolean(func, "do_ui_user", true, "",
+ "Make sure interface does not reference this light probe");
+
+ func = RNA_def_function(srna, "tag", "rna_Main_lightprobes_tag");
+ parm = RNA_def_boolean(func, "value", 0, "Value", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_boolean_funcs(prop, "rna_Main_lightprobes_is_updated_get", NULL);
+}
+
#endif
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index c266e0e7f31..564232c3dd4 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -56,9 +56,10 @@
#include "DNA_movieclip_types.h"
-#include "BKE_depsgraph.h"
#include "BKE_mask.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "WM_api.h"
@@ -68,7 +69,7 @@ static void rna_Mask_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin
Mask *mask = ptr->id.data;
WM_main_add_notifier(NC_MASK | ND_DATA, mask);
- DAG_id_tag_update( &mask->id, 0);
+ DEG_id_tag_update( &mask->id, 0);
}
static void rna_Mask_update_parent(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -448,7 +449,7 @@ static void rna_MaskLayer_spline_remove(ID *id, MaskLayer *mask_layer, ReportLis
RNA_POINTER_INVALIDATE(spline_ptr);
- DAG_id_tag_update(&mask->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&mask->id, OB_RECALC_DATA);
}
static void rna_Mask_start_frame_set(PointerRNA *ptr, int value)
@@ -522,7 +523,7 @@ static void rna_MaskSpline_points_add(ID *id, MaskSpline *spline, int count)
}
WM_main_add_notifier(NC_MASK | ND_DATA, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
}
static void rna_MaskSpline_point_remove(ID *id, MaskSpline *spline, ReportList *reports, PointerRNA *point_ptr)
@@ -582,7 +583,7 @@ static void rna_MaskSpline_point_remove(ID *id, MaskSpline *spline, ReportList *
BKE_mask_layer_shape_changed_remove(layer, BKE_mask_layer_shape_spline_to_index(layer, spline) + point_index, 1);
WM_main_add_notifier(NC_MASK | ND_DATA, mask);
- DAG_id_tag_update(&mask->id, 0);
+ DEG_id_tag_update(&mask->id, 0);
RNA_POINTER_INVALIDATE(point_ptr);
}
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 1965361b81b..440af0d0e8e 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -87,13 +87,15 @@ const EnumPropertyItem rna_enum_ramp_blend_items[] = {
#include "BKE_colorband.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_texture.h"
#include "BKE_node.h"
#include "BKE_paint.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_node.h"
#include "ED_image.h"
#include "BKE_scene.h"
@@ -102,7 +104,7 @@ static void rna_Material_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point
{
Material *ma = ptr->id.data;
- DAG_id_tag_update(&ma->id, 0);
+ DEG_id_tag_update(&ma->id, 0);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma);
}
@@ -120,7 +122,7 @@ static void rna_Material_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
{
Material *ma = ptr->id.data;
- DAG_id_tag_update(&ma->id, 0);
+ DEG_id_tag_update(&ma->id, 0);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma);
}
@@ -214,7 +216,7 @@ static void rna_Material_active_paint_texture_index_update(Main *bmain, Scene *s
}
}
- DAG_id_tag_update(&ma->id, 0);
+ DEG_id_tag_update(&ma->id, 0);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma);
}
@@ -339,11 +341,13 @@ static void rna_Material_use_specular_ramp_set(PointerRNA *ptr, int value)
static void rna_Material_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Material *ma = (Material *)ptr->data;
+ Main *bmain = CTX_data_main(C);
if (ma->use_nodes && ma->nodetree == NULL)
ED_node_shader_default(C, &ma->id);
-
- rna_Material_draw_update(CTX_data_main(C), CTX_data_scene(C), ptr);
+
+ DEG_relations_tag_update(bmain);
+ rna_Material_draw_update(bmain, CTX_data_scene(C), ptr);
}
static const EnumPropertyItem *rna_Material_texture_coordinates_itemf(bContext *UNUSED(C), PointerRNA *ptr,
@@ -428,7 +432,7 @@ void rna_mtex_texture_slots_clear(ID *self_id, struct bContext *C, ReportList *r
id_us_min((ID *)mtex_ar[index]->tex);
MEM_freeN(mtex_ar[index]);
mtex_ar[index] = NULL;
- DAG_id_tag_update(self_id, 0);
+ DEG_id_tag_update(self_id, 0);
}
/* for redraw only */
@@ -1805,6 +1809,24 @@ void RNA_def_material(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_eevee_blend_items[] = {
+ {MA_BM_SOLID, "OPAQUE", 0, "Opaque", "Render surface without transparency"},
+ {MA_BM_ADD, "ADD", 0, "Additive", "Render surface and blend the result with additive blending"},
+ {MA_BM_MULTIPLY, "MULTIPLY", 0, "Multiply", "Render surface and blend the result with multiplicative blending"},
+ {MA_BM_CLIP, "CLIP", 0, "Alpha Clip", "Use the alpha threshold to clip the visibility (binary visibility)"},
+ {MA_BM_HASHED, "HASHED", 0, "Alpha Hashed", "Use noise to dither the binary visibility (works well with multi-samples)"},
+ {MA_BM_BLEND, "BLEND", 0, "Alpha Blend", "Render polygon transparent, depending on alpha channel of the texture"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_eevee_blend_shadow_items[] = {
+ {MA_BS_NONE, "NONE", 0, "None", "Material will cast no shadow"},
+ {MA_BS_SOLID, "OPAQUE", 0, "Opaque", "Material will cast shadows without transparency"},
+ {MA_BS_CLIP, "CLIP", 0, "Clip", "Use the alpha threshold to clip the visibility (binary visibility)"},
+ {MA_BS_HASHED, "HASHED", 0, "Hashed", "Use noise to dither the binary visibility and use filtering to reduce the noise"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "Material", "ID");
RNA_def_struct_ui_text(srna, "Material",
"Material data-block to define the appearance of geometric objects for rendering");
@@ -1827,7 +1849,52 @@ void RNA_def_material(BlenderRNA *brna)
RNA_def_property_enum_items(prop, transparency_items);
RNA_def_property_ui_text(prop, "Transparency Method", "Method to use for rendering transparency");
RNA_def_property_update(prop, 0, "rna_Material_update");
-
+
+ /* Blending (only Eevee for now) */
+ prop = RNA_def_property(srna, "blend_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_eevee_blend_items);
+ RNA_def_property_ui_text(prop, "Blend Mode", "Blend Mode for Transparent Faces");
+ RNA_def_property_update(prop, 0, "rna_Material_draw_update");
+
+ prop = RNA_def_property(srna, "transparent_shadow_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "blend_shadow");
+ RNA_def_property_enum_items(prop, prop_eevee_blend_shadow_items);
+ RNA_def_property_ui_text(prop, "Transparent Shadow", "Shadow method for transparent material");
+ RNA_def_property_update(prop, 0, "rna_Material_draw_update");
+
+ prop = RNA_def_property(srna, "alpha_threshold", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_range(prop, 0, 1);
+ RNA_def_property_ui_text(prop, "Clip Threshold", "A pixel is rendered only if its alpha value is above this threshold");
+ RNA_def_property_update(prop, 0, "rna_Material_draw_update");
+
+ prop = RNA_def_property(srna, "transparent_hide_backside", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_HIDE_BACKSIDE);
+ RNA_def_property_ui_text(prop, "Hide Backside", "Limit transparency to a single layer "
+ "(avoids transparency sorting problems)");
+ RNA_def_property_update(prop, 0, "rna_Material_draw_update");
+
+ prop = RNA_def_property(srna, "use_screen_refraction", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_SS_REFRACTION);
+ RNA_def_property_ui_text(prop, "Screen Space Refraction", "Use raytraced screen space refractions");
+ RNA_def_property_update(prop, 0, "rna_Material_draw_update");
+
+ prop = RNA_def_property(srna, "use_screen_subsurface", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_SS_SUBSURFACE);
+ RNA_def_property_ui_text(prop, "Screen Space Subsurface Scattering", "Use post process subsurface scattering");
+ RNA_def_property_update(prop, 0, "rna_Material_draw_update");
+
+ prop = RNA_def_property(srna, "use_sss_translucency", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_TRANSLUCENCY);
+ RNA_def_property_ui_text(prop, "Subsurface Translucency", "Add translucency effect to subsurface");
+ RNA_def_property_update(prop, 0, "rna_Material_draw_update");
+
+ prop = RNA_def_property(srna, "refraction_depth", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "refract_depth");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Refraction Depth", "Approximate the thickness of the object to compute two refraction "
+ "event (0 is disabled)");
+ RNA_def_property_update(prop, 0, "rna_Material_draw_update");
+
/* For Preview Render */
prop = RNA_def_property(srna, "preview_render_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "pr_type");
@@ -1888,6 +1955,12 @@ void RNA_def_material(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Light Group", "Limit lighting to lamps in this Group");
RNA_def_property_update(prop, 0, "rna_Material_update");
+ prop = RNA_def_property(srna, "edit_image", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "edit_image");
+ RNA_def_property_struct_type(prop, "Image");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Edit Image", "Image to use for UV-mapping");
+
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "index");
RNA_def_property_ui_text(prop, "Pass Index", "Index number for the \"Material Index\" render pass");
@@ -1965,18 +2038,6 @@ void RNA_def_material(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Shadow Type", "How to draw shadows");
RNA_def_property_update(prop, 0, "rna_Material_update");
- prop = RNA_def_property(srna, "use_face_texture", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mode", MA_FACETEXTURE);
- RNA_def_property_ui_text(prop, "Face Textures",
- "Replace the object's base color with color from UV map image textures");
- RNA_def_property_update(prop, 0, "rna_Material_update");
-
- prop = RNA_def_property(srna, "use_face_texture_alpha", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mode", MA_FACETEXTURE_ALPHA);
- RNA_def_property_ui_text(prop, "Face Textures Alpha",
- "Replace the object's base alpha value with alpha from UV map image textures");
- RNA_def_property_update(prop, 0, "rna_Material_update");
-
prop = RNA_def_property(srna, "use_cast_shadows", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode2", MA_CASTSHADOW);
RNA_def_property_ui_text(prop, "Cast Shadows",
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 18fd4c64242..62360ea34a3 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -68,11 +68,12 @@ const EnumPropertyItem rna_enum_mesh_delimit_mode_items[] = {
#include "BLI_math.h"
#include "BKE_customdata.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "ED_mesh.h" /* XXX Bad level call */
#include "WM_api.h"
@@ -186,12 +187,10 @@ static void rna_MeshEdgeLayer_name_set(PointerRNA *ptr, const char *value)
rna_cd_layer_name_set(rna_mesh_edata(ptr), (CustomDataLayer *)ptr->data, value);
}
#endif
-#if 0
static void rna_MeshPolyLayer_name_set(PointerRNA *ptr, const char *value)
{
rna_cd_layer_name_set(rna_mesh_pdata(ptr), (CustomDataLayer *)ptr->data, value);
}
-#endif
static void rna_MeshLoopLayer_name_set(PointerRNA *ptr, const char *value)
{
rna_cd_layer_name_set(rna_mesh_ldata(ptr), (CustomDataLayer *)ptr->data, value);
@@ -224,7 +223,7 @@ static void rna_Mesh_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin
/* cheating way for importers to avoid slow updates */
if (id->us > 0) {
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
}
}
@@ -238,6 +237,20 @@ static void rna_Mesh_update_data_edit_color(Main *bmain, Scene *scene, PointerRN
}
}
+static void rna_Mesh_update_data_edit_weight(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ BKE_mesh_batch_cache_dirty(rna_mesh(ptr), BKE_MESH_BATCH_DIRTY_ALL);
+
+ rna_Mesh_update_data(bmain, scene, ptr);
+}
+
+
+static void rna_Mesh_update_data_edit_active_color(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ BKE_mesh_batch_cache_dirty(rna_mesh(ptr), BKE_MESH_BATCH_DIRTY_ALL);
+
+ rna_Mesh_update_data(bmain, scene, ptr);
+}
static void rna_Mesh_update_select(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
ID *id = ptr->id.data;
@@ -263,6 +276,9 @@ static void rna_Mesh_update_vertmask(Main *bmain, Scene *scene, PointerRNA *ptr)
if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_FACE_SEL)) {
me->editflag &= ~ME_EDIT_PAINT_FACE_SEL;
}
+
+ BKE_mesh_batch_cache_dirty(me, BKE_MESH_BATCH_DIRTY_ALL);
+
rna_Mesh_update_draw(bmain, scene, ptr);
}
@@ -272,6 +288,9 @@ static void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr)
if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_FACE_SEL)) {
me->editflag &= ~ME_EDIT_PAINT_VERT_SEL;
}
+
+ BKE_mesh_batch_cache_dirty(me, BKE_MESH_BATCH_DIRTY_ALL);
+
rna_Mesh_update_draw(bmain, scene, ptr);
}
@@ -758,13 +777,6 @@ static void rna_CustomDataLayer_active_set(PointerRNA *ptr, CustomData *data, in
if (render) CustomData_set_layer_render(data, type, n);
else CustomData_set_layer_active(data, type, n);
- /* sync loop layer */
- if (type == CD_MTEXPOLY) {
- CustomData *ldata = rna_mesh_ldata(ptr);
- if (render) CustomData_set_layer_render(ldata, CD_MLOOPUV, n);
- else CustomData_set_layer_active(ldata, CD_MLOOPUV, n);
- }
-
BKE_mesh_update_customdata_pointers(me, true);
}
@@ -869,6 +881,36 @@ static int rna_MeshUVLoopLayer_data_length(PointerRNA *ptr)
return (me->edit_btmesh) ? 0 : me->totloop;
}
+static int rna_MeshUVLoopLayer_active_render_get(PointerRNA *ptr)
+{
+ return rna_CustomDataLayer_active_get(ptr, rna_mesh_ldata(ptr), CD_MLOOPUV, 1);
+}
+
+static int rna_MeshUVLoopLayer_active_get(PointerRNA *ptr)
+{
+ return rna_CustomDataLayer_active_get(ptr, rna_mesh_ldata(ptr), CD_MLOOPUV, 0);
+}
+
+static int rna_MeshUVLoopLayer_clone_get(PointerRNA *ptr)
+{
+ return rna_CustomDataLayer_clone_get(ptr, rna_mesh_ldata(ptr), CD_MLOOPUV);
+}
+
+static void rna_MeshUVLoopLayer_active_render_set(PointerRNA *ptr, int value)
+{
+ rna_CustomDataLayer_active_set(ptr, rna_mesh_ldata(ptr), value, CD_MLOOPUV, 1);
+}
+
+static void rna_MeshUVLoopLayer_active_set(PointerRNA *ptr, int value)
+{
+ rna_CustomDataLayer_active_set(ptr, rna_mesh_ldata(ptr), value, CD_MLOOPUV, 0);
+}
+
+static void rna_MeshUVLoopLayer_clone_set(PointerRNA *ptr, int value)
+{
+ rna_CustomDataLayer_clone_set(ptr, rna_mesh_ldata(ptr), value, CD_MLOOPUV);
+}
+
/* face uv_textures */
DEFINE_CUSTOMDATA_LAYER_COLLECTION(tessface_uv_texture, fdata, CD_MTFACE)
@@ -920,57 +962,6 @@ static void rna_MeshTextureFaceLayer_clone_set(PointerRNA *ptr, int value)
rna_CustomDataLayer_clone_set(ptr, rna_mesh_fdata(ptr), value, CD_MTFACE);
}
-/* poly uv_textures */
-
-DEFINE_CUSTOMDATA_LAYER_COLLECTION(uv_texture, pdata, CD_MTEXPOLY)
-DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(uv_texture, pdata, CD_MTEXPOLY, active, MeshTexturePolyLayer)
-DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(uv_texture, pdata, CD_MTEXPOLY, clone, MeshTexturePolyLayer)
-DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(uv_texture, pdata, CD_MTEXPOLY, stencil, MeshTexturePolyLayer)
-DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(uv_texture, pdata, CD_MTEXPOLY, render, MeshTexturePolyLayer)
-
-static void rna_MeshTexturePolyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
-{
- Mesh *me = rna_mesh(ptr);
- CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
- rna_iterator_array_begin(iter, layer->data, sizeof(MTexPoly), (me->edit_btmesh) ? 0 : me->totpoly, 0, NULL);
-}
-
-static int rna_MeshTexturePolyLayer_data_length(PointerRNA *ptr)
-{
- Mesh *me = rna_mesh(ptr);
- return (me->edit_btmesh) ? 0 : me->totpoly;
-}
-
-static int rna_MeshTexturePolyLayer_active_render_get(PointerRNA *ptr)
-{
- return rna_CustomDataLayer_active_get(ptr, rna_mesh_pdata(ptr), CD_MTEXPOLY, 1);
-}
-
-static int rna_MeshTexturePolyLayer_active_get(PointerRNA *ptr)
-{
- return rna_CustomDataLayer_active_get(ptr, rna_mesh_pdata(ptr), CD_MTEXPOLY, 0);
-}
-
-static int rna_MeshTexturePolyLayer_clone_get(PointerRNA *ptr)
-{
- return rna_CustomDataLayer_clone_get(ptr, rna_mesh_pdata(ptr), CD_MTEXPOLY);
-}
-
-static void rna_MeshTexturePolyLayer_active_render_set(PointerRNA *ptr, int value)
-{
- rna_CustomDataLayer_active_set(ptr, rna_mesh_pdata(ptr), value, CD_MTEXPOLY, 1);
-}
-
-static void rna_MeshTexturePolyLayer_active_set(PointerRNA *ptr, int value)
-{
- rna_CustomDataLayer_active_set(ptr, rna_mesh_pdata(ptr), value, CD_MTEXPOLY, 0);
-}
-
-static void rna_MeshTexturePolyLayer_clone_set(PointerRNA *ptr, int value)
-{
- rna_CustomDataLayer_clone_set(ptr, rna_mesh_pdata(ptr), value, CD_MTEXPOLY);
-}
-
/* vertex_color_layers */
DEFINE_CUSTOMDATA_LAYER_COLLECTION(tessface_vertex_color, fdata, CD_MCOL)
@@ -1194,42 +1185,75 @@ static int rna_MeshPaintMaskLayer_data_length(PointerRNA *ptr)
/* End paint mask */
-static void rna_TexturePoly_image_set(PointerRNA *ptr, PointerRNA value)
+/* Face maps */
+
+DEFINE_CUSTOMDATA_LAYER_COLLECTION(face_map, pdata, CD_FACEMAP)
+DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(face_map, pdata, CD_FACEMAP, active, MeshFaceMapLayer)
+
+static char *rna_MeshFaceMapLayer_path(PointerRNA *ptr)
{
- MTexPoly *tf = (MTexPoly *)ptr->data;
- ID *id = value.data;
+ CustomDataLayer *cdl = ptr->data;
+ char name_esc[sizeof(cdl->name) * 2];
+ BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
+ return BLI_sprintfN("face_maps[\"%s\"]", name_esc);
+}
+
+static void rna_MeshFaceMapLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ CustomDataLayer *layer = (CustomDataLayer *)ptr->data;
+ rna_iterator_array_begin(iter, layer->data, sizeof(int), me->totpoly, 0, NULL);
+}
+
+static int rna_MeshFaceMapLayer_data_length(PointerRNA *ptr)
+{
+ Mesh *me = rna_mesh(ptr);
+ return me->totpoly;
+}
- if (id) {
- /* special exception here, individual faces don't count
- * as reference, but we do ensure the refcount is not zero */
- if (id->us == 0)
- id_us_plus(id);
- else
- id_lib_extern(id);
+static PointerRNA rna_Mesh_face_map_new(struct Mesh *me, ReportList *reports, const char *name)
+{
+ if (BKE_mesh_ensure_facemap_customdata(me) == false) {
+ BKE_report(reports, RPT_ERROR, "Currently only single face-map layers are supported");
+ return PointerRNA_NULL;
}
- tf->tpage = (struct Image *)id;
+ CustomData *pdata = rna_mesh_pdata_helper(me);
+
+ int index = CustomData_get_layer_index(pdata, CD_FACEMAP);
+ BLI_assert(index != -1);
+ CustomDataLayer *cdl = &pdata->layers[index];
+ rna_cd_layer_name_set(pdata, cdl, name);
+
+ PointerRNA ptr;
+ RNA_pointer_create(&me->id, &RNA_MeshFaceMapLayer, cdl, &ptr);
+ return ptr;
}
-/* while this is supposed to be readonly,
- * keep it to support importers that only make tessfaces */
-static void rna_TextureFace_image_set(PointerRNA *ptr, PointerRNA value)
-{
- MTFace *tf = (MTFace *)ptr->data;
- ID *id = value.data;
-
- if (id) {
- /* special exception here, individual faces don't count
- * as reference, but we do ensure the refcount is not zero */
- if (id->us == 0)
- id_us_plus(id);
- else
- id_lib_extern(id);
+static void rna_Mesh_face_map_remove(struct Mesh *me, ReportList *reports, struct CustomDataLayer *layer)
+{
+ /* just for sanity check */
+ {
+ CustomData *pdata = rna_mesh_pdata_helper(me);
+ int index = CustomData_get_layer_index(pdata, CD_FACEMAP);
+ if (index != -1) {
+ CustomDataLayer *layer_test = &pdata->layers[index];
+ if (layer != layer_test) {
+ /* don't show name, its likely freed memory */
+ BKE_report(reports, RPT_ERROR, "FaceMap not in mesh");
+ return;
+ }
+ }
}
- tf->tpage = (struct Image *)id;
+ if (BKE_mesh_clear_facemap_customdata(me) == false) {
+ BKE_reportf(reports, RPT_ERROR, "Error removing face-map");
+ }
}
+/* End face maps */
+
+
static int rna_MeshTessFace_verts_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
{
MFace *face = (MFace *)ptr->data;
@@ -1380,14 +1404,6 @@ static char *rna_MeshTextureFaceLayer_path(PointerRNA *ptr)
return BLI_sprintfN("tessface_uv_textures[\"%s\"]", name_esc);
}
-static char *rna_MeshTexturePolyLayer_path(PointerRNA *ptr)
-{
- CustomDataLayer *cdl = ptr->data;
- char name_esc[sizeof(cdl->name) * 2];
- BLI_strescape(name_esc, cdl->name, sizeof(name_esc));
- return BLI_sprintfN("uv_textures[\"%s\"]", name_esc);
-}
-
static char *rna_VertCustomData_data_path(PointerRNA *ptr, const char *collection, int type)
{
CustomDataLayer *cdl;
@@ -1483,11 +1499,6 @@ static char *rna_MeshTextureFace_path(PointerRNA *ptr)
return rna_FaceCustomData_data_path(ptr, "tessface_uv_textures", CD_MTFACE);
}
-static char *rna_MeshTexturePoly_path(PointerRNA *ptr)
-{
- return rna_PolyCustomData_data_path(ptr, "uv_textures", CD_MTEXPOLY);
-}
-
static char *rna_MeshColorLayer_path(PointerRNA *ptr)
{
CustomDataLayer *cdl = ptr->data;
@@ -1675,6 +1686,12 @@ void rna_MeshStringProperty_s_set(PointerRNA *ptr, const char *value)
MStringProperty *ms = (MStringProperty *)ptr->data;
BLI_strncpy(ms->s, value, sizeof(ms->s));
}
+
+static char *rna_MeshFaceMap_path(PointerRNA *ptr)
+{
+ return rna_PolyCustomData_data_path(ptr, "face_maps", CD_FACEMAP);
+}
+
/***************************************/
static int rna_Mesh_tot_vert_get(PointerRNA *ptr)
@@ -1768,23 +1785,23 @@ DEFINE_CUSTOMDATA_PROPERTY_API(polygon, int, CD_PROP_INT, pdata, totpoly, MeshPo
DEFINE_CUSTOMDATA_PROPERTY_API(polygon, string, CD_PROP_STR, pdata, totpoly, MeshPolygonStringPropertyLayer)
#undef DEFINE_CUSTOMDATA_PROPERTY_API
-static PointerRNA rna_Mesh_uv_texture_new(struct Mesh *me, const char *name)
+static PointerRNA rna_Mesh_uv_layers_new(struct Mesh *me, const char *name)
{
PointerRNA ptr;
- CustomData *pdata;
+ CustomData *ldata;
CustomDataLayer *cdl = NULL;
int index = ED_mesh_uv_texture_add(me, name, false);
if (index != -1) {
- pdata = rna_mesh_pdata_helper(me);
- cdl = &pdata->layers[CustomData_get_layer_index_n(pdata, CD_MTEXPOLY, index)];
+ ldata = rna_mesh_ldata_helper(me);
+ cdl = &ldata->layers[CustomData_get_layer_index_n(ldata, CD_MLOOPUV, index)];
}
- RNA_pointer_create(&me->id, &RNA_MeshTexturePolyLayer, cdl, &ptr);
+ RNA_pointer_create(&me->id, &RNA_MeshUVLoopLayer, cdl, &ptr);
return ptr;
}
-static void rna_Mesh_uv_texture_layers_remove(struct Mesh *me, ReportList *reports, CustomDataLayer *layer)
+static void rna_Mesh_uv_layers_remove(struct Mesh *me, ReportList *reports, CustomDataLayer *layer)
{
if (ED_mesh_uv_texture_remove_named(me, layer->name) == false) {
BKE_reportf(reports, RPT_ERROR, "Texture layer '%s' not found", layer->name);
@@ -1859,14 +1876,14 @@ static void UNUSED_FUNCTION(rna_mesh_unused)(void)
(void)rna_Mesh_uv_layer_render_index_get;
(void)rna_Mesh_uv_layer_render_index_set;
(void)rna_Mesh_uv_layer_render_set;
- (void)rna_Mesh_uv_texture_render_get;
- (void)rna_Mesh_uv_texture_render_index_get;
- (void)rna_Mesh_uv_texture_render_index_set;
- (void)rna_Mesh_uv_texture_render_set;
(void)rna_Mesh_vertex_color_render_get;
(void)rna_Mesh_vertex_color_render_index_get;
(void)rna_Mesh_vertex_color_render_index_set;
(void)rna_Mesh_vertex_color_render_set;
+ (void)rna_Mesh_face_map_index_range;
+ (void)rna_Mesh_face_map_active_index_set;
+ (void)rna_Mesh_face_map_active_index_get;
+ (void)rna_Mesh_face_map_active_set;
/* end unused function block */
}
@@ -1894,7 +1911,7 @@ static void rna_def_mvert_group(BlenderRNA *brna)
prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Weight", "Vertex Weight");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data_edit_weight");
}
static void rna_def_mvert(BlenderRNA *brna)
@@ -2264,6 +2281,24 @@ static void rna_def_mloopuv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Name", "Name of UV map");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+ prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_MeshUVLoopLayer_active_get", "rna_MeshUVLoopLayer_active_set");
+ RNA_def_property_ui_text(prop, "Active", "Set the map as active for display and editing");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
+ prop = RNA_def_property(srna, "active_render", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "active_rnd", 0);
+ RNA_def_property_boolean_funcs(prop, "rna_MeshUVLoopLayer_active_render_get",
+ "rna_MeshUVLoopLayer_active_render_set");
+ RNA_def_property_ui_text(prop, "Active Render", "Set the map as active for rendering");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
+ prop = RNA_def_property(srna, "active_clone", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "active_clone", 0);
+ RNA_def_property_boolean_funcs(prop, "rna_MeshUVLoopLayer_clone_get", "rna_MeshUVLoopLayer_clone_set");
+ RNA_def_property_ui_text(prop, "Active Clone", "Set the map as active for cloning");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
srna = RNA_def_struct(brna, "MeshUVLoop", NULL);
RNA_def_struct_sdna(srna, "MLoopUV");
RNA_def_struct_path_func(srna, "rna_MeshUVLoop_path");
@@ -2333,13 +2368,6 @@ static void rna_def_mtface(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_MeshTextureFace_path");
RNA_def_struct_ui_icon(srna, ICON_FACESEL_HLT);
- prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "tpage");
- RNA_def_property_pointer_funcs(prop, NULL, "rna_TextureFace_image_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Image", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
/* these are for editing only, access at loops now */
#if 0
prop = RNA_def_property(srna, "select_uv", PROP_BOOLEAN, PROP_NONE);
@@ -2394,84 +2422,6 @@ static void rna_def_mtface(BlenderRNA *brna)
}
-static void rna_def_mtexpoly(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-#if 0 /* BMESH_TODO: needed later when do another todo */
- int uv_dim[] = {4, 2};
-#endif
-
- srna = RNA_def_struct(brna, "MeshTexturePolyLayer", NULL);
- RNA_def_struct_ui_text(srna, "Mesh UV Map", "UV map with assigned image textures in a Mesh data-block");
- RNA_def_struct_sdna(srna, "CustomDataLayer");
- RNA_def_struct_path_func(srna, "rna_MeshTexturePolyLayer_path");
- RNA_def_struct_ui_icon(srna, ICON_GROUP_UVS);
-
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshUVLayer_name_set");
- RNA_def_property_ui_text(prop, "Name", "Name of UV map");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_MeshTexturePolyLayer_active_get", "rna_MeshTexturePolyLayer_active_set");
- RNA_def_property_ui_text(prop, "Active", "Set the map as active for display and editing");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop = RNA_def_property(srna, "active_render", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "active_rnd", 0);
- RNA_def_property_boolean_funcs(prop, "rna_MeshTexturePolyLayer_active_render_get",
- "rna_MeshTexturePolyLayer_active_render_set");
- RNA_def_property_ui_text(prop, "Active Render", "Set the map as active for rendering");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop = RNA_def_property(srna, "active_clone", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "active_clone", 0);
- RNA_def_property_boolean_funcs(prop, "rna_MeshTexturePolyLayer_clone_get", "rna_MeshTexturePolyLayer_clone_set");
- RNA_def_property_ui_text(prop, "Active Clone", "Set the map as active for cloning");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "MeshTexturePoly");
- RNA_def_property_ui_text(prop, "Data", "");
- RNA_def_property_collection_funcs(prop, "rna_MeshTexturePolyLayer_data_begin", "rna_iterator_array_next",
- "rna_iterator_array_end", "rna_iterator_array_get",
- "rna_MeshTexturePolyLayer_data_length", NULL, NULL, NULL);
-
- srna = RNA_def_struct(brna, "MeshTexturePoly", NULL);
- RNA_def_struct_sdna(srna, "MTexPoly");
- RNA_def_struct_ui_text(srna, "Mesh UV Map Face", "UV map and image texture for a face");
- RNA_def_struct_path_func(srna, "rna_MeshTexturePoly_path");
- RNA_def_struct_ui_icon(srna, ICON_FACESEL_HLT);
-
- prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "tpage");
- RNA_def_property_pointer_funcs(prop, NULL, "rna_TexturePoly_image_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Image", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
-#if 0 /* moved to MeshUVLoopLayer */
- prop = RNA_def_property(srna, "select_uv", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", TF_SEL1);
- RNA_def_property_array(prop, 4);
- RNA_def_property_ui_text(prop, "UV Selected", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
-
- prop = RNA_def_property(srna, "pin_uv", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "unwrap", TF_PIN1);
- RNA_def_property_array(prop, 4);
- RNA_def_property_ui_text(prop, "UV Pinned", "");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_select");
-
- prop = RNA_def_property(srna, "uv_raw", PROP_FLOAT, PROP_NONE);
- RNA_def_property_multi_array(prop, 2, uv_dim);
- RNA_def_property_float_sdna(prop, NULL, "uv");
- RNA_def_property_ui_text(prop, "UV", "Fixed size UV coordinates array");
-#endif
-}
-
static void rna_def_mcol(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2938,13 +2888,13 @@ static void rna_def_loop_colors(BlenderRNA *brna, PropertyRNA *cprop)
"rna_Mesh_vertex_color_active_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
RNA_def_property_ui_text(prop, "Active Vertex Color Layer", "Active vertex color layer");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data_edit_active_color");
prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop, "rna_Mesh_vertex_color_active_index_get",
"rna_Mesh_vertex_color_active_index_set", "rna_Mesh_vertex_color_index_range");
RNA_def_property_ui_text(prop, "Active Vertex Color Index", "Active vertex color index");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data_edit_active_color");
}
static void rna_def_uv_layers(BlenderRNA *brna, PropertyRNA *cprop)
@@ -2952,14 +2902,27 @@ static void rna_def_uv_layers(BlenderRNA *brna, PropertyRNA *cprop)
StructRNA *srna;
PropertyRNA *prop;
- /* FunctionRNA *func; */
- /* PropertyRNA *parm; */
+ FunctionRNA *func;
+ PropertyRNA *parm;
RNA_def_property_srna(cprop, "UVLoopLayers");
srna = RNA_def_struct(brna, "UVLoopLayers", NULL);
RNA_def_struct_sdna(srna, "Mesh");
RNA_def_struct_ui_text(srna, "UV Loop Layers", "Collection of uv loop layers");
+ func = RNA_def_function(srna, "new", "rna_Mesh_uv_layers_new");
+ RNA_def_function_ui_description(func, "Add a UV map layer to Mesh");
+ RNA_def_string(func, "name", "UVMap", 0, "", "UV map name");
+ parm = RNA_def_pointer(func, "layer", "MeshUVLoopLayer", "", "The newly created layer");
+ RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Mesh_uv_layers_remove");
+ RNA_def_function_ui_description(func, "Remove a vertex color layer");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "layer", "MeshUVLoopLayer", "", "The layer to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshUVLoopLayer");
RNA_def_property_pointer_funcs(prop, "rna_Mesh_uv_layer_active_get",
@@ -3124,7 +3087,6 @@ static void rna_def_tessface_uv_textures(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
RNA_def_function_return(func, parm);
-
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshTextureFaceLayer");
RNA_def_property_pointer_funcs(prop, "rna_Mesh_tessface_uv_texture_active_get",
@@ -3134,49 +3096,7 @@ static void rna_def_tessface_uv_textures(BlenderRNA *brna, PropertyRNA *cprop)
prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop, "rna_Mesh_tessface_uv_texture_active_index_get",
- "rna_Mesh_tessface_uv_texture_active_index_set", "rna_Mesh_uv_texture_index_range");
- RNA_def_property_ui_text(prop, "Active UV Map Index", "Active UV Map index");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-}
-
-
-static void rna_def_uv_textures(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- FunctionRNA *func;
- PropertyRNA *parm;
-
- RNA_def_property_srna(cprop, "UVTextures");
- srna = RNA_def_struct(brna, "UVTextures", NULL);
- RNA_def_struct_sdna(srna, "Mesh");
- RNA_def_struct_ui_text(srna, "UV Maps", "Collection of UV maps");
-
- func = RNA_def_function(srna, "new", "rna_Mesh_uv_texture_new");
- RNA_def_function_ui_description(func, "Add a UV map layer to Mesh");
- RNA_def_string(func, "name", "UVMap", 0, "", "UV map name");
- parm = RNA_def_pointer(func, "layer", "MeshTexturePolyLayer", "", "The newly created layer");
- RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "remove", "rna_Mesh_uv_texture_layers_remove");
- RNA_def_function_ui_description(func, "Remove a vertex color layer");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "layer", "MeshTexturePolyLayer", "", "The layer to remove");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
-
- prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "MeshTexturePolyLayer");
- RNA_def_property_pointer_funcs(prop, "rna_Mesh_uv_texture_active_get",
- "rna_Mesh_uv_texture_active_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
- RNA_def_property_ui_text(prop, "Active UV Map", "Active UV Map");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_Mesh_uv_texture_active_index_get",
- "rna_Mesh_uv_texture_active_index_set", "rna_Mesh_uv_texture_index_range");
+ "rna_Mesh_tessface_uv_texture_active_index_set", "rna_Mesh_uv_layer_index_range");
RNA_def_property_ui_text(prop, "Active UV Map Index", "Active UV Map index");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
@@ -3259,6 +3179,79 @@ static void rna_def_paint_mask(BlenderRNA *brna, PropertyRNA *UNUSED(cprop))
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
}
+static void rna_def_face_map(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "MeshFaceMapLayer", NULL);
+ RNA_def_struct_ui_text(srna, "Mesh Face Map Layer", "Per-face map index");
+ RNA_def_struct_sdna(srna, "CustomDataLayer");
+ RNA_def_struct_path_func(srna, "rna_MeshFaceMapLayer_path");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshPolyLayer_name_set");
+ RNA_def_property_ui_text(prop, "Name", "Name of face-map layer");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
+ prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "MeshFaceMap");
+ RNA_def_property_ui_text(prop, "Data", "");
+ RNA_def_property_collection_funcs(prop, "rna_MeshFaceMapLayer_data_begin", "rna_iterator_array_next",
+ "rna_iterator_array_end", "rna_iterator_array_get",
+ "rna_MeshFaceMapLayer_data_length", NULL, NULL, NULL);
+
+ /* FaceMap struct */
+ srna = RNA_def_struct(brna, "MeshFaceMap", NULL);
+ RNA_def_struct_sdna(srna, "MIntProperty");
+ RNA_def_struct_ui_text(srna, "Int Property", "");
+ RNA_def_struct_path_func(srna, "rna_MeshFaceMap_path");
+
+ prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "i");
+ RNA_def_property_ui_text(prop, "Value", "");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+}
+
+static void rna_def_face_maps(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ RNA_def_property_srna(cprop, "MeshFaceMapLayers");
+ srna = RNA_def_struct(brna, "MeshFaceMapLayers", NULL);
+ RNA_def_struct_ui_text(srna, "Mesh Face Map Layer", "Per-face map index");
+ RNA_def_struct_sdna(srna, "Mesh");
+ RNA_def_struct_ui_text(srna, "Mesh FaceMaps", "Collection of mesh face-maps");
+
+ /* add this since we only ever have one layer anyway, don't bother with active_index */
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "MeshFaceMapLayer");
+ RNA_def_property_pointer_funcs(prop, "rna_Mesh_face_map_active_get",
+ NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Active FaceMap Layer", "");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ func = RNA_def_function(srna, "new", "rna_Mesh_face_map_new");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Add a float property layer to Mesh");
+ RNA_def_string(func, "name", "Face Map", 0, "", "Face map name");
+ parm = RNA_def_pointer(func, "layer", "MeshFaceMapLayer", "", "The newly created layer");
+ RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Mesh_face_map_remove");
+ RNA_def_function_ui_description(func, "Remove a face map layer");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "layer", "MeshFaceMapLayer", "", "The layer to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+}
+
static void rna_def_mesh(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3348,41 +3341,6 @@ static void rna_def_mesh(BlenderRNA *brna)
"All UV maps for tessellated faces (read-only, for use by renderers)");
rna_def_tessface_uv_textures(brna, prop);
- /* UV maps */
- prop = RNA_def_property(srna, "uv_textures", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
- RNA_def_property_collection_funcs(prop, "rna_Mesh_uv_textures_begin", NULL, NULL, NULL,
- "rna_Mesh_uv_textures_length", NULL, NULL, NULL);
- RNA_def_property_struct_type(prop, "MeshTexturePolyLayer");
- RNA_def_property_ui_text(prop, "UV Maps", "All UV maps");
- rna_def_uv_textures(brna, prop);
-
- prop = RNA_def_property(srna, "uv_texture_clone", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "MeshTexturePolyLayer");
- RNA_def_property_pointer_funcs(prop, "rna_Mesh_uv_texture_clone_get",
- "rna_Mesh_uv_texture_clone_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Clone UV Map", "UV map to be used as cloning source");
-
- prop = RNA_def_property(srna, "uv_texture_clone_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_Mesh_uv_texture_clone_index_get",
- "rna_Mesh_uv_texture_clone_index_set", "rna_Mesh_uv_texture_index_range");
- RNA_def_property_ui_text(prop, "Clone UV Map Index", "Clone UV map index");
-
- prop = RNA_def_property(srna, "uv_texture_stencil", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "MeshTexturePolyLayer");
- RNA_def_property_pointer_funcs(prop, "rna_Mesh_uv_texture_stencil_get",
- "rna_Mesh_uv_texture_stencil_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Mask UV Map", "UV map to mask the painted area");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
- prop = RNA_def_property(srna, "uv_texture_stencil_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_Mesh_uv_texture_stencil_index_get",
- "rna_Mesh_uv_texture_stencil_index_set", "rna_Mesh_uv_texture_index_range");
- RNA_def_property_ui_text(prop, "Mask UV Map Index", "Mask UV map index");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
/* Tessellated face colors - used by renderers */
prop = RNA_def_property(srna, "tessface_vertex_colors", PROP_COLLECTION, PROP_NONE);
@@ -3453,6 +3411,15 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "String Property Layers", "");
rna_def_polygon_string_layers(brna, prop);
+ /* face-maps */
+ prop = RNA_def_property(srna, "face_maps", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "pdata.layers", "pdata.totlayer");
+ RNA_def_property_collection_funcs(prop, "rna_Mesh_face_maps_begin", NULL, NULL, NULL,
+ "rna_Mesh_face_maps_length", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "MeshFaceMapLayer");
+ RNA_def_property_ui_text(prop, "FaceMap", "");
+ rna_def_face_maps(brna, prop);
+
/* Skin vertices */
prop = RNA_def_property(srna, "skin_vertices", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer");
@@ -3723,10 +3690,10 @@ void RNA_def_mesh(BlenderRNA *brna)
rna_def_mpolygon(brna);
rna_def_mloopuv(brna);
rna_def_mtface(brna);
- rna_def_mtexpoly(brna);
rna_def_mcol(brna);
rna_def_mloopcol(brna);
rna_def_mproperties(brna);
+ rna_def_face_map(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 9b0a25560f9..f1f7c9a3b99 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -48,6 +48,7 @@
#include "DNA_mesh_types.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_tangent.h"
#include "BKE_mesh_mapping.h"
#include "ED_mesh.h"
@@ -92,7 +93,7 @@ static void rna_Mesh_calc_tangents(Mesh *mesh, ReportList *reports, const char *
BKE_mesh_calc_normals_split(mesh);
}
- BKE_mesh_loop_tangents(mesh, uvmap, r_looptangents, reports);
+ BKE_mesh_calc_loop_tangent_single(mesh, uvmap, r_looptangents, reports);
}
static void rna_Mesh_free_tangents(Mesh *mesh)
@@ -172,7 +173,7 @@ static void rna_Mesh_normals_split_custom_set(Mesh *mesh, ReportList *reports, i
rna_Mesh_normals_split_custom_do(mesh, loopnors, false);
- DAG_id_tag_update(&mesh->id, 0);
+ DEG_id_tag_update(&mesh->id, 0);
}
static void rna_Mesh_normals_split_custom_set_from_vertices(
@@ -190,14 +191,14 @@ static void rna_Mesh_normals_split_custom_set_from_vertices(
rna_Mesh_normals_split_custom_do(mesh, vertnors, true);
- DAG_id_tag_update(&mesh->id, 0);
+ DEG_id_tag_update(&mesh->id, 0);
}
static void rna_Mesh_transform(Mesh *mesh, float *mat, int shape_keys)
{
BKE_mesh_transform(mesh, (float (*)[4])mat, shape_keys);
- DAG_id_tag_update(&mesh->id, 0);
+ DEG_id_tag_update(&mesh->id, 0);
}
static void rna_Mesh_flip_normals(Mesh *mesh)
@@ -206,7 +207,7 @@ static void rna_Mesh_flip_normals(Mesh *mesh)
BKE_mesh_tessface_clear(mesh);
BKE_mesh_calc_normals(mesh);
- DAG_id_tag_update(&mesh->id, 0);
+ DEG_id_tag_update(&mesh->id, 0);
}
static void rna_Mesh_split_faces(Mesh *mesh, int free_loop_normals)
@@ -214,6 +215,12 @@ static void rna_Mesh_split_faces(Mesh *mesh, int free_loop_normals)
BKE_mesh_split_faces(mesh, free_loop_normals != 0);
}
+static void rna_Mesh_update_gpu_tag(Mesh *mesh)
+{
+ BKE_mesh_batch_cache_dirty(mesh, BKE_MESH_BATCH_DIRTY_ALL);
+}
+
+
#else
void RNA_api_mesh(StructRNA *srna)
@@ -304,6 +311,8 @@ void RNA_api_mesh(StructRNA *srna)
RNA_def_boolean(func, "calc_tessface", 0, "Calculate Tessellation", "Force recalculation of tessellation faces");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_function(srna, "update_gpu_tag", "rna_Mesh_update_gpu_tag");
+
func = RNA_def_function(srna, "unit_test_compare", "rna_Mesh_unit_test_compare");
RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to compare to");
/* return value */
diff --git a/source/blender/makesrna/intern/rna_mesh_utils.h b/source/blender/makesrna/intern/rna_mesh_utils.h
index 0f42596ff13..05274e13e1e 100644
--- a/source/blender/makesrna/intern/rna_mesh_utils.h
+++ b/source/blender/makesrna/intern/rna_mesh_utils.h
@@ -101,12 +101,6 @@
for (layer = data->layers + layer_index, a = 0; layer_index + a < data->totlayer; layer++, a++) { \
if (value.data == layer) { \
CustomData_set_layer_##active_type(data, layer_type, a); \
- \
- /* keep loops in sync */ \
- if (layer_type == CD_MTEXPOLY) { \
- CustomData *ldata = rna_mesh_ldata_helper(me); \
- CustomData_set_layer_##active_type(ldata, CD_MLOOPUV, a); \
- } \
BKE_mesh_update_customdata_pointers(me, true); \
return; \
} \
@@ -131,11 +125,6 @@
CustomData *data = rna_mesh_##customdata_type(ptr); \
if (data) { \
CustomData_set_layer_##active_type(data, layer_type, value); \
- /* keep loops in sync */ \
- if (layer_type == CD_MTEXPOLY) { \
- CustomData *ldata = rna_mesh_ldata_helper(me); \
- CustomData_set_layer_##active_type(ldata, CD_MLOOPUV, value); \
- } \
BKE_mesh_update_customdata_pointers(me, true); \
} \
}
diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c
index 1a45db1e45f..8589d819360 100644
--- a/source/blender/makesrna/intern/rna_meta.c
+++ b/source/blender/makesrna/intern/rna_meta.c
@@ -47,9 +47,10 @@
#include "DNA_object_types.h"
#include "BKE_mball.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
+#include "DEG_depsgraph.h"
+
#include "WM_types.h"
#include "WM_api.h"
@@ -103,7 +104,7 @@ static void rna_MetaBall_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
if (ob->data == mb)
BKE_mball_properties_copy(scene, ob);
- DAG_id_tag_update(&mb->id, 0);
+ DEG_id_tag_update(&mb->id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, mb);
}
}
@@ -121,7 +122,7 @@ static MetaElem *rna_MetaBall_elements_new(MetaBall *mb, int type)
/* cheating way for importers to avoid slow updates */
if (mb->id.us > 0) {
- DAG_id_tag_update(&mb->id, 0);
+ DEG_id_tag_update(&mb->id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, &mb->id);
}
@@ -142,7 +143,7 @@ static void rna_MetaBall_elements_remove(MetaBall *mb, ReportList *reports, Poin
/* cheating way for importers to avoid slow updates */
if (mb->id.us > 0) {
- DAG_id_tag_update(&mb->id, 0);
+ DEG_id_tag_update(&mb->id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, &mb->id);
}
}
@@ -153,7 +154,7 @@ static void rna_MetaBall_elements_clear(MetaBall *mb)
/* cheating way for importers to avoid slow updates */
if (mb->id.us > 0) {
- DAG_id_tag_update(&mb->id, 0);
+ DEG_id_tag_update(&mb->id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, &mb->id);
}
}
diff --git a/source/blender/makesrna/intern/rna_meta_api.c b/source/blender/makesrna/intern/rna_meta_api.c
index 4c3fa787b94..53bb3ef2334 100644
--- a/source/blender/makesrna/intern/rna_meta_api.c
+++ b/source/blender/makesrna/intern/rna_meta_api.c
@@ -47,7 +47,12 @@ static void rna_Meta_transform(struct MetaBall *mb, float *mat)
{
BKE_mball_transform(mb, (float (*)[4])mat, true);
- DAG_id_tag_update(&mb->id, 0);
+ DEG_id_tag_update(&mb->id, 0);
+}
+
+static void rna_Mball_update_gpu_tag(MetaBall *mb)
+{
+ BKE_mball_batch_cache_dirty(mb, BKE_MBALL_BATCH_DIRTY_ALL);
}
#else
@@ -60,6 +65,8 @@ void RNA_api_meta(StructRNA *srna)
RNA_def_function_ui_description(func, "Transform meta elements by a matrix");
parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ RNA_def_function(srna, "update_gpu_tag", "rna_Mball_update_gpu_tag");
}
#endif
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index a99c9f9d89e..1858b6db997 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -286,12 +286,14 @@ const EnumPropertyItem rna_enum_axis_flag_xyz_items[] = {
#include "BKE_cachefile.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#ifdef WITH_ALEMBIC
# include "ABC_alembic.h"
#endif
@@ -453,14 +455,14 @@ static char *rna_Modifier_path(PointerRNA *ptr)
static void rna_Modifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->id.data);
}
static void rna_Modifier_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_Modifier_update(bmain, scene, ptr);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
/* Vertex Groups */
@@ -793,11 +795,11 @@ static void rna_CurveModifier_dependency_update(Main *bmain, Scene *scene, Point
{
CurveModifierData *cmd = (CurveModifierData *)ptr->data;
rna_Modifier_update(bmain, scene, ptr);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
if (cmd->object != NULL) {
Curve *curve = cmd->object->data;
if ((curve->flag & CU_PATH) == 0) {
- DAG_id_tag_update(&curve->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&curve->id, OB_RECALC_DATA);
}
}
}
@@ -806,11 +808,11 @@ static void rna_ArrayModifier_dependency_update(Main *bmain, Scene *scene, Point
{
ArrayModifierData *amd = (ArrayModifierData *)ptr->data;
rna_Modifier_update(bmain, scene, ptr);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
if (amd->curve_ob != NULL) {
Curve *curve = amd->curve_ob->data;
if ((curve->flag & CU_PATH) == 0) {
- DAG_id_tag_update(&curve->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&curve->id, OB_RECALC_DATA);
}
}
}
@@ -933,19 +935,19 @@ static const EnumPropertyItem *rna_DataTransferModifier_layers_select_src_itemf(
if (ob_src) {
DerivedMesh *dm_src;
- CustomData *pdata;
+ CustomData *ldata;
int num_data, i;
dm_src = object_get_derived_final(ob_src, false);
if (dm_src != NULL) {
- pdata = dm_src->getPolyDataLayout(dm_src);
- num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+ ldata = dm_src->getLoopDataLayout(dm_src);
+ num_data = CustomData_number_of_layers(ldata, CD_MLOOPUV);
RNA_enum_item_add_separator(&item, &totitem);
for (i = 0; i < num_data; i++) {
tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i);
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPUV, i);
RNA_enum_item_add(&item, &totitem, &tmp_item);
}
}
@@ -1024,18 +1026,18 @@ static const EnumPropertyItem *rna_DataTransferModifier_layers_select_dst_itemf(
if (ob_dst && ob_dst->data) {
Mesh *me_dst;
- CustomData *pdata;
+ CustomData *ldata;
int num_data, i;
me_dst = ob_dst->data;
- pdata = &me_dst->pdata;
- num_data = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+ ldata = &me_dst->ldata;
+ num_data = CustomData_number_of_layers(ldata, CD_MLOOPUV);
RNA_enum_item_add_separator(&item, &totitem);
for (i = 0; i < num_data; i++) {
tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(pdata, CD_MTEXPOLY, i);
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPUV, i);
RNA_enum_item_add(&item, &totitem, &tmp_item);
}
}
@@ -1815,7 +1817,7 @@ static void rna_def_modifier_armature(BlenderRNA *brna)
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Armature object to deform with");
RNA_def_property_pointer_funcs(prop, NULL, "rna_ArmatureModifier_object_set", NULL, "rna_Armature_object_poll");
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK | PROP_OVERRIDABLE_STATIC);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "use_bone_envelopes", PROP_BOOLEAN, PROP_NONE);
@@ -2293,11 +2295,6 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vertical Scale", "");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
- prop = RNA_def_property(srna, "use_image_override", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_UVPROJECT_OVERRIDEIMAGE);
- RNA_def_property_ui_text(prop, "Override Image", "Override faces' current images with the given image");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
srna = RNA_def_struct(brna, "UVProjector", NULL);
RNA_def_struct_ui_text(srna, "UVProjector", "UV projector used by the UV project modifier");
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index fb743f5236d..850b1cd706b 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -47,7 +47,7 @@
#ifdef RNA_RUNTIME
-#include "BKE_depsgraph.h"
+#include "DEG_depsgraph.h"
#include "ED_clip.h"
@@ -59,7 +59,7 @@ static void rna_MovieClip_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene
MovieClip *clip = (MovieClip *)ptr->id.data;
BKE_movieclip_reload(clip);
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
}
static void rna_MovieClip_size_get(PointerRNA *ptr, int *values)
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 20d5e1e959c..a14508ecb18 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -50,7 +50,6 @@
/* needed for some of the validation stuff... */
#include "BKE_animsys.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_nla.h"
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 4c096beaca7..ab8370f77e7 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -66,6 +66,8 @@
#include "NOD_composite.h"
+#include "DEG_depsgraph.h"
+
const EnumPropertyItem rna_enum_node_socket_in_out_items[] = {
{ SOCK_IN, "IN", 0, "Input", "" },
{ SOCK_OUT, "OUT", 0, "Output", "" },
@@ -187,6 +189,8 @@ static const EnumPropertyItem node_sampler_type_items[] = {
#include "ED_node.h"
#include "ED_render.h"
+#include "GPU_material.h"
+
#include "NOD_common.h"
#include "NOD_socket.h"
@@ -2299,13 +2303,25 @@ static void rna_NodeSocketStandard_vector_range(PointerRNA *ptr, float *min, flo
*softmax = dval->max;
}
+static void rna_NodeSocket_value_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ if (ntree->type == NTREE_SHADER) {
+ DEG_id_tag_update_ex(bmain, ptr->id.data, DEG_TAG_SHADING_UPDATE);
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL);
+ }
+ else {
+ rna_NodeSocket_update(bmain, scene, ptr);
+ }
+}
+
/* using a context update function here, to avoid searching the node if possible */
static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA *ptr)
{
bNode *node;
/* default update */
- rna_NodeSocket_update(CTX_data_main(C), CTX_data_scene(C), ptr);
+ rna_NodeSocket_value_update(CTX_data_main(C), CTX_data_scene(C), ptr);
/* try to use node from context, faster */
node = CTX_data_pointer_get(C, "node").data;
@@ -2751,7 +2767,7 @@ static const EnumPropertyItem *rna_Node_image_view_itemf(bContext *UNUSED(C), Po
return item;
}
-static const EnumPropertyItem *rna_Node_scene_layer_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+static const EnumPropertyItem *rna_Node_view_layer_itemf(bContext *UNUSED(C), PointerRNA *ptr,
PropertyRNA *UNUSED(prop), bool *r_free)
{
bNode *node = (bNode *)ptr->data;
@@ -2764,7 +2780,7 @@ static const EnumPropertyItem *rna_Node_scene_layer_itemf(bContext *UNUSED(C), P
return DummyRNA_NULL_items;
}
- rl = sce->r.layers.first;
+ rl = sce->view_layers.first;
item = renderresult_layers_add_enum(rl);
*r_free = true;
@@ -2772,7 +2788,7 @@ static const EnumPropertyItem *rna_Node_scene_layer_itemf(bContext *UNUSED(C), P
return item;
}
-static void rna_Node_scene_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Node_view_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_Node_update(bmain, scene, ptr);
if (scene->nodetree != NULL) {
@@ -3012,7 +3028,7 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
bNode *node = (bNode *)ptr->data;
- RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
+ RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
if (engine_type && engine_type->update_script_node) {
/* auto update node */
@@ -3113,6 +3129,7 @@ static int point_density_vertex_color_source_from_shader(NodeShaderTexPointDensi
void rna_ShaderNodePointDensity_density_cache(bNode *self,
Scene *scene,
+ ViewLayer *view_layer,
int settings)
{
NodeShaderTexPointDensity *shader_point_density = self->storage;
@@ -3150,12 +3167,13 @@ void rna_ShaderNodePointDensity_density_cache(bNode *self,
/* Single-threaded sampling of the voxel domain. */
RE_point_density_cache(scene,
- pd,
+ view_layer, pd,
settings == 1);
}
void rna_ShaderNodePointDensity_density_calc(bNode *self,
Scene *scene,
+ ViewLayer *view_layer,
int settings,
int *length,
float **values)
@@ -3177,7 +3195,7 @@ void rna_ShaderNodePointDensity_density_calc(bNode *self,
}
/* Single-threaded sampling of the voxel domain. */
- RE_point_density_sample(scene, pd,
+ RE_point_density_sample(scene, view_layer, pd,
resolution,
settings == 1,
*values);
@@ -3190,6 +3208,7 @@ void rna_ShaderNodePointDensity_density_calc(bNode *self,
void rna_ShaderNodePointDensity_density_minmax(bNode *self,
Scene *scene,
+ ViewLayer *view_layer,
int settings,
float r_min[3],
float r_max[3])
@@ -3201,7 +3220,7 @@ void rna_ShaderNodePointDensity_density_minmax(bNode *self,
zero_v3(r_max);
return;
}
- RE_point_density_minmax(scene, pd, settings == 1, r_min, r_max);
+ RE_point_density_minmax(scene, view_layer, pd, settings == 1, r_min, r_max);
}
#else
@@ -3216,7 +3235,7 @@ static const EnumPropertyItem prop_image_view_items[] = {
{0, NULL, 0, NULL, NULL}
};
-static const EnumPropertyItem prop_scene_layer_items[] = {
+static const EnumPropertyItem prop_view_layer_items[] = {
{ 0, "PLACEHOLDER", 0, "Placeholder", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -4185,11 +4204,13 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
func = RNA_def_function(srna, "cache_point_density", "rna_ShaderNodePointDensity_density_cache");
RNA_def_function_ui_description(func, "Cache point density data for later calculation");
RNA_def_pointer(func, "scene", "Scene", "", "");
+ RNA_def_pointer(func, "view_layer", "ViewLayer", "", "");
RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
func = RNA_def_function(srna, "calc_point_density", "rna_ShaderNodePointDensity_density_calc");
RNA_def_function_ui_description(func, "Calculate point density");
RNA_def_pointer(func, "scene", "Scene", "", "");
+ RNA_def_pointer(func, "view_layer", "ViewLayer", "", "");
RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
/* TODO, See how array size of 0 works, this shouldnt be used. */
parm = RNA_def_float_array(func, "rgba_values", 1, NULL, 0, 0, "", "RGBA Values", 0, 0);
@@ -4199,6 +4220,7 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
func = RNA_def_function(srna, "calc_point_density_minmax", "rna_ShaderNodePointDensity_density_minmax");
RNA_def_function_ui_description(func, "Calculate point density");
RNA_def_pointer(func, "scene", "Scene", "", "");
+ RNA_def_pointer(func, "view_layer", "ViewLayer", "", "");
RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
parm = RNA_def_property(func, "min", PROP_FLOAT, PROP_COORDS);
RNA_def_property_array(parm, 3);
@@ -4835,15 +4857,15 @@ static void def_cmp_render_layers(StructRNA *srna)
RNA_def_property_struct_type(prop, "Scene");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Scene", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_scene_layer_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_view_layer_update");
prop = RNA_def_property(srna, "layer", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "custom1");
- RNA_def_property_enum_items(prop, prop_scene_layer_items);
- RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Node_scene_layer_itemf");
+ RNA_def_property_enum_items(prop, prop_view_layer_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Node_view_layer_itemf");
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
RNA_def_property_ui_text(prop, "Layer", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_scene_layer_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_view_layer_update");
}
static void rna_def_cmp_output_file_slot_file(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 52bcb29d21f..a153590f4ac 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -47,6 +47,7 @@
#include "BKE_editmesh.h"
#include "BKE_group.h" /* needed for BKE_group_object_exists() */
#include "BKE_object_deform.h"
+#include "BKE_object_facemap.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -96,16 +97,27 @@ static const EnumPropertyItem parent_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
-#ifndef RNA_RUNTIME
+#define DUPLI_ITEMS_SHARED \
+ {0, "NONE", 0, "None", ""}, \
+ {OB_DUPLIFRAMES, "FRAMES", 0, "Frames", "Make copy of object for every frame"}, \
+ {OB_DUPLIVERTS, "VERTS", 0, "Verts", "Duplicate child objects on all vertices"}, \
+ {OB_DUPLIFACES, "FACES", 0, "Faces", "Duplicate child objects on all faces"}
+
+#define DUPLI_ITEM_GROUP \
+ {OB_DUPLIGROUP, "GROUP", 0, "Group", "Enable group instancing"}
static const EnumPropertyItem dupli_items[] = {
- {0, "NONE", 0, "None", ""},
- {OB_DUPLIFRAMES, "FRAMES", 0, "Frames", "Make copy of object for every frame"},
- {OB_DUPLIVERTS, "VERTS", 0, "Verts", "Duplicate child objects on all vertices"},
- {OB_DUPLIFACES, "FACES", 0, "Faces", "Duplicate child objects on all faces"},
- {OB_DUPLIGROUP, "GROUP", 0, "Group", "Enable group instancing"},
+ DUPLI_ITEMS_SHARED,
+ DUPLI_ITEM_GROUP,
+ {0, NULL, 0, NULL, NULL}
+};
+#ifdef RNA_RUNTIME
+static EnumPropertyItem dupli_items_nogroup[] = {
+ DUPLI_ITEMS_SHARED,
{0, NULL, 0, NULL, NULL}
};
#endif
+#undef DUPLI_ITEMS_SHARED
+#undef DUPLI_ITEM_GROUP
static const EnumPropertyItem collision_bounds_items[] = {
{OB_BOUND_BOX, "BOX", ICON_MESH_CUBE, "Box", ""},
@@ -147,6 +159,7 @@ const EnumPropertyItem rna_enum_object_type_items[] = {
{OB_CAMERA, "CAMERA", 0, "Camera", ""},
{OB_LAMP, "LAMP", 0, "Lamp", ""},
{OB_SPEAKER, "SPEAKER", 0, "Speaker", ""},
+ {OB_LIGHTPROBE, "LIGHT_PROBE", 0, "Probe", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -181,7 +194,6 @@ const EnumPropertyItem rna_enum_object_axis_items[] = {
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_key.h"
@@ -192,6 +204,9 @@ const EnumPropertyItem rna_enum_object_axis_items[] = {
#include "BKE_scene.h"
#include "BKE_deform.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_object.h"
#include "ED_particle.h"
#include "ED_curve.h"
@@ -199,7 +214,7 @@ const EnumPropertyItem rna_enum_object_axis_items[] = {
static void rna_Object_internal_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DAG_id_tag_update(ptr->id.data, OB_RECALC_OB);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_OB);
}
static void rna_Object_matrix_world_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -211,7 +226,7 @@ static void rna_Object_matrix_world_update(Main *bmain, Scene *scene, PointerRNA
static void rna_Object_hide_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
- DAG_id_type_tag(bmain, ID_OB);
+ DEG_id_type_tag(bmain, ID_OB);
}
static void rna_Object_matrix_local_get(PointerRNA *ptr, float values[16])
@@ -254,7 +269,7 @@ static void rna_Object_matrix_basis_set(PointerRNA *ptr, const float values[16])
void rna_Object_internal_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->id.data);
}
@@ -269,7 +284,7 @@ static void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA
EDBM_mesh_load(ob);
EDBM_mesh_make(scene->toolsettings, ob, true);
- DAG_id_tag_update(ob->data, 0);
+ DEG_id_tag_update(ob->data, 0);
EDBM_mesh_normals_update(((Mesh *)ob->data)->edit_btmesh);
BKE_editmesh_tessface_calc(((Mesh *)ob->data)->edit_btmesh);
@@ -291,75 +306,11 @@ static void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA
static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- DAG_id_tag_update(ptr->id.data, OB_RECALC_OB);
- DAG_relations_tag_update(bmain);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_OB);
+ DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_OBJECT | ND_PARENT, ptr->id.data);
}
-/* 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;
- ED_base_object_select(base, mode);
-}
-
-static void rna_Object_layer_update__internal(Main *bmain, Scene *scene, Base *base, Object *ob)
-{
- /* try to avoid scene sort */
- if (scene == NULL) {
- /* pass - unlikely but when running scripts on startup it happens */
- }
- else if ((ob->lay & scene->lay) && (base->lay & scene->lay)) {
- /* pass */
- }
- else if ((ob->lay & scene->lay) == 0 && (base->lay & scene->lay) == 0) {
- /* pass */
- }
- else {
- DAG_relations_tag_update(bmain);
- }
-
- DAG_id_type_tag(bmain, ID_OB);
-}
-
-static void rna_Object_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->id.data;
- Base *base;
-
- base = scene ? BKE_scene_base_find(scene, ob) : NULL;
- if (!base)
- return;
-
- SWAP(unsigned int, base->lay, ob->lay);
-
- rna_Object_layer_update__internal(bmain, scene, base, ob);
- ob->lay = base->lay;
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, scene);
-}
-
-static void rna_Base_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- Base *base = (Base *)ptr->data;
- Object *ob = (Object *)base->object;
-
- rna_Object_layer_update__internal(bmain, scene, base, ob);
- ob->lay = base->lay;
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, scene);
-}
-
static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
{
Object *ob = (Object *)ptr->data;
@@ -424,6 +375,7 @@ static StructRNA *rna_Object_data_typef(PointerRNA *ptr)
case OB_LATTICE: return &RNA_Lattice;
case OB_ARMATURE: return &RNA_Armature;
case OB_SPEAKER: return &RNA_Speaker;
+ case OB_LIGHTPROBE: return &RNA_LightProbe;
default: return &RNA_ID;
}
}
@@ -519,6 +471,23 @@ static void rna_Object_parent_bone_set(PointerRNA *ptr, const char *value)
ED_object_parent(ob, ob->parent, ob->partype, value);
}
+static const EnumPropertyItem *rna_Object_dupli_type_itemf(
+ bContext *UNUSED(C), PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
+{
+ Object *ob = (Object *)ptr->data;
+ const EnumPropertyItem *item;
+
+ if (ob->type == OB_EMPTY) {
+ item = dupli_items;
+ }
+ else {
+ item = dupli_items_nogroup;
+ }
+
+ return item;
+}
+
static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value)
{
Object *ob = (Object *)ptr->data;
@@ -528,9 +497,15 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value)
* thus causing a cycle/infinite-recursion leading to crashes on load [#25298]
*/
if (BKE_group_object_exists(grp, ob) == 0) {
- id_us_min(&ob->dup_group->id);
- ob->dup_group = grp;
- id_us_plus(&ob->dup_group->id);
+ if (ob->type == OB_EMPTY) {
+ id_us_min(&ob->dup_group->id);
+ ob->dup_group = grp;
+ id_us_plus(&ob->dup_group->id);
+ }
+ else {
+ BKE_report(NULL, RPT_ERROR,
+ "Only empty objects support group instances");
+ }
}
else {
BKE_report(NULL, RPT_ERROR,
@@ -618,6 +593,87 @@ void rna_object_vgroup_name_set(PointerRNA *ptr, const char *value, char *result
result[0] = '\0';
}
+static void rna_FaceMap_name_set(PointerRNA *ptr, const char *value)
+{
+ Object *ob = (Object *)ptr->id.data;
+ bFaceMap *fmap = (bFaceMap *)ptr->data;
+ BLI_strncpy_utf8(fmap->name, value, sizeof(fmap->name));
+ BKE_object_facemap_unique_name(ob, fmap);
+}
+
+static int rna_FaceMap_index_get(PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->id.data;
+
+ return BLI_findindex(&ob->fmaps, ptr->data);
+}
+
+static PointerRNA rna_Object_active_face_map_get(PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->id.data;
+ return rna_pointer_inherit_refine(ptr, &RNA_FaceMap, BLI_findlink(&ob->fmaps, ob->actfmap - 1));
+}
+
+static int rna_Object_active_face_map_index_get(PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->id.data;
+ return ob->actfmap - 1;
+}
+
+static void rna_Object_active_face_map_index_set(PointerRNA *ptr, int value)
+{
+ Object *ob = (Object *)ptr->id.data;
+ ob->actfmap = value + 1;
+}
+
+static void rna_Object_active_face_map_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
+{
+ Object *ob = (Object *)ptr->id.data;
+
+ *min = 0;
+ *max = max_ii(0, BLI_listbase_count(&ob->fmaps) - 1);
+}
+
+void rna_object_BKE_object_facemap_name_index_get(PointerRNA *ptr, char *value, int index)
+{
+ Object *ob = (Object *)ptr->id.data;
+ bFaceMap *fmap;
+
+ fmap = BLI_findlink(&ob->fmaps, index - 1);
+
+ if (fmap) BLI_strncpy(value, fmap->name, sizeof(fmap->name));
+ else value[0] = '\0';
+}
+
+int rna_object_BKE_object_facemap_name_index_length(PointerRNA *ptr, int index)
+{
+ Object *ob = (Object *)ptr->id.data;
+ bFaceMap *fmap;
+
+ fmap = BLI_findlink(&ob->fmaps, index - 1);
+ return (fmap) ? strlen(fmap->name) : 0;
+}
+
+void rna_object_BKE_object_facemap_name_index_set(PointerRNA *ptr, const char *value, short *index)
+{
+ Object *ob = (Object *)ptr->id.data;
+ *index = BKE_object_facemap_name_index(ob, value) + 1;
+}
+
+void rna_object_fmap_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen)
+{
+ Object *ob = (Object *)ptr->id.data;
+ bFaceMap *fmap = BKE_object_facemap_find_name(ob, value);
+ if (fmap) {
+ BLI_strncpy(result, value, maxlen); /* no need for BLI_strncpy_utf8, since this matches an existing group */
+ return;
+ }
+
+ result[0] = '\0';
+}
+
+
void rna_object_uvlayer_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen)
{
Object *ob = (Object *)ptr->id.data;
@@ -628,10 +684,10 @@ void rna_object_uvlayer_name_set(PointerRNA *ptr, const char *value, char *resul
if (ob->type == OB_MESH && ob->data) {
me = (Mesh *)ob->data;
- for (a = 0; a < me->pdata.totlayer; a++) {
- layer = &me->pdata.layers[a];
+ for (a = 0; a < me->ldata.totlayer; a++) {
+ layer = &me->ldata.layers[a];
- if (layer->type == CD_MTEXPOLY && STREQ(layer->name, value)) {
+ if (layer->type == CD_MLOOPUV && STREQ(layer->name, value)) {
BLI_strncpy(result, value, maxlen);
return;
}
@@ -705,7 +761,7 @@ static void rna_Object_active_material_set(PointerRNA *ptr, PointerRNA value)
{
Object *ob = (Object *)ptr->id.data;
- DAG_id_tag_update(value.data, 0);
+ DEG_id_tag_update(value.data, 0);
assign_material(ob, value.data, ob->actcol, BKE_MAT_ASSIGN_EXISTING);
}
@@ -747,9 +803,14 @@ static void rna_Object_active_particle_system_index_set(PointerRNA *ptr, int val
static void rna_Object_particle_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
{
+ /* TODO: Disabled for now, because bContext is not available. */
+#if 0
Object *ob = (Object *)ptr->id.data;
-
- PE_current_changed(scene, ob);
+ PE_current_changed(NULL, scene, ob);
+#else
+ (void) scene;
+ (void) ptr;
+#endif
}
/* rotation - axis-angle */
@@ -938,7 +999,7 @@ static void rna_MaterialSlot_update(Main *bmain, Scene *scene, PointerRNA *ptr)
WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, ptr->id.data);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
static char *rna_MaterialSlot_path(PointerRNA *ptr)
@@ -1065,7 +1126,7 @@ static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value)
if ((gameflag_prev & OB_NAVMESH) != (ob->gameflag & OB_NAVMESH)) {
if (ob->type == OB_MESH) {
/* this is needed to refresh the derived meshes draw func */
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
}
}
@@ -1084,49 +1145,6 @@ static PointerRNA rna_Object_game_settings_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_GameObjectSettings, ptr->id.data);
}
-
-static unsigned int rna_Object_layer_validate__internal(const int *values, unsigned int lay)
-{
- int i, tot = 0;
-
- /* ensure we always have some layer selected */
- for (i = 0; i < 20; i++)
- if (values[i])
- tot++;
-
- if (tot == 0)
- return 0;
-
- for (i = 0; i < 20; i++) {
- if (values[i]) lay |= (1 << i);
- else lay &= ~(1 << i);
- }
-
- return lay;
-}
-
-static void rna_Object_layer_set(PointerRNA *ptr, const int *values)
-{
- Object *ob = (Object *)ptr->data;
- unsigned int lay;
-
- lay = rna_Object_layer_validate__internal(values, ob->lay);
- if (lay)
- ob->lay = lay;
-}
-
-static void rna_Base_layer_set(PointerRNA *ptr, const int *values)
-{
- Base *base = (Base *)ptr->data;
-
- unsigned int lay;
- lay = rna_Object_layer_validate__internal(values, base->lay);
- if (lay)
- base->lay = lay;
-
- /* rna_Base_layer_update updates the objects layer */
-}
-
static void rna_GameObjectSettings_state_get(PointerRNA *ptr, int *values)
{
Object *ob = (Object *)ptr->data;
@@ -1462,6 +1480,69 @@ static float rna_VertexGroup_weight(ID *id, bDeformGroup *dg, ReportList *report
return weight;
}
+static bFaceMap *rna_Object_fmap_new(Object *ob, const char *name)
+{
+ bFaceMap *fmap = BKE_object_facemap_add_name(ob, name);
+
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+
+ return fmap;
+}
+
+static void rna_Object_fmap_remove(Object *ob, ReportList *reports, PointerRNA *fmap_ptr)
+{
+ bFaceMap *fmap = fmap_ptr->data;
+ if (BLI_findindex(&ob->fmaps, fmap) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "FaceMap '%s' not in object '%s'", fmap->name, ob->id.name + 2);
+ return;
+ }
+
+ BKE_object_facemap_remove(ob, fmap);
+ RNA_POINTER_INVALIDATE(fmap_ptr);
+
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+}
+
+
+static void rna_Object_fmap_clear(Object *ob)
+{
+ BKE_object_facemap_clear(ob);
+
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+}
+
+
+static void rna_FaceMap_face_add(ID *id, bFaceMap *fmap, ReportList *reports, int index_len,
+ int *index)
+{
+ Object *ob = (Object *)id;
+
+ if (BKE_object_is_in_editmode(ob)) {
+ BKE_report(reports, RPT_ERROR, "FaceMap.add(): cannot be called while object is in edit mode");
+ return;
+ }
+
+ while (index_len--)
+ ED_object_facemap_face_add(ob, fmap, *index++);
+
+ WM_main_add_notifier(NC_GEOM | ND_DATA, (ID *)ob->data);
+}
+
+static void rna_FaceMap_face_remove(ID *id, bFaceMap *fmap, ReportList *reports, int index_len, int *index)
+{
+ Object *ob = (Object *)id;
+
+ if (BKE_object_is_in_editmode(ob)) {
+ BKE_report(reports, RPT_ERROR, "FaceMap.add(): cannot be called while object is in edit mode");
+ return;
+ }
+
+ while (index_len--)
+ ED_object_facemap_face_remove(ob, fmap, *index++);
+
+ WM_main_add_notifier(NC_GEOM | ND_DATA, (ID *)ob->data);
+}
+
/* generic poll functions */
int rna_Lattice_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
@@ -1581,6 +1662,49 @@ static void rna_def_vertex_group(BlenderRNA *brna)
RNA_def_function_return(func, parm);
}
+static void rna_def_face_map(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ FunctionRNA *func;
+
+ srna = RNA_def_struct(brna, "FaceMap", NULL);
+ RNA_def_struct_sdna(srna, "bFaceMap");
+ RNA_def_struct_ui_text(srna, "Face Map", "Group of faces, each face can only be part of one map");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_TRIANGULATE);
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Face map name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_FaceMap_name_set");
+ /* update data because modifiers may use [#24761] */
+ RNA_def_property_update(prop, NC_GEOM | ND_DATA | NA_RENAME, "rna_Object_internal_update_data");
+
+ 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", "Face-map selection state (for tools to use)");
+ /* important not to use a notifier here, creates a feedback loop! */
+
+ prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_int_funcs(prop, "rna_FaceMap_index_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Index", "Index number of the face map");
+
+ func = RNA_def_function(srna, "add", "rna_FaceMap_face_add");
+ RNA_def_function_ui_description(func, "Add vertices to the group");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
+ /* TODO, see how array size of 0 works, this shouldnt be used */
+ prop = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "Index List", 0, 0);
+ RNA_def_parameter_flags(prop, PROP_DYNAMIC, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "remove", "rna_FaceMap_face_remove");
+ RNA_def_function_ui_description(func, "Remove a vertex from the group");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
+ /* TODO, see how array size of 0 works, this shouldnt be used */
+ prop = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "Index List", 0, 0);
+ RNA_def_parameter_flags(prop, PROP_DYNAMIC, PARM_REQUIRED);
+}
+
static void rna_def_material_slot(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2108,6 +2232,54 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Delete all vertex groups from object");
}
+/* object.face_maps */
+static void rna_def_object_face_maps(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ PropertyRNA *prop;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "FaceMaps");
+ srna = RNA_def_struct(brna, "FaceMaps", NULL);
+ RNA_def_struct_sdna(srna, "Object");
+ RNA_def_struct_ui_text(srna, "Face Maps", "Collection of face maps");
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "FaceMap");
+ RNA_def_property_pointer_funcs(prop, "rna_Object_active_face_map_get",
+ "rna_Object_active_face_map_set", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Active Face Map", "Face maps of the object");
+ RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Object_internal_update_data");
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_int_sdna(prop, NULL, "actfmap");
+ RNA_def_property_int_funcs(prop, "rna_Object_active_face_map_index_get",
+ "rna_Object_active_face_map_index_set",
+ "rna_Object_active_face_map_index_range");
+ RNA_def_property_ui_text(prop, "Active Face Map Index", "Active index in face map array");
+ RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Object_internal_update_data");
+
+ /* face maps */ /* add_face_map */
+ func = RNA_def_function(srna, "new", "rna_Object_fmap_new");
+ RNA_def_function_ui_description(func, "Add face map to object");
+ RNA_def_string(func, "name", "Map", 0, "", "face map name"); /* optional */
+ parm = RNA_def_pointer(func, "fmap", "FaceMap", "", "New face map");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Object_fmap_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Delete vertex group from object");
+ parm = RNA_def_pointer(func, "group", "FaceMap", "", "Face map to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+
+ func = RNA_def_function(srna, "clear", "rna_Object_fmap_clear");
+ RNA_def_function_ui_description(func, "Delete all vertex groups from object");
+}
static void rna_def_object_lodlevel(BlenderRNA *brna)
{
@@ -2232,26 +2404,12 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Mode", "Object interaction mode");
- prop = RNA_def_property(srna, "layers", PROP_BOOLEAN, PROP_LAYER_MEMBER);
- RNA_def_property_boolean_sdna(prop, NULL, "lay", 1);
- RNA_def_property_array(prop, 20);
- RNA_def_property_ui_text(prop, "Layers", "Layers the object is on");
- RNA_def_property_boolean_funcs(prop, NULL, "rna_Object_layer_set");
- RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_layer_update");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-
prop = RNA_def_property(srna, "layers_local_view", PROP_BOOLEAN, PROP_LAYER_MEMBER);
RNA_def_property_boolean_sdna(prop, NULL, "lay", 0x01000000);
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 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);
@@ -2264,7 +2422,7 @@ static void rna_def_object(BlenderRNA *brna)
/* parent */
prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_funcs(prop, NULL, "rna_Object_parent_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK | PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Parent", "Parent Object");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_dependency_update");
@@ -2342,6 +2500,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_float_sdna(prop, NULL, "loc");
RNA_def_property_editable_array_func(prop, "rna_Object_location_editable");
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Location", "Location of the object");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update");
@@ -2349,6 +2508,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "rotation_quaternion", PROP_FLOAT, PROP_QUATERNION);
RNA_def_property_float_sdna(prop, NULL, "quat");
RNA_def_property_editable_array_func(prop, "rna_Object_rotation_4d_editable");
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_float_array_default(prop, default_quat);
RNA_def_property_ui_text(prop, "Quaternion Rotation", "Rotation in Quaternions");
RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update");
@@ -2362,12 +2522,14 @@ static void rna_def_object(BlenderRNA *brna)
"rna_Object_rotation_axis_angle_set", NULL);
RNA_def_property_editable_array_func(prop, "rna_Object_rotation_4d_editable");
RNA_def_property_float_array_default(prop, default_axisAngle);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Axis-Angle Rotation", "Angle of Rotation for Axis-Angle rotation representation");
RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update");
prop = RNA_def_property(srna, "rotation_euler", PROP_FLOAT, PROP_EULER);
RNA_def_property_float_sdna(prop, NULL, "rot");
RNA_def_property_editable_array_func(prop, "rna_Object_rotation_euler_editable");
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Euler Rotation", "Rotation in Eulers");
RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update");
@@ -2380,7 +2542,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "size");
- RNA_def_property_flag(prop, PROP_PROPORTIONAL);
+ RNA_def_property_flag(prop, PROP_PROPORTIONAL | PROP_OVERRIDABLE_STATIC);
RNA_def_property_editable_array_func(prop, "rna_Object_scale_editable");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 3);
RNA_def_property_float_array_default(prop, default_scale);
@@ -2507,6 +2669,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Modifier");
RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting the geometric data of the object");
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
rna_def_object_modifiers(brna, prop);
/* constraints */
@@ -2530,6 +2693,14 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vertex Groups", "Vertex groups of the object");
rna_def_object_vertex_groups(brna, prop);
+
+ /* face maps */
+ prop = RNA_def_property(srna, "face_maps", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "fmaps", NULL);
+ RNA_def_property_struct_type(prop, "FaceMap");
+ RNA_def_property_ui_text(prop, "Face Maps", "Maps of faces of the object");
+ rna_def_object_face_maps(brna, prop);
+
/* empty */
prop = RNA_def_property(srna, "empty_draw_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "empty_drawtype");
@@ -2624,6 +2795,18 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update");
+ /* Keep it in sync with BKE_object_is_visible. */
+ prop = RNA_def_property(srna, "is_visible", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "base_flag", BASE_VISIBLED);
+ RNA_def_property_ui_text(prop, "Visible", "Visible to camera rays, set only on objects evaluated by depsgraph");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "collection_properties", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "base_collection_properties->data.group", NULL);
+ RNA_def_property_struct_type(prop, "LayerCollectionSettings");
+ RNA_def_property_ui_text(prop, "Collection Settings",
+ "Engine specific render settings to be overridden by collections");
+
/* anim */
rna_def_animdata_common(srna);
@@ -2658,6 +2841,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "dupli_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "transflag");
RNA_def_property_enum_items(prop, dupli_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Object_dupli_type_itemf");
RNA_def_property_ui_text(prop, "Dupli Type", "If not None, object duplication method to use");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_dependency_update");
@@ -2798,6 +2982,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "pose", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "pose");
RNA_def_property_struct_type(prop, "Pose");
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Pose", "Current pose for armatures");
/* shape keys */
@@ -2839,6 +3024,17 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Level of Detail Levels", "A collection of detail levels to automatically switch between");
RNA_def_property_update(prop, NC_OBJECT | ND_LOD, NULL);
+ /* Base Settings */
+ prop = RNA_def_property(srna, "is_from_duplicator", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "base_flag", BASE_FROMDUPLI);
+ RNA_def_property_ui_text(prop, "Base from Duplicator", "Object comes from a duplicator");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "is_from_set", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "base_flag", BASE_FROM_SET);
+ RNA_def_property_ui_text(prop, "Base from Set", "Object comes from a background set");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
RNA_api_object(srna);
}
@@ -2900,50 +3096,14 @@ static void rna_def_dupli_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Dupli random id", "Random id for this dupli object");
}
-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 scene");
- 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");
-
- /* same as object layer */
- prop = RNA_def_property(srna, "layers", PROP_BOOLEAN, PROP_LAYER_MEMBER);
- RNA_def_property_boolean_sdna(prop, NULL, "lay", 1);
- RNA_def_property_array(prop, 20);
- RNA_def_property_ui_text(prop, "Layers", "Layers the object base is on");
- RNA_def_property_boolean_funcs(prop, NULL, "rna_Base_layer_set");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Base_layer_update");
-
- prop = RNA_def_property(srna, "layers_local_view", PROP_BOOLEAN, PROP_LAYER_MEMBER);
- RNA_def_property_boolean_sdna(prop, NULL, "lay", 0x01000000);
- 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_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);
-}
-
void RNA_def_object(BlenderRNA *brna)
{
rna_def_object(brna);
RNA_define_animate_sdna(false);
rna_def_object_game_settings(brna);
- rna_def_object_base(brna);
rna_def_vertex_group(brna);
+ rna_def_face_map(brna);
rna_def_material_slot(brna);
rna_def_dupli_object(brna);
RNA_define_animate_sdna(true);
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 1d58a4a6350..74528a2c0e8 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -40,10 +40,13 @@
#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 "DEG_depsgraph.h"
#include "rna_internal.h" /* own include */
@@ -88,7 +91,61 @@ static const EnumPropertyItem space_items[] = {
#include "MEM_guardedalloc.h"
-#include "DEG_depsgraph.h"
+static void rna_Object_select_set(Object *ob, bContext *C, ReportList *reports, int action)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (!base) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, view_layer->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_view_layer_base_select(view_layer, base);
+ break;
+ }
+}
+
+static int rna_Object_select_get(Object *ob, bContext *C, ReportList *reports)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (!base) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, view_layer->name);
+ return -1;
+ }
+
+ return ((base->flag & BASE_SELECTED) != 0) ? 1 : 0;
+}
+
+static int rna_Object_visible_get(Object *ob, bContext *C, ReportList *reports)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (!base) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, view_layer->name);
+ return -1;
+ }
+
+ return ((base->flag & BASE_VISIBLED) != 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,
@@ -140,14 +197,16 @@ static void rna_Object_camera_fit_coords(
/* copied from Mesh_getFromObject and adapted to RNA interface */
/* settings: 0 - preview, 1 - render */
static Mesh *rna_Object_to_mesh(
- Object *ob, ReportList *reports, Scene *sce,
+ Object *ob, bContext *C, ReportList *reports, Scene *sce, ViewLayer *view_layer,
int apply_modifiers, int settings, int calc_tessface, int calc_undeformed)
{
- return rna_Main_meshes_new_from_object(G.main, reports, sce, ob, apply_modifiers, settings, calc_tessface, calc_undeformed);
+ Main *bmain = CTX_data_main(C);
+
+ return rna_Main_meshes_new_from_object(bmain, reports, sce, view_layer, ob, apply_modifiers, settings, calc_tessface, calc_undeformed);
}
/* mostly a copy from convertblender.c */
-static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int enable)
+static void dupli_render_particle_set(EvaluationContext *eval_ctx, Scene *scene, Object *ob, int level, int enable)
{
/* ugly function, but we need to set particle systems to their render
* settings before calling object_duplilist, to get render level duplis */
@@ -176,7 +235,7 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e
/* this is to make sure we get render level duplis in groups:
* the derivedmesh must be created before init_render_mesh,
* since object_duplilist does dupliparticles before that */
- dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL);
+ dm = mesh_create_derived_render(eval_ctx, scene, ob, CD_MASK_BAREMESH | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL);
dm->release(dm);
for (psys = ob->particlesystem.first; psys; psys = psys->next)
@@ -188,14 +247,17 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e
group = ob->dup_group;
for (go = group->gobject.first; go; go = go->next)
- dupli_render_particle_set(scene, go->ob, level + 1, enable);
+ dupli_render_particle_set(eval_ctx, scene, go->ob, level + 1, enable);
}
/* When no longer needed, duplilist should be freed with Object.free_duplilist */
-static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce, int settings)
+static void rna_Object_create_duplilist(Object *ob, bContext *C, ReportList *reports, Scene *sce, int settings)
{
bool for_render = (settings == DAG_EVAL_RENDER);
EvaluationContext eval_ctx;
- DEG_evaluation_context_init(&eval_ctx, settings);
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ eval_ctx.mode = settings;
if (!(ob->transflag & OB_DUPLI)) {
BKE_report(reports, RPT_ERROR, "Object does not have duplis");
@@ -210,10 +272,10 @@ static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *
ob->duplilist = NULL;
}
if (for_render)
- dupli_render_particle_set(sce, ob, 0, 1);
+ dupli_render_particle_set(&eval_ctx, sce, ob, 0, 1);
ob->duplilist = object_duplilist(&eval_ctx, sce, ob);
if (for_render)
- dupli_render_particle_set(sce, ob, 0, 0);
+ dupli_render_particle_set(&eval_ctx, sce, ob, 0, 0);
/* ob->duplilist should now be freed with Object.free_duplilist */
}
@@ -261,17 +323,12 @@ static void rna_Object_shape_key_remove(
return;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
RNA_POINTER_INVALIDATE(kb_ptr);
}
-static int rna_Object_is_visible(Object *ob, Scene *sce)
-{
- return !(ob->restrictflag & OB_RESTRICT_VIEW) && (ob->lay & sce->lay);
-}
-
#if 0
static void rna_Mesh_assign_verts_to_group(Object *ob, bDeformGroup *group, int *indices, int totindex,
float weight, int assignmode)
@@ -419,13 +476,6 @@ finally:
free_bvhtree_from_mesh(&treeData);
}
-/* ObjectBase */
-
-static void rna_ObjectBase_layers_from_view(Base *base, View3D *v3d)
-{
- base->lay = base->object->lay = v3d->lay;
-}
-
static int rna_Object_is_modified(Object *ob, Scene *scene, int settings)
{
return BKE_object_is_modified(scene, ob) & settings;
@@ -510,6 +560,32 @@ 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);
+
+ func = RNA_def_function(srna, "visible_get", "rna_Object_visible_get");
+ RNA_def_function_ui_description(func, "Get the object visibility for the active render layer");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm = RNA_def_boolean(func, "result", 0, "", "Object visible");
+ 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");
@@ -561,9 +637,11 @@ void RNA_api_object(StructRNA *srna)
/* mesh */
func = RNA_def_function(srna, "to_mesh", "rna_Object_to_mesh");
RNA_def_function_ui_description(func, "Create a Mesh data-block with modifiers applied");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate modifiers");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "", "Scene layer within which to evaluate modifiers");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Modifier settings to apply");
@@ -582,7 +660,7 @@ void RNA_api_object(StructRNA *srna)
parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate duplis");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
RNA_def_enum(func, "settings", dupli_eval_mode_items, 0, "", "Generate texture coordinates for rendering");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
func = RNA_def_function(srna, "dupli_list_clear", "rna_Object_free_duplilist");
RNA_def_function_ui_description(func, "Free the list of dupli objects");
@@ -664,12 +742,6 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_output(func, parm);
/* View */
- func = RNA_def_function(srna, "is_visible", "rna_Object_is_visible");
- RNA_def_function_ui_description(func, "Determine if object is visible in a given scene");
- parm = RNA_def_pointer(func, "scene", "Scene", "", "");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_boolean(func, "result", 0, "", "Object visibility");
- RNA_def_function_return(func, parm);
/* utility function for checking if the object is modified */
func = RNA_def_function(srna, "is_modified", "rna_Object_is_modified");
@@ -712,17 +784,4 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_ui_description(func, "Release memory used by caches associated with this object. Intended to be used by render engines only");
}
-
-void RNA_api_object_base(StructRNA *srna)
-{
- FunctionRNA *func;
- PropertyRNA *parm;
-
- func = RNA_def_function(srna, "layers_from_view", "rna_ObjectBase_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", "", "");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
-}
-
#endif /* RNA_RUNTIME */
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 366de586fa5..031b0bdec99 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -94,10 +94,13 @@ static const EnumPropertyItem empty_vortex_shape_items[] = {
#include "DNA_modifier_types.h"
#include "DNA_texture_types.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_modifier.h"
#include "BKE_pointcache.h"
-#include "BKE_depsgraph.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
#include "ED_object.h"
@@ -115,7 +118,7 @@ static void rna_Cache_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
for (pid = pidlist.first; pid; pid = pid->next) {
if (pid->cache == cache)
@@ -184,7 +187,7 @@ static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), P
BKE_ptcache_load_external(pid);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, ob);
}
else {
@@ -499,7 +502,7 @@ static void rna_FieldSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
part->pd2->tex = NULL;
}
- DAG_id_tag_update(&part->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME | PSYS_RECALC_RESET);
+ DEG_id_tag_update(&part->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME | PSYS_RECALC_RESET);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
@@ -511,7 +514,7 @@ static void rna_FieldSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
ob->pd->tex = NULL;
}
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
}
@@ -547,7 +550,7 @@ static void rna_FieldSettings_type_set(PointerRNA *ptr, int value)
static void rna_FieldSettings_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
if (particle_id_check(ptr)) {
- DAG_id_tag_update((ID *)ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME | PSYS_RECALC_RESET);
+ DEG_id_tag_update((ID *)ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME | PSYS_RECALC_RESET);
}
else {
Object *ob = (Object *)ptr->id.data;
@@ -563,12 +566,12 @@ static void rna_FieldSettings_dependency_update(Main *bmain, Scene *scene, Point
rna_FieldSettings_shape_update(bmain, scene, ptr);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
if (ob->type == OB_CURVE && ob->pd->forcefield == PFIELD_GUIDE)
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
else
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
@@ -605,23 +608,23 @@ static void rna_EffectorWeight_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
if (id && GS(id->name) == ID_SCE) {
Scene *scene = (Scene *)id;
- Base *base;
-
- for (base = scene->base.first; base; base = base->next) {
- BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH);
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
}
+ FOREACH_SCENE_OBJECT_END
}
else {
- DAG_id_tag_update(id, OB_RECALC_DATA | PSYS_RECALC_RESET);
+ DEG_id_tag_update(id, OB_RECALC_DATA | PSYS_RECALC_RESET);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
}
static void rna_EffectorWeight_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
- DAG_id_tag_update((ID *)ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
+ DEG_id_tag_update((ID *)ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
@@ -718,7 +721,7 @@ static void rna_CollisionSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scen
{
Object *ob = (Object *)ptr->id.data;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
@@ -726,13 +729,13 @@ static void rna_softbody_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point
{
Object *ob = (Object *)ptr->id.data;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
}
static void rna_softbody_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
rna_softbody_update(bmain, scene, ptr);
}
@@ -1683,7 +1686,7 @@ static void rna_def_softbody(BlenderRNA *brna)
prop = RNA_def_property(srna, "spring_length", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "springpreload");
RNA_def_property_range(prop, 0.0f, 200.0f);
- RNA_def_property_ui_text(prop, "SL", "Alter spring length to shrink/blow up (unit %) 0 to disable");
+ RNA_def_property_ui_text(prop, "view_layer", "Alter spring length to shrink/blow up (unit %) 0 to disable");
RNA_def_property_update(prop, 0, "rna_softbody_update");
prop = RNA_def_property(srna, "aero", PROP_INT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 53fe84707d1..67eaa22fbe4 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -135,7 +135,6 @@ static const EnumPropertyItem part_hair_ren_as_items[] = {
#include "BKE_cloth.h"
#include "BKE_colortools.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_effect.h"
@@ -145,6 +144,9 @@ static const EnumPropertyItem part_hair_ren_as_items[] = {
#include "BKE_pointcache.h"
#include "BKE_texture.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
/* use for object space hair get/set */
static void rna_ParticleHairKey_location_object_info(PointerRNA *ptr, ParticleSystemModifierData **psmd_pt,
ParticleData **pa_pt)
@@ -612,8 +614,14 @@ static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, R
}
}
-static void rna_ParticleSystem_set_resolution(ParticleSystem *particlesystem, Scene *scene, Object *object, int resolution)
+static void rna_ParticleSystem_set_resolution(ParticleSystem *particlesystem, Scene *scene, ViewLayer *view_layer, Object *object, int resolution)
{
+ EvaluationContext eval_ctx;
+
+ DEG_evaluation_context_init(&eval_ctx, resolution);
+ eval_ctx.ctime = (float)scene->r.cfra + scene->r.subframe;
+ eval_ctx.view_layer = view_layer;
+
if (resolution == eModifierMode_Render) {
ParticleSystemModifierData *psmd = psys_get_modifier(object, particlesystem);
float mat[4][4];
@@ -622,7 +630,7 @@ static void rna_ParticleSystem_set_resolution(ParticleSystem *particlesystem, Sc
psys_render_set(object, particlesystem, mat, mat, 1, 1, 0.f);
psmd->flag &= ~eParticleSystemFlag_psys_updated;
- particle_system_update(scene, object, particlesystem, true);
+ particle_system_update(&eval_ctx, scene, object, particlesystem, true);
}
else {
ParticleSystemModifierData *psmd = psys_get_modifier(object, particlesystem);
@@ -632,7 +640,7 @@ static void rna_ParticleSystem_set_resolution(ParticleSystem *particlesystem, Sc
}
psmd->flag &= ~eParticleSystemFlag_psys_updated;
- particle_system_update(scene, object, particlesystem, false);
+ particle_system_update(&eval_ctx, scene, object, particlesystem, false);
}
}
@@ -643,10 +651,10 @@ static void particle_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN
psys->recalc = flag;
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
}
else
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA | flag);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA | flag);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
}
@@ -657,7 +665,7 @@ static void rna_Particle_redo(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Particle_redo_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
rna_Particle_redo(bmain, scene, ptr);
}
@@ -668,14 +676,14 @@ static void rna_Particle_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Particle_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
rna_Particle_reset(bmain, scene, ptr);
}
static void rna_Particle_change_type(Main *bmain, Scene *scene, PointerRNA *ptr)
{
particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET | PSYS_RECALC_TYPE);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
static void rna_Particle_change_physics(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -692,7 +700,7 @@ static void rna_Particle_cloth_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
{
Object *ob = (Object *)ptr->id.data;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
}
@@ -737,8 +745,8 @@ static void rna_Particle_target_reset(Main *bmain, Scene *UNUSED(scene), Pointer
psys->recalc = PSYS_RECALC_RESET;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- DAG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
}
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
@@ -753,7 +761,7 @@ static void rna_Particle_target_redo(Main *UNUSED(bmain), Scene *UNUSED(scene),
psys->recalc = PSYS_RECALC_REDO;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
}
}
@@ -774,9 +782,10 @@ static void rna_Particle_hair_dynamics_update(Main *bmain, Scene *scene, Pointer
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- DAG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_relations_tag_update(bmain);
}
+
static PointerRNA rna_particle_settings_get(PointerRNA *ptr)
{
ParticleSystem *psys = (ParticleSystem *)ptr->data;
@@ -2375,10 +2384,10 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Color", "Draw additional particle data as a color");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
- prop = RNA_def_property(srna, "draw_size", PROP_INT, PROP_PIXEL);
+ prop = RNA_def_property(srna, "draw_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0, 1000);
RNA_def_property_ui_range(prop, 0, 100, 1, -1);
- RNA_def_property_ui_text(prop, "Draw Size", "Size of particles on viewport in pixels (0=default)");
+ RNA_def_property_ui_text(prop, "Draw Size", "Size of particles on viewport in BU (0.1 = default)");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "child_type", PROP_ENUM, PROP_NONE);
@@ -3548,6 +3557,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
func = RNA_def_function(srna, "set_resolution", "rna_ParticleSystem_set_resolution");
RNA_def_function_ui_description(func, "Set the resolution to use for the number of particles");
RNA_def_pointer(func, "scene", "Scene", "", "Scene");
+ RNA_def_pointer(func, "view_layer", "ViewLayer", "", "ViewLayer");
RNA_def_pointer(func, "object", "Object", "", "Object");
RNA_def_enum(func, "resolution", resolution_items, 0, "", "Resolution settings to apply");
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index ac27a6c21a5..baf7f5e6aa3 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -106,9 +106,11 @@ const EnumPropertyItem rna_enum_color_sets_items[] = {
#include "BKE_context.h"
#include "BKE_constraint.h"
-#include "BKE_depsgraph.h"
#include "BKE_idprop.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_object.h"
#include "ED_armature.h"
@@ -120,7 +122,7 @@ static void rna_Pose_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN
{
/* XXX when to use this? ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); */
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
}
static void rna_Pose_IK_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -128,7 +130,7 @@ static void rna_Pose_IK_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe
/* XXX when to use this? ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); */
Object *ob = ptr->id.data;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
BIK_clear_data(ob->pose);
}
@@ -233,13 +235,13 @@ static void rna_Pose_ik_solver_update(Main *bmain, Scene *UNUSED(scene), Pointer
bPose *pose = ptr->data;
BKE_pose_tag_recalc(bmain, pose); /* checks & sorts pose channels */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
BKE_pose_update_constraint_flags(pose);
object_test_constraints(ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB);
}
/* rotation - axis-angle */
@@ -349,7 +351,7 @@ static void rna_Itasc_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
itasc->maxvel = 100.f;
BIK_update_param(ob->pose);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
static void rna_Itasc_update_rebuild(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -671,7 +673,7 @@ static void rna_PoseChannel_matrix_set(PointerRNA *ptr, const float *values)
Object *ob = (Object *)ptr->id.data;
float tmat[4][4];
- BKE_armature_mat_pose_to_bone_ex(ob, pchan, (float (*)[4])values, tmat);
+ BKE_armature_mat_pose_to_bone_ex(NULL, ob, pchan, (float (*)[4])values, tmat);
BKE_pchan_apply_mat4(pchan, tmat, false); /* no compat for predictable result */
}
@@ -837,6 +839,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
/* Transformation settings */
prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_float_sdna(prop, NULL, "loc");
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_editable_array_func(prop, "rna_PoseChannel_location_editable");
RNA_def_property_ui_text(prop, "Location", "");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
@@ -844,7 +847,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "size");
- RNA_def_property_flag(prop, PROP_PROPORTIONAL);
+ RNA_def_property_flag(prop, PROP_PROPORTIONAL | PROP_OVERRIDABLE_STATIC);
RNA_def_property_editable_array_func(prop, "rna_PoseChannel_scale_editable");
RNA_def_property_float_array_default(prop, default_scale);
RNA_def_property_ui_text(prop, "Scale", "");
@@ -852,6 +855,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
prop = RNA_def_property(srna, "rotation_quaternion", PROP_FLOAT, PROP_QUATERNION);
RNA_def_property_float_sdna(prop, NULL, "quat");
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_editable_array_func(prop, "rna_PoseChannel_rotation_4d_editable");
RNA_def_property_float_array_default(prop, default_quat);
RNA_def_property_ui_text(prop, "Quaternion Rotation", "Rotation in Quaternions");
@@ -861,6 +865,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
* having a single one is better for Keyframing and other property-management situations...
*/
prop = RNA_def_property(srna, "rotation_axis_angle", PROP_FLOAT, PROP_AXISANGLE);
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_array(prop, 4);
RNA_def_property_float_funcs(prop, "rna_PoseChannel_rotation_axis_angle_get",
"rna_PoseChannel_rotation_axis_angle_set", NULL);
@@ -871,6 +876,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
prop = RNA_def_property(srna, "rotation_euler", PROP_FLOAT, PROP_EULER);
RNA_def_property_float_sdna(prop, NULL, "eul");
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_editable_array_func(prop, "rna_PoseChannel_rotation_euler_editable");
RNA_def_property_ui_text(prop, "Euler Rotation", "Rotation in Eulers");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
@@ -1397,6 +1403,7 @@ static void rna_def_pose(BlenderRNA *brna)
prop = RNA_def_property(srna, "bones", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "chanbase", NULL);
RNA_def_property_struct_type(prop, "PoseBone");
+ RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC);
RNA_def_property_ui_text(prop, "Pose Bones", "Individual pose bones for the armature");
/* can be removed, only for fast lookup */
RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, "rna_PoseBones_lookup_string", NULL);
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index d3b3ed51981..15487082217 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -33,6 +33,8 @@
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
+#include "DEG_depsgraph.h"
+
#include "BKE_scene.h"
#include "BKE_image.h"
@@ -145,7 +147,7 @@ static void engine_unbind_display_space_shader(RenderEngine *UNUSED(engine))
IMB_colormanagement_finish_glsl_draw();
}
-static void engine_update(RenderEngine *engine, Main *bmain, Scene *scene)
+static void engine_update(RenderEngine *engine, Main *bmain, Depsgraph *graph, Scene *scene)
{
extern FunctionRNA rna_RenderEngine_update_func;
PointerRNA ptr;
@@ -157,24 +159,25 @@ static void engine_update(RenderEngine *engine, Main *bmain, Scene *scene)
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "data", &bmain);
+ RNA_parameter_set_lookup(&list, "depsgraph", &graph);
RNA_parameter_set_lookup(&list, "scene", &scene);
engine->type->ext.call(NULL, &ptr, func, &list);
RNA_parameter_list_free(&list);
}
-static void engine_render(RenderEngine *engine, struct Scene *scene)
+static void engine_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
{
- extern FunctionRNA rna_RenderEngine_render_func;
+ extern FunctionRNA rna_RenderEngine_render_to_image_func;
PointerRNA ptr;
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
- func = &rna_RenderEngine_render_func;
+ func = &rna_RenderEngine_render_to_image_func;
RNA_parameter_list_create(&list, &ptr, func);
- RNA_parameter_set_lookup(&list, "scene", &scene);
+ RNA_parameter_set_lookup(&list, "depsgraph", &depsgraph);
engine->type->ext.call(NULL, &ptr, func, &list);
RNA_parameter_list_free(&list);
@@ -225,15 +228,15 @@ static void engine_view_update(RenderEngine *engine, const struct bContext *cont
RNA_parameter_list_free(&list);
}
-static void engine_view_draw(RenderEngine *engine, const struct bContext *context)
+static void engine_render_to_view(RenderEngine *engine, const struct bContext *context)
{
- extern FunctionRNA rna_RenderEngine_view_draw_func;
+ extern FunctionRNA rna_RenderEngine_render_to_view_func;
PointerRNA ptr;
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
- func = &rna_RenderEngine_view_draw_func;
+ func = &rna_RenderEngine_render_to_view_func;
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "context", &context);
@@ -260,7 +263,24 @@ static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *nt
RNA_parameter_list_free(&list);
}
-static void engine_update_render_passes(RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl)
+static void engine_collection_settings_create(RenderEngine *engine, struct IDProperty *props)
+{
+ extern FunctionRNA rna_RenderEngine_collection_settings_create_func;
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
+ func = &rna_RenderEngine_collection_settings_create_func;
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "props", &props);
+ engine->type->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void engine_update_render_passes(RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer)
{
extern FunctionRNA rna_RenderEngine_update_render_passes_func;
PointerRNA ptr;
@@ -272,7 +292,7 @@ static void engine_update_render_passes(RenderEngine *engine, struct Scene *scen
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "scene", &scene);
- RNA_parameter_set_lookup(&list, "renderlayer", &srl);
+ RNA_parameter_set_lookup(&list, "renderlayer", &view_layer);
engine->type->ext.call(NULL, &ptr, func, &list);
RNA_parameter_list_free(&list);
@@ -302,7 +322,7 @@ static StructRNA *rna_RenderEngine_register(
RenderEngineType *et, dummyet = {NULL};
RenderEngine dummyengine = {NULL};
PointerRNA dummyptr;
- int have_function[7];
+ int have_function[8];
/* setup dummy engine & engine type to store static properties in */
dummyengine.type = &dummyet;
@@ -339,14 +359,15 @@ static StructRNA *rna_RenderEngine_register(
RNA_struct_blender_type_set(et->ext.srna, et);
et->update = (have_function[0]) ? engine_update : NULL;
- et->render = (have_function[1]) ? engine_render : NULL;
+ et->render_to_image = (have_function[1]) ? engine_render_to_image : NULL;
et->bake = (have_function[2]) ? engine_bake : NULL;
et->view_update = (have_function[3]) ? engine_view_update : NULL;
- et->view_draw = (have_function[4]) ? engine_view_draw : NULL;
+ et->render_to_view = (have_function[4]) ? engine_render_to_view : NULL;
et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL;
et->update_render_passes = (have_function[6]) ? engine_update_render_passes : NULL;
+ et->collection_settings_create = (have_function[7]) ? engine_collection_settings_create : NULL;
- BLI_addtail(&R_engines, et);
+ RE_engines_register(bmain, et);
return et->ext.srna;
}
@@ -377,6 +398,16 @@ static PointerRNA rna_RenderEngine_render_get(PointerRNA *ptr)
}
}
+static PointerRNA rna_RenderEngine_view_layer_get(PointerRNA *ptr)
+{
+ RenderEngine *engine = (RenderEngine *)ptr->data;
+ if (engine->re != NULL) {
+ ViewLayer *view_layer = RE_engine_get_view_layer(engine->re);
+ return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, view_layer);
+ }
+ return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, NULL);
+}
+
static PointerRNA rna_RenderEngine_camera_override_get(PointerRNA *ptr)
{
RenderEngine *engine = (RenderEngine *)ptr->data;
@@ -481,12 +512,13 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Export scene data for render");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
RNA_def_pointer(func, "data", "BlendData", "", "");
+ RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
RNA_def_pointer(func, "scene", "Scene", "", "");
- func = RNA_def_function(srna, "render", NULL);
+ func = RNA_def_function(srna, "render_to_image", NULL);
RNA_def_function_ui_description(func, "Render scene into an image");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
- RNA_def_pointer(func, "scene", "Scene", "", "");
+ RNA_def_pointer(func, "desgraph", "Depsgraph", "", "");
func = RNA_def_function(srna, "bake", NULL);
RNA_def_function_ui_description(func, "Bake passes");
@@ -517,7 +549,7 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
RNA_def_pointer(func, "context", "Context", "", "");
- func = RNA_def_function(srna, "view_draw", NULL);
+ func = RNA_def_function(srna, "render_to_view", NULL);
RNA_def_function_ui_description(func, "Draw viewport render");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
RNA_def_pointer(func, "context", "Context", "", "");
@@ -529,6 +561,19 @@ static void rna_def_render_engine(BlenderRNA *brna)
parm = RNA_def_pointer(func, "node", "Node", "", "");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+ func = RNA_def_function(srna, "update_render_passes", NULL);
+ RNA_def_function_ui_description(func, "Update the render passes that will be generated");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "scene", "Scene", "", "");
+ parm = RNA_def_pointer(func, "renderlayer", "ViewLayer", "", "");
+
+ /* 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", "LayerCollectionSettings", "", "");
+ 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");
@@ -537,12 +582,6 @@ static void rna_def_render_engine(BlenderRNA *brna)
func = RNA_def_function(srna, "tag_update", "engine_tag_update");
RNA_def_function_ui_description(func, "Request update call for viewport rendering");
- func = RNA_def_function(srna, "update_render_passes", NULL);
- RNA_def_function_ui_description(func, "Update the render passes that will be generated");
- RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
- parm = RNA_def_pointer(func, "scene", "Scene", "", "");
- parm = RNA_def_pointer(func, "renderlayer", "SceneRenderLayer", "", "");
-
func = RNA_def_function(srna, "begin_result", "RE_engine_begin_result");
RNA_def_function_ui_description(func, "Create render result to write linear floating point render layers and passes");
parm = RNA_def_int(func, "x", 0, 0, INT_MAX, "X", "", 0, INT_MAX);
@@ -719,7 +758,7 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Register a render pass that will be part of the render with the current settings");
prop = RNA_def_pointer(func, "scene", "Scene", "", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- prop = RNA_def_pointer(func, "srl", "SceneRenderLayer", "", "");
+ prop = RNA_def_pointer(func, "view_layer", "ViewLayer", "", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
prop = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
@@ -730,6 +769,11 @@ static void rna_def_render_engine(BlenderRNA *brna)
prop = RNA_def_enum(func, "type", render_pass_type_items, SOCK_FLOAT, "Type", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ prop = RNA_def_property(srna, "view_layer", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ViewLayer");
+ RNA_def_property_pointer_funcs(prop, "rna_RenderEngine_view_layer_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Scene layer", "");
+
/* registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
@@ -900,7 +944,7 @@ static void rna_def_render_layer(BlenderRNA *brna)
RNA_define_verify_sdna(0);
- rna_def_render_layer_common(srna, 0);
+ rna_def_view_layer_common(srna, 0);
prop = RNA_def_property(srna, "passes", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "RenderPass");
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
index 335b7d31acf..bc85e9c6503 100644
--- a/source/blender/makesrna/intern/rna_rigidbody.c
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -91,7 +91,6 @@ static const EnumPropertyItem rigidbody_mesh_source_items[] = {
# include "RBI_api.h"
#endif
-#include "BKE_depsgraph.h"
#include "BKE_rigidbody.h"
#include "WM_api.h"
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 507262675b3..24d56ef2a19 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -107,6 +107,8 @@ const EnumPropertyItem rna_enum_property_unit_items[] = {
#include "MEM_guardedalloc.h"
#include "BLI_ghash.h"
+#include "BKE_library_override.h"
+
/* Struct */
static void rna_Struct_identifier_get(PointerRNA *ptr, char *value)
@@ -564,6 +566,13 @@ static int rna_Property_animatable_get(PointerRNA *ptr)
return (prop->flag & PROP_ANIMATABLE) != 0;
}
+static int rna_Property_overridable_get(PointerRNA *ptr)
+{
+ PropertyRNA *prop = (PropertyRNA *)ptr->data;
+
+ return (prop->flag & PROP_OVERRIDABLE_STATIC) != 0;
+}
+
static int rna_Property_use_output_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
@@ -1082,6 +1091,1003 @@ static int rna_BlenderRNA_structs_lookup_string(PointerRNA *ptr, const char *key
return false;
}
+/* Default override (and compare) callbacks. */
+
+/* Used for both Pointer and Collection properties. */
+static int rna_property_override_equals_propptr(
+ PointerRNA *propptr_a, PointerRNA *propptr_b, eRNACompareMode mode,
+ IDOverrideStatic *override, const char *rna_path, bool *r_override_changed, const int flags)
+{
+ bool is_id = false;
+ bool is_type_null = false;
+
+ /* Beware, PointerRNA_NULL has no type and is considered a 'blank page'! */
+ if (propptr_a->type == NULL) {
+ if (propptr_b->type == NULL) {
+ if (r_override_changed) {
+ *r_override_changed = false;
+ }
+ return 0;
+ }
+ is_id = RNA_struct_is_ID(propptr_b->type);
+ is_type_null = true;
+ }
+ else {
+ is_id = RNA_struct_is_ID(propptr_a->type);
+ is_type_null = (propptr_b->type == NULL);
+ }
+
+ if (is_id) {
+ BLI_assert(propptr_a->data == propptr_a->id.data && propptr_b->data == propptr_b->id.data);
+ }
+
+ if (override) {
+ if (rna_path) {
+ if (is_type_null || is_id) {
+ /* In case this is an ID (or one of the pointers is NULL), do not compare structs!
+ * This is a quite safe path to infinite loop.
+ * Instead, just compare pointers themselves (we assume sub-ID structs cannot loop). */
+ const int comp = (propptr_a->data != propptr_b->data);
+
+ if (comp != 0 && rna_path) {
+ bool created = false;
+ IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
+
+ if (op != NULL && created) { /* If not yet overridden... */
+ BKE_override_static_property_operation_get(
+ op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
+ if (r_override_changed) {
+ *r_override_changed = created;
+ }
+ }
+ }
+
+ return comp;
+ }
+ else {
+ const bool changed = RNA_struct_auto_override(propptr_a, propptr_b, override, rna_path);
+ if (r_override_changed) {
+ *r_override_changed = *r_override_changed || changed;
+ }
+ /* XXX Simplification here, if no override was added we assume they are equal,
+ * this may not be good behavior, time will say. */
+ return !changed;
+ }
+ }
+ else {
+ return !RNA_struct_override_matches(
+ propptr_a, propptr_b, override,
+ flags & RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE,
+ flags & RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN);
+ }
+ }
+ else {
+ return !RNA_struct_equals(propptr_a, propptr_b, mode);
+ }
+}
+
+static char *rna_path_collection_prop_item_extend(const char *rna_path_prop, const char *item_name)
+{
+ const size_t esc_item_name_len = strlen(item_name) * 2;
+ char *esc_item_name = alloca(sizeof(*esc_item_name) * esc_item_name_len);
+ BLI_strescape(esc_item_name, item_name, esc_item_name_len);
+ return BLI_sprintfN("%s[\"%s\"]", rna_path_prop, esc_item_name);
+}
+
+int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b,
+ PropertyRNA *prop_a, PropertyRNA *prop_b,
+ const int len_a, const int len_b,
+ const int mode,
+ IDOverrideStatic *override, const char *rna_path,
+ const int flags, bool *r_override_changed)
+{
+ BLI_assert(len_a == len_b);
+
+ switch (RNA_property_type(prop_a)) {
+ case PROP_BOOLEAN:
+ {
+ if (len_a) {
+ int array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
+ int *array_a, *array_b;
+
+ array_a = (len_a > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(int) * len_a, "RNA equals") : array_stack_a;
+ array_b = (len_b > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(int) * len_b, "RNA equals") : array_stack_b;
+
+ RNA_property_boolean_get_array(ptr_a, prop_a, array_a);
+ RNA_property_boolean_get_array(ptr_b, prop_b, array_b);
+
+ const int comp = memcmp(array_a, array_b, sizeof(int) * len_a);
+
+ if (comp != 0 && rna_path) {
+ /* XXX TODO this will have to be refined to handle array items */
+ bool created = false;
+ IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
+
+ if (op != NULL && created) {
+ BKE_override_static_property_operation_get(
+ op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
+ if (r_override_changed) {
+ *r_override_changed = created;
+ }
+ }
+ else {
+ /* Already overriden prop, we'll have to check arrays items etc. */
+ }
+ }
+
+ if (array_a != array_stack_a) MEM_freeN(array_a);
+ if (array_b != array_stack_b) MEM_freeN(array_b);
+
+ return comp;
+ }
+ else {
+ const int value_a = RNA_property_boolean_get(ptr_a, prop_a);
+ const int value_b = RNA_property_boolean_get(ptr_b, prop_b);
+ const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0;
+
+ if (comp != 0 && rna_path) {
+ bool created = false;
+ IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
+
+ if (op != NULL && created) { /* If not yet overridden... */
+ BKE_override_static_property_operation_get(
+ op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
+ if (r_override_changed) {
+ *r_override_changed = created;
+ }
+ }
+ }
+
+ return comp;
+ }
+ }
+
+ case PROP_INT:
+ {
+ if (len_a) {
+ int array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
+ int *array_a, *array_b;
+
+ array_a = (len_a > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(int) * len_a, "RNA equals") : array_stack_a;
+ array_b = (len_b > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(int) * len_b, "RNA equals") : array_stack_b;
+
+ RNA_property_int_get_array(ptr_a, prop_a, array_a);
+ RNA_property_int_get_array(ptr_b, prop_b, array_b);
+
+ const int comp = memcmp(array_a, array_b, sizeof(int) * len_a);
+
+ if (comp != 0 && rna_path) {
+ /* XXX TODO this will have to be refined to handle array items */
+ bool created = false;
+ IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
+
+ if (op != NULL && created) {
+ BKE_override_static_property_operation_get(
+ op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
+ if (r_override_changed) {
+ *r_override_changed = created;
+ }
+ }
+ else {
+ /* Already overriden prop, we'll have to check arrays items etc. */
+ }
+ }
+
+ if (array_a != array_stack_a) MEM_freeN(array_a);
+ if (array_b != array_stack_b) MEM_freeN(array_b);
+
+ return comp;
+ }
+ else {
+ const int value_a = RNA_property_int_get(ptr_a, prop_a);
+ const int value_b = RNA_property_int_get(ptr_b, prop_b);
+ const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0;
+
+ if (comp != 0 && rna_path) {
+ bool created = false;
+ IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
+
+ if (op != NULL && created) { /* If not yet overridden... */
+ BKE_override_static_property_operation_get(
+ op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
+ if (r_override_changed) {
+ *r_override_changed = created;
+ }
+ }
+ }
+
+ return comp;
+ }
+ }
+
+ case PROP_FLOAT:
+ {
+ const bool is_proportional = (prop_a->flag & PROP_PROPORTIONAL) != 0;
+ if (len_a) {
+ float array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
+ float *array_a, *array_b;
+
+ array_a = (len_a > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(float) * len_a, "RNA equals") : array_stack_a;
+ array_b = (len_b > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(float) * len_b, "RNA equals") : array_stack_b;
+
+ RNA_property_float_get_array(ptr_a, prop_a, array_a);
+ RNA_property_float_get_array(ptr_b, prop_b, array_b);
+
+ const int comp = memcmp(array_a, array_b, sizeof(float) * len_a);
+
+ if (comp != 0 && rna_path) {
+ /* XXX TODO this will have to be refined to handle array items */
+ bool created = false;
+ IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
+
+ if (op != NULL && created) {
+ BKE_override_static_property_operation_get(
+ op, is_proportional ? IDOVERRIDESTATIC_OP_MULTIPLY : IDOVERRIDESTATIC_OP_REPLACE,
+ NULL, NULL, -1, -1, true, NULL, NULL);
+ if (r_override_changed) {
+ *r_override_changed = created;
+ }
+ }
+ else {
+ /* Already overriden prop, we'll have to check arrays items etc. */
+ }
+ }
+
+ if (array_a != array_stack_a) MEM_freeN(array_a);
+ if (array_b != array_stack_b) MEM_freeN(array_b);
+
+ return comp;
+ }
+ else {
+ const float value_a = RNA_property_float_get(ptr_a, prop_a);
+ const float value_b = RNA_property_float_get(ptr_b, prop_b);
+ const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0;
+
+ if (comp != 0 && rna_path) {
+ bool created = false;
+ IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
+
+ if (op != NULL && created) { /* If not yet overridden... */
+ BKE_override_static_property_operation_get(
+ op, is_proportional ? IDOVERRIDESTATIC_OP_MULTIPLY : IDOVERRIDESTATIC_OP_REPLACE,
+ NULL, NULL, -1, -1, true, NULL, NULL);
+ if (r_override_changed) {
+ *r_override_changed = created;
+ }
+ }
+ }
+
+ return comp ;
+ }
+ }
+
+ case PROP_ENUM:
+ {
+ const int value_a = RNA_property_enum_get(ptr_a, prop_a);
+ const int value_b = RNA_property_enum_get(ptr_b, prop_b);
+ const int comp = value_a != value_b;
+
+ if (comp != 0 && rna_path) {
+ bool created = false;
+ IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
+
+ if (op != NULL && created) { /* If not yet overridden... */
+ BKE_override_static_property_operation_get(
+ op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
+ if (r_override_changed) {
+ *r_override_changed = created;
+ }
+ }
+ }
+
+ return comp;
+ }
+
+ case PROP_STRING:
+ {
+ char fixed_a[128], fixed_b[128];
+ int len_str_a, len_str_b;
+ char *value_a = RNA_property_string_get_alloc(ptr_a, prop_a, fixed_a, sizeof(fixed_a), &len_str_a);
+ char *value_b = RNA_property_string_get_alloc(ptr_b, prop_b, fixed_b, sizeof(fixed_b), &len_str_b);
+ const int comp = strcmp(value_a, value_b);
+
+ if (comp != 0 && rna_path) {
+ bool created = false;
+ IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created);
+
+ if (op != NULL && created) { /* If not yet overridden... */
+ BKE_override_static_property_operation_get(
+ op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
+ if (r_override_changed) {
+ *r_override_changed = created;
+ }
+ }
+ }
+
+ if (value_a != fixed_a) MEM_freeN(value_a);
+ if (value_b != fixed_b) MEM_freeN(value_b);
+
+ return comp;
+ }
+
+ case PROP_POINTER:
+ {
+ if (STREQ(RNA_property_identifier(prop_a), "rna_type")) {
+ /* Dummy 'pass' answer, this is a meta-data and must be ignored... */
+ return 0;
+ }
+ else {
+ PointerRNA propptr_a = RNA_property_pointer_get(ptr_a, prop_a);
+ PointerRNA propptr_b = RNA_property_pointer_get(ptr_b, prop_b);
+ return rna_property_override_equals_propptr(
+ &propptr_a, &propptr_b, mode,
+ override, rna_path, r_override_changed, flags);
+ }
+ break;
+ }
+
+ case PROP_COLLECTION:
+ {
+ bool equals = true;
+ int idx = 0;
+
+ CollectionPropertyIterator iter_a, iter_b;
+ RNA_property_collection_begin(ptr_a, prop_a, &iter_a);
+ RNA_property_collection_begin(ptr_b, prop_b, &iter_b);
+
+ for (; iter_a.valid && iter_b.valid;
+ RNA_property_collection_next(&iter_a), RNA_property_collection_next(&iter_b), idx++)
+ {
+ char *extended_rna_path = NULL;
+
+ if (iter_a.ptr.type != iter_b.ptr.type) {
+ /* nothing we can do (for until we support adding/removing from collections), skip it. */
+ equals = false;
+ continue;
+ }
+
+ PropertyRNA *propname = RNA_struct_name_property(iter_a.ptr.type);
+ char propname_buff_a[256], propname_buff_b[256];
+ char *propname_a = NULL, *propname_b = NULL;
+
+ if (propname != NULL) {
+ propname_a = RNA_property_string_get_alloc(&iter_a.ptr, propname, propname_buff_a, sizeof(propname_buff_a), NULL);
+ propname_b = RNA_property_string_get_alloc(&iter_b.ptr, propname, propname_buff_b, sizeof(propname_buff_b), NULL);
+ if (!STREQ(propname_a, propname_b)) {
+ /* Same as above, not same structs. */
+ equals = false;
+ }
+ else if (rna_path) {
+ extended_rna_path = rna_path_collection_prop_item_extend(rna_path, propname_a);
+ }
+ }
+ else { /* Based on index... */
+ if (rna_path) {
+ extended_rna_path = BLI_sprintfN("%s[%d]", rna_path, idx);
+ }
+ }
+
+ if (equals) {
+ const int eq = rna_property_override_equals_propptr(
+ &iter_a.ptr, &iter_b.ptr, mode,
+ override, extended_rna_path, r_override_changed, flags);
+ equals = equals && eq;
+ }
+
+ if (propname_a != propname_buff_a) {
+ MEM_freeN(propname_a);
+ }
+ if (propname_b != propname_buff_b) {
+ MEM_freeN(propname_b);
+ }
+ MEM_SAFE_FREE(extended_rna_path);
+
+ if (!rna_path && !equals) {
+ break; /* Early out in case we do not want to loop over whole collection. */
+ }
+ }
+
+ equals = equals && !(iter_a.valid || iter_b.valid); /* Not same number of items in both collections... */
+ RNA_property_collection_end(&iter_a);
+ RNA_property_collection_end(&iter_b);
+
+ return (equals == false);
+ }
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+bool rna_property_override_store_default(
+ PointerRNA *ptr_local, PointerRNA *ptr_reference, PointerRNA *ptr_storage,
+ PropertyRNA *prop_local, PropertyRNA *prop_reference, PropertyRNA *prop_storage,
+ const int len_local, const int len_reference, const int len_storage,
+ IDOverrideStaticPropertyOperation *opop)
+{
+ BLI_assert(len_local == len_reference && (!ptr_storage || len_local == len_storage));
+ UNUSED_VARS_NDEBUG(len_reference, len_storage);
+
+ bool changed = false;
+ const int index = opop->subitem_reference_index;
+
+ if (!ELEM(opop->operation, IDOVERRIDESTATIC_OP_ADD, IDOVERRIDESTATIC_OP_SUBTRACT, IDOVERRIDESTATIC_OP_MULTIPLY)) {
+ return changed;
+ }
+
+ /* XXX TODO About range limits.
+ * Ideally, it woudl be great to get rid of RNA range in that specific case.
+ * However, this won't be that easy and will add yet another layer of complexity in generated code,
+ * not to mention that we could most likely *not* bypass custom setters anyway.
+ * So for now, if needed second operand value is not in valid range, we simply fall back
+ * to a mere REPLACE operation.
+ * Time will say whether this is acceptable limitation or not. */
+ switch (RNA_property_type(prop_local)) {
+ case PROP_BOOLEAN:
+ /* TODO support boolean ops? Really doubt this would ever be useful though... */
+ BLI_assert(0 && "Boolean properties support no override diff operation");
+ break;
+ case PROP_INT:
+ {
+ int prop_min, prop_max;
+ RNA_property_int_range(ptr_local, prop_local, &prop_min, &prop_max);
+
+ if (len_local) {
+ if (index == -1) {
+ int array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
+ int *array_a, *array_b;
+
+ array_a = (len_local > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_a) * len_local, __func__) : array_stack_a;
+ RNA_property_int_get_array(ptr_reference, prop_reference, array_a);
+
+ switch (opop->operation) {
+ case IDOVERRIDESTATIC_OP_ADD:
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ {
+ const int fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1 : -1;
+ const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
+ bool do_set = true;
+ array_b = (len_local > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_b) * len_local, __func__) : array_stack_b;
+ RNA_property_int_get_array(ptr_local, prop_local, array_b);
+ for (int i = len_local; i--;) {
+ array_b[i] = fac * (array_b[i] - array_a[i]);
+ if (array_b[i] < prop_min || array_b[i] > prop_max) {
+ opop->operation = other_op;
+ for (int j = len_local; j--;) {
+ array_b[j] = j >= i ? -array_b[j] : fac * (array_a[j] - array_b[j]);
+ if (array_b[j] < prop_min || array_b[j] > prop_max) {
+ /* We failed to find a suitable diff op,
+ * fall back to plain REPLACE one. */
+ opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
+ do_set = false;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ if (do_set) {
+ changed = true;
+ RNA_property_int_set_array(ptr_storage, prop_storage, array_b);
+ }
+ if (array_b != array_stack_b) MEM_freeN(array_b);
+ break;
+ }
+ default:
+ BLI_assert(0 && "Unsupported RNA override diff operation on integer");
+ break;
+ }
+
+ if (array_a != array_stack_a) MEM_freeN(array_a);
+ }
+ else {
+ const int value = RNA_property_int_get_index(ptr_reference, prop_reference, index);
+
+ switch (opop->operation) {
+ case IDOVERRIDESTATIC_OP_ADD:
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ {
+ const int fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1 : -1;
+ const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
+ int b = fac * (RNA_property_int_get_index(ptr_local, prop_local, index) - value);
+ if (b < prop_min || b > prop_max) {
+ opop->operation = other_op;
+ b = -b;
+ if (b < prop_min || b > prop_max) {
+ opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
+ break;
+ }
+ }
+ changed = true;
+ RNA_property_int_set_index(ptr_storage, prop_storage, index, b);
+ break;
+ }
+ default:
+ BLI_assert(0 && "Unsupported RNA override diff operation on integer");
+ break;
+ }
+ }
+ }
+ else {
+ const int value = RNA_property_int_get(ptr_reference, prop_reference);
+
+ switch (opop->operation) {
+ case IDOVERRIDESTATIC_OP_ADD:
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ {
+ const int fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1 : -1;
+ const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
+ int b = fac * (RNA_property_int_get(ptr_local, prop_local) - value);
+ if (b < prop_min || b > prop_max) {
+ opop->operation = other_op;
+ b = -b;
+ if (b < prop_min || b > prop_max) {
+ opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
+ break;
+ }
+ }
+ changed = true;
+ RNA_property_int_set(ptr_storage, prop_storage, b);
+ break;
+ }
+ default:
+ BLI_assert(0 && "Unsupported RNA override diff operation on integer");
+ break;
+ }
+ }
+ break;
+ }
+ case PROP_FLOAT:
+ {
+ float prop_min, prop_max;
+ RNA_property_float_range(ptr_local, prop_local, &prop_min, &prop_max);
+
+ if (len_local) {
+ if (index == -1) {
+ float array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
+ float *array_a, *array_b;
+
+ array_a = (len_local > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_a) * len_local, __func__) : array_stack_a;
+
+ RNA_property_float_get_array(ptr_reference, prop_reference, array_a);
+ switch (opop->operation) {
+ case IDOVERRIDESTATIC_OP_ADD:
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ {
+ const float fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1.0 : -1.0;
+ const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
+ bool do_set = true;
+ array_b = (len_local > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_b) * len_local, __func__) : array_stack_b;
+ RNA_property_float_get_array(ptr_local, prop_local, array_b);
+ for (int i = len_local; i--;) {
+ array_b[i] = fac * (array_b[i] - array_a[i]);
+ if (array_b[i] < prop_min || array_b[i] > prop_max) {
+ opop->operation = other_op;
+ for (int j = len_local; j--;) {
+ array_b[j] = j >= i ? -array_b[j] : fac * (array_a[j] - array_b[j]);
+ if (array_b[j] < prop_min || array_b[j] > prop_max) {
+ /* We failed to find a suitable diff op,
+ * fall back to plain REPLACE one. */
+ opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
+ do_set = false;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ if (do_set) {
+ changed = true;
+ RNA_property_float_set_array(ptr_storage, prop_storage, array_b);
+ }
+ if (array_b != array_stack_b) MEM_freeN(array_b);
+ break;
+ }
+ case IDOVERRIDESTATIC_OP_MULTIPLY:
+ {
+ bool do_set = true;
+ array_b = (len_local > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_b) * len_local, __func__) : array_stack_b;
+ RNA_property_float_get_array(ptr_local, prop_local, array_b);
+ for (int i = len_local; i--;) {
+ array_b[i] = array_a[i] == 0.0f ? array_b[i] : array_b[i] / array_a[i];
+ if (array_b[i] < prop_min || array_b[i] > prop_max) {
+ opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
+ do_set = false;
+ break;
+ }
+ }
+ if (do_set) {
+ changed = true;
+ RNA_property_float_set_array(ptr_storage, prop_storage, array_b);
+ }
+ if (array_b != array_stack_b) MEM_freeN(array_b);
+ break;
+ }
+ default:
+ BLI_assert(0 && "Unsupported RNA override diff operation on float");
+ break;
+ }
+
+ if (array_a != array_stack_a) MEM_freeN(array_a);
+ }
+ else {
+ const float value = RNA_property_float_get_index(ptr_reference, prop_reference, index);
+
+ switch (opop->operation) {
+ case IDOVERRIDESTATIC_OP_ADD:
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ {
+ const float fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1.0f : -1.0f;
+ const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
+ float b = fac * (RNA_property_float_get_index(ptr_local, prop_local, index) - value);
+ if (b < prop_min || b > prop_max) {
+ opop->operation = other_op;
+ b = -b;
+ if (b < prop_min || b > prop_max) {
+ opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
+ break;
+ }
+ }
+ changed = true;
+ RNA_property_float_set_index(ptr_storage, prop_storage, index, b);
+ break;
+ }
+ case IDOVERRIDESTATIC_OP_MULTIPLY:
+ {
+ const float b = RNA_property_float_get_index(ptr_local, prop_local, index) / (value == 0.0f ? 1.0f : value);
+ if (b < prop_min || b > prop_max) {
+ opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
+ break;
+ }
+ changed = true;
+ RNA_property_float_set_index(ptr_storage, prop_storage, index, b);
+ break;
+ }
+ default:
+ BLI_assert(0 && "Unsupported RNA override diff operation on float");
+ break;
+ }
+ }
+ }
+ else {
+ const float value = RNA_property_float_get(ptr_reference, prop_reference);
+
+ switch (opop->operation) {
+ case IDOVERRIDESTATIC_OP_ADD:
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ {
+ const float fac = opop->operation == IDOVERRIDESTATIC_OP_ADD ? 1.0f : -1.0f;
+ const int other_op = opop->operation == IDOVERRIDESTATIC_OP_ADD ? IDOVERRIDESTATIC_OP_SUBTRACT : IDOVERRIDESTATIC_OP_ADD;
+ float b = fac * (RNA_property_float_get(ptr_local, prop_local) - value);
+ if (b < prop_min || b > prop_max) {
+ opop->operation = other_op;
+ b = -b;
+ if (b < prop_min || b > prop_max) {
+ opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
+ break;
+ }
+ }
+ changed = true;
+ RNA_property_float_set(ptr_storage, prop_storage, b);
+ break;
+ }
+ case IDOVERRIDESTATIC_OP_MULTIPLY:
+ {
+ const float b = RNA_property_float_get(ptr_local, prop_local) / (value == 0.0f ? 1.0f : value);
+ if (b < prop_min || b > prop_max) {
+ opop->operation = IDOVERRIDESTATIC_OP_REPLACE;
+ break;
+ }
+ changed = true;
+ RNA_property_float_set(ptr_storage, prop_storage, b);
+ break;
+ }
+ default:
+ BLI_assert(0 && "Unsupported RNA override diff operation on float");
+ break;
+ }
+ }
+ return true;
+ }
+ case PROP_ENUM:
+ /* TODO support add/sub, for bitflags? */
+ BLI_assert(0 && "Enum properties support no override diff operation");
+ break;
+ case PROP_POINTER:
+ BLI_assert(0 && "Pointer properties support no override diff operation");
+ break;
+ case PROP_STRING:
+ BLI_assert(0 && "String properties support no override diff operation");
+ break;
+ case PROP_COLLECTION:
+ /* XXX TODO support this of course... */
+ BLI_assert(0 && "Collection properties support no override diff operation");
+ break;
+ default:
+ break;
+ }
+
+ return changed;
+}
+
+bool rna_property_override_apply_default(
+ PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage,
+ PropertyRNA *prop_dst, PropertyRNA *prop_src, PropertyRNA *prop_storage,
+ const int len_dst, const int len_src, const int len_storage,
+ IDOverrideStaticPropertyOperation *opop)
+{
+ BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage));
+ UNUSED_VARS_NDEBUG(len_src, len_storage);
+
+ const int index = opop->subitem_reference_index;
+ const short override_op = opop->operation;
+
+ switch (RNA_property_type(prop_dst)) {
+ case PROP_BOOLEAN:
+ if (len_dst) {
+ if (index == -1) {
+ int array_stack_a[RNA_STACK_ARRAY];
+ int *array_a;
+
+ array_a = (len_dst > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_a) * len_dst, __func__) : array_stack_a;
+
+ RNA_property_boolean_get_array(ptr_src, prop_src, array_a);
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_boolean_set_array(ptr_dst, prop_dst, array_a);
+ break;
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on boolean");
+ return false;
+ }
+
+ if (array_a != array_stack_a) MEM_freeN(array_a);
+ }
+ else {
+ const int value = RNA_property_boolean_get_index(ptr_src, prop_src, index);
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_boolean_set_index(ptr_dst, prop_dst, index, value);
+ break;
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on boolean");
+ return false;
+ }
+ }
+ }
+ else {
+ const int value = RNA_property_boolean_get(ptr_src, prop_src);
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_boolean_set(ptr_dst, prop_dst, value);
+ break;
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on boolean");
+ return false;
+ }
+ }
+ return true;
+ case PROP_INT:
+ if (len_dst) {
+ if (index == -1) {
+ int array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
+ int *array_a, *array_b;
+
+ array_a = (len_dst > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_a) * len_dst, __func__) : array_stack_a;
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_int_get_array(ptr_src, prop_src, array_a);
+ RNA_property_int_set_array(ptr_dst, prop_dst, array_a);
+ break;
+ case IDOVERRIDESTATIC_OP_ADD:
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ RNA_property_int_get_array(ptr_dst, prop_dst, array_a);
+ array_b = (len_dst > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_b) * len_dst, __func__) : array_stack_b;
+ RNA_property_int_get_array(ptr_storage, prop_storage, array_b);
+ if (override_op == IDOVERRIDESTATIC_OP_ADD) {
+ for (int i = len_dst; i--;) array_a[i] += array_b[i];
+ }
+ else {
+ for (int i = len_dst; i--;) array_a[i] -= array_b[i];
+ }
+ RNA_property_int_set_array(ptr_dst, prop_dst, array_a);
+ if (array_b != array_stack_b) MEM_freeN(array_b);
+ break;
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on integer");
+ return false;
+ }
+
+ if (array_a != array_stack_a) MEM_freeN(array_a);
+ }
+ else {
+ const int storage_value = ptr_storage ? RNA_property_int_get_index(ptr_storage, prop_storage, index) : 0;
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_int_set_index(ptr_dst, prop_dst, index,
+ RNA_property_int_get_index(ptr_src, prop_src, index));
+ break;
+ case IDOVERRIDESTATIC_OP_ADD:
+ RNA_property_int_set_index(ptr_dst, prop_dst, index,
+ RNA_property_int_get_index(ptr_dst, prop_dst, index) - storage_value);
+ break;
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ RNA_property_int_set_index(ptr_dst, prop_dst, index,
+ RNA_property_int_get_index(ptr_dst, prop_dst, index) - storage_value);
+ break;
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on integer");
+ return false;
+ }
+ }
+ }
+ else {
+ const int storage_value = ptr_storage ? RNA_property_int_get(ptr_storage, prop_storage) : 0;
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_int_set(ptr_dst, prop_dst, RNA_property_int_get(ptr_src, prop_src));
+ break;
+ case IDOVERRIDESTATIC_OP_ADD:
+ RNA_property_int_set(ptr_dst, prop_dst, RNA_property_int_get(ptr_dst, prop_dst) + storage_value);
+ break;
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ RNA_property_int_set(ptr_dst, prop_dst, RNA_property_int_get(ptr_dst, prop_dst) - storage_value);
+ break;
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on integer");
+ return false;
+ }
+ }
+ return true;
+ case PROP_FLOAT:
+ if (len_dst) {
+ if (index == -1) {
+ float array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
+ float *array_a, *array_b;
+
+ array_a = (len_dst > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_a) * len_dst, __func__) : array_stack_a;
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_float_get_array(ptr_src, prop_src, array_a);
+ RNA_property_float_set_array(ptr_dst, prop_dst, array_a);
+ break;
+ case IDOVERRIDESTATIC_OP_ADD:
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ case IDOVERRIDESTATIC_OP_MULTIPLY:
+ RNA_property_float_get_array(ptr_dst, prop_dst, array_a);
+ array_b = (len_dst > RNA_STACK_ARRAY) ? MEM_mallocN(sizeof(*array_b) * len_dst, __func__) : array_stack_b;
+ RNA_property_float_get_array(ptr_storage, prop_storage, array_b);
+ if (override_op == IDOVERRIDESTATIC_OP_ADD) {
+ for (int i = len_dst; i--;) array_a[i] += array_b[i];
+ }
+ else if (override_op == IDOVERRIDESTATIC_OP_SUBTRACT) {
+ for (int i = len_dst; i--;) array_a[i] -= array_b[i];
+ }
+ else {
+ for (int i = len_dst; i--;) array_a[i] *= array_b[i];
+ }
+ RNA_property_float_set_array(ptr_dst, prop_dst, array_a);
+ if (array_b != array_stack_b) MEM_freeN(array_b);
+ break;
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on float");
+ return false;
+ }
+
+ if (array_a != array_stack_a) MEM_freeN(array_a);
+ }
+ else {
+ const float storage_value = ptr_storage ? RNA_property_float_get_index(ptr_storage, prop_storage, index) : 0.0f;
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_float_set_index(ptr_dst, prop_dst, index,
+ RNA_property_float_get_index(ptr_src, prop_src, index));
+ break;
+ case IDOVERRIDESTATIC_OP_ADD:
+ RNA_property_float_set_index(ptr_dst, prop_dst, index,
+ RNA_property_float_get_index(ptr_dst, prop_dst, index) + storage_value);
+ break;
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ RNA_property_float_set_index(ptr_dst, prop_dst, index,
+ RNA_property_float_get_index(ptr_dst, prop_dst, index) - storage_value);
+ break;
+ case IDOVERRIDESTATIC_OP_MULTIPLY:
+ RNA_property_float_set_index(ptr_dst, prop_dst, index,
+ RNA_property_float_get_index(ptr_dst, prop_dst, index) * storage_value);
+ break;
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on float");
+ return false;
+ }
+ }
+ }
+ else {
+ const float storage_value = ptr_storage ? RNA_property_float_get(ptr_storage, prop_storage) : 0.0f;
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_float_set(ptr_dst, prop_dst, RNA_property_float_get(ptr_src, prop_src));
+ break;
+ case IDOVERRIDESTATIC_OP_ADD:
+ RNA_property_float_set(ptr_dst, prop_dst, RNA_property_float_get(ptr_dst, prop_dst) + storage_value);
+ break;
+ case IDOVERRIDESTATIC_OP_SUBTRACT:
+ RNA_property_float_set(ptr_dst, prop_dst, RNA_property_float_get(ptr_dst, prop_dst) - storage_value);
+ break;
+ case IDOVERRIDESTATIC_OP_MULTIPLY:
+ RNA_property_float_set(ptr_dst, prop_dst, RNA_property_float_get(ptr_dst, prop_dst) * storage_value);
+ break;
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on float");
+ return false;
+ }
+ }
+ return true;
+ case PROP_ENUM:
+ {
+ const int value = RNA_property_enum_get(ptr_src, prop_src);
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_enum_set(ptr_dst, prop_dst, value);
+ break;
+ /* TODO support add/sub, for bitflags? */
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on enum");
+ return false;
+ }
+ return true;
+ }
+ case PROP_POINTER:
+ {
+ PointerRNA value = RNA_property_pointer_get(ptr_src, prop_src);
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_pointer_set(ptr_dst, prop_dst, value);
+ break;
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on pointer");
+ return false;
+ }
+ return true;
+ }
+ case PROP_STRING:
+ {
+ char buff[256];
+ char *value = RNA_property_string_get_alloc(ptr_src, prop_src, buff, sizeof(buff), NULL);
+
+ switch (override_op) {
+ case IDOVERRIDESTATIC_OP_REPLACE:
+ RNA_property_string_set(ptr_dst, prop_dst, value);
+ break;
+ default:
+ BLI_assert(0 && "Unsupported RNA override operation on string");
+ return false;
+ }
+
+ if (value != buff) MEM_freeN(value);
+ return true;
+ }
+ default:
+ /* TODO PROP_COLLECTION of course! */
+ return false;
+ }
+
+ return false;
+}
+
+
#else
@@ -1259,6 +2265,11 @@ static void rna_def_property(BlenderRNA *brna)
RNA_def_property_boolean_funcs(prop, "rna_Property_animatable_get", NULL);
RNA_def_property_ui_text(prop, "Animatable", "Property is animatable through RNA");
+ prop = RNA_def_property(srna, "is_overridable", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_boolean_funcs(prop, "rna_Property_overridable_get", NULL);
+ RNA_def_property_ui_text(prop, "Overridable", "Property is overridable through RNA");
+
prop = RNA_def_property(srna, "is_required", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_Property_is_required_get", NULL);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index fda92ff7c0d..785f805a33e 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"
@@ -430,6 +435,7 @@ static const EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
+
#endif
#ifdef RNA_RUNTIME
@@ -440,22 +446,24 @@ static const EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_text_types.h"
+#include "DNA_workspace_types.h"
#include "RNA_access.h"
#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_idprop.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
-#include "BKE_depsgraph.h"
#include "BKE_mesh.h"
#include "BKE_sound.h"
#include "BKE_screen.h"
@@ -470,6 +478,11 @@ static const EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
#include "ED_mesh.h"
#include "ED_keyframing.h"
#include "ED_image.h"
+#include "ED_scene.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#ifdef WITH_FREESTYLE
#include "FRS_freestyle.h"
@@ -605,87 +618,39 @@ static void rna_SpaceImageEditor_uv_sculpt_update(Main *bmain, Scene *scene, Poi
ED_space_image_uv_sculpt_update(bmain->wm.first, scene);
}
-static int rna_Scene_object_bases_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+
+/* Read-only Iterator of all the scene objects. */
+
+static void rna_Scene_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
- Base *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);
- return true;
- }
- }
+ iter->internal.custom = MEM_callocN(sizeof(BLI_Iterator), __func__);
- return false;
+ ((BLI_Iterator *)iter->internal.custom)->valid = true;
+ BKE_scene_objects_iterator_begin(iter->internal.custom, (void *)scene);
+ iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
}
-static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter)
+static void rna_Scene_objects_next(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);
+ BKE_scene_objects_iterator_next(iter->internal.custom);
+ iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
}
-static Base *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *reports, Object *ob)
+static void rna_Scene_objects_end(CollectionPropertyIterator *iter)
{
- Scene *scene_act = CTX_data_scene(C);
- Base *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);
- return NULL;
- }
-
- base = BKE_scene_base_add(scene, ob);
- id_us_plus(&ob->id);
-
- /* this is similar to what object_add_type and BKE_object_add do */
- base->lay = scene->lay;
-
- /* when linking to an inactive scene don't touch the layer */
- if (scene == scene_act)
- ob->lay = base->lay;
-
- /* TODO(sergey): Only update relations for the current scene. */
- DAG_relations_tag_update(CTX_data_main(C));
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
-
- /* slows down importers too much, run scene.update() */
- /* DAG_srelations_tag_update(G.main); */
-
- WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene);
-
- return base;
+ BKE_scene_objects_iterator_end(iter->internal.custom);
+ MEM_freeN(iter->internal.custom);
}
-static void rna_Scene_object_unlink(Scene *scene, ReportList *reports, Object *ob)
+static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter)
{
- Base *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;
- }
- if (base == scene->basact && ob->mode != OB_MODE_OBJECT) {
- BKE_reportf(reports, RPT_ERROR, "Object '%s' must be in object mode to unlink", ob->id.name + 2);
- return;
- }
- if (scene->basact == base) {
- scene->basact = NULL;
- }
-
- BKE_scene_base_unlink(scene, base);
- MEM_freeN(base);
-
- id_us_min(&ob->id);
-
- /* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */
- DAG_relations_tag_update(G.main);
-
- WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene);
+ Object *ob = ((BLI_Iterator *)iter->internal.custom)->current;
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ob);
}
+/* End of read-only Iterator of all the scene objects. */
+
static void rna_Scene_skgen_etch_template_set(PointerRNA *ptr, PointerRNA value)
{
ToolSettings *ts = (ToolSettings *)ptr->data;
@@ -695,21 +660,6 @@ static void rna_Scene_skgen_etch_template_set(PointerRNA *ptr, PointerRNA value)
ts->skgen_template = NULL;
}
-static PointerRNA rna_Scene_active_object_get(PointerRNA *ptr)
-{
- Scene *scene = (Scene *)ptr->data;
- return rna_pointer_inherit_refine(ptr, &RNA_Object, scene->basact ? scene->basact->object : NULL);
-}
-
-static void rna_Scene_active_object_set(PointerRNA *ptr, PointerRNA value)
-{
- Scene *scene = (Scene *)ptr->data;
- if (value.data)
- scene->basact = BKE_scene_base_find(scene, (Object *)value.data);
- else
- scene->basact = NULL;
-}
-
static void rna_Scene_set_set(PointerRNA *ptr, PointerRNA value)
{
Scene *scene = (Scene *)ptr->data;
@@ -728,11 +678,25 @@ static void rna_Scene_set_set(PointerRNA *ptr, PointerRNA value)
scene->set = set;
}
+void rna_Scene_set_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update_ex(bmain, &scene->id, 0);
+ if (scene->set != NULL) {
+ /* Objects which are pulled into main scene's depsgraph needs to have
+ * their base flags updated.
+ */
+ DEG_id_tag_update_ex(bmain, &scene->set->id, 0);
+ }
+}
+
static void rna_Scene_layer_set(PointerRNA *ptr, const int *values)
{
Scene *scene = (Scene *)ptr->data;
- scene->lay = ED_view3d_scene_layer_set(scene->lay, values, &scene->layact);
+ scene->lay = ED_view3d_view_layer_set(scene->lay, values, &scene->layact);
}
static int rna_Scene_active_layer_get(PointerRNA *ptr)
@@ -744,19 +708,21 @@ static int rna_Scene_active_layer_get(PointerRNA *ptr)
static void rna_Scene_view3d_update(Main *bmain, Scene *UNUSED(scene_unused), PointerRNA *ptr)
{
+ wmWindowManager *wm = bmain->wm.first;
Scene *scene = (Scene *)ptr->data;
- BKE_screen_view3d_main_sync(&bmain->screen, scene);
+ WM_windows_scene_data_sync(&wm->windows, scene);
}
-static void rna_Scene_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Scene_layer_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
- rna_Scene_view3d_update(bmain, scene, ptr);
/* XXX We would need do_time=true here, else we can have update issues like [#36289]...
* However, this has too much drawbacks (like slower layer switch, undesired updates...).
* That's TODO for future DAG updates.
*/
- DAG_on_visible_update(bmain, false);
+ DEG_on_visible_update(bmain, false);
+
+ /* No need to sync scene data here (WM_windows_scene_data_sync), handled through notifier. */
}
static void rna_Scene_fps_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
@@ -1334,73 +1300,6 @@ static void rna_FFmpegSettings_codec_settings_update(Main *UNUSED(bmain), Scene
}
#endif
-static int rna_RenderSettings_active_layer_index_get(PointerRNA *ptr)
-{
- RenderData *rd = (RenderData *)ptr->data;
- return rd->actlay;
-}
-
-static void rna_RenderSettings_active_layer_index_set(PointerRNA *ptr, int value)
-{
- RenderData *rd = (RenderData *)ptr->data;
- int num_layers = BLI_listbase_count(&rd->layers);
- rd->actlay = min_ff(value, num_layers - 1);
-}
-
-static void rna_RenderSettings_active_layer_index_range(
- PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
-{
- RenderData *rd = (RenderData *)ptr->data;
-
- *min = 0;
- *max = max_ii(0, BLI_listbase_count(&rd->layers) - 1);
-}
-
-static PointerRNA rna_RenderSettings_active_layer_get(PointerRNA *ptr)
-{
- RenderData *rd = (RenderData *)ptr->data;
- SceneRenderLayer *srl = BLI_findlink(&rd->layers, rd->actlay);
-
- return rna_pointer_inherit_refine(ptr, &RNA_SceneRenderLayer, srl);
-}
-
-static void rna_RenderSettings_active_layer_set(PointerRNA *ptr, PointerRNA value)
-{
- RenderData *rd = (RenderData *)ptr->data;
- SceneRenderLayer *srl = (SceneRenderLayer *)value.data;
- const int index = BLI_findindex(&rd->layers, srl);
- if (index != -1) rd->actlay = index;
-}
-
-static SceneRenderLayer *rna_RenderLayer_new(ID *id, RenderData *UNUSED(rd), const char *name)
-{
- Scene *scene = (Scene *)id;
- SceneRenderLayer *srl = BKE_scene_add_render_layer(scene, name);
-
- DAG_id_tag_update(&scene->id, 0);
- WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
- return srl;
-}
-
-static void rna_RenderLayer_remove(
- ID *id, RenderData *UNUSED(rd), Main *bmain, ReportList *reports, PointerRNA *srl_ptr)
-{
- SceneRenderLayer *srl = srl_ptr->data;
- Scene *scene = (Scene *)id;
-
- if (!BKE_scene_remove_render_layer(bmain, scene, srl)) {
- BKE_reportf(reports, RPT_ERROR, "Render layer '%s' could not be removed from scene '%s'",
- srl->name, scene->id.name + 2);
- return;
- }
-
- RNA_POINTER_INVALIDATE(srl_ptr);
-
- DAG_id_tag_update(&scene->id, 0);
- WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
-}
-
static int rna_RenderSettings_active_view_index_get(PointerRNA *ptr)
{
RenderData *rd = (RenderData *)ptr->data;
@@ -1465,121 +1364,74 @@ static void rna_RenderView_remove(
WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
}
-static void rna_RenderSettings_engine_set(PointerRNA *ptr, int value)
+static void rna_RenderSettings_views_format_set(PointerRNA *ptr, int value)
{
RenderData *rd = (RenderData *)ptr->data;
- RenderEngineType *type = BLI_findlink(&R_engines, value);
-
- if (type)
- BLI_strncpy_utf8(rd->engine, type->idname, sizeof(rd->engine));
-}
-static const EnumPropertyItem *rna_RenderSettings_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);
+ if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW &&
+ value == SCE_VIEWS_FORMAT_STEREO_3D)
+ {
+ /* make sure the actview is visible */
+ if (rd->actview > 1) rd->actview = 1;
}
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
- return item;
+ rd->views_format = value;
}
-static int rna_RenderSettings_engine_get(PointerRNA *ptr)
+void rna_Scene_glsl_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- RenderData *rd = (RenderData *)ptr->data;
- RenderEngineType *type;
- int a = 0;
-
- for (type = R_engines.first; type; type = type->next, a++)
- if (STREQ(type->idname, rd->engine))
- return a;
-
- return 0;
-}
+ Scene *scene = (Scene *)ptr->id.data;
-static void rna_RenderSettings_engine_update(Main *bmain, Scene *UNUSED(unused), PointerRNA *UNUSED(ptr))
-{
- ED_render_engine_changed(bmain);
+ DEG_id_tag_update(&scene->id, 0);
}
-static void rna_Scene_glsl_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Scene_world_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *sc = (Scene *)ptr->id.data;
- DAG_id_tag_update(&scene->id, 0);
+ rna_Scene_glsl_update(bmain, scene, ptr);
+ WM_main_add_notifier(NC_WORLD | ND_WORLD, &sc->id);
}
-static void rna_Scene_freestyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+void rna_Scene_freestyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
- DAG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&scene->id, 0);
}
-static void rna_Scene_use_view_map_cache_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+void rna_Scene_use_view_map_cache_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
#ifdef WITH_FREESTYLE
FRS_free_view_map_cache();
#endif
}
-static IDProperty *rna_SceneRenderLayer_idprops(PointerRNA *ptr, bool create)
-{
- SceneRenderLayer *srl = (SceneRenderLayer *)ptr->data;
-
- if (create && !srl->prop) {
- IDPropertyTemplate val = {0};
- srl->prop = IDP_New(IDP_GROUP, &val, "SceneRenderLayer ID properties");
- }
-
- return srl->prop;
-}
-
-static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value)
+void rna_ViewLayer_name_set(PointerRNA *ptr, const char *value)
{
Scene *scene = (Scene *)ptr->id.data;
- SceneRenderLayer *rl = (SceneRenderLayer *)ptr->data;
- char oldname[sizeof(rl->name)];
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ char oldname[sizeof(view_layer->name)];
- BLI_strncpy(oldname, rl->name, sizeof(rl->name));
+ BLI_strncpy(oldname, view_layer->name, sizeof(view_layer->name));
- BLI_strncpy_utf8(rl->name, value, sizeof(rl->name));
- BLI_uniquename(&scene->r.layers, rl, DATA_("RenderLayer"), '.', offsetof(SceneRenderLayer, name), sizeof(rl->name));
+ BLI_strncpy_utf8(view_layer->name, value, sizeof(view_layer->name));
+ BLI_uniquename(&scene->view_layers, view_layer, DATA_("ViewLayer"), '.', offsetof(ViewLayer, name), sizeof(view_layer->name));
if (scene->nodetree) {
bNode *node;
- int index = BLI_findindex(&scene->r.layers, rl);
+ int index = BLI_findindex(&scene->view_layers, view_layer);
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, rl->name, NODE_MAXSTR);
+ BLI_strncpy(node->name, view_layer->name, NODE_MAXSTR);
}
}
}
/* fix all the animation data which may link to this */
- BKE_animdata_fix_paths_rename_all(NULL, "render.layers", oldname, rl->name);
-}
-
-static char *rna_SceneRenderLayer_path(PointerRNA *ptr)
-{
- SceneRenderLayer *srl = (SceneRenderLayer *)ptr->data;
- char name_esc[sizeof(srl->name) * 2];
-
- BLI_strescape(name_esc, srl->name, sizeof(name_esc));
- return BLI_sprintfN("render.layers[\"%s\"]", name_esc);
+ BKE_animdata_fix_paths_rename_all(NULL, "view_layers", oldname, view_layer->name);
}
static void rna_SceneRenderView_name_set(PointerRNA *ptr, const char *value)
@@ -1590,62 +1442,7 @@ static void rna_SceneRenderView_name_set(PointerRNA *ptr, const char *value)
BLI_uniquename(&scene->r.views, rv, DATA_("RenderView"), '.', offsetof(SceneRenderView, name), sizeof(rv->name));
}
-static char *rna_SceneRenderView_path(PointerRNA *ptr)
-{
- SceneRenderView *srv = (SceneRenderView *)ptr->data;
- return BLI_sprintfN("render.views[\"%s\"]", srv->name);
-}
-
-static void rna_RenderSettings_views_format_set(PointerRNA *ptr, int value)
-{
- RenderData *rd = (RenderData *)ptr->data;
-
- if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW &&
- value == SCE_VIEWS_FORMAT_STEREO_3D)
- {
- /* make sure the actview is visible */
- if (rd->actview > 1) rd->actview = 1;
- }
-
- rd->views_format = value;
-}
-
-static int rna_RenderSettings_multiple_engines_get(PointerRNA *UNUSED(ptr))
-{
- return (BLI_listbase_count(&R_engines) > 1);
-}
-
-static int rna_RenderSettings_use_shading_nodes_get(PointerRNA *ptr)
-{
- Scene *scene = (Scene *)ptr->id.data;
- return BKE_scene_use_new_shading_nodes(scene);
-}
-
-static int rna_RenderSettings_use_spherical_stereo_get(PointerRNA *ptr)
-{
- Scene *scene = (Scene *)ptr->id.data;
- return BKE_scene_use_spherical_stereo(scene);
-}
-
-static int rna_RenderSettings_use_game_engine_get(PointerRNA *ptr)
-{
- RenderData *rd = (RenderData *)ptr->data;
- RenderEngineType *type;
-
- for (type = R_engines.first; type; type = type->next)
- if (STREQ(type->idname, rd->engine))
- return (type->flag & RE_GAME) != 0;
-
- return 0;
-}
-
-static void rna_SceneRenderLayer_layer_set(PointerRNA *ptr, const int *values)
-{
- SceneRenderLayer *rl = (SceneRenderLayer *)ptr->data;
- rl->lay = ED_view3d_scene_layer_set(rl->lay, values, NULL);
-}
-
-static void rna_SceneRenderLayer_pass_update(Main *bmain, Scene *activescene, PointerRNA *ptr)
+void rna_ViewLayer_pass_update(Main *bmain, Scene *activescene, PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
@@ -1655,11 +1452,10 @@ static void rna_SceneRenderLayer_pass_update(Main *bmain, Scene *activescene, Po
rna_Scene_glsl_update(bmain, activescene, ptr);
}
-static void rna_SceneRenderLayer_update_render_passes(ID *id)
+static char *rna_SceneRenderView_path(PointerRNA *ptr)
{
- Scene *scene = (Scene *)id;
- if (scene->nodetree)
- ntreeCompositUpdateRLayers(scene->nodetree);
+ SceneRenderView *srv = (SceneRenderView *)ptr->data;
+ return BLI_sprintfN("render.views[\"%s\"]", srv->name);
}
static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr)
@@ -1673,23 +1469,25 @@ 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;
-
- for (base = scene->base.first; base; base = base->next)
- BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH);
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
+ }
+ FOREACH_SCENE_OBJECT_END
}
static void rna_Scene_editmesh_select_mode_set(PointerRNA *ptr, const int *value)
{
Scene *scene = (Scene *)ptr->id.data;
+ ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
ToolSettings *ts = (ToolSettings *)ptr->data;
int flag = (value[0] ? SCE_SELECT_VERTEX : 0) | (value[1] ? SCE_SELECT_EDGE : 0) | (value[2] ? SCE_SELECT_FACE : 0);
if (flag) {
ts->selectmode = flag;
- if (scene->basact) {
- Mesh *me = BKE_mesh_from_object(scene->basact->object);
+ if (view_layer->basact) {
+ Mesh *me = BKE_mesh_from_object(view_layer->basact->object);
if (me && me->edit_btmesh && me->edit_btmesh->selectmode != flag) {
me->edit_btmesh->selectmode = flag;
EDBM_selectmode_set(me->edit_btmesh);
@@ -1698,12 +1496,13 @@ static void rna_Scene_editmesh_select_mode_set(PointerRNA *ptr, const int *value
}
}
-static void rna_Scene_editmesh_select_mode_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_Scene_editmesh_select_mode_update(bContext *C, PointerRNA *UNUSED(ptr))
{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Mesh *me = NULL;
- if (scene->basact) {
- me = BKE_mesh_from_object(scene->basact->object);
+ if (view_layer->basact) {
+ me = BKE_mesh_from_object(view_layer->basact->object);
if (me && me->edit_btmesh == NULL)
me = NULL;
}
@@ -1725,7 +1524,7 @@ static void object_simplify_update(Object *ob)
for (md = ob->modifiers.first; md; md = md->next) {
if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires, eModifierType_ParticleSystem)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
@@ -1740,33 +1539,39 @@ static void object_simplify_update(Object *ob)
}
}
-static void rna_Scene_use_simplify_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Scene_use_simplify_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *sce = ptr->id.data;
Scene *sce_iter;
Base *base;
- BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true);
- for (SETLOOPER(sce, sce_iter, base))
+ FOREACH_SCENE_OBJECT(sce, ob)
+ {
+ object_simplify_update(ob);
+ }
+ FOREACH_SCENE_OBJECT_END
+
+ for (SETLOOPER_SET_ONLY(sce, sce_iter, base)) {
object_simplify_update(base->object);
+ }
WM_main_add_notifier(NC_GEOM | ND_DATA, NULL);
- DAG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&sce->id, 0);
}
-static void rna_Scene_simplify_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Scene_simplify_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Scene *sce = ptr->id.data;
if (sce->r.mode & R_SIMPLIFY)
- rna_Scene_use_simplify_update(bmain, sce, ptr);
+ rna_Scene_use_simplify_update(bmain, scene, ptr);
}
static void rna_SceneRenderData_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *sce = ptr->id.data;
- DAG_id_tag_update(&sce->id, 0);
+ DEG_id_tag_update(&sce->id, 0);
}
static void rna_Scene_use_persistent_data_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -1896,9 +1701,11 @@ static KeyingSet *rna_Scene_keying_set_new(Scene *sce, ReportList *reports, cons
}
}
-static void rna_UnifiedPaintSettings_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_UnifiedPaintSettings_update(bContext *C, PointerRNA *UNUSED(ptr))
{
- Brush *br = BKE_paint_brush(BKE_paint_get_active(scene));
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Brush *br = BKE_paint_brush(BKE_paint_get_active(scene, view_layer));
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
@@ -1921,11 +1728,11 @@ static void rna_UnifiedPaintSettings_unprojected_radius_set(PointerRNA *ptr, flo
ups->unprojected_radius = value;
}
-static void rna_UnifiedPaintSettings_radius_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_UnifiedPaintSettings_radius_update(bContext *C, PointerRNA *ptr)
{
/* changing the unified size should invalidate the overlay but also update the brush */
BKE_paint_invalidate_overlay_all();
- rna_UnifiedPaintSettings_update(bmain, scene, ptr);
+ rna_UnifiedPaintSettings_update(C, ptr);
}
static char *rna_UnifiedPaintSettings_path(PointerRNA *UNUSED(ptr))
@@ -1939,18 +1746,19 @@ static char *rna_CurvePaintSettings_path(PointerRNA *UNUSED(ptr))
}
/* generic function to recalc geometry */
-static void rna_EditMesh_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_EditMesh_update(bContext *C, PointerRNA *UNUSED(ptr))
{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Mesh *me = NULL;
- if (scene->basact) {
- me = BKE_mesh_from_object(scene->basact->object);
+ if (view_layer->basact) {
+ me = BKE_mesh_from_object(view_layer->basact->object);
if (me && me->edit_btmesh == NULL)
me = NULL;
}
if (me) {
- DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&me->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_GEOM | ND_DATA, me);
}
}
@@ -1965,11 +1773,13 @@ static char *rna_MeshStatVis_path(PointerRNA *UNUSED(ptr))
* is not for general use and only for the few cases where changing scene
* settings and NOT for general purpose updates, possibly this should be
* given its own notifier. */
-static void rna_Scene_update_active_object_data(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_Scene_update_active_object_data(bContext *C, PointerRNA *UNUSED(ptr))
{
- Object *ob = OBACT;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+
if (ob) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, &ob->id);
}
}
@@ -1980,7 +1790,7 @@ static void rna_SceneCamera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
Object *camera = scene->camera;
if (camera)
- DAG_id_tag_update(&camera->id, 0);
+ DEG_id_tag_update(&camera->id, 0);
}
static void rna_SceneSequencer_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
@@ -1994,14 +1804,14 @@ static char *rna_ToolSettings_path(PointerRNA *UNUSED(ptr))
return BLI_strdup("tool_settings");
}
-static PointerRNA rna_FreestyleLineSet_linestyle_get(PointerRNA *ptr)
+PointerRNA rna_FreestyleLineSet_linestyle_get(PointerRNA *ptr)
{
FreestyleLineSet *lineset = (FreestyleLineSet *)ptr->data;
return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineStyle, lineset->linestyle);
}
-static void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value)
+void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value)
{
FreestyleLineSet *lineset = (FreestyleLineSet *)ptr->data;
@@ -2011,19 +1821,19 @@ static void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value
id_us_plus(&lineset->linestyle->id);
}
-static FreestyleLineSet *rna_FreestyleSettings_lineset_add(
+FreestyleLineSet *rna_FreestyleSettings_lineset_add(
ID *id, FreestyleSettings *config, Main *bmain, const char *name)
{
Scene *scene = (Scene *)id;
FreestyleLineSet *lineset = BKE_freestyle_lineset_add(bmain, (FreestyleConfig *)config, name);
- DAG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&scene->id, 0);
WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
return lineset;
}
-static void rna_FreestyleSettings_lineset_remove(
+void rna_FreestyleSettings_lineset_remove(
ID *id, FreestyleSettings *config, ReportList *reports, PointerRNA *lineset_ptr)
{
FreestyleLineSet *lineset = lineset_ptr->data;
@@ -2036,18 +1846,18 @@ static void rna_FreestyleSettings_lineset_remove(
RNA_POINTER_INVALIDATE(lineset_ptr);
- DAG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&scene->id, 0);
WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
}
-static PointerRNA rna_FreestyleSettings_active_lineset_get(PointerRNA *ptr)
+PointerRNA rna_FreestyleSettings_active_lineset_get(PointerRNA *ptr)
{
FreestyleConfig *config = (FreestyleConfig *)ptr->data;
FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineSet, lineset);
}
-static void rna_FreestyleSettings_active_lineset_index_range(
+void rna_FreestyleSettings_active_lineset_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
FreestyleConfig *config = (FreestyleConfig *)ptr->data;
@@ -2056,30 +1866,30 @@ static void rna_FreestyleSettings_active_lineset_index_range(
*max = max_ii(0, BLI_listbase_count(&config->linesets) - 1);
}
-static int rna_FreestyleSettings_active_lineset_index_get(PointerRNA *ptr)
+int rna_FreestyleSettings_active_lineset_index_get(PointerRNA *ptr)
{
FreestyleConfig *config = (FreestyleConfig *)ptr->data;
return BKE_freestyle_lineset_get_active_index(config);
}
-static void rna_FreestyleSettings_active_lineset_index_set(PointerRNA *ptr, int value)
+void rna_FreestyleSettings_active_lineset_index_set(PointerRNA *ptr, int value)
{
FreestyleConfig *config = (FreestyleConfig *)ptr->data;
BKE_freestyle_lineset_set_active_index(config, value);
}
-static FreestyleModuleConfig *rna_FreestyleSettings_module_add(ID *id, FreestyleSettings *config)
+FreestyleModuleConfig *rna_FreestyleSettings_module_add(ID *id, FreestyleSettings *config)
{
Scene *scene = (Scene *)id;
FreestyleModuleConfig *module = BKE_freestyle_module_add((FreestyleConfig *)config);
- DAG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&scene->id, 0);
WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
return module;
}
-static void rna_FreestyleSettings_module_remove(
+void rna_FreestyleSettings_module_remove(
ID *id, FreestyleSettings *config, ReportList *reports, PointerRNA *module_ptr)
{
Scene *scene = (Scene *)id;
@@ -2095,7 +1905,7 @@ static void rna_FreestyleSettings_module_remove(
RNA_POINTER_INVALIDATE(module_ptr);
- DAG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&scene->id, 0);
WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
}
@@ -2164,7 +1974,69 @@ static void rna_Stereo3dFormat_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
static int rna_gpu_is_hq_supported_get(PointerRNA *UNUSED(ptr))
{
- return GPU_instanced_drawing_support() && GPU_geometry_shader_support();
+ return true;
+}
+
+static int rna_ViewLayer_active_view_layer_index_get(PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->data;
+ return scene->active_view_layer;
+}
+
+static void rna_ViewLayer_active_view_layer_index_set(PointerRNA *ptr, int value)
+{
+ Scene *scene = (Scene *)ptr->data;
+ int num_layers = BLI_listbase_count(&scene->view_layers);
+ scene->active_view_layer = min_ff(value, num_layers - 1);
+}
+
+static void rna_ViewLayer_active_view_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->view_layers) - 1);
+}
+
+static PointerRNA rna_ViewLayer_active_view_layer_get(PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->data;
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+
+ return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, view_layer);
+}
+
+static void rna_ViewLayer_active_view_layer_set(PointerRNA *ptr, PointerRNA value)
+{
+ Scene *scene = (Scene *)ptr->data;
+ ViewLayer *view_layer = (ViewLayer *)value.data;
+ const int index = BLI_findindex(&scene->view_layers, view_layer);
+ if (index != -1) scene->active_view_layer = index;
+}
+
+static ViewLayer *rna_ViewLayer_new(
+ ID *id, Scene *UNUSED(sce), Main *bmain, const char *name)
+{
+ Scene *scene = (Scene *)id;
+ ViewLayer *view_layer = BKE_view_layer_add(scene, name);
+
+ DEG_id_tag_update(&scene->id, 0);
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return view_layer;
+}
+
+static void rna_ViewLayer_remove(
+ ID *id, Scene *UNUSED(sce), Main *bmain, ReportList *reports, PointerRNA *sl_ptr)
+{
+ Scene *scene = (Scene *)id;
+ ViewLayer *view_layer = sl_ptr->data;
+
+ if (ED_scene_view_layer_delete(bmain, scene, view_layer, reports)) {
+ RNA_POINTER_INVALIDATE(sl_ptr);
+ }
}
#else
@@ -2435,24 +2307,6 @@ static void rna_def_gpencil_brushes(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_ui_text(prop, "Active Brush Index", "Index of active brush");
}
-static void rna_def_transform_orientation(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "TransformOrientation", NULL);
-
- prop = RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX);
- RNA_def_property_float_sdna(prop, NULL, "mat");
- RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_3x3);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_ui_text(prop, "Name", "Name of the custom transform orientation");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-}
-
static void rna_def_tool_settings(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2544,6 +2398,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Sculpt", "");
prop = RNA_def_property(srna, "use_auto_normalize", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_normalize", 1);
RNA_def_property_ui_text(prop, "WPaint Auto-Normalize",
"Ensure all bone-deforming vertex groups add up "
@@ -2551,6 +2406,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
prop = RNA_def_property(srna, "use_multipaint", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_boolean_sdna(prop, NULL, "multipaint", 1);
RNA_def_property_ui_text(prop, "WPaint Multi-Paint",
"Paint across the weights of all selected bones, "
@@ -2558,12 +2414,14 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
prop = RNA_def_property(srna, "vertex_group_user", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_enum_sdna(prop, NULL, "weightuser");
RNA_def_property_enum_items(prop, draw_groupuser_items);
RNA_def_property_ui_text(prop, "Mask Non-Group Vertices", "Display unweighted vertices");
RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
prop = RNA_def_property(srna, "vertex_group_subset", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_enum_sdna(prop, NULL, "vgroupsubset");
RNA_def_property_enum_items(prop, vertex_group_select_items);
RNA_def_property_ui_text(prop, "Subset", "Filter Vertex groups for Display");
@@ -2874,6 +2732,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_boolean_funcs(prop, NULL, "rna_Scene_editmesh_select_mode_set");
RNA_def_property_ui_text(prop, "Mesh Selection Mode", "Which mesh elements selection works on");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_Scene_editmesh_select_mode_update");
prop = RNA_def_property(srna, "vertex_group_weight", PROP_FLOAT, PROP_FACTOR);
@@ -3009,6 +2868,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
* from the active brush */
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
RNA_def_property_int_funcs(prop, NULL, "rna_UnifiedPaintSettings_size_set", NULL);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS * 10);
RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 1, -1);
RNA_def_property_ui_text(prop, "Radius", "Radius of the brush");
@@ -3016,6 +2876,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "unprojected_radius", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_funcs(prop, NULL, "rna_UnifiedPaintSettings_unprojected_radius_set", NULL);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 0.001, FLT_MAX);
RNA_def_property_ui_range(prop, 0.001, 1, 0, -1);
RNA_def_property_ui_text(prop, "Unprojected Radius", "Radius of brush in Blender units");
@@ -3023,6 +2884,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "alpha");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, 10.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 3);
@@ -3031,6 +2893,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "weight");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 3);
@@ -3038,12 +2901,14 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "rgb");
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "secondary_rgb");
RNA_def_property_ui_text(prop, "Secondary Color", "");
@@ -3185,6 +3050,7 @@ static void rna_def_statvis(BlenderRNA *brna)
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, stat_type);
RNA_def_property_ui_text(prop, "Type", "Type of data to visualize/check");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
@@ -3195,6 +3061,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 0.001, 3);
RNA_def_property_ui_text(prop, "Overhang Min", "Minimum angle to display");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
prop = RNA_def_property(srna, "overhang_max", PROP_FLOAT, PROP_ANGLE);
@@ -3203,12 +3070,14 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Overhang Max", "Maximum angle to display");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
prop = RNA_def_property(srna, "overhang_axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "overhang_axis");
RNA_def_property_enum_items(prop, rna_enum_object_axis_items);
RNA_def_property_ui_text(prop, "Axis", "");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
@@ -3219,6 +3088,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1000.0);
RNA_def_property_ui_range(prop, 0.0f, 100.0, 0.001, 3);
RNA_def_property_ui_text(prop, "Thickness Min", "Minimum for measuring thickness");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
prop = RNA_def_property(srna, "thickness_max", PROP_FLOAT, PROP_DISTANCE);
@@ -3227,12 +3097,14 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1000.0);
RNA_def_property_ui_range(prop, 0.0f, 100.0, 0.001, 3);
RNA_def_property_ui_text(prop, "Thickness Max", "Maximum for measuring thickness");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
prop = RNA_def_property(srna, "thickness_samples", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "thickness_samples");
RNA_def_property_range(prop, 1, 32);
RNA_def_property_ui_text(prop, "Samples", "Number of samples to test per face");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
/* distort */
@@ -3242,6 +3114,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Min", "Minimum angle to display");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
prop = RNA_def_property(srna, "distort_max", PROP_FLOAT, PROP_ANGLE);
@@ -3250,6 +3123,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Max", "Maximum angle to display");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
/* sharp */
@@ -3259,6 +3133,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f));
RNA_def_property_ui_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Min", "Minimum angle to display");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
prop = RNA_def_property(srna, "sharp_max", PROP_FLOAT, PROP_ANGLE);
@@ -3267,6 +3142,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f));
RNA_def_property_ui_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Max", "Maximum angle to display");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
}
@@ -3314,67 +3190,19 @@ static void rna_def_unit_settings(BlenderRNA *brna)
RNA_def_property_update(prop, NC_WINDOW, NULL);
}
-void rna_def_render_layer_common(StructRNA *srna, int scene)
+void rna_def_view_layer_common(StructRNA *srna, int scene)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- if (scene) RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SceneRenderLayer_name_set");
+ if (scene) RNA_def_property_string_funcs(prop, NULL, NULL, "rna_ViewLayer_name_set");
else RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_ui_text(prop, "Name", "Render layer name");
RNA_def_struct_name_property(srna, prop);
if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- prop = RNA_def_property(srna, "material_override", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "mat_override");
- RNA_def_property_struct_type(prop, "Material");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Material Override",
- "Material to override all other materials in this render layer");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
- else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- prop = RNA_def_property(srna, "light_override", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "light_override");
- RNA_def_property_struct_type(prop, "Group");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Light Override", "Group to override all other lights in this render layer");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
- else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- /* layers */
- prop = RNA_def_property(srna, "layers", PROP_BOOLEAN, PROP_LAYER_MEMBER);
- RNA_def_property_boolean_sdna(prop, NULL, "lay", 1);
- RNA_def_property_array(prop, 20);
- RNA_def_property_ui_text(prop, "Visible Layers", "Scene layers included in this render layer");
- if (scene) RNA_def_property_boolean_funcs(prop, NULL, "rna_SceneRenderLayer_layer_set");
- else RNA_def_property_boolean_funcs(prop, NULL, "rna_RenderLayer_layer_set");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
- else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- /* this seems to be too much trouble with depsgraph updates/etc. currently (20140423) */
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-
- prop = RNA_def_property(srna, "layers_zmask", PROP_BOOLEAN, PROP_LAYER);
- RNA_def_property_boolean_sdna(prop, NULL, "lay_zmask", 1);
- RNA_def_property_array(prop, 20);
- RNA_def_property_ui_text(prop, "Zmask Layers", "Zmask scene layers for solid faces");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
- else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- prop = RNA_def_property(srna, "layers_exclude", PROP_BOOLEAN, PROP_LAYER);
- RNA_def_property_boolean_sdna(prop, NULL, "lay_exclude", 1);
- RNA_def_property_array(prop, 20);
- RNA_def_property_ui_text(prop, "Exclude Layers", "Exclude scene layers from having any influence");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
- else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
if (scene) {
- prop = RNA_def_property(srna, "samples", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_ui_text(prop, "Samples", "Override number of render samples for this render layer, "
- "0 will use the scene setting");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
prop = RNA_def_property(srna, "pass_alpha_threshold", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_ui_text(prop, "Alpha Threshold",
"Z, Index, normal, UV and vector passes are only affected by surfaces with "
@@ -3383,12 +3211,6 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
}
/* layer options */
- prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "layflag", SCE_LAY_DISABLE);
- RNA_def_property_ui_text(prop, "Enabled", "Disable or enable the render layer");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
- else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
prop = RNA_def_property(srna, "use_zmask", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "layflag", SCE_LAY_ZMASK);
RNA_def_property_ui_text(prop, "Zmask", "Only render what's in front of the solid z values");
@@ -3450,247 +3272,241 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- prop = RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "layflag", SCE_LAY_FRS);
- RNA_def_property_ui_text(prop, "Freestyle", "Render stylized strokes in this Layer");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update");
- else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
/* passes */
prop = RNA_def_property(srna, "use_pass_combined", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_COMBINED);
RNA_def_property_ui_text(prop, "Combined", "Deliver full combined RGBA buffer");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_z", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_Z);
RNA_def_property_ui_text(prop, "Z", "Deliver Z values pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_vector", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_VECTOR);
RNA_def_property_ui_text(prop, "Vector", "Deliver speed vector pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_normal", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_NORMAL);
RNA_def_property_ui_text(prop, "Normal", "Deliver normal pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_uv", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_UV);
RNA_def_property_ui_text(prop, "UV", "Deliver texture UV pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_mist", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_MIST);
RNA_def_property_ui_text(prop, "Mist", "Deliver mist factor pass (0.0-1.0)");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_object_index", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_INDEXOB);
RNA_def_property_ui_text(prop, "Object Index", "Deliver object index pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_material_index", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_INDEXMA);
RNA_def_property_ui_text(prop, "Material Index", "Deliver material index pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_RGBA);
RNA_def_property_ui_text(prop, "Color", "Deliver shade-less color pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_diffuse", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_DIFFUSE);
RNA_def_property_ui_text(prop, "Diffuse", "Deliver diffuse pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_specular", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_SPEC);
RNA_def_property_ui_text(prop, "Specular", "Deliver specular pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_shadow", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_SHADOW);
RNA_def_property_ui_text(prop, "Shadow", "Deliver shadow pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_ambient_occlusion", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_AO);
RNA_def_property_ui_text(prop, "AO", "Deliver AO pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_reflection", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_REFLECT);
RNA_def_property_ui_text(prop, "Reflection", "Deliver raytraced reflection pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_refraction", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_REFRACT);
RNA_def_property_ui_text(prop, "Refraction", "Deliver raytraced refraction pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_emit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_EMIT);
RNA_def_property_ui_text(prop, "Emit", "Deliver emission pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_environment", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_ENVIRONMENT);
RNA_def_property_ui_text(prop, "Environment", "Deliver environment lighting pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_indirect", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_INDIRECT);
RNA_def_property_ui_text(prop, "Indirect", "Deliver indirect lighting pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "exclude_specular", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_SPEC);
RNA_def_property_ui_text(prop, "Specular Exclude", "Exclude specular pass from combined");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "exclude_shadow", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_SHADOW);
RNA_def_property_ui_text(prop, "Shadow Exclude", "Exclude shadow pass from combined");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "exclude_ambient_occlusion", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_AO);
RNA_def_property_ui_text(prop, "AO Exclude", "Exclude AO pass from combined");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "exclude_reflection", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_REFLECT);
RNA_def_property_ui_text(prop, "Reflection Exclude", "Exclude raytraced reflection pass from combined");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "exclude_refraction", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_REFRACT);
RNA_def_property_ui_text(prop, "Refraction Exclude", "Exclude raytraced refraction pass from combined");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "exclude_emit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_EMIT);
RNA_def_property_ui_text(prop, "Emit Exclude", "Exclude emission pass from combined");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "exclude_environment", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_ENVIRONMENT);
RNA_def_property_ui_text(prop, "Environment Exclude", "Exclude environment pass from combined");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "exclude_indirect", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_INDIRECT);
RNA_def_property_ui_text(prop, "Indirect Exclude", "Exclude indirect pass from combined");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_diffuse_direct", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_DIFFUSE_DIRECT);
RNA_def_property_ui_text(prop, "Diffuse Direct", "Deliver diffuse direct pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_diffuse_indirect", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_DIFFUSE_INDIRECT);
RNA_def_property_ui_text(prop, "Diffuse Indirect", "Deliver diffuse indirect pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_diffuse_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_DIFFUSE_COLOR);
RNA_def_property_ui_text(prop, "Diffuse Color", "Deliver diffuse color pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_glossy_direct", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_GLOSSY_DIRECT);
RNA_def_property_ui_text(prop, "Glossy Direct", "Deliver glossy direct pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_glossy_indirect", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_GLOSSY_INDIRECT);
RNA_def_property_ui_text(prop, "Glossy Indirect", "Deliver glossy indirect pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_glossy_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_GLOSSY_COLOR);
RNA_def_property_ui_text(prop, "Glossy Color", "Deliver glossy color pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_transmission_direct", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_TRANSM_DIRECT);
RNA_def_property_ui_text(prop, "Transmission Direct", "Deliver transmission direct pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_transmission_indirect", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_TRANSM_INDIRECT);
RNA_def_property_ui_text(prop, "Transmission Indirect", "Deliver transmission indirect pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_transmission_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_TRANSM_COLOR);
RNA_def_property_ui_text(prop, "Transmission Color", "Deliver transmission color pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_subsurface_direct", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_SUBSURFACE_DIRECT);
RNA_def_property_ui_text(prop, "Subsurface Direct", "Deliver subsurface direct pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_subsurface_indirect", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_SUBSURFACE_INDIRECT);
RNA_def_property_ui_text(prop, "Subsurface Indirect", "Deliver subsurface indirect pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "use_pass_subsurface_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_SUBSURFACE_COLOR);
RNA_def_property_ui_text(prop, "Subsurface Color", "Deliver subsurface color pass");
- if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update");
+ if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
@@ -3760,7 +3576,7 @@ static void rna_def_freestyle_linesets(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
}
-static void rna_def_freestyle_settings(BlenderRNA *brna)
+void rna_def_freestyle_settings(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
@@ -4053,8 +3869,8 @@ static void rna_def_freestyle_settings(BlenderRNA *brna)
srna = RNA_def_struct(brna, "FreestyleSettings", NULL);
RNA_def_struct_sdna(srna, "FreestyleConfig");
- RNA_def_struct_nested(brna, srna, "SceneRenderLayer");
- RNA_def_struct_ui_text(srna, "Freestyle Settings", "Freestyle settings for a SceneRenderLayer data-block");
+ RNA_def_struct_nested(brna, srna, "ViewLayer");
+ RNA_def_struct_ui_text(srna, "Freestyle Settings", "Freestyle settings for a ViewLayer data-block");
prop = RNA_def_property(srna, "modules", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "modules", NULL);
@@ -4780,11 +4596,6 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
"Respect the frame rate from the Physics panel in the world properties "
"rather than rendering as many frames as possible");
- prop = RNA_def_property(srna, "use_display_lists", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GAME_DISPLAY_LISTS);
- RNA_def_property_ui_text(prop, "Display Lists",
- "Use display lists to speed up rendering by keeping geometry on the GPU");
-
prop = RNA_def_property(srna, "use_deprecation_warnings", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GAME_IGNORE_DEPRECATION_WARNINGS);
RNA_def_property_ui_text(prop, "Deprecation Warnings",
@@ -4944,11 +4755,23 @@ static void rna_def_gpu_dof_fx(BlenderRNA *brna)
RNA_def_property_int_funcs(prop, NULL, "rna_GPUDOFSettings_blades_set", NULL);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
+ prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_ui_text(prop, "Rotation", "Rotation of blades in apperture");
+ RNA_def_property_range(prop, -M_PI, M_PI);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "ratio", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Ratio", "Distortion to simulate anamorphic lens bokeh");
+ RNA_def_property_range(prop, 0.0000001f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 1.0f, 2.0f, 0.1, 3);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
prop = RNA_def_property(srna, "use_high_quality", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "high_quality", 1);
RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
+ /* NOTE: high quality is always supported */
prop = RNA_def_property(srna, "is_hq_supported", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_gpu_is_hq_supported_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -5029,77 +4852,46 @@ static void rna_def_gpu_fx(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update");
}
-
-static void rna_def_scene_render_layer(BlenderRNA *brna)
+static void rna_def_view_layers(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
- PropertyRNA *prop;
- FunctionRNA *func;
-
- srna = RNA_def_struct(brna, "SceneRenderLayer", NULL);
- RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer");
- RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
- RNA_def_struct_path_func(srna, "rna_SceneRenderLayer_path");
- RNA_def_struct_idprops_func(srna, "rna_SceneRenderLayer_idprops");
-
- rna_def_render_layer_common(srna, 1);
-
- func = RNA_def_function(srna, "update_render_passes", "rna_SceneRenderLayer_update_render_passes");
- RNA_def_function_ui_description(func, "Requery the enabled render passes from the render engine");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF);
-
- /* Freestyle */
- rna_def_freestyle_settings(brna);
-
- prop = RNA_def_property(srna, "freestyle_settings", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "freestyleConfig");
- RNA_def_property_struct_type(prop, "FreestyleSettings");
- RNA_def_property_ui_text(prop, "Freestyle Settings", "");
-}
-
-/* Render Layers */
-static void rna_def_render_layers(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
FunctionRNA *func;
PropertyRNA *parm;
+ PropertyRNA *prop;
- RNA_def_property_srna(cprop, "RenderLayers");
- srna = RNA_def_struct(brna, "RenderLayers", NULL);
- RNA_def_struct_sdna(srna, "RenderData");
+ RNA_def_property_srna(cprop, "ViewLayers");
+ srna = RNA_def_struct(brna, "ViewLayers", 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, "actlay");
- RNA_def_property_int_funcs(prop, "rna_RenderSettings_active_layer_index_get",
- "rna_RenderSettings_active_layer_index_set",
- "rna_RenderSettings_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_RENDER_OPTIONS, "rna_Scene_glsl_update");
-
+ RNA_def_property_int_sdna(prop, NULL, "active_view_layer");
+ RNA_def_property_int_funcs(prop, "rna_ViewLayer_active_view_layer_index_get",
+ "rna_ViewLayer_active_view_layer_index_set",
+ "rna_ViewLayer_active_view_layer_index_range");
+ RNA_def_property_ui_text(prop, "Active View Layer Index", "Active index in view 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, "SceneRenderLayer");
- RNA_def_property_pointer_funcs(prop, "rna_RenderSettings_active_layer_get",
- "rna_RenderSettings_active_layer_set", NULL, NULL);
+ RNA_def_property_struct_type(prop, "ViewLayer");
+ RNA_def_property_pointer_funcs(prop, "rna_ViewLayer_active_view_layer_get",
+ "rna_ViewLayer_active_view_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_RENDER_OPTIONS, "rna_Scene_glsl_update");
+ RNA_def_property_ui_text(prop, "Active View Layer", "Active View Layer");
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL);
- func = RNA_def_function(srna, "new", "rna_RenderLayer_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", "RenderLayer", 0, "", "New name for the render layer (not unique)");
+ func = RNA_def_function(srna, "new", "rna_ViewLayer_new");
+ RNA_def_function_ui_description(func, "Add a view layer to scene");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_string(func, "name", "ViewLayer", 0, "", "New name for the view layer (not unique)");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- parm = RNA_def_pointer(func, "result", "SceneRenderLayer", "", "Newly created render layer");
+ parm = RNA_def_pointer(func, "result", "ViewLayer", "", "Newly created view layer");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_RenderLayer_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", "SceneRenderLayer", "", "Render layer to remove");
+ func = RNA_def_function(srna, "remove", "rna_ViewLayer_remove");
+ RNA_def_function_ui_description(func, "Remove a view layer");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "layer", "ViewLayer", "", "View 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);
}
@@ -5773,11 +5565,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static const EnumPropertyItem engine_items[] = {
- {0, "BLENDER_RENDER", 0, "Blender Render", "Use the Blender internal rendering engine for rendering"},
- {0, NULL, 0, NULL, NULL}
- };
-
static const EnumPropertyItem freestyle_thickness_items[] = {
{R_LINE_THICKNESS_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Specify unit line thickness in pixels"},
{R_LINE_THICKNESS_RELATIVE, "RELATIVE", 0, "Relative",
@@ -6479,14 +6266,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Depth of Field", "Use depth of field using the values from scene strip active camera");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update");
- /* layers */
- prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "layers", NULL);
- RNA_def_property_struct_type(prop, "SceneRenderLayer");
- RNA_def_property_ui_text(prop, "Render Layers", "");
- rna_def_render_layers(brna, prop);
-
-
prop = RNA_def_property(srna, "use_single_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_SINGLE_LAYER);
RNA_def_property_ui_text(prop, "Single Layer", "Only render the active layer");
@@ -6519,35 +6298,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_enum_funcs(prop, NULL, "rna_RenderSettings_views_format_set", NULL);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, 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_RenderSettings_engine_get", "rna_RenderSettings_engine_set",
- "rna_RenderSettings_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_RenderSettings_engine_update");
-
- prop = RNA_def_property(srna, "has_multiple_engines", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_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");
-
- prop = RNA_def_property(srna, "use_shading_nodes", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_use_shading_nodes_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Use Shading Nodes", "Active render engine uses new shading nodes system");
-
- prop = RNA_def_property(srna, "use_spherical_stereo", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_use_spherical_stereo_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Use Spherical Stereo", "Active render engine supports spherical stereo rendering");
-
- prop = RNA_def_property(srna, "use_game_engine", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_use_game_engine_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Use Game Engine", "Current rendering engine is a game engine");
-
/* simplify */
prop = RNA_def_property(srna, "use_simplify", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_SIMPLIFY);
@@ -6633,61 +6383,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
static void rna_def_scene_objects(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
- PropertyRNA *prop;
- FunctionRNA *func;
- PropertyRNA *parm;
-
RNA_def_property_srna(cprop, "SceneObjects");
srna = RNA_def_struct(brna, "SceneObjects", NULL);
RNA_def_struct_sdna(srna, "Scene");
- RNA_def_struct_ui_text(srna, "Scene Objects", "Collection of scene objects");
-
- func = RNA_def_function(srna, "link", "rna_Scene_object_link");
- RNA_def_function_ui_description(func, "Link object to scene, run scene.update() after");
- 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");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "unlink", "rna_Scene_object_unlink");
- RNA_def_function_ui_description(func, "Unlink object from scene");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove from scene");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
-
- prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_pointer_funcs(prop, "rna_Scene_active_object_get", "rna_Scene_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 scene");
- /* Could call: ED_base_object_activate(C, scene->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);
-}
-
-
-/* scene.bases.* */
-static void rna_def_scene_bases(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
-/* FunctionRNA *func; */
-/* PropertyRNA *parm; */
-
- RNA_def_property_srna(cprop, "SceneBases");
- srna = RNA_def_struct(brna, "SceneBases", NULL);
- RNA_def_struct_sdna(srna, "Scene");
- 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_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");
- RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL);
+ RNA_def_struct_ui_text(srna, "Scene Objects", "All the of scene objects");
}
/* scene.timeline_markers */
@@ -6910,33 +6610,28 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_pointer_funcs(prop, NULL, "rna_Scene_set_set", NULL, NULL);
RNA_def_property_ui_text(prop, "Background Scene", "Background set scene");
- RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_glsl_update");
+ RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_set_update");
prop = RNA_def_property(srna, "world", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "World", "World used for rendering the scene");
- RNA_def_property_update(prop, NC_SCENE | ND_WORLD, "rna_Scene_glsl_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_WORLD, "rna_Scene_world_update");
prop = RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ_LENGTH);
RNA_def_property_float_sdna(prop, NULL, "cursor");
RNA_def_property_ui_text(prop, "Cursor Location", "3D cursor location");
RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 4);
RNA_def_property_update(prop, NC_WINDOW, NULL);
-
- /* 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_ui_text(prop, "Bases", "");
- RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
- "rna_Scene_object_bases_lookup_string", NULL);
- rna_def_scene_bases(brna, prop);
prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "base", NULL);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_ui_text(prop, "Objects", "");
- RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_Scene_objects_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_collection_funcs(prop,
+ "rna_Scene_objects_begin",
+ "rna_Scene_objects_next",
+ "rna_Scene_objects_end",
+ "rna_Scene_objects_get",
+ NULL, NULL, NULL, NULL);
rna_def_scene_objects(brna, prop);
/* Layers */
@@ -7175,7 +6870,26 @@ 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", "");
-
+
+ /* View Render */
+ prop = RNA_def_property(srna, "view_render", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "ViewRenderSettings");
+ RNA_def_property_ui_text(prop, "View Render", "");
+
+ /* Render Engine Data */
+ prop = RNA_def_property(srna, "layer_properties", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "layer_properties->data.group", NULL);
+ RNA_def_property_struct_type(prop, "ViewLayerSettings");
+ RNA_def_property_ui_text(prop, "Layer Settings",
+ "Engine specific render settings to be overridden by layers");
+
+ prop = RNA_def_property(srna, "collection_properties", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "collection_properties->data.group", NULL);
+ RNA_def_property_struct_type(prop, "LayerCollectionSettings");
+ RNA_def_property_ui_text(prop, "Collection Settings",
+ "Engine specific render settings to be overridden by collections");
+
/* Safe Areas */
prop = RNA_def_property(srna, "safe_areas", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "safe_areas");
@@ -7245,6 +6959,8 @@ void RNA_def_scene(BlenderRNA *brna)
/* Statistics */
func = RNA_def_function(srna, "statistics", "ED_info_stats_string");
+ parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "", "Active layer");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_string(func, "statistics", NULL, 0, "Statistics", "");
RNA_def_function_return(func, parm);
@@ -7255,12 +6971,6 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil data-block");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
- /* Transform Orientations */
- prop = RNA_def_property(srna, "orientations", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "transform_spaces", NULL);
- RNA_def_property_struct_type(prop, "TransformOrientation");
- RNA_def_property_ui_text(prop, "Transform Orientations", "");
/* active MovieClip */
prop = RNA_def_property(srna, "active_clip", PROP_POINTER, PROP_NONE);
@@ -7286,10 +6996,18 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "ColorManagedSequencerColorspaceSettings");
RNA_def_property_ui_text(prop, "Sequencer Color Space Settings", "Settings of color space sequencer is working in");
- /* Dependency Graph */
- prop = RNA_def_property(srna, "depsgraph", PROP_POINTER, PROP_NONE);
- 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, "view_layers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "view_layers", NULL);
+ RNA_def_property_struct_type(prop, "ViewLayer");
+ RNA_def_property_ui_text(prop, "View Layers", "");
+ rna_def_view_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 *** */
@@ -7303,13 +7021,11 @@ void RNA_def_scene(BlenderRNA *brna)
rna_def_unit_settings(brna);
rna_def_scene_image_format_data(brna);
rna_def_scene_game_data(brna);
- rna_def_transform_orientation(brna);
rna_def_selected_uv_element(brna);
rna_def_display_safe_areas(brna);
RNA_define_animate_sdna(true);
/* *** Animated *** */
rna_def_scene_render_data(brna);
- rna_def_scene_render_layer(brna);
rna_def_gpu_fx(brna);
rna_def_scene_render_view(brna);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 0f22f8d3b0f..7d8bf4949d5 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -60,7 +60,6 @@ const EnumPropertyItem rna_enum_abc_compression_items[] = {
#ifdef RNA_RUNTIME
#include "BKE_animsys.h"
-#include "BKE_depsgraph.h"
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_image.h"
@@ -86,8 +85,17 @@ static void rna_Scene_frame_set(Scene *scene, Main *bmain, int frame, float subf
BPy_BEGIN_ALLOW_THREADS;
#endif
- /* It's possible that here we're including layers which were never visible before. */
- BKE_scene_update_for_newframe_ex(bmain->eval_ctx, bmain, scene, (1 << 20) - 1, true);
+ for (ViewLayer *view_layer = scene->view_layers.first;
+ view_layer != NULL;
+ view_layer = view_layer->next)
+ {
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx,
+ depsgraph,
+ bmain,
+ scene,
+ view_layer);
+ }
#ifdef WITH_PYTHON
BPy_END_ALLOW_THREADS;
@@ -99,7 +107,7 @@ static void rna_Scene_frame_set(Scene *scene, Main *bmain, int frame, float subf
* redrawing while the data is being modified for render */
if (!G.is_rendering) {
/* cant use NC_SCENE|ND_FRAME because this causes wm_event_do_notifiers to call
- * BKE_scene_update_for_newframe which will loose any un-keyed changes [#24690] */
+ * BKE_scene_graph_update_for_newframe which will loose any un-keyed changes [#24690] */
/* WM_main_add_notifier(NC_SCENE|ND_FRAME, scene); */
/* instead just redraw the views */
@@ -112,7 +120,7 @@ static void rna_Scene_uvedit_aspect(Scene *scene, Object *ob, float *aspect)
if ((ob->type == OB_MESH) && (ob->mode == OB_MODE_EDIT)) {
BMEditMesh *em;
em = BKE_editmesh_from_object(ob);
- if (EDBM_mtexpoly_check(em)) {
+ if (EDBM_uv_check(em)) {
ED_uvedit_get_aspect(scene, ob, em->bm, aspect, aspect + 1);
return;
}
@@ -127,7 +135,17 @@ static void rna_Scene_update_tagged(Scene *scene, Main *bmain)
BPy_BEGIN_ALLOW_THREADS;
#endif
- BKE_scene_update_tagged(bmain->eval_ctx, bmain, scene);
+ for (ViewLayer *view_layer = scene->view_layers.first;
+ view_layer != NULL;
+ view_layer = view_layer->next)
+ {
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ BKE_scene_graph_update_tagged(bmain->eval_ctx,
+ depsgraph,
+ bmain,
+ scene,
+ view_layer);
+ }
#ifdef WITH_PYTHON
BPy_END_ALLOW_THREADS;
@@ -153,14 +171,24 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int previe
}
static void rna_Scene_ray_cast(
- Scene *scene, float origin[3], float direction[3], float ray_dist,
+ Scene *scene, ViewLayer *view_layer, const char *engine_id,
+ float origin[3], float direction[3], float ray_dist,
int *r_success, float r_location[3], float r_normal[3], int *r_index,
Object **r_ob, float r_obmat[16])
{
+ RenderEngineType *engine_type;
+
+ if (engine_id == NULL || engine_id[0] == '\0') {
+ engine_type = RE_engines_find(scene->view_render.engine_id);
+ }
+ else {
+ engine_type = RE_engines_find(engine_id);
+ }
+
normalize_v3(direction);
SnapObjectContext *sctx = ED_transform_snap_object_context_create(
- G.main, scene, 0);
+ G.main, scene, view_layer, engine_type, 0);
bool ret = ED_transform_snap_object_project_ray_ex(
sctx,
@@ -269,6 +297,7 @@ static void rna_Scene_alembic_export(
/* Note: This definition must match to the generated function call */
static void rna_Scene_collada_export(
Scene *scene,
+ bContext *C,
const char *filepath,
int apply_modifiers,
@@ -279,7 +308,7 @@ static void rna_Scene_collada_export(
int include_shapekeys,
int deform_bones_only,
int active_uv_only,
- int export_texture_type,
+ int include_material_textures,
int use_texture_copies,
int triangulate,
int use_object_instantiation,
@@ -290,7 +319,13 @@ static void rna_Scene_collada_export(
int limit_precision,
int keep_bind_info)
{
- collada_export(scene,
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ collada_export(&eval_ctx,
+ scene,
+ CTX_data_view_layer(C),
filepath,
apply_modifiers,
@@ -303,7 +338,7 @@ static void rna_Scene_collada_export(
deform_bones_only,
active_uv_only,
- export_texture_type,
+ include_material_textures,
use_texture_copies,
triangulate,
@@ -349,6 +384,9 @@ void RNA_api_scene(StructRNA *srna)
/* Ray Cast */
func = RNA_def_function(srna, "ray_cast", "rna_Scene_ray_cast");
RNA_def_function_ui_description(func, "Cast a ray onto in object space");
+ parm = RNA_def_pointer(func, "view_layer", "ViewLayer", "", "Scene Layer");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_string(func, "engine", NULL, MAX_NAME, "Engine", "Render engine, use scene one by default");
/* ray start and end */
parm = RNA_def_float_vector(func, "origin", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
@@ -402,8 +440,8 @@ void RNA_api_scene(StructRNA *srna)
RNA_def_boolean(func, "active_uv_only", false, "Only Selected UV Map", "Export only the selected UV Map");
- RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX,
- "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX);
+ RNA_def_boolean(func, "include_material_textures", false,
+ "Include Material Textures", "Export textures assigned to the object Materials");
RNA_def_boolean(func, "use_texture_copies", true,
"Copy", "Copy textures to same folder where the .dae file is exported");
@@ -432,6 +470,8 @@ void RNA_api_scene(StructRNA *srna)
"Keep Bind Info",
"Store bind pose information in custom bone properties for later use during Collada export");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+
#endif
#ifdef WITH_ALEMBIC
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index ce6d60a4ae7..0221a40cb5d 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -35,6 +35,7 @@
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
+#include "DNA_workspace_types.h"
const EnumPropertyItem rna_enum_region_type_items[] = {
{RGN_TYPE_WINDOW, "WINDOW", 0, "Window", ""},
@@ -56,7 +57,9 @@ const EnumPropertyItem rna_enum_region_type_items[] = {
#ifdef RNA_RUNTIME
#include "BKE_global.h"
-#include "BKE_depsgraph.h"
+#include "BKE_workspace.h"
+
+#include "DEG_depsgraph.h"
#include "UI_view2d.h"
@@ -64,55 +67,58 @@ const EnumPropertyItem rna_enum_region_type_items[] = {
# include "BPY_extern.h"
#endif
-static void rna_Screen_scene_set(PointerRNA *ptr, PointerRNA value)
-{
- bScreen *sc = (bScreen *)ptr->data;
- if (value.data == NULL)
- return;
+static void rna_Screen_redraw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bScreen *screen = (bScreen *)ptr->data;
- sc->newscene = value.data;
+ /* the settings for this are currently only available from a menu in the TimeLine, hence refresh=SPACE_TIME */
+ ED_screen_animation_timer_update(screen, screen->redraws_flag, SPACE_TIME);
}
-static void rna_Screen_scene_update(bContext *C, PointerRNA *ptr)
+static int rna_Screen_is_animation_playing_get(PointerRNA *UNUSED(ptr))
{
- bScreen *sc = (bScreen *)ptr->data;
-
- /* exception: must use context so notifier gets to the right window */
- if (sc->newscene) {
-#ifdef WITH_PYTHON
- BPy_BEGIN_ALLOW_THREADS;
-#endif
-
- ED_screen_set_scene(C, sc, sc->newscene);
-
-#ifdef WITH_PYTHON
- BPy_END_ALLOW_THREADS;
-#endif
-
- WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, sc->newscene);
+ /* can be NULL on file load, T42619 */
+ wmWindowManager *wm = G.main->wm.first;
+ return wm ? (ED_screen_animation_playing(wm) != NULL) : 0;
+}
- if (G.debug & G_DEBUG)
- printf("scene set %p\n", sc->newscene);
+static void rna_Screen_layout_name_get(PointerRNA *ptr, char *value)
+{
+ const bScreen *screen = ptr->data;
+ const WorkSpaceLayout *layout = BKE_workspace_layout_find_global(G.main, screen, NULL);
- sc->newscene = NULL;
+ if (layout) {
+ const char *name = BKE_workspace_layout_name_get(layout);
+ strcpy(value, name);
+ }
+ else {
+ value[0] = '\0';
}
}
-static void rna_Screen_redraw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static int rna_Screen_layout_name_length(PointerRNA *ptr)
{
- bScreen *screen = (bScreen *)ptr->data;
+ const bScreen *screen = ptr->data;
+ const WorkSpaceLayout *layout = BKE_workspace_layout_find_global(G.main, screen, NULL);
- /* the settings for this are currently only available from a menu in the TimeLine, hence refresh=SPACE_TIME */
- ED_screen_animation_timer_update(screen, screen->redraws_flag, SPACE_TIME);
-}
+ if (layout) {
+ const char *name = BKE_workspace_layout_name_get(layout);
+ return strlen(name);
+ }
+ return 0;
+}
-static int rna_Screen_is_animation_playing_get(PointerRNA *UNUSED(ptr))
+static void rna_Screen_layout_name_set(PointerRNA *ptr, const char *value)
{
- /* can be NULL on file load, T42619 */
- wmWindowManager *wm = G.main->wm.first;
- return wm ? (ED_screen_animation_playing(wm) != NULL) : 0;
+ bScreen *screen = ptr->data;
+ WorkSpace *workspace;
+ WorkSpaceLayout *layout = BKE_workspace_layout_find_global(G.main, screen, &workspace);
+
+ if (layout) {
+ BKE_workspace_layout_name_set(workspace, layout, value);
+ }
}
static int rna_Screen_fullscreen_get(PointerRNA *ptr)
@@ -152,7 +158,7 @@ static void rna_Area_type_update(bContext *C, PointerRNA *ptr)
/* XXX this call still use context, so we trick it to work in the right context */
for (win = wm->windows.first; win; win = win->next) {
- if (sc == win->screen) {
+ if (sc == WM_window_get_active_screen(win)) {
wmWindow *prevwin = CTX_wm_window(C);
ScrArea *prevsa = CTX_wm_area(C);
ARegion *prevar = CTX_wm_region(C);
@@ -166,7 +172,7 @@ static void rna_Area_type_update(bContext *C, PointerRNA *ptr)
/* It is possible that new layers becomes visible. */
if (sa->spacetype == SPACE_VIEW3D) {
- DAG_on_visible_update(CTX_data_main(C), false);
+ DEG_on_visible_update(CTX_data_main(C), false);
}
CTX_wm_window_set(C, prevwin);
@@ -377,13 +383,11 @@ static void rna_def_screen(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Screen", "Screen data-block, defining the layout of areas in a window");
RNA_def_struct_ui_icon(srna, ICON_SPLITSCREEN);
- /* pointers */
- prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL);
- RNA_def_property_pointer_funcs(prop, NULL, "rna_Screen_scene_set", NULL, NULL);
- RNA_def_property_ui_text(prop, "Scene", "Active scene to be edited in the screen");
- RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, 0, "rna_Screen_scene_update");
+ prop = RNA_def_property(srna, "layout_name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, "rna_Screen_layout_name_get", "rna_Screen_layout_name_length",
+ "rna_Screen_layout_name_set");
+ RNA_def_property_ui_text(prop, "Layout Name", "The name of the layout that refers to the screen");
+ RNA_def_struct_name_property(srna, prop);
/* collections */
prop = RNA_def_property(srna, "areas", PROP_COLLECTION, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 9da27233e0e..ddcf525c3c8 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -106,9 +106,10 @@ const EnumPropertyItem rna_enum_symmetrize_direction_items[] = {
#include "BKE_DerivedMesh.h"
#include "BKE_pointcache.h"
#include "BKE_particle.h"
-#include "BKE_depsgraph.h"
#include "BKE_pbvh.h"
+#include "DEG_depsgraph.h"
+
#include "GPU_buffers.h"
#include "ED_particle.h"
@@ -152,10 +153,12 @@ static PointerRNA rna_ParticleBrush_curve_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_CurveMapping, NULL);
}
-static void rna_ParticleEdit_redo(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_ParticleEdit_redo(bContext *C, PointerRNA *UNUSED(ptr))
{
- Object *ob = (scene->basact) ? scene->basact->object : NULL;
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ PTCacheEdit *edit = PE_get_current(scene, view_layer, ob);
if (!edit)
return;
@@ -163,21 +166,23 @@ static void rna_ParticleEdit_redo(Main *UNUSED(bmain), Scene *scene, PointerRNA
psys_free_path_cache(edit->psys, edit);
}
-static void rna_ParticleEdit_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_ParticleEdit_update(bContext *C, PointerRNA *UNUSED(ptr))
{
- Object *ob = (scene->basact) ? scene->basact->object : NULL;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
- if (ob) DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ if (ob) DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
+
static void rna_ParticleEdit_tool_set(PointerRNA *ptr, int value)
{
ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
/* redraw hair completely if weight brush is/was used */
- if ((pset->brushtype == PE_BRUSH_WEIGHT || value == PE_BRUSH_WEIGHT) && pset->scene) {
- Object *ob = (pset->scene->basact) ? pset->scene->basact->object : NULL;
+ if ((pset->brushtype == PE_BRUSH_WEIGHT || value == PE_BRUSH_WEIGHT) && pset->view_layer) {
+ Object *ob = (pset->view_layer->basact) ? pset->view_layer->basact->object : NULL;
if (ob) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
}
}
@@ -187,9 +192,10 @@ static void rna_ParticleEdit_tool_set(PointerRNA *ptr, int value)
static const EnumPropertyItem *rna_ParticleEdit_tool_itemf(bContext *C, PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = (scene->basact) ? scene->basact->object : NULL;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
#if 0
+ Scene *scene = CTX_data_scene(C);
PTCacheEdit *edit = PE_get_current(scene, ob);
ParticleSystem *psys = edit ? edit->psys : NULL;
#else
@@ -215,14 +221,14 @@ static int rna_ParticleEdit_editable_get(PointerRNA *ptr)
{
ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
- return (pset->object && pset->scene && PE_get_current(pset->scene, pset->object));
+ return (pset->object && pset->scene && PE_get_current(pset->scene, pset->view_layer, pset->object));
}
static int rna_ParticleEdit_hair_get(PointerRNA *ptr)
{
ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
if (pset->scene) {
- PTCacheEdit *edit = PE_get_current(pset->scene, pset->object);
+ PTCacheEdit *edit = PE_get_current(pset->scene, pset->view_layer, pset->object);
return (edit && edit->psys);
}
@@ -257,12 +263,14 @@ static int rna_Brush_mode_poll(PointerRNA *ptr, PointerRNA value)
return brush->ob_mode & mode;
}
-static void rna_Sculpt_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_Sculpt_update(bContext *C, PointerRNA *UNUSED(ptr))
{
- Object *ob = (scene->basact) ? scene->basact->object : NULL;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
if (ob) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
if (ob->sculpt) {
@@ -272,11 +280,13 @@ static void rna_Sculpt_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNU
}
}
-static void rna_Sculpt_ShowDiffuseColor_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_Sculpt_ShowDiffuseColor_update(bContext *C, PointerRNA *UNUSED(ptr))
{
- Object *ob = (scene->basact) ? scene->basact->object : NULL;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
if (ob && ob->sculpt) {
+ Scene *scene = CTX_data_scene(C);
Sculpt *sd = scene->toolsettings->sculpt;
ob->sculpt->show_diffuse_color = ((sd->flags & SCULPT_SHOW_DIFFUSE) != 0);
@@ -333,9 +343,11 @@ static void rna_ImaPaint_viewport_update(Main *UNUSED(bmain), Scene *UNUSED(scen
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
-static void rna_ImaPaint_mode_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_ImaPaint_mode_update(bContext *C, PointerRNA *UNUSED(ptr))
{
- Object *ob = OBACT;
+ Scene *scene = CTX_data_scene(C);\
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
if (ob && ob->type == OB_MESH) {
/* of course we need to invalidate here */
@@ -348,9 +360,11 @@ static void rna_ImaPaint_mode_update(Main *UNUSED(bmain), Scene *scene, PointerR
}
}
-static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_ImaPaint_stencil_update(bContext *C, PointerRNA *UNUSED(ptr))
{
- Object *ob = OBACT;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
if (ob && ob->type == OB_MESH) {
GPU_drawobject_free(ob->derivedFinal);
@@ -359,19 +373,22 @@ static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *scene, Point
}
}
-static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_ImaPaint_canvas_update(bContext *C, PointerRNA *UNUSED(ptr))
{
- Object *ob = OBACT;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
bScreen *sc;
Image *ima = scene->toolsettings->imapaint.canvas;
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
+ SpaceLink *slink;
+ for (slink = sa->spacedata.first; slink; slink = slink->next) {
+ if (slink->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)slink;
if (!sima->pin)
ED_space_image_set(sima, scene, scene->obedit, ima);
@@ -586,12 +603,14 @@ static void rna_def_sculpt(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Deform Only",
"Use only deformation modifiers (temporary disable all "
"constructive modifiers except multi-resolution)");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_update");
prop = RNA_def_property(srna, "show_diffuse_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_SHOW_DIFFUSE);
RNA_def_property_ui_text(prop, "Show Diffuse Color",
"Show diffuse color of object and overlay sculpt mask on top of it");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_ShowDiffuseColor_update");
prop = RNA_def_property(srna, "detail_size", PROP_FLOAT, PROP_PIXEL);
@@ -617,6 +636,7 @@ static void rna_def_sculpt(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Smooth Shading",
"Show faces in dynamic-topology mode with smooth "
"shading rather than flat shaded");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_update");
prop = RNA_def_property(srna, "symmetrize_direction", PROP_ENUM, PROP_NONE);
@@ -742,12 +762,12 @@ static void rna_def_image_paint(BlenderRNA *brna)
prop = RNA_def_property(srna, "stencil_image", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "stencil");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Stencil Image", "Image used as stencil");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
prop = RNA_def_property(srna, "canvas", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Canvas", "Image used as canvas");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_canvas_update");
@@ -789,6 +809,7 @@ static void rna_def_image_paint(BlenderRNA *brna)
RNA_def_property_range(prop, 512, 16384);
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_enum_items(prop, paint_type_items);
RNA_def_property_ui_text(prop, "Mode", "Mode of operation for projection painting");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_mode_update");
@@ -868,6 +889,7 @@ static void rna_def_particle_edit(BlenderRNA *brna)
RNA_def_property_enum_bitflag_sdna(prop, NULL, "selectmode");
RNA_def_property_enum_items(prop, select_mode_items);
RNA_def_property_ui_text(prop, "Selection Mode", "Particle select and display mode");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_update");
prop = RNA_def_property(srna, "use_preserve_length", PROP_BOOLEAN, PROP_NONE);
@@ -890,6 +912,7 @@ static void rna_def_particle_edit(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_fade_time", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_FADE_TIME);
RNA_def_property_ui_text(prop, "Fade Time", "Fade paths and keys further away from current frame");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_update");
prop = RNA_def_property(srna, "use_auto_velocity", PROP_BOOLEAN, PROP_NONE);
@@ -897,6 +920,7 @@ static void rna_def_particle_edit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Auto Velocity", "Calculate point velocities automatically");
prop = RNA_def_property(srna, "show_particles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_DRAW_PART);
RNA_def_property_ui_text(prop, "Draw Particles", "Draw actual particles");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_redo");
@@ -917,6 +941,7 @@ static void rna_def_particle_edit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Brush", "");
prop = RNA_def_property(srna, "draw_step", PROP_INT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 1, 10);
RNA_def_property_ui_text(prop, "Steps", "How many steps to draw the path with");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_redo");
@@ -924,9 +949,11 @@ static void rna_def_particle_edit(BlenderRNA *brna)
prop = RNA_def_property(srna, "fade_frames", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 1, 100);
RNA_def_property_ui_text(prop, "Frames", "How many frames to fade");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_update");
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_enum_sdna(prop, NULL, "edittype");
RNA_def_property_enum_items(prop, edit_type_items);
RNA_def_property_ui_text(prop, "Type", "");
@@ -947,7 +974,7 @@ static void rna_def_particle_edit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Object", "The edited object");
prop = RNA_def_property(srna, "shape_object", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Shape Object", "Outer shape to use for tools");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_redo");
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index 9b206f3ee12..ac13f9d8294 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -54,21 +54,23 @@
#include "BKE_colorband.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_particle.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "smoke_API.h"
static void rna_Smoke_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
}
static void rna_Smoke_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_Smoke_update(bmain, scene, ptr);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
static void rna_Smoke_resetCache(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -76,7 +78,7 @@ static void rna_Smoke_resetCache(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin
SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
if (settings->smd && settings->smd->domain)
settings->point_cache[0]->flag |= PTCACHE_OUTDATED;
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
}
static void rna_Smoke_cachetype_set(struct PointerRNA *ptr, int value)
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index ebbebb32974..aa3f159af40 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -45,6 +45,7 @@
#include "DNA_sequence_types.h"
#include "DNA_mask_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_workspace_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -196,7 +197,7 @@ const EnumPropertyItem rna_enum_clip_editor_mode_items[] = {
static const EnumPropertyItem buttons_context_items[] = {
{BCONTEXT_SCENE, "SCENE", ICON_SCENE_DATA, "Scene", "Scene"},
{BCONTEXT_RENDER, "RENDER", ICON_SCENE, "Render", "Render"},
- {BCONTEXT_RENDER_LAYER, "RENDER_LAYER", ICON_RENDERLAYERS, "Render Layers", "Render layers"},
+ {BCONTEXT_VIEW_LAYER, "VIEW_LAYER", ICON_RENDERLAYERS, "View Layers", "View layers"},
{BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World"},
{BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object"},
{BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraints", "Object constraints"},
@@ -208,6 +209,8 @@ static const 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"},
+ {BCONTEXT_WORKSPACE, "WORKSPACE", ICON_RENDER_RESULT, "Workspace", "Workspace"},
{0, NULL, 0, NULL, NULL}
};
@@ -222,6 +225,11 @@ static const EnumPropertyItem buttons_texture_context_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static const EnumPropertyItem buttons_collection_context_items[] = {
+ {SB_COLLECTION_CTX_VIEW_LAYER, "VIEW_LAYER", ICON_RENDERLAYERS, "", "Show material textures"},
+ {SB_COLLECTION_CTX_GROUP, "GROUP", ICON_GROUP, "", "Show world textures"},
+ {0, NULL, 0, NULL, NULL}
+};
static const EnumPropertyItem fileselectparams_recursion_level_items[] = {
{0, "NONE", 0, "None", "Only list current directory's content, with no recursion"},
@@ -253,17 +261,23 @@ const EnumPropertyItem rna_enum_file_sort_items[] = {
#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
+#include "BKE_global.h"
#include "BKE_nla.h"
#include "BKE_paint.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_icons.h"
+#include "BKE_workspace.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
#include "ED_buttons.h"
#include "ED_fileselect.h"
#include "ED_image.h"
#include "ED_node.h"
+#include "ED_transform.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_sequencer.h"
@@ -403,44 +417,64 @@ static void rna_Space_view2d_sync_update(Main *UNUSED(bmain), Scene *UNUSED(scen
}
}
-static PointerRNA rna_CurrentOrientation_get(PointerRNA *ptr)
+static int rna_View3D_transform_orientation_get(PointerRNA *ptr)
+{
+ const View3D *v3d = (View3D *)ptr->data;
+ /* convert to enum value */
+ return (v3d->twmode == V3D_MANIP_CUSTOM) ? (v3d->twmode + v3d->custom_orientation_index) : v3d->twmode;
+}
+
+void rna_View3D_transform_orientation_set(PointerRNA *ptr, int value)
{
- Scene *scene = ((bScreen *)ptr->id.data)->scene;
View3D *v3d = (View3D *)ptr->data;
+ BIF_selectTransformOrientationValue(v3d, value);
+}
- if (v3d->twmode < V3D_MANIP_CUSTOM)
- return rna_pointer_inherit_refine(ptr, &RNA_TransformOrientation, NULL);
- else
- return rna_pointer_inherit_refine(ptr, &RNA_TransformOrientation,
- BLI_findlink(&scene->transform_spaces, v3d->twmode - V3D_MANIP_CUSTOM));
+static PointerRNA rna_View3D_current_orientation_get(PointerRNA *ptr)
+{
+ View3D *v3d = (View3D *)ptr->data;
+ TransformOrientation *orientation;
+
+ if (v3d->twmode < V3D_MANIP_CUSTOM) {
+ orientation = NULL;
+ }
+ else {
+ WorkSpace *workspace;
+ bScreen *screen = ptr->id.data;
+
+ BKE_workspace_layout_find_global(G.main, screen, &workspace);
+ orientation = BKE_workspace_transform_orientation_find(workspace, v3d->custom_orientation_index);
+ }
+
+ return rna_pointer_inherit_refine(ptr, &RNA_TransformOrientation, orientation);
}
const EnumPropertyItem *rna_TransformOrientation_itemf(
bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
- Scene *scene = NULL;
- ListBase *transform_spaces;
- TransformOrientation *ts = NULL;
+ WorkSpace *workspace;
+ ListBase *transform_orientations;
EnumPropertyItem tmp = {0, "", 0, "", ""};
EnumPropertyItem *item = NULL;
int i = V3D_MANIP_CUSTOM, totitem = 0;
RNA_enum_items_add(&item, &totitem, transform_orientation_items);
- if (ptr->type == &RNA_SpaceView3D)
- scene = ((bScreen *)ptr->id.data)->scene;
- else
- scene = CTX_data_scene(C); /* can't use scene from ptr->id.data because that enum is also used by operators */
-
- if (scene) {
- transform_spaces = &scene->transform_spaces;
- ts = transform_spaces->first;
+ if (ptr->type == &RNA_SpaceView3D) {
+ bScreen *screen = ptr->id.data;
+ BKE_workspace_layout_find_global(G.main, screen, &workspace);
+ }
+ else {
+ /* can't use scene from ptr->id.data because that enum is also used by operators */
+ workspace = C ? CTX_wm_workspace(C) : NULL;
}
- if (ts) {
+ transform_orientations = workspace ? BKE_workspace_transform_orientations_get(workspace) : NULL;
+
+ if (transform_orientations && (BLI_listbase_is_empty(transform_orientations) == false)) {
RNA_enum_item_add_separator(&item, &totitem);
- for (; ts; ts = ts->next) {
+ for (TransformOrientation *ts = transform_orientations->first; ts; ts = ts->next) {
tmp.identifier = ts->name;
tmp.name = ts->name;
tmp.value = i++;
@@ -459,8 +493,10 @@ static void rna_SpaceView3D_camera_update(Main *bmain, Scene *scene, PointerRNA
{
View3D *v3d = (View3D *)(ptr->data);
if (v3d->scenelock) {
+ wmWindowManager *wm = bmain->wm.first;
+
scene->camera = v3d->camera;
- BKE_screen_view3d_main_sync(&bmain->screen, scene);
+ WM_windows_scene_data_sync(&wm->windows, scene);
}
}
@@ -472,8 +508,10 @@ static void rna_SpaceView3D_lock_camera_and_layers_set(PointerRNA *ptr, int valu
v3d->scenelock = value;
if (value) {
+ Scene *scene = ED_screen_scene_find(sc, G.main->wm.first);
int bit;
- v3d->lay = sc->scene->lay;
+
+ v3d->lay = scene->lay;
/* seek for layact */
bit = 0;
while (bit < 32) {
@@ -483,15 +521,15 @@ static void rna_SpaceView3D_lock_camera_and_layers_set(PointerRNA *ptr, int valu
}
bit++;
}
- v3d->camera = sc->scene->camera;
+ v3d->camera = scene->camera;
}
}
static void rna_View3D_CursorLocation_get(PointerRNA *ptr, float *values)
{
View3D *v3d = (View3D *)(ptr->data);
- bScreen *sc = (bScreen *)ptr->id.data;
- Scene *scene = (Scene *)sc->scene;
+ bScreen *screen = ptr->id.data;
+ Scene *scene = ED_screen_scene_find(screen, G.main->wm.first);
const float *loc = ED_view3d_cursor3d_get(scene, v3d);
copy_v3_v3(values, loc);
@@ -500,8 +538,8 @@ static void rna_View3D_CursorLocation_get(PointerRNA *ptr, float *values)
static void rna_View3D_CursorLocation_set(PointerRNA *ptr, const float *values)
{
View3D *v3d = (View3D *)(ptr->data);
- bScreen *sc = (bScreen *)ptr->id.data;
- Scene *scene = (Scene *)sc->scene;
+ bScreen *screen = ptr->id.data;
+ Scene *scene = ED_screen_scene_find(screen, G.main->wm.first);
float *cursor = ED_view3d_cursor3d_get(scene, v3d);
copy_v3_v3(cursor, values);
@@ -510,8 +548,8 @@ static void rna_View3D_CursorLocation_set(PointerRNA *ptr, const float *values)
static float rna_View3D_GridScaleUnit_get(PointerRNA *ptr)
{
View3D *v3d = (View3D *)(ptr->data);
- bScreen *sc = (bScreen *)ptr->id.data;
- Scene *scene = (Scene *)sc->scene;
+ bScreen *screen = ptr->id.data;
+ Scene *scene = ED_screen_scene_find(screen, G.main->wm.first);
return ED_view3d_grid_scale(scene, v3d, NULL);
}
@@ -520,7 +558,7 @@ static void rna_SpaceView3D_layer_set(PointerRNA *ptr, const int *values)
{
View3D *v3d = (View3D *)(ptr->data);
- v3d->lay = ED_view3d_scene_layer_set(v3d->lay, values, &v3d->layact);
+ v3d->lay = ED_view3d_view_layer_set(v3d->lay, values, &v3d->layact);
}
static int rna_SpaceView3D_active_layer_get(PointerRNA *ptr)
@@ -532,7 +570,7 @@ static int rna_SpaceView3D_active_layer_get(PointerRNA *ptr)
static void rna_SpaceView3D_layer_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
- DAG_on_visible_update(bmain, false);
+ DEG_on_visible_update(bmain, false);
}
static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -695,12 +733,18 @@ static void rna_RegionView3D_view_matrix_set(PointerRNA *ptr, const float *value
static int rna_SpaceView3D_viewport_shade_get(PointerRNA *ptr)
{
- Scene *scene = ((bScreen *)ptr->id.data)->scene;
- RenderEngineType *type = RE_engines_find(scene->r.engine);
+ bScreen *screen = ptr->id.data;
+
+ Scene *scene = WM_windows_scene_get_from_screen(G.main->wm.first, screen);
+ WorkSpace *workspace = WM_windows_workspace_get_from_screen(G.main->wm.first, screen);
+
+ ViewRender *view_render = BKE_viewrender_get(scene, workspace);
+ RenderEngineType *type = RE_engines_find(view_render->engine_id);
+
View3D *v3d = (View3D *)ptr->data;
int drawtype = v3d->drawtype;
- if (drawtype == OB_RENDER && !(type && type->view_draw))
+ if (drawtype == OB_RENDER && !(type && type->render_to_view))
return OB_SOLID;
return drawtype;
@@ -715,11 +759,14 @@ static void rna_SpaceView3D_viewport_shade_set(PointerRNA *ptr, int value)
v3d->drawtype = value;
}
-static const EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+static const EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *C, PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), bool *r_free)
{
- Scene *scene = ((bScreen *)ptr->id.data)->scene;
- RenderEngineType *type = RE_engines_find(scene->r.engine);
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = WM_window_get_active_scene(win);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ ViewRender *view_render = BKE_viewrender_get(scene, workspace);
+ RenderEngineType *type = RE_engines_find(view_render->engine_id);
EnumPropertyItem *item = NULL;
int totitem = 0;
@@ -730,7 +777,7 @@ static const EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UN
RNA_enum_items_add_value(&item, &totitem, rna_enum_viewport_shade_items, OB_TEXTURE);
RNA_enum_items_add_value(&item, &totitem, rna_enum_viewport_shade_items, OB_MATERIAL);
- if (type && type->view_draw)
+ if (type && type->render_to_view)
RNA_enum_items_add_value(&item, &totitem, rna_enum_viewport_shade_items, OB_RENDER);
RNA_enum_item_end(&item, &totitem);
@@ -739,10 +786,10 @@ static const EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UN
return item;
}
-static const EnumPropertyItem *rna_SpaceView3D_stereo3d_camera_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+static const EnumPropertyItem *rna_SpaceView3D_stereo3d_camera_itemf(bContext *C, PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
{
- Scene *scene = ((bScreen *)ptr->id.data)->scene;
+ Scene *scene = CTX_data_scene(C);
if (scene->r.views_format == SCE_VIEWS_FORMAT_MULTIVIEW)
return multiview_camera_items;
@@ -810,22 +857,28 @@ static int rna_SpaceImageEditor_show_uvedit_get(PointerRNA *ptr)
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
bScreen *sc = (bScreen *)ptr->id.data;
- return ED_space_image_show_uvedit(sima, sc->scene->obedit);
+ Scene *scene = ED_screen_scene_find(sc, G.main->wm.first);
+
+ return ED_space_image_show_uvedit(sima, scene->obedit);
}
static int rna_SpaceImageEditor_show_maskedit_get(PointerRNA *ptr)
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
bScreen *sc = (bScreen *)ptr->id.data;
- return ED_space_image_check_show_maskedit(sc->scene, sima);
+ Scene *scene = ED_screen_scene_find(sc, G.main->wm.first);
+ ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
+
+ return ED_space_image_check_show_maskedit(view_layer, sima);
}
static void rna_SpaceImageEditor_image_set(PointerRNA *ptr, PointerRNA value)
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
bScreen *sc = (bScreen *)ptr->id.data;
+ Scene *scene = ED_screen_scene_find(sc, G.main->wm.first);
- ED_space_image_set(sima, sc->scene, sc->scene->obedit, (Image *)value.data);
+ ED_space_image_set(sima, scene, scene->obedit, (Image *)value.data);
}
static void rna_SpaceImageEditor_mask_set(PointerRNA *ptr, PointerRNA value)
@@ -1071,8 +1124,8 @@ static const EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSE
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_RENDER);
}
- if (sbuts->pathflag & (1 << BCONTEXT_RENDER_LAYER)) {
- RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_RENDER_LAYER);
+ if (sbuts->pathflag & (1 << BCONTEXT_VIEW_LAYER)) {
+ RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_VIEW_LAYER);
}
if (sbuts->pathflag & (1 << BCONTEXT_SCENE)) {
@@ -1083,6 +1136,14 @@ static const EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSE
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_WORLD);
}
+ if (sbuts->pathflag & (1 << BCONTEXT_WORKSPACE)) {
+ RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_WORKSPACE);
+ }
+
+ if (sbuts->pathflag & (1 << BCONTEXT_COLLECTION)) {
+ RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_COLLECTION);
+ }
+
if (sbuts->pathflag & (1 << BCONTEXT_OBJECT)) {
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_OBJECT);
}
@@ -1264,10 +1325,12 @@ static void rna_SpaceDopeSheetEditor_action_set(PointerRNA *ptr, PointerRNA valu
}
}
-static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr)
{
SpaceAction *saction = (SpaceAction *)(ptr->data);
- Object *obact = (scene->basact) ? scene->basact->object : NULL;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Main *bmain = CTX_data_main(C);
+ Object *obact = OBACT(view_layer);
/* we must set this action to be the one used by active object (if not pinned) */
if (obact /* && saction->pin == 0*/) {
@@ -1333,16 +1396,17 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, Po
}
/* force depsgraph flush too */
- DAG_id_tag_update(&obact->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&obact->id, OB_RECALC_OB | OB_RECALC_DATA);
/* Update relations as well, so new time source dependency is added. */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
}
-static void rna_SpaceDopeSheetEditor_mode_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_SpaceDopeSheetEditor_mode_update(bContext *C, PointerRNA *ptr)
{
SpaceAction *saction = (SpaceAction *)(ptr->data);
- Object *obact = (scene->basact) ? scene->basact->object : NULL;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obact = OBACT(view_layer);
/* special exceptions for ShapeKey Editor mode */
if (saction->mode == SACTCONT_SHAPEKEY) {
@@ -1404,59 +1468,6 @@ static void rna_Sequencer_view_type_update(Main *UNUSED(bmain), Scene *UNUSED(sc
ED_area_tag_refresh(sa);
}
-static float rna_BackgroundImage_opacity_get(PointerRNA *ptr)
-{
- BGpic *bgpic = (BGpic *)ptr->data;
- return 1.0f - bgpic->blend;
-}
-
-static void rna_BackgroundImage_opacity_set(PointerRNA *ptr, float value)
-{
- BGpic *bgpic = (BGpic *)ptr->data;
- bgpic->blend = 1.0f - value;
-}
-
-/* radius internally (expose as a distance value) */
-static float rna_BackgroundImage_size_get(PointerRNA *ptr)
-{
- BGpic *bgpic = ptr->data;
- return bgpic->size * 2.0f;
-}
-
-static void rna_BackgroundImage_size_set(PointerRNA *ptr, float value)
-{
- BGpic *bgpic = ptr->data;
- bgpic->size = value * 0.5f;
-}
-
-static BGpic *rna_BackgroundImage_new(View3D *v3d)
-{
- BGpic *bgpic = ED_view3D_background_image_new(v3d);
-
- WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, v3d);
-
- return bgpic;
-}
-
-static void rna_BackgroundImage_remove(View3D *v3d, ReportList *reports, PointerRNA *bgpic_ptr)
-{
- BGpic *bgpic = bgpic_ptr->data;
- if (BLI_findindex(&v3d->bgpicbase, bgpic) == -1) {
- BKE_report(reports, RPT_ERROR, "Background image cannot be removed");
- }
-
- ED_view3D_background_image_remove(v3d, bgpic);
- RNA_POINTER_INVALIDATE(bgpic_ptr);
-
- WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, v3d);
-}
-
-static void rna_BackgroundImage_clear(View3D *v3d)
-{
- ED_view3D_background_image_clear(v3d);
- WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, v3d);
-}
-
/* Space Node Editor */
static void rna_SpaceNodeEditor_node_tree_set(PointerRNA *ptr, const PointerRNA value)
@@ -2104,6 +2115,9 @@ 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_ACT_LAYER, "ACT_LAYER", 0, "Active View Layer", "Display the collections of the active view layer"},
+ {SO_COLLECTIONS, "MASTER_COLLECTION", 0, "Master Collection Tree", "Display all collections based on the "
+ "master collection hierarchy"},
{0, NULL, 0, NULL, NULL}
};
@@ -2144,194 +2158,6 @@ static void rna_def_space_outliner(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
}
-static void rna_def_background_image(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- /* note: combinations work but don't flip so arnt that useful */
- static const EnumPropertyItem bgpic_axis_items[] = {
- {0, "", 0, N_("X Axis"), ""},
- {(1 << RV3D_VIEW_LEFT), "LEFT", 0, "Left", "Show background image while looking to the left"},
- {(1 << RV3D_VIEW_RIGHT), "RIGHT", 0, "Right", "Show background image while looking to the right"},
- /*{(1<<RV3D_VIEW_LEFT)|(1<<RV3D_VIEW_RIGHT), "LEFT_RIGHT", 0, "Left/Right", ""},*/
- {0, "", 0, N_("Y Axis"), ""},
- {(1 << RV3D_VIEW_BACK), "BACK", 0, "Back", "Show background image in back view"},
- {(1 << RV3D_VIEW_FRONT), "FRONT", 0, "Front", "Show background image in front view"},
- /*{(1<<RV3D_VIEW_BACK)|(1<<RV3D_VIEW_FRONT), "BACK_FRONT", 0, "Back/Front", ""},*/
- {0, "", 0, N_("Z Axis"), ""},
- {(1 << RV3D_VIEW_BOTTOM), "BOTTOM", 0, "Bottom", "Show background image in bottom view"},
- {(1 << RV3D_VIEW_TOP), "TOP", 0, "Top", "Show background image in top view"},
- /*{(1<<RV3D_VIEW_BOTTOM)|(1<<RV3D_VIEW_TOP), "BOTTOM_TOP", 0, "Top/Bottom", ""},*/
- {0, "", 0, N_("Other"), ""},
- {0, "ALL", 0, "All Views", "Show background image in all views"},
- {(1 << RV3D_VIEW_CAMERA), "CAMERA", 0, "Camera", "Show background image in camera view"},
- {0, NULL, 0, NULL, NULL}
- };
-
- static const EnumPropertyItem bgpic_source_items[] = {
- {V3D_BGPIC_IMAGE, "IMAGE", 0, "Image", ""},
- {V3D_BGPIC_MOVIE, "MOVIE_CLIP", 0, "Movie Clip", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static const EnumPropertyItem bgpic_camera_frame_items[] = {
- {0, "STRETCH", 0, "Stretch", ""},
- {V3D_BGPIC_CAMERA_ASPECT, "FIT", 0, "Fit", ""},
- {V3D_BGPIC_CAMERA_ASPECT | V3D_BGPIC_CAMERA_CROP, "CROP", 0, "Crop", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static const EnumPropertyItem bgpic_draw_depth_items[] = {
- {0, "BACK", 0, "Back", ""},
- {V3D_BGPIC_FOREGROUND, "FRONT", 0, "Front", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "BackgroundImage", NULL);
- RNA_def_struct_sdna(srna, "BGpic");
- RNA_def_struct_ui_text(srna, "Background Image", "Image and settings for display in the 3D View background");
-
- prop = RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "source");
- RNA_def_property_enum_items(prop, bgpic_source_items);
- RNA_def_property_ui_text(prop, "Background Source", "Data source used for background");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "ima");
- RNA_def_property_ui_text(prop, "Image", "Image displayed and edited in this space");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "clip");
- RNA_def_property_ui_text(prop, "MovieClip", "Movie clip displayed and edited in this space");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "iuser");
- RNA_def_property_ui_text(prop, "Image User",
- "Parameters defining which layer, pass and frame of the image is displayed");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "clip_user", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_struct_type(prop, "MovieClipUser");
- RNA_def_property_pointer_sdna(prop, NULL, "cuser");
- RNA_def_property_ui_text(prop, "Clip User", "Parameters defining which frame of the movie clip is displayed");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "offset_x", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "xof");
- RNA_def_property_ui_text(prop, "X Offset", "Offset image horizontally from the world origin");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "offset_y", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "yof");
- RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically from the world origin");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_float_sdna(prop, NULL, "size");
- RNA_def_property_float_funcs(prop, "rna_BackgroundImage_size_get", "rna_BackgroundImage_size_set", NULL);
- RNA_def_property_ui_text(prop, "Size", "Size of the background image (ortho view only)");
- RNA_def_property_range(prop, 0.0, FLT_MAX);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER);
- RNA_def_property_float_sdna(prop, NULL, "rotation");
- RNA_def_property_ui_text(prop, "Rotation", "Rotation for the background image (ortho view only)");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_BGPIC_FLIP_X);
- RNA_def_property_ui_text(prop, "Flip Horizontally", "Flip the background image horizontally");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "use_flip_y", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_BGPIC_FLIP_Y);
- RNA_def_property_ui_text(prop, "Flip Vertically", "Flip the background image vertically");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "opacity", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "blend");
- RNA_def_property_float_funcs(prop, "rna_BackgroundImage_opacity_get", "rna_BackgroundImage_opacity_set", NULL);
- RNA_def_property_ui_text(prop, "Opacity", "Image opacity to blend the image against the background color");
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "view_axis", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "view");
- RNA_def_property_enum_items(prop, bgpic_axis_items);
- RNA_def_property_ui_text(prop, "Image Axis", "The axis to display the image on");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_BGPIC_EXPANDED);
- RNA_def_property_ui_text(prop, "Show Expanded", "Show the expanded in the user interface");
- RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1);
-
- prop = RNA_def_property(srna, "use_camera_clip", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_BGPIC_CAMERACLIP);
- RNA_def_property_ui_text(prop, "Camera Clip", "Use movie clip from active scene camera");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "show_background_image", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", V3D_BGPIC_DISABLED);
- RNA_def_property_ui_text(prop, "Show Background Image", "Show this image as background");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "show_on_foreground", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_BGPIC_FOREGROUND);
- RNA_def_property_ui_text(prop, "Show On Foreground", "Show this image in front of objects in viewport");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- /* expose 1 flag as a enum of 2 items */
- prop = RNA_def_property(srna, "draw_depth", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
- RNA_def_property_enum_items(prop, bgpic_draw_depth_items);
- RNA_def_property_ui_text(prop, "Depth", "Draw under or over everything");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- /* expose 2 flags as a enum of 3 items */
- prop = RNA_def_property(srna, "frame_method", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
- RNA_def_property_enum_items(prop, bgpic_camera_frame_items);
- RNA_def_property_ui_text(prop, "Frame Method", "How the image fits in the camera frame");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-}
-
-static void rna_def_backgroundImages(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- FunctionRNA *func;
- PropertyRNA *parm;
-
- RNA_def_property_srna(cprop, "BackgroundImages");
- srna = RNA_def_struct(brna, "BackgroundImages", NULL);
- RNA_def_struct_sdna(srna, "View3D");
- RNA_def_struct_ui_text(srna, "Background Images", "Collection of background images");
-
- func = RNA_def_function(srna, "new", "rna_BackgroundImage_new");
- RNA_def_function_ui_description(func, "Add new background image");
- parm = RNA_def_pointer(func, "image", "BackgroundImage", "", "Image displayed as viewport background");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "remove", "rna_BackgroundImage_remove");
- RNA_def_function_ui_description(func, "Remove background image");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "image", "BackgroundImage", "", "Image displayed as viewport background");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
- RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
-
- func = RNA_def_function(srna, "clear", "rna_BackgroundImage_clear");
- RNA_def_function_ui_description(func, "Remove all background images");
-}
-
-
static void rna_def_space_view3d(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2576,9 +2402,9 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Backface Culling", "Use back face culling to hide the back side of faces");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- prop = RNA_def_property(srna, "show_textured_shadeless", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SHADELESS_TEX);
- RNA_def_property_ui_text(prop, "Shadeless", "Show shadeless texture without lighting in textured draw mode");
+ prop = RNA_def_property(srna, "show_mode_shade_override", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SHOW_MODE_SHADE_OVERRIDE);
+ RNA_def_property_ui_text(prop, "Full Shading", "Use full shading for mode drawing (to view final result)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_occlude_wire", PROP_BOOLEAN, PROP_NONE);
@@ -2607,19 +2433,6 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_ORTHO, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- prop = RNA_def_property(srna, "background_images", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "bgpicbase", NULL);
- RNA_def_property_struct_type(prop, "BackgroundImage");
- RNA_def_property_ui_text(prop, "Background Images", "List of background images");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
- rna_def_backgroundImages(brna, prop);
-
- prop = RNA_def_property(srna, "show_background_images", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_DISPBGPICS);
- RNA_def_property_ui_text(prop, "Display Background Images",
- "Display reference images behind objects in the 3D View");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "around");
RNA_def_property_enum_items(prop, pivot_items_full);
@@ -2633,7 +2446,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_pivot_update");
prop = RNA_def_property(srna, "show_manipulator", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "twflag", V3D_USE_MANIPULATOR);
+ RNA_def_property_boolean_sdna(prop, NULL, "twflag", V3D_MANIPULATOR_DRAW);
RNA_def_property_ui_text(prop, "Manipulator", "Use a 3D manipulator widget for controlling transforms");
RNA_def_property_ui_icon(prop, ICON_MANIPUL, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
@@ -2648,13 +2461,14 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop = RNA_def_property(srna, "transform_orientation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "twmode");
RNA_def_property_enum_items(prop, transform_orientation_items);
- RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_TransformOrientation_itemf");
+ RNA_def_property_enum_funcs(prop, "rna_View3D_transform_orientation_get", "rna_View3D_transform_orientation_set",
+ "rna_TransformOrientation_itemf");
RNA_def_property_ui_text(prop, "Transform Orientation", "Transformation orientation");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "current_orientation", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "TransformOrientation");
- RNA_def_property_pointer_funcs(prop, "rna_CurrentOrientation_get", NULL, NULL, NULL);
+ RNA_def_property_pointer_funcs(prop, "rna_View3D_current_orientation_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Current Transform Orientation", "Current transformation orientation");
prop = RNA_def_property(srna, "lock_camera_and_layers", PROP_BOOLEAN, PROP_NONE);
@@ -2934,6 +2748,11 @@ static void rna_def_space_buttons(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Limited Texture Context",
"Use the limited version of texture user (for 'old shading' mode)");
+ prop = RNA_def_property(srna, "collection_context", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, buttons_collection_context_items);
+ RNA_def_property_ui_text(prop, "Collection Context", "Which collection we want to show");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, NULL);
+
/* pinned data */
prop = RNA_def_property(srna, "pin_id", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "pinid");
@@ -3398,7 +3217,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
PropertyRNA *prop;
/* XXX: action-editor is currently for object-level only actions, so show that using object-icon hint */
- static const EnumPropertyItem mode_items[] = {
+ static EnumPropertyItem mode_items[] = {
{SACTCONT_DOPESHEET, "DOPESHEET", ICON_OOPS, "Dope Sheet", "Edit all keyframes in scene"},
{SACTCONT_ACTION, "ACTION", ICON_OBJECT_DATA, "Action Editor", "Edit keyframes in active object's Object-level action"},
{SACTCONT_SHAPEKEY, "SHAPEKEY", ICON_SHAPEKEY_DATA, "Shape Key Editor", "Edit keyframes in active object's Shape Keys action"},
@@ -3419,6 +3238,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceDopeSheetEditor_action_set", NULL,
"rna_Action_actedit_assign_poll");
RNA_def_property_ui_text(prop, "Action", "Action displayed and edited in this space");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_SpaceDopeSheetEditor_action_update");
/* mode */
@@ -3426,6 +3246,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, mode_items);
RNA_def_property_ui_text(prop, "Mode", "Editing context being displayed");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, "rna_SpaceDopeSheetEditor_mode_update");
/* display */
@@ -3869,6 +3690,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
"Particles Settings", "Show/hide Particle Settings data-blocks"},
{FILTER_ID_PAL, "PALETTE", ICON_COLOR, "Palettes", "Show/hide Palette data-blocks"},
{FILTER_ID_PC, "PAINT_CURVE", ICON_CURVE_BEZCURVE, "Paint Curves", "Show/hide Paint Curve data-blocks"},
+ {FILTER_ID_LP, "LIGHT_PROBE", ICON_RADIO, "Light Probes", "Show/hide Light Probe data-blocks"},
{FILTER_ID_SCE, "SCENE", ICON_SCENE_DATA, "Scenes", "Show/hide Scene data-blocks"},
{FILTER_ID_SPK, "SPEAKER", ICON_SPEAKER, "Speakers", "Show/hide Speaker data-blocks"},
{FILTER_ID_SO, "SOUND", ICON_SOUND, "Sounds", "Show/hide Sound data-blocks"},
@@ -3876,6 +3698,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
{FILTER_ID_TXT, "TEXT", ICON_TEXT, "Texts", "Show/hide Text data-blocks"},
{FILTER_ID_VF, "FONT", ICON_FONT_DATA, "Fonts", "Show/hide Font data-blocks"},
{FILTER_ID_WO, "WORLD", ICON_WORLD_DATA, "Worlds", "Show/hide World data-blocks"},
+ {FILTER_ID_WS, "WORK_SPACE", ICON_NONE, "Workspaces", "Show/hide workspace data-blocks"},
{0, NULL, 0, NULL, NULL}
};
@@ -3893,7 +3716,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
"Show/hide materials, nodetrees, textures and Freestyle's linestyles"},
{FILTER_ID_IM | FILTER_ID_MC | FILTER_ID_MSK | FILTER_ID_SO,
"IMAGE", ICON_IMAGE_DATA, "Images & Sounds", "Show/hide images, movie clips, sounds and masks"},
- {FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_SPK | FILTER_ID_WO,
+ {FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_SPK | FILTER_ID_WO | FILTER_ID_WS,
"ENVIRONMENT", ICON_WORLD_DATA, "Environment", "Show/hide worlds, lamps, cameras and speakers"},
{FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_CF,
"MISC", ICON_GREASEPENCIL, "Miscellaneous", "Show/hide other data types"},
@@ -4408,14 +4231,10 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Backdrop Zoom", "Backdrop zoom factor");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
- prop = RNA_def_property(srna, "backdrop_x", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "backdrop_offset", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "xof");
- RNA_def_property_ui_text(prop, "Backdrop X", "Backdrop X offset");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
-
- prop = RNA_def_property(srna, "backdrop_y", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "yof");
- RNA_def_property_ui_text(prop, "Backdrop Y", "Backdrop Y offset");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_ui_text(prop, "Backdrop Offset", "Backdrop offset");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
prop = RNA_def_property(srna, "backdrop_channels", PROP_ENUM, PROP_NONE);
@@ -4789,7 +4608,6 @@ void RNA_def_space(BlenderRNA *brna)
rna_def_filemenu_entry(brna);
rna_def_space_filebrowser(brna);
rna_def_space_outliner(brna);
- rna_def_background_image(brna);
rna_def_space_view3d(brna);
rna_def_space_buttons(brna);
rna_def_space_dopesheet(brna);
diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c
index 8f771eda99d..822f5cbb4b6 100644
--- a/source/blender/makesrna/intern/rna_space_api.c
+++ b/source/blender/makesrna/intern/rna_space_api.c
@@ -31,23 +31,28 @@
#ifdef RNA_RUNTIME
+#include "BKE_global.h"
+
+#include "ED_screen.h"
#include "ED_text.h"
-static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d)
+static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d, bContext *C)
{
bScreen *sc = (bScreen *)id;
+ EvaluationContext eval_ctx;
ScrArea *sa;
ARegion *ar;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
area_region_from_regiondata(sc, rv3d, &sa, &ar);
if (sa && ar && sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d;
+ View3D *v3d = sa->spacedata.first;
+ Scene *scene = ED_screen_scene_find(sc, G.main->wm.first);
- v3d = (View3D *)sa->spacedata.first;
-
- ED_view3d_update_viewmat(sc->scene, v3d, ar, NULL, NULL, NULL);
+ ED_view3d_update_viewmat(&eval_ctx, scene, v3d, ar, NULL, NULL, NULL);
}
}
@@ -71,7 +76,7 @@ void RNA_api_region_view3d(StructRNA *srna)
FunctionRNA *func;
func = RNA_def_function(srna, "update", "rna_RegionView3D_update");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func, "Recalculate the view matrices");
}
diff --git a/source/blender/makesrna/intern/rna_speaker.c b/source/blender/makesrna/intern/rna_speaker.c
index f47b54c2d95..f37b75b3db2 100644
--- a/source/blender/makesrna/intern/rna_speaker.c
+++ b/source/blender/makesrna/intern/rna_speaker.c
@@ -41,7 +41,6 @@
#include "MEM_guardedalloc.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "WM_api.h"
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index 39674724889..42e3e2c83fb 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -114,11 +114,12 @@ static const EnumPropertyItem blend_type_items[] = {
#include "BKE_colorband.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BKE_texture.h"
#include "BKE_main.h"
+#include "DEG_depsgraph.h"
+
#include "ED_node.h"
#include "ED_render.h"
@@ -169,7 +170,7 @@ static void rna_Texture_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *pt
if (GS(id->name) == ID_TE) {
Tex *tex = ptr->id.data;
- DAG_id_tag_update(&tex->id, 0);
+ DEG_id_tag_update(&tex->id, 0);
WM_main_add_notifier(NC_TEXTURE, tex);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, NULL);
}
@@ -215,7 +216,7 @@ static void rna_Texture_nodes_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
{
Tex *tex = ptr->id.data;
- DAG_id_tag_update(&tex->id, 0);
+ DEG_id_tag_update(&tex->id, 0);
WM_main_add_notifier(NC_TEXTURE | ND_NODES, tex);
}
@@ -226,11 +227,11 @@ static void rna_Texture_type_set(PointerRNA *ptr, int value)
BKE_texture_type_set(tex, value);
}
-void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+void rna_TextureSlot_update(bContext *C, PointerRNA *ptr)
{
ID *id = ptr->id.data;
- DAG_id_tag_update(id, 0);
+ DEG_id_tag_update(id, 0);
switch (GS(id->name)) {
case ID_MA:
@@ -246,8 +247,10 @@ void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
break;
case ID_BR:
{
+ Scene *scene = CTX_data_scene(C);
MTex *mtex = ptr->data;
- BKE_paint_invalidate_overlay_tex(scene, mtex->tex);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_paint_invalidate_overlay_tex(scene, view_layer, mtex->tex);
WM_main_add_notifier(NC_BRUSH, id);
break;
}
@@ -264,7 +267,7 @@ void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
if (mtex->mapto & PAMAP_CHILD)
recalc |= PSYS_RECALC_CHILD;
- DAG_id_tag_update(id, recalc);
+ DEG_id_tag_update(id, recalc);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
break;
}
@@ -649,7 +652,7 @@ static void rna_def_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tex");
RNA_def_property_struct_type(prop, "Texture");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Texture", "Texture data-block used by this texture slot");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_TextureSlot_update");
@@ -657,6 +660,7 @@ static void rna_def_mtex(BlenderRNA *brna)
RNA_def_property_string_funcs(prop, "rna_TextureSlot_name_get", "rna_TextureSlot_name_length", NULL);
RNA_def_property_ui_text(prop, "Name", "Texture slot name");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_struct_name_property(srna, prop);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
@@ -664,12 +668,13 @@ static void rna_def_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_float_sdna(prop, NULL, "ofs");
RNA_def_property_ui_range(prop, -10, 10, 10, RNA_TRANSLATION_PREC_DEFAULT);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Offset", "Fine tune of the texture mapping X, Y and Z locations");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "size");
- RNA_def_property_flag(prop, PROP_PROPORTIONAL);
+ RNA_def_property_flag(prop, PROP_PROPORTIONAL | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_range(prop, -100, 100, 10, 2);
RNA_def_property_ui_text(prop, "Size", "Set scaling for the texture's X, Y and Z sizes");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
@@ -677,6 +682,7 @@ static void rna_def_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "r");
RNA_def_property_array(prop, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Color",
"Default color for textures that don't return RGB or when RGB to intensity is enabled");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
@@ -684,26 +690,31 @@ static void rna_def_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "blendtype");
RNA_def_property_enum_items(prop, blend_type_items);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Blend Type", "Mode used to apply the texture");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "use_stencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_STENCIL);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Stencil", "Use this texture as a blending value on the next texture");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_NEGATIVE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Negate", "Invert the values of the texture to reverse its effect");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "use_rgb_to_intensity", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_RGBTOINT);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "RGB to Intensity", "Convert texture RGB values to intensity (gray) values");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "def_var");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_range(prop, 0, 1, 10, 3);
RNA_def_property_ui_text(prop, "Default Value",
"Value to use for Ref, Spec, Amb, Emit, Alpha, RayMir, TransLu and Hard");
@@ -712,6 +723,7 @@ static void rna_def_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "output_node", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "which_output");
RNA_def_property_enum_items(prop, output_node_items);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_enum_funcs(prop, "rna_TextureSlot_output_node_get", NULL, "rna_TextureSlot_output_node_itemf");
RNA_def_property_ui_text(prop, "Output Node", "Which output node to use, for node-based textures");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
@@ -738,7 +750,7 @@ static void rna_def_filter_common(StructRNA *srna)
RNA_def_property_ui_text(prop, "Filter", "Texture filter to use for sampling image");
RNA_def_property_update(prop, 0, "rna_Texture_update");
- prop = RNA_def_property(srna, "filter_probes", PROP_INT, PROP_NONE);
+ prop = RNA_def_property(srna, "filter_lightprobes", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "afmax");
RNA_def_property_range(prop, 1, 256);
RNA_def_property_ui_text(prop, "Filter Probes",
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index b0f6879656a..d23017429c1 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -48,9 +48,10 @@
#ifdef RNA_RUNTIME
-#include "BKE_depsgraph.h"
#include "BKE_node.h"
+#include "DEG_depsgraph.h"
+
#include "IMB_imbuf.h"
#include "WM_api.h"
@@ -466,7 +467,7 @@ static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerR
WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
WM_main_add_notifier(NC_SCENE, NULL);
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
}
static void rna_tracking_resetIntrinsics(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -555,7 +556,7 @@ static void rna_trackingObject_flushUpdate(Main *UNUSED(bmain), Scene *UNUSED(sc
MovieClip *clip = (MovieClip *)ptr->id.data;
WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, NULL);
- DAG_id_tag_update(&clip->id, 0);
+ DEG_id_tag_update(&clip->id, 0);
}
static void rna_trackingMarker_frame_set(PointerRNA *ptr, int value)
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 7f7b1d05ffc..0b44809cf48 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -704,7 +704,31 @@ void RNA_api_ui_layout(StructRNA *srna)
"Identifier of property in data giving the type of the ID-blocks to use");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
api_ui_item_common_text(func);
-
+
+ func = RNA_def_function(srna, "template_search", "uiTemplateSearch");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ api_ui_item_rna_common(func);
+ parm = RNA_def_pointer(func, "search_data", "AnyType", "", "Data from which to take collection to search in");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_string(func, "search_property", NULL, 0, "", "Identifier of search collection property");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_string(func, "new", NULL, 0, "", "Operator identifier to create a new item for the collection");
+ RNA_def_string(func, "unlink", NULL, 0, "", "Operator identifier to unlink or delete the active "
+ "item from the collection");
+
+ func = RNA_def_function(srna, "template_search_preview", "uiTemplateSearchPreview");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ api_ui_item_rna_common(func);
+ parm = RNA_def_pointer(func, "search_data", "AnyType", "", "Data from which to take collection to search in");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_string(func, "search_property", NULL, 0, "", "Identifier of search collection property");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_string(func, "new", NULL, 0, "", "Operator identifier to create a new item for the collection");
+ RNA_def_string(func, "unlink", NULL, 0, "", "Operator identifier to unlink or delete the active "
+ "item from the collection");
+ RNA_def_int(func, "rows", 0, 0, INT_MAX, "Number of thumbnail preview rows to display", "", 0, INT_MAX);
+ RNA_def_int(func, "cols", 0, 0, INT_MAX, "Number of thumbnail preview columns to display", "", 0, INT_MAX);
+
func = RNA_def_function(srna, "template_path_builder", "rna_uiTemplatePathBuilder");
parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
@@ -921,6 +945,16 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_pointer(func, "item", "KeyMapItem", "", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ func = RNA_def_function(srna, "template_override_property", "uiTemplateOverrideProperty");
+ parm = RNA_def_pointer(func, "collection_render_overrides", "AnyType", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_pointer(func, "scene_collection_properties", "AnyType", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_string(func, "property", NULL, 0, "", "Identifier of property in collection_properties");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ api_ui_item_common(func);
+ parm = RNA_def_string(func, "custom_template", NULL, 0, "", "Optional template to use for property");
+
func = RNA_def_function(srna, "template_component_menu", "uiTemplateComponentMenu");
RNA_def_function_ui_description(func, "Item. Display expanded property in a popup menu");
parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index f0313601c3a..273f9fcf280 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -66,16 +66,7 @@ static const EnumPropertyItem opensubdiv_compute_type_items[] = {
#endif
static const EnumPropertyItem audio_device_items[] = {
- {0, "NONE", 0, "None", "Null device - there will be no audio output"},
-#ifdef WITH_SDL
- {1, "SDL", 0, "SDL", "SDL device - simple direct media layer, recommended for sequencer usage"},
-#endif
-#ifdef WITH_OPENAL
- {2, "OPENAL", 0, "OpenAL", "OpenAL device - supports 3D audio, recommended for game engine usage"},
-#endif
-#ifdef WITH_JACK
- {3, "JACK", 0, "JACK", "JACK Audio Connection Kit, recommended for pro audio users"},
-#endif
+ {0, "Null", 0, "None", "Null device - there will be no audio output"},
{0, NULL, 0, NULL, NULL}
};
@@ -98,13 +89,14 @@ static const EnumPropertyItem rna_enum_language_default_items[] = {
#include "DNA_screen_types.h"
#include "BKE_blender.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_idprop.h"
#include "BKE_pbvh.h"
#include "BKE_paint.h"
+#include "DEG_depsgraph.h"
+
#include "GPU_draw.h"
#include "GPU_select.h"
@@ -175,10 +167,12 @@ static void rna_userdef_show_manipulator_update(Main *bmain, Scene *scene, Point
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
- if (userdef->tw_flag & V3D_USE_MANIPULATOR)
- v3d->twflag |= V3D_USE_MANIPULATOR;
- else
- v3d->twflag &= ~V3D_USE_MANIPULATOR;
+ if (userdef->manipulator_flag & USER_MANIPULATOR_DRAW) {
+ v3d->twflag |= V3D_MANIPULATOR_DRAW;
+ }
+ else {
+ v3d->twflag &= ~V3D_MANIPULATOR_DRAW;
+ }
}
}
}
@@ -363,7 +357,7 @@ static void rna_UserDef_weight_color_update(Main *bmain, Scene *scene, PointerRN
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->mode & OB_MODE_WEIGHT_PAINT)
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
rna_userdef_update(bmain, scene, ptr);
@@ -502,7 +496,7 @@ static void rna_userdef_opensubdiv_update(Main *bmain, Scene *UNUSED(scene), Poi
if (object->derivedFinal != NULL &&
object->derivedFinal->type == DM_TYPE_CCGDM)
{
- DAG_id_tag_update(&object->id, OB_RECALC_OB);
+ DEG_id_tag_update(&object->id, OB_RECALC_OB);
}
}
}
@@ -516,7 +510,6 @@ static const EnumPropertyItem *rna_userdef_audio_device_itemf(bContext *UNUSED(C
int totitem = 0;
EnumPropertyItem *item = NULL;
-#ifdef WITH_SYSTEM_AUDASPACE
int i;
char **names = BKE_sound_get_device_names();
@@ -525,31 +518,6 @@ static const EnumPropertyItem *rna_userdef_audio_device_itemf(bContext *UNUSED(C
EnumPropertyItem new_item = {i, names[i], 0, names[i], names[i]};
RNA_enum_item_add(&item, &totitem, &new_item);
}
-#else
- /* NONE */
- RNA_enum_item_add(&item, &totitem, &audio_device_items[index++]);
-
-#ifdef WITH_SDL
-# ifdef WITH_SDL_DYNLOAD
- if (sdlewInit() == SDLEW_SUCCESS)
-# endif
- {
- RNA_enum_item_add(&item, &totitem, &audio_device_items[index]);
- }
- index++;
-#endif
-
-#ifdef WITH_OPENAL
- RNA_enum_item_add(&item, &totitem, &audio_device_items[index++]);
-#endif
-
-#ifdef WITH_JACK
- if (BKE_sound_is_jack_supported()) {
- RNA_enum_item_add(&item, &totitem, &audio_device_items[index]);
- }
- index++;
-#endif
-#endif
/* may be unused */
UNUSED_VARS(index, audio_device_items);
@@ -859,6 +827,16 @@ static void rna_def_userdef_theme_ui_wcol_state(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Driven Selected", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop = RNA_def_property(srna, "inner_overridden", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Overridden", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "inner_overridden_sel", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Overridden Selected", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
prop = RNA_def_property(srna, "blend", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_ui_text(prop, "Blend", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
@@ -1070,6 +1048,37 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Z Axis", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ /* Generic manipulator colors. */
+ prop = RNA_def_property(srna, "manipulator_hi", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "manipulator_hi");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Manipulator Highlight", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "manipulator_primary", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "manipulator_primary");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Manipulator Primary", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "manipulator_secondary", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "manipulator_secondary");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Manipulator Secondary", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "manipulator_a", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "manipulator_a");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Manipulator A", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "manipulator_b", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "manipulator_b");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Manipulator B", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_space_common(StructRNA *srna)
@@ -1273,7 +1282,7 @@ static void rna_def_userdef_theme_spaces_vertex(StructRNA *srna)
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "vertex_size", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 1, 10);
+ RNA_def_property_range(prop, 1, 32);
RNA_def_property_ui_text(prop, "Vertex Size", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
@@ -1495,7 +1504,7 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "handle_vertex_size", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 0, 255);
+ RNA_def_property_range(prop, 1, 100);
RNA_def_property_ui_text(prop, "Handle Vertex Size", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
}
@@ -3347,11 +3356,6 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Display Object Info", "Display objects name and frame number in 3D view");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "use_global_scene", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_SCENEGLOBAL);
- RNA_def_property_ui_text(prop, "Global Scene", "Force the current Scene to be displayed in all Screens");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
prop = RNA_def_property(srna, "show_large_cursors", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "curssize", 0);
RNA_def_property_ui_text(prop, "Large Cursors", "Use large mouse cursors when available");
@@ -3517,30 +3521,25 @@ static void rna_def_userdef_view(BlenderRNA *brna)
/* 3D transform widget */
prop = RNA_def_property(srna, "show_manipulator", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "tw_flag", V3D_USE_MANIPULATOR);
+ RNA_def_property_boolean_sdna(prop, NULL, "manipulator_flag", USER_MANIPULATOR_DRAW);
RNA_def_property_ui_text(prop, "Manipulator", "Use 3D transform manipulator");
RNA_def_property_update(prop, 0, "rna_userdef_show_manipulator_update");
+ /* TODO, expose once it's working. */
+#if 0
+ prop = RNA_def_property(srna, "show_manipulator_shaded", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "manipulator_flag", USER_MANIPULATOR_SHADED);
+ RNA_def_property_ui_text(prop, "Manipulator Shaded", "Use 3D transform manipulator");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+#endif
+
prop = RNA_def_property(srna, "manipulator_size", PROP_INT, PROP_PIXEL);
- RNA_def_property_int_sdna(prop, NULL, "tw_size");
+ RNA_def_property_int_sdna(prop, NULL, "manipulator_size");
RNA_def_property_range(prop, 10, 200);
RNA_def_property_int_default(prop, 75);
RNA_def_property_ui_text(prop, "Manipulator Size", "Diameter of the manipulator");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "manipulator_handle_size", PROP_INT, PROP_PERCENTAGE);
- RNA_def_property_int_sdna(prop, NULL, "tw_handlesize");
- RNA_def_property_range(prop, 2, 40);
- RNA_def_property_int_default(prop, 25);
- RNA_def_property_ui_text(prop, "Manipulator Handle Size", "Size of manipulator handles as percentage of the radius");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "manipulator_hotspot", PROP_INT, PROP_PIXEL);
- RNA_def_property_int_sdna(prop, NULL, "tw_hotspot");
- RNA_def_property_range(prop, 4, 40);
- RNA_def_property_int_default(prop, 14);
- RNA_def_property_ui_text(prop, "Manipulator Hotspot", "Distance around the handles to accept mouse clicks");
-
prop = RNA_def_property(srna, "object_origin_size", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "obcenter_dia");
RNA_def_property_range(prop, 4, 10);
@@ -4189,6 +4188,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_enum_items(prop, multi_sample_levels);
RNA_def_property_ui_text(prop, "MultiSample",
"Enable OpenGL multi-sampling, only for systems that support it, requires restart");
+ RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
prop = RNA_def_property(srna, "use_region_overlap", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_REGION_OVERLAP);
diff --git a/source/blender/makesrna/intern/rna_vfont.c b/source/blender/makesrna/intern/rna_vfont.c
index c743751649c..78d46d35246 100644
--- a/source/blender/makesrna/intern/rna_vfont.c
+++ b/source/blender/makesrna/intern/rna_vfont.c
@@ -38,9 +38,10 @@
#ifdef RNA_RUNTIME
#include "BKE_font.h"
-#include "BKE_depsgraph.h"
#include "DNA_object_types.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
/* matching fnction in rna_ID.c */
@@ -60,7 +61,7 @@ static void rna_VectorFont_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scen
/* update */
WM_main_add_notifier(NC_GEOM | ND_DATA, NULL);
- DAG_id_tag_update(&vf->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&vf->id, OB_RECALC_OB | OB_RECALC_DATA);
}
#else
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 23ad51be343..36f07db727b 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -36,6 +36,8 @@
#include "BLT_translation.h"
+#include "BKE_workspace.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -442,6 +444,11 @@ const EnumPropertyItem rna_enum_operator_return_items[] = {
{0, NULL, 0, NULL, NULL}
};
+const EnumPropertyItem rna_enum_operator_property_tags[] = {
+ {OP_PROP_TAG_ADVANCED, "ADVANCED", 0, "Advanced", "The property is advanced so UI is suggested to hide it"},
+ {0, NULL, 0, NULL, NULL}
+};
+
/* flag/enum */
const EnumPropertyItem rna_enum_wm_report_items[] = {
{RPT_DEBUG, "DEBUG", 0, "Debug", ""},
@@ -462,12 +469,23 @@ const EnumPropertyItem rna_enum_wm_report_items[] = {
#include "WM_api.h"
+#include "DNA_object_types.h"
+#include "DNA_workspace_types.h"
+
+#include "ED_screen.h"
+
#include "UI_interface.h"
+#include "BKE_global.h"
#include "BKE_idprop.h"
#include "MEM_guardedalloc.h"
+#ifdef WITH_PYTHON
+# include "BPY_extern.h"
+#endif
+
+
static wmOperator *rna_OperatorProperties_find_operator(PointerRNA *ptr)
{
wmWindowManager *wm = ptr->id.data;
@@ -622,42 +640,166 @@ static PointerRNA rna_PieMenu_layout_get(PointerRNA *ptr)
return rptr;
}
-static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value)
+static void rna_Window_scene_set(PointerRNA *ptr, PointerRNA value)
+{
+ wmWindow *win = ptr->data;
+
+ if (value.data == NULL) {
+ return;
+ }
+
+ win->new_scene = value.data;
+}
+
+static void rna_Window_scene_update(bContext *C, PointerRNA *ptr)
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = ptr->data;
+
+ /* exception: must use context so notifier gets to the right window */
+ if (win->new_scene) {
+#ifdef WITH_PYTHON
+ BPy_BEGIN_ALLOW_THREADS;
+#endif
+
+ WM_window_change_active_scene(bmain, C, win, win->new_scene);
+
+#ifdef WITH_PYTHON
+ BPy_END_ALLOW_THREADS;
+#endif
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SCENEBROWSE, win->new_scene);
+
+ if (G.debug & G_DEBUG)
+ printf("scene set %p\n", win->new_scene);
+
+ win->new_scene = NULL;
+ }
+}
+
+static PointerRNA rna_Window_workspace_get(PointerRNA *ptr)
+{
+ wmWindow *win = ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_WorkSpace, BKE_workspace_active_get(win->workspace_hook));
+}
+
+static void rna_Window_workspace_set(PointerRNA *ptr, PointerRNA value)
{
wmWindow *win = (wmWindow *)ptr->data;
/* disallow ID-browsing away from temp screens */
- if (win->screen->temp) {
+ if (WM_window_is_temp_screen(win)) {
return;
}
+ if (value.data == NULL) {
+ return;
+ }
+
+ /* exception: can't set workspaces inside of area/region handlers */
+ win->workspace_hook->temp_workspace_store = value.data;
+}
+
+static void rna_Window_workspace_update(bContext *C, PointerRNA *ptr)
+{
+ wmWindow *win = ptr->data;
+ WorkSpace *new_workspace = win->workspace_hook->temp_workspace_store;
- if (value.data == NULL)
+ /* exception: can't set screens inside of area/region handlers,
+ * and must use context so notifier gets to the right window */
+ if (new_workspace) {
+ WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, new_workspace);
+ win->workspace_hook->temp_workspace_store = NULL;
+ }
+}
+
+PointerRNA rna_Window_screen_get(PointerRNA *ptr)
+{
+ wmWindow *win = ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_Screen, BKE_workspace_active_screen_get(win->workspace_hook));
+}
+
+static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value)
+{
+ wmWindow *win = ptr->data;
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ WorkSpaceLayout *layout_new;
+ const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
+
+ /* disallow ID-browsing away from temp screens */
+ if (screen->temp) {
return;
+ }
+ if (value.data == NULL) {
+ return;
+ }
/* exception: can't set screens inside of area/region handlers */
- win->newscreen = value.data;
+ layout_new = BKE_workspace_layout_find(workspace, value.data);
+ win->workspace_hook->temp_layout_store = layout_new;
}
static int rna_Window_screen_assign_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
- bScreen *screen = (bScreen *)value.id.data;
-
+ bScreen *screen = value.id.data;
return !screen->temp;
}
-
-static void rna_Window_screen_update(bContext *C, PointerRNA *ptr)
+static void rna_workspace_screen_update(bContext *C, PointerRNA *ptr)
{
- wmWindow *win = (wmWindow *)ptr->data;
+ wmWindow *win = ptr->data;
+ WorkSpaceLayout *layout_new = win->workspace_hook->temp_layout_store;
/* exception: can't set screens inside of area/region handlers,
* and must use context so notifier gets to the right window */
- if (win->newscreen) {
- WM_event_add_notifier(C, NC_SCREEN | ND_SCREENBROWSE, win->newscreen);
- win->newscreen = NULL;
+ if (layout_new) {
+ WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTBROWSE, layout_new);
+ win->workspace_hook->temp_layout_store = NULL;
}
}
+static PointerRNA rna_Window_view_layer_get(PointerRNA *ptr)
+{
+ wmWindow *win = ptr->data;
+ Scene *scene = WM_window_get_active_scene(win);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene);
+ PointerRNA scene_ptr;
+
+ RNA_id_pointer_create(&scene->id, &scene_ptr);
+ return rna_pointer_inherit_refine(&scene_ptr, &RNA_ViewLayer, view_layer);
+}
+
+static void rna_Window_view_layer_set(PointerRNA *ptr, PointerRNA value)
+{
+ wmWindow *win = ptr->data;
+ Scene *scene = WM_window_get_active_scene(win);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+
+ BKE_workspace_view_layer_set(workspace, value.data, scene);
+}
+
+#ifdef USE_WORKSPACE_MODE
+
+static int rna_Window_object_mode_get(PointerRNA *ptr)
+{
+ wmWindow *win = ptr->data;
+ Scene *scene = WM_window_get_active_scene(win);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+
+ return (int)BKE_workspace_object_mode_get(workspace, scene);
+}
+
+static void rna_Window_object_mode_set(PointerRNA *ptr, int value)
+{
+ wmWindow *win = ptr->data;
+ Scene *scene = WM_window_get_active_scene(win);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+
+ BKE_workspace_object_mode_set(workspace, scene, value);
+}
+
+#endif /* USE_WORKSPACE_MODE */
+
static PointerRNA rna_KeyMapItem_properties_get(PointerRNA *ptr)
{
wmKeyMapItem *kmi = ptr->data;
@@ -1193,6 +1335,7 @@ static StructRNA *rna_Operator_register(
/* create a new operator type */
dummyot.ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummyot.idname, &RNA_Operator);
RNA_def_struct_flag(dummyot.ext.srna, STRUCT_NO_IDPROPERTIES); /* operator properties are registered separately */
+ RNA_def_struct_property_tags(dummyot.ext.srna, rna_enum_operator_property_tags);
RNA_def_struct_translation_context(dummyot.ext.srna, dummyot.translation_context);
dummyot.ext.data = data;
dummyot.ext.call = call;
@@ -1547,6 +1690,7 @@ static void rna_def_operator(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Operator Properties", "Input properties of an Operator");
RNA_def_struct_refine_func(srna, "rna_OperatorProperties_refine");
RNA_def_struct_idprops_func(srna, "rna_OperatorProperties_idprops");
+ RNA_def_struct_property_tags(srna, rna_enum_operator_property_tags);
RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES);
}
@@ -1902,14 +2046,42 @@ static void rna_def_window(BlenderRNA *brna)
rna_def_window_stereo3d(brna);
- prop = RNA_def_property(srna, "screen", PROP_POINTER, PROP_NONE);
+ prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL);
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_Window_scene_set", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Scene", "Active scene to be edited in the window");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_Window_scene_update");
+
+ prop = RNA_def_property(srna, "workspace", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "WorkSpace");
+ RNA_def_property_ui_text(prop, "Workspace", "Active workspace showing in the window");
+ RNA_def_property_pointer_funcs(prop, "rna_Window_workspace_get", "rna_Window_workspace_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_Window_workspace_update");
+
+ prop = RNA_def_property(srna, "screen", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Screen");
- RNA_def_property_ui_text(prop, "Screen", "Active screen showing in the window");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_pointer_funcs(prop, NULL, "rna_Window_screen_set", NULL, "rna_Window_screen_assign_poll");
- RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, 0, "rna_Window_screen_update");
+ RNA_def_property_ui_text(prop, "Screen", "Active workspace screen showing in the window");
+ RNA_def_property_pointer_funcs(prop, "rna_Window_screen_get", "rna_Window_screen_set", NULL,
+ "rna_Window_screen_assign_poll");
+ RNA_def_property_flag(prop, PROP_NEVER_NULL | PROP_EDITABLE | PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, 0, "rna_workspace_screen_update");
+
+ prop = RNA_def_property(srna, "view_layer", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ViewLayer");
+ RNA_def_property_pointer_funcs(prop, "rna_Window_view_layer_get", "rna_Window_view_layer_set", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Active View Layer", "The active workspace view layer showing in the window");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL);
+ RNA_def_property_update(prop, NC_SCREEN | ND_LAYER, NULL);
+
+#ifdef USE_WORKSPACE_MODE
+ prop = RNA_def_property(srna, "object_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_object_mode_items);
+ RNA_def_property_enum_funcs(prop, "rna_Window_object_mode_get", "rna_Window_object_mode_set", NULL);
+ RNA_def_property_ui_text(prop, "Mode", "Object interaction mode used in this window");
+#endif
prop = RNA_def_property(srna, "x", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "posx");
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index 089504e342a..188b63d7d24 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -71,6 +71,8 @@ const EnumPropertyItem rna_enum_window_cursor_items[] = {
#include "UI_interface.h"
#include "BKE_context.h"
+#include "WM_types.h"
+
static wmKeyMap *rna_keymap_active(wmKeyMap *km, bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -115,6 +117,37 @@ static void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer)
WM_event_remove_timer(wm, timer->win, timer);
}
+
+static wmManipulatorGroupType *wm_manipulatorgrouptype_find_for_add_remove(ReportList *reports, const char *idname)
+{
+ wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(idname, true);
+ if (wgt == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Manipulator group type '%s' not found!", idname);
+ return NULL;
+ }
+ if (wgt->flag & WM_MANIPULATORGROUPTYPE_PERSISTENT) {
+ BKE_reportf(reports, RPT_ERROR, "Manipulator group '%s' has 'PERSISTENT' option set!", idname);
+ return NULL;
+ }
+ return wgt;
+}
+
+static void rna_manipulator_group_type_add(ReportList *reports, const char *idname)
+{
+ wmManipulatorGroupType *wgt = wm_manipulatorgrouptype_find_for_add_remove(reports, idname);
+ if (wgt != NULL) {
+ WM_manipulator_group_type_add_ptr(wgt);
+ }
+}
+
+static void rna_manipulator_group_type_remove(Main *bmain, ReportList *reports, const char *idname)
+{
+ wmManipulatorGroupType *wgt = wm_manipulatorgrouptype_find_for_add_remove(reports, idname);
+ if (wgt != NULL) {
+ WM_manipulator_group_type_remove_ptr(bmain, wgt);
+ }
+}
+
/* placeholder data for final implementation of a true progressbar */
static struct wmStaticProgress {
float min;
@@ -426,6 +459,18 @@ void RNA_api_wm(StructRNA *srna)
parm = RNA_def_pointer(func, "timer", "Timer", "", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ func = RNA_def_function(srna, "manipulator_group_type_add", "rna_manipulator_group_type_add");
+ RNA_def_function_ui_description(func, "Activate an existing widget group (when the persistent option isn't set)");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_REPORTS);
+ parm = RNA_def_string(func, "identifier", NULL, 0, "", "Manipulator group type name");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "manipulator_group_type_remove", "rna_manipulator_group_type_remove");
+ RNA_def_function_ui_description(func, "De-activate a widget group (when the persistent option isn't set)");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_MAIN | FUNC_USE_REPORTS);
+ parm = RNA_def_string(func, "identifier", NULL, 0, "", "Manipulator group type name");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
/* Progress bar interface */
func = RNA_def_function(srna, "progress_begin", "rna_progress_begin");
RNA_def_function_ui_description(func, "Start progress report");
diff --git a/source/blender/makesrna/intern/rna_wm_manipulator.c b/source/blender/makesrna/intern/rna_wm_manipulator.c
new file mode 100644
index 00000000000..00705456fc7
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_wm_manipulator.c
@@ -0,0 +1,1306 @@
+/*
+ * ***** 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/makesrna/intern/rna_wm_manipulator.c
+ * \ingroup RNA
+ */
+
+#include <stdlib.h>
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_string_utils.h"
+
+#include "BLT_translation.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#include "WM_types.h"
+
+#ifdef RNA_RUNTIME
+/* enum definitions */
+#endif /* RNA_RUNTIME */
+
+#ifdef RNA_RUNTIME
+
+#include <assert.h>
+
+#include "WM_api.h"
+
+#include "DNA_workspace_types.h"
+
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+
+#include "BKE_global.h"
+#include "BKE_idprop.h"
+#include "BKE_workspace.h"
+
+#include "MEM_guardedalloc.h"
+
+#ifdef WITH_PYTHON
+# include "BPY_extern.h"
+#endif
+
+/* -------------------------------------------------------------------- */
+
+/** \name Manipulator API
+ * \{ */
+
+static void rna_manipulator_draw_cb(
+ const struct bContext *C, struct wmManipulator *mpr)
+{
+ extern FunctionRNA rna_Manipulator_draw_func;
+ wmManipulatorGroup *mgroup = mpr->parent_mgroup;
+ PointerRNA mpr_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
+ /* RNA_struct_find_function(&mpr_ptr, "draw"); */
+ func = &rna_Manipulator_draw_func;
+ RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_manipulator_draw_select_cb(
+ const struct bContext *C, struct wmManipulator *mpr, int select_id)
+{
+ extern FunctionRNA rna_Manipulator_draw_select_func;
+ wmManipulatorGroup *mgroup = mpr->parent_mgroup;
+ PointerRNA mpr_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
+ /* RNA_struct_find_function(&mpr_ptr, "draw_select"); */
+ func = &rna_Manipulator_draw_select_func;
+ RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "select_id", &select_id);
+ mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+ RNA_parameter_list_free(&list);
+}
+
+static int rna_manipulator_test_select_cb(
+ struct bContext *C, struct wmManipulator *mpr, const struct wmEvent *event)
+{
+ extern FunctionRNA rna_Manipulator_test_select_func;
+ wmManipulatorGroup *mgroup = mpr->parent_mgroup;
+ PointerRNA mpr_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
+ /* RNA_struct_find_function(&mpr_ptr, "test_select"); */
+ func = &rna_Manipulator_test_select_func;
+ RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "event", &event);
+ mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+
+ void *ret;
+ RNA_parameter_get_lookup(&list, "intersect_id", &ret);
+ int intersect_id = *(int *)ret;
+
+ RNA_parameter_list_free(&list);
+ return intersect_id;
+}
+
+static int rna_manipulator_modal_cb(
+ struct bContext *C, struct wmManipulator *mpr, const struct wmEvent *event,
+ eWM_ManipulatorTweak tweak_flag)
+{
+ extern FunctionRNA rna_Manipulator_modal_func;
+ wmManipulatorGroup *mgroup = mpr->parent_mgroup;
+ PointerRNA mpr_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ const int tweak_flag_int = tweak_flag;
+ RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
+ /* RNA_struct_find_function(&mpr_ptr, "modal"); */
+ func = &rna_Manipulator_modal_func;
+ RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "event", &event);
+ RNA_parameter_set_lookup(&list, "tweak", &tweak_flag_int);
+ mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+
+ void *ret;
+ RNA_parameter_get_lookup(&list, "result", &ret);
+ int ret_enum = *(int *)ret;
+
+ RNA_parameter_list_free(&list);
+ return ret_enum;
+}
+
+static void rna_manipulator_setup_cb(
+ struct wmManipulator *mpr)
+{
+ extern FunctionRNA rna_Manipulator_setup_func;
+ wmManipulatorGroup *mgroup = mpr->parent_mgroup;
+ PointerRNA mpr_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
+ /* RNA_struct_find_function(&mpr_ptr, "setup"); */
+ func = &rna_Manipulator_setup_func;
+ RNA_parameter_list_create(&list, &mpr_ptr, func);
+ mgroup->type->ext.call((bContext *)NULL, &mpr_ptr, func, &list);
+ RNA_parameter_list_free(&list);
+}
+
+
+static int rna_manipulator_invoke_cb(
+ struct bContext *C, struct wmManipulator *mpr, const struct wmEvent *event)
+{
+ extern FunctionRNA rna_Manipulator_invoke_func;
+ wmManipulatorGroup *mgroup = mpr->parent_mgroup;
+ PointerRNA mpr_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
+ /* RNA_struct_find_function(&mpr_ptr, "invoke"); */
+ func = &rna_Manipulator_invoke_func;
+ RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "event", &event);
+ mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+
+ void *ret;
+ RNA_parameter_get_lookup(&list, "result", &ret);
+ int ret_enum = *(int *)ret;
+
+ RNA_parameter_list_free(&list);
+ return ret_enum;
+}
+
+static void rna_manipulator_exit_cb(
+ struct bContext *C, struct wmManipulator *mpr, bool cancel)
+{
+ extern FunctionRNA rna_Manipulator_exit_func;
+ wmManipulatorGroup *mgroup = mpr->parent_mgroup;
+ PointerRNA mpr_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
+ /* RNA_struct_find_function(&mpr_ptr, "exit"); */
+ func = &rna_Manipulator_exit_func;
+ RNA_parameter_list_create(&list, &mpr_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ {
+ int cancel_i = cancel;
+ RNA_parameter_set_lookup(&list, "cancel", &cancel_i);
+ }
+ mgroup->type->ext.call((bContext *)C, &mpr_ptr, func, &list);
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_manipulator_select_refresh_cb(
+ struct wmManipulator *mpr)
+{
+ extern FunctionRNA rna_Manipulator_select_refresh_func;
+ wmManipulatorGroup *mgroup = mpr->parent_mgroup;
+ PointerRNA mpr_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ RNA_pointer_create(NULL, mpr->type->ext.srna, mpr, &mpr_ptr);
+ /* RNA_struct_find_function(&mpr_ptr, "select_refresh"); */
+ func = &rna_Manipulator_select_refresh_func;
+ RNA_parameter_list_create(&list, &mpr_ptr, func);
+ mgroup->type->ext.call((bContext *)NULL, &mpr_ptr, func, &list);
+ RNA_parameter_list_free(&list);
+}
+
+/* just to work around 'const char *' warning and to ensure this is a python op */
+static void rna_Manipulator_bl_idname_set(PointerRNA *ptr, const char *value)
+{
+ wmManipulator *data = ptr->data;
+ char *str = (char *)data->type->idname;
+ if (!str[0]) {
+ BLI_strncpy(str, value, MAX_NAME); /* utf8 already ensured */
+ }
+ else {
+ assert(!"setting the bl_idname on a non-builtin operator");
+ }
+}
+
+static wmManipulator *rna_ManipulatorProperties_find_operator(PointerRNA *ptr)
+{
+#if 0
+ wmWindowManager *wm = ptr->id.data;
+#endif
+
+ /* We could try workaruond this lookup, but not trivial. */
+ for (bScreen *screen = G.main->screen.first; screen; screen = screen->id.next) {
+ IDProperty *properties = ptr->data;
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->manipulator_map) {
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ for (wmManipulatorGroup *mgroup = WM_manipulatormap_group_list(mmap)->first;
+ mgroup;
+ mgroup = mgroup->next)
+ {
+ for (wmManipulator *mpr = mgroup->manipulators.first; mpr; mpr = mpr->next) {
+ if (mpr->properties == properties) {
+ return mpr;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+static StructRNA *rna_ManipulatorProperties_refine(PointerRNA *ptr)
+{
+ wmManipulator *mpr = rna_ManipulatorProperties_find_operator(ptr);
+
+ if (mpr)
+ return mpr->type->srna;
+ else
+ return ptr->type;
+}
+
+static IDProperty *rna_ManipulatorProperties_idprops(PointerRNA *ptr, bool create)
+{
+ if (create && !ptr->data) {
+ IDPropertyTemplate val = {0};
+ ptr->data = IDP_New(IDP_GROUP, &val, "RNA_ManipulatorProperties group");
+ }
+
+ return ptr->data;
+}
+
+static PointerRNA rna_Manipulator_properties_get(PointerRNA *ptr)
+{
+ wmManipulator *mpr = ptr->data;
+ return rna_pointer_inherit_refine(ptr, mpr->type->srna, mpr->properties);
+}
+
+/* wmManipulator.float */
+#define RNA_MANIPULATOR_GENERIC_FLOAT_RW_DEF(func_id, member_id) \
+static float rna_Manipulator_##func_id##_get(PointerRNA *ptr) \
+{ \
+ wmManipulator *mpr = ptr->data; \
+ return mpr->member_id; \
+} \
+static void rna_Manipulator_##func_id##_set(PointerRNA *ptr, float value) \
+{ \
+ wmManipulator *mpr = ptr->data; \
+ mpr->member_id = value; \
+}
+#define RNA_MANIPULATOR_GENERIC_FLOAT_ARRAY_INDEX_RW_DEF(func_id, member_id, index) \
+static float rna_Manipulator_##func_id##_get(PointerRNA *ptr) \
+{ \
+ wmManipulator *mpr = ptr->data; \
+ return mpr->member_id[index]; \
+} \
+static void rna_Manipulator_##func_id##_set(PointerRNA *ptr, float value) \
+{ \
+ wmManipulator *mpr = ptr->data; \
+ mpr->member_id[index] = value; \
+}
+/* wmManipulator.float[len] */
+#define RNA_MANIPULATOR_GENERIC_FLOAT_ARRAY_RW_DEF(func_id, member_id, len) \
+static void rna_Manipulator_##func_id##_get(PointerRNA *ptr, float value[len]) \
+{ \
+ wmManipulator *mpr = ptr->data; \
+ memcpy(value, mpr->member_id, sizeof(float[len])); \
+} \
+static void rna_Manipulator_##func_id##_set(PointerRNA *ptr, const float value[len]) \
+{ \
+ wmManipulator *mpr = ptr->data; \
+ memcpy(mpr->member_id, value, sizeof(float[len])); \
+}
+
+/* wmManipulator.flag */
+#define RNA_MANIPULATOR_GENERIC_FLAG_RW_DEF(func_id, member_id, flag_value) \
+static int rna_Manipulator_##func_id##_get(PointerRNA *ptr) \
+{ \
+ wmManipulator *mpr = ptr->data; \
+ return (mpr->member_id & flag_value) != 0; \
+} \
+static void rna_Manipulator_##func_id##_set(PointerRNA *ptr, int value) \
+{ \
+ wmManipulator *mpr = ptr->data; \
+ SET_FLAG_FROM_TEST(mpr->member_id, value, flag_value); \
+}
+
+/* wmManipulator.flag (negative) */
+#define RNA_MANIPULATOR_GENERIC_FLAG_NEG_RW_DEF(func_id, member_id, flag_value) \
+static int rna_Manipulator_##func_id##_get(PointerRNA *ptr) \
+{ \
+ wmManipulator *mpr = ptr->data; \
+ return (mpr->member_id & flag_value) == 0; \
+} \
+static void rna_Manipulator_##func_id##_set(PointerRNA *ptr, int value) \
+{ \
+ wmManipulator *mpr = ptr->data; \
+ SET_FLAG_FROM_TEST(mpr->member_id, !value, flag_value); \
+}
+
+#define RNA_MANIPULATOR_FLAG_RO_DEF(func_id, member_id, flag_value) \
+static int rna_Manipulator_##func_id##_get(PointerRNA *ptr) \
+{ \
+ wmManipulator *mpr = ptr->data; \
+ return (mpr->member_id & flag_value) != 0; \
+}
+
+RNA_MANIPULATOR_GENERIC_FLOAT_ARRAY_RW_DEF(color, color, 3);
+RNA_MANIPULATOR_GENERIC_FLOAT_ARRAY_RW_DEF(color_hi, color_hi, 3);
+
+RNA_MANIPULATOR_GENERIC_FLOAT_ARRAY_INDEX_RW_DEF(alpha, color, 3);
+RNA_MANIPULATOR_GENERIC_FLOAT_ARRAY_INDEX_RW_DEF(alpha_hi, color_hi, 3);
+
+RNA_MANIPULATOR_GENERIC_FLOAT_ARRAY_RW_DEF(matrix_space, matrix_space, 16);
+RNA_MANIPULATOR_GENERIC_FLOAT_ARRAY_RW_DEF(matrix_basis, matrix_basis, 16);
+RNA_MANIPULATOR_GENERIC_FLOAT_ARRAY_RW_DEF(matrix_offset, matrix_offset, 16);
+
+static void rna_Manipulator_matrix_world_get(PointerRNA *ptr, float value[16])
+{
+ wmManipulator *mpr = ptr->data;
+ WM_manipulator_calc_matrix_final(mpr, (float (*)[4])value);
+}
+
+RNA_MANIPULATOR_GENERIC_FLOAT_RW_DEF(scale_basis, scale_basis);
+RNA_MANIPULATOR_GENERIC_FLOAT_RW_DEF(line_width, line_width);
+
+RNA_MANIPULATOR_GENERIC_FLAG_RW_DEF(flag_use_draw_hover, flag, WM_MANIPULATOR_DRAW_HOVER);
+RNA_MANIPULATOR_GENERIC_FLAG_RW_DEF(flag_use_draw_modal, flag, WM_MANIPULATOR_DRAW_MODAL);
+RNA_MANIPULATOR_GENERIC_FLAG_RW_DEF(flag_use_draw_value, flag, WM_MANIPULATOR_DRAW_VALUE);
+RNA_MANIPULATOR_GENERIC_FLAG_RW_DEF(flag_use_draw_offset_scale, flag, WM_MANIPULATOR_DRAW_OFFSET_SCALE);
+RNA_MANIPULATOR_GENERIC_FLAG_NEG_RW_DEF(flag_use_draw_scale, flag, WM_MANIPULATOR_DRAW_OFFSET_SCALE);
+RNA_MANIPULATOR_GENERIC_FLAG_RW_DEF(flag_hide, flag, WM_MANIPULATOR_HIDDEN);
+
+/* wmManipulator.state */
+RNA_MANIPULATOR_FLAG_RO_DEF(state_is_highlight, state, WM_MANIPULATOR_STATE_HIGHLIGHT);
+RNA_MANIPULATOR_FLAG_RO_DEF(state_is_modal, state, WM_MANIPULATOR_STATE_MODAL);
+RNA_MANIPULATOR_FLAG_RO_DEF(state_select, state, WM_MANIPULATOR_STATE_SELECT);
+
+static void rna_Manipulator_state_select_set(struct PointerRNA *ptr, int value)
+{
+ wmManipulator *mpr = ptr->data;
+ wmManipulatorGroup *mgroup = mpr->parent_mgroup;
+ WM_manipulator_select_set(mgroup->parent_mmap, mpr, value);
+}
+
+static PointerRNA rna_Manipulator_group_get(PointerRNA *ptr)
+{
+ wmManipulator *mpr = ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_ManipulatorGroup, mpr->parent_mgroup);
+}
+
+#ifdef WITH_PYTHON
+
+static void rna_Manipulator_unregister(struct Main *bmain, StructRNA *type);
+void BPY_RNA_manipulator_wrapper(wmManipulatorType *wgt, void *userdata);
+
+static StructRNA *rna_Manipulator_register(
+ Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ struct {
+ char idname[MAX_NAME];
+ } temp_buffers;
+
+ wmManipulatorType dummywt = {NULL};
+ wmManipulator dummymnp = {NULL};
+ PointerRNA mnp_ptr;
+
+ /* Two sets of functions. */
+ int have_function[8];
+
+ /* setup dummy manipulator & manipulator type to store static properties in */
+ dummymnp.type = &dummywt;
+ dummywt.idname = temp_buffers.idname;
+ RNA_pointer_create(NULL, &RNA_Manipulator, &dummymnp, &mnp_ptr);
+
+ /* Clear so we can detect if it's left unset. */
+ temp_buffers.idname[0] = '\0';
+
+ /* validate the python class */
+ if (validate(&mnp_ptr, data, have_function) != 0)
+ return NULL;
+
+ if (strlen(identifier) >= sizeof(temp_buffers.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "Registering manipulator class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(temp_buffers.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this manipulator type before, and remove it */
+ {
+ const wmManipulatorType *wt = WM_manipulatortype_find(dummywt.idname, true);
+ if (wt && wt->ext.srna) {
+ rna_Manipulator_unregister(bmain, wt->ext.srna);
+ }
+ }
+ if (!RNA_struct_available_or_report(reports, dummywt.idname)) {
+ return NULL;
+ }
+
+ { /* allocate the idname */
+ /* For multiple strings see ManipulatorGroup. */
+ dummywt.idname = BLI_strdup(temp_buffers.idname);
+ }
+
+ /* create a new manipulator type */
+ dummywt.ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummywt.idname, &RNA_Manipulator);
+ /* manipulator properties are registered separately */
+ RNA_def_struct_flag(dummywt.ext.srna, STRUCT_NO_IDPROPERTIES);
+ dummywt.ext.data = data;
+ dummywt.ext.call = call;
+ dummywt.ext.free = free;
+
+ {
+ int i = 0;
+ dummywt.draw = (have_function[i++]) ? rna_manipulator_draw_cb : NULL;
+ dummywt.draw_select = (have_function[i++]) ? rna_manipulator_draw_select_cb : NULL;
+ dummywt.test_select = (have_function[i++]) ? rna_manipulator_test_select_cb : NULL;
+ dummywt.modal = (have_function[i++]) ? rna_manipulator_modal_cb : NULL;
+// dummywt.property_update = (have_function[i++]) ? rna_manipulator_property_update : NULL;
+// dummywt.position_get = (have_function[i++]) ? rna_manipulator_position_get : NULL;
+ dummywt.setup = (have_function[i++]) ? rna_manipulator_setup_cb : NULL;
+ dummywt.invoke = (have_function[i++]) ? rna_manipulator_invoke_cb : NULL;
+ dummywt.exit = (have_function[i++]) ? rna_manipulator_exit_cb : NULL;
+ dummywt.select_refresh = (have_function[i++]) ? rna_manipulator_select_refresh_cb : NULL;
+
+ BLI_assert(i == ARRAY_SIZE(have_function));
+ }
+
+ WM_manipulatortype_append_ptr(BPY_RNA_manipulator_wrapper, (void *)&dummywt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+
+ return dummywt.ext.srna;
+}
+
+static void rna_Manipulator_unregister(struct Main *bmain, StructRNA *type)
+{
+ wmManipulatorType *wt = RNA_struct_blender_type_get(type);
+
+ if (!wt)
+ return;
+
+ RNA_struct_free_extension(type, &wt->ext);
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+
+ WM_manipulatortype_remove_ptr(NULL, bmain, wt);
+}
+
+static void **rna_Manipulator_instance(PointerRNA *ptr)
+{
+ wmManipulator *mpr = ptr->data;
+ return &mpr->py_instance;
+}
+
+#endif /* WITH_PYTHON */
+
+
+static StructRNA *rna_Manipulator_refine(PointerRNA *mnp_ptr)
+{
+ wmManipulator *mpr = mnp_ptr->data;
+ return (mpr->type && mpr->type->ext.srna) ? mpr->type->ext.srna : &RNA_Manipulator;
+}
+
+/** \} */
+
+/** \name Manipulator Group API
+ * \{ */
+
+static wmManipulator *rna_ManipulatorGroup_manipulator_new(
+ wmManipulatorGroup *mgroup, ReportList *reports, const char *idname)
+{
+ const wmManipulatorType *wt = WM_manipulatortype_find(idname, true);
+ if (wt == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "ManipulatorType '%s' not known", idname);
+ return NULL;
+ }
+ wmManipulator *mpr = WM_manipulator_new_ptr(wt, mgroup, NULL);
+ return mpr;
+}
+
+static void rna_ManipulatorGroup_manipulator_remove(
+ wmManipulatorGroup *mgroup, bContext *C, wmManipulator *mpr)
+{
+ WM_manipulator_unlink(&mgroup->manipulators, mgroup->parent_mmap, mpr, C);
+}
+
+static void rna_ManipulatorGroup_manipulator_clear(
+ wmManipulatorGroup *mgroup, bContext *C)
+{
+ while (mgroup->manipulators.first) {
+ WM_manipulator_unlink(&mgroup->manipulators, mgroup->parent_mmap, mgroup->manipulators.first, C);
+ }
+}
+
+static void rna_ManipulatorGroup_name_get(PointerRNA *ptr, char *value)
+{
+ wmManipulatorGroup *mgroup = ptr->data;
+ strcpy(value, mgroup->type->name);
+}
+
+static int rna_ManipulatorGroup_name_length(PointerRNA *ptr)
+{
+ wmManipulatorGroup *mgroup = ptr->data;
+ return strlen(mgroup->type->name);
+}
+
+/* just to work around 'const char *' warning and to ensure this is a python op */
+static void rna_ManipulatorGroup_bl_idname_set(PointerRNA *ptr, const char *value)
+{
+ wmManipulatorGroup *data = ptr->data;
+ char *str = (char *)data->type->idname;
+ if (!str[0])
+ BLI_strncpy(str, value, MAX_NAME); /* utf8 already ensured */
+ else
+ assert(!"setting the bl_idname on a non-builtin operator");
+}
+
+static void rna_ManipulatorGroup_bl_label_set(PointerRNA *ptr, const char *value)
+{
+ wmManipulatorGroup *data = ptr->data;
+ char *str = (char *)data->type->name;
+ if (!str[0])
+ BLI_strncpy(str, value, MAX_NAME); /* utf8 already ensured */
+ else
+ assert(!"setting the bl_label on a non-builtin operator");
+}
+
+static int rna_ManipulatorGroup_has_reports_get(PointerRNA *ptr)
+{
+ wmManipulatorGroup *mgroup = ptr->data;
+ return (mgroup->reports && mgroup->reports->list.first);
+}
+
+#ifdef WITH_PYTHON
+
+static bool rna_manipulatorgroup_poll_cb(const bContext *C, wmManipulatorGroupType *wgt)
+{
+
+ extern FunctionRNA rna_ManipulatorGroup_poll_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+ int visible;
+
+ RNA_pointer_create(NULL, wgt->ext.srna, NULL, &ptr); /* dummy */
+ func = &rna_ManipulatorGroup_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ wgt->ext.call((bContext *)C, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "visible", &ret);
+ visible = *(int *)ret;
+
+ RNA_parameter_list_free(&list);
+
+ return visible;
+}
+
+static void rna_manipulatorgroup_setup_cb(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ extern FunctionRNA rna_ManipulatorGroup_setup_func;
+
+ PointerRNA mgroup_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(NULL, mgroup->type->ext.srna, mgroup, &mgroup_ptr);
+ func = &rna_ManipulatorGroup_setup_func; /* RNA_struct_find_function(&wgroupr, "setup"); */
+
+ RNA_parameter_list_create(&list, &mgroup_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ mgroup->type->ext.call((bContext *)C, &mgroup_ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static wmKeyMap *rna_manipulatorgroup_setup_keymap_cb(const wmManipulatorGroupType *wgt, wmKeyConfig *config)
+{
+ extern FunctionRNA rna_ManipulatorGroup_setup_keymap_func;
+ void *ret;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(NULL, wgt->ext.srna, NULL, &ptr); /* dummy */
+ func = &rna_ManipulatorGroup_setup_keymap_func; /* RNA_struct_find_function(&wgroupr, "setup_keymap"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "keyconfig", &config);
+ wgt->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "keymap", &ret);
+ wmKeyMap *keymap = *(wmKeyMap **)ret;
+
+ RNA_parameter_list_free(&list);
+
+ return keymap;
+}
+
+static void rna_manipulatorgroup_refresh_cb(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ extern FunctionRNA rna_ManipulatorGroup_refresh_func;
+
+ PointerRNA mgroup_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(NULL, mgroup->type->ext.srna, mgroup, &mgroup_ptr);
+ func = &rna_ManipulatorGroup_refresh_func; /* RNA_struct_find_function(&wgroupr, "refresh"); */
+
+ RNA_parameter_list_create(&list, &mgroup_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ mgroup->type->ext.call((bContext *)C, &mgroup_ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_manipulatorgroup_draw_prepare_cb(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ extern FunctionRNA rna_ManipulatorGroup_draw_prepare_func;
+
+ PointerRNA mgroup_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(NULL, mgroup->type->ext.srna, mgroup, &mgroup_ptr);
+ func = &rna_ManipulatorGroup_draw_prepare_func; /* RNA_struct_find_function(&wgroupr, "draw_prepare"); */
+
+ RNA_parameter_list_create(&list, &mgroup_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ mgroup->type->ext.call((bContext *)C, &mgroup_ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+void BPY_RNA_manipulatorgroup_wrapper(wmManipulatorGroupType *wgt, void *userdata);
+static void rna_ManipulatorGroup_unregister(struct Main *bmain, StructRNA *type);
+
+static StructRNA *rna_ManipulatorGroup_register(
+ Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ struct {
+ char name[MAX_NAME];
+ char idname[MAX_NAME];
+ } temp_buffers;
+
+ wmManipulatorGroupType dummywgt = {NULL};
+ wmManipulatorGroup dummywg = {NULL};
+ PointerRNA wgptr;
+
+ /* Two sets of functions. */
+ int have_function[5];
+
+ /* setup dummy manipulatorgroup & manipulatorgroup type to store static properties in */
+ dummywg.type = &dummywgt;
+ dummywgt.name = temp_buffers.name;
+ dummywgt.idname = temp_buffers.idname;
+
+ RNA_pointer_create(NULL, &RNA_ManipulatorGroup, &dummywg, &wgptr);
+
+ /* Clear so we can detect if it's left unset. */
+ temp_buffers.idname[0] = temp_buffers.name[0] = '\0';
+
+ /* validate the python class */
+ if (validate(&wgptr, data, have_function) != 0)
+ return NULL;
+
+ if (strlen(identifier) >= sizeof(temp_buffers.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "Registering manipulatorgroup class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(temp_buffers.idname));
+ return NULL;
+ }
+
+ /* check if the area supports widgets */
+ const struct wmManipulatorMapType_Params wmap_params = {
+ .spaceid = dummywgt.mmap_params.spaceid,
+ .regionid = dummywgt.mmap_params.regionid,
+ };
+
+ wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(&wmap_params);
+ if (mmap_type == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Area type does not support manipulators");
+ return NULL;
+ }
+
+ /* check if we have registered this manipulatorgroup type before, and remove it */
+ {
+ wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(dummywgt.idname, true);
+ if (wgt && wgt->ext.srna) {
+ rna_ManipulatorGroup_unregister(bmain, wgt->ext.srna);
+ }
+ }
+ if (!RNA_struct_available_or_report(reports, dummywgt.idname)) {
+ return NULL;
+ }
+
+ { /* allocate the idname */
+ const char *strings[] = {
+ temp_buffers.idname,
+ temp_buffers.name,
+ };
+ char *strings_table[ARRAY_SIZE(strings)];
+ BLI_string_join_array_by_sep_char_with_tableN('\0', strings_table, strings, ARRAY_SIZE(strings));
+
+ dummywgt.idname = strings_table[0]; /* allocated string stored here */
+ dummywgt.name = strings_table[1];
+ BLI_assert(ARRAY_SIZE(strings) == 2);
+ }
+
+ /* create a new manipulatorgroup type */
+ dummywgt.ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummywgt.idname, &RNA_ManipulatorGroup);
+ RNA_def_struct_flag(dummywgt.ext.srna, STRUCT_NO_IDPROPERTIES); /* manipulatorgroup properties are registered separately */
+ dummywgt.ext.data = data;
+ dummywgt.ext.call = call;
+ dummywgt.ext.free = free;
+
+ /* We used to register widget group types like this, now we do it similar to
+ * operator types. Thus we should be able to do the same as operator types now. */
+ dummywgt.poll = (have_function[0]) ? rna_manipulatorgroup_poll_cb : NULL;
+ dummywgt.setup_keymap = (have_function[1]) ? rna_manipulatorgroup_setup_keymap_cb : NULL;
+ dummywgt.setup = (have_function[2]) ? rna_manipulatorgroup_setup_cb : NULL;
+ dummywgt.refresh = (have_function[3]) ? rna_manipulatorgroup_refresh_cb : NULL;
+ dummywgt.draw_prepare = (have_function[4]) ? rna_manipulatorgroup_draw_prepare_cb : NULL;
+
+ wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_append_ptr(
+ BPY_RNA_manipulatorgroup_wrapper, (void *)&dummywgt);
+
+ if (wgt->flag & WM_MANIPULATORGROUPTYPE_PERSISTENT) {
+ WM_manipulator_group_type_add_ptr_ex(wgt, mmap_type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+ }
+
+ return dummywgt.ext.srna;
+}
+
+static void rna_ManipulatorGroup_unregister(struct Main *bmain, StructRNA *type)
+{
+ wmManipulatorGroupType *wgt = RNA_struct_blender_type_get(type);
+
+ if (!wgt)
+ return;
+
+ RNA_struct_free_extension(type, &wgt->ext);
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+
+ WM_manipulator_group_type_remove_ptr(bmain, wgt);
+}
+
+static void **rna_ManipulatorGroup_instance(PointerRNA *ptr)
+{
+ wmManipulatorGroup *mgroup = ptr->data;
+ return &mgroup->py_instance;
+}
+
+#endif /* WITH_PYTHON */
+
+static StructRNA *rna_ManipulatorGroup_refine(PointerRNA *mgroup_ptr)
+{
+ wmManipulatorGroup *mgroup = mgroup_ptr->data;
+ return (mgroup->type && mgroup->type->ext.srna) ? mgroup->type->ext.srna : &RNA_ManipulatorGroup;
+}
+
+static void rna_ManipulatorGroup_manipulators_begin(CollectionPropertyIterator *iter, PointerRNA *mgroup_ptr)
+{
+ wmManipulatorGroup *mgroup = mgroup_ptr->data;
+ rna_iterator_listbase_begin(iter, &mgroup->manipulators, NULL);
+}
+
+/** \} */
+
+
+#else /* RNA_RUNTIME */
+
+
+/* ManipulatorGroup.manipulators */
+static void rna_def_manipulators(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "Manipulators");
+ srna = RNA_def_struct(brna, "Manipulators", NULL);
+ RNA_def_struct_sdna(srna, "wmManipulatorGroup");
+ RNA_def_struct_ui_text(srna, "Manipulators", "Collection of manipulators");
+
+ func = RNA_def_function(srna, "new", "rna_ManipulatorGroup_manipulator_new");
+ RNA_def_function_ui_description(func, "Add manipulator");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_string(func, "type", "Type", 0, "", "Manipulator identifier"); /* optional */
+ parm = RNA_def_pointer(func, "manipulator", "Manipulator", "", "New manipulator");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_ManipulatorGroup_manipulator_remove");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(func, "Delete manipulator");
+ parm = RNA_def_pointer(func, "manipulator", "Manipulator", "", "New manipulator");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+
+ func = RNA_def_function(srna, "clear", "rna_ManipulatorGroup_manipulator_clear");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(func, "Delete all manipulators");
+}
+
+
+static void rna_def_manipulator(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "Manipulator");
+ srna = RNA_def_struct(brna, "Manipulator", NULL);
+ RNA_def_struct_sdna(srna, "wmManipulator");
+ RNA_def_struct_ui_text(srna, "Manipulator", "Collection of manipulators");
+ RNA_def_struct_refine_func(srna, "rna_Manipulator_refine");
+
+#ifdef WITH_PYTHON
+ RNA_def_struct_register_funcs(
+ srna,
+ "rna_Manipulator_register",
+ "rna_Manipulator_unregister",
+ "rna_Manipulator_instance");
+#endif
+ RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+
+ prop = RNA_def_property(srna, "properties", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "ManipulatorProperties");
+ RNA_def_property_ui_text(prop, "Properties", "");
+ RNA_def_property_pointer_funcs(prop, "rna_Manipulator_properties_get", NULL, NULL, NULL);
+
+ /* -------------------------------------------------------------------- */
+ /* Registerable Variables */
+
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "type->idname");
+ RNA_def_property_string_maxlength(prop, MAX_NAME);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Manipulator_bl_idname_set");
+ /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ RNA_def_property_flag(prop, PROP_REGISTER);
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+
+ /* wmManipulator.draw */
+ func = RNA_def_function(srna, "draw", NULL);
+ RNA_def_function_ui_description(func, "");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+
+ /* wmManipulator.draw_select */
+ func = RNA_def_function(srna, "draw_select", NULL);
+ RNA_def_function_ui_description(func, "");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_int(func, "select_id", 0, 0, INT_MAX, "", "", 0, INT_MAX);
+
+ /* wmManipulator.test_select */
+ func = RNA_def_function(srna, "test_select", NULL);
+ RNA_def_function_ui_description(func, "");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "event", "Event", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_int(func, "intersect_id", 0, 0, INT_MAX, "", "", 0, INT_MAX);
+ RNA_def_function_return(func, parm);
+
+ /* wmManipulator.handler */
+ static EnumPropertyItem tweak_actions[] = {
+ {WM_MANIPULATOR_TWEAK_PRECISE, "PRECISE", 0, "Precise", ""},
+ {WM_MANIPULATOR_TWEAK_SNAP, "SNAP", 0, "Snap", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ func = RNA_def_function(srna, "modal", NULL);
+ RNA_def_function_ui_description(func, "");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "event", "Event", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ /* TODO, shuold be a enum-flag */
+ parm = RNA_def_enum_flag(func, "tweak", tweak_actions, 0, "Tweak", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_enum_flag(func, "result", rna_enum_operator_return_items, OPERATOR_CANCELLED, "result", "");
+ RNA_def_function_return(func, parm);
+ /* wmManipulator.property_update */
+ /* TODO */
+
+ /* wmManipulator.setup */
+ func = RNA_def_function(srna, "setup", NULL);
+ RNA_def_function_ui_description(func, "");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+
+ /* wmManipulator.invoke */
+ func = RNA_def_function(srna, "invoke", NULL);
+ RNA_def_function_ui_description(func, "");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "event", "Event", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_enum_flag(func, "result", rna_enum_operator_return_items, OPERATOR_CANCELLED, "result", "");
+ RNA_def_function_return(func, parm);
+
+ /* wmManipulator.exit */
+ func = RNA_def_function(srna, "exit", NULL);
+ RNA_def_function_ui_description(func, "");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_boolean(func, "cancel", 0, "Cancel, otherwise confirm", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ /* wmManipulator.cursor_get */
+ /* TODO */
+
+ /* wmManipulator.select_refresh */
+ func = RNA_def_function(srna, "select_refresh", NULL);
+ RNA_def_function_ui_description(func, "");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+
+
+ /* -------------------------------------------------------------------- */
+ /* Instance Variables */
+
+ prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "ManipulatorGroup");
+ RNA_def_property_pointer_funcs(prop, "rna_Manipulator_group_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "", "Manipulator group this manipulator is a member of");
+
+ /* Color & Alpha */
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_float_funcs(prop, "rna_Manipulator_color_get", "rna_Manipulator_color_set", NULL);
+
+ prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Alpha", "");
+ RNA_def_property_float_funcs(prop, "rna_Manipulator_alpha_get", "rna_Manipulator_alpha_set", NULL);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+
+ /* Color & Alpha (highlight) */
+ prop = RNA_def_property(srna, "color_highlight", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_float_funcs(prop, "rna_Manipulator_color_hi_get", "rna_Manipulator_color_hi_set", NULL);
+
+ prop = RNA_def_property(srna, "alpha_highlight", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Alpha", "");
+ RNA_def_property_float_funcs(prop, "rna_Manipulator_alpha_hi_get", "rna_Manipulator_alpha_hi_set", NULL);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+
+ prop = RNA_def_property(srna, "matrix_space", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(prop, "Space Matrix", "");
+ RNA_def_property_float_funcs(prop, "rna_Manipulator_matrix_space_get", "rna_Manipulator_matrix_space_set", NULL);
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+
+ prop = RNA_def_property(srna, "matrix_basis", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(prop, "Basis Matrix", "");
+ RNA_def_property_float_funcs(prop, "rna_Manipulator_matrix_basis_get", "rna_Manipulator_matrix_basis_set", NULL);
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+
+ prop = RNA_def_property(srna, "matrix_offset", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(prop, "Offset Matrix", "");
+ RNA_def_property_float_funcs(prop, "rna_Manipulator_matrix_offset_get", "rna_Manipulator_matrix_offset_set", NULL);
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+
+ prop = RNA_def_property(srna, "matrix_world", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(prop, "Final World Matrix", "");
+ RNA_def_property_float_funcs(prop, "rna_Manipulator_matrix_world_get", NULL, NULL);
+
+ prop = RNA_def_property(srna, "scale_basis", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Scale Basis", "");
+ RNA_def_property_float_funcs(prop, "rna_Manipulator_scale_basis_get", "rna_Manipulator_scale_basis_set", NULL);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+
+ prop = RNA_def_property(srna, "line_width", PROP_FLOAT, PROP_PIXEL);
+ RNA_def_property_ui_text(prop, "Line Width", "");
+ RNA_def_property_float_funcs(prop, "rna_Manipulator_line_width_get", "rna_Manipulator_line_width_set", NULL);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+
+ /* wmManipulator.flag */
+ /* WM_MANIPULATOR_HIDDEN */
+ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(
+ prop, "rna_Manipulator_flag_hide_get", "rna_Manipulator_flag_hide_set");
+ RNA_def_property_ui_text(prop, "Hide", "");
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ /* WM_MANIPULATOR_DRAW_HOVER */
+ prop = RNA_def_property(srna, "use_draw_hover", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(
+ prop, "rna_Manipulator_flag_use_draw_hover_get", "rna_Manipulator_flag_use_draw_hover_set");
+ RNA_def_property_ui_text(prop, "Draw Hover", "");
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ /* WM_MANIPULATOR_DRAW_MODAL */
+ prop = RNA_def_property(srna, "use_draw_modal", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(
+ prop, "rna_Manipulator_flag_use_draw_modal_get", "rna_Manipulator_flag_use_draw_modal_set");
+ RNA_def_property_ui_text(prop, "Draw Active", "Draw while dragging");
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ /* WM_MANIPULATOR_DRAW_VALUE */
+ prop = RNA_def_property(srna, "use_draw_value", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(
+ prop, "rna_Manipulator_flag_use_draw_value_get", "rna_Manipulator_flag_use_draw_value_set");
+ RNA_def_property_ui_text(prop, "Draw Value", "Show an indicator for the current value while dragging");
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ /* WM_MANIPULATOR_DRAW_OFFSET_SCALE */
+ prop = RNA_def_property(srna, "use_draw_offset_scale", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(
+ prop, "rna_Manipulator_flag_use_draw_offset_scale_get", "rna_Manipulator_flag_use_draw_offset_scale_set");
+ RNA_def_property_ui_text(prop, "Scale Offset", "Scale the offset matrix (use to apply screen-space offset)");
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ /* WM_MANIPULATOR_DRAW_NO_SCALE (negated) */
+ prop = RNA_def_property(srna, "use_draw_scale", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(
+ prop, "rna_Manipulator_flag_use_draw_scale_get", "rna_Manipulator_flag_use_draw_scale_set");
+ RNA_def_property_ui_text(prop, "Scale", "Use scale when calculating the matrix");
+ RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+
+ /* wmManipulator.state (readonly) */
+ /* WM_MANIPULATOR_STATE_HIGHLIGHT */
+ prop = RNA_def_property(srna, "is_highlight", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_Manipulator_state_is_highlight_get", NULL);
+ RNA_def_property_ui_text(prop, "Highlight", "");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ /* WM_MANIPULATOR_STATE_MODAL */
+ prop = RNA_def_property(srna, "is_modal", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_Manipulator_state_is_modal_get", NULL);
+ RNA_def_property_ui_text(prop, "Highlight", "");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ /* WM_MANIPULATOR_STATE_SELECT */
+ /* (note that setting is involved, needs to handle array) */
+ prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_Manipulator_state_select_get", "rna_Manipulator_state_select_set");
+ RNA_def_property_ui_text(prop, "Select", "");
+
+ RNA_api_manipulator(srna);
+
+ srna = RNA_def_struct(brna, "ManipulatorProperties", NULL);
+ RNA_def_struct_ui_text(srna, "Manipulator Properties", "Input properties of an Manipulator");
+ RNA_def_struct_refine_func(srna, "rna_ManipulatorProperties_refine");
+ RNA_def_struct_idprops_func(srna, "rna_ManipulatorProperties_idprops");
+ RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES);
+}
+
+static void rna_def_manipulatorgroup(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ srna = RNA_def_struct(brna, "ManipulatorGroup", NULL);
+ RNA_def_struct_ui_text(srna, "ManipulatorGroup", "Storage of an operator being executed, or registered after execution");
+ RNA_def_struct_sdna(srna, "wmManipulatorGroup");
+ RNA_def_struct_refine_func(srna, "rna_ManipulatorGroup_refine");
+#ifdef WITH_PYTHON
+ RNA_def_struct_register_funcs(
+ srna,
+ "rna_ManipulatorGroup_register",
+ "rna_ManipulatorGroup_unregister",
+ "rna_ManipulatorGroup_instance");
+#endif
+ RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+
+ /* -------------------------------------------------------------------- */
+ /* Registration */
+
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "type->idname");
+ RNA_def_property_string_maxlength(prop, MAX_NAME);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_ManipulatorGroup_bl_idname_set");
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_struct_name_property(srna, prop);
+
+ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "type->name");
+ RNA_def_property_string_maxlength(prop, MAX_NAME); /* else it uses the pointer size! */
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_ManipulatorGroup_bl_label_set");
+ /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ RNA_def_property_flag(prop, PROP_REGISTER);
+
+ prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type->mmap_params.spaceid");
+ RNA_def_property_enum_items(prop, rna_enum_space_type_items);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_property_ui_text(prop, "Space type", "The space where the panel is going to be used in");
+
+ prop = RNA_def_property(srna, "bl_region_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type->mmap_params.regionid");
+ RNA_def_property_enum_items(prop, rna_enum_region_type_items);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_property_ui_text(prop, "Region Type", "The region where the panel is going to be used in");
+
+ /* bl_options */
+ static EnumPropertyItem manipulatorgroup_flag_items[] = {
+ {WM_MANIPULATORGROUPTYPE_3D, "3D", 0, "3D",
+ "Use in 3D viewport"},
+ {WM_MANIPULATORGROUPTYPE_SCALE, "SCALE", 0, "Scale",
+ "Scale to respect zoom (otherwise zoom independent draw size)"},
+ {WM_MANIPULATORGROUPTYPE_DEPTH_3D, "DEPTH_3D", 0, "Depth 3D",
+ "Supports culled depth by other objects in the view"},
+ {WM_MANIPULATORGROUPTYPE_SELECT, "SELECT", 0, "Select",
+ "Supports selection"},
+ {WM_MANIPULATORGROUPTYPE_PERSISTENT, "PERSISTENT", 0, "Persistent",
+ ""},
+ {WM_MANIPULATORGROUPTYPE_DRAW_MODAL_ALL, "SHOW_MODAL_ALL", 0, "Show Modal All",
+ "Show all while interacting"},
+ {0, NULL, 0, NULL, NULL}
+ };
+ prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type->flag");
+ RNA_def_property_enum_items(prop, manipulatorgroup_flag_items);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
+ RNA_def_property_ui_text(prop, "Options", "Options for this operator type");
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+
+
+ /* Functions */
+
+ /* poll */
+ func = RNA_def_function(srna, "poll", NULL);
+ RNA_def_function_ui_description(func, "Test if the manipulator group can be called or not");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
+ RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", ""));
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+
+ /* setup_keymap */
+ func = RNA_def_function(srna, "setup_keymap", NULL);
+ RNA_def_function_ui_description(
+ func,
+ "Initialize keymaps for this manipulator group, use fallback keymap when not present");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "keyconfig", "KeyConfig", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ /* return */
+ parm = RNA_def_pointer(func, "keymap", "KeyMap", "", "");
+ RNA_def_property_flag(parm, PROP_NEVER_NULL);
+ RNA_def_function_return(func, parm);
+
+ /* setup */
+ func = RNA_def_function(srna, "setup", NULL);
+ RNA_def_function_ui_description(func, "Create manipulators function for the manipulator group");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+
+ /* refresh */
+ func = RNA_def_function(srna, "refresh", NULL);
+ RNA_def_function_ui_description(func, "Refresh data (called on common state changes such as selection)");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "draw_prepare", NULL);
+ RNA_def_function_ui_description(func, "Run before each redraw");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+
+ /* -------------------------------------------------------------------- */
+ /* Instance Variables */
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_string_funcs(prop, "rna_ManipulatorGroup_name_get", "rna_ManipulatorGroup_name_length", NULL);
+ RNA_def_property_ui_text(prop, "Name", "");
+
+ prop = RNA_def_property(srna, "has_reports", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* this is 'virtual' property */
+ RNA_def_property_boolean_funcs(prop, "rna_ManipulatorGroup_has_reports_get", NULL);
+ RNA_def_property_ui_text(prop, "Has Reports",
+ "ManipulatorGroup has a set of reports (warnings and errors) from last execution");
+
+
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ prop = RNA_def_property(srna, "manipulators", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "manipulators", NULL);
+ RNA_def_property_struct_type(prop, "Manipulator");
+ RNA_def_property_collection_funcs(
+ prop, "rna_ManipulatorGroup_manipulators_begin", "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end", "rna_iterator_listbase_get",
+ NULL, NULL, NULL, NULL);
+
+ RNA_def_property_ui_text(prop, "Manipulators", "List of manipulators in the Manipulator Map");
+ rna_def_manipulator(brna, prop);
+ rna_def_manipulators(brna, prop);
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+
+ RNA_api_manipulatorgroup(srna);
+}
+
+void RNA_def_wm_manipulator(BlenderRNA *brna)
+{
+ rna_def_manipulatorgroup(brna);
+}
+
+#endif /* RNA_RUNTIME */
diff --git a/source/blender/makesrna/intern/rna_wm_manipulator_api.c b/source/blender/makesrna/intern/rna_wm_manipulator_api.c
new file mode 100644
index 00000000000..c948f84e087
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_wm_manipulator_api.c
@@ -0,0 +1,290 @@
+/*
+ * ***** 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/makesrna/intern/rna_wm_manipulator_api.c
+ * \ingroup RNA
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "BLI_utildefines.h"
+
+#include "BKE_report.h"
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "DNA_windowmanager_types.h"
+
+#include "WM_api.h"
+
+#include "rna_internal.h" /* own include */
+
+#ifdef RNA_RUNTIME
+
+#include "UI_interface.h"
+#include "BKE_context.h"
+
+#include "ED_manipulator_library.h"
+
+static void rna_manipulator_draw_preset_box(
+ wmManipulator *mpr, float matrix[16], int select_id)
+{
+ ED_manipulator_draw_preset_box(mpr, (float (*)[4])matrix, select_id);
+}
+
+static void rna_manipulator_draw_preset_arrow(
+ wmManipulator *mpr, float matrix[16], int axis, int select_id)
+{
+ ED_manipulator_draw_preset_arrow(mpr, (float (*)[4])matrix, axis, select_id);
+}
+
+static void rna_manipulator_draw_preset_circle(
+ wmManipulator *mpr, float matrix[16], int axis, int select_id)
+{
+ ED_manipulator_draw_preset_circle(mpr, (float (*)[4])matrix, axis, select_id);
+}
+
+static void rna_manipulator_draw_preset_facemap(
+ wmManipulator *mpr, struct bContext *C, struct Object *ob, int facemap, int select_id)
+{
+ struct Scene *scene = CTX_data_scene(C);
+ ED_manipulator_draw_preset_facemap(C, mpr, scene, ob, facemap, select_id);
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Manipulator Property Define
+ * \{ */
+
+static void rna_manipulator_target_set_prop(
+ wmManipulator *mpr, ReportList *reports, const char *target_propname,
+ PointerRNA *ptr, const char *propname, int index)
+{
+ const wmManipulatorPropertyType *mpr_prop_type =
+ WM_manipulatortype_target_property_find(mpr->type, target_propname);
+ if (mpr_prop_type == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Manipulator target property '%s.%s' not found",
+ mpr->type->idname, target_propname);
+ return;
+ }
+
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ if (prop == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Property '%s.%s' not found",
+ RNA_struct_identifier(ptr->type), target_propname);
+ return;
+ }
+
+ if (mpr_prop_type->data_type != RNA_property_type(prop)) {
+ const int manipulator_type_index = RNA_enum_from_value(rna_enum_property_type_items, mpr_prop_type->data_type);
+ const int prop_type_index = RNA_enum_from_value(rna_enum_property_type_items, RNA_property_type(prop));
+ BLI_assert((manipulator_type_index != -1) && (prop_type_index == -1));
+
+ BKE_reportf(reports, RPT_ERROR, "Manipulator target '%s.%s' expects '%s', '%s.%s' is '%s'",
+ mpr->type->idname, target_propname,
+ rna_enum_property_type_items[manipulator_type_index].identifier,
+ RNA_struct_identifier(ptr->type), propname,
+ rna_enum_property_type_items[prop_type_index].identifier);
+ return;
+ }
+
+ if (RNA_property_array_check(prop)) {
+ if (index == -1) {
+ const int prop_array_length = RNA_property_array_length(ptr, prop);
+ if (mpr_prop_type->array_length != prop_array_length) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Manipulator target property '%s.%s' expects an array of length %d, found %d",
+ mpr->type->idname, target_propname,
+ mpr_prop_type->array_length,
+ prop_array_length);
+ return;
+ }
+ }
+ }
+ else {
+ if (mpr_prop_type->array_length != 1) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Manipulator target property '%s.%s' expects an array of length %d",
+ mpr->type->idname, target_propname,
+ mpr_prop_type->array_length);
+ return;
+ }
+ }
+
+ if (index >= mpr_prop_type->array_length) {
+ BKE_reportf(reports, RPT_ERROR, "Manipulator target property '%s.%s', index %d must be below %d",
+ mpr->type->idname, target_propname, index, mpr_prop_type->array_length);
+ return;
+ }
+
+ WM_manipulator_target_property_def_rna_ptr(mpr, mpr_prop_type, ptr, prop, index);
+}
+
+static PointerRNA rna_manipulator_target_set_operator(
+ wmManipulator *mpr, ReportList *reports, const char *opname, int part_index)
+{
+ wmOperatorType *ot;
+
+ ot = WM_operatortype_find(opname, 0); /* print error next */
+ if (!ot || !ot->srna) {
+ BKE_reportf(reports, RPT_ERROR, "%s '%s'", ot ? "unknown operator" : "operator missing srna", opname);
+ return PointerRNA_NULL;
+ }
+
+ /* For the return value to be usable, we need 'PointerRNA.data' to be set. */
+ IDProperty *properties;
+ {
+ IDPropertyTemplate val = {0};
+ properties = IDP_New(IDP_GROUP, &val, "wmManipulatorProperties");
+ }
+
+ return *WM_manipulator_operator_set(mpr, part_index, ot, properties);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Manipulator Property Access
+ * \{ */
+
+static int rna_manipulator_target_is_valid(
+ wmManipulator *mpr, ReportList *reports, const char *target_propname)
+{
+ wmManipulatorProperty *mpr_prop =
+ WM_manipulator_target_property_find(mpr, target_propname);
+ if (mpr_prop == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Manipulator target property '%s.%s' not found",
+ mpr->type->idname, target_propname);
+ return false;
+ }
+ return WM_manipulator_target_property_is_valid(mpr_prop);
+}
+
+/** \} */
+
+#else
+
+void RNA_api_manipulator(StructRNA *srna)
+{
+ /* Utility draw functions, since we don't expose new OpenGL drawing wrappers via Python yet.
+ * exactly how these should be exposed isn't totally clear.
+ * However it's probably good to have some high level API's for this anyway.
+ * Just note that this could be re-worked once tests are done.
+ */
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ /* -------------------------------------------------------------------- */
+ /* Primitive Shapes */
+
+ /* draw_preset_box */
+ func = RNA_def_function(srna, "draw_preset_box", "rna_manipulator_draw_preset_box");
+ RNA_def_function_ui_description(func, "Draw a box");
+ parm = RNA_def_property(func, "matrix", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(parm, "", "The matrix to transform");
+ RNA_def_int(func, "select_id", -1, -1, INT_MAX, "Zero when not selecting", "", -1, INT_MAX);
+
+ /* draw_preset_box */
+ func = RNA_def_function(srna, "draw_preset_arrow", "rna_manipulator_draw_preset_arrow");
+ RNA_def_function_ui_description(func, "Draw a box");
+ parm = RNA_def_property(func, "matrix", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(parm, "", "The matrix to transform");
+ RNA_def_enum(func, "axis", rna_enum_object_axis_items, 2, "", "Arrow Orientation");
+ RNA_def_int(func, "select_id", -1, -1, INT_MAX, "Zero when not selecting", "", -1, INT_MAX);
+
+ func = RNA_def_function(srna, "draw_preset_circle", "rna_manipulator_draw_preset_circle");
+ RNA_def_function_ui_description(func, "Draw a box");
+ parm = RNA_def_property(func, "matrix", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(parm, "", "The matrix to transform");
+ RNA_def_enum(func, "axis", rna_enum_object_axis_items, 2, "", "Arrow Orientation");
+ RNA_def_int(func, "select_id", -1, -1, INT_MAX, "Zero when not selecting", "", -1, INT_MAX);
+
+ /* -------------------------------------------------------------------- */
+ /* Other Shapes */
+
+ /* draw_preset_facemap */
+ func = RNA_def_function(srna, "draw_preset_facemap", "rna_manipulator_draw_preset_facemap");
+ RNA_def_function_ui_description(func, "Draw the face-map of a mesh object");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ parm = RNA_def_pointer(func, "object", "Object", "", "Object");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ RNA_def_int(func, "facemap", 0, 0, INT_MAX, "Face map index", "", 0, INT_MAX);
+ RNA_def_int(func, "select_id", -1, -1, INT_MAX, "Zero when not selecting", "", -1, INT_MAX);
+
+
+ /* -------------------------------------------------------------------- */
+ /* Property API */
+
+ /* Define Properties */
+ /* note, 'target_set_handler' is defined in 'bpy_rna_manipulator.c' */
+ func = RNA_def_function(srna, "target_set_prop", "rna_manipulator_target_set_prop");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "");
+ parm = RNA_def_string(func, "target", NULL, 0, "", "Target property");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* similar to UILayout.prop */
+ parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_string(func, "property", NULL, 0, "", "Identifier of property in data");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_int(func, "index", -1, -1, INT_MAX, "", "", -1, INT_MAX); /* RNA_NO_INDEX == -1 */
+
+ func = RNA_def_function(srna, "target_set_operator", "rna_manipulator_target_set_operator");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(
+ func, "Operator to run when activating the manipulator "
+ "(overrides property targets)");
+ parm = RNA_def_string(func, "operator", NULL, 0, "", "Target operator");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_int(func, "index", 0, 0, 255, "Part index", "", 0, 255);
+
+ /* similar to UILayout.operator */
+ parm = RNA_def_pointer(func, "properties", "OperatorProperties", "", "Operator properties to fill in");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_function_return(func, parm);
+
+ /* Access Properties */
+ /* note, 'target_get', 'target_set' is defined in 'bpy_rna_manipulator.c' */
+ func = RNA_def_function(srna, "target_is_valid", "rna_manipulator_target_is_valid");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_string(func, "property", NULL, 0, "", "Property identifier");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_function_ui_description(func, "");
+ parm = RNA_def_boolean(func, "result", 0, "", "");
+ RNA_def_function_return(func, parm);
+
+}
+
+
+void RNA_api_manipulatorgroup(StructRNA *UNUSED(srna))
+{
+ /* nothing yet */
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c
new file mode 100644
index 00000000000..0bed91f2807
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_workspace.c
@@ -0,0 +1,163 @@
+/*
+ * ***** 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/makesrna/intern/rna_workspace.c
+ * \ingroup RNA
+ */
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+#include "RNA_types.h"
+
+#include "BKE_workspace.h"
+
+#include "ED_render.h"
+
+#include "RE_engine.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "rna_internal.h"
+
+/* Allow accessing private members of DNA_workspace_types.h */
+#define DNA_PRIVATE_WORKSPACE_ALLOW
+#include "DNA_workspace_types.h"
+
+#ifdef RNA_RUNTIME
+
+#include "BLI_listbase.h"
+
+#include "BKE_global.h"
+
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+
+#include "RNA_access.h"
+
+
+void rna_workspace_screens_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ WorkSpace *workspace = ptr->id.data;
+ rna_iterator_listbase_begin(iter, BKE_workspace_layouts_get(workspace), NULL);
+}
+
+static PointerRNA rna_workspace_screens_item_get(CollectionPropertyIterator *iter)
+{
+ WorkSpaceLayout *layout = rna_iterator_listbase_get(iter);
+ bScreen *screen = BKE_workspace_layout_screen_get(layout);
+
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_Screen, screen);
+}
+
+void rna_workspace_transform_orientations_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ WorkSpace *workspace = ptr->id.data;
+ rna_iterator_listbase_begin(iter, BKE_workspace_transform_orientations_get(workspace), NULL);
+}
+
+static PointerRNA rna_workspace_transform_orientations_item_get(CollectionPropertyIterator *iter)
+{
+ TransformOrientation *transform_orientation = rna_iterator_listbase_get(iter);
+ return rna_pointer_inherit_refine(&iter->parent, &RNA_TransformOrientation, transform_orientation);
+}
+
+#else /* RNA_RUNTIME */
+
+static void rna_def_workspace(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "WorkSpace", "ID");
+ RNA_def_struct_sdna(srna, "WorkSpace");
+ RNA_def_struct_ui_text(srna, "Workspace", "Workspace data-block, defining the working environment for the user");
+ /* TODO: real icon, just to show something */
+ RNA_def_struct_ui_icon(srna, ICON_RENDER_RESULT);
+
+ prop = RNA_def_property(srna, "screens", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "layouts", NULL);
+ RNA_def_property_struct_type(prop, "Screen");
+ RNA_def_property_collection_funcs(prop, "rna_workspace_screens_begin", NULL, NULL,
+ "rna_workspace_screens_item_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Screens", "Screen layouts of a workspace");
+
+ prop = RNA_def_property(srna, "tool_keymap", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "tool.keymap");
+ RNA_def_property_ui_text(prop, "Active Tool", "Currently active tool keymap");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "tool_manipulator_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "tool.manipulator_group");
+ RNA_def_property_ui_text(prop, "Active Tool", "Currently active tool manipulator");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "tool_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "tool.index");
+ RNA_def_property_ui_text(prop, "Active Tool Index", "Tool group index");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "orientations", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "transform_orientations", NULL);
+ RNA_def_property_struct_type(prop, "TransformOrientation");
+ RNA_def_property_collection_funcs(prop, "rna_workspace_transform_orientations_begin", NULL, NULL,
+ "rna_workspace_transform_orientations_item_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Transform Orientations", "");
+
+ /* View Render */
+ prop = RNA_def_property(srna, "view_render", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "ViewRenderSettings");
+ RNA_def_property_ui_text(prop, "View Render", "");
+
+ /* Flags */
+ prop = RNA_def_property(srna, "use_scene_settings", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", WORKSPACE_USE_SCENE_SETTINGS);
+ RNA_def_property_ui_text(prop, "Scene Settings",
+ "Use scene settings instead of workspace settings");
+ RNA_def_property_update(prop, NC_SCREEN | ND_LAYER, NULL);
+}
+
+static void rna_def_transform_orientation(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "TransformOrientation", NULL);
+
+ prop = RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_float_sdna(prop, NULL, "mat");
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_3x3);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_ui_text(prop, "Name", "Name of the custom transform orientation");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+}
+
+void RNA_def_workspace(BlenderRNA *brna)
+{
+ rna_def_workspace(brna);
+ rna_def_transform_orientation(brna);
+}
+
+#endif /* RNA_RUNTIME */
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index 925bc52d06f..15fa686a40a 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -43,10 +43,12 @@
#include "MEM_guardedalloc.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_texture.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "ED_node.h"
#include "WM_api.h"
@@ -88,7 +90,7 @@ static void rna_World_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
{
World *wo = ptr->id.data;
- DAG_id_tag_update(&wo->id, 0);
+ DEG_id_tag_update(&wo->id, 0);
WM_main_add_notifier(NC_WORLD | ND_WORLD, wo);
}
@@ -97,7 +99,7 @@ static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
{
World *wo = ptr->id.data;
- DAG_id_tag_update(&wo->id, 0);
+ DEG_id_tag_update(&wo->id, 0);
WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, wo);
}
#endif
@@ -106,7 +108,7 @@ static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
{
World *wo = ptr->id.data;
- DAG_id_tag_update(&wo->id, 0);
+ DEG_id_tag_update(&wo->id, 0);
WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, wo);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
@@ -114,11 +116,15 @@ static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
static void rna_World_use_nodes_update(bContext *C, PointerRNA *ptr)
{
World *wrld = (World *)ptr->data;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
if (wrld->use_nodes && wrld->nodetree == NULL)
ED_node_shader_default(C, &wrld->id);
-
- rna_World_update(CTX_data_main(C), CTX_data_scene(C), ptr);
+
+ DEG_relations_tag_update(bmain);
+ rna_World_update(bmain, scene, ptr);
+ rna_World_draw_update(bmain, scene, ptr);
}
#else
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index ad2b862141c..d6a7b94505f 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -114,10 +114,6 @@ set(SRC
intern/MOD_weightvg_util.h
)
-if(WITH_LEGACY_DEPSGRAPH)
- add_definitions(-DWITH_LEGACY_DEPSGRAPH)
-endif()
-
if(WITH_ALEMBIC)
add_definitions(-DWITH_ALEMBIC)
list(APPEND INC
@@ -162,4 +158,7 @@ if(WITH_OPENSUBDIV)
add_definitions(-DWITH_OPENSUBDIV)
endif()
+# So we can have special tricks in modifier system.
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(bf_modifiers "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index f2f76f13883..60c7998853e 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -50,8 +50,6 @@
#include "MEM_guardedalloc.h"
-#include "depsgraph_private.h"
-
#include "MOD_util.h"
@@ -99,22 +97,6 @@ static void foreachObjectLink(
walk(userData, ob, &amd->object, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- ArmatureModifierData *amd = (ArmatureModifierData *) md;
-
- if (amd->object) {
- DagNode *curNode = dag_get_node(forest, amd->object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Armature Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -128,8 +110,8 @@ static void updateDepsgraph(ModifierData *md,
}
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts,
ModifierApplyFlag UNUSED(flag))
@@ -149,7 +131,7 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct BMEditMesh *em,
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, struct BMEditMesh *em,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
ArmatureModifierData *amd = (ArmatureModifierData *) md;
@@ -172,7 +154,7 @@ static void deformVertsEM(
}
static void deformMatricesEM(
- ModifierData *md, Object *ob, struct BMEditMesh *em,
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, struct BMEditMesh *em,
DerivedMesh *derivedData, float (*vertexCos)[3],
float (*defMats)[3][3], int numVerts)
{
@@ -187,7 +169,7 @@ static void deformMatricesEM(
if (!derivedData) dm->release(dm);
}
-static void deformMatrices(ModifierData *md, Object *ob, DerivedMesh *derivedData,
+static void deformMatrices(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], float (*defMats)[3][3], int numVerts)
{
ArmatureModifierData *amd = (ArmatureModifierData *) md;
@@ -221,7 +203,6 @@ ModifierTypeInfo modifierType_Armature = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index a3f3af0c748..cd19020d375 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -54,13 +54,7 @@
#include "MOD_util.h"
-#include "depsgraph_private.h"
-
-/* Due to cyclic dependencies it's possible that curve used for
- * deformation here is not evaluated at the time of evaluating
- * this modifier.
- */
-#define CYCLIC_DEPENDENCY_WORKAROUND
+#include "DEG_depsgraph.h"
static void initData(ModifierData *md)
{
@@ -102,40 +96,6 @@ static void foreachObjectLink(
walk(userData, ob, &amd->offset_ob, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- ArrayModifierData *amd = (ArrayModifierData *) md;
-
- if (amd->start_cap) {
- DagNode *curNode = dag_get_node(forest, amd->start_cap);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
- if (amd->end_cap) {
- DagNode *curNode = dag_get_node(forest, amd->end_cap);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
- if (amd->curve_ob) {
- DagNode *curNode = dag_get_node(forest, amd->curve_ob);
- curNode->eval_flags |= DAG_EVAL_NEED_CURVE_PATH;
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
- if (amd->offset_ob) {
- DagNode *curNode = dag_get_node(forest, amd->offset_ob);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -390,8 +350,7 @@ static void dm_merge_transform(
}
static DerivedMesh *arrayModifier_doArray(
- ArrayModifierData *amd,
- Scene *scene, Object *ob, DerivedMesh *dm,
+ ArrayModifierData *amd, Object *ob, DerivedMesh *dm,
ModifierApplyFlag flag)
{
const float eps = 1e-6f;
@@ -494,12 +453,6 @@ static DerivedMesh *arrayModifier_doArray(
if (amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
Curve *cu = amd->curve_ob->data;
if (cu) {
-#ifdef CYCLIC_DEPENDENCY_WORKAROUND
- if (amd->curve_ob->curve_cache == NULL) {
- BKE_displist_make_curveTypes(scene, amd->curve_ob, false);
- }
-#endif
-
if (amd->curve_ob->curve_cache && amd->curve_ob->curve_cache->path) {
float scale_fac = mat4_to_scale(amd->curve_ob->obmat);
length = scale_fac * amd->curve_ob->curve_cache->path->totdist;
@@ -779,12 +732,12 @@ static DerivedMesh *arrayModifier_doArray(
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *dm,
+static DerivedMesh *applyModifier(ModifierData *md, const EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *dm,
ModifierApplyFlag flag)
{
ArrayModifierData *amd = (ArrayModifierData *) md;
- return arrayModifier_doArray(amd, md->scene, ob, dm, flag);
+ return arrayModifier_doArray(amd, ob, dm, flag);
}
@@ -810,7 +763,6 @@ ModifierTypeInfo modifierType_Array = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index 93dc0203f83..35b8a3fd9cb 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -86,8 +86,8 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
/*
* This calls the new bevel code (added since 2.64)
*/
-static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob,
- DerivedMesh *dm,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ struct Object *ob, DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *result;
@@ -205,7 +205,6 @@ ModifierTypeInfo modifierType_Bevel = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 1140460161f..5811017f745 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -49,8 +49,6 @@
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "depsgraph_private.h"
-
#include "MOD_boolean_util.h"
#include "MOD_util.h"
@@ -105,22 +103,6 @@ static void foreachObjectLink(
walk(userData, ob, &bmd->object, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- BooleanModifierData *bmd = (BooleanModifierData *) md;
-
- if (bmd->object) {
- DagNode *curNode = dag_get_node(forest, bmd->object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Boolean Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -443,8 +425,8 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(
}
static DerivedMesh *applyModifier(
- ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
ModifierApplyFlag flag)
{
BooleanModifierData *bmd = (BooleanModifierData *)md;
@@ -483,7 +465,6 @@ ModifierTypeInfo modifierType_Boolean = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index 56a274b9ac9..0a0ad11fe16 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -75,8 +75,8 @@ static bool dependsOnTime(ModifierData *UNUSED(md))
return true;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
- DerivedMesh *derivedData,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *UNUSED(ob), DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *dm = derivedData;
@@ -324,7 +324,6 @@ ModifierTypeInfo modifierType_Build = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index ddcf1852dc6..93a5b9607bf 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -45,9 +45,6 @@
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-
-#include "depsgraph_private.h"
-
#include "MOD_util.h"
static void initData(ModifierData *md)
@@ -105,22 +102,6 @@ static void foreachObjectLink(
walk(userData, ob, &cmd->object, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- CastModifierData *cmd = (CastModifierData *) md;
-
- if (cmd->object) {
- DagNode *curNode = dag_get_node(forest, cmd->object);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
- "Cast Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -452,8 +433,8 @@ static void cuboid_do(
}
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts,
ModifierApplyFlag UNUSED(flag))
@@ -475,7 +456,8 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct BMEditMesh *editData,
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, false, false);
@@ -513,7 +495,6 @@ ModifierTypeInfo modifierType_Cast = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index e8c39770a14..b234cc63228 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -43,7 +43,6 @@
#include "BLI_utildefines.h"
-
#include "BKE_cloth.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_effect.h"
@@ -53,8 +52,6 @@
#include "BKE_modifier.h"
#include "BKE_pointcache.h"
-#include "depsgraph_private.h"
-
#include "MOD_util.h"
static void initData(ModifierData *md)
@@ -72,7 +69,7 @@ static void initData(ModifierData *md)
cloth_init(clmd);
}
-static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3],
+static void deformVerts(ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3],
int numVerts, ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *dm;
@@ -112,31 +109,11 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
CDDM_apply_vert_coords(dm, vertexCos);
- clothModifier_do(clmd, md->scene, ob, dm, vertexCos);
+ clothModifier_do(clmd, eval_ctx, md->scene, ob, dm, vertexCos);
dm->release(dm);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- Scene *scene, Object *ob, DagNode *obNode)
-{
- ClothModifierData *clmd = (ClothModifierData *) md;
-
- if (clmd) {
- /* Actual code uses get_collisionobjects */
-#ifdef WITH_LEGACY_DEPSGRAPH
- dag_add_collision_relations(forest, scene, ob, obNode, clmd->coll_parms->group, ob->lay|scene->lay, eModifierType_Collision, NULL, true, "Cloth Collision");
- dag_add_forcefield_relations(forest, scene, ob, obNode, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
-#else
- (void)forest;
- (void)scene;
- (void)ob;
- (void)obNode;
-#endif
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -146,7 +123,7 @@ static void updateDepsgraph(ModifierData *md,
ClothModifierData *clmd = (ClothModifierData *)md;
if (clmd != NULL) {
/* Actual code uses get_collisionobjects */
- DEG_add_collision_relations(node, scene, ob, clmd->coll_parms->group, ob->lay|scene->lay, eModifierType_Collision, NULL, true, "Cloth Collision");
+ DEG_add_collision_relations(node, scene, ob, clmd->coll_parms->group, eModifierType_Collision, NULL, true, "Cloth Collision");
DEG_add_forcefield_relations(node, scene, ob, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
}
@@ -262,7 +239,6 @@ ModifierTypeInfo modifierType_Cloth = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index 74e49dda074..b9a2310366a 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -98,8 +98,8 @@ static bool dependsOnTime(ModifierData *UNUSED(md))
return true;
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int UNUSED(numVerts),
ModifierApplyFlag UNUSED(flag))
@@ -264,7 +264,6 @@ ModifierTypeInfo modifierType_Collision = {
/* requiredDataMask */ NULL,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c
index 77fd84a2948..716b918d0f0 100644
--- a/source/blender/modifiers/intern/MOD_correctivesmooth.c
+++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c
@@ -713,7 +713,7 @@ error:
static void deformVerts(
- ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *dm = get_dm(ob, NULL, derivedData, NULL, false, false);
@@ -727,7 +727,7 @@ static void deformVerts(
static void deformVertsEM(
- ModifierData *md, Object *ob, struct BMEditMesh *editData,
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, false, false);
@@ -759,7 +759,6 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index c9a910d769b..62c9f8796a0 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -39,12 +39,13 @@
#include "BLI_utildefines.h"
+
#include "BKE_cdderivedmesh.h"
#include "BKE_lattice.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "depsgraph_private.h"
+#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "MOD_modifiertypes.h"
@@ -92,23 +93,6 @@ static void foreachObjectLink(
walk(userData, ob, &cmd->object, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- CurveModifierData *cmd = (CurveModifierData *) md;
-
- if (cmd->object) {
- DagNode *curNode = dag_get_node(forest, cmd->object);
- curNode->eval_flags |= DAG_EVAL_NEED_CURVE_PATH;
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -131,8 +115,8 @@ static void updateDepsgraph(ModifierData *md,
DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Curve Modifier");
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts,
ModifierApplyFlag UNUSED(flag))
@@ -141,19 +125,19 @@ static void deformVerts(ModifierData *md, Object *ob,
/* silly that defaxis and curve_deform_verts are off by 1
* but leave for now to save having to call do_versions */
- curve_deform_verts(md->scene, cmd->object, ob, derivedData, vertexCos, numVerts,
+ curve_deform_verts(cmd->object, ob, derivedData, vertexCos, numVerts,
cmd->name, cmd->defaxis - 1);
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct BMEditMesh *em,
+ ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob, struct BMEditMesh *em,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
if (!derivedData) dm = CDDM_from_editbmesh(em, false, false);
- deformVerts(md, ob, dm, vertexCos, numVerts, 0);
+ deformVerts(md, eval_ctx, ob, dm, vertexCos, numVerts, 0);
if (!derivedData) dm->release(dm);
}
@@ -179,7 +163,6 @@ ModifierTypeInfo modifierType_Curve = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index a2210893602..e7069937868 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -50,8 +50,6 @@
#include "MEM_guardedalloc.h"
#include "MOD_util.h"
-#include "depsgraph_private.h"
-
/**************************************
* Modifiers functions. *
**************************************/
@@ -127,22 +125,6 @@ static void foreachObjectLink(
walk(userData, ob, &dtmd->ob_source, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
- DagNode *curNode;
-
- if (dtmd->ob_source) {
- curNode = dag_get_node(forest, dtmd->ob_source);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "DataTransfer Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -170,7 +152,7 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
DT_TYPE_SHARP_FACE \
)
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob, DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
@@ -202,7 +184,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
BKE_reports_init(&reports, RPT_STORE);
/* Note: no islands precision for now here. */
- BKE_object_data_transfer_dm(md->scene, dtmd->ob_source, ob, dm, dtmd->data_types, false,
+ BKE_object_data_transfer_dm(eval_ctx, md->scene, dtmd->ob_source, ob, dm, dtmd->data_types, false,
dtmd->vmap_mode, dtmd->emap_mode, dtmd->lmap_mode, dtmd->pmap_mode,
space_transform, false, max_dist, dtmd->map_ray_radius, 0.0f,
dtmd->layers_select_src, dtmd->layers_select_dst,
@@ -254,7 +236,6 @@ ModifierTypeInfo modifierType_DataTransfer = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index 617ae5a89f3..078a3085fc7 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -86,8 +86,8 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
DecimateModifierData *dmd = (DecimateModifierData *) md;
@@ -227,7 +227,6 @@ ModifierTypeInfo modifierType_Decimate = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index fb8c0dd05a5..c9ccdc3b8c2 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -50,7 +50,6 @@
#include "BKE_deform.h"
#include "BKE_object.h"
-#include "depsgraph_private.h"
#include "MEM_guardedalloc.h"
#include "MOD_util.h"
@@ -155,31 +154,6 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
return ((!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) || dmd->strength == 0.0f);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- DisplaceModifierData *dmd = (DisplaceModifierData *) md;
-
- if (dmd->map_object && dmd->texmapping == MOD_DISP_MAP_OBJECT) {
- DagNode *curNode = dag_get_node(forest, dmd->map_object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Displace Modifier");
- }
-
-
- if (dmd->texmapping == MOD_DISP_MAP_GLOBAL ||
- (ELEM(dmd->direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) &&
- dmd->space == MOD_DISP_SPACE_GLOBAL))
- {
- dag_add_relation(forest, obNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Displace Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -397,8 +371,8 @@ static void displaceModifier_do(
}
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts,
ModifierApplyFlag UNUSED(flag))
@@ -413,7 +387,7 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct BMEditMesh *editData,
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = get_cddm(ob, editData, derivedData, vertexCos, dependsOnNormals(md));
@@ -445,7 +419,6 @@ ModifierTypeInfo modifierType_Displace = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index eec97828091..cf3f84364ea 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -36,11 +36,13 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_dynamicpaint.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "depsgraph_private.h"
+#include "DEG_depsgraph.h"
+
#include "DEG_depsgraph_build.h"
#include "MOD_modifiertypes.h"
@@ -89,7 +91,7 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ ||
surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE)
{
- dataMask |= CD_MASK_MLOOPUV | CD_MASK_MTEXPOLY;
+ dataMask |= CD_MASK_MLOOPUV;
}
/* mcol */
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT ||
@@ -106,21 +108,21 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
if (pmd->brush) {
if (pmd->brush->flags & MOD_DPAINT_USE_MATERIAL) {
- dataMask |= CD_MASK_MLOOPUV | CD_MASK_MTEXPOLY;
+ dataMask |= CD_MASK_MLOOPUV;
}
}
return dataMask;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *dm,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, DerivedMesh *dm,
ModifierApplyFlag flag)
{
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *) md;
/* dont apply dynamic paint on orco dm stack */
if (!(flag & MOD_APPLY_ORCO)) {
- return dynamicPaint_Modifier_do(pmd, md->scene, ob, dm);
+ return dynamicPaint_Modifier_do(pmd, eval_ctx, md->scene, ob, dm);
}
return dm;
}
@@ -130,34 +132,6 @@ static bool is_brush_cb(Object *UNUSED(ob), ModifierData *pmd)
return ((DynamicPaintModifierData *)pmd)->brush != NULL;
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *scene,
- Object *ob,
- DagNode *obNode)
-{
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *) md;
-
- /* add relation from canvases to all brush objects */
- if (pmd && pmd->canvas) {
-#ifdef WITH_LEGACY_DEPSGRAPH
- for (DynamicPaintSurface *surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
- if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
- dag_add_forcefield_relations(forest, scene, ob, obNode, surface->effector_weights, true, 0, "Dynamic Paint Field");
- }
-
- /* Actual code uses custom loop over group/scene without layer checks in dynamicPaint_doStep */
- dag_add_collision_relations(forest, scene, ob, obNode, surface->brush_group, -1, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush");
- }
-#else
- (void)forest;
- (void)scene;
- (void)ob;
- (void)obNode;
-#endif
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -173,7 +147,7 @@ static void updateDepsgraph(ModifierData *md,
}
/* Actual code uses custom loop over group/scene without layer checks in dynamicPaint_doStep */
- DEG_add_collision_relations(node, scene, ob, surface->brush_group, -1, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush");
+ DEG_add_collision_relations(node, scene, ob, surface->brush_group, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush");
}
}
}
@@ -232,7 +206,6 @@ ModifierTypeInfo modifierType_DynamicPaint = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index a17870f2bf4..0e344a851f2 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -121,7 +121,8 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), DerivedMesh *dm,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *UNUSED(ob), DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *result;
@@ -158,7 +159,6 @@ ModifierTypeInfo modifierType_EdgeSplit = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 72bc046b440..38785abbc19 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -785,9 +785,10 @@ static DerivedMesh *cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
return splitdm;
}
-static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
- ParticleSystemModifierData *psmd, Scene *scene, Object *ob,
- DerivedMesh *to_explode)
+static DerivedMesh *explodeMesh(
+ ExplodeModifierData *emd,
+ ParticleSystemModifierData *psmd, const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, DerivedMesh *to_explode)
{
DerivedMesh *explode, *dm = to_explode;
MFace *mf = NULL, *mface;
@@ -812,6 +813,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
mface = dm->getTessFaceArray(dm);
totpart = psmd->psys->totpart;
+ sim.eval_ctx = eval_ctx;
sim.scene = scene;
sim.ob = ob;
sim.psys = psmd->psys;
@@ -993,8 +995,8 @@ static ParticleSystemModifierData *findPrecedingParticlesystem(Object *ob, Modif
}
return psmd;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *dm = derivedData;
@@ -1028,7 +1030,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (emd->flag & eExplodeFlag_EdgeCut) {
int *facepa = emd->facepa;
DerivedMesh *splitdm = cutEdges(emd, dm);
- DerivedMesh *explode = explodeMesh(emd, psmd, md->scene, ob, splitdm);
+ DerivedMesh *explode = explodeMesh(emd, psmd, eval_ctx, md->scene, ob, splitdm);
MEM_freeN(emd->facepa);
emd->facepa = facepa;
@@ -1036,7 +1038,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
return explode;
}
else
- return explodeMesh(emd, psmd, md->scene, ob, derivedData);
+ return explodeMesh(emd, psmd, eval_ctx, md->scene, ob, derivedData);
}
return derivedData;
}
@@ -1059,7 +1061,6 @@ ModifierTypeInfo modifierType_Explode = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c
index 53f955b15f0..f9e7f10653b 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim.c
@@ -41,9 +41,9 @@
#include "BKE_cdderivedmesh.h"
+#include "BKE_layer.h"
#include "BKE_modifier.h"
-#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
#include "MOD_fluidsim_util.h"
@@ -82,8 +82,8 @@ static void copyData(ModifierData *md, ModifierData *target)
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *dm,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *dm,
ModifierApplyFlag flag)
{
FluidsimModifierData *fluidmd = (FluidsimModifierData *) md;
@@ -103,33 +103,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
return result ? result : dm;
}
-static void updateDepgraph(
- ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain), Scene *scene,
- Object *ob, DagNode *obNode)
-{
- FluidsimModifierData *fluidmd = (FluidsimModifierData *) md;
- Base *base;
-
- if (fluidmd && fluidmd->fss) {
- if (fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) {
- for (base = scene->base.first; base; base = base->next) {
- Object *ob1 = base->object;
- if (ob1 != ob) {
- FluidsimModifierData *fluidmdtmp =
- (FluidsimModifierData *)modifiers_findByType(ob1, eModifierType_Fluidsim);
-
- /* only put dependencies from NON-DOMAIN fluids in here */
- if (fluidmdtmp && fluidmdtmp->fss && (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN)) {
- DagNode *curNode = dag_get_node(forest, ob1);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Fluidsim Object");
- }
- }
- }
- }
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -139,9 +112,8 @@ static void updateDepsgraph(ModifierData *md,
FluidsimModifierData *fluidmd = (FluidsimModifierData *) md;
if (fluidmd && fluidmd->fss) {
if (fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) {
- Base *base;
- for (base = scene->base.first; base; base = base->next) {
- Object *ob1 = base->object;
+ FOREACH_SCENE_OBJECT(scene, ob1)
+ {
if (ob1 != ob) {
FluidsimModifierData *fluidmdtmp =
(FluidsimModifierData *)modifiers_findByType(ob1, eModifierType_Fluidsim);
@@ -152,6 +124,7 @@ static void updateDepsgraph(ModifierData *md,
}
}
}
+ FOREACH_SCENE_OBJECT_END
}
}
}
@@ -183,7 +156,6 @@ ModifierTypeInfo modifierType_Fluidsim = {
/* requiredDataMask */ NULL,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index 56c494ff3c0..25617c84dac 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -46,8 +46,6 @@
#include "BKE_deform.h"
#include "BKE_colortools.h"
-
-#include "depsgraph_private.h"
#include "MEM_guardedalloc.h"
#include "MOD_util.h"
@@ -118,24 +116,6 @@ static void foreachObjectLink(
walk(userData, ob, &hmd->object, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- HookModifierData *hmd = (HookModifierData *) md;
-
- if (hmd->object) {
- DagNode *curNode = dag_get_node(forest, hmd->object);
-
- if (hmd->subtarget[0])
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Hook Modifier");
- else
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "Hook Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -376,7 +356,7 @@ static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
}
}
-static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts,
ModifierApplyFlag UNUSED(flag))
{
@@ -392,7 +372,7 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
dm->release(dm);
}
-static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *editData,
+static void deformVertsEM(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
HookModifierData *hmd = (HookModifierData *) md;
@@ -427,7 +407,6 @@ ModifierTypeInfo modifierType_Hook = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index c2896e83a0b..d322b8631d2 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -724,7 +724,7 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *dm = get_dm(ob, NULL, derivedData, NULL, false, false);
@@ -736,7 +736,7 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct BMEditMesh *editData,
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, false, false);
@@ -775,7 +775,6 @@ ModifierTypeInfo modifierType_LaplacianDeform = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index f1216ff462a..d7bc7b6c427 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -506,7 +506,7 @@ static CustomDataMask required_data_mask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *dm;
@@ -524,7 +524,7 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct BMEditMesh *editData,
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm;
@@ -561,7 +561,6 @@ ModifierTypeInfo modifierType_LaplacianSmooth = {
/* requiredDataMask */ required_data_mask,
/* freeData */ NULL,
/* isDisabled */ is_disabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index dc246084dca..cd8b6139d75 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -44,8 +44,6 @@
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "depsgraph_private.h"
-
#include "MOD_util.h"
static void initData(ModifierData *md)
@@ -91,22 +89,6 @@ static void foreachObjectLink(
walk(userData, ob, &lmd->object, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- LatticeModifierData *lmd = (LatticeModifierData *) md;
-
- if (lmd->object) {
- DagNode *latNode = dag_get_node(forest, lmd->object);
-
- dag_add_relation(forest, latNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Lattice Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -121,8 +103,8 @@ static void updateDepsgraph(ModifierData *md,
DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Lattice Modifier");
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts,
ModifierApplyFlag UNUSED(flag))
@@ -137,14 +119,14 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct BMEditMesh *em,
+ ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob, struct BMEditMesh *em,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
if (!derivedData) dm = CDDM_from_editbmesh(em, false, false);
- deformVerts(md, ob, dm, vertexCos, numVerts, 0);
+ deformVerts(md, eval_ctx, ob, dm, vertexCos, numVerts, 0);
if (!derivedData) dm->release(dm);
}
@@ -169,7 +151,6 @@ ModifierTypeInfo modifierType_Lattice = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 18caf4a39f4..d942b23b216 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -50,7 +50,6 @@
#include "BKE_modifier.h"
#include "BKE_deform.h"
-#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
#include "MOD_modifiertypes.h"
@@ -79,24 +78,6 @@ static void foreachObjectLink(
walk(userData, ob, &mmd->ob_arm, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- MaskModifierData *mmd = (MaskModifierData *)md;
-
- if (mmd->ob_arm) {
- bArmature *arm = (bArmature *)mmd->ob_arm->data;
- DagNode *armNode = dag_get_node(forest, mmd->ob_arm);
-
- /* tag relationship in depsgraph, but also on the armature */
- dag_add_relation(forest, armNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mask Modifier");
- arm->flag |= ARM_HAS_VIZ_DEPS;
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -113,8 +94,8 @@ static void updateDepsgraph(ModifierData *md,
}
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *dm,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
{
MaskModifierData *mmd = (MaskModifierData *)md;
@@ -403,7 +384,6 @@ ModifierTypeInfo modifierType_Mask = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c
index aa3e3ebcf7e..c990951c578 100644
--- a/source/blender/modifiers/intern/MOD_meshcache.c
+++ b/source/blender/modifiers/intern/MOD_meshcache.c
@@ -272,8 +272,8 @@ static void meshcache_do(
}
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts,
ModifierApplyFlag UNUSED(flag))
@@ -284,7 +284,7 @@ static void deformVerts(ModifierData *md, Object *ob,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct BMEditMesh *UNUSED(editData),
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
@@ -313,7 +313,6 @@ ModifierTypeInfo modifierType_MeshCache = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index b1938395a7b..ab43204365d 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -47,8 +47,6 @@
#include "BKE_deform.h"
#include "BKE_editmesh.h"
-#include "depsgraph_private.h"
-
#include "MEM_guardedalloc.h"
#include "MOD_util.h"
@@ -122,23 +120,6 @@ static void foreachObjectLink(
walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- MeshDeformModifierData *mmd = (MeshDeformModifierData *) md;
-
- if (mmd->object) {
- DagNode *curNode = dag_get_node(forest, mmd->object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA | DAG_RL_DATA_OB | DAG_RL_OB_OB,
- "Mesh Deform Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -291,7 +272,7 @@ static void meshdeform_vert_task(void *userdata, const int iter)
}
static void meshdeformModifier_do(
- ModifierData *md, Object *ob, DerivedMesh *dm,
+ ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
MeshDeformModifierData *mmd = (MeshDeformModifierData *) md;
@@ -318,7 +299,7 @@ static void meshdeformModifier_do(
*/
if (mmd->object == md->scene->obedit) {
BMEditMesh *em = BKE_editmesh_from_object(mmd->object);
- tmpdm = editbmesh_get_derived_cage_and_final(md->scene, mmd->object, em, 0, &cagedm);
+ tmpdm = editbmesh_get_derived_cage_and_final(eval_ctx, md->scene, mmd->object, em, 0, &cagedm);
if (tmpdm)
tmpdm->release(tmpdm);
}
@@ -421,7 +402,7 @@ static void meshdeformModifier_do(
cagedm->release(cagedm);
}
-static void deformVerts(ModifierData *md, Object *ob,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob,
DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts,
@@ -431,13 +412,13 @@ static void deformVerts(ModifierData *md, Object *ob,
modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
- meshdeformModifier_do(md, ob, dm, vertexCos, numVerts);
+ meshdeformModifier_do(md, eval_ctx, ob, dm, vertexCos, numVerts);
if (dm && dm != derivedData)
dm->release(dm);
}
-static void deformVertsEM(ModifierData *md, Object *ob,
+static void deformVertsEM(ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob,
struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData,
float (*vertexCos)[3],
@@ -445,7 +426,7 @@ static void deformVertsEM(ModifierData *md, Object *ob,
{
DerivedMesh *dm = get_dm(ob, NULL, derivedData, NULL, false, false);
- meshdeformModifier_do(md, ob, dm, vertexCos, numVerts);
+ meshdeformModifier_do(md, eval_ctx, ob, dm, vertexCos, numVerts);
if (dm && dm != derivedData)
dm->release(dm);
@@ -534,7 +515,6 @@ ModifierTypeInfo modifierType_MeshDeform = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index 3e527489d20..e28459814e2 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -38,7 +38,6 @@
#include "BKE_library_query.h"
#include "BKE_scene.h"
-#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
#include "MOD_modifiertypes.h"
@@ -95,8 +94,8 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
return (mcmd->cache_file == NULL) || (mcmd->object_path[0] == '\0');
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *dm,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
{
#ifdef WITH_ALEMBIC
@@ -174,23 +173,6 @@ static void foreachIDLink(ModifierData *md, Object *ob,
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *bmain,
- struct Scene *scene,
- Object *ob, DagNode *obNode)
-{
- MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md;
-
- if (mcmd->cache_file != NULL) {
- DagNode *curNode = dag_get_node(forest, mcmd->cache_file);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Cache File Modifier");
- }
-
- UNUSED_VARS(bmain, scene, ob);
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *bmain,
struct Scene *scene,
@@ -224,7 +206,6 @@ ModifierTypeInfo modifierType_MeshSequenceCache = {
/* requiredDataMask */ NULL,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 157f37e973c..db06dc43b8e 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -45,7 +45,6 @@
#include "MEM_guardedalloc.h"
-#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
#include "MOD_modifiertypes.h"
@@ -77,21 +76,6 @@ static void foreachObjectLink(
walk(userData, ob, &mmd->mirror_ob, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- MirrorModifierData *mmd = (MirrorModifierData *) md;
-
- if (mmd->mirror_ob) {
- DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
-
- dag_add_relation(forest, latNode, obNode, DAG_RL_OB_DATA, "Mirror Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -339,8 +323,8 @@ static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
return result;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *result;
@@ -379,7 +363,6 @@ ModifierTypeInfo modifierType_Mirror = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index f9f17b88fa4..2b675d36140 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -67,8 +67,8 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm,
- ModifierApplyFlag flag)
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob,
+ DerivedMesh *dm, ModifierApplyFlag flag)
{
MultiresModifierData *mmd = (MultiresModifierData *)md;
DerivedMesh *result;
@@ -163,7 +163,6 @@ ModifierTypeInfo modifierType_Multires = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c
index d9d9ba2966d..3fb780f566d 100644
--- a/source/blender/modifiers/intern/MOD_none.c
+++ b/source/blender/modifiers/intern/MOD_none.c
@@ -67,7 +67,6 @@ ModifierTypeInfo modifierType_None = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index 20eae751ca4..1c7c640b971 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -42,8 +42,6 @@
#include "BKE_mesh.h"
#include "BKE_deform.h"
-#include "depsgraph_private.h"
-
#include "MOD_util.h"
@@ -511,20 +509,6 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
return !is_valid_target(enmd);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- NormalEditModifierData *enmd = (NormalEditModifierData *) md;
-
- if (enmd->target) {
- DagNode *Node = dag_get_node(forest, enmd->target);
-
- dag_add_relation(forest, Node, obNode, DAG_RL_OB_DATA, "NormalEdit Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -537,7 +521,8 @@ static void updateDepsgraph(ModifierData *md,
}
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, ModifierApplyFlag UNUSED(flag))
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob,
+ DerivedMesh *dm, ModifierApplyFlag UNUSED(flag))
{
return normalEditModifier_do((NormalEditModifierData *)md, ob, dm);
}
@@ -562,7 +547,6 @@ ModifierTypeInfo modifierType_NormalEdit = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index 8d8565e7e62..189cfb8553e 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -378,7 +378,6 @@ static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd)
/* add uvs */
if (CustomData_number_of_layers(&result->loopData, CD_MLOOPUV) < MAX_MTFACE) {
gogd.mloopuvs = CustomData_add_layer(&result->loopData, CD_MLOOPUV, CD_CALLOC, NULL, num_polys * 4);
- CustomData_add_layer(&result->polyData, CD_MTEXPOLY, CD_CALLOC, NULL, num_polys);
if (gogd.mloopuvs) { /* unlikely to fail */
gogd.ix = 1.0 / gogd.rx;
@@ -543,8 +542,8 @@ static DerivedMesh *doOcean(ModifierData *md, Object *UNUSED(ob),
}
#endif /* WITH_OCEANSIM */
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *result;
@@ -578,7 +577,6 @@ ModifierTypeInfo modifierType_Ocean = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 0c91cb08da7..de59635f335 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -51,7 +51,6 @@
#include "BKE_particle.h"
#include "BKE_pointcache.h"
-#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
#include "MOD_modifiertypes.h"
@@ -112,24 +111,6 @@ static bool isDisabled(ModifierData *md, int useRenderParams)
return false;
}
-
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
-
- if (pimd->ob) {
- DagNode *curNode = dag_get_node(forest, pimd->ob);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "Particle Instance Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -185,8 +166,8 @@ static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psy
return 0;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *dm = derivedData, *result;
@@ -231,6 +212,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (totpart == 0)
return derivedData;
+ sim.eval_ctx = eval_ctx;
sim.scene = md->scene;
sim.ob = pimd->ob;
sim.psys = psys;
@@ -462,7 +444,6 @@ ModifierTypeInfo modifierType_ParticleInstance = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index d8cccca415c..9cc6e5f56b5 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -97,8 +97,8 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
}
/* saves the current emitter state for a particle system and calculates particles */
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int UNUSED(numVerts),
ModifierApplyFlag flag)
@@ -186,7 +186,7 @@ static void deformVerts(ModifierData *md, Object *ob,
if (!(ob->transflag & OB_NO_PSYS_UPDATE)) {
psmd->flag &= ~eParticleSystemFlag_psys_updated;
- particle_system_update(md->scene, ob, psys, (flag & MOD_APPLY_RENDER) != 0);
+ particle_system_update(eval_ctx, md->scene, ob, psys, (flag & MOD_APPLY_RENDER) != 0);
psmd->flag |= eParticleSystemFlag_psys_updated;
}
}
@@ -231,7 +231,6 @@ ModifierTypeInfo modifierType_ParticleSystem = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c
index b85898c07e9..c9070cced7e 100644
--- a/source/blender/modifiers/intern/MOD_remesh.c
+++ b/source/blender/modifiers/intern/MOD_remesh.c
@@ -143,6 +143,7 @@ static void dualcon_add_quad(void *output_v, const int vert_indices[4])
}
static DerivedMesh *applyModifier(ModifierData *md,
+ const struct EvaluationContext *UNUSED(eval_ctx),
Object *UNUSED(ob),
DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
@@ -203,7 +204,9 @@ static DerivedMesh *applyModifier(ModifierData *md,
#else /* !WITH_MOD_REMESH */
-static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
+static DerivedMesh *applyModifier(ModifierData *UNUSED(md),
+ const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *UNUSED(ob),
DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
@@ -231,7 +234,6 @@ ModifierTypeInfo modifierType_Remesh = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 2c3d7f394bb..010bf8bf092 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -46,7 +46,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_library_query.h"
-#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
#include "MOD_modifiertypes.h"
@@ -185,8 +184,8 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
ModifierApplyFlag flag)
{
DerivedMesh *dm = derivedData;
@@ -1118,24 +1117,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
return result;
}
-
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- ScrewModifierData *ltmd = (ScrewModifierData *) md;
-
- if (ltmd->ob_axis) {
- DagNode *curNode = dag_get_node(forest, ltmd->ob_axis);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "Screw Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -1179,7 +1160,6 @@ ModifierTypeInfo modifierType_Screw = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index 97aae733532..822decea423 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -44,8 +44,8 @@
#include "MOD_modifiertypes.h"
-static void deformVerts(ModifierData *UNUSED(md), Object *ob,
- DerivedMesh *UNUSED(derivedData),
+static void deformVerts(ModifierData *UNUSED(md), const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *UNUSED(derivedData),
float (*vertexCos)[3],
int numVerts,
ModifierApplyFlag UNUSED(flag))
@@ -61,7 +61,7 @@ static void deformVerts(ModifierData *UNUSED(md), Object *ob,
}
}
-static void deformMatrices(ModifierData *md, Object *ob, DerivedMesh *derivedData,
+static void deformMatrices(ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], float (*defMats)[3][3], int numVerts)
{
Key *key = BKE_key_from_object(ob);
@@ -80,10 +80,10 @@ static void deformMatrices(ModifierData *md, Object *ob, DerivedMesh *derivedDat
copy_m3_m3(defMats[a], scale);
}
- deformVerts(md, ob, derivedData, vertexCos, numVerts, 0);
+ deformVerts(md, eval_ctx, ob, derivedData, vertexCos, numVerts, 0);
}
-static void deformVertsEM(ModifierData *md, Object *ob,
+static void deformVertsEM(ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob,
struct BMEditMesh *UNUSED(editData),
DerivedMesh *derivedData,
float (*vertexCos)[3],
@@ -92,11 +92,11 @@ static void deformVertsEM(ModifierData *md, Object *ob,
Key *key = BKE_key_from_object(ob);
if (key && key->type == KEY_RELATIVE)
- deformVerts(md, ob, derivedData, vertexCos, numVerts, 0);
+ deformVerts(md, eval_ctx, ob, derivedData, vertexCos, numVerts, 0);
}
-static void deformMatricesEM(ModifierData *UNUSED(md), Object *ob,
- struct BMEditMesh *UNUSED(editData),
+static void deformMatricesEM(ModifierData *UNUSED(md), const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, struct BMEditMesh *UNUSED(editData),
DerivedMesh *UNUSED(derivedData),
float (*vertexCos)[3],
float (*defMats)[3][3],
@@ -138,7 +138,6 @@ ModifierTypeInfo modifierType_ShapeKey = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index a14747bc153..c87fdd321ab 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -45,8 +45,6 @@
#include "BKE_modifier.h"
#include "BKE_shrinkwrap.h"
-#include "depsgraph_private.h"
-
#include "MOD_util.h"
static bool dependsOnNormals(ModifierData *md);
@@ -105,8 +103,8 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
walk(userData, ob, &smd->auxTarget, IDWALK_CB_NOP);
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts,
ModifierApplyFlag flag)
@@ -126,7 +124,8 @@ static void deformVerts(ModifierData *md, Object *ob,
dm->release(dm);
}
-static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *editData, DerivedMesh *derivedData,
+static void deformVertsEM(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob,
+ struct BMEditMesh *editData, DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
@@ -143,23 +142,6 @@ static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *editD
dm->release(dm);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *) md;
-
- if (smd->target)
- dag_add_relation(forest, dag_get_node(forest, smd->target), obNode,
- DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
-
- if (smd->auxTarget)
- dag_add_relation(forest, dag_get_node(forest, smd->auxTarget), obNode,
- DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -209,7 +191,6 @@ ModifierTypeInfo modifierType_Shrinkwrap = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 379eaea5b0c..146e882a6b6 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -44,9 +44,6 @@
#include "BKE_modifier.h"
#include "BKE_deform.h"
-
-#include "depsgraph_private.h"
-
#include "MOD_util.h"
#define BEND_EPS 0.000001f
@@ -293,18 +290,6 @@ static void foreachObjectLink(
walk(userData, ob, &smd->origin, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
-
- if (smd->origin)
- dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier");
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -317,8 +302,8 @@ static void updateDepsgraph(ModifierData *md,
}
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts,
ModifierApplyFlag UNUSED(flag))
@@ -337,8 +322,8 @@ static void deformVerts(ModifierData *md, Object *ob,
dm->release(dm);
}
-static void deformVertsEM(ModifierData *md, Object *ob,
- struct BMEditMesh *editData,
+static void deformVertsEM(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts)
@@ -381,7 +366,6 @@ ModifierTypeInfo modifierType_SimpleDeform = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index ad1e4badd3e..9d1c6913c1c 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -1917,6 +1917,7 @@ static void copyData(ModifierData *md, ModifierData *target)
}
static DerivedMesh *applyModifier(ModifierData *md,
+ const struct EvaluationContext *UNUSED(eval_ctx),
Object *UNUSED(ob),
DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
@@ -1952,7 +1953,6 @@ ModifierTypeInfo modifierType_Skin = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c
index 7f2d9e42fe6..e66afe07841 100644
--- a/source/blender/modifiers/intern/MOD_smoke.c
+++ b/source/blender/modifiers/intern/MOD_smoke.c
@@ -46,13 +46,14 @@
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_smoke.h"
-#include "depsgraph_private.h"
+#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "MOD_modifiertypes.h"
@@ -101,8 +102,8 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *dm,
+static DerivedMesh *applyModifier(ModifierData *md, const EvaluationContext *eval_ctx,
+ Object *ob, DerivedMesh *dm,
ModifierApplyFlag flag)
{
SmokeModifierData *smd = (SmokeModifierData *) md;
@@ -110,7 +111,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (flag & MOD_APPLY_ORCO)
return dm;
- return smokeModifier_do(smd, md->scene, ob, dm);
+ return smokeModifier_do(smd, eval_ctx, md->scene, ob, dm);
}
static bool dependsOnTime(ModifierData *UNUSED(md))
@@ -130,28 +131,6 @@ static bool is_coll_cb(Object *UNUSED(ob), ModifierData *md)
return (smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll;
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *scene, struct Object *ob,
- DagNode *obNode)
-{
- SmokeModifierData *smd = (SmokeModifierData *) md;
-
- if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- /* Actual code uses get_collisionobjects */
-#ifdef WITH_LEGACY_DEPSGRAPH
- dag_add_collision_relations(forest, scene, ob, obNode, smd->domain->fluid_group, ob->lay|scene->lay, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow");
- dag_add_collision_relations(forest, scene, ob, obNode, smd->domain->coll_group, ob->lay|scene->lay, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll");
- dag_add_forcefield_relations(forest, scene, ob, obNode, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field");
-#else
- (void)forest;
- (void)scene;
- (void)ob;
- (void)obNode;
-#endif
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -162,8 +141,8 @@ static void updateDepsgraph(ModifierData *md,
if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
/* Actual code uses get_collisionobjects */
- DEG_add_collision_relations(node, scene, ob, smd->domain->fluid_group, ob->lay|scene->lay, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow");
- DEG_add_collision_relations(node, scene, ob, smd->domain->coll_group, ob->lay|scene->lay, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll");
+ DEG_add_collision_relations(node, scene, ob, smd->domain->fluid_group, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow");
+ DEG_add_collision_relations(node, scene, ob, smd->domain->coll_group, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll");
DEG_add_forcefield_relations(node, scene, ob, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field");
}
@@ -209,7 +188,6 @@ ModifierTypeInfo modifierType_Smoke = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index d45c8528510..be55030e18a 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -215,7 +215,7 @@ static void smoothModifier_do(
MEM_freeN(uctmp);
}
-static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *dm = get_dm(ob, NULL, derivedData, NULL, false, false);
@@ -228,7 +228,7 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct BMEditMesh *editData,
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, false, false);
@@ -261,7 +261,6 @@ ModifierTypeInfo modifierType_Smooth = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c
index a0bbe5da04a..020dd3da6a5 100644
--- a/source/blender/modifiers/intern/MOD_softbody.c
+++ b/source/blender/modifiers/intern/MOD_softbody.c
@@ -40,21 +40,22 @@
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_layer.h"
#include "BKE_particle.h"
#include "BKE_softbody.h"
-#include "depsgraph_private.h"
+#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "MOD_modifiertypes.h"
-static void deformVerts(ModifierData *md, Object *ob,
+static void deformVerts(ModifierData *md, const EvaluationContext *eval_ctx, Object *ob,
DerivedMesh *UNUSED(derivedData),
float (*vertexCos)[3],
int numVerts,
ModifierApplyFlag UNUSED(flag))
{
- sbObjectStep(md->scene, ob, (float)md->scene->r.cfra, vertexCos, numVerts);
+ sbObjectStep(eval_ctx, md->scene, ob, (float)md->scene->r.cfra, vertexCos, numVerts);
}
static bool dependsOnTime(ModifierData *UNUSED(md))
@@ -62,25 +63,6 @@ static bool dependsOnTime(ModifierData *UNUSED(md))
return true;
}
-static void updateDepgraph(ModifierData *UNUSED(md), DagForest *forest,
- struct Main *UNUSED(bmain),
- Scene *scene, Object *ob, DagNode *obNode)
-{
- if (ob->soft) {
-#ifdef WITH_LEGACY_DEPSGRAPH
- /* Actual code uses ccd_build_deflector_hash */
- dag_add_collision_relations(forest, scene, ob, obNode, ob->soft->collision_group, ob->lay, eModifierType_Collision, NULL, false, "Softbody Collision");
-
- dag_add_forcefield_relations(forest, scene, ob, obNode, ob->soft->effector_weights, true, 0, "Softbody Field");
-#else
- (void)forest;
- (void)scene;
- (void)ob;
- (void)obNode;
-#endif
- }
-}
-
static void updateDepsgraph(ModifierData *UNUSED(md),
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -89,7 +71,7 @@ static void updateDepsgraph(ModifierData *UNUSED(md),
{
if (ob->soft) {
/* Actual code uses ccd_build_deflector_hash */
- DEG_add_collision_relations(node, scene, ob, ob->soft->collision_group, ob->lay, eModifierType_Collision, NULL, false, "Softbody Collision");
+ DEG_add_collision_relations(node, scene, ob, ob->soft->collision_group, eModifierType_Collision, NULL, false, "Softbody Collision");
DEG_add_forcefield_relations(node, scene, ob, ob->soft->effector_weights, true, 0, "Softbody Field");
}
@@ -116,7 +98,6 @@ ModifierTypeInfo modifierType_Softbody = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index e96771e0665..14b29855728 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -205,8 +205,8 @@ BLI_INLINE void madd_v3v3short_fl(float r[3], const short a[3], const float f)
}
static DerivedMesh *applyModifier(
- ModifierData *md, Object *ob,
- DerivedMesh *dm,
+ ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *result;
@@ -973,7 +973,6 @@ ModifierTypeInfo modifierType_Solidify = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index 8711384e1ee..a09923d6dfe 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -46,10 +46,12 @@
#include "BKE_cdderivedmesh.h"
-#include "BKE_depsgraph.h"
#include "BKE_scene.h"
#include "BKE_subsurf.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "MOD_modifiertypes.h"
#include "intern/CCGSubSurf.h"
@@ -96,8 +98,8 @@ static bool isDisabled(ModifierData *md, int useRenderParams)
return get_render_subsurf_level(&md->scene->r, levels, useRenderParams != 0) == 0;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static DerivedMesh *applyModifier(ModifierData *md, const EvaluationContext *eval_ctx,
+ Object *ob, DerivedMesh *derivedData,
ModifierApplyFlag flag)
{
SubsurfModifierData *smd = (SubsurfModifierData *) md;
@@ -133,7 +135,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
else if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) != 0) {
modifier_setError(md, "OpenSubdiv is not supported in paint modes");
}
- else if ((DAG_get_eval_flags_for_object(md->scene, ob) & DAG_EVAL_NEED_CPU) == 0) {
+ else if ((DEG_get_eval_flags_for_id(eval_ctx->depsgraph, &ob->id) & DAG_EVAL_NEED_CPU) == 0) {
subsurf_flags |= SUBSURF_USE_GPU_BACKEND;
do_cddm_convert = false;
}
@@ -146,19 +148,25 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
result = subsurf_make_derived_from_derived(derivedData, smd, NULL, subsurf_flags);
result->cd_flag = derivedData->cd_flag;
- if (do_cddm_convert) {
+ {
DerivedMesh *cddm = CDDM_copy(result);
result->release(result);
result = cddm;
}
+#ifndef WITH_OPESUBDIV
+ (void) do_cddm_convert;
+ UNUSED_VARS(eval_ctx);
+#endif
+
return result;
}
-static DerivedMesh *applyModifierEM(ModifierData *md, Object *UNUSED(ob),
- struct BMEditMesh *UNUSED(editData),
- DerivedMesh *derivedData,
- ModifierApplyFlag flag)
+static DerivedMesh *applyModifierEM(
+ ModifierData *md, const EvaluationContext *UNUSED(eval_ctx),
+ Object *UNUSED(ob), struct BMEditMesh *UNUSED(editData),
+ DerivedMesh *derivedData,
+ ModifierApplyFlag flag)
{
SubsurfModifierData *smd = (SubsurfModifierData *) md;
DerivedMesh *result;
@@ -211,7 +219,6 @@ ModifierTypeInfo modifierType_Subsurf = {
/* requiredDataMask */ NULL,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index e5b0f9c0001..c408b4fbd63 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -85,8 +85,8 @@ static bool dependsOnTime(ModifierData *UNUSED(md))
return true;
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int UNUSED(numVerts),
ModifierApplyFlag UNUSED(flag))
@@ -186,7 +186,6 @@ ModifierTypeInfo modifierType_Surface = {
/* requiredDataMask */ NULL,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index b692137b604..b623293ed5c 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -11,8 +11,6 @@
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "depsgraph_private.h"
-
#include "MEM_guardedalloc.h"
#include "MOD_util.h"
@@ -170,21 +168,6 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
walk(userData, ob, &smd->target, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
-
- if (smd->target) {
- DagNode *curNode = dag_get_node(forest, smd->target);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA, "Surface Deform Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -1179,16 +1162,16 @@ static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], un
}
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *UNUSED(derivedData),
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *UNUSED(derivedData),
float (*vertexCos)[3], int numVerts,
ModifierApplyFlag UNUSED(flag))
{
surfacedeformModifier_do(md, vertexCos, numVerts, ob);
}
-static void deformVertsEM(ModifierData *md, Object *ob,
- struct BMEditMesh *UNUSED(editData),
+static void deformVertsEM(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, struct BMEditMesh *UNUSED(editData),
DerivedMesh *UNUSED(derivedData),
float (*vertexCos)[3], int numVerts)
{
@@ -1221,7 +1204,6 @@ ModifierTypeInfo modifierType_SurfaceDeform = {
/* requiredDataMask */ NULL,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c
index b057d6d5a86..5dd7e3dfda4 100644
--- a/source/blender/modifiers/intern/MOD_triangulate.c
+++ b/source/blender/modifiers/intern/MOD_triangulate.c
@@ -85,6 +85,7 @@ static void copyData(ModifierData *md, ModifierData *target)
}
static DerivedMesh *applyModifier(ModifierData *md,
+ const struct EvaluationContext *UNUSED(eval_ctx),
Object *UNUSED(ob),
DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
@@ -120,7 +121,6 @@ ModifierTypeInfo modifierType_Triangulate = {
/* requiredDataMask */ NULL, //requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 01468c1143a..c9a842621b6 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -47,6 +47,7 @@
#include "BKE_camera.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
+#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_DerivedMesh.h"
@@ -54,14 +55,13 @@
#include "MEM_guardedalloc.h"
-#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
static void initData(ModifierData *md)
{
UVProjectModifierData *umd = (UVProjectModifierData *) md;
- umd->flags = 0;
+
umd->num_projectors = 1;
umd->aspectx = umd->aspecty = 1.0f;
umd->scalex = umd->scaley = 1.0f;
@@ -84,7 +84,7 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(
CustomDataMask dataMask = 0;
/* ask for UV coordinates */
- dataMask |= CD_MLOOPUV | CD_MTEXPOLY;
+ dataMask |= CD_MLOOPUV;
return dataMask;
}
@@ -109,25 +109,6 @@ static void foreachIDLink(ModifierData *md, Object *ob,
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- UVProjectModifierData *umd = (UVProjectModifierData *) md;
- int i;
-
- for (i = 0; i < umd->num_projectors; ++i) {
- if (umd->projectors[i]) {
- DagNode *curNode = dag_get_node(forest, umd->projectors[i]);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "UV Project Modifier");
- }
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -155,12 +136,10 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
{
float (*coords)[3], (*co)[3];
MLoopUV *mloop_uv;
- MTexPoly *mtexpoly, *mt = NULL;
int i, numVerts, numPolys, numLoops;
Image *image = umd->image;
MPoly *mpoly, *mp;
MLoop *mloop;
- const bool override_image = (umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0;
Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
int num_projectors = 0;
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
@@ -245,10 +224,6 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
mloop_uv = CustomData_duplicate_referenced_layer_named(&dm->loopData,
CD_MLOOPUV, uvname, numLoops);
- /* can be NULL */
- mt = mtexpoly = CustomData_duplicate_referenced_layer_named(&dm->polyData,
- CD_MTEXPOLY, uvname, numPolys);
-
numVerts = dm->getNumVerts(dm);
coords = MEM_mallocN(sizeof(*coords) * numVerts,
@@ -267,9 +242,14 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
mpoly = dm->getPolyArray(dm);
mloop = dm->getLoopArray(dm);
+ Image **ob_image_array = NULL;
+ if (image) {
+ ob_image_array = BKE_object_material_edit_image_get_array(ob);
+ }
+
/* apply coords as UVs, and apply image if tfaces are new */
- for (i = 0, mp = mpoly; i < numPolys; ++i, ++mp, ++mt) {
- if (override_image || !image || (mtexpoly == NULL || mt->tpage == image)) {
+ for (i = 0, mp = mpoly; i < numPolys; ++i, ++mp) {
+ if (!image || (mp->mat_nr < ob->totcol ? ob_image_array[mp->mat_nr] : NULL) == image) {
if (num_projectors == 1) {
if (projectors[0].uci) {
unsigned int fidx = mp->totloop - 1;
@@ -332,13 +312,13 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
}
}
}
-
- if (override_image && mtexpoly) {
- mt->tpage = image;
- }
}
MEM_freeN(coords);
+
+ if (ob_image_array) {
+ MEM_freeN(ob_image_array);
+ }
if (free_uci) {
int j;
@@ -355,8 +335,8 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
return dm;
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *result;
@@ -389,7 +369,6 @@ ModifierTypeInfo modifierType_UVProject = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index b3fc3842635..3773eed26dc 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -40,8 +40,6 @@
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "depsgraph_private.h"
-
#include "MOD_util.h"
@@ -145,8 +143,8 @@ static void uv_warp_compute(void *userdata, const int i)
}
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *dm,
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob, DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
{
UVWarpModifierData *umd = (UVWarpModifierData *) md;
@@ -225,34 +223,9 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
walk(userData, ob, &umd->object_src, IDWALK_CB_NOP);
}
-static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode,
- Object *obj, const char *bonename)
-{
- if (obj) {
- DagNode *curNode = dag_get_node(forest, obj);
-
- if (bonename[0])
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "UVWarp Modifier");
- else
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "UVWarp Modifier");
- }
-}
-
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- UVWarpModifierData *umd = (UVWarpModifierData *) md;
-
- uv_warp_deps_object_bone(forest, obNode, umd->object_src, umd->bone_src);
- uv_warp_deps_object_bone(forest, obNode, umd->object_dst, umd->bone_dst);
-}
-
-static void uv_warp_deps_object_bone_new(struct DepsNodeHandle *node,
- Object *object,
- const char *bonename)
+static void uv_warp_deps_object_bone(struct DepsNodeHandle *node,
+ Object *object,
+ const char *bonename)
{
if (object != NULL) {
if (bonename[0])
@@ -270,8 +243,8 @@ static void updateDepsgraph(ModifierData *md,
{
UVWarpModifierData *umd = (UVWarpModifierData *) md;
- uv_warp_deps_object_bone_new(node, umd->object_src, umd->bone_src);
- uv_warp_deps_object_bone_new(node, umd->object_dst, umd->bone_dst);
+ uv_warp_deps_object_bone(node, umd->object_src, umd->bone_src);
+ uv_warp_deps_object_bone(node, umd->object_dst, umd->bone_dst);
}
ModifierTypeInfo modifierType_UVWarp = {
@@ -293,7 +266,6 @@ ModifierTypeInfo modifierType_UVWarp = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index b340356467a..566ee5b2d24 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -42,8 +42,6 @@
#include "BKE_texture.h"
#include "BKE_colortools.h"
-#include "depsgraph_private.h"
-
#include "RE_shader_ext.h"
#include "MOD_util.h"
@@ -139,27 +137,6 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- WarpModifierData *wmd = (WarpModifierData *) md;
-
- if (wmd->object_from && wmd->object_to) {
- DagNode *fromNode = dag_get_node(forest, wmd->object_from);
- DagNode *toNode = dag_get_node(forest, wmd->object_to);
-
- dag_add_relation(forest, fromNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier1");
- dag_add_relation(forest, toNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier2");
- }
-
- if ((wmd->texmapping == MOD_DISP_MAP_OBJECT) && wmd->map_object) {
- DagNode *curNode = dag_get_node(forest, wmd->map_object);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier3");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -336,7 +313,7 @@ static int warp_needs_dm(WarpModifierData *wmd)
return wmd->texture || wmd->defgrp_name[0];
}
-static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *dm = NULL;
@@ -353,7 +330,7 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
}
}
-static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *em,
+static void deformVertsEM(ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob, struct BMEditMesh *em,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
@@ -364,7 +341,7 @@ static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *em,
dm = CDDM_from_editbmesh(em, false, false);
}
- deformVerts(md, ob, dm, vertexCos, numVerts, 0);
+ deformVerts(md, eval_ctx, ob, dm, vertexCos, numVerts, 0);
if (use_dm) {
if (!derivedData) dm->release(dm);
@@ -391,7 +368,6 @@ ModifierTypeInfo modifierType_Warp = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index b4990c5250e..c408f244afd 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -49,14 +49,14 @@
#include "BKE_scene.h"
#include "BKE_texture.h"
-#include "depsgraph_private.h"
-
#include "MEM_guardedalloc.h"
#include "RE_shader_ext.h"
#include "MOD_modifiertypes.h"
#include "MOD_util.h"
+#include "DEG_depsgraph.h"
+
static void initData(ModifierData *md)
{
WaveModifierData *wmd = (WaveModifierData *) md; // whadya know, moved here from Iraq
@@ -127,29 +127,6 @@ static void foreachTexLink(ModifierData *md, Object *ob,
walk(userData, ob, md, "texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- WaveModifierData *wmd = (WaveModifierData *) md;
-
- if (wmd->objectcenter) {
- DagNode *curNode = dag_get_node(forest, wmd->objectcenter);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
- "Wave Modifier");
- }
-
- if (wmd->map_object) {
- DagNode *curNode = dag_get_node(forest, wmd->map_object);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
- "Wave Modifer");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -182,15 +159,16 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-static void waveModifier_do(WaveModifierData *md,
- Scene *scene, Object *ob, DerivedMesh *dm,
+static void waveModifier_do(WaveModifierData *md,
+ const EvaluationContext *eval_ctx,
+ Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
WaveModifierData *wmd = (WaveModifierData *) md;
MVert *mvert = NULL;
MDeformVert *dvert;
int defgrp_index;
- float ctime = BKE_scene_frame_get(scene);
+ float ctime = eval_ctx->ctime;
float minfac = (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
float lifefac = wmd->height;
float (*tex_co)[3] = NULL;
@@ -335,8 +313,8 @@ static void waveModifier_do(WaveModifierData *md,
if (wmd->texture) MEM_freeN(tex_co);
}
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
+static void deformVerts(ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts,
ModifierApplyFlag UNUSED(flag))
@@ -349,14 +327,15 @@ static void deformVerts(ModifierData *md, Object *ob,
else if (wmd->texture || wmd->defgrp_name[0])
dm = get_dm(ob, NULL, dm, NULL, false, false);
- waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
+ waveModifier_do(wmd, eval_ctx, ob, dm, vertexCos, numVerts);
if (dm != derivedData)
dm->release(dm);
}
static void deformVertsEM(
- ModifierData *md, Object *ob, struct BMEditMesh *editData,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = derivedData;
@@ -367,7 +346,7 @@ static void deformVertsEM(
else if (wmd->texture || wmd->defgrp_name[0])
dm = get_dm(ob, editData, dm, NULL, false, false);
- waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
+ waveModifier_do(wmd, eval_ctx, ob, dm, vertexCos, numVerts);
if (dm != derivedData)
dm->release(dm);
@@ -393,7 +372,6 @@ ModifierTypeInfo modifierType_Wave = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index 13a97c1c13d..dbdaafaa5a7 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -46,7 +46,6 @@
#include "BKE_modifier.h"
#include "BKE_texture.h" /* Texture masking. */
-#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
#include "MEM_guardedalloc.h"
@@ -141,26 +140,6 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
- DagNode *curNode;
-
- if (wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
- curNode = dag_get_node(forest, wmd->mask_tex_map_obj);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGEdit Modifier");
- }
-
- if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL)
- dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGEdit Modifier");
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -183,7 +162,10 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
return (wmd->defgrp_name[0] == '\0');
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
+static DerivedMesh *applyModifier(ModifierData *md,
+ const struct EvaluationContext *UNUSED(eval_ctx),
+ Object *ob,
+ DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
@@ -304,7 +286,6 @@ ModifierTypeInfo modifierType_WeightVGEdit = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 392f42040b0..5f30d4ca72a 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -43,7 +43,6 @@
#include "BKE_modifier.h"
#include "BKE_texture.h" /* Texture masking. */
-#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
#include "MEM_guardedalloc.h"
@@ -190,26 +189,6 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
- DagNode *curNode;
-
- if (wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
- curNode = dag_get_node(forest, wmd->mask_tex_map_obj);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGMix Modifier");
- }
-
- if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL)
- dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGMix Modifier");
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -234,8 +213,8 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
return (wmd->defgrp_name_a[0] == '\0');
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
- ModifierApplyFlag UNUSED(flag))
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob,
+ DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag))
{
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
DerivedMesh *dm = derivedData;
@@ -436,7 +415,6 @@ ModifierTypeInfo modifierType_WeightVGMix = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 2ca380ba5c2..c8bbbfe44b2 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -47,7 +47,6 @@
#include "BKE_modifier.h"
#include "BKE_texture.h" /* Texture masking. */
-#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
#include "MEM_guardedalloc.h"
@@ -341,32 +340,6 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
- DagNode *curNode;
-
- if (wmd->proximity_ob_target) {
- curNode = dag_get_node(forest, wmd->proximity_ob_target);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGProximity Modifier");
- }
-
- if (wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
- curNode = dag_get_node(forest, wmd->mask_tex_map_obj);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGProximity Modifier");
- }
-
- if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL)
- dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGProximity Modifier");
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -397,8 +370,8 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
return (wmd->proximity_ob_target == NULL);
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
- ModifierApplyFlag UNUSED(flag))
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob,
+ DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag))
{
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
DerivedMesh *dm = derivedData;
@@ -615,7 +588,6 @@ ModifierTypeInfo modifierType_WeightVGProximity = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c
index adadd4834d4..6fc1907ba0a 100644
--- a/source/blender/modifiers/intern/MOD_wireframe.c
+++ b/source/blender/modifiers/intern/MOD_wireframe.c
@@ -107,7 +107,8 @@ static DerivedMesh *WireframeModifier_do(WireframeModifierData *wmd, Object *ob,
}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, ModifierApplyFlag UNUSED(flag))
+static DerivedMesh *applyModifier(ModifierData *md, const struct EvaluationContext *UNUSED(eval_ctx), Object *ob,
+ DerivedMesh *dm, ModifierApplyFlag UNUSED(flag))
{
return WireframeModifier_do((WireframeModifierData *)md, ob, dm);
}
@@ -132,7 +133,6 @@ ModifierTypeInfo modifierType_Wireframe = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 21f9afec903..a6e04510b03 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -184,6 +184,7 @@ set(SRC
shader/nodes/node_shader_normal_map.c
shader/nodes/node_shader_object_info.c
shader/nodes/node_shader_hair_info.c
+ shader/nodes/node_shader_eevee_specular.c
shader/nodes/node_shader_output_lamp.c
shader/nodes/node_shader_output_material.c
shader/nodes/node_shader_output_world.c
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index a5c2e604f46..dfcb83b873a 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -140,7 +140,7 @@ void register_node_type_cmp_planetrackdeform(void);
void register_node_type_cmp_cornerpin(void);
void node_cmp_rlayers_outputs(struct bNodeTree *ntree, struct bNode *node);
-void node_cmp_rlayers_register_pass(struct bNodeTree *ntree, struct bNode *node, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type);
+void node_cmp_rlayers_register_pass(struct bNodeTree *ntree, struct bNode *node, struct Scene *scene, struct ViewLayer *view_layer, const char *name, int type);
const char *node_cmp_rlayers_sock_to_pass(int sock_index);
#endif
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index f7d36e3dbef..62a92e8d084 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -118,9 +118,12 @@ void register_node_type_sh_mix_shader(void);
void register_node_type_sh_add_shader(void);
void register_node_type_sh_uvmap(void);
void register_node_type_sh_uvalongstroke(void);
+void register_node_type_sh_eevee_metallic(void);
+void register_node_type_sh_eevee_specular(void);
void register_node_type_sh_output_lamp(void);
void register_node_type_sh_output_material(void);
+void register_node_type_sh_output_eevee_material(void);
void register_node_type_sh_output_world(void);
void register_node_type_sh_output_linestyle(void);
diff --git a/source/blender/nodes/NOD_socket.h b/source/blender/nodes/NOD_socket.h
index 5c8875593e7..e311adc45eb 100644
--- a/source/blender/nodes/NOD_socket.h
+++ b/source/blender/nodes/NOD_socket.h
@@ -49,7 +49,7 @@ struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struc
void node_verify_socket_templates(struct bNodeTree *ntree, struct bNode *node);
void node_socket_init_default_value(struct bNodeSocket *sock);
-void node_socket_copy_default_value(struct bNodeSocket *to, struct bNodeSocket *from);
+void node_socket_copy_default_value(struct bNodeSocket *to, const struct bNodeSocket *from);
void register_standard_node_socket_types(void);
#endif
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 13844298c5a..a18ee154af8 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -67,6 +67,7 @@ DefNode( ShaderNode, SH_NODE_COMBRGB, 0, "COMBR
DefNode( ShaderNode, SH_NODE_HUE_SAT, 0, "HUE_SAT", HueSaturation, "Hue/Saturation", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_MATERIAL, def_sh_output, "OUTPUT_MATERIAL", OutputMaterial, "Material Output", "" )
+DefNode( ShaderNode, SH_NODE_EEVEE_SPECULAR, 0, "EEVEE_SPECULAR", EeveeSpecular, "Specular", "")
DefNode( ShaderNode, SH_NODE_OUTPUT_LAMP, def_sh_output, "OUTPUT_LAMP", OutputLamp, "Lamp Output", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_WORLD, def_sh_output, "OUTPUT_WORLD", OutputWorld, "World Output", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_LINESTYLE, def_sh_output_linestyle,"OUTPUT_LINESTYLE", OutputLineStyle, "Line Style Output", "" )
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index 36778a18f77..8cb25d9167f 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -65,7 +65,7 @@ static void composite_get_from_context(const bContext *C, bNodeTreeType *UNUSED(
*r_ntree = scene->nodetree;
}
-static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
+static void foreach_nodeclass(ViewRender *UNUSED(view_render), void *calldata, bNodeClassCallback func)
{
func(calldata, NODE_CLASS_INPUT, N_("Input"));
func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
@@ -261,7 +261,7 @@ void ntreeCompositUpdateRLayers(bNodeTree *ntree)
}
-void ntreeCompositRegisterPass(bNodeTree *ntree, Scene *scene, SceneRenderLayer *srl, const char *name, int type)
+void ntreeCompositRegisterPass(bNodeTree *ntree, Scene *scene, ViewLayer *view_layer, const char *name, int type)
{
bNode *node;
@@ -269,7 +269,7 @@ void ntreeCompositRegisterPass(bNodeTree *ntree, Scene *scene, SceneRenderLayer
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == CMP_NODE_R_LAYERS)
- node_cmp_rlayers_register_pass(ntree, node, scene, srl, name, type);
+ node_cmp_rlayers_register_pass(ntree, node, scene, view_layer, name, type);
}
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index a95c3233132..bd7c4df317f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -41,6 +41,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_scene.h"
/* **************** IMAGE (and RenderResult, multilayer image) ******************** */
@@ -190,16 +191,16 @@ typedef struct RLayerUpdateData {
int prev_index;
} RLayerUpdateData;
-void node_cmp_rlayers_register_pass(bNodeTree *ntree, bNode *node, Scene *scene, SceneRenderLayer *srl, const char *name, int type)
+void node_cmp_rlayers_register_pass(bNodeTree *ntree, bNode *node, Scene *scene, ViewLayer *view_layer, const char *name, int type)
{
RLayerUpdateData *data = node->storage;
- if (scene == NULL || srl == NULL || data == NULL || node->id != (ID *)scene) {
+ if (scene == NULL || view_layer == NULL || data == NULL || node->id != (ID *)scene) {
return;
}
- SceneRenderLayer *node_srl = BLI_findlink(&scene->r.layers, node->custom1);
- if (node_srl != srl) {
+ ViewLayer *node_view_layer = BLI_findlink(&scene->view_layers, node->custom1);
+ if (node_view_layer != view_layer) {
return;
}
@@ -218,17 +219,17 @@ static void cmp_node_rlayer_create_outputs(bNodeTree *ntree, bNode *node, LinkNo
Scene *scene = (Scene *)node->id;
if (scene) {
- RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
+ RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
if (engine_type && engine_type->update_render_passes) {
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, node->custom1);
- if (srl) {
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, node->custom1);
+ if (view_layer) {
RLayerUpdateData *data = MEM_mallocN(sizeof(RLayerUpdateData), "render layer update data");
data->available_sockets = available_sockets;
data->prev_index = -1;
node->storage = data;
RenderEngine *engine = RE_engine_create(engine_type);
- engine_type->update_render_passes(engine, scene, srl);
+ engine_type->update_render_passes(engine, scene, view_layer);
RE_engine_free(engine);
MEM_freeN(data);
diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c
index 5b5eadc1a99..382492707ce 100644
--- a/source/blender/nodes/intern/node_socket.c
+++ b/source/blender/nodes/intern/node_socket.c
@@ -268,7 +268,7 @@ void node_socket_init_default_value(bNodeSocket *sock)
}
}
-void node_socket_copy_default_value(bNodeSocket *to, bNodeSocket *from)
+void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from)
{
/* sanity check */
if (to->type != from->type)
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index b4cdb158526..bd22a2be647 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -39,6 +39,7 @@
#include "DNA_space_types.h"
#include "DNA_world_types.h"
#include "DNA_linestyle_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_listbase.h"
#include "BLI_threads.h"
@@ -67,22 +68,29 @@
static int shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
{
Scene *scene = CTX_data_scene(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ ViewRender *view_render = BKE_viewrender_get(scene, workspace);
+ const char *engine_id = view_render->engine_id;
+
/* allow empty engine string too, this is from older versions that didn't have registerable engines yet */
- return (scene->r.engine[0] == '\0' ||
- STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER) ||
- STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME) ||
- STREQ(scene->r.engine, RE_engine_id_CYCLES) ||
- !BKE_scene_use_shading_nodes_custom(scene));
+ return (engine_id[0] == '\0' ||
+ STREQ(engine_id, RE_engine_id_BLENDER_RENDER) ||
+ STREQ(engine_id, RE_engine_id_BLENDER_GAME) ||
+ STREQ(engine_id, RE_engine_id_CYCLES) ||
+ !BKE_viewrender_use_shading_nodes_custom(view_render));
}
static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
{
SpaceNode *snode = CTX_wm_space_node(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = OBACT;
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ ViewRender *view_render = BKE_viewrender_get(scene, workspace);
if ((snode->shaderfrom == SNODE_SHADER_OBJECT) ||
- (BKE_scene_use_new_shading_nodes(scene) == false))
+ (BKE_viewrender_use_new_shading_nodes(view_render) == false))
{
if (ob) {
*r_from = &ob->id;
@@ -118,12 +126,12 @@ static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(tre
}
}
-static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback func)
+static void foreach_nodeclass(ViewRender *view_render, void *calldata, bNodeClassCallback func)
{
func(calldata, NODE_CLASS_INPUT, N_("Input"));
func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
- if (BKE_scene_use_new_shading_nodes(scene)) {
+ if (BKE_viewrender_use_new_shading_nodes(view_render)) {
func(calldata, NODE_CLASS_SHADER, N_("Shader"));
func(calldata, NODE_CLASS_TEXTURE, N_("Texture"));
}
@@ -213,6 +221,9 @@ static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
* render engines works but it's how the GPU shader compilation works. This we
* can change in the future and make it a generic function, but for now it stays
* private here.
+ *
+ * It also does not yet take into account render engine specific output nodes,
+ * it should give priority to e.g. the Eevee material output node for Eevee.
*/
static bNode *ntree_shader_output_node(bNodeTree *ntree)
{
@@ -430,7 +441,7 @@ static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
static void ntree_shader_relink_displacement(bNodeTree *ntree,
short compatibility)
{
- if (compatibility != NODE_NEW_SHADING) {
+ if ((compatibility & NODE_NEW_SHADING) == 0) {
/* We can only deal with new shading system here. */
return;
}
@@ -476,6 +487,112 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree,
ntreeUpdateTree(G.main, ntree);
}
+static bool ntree_tag_ssr_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata, const bool UNUSED(reversed))
+{
+ switch (fromnode->type) {
+ case SH_NODE_BSDF_ANISOTROPIC:
+ case SH_NODE_EEVEE_SPECULAR:
+ case SH_NODE_BSDF_PRINCIPLED:
+ case SH_NODE_BSDF_GLOSSY:
+ case SH_NODE_BSDF_GLASS:
+ fromnode->ssr_id = (*(float *)userdata);
+ (*(float *)userdata) += 1;
+ break;
+ default:
+ /* We could return false here but since we (will)
+ * allow the use of Closure as RGBA, we can have
+ * Bsdf nodes linked to other Bsdf nodes. */
+ break;
+ }
+
+ return true;
+}
+
+/* EEVEE: Scan the ntree to set the Screen Space Reflection
+ * layer id of every specular node.
+ */
+static void ntree_shader_tag_ssr_node(bNodeTree *ntree, short compatibility)
+{
+ if ((compatibility & NODE_NEWER_SHADING) == 0) {
+ /* We can only deal with new shading system here. */
+ return;
+ }
+
+ bNode *output_node = ntree_shader_output_node(ntree);
+ if (output_node == NULL) {
+ return;
+ }
+ /* Make sure sockets links pointers are correct. */
+ ntreeUpdateTree(G.main, ntree);
+
+ float lobe_id = 1;
+ nodeChainIter(ntree, output_node, ntree_tag_ssr_bsdf_cb, &lobe_id, true);
+}
+
+static bool ntree_tag_sss_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata, const bool UNUSED(reversed))
+{
+ switch (fromnode->type) {
+ case SH_NODE_BSDF_PRINCIPLED:
+ case SH_NODE_SUBSURFACE_SCATTERING:
+ fromnode->sss_id = (*(float *)userdata);
+ (*(float *)userdata) += 1;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+/* EEVEE: Scan the ntree to set the Subsurface Scattering id of every SSS node.
+ */
+static void ntree_shader_tag_sss_node(bNodeTree *ntree, short compatibility)
+{
+ if ((compatibility & NODE_NEWER_SHADING) == 0) {
+ /* We can only deal with new shading system here. */
+ return;
+ }
+
+ bNode *output_node = ntree_shader_output_node(ntree);
+ if (output_node == NULL) {
+ return;
+ }
+ /* Make sure sockets links pointers are correct. */
+ ntreeUpdateTree(G.main, ntree);
+
+ float sss_id = 1;
+ nodeChainIter(ntree, output_node, ntree_tag_sss_bsdf_cb, &sss_id, true);
+}
+
+/* EEVEE: Find which material domain are used (volume, surface ...).
+ */
+void ntreeGPUMaterialDomain(bNodeTree *ntree, bool *has_surface_output, bool *has_volume_output)
+{
+ /* localize tree to create links for reroute and mute */
+ bNodeTree *localtree = ntreeLocalize(ntree);
+
+ struct bNode *output = ntree_shader_output_node(localtree);
+
+ *has_surface_output = false;
+ *has_volume_output = false;
+
+ if (output != NULL) {
+ bNodeSocket *surface_sock = ntree_shader_node_find_input(output, "Surface");
+ bNodeSocket *volume_sock = ntree_shader_node_find_input(output, "Volume");
+
+ if (surface_sock != NULL) {
+ *has_surface_output = (nodeCountSocketLinks(localtree, surface_sock) > 0);
+ }
+
+ if (volume_sock != NULL) {
+ *has_volume_output = (nodeCountSocketLinks(localtree, volume_sock) > 0);
+ }
+ }
+
+ ntreeFreeTree(localtree);
+ MEM_freeN(localtree);
+}
+
void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat, short compatibility)
{
/* localize tree to create links for reroute and mute */
@@ -487,6 +604,9 @@ void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat, short compatibili
*/
ntree_shader_relink_displacement(localtree, compatibility);
+ ntree_shader_tag_ssr_node(localtree, compatibility);
+ ntree_shader_tag_sss_node(localtree, compatibility);
+
exec = ntreeShaderBeginExecTree(localtree);
ntreeExecGPUNodes(exec, mat, 1, compatibility);
ntreeShaderEndExecTree(exec);
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 5bc97f13b41..8559765e315 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -163,7 +163,7 @@ void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns)
else if (type == SOCK_RGBA)
gs->type = GPU_VEC4;
else if (type == SOCK_SHADER)
- gs->type = GPU_VEC4;
+ gs->type = GPU_CLOSURE;
else
gs->type = GPU_NONE;
diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index a902ede8aa7..2363addb56a 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -77,7 +77,9 @@
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
+#include "GPU_uniformbuffer.h"
int sh_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
diff --git a/source/blender/nodes/shader/nodes/node_shader_add_shader.c b/source/blender/nodes/shader/nodes/node_shader_add_shader.c
index 1edac62438e..d3bb8fccf71 100644
--- a/source/blender/nodes/shader/nodes/node_shader_add_shader.c
+++ b/source/blender/nodes/shader/nodes/node_shader_add_shader.c
@@ -40,9 +40,9 @@ static bNodeSocketTemplate sh_node_add_shader_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_add_shader(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_add_shader(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_add_shader", in, out);
+ return GPU_stack_link(mat, node, "node_add_shader", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
index 878f8562619..cb4335ca9a7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
+++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
@@ -39,9 +39,9 @@ static bNodeSocketTemplate sh_node_ambient_occlusion_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL));
+ return GPU_stack_link(mat, node, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.c b/source/blender/nodes/shader/nodes/node_shader_attribute.c
index 0a69593cf07..5f3699e52eb 100644
--- a/source/blender/nodes/shader/nodes/node_shader_attribute.c
+++ b/source/blender/nodes/shader/nodes/node_shader_attribute.c
@@ -45,9 +45,24 @@ static void node_shader_init_attribute(bNodeTree *UNUSED(ntree), bNode *node)
static int node_shader_gpu_attribute(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
NodeShaderAttribute *attr = node->storage;
- GPUNodeLink *cd_attr = GPU_attribute(CD_AUTO_FROM_NAME, attr->name);
- return GPU_stack_link(mat, "node_attribute", in, out, cd_attr);
+ /* FIXME : if an attribute layer (like vertex color) has one of theses name, it will not work as expected. */
+ if (strcmp(attr->name, "density") == 0) {
+ return GPU_stack_link(mat, node, "node_attribute_volume_density", in, out,
+ GPU_builtin(GPU_VOLUME_DENSITY));
+ }
+ else if (strcmp(attr->name, "color") == 0) {
+ return GPU_stack_link(mat, node, "node_attribute_volume_color", in, out,
+ GPU_builtin(GPU_VOLUME_DENSITY));
+ }
+ else if (strcmp(attr->name, "flame") == 0) {
+ return GPU_stack_link(mat, node, "node_attribute_volume_flame", in, out,
+ GPU_builtin(GPU_VOLUME_FLAME));
+ }
+ else {
+ GPUNodeLink *cd_attr = GPU_attribute(CD_AUTO_FROM_NAME, attr->name);
+ return GPU_stack_link(mat, node, "node_attribute", in, out, cd_attr);
+ }
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_background.c b/source/blender/nodes/shader/nodes/node_shader_background.c
index b387529e456..4ea675f9e0c 100644
--- a/source/blender/nodes/shader/nodes/node_shader_background.c
+++ b/source/blender/nodes/shader/nodes/node_shader_background.c
@@ -40,9 +40,9 @@ static bNodeSocketTemplate sh_node_background_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_background(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_background(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_background", in, out, GPU_builtin(GPU_VIEW_NORMAL));
+ return GPU_stack_link(mat, node, "node_background", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bevel.c b/source/blender/nodes/shader/nodes/node_shader_bevel.c
index e2e4da21ef3..dd9bc91e2d1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bevel.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bevel.c
@@ -45,13 +45,13 @@ static void node_shader_init_bevel(bNodeTree *UNUSED(ntree), bNode *node)
node->custom1 = 4; /* samples */
}
-static int gpu_shader_bevel(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_bevel(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[1].link) {
GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &in[1].link);
}
- return GPU_stack_link(mat, "node_bevel", in, out);
+ return GPU_stack_link(mat, node, "node_bevel", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_brightness.c b/source/blender/nodes/shader/nodes/node_shader_brightness.c
index e992c0773c2..457708405af 100644
--- a/source/blender/nodes/shader/nodes/node_shader_brightness.c
+++ b/source/blender/nodes/shader/nodes/node_shader_brightness.c
@@ -42,9 +42,9 @@ static bNodeSocketTemplate sh_node_brightcontrast_out[] = {
{ -1, 0, "" }
};
-static int gpu_shader_brightcontrast(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_brightcontrast(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "brightness_contrast", in, out);
+ return GPU_stack_link(mat, node, "brightness_contrast", in, out);
}
void register_node_type_sh_brightcontrast(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
index 01ca0bd6512..13e8ac67f63 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
@@ -49,14 +49,12 @@ static void node_shader_init_anisotropic(bNodeTree *UNUSED(ntree), bNode *node)
node->custom1 = SHD_GLOSSY_GGX;
}
-static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[4].link)
- in[4].link = GPU_builtin(GPU_VIEW_NORMAL);
- else
- GPU_link(mat, "direction_transform_m4v3", in[4].link, GPU_builtin(GPU_VIEW_MATRIX), &in[4].link);
+ GPU_link(mat, "world_normals_get", &in[4].link);
- return GPU_stack_link(mat, "node_bsdf_anisotropic", in, out);
+ return GPU_stack_link(mat, node, "node_bsdf_anisotropic", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
index e86d2677a61..be7012712cc 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
@@ -41,14 +41,12 @@ static bNodeSocketTemplate sh_node_bsdf_diffuse_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[2].link)
- in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
- else
- GPU_link(mat, "direction_transform_m4v3", in[2].link, GPU_builtin(GPU_VIEW_MATRIX), &in[2].link);
+ GPU_link(mat, "world_normals_get", &in[2].link);
- return GPU_stack_link(mat, "node_bsdf_diffuse", in, out);
+ return GPU_stack_link(mat, node, "node_bsdf_diffuse", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
index 5569fe85489..1537e07ca16 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
@@ -47,14 +47,12 @@ static void node_shader_init_glass(bNodeTree *UNUSED(ntree), bNode *node)
node->custom1 = SHD_GLOSSY_BECKMANN;
}
-static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
- in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
- else
- GPU_link(mat, "direction_transform_m4v3", in[3].link, GPU_builtin(GPU_VIEW_MATRIX), &in[3].link);
+ GPU_link(mat, "world_normals_get", &in[3].link);
- return GPU_stack_link(mat, "node_bsdf_glass", in, out);
+ return GPU_stack_link(mat, node, "node_bsdf_glass", in, out, GPU_uniform(&node->ssr_id));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
index 7e1bc971c73..35121b2afed 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
@@ -46,14 +46,12 @@ static void node_shader_init_glossy(bNodeTree *UNUSED(ntree), bNode *node)
node->custom1 = SHD_GLOSSY_GGX;
}
-static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[2].link)
- in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
- else
- GPU_link(mat, "direction_transform_m4v3", in[2].link, GPU_builtin(GPU_VIEW_MATRIX), &in[2].link);
+ GPU_link(mat, "world_normals_get", &in[2].link);
- return GPU_stack_link(mat, "node_bsdf_glossy", in, out);
+ return GPU_stack_link(mat, node, "node_bsdf_glossy", in, out, GPU_uniform(&node->ssr_id));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c
index 25be59f091d..b8078ac60ac 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c
@@ -43,9 +43,9 @@ static bNodeSocketTemplate sh_node_bsdf_hair_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_hair(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_hair(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_bsdf_hair", in, out);
+ return GPU_stack_link(mat, node, "node_bsdf_hair", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
index e0330d110ca..b0ca4128d19 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
@@ -63,8 +63,10 @@ static void node_shader_init_principled(bNodeTree *UNUSED(ntree), bNode *node)
node->custom1 = SHD_GLOSSY_MULTI_GGX;
}
-static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
+ GPUNodeLink *sss_scale;
+#if 0 /* Old 2.7 glsl viewport */
// normal
if (!in[17].link)
in[17].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -76,8 +78,46 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *UNUSED(node)
in[18].link = GPU_builtin(GPU_VIEW_NORMAL);
else
GPU_link(mat, "direction_transform_m4v3", in[18].link, GPU_builtin(GPU_VIEW_MATRIX), &in[18].link);
+#endif
- return GPU_stack_link(mat, "node_bsdf_principled", in, out, GPU_builtin(GPU_VIEW_POSITION));
+ /* Normals */
+ if (!in[17].link) {
+ GPU_link(mat, "world_normals_get", &in[17].link);
+ }
+
+ /* Clearcoat Normals */
+ if (!in[18].link) {
+ GPU_link(mat, "world_normals_get", &in[18].link);
+ }
+
+ /* Tangents */
+ if (!in[19].link) {
+ GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
+ GPU_link(mat, "tangent_orco_z", orco, &in[19].link);
+ GPU_link(mat, "node_tangent",
+ GPU_builtin(GPU_VIEW_NORMAL), in[19].link, GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
+ &in[19].link);
+ }
+
+ /* SSS Profile */
+ if (node->sss_id == 1) {
+ static short profile = SHD_SUBSURFACE_BURLEY;
+ bNodeSocket *socket = BLI_findlink(&node->original->inputs, 2);
+ bNodeSocketValueRGBA *socket_data = socket->default_value;
+ /* For some reason it seems that the socket value is in ARGB format. */
+ GPU_material_sss_profile_create(mat, &socket_data->value[1], &profile, NULL);
+ }
+
+ if (in[2].link) {
+ sss_scale = in[2].link;
+ }
+ else {
+ float one[3] = {1.0f, 1.0f, 1.0f};
+ GPU_link(mat, "set_rgb", GPU_uniform((float *)one), &sss_scale);
+ }
+
+ return GPU_stack_link(mat, node, "node_bsdf_principled_clearcoat", in, out, GPU_builtin(GPU_VIEW_POSITION),
+ GPU_uniform(&node->ssr_id), GPU_uniform(&node->sss_id), sss_scale);
}
static void node_shader_update_principled(bNodeTree *UNUSED(ntree), bNode *node)
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
index c447f5de219..9dbe3361e8b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
@@ -47,14 +47,12 @@ static void node_shader_init_refraction(bNodeTree *UNUSED(ntree), bNode *node)
node->custom1 = SHD_GLOSSY_BECKMANN;
}
-static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
- in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
- else
- GPU_link(mat, "direction_transform_m4v3", in[3].link, GPU_builtin(GPU_VIEW_MATRIX), &in[3].link);
+ GPU_link(mat, "world_normals_get", &in[3].link);
- return GPU_stack_link(mat, "node_bsdf_refraction", in, out);
+ return GPU_stack_link(mat, node, "node_bsdf_refraction", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.c
index c3510beb470..28941fbd662 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.c
@@ -42,14 +42,14 @@ static bNodeSocketTemplate sh_node_bsdf_toon_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_toon(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_toon(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
else
GPU_link(mat, "direction_transform_m4v3", in[3].link, GPU_builtin(GPU_VIEW_MATRIX), &in[3].link);
- return GPU_stack_link(mat, "node_bsdf_toon", in, out);
+ return GPU_stack_link(mat, node, "node_bsdf_toon", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
index 3b88d609cdb..f6f6da524d5 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
@@ -40,14 +40,12 @@ static bNodeSocketTemplate sh_node_bsdf_translucent_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[1].link)
- in[1].link = GPU_builtin(GPU_VIEW_NORMAL);
- else
- GPU_link(mat, "direction_transform_m4v3", in[1].link, GPU_builtin(GPU_VIEW_MATRIX), &in[1].link);
+ GPU_link(mat, "world_normals_get", &in[1].link);
- return GPU_stack_link(mat, "node_bsdf_translucent", in, out);
+ return GPU_stack_link(mat, node, "node_bsdf_translucent", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c
index 5cb50b00e1a..76afe935433 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c
@@ -39,9 +39,9 @@ static bNodeSocketTemplate sh_node_bsdf_transparent_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_bsdf_transparent", in, out);
+ return GPU_stack_link(mat, node, "node_bsdf_transparent", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
index ef3d52ecbce..6d61f3f7473 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
@@ -41,14 +41,12 @@ static bNodeSocketTemplate sh_node_bsdf_velvet_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[2].link)
- in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
- else
- GPU_link(mat, "direction_transform_m4v3", in[2].link, GPU_builtin(GPU_VIEW_MATRIX), &in[2].link);
+ GPU_link(mat, "world_normals_get", &in[2].link);
- return GPU_stack_link(mat, "node_bsdf_velvet", in, out);
+ return GPU_stack_link(mat, node, "node_bsdf_velvet", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c
index b39ca5d90ee..15a8c47db7a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bump.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bump.c
@@ -52,7 +52,7 @@ static int gpu_shader_bump(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
else
GPU_link(mat, "direction_transform_m4v3", in[3].link, GPU_builtin(GPU_VIEW_MATRIX), &in[3].link);
float invert = node->custom1;
- GPU_stack_link(mat, "node_bump", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_uniform(&invert));
+ GPU_stack_link(mat, node, "node_bump", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_uniform(&invert));
/* Other nodes are applying view matrix if the input Normal has a link.
* We don't want normal to have view matrix applied twice, so we cancel it here.
*
diff --git a/source/blender/nodes/shader/nodes/node_shader_camera.c b/source/blender/nodes/shader/nodes/node_shader_camera.c
index 3bdb5c36d69..ac0880d22ba 100644
--- a/source/blender/nodes/shader/nodes/node_shader_camera.c
+++ b/source/blender/nodes/shader/nodes/node_shader_camera.c
@@ -52,7 +52,7 @@ static void node_shader_exec_camera(void *data, int UNUSED(thread), bNode *UNUSE
}
}
-static int gpu_shader_camera(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_camera(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *viewvec;
@@ -62,7 +62,7 @@ static int gpu_shader_camera(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecDat
if (GPU_material_use_new_shading_nodes(mat))
GPU_link(mat, "invert_z", viewvec, &viewvec);
- return GPU_stack_link(mat, "camera", in, out, viewvec);
+ return GPU_stack_link(mat, node, "camera", in, out, viewvec);
}
void register_node_type_sh_camera(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c
index 5e067e6c630..ceba8fd1248 100644
--- a/source/blender/nodes/shader/nodes/node_shader_curves.c
+++ b/source/blender/nodes/shader/nodes/node_shader_curves.c
@@ -66,7 +66,7 @@ static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, bNodeExecData *UN
int size;
curvemapping_table_RGBA(node->storage, &array, &size);
- return GPU_stack_link(mat, "curves_vec", in, out, GPU_texture(size, array));
+ return GPU_stack_link(mat, node, "curves_vec", in, out, GPU_texture(size, array));
}
void register_node_type_sh_curve_vec(void)
@@ -125,7 +125,7 @@ static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UN
curvemapping_initialize(node->storage);
curvemapping_table_RGBA(node->storage, &array, &size);
- return GPU_stack_link(mat, "curves_rgb", in, out, GPU_texture(size, array));
+ return GPU_stack_link(mat, node, "curves_rgb", in, out, GPU_texture(size, array));
}
void register_node_type_sh_curve_rgb(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c
new file mode 100644
index 00000000000..c249e77c17a
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c
@@ -0,0 +1,87 @@
+/*
+ * ***** 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): Clément Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_eevee_specular_in[] = {
+ { SOCK_RGBA, 1, N_("Base Color"), 0.8f, 0.8f, 0.8f, 1.0f},
+ { SOCK_RGBA, 1, N_("Specular"), 0.03f, 0.03f, 0.03f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_RGBA, 1, N_("Emissive Color"), 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Transparency"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { SOCK_FLOAT, 1, N_("Clear Coat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_FLOAT, 1, N_("Clear Coat Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_VECTOR, 1, N_("Clear Coat Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { SOCK_FLOAT, 1, N_("Ambient Occlusion"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_eevee_specular_out[] = {
+ { SOCK_SHADER, 0, N_("BSDF")},
+ { -1, 0, "" }
+};
+
+static int node_shader_gpu_eevee_specular(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ static float one = 1.0f;
+
+ /* Normals */
+ if (!in[5].link) {
+ GPU_link(mat, "world_normals_get", &in[5].link);
+ }
+
+ /* Clearcoat Normals */
+ if (!in[8].link) {
+ GPU_link(mat, "world_normals_get", &in[8].link);
+ }
+
+ /* Occlusion */
+ if (!in[9].link) {
+ GPU_link(mat, "set_value", GPU_uniform(&one), &in[9].link);
+ }
+
+ return GPU_stack_link(mat, node, "node_eevee_specular", in, out, GPU_uniform(&node->ssr_id));
+}
+
+
+/* node type definition */
+void register_node_type_sh_eevee_specular(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_EEVEE_SPECULAR, "Specular", NODE_CLASS_SHADER, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_eevee_specular_in, sh_node_eevee_specular_out);
+ node_type_init(&ntype, NULL);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_eevee_specular);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_emission.c b/source/blender/nodes/shader/nodes/node_shader_emission.c
index 51b3d5740a7..0901e8204f8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_emission.c
+++ b/source/blender/nodes/shader/nodes/node_shader_emission.c
@@ -40,9 +40,9 @@ static bNodeSocketTemplate sh_node_emission_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_emission(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_emission(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_emission", in, out, GPU_builtin(GPU_VIEW_NORMAL));
+ return GPU_stack_link(mat, node, "node_emission", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.c b/source/blender/nodes/shader/nodes/node_shader_fresnel.c
index 8262b70fc44..b285f1a8a3e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_fresnel.c
+++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.c
@@ -39,7 +39,7 @@ static bNodeSocketTemplate sh_node_fresnel_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[1].link) {
in[1].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -48,7 +48,7 @@ static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), bNodeE
GPU_link(mat, "direction_transform_m4v3", in[1].link, GPU_builtin(GPU_VIEW_MATRIX), &in[1].link);
}
- return GPU_stack_link(mat, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_POSITION));
+ return GPU_stack_link(mat, node, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_POSITION));
}
static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c
index 37439569f77..1aebfbe5888 100644
--- a/source/blender/nodes/shader/nodes/node_shader_gamma.c
+++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c
@@ -52,9 +52,9 @@ static void node_shader_exec_gamma(void *UNUSED(data), int UNUSED(thread), bNode
out[0]->vec[2] = col[2] > 0.0f ? powf(col[2], gamma) : col[2];
}
-static int node_shader_gpu_gamma(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_gamma(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_gamma", in, out);
+ return GPU_stack_link(mat, node, "node_gamma", in, out);
}
void register_node_type_sh_gamma(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_geom.c b/source/blender/nodes/shader/nodes/node_shader_geom.c
index b289d66efc3..57bef4a6784 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geom.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geom.c
@@ -136,7 +136,7 @@ static int gpu_shader_geom(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ngeo->uvname);
GPUNodeLink *mcol = GPU_attribute(CD_MCOL, ngeo->colname);
- bool ret = GPU_stack_link(mat, "geom", in, out,
+ bool ret = GPU_stack_link(mat, node, "geom", in, out,
GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
GPU_builtin(GPU_INVERSE_VIEW_MATRIX), orco, mtface, mcol);
if (GPU_material_use_world_space_shading(mat)) {
diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c
index 553ea65154f..6647f27e5c9 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geometry.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c
@@ -41,10 +41,11 @@ static bNodeSocketTemplate sh_node_geometry_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_geometry", in, out,
+ return GPU_stack_link(mat, node, "node_geometry", in, out,
GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
+ GPU_attribute(CD_ORCO, ""), GPU_builtin(GPU_OBJECT_MATRIX),
GPU_builtin(GPU_INVERSE_VIEW_MATRIX));
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
index 6fe6a33010a..9eaa0c9f91c 100644
--- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
@@ -82,9 +82,9 @@ static void node_shader_exec_hue_sat(void *UNUSED(data), int UNUSED(thread), bNo
}
-static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "hue_sat", in, out);
+ return GPU_stack_link(mat, node, "hue_sat", in, out);
}
void register_node_type_sh_hue_sat(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.c b/source/blender/nodes/shader/nodes/node_shader_invert.c
index 27450ba0fe6..6a54733006d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_invert.c
+++ b/source/blender/nodes/shader/nodes/node_shader_invert.c
@@ -65,9 +65,9 @@ static void node_shader_exec_invert(void *UNUSED(data), int UNUSED(thread), bNod
copy_v3_v3(out[0]->vec, icol);
}
-static int gpu_shader_invert(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_invert(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "invert", in, out);
+ return GPU_stack_link(mat, node, "invert", in, out);
}
void register_node_type_sh_invert(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_lamp.c b/source/blender/nodes/shader/nodes/node_shader_lamp.c
index 2c96c91958e..3c41227ab8b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_lamp.c
+++ b/source/blender/nodes/shader/nodes/node_shader_lamp.c
@@ -68,7 +68,7 @@ static int gpu_shader_lamp(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
visifac = GPU_lamp_get_data(mat, lamp, &col, &lv, &dist, &shadow, &energy);
- bool ret = GPU_stack_link(mat, "lamp", in, out, col, energy, lv, dist, shadow, visifac);
+ bool ret = GPU_stack_link(mat, node, "lamp", in, out, col, energy, lv, dist, shadow, visifac);
if (GPU_material_use_world_space_shading(mat))
ret &= GPU_link(mat, "direction_transform_m4v3", out[1].link, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &out[1].link);
return ret;
diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
index 998e1a5687e..3ab73fdde18 100644
--- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
+++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_layer_weight_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_layer_weight(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_layer_weight(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[1].link)
in[1].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -49,7 +49,7 @@ static int node_shader_gpu_layer_weight(GPUMaterial *mat, bNode *UNUSED(node), b
GPU_link(mat, "direction_transform_m4v3", in[1].link, GPU_builtin(GPU_VIEW_MATRIX), &in[1].link);
}
- return GPU_stack_link(mat, "node_layer_weight", in, out, GPU_builtin(GPU_VIEW_POSITION));
+ return GPU_stack_link(mat, node, "node_layer_weight", in, out, GPU_builtin(GPU_VIEW_POSITION));
}
static void node_shader_exec_layer_weight(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
diff --git a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c
index 3aad476ea05..a51e4dc720f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c
+++ b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c
@@ -44,9 +44,9 @@ static bNodeSocketTemplate sh_node_light_falloff_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_light_falloff(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_light_falloff(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_light_falloff", in, out);
+ return GPU_stack_link(mat, node, "node_light_falloff", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_light_path.c b/source/blender/nodes/shader/nodes/node_shader_light_path.c
index 052f2a66ec8..be6db9c8269 100644
--- a/source/blender/nodes/shader/nodes/node_shader_light_path.c
+++ b/source/blender/nodes/shader/nodes/node_shader_light_path.c
@@ -46,9 +46,9 @@ static bNodeSocketTemplate sh_node_light_path_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_light_path(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_light_path(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_light_path", in, out);
+ return GPU_stack_link(mat, node, "node_light_path", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c
index 2044f5390cc..7f25b298cb2 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mapping.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c
@@ -94,7 +94,7 @@ static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUS
GPUNodeLink *tdomin = GPU_uniform(&domin);
GPUNodeLink *tdomax = GPU_uniform(&domax);
- GPU_stack_link(mat, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax);
+ GPU_stack_link(mat, node, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax);
if (texmap->type == TEXMAP_TYPE_NORMAL)
GPU_link(mat, "texco_norm", out[0].link, &out[0].link);
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c
index 2a1e936570d..6cd58d2fb85 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.c
+++ b/source/blender/nodes/shader/nodes/node_shader_math.c
@@ -249,7 +249,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
case NODE_MATH_LESS:
case NODE_MATH_GREATER:
case NODE_MATH_MOD:
- GPU_stack_link(mat, names[node->custom1], in, out);
+ GPU_stack_link(mat, node, names[node->custom1], in, out);
break;
case NODE_MATH_SIN:
case NODE_MATH_COS:
@@ -264,14 +264,14 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(
GPUNodeStack tmp_in[2];
memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack));
memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
- GPU_stack_link(mat, names[node->custom1], tmp_in, out);
+ GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
}
else {
/* use only second item and terminator */
GPUNodeStack tmp_in[2];
memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack));
memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
- GPU_stack_link(mat, names[node->custom1], tmp_in, out);
+ GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
}
break;
default:
diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
index f911fa058dc..cca0a1e0561 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
@@ -71,7 +71,8 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUS
"mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light",
"mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat",
"mix_val", "mix_color", "mix_soft", "mix_linear"};
- int ret = GPU_stack_link(mat, names[node->custom1], in, out);
+
+ int ret = GPU_stack_link(mat, node, names[node->custom1], in, out);
if (ret && node->custom2 & SHD_MIXRGB_CLAMP) {
float min[3] = {0.0f, 0.0f, 0.0f};
float max[3] = {1.0f, 1.0f, 1.0f};
diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c b/source/blender/nodes/shader/nodes/node_shader_mix_shader.c
index 7c5362a8969..5ac576004be 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mix_shader.c
@@ -41,9 +41,9 @@ static bNodeSocketTemplate sh_node_mix_shader_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_mix_shader(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_mix_shader(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_mix_shader", in, out);
+ return GPU_stack_link(mat, node, "node_mix_shader", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c
index 092fc201aa7..64f3ec94369 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal.c
@@ -58,14 +58,14 @@ static void node_shader_exec_normal(void *UNUSED(data), int UNUSED(thread), bNod
out[1]->vec[0] = -dot_v3v3(vec, out[0]->vec);
}
-static int gpu_shader_normal(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_normal(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *vec = GPU_uniform(out[0].vec);
if (GPU_material_use_new_shading_nodes(mat)) {
- return GPU_stack_link(mat, "normal_new_shading", in, out, vec);
+ return GPU_stack_link(mat, node, "normal_new_shading", in, out, vec);
}
else {
- return GPU_stack_link(mat, "normal", in, out, vec);
+ return GPU_stack_link(mat, node, "normal", in, out, vec);
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c
index 63d3bac88a0..471331beae3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_object_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c
@@ -37,9 +37,9 @@ static bNodeSocketTemplate sh_node_object_info_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "node_object_info", in, out, GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_OBJECT_INFO));
+ return GPU_stack_link(mat, node, "node_object_info", in, out, GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_OBJECT_INFO));
}
static void node_shader_exec_object_info(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out)
diff --git a/source/blender/nodes/shader/nodes/node_shader_output.c b/source/blender/nodes/shader/nodes/node_shader_output.c
index 789df09d898..52f659d8321 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output.c
@@ -32,6 +32,8 @@
#include "node_shader_util.h"
+#include "BKE_scene.h"
+
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_output_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f},
@@ -65,7 +67,7 @@ static void node_shader_exec_output(void *data, int UNUSED(thread), bNode *node,
}
}
-static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_output(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *outlink;
@@ -74,7 +76,7 @@ static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecDat
GPU_material_enable_alpha(mat);
#endif
- GPU_stack_link(mat, "output_node", in, out, &outlink);
+ GPU_stack_link(mat, node, "output_node", in, out, &outlink);
GPU_material_output_link(mat, outlink);
return 1;
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.c b/source/blender/nodes/shader/nodes/node_shader_output_material.c
index 336536b21ee..0418b039337 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_material.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_material.c
@@ -27,6 +27,8 @@
#include "../node_shader_util.h"
+#include "BKE_scene.h"
+
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_output_material_in[] = {
@@ -36,11 +38,11 @@ static bNodeSocketTemplate sh_node_output_material_in[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *outlink;
- GPU_stack_link(mat, "node_output_material", in, out, &outlink);
+ GPU_stack_link(mat, node, "node_output_material", in, out, &outlink);
GPU_material_output_link(mat, outlink);
return true;
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_world.c b/source/blender/nodes/shader/nodes/node_shader_output_world.c
index f95cc842720..abab4fc351a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_world.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_world.c
@@ -35,11 +35,11 @@ static bNodeSocketTemplate sh_node_output_world_in[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_output_world(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_output_world(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *outlink;
- GPU_stack_link(mat, "node_output_world", in, out, &outlink);
+ GPU_stack_link(mat, node, "node_output_world", in, out, &outlink);
GPU_material_output_link(mat, outlink);
return true;
diff --git a/source/blender/nodes/shader/nodes/node_shader_particle_info.c b/source/blender/nodes/shader/nodes/node_shader_particle_info.c
index 5f0d81e98c9..8bdc88292e7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_particle_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.c
@@ -48,10 +48,10 @@ static void node_shader_exec_particle_info(void *data, int UNUSED(thread), bNode
RE_instance_get_particle_info(shi->obi, out[0]->vec, out[1]->vec, out[2]->vec, out[3]->vec, out[4]->vec, out[5]->vec, out[6]->vec);
}
-static int gpu_shader_particle_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_particle_info(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "particle_info", in, out,
+ return GPU_stack_link(mat, node, "particle_info", in, out,
GPU_builtin(GPU_PARTICLE_SCALAR_PROPS),
GPU_builtin(GPU_PARTICLE_LOCATION),
GPU_builtin(GPU_PARTICLE_VELOCITY),
diff --git a/source/blender/nodes/shader/nodes/node_shader_rgb.c b/source/blender/nodes/shader/nodes/node_shader_rgb.c
index 4f345bf2067..b9c051c0441 100644
--- a/source/blender/nodes/shader/nodes/node_shader_rgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_rgb.c
@@ -38,10 +38,10 @@ static bNodeSocketTemplate sh_node_rgb_out[] = {
{ -1, 0, "" }
};
-static int gpu_shader_rgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- GPUNodeLink *vec = GPU_uniform(out[0].vec);
- return GPU_stack_link(mat, "set_rgba", in, out, vec);
+ GPUNodeLink *link = GPU_uniformbuffer_link_out(mat, node, out, 0);
+ return GPU_stack_link(mat, node, "set_rgba", in, out, link);
}
void register_node_type_sh_rgb(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
index b5b15397595..d031a2e412f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
@@ -53,9 +53,9 @@ static void node_shader_exec_sephsv(void *UNUSED(data), int UNUSED(thread), bNod
&out[0]->vec[0], &out[1]->vec[0], &out[2]->vec[0]);
}
-static int gpu_shader_sephsv(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_sephsv(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "separate_hsv", in, out);
+ return GPU_stack_link(mat, node, "separate_hsv", in, out);
}
void register_node_type_sh_sephsv(void)
@@ -94,9 +94,9 @@ static void node_shader_exec_combhsv(void *UNUSED(data), int UNUSED(thread), bNo
hsv_to_rgb(h, s, v, &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2]);
}
-static int gpu_shader_combhsv(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_combhsv(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "combine_hsv", in, out);
+ return GPU_stack_link(mat, node, "combine_hsv", in, out);
}
void register_node_type_sh_combhsv(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
index 006ba34c3f3..682909edb0e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
@@ -54,9 +54,9 @@ static void node_shader_exec_seprgb(void *UNUSED(data), int UNUSED(thread), bNod
out[2]->vec[0] = col[2];
}
-static int gpu_shader_seprgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_seprgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "separate_rgb", in, out);
+ return GPU_stack_link(mat, node, "separate_rgb", in, out);
}
void register_node_type_sh_seprgb(void)
@@ -98,9 +98,9 @@ static void node_shader_exec_combrgb(void *UNUSED(data), int UNUSED(thread), bNo
out[0]->vec[2] = b;
}
-static int gpu_shader_combrgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_combrgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "combine_rgb", in, out);
+ return GPU_stack_link(mat, node, "combine_rgb", in, out);
}
void register_node_type_sh_combrgb(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
index 6375dcc8782..fce62f730b9 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
@@ -44,9 +44,9 @@ static bNodeSocketTemplate sh_node_sepxyz_out[] = {
{ -1, 0, "" }
};
-static int gpu_shader_sepxyz(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_sepxyz(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "separate_xyz", in, out);
+ return GPU_stack_link(mat, node, "separate_xyz", in, out);
}
void register_node_type_sh_sepxyz(void)
@@ -75,9 +75,9 @@ static bNodeSocketTemplate sh_node_combxyz_out[] = {
{ -1, 0, "" }
};
-static int gpu_shader_combxyz(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_combxyz(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "combine_xyz", in, out);
+ return GPU_stack_link(mat, node, "combine_xyz", in, out);
}
void register_node_type_sh_combxyz(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_squeeze.c b/source/blender/nodes/shader/nodes/node_shader_squeeze.c
index a4c995748d9..2a1fbc2d02d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_squeeze.c
+++ b/source/blender/nodes/shader/nodes/node_shader_squeeze.c
@@ -56,9 +56,9 @@ static void node_shader_exec_squeeze(void *UNUSED(data), int UNUSED(thread), bNo
out[0]->vec[0] = 1.0f / (1.0f + powf(M_E, -((vec[0] - vec[2]) * vec[1])));
}
-static int gpu_shader_squeeze(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_squeeze(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "squeeze", in, out);
+ return GPU_stack_link(mat, node, "squeeze", in, out);
}
void register_node_type_sh_squeeze(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
index 7dfac32e85b..116825ff0da 100644
--- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
+++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c
@@ -49,14 +49,23 @@ static void node_shader_init_subsurface_scattering(bNodeTree *UNUSED(ntree), bNo
node->custom1 = SHD_SUBSURFACE_BURLEY;
}
-static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[5].link)
- in[5].link = GPU_builtin(GPU_VIEW_NORMAL);
- else
- GPU_link(mat, "direction_transform_m4v3", in[5].link, GPU_builtin(GPU_VIEW_MATRIX), &in[5].link);
+ GPU_link(mat, "world_normals_get", &in[5].link);
- return GPU_stack_link(mat, "node_subsurface_scattering", in, out);
+ if (node->sss_id == 1) {
+ bNodeSocket *socket = BLI_findlink(&node->original->inputs, 2);
+ bNodeSocketValueRGBA *socket_data = socket->default_value;
+ bNodeSocket *socket_sharp = BLI_findlink(&node->original->inputs, 3);
+ bNodeSocketValueFloat *socket_data_sharp = socket_sharp->default_value;
+ /* For some reason it seems that the socket value is in ARGB format. */
+ GPU_material_sss_profile_create(mat, &socket_data->value[1],
+ &node->original->custom1,
+ &socket_data_sharp->value);
+ }
+
+ return GPU_stack_link(mat, node, "node_subsurface_scattering", in, out, GPU_uniform(&node->sss_id));
}
static void node_shader_update_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node)
diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c
index 7aa7fb43221..f2c59ec8fd8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tangent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c
@@ -41,6 +41,28 @@ static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node)
node->storage = attr;
}
+static int node_shader_gpu_tangent(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ NodeShaderTangent *attr = node->storage;
+
+ if (attr->direction_type == SHD_TANGENT_UVMAP) {
+ return GPU_stack_link(mat, node, "node_tangentmap", in, out, GPU_attribute(CD_TANGENT, ""), GPU_builtin(GPU_INVERSE_VIEW_MATRIX));
+ }
+ else {
+ GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
+
+ if (attr->axis == SHD_TANGENT_AXIS_X)
+ GPU_link(mat, "tangent_orco_x", orco, &orco);
+ else if (attr->axis == SHD_TANGENT_AXIS_Y)
+ GPU_link(mat, "tangent_orco_y", orco, &orco);
+ else
+ GPU_link(mat, "tangent_orco_z", orco, &orco);
+
+ return GPU_stack_link(mat, node, "node_tangent", in, out, GPU_builtin(GPU_VIEW_NORMAL), orco,
+ GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX));
+ }
+}
+
/* node type definition */
void register_node_type_sh_tangent(void)
{
@@ -51,6 +73,7 @@ void register_node_type_sh_tangent(void)
node_type_socket_templates(&ntype, NULL, sh_node_tangent_out);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_init(&ntype, node_shader_init_tangent);
+ node_type_gpu(&ntype, node_shader_gpu_tangent);
node_type_storage(&ntype, "NodeShaderTangent", node_free_standard_storage, node_copy_standard_storage);
nodeRegisterType(&ntype);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
index 1dfebc45d60..20ea162d98f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
@@ -80,7 +80,7 @@ static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, bNodeExecDat
NodeTexBrick *tex = (NodeTexBrick *)node->storage;
float offset_freq = tex->offset_freq;
float squash_freq = tex->squash_freq;
- return GPU_stack_link(mat, "node_tex_brick",
+ return GPU_stack_link(mat, node, "node_tex_brick",
in, out,
GPU_uniform(&tex->offset), GPU_uniform(&offset_freq),
GPU_uniform(&tex->squash), GPU_uniform(&squash_freq));
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
index 77edd0e115e..3dbf98a929c 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
@@ -61,7 +61,7 @@ static int node_shader_gpu_tex_checker(GPUMaterial *mat, bNode *node, bNodeExecD
node_shader_gpu_tex_mapping(mat, node, in, out);
- return GPU_stack_link(mat, "node_tex_checker", in, out);
+ return GPU_stack_link(mat, node, "node_tex_checker", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
index be393582a42..0cab9379364 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
@@ -42,20 +42,22 @@ static bNodeSocketTemplate sh_node_tex_coord_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, "");
GPUMatType type = GPU_Material_get_type(mat);
+
+ GPU_link(mat, "generated_from_orco", orco, &orco);
- if (type == GPU_MATERIAL_TYPE_MESH) {
- return GPU_stack_link(mat, "node_tex_coord", in, out,
+ if (type == GPU_MATERIAL_TYPE_WORLD) {
+ return GPU_stack_link(mat, node, "node_tex_coord_background", in, out,
GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
GPU_builtin(GPU_CAMERA_TEXCO_FACTORS), orco, mtface);
}
else {
- return GPU_stack_link(mat, "node_tex_coord_background", in, out,
+ return GPU_stack_link(mat, node, "node_tex_coord", in, out,
GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
GPU_builtin(GPU_CAMERA_TEXCO_FACTORS), orco, mtface);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index 2f8f95b0675..4d98b142f37 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -62,7 +62,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeE
int isdata = tex->color_space == SHD_COLORSPACE_NONE;
if (!ima)
- return GPU_stack_link(mat, "node_tex_environment_empty", in, out);
+ return GPU_stack_link(mat, node, "node_tex_environment_empty", in, out);
if (!in[0].link) {
GPUMatType type = GPU_Material_get_type(mat);
@@ -76,9 +76,9 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeE
node_shader_gpu_tex_mapping(mat, node, in, out);
if (tex->projection == SHD_PROJ_EQUIRECTANGULAR)
- GPU_stack_link(mat, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata));
+ GPU_stack_link(mat, node, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata));
else
- GPU_stack_link(mat, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata));
+ GPU_stack_link(mat, node, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata));
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
index 18a8065fb57..13d3438587c 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
@@ -61,7 +61,7 @@ static int node_shader_gpu_tex_gradient(GPUMaterial *mat, bNode *node, bNodeExec
NodeTexGradient *tex = (NodeTexGradient *)node->storage;
float gradient_type = tex->gradient_type;
- return GPU_stack_link(mat, "node_tex_gradient", in, out, GPU_uniform(&gradient_type));
+ return GPU_stack_link(mat, node, "node_tex_gradient", in, out, GPU_uniform(&gradient_type));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index 71200dfe9d3..c86a502b666 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -66,7 +66,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
float blend = tex->projection_blend;
if (!ima)
- return GPU_stack_link(mat, "node_tex_image_empty", in, out);
+ return GPU_stack_link(mat, node, "node_tex_image_empty", in, out);
if (!in[0].link)
in[0].link = GPU_attribute(CD_MTFACE, "");
@@ -75,7 +75,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
switch (tex->projection) {
case SHD_PROJ_FLAT:
- GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ GPU_stack_link(mat, node, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
break;
case SHD_PROJ_BOX:
GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL),
@@ -94,12 +94,12 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
case SHD_PROJ_SPHERE:
GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
GPU_link(mat, "point_map_to_sphere", in[0].link, &in[0].link);
- GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ GPU_stack_link(mat, node, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
break;
case SHD_PROJ_TUBE:
GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
GPU_link(mat, "point_map_to_tube", in[0].link, &in[0].link);
- GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ GPU_stack_link(mat, node, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
break;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
index 8700d7954e7..7cd79067693 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
@@ -64,7 +64,7 @@ static int node_shader_gpu_tex_magic(GPUMaterial *mat, bNode *node, bNodeExecDat
node_shader_gpu_tex_mapping(mat, node, in, out);
- return GPU_stack_link(mat, "node_tex_magic", in, out, GPU_uniform(&depth));
+ return GPU_stack_link(mat, node, "node_tex_magic", in, out, GPU_uniform(&depth));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
index 51d6699fadd..e36b2d5b95b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
@@ -68,7 +68,7 @@ static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, bNode *node, bNodeExec
NodeTexMusgrave *tex = (NodeTexMusgrave *)node->storage;
float type = tex->musgrave_type;
- return GPU_stack_link(mat, "node_tex_musgrave", in, out, GPU_uniform(&type));
+ return GPU_stack_link(mat, node, "node_tex_musgrave", in, out, GPU_uniform(&type));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
index 91015b3db25..38b208fc876 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
@@ -61,7 +61,7 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat, bNode *node, bNodeExecDat
node_shader_gpu_tex_mapping(mat, node, in, out);
- return GPU_stack_link(mat, "node_tex_noise", in, out);
+ return GPU_stack_link(mat, node, "node_tex_noise", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
index 495c78ca929..7df6d34b756 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
@@ -61,7 +61,7 @@ static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, bNodeExecData
node_shader_gpu_tex_mapping(mat, node, in, out);
- return GPU_stack_link(mat, "node_tex_sky", in, out);
+ return GPU_stack_link(mat, node, "node_tex_sky", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
index c994798e2da..30deb422e58 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
@@ -63,7 +63,7 @@ static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, bNodeExecD
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
float coloring = tex->coloring;
- return GPU_stack_link(mat, "node_tex_voronoi", in, out, GPU_uniform(&coloring));
+ return GPU_stack_link(mat, node, "node_tex_voronoi", in, out, GPU_uniform(&coloring));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
index 1194874e06c..356d2a78139 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
@@ -67,7 +67,7 @@ static int node_shader_gpu_tex_wave(GPUMaterial *mat, bNode *node, bNodeExecData
float wave_type = tex->wave_type;
float wave_profile = tex->wave_profile;
- return GPU_stack_link(mat, "node_tex_wave", in, out, GPU_uniform(&wave_type), GPU_uniform(&wave_profile));
+ return GPU_stack_link(mat, node, "node_tex_wave", in, out, GPU_uniform(&wave_type), GPU_uniform(&wave_profile));
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c
index b0b25a4878b..755ef106ade 100644
--- a/source/blender/nodes/shader/nodes/node_shader_texture.c
+++ b/source/blender/nodes/shader/nodes/node_shader_texture.c
@@ -126,7 +126,7 @@ static int gpu_shader_texture(GPUMaterial *mat, bNode *node, bNodeExecData *UNUS
if (tex && tex->ima && (tex->type == TEX_IMAGE || tex->type == TEX_ENVMAP)) {
if (tex->type == TEX_IMAGE) {
GPUNodeLink *texlink = GPU_image(tex->ima, &tex->iuser, false);
- GPU_stack_link(mat, "texture_image", in, out, texlink);
+ GPU_stack_link(mat, node, "texture_image", in, out, texlink);
}
else { /* TEX_ENVMAP */
if (!in[0].link)
diff --git a/source/blender/nodes/shader/nodes/node_shader_uvmap.c b/source/blender/nodes/shader/nodes/node_shader_uvmap.c
index 0f96cb45fe0..c47bb9022b6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_uvmap.c
+++ b/source/blender/nodes/shader/nodes/node_shader_uvmap.c
@@ -47,7 +47,7 @@ static int node_shader_gpu_uvmap(GPUMaterial *mat, bNode *node, bNodeExecData *U
NodeShaderUVMap *attr = node->storage;
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, attr->uv_map);
- return GPU_stack_link(mat, "node_uvmap", in, out, mtface);
+ return GPU_stack_link(mat, node, "node_uvmap", in, out, mtface);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
index c960e006a9b..39598eb8675 100644
--- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
@@ -69,7 +69,7 @@ static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNU
int size;
BKE_colorband_evaluate_table_rgba(node->storage, &array, &size);
- return GPU_stack_link(mat, "valtorgb", in, out, GPU_texture(size, array));
+ return GPU_stack_link(mat, node, "valtorgb", in, out, GPU_texture(size, array));
}
void register_node_type_sh_valtorgb(void)
@@ -110,9 +110,9 @@ static void node_shader_exec_rgbtobw(void *UNUSED(data), int UNUSED(thread), bNo
out[0]->vec[0] = IMB_colormanagement_get_luminance(col);
}
-static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "rgbtobw", in, out);
+ return GPU_stack_link(mat, node, "rgbtobw", in, out);
}
void register_node_type_sh_rgbtobw(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_value.c b/source/blender/nodes/shader/nodes/node_shader_value.c
index 3a9582a6a7c..1e5bd8c5bff 100644
--- a/source/blender/nodes/shader/nodes/node_shader_value.c
+++ b/source/blender/nodes/shader/nodes/node_shader_value.c
@@ -38,10 +38,10 @@ static bNodeSocketTemplate sh_node_value_out[] = {
{ -1, 0, "" }
};
-static int gpu_shader_value(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_value(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- GPUNodeLink *vec = GPU_uniform(out[0].vec);
- return GPU_stack_link(mat, "set_value", in, out, vec);
+ GPUNodeLink *link = GPU_uniformbuffer_link_out(mat, node, out, 0);
+ return GPU_stack_link(mat, node, "set_value", in, out, link);
}
void register_node_type_sh_value(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
index 26045dfca04..f117adde98c 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
@@ -111,7 +111,7 @@ static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, bNodeExecData *UN
case 2:
case 3:
case 4:
- GPU_stack_link(mat, names[node->custom1], in, out);
+ GPU_stack_link(mat, node, names[node->custom1], in, out);
break;
case 5:
if (in[0].hasinput || !in[1].hasinput) {
@@ -119,14 +119,14 @@ static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, bNodeExecData *UN
GPUNodeStack tmp_in[2];
memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack));
memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
- GPU_stack_link(mat, names[node->custom1], tmp_in, out);
+ GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
}
else {
/* use only second item and terminator */
GPUNodeStack tmp_in[2];
memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack));
memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
- GPU_stack_link(mat, names[node->custom1], tmp_in, out);
+ GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
}
break;
default:
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_absorption.c b/source/blender/nodes/shader/nodes/node_shader_volume_absorption.c
index 4861871e8d3..518ab6587b2 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_absorption.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_absorption.c
@@ -40,9 +40,9 @@ static bNodeSocketTemplate sh_node_volume_absorption_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_volume_absorption(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+static int node_shader_gpu_volume_absorption(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return false;
+ return GPU_stack_link(mat, node, "node_volume_absorption", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
index 0c5647b4ba8..bce4695af10 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
@@ -41,9 +41,9 @@ static bNodeSocketTemplate sh_node_volume_scatter_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_volume_scatter(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+static int node_shader_gpu_volume_scatter(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return false;
+ return GPU_stack_link(mat, node, "node_volume_scatter", in, out);
}
/* node type definition */
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index 714665c303b..dcae9d2345f 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -62,7 +62,8 @@ static void texture_get_from_context(const bContext *C, bNodeTreeType *UNUSED(tr
{
SpaceNode *snode = CTX_wm_space_node(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = OBACT;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
Tex *tx = NULL;
if (snode->texfrom == SNODE_TEX_OBJECT) {
@@ -120,7 +121,7 @@ static void texture_get_from_context(const bContext *C, bNodeTreeType *UNUSED(tr
}
}
-static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
+static void foreach_nodeclass(ViewRender *UNUSED(view_render), void *calldata, bNodeClassCallback func)
{
func(calldata, NODE_CLASS_INPUT, N_("Input"));
func(calldata, NODE_CLASS_OUTPUT, N_("Output"));
diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt
index e855f3a3756..8d26fee0abd 100644
--- a/source/blender/python/CMakeLists.txt
+++ b/source/blender/python/CMakeLists.txt
@@ -17,6 +17,7 @@
# ***** END GPL LICENSE BLOCK *****
add_subdirectory(intern)
+add_subdirectory(gawain)
add_subdirectory(generic)
add_subdirectory(mathutils)
add_subdirectory(bmesh)
diff --git a/source/blender/python/bmesh/CMakeLists.txt b/source/blender/python/bmesh/CMakeLists.txt
index c7b86acc8f9..4d3230fa3e9 100644
--- a/source/blender/python/bmesh/CMakeLists.txt
+++ b/source/blender/python/bmesh/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../bmesh
../../blenkernel
../../blenlib
+ ../../depsgraph
../../makesdna
../../../../intern/guardedalloc
)
diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c
index d5973baeadb..d6189f7c1eb 100644
--- a/source/blender/python/bmesh/bmesh_py_api.c
+++ b/source/blender/python/bmesh/bmesh_py_api.c
@@ -156,11 +156,6 @@ static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args,
{
extern void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive);
- BMEditMesh *em = me->edit_btmesh;
- BMesh *bm = em->bm;
-
- /* python won't ensure matching uv/mtex */
- BM_mesh_cd_validate(bm);
EDBM_update_generic(me->edit_btmesh, do_tessface, is_destructive);
}
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 6ab5ebf3c81..629c3a3c7a3 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -34,10 +34,11 @@
#include "DNA_object_types.h"
#include "DNA_material_types.h"
-#include "BKE_depsgraph.h"
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
+#include "DEG_depsgraph.h"
+
#include "bmesh.h"
#include <Python.h>
@@ -901,14 +902,11 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
bm = self->bm;
- /* python won't ensure matching uv/mtex */
- BM_mesh_cd_validate(bm);
-
BM_mesh_bm_to_me(bm, me, (&(struct BMeshToMeshParams){0}));
/* we could have the user do this but if they forget blender can easy crash
* since the references arrays for the objects derived meshes are now invalid */
- DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&me->id, OB_RECALC_DATA);
Py_RETURN_NONE;
}
@@ -931,6 +929,8 @@ PyDoc_STRVAR(bpy_bmesh_from_object_doc,
);
static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject *kw)
{
+ /* TODO: This doesn't work currently because of eval_ctx. */
+#if 0
static const char *kwlist[] = {"object", "scene", "deform", "render", "cage", "face_normals", NULL};
PyObject *py_object;
PyObject *py_scene;
@@ -1023,6 +1023,10 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject
dm->release(dm);
Py_RETURN_NONE;
+#else
+ UNUSED_VARS(self, args, kw);
+#endif
+ return NULL;
}
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index cb95ded4f0d..e2241ade7f0 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -105,9 +105,6 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__bevel_weight_doc,
PyDoc_STRVAR(bpy_bmlayeraccess_collection__crease_doc,
"Edge crease for subsurf - float in [0 - 1].\n\n:type: :class:`BMLayerCollection`"
);
-PyDoc_STRVAR(bpy_bmlayeraccess_collection__tex_doc,
-"Accessor for :class:`BMTexPoly` layer (TODO).\n\ntype: :class:`BMLayerCollection`" // TYPE DOESN'T EXIST YET
-);
PyDoc_STRVAR(bpy_bmlayeraccess_collection__uv_doc,
"Accessor for :class:`BMLoopUV` UV (as a 2D Vector).\n\ntype: :class:`BMLayerCollection`"
);
@@ -120,6 +117,9 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__skin_doc,
PyDoc_STRVAR(bpy_bmlayeraccess_collection__paint_mask_doc,
"Accessor for paint mask layer.\n\ntype: :class:`BMLayerCollection`"
);
+PyDoc_STRVAR(bpy_bmlayeraccess_collection__face_map_doc,
+"FaceMap custom-data layer.\n\ntype: :class:`BMLayerCollection`"
+);
#ifdef WITH_FREESTYLE
PyDoc_STRVAR(bpy_bmlayeraccess_collection__freestyle_edge_doc,
"Accessor for Freestyle edge layer.\n\ntype: :class:`BMLayerCollection`"
@@ -222,8 +222,7 @@ static PyGetSetDef bpy_bmlayeraccess_face_getseters[] = {
{(char *)"float", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__float_doc, (void *)CD_PROP_FLT},
{(char *)"int", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__int_doc, (void *)CD_PROP_INT},
{(char *)"string", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__string_doc, (void *)CD_PROP_STR},
-
- {(char *)"tex", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__tex_doc, (void *)CD_MTEXPOLY},
+ {(char *)"face_map", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__face_map_doc, (void *)CD_FACEMAP},
#ifdef WITH_FREESTYLE
{(char *)"freestyle", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__freestyle_face_doc, (void *)CD_FREESTYLE_FACE},
@@ -989,6 +988,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
break;
}
case CD_PROP_INT:
+ case CD_FACEMAP:
{
ret = PyLong_FromLong(*(int *)value);
break;
@@ -999,11 +999,6 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
ret = PyBytes_FromStringAndSize(mstring->s, mstring->s_len);
break;
}
- case CD_MTEXPOLY:
- {
- ret = BPy_BMTexPoly_CreatePyObject(value);
- break;
- }
case CD_MLOOPUV:
{
ret = BPy_BMLoopUV_CreatePyObject(value);
@@ -1074,6 +1069,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj
break;
}
case CD_PROP_INT:
+ case CD_FACEMAP:
{
int tmp_val = PyC_Long_AsI32(py_value);
if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) {
@@ -1102,11 +1098,6 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj
}
break;
}
- case CD_MTEXPOLY:
- {
- ret = BPy_BMTexPoly_AssignPyObject(value, py_value);
- break;
- }
case CD_MLOOPUV:
{
ret = BPy_BMLoopUV_AssignPyObject(value, py_value);
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
index 7984f625d96..54b33e7b6b6 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
@@ -48,96 +48,6 @@
#include "../generic/py_capi_utils.h"
#include "../generic/python_utildefines.h"
-
-/* Mesh BMTexPoly
- * ************** */
-
-#define BPy_BMTexPoly_Check(v) (Py_TYPE(v) == &BPy_BMTexPoly_Type)
-
-typedef struct BPy_BMTexPoly {
- PyObject_VAR_HEAD
- MTexPoly *data;
-} BPy_BMTexPoly;
-
-extern PyObject *pyrna_id_CreatePyObject(ID *id);
-extern bool pyrna_id_FromPyObject(PyObject *obj, ID **id);
-
-PyDoc_STRVAR(bpy_bmtexpoly_image_doc,
-"Image or None.\n\n:type: :class:`bpy.types.Image`"
-);
-static PyObject *bpy_bmtexpoly_image_get(BPy_BMTexPoly *self, void *UNUSED(closure))
-{
- return pyrna_id_CreatePyObject((ID *)self->data->tpage);
-}
-
-static int bpy_bmtexpoly_image_set(BPy_BMTexPoly *self, PyObject *value, void *UNUSED(closure))
-{
- ID *id;
-
- if (value == Py_None) {
- id = NULL;
- }
- else if (pyrna_id_FromPyObject(value, &id) && id && GS(id->name) == ID_IM) {
- /* pass */
- }
- else {
- PyErr_Format(PyExc_KeyError, "BMTexPoly.image = x"
- "expected an image or None, not '%.200s'",
- Py_TYPE(value)->tp_name);
- return -1;
- }
-
- id_lib_extern(id);
- self->data->tpage = (struct Image *)id;
-
- return 0;
-}
-
-static PyGetSetDef bpy_bmtexpoly_getseters[] = {
- /* attributes match rna_def_mtpoly */
- {(char *)"image", (getter)bpy_bmtexpoly_image_get, (setter)bpy_bmtexpoly_image_set, (char *)bpy_bmtexpoly_image_doc, NULL},
-
- {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
-};
-
-static PyTypeObject BPy_BMTexPoly_Type; /* bm.loops.layers.uv.active */
-
-static void bm_init_types_bmtexpoly(void)
-{
- BPy_BMTexPoly_Type.tp_basicsize = sizeof(BPy_BMTexPoly);
-
- BPy_BMTexPoly_Type.tp_name = "BMTexPoly";
-
- BPy_BMTexPoly_Type.tp_doc = NULL; // todo
-
- BPy_BMTexPoly_Type.tp_getset = bpy_bmtexpoly_getseters;
-
- BPy_BMTexPoly_Type.tp_flags = Py_TPFLAGS_DEFAULT;
-
- PyType_Ready(&BPy_BMTexPoly_Type);
-}
-
-int BPy_BMTexPoly_AssignPyObject(struct MTexPoly *mtpoly, PyObject *value)
-{
- if (UNLIKELY(!BPy_BMTexPoly_Check(value))) {
- PyErr_Format(PyExc_TypeError, "expected BMTexPoly, not a %.200s", Py_TYPE(value)->tp_name);
- return -1;
- }
- else {
- *((MTexPoly *)mtpoly) = *(((BPy_BMTexPoly *)value)->data);
- return 0;
- }
-}
-
-PyObject *BPy_BMTexPoly_CreatePyObject(struct MTexPoly *mtpoly)
-{
- BPy_BMTexPoly *self = PyObject_New(BPy_BMTexPoly, &BPy_BMTexPoly_Type);
- self->data = mtpoly;
- return (PyObject *)self;
-}
-
-/* --- End Mesh BMTexPoly --- */
-
/* Mesh Loop UV
* ************ */
@@ -797,7 +707,6 @@ PyObject *BPy_BMDeformVert_CreatePyObject(struct MDeformVert *dvert)
/* call to init all types */
void BPy_BM_init_types_meshdata(void)
{
- bm_init_types_bmtexpoly();
bm_init_types_bmloopuv();
bm_init_types_bmloopcol();
bm_init_types_bmdvert();
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.h b/source/blender/python/bmesh/bmesh_py_types_meshdata.h
index 07d8a46cc65..c8ae2596f99 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.h
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.h
@@ -40,15 +40,11 @@ typedef struct BPy_BMGenericMeshData {
void *data;
} BPy_BMGenericMeshData;
-struct MTexPoly;
struct MLoopUV;
struct MLoopCol;
struct MDeformVert;
struct MVertSkin;
-int BPy_BMTexPoly_AssignPyObject(struct MTexPoly *mloopuv, PyObject *value);
-PyObject *BPy_BMTexPoly_CreatePyObject(struct MTexPoly *mloopuv);
-
int BPy_BMLoopUV_AssignPyObject(struct MLoopUV *data, PyObject *value);
PyObject *BPy_BMLoopUV_CreatePyObject(struct MLoopUV *data);
diff --git a/source/blender/python/gawain/CMakeLists.txt b/source/blender/python/gawain/CMakeLists.txt
new file mode 100644
index 00000000000..6b6c902f48a
--- /dev/null
+++ b/source/blender/python/gawain/CMakeLists.txt
@@ -0,0 +1,47 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Contributor(s): Campbell Barton
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ../../blenkernel
+ ../../blenlib
+ ../../gpu
+ ../../makesdna
+ ../../../../intern/gawain
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
+)
+
+set(INC_SYS
+ ${GLEW_INCLUDE_PATH}
+ ${PYTHON_INCLUDE_DIRS}
+)
+
+set(SRC
+ gwn_py_api.c
+ gwn_py_types.c
+
+ gwn_py_api.h
+ gwn_py_types.h
+)
+
+add_definitions(${GL_DEFINITIONS})
+
+blender_add_lib(bf_python_gawain "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/python/gawain/gwn_py_api.c b/source/blender/python/gawain/gwn_py_api.c
new file mode 100644
index 00000000000..d79ef070649
--- /dev/null
+++ b/source/blender/python/gawain/gwn_py_api.c
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gawain/gwn_py_api.c
+ * \ingroup pygawain
+ *
+ * Experimental Python API, not considered public yet (called '_gawain'),
+ * we may re-expose as public later.
+ */
+
+#include <Python.h>
+
+#include "gawain/gwn_batch.h"
+#include "gawain/gwn_vertex_format.h"
+
+#include "gwn_py_api.h"
+#include "gwn_py_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "../generic/python_utildefines.h"
+
+PyDoc_STRVAR(GWN_doc,
+"This module provides access to gawain drawing functions."
+);
+static struct PyModuleDef GWN_module_def = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "_gawain", /* m_name */
+ .m_doc = GWN_doc, /* m_doc */
+};
+
+PyObject *BPyInit_gawain(void)
+{
+ PyObject *sys_modules = PyThreadState_GET()->interp->modules;
+ PyObject *submodule;
+ PyObject *mod;
+
+ mod = PyModule_Create(&GWN_module_def);
+
+ /* _gawain.types */
+ PyModule_AddObject(mod, "types", (submodule = BPyInit_gawain_types()));
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
+ Py_INCREF(submodule);
+
+ return mod;
+}
diff --git a/source/blender/python/gawain/gwn_py_api.h b/source/blender/python/gawain/gwn_py_api.h
new file mode 100644
index 00000000000..3ef85e8ae0f
--- /dev/null
+++ b/source/blender/python/gawain/gwn_py_api.h
@@ -0,0 +1,30 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __GWN_PY_API_H__
+#define __GWN_PY_API_H__
+
+/** \file blender/python/gawain/gwn_py_api.h
+ * \ingroup pygawain
+ */
+
+PyObject *BPyInit_gawain(void);
+
+#endif /* __GWN_PY_API_H__ */
diff --git a/source/blender/python/gawain/gwn_py_types.c b/source/blender/python/gawain/gwn_py_types.c
new file mode 100644
index 00000000000..5b602e85a12
--- /dev/null
+++ b/source/blender/python/gawain/gwn_py_types.c
@@ -0,0 +1,847 @@
+/*
+ * ***** 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/python/gawain/gwn_py_types.c
+ * \ingroup pygawain
+ *
+ * - Use ``bpygwn_`` for local API.
+ * - Use ``BPyGwn_`` for public API.
+ */
+
+#include <Python.h>
+
+#include "gawain/gwn_batch.h"
+#include "gawain/gwn_vertex_format.h"
+
+#include "BLI_math.h"
+
+#include "GPU_batch.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
+#include "gwn_py_types.h" /* own include */
+
+#ifdef __BIG_ENDIAN__
+ /* big endian */
+# define MAKE_ID2(c, d) ((c) << 8 | (d))
+# define MAKE_ID3(a, b, c) ( (int)(a) << 24 | (int)(b) << 16 | (c) << 8 )
+# define MAKE_ID4(a, b, c, d) ( (int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d) )
+#else
+ /* little endian */
+# define MAKE_ID2(c, d) ((d) << 8 | (c))
+# define MAKE_ID3(a, b, c) ( (int)(c) << 16 | (b) << 8 | (a) )
+# define MAKE_ID4(a, b, c, d) ( (int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a) )
+#endif
+
+/* -------------------------------------------------------------------- */
+
+/** \name Enum Conversion
+ *
+ * Use with PyArg_ParseTuple's "O&" formatting.
+ * \{ */
+
+static int bpygwn_ParseVertCompType(PyObject *o, void *p)
+{
+ Py_ssize_t comp_type_id_len;
+ const char *comp_type_id = _PyUnicode_AsStringAndSize(o, &comp_type_id_len);
+ if (comp_type_id == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "expected a string, got %s",
+ Py_TYPE(o)->tp_name);
+ return 0;
+ }
+
+ Gwn_VertCompType comp_type;
+ if (comp_type_id_len == 2) {
+ switch (*((ushort *)comp_type_id)) {
+ case MAKE_ID2('I', '8'): { comp_type = GWN_COMP_I8; goto success; }
+ case MAKE_ID2('U', '8'): { comp_type = GWN_COMP_U8; goto success; }
+ }
+ }
+ else if (comp_type_id_len == 3) {
+ switch (*((uint *)comp_type_id)) {
+ case MAKE_ID3('I', '1', '6'): { comp_type = GWN_COMP_I16; goto success; }
+ case MAKE_ID3('U', '1', '6'): { comp_type = GWN_COMP_U16; goto success; }
+ case MAKE_ID3('I', '3', '2'): { comp_type = GWN_COMP_I32; goto success; }
+ case MAKE_ID3('U', '3', '2'): { comp_type = GWN_COMP_U32; goto success; }
+ case MAKE_ID3('F', '3', '2'): { comp_type = GWN_COMP_F32; goto success; }
+ case MAKE_ID3('I', '1', '0'): { comp_type = GWN_COMP_I10; goto success; }
+ }
+ }
+
+ PyErr_Format(PyExc_ValueError,
+ "unknown type literal: '%s'",
+ comp_type_id);
+ return 0;
+
+success:
+ *((Gwn_VertCompType *)p) = comp_type;
+ return 1;
+}
+
+static int bpygwn_ParseVertFetchMode(PyObject *o, void *p)
+{
+ Py_ssize_t mode_id_len;
+ const char *mode_id = _PyUnicode_AsStringAndSize(o, &mode_id_len);
+ if (mode_id == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "expected a string, got %s",
+ Py_TYPE(o)->tp_name);
+ return 0;
+ }
+#define MATCH_ID(id) \
+ if (mode_id_len == strlen(STRINGIFY(id))) { \
+ if (STREQ(mode_id, STRINGIFY(id))) { \
+ mode = GWN_FETCH_##id; \
+ goto success; \
+ } \
+ } ((void)0)
+
+ Gwn_VertCompType mode;
+ MATCH_ID(FLOAT);
+ MATCH_ID(INT);
+ MATCH_ID(INT_TO_FLOAT_UNIT);
+ MATCH_ID(INT_TO_FLOAT);
+#undef MATCH_ID
+ PyErr_Format(PyExc_ValueError,
+ "unknown type literal: '%s'",
+ mode_id);
+ return 0;
+
+success:
+ (*(Gwn_VertFetchMode *)p) = mode;
+ return 1;
+}
+
+static int bpygwn_ParsePrimType(PyObject *o, void *p)
+{
+ Py_ssize_t mode_id_len;
+ const char *mode_id = _PyUnicode_AsStringAndSize(o, &mode_id_len);
+ if (mode_id == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "expected a string, got %s",
+ Py_TYPE(o)->tp_name);
+ return 0;
+ }
+#define MATCH_ID(id) \
+ if (mode_id_len == strlen(STRINGIFY(id))) { \
+ if (STREQ(mode_id, STRINGIFY(id))) { \
+ mode = GWN_PRIM_##id; \
+ goto success; \
+ } \
+ } ((void)0)
+
+ Gwn_PrimType mode;
+ MATCH_ID(POINTS);
+ MATCH_ID(LINES);
+ MATCH_ID(TRIS);
+ MATCH_ID(LINE_STRIP);
+ MATCH_ID(LINE_LOOP);
+ MATCH_ID(TRI_STRIP);
+ MATCH_ID(TRI_FAN);
+ MATCH_ID(LINE_STRIP_ADJ);
+
+#undef MATCH_ID
+ PyErr_Format(PyExc_ValueError,
+ "unknown type literal: '%s'",
+ mode_id);
+ return 0;
+
+success:
+ (*(Gwn_VertFetchMode *)p) = mode;
+ return 1;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Utility Functions
+ * \{ */
+
+#define PY_AS_NATIVE_SWITCH(attr) \
+ switch (attr->comp_type) { \
+ case GWN_COMP_I8: { PY_AS_NATIVE(int8_t, PyC_Long_AsI8); break; } \
+ case GWN_COMP_U8: { PY_AS_NATIVE(uint8_t, PyC_Long_AsU8); break; } \
+ case GWN_COMP_I16: { PY_AS_NATIVE(int16_t, PyC_Long_AsI16); break; } \
+ case GWN_COMP_U16: { PY_AS_NATIVE(uint16_t, PyC_Long_AsU16); break; } \
+ case GWN_COMP_I32: { PY_AS_NATIVE(int32_t, PyC_Long_AsI32); break; } \
+ case GWN_COMP_U32: { PY_AS_NATIVE(uint32_t, PyC_Long_AsU32); break; } \
+ case GWN_COMP_F32: { PY_AS_NATIVE(float, PyFloat_AsDouble); break; } \
+ default: \
+ BLI_assert(0); \
+ } ((void)0)
+
+/* No error checking, callers must run PyErr_Occurred */
+static void fill_format_elem(void *data_dst_void, PyObject *py_src, const Gwn_VertAttr *attr)
+{
+#define PY_AS_NATIVE(ty_dst, py_as_native) \
+{ \
+ ty_dst *data_dst = data_dst_void; \
+ *data_dst = py_as_native(py_src); \
+} ((void)0)
+
+ PY_AS_NATIVE_SWITCH(attr);
+
+#undef PY_AS_NATIVE
+}
+
+/* No error checking, callers must run PyErr_Occurred */
+static void fill_format_tuple(void *data_dst_void, PyObject *py_src, const Gwn_VertAttr *attr)
+{
+ const uint len = attr->comp_ct;
+
+/**
+ * Args are constants, so range checks will be optimized out if they're nop's.
+ */
+#define PY_AS_NATIVE(ty_dst, py_as_native) \
+ ty_dst *data_dst = data_dst_void; \
+ for (uint i = 0; i < len; i++) { \
+ data_dst[i] = py_as_native(PyTuple_GET_ITEM(py_src, i)); \
+ } ((void)0)
+
+ PY_AS_NATIVE_SWITCH(attr);
+
+#undef PY_AS_NATIVE
+}
+
+#undef PY_AS_NATIVE_SWITCH
+#undef WARN_TYPE_LIMIT_PUSH
+#undef WARN_TYPE_LIMIT_POP
+
+static bool bpygwn_vertbuf_fill_impl(
+ Gwn_VertBuf *vbo,
+ uint data_id, PyObject *seq)
+{
+ bool ok = true;
+ const Gwn_VertAttr *attr = &vbo->format.attribs[data_id];
+
+ Gwn_VertBufRaw data_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, data_id, &data_step);
+
+ PyObject *seq_fast = PySequence_Fast(seq, "Vertex buffer fill");
+ if (seq_fast == NULL) {
+ goto finally;
+ }
+
+ const uint seq_len = PySequence_Fast_GET_SIZE(seq_fast);
+
+ if (seq_len != vbo->vertex_ct) {
+ PyErr_Format(PyExc_ValueError,
+ "Expected a sequence of size %d, got %d",
+ vbo->vertex_ct, seq_len);
+ }
+
+ PyObject **seq_items = PySequence_Fast_ITEMS(seq_fast);
+
+ if (attr->comp_ct == 1) {
+ for (uint i = 0; i < seq_len; i++) {
+ uchar *data = (uchar *)GWN_vertbuf_raw_step(&data_step);
+ PyObject *item = seq_items[i];
+ fill_format_elem(data, item, attr);
+ }
+ }
+ else {
+ for (uint i = 0; i < seq_len; i++) {
+ uchar *data = (uchar *)GWN_vertbuf_raw_step(&data_step);
+ PyObject *item = seq_items[i];
+ if (!PyTuple_CheckExact(item)) {
+ PyErr_Format(PyExc_ValueError,
+ "expected a tuple, got %s",
+ Py_TYPE(item)->tp_name);
+ ok = false;
+ goto finally;
+ }
+ if (PyTuple_GET_SIZE(item) != attr->comp_ct) {
+ PyErr_Format(PyExc_ValueError,
+ "expected a tuple of size %d, got %d",
+ attr->comp_ct, PyTuple_GET_SIZE(item));
+ ok = false;
+ goto finally;
+ }
+
+ /* May trigger error, check below */
+ fill_format_tuple(data, item, attr);
+ }
+ }
+
+ if (PyErr_Occurred()) {
+ ok = false;
+ }
+
+finally:
+
+ Py_DECREF(seq_fast);
+ return ok;
+}
+
+/* handy, but not used just now */
+#if 0
+static int bpygwn_find_id(const Gwn_VertFormat *fmt, const char *id)
+{
+ for (int i = 0; i < fmt->attrib_ct; i++) {
+ for (uint j = 0; j < fmt->name_ct; j++) {
+ if (STREQ(fmt->attribs[i].name[j], id)) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+#endif
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name VertFormat Type
+ * \{ */
+
+static PyObject *bpygwn_VertFormat_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
+{
+ if (PyTuple_GET_SIZE(args) || (kwds && PyDict_Size(kwds))) {
+ PyErr_SetString(PyExc_TypeError,
+ "VertFormat(): takes no arguments");
+ return NULL;
+ }
+
+ BPyGwn_VertFormat *ret = (BPyGwn_VertFormat *)BPyGwn_VertFormat_CreatePyObject(NULL);
+
+ return (PyObject *)ret;
+}
+
+PyDoc_STRVAR(bpygwn_VertFormat_attr_add_doc,
+"TODO"
+);
+static PyObject *bpygwn_VertFormat_attr_add(BPyGwn_VertFormat *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"id", "comp_type", "len", "fetch_mode", NULL};
+
+ struct {
+ const char *id;
+ Gwn_VertCompType comp_type;
+ uint len;
+ Gwn_VertFetchMode fetch_mode;
+ } params;
+
+ if (self->fmt.attrib_ct == GWN_VERT_ATTR_MAX_LEN) {
+ PyErr_SetString(PyExc_ValueError, "Maxumum attr reached " STRINGIFY(GWN_VERT_ATTR_MAX_LEN));
+ return NULL;
+ }
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwds, "$sO&IO&:attr_add", (char **)kwlist,
+ &params.id,
+ bpygwn_ParseVertCompType, &params.comp_type,
+ &params.len,
+ bpygwn_ParseVertFetchMode, &params.fetch_mode))
+ {
+ return NULL;
+ }
+
+ uint attr_id = GWN_vertformat_attr_add(&self->fmt, params.id, params.comp_type, params.len, params.fetch_mode);
+ return PyLong_FromLong(attr_id);
+}
+
+static struct PyMethodDef bpygwn_VertFormat_methods[] = {
+ {"attr_add", (PyCFunction)bpygwn_VertFormat_attr_add,
+ METH_VARARGS | METH_KEYWORDS, bpygwn_VertFormat_attr_add_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+
+static void bpygwn_VertFormat_dealloc(BPyGwn_VertFormat *self)
+{
+ Py_TYPE(self)->tp_free(self);
+}
+
+PyTypeObject BPyGwn_VertFormat_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "Gwn_VertFormat",
+ .tp_basicsize = sizeof(BPyGwn_VertFormat),
+ .tp_dealloc = (destructor)bpygwn_VertFormat_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_methods = bpygwn_VertFormat_methods,
+ .tp_new = bpygwn_VertFormat_new,
+};
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name VertBuf Type
+ * \{ */
+
+static PyObject *bpygwn_VertBuf_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
+{
+ const char * const keywords[] = {"len", "format", NULL};
+
+ struct {
+ BPyGwn_VertFormat *py_fmt;
+ uint len;
+ } params;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwds,
+ "$IO!:Gwn_VertBuf.__new__", (char **)keywords,
+ &params.len,
+ &BPyGwn_VertFormat_Type, &params.py_fmt))
+ {
+ return NULL;
+ }
+
+ struct Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&params.py_fmt->fmt);
+
+ GWN_vertbuf_data_alloc(vbo, params.len);
+
+ return BPyGwn_VertBuf_CreatePyObject(vbo);
+}
+
+PyDoc_STRVAR(bpygwn_VertBuf_fill_doc,
+"TODO"
+);
+static PyObject *bpygwn_VertBuf_fill(BPyGwn_VertBuf *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"id", "data", NULL};
+
+ struct {
+ uint id;
+ PyObject *py_seq_data;
+ } params;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwds, "$IO:fill", (char **)kwlist,
+ &params.id,
+ &params.py_seq_data))
+ {
+ return NULL;
+ }
+
+ if (params.id >= self->buf->format.attrib_ct) {
+ PyErr_Format(PyExc_ValueError,
+ "Format id %d out of range",
+ params.id);
+ return NULL;
+ }
+
+ if (self->buf->vbo_id != 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "Can't fill, buffer already in use");
+ return NULL;
+ }
+
+ if (!bpygwn_vertbuf_fill_impl(self->buf, params.id, params.py_seq_data)) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static struct PyMethodDef bpygwn_VertBuf_methods[] = {
+ {"fill", (PyCFunction) bpygwn_VertBuf_fill,
+ METH_VARARGS | METH_KEYWORDS, bpygwn_VertBuf_fill_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+static void bpygwn_VertBuf_dealloc(BPyGwn_VertBuf *self)
+{
+ GWN_vertbuf_discard(self->buf);
+ Py_TYPE(self)->tp_free(self);
+}
+
+PyTypeObject BPyGwn_VertBuf_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "Gwn_VertBuf",
+ .tp_basicsize = sizeof(BPyGwn_VertBuf),
+ .tp_dealloc = (destructor)bpygwn_VertBuf_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_methods = bpygwn_VertBuf_methods,
+ .tp_new = bpygwn_VertBuf_new,
+};
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name VertBatch Type
+ * \{ */
+
+static PyObject *bpygwn_Batch_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
+{
+ const char * const keywords[] = {"type", "buf", NULL};
+
+ struct {
+ Gwn_PrimType type_id;
+ BPyGwn_VertBuf *py_buf;
+ } params;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwds,
+ "$O&O!:Gwn_Batch.__new__", (char **)keywords,
+ bpygwn_ParsePrimType, &params.type_id,
+ &BPyGwn_VertBuf_Type, &params.py_buf))
+ {
+ return NULL;
+ }
+
+ Gwn_Batch *batch = GWN_batch_create(params.type_id, params.py_buf->buf, NULL);
+ BPyGwn_Batch *ret = (BPyGwn_Batch *)BPyGwn_Batch_CreatePyObject(batch);
+
+#ifdef USE_GWN_PY_REFERENCES
+ ret->references = PyList_New(1);
+ PyList_SET_ITEM(ret->references, 0, (PyObject *)params.py_buf);
+ Py_INCREF(params.py_buf);
+ PyObject_GC_Track(ret);
+#endif
+
+ return (PyObject *)ret;
+}
+
+PyDoc_STRVAR(bpygwn_VertBatch_vertbuf_add_doc,
+"TODO"
+);
+static PyObject *bpygwn_VertBatch_vertbuf_add(BPyGwn_Batch *self, BPyGwn_VertBuf *py_buf)
+{
+ if (!BPyGwn_VertBuf_Check(py_buf)) {
+ PyErr_Format(PyExc_TypeError,
+ "Expected a Gwn_VertBuf, got %s",
+ Py_TYPE(py_buf)->tp_name);
+ return NULL;
+ }
+
+ if (self->batch->verts[0]->vertex_ct != py_buf->buf->vertex_ct) {
+ PyErr_Format(PyExc_TypeError,
+ "Expected %d length, got %d",
+ self->batch->verts[0]->vertex_ct, py_buf->buf->vertex_ct);
+ return NULL;
+ }
+
+#ifdef USE_GWN_PY_REFERENCES
+ /* Hold user */
+ PyList_Append(self->references, (PyObject *)py_buf);
+#endif
+
+ GWN_batch_vertbuf_add(self->batch, py_buf->buf);
+ Py_RETURN_NONE;
+}
+
+/* Currently magic number from Py perspective. */
+PyDoc_STRVAR(bpygwn_VertBatch_program_set_builtin_doc,
+"TODO"
+);
+static PyObject *bpygwn_VertBatch_program_set_builtin(BPyGwn_Batch *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"id", NULL};
+
+ struct {
+ const char *shader;
+ } params;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwds, "s:program_set_builtin", (char **)kwlist,
+ &params.shader))
+ {
+ return NULL;
+ }
+
+ GPUBuiltinShader shader;
+
+#define MATCH_ID(id) \
+ if (STREQ(params.shader, STRINGIFY(id))) { \
+ shader = GPU_SHADER_##id; \
+ goto success; \
+ } ((void)0)
+
+ MATCH_ID(2D_FLAT_COLOR);
+ MATCH_ID(2D_SMOOTH_COLOR);
+ MATCH_ID(2D_UNIFORM_COLOR);
+
+ MATCH_ID(3D_FLAT_COLOR);
+ MATCH_ID(3D_SMOOTH_COLOR);
+ MATCH_ID(3D_UNIFORM_COLOR);
+
+#undef MATCH_ID
+
+ PyErr_SetString(PyExc_ValueError,
+ "shader name not known");
+ return NULL;
+
+success:
+ GWN_batch_program_set_builtin(self->batch, shader);
+ Py_RETURN_NONE;
+}
+
+static PyObject *bpygwn_VertBatch_uniform_bool(BPyGwn_Batch *self, PyObject *args)
+{
+ struct {
+ const char *id;
+ bool values[1];
+ } params;
+
+ if (!PyArg_ParseTuple(
+ args, "sO&:uniform_bool",
+ &params.id,
+ PyC_ParseBool, &params.values[0]))
+ {
+ return NULL;
+ }
+
+ GWN_batch_uniform_1b(self->batch, params.id, params.values[0]);
+ Py_RETURN_NONE;
+}
+
+static PyObject *bpygwn_VertBatch_uniform_i32(BPyGwn_Batch *self, PyObject *args)
+{
+ struct {
+ const char *id;
+ int values[1];
+ } params;
+
+ if (!PyArg_ParseTuple(
+ args, "si:uniform_i32",
+ &params.id,
+ &params.values[0]))
+ {
+ return NULL;
+ }
+
+ GWN_batch_uniform_1i(self->batch, params.id, params.values[0]);
+ Py_RETURN_NONE;
+}
+
+static PyObject *bpygwn_VertBatch_uniform_f32(BPyGwn_Batch *self, PyObject *args)
+{
+ static struct {
+ const char *id;
+ float values[4];
+ } params;
+
+ if (!PyArg_ParseTuple(
+ args, "sf|fff:uniform_f32",
+ &params.id,
+ &params.values[0], &params.values[1], &params.values[2], &params.values[3]))
+ {
+ return NULL;
+ }
+
+ switch (PyTuple_GET_SIZE(args)) {
+ case 2: GWN_batch_uniform_1f(self->batch, params.id, params.values[0]); break;
+ case 3: GWN_batch_uniform_2fv(self->batch, params.id, params.values); break;
+ case 4: GWN_batch_uniform_3fv(self->batch, params.id, params.values); break;
+ case 5: GWN_batch_uniform_4fv(self->batch, params.id, params.values); break;
+ default:
+ BLI_assert(0);
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpygwn_VertBatch_draw_doc,
+"TODO"
+);
+static PyObject *bpygwn_VertBatch_draw(BPyGwn_Batch *self)
+{
+ if (!glIsProgram(self->batch->program)) {
+ PyErr_SetString(PyExc_ValueError,
+ "batch program has not not set");
+ }
+ GWN_batch_draw(self->batch);
+ Py_RETURN_NONE;
+}
+
+static PyObject *bpygwn_VertBatch_program_use_begin(BPyGwn_Batch *self)
+{
+ if (!glIsProgram(self->batch->program)) {
+ PyErr_SetString(PyExc_ValueError,
+ "batch program has not not set");
+ }
+ GWN_batch_program_use_begin(self->batch);
+ Py_RETURN_NONE;
+}
+
+static PyObject *bpygwn_VertBatch_program_use_end(BPyGwn_Batch *self)
+{
+ if (!glIsProgram(self->batch->program)) {
+ PyErr_SetString(PyExc_ValueError,
+ "batch program has not not set");
+ }
+ GWN_batch_program_use_end(self->batch);
+ Py_RETURN_NONE;
+}
+
+static struct PyMethodDef bpygwn_VertBatch_methods[] = {
+ {"vertbuf_add", (PyCFunction)bpygwn_VertBatch_vertbuf_add,
+ METH_O, bpygwn_VertBatch_vertbuf_add_doc},
+ {"program_set_builtin", (PyCFunction)bpygwn_VertBatch_program_set_builtin,
+ METH_VARARGS | METH_KEYWORDS, bpygwn_VertBatch_program_set_builtin_doc},
+ {"uniform_bool", (PyCFunction)bpygwn_VertBatch_uniform_bool,
+ METH_VARARGS, NULL},
+ {"uniform_i32", (PyCFunction)bpygwn_VertBatch_uniform_i32,
+ METH_VARARGS, NULL},
+ {"uniform_f32", (PyCFunction)bpygwn_VertBatch_uniform_f32,
+ METH_VARARGS, NULL},
+ {"draw", (PyCFunction) bpygwn_VertBatch_draw,
+ METH_NOARGS, bpygwn_VertBatch_draw_doc},
+ {"program_use_begin", (PyCFunction)bpygwn_VertBatch_program_use_begin,
+ METH_NOARGS, ""},
+ {"program_use_end", (PyCFunction)bpygwn_VertBatch_program_use_end,
+ METH_NOARGS, ""},
+ {NULL, NULL, 0, NULL}
+};
+
+#ifdef USE_GWN_PY_REFERENCES
+
+static int bpygwn_Batch_traverse(BPyGwn_Batch *self, visitproc visit, void *arg)
+{
+ Py_VISIT(self->references);
+ return 0;
+}
+
+static int bpygwn_Batch_clear(BPyGwn_Batch *self)
+{
+ Py_CLEAR(self->references);
+ return 0;
+}
+
+#endif
+
+static void bpygwn_Batch_dealloc(BPyGwn_Batch *self)
+{
+ GWN_batch_discard(self->batch);
+
+#ifdef USE_GWN_PY_REFERENCES
+ if (self->references) {
+ PyObject_GC_UnTrack(self);
+ bpygwn_Batch_clear(self);
+ Py_XDECREF(self->references);
+ }
+#endif
+
+ Py_TYPE(self)->tp_free(self);
+}
+
+PyTypeObject BPyGwn_Batch_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "Gwn_Batch",
+ .tp_basicsize = sizeof(BPyGwn_Batch),
+ .tp_dealloc = (destructor)bpygwn_Batch_dealloc,
+#ifdef USE_GWN_PY_REFERENCES
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
+ .tp_traverse = (traverseproc)bpygwn_Batch_traverse,
+ .tp_clear = (inquiry)bpygwn_Batch_clear,
+#else
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+#endif
+ .tp_methods = bpygwn_VertBatch_methods,
+ .tp_new = bpygwn_Batch_new,
+};
+
+/* -------------------------------------------------------------------- */
+
+
+/** \name Gawain Types Module
+ * \{ */
+
+static struct PyModuleDef BPy_BM_types_module_def = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "_gawain.types",
+};
+
+PyObject *BPyInit_gawain_types(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&BPy_BM_types_module_def);
+
+ if (PyType_Ready(&BPyGwn_VertFormat_Type) < 0)
+ return NULL;
+ if (PyType_Ready(&BPyGwn_VertBuf_Type) < 0)
+ return NULL;
+ if (PyType_Ready(&BPyGwn_Batch_Type) < 0)
+ return NULL;
+
+#define MODULE_TYPE_ADD(s, t) \
+ PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
+
+ MODULE_TYPE_ADD(submodule, BPyGwn_VertFormat_Type);
+ MODULE_TYPE_ADD(submodule, BPyGwn_VertBuf_Type);
+ MODULE_TYPE_ADD(submodule, BPyGwn_Batch_Type);
+
+#undef MODULE_TYPE_ADD
+
+ return submodule;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Public API
+ * \{ */
+
+PyObject *BPyGwn_VertFormat_CreatePyObject(Gwn_VertFormat *fmt)
+{
+ BPyGwn_VertFormat *self;
+
+ self = PyObject_New(BPyGwn_VertFormat, &BPyGwn_VertFormat_Type);
+ if (fmt) {
+ self->fmt = *fmt;
+ }
+ else {
+ memset(&self->fmt, 0, sizeof(self->fmt));
+ }
+
+ return (PyObject *)self;
+}
+
+PyObject *BPyGwn_VertBuf_CreatePyObject(Gwn_VertBuf *buf)
+{
+ BPyGwn_VertBuf *self;
+
+ self = PyObject_New(BPyGwn_VertBuf, &BPyGwn_VertBuf_Type);
+ self->buf = buf;
+
+ return (PyObject *)self;
+}
+
+
+PyObject *BPyGwn_Batch_CreatePyObject(Gwn_Batch *batch)
+{
+ BPyGwn_Batch *self;
+
+#ifdef USE_GWN_PY_REFERENCES
+ self = (BPyGwn_Batch *)_PyObject_GC_New(&BPyGwn_Batch_Type);
+ self->references = NULL;
+#else
+ self = PyObject_New(BPyGwn_Batch, &BPyGwn_Batch_Type);
+#endif
+
+ self->batch = batch;
+
+ return (PyObject *)self;
+}
+
+/** \} */
diff --git a/source/blender/python/gawain/gwn_py_types.h b/source/blender/python/gawain/gwn_py_types.h
new file mode 100644
index 00000000000..dde6cf98827
--- /dev/null
+++ b/source/blender/python/gawain/gwn_py_types.h
@@ -0,0 +1,67 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/gawain/gwn_py_types.h
+ * \ingroup pygawain
+ */
+
+#ifndef __GWN_PY_TYPES_H__
+#define __GWN_PY_TYPES_H__
+
+#include "BLI_compiler_attrs.h"
+
+#define USE_GWN_PY_REFERENCES
+
+extern PyTypeObject BPyGwn_VertFormat_Type;
+extern PyTypeObject BPyGwn_VertBuf_Type;
+extern PyTypeObject BPyGwn_Batch_Type;
+
+#define BPyGwn_VertFormat_Check(v) (Py_TYPE(v) == &BPyGwn_VertFormat_Type)
+#define BPyGwn_VertBuf_Check(v) (Py_TYPE(v) == &BPyGwn_VertBuf_Type)
+#define BPyGwn_Batch_Check(v) (Py_TYPE(v) == &BPyGwn_Batch_Type)
+
+typedef struct BPyGwn_VertFormat {
+ PyObject_VAR_HEAD
+ struct Gwn_VertFormat fmt;
+} BPyGwn_VertFormat;
+
+typedef struct BPyGwn_VertBuf {
+ PyObject_VAR_HEAD
+ /* The buf is owned, we may support thin wrapped batches later. */
+ struct Gwn_VertBuf *buf;
+} BPyGwn_VertBuf;
+
+typedef struct BPyGwn_Batch {
+ PyObject_VAR_HEAD
+ /* The batch is owned, we may support thin wrapped batches later. */
+ struct Gwn_Batch *batch;
+#ifdef USE_GWN_PY_REFERENCES
+ /* Just to keep a user to prevent freeing buf's we're using */
+ PyObject *references;
+#endif
+} BPyGwn_Batch;
+
+PyObject *BPyInit_gawain_types(void);
+
+PyObject *BPyGwn_VertFormat_CreatePyObject(struct Gwn_VertFormat *fmt);
+PyObject *BPyGwn_VertBuf_CreatePyObject(struct Gwn_VertBuf *vbo) ATTR_NONNULL(1);
+PyObject *BPyGwn_Batch_CreatePyObject(struct Gwn_Batch *batch) ATTR_NONNULL(1);
+
+#endif /* __GWN_PY_TYPES_H__ */
diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c
index 072021c6ac9..827b69f5403 100644
--- a/source/blender/python/generic/bgl.c
+++ b/source/blender/python/generic/bgl.c
@@ -185,11 +185,13 @@
#define GLbitfield_ref(num) &bgl_var##num
#define GLbitfield_def(num) /* unsigned */ int GLbitfield_var(num)
+#if 0
/* typedef signed char GLbyte; */
#define GLbyte_str "b"
#define GLbyte_var(num) bgl_var##num
#define GLbyte_ref(num) &bgl_var##num
#define GLbyte_def(num) signed char GLbyte_var(num)
+#endif
/* typedef short GLshort; */
#define GLshort_str "h"
@@ -227,11 +229,13 @@
#define GLubyte_ref(num) &bgl_var##num
#define GLubyte_def(num) /* unsigned */ char GLubyte_var(num)
+#if 0
/* typedef unsigned short GLushort; */
#define GLushort_str "H"
#define GLushort_var(num) bgl_var##num
#define GLushort_ref(num) &bgl_var##num
#define GLushort_def(num) /* unsigned */ short GLushort_var(num)
+#endif
/* typedef unsigned int GLuint; */
#define GLuint_str "I"
@@ -1073,358 +1077,71 @@ static PyObject *Method_##funcname (PyObject *UNUSED(self), PyObject *args) \
ret_ret_##ret; \
}
-#define BGLU_Wrap(funcname, ret, arg_list) \
-static PyObject *Method_##funcname (PyObject *UNUSED(self), PyObject *args) \
-{ \
- arg_def arg_list; \
- ret_def_##ret; \
- if (!PyArg_ParseTuple(args, arg_str arg_list, arg_ref arg_list)) { \
- return NULL; \
- } \
- ret_set_##ret glu##funcname (arg_var arg_list); \
- ret_ret_##ret; \
-}
-
/* GL_VERSION_1_0 */
-BGL_Wrap(Accum, void, (GLenum, GLfloat))
-BGL_Wrap(AlphaFunc, void, (GLenum, GLfloat))
-BGL_Wrap(Begin, void, (GLenum))
-BGL_Wrap(Bitmap, void, (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat, GLubyteP))
BGL_Wrap(BlendFunc, void, (GLenum, GLenum))
-BGL_Wrap(CallList, void, (GLuint))
-BGL_Wrap(CallLists, void, (GLsizei, GLenum, GLvoidP))
BGL_Wrap(Clear, void, (GLbitfield))
-BGL_Wrap(ClearAccum, void, (GLfloat, GLfloat, GLfloat, GLfloat))
BGL_Wrap(ClearColor, void, (GLfloat, GLfloat, GLfloat, GLfloat))
BGL_Wrap(ClearDepth, void, (GLdouble))
-BGL_Wrap(ClearIndex, void, (GLfloat))
BGL_Wrap(ClearStencil, void, (GLint))
-BGL_Wrap(ClipPlane, void, (GLenum, GLdoubleP))
-BGL_Wrap(Color3b, void, (GLbyte, GLbyte, GLbyte))
-BGL_Wrap(Color3bv, void, (GLbyteP))
-BGL_Wrap(Color3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Color3dv, void, (GLdoubleP))
-BGL_Wrap(Color3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Color3fv, void, (GLfloatP))
-BGL_Wrap(Color3i, void, (GLint, GLint, GLint))
-BGL_Wrap(Color3iv, void, (GLintP))
-BGL_Wrap(Color3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(Color3sv, void, (GLshortP))
-BGL_Wrap(Color3ub, void, (GLubyte, GLubyte, GLubyte))
-BGL_Wrap(Color3ubv, void, (GLubyteP))
-BGL_Wrap(Color3ui, void, (GLuint, GLuint, GLuint))
-BGL_Wrap(Color3uiv, void, (GLuintP))
-BGL_Wrap(Color3us, void, (GLushort, GLushort, GLushort))
-BGL_Wrap(Color3usv, void, (GLushortP))
-BGL_Wrap(Color4b, void, (GLbyte, GLbyte, GLbyte, GLbyte))
-BGL_Wrap(Color4bv, void, (GLbyteP))
-BGL_Wrap(Color4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Color4dv, void, (GLdoubleP))
-BGL_Wrap(Color4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Color4fv, void, (GLfloatP))
-BGL_Wrap(Color4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(Color4iv, void, (GLintP))
-BGL_Wrap(Color4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(Color4sv, void, (GLshortP))
-BGL_Wrap(Color4ub, void, (GLubyte, GLubyte, GLubyte, GLubyte))
-BGL_Wrap(Color4ubv, void, (GLubyteP))
-BGL_Wrap(Color4ui, void, (GLuint, GLuint, GLuint, GLuint))
-BGL_Wrap(Color4uiv, void, (GLuintP))
-BGL_Wrap(Color4us, void, (GLushort, GLushort, GLushort, GLushort))
-BGL_Wrap(Color4usv, void, (GLushortP))
BGL_Wrap(ColorMask, void, (GLboolean, GLboolean, GLboolean, GLboolean))
-BGL_Wrap(ColorMaterial, void, (GLenum, GLenum))
-BGL_Wrap(CopyPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum))
BGL_Wrap(CullFace, void, (GLenum))
-BGL_Wrap(DeleteLists, void, (GLuint, GLsizei))
BGL_Wrap(DepthFunc, void, (GLenum))
BGL_Wrap(DepthMask, void, (GLboolean))
BGL_Wrap(DepthRange, void, (GLdouble, GLdouble))
BGL_Wrap(Disable, void, (GLenum))
BGL_Wrap(DrawBuffer, void, (GLenum))
-BGL_Wrap(DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(EdgeFlag, void, (GLboolean))
-BGL_Wrap(EdgeFlagv, void, (GLbooleanP))
BGL_Wrap(Enable, void, (GLenum))
-BGL_Wrap(End, void, (void))
-BGL_Wrap(EndList, void, (void))
-BGL_Wrap(EvalCoord1d, void, (GLdouble))
-BGL_Wrap(EvalCoord1dv, void, (GLdoubleP))
-BGL_Wrap(EvalCoord1f, void, (GLfloat))
-BGL_Wrap(EvalCoord1fv, void, (GLfloatP))
-BGL_Wrap(EvalCoord2d, void, (GLdouble, GLdouble))
-BGL_Wrap(EvalCoord2dv, void, (GLdoubleP))
-BGL_Wrap(EvalCoord2f, void, (GLfloat, GLfloat))
-BGL_Wrap(EvalCoord2fv, void, (GLfloatP))
-BGL_Wrap(EvalMesh1, void, (GLenum, GLint, GLint))
-BGL_Wrap(EvalMesh2, void, (GLenum, GLint, GLint, GLint, GLint))
-BGL_Wrap(EvalPoint1, void, (GLint))
-BGL_Wrap(EvalPoint2, void, (GLint, GLint))
-BGL_Wrap(FeedbackBuffer, void, (GLsizei, GLenum, GLfloatP))
BGL_Wrap(Finish, void, (void))
BGL_Wrap(Flush, void, (void))
-BGL_Wrap(Fogf, void, (GLenum, GLfloat))
-BGL_Wrap(Fogfv, void, (GLenum, GLfloatP))
-BGL_Wrap(Fogi, void, (GLenum, GLint))
-BGL_Wrap(Fogiv, void, (GLenum, GLintP))
BGL_Wrap(FrontFace, void, (GLenum))
-BGL_Wrap(Frustum, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(GenLists, GLuint, (GLsizei))
BGL_Wrap(GetBooleanv, void, (GLenum, GLbooleanP))
-BGL_Wrap(GetClipPlane, void, (GLenum, GLdoubleP))
BGL_Wrap(GetDoublev, void, (GLenum, GLdoubleP))
BGL_Wrap(GetError, GLenum, (void))
BGL_Wrap(GetFloatv, void, (GLenum, GLfloatP))
BGL_Wrap(GetIntegerv, void, (GLenum, GLintP))
-BGL_Wrap(GetLightfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetLightiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetMapdv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(GetMapfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetMapiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetMaterialfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetMaterialiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetPixelMapfv, void, (GLenum, GLfloatP))
-BGL_Wrap(GetPixelMapuiv, void, (GLenum, GLuintP))
-BGL_Wrap(GetPixelMapusv, void, (GLenum, GLushortP))
-BGL_Wrap(GetPolygonStipple, void, (GLubyteP))
BGL_Wrap(GetString, GLstring, (GLenum))
-BGL_Wrap(GetTexEnvfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetTexEnviv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetTexGendv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(GetTexGenfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetTexGeniv, void, (GLenum, GLenum, GLintP))
BGL_Wrap(GetTexImage, void, (GLenum, GLint, GLenum, GLenum, GLvoidP))
BGL_Wrap(GetTexLevelParameterfv, void, (GLenum, GLint, GLenum, GLfloatP))
BGL_Wrap(GetTexLevelParameteriv, void, (GLenum, GLint, GLenum, GLintP))
BGL_Wrap(GetTexParameterfv, void, (GLenum, GLenum, GLfloatP))
BGL_Wrap(GetTexParameteriv, void, (GLenum, GLenum, GLintP))
BGL_Wrap(Hint, void, (GLenum, GLenum))
-BGL_Wrap(IndexMask, void, (GLuint))
-BGL_Wrap(Indexd, void, (GLdouble))
-BGL_Wrap(Indexdv, void, (GLdoubleP))
-BGL_Wrap(Indexf, void, (GLfloat))
-BGL_Wrap(Indexfv, void, (GLfloatP))
-BGL_Wrap(Indexi, void, (GLint))
-BGL_Wrap(Indexiv, void, (GLintP))
-BGL_Wrap(Indexs, void, (GLshort))
-BGL_Wrap(Indexsv, void, (GLshortP))
-BGL_Wrap(InitNames, void, (void))
BGL_Wrap(IsEnabled, GLboolean, (GLenum))
-BGL_Wrap(IsList, GLboolean, (GLuint))
-BGL_Wrap(LightModelf, void, (GLenum, GLfloat))
-BGL_Wrap(LightModelfv, void, (GLenum, GLfloatP))
-BGL_Wrap(LightModeli, void, (GLenum, GLint))
-BGL_Wrap(LightModeliv, void, (GLenum, GLintP))
-BGL_Wrap(Lightf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(Lightfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(Lighti, void, (GLenum, GLenum, GLint))
-BGL_Wrap(Lightiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(LineStipple, void, (GLint, GLushort))
BGL_Wrap(LineWidth, void, (GLfloat))
-BGL_Wrap(ListBase, void, (GLuint))
-BGL_Wrap(LoadIdentity, void, (void))
-BGL_Wrap(LoadMatrixd, void, (GLdoubleP))
-BGL_Wrap(LoadMatrixf, void, (GLfloatP))
-BGL_Wrap(LoadName, void, (GLuint))
BGL_Wrap(LogicOp, void, (GLenum))
-BGL_Wrap(Map1d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
-BGL_Wrap(Map1f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloatP))
-BGL_Wrap(Map2d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
-BGL_Wrap(Map2f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloatP))
-BGL_Wrap(MapGrid1d, void, (GLint, GLdouble, GLdouble))
-BGL_Wrap(MapGrid1f, void, (GLint, GLfloat, GLfloat))
-BGL_Wrap(MapGrid2d, void, (GLint, GLdouble, GLdouble, GLint, GLdouble, GLdouble))
-BGL_Wrap(MapGrid2f, void, (GLint, GLfloat, GLfloat, GLint, GLfloat, GLfloat))
-BGL_Wrap(Materialf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(Materialfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(Materiali, void, (GLenum, GLenum, GLint))
-BGL_Wrap(Materialiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(MatrixMode, void, (GLenum))
-BGL_Wrap(MultMatrixd, void, (GLdoubleP))
-BGL_Wrap(MultMatrixf, void, (GLfloatP))
-BGL_Wrap(NewList, void, (GLuint, GLenum))
-BGL_Wrap(Normal3b, void, (GLbyte, GLbyte, GLbyte))
-BGL_Wrap(Normal3bv, void, (GLbyteP))
-BGL_Wrap(Normal3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Normal3dv, void, (GLdoubleP))
-BGL_Wrap(Normal3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Normal3fv, void, (GLfloatP))
-BGL_Wrap(Normal3i, void, (GLint, GLint, GLint))
-BGL_Wrap(Normal3iv, void, (GLintP))
-BGL_Wrap(Normal3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(Normal3sv, void, (GLshortP))
-BGL_Wrap(Ortho, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(PassThrough, void, (GLfloat))
-BGL_Wrap(PixelMapfv, void, (GLenum, GLsizei, GLfloatP))
-BGL_Wrap(PixelMapuiv, void, (GLenum, GLsizei, GLuintP))
-BGL_Wrap(PixelMapusv, void, (GLenum, GLsizei, GLushortP))
BGL_Wrap(PixelStoref, void, (GLenum, GLfloat))
BGL_Wrap(PixelStorei, void, (GLenum, GLint))
-BGL_Wrap(PixelTransferf, void, (GLenum, GLfloat))
-BGL_Wrap(PixelTransferi, void, (GLenum, GLint))
-BGL_Wrap(PixelZoom, void, (GLfloat, GLfloat))
BGL_Wrap(PointSize, void, (GLfloat))
BGL_Wrap(PolygonMode, void, (GLenum, GLenum))
-BGL_Wrap(PolygonStipple, void, (GLubyteP))
-BGL_Wrap(PopAttrib, void, (void))
-BGL_Wrap(PopMatrix, void, (void))
-BGL_Wrap(PopName, void, (void))
-BGL_Wrap(PushAttrib, void, (GLbitfield))
-BGL_Wrap(PushMatrix, void, (void))
-BGL_Wrap(PushName, void, (GLuint))
-BGL_Wrap(RasterPos2d, void, (GLdouble, GLdouble))
-BGL_Wrap(RasterPos2dv, void, (GLdoubleP))
-BGL_Wrap(RasterPos2f, void, (GLfloat, GLfloat))
-BGL_Wrap(RasterPos2fv, void, (GLfloatP))
-BGL_Wrap(RasterPos2i, void, (GLint, GLint))
-BGL_Wrap(RasterPos2iv, void, (GLintP))
-BGL_Wrap(RasterPos2s, void, (GLshort, GLshort))
-BGL_Wrap(RasterPos2sv, void, (GLshortP))
-BGL_Wrap(RasterPos3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(RasterPos3dv, void, (GLdoubleP))
-BGL_Wrap(RasterPos3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(RasterPos3fv, void, (GLfloatP))
-BGL_Wrap(RasterPos3i, void, (GLint, GLint, GLint))
-BGL_Wrap(RasterPos3iv, void, (GLintP))
-BGL_Wrap(RasterPos3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(RasterPos3sv, void, (GLshortP))
-BGL_Wrap(RasterPos4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(RasterPos4dv, void, (GLdoubleP))
-BGL_Wrap(RasterPos4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(RasterPos4fv, void, (GLfloatP))
-BGL_Wrap(RasterPos4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(RasterPos4iv, void, (GLintP))
-BGL_Wrap(RasterPos4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(RasterPos4sv, void, (GLshortP))
BGL_Wrap(ReadBuffer, void, (GLenum))
BGL_Wrap(ReadPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(Rectd, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Rectdv, void, (GLdoubleP, GLdoubleP))
-BGL_Wrap(Rectf, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Rectfv, void, (GLfloatP, GLfloatP))
-BGL_Wrap(Recti, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(Rectiv, void, (GLintP, GLintP))
-BGL_Wrap(Rects, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(Rectsv, void, (GLshortP, GLshortP))
-BGL_Wrap(RenderMode, GLint, (GLenum))
-BGL_Wrap(Rotated, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Rotatef, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Scaled, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Scalef, void, (GLfloat, GLfloat, GLfloat))
BGL_Wrap(Scissor, void, (GLint, GLint, GLsizei, GLsizei))
-BGL_Wrap(SelectBuffer, void, (GLsizei, GLuintP))
-BGL_Wrap(ShadeModel, void, (GLenum))
BGL_Wrap(StencilFunc, void, (GLenum, GLint, GLuint))
BGL_Wrap(StencilMask, void, (GLuint))
BGL_Wrap(StencilOp, void, (GLenum, GLenum, GLenum))
-BGL_Wrap(TexCoord1d, void, (GLdouble))
-BGL_Wrap(TexCoord1dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord1f, void, (GLfloat))
-BGL_Wrap(TexCoord1fv, void, (GLfloatP))
-BGL_Wrap(TexCoord1i, void, (GLint))
-BGL_Wrap(TexCoord1iv, void, (GLintP))
-BGL_Wrap(TexCoord1s, void, (GLshort))
-BGL_Wrap(TexCoord1sv, void, (GLshortP))
-BGL_Wrap(TexCoord2d, void, (GLdouble, GLdouble))
-BGL_Wrap(TexCoord2dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord2f, void, (GLfloat, GLfloat))
-BGL_Wrap(TexCoord2fv, void, (GLfloatP))
-BGL_Wrap(TexCoord2i, void, (GLint, GLint))
-BGL_Wrap(TexCoord2iv, void, (GLintP))
-BGL_Wrap(TexCoord2s, void, (GLshort, GLshort))
-BGL_Wrap(TexCoord2sv, void, (GLshortP))
-BGL_Wrap(TexCoord3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(TexCoord3dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(TexCoord3fv, void, (GLfloatP))
-BGL_Wrap(TexCoord3i, void, (GLint, GLint, GLint))
-BGL_Wrap(TexCoord3iv, void, (GLintP))
-BGL_Wrap(TexCoord3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(TexCoord3sv, void, (GLshortP))
-BGL_Wrap(TexCoord4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(TexCoord4dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(TexCoord4fv, void, (GLfloatP))
-BGL_Wrap(TexCoord4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(TexCoord4iv, void, (GLintP))
-BGL_Wrap(TexCoord4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(TexCoord4sv, void, (GLshortP))
-BGL_Wrap(TexEnvf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(TexEnvfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(TexEnvi, void, (GLenum, GLenum, GLint))
-BGL_Wrap(TexEnviv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(TexGend, void, (GLenum, GLenum, GLdouble))
-BGL_Wrap(TexGendv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(TexGenf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(TexGenfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(TexGeni, void, (GLenum, GLenum, GLint))
-BGL_Wrap(TexGeniv, void, (GLenum, GLenum, GLintP))
BGL_Wrap(TexImage1D, void, (GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, GLvoidP))
BGL_Wrap(TexImage2D, void, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP))
BGL_Wrap(TexParameterf, void, (GLenum, GLenum, GLfloat))
BGL_Wrap(TexParameterfv, void, (GLenum, GLenum, GLfloatP))
BGL_Wrap(TexParameteri, void, (GLenum, GLenum, GLint))
BGL_Wrap(TexParameteriv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(Translated, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Translatef, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Vertex2d, void, (GLdouble, GLdouble))
-BGL_Wrap(Vertex2dv, void, (GLdoubleP))
-BGL_Wrap(Vertex2f, void, (GLfloat, GLfloat))
-BGL_Wrap(Vertex2fv, void, (GLfloatP))
-BGL_Wrap(Vertex2i, void, (GLint, GLint))
-BGL_Wrap(Vertex2iv, void, (GLintP))
-BGL_Wrap(Vertex2s, void, (GLshort, GLshort))
-BGL_Wrap(Vertex2sv, void, (GLshortP))
-BGL_Wrap(Vertex3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Vertex3dv, void, (GLdoubleP))
-BGL_Wrap(Vertex3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Vertex3fv, void, (GLfloatP))
-BGL_Wrap(Vertex3i, void, (GLint, GLint, GLint))
-BGL_Wrap(Vertex3iv, void, (GLintP))
-BGL_Wrap(Vertex3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(Vertex3sv, void, (GLshortP))
-BGL_Wrap(Vertex4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Vertex4dv, void, (GLdoubleP))
-BGL_Wrap(Vertex4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Vertex4fv, void, (GLfloatP))
-BGL_Wrap(Vertex4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(Vertex4iv, void, (GLintP))
-BGL_Wrap(Vertex4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(Vertex4sv, void, (GLshortP))
BGL_Wrap(Viewport, void, (GLint, GLint, GLsizei, GLsizei))
/* GL_VERSION_1_1 */
-BGL_Wrap(AreTexturesResident, GLboolean, (GLsizei, GLuintP, GLbooleanP))
-BGL_Wrap(ArrayElement, void, (GLint))
BGL_Wrap(BindTexture, void, (GLenum, GLuint))
-BGL_Wrap(ColorPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
BGL_Wrap(CopyTexImage1D, void, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint))
BGL_Wrap(CopyTexImage2D, void, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint))
BGL_Wrap(CopyTexSubImage1D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei))
BGL_Wrap(CopyTexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei))
BGL_Wrap(DeleteTextures, void, (GLsizei, GLuintP))
-BGL_Wrap(DisableClientState, void, (GLenum))
BGL_Wrap(DrawArrays, void, (GLenum, GLint, GLsizei))
BGL_Wrap(DrawElements, void, (GLenum, GLsizei, GLenum, GLvoidP))
-BGL_Wrap(EdgeFlagPointer, void, (GLsizei, GLvoidP))
-BGL_Wrap(EnableClientState, void, (GLenum))
BGL_Wrap(GenTextures, void, (GLsizei, GLuintP))
-BGL_Wrap(GetPointerv, void, (GLenum, GLvoidP))
-BGL_Wrap(IndexPointer, void, (GLenum, GLsizei, GLvoidP))
-BGL_Wrap(Indexub, void, (GLubyte))
-BGL_Wrap(Indexubv, void, (GLubyteP))
-BGL_Wrap(InterleavedArrays, void, (GLenum, GLsizei, GLvoidP))
BGL_Wrap(IsTexture, GLboolean, (GLuint))
-BGL_Wrap(NormalPointer, void, (GLenum, GLsizei, GLvoidP))
BGL_Wrap(PolygonOffset, void, (GLfloat, GLfloat))
-BGL_Wrap(PopClientAttrib, void, (void))
-BGL_Wrap(PrioritizeTextures, void, (GLsizei, GLuintP, GLfloatP))
-BGL_Wrap(PushClientAttrib, void, (GLbitfield))
-BGL_Wrap(TexCoordPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
BGL_Wrap(TexSubImage1D, void, (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, GLvoidP))
BGL_Wrap(TexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(VertexPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
/* GL_VERSION_1_2 */
@@ -1436,7 +1153,6 @@ BGL_Wrap(TexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLi
/* GL_VERSION_1_3 */
BGL_Wrap(ActiveTexture, void, (GLenum))
-BGL_Wrap(ClientActiveTexture, void, (GLenum))
BGL_Wrap(CompressedTexImage1D, void, (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, GLvoidP))
BGL_Wrap(CompressedTexImage2D, void, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, GLvoidP))
BGL_Wrap(CompressedTexImage3D, void, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, GLvoidP))
@@ -1444,42 +1160,6 @@ BGL_Wrap(CompressedTexSubImage1D, void, (GLenum, GLint, GLint, GLsizei, G
BGL_Wrap(CompressedTexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, GLvoidP))
BGL_Wrap(CompressedTexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, GLvoidP))
BGL_Wrap(GetCompressedTexImage, void, (GLenum, GLint, GLvoidP))
-BGL_Wrap(LoadTransposeMatrixd, void, (GLdoubleP))
-BGL_Wrap(LoadTransposeMatrixf, void, (GLfloatP))
-BGL_Wrap(MultTransposeMatrixd, void, (GLdoubleP))
-BGL_Wrap(MultTransposeMatrixf, void, (GLfloatP))
-BGL_Wrap(MultiTexCoord1d, void, (GLenum, GLdouble))
-BGL_Wrap(MultiTexCoord1dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord1f, void, (GLenum, GLfloat))
-BGL_Wrap(MultiTexCoord1fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord1i, void, (GLenum, GLint))
-BGL_Wrap(MultiTexCoord1iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord1s, void, (GLenum, GLshort))
-BGL_Wrap(MultiTexCoord1sv, void, (GLenum, GLshortP))
-BGL_Wrap(MultiTexCoord2d, void, (GLenum, GLdouble, GLdouble))
-BGL_Wrap(MultiTexCoord2dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord2f, void, (GLenum, GLfloat, GLfloat))
-BGL_Wrap(MultiTexCoord2fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord2i, void, (GLenum, GLint, GLint))
-BGL_Wrap(MultiTexCoord2iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord2s, void, (GLenum, GLshort, GLshort))
-BGL_Wrap(MultiTexCoord2sv, void, (GLenum, GLshortP))
-BGL_Wrap(MultiTexCoord3d, void, (GLenum, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(MultiTexCoord3dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord3f, void, (GLenum, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(MultiTexCoord3fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord3i, void, (GLenum, GLint, GLint, GLint))
-BGL_Wrap(MultiTexCoord3iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord3s, void, (GLenum, GLshort, GLshort, GLshort))
-BGL_Wrap(MultiTexCoord3sv, void, (GLenum, GLshortP))
-BGL_Wrap(MultiTexCoord4d, void, (GLenum, GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(MultiTexCoord4dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord4f, void, (GLenum, GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(MultiTexCoord4fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord4i, void, (GLenum, GLint, GLint, GLint, GLint))
-BGL_Wrap(MultiTexCoord4iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord4s, void, (GLenum, GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(MultiTexCoord4sv, void, (GLenum, GLshortP))
BGL_Wrap(SampleCoverage, void, (GLfloat, GLboolean))
@@ -1618,6 +1298,7 @@ BGL_Wrap(UniformMatrix4x3fv, void, (GLint, GLsizei, GLboolean, GLflo
BGL_Wrap(BindVertexArray, void, (GLuint))
BGL_Wrap(DeleteVertexArrays, void, (GLsizei, GLuintP))
BGL_Wrap(GenVertexArrays, void, (GLsizei, GLuintP))
+BGL_Wrap(GetStringi, GLstring, (GLenum, GLuint))
BGL_Wrap(IsVertexArray, GLboolean, (GLuint))
@@ -1645,44 +1326,7 @@ BGL_Wrap(TexImage3DMultisample, void, (GLenum, GLsizei, GLenum, GLsizei
/* GL_VERSION_3_3 */
-BGL_Wrap(ColorP3ui, void, (GLenum, GLuint))
-BGL_Wrap(ColorP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(ColorP4ui, void, (GLenum, GLuint))
-BGL_Wrap(ColorP4uiv, void, (GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP1ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP1uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP2ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP2uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP3ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP3uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP4ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP4uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(NormalP3ui, void, (GLenum, GLuint))
-BGL_Wrap(NormalP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(SecondaryColorP3ui, void, (GLenum, GLuint))
-BGL_Wrap(SecondaryColorP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP1ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP1uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP2ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP2uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP3ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP4ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP4uiv, void, (GLenum, GLuintP))
-BGL_Wrap(VertexP2ui, void, (GLenum, GLuint))
-BGL_Wrap(VertexP2uiv, void, (GLenum, GLuintP))
-BGL_Wrap(VertexP3ui, void, (GLenum, GLuint))
-BGL_Wrap(VertexP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(VertexP4ui, void, (GLenum, GLuint))
-BGL_Wrap(VertexP4uiv, void, (GLenum, GLuintP))
-
-
-BGLU_Wrap(Perspective, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(LookAt, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(Ortho2D, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(PickMatrix, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLintP))
-BGLU_Wrap(Project, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
-BGLU_Wrap(UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
+/* no new functions besides packed immediate mode (not part of core profile) */
/** \} */
@@ -1692,26 +1336,12 @@ BGLU_Wrap(UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdouble
/** \name Module Definition
* \{ */
-#define MethodDefu(func) {"glu"#func, Method_##func, METH_VARARGS, NULL}
-
-static struct PyMethodDef BGL_methods[] = {
- MethodDefu(Perspective),
- MethodDefu(LookAt),
- MethodDefu(Ortho2D),
- MethodDefu(PickMatrix),
- MethodDefu(Project),
- MethodDefu(UnProject),
- {NULL, NULL, 0, NULL}
-};
-
-#undef MethodDefu
-
static struct PyModuleDef BGL_module_def = {
PyModuleDef_HEAD_INIT,
"bgl", /* m_name */
NULL, /* m_doc */
0, /* m_size */
- BGL_methods, /* m_methods */
+ NULL, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
@@ -1745,9 +1375,6 @@ static void py_module_dict_add_method(PyObject *submodule, PyObject *dict, PyMet
}
}
-/* TODO, expose to users */
-static bool use_deprecated = true;
-
PyObject *BPyInit_bgl(void)
{
PyObject *submodule, *dict;
@@ -1822,268 +1449,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(TexParameteriv);
PY_MOD_ADD_METHOD(Viewport);
}
- /* adding in GL_VERSION_1_0 removed from core profile */
- if (use_deprecated == true) {
- PY_MOD_ADD_METHOD(Accum);
- PY_MOD_ADD_METHOD(AlphaFunc);
- PY_MOD_ADD_METHOD(Begin);
- PY_MOD_ADD_METHOD(Bitmap);
- PY_MOD_ADD_METHOD(CallList);
- PY_MOD_ADD_METHOD(CallLists);
- PY_MOD_ADD_METHOD(ClearAccum);
- PY_MOD_ADD_METHOD(ClearIndex);
- PY_MOD_ADD_METHOD(ClipPlane);
- PY_MOD_ADD_METHOD(Color3b);
- PY_MOD_ADD_METHOD(Color3bv);
- PY_MOD_ADD_METHOD(Color3d);
- PY_MOD_ADD_METHOD(Color3dv);
- PY_MOD_ADD_METHOD(Color3f);
- PY_MOD_ADD_METHOD(Color3fv);
- PY_MOD_ADD_METHOD(Color3i);
- PY_MOD_ADD_METHOD(Color3iv);
- PY_MOD_ADD_METHOD(Color3s);
- PY_MOD_ADD_METHOD(Color3sv);
- PY_MOD_ADD_METHOD(Color3ub);
- PY_MOD_ADD_METHOD(Color3ubv);
- PY_MOD_ADD_METHOD(Color3ui);
- PY_MOD_ADD_METHOD(Color3uiv);
- PY_MOD_ADD_METHOD(Color3us);
- PY_MOD_ADD_METHOD(Color3usv);
- PY_MOD_ADD_METHOD(Color4b);
- PY_MOD_ADD_METHOD(Color4bv);
- PY_MOD_ADD_METHOD(Color4d);
- PY_MOD_ADD_METHOD(Color4dv);
- PY_MOD_ADD_METHOD(Color4f);
- PY_MOD_ADD_METHOD(Color4fv);
- PY_MOD_ADD_METHOD(Color4i);
- PY_MOD_ADD_METHOD(Color4iv);
- PY_MOD_ADD_METHOD(Color4s);
- PY_MOD_ADD_METHOD(Color4sv);
- PY_MOD_ADD_METHOD(Color4ub);
- PY_MOD_ADD_METHOD(Color4ubv);
- PY_MOD_ADD_METHOD(Color4ui);
- PY_MOD_ADD_METHOD(Color4uiv);
- PY_MOD_ADD_METHOD(Color4us);
- PY_MOD_ADD_METHOD(Color4usv);
- PY_MOD_ADD_METHOD(ColorMaterial);
- PY_MOD_ADD_METHOD(CopyPixels);
- PY_MOD_ADD_METHOD(DeleteLists);
- PY_MOD_ADD_METHOD(DrawPixels);
- PY_MOD_ADD_METHOD(EdgeFlag);
- PY_MOD_ADD_METHOD(EdgeFlagv);
- PY_MOD_ADD_METHOD(End);
- PY_MOD_ADD_METHOD(EndList);
- PY_MOD_ADD_METHOD(EvalCoord1d);
- PY_MOD_ADD_METHOD(EvalCoord1dv);
- PY_MOD_ADD_METHOD(EvalCoord1f);
- PY_MOD_ADD_METHOD(EvalCoord1fv);
- PY_MOD_ADD_METHOD(EvalCoord2d);
- PY_MOD_ADD_METHOD(EvalCoord2dv);
- PY_MOD_ADD_METHOD(EvalCoord2f);
- PY_MOD_ADD_METHOD(EvalCoord2fv);
- PY_MOD_ADD_METHOD(EvalMesh1);
- PY_MOD_ADD_METHOD(EvalMesh2);
- PY_MOD_ADD_METHOD(EvalPoint1);
- PY_MOD_ADD_METHOD(EvalPoint2);
- PY_MOD_ADD_METHOD(FeedbackBuffer);
- PY_MOD_ADD_METHOD(Fogf);
- PY_MOD_ADD_METHOD(Fogfv);
- PY_MOD_ADD_METHOD(Fogi);
- PY_MOD_ADD_METHOD(Fogiv);
- PY_MOD_ADD_METHOD(Frustum);
- PY_MOD_ADD_METHOD(GenLists);
- PY_MOD_ADD_METHOD(GetClipPlane);
- PY_MOD_ADD_METHOD(GetLightfv);
- PY_MOD_ADD_METHOD(GetLightiv);
- PY_MOD_ADD_METHOD(GetMapdv);
- PY_MOD_ADD_METHOD(GetMapfv);
- PY_MOD_ADD_METHOD(GetMapiv);
- PY_MOD_ADD_METHOD(GetMaterialfv);
- PY_MOD_ADD_METHOD(GetMaterialiv);
- PY_MOD_ADD_METHOD(GetPixelMapfv);
- PY_MOD_ADD_METHOD(GetPixelMapuiv);
- PY_MOD_ADD_METHOD(GetPixelMapusv);
- PY_MOD_ADD_METHOD(GetPolygonStipple);
- PY_MOD_ADD_METHOD(GetTexEnvfv);
- PY_MOD_ADD_METHOD(GetTexEnviv);
- PY_MOD_ADD_METHOD(GetTexGendv);
- PY_MOD_ADD_METHOD(GetTexGenfv);
- PY_MOD_ADD_METHOD(GetTexGeniv);
- PY_MOD_ADD_METHOD(IndexMask);
- PY_MOD_ADD_METHOD(Indexd);
- PY_MOD_ADD_METHOD(Indexdv);
- PY_MOD_ADD_METHOD(Indexf);
- PY_MOD_ADD_METHOD(Indexfv);
- PY_MOD_ADD_METHOD(Indexi);
- PY_MOD_ADD_METHOD(Indexiv);
- PY_MOD_ADD_METHOD(Indexs);
- PY_MOD_ADD_METHOD(Indexsv);
- PY_MOD_ADD_METHOD(InitNames);
- PY_MOD_ADD_METHOD(IsList);
- PY_MOD_ADD_METHOD(LightModelf);
- PY_MOD_ADD_METHOD(LightModelfv);
- PY_MOD_ADD_METHOD(LightModeli);
- PY_MOD_ADD_METHOD(LightModeliv);
- PY_MOD_ADD_METHOD(Lightf);
- PY_MOD_ADD_METHOD(Lightfv);
- PY_MOD_ADD_METHOD(Lighti);
- PY_MOD_ADD_METHOD(Lightiv);
- PY_MOD_ADD_METHOD(LineStipple);
- PY_MOD_ADD_METHOD(ListBase);
- PY_MOD_ADD_METHOD(LoadIdentity);
- PY_MOD_ADD_METHOD(LoadMatrixd);
- PY_MOD_ADD_METHOD(LoadMatrixf);
- PY_MOD_ADD_METHOD(LoadName);
- PY_MOD_ADD_METHOD(Map1d);
- PY_MOD_ADD_METHOD(Map1f);
- PY_MOD_ADD_METHOD(Map2d);
- PY_MOD_ADD_METHOD(Map2f);
- PY_MOD_ADD_METHOD(MapGrid1d);
- PY_MOD_ADD_METHOD(MapGrid1f);
- PY_MOD_ADD_METHOD(MapGrid2d);
- PY_MOD_ADD_METHOD(MapGrid2f);
- PY_MOD_ADD_METHOD(Materialf);
- PY_MOD_ADD_METHOD(Materialfv);
- PY_MOD_ADD_METHOD(Materiali);
- PY_MOD_ADD_METHOD(Materialiv);
- PY_MOD_ADD_METHOD(MatrixMode);
- PY_MOD_ADD_METHOD(MultMatrixd);
- PY_MOD_ADD_METHOD(MultMatrixf);
- PY_MOD_ADD_METHOD(NewList);
- PY_MOD_ADD_METHOD(Normal3b);
- PY_MOD_ADD_METHOD(Normal3bv);
- PY_MOD_ADD_METHOD(Normal3d);
- PY_MOD_ADD_METHOD(Normal3dv);
- PY_MOD_ADD_METHOD(Normal3f);
- PY_MOD_ADD_METHOD(Normal3fv);
- PY_MOD_ADD_METHOD(Normal3i);
- PY_MOD_ADD_METHOD(Normal3iv);
- PY_MOD_ADD_METHOD(Normal3s);
- PY_MOD_ADD_METHOD(Normal3sv);
- PY_MOD_ADD_METHOD(Ortho);
- PY_MOD_ADD_METHOD(PassThrough);
- PY_MOD_ADD_METHOD(PixelMapfv);
- PY_MOD_ADD_METHOD(PixelMapuiv);
- PY_MOD_ADD_METHOD(PixelMapusv);
- PY_MOD_ADD_METHOD(PixelTransferf);
- PY_MOD_ADD_METHOD(PixelTransferi);
- PY_MOD_ADD_METHOD(PixelZoom);
- PY_MOD_ADD_METHOD(PolygonStipple);
- PY_MOD_ADD_METHOD(PopAttrib);
- PY_MOD_ADD_METHOD(PopMatrix);
- PY_MOD_ADD_METHOD(PopName);
- PY_MOD_ADD_METHOD(PushAttrib);
- PY_MOD_ADD_METHOD(PushMatrix);
- PY_MOD_ADD_METHOD(PushName);
- PY_MOD_ADD_METHOD(RasterPos2d);
- PY_MOD_ADD_METHOD(RasterPos2dv);
- PY_MOD_ADD_METHOD(RasterPos2f);
- PY_MOD_ADD_METHOD(RasterPos2fv);
- PY_MOD_ADD_METHOD(RasterPos2i);
- PY_MOD_ADD_METHOD(RasterPos2iv);
- PY_MOD_ADD_METHOD(RasterPos2s);
- PY_MOD_ADD_METHOD(RasterPos2sv);
- PY_MOD_ADD_METHOD(RasterPos3d);
- PY_MOD_ADD_METHOD(RasterPos3dv);
- PY_MOD_ADD_METHOD(RasterPos3f);
- PY_MOD_ADD_METHOD(RasterPos3fv);
- PY_MOD_ADD_METHOD(RasterPos3i);
- PY_MOD_ADD_METHOD(RasterPos3iv);
- PY_MOD_ADD_METHOD(RasterPos3s);
- PY_MOD_ADD_METHOD(RasterPos3sv);
- PY_MOD_ADD_METHOD(RasterPos4d);
- PY_MOD_ADD_METHOD(RasterPos4dv);
- PY_MOD_ADD_METHOD(RasterPos4f);
- PY_MOD_ADD_METHOD(RasterPos4fv);
- PY_MOD_ADD_METHOD(RasterPos4i);
- PY_MOD_ADD_METHOD(RasterPos4iv);
- PY_MOD_ADD_METHOD(RasterPos4s);
- PY_MOD_ADD_METHOD(RasterPos4sv);
- PY_MOD_ADD_METHOD(Rectd);
- PY_MOD_ADD_METHOD(Rectdv);
- PY_MOD_ADD_METHOD(Rectf);
- PY_MOD_ADD_METHOD(Rectfv);
- PY_MOD_ADD_METHOD(Recti);
- PY_MOD_ADD_METHOD(Rectiv);
- PY_MOD_ADD_METHOD(Rects);
- PY_MOD_ADD_METHOD(Rectsv);
- PY_MOD_ADD_METHOD(RenderMode);
- PY_MOD_ADD_METHOD(Rotated);
- PY_MOD_ADD_METHOD(Rotatef);
- PY_MOD_ADD_METHOD(Scaled);
- PY_MOD_ADD_METHOD(Scalef);
- PY_MOD_ADD_METHOD(SelectBuffer);
- PY_MOD_ADD_METHOD(ShadeModel);
- PY_MOD_ADD_METHOD(TexCoord1d);
- PY_MOD_ADD_METHOD(TexCoord1dv);
- PY_MOD_ADD_METHOD(TexCoord1f);
- PY_MOD_ADD_METHOD(TexCoord1fv);
- PY_MOD_ADD_METHOD(TexCoord1i);
- PY_MOD_ADD_METHOD(TexCoord1iv);
- PY_MOD_ADD_METHOD(TexCoord1s);
- PY_MOD_ADD_METHOD(TexCoord1sv);
- PY_MOD_ADD_METHOD(TexCoord2d);
- PY_MOD_ADD_METHOD(TexCoord2dv);
- PY_MOD_ADD_METHOD(TexCoord2f);
- PY_MOD_ADD_METHOD(TexCoord2fv);
- PY_MOD_ADD_METHOD(TexCoord2i);
- PY_MOD_ADD_METHOD(TexCoord2iv);
- PY_MOD_ADD_METHOD(TexCoord2s);
- PY_MOD_ADD_METHOD(TexCoord2sv);
- PY_MOD_ADD_METHOD(TexCoord3d);
- PY_MOD_ADD_METHOD(TexCoord3dv);
- PY_MOD_ADD_METHOD(TexCoord3f);
- PY_MOD_ADD_METHOD(TexCoord3fv);
- PY_MOD_ADD_METHOD(TexCoord3i);
- PY_MOD_ADD_METHOD(TexCoord3iv);
- PY_MOD_ADD_METHOD(TexCoord3s);
- PY_MOD_ADD_METHOD(TexCoord3sv);
- PY_MOD_ADD_METHOD(TexCoord4d);
- PY_MOD_ADD_METHOD(TexCoord4dv);
- PY_MOD_ADD_METHOD(TexCoord4f);
- PY_MOD_ADD_METHOD(TexCoord4fv);
- PY_MOD_ADD_METHOD(TexCoord4i);
- PY_MOD_ADD_METHOD(TexCoord4iv);
- PY_MOD_ADD_METHOD(TexCoord4s);
- PY_MOD_ADD_METHOD(TexCoord4sv);
- PY_MOD_ADD_METHOD(TexEnvf);
- PY_MOD_ADD_METHOD(TexEnvfv);
- PY_MOD_ADD_METHOD(TexEnvi);
- PY_MOD_ADD_METHOD(TexEnviv);
- PY_MOD_ADD_METHOD(TexGend);
- PY_MOD_ADD_METHOD(TexGendv);
- PY_MOD_ADD_METHOD(TexGenf);
- PY_MOD_ADD_METHOD(TexGenfv);
- PY_MOD_ADD_METHOD(TexGeni);
- PY_MOD_ADD_METHOD(TexGeniv);
- PY_MOD_ADD_METHOD(Translated);
- PY_MOD_ADD_METHOD(Translatef);
- PY_MOD_ADD_METHOD(Vertex2d);
- PY_MOD_ADD_METHOD(Vertex2dv);
- PY_MOD_ADD_METHOD(Vertex2f);
- PY_MOD_ADD_METHOD(Vertex2fv);
- PY_MOD_ADD_METHOD(Vertex2i);
- PY_MOD_ADD_METHOD(Vertex2iv);
- PY_MOD_ADD_METHOD(Vertex2s);
- PY_MOD_ADD_METHOD(Vertex2sv);
- PY_MOD_ADD_METHOD(Vertex3d);
- PY_MOD_ADD_METHOD(Vertex3dv);
- PY_MOD_ADD_METHOD(Vertex3f);
- PY_MOD_ADD_METHOD(Vertex3fv);
- PY_MOD_ADD_METHOD(Vertex3i);
- PY_MOD_ADD_METHOD(Vertex3iv);
- PY_MOD_ADD_METHOD(Vertex3s);
- PY_MOD_ADD_METHOD(Vertex3sv);
- PY_MOD_ADD_METHOD(Vertex4d);
- PY_MOD_ADD_METHOD(Vertex4dv);
- PY_MOD_ADD_METHOD(Vertex4f);
- PY_MOD_ADD_METHOD(Vertex4fv);
- PY_MOD_ADD_METHOD(Vertex4i);
- PY_MOD_ADD_METHOD(Vertex4iv);
- PY_MOD_ADD_METHOD(Vertex4s);
- PY_MOD_ADD_METHOD(Vertex4sv);
- }
-
/* GL_VERSION_1_1 */
{
@@ -2101,27 +1466,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(TexSubImage1D);
PY_MOD_ADD_METHOD(TexSubImage2D);
}
- /* adding in GL_VERSION_1_1 removed from core profile */
- if (use_deprecated == true) {
- PY_MOD_ADD_METHOD(AreTexturesResident);
- PY_MOD_ADD_METHOD(ArrayElement);
- PY_MOD_ADD_METHOD(ColorPointer);
- PY_MOD_ADD_METHOD(DisableClientState);
- PY_MOD_ADD_METHOD(EdgeFlagPointer);
- PY_MOD_ADD_METHOD(EnableClientState);
- PY_MOD_ADD_METHOD(GetPointerv);
- PY_MOD_ADD_METHOD(IndexPointer);
- PY_MOD_ADD_METHOD(Indexub);
- PY_MOD_ADD_METHOD(Indexubv);
- PY_MOD_ADD_METHOD(InterleavedArrays);
- PY_MOD_ADD_METHOD(NormalPointer);
- PY_MOD_ADD_METHOD(PopClientAttrib);
- PY_MOD_ADD_METHOD(PrioritizeTextures);
- PY_MOD_ADD_METHOD(PushClientAttrib);
- PY_MOD_ADD_METHOD(TexCoordPointer);
- PY_MOD_ADD_METHOD(VertexPointer);
- }
-
/* GL_VERSION_1_2 */
{
@@ -2131,7 +1475,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(TexSubImage3D);
}
-
/* GL_VERSION_1_3 */
{
PY_MOD_ADD_METHOD(ActiveTexture);
@@ -2144,47 +1487,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(GetCompressedTexImage);
PY_MOD_ADD_METHOD(SampleCoverage);
}
- /* adding in GL_VERSION_1_3 removed from core profile */
- if (use_deprecated == true) {
- PY_MOD_ADD_METHOD(ClientActiveTexture);
- PY_MOD_ADD_METHOD(LoadTransposeMatrixd);
- PY_MOD_ADD_METHOD(LoadTransposeMatrixf);
- PY_MOD_ADD_METHOD(MultTransposeMatrixd);
- PY_MOD_ADD_METHOD(MultTransposeMatrixf);
- PY_MOD_ADD_METHOD(MultiTexCoord1d);
- PY_MOD_ADD_METHOD(MultiTexCoord1dv);
- PY_MOD_ADD_METHOD(MultiTexCoord1f);
- PY_MOD_ADD_METHOD(MultiTexCoord1fv);
- PY_MOD_ADD_METHOD(MultiTexCoord1i);
- PY_MOD_ADD_METHOD(MultiTexCoord1iv);
- PY_MOD_ADD_METHOD(MultiTexCoord1s);
- PY_MOD_ADD_METHOD(MultiTexCoord1sv);
- PY_MOD_ADD_METHOD(MultiTexCoord2d);
- PY_MOD_ADD_METHOD(MultiTexCoord2dv);
- PY_MOD_ADD_METHOD(MultiTexCoord2f);
- PY_MOD_ADD_METHOD(MultiTexCoord2fv);
- PY_MOD_ADD_METHOD(MultiTexCoord2i);
- PY_MOD_ADD_METHOD(MultiTexCoord2iv);
- PY_MOD_ADD_METHOD(MultiTexCoord2s);
- PY_MOD_ADD_METHOD(MultiTexCoord2sv);
- PY_MOD_ADD_METHOD(MultiTexCoord3d);
- PY_MOD_ADD_METHOD(MultiTexCoord3dv);
- PY_MOD_ADD_METHOD(MultiTexCoord3f);
- PY_MOD_ADD_METHOD(MultiTexCoord3fv);
- PY_MOD_ADD_METHOD(MultiTexCoord3i);
- PY_MOD_ADD_METHOD(MultiTexCoord3iv);
- PY_MOD_ADD_METHOD(MultiTexCoord3s);
- PY_MOD_ADD_METHOD(MultiTexCoord3sv);
- PY_MOD_ADD_METHOD(MultiTexCoord4d);
- PY_MOD_ADD_METHOD(MultiTexCoord4dv);
- PY_MOD_ADD_METHOD(MultiTexCoord4f);
- PY_MOD_ADD_METHOD(MultiTexCoord4fv);
- PY_MOD_ADD_METHOD(MultiTexCoord4i);
- PY_MOD_ADD_METHOD(MultiTexCoord4iv);
- PY_MOD_ADD_METHOD(MultiTexCoord4s);
- PY_MOD_ADD_METHOD(MultiTexCoord4sv);
- }
-
/* GL_VERSION_1_4 */
{
@@ -2192,7 +1494,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(BlendEquation);
}
-
/* GL_VERSION_1_5 */
{
PY_MOD_ADD_METHOD(BeginQuery);
@@ -2216,7 +1517,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(UnmapBuffer);
}
-
/* GL_VERSION_2_0 */
{
PY_MOD_ADD_METHOD(AttachShader);
@@ -2314,7 +1614,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(VertexAttribPointer);
}
-
/* GL_VERSION_2_1 */
{
PY_MOD_ADD_METHOD(UniformMatrix2x3fv);
@@ -2325,16 +1624,15 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(UniformMatrix4x3fv);
}
-
/* GL_VERSION_3_0 */
{
PY_MOD_ADD_METHOD(BindVertexArray);
PY_MOD_ADD_METHOD(DeleteVertexArrays);
PY_MOD_ADD_METHOD(GenVertexArrays);
+ PY_MOD_ADD_METHOD(GetStringi);
PY_MOD_ADD_METHOD(IsVertexArray);
}
-
/* GL_VERSION_3_1 */
{
PY_MOD_ADD_METHOD(BindBufferBase);
@@ -2349,7 +1647,6 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(UniformBlockBinding);
}
-
/* GL_VERSION_3_2 */
{
PY_MOD_ADD_METHOD(FramebufferTexture);
@@ -2361,39 +1658,8 @@ PyObject *BPyInit_bgl(void)
PY_MOD_ADD_METHOD(TexImage3DMultisample);
}
-
/* GL_VERSION_3_3 */
{
- PY_MOD_ADD_METHOD(ColorP3ui);
- PY_MOD_ADD_METHOD(ColorP3uiv);
- PY_MOD_ADD_METHOD(ColorP4ui);
- PY_MOD_ADD_METHOD(ColorP4uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP1ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP1uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP2ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP2uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP3ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP3uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP4ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP4uiv);
- PY_MOD_ADD_METHOD(NormalP3ui);
- PY_MOD_ADD_METHOD(NormalP3uiv);
- PY_MOD_ADD_METHOD(SecondaryColorP3ui);
- PY_MOD_ADD_METHOD(SecondaryColorP3uiv);
- PY_MOD_ADD_METHOD(TexCoordP1ui);
- PY_MOD_ADD_METHOD(TexCoordP1uiv);
- PY_MOD_ADD_METHOD(TexCoordP2ui);
- PY_MOD_ADD_METHOD(TexCoordP2uiv);
- PY_MOD_ADD_METHOD(TexCoordP3ui);
- PY_MOD_ADD_METHOD(TexCoordP3uiv);
- PY_MOD_ADD_METHOD(TexCoordP4ui);
- PY_MOD_ADD_METHOD(TexCoordP4uiv);
- PY_MOD_ADD_METHOD(VertexP2ui);
- PY_MOD_ADD_METHOD(VertexP2uiv);
- PY_MOD_ADD_METHOD(VertexP3ui);
- PY_MOD_ADD_METHOD(VertexP3uiv);
- PY_MOD_ADD_METHOD(VertexP4ui);
- PY_MOD_ADD_METHOD(VertexP4uiv);
}
#define PY_DICT_ADD_INT(x) py_module_dict_add_int(dict, #x, x)
@@ -2511,8 +1777,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_POINT);
PY_DICT_ADD_INT(GL_POINTS);
PY_DICT_ADD_INT(GL_POINT_SIZE);
- PY_DICT_ADD_INT(GL_POINT_SIZE_GRANULARITY);
- PY_DICT_ADD_INT(GL_POINT_SIZE_RANGE);
PY_DICT_ADD_INT(GL_POLYGON_MODE);
PY_DICT_ADD_INT(GL_POLYGON_OFFSET_FACTOR);
PY_DICT_ADD_INT(GL_POLYGON_OFFSET_FILL);
@@ -2602,338 +1866,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_XOR);
PY_DICT_ADD_INT(GL_ZERO);
}
- /* adding in GL_VERSION_1_1 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_2D);
- PY_DICT_ADD_INT(GL_2_BYTES);
- PY_DICT_ADD_INT(GL_3D);
- PY_DICT_ADD_INT(GL_3D_COLOR);
- PY_DICT_ADD_INT(GL_3D_COLOR_TEXTURE);
- PY_DICT_ADD_INT(GL_3_BYTES);
- PY_DICT_ADD_INT(GL_4D_COLOR_TEXTURE);
- PY_DICT_ADD_INT(GL_4_BYTES);
- PY_DICT_ADD_INT(GL_ACCUM);
- PY_DICT_ADD_INT(GL_ACCUM_ALPHA_BITS);
- PY_DICT_ADD_INT(GL_ACCUM_BLUE_BITS);
- PY_DICT_ADD_INT(GL_ACCUM_BUFFER_BIT);
- PY_DICT_ADD_INT(GL_ACCUM_CLEAR_VALUE);
- PY_DICT_ADD_INT(GL_ACCUM_GREEN_BITS);
- PY_DICT_ADD_INT(GL_ACCUM_RED_BITS);
- PY_DICT_ADD_INT(GL_ADD);
- PY_DICT_ADD_INT(GL_ALL_ATTRIB_BITS);
- PY_DICT_ADD_INT(GL_ALPHA12);
- PY_DICT_ADD_INT(GL_ALPHA16);
- PY_DICT_ADD_INT(GL_ALPHA4);
- PY_DICT_ADD_INT(GL_ALPHA8);
- PY_DICT_ADD_INT(GL_ALPHA_BIAS);
- PY_DICT_ADD_INT(GL_ALPHA_BITS);
- PY_DICT_ADD_INT(GL_ALPHA_SCALE);
- PY_DICT_ADD_INT(GL_ALPHA_TEST);
- PY_DICT_ADD_INT(GL_ALPHA_TEST_FUNC);
- PY_DICT_ADD_INT(GL_ALPHA_TEST_REF);
- PY_DICT_ADD_INT(GL_AMBIENT);
- PY_DICT_ADD_INT(GL_AMBIENT_AND_DIFFUSE);
- PY_DICT_ADD_INT(GL_ATTRIB_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_AUTO_NORMAL);
- PY_DICT_ADD_INT(GL_AUX0);
- PY_DICT_ADD_INT(GL_AUX1);
- PY_DICT_ADD_INT(GL_AUX2);
- PY_DICT_ADD_INT(GL_AUX3);
- PY_DICT_ADD_INT(GL_AUX_BUFFERS);
- PY_DICT_ADD_INT(GL_BITMAP);
- PY_DICT_ADD_INT(GL_BITMAP_TOKEN);
- PY_DICT_ADD_INT(GL_BLUE_BIAS);
- PY_DICT_ADD_INT(GL_BLUE_BITS);
- PY_DICT_ADD_INT(GL_BLUE_SCALE);
- PY_DICT_ADD_INT(GL_C3F_V3F);
- PY_DICT_ADD_INT(GL_C4F_N3F_V3F);
- PY_DICT_ADD_INT(GL_C4UB_V2F);
- PY_DICT_ADD_INT(GL_C4UB_V3F);
- PY_DICT_ADD_INT(GL_CLAMP);
- PY_DICT_ADD_INT(GL_CLIENT_ALL_ATTRIB_BITS);
- PY_DICT_ADD_INT(GL_CLIENT_ATTRIB_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_CLIENT_PIXEL_STORE_BIT);
- PY_DICT_ADD_INT(GL_CLIENT_VERTEX_ARRAY_BIT);
- PY_DICT_ADD_INT(GL_CLIP_PLANE0);
- PY_DICT_ADD_INT(GL_CLIP_PLANE1);
- PY_DICT_ADD_INT(GL_CLIP_PLANE2);
- PY_DICT_ADD_INT(GL_CLIP_PLANE3);
- PY_DICT_ADD_INT(GL_CLIP_PLANE4);
- PY_DICT_ADD_INT(GL_CLIP_PLANE5);
- PY_DICT_ADD_INT(GL_COEFF);
- PY_DICT_ADD_INT(GL_COLOR_ARRAY);
- PY_DICT_ADD_INT(GL_COLOR_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_COLOR_ARRAY_SIZE);
- PY_DICT_ADD_INT(GL_COLOR_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_COLOR_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_COLOR_INDEX);
- PY_DICT_ADD_INT(GL_COLOR_INDEXES);
- PY_DICT_ADD_INT(GL_COLOR_MATERIAL);
- PY_DICT_ADD_INT(GL_COLOR_MATERIAL_FACE);
- PY_DICT_ADD_INT(GL_COLOR_MATERIAL_PARAMETER);
- PY_DICT_ADD_INT(GL_COMPILE);
- PY_DICT_ADD_INT(GL_COMPILE_AND_EXECUTE);
- PY_DICT_ADD_INT(GL_CONSTANT_ATTENUATION);
- PY_DICT_ADD_INT(GL_COPY_PIXEL_TOKEN);
- PY_DICT_ADD_INT(GL_CURRENT_BIT);
- PY_DICT_ADD_INT(GL_CURRENT_COLOR);
- PY_DICT_ADD_INT(GL_CURRENT_INDEX);
- PY_DICT_ADD_INT(GL_CURRENT_NORMAL);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_COLOR);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_DISTANCE);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_INDEX);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_POSITION);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_POSITION_VALID);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_TEXTURE_COORDS);
- PY_DICT_ADD_INT(GL_CURRENT_TEXTURE_COORDS);
- PY_DICT_ADD_INT(GL_DECAL);
- PY_DICT_ADD_INT(GL_DEPTH_BIAS);
- PY_DICT_ADD_INT(GL_DEPTH_BITS);
- PY_DICT_ADD_INT(GL_DEPTH_SCALE);
- PY_DICT_ADD_INT(GL_DIFFUSE);
- PY_DICT_ADD_INT(GL_DOMAIN);
- PY_DICT_ADD_INT(GL_DRAW_PIXEL_TOKEN);
- PY_DICT_ADD_INT(GL_EDGE_FLAG);
- PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY);
- PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_EMISSION);
- PY_DICT_ADD_INT(GL_ENABLE_BIT);
- PY_DICT_ADD_INT(GL_EVAL_BIT);
- PY_DICT_ADD_INT(GL_EXP);
- PY_DICT_ADD_INT(GL_EXP2);
- PY_DICT_ADD_INT(GL_EYE_LINEAR);
- PY_DICT_ADD_INT(GL_EYE_PLANE);
- PY_DICT_ADD_INT(GL_FEEDBACK);
- PY_DICT_ADD_INT(GL_FEEDBACK_BUFFER_POINTER);
- PY_DICT_ADD_INT(GL_FEEDBACK_BUFFER_SIZE);
- PY_DICT_ADD_INT(GL_FEEDBACK_BUFFER_TYPE);
- PY_DICT_ADD_INT(GL_FLAT);
- PY_DICT_ADD_INT(GL_FOG);
- PY_DICT_ADD_INT(GL_FOG_BIT);
- PY_DICT_ADD_INT(GL_FOG_COLOR);
- PY_DICT_ADD_INT(GL_FOG_DENSITY);
- PY_DICT_ADD_INT(GL_FOG_END);
- PY_DICT_ADD_INT(GL_FOG_HINT);
- PY_DICT_ADD_INT(GL_FOG_INDEX);
- PY_DICT_ADD_INT(GL_FOG_MODE);
- PY_DICT_ADD_INT(GL_FOG_START);
- PY_DICT_ADD_INT(GL_GREEN_BIAS);
- PY_DICT_ADD_INT(GL_GREEN_BITS);
- PY_DICT_ADD_INT(GL_GREEN_SCALE);
- PY_DICT_ADD_INT(GL_HINT_BIT);
- PY_DICT_ADD_INT(GL_INDEX_ARRAY);
- PY_DICT_ADD_INT(GL_INDEX_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_INDEX_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_INDEX_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_INDEX_BITS);
- PY_DICT_ADD_INT(GL_INDEX_CLEAR_VALUE);
- PY_DICT_ADD_INT(GL_INDEX_LOGIC_OP);
- PY_DICT_ADD_INT(GL_INDEX_MODE);
- PY_DICT_ADD_INT(GL_INDEX_OFFSET);
- PY_DICT_ADD_INT(GL_INDEX_SHIFT);
- PY_DICT_ADD_INT(GL_INDEX_WRITEMASK);
- PY_DICT_ADD_INT(GL_INTENSITY);
- PY_DICT_ADD_INT(GL_INTENSITY12);
- PY_DICT_ADD_INT(GL_INTENSITY16);
- PY_DICT_ADD_INT(GL_INTENSITY4);
- PY_DICT_ADD_INT(GL_INTENSITY8);
- PY_DICT_ADD_INT(GL_LIGHT0);
- PY_DICT_ADD_INT(GL_LIGHT1);
- PY_DICT_ADD_INT(GL_LIGHT2);
- PY_DICT_ADD_INT(GL_LIGHT3);
- PY_DICT_ADD_INT(GL_LIGHT4);
- PY_DICT_ADD_INT(GL_LIGHT5);
- PY_DICT_ADD_INT(GL_LIGHT6);
- PY_DICT_ADD_INT(GL_LIGHT7);
- PY_DICT_ADD_INT(GL_LIGHTING);
- PY_DICT_ADD_INT(GL_LIGHTING_BIT);
- PY_DICT_ADD_INT(GL_LIGHT_MODEL_AMBIENT);
- PY_DICT_ADD_INT(GL_LIGHT_MODEL_LOCAL_VIEWER);
- PY_DICT_ADD_INT(GL_LIGHT_MODEL_TWO_SIDE);
- PY_DICT_ADD_INT(GL_LINEAR_ATTENUATION);
- PY_DICT_ADD_INT(GL_LINE_BIT);
- PY_DICT_ADD_INT(GL_LINE_RESET_TOKEN);
- PY_DICT_ADD_INT(GL_LINE_STIPPLE);
- PY_DICT_ADD_INT(GL_LINE_STIPPLE_PATTERN);
- PY_DICT_ADD_INT(GL_LINE_STIPPLE_REPEAT);
- PY_DICT_ADD_INT(GL_LINE_TOKEN);
- PY_DICT_ADD_INT(GL_LIST_BASE);
- PY_DICT_ADD_INT(GL_LIST_BIT);
- PY_DICT_ADD_INT(GL_LIST_INDEX);
- PY_DICT_ADD_INT(GL_LIST_MODE);
- PY_DICT_ADD_INT(GL_LOAD);
- PY_DICT_ADD_INT(GL_LOGIC_OP);
- PY_DICT_ADD_INT(GL_LUMINANCE);
- PY_DICT_ADD_INT(GL_LUMINANCE12);
- PY_DICT_ADD_INT(GL_LUMINANCE12_ALPHA12);
- PY_DICT_ADD_INT(GL_LUMINANCE12_ALPHA4);
- PY_DICT_ADD_INT(GL_LUMINANCE16);
- PY_DICT_ADD_INT(GL_LUMINANCE16_ALPHA16);
- PY_DICT_ADD_INT(GL_LUMINANCE4);
- PY_DICT_ADD_INT(GL_LUMINANCE4_ALPHA4);
- PY_DICT_ADD_INT(GL_LUMINANCE6_ALPHA2);
- PY_DICT_ADD_INT(GL_LUMINANCE8);
- PY_DICT_ADD_INT(GL_LUMINANCE8_ALPHA8);
- PY_DICT_ADD_INT(GL_LUMINANCE_ALPHA);
- PY_DICT_ADD_INT(GL_MAP1_COLOR_4);
- PY_DICT_ADD_INT(GL_MAP1_GRID_DOMAIN);
- PY_DICT_ADD_INT(GL_MAP1_GRID_SEGMENTS);
- PY_DICT_ADD_INT(GL_MAP1_INDEX);
- PY_DICT_ADD_INT(GL_MAP1_NORMAL);
- PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_1);
- PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_2);
- PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_3);
- PY_DICT_ADD_INT(GL_MAP1_TEXTURE_COORD_4);
- PY_DICT_ADD_INT(GL_MAP1_VERTEX_3);
- PY_DICT_ADD_INT(GL_MAP1_VERTEX_4);
- PY_DICT_ADD_INT(GL_MAP2_COLOR_4);
- PY_DICT_ADD_INT(GL_MAP2_GRID_DOMAIN);
- PY_DICT_ADD_INT(GL_MAP2_GRID_SEGMENTS);
- PY_DICT_ADD_INT(GL_MAP2_INDEX);
- PY_DICT_ADD_INT(GL_MAP2_NORMAL);
- PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_1);
- PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_2);
- PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_3);
- PY_DICT_ADD_INT(GL_MAP2_TEXTURE_COORD_4);
- PY_DICT_ADD_INT(GL_MAP2_VERTEX_3);
- PY_DICT_ADD_INT(GL_MAP2_VERTEX_4);
- PY_DICT_ADD_INT(GL_MAP_COLOR);
- PY_DICT_ADD_INT(GL_MAP_STENCIL);
- PY_DICT_ADD_INT(GL_MATRIX_MODE);
- PY_DICT_ADD_INT(GL_MAX_ATTRIB_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MAX_CLIP_PLANES);
- PY_DICT_ADD_INT(GL_MAX_EVAL_ORDER);
- PY_DICT_ADD_INT(GL_MAX_LIGHTS);
- PY_DICT_ADD_INT(GL_MAX_LIST_NESTING);
- PY_DICT_ADD_INT(GL_MAX_MODELVIEW_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MAX_NAME_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MAX_PIXEL_MAP_TABLE);
- PY_DICT_ADD_INT(GL_MAX_PROJECTION_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MAX_TEXTURE_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MODELVIEW);
- PY_DICT_ADD_INT(GL_MODELVIEW_MATRIX);
- PY_DICT_ADD_INT(GL_MODELVIEW_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_MODULATE);
- PY_DICT_ADD_INT(GL_MULT);
- PY_DICT_ADD_INT(GL_N3F_V3F);
- PY_DICT_ADD_INT(GL_NAME_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_NORMALIZE);
- PY_DICT_ADD_INT(GL_NORMAL_ARRAY);
- PY_DICT_ADD_INT(GL_NORMAL_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_NORMAL_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_NORMAL_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_OBJECT_LINEAR);
- PY_DICT_ADD_INT(GL_OBJECT_PLANE);
- PY_DICT_ADD_INT(GL_ORDER);
- PY_DICT_ADD_INT(GL_PASS_THROUGH_TOKEN);
- PY_DICT_ADD_INT(GL_PERSPECTIVE_CORRECTION_HINT);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_A_TO_A);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_A_TO_A_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_B_TO_B);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_B_TO_B_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_G_TO_G);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_G_TO_G_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_A);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_A_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_B);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_B_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_G);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_G_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_I);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_I_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_R);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_I_TO_R_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_R_TO_R);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_R_TO_R_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_S_TO_S);
- PY_DICT_ADD_INT(GL_PIXEL_MAP_S_TO_S_SIZE);
- PY_DICT_ADD_INT(GL_PIXEL_MODE_BIT);
- PY_DICT_ADD_INT(GL_POINT_BIT);
- PY_DICT_ADD_INT(GL_POINT_SMOOTH);
- PY_DICT_ADD_INT(GL_POINT_SMOOTH_HINT);
- PY_DICT_ADD_INT(GL_POINT_TOKEN);
- PY_DICT_ADD_INT(GL_POLYGON);
- PY_DICT_ADD_INT(GL_POLYGON_BIT);
- PY_DICT_ADD_INT(GL_POLYGON_STIPPLE);
- PY_DICT_ADD_INT(GL_POLYGON_STIPPLE_BIT);
- PY_DICT_ADD_INT(GL_POLYGON_TOKEN);
- PY_DICT_ADD_INT(GL_POSITION);
- PY_DICT_ADD_INT(GL_PROJECTION);
- PY_DICT_ADD_INT(GL_PROJECTION_MATRIX);
- PY_DICT_ADD_INT(GL_PROJECTION_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_Q);
- PY_DICT_ADD_INT(GL_QUADRATIC_ATTENUATION);
- PY_DICT_ADD_INT(GL_QUADS);
- PY_DICT_ADD_INT(GL_QUAD_STRIP);
- PY_DICT_ADD_INT(GL_R);
- PY_DICT_ADD_INT(GL_RED_BIAS);
- PY_DICT_ADD_INT(GL_RED_BITS);
- PY_DICT_ADD_INT(GL_RED_SCALE);
- PY_DICT_ADD_INT(GL_RENDER);
- PY_DICT_ADD_INT(GL_RENDER_MODE);
- PY_DICT_ADD_INT(GL_RETURN);
- PY_DICT_ADD_INT(GL_RGBA_MODE);
- PY_DICT_ADD_INT(GL_S);
- PY_DICT_ADD_INT(GL_SCISSOR_BIT);
- PY_DICT_ADD_INT(GL_SELECT);
- PY_DICT_ADD_INT(GL_SELECTION_BUFFER_POINTER);
- PY_DICT_ADD_INT(GL_SELECTION_BUFFER_SIZE);
- PY_DICT_ADD_INT(GL_SHADE_MODEL);
- PY_DICT_ADD_INT(GL_SHININESS);
- PY_DICT_ADD_INT(GL_SMOOTH);
- PY_DICT_ADD_INT(GL_SPECULAR);
- PY_DICT_ADD_INT(GL_SPHERE_MAP);
- PY_DICT_ADD_INT(GL_SPOT_CUTOFF);
- PY_DICT_ADD_INT(GL_SPOT_DIRECTION);
- PY_DICT_ADD_INT(GL_SPOT_EXPONENT);
- PY_DICT_ADD_INT(GL_STACK_OVERFLOW);
- PY_DICT_ADD_INT(GL_STACK_UNDERFLOW);
- PY_DICT_ADD_INT(GL_STENCIL_BITS);
- PY_DICT_ADD_INT(GL_T);
- PY_DICT_ADD_INT(GL_T2F_C3F_V3F);
- PY_DICT_ADD_INT(GL_T2F_C4F_N3F_V3F);
- PY_DICT_ADD_INT(GL_T2F_C4UB_V3F);
- PY_DICT_ADD_INT(GL_T2F_N3F_V3F);
- PY_DICT_ADD_INT(GL_T2F_V3F);
- PY_DICT_ADD_INT(GL_T4F_C4F_N3F_V4F);
- PY_DICT_ADD_INT(GL_T4F_V4F);
- PY_DICT_ADD_INT(GL_TEXTURE_BIT);
- PY_DICT_ADD_INT(GL_TEXTURE_BORDER);
- PY_DICT_ADD_INT(GL_TEXTURE_COMPONENTS);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_SIZE);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_TEXTURE_ENV);
- PY_DICT_ADD_INT(GL_TEXTURE_ENV_COLOR);
- PY_DICT_ADD_INT(GL_TEXTURE_ENV_MODE);
- PY_DICT_ADD_INT(GL_TEXTURE_GEN_MODE);
- PY_DICT_ADD_INT(GL_TEXTURE_GEN_Q);
- PY_DICT_ADD_INT(GL_TEXTURE_GEN_R);
- PY_DICT_ADD_INT(GL_TEXTURE_GEN_S);
- PY_DICT_ADD_INT(GL_TEXTURE_GEN_T);
- PY_DICT_ADD_INT(GL_TEXTURE_INTENSITY_SIZE);
- PY_DICT_ADD_INT(GL_TEXTURE_LUMINANCE_SIZE);
- PY_DICT_ADD_INT(GL_TEXTURE_MATRIX);
- PY_DICT_ADD_INT(GL_TEXTURE_PRIORITY);
- PY_DICT_ADD_INT(GL_TEXTURE_RESIDENT);
- PY_DICT_ADD_INT(GL_TEXTURE_STACK_DEPTH);
- PY_DICT_ADD_INT(GL_TRANSFORM_BIT);
- PY_DICT_ADD_INT(GL_V2F);
- PY_DICT_ADD_INT(GL_V3F);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY_SIZE);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_VIEWPORT_BIT);
- PY_DICT_ADD_INT(GL_ZOOM_X);
- PY_DICT_ADD_INT(GL_ZOOM_Y);
- }
-
/* GL_VERSION_1_2 */
{
@@ -2974,15 +1906,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_UNSIGNED_SHORT_5_6_5);
PY_DICT_ADD_INT(GL_UNSIGNED_SHORT_5_6_5_REV);
}
- /* adding in GL_VERSION_1_2 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_ALIASED_POINT_SIZE_RANGE);
- PY_DICT_ADD_INT(GL_LIGHT_MODEL_COLOR_CONTROL);
- PY_DICT_ADD_INT(GL_RESCALE_NORMAL);
- PY_DICT_ADD_INT(GL_SEPARATE_SPECULAR_COLOR);
- PY_DICT_ADD_INT(GL_SINGLE_COLOR);
- }
-
/* GL_VERSION_1_3 */
{
@@ -3046,47 +1969,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
}
- /* adding in GL_VERSION_1_3 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_ADD_SIGNED);
- PY_DICT_ADD_INT(GL_CLIENT_ACTIVE_TEXTURE);
- PY_DICT_ADD_INT(GL_COMBINE);
- PY_DICT_ADD_INT(GL_COMBINE_ALPHA);
- PY_DICT_ADD_INT(GL_COMBINE_RGB);
- PY_DICT_ADD_INT(GL_COMPRESSED_ALPHA);
- PY_DICT_ADD_INT(GL_COMPRESSED_INTENSITY);
- PY_DICT_ADD_INT(GL_COMPRESSED_LUMINANCE);
- PY_DICT_ADD_INT(GL_COMPRESSED_LUMINANCE_ALPHA);
- PY_DICT_ADD_INT(GL_CONSTANT);
- PY_DICT_ADD_INT(GL_DOT3_RGB);
- PY_DICT_ADD_INT(GL_DOT3_RGBA);
- PY_DICT_ADD_INT(GL_INTERPOLATE);
- PY_DICT_ADD_INT(GL_MAX_TEXTURE_UNITS);
- PY_DICT_ADD_INT(GL_MULTISAMPLE_BIT);
- PY_DICT_ADD_INT(GL_NORMAL_MAP);
- PY_DICT_ADD_INT(GL_OPERAND0_ALPHA);
- PY_DICT_ADD_INT(GL_OPERAND0_RGB);
- PY_DICT_ADD_INT(GL_OPERAND1_ALPHA);
- PY_DICT_ADD_INT(GL_OPERAND1_RGB);
- PY_DICT_ADD_INT(GL_OPERAND2_ALPHA);
- PY_DICT_ADD_INT(GL_OPERAND2_RGB);
- PY_DICT_ADD_INT(GL_PREVIOUS);
- PY_DICT_ADD_INT(GL_PRIMARY_COLOR);
- PY_DICT_ADD_INT(GL_REFLECTION_MAP);
- PY_DICT_ADD_INT(GL_RGB_SCALE);
- PY_DICT_ADD_INT(GL_SOURCE0_ALPHA);
- PY_DICT_ADD_INT(GL_SOURCE0_RGB);
- PY_DICT_ADD_INT(GL_SOURCE1_ALPHA);
- PY_DICT_ADD_INT(GL_SOURCE1_RGB);
- PY_DICT_ADD_INT(GL_SOURCE2_ALPHA);
- PY_DICT_ADD_INT(GL_SOURCE2_RGB);
- PY_DICT_ADD_INT(GL_SUBTRACT);
- PY_DICT_ADD_INT(GL_TRANSPOSE_COLOR_MATRIX);
- PY_DICT_ADD_INT(GL_TRANSPOSE_MODELVIEW_MATRIX);
- PY_DICT_ADD_INT(GL_TRANSPOSE_PROJECTION_MATRIX);
- PY_DICT_ADD_INT(GL_TRANSPOSE_TEXTURE_MATRIX);
- }
-
/* GL_VERSION_1_4 */
{
@@ -3116,33 +1998,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_TEXTURE_DEPTH_SIZE);
PY_DICT_ADD_INT(GL_TEXTURE_LOD_BIAS);
}
- /* adding in GL_VERSION_1_4 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_COLOR_SUM);
- PY_DICT_ADD_INT(GL_COMPARE_R_TO_TEXTURE);
- PY_DICT_ADD_INT(GL_CURRENT_FOG_COORDINATE);
- PY_DICT_ADD_INT(GL_CURRENT_SECONDARY_COLOR);
- PY_DICT_ADD_INT(GL_DEPTH_TEXTURE_MODE);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_SOURCE);
- PY_DICT_ADD_INT(GL_FRAGMENT_DEPTH);
- PY_DICT_ADD_INT(GL_GENERATE_MIPMAP);
- PY_DICT_ADD_INT(GL_GENERATE_MIPMAP_HINT);
- PY_DICT_ADD_INT(GL_POINT_DISTANCE_ATTENUATION);
- PY_DICT_ADD_INT(GL_POINT_SIZE_MAX);
- PY_DICT_ADD_INT(GL_POINT_SIZE_MIN);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_SIZE);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_TEXTURE_FILTER_CONTROL);
- }
-
/* GL_VERSION_1_5 */
{
@@ -3165,7 +2020,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_READ_ONLY);
PY_DICT_ADD_INT(GL_READ_WRITE);
PY_DICT_ADD_INT(GL_SAMPLES_PASSED);
- PY_DICT_ADD_INT(GL_SRC1_ALPHA);
PY_DICT_ADD_INT(GL_STATIC_COPY);
PY_DICT_ADD_INT(GL_STATIC_DRAW);
PY_DICT_ADD_INT(GL_STATIC_READ);
@@ -3175,32 +2029,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
PY_DICT_ADD_INT(GL_WRITE_ONLY);
}
- /* adding in GL_VERSION_1_5 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_COLOR_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_CURRENT_FOG_COORD);
- PY_DICT_ADD_INT(GL_EDGE_FLAG_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_FOG_COORD);
- PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY);
- PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_POINTER);
- PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_STRIDE);
- PY_DICT_ADD_INT(GL_FOG_COORD_ARRAY_TYPE);
- PY_DICT_ADD_INT(GL_FOG_COORD_SRC);
- PY_DICT_ADD_INT(GL_INDEX_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_NORMAL_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_SRC0_ALPHA);
- PY_DICT_ADD_INT(GL_SRC0_RGB);
- PY_DICT_ADD_INT(GL_SRC1_RGB);
- PY_DICT_ADD_INT(GL_SRC2_ALPHA);
- PY_DICT_ADD_INT(GL_SRC2_RGB);
- PY_DICT_ADD_INT(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_VERTEX_ARRAY_BUFFER_BINDING);
- PY_DICT_ADD_INT(GL_WEIGHT_ARRAY_BUFFER_BINDING);
- }
-
/* GL_VERSION_2_0 */
{
@@ -3285,14 +2113,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_VERTEX_PROGRAM_POINT_SIZE);
PY_DICT_ADD_INT(GL_VERTEX_SHADER);
}
- /* adding in GL_VERSION_2_0 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_COORD_REPLACE);
- PY_DICT_ADD_INT(GL_MAX_TEXTURE_COORDS);
- PY_DICT_ADD_INT(GL_POINT_SPRITE);
- PY_DICT_ADD_INT(GL_VERTEX_PROGRAM_TWO_SIDE);
- }
-
/* GL_VERSION_2_1 */
{
@@ -3313,16 +2133,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_SRGB8_ALPHA8);
PY_DICT_ADD_INT(GL_SRGB_ALPHA);
}
- /* adding in GL_VERSION_2_1 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_COMPRESSED_SLUMINANCE);
- PY_DICT_ADD_INT(GL_COMPRESSED_SLUMINANCE_ALPHA);
- PY_DICT_ADD_INT(GL_CURRENT_RASTER_SECONDARY_COLOR);
- PY_DICT_ADD_INT(GL_SLUMINANCE);
- PY_DICT_ADD_INT(GL_SLUMINANCE8);
- PY_DICT_ADD_INT(GL_SLUMINANCE8_ALPHA8);
- PY_DICT_ADD_INT(GL_SLUMINANCE_ALPHA);
- }
/* GL_VERSION_3_0 */
{
@@ -3563,14 +2373,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_VERTEX_ARRAY_BINDING);
PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_INTEGER);
}
- /* adding in GL_VERSION_3_0 removed from core profile */
- if (use_deprecated == true) {
- PY_DICT_ADD_INT(GL_ALPHA_INTEGER);
- PY_DICT_ADD_INT(GL_CLAMP_FRAGMENT_COLOR);
- PY_DICT_ADD_INT(GL_CLAMP_VERTEX_COLOR);
- PY_DICT_ADD_INT(GL_TEXTURE_INTENSITY_TYPE);
- PY_DICT_ADD_INT(GL_TEXTURE_LUMINANCE_TYPE);
- }
/* GL_VERSION_3_1 */
{
@@ -3637,7 +2439,6 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_BUFFER);
}
-
/* GL_VERSION_3_2 */
{
PY_DICT_ADD_INT(GL_ALREADY_SIGNALED);
@@ -3743,4 +2544,4 @@ static PyObject *Method_ShaderSource(PyObject *UNUSED(self), PyObject *args)
}
-/** \} */ \ No newline at end of file
+/** \} */
diff --git a/source/blender/python/generic/blf_py_api.c b/source/blender/python/generic/blf_py_api.c
index 69f1e297b43..02bd1fdbe39 100644
--- a/source/blender/python/generic/blf_py_api.c
+++ b/source/blender/python/generic/blf_py_api.c
@@ -114,6 +114,7 @@ static PyObject *py_blf_aspect(PyObject *UNUSED(self), PyObject *args)
}
+#if BLF_BLUR_ENABLE
PyDoc_STRVAR(py_blf_blur_doc,
".. function:: blur(fontid, radius)\n"
"\n"
@@ -135,6 +136,7 @@ static PyObject *py_blf_blur(PyObject *UNUSED(self), PyObject *args)
Py_RETURN_NONE;
}
+#endif
PyDoc_STRVAR(py_blf_draw_doc,
@@ -418,7 +420,9 @@ static PyObject *py_blf_unload(PyObject *UNUSED(self), PyObject *args)
/*----------------------------MODULE INIT-------------------------*/
static PyMethodDef BLF_methods[] = {
{"aspect", (PyCFunction) py_blf_aspect, METH_VARARGS, py_blf_aspect_doc},
+#if BLF_BLUR_ENABLE
{"blur", (PyCFunction) py_blf_blur, METH_VARARGS, py_blf_blur_doc},
+#endif
{"clipping", (PyCFunction) py_blf_clipping, METH_VARARGS, py_blf_clipping_doc},
{"word_wrap", (PyCFunction) py_blf_word_wrap, METH_VARARGS, py_blf_word_wrap_doc},
{"disable", (PyCFunction) py_blf_disable, METH_VARARGS, py_blf_disable_doc},
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index cdbf65546d3..41018468695 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -64,6 +64,8 @@ set(SRC
bpy_intern_string.c
bpy_library_load.c
bpy_library_write.c
+ bpy_manipulator_wrap.c
+ bpy_msgbus.c
bpy_operator.c
bpy_operator_wrap.c
bpy_path.c
@@ -74,11 +76,14 @@ set(SRC
bpy_rna_callback.c
bpy_rna_driver.c
bpy_rna_id_collection.c
+ bpy_rna_manipulator.c
bpy_traceback.c
bpy_utils_previews.c
bpy_utils_units.c
gpu.c
gpu_offscreen.c
+ gpu_py_matrix.c
+ gpu_py_select.c
stubs.c
bpy.h
@@ -97,6 +102,8 @@ set(SRC
bpy_driver.h
bpy_intern_string.h
bpy_library.h
+ bpy_manipulator_wrap.h
+ bpy_msgbus.h
bpy_operator.h
bpy_operator_wrap.h
bpy_path.h
@@ -106,6 +113,7 @@ set(SRC
bpy_rna_callback.h
bpy_rna_driver.h
bpy_rna_id_collection.h
+ bpy_rna_manipulator.h
bpy_traceback.h
bpy_utils_previews.h
bpy_utils_units.h
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 7150cc65942..0b791b6acaa 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -46,6 +46,7 @@
#include "bpy_rna.h"
#include "bpy_app.h"
#include "bpy_rna_id_collection.h"
+#include "bpy_rna_manipulator.h"
#include "bpy_props.h"
#include "bpy_library.h"
#include "bpy_operator.h"
@@ -57,6 +58,7 @@
/* external util modules */
#include "../generic/idprop_py_api.h"
+#include "bpy_msgbus.h"
#ifdef WITH_FREESTYLE
# include "BPy_Freestyle.h"
@@ -338,6 +340,8 @@ void BPy_init_modules(void)
BPY_rna_id_collection_module(mod);
+ BPY_rna_manipulator_module(mod);
+
bpy_import_test("bpy_types");
PyModule_AddObject(mod, "data", BPY_rna_module()); /* imports bpy_types by running this */
bpy_import_test("bpy_types");
@@ -347,6 +351,7 @@ void BPy_init_modules(void)
PyModule_AddObject(mod, "app", BPY_app_struct());
PyModule_AddObject(mod, "_utils_units", BPY_utils_units());
PyModule_AddObject(mod, "_utils_previews", BPY_utils_previews_module());
+ PyModule_AddObject(mod, "msgbus", BPY_msgbus_module());
/* bpy context */
RNA_pointer_create(NULL, &RNA_Context, (void *)BPy_GetContext(), &ctx_ptr);
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 90aa22de5bf..5a309339e17 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -59,12 +59,6 @@ static PyStructSequence_Field app_cb_info_fields[] = {
{(char *)"load_post", (char *)"on loading a new blend file (after)"},
{(char *)"save_pre", (char *)"on saving a blend file (before)"},
{(char *)"save_post", (char *)"on saving a blend file (after)"},
- {(char *)"scene_update_pre", (char *)"on every scene data update. Does not imply that anything changed in the "
- "scene, just that the dependency graph is about to be reevaluated, and the "
- "scene is about to be updated by Blender's animation system."},
- {(char *)"scene_update_post", (char *)"on every scene data update. Does not imply that anything changed in the "
- "scene, just that the dependency graph was reevaluated, and the scene was "
- "possibly updated by Blender's animation system."},
{(char *)"game_pre", (char *)"on starting the game engine"},
{(char *)"game_post", (char *)"on ending the game engine"},
{(char *)"version_update", (char *)"on ending the versioning code"},
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index ae8e35ae3fc..11a233461d8 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -72,6 +72,7 @@
#include "../generic/bgl.h"
#include "../generic/blf_py_api.h"
#include "../generic/idprop_py_api.h"
+#include "../gawain/gwn_py_api.h"
#include "../bmesh/bmesh_py_api.h"
#include "../mathutils/mathutils.h"
@@ -212,6 +213,7 @@ static struct _inittab bpy_internal_modules[] = {
{"mathutils.kdtree", PyInit_mathutils_kdtree},
#endif
{"_bpy_path", BPyInit__bpy_path},
+ {"_gawain", BPyInit_gawain},
{"bgl", BPyInit_bgl},
{"blf", BPyInit_blf},
{"bmesh", BPyInit_bmesh},
@@ -530,7 +532,8 @@ static bool python_script_exec(
if (py_dict) {
#ifdef PYMODULE_CLEAR_WORKAROUND
- PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItemString(PyThreadState_GET()->interp->modules, "__main__");
+ PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItem(
+ PyThreadState_GET()->interp->modules, bpy_intern_str___main__);
PyObject *dict_back = mmod->md_dict;
/* freeing the module will clear the namespace,
* gives problems running classes defined in this namespace being used later. */
diff --git a/source/blender/python/intern/bpy_intern_string.c b/source/blender/python/intern/bpy_intern_string.c
index ac0100fa75d..6911e985e93 100644
--- a/source/blender/python/intern/bpy_intern_string.c
+++ b/source/blender/python/intern/bpy_intern_string.c
@@ -34,21 +34,24 @@
#include "BLI_utildefines.h"
-static PyObject *bpy_intern_str_arr[13];
+static PyObject *bpy_intern_str_arr[16];
-PyObject *bpy_intern_str_register;
-PyObject *bpy_intern_str_unregister;
-PyObject *bpy_intern_str_bl_rna;
+PyObject *bpy_intern_str___doc__;
+PyObject *bpy_intern_str___main__;
+PyObject *bpy_intern_str___module__;
+PyObject *bpy_intern_str___name__;
+PyObject *bpy_intern_str___slots__;
+PyObject *bpy_intern_str_attr;
PyObject *bpy_intern_str_bl_property;
+PyObject *bpy_intern_str_bl_rna;
+PyObject *bpy_intern_str_bl_target_properties;
PyObject *bpy_intern_str_bpy_types;
+PyObject *bpy_intern_str_frame;
PyObject *bpy_intern_str_order;
-PyObject *bpy_intern_str_attr;
+PyObject *bpy_intern_str_properties;
+PyObject *bpy_intern_str_register;
PyObject *bpy_intern_str_self;
-PyObject *bpy_intern_str_frame;
-PyObject *bpy_intern_str___slots__;
-PyObject *bpy_intern_str___name__;
-PyObject *bpy_intern_str___doc__;
-PyObject *bpy_intern_str___module__;
+PyObject *bpy_intern_str_unregister;
void bpy_intern_string_init(void)
{
@@ -57,19 +60,22 @@ void bpy_intern_string_init(void)
#define BPY_INTERN_STR(var, str) \
{ var = bpy_intern_str_arr[i++] = PyUnicode_FromString(str); } (void)0
- BPY_INTERN_STR(bpy_intern_str_register, "register");
- BPY_INTERN_STR(bpy_intern_str_unregister, "unregister");
- BPY_INTERN_STR(bpy_intern_str_bl_rna, "bl_rna");
+ BPY_INTERN_STR(bpy_intern_str___doc__, "__doc__");
+ BPY_INTERN_STR(bpy_intern_str___main__, "__main__");
+ BPY_INTERN_STR(bpy_intern_str___module__, "__module__");
+ BPY_INTERN_STR(bpy_intern_str___name__, "__name__");
+ BPY_INTERN_STR(bpy_intern_str___slots__, "__slots__");
+ BPY_INTERN_STR(bpy_intern_str_attr, "attr");
BPY_INTERN_STR(bpy_intern_str_bl_property, "bl_property");
+ BPY_INTERN_STR(bpy_intern_str_bl_rna, "bl_rna");
+ BPY_INTERN_STR(bpy_intern_str_bl_target_properties, "bl_target_properties");
BPY_INTERN_STR(bpy_intern_str_bpy_types, "bpy.types");
+ BPY_INTERN_STR(bpy_intern_str_frame, "frame");
BPY_INTERN_STR(bpy_intern_str_order, "order");
- BPY_INTERN_STR(bpy_intern_str_attr, "attr");
+ BPY_INTERN_STR(bpy_intern_str_properties, "properties");
+ BPY_INTERN_STR(bpy_intern_str_register, "register");
BPY_INTERN_STR(bpy_intern_str_self, "self");
- BPY_INTERN_STR(bpy_intern_str_frame, "frame");
- BPY_INTERN_STR(bpy_intern_str___slots__, "__slots__");
- BPY_INTERN_STR(bpy_intern_str___name__, "__name__");
- BPY_INTERN_STR(bpy_intern_str___doc__, "__doc__");
- BPY_INTERN_STR(bpy_intern_str___module__, "__module__");
+ BPY_INTERN_STR(bpy_intern_str_unregister, "unregister");
#undef BPY_INTERN_STR
diff --git a/source/blender/python/intern/bpy_intern_string.h b/source/blender/python/intern/bpy_intern_string.h
index 394e84d89bd..998c312c321 100644
--- a/source/blender/python/intern/bpy_intern_string.h
+++ b/source/blender/python/intern/bpy_intern_string.h
@@ -30,18 +30,21 @@
void bpy_intern_string_init(void);
void bpy_intern_string_exit(void);
-extern PyObject *bpy_intern_str_register;
-extern PyObject *bpy_intern_str_unregister;
-extern PyObject *bpy_intern_str_bl_rna;
+extern PyObject *bpy_intern_str___doc__;
+extern PyObject *bpy_intern_str___main__;
+extern PyObject *bpy_intern_str___module__;
+extern PyObject *bpy_intern_str___name__;
+extern PyObject *bpy_intern_str___slots__;
+extern PyObject *bpy_intern_str_attr;
extern PyObject *bpy_intern_str_bl_property;
+extern PyObject *bpy_intern_str_bl_rna;
+extern PyObject *bpy_intern_str_bl_target_properties;
extern PyObject *bpy_intern_str_bpy_types;
+extern PyObject *bpy_intern_str_frame;
extern PyObject *bpy_intern_str_order;
-extern PyObject *bpy_intern_str_attr;
+extern PyObject *bpy_intern_str_properties;
+extern PyObject *bpy_intern_str_register;
extern PyObject *bpy_intern_str_self;
-extern PyObject *bpy_intern_str_frame;
-extern PyObject *bpy_intern_str___slots__;
-extern PyObject *bpy_intern_str___name__;
-extern PyObject *bpy_intern_str___doc__;
-extern PyObject *bpy_intern_str___module__;
+extern PyObject *bpy_intern_str_unregister;
#endif /* __BPY_INTERN_STRING_H__ */
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index 20226ffe6a3..4cd5e21bc22 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -38,8 +38,6 @@
#include "BLI_linklist.h"
#include "BLI_path_util.h"
-#include "BLO_readfile.h"
-
#include "BKE_main.h"
#include "BKE_library.h"
#include "BKE_idcode.h"
@@ -48,6 +46,8 @@
#include "DNA_space_types.h" /* FILE_LINK, FILE_RELPATH */
+#include "BLO_readfile.h"
+
#include "bpy_capi_utils.h"
#include "bpy_library.h"
@@ -332,6 +332,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
Main *bmain = CTX_data_main(BPy_GetContext());
Main *mainl = NULL;
int err = 0;
+ const bool do_append = ((self->flag & FILE_LINK) == 0);
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
@@ -341,7 +342,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
{
int idcode_step = 0, idcode;
while ((idcode = BKE_idcode_iter_step(&idcode_step))) {
- if (BKE_idcode_is_linkable(idcode)) {
+ if (BKE_idcode_is_linkable(idcode) && (idcode != ID_WS || do_append)) {
const char *name_plural = BKE_idcode_to_name_plural(idcode);
PyObject *ls = PyDict_GetItemString(self->dict, name_plural);
// printf("lib: %s\n", name_plural);
@@ -414,7 +415,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
BKE_main_lib_objects_recalc_all(bmain);
/* append, rather than linking */
- if ((self->flag & FILE_LINK) == 0) {
+ if (do_append) {
BKE_library_make_local(bmain, lib, old_to_new_ids, true, false);
}
}
@@ -427,7 +428,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
{
int idcode_step = 0, idcode;
while ((idcode = BKE_idcode_iter_step(&idcode_step))) {
- if (BKE_idcode_is_linkable(idcode)) {
+ if (BKE_idcode_is_linkable(idcode) && (idcode != ID_WS || do_append)) {
const char *name_plural = BKE_idcode_to_name_plural(idcode);
PyObject *ls = PyDict_GetItemString(self->dict, name_plural);
if (ls && PyList_Check(ls)) {
diff --git a/source/blender/python/intern/bpy_manipulator_wrap.c b/source/blender/python/intern/bpy_manipulator_wrap.c
new file mode 100644
index 00000000000..9df4e81ec55
--- /dev/null
+++ b/source/blender/python/intern/bpy_manipulator_wrap.c
@@ -0,0 +1,236 @@
+/*
+ * ***** 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/python/intern/bpy_manipulator_wrap.c
+ * \ingroup pythonintern
+ *
+ * This file is so Python can define widget-group's that C can call into.
+ * The generic callback functions for Python widget-group are defines in
+ * 'rna_wm.c', some calling into functions here to do python specific
+ * functionality.
+ *
+ * \note This follows 'bpy_operator_wrap.c' very closely.
+ * Keep in sync unless there is good reason not to!
+ */
+
+#include <Python.h>
+
+#include "BLI_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "bpy_rna.h"
+#include "bpy_intern_string.h"
+#include "bpy_manipulator_wrap.h" /* own include */
+
+/* we may want to add, but not now */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Manipulator
+ * \{ */
+
+
+static bool bpy_manipulatortype_target_property_def(
+ wmManipulatorType *wt, PyObject *item)
+{
+ /* Note: names based on 'rna_rna.c' */
+ PyObject *empty_tuple = PyTuple_New(0);
+
+ struct {
+ char *id;
+ char *type_id; int type;
+ int array_length;
+ } params = {
+ .id = NULL, /* not optional */
+ .type = PROP_FLOAT,
+ .type_id = NULL,
+ .array_length = 1,
+ };
+
+ static const char * const _keywords[] = {"id", "type", "array_length", NULL};
+ static _PyArg_Parser _parser = {"|$ssi:register_class", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ empty_tuple, item,
+ &_parser,
+ &params.id,
+ &params.type_id,
+ &params.array_length))
+ {
+ goto fail;
+ }
+
+ if (params.id == NULL) {
+ PyErr_SetString(PyExc_ValueError, "'id' argument not given");
+ goto fail;
+ }
+
+ if ((params.type_id != NULL) &&
+ pyrna_enum_value_from_id(
+ rna_enum_property_type_items, params.type_id, &params.type, "'type' enum value") == -1)
+ {
+ goto fail;
+ }
+ else {
+ params.type = rna_enum_property_type_items[params.type].value;
+ }
+
+ if ((params.array_length < 1 || params.array_length > RNA_MAX_ARRAY_LENGTH)) {
+ PyErr_SetString(PyExc_ValueError, "'array_length' out of range");
+ goto fail;
+ }
+
+ WM_manipulatortype_target_property_def(wt, params.id, params.type, params.array_length);
+ Py_DECREF(empty_tuple);
+ return true;
+
+fail:
+ Py_DECREF(empty_tuple);
+ return false;
+}
+
+static void manipulator_properties_init(wmManipulatorType *wt)
+{
+ PyTypeObject *py_class = wt->ext.data;
+ RNA_struct_blender_type_set(wt->ext.srna, wt);
+
+ /* only call this so pyrna_deferred_register_class gives a useful error
+ * WM_operatortype_append_ptr will call RNA_def_struct_identifier
+ * later */
+ RNA_def_struct_identifier_no_struct_map(wt->srna, wt->idname);
+
+ if (pyrna_deferred_register_class(wt->srna, py_class) != 0) {
+ PyErr_Print(); /* failed to register operator props */
+ PyErr_Clear();
+ }
+
+ /* Extract target property definitions from 'bl_target_properties' */
+ {
+ /* picky developers will notice that 'bl_targets' won't work with inheritance
+ * get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */
+ PyObject *py_class_dict = py_class->tp_dict;
+ PyObject *bl_target_properties = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_target_properties);
+
+ /* Some widgets may only exist to activate operators. */
+ if (bl_target_properties != NULL) {
+ PyObject *bl_target_properties_fast;
+ if (!(bl_target_properties_fast = PySequence_Fast(
+ bl_target_properties, "bl_target_properties sequence")))
+ {
+ /* PySequence_Fast sets the error */
+ PyErr_Print();
+ PyErr_Clear();
+ return;
+ }
+
+ const uint items_len = PySequence_Fast_GET_SIZE(bl_target_properties_fast);
+ PyObject **items = PySequence_Fast_ITEMS(bl_target_properties_fast);
+
+ for (uint i = 0; i < items_len; i++) {
+ if (!bpy_manipulatortype_target_property_def(wt, items[i])) {
+ PyErr_Print();
+ PyErr_Clear();
+ break;
+ }
+ }
+
+ Py_DECREF(bl_target_properties_fast);
+ }
+ }
+}
+
+void BPY_RNA_manipulator_wrapper(wmManipulatorType *wt, void *userdata)
+{
+ /* take care not to overwrite anything set in
+ * WM_manipulatormaptype_group_link_ptr before opfunc() is called */
+ StructRNA *srna = wt->srna;
+ *wt = *((wmManipulatorType *)userdata);
+ wt->srna = srna; /* restore */
+
+ /* don't do translations here yet */
+#if 0
+ /* Use i18n context from ext.srna if possible (py manipulatorgroups). */
+ if (wt->ext.srna) {
+ RNA_def_struct_translation_context(wt->srna, RNA_struct_translation_context(wt->ext.srna));
+ }
+#endif
+
+ wt->struct_size = sizeof(wmManipulator);
+
+ manipulator_properties_init(wt);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Manipulator Group
+ * \{ */
+
+static void manipulatorgroup_properties_init(wmManipulatorGroupType *wgt)
+{
+#ifdef USE_SRNA
+ PyTypeObject *py_class = wgt->ext.data;
+#endif
+ RNA_struct_blender_type_set(wgt->ext.srna, wgt);
+
+#ifdef USE_SRNA
+ /* only call this so pyrna_deferred_register_class gives a useful error
+ * WM_operatortype_append_ptr will call RNA_def_struct_identifier
+ * later */
+ RNA_def_struct_identifier(wgt->srna, wgt->idname);
+
+ if (pyrna_deferred_register_class(wgt->srna, py_class) != 0) {
+ PyErr_Print(); /* failed to register operator props */
+ PyErr_Clear();
+ }
+#endif
+}
+
+void BPY_RNA_manipulatorgroup_wrapper(wmManipulatorGroupType *wgt, void *userdata)
+{
+ /* take care not to overwrite anything set in
+ * WM_manipulatormaptype_group_link_ptr before opfunc() is called */
+#ifdef USE_SRNA
+ StructRNA *srna = wgt->srna;
+#endif
+ *wgt = *((wmManipulatorGroupType *)userdata);
+#ifdef USE_SRNA
+ wgt->srna = srna; /* restore */
+#endif
+
+#ifdef USE_SRNA
+ /* Use i18n context from ext.srna if possible (py manipulatorgroups). */
+ if (wgt->ext.srna) {
+ RNA_def_struct_translation_context(wgt->srna, RNA_struct_translation_context(wgt->ext.srna));
+ }
+#endif
+
+ manipulatorgroup_properties_init(wgt);
+}
+
+/** \} */
+
diff --git a/source/blender/python/intern/bpy_manipulator_wrap.h b/source/blender/python/intern/bpy_manipulator_wrap.h
new file mode 100644
index 00000000000..3f739e26059
--- /dev/null
+++ b/source/blender/python/intern/bpy_manipulator_wrap.h
@@ -0,0 +1,36 @@
+/*
+ * ***** 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/python/intern/bpy_manipulator_wrap.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_MANIPULATOR_WRAP_H__
+#define __BPY_MANIPULATOR_WRAP_H__
+
+struct wmManipulatorType;
+struct wmManipulatorGroupType;
+
+/* exposed to rna/wm api */
+void BPY_RNA_manipulator_wrapper(struct wmManipulatorType *wt, void *userdata);
+void BPY_RNA_manipulatorgroup_wrapper(struct wmManipulatorGroupType *wgt, void *userdata);
+
+#endif /* __BPY_MANIPULATOR_WRAP_H__ */
+
diff --git a/source/blender/python/intern/bpy_msgbus.c b/source/blender/python/intern/bpy_msgbus.c
new file mode 100644
index 00000000000..945d2a9b6cc
--- /dev/null
+++ b/source/blender/python/intern/bpy_msgbus.c
@@ -0,0 +1,400 @@
+/*
+ * ***** 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/python/intern/bpy_msgbus.c
+ * \ingroup pythonintern
+ * This file defines '_bpy_msgbus' module, exposed as 'bpy.msgbus'.
+ */
+
+#include <Python.h>
+
+#include "../generic/python_utildefines.h"
+#include "../generic/py_capi_utils.h"
+#include "../mathutils/mathutils.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "WM_message.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "bpy_capi_utils.h"
+#include "bpy_rna.h"
+#include "bpy_intern_string.h"
+#include "bpy_manipulator_wrap.h" /* own include */
+
+
+#include "bpy_msgbus.h" /* own include */
+
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Utils
+ * \{ */
+
+#define BPY_MSGBUS_RNA_MSGKEY_DOC \
+" :arg key: Represents the type of data being subscribed to\n" \
+"\n" \
+" Arguments include\n" \
+" - :class:`bpy.types.Property` instance.\n" \
+" - :class:`bpy.types.Struct` type.\n" \
+" - (:class:`bpy.types.Struct`, str) type and property name.\n" \
+" :type key: Muliple\n"
+
+/**
+ * There are multiple ways we can get RNA from Python,
+ * it's also possible to register a type instead of an instance.
+ *
+ * This function handles converting Python to RNA subscription information.
+ *
+ * \param py_sub: See #BPY_MSGBUS_RNA_MSGKEY_DOC for description.
+ * \param msg_key_params: Message key with all members zeroed out.
+ * \return -1 on failure, 0 on success.
+ */
+static int py_msgbus_rna_key_from_py(
+ PyObject *py_sub,
+ wmMsgParams_RNA *msg_key_params,
+ const char *error_prefix)
+{
+
+ /* Allow common case, object rotation, location - etc. */
+ if (BaseMathObject_CheckExact(py_sub)) {
+ BaseMathObject *py_sub_math = (BaseMathObject *)py_sub;
+ if (py_sub_math->cb_user == NULL) {
+ PyErr_Format(
+ PyExc_TypeError,
+ "%s: math argument has no owner",
+ error_prefix);
+ return -1;
+ }
+ py_sub = py_sub_math->cb_user;
+ /* Common case will use BPy_PropertyRNA_Check below. */
+ }
+
+ if (BPy_PropertyRNA_Check(py_sub)) {
+ BPy_PropertyRNA *data_prop = (BPy_PropertyRNA *)py_sub;
+ PYRNA_PROP_CHECK_INT(data_prop);
+ msg_key_params->ptr = data_prop->ptr;
+ msg_key_params->prop = data_prop->prop;
+ }
+ else if (BPy_StructRNA_Check(py_sub)) {
+ /* note, this isn't typically used since we don't edit structs directly. */
+ BPy_StructRNA *data_srna = (BPy_StructRNA *)py_sub;
+ PYRNA_STRUCT_CHECK_INT(data_srna);
+ msg_key_params->ptr = data_srna->ptr;
+ }
+ /* TODO - property / type, not instance. */
+ else if (PyType_Check(py_sub)) {
+ StructRNA *data_type = pyrna_struct_as_srna(py_sub, false, error_prefix);
+ if (data_type == NULL) {
+ return -1;
+ }
+ msg_key_params->ptr.type = data_type;
+ }
+ else if (PyTuple_CheckExact(py_sub)) {
+ if (PyTuple_GET_SIZE(py_sub) == 2) {
+ PyObject *data_type_py = PyTuple_GET_ITEM(py_sub, 0);
+ PyObject *data_prop_py = PyTuple_GET_ITEM(py_sub, 1);
+ StructRNA *data_type = pyrna_struct_as_srna(data_type_py, false, error_prefix);
+ if (data_type == NULL) {
+ return -1;
+ }
+ if (!PyUnicode_CheckExact(data_prop_py)) {
+ PyErr_Format(
+ PyExc_TypeError,
+ "%s: expected property to be a string",
+ error_prefix);
+ return -1;
+ }
+ PointerRNA data_type_ptr = { .type = data_type, };
+ const char *data_prop_str = _PyUnicode_AsString(data_prop_py);
+ PropertyRNA *data_prop = RNA_struct_find_property(&data_type_ptr, data_prop_str);
+
+ if (data_prop == NULL) {
+ PyErr_Format(
+ PyExc_TypeError,
+ "%s: struct %.200s does not contain property %.200s",
+ error_prefix,
+ RNA_struct_identifier(data_type),
+ data_prop_str);
+ return -1;
+ }
+
+ msg_key_params->ptr.type = data_type;
+ msg_key_params->prop = data_prop;
+ }
+ else {
+ PyErr_Format(
+ PyExc_ValueError,
+ "%s: Expected a pair (type, property_id)",
+ error_prefix);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Callbacks
+ * \{ */
+
+#define BPY_MSGBUS_USER_DATA_LEN 2
+
+/* Follow wmMsgNotifyFn spec */
+static void bpy_msgbus_notify(
+ bContext *C, wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
+{
+ PyGILState_STATE gilstate;
+ bpy_context_set(C, &gilstate);
+
+ PyObject *user_data = msg_val->user_data;
+ BLI_assert(PyTuple_GET_SIZE(user_data) == BPY_MSGBUS_USER_DATA_LEN);
+
+ PyObject *callback_args = PyTuple_GET_ITEM(user_data, 0);
+ PyObject *callback_notify = PyTuple_GET_ITEM(user_data, 1);
+
+ const bool is_write_ok = pyrna_write_check();
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ PyObject *ret = PyObject_CallObject(callback_notify, callback_args);
+
+ if (ret == NULL) {
+ PyC_Err_PrintWithFunc(callback_notify);
+ }
+ else {
+ if (ret != Py_None) {
+ PyErr_SetString(PyExc_ValueError, "the return value must be None");
+ PyC_Err_PrintWithFunc(callback_notify);
+ }
+ Py_DECREF(ret);
+ }
+
+ bpy_context_clear(C, &gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+/* Follow wmMsgSubscribeValueFreeDataFn spec */
+static void bpy_msgbus_subscribe_value_free_data(
+ struct wmMsgSubscribeKey *UNUSED(msg_key), struct wmMsgSubscribeValue *msg_val)
+{
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+ Py_DECREF(msg_val->owner);
+ Py_DECREF(msg_val->user_data);
+ PyGILState_Release(gilstate);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Public Message Bus API
+ * \{ */
+
+PyDoc_STRVAR(bpy_msgbus_subscribe_rna_doc,
+".. function:: subscribe_rna(data, owner, args, notify)\n"
+"\n"
+BPY_MSGBUS_RNA_MSGKEY_DOC
+" :arg owner: Handle for this subscription (compared by identity).\n"
+" :type owner: Any type.\n"
+"\n"
+" Returns a new vector int property definition.\n"
+);
+static PyObject *bpy_msgbus_subscribe_rna(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ const char *error_prefix = "subscribe_rna";
+ PyObject *py_sub = NULL;
+ PyObject *py_owner = NULL;
+ PyObject *callback_args = NULL;
+ PyObject *callback_notify = NULL;
+
+ enum {
+ IS_PERSISTENT = (1 << 0),
+ };
+ PyObject *py_options = NULL;
+ EnumPropertyItem py_options_enum[] = {
+ {IS_PERSISTENT, "PERSISTENT", 0, ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ int options = 0;
+
+ static const char *_keywords[] = {
+ "key",
+ "owner",
+ "args",
+ "notify",
+ "options",
+ NULL,
+ };
+ static _PyArg_Parser _parser = {"$OOO!OO!:subscribe_rna", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser,
+ &py_sub, &py_owner,
+ &PyTuple_Type, &callback_args,
+ &callback_notify,
+ &PySet_Type, &py_options))
+ {
+ return NULL;
+ }
+
+ if (py_options &&
+ (pyrna_set_to_enum_bitfield(py_options_enum, py_options, &options, error_prefix)) == -1)
+ {
+ return NULL;
+ }
+
+ /* Note: we may want to have a way to pass this in. */
+ bContext *C = (bContext *)BPy_GetContext();
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ wmMsgParams_RNA msg_key_params = {0};
+
+ wmMsgSubscribeValue msg_val_params = {0};
+
+ if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) {
+ return NULL;
+ }
+
+ if (!PyFunction_Check(callback_notify)) {
+ PyErr_Format(
+ PyExc_TypeError,
+ "notify expects a function, found %.200s",
+ Py_TYPE(callback_notify)->tp_name);
+ return NULL;
+ }
+
+ if (options != 0) {
+ if (options & IS_PERSISTENT) {
+ msg_val_params.is_persistent = true;
+ }
+ }
+
+ /* owner can be anything. */
+ {
+ msg_val_params.owner = py_owner;
+ Py_INCREF(py_owner);
+ }
+
+ {
+ PyObject *user_data = PyTuple_New(2);
+ PyTuple_SET_ITEMS(
+ user_data,
+ Py_INCREF_RET(callback_args),
+ Py_INCREF_RET(callback_notify));
+ msg_val_params.user_data = user_data;
+ }
+
+ msg_val_params.notify = bpy_msgbus_notify;
+ msg_val_params.free_data = bpy_msgbus_subscribe_value_free_data;
+
+ WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_val_params, __func__);
+
+ WM_msg_dump(mbus, __func__);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpy_msgbus_publish_rna_doc,
+".. function:: publish_rna(data, owner, args, notify)\n"
+"\n"
+BPY_MSGBUS_RNA_MSGKEY_DOC
+"\n"
+" Notify subscribers of changes to this property\n"
+" (this typically doesn't need to be called explicitly since changes will automatically publish updates).\n"
+" In some cases it may be useful to publish changes explicitly using more general keys.\n"
+);
+static PyObject *bpy_msgbus_publish_rna(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ const char *error_prefix = "publish_rna";
+ PyObject *py_sub = NULL;
+
+ static const char *_keywords[] = {
+ "key",
+ NULL,
+ };
+ static _PyArg_Parser _parser = {"$O:publish_rna", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser,
+ &py_sub))
+ {
+ return NULL;
+ }
+
+ /* Note: we may want to have a way to pass this in. */
+ bContext *C = (bContext *)BPy_GetContext();
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ wmMsgParams_RNA msg_key_params = {0};
+
+ if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) {
+ return NULL;
+ }
+
+ WM_msg_publish_rna_params(mbus, &msg_key_params);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpy_msgbus_clear_by_owner_doc,
+".. function:: clear_by_owner(owner)\n"
+"\n"
+" Clear all subscribers using this owner.\n"
+);
+static PyObject *bpy_msgbus_clear_by_owner(PyObject *UNUSED(self), PyObject *py_owner)
+{
+ bContext *C = (bContext *)BPy_GetContext();
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ WM_msgbus_clear_by_owner(mbus, py_owner);
+ Py_RETURN_NONE;
+}
+
+static struct PyMethodDef BPy_msgbus_methods[] = {
+ {"subscribe_rna", (PyCFunction)bpy_msgbus_subscribe_rna, METH_VARARGS | METH_KEYWORDS, bpy_msgbus_subscribe_rna_doc},
+ {"publish_rna", (PyCFunction)bpy_msgbus_publish_rna, METH_VARARGS | METH_KEYWORDS, bpy_msgbus_publish_rna_doc},
+ {"clear_by_owner", (PyCFunction)bpy_msgbus_clear_by_owner, METH_O, bpy_msgbus_clear_by_owner_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyModuleDef _bpy_msgbus_def = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "msgbus",
+ .m_methods = BPy_msgbus_methods,
+};
+
+
+PyObject *BPY_msgbus_module(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&_bpy_msgbus_def);
+
+ return submodule;
+}
+
+/** \} */
+
diff --git a/source/blender/python/intern/bpy_msgbus.h b/source/blender/python/intern/bpy_msgbus.h
new file mode 100644
index 00000000000..97b20e9b926
--- /dev/null
+++ b/source/blender/python/intern/bpy_msgbus.h
@@ -0,0 +1,30 @@
+/*
+ * ***** 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/python/intern/bpy_msgbus.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_MSGBUS_H__
+#define __BPY_MSGBUS_H__
+
+PyObject *BPY_msgbus_module(void);
+
+#endif /* __BPY_MSGBUS_H__ */
diff --git a/source/blender/python/intern/bpy_props.h b/source/blender/python/intern/bpy_props.h
index 614c1b4b708..fa2594f94d2 100644
--- a/source/blender/python/intern/bpy_props.h
+++ b/source/blender/python/intern/bpy_props.h
@@ -34,6 +34,6 @@ PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw);
PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw);
StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix);
-#define PYRNA_STACK_ARRAY 32
+#define PYRNA_STACK_ARRAY RNA_STACK_ARRAY
#endif
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 1a9fd920af5..fdad3a7d919 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -312,7 +312,7 @@ static bool rna_id_write_error(PointerRNA *ptr, PyObject *key)
ID *id = ptr->id.data;
if (id) {
const short idcode = GS(id->name);
- if (!ELEM(idcode, ID_WM, ID_SCR)) { /* may need more added here */
+ if (!ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { /* may need more added here */
const char *idtype = BKE_idcode_to_name(idcode);
const char *pyname;
if (key && PyUnicode_Check(key)) pyname = _PyUnicode_AsString(key);
@@ -1847,19 +1847,28 @@ static int pyrna_py_to_prop(
* class mixing if this causes problems in the future it should be removed.
*/
if ((ptr_type == &RNA_AnyType) &&
- (BPy_StructRNA_Check(value)) &&
- (RNA_struct_is_a(((BPy_StructRNA *)value)->ptr.type, &RNA_Operator)))
+ (BPy_StructRNA_Check(value)))
{
- value = PyObject_GetAttrString(value, "properties");
- value_new = value;
+ const StructRNA *base_type =
+ RNA_struct_base_child_of(((const BPy_StructRNA *)value)->ptr.type, NULL);
+ if (ELEM(base_type, &RNA_Operator, &RNA_Manipulator)) {
+ value = PyObject_GetAttr(value, bpy_intern_str_properties);
+ value_new = value;
+ }
}
-
- /* if property is an OperatorProperties pointer and value is a map,
+ /* if property is an OperatorProperties/ManipulatorProperties pointer and value is a map,
* forward back to pyrna_pydict_to_props */
- if (RNA_struct_is_a(ptr_type, &RNA_OperatorProperties) && PyDict_Check(value)) {
- PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
- return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+ if (PyDict_Check(value)) {
+ const StructRNA *base_type = RNA_struct_base_child_of(ptr_type, NULL);
+ if (base_type == &RNA_OperatorProperties) {
+ PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
+ return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+ }
+ else if (base_type == &RNA_ManipulatorProperties) {
+ PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
+ return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+ }
}
/* another exception, allow to pass a collection as an RNA property */
@@ -6762,7 +6771,30 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
if (ptr->data == NULL && ptr->type == NULL) { /* Operator RNA has NULL data */
Py_RETURN_NONE;
}
- else {
+
+ /* New in 2.8x, since not many types support instancing
+ * we may want to use a flag to avoid looping over all classes. - campbell */
+ void **instance = ptr->data ? RNA_struct_instance(ptr) : NULL;
+ if (instance && *instance) {
+ pyrna = *instance;
+
+ /* Refine may have changed types after the first instance was created. */
+ if (ptr->type == pyrna->ptr.type) {
+ Py_INCREF(pyrna);
+ return (PyObject *)pyrna;
+ }
+ else {
+ /* Existing users will need to use 'type_recast' method. */
+ Py_DECREF(pyrna);
+ *instance = NULL;
+ /* Continue as if no instance was made */
+#if 0 /* no need to assign, will be written to next... */
+ pyrna = NULL;
+#endif
+ }
+ }
+
+ {
PyTypeObject *tp = (PyTypeObject *)pyrna_struct_Subtype(ptr);
if (tp) {
@@ -6783,6 +6815,12 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
return NULL;
}
+ /* Blender's instance owns a reference (to avoid Python freeing it). */
+ if (instance) {
+ *instance = pyrna;
+ Py_INCREF(pyrna);
+ }
+
pyrna->ptr = *ptr;
#ifdef PYRNA_FREE_SUPPORT
pyrna->freeptr = false;
@@ -7547,7 +7585,6 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
PyObject *args;
PyObject *ret = NULL, *py_srna = NULL, *py_class_instance = NULL, *parmitem;
PyTypeObject *py_class;
- void **py_class_instance_store = NULL;
PropertyRNA *parm;
ParameterIterator iter;
PointerRNA funcptr;
@@ -7562,7 +7599,8 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
PyGILState_STATE gilstate;
#ifdef USE_PEDANTIC_WRITE
- const bool is_operator = RNA_struct_is_a(ptr->type, &RNA_Operator);
+ const bool is_readonly_init = !(RNA_struct_is_a(ptr->type, &RNA_Operator) ||
+ RNA_struct_is_a(ptr->type, &RNA_Manipulator));
// const char *func_id = RNA_function_identifier(func); /* UNUSED */
/* testing, for correctness, not operator and not draw function */
const bool is_readonly = !(RNA_function_flag(func) & FUNC_ALLOW_WRITE);
@@ -7597,10 +7635,6 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
py_class_instance = *instance;
Py_INCREF(py_class_instance);
}
- else {
- /* store the instance here once its created */
- py_class_instance_store = instance;
- }
}
}
/* end exception */
@@ -7627,7 +7661,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
if (py_class->tp_init) {
#ifdef USE_PEDANTIC_WRITE
const int prev_write = rna_disallow_writes;
- rna_disallow_writes = is_operator ? false : true; /* only operators can write on __init__ */
+ rna_disallow_writes = is_readonly_init ? false : true; /* only operators can write on __init__ */
#endif
/* true in most cases even when the class its self doesn't define an __init__ function. */
@@ -7671,10 +7705,6 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
if (py_class_instance == NULL) {
err = -1; /* so the error is not overridden below */
}
- else if (py_class_instance_store) {
- *py_class_instance_store = py_class_instance;
- Py_INCREF(py_class_instance);
- }
}
}
diff --git a/source/blender/python/intern/bpy_rna_manipulator.c b/source/blender/python/intern/bpy_rna_manipulator.c
new file mode 100644
index 00000000000..950f7f98be0
--- /dev/null
+++ b/source/blender/python/intern/bpy_rna_manipulator.c
@@ -0,0 +1,565 @@
+/*
+ * ***** 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/python/intern/bpy_rna_manipulator.c
+ * \ingroup pythonintern
+ *
+ * .
+ */
+
+#include <Python.h>
+#include <stddef.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+
+#include "BKE_main.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "bpy_capi_utils.h"
+#include "bpy_rna_manipulator.h"
+
+#include "../generic/py_capi_utils.h"
+#include "../generic/python_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+#include "RNA_enum_types.h"
+
+#include "bpy_rna.h"
+
+
+/* -------------------------------------------------------------------- */
+/** \name Manipulator Target Property Define API
+ * \{ */
+
+enum {
+ BPY_MANIPULATOR_FN_SLOT_GET = 0,
+ BPY_MANIPULATOR_FN_SLOT_SET,
+ BPY_MANIPULATOR_FN_SLOT_RANGE_GET,
+};
+#define BPY_MANIPULATOR_FN_SLOT_LEN (BPY_MANIPULATOR_FN_SLOT_RANGE_GET + 1)
+
+struct BPyManipulatorHandlerUserData {
+
+ PyObject *fn_slots[BPY_MANIPULATOR_FN_SLOT_LEN];
+};
+
+static void py_rna_manipulator_handler_get_cb(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ struct BPyManipulatorHandlerUserData *data = mpr_prop->custom_func.user_data;
+ PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_MANIPULATOR_FN_SLOT_GET], NULL);
+ if (ret == NULL) {
+ goto fail;
+ }
+
+ if (mpr_prop->type->data_type == PROP_FLOAT) {
+ float *value = value_p;
+ if (mpr_prop->type->array_length == 1) {
+ if ((*value = PyFloat_AsDouble(ret)) == -1.0f && PyErr_Occurred()) {
+ goto fail;
+ }
+ }
+ else {
+ if (PyC_AsArray(value, ret, mpr_prop->type->array_length, &PyFloat_Type, false,
+ "Manipulator get callback: ") == -1)
+ {
+ goto fail;
+ }
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
+ goto fail;
+ }
+
+ Py_DECREF(ret);
+
+ PyGILState_Release(gilstate);
+ return;
+
+fail:
+ PyErr_Print();
+ PyErr_Clear();
+
+ PyGILState_Release(gilstate);
+}
+
+static void py_rna_manipulator_handler_set_cb(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
+ const void *value_p)
+{
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ struct BPyManipulatorHandlerUserData *data = mpr_prop->custom_func.user_data;
+
+ PyObject *args = PyTuple_New(1);
+
+ if (mpr_prop->type->data_type == PROP_FLOAT) {
+ const float *value = value_p;
+ PyObject *py_value;
+ if (mpr_prop->type->array_length == 1) {
+ py_value = PyFloat_FromDouble(*value);
+ }
+ else {
+ py_value = PyC_Tuple_PackArray_F32(value, mpr_prop->type->array_length);
+ }
+ if (py_value == NULL) {
+ goto fail;
+ }
+ PyTuple_SET_ITEM(args, 0, py_value);
+ }
+ else {
+ PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
+ goto fail;
+ }
+
+ PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_MANIPULATOR_FN_SLOT_SET], args);
+ if (ret == NULL) {
+ goto fail;
+ }
+ Py_DECREF(ret);
+
+ PyGILState_Release(gilstate);
+ return;
+
+fail:
+ PyErr_Print();
+ PyErr_Clear();
+
+ Py_DECREF(args);
+
+ PyGILState_Release(gilstate);
+}
+
+static void py_rna_manipulator_handler_range_get_cb(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
+ void *value_p)
+{
+ struct BPyManipulatorHandlerUserData *data = mpr_prop->custom_func.user_data;
+
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_MANIPULATOR_FN_SLOT_RANGE_GET], NULL);
+ if (ret == NULL) {
+ goto fail;
+ }
+
+ if (!PyTuple_Check(ret)) {
+ PyErr_Format(PyExc_TypeError,
+ "Expected a tuple, not %.200s",
+ Py_TYPE(ret)->tp_name);
+ goto fail;
+ }
+
+ if (PyTuple_GET_SIZE(ret) != 2) {
+ PyErr_Format(PyExc_TypeError,
+ "Expected a tuple of size 2, not %d",
+ PyTuple_GET_SIZE(ret));
+ goto fail;
+ }
+
+ if (mpr_prop->type->data_type == PROP_FLOAT) {
+ float range[2];
+ for (int i = 0; i < 2; i++) {
+ if (((range[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(ret, i))) == -1.0f && PyErr_Occurred()) == 0) {
+ /* pass */
+ }
+ else {
+ goto fail;
+ }
+ }
+ memcpy(value_p, range, sizeof(range));
+ }
+ else {
+ PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
+ goto fail;
+ }
+
+ Py_DECREF(ret);
+ PyGILState_Release(gilstate);
+ return;
+
+fail:
+ Py_XDECREF(ret);
+
+ PyErr_Print();
+ PyErr_Clear();
+
+ PyGILState_Release(gilstate);
+}
+
+static void py_rna_manipulator_handler_free_cb(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop)
+{
+ struct BPyManipulatorHandlerUserData *data = mpr_prop->custom_func.user_data;
+
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+ for (int i = 0; i < BPY_MANIPULATOR_FN_SLOT_LEN; i++) {
+ Py_XDECREF(data->fn_slots[i]);
+ }
+ PyGILState_Release(gilstate);
+
+ MEM_freeN(data);
+
+}
+
+PyDoc_STRVAR(bpy_manipulator_target_set_handler_doc,
+".. method:: target_set_handler(target, get, set, range=None):\n"
+"\n"
+" Assigns callbacks to a manipulators property.\n"
+"\n"
+" :arg get: Function that returns the value for this property (single value or sequence).\n"
+" :type get: callable\n"
+" :arg set: Function that takes a single value argument and applies it.\n"
+" :type set: callable\n"
+" :arg range: Function that returns a (min, max) tuple for manipulators that use a range.\n"
+" :type range: callable\n"
+);
+static PyObject *bpy_manipulator_target_set_handler(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ PyGILState_STATE gilstate = PyGILState_Ensure();
+
+ struct {
+ PyObject *self;
+ char *target;
+ PyObject *py_fn_slots[BPY_MANIPULATOR_FN_SLOT_LEN];
+ } params = {
+ .self = NULL,
+ .target = NULL,
+ .py_fn_slots = {NULL},
+ };
+
+ /* Note: this is a counter-part to functions:
+ * 'Manipulator.target_set_prop & target_set_operator'
+ * (see: rna_wm_manipulator_api.c). conventions should match. */
+ static const char * const _keywords[] = {"self", "target", "get", "set", "range", NULL};
+ static _PyArg_Parser _parser = {"Os|$OOO:target_set_handler", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser,
+ &params.self,
+ &params.target,
+ &params.py_fn_slots[BPY_MANIPULATOR_FN_SLOT_GET],
+ &params.py_fn_slots[BPY_MANIPULATOR_FN_SLOT_SET],
+ &params.py_fn_slots[BPY_MANIPULATOR_FN_SLOT_RANGE_GET]))
+ {
+ goto fail;
+ }
+
+ wmManipulator *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
+
+ const wmManipulatorPropertyType *mpr_prop_type =
+ WM_manipulatortype_target_property_find(mpr->type, params.target);
+ if (mpr_prop_type == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "Manipulator target property '%s.%s' not found",
+ mpr->type->idname, params.target);
+ goto fail;
+ }
+
+ {
+ const int slots_required = 2;
+ const int slots_start = 2;
+ for (int i = 0; i < BPY_MANIPULATOR_FN_SLOT_LEN; i++) {
+ if (params.py_fn_slots[i] == NULL) {
+ if (i < slots_required) {
+ PyErr_Format(PyExc_ValueError, "Argument '%s' not given", _keywords[slots_start + i]);
+ goto fail;
+ }
+ }
+ else if (!PyCallable_Check(params.py_fn_slots[i])) {
+ PyErr_Format(PyExc_ValueError, "Argument '%s' not callable", _keywords[slots_start + i]);
+ goto fail;
+ }
+ }
+ }
+
+ struct BPyManipulatorHandlerUserData *data = MEM_callocN(sizeof(*data), __func__);
+
+ for (int i = 0; i < BPY_MANIPULATOR_FN_SLOT_LEN; i++) {
+ data->fn_slots[i] = params.py_fn_slots[i];
+ Py_XINCREF(params.py_fn_slots[i]);
+ }
+
+ WM_manipulator_target_property_def_func_ptr(
+ mpr, mpr_prop_type,
+ &(const struct wmManipulatorPropertyFnParams) {
+ .value_get_fn = py_rna_manipulator_handler_get_cb,
+ .value_set_fn = py_rna_manipulator_handler_set_cb,
+ .range_get_fn = py_rna_manipulator_handler_range_get_cb,
+ .free_fn = py_rna_manipulator_handler_free_cb,
+ .user_data = data,
+ });
+
+ PyGILState_Release(gilstate);
+
+ Py_RETURN_NONE;
+
+fail:
+ PyGILState_Release(gilstate);
+ return NULL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Manipulator Target Property Access API
+ * \{ */
+
+PyDoc_STRVAR(bpy_manipulator_target_get_value_doc,
+".. method:: target_get_value(target):\n"
+"\n"
+" Get the value of this target property.\n"
+"\n"
+" :arg target: Target property name.\n"
+" :type target: string\n"
+" :return: The value of the target property.\n"
+" :rtype: Single value or array based on the target type\n"
+);
+static PyObject *bpy_manipulator_target_get_value(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ struct {
+ PyObject *self;
+ char *target;
+ } params = {
+ .self = NULL,
+ .target = NULL,
+ };
+
+ static const char * const _keywords[] = {"self", "target", NULL};
+ static _PyArg_Parser _parser = {"Os:target_get_value", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser,
+ &params.self,
+ &params.target))
+ {
+ goto fail;
+ }
+
+ wmManipulator *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
+
+ wmManipulatorProperty *mpr_prop =
+ WM_manipulator_target_property_find(mpr, params.target);
+ if (mpr_prop == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "Manipulator target property '%s.%s' not found",
+ mpr->type->idname, params.target);
+ goto fail;
+ }
+
+ const int array_len = WM_manipulator_target_property_array_length(mpr, mpr_prop);
+ switch (mpr_prop->type->data_type) {
+ case PROP_FLOAT:
+ {
+ if (array_len != 0) {
+ float *value = BLI_array_alloca(value, array_len);
+ WM_manipulator_target_property_value_get_array(mpr, mpr_prop, value);
+ return PyC_Tuple_PackArray_F32(value, array_len);
+ }
+ else {
+ float value = WM_manipulator_target_property_value_get(mpr, mpr_prop);
+ return PyFloat_FromDouble(value);
+ }
+ break;
+ }
+ default:
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
+ goto fail;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+PyDoc_STRVAR(bpy_manipulator_target_set_value_doc,
+".. method:: target_set_value(target):\n"
+"\n"
+" Set the value of this target property.\n"
+"\n"
+" :arg target: Target property name.\n"
+" :type target: string\n"
+);
+static PyObject *bpy_manipulator_target_set_value(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ struct {
+ PyObject *self;
+ char *target;
+ PyObject *value;
+ } params = {
+ .self = NULL,
+ .target = NULL,
+ .value = NULL,
+ };
+
+ static const char * const _keywords[] = {"self", "target", "value", NULL};
+ static _PyArg_Parser _parser = {"OsO:target_set_value", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser,
+ &params.self,
+ &params.target,
+ &params.value))
+ {
+ goto fail;
+ }
+
+ wmManipulator *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
+
+ wmManipulatorProperty *mpr_prop =
+ WM_manipulator_target_property_find(mpr, params.target);
+ if (mpr_prop == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "Manipulator target property '%s.%s' not found",
+ mpr->type->idname, params.target);
+ goto fail;
+ }
+
+ const int array_len = WM_manipulator_target_property_array_length(mpr, mpr_prop);
+ switch (mpr_prop->type->data_type) {
+ case PROP_FLOAT:
+ {
+ if (array_len != 0) {
+ float *value = BLI_array_alloca(value, array_len);
+ if (PyC_AsArray(value, params.value, mpr_prop->type->array_length, &PyFloat_Type, false,
+ "Manipulator target property array") == -1)
+ {
+ goto fail;
+ }
+ WM_manipulator_target_property_value_set_array(BPy_GetContext(), mpr, mpr_prop, value);
+ }
+ else {
+ float value;
+ if ((value = PyFloat_AsDouble(params.value)) == -1.0f && PyErr_Occurred()) {
+ goto fail;
+ }
+ WM_manipulator_target_property_value_set(BPy_GetContext(), mpr, mpr_prop, value);
+ }
+ Py_RETURN_NONE;
+ }
+ default:
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
+ goto fail;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+
+PyDoc_STRVAR(bpy_manipulator_target_get_range_doc,
+".. method:: target_get_range(target):\n"
+"\n"
+" Get the range for this target property.\n"
+"\n"
+" :arg target: Target property name.\n"
+" :Get the range for this target property"
+" :return: The range of this property (min, max).\n"
+" :rtype: tuple pair.\n"
+);
+static PyObject *bpy_manipulator_target_get_range(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ struct {
+ PyObject *self;
+ char *target;
+ } params = {
+ .self = NULL,
+ .target = NULL,
+ };
+
+ static const char * const _keywords[] = {"self", "target", NULL};
+ static _PyArg_Parser _parser = {"Os:target_get_range", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser,
+ &params.self,
+ &params.target))
+ {
+ goto fail;
+ }
+
+ wmManipulator *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
+
+ wmManipulatorProperty *mpr_prop =
+ WM_manipulator_target_property_find(mpr, params.target);
+ if (mpr_prop == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "Manipulator target property '%s.%s' not found",
+ mpr->type->idname, params.target);
+ goto fail;
+ }
+
+ switch (mpr_prop->type->data_type) {
+ case PROP_FLOAT:
+ {
+ float range[2];
+ WM_manipulator_target_property_range_get(mpr, mpr_prop, range);
+ return PyC_Tuple_PackArray_F32(range, 2);
+ }
+ default:
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
+ goto fail;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+/** \} */
+
+int BPY_rna_manipulator_module(PyObject *mod_par)
+{
+ static PyMethodDef method_def_array[] = {
+ /* Manipulator Target Property Define API */
+ {"target_set_handler", (PyCFunction)bpy_manipulator_target_set_handler,
+ METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_set_handler_doc},
+ /* Manipulator Target Property Access API */
+ {"target_get_value", (PyCFunction)bpy_manipulator_target_get_value,
+ METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_get_value_doc},
+ {"target_set_value", (PyCFunction)bpy_manipulator_target_set_value,
+ METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_set_value_doc},
+ {"target_get_range", (PyCFunction)bpy_manipulator_target_get_range,
+ METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_get_range_doc},
+ /* no sentinel needed. */
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(method_def_array); i++) {
+ PyMethodDef *m = &method_def_array[i];
+ PyObject *func = PyCFunction_New(m, NULL);
+ PyObject *func_inst = PyInstanceMethod_New(func);
+ char name_prefix[128];
+ PyOS_snprintf(name_prefix, sizeof(name_prefix), "_rna_manipulator_%s", m->ml_name);
+ /* TODO, return a type that binds nearly to a method. */
+ PyModule_AddObject(mod_par, name_prefix, func_inst);
+ }
+
+ return 0;
+}
diff --git a/source/blender/python/intern/bpy_rna_manipulator.h b/source/blender/python/intern/bpy_rna_manipulator.h
new file mode 100644
index 00000000000..b6f3a2e651d
--- /dev/null
+++ b/source/blender/python/intern/bpy_rna_manipulator.h
@@ -0,0 +1,32 @@
+/*
+ * ***** 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): Bastien Montagne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_rna_manipulator.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_RNA_MANIPULATOR_H__
+#define __BPY_RNA_MANIPULATOR_H__
+
+int BPY_rna_manipulator_module(PyObject *);
+
+#endif /* __BPY_RNA_MANIPULATOR_H__ */
diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c
index 60ce00c583e..a7a0ae78f26 100644
--- a/source/blender/python/intern/gpu.c
+++ b/source/blender/python/intern/gpu.c
@@ -337,6 +337,14 @@ PyObject *GPU_initPython(void)
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
+ PyModule_AddObject(module, "matrix", (submodule = BPyInit_gpu_matrix()));
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
+ Py_INCREF(submodule);
+
+ PyModule_AddObject(module, "select", (submodule = BPyInit_gpu_select()));
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
+ Py_INCREF(submodule);
+
PyDict_SetItem(PyImport_GetModuleDict(), PyModule_GetNameObject(module), module);
return module;
}
diff --git a/source/blender/python/intern/gpu.h b/source/blender/python/intern/gpu.h
index 0da44a4eb87..92841db9027 100644
--- a/source/blender/python/intern/gpu.h
+++ b/source/blender/python/intern/gpu.h
@@ -37,5 +37,7 @@
PyObject *GPU_initPython(void);
PyObject *BPyInit_gpu_offscreen(void);
+PyObject *BPyInit_gpu_matrix(void);
+PyObject *BPyInit_gpu_select(void);
#endif /* __GPU_H__ */
diff --git a/source/blender/python/intern/gpu_offscreen.c b/source/blender/python/intern/gpu_offscreen.c
index 3c340d14e3f..226bfcc7c21 100644
--- a/source/blender/python/intern/gpu_offscreen.c
+++ b/source/blender/python/intern/gpu_offscreen.c
@@ -162,12 +162,15 @@ PyDoc_STRVAR(pygpu_offscreen_draw_view3d_doc,
);
static PyObject *pygpu_offscreen_draw_view3d(BPy_GPUOffScreen *self, PyObject *args, PyObject *kwds)
{
- static const char *kwlist[] = {"scene", "view3d", "region", "projection_matrix", "modelview_matrix", NULL};
+ /* TODO: This doesn't work currently because of eval_ctx. */
+#if 0
+ static const char *kwlist[] = {"scene", "view_layer", "view3d", "region", "projection_matrix", "modelview_matrix", NULL};
MatrixObject *py_mat_modelview, *py_mat_projection;
- PyObject *py_scene, *py_region, *py_view3d;
+ PyObject *py_scene, *py_view_layer, *py_region, *py_view3d;
Scene *scene;
+ ViewLayer *view_layer;
View3D *v3d;
ARegion *ar;
GPUFX *fx;
@@ -177,13 +180,14 @@ static PyObject *pygpu_offscreen_draw_view3d(BPy_GPUOffScreen *self, PyObject *a
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
if (!PyArg_ParseTupleAndKeywords(
- args, kwds, "OOOO&O&:draw_view3d", (char **)(kwlist),
- &py_scene, &py_view3d, &py_region,
+ args, kwds, "OOOOO&O&:draw_view3d", (char **)(kwlist),
+ &py_scene, &py_view_layer, &py_view3d, &py_region,
Matrix_Parse4x4, &py_mat_projection,
Matrix_Parse4x4, &py_mat_modelview) ||
- (!(scene = PyC_RNA_AsPointer(py_scene, "Scene")) ||
- !(v3d = PyC_RNA_AsPointer(py_view3d, "SpaceView3D")) ||
- !(ar = PyC_RNA_AsPointer(py_region, "Region"))))
+ (!(scene = PyC_RNA_AsPointer(py_scene, "Scene")) ||
+ !(view_layer = PyC_RNA_AsPointer(py_view_layer, "ViewLayer")) ||
+ !(v3d = PyC_RNA_AsPointer(py_view3d, "SpaceView3D")) ||
+ !(ar = PyC_RNA_AsPointer(py_region, "Region"))))
{
return NULL;
}
@@ -192,14 +196,14 @@ static PyObject *pygpu_offscreen_draw_view3d(BPy_GPUOffScreen *self, PyObject *a
fx_settings = v3d->fx_settings; /* full copy */
- ED_view3d_draw_offscreen_init(scene, v3d);
+ ED_view3d_draw_offscreen_init(scene, view_layer, v3d);
rv3d_mats = ED_view3d_mats_rv3d_backup(ar->regiondata);
GPU_offscreen_bind(self->ofs, true); /* bind */
ED_view3d_draw_offscreen(
- scene, v3d, ar, GPU_offscreen_width(self->ofs), GPU_offscreen_height(self->ofs),
+ scene, view_layer, v3d, ar, GPU_offscreen_width(self->ofs), GPU_offscreen_height(self->ofs),
(float(*)[4])py_mat_modelview->matrix, (float(*)[4])py_mat_projection->matrix,
false, true, true, "",
fx, &fx_settings,
@@ -212,6 +216,10 @@ static PyObject *pygpu_offscreen_draw_view3d(BPy_GPUOffScreen *self, PyObject *a
MEM_freeN(rv3d_mats);
Py_RETURN_NONE;
+#else
+ UNUSED_VARS(self, args, kwds);
+#endif
+ return NULL;
}
PyDoc_STRVAR(pygpu_offscreen_free_doc,
diff --git a/source/blender/python/intern/gpu_py_matrix.c b/source/blender/python/intern/gpu_py_matrix.c
new file mode 100644
index 00000000000..68b08dfb324
--- /dev/null
+++ b/source/blender/python/intern/gpu_py_matrix.c
@@ -0,0 +1,552 @@
+/*
+ * ***** 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/python/intern/gpu_py_matrix.c
+ * \ingroup pythonintern
+ *
+ * This file defines the gpu.matrix stack API.
+ *
+ * \warning While these functions attempt to ensure correct stack usage.
+ * Mixing Python and C functions may still crash on invalid use.
+ */
+
+#include <Python.h>
+
+
+#include "BLI_utildefines.h"
+
+#include "../mathutils/mathutils.h"
+
+#include "../generic/py_capi_utils.h"
+
+#include "gpu.h"
+
+#define USE_GPU_PY_MATRIX_API
+#include "GPU_matrix.h"
+#undef USE_GPU_PY_MATRIX_API
+
+/* -------------------------------------------------------------------- */
+/** \name Helper Functions
+ * \{ */
+
+static bool pygpu_stack_is_push_model_view_ok_or_error(void)
+{
+ if (GPU_matrix_stack_level_get_model_view() >= GPU_PY_MATRIX_STACK_LEN) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Maximum model-view stack depth " STRINGIFY(GPU_PY_MATRIX_STACK_DEPTH) " reached");
+ return false;
+ }
+ return true;
+}
+
+static bool pygpu_stack_is_push_projection_ok_or_error(void)
+{
+ if (GPU_matrix_stack_level_get_projection() >= GPU_PY_MATRIX_STACK_LEN) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Maximum projection stack depth " STRINGIFY(GPU_PY_MATRIX_STACK_DEPTH) " reached");
+ return false;
+ }
+ return true;
+}
+
+static bool pygpu_stack_is_pop_model_view_ok_or_error(void)
+{
+ if (GPU_matrix_stack_level_get_model_view() == 0) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Minimum model-view stack depth reached");
+ return false;
+ }
+ return true;
+}
+
+static bool pygpu_stack_is_pop_projection_ok_or_error(void)
+{
+ if (GPU_matrix_stack_level_get_projection() == 0) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Minimum projection stack depth reached");
+ return false;
+ }
+ return true;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Manage Stack
+ * \{ */
+
+PyDoc_STRVAR(pygpu_matrix_push_doc,
+"push()\n"
+"\n"
+" Add to the model-view matrix stack.\n"
+);
+static PyObject *pygpu_matrix_push(PyObject *UNUSED(self))
+{
+ if (!pygpu_stack_is_push_model_view_ok_or_error()) {
+ return NULL;
+ }
+ gpuPushMatrix();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pygpu_matrix_pop_doc,
+"pop()\n"
+"\n"
+" Remove the last model-view matrix from the stack.\n"
+);
+static PyObject *pygpu_matrix_pop(PyObject *UNUSED(self))
+{
+ if (!pygpu_stack_is_pop_model_view_ok_or_error()) {
+ return NULL;
+ }
+ gpuPopMatrix();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pygpu_matrix_push_projection_doc,
+"push_projection()\n"
+"\n"
+" Add to the projection matrix stack.\n"
+);
+static PyObject *pygpu_matrix_push_projection(PyObject *UNUSED(self))
+{
+ if (!pygpu_stack_is_push_projection_ok_or_error()) {
+ return NULL;
+ }
+ gpuPushProjectionMatrix();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pygpu_matrix_pop_projection_doc,
+"pop_projection()\n"
+"\n"
+" Remove the last projection matrix from the stack.\n"
+);
+static PyObject *pygpu_matrix_pop_projection(PyObject *UNUSED(self))
+{
+ if (!pygpu_stack_is_pop_projection_ok_or_error()) {
+ return NULL;
+ }
+ gpuPopProjectionMatrix();
+ Py_RETURN_NONE;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stack (Context Manager)
+ *
+ * Safer alternative to ensure balanced push/pop calls.
+ *
+ * \{ */
+
+typedef struct {
+ PyObject_HEAD /* required python macro */
+ int type;
+ int level;
+} BPy_GPU_MatrixStackContext;
+
+enum {
+ PYGPU_MATRIX_TYPE_MODEL_VIEW = 1,
+ PYGPU_MATRIX_TYPE_PROJECTION = 2,
+};
+
+static PyObject *pygpu_matrix_stack_context_enter(BPy_GPU_MatrixStackContext *self);
+static PyObject *pygpu_matrix_stack_context_exit(BPy_GPU_MatrixStackContext *self, PyObject *args);
+
+static PyMethodDef pygpu_matrix_stack_context_methods[] = {
+ {"__enter__", (PyCFunction)pygpu_matrix_stack_context_enter, METH_NOARGS},
+ {"__exit__", (PyCFunction)pygpu_matrix_stack_context_exit, METH_VARARGS},
+ {NULL}
+};
+
+static PyTypeObject pygpu_matrix_stack_context_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "GPUMatrixStackContext",
+ .tp_basicsize = sizeof(BPy_GPU_MatrixStackContext),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_methods = pygpu_matrix_stack_context_methods,
+};
+
+static PyObject *pygpu_matrix_stack_context_enter(BPy_GPU_MatrixStackContext *self)
+{
+ /* sanity - should never happen */
+ if (self->level != -1) {
+ PyErr_SetString(PyExc_RuntimeError, "Already in use");
+ return NULL;
+ }
+
+ if (self->type == PYGPU_MATRIX_TYPE_MODEL_VIEW) {
+ if (!pygpu_stack_is_push_model_view_ok_or_error()) {
+ return NULL;
+ }
+ gpuPushMatrix();
+ self->level = GPU_matrix_stack_level_get_model_view();
+ }
+ else if (self->type == PYGPU_MATRIX_TYPE_PROJECTION) {
+ if (!pygpu_stack_is_push_projection_ok_or_error()) {
+ return NULL;
+ }
+ gpuPushProjectionMatrix();
+ self->level = GPU_matrix_stack_level_get_projection();
+ }
+ else {
+ BLI_assert(0);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *pygpu_matrix_stack_context_exit(BPy_GPU_MatrixStackContext *self, PyObject *UNUSED(args))
+{
+ /* sanity - should never happen */
+ if (self->level == -1) {
+ fprintf(stderr, "Not yet in use\n");
+ goto finally;
+ }
+
+ if (self->type == PYGPU_MATRIX_TYPE_MODEL_VIEW) {
+ const int level = GPU_matrix_stack_level_get_model_view();
+ if (level != self->level) {
+ fprintf(stderr, "Level push/pop mismatch, expected %d, got %d\n", self->level, level);
+ }
+ if (level != 0) {
+ gpuPopMatrix();
+ }
+ }
+ else if (self->type == PYGPU_MATRIX_TYPE_PROJECTION) {
+ const int level = GPU_matrix_stack_level_get_projection();
+ if (level != self->level) {
+ fprintf(stderr, "Level push/pop mismatch, expected %d, got %d", self->level, level);
+ }
+ if (level != 0) {
+ gpuPopProjectionMatrix();
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+finally:
+ Py_RETURN_NONE;
+}
+
+static PyObject *pygpu_matrix_push_pop_impl(int type)
+{
+ BPy_GPU_MatrixStackContext *ret = PyObject_New(BPy_GPU_MatrixStackContext, &pygpu_matrix_stack_context_Type);
+ ret->type = type;
+ ret->level = -1;
+ return (PyObject *)ret;
+}
+
+PyDoc_STRVAR(pygpu_matrix_push_pop_doc,
+"push_pop()\n"
+"\n"
+" Context manager to ensure balanced push/pop calls, even in the case of an error.\n"
+);
+static PyObject *pygpu_matrix_push_pop(PyObject *UNUSED(self))
+{
+ return pygpu_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_MODEL_VIEW);
+}
+
+PyDoc_STRVAR(pygpu_matrix_push_pop_projection_doc,
+"push_pop_projection()\n"
+"\n"
+" Context manager to ensure balanced push/pop calls, even in the case of an error.\n"
+);
+static PyObject *pygpu_matrix_push_pop_projection(PyObject *UNUSED(self))
+{
+ return pygpu_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_PROJECTION);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Manipulate State
+ * \{ */
+
+PyDoc_STRVAR(pygpu_matrix_multiply_matrix_doc,
+"multiply_matrix(matrix)\n"
+"\n"
+" Multiply the current stack matrix.\n"
+"\n"
+" :param matrix: A 4x4 matrix.\n"
+" :type matrix: :class:`mathutils.Matrix`\n"
+);
+static PyObject *pygpu_matrix_multiply_matrix(PyObject *UNUSED(self), PyObject *value)
+{
+ MatrixObject *pymat;
+ if (!Matrix_Parse4x4(value, &pymat)) {
+ return NULL;
+ }
+ gpuMultMatrix(pymat->matrix);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pygpu_matrix_scale_doc,
+"scale(scale)\n"
+"\n"
+" Scale the current stack matrix.\n"
+"\n"
+" :param scale: Scale the current stack matrix.\n"
+" :type scale: sequence of 2 or 3 floats\n"
+);
+static PyObject *pygpu_matrix_scale(PyObject *UNUSED(self), PyObject *value)
+{
+ float scale[3];
+ int len;
+ if ((len = mathutils_array_parse(scale, 2, 3, value, "gpu.matrix.scale(): invalid vector arg")) == -1) {
+ return NULL;
+ }
+ if (len == 2) {
+ gpuScale2fv(scale);
+ }
+ else {
+ gpuScale3fv(scale);
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pygpu_matrix_scale_uniform_doc,
+"scale_uniform(scale)\n"
+"\n"
+" :param scale: Scale the current stack matrix.\n"
+" :type scale: sequence of 2 or 3 floats\n"
+);
+static PyObject *pygpu_matrix_scale_uniform(PyObject *UNUSED(self), PyObject *value)
+{
+ float scalar;
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
+ PyErr_Format(PyExc_TypeError,
+ "expected a number, not %.200s",
+ Py_TYPE(value)->tp_name);
+ return NULL;
+ }
+ gpuScaleUniform(scalar);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pygpu_matrix_translate_doc,
+"translate(offset)\n"
+"\n"
+" Scale the current stack matrix.\n"
+"\n"
+" :param offset: Translate the current stack matrix.\n"
+" :type offset: sequence of 2 or 3 floats\n"
+);
+static PyObject *pygpu_matrix_translate(PyObject *UNUSED(self), PyObject *value)
+{
+ float offset[3];
+ int len;
+ if ((len = mathutils_array_parse(offset, 2, 3, value, "gpu.matrix.translate(): invalid vector arg")) == -1) {
+ return NULL;
+ }
+ if (len == 2) {
+ gpuTranslate2fv(offset);
+ }
+ else {
+ gpuTranslate3fv(offset);
+ }
+ Py_RETURN_NONE;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Write State
+ * \{ */
+
+PyDoc_STRVAR(pygpu_matrix_reset_doc,
+"reset()\n"
+"\n"
+" Empty stack and set to identity.\n"
+);
+static PyObject *pygpu_matrix_reset(PyObject *UNUSED(self))
+{
+ gpuMatrixReset();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pygpu_matrix_load_identity_doc,
+"load_identity()\n"
+"\n"
+" Empty stack and set to identity.\n"
+);
+static PyObject *pygpu_matrix_load_identity(PyObject *UNUSED(self))
+{
+ gpuLoadIdentity();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pygpu_matrix_load_matrix_doc,
+"load_matrix(matrix)\n"
+"\n"
+" Load a matrix into the stack.\n"
+"\n"
+" :param matrix: A 4x4 matrix.\n"
+" :type matrix: :class:`mathutils.Matrix`\n"
+);
+static PyObject *pygpu_matrix_load_matrix(PyObject *UNUSED(self), PyObject *value)
+{
+ MatrixObject *pymat;
+ if (!Matrix_Parse4x4(value, &pymat)) {
+ return NULL;
+ }
+ gpuLoadMatrix(pymat->matrix);
+ Py_RETURN_NONE;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read State
+ * \{ */
+
+PyDoc_STRVAR(pygpu_matrix_get_projection_matrix_doc,
+"get_projection_matrix()\n"
+"\n"
+" Return a copy of the projection matrix.\n"
+"\n"
+" :return: A 4x4 projection matrix.\n"
+" :rtype: :class:`mathutils.Matrix`\n"
+);
+static PyObject *pygpu_matrix_get_projection_matrix(PyObject *UNUSED(self))
+{
+ float matrix[4][4];
+ gpuGetModelViewMatrix(matrix);
+ return Matrix_CreatePyObject(&matrix[0][0], 4, 4, NULL);
+}
+
+
+PyDoc_STRVAR(pygpu_matrix_get_modal_view_matrix_doc,
+"get_view_matrix()\n"
+"\n"
+" Return a copy of the view matrix.\n"
+"\n"
+" :return: A 4x4 view matrix.\n"
+" :rtype: :class:`mathutils.Matrix`\n"
+);
+static PyObject *pygpu_matrix_get_modal_view_matrix(PyObject *UNUSED(self))
+{
+ float matrix[4][4];
+ gpuGetProjectionMatrix(matrix);
+ return Matrix_CreatePyObject(&matrix[0][0], 4, 4, NULL);
+}
+
+PyDoc_STRVAR(pygpu_matrix_get_normal_matrix_doc,
+"get_normal_matrix()\n"
+"\n"
+" Return a copy of the normal matrix.\n"
+"\n"
+" :return: A 3x3 normal matrix.\n"
+" :rtype: :class:`mathutils.Matrix`\n"
+);
+static PyObject *pygpu_matrix_get_normal_matrix(PyObject *UNUSED(self))
+{
+ float matrix[3][3];
+ gpuGetNormalMatrix(matrix);
+ return Matrix_CreatePyObject(&matrix[0][0], 3, 3, NULL);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Module
+ * \{ */
+
+static struct PyMethodDef BPy_GPU_matrix_methods[] = {
+ /* Manage Stack */
+ {"push", (PyCFunction)pygpu_matrix_push,
+ METH_NOARGS, pygpu_matrix_push_doc},
+ {"pop", (PyCFunction)pygpu_matrix_pop,
+ METH_NOARGS, pygpu_matrix_pop_doc},
+
+ {"push_projection", (PyCFunction)pygpu_matrix_push_projection,
+ METH_NOARGS, pygpu_matrix_push_projection_doc},
+ {"pop_projection", (PyCFunction)pygpu_matrix_pop_projection,
+ METH_NOARGS, pygpu_matrix_pop_projection_doc},
+
+ /* Stack (Context Manager) */
+ {"push_pop", (PyCFunction)pygpu_matrix_push_pop,
+ METH_NOARGS, pygpu_matrix_push_pop_doc},
+ {"push_pop_projection", (PyCFunction)pygpu_matrix_push_pop_projection,
+ METH_NOARGS, pygpu_matrix_push_pop_projection_doc},
+
+ /* Manipulate State */
+ {"multiply_matrix", (PyCFunction)pygpu_matrix_multiply_matrix,
+ METH_O, pygpu_matrix_multiply_matrix_doc},
+ {"scale", (PyCFunction)pygpu_matrix_scale,
+ METH_O, pygpu_matrix_scale_doc},
+ {"scale_uniform", (PyCFunction)pygpu_matrix_scale_uniform,
+ METH_O, pygpu_matrix_scale_uniform_doc},
+ {"translate", (PyCFunction)pygpu_matrix_translate,
+ METH_O, pygpu_matrix_translate_doc},
+
+ /* TODO */
+#if 0
+ {"rotate", (PyCFunction)pygpu_matrix_rotate,
+ METH_O, pygpu_matrix_rotate_doc},
+ {"rotate_axis", (PyCFunction)pygpu_matrix_rotate_axis,
+ METH_O, pygpu_matrix_rotate_axis_doc},
+ {"look_at", (PyCFunction)pygpu_matrix_look_at,
+ METH_O, pygpu_matrix_look_at_doc},
+#endif
+
+ /* Write State */
+ {"reset", (PyCFunction)pygpu_matrix_reset,
+ METH_NOARGS, pygpu_matrix_reset_doc},
+ {"load_identity", (PyCFunction)pygpu_matrix_load_identity,
+ METH_NOARGS, pygpu_matrix_load_identity_doc},
+ {"load_matrix", (PyCFunction)pygpu_matrix_load_matrix,
+ METH_O, pygpu_matrix_load_matrix_doc},
+
+ /* Read State */
+ {"get_projection_matrix", (PyCFunction)pygpu_matrix_get_projection_matrix,
+ METH_NOARGS, pygpu_matrix_get_projection_matrix_doc},
+ {"get_model_view_matrix", (PyCFunction)pygpu_matrix_get_modal_view_matrix,
+ METH_NOARGS, pygpu_matrix_get_modal_view_matrix_doc},
+ {"get_normal_matrix", (PyCFunction)pygpu_matrix_get_normal_matrix,
+ METH_NOARGS, pygpu_matrix_get_normal_matrix_doc},
+
+ {NULL, NULL, 0, NULL}
+};
+
+PyDoc_STRVAR(BPy_GPU_matrix_doc,
+"This module provides access to the matrix stack."
+);
+static PyModuleDef BPy_GPU_matrix_module_def = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "gpu.matrix",
+ .m_doc = BPy_GPU_matrix_doc,
+ .m_methods = BPy_GPU_matrix_methods,
+};
+
+PyObject *BPyInit_gpu_matrix(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&BPy_GPU_matrix_module_def);
+
+ if (PyType_Ready(&pygpu_matrix_stack_context_Type) < 0) {
+ return NULL;
+ }
+
+ return submodule;
+}
+
+/** \} */
diff --git a/source/blender/python/intern/gpu_py_select.c b/source/blender/python/intern/gpu_py_select.c
new file mode 100644
index 00000000000..f570c4cdae2
--- /dev/null
+++ b/source/blender/python/intern/gpu_py_select.c
@@ -0,0 +1,92 @@
+/*
+ * ***** 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/python/intern/gpu_py_select.c
+ * \ingroup pythonintern
+ *
+ * This file defines the gpu.select API.
+ *
+ * \note Currently only used for manipulator selection,
+ * will need to add begin/end and a way to access the hits.
+ */
+
+#include <Python.h>
+
+#include "BLI_utildefines.h"
+
+#include "../generic/py_capi_utils.h"
+
+#include "gpu.h"
+
+#include "GPU_select.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Methods
+ * \{ */
+
+PyDoc_STRVAR(pygpu_select_load_id_doc,
+"load_id(id)\n"
+"\n"
+" Set the selection ID.\n"
+"\n"
+" :param id: Number (32-bit unsigned int).\n"
+" :type select: int\n"
+);
+static PyObject *pygpu_select_load_id(PyObject *UNUSED(self), PyObject *value)
+{
+ uint id;
+ if ((id = PyC_Long_AsU32(value)) == (uint)-1) {
+ return NULL;
+ }
+ GPU_select_load_id(id);
+ Py_RETURN_NONE;
+}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Module
+ * \{ */
+
+static struct PyMethodDef BPy_GPU_select_methods[] = {
+ /* Manage Stack */
+ {"load_id", (PyCFunction)pygpu_select_load_id, METH_O, pygpu_select_load_id_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+PyDoc_STRVAR(BPy_GPU_select_doc,
+"This module provides access to selection."
+);
+static PyModuleDef BPy_GPU_select_module_def = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "gpu.select",
+ .m_doc = BPy_GPU_select_doc,
+ .m_methods = BPy_GPU_select_methods,
+};
+
+PyObject *BPyInit_gpu_select(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&BPy_GPU_select_module_def);
+
+ return submodule;
+}
+
+/** \} */
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
index 22e7bf3dd27..ba0b6eb11a5 100644
--- a/source/blender/python/mathutils/mathutils_bvhtree.c
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -1049,6 +1049,8 @@ static DerivedMesh *bvh_get_derived_mesh(
const char *funcname, struct Scene *scene, Object *ob,
bool use_deform, bool use_render, bool use_cage)
{
+ /* TODO: This doesn't work currently because of eval_ctx. */
+#if 0
/* we only need minimum mesh data for topology and vertex locations */
CustomDataMask mask = CD_MASK_BAREMESH;
@@ -1096,6 +1098,11 @@ static DerivedMesh *bvh_get_derived_mesh(
}
}
}
+#else
+ UNUSED_VARS(funcname, scene, ob, use_deform, use_render, use_cage);
+#endif
+
+ return NULL;
}
PyDoc_STRVAR(C_BVHTree_FromObject_doc,
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index 27ec6bf8ba6..5cbc907d9c6 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -36,6 +36,7 @@ set(INC
../makesrna
../nodes
../physics
+ ../draw
../../../intern/atomic
../../../intern/guardedalloc
../../../intern/mikktspace
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index 321eda0175f..60ffd8f42e4 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -39,6 +39,9 @@
struct bNode;
struct bNodeTree;
+struct Depsgraph;
+struct IDProperty;
+struct Main;
struct Object;
struct Render;
struct RenderData;
@@ -63,6 +66,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_LEGACY_PIPELINE 1024 /* XXX Temporary flag, to be removed once draw manager is finished. */
/* RenderEngine.flag */
#define RE_ENGINE_ANIMATION 1
@@ -88,15 +92,22 @@ typedef struct RenderEngineType {
char name[64];
int flag;
- void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Scene *scene);
- void (*render)(struct RenderEngine *engine, struct Scene *scene);
- void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, const int pass_filter, const int object_id, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result);
+ void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene);
+ void (*render_to_image)(struct RenderEngine *engine, struct Depsgraph *depsgraph);
+ void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type,
+ const int pass_filter, const int object_id, const struct BakePixel *pixel_array, const int num_pixels,
+ const int depth, void *result);
void (*view_update)(struct RenderEngine *engine, const struct bContext *context);
- void (*view_draw)(struct RenderEngine *engine, const struct bContext *context);
+ void (*render_to_view)(struct RenderEngine *engine, const struct bContext *context);
void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node);
- void (*update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl);
+ void (*update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer);
+
+ void (*collection_settings_create)(struct RenderEngine *engine, struct IDProperty *props);
+ void (*render_settings_create)(struct RenderEngine *engine, struct IDProperty *props);
+
+ struct DrawEngineType *draw_engine;
/* RNA integration */
ExtensionRNA ext;
@@ -163,19 +174,23 @@ bool RE_engine_is_external(struct Render *re);
void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe);
-void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl,
+void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
const char *name, int channels, const char *chanid, int type);
/* Engine Types */
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);
rcti* RE_engine_get_current_tiles(struct Render *re, int *r_total_tiles, bool *r_needs_free);
struct RenderData *RE_engine_get_render_data(struct Render *re);
-void RE_bake_engine_set_engine_parameters(struct Render *re, struct Main *bmain, struct Scene *scene);
+void RE_bake_engine_set_engine_parameters(
+ struct Render *re, struct Main *bmain, struct Depsgraph *graph, struct Scene *scene);
+
+struct ViewLayer *RE_engine_get_view_layer(struct Render *re);
#endif /* __RE_ENGINE_H__ */
diff --git a/source/blender/render/extern/include/RE_multires_bake.h b/source/blender/render/extern/include/RE_multires_bake.h
index c1c5fc4a04d..901c1c1d05d 100644
--- a/source/blender/render/extern/include/RE_multires_bake.h
+++ b/source/blender/render/extern/include/RE_multires_bake.h
@@ -43,6 +43,12 @@ typedef struct MultiresBakeRender {
short mode;
bool use_lores_mesh; /* Use low-resolution mesh when baking displacement maps */
+ /* material aligned image array (for per-face bake image) */
+ struct {
+ Image **array;
+ int len;
+ } ob_image;
+
int number_of_rays; /* Number of rays to be cast when doing AO baking */
float bias; /* Bias between object and start ray point when doing AO baking */
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 830f6a0bbf1..a0f3a053618 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -37,6 +37,8 @@
struct bMovieHandle;
struct bNodeTree;
+struct Depsgraph;
+struct EvaluationContext;
struct Image;
struct ImageFormatData;
struct Main;
@@ -46,9 +48,10 @@ struct RenderData;
struct RenderResult;
struct ReportList;
struct Scene;
-struct SceneRenderLayer;
+struct ViewLayer;
struct EnvMap;
struct StampData;
+struct ViewRender;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* this include is what is exposed of render to outside world */
@@ -105,12 +108,8 @@ typedef struct RenderLayer {
/* copy of RenderData */
char name[RE_MAXNAME];
- unsigned int lay, lay_zmask, lay_exclude;
int layflag, passflag, pass_xor;
- struct Material *mat_override;
- struct Group *light_override;
-
/* MULTIVIEW_TODO: acolrect and scolrect are not supported by multiview at the moment.
* If they are really required they should be in RenderView instead */
@@ -241,7 +240,8 @@ struct RenderPass *RE_create_gp_pass(struct RenderResult *rr, const char *layern
/* obligatory initialize call, disprect is optional */
void RE_InitState(struct Render *re, struct Render *source, struct RenderData *rd,
- struct SceneRenderLayer *srl,
+ struct ListBase *render_layers, const int active_layer,
+ struct ViewRender *view_render, struct ViewLayer *view_layer,
int winx, int winy, rcti *disprect);
void RE_ChangeResolution(struct Render *re, int winx, int winy, rcti *disprect);
void RE_ChangeModeFlag(struct Render *re, int flag, bool clear);
@@ -250,6 +250,7 @@ void RE_ChangeModeFlag(struct Render *re, int flag, bool clear);
struct Object *RE_GetCamera(struct Render *re); /* return camera override if set */
void RE_SetOverrideCamera(struct Render *re, struct Object *camera);
void RE_SetCamera(struct Render *re, struct Object *camera);
+void RE_SetDepsgraph(struct Render *re, struct Depsgraph *graph);
void RE_SetEnvmapCamera(struct Render *re, struct Object *cam_ob, float viewscale, float clipsta, float clipend);
void RE_SetWindow(struct Render *re, const rctf *viewplane, float clipsta, float clipend);
void RE_SetOrtho(struct Render *re, const rctf *viewplane, float clipsta, float clipend);
@@ -289,7 +290,7 @@ bool RE_WriteRenderViewsMovie(
/* only RE_NewRender() needed, main Blender render calls */
void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene,
- struct SceneRenderLayer *srl, struct Object *camera_override,
+ struct ViewLayer *view_layer, struct Object *camera_override,
unsigned int lay_override, int frame, const bool write_still);
void RE_BlenderAnim(struct Render *re, struct Main *bmain, struct Scene *scene, struct Object *camera_override,
unsigned int lay_override, int sfra, int efra, int tfra);
@@ -301,11 +302,13 @@ void RE_RenderFreestyleExternal(struct Render *re);
void RE_SetActiveRenderView(struct Render *re, const char *viewname);
const char *RE_GetActiveRenderView(struct Render *re);
+void RE_SetEngineByID(struct Render *re, const char *engine_id);
+
/* error reporting */
void RE_SetReports(struct Render *re, struct ReportList *reports);
/* main preview render call */
-void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene);
+void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene, struct ViewRender *render_view);
bool RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode);
bool RE_WriteRenderResult(
@@ -372,6 +375,7 @@ void RE_DataBase_GetView(struct Render *re, float mat[4][4]);
void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4]);
void RE_GetCameraModelMatrix(struct Render *re, struct Object *camera, float r_mat[4][4]);
struct Scene *RE_GetScene(struct Render *re);
+struct EvaluationContext *RE_GetEvalCtx(struct Render *re);
bool RE_force_single_renderlayer(struct Scene *scene);
bool RE_is_rendering_allowed(struct Scene *scene, struct Object *camera_override, struct ReportList *reports);
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index 1779ccc5d19..17b321fd3b4 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -41,6 +41,8 @@ struct DerivedMesh;
struct ImagePool;
struct MTex;
struct Scene;
+struct ViewLayer;
+struct Render;
/* render_texture.c */
/* used by particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */
@@ -70,17 +72,20 @@ struct PointDensity;
void RE_point_density_cache(
struct Scene *scene,
+ struct ViewLayer *view_layer,
struct PointDensity *pd,
const bool use_render_params);
void RE_point_density_minmax(
struct Scene *scene,
+ struct ViewLayer *view_layer,
struct PointDensity *pd,
const bool use_render_params,
float r_min[3], float r_max[3]);
void RE_point_density_sample(
struct Scene *scene,
+ struct ViewLayer *view_layer,
struct PointDensity *pd,
const int resolution,
const bool use_render_params,
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index b64c0c8fc52..0b392c122db 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -179,8 +179,6 @@ typedef struct ShadeInput {
unsigned int lay;
int layflag, passflag, combinedflag;
short object_pass_index;
- struct Group *light_override;
- struct Material *mat_override;
#ifdef RE_RAYCOUNTER
RayCounter raycounter;
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 45206f21ae4..d24aae6ac97 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -186,11 +186,16 @@ struct Render {
/* shadow counter, detect shadow-reuse for shaders */
int shadowsamplenr[BLENDER_MAX_THREADS];
+ struct Depsgraph *depsgraph;
+
/* main, scene, and its full copy of renderdata and world */
struct Main *main;
Scene *scene;
RenderData r;
+ ListBase view_layers;
+ int active_view_layer;
World wrld;
+ ViewRender view_render;
struct Object *camera_override;
unsigned int lay, layer_override;
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index f4c4a50ac27..c01db7db53e 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -83,7 +83,7 @@ void zbufshade_sss_tile(struct RenderPart *pa);
int get_sample_layers(struct RenderPart *pa, struct RenderLayer *rl, struct RenderLayer **rlpp);
-void render_internal_update_passes(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl);
+void render_internal_update_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer);
/* -------- ray.c ------- */
diff --git a/source/blender/render/intern/include/renderpipeline.h b/source/blender/render/intern/include/renderpipeline.h
index c5d6e3b44b1..8c23eb0d4cb 100644
--- a/source/blender/render/intern/include/renderpipeline.h
+++ b/source/blender/render/intern/include/renderpipeline.h
@@ -33,15 +33,18 @@
#ifndef __RENDERPIPELINE_H__
#define __RENDERPIPELINE_H__
+struct ListBase;
struct Render;
struct RenderData;
struct RenderLayer;
struct RenderResult;
+struct ViewRender;
struct RenderLayer *render_get_active_layer(struct Render *re, struct RenderResult *rr);
float panorama_pixel_rot(struct Render *re);
-void render_update_anim_renderdata(struct Render *re, struct RenderData *rd);
+void render_update_anim_renderdata(struct Render *re, struct RenderData *rd, struct ListBase *render_layers);
void render_copy_renderdata(struct RenderData *to, struct RenderData *from);
+void render_copy_viewrender(struct ViewRender *to, struct ViewRender *from);
#endif /* __RENDERPIPELINE_H__ */
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
index 31e461b4536..71a595d6a8b 100644
--- a/source/blender/render/intern/source/bake.c
+++ b/source/blender/render/intern/source/bake.c
@@ -669,11 +669,12 @@ static int get_next_bake_face(BakeShade *bs)
const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f};
tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
+ /* should use 'BKE_object_material_edit_image_get' but in this case simpler not to */
+ ima = vlr->mat ? vlr->mat->edit_image : NULL;
- if (!tface || !tface->tpage)
+ if (!tface || !ima)
continue;
- ima = tface->tpage;
ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
if (ibuf == NULL)
@@ -814,7 +815,7 @@ static void shade_tface(BakeShade *bs)
ObjectInstanceRen *obi = bs->obi;
ObjectRen *obr = obi->obr;
MTFace *tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
- Image *ima = tface->tpage;
+ Image *ima = vlr->mat->edit_image;
float vec[4][2];
int a, i1, i2, i3;
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index fd46acc3638..74de3fcded6 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -66,12 +66,13 @@
#include "BKE_customdata.h"
#include "BKE_colortools.h"
#include "BKE_displist.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
+#include "BKE_group.h"
#include "BKE_key.h"
#include "BKE_image.h"
#include "BKE_lattice.h"
+#include "BKE_layer.h"
#include "BKE_material.h"
#include "BKE_main.h"
#include "BKE_mball.h"
@@ -82,6 +83,8 @@
#include "BKE_particle.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
#include "PIL_time.h"
#include "envmap.h"
@@ -1349,10 +1352,11 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if (!(psmd->modifier.mode & eModifierMode_Render))
return 0;
- sim.scene= re->scene;
- sim.ob= ob;
- sim.psys= psys;
- sim.psmd= psmd;
+ sim.eval_ctx = re->eval_ctx;
+ sim.scene = re->scene;
+ sim.ob = ob;
+ sim.psys = psys;
+ sim.psmd = psmd;
if (part->phystype==PART_PHYS_KEYED)
psys_count_keyed_targets(&sim);
@@ -2599,13 +2603,13 @@ static void init_render_surf(Render *re, ObjectRen *obr, int timeoffset)
if (ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1;
- BKE_displist_make_surf(re->scene, ob, &displist, &dm, 1, 0, 1);
+ BKE_displist_make_surf(re->eval_ctx, re->scene, ob, &displist, &dm, 1, 0, 1);
if (dm) {
if (need_orco) {
orco = get_object_orco(re, ob);
if (!orco) {
- orco= BKE_displist_make_orco(re->scene, ob, dm, true, true);
+ orco= BKE_displist_make_orco(re->eval_ctx, re->scene, ob, dm, true, true);
if (orco) {
set_object_orco(re, ob, orco);
}
@@ -2657,7 +2661,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
if (ob->type==OB_FONT && cu->str==NULL) return;
else if (ob->type==OB_CURVE && cu->nurb.first==NULL) return;
- BKE_displist_make_curveTypes_forRender(re->scene, ob, &disp, &dm, false, true);
+ BKE_displist_make_curveTypes_forRender(re->eval_ctx, re->scene, ob, &disp, &dm, false, true);
dl= disp.first;
if (dl==NULL) return;
@@ -2684,7 +2688,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
if (need_orco) {
orco = get_object_orco(re, ob);
if (!orco) {
- orco = BKE_displist_make_orco(re->scene, ob, dm, true, true);
+ orco = BKE_displist_make_orco(re->eval_ctx, re->scene, ob, dm, true, true);
if (orco) {
set_object_orco(re, ob, orco);
}
@@ -2698,7 +2702,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
if (need_orco) {
orco = get_object_orco(re, ob);
if (!orco) {
- orco = BKE_curve_make_orco(re->scene, ob, NULL);
+ orco = BKE_curve_make_orco(re->eval_ctx, re->scene, ob, NULL);
set_object_orco(re, ob, orco);
}
}
@@ -3153,11 +3157,11 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
/* normalmaps, test if tangents needed, separated from shading */
if (ma->mode_l & MA_TANGENT_V) {
need_tangent= 1;
- if (me->mtpoly==NULL)
+ if (me->mloopuv==NULL)
need_orco= 1;
}
if (ma->mode_l & MA_NORMAP_TANG) {
- if (me->mtpoly==NULL) {
+ if (me->mloopuv==NULL) {
need_orco= 1;
}
need_tangent= 1;
@@ -3170,7 +3174,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
if (re->flag & R_NEED_TANGENT) {
/* exception for tangent space baking */
- if (me->mtpoly==NULL) {
+ if (me->mloopuv==NULL) {
need_orco= 1;
}
need_tangent= 1;
@@ -3198,9 +3202,9 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
#endif
if (re->r.scemode & R_VIEWPORT_PREVIEW)
- dm= mesh_create_derived_view(re->scene, ob, mask);
+ dm= mesh_create_derived_view(re->eval_ctx, re->scene, ob, mask);
else
- dm= mesh_create_derived_render(re->scene, ob, mask);
+ dm= mesh_create_derived_render(re->eval_ctx, re->scene, ob, mask);
if (dm==NULL) return; /* in case duplicated object fails? */
mvert= dm->getVertArray(dm);
@@ -3976,28 +3980,32 @@ static bool is_object_hidden(Render *re, Object *ob)
/* layflag: allows material group to ignore layerflag */
static void add_lightgroup(Render *re, Group *group, int exclusive)
{
- GroupObject *go, *gol;
-
group->id.tag &= ~LIB_TAG_DOIT;
+#if 0
/* it's a bit too many loops in loops... but will survive */
/* note that 'exclusive' will remove it from the global list */
- for (go= group->gobject.first; go; go= go->next) {
- go->lampren= NULL;
+ FOREACH_GROUP_BASE(group, base)
+ {
+ Object *object = base->object;
- if (is_object_hidden(re, go->ob))
+ if (is_object_hidden(re, object)) {
continue;
-
- if (go->ob->lay & re->lay) {
- if (go->ob && go->ob->type==OB_LAMP) {
- for (gol= re->lights.first; gol; gol= gol->next) {
- if (gol->ob==go->ob) {
- go->lampren= gol->lampren;
+ }
+
+ if (base->flag & BASE_VISIBLED) {
+ if (object && object->type == OB_LAMP) {
+ for (GroupObject *gol = re->lights.first; gol; gol = gol->next) {
+ if (gol->ob == object) {
+ go->lampren = gol->lampren;
break;
}
}
- if (go->lampren==NULL)
- gol= add_render_lamp(re, go->ob);
+
+ if (go->lampren == NULL) {
+ gol= add_render_lamp(re, object);
+ }
+
if (gol && exclusive) {
BLI_remlink(&re->lights, gol);
MEM_freeN(gol);
@@ -4005,6 +4013,10 @@ static void add_lightgroup(Render *re, Group *group, int exclusive)
}
}
}
+ FOREACH_GROUP_BASE_END
+#else
+ UNUSED_VARS(re, exclusive);
+#endif
}
static void set_material_lightgroups(Render *re)
@@ -4027,16 +4039,6 @@ static void set_material_lightgroups(Render *re)
}
}
-static void set_renderlayer_lightgroups(Render *re, Scene *sce)
-{
- SceneRenderLayer *srl;
-
- for (srl= sce->r.layers.first; srl; srl= srl->next) {
- if (srl->light_override)
- add_lightgroup(re, srl->light_override, 0);
- }
-}
-
/* ------------------------------------------------------------------------- */
/* World */
/* ------------------------------------------------------------------------- */
@@ -4618,9 +4620,9 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset)
const CustomDataMask mask = CD_MASK_RENDER_INTERNAL;
if (re->r.scemode & R_VIEWPORT_PREVIEW)
- dm = mesh_create_derived_view(re->scene, ob, mask);
+ dm = mesh_create_derived_view(re->eval_ctx, re->scene, ob, mask);
else
- dm = mesh_create_derived_render(re->scene, ob, mask);
+ dm = mesh_create_derived_render(re->eval_ctx, re->scene, ob, mask);
dm->release(dm);
}
@@ -4846,6 +4848,8 @@ void RE_Database_Free(Render *re)
BLI_memarena_free(re->memArena);
re->memArena = NULL;
}
+
+ BKE_viewrender_free(&re->view_render);
}
static int allow_render_object(Render *re, Object *ob, int nolamps, int onlyselected, Object *actob)
@@ -4904,8 +4908,6 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in
{
/* ugly function, but we need to set particle systems to their render
* settings before calling object_duplilist, to get render level duplis */
- Group *group;
- GroupObject *go;
ParticleSystem *psys;
DerivedMesh *dm;
@@ -4929,7 +4931,7 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in
/* this is to make sure we get render level duplis in groups:
* the derivedmesh must be created before init_render_mesh,
* since object_duplilist does dupliparticles before that */
- dm = mesh_create_derived_render(re->scene, ob, CD_MASK_RENDER_INTERNAL);
+ dm = mesh_create_derived_render(re->eval_ctx, re->scene, ob, CD_MASK_RENDER_INTERNAL);
dm->release(dm);
for (psys=ob->particlesystem.first; psys; psys=psys->next)
@@ -4937,60 +4939,52 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in
}
}
- if (ob->dup_group==NULL) return;
- group= ob->dup_group;
+ if (ob->dup_group == NULL) return;
- for (go= group->gobject.first; go; go= go->next)
- dupli_render_particle_set(re, go->ob, timeoffset, level+1, enable);
+ FOREACH_GROUP_OBJECT(ob->dup_group, object)
+ {
+ dupli_render_particle_set(re, object, timeoffset, level+1, enable);
+ }
+ FOREACH_GROUP_OBJECT_END
}
-static int get_vector_renderlayers(Scene *sce)
+static int get_vector_viewlayers(Scene *UNUSED(sce))
{
- SceneRenderLayer *srl;
- unsigned int lay= 0;
-
- for (srl= sce->r.layers.first; srl; srl= srl->next)
- if (srl->passflag & SCE_PASS_VECTOR)
- lay |= srl->lay;
-
- return lay;
+ return 0;
}
static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, int onlyselected, Object *actob, int timeoffset, int level)
{
- GroupObject *go;
- Object *ob;
-
- /* simple preventing of too deep nested groups */
- if (level>MAX_DUPLI_RECUR) return;
-
- /* recursively go into dupligroups to find objects with OB_RENDER_DUPLI
- * that were not created yet */
- for (go= group->gobject.first; go; go= go->next) {
- ob= go->ob;
+ /* Simple preventing of too deep nested groups. */
+ if (level > MAX_DUPLI_RECUR) return;
+ /* Recursively go into dupligroups to find objects with OB_RENDER_DUPLI
+ * that were not created yet. */
+ FOREACH_GROUP_OBJECT(group, ob)
+ {
if (ob->flag & OB_DONE) {
if (ob->transflag & OB_RENDER_DUPLI) {
if (allow_render_object(re, ob, nolamps, onlyselected, actob)) {
init_render_object(re, ob, NULL, NULL, NULL, timeoffset);
ob->transflag &= ~OB_RENDER_DUPLI;
- if (ob->dup_group)
+ if (ob->dup_group) {
add_group_render_dupli_obs(re, ob->dup_group, nolamps, onlyselected, actob, timeoffset, level+1);
+ }
}
}
}
}
+ FOREACH_GROUP_OBJECT_END
}
-static void database_init_objects(Render *re, unsigned int renderlay, int nolamps, int onlyselected, Object *actob, int timeoffset)
+static void database_init_objects(Render *re, unsigned int UNUSED(renderlay), int nolamps, int onlyselected, Object *actob, int timeoffset)
{
Base *base;
Object *ob;
Group *group;
ObjectInstanceRen *obi;
Scene *sce_iter;
- int lay, vectorlay;
/* for duplis we need the Object texture mapping to work as if
* untransformed, set_dupli_tex_mat sets the matrix to allow that
@@ -5018,14 +5012,18 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
for (SETLOOPER(re->scene, sce_iter, base)) {
ob= base->object;
+#if 0
+ TODO_LAYER; /* investigate if this is an issue*/
/* in the prev/next pass for making speed vectors, avoid creating
* objects that are not on a renderlayer with a vector pass, can
* save a lot of time in complex scenes */
- vectorlay= get_vector_renderlayers(re->scene);
- lay= (timeoffset)? renderlay & vectorlay: renderlay;
+ vectorlay= get_vector_viewlayers(re->scene);
+#endif
- /* if the object has been restricted from rendering in the outliner, ignore it */
- if (is_object_restricted(re, ob)) continue;
+ /* if the object is not visible, ignore it */
+ if ((base->flag & BASE_VISIBLED) == 0) {
+ continue;
+ }
/* OB_DONE means the object itself got duplicated, so was already converted */
if (ob->flag & OB_DONE) {
@@ -5038,7 +5036,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
}
}
}
- else if ((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->lay)) ) {
+ else if (((base->flag & BASE_VISIBLED) != 0) || (ob->type==OB_LAMP)) {
if ((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) {
DupliObject *dob;
ListBase *duplilist;
@@ -5049,7 +5047,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
* system need to have render settings set for dupli particles */
dupli_render_particle_set(re, ob, timeoffset, 0, 1);
duplilist = object_duplilist(re->eval_ctx, re->scene, ob);
- duplilist_apply_data = duplilist_apply(ob, NULL, duplilist);
+ duplilist_apply_data = duplilist_apply(re->eval_ctx, ob, NULL, duplilist);
/* postpone 'dupli_render_particle_set', since RE_addRenderInstance reads
* index values from 'dob->persistent_id[0]', referencing 'psys->child' which
* may be smaller once the particle system is restored, see: T45563. */
@@ -5176,7 +5174,6 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
/* used to be 'rotate scene' */
void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int lay, int use_camera_view)
{
- Scene *sce;
Object *camera;
float mat[4][4];
float amb[3];
@@ -5195,6 +5192,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
re->i.infostr= "Preparing Scene data";
re->i.cfra= scene->r.cfra;
BLI_strncpy(re->i.scene_name, scene->id.name + 2, sizeof(re->i.scene_name));
+ re->view_render = scene->view_render;
/* XXX add test if dbase was filled already? */
@@ -5211,14 +5209,14 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
/* applies changes fully */
if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0) {
- BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, lay);
- render_update_anim_renderdata(re, &re->scene->r);
+ BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, re->scene, NULL);
+ render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers);
}
/* if no camera, viewmat should have been set! */
if (use_camera_view && camera) {
/* called before but need to call again in case of lens animation from the
- * above call to BKE_scene_update_for_newframe, fixes bug. [#22702].
+ * above call to BKE_scene_graph_update_for_newframe, fixes bug. [#22702].
* following calls don't depend on 'RE_SetCamera' */
RE_SetCamera(re, camera);
RE_GetCameraModelMatrix(re, camera, mat);
@@ -5226,7 +5224,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
RE_SetView(re, mat);
/* force correct matrix for scaled cameras */
- DAG_id_tag_update_ex(re->main, &camera->id, OB_RECALC_OB);
+ DEG_id_tag_update_ex(re->main, &camera->id, OB_RECALC_OB);
}
/* store for incremental render, viewmat rotates dbase */
@@ -5252,8 +5250,6 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
if (!re->test_break(re->tbh)) {
set_material_lightgroups(re);
- for (sce= re->scene; sce; sce= sce->set)
- set_renderlayer_lightgroups(re, sce);
/* for now some clumsy copying still */
re->i.totvert= re->totvert;
@@ -5381,13 +5377,9 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
re->i.totface=re->i.totvert=re->i.totstrand=re->i.totlamp=re->i.tothalo= 0;
re->lights.first= re->lights.last= NULL;
- /* in localview, lamps are using normal layers, objects only local bits */
- if (re->lay & 0xFF000000)
- lay &= 0xFF000000;
-
/* applies changes fully */
scene->r.cfra += timeoffset;
- BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, lay);
+ BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, re->scene, NULL);
/* if no camera, viewmat should have been set! */
if (camera) {
@@ -5804,7 +5796,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned
}
if (!re->test_break(re->tbh)) {
- int vectorlay= get_vector_renderlayers(re->scene);
+ int vectorlay= get_vector_viewlayers(re->scene);
for (step= 0; step<2; step++) {
@@ -5908,6 +5900,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
/* renderdata setup and exceptions */
render_copy_renderdata(&re->r, &scene->r);
+ render_copy_viewrender(&re->view_render, &scene->view_render);
RE_init_threadcount(re);
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index 156b4215992..2a7aab58980 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -51,6 +51,7 @@
#include "BKE_main.h"
#include "BKE_image.h" /* BKE_imbuf_write */
+#include "BKE_layer.h"
#include "BKE_texture.h"
#include "BKE_scene.h"
@@ -141,9 +142,8 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
envre->flag = re->flag;
/* set up renderdata */
- render_copy_renderdata(&envre->r, &re->r);
envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR);
- BLI_freelistN(&envre->r.layers);
+ BLI_freelistN(&envre->view_layers);
BLI_freelistN(&envre->r.views);
envre->r.filtertype = 0;
envre->r.tilex = envre->r.xsch / 2;
@@ -151,7 +151,7 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
envre->r.size = 100;
envre->r.yasp = envre->r.xasp = 1;
- RE_InitState(envre, NULL, &envre->r, NULL, cuberes, cuberes, NULL);
+ RE_InitState(envre, NULL, &envre->r, &re->view_layers, re->active_view_layer, &envre->view_render, NULL, cuberes, cuberes, NULL);
envre->main = re->main;
envre->scene = re->scene; /* unsure about this... */
envre->scene_color_manage = re->scene_color_manage;
@@ -248,17 +248,14 @@ static void envmap_transmatrix(float mat[4][4], int part)
static void env_set_imats(Render *re)
{
- Base *base;
float mat[4][4];
-
- base = re->scene->base.first;
- while (base) {
- mul_m4_m4m4(mat, re->viewmat, base->object->obmat);
- invert_m4_m4(base->object->imat, mat);
-
- base = base->next;
+
+ FOREACH_SCENE_OBJECT(re->scene, ob)
+ {
+ mul_m4_m4m4(mat, re->viewmat, ob->obmat);
+ invert_m4_m4(ob->imat, mat);
}
-
+ FOREACH_SCENE_OBJECT_END
}
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 8764abf9674..68077d4d93b 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -45,9 +45,12 @@
#include "BKE_camera.h"
#include "BKE_global.h"
#include "BKE_colortools.h"
+#include "BKE_layer.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#ifdef WITH_PYTHON
@@ -58,6 +61,8 @@
#include "RE_pipeline.h"
#include "RE_bake.h"
+#include "DRW_engine.h"
+
#include "initrender.h"
#include "renderpipeline.h"
#include "render_types.h"
@@ -68,8 +73,8 @@
static RenderEngineType internal_render_type = {
NULL, NULL,
- "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
- NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes,
+ "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL | RE_USE_LEGACY_PIPELINE,
+ NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@@ -77,8 +82,8 @@ 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,
+ "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME | RE_USE_LEGACY_PIPELINE,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@@ -88,16 +93,22 @@ 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_register();
}
void RE_engines_exit(void)
{
RenderEngineType *type, *next;
+ DRW_engines_free();
+
+ BKE_layer_collection_engine_settings_callback_free();
+ BKE_view_layer_engine_settings_callback_free();
+
for (type = R_engines.first; type; type = next) {
next = type->next;
@@ -112,6 +123,22 @@ void RE_engines_exit(void)
}
}
+void RE_engines_register(Main *bmain, RenderEngineType *render_type)
+{
+ if (render_type->draw_engine) {
+ DRW_engine_register(render_type->draw_engine);
+ }
+ if (render_type->collection_settings_create) {
+ BKE_layer_collection_engine_settings_callback_register(
+ bmain, render_type->idname, render_type->collection_settings_create);
+ }
+ if (render_type->render_settings_create) {
+ BKE_view_layer_engine_settings_callback_register(
+ bmain, render_type->idname, render_type->render_settings_create);
+ }
+ BLI_addtail(&R_engines, render_type);
+}
+
RenderEngineType *RE_engines_find(const char *idname)
{
RenderEngineType *type;
@@ -125,8 +152,7 @@ RenderEngineType *RE_engines_find(const char *idname)
bool RE_engine_is_external(Render *re)
{
- RenderEngineType *type = RE_engines_find(re->r.engine);
- return (type && type->render);
+ return (re->engine && re->engine->type && re->engine->type->render_to_image);
}
/* Create, Free */
@@ -184,7 +210,8 @@ static RenderPart *get_part_from_result(Render *re, RenderResult *result)
return NULL;
}
-RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
+RenderResult *RE_engine_begin_result(
+ RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
{
Render *re = engine->re;
RenderResult *result;
@@ -414,7 +441,8 @@ float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera, int use
return BKE_camera_multiview_shift_x(re ? &re->r : NULL, camera, re->viewname);
}
-void RE_engine_get_camera_model_matrix(RenderEngine *engine, Object *camera, int use_spherical_stereo, float *r_modelmat)
+void RE_engine_get_camera_model_matrix(
+ RenderEngine *engine, Object *camera, int use_spherical_stereo, float *r_modelmat)
{
Render *re = engine->re;
@@ -491,16 +519,18 @@ RenderData *RE_engine_get_render_data(Render *re)
}
/* Bake */
-void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene)
+void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Depsgraph *graph, Scene *scene)
{
+ re->depsgraph = graph;
re->scene = scene;
re->main = bmain;
render_copy_renderdata(&re->r, &scene->r);
+ render_copy_viewrender(&re->view_render, &scene->view_render);
}
bool RE_bake_has_engine(Render *re)
{
- RenderEngineType *type = RE_engines_find(re->r.engine);
+ RenderEngineType *type = RE_engines_find(re->view_render.engine_id);
return (type->bake != NULL);
}
@@ -511,7 +541,7 @@ bool RE_bake_engine(
const eScenePassType pass_type, const int pass_filter,
float result[])
{
- RenderEngineType *type = RE_engines_find(re->r.engine);
+ RenderEngineType *type = RE_engines_find(re->view_render.engine_id);
RenderEngine *engine;
bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
@@ -542,10 +572,21 @@ bool RE_bake_engine(
/* update is only called so we create the engine.session */
if (type->update)
- type->update(engine, re->main, re->scene);
-
- if (type->bake)
- type->bake(engine, re->scene, object, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result);
+ type->update(engine, re->main, re->depsgraph, re->scene);
+
+ if (type->bake) {
+ type->bake(
+ engine,
+ re->scene,
+ object,
+ pass_type,
+ pass_filter,
+ object_id,
+ pixel_array,
+ num_pixels,
+ depth,
+ result);
+ }
engine->tile_x = 0;
engine->tile_y = 0;
@@ -581,8 +622,7 @@ void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
BPy_BEGIN_ALLOW_THREADS;
#endif
- /* It's possible that here we're including layers which were never visible before. */
- BKE_scene_update_for_newframe_ex(re->eval_ctx, re->main, scene, (1 << 20) - 1, true);
+ BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, scene, NULL);
#ifdef WITH_PYTHON
BPy_END_ALLOW_THREADS;
@@ -593,25 +633,14 @@ void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
/* Render */
-static bool render_layer_exclude_animated(Scene *scene, SceneRenderLayer *srl)
-{
- PointerRNA ptr;
- PropertyRNA *prop;
-
- RNA_pointer_create(&scene->id, &RNA_SceneRenderLayer, srl, &ptr);
- prop = RNA_struct_find_property(&ptr, "layers_exclude");
-
- return RNA_property_animated(&ptr, prop);
-}
-
int RE_engine_render(Render *re, int do_all)
{
- RenderEngineType *type = RE_engines_find(re->r.engine);
+ RenderEngineType *type = RE_engines_find(re->view_render.engine_id);
RenderEngine *engine;
bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
/* verify if we can render */
- if (!type->render)
+ if (!type->render_to_image)
return 0;
if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW))
return 0;
@@ -628,41 +657,8 @@ int RE_engine_render(Render *re, int do_all)
/* update animation here so any render layer animation is applied before
* creating the render result */
if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_BUTS_PREVIEW)) == 0) {
- unsigned int lay = re->lay;
-
- /* don't update layers excluded on all render layers */
- if (type->flag & RE_USE_EXCLUDE_LAYERS) {
- SceneRenderLayer *srl;
- unsigned int non_excluded_lay = 0;
-
- if (re->r.scemode & R_SINGLE_LAYER) {
- srl = BLI_findlink(&re->r.layers, re->r.actlay);
- if (srl) {
- non_excluded_lay |= ~(srl->lay_exclude & ~srl->lay_zmask);
-
- /* in this case we must update all because animation for
- * the scene has not been updated yet, and so may not be
- * up to date until after BKE_scene_update_for_newframe */
- if (render_layer_exclude_animated(re->scene, srl))
- non_excluded_lay |= ~0;
- }
- }
- else {
- for (srl = re->r.layers.first; srl; srl = srl->next) {
- if (!(srl->layflag & SCE_LAY_DISABLE)) {
- non_excluded_lay |= ~(srl->lay_exclude & ~srl->lay_zmask);
-
- if (render_layer_exclude_animated(re->scene, srl))
- non_excluded_lay |= ~0;
- }
- }
- }
-
- lay &= non_excluded_lay;
- }
-
- BKE_scene_update_for_newframe_ex(re->eval_ctx, re->main, re->scene, lay, true);
- render_update_anim_renderdata(re, &re->scene->r);
+ BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, re->scene, NULL);
+ render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers);
}
/* create render result */
@@ -727,16 +723,18 @@ int RE_engine_render(Render *re, int do_all)
if (re->result->do_exr_tile)
render_result_exr_file_begin(re);
- if (type->update)
- type->update(engine, re->main, re->scene);
+ if (type->update) {
+ type->update(engine, re->main, re->depsgraph, re->scene);
+ }
/* Clear UI drawing locks. */
if (re->draw_lock) {
re->draw_lock(re->dlh, 0);
}
- if (type->render)
- type->render(engine, re->scene);
+ if (type->render_to_image) {
+ type->render_to_image(engine, re->depsgraph);
+ }
engine->tile_x = 0;
engine->tile_y = 0;
@@ -779,12 +777,12 @@ int RE_engine_render(Render *re, int do_all)
return 1;
}
-void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl,
+void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer,
const char *name, int UNUSED(channels), const char *UNUSED(chanid), int type)
{
/* The channel information is currently not used, but is part of the API in case it's needed in the future. */
- if (!(scene && srl && engine)) {
+ if (!(scene && view_layer && engine)) {
return;
}
@@ -794,7 +792,12 @@ void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, s
Scene *sce;
for (sce = G.main->scene.first; sce; sce = sce->id.next) {
if (sce->nodetree) {
- ntreeCompositRegisterPass(sce->nodetree, scene, srl, name, type);
+ ntreeCompositRegisterPass(sce->nodetree, scene, view_layer, name, type);
}
}
}
+
+ViewLayer *RE_engine_get_view_layer(Render *re)
+{
+ return re->eval_ctx->view_layer;
+}
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index fbf18405093..731a5ec4e22 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -48,6 +48,8 @@
#include "BKE_camera.h"
+#include "DEG_depsgraph.h"
+
/* this module */
#include "renderpipeline.h"
#include "render_types.h"
@@ -499,6 +501,11 @@ void RE_SetCamera(Render *re, Object *cam_ob)
re_camera_params_get(re, &params, cam_ob);
}
+void RE_SetDepsgraph(Render *re, Depsgraph *graph)
+{
+ re->depsgraph = graph;
+}
+
void RE_SetPixelSize(Render *re, float pixsize)
{
re->viewdx = pixsize;
diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
index fba5836ac32..4c0355ef604 100644
--- a/source/blender/render/intern/source/multires_bake.c
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -42,14 +42,16 @@
#include "BLI_threads.h"
#include "BKE_ccg.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_modifier.h"
#include "BKE_subsurf.h"
+#include "DEG_depsgraph.h"
+
#include "RE_multires_bake.h"
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
@@ -78,7 +80,6 @@ typedef struct {
MLoop *mloop;
MLoopUV *mloopuv;
const MLoopTri *mlooptri;
- MTexPoly *mtpoly;
float *pvtangent;
const float *precomputed_normals;
int w, h;
@@ -89,6 +90,8 @@ typedef struct {
void *bake_data;
ImBuf *ibuf;
MPassKnownData pass_data;
+ /* material aligned UV array */
+ Image **image_array;
} MResolvePixelData;
typedef void (*MFlushPixel)(const MResolvePixelData *data, const int x, const int y);
@@ -373,13 +376,15 @@ static void *do_multires_bake_thread(void *data_v)
while ((tri_index = multires_bake_queue_next_tri(handle->queue)) >= 0) {
const MLoopTri *lt = &data->mlooptri[tri_index];
- MTexPoly *mtpoly = &data->mtpoly[lt->poly];
- MLoopUV *mloopuv = data->mloopuv;
+ const MPoly *mp = &data->mpoly[lt->poly];
+ const short mat_nr = mp->mat_nr;
+ const MLoopUV *mloopuv = data->mloopuv;
if (multiresbake_test_break(bkr))
break;
- if (mtpoly->tpage != handle->image)
+ Image *tri_image = mat_nr < bkr->ob_image.len ? bkr->ob_image.array[mat_nr] : NULL;
+ if (tri_image != handle->image)
continue;
data->tri_index = tri_index;
@@ -445,7 +450,6 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
MPoly *mpoly = dm->getPolyArray(dm);
MLoop *mloop = dm->getLoopArray(dm);
MLoopUV *mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV);
- MTexPoly *mtpoly = dm->getPolyDataArray(dm, CD_MTEXPOLY);
const float *precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL);
float *pvtangent = NULL;
@@ -489,7 +493,6 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_t
handle->data.mvert = mvert;
handle->data.mloopuv = mloopuv;
handle->data.mlooptri = mlooptri;
- handle->data.mtpoly = mtpoly;
handle->data.mloop = mloop;
handle->data.pvtangent = pvtangent;
handle->data.precomputed_normals = precomputed_normals; /* don't strictly need this */
@@ -1178,30 +1181,34 @@ static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void
static void count_images(MultiresBakeRender *bkr)
{
- int a, totpoly;
- DerivedMesh *dm = bkr->lores_dm;
- MTexPoly *mtexpoly = CustomData_get_layer(&dm->polyData, CD_MTEXPOLY);
-
BLI_listbase_clear(&bkr->image);
bkr->tot_image = 0;
- totpoly = dm->getNumPolys(dm);
-
- for (a = 0; a < totpoly; a++)
- mtexpoly[a].tpage->id.tag &= ~LIB_TAG_DOIT;
+ for (int i = 0; i < bkr->ob_image.len; i++) {
+ Image *ima = bkr->ob_image.array[i];
+ if (ima) {
+ ima->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
- for (a = 0; a < totpoly; a++) {
- Image *ima = mtexpoly[a].tpage;
- if ((ima->id.tag & LIB_TAG_DOIT) == 0) {
- LinkData *data = BLI_genericNodeN(ima);
- BLI_addtail(&bkr->image, data);
- bkr->tot_image++;
- ima->id.tag |= LIB_TAG_DOIT;
+ for (int i = 0; i < bkr->ob_image.len; i++) {
+ Image *ima = bkr->ob_image.array[i];
+ if (ima) {
+ if ((ima->id.tag & LIB_TAG_DOIT) == 0) {
+ LinkData *data = BLI_genericNodeN(ima);
+ BLI_addtail(&bkr->image, data);
+ bkr->tot_image++;
+ ima->id.tag |= LIB_TAG_DOIT;
+ }
}
}
- for (a = 0; a < totpoly; a++)
- mtexpoly[a].tpage->id.tag &= ~LIB_TAG_DOIT;
+ for (int i = 0; i < bkr->ob_image.len; i++) {
+ Image *ima = bkr->ob_image.array[i];
+ if (ima) {
+ ima->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
}
static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
@@ -1283,7 +1290,7 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
}
BKE_image_release_ibuf(ima, ibuf, NULL);
- DAG_id_tag_update(&ima->id, 0);
+ DEG_id_tag_update(&ima->id, 0);
}
}
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index f5577ae89ea..7fdaf38a9ff 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -62,9 +62,9 @@
#include "BKE_animsys.h" /* <------ should this be here?, needed for sequencer update */
#include "BKE_camera.h"
#include "BKE_colortools.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_main.h"
@@ -78,6 +78,8 @@
#include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */
#include "BKE_object.h"
+#include "DEG_depsgraph.h"
+
#include "PIL_time.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
@@ -262,7 +264,7 @@ RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool
RenderLayer *render_get_active_layer(Render *re, RenderResult *rr)
{
- RenderLayer *rl = BLI_findlink(&rr->layers, re->r.actlay);
+ RenderLayer *rl = BLI_findlink(&rr->layers, re->active_view_layer);
if (rl)
return rl;
@@ -272,21 +274,21 @@ RenderLayer *render_get_active_layer(Render *re, RenderResult *rr)
static int render_scene_needs_vector(Render *re)
{
- SceneRenderLayer *srl;
-
- for (srl = re->r.layers.first; srl; srl = srl->next)
- if (!(srl->layflag & SCE_LAY_DISABLE))
- if (srl->passflag & SCE_PASS_VECTOR)
+ ViewLayer *view_layer;
+ for (view_layer = re->view_layers.first; view_layer; view_layer = view_layer->next)
+ if (view_layer->flag & VIEW_LAYER_RENDER) {
+ if (view_layer->passflag & SCE_PASS_VECTOR) {
return 1;
-
+ }
+ }
return 0;
}
static bool render_scene_has_layers_to_render(Scene *scene)
{
- SceneRenderLayer *srl;
- for (srl = scene->r.layers.first; srl; srl = srl->next) {
- if (!(srl->layflag & SCE_LAY_DISABLE)) {
+ ViewLayer *view_layer;
+ for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ if (view_layer->flag & VIEW_LAYER_RENDER) {
return true;
}
}
@@ -351,6 +353,15 @@ Scene *RE_GetScene(Render *re)
return NULL;
}
+EvaluationContext *RE_GetEvalCtx(Render *re)
+{
+ if (re) {
+ return re->eval_ctx;
+ }
+
+ return NULL;
+}
+
/**
* Same as #RE_AcquireResultImage but creating the necessary views to store the result
* fill provided result struct with a copy of thew views of what is done so far the
@@ -573,7 +584,7 @@ void RE_FreeRender(Render *re)
BLI_rw_mutex_end(&re->resultmutex);
BLI_rw_mutex_end(&re->partsmutex);
- BLI_freelistN(&re->r.layers);
+ BLI_freelistN(&re->view_layers);
BLI_freelistN(&re->r.views);
curvemapping_free_data(&re->r.mblur_shutter_curve);
@@ -581,6 +592,7 @@ void RE_FreeRender(Render *re)
/* main dbase can already be invalid now, some database-free code checks it */
re->main = NULL;
re->scene = NULL;
+ re->depsgraph = NULL;
RE_Database_Free(re); /* view render can still have full database */
free_sample_tables(re);
@@ -650,12 +662,13 @@ void RE_FreePersistentData(void)
/* ********* initialize state ******** */
/* clear full sample and tile flags if needed */
-static int check_mode_full_sample(RenderData *rd)
+static int check_mode_full_sample(RenderData *rd, ViewRender *view_render)
{
+ const char *engine_id = view_render->engine_id;
int scemode = rd->scemode;
- if (!STREQ(rd->engine, RE_engine_id_BLENDER_RENDER) &&
- !STREQ(rd->engine, RE_engine_id_BLENDER_GAME))
+ if (!STREQ(engine_id, RE_engine_id_BLENDER_RENDER) &&
+ !STREQ(engine_id, RE_engine_id_BLENDER_GAME))
{
scemode &= ~R_FULL_SAMPLE;
}
@@ -717,21 +730,25 @@ static void re_init_resolution(Render *re, Render *source,
void render_copy_renderdata(RenderData *to, RenderData *from)
{
- BLI_freelistN(&to->layers);
BLI_freelistN(&to->views);
curvemapping_free_data(&to->mblur_shutter_curve);
*to = *from;
- BLI_duplicatelist(&to->layers, &from->layers);
BLI_duplicatelist(&to->views, &from->views);
curvemapping_copy_data(&to->mblur_shutter_curve, &from->mblur_shutter_curve);
}
+void render_copy_viewrender(ViewRender *to, ViewRender *from)
+{
+ BKE_viewrender_copy(to, from);
+}
+
/* what doesn't change during entire render sequence */
/* disprect is optional, if NULL it assumes full window render */
void RE_InitState(Render *re, Render *source, RenderData *rd,
- SceneRenderLayer *srl,
+ ListBase *render_layers, const int active_layer,
+ ViewRender *view_render, ViewLayer *view_layer,
int winx, int winy, rcti *disprect)
{
bool had_freestyle = (re->r.mode & R_EDGE_FRS) != 0;
@@ -742,6 +759,10 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
/* copy render data and render layers for thread safety */
render_copy_renderdata(&re->r, rd);
+ render_copy_viewrender(&re->view_render, view_render);
+ BLI_freelistN(&re->view_layers);
+ BLI_duplicatelist(&re->view_layers, render_layers);
+ re->active_view_layer = active_layer;
if (source) {
/* reuse border flags from source renderer */
@@ -771,7 +792,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
return;
}
- re->r.scemode = check_mode_full_sample(&re->r);
+ re->r.scemode = check_mode_full_sample(&re->r, &re->view_render);
/* fullsample wants uniform osa levels */
if (source && (re->r.scemode & R_FULL_SAMPLE)) {
@@ -790,10 +811,10 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
else re->osa = 0;
}
- if (srl) {
- int index = BLI_findindex(&rd->layers, srl);
+ if (view_layer) {
+ int index = BLI_findindex(render_layers, view_layer);
if (index != -1) {
- re->r.actlay = index;
+ re->active_view_layer = index;
re->r.scemode |= R_SINGLE_LAYER;
}
}
@@ -811,12 +832,12 @@ void RE_InitState(Render *re, Render *source, RenderData *rd,
re->result = NULL;
}
else if (re->result) {
- SceneRenderLayer *actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
+ ViewLayer *active_render_layer = BLI_findlink(&re->view_layers, re->active_view_layer);
RenderLayer *rl;
bool have_layer = false;
for (rl = re->result->layers.first; rl; rl = rl->next)
- if (STREQ(rl->name, actsrl->name))
+ if (STREQ(rl->name, active_render_layer->name))
have_layer = true;
if (re->result->rectx == re->rectx && re->result->recty == re->recty &&
@@ -941,7 +962,7 @@ void RE_ChangeModeFlag(Render *re, int flag, bool clear)
/* update some variables that can be animated, and otherwise wouldn't be due to
* RenderData getting copied once at the start of animation render */
-void render_update_anim_renderdata(Render *re, RenderData *rd)
+void render_update_anim_renderdata(Render *re, RenderData *rd, ListBase *render_layers)
{
/* filter */
re->r.gauss = rd->gauss;
@@ -955,8 +976,8 @@ void render_update_anim_renderdata(Render *re, RenderData *rd)
re->r.unit_line_thickness = rd->unit_line_thickness;
/* render layers */
- BLI_freelistN(&re->r.layers);
- BLI_duplicatelist(&re->r.layers, &rd->layers);
+ BLI_freelistN(&re->view_layers);
+ BLI_duplicatelist(&re->view_layers, render_layers);
/* render views */
BLI_freelistN(&re->r.views);
@@ -1729,7 +1750,7 @@ static void do_render_blur_3d(Render *re)
/* make sure motion blur changes get reset to current frame */
if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0) {
- BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, re->lay);
+ BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, re->scene, NULL);
}
/* weak... the display callback wants an active renderlayer pointer... */
@@ -1958,13 +1979,14 @@ static void render_scene(Render *re, Scene *sce, int cfra)
}
/* initial setup */
- RE_InitState(resc, re, &sce->r, NULL, winx, winy, &re->disprect);
+ RE_InitState(resc, re, &sce->r, &sce->view_layers, sce->active_view_layer, &sce->view_render, NULL, winx, winy, &re->disprect);
/* We still want to use 'rendercache' setting from org (main) scene... */
resc->r.scemode = (resc->r.scemode & ~R_EXR_CACHE_FILE) | (re->r.scemode & R_EXR_CACHE_FILE);
/* still unsure entity this... */
resc->main = re->main;
+ resc->depsgraph = re->depsgraph;
resc->scene = sce;
resc->lay = sce->lay;
resc->scene_color_manage = BKE_scene_check_color_management_enabled(sce);
@@ -2045,17 +2067,10 @@ bool RE_allow_render_generic_object(Object *ob)
#define DEPSGRAPH_WORKAROUND_HACK
#ifdef DEPSGRAPH_WORKAROUND_HACK
-static void tag_dependend_objects_for_render(Scene *scene, int renderlay)
+static void tag_dependend_objects_for_render(Scene *scene, int UNUSED(renderlay))
{
- Scene *sce_iter;
- Base *base;
- for (SETLOOPER(scene, sce_iter, base)) {
- Object *object = base->object;
-
- if ((base->lay & renderlay) == 0) {
- continue;
- }
-
+ FOREACH_OBJECT_RENDERABLE(scene, object)
+ {
if (object->type == OB_MESH) {
if (RE_allow_render_generic_object(object)) {
ModifierData *md;
@@ -2072,28 +2087,29 @@ static void tag_dependend_objects_for_render(Scene *scene, int renderlay)
if (md->type == eModifierType_Boolean) {
BooleanModifierData *bmd = (BooleanModifierData *)md;
if (bmd->object && bmd->object->type == OB_MESH) {
- DAG_id_tag_update(&bmd->object->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&bmd->object->id, OB_RECALC_DATA);
}
}
else if (md->type == eModifierType_Array) {
ArrayModifierData *amd = (ArrayModifierData *)md;
if (amd->start_cap && amd->start_cap->type == OB_MESH) {
- DAG_id_tag_update(&amd->start_cap->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&amd->start_cap->id, OB_RECALC_DATA);
}
if (amd->end_cap && amd->end_cap->type == OB_MESH) {
- DAG_id_tag_update(&amd->end_cap->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&amd->end_cap->id, OB_RECALC_DATA);
}
}
else if (md->type == eModifierType_Shrinkwrap) {
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
if (smd->target && smd->target->type == OB_MESH) {
- DAG_id_tag_update(&smd->target->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&smd->target->id, OB_RECALC_DATA);
}
}
}
}
}
}
+ FOREACH_OBJECT_RENDERABLE_END
}
#endif
@@ -2234,24 +2250,24 @@ static void init_freestyle(Render *re)
/* invokes Freestyle stroke rendering */
static void add_freestyle(Render *re, int render)
{
- SceneRenderLayer *srl, *actsrl;
+ ViewLayer *view_layer, *active_view_layer;
LinkData *link;
Render *r;
const bool do_link = (re->r.mode & R_MBLUR) == 0 || re->i.curblur == re->r.mblur_samples;
- actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
+ active_view_layer = BLI_findlink(&re->view_layers, re->active_view_layer);
FRS_begin_stroke_rendering(re);
- for (srl = (SceneRenderLayer *)re->r.layers.first; srl; srl = srl->next) {
+ for (view_layer = (ViewLayer *)re->view_layers.first; view_layer; view_layer = view_layer->next) {
if (do_link) {
link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render");
BLI_addtail(&re->freestyle_renders, link);
}
- if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
+ if ((re->r.scemode & R_SINGLE_LAYER) && view_layer != active_view_layer)
continue;
- if (FRS_is_freestyle_enabled(srl)) {
- r = FRS_do_stroke_rendering(re, srl, render);
+ if (FRS_is_freestyle_enabled(view_layer)) {
+ r = FRS_do_stroke_rendering(re, view_layer, render);
if (do_link)
link->data = (void *)r;
}
@@ -2268,25 +2284,25 @@ static void composite_freestyle_renders(Render *re, int sample)
{
Render *freestyle_render;
RenderView *rv;
- SceneRenderLayer *srl, *actsrl;
+ ViewLayer *view_layer, *active_view_layer;
LinkData *link;
- actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
+ active_view_layer = BLI_findlink(&re->view_layers, re->active_view_layer);
link = (LinkData *)re->freestyle_renders.first;
for (rv = re->result->views.first; rv; rv = rv->next) {
- for (srl = (SceneRenderLayer *)re->r.layers.first; srl; srl = srl->next) {
- if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
+ for (view_layer = (ViewLayer *)re->view_layers.first; view_layer; view_layer = view_layer->next) {
+ if ((re->r.scemode & R_SINGLE_LAYER) && view_layer != active_view_layer)
continue;
- if (FRS_is_freestyle_enabled(srl)) {
+ if (FRS_is_freestyle_enabled(view_layer)) {
freestyle_render = (Render *)link->data;
/* may be NULL in case of empty render layer */
if (freestyle_render) {
render_result_exr_file_read_sample(freestyle_render, sample);
- FRS_composite_result(re, srl, freestyle_render);
+ FRS_composite_result(re, view_layer, freestyle_render);
RE_FreeRenderResult(freestyle_render->result);
freestyle_render->result = NULL;
}
@@ -2621,7 +2637,7 @@ static void do_render_composite_fields_blur_3d(Render *re)
R.i.cfra = re->i.cfra;
if (update_newframe)
- BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, re->lay);
+ BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, re->main, re->scene, NULL);
if (re->r.scemode & R_FULL_SAMPLE)
do_merge_fullsample(re, ntree);
@@ -2864,12 +2880,12 @@ static void do_render_all_options(Render *re)
bool RE_force_single_renderlayer(Scene *scene)
{
- int scemode = check_mode_full_sample(&scene->r);
+ int scemode = check_mode_full_sample(&scene->r, &scene->view_render);
if (scemode & R_SINGLE_LAYER) {
- SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
/* force layer to be enabled */
- if (srl->layflag & SCE_LAY_DISABLE) {
- srl->layflag &= ~SCE_LAY_DISABLE;
+ if ((view_layer->flag & VIEW_LAYER_RENDER) == 0) {
+ view_layer->flag |= VIEW_LAYER_RENDER;
return true;
}
}
@@ -2885,7 +2901,7 @@ static bool check_valid_compositing_camera(Scene *scene, Object *camera_override
if (node->type == CMP_NODE_R_LAYERS && (node->flag & NODE_MUTED) == 0) {
Scene *sce = node->id ? (Scene *)node->id : scene;
if (sce->camera == NULL) {
- sce->camera = BKE_scene_camera_find(sce);
+ sce->camera = BKE_view_layer_camera_find(BKE_view_layer_from_scene_get(sce));
}
if (sce->camera == NULL) {
/* all render layers nodes need camera */
@@ -2943,7 +2959,7 @@ static int check_valid_camera(Scene *scene, Object *camera_override, ReportList
const char *err_msg = "No camera found in scene \"%s\"";
if (camera_override == NULL && scene->camera == NULL)
- scene->camera = BKE_scene_camera_find(scene);
+ scene->camera = BKE_view_layer_camera_find(BKE_view_layer_from_scene_get(scene));
if (!check_valid_camera_multiview(scene, scene->camera, reports))
return false;
@@ -2958,7 +2974,9 @@ static int check_valid_camera(Scene *scene, Object *camera_override, ReportList
(seq->scene != NULL))
{
if (!seq->scene_camera) {
- if (!seq->scene->camera && !BKE_scene_camera_find(seq->scene)) {
+ if (!seq->scene->camera &&
+ !BKE_view_layer_camera_find(BKE_view_layer_from_scene_get(seq->scene)))
+ {
/* camera could be unneeded due to composite nodes */
Object *override = (seq->scene == scene) ? camera_override : NULL;
@@ -3011,7 +3029,7 @@ static int check_composite_output(Scene *scene)
bool RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *reports)
{
- int scemode = check_mode_full_sample(&scene->r);
+ int scemode = check_mode_full_sample(&scene->r, &scene->view_render);
if (scene->r.mode & R_BORDER) {
if (scene->r.border.xmax <= scene->r.border.xmin ||
@@ -3124,13 +3142,15 @@ static void validate_render_settings(Render *re)
}
}
-static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init))
+static void update_physics_cache(Render *re, Scene *scene, ViewLayer *view_layer, int UNUSED(anim_init))
{
PTCacheBaker baker;
memset(&baker, 0, sizeof(baker));
baker.main = re->main;
baker.scene = scene;
+ baker.view_layer = view_layer;
+ baker.depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
baker.bake = 0;
baker.render = 1;
baker.anim_init = 1;
@@ -3149,9 +3169,15 @@ const char *RE_GetActiveRenderView(Render *re)
return re->viewname;
}
+void RE_SetEngineByID(Render *re, const char *engine_id)
+{
+ BLI_strncpy(re->view_render.engine_id, engine_id, sizeof(re->view_render.engine_id));
+}
+
/* evaluating scene options for general Blender render */
-static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, Scene *scene, SceneRenderLayer *srl,
- Object *camera_override, unsigned int lay_override, int anim, int anim_init)
+static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, Scene *scene, ViewRender *view_render,
+ ViewLayer *view_layer, Object *camera_override, unsigned int lay_override,
+ int anim, int anim_init)
{
int winx, winy;
rcti disprect;
@@ -3185,10 +3211,11 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain,
re->layer_override = lay_override;
re->i.localview = (re->lay & 0xFF000000) != 0;
re->viewname[0] = '\0';
+ RE_SetEngineByID(re, view_render->engine_id);
/* not too nice, but it survives anim-border render */
if (anim) {
- render_update_anim_renderdata(re, &scene->r);
+ render_update_anim_renderdata(re, &scene->r, &scene->view_layers);
re->disprect = disprect;
return 1;
}
@@ -3203,16 +3230,17 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain,
*/
if (0) {
/* make sure dynamics are up to date */
- update_physics_cache(re, scene, anim_init);
+ view_layer = BKE_view_layer_from_scene_get(scene);
+ update_physics_cache(re, scene, view_layer, anim_init);
}
- if (srl || scene->r.scemode & R_SINGLE_LAYER) {
+ if (view_layer || scene->r.scemode & R_SINGLE_LAYER) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
render_result_single_layer_begin(re);
BLI_rw_mutex_unlock(&re->resultmutex);
}
- RE_InitState(re, NULL, &scene->r, srl, winx, winy, &disprect);
+ RE_InitState(re, NULL, &scene->r, &scene->view_layers, scene->active_view_layer, &scene->view_render, view_layer, winx, winy, &disprect);
if (!re->ok) /* if an error was printed, abort */
return 0;
@@ -3233,7 +3261,7 @@ void RE_SetReports(Render *re, ReportList *reports)
}
/* general Blender frame render call */
-void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, Object *camera_override,
+void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, ViewLayer *view_layer, Object *camera_override,
unsigned int lay_override, int frame, const bool write_still)
{
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT);
@@ -3243,7 +3271,9 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
scene->r.cfra = frame;
- if (render_initialize_from_main(re, &scene->r, bmain, scene, srl, camera_override, lay_override, 0, 0)) {
+ if (render_initialize_from_main(re, &scene->r, bmain, scene, &scene->view_render, view_layer,
+ camera_override, lay_override, 0, 0))
+ {
MEM_reset_peak_memory();
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
@@ -3282,7 +3312,7 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
void RE_RenderFreestyleStrokes(Render *re, Main *bmain, Scene *scene, int render)
{
re->result_ok= 0;
- if (render_initialize_from_main(re, &scene->r, bmain, scene, NULL, NULL, scene->lay, 0, 0)) {
+ if (render_initialize_from_main(re, &scene->r, bmain, scene, &scene->view_render, NULL, NULL, scene->lay, 0, 0)) {
if (render)
do_render_fields_blur_3d(re);
}
@@ -3577,7 +3607,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT);
/* do not fully call for each frame, it initializes & pops output window */
- if (!render_initialize_from_main(re, &rd, bmain, scene, NULL, camera_override, lay_override, 0, 1))
+ if (!render_initialize_from_main(re, &rd, bmain, scene, &scene->view_render, NULL, camera_override, lay_override, 0, 1))
return;
/* MULTIVIEW_TODO:
@@ -3667,22 +3697,12 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
}
/* only border now, todo: camera lens. (ton) */
- render_initialize_from_main(re, &rd, bmain, scene, NULL, camera_override, lay_override, 1, 0);
+ render_initialize_from_main(re, &rd, bmain, scene, &scene->view_render,
+ NULL, camera_override, lay_override, 1, 0);
if (nfra != scene->r.cfra) {
- /*
- * Skip this frame, but update for physics and particles system.
- * From convertblender.c:
- * in localview, lamps are using normal layers, objects only local bits.
- */
- unsigned int updatelay;
-
- if (re->lay & 0xFF000000)
- updatelay = re->lay & 0xFF000000;
- else
- updatelay = re->lay;
-
- BKE_scene_update_for_newframe(re->eval_ctx, bmain, scene, updatelay);
+ /* Skip this frame, but update for physics and particles system. */
+ BKE_scene_graph_update_for_newframe(re->eval_ctx, re->depsgraph, bmain, scene, NULL);
continue;
}
else
@@ -3828,15 +3848,16 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
G.is_rendering = false;
}
-void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
+void RE_PreviewRender(Render *re, Main *bmain, Scene *sce, ViewRender *view_render)
{
Object *camera;
+ ViewLayer *view_layer = BKE_view_layer_from_scene_get(sce);
int winx, winy;
winx = (sce->r.size * sce->r.xsch) / 100;
winy = (sce->r.size * sce->r.ysch) / 100;
- RE_InitState(re, NULL, &sce->r, NULL, winx, winy, NULL);
+ RE_InitState(re, NULL, &sce->r, &sce->view_layers, sce->active_view_layer, view_render, NULL, winx, winy, NULL);
re->pool = BKE_image_pool_new();
@@ -3844,6 +3865,8 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
re->scene = sce;
re->scene_color_manage = BKE_scene_check_color_management_enabled(sce);
re->lay = sce->lay;
+ re->depsgraph = BKE_scene_get_depsgraph(sce, view_layer, false);
+ re->eval_ctx->view_layer = view_layer;
camera = RE_GetCamera(re);
RE_SetCamera(re, camera);
@@ -3889,7 +3912,7 @@ bool RE_ReadRenderResult(Scene *scene, Scene *scenode)
re = RE_GetSceneRender(scene);
if (re == NULL)
re = RE_NewSceneRender(scene);
- RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect);
+ RE_InitState(re, NULL, &scene->r, &scene->view_layers, scene->active_view_layer, &scene->view_render, NULL, winx, winy, &disprect);
re->scene = scene;
re->scene_color_manage = BKE_scene_check_color_management_enabled(scene);
@@ -4122,7 +4145,6 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha
rl = MEM_callocN(sizeof(RenderLayer), layername);
BLI_addtail(&rr->layers, rl);
BLI_strncpy(rl->name, layername, sizeof(rl->name));
- rl->lay = 0;
rl->layflag = SCE_LAY_SOLID;
rl->passflag = SCE_PASS_COMBINED;
rl->rectx = rr->rectx;
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index b215db49264..28d62f36ddd 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -58,6 +58,8 @@
#include "BKE_scene.h"
#include "BKE_colortools.h"
+#include "DEG_depsgraph.h"
+
#include "render_types.h"
#include "texture.h"
#include "pointdensity.h"
@@ -167,7 +169,7 @@ static void alloc_point_data(PointDensity *pd)
}
}
-static void pointdensity_cache_psys(Scene *scene,
+static void pointdensity_cache_psys(EvaluationContext *eval_ctx, Scene *scene,
PointDensity *pd,
Object *ob,
ParticleSystem *psys,
@@ -201,12 +203,12 @@ static void pointdensity_cache_psys(Scene *scene,
}
if (use_render_params) {
- dm = mesh_create_derived_render(scene,
+ dm = mesh_create_derived_render(eval_ctx, scene,
ob,
CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
}
else {
- dm = mesh_get_derived_final(scene,
+ dm = mesh_get_derived_final(eval_ctx, scene,
ob,
CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
}
@@ -216,6 +218,7 @@ static void pointdensity_cache_psys(Scene *scene,
return;
}
+ sim.eval_ctx = eval_ctx;
sim.scene = scene;
sim.ob = ob;
sim.psys = psys;
@@ -400,7 +403,7 @@ static void pointdensity_cache_vertex_normal(PointDensity *pd, Object *UNUSED(ob
}
}
-static void pointdensity_cache_object(Scene *scene,
+static void pointdensity_cache_object(EvaluationContext *eval_ctx, Scene *scene,
PointDensity *pd,
Object *ob,
const bool use_render_params)
@@ -421,10 +424,10 @@ static void pointdensity_cache_object(Scene *scene,
}
if (use_render_params) {
- dm = mesh_create_derived_render(scene, ob, mask);
+ dm = mesh_create_derived_render(eval_ctx, scene, ob, mask);
}
else {
- dm = mesh_get_derived_final(scene, ob, mask);
+ dm = mesh_get_derived_final(eval_ctx, scene, ob, mask);
}
mvert = dm->getVertArray(dm); /* local object space */
@@ -475,7 +478,7 @@ static void pointdensity_cache_object(Scene *scene,
}
-static void cache_pointdensity_ex(Scene *scene,
+static void cache_pointdensity_ex(EvaluationContext *eval_ctx, Scene *scene,
PointDensity *pd,
float viewmat[4][4],
float winmat[4][4],
@@ -504,7 +507,8 @@ static void cache_pointdensity_ex(Scene *scene,
return;
}
- pointdensity_cache_psys(scene,
+ pointdensity_cache_psys(eval_ctx,
+ scene,
pd,
ob,
psys,
@@ -515,13 +519,14 @@ static void cache_pointdensity_ex(Scene *scene,
else if (pd->source == TEX_PD_OBJECT) {
Object *ob = pd->object;
if (ob && ob->type == OB_MESH)
- pointdensity_cache_object(scene, pd, ob, use_render_params);
+ pointdensity_cache_object(eval_ctx, scene, pd, ob, use_render_params);
}
}
void cache_pointdensity(Render *re, PointDensity *pd)
{
- cache_pointdensity_ex(re->scene,
+ cache_pointdensity_ex(re->eval_ctx,
+ re->scene,
pd,
re->viewmat, re->winmat,
re->winx, re->winy,
@@ -876,7 +881,8 @@ static void sample_dummy_point_density(int resolution, float *values)
memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution);
}
-static void particle_system_minmax(Scene *scene,
+static void particle_system_minmax(EvaluationContext *eval_ctx,
+ Scene *scene,
Object *object,
ParticleSystem *psys,
float radius,
@@ -903,6 +909,7 @@ static void particle_system_minmax(Scene *scene,
psys_render_set(object, psys, mat, mat, 1, 1, 0);
}
+ sim.eval_ctx = eval_ctx;
sim.scene = scene;
sim.ob = object;
sim.psys = psys;
@@ -938,19 +945,28 @@ static void particle_system_minmax(Scene *scene,
void RE_point_density_cache(
Scene *scene,
+ ViewLayer *view_layer,
PointDensity *pd,
const bool use_render_params)
{
+ EvaluationContext eval_ctx = {0};
float mat[4][4];
+
+ DEG_evaluation_context_init(&eval_ctx, use_render_params ? DAG_EVAL_RENDER
+ : DAG_EVAL_VIEWPORT);
+
+ eval_ctx.view_layer = view_layer;
+
/* Same matricies/resolution as dupli_render_particle_set(). */
unit_m4(mat);
BLI_mutex_lock(&sample_mutex);
- cache_pointdensity_ex(scene, pd, mat, mat, 1, 1, use_render_params);
+ cache_pointdensity_ex(&eval_ctx, scene, pd, mat, mat, 1, 1, use_render_params);
BLI_mutex_unlock(&sample_mutex);
}
void RE_point_density_minmax(
struct Scene *scene,
+ ViewLayer *view_layer,
struct PointDensity *pd,
const bool use_render_params,
float r_min[3], float r_max[3])
@@ -963,6 +979,8 @@ void RE_point_density_minmax(
}
if (pd->source == TEX_PD_PSYS) {
ParticleSystem *psys;
+ EvaluationContext eval_ctx = {0};
+
if (pd->psys == 0) {
zero_v3(r_min);
zero_v3(r_max);
@@ -974,7 +992,15 @@ void RE_point_density_minmax(
zero_v3(r_max);
return;
}
- particle_system_minmax(scene,
+
+ DEG_evaluation_context_init(&eval_ctx, use_render_params ? DAG_EVAL_RENDER :
+ DAG_EVAL_VIEWPORT);
+
+ eval_ctx.ctime = (float)scene->r.cfra + scene->r.subframe;
+ eval_ctx.view_layer = view_layer;
+
+ particle_system_minmax(&eval_ctx,
+ scene,
object,
psys,
pd->radius,
@@ -1044,6 +1070,7 @@ static void point_density_sample_func(void *data_v, const int iter)
*/
void RE_point_density_sample(
Scene *scene,
+ ViewLayer *view_layer,
PointDensity *pd,
const int resolution,
const bool use_render_params,
@@ -1063,6 +1090,7 @@ void RE_point_density_sample(
BLI_mutex_lock(&sample_mutex);
RE_point_density_minmax(scene,
+ view_layer,
pd,
use_render_params,
min,
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 26a0b0c71b4..7bac7f29c5a 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -742,8 +742,6 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, con
shi.passflag= SCE_PASS_COMBINED; /* result of tracing needs no pass info */
shi.combinedflag= 0xFFFFFF; /* ray trace does all options */
//shi.do_preview = false; // memset above, so don't need this
- shi.light_override= origshi->light_override;
- shi.mat_override= origshi->mat_override;
shade_ray(&isec, &shi, &shr);
/* ray has traveled inside the material, so shade by transmission */
@@ -995,7 +993,7 @@ static float *give_jitter_plane(LampRen *lar, int thread, int xs, int ys)
/* **************** QMC sampling *************** */
-static void halton_sample(double *ht_invprimes, double *ht_nums, double *v)
+static void UNUSED_FUNCTION(halton_sample)(double *ht_invprimes, double *ht_nums, double *v)
{
/* incremental halton sequence generator, from:
* "Instant Radiosity", Keller A. */
@@ -1022,26 +1020,6 @@ static void halton_sample(double *ht_invprimes, double *ht_nums, double *v)
}
}
-/* Generate Hammersley points in [0,1)^2
- * From Lucille renderer */
-static void hammersley_create(double *out, int n)
-{
- double p, t;
- int k, kk;
-
- for (k = 0; k < n; k++) {
- t = 0;
- for (p = 0.5, kk = k; kk; p *= 0.5, kk >>= 1) {
- if (kk & 1) { /* kk mod 2 = 1 */
- t += p;
- }
- }
-
- out[2 * k + 0] = (double)k / (double)n;
- out[2 * k + 1] = t;
- }
-}
-
static struct QMCSampler *QMC_initSampler(int type, int tot)
{
QMCSampler *qsa = MEM_callocN(sizeof(QMCSampler), "qmc sampler");
@@ -1051,7 +1029,7 @@ static struct QMCSampler *QMC_initSampler(int type, int tot)
qsa->type = type;
if (qsa->type==SAMP_TYPE_HAMMERSLEY)
- hammersley_create(qsa->samp2d, qsa->tot);
+ BLI_hammersley_2D_sequence(qsa->tot, qsa->samp2d);
return qsa;
}
@@ -1069,20 +1047,13 @@ static void QMC_initPixel(QMCSampler *qsa, int thread)
/* generate a new randomized halton sequence per pixel
* to alleviate qmc artifacts and make it reproducible
* between threads/frames */
- double ht_invprimes[2], ht_nums[2];
- double r[2];
- int i;
+ double ht_offset[2];
+ unsigned int ht_primes[2] = {2, 3};
- ht_nums[0] = BLI_thread_frand(thread);
- ht_nums[1] = BLI_thread_frand(thread);
- ht_invprimes[0] = 0.5;
- ht_invprimes[1] = 1.0/3.0;
+ ht_offset[0] = BLI_thread_frand(thread);
+ ht_offset[1] = BLI_thread_frand(thread);
- for (i=0; i< qsa->tot; i++) {
- halton_sample(ht_invprimes, ht_nums, r);
- qsa->samp2d[2*i+0] = r[0];
- qsa->samp2d[2*i+1] = r[1];
- }
+ BLI_halton_2D_sequence(ht_primes, ht_offset, qsa->tot, qsa->samp2d);
}
}
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 88ccb9452ba..0e7f35fbca3 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -264,7 +264,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
RenderResult *rr;
RenderLayer *rl;
RenderView *rv;
- SceneRenderLayer *srl;
+ ViewLayer *view_layer;
int rectx, recty;
int nr;
@@ -294,33 +294,30 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
render_result_views_new(rr, &re->r);
/* check renderdata for amount of layers */
- for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) {
+ for (nr = 0, view_layer = re->view_layers.first; view_layer; view_layer = view_layer->next, nr++) {
if (layername && layername[0])
- if (!STREQ(srl->name, layername))
+ if (!STREQ(view_layer->name, layername))
continue;
if (re->r.scemode & R_SINGLE_LAYER) {
- if (nr != re->r.actlay)
+ if (nr != re->active_view_layer) {
continue;
+ }
}
else {
- if (srl->layflag & SCE_LAY_DISABLE)
+ if ((view_layer->flag & VIEW_LAYER_RENDER) == 0) {
continue;
+ }
}
rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
BLI_addtail(&rr->layers, rl);
- BLI_strncpy(rl->name, srl->name, sizeof(rl->name));
- rl->lay = srl->lay;
- rl->lay_zmask = srl->lay_zmask;
- rl->lay_exclude = srl->lay_exclude;
- rl->layflag = srl->layflag;
- rl->passflag = srl->passflag; /* for debugging: srl->passflag | SCE_PASS_RAYHITS; */
- rl->pass_xor = srl->pass_xor;
- rl->light_override = srl->light_override;
- rl->mat_override = srl->mat_override;
+ BLI_strncpy(rl->name, view_layer->name, sizeof(rl->name));
+ rl->layflag = view_layer->layflag;
+ rl->passflag = view_layer->passflag; /* for debugging: view_layer->passflag | SCE_PASS_RAYHITS; */
+ rl->pass_xor = view_layer->pass_xor;
rl->rectx = rectx;
rl->recty = recty;
@@ -355,65 +352,65 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
/* a renderlayer should always have a Combined pass*/
render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA");
- if (srl->passflag & SCE_PASS_Z)
+ if (view_layer->passflag & SCE_PASS_Z)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z");
- if (srl->passflag & SCE_PASS_VECTOR)
+ if (view_layer->passflag & SCE_PASS_VECTOR)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW");
- if (srl->passflag & SCE_PASS_NORMAL)
+ if (view_layer->passflag & SCE_PASS_NORMAL)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ");
- if (srl->passflag & SCE_PASS_UV)
+ if (view_layer->passflag & SCE_PASS_UV)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA");
- if (srl->passflag & SCE_PASS_RGBA)
+ if (view_layer->passflag & SCE_PASS_RGBA)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RGBA, view, "RGBA");
- if (srl->passflag & SCE_PASS_EMIT)
+ if (view_layer->passflag & SCE_PASS_EMIT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB");
- if (srl->passflag & SCE_PASS_DIFFUSE)
+ if (view_layer->passflag & SCE_PASS_DIFFUSE)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE, view, "RGB");
- if (srl->passflag & SCE_PASS_SPEC)
+ if (view_layer->passflag & SCE_PASS_SPEC)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SPEC, view, "RGB");
- if (srl->passflag & SCE_PASS_AO)
+ if (view_layer->passflag & SCE_PASS_AO)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB");
- if (srl->passflag & SCE_PASS_ENVIRONMENT)
+ if (view_layer->passflag & SCE_PASS_ENVIRONMENT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB");
- if (srl->passflag & SCE_PASS_INDIRECT)
+ if (view_layer->passflag & SCE_PASS_INDIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_INDIRECT, view, "RGB");
- if (srl->passflag & SCE_PASS_SHADOW)
+ if (view_layer->passflag & SCE_PASS_SHADOW)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB");
- if (srl->passflag & SCE_PASS_REFLECT)
+ if (view_layer->passflag & SCE_PASS_REFLECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFLECT, view, "RGB");
- if (srl->passflag & SCE_PASS_REFRACT)
+ if (view_layer->passflag & SCE_PASS_REFRACT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFRACT, view, "RGB");
- if (srl->passflag & SCE_PASS_INDEXOB)
+ if (view_layer->passflag & SCE_PASS_INDEXOB)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X");
- if (srl->passflag & SCE_PASS_INDEXMA)
+ if (view_layer->passflag & SCE_PASS_INDEXMA)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X");
- if (srl->passflag & SCE_PASS_MIST)
+ if (view_layer->passflag & SCE_PASS_MIST)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z");
if (rl->passflag & SCE_PASS_RAYHITS)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RAYHITS, view, "RGB");
- if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT)
+ if (view_layer->passflag & SCE_PASS_DIFFUSE_DIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB");
- if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT)
+ if (view_layer->passflag & SCE_PASS_DIFFUSE_INDIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB");
- if (srl->passflag & SCE_PASS_DIFFUSE_COLOR)
+ if (view_layer->passflag & SCE_PASS_DIFFUSE_COLOR)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB");
- if (srl->passflag & SCE_PASS_GLOSSY_DIRECT)
+ if (view_layer->passflag & SCE_PASS_GLOSSY_DIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB");
- if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT)
+ if (view_layer->passflag & SCE_PASS_GLOSSY_INDIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB");
- if (srl->passflag & SCE_PASS_GLOSSY_COLOR)
+ if (view_layer->passflag & SCE_PASS_GLOSSY_COLOR)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB");
- if (srl->passflag & SCE_PASS_TRANSM_DIRECT)
+ if (view_layer->passflag & SCE_PASS_TRANSM_DIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB");
- if (srl->passflag & SCE_PASS_TRANSM_INDIRECT)
+ if (view_layer->passflag & SCE_PASS_TRANSM_INDIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB");
- if (srl->passflag & SCE_PASS_TRANSM_COLOR)
+ if (view_layer->passflag & SCE_PASS_TRANSM_COLOR)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB");
- if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT)
+ if (view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB");
- if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT)
+ if (view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB");
- if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR)
+ if (view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR)
RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB");
#undef RENDER_LAYER_ADD_PASS_SAFE
}
@@ -447,11 +444,10 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
}
/* note, this has to be in sync with scene.c */
- rl->lay = (1 << 20) - 1;
rl->layflag = 0x7FFF; /* solid ztra halo strand */
rl->passflag = SCE_PASS_COMBINED;
- re->r.actlay = 0;
+ re->active_view_layer = 0;
}
/* border render; calculate offset for use in compositor. compo is centralized coords */
@@ -992,7 +988,7 @@ void render_result_single_layer_begin(Render *re)
/* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */
void render_result_single_layer_end(Render *re)
{
- SceneRenderLayer *srl;
+ ViewLayer *view_layer;
RenderLayer *rlpush;
RenderLayer *rl;
int nr;
@@ -1013,12 +1009,12 @@ void render_result_single_layer_end(Render *re)
BLI_remlink(&re->result->layers, rl);
/* reconstruct render result layers */
- for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) {
- if (nr == re->r.actlay) {
+ for (nr = 0, view_layer = re->view_layers.first; view_layer; view_layer = view_layer->next, nr++) {
+ if (nr == re->active_view_layer) {
BLI_addtail(&re->result->layers, rl);
}
else {
- rlpush = RE_GetRenderLayer(re->pushedresult, srl->name);
+ rlpush = RE_GetRenderLayer(re->pushedresult, view_layer->name);
if (rlpush) {
BLI_remlink(&re->pushedresult->layers, rlpush);
BLI_addtail(&re->result->layers, rlpush);
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 77f399d08d1..c9072105dd9 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -246,7 +246,7 @@ static void halo_tile(RenderPart *pa, RenderLayer *rl)
intptr_t *rd= NULL;
int a, *rz, zz, y, sample, totsample, od;
short minx, maxx, miny, maxy, x;
- unsigned int lay= rl->lay;
+ unsigned int lay= (1 << 20) - 1;
/* we don't render halos in the cropped area, gives errors in flare counter */
if (pa->crop) {
@@ -1651,7 +1651,7 @@ void zbufshade_sss_tile(RenderPart *pa)
ssamp.tot= 1;
for (rl=rr->layers.first; rl; rl=rl->next) {
- ssamp.shi[0].lay |= rl->lay;
+ ssamp.shi[0].lay |= (1 << 20) - 1;
ssamp.shi[0].layflag |= rl->layflag;
ssamp.shi[0].passflag |= rl->passflag;
ssamp.shi[0].combinedflag |= ~rl->pass_xor;
@@ -1660,8 +1660,6 @@ void zbufshade_sss_tile(RenderPart *pa)
rl= rr->layers.first;
ssamp.shi[0].passflag |= SCE_PASS_RGBA|SCE_PASS_COMBINED;
ssamp.shi[0].combinedflag &= ~(SCE_PASS_SPEC);
- ssamp.shi[0].mat_override= NULL;
- ssamp.shi[0].light_override= NULL;
lay= ssamp.shi[0].lay;
/* create the pixelstrs to be used later */
@@ -1978,7 +1976,7 @@ void add_halo_flare(Render *re)
for (a=0; a<R.tothalo; a++) {
har= R.sortedhalos[a];
- if (har->flarec && (har->lay & rl->lay)) {
+ if (har->flarec && (har->lay & ((1 << 20) - 1))) {
do_draw = true;
renderflare(rr, rect, har);
}
@@ -1994,18 +1992,18 @@ void add_halo_flare(Render *re)
}
}
-void render_internal_update_passes(RenderEngine *engine, Scene *scene, SceneRenderLayer *srl)
+void render_internal_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)
{
int type;
- RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
+ RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
#define CHECK_PASS(name, channels, chanid) \
- if (srl->passflag & (SCE_PASS_ ## name)) { \
+ if (view_layer->passflag & (SCE_PASS_ ## name)) { \
if (channels == 4) type = SOCK_RGBA; \
else if (channels == 3) type = SOCK_VECTOR; \
else type = SOCK_FLOAT; \
- RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_ ## name, channels, chanid, type); \
+ RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_ ## name, channels, chanid, type); \
}
CHECK_PASS(Z, 1, "Z");
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index b4ff5f52fcf..6cad37c3e78 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -268,7 +268,7 @@ void shade_input_set_triangle_i(ShadeInput *shi, ObjectInstanceRen *obi, VlakRen
shi->i3 = i3;
/* note, shi->mat is set in node shaders */
- shi->mat = shi->mat_override ? shi->mat_override : vlr->mat;
+ shi->mat = vlr->mat;
shi->osatex = (shi->mat->texco & TEXCO_OSA);
shi->mode = shi->mat->mode_l; /* or-ed result for all nodes */
@@ -325,7 +325,7 @@ void shade_input_copy_triangle(ShadeInput *shi, ShadeInput *from)
void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spoint)
{
/* note, shi->mat is set in node shaders */
- shi->mat = shi->mat_override ? shi->mat_override : strand->buffer->ma;
+ shi->mat = strand->buffer->ma;
shi->osatex = (shi->mat->texco & TEXCO_OSA);
shi->mode = shi->mat->mode_l; /* or-ed result for all nodes */
@@ -438,7 +438,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
}
}
- if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE))) {
+ if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP))) {
MCol *mcol;
const float *uv;
char *name;
@@ -500,15 +500,6 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
suv->dyuv[0] = 0.0f;
suv->dyuv[1] = 0.0f;
}
-
- if ((mode & MA_FACETEXTURE) && i == obr->actmtface) {
- if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) {
- shi->vcol[0] = 1.0f;
- shi->vcol[1] = 1.0f;
- shi->vcol[2] = 1.0f;
- shi->vcol[3] = 1.0f;
- }
- }
}
if (shi->totuv == 0) {
@@ -517,14 +508,6 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
suv->uv[0] = 0.0f;
suv->uv[1] = spoint->strandco;
suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */
-
- if (mode & MA_FACETEXTURE) {
- /* no tface? set at 1.0f */
- shi->vcol[0] = 1.0f;
- shi->vcol[1] = 1.0f;
- shi->vcol[2] = 1.0f;
- shi->vcol[3] = 1.0f;
- }
}
}
@@ -566,7 +549,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
}
if (shi->do_manage) {
- if (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) {
+ if (mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) {
srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol);
}
}
@@ -1072,7 +1055,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
}
}
- if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) || (R.flag & R_NEED_VCOL)) {
+ if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) || (R.flag & R_NEED_VCOL)) {
VlakRen *vlr = shi->vlr;
MTFace *tface;
MCol *mcol;
@@ -1227,18 +1210,6 @@ void shade_input_set_shade_texco(ShadeInput *shi)
suv->dyuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]);
suv->dyuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]);
}
-
- if ((mode & MA_FACETEXTURE) && i == obr->actmtface) {
- if (((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) && ((R.flag & R_NEED_VCOL) == 0)) {
- shi->vcol[0] = 1.0f;
- shi->vcol[1] = 1.0f;
- shi->vcol[2] = 1.0f;
- shi->vcol[3] = 1.0f;
- }
- if (tface->tpage) {
- render_realtime_texture(shi, tface->tpage);
- }
- }
}
}
@@ -1252,14 +1223,6 @@ void shade_input_set_shade_texco(ShadeInput *shi)
suv->uv[0] = 2.0f * (u + .5f);
suv->uv[1] = 2.0f * (v + .5f);
suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */
-
- if (mode & MA_FACETEXTURE) {
- /* no tface? set at 1.0f */
- shi->vcol[0] = 1.0f;
- shi->vcol[1] = 1.0f;
- shi->vcol[2] = 1.0f;
- shi->vcol[3] = 1.0f;
- }
}
}
@@ -1315,7 +1278,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
* else un-initialized values are used
*/
if (shi->do_manage) {
- if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) || (R.flag & R_NEED_VCOL)) {
+ if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) || (R.flag & R_NEED_VCOL)) {
srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol);
}
}
@@ -1337,12 +1300,10 @@ void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, in
shi->do_manage = BKE_scene_check_color_management_enabled(R.scene);
shi->use_world_space_shading = BKE_scene_use_world_space_shading(R.scene);
- shi->lay = rl->lay;
+ shi->lay = (1 << 20) - 1;
shi->layflag = rl->layflag;
shi->passflag = rl->passflag;
shi->combinedflag = ~rl->pass_xor;
- shi->mat_override = rl->mat_override;
- shi->light_override = rl->light_override;
// shi->rl= rl;
/* note shi.depth==0 means first hit, not raytracing */
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index b10389538c2..c2d5c060530 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -71,8 +71,6 @@ ListBase *get_lights(ShadeInput *shi)
if (R.r.scemode & R_BUTS_PREVIEW)
return &R.lights;
- if (shi->light_override)
- return &shi->light_override->gobject;
if (shi->mat && shi->mat->group)
return &shi->mat->group->gobject;
@@ -897,14 +895,7 @@ void shade_color(ShadeInput *shi, ShadeResult *shr)
{
Material *ma= shi->mat;
- if (ma->mode & (MA_FACETEXTURE)) {
- shi->r= shi->vcol[0];
- shi->g= shi->vcol[1];
- shi->b= shi->vcol[2];
- if (ma->mode & (MA_FACETEXTURE_ALPHA))
- shi->alpha= shi->vcol[3];
- }
- else if (ma->mode & (MA_VERTEXCOLP)) {
+ if (ma->mode & (MA_VERTEXCOLP)) {
float neg_alpha = 1.0f - shi->vcol[3];
shi->r= shi->r*neg_alpha + shi->vcol[0]*shi->vcol[3];
shi->g= shi->g*neg_alpha + shi->vcol[1]*shi->vcol[3];
@@ -1762,12 +1753,8 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
/* material color itself */
if (passflag & color_passes) {
- if (ma->mode & (MA_FACETEXTURE)) {
- shi->r= shi->vcol[0];
- shi->g= shi->vcol[1];
- shi->b= shi->vcol[2];
- if (ma->mode & (MA_FACETEXTURE_ALPHA))
- shi->alpha= shi->vcol[3];
+ if (false) {
+ /* pass */
}
#ifdef WITH_FREESTYLE
else if (ma->vcol_alpha) {
@@ -2099,13 +2086,6 @@ float RE_lamp_get_data(ShadeInput *shi, Object *lamp_obj, float col[4], float lv
return 0.0f;
}
- if (shi->light_override) {
- for (go = shi->light_override->gobject.first; go; go = go->next) {
- if (go->ob == lamp_obj)
- return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
- }
- }
-
if (shi->mat && shi->mat->group) {
for (go = shi->mat->group->gobject.first; go; go = go->next) {
if (go->ob == lamp_obj)
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
index 7fe52328781..e12a7246254 100644
--- a/source/blender/render/intern/source/volumetric.c
+++ b/source/blender/render/intern/source/volumetric.c
@@ -172,8 +172,6 @@ static void shade_intersection(ShadeInput *shi, float col_r[4], Isect *is)
shi_new.lay = shi->lay;
shi_new.passflag = SCE_PASS_COMBINED; /* result of tracing needs no pass info */
shi_new.combinedflag = 0xFFFFFF; /* ray trace does all options */
- shi_new.light_override = shi->light_override;
- shi_new.mat_override = shi->mat_override;
copy_v3_v3(shi_new.camera_co, is->start);
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 1481e7a8059..f39936dc01f 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -2066,7 +2066,7 @@ void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart *
ObjectRen *obr;
float obwinmat[4][4], winmat[4][4], bounds[4];
float ho1[4], ho2[4], ho3[4], ho4[4]={0};
- unsigned int lay= rl->lay, lay_zmask= rl->lay_zmask;
+ unsigned int lay= (1 << 20) - 1, lay_zmask= 0;
int i, v, zvlnr, zsample, samples, c1, c2, c3, c4=0;
short nofill=0, env=0, wire=0, zmaskpass=0;
const bool all_z = (rl->layflag & SCE_LAY_ALL_Z) && !(rl->layflag & SCE_LAY_ZMASK);
@@ -3450,9 +3450,9 @@ static int zbuffer_abuf_render(RenderPart *pa, APixstr *APixbuf, APixstrand *APi
zbuf_make_winmat(&R, winmat);
if (rl->layflag & SCE_LAY_ZTRA)
- doztra+= zbuffer_abuf(&R, pa, APixbuf, apsmbase, rl->lay, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0);
+ doztra+= zbuffer_abuf(&R, pa, APixbuf, apsmbase, (1 << 20) - 1, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0);
if ((rl->layflag & SCE_LAY_STRAND) && APixbufstrand)
- doztra+= zbuffer_strands_abuf(&R, pa, APixbufstrand, apsmbase, rl->lay, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0, sscache);
+ doztra+= zbuffer_strands_abuf(&R, pa, APixbufstrand, apsmbase, (1 << 20) - 1, negzmask, winmat, R.winx, R.winy, samples, jit, R.clipcrop, 0, sscache);
return doztra;
}
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index a8b3c994d24..b5784fe543c 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -25,12 +25,15 @@
set(INC
.
+ manipulators
+ manipulators/intern
../blenfont
../blenkernel
../blenlib
../blenloader
../blentranslation
../compositor
+ ../depsgraph
../editors/include
../gpu
../imbuf
@@ -69,6 +72,16 @@ set(SRC
intern/wm_subwindow.c
intern/wm_window.c
intern/wm_stereo.c
+ intern/wm_toolsystem.c
+ manipulators/intern/wm_manipulator.c
+ manipulators/intern/wm_manipulator_group.c
+ manipulators/intern/wm_manipulator_group_type.c
+ manipulators/intern/wm_manipulator_map.c
+ manipulators/intern/wm_manipulator_target_props.c
+ manipulators/intern/wm_manipulator_type.c
+ message_bus/intern/wm_message_bus.c
+ message_bus/intern/wm_message_bus_rna.c
+ message_bus/intern/wm_message_bus_static.c
WM_api.h
WM_keymap.h
@@ -81,10 +94,17 @@ set(SRC
wm_files.h
wm_subwindow.h
wm_window.h
+ manipulators/WM_manipulator_api.h
+ manipulators/WM_manipulator_types.h
+ manipulators/wm_manipulator_fn.h
+ manipulators/wm_manipulator_wmapi.h
+ manipulators/intern/wm_manipulator_intern.h
+ message_bus/intern/wm_message_bus_intern.h
+ message_bus/wm_message_bus.h
)
if(WITH_AUDASPACE)
- add_definitions(${AUDASPACE_DEFINITIONS})
+ add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index e40026880c4..7671fbeb926 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -64,12 +64,18 @@ struct wmDrag;
struct ImBuf;
struct ImageFormatData;
struct ARegion;
+struct ScrArea;
+struct Main;
+struct bToolDef;
#ifdef WITH_INPUT_NDOF
struct wmNDOFMotionData;
#endif
typedef struct wmJob wmJob;
+typedef struct wmManipulator wmManipulator;
+typedef struct wmManipulatorMap wmManipulatorMap;
+typedef struct wmManipulatorMapType wmManipulatorMapType;
/* general API */
void WM_init_state_size_set (int stax, int stay, int sizx, int sizy);
@@ -94,6 +100,22 @@ int WM_window_pixels_x (struct wmWindow *win);
int WM_window_pixels_y (struct wmWindow *win);
bool WM_window_is_fullscreen (struct wmWindow *win);
+void WM_windows_scene_data_sync(const ListBase *win_lb, struct Scene *scene) ATTR_NONNULL();
+struct Scene *WM_windows_scene_get_from_screen(const struct wmWindowManager *wm, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+struct WorkSpace *WM_windows_workspace_get_from_screen(const wmWindowManager *wm, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+
+struct Scene *WM_window_get_active_scene(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+void WM_window_change_active_scene(struct Main *bmain, struct bContext *C, struct wmWindow *win,
+ struct Scene *scene_new) ATTR_NONNULL();
+struct WorkSpace *WM_window_get_active_workspace(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+void WM_window_set_active_workspace(struct wmWindow *win, struct WorkSpace *workspace) ATTR_NONNULL(1);
+struct WorkSpaceLayout *WM_window_get_active_layout(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+void WM_window_set_active_layout(
+ struct wmWindow *win, struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL(1);
+struct bScreen *WM_window_get_active_screen(const struct wmWindow *win) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+void WM_window_set_active_screen(struct wmWindow *win, struct WorkSpace *workspace, struct bScreen *screen) ATTR_NONNULL(1);
+bool WM_window_is_temp_screen(const struct wmWindow *win) ATTR_WARN_UNUSED_RESULT;
+
/* defines for 'type' WM_window_open_temp */
enum {
WM_WINDOW_RENDER = 1,
@@ -143,6 +165,7 @@ float WM_cursor_pressure (const struct wmWindow *win);
/* event map */
int WM_userdef_event_map(int kmitype);
+int WM_userdef_event_type_from_keymap_type(int kmitype);
/* handlers */
@@ -172,6 +195,9 @@ void WM_event_free_ui_handler_all(
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove);
struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op);
+void WM_event_modal_handler_area_replace(wmWindow *win, const struct ScrArea *old_area, struct ScrArea *new_area);
+void WM_event_modal_handler_region_replace(wmWindow *win, const struct ARegion *old_region, struct ARegion *new_region);
+
void WM_event_remove_handlers(struct bContext *C, ListBase *handlers);
/* handler flag */
@@ -230,6 +256,7 @@ void WM_operator_view3d_unit_defaults(struct bContext *C, struct wmOperator *op
int WM_operator_smooth_viewtx_get(const struct wmOperator *op);
int WM_menu_invoke_ex(struct bContext *C, struct wmOperator *op, int opcontext);
int WM_menu_invoke (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int WM_enum_search_invoke_previews(struct bContext *C, struct wmOperator *op, short prv_cols, short prv_rows);
int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
/* invoke callback, confirm menu + exec */
int WM_operator_confirm (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
@@ -267,6 +294,14 @@ void WM_operatortype_append_macro_ptr(void (*opfunc)(struct wmOperatorType *, v
void WM_operatortype_remove_ptr(struct wmOperatorType *ot);
bool WM_operatortype_remove(const char *idname);
void WM_operatortype_last_properties_clear_all(void);
+void WM_operatortype_props_advanced_begin(struct wmOperatorType *ot);
+void WM_operatortype_props_advanced_end(struct wmOperatorType *ot);
+
+#define WM_operatortype_prop_tag(property, tags) \
+ { \
+ CHECK_TYPE(tags, eOperatorPropTags); \
+ RNA_def_property_tags(prop, tags); \
+ } (void)0
struct wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *name, const char *description, int flag);
struct wmOperatorTypeMacro *WM_operatortype_macro_define(struct wmOperatorType *ot, const char *idname);
@@ -423,9 +458,7 @@ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid);
void wmSubWindowSet (struct wmWindow *win, int swinid);
void wmSubWindowScissorSet (struct wmWindow *win, int swinid, const struct rcti *srct, bool srct_pad);
- /* OpenGL utilities with safety check + working in modelview matrix mode */
-void wmFrustum (float x1, float x2, float y1, float y2, float n, float f);
-void wmOrtho (float x1, float x2, float y1, float y2, float n, float f);
+ /* OpenGL utilities with safety check */
void wmOrtho2 (float x1, float x2, float y1, float y2);
/* use for conventions (avoid hard-coded offsets all over) */
void wmOrtho2_region_pixelspace(const struct ARegion *ar);
@@ -531,6 +564,13 @@ bool WM_event_is_tablet(const struct wmEvent *event);
bool WM_event_is_ime_switch(const struct wmEvent *event);
#endif
+/* wm_toolsystem.c */
+void WM_toolsystem_unlink(struct bContext *C, struct WorkSpace *workspace);
+void WM_toolsystem_link(struct bContext *C, struct WorkSpace *workspace);
+
+void WM_toolsystem_set(struct bContext *C, const struct bToolDef *tool);
+void WM_toolsystem_init(struct bContext *C);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/windowmanager/WM_message.h b/source/blender/windowmanager/WM_message.h
new file mode 100644
index 00000000000..48197ae99cd
--- /dev/null
+++ b/source/blender/windowmanager/WM_message.h
@@ -0,0 +1,30 @@
+/*
+ * ***** 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/windowmanager/WM_message.h
+ * \ingroup wm
+ */
+
+#ifndef __WM_MESSAGE_H__
+#define __WM_MESSAGE_H__
+
+#include "message_bus/wm_message_bus.h"
+
+#endif /* __WM_MESSAGE_H__ */
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 6c47d61c535..9edae85cc3c 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -109,6 +109,7 @@ extern "C" {
struct bContext;
struct wmEvent;
struct wmWindowManager;
+struct wmMsgBus;
struct wmOperator;
struct ImBuf;
@@ -119,6 +120,10 @@ struct ImBuf;
/* exported types for WM */
#include "wm_cursors.h"
#include "wm_event_types.h"
+#include "manipulators/WM_manipulator_types.h"
+
+/* Include external manipulator API's */
+#include "manipulators/WM_manipulator_api.h"
/* ************** wmOperatorType ************************ */
@@ -160,6 +165,12 @@ enum {
WM_OP_EXEC_SCREEN
};
+/* property tags for RNA_OperatorProperties */
+typedef enum eOperatorPropTags {
+ OP_PROP_TAG_ADVANCED = (1 << 0),
+} eOperatorPropTags;
+#define OP_PROP_TAG_ADVANCED ((eOperatorPropTags)OP_PROP_TAG_ADVANCED)
+
/* ************** wmKeyMap ************************ */
/* modifier */
@@ -223,7 +234,7 @@ typedef struct wmNotifier {
#define NOTE_CATEGORY 0xFF000000
#define NC_WM (1<<24)
#define NC_WINDOW (2<<24)
-#define NC_SCREEN (3<<24)
+#define NC_SCREEN (3<<24)
#define NC_SCENE (4<<24)
#define NC_OBJECT (5<<24)
#define NC_MATERIAL (6<<24)
@@ -257,15 +268,16 @@ typedef struct wmNotifier {
#define ND_JOB (5<<16)
#define ND_UNDO (6<<16)
- /* NC_SCREEN screen */
-#define ND_SCREENBROWSE (1<<16)
-#define ND_SCREENDELETE (2<<16)
+ /* NC_SCREEN */
+#define ND_LAYOUTBROWSE (1<<16)
+#define ND_LAYOUTDELETE (2<<16)
#define ND_SCREENCAST (3<<16)
#define ND_ANIMPLAY (4<<16)
#define ND_GPENCIL (5<<16)
#define ND_EDITOR_CHANGED (6<<16) /*sent to new editors after switching to them*/
-#define ND_SCREENSET (7<<16)
+#define ND_LAYOUTSET (7<<16)
#define ND_SKETCH (8<<16)
+#define ND_WORKSPACE_SET (9<<16)
/* NC_SCENE Scene */
#define ND_SCENEBROWSE (1<<16)
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index a09cc4aeb31..623a7af5165 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -52,9 +52,11 @@
#include "BKE_screen.h"
#include "BKE_report.h"
#include "BKE_global.h"
+#include "BKE_workspace.h"
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "wm_window.h"
#include "wm_event_system.h"
#include "wm_draw.h"
@@ -353,7 +355,7 @@ void WM_keymap_init(bContext *C)
/* initialize only after python init is done, for keymaps that
* use python operators */
- if (CTX_py_init_get(C) && (wm->initialized & WM_INIT_KEYMAP) == 0) {
+ if (CTX_py_init_get(C) && (wm->initialized & WM_KEYMAP_IS_INITIALIZED) == 0) {
/* create default key config, only initialize once,
* it's persistent across sessions */
if (!(wm->defaultconf->flag & KEYCONF_INIT_DEFAULT)) {
@@ -366,7 +368,7 @@ void WM_keymap_init(bContext *C)
WM_keyconfig_update_tag(NULL, NULL);
WM_keyconfig_update(wm);
- wm->initialized |= WM_INIT_KEYMAP;
+ wm->initialized |= WM_KEYMAP_IS_INITIALIZED;
}
}
@@ -386,7 +388,7 @@ void WM_check(bContext *C)
if (!G.background) {
/* case: fileread */
- if ((wm->initialized & WM_INIT_WINDOW) == 0) {
+ if ((wm->initialized & WM_WINDOW_IS_INITIALIZED) == 0) {
WM_keymap_init(C);
WM_autosave_init(wm);
}
@@ -395,11 +397,15 @@ void WM_check(bContext *C)
wm_window_ghostwindows_ensure(wm);
}
+ if (wm->message_bus == NULL) {
+ wm->message_bus = WM_msgbus_create();
+ }
+
/* case: fileread */
/* note: this runs in bg mode to set the screen context cb */
- if ((wm->initialized & WM_INIT_WINDOW) == 0) {
+ if ((wm->initialized & WM_WINDOW_IS_INITIALIZED) == 0) {
ED_screens_initialize(wm);
- wm->initialized |= WM_INIT_WINDOW;
+ wm->initialized |= WM_WINDOW_IS_INITIALIZED;
}
}
@@ -428,21 +434,24 @@ void wm_clear_default_size(bContext *C)
}
/* on startup, it adds all data, for matching */
-void wm_add_default(bContext *C)
+void wm_add_default(Main *bmain, bContext *C)
{
- wmWindowManager *wm = BKE_libblock_alloc(CTX_data_main(C), ID_WM, "WinMan", 0);
+ wmWindowManager *wm = BKE_libblock_alloc(bmain, ID_WM, "WinMan", 0);
wmWindow *win;
bScreen *screen = CTX_wm_screen(C); /* XXX from file read hrmf */
-
+ WorkSpace *workspace;
+ WorkSpaceLayout *layout = BKE_workspace_layout_find_global(bmain, screen, &workspace);
+
CTX_wm_manager_set(C, wm);
win = wm_window_new(C);
- win->screen = screen;
+ win->scene = CTX_data_scene(C);
+ WM_window_set_active_workspace(win, workspace);
+ WM_window_set_active_layout(win, workspace, layout);
screen->winid = win->winid;
- BLI_strncpy(win->screenname, screen->id.name + 2, sizeof(win->screenname));
wm->winactive = win;
wm->file_saved = 1;
- wm_window_make_drawable(wm, win);
+ wm_window_make_drawable(wm, win);
}
@@ -457,7 +466,7 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
wm_autosave_timer_ended(wm);
while ((win = BLI_pophead(&wm->windows))) {
- win->screen = NULL; /* prevent draw clear to use screen */
+ WM_window_set_active_workspace(win, NULL); /* prevent draw clear to use screen */
wm_draw_window_clear(win);
wm_window_free(C, wm, win);
}
@@ -471,7 +480,11 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
}
BLI_freelistN(&wm->queue);
-
+
+ if (wm->message_bus != NULL) {
+ WM_msgbus_destroy(wm->message_bus);
+ }
+
BLI_freelistN(&wm->paintcursors);
WM_drag_free_list(&wm->drags);
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index dd01efdb4c4..05d9689565c 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -46,6 +46,8 @@
#include "BKE_context.h"
+#include "GPU_shader.h"
+
#include "IMB_imbuf_types.h"
#include "UI_interface.h"
@@ -268,10 +270,10 @@ void wm_drags_check_ops(bContext *C, const wmEvent *event)
static void wm_drop_operator_draw(const char *name, int x, int y)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- const unsigned char fg[4] = {255, 255, 255, 255};
- const unsigned char bg[4] = {0, 0, 0, 50};
+ const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f};
- UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, fg, bg);
+ UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg);
}
static const char *wm_drag_name(wmDrag *drag)
@@ -332,8 +334,10 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
if (rect)
drag_rect_minmax(rect, x, y, x + drag->sx, y + drag->sy);
else {
- glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */
- glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, drag->imb->rect, drag->scale, drag->scale);
+ float col[4] = {1.0f, 1.0f, 1.0f, 0.65f}; /* this blends texture */
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTexScaled(&state, x, y, drag->imb->x, drag->imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST,
+ drag->imb->rect, drag->scale, drag->scale, 1.0f, 1.0f, col);
}
}
else {
@@ -361,8 +365,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_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index f802e873555..c6b25ff8079 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -34,6 +34,8 @@
#include <string.h>
#include "DNA_listBase.h"
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_userdef_types.h"
@@ -57,8 +59,8 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
-#include "GPU_glew.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_viewport.h"
#include "RE_engine.h"
@@ -88,7 +90,7 @@ static void wm_paintcursor_draw(bContext *C, ARegion *ar)
if (wm->paintcursors.first) {
wmWindow *win = CTX_wm_window(C);
- bScreen *screen = win->screen;
+ bScreen *screen = WM_window_get_active_screen(win);
wmPaintCursor *pc;
if (ar->swinid && screen->subwinactive == ar->swinid) {
@@ -128,18 +130,18 @@ static bool wm_area_test_invalid_backbuf(ScrArea *sa)
if (sa->spacetype == SPACE_VIEW3D)
return (((View3D *)sa->spacedata.first)->flag & V3D_INVALID_BACKBUF) != 0;
else
- return 1;
+ return true;
}
-static void wm_region_test_render_do_draw(bScreen *screen, ScrArea *sa, ARegion *ar)
+static void wm_region_test_render_do_draw(const Scene *scene, ScrArea *sa, ARegion *ar)
{
/* tag region for redraw from render engine preview running inside of it */
if (sa->spacetype == SPACE_VIEW3D) {
RegionView3D *rv3d = ar->regiondata;
RenderEngine *engine = (rv3d) ? rv3d->render_engine : NULL;
+ GPUViewport *viewport = (rv3d) ? rv3d->viewport : NULL;
if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) {
- Scene *scene = screen->scene;
View3D *v3d = sa->spacedata.first;
rcti border_rect;
@@ -151,6 +153,9 @@ static void wm_region_test_render_do_draw(bScreen *screen, ScrArea *sa, ARegion
engine->flag &= ~RE_ENGINE_DO_DRAW;
}
+ else if (viewport && GPU_viewport_do_update(viewport)) {
+ ED_region_tag_redraw(ar);
+ }
}
}
@@ -159,7 +164,7 @@ static void wm_region_test_render_do_draw(bScreen *screen, ScrArea *sa, ARegion
static void wm_method_draw_full(bContext *C, wmWindow *win)
{
- bScreen *screen = win->screen;
+ bScreen *screen = WM_window_get_active_screen(win);
ScrArea *sa;
ARegion *ar;
@@ -182,7 +187,7 @@ static void wm_method_draw_full(bContext *C, wmWindow *win)
}
ED_screen_draw(win);
- win->screen->do_draw = false;
+ screen->do_draw = false;
/* draw overlapping regions */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
@@ -238,7 +243,7 @@ static void wm_flush_regions_up(bScreen *screen, rcti *dirty)
static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
{
wmWindowManager *wm = CTX_wm_manager(C);
- bScreen *screen = win->screen;
+ bScreen *screen = WM_window_get_active_screen(win);
ScrArea *sa;
ARegion *ar;
static rcti rect = {0, 0, 0, 0};
@@ -319,7 +324,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
/* after area regions so we can do area 'overlay' drawing */
if (screen->do_draw) {
ED_screen_draw(win);
- win->screen->do_draw = false;
+ screen->do_draw = false;
if (exchange)
screen->swap = WIN_FRONT_OK;
@@ -327,7 +332,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
else if (exchange) {
if (screen->swap == WIN_FRONT_OK) {
ED_screen_draw(win);
- win->screen->do_draw = false;
+ screen->do_draw = false;
screen->swap = WIN_BOTH_OK;
}
else if (screen->swap == WIN_BACK_OK)
@@ -372,118 +377,116 @@ static void wm_draw_triple_fail(bContext *C, wmWindow *win)
{
wm_draw_window_clear(win);
- win->drawfail = 1;
+ win->drawfail = true;
wm_method_draw_overlap_all(C, win, 0);
}
-static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
+static bool wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
{
- const int winsize_x = WM_window_pixels_x(win);
- const int winsize_y = WM_window_pixels_y(win);
-
- GLint maxsize;
-
/* compute texture sizes */
- if (GLEW_ARB_texture_rectangle || GLEW_NV_texture_rectangle || GLEW_EXT_texture_rectangle) {
- triple->target = GL_TEXTURE_RECTANGLE_ARB;
- }
- else {
- triple->target = GL_TEXTURE_2D;
- }
-
- triple->x = winsize_x;
- triple->y = winsize_y;
+ triple->x = WM_window_pixels_x(win);
+ triple->y = WM_window_pixels_y(win);
+
+#if USE_TEXTURE_RECTANGLE
+ /* GL_TEXTURE_RECTANGLE is part of GL 3.1 so we can use it soon without runtime checks */
+ triple->target = GL_TEXTURE_RECTANGLE;
+#else
+ triple->target = GL_TEXTURE_2D;
+#endif
/* generate texture names */
glGenTextures(1, &triple->bind);
- if (!triple->bind) {
- /* not the typical failure case but we handle it anyway */
- printf("WM: failed to allocate texture for triple buffer drawing (glGenTextures).\n");
- return 0;
- }
-
/* proxy texture is only guaranteed to test for the cases that
* there is only one texture in use, which may not be the case */
- maxsize = GPU_max_texture_size();
+ const GLint maxsize = GPU_max_texture_size();
if (triple->x > maxsize || triple->y > maxsize) {
- glBindTexture(triple->target, 0);
printf("WM: failed to allocate texture for triple buffer drawing "
- "(texture too large for graphics card).\n");
- return 0;
+ "(texture too large for graphics card).\n");
+ return false;
}
/* setup actual texture */
glBindTexture(triple->target, triple->bind);
- glTexImage2D(triple->target, 0, GL_RGB8, triple->x, triple->y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+
+ /* no mipmaps */
+#if USE_TEXTURE_RECTANGLE
+ /* already has no mipmaps */
+#else
+ glTexParameteri(triple->target, GL_TEXTURE_MAX_LEVEL, 0);
+ /* GL_TEXTURE_BASE_LEVEL = 0 by default */
+#endif
+
glTexParameteri(triple->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(triple->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glBindTexture(triple->target, 0);
- /* not sure if this works everywhere .. */
- if (glGetError() == GL_OUT_OF_MEMORY) {
- printf("WM: failed to allocate texture for triple buffer drawing (out of memory).\n");
- return 0;
- }
+ glTexImage2D(triple->target, 0, GL_RGB8, triple->x, triple->y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
- return 1;
+ glBindTexture(triple->target, 0);
+
+ return true;
}
-void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha, bool is_interlace)
+void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
{
const int sizex = WM_window_pixels_x(win);
const int sizey = WM_window_pixels_y(win);
- float halfx, halfy, ratiox, ratioy;
-
/* wmOrtho for the screen has this same offset */
- ratiox = sizex;
- ratioy = sizey;
- halfx = GLA_PIXEL_OFS;
- halfy = GLA_PIXEL_OFS;
+ float ratiox = sizex;
+ float ratioy = sizey;
+ float halfx = GLA_PIXEL_OFS;
+ float halfy = GLA_PIXEL_OFS;
+#if USE_TEXTURE_RECTANGLE
/* texture rectangle has unnormalized coordinates */
- if (triple->target == GL_TEXTURE_2D) {
- ratiox /= triple->x;
- ratioy /= triple->y;
- halfx /= triple->x;
- halfy /= triple->y;
- }
+#else
+ ratiox /= triple->x;
+ ratioy /= triple->y;
+ halfx /= triple->x;
+ halfy /= triple->y;
+#endif
- /* interlace stereo buffer bind the shader before calling wm_triple_draw_textures */
- if (is_interlace) {
- glEnable(triple->target);
- }
- else {
- GPU_basic_shader_bind((triple->target == GL_TEXTURE_2D) ? GPU_SHADER_TEXTURE_2D : GPU_SHADER_TEXTURE_RECT);
- }
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ const int activeTex = 7; /* arbitrary */
+ glActiveTexture(GL_TEXTURE0 + activeTex);
glBindTexture(triple->target, triple->bind);
- glColor4f(1.0f, 1.0f, 1.0f, alpha);
- glBegin(GL_QUADS);
- glTexCoord2f(halfx, halfy);
- glVertex2f(0, 0);
+#if USE_TEXTURE_RECTANGLE
+ immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA);
+#else
+ immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
+ /* TODO: make pure 2D version
+ * and a 2D_IMAGE (replace, not modulate) version for when alpha = 1.0
+ */
+#endif
+ immUniform1f("alpha", alpha);
+ immUniform1i("image", activeTex);
- glTexCoord2f(ratiox + halfx, halfy);
- glVertex2f(sizex, 0);
+ immBegin(GWN_PRIM_TRI_FAN, 4);
- glTexCoord2f(ratiox + halfx, ratioy + halfy);
- glVertex2f(sizex, sizey);
+ immAttrib2f(texcoord, halfx, halfy);
+ immVertex2f(pos, 0.0f, 0.0f);
- glTexCoord2f(halfx, ratioy + halfy);
- glVertex2f(0, sizey);
- glEnd();
+ immAttrib2f(texcoord, ratiox + halfx, halfy);
+ immVertex2f(pos, sizex, 0.0f);
- glBindTexture(triple->target, 0);
+ immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy);
+ immVertex2f(pos, sizex, sizey);
- if (is_interlace) {
- glDisable(triple->target);
- }
- else {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- }
+ immAttrib2f(texcoord, halfx, ratioy + halfy);
+ immVertex2f(pos, 0.0f, sizey);
+
+ immEnd();
+ immUnbindProgram();
+
+ glBindTexture(triple->target, 0);
+ if (activeTex != 0)
+ glActiveTexture(GL_TEXTURE0);
}
static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
@@ -492,8 +495,8 @@ static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
const int sizey = WM_window_pixels_y(win);
glBindTexture(triple->target, triple->bind);
+ /* what is GL_READ_BUFFER right now? */
glCopyTexSubImage2D(triple->target, 0, 0, 0, 0, 0, sizex, sizey);
-
glBindTexture(triple->target, 0);
}
@@ -503,10 +506,12 @@ static void wm_draw_region_blend(wmWindow *win, ARegion *ar, wmDrawTriple *tripl
/* region blend always is 1, except when blend timer is running */
if (fac < 1.0f) {
- wmSubWindowScissorSet(win, win->screen->mainwin, &ar->winrct, true);
+ bScreen *screen = WM_window_get_active_screen(win);
+
+ wmSubWindowScissorSet(win, screen->mainwin, &ar->winrct, true);
glEnable(GL_BLEND);
- wm_triple_draw_textures(win, triple, 1.0f - fac, false);
+ wm_triple_draw_textures(win, triple, 1.0f - fac);
glDisable(GL_BLEND);
}
}
@@ -514,20 +519,21 @@ static void wm_draw_region_blend(wmWindow *win, ARegion *ar, wmDrawTriple *tripl
static void wm_method_draw_triple(bContext *C, wmWindow *win)
{
wmWindowManager *wm = CTX_wm_manager(C);
- wmDrawTriple *triple;
wmDrawData *dd, *dd_next, *drawdata = win->drawdata.first;
- bScreen *screen = win->screen;
+ bScreen *screen = WM_window_get_active_screen(win);
ScrArea *sa;
ARegion *ar;
- int copytex = false;
+ bool copytex = false;
if (drawdata && drawdata->triple) {
- glClearColor(0, 0, 0, 0);
+#if 0 /* why do we need to clear before overwriting? */
+ glClearColor(1, 1, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#endif
wmSubWindowSet(win, screen->mainwin);
- wm_triple_draw_textures(win, drawdata->triple, 1.0f, false);
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
}
else {
/* we run it when we start OR when we turn stereo on */
@@ -554,7 +560,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
MEM_freeN(dd);
}
- triple = drawdata->triple;
+ wmDrawTriple *triple = drawdata->triple;
/* draw marked area regions */
for (sa = screen->areabase.first; sa; sa = sa->next) {
@@ -562,7 +568,6 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->swinid && ar->do_draw) {
-
if (ar->overlap == false) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
@@ -623,7 +628,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
/* after area regions so we can do area 'overlay' drawing */
ED_screen_draw(win);
- win->screen->do_draw = false;
+ WM_window_get_active_screen(win)->do_draw = false;
/* draw floating regions (menus) */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
@@ -650,7 +655,7 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
wmWindowManager *wm = CTX_wm_manager(C);
wmDrawData *drawdata;
wmDrawTriple *triple_data, *triple_all;
- bScreen *screen = win->screen;
+ bScreen *screen = WM_window_get_active_screen(win);
ScrArea *sa;
ARegion *ar;
int copytex = false;
@@ -662,12 +667,14 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
if (drawdata && drawdata->triple) {
if (id == 0) {
+#if 0 /* why do we need to clear before overwriting? */
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#endif
wmSubWindowSet(win, screen->mainwin);
- wm_triple_draw_textures(win, drawdata->triple, 1.0f, false);
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
}
}
else {
@@ -703,9 +710,12 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
case SPACE_VIEW3D:
{
View3D *v3d = sa->spacedata.first;
- BGpic *bgpic = v3d->bgpicbase.first;
- v3d->multiview_eye = sview;
- if (bgpic) bgpic->iuser.multiview_eye = sview;
+ if (v3d->camera && v3d->camera->type == OB_CAMERA) {
+ Camera *cam = v3d->camera->data;
+ CameraBGImage *bgpic = cam->bg_images.first;
+ v3d->multiview_eye = sview;
+ if (bgpic) bgpic->iuser.multiview_eye = sview;
+ }
break;
}
case SPACE_NODE:
@@ -794,7 +804,7 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
/* after area regions so we can do area 'overlay' drawing */
ED_screen_draw(win);
if (sview == STEREO_RIGHT_ID)
- win->screen->do_draw = false;
+ screen->do_draw = false;
/* draw floating regions (menus) */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
@@ -826,11 +836,13 @@ static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoV
/* quick test to prevent changing window drawable */
static bool wm_draw_update_test_window(wmWindow *win)
{
+ const Scene *scene = WM_window_get_active_scene(win);
+ const bScreen *screen = WM_window_get_active_screen(win);
ScrArea *sa;
ARegion *ar;
bool do_draw = false;
- for (ar = win->screen->regionbase.first; ar; ar = ar->next) {
+ for (ar = screen->regionbase.first; ar; ar = ar->next) {
if (ar->do_draw_overlay) {
wm_tag_redraw_overlay(win, ar);
ar->do_draw_overlay = false;
@@ -839,9 +851,9 @@ static bool wm_draw_update_test_window(wmWindow *win)
do_draw = true;
}
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- wm_region_test_render_do_draw(win->screen, sa, ar);
+ wm_region_test_render_do_draw(scene, sa, ar);
if (ar->swinid && ar->do_draw)
do_draw = true;
@@ -849,20 +861,20 @@ static bool wm_draw_update_test_window(wmWindow *win)
}
if (do_draw)
- return 1;
+ return true;
- if (win->screen->do_refresh)
- return 1;
- if (win->screen->do_draw)
- return 1;
- if (win->screen->do_draw_gesture)
- return 1;
- if (win->screen->do_draw_paintcursor)
- return 1;
- if (win->screen->do_draw_drag)
- return 1;
+ if (screen->do_refresh)
+ return true;
+ if (screen->do_draw)
+ return true;
+ if (screen->do_draw_gesture)
+ return true;
+ if (screen->do_draw_paintcursor)
+ return true;
+ if (screen->do_draw_drag)
+ return true;
- return 0;
+ return false;
}
static int wm_automatic_draw_method(wmWindow *win)
@@ -888,15 +900,18 @@ void wm_tag_redraw_overlay(wmWindow *win, ARegion *ar)
{
/* for draw triple gestures, paint cursors don't need region redraw */
if (ar && win) {
+ bScreen *screen = WM_window_get_active_screen(win);
+
if (wm_automatic_draw_method(win) != USER_DRAW_TRIPLE)
ED_region_tag_redraw(ar);
- win->screen->do_draw_paintcursor = true;
+ screen->do_draw_paintcursor = true;
}
}
void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *ar)
{
- win->screen->do_draw_paintcursor = true;
+ bScreen *screen = WM_window_get_active_screen(win);
+ screen->do_draw_paintcursor = true;
wm_tag_redraw_overlay(win, ar);
}
@@ -904,7 +919,6 @@ void wm_draw_update(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win;
- int drawmethod;
#ifdef WITH_OPENSUBDIV
BKE_subsurf_free_unused_buffers();
@@ -930,16 +944,18 @@ void wm_draw_update(bContext *C)
}
if (wm_draw_update_test_window(win)) {
+ bScreen *screen = WM_window_get_active_screen(win);
+
CTX_wm_window_set(C, win);
/* sets context window+screen */
wm_window_make_drawable(wm, win);
/* notifiers for screen redraw */
- if (win->screen->do_refresh)
+ if (screen->do_refresh)
ED_screen_refresh(wm, win);
- drawmethod = wm_automatic_draw_method(win);
+ int drawmethod = wm_automatic_draw_method(win);
if (win->drawfail)
wm_method_draw_overlap_all(C, win, 0);
@@ -960,9 +976,9 @@ void wm_draw_update(bContext *C)
}
}
- win->screen->do_draw_gesture = false;
- win->screen->do_draw_paintcursor = false;
- win->screen->do_draw_drag = false;
+ screen->do_draw_gesture = false;
+ screen->do_draw_paintcursor = false;
+ screen->do_draw_drag = false;
wm_window_swap_buffers(win);
@@ -983,7 +999,7 @@ void wm_draw_data_free(wmWindow *win)
void wm_draw_window_clear(wmWindow *win)
{
- bScreen *screen = win->screen;
+ bScreen *screen = WM_window_get_active_screen(win);
ScrArea *sa;
ARegion *ar;
@@ -1001,12 +1017,13 @@ void wm_draw_window_clear(wmWindow *win)
void wm_draw_region_clear(wmWindow *win, ARegion *ar)
{
+ bScreen *screen = WM_window_get_active_screen(win);
int drawmethod = wm_automatic_draw_method(win);
if (ELEM(drawmethod, USER_DRAW_OVERLAP, USER_DRAW_OVERLAP_FLIP))
- wm_flush_regions_down(win->screen, &ar->winrct);
+ wm_flush_regions_down(screen, &ar->winrct);
- win->screen->do_draw = true;
+ screen->do_draw = true;
}
void WM_redraw_windows(bContext *C)
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index a71202bfa71..b1ec1c009df 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -53,10 +53,12 @@
#include "BKE_context.h"
#include "BKE_idprop.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
#include "BKE_sound.h"
@@ -68,14 +70,13 @@
#include "RNA_access.h"
-#include "GPU_debug.h"
-
#include "UI_interface.h"
#include "PIL_time.h"
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "wm.h"
#include "wm_window.h"
#include "wm_event_system.h"
@@ -83,6 +84,8 @@
#include "RNA_enum_types.h"
+#include "DEG_depsgraph.h"
+
/* Motion in pixels allowed before we don't consider single/double click. */
#define WM_EVENT_CLICK_WIGGLE_ROOM 2
@@ -239,6 +242,14 @@ void WM_main_remove_notifier_reference(const void *reference)
wm_notifier_clear(note);
}
}
+
+ /* Remap instead. */
+#if 0
+ if (wm->message_bus) {
+ WM_msg_id_remove(wm->message_bus, reference);
+ }
+#endif
+
}
}
@@ -258,6 +269,17 @@ void WM_main_remap_editor_id_reference(ID *old_id, ID *new_id)
}
}
}
+
+ wmWindowManager *wm = bmain->wm.first;
+ if (wm && wm->message_bus) {
+ struct wmMsgBus *mbus = wm->message_bus;
+ if (new_id != NULL) {
+ WM_msg_id_update(mbus, old_id, new_id);
+ }
+ else {
+ WM_msg_id_remove(mbus, old_id);
+ }
+ }
}
static void wm_notifier_clear(wmNotifier *note)
@@ -277,15 +299,20 @@ void wm_event_do_refresh_wm_and_depsgraph(bContext *C)
/* combine datamasks so 1 win doesn't disable UV's in another [#26448] */
for (wmWindow *win = wm->windows.first; win; win = win->next) {
- win_combine_v3d_datamask |= ED_view3d_screen_datamask(win->screen);
+ const Scene *scene = WM_window_get_active_scene(win);
+ const bScreen *screen = WM_window_get_active_screen(win);
+
+ win_combine_v3d_datamask |= ED_view3d_screen_datamask(scene, screen);
}
/* cached: editor refresh callbacks now, they get context */
for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ const bScreen *screen = WM_window_get_active_screen(win);
+ Scene *scene = WM_window_get_active_scene(win);
ScrArea *sa;
CTX_wm_window_set(C, win);
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
if (sa->do_refresh) {
CTX_wm_area_set(C, sa);
ED_area_do_refresh(C, sa);
@@ -298,12 +325,13 @@ void wm_event_do_refresh_wm_and_depsgraph(bContext *C)
Main *bmain = CTX_data_main(C);
/* copied to set's in scene_update_tagged_recursive() */
- win->screen->scene->customdata_mask = win_combine_v3d_datamask;
+ scene->customdata_mask = win_combine_v3d_datamask;
/* XXX, hack so operators can enforce datamasks [#26482], gl render */
- win->screen->scene->customdata_mask |= win->screen->scene->customdata_mask_modal;
+ scene->customdata_mask |= scene->customdata_mask_modal;
- BKE_scene_update_tagged(bmain->eval_ctx, bmain, win->screen->scene);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ BKE_workspace_update_tagged(bmain->eval_ctx, bmain, workspace, scene);
}
}
@@ -319,9 +347,12 @@ void wm_event_do_notifiers(bContext *C)
if (wm == NULL)
return;
-
+
+ /* disable? - keep for now since its used for window level notifiers. */
+#if 1
/* cache & catch WM level notifiers, such as frame change, scene/screen set */
for (win = wm->windows.first; win; win = win->next) {
+ Scene *scene = WM_window_get_active_scene(win);
bool do_anim = false;
CTX_wm_window_set(C, win);
@@ -339,17 +370,31 @@ void wm_event_do_notifiers(bContext *C)
}
if (note->window == win) {
if (note->category == NC_SCREEN) {
- if (note->data == ND_SCREENBROWSE) {
+ if (note->data == ND_WORKSPACE_SET) {
+ WorkSpace *ref_ws = note->reference;
+
+ UI_popup_handlers_remove_all(C, &win->modalhandlers);
+
+ ED_workspace_change(ref_ws, C, wm, win);
+ if (G.debug & G_DEBUG_EVENTS)
+ printf("%s: Workspace set %p\n", __func__, note->reference);
+ }
+ else if (note->data == ND_LAYOUTBROWSE) {
+ bScreen *ref_screen = BKE_workspace_layout_screen_get(note->reference);
+
/* free popup handlers only [#35434] */
UI_popup_handlers_remove_all(C, &win->modalhandlers);
- ED_screen_set(C, note->reference); // XXX hrms, think this over!
+ ED_screen_change(C, ref_screen); /* XXX hrms, think this over! */
if (G.debug & G_DEBUG_EVENTS)
printf("%s: screen set %p\n", __func__, note->reference);
}
- else if (note->data == ND_SCREENDELETE) {
- ED_screen_delete(C, note->reference); // XXX hrms, think this over!
+ else if (note->data == ND_LAYOUTDELETE) {
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ WorkSpaceLayout *layout = note->reference;
+
+ ED_workspace_layout_delete(workspace, layout, C); // XXX hrms, think this over!
if (G.debug & G_DEBUG_EVENTS)
printf("%s: screen delete %p\n", __func__, note->reference);
}
@@ -357,7 +402,7 @@ void wm_event_do_notifiers(bContext *C)
}
if (note->window == win ||
- (note->window == NULL && (note->reference == NULL || note->reference == win->screen->scene)))
+ (note->window == NULL && (note->reference == NULL || note->reference == scene)))
{
if (note->category == NC_SCENE) {
if (note->data == ND_FRAME)
@@ -365,19 +410,21 @@ void wm_event_do_notifiers(bContext *C)
}
}
if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_WM)) {
- ED_info_stats_clear(win->screen->scene);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ ED_info_stats_clear(view_layer);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
}
}
if (do_anim) {
/* XXX, quick frame changes can cause a crash if framechange and rendering
- * collide (happens on slow scenes), BKE_scene_update_for_newframe can be called
+ * collide (happens on slow scenes), BKE_scene_graph_update_for_newframe can be called
* twice which can depgraph update the same object at once */
if (G.is_rendering == false) {
-
/* depsgraph gets called, might send more notifiers */
- ED_update_for_newframe(CTX_data_main(C), win->screen->scene, 1);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_update_for_newframe(CTX_data_main(C), scene, view_layer, depsgraph);
}
}
}
@@ -385,12 +432,20 @@ void wm_event_do_notifiers(bContext *C)
/* the notifiers are sent without context, to keep it clean */
while ((note = BLI_pophead(&wm->queue))) {
for (win = wm->windows.first; win; win = win->next) {
-
+ Scene *scene = WM_window_get_active_scene(win);
+ bScreen *screen = WM_window_get_active_screen(win);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+
/* filter out notifiers */
- if (note->category == NC_SCREEN && note->reference && note->reference != win->screen) {
+ if (note->category == NC_SCREEN &&
+ note->reference &&
+ note->reference != screen &&
+ note->reference != workspace &&
+ note->reference != WM_window_get_active_layout(win))
+ {
/* pass */
}
- else if (note->category == NC_SCENE && note->reference && note->reference != win->screen->scene) {
+ else if (note->category == NC_SCENE && note->reference && note->reference != scene) {
/* pass */
}
else {
@@ -403,14 +458,14 @@ void wm_event_do_notifiers(bContext *C)
/* printf("notifier win %d screen %s cat %x\n", win->winid, win->screen->id.name + 2, note->category); */
ED_screen_do_listen(C, note);
- for (ar = win->screen->regionbase.first; ar; ar = ar->next) {
- ED_region_do_listen(win->screen, NULL, ar, note);
+ for (ar = screen->regionbase.first; ar; ar = ar->next) {
+ ED_region_do_listen(screen, NULL, ar, note, scene);
}
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- ED_area_do_listen(win->screen, sa, note);
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ ED_area_do_listen(screen, sa, note, scene, workspace);
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- ED_region_do_listen(win->screen, sa, ar, note);
+ ED_region_do_listen(screen, sa, ar, note, scene);
}
}
}
@@ -418,7 +473,17 @@ void wm_event_do_notifiers(bContext *C)
MEM_freeN(note);
}
-
+#endif /* if 1 (postpone disabling for in favor of message-bus), eventually. */
+
+ /* Handle message bus. */
+ {
+ for (win = wm->windows.first; win; win = win->next) {
+ CTX_wm_window_set(C, win);
+ WM_msgbus_handle(wm->message_bus, C);
+ }
+ CTX_wm_window_set(C, NULL);
+ }
+
wm_event_do_refresh_wm_and_depsgraph(C);
}
@@ -1571,6 +1636,36 @@ int WM_userdef_event_map(int kmitype)
return kmitype;
}
+/**
+ * Use so we can check if 'wmEvent.type' is released in modal operators.
+ *
+ * An alternative would be to add a 'wmEvent.type_nokeymap'... or similar.
+ */
+int WM_userdef_event_type_from_keymap_type(int kmitype)
+{
+ switch (kmitype) {
+ case SELECTMOUSE:
+ return (U.flag & USER_LMOUSESELECT) ? LEFTMOUSE : RIGHTMOUSE;
+ case ACTIONMOUSE:
+ return (U.flag & USER_LMOUSESELECT) ? RIGHTMOUSE : LEFTMOUSE;
+ case EVT_TWEAK_S:
+ return (U.flag & USER_LMOUSESELECT) ? LEFTMOUSE : RIGHTMOUSE;
+ case EVT_TWEAK_A:
+ return (U.flag & USER_LMOUSESELECT) ? RIGHTMOUSE : LEFTMOUSE;
+ case EVT_TWEAK_L:
+ return LEFTMOUSE;
+ case EVT_TWEAK_M:
+ return MIDDLEMOUSE;
+ case EVT_TWEAK_R:
+ return RIGHTMOUSE;
+ case WHEELOUTMOUSE:
+ return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELUPMOUSE : WHEELDOWNMOUSE;
+ case WHEELINMOUSE:
+ return (U.uiflag & USER_WHEELZOOMDIR) ? WHEELDOWNMOUSE : WHEELUPMOUSE;
+ }
+
+ return kmitype;
+}
static int wm_eventmatch(const wmEvent *winevent, wmKeyMapItem *kmi)
{
@@ -1719,7 +1814,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
wm_handler_op_context(C, handler, event);
wm_region_mouse_co(C, event);
wm_event_modalkeymap(C, op, event, &dbl_click_disabled);
-
+
if (ot->flag & OPTYPE_UNDO)
wm->op_undo_depth++;
@@ -1768,6 +1863,9 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
CTX_wm_region_set(C, NULL);
}
+ /* update manipulators during modal handlers */
+ wm_manipulatormaps_handled_modal_update(C, event, handler);
+
/* remove modal handler, operator itself should have been canceled and freed */
if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) {
WM_cursor_grab_disable(CTX_wm_window(C), NULL);
@@ -2140,6 +2238,137 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
}
}
}
+ else if (handler->manipulator_map) {
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ wmManipulatorMap *mmap = handler->manipulator_map;
+ wmManipulator *mpr = wm_manipulatormap_highlight_get(mmap);
+
+ if (region->manipulator_map != handler->manipulator_map) {
+ WM_manipulatormap_tag_refresh(handler->manipulator_map);
+ }
+
+ wm_manipulatormap_handler_context(C, handler);
+ wm_region_mouse_co(C, event);
+
+ /* handle manipulator highlighting */
+ if (event->type == MOUSEMOVE && !wm_manipulatormap_modal_get(mmap)) {
+ int part;
+ mpr = wm_manipulatormap_highlight_find(mmap, C, event, &part);
+ wm_manipulatormap_highlight_set(mmap, C, mpr, part);
+ }
+ /* handle user configurable manipulator-map keymap */
+ else {
+ /* Either we operate on a single highlighted item
+ * or groups attached to the selected manipulators.
+ * To simplify things both cases loop over an array of items. */
+ wmManipulatorGroup *mgroup_first;
+ bool is_mgroup_single;
+
+ if (ISMOUSE(event->type)) {
+ /* Keep mpr set as-is, just fake single selection. */
+ if (mpr) {
+ mgroup_first = mpr->parent_mgroup;
+ }
+ else {
+ mgroup_first = NULL;
+ }
+ is_mgroup_single = true;
+ }
+ else {
+ if (WM_manipulatormap_is_any_selected(mmap)) {
+ const ListBase *groups = WM_manipulatormap_group_list(mmap);
+ mgroup_first = groups->first;
+ }
+ else {
+ mgroup_first = NULL;
+ }
+ is_mgroup_single = false;
+ }
+
+ /* Don't use from now on. */
+ mpr = NULL;
+
+ for (wmManipulatorGroup *mgroup = mgroup_first; mgroup; mgroup = mgroup->next) {
+ /* get user customized keymap from default one */
+
+ if ((is_mgroup_single == false) &&
+ /* We might want to change the logic here and use some kind of manipulator edit-mode.
+ * For now just use keymap when a selection exists. */
+ wm_manipulatorgroup_is_any_selected(mgroup) == false)
+ {
+ continue;
+ }
+
+ const wmKeyMap *keymap = WM_keymap_active(wm, mgroup->type->keymap);
+ wmKeyMapItem *kmi;
+
+ PRINT("%s: checking '%s' ...", __func__, keymap->idname);
+
+ if (!keymap->poll || keymap->poll(C)) {
+ PRINT("pass\n");
+ for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ if (wm_eventmatch(event, kmi)) {
+ wmOperator *op = handler->op;
+
+ PRINT("%s: item matched '%s'\n", __func__, kmi->idname);
+
+ /* weak, but allows interactive callback to not use rawkey */
+ event->keymap_idname = kmi->idname;
+
+ CTX_wm_manipulator_group_set(C, mgroup);
+
+ /* handler->op is called later, we want keymap op to be triggered here */
+ handler->op = NULL;
+ action |= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr);
+ handler->op = op;
+
+ CTX_wm_manipulator_group_set(C, NULL);
+
+ if (action & WM_HANDLER_BREAK) {
+ if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) {
+ printf("%s: handled - and pass on! '%s'\n",
+ __func__, kmi->idname);
+ }
+ break;
+ }
+ else {
+ if (action & WM_HANDLER_HANDLED) {
+ if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) {
+ printf("%s: handled - and pass on! '%s'\n",
+ __func__, kmi->idname);
+ }
+ }
+ else {
+ PRINT("%s: un-handled '%s'\n",
+ __func__, kmi->idname);
+ }
+ }
+ }
+ }
+ }
+ else {
+ PRINT("fail\n");
+ }
+
+ if (action & WM_HANDLER_BREAK) {
+ break;
+ }
+
+ if (is_mgroup_single) {
+ break;
+ }
+ }
+ }
+
+ /* restore the area */
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
+
+ if (handler->op) {
+ action |= wm_handler_operator_call(C, handlers, handler, event, NULL);
+ }
+ }
else {
/* modal, swallows all */
action |= wm_handler_operator_call(C, handlers, handler, event, NULL);
@@ -2320,17 +2549,19 @@ static void wm_paintcursor_test(bContext *C, const wmEvent *event)
static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *event)
{
+ bScreen *screen = WM_window_get_active_screen(win);
+
if (BLI_listbase_is_empty(&wm->drags)) {
return;
}
if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) {
- win->screen->do_draw_drag = true;
+ screen->do_draw_drag = true;
}
else if (event->type == ESCKEY) {
WM_drag_free_list(&wm->drags);
- win->screen->do_draw_drag = true;
+ screen->do_draw_drag = true;
}
else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
event->type = EVT_DROP;
@@ -2346,16 +2577,16 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even
event->customdatafree = 1;
/* clear drop icon */
- win->screen->do_draw_drag = true;
+ screen->do_draw_drag = true;
/* restore cursor (disabled, see wm_dragdrop.c) */
// WM_cursor_modal_restore(win);
}
/* overlap fails otherwise */
- if (win->screen->do_draw_drag)
+ if (screen->do_draw_drag)
if (win->drawmethod == USER_DRAW_OVERLAP)
- win->screen->do_draw = true;
+ screen->do_draw = true;
}
@@ -2385,22 +2616,28 @@ void wm_event_do_handlers(bContext *C)
/* update key configuration before handling events */
WM_keyconfig_update(wm);
+ WM_manipulatorconfig_update(CTX_data_main(C));
for (win = wm->windows.first; win; win = win->next) {
+ bScreen *screen = WM_window_get_active_screen(win);
wmEvent *event;
-
- if (win->screen == NULL)
+
+ /* some safty checks - these should always be set! */
+ BLI_assert(WM_window_get_active_scene(win));
+ BLI_assert(WM_window_get_active_screen(win));
+ BLI_assert(WM_window_get_active_workspace(win));
+
+ if (screen == NULL)
wm_event_free_all(win);
else {
- Scene *scene = win->screen->scene;
-
+ Scene *scene = WM_window_get_active_scene(win);
+
if (scene) {
- int is_playing_sound = BKE_sound_scene_playing(win->screen->scene);
+ int is_playing_sound = BKE_sound_scene_playing(scene);
if (is_playing_sound != -1) {
bool is_playing_screen;
CTX_wm_window_set(C, win);
- CTX_wm_screen_set(C, win->screen);
CTX_data_scene_set(C, scene);
is_playing_screen = (ED_screen_animation_playing(wm) != NULL);
@@ -2417,7 +2654,9 @@ void wm_event_do_handlers(bContext *C)
int ncfra = time * (float)FPS + 0.5f;
if (ncfra != scene->r.cfra) {
scene->r.cfra = ncfra;
- ED_update_for_newframe(CTX_data_main(C), scene, 1);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_update_for_newframe(CTX_data_main(C), scene, view_layer, depsgraph);
WM_event_add_notifier(C, NC_WINDOW, NULL);
}
}
@@ -2433,6 +2672,9 @@ void wm_event_do_handlers(bContext *C)
while ( (event = win->queue.first) ) {
int action = WM_HANDLER_CONTINUE;
+ /* active screen might change during handlers, update pointer */
+ screen = WM_window_get_active_screen(win);
+
if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
printf("\n%s: Handling event\n", __func__);
WM_event_print(event);
@@ -2490,12 +2732,12 @@ void wm_event_do_handlers(bContext *C)
}
#endif
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
/* after restoring a screen from SCREENMAXIMIZED we have to wait
* with the screen handling till the region coordinates are updated */
- if (win->screen->skip_handling == true) {
+ if (screen->skip_handling == true) {
/* restore for the next iteration of wm_event_do_handlers */
- win->screen->skip_handling = false;
+ screen->skip_handling = false;
break;
}
@@ -2522,9 +2764,48 @@ void wm_event_do_handlers(bContext *C)
wm_drags_check_ops(C, event);
}
}
-
+
+#ifdef USE_WORKSPACE_TOOL
+ /* How to solve properly?
+ *
+ * Handlers are stored in each region,
+ * however the tool-system swaps keymaps often and isn't stored
+ * per region.
+ *
+ * Need to investigate how this could be done better.
+ * We might need to add a more dynamic handler type that uses a callback
+ * to fetch its current keymap.
+ */
+ wmEventHandler sneaky_handler = {NULL};
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ if (workspace->tool.keymap[0] &&
+ workspace->tool.spacetype == sa->spacetype)
+ {
+ wmKeyMap *km = WM_keymap_find_all(
+ C, workspace->tool.keymap, sa->spacetype, RGN_TYPE_WINDOW);
+ if (km != NULL) {
+ sneaky_handler.keymap = km;
+ /* Handle widgets first. */
+ wmEventHandler *handler_last = ar->handlers.last;
+ while (handler_last && handler_last->manipulator_map == NULL) {
+ handler_last = handler_last->prev;
+ }
+ /* Head of list or after last manipulator. */
+ BLI_insertlinkafter(&ar->handlers, handler_last, &sneaky_handler);
+ }
+ }
+ }
+#endif /* USE_WORKSPACE_TOOL */
+
action |= wm_handlers_do(C, event, &ar->handlers);
+#ifdef USE_WORKSPACE_TOOL
+ if (sneaky_handler.keymap) {
+ BLI_remlink(&ar->handlers, &sneaky_handler);
+ }
+#endif /* USE_WORKSPACE_TOOL */
+
/* fileread case (python), [#29489] */
if (CTX_wm_window(C) == NULL)
return;
@@ -2589,8 +2870,7 @@ void wm_event_do_handlers(bContext *C)
/* update key configuration after handling events */
WM_keyconfig_update(wm);
-
- GPU_ASSERT_NO_GL_ERRORS("wm_event_do_handlers");
+ WM_manipulatorconfig_update(CTX_data_main(C));
}
/* ********** filesector handling ************ */
@@ -2703,6 +2983,34 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op)
return handler;
}
+/**
+ * Modal handlers store a pointer to an area which might be freed while the handler runs.
+ * Use this function to NULL all handler pointers to \a old_area.
+ */
+void WM_event_modal_handler_area_replace(wmWindow *win, const ScrArea *old_area, ScrArea *new_area)
+{
+ for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) {
+ /* fileselect handler is quite special... it needs to keep old area stored in handler, so don't change it */
+ if ((handler->op_area == old_area) && (handler->type != WM_HANDLER_FILESELECT)) {
+ handler->op_area = new_area;
+ }
+ }
+}
+
+/**
+ * Modal handlers store a pointer to a region which might be freed while the handler runs.
+ * Use this function to NULL all handler pointers to \a old_region.
+ */
+void WM_event_modal_handler_region_replace(wmWindow *win, const ARegion *old_region, ARegion *new_region)
+{
+ for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) {
+ if (handler->op_region == old_region) {
+ handler->op_region = new_region;
+ handler->op_region_type = new_region ? new_region->regiontype : RGN_TYPE_WINDOW;
+ }
+ }
+}
+
wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
{
wmEventHandler *handler;
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 57f4219f23f..7c8059fcda9 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -69,6 +69,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "BKE_appdir.h"
#include "BKE_autoexec.h"
@@ -76,7 +77,6 @@
#include "BKE_blendfile.h"
#include "BKE_blender_undo.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -85,6 +85,7 @@
#include "BKE_sound.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
#include "BLO_readfile.h"
#include "BLO_writefile.h"
@@ -118,8 +119,11 @@
#include "BPY_extern.h"
#endif
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "wm.h"
#include "wm_files.h"
#include "wm_window.h"
@@ -158,7 +162,7 @@ static void wm_window_match_init(bContext *C, ListBase *wmlist)
CTX_wm_window_set(C, win); /* needed by operator close callbacks */
WM_event_remove_handlers(C, &win->handlers);
WM_event_remove_handlers(C, &win->modalhandlers);
- ED_screen_exit(C, win, win->screen);
+ ED_screen_exit(C, win, WM_window_get_active_screen(win));
}
}
@@ -173,21 +177,6 @@ static void wm_window_match_init(bContext *C, ListBase *wmlist)
CTX_wm_menu_set(C, NULL);
ED_editors_exit(C);
-
- /* just had return; here from r12991, this code could just get removed?*/
-#if 0
- if (wm == NULL) return;
- if (G.fileflags & G_FILE_NO_UI) return;
-
- /* we take apart the used screens from non-active window */
- for (win = wm->windows.first; win; win = win->next) {
- BLI_strncpy(win->screenname, win->screen->id.name, MAX_ID_NAME);
- if (win != wm->winactive) {
- BLI_remlink(&G.main->screen, win->screen);
- //BLI_addtail(screenbase, win->screen);
- }
- }
-#endif
}
static void wm_window_substitute_old(wmWindowManager *wm, wmWindow *oldwin, wmWindow *win)
@@ -214,111 +203,134 @@ static void wm_window_substitute_old(wmWindowManager *wm, wmWindow *oldwin, wmWi
win->posy = oldwin->posy;
}
-/* match old WM with new, 4 cases:
- * 1- no current wm, no read wm: make new default
- * 2- no current wm, but read wm: that's OK, do nothing
- * 3- current wm, but not in file: try match screen names
- * 4- current wm, and wm in file: try match ghostwin
- */
-
-static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
+static void wm_window_match_keep_current_wm(
+ const bContext *C, ListBase *current_wm_list,
+ const bool load_ui,
+ ListBase *r_new_wm_list)
{
- wmWindowManager *oldwm, *wm;
- wmWindow *oldwin, *win;
-
- /* cases 1 and 2 */
- if (BLI_listbase_is_empty(oldwmlist)) {
- if (G.main->wm.first) {
- /* nothing todo */
- }
- else {
- wm_add_default(C);
- }
- }
- else {
- /* cases 3 and 4 */
-
- /* we've read file without wm..., keep current one entirely alive */
- if (BLI_listbase_is_empty(&G.main->wm)) {
- bScreen *screen = NULL;
-
- /* when loading without UI, no matching needed */
- if (!(G.fileflags & G_FILE_NO_UI) && (screen = CTX_wm_screen(C))) {
-
- /* match oldwm to new dbase, only old files */
- for (wm = oldwmlist->first; wm; wm = wm->id.next) {
-
- for (win = wm->windows.first; win; win = win->next) {
- /* all windows get active screen from file */
- if (screen->winid == 0)
- win->screen = screen;
- else
- win->screen = ED_screen_duplicate(win, screen);
-
- BLI_strncpy(win->screenname, win->screen->id.name + 2, sizeof(win->screenname));
- win->screen->winid = win->winid;
- }
- }
+ wmWindowManager *wm = current_wm_list->first;
+ bScreen *screen = NULL;
+
+ /* match oldwm to new dbase, only old files */
+ wm->initialized &= ~WM_WINDOW_IS_INITIALIZED;
+
+ /* when loading without UI, no matching needed */
+ if (load_ui && (screen = CTX_wm_screen(C))) {
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ WorkSpace *workspace;
+
+ BKE_workspace_layout_find_global(G.main, screen, &workspace);
+ BKE_workspace_active_set(win->workspace_hook, workspace);
+ win->scene = CTX_data_scene(C);
+
+ /* all windows get active screen from file */
+ if (screen->winid == 0) {
+ WM_window_set_active_screen(win, workspace, screen);
}
-
- G.main->wm = *oldwmlist;
-
- /* screens were read from file! */
- ED_screens_initialize(G.main->wm.first);
- }
- else {
- bool has_match = false;
+ else {
+ WorkSpaceLayout *layout_old = WM_window_get_active_layout(win);
+ WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(workspace, layout_old, win);
- /* what if old was 3, and loaded 1? */
- /* this code could move to setup_appdata */
- oldwm = oldwmlist->first;
- wm = G.main->wm.first;
+ WM_window_set_active_layout(win, workspace, layout_new);
+ }
- /* preserve key configurations in new wm, to preserve their keymaps */
- wm->keyconfigs = oldwm->keyconfigs;
- wm->addonconf = oldwm->addonconf;
- wm->defaultconf = oldwm->defaultconf;
- wm->userconf = oldwm->userconf;
+ bScreen *win_screen = WM_window_get_active_screen(win);
+ win_screen->winid = win->winid;
+ }
+ }
- BLI_listbase_clear(&oldwm->keyconfigs);
- oldwm->addonconf = NULL;
- oldwm->defaultconf = NULL;
- oldwm->userconf = NULL;
+ *r_new_wm_list = *current_wm_list;
+}
- /* ensure making new keymaps and set space types */
- wm->initialized = 0;
- wm->winactive = NULL;
+static void wm_window_match_replace_by_file_wm(
+ bContext *C, ListBase *current_wm_list, ListBase *readfile_wm_list,
+ ListBase *r_new_wm_list)
+{
+ wmWindowManager *oldwm = current_wm_list->first;
+ wmWindowManager *wm = readfile_wm_list->first; /* will become our new WM */
+ bool has_match = false;
- /* only first wm in list has ghostwins */
- for (win = wm->windows.first; win; win = win->next) {
- for (oldwin = oldwm->windows.first; oldwin; oldwin = oldwin->next) {
+ /* this code could move to setup_appdata */
- if (oldwin->winid == win->winid) {
- has_match = true;
+ /* preserve key configurations in new wm, to preserve their keymaps */
+ wm->keyconfigs = oldwm->keyconfigs;
+ wm->addonconf = oldwm->addonconf;
+ wm->defaultconf = oldwm->defaultconf;
+ wm->userconf = oldwm->userconf;
- wm_window_substitute_old(wm, oldwin, win);
- }
- }
- }
+ BLI_listbase_clear(&oldwm->keyconfigs);
+ oldwm->addonconf = NULL;
+ oldwm->defaultconf = NULL;
+ oldwm->userconf = NULL;
+
+ /* ensure making new keymaps and set space types */
+ wm->initialized = 0;
+ wm->winactive = NULL;
- /* make sure at least one window is kept open so we don't lose the context, check T42303 */
- if (!has_match) {
- oldwin = oldwm->windows.first;
- win = wm->windows.first;
+ /* only first wm in list has ghostwins */
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ for (wmWindow *oldwin = oldwm->windows.first; oldwin; oldwin = oldwin->next) {
+ if (oldwin->winid == win->winid) {
+ has_match = true;
wm_window_substitute_old(wm, oldwin, win);
}
+ }
+ }
+ /* make sure at least one window is kept open so we don't lose the context, check T42303 */
+ if (!has_match) {
+ wm_window_substitute_old(wm, oldwm->windows.first, wm->windows.first);
+ }
+
+ wm_close_and_free_all(C, current_wm_list);
+
+ *r_new_wm_list = *readfile_wm_list;
+}
- wm_close_and_free_all(C, oldwmlist);
+/**
+ * Match old WM with new, 4 cases:
+ * 1) No current WM, no WM in file: Make new default.
+ * 2) No current WM, but WM in file: Keep current WM, do nothing else.
+ * 3) Current WM, but not in file: Keep current WM, update windows with screens from file.
+ * 4) Current WM, and WM in file: Try to keep current GHOST windows, use WM from file.
+ *
+ * \param r_new_wm_list: Return argument for the wm list to be used from now on.
+ */
+static void wm_window_match_do(
+ bContext *C,
+ ListBase *current_wm_list, ListBase *readfile_wm_list,
+ ListBase *r_new_wm_list)
+{
+ if (BLI_listbase_is_empty(current_wm_list)) {
+ /* case 1 */
+ if (BLI_listbase_is_empty(readfile_wm_list)) {
+ Main *bmain = CTX_data_main(C);
+ /* Neither current, no newly read file have a WM -> add the default one. */
+ wm_add_default(bmain, C);
+ *r_new_wm_list = bmain->wm;
+ }
+ /* case 2 */
+ else {
+ *r_new_wm_list = *readfile_wm_list;
+ }
+ }
+ else {
+ /* case 3 */
+ if (BLI_listbase_is_empty(readfile_wm_list)) {
+ /* We've read file without wm, keep current one entirely alive.
+ * Happens when reading pre 2.5 files (no WM back then) */
+ wm_window_match_keep_current_wm(C, current_wm_list, (G.fileflags & G_FILE_NO_UI) == 0, r_new_wm_list);
+ }
+ /* case 4 */
+ else {
+ wm_window_match_replace_by_file_wm(C, current_wm_list, readfile_wm_list, r_new_wm_list);
}
}
}
/* in case UserDef was read, we re-initialize all, and do versioning */
-static void wm_init_userdef(bContext *C, const bool read_userdef_from_memory)
+static void wm_init_userdef(Main *bmain, const bool read_userdef_from_memory)
{
- Main *bmain = CTX_data_main(C);
-
/* versioning is here */
UI_init_userdef();
@@ -424,8 +436,9 @@ void wm_file_read_report(bContext *C)
Scene *sce;
for (sce = G.main->scene.first; sce; sce = sce->id.next) {
- if (sce->r.engine[0] &&
- BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL)
+ ViewRender *view_render = &sce->view_render;
+ if (view_render->engine_id[0] &&
+ BLI_findstring(&R_engines, view_render->engine_id, offsetof(RenderEngineType, idname)) == NULL)
{
if (reports == NULL) {
reports = CTX_wm_reports(C);
@@ -433,7 +446,7 @@ void wm_file_read_report(bContext *C)
BKE_reportf(reports, RPT_ERROR,
"Engine '%s' not available for scene '%s' (an add-on may need to be installed or enabled)",
- sce->r.engine, sce->id.name + 2);
+ view_render->engine_id, sce->id.name + 2);
}
}
@@ -461,7 +474,7 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo
CTX_wm_window_set(C, wm->windows.first);
ED_editors_init(C);
- DAG_on_visible_update(CTX_data_main(C), true);
+ DEG_on_visible_update(CTX_data_main(C), true);
#ifdef WITH_PYTHON
if (is_startup_file) {
@@ -492,17 +505,11 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
- /* Would otherwise be handled by event loop.
- *
- * Disabled for startup file, since it causes problems when PyDrivers are used in the startup file.
- * While its possible state of startup file may be wrong,
- * in this case users nearly always load a file to replace the startup file. */
- if (G.background && (is_startup_file == false)) {
- Main *bmain = CTX_data_main(C);
- BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C));
- }
-
+#if 1
WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);
+#else
+ WM_msg_publish_static(CTX_wm_message_bus(C), WM_MSG_STATICTYPE_FILE_READ);
+#endif
/* report any errors.
* currently disabled if addons aren't yet loaded */
@@ -515,6 +522,9 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo
* a blend file and do anything since the screen
* won't be set to a valid value again */
CTX_wm_window_set(C, NULL); /* exits queues */
+
+ /* Ensure tools are registered. */
+ WM_toolsystem_init(C);
}
if (!G.background) {
@@ -552,7 +562,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* put aside screens to match with persistent windows later */
/* also exit screens and editors */
- wm_window_match_init(C, &wmbase);
+ wm_window_match_init(C, &wmbase);
/* confusing this global... */
G.relbase_valid = 1;
@@ -574,12 +584,12 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
/* match the read WM with current WM */
- wm_window_match_do(C, &wmbase);
+ wm_window_match_do(C, &wmbase, &G.main->wm, &G.main->wm);
WM_check(C); /* opens window(s), checks keymaps */
if (retval == BKE_BLENDFILE_READ_OK_USERPREFS) {
/* in case a userdef is read from regular .blend */
- wm_init_userdef(C, false);
+ wm_init_userdef(G.main, false);
}
if (retval != BKE_BLENDFILE_READ_FAIL) {
@@ -837,14 +847,14 @@ int wm_homefile_read(
/* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise
* can remove this eventually, only in a 2.53 and older, now its not written */
G.fileflags &= ~G_FILE_RELATIVE_REMAP;
-
- if (use_userdef) {
+
+ if (use_userdef) {
/* check userdef before open window, keymaps etc */
- wm_init_userdef(C, read_userdef_from_memory);
+ wm_init_userdef(CTX_data_main(C), read_userdef_from_memory);
}
/* match the read WM with current WM */
- wm_window_match_do(C, &wmbase);
+ wm_window_match_do(C, &wmbase, &G.main->wm, &G.main->wm);
WM_check(C); /* opens window(s), checks keymaps */
G.main->name[0] = '\0';
@@ -990,7 +1000,7 @@ static void wm_history_file_update(void)
/* screen can be NULL */
-static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, BlendThumbnail **thumb_pt)
+static ImBuf *blend_file_thumb(const bContext *C, Scene *scene, ViewLayer *view_layer, bScreen *screen, BlendThumbnail **thumb_pt)
{
/* will be scaled down, but gives some nice oversampling */
ImBuf *ibuf;
@@ -1002,6 +1012,10 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, BlendThumbnail **t
ARegion *ar = NULL;
View3D *v3d = NULL;
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* In case we are given a valid thumbnail data, just generate image from it. */
if (*thumb_pt) {
thumb = *thumb_pt;
@@ -1027,14 +1041,14 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, BlendThumbnail **t
/* gets scaled to BLEN_THUMB_SIZE */
if (scene->camera) {
ibuf = ED_view3d_draw_offscreen_imbuf_simple(
- scene, scene->camera,
+ &eval_ctx, scene, view_layer, scene->camera,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
IB_rect, OB_SOLID, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
NULL, NULL, err_out);
}
else {
ibuf = ED_view3d_draw_offscreen_imbuf(
- scene, v3d, ar,
+ &eval_ctx, scene, view_layer, v3d, ar,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL,
NULL, NULL, err_out);
@@ -1130,7 +1144,7 @@ static int wm_file_write(bContext *C, const char *filepath, int fileflags, Repor
/* Main now can store a .blend thumbnail, usefull for background mode or thumbnail customization. */
main_thumb = thumb = CTX_data_main(C)->blen_thumb;
if ((U.flag & USER_SAVE_PREVIEWS) && BLI_thread_is_main()) {
- ibuf_thumb = blend_file_thumb(CTX_data_scene(C), CTX_wm_screen(C), &thumb);
+ ibuf_thumb = blend_file_thumb(C, CTX_data_scene(C), CTX_data_view_layer(C), CTX_wm_screen(C), &thumb);
}
/* operator now handles overwrite checks */
@@ -1385,7 +1399,7 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE);
/* check current window and close it if temp */
- if (win && win->screen->temp)
+ if (win && WM_window_is_temp_screen(win))
wm_window_close(C, wm, win);
/* update keymaps in user preferences */
@@ -1532,6 +1546,42 @@ void WM_OT_save_userpref(wmOperatorType *ot)
ot->exec = wm_userpref_write_exec;
}
+static int wm_workspace_configuration_file_write_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ char filepath[FILE_MAX];
+
+ const char *app_template = U.app_template[0] ? U.app_template : NULL;
+ const char * const cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, app_template);
+ if (cfgdir == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to create workspace configuration file path");
+ return OPERATOR_CANCELLED;
+ }
+
+ BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_WORKSPACES_FILE, NULL);
+ printf("trying to save workspace configuration file at %s ", filepath);
+
+ if (BKE_blendfile_workspace_config_write(bmain, filepath, op->reports) != 0) {
+ printf("ok\n");
+ return OPERATOR_FINISHED;
+ }
+ else {
+ printf("fail\n");
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void WM_OT_save_workspace_file(wmOperatorType *ot)
+{
+ ot->name = "Save Workspace Configuration";
+ ot->idname = "WM_OT_save_workspace_file";
+ ot->description = "Save workspaces of the current file as part of the user configuration";
+
+ ot->invoke = WM_operator_confirm;
+ ot->exec = wm_workspace_configuration_file_write_exec;
+}
+
static int wm_history_file_read_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
{
ED_file_read_bookmarks();
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index 05c569cbaac..cd6a38cb9a8 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -59,7 +59,7 @@
#include "BLO_readfile.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_global.h"
@@ -69,6 +69,8 @@
#include "BKE_idcode.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
#include "IMB_colormanagement.h"
@@ -131,8 +133,8 @@ static short wm_link_append_flag(wmOperator *op)
if (RNA_boolean_get(op->ptr, "autoselect"))
flag |= FILE_AUTOSELECT;
- if (RNA_boolean_get(op->ptr, "active_layer"))
- flag |= FILE_ACTIVELAY;
+ if (RNA_boolean_get(op->ptr, "active_collection"))
+ flag |= FILE_ACTIVE_COLLECTION;
if ((prop = RNA_struct_find_property(op->ptr, "relative_path")) && RNA_property_boolean_get(op->ptr, prop))
flag |= FILE_RELPATH;
if (RNA_boolean_get(op->ptr, "link"))
@@ -211,7 +213,8 @@ static WMLinkAppendDataItem *wm_link_append_data_item_add(
return item;
}
-static void wm_link_do(WMLinkAppendData *lapp_data, ReportList *reports, Main *bmain, Scene *scene, View3D *v3d)
+static void wm_link_do(
+ WMLinkAppendData *lapp_data, ReportList *reports, Main *bmain, Scene *scene, ViewLayer *view_layer)
{
Main *mainl;
BlendHandle *bh;
@@ -258,7 +261,7 @@ static void wm_link_do(WMLinkAppendData *lapp_data, ReportList *reports, Main *b
continue;
}
- new_id = BLO_library_link_named_part_ex(mainl, &bh, item->idcode, item->name, flag, scene, v3d);
+ new_id = BLO_library_link_named_part_ex(mainl, &bh, item->idcode, item->name, flag, scene, view_layer);
if (new_id) {
/* If the link is successful, clear item's libs 'todo' flags.
@@ -268,21 +271,58 @@ static void wm_link_do(WMLinkAppendData *lapp_data, ReportList *reports, Main *b
}
}
- BLO_library_link_end(mainl, &bh, flag, scene, v3d);
+ BLO_library_link_end(mainl, &bh, flag, scene, view_layer);
BLO_blendhandle_close(bh);
}
}
+/**
+ * Check if an item defined by \a name and \a group can be appended/linked.
+ *
+ * \param reports: Optionally report an error when an item can't be appended/linked.
+ */
+static bool wm_link_append_item_poll(
+ ReportList *reports, const char *path, const char *group, const char *name, const bool do_append)
+{
+ short idcode;
+
+ if (!group || !name) {
+ printf("skipping %s\n", path);
+ return false;
+ }
+
+ idcode = BKE_idcode_from_name(group);
+
+ /* XXX For now, we do a nasty exception for workspace, forbid linking them.
+ * Not nice, ultimately should be solved! */
+ if (!BKE_idcode_is_linkable(idcode) && (do_append || idcode != ID_WS)) {
+ if (reports) {
+ if (do_append) {
+ BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Can't append data-block '%s' of type '%s'", name, group);
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Can't link data-block '%s' of type '%s'", name, group);
+ }
+ }
+ return false;
+ }
+
+ return true;
+}
+
static int wm_link_append_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
PropertyRNA *prop;
WMLinkAppendData *lapp_data;
char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA], relname[FILE_MAX];
char *group, *name;
int totfiles = 0;
short flag;
+ bool has_item = false;
+ bool do_append;
RNA_string_get(op->ptr, "filename", relname);
RNA_string_get(op->ptr, "directory", root);
@@ -320,6 +360,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
}
flag = wm_link_append_flag(op);
+ do_append = (flag & FILE_LINK) == 0;
/* sanity checks for flag */
if (scene && scene->id.lib) {
@@ -333,8 +374,8 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
/* from here down, no error returns */
- if (scene && RNA_boolean_get(op->ptr, "autoselect")) {
- BKE_scene_base_deselect_all(scene);
+ if (view_layer && RNA_boolean_get(op->ptr, "autoselect")) {
+ BKE_view_layer_base_deselect_all(view_layer);
}
/* tag everything, all untagged data can be made local
@@ -357,7 +398,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
BLI_join_dirfile(path, sizeof(path), root, relname);
if (BLO_library_path_explode(path, libname, &group, &name)) {
- if (!group || !name) {
+ if (!wm_link_append_item_poll(NULL, path, group, name, do_append)) {
continue;
}
@@ -365,6 +406,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
BLI_ghash_insert(libraries, BLI_strdup(libname), SET_INT_IN_POINTER(lib_idx));
lib_idx++;
wm_link_append_data_library_add(lapp_data, libname);
+ has_item = true;
}
}
}
@@ -378,8 +420,8 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
if (BLO_library_path_explode(path, libname, &group, &name)) {
WMLinkAppendDataItem *item;
- if (!group || !name) {
- printf("skipping %s\n", path);
+
+ if (!wm_link_append_item_poll(op->reports, path, group, name, do_append)) {
continue;
}
@@ -387,6 +429,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL);
BLI_BITMAP_ENABLE(item->libraries, lib_idx);
+ has_item = true;
}
}
RNA_END;
@@ -399,12 +442,18 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
wm_link_append_data_library_add(lapp_data, libname);
item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL);
BLI_BITMAP_ENABLE(item->libraries, 0);
+ has_item = true;
+ }
+
+ if (!has_item) {
+ wm_link_append_data_free(lapp_data);
+ return OPERATOR_CANCELLED;
}
/* XXX We'd need re-entrant locking on Main for this to work... */
/* BKE_main_lock(bmain); */
- wm_link_do(lapp_data, op->reports, bmain, scene, CTX_wm_view3d(C));
+ wm_link_do(lapp_data, op->reports, bmain, scene, view_layer);
/* BKE_main_unlock(bmain); */
@@ -413,7 +462,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
IMB_colormanagement_check_file_config(bmain);
/* append, rather than linking */
- if ((flag & FILE_LINK) == 0) {
+ if (do_append) {
const bool set_fake = RNA_boolean_get(op->ptr, "set_fake");
const bool use_recursive = RNA_boolean_get(op->ptr, "use_recursive");
@@ -444,13 +493,17 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
* link into other scenes from this blend file */
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
+ /* TODO(sergey): Use proper flag for tagging here. */
+
+ /* TODO (dalai): Temporary solution!
+ * Ideally we only need to tag the new objects themselves, not the scene. This way we'll avoid flush of
+ * collection properties to all objects and limit update to the particular object only.
+ * But afraid first we need to change collection evaluation in DEG according to depsgraph manifesto.
+ */
+ DEG_id_tag_update(&scene->id, 0);
+
/* recreate dependency graph to include new objects */
- if (scene) {
- DAG_scene_relations_rebuild(bmain, scene);
- }
-
- /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */
- GPU_materials_free();
+ DEG_relations_tag_update(bmain);
/* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */
BLI_strncpy(G.lib, root, FILE_MAX);
@@ -472,8 +525,8 @@ static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link)
prop = RNA_def_boolean(ot->srna, "autoselect", true,
"Select", "Select new objects");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "active_layer", true,
- "Active Layer", "Put new objects on the active layer");
+ prop = RNA_def_boolean(ot->srna, "active_collection", true,
+ "Active Collection", "Put new objects on the active collection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "instance_groups", is_link,
"Instance Groups", "Create Dupli-Group instances for each group");
@@ -553,7 +606,7 @@ static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UN
}
static void lib_relocate_do(
- Main *bmain, Scene *scene,
+ Main *bmain,
Library *library, WMLinkAppendData *lapp_data, ReportList *reports, const bool do_reload)
{
ListBase *lbarray[MAX_LIBARRAY];
@@ -561,6 +614,7 @@ static void lib_relocate_do(
LinkNode *itemlink;
int item_idx;
+ bool has_item = false;
/* Remove all IDs to be reloaded from Main. */
lba_idx = set_listbasepointers(bmain, lbarray);
@@ -582,6 +636,7 @@ static void lib_relocate_do(
BLI_remlink(lbarray[lba_idx], id);
item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id);
BLI_BITMAP_SET_ALL(item->libraries, true, lapp_data->num_libraries);
+ has_item = true;
#ifdef PRINT_DEBUG
printf("\tdatablock to seek for: %s\n", id->name);
@@ -590,6 +645,11 @@ static void lib_relocate_do(
}
}
+ if (!has_item) {
+ /* nothing to relocate */
+ return;
+ }
+
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
/* We do not want any instanciation here! */
@@ -738,10 +798,7 @@ static void lib_relocate_do(
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
/* recreate dependency graph to include new objects */
- DAG_scene_relations_rebuild(bmain, scene);
-
- /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */
- GPU_materials_free();
+ DEG_relations_tag_update(bmain);
}
void WM_lib_reload(Library *lib, bContext *C, ReportList *reports)
@@ -761,7 +818,7 @@ void WM_lib_reload(Library *lib, bContext *C, ReportList *reports)
wm_link_append_data_library_add(lapp_data, lib->filepath);
- lib_relocate_do(CTX_data_main(C), CTX_data_scene(C), lib, lapp_data, reports, true);
+ lib_relocate_do(CTX_data_main(C), lib, lapp_data, reports, true);
wm_link_append_data_free(lapp_data);
@@ -778,7 +835,6 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload)
if (lib) {
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
PropertyRNA *prop;
WMLinkAppendData *lapp_data;
@@ -872,7 +928,7 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload)
lapp_data->flag |= BLO_LIBLINK_USE_PLACEHOLDERS | BLO_LIBLINK_FORCE_INDIRECT;
}
- lib_relocate_do(bmain, scene, lib, lapp_data, op->reports, do_reload);
+ lib_relocate_do(bmain, lib, lapp_data, op->reports, do_reload);
wm_link_append_data_free(lapp_data);
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index b63962ffce2..fa5fd38b7b2 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -45,15 +45,15 @@
#include "BKE_context.h"
-
#include "WM_api.h"
#include "WM_types.h"
#include "wm.h"
#include "wm_subwindow.h"
#include "wm_draw.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
#include "BIF_glutil.h"
@@ -166,69 +166,99 @@ int wm_gesture_evaluate(wmGesture *gesture)
/* ******************* gesture draw ******************* */
-static void wm_gesture_draw_rect(wmGesture *gt)
+static void wm_gesture_draw_line(wmGesture *gt)
{
rcti *rect = (rcti *)gt->customdata;
-
- glEnable(GL_BLEND);
- glColor4f(1.0, 1.0, 1.0, 0.05);
- glBegin(GL_QUADS);
- glVertex2s(rect->xmax, rect->ymin);
- glVertex2s(rect->xmax, rect->ymax);
- glVertex2s(rect->xmin, rect->ymax);
- glVertex2s(rect->xmin, rect->ymin);
- glEnd();
- glDisable(GL_BLEND);
-
- GPU_basic_shader_bind(GPU_SHADER_LINE | GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor3ub(96, 96, 96);
- GPU_basic_shader_line_stipple(1, 0xCCCC);
- sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- glColor3ub(255, 255, 255);
- GPU_basic_shader_line_stipple(1, 0x3333);
- sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+
+ uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", 8.0f);
+
+ float xmin = (float)rect->xmin;
+ float ymin = (float)rect->ymin;
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(shdr_pos, xmin, ymin);
+ immVertex2f(shdr_pos, (float)rect->xmax, (float)rect->ymax);
+ immEnd();
+
+ immUnbindProgram();
}
-static void wm_gesture_draw_line(wmGesture *gt)
+static void wm_gesture_draw_rect(wmGesture *gt)
{
rcti *rect = (rcti *)gt->customdata;
-
- GPU_basic_shader_bind(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- glColor3ub(96, 96, 96);
- GPU_basic_shader_line_stipple(1, 0xAAAA);
- sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- glColor3ub(255, 255, 255);
- GPU_basic_shader_line_stipple(1, 0x5555);
- sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
-
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-
+
+ uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
+
+ glEnable(GL_BLEND);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.05f);
+
+ immRecti(shdr_pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ immUnbindProgram();
+
+ glDisable(GL_BLEND);
+
+ shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", 8.0f);
+
+ imm_draw_box_wire_2d(shdr_pos, (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, (float)rect->ymax);
+
+ immUnbindProgram();
+
+ // wm_gesture_draw_line(gt); // draws a diagonal line in the lined box to test wm_gesture_draw_line
}
static void wm_gesture_draw_circle(wmGesture *gt)
{
rcti *rect = (rcti *)gt->customdata;
- glTranslatef((float)rect->xmin, (float)rect->ymin, 0.0f);
-
glEnable(GL_BLEND);
- glColor4f(1.0, 1.0, 1.0, 0.05);
- glutil_draw_filled_arc(0.0, M_PI * 2.0, rect->xmax, 40);
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.05f);
+ imm_draw_circle_fill_2d(shdr_pos, (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, 40);
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
-
- // for USE_GLSL works bad because of no relation between lines
- GPU_basic_shader_bind(GPU_SHADER_LINE | GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor3ub(96, 96, 96);
- GPU_basic_shader_line_stipple(1, 0xAAAA);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, rect->xmax, 40);
- glColor3ub(255, 255, 255);
- GPU_basic_shader_line_stipple(1, 0x5555);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, rect->xmax, 40);
-
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- glTranslatef(-rect->xmin, -rect->ymin, 0.0f);
-
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", 4.0f);
+
+ imm_draw_circle_wire_2d(shdr_pos, (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, 40);
+
+ immUnbindProgram();
}
struct LassoFillData {
@@ -251,6 +281,7 @@ static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
int i;
rcti rect;
rcti rect_win;
+ float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
for (i = 0; i < tot; i++, lasso += 2) {
moves[i][0] = lasso[0];
@@ -276,28 +307,28 @@ static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
(const int (*)[2])moves, tot,
draw_filled_lasso_px_cb, &lasso_fill_data);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ /* Additive Blending */
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
- glColor4f(1, 1, 1, 1);
- glPixelTransferf(GL_RED_BIAS, 1);
- glPixelTransferf(GL_GREEN_BIAS, 1);
- glPixelTransferf(GL_BLUE_BIAS, 1);
+ GLint unpack_alignment;
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment);
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glEnable(GL_BLEND);
- glaDrawPixelsTex(rect.xmin, rect.ymin, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, GL_NEAREST, pixel_buf);
- glDisable(GL_BLEND);
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_bind(state.shader);
+ GPU_shader_uniform_vector(state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immDrawPixelsTex(&state, rect.xmin, rect.ymin, w, h, GL_RED, GL_UNSIGNED_BYTE, GL_NEAREST, pixel_buf, 1.0f, 1.0f, NULL);
- glPixelTransferf(GL_RED_BIAS, 0);
- glPixelTransferf(GL_GREEN_BIAS, 0);
- glPixelTransferf(GL_BLUE_BIAS, 0);
+ GPU_shader_unbind();
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment);
MEM_freeN(pixel_buf);
+
+ glDisable(GL_BLEND);
}
MEM_freeN(moves);
@@ -313,29 +344,34 @@ static void wm_gesture_draw_lasso(wmWindow *win, wmGesture *gt, bool filled)
draw_filled_lasso(win, gt);
}
- // for USE_GLSL can't check this yet
- GPU_basic_shader_bind(GPU_SHADER_LINE | GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor3ub(96, 96, 96);
- GPU_basic_shader_line_stipple(1, 0xAAAA);
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < gt->points; i++, lasso += 2)
- glVertex2sv(lasso);
- if (gt->type == WM_GESTURE_LASSO)
- glVertex2sv((short *)gt->customdata);
- glEnd();
-
- glColor3ub(255, 255, 255);
- GPU_basic_shader_line_stipple(1, 0x5555);
- glBegin(GL_LINE_STRIP);
- lasso = (short *)gt->customdata;
- for (i = 0; i < gt->points; i++, lasso += 2)
- glVertex2sv(lasso);
- if (gt->type == WM_GESTURE_LASSO)
- glVertex2sv((short *)gt->customdata);
- glEnd();
-
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-
+ const int numverts = gt->points;
+
+ /* Nothing to draw, do early output. */
+ if (numverts < 2) {
+ return;
+ }
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", 2.0f);
+
+ immBegin((gt->type == WM_GESTURE_LASSO) ? GWN_PRIM_LINE_LOOP : GWN_PRIM_LINE_STRIP, numverts);
+
+ for (i = 0; i < gt->points; i++, lasso += 2) {
+ immVertex2f(shdr_pos, (float)lasso[0], (float)lasso[1]);
+ }
+
+ immEnd();
+
+ immUnbindProgram();
}
static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
@@ -344,25 +380,49 @@ static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
- GPU_basic_shader_bind(GPU_SHADER_LINE | GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor3ub(96, 96, 96);
- GPU_basic_shader_line_stipple(1, 0xCCCC);
- sdrawline(rect->xmin - winsize_x, rect->ymin, rect->xmin + winsize_x, rect->ymin);
- sdrawline(rect->xmin, rect->ymin - winsize_y, rect->xmin, rect->ymin + winsize_y);
-
- glColor3ub(255, 255, 255);
- GPU_basic_shader_line_stipple(1, 0x3333);
- sdrawline(rect->xmin - winsize_x, rect->ymin, rect->xmin + winsize_x, rect->ymin);
- sdrawline(rect->xmin, rect->ymin - winsize_y, rect->xmin, rect->ymin + winsize_y);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ float x1, x2, y1, y2;
+
+ const uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ glGetFloatv(GL_VIEWPORT, viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("num_colors", 2); /* "advanced" mode */
+ immUniformArray4fv("colors", (float *)(float[][4]){{0.4f, 0.4f, 0.4f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, 2);
+ immUniform1f("dash_width", 8.0f);
+
+ immBegin(GWN_PRIM_LINES, 4);
+
+ x1 = (float)(rect->xmin - winsize_x);
+ y1 = (float)rect->ymin;
+ x2 = (float)(rect->xmin + winsize_x);
+ y2 = y1;
+
+ immVertex2f(shdr_pos, x1, y1);
+ immVertex2f(shdr_pos, x2, y2);
+
+ x1 = (float)rect->xmin;
+ y1 = (float)(rect->ymin - winsize_y);
+ x2 = x1;
+ y2 = (float)(rect->ymin + winsize_y);
+
+ immVertex2f(shdr_pos, x1, y1);
+ immVertex2f(shdr_pos, x2, y2);
+
+ immEnd();
+
+ immUnbindProgram();
}
/* called in wm_draw.c */
void wm_gesture_draw(wmWindow *win)
{
wmGesture *gt = (wmGesture *)win->gesture.first;
-
- GPU_basic_shader_line_width(1);
+
+ glLineWidth(1.0f);
for (; gt; gt = gt->next) {
/* all in subwindow space */
wmSubWindowSet(win, gt->swinid);
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 7608b015f49..55ed8b2a091 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -93,6 +93,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "wm_cursors.h"
#include "wm_event_system.h"
@@ -119,10 +120,11 @@
#include "GPU_draw.h"
#include "GPU_init_exit.h"
-#include "BKE_depsgraph.h"
#include "BKE_sound.h"
#include "COM_compositor.h"
+#include "DEG_depsgraph.h"
+
#ifdef WITH_OPENSUBDIV
# include "BKE_subsurf.h"
#endif
@@ -164,17 +166,20 @@ void WM_init(bContext *C, int argc, const char **argv)
wm_operatortype_init();
WM_menutype_init();
WM_uilisttype_init();
+ wm_manipulatortype_init();
+ wm_manipulatorgrouptype_init();
BKE_undo_callback_wm_kill_jobs_set(wm_undo_kill_callback);
BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */
BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */
+ BKE_region_callback_free_manipulatormap_set(wm_manipulatormap_remove); /* screen.c */
+ BKE_region_callback_refresh_tag_manipulatormap_set(WM_manipulatormap_tag_refresh);
BKE_library_callback_remap_editor_id_reference_set(WM_main_remap_editor_id_reference); /* library.c */
BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */
BKE_spacedata_callback_id_remap_set(ED_spacedata_id_remap); /* screen.c */
- DAG_editors_update_cb(ED_render_id_flush_update,
- ED_render_scene_update,
- ED_render_scene_update_pre); /* depsgraph.c */
+ DEG_editors_set_update_cb(ED_render_id_flush_update,
+ ED_render_scene_update);
ED_spacetypes_init(); /* editors/space_api/spacetype.c */
@@ -188,6 +193,8 @@ void WM_init(bContext *C, int argc, const char **argv)
* but keep before file reading, since that may report errors */
wm_init_reports(C);
+ WM_msgbus_types_init();
+
/* get the default database, plus a wm */
wm_homefile_read(C, NULL, G.factory_startup, false, true, NULL, NULL);
@@ -473,7 +480,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
CTX_wm_window_set(C, win); /* needed by operator close callbacks */
WM_event_remove_handlers(C, &win->handlers);
WM_event_remove_handlers(C, &win->modalhandlers);
- ED_screen_exit(C, win, win->screen);
+ ED_screen_exit(C, win, WM_window_get_active_screen(win));
}
}
@@ -524,6 +531,11 @@ void WM_exit_ext(bContext *C, const bool do_python)
ED_gpencil_strokes_copybuf_free();
BKE_node_clipboard_clear();
+ /* free manipulator-maps after freeing blender, so no deleted data get accessed during cleaning up of areas */
+ wm_manipulatormaptypes_free();
+ wm_manipulatorgrouptype_free();
+ wm_manipulatortype_free();
+
BLF_exit();
#ifdef WITH_INTERNATIONAL
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 4674df9983b..ad1d0730ad2 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -52,6 +52,7 @@
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "BLT_translation.h"
@@ -70,7 +71,6 @@
#include "BKE_blender_version.h"
#include "BKE_brush.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
@@ -86,9 +86,12 @@
#include "BKE_idcode.h"
-#include "BIF_glutil.h" /* for paint cursor */
#include "BLF_api.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -97,8 +100,6 @@
#include "ED_util.h"
#include "ED_view3d.h"
-#include "GPU_basic_shader.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -118,6 +119,8 @@
#include "wm_window.h"
static GHash *global_ops_hash = NULL;
+/** Counter for operator-properties that should not be tagged with #OP_PROP_TAG_ADVANCED. */
+static int ot_prop_basic_count = -1;
#define UNDOCUMENTED_OPERATOR_TIP N_("(undocumented operator)")
@@ -157,23 +160,33 @@ void WM_operatortype_iter(GHashIterator *ghi)
BLI_ghashIterator_init(ghi, global_ops_hash);
}
-/* all ops in 1 list (for time being... needs evaluation later) */
-void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
+/** \name Operator Type Append
+ * \{ */
+
+static wmOperatorType *wm_operatortype_append__begin(void)
{
- wmOperatorType *ot;
-
- ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
+ wmOperatorType *ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
+
+ BLI_assert(ot_prop_basic_count == -1);
+
ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties);
+ RNA_def_struct_property_tags(ot->srna, rna_enum_operator_property_tags);
/* Set the default i18n context now, so that opfunc can redefine it if needed! */
RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT;
- opfunc(ot);
+ return ot;
+}
+static void wm_operatortype_append__end(wmOperatorType *ot)
+{
if (ot->name == NULL) {
fprintf(stderr, "ERROR: Operator %s has no name property!\n", ot->idname);
ot->name = N_("Dummy Name");
}
+ /* Allow calling _begin without _end in operatortype creation. */
+ WM_operatortype_props_advanced_end(ot);
+
/* XXX All ops should have a description but for now allow them not to. */
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP);
RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
@@ -181,22 +194,23 @@ void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
}
-void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *userdata)
+/* all ops in 1 list (for time being... needs evaluation later) */
+void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
{
- wmOperatorType *ot;
+ wmOperatorType *ot = wm_operatortype_append__begin();
+ opfunc(ot);
+ wm_operatortype_append__end(ot);
+}
- ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
- ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties);
- /* Set the default i18n context now, so that opfunc can redefine it if needed! */
- RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
- ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT;
+void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *userdata)
+{
+ wmOperatorType *ot = wm_operatortype_append__begin();
opfunc(ot, userdata);
- RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP);
- RNA_def_struct_identifier(&BLENDER_RNA, ot->srna, ot->idname);
-
- BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
+ wm_operatortype_append__end(ot);
}
+/** \} */
+
/* ********************* macro operator ******************** */
typedef struct {
@@ -527,6 +541,55 @@ void WM_operatortype_last_properties_clear_all(void)
}
}
+/**
+ * Tag all operator-properties of \a ot defined after calling this, until
+ * the next #WM_operatortype_props_advanced_end call (if available), with
+ * #OP_PROP_TAG_ADVANCED. Previously defined ones properties not touched.
+ *
+ * Calling this multiple times without a call to #WM_operatortype_props_advanced_end,
+ * all calls after the first one are ignored. Meaning all propereties defined after the
+ * first call are tagged as advanced.
+ *
+ * This doesn't do the actual tagging, #WM_operatortype_props_advanced_end does which is
+ * called for all operators during registration (see #wm_operatortype_append__end).
+ */
+void WM_operatortype_props_advanced_begin(wmOperatorType *ot)
+{
+ if (ot_prop_basic_count == -1) { /* Don't do anything if _begin was called before, but not _end */
+ ot_prop_basic_count = RNA_struct_count_properties(ot->srna);
+ }
+}
+
+/**
+ * Tags all operator-properties of \ot defined since the first #WM_operatortype_props_advanced_begin
+ * call, or the last #WM_operatortype_props_advanced_end call, with #OP_PROP_TAG_ADVANCED.
+ * Note that this is called for all operators during registration (see #wm_operatortype_append__end).
+ * So it does not need to be explicitly called in operator-type definition.
+ */
+void WM_operatortype_props_advanced_end(wmOperatorType *ot)
+{
+ PointerRNA struct_ptr;
+ int counter = 0;
+
+ if (ot_prop_basic_count == -1) {
+ /* WM_operatortype_props_advanced_begin was not called. Don't do anything. */
+ return;
+ }
+
+ RNA_pointer_create(NULL, ot->srna, NULL, &struct_ptr);
+
+ RNA_STRUCT_BEGIN (&struct_ptr, prop)
+ {
+ counter++;
+ if (counter > ot_prop_basic_count) {
+ WM_operatortype_prop_tag(prop, OP_PROP_TAG_ADVANCED);
+ }
+ }
+ RNA_STRUCT_END;
+
+ ot_prop_basic_count = -1;
+}
+
/* SOME_OT_op -> some.op */
void WM_operator_py_idname(char *to, const char *from)
{
@@ -1164,46 +1227,70 @@ int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_REGION_WIN);
}
+struct EnumSearchMenu {
+ wmOperator *op; /* the operator that will be executed when selecting an item */
+
+ bool use_previews;
+ short prv_cols, prv_rows;
+};
/* generic enum search invoke popup */
-static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op)
+static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg)
{
- static char search[256] = "";
- wmEvent event;
+ struct EnumSearchMenu *search_menu = arg;
wmWindow *win = CTX_wm_window(C);
+ wmOperator *op = search_menu->op;
+ /* template_ID uses 4 * widget_unit for width, we use a bit more, some items may have a suffix to show */
+ const int width = search_menu->use_previews ? 5 * U.widget_unit * search_menu->prv_cols : UI_searchbox_size_x();
+ const int height = search_menu->use_previews ? 5 * U.widget_unit * search_menu->prv_rows : UI_searchbox_size_y();
+ static char search[256] = "";
uiBlock *block;
uiBut *but;
- wmOperator *op = (wmOperator *)arg_op;
block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
search[0] = '\0';
+ BLI_assert(search_menu->use_previews || (search_menu->prv_cols == 0 && search_menu->prv_rows == 0));
#if 0 /* ok, this isn't so easy... */
uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_struct_ui_name(op->type->srna), 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
#endif
but = uiDefSearchButO_ptr(block, op->type, op->ptr->data, search, 0, ICON_VIEWZOOM, sizeof(search),
- 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, 0, 0, "");
+ 10, 10, width, UI_UNIT_Y, search_menu->prv_rows, search_menu->prv_cols, "");
/* fake button, it holds space for search items */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - UI_searchbox_size_y(), UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - UI_searchbox_size_y(), width, height, NULL, 0, 0, 0, 0, NULL);
UI_block_bounds_set_popup(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
-
- wm_event_init_from_window(win, &event);
- event.type = EVT_BUT_OPEN;
- event.val = KM_PRESS;
- event.customdata = but;
- event.customdatafree = false;
- wm_event_add(win, &event);
+ UI_but_focus_on_enter_event(win, but);
return block;
}
+/**
+ * Similar to #WM_enum_search_invoke, but draws previews. Also, this can't
+ * be used as invoke callback directly since it needs additional info.
+ */
+int WM_enum_search_invoke_previews(
+ bContext *C, wmOperator *op, short prv_cols, short prv_rows)
+{
+ static struct EnumSearchMenu search_menu;
+
+ search_menu.op = op;
+ search_menu.use_previews = true;
+ search_menu.prv_cols = prv_cols;
+ search_menu.prv_rows = prv_rows;
+
+ UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu);
+
+ return OPERATOR_INTERFACE;
+}
int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- UI_popup_block_invoke(C, wm_enum_search_menu, op);
+ static struct EnumSearchMenu search_menu;
+ search_menu.op = op;
+ UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu);
return OPERATOR_INTERFACE;
}
@@ -1716,6 +1803,48 @@ static void WM_OT_operator_defaults(wmOperatorType *ot)
ot->flag = OPTYPE_INTERNAL;
}
+#ifdef USE_WORKSPACE_TOOL
+/* ***************** Set Active Tool ************************* */
+
+/* Developers note: in it's current form this doesn't need to be an operator,
+ * keep this as-is for now since it may end up setting an active key-map.
+ */
+
+static int wm_operator_tool_set_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ bToolDef tool_def = {0};
+
+ tool_def.index = RNA_int_get(op->ptr, "index");
+ tool_def.spacetype = sa->spacetype;
+ RNA_string_get(op->ptr, "keymap", tool_def.keymap);
+ RNA_string_get(op->ptr, "manipulator_group", tool_def.manipulator_group);
+
+ WM_toolsystem_set(C, &tool_def);
+
+ /* For some reason redraw fails with menus (even though 'ar' isn't the menu's region). */
+ ED_area_tag_redraw(sa);
+
+ return OPERATOR_FINISHED;
+}
+
+static void WM_OT_tool_set(wmOperatorType *ot)
+{
+ ot->name = "Set Active Tool";
+ ot->idname = "WM_OT_tool_set";
+ ot->description = "Set the active tool";
+
+ ot->exec = wm_operator_tool_set_exec;
+
+ ot->flag = OPTYPE_INTERNAL;
+
+ RNA_def_string(ot->srna, "keymap", NULL, KMAP_MAX_NAME, "Key Map", "");
+ RNA_def_string(ot->srna, "manipulator_group", NULL, MAX_NAME, "Manipulator Group", "");
+ RNA_def_int(ot->srna, "index", 0, INT_MIN, INT_MAX, "Index", "", INT_MIN, INT_MAX);
+}
+#endif /* USE_WORKSPACE_TOOL */
+
/* ***************** Splash Screen ************************* */
static void wm_block_splash_close(bContext *C, void *arg_block, void *UNUSED(arg))
@@ -1859,8 +1988,8 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
if (version_suffix != NULL && version_suffix[0]) {
/* placed after the version number in the image,
* placing y is tricky to match baseline */
- int x = 260 * U.pixelsize - (2 * UI_DPI_FAC);
- int y = 242 * U.pixelsize + (4 * UI_DPI_FAC);
+ int x = 236 * U.pixelsize - (2 * UI_DPI_FAC);
+ int y = 231 * U.pixelsize + (4 * UI_DPI_FAC);
int w = 240 * U.pixelsize;
/* hack to have text draw 'text_sel' */
@@ -1873,17 +2002,32 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
#ifdef WITH_BUILDINFO
if (build_commit_timestamp != 0) {
- uiDefBut(block, UI_BTYPE_LABEL, 0, date_buf, U.pixelsize * 494 - date_width, U.pixelsize * 270, date_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ but = uiDefBut(
+ block, UI_BTYPE_LABEL, 0, date_buf,
+ U.pixelsize * 502 - date_width, U.pixelsize * 267,
+ date_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ /* XXX, set internal flag - UI_SELECT */
+ UI_but_flag_enable(but, 1);
label_delta = 12;
}
- uiDefBut(block, UI_BTYPE_LABEL, 0, hash_buf, U.pixelsize * 494 - hash_width, U.pixelsize * (270 - label_delta), hash_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ but = uiDefBut(
+ block, UI_BTYPE_LABEL, 0, hash_buf,
+ U.pixelsize * 502 - hash_width, U.pixelsize * (267 - label_delta),
+ hash_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ /* XXX, set internal flag - UI_SELECT */
+ UI_but_flag_enable(but, 1);
if (!STREQ(build_branch, "master")) {
char branch_buf[128] = "\0";
int branch_width;
BLI_snprintf(branch_buf, sizeof(branch_buf), "Branch: %s", build_branch);
branch_width = (int)BLF_width(style->widgetlabel.uifont_id, branch_buf, sizeof(branch_buf)) + U.widget_unit;
- uiDefBut(block, UI_BTYPE_LABEL, 0, branch_buf, U.pixelsize * 494 - branch_width, U.pixelsize * (258 - label_delta), branch_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ but = uiDefBut(
+ block, UI_BTYPE_LABEL, 0, branch_buf,
+ U.pixelsize * 502 - branch_width, U.pixelsize * (255 - label_delta),
+ branch_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ /* XXX, set internal flag - UI_SELECT */
+ UI_but_flag_enable(but, 1);
}
#endif /* WITH_BUILDINFO */
@@ -2122,8 +2266,11 @@ static void WM_OT_call_menu_pie(wmOperatorType *ot)
static int wm_operator_winactive_normal(bContext *C)
{
wmWindow *win = CTX_wm_window(C);
+ bScreen *screen;
- if (win == NULL || win->screen == NULL || win->screen->state != SCREENNORMAL)
+ if (win == NULL)
+ return 0;
+ if (!((screen = WM_window_get_active_screen(win)) && (screen->state == SCREENNORMAL)))
return 0;
return 1;
@@ -2140,14 +2287,22 @@ static void WM_OT_window_close(wmOperatorType *ot)
ot->poll = WM_operator_winactive;
}
-static void WM_OT_window_duplicate(wmOperatorType *ot)
+static void WM_OT_window_new(wmOperatorType *ot)
{
- ot->name = "Duplicate Window";
- ot->idname = "WM_OT_window_duplicate";
- ot->description = "Duplicate the current Blender window";
-
- ot->exec = wm_window_duplicate_exec;
+ PropertyRNA *prop;
+
+ ot->name = "New Window";
+ ot->idname = "WM_OT_window_new";
+ ot->description = "Create a new Blender window";
+
+ ot->exec = wm_window_new_exec;
+ ot->invoke = wm_window_new_invoke;
ot->poll = wm_operator_winactive_normal;
+
+ prop = RNA_def_enum(ot->srna, "screen", DummyRNA_NULL_items, 0, "Screen", "");
+ RNA_def_enum_funcs(prop, wm_window_new_screen_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot)
@@ -2351,8 +2506,8 @@ static void radial_control_set_tex(RadialControl *rc)
if ((ibuf = BKE_brush_gen_radial_control_imbuf(rc->image_id_ptr.data, rc->use_secondary_tex))) {
glGenTextures(1, &rc->gltex);
glBindTexture(GL_TEXTURE_2D, rc->gltex);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, ibuf->x, ibuf->y, 0,
- GL_ALPHA, GL_FLOAT, ibuf->rect_float);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, ibuf->x, ibuf->y, 0,
+ GL_RED, GL_FLOAT, ibuf->rect_float);
MEM_freeN(ibuf->rect_float);
MEM_freeN(ibuf);
}
@@ -2385,43 +2540,63 @@ static void radial_control_paint_tex(RadialControl *rc, float radius, float alph
RNA_property_float_get_array(fill_ptr, fill_prop, col);
}
- glColor4f(col[0], col[1], col[2], alpha);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
if (rc->gltex) {
+
+ unsigned int texCoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
glBindTexture(GL_TEXTURE_2D, rc->gltex);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ GLint swizzleMask[] = {GL_ZERO, GL_ZERO, GL_ZERO, GL_RED};
+ glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR);
+
+ immUniformColor3fvAlpha(col, alpha);
+ immUniform1i("image", GL_TEXTURE0);
/* set up rotation if available */
if (rc->rot_prop) {
rot = RNA_property_float_get(&rc->rot_ptr, rc->rot_prop);
- glPushMatrix();
- glRotatef(RAD2DEGF(rot), 0, 0, 1);
+ gpuPushMatrix();
+ gpuRotate2D(RAD2DEGF(rot));
}
/* draw textured quad */
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0);
- glVertex2f(-radius, -radius);
- glTexCoord2f(1, 0);
- glVertex2f(radius, -radius);
- glTexCoord2f(1, 1);
- glVertex2f(radius, radius);
- glTexCoord2f(0, 1);
- glVertex2f(-radius, radius);
- glEnd();
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immBegin(GWN_PRIM_TRI_FAN, 4);
+
+ immAttrib2f(texCoord, 0, 0);
+ immVertex2f(pos, -radius, -radius);
+
+ immAttrib2f(texCoord, 1, 0);
+ immVertex2f(pos, radius, -radius);
+
+ immAttrib2f(texCoord, 1, 1);
+ immVertex2f(pos, radius, radius);
+
+ immAttrib2f(texCoord, 0, 1);
+ immVertex2f(pos, -radius, radius);
+
+ immEnd();
/* undo rotation */
if (rc->rot_prop)
- glPopMatrix();
+ gpuPopMatrix();
}
else {
/* flat color if no texture available */
- glutil_draw_filled_arc(0, M_PI * 2, radius, 40);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fvAlpha(col, alpha);
+ imm_draw_circle_fill_2d(pos, 0.0f, 0.0f, radius, 40);
}
+
+ immUnbindProgram();
}
static void radial_control_paint_cursor(bContext *C, int x, int y, void *customdata)
@@ -2480,7 +2655,7 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
/* Keep cursor in the original place */
x = rc->initial_mouse[0] - ar->winrct.xmin;
y = rc->initial_mouse[1] - ar->winrct.ymin;
- glTranslatef((float)x, (float)y, 0.0f);
+ gpuTranslate2f((float)x, (float)y);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
@@ -2488,7 +2663,7 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
/* apply zoom if available */
if (rc->zoom_prop) {
RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
- glScalef(zoom[0], zoom[1], 1);
+ gpuScale2fv(zoom);
}
/* draw rotated texture */
@@ -2497,24 +2672,39 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
/* set line color */
if (rc->col_prop)
RNA_property_float_get_array(&rc->col_ptr, rc->col_prop, col);
- glColor4f(col[0], col[1], col[2], 0.5);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fvAlpha(col, 0.5f);
if (rc->subtype == PROP_ANGLE) {
- glPushMatrix();
+ gpuPushMatrix();
+
/* draw original angle line */
- glRotatef(RAD2DEGF(rc->initial_value), 0, 0, 1);
- fdrawline((float)WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE, 0.0f, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f);
+ gpuRotate2D(RAD2DEGF(rc->initial_value));
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE, 0.0f);
+ immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f);
+ immEnd();
+
/* draw new angle line */
- glRotatef(RAD2DEGF(rc->current_value - rc->initial_value), 0, 0, 1);
- fdrawline((float)WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE, 0.0f, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f);
- glPopMatrix();
+ gpuRotate2D(RAD2DEGF(rc->current_value - rc->initial_value));
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE, 0.0f);
+ immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f);
+ immEnd();
+
+ gpuPopMatrix();
}
/* draw circles on top */
- glutil_draw_lined_arc(0.0, (float)(M_PI * 2.0), r1, 40);
- glutil_draw_lined_arc(0.0, (float)(M_PI * 2.0), r2, 40);
+ imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r1, 40);
+ imm_draw_circle_wire_2d(pos, 0.0f, 0.0f, r2, 40);
if (rmin > 0.0f)
- glutil_draw_lined_arc(0.0, (float)(M_PI * 2.0), rmin, 40);
+ imm_draw_circle_wire_2d(pos, 0.0, 0.0f, rmin, 40);
+ immUnbindProgram();
BLF_size(fontid, 1.5 * fstyle_points * U.pixelsize, U.dpi);
BLF_enable(fontid, BLF_SHADOW);
@@ -2530,6 +2720,7 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
+
}
typedef enum {
@@ -3089,7 +3280,8 @@ static const EnumPropertyItem redraw_timer_type_items[] = {
static void redraw_timer_step(
- bContext *C, Main *bmain, Scene *scene,
+ bContext *C, Main *bmain, Scene *scene, ViewLayer *view_layer,
+ struct Depsgraph *depsgraph,
wmWindow *win, ScrArea *sa, ARegion *ar,
const int type, const int cfra)
{
@@ -3108,11 +3300,12 @@ static void redraw_timer_step(
CTX_wm_window_set(C, win); /* XXX context manipulation warning! */
}
else if (type == eRTDrawWindow) {
+ bScreen *screen = WM_window_get_active_screen(win);
ScrArea *sa_iter;
CTX_wm_menu_set(C, NULL);
- for (sa_iter = win->screen->areabase.first; sa_iter; sa_iter = sa_iter->next) {
+ for (sa_iter = screen->areabase.first; sa_iter; sa_iter = sa_iter->next) {
ARegion *ar_iter;
CTX_wm_area_set(C, sa_iter);
@@ -3135,7 +3328,7 @@ static void redraw_timer_step(
}
else if (type == eRTAnimationStep) {
scene->r.cfra += (cfra == scene->r.cfra) ? 1 : -1;
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
}
else if (type == eRTAnimationPlay) {
/* play anim, return on same frame as started with */
@@ -3147,7 +3340,7 @@ static void redraw_timer_step(
if (scene->r.cfra > scene->r.efra)
scene->r.cfra = scene->r.sfra;
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
redraw_timer_window_swap(C);
}
}
@@ -3161,6 +3354,7 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -3171,13 +3365,14 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
const int cfra = scene->r.cfra;
int a, iter_steps = 0;
const char *infostr = "";
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
WM_cursor_wait(1);
time_start = PIL_check_seconds_timer();
for (a = 0; a < iter; a++) {
- redraw_timer_step(C, bmain, scene, win, sa, ar, type, cfra);
+ redraw_timer_step(C, bmain, scene, view_layer, depsgraph, win, sa, ar, type, cfra);
iter_steps += 1;
if (time_limit != 0.0) {
@@ -3235,28 +3430,6 @@ static void WM_OT_memory_statistics(wmOperatorType *ot)
ot->exec = memory_statistics_exec;
}
-/* ************************** memory statistics for testing ***************** */
-
-static int dependency_relations_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
-
- DAG_print_dependencies(bmain, scene, ob);
-
- return OPERATOR_FINISHED;
-}
-
-static void WM_OT_dependency_relations(wmOperatorType *ot)
-{
- ot->name = "Dependency Relations";
- ot->idname = "WM_OT_dependency_relations";
- ot->description = "Print dependency graph relations to the console";
-
- ot->exec = dependency_relations_exec;
-}
-
/* *************************** Mat/tex/etc. previews generation ************* */
typedef struct PreviewsIDEnsureData {
@@ -3503,12 +3676,13 @@ void wm_operatortype_init(void)
global_ops_hash = BLI_ghash_str_new_ex("wm_operatortype_init gh", 2048);
WM_operatortype_append(WM_OT_window_close);
- WM_operatortype_append(WM_OT_window_duplicate);
+ WM_operatortype_append(WM_OT_window_new);
WM_operatortype_append(WM_OT_read_history);
WM_operatortype_append(WM_OT_read_homefile);
WM_operatortype_append(WM_OT_read_factory_settings);
WM_operatortype_append(WM_OT_save_homefile);
WM_operatortype_append(WM_OT_save_userpref);
+ WM_operatortype_append(WM_OT_save_workspace_file);
WM_operatortype_append(WM_OT_userpref_autoexec_path_add);
WM_operatortype_append(WM_OT_userpref_autoexec_path_remove);
WM_operatortype_append(WM_OT_window_fullscreen_toggle);
@@ -3525,9 +3699,11 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_save_mainfile);
WM_operatortype_append(WM_OT_redraw_timer);
WM_operatortype_append(WM_OT_memory_statistics);
- WM_operatortype_append(WM_OT_dependency_relations);
WM_operatortype_append(WM_OT_debug_menu);
WM_operatortype_append(WM_OT_operator_defaults);
+#ifdef USE_WORKSPACE_TOOL
+ WM_operatortype_append(WM_OT_tool_set);
+#endif
WM_operatortype_append(WM_OT_splash);
WM_operatortype_append(WM_OT_search_menu);
WM_operatortype_append(WM_OT_call_menu);
@@ -3540,6 +3716,10 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_previews_ensure);
WM_operatortype_append(WM_OT_previews_clear);
WM_operatortype_append(WM_OT_doc_view_manual_ui_context);
+
+ /* manipulators */
+ WM_operatortype_append(MANIPULATORGROUP_OT_manipulator_select);
+ WM_operatortype_append(MANIPULATORGROUP_OT_manipulator_tweak);
}
/* circleselect-like modal operators */
@@ -3742,7 +3922,7 @@ void wm_window_keymap(wmKeyConfig *keyconf)
wmKeyMapItem *kmi;
/* note, this doesn't replace existing keymap items */
- WM_keymap_verify_item(keymap, "WM_OT_window_duplicate", WKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "WM_OT_window_new", WKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
#ifdef __APPLE__
WM_keymap_add_item(keymap, "WM_OT_read_homefile", NKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_menu(keymap, "INFO_MT_file_open_recent", OKEY, KM_PRESS, KM_SHIFT | KM_OSKEY, 0);
@@ -3846,6 +4026,7 @@ void wm_window_keymap(wmKeyConfig *keyconf)
RNA_float_set(kmi->ptr, "value", 1.0f / 1.5f);
#endif /* WITH_INPUT_NDOF */
+ wm_manipulators_keymap(keyconf);
gesture_circle_modal_keymap(keyconf);
gesture_border_modal_keymap(keyconf);
gesture_zoom_border_modal_keymap(keyconf);
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 77378cf8e0c..fcb471530e0 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -58,24 +58,29 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-#include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_matrix.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+
#include "DNA_scene_types.h"
#include "ED_datafiles.h" /* for fonts */
#include "GHOST_C-api.h"
#include "BLF_api.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h" /* only for WM_main_playanim */
#ifdef WITH_AUDASPACE
-# include AUD_DEVICE_H
-# include AUD_HANDLE_H
-# include AUD_SOUND_H
-# include AUD_SPECIAL_H
+# include <AUD_Device.h>
+# include <AUD_Handle.h>
+# include <AUD_Sound.h>
+# include <AUD_Special.h>
static AUD_Sound *source = NULL;
static AUD_Handle *playback_handle = NULL;
@@ -190,10 +195,7 @@ static void playanim_window_get_size(int *r_width, int *r_height)
static void playanim_gl_matrix(void)
{
/* unified matrix, note it affects offset for drawing */
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
- glMatrixMode(GL_MODELVIEW);
+ gpuOrtho2D(0.0f, 1.0f, 0.0f, 1.0f);
}
/* implementation */
@@ -308,42 +310,45 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf
CLAMP(offs_x, 0.0f, 1.0f);
CLAMP(offs_y, 0.0f, 1.0f);
- glRasterPos2f(offs_x, offs_y);
glClearColor(0.1, 0.1, 0.1, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
-
+
/* checkerboard for case alpha */
if (ibuf->planes == 32) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- fdrawcheckerboard(offs_x, offs_y, offs_x + span_x, offs_y + span_y);
+ imm_draw_box_checker_2d(offs_x, offs_y, offs_x + span_x, offs_y + span_y);
}
- glRasterPos2f(offs_x + (ps->draw_flip[0] ? span_x : 0.0f),
- offs_y + (ps->draw_flip[1] ? span_y : 0.0f));
-
- glPixelZoom(ps->zoom * (ps->draw_flip[0] ? -1.0f : 1.0f),
- ps->zoom * (ps->draw_flip[1] ? -1.0f : 1.0f));
+ IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- glDrawPixels(ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ immDrawPixelsTex(
+ &state,
+ offs_x + (ps->draw_flip[0] ? span_x : 0.0f),
+ offs_y + (ps->draw_flip[1] ? span_y : 0.0f),
+ ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST,
+ ibuf->rect,
+ ((ps->draw_flip[0] ? -1.0f : 1.0f)) * (ps->zoom / (float)ps->win_x),
+ ((ps->draw_flip[1] ? -1.0f : 1.0f)) * (ps->zoom / (float)ps->win_y),
+ NULL);
glDisable(GL_BLEND);
-
+
pupdate_time();
if (picture && (g_WS.qual & (WS_QUAL_SHIFT | WS_QUAL_LMOUSE)) && (fontid != -1)) {
int sizex, sizey;
float fsizex_inv, fsizey_inv;
char str[32 + FILE_MAX];
- cpack(-1);
BLI_snprintf(str, sizeof(str), "%s | %.2f frames/s", picture->name, fstep / swaptime);
playanim_window_get_size(&sizex, &sizey);
fsizex_inv = 1.0f / sizex;
fsizey_inv = 1.0f / sizey;
+ BLF_color4f(fontid, 1.0, 1.0, 1.0, 1.0);
BLF_enable(fontid, BLF_ASPECT);
BLF_aspect(fontid, fsizex_inv, fsizey_inv, 1.0f);
BLF_position(fontid, 10.0f * fsizex_inv, 10.0f * fsizey_inv, 0.0f);
@@ -354,24 +359,25 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf
float fac = ps->picture->frame / (double)(((PlayAnimPict *)picsbase.last)->frame - ((PlayAnimPict *)picsbase.first)->frame);
fac = 2.0f * fac - 1.0f;
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
-
- glBegin(GL_LINES);
- glVertex2f(fac, -1.0f);
- glVertex2f(fac, 1.0f);
- glEnd();
-
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
+ gpuPushProjectionMatrix();
+ gpuLoadIdentityProjectionMatrix();
+ gpuPushMatrix();
+ gpuLoadIdentity();
+
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ub(0, 255, 0);
+
+ immBegin(GWN_PRIM_LINES, 2);
+ immVertex2f(pos, fac, -1.0f);
+ immVertex2f(pos, fac, 1.0f);
+ immEnd();
+
+ immUnbindProgram();
+
+ gpuPopMatrix();
+ gpuPopProjectionMatrix();
}
GHOST_SwapWindowBuffers(g_WS.ghost_window);
@@ -1255,6 +1261,9 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
//GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
+ /* initialize OpenGL immediate mode */
+ immInit();
+
/* initialize the font */
BLF_init();
ps.fontid = BLF_load_mem("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size);
@@ -1524,7 +1533,11 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
#endif
/* we still miss freeing a lot!,
* but many areas could skip initialization too for anim play */
-
+
+ GPU_shader_free_builtin_shaders();
+
+ immDestroy();
+
BLF_exit();
GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window);
@@ -1537,7 +1550,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
IMB_exit();
BKE_images_exit();
- DAG_exit();
+ DEG_free_node_types();
totblock = MEM_get_memory_blocks_in_use();
if (totblock != 0) {
diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c
index 66ebf18c9e1..c0800705b28 100644
--- a/source/blender/windowmanager/intern/wm_stereo.c
+++ b/source/blender/windowmanager/intern/wm_stereo.c
@@ -52,8 +52,7 @@
#include "ED_screen.h"
-#include "GPU_glew.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -77,54 +76,82 @@ static void wm_method_draw_stereo3d_pageflip(wmWindow *win)
else //STEREO_RIGHT_ID
glDrawBuffer(GL_BACK_RIGHT);
- wm_triple_draw_textures(win, drawdata->triple, 1.0f, false);
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
}
glDrawBuffer(GL_BACK);
}
-static enum eStereo3dInterlaceType interlace_prev_type = -1;
-static char interlace_prev_swap = -1;
+static GPUInterlaceShader interlace_gpu_id_from_type(eStereo3dInterlaceType interlace_type)
+{
+ switch (interlace_type) {
+ case S3D_INTERLACE_ROW:
+ return GPU_SHADER_INTERLACE_ROW;
+ case S3D_INTERLACE_COLUMN:
+ return GPU_SHADER_INTERLACE_COLUMN;
+ case S3D_INTERLACE_CHECKERBOARD:
+ default:
+ return GPU_SHADER_INTERLACE_CHECKER;
+ }
+}
static void wm_method_draw_stereo3d_interlace(wmWindow *win)
{
- wmDrawData *drawdata;
- int view;
- bool flag;
bool swap = (win->stereo3d_format->flag & S3D_INTERLACE_SWAP) != 0;
enum eStereo3dInterlaceType interlace_type = win->stereo3d_format->interlace_type;
- for (view = 0; view < 2; view ++) {
- flag = swap ? !view : view;
- drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE);
- switch (interlace_type) {
- case S3D_INTERLACE_ROW:
- if (flag)
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW_SWAP);
- else
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW);
- break;
- case S3D_INTERLACE_COLUMN:
- if (flag)
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN_SWAP);
- else
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN);
- break;
- case S3D_INTERLACE_CHECKERBOARD:
- default:
- if (flag)
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER_SWAP);
- else
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER);
- break;
- }
+ wmDrawData *drawdata[2];
+ for (int eye = 0; eye < 2; eye++) {
+ int view = swap ? !eye : eye;
+ drawdata[eye] = BLI_findlink(&win->drawdata, (view * 2) + 1);
+ }
+
+ const int sizex = WM_window_pixels_x(win);
+ const int sizey = WM_window_pixels_y(win);
+
+ /* wmOrtho for the screen has this same offset */
+ float ratiox = sizex;
+ float ratioy = sizey;
+ float halfx = GLA_PIXEL_OFS;
+ float halfy = GLA_PIXEL_OFS;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_INTERLACE);
+
+ /* leave GL_TEXTURE0 as the latest bind texture */
+ for (int eye = 1; eye >= 0; eye--) {
+ glActiveTexture(GL_TEXTURE0 + eye);
+ glBindTexture(drawdata[eye]->triple->target, drawdata[eye]->triple->bind);
+ }
- wm_triple_draw_textures(win, drawdata->triple, 1.0f, true);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immUniform1i("image_a", 0);
+ immUniform1i("image_b", 1);
+
+ immUniform1i("interlace_id", interlace_gpu_id_from_type(interlace_type));
+
+ immBegin(GWN_PRIM_TRI_FAN, 4);
+
+ immAttrib2f(texcoord, halfx, halfy);
+ immVertex2f(pos, 0.0f, 0.0f);
+
+ immAttrib2f(texcoord, ratiox + halfx, halfy);
+ immVertex2f(pos, sizex, 0.0f);
+
+ immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy);
+ immVertex2f(pos, sizex, sizey);
+
+ immAttrib2f(texcoord, halfx, ratioy + halfy);
+ immVertex2f(pos, 0.0f, sizey);
+
+ immEnd();
+ immUnbindProgram();
+
+ for (int eye = 0; eye < 2; eye++) {
+ glBindTexture(drawdata[eye]->triple->target, 0);
}
- interlace_prev_type = interlace_type;
- interlace_prev_swap = swap;
}
static void wm_method_draw_stereo3d_anaglyph(wmWindow *win)
@@ -157,7 +184,7 @@ static void wm_method_draw_stereo3d_anaglyph(wmWindow *win)
break;
}
- wm_triple_draw_textures(win, drawdata->triple, 1.0f, false);
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
@@ -172,6 +199,10 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
int soffx;
bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0;
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
for (view = 0; view < 2; view ++) {
drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
triple = drawdata->triple;
@@ -203,26 +234,33 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
halfy /= triple->y;
}
- glEnable(triple->target);
+ /* TODO: if target is always same for both eyes, bind program & set uniform before loop */
+ immBindBuiltinProgram((triple->target == GL_TEXTURE_2D) ? GPU_SHADER_3D_IMAGE_MODULATE_ALPHA : GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA);
+
glBindTexture(triple->target, triple->bind);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- glBegin(GL_QUADS);
- glTexCoord2f(halfx, halfy);
- glVertex2f(soffx, 0);
+ immUniform1f("alpha", 1.0f);
+ immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
- glTexCoord2f(ratiox + halfx, halfy);
- glVertex2f(soffx + (sizex * 0.5f), 0);
+ immBegin(GWN_PRIM_TRI_FAN, 4);
- glTexCoord2f(ratiox + halfx, ratioy + halfy);
- glVertex2f(soffx + (sizex * 0.5f), sizey);
+ immAttrib2f(texcoord, halfx, halfy);
+ immVertex2f(pos, soffx, 0.0f);
- glTexCoord2f(halfx, ratioy + halfy);
- glVertex2f(soffx, sizey);
- glEnd();
+ immAttrib2f(texcoord, ratiox + halfx, halfy);
+ immVertex2f(pos, soffx + (sizex * 0.5f), 0.0f);
+ immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy);
+ immVertex2f(pos, soffx + (sizex * 0.5f), sizey);
+
+ immAttrib2f(texcoord, halfx, ratioy + halfy);
+ immVertex2f(pos, soffx, sizey);
+
+ immEnd();
+
+ /* TODO: if target is always same for both eyes, unbind program & texture target after loop */
glBindTexture(triple->target, 0);
- glDisable(triple->target);
+ immUnbindProgram();
}
}
@@ -234,6 +272,10 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
int view;
int soffy;
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
for (view = 0; view < 2; view ++) {
drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
triple = drawdata->triple;
@@ -262,26 +304,33 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
halfy /= triple->y;
}
- glEnable(triple->target);
+ /* TODO: if target is always same for both eyes, bind program & set uniforms before loop */
+ immBindBuiltinProgram((triple->target == GL_TEXTURE_2D) ? GPU_SHADER_3D_IMAGE_MODULATE_ALPHA : GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA);
+
glBindTexture(triple->target, triple->bind);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- glBegin(GL_QUADS);
- glTexCoord2f(halfx, halfy);
- glVertex2f(0, soffy);
+ immUniform1f("alpha", 1.0f);
+ immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
- glTexCoord2f(ratiox + halfx, halfy);
- glVertex2f(sizex, soffy);
+ immBegin(GWN_PRIM_TRI_FAN, 4);
- glTexCoord2f(ratiox + halfx, ratioy + halfy);
- glVertex2f(sizex, soffy + (sizey * 0.5f));
+ immAttrib2f(texcoord, halfx, halfy);
+ immVertex2f(pos, 0.0f, soffy);
- glTexCoord2f(halfx, ratioy + halfy);
- glVertex2f(0, soffy + (sizey * 0.5f));
- glEnd();
+ immAttrib2f(texcoord, ratiox + halfx, halfy);
+ immVertex2f(pos, sizex, soffy);
+ immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy);
+ immVertex2f(pos, sizex, soffy + (sizey * 0.5f));
+
+ immAttrib2f(texcoord, halfx, ratioy + halfy);
+ immVertex2f(pos, 0.0f, soffy + (sizey * 0.5f));
+
+ immEnd();
+
+ /* TODO: if target is always same for both eyes, unbind program & texture target after loop */
+ immUnbindProgram();
glBindTexture(triple->target, 0);
- glDisable(triple->target);
}
}
@@ -310,9 +359,9 @@ void wm_method_draw_stereo3d(const bContext *UNUSED(C), wmWindow *win)
static bool wm_stereo3d_quadbuffer_supported(void)
{
- int gl_stereo = 0;
- glGetBooleanv(GL_STEREO, (GLboolean *)&gl_stereo);
- return gl_stereo != 0;
+ GLboolean stereo = GL_FALSE;
+ glGetBooleanv(GL_STEREO, &stereo);
+ return stereo == GL_TRUE;
}
static bool wm_stereo3d_is_fullscreen_required(eStereoDisplayMode stereo_display)
@@ -324,7 +373,8 @@ static bool wm_stereo3d_is_fullscreen_required(eStereoDisplayMode stereo_display
bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check)
{
- bScreen *screen = win->screen;
+ const bScreen *screen = WM_window_get_active_screen(win);
+ const Scene *scene = WM_window_get_active_scene(win);
/* some 3d methods change the window arrangement, thus they shouldn't
* toggle on/off just because there is no 3d elements being drawn */
@@ -332,7 +382,7 @@ bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check)
return GHOST_GetWindowState(win->ghostwin) == GHOST_kWindowStateFullScreen;
}
- if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen) == false)) {
+ if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen, scene) == false)) {
return false;
}
@@ -459,7 +509,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op)
prev_display_mode != win_src->stereo3d_format->display_mode)
{
/* in case the hardward supports pageflip but not the display */
- if ((win_dst = wm_window_copy_test(C, win_src))) {
+ if ((win_dst = wm_window_copy_test(C, win_src, false))) {
/* pass */
}
else {
@@ -469,14 +519,16 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op)
}
}
else if (win_src->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) {
- /* ED_screen_duplicate() can't handle other cases yet T44688 */
- if (win_src->screen->state != SCREENNORMAL) {
+ const bScreen *screen = WM_window_get_active_screen(win_src);
+
+ /* ED_workspace_layout_duplicate() can't handle other cases yet T44688 */
+ if (screen->state != SCREENNORMAL) {
BKE_report(op->reports, RPT_ERROR,
"Failed to switch to Time Sequential mode when in fullscreen");
ok = false;
}
/* pageflip requires a new window to be created with the proper OS flags */
- else if ((win_dst = wm_window_copy_test(C, win_src))) {
+ else if ((win_dst = wm_window_copy_test(C, win_src, false))) {
if (wm_stereo3d_quadbuffer_supported()) {
BKE_report(op->reports, RPT_INFO, "Quad-buffer window successfully created");
}
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 458ac4a121a..1a8f71891c0 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -47,8 +47,7 @@
#include "BIF_gl.h"
-#include "GPU_extensions.h"
-#include "GPU_basic_shader.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "wm_subwindow.h"
@@ -142,15 +141,17 @@ void wm_subwindow_origin_get(wmWindow *win, int swinid, int *x, int *y)
static void wm_swin_matrix_get(wmWindow *win, wmSubWindow *swin, float mat[4][4])
{
+ const bScreen *screen = WM_window_get_active_screen(win);
+
/* used by UI, should find a better way to get the matrix there */
- if (swin->swinid == win->screen->mainwin) {
+ if (swin->swinid == screen->mainwin) {
int width, height;
wm_swin_size_get(swin, &width, &height);
orthographic_m4(mat, -GLA_PIXEL_OFS, (float)width - GLA_PIXEL_OFS, -GLA_PIXEL_OFS, (float)height - GLA_PIXEL_OFS, -100, 100);
}
else {
- glGetFloatv(GL_PROJECTION_MATRIX, (float *)mat);
+ gpuGetProjectionMatrix(mat);
}
}
void wm_subwindow_matrix_get(wmWindow *win, int swinid, float mat[4][4])
@@ -216,7 +217,7 @@ int wm_subwindow_open(wmWindow *win, const rcti *winrct, bool activate)
/* extra service */
wm_swin_size_get(swin, &width, &height);
wmOrtho2_pixelspace(width, height);
- glLoadIdentity();
+ gpuLoadIdentity();
}
return swin->swinid;
@@ -322,7 +323,7 @@ void wmSubWindowScissorSet(wmWindow *win, int swinid, const rcti *srct, bool src
glScissor(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height);
wmOrtho2_pixelspace(width, height);
- glLoadIdentity();
+ gpuLoadIdentity();
glFlush();
}
@@ -333,31 +334,13 @@ void wmSubWindowSet(wmWindow *win, int swinid)
wmSubWindowScissorSet(win, swinid, NULL, true);
}
-void wmFrustum(float x1, float x2, float y1, float y2, float n, float f)
-{
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glFrustum(x1, x2, y1, y2, n, f);
- glMatrixMode(GL_MODELVIEW);
-}
-
-void wmOrtho(float x1, float x2, float y1, float y2, float n, float f)
-{
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- glOrtho(x1, x2, y1, y2, n, f);
-
- glMatrixMode(GL_MODELVIEW);
-}
-
void wmOrtho2(float x1, float x2, float y1, float y2)
{
/* prevent opengl from generating errors */
if (x1 == x2) x2 += 1.0f;
if (y1 == y2) y2 += 1.0f;
- wmOrtho(x1, x2, y1, y2, -100, 100);
+ gpuOrtho(x1, x2, y1, y2, -100, 100);
}
static void wmOrtho2_offset(const float x, const float y, const float ofs)
diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c
new file mode 100644
index 00000000000..5e000489ace
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_toolsystem.c
@@ -0,0 +1,107 @@
+/*
+ * ***** 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/windowmanager/intern/wm_toolsystem.c
+ * \ingroup wm
+ *
+ * Experimental tool-system>
+ */
+
+#include <string.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+
+#include "DNA_ID.h"
+#include "DNA_scene_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
+
+#include "BKE_context.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace)
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = bmain->wm.first;
+
+ if (workspace->tool.manipulator_group[0]) {
+ wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(workspace->tool.manipulator_group, false);
+ if (wgt != NULL) {
+ bool found = false;
+
+ /* Check another workspace isn't using this tool. */
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ const WorkSpace *workspace_iter = WM_window_get_active_workspace(win);
+ if (workspace != workspace_iter) {
+ if (STREQ(workspace->tool.manipulator_group, workspace_iter->tool.manipulator_group)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(&wgt->mmap_params);
+ WM_manipulatormaptype_group_unlink(C, bmain, mmap_type, wgt);
+ }
+ }
+ }
+}
+
+void WM_toolsystem_link(bContext *UNUSED(C), WorkSpace *workspace)
+{
+ if (workspace->tool.manipulator_group[0]) {
+ WM_manipulator_group_type_ensure(workspace->tool.manipulator_group);
+ }
+}
+
+void WM_toolsystem_set(bContext *C, const bToolDef *tool)
+{
+ WorkSpace *workspace = CTX_wm_workspace(C);
+
+ WM_toolsystem_unlink(C, workspace);
+
+ workspace->tool.index = tool->index;
+ workspace->tool.spacetype = tool->spacetype;
+
+ if (&workspace->tool != tool) {
+ BLI_strncpy(workspace->tool.keymap, tool->keymap, sizeof(tool->keymap));
+ BLI_strncpy(workspace->tool.manipulator_group, tool->manipulator_group, sizeof(tool->manipulator_group));
+ workspace->tool.spacetype = tool->spacetype;
+ }
+
+ WM_toolsystem_link(C, workspace);
+}
+
+void WM_toolsystem_init(bContext *C)
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = bmain->wm.first;
+
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ WM_toolsystem_link(C, workspace);
+ }
+}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 79078b321da..0e07b66996d 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -38,6 +38,7 @@
#include "DNA_listBase.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "MEM_guardedalloc.h"
@@ -51,12 +52,16 @@
#include "BKE_blender.h"
#include "BKE_context.h"
+#include "BKE_icons.h"
#include "BKE_library.h"
#include "BKE_global.h"
#include "BKE_main.h"
-
+#include "BKE_screen.h"
+#include "BKE_workspace.h"
#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -66,19 +71,23 @@
#include "wm_subwindow.h"
#include "wm_event_system.h"
+#include "ED_scene.h"
#include "ED_screen.h"
#include "ED_fileselect.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "PIL_time.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_init_exit.h"
-#include "GPU_glew.h"
+#include "GPU_immediate.h"
#include "BLF_api.h"
+#include "UI_resources.h"
+
/* for assert */
#ifndef NDEBUG
# include "BLI_threads.h"
@@ -213,6 +222,7 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
wm_ghostwindow_destroy(win);
+ BKE_workspace_instance_hook_free(G.main, win->workspace_hook);
MEM_freeN(win->stereo3d_format);
MEM_freeN(win);
@@ -233,35 +243,57 @@ static int find_free_winid(wmWindowManager *wm)
/* don't change context itself */
wmWindow *wm_window_new(bContext *C)
{
+ Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = MEM_callocN(sizeof(wmWindow), "window");
-
+
BLI_addtail(&wm->windows, win);
win->winid = find_free_winid(wm);
win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)");
+ win->workspace_hook = BKE_workspace_instance_hook_create(bmain);
return win;
}
+/**
+ * A higher level version of copy that tests the new window can be added.
+ */
+static wmWindow *wm_window_new_test(bContext *C)
+{
+ wmWindow *win = wm_window_new(C);
+
+ WM_check(C);
+
+ if (win->ghostwin) {
+ WM_event_add_notifier(C, NC_WINDOW | NA_ADDED, NULL);
+ return win;
+ }
+ else {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wm_window_close(C, wm, win);
+ return NULL;
+ }
+}
/* part of wm_window.c api */
-wmWindow *wm_window_copy(bContext *C, wmWindow *win_src)
+wmWindow *wm_window_copy(bContext *C, wmWindow *win_src, const bool duplicate_layout)
{
wmWindow *win_dst = wm_window_new(C);
-
+ WorkSpace *workspace = WM_window_get_active_workspace(win_src);
+ WorkSpaceLayout *layout_old = WM_window_get_active_layout(win_src);
+ Scene *scene = WM_window_get_active_scene(win_src);
+ WorkSpaceLayout *layout_new;
+
win_dst->posx = win_src->posx + 10;
win_dst->posy = win_src->posy;
win_dst->sizex = win_src->sizex;
win_dst->sizey = win_src->sizey;
-
- /* duplicate assigns to window */
- win_dst->screen = ED_screen_duplicate(win_dst, win_src->screen);
- BLI_strncpy(win_dst->screenname, win_dst->screen->id.name + 2, sizeof(win_dst->screenname));
- win_dst->screen->winid = win_dst->winid;
- win_dst->screen->do_refresh = true;
- win_dst->screen->do_draw = true;
+ win_dst->scene = scene;
+ WM_window_set_active_workspace(win_dst, workspace);
+ layout_new = duplicate_layout ? ED_workspace_layout_duplicate(workspace, layout_old, win_dst) : layout_old;
+ WM_window_set_active_layout(win_dst, workspace, layout_new);
win_dst->drawmethod = U.wmdrawmethod;
@@ -276,12 +308,12 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *win_src)
* A higher level version of copy that tests the new window can be added.
* (called from the operator directly)
*/
-wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src)
+wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src, const bool duplicate_layout)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win_dst;
- win_dst = wm_window_copy(C, win_src);
+ win_dst = wm_window_copy(C, win_src, duplicate_layout);
WM_check(C);
@@ -305,7 +337,7 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
for (tmpwin = wm->windows.first; tmpwin; tmpwin = tmpwin->next) {
if (tmpwin == win)
continue;
- if (tmpwin->screen->temp == 0)
+ if (WM_window_is_temp_screen(tmpwin) == false)
break;
}
@@ -324,8 +356,10 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
WM_exit(C);
}
else {
- bScreen *screen = win->screen;
-
+ bScreen *screen = WM_window_get_active_screen(win);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ WorkSpaceLayout *layout = BKE_workspace_active_layout_get(win->workspace_hook);
+
BLI_remlink(&wm->windows, win);
wm_draw_window_clear(win);
@@ -336,8 +370,8 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
/* for regular use this will _never_ be NULL,
* however we may be freeing an improperly initialized window. */
- if (win->screen) {
- ED_screen_exit(C, win, win->screen);
+ if (screen) {
+ ED_screen_exit(C, win, screen);
}
wm_window_free(C, wm, win);
@@ -345,14 +379,16 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
/* if temp screen, delete it after window free (it stops jobs that can access it) */
if (screen && screen->temp) {
Main *bmain = CTX_data_main(C);
- BKE_libblock_free(bmain, screen);
+
+ BLI_assert(BKE_workspace_layout_screen_get(layout) == screen);
+ BKE_workspace_layout_remove(bmain, workspace, layout);
}
- }
+ }
}
void wm_window_title(wmWindowManager *wm, wmWindow *win)
{
- if (win->screen && win->screen->temp) {
+ if (WM_window_is_temp_screen(win)) {
/* nothing to do for 'temp' windows,
* because WM_window_open_temp always sets window title */
}
@@ -658,8 +694,10 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect)
*/
wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, int type)
{
+ Main *bmain = CTX_data_main(C);
wmWindow *win_prev = CTX_wm_window(C);
wmWindow *win;
+ bScreen *screen;
ScrArea *sa;
Scene *scene = CTX_data_scene(C);
const char *title;
@@ -683,7 +721,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i
/* test if we have a temp screen already */
for (win = CTX_wm_manager(C)->windows.first; win; win = win->next)
- if (win->screen->temp)
+ if (WM_window_is_temp_screen(win))
break;
/* add new window? */
@@ -694,6 +732,8 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i
win->posy = rect.ymin;
}
+ screen = WM_window_get_active_screen(win);
+
win->sizex = BLI_rcti_size_x(&rect);
win->sizey = BLI_rcti_size_y(&rect);
@@ -701,19 +741,27 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i
wm_window_set_size(win, win->sizex, win->sizey);
wm_window_raise(win);
}
-
- if (win->screen == NULL) {
- /* add new screen */
- win->screen = ED_screen_add(win, scene, "temp");
+
+ if (WM_window_get_active_workspace(win) == NULL) {
+ WorkSpace *workspace = WM_window_get_active_workspace(win_prev);
+ WM_window_set_active_workspace(win, workspace);
}
- else {
- /* switch scene for rendering */
- if (win->screen->scene != scene)
- ED_screen_set_scene(C, win->screen, scene);
+
+ if (screen == NULL) {
+ /* add new screen layout */
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ WorkSpaceLayout *layout = ED_workspace_layout_add(workspace, win, "temp");
+
+ screen = BKE_workspace_layout_screen_get(layout);
+ WM_window_set_active_layout(win, workspace, layout);
}
- win->screen->temp = 1;
-
+ if (WM_window_get_active_scene(win) != scene) {
+ WM_window_change_active_scene(bmain, C, win, scene);
+ }
+
+ screen->temp = 1;
+
/* make window active, and validate/resize */
CTX_wm_window_set(C, win);
WM_check(C);
@@ -725,7 +773,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i
*/
/* ensure it shows the right spacetype editor */
- sa = win->screen->areabase.first;
+ sa = screen->areabase.first;
CTX_wm_area_set(C, sa);
if (type == WM_WINDOW_RENDER) {
@@ -735,7 +783,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i
ED_area_newspace(C, sa, SPACE_USERPREF, false);
}
- ED_screen_set(C, win->screen);
+ ED_screen_change(C, screen);
ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */
if (sa->spacetype == SPACE_IMAGE)
@@ -771,17 +819,107 @@ int wm_window_close_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-/* operator callback */
-int wm_window_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
+static WorkSpaceLayout *wm_window_new_find_layout(wmOperator *op, WorkSpace *workspace)
+{
+ ListBase *listbase = BKE_workspace_layouts_get(workspace);
+ const int layout_id = RNA_enum_get(op->ptr, "screen");
+ int i = 0;
+
+ for (WorkSpaceLayout *layout = listbase->first; layout; layout = layout->next) {
+ if (i++ == layout_id) {
+ return layout;
+ }
+ }
+
+ BLI_assert(0);
+ return NULL;
+}
+
+/* new window operator callback */
+int wm_window_new_exec(bContext *C, wmOperator *op)
{
wmWindow *win_src = CTX_wm_window(C);
- bool ok;
+ WorkSpace *workspace = WM_window_get_active_workspace(win_src);
+ WorkSpaceLayout *layout_new = wm_window_new_find_layout(op, workspace);
+ bScreen *screen_new = BKE_workspace_layout_screen_get(layout_new);
+ wmWindow *win_dst;
- ok = (wm_window_copy_test(C, win_src) != NULL);
+ if ((win_dst = wm_window_new_test(C))) {
+ if (screen_new->winid) {
+ /* layout/screen is already used, duplicate it */
+ layout_new = ED_workspace_layout_duplicate(workspace, layout_new, win_dst);
+ screen_new = BKE_workspace_layout_screen_get(layout_new);
+ }
+ /* New window with a different screen but same workspace */
+ WM_window_set_active_workspace(win_dst, workspace);
+ WM_window_set_active_screen(win_dst, workspace, screen_new);
+ win_dst->scene = win_src->scene;
+ screen_new->winid = win_dst->winid;
+ CTX_wm_window_set(C, win_dst);
+ ED_screen_refresh(CTX_wm_manager(C), win_dst);
+ }
- return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (win_dst != NULL) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
+int wm_window_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ wmWindow *win = CTX_wm_window(C);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ ListBase *listbase = BKE_workspace_layouts_get(workspace);
+
+ if (BLI_listbase_count_ex(listbase, 2) == 1) {
+ RNA_enum_set(op->ptr, "screen", 0);
+ return wm_window_new_exec(C, op);
+ }
+ else {
+ return WM_enum_search_invoke_previews(C, op, 6, 2);
+ }
+}
+
+const EnumPropertyItem *wm_window_new_screen_itemf(
+ bContext *C, struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ if (C == NULL) {
+ return DummyRNA_NULL_items;
+ }
+ wmWindow *win = CTX_wm_window(C);
+ WorkSpace *workspace = WM_window_get_active_workspace(win);
+ ListBase *listbase = BKE_workspace_layouts_get(workspace);
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int value = 0, totitem = 0;
+ int count_act_screens = 0;
+ /* XXX setting max number of windows to 20. We'd need support
+ * for dynamic strings in EnumPropertyItem.name to avoid this. */
+ static char active_screens[20][MAX_NAME + 12];
+
+ for (WorkSpaceLayout *layout = listbase->first; layout; layout = layout->next) {
+ bScreen *screen = BKE_workspace_layout_screen_get(layout);
+ const char *layout_name = BKE_workspace_layout_name_get(layout);
+
+ if (screen->winid) {
+ BLI_snprintf(active_screens[count_act_screens], sizeof(*active_screens), "%s (Duplicate)", layout_name);
+ tmp.name = active_screens[count_act_screens++];
+ }
+ else {
+ tmp.name = layout_name;
+ }
+
+ tmp.value = value;
+ tmp.identifier = layout_name;
+ UI_id_icon_render(C, CTX_data_scene(C), &screen->id, true, false);
+ tmp.icon = BKE_icon_id_ensure(&screen->id);
+
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ value++;
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
/* fullscreen operator callback */
int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op))
@@ -881,8 +1019,11 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
if (G.debug & G_DEBUG_EVENTS) {
printf("%s: set drawable %d\n", __func__, win->winid);
}
+
+ immDeactivate();
GHOST_ActivateWindowDrawingContext(win->ghostwin);
-
+ immActivate();
+
/* this can change per window */
WM_window_set_dpi(win);
}
@@ -907,7 +1048,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
/* Ghost now can call this function for life resizes, but it should return if WM didn't initialize yet.
* Can happen on file read (especially full size window) */
- if ((wm->initialized & WM_INIT_WINDOW) == 0) {
+ if ((wm->initialized & WM_WINDOW_IS_INITIALIZED) == 0) {
return 1;
}
if (!ghostwin) {
@@ -1081,7 +1222,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
/* stop screencast if resize */
if (type == GHOST_kEventWindowSize) {
- WM_jobs_stop(wm, win->screen, NULL);
+ WM_jobs_stop(wm, WM_window_get_active_screen(win), NULL);
}
WM_window_set_dpi(win);
@@ -1116,6 +1257,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
win->posx != posx ||
win->posy != posy)
{
+ const bScreen *screen = WM_window_get_active_screen(win);
+
win->sizex = sizex;
win->sizey = sizey;
win->posx = posx;
@@ -1152,6 +1295,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
wm_window_make_drawable(wm, win);
wm_draw_window_clear(win);
+ BKE_icon_changed(screen->id.icon_id);
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL);
@@ -1263,6 +1407,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
WM_window_set_dpi(win);
if (U.pixelsize != prev_pixelsize) {
+ BKE_icon_changed(WM_window_get_active_screen(win)->id.icon_id);
+
// close all popups since they are positioned with the pixel
// size baked in and it's difficult to correct them
wmWindow *oldWindow = CTX_wm_window(C);
@@ -1768,6 +1914,96 @@ bool WM_window_is_fullscreen(wmWindow *win)
return win->windowstate == GHOST_kWindowStateFullScreen;
}
+/**
+ * Some editor data may need to be synced with scene data (3D View camera and layers).
+ * This function ensures data is synced for editors in visible workspaces and their visible layouts.
+ */
+void WM_windows_scene_data_sync(const ListBase *win_lb, Scene *scene)
+{
+ for (wmWindow *win = win_lb->first; win; win = win->next) {
+ if (WM_window_get_active_scene(win) == scene) {
+ ED_workspace_scene_data_sync(win->workspace_hook, scene);
+ }
+ }
+}
+
+Scene *WM_windows_scene_get_from_screen(const wmWindowManager *wm, const bScreen *screen)
+{
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (WM_window_get_active_screen(win) == screen) {
+ return WM_window_get_active_scene(win);
+ }
+ }
+
+ return NULL;
+}
+
+WorkSpace *WM_windows_workspace_get_from_screen(const wmWindowManager *wm, const bScreen *screen)
+{
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (WM_window_get_active_screen(win) == screen) {
+ return WM_window_get_active_workspace(win);
+ }
+ }
+ return NULL;
+}
+
+Scene *WM_window_get_active_scene(const wmWindow *win)
+{
+ return win->scene;
+}
+
+/**
+ * \warning Only call outside of area/region loops
+ */
+void WM_window_change_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene *scene_new)
+{
+ const bScreen *screen = WM_window_get_active_screen(win);
+
+ ED_scene_exit(C);
+ win->scene = scene_new;
+ ED_scene_changed_update(bmain, C, scene_new, screen);
+}
+
+WorkSpace *WM_window_get_active_workspace(const wmWindow *win)
+{
+ return BKE_workspace_active_get(win->workspace_hook);
+}
+void WM_window_set_active_workspace(wmWindow *win, WorkSpace *workspace)
+{
+ BKE_workspace_active_set(win->workspace_hook, workspace);
+}
+
+WorkSpaceLayout *WM_window_get_active_layout(const wmWindow *win)
+{
+ const WorkSpace *workspace = WM_window_get_active_workspace(win);
+ return (LIKELY(workspace != NULL) ? BKE_workspace_active_layout_get(win->workspace_hook) : NULL);
+}
+void WM_window_set_active_layout(wmWindow *win, WorkSpace *workspace, WorkSpaceLayout *layout)
+{
+ BKE_workspace_hook_layout_for_workspace_set(win->workspace_hook, workspace, layout);
+}
+
+/**
+ * Get the active screen of the active workspace in \a win.
+ */
+bScreen *WM_window_get_active_screen(const wmWindow *win)
+{
+ const WorkSpace *workspace = WM_window_get_active_workspace(win);
+ /* May be NULL in rare cases like closing Blender */
+ return (LIKELY(workspace != NULL) ? BKE_workspace_active_screen_get(win->workspace_hook) : NULL);
+}
+void WM_window_set_active_screen(wmWindow *win, WorkSpace *workspace, bScreen *screen)
+{
+ BKE_workspace_active_screen_set(win->workspace_hook, workspace, screen);
+}
+
+bool WM_window_is_temp_screen(const wmWindow *win)
+{
+ const bScreen *screen = WM_window_get_active_screen(win);
+ return (screen && screen->temp != 0);
+}
+
#ifdef WITH_INPUT_IME
/* note: keep in mind wm_window_IME_begin is also used to reposition the IME window */
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_api.h b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
new file mode 100644
index 00000000000..9214bccb6a0
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
@@ -0,0 +1,331 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/WM_manipulator_api.h
+ * \ingroup wm
+ *
+ * \name Manipulator API
+ * \brief API for external use of wmManipulator types.
+ *
+ * Only included in WM_api.h
+ */
+
+
+#ifndef __WM_MANIPULATOR_API_H__
+#define __WM_MANIPULATOR_API_H__
+
+struct ARegion;
+struct GHashIterator;
+struct IDProperty;
+struct Main;
+struct PropertyRNA;
+struct wmKeyConfig;
+struct wmManipulator;
+struct wmManipulatorProperty;
+struct wmManipulatorPropertyType;
+struct wmManipulatorType;
+struct wmManipulatorGroup;
+struct wmManipulatorGroupType;
+struct wmManipulatorMap;
+struct wmManipulatorMapType;
+struct wmManipulatorMapType_Params;
+struct wmMsgSubscribeKey;
+struct wmMsgSubscribeValue;
+
+#include "wm_manipulator_fn.h"
+
+/* -------------------------------------------------------------------- */
+/* wmManipulator */
+
+struct wmManipulator *WM_manipulator_new_ptr(
+ const struct wmManipulatorType *wt, struct wmManipulatorGroup *mgroup,
+ struct PointerRNA *properties);
+struct wmManipulator *WM_manipulator_new(
+ const char *idname, struct wmManipulatorGroup *mgroup,
+ struct PointerRNA *properties);
+void WM_manipulator_free(struct wmManipulator *mpr);
+void WM_manipulator_unlink(
+ ListBase *manipulatorlist, struct wmManipulatorMap *mmap, struct wmManipulator *mpr,
+ struct bContext *C);
+
+void WM_manipulator_name_set(struct wmManipulatorGroup *mgroup, struct wmManipulator *mpr, const char *name);
+
+bool WM_manipulator_select_unlink(struct wmManipulatorMap *mmap, struct wmManipulator *mpr);
+bool WM_manipulator_select_set(struct wmManipulatorMap *mmap, struct wmManipulator *mpr, bool select);
+void WM_manipulator_highlight_set(struct wmManipulatorMap *mmap, struct wmManipulator *mpr);
+
+struct wmManipulatorOpElem *WM_manipulator_operator_get(
+ struct wmManipulator *mpr, int part_index);
+struct PointerRNA *WM_manipulator_operator_set(
+ struct wmManipulator *mpr, int part_index,
+ struct wmOperatorType *ot, struct IDProperty *properties);
+
+/* callbacks */
+void WM_manipulator_set_fn_custom_modal(struct wmManipulator *mpr, wmManipulatorFnModal fn);
+
+void WM_manipulator_set_matrix_location(
+ struct wmManipulator *mpr, const float origin[3]);
+void WM_manipulator_set_matrix_rotation_from_z_axis(
+ struct wmManipulator *mpr, const float z_axis[3]);
+void WM_manipulator_set_matrix_rotation_from_yz_axis(
+ struct wmManipulator *mpr, const float y_axis[3], const float z_axis[3]);
+
+void WM_manipulator_set_matrix_offset_location(
+ struct wmManipulator *mpr, const float origin[3]);
+void WM_manipulator_set_matrix_offset_rotation_from_z_axis(
+ struct wmManipulator *mpr, const float z_axis[3]);
+void WM_manipulator_set_matrix_offset_rotation_from_yz_axis(
+ struct wmManipulator *mpr, const float y_axis[3], const float z_axis[3]);
+
+void WM_manipulator_set_flag(struct wmManipulator *mpr, const int flag, const bool enable);
+void WM_manipulator_set_scale(struct wmManipulator *mpr, float scale);
+void WM_manipulator_set_line_width(struct wmManipulator *mpr, const float line_width);
+
+void WM_manipulator_get_color(const struct wmManipulator *mpr, float color[4]);
+void WM_manipulator_set_color(struct wmManipulator *mpr, const float color[4]);
+void WM_manipulator_get_color_highlight(const struct wmManipulator *mpr, float color_hi[4]);
+void WM_manipulator_set_color_highlight(struct wmManipulator *mpr, const float color[4]);
+
+/**
+ * Leaving values NULL use values from #wmManipulator.
+ */
+struct WM_ManipulatorMatrixParams {
+ const float(*matrix_space)[4];
+ const float(*matrix_basis)[4];
+ const float(*matrix_offset)[4];
+ const float *scale_final;
+};
+
+void WM_manipulator_calc_matrix_final_params(
+ const struct wmManipulator *mpr, const struct WM_ManipulatorMatrixParams *params,
+ float r_mat[4][4]);
+
+void WM_manipulator_calc_matrix_final(const struct wmManipulator *mpr, float r_mat[4][4]);
+
+/* properties */
+void WM_manipulator_properties_create_ptr(struct PointerRNA *ptr, struct wmManipulatorType *wt);
+void WM_manipulator_properties_create(struct PointerRNA *ptr, const char *opstring);
+void WM_manipulator_properties_alloc(struct PointerRNA **ptr, struct IDProperty **properties, const char *wtstring);
+void WM_manipulator_properties_sanitize(struct PointerRNA *ptr, const bool no_context);
+bool WM_manipulator_properties_default(struct PointerRNA *ptr, const bool do_update);
+void WM_manipulator_properties_reset(struct wmManipulator *op);
+void WM_manipulator_properties_clear(struct PointerRNA *ptr);
+void WM_manipulator_properties_free(struct PointerRNA *ptr);
+
+
+/* wm_manipulator_type.c */
+const struct wmManipulatorType *WM_manipulatortype_find(const char *idname, bool quiet);
+void WM_manipulatortype_append(void (*wtfunc)(struct wmManipulatorType *));
+void WM_manipulatortype_append_ptr(void (*mnpfunc)(struct wmManipulatorType *, void *), void *userdata);
+bool WM_manipulatortype_remove(struct bContext *C, struct Main *bmain, const char *idname);
+void WM_manipulatortype_remove_ptr(struct bContext *C, struct Main *bmain, struct wmManipulatorType *wt);
+void WM_manipulatortype_iter(struct GHashIterator *ghi);
+
+/* wm_manipulator_group_type.c */
+struct wmManipulatorGroupType *WM_manipulatorgrouptype_find(const char *idname, bool quiet);
+struct wmManipulatorGroupType *WM_manipulatorgrouptype_append(void (*wtfunc)(struct wmManipulatorGroupType *));
+struct wmManipulatorGroupType *WM_manipulatorgrouptype_append_ptr(void (*mnpfunc)(struct wmManipulatorGroupType *, void *), void *userdata);
+bool WM_manipulatorgrouptype_free(const char *idname);
+void WM_manipulatorgrouptype_free_ptr(struct wmManipulatorGroupType *wt);
+void WM_manipulatorgrouptype_iter(struct GHashIterator *ghi);
+
+struct wmManipulatorGroupTypeRef *WM_manipulatorgrouptype_append_and_link(
+ struct wmManipulatorMapType *mmap_type,
+ void (*wtfunc)(struct wmManipulatorGroupType *));
+
+/* wm_manipulator_map.c */
+
+/* Dynamic Updates (for RNA runtime registration) */
+void WM_manipulatorconfig_update_tag_init(struct wmManipulatorMapType *mmap_type, struct wmManipulatorGroupType *wgt);
+void WM_manipulatorconfig_update_tag_remove(struct wmManipulatorMapType *mmap_type, struct wmManipulatorGroupType *wgt);
+void WM_manipulatorconfig_update(struct Main *bmain);
+
+
+/* wm_maniulator_target_props.c */
+struct wmManipulatorProperty *WM_manipulator_target_property_array(struct wmManipulator *mpr);
+struct wmManipulatorProperty *WM_manipulator_target_property_at_index(
+ struct wmManipulator *mpr, int index);
+struct wmManipulatorProperty *WM_manipulator_target_property_find(
+ struct wmManipulator *mpr, const char *idname);
+
+void WM_manipulator_target_property_def_rna_ptr(
+ struct wmManipulator *mpr, const struct wmManipulatorPropertyType *mpr_prop_type,
+ struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
+void WM_manipulator_target_property_def_rna(
+ struct wmManipulator *mpr, const char *idname,
+ struct PointerRNA *ptr, const char *propname, int index);
+
+void WM_manipulator_target_property_def_func_ptr(
+ struct wmManipulator *mpr, const struct wmManipulatorPropertyType *mpr_prop_type,
+ const struct wmManipulatorPropertyFnParams *params);
+void WM_manipulator_target_property_def_func(
+ struct wmManipulator *mpr, const char *idname,
+ const struct wmManipulatorPropertyFnParams *params);
+
+void WM_manipulator_target_property_clear_rna_ptr(
+ struct wmManipulator *mpr, const struct wmManipulatorPropertyType *mpr_prop_type);
+void WM_manipulator_target_property_clear_rna(
+ struct wmManipulator *mpr, const char *idname);
+
+bool WM_manipulator_target_property_is_valid_any(struct wmManipulator *mpr);
+bool WM_manipulator_target_property_is_valid(
+ const struct wmManipulatorProperty *mpr_prop);
+float WM_manipulator_target_property_value_get(
+ const struct wmManipulator *mpr, struct wmManipulatorProperty *mpr_prop);
+void WM_manipulator_target_property_value_set(
+ struct bContext *C, const struct wmManipulator *mpr, struct wmManipulatorProperty *mpr_prop,
+ const float value);
+
+void WM_manipulator_target_property_value_get_array(
+ const struct wmManipulator *mpr, struct wmManipulatorProperty *mpr_prop,
+ float *value);
+void WM_manipulator_target_property_value_set_array(
+ struct bContext *C, const struct wmManipulator *mpr, struct wmManipulatorProperty *mpr_prop,
+ const float *value);
+
+bool WM_manipulator_target_property_range_get(
+ const struct wmManipulator *mpr, struct wmManipulatorProperty *mpr_prop,
+ float range[2]);
+
+int WM_manipulator_target_property_array_length(
+ const struct wmManipulator *mpr, struct wmManipulatorProperty *mpr_prop);
+
+/* definitions */
+const struct wmManipulatorPropertyType *WM_manipulatortype_target_property_find(
+ const struct wmManipulatorType *wt, const char *idname);
+void WM_manipulatortype_target_property_def(
+ struct wmManipulatorType *wt, const char *idname, int data_type, int array_length);
+
+/* utilities */
+void WM_manipulator_do_msg_notify_tag_refresh(
+ struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val);
+void WM_manipulator_target_property_subscribe_all(
+ struct wmManipulator *mpr, struct wmMsgBus *mbus, struct ARegion *ar);
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorGroup */
+
+/* Callbacks for 'wmManipulatorGroupType.setup_keymap' */
+struct wmKeyMap *WM_manipulatorgroup_keymap_common(
+ const struct wmManipulatorGroupType *wgt, struct wmKeyConfig *config);
+struct wmKeyMap *WM_manipulatorgroup_keymap_common_select(
+ const struct wmManipulatorGroupType *wgt, struct wmKeyConfig *config);
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorMap */
+
+struct wmManipulatorMap *WM_manipulatormap_new_from_type(
+ const struct wmManipulatorMapType_Params *mmap_params);
+const struct ListBase *WM_manipulatormap_group_list(struct wmManipulatorMap *mmap);
+struct wmManipulatorGroup *WM_manipulatormap_group_find(
+ struct wmManipulatorMap *mmap,
+ const char *idname);
+struct wmManipulatorGroup *WM_manipulatormap_group_find_ptr(
+ struct wmManipulatorMap *mmap,
+ const struct wmManipulatorGroupType *wgt);
+void WM_manipulatormap_tag_refresh(struct wmManipulatorMap *mmap);
+void WM_manipulatormap_draw(
+ struct wmManipulatorMap *mmap, const struct bContext *C, const eWM_ManipulatorMapDrawStep drawstep);
+void WM_manipulatormap_add_handlers(struct ARegion *ar, struct wmManipulatorMap *mmap);
+bool WM_manipulatormap_select_all(struct bContext *C, struct wmManipulatorMap *mmap, const int action);
+bool WM_manipulatormap_cursor_set(const struct wmManipulatorMap *mmap, struct wmWindow *win);
+void WM_manipulatormap_message_subscribe(
+ struct bContext *C, struct wmManipulatorMap *mmap, struct ARegion *ar, struct wmMsgBus *mbus);
+bool WM_manipulatormap_is_any_selected(const struct wmManipulatorMap *mmap);
+bool WM_manipulatormap_minmax(
+ const struct wmManipulatorMap *mmap, bool use_hidden, bool use_select,
+ float r_min[3], float r_max[3]);
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorMapType */
+
+struct wmManipulatorMapType *WM_manipulatormaptype_find(
+ const struct wmManipulatorMapType_Params *mmap_params);
+struct wmManipulatorMapType *WM_manipulatormaptype_ensure(
+ const struct wmManipulatorMapType_Params *mmap_params);
+
+struct wmManipulatorGroupTypeRef *WM_manipulatormaptype_group_find(
+ struct wmManipulatorMapType *mmap_type,
+ const char *idname);
+struct wmManipulatorGroupTypeRef *WM_manipulatormaptype_group_find_ptr(
+ struct wmManipulatorMapType *mmap_type,
+ const struct wmManipulatorGroupType *wgt);
+struct wmManipulatorGroupTypeRef *WM_manipulatormaptype_group_link(
+ struct wmManipulatorMapType *mmap_type,
+ const char *idname);
+struct wmManipulatorGroupTypeRef *WM_manipulatormaptype_group_link_ptr(
+ struct wmManipulatorMapType *mmap_type,
+ struct wmManipulatorGroupType *wgt);
+
+void WM_manipulatormaptype_group_init_runtime_keymap(
+ const struct Main *bmain,
+ struct wmManipulatorGroupType *wgt);
+void WM_manipulatormaptype_group_init_runtime(
+ const struct Main *bmain, struct wmManipulatorMapType *mmap_type,
+ struct wmManipulatorGroupType *wgt);
+void WM_manipulatormaptype_group_unlink(
+ struct bContext *C, struct Main *bmain, struct wmManipulatorMapType *mmap_type,
+ const struct wmManipulatorGroupType *wgt);
+
+void WM_manipulatormaptype_group_free(struct wmManipulatorGroupTypeRef *wgt);
+
+/* -------------------------------------------------------------------- */
+/* ManipulatorGroup */
+
+/* Add/Ensure/Remove (High level API) */
+
+void WM_manipulator_group_type_add_ptr_ex(
+ struct wmManipulatorGroupType *wgt,
+ struct wmManipulatorMapType *mmap_type);
+void WM_manipulator_group_type_add_ptr(
+ struct wmManipulatorGroupType *wgt);
+void WM_manipulator_group_type_add(const char *idname);
+
+void WM_manipulator_group_type_ensure_ptr_ex(
+ struct wmManipulatorGroupType *wgt,
+ struct wmManipulatorMapType *mmap_type);
+void WM_manipulator_group_type_ensure_ptr(
+ struct wmManipulatorGroupType *wgt);
+void WM_manipulator_group_type_ensure(const char *idname);
+
+void WM_manipulator_group_type_remove_ptr_ex(
+ struct Main *bmain, struct wmManipulatorGroupType *wgt,
+ struct wmManipulatorMapType *mmap_type);
+void WM_manipulator_group_type_remove_ptr(
+ struct Main *bmain, struct wmManipulatorGroupType *wgt);
+void WM_manipulator_group_type_remove(struct Main *bmain, const char *idname);
+
+void WM_manipulator_group_type_unlink_delayed_ptr_ex(
+ struct wmManipulatorGroupType *wgt,
+ struct wmManipulatorMapType *mmap_type);
+void WM_manipulator_group_type_unlink_delayed_ptr(
+ struct wmManipulatorGroupType *wgt);
+void WM_manipulator_group_type_unlink_delayed(const char *idname);
+
+/* Utilities */
+void WM_manipulator_group_type_is_any_selected(const char *idname);
+
+#endif /* __WM_MANIPULATOR_API_H__ */
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_types.h b/source/blender/windowmanager/manipulators/WM_manipulator_types.h
new file mode 100644
index 00000000000..5fa89b8d35f
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_types.h
@@ -0,0 +1,408 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/WM_manipulator_types.h
+ * \ingroup wm
+ *
+ * \name Manipulator Types
+ * \brief Manipulator defines for external use.
+ *
+ * Only included in WM_types.h and lower level files.
+ */
+
+
+#ifndef __WM_MANIPULATOR_TYPES_H__
+#define __WM_MANIPULATOR_TYPES_H__
+
+#include "BLI_compiler_attrs.h"
+
+struct wmManipulatorMapType;
+struct wmManipulatorGroupType;
+struct wmManipulatorGroup;
+struct wmManipulator;
+struct wmManipulatorProperty;
+struct wmKeyConfig;
+
+#include "DNA_listBase.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Enum Typedef's */
+
+
+/**
+ * #wmManipulator.state
+ */
+typedef enum eWM_ManipulatorState {
+ WM_MANIPULATOR_STATE_HIGHLIGHT = (1 << 0), /* while hovered */
+ WM_MANIPULATOR_STATE_MODAL = (1 << 1), /* while dragging */
+ WM_MANIPULATOR_STATE_SELECT = (1 << 2),
+} eWM_ManipulatorState;
+
+
+/**
+ * #wmManipulator.flag
+ * Flags for individual manipulators.
+ */
+typedef enum eWM_ManipulatorFlag {
+ WM_MANIPULATOR_DRAW_HOVER = (1 << 0), /* draw *only* while hovering */
+ WM_MANIPULATOR_DRAW_MODAL = (1 << 1), /* draw while dragging */
+ WM_MANIPULATOR_DRAW_VALUE = (1 << 2), /* draw an indicator for the current value while dragging */
+ WM_MANIPULATOR_HIDDEN = (1 << 3),
+ /**
+ * When set 'scale_final' value also scales the offset.
+ * Use when offset is to avoid screen-space overlap instead of absolute positioning. */
+ WM_MANIPULATOR_DRAW_OFFSET_SCALE = (1 << 4),
+ /**
+ * User should still use 'scale_final' for any handles and UI elements.
+ * This simply skips scale when calculating the final matrix.
+ * Needed when the manipulator needs to align with the interface underneath it. */
+ WM_MANIPULATOR_DRAW_NO_SCALE = (1 << 5),
+} eWM_ManipulatorFlag;
+
+/**
+ * #wmManipulatorGroupType.flag
+ * Flags that influence the behavior of all manipulators in the group.
+ */
+typedef enum eWM_ManipulatorGroupTypeFlag {
+ /* Mark manipulator-group as being 3D */
+ WM_MANIPULATORGROUPTYPE_3D = (1 << 0),
+ /* Scale manipulators as 3D object that respects zoom (otherwise zoom independent draw size).
+ * note: currently only for 3D views, 2D support needs adding. */
+ WM_MANIPULATORGROUPTYPE_SCALE = (1 << 1),
+ /* Manipulators can be depth culled with scene objects (covered by other geometry - TODO) */
+ WM_MANIPULATORGROUPTYPE_DEPTH_3D = (1 << 2),
+ /* Manipulators can be selected */
+ WM_MANIPULATORGROUPTYPE_SELECT = (1 << 3),
+ /* The manipulator group is to be kept (not removed on loading a new file for eg). */
+ WM_MANIPULATORGROUPTYPE_PERSISTENT = (1 << 4),
+ /* Show all other manipulators when interacting. */
+ WM_MANIPULATORGROUPTYPE_DRAW_MODAL_ALL = (1 << 5),
+} eWM_ManipulatorGroupTypeFlag;
+
+
+/**
+ * #wmManipulatorGroup.init_flag
+ */
+typedef enum eWM_ManipulatorGroupInitFlag {
+ /* mgroup has been initialized */
+ WM_MANIPULATORGROUP_INIT_SETUP = (1 << 0),
+ WM_MANIPULATORGROUP_INIT_REFRESH = (1 << 1),
+} eWM_ManipulatorGroupInitFlag;
+
+/**
+ * #wmManipulatorMapType.type_update_flag
+ * Manipulator-map type update flag
+ */
+typedef enum eWM_ManipulatorMapTypeUpdateFlag {
+ /* A new type has been added, needs to be initialized for all views. */
+ WM_MANIPULATORMAPTYPE_UPDATE_INIT = (1 << 0),
+ WM_MANIPULATORMAPTYPE_UPDATE_REMOVE = (1 << 1),
+
+ /* Needed because keymap may be registered before and after window initialization.
+ * So we need to keep track of keymap initialization separately. */
+ WM_MANIPULATORMAPTYPE_KEYMAP_INIT = (1 << 2),
+} eWM_ManipulatorMapTypeUpdateFlag;
+
+/* -------------------------------------------------------------------- */
+/* wmManipulator */
+
+/**
+ * \brief Manipulator tweak flag.
+ * Bitflag passed to manipulator while tweaking.
+ *
+ * \note Manipulators are responsible for handling this #wmManipulator.modal callback!.
+ */
+typedef enum {
+ /* Drag with extra precision (Shift). */
+ WM_MANIPULATOR_TWEAK_PRECISE = (1 << 0),
+ /* Drag with snap enabled (Ctrl). */
+ WM_MANIPULATOR_TWEAK_SNAP = (1 << 1),
+} eWM_ManipulatorTweak;
+
+#include "wm_manipulator_fn.h"
+
+typedef struct wmManipulatorOpElem {
+ struct wmOperatorType *type;
+ /* operator properties if manipulator spawns and controls an operator,
+ * or owner pointer if manipulator spawns and controls a property */
+ PointerRNA ptr;
+} wmManipulatorOpElem;
+
+/* manipulators are set per region by registering them on manipulator-maps */
+struct wmManipulator {
+ struct wmManipulator *next, *prev;
+
+ /* While we don't have a real type, use this to put type-like vars. */
+ const struct wmManipulatorType *type;
+
+ /* Overrides 'type->modal' when set.
+ * Note that this is a workaround, remove if we can. */
+ wmManipulatorFnModal custom_modal;
+
+ /* pointer back to group this manipulator is in (just for quick access) */
+ struct wmManipulatorGroup *parent_mgroup;
+
+ void *py_instance;
+
+ /* rna pointer to access properties */
+ struct PointerRNA *ptr;
+
+ /* flags that influence the behavior or how the manipulators are drawn */
+ eWM_ManipulatorFlag flag;
+ /* state flags (active, highlighted, selected) */
+ eWM_ManipulatorState state;
+
+ /* Optional ID for highlighting different parts of this manipulator.
+ * -1 when unset, otherwise a valid index. (Used as index to 'op_data'). */
+ int highlight_part;
+
+ /* Transformation of the manipulator in 2d or 3d space.
+ * - Matrix axis are expected to be unit length (scale is applied after).
+ * - Behavior when axis aren't orthogonal depends on each manipulator.
+ * - Typically the +Z is the primary axis for manipulators to use.
+ * - 'matrix[3]' must be used for location,
+ * besides this it's up to the manipulators internal code how the
+ * rotation components are used for drawing and interaction.
+ */
+
+ /* The space this manipulator is being modified in. */
+ float matrix_space[4][4];
+ /* Transformation of this manipulator. */
+ float matrix_basis[4][4];
+ /* custom offset from origin */
+ float matrix_offset[4][4];
+ /* runtime property, set the scale while drawing on the viewport */
+ float scale_final;
+ /* user defined scale, in addition to the original one */
+ float scale_basis;
+ /* user defined width for line drawing */
+ float line_width;
+ /* manipulator colors (uses default fallbacks if not defined) */
+ float color[4], color_hi[4];
+
+ /* data used during interaction */
+ void *interaction_data;
+
+ /* Operator to spawn when activating the manipulator (overrides property editing),
+ * an array of items (aligned with #wmManipulator.highlight_part). */
+ wmManipulatorOpElem *op_data;
+ int op_data_len;
+
+ struct IDProperty *properties;
+
+ /* over alloc target_properties after 'wmManipulatorType.struct_size' */
+};
+
+/* Similar to PropertyElemRNA, but has an identifier. */
+typedef struct wmManipulatorProperty {
+ const struct wmManipulatorPropertyType *type;
+
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+
+
+ /* Optional functions for converting to/from RNA */
+ struct {
+ wmManipulatorPropertyFnGet value_get_fn;
+ wmManipulatorPropertyFnSet value_set_fn;
+ wmManipulatorPropertyFnRangeGet range_get_fn;
+ wmManipulatorPropertyFnFree free_fn;
+ void *user_data;
+ } custom_func;
+} wmManipulatorProperty;
+
+typedef struct wmManipulatorPropertyType {
+ struct wmManipulatorPropertyType *next, *prev;
+ /* PropertyType, typically 'PROP_FLOAT' */
+ int data_type;
+ int array_length;
+
+ /* index within 'wmManipulatorType' */
+ int index_in_type;
+
+ /* over alloc */
+ char idname[0];
+} wmManipulatorPropertyType;
+
+
+/**
+ * Simple utility wrapper for storing a single manipulator as wmManipulatorGroup.customdata (which gets freed).
+ */
+typedef struct wmManipulatorWrapper {
+ struct wmManipulator *manipulator;
+} wmManipulatorWrapper;
+
+struct wmManipulatorMapType_Params {
+ short spaceid;
+ short regionid;
+};
+
+typedef struct wmManipulatorType {
+
+ const char *idname; /* MAX_NAME */
+
+ /* Set to 'sizeof(wmManipulator)' or larger for instances of this type,
+ * use so we can cant to other types without the hassle of a custom-data pointer. */
+ uint struct_size;
+
+ /* Initialize struct (calloc'd 'struct_size' region). */
+ wmManipulatorFnSetup setup;
+
+ /* draw manipulator */
+ wmManipulatorFnDraw draw;
+
+ /* determines 3d intersection by rendering the manipulator in a selection routine. */
+ wmManipulatorFnDrawSelect draw_select;
+
+ /* Determine if the mouse intersects with the manipulator.
+ * The calculation should be done in the callback itself, -1 for no seleciton. */
+ wmManipulatorFnTestSelect test_select;
+
+ /* handler used by the manipulator. Usually handles interaction tied to a manipulator type */
+ wmManipulatorFnModal modal;
+
+ /* manipulator-specific handler to update manipulator attributes based on the property value */
+ wmManipulatorFnPropertyUpdate property_update;
+
+ /* Returns the final transformation which may be different from the 'matrix',
+ * depending on the manipulator.
+ * Notes:
+ * - Scale isn't applied (wmManipulator.scale/user_scale).
+ * - Offset isn't applied (wmManipulator.matrix_offset).
+ */
+ wmManipulatorFnMatrixBasisGet matrix_basis_get;
+
+ /* activate a manipulator state when the user clicks on it */
+ wmManipulatorFnInvoke invoke;
+
+ /* called when manipulator tweaking is done - used to free data and reset property when cancelling */
+ wmManipulatorFnExit exit;
+
+ wmManipulatorFnCursorGet cursor_get;
+
+ /* called when manipulator selection state changes */
+ wmManipulatorFnSelectRefresh select_refresh;
+
+ /* RNA for properties */
+ struct StructRNA *srna;
+
+ /* RNA integration */
+ ExtensionRNA ext;
+
+ ListBase target_property_defs;
+ int target_property_defs_len;
+
+} wmManipulatorType;
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorGroup */
+
+/* factory class for a manipulator-group type, gets called every time a new area is spawned */
+typedef struct wmManipulatorGroupTypeRef {
+ struct wmManipulatorGroupTypeRef *next, *prev;
+ struct wmManipulatorGroupType *type;
+} wmManipulatorGroupTypeRef;
+
+/* factory class for a manipulator-group type, gets called every time a new area is spawned */
+typedef struct wmManipulatorGroupType {
+ const char *idname; /* MAX_NAME */
+ const char *name; /* manipulator-group name - displayed in UI (keymap editor) */
+
+ /* poll if manipulator-map should be visible */
+ wmManipulatorGroupFnPoll poll;
+ /* initially create manipulators and set permanent data - stuff you only need to do once */
+ wmManipulatorGroupFnInit setup;
+ /* refresh data, only called if recreate flag is set (WM_manipulatormap_tag_refresh) */
+ wmManipulatorGroupFnRefresh refresh;
+ /* refresh data for drawing, called before each redraw */
+ wmManipulatorGroupFnDrawPrepare draw_prepare;
+
+ /* Keymap init callback for this manipulator-group (optional),
+ * will fall back to default tweak keymap when left NULL. */
+ wmManipulatorGroupFnSetupKeymap setup_keymap;
+
+ /* Optionally subscribe to wmMsgBus events,
+ * these are calculated automatically from RNA properties,
+ * only needed if manipulators depend indirectly on properties. */
+ wmManipulatorGroupFnMsgBusSubscribe message_subscribe;
+
+ /* keymap created with callback from above */
+ struct wmKeyMap *keymap;
+ /* Only for convenient removal. */
+ struct wmKeyConfig *keyconf;
+
+ /* Disable for now, maybe some day we want properties. */
+#if 0
+ /* rna for properties */
+ struct StructRNA *srna;
+#endif
+
+ /* RNA integration */
+ ExtensionRNA ext;
+
+ eWM_ManipulatorGroupTypeFlag flag;
+
+ /* So we know which group type to update. */
+ eWM_ManipulatorMapTypeUpdateFlag type_update_flag;
+
+ /* same as manipulator-maps, so registering/unregistering goes to the correct region */
+ struct wmManipulatorMapType_Params mmap_params;
+
+} wmManipulatorGroupType;
+
+typedef struct wmManipulatorGroup {
+ struct wmManipulatorGroup *next, *prev;
+
+ struct wmManipulatorGroupType *type;
+ ListBase manipulators;
+
+ struct wmManipulatorMap *parent_mmap;
+
+ void *py_instance; /* python stores the class instance here */
+ struct ReportList *reports; /* errors and warnings storage */
+
+ void *customdata;
+ void (*customdata_free)(void *); /* for freeing customdata from above */
+ eWM_ManipulatorGroupInitFlag init_flag;
+} wmManipulatorGroup;
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorMap */
+
+/**
+ * Pass a value of this enum to #WM_manipulatormap_draw to tell it what to draw.
+ */
+typedef enum eWM_ManipulatorMapDrawStep {
+ /** Draw 2D manipulator-groups (#WM_MANIPULATORGROUPTYPE_3D not set). */
+ WM_MANIPULATORMAP_DRAWSTEP_2D = 0,
+ /** Draw 3D manipulator-groups (#WM_MANIPULATORGROUPTYPE_3D set). */
+ WM_MANIPULATORMAP_DRAWSTEP_3D,
+} eWM_ManipulatorMapDrawStep;
+#define WM_MANIPULATORMAP_DRAWSTEP_MAX 2
+
+#endif /* __WM_MANIPULATOR_TYPES_H__ */
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
new file mode 100644
index 00000000000..7ca1f8fd5f2
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
@@ -0,0 +1,731 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/intern/wm_manipulator.c
+ * \ingroup wm
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
+
+#include "BKE_context.h"
+
+#include "GPU_batch.h"
+#include "GPU_glew.h"
+#include "GPU_immediate.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_idprop.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#ifdef WITH_PYTHON
+#include "BPY_extern.h"
+#endif
+
+/* only for own init/exit calls (wm_manipulatortype_init/wm_manipulatortype_free) */
+#include "wm.h"
+
+/* own includes */
+#include "wm_manipulator_wmapi.h"
+#include "wm_manipulator_intern.h"
+
+static void wm_manipulator_register(
+ wmManipulatorGroup *mgroup, wmManipulator *mpr);
+
+/**
+ * \note Follow #wm_operator_create convention.
+ */
+static wmManipulator *wm_manipulator_create(
+ const wmManipulatorType *wt,
+ PointerRNA *properties)
+{
+ BLI_assert(wt != NULL);
+ BLI_assert(wt->struct_size >= sizeof(wmManipulator));
+
+ wmManipulator *mpr = MEM_callocN(
+ wt->struct_size + (sizeof(wmManipulatorProperty) * wt->target_property_defs_len), __func__);
+ mpr->type = wt;
+
+ /* initialize properties, either copy or create */
+ mpr->ptr = MEM_callocN(sizeof(PointerRNA), "wmManipulatorPtrRNA");
+ if (properties && properties->data) {
+ mpr->properties = IDP_CopyProperty(properties->data);
+ }
+ else {
+ IDPropertyTemplate val = {0};
+ mpr->properties = IDP_New(IDP_GROUP, &val, "wmManipulatorProperties");
+ }
+ RNA_pointer_create(G.main->wm.first, wt->srna, mpr->properties, mpr->ptr);
+
+ WM_manipulator_properties_sanitize(mpr->ptr, 0);
+
+ unit_m4(mpr->matrix_space);
+ unit_m4(mpr->matrix_basis);
+ unit_m4(mpr->matrix_offset);
+
+ return mpr;
+}
+
+wmManipulator *WM_manipulator_new_ptr(
+ const wmManipulatorType *wt, wmManipulatorGroup *mgroup,
+ PointerRNA *properties)
+{
+ wmManipulator *mpr = wm_manipulator_create(wt, properties);
+
+ wm_manipulator_register(mgroup, mpr);
+
+ if (mpr->type->setup != NULL) {
+ mpr->type->setup(mpr);
+ }
+
+ return mpr;
+}
+
+/**
+ * \param wt: Must be valid,
+ * if you need to check it exists use #WM_manipulator_new_ptr
+ * because callers of this function don't NULL check the return value.
+ */
+wmManipulator *WM_manipulator_new(
+ const char *idname, wmManipulatorGroup *mgroup,
+ PointerRNA *properties)
+{
+ const wmManipulatorType *wt = WM_manipulatortype_find(idname, false);
+ return WM_manipulator_new_ptr(wt, mgroup, properties);
+}
+
+/**
+ * Initialize default values and allocate needed memory for members.
+ */
+static void manipulator_init(wmManipulator *mpr)
+{
+ const float color_default[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ mpr->scale_basis = 1.0f;
+ mpr->line_width = 1.0f;
+
+ /* defaults */
+ copy_v4_v4(mpr->color, color_default);
+ copy_v4_v4(mpr->color_hi, color_default);
+}
+
+/**
+ * Register \a manipulator.
+ *
+ * \param name: name used to create a unique idname for \a manipulator in \a mgroup
+ *
+ * \note Not to be confused with type registration from RNA.
+ */
+static void wm_manipulator_register(wmManipulatorGroup *mgroup, wmManipulator *mpr)
+{
+ manipulator_init(mpr);
+ wm_manipulatorgroup_manipulator_register(mgroup, mpr);
+}
+
+/**
+ * \warning this doesn't check #wmManipulatorMap (highlight, selection etc).
+ * Typical use is when freeing the windowing data,
+ * where caller can manage clearing selection, highlight... etc.
+ */
+void WM_manipulator_free(wmManipulator *mpr)
+{
+#ifdef WITH_PYTHON
+ if (mpr->py_instance) {
+ /* do this first in case there are any __del__ functions or
+ * similar that use properties */
+ BPY_DECREF_RNA_INVALIDATE(mpr->py_instance);
+ }
+#endif
+
+ if (mpr->op_data) {
+ for (int i = 0; i < mpr->op_data_len; i++) {
+ WM_operator_properties_free(&mpr->op_data[i].ptr);
+ }
+ MEM_freeN(mpr->op_data);
+ }
+
+ if (mpr->ptr != NULL) {
+ WM_manipulator_properties_free(mpr->ptr);
+ MEM_freeN(mpr->ptr);
+ }
+
+ if (mpr->type->target_property_defs_len != 0) {
+ wmManipulatorProperty *mpr_prop_array = WM_manipulator_target_property_array(mpr);
+ for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
+ wmManipulatorProperty *mpr_prop = &mpr_prop_array[i];
+ if (mpr_prop->custom_func.free_fn) {
+ mpr_prop->custom_func.free_fn(mpr, mpr_prop);
+ }
+ }
+ }
+
+ MEM_freeN(mpr);
+}
+
+/**
+ * Free \a manipulator and unlink from \a manipulatorlist.
+ * \a manipulatorlist is allowed to be NULL.
+ */
+void WM_manipulator_unlink(ListBase *manipulatorlist, wmManipulatorMap *mmap, wmManipulator *mpr, bContext *C)
+{
+ if (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) {
+ wm_manipulatormap_highlight_set(mmap, C, NULL, 0);
+ }
+ if (mpr->state & WM_MANIPULATOR_STATE_MODAL) {
+ wm_manipulatormap_modal_set(mmap, C, mpr, NULL, false);
+ }
+ /* Unlink instead of setting so we don't run callbacks. */
+ if (mpr->state & WM_MANIPULATOR_STATE_SELECT) {
+ WM_manipulator_select_unlink(mmap, mpr);
+ }
+
+ if (manipulatorlist) {
+ BLI_remlink(manipulatorlist, mpr);
+ }
+
+ BLI_assert(mmap->mmap_context.highlight != mpr);
+ BLI_assert(mmap->mmap_context.modal != mpr);
+
+ WM_manipulator_free(mpr);
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Manipulator Creation API
+ *
+ * API for defining data on manipulator creation.
+ *
+ * \{ */
+
+struct wmManipulatorOpElem *WM_manipulator_operator_get(
+ wmManipulator *mpr, int part_index)
+{
+ if (mpr->op_data && ((part_index >= 0) && (part_index < mpr->op_data_len))) {
+ return &mpr->op_data[part_index];
+ }
+ return NULL;
+}
+
+PointerRNA *WM_manipulator_operator_set(
+ wmManipulator *mpr, int part_index,
+ wmOperatorType *ot, IDProperty *properties)
+{
+ BLI_assert(part_index < 255);
+ /* We could pre-allocate these but using multiple is such a rare thing. */
+ if (part_index >= mpr->op_data_len) {
+ mpr->op_data_len = part_index + 1;
+ mpr->op_data = MEM_recallocN(mpr->op_data, sizeof(*mpr->op_data) * mpr->op_data_len);
+ }
+ wmManipulatorOpElem *mpop = &mpr->op_data[part_index];
+ mpop->type = ot;
+
+ if (mpop->ptr.data) {
+ WM_operator_properties_free(&mpop->ptr);
+ }
+ WM_operator_properties_create_ptr(&mpop->ptr, ot);
+
+ if (properties) {
+ mpop->ptr.data = properties;
+ }
+
+ return &mpop->ptr;
+}
+
+static void wm_manipulator_set_matrix_rotation_from_z_axis__internal(
+ float matrix[4][4], const float z_axis[3])
+{
+ /* old code, seems we can use simpler method */
+#if 0
+ const float z_global[3] = {0.0f, 0.0f, 1.0f};
+ float rot[3][3];
+
+ rotation_between_vecs_to_mat3(rot, z_global, z_axis);
+ copy_v3_v3(matrix[0], rot[0]);
+ copy_v3_v3(matrix[1], rot[1]);
+ copy_v3_v3(matrix[2], rot[2]);
+#else
+ normalize_v3_v3(matrix[2], z_axis);
+ ortho_basis_v3v3_v3(matrix[0], matrix[1], matrix[2]);
+#endif
+
+}
+
+static void wm_manipulator_set_matrix_rotation_from_yz_axis__internal(
+ float matrix[4][4], const float y_axis[3], const float z_axis[3])
+{
+ normalize_v3_v3(matrix[1], y_axis);
+ normalize_v3_v3(matrix[2], z_axis);
+ cross_v3_v3v3(matrix[0], matrix[1], matrix[2]);
+ normalize_v3(matrix[0]);
+}
+
+/**
+ * wmManipulator.matrix utils.
+ */
+void WM_manipulator_set_matrix_rotation_from_z_axis(
+ wmManipulator *mpr, const float z_axis[3])
+{
+ wm_manipulator_set_matrix_rotation_from_z_axis__internal(mpr->matrix_basis, z_axis);
+}
+void WM_manipulator_set_matrix_rotation_from_yz_axis(
+ wmManipulator *mpr, const float y_axis[3], const float z_axis[3])
+{
+ wm_manipulator_set_matrix_rotation_from_yz_axis__internal(mpr->matrix_basis, y_axis, z_axis);
+}
+void WM_manipulator_set_matrix_location(wmManipulator *mpr, const float origin[3])
+{
+ copy_v3_v3(mpr->matrix_basis[3], origin);
+}
+
+/**
+ * wmManipulator.matrix_offset utils.
+ */
+void WM_manipulator_set_matrix_offset_rotation_from_z_axis(
+ wmManipulator *mpr, const float z_axis[3])
+{
+ wm_manipulator_set_matrix_rotation_from_z_axis__internal(mpr->matrix_offset, z_axis);
+}
+void WM_manipulator_set_matrix_offset_rotation_from_yz_axis(
+ wmManipulator *mpr, const float y_axis[3], const float z_axis[3])
+{
+ wm_manipulator_set_matrix_rotation_from_yz_axis__internal(mpr->matrix_offset, y_axis, z_axis);
+}
+void WM_manipulator_set_matrix_offset_location(wmManipulator *mpr, const float offset[3])
+{
+ copy_v3_v3(mpr->matrix_offset[3], offset);
+}
+
+void WM_manipulator_set_flag(wmManipulator *mpr, const int flag, const bool enable)
+{
+ if (enable) {
+ mpr->flag |= flag;
+ }
+ else {
+ mpr->flag &= ~flag;
+ }
+}
+
+void WM_manipulator_set_scale(wmManipulator *mpr, const float scale)
+{
+ mpr->scale_basis = scale;
+}
+
+void WM_manipulator_set_line_width(wmManipulator *mpr, const float line_width)
+{
+ mpr->line_width = line_width;
+}
+
+/**
+ * Set manipulator rgba colors.
+ *
+ * \param col Normal state color.
+ * \param col_hi Highlighted state color.
+ */
+void WM_manipulator_get_color(const wmManipulator *mpr, float color[4])
+{
+ copy_v4_v4(color, mpr->color);
+}
+void WM_manipulator_set_color(wmManipulator *mpr, const float color[4])
+{
+ copy_v4_v4(mpr->color, color);
+}
+
+void WM_manipulator_get_color_highlight(const wmManipulator *mpr, float color_hi[4])
+{
+ copy_v4_v4(color_hi, mpr->color_hi);
+}
+void WM_manipulator_set_color_highlight(wmManipulator *mpr, const float color_hi[4])
+{
+ copy_v4_v4(mpr->color_hi, color_hi);
+}
+
+
+/** \} */ // Manipulator Creation API
+
+
+/* -------------------------------------------------------------------- */
+/** \name Manipulator Callback Assignment
+ *
+ * \{ */
+
+void WM_manipulator_set_fn_custom_modal(struct wmManipulator *mpr, wmManipulatorFnModal fn)
+{
+ mpr->custom_modal = fn;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/**
+ * Add/Remove \a manipulator to selection.
+ * Reallocates memory for selected manipulators so better not call for selecting multiple ones.
+ *
+ * \return if the selection has changed.
+ */
+bool wm_manipulator_select_set_ex(
+ wmManipulatorMap *mmap, wmManipulator *mpr, bool select,
+ bool use_array, bool use_callback)
+{
+ bool changed = false;
+
+ if (select) {
+ if ((mpr->state & WM_MANIPULATOR_STATE_SELECT) == 0) {
+ if (use_array) {
+ wm_manipulatormap_select_array_push_back(mmap, mpr);
+ }
+ mpr->state |= WM_MANIPULATOR_STATE_SELECT;
+ changed = true;
+ }
+ }
+ else {
+ if (mpr->state & WM_MANIPULATOR_STATE_SELECT) {
+ if (use_array) {
+ wm_manipulatormap_select_array_remove(mmap, mpr);
+ }
+ mpr->state &= ~WM_MANIPULATOR_STATE_SELECT;
+ changed = true;
+ }
+ }
+
+ /* In the case of unlinking we only want to remove from the array
+ * and not write to the external state */
+ if (use_callback && changed) {
+ if (mpr->type->select_refresh) {
+ mpr->type->select_refresh(mpr);
+ }
+ }
+
+ return changed;
+}
+
+/* Remove from selection array without running callbacks. */
+bool WM_manipulator_select_unlink(wmManipulatorMap *mmap, wmManipulator *mpr)
+{
+ return wm_manipulator_select_set_ex(mmap, mpr, false, true, false);
+}
+
+bool WM_manipulator_select_set(wmManipulatorMap *mmap, wmManipulator *mpr, bool select)
+{
+ return wm_manipulator_select_set_ex(mmap, mpr, select, true, true);
+}
+
+void WM_manipulator_highlight_set(wmManipulatorMap *mmap, wmManipulator *mpr)
+{
+ wm_manipulatormap_highlight_set(mmap, NULL, mpr, mpr ? mpr->highlight_part : 0);
+}
+
+bool wm_manipulator_select_and_highlight(bContext *C, wmManipulatorMap *mmap, wmManipulator *mpr)
+{
+ if (WM_manipulator_select_set(mmap, mpr, true)) {
+ wm_manipulatormap_highlight_set(mmap, C, mpr, mpr->highlight_part);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+void wm_manipulator_calculate_scale(wmManipulator *mpr, const bContext *C)
+{
+ const RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float scale = U.ui_scale;
+
+ if ((mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_SCALE) == 0) {
+ scale *= U.manipulator_size;
+ if (rv3d) {
+ /* 'ED_view3d_pixel_size' includes 'U.pixelsize', remove it. */
+ float matrix_world[4][4];
+ if (mpr->type->matrix_basis_get) {
+ float matrix_basis[4][4];
+ mpr->type->matrix_basis_get(mpr, matrix_basis);
+ mul_m4_m4m4(matrix_world, mpr->matrix_space, matrix_basis);
+ }
+ else {
+ mul_m4_m4m4(matrix_world, mpr->matrix_space, mpr->matrix_basis);
+ }
+
+ /* Exclude matrix_offset from scale. */
+ scale *= ED_view3d_pixel_size(rv3d, matrix_world[3]) / U.pixelsize;
+ }
+ else {
+ scale *= 0.02f;
+ }
+ }
+
+ mpr->scale_final = mpr->scale_basis * scale;
+}
+
+static void manipulator_update_prop_data(wmManipulator *mpr)
+{
+ /* manipulator property might have been changed, so update manipulator */
+ if (mpr->type->property_update) {
+ wmManipulatorProperty *mpr_prop_array = WM_manipulator_target_property_array(mpr);
+ for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
+ wmManipulatorProperty *mpr_prop = &mpr_prop_array[i];
+ if (WM_manipulator_target_property_is_valid(mpr_prop)) {
+ mpr->type->property_update(mpr, mpr_prop);
+ }
+ }
+ }
+}
+
+void wm_manipulator_update(wmManipulator *mpr, const bContext *C, const bool refresh_map)
+{
+ if (refresh_map) {
+ manipulator_update_prop_data(mpr);
+ }
+ wm_manipulator_calculate_scale(mpr, C);
+}
+
+int wm_manipulator_is_visible(wmManipulator *mpr)
+{
+ if (mpr->flag & WM_MANIPULATOR_HIDDEN) {
+ return 0;
+ }
+ if ((mpr->state & WM_MANIPULATOR_STATE_MODAL) &&
+ !(mpr->flag & (WM_MANIPULATOR_DRAW_MODAL | WM_MANIPULATOR_DRAW_VALUE)))
+ {
+ /* don't draw while modal (dragging) */
+ return 0;
+ }
+ if ((mpr->flag & WM_MANIPULATOR_DRAW_HOVER) &&
+ !(mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) &&
+ !(mpr->state & WM_MANIPULATOR_STATE_SELECT)) /* still draw selected manipulators */
+ {
+ /* update but don't draw */
+ return WM_MANIPULATOR_IS_VISIBLE_UPDATE;
+ }
+
+ return WM_MANIPULATOR_IS_VISIBLE_UPDATE | WM_MANIPULATOR_IS_VISIBLE_DRAW;
+}
+
+void WM_manipulator_calc_matrix_final_params(
+ const wmManipulator *mpr,
+ const struct WM_ManipulatorMatrixParams *params,
+ float r_mat[4][4])
+{
+ const float (* const matrix_space)[4] = params->matrix_space ? params->matrix_space : mpr->matrix_space;
+ const float (* const matrix_basis)[4] = params->matrix_basis ? params->matrix_basis : mpr->matrix_basis;
+ const float (* const matrix_offset)[4] = params->matrix_offset ? params->matrix_offset : mpr->matrix_offset;
+ const float *scale_final = params->scale_final ? params->scale_final : &mpr->scale_final;
+
+ float final_matrix[4][4];
+ if (params->matrix_basis == NULL && mpr->type->matrix_basis_get) {
+ mpr->type->matrix_basis_get(mpr, final_matrix);
+ }
+ else {
+ copy_m4_m4(final_matrix, matrix_basis);
+ }
+
+ if (mpr->flag & WM_MANIPULATOR_DRAW_NO_SCALE) {
+ mul_m4_m4m4(final_matrix, final_matrix, matrix_offset);
+ }
+ else {
+ if (mpr->flag & WM_MANIPULATOR_DRAW_OFFSET_SCALE) {
+ mul_mat3_m4_fl(final_matrix, *scale_final);
+ mul_m4_m4m4(final_matrix, final_matrix, matrix_offset);
+ }
+ else {
+ mul_m4_m4m4(final_matrix, final_matrix, matrix_offset);
+ mul_mat3_m4_fl(final_matrix, *scale_final);
+ }
+ }
+
+ mul_m4_m4m4(r_mat, matrix_space, final_matrix);
+}
+
+void WM_manipulator_calc_matrix_final(const wmManipulator *mpr, float r_mat[4][4])
+{
+ WM_manipulator_calc_matrix_final_params(
+ mpr,
+ &((struct WM_ManipulatorMatrixParams) {
+ .matrix_space = NULL,
+ .matrix_basis = NULL,
+ .matrix_offset = NULL,
+ .scale_final = NULL,
+ }), r_mat
+ );
+}
+
+/** \name Manipulator Propery Access
+ *
+ * Matches `WM_operator_properties` conventions.
+ *
+ * \{ */
+
+
+void WM_manipulator_properties_create_ptr(PointerRNA *ptr, wmManipulatorType *wt)
+{
+ RNA_pointer_create(NULL, wt->srna, NULL, ptr);
+}
+
+void WM_manipulator_properties_create(PointerRNA *ptr, const char *wtstring)
+{
+ const wmManipulatorType *wt = WM_manipulatortype_find(wtstring, false);
+
+ if (wt)
+ WM_manipulator_properties_create_ptr(ptr, (wmManipulatorType *)wt);
+ else
+ RNA_pointer_create(NULL, &RNA_ManipulatorProperties, NULL, ptr);
+}
+
+/* similar to the function above except its uses ID properties
+ * used for keymaps and macros */
+void WM_manipulator_properties_alloc(PointerRNA **ptr, IDProperty **properties, const char *wtstring)
+{
+ if (*properties == NULL) {
+ IDPropertyTemplate val = {0};
+ *properties = IDP_New(IDP_GROUP, &val, "wmOpItemProp");
+ }
+
+ if (*ptr == NULL) {
+ *ptr = MEM_callocN(sizeof(PointerRNA), "wmOpItemPtr");
+ WM_manipulator_properties_create(*ptr, wtstring);
+ }
+
+ (*ptr)->data = *properties;
+
+}
+
+void WM_manipulator_properties_sanitize(PointerRNA *ptr, const bool no_context)
+{
+ RNA_STRUCT_BEGIN (ptr, prop)
+ {
+ switch (RNA_property_type(prop)) {
+ case PROP_ENUM:
+ if (no_context)
+ RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);
+ else
+ RNA_def_property_clear_flag(prop, PROP_ENUM_NO_CONTEXT);
+ break;
+ case PROP_POINTER:
+ {
+ StructRNA *ptype = RNA_property_pointer_type(ptr, prop);
+
+ /* recurse into manipulator properties */
+ if (RNA_struct_is_a(ptype, &RNA_ManipulatorProperties)) {
+ PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
+ WM_manipulator_properties_sanitize(&opptr, no_context);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ RNA_STRUCT_END;
+}
+
+
+/** set all props to their default,
+ * \param do_update Only update un-initialized props.
+ *
+ * \note, theres nothing specific to manipulators here.
+ * this could be made a general function.
+ */
+bool WM_manipulator_properties_default(PointerRNA *ptr, const bool do_update)
+{
+ bool changed = false;
+ RNA_STRUCT_BEGIN (ptr, prop)
+ {
+ switch (RNA_property_type(prop)) {
+ case PROP_POINTER:
+ {
+ StructRNA *ptype = RNA_property_pointer_type(ptr, prop);
+ if (ptype != &RNA_Struct) {
+ PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
+ changed |= WM_manipulator_properties_default(&opptr, do_update);
+ }
+ break;
+ }
+ default:
+ if ((do_update == false) || (RNA_property_is_set(ptr, prop) == false)) {
+ if (RNA_property_reset(ptr, prop, -1)) {
+ changed = true;
+ }
+ }
+ break;
+ }
+ }
+ RNA_STRUCT_END;
+
+ return changed;
+}
+
+/* remove all props without PROP_SKIP_SAVE */
+void WM_manipulator_properties_reset(wmManipulator *mpr)
+{
+ if (mpr->ptr->data) {
+ PropertyRNA *iterprop;
+ iterprop = RNA_struct_iterator_property(mpr->type->srna);
+
+ RNA_PROP_BEGIN (mpr->ptr, itemptr, iterprop)
+ {
+ PropertyRNA *prop = itemptr.data;
+
+ if ((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) {
+ const char *identifier = RNA_property_identifier(prop);
+ RNA_struct_idprops_unset(mpr->ptr, identifier);
+ }
+ }
+ RNA_PROP_END;
+ }
+}
+
+void WM_manipulator_properties_clear(PointerRNA *ptr)
+{
+ IDProperty *properties = ptr->data;
+
+ if (properties) {
+ IDP_ClearProperty(properties);
+ }
+}
+
+void WM_manipulator_properties_free(PointerRNA *ptr)
+{
+ IDProperty *properties = ptr->data;
+
+ if (properties) {
+ IDP_FreeProperty(properties);
+ MEM_freeN(properties);
+ ptr->data = NULL; /* just in case */
+ }
+}
+
+/** \} */
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
new file mode 100644
index 00000000000..d62aac8cd87
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
@@ -0,0 +1,788 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/intern/wm_manipulator_group.c
+ * \ingroup wm
+ *
+ * \name Manipulator-Group
+ *
+ * Manipulator-groups store and manage groups of manipulators. They can be
+ * attached to modal handlers and have own keymaps.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm_event_system.h"
+
+#include "ED_screen.h"
+
+/* own includes */
+#include "wm_manipulator_wmapi.h"
+#include "wm_manipulator_intern.h"
+
+#ifdef WITH_PYTHON
+# include "BPY_extern.h"
+#endif
+
+/* -------------------------------------------------------------------- */
+/** \name wmManipulatorGroup
+ *
+ * \{ */
+
+/**
+ * Create a new manipulator-group from \a wgt.
+ */
+wmManipulatorGroup *wm_manipulatorgroup_new_from_type(
+ wmManipulatorMap *mmap, wmManipulatorGroupType *wgt)
+{
+ wmManipulatorGroup *mgroup = MEM_callocN(sizeof(*mgroup), "manipulator-group");
+ mgroup->type = wgt;
+
+ /* keep back-link */
+ mgroup->parent_mmap = mmap;
+
+ BLI_addtail(&mmap->groups, mgroup);
+
+ return mgroup;
+}
+
+void wm_manipulatorgroup_free(bContext *C, wmManipulatorGroup *mgroup)
+{
+ wmManipulatorMap *mmap = mgroup->parent_mmap;
+
+ /* Similar to WM_manipulator_unlink, but only to keep mmap state correct,
+ * we don't want to run callbacks. */
+ if (mmap->mmap_context.highlight && mmap->mmap_context.highlight->parent_mgroup == mgroup) {
+ wm_manipulatormap_highlight_set(mmap, C, NULL, 0);
+ }
+ if (mmap->mmap_context.modal && mmap->mmap_context.modal->parent_mgroup == mgroup) {
+ wm_manipulatormap_modal_set(mmap, C, mmap->mmap_context.modal, NULL, false);
+ }
+
+ for (wmManipulator *mpr = mgroup->manipulators.first, *mpr_next; mpr; mpr = mpr_next) {
+ mpr_next = mpr->next;
+ if (mmap->mmap_context.select.len) {
+ WM_manipulator_select_unlink(mmap, mpr);
+ }
+ WM_manipulator_free(mpr);
+ }
+ BLI_listbase_clear(&mgroup->manipulators);
+
+#ifdef WITH_PYTHON
+ if (mgroup->py_instance) {
+ /* do this first in case there are any __del__ functions or
+ * similar that use properties */
+ BPY_DECREF_RNA_INVALIDATE(mgroup->py_instance);
+ }
+#endif
+
+ if (mgroup->reports && (mgroup->reports->flag & RPT_FREE)) {
+ BKE_reports_clear(mgroup->reports);
+ MEM_freeN(mgroup->reports);
+ }
+
+ if (mgroup->customdata_free) {
+ mgroup->customdata_free(mgroup->customdata);
+ }
+ else {
+ MEM_SAFE_FREE(mgroup->customdata);
+ }
+
+ BLI_remlink(&mmap->groups, mgroup);
+
+ MEM_freeN(mgroup);
+}
+
+/**
+ * Add \a manipulator to \a mgroup and make sure its name is unique within the group.
+ */
+void wm_manipulatorgroup_manipulator_register(wmManipulatorGroup *mgroup, wmManipulator *mpr)
+{
+ BLI_assert(BLI_findindex(&mgroup->manipulators, mpr) == -1);
+ BLI_addtail(&mgroup->manipulators, mpr);
+ mpr->parent_mgroup = mgroup;
+}
+
+wmManipulator *wm_manipulatorgroup_find_intersected_mainpulator(
+ const wmManipulatorGroup *mgroup, bContext *C, const wmEvent *event,
+ int *r_part)
+{
+ for (wmManipulator *mpr = mgroup->manipulators.first; mpr; mpr = mpr->next) {
+ if (mpr->type->test_select && (mpr->flag & WM_MANIPULATOR_HIDDEN) == 0) {
+ if ((*r_part = mpr->type->test_select(C, mpr, event)) != -1) {
+ return mpr;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Adds all manipulators of \a mgroup that can be selected to the head of \a listbase. Added items need freeing!
+ */
+void wm_manipulatorgroup_intersectable_manipulators_to_list(const wmManipulatorGroup *mgroup, ListBase *listbase)
+{
+ for (wmManipulator *mpr = mgroup->manipulators.first; mpr; mpr = mpr->next) {
+ if ((mpr->flag & WM_MANIPULATOR_HIDDEN) == 0) {
+ if (((mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) && mpr->type->draw_select) ||
+ ((mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) == 0 && mpr->type->test_select))
+ {
+ BLI_addhead(listbase, BLI_genericNodeN(mpr));
+ }
+ }
+ }
+}
+
+void wm_manipulatorgroup_ensure_initialized(wmManipulatorGroup *mgroup, const bContext *C)
+{
+ /* prepare for first draw */
+ if (UNLIKELY((mgroup->init_flag & WM_MANIPULATORGROUP_INIT_SETUP) == 0)) {
+ mgroup->type->setup(C, mgroup);
+
+ /* Not ideal, initialize keymap here, needed for RNA runtime generated manipulators. */
+ wmManipulatorGroupType *wgt = mgroup->type;
+ if (wgt->keymap == NULL) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wm_manipulatorgrouptype_setup_keymap(wgt, wm->defaultconf);
+ BLI_assert(wgt->keymap != NULL);
+ }
+ mgroup->init_flag |= WM_MANIPULATORGROUP_INIT_SETUP;
+ }
+
+ /* refresh may be called multiple times, this just ensures its called at least once before we draw. */
+ if (UNLIKELY((mgroup->init_flag & WM_MANIPULATORGROUP_INIT_REFRESH) == 0)) {
+ if (mgroup->type->refresh) {
+ mgroup->type->refresh(C, mgroup);
+ }
+ mgroup->init_flag |= WM_MANIPULATORGROUP_INIT_REFRESH;
+ }
+}
+
+bool wm_manipulatorgroup_is_visible(const wmManipulatorGroup *mgroup, const bContext *C)
+{
+ /* Check for poll function, if manipulator-group belongs to an operator, also check if the operator is running. */
+ return (!mgroup->type->poll || mgroup->type->poll(C, mgroup->type));
+}
+
+bool wm_manipulatorgroup_is_visible_in_drawstep(
+ const wmManipulatorGroup *mgroup, const eWM_ManipulatorMapDrawStep drawstep)
+{
+ switch (drawstep) {
+ case WM_MANIPULATORMAP_DRAWSTEP_2D:
+ return (mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) == 0;
+ case WM_MANIPULATORMAP_DRAWSTEP_3D:
+ return (mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D);
+ default:
+ BLI_assert(0);
+ return false;
+ }
+}
+
+bool wm_manipulatorgroup_is_any_selected(const wmManipulatorGroup *mgroup)
+{
+ if (mgroup->type->flag & WM_MANIPULATORGROUPTYPE_SELECT) {
+ for (const wmManipulator *mpr = mgroup->manipulators.first; mpr; mpr = mpr->next) {
+ if (mpr->state & WM_MANIPULATOR_STATE_SELECT) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/** \} */
+
+/** \name Manipulator operators
+ *
+ * Basic operators for manipulator interaction with user configurable keymaps.
+ *
+ * \{ */
+
+static int manipulator_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ ARegion *ar = CTX_wm_region(C);
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ wmManipulatorMapSelectState *msel = &mmap->mmap_context.select;
+ wmManipulator *highlight = mmap->mmap_context.highlight;
+
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool deselect = RNA_boolean_get(op->ptr, "deselect");
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+
+ /* deselect all first */
+ if (extend == false && deselect == false && toggle == false) {
+ wm_manipulatormap_deselect_all(mmap);
+ BLI_assert(msel->items == NULL && msel->len == 0);
+ UNUSED_VARS_NDEBUG(msel);
+ }
+
+ if (highlight) {
+ const bool is_selected = (highlight->state & WM_MANIPULATOR_STATE_SELECT);
+ bool redraw = false;
+
+ if (toggle) {
+ /* toggle: deselect if already selected, else select */
+ deselect = is_selected;
+ }
+
+ if (deselect) {
+ if (is_selected && WM_manipulator_select_set(mmap, highlight, false)) {
+ redraw = true;
+ }
+ }
+ else if (wm_manipulator_select_and_highlight(C, mmap, highlight)) {
+ redraw = true;
+ }
+
+ if (redraw) {
+ ED_region_tag_redraw(ar);
+ }
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BLI_assert(0);
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ return OPERATOR_PASS_THROUGH;
+}
+
+void MANIPULATORGROUP_OT_manipulator_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Manipulator Select";
+ ot->description = "Select the currently highlighted manipulator";
+ ot->idname = "MANIPULATORGROUP_OT_manipulator_select";
+
+ /* api callbacks */
+ ot->invoke = manipulator_select_invoke;
+
+ ot->flag = OPTYPE_UNDO;
+
+ WM_operator_properties_mouse_select(ot);
+}
+
+typedef struct ManipulatorTweakData {
+ wmManipulatorMap *mmap;
+ wmManipulator *mpr_modal;
+
+ int init_event; /* initial event type */
+ int flag; /* tweak flags */
+} ManipulatorTweakData;
+
+static void manipulator_tweak_finish(bContext *C, wmOperator *op, const bool cancel)
+{
+ ManipulatorTweakData *mtweak = op->customdata;
+ if (mtweak->mpr_modal->type->exit) {
+ mtweak->mpr_modal->type->exit(C, mtweak->mpr_modal, cancel);
+ }
+ wm_manipulatormap_modal_set(mtweak->mmap, C, mtweak->mpr_modal, NULL, false);
+ MEM_freeN(mtweak);
+}
+
+static int manipulator_tweak_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ManipulatorTweakData *mtweak = op->customdata;
+ wmManipulator *mpr = mtweak->mpr_modal;
+
+ if (mpr == NULL) {
+ BLI_assert(0);
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ if (event->type == mtweak->init_event && event->val == KM_RELEASE) {
+ manipulator_tweak_finish(C, op, false);
+ return OPERATOR_FINISHED;
+ }
+
+
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case TWEAK_MODAL_CANCEL:
+ manipulator_tweak_finish(C, op, true);
+ return OPERATOR_CANCELLED;
+ case TWEAK_MODAL_CONFIRM:
+ manipulator_tweak_finish(C, op, false);
+ return OPERATOR_FINISHED;
+
+ case TWEAK_MODAL_PRECISION_ON:
+ mtweak->flag |= WM_MANIPULATOR_TWEAK_PRECISE;
+ break;
+ case TWEAK_MODAL_PRECISION_OFF:
+ mtweak->flag &= ~WM_MANIPULATOR_TWEAK_PRECISE;
+ break;
+
+ case TWEAK_MODAL_SNAP_ON:
+ mtweak->flag |= WM_MANIPULATOR_TWEAK_SNAP;
+ break;
+ case TWEAK_MODAL_SNAP_OFF:
+ mtweak->flag &= ~WM_MANIPULATOR_TWEAK_SNAP;
+ break;
+ }
+ }
+
+ /* handle manipulator */
+ wmManipulatorFnModal modal_fn = mpr->custom_modal ? mpr->custom_modal : mpr->type->modal;
+ int retval = modal_fn(C, mpr, event, mtweak->flag);
+
+ if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
+ manipulator_tweak_finish(C, op, (retval & OPERATOR_CANCELLED) != 0);
+ return OPERATOR_FINISHED;
+ }
+
+ /* Ugly hack to send manipulator events */
+ ((wmEvent *)event)->type = EVT_MANIPULATOR_UPDATE;
+
+ /* always return PASS_THROUGH so modal handlers
+ * with manipulators attached can update */
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int manipulator_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ wmManipulator *mpr = mmap->mmap_context.highlight;
+
+ if (!mpr) {
+ /* wm_handlers_do_intern shouldn't let this happen */
+ BLI_assert(0);
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+
+ /* activate highlighted manipulator */
+ wm_manipulatormap_modal_set(mmap, C, mpr, event, true);
+
+ /* XXX temporary workaround for modal manipulator operator
+ * conflicting with modal operator attached to manipulator */
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, mpr->highlight_part);
+ if (mpop && mpop->type) {
+ if (mpop->type->modal) {
+ return OPERATOR_FINISHED;
+ }
+ }
+
+ /* Couldn't start the manipulator. */
+ if ((mpr->state & WM_MANIPULATOR_STATE_MODAL) == 0) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ ManipulatorTweakData *mtweak = MEM_mallocN(sizeof(ManipulatorTweakData), __func__);
+
+ mtweak->init_event = WM_userdef_event_type_from_keymap_type(event->type);
+ mtweak->mpr_modal = mmap->mmap_context.highlight;
+ mtweak->mmap = mmap;
+ mtweak->flag = 0;
+
+ op->customdata = mtweak;
+
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void MANIPULATORGROUP_OT_manipulator_tweak(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Manipulator Tweak";
+ ot->description = "Tweak the active manipulator";
+ ot->idname = "MANIPULATORGROUP_OT_manipulator_tweak";
+
+ /* api callbacks */
+ ot->invoke = manipulator_tweak_invoke;
+ ot->modal = manipulator_tweak_modal;
+
+ /* TODO(campbell) This causes problems tweaking settings for operators,
+ * need to find a way to support this. */
+#if 0
+ ot->flag = OPTYPE_UNDO;
+#endif
+}
+
+/** \} */ // Manipulator operators
+
+
+static wmKeyMap *manipulatorgroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char *mgroupname)
+{
+ wmKeyMap *keymap;
+ char name[KMAP_MAX_NAME];
+
+ static EnumPropertyItem modal_items[] = {
+ {TWEAK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {TWEAK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ {TWEAK_MODAL_PRECISION_ON, "PRECISION_ON", 0, "Enable Precision", ""},
+ {TWEAK_MODAL_PRECISION_OFF, "PRECISION_OFF", 0, "Disable Precision", ""},
+ {TWEAK_MODAL_SNAP_ON, "SNAP_ON", 0, "Enable Snap", ""},
+ {TWEAK_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Disable Snap", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+
+ BLI_snprintf(name, sizeof(name), "%s Tweak Modal Map", mgroupname);
+ keymap = WM_modalkeymap_get(keyconf, name);
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if (keymap && keymap->modal_items)
+ return NULL;
+
+ keymap = WM_modalkeymap_add(keyconf, name, modal_items);
+
+
+ /* items for modal map */
+ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CANCEL);
+ WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CANCEL);
+
+ WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CONFIRM);
+
+ WM_modalkeymap_add_item(keymap, RIGHTSHIFTKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_PRECISION_ON);
+ WM_modalkeymap_add_item(keymap, RIGHTSHIFTKEY, KM_RELEASE, KM_ANY, 0, TWEAK_MODAL_PRECISION_OFF);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_PRECISION_ON);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, TWEAK_MODAL_PRECISION_OFF);
+
+ WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_SNAP_ON);
+ WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_RELEASE, KM_ANY, 0, TWEAK_MODAL_SNAP_OFF);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_SNAP_ON);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, TWEAK_MODAL_SNAP_OFF);
+
+ WM_modalkeymap_assign(keymap, "MANIPULATORGROUP_OT_manipulator_tweak");
+
+ return keymap;
+}
+
+/**
+ * Common default keymap for manipulator groups
+ */
+wmKeyMap *WM_manipulatorgroup_keymap_common(
+ const wmManipulatorGroupType *wgt, wmKeyConfig *config)
+{
+ /* Use area and region id since we might have multiple manipulators with the same name in different areas/regions */
+ wmKeyMap *km = WM_keymap_find(config, wgt->name, wgt->mmap_params.spaceid, wgt->mmap_params.regionid);
+
+ WM_keymap_add_item(km, "MANIPULATORGROUP_OT_manipulator_tweak", LEFTMOUSE, KM_PRESS, KM_ANY, 0);
+ manipulatorgroup_tweak_modal_keymap(config, wgt->name);
+
+ return km;
+}
+
+/**
+ * Variation of #WM_manipulatorgroup_keymap_common but with keymap items for selection
+ */
+wmKeyMap *WM_manipulatorgroup_keymap_common_select(
+ const wmManipulatorGroupType *wgt, wmKeyConfig *config)
+{
+ /* Use area and region id since we might have multiple manipulators with the same name in different areas/regions */
+ wmKeyMap *km = WM_keymap_find(config, wgt->name, wgt->mmap_params.spaceid, wgt->mmap_params.regionid);
+
+ WM_keymap_add_item(km, "MANIPULATORGROUP_OT_manipulator_tweak", ACTIONMOUSE, KM_PRESS, KM_ANY, 0);
+ WM_keymap_add_item(km, "MANIPULATORGROUP_OT_manipulator_tweak", EVT_TWEAK_S, KM_ANY, 0, 0);
+ manipulatorgroup_tweak_modal_keymap(config, wgt->name);
+
+ wmKeyMapItem *kmi = WM_keymap_add_item(km, "MANIPULATORGROUP_OT_manipulator_select", SELECTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "extend", false);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ RNA_boolean_set(kmi->ptr, "toggle", false);
+ kmi = WM_keymap_add_item(km, "MANIPULATORGROUP_OT_manipulator_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", false);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ RNA_boolean_set(kmi->ptr, "toggle", true);
+
+ return km;
+}
+
+/** \} */ /* wmManipulatorGroup */
+
+/* -------------------------------------------------------------------- */
+/** \name wmManipulatorGroupType
+ *
+ * \{ */
+
+struct wmManipulatorGroupTypeRef *WM_manipulatormaptype_group_find_ptr(
+ struct wmManipulatorMapType *mmap_type,
+ const wmManipulatorGroupType *wgt)
+{
+ /* could use hash lookups as operator types do, for now simple search. */
+ for (wmManipulatorGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first;
+ wgt_ref;
+ wgt_ref = wgt_ref->next)
+ {
+ if (wgt_ref->type == wgt) {
+ return wgt_ref;
+ }
+ }
+ return NULL;
+}
+
+struct wmManipulatorGroupTypeRef *WM_manipulatormaptype_group_find(
+ struct wmManipulatorMapType *mmap_type,
+ const char *idname)
+{
+ /* could use hash lookups as operator types do, for now simple search. */
+ for (wmManipulatorGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first;
+ wgt_ref;
+ wgt_ref = wgt_ref->next)
+ {
+ if (STREQ(idname, wgt_ref->type->idname)) {
+ return wgt_ref;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Use this for registering manipulators on startup. For runtime, use #WM_manipulatormaptype_group_link_runtime.
+ */
+wmManipulatorGroupTypeRef *WM_manipulatormaptype_group_link(
+ wmManipulatorMapType *mmap_type, const char *idname)
+{
+ wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(idname, false);
+ BLI_assert(wgt != NULL);
+ return WM_manipulatormaptype_group_link_ptr(mmap_type, wgt);
+}
+
+wmManipulatorGroupTypeRef *WM_manipulatormaptype_group_link_ptr(
+ wmManipulatorMapType *mmap_type, wmManipulatorGroupType *wgt)
+{
+ wmManipulatorGroupTypeRef *wgt_ref = MEM_callocN(sizeof(wmManipulatorGroupTypeRef), "manipulator-group-ref");
+ wgt_ref->type = wgt;
+ BLI_addtail(&mmap_type->grouptype_refs, wgt_ref);
+ return wgt_ref;
+}
+
+void WM_manipulatormaptype_group_init_runtime_keymap(
+ const Main *bmain,
+ wmManipulatorGroupType *wgt)
+{
+ /* init keymap - on startup there's an extra call to init keymaps for 'permanent' manipulator-groups */
+ wm_manipulatorgrouptype_setup_keymap(wgt, ((wmWindowManager *)bmain->wm.first)->defaultconf);
+}
+
+void WM_manipulatormaptype_group_init_runtime(
+ const Main *bmain, wmManipulatorMapType *mmap_type,
+ wmManipulatorGroupType *wgt)
+{
+ /* now create a manipulator for all existing areas */
+ for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ for (ARegion *ar = lb->first; ar; ar = ar->next) {
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ if (mmap && mmap->type == mmap_type) {
+ wm_manipulatorgroup_new_from_type(mmap, wgt);
+
+ /* just add here, drawing will occur on next update */
+ wm_manipulatormap_highlight_set(mmap, NULL, NULL, 0);
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Unlike #WM_manipulatormaptype_group_unlink this doesn't maintain correct state, simply free.
+ */
+void WM_manipulatormaptype_group_free(wmManipulatorGroupTypeRef *wgt_ref)
+{
+ MEM_freeN(wgt_ref);
+}
+
+void WM_manipulatormaptype_group_unlink(
+ bContext *C, Main *bmain, wmManipulatorMapType *mmap_type,
+ const wmManipulatorGroupType *wgt)
+{
+ /* Free instances. */
+ for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ for (ARegion *ar = lb->first; ar; ar = ar->next) {
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ if (mmap && mmap->type == mmap_type) {
+ wmManipulatorGroup *mgroup, *mgroup_next;
+ for (mgroup = mmap->groups.first; mgroup; mgroup = mgroup_next) {
+ mgroup_next = mgroup->next;
+ if (mgroup->type == wgt) {
+ BLI_assert(mgroup->parent_mmap == mmap);
+ wm_manipulatorgroup_free(C, mgroup);
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Free types. */
+ wmManipulatorGroupTypeRef *wgt_ref = WM_manipulatormaptype_group_find_ptr(mmap_type, wgt);
+ if (wgt_ref) {
+ BLI_remlink(&mmap_type->grouptype_refs, wgt_ref);
+ WM_manipulatormaptype_group_free(wgt_ref);
+ }
+
+ /* Note, we may want to keep this keymap for editing */
+ WM_keymap_remove(wgt->keyconf, wgt->keymap);
+
+ BLI_assert(WM_manipulatormaptype_group_find_ptr(mmap_type, wgt) == NULL);
+}
+
+void wm_manipulatorgrouptype_setup_keymap(
+ wmManipulatorGroupType *wgt, wmKeyConfig *keyconf)
+{
+ /* Use flag since setup_keymap may return NULL,
+ * in that case we better not keep calling it. */
+ if (wgt->type_update_flag & WM_MANIPULATORMAPTYPE_KEYMAP_INIT) {
+ wgt->keymap = wgt->setup_keymap(wgt, keyconf);
+ wgt->keyconf = keyconf;
+ wgt->type_update_flag &= ~WM_MANIPULATORMAPTYPE_KEYMAP_INIT;
+ }
+}
+
+/** \} */ /* wmManipulatorGroupType */
+
+/* -------------------------------------------------------------------- */
+/** \name High Level Add/Remove API
+ *
+ * For use directly from operators & RNA registration.
+ *
+ * \note In context of manipulator API these names are a bit misleading,
+ * but for general use terms its OK.
+ * `WM_manipulator_group_type_add` would be more correctly called:
+ * `WM_manipulatormaptype_grouptype_reference_link`
+ * but for general purpose API this is too detailed & annoying.
+ *
+ * \note We may want to return a value if there is nothing to remove.
+ *
+ * \{ */
+
+void WM_manipulator_group_type_add_ptr_ex(
+ wmManipulatorGroupType *wgt,
+ wmManipulatorMapType *mmap_type)
+{
+ WM_manipulatormaptype_group_link_ptr(mmap_type, wgt);
+
+ WM_manipulatorconfig_update_tag_init(mmap_type, wgt);
+}
+void WM_manipulator_group_type_add_ptr(
+ wmManipulatorGroupType *wgt)
+{
+ wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(&wgt->mmap_params);
+ WM_manipulator_group_type_add_ptr_ex(wgt, mmap_type);
+}
+void WM_manipulator_group_type_add(const char *idname)
+{
+ wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(idname, false);
+ BLI_assert(wgt != NULL);
+ WM_manipulator_group_type_add_ptr(wgt);
+}
+
+void WM_manipulator_group_type_ensure_ptr_ex(
+ wmManipulatorGroupType *wgt,
+ wmManipulatorMapType *mmap_type)
+{
+ wmManipulatorGroupTypeRef *wgt_ref = WM_manipulatormaptype_group_find_ptr(mmap_type, wgt);
+ if (wgt_ref == NULL) {
+ WM_manipulator_group_type_add_ptr_ex(wgt, mmap_type);
+ }
+}
+void WM_manipulator_group_type_ensure_ptr(
+ wmManipulatorGroupType *wgt)
+{
+ wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(&wgt->mmap_params);
+ WM_manipulator_group_type_ensure_ptr_ex(wgt, mmap_type);
+}
+void WM_manipulator_group_type_ensure(const char *idname)
+{
+ wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(idname, false);
+ BLI_assert(wgt != NULL);
+ WM_manipulator_group_type_ensure_ptr(wgt);
+}
+
+void WM_manipulator_group_type_remove_ptr_ex(
+ struct Main *bmain, wmManipulatorGroupType *wgt,
+ wmManipulatorMapType *mmap_type)
+{
+ WM_manipulatormaptype_group_unlink(NULL, bmain, mmap_type, wgt);
+ WM_manipulatorgrouptype_free_ptr(wgt);
+}
+void WM_manipulator_group_type_remove_ptr(
+ struct Main *bmain, wmManipulatorGroupType *wgt)
+{
+ wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(&wgt->mmap_params);
+ WM_manipulator_group_type_remove_ptr_ex(bmain, wgt, mmap_type);
+}
+void WM_manipulator_group_type_remove(struct Main *bmain, const char *idname)
+{
+ wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(idname, false);
+ BLI_assert(wgt != NULL);
+ WM_manipulator_group_type_remove_ptr(bmain, wgt);
+}
+
+/* delayed versions */
+
+void WM_manipulator_group_type_unlink_delayed_ptr_ex(
+ wmManipulatorGroupType *wgt,
+ wmManipulatorMapType *mmap_type)
+{
+ WM_manipulatorconfig_update_tag_remove(mmap_type, wgt);
+}
+
+void WM_manipulator_group_type_unlink_delayed_ptr(
+ wmManipulatorGroupType *wgt)
+{
+ wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(&wgt->mmap_params);
+ WM_manipulator_group_type_unlink_delayed_ptr_ex(wgt, mmap_type);
+}
+
+void WM_manipulator_group_type_unlink_delayed(const char *idname)
+{
+ wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(idname, false);
+ BLI_assert(wgt != NULL);
+ WM_manipulator_group_type_unlink_delayed_ptr(wgt);
+}
+
+/** \} */
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group_type.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group_type.c
new file mode 100644
index 00000000000..d97305458e8
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group_type.c
@@ -0,0 +1,198 @@
+/*
+ * ***** 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/windowmanager/manipulators/intern/wm_manipulator_group_type.c
+ * \ingroup wm
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
+
+#include "BKE_context.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* only for own init/exit calls (wm_manipulatorgrouptype_init/wm_manipulatorgrouptype_free) */
+#include "wm.h"
+
+/* own includes */
+#include "wm_manipulator_wmapi.h"
+#include "wm_manipulator_intern.h"
+
+
+/** \name ManipulatorGroup Type Append
+ *
+ * \note This follows conventions from #WM_operatortype_find #WM_operatortype_append & friends.
+ * \{ */
+
+static GHash *global_manipulatorgrouptype_hash = NULL;
+
+wmManipulatorGroupType *WM_manipulatorgrouptype_find(const char *idname, bool quiet)
+{
+ if (idname[0]) {
+ wmManipulatorGroupType *wgt;
+
+ wgt = BLI_ghash_lookup(global_manipulatorgrouptype_hash, idname);
+ if (wgt) {
+ return wgt;
+ }
+
+ if (!quiet) {
+ printf("search for unknown manipulator group '%s'\n", idname);
+ }
+ }
+ else {
+ if (!quiet) {
+ printf("search for empty manipulator group\n");
+ }
+ }
+
+ return NULL;
+}
+
+/* caller must free */
+void WM_manipulatorgrouptype_iter(GHashIterator *ghi)
+{
+ BLI_ghashIterator_init(ghi, global_manipulatorgrouptype_hash);
+}
+
+static wmManipulatorGroupType *wm_manipulatorgrouptype_append__begin(void)
+{
+ wmManipulatorGroupType *wgt = MEM_callocN(sizeof(wmManipulatorGroupType), "manipulatorgrouptype");
+
+ return wgt;
+}
+static void wm_manipulatorgrouptype_append__end(wmManipulatorGroupType *wgt)
+{
+ BLI_assert(wgt->name != NULL);
+ BLI_assert(wgt->idname != NULL);
+
+ wgt->type_update_flag |= WM_MANIPULATORMAPTYPE_KEYMAP_INIT;
+
+ /* if not set, use default */
+ if (wgt->setup_keymap == NULL) {
+ if (wgt->flag & WM_MANIPULATORGROUPTYPE_SELECT) {
+ wgt->setup_keymap = WM_manipulatorgroup_keymap_common_select;
+ }
+ else {
+ wgt->setup_keymap = WM_manipulatorgroup_keymap_common;
+ }
+ }
+
+ BLI_ghash_insert(global_manipulatorgrouptype_hash, (void *)wgt->idname, wgt);
+}
+
+wmManipulatorGroupType *WM_manipulatorgrouptype_append(
+ void (*wtfunc)(struct wmManipulatorGroupType *))
+{
+ wmManipulatorGroupType *wgt = wm_manipulatorgrouptype_append__begin();
+ wtfunc(wgt);
+ wm_manipulatorgrouptype_append__end(wgt);
+ return wgt;
+}
+
+wmManipulatorGroupType *WM_manipulatorgrouptype_append_ptr(
+ void (*wtfunc)(struct wmManipulatorGroupType *, void *), void *userdata)
+{
+ wmManipulatorGroupType *wgt = wm_manipulatorgrouptype_append__begin();
+ wtfunc(wgt, userdata);
+ wm_manipulatorgrouptype_append__end(wgt);
+ return wgt;
+}
+
+/**
+ * Append and insert into a manipulator typemap.
+ * This is most common for C manipulators which are enabled by default.
+ */
+wmManipulatorGroupTypeRef *WM_manipulatorgrouptype_append_and_link(
+ wmManipulatorMapType *mmap_type,
+ void (*wtfunc)(struct wmManipulatorGroupType *))
+{
+ wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_append(wtfunc);
+
+ wgt->mmap_params.spaceid = mmap_type->spaceid;
+ wgt->mmap_params.regionid = mmap_type->regionid;
+
+ return WM_manipulatormaptype_group_link_ptr(mmap_type, wgt);
+}
+
+/**
+ * Free but don't remove from ghash.
+ */
+static void manipulatorgrouptype_free(wmManipulatorGroupType *wgt)
+{
+ if (wgt->ext.srna) { /* python manipulator group, allocs own string */
+ MEM_freeN((void *)wgt->idname);
+ }
+
+ MEM_freeN(wgt);
+}
+
+void WM_manipulatorgrouptype_free_ptr(wmManipulatorGroupType *wgt)
+{
+ BLI_assert(wgt == WM_manipulatorgrouptype_find(wgt->idname, false));
+
+ BLI_ghash_remove(global_manipulatorgrouptype_hash, wgt->idname, NULL, NULL);
+
+ manipulatorgrouptype_free(wgt);
+
+ /* XXX, TODO, update the world! */
+}
+
+bool WM_manipulatorgrouptype_free(const char *idname)
+{
+ wmManipulatorGroupType *wgt = BLI_ghash_lookup(global_manipulatorgrouptype_hash, idname);
+
+ if (wgt == NULL) {
+ return false;
+ }
+
+ WM_manipulatorgrouptype_free_ptr(wgt);
+
+ return true;
+}
+
+static void wm_manipulatorgrouptype_ghash_free_cb(wmManipulatorGroupType *mt)
+{
+ manipulatorgrouptype_free(mt);
+}
+
+void wm_manipulatorgrouptype_free(void)
+{
+ BLI_ghash_free(global_manipulatorgrouptype_hash, NULL, (GHashValFreeFP)wm_manipulatorgrouptype_ghash_free_cb);
+ global_manipulatorgrouptype_hash = NULL;
+}
+
+/* called on initialize WM_init() */
+void wm_manipulatorgrouptype_init(void)
+{
+ /* reserve size is set based on blender default setup */
+ global_manipulatorgrouptype_hash = BLI_ghash_str_new_ex("wm_manipulatorgrouptype_init gh", 128);
+}
+
+/** \} */
+
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
new file mode 100644
index 00000000000..bf5c38b9e39
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
@@ -0,0 +1,140 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
+ * \ingroup wm
+ */
+
+
+#ifndef __WM_MANIPULATOR_INTERN_H__
+#define __WM_MANIPULATOR_INTERN_H__
+
+struct wmKeyConfig;
+struct wmManipulatorMap;
+struct ManipulatorGeomInfo;
+struct GHashIterator;
+
+#include "wm_manipulator_fn.h"
+
+/* -------------------------------------------------------------------- */
+/* wmManipulator */
+
+
+bool wm_manipulator_select_set_ex(
+ struct wmManipulatorMap *mmap, struct wmManipulator *mpr, bool select,
+ bool use_array, bool use_callback);
+bool wm_manipulator_select_and_highlight(bContext *C, struct wmManipulatorMap *mmap, struct wmManipulator *mpr);
+
+void wm_manipulator_calculate_scale(struct wmManipulator *mpr, const bContext *C);
+void wm_manipulator_update(struct wmManipulator *mpr, const bContext *C, const bool refresh_map);
+
+int wm_manipulator_is_visible(struct wmManipulator *mpr);
+enum {
+ WM_MANIPULATOR_IS_VISIBLE_UPDATE = (1 << 0),
+ WM_MANIPULATOR_IS_VISIBLE_DRAW = (1 << 1),
+};
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorGroup */
+
+enum {
+ TWEAK_MODAL_CANCEL = 1,
+ TWEAK_MODAL_CONFIRM,
+ TWEAK_MODAL_PRECISION_ON,
+ TWEAK_MODAL_PRECISION_OFF,
+ TWEAK_MODAL_SNAP_ON,
+ TWEAK_MODAL_SNAP_OFF,
+};
+
+struct wmManipulatorGroup *wm_manipulatorgroup_new_from_type(
+ struct wmManipulatorMap *mmap, struct wmManipulatorGroupType *wgt);
+void wm_manipulatorgroup_free(bContext *C, struct wmManipulatorGroup *mgroup);
+void wm_manipulatorgroup_manipulator_register(struct wmManipulatorGroup *mgroup, struct wmManipulator *mpr);
+struct wmManipulator *wm_manipulatorgroup_find_intersected_mainpulator(
+ const struct wmManipulatorGroup *mgroup, struct bContext *C, const struct wmEvent *event,
+ int *r_part);
+void wm_manipulatorgroup_intersectable_manipulators_to_list(
+ const struct wmManipulatorGroup *mgroup, struct ListBase *listbase);
+void wm_manipulatorgroup_ensure_initialized(struct wmManipulatorGroup *mgroup, const struct bContext *C);
+bool wm_manipulatorgroup_is_visible(const struct wmManipulatorGroup *mgroup, const struct bContext *C);
+bool wm_manipulatorgroup_is_visible_in_drawstep(
+ const struct wmManipulatorGroup *mgroup, const eWM_ManipulatorMapDrawStep drawstep);
+
+void wm_manipulatorgrouptype_setup_keymap(
+ struct wmManipulatorGroupType *wgt, struct wmKeyConfig *keyconf);
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorMap */
+
+typedef struct wmManipulatorMapSelectState {
+ struct wmManipulator **items;
+ int len, len_alloc;
+} wmManipulatorMapSelectState;
+
+struct wmManipulatorMap {
+
+ struct wmManipulatorMapType *type;
+ ListBase groups; /* wmManipulatorGroup */
+
+ /* private, update tagging (enum defined in C source). */
+ char update_flag[WM_MANIPULATORMAP_DRAWSTEP_MAX];
+
+ /**
+ * \brief Manipulator map runtime context
+ *
+ * Contains information about this manipulator-map. Currently
+ * highlighted manipulator, currently selected manipulators, ...
+ */
+ struct {
+ /* we redraw the manipulator-map when this changes */
+ struct wmManipulator *highlight;
+ /* User has clicked this manipulator and it gets all input. */
+ struct wmManipulator *modal;
+ /* array for all selected manipulators */
+ struct wmManipulatorMapSelectState select;
+ } mmap_context;
+};
+
+/**
+ * This is a container for all manipulator types that can be instantiated in a region.
+ * (similar to dropboxes).
+ *
+ * \note There is only ever one of these for every (area, region) combination.
+ */
+struct wmManipulatorMapType {
+ struct wmManipulatorMapType *next, *prev;
+ short spaceid, regionid;
+ /* types of manipulator-groups for this manipulator-map type */
+ ListBase grouptype_refs;
+
+ /* eManipulatorMapTypeUpdateFlags */
+ eWM_ManipulatorMapTypeUpdateFlag type_update_flag;
+};
+
+void wm_manipulatormap_select_array_clear(struct wmManipulatorMap *mmap);
+bool wm_manipulatormap_deselect_all(struct wmManipulatorMap *mmap);
+void wm_manipulatormap_select_array_shrink(struct wmManipulatorMap *mmap, int len_subtract);
+void wm_manipulatormap_select_array_push_back(struct wmManipulatorMap *mmap, wmManipulator *mpr);
+void wm_manipulatormap_select_array_remove(struct wmManipulatorMap *mmap, wmManipulator *mpr);
+
+#endif
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
new file mode 100644
index 00000000000..5d9810272cc
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
@@ -0,0 +1,1139 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/intern/wm_manipulator_map.c
+ * \ingroup wm
+ */
+
+#include <string.h>
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
+#include "BLI_ghash.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "GPU_glew.h"
+#include "GPU_matrix.h"
+#include "GPU_select.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm_event_system.h"
+
+#include "DEG_depsgraph.h"
+
+/* own includes */
+#include "wm_manipulator_wmapi.h"
+#include "wm_manipulator_intern.h"
+
+/**
+ * Store all manipulator-maps here. Anyone who wants to register a manipulator for a certain
+ * area type can query the manipulator-map to do so.
+ */
+static ListBase manipulatormaptypes = {NULL, NULL};
+
+/**
+ * Update when manipulator-map types change.
+ */
+/* so operator removal can trigger update */
+typedef enum eWM_ManipulatorGroupTypeGlobalFlag {
+ WM_MANIPULATORMAPTYPE_GLOBAL_UPDATE_INIT = (1 << 0),
+ WM_MANIPULATORMAPTYPE_GLOBAL_UPDATE_REMOVE = (1 << 1),
+} eWM_ManipulatorGroupTypeGlobalFlag;
+
+static eWM_ManipulatorGroupTypeGlobalFlag wm_mmap_type_update_flag = 0;
+
+/**
+ * Manipulator-map update tagging.
+ */
+enum {
+ /** #manipulatormap_prepare_drawing has run */
+ MANIPULATORMAP_IS_PREPARE_DRAW = (1 << 0),
+ MANIPULATORMAP_IS_REFRESH_CALLBACK = (1 << 1),
+};
+
+
+/* -------------------------------------------------------------------- */
+/** \name wmManipulatorMap Selection Array API
+ *
+ * Just handle ``wm_manipulatormap_select_array_*``, not flags or callbacks.
+ *
+ * \{ */
+
+static void wm_manipulatormap_select_array_ensure_len_alloc(wmManipulatorMap *mmap, int len)
+{
+ wmManipulatorMapSelectState *msel = &mmap->mmap_context.select;
+ if (len <= msel->len_alloc) {
+ return;
+ }
+ msel->items = MEM_reallocN(msel->items, sizeof(*msel->items) * len);
+ msel->len_alloc = len;
+}
+
+void wm_manipulatormap_select_array_clear(wmManipulatorMap *mmap)
+{
+ wmManipulatorMapSelectState *msel = &mmap->mmap_context.select;
+ MEM_SAFE_FREE(msel->items);
+ msel->len = 0;
+ msel->len_alloc = 0;
+}
+
+void wm_manipulatormap_select_array_shrink(wmManipulatorMap *mmap, int len_subtract)
+{
+ wmManipulatorMapSelectState *msel = &mmap->mmap_context.select;
+ msel->len -= len_subtract;
+ if (msel->len <= 0) {
+ wm_manipulatormap_select_array_clear(mmap);
+ }
+ else {
+ if (msel->len < msel->len_alloc / 2) {
+ msel->items = MEM_reallocN(msel->items, sizeof(*msel->items) * msel->len);
+ msel->len_alloc = msel->len;
+ }
+ }
+}
+
+void wm_manipulatormap_select_array_push_back(wmManipulatorMap *mmap, wmManipulator *mpr)
+{
+ wmManipulatorMapSelectState *msel = &mmap->mmap_context.select;
+ BLI_assert(msel->len <= msel->len_alloc);
+ if (msel->len == msel->len_alloc) {
+ msel->len_alloc = (msel->len + 1) * 2;
+ msel->items = MEM_reallocN(msel->items, sizeof(*msel->items) * msel->len_alloc);
+ }
+ msel->items[msel->len++] = mpr;
+}
+
+void wm_manipulatormap_select_array_remove(wmManipulatorMap *mmap, wmManipulator *mpr)
+{
+ wmManipulatorMapSelectState *msel = &mmap->mmap_context.select;
+ /* remove manipulator from selected_manipulators array */
+ for (int i = 0; i < msel->len; i++) {
+ if (msel->items[i] == mpr) {
+ for (int j = i; j < (msel->len - 1); j++) {
+ msel->items[j] = msel->items[j + 1];
+ }
+ wm_manipulatormap_select_array_shrink(mmap, 1);
+ break;
+ }
+ }
+
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name wmManipulatorMap
+ *
+ * \{ */
+
+/**
+ * Creates a manipulator-map with all registered manipulators for that type
+ */
+wmManipulatorMap *WM_manipulatormap_new_from_type(
+ const struct wmManipulatorMapType_Params *mmap_params)
+{
+ wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(mmap_params);
+ wmManipulatorMap *mmap;
+
+ mmap = MEM_callocN(sizeof(wmManipulatorMap), "ManipulatorMap");
+ mmap->type = mmap_type;
+ WM_manipulatormap_tag_refresh(mmap);
+
+ /* create all manipulator-groups for this manipulator-map. We may create an empty one
+ * too in anticipation of manipulators from operators etc */
+ for (wmManipulatorGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first; wgt_ref; wgt_ref = wgt_ref->next) {
+ wm_manipulatorgroup_new_from_type(mmap, wgt_ref->type);
+ }
+
+ return mmap;
+}
+
+void wm_manipulatormap_remove(wmManipulatorMap *mmap)
+{
+ /* Clear first so further calls don't waste time trying to maintain correct array state. */
+ wm_manipulatormap_select_array_clear(mmap);
+
+ for (wmManipulatorGroup *mgroup = mmap->groups.first, *mgroup_next; mgroup; mgroup = mgroup_next) {
+ mgroup_next = mgroup->next;
+ BLI_assert(mgroup->parent_mmap == mmap);
+ wm_manipulatorgroup_free(NULL, mgroup);
+ }
+ BLI_assert(BLI_listbase_is_empty(&mmap->groups));
+
+ MEM_freeN(mmap);
+}
+
+
+wmManipulatorGroup *WM_manipulatormap_group_find(
+ struct wmManipulatorMap *mmap,
+ const char *idname)
+{
+ wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(idname, false);
+ if (wgt) {
+ return WM_manipulatormap_group_find_ptr(mmap, wgt);
+ }
+ return NULL;
+}
+
+wmManipulatorGroup *WM_manipulatormap_group_find_ptr(
+ struct wmManipulatorMap *mmap,
+ const struct wmManipulatorGroupType *wgt)
+{
+ for (wmManipulatorGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
+ if (mgroup->type == wgt) {
+ return mgroup;
+ }
+ }
+ return NULL;
+}
+
+const ListBase *WM_manipulatormap_group_list(wmManipulatorMap *mmap)
+{
+ return &mmap->groups;
+}
+
+bool WM_manipulatormap_is_any_selected(const wmManipulatorMap *mmap)
+{
+ return mmap->mmap_context.select.len != 0;
+}
+
+/**
+ * \note We could use a callback to define bounds, for now just use matrix location.
+ */
+bool WM_manipulatormap_minmax(
+ const wmManipulatorMap *mmap, bool UNUSED(use_hidden), bool use_select,
+ float r_min[3], float r_max[3])
+{
+ if (use_select) {
+ int i;
+ for (i = 0; i < mmap->mmap_context.select.len; i++) {
+ minmax_v3v3_v3(r_min, r_max, mmap->mmap_context.select.items[i]->matrix_basis[3]);
+ }
+ return i != 0;
+ }
+ else {
+ bool ok = false;
+ BLI_assert(!"TODO");
+ return ok;
+ }
+}
+
+/**
+ * Creates and returns idname hash table for (visible) manipulators in \a mmap
+ *
+ * \param poll Polling function for excluding manipulators.
+ * \param data Custom data passed to \a poll
+ *
+ * TODO(campbell): this uses unreliable order,
+ * best we use an iterator function instead of a hash.
+ */
+static GHash *WM_manipulatormap_manipulator_hash_new(
+ const bContext *C, wmManipulatorMap *mmap,
+ bool (*poll)(const wmManipulator *, void *),
+ void *data, const bool include_hidden)
+{
+ GHash *hash = BLI_ghash_ptr_new(__func__);
+
+ /* collect manipulators */
+ for (wmManipulatorGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
+ if (!mgroup->type->poll || mgroup->type->poll(C, mgroup->type)) {
+ for (wmManipulator *mpr = mgroup->manipulators.first; mpr; mpr = mpr->next) {
+ if ((include_hidden || (mpr->flag & WM_MANIPULATOR_HIDDEN) == 0) &&
+ (!poll || poll(mpr, data)))
+ {
+ BLI_ghash_insert(hash, mpr, mpr);
+ }
+ }
+ }
+ }
+
+ return hash;
+}
+
+void WM_manipulatormap_tag_refresh(wmManipulatorMap *mmap)
+{
+ if (mmap) {
+ /* We might want only to refresh some, for tag all steps. */
+ for (int i = 0; i < WM_MANIPULATORMAP_DRAWSTEP_MAX; i++) {
+ mmap->update_flag[i] |= (
+ MANIPULATORMAP_IS_PREPARE_DRAW |
+ MANIPULATORMAP_IS_REFRESH_CALLBACK);
+ }
+ }
+}
+
+static bool manipulator_prepare_drawing(
+ wmManipulatorMap *mmap, wmManipulator *mpr,
+ const bContext *C, ListBase *draw_manipulators,
+ const eWM_ManipulatorMapDrawStep drawstep)
+{
+ int do_draw = wm_manipulator_is_visible(mpr);
+ if (do_draw == 0) {
+ /* skip */
+ }
+ else {
+ /* Ensure we get RNA updates */
+ if (do_draw & WM_MANIPULATOR_IS_VISIBLE_UPDATE) {
+ /* hover manipulators need updating, even if we don't draw them */
+ wm_manipulator_update(mpr, C, (mmap->update_flag[drawstep] & MANIPULATORMAP_IS_PREPARE_DRAW) != 0);
+ }
+ if (do_draw & WM_MANIPULATOR_IS_VISIBLE_DRAW) {
+ BLI_addhead(draw_manipulators, BLI_genericNodeN(mpr));
+ }
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Update manipulators of \a mmap to prepare for drawing. Adds all manipulators that
+ * should be drawn to list \a draw_manipulators, note that added items need freeing.
+ */
+static void manipulatormap_prepare_drawing(
+ wmManipulatorMap *mmap, const bContext *C, ListBase *draw_manipulators,
+ const eWM_ManipulatorMapDrawStep drawstep)
+{
+ if (!mmap || BLI_listbase_is_empty(&mmap->groups))
+ return;
+ wmManipulator *mpr_modal = mmap->mmap_context.modal;
+
+ /* only active manipulator needs updating */
+ if (mpr_modal) {
+ if ((mpr_modal->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_DRAW_MODAL_ALL) == 0) {
+ if (wm_manipulatorgroup_is_visible_in_drawstep(mpr_modal->parent_mgroup, drawstep)) {
+ if (manipulator_prepare_drawing(mmap, mpr_modal, C, draw_manipulators, drawstep)) {
+ mmap->update_flag[drawstep] &= ~MANIPULATORMAP_IS_PREPARE_DRAW;
+ }
+ }
+ /* don't draw any other manipulators */
+ return;
+ }
+ }
+
+ for (wmManipulatorGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
+ /* check group visibility - drawstep first to avoid unnecessary call of group poll callback */
+ if (!wm_manipulatorgroup_is_visible_in_drawstep(mgroup, drawstep) ||
+ !wm_manipulatorgroup_is_visible(mgroup, C))
+ {
+ continue;
+ }
+
+ /* needs to be initialized on first draw */
+ /* XXX weak: Manipulator-group may skip refreshing if it's invisible (map gets untagged nevertheless) */
+ if (mmap->update_flag[drawstep] & MANIPULATORMAP_IS_REFRESH_CALLBACK) {
+ /* force refresh again. */
+ mgroup->init_flag &= ~WM_MANIPULATORGROUP_INIT_REFRESH;
+ }
+ /* Calls `setup`, `setup_keymap` and `refresh` if they're defined. */
+ wm_manipulatorgroup_ensure_initialized(mgroup, C);
+
+ /* prepare drawing */
+ if (mgroup->type->draw_prepare) {
+ mgroup->type->draw_prepare(C, mgroup);
+ }
+
+ for (wmManipulator *mpr = mgroup->manipulators.first; mpr; mpr = mpr->next) {
+ manipulator_prepare_drawing(mmap, mpr, C, draw_manipulators, drawstep);
+ }
+ }
+
+ mmap->update_flag[drawstep] &=
+ ~(MANIPULATORMAP_IS_REFRESH_CALLBACK |
+ MANIPULATORMAP_IS_PREPARE_DRAW);
+}
+
+/**
+ * Draw all visible manipulators in \a mmap.
+ * Uses global draw_manipulators listbase.
+ */
+static void manipulators_draw_list(const wmManipulatorMap *mmap, const bContext *C, ListBase *draw_manipulators)
+{
+ /* Can be empty if we're dynamically added and removed. */
+ if ((mmap == NULL) || BLI_listbase_is_empty(&mmap->groups)) {
+ return;
+ }
+
+ const bool draw_multisample = (U.ogl_multisamples != USER_MULTISAMPLE_NONE);
+
+ /* TODO this will need it own shader probably? don't think it can be handled from that point though. */
+/* const bool use_lighting = (U.manipulator_flag & V3D_MANIPULATOR_SHADED) != 0; */
+
+ /* enable multisampling */
+ if (draw_multisample) {
+ glEnable(GL_MULTISAMPLE);
+ }
+
+ bool is_depth_prev = false;
+
+ /* draw_manipulators contains all visible manipulators - draw them */
+ for (LinkData *link = draw_manipulators->first, *link_next; link; link = link_next) {
+ wmManipulator *mpr = link->data;
+ link_next = link->next;
+
+ bool is_depth = (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_DEPTH_3D) != 0;
+
+ /* Weak! since we don't 100% support depth yet (select ignores depth) always show highlighted */
+ if (is_depth && (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT)) {
+ is_depth = false;
+ }
+
+ if (is_depth == is_depth_prev) {
+ /* pass */
+ }
+ else {
+ if (is_depth) {
+ glEnable(GL_DEPTH_TEST);
+ }
+ else {
+ glDisable(GL_DEPTH_TEST);
+ }
+ is_depth_prev = is_depth;
+ }
+
+ mpr->type->draw(C, mpr);
+ /* free/remove manipulator link after drawing */
+ BLI_freelinkN(draw_manipulators, link);
+ }
+
+ if (is_depth_prev) {
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ if (draw_multisample) {
+ glDisable(GL_MULTISAMPLE);
+ }
+}
+
+void WM_manipulatormap_draw(
+ wmManipulatorMap *mmap, const bContext *C,
+ const eWM_ManipulatorMapDrawStep drawstep)
+{
+ ListBase draw_manipulators = {NULL};
+
+ manipulatormap_prepare_drawing(mmap, C, &draw_manipulators, drawstep);
+ manipulators_draw_list(mmap, C, &draw_manipulators);
+ BLI_assert(BLI_listbase_is_empty(&draw_manipulators));
+}
+
+static void manipulator_draw_select_3D_loop(const bContext *C, ListBase *visible_manipulators)
+{
+ int select_id = 0;
+ wmManipulator *mpr;
+
+ /* TODO(campbell): this depends on depth buffer being written to, currently broken for the 3D view. */
+ bool is_depth_prev = false;
+
+ for (LinkData *link = visible_manipulators->first; link; link = link->next) {
+ mpr = link->data;
+
+ bool is_depth = (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_DEPTH_3D) != 0;
+ if (is_depth == is_depth_prev) {
+ /* pass */
+ }
+ else {
+ if (is_depth) {
+ glEnable(GL_DEPTH_TEST);
+ }
+ else {
+ glDisable(GL_DEPTH_TEST);
+ }
+ is_depth_prev = is_depth;
+ }
+
+ /* pass the selection id shifted by 8 bits. Last 8 bits are used for selected manipulator part id */
+
+ mpr->type->draw_select(C, mpr, select_id << 8);
+
+
+ select_id++;
+ }
+
+ if (is_depth_prev) {
+ glDisable(GL_DEPTH_TEST);
+ }
+}
+
+static int manipulator_find_intersected_3d_intern(
+ ListBase *visible_manipulators, const bContext *C, const int co[2],
+ const int hotspot)
+{
+ EvaluationContext eval_ctx;
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = sa->spacedata.first;
+ rcti rect;
+ /* Almost certainly overkill, but allow for many custom manipulators. */
+ GLuint buffer[MAXPICKBUF];
+ short hits;
+ const bool do_passes = GPU_select_query_check_active();
+
+ BLI_rcti_init_pt_radius(&rect, co, hotspot);
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ ED_view3d_draw_setup_view(CTX_wm_window(C), &eval_ctx, CTX_data_scene(C), ar, v3d, NULL, NULL, &rect);
+
+ if (do_passes)
+ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
+ else
+ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_ALL, 0);
+ /* do the drawing */
+ manipulator_draw_select_3D_loop(C, visible_manipulators);
+
+ hits = GPU_select_end();
+
+ if (do_passes && (hits > 0)) {
+ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+ manipulator_draw_select_3D_loop(C, visible_manipulators);
+ GPU_select_end();
+ }
+
+ ED_view3d_draw_setup_view(CTX_wm_window(C), &eval_ctx, CTX_data_scene(C), ar, v3d, NULL, NULL, NULL);
+
+ const GLuint *hit_near = GPU_select_buffer_near(buffer, hits);
+
+ return hit_near ? hit_near[3] : -1;
+}
+
+/**
+ * Try to find a 3D manipulator at screen-space coordinate \a co. Uses OpenGL picking.
+ */
+static wmManipulator *manipulator_find_intersected_3d(
+ bContext *C, const int co[2], ListBase *visible_manipulators,
+ int *r_part)
+{
+ wmManipulator *result = NULL;
+ int hit = -1;
+
+ int hotspot_radii[] = {
+ 3 * U.pixelsize,
+#if 0 /* We may want to enable when selection doesn't run on mousemove! */
+ 7 * U.pixelsize,
+#endif
+ };
+
+ *r_part = 0;
+ /* set up view matrices */
+ view3d_operator_needs_opengl(C);
+
+ hit = -1;
+
+ for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) {
+ hit = manipulator_find_intersected_3d_intern(visible_manipulators, C, co, hotspot_radii[i]);
+ if (hit != -1) {
+ break;
+ }
+ }
+
+ if (hit != -1) {
+ LinkData *link = BLI_findlink(visible_manipulators, hit >> 8);
+ if (link != NULL) {
+ *r_part = hit & 255;
+ result = link->data;
+ }
+ else {
+ /* All manipulators should use selection ID they're given as part of the callback,
+ * if they don't it will attempt tp lookup non-existing index. */
+ BLI_assert(0);
+ }
+ }
+
+ return result;
+}
+
+/**
+ * Try to find a manipulator under the mouse position. 2D intersections have priority over
+ * 3D ones (could check for smallest screen-space distance but not needed right now).
+ */
+wmManipulator *wm_manipulatormap_highlight_find(
+ wmManipulatorMap *mmap, bContext *C, const wmEvent *event,
+ int *r_part)
+{
+ wmManipulator *mpr = NULL;
+ ListBase visible_3d_manipulators = {NULL};
+
+ for (wmManipulatorGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
+
+ /* If it were important we could initialize here,
+ * but this only happens when events are handled before drawing,
+ * just skip to keep code-path for initializing manipulators simple. */
+ if ((mgroup->init_flag & WM_MANIPULATORGROUP_INIT_SETUP) == 0) {
+ continue;
+ }
+
+ if (wm_manipulatorgroup_is_visible(mgroup, C)) {
+ if (mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) {
+ if ((mmap->update_flag[WM_MANIPULATORMAP_DRAWSTEP_3D] & MANIPULATORMAP_IS_REFRESH_CALLBACK) &&
+ mgroup->type->refresh)
+ {
+ mgroup->type->refresh(C, mgroup);
+ /* cleared below */
+ }
+ wm_manipulatorgroup_intersectable_manipulators_to_list(mgroup, &visible_3d_manipulators);
+ }
+ else {
+ if ((mmap->update_flag[WM_MANIPULATORMAP_DRAWSTEP_2D] & MANIPULATORMAP_IS_REFRESH_CALLBACK) &&
+ mgroup->type->refresh)
+ {
+ mgroup->type->refresh(C, mgroup);
+ /* cleared below */
+ }
+
+ if ((mpr = wm_manipulatorgroup_find_intersected_mainpulator(mgroup, C, event, r_part))) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (!BLI_listbase_is_empty(&visible_3d_manipulators)) {
+ /* 2D manipulators get priority. */
+ if (mpr == NULL) {
+ mpr = manipulator_find_intersected_3d(C, event->mval, &visible_3d_manipulators, r_part);
+ }
+ BLI_freelistN(&visible_3d_manipulators);
+ }
+
+ mmap->update_flag[WM_MANIPULATORMAP_DRAWSTEP_3D] &= ~MANIPULATORMAP_IS_REFRESH_CALLBACK;
+ mmap->update_flag[WM_MANIPULATORMAP_DRAWSTEP_2D] &= ~MANIPULATORMAP_IS_REFRESH_CALLBACK;
+
+ return mpr;
+}
+
+void WM_manipulatormap_add_handlers(ARegion *ar, wmManipulatorMap *mmap)
+{
+ wmEventHandler *handler;
+
+ for (handler = ar->handlers.first; handler; handler = handler->next) {
+ if (handler->manipulator_map == mmap) {
+ return;
+ }
+ }
+
+ handler = MEM_callocN(sizeof(wmEventHandler), "manipulator handler");
+
+ BLI_assert(mmap == ar->manipulator_map);
+ handler->manipulator_map = mmap;
+ BLI_addtail(&ar->handlers, handler);
+}
+
+void wm_manipulatormaps_handled_modal_update(
+ bContext *C, wmEvent *event, wmEventHandler *handler)
+{
+ const bool modal_running = (handler->op != NULL);
+
+ /* happens on render or when joining areas */
+ if (!handler->op_region || !handler->op_region->manipulator_map) {
+ return;
+ }
+
+ wmManipulatorMap *mmap = handler->op_region->manipulator_map;
+ wmManipulator *mpr = wm_manipulatormap_modal_get(mmap);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+
+ wm_manipulatormap_handler_context(C, handler);
+
+ /* regular update for running operator */
+ if (modal_running) {
+ wmManipulatorOpElem *mpop = mpr ? WM_manipulator_operator_get(mpr, mpr->highlight_part) : NULL;
+ if (mpr && mpop && (mpop->type != NULL) && (mpop->type == handler->op->type)) {
+ wmManipulatorFnModal modal_fn = mpr->custom_modal ? mpr->custom_modal : mpr->type->modal;
+ if (modal_fn != NULL) {
+ int retval = modal_fn(C, mpr, event, 0);
+ /* The manipulator is tried to the operator, we can't choose when to exit. */
+ BLI_assert(retval & OPERATOR_RUNNING_MODAL);
+ UNUSED_VARS_NDEBUG(retval);
+ }
+ }
+ }
+ /* operator not running anymore */
+ else {
+ wm_manipulatormap_highlight_set(mmap, C, NULL, 0);
+ if (mpr) {
+ /* This isn't defined if it ends because of success of cancel, we may want to change. */
+ bool cancel = true;
+ if (mpr->type->exit) {
+ mpr->type->exit(C, mpr, cancel);
+ }
+ wm_manipulatormap_modal_set(mmap, C, mpr, NULL, false);
+ }
+ }
+
+ /* restore the area */
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
+}
+
+/**
+ * Deselect all selected manipulators in \a mmap.
+ * \return if selection has changed.
+ */
+bool wm_manipulatormap_deselect_all(wmManipulatorMap *mmap)
+{
+ wmManipulatorMapSelectState *msel = &mmap->mmap_context.select;
+
+ if (msel->items == NULL || msel->len == 0) {
+ return false;
+ }
+
+ for (int i = 0; i < msel->len; i++) {
+ wm_manipulator_select_set_ex(mmap, msel->items[i], false, false, true);
+ }
+
+ wm_manipulatormap_select_array_clear(mmap);
+
+ /* always return true, we already checked
+ * if there's anything to deselect */
+ return true;
+}
+
+BLI_INLINE bool manipulator_selectable_poll(const wmManipulator *mpr, void *UNUSED(data))
+{
+ return (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_SELECT);
+}
+
+/**
+ * Select all selectable manipulators in \a mmap.
+ * \return if selection has changed.
+ */
+static bool wm_manipulatormap_select_all_intern(
+ bContext *C, wmManipulatorMap *mmap)
+{
+ wmManipulatorMapSelectState *msel = &mmap->mmap_context.select;
+ /* GHash is used here to avoid having to loop over all manipulators twice (once to
+ * get tot_sel for allocating, once for actually selecting). Instead we collect
+ * selectable manipulators in hash table and use this to get tot_sel and do selection */
+
+ GHash *hash = WM_manipulatormap_manipulator_hash_new(C, mmap, manipulator_selectable_poll, NULL, true);
+ GHashIterator gh_iter;
+ int i;
+ bool changed = false;
+
+ wm_manipulatormap_select_array_ensure_len_alloc(mmap, BLI_ghash_size(hash));
+
+ GHASH_ITER_INDEX (gh_iter, hash, i) {
+ wmManipulator *mpr_iter = BLI_ghashIterator_getValue(&gh_iter);
+ WM_manipulator_select_set(mmap, mpr_iter, true);
+ }
+ /* highlight first manipulator */
+ wm_manipulatormap_highlight_set(mmap, C, msel->items[0], msel->items[0]->highlight_part);
+
+ BLI_assert(BLI_ghash_size(hash) == msel->len);
+
+ BLI_ghash_free(hash, NULL, NULL);
+ return changed;
+}
+
+/**
+ * Select/Deselect all selectable manipulators in \a mmap.
+ * \return if selection has changed.
+ *
+ * TODO select all by type
+ */
+bool WM_manipulatormap_select_all(bContext *C, wmManipulatorMap *mmap, const int action)
+{
+ bool changed = false;
+
+ switch (action) {
+ case SEL_SELECT:
+ changed = wm_manipulatormap_select_all_intern(C, mmap);
+ break;
+ case SEL_DESELECT:
+ changed = wm_manipulatormap_deselect_all(mmap);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if (changed)
+ WM_event_add_mousemove(C);
+
+ return changed;
+}
+
+/**
+ * Prepare context for manipulator handling (but only if area/region is
+ * part of screen). Version of #wm_handler_op_context for manipulators.
+ */
+void wm_manipulatormap_handler_context(bContext *C, wmEventHandler *handler)
+{
+ bScreen *screen = CTX_wm_screen(C);
+
+ if (screen) {
+ if (handler->op_area == NULL) {
+ /* do nothing in this context */
+ }
+ else {
+ ScrArea *sa;
+
+ for (sa = screen->areabase.first; sa; sa = sa->next)
+ if (sa == handler->op_area)
+ break;
+ if (sa == NULL) {
+ /* when changing screen layouts with running modal handlers (like render display), this
+ * is not an error to print */
+ if (handler->manipulator_map == NULL)
+ printf("internal error: modal manipulator-map handler has invalid area\n");
+ }
+ else {
+ ARegion *ar;
+ CTX_wm_area_set(C, sa);
+ for (ar = sa->regionbase.first; ar; ar = ar->next)
+ if (ar == handler->op_region)
+ break;
+ /* XXX no warning print here, after full-area and back regions are remade */
+ if (ar)
+ CTX_wm_region_set(C, ar);
+ }
+ }
+ }
+}
+
+bool WM_manipulatormap_cursor_set(const wmManipulatorMap *mmap, wmWindow *win)
+{
+ wmManipulator *mpr = mmap->mmap_context.highlight;
+ if (mpr && mpr->type->cursor_get) {
+ WM_cursor_set(win, mpr->type->cursor_get(mpr));
+ return true;
+ }
+
+ return false;
+}
+
+void wm_manipulatormap_highlight_set(
+ wmManipulatorMap *mmap, const bContext *C, wmManipulator *mpr, int part)
+{
+ if ((mpr != mmap->mmap_context.highlight) ||
+ (mpr && part != mpr->highlight_part))
+ {
+ if (mmap->mmap_context.highlight) {
+ mmap->mmap_context.highlight->state &= ~WM_MANIPULATOR_STATE_HIGHLIGHT;
+ mmap->mmap_context.highlight->highlight_part = -1;
+ }
+
+ mmap->mmap_context.highlight = mpr;
+
+ if (mpr) {
+ mpr->state |= WM_MANIPULATOR_STATE_HIGHLIGHT;
+ mpr->highlight_part = part;
+
+ if (C && mpr->type->cursor_get) {
+ wmWindow *win = CTX_wm_window(C);
+ WM_cursor_set(win, mpr->type->cursor_get(mpr));
+ }
+ }
+ else {
+ if (C) {
+ wmWindow *win = CTX_wm_window(C);
+ WM_cursor_set(win, CURSOR_STD);
+ }
+ }
+
+ /* tag the region for redraw */
+ if (C) {
+ ARegion *ar = CTX_wm_region(C);
+ ED_region_tag_redraw(ar);
+ }
+ }
+}
+
+wmManipulator *wm_manipulatormap_highlight_get(wmManipulatorMap *mmap)
+{
+ return mmap->mmap_context.highlight;
+}
+
+/**
+ * Caller should call exit when (enable == False).
+ */
+void wm_manipulatormap_modal_set(
+ wmManipulatorMap *mmap, bContext *C, wmManipulator *mpr, const wmEvent *event, bool enable)
+{
+ if (enable) {
+ BLI_assert(mmap->mmap_context.modal == NULL);
+
+ /* For now only grab cursor for 3D manipulators. */
+ bool grab_cursor = (mpr->parent_mgroup->type->flag & WM_MANIPULATORGROUPTYPE_3D) != 0;
+ int retval = OPERATOR_RUNNING_MODAL;
+
+ if (mpr->type->invoke &&
+ (mpr->type->modal || mpr->custom_modal))
+ {
+ retval = mpr->type->invoke(C, mpr, event);
+ }
+
+ if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
+ return;
+ }
+
+ mpr->state |= WM_MANIPULATOR_STATE_MODAL;
+ mmap->mmap_context.modal = mpr;
+
+ struct wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, mpr->highlight_part);
+ if (mpop && mpop->type) {
+ WM_operator_name_call_ptr(C, mpop->type, WM_OP_INVOKE_DEFAULT, &mpop->ptr);
+
+ /* we failed to hook the manipulator to the operator handler or operator was cancelled, return */
+ if (!mmap->mmap_context.modal) {
+ mpr->state &= ~WM_MANIPULATOR_STATE_MODAL;
+ MEM_SAFE_FREE(mpr->interaction_data);
+ }
+ return;
+ }
+
+ if (grab_cursor) {
+ WM_cursor_grab_enable(CTX_wm_window(C), true, true, NULL);
+ }
+ }
+ else {
+ BLI_assert(ELEM(mmap->mmap_context.modal, NULL, mpr));
+
+ /* deactivate, manipulator but first take care of some stuff */
+ if (mpr) {
+ mpr->state &= ~WM_MANIPULATOR_STATE_MODAL;
+ MEM_SAFE_FREE(mpr->interaction_data);
+ }
+ mmap->mmap_context.modal = NULL;
+
+ if (C) {
+ WM_cursor_grab_disable(CTX_wm_window(C), NULL);
+ ED_region_tag_redraw(CTX_wm_region(C));
+ WM_event_add_mousemove(C);
+ }
+ }
+}
+
+wmManipulator *wm_manipulatormap_modal_get(wmManipulatorMap *mmap)
+{
+ return mmap->mmap_context.modal;
+}
+
+wmManipulator **wm_manipulatormap_selected_get(wmManipulatorMap *mmap, int *r_selected_len)
+{
+ *r_selected_len = mmap->mmap_context.select.len;
+ return mmap->mmap_context.select.items;
+}
+
+ListBase *wm_manipulatormap_groups_get(wmManipulatorMap *mmap)
+{
+ return &mmap->groups;
+}
+
+void WM_manipulatormap_message_subscribe(
+ bContext *C, wmManipulatorMap *mmap, ARegion *ar, struct wmMsgBus *mbus)
+{
+ for (wmManipulatorGroup *mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
+ if (!wm_manipulatorgroup_is_visible(mgroup, C)) {
+ continue;
+ }
+ for (wmManipulator *mpr = mgroup->manipulators.first; mpr; mpr = mpr->next) {
+ if (mpr->flag & WM_MANIPULATOR_HIDDEN) {
+ continue;
+ }
+ WM_manipulator_target_property_subscribe_all(mpr, mbus, ar);
+ }
+ if (mgroup->type->message_subscribe != NULL) {
+ mgroup->type->message_subscribe(C, mgroup, mbus);
+ }
+ }
+}
+
+/** \} */ /* wmManipulatorMap */
+
+
+/* -------------------------------------------------------------------- */
+/** \name wmManipulatorMapType
+ *
+ * \{ */
+
+wmManipulatorMapType *WM_manipulatormaptype_find(
+ const struct wmManipulatorMapType_Params *mmap_params)
+{
+ for (wmManipulatorMapType *mmap_type = manipulatormaptypes.first; mmap_type; mmap_type = mmap_type->next) {
+ if (mmap_type->spaceid == mmap_params->spaceid &&
+ mmap_type->regionid == mmap_params->regionid)
+ {
+ return mmap_type;
+ }
+ }
+
+ return NULL;
+}
+
+wmManipulatorMapType *WM_manipulatormaptype_ensure(
+ const struct wmManipulatorMapType_Params *mmap_params)
+{
+ wmManipulatorMapType *mmap_type = WM_manipulatormaptype_find(mmap_params);
+
+ if (mmap_type) {
+ return mmap_type;
+ }
+
+ mmap_type = MEM_callocN(sizeof(wmManipulatorMapType), "manipulatortype list");
+ mmap_type->spaceid = mmap_params->spaceid;
+ mmap_type->regionid = mmap_params->regionid;
+ BLI_addhead(&manipulatormaptypes, mmap_type);
+
+ return mmap_type;
+}
+
+void wm_manipulatormaptypes_free(void)
+{
+ for (wmManipulatorMapType *mmap_type = manipulatormaptypes.first, *mmap_type_next;
+ mmap_type;
+ mmap_type = mmap_type_next)
+ {
+ mmap_type_next = mmap_type->next;
+ for (wmManipulatorGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first, *wgt_next;
+ wgt_ref;
+ wgt_ref = wgt_next)
+ {
+ wgt_next = wgt_ref->next;
+ WM_manipulatormaptype_group_free(wgt_ref);
+ }
+ MEM_freeN(mmap_type);
+ }
+}
+
+/**
+ * Initialize keymaps for all existing manipulator-groups
+ */
+void wm_manipulators_keymap(wmKeyConfig *keyconf)
+{
+ /* we add this item-less keymap once and use it to group manipulator-group keymaps into it */
+ WM_keymap_find(keyconf, "Manipulators", 0, 0);
+
+ for (wmManipulatorMapType *mmap_type = manipulatormaptypes.first; mmap_type; mmap_type = mmap_type->next) {
+ for (wmManipulatorGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first; wgt_ref; wgt_ref = wgt_ref->next) {
+ wm_manipulatorgrouptype_setup_keymap(wgt_ref->type, keyconf);
+ }
+ }
+}
+
+/** \} */ /* wmManipulatorMapType */
+
+/* -------------------------------------------------------------------- */
+/** \name Updates for Dynamic Type Registraion
+ *
+ * \{ */
+
+
+void WM_manipulatorconfig_update_tag_init(
+ wmManipulatorMapType *mmap_type, wmManipulatorGroupType *wgt)
+{
+ /* tag for update on next use */
+ mmap_type->type_update_flag |= (WM_MANIPULATORMAPTYPE_UPDATE_INIT | WM_MANIPULATORMAPTYPE_KEYMAP_INIT);
+ wgt->type_update_flag |= (WM_MANIPULATORMAPTYPE_UPDATE_INIT | WM_MANIPULATORMAPTYPE_KEYMAP_INIT);
+
+ wm_mmap_type_update_flag |= WM_MANIPULATORMAPTYPE_GLOBAL_UPDATE_INIT;
+}
+
+void WM_manipulatorconfig_update_tag_remove(
+ wmManipulatorMapType *mmap_type, wmManipulatorGroupType *wgt)
+{
+ /* tag for update on next use */
+ mmap_type->type_update_flag |= WM_MANIPULATORMAPTYPE_UPDATE_REMOVE;
+ wgt->type_update_flag |= WM_MANIPULATORMAPTYPE_UPDATE_REMOVE;
+
+ wm_mmap_type_update_flag |= WM_MANIPULATORMAPTYPE_GLOBAL_UPDATE_REMOVE;
+}
+
+/**
+ * Run incase new types have been added (runs often, early exit where possible).
+ * Follows #WM_keyconfig_update concentions.
+ */
+void WM_manipulatorconfig_update(struct Main *bmain)
+{
+ if (G.background)
+ return;
+
+ if (wm_mmap_type_update_flag == 0)
+ return;
+
+ if (wm_mmap_type_update_flag & WM_MANIPULATORMAPTYPE_GLOBAL_UPDATE_REMOVE) {
+ for (wmManipulatorMapType *mmap_type = manipulatormaptypes.first;
+ mmap_type;
+ mmap_type = mmap_type->next)
+ {
+ if (mmap_type->type_update_flag & WM_MANIPULATORMAPTYPE_GLOBAL_UPDATE_REMOVE) {
+ mmap_type->type_update_flag &= ~WM_MANIPULATORMAPTYPE_UPDATE_REMOVE;
+ for (wmManipulatorGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first, *wgt_ref_next;
+ wgt_ref;
+ wgt_ref = wgt_ref_next)
+ {
+ wgt_ref_next = wgt_ref->next;
+ if (wgt_ref->type->type_update_flag & WM_MANIPULATORMAPTYPE_UPDATE_REMOVE) {
+ WM_manipulatormaptype_group_unlink(NULL, bmain, mmap_type, wgt_ref->type);
+ }
+ }
+ }
+ }
+
+ wm_mmap_type_update_flag &= ~WM_MANIPULATORMAPTYPE_GLOBAL_UPDATE_REMOVE;
+ }
+
+ if (wm_mmap_type_update_flag & WM_MANIPULATORMAPTYPE_GLOBAL_UPDATE_INIT) {
+ for (wmManipulatorMapType *mmap_type = manipulatormaptypes.first;
+ mmap_type;
+ mmap_type = mmap_type->next)
+ {
+ const uchar type_update_all = WM_MANIPULATORMAPTYPE_UPDATE_INIT | WM_MANIPULATORMAPTYPE_KEYMAP_INIT;
+ if (mmap_type->type_update_flag & type_update_all) {
+ mmap_type->type_update_flag &= ~type_update_all;
+ for (wmManipulatorGroupTypeRef *wgt_ref = mmap_type->grouptype_refs.first;
+ wgt_ref;
+ wgt_ref = wgt_ref->next)
+ {
+ if (wgt_ref->type->type_update_flag & WM_MANIPULATORMAPTYPE_KEYMAP_INIT) {
+ WM_manipulatormaptype_group_init_runtime_keymap(bmain, wgt_ref->type);
+ wgt_ref->type->type_update_flag &= ~WM_MANIPULATORMAPTYPE_KEYMAP_INIT;
+ }
+
+ if (wgt_ref->type->type_update_flag & WM_MANIPULATORMAPTYPE_UPDATE_INIT) {
+ WM_manipulatormaptype_group_init_runtime(bmain, mmap_type, wgt_ref->type);
+ wgt_ref->type->type_update_flag &= ~WM_MANIPULATORMAPTYPE_UPDATE_INIT;
+ }
+ }
+ }
+ }
+
+ wm_mmap_type_update_flag &= ~WM_MANIPULATORMAPTYPE_GLOBAL_UPDATE_INIT;
+ }
+}
+
+/** \} */
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_target_props.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_target_props.c
new file mode 100644
index 00000000000..137e8f5639d
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_target_props.c
@@ -0,0 +1,364 @@
+/*
+ * ***** 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/windowmanager/manipulators/intern/wm_manipulator_target_props.c
+ * \ingroup wm
+ */
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
+
+#include "BKE_context.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "WM_message.h"
+
+#include "wm.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+/* own includes */
+#include "wm_manipulator_wmapi.h"
+#include "wm_manipulator_intern.h"
+
+/* -------------------------------------------------------------------- */
+
+/** \name Property Definition
+ * \{ */
+
+BLI_INLINE wmManipulatorProperty *wm_manipulator_target_property_array(wmManipulator *mpr)
+{
+ return (wmManipulatorProperty *)(POINTER_OFFSET(mpr, mpr->type->struct_size));
+}
+
+wmManipulatorProperty *WM_manipulator_target_property_array(wmManipulator *mpr)
+{
+ return wm_manipulator_target_property_array(mpr);
+}
+
+wmManipulatorProperty *WM_manipulator_target_property_at_index(wmManipulator *mpr, int index)
+{
+ BLI_assert(index < mpr->type->target_property_defs_len);
+ BLI_assert(index != -1);
+ wmManipulatorProperty *mpr_prop_array = wm_manipulator_target_property_array(mpr);
+ return &mpr_prop_array[index];
+}
+
+wmManipulatorProperty *WM_manipulator_target_property_find(wmManipulator *mpr, const char *idname)
+{
+ int index = BLI_findstringindex(
+ &mpr->type->target_property_defs, idname, offsetof(wmManipulatorPropertyType, idname));
+ if (index != -1) {
+ return WM_manipulator_target_property_at_index(mpr, index);
+ }
+ else {
+ return NULL;
+ }
+}
+
+void WM_manipulator_target_property_def_rna_ptr(
+ wmManipulator *mpr, const wmManipulatorPropertyType *mpr_prop_type,
+ PointerRNA *ptr, PropertyRNA *prop, int index)
+{
+ wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_at_index(mpr, mpr_prop_type->index_in_type);
+
+ /* if manipulator evokes an operator we cannot use it for property manipulation */
+ BLI_assert(mpr->op_data == NULL);
+
+ mpr_prop->type = mpr_prop_type;
+
+ mpr_prop->ptr = *ptr;
+ mpr_prop->prop = prop;
+ mpr_prop->index = index;
+
+ if (mpr->type->property_update) {
+ mpr->type->property_update(mpr, mpr_prop);
+ }
+}
+
+void WM_manipulator_target_property_def_rna(
+ wmManipulator *mpr, const char *idname,
+ PointerRNA *ptr, const char *propname, int index)
+{
+ const wmManipulatorPropertyType *mpr_prop_type = WM_manipulatortype_target_property_find(mpr->type, idname);
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ WM_manipulator_target_property_def_rna_ptr(mpr, mpr_prop_type, ptr, prop, index);
+}
+
+void WM_manipulator_target_property_def_func_ptr(
+ wmManipulator *mpr, const wmManipulatorPropertyType *mpr_prop_type,
+ const wmManipulatorPropertyFnParams *params)
+{
+ wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_at_index(mpr, mpr_prop_type->index_in_type);
+
+ /* if manipulator evokes an operator we cannot use it for property manipulation */
+ BLI_assert(mpr->op_data == NULL);
+
+ mpr_prop->type = mpr_prop_type;
+
+ mpr_prop->custom_func.value_get_fn = params->value_get_fn;
+ mpr_prop->custom_func.value_set_fn = params->value_set_fn;
+ mpr_prop->custom_func.range_get_fn = params->range_get_fn;
+ mpr_prop->custom_func.free_fn = params->free_fn;
+ mpr_prop->custom_func.user_data = params->user_data;
+
+ if (mpr->type->property_update) {
+ mpr->type->property_update(mpr, mpr_prop);
+ }
+}
+
+void WM_manipulator_target_property_def_func(
+ wmManipulator *mpr, const char *idname,
+ const wmManipulatorPropertyFnParams *params)
+{
+ const wmManipulatorPropertyType *mpr_prop_type = WM_manipulatortype_target_property_find(mpr->type, idname);
+ WM_manipulator_target_property_def_func_ptr(mpr, mpr_prop_type, params);
+}
+
+void WM_manipulator_target_property_clear_rna_ptr(
+ wmManipulator *mpr, const wmManipulatorPropertyType *mpr_prop_type)
+{
+ wmManipulatorProperty *mpr_prop = WM_manipulator_target_property_at_index(mpr, mpr_prop_type->index_in_type);
+
+ /* if manipulator evokes an operator we cannot use it for property manipulation */
+ BLI_assert(mpr->op_data == NULL);
+
+ mpr_prop->type = NULL;
+
+ mpr_prop->ptr = PointerRNA_NULL;
+ mpr_prop->prop = NULL;
+ mpr_prop->index = -1;
+}
+
+void WM_manipulator_target_property_clear_rna(
+ wmManipulator *mpr, const char *idname)
+{
+ const wmManipulatorPropertyType *mpr_prop_type = WM_manipulatortype_target_property_find(mpr->type, idname);
+ WM_manipulator_target_property_clear_rna_ptr(mpr, mpr_prop_type);
+}
+
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Property Access
+ * \{ */
+
+bool WM_manipulator_target_property_is_valid_any(wmManipulator *mpr)
+{
+ wmManipulatorProperty *mpr_prop_array = wm_manipulator_target_property_array(mpr);
+ for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
+ wmManipulatorProperty *mpr_prop = &mpr_prop_array[i];
+ if (WM_manipulator_target_property_is_valid(mpr_prop)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool WM_manipulator_target_property_is_valid(const wmManipulatorProperty *mpr_prop)
+{
+ return ((mpr_prop->prop != NULL) ||
+ (mpr_prop->custom_func.value_get_fn && mpr_prop->custom_func.value_set_fn));
+}
+
+float WM_manipulator_target_property_value_get(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop)
+{
+ if (mpr_prop->custom_func.value_get_fn) {
+ float value = 0.0f;
+ BLI_assert(mpr_prop->type->array_length == 1);
+ mpr_prop->custom_func.value_get_fn(mpr, mpr_prop, &value);
+ return value;
+ }
+
+ if (mpr_prop->index == -1) {
+ return RNA_property_float_get(&mpr_prop->ptr, mpr_prop->prop);
+ }
+ else {
+ return RNA_property_float_get_index(&mpr_prop->ptr, mpr_prop->prop, mpr_prop->index);
+ }
+}
+
+void WM_manipulator_target_property_value_set(
+ bContext *C, const wmManipulator *mpr,
+ wmManipulatorProperty *mpr_prop, const float value)
+{
+ if (mpr_prop->custom_func.value_set_fn) {
+ BLI_assert(mpr_prop->type->array_length == 1);
+ mpr_prop->custom_func.value_set_fn(mpr, mpr_prop, &value);
+ return;
+ }
+
+ /* reset property */
+ if (mpr_prop->index == -1) {
+ RNA_property_float_set(&mpr_prop->ptr, mpr_prop->prop, value);
+ }
+ else {
+ RNA_property_float_set_index(&mpr_prop->ptr, mpr_prop->prop, mpr_prop->index, value);
+ }
+ RNA_property_update(C, &mpr_prop->ptr, mpr_prop->prop);
+}
+
+void WM_manipulator_target_property_value_get_array(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ float *value)
+{
+ if (mpr_prop->custom_func.value_get_fn) {
+ mpr_prop->custom_func.value_get_fn(mpr, mpr_prop, value);
+ return;
+ }
+ RNA_property_float_get_array(&mpr_prop->ptr, mpr_prop->prop, value);
+}
+
+void WM_manipulator_target_property_value_set_array(
+ bContext *C, const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ const float *value)
+{
+ if (mpr_prop->custom_func.value_set_fn) {
+ mpr_prop->custom_func.value_set_fn(mpr, mpr_prop, value);
+ return;
+ }
+ RNA_property_float_set_array(&mpr_prop->ptr, mpr_prop->prop, value);
+
+ RNA_property_update(C, &mpr_prop->ptr, mpr_prop->prop);
+}
+
+bool WM_manipulator_target_property_range_get(
+ const wmManipulator *mpr, wmManipulatorProperty *mpr_prop,
+ float range[2])
+{
+ if (mpr_prop->custom_func.value_get_fn) {
+ if (mpr_prop->custom_func.range_get_fn) {
+ mpr_prop->custom_func.range_get_fn(mpr, mpr_prop, range);
+ return true;
+ }
+ else {
+ return false;
+
+ }
+ }
+
+ float step, precision;
+ RNA_property_float_ui_range(&mpr_prop->ptr, mpr_prop->prop, &range[0], &range[1], &step, &precision);
+ return true;
+}
+
+int WM_manipulator_target_property_array_length(
+ const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop)
+{
+ if (mpr_prop->custom_func.value_get_fn) {
+ return mpr_prop->type->array_length;
+ }
+ return RNA_property_array_length(&mpr_prop->ptr, mpr_prop->prop);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Property Define
+ * \{ */
+
+const wmManipulatorPropertyType *WM_manipulatortype_target_property_find(
+ const wmManipulatorType *wt, const char *idname)
+{
+ return BLI_findstring(&wt->target_property_defs, idname, offsetof(wmManipulatorPropertyType, idname));
+}
+
+void WM_manipulatortype_target_property_def(
+ wmManipulatorType *wt, const char *idname, int data_type, int array_length)
+{
+ wmManipulatorPropertyType *mpt;
+
+ BLI_assert(WM_manipulatortype_target_property_find(wt, idname) == NULL);
+
+ const uint idname_size = strlen(idname) + 1;
+ mpt = MEM_callocN(sizeof(wmManipulatorPropertyType) + idname_size, __func__);
+ memcpy(mpt->idname, idname, idname_size);
+ mpt->data_type = data_type;
+ mpt->array_length = array_length;
+ mpt->index_in_type = wt->target_property_defs_len;
+ wt->target_property_defs_len += 1;
+ BLI_addtail(&wt->target_property_defs, mpt);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Property Utilities
+ * \{ */
+
+void WM_manipulator_do_msg_notify_tag_refresh(
+ bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
+{
+ ARegion *ar = msg_val->owner;
+ wmManipulatorMap *mmap = msg_val->user_data;
+
+ ED_region_tag_redraw(ar);
+ WM_manipulatormap_tag_refresh(mmap);
+}
+
+/**
+ * Runs on the "prepare draw" pass,
+ * drawing the region clears.
+ */
+void WM_manipulator_target_property_subscribe_all(
+ wmManipulator *mpr, struct wmMsgBus *mbus, ARegion *ar)
+{
+ if (mpr->type->target_property_defs_len) {
+ wmManipulatorProperty *mpr_prop_array = WM_manipulator_target_property_array(mpr);
+ for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
+ wmManipulatorProperty *mpr_prop = &mpr_prop_array[i];
+ if (WM_manipulator_target_property_is_valid(mpr_prop)) {
+ if (mpr_prop->prop) {
+ WM_msg_subscribe_rna(
+ mbus, &mpr_prop->ptr, mpr_prop->prop,
+ &(const wmMsgSubscribeValue){
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ }, __func__);
+ WM_msg_subscribe_rna(
+ mbus, &mpr_prop->ptr, mpr_prop->prop,
+ &(const wmMsgSubscribeValue){
+ .owner = ar,
+ .user_data = mpr->parent_mgroup->parent_mmap,
+ .notify = WM_manipulator_do_msg_notify_tag_refresh,
+ }, __func__);
+ }
+ }
+ }
+ }
+}
+
+/** \} */
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c
new file mode 100644
index 00000000000..fd7f31db903
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c
@@ -0,0 +1,212 @@
+/*
+ * ***** 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/windowmanager/manipulators/intern/wm_manipulator_type.c
+ * \ingroup wm
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
+
+#include "BKE_context.h"
+#include "BKE_main.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+/* only for own init/exit calls (wm_manipulatortype_init/wm_manipulatortype_free) */
+#include "wm.h"
+
+/* own includes */
+#include "wm_manipulator_wmapi.h"
+#include "wm_manipulator_intern.h"
+
+
+/** \name Manipulator Type Append
+ *
+ * \note This follows conventions from #WM_operatortype_find #WM_operatortype_append & friends.
+ * \{ */
+
+static GHash *global_manipulatortype_hash = NULL;
+
+const wmManipulatorType *WM_manipulatortype_find(const char *idname, bool quiet)
+{
+ if (idname[0]) {
+ wmManipulatorType *wt;
+
+ wt = BLI_ghash_lookup(global_manipulatortype_hash, idname);
+ if (wt) {
+ return wt;
+ }
+
+ if (!quiet) {
+ printf("search for unknown manipulator '%s'\n", idname);
+ }
+ }
+ else {
+ if (!quiet) {
+ printf("search for empty manipulator\n");
+ }
+ }
+
+ return NULL;
+}
+
+/* caller must free */
+void WM_manipulatortype_iter(GHashIterator *ghi)
+{
+ BLI_ghashIterator_init(ghi, global_manipulatortype_hash);
+}
+
+static wmManipulatorType *wm_manipulatortype_append__begin(void)
+{
+ wmManipulatorType *wt = MEM_callocN(sizeof(wmManipulatorType), "manipulatortype");
+ wt->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_ManipulatorProperties);
+#if 0
+ /* Set the default i18n context now, so that opfunc can redefine it if needed! */
+ RNA_def_struct_translation_context(ot->srna, BLT_I18NCONTEXT_OPERATOR_DEFAULT);
+ ot->translation_context = BLT_I18NCONTEXT_OPERATOR_DEFAULT;
+#endif
+ return wt;
+}
+static void wm_manipulatortype_append__end(wmManipulatorType *wt)
+{
+ BLI_assert(wt->struct_size >= sizeof(wmManipulator));
+
+ RNA_def_struct_identifier(&BLENDER_RNA, wt->srna, wt->idname);
+
+ BLI_ghash_insert(global_manipulatortype_hash, (void *)wt->idname, wt);
+}
+
+void WM_manipulatortype_append(void (*wtfunc)(struct wmManipulatorType *))
+{
+ wmManipulatorType *wt = wm_manipulatortype_append__begin();
+ wtfunc(wt);
+ wm_manipulatortype_append__end(wt);
+}
+
+void WM_manipulatortype_append_ptr(void (*wtfunc)(struct wmManipulatorType *, void *), void *userdata)
+{
+ wmManipulatorType *mt = wm_manipulatortype_append__begin();
+ wtfunc(mt, userdata);
+ wm_manipulatortype_append__end(mt);
+}
+
+/**
+ * Free but don't remove from ghash.
+ */
+static void manipulatortype_free(wmManipulatorType *wt)
+{
+ if (wt->ext.srna) { /* python manipulator, allocs own string */
+ MEM_freeN((void *)wt->idname);
+ }
+
+ BLI_freelistN(&wt->target_property_defs);
+ MEM_freeN(wt);
+}
+
+/**
+ * \param C: May be NULL.
+ */
+static void manipulatortype_unlink(
+ bContext *C, Main *bmain, wmManipulatorType *wt)
+{
+ /* Free instances. */
+ for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ for (ARegion *ar = lb->first; ar; ar = ar->next) {
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ if (mmap) {
+ wmManipulatorGroup *mgroup;
+ for (mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) {
+ for (wmManipulator *mpr = mgroup->manipulators.first, *mpr_next; mpr; mpr = mpr_next) {
+ mpr_next = mpr->next;
+ BLI_assert(mgroup->parent_mmap == mmap);
+ if (mpr->type == wt) {
+ WM_manipulator_unlink(&mgroup->manipulators, mgroup->parent_mmap, mpr, C);
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void WM_manipulatortype_remove_ptr(bContext *C, Main *bmain, wmManipulatorType *wt)
+{
+ BLI_assert(wt == WM_manipulatortype_find(wt->idname, false));
+
+ BLI_ghash_remove(global_manipulatortype_hash, wt->idname, NULL, NULL);
+
+ manipulatortype_unlink(C, bmain, wt);
+
+ manipulatortype_free(wt);
+}
+
+bool WM_manipulatortype_remove(bContext *C, Main *bmain, const char *idname)
+{
+ wmManipulatorType *wt = BLI_ghash_lookup(global_manipulatortype_hash, idname);
+
+ if (wt == NULL) {
+ return false;
+ }
+
+ WM_manipulatortype_remove_ptr(C, bmain, wt);
+
+ return true;
+}
+
+static void wm_manipulatortype_ghash_free_cb(wmManipulatorType *mt)
+{
+ manipulatortype_free(mt);
+}
+
+void wm_manipulatortype_free(void)
+{
+ BLI_ghash_free(global_manipulatortype_hash, NULL, (GHashValFreeFP)wm_manipulatortype_ghash_free_cb);
+ global_manipulatortype_hash = NULL;
+}
+
+/* called on initialize WM_init() */
+void wm_manipulatortype_init(void)
+{
+ /* reserve size is set based on blender default setup */
+ global_manipulatortype_hash = BLI_ghash_str_new_ex("wm_manipulatortype_init gh", 128);
+}
+
+/** \} */
diff --git a/source/blender/windowmanager/manipulators/wm_manipulator_fn.h b/source/blender/windowmanager/manipulators/wm_manipulator_fn.h
new file mode 100644
index 00000000000..7e163f8a785
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/wm_manipulator_fn.h
@@ -0,0 +1,87 @@
+/*
+ * ***** 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/windowmanager/manipulators/wm_manipulator_fn.h
+ * \ingroup wm
+ *
+ * Callback function definitions, needed for both Types & API headers.
+ */
+
+#ifndef __WM_MANIPULATOR_FN_H__
+#define __WM_MANIPULATOR_FN_H__
+
+#include "BLI_compiler_attrs.h"
+
+/* wmManipulatorGroup */
+typedef bool (*wmManipulatorGroupFnPoll)(
+ const struct bContext *, struct wmManipulatorGroupType *)
+ ATTR_WARN_UNUSED_RESULT;
+typedef void (*wmManipulatorGroupFnInit)(
+ const struct bContext *, struct wmManipulatorGroup *);
+typedef void (*wmManipulatorGroupFnRefresh)(
+ const struct bContext *, struct wmManipulatorGroup *);
+typedef void (*wmManipulatorGroupFnDrawPrepare)(
+ const struct bContext *, struct wmManipulatorGroup *);
+typedef struct wmKeyMap *(*wmManipulatorGroupFnSetupKeymap)(
+ const struct wmManipulatorGroupType *, struct wmKeyConfig *)
+ ATTR_WARN_UNUSED_RESULT;
+typedef void (*wmManipulatorGroupFnMsgBusSubscribe)(
+ const struct bContext *, struct wmManipulatorGroup *, struct wmMsgBus *);
+
+/* wmManipulator */
+/* See: wmManipulatorType for docs on each type. */
+
+typedef void (*wmManipulatorFnSetup)(struct wmManipulator *);
+typedef void (*wmManipulatorFnDraw)(const struct bContext *, struct wmManipulator *);
+typedef void (*wmManipulatorFnDrawSelect)(const struct bContext *, struct wmManipulator *, int);
+typedef int (*wmManipulatorFnTestSelect)(struct bContext *, struct wmManipulator *, const struct wmEvent *);
+typedef int (*wmManipulatorFnModal)(struct bContext *, struct wmManipulator *, const struct wmEvent *, eWM_ManipulatorTweak);
+typedef void (*wmManipulatorFnPropertyUpdate)(struct wmManipulator *, struct wmManipulatorProperty *);
+typedef void (*wmManipulatorFnMatrixBasisGet)(const struct wmManipulator *, float[4][4]);
+typedef int (*wmManipulatorFnInvoke)(struct bContext *, struct wmManipulator *, const struct wmEvent *);
+typedef void (*wmManipulatorFnExit)(struct bContext *, struct wmManipulator *, const bool);
+typedef int (*wmManipulatorFnCursorGet)(struct wmManipulator *);
+typedef void (*wmManipulatorFnSelectRefresh)(struct wmManipulator *);
+
+/* wmManipulatorProperty ('value' type defined by 'wmManipulatorProperty.data_type') */
+typedef void (*wmManipulatorPropertyFnGet)(
+ const struct wmManipulator *, struct wmManipulatorProperty *,
+ /* typically 'float *' */
+ void *value);
+typedef void (*wmManipulatorPropertyFnSet)(
+ const struct wmManipulator *, struct wmManipulatorProperty *,
+ /* typically 'const float *' */
+ const void *value);
+typedef void (*wmManipulatorPropertyFnRangeGet)(
+ const struct wmManipulator *, struct wmManipulatorProperty *,
+ /* typically 'float[2]' */
+ void *range);
+typedef void (*wmManipulatorPropertyFnFree)(
+ const struct wmManipulator *, struct wmManipulatorProperty *);
+
+typedef struct wmManipulatorPropertyFnParams {
+ wmManipulatorPropertyFnGet value_get_fn;
+ wmManipulatorPropertyFnSet value_set_fn;
+ wmManipulatorPropertyFnRangeGet range_get_fn;
+ wmManipulatorPropertyFnFree free_fn;
+ void *user_data;
+} wmManipulatorPropertyFnParams;
+
+#endif /* __WM_MANIPULATOR_FN_H__ */
diff --git a/source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h b/source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h
new file mode 100644
index 00000000000..87cf711a60b
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h
@@ -0,0 +1,98 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/wm_manipulator_wmapi.h
+ * \ingroup wm
+ *
+ * \name Manipulators Window Manager API
+ * API for usage in window manager code only. It should contain all functionality
+ * needed to hook up the manipulator system with Blender's window manager. It's
+ * mostly the event system that needs to communicate with manipulator code.
+ *
+ * Only included in wm.h and lower level files.
+ */
+
+
+#ifndef __WM_MANIPULATOR_WMAPI_H__
+#define __WM_MANIPULATOR_WMAPI_H__
+
+struct wmEventHandler;
+struct wmManipulatorMap;
+struct wmOperatorType;
+struct wmOperator;
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulator */
+
+/* wm_manipulator_type.c, for init/exit */
+void wm_manipulatortype_free(void);
+void wm_manipulatortype_init(void);
+
+/* wm_manipulatorgroup_type.c, for init/exit */
+void wm_manipulatorgrouptype_free(void);
+void wm_manipulatorgrouptype_init(void);
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorGroup */
+
+void MANIPULATORGROUP_OT_manipulator_select(struct wmOperatorType *ot);
+void MANIPULATORGROUP_OT_manipulator_tweak(struct wmOperatorType *ot);
+
+bool wm_manipulatorgroup_is_any_selected(const struct wmManipulatorGroup *mgroup);
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorMap */
+
+void wm_manipulatormap_remove(struct wmManipulatorMap *mmap);
+
+void wm_manipulators_keymap(struct wmKeyConfig *keyconf);
+
+void wm_manipulatormaps_handled_modal_update(
+ bContext *C, struct wmEvent *event, struct wmEventHandler *handler);
+void wm_manipulatormap_handler_context(bContext *C, struct wmEventHandler *handler);
+
+struct wmManipulator *wm_manipulatormap_highlight_find(
+ struct wmManipulatorMap *mmap, bContext *C, const struct wmEvent *event,
+ int *r_part);
+void wm_manipulatormap_highlight_set(
+ struct wmManipulatorMap *mmap, const bContext *C,
+ struct wmManipulator *mpr, int part);
+struct wmManipulator *wm_manipulatormap_highlight_get(struct wmManipulatorMap *mmap);
+void wm_manipulatormap_modal_set(
+ struct wmManipulatorMap *mmap, bContext *C, struct wmManipulator *mpr,
+ const struct wmEvent *event, bool enable);
+
+struct wmManipulator *wm_manipulatormap_modal_get(struct wmManipulatorMap *mmap);
+struct wmManipulator **wm_manipulatormap_selected_get(wmManipulatorMap *mmap, int *r_selected_len);
+struct ListBase *wm_manipulatormap_groups_get(wmManipulatorMap *mmap);
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorMapType */
+
+void wm_manipulatormaptypes_free(void);
+
+#endif /* __WM_MANIPULATOR_WMAPI_H__ */
+
diff --git a/source/blender/windowmanager/message_bus/intern/wm_message_bus.c b/source/blender/windowmanager/message_bus/intern/wm_message_bus.c
new file mode 100644
index 00000000000..7183655b0de
--- /dev/null
+++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus.c
@@ -0,0 +1,247 @@
+/*
+ * ***** 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/windowmanager/message_bus/intern/wm_message_bus.c
+ * \ingroup wm
+ */
+
+#include <string.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+
+#include "BLI_ghash.h"
+
+#include "WM_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "message_bus/wm_message_bus.h"
+#include "message_bus/intern/wm_message_bus_intern.h"
+
+/* -------------------------------------------------------------------------- */
+/** \name Public API
+ * \{ */
+
+static wmMsgTypeInfo wm_msg_types[WM_MSG_TYPE_NUM] = {NULL};
+
+typedef void (*wmMsgTypeInitFn)(wmMsgTypeInfo *);
+
+static wmMsgTypeInitFn wm_msg_init_fn[WM_MSG_TYPE_NUM] = {
+ WM_msgtypeinfo_init_rna,
+ WM_msgtypeinfo_init_static,
+};
+
+void WM_msgbus_types_init(void)
+{
+ for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
+ wm_msg_init_fn[i](&wm_msg_types[i]);
+ }
+}
+
+struct wmMsgBus *WM_msgbus_create(void)
+{
+ struct wmMsgBus *mbus = MEM_callocN(sizeof(*mbus), __func__);
+ const uint gset_reserve = 512;
+ for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
+ wmMsgTypeInfo *info = &wm_msg_types[i];
+ mbus->messages_gset[i] = BLI_gset_new_ex(info->gset.hash_fn, info->gset.cmp_fn, __func__, gset_reserve);
+ }
+ return mbus;
+}
+
+void WM_msgbus_destroy(struct wmMsgBus *mbus)
+{
+ for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
+ wmMsgTypeInfo *info = &wm_msg_types[i];
+ BLI_gset_free(mbus->messages_gset[i], info->gset.key_free_fn);
+ }
+ MEM_freeN(mbus);
+}
+
+void WM_msgbus_clear_by_owner(struct wmMsgBus *mbus, void *owner)
+{
+ wmMsgSubscribeKey *msg_key, *msg_key_next;
+ for (msg_key = mbus->messages.first; msg_key; msg_key = msg_key_next) {
+ msg_key_next = msg_key->next;
+
+ wmMsgSubscribeValueLink *msg_lnk_next;
+ for (wmMsgSubscribeValueLink *msg_lnk = msg_key->values.first; msg_lnk; msg_lnk = msg_lnk_next) {
+ msg_lnk_next = msg_lnk->next;
+ if (msg_lnk->params.owner == owner) {
+ if (msg_lnk->params.free_data) {
+ msg_lnk->params.free_data(msg_key, &msg_lnk->params);
+ }
+ BLI_remlink(&msg_key->values, msg_lnk);
+ MEM_freeN(msg_lnk);
+ }
+ }
+
+ if (BLI_listbase_is_empty(&msg_key->values)) {
+ const wmMsg *msg = wm_msg_subscribe_value_msg_cast(msg_key);
+ wmMsgTypeInfo *info = &wm_msg_types[msg->type];
+ BLI_remlink(&mbus->messages, msg_key);
+ bool ok = BLI_gset_remove(mbus->messages_gset[msg->type], msg_key, info->gset.key_free_fn);
+ BLI_assert(ok);
+ UNUSED_VARS_NDEBUG(ok);
+ }
+ }
+}
+
+void WM_msg_dump(struct wmMsgBus *mbus, const char *info_str)
+{
+ printf(">>>> %s\n", info_str);
+ for (wmMsgSubscribeKey *key = mbus->messages.first; key; key = key->next) {
+ const wmMsg *msg = wm_msg_subscribe_value_msg_cast(key);
+ const wmMsgTypeInfo *info = &wm_msg_types[msg->type];
+ info->repr(stdout, key);
+ }
+ printf("<<<< %s\n", info_str);
+}
+
+void WM_msgbus_handle(struct wmMsgBus *mbus, struct bContext *C)
+{
+ if (mbus->messages_tag_count == 0) {
+ // printf("msgbus: skipping\n");
+ return;
+ }
+
+ if (false) {
+ WM_msg_dump(mbus, __func__);
+ }
+
+ // uint a = 0, b = 0;
+ for (wmMsgSubscribeKey *key = mbus->messages.first; key; key = key->next) {
+ for (wmMsgSubscribeValueLink *msg_lnk = key->values.first; msg_lnk; msg_lnk = msg_lnk->next) {
+ if (msg_lnk->params.tag) {
+ msg_lnk->params.notify(C, key, &msg_lnk->params);
+ msg_lnk->params.tag = false;
+ mbus->messages_tag_count -= 1;
+ }
+ // b++;
+ }
+ // a++;
+ }
+ BLI_assert(mbus->messages_tag_count == 0);
+ mbus->messages_tag_count = 0;
+ // printf("msgbus: keys=%u values=%u\n", a, b);
+}
+
+/**
+ * \param msg_key_test: Needs following #wmMsgSubscribeKey fields filled in:
+ * - msg.params
+ * - msg.head.type
+ * - msg.head.id
+ * .. other values should be zeroed.
+ *
+ * \return The key for this subscription.
+ * note that this is only needed in rare cases when the key needs further manipulation.
+ */
+wmMsgSubscribeKey *WM_msg_subscribe_with_key(
+ struct wmMsgBus *mbus,
+ const wmMsgSubscribeKey *msg_key_test,
+ const wmMsgSubscribeValue *msg_val_params)
+{
+ const uint type = wm_msg_subscribe_value_msg_cast(msg_key_test)->type;
+ const wmMsgTypeInfo *info = &wm_msg_types[type];
+ wmMsgSubscribeKey *key;
+
+ BLI_assert(wm_msg_subscribe_value_msg_cast(msg_key_test)->id != NULL);
+
+ void **r_key;
+ if (!BLI_gset_ensure_p_ex(mbus->messages_gset[type], msg_key_test, &r_key)) {
+ key = *r_key = MEM_mallocN(info->msg_key_size, __func__);
+ memcpy(key, msg_key_test, info->msg_key_size);
+ BLI_addtail(&mbus->messages, key);
+ }
+ else {
+ key = *r_key;
+ for (wmMsgSubscribeValueLink *msg_lnk = key->values.first; msg_lnk; msg_lnk = msg_lnk->next) {
+ if ((msg_lnk->params.notify == msg_val_params->notify) &&
+ (msg_lnk->params.owner == msg_val_params->owner) &&
+ (msg_lnk->params.user_data == msg_val_params->user_data))
+ {
+ return key;
+ }
+ }
+ }
+
+ wmMsgSubscribeValueLink *msg_lnk = MEM_mallocN(sizeof(wmMsgSubscribeValueLink), __func__);
+ msg_lnk->params = *msg_val_params;
+ BLI_addtail(&key->values, msg_lnk);
+ return key;
+}
+
+void WM_msg_publish_with_key(struct wmMsgBus *mbus, wmMsgSubscribeKey *msg_key)
+{
+ for (wmMsgSubscribeValueLink *msg_lnk = msg_key->values.first; msg_lnk; msg_lnk = msg_lnk->next) {
+ if (false) { /* make an option? */
+ msg_lnk->params.notify(NULL, msg_key, &msg_lnk->params);
+ }
+ else {
+ if (msg_lnk->params.tag == false) {
+ msg_lnk->params.tag = true;
+ mbus->messages_tag_count += 1;
+ }
+ }
+ }
+}
+
+void WM_msg_id_update(
+ struct wmMsgBus *mbus,
+ struct ID *id_src, struct ID *id_dst)
+{
+ for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
+ wmMsgTypeInfo *info = &wm_msg_types[i];
+ if (info->update_by_id != NULL) {
+ info->update_by_id(mbus, id_src, id_dst);
+ }
+ }
+}
+
+void WM_msg_id_remove(struct wmMsgBus *mbus, const struct ID *id)
+{
+ for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
+ wmMsgTypeInfo *info = &wm_msg_types[i];
+ if (info->remove_by_id != NULL) {
+ info->remove_by_id(mbus, id);
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------------- */
+/** \name Internal API
+ *
+ * \note While we could have a separate type for ID's, use RNA since there is enough overlap.
+ * \{ */
+
+void wm_msg_subscribe_value_free(
+ wmMsgSubscribeKey *msg_key, wmMsgSubscribeValueLink *msg_lnk)
+{
+ if (msg_lnk->params.free_data) {
+ msg_lnk->params.free_data(msg_key, &msg_lnk->params);
+ }
+ BLI_remlink(&msg_key->values, msg_lnk);
+ MEM_freeN(msg_lnk);
+}
+
+/** \} */
diff --git a/source/blender/windowmanager/message_bus/intern/wm_message_bus_intern.h b/source/blender/windowmanager/message_bus/intern/wm_message_bus_intern.h
new file mode 100644
index 00000000000..db8b481a3c2
--- /dev/null
+++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus_intern.h
@@ -0,0 +1,55 @@
+/*
+ * ***** 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/windowmanager/message_bus/intern/wm_message_bus_intern.h
+ * \ingroup wm
+ */
+
+#ifndef __WM_MESSAGE_BUS_INTERN_H__
+#define __WM_MESSAGE_BUS_INTERN_H__
+
+/* wm_message_bus.h must be included first */
+
+struct wmMsgBus {
+ struct GSet *messages_gset[WM_MSG_TYPE_NUM];
+ /** Messages in order of being added. */
+ ListBase messages;
+ /** Avoid checking messages when no tags exist. */
+ uint messages_tag_count;
+};
+
+void wm_msg_subscribe_value_free(
+ struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValueLink *msg_lnk);
+
+typedef struct wmMsgSubscribeKey_Generic {
+ wmMsgSubscribeKey head;
+ wmMsg msg;
+} wmMsgSubscribeKey_Generic;
+
+BLI_INLINE const wmMsg *wm_msg_subscribe_value_msg_cast(const wmMsgSubscribeKey *key)
+{
+ return &((wmMsgSubscribeKey_Generic *)key)->msg;
+}
+BLI_INLINE wmMsg *wm_msg_subscribe_value_msg_cast_mut(wmMsgSubscribeKey *key)
+{
+ return &((wmMsgSubscribeKey_Generic *)key)->msg;
+}
+
+#endif /* __WM_MESSAGE_BUS_INTERN_H__ */
diff --git a/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c b/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c
new file mode 100644
index 00000000000..f9d8d968b84
--- /dev/null
+++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c
@@ -0,0 +1,316 @@
+/*
+ * ***** 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/windowmanager/intern/wm_message_bus_rna.c
+ * \ingroup wm
+ */
+
+#include <stdio.h>
+#include "DNA_ID.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+
+#include "WM_types.h"
+#include "WM_message.h"
+#include "message_bus/intern/wm_message_bus_intern.h"
+
+#include "RNA_access.h"
+
+#include "MEM_guardedalloc.h"
+
+/* -------------------------------------------------------------------------- */
+
+BLI_INLINE uint void_hash_uint(const void *key)
+{
+ size_t y = (size_t)key >> (sizeof(void *));
+ return (unsigned int)y;
+}
+
+static uint wm_msg_rna_gset_hash(const void *key_p)
+{
+ const wmMsgSubscribeKey_RNA *key = key_p;
+ const wmMsgParams_RNA *params = &key->msg.params;
+// printf("%s\n", RNA_struct_identifier(params->ptr.type));
+ uint k = void_hash_uint(params->ptr.type);
+ k ^= void_hash_uint(params->ptr.data);
+ k ^= void_hash_uint(params->ptr.id.data);
+ k ^= void_hash_uint(params->prop);
+ return k;
+}
+static bool wm_msg_rna_gset_cmp(const void *key_a_p, const void *key_b_p)
+{
+ const wmMsgParams_RNA *params_a = &((const wmMsgSubscribeKey_RNA *)key_a_p)->msg.params;
+ const wmMsgParams_RNA *params_b = &((const wmMsgSubscribeKey_RNA *)key_b_p)->msg.params;
+ return !(
+ (params_a->ptr.type ==
+ params_b->ptr.type) &&
+ (params_a->ptr.id.data ==
+ params_b->ptr.id.data) &&
+ (params_a->ptr.data ==
+ params_b->ptr.data) &&
+ (params_a->prop ==
+ params_b->prop)
+ );
+}
+static void wm_msg_rna_gset_key_free(void *key_p)
+{
+ wmMsgSubscribeKey_RNA *key = key_p;
+ wmMsgSubscribeValueLink *msg_lnk_next;
+ for (wmMsgSubscribeValueLink *msg_lnk = key->head.values.first; msg_lnk; msg_lnk = msg_lnk_next) {
+ msg_lnk_next = msg_lnk->next;
+ wm_msg_subscribe_value_free(&key->head, msg_lnk);
+ }
+ if (key->msg.params.data_path != NULL) {
+ MEM_freeN(key->msg.params.data_path);
+ }
+ MEM_freeN(key);
+}
+
+static void wm_msg_rna_repr(FILE *stream, const wmMsgSubscribeKey *msg_key)
+{
+ const wmMsgSubscribeKey_RNA *m = (wmMsgSubscribeKey_RNA *)msg_key;
+ const char *none = "<none>";
+ fprintf(stream,
+ "<wmMsg_RNA %p, "
+ "id='%s', "
+ "%s.%s values_len=%d\n",
+ m, m->msg.head.id,
+ m->msg.params.ptr.type ? RNA_struct_identifier(m->msg.params.ptr.type) : none,
+ m->msg.params.prop ? RNA_property_identifier((PropertyRNA *)m->msg.params.prop) : none,
+ BLI_listbase_count(&m->head.values));
+}
+
+static void wm_msg_rna_update_by_id(
+ struct wmMsgBus *mbus,
+ ID *id_src, ID *id_dst)
+{
+ GSet *gs = mbus->messages_gset[WM_MSG_TYPE_RNA];
+ GSetIterator gs_iter;
+ BLI_gsetIterator_init(&gs_iter, gs);
+ while (BLI_gsetIterator_done(&gs_iter) == false) {
+ wmMsgSubscribeKey_RNA *key = BLI_gsetIterator_getKey(&gs_iter);
+ BLI_gsetIterator_step(&gs_iter);
+ if (key->msg.params.ptr.id.data == id_src) {
+
+ /* GSet always needs updating since the key changes. */
+ BLI_gset_remove(gs, key, NULL);
+
+ /* Remove any non-persistent values, so a single persistent
+ * value doesn't modify behavior for the rest. */
+ wmMsgSubscribeValueLink *msg_lnk_next;
+ for (wmMsgSubscribeValueLink *msg_lnk = key->head.values.first; msg_lnk; msg_lnk = msg_lnk_next) {
+ msg_lnk_next = msg_lnk->next;
+ if (msg_lnk->params.is_persistent == false) {
+ wm_msg_subscribe_value_free(&key->head, msg_lnk);
+ }
+ }
+
+ bool remove = true;
+
+ if (BLI_listbase_is_empty(&key->head.values)) {
+ /* Remove, no reason to keep. */
+ }
+ else if (key->msg.params.ptr.data == key->msg.params.ptr.id.data) {
+ /* Simple, just update the ID. */
+ key->msg.params.ptr.data = id_dst;
+ key->msg.params.ptr.id.data = id_dst;
+ remove = false;
+ }
+ else {
+ /* we need to resolve this from the */
+ PointerRNA idptr;
+ RNA_id_pointer_create(id_dst, &idptr);
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ if (!RNA_path_resolve(&idptr, key->msg.params.data_path, &ptr, &prop)) {
+ key->msg.params.ptr = ptr;
+ key->msg.params.prop = prop;
+ remove = false;
+ }
+ }
+
+ printf("AAA ~ %d\n", remove);
+ if (remove) {
+ /* Failed to persist, remove the key. */
+ BLI_remlink(&mbus->messages, key);
+ wm_msg_rna_gset_key_free(key);
+ }
+ else {
+ /* note that it's not impossible this key exists, however it is very unlikely
+ * since a subscriber would need to register in the middle of an undo for eg. so assert for now. */
+ BLI_assert(!BLI_gset_haskey(gs, key));
+ BLI_gset_add(gs, key);
+ }
+ }
+ }
+}
+
+static void wm_msg_rna_remove_by_id(struct wmMsgBus *mbus, const ID *id)
+{
+ GSet *gs = mbus->messages_gset[WM_MSG_TYPE_RNA];
+ GSetIterator gs_iter;
+ BLI_gsetIterator_init(&gs_iter, gs);
+ while (BLI_gsetIterator_done(&gs_iter) == false) {
+ wmMsgSubscribeKey_RNA *key = BLI_gsetIterator_getKey(&gs_iter);
+ BLI_gsetIterator_step(&gs_iter);
+ if (key->msg.params.ptr.id.data == id) {
+ BLI_remlink(&mbus->messages, key);
+ BLI_gset_remove(gs, key, NULL);
+ wm_msg_rna_gset_key_free(key);
+ }
+ }
+}
+
+void WM_msgtypeinfo_init_rna(wmMsgTypeInfo *msgtype_info)
+{
+ msgtype_info->gset.hash_fn = wm_msg_rna_gset_hash;
+ msgtype_info->gset.cmp_fn = wm_msg_rna_gset_cmp;
+ msgtype_info->gset.key_free_fn = wm_msg_rna_gset_key_free;
+
+ msgtype_info->repr = wm_msg_rna_repr;
+ msgtype_info->update_by_id = wm_msg_rna_update_by_id;
+ msgtype_info->remove_by_id = wm_msg_rna_remove_by_id;
+
+ msgtype_info->msg_key_size = sizeof(wmMsgSubscribeKey_RNA);
+}
+
+/* -------------------------------------------------------------------------- */
+
+
+wmMsgSubscribeKey_RNA *WM_msg_lookup_rna(struct wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params)
+{
+ wmMsgSubscribeKey_RNA key_test;
+ key_test.msg.params = *msg_key_params;
+ return BLI_gset_lookup(mbus->messages_gset[WM_MSG_TYPE_RNA], &key_test);
+}
+
+void WM_msg_publish_rna_params(struct wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params)
+{
+ wmMsgSubscribeKey_RNA *key;
+
+ if ((key = WM_msg_lookup_rna(mbus, msg_key_params))) {
+ WM_msg_publish_with_key(mbus, &key->head);
+ }
+
+ /* Support anonymous subscribers, this may be some extra overhead
+ * but we want to be able to be more ambiguous. */
+ if (msg_key_params->ptr.id.data || msg_key_params->ptr.data) {
+ wmMsgParams_RNA msg_key_params_anon = *msg_key_params;
+
+ /* We might want to enable this later? */
+ if (msg_key_params_anon.prop != NULL) {
+ /* All properties for this type. */
+ msg_key_params_anon.prop = NULL;
+ if ((key = WM_msg_lookup_rna(mbus, &msg_key_params_anon))) {
+ WM_msg_publish_with_key(mbus, &key->head);
+ }
+ msg_key_params_anon.prop = msg_key_params->prop;
+ }
+
+ msg_key_params_anon.ptr.id.data = NULL;
+ msg_key_params_anon.ptr.data = NULL;
+ if ((key = WM_msg_lookup_rna(mbus, &msg_key_params_anon))) {
+ WM_msg_publish_with_key(mbus, &key->head);
+ }
+
+ /* Support subscribers to a type. */
+ if (msg_key_params->prop) {
+ msg_key_params_anon.prop = NULL;
+ if ((key = WM_msg_lookup_rna(mbus, &msg_key_params_anon))) {
+ WM_msg_publish_with_key(mbus, &key->head);
+ }
+ }
+ }
+}
+
+void WM_msg_publish_rna(struct wmMsgBus *mbus, PointerRNA *ptr, PropertyRNA *prop)
+{
+ WM_msg_publish_rna_params(mbus, &(wmMsgParams_RNA){ .ptr = *ptr, .prop = prop, });
+}
+
+void WM_msg_subscribe_rna_params(
+ struct wmMsgBus *mbus,
+ const wmMsgParams_RNA *msg_key_params,
+ const wmMsgSubscribeValue *msg_val_params,
+ const char *id_repr)
+{
+ wmMsgSubscribeKey_RNA msg_key_test = {{NULL}};
+
+ /* use when added */
+ msg_key_test.msg.head.id = id_repr;
+ msg_key_test.msg.head.type = WM_MSG_TYPE_RNA;
+ /* for lookup */
+ msg_key_test.msg.params = *msg_key_params;
+
+ wmMsgSubscribeKey_RNA *msg_key = (wmMsgSubscribeKey_RNA *)WM_msg_subscribe_with_key(
+ mbus, &msg_key_test.head, msg_val_params);
+
+ if (msg_val_params->is_persistent) {
+ if (msg_key->msg.params.data_path == NULL) {
+ if (msg_key->msg.params.ptr.data != msg_key->msg.params.ptr.id.data) {
+ /* We assume prop type can't change. */
+ msg_key->msg.params.data_path = RNA_path_from_ID_to_struct(&msg_key->msg.params.ptr);
+ }
+ }
+ }
+}
+
+void WM_msg_subscribe_rna(
+ struct wmMsgBus *mbus,
+ PointerRNA *ptr, const PropertyRNA *prop,
+ const wmMsgSubscribeValue *msg_val_params,
+ const char *id_repr)
+{
+ WM_msg_subscribe_rna_params(
+ mbus,
+ &(const wmMsgParams_RNA){
+ .ptr = *ptr,
+ .prop = prop,
+ },
+ msg_val_params, id_repr);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------------- */
+/** \name ID variants of RNA API
+ *
+ * \note While we could have a separate type for ID's, use RNA since there is enough overlap.
+ * \{ */
+
+void WM_msg_subscribe_ID(
+ struct wmMsgBus *mbus, ID *id, const wmMsgSubscribeValue *msg_val_params,
+ const char *id_repr)
+{
+ wmMsgParams_RNA msg_key_params = {NULL};
+ RNA_id_pointer_create(id, &msg_key_params.ptr);
+ WM_msg_subscribe_rna_params(mbus, &msg_key_params, msg_val_params, id_repr);
+}
+
+void WM_msg_publish_ID(struct wmMsgBus *mbus, ID *id)
+{
+ wmMsgParams_RNA msg_key_params = {NULL};
+ RNA_id_pointer_create(id, &msg_key_params.ptr);
+ WM_msg_publish_rna_params(mbus, &msg_key_params);
+}
+
+/** \} */
diff --git a/source/blender/windowmanager/message_bus/intern/wm_message_bus_static.c b/source/blender/windowmanager/message_bus/intern/wm_message_bus_static.c
new file mode 100644
index 00000000000..59bebad7f7b
--- /dev/null
+++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus_static.c
@@ -0,0 +1,136 @@
+/*
+ * ***** 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/windowmanager/intern/wm_message_bus_static.c
+ * \ingroup wm
+ */
+
+#include <stdio.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+
+#include "WM_types.h"
+#include "WM_message.h"
+#include "message_bus/intern/wm_message_bus_intern.h"
+
+#include "MEM_guardedalloc.h"
+
+/* -------------------------------------------------------------------------- */
+
+static uint wm_msg_static_gset_hash(const void *key_p)
+{
+ const wmMsgSubscribeKey_Static *key = key_p;
+ const wmMsgParams_Static *params = &key->msg.params;
+ uint k = params->event;
+ return k;
+}
+static bool wm_msg_static_gset_cmp(const void *key_a_p, const void *key_b_p)
+{
+ const wmMsgParams_Static *params_a = &((const wmMsgSubscribeKey_Static *)key_a_p)->msg.params;
+ const wmMsgParams_Static *params_b = &((const wmMsgSubscribeKey_Static *)key_b_p)->msg.params;
+ return !(
+ (params_a->event ==
+ params_b->event)
+ );
+}
+static void wm_msg_static_gset_key_free(void *key_p)
+{
+ wmMsgSubscribeKey *key = key_p;
+ wmMsgSubscribeValueLink *msg_lnk_next;
+ for (wmMsgSubscribeValueLink *msg_lnk = key->values.first; msg_lnk; msg_lnk = msg_lnk_next) {
+ msg_lnk_next = msg_lnk->next;
+ BLI_remlink(&key->values, msg_lnk);
+ MEM_freeN(msg_lnk);
+ }
+ MEM_freeN(key);
+}
+
+static void wm_msg_static_repr(FILE *stream, const wmMsgSubscribeKey *msg_key)
+{
+ const wmMsgSubscribeKey_Static *m = (wmMsgSubscribeKey_Static *)msg_key;
+ fprintf(stream,
+ "<wmMsg_Static %p, "
+ "id='%s', "
+ "values_len=%d\n",
+ m, m->msg.head.id,
+ BLI_listbase_count(&m->head.values));
+}
+
+
+void WM_msgtypeinfo_init_static(wmMsgTypeInfo *msgtype_info)
+{
+ msgtype_info->gset.hash_fn = wm_msg_static_gset_hash;
+ msgtype_info->gset.cmp_fn = wm_msg_static_gset_cmp;
+ msgtype_info->gset.key_free_fn = wm_msg_static_gset_key_free;
+ msgtype_info->repr = wm_msg_static_repr;
+
+ msgtype_info->msg_key_size = sizeof(wmMsgSubscribeKey_Static);
+}
+
+/* -------------------------------------------------------------------------- */
+
+
+wmMsgSubscribeKey_Static *WM_msg_lookup_static(struct wmMsgBus *mbus, const wmMsgParams_Static *msg_key_params)
+{
+ wmMsgSubscribeKey_Static key_test;
+ key_test.msg.params = *msg_key_params;
+ return BLI_gset_lookup(mbus->messages_gset[WM_MSG_TYPE_STATIC], &key_test);
+}
+
+void WM_msg_publish_static_params(struct wmMsgBus *mbus, const wmMsgParams_Static *msg_key_params)
+{
+ wmMsgSubscribeKey_Static *key = WM_msg_lookup_static(mbus, msg_key_params);
+ if (key) {
+ WM_msg_publish_with_key(mbus, &key->head);
+ }
+}
+
+void WM_msg_publish_static(struct wmMsgBus *mbus, int event)
+{
+ WM_msg_publish_static_params(mbus, &(wmMsgParams_Static){ .event = event, });
+}
+
+void WM_msg_subscribe_static_params(
+ struct wmMsgBus *mbus,
+ const wmMsgParams_Static *msg_key_params,
+ const wmMsgSubscribeValue *msg_val_params,
+ const char *id_repr)
+{
+ wmMsgSubscribeKey_Static msg_key_test = {{NULL}};
+
+ /* use when added */
+ msg_key_test.msg.head.id = id_repr;
+ msg_key_test.msg.head.type = WM_MSG_TYPE_STATIC;
+ /* for lookup */
+ msg_key_test.msg.params = *msg_key_params;
+
+ WM_msg_subscribe_with_key(mbus, &msg_key_test.head, msg_val_params);
+}
+
+void WM_msg_subscribe_static(
+ struct wmMsgBus *mbus,
+ int event,
+ const wmMsgSubscribeValue *msg_val_params,
+ const char *id_repr)
+{
+ WM_msg_subscribe_static_params(mbus, &(const wmMsgParams_Static){ .event = event, }, msg_val_params, id_repr);
+}
diff --git a/source/blender/windowmanager/message_bus/wm_message_bus.h b/source/blender/windowmanager/message_bus/wm_message_bus.h
new file mode 100644
index 00000000000..53f283cacd2
--- /dev/null
+++ b/source/blender/windowmanager/message_bus/wm_message_bus.h
@@ -0,0 +1,256 @@
+/*
+ * ***** 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/windowmanager/wm_message_bus.h
+ * \ingroup wm
+ */
+
+#ifndef __WM_MESSAGE_BUS_H__
+#define __WM_MESSAGE_BUS_H__
+
+struct GSet;
+struct ID;
+struct bContext;
+struct wmMsg;
+
+/* opaque (don't expose outside wm_message_bus.c) */
+struct wmMsgBus;
+struct wmMsgSubscribeKey;
+struct wmMsgSubscribeValue;
+struct wmMsgSubscribeValueLink;
+
+typedef void (*wmMsgNotifyFn)(
+ struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val);
+typedef void (*wmMsgSubscribeValueFreeDataFn)(
+ struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val);
+
+/* Exactly what arguments here is not obvious. */
+typedef void (*wmMsgSubscribeValueUpdateIdFn)(
+ struct bContext *C,
+ struct wmMsgBus *mbus,
+ struct ID *id_src, struct ID *id_dst,
+ struct wmMsgSubscribeValue *msg_val);
+enum {
+ WM_MSG_TYPE_RNA = 0,
+ WM_MSG_TYPE_STATIC = 1,
+};
+#define WM_MSG_TYPE_NUM 2
+
+typedef struct wmMsgTypeInfo {
+ struct {
+ unsigned int (*hash_fn)(const void *msg);
+ bool (*cmp_fn)(const void *a, const void *b);
+ void (*key_free_fn)(void *key);
+ } gset;
+
+ void (*update_by_id)(struct wmMsgBus *mbus, struct ID *id_src, struct ID *id_dst);
+ void (*remove_by_id)(struct wmMsgBus *mbus, const struct ID *id);
+ void (*repr)(FILE *stream, const struct wmMsgSubscribeKey *msg_key);
+
+ /* sizeof(wmMsgSubscribeKey_*) */
+ uint msg_key_size;
+} wmMsgTypeInfo;
+
+typedef struct wmMsg {
+ unsigned int type;
+// #ifdef DEBUG
+ /* For debugging: '__func__:__LINE__'. */
+ const char *id;
+// #endif
+} wmMsg;
+
+typedef struct wmMsgSubscribeKey {
+ /** Linked list for predicable ordering, otherwise we would depend on ghash bucketing. */
+ struct wmMsgSubscribeKey *next, *prev;
+ ListBase values;
+ /* over-alloc, eg: wmMsgSubscribeKey_RNA */
+ /* Last member will be 'wmMsg_*' */
+} wmMsgSubscribeKey;
+
+/** One of many in #wmMsgSubscribeKey.values */
+typedef struct wmMsgSubscribeValue {
+ struct wmMsgSubscribe *next, *prev;
+
+ /** Handle, used to iterate and clear. */
+ void *owner;
+ /** User data, can be whatever we like, free using the 'free_data' callback if it's owned. */
+ void *user_data;
+
+ /** Callbacks */
+ wmMsgNotifyFn notify;
+ wmMsgSubscribeValueUpdateIdFn update_id;
+ wmMsgSubscribeValueFreeDataFn free_data;
+
+ /** Keep this subscriber if possible. */
+ uint is_persistent : 1;
+ /* tag to run when handling events,
+ * we may want option for immediate execution. */
+ uint tag : 1;
+} wmMsgSubscribeValue;
+
+/** One of many in #wmMsgSubscribeKey.values */
+typedef struct wmMsgSubscribeValueLink {
+ struct wmMsgSubscribeValueLink *next, *prev;
+ wmMsgSubscribeValue params;
+} wmMsgSubscribeValueLink;
+
+void WM_msgbus_types_init(void);
+
+struct wmMsgBus *WM_msgbus_create(void);
+void WM_msgbus_destroy(struct wmMsgBus *mbus);
+
+void WM_msgbus_clear_by_owner(struct wmMsgBus *mbus, void *owner);
+
+void WM_msg_dump(struct wmMsgBus *mbus, const char *info);
+void WM_msgbus_handle(struct wmMsgBus *mbus, struct bContext *C);
+
+void WM_msg_publish_with_key(struct wmMsgBus *mbus, wmMsgSubscribeKey *msg_key);
+wmMsgSubscribeKey *WM_msg_subscribe_with_key(
+ struct wmMsgBus *mbus,
+ const wmMsgSubscribeKey *msg_key_test,
+ const wmMsgSubscribeValue *msg_val_params);
+
+void WM_msg_id_update(
+ struct wmMsgBus *mbus,
+ struct ID *id_src, struct ID *id_dst);
+void WM_msg_id_remove(struct wmMsgBus *mbus, const struct ID *id);
+
+/* -------------------------------------------------------------------------- */
+/* wm_message_bus_static.c */
+
+enum {
+ /* generic window redraw */
+ WM_MSG_STATICTYPE_WINDOW_DRAW = 0,
+ WM_MSG_STATICTYPE_SCREEN_EDIT = 1,
+ WM_MSG_STATICTYPE_FILE_READ = 2,
+};
+
+typedef struct wmMsgParams_Static {
+ int event;
+} wmMsgParams_Static;
+
+typedef struct wmMsg_Static {
+ wmMsg head; /* keep first */
+ wmMsgParams_Static params;
+} wmMsg_Static;
+
+typedef struct wmMsgSubscribeKey_Static {
+ wmMsgSubscribeKey head;
+ wmMsg_Static msg;
+} wmMsgSubscribeKey_Static;
+
+void WM_msgtypeinfo_init_static(wmMsgTypeInfo *msg_type);
+
+wmMsgSubscribeKey_Static *WM_msg_lookup_static(
+ struct wmMsgBus *mbus, const wmMsgParams_Static *msg_key_params);
+void WM_msg_publish_static_params(
+ struct wmMsgBus *mbus,
+ const wmMsgParams_Static *msg_key_params);
+void WM_msg_publish_static(
+ struct wmMsgBus *mbus,
+ /* wmMsgParams_Static (expanded) */
+ int event);
+void WM_msg_subscribe_static_params(
+ struct wmMsgBus *mbus,
+ const wmMsgParams_Static *msg_key_params,
+ const wmMsgSubscribeValue *msg_val_params,
+ const char *id_repr);
+void WM_msg_subscribe_static(
+ struct wmMsgBus *mbus,
+ int event,
+ const wmMsgSubscribeValue *msg_val_params,
+ const char *id_repr);
+
+/* -------------------------------------------------------------------------- */
+/* wm_message_bus_rna.c */
+
+typedef struct wmMsgParams_RNA {
+ /** when #PointerRNA.data & id.data are NULL. match against all. */
+ PointerRNA ptr;
+ /** when NULL, match against any property. */
+ const PropertyRNA *prop;
+
+ /**
+ * Optional RNA data path for persistent RNA properties, ignore if NULL.
+ * otherwise it's allocated.
+ */
+ char *data_path;
+} wmMsgParams_RNA;
+
+typedef struct wmMsg_RNA {
+ wmMsg head; /* keep first */
+ wmMsgParams_RNA params;
+} wmMsg_RNA;
+
+typedef struct wmMsgSubscribeKey_RNA {
+ wmMsgSubscribeKey head;
+ wmMsg_RNA msg;
+} wmMsgSubscribeKey_RNA;
+
+void WM_msgtypeinfo_init_rna(wmMsgTypeInfo *msg_type);
+
+wmMsgSubscribeKey_RNA *WM_msg_lookup_rna(
+ struct wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params);
+void WM_msg_publish_rna_params(
+ struct wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params);
+void WM_msg_publish_rna(
+ struct wmMsgBus *mbus,
+ /* wmMsgParams_RNA (expanded) */
+ PointerRNA *ptr, PropertyRNA *prop);
+void WM_msg_subscribe_rna_params(
+ struct wmMsgBus *mbus,
+ const wmMsgParams_RNA *msg_key_params,
+ const wmMsgSubscribeValue *msg_val_params,
+ const char *id_repr);
+void WM_msg_subscribe_rna(
+ struct wmMsgBus *mbus,
+ PointerRNA *ptr, const PropertyRNA *prop,
+ const wmMsgSubscribeValue *msg_val_params,
+ const char *id_repr);
+
+/* ID variants */
+void WM_msg_subscribe_ID(
+ struct wmMsgBus *mbus, struct ID *id, const wmMsgSubscribeValue *msg_val_params,
+ const char *id_repr);
+void WM_msg_publish_ID(
+ struct wmMsgBus *mbus, struct ID *id);
+
+/* Anonymous variants (for convenience) */
+#define WM_msg_subscribe_rna_anon_type(mbus, type_, value) { \
+ WM_msg_subscribe_rna_params( \
+ mbus, \
+ &(const wmMsgParams_RNA){ \
+ .ptr = (PointerRNA){.type = &RNA_##type_}, \
+ .prop = NULL, \
+ }, \
+ value, __func__); \
+} ((void)0)
+#define WM_msg_subscribe_rna_anon_prop(mbus, type_, prop_, value) { \
+ extern PropertyRNA rna_##type_##_##prop_; \
+ WM_msg_subscribe_rna_params( \
+ mbus, \
+ &(const wmMsgParams_RNA){ \
+ .ptr = (PointerRNA){.type = &RNA_##type_}, \
+ .prop = &rna_##type_##_##prop_, \
+ }, \
+ value, __func__); \
+} ((void)0)
+
+#endif /* __WM_MESSAGE_BUS_H__ */
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index a417a719b8d..7fe6db4e470 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -34,6 +34,8 @@
struct wmWindow;
struct ReportList;
+#include "manipulators/wm_manipulator_wmapi.h"
+
typedef struct wmPaintCursor {
struct wmPaintCursor *next, *prev;
@@ -46,7 +48,7 @@ typedef struct wmPaintCursor {
extern void wm_close_and_free(bContext *C, wmWindowManager *);
extern void wm_close_and_free_all(bContext *C, ListBase *);
-extern void wm_add_default(bContext *C);
+extern void wm_add_default(struct Main *bmain, bContext *C);
extern void wm_clear_default_size(bContext *C);
/* register to windowmanager for redo or macro */
diff --git a/source/blender/windowmanager/wm_draw.h b/source/blender/windowmanager/wm_draw.h
index 5257bba45ff..56dff304719 100644
--- a/source/blender/windowmanager/wm_draw.h
+++ b/source/blender/windowmanager/wm_draw.h
@@ -34,6 +34,8 @@
#include "GPU_glew.h"
+#define USE_TEXTURE_RECTANGLE 1
+
typedef struct wmDrawTriple {
GLuint bind;
int x, y;
@@ -56,7 +58,7 @@ void wm_draw_region_clear (struct wmWindow *win, struct ARegion *ar);
void wm_tag_redraw_overlay (struct wmWindow *win, struct ARegion *ar);
-void wm_triple_draw_textures (struct wmWindow *win, struct wmDrawTriple *triple, float alpha, bool is_interlace);
+void wm_triple_draw_textures (struct wmWindow *win, struct wmDrawTriple *triple, float alpha);
void wm_draw_data_free (struct wmWindow *win);
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index 9977e73f2fd..c14517f1662 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -68,7 +68,8 @@ typedef struct wmEventHandler {
/* drop box handler */
ListBase *dropboxes;
-
+ /* manipulator handler */
+ struct wmManipulatorMap *manipulator_map;
} wmEventHandler;
/* custom types for handlers, for signaling, freeing */
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 090c8c90280..e327bd81d81 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -339,6 +339,8 @@ enum {
EVT_DROP = 0x5023,
EVT_BUT_CANCEL = 0x5024,
+ /* could become manipulator callback */
+ EVT_MANIPULATOR_UPDATE = 0x5025,
/* ********** End of Blender internal events. ********** */
};
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index b102b6c7cc7..6f63e55e8ab 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -45,6 +45,7 @@ void WM_OT_save_homefile(struct wmOperatorType *ot);
void WM_OT_userpref_autoexec_path_add(struct wmOperatorType *ot);
void WM_OT_userpref_autoexec_path_remove(struct wmOperatorType *ot);
void WM_OT_save_userpref(struct wmOperatorType *ot);
+void WM_OT_save_workspace_file(struct wmOperatorType *ot);
void WM_OT_read_history(struct wmOperatorType *ot);
void WM_OT_read_homefile(struct wmOperatorType *ot);
void WM_OT_read_factory_settings(struct wmOperatorType *ot);
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index f70ec6b47f6..0264955a4c5 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -32,7 +32,11 @@
#ifndef __WM_WINDOW_H__
#define __WM_WINDOW_H__
+struct EnumPropertyItem;
+struct wmEvent;
struct wmOperator;
+struct PointerRNA;
+struct PropertyRNA;
/* *************** internal api ************** */
void wm_ghost_init (bContext *C);
@@ -42,8 +46,8 @@ void wm_get_screensize(int *r_width, int *r_height);
void wm_get_desktopsize(int *r_width, int *r_height);
wmWindow *wm_window_new (bContext *C);
-wmWindow *wm_window_copy (bContext *C, wmWindow *win_src);
-wmWindow *wm_window_copy_test (bContext *C, wmWindow *win_src);
+wmWindow *wm_window_copy (bContext *C, wmWindow *win_src, const bool duplicate_layout);
+wmWindow *wm_window_copy_test (bContext *C, wmWindow *win_src, const bool duplicate_layout);
void wm_window_free (bContext *C, wmWindowManager *wm, wmWindow *win);
void wm_window_close (bContext *C, wmWindowManager *wm, wmWindow *win);
@@ -76,9 +80,13 @@ void wm_window_IME_end (wmWindow *win);
/* *************** window operators ************** */
int wm_window_close_exec(bContext *C, struct wmOperator *op);
-int wm_window_duplicate_exec(bContext *C, struct wmOperator *op);
int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op);
+const struct EnumPropertyItem *wm_window_new_screen_itemf(
+ bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
+int wm_window_new_exec(bContext *C, struct wmOperator *op);
+int wm_window_new_invoke(bContext *C, struct wmOperator *op, const struct wmEvent *event);
+
/* Initial (unmaximized) size to start with for
* systems that can't find it for themselves (X11).
* Clamped by real desktop limits */
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index e5a5ff828dd..328453df118 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -87,6 +87,12 @@ list(APPEND BLENDER_LINK_LIBS
blenkernel_blc
)
+if(WITH_AUDASPACE AND NOT WITH_SYSTEM_AUDASPACE)
+ list(APPEND BLENDER_LINK_LIBS
+ audaspace
+ audaspace-py)
+endif()
+
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
list(APPEND BLENDER_LINK_LIBS extern_binreloc)
endif()
@@ -123,6 +129,7 @@ endif()
bf_intern_moto
bf_nodes
bf_gpu
+ bf_intern_gawain
bf_imbuf
bf_avi
ge_logic_network
@@ -145,6 +152,8 @@ endif()
bf_blenfont
bf_blentranslation
bf_intern_audaspace
+ audaspace
+ audaspace-py
blenkernel_blc
bf_bmesh
bf_blenlib
diff --git a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
index 0e570e19258..d2c2129532a 100644
--- a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
+++ b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
@@ -35,11 +35,12 @@ set(INC
../../blender/blenloader
../../blender/makesdna
../../blender/makesrna
+ ../../../intern/glew-mx
../../../intern/guardedalloc
)
set(INC_SYS
-
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index b8e88269dc7..ff1ed8998e8 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -43,6 +43,7 @@
struct ARegion;
struct ARegionType;
+struct bFaceMap;
struct BMEditMesh;
struct Base;
struct bContext;
@@ -113,6 +114,7 @@ struct bConstraintOb;
struct bConstraintTarget;
struct bContextDataResult;
struct bGPDlayer;
+struct bFaceMap;
struct bNode;
struct bNodeType;
struct bNodeSocket;
@@ -130,6 +132,8 @@ struct wmOperator;
struct wmOperatorType;
struct wmWindow;
struct wmWindowManager;
+struct wmManipulatorGroupType;
+struct wmManipulatorMap;
/* -------------------------------------------------------------------- */
@@ -142,6 +146,8 @@ struct wmWindowManager;
# pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
+#include <stdio.h> /* FILE */
+
#include "../../intern/dualcon/dualcon.h"
#include "../../intern/elbeem/extern/elbeem.h"
#include "../blender/blenkernel/BKE_modifier.h"
@@ -160,12 +166,14 @@ struct wmWindowManager;
#include "../blender/editors/include/ED_keyframes_edit.h"
#include "../blender/editors/include/ED_keyframing.h"
#include "../blender/editors/include/ED_lattice.h"
+#include "../blender/editors/include/ED_manipulator_library.h"
#include "../blender/editors/include/ED_mball.h"
#include "../blender/editors/include/ED_mesh.h"
#include "../blender/editors/include/ED_node.h"
#include "../blender/editors/include/ED_object.h"
#include "../blender/editors/include/ED_particle.h"
#include "../blender/editors/include/ED_render.h"
+#include "../blender/editors/include/ED_scene.h"
#include "../blender/editors/include/ED_screen.h"
#include "../blender/editors/include/ED_space_api.h"
#include "../blender/editors/include/ED_text.h"
@@ -178,12 +186,18 @@ struct wmWindowManager;
#include "../blender/editors/include/UI_resources.h"
#include "../blender/editors/include/UI_view2d.h"
#include "../blender/freestyle/FRS_freestyle.h"
+#include "../blender/gpu/GPU_immediate.h"
+#include "../blender/gpu/GPU_matrix.h"
#include "../blender/python/BPY_extern.h"
+#include "../blender/python/intern/bpy_manipulator_wrap.h"
#include "../blender/render/extern/include/RE_engine.h"
#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"
+#include "../blender/windowmanager/WM_types.h"
+#include "../blender/windowmanager/WM_message.h"
/* -------------------------------------------------------------------- */
@@ -193,7 +207,11 @@ struct wmWindowManager;
/* bpy_operator_wrap.h */
extern void macro_wrapper(struct wmOperatorType *ot, void *userdata);
-extern void operator_wrapper(struct wmOperatorType *ot, void *userdata);
+extern void operator_wrapper(struct wmManipulatorGroupType *wgt, void *userdata);
+
+/* bpy_widgetgroup_wrap.h */
+extern void widgetgroup_wrapper(struct wmOperatorType *ot, void *userdata);
+
/* bpy_rna.h */
extern bool pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id);
extern const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid);
@@ -218,7 +236,6 @@ bool BPY_string_is_keyword(const char *str) { return false; }
#define RET_ARG(arg) {STUB_ASSERT(0); return arg; }
#define RET_NONE {STUB_ASSERT(0);}
-
/* -------------------------------------------------------------------- */
/* Stubs */
@@ -228,7 +245,7 @@ void EDBM_mesh_load(struct Object *ob) RET_NONE
void EDBM_mesh_make(struct ToolSettings *ts, struct Object *ob, const bool use_key_index) RET_NONE
void EDBM_mesh_normals_update(struct BMEditMesh *em) RET_NONE
void *g_system;
-bool EDBM_mtexpoly_check(struct BMEditMesh *em) RET_ZERO
+bool EDBM_uv_check(struct BMEditMesh *em) RET_ZERO
float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname) RET_NULL
float RE_filter_value(int type, float x) RET_ZERO
@@ -260,7 +277,7 @@ bool ED_texture_context_check_linestyle(const struct bContext *C) RET_ZERO
void FRS_free_view_map_cache(void) RET_NONE
/* texture.c */
-int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, short thread, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image) RET_ZERO
+int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, const short thread, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image) RET_ZERO
int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image) RET_ZERO
int multitex_nodes(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex, struct ImagePool *pool) RET_ZERO
@@ -299,7 +316,7 @@ double elbeemEstimateMemreq(int res, float sx, float sy, float sz, int refine, c
struct Render *RE_NewRender(const char *name) RET_NULL
struct Render *RE_NewSceneRender(const struct Scene *scene) RET_NULL
void RE_SwapResult(struct Render *re, struct RenderResult **rr) RET_NONE
-void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct SceneRenderLayer *srl, struct Object *camera_override, unsigned int lay_override, int frame, const bool write_still) RET_NONE
+void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct Object *camera_override, unsigned int lay_override, int frame, const bool write_still) RET_NONE
bool RE_WriteEnvmapResult(struct ReportList *reports, struct Scene *scene, struct EnvMap *env, const char *relpath, const char imtype, float layout[12]) RET_ZERO
/* rna */
@@ -313,12 +330,23 @@ struct MenuType *WM_menutype_find(const char *idname, bool quiet) RET_NULL
void WM_operator_stack_clear(struct wmWindowManager *wm) RET_NONE
void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot) RET_NONE
bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op) RET_ZERO;
+void WM_windows_scene_data_sync(const struct ListBase *win_lb, struct Scene *scene) RET_NONE
+struct Scene *WM_windows_scene_get_from_screen(const struct wmWindowManager *wm, const struct bScreen *screen) RET_NULL
+struct WorkSpace *WM_windows_workspace_get_from_screen(const struct wmWindowManager *wm, const struct bScreen *screen) RET_NULL
+struct bScreen *WM_window_get_active_screen(const struct wmWindow *win) RET_NULL
+struct Scene *WM_window_get_active_scene(const struct wmWindow *win) RET_NULL
+struct WorkSpace *WM_window_get_active_workspace(const wmWindow *win) RET_NULL
+void WM_window_change_active_scene(struct Main *bmain, struct bContext *C, struct wmWindow *win, struct Scene *scene_new) RET_NONE
+bool WM_window_is_temp_screen(const struct wmWindow *win) RET_ZERO
void WM_autosave_init(wmWindowManager *wm) RET_NONE
void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner) RET_NONE
void WM_lib_reload(struct Library *lib, struct bContext *C, struct ReportList *reports) RET_NONE
+void WM_msg_publish_rna(struct wmMsgBus *mbus, PointerRNA *ptr, PropertyRNA *prop) RET_NONE
+
+
char *WM_clipboard_text_get(bool selection, int *r_len) RET_NULL
char *WM_clipboard_text_get_firstline(bool selection, int *r_len) RET_NULL
void WM_clipboard_text_set(const char *buf, bool selection) RET_NONE
@@ -342,6 +370,42 @@ void WM_jobs_callbacks(struct wmJob *job,
void WM_jobs_start(struct wmWindowManager *wm, struct wmJob *job) RET_NONE
void WM_report(ReportType type, const char *message) RET_NONE
+void BPY_RNA_manipulatorgroup_wrapper(struct wmManipulatorGroupType *wgt, void *userdata) RET_NONE
+void BPY_RNA_manipulator_wrapper(struct wmManipulatorType *wgt, void *userdata) RET_NONE
+
+struct PointerRNA *WM_manipulator_operator_set(struct wmManipulator *mpr, int part_index, struct wmOperatorType *ot, struct IDProperty *properties) RET_NULL
+const struct wmManipulatorPropertyType *WM_manipulatortype_target_property_find(const struct wmManipulatorType *wt, const char *idname) RET_NULL
+const struct wmManipulatorType *WM_manipulatortype_find(const char *idname, bool quiet) RET_NULL
+struct wmManipulator *WM_manipulator_new_ptr(const struct wmManipulatorType *wt, struct wmManipulatorGroup *mgroup, struct PointerRNA *properties) RET_NULL
+struct wmManipulatorGroupType *WM_manipulatorgrouptype_append_ptr(void (*mnpfunc)(struct wmManipulatorGroupType *, void *), void *userdata) RET_NULL
+struct wmManipulatorGroupType *WM_manipulatorgrouptype_find(const char *idname, bool quiet) RET_NULL
+void WM_manipulator_unlink(ListBase *manipulatorlist, struct wmManipulatorMap *mmap, struct wmManipulator *mpr, struct bContext *C) RET_NONE
+void WM_manipulator_group_type_add_ptr(struct wmManipulatorGroupType *wgt) RET_NONE
+void WM_manipulator_group_type_add_ptr_ex(struct wmManipulatorGroupType *wgt, struct wmManipulatorMapType *mmap_type) RET_NONE
+void WM_manipulator_group_type_remove_ptr(struct Main *bmain, struct wmManipulatorGroupType *wgt) RET_NONE
+void WM_manipulator_name_set(struct wmManipulatorGroup *mgroup, struct wmManipulator *mpr, const char *name) RET_NONE
+bool WM_manipulator_select_set(struct wmManipulatorMap *mmap, struct wmManipulator *mpr, bool select) RET_ZERO
+void WM_manipulator_target_property_def_rna_ptr(struct wmManipulator *mpr, const struct wmManipulatorPropertyType *mpr_prop_type, struct PointerRNA *ptr, struct PropertyRNA *prop, int index) RET_NONE
+void WM_manipulatorgrouptype_free_ptr(struct wmManipulatorGroupType *wt) RET_NONE
+void WM_manipulatormaptype_group_unlink(struct bContext *C, struct Main *bmain, struct wmManipulatorMapType *mmap_type, const struct wmManipulatorGroupType *wgt) RET_NONE
+void WM_manipulatortype_append_ptr(void (*mnpfunc)(struct wmManipulatorType *, void *), void *userdata) RET_NONE
+void WM_manipulatortype_remove_ptr(struct bContext *C, struct Main *bmain, struct wmManipulatorType *wt) RET_NONE
+
+void ED_manipulator_draw_preset_box(const struct wmManipulator *mpr, float mat[4][4], int select_id) RET_NONE
+void ED_manipulator_draw_preset_arrow(const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id) RET_NONE
+void ED_manipulator_draw_preset_circle(const struct wmManipulator *mpr, float mat[4][4], int axis, int select_id) RET_NONE
+void ED_manipulator_draw_preset_facemap(const struct bContext *C, const struct wmManipulator *mpr, struct Scene *scene, struct Object *ob, const int facemap, int select_id) RET_NONE
+
+struct wmManipulatorMapType *WM_manipulatormaptype_find(const struct wmManipulatorMapType_Params *wmap_params) RET_NULL
+struct wmManipulatorMapType *WM_manipulatormaptype_ensure(const struct wmManipulatorMapType_Params *wmap_params) RET_NULL
+struct wmManipulatorMap *WM_manipulatormap_new_from_type(const struct wmManipulatorMapType_Params *wmap_params) RET_NULL
+void WM_manipulatormaptype_group_init_runtime(
+ const struct Main *bmain, struct wmManipulatorMapType *mmap_type, struct wmManipulatorGroupType *wgt) RET_NONE
+const struct ListBase *WM_manipulatormap_group_list(struct wmManipulatorMap *mmap) RET_NULL
+void WM_manipulator_calc_matrix_final(const struct wmManipulator *mpr, float r_mat[4][4]) RET_NONE
+struct wmManipulatorProperty *WM_manipulator_target_property_find(struct wmManipulator *mpr, const char *idname) RET_NULL
+bool WM_manipulator_target_property_is_valid(const struct wmManipulatorProperty *mpr_prop) RET_ZERO
+
#ifdef WITH_INPUT_NDOF
void WM_ndof_deadzone_set(float deadzone) RET_NONE
#endif
@@ -367,8 +431,10 @@ void ED_armature_edit_bone_remove(struct bArmature *arm, struct EditBone *exBone
void object_test_constraints(struct Object *owner) RET_NONE
void ED_armature_ebone_to_mat4(struct EditBone *ebone, float mat[4][4]) RET_NONE
void ED_armature_ebone_from_mat4(EditBone *ebone, float mat[4][4]) RET_NONE
-void ED_object_parent(struct Object *ob, struct Object *par, int type, const char *substr) RET_NONE
+void ED_object_parent(struct Object *ob, struct Object *par, const int type, const char *substr) RET_NONE
void ED_object_constraint_set_active(struct Object *ob, struct bConstraint *con) RET_NONE
+void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum) RET_NONE
+void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int facenum) RET_NONE
void ED_node_composit_default(const struct bContext *C, struct Scene *scene) RET_NONE
void *ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *custumdata, int type) RET_ZERO /* XXX this one looks weird */
void *ED_region_draw_cb_customdata(void *handle) RET_ZERO /* XXX This one looks wrong also */
@@ -395,7 +461,6 @@ void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *s
void ED_uvedit_get_aspect(struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy) RET_NONE
-void ED_screen_set_scene(struct bContext *C, struct bScreen *screen, struct Scene *scene) RET_NONE
struct MovieClip *ED_space_clip_get_clip(struct SpaceClip *sc) RET_NULL
void ED_space_clip_set_clip(struct bContext *C, struct bScreen *screen, struct SpaceClip *sc, struct MovieClip *clip) RET_NONE
void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mask *mask) RET_NONE
@@ -416,8 +481,8 @@ void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *name) RET
char *ED_fsmenu_entry_get_name(struct FSMenuEntry *fsentry) RET_NULL
void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name) RET_NONE
-struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob) RET_NULL
-void PE_current_changed(struct Scene *scene, struct Object *ob) RET_NONE
+struct PTCacheEdit *PE_get_current(struct Scene *scene, struct ViewLayer *view_layer, struct Object *ob) RET_NULL
+void PE_current_changed(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob) RET_NONE
/* rna keymap */
struct wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *keymap) RET_NULL
@@ -456,7 +521,7 @@ bool ANIM_remove_driver(struct ReportList *reports, struct ID *id, const char rn
void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock) RET_NONE
struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **r_lock) RET_NULL
void ED_space_image_get_zoom(struct SpaceImage *sima, struct ARegion *ar, float *zoomx, float *zoomy) RET_NONE
-const char *ED_info_stats_string(struct Scene *scene) RET_NULL
+const char *ED_info_stats_string(struct Scene *scene, struct ViewLayer *view_layer) RET_NULL
void ED_area_tag_redraw(struct ScrArea *sa) RET_NONE
void ED_area_tag_refresh(struct ScrArea *sa) RET_NONE
void ED_area_newspace(struct bContext *C, struct ScrArea *sa, int type, const bool skip_ar_exit) RET_NONE
@@ -478,19 +543,18 @@ void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int ma
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
+int ED_view3d_view_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
-struct BGpic *ED_view3D_background_image_new(struct View3D *v3d) RET_NULL
-void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic) RET_NONE
-void ED_view3D_background_image_clear(struct View3D *v3d) RET_NONE
-void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4], const struct rcti *rect) RET_NONE
+void ED_view3d_update_viewmat(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4], const struct rcti *rect) RET_NONE
float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) RET_ZERO
void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa) RET_NONE
void ED_node_shader_default(const struct bContext *C, struct ID *id) RET_NONE
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh) RET_NONE
struct bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm) RET_NULL
-void ED_base_object_select(struct Base *base, short mode) RET_NONE
+struct Scene *ED_screen_scene_find(const struct bScreen *screen, const struct wmWindowManager *wm) RET_NULL
+bool ED_scene_view_layer_delete(struct Main *bmain, Scene *scene, ViewLayer *layer, ReportList *reports) RET_ZERO
+void ED_object_base_select(struct Base *base, eObjectSelect_Mode 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
@@ -511,7 +575,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_object_base_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
@@ -537,7 +601,7 @@ int ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, struc
float ED_rollBoneToVector(EditBone *bone, const float new_up_axis[3], const bool axis_only) RET_ZERO
void ED_space_image_get_size(struct SpaceImage *sima, int *width, int *height) RET_NONE
-bool ED_space_image_check_show_maskedit(struct Scene *scene, struct SpaceImage *sima) RET_ZERO
+bool ED_space_image_check_show_maskedit(struct ViewLayer *view_layer, struct SpaceImage *sima) RET_ZERO
bool ED_texture_context_check_world(const struct bContext *C) RET_ZERO
bool ED_texture_context_check_material(const struct bContext *C) RET_ZERO
@@ -548,9 +612,9 @@ bool ED_texture_context_check_others(const struct bContext *C) RET_ZERO
bool ED_text_region_location_from_cursor(SpaceText *st, ARegion *ar, const int cursor_co[2], int r_pixel_co[2]) RET_ZERO
SnapObjectContext *ED_transform_snap_object_context_create(
- struct Main *bmain, struct Scene *scene, int flag) RET_NULL
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct RenderEngineType *engine, int flag) RET_NULL
SnapObjectContext *ED_transform_snap_object_context_create_view3d(
- struct Main *bmain, struct Scene *scene, int flag,
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct RenderEngineType *engine, int flag,
const struct ARegion *ar, const struct View3D *v3d) RET_NULL
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) RET_NONE
bool ED_transform_snap_object_project_ray_ex(
@@ -560,6 +624,7 @@ bool ED_transform_snap_object_project_ray_ex(
/* return args */
float r_loc[3], float r_no[3], int *r_index,
struct Object **r_ob, float r_obmat[4][4]) RET_ZERO
+void BIF_selectTransformOrientationValue(struct View3D *v3d, int orientation) RET_NONE
void ED_lattice_editlatt_make(struct Object *obedit) RET_NONE
void ED_lattice_editlatt_load(struct Object *obedit) RET_NONE
@@ -602,6 +667,14 @@ const char *uiLayoutIntrospect(uiLayout *layout) RET_NULL
void UI_reinit_font(void) RET_NONE
int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big) RET_ZERO
struct bTheme *UI_GetTheme(void) RET_NULL
+void UI_GetThemeColor3fv(int colorid, float col[4]) RET_NONE
+void UI_GetThemeColor4fv(int colorid, float col[4]) RET_NONE
+void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4]) RET_NONE
+void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4]) RET_NONE
+void UI_GetThemeColorBlendShade3fv(int colorid1, int colorid2, float fac, int offset, float col[3]) RET_NONE
+void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4]) RET_NONE
+void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3]) RET_NONE
+void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4]) RET_NONE
/* rna template */
void uiTemplateAnyID(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *proptypename, const char *text) RET_NONE
@@ -613,6 +686,17 @@ struct uiLayout *uiTemplateConstraint(struct uiLayout *layout, struct PointerRNA
void uiTemplatePreview(struct uiLayout *layout, struct bContext *C, struct ID *id, int show_buttons, struct ID *parent,
struct MTex *slot, const char *preview_id) RET_NONE
void uiTemplateIDPreview(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int rows, int cols) RET_NONE
+void uiTemplateSearch(
+ uiLayout *layout, struct bContext *C,
+ PointerRNA *ptr, const char *propname,
+ PointerRNA *searchptr, const char *searchpropname,
+ const char *newop, const char *unlinkop) RET_NONE
+void uiTemplateSearchPreview(
+ uiLayout *layout, struct bContext *C,
+ PointerRNA *ptr, const char *propname,
+ PointerRNA *searchptr, const char *searchpropname,
+ const char *newop, const char *unlinkop,
+ const int rows, const int cols) RET_NONE
void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type, int levels, int brush, int neg_slope) RET_NONE
void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int expand) RET_NONE
void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *used_ptr, const char *used_propname, int active_layer) RET_NONE
@@ -635,6 +719,7 @@ void uiTemplateNodeView(struct uiLayout *layout, struct bContext *C, struct bNod
void uiTemplateTextureUser(struct uiLayout *layout, struct bContext *C) RET_NONE
void uiTemplateTextureShow(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop) RET_NONE
void uiTemplateKeymapItemProperties(struct uiLayout *layout, struct PointerRNA *ptr) RET_NONE
+void uiTemplateOverrideProperty(struct uiLayout *layout, struct PointerRNA *collection_props_ptr, struct PointerRNA *scene_props_ptr, const char *propname, const char *name, const char *text_ctxt, int translate, int icon, const char *custom_template) RET_NONE
void uiTemplateMovieClip(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, int compact) RET_NONE
void uiTemplateMovieclipInformation(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr) RET_NONE
void uiTemplateTrack(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) RET_NONE
@@ -669,6 +754,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
@@ -677,14 +763,23 @@ void RE_engine_update_memory_stats(struct RenderEngine *engine, float mem_used,
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_cache(struct Scene *scene, struct ViewLayer *view_layer, struct PointDensity *pd, const bool use_render_params) RET_NONE
+void RE_point_density_minmax(struct Scene *scene, struct ViewLayer *view_layer, 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 ViewLayer *view_layer, struct PointDensity *pd, const 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
-void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int channels, const char *chanid, int type) RET_NONE
+void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer, const char *name, int channels, const char *chanid, int type) RET_NONE
+struct ViewLayer *RE_engine_get_view_layer(struct Render *re) RET_NULL
+void RE_SetDepsgraph(struct Render *re, struct Depsgraph *graph) RET_NONE
+
+/* Draw */
+void OBJECT_collection_settings_create(struct IDProperty *properties) RET_NONE
+void EDIT_MESH_collection_settings_create(struct IDProperty *properties) RET_NONE
+void EDIT_ARMATURE_collection_settings_create(struct IDProperty *properties) RET_NONE
+void PAINT_WEIGHT_collection_settings_create(struct IDProperty *properties) RET_NONE
+void PAINT_VERTEX_collection_settings_create(struct IDProperty *properties) RET_NONE
/* python */
struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) RET_NULL
@@ -726,10 +821,10 @@ struct uiLayout *uiLayoutRadial(struct uiLayout *layout) RET_NULL
int UI_pie_menu_invoke_from_operator_enum(struct bContext *C, const char *title, const char *opname,
const char *propname, const struct wmEvent *event) RET_ZERO
-/* RNA COLLADA dependency */
-/* XXX (gaia) Why do we need this declaration here? */
-/* The collada header is included anyways further up... */
-int collada_export(struct Scene *sce,
+/* RNA COLLADA dependency */
+int collada_export(const struct EvaluationContext *eval_ctx,
+ struct Scene *sce,
+ struct ViewLayer *view_layer,
const char *filepath,
int apply_modifiers,
BC_export_mesh_type export_mesh_type,
@@ -741,7 +836,7 @@ int collada_export(struct Scene *sce,
int deform_bones_only,
int active_uv_only,
- BC_export_texture_type export_texture_type,
+ int include_material_textures,
int use_texture_copies,
int triangulate,
@@ -762,6 +857,7 @@ void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata) RET_NON
void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
void BPY_text_free_code(struct Text *text) RET_NONE
void BPY_id_release(struct ID *id) RET_NONE
+void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr) RET_NONE
int BPY_context_member_get(struct bContext *C, const char *member, struct bContextDataResult *result) RET_ZERO
void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTarget *ct) RET_NONE
float BPY_driver_exec(PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime) RET_ZERO /* might need this one! */
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 2bda651f756..c5acd7e640e 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -412,6 +412,12 @@ if(WITH_OPENCOLORIO)
)
endif()
+# Add default workspaces.blend to build (under [version]/datafiles
+install(
+ FILES ${CMAKE_SOURCE_DIR}/release/datafiles/workspaces.blend
+ DESTINATION ${TARGETDIR_VER}/datafiles
+)
+
# helpful tip when using make
if("${CMAKE_GENERATOR}" MATCHES ".*Makefiles.*")
# message after building.
diff --git a/source/creator/creator.c b/source/creator/creator.c
index a59a45f885c..78bab14cd96 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -56,7 +56,6 @@
#include "BKE_brush.h"
#include "BKE_cachefile.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h" /* for DAG_init */
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_material.h"
@@ -66,6 +65,7 @@
#include "BKE_image.h"
#include "BKE_particle.h"
+#include "DEG_depsgraph.h"
#include "IMB_imbuf.h" /* for IMB_init */
@@ -361,7 +361,7 @@ int main(
BKE_cachefiles_init();
BKE_images_init();
BKE_modifier_init();
- DAG_init();
+ DEG_register_node_types();
BKE_brush_system_init();
RE_texture_rng_init();
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 19f30584f89..6b47d7c3474 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -57,8 +57,6 @@
#include "BKE_sound.h"
#include "BKE_image.h"
-#include "DEG_depsgraph.h"
-
#ifdef WITH_FFMPEG
#include "IMB_imbuf.h"
#endif
@@ -74,9 +72,7 @@
#include "WM_api.h"
-#include "GPU_basic_shader.h"
#include "GPU_draw.h"
-#include "GPU_extensions.h"
/* for passing information between creator and gameengine */
#ifdef WITH_GAMEENGINE
@@ -93,6 +89,10 @@
# include "CCL_api.h"
#endif
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_debug.h"
+
#include "creator_intern.h" /* own include */
@@ -428,6 +428,25 @@ static void arg_py_context_restore(
/** \} */
+static void render_set_depgraph(bContext *C, Render *re)
+{
+ /* TODO(sergey): For until we make depsgraph to be created and
+ * handled by render pipeline.
+ */
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ /* NOTE: This is STUPID to use first layer, but is ok for now
+ * (at least for until depsgraph becomes per-layer).
+ * Apparently, CTX_data_layer is crashing here (context's layer
+ * is NULL for old files, and there is no workspace).
+ */
+ ViewLayer *view_layer = scene->view_layers.first;
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
+ DEG_graph_on_visible_update(bmain, depsgraph);
+
+ RE_SetDepsgraph(re, depsgraph);
+}
/* -------------------------------------------------------------------- */
@@ -554,6 +573,7 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
BLI_argsPrintArgDoc(ba, "--debug-depsgraph-no-threads");
BLI_argsPrintArgDoc(ba, "--debug-gpumem");
+ BLI_argsPrintArgDoc(ba, "--debug-gpu-shaders");
BLI_argsPrintArgDoc(ba, "--debug-wm");
BLI_argsPrintArgDoc(ba, "--debug-all");
BLI_argsPrintArgDoc(ba, "--debug-io");
@@ -571,7 +591,6 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
BLI_argsPrintArgDoc(ba, "--env-system-python");
printf("\n");
BLI_argsPrintArgDoc(ba, "-nojoystick");
- BLI_argsPrintArgDoc(ba, "-noglsl");
BLI_argsPrintArgDoc(ba, "-noaudio");
BLI_argsPrintArgDoc(ba, "-setaudio");
@@ -589,8 +608,7 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
printf("\n");
printf("Experimental Features:\n");
- BLI_argsPrintArgDoc(ba, "--enable-new-depsgraph");
- BLI_argsPrintArgDoc(ba, "--enable-new-basic-shader-glsl");
+ BLI_argsPrintArgDoc(ba, "--enable-copy-on-write");
/* Other options _must_ be last (anything not handled will show here) */
printf("\n");
@@ -1021,15 +1039,6 @@ static int arg_handle_joystick_disable(int UNUSED(argc), const char **UNUSED(arg
return 0;
}
-static const char arg_handle_glsl_disable_doc[] =
-"\n\tDisable GLSL shading."
-;
-static int arg_handle_glsl_disable(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
-{
- GPU_extensions_disable();
- return 0;
-}
-
static const char arg_handle_audio_disable_doc[] =
"\n\tForce sound system to None."
;
@@ -1107,10 +1116,8 @@ static int arg_handle_engine_set(int argc, const char **argv, void *data)
else {
Scene *scene = CTX_data_scene(C);
if (scene) {
- RenderData *rd = &scene->r;
-
if (BLI_findstring(&R_engines, argv[1], offsetof(RenderEngineType, idname))) {
- BLI_strncpy_utf8(rd->engine, argv[1], sizeof(rd->engine));
+ BLI_strncpy_utf8(scene->view_render.engine_id, argv[1], sizeof(scene->view_render.engine_id));
}
else {
printf("\nError: engine not found '%s'\n", argv[1]);
@@ -1193,23 +1200,13 @@ static int arg_handle_threads_set(int argc, const char **argv, void *UNUSED(data
}
}
-static const char arg_handle_depsgraph_use_new_doc[] =
-"\n\tUse new dependency graph."
+static const char arg_handle_use_copy_on_write_doc[] =
+"\n\tUse new dependency graph"
;
-static int arg_handle_depsgraph_use_new(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+static int arg_handle_use_copy_on_write(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
- printf("Using new dependency graph.\n");
- DEG_depsgraph_switch_to_new();
- return 0;
-}
-
-static const char arg_handle_basic_shader_glsl_use_new_doc[] =
-"\n\tUse new GLSL basic shader."
-;
-static int arg_handle_basic_shader_glsl_use_new(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
-{
- printf("Using new GLSL basic shader.\n");
- GPU_basic_shader_use_glsl_set(true);
+ printf("Using copy on write. This is highly EXPERIMENTAL!\n");
+ DEG_depsgraph_enable_copy_on_write();
return 0;
}
@@ -1378,8 +1375,8 @@ static int arg_handle_render_frame(int argc, const char **argv, void *data)
re = RE_NewSceneRender(scene);
BLI_begin_threaded_malloc();
BKE_reports_init(&reports, RPT_STORE);
-
RE_SetReports(re, &reports);
+ render_set_depgraph(C, re);
for (int i = 0; i < frames_range_len; i++) {
/* We could pass in frame ranges,
* but prefer having exact behavior as passing in multiple frames */
@@ -1422,6 +1419,7 @@ static int arg_handle_render_animation(int UNUSED(argc), const char **UNUSED(arg
BLI_begin_threaded_malloc();
BKE_reports_init(&reports, RPT_STORE);
RE_SetReports(re, &reports);
+ render_set_depgraph(C, re);
RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step);
RE_SetReports(re, NULL);
BKE_reports_clear(&reports);
@@ -1861,9 +1859,10 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
CB_EX(arg_handle_debug_mode_generic_set, depsgraph_no_threads), (void *)G_DEBUG_DEPSGRAPH_NO_THREADS);
BLI_argsAdd(ba, 1, NULL, "--debug-gpumem",
CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM);
+ BLI_argsAdd(ba, 1, NULL, "--debug-gpu-shaders",
+ CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_SHADERS);
- BLI_argsAdd(ba, 1, NULL, "--enable-new-depsgraph", CB(arg_handle_depsgraph_use_new), NULL);
- BLI_argsAdd(ba, 1, NULL, "--enable-new-basic-shader-glsl", CB(arg_handle_basic_shader_glsl_use_new), NULL);
+ BLI_argsAdd(ba, 1, NULL, "--enable-copy-on-write", CB(arg_handle_use_copy_on_write), NULL);
BLI_argsAdd(ba, 1, NULL, "--verbose", CB(arg_handle_verbosity_set), NULL);
@@ -1885,7 +1884,6 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
/* third pass: disabling things and forcing settings */
BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, CB(arg_handle_joystick_disable), syshandle);
- BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, CB(arg_handle_glsl_disable), NULL);
BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, CB(arg_handle_audio_disable), NULL);
BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, CB(arg_handle_audio_set), NULL);
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 6e698166fd9..4e8f0eba9b7 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -101,7 +101,7 @@ typedef void * wmUIHandlerRemoveFunc;
}
#ifdef WITH_AUDASPACE
-# include AUD_DEVICE_H
+# include <AUD_Device.h>
#endif
static BlendFileData *load_game_data(const char *filename)
@@ -267,7 +267,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
bool animation_record = (SYS_GetCommandLineInt(syshandle, "animation_record", 0) != 0);
- bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0) && GPU_display_list_support();
+ bool displaylists = false; // (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0) && GPU_display_list_support();
#ifdef WITH_PYTHON
bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0);
#endif
diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt
index aaeb2e10462..42293050753 100644
--- a/source/gameengine/BlenderRoutines/CMakeLists.txt
+++ b/source/gameengine/BlenderRoutines/CMakeLists.txt
@@ -56,7 +56,7 @@ set(SRC
add_definitions(${GL_DEFINITIONS})
if(WITH_AUDASPACE)
- add_definitions(${AUDASPACE_DEFINITIONS})
+ add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
index a6b2340d7b4..6fdc823ba1a 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
@@ -324,7 +324,6 @@ static unsigned int *screenshot(ScrArea *curarea, int *dumpsx, int *dumpsy)
void KX_BlenderCanvas::MakeScreenShot(const char *filename)
{
ScrArea area_dummy= {0};
- bScreen *screen = m_win->screen;
unsigned int *dumprect;
int dumpsx, dumpsy;
@@ -340,7 +339,7 @@ void KX_BlenderCanvas::MakeScreenShot(const char *filename)
}
/* initialize image file format data */
- Scene *scene = (screen)? screen->scene: NULL;
+ Scene *scene = WM_window_get_active_scene(m_win);
ImageFormatData *im_format = (ImageFormatData *)MEM_mallocN(sizeof(ImageFormatData), "im_format");
if (scene)
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index a5af525e13a..049fd49cab9 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -138,7 +138,8 @@ static void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
if (pchan->prop)
pchan->prop= IDP_CopyProperty(pchan->prop);
#endif
- pchan->prop= NULL;
+ pchan->prop = NULL;
+ pchan->draw_data = NULL;
}
BLI_ghash_free(ghash, NULL, NULL);
@@ -469,6 +470,8 @@ bool BL_ArmatureObject::UnlinkObject(SCA_IObject* clientobj)
void BL_ArmatureObject::ApplyPose()
{
+ /* TODO: This doesn't work currently because of eval_ctx. */
+#if 0
m_armpose = m_objArma->pose;
m_objArma->pose = m_pose;
// in the GE, we use ctime to store the timestep
@@ -491,6 +494,7 @@ void BL_ArmatureObject::ApplyPose()
}
m_lastapplyframe = m_lastframe;
}
+#endif
}
void BL_ArmatureObject::RestorePose()
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 4751e60996d..acd425e788a 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -45,7 +45,9 @@
* This workaround will make sure that curve_cache for curves
* is up-to-date.
*/
-#define THREADED_DAG_WORKAROUND
+
+/* TODO: Disabled for now, because of eval_ctx. */
+//#define THREADED_DAG_WORKAROUND
#include <math.h>
#include <vector>
@@ -145,6 +147,8 @@ extern "C" {
#include "BKE_customdata.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_group.h"
+#include "BKE_layer.h"
#include "BKE_material.h" /* give_current_material */
#include "BKE_image.h"
#include "IMB_imbuf_types.h"
@@ -589,17 +593,17 @@ static bool ConvertMaterial(
/* In Multitexture use the face texture if and only if
* it is set in the buttons
* In GLSL is not working yet :/ 3.2011 */
- bool facetex = false;
- if (validface && mat->mode & MA_FACETEXTURE) {
- facetex = true;
- }
// foreach MTex
for (int i = 0; i < MAXTEX; i++) {
// use face tex
- if (i == 0 && facetex ) {
- facetex = false;
+ if (i == 0) {
+#if 0
Image *tmp = (Image *)(tface->tpage);
+#else
+ /* weak but better then nothing */
+ Image *tmp = mat ? mat->edit_image : NULL;
+#endif
if (tmp) {
material->img[i] = tmp;
@@ -789,7 +793,11 @@ static bool ConvertMaterial(
// check for tface tex to fallback on
if (validface) {
+#if 0
material->img[0] = (Image *)(tface->tpage);
+#else
+ material->img[0] = mat ? mat->edit_image : NULL;
+#endif
// ------------------------
if (material->img[0]) {
material->texname[0] = material->img[0]->id.name;
@@ -830,7 +838,7 @@ static bool ConvertMaterial(
/* No material, what to do? let's see what is in the UV and set the material accordingly
* light and visible is always on */
if (validface) {
- material->tile = tface->tile;
+ /* nop */
}
else {
// nothing at all
@@ -869,13 +877,6 @@ static bool ConvertMaterial(
if (validmat) {
material->matname =(mat->id.name);
}
-
- if (tface) {
- ME_MTEXFACE_CPY(&material->mtexpoly, tface);
- }
- else {
- memset(&material->mtexpoly, 0, sizeof(material->mtexpoly));
- }
material->material = mat;
return true;
}
@@ -894,7 +895,7 @@ static RAS_MaterialBucket *material_from_mesh(Material *ma, MFace *mface, MTFace
ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol,
converter->GetGLSLMaterials());
- if (ma && (ma->mode & MA_FACETEXTURE) == 0)
+ if (ma)
converter->CacheBlenderMaterial(scene, ma, bl_mat);
}
@@ -910,7 +911,7 @@ static RAS_MaterialBucket *material_from_mesh(Material *ma, MFace *mface, MTFace
kx_blmat->Initialize(scene, bl_mat, (ma?&ma->game:NULL), lightlayer);
polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat);
- if (ma && (ma->mode & MA_FACETEXTURE) == 0)
+ if (ma)
converter->CachePolyMaterial(scene, ma, polymat);
}
@@ -1740,7 +1741,7 @@ static void blenderSceneSetBackground(Scene *blenderscene)
for (SETLOOPER(blenderscene, it, base)) {
base->object->lay = base->lay;
- base->object->flag = base->flag;
+ BKE_scene_object_base_flag_sync_from_base(base);
}
}
@@ -2052,10 +2053,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
for (git=tempglist.begin(); git!=tempglist.end(); git++)
{
Group* group = *git;
- GroupObject* go;
- for (go=(GroupObject*)group->gobject.first; go; go=(GroupObject*)go->next)
+ FOREACH_GROUP_OBJECT(group, blenderobject)
{
- Object* blenderobject = go->ob;
if (converter->FindGameObject(blenderobject) == NULL)
{
allblobj.insert(blenderobject);
@@ -2090,6 +2089,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
}
}
}
+ FOREACH_GROUP_OBJECT_END
}
}
}
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp
index b40fb7a9f47..3be2c1aff43 100644
--- a/source/gameengine/Converter/BL_ModifierDeformer.cpp
+++ b/source/gameengine/Converter/BL_ModifierDeformer.cpp
@@ -133,6 +133,8 @@ bool BL_ModifierDeformer::HasArmatureDeformer(Object *ob)
// return a deformed mesh that supports mapping (with a valid CD_ORIGINDEX layer)
struct DerivedMesh* BL_ModifierDeformer::GetPhysicsMesh()
{
+ /* TODO: This doesn't work currently because of eval_ctx. */
+#if 0
/* we need to compute the deformed mesh taking into account the current
* shape and skin deformers, we cannot just call mesh_create_derived_physics()
* because that would use the m_transvers already deformed previously by BL_ModifierDeformer::Update(),
@@ -152,10 +154,14 @@ struct DerivedMesh* BL_ModifierDeformer::GetPhysicsMesh()
/* m_transverts is correct here (takes into account deform only modifiers) */
/* the derived mesh returned by this function must be released by the caller !!! */
return dm;
+#endif
+ return NULL;
}
bool BL_ModifierDeformer::Update(void)
{
+ /* TODO: This doesn't work currently because of eval_ctx. */
+#if 0
bool bShapeUpdate = BL_ShapeDeformer::Update();
if (bShapeUpdate || m_lastModifierUpdate != m_gameobj->GetLastFrame()) {
@@ -208,6 +214,8 @@ bool BL_ModifierDeformer::Update(void)
}
}
return bShapeUpdate;
+#endif
+ return false;
}
bool BL_ModifierDeformer::Apply(RAS_IPolyMaterial *mat)
diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt
index 4db9fcebd06..7d6195e3c38 100644
--- a/source/gameengine/Converter/CMakeLists.txt
+++ b/source/gameengine/Converter/CMakeLists.txt
@@ -113,7 +113,7 @@ if(WITH_BULLET)
endif()
if(WITH_AUDASPACE)
- add_definitions(${AUDASPACE_DEFINITIONS})
+ add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 974dcbca95b..d78ea4eed54 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -42,7 +42,7 @@
#include "KX_ConvertActuators.h"
#ifdef WITH_AUDASPACE
-# include AUD_SOUND_H
+# include <AUD_Sound.h>
#endif
// Actuators
diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt
index 577e25d6198..5bce9fcd248 100644
--- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt
+++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt
@@ -43,6 +43,7 @@ set(INC
../../../blender/blenlib
../../../blender/blenloader
../../../blender/blentranslation
+ ../../../blender/depsgraph
../../../blender/gpu
../../../blender/imbuf
../../../blender/makesdna
@@ -94,7 +95,7 @@ if(WITH_INTERNATIONAL)
endif()
if(WITH_AUDASPACE)
- add_definitions(${AUDASPACE_DEFINITIONS})
+ add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index 50c34bbadaf..1b6b6defdf9 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -99,7 +99,7 @@ extern "C"
#include "GHOST_Rect.h"
#ifdef WITH_AUDASPACE
-# include AUD_DEVICE_H
+# include <AUD_Device.h>
#endif
static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
@@ -586,7 +586,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixedtime", (gm->flag & GAME_ENABLE_ALL_FRAMES)) != 0);
bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
- bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", gm->flag & GAME_DISPLAY_LISTS) != 0) && GPU_display_list_support();
+ bool useLists = false; // (SYS_GetCommandLineInt(syshandle, "displaylists", gm->flag & GAME_DISPLAY_LISTS) != 0) && GPU_display_list_support();
bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 1) != 0);
bool restrictAnimFPS = (gm->flag & GAME_RESTRICT_ANIM_UPDATES) != 0;
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index 906e9d9a821..998058193bb 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -68,7 +68,6 @@ extern "C"
#include "BKE_appdir.h"
#include "BKE_blender.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_image.h"
@@ -81,6 +80,8 @@ extern "C"
#include "BKE_text.h"
#include "BKE_sound.h"
+#include "DEG_depsgraph.h"
+
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
@@ -509,7 +510,7 @@ int main(
IMB_init();
BKE_images_init();
BKE_modifier_init();
- DAG_init();
+ DEG_register_node_types();
#ifdef WITH_FFMPEG
IMB_ffmpeg_init();
@@ -1201,7 +1202,7 @@ int main(
IMB_exit();
BKE_images_exit();
- DAG_exit();
+ DEG_free_node_types();
IMB_moviecache_destruct();
SYS_DeleteSystem(syshandle);
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp
index 9cbd61590b6..572218e691d 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.cpp
+++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp
@@ -77,7 +77,7 @@ void BL_BlenderShader::SetProg(bool enable, double time, RAS_IRasterizer* rasty)
view.getValue(&viewmat[0][0]);
viewinv.getValue(&viewinvmat[0][0]);
- GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1, viewmat, viewinvmat, NULL, false);
+ GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1, viewmat, viewinvmat, NULL);
}
else
GPU_material_unbind(mGPUMat);
diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp
index 4f707e6267f..40384b43054 100644
--- a/source/gameengine/Ketsji/BL_Material.cpp
+++ b/source/gameengine/Ketsji/BL_Material.cpp
@@ -69,7 +69,6 @@ void BL_Material::Initialize()
alpha = 1.f;
emit = 0.f;
material = 0;
- memset(&mtexpoly, 0, sizeof(mtexpoly));
materialindex = 0;
amb=0.5f;
num_enabled = 0;
diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h
index 9207a41f56d..710c02f4871 100644
--- a/source/gameengine/Ketsji/BL_Material.h
+++ b/source/gameengine/Ketsji/BL_Material.h
@@ -84,7 +84,6 @@ public:
Material* material;
- MTexPoly mtexpoly; /* copy of the derived meshes tface */
Image* img[MAXTEX];
EnvMap* cubemap[MAXTEX];
diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt
index 417f54cc8b9..cb7c0180f30 100644
--- a/source/gameengine/Ketsji/CMakeLists.txt
+++ b/source/gameengine/Ketsji/CMakeLists.txt
@@ -244,7 +244,7 @@ if(WITH_CODEC_FFMPEG)
endif()
if(WITH_AUDASPACE)
- add_definitions(${AUDASPACE_DEFINITIONS})
+ add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index d26e35f8138..98d27ef3685 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -160,12 +160,6 @@ KX_BlenderMaterial::~KX_BlenderMaterial()
OnExit();
}
-MTexPoly *KX_BlenderMaterial::GetMTexPoly() const
-{
- // fonts on polys
- return &mMaterial->mtexpoly;
-}
-
unsigned int* KX_BlenderMaterial::GetMCol() const
{
// fonts on polys
@@ -190,7 +184,7 @@ Material *KX_BlenderMaterial::GetBlenderMaterial() const
Image *KX_BlenderMaterial::GetBlenderImage() const
{
- return mMaterial->mtexpoly.tpage;
+ return mMaterial->material ? mMaterial->material->edit_image : NULL;
}
Scene* KX_BlenderMaterial::GetBlenderScene() const
@@ -290,11 +284,6 @@ void KX_BlenderMaterial::OnExit()
mTextures[i].DeleteTex();
mTextures[i].DisableUnit();
}
-
- /* used to call with 'mMaterial->tface' but this can be a freed array,
- * see: [#30493], so just call with NULL, this is best since it clears
- * the 'lastface' pointer in GPU too - campbell */
- GPU_set_tpage(NULL, 1, mMaterial->alphablend);
}
@@ -310,7 +299,7 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras)
mLastShader = NULL;
}
- ras->SetAlphaBlend(TF_SOLID);
+ ras->SetAlphaBlend(GPU_BLEND_SOLID);
BL_Texture::DisableAllTextures();
return;
}
@@ -334,7 +323,7 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras)
ras->SetAlphaBlend(mMaterial->alphablend);
}
else {
- ras->SetAlphaBlend(TF_SOLID);
+ ras->SetAlphaBlend(GPU_BLEND_SOLID);
ras->SetAlphaBlend(-1); // indicates custom mode
// tested to be valid enums
@@ -346,7 +335,7 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras)
void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras)
{
if ( !enable || !mBlenderShader->Ok() ) {
- ras->SetAlphaBlend(TF_SOLID);
+ ras->SetAlphaBlend(GPU_BLEND_SOLID);
// frame cleanup.
if (mLastBlenderShader) {
@@ -377,7 +366,7 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras)
BL_Texture::DisableAllTextures();
if ( !enable ) {
- ras->SetAlphaBlend(TF_SOLID);
+ ras->SetAlphaBlend(GPU_BLEND_SOLID);
return;
}
@@ -420,7 +409,7 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras)
ras->SetAlphaBlend(mMaterial->alphablend);
}
else {
- ras->SetAlphaBlend(TF_SOLID);
+ ras->SetAlphaBlend(GPU_BLEND_SOLID);
ras->SetAlphaBlend(-1); // indicates custom mode
glEnable(GL_BLEND);
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h
index a3d10c0a89d..c562ee0c583 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.h
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h
@@ -84,7 +84,6 @@ public:
Material* GetBlenderMaterial() const;
Image* GetBlenderImage() const;
- MTexPoly *GetMTexPoly() const;
unsigned int* GetMCol() const;
BL_Texture * getTex (unsigned int idx) {
return (idx < MAXTEX) ? mTextures + idx : NULL;
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp
index 89aea80bb67..b22873aa862 100644
--- a/source/gameengine/Ketsji/KX_Camera.cpp
+++ b/source/gameengine/Ketsji/KX_Camera.cpp
@@ -30,8 +30,8 @@
* \ingroup ketsji
*/
-
-#include "glew-mx.h"
+#include "GPU_glew.h"
+#include "GPU_matrix.h"
#include "KX_Camera.h"
#include "KX_Scene.h"
#include "KX_PythonInit.h"
@@ -1048,19 +1048,21 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition,
}
const GLint *viewport;
- GLdouble win[3];
- GLdouble modelmatrix[16];
- GLdouble projmatrix[16];
+ GLfloat vec[3];
+ GLfloat win[3];
+ GLfloat modelmatrix[4][4];
+ GLfloat projmatrix[4][4];
MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera();
MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix();
- m_modelmatrix.getValue(modelmatrix);
- m_projmatrix.getValue(projmatrix);
+ vect.getValue(vec);
+ m_modelmatrix.getValue((float*) modelmatrix);
+ m_projmatrix.getValue((float*) projmatrix);
viewport = KX_GetActiveEngine()->GetCanvas()->GetViewPort();
- gluProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]);
+ gpuProject(vec, modelmatrix, projmatrix, viewport, win);
vect[0] = (win[0] - viewport[0]) / viewport[2];
vect[1] = (win[1] - viewport[1]) / viewport[3];
@@ -1087,36 +1089,33 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect,
y = 1.0 - y; //to follow Blender window coordinate system (Top-Down)
- MT_Vector3 vect;
- MT_Point3 campos, screenpos;
-
const GLint *viewport;
- GLdouble win[3];
- GLdouble modelmatrix[16];
- GLdouble projmatrix[16];
+ GLfloat vec[3];
+ GLfloat win[3];
+ GLfloat modelmatrix[4][4];
+ GLfloat projmatrix[4][4];
MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera();
MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix();
- m_modelmatrix.getValue(modelmatrix);
- m_projmatrix.getValue(projmatrix);
+ m_modelmatrix.getValue((float*) modelmatrix);
+ m_projmatrix.getValue((float*) projmatrix);
viewport = KX_GetActiveEngine()->GetCanvas()->GetViewPort();
- vect[0] = x * viewport[2];
- vect[1] = y * viewport[3];
-
- vect[0] += viewport[0];
- vect[1] += viewport[1];
+ vec[0] = x * viewport[2];
+ vec[1] = y * viewport[3];
- vect[2] = 0.f;
+ vec[0] += viewport[0];
+ vec[1] += viewport[1];
- gluUnProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]);
+ vec[2] = 0.f;
- campos = this->GetCameraLocation();
- screenpos = MT_Point3(win[0], win[1], win[2]);
- vect = campos-screenpos;
+ gpuUnProject(vec, modelmatrix, projmatrix, viewport, win);
+ MT_Point3 campos = this->GetCameraLocation();
+ MT_Point3 screenpos(win[0], win[1], win[2]);
+ MT_Vector3 vect = campos - screenpos;
vect.normalize();
return PyObjectFrom(vect);
}
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index d08372e47d4..7abff85d39c 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -41,7 +41,7 @@
#include "RAS_CameraData.h"
#include "BLI_math.h"
-#include "glew-mx.h"
+#include "GPU_matrix.h"
// constructor
KX_Dome::KX_Dome (
@@ -1685,7 +1685,7 @@ void KX_Dome::DrawEnvMap(void)
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- gluLookAt(0.0f,0.0f,1.0f, 0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f);
+ gpuLookAt(0.0f,0.0f,1.0f, 0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f);
glPolygonMode(GL_FRONT, GL_FILL);
glShadeModel(GL_SMOOTH);
@@ -1830,7 +1830,7 @@ void KX_Dome::DrawDomeFisheye(void)
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- gluLookAt(0.0f,-1.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,1.0f);
+ gpuLookAt(0.0f,-1.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,1.0f);
if (m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
glPolygonMode(GL_FRONT, GL_LINE);
@@ -1913,7 +1913,7 @@ void KX_Dome::DrawPanorama(void)
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- gluLookAt(0.0f,-1.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,1.0f);
+ gpuLookAt(0.0f,-1.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,1.0f);
if (m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
glPolygonMode(GL_FRONT, GL_LINE);
@@ -1981,7 +1981,7 @@ void KX_Dome::DrawDomeWarped(void)
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- gluLookAt(0.0f, 0.0f, 1.0f, 0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f);
+ gpuLookAt(0.0f, 0.0f, 1.0f, 0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f);
if (m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
glPolygonMode(GL_FRONT, GL_LINE);
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index 5f490747c2b..fcdcdf4a02a 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"
@@ -65,7 +65,6 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,
m_rasterizer->AddLight(m_lightobj);
m_lightobj->m_glsl = glsl;
m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene();
- m_base = NULL;
};
@@ -75,11 +74,6 @@ KX_LightObject::~KX_LightObject()
m_rasterizer->RemoveLight(m_lightobj);
delete(m_lightobj);
}
-
- if (m_base) {
- BKE_scene_base_unlink(m_blenderscene, m_base);
- MEM_freeN(m_base);
- }
}
@@ -93,8 +87,6 @@ CValue* KX_LightObject::GetReplica()
replica->m_lightobj = m_lightobj->Clone();
replica->m_lightobj->m_light = replica;
m_rasterizer->AddLight(replica->m_lightobj);
- if (m_base)
- m_base = NULL;
return replica;
}
@@ -103,7 +95,6 @@ void KX_LightObject::UpdateScene(KX_Scene *kxscene)
{
m_lightobj->m_scene = (void*)kxscene;
m_blenderscene = kxscene->GetBlenderScene();
- m_base = BKE_scene_base_add(m_blenderscene, GetBlenderObject());
}
void KX_LightObject::SetLayer(int layer)
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index b446acd6e63..b354fca4d41 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -51,7 +51,6 @@ protected:
RAS_ILightObject* m_lightobj;
class RAS_IRasterizer* m_rasterizer; //needed for registering and replication of lightobj
Scene* m_blenderscene;
- Base* m_base;
public:
KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,RAS_IRasterizer* rasterizer,RAS_ILightObject* lightobj, bool glsl);
diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
index 5beda2e038a..83accb1d7a5 100644
--- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp
+++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
@@ -113,6 +113,8 @@ bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts,
float *&dvertices, int &ndvertsuniq, unsigned short *&dtris,
int& ndtris, int &vertsPerPoly)
{
+ /* TODO: This doesn't work currently because of eval_ctx. */
+#if 0
DerivedMesh* dm = mesh_create_derived_no_virtual(GetScene()->GetBlenderScene(), GetBlenderObject(),
NULL, CD_MASK_MESH);
CustomData *pdata = dm->getPolyDataLayout(dm);
@@ -280,6 +282,8 @@ bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts,
dm->release(dm);
return true;
+#endif
+ return false;
}
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index b3061087344..48b50d24975 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -105,6 +105,7 @@
#include "KX_Light.h"
+#include "BKE_group.h"
#include "BLI_task.h"
static void *KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene)
@@ -720,7 +721,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
KX_GameObject* gameobj;
Object* blgroupobj = groupobj->GetBlenderObject();
Group* group;
- GroupObject *go;
vector<KX_GameObject*> duplilist;
if (!groupobj->GetSGNode() ||
@@ -738,9 +738,9 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
m_groupGameObjects.clear();
group = blgroupobj->dup_group;
- for (go=(GroupObject*)group->gobject.first; go; go=(GroupObject*)go->next)
+ FOREACH_GROUP_BASE(group, base)
{
- Object* blenderobj = go->ob;
+ Object *blenderobj = base->object;
if (blgroupobj == blenderobj)
// this check is also in group_duplilist()
continue;
@@ -755,13 +755,13 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
gameobj->SetBlenderGroupObject(blgroupobj);
- if ((blenderobj->lay & group->layer)==0)
- {
+ if ((base->flag & BASE_VISIBLED) == 0) {
// object is not visible in the 3D view, will not be instantiated
continue;
}
m_groupGameObjects.insert(gameobj);
}
+ FOREACH_GROUP_BASE_END
set<CValue*>::iterator oit;
for (oit=m_groupGameObjects.begin(); oit != m_groupGameObjects.end(); oit++)
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index 64aab31ba22..a09429450cb 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -37,14 +37,12 @@
#include "KX_SoundActuator.h"
#ifdef WITH_AUDASPACE
-# ifdef WITH_SYSTEM_AUDASPACE
typedef float sample_t;
-# include AUD_PYTHON_H
-# endif
-# include AUD_SOUND_H
-# include AUD_SPECIAL_H
-# include AUD_DEVICE_H
-# include AUD_HANDLE_H
+# include <python/PyAPI.h>
+# include <AUD_Sound.h>
+# include <AUD_Special.h>
+# include <AUD_Device.h>
+# include <AUD_Handle.h>
#endif
#include "KX_GameObject.h"
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h
index 5ec2fda722f..4f3e6f707e0 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.h
+++ b/source/gameengine/Ketsji/KX_SoundActuator.h
@@ -35,8 +35,8 @@
#include "SCA_IActuator.h"
#ifdef WITH_AUDASPACE
-# include AUD_SOUND_H
-# include AUD_HANDLE_H
+# include <AUD_Sound.h>
+# include <AUD_Handle.h>
#endif
#include "BKE_sound.h"
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index c79e1c23ef6..b3cee944880 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -2234,7 +2234,9 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA
std::vector<int> vert_remap_array(numverts, 0);
for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) {
- if (tf->mode & TF_DYNAMIC) {
+ // 2.8x TODO: use GEMAT_NOPHYSICS.
+ // if (tf->mode & TF_DYNAMIC)
+ {
int flen;
if (mf->v4) {
@@ -2271,7 +2273,9 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RA
int *poly_index_pt = &m_polygonIndexArray[0];
for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) {
- if (tf->mode & TF_DYNAMIC) {
+ // 2.8x TODO: use GEMAT_NOPHYSICS.
+ // if (tf->mode & TF_DYNAMIC)
+ {
int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i;
if (mf->v4) {
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
index 2a736aa7deb..1d22d2debf9 100644
--- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
+++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
@@ -233,10 +233,6 @@ Image *RAS_IPolyMaterial::GetBlenderImage() const
{
return NULL;
}
-MTexPoly *RAS_IPolyMaterial::GetMTexPoly() const
-{
- return NULL;
-}
unsigned int *RAS_IPolyMaterial::GetMCol() const
{
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
index a34f7a9b390..7023d305510 100644
--- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
+++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
@@ -41,7 +41,6 @@
#endif
class RAS_IRasterizer;
-struct MTexPoly;
struct Material;
struct Image;
struct Scene;
@@ -167,7 +166,6 @@ public:
virtual Material* GetBlenderMaterial() const;
virtual Image* GetBlenderImage() const;
- virtual MTexPoly* GetMTexPoly() const;
virtual unsigned int* GetMCol() const;
virtual Scene* GetBlenderScene() const;
virtual void ReleaseMaterial();
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
index 69e859f06d9..18254357f85 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
@@ -43,6 +43,7 @@
#include "DNA_lamp_types.h"
#include "DNA_scene_types.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
RAS_OpenGLLight::RAS_OpenGLLight(RAS_OpenGLRasterizer *ras)
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index 5eed9b3b8f8..d1c3162f752 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -60,6 +60,7 @@
extern "C"{
#include "BLF_api.h"
#include "BKE_DerivedMesh.h"
+ #include "DNA_material_types.h"
}
@@ -710,7 +711,7 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
glattrib = unit;
GPU_render_text(
- polymat->GetMTexPoly(), polymat->GetDrawingMode(), mytext, mytext.Length(), polymat->GetMCol(),
+ polymat->GetDrawingMode(), mytext, mytext.Length(), polymat->GetMCol(),
v_ptr, uv_ptr, glattrib);
ClearCachingInfo();
@@ -769,7 +770,6 @@ static RAS_MeshSlot *current_ms;
static RAS_MeshObject *current_mesh;
static int current_blmat_nr;
static GPUVertexAttribs current_gpu_attribs;
-static Image *current_image;
static int CheckMaterialDM(int matnr, void *attribs)
{
// only draw the current material
@@ -781,33 +781,6 @@ static int CheckMaterialDM(int matnr, void *attribs)
return 1;
}
-static DMDrawOption CheckTexDM(MTexPoly *mtexpoly, const bool has_mcol, int matnr)
-{
-
- // index is the original face index, retrieve the polygon
- if (matnr == current_blmat_nr &&
- (mtexpoly == NULL || mtexpoly->tpage == current_image)) {
- // must handle color.
- if (current_wireframe)
- return DM_DRAW_OPTION_NO_MCOL;
- if (current_ms->m_bObjectColor) {
- MT_Vector4& rgba = current_ms->m_RGBAcolor;
- glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
- // don't use mcol
- return DM_DRAW_OPTION_NO_MCOL;
- }
- if (!has_mcol) {
- // we have to set the color from the material
- unsigned char rgba[4];
- current_polymat->GetMaterialRGBAColor(rgba);
- glColor4ubv((const GLubyte *)rgba);
- return DM_DRAW_OPTION_NORMAL;
- }
- return DM_DRAW_OPTION_NORMAL;
- }
- return DM_DRAW_OPTION_SKIP;
-}
-
void RAS_OpenGLRasterizer::DrawDerivedMesh(class RAS_MeshSlot &ms)
{
// mesh data is in derived mesh
@@ -824,7 +797,10 @@ void RAS_OpenGLRasterizer::DrawDerivedMesh(class RAS_MeshSlot &ms)
else
this->SetCullFace(false);
- if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
+#if 0
+ if (current_polymat->GetFlag() & RAS_BLENDERGLSL)
+#endif
+ {
// GetMaterialIndex return the original mface material index,
// increment by 1 to match what derived mesh is doing
current_blmat_nr = current_polymat->GetMaterialIndex()+1;
@@ -839,11 +815,6 @@ void RAS_OpenGLRasterizer::DrawDerivedMesh(class RAS_MeshSlot &ms)
int current_blend_mode = GPU_get_material_alpha_blend();
ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
GPU_set_material_alpha_blend(current_blend_mode);
- } else {
- //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
- current_blmat_nr = current_polymat->GetMaterialIndex();
- current_image = current_polymat->GetBlenderImage();
- ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL, DM_DRAW_USE_ACTIVE_UV);
}
}
diff --git a/source/tools b/source/tools
-Subproject e10a1b031b243482371c0673ee17aa3c0f53637
+Subproject 9ea62ef860cde8eb313b74cd1b23ca5a0734eef